Compare commits
138 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 029f24b079 | |||
| 9f4b55ce07 | |||
| 01b7c42851 | |||
| f0221f6e43 | |||
| 30bbdb0f1d | |||
| a6f0bc78d4 | |||
| ceb6a88964 | |||
| a39fff8b3a | |||
| 0cf3d5993c | |||
| 2966484cda | |||
| ac3bb58106 | |||
| 36e2f1bdee | |||
| 70083bd870 | |||
| f7b39fca26 | |||
| 70873e83bd | |||
| 2858bba8b2 | |||
| bd0404fbaf | |||
| 317f6256f6 | |||
| 6c9b738717 | |||
| 2f8c584af5 | |||
| d3b417679e | |||
| 00dd8bfc72 | |||
| e1eea4adf3 | |||
| fd2d2e90d4 | |||
| f97b70ce45 | |||
| 45d79478fb | |||
| a59f42bd62 | |||
| a189fa7b6d | |||
| 794bc97207 | |||
| 24f7def7ab | |||
| 01071c236e | |||
| a6326ac9fa | |||
| 4c6d409be8 | |||
| 44ad8e51a5 | |||
| e82578adfb | |||
| 24f28b559e | |||
| b086a5d3d2 | |||
| bb0b87b770 | |||
| aa4f82fa98 | |||
| 873ace4170 | |||
| 5a9d8ba0a7 | |||
| 07f0fdcc1c | |||
| ff7ee4fb98 | |||
| b1f5b62757 | |||
| a67c857204 | |||
| 4032c53a30 | |||
| 0a37ed74d9 | |||
| f07efe440a | |||
| 2d5e67802d | |||
| 7b8e013084 | |||
| b69fc04b5c | |||
| b6dfdd4741 | |||
| ff3985a542 | |||
| 9c7e1dcaf1 | |||
| 48eb09687c | |||
| 86b339535d | |||
| 576b6dc774 | |||
| 18ca971f67 | |||
| 3916a5e6e8 | |||
| 1446fdad5e | |||
| 1478886e04 | |||
| 54d61790a9 | |||
| bb638fd8db | |||
| e3a2589517 | |||
| 6f557a6463 | |||
| 323f27f6e4 | |||
| 8d4a38dccb | |||
| 54a3b30e83 | |||
| 6251bcd8fd | |||
| e42099c1a9 | |||
| b07ee91cf9 | |||
| 62c028fc3c | |||
| 07ea575b0f | |||
| ee78786974 | |||
| e1814663cd | |||
| 6ae3e019ff | |||
| cadf539c3d | |||
| 51929d7ef7 | |||
| 0edc7f077f | |||
| 2488cee7ea | |||
| edf64db69a | |||
| c65bf51dcd | |||
| effe235a95 | |||
| 583d1494c2 | |||
| 983daf0d1c | |||
| 756ddf1a8b | |||
| 9ccd647d97 | |||
| dc9bfdc553 | |||
| af4e91faba | |||
| 394020157b | |||
| f16aab12e1 | |||
| e08216d6dd | |||
| ebb4f8e73e | |||
| b9939e5d5f | |||
| 9eb3bca8d6 | |||
| 022f263bf9 | |||
| 56972652d5 | |||
| d75b9e2688 | |||
| d2c5440e39 | |||
| 8ff30e426e | |||
| 7cdbef609e | |||
| f6195a468d | |||
| c23bf72d55 | |||
| c02441402b | |||
| b9a8764b55 | |||
| a2374c1981 | |||
| 9cfd5af704 | |||
| a6f473b8ed | |||
| e0a74402cb | |||
| c6e57b278e | |||
| e63f1f8f09 | |||
| e866c019f0 | |||
| 5f4bd6d3e3 | |||
| 57da9c9885 | |||
| e6a3acf4c2 | |||
| 537869e862 | |||
| ae2ff7b3b1 | |||
| 1db01dbdb1 | |||
| 7988438dc7 | |||
| 3b32823f94 | |||
| 3370c754f2 | |||
| 2d84e5a611 | |||
| 8d5f73849e | |||
| 7a5019164a | |||
| f5733ea2d7 | |||
| 413287c691 | |||
| 9e941dfce2 | |||
| d32af771dc | |||
| 1c84f40bcf | |||
| 671eba22e0 | |||
| c00cb3076c | |||
| 62daa13e54 | |||
| 4cc0a66a7d | |||
| 92e13220d8 | |||
| 2a5fdd852a | |||
| 7759fd862f | |||
| ca5dd0ac30 | |||
| 18be29fd88 |
@@ -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 {} ===" \;
|
||||
|
||||
@@ -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 {} ===" \;
|
||||
|
||||
@@ -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 {} ===" \;
|
||||
|
||||
@@ -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 {} ===" \;
|
||||
|
||||
@@ -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}}'
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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 ..
|
||||
|
||||
@@ -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: |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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!
|
||||
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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();
|
||||
@@ -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();
|
||||
// });
|
||||
|
||||
});
|
||||
|
||||
@@ -16,3 +16,10 @@ services:
|
||||
- 16004:3306
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=Pwd2020Db
|
||||
|
||||
mysql-ssh:
|
||||
build: mysql-ssh
|
||||
restart: always
|
||||
ports:
|
||||
- 16005:3306
|
||||
- 16006:22
|
||||
|
||||
@@ -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"]
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
service ssh start
|
||||
|
||||
service mysql start
|
||||
|
||||
tail -f /dev/null
|
||||
+44
-2
@@ -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());
|
||||
|
||||
+580
-416
File diff suppressed because it is too large
Load Diff
+3
-3
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.`);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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') {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
Vendored
+20
-1
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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 [];
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}}
|
||||
|
||||
@@ -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);
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
`;
|
||||
@@ -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
|
||||
`;
|
||||
@@ -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
|
||||
`;
|
||||
@@ -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
|
||||
`;
|
||||
@@ -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",
|
||||
|
||||
@@ -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';
|
||||
`;
|
||||
@@ -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 {} ===" \;
|
||||
@@ -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}}
|
||||
@@ -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
|
||||
@@ -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
Reference in New Issue
Block a user