Compare commits

...

138 Commits

Author SHA1 Message Date
Nybkox 029f24b079 feat: update dbgate-query-splitter tp 4.11.3 2025-01-07 09:20:59 +01:00
Nybkox 9f4b55ce07 feat: sqlite triggers tests 2025-01-02 11:47:07 +01:00
Nybkox 01b7c42851 fix: prevent testing empty parameters 2025-01-02 11:41:00 +01:00
Nybkox f0221f6e43 feat: sqlite triggers 2025-01-02 11:26:40 +01:00
Nybkox 30bbdb0f1d refactor: move sqlite queries to sql directory 2025-01-02 11:26:40 +01:00
Nybkox a6f0bc78d4 fix: always show pin icon on the right 2025-01-02 10:59:22 +01:00
Jan Prochazka ceb6a88964 Merge branch 'feature/workflow-refactor' 2024-12-30 15:25:39 +01:00
Jan Prochazka a39fff8b3a ssh tunnel test disabled 2024-12-30 15:25:23 +01:00
Jan Prochazka 0cf3d5993c generated header 2024-12-30 08:28:25 +01:00
Jan Prochazka 2966484cda v6.1.3-beta.1 2024-12-30 08:23:36 +01:00
Jan Prochazka ac3bb58106 generated workflows 2024-12-30 08:23:18 +01:00
Jan Prochazka 36e2f1bdee workflow templates 2024-12-30 08:11:18 +01:00
Jan Prochazka 70083bd870 workflows - defs support 2024-12-30 07:05:25 +01:00
Jan Prochazka f7b39fca26 code cleanup 2024-12-29 09:57:33 +01:00
Jan Prochazka 70873e83bd docker pipeline refactor 2024-12-29 09:57:18 +01:00
Jan Prochazka 2858bba8b2 yaml replace changed 2024-12-28 21:16:52 +01:00
Jan Prochazka bd0404fbaf fixes 2024-12-28 15:36:05 +01:00
Jan Prochazka 317f6256f6 fix 2024-12-28 15:28:34 +01:00
Jan Prochazka 6c9b738717 fix 2024-12-28 15:10:45 +01:00
Jan Prochazka 2f8c584af5 workflows 2024-12-28 15:03:38 +01:00
Jan Prochazka d3b417679e workflow processor 2024-12-28 15:00:59 +01:00
Jan Prochazka 00dd8bfc72 fixed links to dbgate.org 2024-12-28 14:01:19 +01:00
Jan Prochazka e1eea4adf3 fixed links to dbgate.org 2024-12-28 11:30:18 +01:00
Jan Prochazka fd2d2e90d4 workflow refactor WIP 2024-12-27 08:34:17 +01:00
Jan Prochazka f97b70ce45 v6.1.2 2024-12-26 08:05:17 +01:00
Jan Prochazka 45d79478fb workflow fixes 2024-12-26 08:05:03 +01:00
Jan Prochazka a59f42bd62 v6.1.2-premium-beta.18 2024-12-26 07:47:14 +01:00
Jan Prochazka a189fa7b6d fix 2024-12-26 07:46:58 +01:00
Jan Prochazka 794bc97207 v6.1.2-beta.17 2024-12-26 07:45:27 +01:00
Jan Prochazka 24f7def7ab v6.1.2-premium-beta.16 2024-12-26 07:45:16 +01:00
Jan Prochazka 01071c236e notarization log 2024-12-26 07:44:53 +01:00
Jan Prochazka a6326ac9fa v6.1.2-premium-beta.15 2024-12-26 07:37:36 +01:00
Jan Prochazka 4c6d409be8 print notarization log 2024-12-26 07:37:19 +01:00
Jan Prochazka 44ad8e51a5 v6.1.2-premium-beta.14 2024-12-26 07:18:26 +01:00
Jan Prochazka e82578adfb v6.1.2-beta.14 2024-12-26 07:17:52 +01:00
Jan Prochazka 24f28b559e pro app build 2024-12-26 07:17:24 +01:00
Jan Prochazka b086a5d3d2 prevent double upload snap 2024-12-25 21:32:17 +01:00
Jan Prochazka bb0b87b770 v6.1.2-beta.13 2024-12-25 20:20:26 +01:00
Jan Prochazka aa4f82fa98 fix 2024-12-25 20:20:10 +01:00
Jan Prochazka 873ace4170 v6.1.2-beta.12 2024-12-25 19:51:24 +01:00
Jan Prochazka 5a9d8ba0a7 fix 2024-12-25 19:51:16 +01:00
Jan Prochazka 07f0fdcc1c v6.1.2-beta.11 2024-12-25 19:43:27 +01:00
Jan Prochazka ff7ee4fb98 fix 2024-12-25 19:43:16 +01:00
Jan Prochazka b1f5b62757 v6.1.2-beta.10 2024-12-25 19:39:37 +01:00
Jan Prochazka a67c857204 python 3.11 fix 2024-12-25 19:39:26 +01:00
Jan Prochazka 4032c53a30 v6.1.2-beta.9 2024-12-25 12:19:09 +01:00
Jan Prochazka 0a37ed74d9 electron reverted to version 30 2024-12-25 12:18:58 +01:00
Jan Prochazka f07efe440a v6.1.2-beta.8 2024-12-25 12:09:35 +01:00
Jan Prochazka 2d5e67802d removed mongodb-client-encryption from community build 2024-12-25 12:09:25 +01:00
Jan Prochazka 7b8e013084 v6.1.2-beta.7 2024-12-25 11:29:42 +01:00
Jan Prochazka b69fc04b5c try to upgrade electron 2024-12-25 11:29:23 +01:00
Jan Prochazka b6dfdd4741 v6.1.2-beta.6 2024-12-25 11:14:10 +01:00
Jan Prochazka ff3985a542 upgraded mongodb-client-encryption 2024-12-25 11:13:54 +01:00
Jan Prochazka 9c7e1dcaf1 v6.1.2-beta.5 2024-12-25 10:44:39 +01:00
Jan Prochazka 48eb09687c app build - node version 22 2024-12-25 10:44:02 +01:00
Jan Prochazka 86b339535d updated electron builder 2024-12-25 10:42:49 +01:00
Jan Prochazka 576b6dc774 v6.1.2-beta.4 2024-12-25 10:28:26 +01:00
Jan Prochazka 18ca971f67 try to use electron notarize 2024-12-25 10:28:10 +01:00
Jan Prochazka 3916a5e6e8 fixed ssh tunnel connection test #972 #973 2024-12-25 09:49:23 +01:00
Jan Prochazka 1446fdad5e v6.1.2-beta.3 2024-12-23 09:52:31 +01:00
Jan Prochazka 1478886e04 fix 2024-12-23 09:52:22 +01:00
Jan Prochazka 54d61790a9 v6.1.2-beta.2 2024-12-23 09:27:28 +01:00
Jan Prochazka bb638fd8db fix 2024-12-23 09:27:14 +01:00
Jan Prochazka e3a2589517 v6.1.2-beta.1 2024-12-23 09:21:42 +01:00
Jan Prochazka 6f557a6463 print notarization error 2024-12-23 09:21:31 +01:00
Jan Prochazka 323f27f6e4 changelog 2024-12-23 07:06:36 +01:00
Jan Prochazka 8d4a38dccb v6.1.1 2024-12-23 07:06:12 +01:00
SPRINX0\prochazka 54a3b30e83 Merge branch 'master' of https://github.com/dbgate/dbgate 2024-12-20 13:45:41 +01:00
SPRINX0\prochazka 6251bcd8fd changelog 2024-12-20 13:45:39 +01:00
SPRINX0\prochazka e42099c1a9 v6.1.1-beta.1 2024-12-20 12:57:25 +01:00
Jan Prochazka b07ee91cf9 fixed oracle export + clickhouse test 2024-12-20 12:23:29 +01:00
Jan Prochazka 62c028fc3c export test finished 2024-12-20 11:33:28 +01:00
SPRINX0\prochazka 07ea575b0f fixed postgres export + export tests #970 2024-12-20 11:17:43 +01:00
SPRINX0\prochazka ee78786974 #968 mysql table comment fix 2024-12-20 10:47:14 +01:00
SPRINX0\prochazka e1814663cd trigger fulltext search 2024-12-20 10:40:57 +01:00
SPRINX0\prochazka 6ae3e019ff ux 2024-12-20 10:38:29 +01:00
Jan Prochazka cadf539c3d fixed diff for triggers 2024-12-20 10:30:05 +01:00
Jan Prochazka 51929d7ef7 some tests fixed 2024-12-20 10:23:49 +01:00
Jan Prochazka 0edc7f077f test trigger createSql 2024-12-20 09:26:53 +01:00
SPRINX0\prochazka 2488cee7ea test definition refactor 2024-12-20 09:03:30 +01:00
SPRINX0\prochazka edf64db69a search settings improvement 2024-12-20 08:42:30 +01:00
SPRINX0\prochazka c65bf51dcd Merge branch 'feature/parameters-oracle' 2024-12-20 07:46:51 +01:00
Nybkox effe235a95 feat: oracle parameters 2024-12-19 16:06:56 +01:00
Nybkox 583d1494c2 feat: fallback to position if param does not have name 2024-12-19 12:50:50 +01:00
Nybkox 983daf0d1c feat: add options position to params typing 2024-12-19 12:09:25 +01:00
Jan Prochazka 756ddf1a8b Merge pull request #969 from dbgate/feature/triggers
Feature/triggers
2024-12-19 12:09:08 +01:00
Nybkox 9ccd647d97 fix: update triggers typing to cover all oracle timing options 2024-12-19 11:55:22 +01:00
Nybkox dc9bfdc553 fix: update pssql triggers query to match ts def 2024-12-19 10:50:39 +01:00
Nybkox af4e91faba fix: update oracle triggers test create queries 2024-12-19 10:46:40 +01:00
Nybkox 394020157b fix: update oracle triggers tests expected values 2024-12-19 10:26:48 +01:00
Nybkox f16aab12e1 fix: add trigger event type to oracle triggers query 2024-12-19 10:17:16 +01:00
Nybkox e08216d6dd feat: mssql triggers tests 2024-12-19 10:13:15 +01:00
Nybkox ebb4f8e73e fix: mssql triggers query naming 2024-12-19 10:13:04 +01:00
Nybkox b9939e5d5f fix: correctly map mysql triggers sql output 2024-12-19 09:58:54 +01:00
Nybkox 9eb3bca8d6 feat: add other create/drop for triggers tests 2024-12-19 09:54:17 +01:00
Nybkox 022f263bf9 fix: update pssql triggers test sql 2024-12-19 09:53:47 +01:00
Nybkox 56972652d5 fix: pssql triggers - map tgtype to timing / event type correctly 2024-12-19 09:53:11 +01:00
SPRINX0\prochazka d75b9e2688 ace-builds patch #954 2024-12-19 09:21:57 +01:00
Nybkox d2c5440e39 feat: pssql tirgger test 2024-12-19 08:33:26 +01:00
Jan Prochazka 8ff30e426e fix - expand limited when accessing bykeyboard nav 2024-12-18 14:13:01 +01:00
Jan Prochazka 7cdbef609e arm-64 builds 2024-12-18 10:59:21 +01:00
Jan Prochazka f6195a468d v6.1.0 2024-12-18 10:37:54 +01:00
Jan Prochazka c23bf72d55 changelog 2024-12-18 10:35:54 +01:00
Jan Prochazka c02441402b fixed search in list 2024-12-18 10:22:02 +01:00
Jan Prochazka b9a8764b55 fixed search 2024-12-18 10:01:52 +01:00
Jan Prochazka a2374c1981 v6.0.1-beta.6 2024-12-18 09:39:57 +01:00
Jan Prochazka 9cfd5af704 prevent jump to first item when focusing because of mouse 2024-12-18 09:37:40 +01:00
Jan Prochazka a6f473b8ed better connection UX 2024-12-18 09:08:42 +01:00
Jan Prochazka e0a74402cb dropdown for default database 2024-12-18 08:43:51 +01:00
Jan Prochazka c6e57b278e use default database 2024-12-18 08:18:09 +01:00
Jan Prochazka e63f1f8f09 clickAction refactor, settings - open detail after keyboard navigation 2024-12-18 08:08:45 +01:00
Nybkox e866c019f0 feat: mysql and oracle triggers tests 2024-12-18 06:09:30 +01:00
Nybkox 5f4bd6d3e3 fix: triggers typing and yaml conv 2024-12-18 06:05:49 +01:00
SPRINX0\prochazka 57da9c9885 changelog wip 2024-12-17 17:17:31 +01:00
SPRINX0\prochazka e6a3acf4c2 search GUI improved 2024-12-17 16:27:54 +01:00
SPRINX0\prochazka 537869e862 data grid - no rows info 2024-12-17 16:03:21 +01:00
SPRINX0\prochazka ae2ff7b3b1 fixed display CLOB an NCLOB columns in Oracle #944 2024-12-17 15:31:10 +01:00
SPRINX0\prochazka 1db01dbdb1 optimalization 2024-12-17 14:59:44 +01:00
SPRINX0\prochazka 7988438dc7 fix search connections 2024-12-17 14:43:05 +01:00
SPRINX0\prochazka 3b32823f94 v6.0.1-beta.5 2024-12-17 14:29:56 +01:00
SPRINX0\prochazka 3370c754f2 try to fix postgres plugin 2024-12-17 14:29:45 +01:00
SPRINX0\prochazka 2d84e5a611 dataGrid align numbers right #957 2024-12-17 13:43:21 +01:00
SPRINX0\prochazka 8d5f73849e upgraded ace-builds #954 2024-12-17 12:42:09 +01:00
SPRINX0\prochazka 7a5019164a configurable search in connections 2024-12-17 12:26:50 +01:00
SPRINX0\prochazka f5733ea2d7 handle camelCase in tokenizer 2024-12-17 10:16:19 +01:00
Nybkox 413287c691 fix: remove triggerName 2024-12-17 10:16:07 +01:00
Nybkox 9e941dfce2 feat: add triggers to ui 2024-12-17 10:16:07 +01:00
Nybkox d32af771dc fix: add purename to trigger analysers 2024-12-17 10:16:07 +01:00
Nybkox 1c84f40bcf feat: add triggers loading message 2024-12-17 10:16:06 +01:00
Nybkox 671eba22e0 feat: add oracle triggers to analyser 2024-12-17 10:16:06 +01:00
Nybkox c00cb3076c feat: add mysql triggers to analyser 2024-12-17 10:16:06 +01:00
Nybkox 62daa13e54 feat: add mssql triggers to analyser 2024-12-17 10:16:06 +01:00
Nybkox 4cc0a66a7d feat: add pssql triggers to analyser 2024-12-17 10:16:06 +01:00
SPRINX0\prochazka 92e13220d8 tokenized search in references 2024-12-17 10:12:45 +01:00
SPRINX0\prochazka 2a5fdd852a search tokenizer optimalization 2024-12-17 10:09:52 +01:00
SPRINX0\prochazka 7759fd862f ability to disable tab preview mode 2024-12-17 09:34:16 +01:00
SPRINX0\prochazka ca5dd0ac30 v6.0.1-beta.4 2024-12-16 17:01:39 +01:00
SPRINX0\prochazka 18be29fd88 Merge branch 'feature/search' 2024-12-16 17:01:26 +01:00
104 changed files with 3903 additions and 2185 deletions
+51 -43
View File
@@ -1,83 +1,86 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Electron app BETA
on:
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+'
jobs:
build:
runs-on: ${{ matrix.os }}
runs-on: '${{ matrix.os }}'
strategy:
fail-fast: false
matrix:
os: [macos-14, windows-2022, ubuntu-22.04]
# os: [macOS-10.15]
os:
- macos-14
- windows-2022
- ubuntu-22.04
steps:
- name: Install python 3.11 (MacOS)
if: matrix.os == 'macos-14'
run: |
brew install python@3.11
echo "PYTHON=/opt/homebrew/bin/python3.11" >> $GITHUB_ENV
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
GITHUB_CONTEXT: '${{ toJson(github) }}'
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Use Node.js 18.x
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 18.x
- name: yarn adjustPackageJson
node-version: 22.x
- name: adjustPackageJson
run: |
yarn adjustPackageJson
node adjustPackageJson --community
- name: setUpdaterChannel beta
run: |
node setUpdaterChannel beta
- name: yarn set timeout
run: |
yarn config set network-timeout 100000
- name: yarn install
run: |
yarn install
- name: setCurrentVersion
run: |
yarn setCurrentVersion
- name: printSecrets
run: |
yarn printSecrets
yarn printSecrets
env:
GIST_UPLOAD_SECRET : ${{secrets.GIST_UPLOAD_SECRET}}
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
- name: fillPackagedPlugins
run: |
yarn fillPackagedPlugins
- name: Install Snapcraft
if: matrix.os == 'ubuntu-22.04'
uses: samuelmeuli/action-snapcraft@v1
- name: Publish
run: |
yarn run build:app
env:
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_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
- name: publishSnap
if: matrix.os == 'ubuntu-22.04'
run: |
snapcraft upload --release=beta app/dist/*.snap
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
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_KEY_PASSWORD: '${{ secrets.APPLECERT_PASSWORD }}'
APPLE_ID: '${{ secrets.APPLE_ID }}'
APPLE_TEAM_ID: '${{ secrets.APPLE_TEAM_ID }}'
APPLE_ID_PASSWORD: '${{ secrets.APPLE_ID_PASSWORD }}'
SNAPCRAFT_STORE_CREDENTIALS: '${{secrets.SNAPCRAFT_LOGIN}}'
APPLE_APP_SPECIFIC_PASSWORD: '${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}'
- name: Copy artifacts
run: |
mkdir artifacts
@@ -89,8 +92,10 @@ jobs:
cp app/dist/*win*.exe artifacts/dbgate-beta.exe || true
cp app/dist/*win_x64.zip artifacts/dbgate-windows-beta.zip || true
cp app/dist/*win_arm64.zip artifacts/dbgate-windows-beta-arm64.zip || true
cp app/dist/*-mac_x64.dmg artifacts/dbgate-beta.dmg || true
cp app/dist/*-mac_universal.dmg artifacts/dbgate-beta.dmg || true
cp app/dist/*-mac_x64.dmg artifacts/dbgate-beta-x64.dmg || true
cp app/dist/*-mac_arm64.dmg artifacts/dbgate-beta-arm64.dmg || true
mv app/dist/*.snap artifacts/dbgate-beta.snap || true
mv app/dist/*.exe artifacts/ || true
mv app/dist/*.zip artifacts/ || true
@@ -103,18 +108,21 @@ jobs:
mv app/dist/*.yml artifacts/ || true
rm artifacts/builder-debug.yml
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}
name: '${{ matrix.os }}'
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
if: 'startsWith(github.ref, ''refs/tags/'')'
with:
files: 'artifacts/**'
files: artifacts/**
prerelease: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
- name: Print content of notarization-error.log
if: failure() && matrix.os == 'macos-14'
run: |
find . -type f -name "notarization-error.log" -exec echo "=== Start of {} ===" \; -exec cat {} \; -exec echo "=== End of {} ===" \;
+62 -50
View File
@@ -1,43 +1,44 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Electron app PREMIUM BETA
on:
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+-premium-beta.[0-9]+'
jobs:
build:
runs-on: ${{ matrix.os }}
runs-on: '${{ matrix.os }}'
strategy:
fail-fast: false
matrix:
# os: [windows-2022]
# os: [ubuntu-22.04]
# os: [windows-2022, ubuntu-22.04]
os: [macos-14, windows-2022, ubuntu-22.04]
# os: [macOS-10.15]
os:
- macos-14
- windows-2022
- ubuntu-22.04
steps:
- name: Install python 3.11 (MacOS)
if: matrix.os == 'macos-14'
run: |
brew install python@3.11
echo "PYTHON=/opt/homebrew/bin/python3.11" >> $GITHUB_ENV
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
GITHUB_CONTEXT: '${{ toJson(github) }}'
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Use Node.js 18.x
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 18.x
node-version: 22.x
- name: Checkout dbgate/dbgate-pro
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
token: '${{ secrets.GH_TOKEN }}'
path: dbgate-pro
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
@@ -49,76 +50,82 @@ jobs:
yarn
node sync.js --nowatch
cd ..
- name: adjustPackageJson
run: |
cd ..
cd dbgate-merged
- name: yarn adjustPackageJson
run: |
cd ..
cd dbgate-merged
yarn adjustPackageJson
- name: adjustAppPackageJsonPremium
run: |
cd ..
cd dbgate-merged
node adjustAppPackageJsonPremium
node adjustPackageJson --premium
- name: setUpdaterChannel premium-beta
run: |
cd ..
cd dbgate-merged
node setUpdaterChannel premium-beta
- name: yarn set timeout
run: |
cd ..
cd dbgate-merged
yarn config set network-timeout 100000
- name: yarn install
run: |
cd ..
cd dbgate-merged
yarn install
- name: setCurrentVersion
run: |
cd ..
cd dbgate-merged
yarn setCurrentVersion
- name: printSecrets
run: |
cd ..
cd dbgate-merged
yarn printSecrets
yarn printSecrets
env:
GIST_UPLOAD_SECRET : ${{secrets.GIST_UPLOAD_SECRET}}
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
- name: fillPackagedPlugins
run: |
cd ..
cd dbgate-merged
yarn fillPackagedPlugins
- name: Publish
run: |
cd ..
cd dbgate-merged
yarn run build:app
env:
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_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
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_KEY_PASSWORD: '${{ secrets.APPLECERT_PASSWORD }}'
APPLE_ID: '${{ secrets.APPLE_ID }}'
APPLE_TEAM_ID: '${{ secrets.APPLE_TEAM_ID }}'
APPLE_ID_PASSWORD: '${{ secrets.APPLE_ID_PASSWORD }}'
SNAPCRAFT_STORE_CREDENTIALS: '${{secrets.SNAPCRAFT_LOGIN}}'
APPLE_APP_SPECIFIC_PASSWORD: '${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}'
- name: Copy artifacts
run: |
mkdir artifacts
cp ../dbgate-merged/app/dist/*.deb artifacts/dbgate-premium-beta.deb || true
cp ../dbgate-merged/app/dist/*x86*.AppImage artifacts/dbgate-premium-beta.AppImage || true
cp ../dbgate-merged/app/dist/*arm64*.AppImage artifacts/dbgate-premium-beta-arm64.AppImage || true
cp ../dbgate-merged/app/dist/*armv7l*.AppImage artifacts/dbgate-premium-beta-armv7l.AppImage || true
cp ../dbgate-merged/app/dist/*win*.exe artifacts/dbgate-premium-beta.exe || true
cp ../dbgate-merged/app/dist/*-mac_x64.dmg artifacts/dbgate-premium-beta.dmg || true
cp ../dbgate-merged/app/dist/*win_x64.zip artifacts/dbgate-windows-premium-beta.zip || true
cp ../dbgate-merged/app/dist/*win_arm64.zip artifacts/dbgate-windows-premium-beta-arm64.zip || true
cp ../dbgate-merged/app/dist/*-mac_universal.dmg artifacts/dbgate-premium-beta.dmg || true
cp ../dbgate-merged/app/dist/*-mac_x64.dmg artifacts/dbgate-premium-beta-x64.dmg || true
cp ../dbgate-merged/app/dist/*-mac_arm64.dmg artifacts/dbgate-premium-beta-arm64.dmg || true
mv ../dbgate-merged/app/dist/*.snap artifacts/dbgate-premium-beta.snap || true
mv ../dbgate-merged/app/dist/*.exe artifacts/ || true
mv ../dbgate-merged/app/dist/*.zip artifacts/ || true
@@ -131,18 +138,23 @@ jobs:
mv ../dbgate-merged/app/dist/*.yml artifacts/ || true
rm artifacts/builder-debug.yml
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}
name: '${{ matrix.os }}'
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
if: 'startsWith(github.ref, ''refs/tags/'')'
with:
files: 'artifacts/**'
files: artifacts/**
prerelease: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
- name: Print content of notarization-error.log
if: failure() && matrix.os == 'macos-14'
run: |
cd ..
cd dbgate-merged
find . -type f -name "notarization-error.log" -exec echo "=== Start of {} ===" \; -exec cat {} \; -exec echo "=== End of {} ===" \;
+62 -52
View File
@@ -1,44 +1,44 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Electron app PREMIUM
on:
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
# - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
# branches:
# - production
jobs:
build:
runs-on: ${{ matrix.os }}
runs-on: '${{ matrix.os }}'
strategy:
fail-fast: false
matrix:
# os: [ubuntu-22.04, windows-2016]
os: [macos-14, windows-2022, ubuntu-22.04]
os:
- macos-14
- windows-2022
- ubuntu-22.04
steps:
- name: Install python 3.11 (MacOS)
if: matrix.os == 'macos-14'
run: |
brew install python@3.11
echo "PYTHON=/opt/homebrew/bin/python3.11" >> $GITHUB_ENV
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
GITHUB_CONTEXT: '${{ toJson(github) }}'
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Use Node.js 18.x
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 18.x
node-version: 22.x
- name: Checkout dbgate/dbgate-pro
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
token: '${{ secrets.GH_TOKEN }}'
path: dbgate-pro
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
@@ -50,101 +50,111 @@ jobs:
yarn
node sync.js --nowatch
cd ..
- name: adjustPackageJson
run: |
cd ..
cd dbgate-merged
- name: yarn adjustPackageJson
run: |
cd ..
cd dbgate-merged
yarn adjustPackageJson
- name: adjustAppPackageJsonPremium
run: |
cd ..
cd dbgate-merged
node adjustAppPackageJsonPremium
node adjustPackageJson --premium
- name: setUpdaterChannel premium
run: |
cd ..
cd dbgate-merged
node setUpdaterChannel premium
- name: yarn set timeout
run: |
cd ..
cd dbgate-merged
yarn config set network-timeout 100000
- name: yarn install
run: |
cd ..
cd dbgate-merged
yarn install
- name: setCurrentVersion
run: |
cd ..
cd dbgate-merged
yarn setCurrentVersion
- name: printSecrets
run: |
cd ..
cd dbgate-merged
yarn printSecrets
env:
GIST_UPLOAD_SECRET : ${{secrets.GIST_UPLOAD_SECRET}}
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
- name: fillPackagedPlugins
run: |
cd ..
cd dbgate-merged
yarn fillPackagedPlugins
- name: Publish
run: |
cd ..
cd dbgate-merged
yarn run build:app
env:
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_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
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_KEY_PASSWORD: '${{ secrets.APPLECERT_PASSWORD }}'
APPLE_ID: '${{ secrets.APPLE_ID }}'
APPLE_TEAM_ID: '${{ secrets.APPLE_TEAM_ID }}'
APPLE_ID_PASSWORD: '${{ secrets.APPLE_ID_PASSWORD }}'
SNAPCRAFT_STORE_CREDENTIALS: '${{secrets.SNAPCRAFT_LOGIN}}'
APPLE_APP_SPECIFIC_PASSWORD: '${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}'
- name: Copy artifacts
run: |
mkdir artifacts
cp ../dbgate-merged/app/dist/*.deb artifacts/dbgate-premium-latest.deb || true
cp ../dbgate-merged/app/dist/*x86*.AppImage artifacts/dbgate-premium-latest.AppImage || true
cp ../dbgate-merged/app/dist/*.exe artifacts/dbgate-premium-latest.exe || true
cp ../dbgate-merged/app/dist/*win_x64.zip artifacts/dbgate-premium-windows-latest.zip || true
cp ../dbgate-merged/app/dist/*win_arm64.zip artifacts/dbgate-premium-windows-latest-arm64.zip || true
cp ../dbgate-merged/app/dist/*arm64*.AppImage artifacts/dbgate-premium-latest-arm64.AppImage || true
cp ../dbgate-merged/app/dist/*armv7l*.AppImage artifacts/dbgate-premium-latest-armv7l.AppImage || true
cp ../dbgate-merged/app/dist/*win*.exe artifacts/dbgate-premium-latest.exe || true
cp ../dbgate-merged/app/dist/*win_x64.zip artifacts/dbgate-windows-premium-latest.zip || true
cp ../dbgate-merged/app/dist/*win_arm64.zip artifacts/dbgate-windows-premium-latest-arm64.zip || true
cp ../dbgate-merged/app/dist/*-mac_universal.dmg artifacts/dbgate-premium-latest.dmg || true
cp ../dbgate-merged/app/dist/*-mac_x64.dmg artifacts/dbgate-premium-latest-x64.dmg || true
cp ../dbgate-merged/app/dist/*-mac_arm64.dmg artifacts/dbgate-premium-latest-arm64.dmg || true
mv ../dbgate-merged/app/dist/*.snap artifacts/dbgate-premium-latest.snap || true
mv ../dbgate-merged/app/dist/*.exe artifacts/ || true
mv ../dbgate-merged/app/dist/*.zip artifacts/ || true
mv ../dbgate-merged/app/dist/*.tar.gz artifacts/ || true
mv ../dbgate-merged/app/dist/*.AppImage artifacts/ || true
mv ../dbgate-merged/app/dist/*.deb artifacts/ || true
mv ../dbgate-merged/app/dist/*.snap artifacts/ || true
mv ../dbgate-merged/app/dist/*.dmg artifacts/ || true
mv ../dbgate-merged/app/dist/*.blockmap artifacts/ || true
mv ../dbgate-merged/app/dist/*.yml artifacts/ || true
rm artifacts/builder-debug.yml
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}
name: '${{ matrix.os }}'
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
if: 'startsWith(github.ref, ''refs/tags/'')'
with:
files: 'artifacts/**'
files: artifacts/**
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
- name: Print content of notarization-error.log
if: failure() && matrix.os == 'macos-14'
run: |
cd ..
cd dbgate-merged
find . -type f -name "notarization-error.log" -exec echo "=== Start of {} ===" \; -exec cat {} \; -exec echo "=== End of {} ===" \;
+51 -86
View File
@@ -1,90 +1,85 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Electron app
on:
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
# - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
# branches:
# - production
jobs:
build:
runs-on: ${{ matrix.os }}
runs-on: '${{ matrix.os }}'
strategy:
fail-fast: false
matrix:
# os: [ubuntu-22.04, windows-2016]
os: [macos-14, windows-2022, ubuntu-22.04]
os:
- macos-14
- windows-2022
- ubuntu-22.04
steps:
- name: Install python 3.11 (MacOS)
if: matrix.os == 'macos-14'
run: |
brew install python@3.11
echo "PYTHON=/opt/homebrew/bin/python3.11" >> $GITHUB_ENV
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
GITHUB_CONTEXT: '${{ toJson(github) }}'
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Use Node.js 18.x
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 18.x
- name: yarn adjustPackageJson
node-version: 22.x
- name: adjustPackageJson
run: |
yarn adjustPackageJson
node adjustPackageJson --community
- name: yarn set timeout
run: |
yarn config set network-timeout 100000
- name: yarn install
run: |
# yarn --version
# yarn config set network-timeout 300000
yarn install
- name: setCurrentVersion
run: |
yarn setCurrentVersion
- name: printSecrets
run: |
yarn printSecrets
yarn printSecrets
env:
GIST_UPLOAD_SECRET : ${{secrets.GIST_UPLOAD_SECRET}}
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
- name: fillPackagedPlugins
run: |
yarn fillPackagedPlugins
- name: Install Snapcraft
if: matrix.os == 'ubuntu-22.04'
uses: samuelmeuli/action-snapcraft@v1
- name: Publish
run: |
yarn run build:app
env:
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_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
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_KEY_PASSWORD: '${{ secrets.APPLECERT_PASSWORD }}'
APPLE_ID: '${{ secrets.APPLE_ID }}'
APPLE_TEAM_ID: '${{ secrets.APPLE_TEAM_ID }}'
APPLE_ID_PASSWORD: '${{ secrets.APPLE_ID_PASSWORD }}'
SNAPCRAFT_STORE_CREDENTIALS: '${{secrets.SNAPCRAFT_LOGIN}}'
APPLE_APP_SPECIFIC_PASSWORD: '${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}'
- name: generatePadFile
run: |
yarn generatePadFile
- name: publishSnap
if: matrix.os == 'ubuntu-22.04'
run: |
snapcraft upload --release=stable app/dist/*.snap
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
- name: Copy artifacts
run: |
mkdir artifacts
@@ -93,74 +88,44 @@ jobs:
cp app/dist/*x86*.AppImage artifacts/dbgate-latest.AppImage || true
cp app/dist/*arm64*.AppImage artifacts/dbgate-latest-arm64.AppImage || true
cp app/dist/*armv7l*.AppImage artifacts/dbgate-latest-armv7l.AppImage || true
cp app/dist/*.exe artifacts/dbgate-latest.exe || true
cp app/dist/*win*.exe artifacts/dbgate-latest.exe || true
cp app/dist/*win_x64.zip artifacts/dbgate-windows-latest.zip || true
cp app/dist/*win_arm64.zip artifacts/dbgate-windows-latest-arm64.zip || true
cp app/dist/*-mac_universal.dmg artifacts/dbgate-latest.dmg || true
cp app/dist/*-mac_x64.dmg artifacts/dbgate-latest-x64.dmg || true
cp app/dist/*-mac_arm64.dmg artifacts/dbgate-latest-arm64.dmg || true
mv app/dist/*.snap artifacts/dbgate-latest.snap || true
mv app/dist/*.exe artifacts/ || true
mv app/dist/*.zip artifacts/ || true
mv app/dist/*.tar.gz artifacts/ || true
mv app/dist/*.AppImage artifacts/ || true
mv app/dist/*.deb artifacts/ || true
mv app/dist/*.snap artifacts/ || true
mv app/dist/*.dmg artifacts/ || true
mv app/dist/*.snap artifacts/dbgate-latest.snap || true
mv app/dist/*.blockmap artifacts/ || true
mv app/dist/*.yml artifacts/ || true
rm artifacts/builder-debug.yml
# - name: Copy artifacts Linux, MacOs
# if: matrix.os != 'windows-2016'
# run: |
# mkdir artifacts
# cp app/dist/*.AppImage artifacts/ || true
# cp app/dist/*.dmg artifacts/ || true
# cp app/dist/*.deb artifacts/ || true
# mv app/dist/*.deb artifacts/dbgate-linux.deb || true
# mv app/dist/*.AppImage artifacts/dbgate-linux.AppImage || true
# mv app/dist/*.dmg artifacts/dbgate-mac.dmg || true
# - name: Copy artifacts Win
# if: matrix.os == 'windows-2016'
# run: |
# mkdir artifacts
# cp app/dist/*.exe artifacts/ || true
# mv app/dist/*.exe artifacts/dbgate-windows.exe
# mv app/dist/latest.yml artifacts/latest.yml || true
- name: Copy PAD file
if: matrix.os == 'windows-2022'
run: |
mv app/dist/dbgate-pad.xml artifacts/ || true
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}
name: '${{ matrix.os }}'
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
if: 'startsWith(github.ref, ''refs/tags/'')'
with:
files: 'artifacts/**'
files: artifacts/**
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
- name: Print content of notarization-error.log
if: failure() && matrix.os == 'macos-14'
run: |
# - name: Create Release
# id: create_release
# uses: actions/create-release@v1
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# with:
# tag_name: ${{ github.ref }}
# release_name: Release ${{ github.ref }}
# draft: false
# prerelease: false
find . -type f -name "notarization-error.log" -exec echo "=== Start of {} ===" \; -exec cat {} \; -exec echo "=== End of {} ===" \;
+25 -50
View File
@@ -1,47 +1,41 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: AWS image PREMIUM
on:
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
# - 'v[0-9]+.[0-9]+.[0-9]+-premium-beta.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-packer-beta.[0-9]+'
jobs:
build:
runs-on: ${{ matrix.os }}
runs-on: '${{ matrix.os }}'
strategy:
matrix:
os: [ubuntu-22.04]
os:
- ubuntu-22.04
steps:
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
GITHUB_CONTEXT: '${{ toJson(github) }}'
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Use Node.js 18.x
uses: actions/setup-node@v1
with:
node-version: 18.x
- name: Setup `packer`
uses: hashicorp/setup-packer@main
with:
version: latest
- name: Checkout dbgate/dbgate-pro
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
token: '${{ secrets.GH_TOKEN }}'
path: dbgate-pro
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
@@ -53,33 +47,28 @@ jobs:
yarn
node sync.js --nowatch
cd ..
- name: yarn adjustPackageJson
- name: adjustPackageJson
run: |
cd ..
cd dbgate-merged
yarn adjustPackageJson
node adjustPackageJson --premium
- name: yarn install
run: |
cd ..
cd dbgate-merged
yarn install
- name: setCurrentVersion
run: |
cd ..
cd dbgate-merged
yarn setCurrentVersion
- name: printSecrets
run: |
cd ..
cd dbgate-merged
yarn printSecrets
env:
GIST_UPLOAD_SECRET : ${{secrets.GIST_UPLOAD_SECRET}}
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
- name: Prepare packer build
run: |
cd ..
@@ -87,62 +76,48 @@ jobs:
yarn run prepare:packer
cd packer
zip -r cloud-build.zip build
- name: Copy artifacts
run: |
mkdir artifacts
cp ../dbgate-merged/packer/cloud-build.zip artifacts/cloud-build.zip || true
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}
name: '${{ matrix.os }}'
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
if: 'startsWith(github.ref, ''refs/tags/'')'
with:
files: 'artifacts/**'
files: artifacts/**
prerelease: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
- name: Run `packer init`
run: |
cd ../dbgate-merged/packer
packer init ./aws-ubuntu.pkr.hcl
env:
AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
AWS_DEFAULT_REGION: ${{secrets.AWS_DEFAULT_REGION}}
AWS_ACCESS_KEY_ID: '${{secrets.AWS_ACCESS_KEY_ID}}'
AWS_SECRET_ACCESS_KEY: '${{secrets.AWS_SECRET_ACCESS_KEY}}'
AWS_DEFAULT_REGION: '${{secrets.AWS_DEFAULT_REGION}}'
- name: Run `packer build`
run: |
cd ../dbgate-merged/packer
packer build ./aws-ubuntu.pkr.hcl
env:
AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
AWS_DEFAULT_REGION: ${{secrets.AWS_DEFAULT_REGION}}
# - name: Install AWS CLI
# run: |
# curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
# unzip awscliv2.zip
# sudo ./aws/install
# sudo apt-get install jq -y
AWS_ACCESS_KEY_ID: '${{secrets.AWS_ACCESS_KEY_ID}}'
AWS_SECRET_ACCESS_KEY: '${{secrets.AWS_SECRET_ACCESS_KEY}}'
AWS_DEFAULT_REGION: '${{secrets.AWS_DEFAULT_REGION}}'
- name: Install jq
run: |
sudo apt-get install jq -y
- name: Delete old AMIs
run: |
cd ../dbgate-merged/packer
chmod +x delete-old-amis.sh
./delete-old-amis.sh
env:
AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
AWS_DEFAULT_REGION: ${{secrets.AWS_DEFAULT_REGION}}
AWS_ACCESS_KEY_ID: '${{secrets.AWS_ACCESS_KEY_ID}}'
AWS_SECRET_ACCESS_KEY: '${{secrets.AWS_SECRET_ACCESS_KEY}}'
AWS_DEFAULT_REGION: '${{secrets.AWS_DEFAULT_REGION}}'
+24 -29
View File
@@ -1,35 +1,32 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Docker image PREMIUM
on:
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-premium-beta.[0-9]+'
jobs:
build:
runs-on: ${{ matrix.os }}
runs-on: '${{ matrix.os }}'
strategy:
matrix:
os: [ubuntu-22.04]
os:
- ubuntu-22.04
steps:
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
GITHUB_CONTEXT: '${{ toJson(github) }}'
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: |
dbgate/dbgate-premium
images: dbgate/dbgate-premium
flavor: |
latest=false
tags: |
@@ -37,19 +34,16 @@ jobs:
type=match,pattern=\d+.\d+.\d+,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
type=raw,value=latest,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
- name: Use Node.js 18.x
uses: actions/setup-node@v1
with:
node-version: 18.x
- name: Checkout dbgate/dbgate-pro
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
token: '${{ secrets.GH_TOKEN }}'
path: dbgate-pro
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
@@ -61,50 +55,51 @@ jobs:
yarn
node sync.js --nowatch
cd ..
- name: yarn adjustPackageJson
- name: adjustPackageJson
run: |
cd ..
cd dbgate-merged
yarn adjustPackageJson
node adjustPackageJson --premium
- name: yarn install
run: |
cd ..
cd dbgate-merged
yarn install
# yarn --version
# yarn config set network-timeout 300000
yarn install
- name: setCurrentVersion
run: |
cd ..
cd dbgate-merged
yarn setCurrentVersion
- name: printSecrets
run: |
cd ..
cd dbgate-merged
yarn printSecrets
yarn printSecrets
env:
GIST_UPLOAD_SECRET : ${{secrets.GIST_UPLOAD_SECRET}}
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
- name: Prepare docker image
run: |
cd ..
cd dbgate-merged
yarn run prepare:docker
yarn run prepare:docker
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
username: '${{ secrets.DOCKER_USERNAME }}'
password: '${{ secrets.DOCKER_PASSWORD }}'
- name: Build and push
uses: docker/build-push-action@v3
with:
push: true
context: ../dbgate-merged/docker
tags: ${{ steps.meta.outputs.tags }}
platforms: linux/amd64,linux/arm64
tags: '${{ steps.meta.outputs.tags }}'
platforms: 'linux/amd64,linux/arm64'
+24 -31
View File
@@ -1,35 +1,32 @@
name: Docker image
on:
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Docker image Community
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+'
jobs:
build:
runs-on: ${{ matrix.os }}
runs-on: '${{ matrix.os }}'
strategy:
matrix:
os: [ubuntu-22.04]
os:
- ubuntu-22.04
steps:
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
GITHUB_CONTEXT: '${{ toJson(github) }}'
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: |
dbgate/dbgate
images: dbgate/dbgate
flavor: |
latest=false
tags: |
@@ -37,7 +34,6 @@ jobs:
type=match,pattern=\d+.\d+.\d+,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
type=raw,value=latest,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
- name: Docker alpine meta
id: alpmeta
uses: docker/metadata-action@v4
@@ -51,56 +47,53 @@ jobs:
type=match,pattern=\d+.\d+.\d+,suffix=-alpine,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
type=raw,value=alpine,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
- name: Use Node.js 18.x
uses: actions/setup-node@v1
with:
node-version: 18.x
- name: yarn adjustPackageJson
- name: adjustPackageJson
run: |
yarn adjustPackageJson
node adjustPackageJson --community
- name: yarn install
run: |
# yarn --version
# yarn config set network-timeout 300000
yarn install
- name: setCurrentVersion
run: |
yarn setCurrentVersion
- name: printSecrets
run: |
yarn printSecrets
yarn printSecrets
env:
GIST_UPLOAD_SECRET : ${{secrets.GIST_UPLOAD_SECRET}}
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
- name: Prepare docker image
run: |
yarn run prepare:docker
yarn run prepare:docker
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
username: '${{ secrets.DOCKER_USERNAME }}'
password: '${{ secrets.DOCKER_PASSWORD }}'
- name: Build and push
uses: docker/build-push-action@v3
with:
push: true
context: ./docker
tags: ${{ steps.meta.outputs.tags }}
platforms: linux/amd64,linux/arm64,linux/arm/v7
tags: '${{ steps.meta.outputs.tags }}'
platforms: 'linux/amd64,linux/arm64,linux/arm/v7'
- name: Build and push alpine
uses: docker/build-push-action@v3
with:
push: true
context: ./docker
file: ./docker/Dockerfile-alpine
tags: ${{ steps.alpmeta.outputs.tags }}
platforms: linux/amd64,linux/arm64,linux/arm/v7
tags: '${{ steps.alpmeta.outputs.tags }}'
platforms: 'linux/amd64,linux/arm64,linux/arm/v7'
+11 -31
View File
@@ -1,31 +1,23 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: NPM packages PREMIUM
# on: [push]
on:
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+'
# on:
# push:
# branches:
# - production
jobs:
build:
runs-on: ${{ matrix.os }}
runs-on: '${{ matrix.os }}'
strategy:
matrix:
os: [ubuntu-22.04]
os:
- ubuntu-22.04
steps:
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
GITHUB_CONTEXT: '${{ toJson(github) }}'
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
@@ -34,14 +26,12 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: 18.x
- name: Checkout dbgate/dbgate-pro
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
token: '${{ secrets.GH_TOKEN }}'
path: dbgate-pro
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
@@ -53,65 +43,55 @@ jobs:
yarn
node sync.js --nowatch
cd ..
- name: adjustNpmPackageJsonPremium
run: |
cd ..
cd dbgate-merged
node adjustNpmPackageJsonPremium
- name: Configure NPM token
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
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
run: |
cd ..
cd dbgate-merged
rm -rf packages/dbmodel
- name: yarn install
run: |
cd ..
cd dbgate-merged
yarn install
- name: setCurrentVersion
run: |
cd ..
cd dbgate-merged
yarn setCurrentVersion
- name: printSecrets
run: |
cd ..
cd dbgate-merged
yarn printSecrets
env:
GIST_UPLOAD_SECRET : ${{secrets.GIST_UPLOAD_SECRET}}
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
- name: Publish dbgate-api-premium
run: |
cd ..
cd dbgate-merged/packages/api
npm publish
- name: Publish dbgate-web-premium
run: |
cd ..
cd dbgate-merged/packages/web
npm publish
- name: Publish dbgate-serve-premium
run: |
cd ..
cd dbgate-merged/packages/serve
npm publish
- name: Publish dbgate-plugin-cosmosdb
run: |
cd ..
+11 -42
View File
@@ -1,31 +1,23 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: NPM packages
# on: [push]
on:
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+'
# on:
# push:
# branches:
# - production
jobs:
build:
runs-on: ${{ matrix.os }}
runs-on: '${{ matrix.os }}'
strategy:
matrix:
os: [ubuntu-22.04]
os:
- ubuntu-22.04
steps:
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
GITHUB_CONTEXT: '${{ toJson(github) }}'
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
@@ -34,37 +26,30 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: 18.x
- name: Configure NPM token
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_TOKEN: '${{ secrets.NPM_TOKEN }}'
run: |
npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
- name: yarn install
run: |
yarn install
- name: setCurrentVersion
run: |
yarn setCurrentVersion
- name: printSecrets
run: |
yarn printSecrets
yarn printSecrets
env:
GIST_UPLOAD_SECRET : ${{secrets.GIST_UPLOAD_SECRET}}
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
- name: Publish types
working-directory: packages/types
run: |
npm publish
- name: Publish tools
working-directory: packages/tools
run: |
npm publish
- name: Publish sqltree
working-directory: packages/sqltree
run: |
@@ -74,82 +59,66 @@ jobs:
working-directory: packages/api
run: |
npm publish
- name: Publish datalib
working-directory: packages/datalib
run: |
npm publish
- name: Publish filterparser
working-directory: packages/filterparser
run: |
npm publish
- name: Publish web
working-directory: packages/web
run: |
npm publish
- name: Publish dbgate-serve
working-directory: packages/serve
run: |
npm publish
- name: Publish dbmodel
working-directory: packages/dbmodel
run: |
npm publish
- name: Publish dbgate-plugin-csv
working-directory: plugins/dbgate-plugin-csv
run: |
npm publish
- name: Publish dbgate-plugin-xml
working-directory: plugins/dbgate-plugin-xml
run: |
npm publish
- name: Publish dbgate-plugin-excel
working-directory: plugins/dbgate-plugin-excel
run: |
npm publish
- name: Publish dbgate-plugin-mssql
working-directory: plugins/dbgate-plugin-mssql
run: |
npm publish
- name: Publish dbgate-plugin-mysql
working-directory: plugins/dbgate-plugin-mysql
run: |
npm publish
- name: Publish dbgate-plugin-mongo
working-directory: plugins/dbgate-plugin-mongo
run: |
npm publish
- name: Publish dbgate-plugin-postgres
working-directory: plugins/dbgate-plugin-postgres
run: |
npm publish
- name: Publish dbgate-plugin-sqlite
working-directory: plugins/dbgate-plugin-sqlite
run: |
npm publish
- name: Publish dbgate-plugin-redis
working-directory: plugins/dbgate-plugin-redis
run: |
npm publish
- name: Publish dbgate-plugin-oracle
working-directory: plugins/dbgate-plugin-oracle
run: |
npm publish
- name: Publish dbgate-plugin-clickhouse
working-directory: plugins/dbgate-plugin-clickhouse
run: |
+14 -26
View File
@@ -1,16 +1,17 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Run tests
on:
'on':
push:
branches:
- master
- develop
- 'feature/**'
- feature/**
jobs:
test-runner:
runs-on: ubuntu-latest
container: node:18
container: 'node:18'
steps:
- name: Install dependencies for cypress
run: |
@@ -37,7 +38,6 @@ jobs:
run: |
cd integration-tests
yarn test:ci
# yarn wait:ci
- name: Filter parser tests
if: always()
run: |
@@ -51,54 +51,42 @@ jobs:
- uses: tanmen/jest-reporter@v1
if: always()
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
github-token: '${{ secrets.GITHUB_TOKEN }}'
result-file: integration-tests/result.json
action-name: Integration tests
- uses: tanmen/jest-reporter@v1
if: always()
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
github-token: '${{ secrets.GITHUB_TOKEN }}'
result-file: packages/filterparser/result.json
action-name: Filter parser test results
- uses: tanmen/jest-reporter@v1
if: always()
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
github-token: '${{ secrets.GITHUB_TOKEN }}'
result-file: packages/datalib/result.json
action-name: Datalib (perspectives) test results
services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: Pwd2020Db
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
options: '--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5'
mysql:
image: mysql:8.0.18
image: 'mysql:8.0.18'
env:
MYSQL_ROOT_PASSWORD: Pwd2020Db
mssql:
image: mcr.microsoft.com/mssql/server
env:
ACCEPT_EULA: Y
ACCEPT_EULA: 'Y'
SA_PASSWORD: Pwd2020Db
MSSQL_PID: Express
clickhouse:
image: bitnami/clickhouse:24.8.4
image: 'bitnami/clickhouse:24.8.4'
env:
CLICKHOUSE_ADMIN_PASSWORD: Pwd2020Db
oracle:
image: gvenzl/oracle-xe:21-slim
image: 'gvenzl/oracle-xe:21-slim'
env:
ORACLE_PASSWORD: Pwd2020Db
# cockroachdb:
# image: cockroachdb/cockroach
+23
View File
@@ -8,6 +8,29 @@ Builds:
- linux - application for linux
- win - application for Windows
### 6.1.1
- ADDED: Trigger support (SQL Server, PostgreSQL, MySQL, Oracle)
- FIXED: PostgreSQL and Oracle export #970
- FIXED: Cursor Becomes Stuck When Escaping "Case" #954
- CHANGED: Defualt search criteria for tables are names only
- FIXED: Search in packed list
### 6.1.0
- ADDED: Fulltext search in DB model and connections, highlight searched names
- ADDED: Tab preview mode configuration #963
- CHANGED: Single-click to open server connection/database + ability to configure this #959
- ADDED: Option to align numbers to right in data grid #957
- FIXED: Cursor Becomes Stuck When Escaping "Case" #954
- ADDED: Postgres GEOGRAPHY types are shown on map, event when executing query #948
- FIXED: Error displaying CLOB and NCLOB in Oracle
- FIXED: Analysing of foreign keys in Postgres and MS SQL, when the same FKS are used across different schemas
- ADDED: Support of views, procedures, functions to Oracle. Added integration tests for Oracle
- ADDED: Display "No rows" message, quick add new row
- ADDED: Choose default database from list
- ADDED: Default database is automatically selected on connect
- ADDED: Apple-Silicon-only build for Mac #949
- ADDED: Display comment into tables and column list #755
### 6.0.0
- ADDED: Order or filter the indexes for huge tables #922
- ADDED: Empty string filters
+2 -2
View File
@@ -17,7 +17,7 @@ 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
* **Download** application for Windows, Linux or Mac from [dbgate.org](https://dbgate.org/download/)
* 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://dbgate.org/docs/scripting.html) ([API documentation](https://dbgate.org/docs/apidoc.html))
* Use nodeJs [scripting interface](https://dbgate.org/docs/scripting) ([API documentation](https://dbgate.org/docs/apidoc))
* [Recommend DbGate](https://testimonial.to/dbgate) | [Rate on G2](https://www.g2.com/products/dbgate/reviews)
## Supported databases
@@ -87,7 +87,7 @@ Any contributions are welcome. If you want to contribute without coding, conside
* 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)
* Become a backer on [GitHub sponsors](https://github.com/sponsors/dbgate) or [Open collective](https://opencollective.com/dbgate)
* Where a small coding is acceptable for you, you could [create plugin](https://dbgate.org/docs/plugin-development.html). Plugins for new themes can be created actually without JS coding
* Where a small coding is acceptable for you, you could [create plugin](https://dbgate.org/docs/plugin-development). Plugins for new themes can be created actually without JS coding
Thank you!
+23
View File
@@ -41,6 +41,29 @@ function adjustFile(file, isApp = false) {
delete json.optionalDependencies.msnodesqlv8;
}
if (process.argv.includes('--community')) {
delete json.optionalDependencies['mongodb-client-encryption'];
}
if (isApp && process.argv.includes('--premium')) {
json.build.win.target = [
{
target: 'nsis',
arch: ['x64'],
},
];
json.build.linux.target = [
{
target: 'AppImage',
arch: ['x64'],
},
];
json.name = 'dbgate-premium';
json.build.artifactName = 'dbgate-premium-${version}-${os}_${arch}.${ext}';
json.build.appId = 'org.dbgate.premium';
json.build.productName = 'DbGate Premium';
}
fs.writeFileSync(file, JSON.stringify(json, null, 2), 'utf-8');
}
+3 -4
View File
@@ -19,7 +19,6 @@
"artifactName": "dbgate-${version}-${os}_${arch}.${ext}",
"appId": "org.dbgate",
"productName": "DbGate",
"afterSign": "electron-builder-notarize",
"asarUnpack": "**/*.node",
"mac": {
"category": "database",
@@ -41,7 +40,8 @@
"x64",
"arm64"
]
}
},
"notarize": true
},
"linux": {
"target": [
@@ -130,7 +130,6 @@
"copyfiles": "^2.2.0",
"cross-env": "^6.0.3",
"electron": "30.0.2",
"electron-builder": "23.1.0",
"electron-builder-notarize": "^1.5.2"
"electron-builder": "25.1.8"
}
}
+828 -1022
View File
File diff suppressed because it is too large Load Diff
+174
View File
@@ -0,0 +1,174 @@
const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');
const _ = require('lodash');
const indir = path.resolve(path.join(__dirname, '..', 'workflow-templates'));
const outdir = path.resolve(path.join(__dirname, '..', '.github', 'workflows'));
const includes = {};
const HEADER = `# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
`;
function readIncludes() {
for (const file of fs.readdirSync(indir)) {
const text = fs.readFileSync(path.join(indir, file), { encoding: 'utf-8' });
const json = yaml.load(text);
if (json._module) {
for (const key in json) {
if (key === '_module') {
continue;
}
includes[key] = json[key];
}
}
}
}
let modified = false;
function conditionMatch(condition, args) {
if (_.isString(condition)) {
return args.defs.includes(condition);
}
return false;
}
function processJsonStep(json, args) {
return _.cloneDeepWith(json, value => {
if (_.isArray(value)) {
const res = [];
let arrayModified = false;
for (const item of value) {
if (item._if) {
modified = true;
arrayModified = true;
if (conditionMatch(item._if, args)) {
res.push(_.omit(item, ['_if']));
}
} else if (item._replace || item._include) {
const replaceWith = item._replace ? args.replace?.[item._replace] : includes[item._include];
if (replaceWith) {
modified = true;
arrayModified = true;
if (_.isArray(replaceWith)) {
res.push(...replaceWith);
} else {
res.push(replaceWith);
}
} else {
res.push(item);
}
} else {
res.push(item);
}
}
if (arrayModified) {
return res;
}
return undefined;
}
if (_.isPlainObject(value)) {
if (_.intersection(args.allDefs ?? [], Object.keys(value))?.length > 0) {
modified = true;
for (const key in value) {
if (args.defs.includes(key)) {
return value[key];
}
}
return undefined;
}
}
if (_.isString(value)) {
let stringModified = false;
for (const key of Object.keys(args.stringReplace ?? {})) {
if (value.includes(key)) {
modified = true;
stringModified = true;
value = value.replaceAll(key, args.stringReplace[key]);
}
}
if (stringModified) {
return value;
}
return undefined;
}
if (value?._include) {
modified = true;
return includes[value?._include];
}
if (value?._replace) {
modified = true;
return args?.replace[value?._replace];
}
});
}
function processJson(json, args = {}) {
const MAX_STEPS = 64;
for (let i = 0; i < MAX_STEPS; i++) {
modified = false;
json = processJsonStep(json, args);
if (!modified) {
break;
}
}
return json;
}
function processFiles() {
const dumpOptions = {
lineWidth: -1,
};
for (const file of fs.readdirSync(indir)) {
const text = fs.readFileSync(path.join(indir, file), { encoding: 'utf-8' });
const json = yaml.load(text);
if (json._module) {
continue;
}
if (json._templates) {
const allDefs = Object.keys(json._templates);
for (const key in json._templates) {
allDefs.push(...(json._templates[key].defs ?? []));
}
for (const key in json._templates) {
const args = {
defs: [key, ...(json._templates[key]?.defs ?? [])],
replace: json._templates[key]?.replace,
stringReplace: json._templates[key]?.['string-replace'],
allDefs,
};
const converted = processJson(_.omit(json, ['_templates']), args);
const out = path.join(outdir, json._templates[key].file);
fs.writeFileSync(out, HEADER + yaml.dump(converted, dumpOptions));
}
} else {
fs.writeFileSync(path.join(outdir, file), HEADER + yaml.dump(processJson(json), dumpOptions));
}
}
}
function deleteOldFiles() {
const files = fs.readdirSync(outdir);
for (const file of files) {
fs.unlinkSync(path.join(outdir, file));
}
}
function run() {
deleteOldFiles();
readIncludes();
processFiles();
}
run();
+40 -1
View File
@@ -23,9 +23,48 @@ describe('Initialization', () => {
cy.contains('performance_schema');
});
// it('SSH connection', () => {
// const runOnCI = Cypress.env('runOnCI');
// cy.get('body')
// .trigger('keydown', {
// key: 'F1',
// code: 'F1',
// which: 112,
// keyCode: 112,
// bubbles: true,
// })
// .trigger('keyup', {
// key: 'F1',
// code: 'F1',
// which: 112,
// keyCode: 112,
// bubbles: true,
// });
// cy.get('body').type('Close all');
// cy.get('body').type('{enter}');
// cy.visit('http://localhost:3000');
// cy.get('[data-testid=ConnectionList_buttonNewConnection]').click();
// cy.get('[data-testid=ConnectionDriverFields_connectionType]').select('MySQL');
// cy.get('[data-testid=ConnectionDriverFields_user]').clear().type('root');
// cy.get('[data-testid=ConnectionDriverFields_password]').clear().type('root');
// cy.get('[data-testid=ConnectionSshTunnelFields_sshLogin]').clear().type('root');
// cy.get('[data-testid=ConnectionSshTunnelFields_sshPassword]').clear().type('root');
// if (runOnCI) {
// cy.get('[data-testid=ConnectionSshTunnelFields_sshHost]').clear().type('mysql-ssh');
// } else {
// cy.get('[data-testid=ConnectionSshTunnelFields_sshPort]').clear().type('16006');
// }
// cy.get('[data-testid=ConnectionDriverFields_displayName]').clear().type('test-mysql-ssh-1');
// cy.get('[data-testid=ConnectionTab_buttonSave]').click();
// cy.get('[data-testid=ConnectionTab_buttonConnect]').click();
// cy.contains('performance_schema');
// });
// it('import chinook DB', () => {
// cy.visit('http://localhost:3000');
// cy.get('[data-testid=ConnectionTab_buttonConnect]').click();
// });
});
+7
View File
@@ -16,3 +16,10 @@ services:
- 16004:3306
environment:
- MYSQL_ROOT_PASSWORD=Pwd2020Db
mysql-ssh:
build: mysql-ssh
restart: always
ports:
- 16005:3306
- 16006:22
+22
View File
@@ -0,0 +1,22 @@
FROM ubuntu:22.04
RUN apt-get update && \
apt-get install -y openssh-server mysql-server && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN mkdir /var/run/sshd
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN echo 'root:root' | chpasswd
RUN service mysql start && \
mysql -uroot -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root'; FLUSH PRIVILEGES;" && \
service mysql stop
EXPOSE 22 3306
COPY start.sh /start.sh
RUN chmod +x /start.sh
CMD ["/start.sh"]
+7
View File
@@ -0,0 +1,7 @@
#!/bin/bash
service ssh start
service mysql start
tail -f /dev/null
@@ -2,10 +2,11 @@ const engines = require('../engines');
const stream = require('stream');
const { testWrapper } = require('../tools');
const tableWriter = require('dbgate-api/src/shell/tableWriter');
const tableReader = require('dbgate-api/src/shell/tableReader');
const copyStream = require('dbgate-api/src/shell/copyStream');
const importDatabase = require('dbgate-api/src/shell/importDatabase');
const fakeObjectReader = require('dbgate-api/src/shell/fakeObjectReader');
const { runQueryOnDriver } = require('dbgate-tools');
const { runQueryOnDriver, runCommandOnDriver } = require('dbgate-tools');
function createImportStream() {
const pass = new stream.PassThrough({
@@ -23,7 +24,17 @@ function createImportStream() {
return pass;
}
describe('DB Import', () => {
function createExportStream() {
const writable = new stream.Writable({ objectMode: true });
writable.resultArray = [];
writable._write = (chunk, encoding, callback) => {
writable.resultArray.push(chunk);
callback();
};
return writable;
}
describe('DB Import/export', () => {
test.each(engines.map(engine => [engine.label, engine]))(
'Import one table - %s',
testWrapper(async (conn, driver, engine) => {
@@ -99,4 +110,35 @@ describe('DB Import', () => {
// expect(res2.rows[0].cnt.toString()).toEqual('6');
})
);
test.each(engines.map(engine => [engine.label, engine]))(
'Export one table - %s',
testWrapper(async (conn, driver, engine) => {
// const reader = await fakeObjectReader({ delay: 10 });
// const reader = await fakeObjectReader();
await runCommandOnDriver(conn, driver, 'create table ~t1 (~id int primary key, ~country varchar(100))');
const data = [
[1, 'Czechia'],
[2, 'Austria'],
[3, 'Germany'],
[4, 'Romania'],
[5, 'Great Britain'],
[6, 'Bosna, Hecegovina'],
];
for (const row of data) {
await runCommandOnDriver(conn, driver, dmp =>
dmp.put('insert into ~t1(~id, ~country) values (%v, %v)', ...row)
);
}
const reader = await tableReader({
systemConnection: conn,
driver,
pureName: 't1',
});
const writer = createExportStream();
await copyStream(reader, writer);
expect(writer.resultArray.filter(x => !x.__isStreamHeader).map(row => [row.id, row.country])).toEqual(data);
})
);
});
@@ -419,7 +419,7 @@ describe('Deploy database', () => {
})
);
test.each(engines.enginesPostgre.map(engine => [engine.label, engine]))(
test.each([engines.postgreSqlEngine].map(engine => [engine.label, engine]))(
'Current timestamp default value - %s',
testWrapper(async (conn, driver, engine) => {
await testDatabaseDeploy(engine, conn, driver, [
@@ -19,6 +19,10 @@ function flatSourceParameters() {
);
}
function flatSourceTriggers() {
return _.flatten(engines.map(engine => (engine.triggers || []).map(trigger => [engine.label, trigger, engine])));
}
const obj1Match = expect.objectContaining({
pureName: 'obj1',
});
@@ -96,44 +100,78 @@ describe('Object analyse', () => {
})
);
test.each(flatSourceParameters())(
'Test parameters simple analyse - %s - %s',
testWrapper(async (conn, driver, testName, parameter, engine) => {
for (const sql of initSql) await runCommandOnDriver(conn, driver, sql);
for (const sql of engine.parametersOtherSql) await runCommandOnDriver(conn, driver, sql);
const flatParameters = flatSourceParameters();
await runCommandOnDriver(conn, driver, parameter.create);
if (flatParameters.length > 0) {
test.each(flatParameters)(
'Test parameters simple analyse - %s - %s',
testWrapper(async (conn, driver, testName, parameter, engine) => {
for (const sql of initSql) await runCommandOnDriver(conn, driver, sql);
for (const sql of engine.parametersOtherSql) await runCommandOnDriver(conn, driver, sql);
await runCommandOnDriver(conn, driver, parameter.create);
const structure = await driver.analyseFull(conn);
const parameters = structure[parameter.objectTypeField].find(x => x.pureName == 'obj1').parameters;
expect(parameters.length).toEqual(parameter.list.length);
for (let i = 0; i < parameters.length; i += 1) {
expect(parameters[i]).toEqual(expect.objectContaining(parameter.list[i]));
}
})
);
test.each(flatParameters)(
'Test parameters create SQL - %s - %s',
testWrapper(async (conn, driver, testName, parameter, engine) => {
for (const sql of initSql) await runCommandOnDriver(conn, driver, sql);
for (const sql of engine.parametersOtherSql) await runCommandOnDriver(conn, driver, sql);
await runCommandOnDriver(conn, driver, parameter.create);
const structure1 = await driver.analyseFull(conn);
await runCommandOnDriver(conn, driver, parameter.drop);
const obj = structure1[parameter.objectTypeField].find(x => x.pureName == 'obj1');
await driver.script(conn, obj.createSql, { discardResult: true });
const structure2 = await driver.analyseFull(conn);
const parameters = structure2[parameter.objectTypeField].find(x => x.pureName == 'obj1').parameters;
expect(parameters.length).toEqual(parameter.list.length);
for (let i = 0; i < parameters.length; i += 1) {
expect(parameters[i]).toEqual(expect.objectContaining(parameter.list[i]));
}
})
);
}
test.each(flatSourceTriggers())(
'Test triggers - %s - %s',
testWrapper(async (conn, driver, trigger) => {
for (const sql of initSql) await runCommandOnDriver(conn, driver, sql);
const { triggerOtherDropSql, triggerOtherCreateSql, create, drop, expected, objectTypeField } = trigger;
if (triggerOtherCreateSql) await runCommandOnDriver(conn, driver, triggerOtherCreateSql);
await runCommandOnDriver(conn, driver, create);
const structure = await driver.analyseFull(conn);
await runCommandOnDriver(conn, driver, drop);
const parameters = structure[parameter.objectTypeField].find(x => x.pureName == 'obj1').parameters;
if (triggerOtherDropSql) await runCommandOnDriver(conn, driver, triggerOtherDropSql);
expect(parameters.length).toEqual(parameter.list.length);
for (let i = 0; i < parameters.length; i += 1) {
expect(parameters[i]).toEqual(expect.objectContaining(parameter.list[i]));
}
})
);
const createdTrigger = structure[objectTypeField].find(x => x.pureName == expected.pureName);
expect(createdTrigger).toEqual(expect.objectContaining(expected));
test.each(flatSourceParameters())(
'Test parameters create SQL - %s - %s',
testWrapper(async (conn, driver, testName, parameter, engine) => {
for (const sql of initSql) await runCommandOnDriver(conn, driver, sql);
for (const sql of engine.parametersOtherSql) await runCommandOnDriver(conn, driver, sql);
await runCommandOnDriver(conn, driver, parameter.create);
const structure1 = await driver.analyseFull(conn);
await runCommandOnDriver(conn, driver, parameter.drop);
const obj = structure1[parameter.objectTypeField].find(x => x.pureName == 'obj1');
await driver.script(conn, obj.createSql, { discardResult: true });
// test trigger createSql
if (triggerOtherCreateSql) await runCommandOnDriver(conn, driver, triggerOtherCreateSql);
await driver.script(conn, createdTrigger.createSql);
const structure2 = await driver.analyseFull(conn);
const parameters = structure2[parameter.objectTypeField].find(x => x.pureName == 'obj1').parameters;
expect(parameters.length).toEqual(parameter.list.length);
for (let i = 0; i < parameters.length; i += 1) {
expect(parameters[i]).toEqual(expect.objectContaining(parameter.list[i]));
}
const createdTrigger2 = structure2[objectTypeField].find(x => x.pureName == expected.pureName);
expect(createdTrigger2).toEqual(expect.objectContaining(expected));
})
);
});
console.log(flatSourceTriggers());
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -1,6 +1,6 @@
{
"private": true,
"version": "6.0.1-beta.3",
"version": "6.1.3-beta.1",
"name": "dbgate-all",
"workspaces": [
"packages/*",
@@ -47,7 +47,6 @@
"setCurrentVersion": "node setCurrentVersion",
"printSecrets": "node printSecrets",
"generatePadFile": "node generatePadFile",
"adjustPackageJson": "node adjustPackageJson",
"fillPackagedPlugins": "node fillPackagedPlugins",
"resetPackagedPlugins": "node resetPackagedPlugins",
"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",
@@ -63,7 +62,8 @@
"ts:web": "yarn workspace dbgate-web ts",
"ts": "yarn ts:api && yarn ts:web",
"postinstall": "yarn resetPackagedPlugins && yarn build:lib && patch-package && yarn build:plugins:frontend",
"dbgate-serve": "node packages/dbgate/bin/dbgate-serve.js"
"dbgate-serve": "node packages/dbgate/bin/dbgate-serve.js",
"workflows": "node common/processWorkflows.js"
},
"dependencies": {
"concurrently": "^5.1.0",
+1 -1
View File
@@ -30,7 +30,7 @@
"cors": "^2.8.5",
"cross-env": "^6.0.3",
"dbgate-datalib": "^6.0.0-alpha.1",
"dbgate-query-splitter": "^4.11.2",
"dbgate-query-splitter": "^4.11.3",
"dbgate-sqltree": "^6.0.0-alpha.1",
"dbgate-tools": "^6.0.0-alpha.1",
"debug": "^4.3.4",
+2 -2
View File
@@ -222,7 +222,7 @@ module.exports = {
},
test_meta: true,
test(connection) {
test({ connection, requestDbList }) {
const subprocess = fork(
global['API_PACKAGE'] || process.argv[1],
[
@@ -237,7 +237,7 @@ module.exports = {
}
);
pipeForkLogs(subprocess);
subprocess.send(connection);
subprocess.send({ ...connection, requestDbList });
return new Promise(resolve => {
subprocess.on('message', resp => {
if (handleProcessCommunication(resp, subprocess)) return;
+7 -1
View File
@@ -17,12 +17,18 @@ Platform: ${process.platform}
function start() {
childProcessChecker();
process.on('message', async connection => {
// @ts-ignore
const { requestDbList } = connection;
if (handleProcessCommunication(connection)) return;
try {
const driver = requireEngineDriver(connection);
const dbhan = await connectUtility(driver, connection, 'app');
const res = await driver.getVersion(dbhan);
process.send({ msgtype: 'connected', ...res });
let databases = undefined;
if (requestDbList) {
databases = await driver.listDatabases(dbhan);
}
process.send({ msgtype: 'connected', ...res, databases });
await driver.close(dbhan);
} catch (e) {
console.error(e);
+5 -2
View File
@@ -8,12 +8,15 @@ const logger = getLogger('tableReader');
* @param {object} options
* @param {connectionType} options.connection - connection object
* @param {object} options.systemConnection - system connection (result of driver.connect). If not provided, new connection will be created
* @param {object} options.driver - driver object. If not provided, it will be loaded from connection
* @param {string} options.pureName - table name
* @param {string} options.schemaName - schema name
* @returns {Promise<readerType>} - reader object
*/
async function tableReader({ connection, systemConnection, pureName, schemaName }) {
const driver = requireEngineDriver(connection);
async function tableReader({ connection, systemConnection, pureName, schemaName, driver }) {
if (!driver) {
driver = requireEngineDriver(connection);
}
const dbhan = systemConnection || (await connectUtility(driver, connection, 'read'));
logger.info(`Connected.`);
+1 -1
View File
@@ -41,7 +41,7 @@ STORAGE_DATABASE=dbname
STORAGE_ENGINE=mysql@dbgate-plugin-mysql
```
You could find more about environment variable configuration on [DbGate docs](https://dbgate.org/docs/env-variables.html) page.
You could find more about environment variable configuration on [DbGate docs](https://dbgate.org/docs/env-variables/) page.
After installing, you can run dbgate with command:
```sh
+1 -1
View File
@@ -31,7 +31,7 @@
"typescript": "^4.4.3"
},
"dependencies": {
"dbgate-query-splitter": "^4.11.2",
"dbgate-query-splitter": "^4.11.3",
"dbgate-sqltree": "^6.0.0-alpha.1",
"debug": "^4.3.4",
"json-stable-stringify": "^1.0.1",
+1 -1
View File
@@ -715,7 +715,7 @@ export function createAlterDatabasePlan(
): AlterPlan {
const plan = new AlterPlan(wholeOldDb, wholeNewDb, driver.dialect, opts);
for (const objectTypeField of ['tables', 'views', 'procedures', 'matviews', 'functions']) {
for (const objectTypeField of ['tables', 'views', 'procedures', 'matviews', 'functions', 'triggers']) {
for (const oldobj of oldDb[objectTypeField] || []) {
const newobj = (newDb[objectTypeField] || []).find(x => x.pairingId == oldobj.pairingId);
if (objectTypeField == 'tables') {
+16 -5
View File
@@ -90,11 +90,16 @@ export function tokenizeBySearchFilter(text: string, filter: string): { text: st
for (const item of res) {
const indexes = [];
for (const char of token) {
const index = item.text.indexOf(char, indexes.length > 0 ? indexes[indexes.length - 1] + 1 : 0);
if (index < 0) {
indexes.push(-1);
if (indexes.length == 0 && char == item.text[0]?.toUpperCase()) {
// handle first letter of camelcase
indexes.push(0);
} else {
indexes.push(index);
const index = item.text.indexOf(char, indexes.length > 0 ? indexes[indexes.length - 1] + 1 : 0);
if (index < 0) {
indexes.push(-1);
} else {
indexes.push(index);
}
}
}
if (indexes.some(x => x < 0)) {
@@ -129,7 +134,13 @@ export function tokenizeBySearchFilter(text: string, filter: string): { text: st
res = nextres;
}
return res.filter(x => x.text.length > 0);
res = res.filter(x => x.text.length > 0);
if (res.length == 1 && !res[0].isMatch) {
return null;
}
return res;
// const result = [];
// let lastMatch = 0;
+1
View File
@@ -234,6 +234,7 @@ export function databaseInfoFromYamlModel(filesOrDbInfo: DatabaseModelFile[] | D
if (file.name.endsWith('.trigger.sql')) {
model.triggers.push({
objectId: `triggers:${file.name.slice(0, -'.trigger.sql'.length)}`,
pureName: file.name.slice(0, -'.trigger.sql'.length),
createSql: file.text,
});
+20 -1
View File
@@ -124,6 +124,7 @@ export interface ParameterInfo extends NamedObjectInfo {
parameterName?: string;
dataType: string;
parameterMode?: ParameterMode;
position?: number;
}
export interface CallableObjectInfo extends SqlObjectInfo {
@@ -136,7 +137,25 @@ export interface FunctionInfo extends CallableObjectInfo {
returnType?: string;
}
export interface TriggerInfo extends SqlObjectInfo {}
export interface TriggerInfo extends SqlObjectInfo {
objectId: string;
functionName?: string;
tableName?: string;
triggerTiming?:
| 'BEFORE'
| 'AFTER'
| 'INSTEAD OF'
| 'BEFORE EACH ROW'
| 'INSTEAD OF'
| 'AFTER EACH ROW'
| 'AFTER STATEMENT'
| 'BEFORE STATEMENT'
| 'AFTER EVENT'
| 'BEFORE EVENT'
| null;
triggerLevel?: 'ROW' | 'STATEMENT';
eventType?: 'INSERT' | 'UPDATE' | 'DELETE' | 'TRUNCATE';
}
export interface SchemaInfo {
objectId?: string;
+2 -2
View File
@@ -20,12 +20,12 @@
"@rollup/plugin-replace": "^3.0.0",
"@rollup/plugin-typescript": "^8.2.5",
"@tsconfig/svelte": "^1.0.0",
"ace-builds": "^1.4.8",
"ace-builds": "^1.36.5",
"chart.js": "^4.4.2",
"chartjs-adapter-moment": "^1.0.0",
"cross-env": "^7.0.3",
"dbgate-datalib": "^6.0.0-alpha.1",
"dbgate-query-splitter": "^4.11.2",
"dbgate-query-splitter": "^4.11.3",
"dbgate-sqltree": "^6.0.0-alpha.1",
"dbgate-tools": "^6.0.0-alpha.1",
"dbgate-types": "^6.0.0-alpha.1",
@@ -194,6 +194,12 @@
<slot />
<style>
.pin,
.pin-active {
position: absolute;
right: 0;
z-index: 150;
}
.main {
padding: 5px;
cursor: pointer;
@@ -89,6 +89,7 @@
{passProps}
isExpandedBySearch={filter && item.isChildMatched}
{filter}
isMainMatched={item.isMainMatched}
/>
{/each}
</div>
+24 -7
View File
@@ -6,6 +6,8 @@
import AppObjectListItem from './AppObjectListItem.svelte';
import { writable } from 'svelte/store';
import Link from '../elements/Link.svelte';
import { focusedConnectionOrDatabase } from '../stores';
import { tick } from 'svelte';
export let list;
export let module;
@@ -40,33 +42,33 @@
const matchResult = matcher ? matcher(data) : true;
let isMatched = true;
let isMainMatched = true;
let isChildMatched = true;
if (matchResult == false) {
isMatched = false;
isChildMatched = false;
isMainMatched = false;
} else if (matchResult == 'child') {
isMatched = true;
isChildMatched = true;
isMainMatched = false;
} else if (matchResult == 'main') {
isMatched = true;
isChildMatched = false;
} else if (matchResult == 'none') {
isMatched = false;
isChildMatched = false;
isMainMatched = false;
} else if (matchResult == 'both') {
isMatched = true;
isChildMatched = !module.disableShowChildrenWithParentMatch;
}
const group = groupFunc ? groupFunc(data) : undefined;
return { group, data, isMatched, isChildMatched };
return { group, data, isMatched, isChildMatched, isMainMatched };
})
);
$: filtered = dataLabeled.filter(x => x.isMatched).map(x => x.data);
$: childrenMatched = dataLabeled.filter(x => x.isChildMatched).map(x => x.data);
$: mainMatched = dataLabeled.filter(x => x.isMainMatched).map(x => x.data);
// let filtered = [];
@@ -93,10 +95,24 @@
return res;
}
function setExpandLimited() {
expandLimited = true;
}
$: groups = groupFunc ? extendGroups(_.groupBy(dataLabeled, 'group'), emptyGroupNames) : null;
$: listLimited = isExpandedBySearch && !expandLimited ? filtered.slice(0, Math.min(filter.trim().length, 3)) : list;
$: listLimited = isExpandedBySearch && !expandLimited ? filtered.slice(0, filter.trim().length < 3 ? 1 : 3) : list;
$: isListLimited = isExpandedBySearch && listLimited.length < filtered.length;
$: listMissingItems = isListLimited ? filtered.slice(listLimited.length) : [];
$: if (
$focusedConnectionOrDatabase &&
listMissingItems.some(
x => $focusedConnectionOrDatabase.conid == x?.connection?._id && $focusedConnectionOrDatabase.database == x?.name
)
) {
tick().then(setExpandLimited);
}
</script>
{#if groupFunc}
@@ -136,6 +152,7 @@
{disableContextMenu}
{filter}
isExpandedBySearch={filter && childrenMatched.includes(data)}
isMainMatched={filter && mainMatched.includes(data)}
{passProps}
{getIsExpanded}
{setIsExpanded}
@@ -24,6 +24,7 @@
export let passProps;
export let getIsExpanded = null;
export let setIsExpanded = null;
export let isMainMatched = false;
let isExpandedCore = false;
@@ -70,7 +71,8 @@
{filter}
{passProps}
{isExpandedBySearch}
isExpandedOnlyBySearch={isExpandedBySearch && !isExpanded}
{isExpanded}
{isMainMatched}
/>
</div>
{/if}
@@ -2,7 +2,7 @@
export const extractKey = ({ columnName }) => columnName;
export const createMatcher =
(filter, cfg = DEFAULT_SEARCH_SETTINGS) =>
(filter, cfg = DEFAULT_OBJECT_SEARCH_SETTINGS) =>
data => {
const filterArgs = [];
if (cfg.columnName) filterArgs.push(data.columnName);
@@ -21,7 +21,7 @@
import { renameDatabaseObjectDialog, alterDatabaseDialog } from '../utility/alterDatabaseTools';
import AppObjectCore from './AppObjectCore.svelte';
import { DEFAULT_SEARCH_SETTINGS } from '../stores';
import { DEFAULT_OBJECT_SEARCH_SETTINGS } from '../stores';
import { filterName } from 'dbgate-tools';
export let data;
@@ -1,14 +1,24 @@
<script context="module">
export const extractKey = data => data._id;
export const createMatcher = filter => props => {
const { _id, displayName, server } = props;
const databases = getLocalStorage(`database_list_${_id}`) || [];
return filterNameCompoud(
filter,
[displayName, server],
databases.map(x => x.name)
);
};
export const createMatcher =
(filter, cfg = DEFAULT_CONNECTION_SEARCH_SETTINGS) =>
props => {
const { _id, displayName, server, user, engine } = props;
const databases = getLocalStorage(`database_list_${_id}`) || [];
const match = (engine || '').match(/^([^@]*)@/);
const engineDisplay = match ? match[1] : engine;
return filterNameCompoud(
filter,
[
cfg.displayName ? displayName : null,
cfg.server ? server : null,
cfg.user ? user : null,
cfg.engine ? engineDisplay : null,
],
cfg.database ? databases.map(x => x.name) : []
);
};
export function openConnection(connection, disableExpand = false) {
if (connection.singleDatabase) {
if (getOpenedSingleDatabaseConnections().includes(connection._id)) {
@@ -40,6 +50,10 @@
expandedConnections.update(x => _.uniq([...x, connection._id]));
}
if (connection.defaultDatabase) {
switchCurrentDatabase({ connection, name: connection.defaultDatabase });
}
// if (!config.runAsPortal && getCurrentSettings()['defaultAction.connectionClick'] != 'connect') {
// expandedConnections.update(x => _.uniq([...x, connection._id]));
// }
@@ -92,6 +106,7 @@
import AppObjectCore from './AppObjectCore.svelte';
import {
currentDatabase,
DEFAULT_CONNECTION_SEARCH_SETTINGS,
expandedConnections,
extensions,
focusedConnectionOrDatabase,
@@ -3,13 +3,13 @@
export const extractKey = ({ schemaName, pureName }) => (schemaName ? `${schemaName}.${pureName}` : pureName);
export const createMatcher =
(filter, cfg = DEFAULT_SEARCH_SETTINGS) =>
({ schemaName, pureName, objectComment, tableEngine, columns, objectTypeField, createSql }) => {
(filter, cfg = DEFAULT_OBJECT_SEARCH_SETTINGS) =>
({ schemaName, pureName, objectComment, tableEngine, columns, objectTypeField, tableName, createSql }) => {
const mainArgs = [];
const childArgs = [];
if (cfg.schemaName) mainArgs.push(schemaName);
if (cfg.pureName) mainArgs.push(pureName);
if (objectTypeField == 'tables') {
if (cfg.tableName) mainArgs.push(pureName);
if (cfg.tableComment) mainArgs.push(objectComment);
if (cfg.tableEngine) mainArgs.push(tableEngine);
@@ -19,9 +19,11 @@
if (cfg.columnDataType) childArgs.push(column.dataType);
}
} else {
if (cfg.sqlObjectName) mainArgs.push(pureName);
if (cfg.sqlObjectText) childArgs.push(createSql);
}
if (objectTypeField == 'triggers' && cfg.pureName) {
mainArgs.push(tableName);
}
const res = filterNameCompoud(filter, mainArgs, childArgs);
return res;
@@ -39,6 +41,7 @@
procedures: 'img procedure',
functions: 'img function',
queries: 'img query-data',
triggers: 'icon trigger',
};
const defaultTabs = {
@@ -49,6 +52,7 @@
queries: 'QueryDataTab',
procedures: 'SqlObjectTab',
functions: 'SqlObjectTab',
triggers: 'SqlObjectTab',
};
function createScriptTemplatesSubmenu(objectTypeField) {
@@ -340,40 +344,8 @@
},
];
case 'functions':
return [
...defaultDatabaseObjectAppObjectActions['functions'],
{
divider: true,
},
hasPermission('dbops/model/edit') && {
label: 'Drop function',
isDrop: true,
requiresWriteAccess: true,
},
hasPermission('dbops/model/edit') && {
label: 'Rename function',
isRename: true,
requiresWriteAccess: true,
},
createScriptTemplatesSubmenu('functions'),
{
label: 'SQL generator',
submenu: [
{
label: 'CREATE FUNCTION',
sqlGeneratorProps: {
createFunctions: true,
},
},
{
label: 'DROP FUNCTION',
sqlGeneratorProps: {
dropFunctions: true,
},
},
],
},
];
case 'triggers':
return [...defaultDatabaseObjectAppObjectActions['triggers']];
case 'collections':
return [
...defaultDatabaseObjectAppObjectActions['collections'],
@@ -751,7 +723,7 @@
return;
}
const availableDefaultActions = defaultDatabaseObjectAppObjectActions[objectTypeField];
const availableDefaultActions = defaultDatabaseObjectAppObjectActions[objectTypeField] ?? [];
const configuredActionId = getLastUsedDefaultActions()[objectTypeField];
const prefferedAction =
@@ -885,7 +857,35 @@
return createDatabaseObjectMenu(data);
}
export function handleObjectClick(data, { forceNewTab = false, tabPreviewMode = false, focusTab = false }) {
export function handleObjectClick(data, clickAction) {
// on:click={() => handleObjectClick(data, { tabPreviewMode: true })}
// on:middleclick={() => handleObjectClick(data, { forceNewTab: true })}
// on:dblclick={() => handleObjectClick(data, { tabPreviewMode: false, focusTab: true })}
const openDetailOnArrows = getOpenDetailOnArrowsSettings();
let forceNewTab = false;
let tabPreviewMode = false;
let focusTab = false;
switch (clickAction) {
case 'leftClick':
tabPreviewMode = true;
break;
case 'middleClick':
forceNewTab = true;
break;
case 'dblClick':
focusTab = true;
break;
case 'keyEnter':
focusTab = true;
break;
case 'keyArrow':
if (!openDetailOnArrows) return;
tabPreviewMode = true;
break;
}
return handleDatabaseObjectClick(data, { forceNewTab, tabPreviewMode, focusTab });
}
</script>
@@ -894,30 +894,18 @@
import _ from 'lodash';
import AppObjectCore from './AppObjectCore.svelte';
import {
currentDatabase,
DEFAULT_SEARCH_SETTINGS,
extensions,
DEFAULT_OBJECT_SEARCH_SETTINGS,
getActiveTab,
getCurrentSettings,
getDatabaseObjectAppObjectSearchSettings,
getExtensions,
getLastUsedDefaultActions,
lastUsedDefaultActions,
openedConnections,
openedTabs,
pinnedTables,
selectedDatabaseObjectAppObject,
} from '../stores';
import openNewTab from '../utility/openNewTab';
import {
extractDbNameFromComposite,
filterName,
filterNameCompoud,
generateDbPairingId,
getAlterDatabaseScript,
getConnectionLabel,
} from 'dbgate-tools';
import { getConnectionInfo, getDatabaseInfo } from '../utility/metadataLoaders';
import { extractDbNameFromComposite, filterNameCompoud, getConnectionLabel } from 'dbgate-tools';
import { getConnectionInfo } from '../utility/metadataLoaders';
import fullDisplayName from '../utility/fullDisplayName';
import { showModal } from '../modals/modalTools';
import { findEngineDriver } from 'dbgate-tools';
@@ -928,7 +916,6 @@
import ConfirmSqlModal, { runOperationOnDatabase, saveScriptToDatabase } from '../modals/ConfirmSqlModal.svelte';
import { alterDatabaseDialog, renameDatabaseObjectDialog } from '../utility/alterDatabaseTools';
import ConfirmModal from '../modals/ConfirmModal.svelte';
import { apiCall } from '../utility/api';
import InputTextModal from '../modals/InputTextModal.svelte';
import { extractShellConnection } from '../impexp/createImpExpScript';
import { format as dateFormat } from 'date-fns';
@@ -937,22 +924,21 @@
import { openImportExportTab } from '../utility/importExportTools';
import { defaultDatabaseObjectAppObjectActions, matchDatabaseObjectAppObject } from './appObjectTools';
import { getSupportedScriptTemplates } from '../utility/applyScriptTemplate';
import { getBoolSettingsValue } from '../settings/settingsTools';
import { getBoolSettingsValue, getOpenDetailOnArrowsSettings } from '../settings/settingsTools';
import { isProApp } from '../utility/proTools';
export let data;
export let passProps;
function handleClick({ forceNewTab = false, tabPreviewMode = false, focusTab = false } = {}) {
handleDatabaseObjectClick(data, { forceNewTab, tabPreviewMode, focusTab });
}
function createMenu() {
return createDatabaseObjectMenu(data, passProps?.connection);
}
function getExtInfo(data) {
const res = [];
if (data.objectTypeField === 'triggers') {
res.push(`${data.tableName}, ${data.triggerTiming?.toLowerCase() ?? ''} ${data.eventType?.toLowerCase() ?? ''}`);
}
if (data.objectComment) {
res.push(data.objectComment);
}
@@ -981,9 +967,9 @@
onUnpin={isPinned ? () => pinnedTables.update(list => list.filter(x => !testEqual(x, data))) : null}
extInfo={getExtInfo(data)}
isChoosed={matchDatabaseObjectAppObject($selectedDatabaseObjectAppObject, data)}
on:click={() => handleClick({ tabPreviewMode: true })}
on:middleclick={() => handleClick({ forceNewTab: true })}
on:dblclick={() => handleClick({ tabPreviewMode: false, focusTab: true })}
on:click={() => handleObjectClick(data, 'leftClick')}
on:middleclick={() => handleObjectClick(data, 'middleClick')}
on:dblclick={() => handleObjectClick(data, 'dblClick')}
on:expand
on:dragstart
on:dragenter
@@ -6,13 +6,26 @@
import AppObjectCore from './AppObjectCore.svelte';
export let data;
function createParameterTitle(parameter) {
if (!parameter.parameterName) return parameter.position ?? null;
if (parameter.parameterName.startsWith('@')) return parameter.parameterName.substring(1);
return data.parameterName;
}
function createParameterExtInfo(parameter) {
if (parameter.parameterMode && parameter.parameterMode !== 'IN') {
return `${parameter.dataType} ${parameter.parameterMode}`;
}
return parameter.dataType;
}
</script>
<AppObjectCore
{...$$restProps}
{data}
title={data.parameterName?.startsWith('@') ? data.parameterName.substring(1) : data.parameterName}
extInfo={data.parameterMode && data.parameterMode !== 'IN' ? `${data.dataType} ${data.parameterMode}` : data.dataType}
title={createParameterTitle(data)}
extInfo={createParameterExtInfo(data)}
icon={'icon parameter'}
disableHover
/>
@@ -2,7 +2,7 @@
export const extractKey = ({ columnName }) => columnName;
export const createMatcher =
(filter, cfg = DEFAULT_SEARCH_SETTINGS) =>
(filter, cfg = DEFAULT_OBJECT_SEARCH_SETTINGS) =>
data => {
const filterArgs = [];
if (cfg.sqlObjectText) filterArgs.push(data.lineData);
@@ -15,7 +15,7 @@
<script lang="ts">
import AppObjectCore from './AppObjectCore.svelte';
import { filterName } from 'dbgate-tools';
import { DEFAULT_SEARCH_SETTINGS } from '../stores';
import { DEFAULT_OBJECT_SEARCH_SETTINGS } from '../stores';
export let data;
</script>
@@ -11,8 +11,11 @@
export let data;
export let passProps;
export let isExpandedOnlyBySearch;
export let isExpandedBySearch;
export let isExpanded;
export let isMainMatched;
$: isExpandedOnlyBySearch = isExpandedBySearch && !isExpanded;
$: databases = useDatabaseList({ conid: isExpandedOnlyBySearch ? null : data._id });
$: dbList = isExpandedOnlyBySearch ? getLocalStorage(`database_list_${data._id}`) || [] : $databases || [];
@@ -24,6 +27,6 @@
list={_.sortBy(dbList, x => x.sortOrder ?? x.name).map(db => ({ ...db, connection: data }))}
module={databaseAppObject}
{passProps}
{filter}
filter={isMainMatched ? '' : filter}
{isExpandedBySearch}
/>
@@ -60,6 +60,14 @@ export const defaultDatabaseObjectAppObjectActions = {
icon: 'img sql-file',
},
],
triggers: [
{
label: 'Show SQL',
tab: 'SqlObjectTab',
defaultActionId: 'showSql',
icon: 'img sql-file',
},
],
collections: [
{
label: 'Open data',
+18 -6
View File
@@ -7,20 +7,32 @@
export let icon = 'icon chevron-down';
export let menu;
export let asyncMenu = undefined;
export let narrow = false;
export let square = true;
export let disabled = false;
let domButton;
function handleClick() {
let domButton;
let isLoading = false;
async function handleClick() {
if (disabled) return;
let items = menu;
if (asyncMenu) {
isLoading = true;
items = await asyncMenu();
isLoading = false;
}
const rect = domButton.getBoundingClientRect();
const left = rect.left;
const top = rect.bottom;
currentDropDownMenu.set({ left, top, items: menu });
currentDropDownMenu.set({ left, top, items });
}
</script>
<InlineButton square {narrow} on:click={handleClick} bind:this={domButton} {disabled}>
<FontIcon {icon} />
<InlineButton {square} {narrow} on:click={handleClick} bind:this={domButton} {disabled}>
<FontIcon icon={isLoading ? 'icon loading' : icon} />
</InlineButton>
@@ -54,6 +54,8 @@
// don't parse JSON for explicit data types
$: jsonParsedValue = !editorTypes?.explicitDataType && isJsonLikeLongString(value) ? safeJsonParse(value) : null;
$: showHint = allowHintField && rowData && _.some(col.hintColumnNames, hintColumnName => rowData[hintColumnName]);
</script>
<td
@@ -68,11 +70,12 @@
class:isDeleted
class:isAutofillSelected
class:isFocusedColumn
class:alignRight={_.isNumber(value) && !showHint}
{style}
>
<CellValue {rowData} {value} {jsonParsedValue} {editorTypes} />
{#if allowHintField && rowData && _.some(col.hintColumnNames, hintColumnName => rowData[hintColumnName])}
{#if showHint}
<span class="hint"
>{col.hintColumnNames.map(hintColumnName => rowData[hintColumnName]).join(col.hintColumnDelimiter || ' ')}</span
>
@@ -199,4 +202,9 @@
overflow: visible;
cursor: crosshair;
}
.alignRight {
color: var(--theme-icon-green);
text-align: var(--data-grid-numbers-align);
}
</style>
+33 -3
View File
@@ -483,6 +483,7 @@
let domFocusField;
let domHorizontalScroll;
let domVerticalScroll;
let domContainer;
let currentCell = topLeftCell;
let selectedCells = [topLeftCell];
@@ -492,7 +493,7 @@
let autofillSelectedCells = emptyCellArray;
const domFilterControlsRef = createRef({});
let isGridFocused=false;
let isGridFocused = false;
const tabid = getContext('tabid');
@@ -596,6 +597,7 @@
selectedCells = [cell];
await tick();
scrollIntoView(cell);
domFocusField?.focus();
}
export async function cloneRows() {
@@ -1838,11 +1840,11 @@
{/if}
</div>
{:else if isDynamicStructure && isLoadedAll && grider?.rowCount == 0}
<div>
<div class="ml-2">
<ErrorInfo
alignTop
message={grider.editable
? 'No rows loaded, check filter or add new documents. You could copy documents from ohter collections/tables with Copy advanved/Copy as JSON command.'
? 'No rows loaded, check filter or add new documents. You could copy documents from other collections/tables with Copy advanved/Copy as JSON command.'
: 'No rows loaded'}
/>
{#if display.filterCount > 0}
@@ -1867,9 +1869,15 @@
class:data-grid-focused={isGridFocused}
bind:clientWidth={containerWidth}
bind:clientHeight={containerHeight}
bind:this={domContainer}
use:contextMenu={buildMenu}
use:contextMenuActivator={activator}
on:wheel={handleGridWheel}
on:click={e => {
if (e.target == domContainer) {
domFocusField?.focus();
}
}}
>
<input
type="text"
@@ -2014,6 +2022,24 @@
{/each}
</tbody>
</table>
{#if !isDynamicStructure && isLoadedAll && grider?.rowCount == 0}
<div class="no-rows-info ml-2">
<div class="mb-3">
<ErrorInfo alignTop message="No rows loaded" icon="img info" />
</div>
{#if display.filterCount > 0}
<FormStyledButton value="Reset filter" on:click={() => display.clearFilters()} />
{/if}
{#if grider.editable}
<FormStyledButton value="Add row" on:click={insertNewRow} />
{/if}
{#if onOpenQuery}
<FormStyledButton value="Open Query" on:click={onOpenQuery} />
{/if}
</div>
{/if}
<HorizontalScrollBar
minimum={0}
maximum={maxScrollColumn}
@@ -2092,4 +2118,8 @@
right: 40px;
bottom: 20px;
}
.no-rows-info {
margin-top: 60px;
}
</style>
@@ -9,7 +9,7 @@
import SearchBoxWrapper from '../elements/SearchBoxWrapper.svelte';
import SearchInput from '../elements/SearchInput.svelte';
import FontIcon from '../icons/FontIcon.svelte';
import ColumnManagerRow from './ColumnManagerRow.svelte';
import TokenizedFilteredText from '../widgets/TokenizedFilteredText.svelte';
export let managerSize;
export let display: GridDisplay;
@@ -21,7 +21,6 @@
$: foreignKeys = display?.baseTable?.foreignKeys || [];
$: dependencies = display?.baseTable?.dependencies || [];
</script>
<SearchBoxWrapper>
@@ -46,7 +45,7 @@
>
<FontIcon icon="img link" />
<div class="ml-1 nowrap">
{fk.refTableName}
<TokenizedFilteredText text={fk.refTableName} {filter} />
({fk.columns.map(x => x.columnName).join(', ')})
</div>
</div>
@@ -70,7 +69,7 @@
>
<FontIcon icon="img reference" />
<div class="ml-1 nowrap">
{fk.pureName}
<TokenizedFilteredText text={fk.pureName} {filter} />
({fk.columns.map(x => x.columnName).join(', ')})
</div>
</div>
@@ -89,5 +88,4 @@
.link:hover {
text-decoration: underline;
}
</style>
@@ -9,6 +9,7 @@
export let disabled = false;
export let defaultValue;
export let menu;
export let asyncMenu;
const { values, setFieldValue } = getFormContext();
@@ -26,5 +27,5 @@
value={$values[name] ?? defaultValue}
on:input={e => setFieldValue(name, e.target['value'])}
/>
<DropDownButton {menu} {disabled} />
<DropDownButton {menu} {asyncMenu} {disabled} />
</div>
+4
View File
@@ -64,6 +64,7 @@
'icon add-folder': 'mdi mdi-folder-plus-outline',
'icon add-column': 'mdi mdi-table-column-plus-after',
'icon parameter': 'mdi mdi-at',
'icon trigger': 'mdi mdi-lightning-bolt',
'icon window-restore': 'mdi mdi-window-restore',
'icon window-maximize': 'mdi mdi-window-maximize',
@@ -287,6 +288,9 @@
'img import': 'mdi mdi-database-import color-icon-green',
'img export': 'mdi mdi-database-export color-icon-green',
'img transform': 'mdi mdi-rotate-orbit color-icon-blue',
'img tip': 'mdi mdi-lightbulb-on color-icon-yellow',
'img filter-active': 'mdi mdi-filter-cog color-icon-blue',
};
</script>
+4 -4
View File
@@ -82,7 +82,7 @@
submenuOffset = hoverOffset;
return;
}
if (item.switchStore) {
if (item.switchStore && item.switchValue) {
item.switchStore.update(x => ({
...x,
[item.switchValue]: !x[item.switchValue],
@@ -142,12 +142,12 @@
>
<a on:click={e => handleClick(e, item)} class:disabled={item.disabled} class:bold={item.isBold}>
<span>
{#if item.switchStoreGetter}
{#if item.switchValue && item.switchStoreGetter}
{#key switchIndex}
{#if item.switchStoreGetter()[item.switchValue]}
<FontIcon icon="icon checkbox-marked" padRight />
<FontIcon icon="icon check" padRight />
{:else}
<FontIcon icon="icon checkbox-blank" padRight />
<FontIcon icon="icon invisible-box" padRight />
{/if}
{/key}
{/if}
@@ -16,8 +16,12 @@
import FormColorField from '../forms/FormColorField.svelte';
import FontIcon from '../icons/FontIcon.svelte';
import FormDropDownTextField from '../forms/FormDropDownTextField.svelte';
import { getConnectionLabel } from 'dbgate-tools';
const { values } = getFormContext();
export let getDatabaseList;
export let currentConnection;
const { values, setFieldValue } = getFormContext();
const electron = getElectron();
$: authType = $values.authType;
@@ -69,6 +73,14 @@
'me-central-1',
'sa-east-1',
];
async function createDatabasesMenu() {
const databases = await getDatabaseList();
return databases.map(db => ({
text: db.name,
onClick: () => setFieldValue('defaultDatabase', db.name),
}));
}
</script>
<FormSelectField
@@ -377,11 +389,13 @@
{/if}
{#if driver?.showConnectionField('defaultDatabase', $values, showConnectionFieldArgs)}
<FormTextField
<FormDropDownTextField
label="Default database"
name="defaultDatabase"
disabled={isConnected}
data-testid="ConnectionDriverFields_defaultDatabase"
asyncMenu={createDatabasesMenu}
placeholder="(not selected - optional)"
/>
{/if}
@@ -412,7 +426,8 @@
templateProps={{ noMargin: true }}
disabled={isConnected}
data-testid="ConnectionDriverFields_displayName"
/>
placeholder={getConnectionLabel(currentConnection)}
/>
</div>
<div class="col-6 mr-1">
<FormColorField
@@ -28,7 +28,12 @@
$: isConnected = $openedConnections.includes($values._id) || $openedSingleDatabaseConnections.includes($values._id);
</script>
<FormCheckboxField label="Use SSH tunnel" name="useSshTunnel" disabled={isConnected} />
<FormCheckboxField
label="Use SSH tunnel"
name="useSshTunnel"
disabled={isConnected}
data-testid="ConnectionSshTunnelFields_useSshTunnel"
/>
<div class="row">
<div class="col-9 mr-1">
@@ -37,6 +42,7 @@
name="sshHost"
disabled={isConnected || !useSshTunnel}
templateProps={{ noMargin: true }}
data-testid="ConnectionSshTunnelFields_sshHost"
/>
</div>
<div class="col-3">
@@ -46,6 +52,7 @@
disabled={isConnected || !useSshTunnel}
templateProps={{ noMargin: true }}
placeholder="22"
data-testid="ConnectionSshTunnelFields_sshPort"
/>
</div>
</div>
@@ -62,10 +69,16 @@
{ value: 'agent', label: 'SSH agent' },
{ value: 'keyFile', label: 'Key file' },
]}
data-testid="ConnectionSshTunnelFields_sshMode"
/>
{#if ($values.sshMode || 'userPassword') != 'userPassword'}
<FormTextField label="Login" name="sshLogin" disabled={isConnected || !useSshTunnel} />
<FormTextField
label="Login"
name="sshLogin"
disabled={isConnected || !useSshTunnel}
data-testid="ConnectionSshTunnelFields_sshLogin"
/>
{/if}
{#if ($values.sshMode || 'userPassword') == 'userPassword'}
@@ -76,6 +89,7 @@
name="sshLogin"
disabled={isConnected || !useSshTunnel}
templateProps={{ noMargin: true }}
data-testid="ConnectionSshTunnelFields_sshLogin"
/>
</div>
<div class="col-6">
@@ -84,6 +98,7 @@
name="sshPassword"
disabled={isConnected || !useSshTunnel}
templateProps={{ noMargin: true }}
data-testid="ConnectionSshTunnelFields_sshPassword"
/>
</div>
</div>
@@ -99,6 +114,7 @@
disabled={isConnected || !useSshTunnel}
templateProps={{ noMargin: true }}
defaultFileName={$platformInfo?.defaultKeyfile}
data-testid="ConnectionSshTunnelFields_sshKeyfile"
/>
{:else}
<FormTextField
@@ -107,6 +123,7 @@
disabled={isConnected || !useSshTunnel}
templateProps={{ noMargin: true }}
placeholder={$platformInfo?.defaultKeyfile}
data-testid="ConnectionSshTunnelFields_sshKeyfile"
/>
{/if}
</div>
@@ -116,6 +133,7 @@
name="sshKeyfilePassword"
disabled={isConnected || !useSshTunnel}
templateProps={{ noMargin: true }}
data-testid="ConnectionSshTunnelFields_sshKeyfilePassword"
/>
</div>
</div>
+26 -1
View File
@@ -100,7 +100,7 @@ ORDER BY
{ label: 'Connection', slot: 2 },
{ label: 'Themes', slot: 3 },
{ label: 'Default Actions', slot: 4 },
{ label: 'Confirmations', slot: 5 },
{ label: 'Behaviour', slot: 5 },
{ label: 'Other', slot: 6 },
]}
>
@@ -138,6 +138,8 @@ ORDER BY
defaultValue="10"
/>
<FormCheckboxField name="dataGrid.alignNumbersRight" label="Align numbers to right" defaultValue={false} />
<div class="heading">SQL editor</div>
<div class="flex">
@@ -331,6 +333,24 @@ ORDER BY
/>
</svelte:fragment>
<svelte:fragment slot="5">
<div class="heading">Behaviour</div>
<FormCheckboxField name="behaviour.useTabPreviewMode" label="Use tab preview mode" defaultValue={true} />
<div class="tip">
<FontIcon icon="img tip" /> When you single-click or select a file in the "Tables, Views, Functions" view, it
is shown in a preview mode and reuses an existing tab (preview tab). This is useful if you are quickly browsing
tables and don't want every visited table to have its own tab. When you start editing the table or use double-click
to open the table from the "Tables" view, a new tab is dedicated to that table.
</div>
<FormCheckboxField
name="behaviour.openDetailOnArrows"
label="Open detail on keyboard navigation"
defaultValue={true}
disabled={values['behaviour.useTabPreviewMode'] === false}
/>
<div class="heading">Confirmations</div>
<FormCheckboxField name="skipConfirm.tableDataSave" label="Skip confirmation when saving table data (SQL)" />
@@ -405,6 +425,11 @@ ORDER BY
margin-top: var(--dim-large-form-margin);
}
.tip {
margin-left: var(--dim-large-form-margin);
margin-top: var(--dim-large-form-margin);
}
.themes {
overflow-x: scroll;
display: flex;
@@ -36,3 +36,10 @@ export function getConnectionClickActionSetting(): 'connect' | 'openDetails' | '
export function getDatabaseClickActionSetting(): 'switch' | 'none' {
return getStringSettingsValue('defaultAction.databaseClick', 'switch');
}
export function getOpenDetailOnArrowsSettings(): boolean {
return (
getBoolSettingsValue('behaviour.useTabPreviewMode', true) &&
getBoolSettingsValue('behaviour.openDetailOnArrows', true)
);
}
+34 -12
View File
@@ -161,23 +161,33 @@ export const lastUsedDefaultActions = writableWithStorage({}, 'lastUsedDefaultAc
export const selectedDatabaseObjectAppObject = writable(null);
export const focusedConnectionOrDatabase = writable<{ conid: string; database?: string; connection: any }>(null);
export const DEFAULT_SEARCH_SETTINGS = {
collectionName: true,
export const DEFAULT_OBJECT_SEARCH_SETTINGS = {
pureName: true,
schemaName: false,
tableName: true,
viewName: true,
columnName: true,
columnName: false,
columnDataType: false,
tableComment: true,
columnComment: true,
sqlObjectName: true,
sqlObjectText: true,
columnComment: false,
sqlObjectText: false,
tableEngine: false,
};
export const DEFAULT_CONNECTION_SEARCH_SETTINGS = {
displayName: true,
server: true,
user: false,
engine: false,
database: true,
};
export const databaseObjectAppObjectSearchSettings = writableWithStorage(
DEFAULT_SEARCH_SETTINGS,
'databaseObjectAppObjectSearchSettings'
DEFAULT_OBJECT_SEARCH_SETTINGS,
'databaseObjectAppObjectSearchSettings2'
);
export const connectionAppObjectSearchSettings = writableWithStorage(
DEFAULT_CONNECTION_SEARCH_SETTINGS,
'connectionAppObjectSearchSettings2'
);
export const currentThemeDefinition = derived([currentTheme, extensions], ([$currentTheme, $extensions]) =>
@@ -205,6 +215,9 @@ export const visibleTitleBar = derived(useSettings(), $settings => {
// console.log('nativeMenuOnStartup', nativeMenuOnStartup);
return !$settings['app.fullscreen'] && !nativeMenuOnStartup;
});
export const alignDataGridNumbersToRight = derived(useSettings(), $settings => {
return !!$settings?.['dataGrid.alignNumbersRight'];
});
export const visibleHamburgerMenuWidget = derived(useSettings(), $settings => {
const electron = getElectron();
@@ -218,6 +231,7 @@ subscribeCssVariable(visibleSelectedWidget, x => (x ? 1 : 0), '--dim-visible-lef
subscribeCssVariable(leftPanelWidth, x => `${x}px`, '--dim-left-panel-width');
subscribeCssVariable(visibleTitleBar, x => (x ? 1 : 0), '--dim-visible-titlebar');
subscribeCssVariable(lockedDatabaseMode, x => (x ? 0 : 1), '--dim-visible-tabs-databases');
subscribeCssVariable(alignDataGridNumbersToRight, x => (x ? 'right' : 'left'), '--data-grid-numbers-align');
let activeTabIdValue = null;
activeTabId.subscribe(value => {
@@ -379,10 +393,18 @@ lastUsedDefaultActions.subscribe(value => {
});
export const getLastUsedDefaultActions = () => lastUsedDefaultActionsValue;
let databaseObjectAppObjectSearchSettingsValue: typeof DEFAULT_SEARCH_SETTINGS = {
...DEFAULT_SEARCH_SETTINGS,
let databaseObjectAppObjectSearchSettingsValue: typeof DEFAULT_OBJECT_SEARCH_SETTINGS = {
...DEFAULT_OBJECT_SEARCH_SETTINGS,
};
databaseObjectAppObjectSearchSettings.subscribe(value => {
databaseObjectAppObjectSearchSettingsValue = value;
});
export const getDatabaseObjectAppObjectSearchSettings = () => databaseObjectAppObjectSearchSettingsValue;
let connectionAppObjectSearchSettingsValue: typeof DEFAULT_CONNECTION_SEARCH_SETTINGS = {
...DEFAULT_CONNECTION_SEARCH_SETTINGS,
};
connectionAppObjectSearchSettings.subscribe(value => {
connectionAppObjectSearchSettingsValue = value;
});
export const getConnectionAppObjectSearchSettings = () => connectionAppObjectSearchSettingsValue;
+34 -14
View File
@@ -63,15 +63,16 @@
const testIdRef = createRef(0);
async function handleTest(e) {
async function handleTest(e, requestDbList = false) {
isTesting = true;
testIdRef.update(x => x + 1);
const testid = testIdRef.get();
const resp = await apiCall('connections/test', e.detail);
const resp = await apiCall('connections/test', { connection: e.detail, requestDbList });
if (testIdRef.get() != testid) return;
isTesting = false;
sqlConnectResult = resp;
return resp;
}
function handleCancelTest() {
@@ -80,6 +81,10 @@
}
function getCurrentConnection() {
return getCurrentConnectionCore($values, driver);
}
function getCurrentConnectionCore(values, driver) {
const allProps = [
'databaseFile',
'useDatabaseUrl',
@@ -94,15 +99,15 @@
'socketPath',
'serviceName',
];
const visibleProps = allProps.filter(x => driver?.showConnectionField(x, $values, { config: $config }));
const visibleProps = allProps.filter(x => driver?.showConnectionField(x, values, { config: $config }));
const omitProps = _.difference(allProps, visibleProps);
if (!$values.defaultDatabase) omitProps.push('singleDatabase');
if (!values.defaultDatabase) omitProps.push('singleDatabase');
let connection: Dictionary<string | boolean> = _.omit($values, omitProps);
let connection: Dictionary<string | boolean> = _.omit(values, omitProps);
if (driver?.beforeConnectionSave) connection = driver?.beforeConnectionSave(connection);
if (driver?.showConnectionTab('sshTunnel', $values)) {
if (!$values.useSshTunnel) {
if (driver?.showConnectionTab('sshTunnel', values)) {
if (!values.useSshTunnel) {
connection = _.omitBy(connection, (v, k) => k.startsWith('ssh'));
}
} else {
@@ -110,8 +115,8 @@
connection = _.omitBy(connection, (v, k) => k.startsWith('ssh'));
}
if (driver?.showConnectionTab('ssl', $values)) {
if (!$values.useSsl) {
if (driver?.showConnectionTab('ssl', values)) {
if (!values.useSsl) {
connection = _.omitBy(connection, (v, k) => k.startsWith('ssl'));
}
} else {
@@ -122,6 +127,8 @@
return connection;
}
$: currentConnection = getCurrentConnectionCore($values, driver);
async function handleSave() {
let connection = getCurrentConnection();
connection = {
@@ -190,6 +197,14 @@
$: isConnected = $openedConnections.includes($values._id) || $openedSingleDatabaseConnections.includes($values._id);
// $: console.log('CONN VALUES', $values);
async function getDatabaseList() {
const resp = await handleTest({ detail: getCurrentConnection() }, true);
if (resp && resp.msgtype == 'connected') {
return resp.databases;
}
return [];
}
</script>
<FormProviderCore template={FormFieldTemplateLarge} {values}>
@@ -202,6 +217,7 @@
{
label: 'General',
component: ConnectionDriverFields,
props: { getDatabaseList, currentConnection },
},
driver?.showConnectionTab('sshTunnel', $values) && {
label: 'SSH Tunnel',
@@ -223,20 +239,24 @@
<div class="buttons">
{#if onlyTestButton}
{#if isTesting}
<FormButton value="Cancel test" on:click={handleCancelTest} data-testid="ConnectionTab_buttonCancelTest" />
<FormButton
value="Cancel test"
on:click={handleCancelTest}
data-testid="ConnectionTab_buttonCancelTest"
/>
{:else}
<FormButton value="Test connection" on:click={handleTest} data-testid="ConnectionTab_buttonDisconnect" />
{/if}
{:else if isConnected}
<FormButton value="Disconnect" on:click={handleDisconnect} data-testid='ConnectionTab_buttonDisconnect' />
<FormButton value="Disconnect" on:click={handleDisconnect} data-testid="ConnectionTab_buttonDisconnect" />
{:else}
<FormButton value="Connect" on:click={handleConnect} data-testid='ConnectionTab_buttonConnect' />
<FormButton value="Connect" on:click={handleConnect} data-testid="ConnectionTab_buttonConnect" />
{#if isTesting}
<FormButton value="Cancel test" on:click={handleCancelTest} />
{:else}
<FormButton value="Test" on:click={handleTest} data-testid='ConnectionTab_buttonTest' />
<FormButton value="Test" on:click={handleTest} data-testid="ConnectionTab_buttonTest" />
{/if}
<FormButton value="Save" on:click={handleSave} data-testid='ConnectionTab_buttonSave' />
<FormButton value="Save" on:click={handleSave} data-testid="ConnectionTab_buttonSave" />
{/if}
</div>
<div class="test-result">
@@ -166,6 +166,13 @@ export function getSupportedScriptTemplates(objectTypeField: string): { label: s
scriptTemplate: 'CALL OBJECT',
},
];
case 'triggers':
return [
{
label: 'CREATE TRIGGER',
scriptTemplate: 'CREATE OBJECT',
},
];
}
return [];
+8
View File
@@ -7,6 +7,7 @@ import localforage from 'localforage';
import stableStringify from 'json-stable-stringify';
import { saveAllPendingEditorData } from '../query/useEditorData';
import { getConnectionInfo } from './metadataLoaders';
import { getBoolSettingsValue } from '../settings/settingsTools';
function findFreeNumber(numbers: number[]) {
if (numbers.length == 0) return 1;
@@ -22,6 +23,13 @@ export default async function openNewTab(newTab, initialData: any = undefined, o
let existing = null;
if (!getBoolSettingsValue('behaviour.useTabPreviewMode', true) && newTab.tabPreviewMode) {
newTab = {
...newTab,
tabPreviewMode: false,
};
}
const { savedFile, savedFolder, savedFilePath, conid, database } = newTab.props || {};
if (conid && database) {
@@ -16,6 +16,7 @@
let isListFocused = false;
let domDiv = null;
let lastInputMethod = null;
export let hideContent = false;
function handleKeyDown(ev) {
@@ -25,6 +26,11 @@
const selected = getSelectedObject();
const index = _.findIndex(listInstance, x => selectedObjectMatcher(x, selected));
if (index < 0) {
focusFirst();
return;
}
if (index == 0 && diff < 0) {
onFocusFilterBox?.();
return;
@@ -41,7 +47,7 @@
if (listInstance[newIndex]) {
selectedObjectStore.set(listInstance[newIndex]);
handleObjectClick?.(listInstance[newIndex], { tabPreviewMode: true });
handleObjectClick?.(listInstance[newIndex], 'keyArrow');
}
if (newIndex == 0) {
@@ -58,7 +64,7 @@
ev.preventDefault();
}
if (ev.keyCode == keycodes.enter) {
handleObjectClick?.(getSelectedObject(), { tabPreviewMode: false, focusTab: true });
handleObjectClick?.(getSelectedObject(), 'keyEnter');
ev.preventDefault();
}
if (ev.keyCode == keycodes.pageDown) {
@@ -72,14 +78,14 @@
if (ev.keyCode == keycodes.home) {
if (listInstance[0]) {
selectedObjectStore.set(listInstance[0]);
handleObjectClick?.(listInstance[0], { tabPreviewMode: true });
handleObjectClick?.(listInstance[0], 'keyArrow');
onScrollTop?.();
}
}
if (ev.keyCode == keycodes.end) {
if (listInstance[listInstance.length - 1]) {
selectedObjectStore.set(listInstance[listInstance.length - 1]);
handleObjectClick?.(listInstance[listInstance.length - 1], { tabPreviewMode: true });
handleObjectClick?.(listInstance[listInstance.length - 1], 'keyArrow');
}
}
if (ev.keyCode == keycodes.numPadAdd) {
@@ -110,17 +116,18 @@
domDiv?.focus();
if (listInstance[0]) {
selectedObjectStore.set(listInstance[0]);
handleObjectClick?.(listInstance[0], { tabPreviewMode: true });
handleObjectClick?.(listInstance[0], 'keyArrow');
onScrollTop?.();
}
}
async function handleFocus() {
async function handleFocus(e) {
isListFocused = true;
// await tick();
await sleep(100);
// console.log('ON FOCUS AFTER SLEEP');
if (lastInputMethod == 'mouse') {
return;
}
const listInstance = _.isFunction(list) ? list() : list;
const selected = getSelectedObject();
const index = _.findIndex(listInstance, x => selectedObjectMatcher(x, selected));
@@ -130,7 +137,7 @@
const index2 = _.findIndex(listInstance, x => selectedObjectMatcher(x, focused));
if (index2 >= 0) {
selectedObjectStore.set(focused);
handleObjectClick?.(focused, { tabPreviewMode: true });
handleObjectClick?.(focused, 'keyArrow');
return;
}
}
@@ -139,6 +146,15 @@
}
</script>
<svelte:window
on:keydown={() => {
lastInputMethod = 'keyboard';
}}
on:mousedown={() => {
lastInputMethod = 'mouse';
}}
/>
<div
tabindex="0"
on:keydown={handleKeyDown}
+49 -13
View File
@@ -20,6 +20,8 @@
getFocusedConnectionOrDatabase,
currentDatabase,
getCurrentConfig,
connectionAppObjectSearchSettings,
getConnectionAppObjectSearchSettings,
} from '../stores';
import runCommand from '../commands/runCommand';
import { filterName, getConnectionLabel } from 'dbgate-tools';
@@ -38,7 +40,13 @@
import { switchCurrentDatabase } from '../utility/common';
import openNewTab from '../utility/openNewTab';
import { openConnection } from '../appobj/ConnectionAppObject.svelte';
import { getConnectionClickActionSetting } from '../settings/settingsTools';
import {
getBoolSettingsValue,
getConnectionClickActionSetting,
getDatabaseClickActionSetting,
getOpenDetailOnArrowsSettings,
} from '../settings/settingsTools';
import DropDownButton from '../buttons/DropDownButton.svelte';
const connections = useConnectionList();
const serverStatus = useServerStatus();
@@ -182,6 +190,21 @@
{ text: 'Delete', onClick: handleDelete },
];
}
function createSearchMenu() {
const res = [];
res.push({ label: 'Search by:', isBold: true, disabled: true });
res.push({ label: 'Display name', switchValue: 'displayName' });
res.push({ label: 'Server', switchValue: 'server' });
res.push({ label: 'User', switchValue: 'user' });
res.push({ label: 'Database engine', switchValue: 'engine' });
res.push({ label: 'Database name', switchValue: 'database' });
return res.map(item => ({
...item,
switchStore: connectionAppObjectSearchSettings,
switchStoreGetter: getConnectionAppObjectSearchSettings,
}));
}
</script>
<SearchBoxWrapper>
@@ -194,6 +217,12 @@
}}
/>
<CloseSearchButton bind:filter />
<DropDownButton
icon={filter ? 'img filter-active' : 'icon filter'}
menu={createSearchMenu}
square={!!filter}
narrow={false}
/>
{#if $commandsCustomized['new.connection']?.enabled}
<InlineButton
on:click={() => runCommand('new.connection')}
@@ -239,30 +268,35 @@
onFocusFilterBox={text => {
domFilter?.focus(text);
}}
handleObjectClick={(data, options) => {
handleObjectClick={(data, clickAction) => {
const connectionClickAction = getConnectionClickActionSetting();
const databaseClickAction = getDatabaseClickActionSetting();
const openDetailOnArrows = getOpenDetailOnArrowsSettings();
if (data.database) {
if (options.focusTab) {
if ($openedSingleDatabaseConnections.includes(data.conid)) {
switchCurrentDatabase({ connection: data.connection, name: data.database });
} else {
switchCurrentDatabase({ connection: data.connection, name: data.database });
}
// console.log('FOCUSING DB', passProps);
// passProps?.onFocusSqlObjectList?.();
if (databaseClickAction == 'switch' && clickAction == 'leftClick') {
switchCurrentDatabase({ connection: data.connection, name: data.database });
}
if (clickAction == 'keyEnter' || clickAction == 'dblClick') {
switchCurrentDatabase({ connection: data.connection, name: data.database });
}
} else {
if (options.focusTab) {
if (clickAction == 'keyEnter' || clickAction == 'dblClick') {
openConnection(data.connection);
} else {
const config = getCurrentConfig();
if (config.runAsPortal == false && !config.storageDatabase && connectionClickAction == 'openDetails') {
if (
config.runAsPortal == false &&
!config.storageDatabase &&
connectionClickAction == 'openDetails' &&
(clickAction == 'leftClick' || (clickAction == 'keyArrow' && openDetailOnArrows))
) {
openNewTab({
title: getConnectionLabel(data.connection),
icon: 'img connection',
tabComponent: 'ConnectionTab',
tabPreviewMode: options.tabPreviewMode,
tabPreviewMode: true,
props: {
conid: data.conid,
},
@@ -289,6 +323,7 @@
...passProps,
connectionColorFactory: $connectionColorFactory,
showPinnedInsteadOfUnpin: true,
searchSettings: $connectionAppObjectSearchSettings,
}}
getIsExpanded={data => $expandedConnections.includes(data._id) && !data.singleDatabase}
setIsExpanded={(data, value) => {
@@ -316,6 +351,7 @@
passProps={{
connectionColorFactory: $connectionColorFactory,
showPinnedInsteadOfUnpin: true,
searchSettings: $connectionAppObjectSearchSettings,
}}
getIsExpanded={data => $expandedConnections.includes(data._id) && !data.singleDatabase}
setIsExpanded={(data, value) => {
@@ -13,6 +13,7 @@
import { filterName } from 'dbgate-tools';
import { currentDatabase, focusedConnectionOrDatabase, getFocusedConnectionOrDatabase } from '../stores';
import { switchCurrentDatabase } from '../utility/common';
import { getConnectionClickActionSetting, getDatabaseClickActionSetting } from '../settings/settingsTools';
export let connection;
@@ -81,9 +82,16 @@
onFocusFilterBox={text => {
domFilter?.focus(text);
}}
handleObjectClick={(data, options) => {
handleObjectClick={(data, clickAction) => {
const connectionClickAction = getConnectionClickActionSetting();
const databaseClickAction = getDatabaseClickActionSetting();
if (data.database) {
if (options.focusTab) {
if (databaseClickAction == 'switch' && clickAction == 'leftClick') {
switchCurrentDatabase({ connection: data.connection, name: data.database });
}
if (clickAction == 'keyEnter' || clickAction == 'dblClick') {
switchCurrentDatabase({ connection: data.connection, name: data.database });
}
}
+13 -11
View File
@@ -80,7 +80,7 @@
// $: console.log('OBJECTS', $objects);
$: objectList = _.flatten([
...['tables', 'collections', 'views', 'matviews', 'procedures', 'functions'].map(objectTypeField =>
...['tables', 'collections', 'views', 'matviews', 'procedures', 'functions', 'triggers'].map(objectTypeField =>
_.sortBy(
(($objects || {})[objectTypeField] || []).map(obj => ({ ...obj, objectTypeField })),
['schemaName', 'pureName']
@@ -129,19 +129,18 @@
function createSearchMenu() {
const res = [];
res.push({ label: 'Search by:', isBold: true, disabled: true });
if (driver?.databaseEngineTypes?.includes('document')) {
res.push({ label: 'Collection names' });
res.push({ label: 'Collection name', switchValue: 'pureName' });
}
if (driver?.databaseEngineTypes?.includes('sql')) {
res.push({ label: 'Schema name', switchValue: 'schemaName' });
res.push({ label: 'Table name', switchValue: 'tableName' });
res.push({ label: 'View name', switchValue: 'viewName' });
res.push({ label: 'Table/view/procedure name', switchValue: 'pureName' });
res.push({ label: 'Schema', switchValue: 'schemaName' });
res.push({ label: 'Column name', switchValue: 'columnName' });
res.push({ label: 'Column data type', switchValue: 'columnType' });
res.push({ label: 'Table comment', switchValue: 'tableComment' });
res.push({ label: 'Column comment', switchValue: 'columnComment' });
res.push({ label: 'Procedure/function/trigger name', switchValue: 'sqlObjectName' });
res.push({ label: 'Procedure/function/trigger text', switchValue: 'sqlObjectText' });
res.push({ label: 'View/procedure/trigger text', switchValue: 'sqlObjectText' });
res.push({ label: 'Table engine', switchValue: 'tableEngine' });
}
return res.map(item => ({
@@ -216,9 +215,12 @@
}}
/>
<CloseSearchButton bind:filter />
{#if filter}
<DropDownButton icon="icon filter" menu={createSearchMenu} />
{/if}
<DropDownButton
icon={filter ? 'img filter-active' : 'icon filter'}
menu={createSearchMenu}
square={!!filter}
narrow={false}
/>
{#if !filter}
<DropDownButton icon="icon plus-thick" menu={createAddMenu} />
{/if}
@@ -250,7 +252,7 @@
selectedObjectStore={selectedDatabaseObjectAppObject}
getSelectedObject={getSelectedDatabaseObjectAppObject}
selectedObjectMatcher={matchDatabaseObjectAppObject}
handleObjectClick={(data, options) => databaseObjectAppObject.handleObjectClick(data, options)}
handleObjectClick={(data, clickAction) => databaseObjectAppObject.handleObjectClick(data, clickAction)}
onScrollTop={() => {
domContainer?.scrollTop();
}}
+22
View File
@@ -0,0 +1,22 @@
diff --git a/node_modules/ace-builds/src-noconflict/mode-sqlserver.js b/node_modules/ace-builds/src-noconflict/mode-sqlserver.js
index 7e61d3d..3e0fb97 100644
--- a/node_modules/ace-builds/src-noconflict/mode-sqlserver.js
+++ b/node_modules/ace-builds/src-noconflict/mode-sqlserver.js
@@ -304,7 +304,7 @@ var BaseFoldMode = require("./cstyle").FoldMode;
var FoldMode = exports.FoldMode = function () { };
oop.inherits(FoldMode, BaseFoldMode);
(function () {
- this.foldingStartMarker = /(\bCASE\b|\bBEGIN\b)|^\s*(\/\*)/i;
+ this.foldingStartMarker = /(?<!\[)(\bCASE\b|\bBEGIN\b)(?!\])|^\s*(\/\*)/i;
this.startRegionRe = /^\s*(\/\*|--)#?region\b/;
this.getFoldWidgetRange = function (session, foldStyle, row, forceMultiline) {
var line = session.getLine(row);
@@ -337,7 +337,7 @@ oop.inherits(FoldMode, BaseFoldMode);
var maxRow = session.getLength();
var line;
var depth = 1;
- var re = /(\bCASE\b|\bBEGIN\b)|(\bEND\b)/i;
+ var re = /(?<!\[)(\bCASE\b|\bBEGIN\b)|(\bEND\b)(?!\])/i;
while (++row < maxRow) {
line = session.getLine(row);
var m = re.exec(line);
+2 -2
View File
@@ -37,13 +37,13 @@
},
"dependencies": {
"bson": "^6.8.0",
"dbgate-query-splitter": "^4.11.2",
"dbgate-query-splitter": "^4.11.3",
"dbgate-tools": "^6.0.0-alpha.1",
"is-promise": "^4.0.0",
"lodash": "^4.17.21",
"mongodb": "^6.3.0"
},
"optionalDependencies": {
"mongodb-client-encryption": "^6.0.0"
"mongodb-client-encryption": "^6.1.1"
}
}
+1 -1
View File
@@ -37,7 +37,7 @@
},
"dependencies": {
"async-lock": "^1.2.6",
"dbgate-query-splitter": "^4.11.2",
"dbgate-query-splitter": "^4.11.3",
"dbgate-tools": "^6.0.0-alpha.1",
"lodash": "^4.17.21",
"tedious": "^18.2.0"
@@ -132,6 +132,9 @@ class MsSqlAnalyser extends DatabaseAnalyser {
const procedureParameterRows = await this.analyserQuery('proceduresParameters');
const functionParameterRows = await this.analyserQuery('functionParameters');
this.feedback({ analysingMessage: 'Loading triggers' });
const triggerRows = await this.analyserQuery('triggers');
this.feedback({ analysingMessage: 'Loading view columns' });
const viewColumnRows = await this.analyserQuery('viewColumns', ['views']);
@@ -214,12 +217,24 @@ class MsSqlAnalyser extends DatabaseAnalyser {
parameters: functionToParameters[row.objectId],
}));
const triggers = triggerRows.rows.map(row => ({
objectId: `triggers:${row.objectId}`,
contentHash: row.modifyDate && row.modifyDate.toISOString(),
createSql: row.definition,
triggerTiming: row.triggerTiming,
eventType: row.eventType,
schemaName: row.schemaName,
tableName: row.tableName,
pureName: row.triggerName,
}));
this.feedback({ analysingMessage: null });
return {
tables,
views,
procedures,
functions,
triggers,
};
}
@@ -12,6 +12,7 @@ const functionParameters = require('./functionParameters');
const viewColumns = require('./viewColumns');
const indexes = require('./indexes');
const indexcols = require('./indexcols');
const triggers = require('./triggers');
module.exports = {
columns,
@@ -28,4 +29,5 @@ module.exports = {
indexes,
indexcols,
tableSizes,
triggers,
};
@@ -2,6 +2,6 @@ module.exports = `
select o.object_id as objectId, o.modify_date as modifyDate, o.type, o.name as pureName, s.name as schemaName
from sys.objects o
inner join sys.schemas s on o.schema_id = s.schema_id
where o.type in ('U', 'V', 'P', 'IF', 'FN', 'TF') -- , 'TR' - triggers disabled
where o.type in ('U', 'V', 'P', 'IF', 'FN', 'TF', 'TR')
and s.name =SCHEMA_NAME_CONDITION
`;
@@ -0,0 +1,28 @@
module.exports = `
SELECT
o.modify_date as modifyDate,
o.object_id as objectId,
o.name AS triggerName,
s.name AS schemaName,
OBJECT_NAME(o.parent_object_id) AS tableName,
CASE
WHEN OBJECTPROPERTY(o.object_id, 'ExecIsAfterTrigger') = 1 THEN 'AFTER'
WHEN OBJECTPROPERTY(o.object_id, 'ExecIsInsteadOfTrigger') = 1 THEN 'INSTEAD OF'
ELSE 'BEFORE'
END AS triggerTiming,
CASE
WHEN OBJECTPROPERTY(o.object_id, 'ExecIsInsertTrigger') = 1 THEN 'INSERT'
WHEN OBJECTPROPERTY(o.object_id, 'ExecIsUpdateTrigger') = 1 THEN 'UPDATE'
WHEN OBJECTPROPERTY(o.object_id, 'ExecIsDeleteTrigger') = 1 THEN 'DELETE'
END AS eventType,
OBJECT_DEFINITION(o.object_id) AS definition
FROM sys.objects o
INNER JOIN sys.tables t
ON o.parent_object_id = t.object_id
INNER JOIN sys.schemas s
ON t.schema_id = s.schema_id
WHERE o.type = 'TR'
AND o.is_ms_shipped = 0
AND o.object_id =OBJECT_ID_CONDITION
AND s.name =SCHEMA_NAME_CONDITION
`;
+1 -1
View File
@@ -37,7 +37,7 @@
},
"dependencies": {
"antares-mysql-dumper": "^0.0.1",
"dbgate-query-splitter": "^4.11.2",
"dbgate-query-splitter": "^4.11.3",
"dbgate-tools": "^6.0.0-alpha.1",
"lodash": "^4.17.21",
"mysql2": "^3.11.3"
@@ -160,6 +160,10 @@ class Analyser extends DatabaseAnalyser {
this.feedback({ analysingMessage: 'Loading indexes' });
const indexes = await this.analyserQuery('indexes', ['tables']);
this.feedback({ analysingMessage: 'Loading uniques' });
this.feedback({ analysingMessage: 'Loading triggers' });
const triggers = await this.analyserQuery('triggers');
const uniqueNames = await this.analyserQuery('uniqueNames', ['tables']);
this.feedback({ analysingMessage: 'Finalizing DB structure' });
@@ -167,6 +171,7 @@ class Analyser extends DatabaseAnalyser {
tables: tables.rows.map(table => ({
...table,
objectId: table.pureName,
objectComment: _.isString(table.objectComment) ? table.objectComment : undefined,
contentHash: _.isDate(table.modifyDate) ? table.modifyDate.toISOString() : table.modifyDate,
columns: columns.rows.filter(col => col.pureName == table.pureName).map(x => getColumnInfo(x, this.driver)),
primaryKey: DatabaseAnalyser.extractPrimaryKeys(table, pkColumns.rows),
@@ -236,6 +241,14 @@ class Analyser extends DatabaseAnalyser {
contentHash: _.isDate(x.modifyDate) ? x.modifyDate.toISOString() : x.modifyDate,
parameters: functionNameToParameters[x.pureName],
})),
triggers: triggers.rows.map(row => ({
contentHash: row.modifyDate,
pureName: row.triggerName,
eventType: row.eventType,
triggerTiming: row.triggerTiming,
tableName: row.tableName,
createSql: `CREATE TRIGGER ${row.triggerName} ${row.triggerTiming} ${row.eventType} ON ${row.tableName} FOR EACH ROW ${row.definition}`,
})),
};
this.feedback({ analysingMessage: null });
return res;
@@ -11,6 +11,7 @@ const functionModifications = require('./functionModifications');
const uniqueNames = require('./uniqueNames');
const viewTexts = require('./viewTexts');
const parameters = require('./parameters');
const triggers = require('./triggers');
module.exports = {
columns,
@@ -26,4 +27,5 @@ module.exports = {
indexes,
uniqueNames,
viewTexts,
triggers,
};
@@ -0,0 +1,13 @@
module.exports = `
SELECT
TRIGGER_NAME AS triggerName,
EVENT_MANIPULATION AS eventType,
ACTION_TIMING AS triggerTiming,
EVENT_OBJECT_SCHEMA AS schemaName,
EVENT_OBJECT_TABLE AS tableName,
ACTION_STATEMENT AS definition,
CREATED as modifyDate
FROM
INFORMATION_SCHEMA.TRIGGERS
WHERE EVENT_OBJECT_SCHEMA = '#DATABASE#' AND TRIGGER_NAME =OBJECT_ID_CONDITION
`;
+1 -1
View File
@@ -35,7 +35,7 @@
"webpack-cli": "^5.1.4"
},
"dependencies": {
"dbgate-query-splitter": "^4.11.2",
"dbgate-query-splitter": "^4.11.3",
"dbgate-tools": "^6.0.0-alpha.1",
"lodash": "^4.17.21"
},
@@ -68,9 +68,36 @@ class Analyser extends DatabaseAnalyser {
const routines = await this.analyserQuery('routines', ['procedures', 'functions'], {
$owner: this.dbhan.database,
});
const parameters = await this.analyserQuery('parameters', ['procedures', 'functions'], {
$owner: this.dbhan.database,
});
console.dir(parameters, { depth: 4 });
const routineToParams = parameters.rows.reduce((acc, row) => {
if (!acc[row.PURE_NAME]) acc[row.PURE_NAME] = [];
acc[row.PURE_NAME].push({
pureName: row.PURE_NAME,
parameterName: row.PARAMETER_NAME,
dataType: row.DATA_TYPE,
charMaxLength: row.CHAR_MAX,
numericPrecision: row.NUMERIC_PRECISION,
numericScale: row.NUMERIC_SCALE,
parameterMode: row.PARAMETER_MODE,
position: row.ORDINAL_POSITION ?? acc[row.PURE_NAME].length,
});
return acc;
}, {});
this.feedback({ analysingMessage: 'Loading indexes' });
const indexes = await this.analyserQuery('indexes', ['tables'], { $owner: this.dbhan.database });
this.feedback({ analysingMessage: 'Loading unique names' });
const triggers = await this.analyserQuery('triggers', undefined, { $owner: this.dbhan.database });
this.feedback({ analysingMessage: 'Loading triggers' });
const uniqueNames = await this.analyserQuery('uniqueNames', ['tables'], { $owner: this.dbhan.database });
this.feedback({ analysingMessage: 'Finalizing DB structure' });
@@ -173,6 +200,7 @@ class Analyser extends DatabaseAnalyser {
// schemaName: proc.schema_name,
createSql: `SET SQLTERMINATOR "/"\nCREATE ${proc.source_code}\n/\n`,
contentHash: proc.hash_code,
parameters: routineToParams[proc.pure_name],
})),
functions: routines.rows
.filter(x => x.object_type == 'FUNCTION')
@@ -182,7 +210,19 @@ class Analyser extends DatabaseAnalyser {
pureName: func.pure_name,
// schemaName: func.schema_name,
contentHash: func.hash_code,
parameters: routineToParams[func.pure_name],
})),
triggers: triggers.rows.map(row => ({
pureName: row.trigger_name,
createSql: `SET SQLTERMINATOR "/"\nCREATE TRIGGER "${row.trigger_name}" ${
row.trigger_timing.includes('BEFORE') ? 'BEFORE' : 'AFTER'
} ${row.event_type} ON "${row.table_name}" FOR EACH ROW ${row.definition} \n/\n`,
// createSql: `SET SQLTERMINATOR "/"\n${row.definition}\n/\n`,
tableName: row.table_name,
triggerLevel: row.trigger_level,
triggerTiming: row.trigger_timing,
eventType: row.event_type,
})),
};
this.feedback({ analysingMessage: null });
@@ -3,7 +3,7 @@ const stream = require('stream');
const driverBase = require('../frontend/driver');
const Analyser = require('./Analyser');
const { createBulkInsertStreamBase, makeUniqueColumnNames } = global.DBGATE_PACKAGES['dbgate-tools'];
const { makeUniqueColumnNames } = global.DBGATE_PACKAGES['dbgate-tools'];
const createOracleBulkInsertStream = require('./createOracleBulkInsertStream');
let platformInfo;
@@ -12,16 +12,11 @@ let oracledbValue;
function getOracledb() {
if (!oracledbValue) {
oracledbValue = require('oracledb');
oracledbValue.fetchAsString = [oracledbValue.CLOB, oracledbValue.NCLOB];
}
return oracledbValue;
}
/*
pg.types.setTypeParser(1082, 'text', val => val); // date
pg.types.setTypeParser(1114, 'text', val => val); // timestamp without timezone
pg.types.setTypeParser(1184, 'text', val => val); // timestamp
*/
function extractOracleColumns(result) {
if (!result /*|| !result.fields */) return [];
const res = result.map(fld => ({
@@ -311,12 +306,9 @@ const driver = {
}
wasHeader = true;
}
pass.write(zipDataRow(row, columns));
});
query.on('data', row => {
// console.log('readQuery data', row);
pass.write(zipDataRow(row, columns));
});
@@ -5,7 +5,9 @@ const foreignKeys = require('./foreignKeys');
const views = require('./views');
const matviews = require('./matviews');
const routines = require('./routines');
const parameters = require('./parameters');
const indexes = require('./indexes'); // use mysql
const triggers = require('./triggers');
//const indexcols = require('./indexcols');
const uniqueNames = require('./uniqueNames');
//const geometryColumns = require('./geometryColumns');
@@ -22,9 +24,11 @@ module.exports = {
foreignKeys,
views,
routines,
parameters,
matviews,
indexes,
// indexcols,
triggers,
// indexcols,
uniqueNames,
//geometryColumns,
//geographyColumns,
@@ -0,0 +1,22 @@
module.exports = `
SELECT
o.OBJECT_NAME AS pure_name,
PACKAGE_NAME,
ARGUMENT_NAME AS parameter_name,
POSITION AS ordinal_position,
DATA_TYPE AS data_type,
CHAR_LENGTH AS char_max_length,
DATA_PRECISION AS numeric_precision,
DATA_SCALE AS numeric_scale,
IN_OUT AS parameter_mode
FROM
all_objects o
LEFT JOIN
all_arguments a
ON o.object_id = a.object_id
WHERE
o.object_type IN ('FUNCTION', 'PROCEDURE')
AND o.OWNER = '$owner'
ORDER BY
POSITION;
`;
@@ -0,0 +1,19 @@
module.exports = `
SELECT
TRIGGER_TYPE AS "trigger_timing",
TRIGGERING_EVENT AS "event_type",
TRIGGER_BODY AS "definition",
TRIGGER_NAME AS "trigger_name",
TABLE_NAME AS "table_name",
OWNER,
CASE
WHEN INSTR(TRIGGER_TYPE, 'ROW') > 0 THEN 'ROW'
WHEN INSTR(TRIGGER_TYPE, 'STATEMENT') > 0 THEN 'STATEMENT'
ELSE NULL
END AS trigger_level
FROM
all_triggers
WHERE
OWNER='$owner'
AND 'tables:' || TABLE_NAME =OBJECT_ID_CONDITION
`;
+2 -2
View File
@@ -30,14 +30,14 @@
"prepublishOnly": "yarn build"
},
"devDependencies": {
"wkx": "^0.5.0",
"dbgate-plugin-tools": "^1.0.7",
"webpack": "^5.91.0",
"webpack-cli": "^5.1.4"
},
"dependencies": {
"wkx": "^0.5.0",
"pg-copy-streams": "^6.0.6",
"dbgate-query-splitter": "^4.11.2",
"dbgate-query-splitter": "^4.11.3",
"dbgate-tools": "^6.0.0-alpha.1",
"lodash": "^4.17.21",
"pg": "^8.11.5"
@@ -114,13 +114,19 @@ class Analyser extends DatabaseAnalyser {
// if (!cntBase || !cntRef) continue;
const baseCols = _.sortBy(
fk_keyColumnUsage.rows.filter(
x => x.table_name == fkRef.table_name && x.constraint_name == fkRef.constraint_name && x.table_schema == fkRef.table_schema
x =>
x.table_name == fkRef.table_name &&
x.constraint_name == fkRef.constraint_name &&
x.table_schema == fkRef.table_schema
),
'ordinal_position'
);
const refCols = _.sortBy(
fk_keyColumnUsage.rows.filter(
x => x.table_name == fkRef.ref_table_name && x.constraint_name == fkRef.unique_constraint_name && x.table_schema == fkRef.ref_table_schema
x =>
x.table_name == fkRef.ref_table_name &&
x.constraint_name == fkRef.unique_constraint_name &&
x.table_schema == fkRef.ref_table_schema
),
'ordinal_position'
);
@@ -185,6 +191,9 @@ class Analyser extends DatabaseAnalyser {
geographyColumns = await this.analyserQuery('geographyColumns', ['tables']);
}
this.feedback({ analysingMessage: 'Loading triggers' });
const triggers = await this.analyserQuery('triggers');
this.feedback({ analysingMessage: 'Finalizing DB structure' });
const columnColumnsMapped = fkColumns.rows.map(x => ({
@@ -348,6 +357,19 @@ class Analyser extends DatabaseAnalyser {
parameters: functionNameToParameters[`${func.schema_name}.${func.pure_name}`],
returnType: func.data_type,
})),
triggers: triggers.rows.map(row => ({
pureName: row.trigger_name,
trigerName: row.trigger_name,
functionName: row.function_name,
triggerTiming: row.trigger_timing,
triggerLevel: row.trigger_level,
eventType: row.event_type,
schemaName: row.schema_name,
tableName: row.table_name,
createSql: row.definition,
contentHash: `triggers:${row.trigger_id}`,
objectId: `triggers:${row.trigger_id}`,
})),
};
this.feedback({ analysingMessage: null });
@@ -134,16 +134,8 @@ const drivers = driverBases.map(driverBase => ({
database,
};
const datatypes = await this.query(
dbhan,
`SELECT oid AS datatypeid, typname AS datatypename FROM pg_type WHERE typname in ('geography')`
);
const typeIdToName = datatypes.rows.reduce((acc, cur) => {
acc[cur.datatypeid] = cur.datatypename;
return acc;
}, {});
const datatypes = await this.query(dbhan, `SELECT oid, typname FROM pg_type WHERE typname in ('geography')`);
const typeIdToName = _.fromPairs(datatypes.rows.map(cur => [cur.oid, cur.typname]));
dbhan['typeIdToName'] = typeIdToName;
if (isReadOnly) {
@@ -309,7 +301,7 @@ const drivers = driverBases.map(driverBase => ({
const zippedRow = zipDataRow(row, columns);
const transformedRow = transformRow(zippedRow, columnsToTransform);
options.row(transformedRow);
pass.write(transformedRow);
});
query.on('end', () => {
@@ -16,6 +16,8 @@ const geometryColumns = require('./geometryColumns');
const geographyColumns = require('./geographyColumns');
const proceduresParameters = require('./proceduresParameters');
const foreignKeys = require('./foreignKeys');
const triggers = require('./triggers');
const fk_keyColumnUsage = require('./fk_key_column_usage');
module.exports = {
@@ -38,4 +40,5 @@ module.exports = {
geometryColumns,
geographyColumns,
proceduresParameters,
triggers,
};
@@ -0,0 +1,35 @@
module.exports = `
SELECT
t.oid AS trigger_id,
t.tgname AS trigger_name,
n.nspname AS schema_name,
c.relname AS table_name,
p.proname AS function_name,
t.tgtype AS original_tgtype,
CASE
WHEN t.tgtype & 1 = 1 THEN 'ROW'
ELSE 'STATEMENT'
END AS trigger_level,
COALESCE(
CASE WHEN (tgtype::int::bit(7) & b'0000010')::int = 0 THEN NULL ELSE 'BEFORE' END,
CASE WHEN (tgtype::int::bit(7) & b'0000010')::int = 0 THEN 'AFTER' ELSE NULL END,
CASE WHEN (tgtype::int::bit(7) & b'1000000')::int = 0 THEN NULL ELSE 'INSTEAD OF' END,
''
)::text as trigger_timing,
(CASE WHEN (tgtype::int::bit(7) & b'0000100')::int = 0 THEN '' ELSE 'INSERT' END) ||
(CASE WHEN (tgtype::int::bit(7) & b'0001000')::int = 0 THEN '' ELSE 'DELETE' END) ||
(CASE WHEN (tgtype::int::bit(7) & b'0010000')::int = 0 THEN '' ELSE 'UPDATE' END) ||
(CASE WHEN (tgtype::int::bit(7) & b'0100000')::int = 0 THEN '' ELSE 'TRUNCATE' END)
as event_type,
pg_get_triggerdef(t.oid) AS definition
FROM
pg_trigger t
JOIN
pg_class c ON c.oid = t.tgrelid
JOIN
pg_namespace n ON n.oid = c.relnamespace
JOIN
pg_proc p ON p.oid = t.tgfoid
WHERE
NOT t.tgisinternal AND n.nspname =SCHEMA_NAME_CONDITION
`;
+1 -1
View File
@@ -34,7 +34,7 @@
"webpack-cli": "^5.1.4"
},
"dependencies": {
"dbgate-query-splitter": "^4.11.2",
"dbgate-query-splitter": "^4.11.3",
"dbgate-tools": "^6.0.0-alpha.1",
"lodash": "^4.17.21",
"async": "^3.2.3",
+1 -1
View File
@@ -37,7 +37,7 @@
"dependencies": {
"dbgate-tools": "^6.0.0-alpha.1",
"lodash": "^4.17.21",
"dbgate-query-splitter": "^4.11.2"
"dbgate-query-splitter": "^4.11.3"
},
"optionalDependencies": {
"better-sqlite3": "9.6.0"
@@ -1,19 +1,6 @@
const _ = require('lodash');
const { DatabaseAnalyser } = global.DBGATE_PACKAGES['dbgate-tools'];
const indexcolsQuery = `
SELECT
m.name as tableName,
il.name as constraintName,
il."unique" as isUnique,
ii.name as columnName,
il.origin
FROM sqlite_schema AS m,
pragma_index_list(m.name) AS il,
pragma_index_info(il.name) AS ii
WHERE m.type='table' AND il.origin <> 'pk'
ORDER BY ii.seqno, il.name
`;
const sql = require('./sql');
class Analyser extends DatabaseAnalyser {
constructor(dbhan, driver, version) {
@@ -26,8 +13,8 @@ class Analyser extends DatabaseAnalyser {
}
async _getFastSnapshot() {
const objects = await this.driver.query(this.dbhan, "select * from sqlite_master where type='table' or type='view'");
const indexcols = await this.driver.query(this.dbhan, indexcolsQuery);
const objects = await this.driver.query(this.dbhan, sql.objects);
const indexcols = await this.driver.query(this.dbhan, sql.indexcols);
return {
tables: objects.rows
@@ -53,10 +40,7 @@ class Analyser extends DatabaseAnalyser {
}
async _runAnalysis() {
const objects = await this.analyserQuery(
"select * from sqlite_master where (type='table' or type='view') and name =OBJECT_ID_CONDITION",
['tables', 'views']
);
const objects = await this.analyserQuery(sql.objectsConditioned, ['tables', 'views']);
const tables = objects.rows.filter((x) => x.type == 'table');
const views = objects.rows.filter((x) => x.type == 'view');
// console.log('TABLES', tables);
@@ -79,7 +63,7 @@ class Analyser extends DatabaseAnalyser {
createSql: x.sql,
}));
const indexcols = await this.driver.query(this.dbhan, indexcolsQuery);
const indexcols = await this.driver.query(this.dbhan, sql.indexcols);
for (const tableName of this.getRequestedObjectPureNames(
'tables',
@@ -165,9 +149,12 @@ class Analyser extends DatabaseAnalyser {
}));
}
const triggers = await this.driver.query(this.dbhan, sql.triggers);
return {
tables: tableList,
views: viewList,
triggers: triggers.rows,
};
}
}
@@ -0,0 +1,11 @@
const objects = require('./objects.js');
const objectsConditioned = require('./objectsConditioned.js');
const indexcols = require('./indexcols.js');
const triggers = require('./triggers.js');
module.exports = {
objects,
objectsConditioned,
indexcols,
triggers,
};
@@ -0,0 +1,14 @@
module.exports = `
SELECT
m.name as tableName,
il.name as constraintName,
il."unique" as isUnique,
ii.name as columnName,
il.origin
FROM sqlite_schema AS m,
pragma_index_list(m.name) AS il,
pragma_index_info(il.name) AS ii
WHERE m.type='table' AND il.origin <> 'pk'
ORDER BY ii.seqno, il.name
`;
@@ -0,0 +1,3 @@
module.exports = `
select * from sqlite_master where (type='table' or type='view')
`;
@@ -0,0 +1,3 @@
module.exports = `
select * from sqlite_master where (type='table' or type='view') and name =OBJECT_ID_CONDITION
`;
@@ -0,0 +1,23 @@
module.exports = `
SELECT
rowid AS objectId,
name AS pureName,
CASE
WHEN sql LIKE '% AFTER %' THEN 'AFTER'
WHEN sql LIKE '% BEFORE %' THEN 'BEFORE'
WHEN sql LIKE '% INSTEAD OF %' THEN 'INSTEAD OF'
ELSE 'UNKNOWN'
END AS triggerTiming,
CASE
WHEN sql LIKE '% INSERT %' THEN 'INSERT'
WHEN sql LIKE '% UPDATE %' THEN 'UPDATE'
WHEN sql LIKE '% DELETE %' THEN 'DELETE'
ELSE NULL
END AS eventType,
tbl_name AS tableName,
sql AS createSql
FROM
sqlite_master
WHERE
type = 'trigger';
`;
+220
View File
@@ -0,0 +1,220 @@
_templates:
_community_beta:
file: build-app-beta.yaml
defs:
- _community
- _beta
- _channel
string-replace:
"<<cd_merged>>": ''
"<<adjust>>": '--community'
"<<artifact-root>>": 'app/dist'
"<<channel>>": beta
"<<suffix>>": 'beta'
_community_stable:
file: build-app.yaml
defs:
- _community
- _stable
string-replace:
"<<cd_merged>>": ''
"<<adjust>>": '--community'
"<<artifact-root>>": 'app/dist'
"<<suffix>>": 'latest'
_premium_beta:
file: build-app-pro-beta.yaml
defs:
- _premium
- _beta
- _channel
string-replace:
"<<cd_merged>>": |
cd ..
cd dbgate-merged
"<<adjust>>": '--premium'
"<<artifact-root>>": '../dbgate-merged/app/dist'
"<<channel>>": 'premium-beta'
"<<suffix>>": 'premium-beta'
_premium_stable:
file: build-app-pro.yaml
defs:
- _premium
- _stable
- _channel
string-replace:
"<<cd_merged>>": |
cd ..
cd dbgate-merged
"<<adjust>>": '--premium'
"<<artifact-root>>": '../dbgate-merged/app/dist'
"<<channel>>": 'premium'
"<<suffix>>": 'premium-latest'
name:
_community_beta: Electron app BETA
_community_stable: Electron app
_premium_beta: Electron app PREMIUM BETA
_premium_stable: Electron app PREMIUM
on:
push:
tags:
- _community_beta: 'v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+'
_premium_beta: 'v[0-9]+.[0-9]+.[0-9]+-premium-beta.[0-9]+'
_stable: 'v[0-9]+.[0-9]+.[0-9]+'
# - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
# branches:
# - production
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
# os: [ubuntu-22.04, windows-2016]
os: [macos-14, windows-2022, ubuntu-22.04]
steps:
- name: Install python 3.11 (MacOS)
if: matrix.os == 'macos-14'
run: |
brew install python@3.11
echo "PYTHON=/opt/homebrew/bin/python3.11" >> $GITHUB_ENV
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 22.x
- _include: checkout-and-merge-pro
_if: _premium
- name: adjustPackageJson
run: |
<<cd_merged>>
node adjustPackageJson <<adjust>>
- name: setUpdaterChannel <<channel>>
_if: _channel
run: |
<<cd_merged>>
node setUpdaterChannel <<channel>>
- name: yarn set timeout
run: |
<<cd_merged>>
yarn config set network-timeout 100000
- name: yarn install
run: |
<<cd_merged>>
yarn install
- name: setCurrentVersion
run: |
<<cd_merged>>
yarn setCurrentVersion
- name: printSecrets
run: |
<<cd_merged>>
yarn printSecrets
env:
GIST_UPLOAD_SECRET : ${{secrets.GIST_UPLOAD_SECRET}}
- name: fillPackagedPlugins
run: |
<<cd_merged>>
yarn fillPackagedPlugins
- name: Install Snapcraft
_if: _community
if: matrix.os == 'ubuntu-22.04'
uses: samuelmeuli/action-snapcraft@v1
- name: Publish
run: |
<<cd_merged>>
yarn run build:app
env:
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_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
- name: generatePadFile
_if: _community_stable
run: |
yarn generatePadFile
- name: Copy artifacts
run: |
mkdir artifacts
cp <<artifact-root>>/*.deb artifacts/dbgate-<<suffix>>.deb || true
cp <<artifact-root>>/*x86*.AppImage artifacts/dbgate-<<suffix>>.AppImage || true
cp <<artifact-root>>/*arm64*.AppImage artifacts/dbgate-<<suffix>>-arm64.AppImage || true
cp <<artifact-root>>/*armv7l*.AppImage artifacts/dbgate-<<suffix>>-armv7l.AppImage || true
cp <<artifact-root>>/*win*.exe artifacts/dbgate-<<suffix>>.exe || true
cp <<artifact-root>>/*win_x64.zip artifacts/dbgate-windows-<<suffix>>.zip || true
cp <<artifact-root>>/*win_arm64.zip artifacts/dbgate-windows-<<suffix>>-arm64.zip || true
cp <<artifact-root>>/*-mac_universal.dmg artifacts/dbgate-<<suffix>>.dmg || true
cp <<artifact-root>>/*-mac_x64.dmg artifacts/dbgate-<<suffix>>-x64.dmg || true
cp <<artifact-root>>/*-mac_arm64.dmg artifacts/dbgate-<<suffix>>-arm64.dmg || true
mv <<artifact-root>>/*.snap artifacts/dbgate-<<suffix>>.snap || true
mv <<artifact-root>>/*.exe artifacts/ || true
mv <<artifact-root>>/*.zip artifacts/ || true
mv <<artifact-root>>/*.tar.gz artifacts/ || true
mv <<artifact-root>>/*.AppImage artifacts/ || true
mv <<artifact-root>>/*.deb artifacts/ || true
mv <<artifact-root>>/*.snap artifacts/ || true
mv <<artifact-root>>/*.dmg artifacts/ || true
mv <<artifact-root>>/*.blockmap artifacts/ || true
mv <<artifact-root>>/*.yml artifacts/ || true
rm artifacts/builder-debug.yml
- name: Copy PAD file
_if: _community_stable
if: matrix.os == 'windows-2022'
run: |
mv app/dist/dbgate-pad.xml artifacts/ || true
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
with:
files: 'artifacts/**'
prerelease:
_beta: true
_stable: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Print content of notarization-error.log
if: failure() && matrix.os == 'macos-14'
run: |
<<cd_merged>>
find . -type f -name "notarization-error.log" -exec echo "=== Start of {} ===" \; -exec cat {} \; -exec echo "=== End of {} ===" \;
+148
View File
@@ -0,0 +1,148 @@
name: AWS image PREMIUM
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
# - 'v[0-9]+.[0-9]+.[0-9]+-premium-beta.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-packer-beta.[0-9]+'
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-22.04]
steps:
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Use Node.js 18.x
uses: actions/setup-node@v1
with:
node-version: 18.x
- name: Setup `packer`
uses: hashicorp/setup-packer@main
with:
version: latest
- name: Checkout dbgate/dbgate-pro
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
mv dbgate-pro/* ../dbgate-pro/
cd ..
mkdir dbgate-merged
cd dbgate-pro
cd sync
yarn
node sync.js --nowatch
cd ..
- name: adjustPackageJson
run: |
cd ..
cd dbgate-merged
node adjustPackageJson --premium
- name: yarn install
run: |
cd ..
cd dbgate-merged
yarn install
- name: setCurrentVersion
run: |
cd ..
cd dbgate-merged
yarn setCurrentVersion
- name: printSecrets
run: |
cd ..
cd dbgate-merged
yarn printSecrets
env:
GIST_UPLOAD_SECRET : ${{secrets.GIST_UPLOAD_SECRET}}
- name: Prepare packer build
run: |
cd ..
cd dbgate-merged
yarn run prepare:packer
cd packer
zip -r cloud-build.zip build
- name: Copy artifacts
run: |
mkdir artifacts
cp ../dbgate-merged/packer/cloud-build.zip artifacts/cloud-build.zip || true
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
with:
files: 'artifacts/**'
prerelease: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run `packer init`
run: |
cd ../dbgate-merged/packer
packer init ./aws-ubuntu.pkr.hcl
env:
AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
AWS_DEFAULT_REGION: ${{secrets.AWS_DEFAULT_REGION}}
- name: Run `packer build`
run: |
cd ../dbgate-merged/packer
packer build ./aws-ubuntu.pkr.hcl
env:
AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
AWS_DEFAULT_REGION: ${{secrets.AWS_DEFAULT_REGION}}
# - name: Install AWS CLI
# run: |
# curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
# unzip awscliv2.zip
# sudo ./aws/install
# sudo apt-get install jq -y
- name: Install jq
run: |
sudo apt-get install jq -y
- name: Delete old AMIs
run: |
cd ../dbgate-merged/packer
chmod +x delete-old-amis.sh
./delete-old-amis.sh
env:
AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
AWS_DEFAULT_REGION: ${{secrets.AWS_DEFAULT_REGION}}
+137
View File
@@ -0,0 +1,137 @@
_templates:
_community:
file: build-docker.yaml
string-replace:
"<<cd_merged>>": ''
"<<adjust>>": '--community'
_premium:
file: build-docker-pro.yaml
string-replace:
"<<cd_merged>>": |
cd ..
cd dbgate-merged
"<<adjust>>": '--premium'
name:
_community: Docker image Community
_premium: Docker image PREMIUM
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- _community: 'v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+'
_premium: 'v[0-9]+.[0-9]+.[0-9]+-premium-beta.[0-9]+'
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-22.04]
steps:
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images:
_community: dbgate/dbgate
_premium: dbgate/dbgate-premium
flavor: |
latest=false
tags: |
type=raw,value=beta,enable=${{ contains(github.ref_name, '-docker.') || contains(github.ref_name, '-beta.') }}
type=match,pattern=\d+.\d+.\d+,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
type=raw,value=latest,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
- name: Docker alpine meta
_if: _community
id: alpmeta
uses: docker/metadata-action@v4
with:
images: |
dbgate/dbgate
flavor: |
latest=false
tags: |
type=raw,value=beta-alpine,enable=${{ contains(github.ref_name, '-docker.') || contains(github.ref_name, '-beta.') }}
type=match,pattern=\d+.\d+.\d+,suffix=-alpine,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
type=raw,value=alpine,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
- name: Use Node.js 18.x
uses: actions/setup-node@v1
with:
node-version: 18.x
- _include: checkout-and-merge-pro
_if: _premium
- name: adjustPackageJson
run: |
<<cd_merged>>
node adjustPackageJson <<adjust>>
- name: yarn install
run: |
<<cd_merged>>
# yarn --version
# yarn config set network-timeout 300000
yarn install
- name: setCurrentVersion
run: |
<<cd_merged>>
yarn setCurrentVersion
- name: printSecrets
run: |
<<cd_merged>>
yarn printSecrets
env:
GIST_UPLOAD_SECRET : ${{secrets.GIST_UPLOAD_SECRET}}
- name: Prepare docker image
run: |
<<cd_merged>>
yarn run prepare:docker
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v3
with:
push: true
context:
_community: ./docker
_premium: ../dbgate-merged/docker
tags: ${{ steps.meta.outputs.tags }}
platforms:
_community: linux/amd64,linux/arm64,linux/arm/v7
_premium: linux/amd64,linux/arm64
- name: Build and push alpine
uses: docker/build-push-action@v3
_if: _community
with:
push: true
context: ./docker
file: ./docker/Dockerfile-alpine
tags: ${{ steps.alpmeta.outputs.tags }}
platforms: linux/amd64,linux/arm64,linux/arm/v7
+102
View File
@@ -0,0 +1,102 @@
name: NPM packages PREMIUM
# on: [push]
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+'
# on:
# push:
# branches:
# - production
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-22.04]
steps:
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Use Node.js 18.x
uses: actions/setup-node@v1
with:
node-version: 18.x
- _include: checkout-and-merge-pro
- name: adjustNpmPackageJsonPremium
run: |
cd ..
cd dbgate-merged
node adjustNpmPackageJsonPremium
- name: Configure NPM token
env:
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
run: |
cd ..
cd dbgate-merged
rm -rf packages/dbmodel
- name: yarn install
run: |
cd ..
cd dbgate-merged
yarn install
- name: setCurrentVersion
run: |
cd ..
cd dbgate-merged
yarn setCurrentVersion
- name: printSecrets
run: |
cd ..
cd dbgate-merged
yarn printSecrets
env:
GIST_UPLOAD_SECRET : ${{secrets.GIST_UPLOAD_SECRET}}
- name: Publish dbgate-api-premium
run: |
cd ..
cd dbgate-merged/packages/api
npm publish
- name: Publish dbgate-web-premium
run: |
cd ..
cd dbgate-merged/packages/web
npm publish
- name: Publish dbgate-serve-premium
run: |
cd ..
cd dbgate-merged/packages/serve
npm publish
- name: Publish dbgate-plugin-cosmosdb
run: |
cd ..
cd dbgate-merged/plugins/dbgate-plugin-cosmosdb
npm publish

Some files were not shown because too many files have changed in this diff Show More