Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bcede22c36 |
@@ -1,86 +1,83 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# 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-14, windows-2022, ubuntu-22.04]
|
||||
# os: [macOS-10.15]
|
||||
|
||||
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 22.x
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 22.x
|
||||
- name: adjustPackageJson
|
||||
node-version: 18.x
|
||||
- name: yarn adjustPackageJson
|
||||
run: |
|
||||
|
||||
node adjustPackageJson --community
|
||||
yarn adjustPackageJson
|
||||
- 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 }}'
|
||||
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}}'
|
||||
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}}
|
||||
|
||||
- name: Copy artifacts
|
||||
run: |
|
||||
mkdir artifacts
|
||||
@@ -92,10 +89,8 @@ 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_universal.dmg artifacts/dbgate-beta.dmg || true
|
||||
cp app/dist/*-mac_x64.dmg artifacts/dbgate-beta-x64.dmg || true
|
||||
cp app/dist/*-mac_x64.dmg artifacts/dbgate-beta.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
|
||||
@@ -108,21 +103,18 @@ 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 }}'
|
||||
- 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 {} ===" \;
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -1,44 +1,43 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# 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:
|
||||
- macos-14
|
||||
- windows-2022
|
||||
- ubuntu-22.04
|
||||
# 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]
|
||||
|
||||
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 22.x
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 22.x
|
||||
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
|
||||
@@ -50,82 +49,76 @@ jobs:
|
||||
yarn
|
||||
node sync.js --nowatch
|
||||
cd ..
|
||||
- name: adjustPackageJson
|
||||
|
||||
- name: yarn adjustPackageJson
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
node adjustPackageJson --premium
|
||||
yarn adjustPackageJson
|
||||
- name: adjustAppPackageJsonPremium
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
node adjustAppPackageJsonPremium
|
||||
- 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 }}'
|
||||
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}}'
|
||||
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: 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/*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
|
||||
cp ../dbgate-merged/app/dist/*-mac_x64.dmg artifacts/dbgate-premium-beta.dmg || true
|
||||
|
||||
mv ../dbgate-merged/app/dist/*.exe artifacts/ || true
|
||||
mv ../dbgate-merged/app/dist/*.zip artifacts/ || true
|
||||
@@ -138,23 +131,18 @@ 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 }}'
|
||||
- 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 {} ===" \;
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -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:
|
||||
- macos-14
|
||||
- windows-2022
|
||||
- ubuntu-22.04
|
||||
# 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) }}'
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js 22.x
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 22.x
|
||||
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
|
||||
@@ -50,111 +50,101 @@ jobs:
|
||||
yarn
|
||||
node sync.js --nowatch
|
||||
cd ..
|
||||
- name: adjustPackageJson
|
||||
|
||||
- name: yarn adjustPackageJson
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
node adjustPackageJson --premium
|
||||
yarn adjustPackageJson
|
||||
- name: adjustAppPackageJsonPremium
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
node adjustAppPackageJsonPremium
|
||||
- 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 }}'
|
||||
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}}'
|
||||
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: 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/*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/*.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/*-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/**
|
||||
prerelease: false
|
||||
files: 'artifacts/**'
|
||||
env:
|
||||
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 {} ===" \;
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -1,85 +1,90 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# 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:
|
||||
- macos-14
|
||||
- windows-2022
|
||||
- ubuntu-22.04
|
||||
# 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) }}'
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js 22.x
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 22.x
|
||||
- name: adjustPackageJson
|
||||
node-version: 18.x
|
||||
- name: yarn adjustPackageJson
|
||||
run: |
|
||||
|
||||
node adjustPackageJson --community
|
||||
yarn adjustPackageJson
|
||||
- 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 }}'
|
||||
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}}'
|
||||
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: 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
|
||||
@@ -88,44 +93,74 @@ 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/*win*.exe artifacts/dbgate-latest.exe || true
|
||||
cp app/dist/*.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/**
|
||||
prerelease: false
|
||||
files: 'artifacts/**'
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
- name: Print content of notarization-error.log
|
||||
if: failure() && matrix.os == 'macos-14'
|
||||
run: |
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
find . -type f -name "notarization-error.log" -exec echo "=== Start of {} ===" \; -exec cat {} \; -exec echo "=== End of {} ===" \;
|
||||
# - 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
|
||||
|
||||
@@ -1,41 +1,47 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# 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
|
||||
@@ -47,28 +53,33 @@ jobs:
|
||||
yarn
|
||||
node sync.js --nowatch
|
||||
cd ..
|
||||
- name: adjustPackageJson
|
||||
|
||||
- name: yarn adjustPackageJson
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
node adjustPackageJson --premium
|
||||
yarn adjustPackageJson
|
||||
|
||||
- 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 ..
|
||||
@@ -76,48 +87,62 @@ 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}}'
|
||||
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}}'
|
||||
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,32 +1,35 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# 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: |
|
||||
@@ -34,16 +37,19 @@ 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
|
||||
@@ -55,51 +61,50 @@ jobs:
|
||||
yarn
|
||||
node sync.js --nowatch
|
||||
cd ..
|
||||
- name: adjustPackageJson
|
||||
|
||||
- name: yarn adjustPackageJson
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
yarn adjustPackageJson
|
||||
|
||||
node adjustPackageJson --premium
|
||||
- name: yarn install
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
# 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
|
||||
|
||||
- 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,32 +1,35 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# This file is generated. Do not edit manually
|
||||
# --------------------------------------------------------------------------------------------
|
||||
name: Docker image Community
|
||||
'on':
|
||||
name: Docker image
|
||||
|
||||
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: |
|
||||
@@ -34,6 +37,7 @@ 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
|
||||
@@ -47,53 +51,56 @@ 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: adjustPackageJson
|
||||
run: |
|
||||
|
||||
node adjustPackageJson --community
|
||||
- name: yarn adjustPackageJson
|
||||
run: |
|
||||
yarn adjustPackageJson
|
||||
|
||||
- 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
|
||||
|
||||
- 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,23 +1,31 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# This file is generated. Do not edit manually
|
||||
# --------------------------------------------------------------------------------------------
|
||||
name: NPM packages PREMIUM
|
||||
'on':
|
||||
|
||||
# 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 }}'
|
||||
|
||||
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:
|
||||
@@ -26,12 +34,14 @@ 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
|
||||
@@ -43,55 +53,65 @@ 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,23 +1,31 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# This file is generated. Do not edit manually
|
||||
# --------------------------------------------------------------------------------------------
|
||||
name: NPM packages
|
||||
'on':
|
||||
|
||||
# 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 }}'
|
||||
|
||||
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:
|
||||
@@ -26,30 +34,37 @@ 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: |
|
||||
@@ -59,66 +74,82 @@ 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,45 +0,0 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# This file is generated. Do not edit manually
|
||||
# --------------------------------------------------------------------------------------------
|
||||
name: Build test containers
|
||||
'on':
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- feature/**
|
||||
paths:
|
||||
- e2e-tests/containers/**
|
||||
jobs:
|
||||
build-docker-ssh:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v3
|
||||
- name: Build mysql-ssh-login image
|
||||
run: |
|
||||
docker build -t dbgate/mysql-ssh-login:latest e2e-tests/containers/mysql-ssh-login
|
||||
- name: Build mysql-ssh-keyfile image
|
||||
run: |
|
||||
docker build -t dbgate/mysql-ssh-keyfile:latest e2e-tests/containers/mysql-ssh-keyfile
|
||||
- name: Build dex image
|
||||
run: |
|
||||
docker build -t dbgate/dex:latest e2e-tests/containers/dex
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: '${{ github.actor }}'
|
||||
password: '${{ secrets.GITHUB_TOKEN }}'
|
||||
- name: Push mysql-ssh-login to GHCR
|
||||
run: |
|
||||
docker tag dbgate/mysql-ssh-login:latest ghcr.io/dbgate/mysql-ssh-login:latest
|
||||
docker push ghcr.io/dbgate/mysql-ssh-login:latest
|
||||
- name: Push mysql-ssh-keyfile to GHCR
|
||||
run: |
|
||||
docker tag dbgate/mysql-ssh-keyfile:latest ghcr.io/dbgate/mysql-ssh-keyfile:latest
|
||||
docker push ghcr.io/dbgate/mysql-ssh-keyfile:latest
|
||||
- name: Push dex to GHCR
|
||||
run: |
|
||||
docker tag dbgate/dex:latest ghcr.io/dbgate/dex:latest
|
||||
docker push ghcr.io/dbgate/dex:latest
|
||||
@@ -0,0 +1,41 @@
|
||||
name: E2E tests
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- 'feature/**'
|
||||
|
||||
jobs:
|
||||
e2e-tests:
|
||||
runs-on: ubuntu-latest
|
||||
container: node:18
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y xvfb libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2 libxtst6
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: yarn install
|
||||
run: |
|
||||
yarn install
|
||||
- name: Build
|
||||
run: |
|
||||
yarn prepare:packer
|
||||
- name: yarn install cypress
|
||||
run: |
|
||||
cd e2e-tests
|
||||
yarn install
|
||||
- name: Run Cypress tests
|
||||
run: |
|
||||
cd e2e-tests
|
||||
yarn test:ci
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.0.18
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: Pwd2020Db
|
||||
@@ -1,42 +1,32 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# This file is generated. Do not edit manually
|
||||
# --------------------------------------------------------------------------------------------
|
||||
name: Run tests
|
||||
'on':
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- feature/**
|
||||
- 'feature/**'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
test-runner:
|
||||
runs-on: ubuntu-latest
|
||||
container: node:18
|
||||
|
||||
steps:
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: actions/checkout@v3
|
||||
- name: Context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: yarn install
|
||||
run: |
|
||||
yarn install
|
||||
- name: Build packer dist for cypress
|
||||
run: |
|
||||
yarn prepare:packer
|
||||
- name: yarn install cypress
|
||||
run: |
|
||||
cd e2e-tests
|
||||
yarn install
|
||||
- name: Run Cypress tests
|
||||
run: |
|
||||
cd e2e-tests
|
||||
yarn test:ci
|
||||
- name: Integration tests
|
||||
run: |
|
||||
cd integration-tests
|
||||
yarn test:ci
|
||||
# yarn wait:ci
|
||||
- name: Filter parser tests
|
||||
if: always()
|
||||
run: |
|
||||
@@ -50,77 +40,49 @@ 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-integr:
|
||||
postgres:
|
||||
image: postgres
|
||||
env:
|
||||
POSTGRES_PASSWORD: Pwd2020Db
|
||||
options: '--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5'
|
||||
ports:
|
||||
- '15000:5432'
|
||||
mysql-integr:
|
||||
image: 'mysql:8.0.18'
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
|
||||
mysql:
|
||||
image: mysql:8.0.18
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: Pwd2020Db
|
||||
ports:
|
||||
- '15001:3306'
|
||||
mssql-integr:
|
||||
|
||||
mssql:
|
||||
image: mcr.microsoft.com/mssql/server
|
||||
env:
|
||||
ACCEPT_EULA: 'Y'
|
||||
ACCEPT_EULA: Y
|
||||
SA_PASSWORD: Pwd2020Db
|
||||
MSSQL_PID: Express
|
||||
ports:
|
||||
- '15002:1433'
|
||||
clickhouse-integr:
|
||||
image: 'bitnami/clickhouse:24.8.4'
|
||||
|
||||
clickhouse:
|
||||
image: bitnami/clickhouse:24.8.4
|
||||
env:
|
||||
CLICKHOUSE_ADMIN_PASSWORD: Pwd2020Db
|
||||
ports:
|
||||
- '15005:8123'
|
||||
oracle-integr:
|
||||
image: 'gvenzl/oracle-xe:21-slim'
|
||||
env:
|
||||
ORACLE_PASSWORD: Pwd2020Db
|
||||
ports:
|
||||
- '15006:1521'
|
||||
postgres-cypress:
|
||||
image: postgres
|
||||
options: '--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5'
|
||||
env:
|
||||
POSTGRES_PASSWORD: Pwd2020Db
|
||||
ports:
|
||||
- '16000:5432'
|
||||
mysql-cypress:
|
||||
image: 'mysql:8.0.18'
|
||||
ports:
|
||||
- '16004:3306'
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: Pwd2020Db
|
||||
mysql-ssh-login:
|
||||
image: 'ghcr.io/dbgate/mysql-ssh-login:latest'
|
||||
ports:
|
||||
- '16006:22'
|
||||
mysql-ssh-keyfile:
|
||||
image: 'ghcr.io/dbgate/mysql-ssh-keyfile:latest'
|
||||
ports:
|
||||
- '16008:22'
|
||||
dex:
|
||||
image: 'ghcr.io/dbgate/dex:latest'
|
||||
ports:
|
||||
- '16009:5556'
|
||||
|
||||
# cockroachdb:
|
||||
# image: cockroachdb/cockroach
|
||||
|
||||
@@ -8,29 +8,6 @@ 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) ([API documentation](https://dbgate.org/docs/apidoc))
|
||||
* Use nodeJs [scripting interface](https://dbgate.org/docs/scripting.html) ([API documentation](https://dbgate.org/docs/apidoc.html))
|
||||
* [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). 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.html). Plugins for new themes can be created actually without JS coding
|
||||
|
||||
Thank you!
|
||||
|
||||
|
||||
@@ -41,29 +41,6 @@ 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');
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -19,6 +19,7 @@
|
||||
"artifactName": "dbgate-${version}-${os}_${arch}.${ext}",
|
||||
"appId": "org.dbgate",
|
||||
"productName": "DbGate",
|
||||
"afterSign": "electron-builder-notarize",
|
||||
"asarUnpack": "**/*.node",
|
||||
"mac": {
|
||||
"category": "database",
|
||||
@@ -37,11 +38,9 @@
|
||||
"target": "default",
|
||||
"arch": [
|
||||
"universal",
|
||||
"x64",
|
||||
"arm64"
|
||||
"x64"
|
||||
]
|
||||
},
|
||||
"notarize": true
|
||||
}
|
||||
},
|
||||
"linux": {
|
||||
"target": [
|
||||
@@ -130,6 +129,7 @@
|
||||
"copyfiles": "^2.2.0",
|
||||
"cross-env": "^6.0.3",
|
||||
"electron": "30.0.2",
|
||||
"electron-builder": "25.1.8"
|
||||
"electron-builder": "23.1.0",
|
||||
"electron-builder-notarize": "^1.5.2"
|
||||
}
|
||||
}
|
||||
|
||||
+1022
-828
File diff suppressed because it is too large
Load Diff
@@ -1,174 +0,0 @@
|
||||
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();
|
||||
@@ -19,7 +19,6 @@ const volatilePackages = [
|
||||
'activedirectory2',
|
||||
'axios',
|
||||
'ssh2',
|
||||
'wkx',
|
||||
];
|
||||
|
||||
module.exports = volatilePackages;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
FROM dexidp/dex:v2.35.3
|
||||
|
||||
COPY dex-config.yaml /etc/dex/cfg/config.yaml
|
||||
|
||||
EXPOSE 5556
|
||||
|
||||
CMD ["dex", "serve", "/etc/dex/cfg/config.yaml"]
|
||||
@@ -1,22 +0,0 @@
|
||||
issuer: http://localhost:16009/dex
|
||||
storage:
|
||||
type: memory
|
||||
web:
|
||||
http: 0.0.0.0:5556
|
||||
|
||||
oauth2:
|
||||
skipApprovalScreen: true
|
||||
|
||||
staticClients:
|
||||
- id: my-app
|
||||
redirectURIs:
|
||||
- 'http://localhost:3000/'
|
||||
name: 'My Test App'
|
||||
secret: my-secret
|
||||
|
||||
enablePasswordDB: true
|
||||
staticPasswords:
|
||||
- email: "test@example.com"
|
||||
hash: "$2y$10$JcmlXnV1y7.egUdKwYNbseOnqYVIGc323gtvvHh4ZuSPZB30veYZy"
|
||||
username: "test"
|
||||
userID: "1234"
|
||||
@@ -1,27 +0,0 @@
|
||||
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/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config && \
|
||||
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin without-password/' /etc/ssh/sshd_config
|
||||
|
||||
RUN mkdir -p /root/.ssh && chmod 700 /root/.ssh
|
||||
|
||||
COPY mykey.pub /root/.ssh/authorized_keys
|
||||
|
||||
RUN chmod 600 /root/.ssh/authorized_keys
|
||||
|
||||
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
|
||||
|
||||
COPY start.sh /start.sh
|
||||
RUN chmod +x /start.sh
|
||||
|
||||
CMD ["/start.sh"]
|
||||
@@ -1 +0,0 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQClN/tu+X7PVYpMBEQDwxtyG0oNuKqcJdBud/vBUalyYSpliXO30BsBusjCyAh8ENVllmGTRaTcqAUPg/vwekaAMFZu9EXmQsdhPEWSxrkPkXXKsWrZVPtRV8l3wuSy/VLxbXRLujTpIEE5Au88e2CFN3zzuhg9rvsXE0cGjyYe9Cw3Ub+Yo6rbnESI7F+Jun29/wD8RF+kRL5cr7BrDoOBQf4yGexrTbUPMZ4b8QlGfXUwZhn6LlWVoWq7BMRelnfIAkuC+LwavvnkMqXMITmGa7sG0zOXByW7iGdP6TWVq9Ks+yCZoAA9ncAkgkpwoNrOSXR6dM5UjrsfJ2Na332QfxK8MmC+nBiyXIKUaQY2G8Wfm93GQqDc+349JFwH4ZjgYWJlTd/UfRCn4j30jxe1RKnjt5xGqb3L+j8JfuSPcojWRekg/K8GxBmaMCcEdqjIFD4MxeIUW3bGHd30wnuZkTPWlSmAGrO0fZXj0s1fmOBME05TjE8jsyKPmb2Kd3JdtCuTrjOgrYiHaMfcv/VqVhIv2kCKjnvhAxCqfGfKxxgcerItbrsfFAvYak1kwZelBquHOK6SkMH5WhDyhvGY+ZF0Wbg3CpynlpJVu4E3LSglYNbkIWqS3pAf+hqJtXl9SHCLgKFUcCIz0ZNQkT+PtUlR3klp6qoPXUWrcL3pdQ== test
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
service ssh start
|
||||
|
||||
service mysql start
|
||||
|
||||
tail -f /dev/null
|
||||
@@ -1,23 +0,0 @@
|
||||
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
|
||||
|
||||
COPY start.sh /start.sh
|
||||
|
||||
RUN chmod +x /start.sh
|
||||
|
||||
CMD ["/start.sh"]
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
service ssh start
|
||||
|
||||
service mysql start
|
||||
|
||||
tail -f /dev/null
|
||||
@@ -1,6 +1,6 @@
|
||||
const { defineConfig } = require('cypress');
|
||||
const killPort = require('kill-port');
|
||||
const { clearTestingData } = require('./e2eTestTools');
|
||||
const { clearDataWithBackup } = require('./e2eTestTools');
|
||||
const waitOn = require('wait-on');
|
||||
const { exec } = require('child_process');
|
||||
|
||||
@@ -10,23 +10,11 @@ module.exports = defineConfig({
|
||||
// implement node event listeners here
|
||||
|
||||
on('before:spec', async details => {
|
||||
await clearTestingData();
|
||||
// console.log('********************* DETAILS *********************', JSON.stringify(details));
|
||||
|
||||
await clearDataWithBackup();
|
||||
|
||||
if (config.isInteractive) {
|
||||
await killPort(3000);
|
||||
switch (details.fileName) {
|
||||
case 'add-connection':
|
||||
serverProcess = exec('yarn start:add-connection');
|
||||
break;
|
||||
case 'portal':
|
||||
serverProcess = exec('yarn start:portal');
|
||||
break;
|
||||
case 'oauth':
|
||||
serverProcess = exec('yarn start:oauth');
|
||||
break;
|
||||
}
|
||||
|
||||
serverProcess = exec('yarn start');
|
||||
await waitOn({ resources: ['http://localhost:3000'] });
|
||||
serverProcess.stdout.on('data', data => {
|
||||
console.log(data.toString());
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
const path = require('path');
|
||||
|
||||
describe('Add connection', () => {
|
||||
it('successfully loads', () => {
|
||||
cy.visit('http://localhost:3000');
|
||||
cy.contains('Database not selected');
|
||||
});
|
||||
|
||||
it('adds connection', () => {
|
||||
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('Pwd2020Db');
|
||||
cy.get('[data-testid=ConnectionDriverFields_port]').clear().type('16004');
|
||||
cy.get('[data-testid=ConnectionDriverFields_displayName]').clear().type('test-mysql-1');
|
||||
|
||||
// test connection
|
||||
cy.get('[data-testid=ConnectionTab_buttonTest]').click();
|
||||
cy.contains('Connected:');
|
||||
|
||||
// save and connect
|
||||
cy.get('[data-testid=ConnectionTab_buttonSave]').click();
|
||||
cy.get('[data-testid=ConnectionTab_buttonConnect]').click();
|
||||
cy.contains('performance_schema');
|
||||
});
|
||||
|
||||
it('SSH connection - user + password', () => {
|
||||
cy.visit('http://localhost:3000');
|
||||
cy.contains('Connections');
|
||||
|
||||
// cy.realPress('F1');
|
||||
// cy.realType('Close all');
|
||||
// cy.realPress('Enter');
|
||||
|
||||
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=ConnectionDriverFields_displayName]').clear().type('test-mysql-ssh-1');
|
||||
|
||||
cy.get('[data-testid=ConnectionTab_tabSshTunnel]').click();
|
||||
cy.get('[data-testid=ConnectionSshTunnelFields_useSshTunnel]').check();
|
||||
cy.get('[data-testid=ConnectionSshTunnelFields_sshLogin]').clear().type('root');
|
||||
cy.get('[data-testid=ConnectionSshTunnelFields_sshPassword]').clear().type('root');
|
||||
cy.get('[data-testid=ConnectionSshTunnelFields_sshPort]').clear().type('16006');
|
||||
cy.get('[data-testid=ConnectionTab_buttonSave]').click();
|
||||
cy.get('[data-testid=ConnectionTab_buttonConnect]').click();
|
||||
cy.contains('performance_schema');
|
||||
});
|
||||
|
||||
it('SSH connection - keyfile', () => {
|
||||
cy.visit('http://localhost:3000');
|
||||
cy.contains('Connections');
|
||||
|
||||
// cy.realPress('F1');
|
||||
// cy.realType('Close all');
|
||||
// cy.realPress('Enter');
|
||||
|
||||
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=ConnectionDriverFields_displayName]').clear().type('test-mysql-ssh-2');
|
||||
|
||||
cy.get('[data-testid=ConnectionTab_tabSshTunnel]').click();
|
||||
cy.get('[data-testid=ConnectionSshTunnelFields_useSshTunnel]').check();
|
||||
cy.get('[data-testid=ConnectionSshTunnelFields_sshMode]').select('Key file');
|
||||
cy.get('[data-testid=ConnectionSshTunnelFields_sshLogin]').clear();
|
||||
cy.get('[data-testid=ConnectionSshTunnelFields_sshLogin]').type('root');
|
||||
cy.get('[data-testid=ConnectionSshTunnelFields_sshKeyfile]')
|
||||
.clear()
|
||||
.type(path.join(Cypress.config('fileServerFolder'), 'cypress', 'e2e', 'mykey'));
|
||||
cy.get('[data-testid=ConnectionSshTunnelFields_sshPort]').clear().type('16008');
|
||||
cy.get('[data-testid=ConnectionTab_buttonSave]').click();
|
||||
cy.get('[data-testid=ConnectionTab_buttonConnect]').click();
|
||||
cy.contains('performance_schema');
|
||||
});
|
||||
|
||||
it('ask password - mysql', () => {
|
||||
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('Pwd2020Db');
|
||||
cy.get('[data-testid=ConnectionDriverFields_port]').clear().type('16004');
|
||||
cy.get('[data-testid=ConnectionDriverFields_displayName]').clear().type('test-mysql-2');
|
||||
cy.testid('ConnectionDriverFields_passwordMode').select('askPassword');
|
||||
|
||||
// test connection
|
||||
cy.get('[data-testid=ConnectionTab_buttonTest]').click();
|
||||
cy.testid('DatabaseLoginModal_password').clear().type('Pwd2020Db');
|
||||
cy.testid('DatabaseLoginModal_connect').click();
|
||||
|
||||
cy.contains('Connected:');
|
||||
|
||||
cy.get('[data-testid=ConnectionTab_buttonSave]').click();
|
||||
cy.get('[data-testid=ConnectionTab_buttonConnect]').click();
|
||||
|
||||
// again type DB password - not saved
|
||||
cy.testid('DatabaseLoginModal_password').clear().type('Pwd2020Db');
|
||||
cy.testid('DatabaseLoginModal_connect').click();
|
||||
|
||||
cy.contains('performance_schema');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
describe('Initialization', () => {
|
||||
it('successfully loads', () => {
|
||||
cy.visit('http://localhost:3000');
|
||||
cy.contains('Database not selected');
|
||||
});
|
||||
|
||||
it('adds connection', () => {
|
||||
const runOnCI = Cypress.env('runOnCI');
|
||||
|
||||
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('Pwd2020Db');
|
||||
if (runOnCI) {
|
||||
cy.get('[data-testid=ConnectionDriverFields_server]').clear().type('mysql');
|
||||
} else {
|
||||
cy.get('[data-testid=ConnectionDriverFields_port]').clear().type('16004');
|
||||
}
|
||||
cy.get('[data-testid=ConnectionDriverFields_displayName]').clear().type('test-mysql-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();
|
||||
// });
|
||||
|
||||
});
|
||||
@@ -1,49 +0,0 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn
|
||||
NhAAAAAwEAAQAAAgEApTf7bvl+z1WKTAREA8MbchtKDbiqnCXQbnf7wVGpcmEqZYlzt9Ab
|
||||
AbrIwsgIfBDVZZZhk0Wk3KgFD4P78HpGgDBWbvRF5kLHYTxFksa5D5F1yrFq2VT7UVfJd8
|
||||
Lksv1S8W10S7o06SBBOQLvPHtghTd887oYPa77FxNHBo8mHvQsN1G/mKOq25xEiOxfibp9
|
||||
vf8A/ERfpES+XK+waw6DgUH+Mhnsa021DzGeG/EJRn11MGYZ+i5VlaFquwTEXpZ3yAJLgv
|
||||
i8Gr755DKlzCE5hmu7BtMzlwclu4hnT+k1lavSrPsgmaAAPZ3AJIJKcKDazkl0enTOVI67
|
||||
HydjWt99kH8SvDJgvpwYslyClGkGNhvFn5vdxkKg3Pt+PSRcB+GY4GFiZU3f1H0Qp+I99I
|
||||
8XtUSp47ecRqm9y/o/CX7kj3KI1kXpIPyvBsQZmjAnBHaoyBQ+DMXiFFt2xh3d9MJ7mZEz
|
||||
1pUpgBqztH2V49LNX5jgTBNOU4xPI7Mij5m9indyXbQrk64zoK2Ih2jH3L/1alYSL9pAio
|
||||
574QMQqnxnyscYHHqyLW67HxQL2GpNZMGXpQarhziukpDB+VoQ8obxmPmRdFm4Nwqcp5aS
|
||||
VbuBNy0oJWDW5CFqkt6QH/oaibV5fUhwi4ChVHAiM9GTUJE/j7VJUd5JaeqqD11Fq3C96X
|
||||
UAAAdAKwO+PisDvj4AAAAHc3NoLXJzYQAAAgEApTf7bvl+z1WKTAREA8MbchtKDbiqnCXQ
|
||||
bnf7wVGpcmEqZYlzt9AbAbrIwsgIfBDVZZZhk0Wk3KgFD4P78HpGgDBWbvRF5kLHYTxFks
|
||||
a5D5F1yrFq2VT7UVfJd8Lksv1S8W10S7o06SBBOQLvPHtghTd887oYPa77FxNHBo8mHvQs
|
||||
N1G/mKOq25xEiOxfibp9vf8A/ERfpES+XK+waw6DgUH+Mhnsa021DzGeG/EJRn11MGYZ+i
|
||||
5VlaFquwTEXpZ3yAJLgvi8Gr755DKlzCE5hmu7BtMzlwclu4hnT+k1lavSrPsgmaAAPZ3A
|
||||
JIJKcKDazkl0enTOVI67HydjWt99kH8SvDJgvpwYslyClGkGNhvFn5vdxkKg3Pt+PSRcB+
|
||||
GY4GFiZU3f1H0Qp+I99I8XtUSp47ecRqm9y/o/CX7kj3KI1kXpIPyvBsQZmjAnBHaoyBQ+
|
||||
DMXiFFt2xh3d9MJ7mZEz1pUpgBqztH2V49LNX5jgTBNOU4xPI7Mij5m9indyXbQrk64zoK
|
||||
2Ih2jH3L/1alYSL9pAio574QMQqnxnyscYHHqyLW67HxQL2GpNZMGXpQarhziukpDB+VoQ
|
||||
8obxmPmRdFm4Nwqcp5aSVbuBNy0oJWDW5CFqkt6QH/oaibV5fUhwi4ChVHAiM9GTUJE/j7
|
||||
VJUd5JaeqqD11Fq3C96XUAAAADAQABAAACAAOZKogKNbF8+BwbuQIpTP8Oim2uE0PUrFYb
|
||||
lYdqUznDKqc3d9ENs+jfu+DyIQKCuK2+ZAr5vf4dnVlEffIzgjbnK/ASsIsJR/UILlkPVu
|
||||
x4izY06FIqFackivtpao2zaAu2CeMJqn6r+H+uCVkp3rpIBm1QekKtqEOiZIOcuS8nZjx2
|
||||
MqliYdA9S7N9DRT0037rKjGpqOOXqQW1FdnfC7d+9nL6OY9EtqgeuTDRQ8BzRGAfeSVdE6
|
||||
QZ9eHI2CCvP5XtkYjICLYUaWDc8YYhRcggWdxrhnjIQRF1MRApJhpHubjmvJkGm7q70CQm
|
||||
FPT1q+OeRJko022SsOScI6p7qkJjEsHS4RLbSGkDAn84U9l1MnHbzOqOQbI/Mnn7vNyZt4
|
||||
e7n/ExUg9HglpdLgETl0oLIaiVgYGrJSLflfYtrgfEISGtoroQDj/X96HZsF+Aku+I3U4z
|
||||
OD7UasFDl3LsTO3bWz8/vqkCfi/ncejZ4keWUA6VahbtJUg8E/eEIWMz8gFoO/vWf1l0H0
|
||||
V51ISzInt1yVnqhdbRPH+Ce4NlNjq9JlhiZVJSsc6ke2580Okttc3JETzdHWNac7k+/0u4
|
||||
lPZK2sII1cq/d+9YAe3JVpUuiQyX6R4Crga2GIyevoqm3EyXUNN/vjDCx4qyToOtJUzHao
|
||||
tXI4tZZkBmtVrhqf1pAAABAQC3lG50iMbJXL8vVsB7P8UWLgmI13PqwHB8ldzsLrNtkU7q
|
||||
N3KYdz/ycGGPAKxfMJiGs00qT8/d107MZYmj7hHE84VuBiHVGSXbzmL5zeth0aN4oINee0
|
||||
jlvCPKjqhoImPtrU1fLglqOeTNJcZK7XzwiZry1ZHp0hXd4XPrWHZBZo37SYv9/t652zR4
|
||||
qmXlxwwwdtzuNFiAexTu0K4zY12hjmoGlvlCS2YJ+B2wJNd3E1RnL505m7dIA/dLnCLeEj
|
||||
zf8j1XiZ9i/m7mrU/g/e9SFP+HVwi5AV5eyHbNSPD6GZ7quWL4SlP+GGkNtKden+LIaB+G
|
||||
iRwCLTgCVThdIC6oAAABAQDA6Gm7luZuzOoWBQzVKc74AOf64Op+eZwQBCC3V+eHjmyIQW
|
||||
oBozvlvaNxapNxJZQjtnlckCkW59RheQxm155j/MV6aVvaD9WWNFB9k+0fujmPd4fPoZF1
|
||||
9y5J3L3l9hmv+51vZvKvky5mXxOGdONTQZkpGqGvmlZpVO9jWe4WWACokqRIrS9zwtfLgf
|
||||
hH+hUMh+9R1iIKACleNdfHbiqia+XIXxivbVdCtTgdPM6mW8i3gP1/oSTpYZI5KIRH4PTO
|
||||
6OgG8EvRCIPc/0mddXZqiabhpPM/r5qe0jKxcQHFf1siwq7EyZ/C8ctBxpEK4dVCNnCTX4
|
||||
k7+/JizOJzhzljAAABAQDbQT0BsBCM2Dl+LbwpAy6iaS0fWqhCnQ9B6ojWcfNouXuIW4tF
|
||||
6fwmoqyFU2SoORmj0G6ww1NiBr+gwSDo5wSEpCI78S1CnFcp7J1HhONGthmdYDclpDlci5
|
||||
t5AOIC7hhmdkqL46happxG9MH8oOua7/cqK7300nJo+ZS3XOo4O3siTjDVtVKXRAY5jWuG
|
||||
mLNXQ8JKCzqmFfLlAAgGWaY7rMaGu+9Rom+F4FEZ4IUitcsN77jFNBXMXqnWy/ayr8CJpe
|
||||
CxgwBm5JWQ7m+cmskMl3nmjkNr8nCiZoMcz4sIrVkZWS4PHoVFtN3jKYmo3c02kq8/378I
|
||||
jIy5WYf/zrVHAAAABHRlc3QBAgMEBQY=
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
@@ -1,14 +0,0 @@
|
||||
describe('OAuth', () => {
|
||||
it('OAuth login', () => {
|
||||
cy.visit('http://localhost:3000');
|
||||
|
||||
// login on DEX
|
||||
cy.get('#login').clear().type('test@example.com');
|
||||
cy.get('#password').clear().type('test');
|
||||
cy.get('#submit-login').click();
|
||||
|
||||
// check DbGate connection
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('performance_schema');
|
||||
});
|
||||
});
|
||||
@@ -1,93 +0,0 @@
|
||||
describe('Run as portal', () => {
|
||||
it('successfully loads', () => {
|
||||
cy.visit('http://localhost:3000');
|
||||
cy.contains('MySql-connection');
|
||||
cy.contains('Postgres-connection');
|
||||
});
|
||||
|
||||
// it('Delete chinook', () => {
|
||||
// cy.visit('http://localhost:3000');
|
||||
|
||||
// cy.contains('MySql-connection').rightclick();
|
||||
// cy.contains('New Query (server)').click();
|
||||
// cy.realType('drop database if exists Chinook');
|
||||
// cy.realPress('F5');
|
||||
// cy.contains('Query execution finished');
|
||||
|
||||
// cy.contains('Postgres-connection').rightclick();
|
||||
// cy.contains('New Query (server)').click();
|
||||
// cy.realType('drop database if exists "Chinook"');
|
||||
// cy.realPress('F5');
|
||||
// cy.contains('Query execution finished');
|
||||
|
||||
// // cy.realPress('F1');
|
||||
// // cy.realType('Close all');
|
||||
// // cy.realPress('Enter');
|
||||
// });
|
||||
|
||||
it('Create Chinook MySQL', () => {
|
||||
cy.visit('http://localhost:3000');
|
||||
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MySql-connection').rightclick();
|
||||
cy.contains('Create database').click();
|
||||
cy.get('[data-testid=InputTextModal_value]').clear().type('Chinook');
|
||||
cy.get('[data-testid=InputTextModal_ok]').click();
|
||||
});
|
||||
|
||||
it('Create Chinook Postgres', () => {
|
||||
cy.visit('http://localhost:3000');
|
||||
|
||||
cy.contains('Postgres-connection').click();
|
||||
cy.contains('Postgres-connection').rightclick();
|
||||
cy.contains('Create database').click();
|
||||
cy.get('[data-testid=InputTextModal_value]').clear().type('Chinook');
|
||||
cy.get('[data-testid=InputTextModal_ok]').click();
|
||||
});
|
||||
|
||||
it('Import Chinook MySQL', () => {
|
||||
cy.visit('http://localhost:3000');
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.get('[data-testid=DatabaseAppObject_Chinook]').rightclick();
|
||||
cy.contains('Chinook').rightclick();
|
||||
cy.contains('Restore/import SQL dump').click();
|
||||
cy.get('#uploadFileButton').selectFile('data/chinook-mysql.sql', { force: true });
|
||||
cy.wait(500);
|
||||
cy.get('[data-testid=ImportDatabaseDumpModal_runImport]').click();
|
||||
cy.contains('Importing database');
|
||||
cy.contains('Finished job script');
|
||||
cy.get('[data-testid=RunScriptModal_close]').click();
|
||||
cy.contains('Chinook').click();
|
||||
cy.contains('Album');
|
||||
});
|
||||
|
||||
it('Import Chinook Postgres', () => {
|
||||
cy.visit('http://localhost:3000');
|
||||
cy.contains('Postgres-connection').click();
|
||||
cy.get('[data-testid=DatabaseAppObject_Chinook]').rightclick();
|
||||
cy.contains('Restore/import SQL dump').click();
|
||||
cy.get('#uploadFileButton').selectFile('data/chinook-postgres.sql', { force: true });
|
||||
cy.wait(500);
|
||||
cy.get('[data-testid=ImportDatabaseDumpModal_runImport]').click();
|
||||
cy.contains('Importing database');
|
||||
cy.contains('Finished job script');
|
||||
cy.get('[data-testid=RunScriptModal_close]').click();
|
||||
cy.contains('Chinook').click();
|
||||
cy.contains('album');
|
||||
});
|
||||
|
||||
it('Open ask pwd connection', () => {
|
||||
cy.visit('http://localhost:3000');
|
||||
cy.contains('Postgres-ask-connection').click();
|
||||
cy.testid('DatabaseLoginModal_username').clear().type('postgres');
|
||||
cy.testid('DatabaseLoginModal_password').clear().type('Pwd2020Db');
|
||||
cy.testid('DatabaseLoginModal_connect').click();
|
||||
cy.contains('Chinook').click();
|
||||
cy.contains('album');
|
||||
});
|
||||
|
||||
// it('import chinook DB', () => {
|
||||
// cy.visit('http://localhost:3000');
|
||||
// cy.get('[data-testid=ConnectionTab_buttonConnect]').click();
|
||||
// });
|
||||
});
|
||||
@@ -22,8 +22,4 @@
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
|
||||
Cypress.Commands.add('testid', (testId, options = {}) => {
|
||||
return cy.get(`[data-testid="${testId}"]`, options);
|
||||
});
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
@@ -14,31 +14,7 @@
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands';
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
|
||||
import 'cypress-real-events';
|
||||
|
||||
beforeEach(() => {
|
||||
// Replace 'my-database-name' with the actual IndexedDB name
|
||||
cy.window().then(win => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = win.indexedDB.deleteDatabase('localforage');
|
||||
request.onsuccess = () => {
|
||||
// Database successfully deleted
|
||||
resolve();
|
||||
};
|
||||
request.onerror = () => {
|
||||
// Some error occurred
|
||||
reject(request.error);
|
||||
};
|
||||
request.onblocked = () => {
|
||||
// Might happen if there are open connections
|
||||
console.warn('IndexedDB deletion blocked');
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
// require('./commands')
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -16,22 +16,3 @@ services:
|
||||
- 16004:3306
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=Pwd2020Db
|
||||
|
||||
mysql-ssh-login:
|
||||
build: containers/mysql-ssh-login
|
||||
restart: always
|
||||
ports:
|
||||
- 16005:3306
|
||||
- "16006:22"
|
||||
|
||||
mysql-ssh-keyfile:
|
||||
build: containers/mysql-ssh-keyfile
|
||||
restart: always
|
||||
ports:
|
||||
- 16007:3306
|
||||
- "16008:22"
|
||||
|
||||
dex:
|
||||
build: containers/dex
|
||||
ports:
|
||||
- "16009:5556"
|
||||
|
||||
+19
-16
@@ -4,26 +4,29 @@ const fs = require('fs');
|
||||
|
||||
const baseDir = path.join(os.homedir(), '.dbgate');
|
||||
|
||||
// function createTimeStamp() {
|
||||
// const now = new Date();
|
||||
// const year = now.getFullYear();
|
||||
// const month = String(now.getMonth() + 1).padStart(2, '0'); // měsíc je 0-indexovaný
|
||||
// const day = String(now.getDate()).padStart(2, '0');
|
||||
// const hours = String(now.getHours()).padStart(2, '0');
|
||||
// const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
// const seconds = String(now.getSeconds()).padStart(2, '0');
|
||||
function createTimeStamp() {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0'); // měsíc je 0-indexovaný
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const hours = String(now.getHours()).padStart(2, '0');
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||||
|
||||
// // Poskládáme datum a čas do názvu souboru
|
||||
// const ts = `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`;
|
||||
// return ts;
|
||||
// }
|
||||
// Poskládáme datum a čas do názvu souboru
|
||||
const ts = `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`;
|
||||
return ts;
|
||||
}
|
||||
|
||||
function clearTestingData() {
|
||||
if (fs.existsSync(path.join(baseDir, 'connections-e2etests.jsonl'))) {
|
||||
fs.unlinkSync(path.join(baseDir, 'connections-e2etests.jsonl'));
|
||||
function clearDataWithBackup() {
|
||||
if (fs.existsSync(path.join(baseDir, 'connections.jsonl'))) {
|
||||
fs.renameSync(
|
||||
path.join(baseDir, 'connections.jsonl'),
|
||||
path.join(baseDir, `connections-${createTimeStamp()}.jsonl.bak`)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
clearTestingData,
|
||||
clearDataWithBackup,
|
||||
};
|
||||
|
||||
Vendored
-15
@@ -1,15 +0,0 @@
|
||||
CONNECTIONS=mysql
|
||||
|
||||
LABEL_mysql=MySql-connection
|
||||
SERVER_mysql=localhost
|
||||
USER_mysql=root
|
||||
PASSWORD_mysql=Pwd2020Db
|
||||
PORT_mysql=16004
|
||||
ENGINE_mysql=mysql@dbgate-plugin-mysql
|
||||
|
||||
OAUTH_AUTH=http://localhost:16009/dex/auth
|
||||
OAUTH_TOKEN=http://localhost:16009/dex/token
|
||||
OAUTH_CLIENT_ID=my-app
|
||||
OAUTH_CLIENT_SECRET=my-secret
|
||||
OAUTH_LOGIN_FIELD=username
|
||||
OAUTH_SCOPE=openid
|
||||
Vendored
-22
@@ -1,22 +0,0 @@
|
||||
CONNECTIONS=mysql,postgres,pgask
|
||||
|
||||
LABEL_mysql=MySql-connection
|
||||
SERVER_mysql=localhost
|
||||
USER_mysql=root
|
||||
PASSWORD_mysql=Pwd2020Db
|
||||
PORT_mysql=16004
|
||||
ENGINE_mysql=mysql@dbgate-plugin-mysql
|
||||
|
||||
LABEL_postgres=Postgres-connection
|
||||
SERVER_postgres=localhost
|
||||
USER_postgres=postgres
|
||||
PASSWORD_postgres=Pwd2020Db
|
||||
PORT_postgres=16000
|
||||
ENGINE_postgres=postgres@dbgate-plugin-postgres
|
||||
|
||||
LABEL_pgask=Postgres-ask-connection
|
||||
SERVER_pgask=localhost
|
||||
USER_pgask=postgres
|
||||
PORT_pgask=16000
|
||||
ENGINE_pgask=postgres@dbgate-plugin-postgres
|
||||
PASSWORD_MODE_pgask=askUser
|
||||
@@ -1,32 +0,0 @@
|
||||
const dbgateApi = require('dbgate-api');
|
||||
dbgateApi.initializeApiEnvironment();
|
||||
const dbgatePluginMysql = require('dbgate-plugin-mysql');
|
||||
dbgateApi.registerPlugins(dbgatePluginMysql);
|
||||
const dbgatePluginPostgres = require('dbgate-plugin-postgres');
|
||||
dbgateApi.registerPlugins(dbgatePluginPostgres);
|
||||
|
||||
async function run() {
|
||||
await dbgateApi.executeQuery({
|
||||
connection: {
|
||||
server: process.env.SERVER_mysql,
|
||||
user: process.env.USER_mysql,
|
||||
password: process.env.PASSWORD_mysql,
|
||||
port: process.env.PORT_mysql,
|
||||
engine: 'mysql@dbgate-plugin-mysql',
|
||||
},
|
||||
sql: 'drop database if exists Chinook',
|
||||
});
|
||||
|
||||
await dbgateApi.executeQuery({
|
||||
connection: {
|
||||
server: process.env.SERVER_postgres,
|
||||
user: process.env.USER_postgres,
|
||||
password: process.env.PASSWORD_postgres,
|
||||
port: process.env.PORT_postgres,
|
||||
engine: 'postgres@dbgate-plugin-postgres',
|
||||
},
|
||||
sql: 'drop database if exists "Chinook"',
|
||||
});
|
||||
}
|
||||
|
||||
dbgateApi.runScript(run);
|
||||
+5
-13
@@ -7,23 +7,15 @@
|
||||
"axios": "^1.7.9",
|
||||
"cross-env": "^7.0.3",
|
||||
"cypress": "^13.16.1",
|
||||
"cypress-real-events": "^1.13.0",
|
||||
"env-cmd": "^10.1.0",
|
||||
"kill-port": "^2.0.1",
|
||||
"start-server-and-test": "^2.0.8"
|
||||
},
|
||||
"scripts": {
|
||||
"cy:open": "cypress open --config experimentalInteractiveRunEvents=true",
|
||||
|
||||
"cy:run:add-connection": "cypress run --spec cypress/e2e/add-connection.cy.js",
|
||||
"cy:run:portal": "cypress run --spec cypress/e2e/portal.cy.js",
|
||||
"cy:run:oauth": "cypress run --spec cypress/e2e/oauth.cy.js",
|
||||
|
||||
"start:add-connection": "cd .. && node packer/build/bundle.js --listen-api --run-e2e-tests",
|
||||
"start:portal": "cd .. && env-cmd -f e2e-tests/env/portal/.env node e2e-tests/init/portal.js && env-cmd -f e2e-tests/env/portal/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
|
||||
"start:oauth": "cd .. && env-cmd -f e2e-tests/env/oauth/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
|
||||
|
||||
"test": "start-server-and-test start:add-connection http://localhost:3000 cy:run:add-connection && start-server-and-test start:portal http://localhost:3000 cy:run:portal && start-server-and-test start:oauth http://localhost:3000 cy:run:oauth",
|
||||
"test:ci": "yarn test"
|
||||
"cy:run": "cypress run",
|
||||
"cy:run:ci": "cypress run --env runOnCI=true",
|
||||
"start": "cd .. && node packer/build/bundle.js --listen-api --run-e2e-tests",
|
||||
"test:ci": "start-server-and-test start http://localhost:3000 cy:run:ci",
|
||||
"test": "start-server-and-test start http://localhost:3000 cy:run"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,11 +319,6 @@ combined-stream@^1.0.8, combined-stream@~1.0.6:
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
|
||||
integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
|
||||
|
||||
commander@^6.2.1:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
|
||||
@@ -355,11 +350,6 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.3:
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
cypress-real-events@^1.13.0:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/cypress-real-events/-/cypress-real-events-1.13.0.tgz#6b7cd32dcac172db1493608f97a2576c7d0bd5af"
|
||||
integrity sha512-LoejtK+dyZ1jaT8wGT5oASTPfsNV8/ClRp99ruN60oPj8cBJYod80iJDyNwfPAu4GCxTXOhhAv9FO65Hpwt6Hg==
|
||||
|
||||
cypress@^13.16.1:
|
||||
version "13.16.1"
|
||||
resolved "https://registry.yarnpkg.com/cypress/-/cypress-13.16.1.tgz#82e776f6ad2037ccce6b6feabed768615c476258"
|
||||
@@ -489,14 +479,6 @@ enquirer@^2.3.6:
|
||||
ansi-colors "^4.1.1"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
env-cmd@^10.1.0:
|
||||
version "10.1.0"
|
||||
resolved "https://registry.yarnpkg.com/env-cmd/-/env-cmd-10.1.0.tgz#c7f5d3b550c9519f137fdac4dd8fb6866a8c8c4b"
|
||||
integrity sha512-mMdWTT9XKN7yNth/6N6g2GuKuJTsKMDHlQFUDacb/heQRRWOTIZ42t1rMHnQu4jYxU1ajdTeJM+9eEETlqToMA==
|
||||
dependencies:
|
||||
commander "^4.0.0"
|
||||
cross-spawn "^7.0.0"
|
||||
|
||||
es-define-property@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845"
|
||||
|
||||
@@ -3,15 +3,9 @@ const _ = require('lodash');
|
||||
const fp = require('lodash/fp');
|
||||
const { testWrapper } = require('../tools');
|
||||
const engines = require('../engines');
|
||||
const {
|
||||
getAlterDatabaseScript,
|
||||
extendDatabaseInfo,
|
||||
generateDbPairingId,
|
||||
formatQueryWithoutParams,
|
||||
runCommandOnDriver,
|
||||
} = require('dbgate-tools');
|
||||
const { getAlterDatabaseScript, extendDatabaseInfo, generateDbPairingId } = require('dbgate-tools');
|
||||
|
||||
const initSql = ['CREATE TABLE ~t1 (~id int primary key)', 'CREATE TABLE ~t2 (~id int primary key)'];
|
||||
const initSql = ['CREATE TABLE t1 (id int primary key)', 'CREATE TABLE t2 (id int primary key)'];
|
||||
|
||||
function flatSource(engineCond = x => !x.skipReferences) {
|
||||
return _.flatten(
|
||||
@@ -22,14 +16,13 @@ function flatSource(engineCond = x => !x.skipReferences) {
|
||||
}
|
||||
|
||||
async function testDatabaseDiff(conn, driver, mangle, createObject = null) {
|
||||
await runCommandOnDriver(conn, driver, `create table ~t1 (~id int not null primary key)`);
|
||||
await driver.query(conn, `create table t1 (id int not null primary key)`);
|
||||
|
||||
await runCommandOnDriver(
|
||||
await driver.query(
|
||||
conn,
|
||||
driver,
|
||||
`create table ~t2 (
|
||||
~id int not null primary key,
|
||||
~t1_id int null references ~t1(~id)
|
||||
`create table t2 (
|
||||
id int not null primary key,
|
||||
t1_id int null references t1(id)
|
||||
)`
|
||||
);
|
||||
|
||||
@@ -70,32 +63,29 @@ describe('Alter database', () => {
|
||||
db => {
|
||||
_.remove(db[type], x => x.pureName == 'obj1');
|
||||
},
|
||||
formatQueryWithoutParams(driver, object.create1)
|
||||
object.create1
|
||||
);
|
||||
expect(db[type].length).toEqual(0);
|
||||
})
|
||||
);
|
||||
|
||||
const objectsSupportingRename = flatSource(x => x.supportRenameSqlObject);
|
||||
if (objectsSupportingRename.length > 0) {
|
||||
test.each(objectsSupportingRename)(
|
||||
'Rename object - %s - %s',
|
||||
testWrapper(async (conn, driver, type, object, engine) => {
|
||||
for (const sql of initSql) await runCommandOnDriver(conn, driver, sql);
|
||||
test.each(flatSource(x => x.supportRenameSqlObject))(
|
||||
'Rename object - %s - %s',
|
||||
testWrapper(async (conn, driver, type, object, engine) => {
|
||||
for (const sql of initSql) await driver.query(conn, sql, { discardResult: true });
|
||||
|
||||
await runCommandOnDriver(conn, driver, object.create1);
|
||||
await driver.query(conn, object.create1, { discardResult: true });
|
||||
|
||||
const structure = extendDatabaseInfo(await driver.analyseFull(conn));
|
||||
const structure = extendDatabaseInfo(await driver.analyseFull(conn));
|
||||
|
||||
const dmp = driver.createDumper();
|
||||
dmp.renameSqlObject(structure[type][0], 'renamed1');
|
||||
const dmp = driver.createDumper();
|
||||
dmp.renameSqlObject(structure[type][0], 'renamed1');
|
||||
|
||||
await driver.query(conn, dmp.s);
|
||||
await driver.query(conn, dmp.s);
|
||||
|
||||
const structure2 = await driver.analyseFull(conn);
|
||||
expect(structure2[type].length).toEqual(1);
|
||||
expect(structure2[type][0].pureName).toEqual('renamed1');
|
||||
})
|
||||
);
|
||||
}
|
||||
const structure2 = await driver.analyseFull(conn);
|
||||
expect(structure2[type].length).toEqual(1);
|
||||
expect(structure2[type][0].pureName).toEqual('renamed1');
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
@@ -4,12 +4,7 @@ const fp = require('lodash/fp');
|
||||
const { testWrapper } = require('../tools');
|
||||
const engines = require('../engines');
|
||||
const crypto = require('crypto');
|
||||
const {
|
||||
getAlterTableScript,
|
||||
extendDatabaseInfo,
|
||||
generateDbPairingId,
|
||||
formatQueryWithoutParams,
|
||||
} = require('dbgate-tools');
|
||||
const { getAlterTableScript, extendDatabaseInfo, generateDbPairingId } = require('dbgate-tools');
|
||||
|
||||
function pickImportantTableInfo(engine, table) {
|
||||
const props = ['columnName', 'defaultValue'];
|
||||
@@ -20,10 +15,7 @@ function pickImportantTableInfo(engine, table) {
|
||||
columns: table.columns
|
||||
.filter(x => x.columnName != 'rowid')
|
||||
.map(fp.pick(props))
|
||||
.map(props => _.omitBy(props, x => x == null))
|
||||
.map(props =>
|
||||
_.omitBy(props, (v, k) => k == 'defaultValue' && v == 'NULL' && engine.setNullDefaultInsteadOfDrop)
|
||||
),
|
||||
.map(props => _.omitBy(props, x => x == null)),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -33,36 +25,27 @@ function checkTableStructure(engine, t1, t2) {
|
||||
}
|
||||
|
||||
async function testTableDiff(engine, conn, driver, mangle) {
|
||||
await driver.query(conn, formatQueryWithoutParams(driver, `create table ~t0 (~id int not null primary key)`));
|
||||
await driver.query(conn, `create table t0 (id int not null primary key)`);
|
||||
|
||||
await driver.query(
|
||||
conn,
|
||||
formatQueryWithoutParams(
|
||||
driver,
|
||||
`create table ~t1 (
|
||||
~col_pk int not null primary key,
|
||||
~col_std int,
|
||||
~col_def int default 12,
|
||||
${engine.skipReferences ? '' : '~col_fk int references ~t0(~id),'}
|
||||
~col_idx int,
|
||||
~col_uq int ${engine.skipUnique ? '' : 'unique'} ,
|
||||
~col_ref int ${engine.skipUnique ? '' : 'unique'}
|
||||
`create table t1 (
|
||||
col_pk int not null primary key,
|
||||
col_std int,
|
||||
col_def int default 12,
|
||||
${engine.skipReferences ? '' : 'col_fk int references t0(id),'}
|
||||
col_idx int,
|
||||
col_uq int ${engine.skipUnique ? '' : 'unique'} ,
|
||||
col_ref int ${engine.skipUnique ? '' : 'unique'}
|
||||
)`
|
||||
)
|
||||
);
|
||||
|
||||
if (!engine.skipIndexes) {
|
||||
await driver.query(conn, formatQueryWithoutParams(driver, `create index ~idx1 on ~t1(~col_idx)`));
|
||||
await driver.query(conn, `create index idx1 on t1(col_idx)`);
|
||||
}
|
||||
|
||||
if (!engine.skipReferences) {
|
||||
await driver.query(
|
||||
conn,
|
||||
formatQueryWithoutParams(
|
||||
driver,
|
||||
`create table ~t2 (~id int not null primary key, ~fkval int null references ~t1(~col_ref))`
|
||||
)
|
||||
);
|
||||
await driver.query(conn, `create table t2 (id int not null primary key, fkval int null references t1(col_ref))`);
|
||||
}
|
||||
|
||||
const tget = x => x.tables.find(y => y.pureName == 't1');
|
||||
@@ -192,4 +175,5 @@ describe('Alter table', () => {
|
||||
// });
|
||||
// })
|
||||
// );
|
||||
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ const engines = require('../engines');
|
||||
const stream = require('stream');
|
||||
const { testWrapper } = require('../tools');
|
||||
const dataDuplicator = require('dbgate-api/src/shell/dataDuplicator');
|
||||
const { runCommandOnDriver, runQueryOnDriver } = require('dbgate-tools');
|
||||
const { runCommandOnDriver } = require('dbgate-tools');
|
||||
|
||||
describe('Data duplicator', () => {
|
||||
test.each(engines.filter(x => !x.skipDataDuplicator).map(engine => [engine.label, engine]))(
|
||||
@@ -84,10 +84,10 @@ describe('Data duplicator', () => {
|
||||
],
|
||||
});
|
||||
|
||||
const res1 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t1`));
|
||||
const res1 = await driver.query(conn, `select count(*) as cnt from t1`);
|
||||
expect(res1.rows[0].cnt.toString()).toEqual('6');
|
||||
|
||||
const res2 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t2`));
|
||||
const res2 = await driver.query(conn, `select count(*) as cnt from t2`);
|
||||
expect(res2.rows[0].cnt.toString()).toEqual('6');
|
||||
})
|
||||
);
|
||||
@@ -145,15 +145,13 @@ describe('Data duplicator', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const res1 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t1`));
|
||||
const res1 = await driver.query(conn, `select count(*) as cnt from t1`);
|
||||
expect(res1.rows[0].cnt.toString()).toEqual('1');
|
||||
|
||||
const res2 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t2`));
|
||||
const res2 = await driver.query(conn, `select count(*) as cnt from t2`);
|
||||
expect(res2.rows[0].cnt.toString()).toEqual('2');
|
||||
|
||||
const res3 = await runQueryOnDriver(conn, driver, dmp =>
|
||||
dmp.put(`select count(*) as ~cnt from ~t2 where ~valfk is not null`)
|
||||
);
|
||||
const res3 = await driver.query(conn, `select count(*) as cnt from t2 where valfk is not null`);
|
||||
expect(res3.rows[0].cnt.toString()).toEqual('1');
|
||||
})
|
||||
);
|
||||
|
||||
+4
-47
@@ -2,11 +2,9 @@ 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, runCommandOnDriver } = require('dbgate-tools');
|
||||
|
||||
function createImportStream() {
|
||||
const pass = new stream.PassThrough({
|
||||
@@ -24,17 +22,7 @@ function createImportStream() {
|
||||
return pass;
|
||||
}
|
||||
|
||||
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', () => {
|
||||
describe('DB Import', () => {
|
||||
test.each(engines.map(engine => [engine.label, engine]))(
|
||||
'Import one table - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
@@ -49,7 +37,7 @@ describe('DB Import/export', () => {
|
||||
});
|
||||
await copyStream(reader, writer);
|
||||
|
||||
const res = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t1`));
|
||||
const res = await driver.query(conn, `select count(*) as cnt from t1`);
|
||||
expect(res.rows[0].cnt.toString()).toEqual('6');
|
||||
})
|
||||
);
|
||||
@@ -77,10 +65,10 @@ describe('DB Import/export', () => {
|
||||
});
|
||||
await copyStream(reader2, writer2);
|
||||
|
||||
const res1 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t1`));
|
||||
const res1 = await driver.query(conn, `select count(*) as cnt from t1`);
|
||||
expect(res1.rows[0].cnt.toString()).toEqual('6');
|
||||
|
||||
const res2 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t2`));
|
||||
const res2 = await driver.query(conn, `select count(*) as cnt from t2`);
|
||||
expect(res2.rows[0].cnt.toString()).toEqual('6');
|
||||
})
|
||||
);
|
||||
@@ -110,35 +98,4 @@ describe('DB Import/export', () => {
|
||||
// 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);
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -4,7 +4,7 @@ const { testWrapper, testWrapperPrepareOnly } = require('../tools');
|
||||
const _ = require('lodash');
|
||||
const engines = require('../engines');
|
||||
const deployDb = require('dbgate-api/src/shell/deployDb');
|
||||
const { databaseInfoFromYamlModel, runQueryOnDriver, formatQueryWithoutParams } = require('dbgate-tools');
|
||||
const { databaseInfoFromYamlModel } = require('dbgate-tools');
|
||||
const generateDeploySql = require('dbgate-api/src/shell/generateDeploySql');
|
||||
const connectUtility = require('dbgate-api/src/utility/connectUtility');
|
||||
|
||||
@@ -69,29 +69,6 @@ function checkStructure(
|
||||
}
|
||||
}
|
||||
|
||||
// function convertObjectText(text, driver) {
|
||||
// if (!text) return undefined;
|
||||
// text = formatQueryWithoutParams(driver, text);
|
||||
// if (driver.dialect.requireFromDual && text.startsWith('create view ') && !text.includes('from')) {
|
||||
// text = text + ' from dual';
|
||||
// }
|
||||
// return text;
|
||||
// }
|
||||
|
||||
// function convertModelToEngine(model, driver) {
|
||||
// return model.map(x => ({
|
||||
// ...x,
|
||||
// text: convertObjectText(x.text, driver),
|
||||
// }));
|
||||
// }
|
||||
|
||||
function convertModelToEngine(model, driver) {
|
||||
return model.map(x => ({
|
||||
...x,
|
||||
text: x.text ? formatQueryWithoutParams(driver, x.text) : undefined,
|
||||
}));
|
||||
}
|
||||
|
||||
async function testDatabaseDeploy(engine, conn, driver, dbModelsYaml, options) {
|
||||
const { testEmptyLastScript, finalCheckAgainstModel, markDeleted, allowDropStatements } = options || {};
|
||||
let index = 0;
|
||||
@@ -106,13 +83,13 @@ async function testDatabaseDeploy(engine, conn, driver, dbModelsYaml, options) {
|
||||
|
||||
for (const loadedDbModel of dbModelsYaml) {
|
||||
if (_.isString(loadedDbModel)) {
|
||||
await driver.script(conn, formatQueryWithoutParams(driver, loadedDbModel));
|
||||
await driver.script(conn, loadedDbModel);
|
||||
} else {
|
||||
const { sql, isEmpty } = await generateDeploySql({
|
||||
systemConnection: conn.isPreparedOnly ? undefined : conn,
|
||||
connection: conn.isPreparedOnly ? conn : undefined,
|
||||
driver,
|
||||
loadedDbModel: convertModelToEngine(loadedDbModel, driver),
|
||||
loadedDbModel,
|
||||
dbdiffOptionsExtra,
|
||||
});
|
||||
console.debug('Generated deploy script:', sql);
|
||||
@@ -129,7 +106,7 @@ async function testDatabaseDeploy(engine, conn, driver, dbModelsYaml, options) {
|
||||
systemConnection: conn.isPreparedOnly ? undefined : conn,
|
||||
connection: conn.isPreparedOnly ? conn : undefined,
|
||||
driver,
|
||||
loadedDbModel: convertModelToEngine(loadedDbModel, driver),
|
||||
loadedDbModel,
|
||||
dbdiffOptionsExtra,
|
||||
});
|
||||
}
|
||||
@@ -140,12 +117,7 @@ async function testDatabaseDeploy(engine, conn, driver, dbModelsYaml, options) {
|
||||
const dbhan = conn.isPreparedOnly ? await connectUtility(driver, conn, 'read') : conn;
|
||||
const structure = await driver.analyseFull(dbhan);
|
||||
if (conn.isPreparedOnly) await driver.close(dbhan);
|
||||
checkStructure(
|
||||
engine,
|
||||
structure,
|
||||
convertModelToEngine(finalCheckAgainstModel ?? _.findLast(dbModelsYaml, x => _.isArray(x)), driver),
|
||||
options
|
||||
);
|
||||
checkStructure(engine, structure, finalCheckAgainstModel ?? _.findLast(dbModelsYaml, x => _.isArray(x)), options);
|
||||
}
|
||||
|
||||
describe('Deploy database', () => {
|
||||
@@ -367,7 +339,7 @@ describe('Deploy database', () => {
|
||||
],
|
||||
]);
|
||||
|
||||
const res = await runQueryOnDriver(conn, driver, `select count(*) as ~cnt from ~t1`);
|
||||
const res = await driver.query(conn, `select count(*) as cnt from t1`);
|
||||
expect(res.rows[0].cnt.toString()).toEqual('3');
|
||||
})
|
||||
);
|
||||
@@ -414,12 +386,12 @@ describe('Deploy database', () => {
|
||||
],
|
||||
]);
|
||||
|
||||
const res = await runQueryOnDriver(conn, driver, `select ~val from ~t1 where ~id = 2`);
|
||||
const res = await driver.query(conn, `select val from t1 where id = 2`);
|
||||
expect(res.rows[0].val.toString()).toEqual('5');
|
||||
})
|
||||
);
|
||||
|
||||
test.each([engines.postgreSqlEngine].map(engine => [engine.label, engine]))(
|
||||
test.each(engines.enginesPostgre.map(engine => [engine.label, engine]))(
|
||||
'Current timestamp default value - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await testDatabaseDeploy(engine, conn, driver, [
|
||||
@@ -442,8 +414,8 @@ describe('Deploy database', () => {
|
||||
],
|
||||
]);
|
||||
|
||||
await runQueryOnDriver(conn, driver, `insert into ~t1 (~id) values (1)`);
|
||||
const res = await runQueryOnDriver(conn, driver, ` select ~val from ~t1 where ~id = 1`);
|
||||
await driver.query(conn, `insert into t1 (id) values (1)`);
|
||||
const res = await driver.query(conn, ` select val from t1 where id = 1`);
|
||||
expect(res.rows[0].val.toString().substring(0, 2)).toEqual('20');
|
||||
})
|
||||
);
|
||||
@@ -466,7 +438,7 @@ describe('Deploy database', () => {
|
||||
},
|
||||
},
|
||||
],
|
||||
'insert into ~t1 (~id, ~val) values (1, 1); insert into ~t1 (~id) values (2)',
|
||||
'insert into t1 (id, val) values (1, 1); insert into t1 (id) values (2)',
|
||||
[
|
||||
{
|
||||
name: 't1.table.yaml',
|
||||
@@ -480,16 +452,16 @@ describe('Deploy database', () => {
|
||||
},
|
||||
},
|
||||
],
|
||||
'insert into ~t1 (~id) values (3);',
|
||||
'insert into t1 (id) values (3);',
|
||||
]);
|
||||
|
||||
const res1 = await runQueryOnDriver(conn, driver, `select ~val from ~t1 where ~id = 1`);
|
||||
const res1 = await driver.query(conn, `select val from t1 where id = 1`);
|
||||
expect(res1.rows[0].val).toEqual(1);
|
||||
|
||||
const res2 = await runQueryOnDriver(conn, driver, `select ~val from ~t1 where ~id = 2`);
|
||||
const res2 = await driver.query(conn, `select val from t1 where id = 2`);
|
||||
expect(res2.rows[0].val).toEqual(20);
|
||||
|
||||
const res3 = await runQueryOnDriver(conn, driver, `select ~val from ~t1 where ~id = 3`);
|
||||
const res3 = await driver.query(conn, `select val from t1 where id = 3`);
|
||||
expect(res2.rows[0].val).toEqual(20);
|
||||
})
|
||||
);
|
||||
@@ -553,17 +525,17 @@ describe('Deploy database', () => {
|
||||
|
||||
const V1 = {
|
||||
name: 'v1.view.sql',
|
||||
text: 'create view ~v1 as select * from ~t1',
|
||||
text: 'create view v1 as select * from t1',
|
||||
};
|
||||
|
||||
const V1_VARIANT2 = {
|
||||
name: 'v1.view.sql',
|
||||
text: 'create view ~v1 as select ~id + ~id ~idsum from ~t1',
|
||||
text: 'create view v1 as select 1 as c1',
|
||||
};
|
||||
|
||||
const V1_DELETED = {
|
||||
name: '_deleted_v1.view.sql',
|
||||
text: 'create view ~_deleted_v1 as select * from ~t1',
|
||||
text: 'create view _deleted_v1 as select * from t1',
|
||||
};
|
||||
|
||||
test.each(engines.map(engine => [engine.label, engine]))(
|
||||
@@ -710,15 +682,15 @@ describe('Deploy database', () => {
|
||||
[
|
||||
{
|
||||
name: '1.predeploy.sql',
|
||||
text: 'create table ~t1 (~id int primary key); insert into ~t1 (~id) values (1);',
|
||||
text: 'create table t1 (id int primary key); insert into t1 (id) values (1);',
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
const res1 = await runQueryOnDriver(conn, driver, 'SELECT COUNT(*) AS ~cnt FROM ~t1');
|
||||
const res1 = await driver.query(conn, 'SELECT COUNT(*) AS cnt FROM t1');
|
||||
expect(res1.rows[0].cnt == 1).toBeTruthy();
|
||||
|
||||
const res2 = await runQueryOnDriver(conn, driver, 'SELECT COUNT(*) AS ~cnt FROM ~dbgate_deploy_journal');
|
||||
const res2 = await driver.query(conn, 'SELECT COUNT(*) AS cnt FROM dbgate_deploy_journal');
|
||||
expect(res2.rows[0].cnt == 1).toBeTruthy();
|
||||
})
|
||||
);
|
||||
@@ -730,53 +702,48 @@ describe('Deploy database', () => {
|
||||
[
|
||||
{
|
||||
name: 't1.uninstall.sql',
|
||||
text: 'drop table ~t1',
|
||||
text: 'drop table t1',
|
||||
},
|
||||
{
|
||||
name: 't1.install.sql',
|
||||
text: 'create table ~t1 (~id int primary key); insert into ~t1 (~id) values (1)',
|
||||
text: 'create table t1 (id int primary key); insert into t1 (id) values (1)',
|
||||
},
|
||||
{
|
||||
name: 't2.once.sql',
|
||||
text: 'create table ~t2 (~id int primary key); insert into ~t2 (~id) values (1)',
|
||||
text: 'create table t2 (id int primary key); insert into t2 (id) values (1)',
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 't1.uninstall.sql',
|
||||
text: 'drop table ~t1',
|
||||
text: 'drop table t1',
|
||||
},
|
||||
{
|
||||
name: 't1.install.sql',
|
||||
text: 'create table ~t1 (~id int primary key, ~val int); insert into ~t1 (~id, ~val) values (1, 11)',
|
||||
text: 'create table t1 (id int primary key, val int); insert into t1 (id, val) values (1, 11)',
|
||||
},
|
||||
{
|
||||
name: 't2.once.sql',
|
||||
text: 'insert into ~t2 (~id) values (2)',
|
||||
text: 'insert into t2 (id) values (2)',
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
const res1 = await runQueryOnDriver(conn, driver, 'SELECT ~val from ~t1 where ~id = 1');
|
||||
const res1 = await driver.query(conn, 'SELECT val from t1 where id = 1');
|
||||
expect(res1.rows[0].val == 11).toBeTruthy();
|
||||
|
||||
const res2 = await runQueryOnDriver(conn, driver, 'SELECT COUNT(*) AS ~cnt FROM ~t2');
|
||||
const res2 = await driver.query(conn, 'SELECT COUNT(*) AS cnt FROM t2');
|
||||
expect(res2.rows[0].cnt == 1).toBeTruthy();
|
||||
|
||||
const res3 = await runQueryOnDriver(conn, driver, 'SELECT COUNT(*) AS ~cnt FROM ~dbgate_deploy_journal');
|
||||
const res3 = await driver.query(conn, 'SELECT COUNT(*) AS cnt FROM dbgate_deploy_journal');
|
||||
expect(res3.rows[0].cnt == 3).toBeTruthy();
|
||||
|
||||
const res4 = await runQueryOnDriver(
|
||||
conn,
|
||||
driver,
|
||||
"SELECT ~run_count from ~dbgate_deploy_journal where ~name = 't2.once.sql'"
|
||||
);
|
||||
const res4 = await driver.query(conn, "SELECT run_count from dbgate_deploy_journal where name = 't2.once.sql'");
|
||||
expect(res4.rows[0].run_count == 1).toBeTruthy();
|
||||
|
||||
const res5 = await runQueryOnDriver(
|
||||
const res5 = await driver.query(
|
||||
conn,
|
||||
driver,
|
||||
"SELECT ~run_count from ~dbgate_deploy_journal where ~name = 't1.install.sql'"
|
||||
"SELECT run_count from dbgate_deploy_journal where name = 't1.install.sql'"
|
||||
);
|
||||
expect(res5.rows[0].run_count == 2).toBeTruthy();
|
||||
})
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
const { testWrapper } = require('../tools');
|
||||
const engines = require('../engines');
|
||||
const _ = require('lodash');
|
||||
const { formatQueryWithoutParams, runCommandOnDriver } = require('dbgate-tools');
|
||||
|
||||
const initSql = ['CREATE TABLE ~t1 (~id int primary key)', 'CREATE TABLE ~t2 (~id int primary key)'];
|
||||
const initSql = ['CREATE TABLE t1 (id int primary key)', 'CREATE TABLE t2 (id int primary key)'];
|
||||
|
||||
function flatSource() {
|
||||
return _.flatten(
|
||||
@@ -19,16 +18,6 @@ function flatSourceParameters() {
|
||||
);
|
||||
}
|
||||
|
||||
function flatSourceTriggers() {
|
||||
return _.flatten(engines.map(engine => (engine.triggers || []).map(trigger => [engine.label, trigger, engine])));
|
||||
}
|
||||
|
||||
function flatSourceSchedulerEvents() {
|
||||
return _.flatten(
|
||||
engines.map(engine => (engine.schedulerEvents || []).map(schedulerEvent => [engine.label, schedulerEvent, engine]))
|
||||
);
|
||||
}
|
||||
|
||||
const obj1Match = expect.objectContaining({
|
||||
pureName: 'obj1',
|
||||
});
|
||||
@@ -45,9 +34,9 @@ describe('Object analyse', () => {
|
||||
test.each(flatSource())(
|
||||
'Full analysis - %s - %s',
|
||||
testWrapper(async (conn, driver, type, object, engine) => {
|
||||
for (const sql of initSql) await runCommandOnDriver(conn, driver, sql);
|
||||
for (const sql of initSql) await driver.query(conn, sql, { discardResult: true });
|
||||
|
||||
await runCommandOnDriver(conn, driver, object.create1);
|
||||
await driver.query(conn, object.create1, { discardResult: true });
|
||||
const structure = await driver.analyseFull(conn);
|
||||
|
||||
expect(structure[type].length).toEqual(1);
|
||||
@@ -58,11 +47,11 @@ describe('Object analyse', () => {
|
||||
test.each(flatSource())(
|
||||
'Incremental analysis - add - %s - %s',
|
||||
testWrapper(async (conn, driver, type, object, engine) => {
|
||||
for (const sql of initSql) await runCommandOnDriver(conn, driver, sql);
|
||||
for (const sql of initSql) await driver.query(conn, sql, { discardResult: true });
|
||||
|
||||
await runCommandOnDriver(conn, driver, object.create2);
|
||||
await driver.query(conn, object.create2, { discardResult: true });
|
||||
const structure1 = await driver.analyseFull(conn);
|
||||
await runCommandOnDriver(conn, driver, object.create1);
|
||||
await driver.query(conn, object.create1, { discardResult: true });
|
||||
const structure2 = await driver.analyseIncremental(conn, structure1);
|
||||
|
||||
expect(structure2[type].length).toEqual(2);
|
||||
@@ -73,12 +62,12 @@ describe('Object analyse', () => {
|
||||
test.each(flatSource())(
|
||||
'Incremental analysis - drop - %s - %s',
|
||||
testWrapper(async (conn, driver, type, object, engine) => {
|
||||
for (const sql of initSql) await runCommandOnDriver(conn, driver, sql);
|
||||
for (const sql of initSql) await driver.query(conn, sql, { discardResult: true });
|
||||
|
||||
await runCommandOnDriver(conn, driver, object.create1);
|
||||
await runCommandOnDriver(conn, driver, object.create2);
|
||||
await driver.query(conn, object.create1, { discardResult: true });
|
||||
await driver.query(conn, object.create2, { discardResult: true });
|
||||
const structure1 = await driver.analyseFull(conn);
|
||||
await runCommandOnDriver(conn, driver, object.drop2);
|
||||
await driver.query(conn, object.drop2, { discardResult: true });
|
||||
const structure2 = await driver.analyseIncremental(conn, structure1);
|
||||
|
||||
expect(structure2[type].length).toEqual(1);
|
||||
@@ -89,11 +78,11 @@ describe('Object analyse', () => {
|
||||
test.each(flatSource())(
|
||||
'Create SQL - add - %s - %s',
|
||||
testWrapper(async (conn, driver, type, object, engine) => {
|
||||
for (const sql of initSql) await runCommandOnDriver(conn, driver, sql);
|
||||
for (const sql of initSql) await driver.query(conn, sql, { discardResult: true });
|
||||
|
||||
await runCommandOnDriver(conn, driver, object.create1);
|
||||
await driver.query(conn, object.create1, { discardResult: true });
|
||||
const structure1 = await driver.analyseFull(conn);
|
||||
await runCommandOnDriver(conn, driver, object.drop1);
|
||||
await driver.query(conn, object.drop1, { discardResult: true });
|
||||
const structure2 = await driver.analyseIncremental(conn, structure1);
|
||||
expect(structure2[type].length).toEqual(0);
|
||||
|
||||
@@ -106,94 +95,44 @@ describe('Object analyse', () => {
|
||||
})
|
||||
);
|
||||
|
||||
const flatParameters = flatSourceParameters();
|
||||
test.each(flatSourceParameters())(
|
||||
'Test parameters simple analyse - %s - %s',
|
||||
testWrapper(async (conn, driver, testName, parameter, engine) => {
|
||||
for (const sql of initSql) await driver.query(conn, sql, { discardResult: true });
|
||||
for (const sql of engine.parametersOtherSql) await driver.query(conn, sql, { discardResult: true });
|
||||
|
||||
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);
|
||||
await driver.query(conn, parameter.create, { discardResult: true });
|
||||
const structure = await driver.analyseFull(conn);
|
||||
await runCommandOnDriver(conn, driver, drop);
|
||||
|
||||
if (triggerOtherDropSql) await runCommandOnDriver(conn, driver, triggerOtherDropSql);
|
||||
const parameters = structure[parameter.objectTypeField].find(x => x.pureName == 'obj1').parameters;
|
||||
|
||||
const createdTrigger = structure[objectTypeField].find(x => x.pureName == expected.pureName);
|
||||
expect(createdTrigger).toEqual(expect.objectContaining(expected));
|
||||
|
||||
// test trigger createSql
|
||||
if (triggerOtherCreateSql) await runCommandOnDriver(conn, driver, triggerOtherCreateSql);
|
||||
|
||||
await driver.script(conn, createdTrigger.createSql);
|
||||
const structure2 = await driver.analyseFull(conn);
|
||||
const createdTrigger2 = structure2[objectTypeField].find(x => x.pureName == expected.pureName);
|
||||
expect(createdTrigger2).toEqual(expect.objectContaining(expected));
|
||||
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 schedulerEvents = flatSourceSchedulerEvents();
|
||||
if (schedulerEvents.length > 0) {
|
||||
test.each(schedulerEvents)(
|
||||
'Test scheduler events - %s - %s',
|
||||
testWrapper(async (conn, driver, event) => {
|
||||
for (const sql of initSql) await runCommandOnDriver(conn, driver, sql);
|
||||
const { create, drop, objectTypeField, expected } = event;
|
||||
test.each(flatSourceParameters())(
|
||||
'Test parameters create SQL - %s - %s',
|
||||
testWrapper(async (conn, driver, testName, parameter, engine) => {
|
||||
for (const sql of initSql) await driver.query(conn, sql, { discardResult: true });
|
||||
for (const sql of engine.parametersOtherSql) await driver.query(conn, sql, { discardResult: true });
|
||||
|
||||
await runCommandOnDriver(conn, driver, create);
|
||||
const structure = await driver.analyseFull(conn);
|
||||
await runCommandOnDriver(conn, driver, drop);
|
||||
await driver.query(conn, parameter.create, { discardResult: true });
|
||||
const structure1 = await driver.analyseFull(conn);
|
||||
await driver.query(conn, parameter.drop, { discardResult: true });
|
||||
|
||||
const createdEvent = structure[objectTypeField].find(x => x.pureName == expected.pureName);
|
||||
expect(createdEvent).toEqual(expect.objectContaining(expected));
|
||||
})
|
||||
);
|
||||
}
|
||||
const obj = structure1[parameter.objectTypeField].find(x => x.pureName == 'obj1');
|
||||
await driver.script(conn, obj.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]));
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
const engines = require('../engines');
|
||||
const { splitQuery } = require('dbgate-query-splitter');
|
||||
const { testWrapper } = require('../tools');
|
||||
const { runQueryOnDriver, runCommandOnDriver, formatQueryWithoutParams } = require('dbgate-tools');
|
||||
|
||||
const initSql = [
|
||||
'CREATE TABLE ~t1 (~id int primary key)',
|
||||
'INSERT INTO ~t1 (~id) VALUES (1)',
|
||||
'INSERT INTO ~t1 (~id) VALUES (2)',
|
||||
'CREATE TABLE t1 (id int primary key)',
|
||||
'INSERT INTO t1 (id) VALUES (1)',
|
||||
'INSERT INTO t1 (id) VALUES (2)',
|
||||
];
|
||||
|
||||
expect.extend({
|
||||
@@ -52,7 +51,7 @@ class StreamHandler {
|
||||
function executeStreamItem(driver, conn, sql) {
|
||||
return new Promise(resolve => {
|
||||
const handler = new StreamHandler(resolve);
|
||||
driver.stream(conn, formatQueryWithoutParams(driver, sql), handler);
|
||||
driver.stream(conn, sql, handler);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -69,11 +68,9 @@ describe('Query', () => {
|
||||
test.each(engines.map(engine => [engine.label, engine]))(
|
||||
'Simple query - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
for (const sql of initSql) {
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(sql));
|
||||
}
|
||||
for (const sql of initSql) await driver.query(conn, sql, { discardResult: true });
|
||||
|
||||
const res = await runQueryOnDriver(conn, driver, dmp => dmp.put('SELECT ~id FROM ~t1 ORDER BY ~id'));
|
||||
const res = await driver.query(conn, 'SELECT id FROM t1 ORDER BY id');
|
||||
expect(res.columns).toEqual([
|
||||
expect.objectContaining({
|
||||
columnName: 'id',
|
||||
@@ -94,11 +91,8 @@ describe('Query', () => {
|
||||
test.each(engines.map(engine => [engine.label, engine]))(
|
||||
'Simple stream query - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
for (const sql of initSql) {
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(sql));
|
||||
}
|
||||
|
||||
const results = await executeStream(driver, conn, 'SELECT ~id FROM ~t1 ORDER BY ~id');
|
||||
for (const sql of initSql) await driver.query(conn, sql, { discardResult: true });
|
||||
const results = await executeStream(driver, conn, 'SELECT id FROM t1 ORDER BY id');
|
||||
expect(results.length).toEqual(1);
|
||||
const res = results[0];
|
||||
|
||||
@@ -110,14 +104,11 @@ describe('Query', () => {
|
||||
test.each(engines.map(engine => [engine.label, engine]))(
|
||||
'More queries - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
for (const sql of initSql) {
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(sql));
|
||||
}
|
||||
|
||||
for (const sql of initSql) await driver.query(conn, sql, { discardResult: true });
|
||||
const results = await executeStream(
|
||||
driver,
|
||||
conn,
|
||||
'SELECT ~id FROM ~t1 ORDER BY ~id; SELECT ~id FROM ~t1 ORDER BY ~id DESC'
|
||||
'SELECT id FROM t1 ORDER BY id; SELECT id FROM t1 ORDER BY id DESC'
|
||||
);
|
||||
expect(results.length).toEqual(2);
|
||||
|
||||
@@ -137,7 +128,7 @@ describe('Query', () => {
|
||||
const results = await executeStream(
|
||||
driver,
|
||||
conn,
|
||||
'CREATE TABLE ~t1 (~id int primary key); INSERT INTO ~t1 (~id) VALUES (1); INSERT INTO ~t1 (~id) VALUES (2); SELECT ~id FROM ~t1 ORDER BY ~id; '
|
||||
'CREATE TABLE t1 (id int primary key); INSERT INTO t1 (id) VALUES (1); INSERT INTO t1 (id) VALUES (2); SELECT id FROM t1 ORDER BY id; '
|
||||
);
|
||||
expect(results.length).toEqual(1);
|
||||
|
||||
@@ -153,7 +144,7 @@ describe('Query', () => {
|
||||
const results = await executeStream(
|
||||
driver,
|
||||
conn,
|
||||
'CREATE TABLE ~t1 (~id int); INSERT INTO ~t1 (~id) VALUES (1); INSERT INTO ~t1 (~id) VALUES (2) '
|
||||
'CREATE TABLE t1 (id int); INSERT INTO t1 (id) VALUES (1); INSERT INTO t1 (id) VALUES (2) '
|
||||
);
|
||||
expect(results.length).toEqual(0);
|
||||
})
|
||||
@@ -162,57 +153,16 @@ describe('Query', () => {
|
||||
test.each(engines.filter(x => !x.skipDataModifications).map(engine => [engine.label, engine]))(
|
||||
'Save data query - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
for (const sql of initSql) {
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(sql));
|
||||
}
|
||||
for (const sql of initSql) await driver.query(conn, sql, { discardResult: true });
|
||||
|
||||
await driver.script(
|
||||
conn,
|
||||
formatQueryWithoutParams(
|
||||
driver,
|
||||
'INSERT INTO ~t1 (~id) VALUES (3);INSERT INTO ~t1 (~id) VALUES (4);UPDATE ~t1 SET ~id=10 WHERE ~id=1;DELETE FROM ~t1 WHERE ~id=2;'
|
||||
),
|
||||
'INSERT INTO t1 (id) VALUES (3);INSERT INTO t1 (id) VALUES (4);UPDATE t1 SET id=10 WHERE id=1;DELETE FROM t1 WHERE id=2;',
|
||||
{ discardResult: true }
|
||||
);
|
||||
const res = await runQueryOnDriver(conn, driver, dmp => dmp.put('SELECT COUNT(*) AS ~cnt FROM ~t1'));
|
||||
const res = await driver.query(conn, 'SELECT COUNT(*) AS cnt FROM t1');
|
||||
// console.log(res);
|
||||
expect(res.rows[0].cnt == 3).toBeTruthy();
|
||||
})
|
||||
);
|
||||
|
||||
test.each(engines.filter(x => !x.skipDataDuplicator).map(engine => [engine.label, engine]))(
|
||||
'Select scope identity - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await runCommandOnDriver(conn, driver, dmp =>
|
||||
dmp.createTable({
|
||||
pureName: 't1',
|
||||
columns: [
|
||||
{ columnName: 'id', dataType: 'int', notNull: true, autoIncrement: true },
|
||||
{ columnName: 'val', dataType: 'varchar(50)' },
|
||||
],
|
||||
primaryKey: {
|
||||
columns: [{ columnName: 'id' }],
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
const structure = await driver.analyseFull(conn);
|
||||
const table = structure.tables.find(x => x.pureName == 't1');
|
||||
|
||||
let res;
|
||||
if (driver.dialect.requireStandaloneSelectForScopeIdentity) {
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put("INSERT INTO ~t1 (~val) VALUES ('aaa')"));
|
||||
res = await runQueryOnDriver(conn, driver, dmp => dmp.selectScopeIdentity(table));
|
||||
} else {
|
||||
res = await runQueryOnDriver(conn, driver, dmp => {
|
||||
dmp.putCmd("INSERT INTO ~t1 (~val) VALUES ('aaa')");
|
||||
dmp.selectScopeIdentity(table);
|
||||
});
|
||||
}
|
||||
const row = res.rows[0];
|
||||
const keys = Object.keys(row);
|
||||
expect(keys.length).toEqual(1);
|
||||
expect(row[keys[0]] == 1).toBeTruthy();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const stableStringify = require('json-stable-stringify');
|
||||
const _ = require('lodash');
|
||||
const fp = require('lodash/fp');
|
||||
const { testWrapper } = require('../tools');
|
||||
const { testWrapper, extractConnection } = require('../tools');
|
||||
const engines = require('../engines');
|
||||
const { runCommandOnDriver } = require('dbgate-tools');
|
||||
|
||||
@@ -62,7 +62,7 @@ describe('Schema tests', () => {
|
||||
await runCommandOnDriver(handle, driver, dmp => dmp.createSchema('myschema'));
|
||||
|
||||
const schemaConnDef = {
|
||||
...engine.connection,
|
||||
...extractConnection(engine),
|
||||
database: `${handle.database}::myschema`,
|
||||
};
|
||||
|
||||
@@ -76,7 +76,7 @@ describe('Schema tests', () => {
|
||||
});
|
||||
|
||||
describe('Base analyser test', () => {
|
||||
test.each(engines.filter(x => !x.skipIncrementalAnalysis).map(engine => [engine.label, engine]))(
|
||||
test.each(engines.map(engine => [engine.label, engine]))(
|
||||
'Structure without change - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await baseStructure(conn, driver);
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
const { runCommandOnDriver } = require('dbgate-tools');
|
||||
const engines = require('../engines');
|
||||
const { testWrapper } = require('../tools');
|
||||
|
||||
const t1Sql = 'CREATE TABLE ~t1 (~id int not null primary key, ~val1 varchar(50))';
|
||||
const ix1Sql = 'CREATE index ~ix1 ON ~t1(~val1, ~id)';
|
||||
const t1Sql = 'CREATE TABLE t1 (id int not null primary key, val1 varchar(50))';
|
||||
const ix1Sql = 'CREATE index ix1 ON t1(val1, id)';
|
||||
const t2Sql = engine =>
|
||||
`CREATE TABLE ~t2 (~id int not null primary key, ~val2 varchar(50) ${engine.skipUnique ? '' : 'unique'})`;
|
||||
const t3Sql = 'CREATE TABLE ~t3 (~id int not null primary key, ~valfk int, foreign key (~valfk) references ~t2(~id))';
|
||||
const t4Sql = 'CREATE TABLE ~t4 (~id int not null primary key, ~valdef int default 12 not null)';
|
||||
`CREATE TABLE t2 (id int not null primary key, val2 varchar(50) ${engine.skipUnique ? '' : 'unique'})`;
|
||||
const t3Sql = 'CREATE TABLE t3 (id int not null primary key, valfk int, foreign key (valfk) references t2(id))';
|
||||
const t4Sql = 'CREATE TABLE t4 (id int not null primary key, valdef int not null default 12)';
|
||||
// const fkSql = 'ALTER TABLE t3 ADD FOREIGN KEY (valfk) REFERENCES t2(id)'
|
||||
|
||||
const txMatch = (engine, tname, vcolname, nextcol, defaultValue) =>
|
||||
@@ -16,7 +15,7 @@ const txMatch = (engine, tname, vcolname, nextcol, defaultValue) =>
|
||||
columns: [
|
||||
expect.objectContaining({
|
||||
columnName: 'id',
|
||||
dataType: expect.stringMatching(/int.*|number/i),
|
||||
dataType: expect.stringMatching(/int.*/i),
|
||||
...(engine.skipNullability ? {} : { notNull: true }),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
@@ -60,10 +59,9 @@ describe('Table analyse', () => {
|
||||
test.each(engines.map(engine => [engine.label, engine]))(
|
||||
'Table structure - full analysis - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(t1Sql));
|
||||
await driver.query(conn, t1Sql);
|
||||
|
||||
const structure = await driver.analyseFull(conn);
|
||||
console.log(JSON.stringify(structure, null, 2));
|
||||
|
||||
expect(structure.tables.length).toEqual(1);
|
||||
expect(structure.tables[0]).toEqual(t1Match(engine));
|
||||
@@ -73,13 +71,13 @@ describe('Table analyse', () => {
|
||||
test.each(engines.map(engine => [engine.label, engine]))(
|
||||
'Table add - incremental analysis - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(t2Sql(engine)));
|
||||
await driver.query(conn, t2Sql(engine));
|
||||
|
||||
const structure1 = await driver.analyseFull(conn);
|
||||
expect(structure1.tables.length).toEqual(1);
|
||||
expect(structure1.tables[0]).toEqual(t2Match(engine));
|
||||
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(t1Sql));
|
||||
await driver.query(conn, t1Sql);
|
||||
const structure2 = await driver.analyseIncremental(conn, structure1);
|
||||
|
||||
expect(structure2.tables.length).toEqual(2);
|
||||
@@ -91,14 +89,14 @@ describe('Table analyse', () => {
|
||||
test.each(engines.map(engine => [engine.label, engine]))(
|
||||
'Table remove - incremental analysis - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(t1Sql));
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(t2Sql(engine)));
|
||||
await driver.query(conn, t1Sql);
|
||||
await driver.query(conn, t2Sql(engine));
|
||||
const structure1 = await driver.analyseFull(conn);
|
||||
expect(structure1.tables.length).toEqual(2);
|
||||
expect(structure1.tables.find(x => x.pureName == 't1')).toEqual(t1Match(engine));
|
||||
expect(structure1.tables.find(x => x.pureName == 't2')).toEqual(t2Match(engine));
|
||||
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put('DROP TABLE ~t2'));
|
||||
await driver.query(conn, 'DROP TABLE t2');
|
||||
const structure2 = await driver.analyseIncremental(conn, structure1);
|
||||
|
||||
expect(structure2.tables.length).toEqual(1);
|
||||
@@ -109,14 +107,15 @@ describe('Table analyse', () => {
|
||||
test.each(engines.map(engine => [engine.label, engine]))(
|
||||
'Table change - incremental analysis - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(t1Sql));
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(t2Sql(engine)));
|
||||
await driver.query(conn, t1Sql);
|
||||
await driver.query(conn, t2Sql(engine));
|
||||
const structure1 = await driver.analyseFull(conn);
|
||||
|
||||
if (engine.dbSnapshotBySeconds) await new Promise(resolve => setTimeout(resolve, 1100));
|
||||
|
||||
await runCommandOnDriver(conn, driver, dmp =>
|
||||
dmp.put(`ALTER TABLE ~t2 ADD ${engine.alterTableAddColumnSyntax ? 'COLUMN' : ''} ~nextcol varchar(50)`)
|
||||
await driver.query(
|
||||
conn,
|
||||
`ALTER TABLE t2 ADD ${engine.alterTableAddColumnSyntax ? 'COLUMN' : ''} nextcol varchar(50)`
|
||||
);
|
||||
const structure2 = await driver.analyseIncremental(conn, structure1);
|
||||
|
||||
@@ -131,8 +130,8 @@ describe('Table analyse', () => {
|
||||
test.each(engines.filter(x => !x.skipIndexes).map(engine => [engine.label, engine]))(
|
||||
'Index - full analysis - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(t1Sql));
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(ix1Sql));
|
||||
await driver.query(conn, t1Sql);
|
||||
await driver.query(conn, ix1Sql);
|
||||
const structure = await driver.analyseFull(conn);
|
||||
|
||||
const t1 = structure.tables.find(x => x.pureName == 't1');
|
||||
@@ -146,7 +145,7 @@ describe('Table analyse', () => {
|
||||
test.each(engines.filter(x => !x.skipUnique).map(engine => [engine.label, engine]))(
|
||||
'Unique - full analysis - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(t2Sql(engine)));
|
||||
await driver.query(conn, t2Sql(engine));
|
||||
const structure = await driver.analyseFull(conn);
|
||||
|
||||
const t2 = structure.tables.find(x => x.pureName == 't2');
|
||||
@@ -160,8 +159,8 @@ describe('Table analyse', () => {
|
||||
test.each(engines.filter(x => !x.skipReferences).map(engine => [engine.label, engine]))(
|
||||
'Foreign key - full analysis - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(t2Sql(engine)));
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(t3Sql));
|
||||
await driver.query(conn, t2Sql(engine));
|
||||
await driver.query(conn, t3Sql);
|
||||
// await driver.query(conn, fkSql);
|
||||
|
||||
const structure = await driver.analyseFull(conn);
|
||||
@@ -180,7 +179,7 @@ describe('Table analyse', () => {
|
||||
test.each(engines.map(engine => [engine.label, engine]))(
|
||||
'Table structure - default value - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put(t4Sql));
|
||||
await driver.query(conn, t4Sql);
|
||||
|
||||
const structure = await driver.analyseFull(conn);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ const _ = require('lodash');
|
||||
const fp = require('lodash/fp');
|
||||
const engines = require('../engines');
|
||||
const { testWrapper } = require('../tools');
|
||||
const { extendDatabaseInfo, runCommandOnDriver } = require('dbgate-tools');
|
||||
const { extendDatabaseInfo } = require('dbgate-tools');
|
||||
|
||||
function createExpector(value) {
|
||||
return _.cloneDeepWith(value, x => {
|
||||
@@ -25,7 +25,7 @@ function checkTableStructure2(t1, t2) {
|
||||
}
|
||||
|
||||
async function testTableCreate(conn, driver, table) {
|
||||
await runCommandOnDriver(conn, driver, dmp => dmp.put('create table ~t0 (~id int not null primary key)'));
|
||||
await driver.query(conn, `create table t0 (id int not null primary key)`);
|
||||
|
||||
const dmp = driver.createDumper();
|
||||
const table1 = {
|
||||
|
||||
@@ -71,8 +71,8 @@ services:
|
||||
# restart: on-failure
|
||||
|
||||
oracle:
|
||||
image: gvenzl/oracle-xe:21-slim
|
||||
image: container-registry.oracle.com/database/express:21.3.0-xe
|
||||
environment:
|
||||
ORACLE_PASSWORD: Pwd2020Db
|
||||
ORACLE_PWD: Pwd2020Db
|
||||
ports:
|
||||
- 15006:1521
|
||||
|
||||
+399
-587
File diff suppressed because it is too large
Load Diff
@@ -11,11 +11,14 @@
|
||||
"scripts": {
|
||||
"wait:local": "cross-env DEVMODE=1 LOCALTEST=1 node wait.js",
|
||||
"wait:ci": "cross-env DEVMODE=1 CITEST=1 node wait.js",
|
||||
"test:local": "cross-env DEVMODE=1 LOCALTEST=1 jest --testTimeout=5000",
|
||||
"test:local": "cross-env DEVMODE=1 LOCALTEST=1 jest",
|
||||
"test:local:path": "cross-env DEVMODE=1 LOCALTEST=1 jest --runTestsByPath __tests__/data-duplicator.spec.js",
|
||||
"test:ci": "cross-env DEVMODE=1 CITEST=1 jest --runInBand --json --outputFile=result.json --testLocationInResults --detectOpenHandles --forceExit --testTimeout=10000",
|
||||
"test:ci": "cross-env DEVMODE=1 CITEST=1 jest --runInBand --json --outputFile=result.json --testLocationInResults --detectOpenHandles --forceExit",
|
||||
"run:local": "docker-compose down && docker-compose up -d && yarn wait:local && yarn test:local"
|
||||
},
|
||||
"jest": {
|
||||
"testTimeout": 5000
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "^7.0.3",
|
||||
"jest": "^27.0.1",
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
const requireEngineDriver = require('dbgate-api/src/utility/requireEngineDriver');
|
||||
const crypto = require('crypto');
|
||||
|
||||
function randomDbName(dialect) {
|
||||
function randomDbName() {
|
||||
const generatedKey = crypto.randomBytes(6);
|
||||
const newKey = generatedKey.toString('hex');
|
||||
const res = `db${newKey}`;
|
||||
if (dialect.upperCaseAllDbObjectNames) return res.toUpperCase();
|
||||
return res;
|
||||
return `db${newKey}`;
|
||||
}
|
||||
|
||||
function extractConnection(engine) {
|
||||
const { connection } = engine;
|
||||
|
||||
if (process.env.LOCALTEST && engine.local) {
|
||||
return {
|
||||
...connection,
|
||||
...engine.local,
|
||||
};
|
||||
}
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
async function connect(engine, database) {
|
||||
const { connection } = engine;
|
||||
const connection = extractConnection(engine);
|
||||
const driver = requireEngineDriver(connection);
|
||||
|
||||
if (engine.generateDbFile) {
|
||||
@@ -35,7 +46,7 @@ async function connect(engine, database) {
|
||||
}
|
||||
|
||||
async function prepareConnection(engine, database) {
|
||||
const { connection } = engine;
|
||||
const connection = extractConnection(engine);
|
||||
const driver = requireEngineDriver(connection);
|
||||
|
||||
if (engine.generateDbFile) {
|
||||
@@ -64,7 +75,7 @@ const testWrapper =
|
||||
async (label, ...other) => {
|
||||
const engine = other[other.length - 1];
|
||||
const driver = requireEngineDriver(engine.connection);
|
||||
const conn = await connect(engine, randomDbName(driver.dialect));
|
||||
const conn = await connect(engine, randomDbName());
|
||||
try {
|
||||
await body(conn, driver, ...other);
|
||||
} finally {
|
||||
@@ -77,13 +88,14 @@ const testWrapperPrepareOnly =
|
||||
async (label, ...other) => {
|
||||
const engine = other[other.length - 1];
|
||||
const driver = requireEngineDriver(engine.connection);
|
||||
const conn = await prepareConnection(engine, randomDbName(driver.dialect));
|
||||
const conn = await prepareConnection(engine, randomDbName());
|
||||
await body(conn, driver, ...other);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
randomDbName,
|
||||
connect,
|
||||
extractConnection,
|
||||
testWrapper,
|
||||
testWrapperPrepareOnly,
|
||||
};
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
const requireEngineDriver = require('dbgate-api/src/utility/requireEngineDriver');
|
||||
const engines = require('./engines');
|
||||
const { extractConnection } = require('./tools');
|
||||
global.DBGATE_PACKAGES = {
|
||||
'dbgate-tools': require('dbgate-tools'),
|
||||
'dbgate-sqltree': require('dbgate-sqltree'),
|
||||
};
|
||||
|
||||
async function connectEngine(engine) {
|
||||
const { connection } = engine;
|
||||
const connection = extractConnection(engine);
|
||||
const driver = requireEngineDriver(connection);
|
||||
for (;;) {
|
||||
try {
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"version": "6.1.3-beta.1",
|
||||
"version": "6.0.1-packer-beta.2",
|
||||
"name": "dbgate-all",
|
||||
"workspaces": [
|
||||
"packages/*",
|
||||
@@ -47,6 +47,7 @@
|
||||
"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",
|
||||
@@ -62,8 +63,7 @@
|
||||
"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",
|
||||
"workflows": "node common/processWorkflows.js"
|
||||
"dbgate-serve": "node packages/dbgate/bin/dbgate-serve.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.3",
|
||||
"dbgate-query-splitter": "^4.11.2",
|
||||
"dbgate-sqltree": "^6.0.0-alpha.1",
|
||||
"dbgate-tools": "^6.0.0-alpha.1",
|
||||
"debug": "^4.3.4",
|
||||
@@ -60,7 +60,7 @@
|
||||
"rimraf": "^3.0.0",
|
||||
"semver": "^7.6.3",
|
||||
"simple-encryptor": "^4.0.0",
|
||||
"ssh2": "^1.16.0",
|
||||
"ssh2": "^1.11.0",
|
||||
"stream-json": "^1.8.0",
|
||||
"tar": "^6.0.5"
|
||||
},
|
||||
|
||||
@@ -230,7 +230,7 @@ class LoginsProvider extends AuthProviderBase {
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
return { error: 'Invalid credentials' };
|
||||
}
|
||||
|
||||
@@ -271,10 +271,11 @@ function hasEnvLogins() {
|
||||
return false;
|
||||
}
|
||||
|
||||
function detectEnvAuthProviderCore() {
|
||||
function detectEnvAuthProvider() {
|
||||
if (process.env.AUTH_PROVIDER) {
|
||||
return process.env.AUTH_PROVIDER;
|
||||
}
|
||||
|
||||
if (process.env.STORAGE_DATABASE) {
|
||||
return 'denyall';
|
||||
}
|
||||
@@ -290,14 +291,6 @@ function detectEnvAuthProviderCore() {
|
||||
return 'none';
|
||||
}
|
||||
|
||||
function detectEnvAuthProvider() {
|
||||
const authProvider = detectEnvAuthProviderCore();
|
||||
if (process.env.BASIC_AUTH && authProvider != 'logins' && authProvider != 'ad') {
|
||||
throw new Error(`BASIC_AUTH is not supported with ${authProvider} auth provider`);
|
||||
}
|
||||
return authProvider;
|
||||
}
|
||||
|
||||
function createEnvAuthProvider() {
|
||||
const authProvider = detectEnvAuthProvider();
|
||||
switch (authProvider) {
|
||||
|
||||
@@ -9,7 +9,6 @@ const _ = require('lodash');
|
||||
const AsyncLock = require('async-lock');
|
||||
const jwt = require('jsonwebtoken');
|
||||
|
||||
const processArgs = require('../utility/processArgs');
|
||||
const currentVersion = require('../currentVersion');
|
||||
const platformInfo = require('../utility/platformInfo');
|
||||
const connections = require('../controllers/connections');
|
||||
@@ -84,8 +83,7 @@ module.exports = {
|
||||
isElectron: platformInfo.isElectron,
|
||||
isLicenseValid,
|
||||
isLicenseExpired: checkedLicense?.isExpired,
|
||||
trialDaysLeft:
|
||||
checkedLicense?.licenseTypeObj?.isTrial && !checkedLicense?.isExpired ? checkedLicense?.daysLeft : null,
|
||||
trialDaysLeft: checkedLicense?.licenseTypeObj?.isTrial && !checkedLicense?.isExpired ? checkedLicense?.daysLeft : null,
|
||||
checkedLicense,
|
||||
configurationError,
|
||||
logoutUrl,
|
||||
@@ -103,10 +101,7 @@ module.exports = {
|
||||
adminPasswordState: adminConfig?.adminPasswordState,
|
||||
storageDatabase: process.env.STORAGE_DATABASE,
|
||||
logsFilePath: getLogsFilePath(),
|
||||
connectionsFilePath: path.join(
|
||||
datadir(),
|
||||
processArgs.runE2eTests ? 'connections-e2etests.jsonl' : 'connections.jsonl'
|
||||
),
|
||||
connectionsFilePath: path.join(datadir(), 'connections.jsonl'),
|
||||
...currentVersion,
|
||||
};
|
||||
|
||||
|
||||
@@ -199,9 +199,7 @@ module.exports = {
|
||||
const dir = datadir();
|
||||
if (!portalConnections) {
|
||||
// @ts-ignore
|
||||
this.datastore = new JsonLinesDatabase(
|
||||
path.join(dir, processArgs.runE2eTests ? 'connections-e2etests.jsonl' : 'connections.jsonl')
|
||||
);
|
||||
this.datastore = new JsonLinesDatabase(path.join(dir, 'connections.jsonl'));
|
||||
}
|
||||
await this.checkUnsavedConnectionsLimit();
|
||||
},
|
||||
@@ -222,7 +220,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
test_meta: true,
|
||||
test({ connection, requestDbList = false }) {
|
||||
test(connection) {
|
||||
const subprocess = fork(
|
||||
global['API_PACKAGE'] || process.argv[1],
|
||||
[
|
||||
@@ -237,7 +235,7 @@ module.exports = {
|
||||
}
|
||||
);
|
||||
pipeForkLogs(subprocess);
|
||||
subprocess.send({ ...connection, requestDbList });
|
||||
subprocess.send(connection);
|
||||
return new Promise(resolve => {
|
||||
subprocess.on('message', resp => {
|
||||
if (handleProcessCommunication(resp, subprocess)) return;
|
||||
@@ -267,7 +265,7 @@ module.exports = {
|
||||
}
|
||||
|
||||
if (test) {
|
||||
const testRes = await this.test({ connection: res });
|
||||
const testRes = await this.test(res);
|
||||
if (testRes.msgtype == 'connected') {
|
||||
volatileConnections[res._id] = res;
|
||||
return {
|
||||
|
||||
@@ -49,8 +49,7 @@ logger.info('Finished job script');
|
||||
dbgateApi.runScript(run);
|
||||
`;
|
||||
|
||||
const loaderScriptTemplate = (prefix, functionName, props, runid) => `
|
||||
${prefix}
|
||||
const loaderScriptTemplate = (functionName, props, runid) => `
|
||||
const dbgateApi = require(process.env.DBGATE_API);
|
||||
dbgateApi.initializeApiEnvironment();
|
||||
${requirePluginsTemplate(extractShellApiPlugins(functionName, props))}
|
||||
@@ -150,7 +149,7 @@ module.exports = {
|
||||
byline(subprocess.stdout).on('data', pipeDispatcher('info'));
|
||||
byline(subprocess.stderr).on('data', pipeDispatcher('error'));
|
||||
subprocess.on('exit', code => {
|
||||
this.rejectRequest(runid, { message: 'No data returned, maybe input data source is too big' });
|
||||
this.rejectRequest(runid, { message: 'No data retured, maybe input data source is too big' });
|
||||
logger.info({ code, pid: subprocess.pid }, 'Exited process');
|
||||
socket.emit(`runner-done-${runid}`, code);
|
||||
});
|
||||
@@ -225,14 +224,10 @@ module.exports = {
|
||||
|
||||
loadReader_meta: true,
|
||||
async loadReader({ functionName, props }) {
|
||||
const prefix = extractShellApiPlugins(functionName)
|
||||
.map(packageName => `// @require ${packageName}\n`)
|
||||
.join('');
|
||||
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const runid = crypto.randomUUID();
|
||||
this.requests[runid] = [resolve, reject];
|
||||
this.startCore(runid, loaderScriptTemplate(prefix, functionName, props, runid));
|
||||
this.startCore(runid, loaderScriptTemplate(functionName, props, runid));
|
||||
});
|
||||
return promise;
|
||||
},
|
||||
|
||||
@@ -17,18 +17,12 @@ 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);
|
||||
let databases = undefined;
|
||||
if (requestDbList) {
|
||||
databases = await driver.listDatabases(dbhan);
|
||||
}
|
||||
process.send({ msgtype: 'connected', ...res, databases });
|
||||
process.send({ msgtype: 'connected', ...res });
|
||||
await driver.close(dbhan);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
||||
@@ -166,9 +166,7 @@ function start() {
|
||||
if (time - lastPing > 40 * 1000) {
|
||||
logger.info('Server connection not alive, exiting');
|
||||
const driver = requireEngineDriver(storedConnection);
|
||||
if (dbhan) {
|
||||
await driver.close(dbhan);
|
||||
}
|
||||
await driver.close(dbhan);
|
||||
process.exit(0);
|
||||
}
|
||||
}, 10 * 1000);
|
||||
|
||||
@@ -7,7 +7,7 @@ const { getLogger, extractErrorLogData, extractErrorMessage } = require('dbgate-
|
||||
|
||||
const logger = getLogger('sshProcess');
|
||||
|
||||
async function getSshConnection(connection, tunnelConfig) {
|
||||
async function getSshConnection(connection) {
|
||||
const sshConfig = {
|
||||
endHost: connection.sshHost || '',
|
||||
endPort: connection.sshPort || 22,
|
||||
@@ -23,7 +23,6 @@ async function getSshConnection(connection, tunnelConfig) {
|
||||
: undefined,
|
||||
skipAutoPrivateKey: true,
|
||||
noReadline: true,
|
||||
bindHost: tunnelConfig.fromHost,
|
||||
};
|
||||
|
||||
const sshConn = new SSHConnection(sshConfig);
|
||||
@@ -32,7 +31,7 @@ async function getSshConnection(connection, tunnelConfig) {
|
||||
|
||||
async function handleStart({ connection, tunnelConfig }) {
|
||||
try {
|
||||
const sshConn = await getSshConnection(connection, tunnelConfig);
|
||||
const sshConn = await getSshConnection(connection);
|
||||
await sshConn.forward(tunnelConfig);
|
||||
|
||||
process.send({
|
||||
|
||||
@@ -8,15 +8,12 @@ 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, driver }) {
|
||||
if (!driver) {
|
||||
driver = requireEngineDriver(connection);
|
||||
}
|
||||
async function tableReader({ connection, systemConnection, pureName, schemaName }) {
|
||||
const driver = requireEngineDriver(connection);
|
||||
const dbhan = systemConnection || (await connectUtility(driver, connection, 'read'));
|
||||
logger.info(`Connected.`);
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ class SSHConnection {
|
||||
const connectionToBastion = await this.connect(bastionHost);
|
||||
return new Promise((resolve, reject) => {
|
||||
connectionToBastion.forwardOut(
|
||||
this.options.bindHost,
|
||||
'127.0.0.1',
|
||||
22,
|
||||
this.options.endHost,
|
||||
this.options.endPort || 22,
|
||||
@@ -228,9 +228,9 @@ class SSHConnection {
|
||||
options.toPort
|
||||
);
|
||||
connection.forwardOut(
|
||||
this.options.bindHost,
|
||||
'localhost',
|
||||
options.fromPort,
|
||||
options.toHost || this.options.bindHost,
|
||||
options.toHost || 'localhost',
|
||||
options.toPort,
|
||||
(error, stream) => {
|
||||
if (error) {
|
||||
@@ -241,7 +241,7 @@ class SSHConnection {
|
||||
}
|
||||
);
|
||||
})
|
||||
.listen(options.fromPort, this.options.bindHost, () => {
|
||||
.listen(options.fromPort, 'localhost', () => {
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -63,7 +63,7 @@ async function connectUtility(driver, storedConnection, connectionMode, addition
|
||||
throw new Error(tunnel.message);
|
||||
}
|
||||
|
||||
connection.server = tunnel.localHost;
|
||||
connection.server = 'localhost';
|
||||
connection.port = tunnel.localPort;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ function packagedPluginsDir() {
|
||||
// }
|
||||
}
|
||||
if (processArgs.runE2eTests) {
|
||||
return path.resolve('packer/build/plugins');
|
||||
return path.resolve('packer/build/plugins');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -113,7 +113,7 @@ function getPluginBackendPath(packageName) {
|
||||
return path.join(packagedPluginsDir(), packageName, 'dist', 'backend.js');
|
||||
}
|
||||
|
||||
const res = path.join(pluginsdir(), packageName, 'dist', 'backend.js');
|
||||
const res = path.join(pluginsdir(), packageName, 'dist', 'backend.js')
|
||||
if (fs.existsSync(res)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
const path = require('path');
|
||||
|
||||
function getNamedArg(name) {
|
||||
const argIndex = process.argv.indexOf(name);
|
||||
if (argIndex > 0) {
|
||||
@@ -22,15 +20,13 @@ function getPassArgs() {
|
||||
const res = [];
|
||||
if (global['PLUGINS_DIR']) {
|
||||
res.push('--plugins-dir', global['PLUGINS_DIR']);
|
||||
} else if (runE2eTests) {
|
||||
res.push('--plugins-dir', path.resolve('packer/build/plugins'));
|
||||
}
|
||||
if (listenApiChild) {
|
||||
res.push('listen-api-child');
|
||||
}
|
||||
// if (runE2eTests) {
|
||||
// res.push('--run-e2e-tests');
|
||||
// }
|
||||
if (runE2eTests) {
|
||||
res.push('--run-e2e-tests');
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,44 +43,33 @@ function callForwardProcess(connection, tunnelConfig, tunnelCacheKey) {
|
||||
logger.error(extractErrorLogData(err), 'Error connecting SSH');
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
let promiseHandled = false;
|
||||
subprocess.on('message', resp => {
|
||||
// @ts-ignore
|
||||
const { msgtype, errorMessage } = resp;
|
||||
if (msgtype == 'connected') {
|
||||
resolve(subprocess);
|
||||
promiseHandled = true;
|
||||
}
|
||||
if (msgtype == 'error') {
|
||||
reject(new Error(errorMessage));
|
||||
promiseHandled = true;
|
||||
}
|
||||
});
|
||||
subprocess.on('exit', code => {
|
||||
logger.info('SSH forward process exited');
|
||||
delete sshTunnelCache[tunnelCacheKey];
|
||||
if (!promiseHandled) {
|
||||
reject(new Error('SSH forward process exited, try to change "Local host address for SSH connections" in Settings/Connections'));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function getSshTunnel(connection) {
|
||||
const config = require('../controllers/config');
|
||||
|
||||
const tunnelCacheKey = stableStringify(_.pick(connection, TUNNEL_FIELDS));
|
||||
const globalSettings = await config.getSettings();
|
||||
|
||||
return await lock.acquire(tunnelCacheKey, async () => {
|
||||
if (sshTunnelCache[tunnelCacheKey]) return sshTunnelCache[tunnelCacheKey];
|
||||
const localPort = await portfinder.getPortPromise({ port: 10000, stopPort: 60000 });
|
||||
const localHost = globalSettings?.['connection.sshBindHost'] || '127.0.0.1';
|
||||
// workaround for `getPortPromise` not releasing the port quickly enough
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
const tunnelConfig = {
|
||||
fromPort: localPort,
|
||||
fromHost: localHost,
|
||||
toPort: connection.port,
|
||||
toHost: connection.server,
|
||||
};
|
||||
@@ -98,7 +87,6 @@ async function getSshTunnel(connection) {
|
||||
sshTunnelCache[tunnelCacheKey] = {
|
||||
state: 'ok',
|
||||
localPort,
|
||||
localHost,
|
||||
subprocess,
|
||||
};
|
||||
return sshTunnelCache[tunnelCacheKey];
|
||||
|
||||
@@ -66,7 +66,7 @@ class DuplicatorItemHolder {
|
||||
this.autoColumn = this.table.columns.find(x => x.autoIncrement)?.columnName;
|
||||
if (
|
||||
this.table.primaryKey?.columns?.length != 1 ||
|
||||
this.table.primaryKey?.columns?.[0]?.columnName != this.autoColumn
|
||||
this.table.primaryKey?.columns?.[0].columnName != this.autoColumn
|
||||
) {
|
||||
this.autoColumn = null;
|
||||
}
|
||||
@@ -140,9 +140,6 @@ class DuplicatorItemHolder {
|
||||
weakref.foreignKey.columns[0].columnName
|
||||
);
|
||||
});
|
||||
if (this.duplicator.driver.dialect.requireFromDual) {
|
||||
dmp.put(' ^from ^dual');
|
||||
}
|
||||
});
|
||||
const qrow = qres.rows[0];
|
||||
return this.weakReferences.filter(x => qrow[x.columnName] == 0).map(x => x.columnName);
|
||||
@@ -197,7 +194,6 @@ class DuplicatorItemHolder {
|
||||
res = await runQueryOnDriver(pool, driver, dmp => dmp.selectScopeIdentity(this.table));
|
||||
}
|
||||
// console.log('IDRES', JSON.stringify(res));
|
||||
// console.log('*********** ENTRIES OF', res?.rows?.[0]);
|
||||
const resId = Object.entries(res?.rows?.[0])?.[0]?.[1];
|
||||
if (resId != null) {
|
||||
this.idMap[chunk[this.autoColumn]] = resId;
|
||||
|
||||
@@ -1492,7 +1492,6 @@ export const chinookDbInfo: DatabaseInfo = {
|
||||
collections: [],
|
||||
matviews: [],
|
||||
triggers: [],
|
||||
schedulerEvents: [],
|
||||
};
|
||||
|
||||
// const ARTIST_TABLE: TableInfo = {
|
||||
|
||||
@@ -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/) page.
|
||||
You could find more about environment variable configuration on [DbGate docs](https://dbgate.org/docs/env-variables.html) page.
|
||||
|
||||
After installing, you can run dbgate with command:
|
||||
```sh
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"typescript": "^4.4.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"dbgate-query-splitter": "^4.11.3",
|
||||
"dbgate-query-splitter": "^4.11.2",
|
||||
"dbgate-sqltree": "^6.0.0-alpha.1",
|
||||
"debug": "^4.3.4",
|
||||
"json-stable-stringify": "^1.0.1",
|
||||
|
||||
@@ -10,16 +10,7 @@ import { extractErrorLogData } from './stringTools';
|
||||
|
||||
const logger = getLogger('dbAnalyser');
|
||||
|
||||
const STRUCTURE_FIELDS = [
|
||||
'tables',
|
||||
'collections',
|
||||
'views',
|
||||
'matviews',
|
||||
'functions',
|
||||
'procedures',
|
||||
'triggers',
|
||||
'schedulerEvents',
|
||||
];
|
||||
const STRUCTURE_FIELDS = ['tables', 'collections', 'views', 'matviews', 'functions', 'procedures', 'triggers'];
|
||||
|
||||
const fp_pick = arg => array => _pick(array, arg);
|
||||
|
||||
@@ -79,9 +70,7 @@ export class DatabaseAnalyser {
|
||||
}
|
||||
|
||||
async fullAnalysis() {
|
||||
logger.debug(
|
||||
`Performing full analysis, DB=${dbNameLogCategory(this.dbhan.database)}, engine=${this.driver.engine}`
|
||||
);
|
||||
logger.debug(`Performing full analysis, DB=${dbNameLogCategory(this.dbhan.database)}, engine=${this.driver.engine}`);
|
||||
const res = this.addEngineField(await this._runAnalysis());
|
||||
// console.log('FULL ANALYSIS', res);
|
||||
return res;
|
||||
@@ -266,7 +255,6 @@ export class DatabaseAnalyser {
|
||||
...this.getDeletedObjectsForField(snapshot, 'procedures'),
|
||||
...this.getDeletedObjectsForField(snapshot, 'functions'),
|
||||
...this.getDeletedObjectsForField(snapshot, 'triggers'),
|
||||
...this.getDeletedObjectsForField(snapshot, 'schedulerEvents'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -367,12 +355,11 @@ export class DatabaseAnalyser {
|
||||
functions: [],
|
||||
procedures: [],
|
||||
triggers: [],
|
||||
schedulerEvents: [],
|
||||
};
|
||||
}
|
||||
|
||||
static byTableFilter(table) {
|
||||
return x => x.pureName == table.pureName && x.schemaName == table.schemaName;
|
||||
return x => x.pureName == table.pureName && x.schemaName == x.schemaName;
|
||||
}
|
||||
|
||||
static extractPrimaryKeys(table, pkColumns) {
|
||||
|
||||
@@ -708,8 +708,6 @@ export class SqlDumper implements AlterProcessor {
|
||||
return 'TRIGGER';
|
||||
case 'matviews':
|
||||
return 'MATERIALIZED VIEW';
|
||||
case 'schedulerEvents':
|
||||
return 'EVENT';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -787,7 +785,10 @@ export class SqlDumper implements AlterProcessor {
|
||||
}
|
||||
|
||||
callableTemplate(func: CallableObjectInfo) {
|
||||
this.put('^call %f(&>&n', func);
|
||||
this.put(
|
||||
'^call %f(&>&n',
|
||||
func,
|
||||
);
|
||||
|
||||
this.putCollection(',&n', func.parameters || [], param => {
|
||||
this.putRaw(param.parameterMode == 'IN' ? ':' + param.parameterName : param.parameterName);
|
||||
|
||||
@@ -155,7 +155,6 @@ export function generateDbPairingId(db: DatabaseInfo): DatabaseInfo {
|
||||
procedures: db.procedures?.map(generateObjectPairingId),
|
||||
functions: db.functions?.map(generateObjectPairingId),
|
||||
triggers: db.triggers?.map(generateObjectPairingId),
|
||||
schedulerEvents: db.schedulerEvents?.map(generateObjectPairingId),
|
||||
matviews: db.matviews?.map(generateObjectPairingId),
|
||||
};
|
||||
}
|
||||
@@ -716,15 +715,7 @@ export function createAlterDatabasePlan(
|
||||
): AlterPlan {
|
||||
const plan = new AlterPlan(wholeOldDb, wholeNewDb, driver.dialect, opts);
|
||||
|
||||
for (const objectTypeField of [
|
||||
'tables',
|
||||
'views',
|
||||
'procedures',
|
||||
'matviews',
|
||||
'functions',
|
||||
'triggers',
|
||||
'schedulerEvents',
|
||||
]) {
|
||||
for (const objectTypeField of ['tables', 'views', 'procedures', 'matviews', 'functions']) {
|
||||
for (const oldobj of oldDb[objectTypeField] || []) {
|
||||
const newobj = (newDb[objectTypeField] || []).find(x => x.pairingId == oldobj.pairingId);
|
||||
if (objectTypeField == 'tables') {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import _compact from 'lodash/compact';
|
||||
import _isString from 'lodash/isString';
|
||||
import { SqlDumper } from './SqlDumper';
|
||||
import { splitQuery } from 'dbgate-query-splitter';
|
||||
import { dumpSqlSelect } from 'dbgate-sqltree';
|
||||
@@ -27,17 +26,9 @@ const dialect = {
|
||||
defaultSchemaName: null,
|
||||
};
|
||||
|
||||
export async function runCommandOnDriver(
|
||||
pool,
|
||||
driver: EngineDriver,
|
||||
cmd: (dmp: SqlDumper) => void | string
|
||||
): Promise<void> {
|
||||
export async function runCommandOnDriver(pool, driver: EngineDriver, cmd: (dmp: SqlDumper) => void): Promise<void> {
|
||||
const dmp = driver.createDumper();
|
||||
if (_isString(cmd)) {
|
||||
dmp.put(cmd);
|
||||
} else {
|
||||
cmd(dmp as any);
|
||||
}
|
||||
cmd(dmp as any);
|
||||
// console.log('CMD:', dmp.s);
|
||||
await driver.query(pool, dmp.s, { discardResult: true });
|
||||
}
|
||||
@@ -48,21 +39,11 @@ export async function runQueryOnDriver(
|
||||
cmd: (dmp: SqlDumper) => void
|
||||
): Promise<QueryResult> {
|
||||
const dmp = driver.createDumper();
|
||||
if (_isString(cmd)) {
|
||||
dmp.put(cmd);
|
||||
} else {
|
||||
cmd(dmp as any);
|
||||
}
|
||||
cmd(dmp as any);
|
||||
// console.log('QUERY:', dmp.s);
|
||||
return await driver.query(pool, dmp.s);
|
||||
}
|
||||
|
||||
export function formatQueryWithoutParams(driver: EngineDriver, sql: string) {
|
||||
const dmp = driver.createDumper();
|
||||
dmp.put(sql);
|
||||
return dmp.s;
|
||||
}
|
||||
|
||||
export const driverBase = {
|
||||
analyserClass: null,
|
||||
dumperClass: SqlDumper,
|
||||
|
||||
@@ -2,9 +2,9 @@ import _compact from 'lodash/compact';
|
||||
import _isString from 'lodash/isString';
|
||||
import _startCase from 'lodash/startCase';
|
||||
|
||||
// export interface FilterNameDefinition {
|
||||
// childName: string;
|
||||
// }
|
||||
export interface FilterNameDefinition {
|
||||
childName: string;
|
||||
}
|
||||
|
||||
function camelMatch(filter: string, text: string): boolean {
|
||||
if (!text) return false;
|
||||
@@ -20,7 +20,7 @@ function camelMatch(filter: string, text: string): boolean {
|
||||
}
|
||||
}
|
||||
|
||||
export function filterName(filter: string, ...names: string[]) {
|
||||
export function filterName(filter: string, ...names: (string | FilterNameDefinition)[]) {
|
||||
if (!filter) return true;
|
||||
|
||||
// const camelVariants = [name.replace(/[^A-Z]/g, '')]
|
||||
@@ -28,135 +28,22 @@ export function filterName(filter: string, ...names: string[]) {
|
||||
|
||||
const namesCompacted = _compact(names);
|
||||
|
||||
// @ts-ignore
|
||||
const namesOwn: string[] = namesCompacted.filter(x => _isString(x));
|
||||
// @ts-ignore
|
||||
const namesChild: string[] = namesCompacted.filter(x => x.childName).map(x => x.childName);
|
||||
|
||||
for (const token of tokens) {
|
||||
const found = namesCompacted.find(name => camelMatch(token, name));
|
||||
if (!found) return false;
|
||||
// const tokenUpper = token.toUpperCase();
|
||||
if (token.startsWith('#')) {
|
||||
// const tokenUpperSub = tokenUpper.substring(1);
|
||||
const found = namesChild.find(name => camelMatch(token.substring(1), name));
|
||||
if (!found) return false;
|
||||
} else {
|
||||
const found = namesOwn.find(name => camelMatch(token, name));
|
||||
if (!found) return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function filterNameCompoud(
|
||||
filter: string,
|
||||
namesMain: string[],
|
||||
namesChild: string[]
|
||||
): 'main' | 'child' | 'both' | 'none' {
|
||||
if (!filter) return 'both';
|
||||
|
||||
// const camelVariants = [name.replace(/[^A-Z]/g, '')]
|
||||
const tokens = filter.split(' ').map(x => x.trim());
|
||||
|
||||
const namesCompactedMain = _compact(namesMain);
|
||||
const namesCompactedChild = _compact(namesChild);
|
||||
|
||||
let isMainOnly = true;
|
||||
let isChildOnly = true;
|
||||
|
||||
for (const token of tokens) {
|
||||
const foundMain = namesCompactedMain.find(name => camelMatch(token, name));
|
||||
const foundChild = namesCompactedChild.find(name => camelMatch(token, name));
|
||||
if (!foundMain && !foundChild) return 'none';
|
||||
|
||||
if (!foundMain) isMainOnly = false;
|
||||
if (!foundChild) isChildOnly = false;
|
||||
}
|
||||
|
||||
if (isMainOnly && isChildOnly) return 'both';
|
||||
if (isMainOnly) return 'main';
|
||||
if (isChildOnly) return 'child';
|
||||
return 'none';
|
||||
}
|
||||
|
||||
export function tokenizeBySearchFilter(text: string, filter: string): { text: string; isMatch: boolean }[] {
|
||||
const camelTokens = [];
|
||||
const stdTokens = [];
|
||||
for (const token of filter.split(' ').map(x => x.trim())) {
|
||||
if (token.replace(/[A-Z]/g, '').length == 0) {
|
||||
camelTokens.push(token);
|
||||
} else {
|
||||
stdTokens.push(token.toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
let res = [
|
||||
{
|
||||
text,
|
||||
isMatch: false,
|
||||
},
|
||||
];
|
||||
|
||||
for (const token of camelTokens) {
|
||||
const nextres = [];
|
||||
for (const item of res) {
|
||||
const indexes = [];
|
||||
for (const char of token) {
|
||||
if (indexes.length == 0 && char == item.text[0]?.toUpperCase()) {
|
||||
// handle first letter of camelcase
|
||||
indexes.push(0);
|
||||
} else {
|
||||
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)) {
|
||||
nextres.push(item);
|
||||
} else {
|
||||
let lastIndex = 0;
|
||||
for (let i = 0; i < indexes.length; i++) {
|
||||
if (indexes[i] > lastIndex) {
|
||||
nextres.push({ text: item.text.substring(lastIndex, indexes[i]), isMatch: false });
|
||||
}
|
||||
nextres.push({ text: item.text.substring(indexes[i], indexes[i] + 1), isMatch: true });
|
||||
lastIndex = indexes[i] + 1;
|
||||
}
|
||||
nextres.push({ text: item.text.substring(lastIndex), isMatch: false });
|
||||
}
|
||||
}
|
||||
res = nextres;
|
||||
}
|
||||
|
||||
for (const token of stdTokens) {
|
||||
const nextres = [];
|
||||
for (const item of res) {
|
||||
const index = item.text?.toUpperCase().indexOf(token);
|
||||
if (index < 0) {
|
||||
nextres.push(item);
|
||||
} else {
|
||||
nextres.push({ text: item.text.substring(0, index), isMatch: false });
|
||||
nextres.push({ text: item.text.substring(index, index + token.length), isMatch: true });
|
||||
nextres.push({ text: item.text.substring(index + token.length), isMatch: false });
|
||||
}
|
||||
}
|
||||
res = nextres;
|
||||
}
|
||||
|
||||
res = res.filter(x => x.text.length > 0);
|
||||
|
||||
if (res.length == 1 && !res[0].isMatch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
// const result = [];
|
||||
// let lastMatch = 0;
|
||||
// for (const token of tokens) {
|
||||
// const index = text.indexOf(token, lastMatch);
|
||||
// if (index < 0) {
|
||||
// result.push({ token, isMatch: false });
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// result.push({ token: text.substring(lastMatch, index), isMatch: false });
|
||||
// result.push({ token: text.substring(index, index + token.length), isMatch: true });
|
||||
// lastMatch = index + token.length;
|
||||
// }
|
||||
|
||||
// result.push({ token: text.substring(lastMatch), isMatch: false });
|
||||
|
||||
// return result;
|
||||
}
|
||||
|
||||
@@ -234,7 +234,6 @@ 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
+2
-34
@@ -75,7 +75,7 @@ export interface DatabaseObjectInfo extends NamedObjectInfo {
|
||||
modifyDate?: string;
|
||||
hashCode?: string;
|
||||
objectTypeField?: string;
|
||||
objectComment?: string;
|
||||
obejctComment?: string;
|
||||
}
|
||||
|
||||
export interface SqlObjectInfo extends DatabaseObjectInfo {
|
||||
@@ -124,7 +124,6 @@ export interface ParameterInfo extends NamedObjectInfo {
|
||||
parameterName?: string;
|
||||
dataType: string;
|
||||
parameterMode?: ParameterMode;
|
||||
position?: number;
|
||||
}
|
||||
|
||||
export interface CallableObjectInfo extends SqlObjectInfo {
|
||||
@@ -137,37 +136,7 @@ export interface FunctionInfo extends CallableObjectInfo {
|
||||
returnType?: string;
|
||||
}
|
||||
|
||||
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 SchedulerEventInfo extends SqlObjectInfo {
|
||||
definer: string;
|
||||
eventType: 'RECURRING' | 'ONE TIME';
|
||||
onCompletion: 'PRESERVE' | 'NOT PRESERVE';
|
||||
status: 'ENABLED' | 'DISABLED';
|
||||
lastExecuted?: string;
|
||||
intervalValue: number;
|
||||
intervalField: string;
|
||||
starts: string;
|
||||
executeAt: string;
|
||||
}
|
||||
export interface TriggerInfo extends SqlObjectInfo {}
|
||||
|
||||
export interface SchemaInfo {
|
||||
objectId?: string;
|
||||
@@ -183,7 +152,6 @@ export interface DatabaseInfoObjects {
|
||||
procedures: ProcedureInfo[];
|
||||
functions: FunctionInfo[];
|
||||
triggers: TriggerInfo[];
|
||||
schedulerEvents: SchedulerEventInfo[];
|
||||
}
|
||||
|
||||
export interface DatabaseInfo extends DatabaseInfoObjects {
|
||||
|
||||
Vendored
-1
@@ -52,7 +52,6 @@ export interface SqlDialect {
|
||||
dropReferencesWhenDropTable?: boolean;
|
||||
requireFromDual?: boolean;
|
||||
userDatabaseNamePrefix?: string; // c## in Oracle
|
||||
upperCaseAllDbObjectNames?: boolean;
|
||||
|
||||
predefinedDataTypes: 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.36.5",
|
||||
"ace-builds": "^1.4.8",
|
||||
"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.3",
|
||||
"dbgate-query-splitter": "^4.11.2",
|
||||
"dbgate-sqltree": "^6.0.0-alpha.1",
|
||||
"dbgate-tools": "^6.0.0-alpha.1",
|
||||
"dbgate-types": "^6.0.0-alpha.1",
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
export const extractKey = data => data.fileName;
|
||||
export const createMatcher =
|
||||
filter =>
|
||||
({ fileName }) =>
|
||||
filter =>
|
||||
filterName(filter, fileName);
|
||||
const APP_ICONS = {
|
||||
'config.json': 'img json',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts" context="module">
|
||||
export const extractKey = data => data.name;
|
||||
export const createMatcher = filter => data => filterName(filter, data.name);
|
||||
export const createMatcher = data => filter => filterName(filter, data.name);
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
import CheckboxField from '../forms/CheckboxField.svelte';
|
||||
import { copyTextToClipboard } from '../utility/clipboard';
|
||||
import { showSnackbarSuccess } from '../utility/snackbar';
|
||||
import TokenizedFilteredText from '../widgets/TokenizedFilteredText.svelte';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
@@ -31,10 +30,6 @@
|
||||
export let onUnpin = null;
|
||||
export let showPinnedInsteadOfUnpin = false;
|
||||
export let indentLevel = 0;
|
||||
export let disableBoldScroll = false;
|
||||
export let filter = null;
|
||||
export let disableHover = false;
|
||||
export let divProps = {};
|
||||
|
||||
$: isChecked =
|
||||
checkedObjectsStore && $checkedObjectsStore.find(x => module?.extractKey(data) == module?.extractKey(x));
|
||||
@@ -62,13 +57,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
function handleMouseDown(e) {
|
||||
if (e.button == 1) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
function setChecked(value) {
|
||||
if (!value && isChecked) {
|
||||
checkedObjectsStore.update(x => x.filter(y => module?.extractKey(data) != module?.extractKey(y)));
|
||||
@@ -81,7 +69,7 @@
|
||||
// $: console.log(title, indentLevel);
|
||||
let domDiv;
|
||||
|
||||
$: if (isBold && domDiv && !disableBoldScroll) {
|
||||
$: if (isBold && domDiv) {
|
||||
domDiv.scrollIntoView({ block: 'nearest', inline: 'nearest' });
|
||||
}
|
||||
|
||||
@@ -94,12 +82,9 @@
|
||||
class="main"
|
||||
class:isBold
|
||||
class:isChoosed
|
||||
class:disableHover
|
||||
draggable={true}
|
||||
on:click={handleClick}
|
||||
on:mouseup={handleMouseUp}
|
||||
on:mousedown={handleMouseDown}
|
||||
on:mousedown
|
||||
on:dblclick
|
||||
use:contextMenu={disableContextMenu ? null : menu}
|
||||
on:dragstart={e => {
|
||||
@@ -110,7 +95,6 @@
|
||||
on:dragend
|
||||
on:drop
|
||||
bind:this={domDiv}
|
||||
{...divProps}
|
||||
>
|
||||
{#if checkedObjectsStore}
|
||||
<CheckboxField
|
||||
@@ -137,7 +121,7 @@
|
||||
{#if colorMark}
|
||||
<FontIcon style={`color:${colorMark}`} icon="icon square" />
|
||||
{/if}
|
||||
<TokenizedFilteredText text={title} {filter} />
|
||||
{title}
|
||||
{#if statusIconBefore}
|
||||
<span class="status">
|
||||
<FontIcon icon={statusIconBefore} />
|
||||
@@ -159,7 +143,7 @@
|
||||
{/if}
|
||||
{#if extInfo}
|
||||
<span class="ext-info">
|
||||
<TokenizedFilteredText text={extInfo} {filter} />
|
||||
{extInfo}
|
||||
</span>
|
||||
{/if}
|
||||
{#if onPin}
|
||||
@@ -196,19 +180,13 @@
|
||||
<slot />
|
||||
|
||||
<style>
|
||||
.pin,
|
||||
.pin-active {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
z-index: 150;
|
||||
}
|
||||
.main {
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
font-weight: normal;
|
||||
}
|
||||
.main:hover:not(.disableHover) {
|
||||
.main:hover {
|
||||
background-color: var(--theme-bg-hover);
|
||||
}
|
||||
.isBold {
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
export let onDropOnGroup = undefined;
|
||||
export let groupContextMenu = null;
|
||||
export let collapsedGroupNames;
|
||||
export let filter = undefined;
|
||||
|
||||
$: isExpanded = !$collapsedGroupNames.includes(group);
|
||||
|
||||
@@ -87,9 +86,6 @@
|
||||
on:objectClick
|
||||
{disableContextMenu}
|
||||
{passProps}
|
||||
isExpandedBySearch={filter && item.isChildMatched}
|
||||
{filter}
|
||||
isMainMatched={item.isMainMatched}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
<script>
|
||||
import _ from 'lodash';
|
||||
import _, { sortBy } from 'lodash';
|
||||
import { asyncFilter } from '../utility/common';
|
||||
import AppObjectGroup from './AppObjectGroup.svelte';
|
||||
import { plusExpandIcon } from '../icons/expandIcons';
|
||||
|
||||
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;
|
||||
@@ -18,7 +16,7 @@
|
||||
export let expandIconFunc = undefined;
|
||||
export let checkedObjectsStore = null;
|
||||
export let disableContextMenu = false;
|
||||
export let passProps = {};
|
||||
export let passProps;
|
||||
export let getIsExpanded = null;
|
||||
export let setIsExpanded = null;
|
||||
export let sortGroups = false;
|
||||
@@ -28,47 +26,25 @@
|
||||
export let groupFunc = undefined;
|
||||
export let onDropOnGroup = undefined;
|
||||
export let emptyGroupNames = [];
|
||||
export let isExpandedBySearch = false;
|
||||
|
||||
export let collapsedGroupNames = writable([]);
|
||||
export let onChangeFilteredList = undefined;
|
||||
export let onChangeFilteredList;
|
||||
|
||||
let expandLimited = false;
|
||||
$: filtered = !groupFunc
|
||||
? list.filter(data => {
|
||||
const matcher = module.createMatcher && module.createMatcher(data);
|
||||
if (matcher && !matcher(filter)) return false;
|
||||
return true;
|
||||
})
|
||||
: null;
|
||||
|
||||
$: matcher = module.createMatcher && module.createMatcher(filter, passProps?.searchSettings);
|
||||
|
||||
$: dataLabeled = _.compact(
|
||||
(list || []).map(data => {
|
||||
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') {
|
||||
isMainMatched = false;
|
||||
} else if (matchResult == 'main') {
|
||||
isChildMatched = false;
|
||||
} else if (matchResult == 'none') {
|
||||
isMatched = false;
|
||||
isChildMatched = false;
|
||||
isMainMatched = false;
|
||||
} else if (matchResult == 'both') {
|
||||
isChildMatched = !module.disableShowChildrenWithParentMatch;
|
||||
}
|
||||
|
||||
const group = groupFunc ? groupFunc(data) : undefined;
|
||||
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);
|
||||
$: childrenMatched = !groupFunc
|
||||
? list.filter(data => {
|
||||
const matcher = module.createChildMatcher && module.createChildMatcher(data);
|
||||
if (matcher && !matcher(filter)) return false;
|
||||
return true;
|
||||
})
|
||||
: null;
|
||||
|
||||
// let filtered = [];
|
||||
|
||||
@@ -84,6 +60,17 @@
|
||||
// }
|
||||
// }
|
||||
|
||||
$: listGrouped = groupFunc
|
||||
? _.compact(
|
||||
(list || []).map(data => {
|
||||
const matcher = module.createMatcher && module.createMatcher(data);
|
||||
const isMatched = matcher && !matcher(filter) ? false : true;
|
||||
const group = groupFunc(data);
|
||||
return { group, data, isMatched };
|
||||
})
|
||||
)
|
||||
: null;
|
||||
|
||||
function extendGroups(base, emptyList) {
|
||||
const res = {
|
||||
...base,
|
||||
@@ -95,24 +82,7 @@
|
||||
return res;
|
||||
}
|
||||
|
||||
function setExpandLimited() {
|
||||
expandLimited = true;
|
||||
}
|
||||
|
||||
$: groups = groupFunc ? extendGroups(_.groupBy(dataLabeled, 'group'), emptyGroupNames) : null;
|
||||
|
||||
$: 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);
|
||||
}
|
||||
$: groups = groupFunc ? extendGroups(_.groupBy(listGrouped, 'group'), emptyGroupNames) : null;
|
||||
</script>
|
||||
|
||||
{#if groupFunc}
|
||||
@@ -138,7 +108,7 @@
|
||||
/>
|
||||
{/each}
|
||||
{:else}
|
||||
{#each listLimited as data}
|
||||
{#each list as data}
|
||||
<AppObjectListItem
|
||||
isHidden={!filtered.includes(data)}
|
||||
{module}
|
||||
@@ -151,20 +121,10 @@
|
||||
{checkedObjectsStore}
|
||||
{disableContextMenu}
|
||||
{filter}
|
||||
isExpandedBySearch={filter && childrenMatched.includes(data)}
|
||||
isMainMatched={filter && mainMatched.includes(data)}
|
||||
isExpandedBySearch={childrenMatched.includes(data)}
|
||||
{passProps}
|
||||
{getIsExpanded}
|
||||
{setIsExpanded}
|
||||
/>
|
||||
{/each}
|
||||
{#if isListLimited}
|
||||
<div class="ml-2">
|
||||
<Link
|
||||
onClick={() => {
|
||||
expandLimited = true;
|
||||
}}>Show next {filtered.length - listLimited.length}</Link
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
export let passProps;
|
||||
export let getIsExpanded = null;
|
||||
export let setIsExpanded = null;
|
||||
export let isMainMatched = false;
|
||||
|
||||
let isExpandedCore = false;
|
||||
|
||||
@@ -58,21 +57,16 @@
|
||||
{module}
|
||||
{disableContextMenu}
|
||||
{passProps}
|
||||
{filter}
|
||||
/>
|
||||
|
||||
{#if (isExpanded || isExpandedBySearch) && subItemsComponent}
|
||||
<div class="subitems">
|
||||
<svelte:component
|
||||
this={subItemsComponent(data, {
|
||||
isExpandedBySearch,
|
||||
})}
|
||||
this={subItemsComponent(data)}
|
||||
{data}
|
||||
{filter}
|
||||
{passProps}
|
||||
{isExpandedBySearch}
|
||||
{isExpanded}
|
||||
{isMainMatched}
|
||||
isExpandedOnlyBySearch={isExpandedBySearch && !isExpanded}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -42,8 +42,8 @@
|
||||
|
||||
export const extractKey = data => data.fileName;
|
||||
export const createMatcher =
|
||||
filter =>
|
||||
({ fileName }) =>
|
||||
filter =>
|
||||
filterName(filter, fileName);
|
||||
const ARCHIVE_ICONS = {
|
||||
'table.yaml': 'img table',
|
||||
@@ -70,7 +70,7 @@
|
||||
import { getExtensions } from '../stores';
|
||||
|
||||
import createQuickExportMenu from '../utility/createQuickExportMenu';
|
||||
import { exportQuickExportFile } from '../utility/exportFileTools';
|
||||
import { exportQuickExportFile, } from '../utility/exportFileTools';
|
||||
import openNewTab from '../utility/openNewTab';
|
||||
import AppObjectCore from './AppObjectCore.svelte';
|
||||
import InputTextModal from '../modals/InputTextModal.svelte';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts" context="module">
|
||||
export const extractKey = data => data.name;
|
||||
export const createMatcher = filter => data => filterName(filter, data.name);
|
||||
export const createMatcher = data => filter => filterName(filter, data.name);
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
<script lang="ts" context="module">
|
||||
export const extractKey = ({ columnName }) => columnName;
|
||||
|
||||
export const createMatcher =
|
||||
(filter, cfg = DEFAULT_OBJECT_SEARCH_SETTINGS) =>
|
||||
data => {
|
||||
const filterArgs = [];
|
||||
if (cfg.columnName) filterArgs.push(data.columnName);
|
||||
if (cfg.columnComment) filterArgs.push(data.columnComment);
|
||||
if (cfg.columnDataType) filterArgs.push(data.dataType);
|
||||
|
||||
const res = filterName(filter, ...filterArgs);
|
||||
return res;
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -21,8 +9,6 @@
|
||||
import { renameDatabaseObjectDialog, alterDatabaseDialog } from '../utility/alterDatabaseTools';
|
||||
|
||||
import AppObjectCore from './AppObjectCore.svelte';
|
||||
import { DEFAULT_OBJECT_SEARCH_SETTINGS } from '../stores';
|
||||
import { filterName } from 'dbgate-tools';
|
||||
|
||||
export let data;
|
||||
|
||||
@@ -49,21 +35,7 @@
|
||||
];
|
||||
}
|
||||
|
||||
function getExtInfo(data) {
|
||||
const res = [];
|
||||
if (data.foreignKey) {
|
||||
res.push(`${data.dataType} -> ${data.foreignKey.refTableName}`);
|
||||
} else {
|
||||
res.push(data.dataType);
|
||||
}
|
||||
if (data.columnComment) {
|
||||
res.push(data.columnComment);
|
||||
}
|
||||
if (res.length > 0) return res.join(', ');
|
||||
return null;
|
||||
}
|
||||
|
||||
$: extInfo = getExtInfo(data);
|
||||
$: extInfo = data.foreignKey ? `${data.dataType} -> ${data.foreignKey.refTableName}` : data.dataType;
|
||||
</script>
|
||||
|
||||
<AppObjectCore
|
||||
@@ -73,5 +45,5 @@
|
||||
{extInfo}
|
||||
icon={getColumnIcon(data, true)}
|
||||
menu={createMenu}
|
||||
\
|
||||
disableHover
|
||||
/>
|
||||
|
||||
@@ -1,24 +1,16 @@
|
||||
<script context="module">
|
||||
export const extractKey = data => data._id;
|
||||
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 const createMatcher = props => filter => {
|
||||
const { _id, displayName, server } = props;
|
||||
const databases = getLocalStorage(`database_list_${_id}`) || [];
|
||||
return filterName(filter, displayName, server, ...databases.map(x => x.name));
|
||||
};
|
||||
export const createChildMatcher = props => filter => {
|
||||
if (!filter) return false;
|
||||
const { _id } = props;
|
||||
const databases = getLocalStorage(`database_list_${_id}`) || [];
|
||||
return filterName(filter, ...databases.map(x => x.name));
|
||||
};
|
||||
export function openConnection(connection, disableExpand = false) {
|
||||
if (connection.singleDatabase) {
|
||||
if (getOpenedSingleDatabaseConnections().includes(connection._id)) {
|
||||
@@ -50,10 +42,6 @@
|
||||
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]));
|
||||
// }
|
||||
@@ -106,7 +94,6 @@
|
||||
import AppObjectCore from './AppObjectCore.svelte';
|
||||
import {
|
||||
currentDatabase,
|
||||
DEFAULT_CONNECTION_SEARCH_SETTINGS,
|
||||
expandedConnections,
|
||||
extensions,
|
||||
focusedConnectionOrDatabase,
|
||||
@@ -119,7 +106,7 @@
|
||||
openedConnections,
|
||||
openedSingleDatabaseConnections,
|
||||
} from '../stores';
|
||||
import { filterName, filterNameCompoud } from 'dbgate-tools';
|
||||
import { filterName } from 'dbgate-tools';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import ConfirmModal from '../modals/ConfirmModal.svelte';
|
||||
import InputTextModal from '../modals/InputTextModal.svelte';
|
||||
@@ -136,7 +123,6 @@
|
||||
import { getConnectionLabel } from 'dbgate-tools';
|
||||
import hasPermission from '../utility/hasPermission';
|
||||
import { switchCurrentDatabase } from '../utility/common';
|
||||
import { getConnectionClickActionSetting } from '../settings/settingsTools';
|
||||
|
||||
export let data;
|
||||
export let passProps;
|
||||
@@ -191,40 +177,24 @@
|
||||
};
|
||||
|
||||
const handleClick = async e => {
|
||||
// focusedConnectionOrDatabase.set({
|
||||
// conid: data?._id,
|
||||
// connection: data,
|
||||
// database: data.singleDatabase ? data.defaultDatabase : null,
|
||||
// });
|
||||
|
||||
const config = getCurrentConfig();
|
||||
|
||||
const connectionClickAction = getConnectionClickActionSetting();
|
||||
if (connectionClickAction == 'openDetails') {
|
||||
if (config.runAsPortal == false && !config.storageDatabase) {
|
||||
openNewTab({
|
||||
title: getConnectionLabel(data),
|
||||
icon: 'img connection',
|
||||
tabComponent: 'ConnectionTab',
|
||||
tabPreviewMode: true,
|
||||
props: {
|
||||
conid: data._id,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
if (connectionClickAction == 'connect') {
|
||||
await tick();
|
||||
handleConnect();
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseDown = () => {
|
||||
focusedConnectionOrDatabase.set({
|
||||
conid: data?._id,
|
||||
connection: data,
|
||||
database: data.singleDatabase ? data.defaultDatabase : null,
|
||||
});
|
||||
|
||||
const config = getCurrentConfig();
|
||||
if (config.runAsPortal == false && !config.storageDatabase) {
|
||||
openNewTab({
|
||||
title: getConnectionLabel(data),
|
||||
icon: 'img connection',
|
||||
tabComponent: 'ConnectionTab',
|
||||
tabPreviewMode: true,
|
||||
props: {
|
||||
conid: data._id,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleSqlRestore = () => {
|
||||
@@ -284,7 +254,6 @@
|
||||
icon: 'img sql-file',
|
||||
tooltip,
|
||||
tabComponent: 'QueryTab',
|
||||
focused: true,
|
||||
props: {
|
||||
conid: data._id,
|
||||
},
|
||||
@@ -321,7 +290,7 @@
|
||||
],
|
||||
{ divider: true },
|
||||
!data.singleDatabase && [
|
||||
hasPermission(`dbops/query`) && { onClick: handleNewQuery, text: 'New Query (server)', isNewQuery: true },
|
||||
hasPermission(`dbops/query`) && { onClick: handleNewQuery, text: 'New query', isNewQuery: true },
|
||||
$openedConnections.includes(data._id) &&
|
||||
data.status && {
|
||||
text: 'Refresh',
|
||||
@@ -404,7 +373,6 @@
|
||||
colorMark={passProps?.connectionColorFactory && passProps?.connectionColorFactory({ conid: data._id })}
|
||||
menu={getContextMenu}
|
||||
on:click={handleClick}
|
||||
on:mousedown={handleMouseDown}
|
||||
on:dblclick
|
||||
on:expand
|
||||
on:dblclick={handleDoubleClick}
|
||||
@@ -417,5 +385,4 @@
|
||||
(data.singleDatabase
|
||||
? $focusedConnectionOrDatabase?.database == data.defaultDatabase
|
||||
: !$focusedConnectionOrDatabase?.database)}
|
||||
disableBoldScroll={!!$focusedConnectionOrDatabase}
|
||||
/>
|
||||
|
||||
@@ -3,11 +3,6 @@
|
||||
|
||||
export const extractKey = props => props.name;
|
||||
|
||||
export const createMatcher = filter => props => {
|
||||
const { name, displayName, server } = props;
|
||||
return filterName(filter, name, displayName, server);
|
||||
};
|
||||
|
||||
export function disconnectDatabaseConnection(conid, database, showConfirmation = true) {
|
||||
const closeCondition = x =>
|
||||
x.props?.conid == conid &&
|
||||
@@ -53,7 +48,6 @@
|
||||
icon: 'img sql-file',
|
||||
tooltip,
|
||||
tabComponent: 'QueryTab',
|
||||
focused: true,
|
||||
props: {
|
||||
conid: connection._id,
|
||||
database: name,
|
||||
@@ -241,7 +235,6 @@
|
||||
title: 'Query #',
|
||||
icon: 'img query-design',
|
||||
tabComponent: 'QueryDesignTab',
|
||||
focused: true,
|
||||
props: {
|
||||
conid: connection._id,
|
||||
database: name,
|
||||
@@ -358,13 +351,11 @@ await dbgateApi.dropAllDbObjects(${JSON.stringify(
|
||||
text: `New ${driver?.collectionSingularLabel ?? 'collection/container'}`,
|
||||
},
|
||||
hasPermission(`dbops/query`) &&
|
||||
driver?.databaseEngineTypes?.includes('sql') &&
|
||||
isProApp() && { onClick: handleQueryDesigner, text: 'Design query' },
|
||||
driver?.databaseEngineTypes?.includes('sql') &&
|
||||
isProApp() && {
|
||||
onClick: handleNewPerspective,
|
||||
text: 'Design perspective query',
|
||||
},
|
||||
driver?.databaseEngineTypes?.includes('sql') && isProApp() && { onClick: handleQueryDesigner, text: 'Design query' },
|
||||
driver?.databaseEngineTypes?.includes('sql') && isProApp() && {
|
||||
onClick: handleNewPerspective,
|
||||
text: 'Design perspective query',
|
||||
},
|
||||
connection.useSeparateSchemas && { onClick: handleRefreshSchemas, text: 'Refresh schemas' },
|
||||
|
||||
{ divider: true },
|
||||
@@ -472,13 +463,7 @@ await dbgateApi.dropAllDbObjects(${JSON.stringify(
|
||||
import openNewTab from '../utility/openNewTab';
|
||||
import AppObjectCore from './AppObjectCore.svelte';
|
||||
import { showSnackbarError, showSnackbarSuccess } from '../utility/snackbar';
|
||||
import {
|
||||
extractDbNameFromComposite,
|
||||
extractPackageName,
|
||||
filterName,
|
||||
findEngineDriver,
|
||||
getConnectionLabel,
|
||||
} from 'dbgate-tools';
|
||||
import { extractDbNameFromComposite, extractPackageName, findEngineDriver, getConnectionLabel } from 'dbgate-tools';
|
||||
import InputTextModal from '../modals/InputTextModal.svelte';
|
||||
import { getDatabaseInfo, useUsedApps } from '../utility/metadataLoaders';
|
||||
import { openJsonDocument } from '../tabs/JsonTab.svelte';
|
||||
@@ -501,7 +486,6 @@ await dbgateApi.dropAllDbObjects(${JSON.stringify(
|
||||
import ChooseArchiveFolderModal from '../modals/ChooseArchiveFolderModal.svelte';
|
||||
import { extractShellConnection } from '../impexp/createImpExpScript';
|
||||
import { getNumberIcon } from '../icons/FontIcon.svelte';
|
||||
import { getDatabaseClickActionSetting } from '../settings/settingsTools';
|
||||
|
||||
export let data;
|
||||
export let passProps;
|
||||
@@ -538,11 +522,6 @@ await dbgateApi.dropAllDbObjects(${JSON.stringify(
|
||||
}}
|
||||
on:click={() => {
|
||||
// switchCurrentDatabase(data);
|
||||
if (getDatabaseClickActionSetting() == 'switch') {
|
||||
switchCurrentDatabase(data);
|
||||
}
|
||||
}}
|
||||
on:mousedown={() => {
|
||||
$focusedConnectionOrDatabase = { conid: data.connection?._id, database: data.name, connection: data.connection };
|
||||
}}
|
||||
on:dragstart
|
||||
@@ -574,8 +553,4 @@ await dbgateApi.dropAllDbObjects(${JSON.stringify(
|
||||
: null}
|
||||
isChoosed={data.connection?._id == $focusedConnectionOrDatabase?.conid &&
|
||||
data.name == $focusedConnectionOrDatabase?.database}
|
||||
disableBoldScroll={!!$focusedConnectionOrDatabase}
|
||||
divProps={{
|
||||
'data-testid': `DatabaseAppObject_${data.name}`,
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -3,34 +3,14 @@
|
||||
|
||||
export const extractKey = ({ schemaName, pureName }) => (schemaName ? `${schemaName}.${pureName}` : pureName);
|
||||
export const createMatcher =
|
||||
(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.tableComment) mainArgs.push(objectComment);
|
||||
if (cfg.tableEngine) mainArgs.push(tableEngine);
|
||||
|
||||
for (const column of columns || []) {
|
||||
if (cfg.columnName) childArgs.push(column.columnName);
|
||||
if (cfg.columnComment) childArgs.push(column.columnComment);
|
||||
if (cfg.columnDataType) childArgs.push(column.dataType);
|
||||
}
|
||||
} else {
|
||||
if (cfg.sqlObjectText) childArgs.push(createSql);
|
||||
}
|
||||
if (objectTypeField == 'triggers' && cfg.pureName) {
|
||||
mainArgs.push(tableName);
|
||||
}
|
||||
|
||||
const res = filterNameCompoud(filter, mainArgs, childArgs);
|
||||
return res;
|
||||
};
|
||||
|
||||
export const disableShowChildrenWithParentMatch = true;
|
||||
|
||||
({ schemaName, pureName, columns }) =>
|
||||
filter =>
|
||||
filterName(
|
||||
filter,
|
||||
pureName,
|
||||
schemaName,
|
||||
...(columns?.map(({ columnName }) => ({ childName: columnName })) || [])
|
||||
);
|
||||
export const createTitle = ({ schemaName, pureName }) => (schemaName ? `${schemaName}.${pureName}` : pureName);
|
||||
|
||||
export const databaseObjectIcons = {
|
||||
@@ -41,8 +21,6 @@
|
||||
procedures: 'img procedure',
|
||||
functions: 'img function',
|
||||
queries: 'img query-data',
|
||||
triggers: 'icon trigger',
|
||||
schedulerEvents: 'icon scheduler-event',
|
||||
};
|
||||
|
||||
const defaultTabs = {
|
||||
@@ -53,7 +31,6 @@
|
||||
queries: 'QueryDataTab',
|
||||
procedures: 'SqlObjectTab',
|
||||
functions: 'SqlObjectTab',
|
||||
triggers: 'SqlObjectTab',
|
||||
};
|
||||
|
||||
function createScriptTemplatesSubmenu(objectTypeField) {
|
||||
@@ -88,12 +65,10 @@
|
||||
isDropCollection?: boolean;
|
||||
isRenameCollection?: boolean;
|
||||
isDuplicateCollection?: boolean;
|
||||
isDisableEvent?: boolean;
|
||||
isEnableEvent?: boolean;
|
||||
submenu?: DbObjMenuItem[];
|
||||
}
|
||||
|
||||
function createMenusCore(objectTypeField, driver, data): DbObjMenuItem[] {
|
||||
function createMenusCore(objectTypeField, driver): DbObjMenuItem[] {
|
||||
switch (objectTypeField) {
|
||||
case 'tables':
|
||||
return [
|
||||
@@ -347,9 +322,40 @@
|
||||
},
|
||||
];
|
||||
case 'functions':
|
||||
return [...defaultDatabaseObjectAppObjectActions['functions']];
|
||||
case 'triggers':
|
||||
return [...defaultDatabaseObjectAppObjectActions['triggers']];
|
||||
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 'collections':
|
||||
return [
|
||||
...defaultDatabaseObjectAppObjectActions['collections'],
|
||||
@@ -387,28 +393,6 @@
|
||||
},
|
||||
...(driver?.getScriptTemplates?.('collections') || []),
|
||||
];
|
||||
case 'schedulerEvents':
|
||||
const menu: DbObjMenuItem[] = [
|
||||
...defaultDatabaseObjectAppObjectActions['schedulerEvents'],
|
||||
{
|
||||
divider: true,
|
||||
},
|
||||
,
|
||||
];
|
||||
|
||||
if (data?.status === 'ENABLED') {
|
||||
menu.push({
|
||||
label: 'Disable',
|
||||
isDisableEvent: true,
|
||||
});
|
||||
} else {
|
||||
menu.push({
|
||||
label: 'Enable',
|
||||
isEnableEvent: true,
|
||||
});
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,7 +431,6 @@
|
||||
title: 'Query #',
|
||||
icon: 'img query-design',
|
||||
tabComponent: 'QueryDesignTab',
|
||||
focused: true,
|
||||
props: {
|
||||
conid: data.conid,
|
||||
database: data.database,
|
||||
@@ -506,36 +489,6 @@
|
||||
x => x.schemaName == data.schemaName && x.pureName == data.pureName
|
||||
);
|
||||
});
|
||||
} else if (menu.isDisableEvent) {
|
||||
const { conid, database, pureName } = data;
|
||||
const driver = await getDriver();
|
||||
const dmp = driver.createDumper();
|
||||
dmp.put('^alter ^event %i ^disable', pureName);
|
||||
|
||||
const sql = dmp.s;
|
||||
|
||||
showModal(ConfirmSqlModal, {
|
||||
sql,
|
||||
onConfirm: async () => {
|
||||
saveScriptToDatabase({ conid, database }, sql);
|
||||
},
|
||||
engine: driver.engine,
|
||||
});
|
||||
} else if (menu.isEnableEvent) {
|
||||
const { conid, database, pureName } = data;
|
||||
const driver = await getDriver();
|
||||
const dmp = driver.createDumper();
|
||||
dmp.put('^alter ^event %i ^enable', pureName);
|
||||
|
||||
const sql = dmp.s;
|
||||
|
||||
showModal(ConfirmSqlModal, {
|
||||
sql,
|
||||
onConfirm: async () => {
|
||||
saveScriptToDatabase({ conid, database }, sql);
|
||||
},
|
||||
engine: driver.engine,
|
||||
});
|
||||
} else if (menu.isTruncate) {
|
||||
const { conid, database } = data;
|
||||
const driver = await getDriver();
|
||||
@@ -681,8 +634,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
function createMenus(objectTypeField, driver, data): ReturnType<typeof createMenusCore> {
|
||||
return createMenusCore(objectTypeField, driver, data).filter(x => {
|
||||
function createMenus(objectTypeField, driver): ReturnType<typeof createMenusCore> {
|
||||
return createMenusCore(objectTypeField, driver).filter(x => {
|
||||
if (x.scriptTemplate) {
|
||||
return hasPermission(`dbops/sql-template/${x.scriptTemplate}`);
|
||||
}
|
||||
@@ -723,7 +676,6 @@
|
||||
{
|
||||
// title: getObjectTitle(connection, schemaName, pureName),
|
||||
title: tabComponent ? getObjectTitle(connection, schemaName, pureName) : 'Query #',
|
||||
focused: tabComponent == null,
|
||||
tooltip,
|
||||
icon:
|
||||
icon ||
|
||||
@@ -781,7 +733,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const availableDefaultActions = defaultDatabaseObjectAppObjectActions[objectTypeField] ?? [];
|
||||
const availableDefaultActions = defaultDatabaseObjectAppObjectActions[objectTypeField];
|
||||
|
||||
const configuredActionId = getLastUsedDefaultActions()[objectTypeField];
|
||||
const prefferedAction =
|
||||
@@ -900,7 +852,7 @@
|
||||
const driver = findEngineDriver(data, getExtensions());
|
||||
|
||||
const { objectTypeField } = data;
|
||||
return createMenus(objectTypeField, driver, data)
|
||||
return createMenus(objectTypeField, driver)
|
||||
.filter(x => x)
|
||||
.map(menu => menuItemMapper(menu, data, connection));
|
||||
}
|
||||
@@ -915,35 +867,7 @@
|
||||
return createDatabaseObjectMenu(data);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
export function handleObjectClick(data, { forceNewTab = false, tabPreviewMode = false, focusTab = false }) {
|
||||
return handleDatabaseObjectClick(data, { forceNewTab, tabPreviewMode, focusTab });
|
||||
}
|
||||
</script>
|
||||
@@ -952,18 +876,27 @@
|
||||
import _ from 'lodash';
|
||||
import AppObjectCore from './AppObjectCore.svelte';
|
||||
import {
|
||||
DEFAULT_OBJECT_SEARCH_SETTINGS,
|
||||
currentDatabase,
|
||||
extensions,
|
||||
getActiveTab,
|
||||
getCurrentSettings,
|
||||
getExtensions,
|
||||
getLastUsedDefaultActions,
|
||||
lastUsedDefaultActions,
|
||||
openedConnections,
|
||||
openedTabs,
|
||||
pinnedTables,
|
||||
selectedDatabaseObjectAppObject,
|
||||
} from '../stores';
|
||||
import openNewTab from '../utility/openNewTab';
|
||||
import { extractDbNameFromComposite, filterNameCompoud, getConnectionLabel } from 'dbgate-tools';
|
||||
import { getConnectionInfo } from '../utility/metadataLoaders';
|
||||
import {
|
||||
extractDbNameFromComposite,
|
||||
filterName,
|
||||
generateDbPairingId,
|
||||
getAlterDatabaseScript,
|
||||
getConnectionLabel,
|
||||
} from 'dbgate-tools';
|
||||
import { getConnectionInfo, getDatabaseInfo } from '../utility/metadataLoaders';
|
||||
import fullDisplayName from '../utility/fullDisplayName';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import { findEngineDriver } from 'dbgate-tools';
|
||||
@@ -974,6 +907,7 @@
|
||||
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';
|
||||
@@ -982,33 +916,23 @@
|
||||
import { openImportExportTab } from '../utility/importExportTools';
|
||||
import { defaultDatabaseObjectAppObjectActions, matchDatabaseObjectAppObject } from './appObjectTools';
|
||||
import { getSupportedScriptTemplates } from '../utility/applyScriptTemplate';
|
||||
import { getBoolSettingsValue, getOpenDetailOnArrowsSettings } from '../settings/settingsTools';
|
||||
import { getBoolSettingsValue } from '../settings/settingsTools';
|
||||
import { isProApp } from '../utility/proTools';
|
||||
|
||||
export let data;
|
||||
export let passProps;
|
||||
|
||||
function handleClick({ forceNewTab = false, tabPreviewMode = false, focusTab = false } = {}) {
|
||||
$selectedDatabaseObjectAppObject = _.pick(data, ['conid', 'database', 'objectTypeField', 'pureName', 'schemaName']);
|
||||
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.objectTypeField == 'schedulerEvents') {
|
||||
if (data.eventType == 'RECURRING') {
|
||||
res.push(`${data.status}, ${data.eventType}, ${data.intervalValue} ${data.intervalField}`);
|
||||
} else {
|
||||
res.push(`${data.status}, ${data.eventType}, ${data.executeAt}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.objectComment) {
|
||||
res.push(data.objectComment);
|
||||
}
|
||||
if (data.tableRowCount != null) {
|
||||
res.push(`${formatRowCount(data.tableRowCount)} rows`);
|
||||
}
|
||||
@@ -1034,15 +958,12 @@
|
||||
onUnpin={isPinned ? () => pinnedTables.update(list => list.filter(x => !testEqual(x, data))) : null}
|
||||
extInfo={getExtInfo(data)}
|
||||
isChoosed={matchDatabaseObjectAppObject($selectedDatabaseObjectAppObject, data)}
|
||||
on:click={() => handleObjectClick(data, 'leftClick')}
|
||||
on:middleclick={() => handleObjectClick(data, 'middleClick')}
|
||||
on:dblclick={() => handleObjectClick(data, 'dblClick')}
|
||||
on:click={() => handleClick({ tabPreviewMode: true })}
|
||||
on:middleclick={() => handleClick({ forceNewTab: true })}
|
||||
on:dblclick={() => handleClick({ tabPreviewMode: false, focusTab: true })}
|
||||
on:expand
|
||||
on:dragstart
|
||||
on:dragenter
|
||||
on:dragend
|
||||
on:drop
|
||||
on:mousedown={() => {
|
||||
$selectedDatabaseObjectAppObject = _.pick(data, ['conid', 'database', 'objectTypeField', 'pureName', 'schemaName']);
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
<script lang="ts" context="module">
|
||||
export const extractKey = data => data.name;
|
||||
export const createMatcher =
|
||||
filter =>
|
||||
({ name, title }) =>
|
||||
filterName(filter, name, title);
|
||||
export const createMatcher = ({ name, title }) => filter => filterName(filter, name, title);
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
@@ -6,26 +6,13 @@
|
||||
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={createParameterTitle(data)}
|
||||
extInfo={createParameterExtInfo(data)}
|
||||
title={data.parameterName?.startsWith('@') ? data.parameterName.substring(1) : data.parameterName}
|
||||
extInfo={data.parameterMode && data.parameterMode !== 'IN' ? `${data.dataType} ${data.parameterMode}` : data.dataType}
|
||||
icon={'icon parameter'}
|
||||
disableHover
|
||||
/>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user