mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-20 06:36:00 +00:00
Merge branch 'master' into feature/translation
This commit is contained in:
46
.github/workflows/build-app-beta.yaml
vendored
46
.github/workflows/build-app-beta.yaml
vendored
@@ -6,9 +6,13 @@ name: Electron app BETA
|
|||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+
|
- v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: write
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
environment: dbgate-app
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -60,21 +64,53 @@ jobs:
|
|||||||
- name: Install Snapcraft
|
- name: Install Snapcraft
|
||||||
if: matrix.os == 'ubuntu-22.04'
|
if: matrix.os == 'ubuntu-22.04'
|
||||||
uses: samuelmeuli/action-snapcraft@v1
|
uses: samuelmeuli/action-snapcraft@v1
|
||||||
- name: Publish
|
- name: Publish Windows
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
run: |
|
||||||
|
|
||||||
|
yarn run build:app
|
||||||
|
- name: Publish MacOS
|
||||||
|
if: matrix.os == 'macos-14'
|
||||||
run: |
|
run: |
|
||||||
|
|
||||||
yarn run build:app
|
yarn run build:app
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
|
||||||
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
|
|
||||||
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
|
|
||||||
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
||||||
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||||
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
|
||||||
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
||||||
|
- name: Publish Linux
|
||||||
|
if: matrix.os == 'ubuntu-22.04'
|
||||||
|
run: |
|
||||||
|
|
||||||
|
yarn run build:app
|
||||||
|
env:
|
||||||
|
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
||||||
|
- name: Azure login (OIDC)
|
||||||
|
uses: azure/login@v2
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
with:
|
||||||
|
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
|
||||||
|
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
|
||||||
|
allow-no-subscriptions: true
|
||||||
|
- name: Sign Windows artifacts with Azure Trusted Signing
|
||||||
|
uses: azure/trusted-signing-action@v0
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
with:
|
||||||
|
endpoint: https://wus3.codesigning.azure.net/
|
||||||
|
trusted-signing-account-name: DbGate
|
||||||
|
certificate-profile-name: DbGate-Release
|
||||||
|
files-folder: app/dist
|
||||||
|
files-folder-filter: exe
|
||||||
|
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||||
|
timestamp-digest: SHA256
|
||||||
|
- name: Fix YML hashes
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
run: |
|
||||||
|
|
||||||
|
yarn run fixYmlHashes
|
||||||
- name: Copy artifacts
|
- name: Copy artifacts
|
||||||
run: |
|
run: |
|
||||||
mkdir artifacts
|
mkdir artifacts
|
||||||
|
|||||||
46
.github/workflows/build-app-check.yaml
vendored
46
.github/workflows/build-app-check.yaml
vendored
@@ -6,9 +6,13 @@ name: Electron app check build
|
|||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- check-[0-9]+-[0-9]+-[0-9]+.[0-9]+
|
- check-[0-9]+-[0-9]+-[0-9]+.[0-9]+
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: write
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
environment: dbgate-app
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -56,21 +60,53 @@ jobs:
|
|||||||
- name: Install Snapcraft
|
- name: Install Snapcraft
|
||||||
if: matrix.os == 'ubuntu-22.04'
|
if: matrix.os == 'ubuntu-22.04'
|
||||||
uses: samuelmeuli/action-snapcraft@v1
|
uses: samuelmeuli/action-snapcraft@v1
|
||||||
- name: Publish
|
- name: Publish Windows
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
run: |
|
||||||
|
|
||||||
|
yarn run build:app
|
||||||
|
- name: Publish MacOS
|
||||||
|
if: matrix.os == 'macos-14'
|
||||||
run: |
|
run: |
|
||||||
|
|
||||||
yarn run build:app
|
yarn run build:app
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
|
||||||
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
|
|
||||||
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
|
|
||||||
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
||||||
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||||
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
|
||||||
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
||||||
|
- name: Publish Linux
|
||||||
|
if: matrix.os == 'ubuntu-22.04'
|
||||||
|
run: |
|
||||||
|
|
||||||
|
yarn run build:app
|
||||||
|
env:
|
||||||
|
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
||||||
|
- name: Azure login (OIDC)
|
||||||
|
uses: azure/login@v2
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
with:
|
||||||
|
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
|
||||||
|
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
|
||||||
|
allow-no-subscriptions: true
|
||||||
|
- name: Sign Windows artifacts with Azure Trusted Signing
|
||||||
|
uses: azure/trusted-signing-action@v0
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
with:
|
||||||
|
endpoint: https://wus3.codesigning.azure.net/
|
||||||
|
trusted-signing-account-name: DbGate
|
||||||
|
certificate-profile-name: DbGate-Release
|
||||||
|
files-folder: app/dist
|
||||||
|
files-folder-filter: exe
|
||||||
|
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||||
|
timestamp-digest: SHA256
|
||||||
|
- name: Fix YML hashes
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
run: |
|
||||||
|
|
||||||
|
yarn run fixYmlHashes
|
||||||
- name: Copy artifacts
|
- name: Copy artifacts
|
||||||
run: |
|
run: |
|
||||||
mkdir artifacts
|
mkdir artifacts
|
||||||
|
|||||||
54
.github/workflows/build-app-pro-beta.yaml
vendored
54
.github/workflows/build-app-pro-beta.yaml
vendored
@@ -6,9 +6,13 @@ name: Electron app PREMIUM BETA
|
|||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- v[0-9]+.[0-9]+.[0-9]+-premium-beta.[0-9]+
|
- v[0-9]+.[0-9]+.[0-9]+-premium-beta.[0-9]+
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: write
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
environment: dbgate-app
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -39,7 +43,7 @@ jobs:
|
|||||||
repository: dbgate/dbgate-pro
|
repository: dbgate/dbgate-pro
|
||||||
token: ${{ secrets.GH_TOKEN }}
|
token: ${{ secrets.GH_TOKEN }}
|
||||||
path: dbgate-pro
|
path: dbgate-pro
|
||||||
ref: 11203754aad94189b565c2816d37760b15c8e07f
|
ref: 6195e103e1d45e4f59bade60df5dd1784f4e6c77
|
||||||
- name: Merge dbgate/dbgate-pro
|
- name: Merge dbgate/dbgate-pro
|
||||||
run: |
|
run: |
|
||||||
mkdir ../dbgate-pro
|
mkdir ../dbgate-pro
|
||||||
@@ -87,23 +91,61 @@ jobs:
|
|||||||
cd dbgate-merged
|
cd dbgate-merged
|
||||||
|
|
||||||
yarn fillPackagedPlugins
|
yarn fillPackagedPlugins
|
||||||
- name: Publish
|
- name: Publish Windows
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
run: |
|
||||||
|
cd ..
|
||||||
|
cd dbgate-merged
|
||||||
|
|
||||||
|
yarn run build:app
|
||||||
|
- name: Publish MacOS
|
||||||
|
if: matrix.os == 'macos-14'
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
cd dbgate-merged
|
cd dbgate-merged
|
||||||
|
|
||||||
yarn run build:app
|
yarn run build:app
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
|
||||||
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
|
|
||||||
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
|
|
||||||
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
||||||
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||||
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
|
||||||
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
||||||
|
- name: Publish Linux
|
||||||
|
if: matrix.os == 'ubuntu-22.04'
|
||||||
|
run: |
|
||||||
|
cd ..
|
||||||
|
cd dbgate-merged
|
||||||
|
|
||||||
|
yarn run build:app
|
||||||
|
env:
|
||||||
|
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
||||||
|
- name: Azure login (OIDC)
|
||||||
|
uses: azure/login@v2
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
with:
|
||||||
|
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
|
||||||
|
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
|
||||||
|
allow-no-subscriptions: true
|
||||||
|
- name: Sign Windows artifacts with Azure Trusted Signing
|
||||||
|
uses: azure/trusted-signing-action@v0
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
with:
|
||||||
|
endpoint: https://wus3.codesigning.azure.net/
|
||||||
|
trusted-signing-account-name: DbGate
|
||||||
|
certificate-profile-name: DbGate-Release
|
||||||
|
files-folder: ../dbgate-merged/app/dist
|
||||||
|
files-folder-filter: exe
|
||||||
|
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||||
|
timestamp-digest: SHA256
|
||||||
|
- name: Fix YML hashes
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
run: |
|
||||||
|
cd ..
|
||||||
|
cd dbgate-merged
|
||||||
|
|
||||||
|
yarn run fixYmlHashes
|
||||||
- name: Copy artifacts
|
- name: Copy artifacts
|
||||||
run: |
|
run: |
|
||||||
mkdir artifacts
|
mkdir artifacts
|
||||||
|
|||||||
54
.github/workflows/build-app-pro.yaml
vendored
54
.github/workflows/build-app-pro.yaml
vendored
@@ -6,9 +6,13 @@ name: Electron app PREMIUM
|
|||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- v[0-9]+.[0-9]+.[0-9]+
|
- v[0-9]+.[0-9]+.[0-9]+
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: write
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
environment: dbgate-app
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -39,7 +43,7 @@ jobs:
|
|||||||
repository: dbgate/dbgate-pro
|
repository: dbgate/dbgate-pro
|
||||||
token: ${{ secrets.GH_TOKEN }}
|
token: ${{ secrets.GH_TOKEN }}
|
||||||
path: dbgate-pro
|
path: dbgate-pro
|
||||||
ref: 11203754aad94189b565c2816d37760b15c8e07f
|
ref: 6195e103e1d45e4f59bade60df5dd1784f4e6c77
|
||||||
- name: Merge dbgate/dbgate-pro
|
- name: Merge dbgate/dbgate-pro
|
||||||
run: |
|
run: |
|
||||||
mkdir ../dbgate-pro
|
mkdir ../dbgate-pro
|
||||||
@@ -87,23 +91,61 @@ jobs:
|
|||||||
cd dbgate-merged
|
cd dbgate-merged
|
||||||
|
|
||||||
yarn fillPackagedPlugins
|
yarn fillPackagedPlugins
|
||||||
- name: Publish
|
- name: Publish Windows
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
run: |
|
||||||
|
cd ..
|
||||||
|
cd dbgate-merged
|
||||||
|
|
||||||
|
yarn run build:app
|
||||||
|
- name: Publish MacOS
|
||||||
|
if: matrix.os == 'macos-14'
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
cd dbgate-merged
|
cd dbgate-merged
|
||||||
|
|
||||||
yarn run build:app
|
yarn run build:app
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
|
||||||
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
|
|
||||||
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
|
|
||||||
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
||||||
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||||
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
|
||||||
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
||||||
|
- name: Publish Linux
|
||||||
|
if: matrix.os == 'ubuntu-22.04'
|
||||||
|
run: |
|
||||||
|
cd ..
|
||||||
|
cd dbgate-merged
|
||||||
|
|
||||||
|
yarn run build:app
|
||||||
|
env:
|
||||||
|
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
||||||
|
- name: Azure login (OIDC)
|
||||||
|
uses: azure/login@v2
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
with:
|
||||||
|
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
|
||||||
|
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
|
||||||
|
allow-no-subscriptions: true
|
||||||
|
- name: Sign Windows artifacts with Azure Trusted Signing
|
||||||
|
uses: azure/trusted-signing-action@v0
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
with:
|
||||||
|
endpoint: https://wus3.codesigning.azure.net/
|
||||||
|
trusted-signing-account-name: DbGate
|
||||||
|
certificate-profile-name: DbGate-Release
|
||||||
|
files-folder: ../dbgate-merged/app/dist
|
||||||
|
files-folder-filter: exe
|
||||||
|
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||||
|
timestamp-digest: SHA256
|
||||||
|
- name: Fix YML hashes
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
run: |
|
||||||
|
cd ..
|
||||||
|
cd dbgate-merged
|
||||||
|
|
||||||
|
yarn run fixYmlHashes
|
||||||
- name: Copy artifacts
|
- name: Copy artifacts
|
||||||
run: |
|
run: |
|
||||||
mkdir artifacts
|
mkdir artifacts
|
||||||
|
|||||||
46
.github/workflows/build-app.yaml
vendored
46
.github/workflows/build-app.yaml
vendored
@@ -6,9 +6,13 @@ name: Electron app
|
|||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- v[0-9]+.[0-9]+.[0-9]+
|
- v[0-9]+.[0-9]+.[0-9]+
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: write
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
environment: dbgate-app
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -56,24 +60,56 @@ jobs:
|
|||||||
- name: Install Snapcraft
|
- name: Install Snapcraft
|
||||||
if: matrix.os == 'ubuntu-22.04'
|
if: matrix.os == 'ubuntu-22.04'
|
||||||
uses: samuelmeuli/action-snapcraft@v1
|
uses: samuelmeuli/action-snapcraft@v1
|
||||||
- name: Publish
|
- name: Publish Windows
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
run: |
|
||||||
|
|
||||||
|
yarn run build:app
|
||||||
|
- name: Publish MacOS
|
||||||
|
if: matrix.os == 'macos-14'
|
||||||
run: |
|
run: |
|
||||||
|
|
||||||
yarn run build:app
|
yarn run build:app
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
|
||||||
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
|
|
||||||
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
|
|
||||||
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
||||||
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||||
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
|
||||||
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
||||||
|
- name: Publish Linux
|
||||||
|
if: matrix.os == 'ubuntu-22.04'
|
||||||
|
run: |
|
||||||
|
|
||||||
|
yarn run build:app
|
||||||
|
env:
|
||||||
|
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
||||||
- name: generatePadFile
|
- name: generatePadFile
|
||||||
run: |
|
run: |
|
||||||
yarn generatePadFile
|
yarn generatePadFile
|
||||||
|
- name: Azure login (OIDC)
|
||||||
|
uses: azure/login@v2
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
with:
|
||||||
|
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
|
||||||
|
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
|
||||||
|
allow-no-subscriptions: true
|
||||||
|
- name: Sign Windows artifacts with Azure Trusted Signing
|
||||||
|
uses: azure/trusted-signing-action@v0
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
with:
|
||||||
|
endpoint: https://wus3.codesigning.azure.net/
|
||||||
|
trusted-signing-account-name: DbGate
|
||||||
|
certificate-profile-name: DbGate-Release
|
||||||
|
files-folder: app/dist
|
||||||
|
files-folder-filter: exe
|
||||||
|
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||||
|
timestamp-digest: SHA256
|
||||||
|
- name: Fix YML hashes
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
run: |
|
||||||
|
|
||||||
|
yarn run fixYmlHashes
|
||||||
- name: Copy artifacts
|
- name: Copy artifacts
|
||||||
run: |
|
run: |
|
||||||
mkdir artifacts
|
mkdir artifacts
|
||||||
|
|||||||
2
.github/workflows/build-cloud-pro.yaml
vendored
2
.github/workflows/build-cloud-pro.yaml
vendored
@@ -39,7 +39,7 @@ jobs:
|
|||||||
repository: dbgate/dbgate-pro
|
repository: dbgate/dbgate-pro
|
||||||
token: ${{ secrets.GH_TOKEN }}
|
token: ${{ secrets.GH_TOKEN }}
|
||||||
path: dbgate-pro
|
path: dbgate-pro
|
||||||
ref: 11203754aad94189b565c2816d37760b15c8e07f
|
ref: 6195e103e1d45e4f59bade60df5dd1784f4e6c77
|
||||||
- name: Merge dbgate/dbgate-pro
|
- name: Merge dbgate/dbgate-pro
|
||||||
run: |
|
run: |
|
||||||
mkdir ../dbgate-pro
|
mkdir ../dbgate-pro
|
||||||
|
|||||||
2
.github/workflows/build-docker-pro.yaml
vendored
2
.github/workflows/build-docker-pro.yaml
vendored
@@ -44,7 +44,7 @@ jobs:
|
|||||||
repository: dbgate/dbgate-pro
|
repository: dbgate/dbgate-pro
|
||||||
token: ${{ secrets.GH_TOKEN }}
|
token: ${{ secrets.GH_TOKEN }}
|
||||||
path: dbgate-pro
|
path: dbgate-pro
|
||||||
ref: 11203754aad94189b565c2816d37760b15c8e07f
|
ref: 6195e103e1d45e4f59bade60df5dd1784f4e6c77
|
||||||
- name: Merge dbgate/dbgate-pro
|
- name: Merge dbgate/dbgate-pro
|
||||||
run: |
|
run: |
|
||||||
mkdir ../dbgate-pro
|
mkdir ../dbgate-pro
|
||||||
|
|||||||
31
.github/workflows/build-npm-pro.yaml
vendored
31
.github/workflows/build-npm-pro.yaml
vendored
@@ -7,6 +7,9 @@ name: NPM packages PREMIUM
|
|||||||
tags:
|
tags:
|
||||||
- v[0-9]+.[0-9]+.[0-9]+
|
- v[0-9]+.[0-9]+.[0-9]+
|
||||||
- v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+
|
- v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: write
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
@@ -32,7 +35,7 @@ jobs:
|
|||||||
repository: dbgate/dbgate-pro
|
repository: dbgate/dbgate-pro
|
||||||
token: ${{ secrets.GH_TOKEN }}
|
token: ${{ secrets.GH_TOKEN }}
|
||||||
path: dbgate-pro
|
path: dbgate-pro
|
||||||
ref: 11203754aad94189b565c2816d37760b15c8e07f
|
ref: 6195e103e1d45e4f59bade60df5dd1784f4e6c77
|
||||||
- name: Merge dbgate/dbgate-pro
|
- name: Merge dbgate/dbgate-pro
|
||||||
run: |
|
run: |
|
||||||
mkdir ../dbgate-pro
|
mkdir ../dbgate-pro
|
||||||
@@ -49,13 +52,8 @@ jobs:
|
|||||||
cd ..
|
cd ..
|
||||||
cd dbgate-merged
|
cd dbgate-merged
|
||||||
node adjustNpmPackageJsonPremium
|
node adjustNpmPackageJsonPremium
|
||||||
- name: Configure NPM token
|
- name: Update npm
|
||||||
env:
|
run: npm install -g npm@latest
|
||||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
||||||
run: |
|
|
||||||
cd ..
|
|
||||||
cd dbgate-merged
|
|
||||||
npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
|
|
||||||
- name: Remove dbmodel - should be not published
|
- name: Remove dbmodel - should be not published
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
@@ -71,28 +69,35 @@ jobs:
|
|||||||
cd ..
|
cd ..
|
||||||
cd dbgate-merged
|
cd dbgate-merged
|
||||||
yarn setCurrentVersion
|
yarn setCurrentVersion
|
||||||
|
- name: Compute npm dist-tag
|
||||||
|
run: |
|
||||||
|
if [[ "${GITHUB_REF_NAME}" =~ -alpha\. ]]; then
|
||||||
|
echo "NPM_TAG=alpha" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "NPM_TAG=latest" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
- name: Publish dbgate-api-premium
|
- name: Publish dbgate-api-premium
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
cd dbgate-merged/packages/api
|
cd dbgate-merged/packages/api
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-web-premium
|
- name: Publish dbgate-web-premium
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
cd dbgate-merged/packages/web
|
cd dbgate-merged/packages/web
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-serve-premium
|
- name: Publish dbgate-serve-premium
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
cd dbgate-merged/packages/serve
|
cd dbgate-merged/packages/serve
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-plugin-cosmosdb
|
- name: Publish dbgate-plugin-cosmosdb
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
cd dbgate-merged/plugins/dbgate-plugin-cosmosdb
|
cd dbgate-merged/plugins/dbgate-plugin-cosmosdb
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-plugin-firestore
|
- name: Publish dbgate-plugin-firestore
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
cd dbgate-merged/plugins/dbgate-plugin-firestore
|
cd dbgate-merged/plugins/dbgate-plugin-firestore
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|||||||
61
.github/workflows/build-npm.yaml
vendored
61
.github/workflows/build-npm.yaml
vendored
@@ -7,6 +7,9 @@ name: NPM packages
|
|||||||
tags:
|
tags:
|
||||||
- v[0-9]+.[0-9]+.[0-9]+
|
- v[0-9]+.[0-9]+.[0-9]+
|
||||||
- v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+
|
- v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: write
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
@@ -26,103 +29,107 @@ jobs:
|
|||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 22.x
|
node-version: 22.x
|
||||||
- name: Configure NPM token
|
- name: Update npm
|
||||||
env:
|
run: npm install -g npm@latest
|
||||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
||||||
run: |
|
|
||||||
npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
|
|
||||||
- name: yarn install
|
- name: yarn install
|
||||||
run: |
|
run: |
|
||||||
yarn install
|
yarn install
|
||||||
- name: setCurrentVersion
|
- name: setCurrentVersion
|
||||||
run: |
|
run: |
|
||||||
yarn setCurrentVersion
|
yarn setCurrentVersion
|
||||||
|
- name: Compute npm dist-tag
|
||||||
|
run: |
|
||||||
|
if [[ "${GITHUB_REF_NAME}" =~ -alpha\. ]]; then
|
||||||
|
echo "NPM_TAG=alpha" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "NPM_TAG=latest" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
- name: Publish types
|
- name: Publish types
|
||||||
working-directory: packages/types
|
working-directory: packages/types
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish tools
|
- name: Publish tools
|
||||||
working-directory: packages/tools
|
working-directory: packages/tools
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish sqltree
|
- name: Publish sqltree
|
||||||
working-directory: packages/sqltree
|
working-directory: packages/sqltree
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish api
|
- name: Publish api
|
||||||
working-directory: packages/api
|
working-directory: packages/api
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish datalib
|
- name: Publish datalib
|
||||||
working-directory: packages/datalib
|
working-directory: packages/datalib
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish filterparser
|
- name: Publish filterparser
|
||||||
working-directory: packages/filterparser
|
working-directory: packages/filterparser
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish web
|
- name: Publish web
|
||||||
working-directory: packages/web
|
working-directory: packages/web
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-serve
|
- name: Publish dbgate-serve
|
||||||
working-directory: packages/serve
|
working-directory: packages/serve
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbmodel
|
- name: Publish dbmodel
|
||||||
working-directory: packages/dbmodel
|
working-directory: packages/dbmodel
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-plugin-csv
|
- name: Publish dbgate-plugin-csv
|
||||||
working-directory: plugins/dbgate-plugin-csv
|
working-directory: plugins/dbgate-plugin-csv
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-plugin-xml
|
- name: Publish dbgate-plugin-xml
|
||||||
working-directory: plugins/dbgate-plugin-xml
|
working-directory: plugins/dbgate-plugin-xml
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-plugin-excel
|
- name: Publish dbgate-plugin-excel
|
||||||
working-directory: plugins/dbgate-plugin-excel
|
working-directory: plugins/dbgate-plugin-excel
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-plugin-mssql
|
- name: Publish dbgate-plugin-mssql
|
||||||
working-directory: plugins/dbgate-plugin-mssql
|
working-directory: plugins/dbgate-plugin-mssql
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-plugin-mysql
|
- name: Publish dbgate-plugin-mysql
|
||||||
working-directory: plugins/dbgate-plugin-mysql
|
working-directory: plugins/dbgate-plugin-mysql
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-plugin-mongo
|
- name: Publish dbgate-plugin-mongo
|
||||||
working-directory: plugins/dbgate-plugin-mongo
|
working-directory: plugins/dbgate-plugin-mongo
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-plugin-postgres
|
- name: Publish dbgate-plugin-postgres
|
||||||
working-directory: plugins/dbgate-plugin-postgres
|
working-directory: plugins/dbgate-plugin-postgres
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-plugin-sqlite
|
- name: Publish dbgate-plugin-sqlite
|
||||||
working-directory: plugins/dbgate-plugin-sqlite
|
working-directory: plugins/dbgate-plugin-sqlite
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-plugin-redis
|
- name: Publish dbgate-plugin-redis
|
||||||
working-directory: plugins/dbgate-plugin-redis
|
working-directory: plugins/dbgate-plugin-redis
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-plugin-oracle
|
- name: Publish dbgate-plugin-oracle
|
||||||
working-directory: plugins/dbgate-plugin-oracle
|
working-directory: plugins/dbgate-plugin-oracle
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-plugin-clickhouse
|
- name: Publish dbgate-plugin-clickhouse
|
||||||
working-directory: plugins/dbgate-plugin-clickhouse
|
working-directory: plugins/dbgate-plugin-clickhouse
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-plugin-dbf
|
- name: Publish dbgate-plugin-dbf
|
||||||
working-directory: plugins/dbgate-plugin-dbf
|
working-directory: plugins/dbgate-plugin-dbf
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
- name: Publish dbgate-plugin-cassandra
|
- name: Publish dbgate-plugin-cassandra
|
||||||
working-directory: plugins/dbgate-plugin-cassandra
|
working-directory: plugins/dbgate-plugin-cassandra
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|||||||
2
.github/workflows/e2e-pro.yaml
vendored
2
.github/workflows/e2e-pro.yaml
vendored
@@ -26,7 +26,7 @@ jobs:
|
|||||||
repository: dbgate/dbgate-pro
|
repository: dbgate/dbgate-pro
|
||||||
token: ${{ secrets.GH_TOKEN }}
|
token: ${{ secrets.GH_TOKEN }}
|
||||||
path: dbgate-pro
|
path: dbgate-pro
|
||||||
ref: 11203754aad94189b565c2816d37760b15c8e07f
|
ref: 6195e103e1d45e4f59bade60df5dd1784f4e6c77
|
||||||
- name: Merge dbgate/dbgate-pro
|
- name: Merge dbgate/dbgate-pro
|
||||||
run: |
|
run: |
|
||||||
mkdir ../dbgate-pro
|
mkdir ../dbgate-pro
|
||||||
|
|||||||
12
CHANGELOG.md
12
CHANGELOG.md
@@ -8,12 +8,24 @@ Builds:
|
|||||||
- linux - application for linux
|
- linux - application for linux
|
||||||
- win - application for Windows
|
- win - application for Windows
|
||||||
|
|
||||||
|
## 6.6.8
|
||||||
|
- CHANGED: Windows executable now uses Azure trusted signing certificate
|
||||||
|
- CHANGED: NPM packages now use GitHub OIDC provenance signing for better security
|
||||||
|
- CHANGED: Some features moved to Premium edition (master/detail views, FK lookups, column expansion, split view, advanced export/import, data archives, grouping, macros)
|
||||||
|
|
||||||
|
## 6.6.6
|
||||||
|
- ADDED: Allow disable/re-enable filter #1174
|
||||||
|
- ADDED: Close right side tabs #1219
|
||||||
|
- ADDED: Ability disable execute current line in query editor #1209
|
||||||
|
- ADDED: Support for Redis Cluster #1204 (Premium)
|
||||||
|
|
||||||
## 6.6.5
|
## 6.6.5
|
||||||
- ADDED: SQL AI assistant - powered by database chat, could help you to write SQL queries (Premium)
|
- ADDED: SQL AI assistant - powered by database chat, could help you to write SQL queries (Premium)
|
||||||
- ADDED: Explain SQL error (powered by AI) (Premium)
|
- ADDED: Explain SQL error (powered by AI) (Premium)
|
||||||
- ADDED: Database chat (and SQL AI Assistant) now supports showing charts (Premium)
|
- ADDED: Database chat (and SQL AI Assistant) now supports showing charts (Premium)
|
||||||
- FIXED: Fxied editing new files and roles (Team Premium)
|
- FIXED: Fxied editing new files and roles (Team Premium)
|
||||||
- FIXED: Connection to standalone database could be now pinned
|
- FIXED: Connection to standalone database could be now pinned
|
||||||
|
- FIXED: Cannot open up large JSON file #1215
|
||||||
|
|
||||||
## 6.6.4
|
## 6.6.4
|
||||||
- ADDED: AI Database chat now supports much more LLM models. (Premium)
|
- ADDED: AI Database chat now supports much more LLM models. (Premium)
|
||||||
|
|||||||
@@ -16,12 +16,9 @@ DbGate is licensed under GPL-3.0 license and is free to use for any purpose.
|
|||||||
|
|
||||||
* Try it online - [demo.dbgate.org](https://demo.dbgate.org) - online demo application
|
* Try it online - [demo.dbgate.org](https://demo.dbgate.org) - online demo application
|
||||||
* **Download** application for Windows, Linux or Mac from [dbgate.io](https://www.dbgate.io/download/)
|
* **Download** application for Windows, Linux or Mac from [dbgate.io](https://www.dbgate.io/download/)
|
||||||
* Looking for DbGate Community? **Download** from [dbgate.org](https://dbgate.org/download/)
|
* Looking for DbGate Community? **Download** from [dbgate.io](https://www.dbgate.io/download-community/)
|
||||||
* Run web version as [NPM package](https://www.npmjs.com/package/dbgate-serve) or as [docker image](https://hub.docker.com/r/dbgate/dbgate)
|
* Run web version as [NPM package](https://www.npmjs.com/package/dbgate-serve) or as [docker image](https://hub.docker.com/r/dbgate/dbgate)
|
||||||
* Use nodeJs [scripting interface](https://docs.dbgate.io/scripting) ([API documentation](https://docs.dbgate.io/apidoc))
|
* Use nodeJs [scripting interface](https://docs.dbgate.io/scripting) ([API documentation](https://docs.dbgate.io/apidoc))
|
||||||
* [Recommend DbGate](https://testimonial.to/dbgate) | [Rate on G2](https://www.g2.com/products/dbgate/reviews)
|
|
||||||
* [Give us feedback](https://dbgate.org/feedback) - it will help us to decide, how to improve DbGate in future
|
|
||||||
* We [offer 2-year PREMIUM license](https://dbgate.org/review/) for any honest review on these platforms (time-limited offer)
|
|
||||||
|
|
||||||
## Supported databases
|
## Supported databases
|
||||||
* MySQL
|
* MySQL
|
||||||
@@ -93,7 +90,6 @@ Any contributions are welcome. If you want to contribute without coding, conside
|
|||||||
|
|
||||||
* Tell your friends about DbGate or share on social networks - when more people will use DbGate, it will grow to be better
|
* Tell your friends about DbGate or share on social networks - when more people will use DbGate, it will grow to be better
|
||||||
* Purchase a [DbGate Premium](https://www.dbgate.io/purchase/premium/) license
|
* Purchase a [DbGate Premium](https://www.dbgate.io/purchase/premium/) license
|
||||||
* Write review on [Product Hunt](https://www.producthunt.com/products/dbgate) or [G2](https://www.g2.com/products/dbgate/reviews) - we offer [2-year PREMIUM license](https://dbgate.org/review/) for reviewers (time limited offer)
|
|
||||||
* Create issue, if you find problem in app, or you have idea to new feature. If issue already exists, you could leave comment on it, to prioritise most wanted issues
|
* Create issue, if you find problem in app, or you have idea to new feature. If issue already exists, you could leave comment on it, to prioritise most wanted issues
|
||||||
* Create some tutorial video on [youtube](https://www.youtube.com/playlist?list=PLCo7KjCVXhr0RfUSjM9wJMsp_ShL1q61A)
|
* Create some tutorial video on [youtube](https://www.youtube.com/playlist?list=PLCo7KjCVXhr0RfUSjM9wJMsp_ShL1q61A)
|
||||||
* Become a backer on [GitHub sponsors](https://github.com/sponsors/dbgate) or [Open collective](https://opencollective.com/dbgate)
|
* Become a backer on [GitHub sponsors](https://github.com/sponsors/dbgate) or [Open collective](https://opencollective.com/dbgate)
|
||||||
|
|||||||
@@ -117,7 +117,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "cross-env ELECTRON_START_URL=http://localhost:5001 DEVMODE=1 electron .",
|
"start": "cross-env ELECTRON_START_URL=http://localhost:5001 DEVMODE=1 electron .",
|
||||||
"start:local": "cross-env electron .",
|
"start:local": "cross-env electron .",
|
||||||
"dist": "electron-builder",
|
"dist": "electron-builder --publish never",
|
||||||
"build": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && yarn dist",
|
"build": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && yarn dist",
|
||||||
"build:local": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && yarn predist",
|
"build:local": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && yarn predist",
|
||||||
"postinstall": "yarn rebuild && patch-package",
|
"postinstall": "yarn rebuild && patch-package",
|
||||||
|
|||||||
110
common/fixYmlHashes.js
Normal file
110
common/fixYmlHashes.js
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
import fs from 'node:fs/promises';
|
||||||
|
import { createHash } from 'node:crypto';
|
||||||
|
import path from 'node:path';
|
||||||
|
import process from 'node:process';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import YAML from 'yaml';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
|
async function sha512Base64(filePath) {
|
||||||
|
const buf = await fs.readFile(filePath);
|
||||||
|
const h = createHash('sha512');
|
||||||
|
h.update(buf);
|
||||||
|
return h.digest('base64');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fileSize(filePath) {
|
||||||
|
const st = await fs.stat(filePath);
|
||||||
|
return st.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fixOneYaml(ymlPath, distDir) {
|
||||||
|
let raw;
|
||||||
|
try {
|
||||||
|
raw = await fs.readFile(ymlPath, 'utf8');
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`✗ Cannot read ${ymlPath}:`, e.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let doc;
|
||||||
|
try {
|
||||||
|
doc = YAML.parse(raw);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`✗ Cannot parse YAML ${ymlPath}:`, e.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!doc || !Array.isArray(doc.files)) {
|
||||||
|
console.warn(`! ${path.basename(ymlPath)} has no 'files' array — skipped.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let changed = false;
|
||||||
|
|
||||||
|
// Update each files[i].sha512 and files[i].size based on files[i].url
|
||||||
|
for (const entry of doc.files) {
|
||||||
|
if (!entry?.url) continue;
|
||||||
|
|
||||||
|
const target = path.resolve(distDir, entry.url);
|
||||||
|
try {
|
||||||
|
const [hash, size] = await Promise.all([sha512Base64(target), fileSize(target)]);
|
||||||
|
if (entry.sha512 !== hash || entry.size !== size) {
|
||||||
|
console.log(`• ${path.basename(ymlPath)}: refresh ${entry.url}`);
|
||||||
|
entry.sha512 = hash;
|
||||||
|
entry.size = size;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(
|
||||||
|
`! Missing or unreadable file for ${entry.url} (referenced by ${path.basename(ymlPath)}): ${e.message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update top-level sha512 for the primary "path" file if present
|
||||||
|
if (doc.path) {
|
||||||
|
const primary = path.resolve(distDir, doc.path);
|
||||||
|
try {
|
||||||
|
const hash = await sha512Base64(primary);
|
||||||
|
if (doc.sha512 !== hash) {
|
||||||
|
console.log(`• ${path.basename(ymlPath)}: refresh top-level sha512 for path=${doc.path}`);
|
||||||
|
doc.sha512 = hash;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(`! Primary 'path' file not found for ${path.basename(ymlPath)}: ${doc.path} (${e.message})`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
const out = YAML.stringify(doc);
|
||||||
|
await fs.writeFile(ymlPath, out, 'utf8');
|
||||||
|
console.log(`✓ Updated ${path.basename(ymlPath)}`);
|
||||||
|
} else {
|
||||||
|
console.log(`= No changes for ${path.basename(ymlPath)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const distDir = path.resolve(process.argv[2] ?? path.join(__dirname, '..', 'app', 'dist'));
|
||||||
|
const entries = await fs.readdir(distDir);
|
||||||
|
const ymls = entries.filter(f => f.toLowerCase().endsWith('.yml'));
|
||||||
|
|
||||||
|
if (ymls.length === 0) {
|
||||||
|
console.warn(`No .yml files found in ${distDir}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Scanning ${distDir}`);
|
||||||
|
for (const y of ymls) {
|
||||||
|
await fixOneYaml(path.join(distDir, y), distDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
@@ -110,7 +110,7 @@ describe('Charts', () => {
|
|||||||
cy.themeshot('new-object-window');
|
cy.themeshot('new-object-window');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Database chat - charts', () => {
|
it.only('Database chat - charts', () => {
|
||||||
cy.contains('MySql-connection').click();
|
cy.contains('MySql-connection').click();
|
||||||
cy.contains('MyChinook').click();
|
cy.contains('MyChinook').click();
|
||||||
cy.testid('TabsPanel_buttonNewObject').click();
|
cy.testid('TabsPanel_buttonNewObject').click();
|
||||||
@@ -119,8 +119,7 @@ describe('Charts', () => {
|
|||||||
cy.get('body').realType('show me chart of most popular genres');
|
cy.get('body').realType('show me chart of most popular genres');
|
||||||
cy.get('body').realPress('{enter}');
|
cy.get('body').realPress('{enter}');
|
||||||
cy.testid('DatabaseChatTab_executeAllQueries', { timeout: 30000 }).click();
|
cy.testid('DatabaseChatTab_executeAllQueries', { timeout: 30000 }).click();
|
||||||
cy.wait(5000);
|
cy.testid('chart-canvas', { timeout: 30000 }).should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
|
||||||
cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
|
|
||||||
cy.themeshot('database-chat-chart');
|
cy.themeshot('database-chat-chart');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "6.6.6-premium-beta.2",
|
"version": "6.6.9",
|
||||||
"name": "dbgate-all",
|
"name": "dbgate-all",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*",
|
"packages/*",
|
||||||
@@ -52,6 +52,7 @@
|
|||||||
"generatePadFile": "node generatePadFile",
|
"generatePadFile": "node generatePadFile",
|
||||||
"fillPackagedPlugins": "node fillPackagedPlugins",
|
"fillPackagedPlugins": "node fillPackagedPlugins",
|
||||||
"resetPackagedPlugins": "node resetPackagedPlugins",
|
"resetPackagedPlugins": "node resetPackagedPlugins",
|
||||||
|
"fixYmlHashes": "cd common && yarn init -y && yarn add yaml -W && cd .. && node common/fixYmlHashes.js app/dist",
|
||||||
"prettier": "prettier --write packages/api/src && prettier --write packages/datalib/src && prettier --write packages/filterparser/src && prettier --write packages/sqltree/src && prettier --write packages/tools/src && prettier --write packages/types && prettier --write packages/web/src && prettier --write app/src",
|
"prettier": "prettier --write packages/api/src && prettier --write packages/datalib/src && prettier --write packages/filterparser/src && prettier --write packages/sqltree/src && prettier --write packages/tools/src && prettier --write packages/types && prettier --write packages/web/src && prettier --write app/src",
|
||||||
"copy:docker:build": "copyfiles packages/api/dist/* docker -f && copyfiles packages/web/public/* docker -u 2 && copyfiles \"packages/web/public/**/*\" docker -u 2 && copyfiles \"plugins/dist/**/*\" docker/plugins -u 2",
|
"copy:docker:build": "copyfiles packages/api/dist/* docker -f && copyfiles packages/web/public/* docker -u 2 && copyfiles \"packages/web/public/**/*\" docker -u 2 && copyfiles \"plugins/dist/**/*\" docker/plugins -u 2",
|
||||||
"copy:packer:build": "copyfiles packages/api/dist/* packer/build -f && copyfiles packages/web/public/* packer/build -u 2 && copyfiles \"packages/web/public/**/*\" packer/build -u 2 && copyfiles \"plugins/dist/**/*\" packer/build/plugins -u 2 && copyfiles packer/install-packages.sh packer/build -f && yarn install:drivers:packer",
|
"copy:packer:build": "copyfiles packages/api/dist/* packer/build -f && copyfiles packages/web/public/* packer/build -u 2 && copyfiles \"packages/web/public/**/*\" packer/build -u 2 && copyfiles \"plugins/dist/**/*\" packer/build/plugins -u 2 && copyfiles packer/install-packages.sh packer/build -f && yarn install:drivers:packer",
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ const {
|
|||||||
putCloudContent,
|
putCloudContent,
|
||||||
removeCloudCachedConnection,
|
removeCloudCachedConnection,
|
||||||
getPromoWidgetData,
|
getPromoWidgetData,
|
||||||
|
getPromoWidgetList,
|
||||||
|
getPromoWidgetPreview,
|
||||||
} = require('../utility/cloudIntf');
|
} = require('../utility/cloudIntf');
|
||||||
const connections = require('./connections');
|
const connections = require('./connections');
|
||||||
const socket = require('../utility/socket');
|
const socket = require('../utility/socket');
|
||||||
@@ -286,7 +288,7 @@ module.exports = {
|
|||||||
|
|
||||||
premiumPromoWidget_meta: true,
|
premiumPromoWidget_meta: true,
|
||||||
async premiumPromoWidget() {
|
async premiumPromoWidget() {
|
||||||
const data = getPromoWidgetData();
|
const data = await getPromoWidgetData();
|
||||||
if (data?.state != 'data') {
|
if (data?.state != 'data') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -296,6 +298,16 @@ module.exports = {
|
|||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
promoWidgetList_meta: true,
|
||||||
|
async promoWidgetList() {
|
||||||
|
return getPromoWidgetList();
|
||||||
|
},
|
||||||
|
|
||||||
|
promoWidgetPreview_meta: true,
|
||||||
|
async promoWidgetPreview({ campaign, variant }) {
|
||||||
|
return getPromoWidgetPreview(campaign, variant);
|
||||||
|
},
|
||||||
|
|
||||||
// chatStream_meta: {
|
// chatStream_meta: {
|
||||||
// raw: true,
|
// raw: true,
|
||||||
// method: 'post',
|
// method: 'post',
|
||||||
|
|||||||
@@ -274,8 +274,6 @@ module.exports = {
|
|||||||
|
|
||||||
start_meta: true,
|
start_meta: true,
|
||||||
async start({ script }, req) {
|
async start({ script }, req) {
|
||||||
await testStandardPermission('run-shell-script', req);
|
|
||||||
|
|
||||||
const runid = crypto.randomUUID();
|
const runid = crypto.randomUUID();
|
||||||
|
|
||||||
if (script.type == 'json') {
|
if (script.type == 'json') {
|
||||||
@@ -291,6 +289,8 @@ module.exports = {
|
|||||||
return this.startCore(runid, scriptTemplate(js, false));
|
return this.startCore(runid, scriptTemplate(js, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await testStandardPermission('run-shell-script', req);
|
||||||
|
|
||||||
if (!platformInfo.allowShellScripting) {
|
if (!platformInfo.allowShellScripting) {
|
||||||
sendToAuditLog(req, {
|
sendToAuditLog(req, {
|
||||||
category: 'shell',
|
category: 'shell',
|
||||||
|
|||||||
@@ -209,11 +209,11 @@ module.exports = {
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
this.lastPinged[conid] = new Date().getTime();
|
this.lastPinged[conid] = new Date().getTime();
|
||||||
|
try {
|
||||||
const opened = await this.ensureOpened(conid);
|
const opened = await this.ensureOpened(conid);
|
||||||
if (!opened) {
|
if (!opened) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
opened.subprocess.send({ msgtype: 'ping' });
|
opened.subprocess.send({ msgtype: 'ping' });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(extractErrorLogData(err), 'DBGM-00121 Error pinging server connection');
|
logger.error(extractErrorLogData(err), 'DBGM-00121 Error pinging server connection');
|
||||||
|
|||||||
@@ -97,6 +97,12 @@ module.exports = {
|
|||||||
socket.emit(`session-initialize-file-${jslid}`);
|
socket.emit(`session-initialize-file-${jslid}`);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handle_changedCurrentDatabase(sesid, props) {
|
||||||
|
const { database } = props;
|
||||||
|
this.dispatchMessage(sesid, `Current database changed to ${database}`);
|
||||||
|
socket.emit(`session-changedb-${sesid}`, { database });
|
||||||
|
},
|
||||||
|
|
||||||
handle_ping() {},
|
handle_ping() {},
|
||||||
|
|
||||||
create_meta: true,
|
create_meta: true,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const logger = getLogger('cloudIntf');
|
|||||||
|
|
||||||
let cloudFiles = null;
|
let cloudFiles = null;
|
||||||
let promoWidgetData = null;
|
let promoWidgetData = null;
|
||||||
|
let promoWidgetDataLoaded = false;
|
||||||
|
|
||||||
const DBGATE_IDENTITY_URL = process.env.LOCAL_DBGATE_IDENTITY
|
const DBGATE_IDENTITY_URL = process.env.LOCAL_DBGATE_IDENTITY
|
||||||
? 'http://localhost:3103'
|
? 'http://localhost:3103'
|
||||||
@@ -260,13 +261,21 @@ async function getPublicFileData(path) {
|
|||||||
return resp.data;
|
return resp.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updatePremiumPromoWidget() {
|
async function ensurePromoWidgetDataLoaded() {
|
||||||
|
if (promoWidgetDataLoaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const fileContent = await fs.readFile(path.join(datadir(), 'promo-widget.json'), 'utf-8');
|
const fileContent = await fs.readFile(path.join(datadir(), 'promo-widget.json'), 'utf-8');
|
||||||
promoWidgetData = JSON.parse(fileContent);
|
promoWidgetData = JSON.parse(fileContent);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
promoWidgetData = null;
|
promoWidgetData = null;
|
||||||
}
|
}
|
||||||
|
promoWidgetDataLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updatePremiumPromoWidget() {
|
||||||
|
await ensurePromoWidgetDataLoaded();
|
||||||
|
|
||||||
const tags = (await collectCloudFilesSearchTags()).join(',');
|
const tags = (await collectCloudFilesSearchTags()).join(',');
|
||||||
|
|
||||||
@@ -466,10 +475,21 @@ async function getPublicIpInfo() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPromoWidgetData() {
|
async function getPromoWidgetData() {
|
||||||
|
await ensurePromoWidgetDataLoaded();
|
||||||
return promoWidgetData;
|
return promoWidgetData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getPromoWidgetPreview(campaign, variant) {
|
||||||
|
const resp = await axios.default.get(`${DBGATE_CLOUD_URL}/premium-promo-widget-preview/${campaign}/${variant}`);
|
||||||
|
return resp.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getPromoWidgetList() {
|
||||||
|
const resp = await axios.default.get(`${DBGATE_CLOUD_URL}/promo-widget-list`);
|
||||||
|
return resp.data;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createDbGateIdentitySession,
|
createDbGateIdentitySession,
|
||||||
startCloudTokenChecking,
|
startCloudTokenChecking,
|
||||||
@@ -488,4 +508,6 @@ module.exports = {
|
|||||||
readCloudTestTokenHolder,
|
readCloudTestTokenHolder,
|
||||||
getPublicIpInfo,
|
getPublicIpInfo,
|
||||||
getPromoWidgetData,
|
getPromoWidgetData,
|
||||||
|
getPromoWidgetPreview,
|
||||||
|
getPromoWidgetList,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ class StreamHandler {
|
|||||||
// this.error = this.error.bind(this);
|
// this.error = this.error.bind(this);
|
||||||
this.done = this.done.bind(this);
|
this.done = this.done.bind(this);
|
||||||
this.info = this.info.bind(this);
|
this.info = this.info.bind(this);
|
||||||
|
this.changedCurrentDatabase = this.changedCurrentDatabase.bind(this);
|
||||||
|
|
||||||
// use this for cancelling - not implemented
|
// use this for cancelling - not implemented
|
||||||
// this.stream = null;
|
// this.stream = null;
|
||||||
@@ -166,6 +167,10 @@ class StreamHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changedCurrentDatabase(database) {
|
||||||
|
process.send({ msgtype: 'changedCurrentDatabase', database, sesid: this.sesid });
|
||||||
|
}
|
||||||
|
|
||||||
recordset(columns) {
|
recordset(columns) {
|
||||||
if (this.rowsLimitOverflow) {
|
if (this.rowsLimitOverflow) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
"name": "dbgate-datalib",
|
"name": "dbgate-datalib",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"typings": "lib/index.d.ts",
|
"typings": "lib/index.d.ts",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/dbgate/dbgate.git"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ export class TableGridDisplay extends GridDisplay {
|
|||||||
public getDictionaryDescription: DictionaryDescriptionFunc = null,
|
public getDictionaryDescription: DictionaryDescriptionFunc = null,
|
||||||
isReadOnly = false,
|
isReadOnly = false,
|
||||||
public isRawMode = false,
|
public isRawMode = false,
|
||||||
public currentSettings = null
|
public currentSettings = null,
|
||||||
|
public areReferencesAllowed = true
|
||||||
) {
|
) {
|
||||||
super(config, setConfig, cache, setCache, driver, dbinfo, serverVersion, currentSettings);
|
super(config, setConfig, cache, setCache, driver, dbinfo, serverVersion, currentSettings);
|
||||||
|
|
||||||
@@ -102,11 +103,11 @@ export class TableGridDisplay extends GridDisplay {
|
|||||||
isChecked: this.isColumnChecked(col),
|
isChecked: this.isColumnChecked(col),
|
||||||
hintColumnNames:
|
hintColumnNames:
|
||||||
this.getFkDictionaryDescription(col.isForeignKeyUnique ? col.foreignKey : null)?.columns?.map(columnName =>
|
this.getFkDictionaryDescription(col.isForeignKeyUnique ? col.foreignKey : null)?.columns?.map(columnName =>
|
||||||
shortenIdentifier(`hint_${col.uniqueName}_${columnName}`, this.driver.dialect.maxIdentifierLength)
|
shortenIdentifier(`hint_${col.uniqueName}_${columnName}`, this.driver?.dialect?.maxIdentifierLength)
|
||||||
) || null,
|
) || null,
|
||||||
hintColumnDelimiter: this.getFkDictionaryDescription(col.isForeignKeyUnique ? col.foreignKey : null)
|
hintColumnDelimiter: this.getFkDictionaryDescription(col.isForeignKeyUnique ? col.foreignKey : null)
|
||||||
?.delimiter,
|
?.delimiter,
|
||||||
uniqueNameShorten: shortenIdentifier(col.uniqueName, this.driver.dialect.maxIdentifierLength),
|
uniqueNameShorten: shortenIdentifier(col.uniqueName, this.driver?.dialect?.maxIdentifierLength),
|
||||||
isExpandable: !!col.foreignKey,
|
isExpandable: !!col.foreignKey,
|
||||||
})) || []
|
})) || []
|
||||||
);
|
);
|
||||||
@@ -117,7 +118,7 @@ export class TableGridDisplay extends GridDisplay {
|
|||||||
if (this.isExpandedColumn(column.uniqueName)) {
|
if (this.isExpandedColumn(column.uniqueName)) {
|
||||||
const table = this.getFkTarget(column);
|
const table = this.getFkTarget(column);
|
||||||
if (table) {
|
if (table) {
|
||||||
const childAlias = shortenIdentifier(`${column.uniqueName}_ref`, this.driver.dialect.maxIdentifierLength);
|
const childAlias = shortenIdentifier(`${column.uniqueName}_ref`, this.driver?.dialect?.maxIdentifierLength);
|
||||||
const subcolumns = this.getDisplayColumns(table, column.uniquePath);
|
const subcolumns = this.getDisplayColumns(table, column.uniquePath);
|
||||||
|
|
||||||
this.addReferenceToSelect(select, parentAlias, column);
|
this.addReferenceToSelect(select, parentAlias, column);
|
||||||
@@ -130,7 +131,7 @@ export class TableGridDisplay extends GridDisplay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addReferenceToSelect(select: Select, parentAlias: string, column: DisplayColumn) {
|
addReferenceToSelect(select: Select, parentAlias: string, column: DisplayColumn) {
|
||||||
const childAlias = shortenIdentifier(`${column.uniqueName}_ref`, this.driver.dialect.maxIdentifierLength);
|
const childAlias = shortenIdentifier(`${column.uniqueName}_ref`, this.driver?.dialect?.maxIdentifierLength);
|
||||||
if ((select.from.relations || []).find(x => x.alias == childAlias)) return;
|
if ((select.from.relations || []).find(x => x.alias == childAlias)) return;
|
||||||
const table = this.getFkTarget(column);
|
const table = this.getFkTarget(column);
|
||||||
if (table && table.primaryKey) {
|
if (table && table.primaryKey) {
|
||||||
@@ -195,11 +196,11 @@ export class TableGridDisplay extends GridDisplay {
|
|||||||
this.addReferenceToSelect(
|
this.addReferenceToSelect(
|
||||||
select,
|
select,
|
||||||
parentUniqueName
|
parentUniqueName
|
||||||
? shortenIdentifier(`${parentUniqueName}_ref`, this.driver.dialect.maxIdentifierLength)
|
? shortenIdentifier(`${parentUniqueName}_ref`, this.driver?.dialect?.maxIdentifierLength)
|
||||||
: 'basetbl',
|
: 'basetbl',
|
||||||
column
|
column
|
||||||
);
|
);
|
||||||
const childAlias = shortenIdentifier(`${column.uniqueName}_ref`, this.driver.dialect.maxIdentifierLength);
|
const childAlias = shortenIdentifier(`${column.uniqueName}_ref`, this.driver?.dialect?.maxIdentifierLength);
|
||||||
select.columns.push(
|
select.columns.push(
|
||||||
...hintDescription.columns.map(
|
...hintDescription.columns.map(
|
||||||
columnName =>
|
columnName =>
|
||||||
@@ -208,7 +209,7 @@ export class TableGridDisplay extends GridDisplay {
|
|||||||
columnName,
|
columnName,
|
||||||
alias: shortenIdentifier(
|
alias: shortenIdentifier(
|
||||||
`hint_${column.uniqueName}_${columnName}`,
|
`hint_${column.uniqueName}_${columnName}`,
|
||||||
this.driver.dialect.maxIdentifierLength
|
this.driver?.dialect?.maxIdentifierLength
|
||||||
),
|
),
|
||||||
source: { alias: childAlias },
|
source: { alias: childAlias },
|
||||||
} as ColumnRefExpression)
|
} as ColumnRefExpression)
|
||||||
@@ -248,6 +249,7 @@ export class TableGridDisplay extends GridDisplay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
processReferences(select: Select, displayedColumnInfo: DisplayedColumnInfo, options) {
|
processReferences(select: Select, displayedColumnInfo: DisplayedColumnInfo, options) {
|
||||||
|
if (!this.areReferencesAllowed) return;
|
||||||
this.addJoinsFromExpandedColumns(select, this.columns, 'basetbl', displayedColumnInfo);
|
this.addJoinsFromExpandedColumns(select, this.columns, 'basetbl', displayedColumnInfo);
|
||||||
if (!options.isExport && this.displayOptions.showHintColumns) {
|
if (!options.isExport && this.displayOptions.showHintColumns) {
|
||||||
this.addHintsToSelect(select);
|
this.addHintsToSelect(select);
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
"name": "dbgate-filterparser",
|
"name": "dbgate-filterparser",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"typings": "lib/index.d.ts",
|
"typings": "lib/index.d.ts",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/dbgate/dbgate.git"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"start": "tsc --watch",
|
"start": "tsc --watch",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import _cloneDeep from 'lodash/cloneDeep';
|
import _cloneDeep from 'lodash/cloneDeep';
|
||||||
|
import _uniq from 'lodash/uniq';
|
||||||
import _isString from 'lodash/isString';
|
import _isString from 'lodash/isString';
|
||||||
import type {
|
import type {
|
||||||
ColumnInfo,
|
ColumnInfo,
|
||||||
@@ -75,9 +76,27 @@ export function findForeignKeyForColumn(table: TableInfo, column: ColumnInfo | s
|
|||||||
return (table.foreignKeys || []).find(fk => fk.columns.find(col => col.columnName == column.columnName));
|
return (table.foreignKeys || []).find(fk => fk.columns.find(col => col.columnName == column.columnName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getConflictingColumnNames(columns: ColumnInfo[]): Set<string> {
|
||||||
|
const conflictingNames = new Set(
|
||||||
|
_uniq(columns.map(x => x.columnName).filter((item, index, arr) => arr.indexOf(item) !== index))
|
||||||
|
);
|
||||||
|
return conflictingNames;
|
||||||
|
}
|
||||||
|
|
||||||
export function makeUniqueColumnNames(res: ColumnInfo[]) {
|
export function makeUniqueColumnNames(res: ColumnInfo[]) {
|
||||||
const usedNames = new Set();
|
const usedNames = new Set();
|
||||||
|
const conflictingNames = getConflictingColumnNames(res);
|
||||||
for (let i = 0; i < res.length; i++) {
|
for (let i = 0; i < res.length; i++) {
|
||||||
|
if (
|
||||||
|
conflictingNames.has(res[i].columnName) &&
|
||||||
|
res[i].pureName &&
|
||||||
|
!usedNames.has(`${res[i].pureName}_${res[i].columnName}`)
|
||||||
|
) {
|
||||||
|
res[i].columnName = `${res[i].pureName}_${res[i].columnName}`;
|
||||||
|
usedNames.add(res[i].columnName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (usedNames.has(res[i].columnName)) {
|
if (usedNames.has(res[i].columnName)) {
|
||||||
let suffix = 2;
|
let suffix = 2;
|
||||||
while (usedNames.has(`${res[i].columnName}${suffix}`)) suffix++;
|
while (usedNames.has(`${res[i].columnName}${suffix}`)) suffix++;
|
||||||
|
|||||||
1
packages/types/engines.d.ts
vendored
1
packages/types/engines.d.ts
vendored
@@ -21,6 +21,7 @@ export interface StreamOptions {
|
|||||||
error?: (error) => void;
|
error?: (error) => void;
|
||||||
done?: (result) => void;
|
done?: (result) => void;
|
||||||
info?: (info) => void;
|
info?: (info) => void;
|
||||||
|
changedCurrentDatabase?: (database: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CollectionOperationInfo =
|
export type CollectionOperationInfo =
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
"build:index": "node build-index.js",
|
"build:index": "node build-index.js",
|
||||||
"prepublishOnly": "yarn build"
|
"prepublishOnly": "yarn build"
|
||||||
},
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/dbgate/dbgate.git"
|
||||||
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"public"
|
"public"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -30,3 +30,20 @@
|
|||||||
.color-icon-inv-red {
|
.color-icon-inv-red {
|
||||||
color: var(--theme-icon-inv-red);
|
color: var(--theme-icon-inv-red);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.premium-background-gradient {
|
||||||
|
background: linear-gradient(135deg, #1686c8, #8a25b1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.premium-gradient {
|
||||||
|
background: linear-gradient(135deg, #1686c8, #8a25b1);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.web-color-primary {
|
||||||
|
background: #1686c8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.web-color-secondary {
|
||||||
|
background: #8a25b1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -125,8 +125,8 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="purchase-info">
|
<div class="purchase-info">
|
||||||
For more info about DbGate licensing, you could visit <Link href="https://dbgate.eu/">dbgate.eu</Link> web or contact
|
For more info about DbGate licensing, you could visit <Link href="https://dbgate.io/">dbgate.io</Link> web or contact
|
||||||
us at <Link href="mailto:sales@dbgate.eu">sales@dbgate.eu</Link>
|
us at <Link href="mailto:sales@dbgate.io">sales@dbgate.io</Link>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<ErrorInfo message="License for DbGate is not valid. Please contact administrator." />
|
<ErrorInfo message="License for DbGate is not valid. Please contact administrator." />
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<div class="heading">Configuration error</div>
|
<div class="heading">Configuration error</div>
|
||||||
{#if $config?.checkedLicense?.status == 'error'}
|
{#if $config?.checkedLicense?.status == 'error'}
|
||||||
<ErrorInfo
|
<ErrorInfo
|
||||||
message={`Invalid license. Please contact sales@dbgate.eu for more details. ${$config?.checkedLicense?.error}`}
|
message={`Invalid license. Please contact sales@dbgate.io for more details. ${$config?.checkedLicense?.error}`}
|
||||||
/>
|
/>
|
||||||
{:else if $config?.configurationError}
|
{:else if $config?.configurationError}
|
||||||
<ErrorInfo message={$config?.configurationError} />
|
<ErrorInfo message={$config?.configurationError} />
|
||||||
|
|||||||
@@ -468,12 +468,14 @@ await dbgateApi.executeQuery(${JSON.stringify(
|
|||||||
|
|
||||||
{ divider: true },
|
{ divider: true },
|
||||||
isSqlOrDoc &&
|
isSqlOrDoc &&
|
||||||
|
isProApp() &&
|
||||||
!connection.isReadOnly &&
|
!connection.isReadOnly &&
|
||||||
hasPermission(`dbops/import`) && {
|
hasPermission(`dbops/import`) && {
|
||||||
onClick: handleImport,
|
onClick: handleImport,
|
||||||
text: _t('database.import', { defaultMessage: 'Import' }),
|
text: _t('database.import', { defaultMessage: 'Import' }),
|
||||||
},
|
},
|
||||||
isSqlOrDoc &&
|
isSqlOrDoc &&
|
||||||
|
isProApp() &&
|
||||||
hasPermission(`dbops/export`) && {
|
hasPermission(`dbops/export`) && {
|
||||||
onClick: handleExport,
|
onClick: handleExport,
|
||||||
text: _t('database.export', { defaultMessage: 'Export' }),
|
text: _t('database.export', { defaultMessage: 'Export' }),
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
export let title = null;
|
export let title = null;
|
||||||
export let skipWidth = false;
|
export let skipWidth = false;
|
||||||
export let outline = false;
|
export let outline = false;
|
||||||
|
export let colorClass = '';
|
||||||
|
|
||||||
function handleClick() {
|
function handleClick() {
|
||||||
if (!disabled) dispatch('click');
|
if (!disabled) dispatch('click');
|
||||||
@@ -31,6 +32,8 @@
|
|||||||
bind:this={domButton}
|
bind:this={domButton}
|
||||||
class:skipWidth
|
class:skipWidth
|
||||||
class:outline
|
class:outline
|
||||||
|
class={colorClass}
|
||||||
|
class:setBackgroundColor={!colorClass}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -38,19 +41,26 @@
|
|||||||
border: 1px solid var(--theme-bg-button-inv-2);
|
border: 1px solid var(--theme-bg-button-inv-2);
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
background-color: var(--theme-bg-button-inv);
|
|
||||||
color: var(--theme-font-inv-1);
|
color: var(--theme-font-inv-1);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.setBackgroundColor {
|
||||||
|
background-color: var(--theme-bg-button-inv);
|
||||||
|
}
|
||||||
|
|
||||||
input:not(.skipWidth) {
|
input:not(.skipWidth) {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:hover:not(.disabled):not(.outline) {
|
input:not(.setBackgroundColor) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.setBackgroundColor:hover:not(.disabled):not(.outline) {
|
||||||
background-color: var(--theme-bg-button-inv-2);
|
background-color: var(--theme-bg-button-inv-2);
|
||||||
}
|
}
|
||||||
input:active:not(.disabled):not(.outline) {
|
input.setBackgroundColor:active:not(.disabled):not(.outline) {
|
||||||
background-color: var(--theme-bg-button-inv-3);
|
background-color: var(--theme-bg-button-inv-3);
|
||||||
}
|
}
|
||||||
input.disabled {
|
input.disabled {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
getCloudSigninTokenHolder,
|
getCloudSigninTokenHolder,
|
||||||
getExtensions,
|
getExtensions,
|
||||||
getVisibleToolbar,
|
getVisibleToolbar,
|
||||||
|
promoWidgetPreview,
|
||||||
visibleToolbar,
|
visibleToolbar,
|
||||||
visibleWidgetSideBar,
|
visibleWidgetSideBar,
|
||||||
} from '../stores';
|
} from '../stores';
|
||||||
@@ -50,6 +51,7 @@ import { isProApp } from '../utility/proTools';
|
|||||||
import { openWebLink } from '../utility/simpleTools';
|
import { openWebLink } from '../utility/simpleTools';
|
||||||
import { _t } from '../translations';
|
import { _t } from '../translations';
|
||||||
import ExportImportConnectionsModal from '../modals/ExportImportConnectionsModal.svelte';
|
import ExportImportConnectionsModal from '../modals/ExportImportConnectionsModal.svelte';
|
||||||
|
import { getBoolSettingsValue } from '../settings/settingsTools';
|
||||||
|
|
||||||
// function themeCommand(theme: ThemeDefinition) {
|
// function themeCommand(theme: ThemeDefinition) {
|
||||||
// return {
|
// return {
|
||||||
@@ -689,7 +691,7 @@ registerCommand({
|
|||||||
name: 'Export database',
|
name: 'Export database',
|
||||||
toolbar: true,
|
toolbar: true,
|
||||||
icon: 'icon export',
|
icon: 'icon export',
|
||||||
testEnabled: () => getCurrentDatabase() != null && hasPermission(`dbops/export`),
|
testEnabled: () => getCurrentDatabase() != null && hasPermission(`dbops/export`) && isProApp(),
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
openImportExportTab({
|
openImportExportTab({
|
||||||
targetStorageType: getDefaultFileFormat(getExtensions()).storageType,
|
targetStorageType: getDefaultFileFormat(getExtensions()).storageType,
|
||||||
@@ -1164,6 +1166,41 @@ registerCommand({
|
|||||||
onClick: () => currentDatabase.set(null),
|
onClick: () => currentDatabase.set(null),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let loadedCampaignList = [];
|
||||||
|
|
||||||
|
registerCommand({
|
||||||
|
id: 'internal.loadCampaigns',
|
||||||
|
category: 'Internal',
|
||||||
|
name: 'Load campaign list',
|
||||||
|
testEnabled: () => getBoolSettingsValue('internal.showCampaigns', false),
|
||||||
|
onClick: async () => {
|
||||||
|
const resp = await apiCall('cloud/promo-widget-list', {});
|
||||||
|
loadedCampaignList = resp;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
registerCommand({
|
||||||
|
id: 'internal.showCampaigns',
|
||||||
|
category: 'Internal',
|
||||||
|
name: 'Show campaigns',
|
||||||
|
testEnabled: () => getBoolSettingsValue('internal.showCampaigns', false) && loadedCampaignList?.length > 0,
|
||||||
|
getSubCommands: () => {
|
||||||
|
return loadedCampaignList.map(campaign => ({
|
||||||
|
text: `${campaign.campaignName} (${campaign.countries || 'Global'}) - #${campaign.quantileRank ?? '*'}/${
|
||||||
|
campaign.quantileGroupCount ?? '*'
|
||||||
|
} - ${campaign.variantIdentifier}`,
|
||||||
|
onClick: async () => {
|
||||||
|
promoWidgetPreview.set(
|
||||||
|
await apiCall('cloud/promo-widget-preview', {
|
||||||
|
campaign: campaign.campaignIdentifier,
|
||||||
|
variant: campaign.variantIdentifier,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const electron = getElectron();
|
const electron = getElectron();
|
||||||
if (electron) {
|
if (electron) {
|
||||||
electron.addEventListener('run-command', (e, commandId) => runCommand(commandId));
|
electron.addEventListener('run-command', (e, commandId) => runCommand(commandId));
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
import { showModal } from '../modals/modalTools';
|
import { showModal } from '../modals/modalTools';
|
||||||
import DefineDictionaryDescriptionModal from '../modals/DefineDictionaryDescriptionModal.svelte';
|
import DefineDictionaryDescriptionModal from '../modals/DefineDictionaryDescriptionModal.svelte';
|
||||||
import { sleep } from '../utility/common';
|
import { sleep } from '../utility/common';
|
||||||
|
import { isProApp } from '../utility/proTools';
|
||||||
|
|
||||||
export let column;
|
export let column;
|
||||||
export let conid = undefined;
|
export let conid = undefined;
|
||||||
@@ -72,15 +73,19 @@
|
|||||||
|
|
||||||
column.foreignKey && [{ divider: true }, { onClick: openReferencedTable, text: column.foreignKey.refTableName }],
|
column.foreignKey && [{ divider: true }, { onClick: openReferencedTable, text: column.foreignKey.refTableName }],
|
||||||
|
|
||||||
setGrouping && { divider: true },
|
isProApp() &&
|
||||||
setGrouping && { onClick: () => setGrouping('GROUP'), text: 'Group by' },
|
setGrouping && [
|
||||||
setGrouping && { onClick: () => setGrouping('MAX'), text: 'MAX' },
|
{ divider: true },
|
||||||
setGrouping && { onClick: () => setGrouping('MIN'), text: 'MIN' },
|
{ onClick: () => setGrouping('GROUP'), text: 'Group by' },
|
||||||
setGrouping && { onClick: () => setGrouping('SUM'), text: 'SUM' },
|
{ onClick: () => setGrouping('MAX'), text: 'MAX' },
|
||||||
setGrouping && { onClick: () => setGrouping('AVG'), text: 'AVG' },
|
{ onClick: () => setGrouping('MIN'), text: 'MIN' },
|
||||||
setGrouping && { onClick: () => setGrouping('COUNT'), text: 'COUNT' },
|
{ onClick: () => setGrouping('SUM'), text: 'SUM' },
|
||||||
setGrouping && { onClick: () => setGrouping('COUNT DISTINCT'), text: 'COUNT DISTINCT' },
|
{ onClick: () => setGrouping('AVG'), text: 'AVG' },
|
||||||
|
{ onClick: () => setGrouping('COUNT'), text: 'COUNT' },
|
||||||
|
{ onClick: () => setGrouping('COUNT DISTINCT'), text: 'COUNT DISTINCT' },
|
||||||
|
],
|
||||||
|
|
||||||
|
isProApp() &&
|
||||||
isTypeDateTime(column.dataType) && [
|
isTypeDateTime(column.dataType) && [
|
||||||
{ divider: true },
|
{ divider: true },
|
||||||
{ onClick: () => setGrouping('GROUP:YEAR'), text: 'Group by YEAR' },
|
{ onClick: () => setGrouping('GROUP:YEAR'), text: 'Group by YEAR' },
|
||||||
@@ -90,8 +95,10 @@
|
|||||||
|
|
||||||
{ divider: true },
|
{ divider: true },
|
||||||
|
|
||||||
|
isProApp() &&
|
||||||
allowDefineVirtualReferences && { onClick: handleDefineVirtualForeignKey, text: 'Define virtual foreign key' },
|
allowDefineVirtualReferences && { onClick: handleDefineVirtualForeignKey, text: 'Define virtual foreign key' },
|
||||||
column.foreignKey && {
|
column.foreignKey &&
|
||||||
|
isProApp() && {
|
||||||
onClick: handleCustomizeDescriptions,
|
onClick: handleCustomizeDescriptions,
|
||||||
text: 'Customize description',
|
text: 'Customize description',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
import { showModal } from '../modals/modalTools';
|
import { showModal } from '../modals/modalTools';
|
||||||
import ColumnEditorModal from '../tableeditor/ColumnEditorModal.svelte';
|
import ColumnEditorModal from '../tableeditor/ColumnEditorModal.svelte';
|
||||||
import { editorDeleteColumn } from 'dbgate-tools';
|
import { editorDeleteColumn } from 'dbgate-tools';
|
||||||
|
import { isProApp } from '../utility/proTools';
|
||||||
|
|
||||||
export let column;
|
export let column;
|
||||||
export let display;
|
export let display;
|
||||||
@@ -59,13 +60,17 @@
|
|||||||
on:mouseup
|
on:mouseup
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
|
{#if isProApp()}
|
||||||
<span class="expandColumnIcon" style={`margin-right: ${5 + (column.uniquePath.length - 1) * 10}px`}>
|
<span class="expandColumnIcon" style={`margin-right: ${5 + (column.uniquePath.length - 1) * 10}px`}>
|
||||||
<FontIcon
|
<FontIcon
|
||||||
icon={column.isExpandable ? plusExpandIcon(display.isExpandedColumn(column.uniqueName)) : 'icon invisible-box'}
|
icon={column.isExpandable
|
||||||
|
? plusExpandIcon(display.isExpandedColumn(column.uniqueName))
|
||||||
|
: 'icon invisible-box'}
|
||||||
on:click={() => display.toggleExpandedColumn(column.uniqueName)}
|
on:click={() => display.toggleExpandedColumn(column.uniqueName)}
|
||||||
data-testid="ColumnManagerRow_expand_{column.uniqueName}"
|
data-testid="ColumnManagerRow_expand_{column.uniqueName}"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
{/if}
|
||||||
{#if isJsonView}
|
{#if isJsonView}
|
||||||
<FontIcon icon="img column" />
|
<FontIcon icon="img column" />
|
||||||
{:else}
|
{:else}
|
||||||
|
|||||||
@@ -69,6 +69,7 @@
|
|||||||
import { registerMenu } from '../utility/contextMenu';
|
import { registerMenu } from '../utility/contextMenu';
|
||||||
import { getLocalStorage, setLocalStorage } from '../utility/storageCache';
|
import { getLocalStorage, setLocalStorage } from '../utility/storageCache';
|
||||||
import { __t, _t } from '../translations';
|
import { __t, _t } from '../translations';
|
||||||
|
import { isProApp } from '../utility/proTools';
|
||||||
|
|
||||||
export let config;
|
export let config;
|
||||||
export let setConfig;
|
export let setConfig;
|
||||||
@@ -206,7 +207,7 @@
|
|||||||
name="references"
|
name="references"
|
||||||
height="30%"
|
height="30%"
|
||||||
collapsed={isDetailView}
|
collapsed={isDetailView}
|
||||||
skip={!(showReferences && display?.hasReferences)}
|
skip={!(showReferences && display?.hasReferences && isProApp())}
|
||||||
data-testid="DataGrid_itemReferences"
|
data-testid="DataGrid_itemReferences"
|
||||||
>
|
>
|
||||||
<ReferenceManager {...$$props} {managerSize} />
|
<ReferenceManager {...$$props} {managerSize} />
|
||||||
@@ -215,7 +216,7 @@
|
|||||||
<WidgetColumnBarItem
|
<WidgetColumnBarItem
|
||||||
title={_t('dataGrid.macros', { defaultMessage: 'Macros' })}
|
title={_t('dataGrid.macros', { defaultMessage: 'Macros' })}
|
||||||
name="macros"
|
name="macros"
|
||||||
skip={!showMacros}
|
skip={!(showMacros && isProApp())}
|
||||||
collapsed={!expandMacros}
|
collapsed={!expandMacros}
|
||||||
data-testid="DataGrid_itemMacros"
|
data-testid="DataGrid_itemMacros"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1413,7 +1413,11 @@
|
|||||||
|
|
||||||
function handleGridWheel(event) {
|
function handleGridWheel(event) {
|
||||||
if (event.shiftKey) {
|
if (event.shiftKey) {
|
||||||
|
if (isMac()) {
|
||||||
|
scrollHorizontal(event.deltaX, event.deltaY);
|
||||||
|
} else {
|
||||||
scrollHorizontal(event.deltaY, event.deltaX);
|
scrollHorizontal(event.deltaY, event.deltaX);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
scrollHorizontal(event.deltaX, event.deltaY);
|
scrollHorizontal(event.deltaX, event.deltaY);
|
||||||
scrollVertical(event.deltaX, event.deltaY);
|
scrollVertical(event.deltaX, event.deltaY);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if dependencies.length > 0}
|
{#if dependencies.length > 0}
|
||||||
<div class="bold nowrap ml-1">Dependend tables ({dependencies.length})</div>
|
<div class="bold nowrap ml-1">Dependent tables ({dependencies.length})</div>
|
||||||
{#each dependencies.filter(fk => filterName(filter, fk.pureName)) as fk}
|
{#each dependencies.filter(fk => filterName(filter, fk.pureName)) as fk}
|
||||||
<div
|
<div
|
||||||
class="link"
|
class="link"
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
import SqlFormView from '../formview/SqlFormView.svelte';
|
import SqlFormView from '../formview/SqlFormView.svelte';
|
||||||
import { getBoolSettingsValue } from '../settings/settingsTools';
|
import { getBoolSettingsValue } from '../settings/settingsTools';
|
||||||
import { getDictionaryDescription } from '../utility/dictionaryDescriptionTools';
|
import { getDictionaryDescription } from '../utility/dictionaryDescriptionTools';
|
||||||
|
import { isProApp } from '../utility/proTools';
|
||||||
|
|
||||||
export let conid;
|
export let conid;
|
||||||
export let database;
|
export let database;
|
||||||
@@ -82,7 +83,8 @@
|
|||||||
extendedDbInfo?.tables?.find(x => x.pureName == pureName && x.schemaName == schemaName)
|
extendedDbInfo?.tables?.find(x => x.pureName == pureName && x.schemaName == schemaName)
|
||||||
?.tablePermissionRole == 'read',
|
?.tablePermissionRole == 'read',
|
||||||
isRawMode,
|
isRawMode,
|
||||||
$settingsValue
|
$settingsValue,
|
||||||
|
isProApp()
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,31 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import JsonUiCountdown from './JsonUiCountdown.svelte';
|
||||||
import JsonUiHeading from './JsonUiHeading.svelte';
|
import JsonUiHeading from './JsonUiHeading.svelte';
|
||||||
|
import JsonUiHighlight from './JsonUiHighlight.svelte';
|
||||||
import JsonUiLinkButton from './JsonUiLinkButton.svelte';
|
import JsonUiLinkButton from './JsonUiLinkButton.svelte';
|
||||||
|
import JsonUiLinkButtonBlock from './JsonUiLinkButtonBlock.svelte';
|
||||||
|
import JsonUiMarkdown from './JsonUiMarkdown.svelte';
|
||||||
import JsonUiTextBlock from './JsonUiTextBlock.svelte';
|
import JsonUiTextBlock from './JsonUiTextBlock.svelte';
|
||||||
import JsonUiTickList from './JsonUiTickList.svelte';
|
import JsonUiTickList from './JsonUiTickList.svelte';
|
||||||
import { JsonUiBlock } from './jsonuitypes';
|
import { JsonUiBlock } from './jsonuitypes';
|
||||||
|
|
||||||
export let blocks: JsonUiBlock[] = [];
|
export let blocks: JsonUiBlock[] = [];
|
||||||
|
export let passProps = {};
|
||||||
|
|
||||||
const componentMap = {
|
const componentMap = {
|
||||||
text: JsonUiTextBlock,
|
text: JsonUiTextBlock,
|
||||||
heading: JsonUiHeading,
|
heading: JsonUiHeading,
|
||||||
ticklist: JsonUiTickList,
|
ticklist: JsonUiTickList,
|
||||||
button: JsonUiLinkButton,
|
button: JsonUiLinkButton,
|
||||||
|
markdown: JsonUiMarkdown,
|
||||||
|
highlight: JsonUiHighlight,
|
||||||
|
countdown: JsonUiCountdown,
|
||||||
|
buttonblock: JsonUiLinkButtonBlock,
|
||||||
} as const;
|
} as const;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#each blocks as block, i}
|
{#each blocks as block, i}
|
||||||
{#if block.type in componentMap}
|
{#if block.type in componentMap}
|
||||||
<svelte:component this={componentMap[block.type]} {...block} />
|
<svelte:component this={componentMap[block.type]} {...block} {...passProps} />
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
|
|||||||
87
packages/web/src/jsonui/JsonUiCountdown.svelte
Normal file
87
packages/web/src/jsonui/JsonUiCountdown.svelte
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { openWebLink } from '../utility/simpleTools';
|
||||||
|
|
||||||
|
export let colorClass: string = 'premium-gradient';
|
||||||
|
export let validTo;
|
||||||
|
export let link;
|
||||||
|
|
||||||
|
function formatRemaining(validTo, now) {
|
||||||
|
let diffMs = validTo.getTime() - now.getTime();
|
||||||
|
if (diffMs <= 0) return '0 minutes';
|
||||||
|
|
||||||
|
const totalMinutes = Math.floor(diffMs / 60000);
|
||||||
|
const days = Math.floor(totalMinutes / (24 * 60));
|
||||||
|
const hours = Math.floor((totalMinutes % (24 * 60)) / 60);
|
||||||
|
const minutes = totalMinutes % 60;
|
||||||
|
|
||||||
|
const parts = [];
|
||||||
|
const en = (n, unit) => ({
|
||||||
|
num: n,
|
||||||
|
unit: n == 1 ? unit : unit + 's',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (days) parts.push(en(days, 'day'));
|
||||||
|
if (hours) parts.push(en(hours, 'hour'));
|
||||||
|
// Always include minutes to report down to minutes
|
||||||
|
parts.push(en(minutes, 'minute'));
|
||||||
|
|
||||||
|
return parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentDate = new Date();
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
currentDate = new Date();
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearInterval(interval);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
$: parts = formatRemaining(new Date(validTo), currentDate);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if validTo}
|
||||||
|
<div
|
||||||
|
class="countdown {colorClass}"
|
||||||
|
class:isLink={!!link}
|
||||||
|
on:click={() => {
|
||||||
|
if (link) {
|
||||||
|
openWebLink(link);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span class="big">Offer ends in:</span><br />
|
||||||
|
{#each parts as part}
|
||||||
|
<span class="part">
|
||||||
|
<span class="big">{part.num}</span>
|
||||||
|
{part.unit}
|
||||||
|
</span>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.countdown {
|
||||||
|
text-align: center;
|
||||||
|
margin: 10px;
|
||||||
|
border: 1px solid;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdown.isLink {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.big {
|
||||||
|
font-size: large;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.part {
|
||||||
|
margin: 0 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
35
packages/web/src/jsonui/JsonUiHighlight.svelte
Normal file
35
packages/web/src/jsonui/JsonUiHighlight.svelte
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { openWebLink } from '../utility/simpleTools';
|
||||||
|
|
||||||
|
export let text: string;
|
||||||
|
export let colorClass: string = 'premium-gradient';
|
||||||
|
export let link: string;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="highlight {colorClass}"
|
||||||
|
class:isLink={!!link}
|
||||||
|
on:click={() => {
|
||||||
|
if (link) {
|
||||||
|
openWebLink(link);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.highlight {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
margin: 10px;
|
||||||
|
font-size: large;
|
||||||
|
font-weight: bold;
|
||||||
|
border: 1px solid;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight.isLink {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -4,14 +4,11 @@
|
|||||||
|
|
||||||
export let text: string;
|
export let text: string;
|
||||||
export let link: string;
|
export let link: string;
|
||||||
export let newTab: boolean = true;
|
export let colorClass: string = '';
|
||||||
|
|
||||||
// very light url guard
|
|
||||||
const safe = /^(https?:)?\/\//i.test(link) || link.startsWith('/');
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="center">
|
<div class="center">
|
||||||
<FormStyledButton on:click={() => openWebLink(link)} value={text} skipWidth />
|
<FormStyledButton on:click={() => openWebLink(link)} value={text} skipWidth {colorClass} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
21
packages/web/src/jsonui/JsonUiLinkButtonBlock.svelte
Normal file
21
packages/web/src/jsonui/JsonUiLinkButtonBlock.svelte
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import FormStyledButton from '../buttons/FormStyledButton.svelte';
|
||||||
|
import { openWebLink } from '../utility/simpleTools';
|
||||||
|
|
||||||
|
export let text: string;
|
||||||
|
export let link: string;
|
||||||
|
export let colorClass: string = '';
|
||||||
|
export let items: any[] = [];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="center">
|
||||||
|
{#each items as item}
|
||||||
|
<FormStyledButton on:click={() => openWebLink(item.link)} value={item.text} skipWidth {colorClass} />
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
15
packages/web/src/jsonui/JsonUiMarkdown.svelte
Normal file
15
packages/web/src/jsonui/JsonUiMarkdown.svelte
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import Markdown from '../elements/Markdown.svelte';
|
||||||
|
|
||||||
|
export let text: string;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Markdown source={text} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -95,6 +95,7 @@
|
|||||||
title: _t('common.exportDatabase', { defaultMessage: 'Export database' }),
|
title: _t('common.exportDatabase', { defaultMessage: 'Export database' }),
|
||||||
description: _t('newObject.exportDescription', { defaultMessage: 'Export to file like CSV, JSON, Excel, or other DB' }),
|
description: _t('newObject.exportDescription', { defaultMessage: 'Export to file like CSV, JSON, Excel, or other DB' }),
|
||||||
command: 'database.export',
|
command: 'database.export',
|
||||||
|
isProFeature: true,
|
||||||
testid: 'NewObjectModal_databaseExport',
|
testid: 'NewObjectModal_databaseExport',
|
||||||
disabledMessage: _t('newObject.exportDisabled', { defaultMessage: 'Export is not available for current database' }),
|
disabledMessage: _t('newObject.exportDisabled', { defaultMessage: 'Export is not available for current database' }),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -187,6 +187,9 @@ export const seenPremiumPromoWidget = writableWithStorage(null, 'seenPremiumProm
|
|||||||
|
|
||||||
export const cloudConnectionsStore = writable({});
|
export const cloudConnectionsStore = writable({});
|
||||||
|
|
||||||
|
export const promoWidgetPreview = writable(null);
|
||||||
|
|
||||||
|
|
||||||
export const DEFAULT_OBJECT_SEARCH_SETTINGS = {
|
export const DEFAULT_OBJECT_SEARCH_SETTINGS = {
|
||||||
pureName: true,
|
pureName: true,
|
||||||
schemaName: false,
|
schemaName: false,
|
||||||
|
|||||||
@@ -358,6 +358,8 @@
|
|||||||
import { handleAfterTabClick } from '../utility/changeCurrentDbByTab';
|
import { handleAfterTabClick } from '../utility/changeCurrentDbByTab';
|
||||||
import { getBoolSettingsValue } from '../settings/settingsTools';
|
import { getBoolSettingsValue } from '../settings/settingsTools';
|
||||||
import NewObjectModal from '../modals/NewObjectModal.svelte';
|
import NewObjectModal from '../modals/NewObjectModal.svelte';
|
||||||
|
import { isProApp } from '../utility/proTools';
|
||||||
|
import { openWebLink } from '../utility/simpleTools';
|
||||||
|
|
||||||
export let multiTabIndex;
|
export let multiTabIndex;
|
||||||
export let shownTab;
|
export let shownTab;
|
||||||
@@ -583,7 +585,13 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<div class="tabs" class:can-split={allowSplitTab} on:wheel={handleTabsWheel} bind:this={domTabs}>
|
<div
|
||||||
|
class="tabs"
|
||||||
|
class:can-split={allowSplitTab && isProApp()}
|
||||||
|
class:tabs-upgrade-button={!isProApp()}
|
||||||
|
on:wheel={handleTabsWheel}
|
||||||
|
bind:this={domTabs}
|
||||||
|
>
|
||||||
{#each groupedTabs as tabGroup}
|
{#each groupedTabs as tabGroup}
|
||||||
<div class="db-wrapper">
|
<div class="db-wrapper">
|
||||||
{#if !$lockedDatabaseMode}
|
{#if !$lockedDatabaseMode}
|
||||||
@@ -713,7 +721,7 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<div class="icons-wrapper">
|
<div class="icons-wrapper">
|
||||||
{#if allowSplitTab}
|
{#if allowSplitTab && isProApp()}
|
||||||
<div
|
<div
|
||||||
class="icon-button"
|
class="icon-button"
|
||||||
on:click={() => splitTab(multiTabIndex)}
|
on:click={() => splitTab(multiTabIndex)}
|
||||||
@@ -723,6 +731,22 @@
|
|||||||
<FontIcon icon="icon split" />
|
<FontIcon icon="icon split" />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{#if !isProApp()}
|
||||||
|
<div
|
||||||
|
class="upgrade-button"
|
||||||
|
on:click={() => {
|
||||||
|
openWebLink(
|
||||||
|
`https://www.dbgate.io/purchase/${isElectronAvailable() ? 'premium' : 'team-premium'}/?utm_campaign=premiumUpgradeButton`
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
title="Upgrade to Premium"
|
||||||
|
data-testid="TabsPanel_buttonUpgrade"
|
||||||
|
>
|
||||||
|
<FontIcon icon="icon premium" padRight /> Upgrade
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="icon-button"
|
class="icon-button"
|
||||||
on:click={() => showModal(NewObjectModal, { multiTabIndex })}
|
on:click={() => showModal(NewObjectModal, { multiTabIndex })}
|
||||||
@@ -756,6 +780,18 @@
|
|||||||
color: var(--theme-font-2);
|
color: var(--theme-font-2);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
.upgrade-button {
|
||||||
|
background: linear-gradient(135deg, #1686c8, #8a25b1);
|
||||||
|
border: 1px solid var(--theme-border);
|
||||||
|
border-radius: 10px;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 10pt;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
.upgrade-button:hover {
|
||||||
|
background: linear-gradient(135deg, #0f5a85, #5c1870);
|
||||||
|
}
|
||||||
.icon-button:hover {
|
.icon-button:hover {
|
||||||
color: var(--theme-font-1);
|
color: var(--theme-font-1);
|
||||||
}
|
}
|
||||||
@@ -769,6 +805,10 @@
|
|||||||
right: 35px;
|
right: 35px;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tabs-upgrade-button {
|
||||||
|
right: 120px;
|
||||||
|
}
|
||||||
.tabs.can-split {
|
.tabs.can-split {
|
||||||
right: 60px;
|
right: 60px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -266,9 +266,11 @@
|
|||||||
if (sid) {
|
if (sid) {
|
||||||
apiOn(`session-done-${sid}`, handleSessionDone);
|
apiOn(`session-done-${sid}`, handleSessionDone);
|
||||||
apiOn(`session-closed-${sid}`, handleSessionClosed);
|
apiOn(`session-closed-${sid}`, handleSessionClosed);
|
||||||
|
apiOn(`session-changedb-${sid}`, handleChangedDatabase);
|
||||||
return () => {
|
return () => {
|
||||||
apiOff(`session-done-${sid}`, handleSessionDone);
|
apiOff(`session-done-${sid}`, handleSessionDone);
|
||||||
apiOff(`session-closed-${sid}`, handleSessionClosed);
|
apiOff(`session-closed-${sid}`, handleSessionClosed);
|
||||||
|
apiOff(`session-changedb-${sid}`, handleChangedDatabase);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return () => {};
|
return () => {};
|
||||||
@@ -567,6 +569,17 @@
|
|||||||
handleSessionDone();
|
handleSessionDone();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleChangedDatabase = async props => {
|
||||||
|
changeTab(tabid, tab => ({
|
||||||
|
...tab,
|
||||||
|
props: {
|
||||||
|
...tab.props,
|
||||||
|
conid,
|
||||||
|
database: props.database,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
const { editorState, editorValue, setEditorData } = useEditorData({
|
const { editorState, editorValue, setEditorData } = useEditorData({
|
||||||
tabid,
|
tabid,
|
||||||
loadFromArgs:
|
loadFromArgs:
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ import type { QuickExportDefinition } from 'dbgate-types';
|
|||||||
import { currentArchive, getCurrentArchive, getExtensions } from '../stores';
|
import { currentArchive, getCurrentArchive, getExtensions } from '../stores';
|
||||||
import hasPermission from './hasPermission';
|
import hasPermission from './hasPermission';
|
||||||
import { _t } from '../translations'
|
import { _t } from '../translations'
|
||||||
|
import { isProApp } from './proTools';
|
||||||
|
|
||||||
export function createQuickExportMenuItems(handler: (fmt: QuickExportDefinition) => Function, advancedExportMenuItem) {
|
export function createQuickExportMenuItems(handler: (fmt: QuickExportDefinition) => Function, advancedExportMenuItem) {
|
||||||
const extensions = getExtensions();
|
const extensions = getExtensions();
|
||||||
return [
|
return [
|
||||||
{
|
isProApp() && {
|
||||||
text: _t('export.exportAdvanced', { defaultMessage : 'Export advanced...'}),
|
text: _t('export.exportAdvanced', { defaultMessage : 'Export advanced...'}),
|
||||||
...advancedExportMenuItem,
|
...advancedExportMenuItem,
|
||||||
},
|
},
|
||||||
@@ -16,7 +17,7 @@ export function createQuickExportMenuItems(handler: (fmt: QuickExportDefinition)
|
|||||||
onClick: handler(fmt),
|
onClick: handler(fmt),
|
||||||
})),
|
})),
|
||||||
{ divider: true },
|
{ divider: true },
|
||||||
{
|
isProApp() && {
|
||||||
text: _t('export.currentArchive', { defaultMessage : 'Current archive'}),
|
text: _t('export.currentArchive', { defaultMessage : 'Current archive'}),
|
||||||
onClick: handler({
|
onClick: handler({
|
||||||
extension: 'jsonl',
|
extension: 'jsonl',
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import JsonUiContentRenderer from '../jsonui/JsonUiContentRenderer.svelte';
|
import JsonUiContentRenderer from '../jsonui/JsonUiContentRenderer.svelte';
|
||||||
|
import { promoWidgetPreview } from '../stores';
|
||||||
import { usePromoWidget } from '../utility/metadataLoaders';
|
import { usePromoWidget } from '../utility/metadataLoaders';
|
||||||
import WidgetsInnerContainer from './WidgetsInnerContainer.svelte';
|
import WidgetsInnerContainer from './WidgetsInnerContainer.svelte';
|
||||||
|
|
||||||
const promoWidget = usePromoWidget({});
|
const promoWidget = usePromoWidget({});
|
||||||
|
|
||||||
|
$: promoWidgetData = $promoWidgetPreview || $promoWidget;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<WidgetsInnerContainer>
|
<WidgetsInnerContainer>
|
||||||
{#if $promoWidget?.state == 'data'}
|
{#if promoWidgetData?.state == 'data'}
|
||||||
<JsonUiContentRenderer blocks={$promoWidget?.blocks} />
|
<JsonUiContentRenderer blocks={promoWidgetData?.blocks} passProps={{ validTo: promoWidgetData?.validTo }} />
|
||||||
{/if}
|
{/if}
|
||||||
</WidgetsInnerContainer>
|
</WidgetsInnerContainer>
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
import { useConnectionColor } from '../utility/useConnectionColor';
|
import { useConnectionColor } from '../utility/useConnectionColor';
|
||||||
import { apiCall } from '../utility/api';
|
import { apiCall } from '../utility/api';
|
||||||
import { statusBarTabInfo } from '../utility/statusBarStore';
|
import { statusBarTabInfo } from '../utility/statusBarStore';
|
||||||
|
import { isProApp } from '../utility/proTools';
|
||||||
|
|
||||||
$: databaseName = $currentDatabase && $currentDatabase.name;
|
$: databaseName = $currentDatabase && $currentDatabase.name;
|
||||||
$: connection = $currentDatabase && $currentDatabase.connection;
|
$: connection = $currentDatabase && $currentDatabase.connection;
|
||||||
@@ -155,7 +156,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if $currentArchive && $currentArchive != 'default'}
|
{#if isProApp() && $currentArchive && $currentArchive != 'default'}
|
||||||
<div
|
<div
|
||||||
class="item flex clickable"
|
class="item flex clickable"
|
||||||
title="Current archive"
|
title="Current archive"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
import PublicCloudWidget from './PublicCloudWidget.svelte';
|
import PublicCloudWidget from './PublicCloudWidget.svelte';
|
||||||
import PrivateCloudWidget from './PrivateCloudWidget.svelte';
|
import PrivateCloudWidget from './PrivateCloudWidget.svelte';
|
||||||
import hasPermission from '../utility/hasPermission';
|
import hasPermission from '../utility/hasPermission';
|
||||||
|
import { isProApp } from '../utility/proTools';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if hasPermission('widgets/database')}
|
{#if hasPermission('widgets/database')}
|
||||||
@@ -22,7 +23,7 @@
|
|||||||
{#if $visibleSelectedWidget == 'history' && hasPermission('widgets/history')}
|
{#if $visibleSelectedWidget == 'history' && hasPermission('widgets/history')}
|
||||||
<HistoryWidget />
|
<HistoryWidget />
|
||||||
{/if}
|
{/if}
|
||||||
{#if $visibleSelectedWidget == 'archive' && hasPermission('widgets/archive')}
|
{#if $visibleSelectedWidget == 'archive' && hasPermission('widgets/archive') && isProApp()}
|
||||||
<ArchiveWidget />
|
<ArchiveWidget />
|
||||||
{/if}
|
{/if}
|
||||||
{#if $visibleSelectedWidget == 'plugins' && hasPermission('widgets/plugins')}
|
{#if $visibleSelectedWidget == 'plugins' && hasPermission('widgets/plugins')}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
getCurrentConfig,
|
getCurrentConfig,
|
||||||
cloudSigninTokenHolder,
|
cloudSigninTokenHolder,
|
||||||
seenPremiumPromoWidget,
|
seenPremiumPromoWidget,
|
||||||
|
promoWidgetPreview,
|
||||||
} from '../stores';
|
} from '../stores';
|
||||||
import mainMenuDefinition from '../../../../app/src/mainMenuDefinition';
|
import mainMenuDefinition from '../../../../app/src/mainMenuDefinition';
|
||||||
import hasPermission from '../utility/hasPermission';
|
import hasPermission from '../utility/hasPermission';
|
||||||
@@ -60,7 +61,7 @@
|
|||||||
name: 'history',
|
name: 'history',
|
||||||
title: 'Query history & Closed tabs',
|
title: 'Query history & Closed tabs',
|
||||||
},
|
},
|
||||||
{
|
isProApp() && {
|
||||||
icon: 'icon archive',
|
icon: 'icon archive',
|
||||||
name: 'archive',
|
name: 'archive',
|
||||||
title: 'Archive (saved tabular data)',
|
title: 'Archive (saved tabular data)',
|
||||||
@@ -167,6 +168,8 @@
|
|||||||
openWebLink(url, true);
|
openWebLink(url, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: promoWidgetData = $promoWidgetPreview || $promoWidget;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="main">
|
<div class="main">
|
||||||
@@ -177,7 +180,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{#each widgets
|
{#each widgets
|
||||||
.filter(x => x && hasPermission(`widgets/${x.name}`))
|
.filter(x => x && hasPermission(`widgets/${x.name}`))
|
||||||
.filter(x => !x.isPremiumPromo || (!isProApp() && $promoWidget?.state == 'data'))
|
.filter(x => !x.isPremiumPromo || (!isProApp() && promoWidgetData?.state == 'data'))
|
||||||
// .filter(x => !x.isPremiumOnly || isProApp())
|
// .filter(x => !x.isPremiumOnly || isProApp())
|
||||||
.filter(x => x.name != 'cloud-private' || $cloudSigninTokenHolder) as item}
|
.filter(x => x.name != 'cloud-private' || $cloudSigninTokenHolder) as item}
|
||||||
<div
|
<div
|
||||||
@@ -186,10 +189,18 @@
|
|||||||
data-testid={`WidgetIconPanel_${item.name}`}
|
data-testid={`WidgetIconPanel_${item.name}`}
|
||||||
on:click={() => handleChangeWidget(item.name)}
|
on:click={() => handleChangeWidget(item.name)}
|
||||||
>
|
>
|
||||||
|
{#if item.isPremiumPromo && promoWidgetData?.isColoredIcon}
|
||||||
|
<FontIcon
|
||||||
|
icon={item.icon}
|
||||||
|
title={item.title}
|
||||||
|
colorClass="premium-background-gradient widget-icon-panel-rounded"
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
<FontIcon icon={item.icon} title={item.title} />
|
<FontIcon icon={item.icon} title={item.title} />
|
||||||
|
{/if}
|
||||||
{#if item.isPremiumPromo}
|
{#if item.isPremiumPromo}
|
||||||
<div class="premium-promo">Premium</div>
|
<div class="premium-promo">Premium</div>
|
||||||
{#if $promoWidget?.identifier != $seenPremiumPromoWidget}
|
{#if promoWidgetData?.identifier != $seenPremiumPromoWidget}
|
||||||
<div class="premium-promo-not-seen">•</div>
|
<div class="premium-promo-not-seen">•</div>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
@@ -281,4 +292,9 @@
|
|||||||
top: -5px;
|
top: -5px;
|
||||||
right: 5px;
|
right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.widget-icon-panel-rounded) {
|
||||||
|
border-top-left-radius: 10px;
|
||||||
|
border-top-right-radius: 10px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"author": "Jan Prochazka",
|
"author": "Jan Prochazka",
|
||||||
"description": "cassandra connector for DbGate",
|
"description": "cassandra connector for DbGate",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/dbgate/dbgate.git"
|
||||||
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"dbgate",
|
"dbgate",
|
||||||
"cassandra",
|
"cassandra",
|
||||||
|
|||||||
@@ -14,6 +14,10 @@
|
|||||||
"dist",
|
"dist",
|
||||||
"icon.svg"
|
"icon.svg"
|
||||||
],
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/dbgate/dbgate.git"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:frontend": "webpack --config webpack-frontend.config",
|
"build:frontend": "webpack --config webpack-frontend.config",
|
||||||
"build:frontend:watch": "webpack --watch --config webpack-frontend.config",
|
"build:frontend:watch": "webpack --watch --config webpack-frontend.config",
|
||||||
|
|||||||
@@ -186,7 +186,11 @@ async function tediousStream(dbhan, sql, options) {
|
|||||||
severity: 'error',
|
severity: 'error',
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const handleDatabaseChange = database => {
|
||||||
|
options.changedCurrentDatabase(database);
|
||||||
|
};
|
||||||
|
|
||||||
|
dbhan.client.on('databaseChange', handleDatabaseChange);
|
||||||
dbhan.client.on('infoMessage', handleInfo);
|
dbhan.client.on('infoMessage', handleInfo);
|
||||||
dbhan.client.on('errorMessage', handleError);
|
dbhan.client.on('errorMessage', handleError);
|
||||||
const request = new tedious.Request(sql, (err, rowCount) => {
|
const request = new tedious.Request(sql, (err, rowCount) => {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ const stream = require('stream');
|
|||||||
const driverBases = require('../frontend/drivers');
|
const driverBases = require('../frontend/drivers');
|
||||||
const Analyser = require('./Analyser');
|
const Analyser = require('./Analyser');
|
||||||
const mysql2 = require('mysql2');
|
const mysql2 = require('mysql2');
|
||||||
|
const fs = require('fs');
|
||||||
const { getLogger, createBulkInsertStreamBase, makeUniqueColumnNames, extractErrorLogData } =
|
const { getLogger, createBulkInsertStreamBase, makeUniqueColumnNames, extractErrorLogData } =
|
||||||
global.DBGATE_PACKAGES['dbgate-tools'];
|
global.DBGATE_PACKAGES['dbgate-tools'];
|
||||||
|
|
||||||
@@ -14,6 +15,7 @@ function extractColumns(fields) {
|
|||||||
if (fields) {
|
if (fields) {
|
||||||
const res = fields.map(col => ({
|
const res = fields.map(col => ({
|
||||||
columnName: col.name,
|
columnName: col.name,
|
||||||
|
pureName: col.orgTable,
|
||||||
}));
|
}));
|
||||||
makeUniqueColumnNames(res);
|
makeUniqueColumnNames(res);
|
||||||
return res;
|
return res;
|
||||||
@@ -53,6 +55,7 @@ const drivers = driverBases.map(driverBase => ({
|
|||||||
supportBigNumbers: true,
|
supportBigNumbers: true,
|
||||||
bigNumberStrings: true,
|
bigNumberStrings: true,
|
||||||
dateStrings: true,
|
dateStrings: true,
|
||||||
|
infileStreamFactory: path => fs.createReadStream(path),
|
||||||
// TODO: test following options
|
// TODO: test following options
|
||||||
// multipleStatements: true,
|
// multipleStatements: true,
|
||||||
};
|
};
|
||||||
@@ -127,6 +130,9 @@ const drivers = driverBases.map(driverBase => ({
|
|||||||
time: new Date(),
|
time: new Date(),
|
||||||
severity: 'info',
|
severity: 'info',
|
||||||
});
|
});
|
||||||
|
if (row.stateChanges?.schema) {
|
||||||
|
options.changedCurrentDatabase(row.stateChanges.schema);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (columns) {
|
if (columns) {
|
||||||
options.row(zipDataRow(row, columns));
|
options.row(zipDataRow(row, columns));
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"homepage": "https://dbgate.org",
|
"homepage": "https://dbgate.org",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/rinie/dbgate-plugin-oracle"
|
"url": "https://github.com/dbgate/dbgate.git"
|
||||||
},
|
},
|
||||||
"author": "Rinie Kervel",
|
"author": "Rinie Kervel",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ const {
|
|||||||
makeUniqueColumnNames,
|
makeUniqueColumnNames,
|
||||||
extractDbNameFromComposite,
|
extractDbNameFromComposite,
|
||||||
extractErrorLogData,
|
extractErrorLogData,
|
||||||
|
getConflictingColumnNames,
|
||||||
} = global.DBGATE_PACKAGES['dbgate-tools'];
|
} = global.DBGATE_PACKAGES['dbgate-tools'];
|
||||||
|
|
||||||
let authProxy;
|
let authProxy;
|
||||||
@@ -60,7 +61,23 @@ function extractPostgresColumns(result, dbhan) {
|
|||||||
columnName: fld.name,
|
columnName: fld.name,
|
||||||
dataTypeId: fld.dataTypeID,
|
dataTypeId: fld.dataTypeID,
|
||||||
dataTypeName: typeIdToName[fld.dataTypeID],
|
dataTypeName: typeIdToName[fld.dataTypeID],
|
||||||
|
tableId: fld.tableID,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// const conflictingNames = getConflictingColumnNames(res);
|
||||||
|
// if (conflictingNames.size > 0) {
|
||||||
|
// const requiredTableIds = res.filter(x => conflictingNames.has(x.columnName)).map(x => x.tableId);
|
||||||
|
// const tableIdResult = await dbhan.client.query(
|
||||||
|
// `SELECT DISTINCT c.oid AS table_id, c.relname AS table_name
|
||||||
|
// FROM pg_class c
|
||||||
|
// WHERE c.oid IN (${requiredTableIds.join(',')})`
|
||||||
|
// );
|
||||||
|
// const tableIdToTableName = _.fromPairs(tableIdResult.rows.map(cur => [cur.table_id, cur.table_name]));
|
||||||
|
// for (const col of res) {
|
||||||
|
// col.pureName = tableIdToTableName[col.tableId];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
makeUniqueColumnNames(res);
|
makeUniqueColumnNames(res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,9 +85,14 @@ on:
|
|||||||
# branches:
|
# branches:
|
||||||
# - production
|
# - production
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
environment: dbgate-app
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -145,33 +150,71 @@ jobs:
|
|||||||
_if: _community
|
_if: _community
|
||||||
if: matrix.os == 'ubuntu-22.04'
|
if: matrix.os == 'ubuntu-22.04'
|
||||||
uses: samuelmeuli/action-snapcraft@v1
|
uses: samuelmeuli/action-snapcraft@v1
|
||||||
- name: Publish
|
|
||||||
|
- name: Publish Windows
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
run: |
|
||||||
|
<<cd_merged>>
|
||||||
|
yarn run build:app
|
||||||
|
# env:
|
||||||
|
# GH_TOKEN: ${{ secrets.GH_TOKEN }} # token for electron publish
|
||||||
|
|
||||||
|
- name: Publish MacOS
|
||||||
|
if: matrix.os == 'macos-14'
|
||||||
run: |
|
run: |
|
||||||
<<cd_merged>>
|
<<cd_merged>>
|
||||||
yarn run build:app
|
yarn run build:app
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN }} # token for electron publish
|
# GH_TOKEN: ${{ secrets.GH_TOKEN }} # token for electron publish
|
||||||
|
|
||||||
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
|
|
||||||
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
|
|
||||||
# WIN_CSC_LINK: ${{ secrets.WINCERT_CERTIFICATE }}
|
|
||||||
# WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_PASSWORD }}
|
|
||||||
|
|
||||||
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
||||||
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
||||||
|
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||||
|
|
||||||
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
|
||||||
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
||||||
|
|
||||||
|
- name: Publish Linux
|
||||||
|
if: matrix.os == 'ubuntu-22.04'
|
||||||
|
run: |
|
||||||
|
<<cd_merged>>
|
||||||
|
yarn run build:app
|
||||||
|
env:
|
||||||
|
# GH_TOKEN: ${{ secrets.GH_TOKEN }} # token for electron publish
|
||||||
|
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
||||||
|
|
||||||
- name: generatePadFile
|
- name: generatePadFile
|
||||||
_if: _community_stable
|
_if: _community_stable
|
||||||
run: |
|
run: |
|
||||||
yarn generatePadFile
|
yarn generatePadFile
|
||||||
|
|
||||||
|
- name: Azure login (OIDC)
|
||||||
|
uses: azure/login@v2
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
with:
|
||||||
|
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
|
||||||
|
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
|
||||||
|
allow-no-subscriptions: true
|
||||||
|
|
||||||
|
- name: Sign Windows artifacts with Azure Trusted Signing
|
||||||
|
uses: azure/trusted-signing-action@v0
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
with:
|
||||||
|
endpoint: https://wus3.codesigning.azure.net/
|
||||||
|
trusted-signing-account-name: DbGate
|
||||||
|
certificate-profile-name: DbGate-Release
|
||||||
|
|
||||||
|
files-folder: <<artifact-root>>
|
||||||
|
files-folder-filter: exe
|
||||||
|
|
||||||
|
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||||
|
timestamp-digest: SHA256
|
||||||
|
|
||||||
|
- name: Fix YML hashes
|
||||||
|
if: matrix.os == 'windows-2022'
|
||||||
|
run: |
|
||||||
|
<<cd_merged>>
|
||||||
|
yarn run fixYmlHashes
|
||||||
|
|
||||||
- name: Copy artifacts
|
- name: Copy artifacts
|
||||||
run: |
|
run: |
|
||||||
mkdir artifacts
|
mkdir artifacts
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ on:
|
|||||||
- 'v[0-9]+.[0-9]+.[0-9]+'
|
- 'v[0-9]+.[0-9]+.[0-9]+'
|
||||||
- 'v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+'
|
- 'v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: write
|
||||||
|
|
||||||
# on:
|
# on:
|
||||||
# push:
|
# push:
|
||||||
# branches:
|
# branches:
|
||||||
@@ -43,13 +47,17 @@ jobs:
|
|||||||
cd dbgate-merged
|
cd dbgate-merged
|
||||||
node adjustNpmPackageJsonPremium
|
node adjustNpmPackageJsonPremium
|
||||||
|
|
||||||
- name: Configure NPM token
|
# - name: Configure NPM token
|
||||||
env:
|
# env:
|
||||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
# NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
run: |
|
# run: |
|
||||||
cd ..
|
# cd ..
|
||||||
cd dbgate-merged
|
# cd dbgate-merged
|
||||||
npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
|
# npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
|
||||||
|
|
||||||
|
# Ensure npm 11.5.1 or later is installed
|
||||||
|
- name: Update npm
|
||||||
|
run: npm install -g npm@latest
|
||||||
|
|
||||||
- name: Remove dbmodel - should be not published
|
- name: Remove dbmodel - should be not published
|
||||||
run: |
|
run: |
|
||||||
@@ -69,33 +77,40 @@ jobs:
|
|||||||
cd dbgate-merged
|
cd dbgate-merged
|
||||||
yarn setCurrentVersion
|
yarn setCurrentVersion
|
||||||
|
|
||||||
|
- name: Compute npm dist-tag
|
||||||
|
run: |
|
||||||
|
if [[ "${GITHUB_REF_NAME}" =~ -alpha\. ]]; then
|
||||||
|
echo "NPM_TAG=alpha" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "NPM_TAG=latest" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Publish dbgate-api-premium
|
- name: Publish dbgate-api-premium
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
cd dbgate-merged/packages/api
|
cd dbgate-merged/packages/api
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-web-premium
|
- name: Publish dbgate-web-premium
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
cd dbgate-merged/packages/web
|
cd dbgate-merged/packages/web
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-serve-premium
|
- name: Publish dbgate-serve-premium
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
cd dbgate-merged/packages/serve
|
cd dbgate-merged/packages/serve
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-plugin-cosmosdb
|
- name: Publish dbgate-plugin-cosmosdb
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
cd dbgate-merged/plugins/dbgate-plugin-cosmosdb
|
cd dbgate-merged/plugins/dbgate-plugin-cosmosdb
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-plugin-firestore
|
- name: Publish dbgate-plugin-firestore
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
cd dbgate-merged/plugins/dbgate-plugin-firestore
|
cd dbgate-merged/plugins/dbgate-plugin-firestore
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ on:
|
|||||||
- 'v[0-9]+.[0-9]+.[0-9]+'
|
- 'v[0-9]+.[0-9]+.[0-9]+'
|
||||||
- 'v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+'
|
- 'v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: write
|
||||||
|
|
||||||
# on:
|
# on:
|
||||||
# push:
|
# push:
|
||||||
# branches:
|
# branches:
|
||||||
@@ -35,11 +39,15 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: 22.x
|
node-version: 22.x
|
||||||
|
|
||||||
- name: Configure NPM token
|
# Ensure npm 11.5.1 or later is installed
|
||||||
env:
|
- name: Update npm
|
||||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
run: npm install -g npm@latest
|
||||||
run: |
|
|
||||||
npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
|
# - name: Configure NPM token
|
||||||
|
# env:
|
||||||
|
# NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
# run: |
|
||||||
|
# npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
|
||||||
|
|
||||||
- name: yarn install
|
- name: yarn install
|
||||||
run: |
|
run: |
|
||||||
@@ -49,112 +57,120 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
yarn setCurrentVersion
|
yarn setCurrentVersion
|
||||||
|
|
||||||
|
- name: Compute npm dist-tag
|
||||||
|
run: |
|
||||||
|
if [[ "${GITHUB_REF_NAME}" =~ -alpha\. ]]; then
|
||||||
|
echo "NPM_TAG=alpha" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "NPM_TAG=latest" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Publish types
|
- name: Publish types
|
||||||
working-directory: packages/types
|
working-directory: packages/types
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish tools
|
- name: Publish tools
|
||||||
working-directory: packages/tools
|
working-directory: packages/tools
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish sqltree
|
- name: Publish sqltree
|
||||||
working-directory: packages/sqltree
|
working-directory: packages/sqltree
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish api
|
- name: Publish api
|
||||||
working-directory: packages/api
|
working-directory: packages/api
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish datalib
|
- name: Publish datalib
|
||||||
working-directory: packages/datalib
|
working-directory: packages/datalib
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish filterparser
|
- name: Publish filterparser
|
||||||
working-directory: packages/filterparser
|
working-directory: packages/filterparser
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish web
|
- name: Publish web
|
||||||
working-directory: packages/web
|
working-directory: packages/web
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-serve
|
- name: Publish dbgate-serve
|
||||||
working-directory: packages/serve
|
working-directory: packages/serve
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbmodel
|
- name: Publish dbmodel
|
||||||
working-directory: packages/dbmodel
|
working-directory: packages/dbmodel
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-plugin-csv
|
- name: Publish dbgate-plugin-csv
|
||||||
working-directory: plugins/dbgate-plugin-csv
|
working-directory: plugins/dbgate-plugin-csv
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-plugin-xml
|
- name: Publish dbgate-plugin-xml
|
||||||
working-directory: plugins/dbgate-plugin-xml
|
working-directory: plugins/dbgate-plugin-xml
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-plugin-excel
|
- name: Publish dbgate-plugin-excel
|
||||||
working-directory: plugins/dbgate-plugin-excel
|
working-directory: plugins/dbgate-plugin-excel
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-plugin-mssql
|
- name: Publish dbgate-plugin-mssql
|
||||||
working-directory: plugins/dbgate-plugin-mssql
|
working-directory: plugins/dbgate-plugin-mssql
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-plugin-mysql
|
- name: Publish dbgate-plugin-mysql
|
||||||
working-directory: plugins/dbgate-plugin-mysql
|
working-directory: plugins/dbgate-plugin-mysql
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-plugin-mongo
|
- name: Publish dbgate-plugin-mongo
|
||||||
working-directory: plugins/dbgate-plugin-mongo
|
working-directory: plugins/dbgate-plugin-mongo
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-plugin-postgres
|
- name: Publish dbgate-plugin-postgres
|
||||||
working-directory: plugins/dbgate-plugin-postgres
|
working-directory: plugins/dbgate-plugin-postgres
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-plugin-sqlite
|
- name: Publish dbgate-plugin-sqlite
|
||||||
working-directory: plugins/dbgate-plugin-sqlite
|
working-directory: plugins/dbgate-plugin-sqlite
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-plugin-redis
|
- name: Publish dbgate-plugin-redis
|
||||||
working-directory: plugins/dbgate-plugin-redis
|
working-directory: plugins/dbgate-plugin-redis
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-plugin-oracle
|
- name: Publish dbgate-plugin-oracle
|
||||||
working-directory: plugins/dbgate-plugin-oracle
|
working-directory: plugins/dbgate-plugin-oracle
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-plugin-clickhouse
|
- name: Publish dbgate-plugin-clickhouse
|
||||||
working-directory: plugins/dbgate-plugin-clickhouse
|
working-directory: plugins/dbgate-plugin-clickhouse
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-plugin-dbf
|
- name: Publish dbgate-plugin-dbf
|
||||||
working-directory: plugins/dbgate-plugin-dbf
|
working-directory: plugins/dbgate-plugin-dbf
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|
||||||
- name: Publish dbgate-plugin-cassandra
|
- name: Publish dbgate-plugin-cassandra
|
||||||
working-directory: plugins/dbgate-plugin-cassandra
|
working-directory: plugins/dbgate-plugin-cassandra
|
||||||
run: |
|
run: |
|
||||||
npm publish
|
npm publish --tag "$NPM_TAG"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ checkout-and-merge-pro:
|
|||||||
repository: dbgate/dbgate-pro
|
repository: dbgate/dbgate-pro
|
||||||
token: ${{ secrets.GH_TOKEN }}
|
token: ${{ secrets.GH_TOKEN }}
|
||||||
path: dbgate-pro
|
path: dbgate-pro
|
||||||
ref: 11203754aad94189b565c2816d37760b15c8e07f
|
ref: 6195e103e1d45e4f59bade60df5dd1784f4e6c77
|
||||||
- name: Merge dbgate/dbgate-pro
|
- name: Merge dbgate/dbgate-pro
|
||||||
run: |
|
run: |
|
||||||
mkdir ../dbgate-pro
|
mkdir ../dbgate-pro
|
||||||
|
|||||||
Reference in New Issue
Block a user