Compare commits

..

22 Commits

Author SHA1 Message Date
Jan Prochazka 750bb3eb4b handle not found connection in ConnectionTab 2024-05-13 09:25:34 +02:00
Jan Prochazka b425985511 small fix 2024-05-13 08:40:27 +02:00
Jan Prochazka 6651f1d610 v5.2.8-beta.21 2024-05-10 14:04:56 +02:00
Jan Prochazka 5758720bfd build tar.gz for linux 2024-05-10 14:04:35 +02:00
Jan Prochazka fcc4f1c2e8 v5.2.8-beta.20 2024-05-10 12:54:04 +02:00
Jan Prochazka 01a113b2d3 flatpak fix 2024-05-10 12:53:43 +02:00
Jan Prochazka 0085a68e7e v5.2.8-beta.19 2024-05-10 12:21:40 +02:00
Jan Prochazka 6868f26d6c fix 2024-05-10 12:18:54 +02:00
Jan Prochazka f4832a579c v5.2.8-beta.18 2024-05-10 12:05:47 +02:00
Jan Prochazka 5bb34c9f0e flatpak without sudo 2024-05-10 11:45:49 +02:00
Jan Prochazka eb55f2276b build flatpak 2024-05-10 11:43:50 +02:00
Jan Prochazka 3f1247459b flatpak build hack 2024-05-10 11:42:04 +02:00
Jan Prochazka ddd9a10e6b flatpak build 2024-05-10 11:25:58 +02:00
Jan Prochazka 45388e61f7 flatpak install with sudo 2024-05-10 09:26:18 +02:00
Jan Prochazka 6752b84404 flatpak params 2024-05-10 09:26:13 +02:00
Jan Prochazka 8e227b3b18 flatpak install dependencies 2024-05-10 09:26:03 +02:00
Jan Prochazka 06c98eb437 copy flatpak artifacts 2024-05-10 09:25:52 +02:00
Jan Prochazka f5c629a6bc apt build-sudo 2024-05-10 09:25:23 +02:00
Jan Prochazka 188afcd2aa flatpak debug 2024-05-10 09:25:16 +02:00
Jan Prochazka 2a241eb944 incorrect 2024-05-10 09:25:05 +02:00
Jan Prochazka 1a01b08343 install flatpak 2024-05-10 09:24:49 +02:00
Jan Prochazka c90a76ec29 flatpak support #297 2024-05-10 09:24:40 +02:00
1117 changed files with 17931 additions and 224553 deletions
+45 -77
View File
@@ -1,31 +1,21 @@
# --------------------------------------------------------------------------------------------
# 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]+
permissions:
id-token: write
contents: write
- 'v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+'
jobs:
build:
runs-on: ${{ matrix.os }}
environment: dbgate-app
strategy:
fail-fast: false
matrix:
os:
- macos-14
- windows-2022
- ubuntu-22.04
os: [macos-12, 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) }}
@@ -33,84 +23,71 @@ jobs:
- 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
- name: setUpdaterChannel beta
run: |
node setUpdaterChannel beta
yarn adjustPackageJson
- name: yarn set timeout
run: |
yarn config set network-timeout 100000
- name: yarn install
run: |
yarn install
- name: setCurrentVersion
run: |
yarn setCurrentVersion
- name: fillNativeModulesElectron
run: |
yarn fillNativeModulesElectron
- name: fillPackagedPlugins
run: |
yarn fillPackagedPlugins
- name: Install Snapcraft
if: matrix.os == 'ubuntu-22.04'
uses: samuelmeuli/action-snapcraft@v1
- name: Publish Windows
if: matrix.os == 'windows-2022'
- name: Install flatpak
if: matrix.os == 'ubuntu-22.04'
run: |
yarn run build:app
- name: Publish MacOS
if: matrix.os == 'macos-14'
sudo apt install flatpak flatpak-builder --yes
flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak install --user --assumeyes --runtime flathub org.freedesktop.Platform/x86_64/23.08
flatpak install --user --assumeyes --runtime flathub org.freedesktop.Sdk/x86_64/23.08
flatpak install --user --assumeyes --app flathub org.electronjs.Electron2.BaseApp/x86_64/23.08
- name: Publish
run: |
yarn run build:app
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }} # token for electron publish
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
# WIN_CSC_LINK: ${{ secrets.WINCERT_CERTIFICATE }}
# WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_PASSWORD }}
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
- name: Publish Linux
- name: Install flatpak
if: matrix.os == 'ubuntu-22.04'
run: |
yarn run build:app:flatpak
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }} # token for electron publish
yarn run build:app
- name: publishSnap
if: matrix.os == 'ubuntu-22.04'
run: |
snapcraft upload --release=beta app/dist/*.snap
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
- name: Azure login (OIDC)
uses: azure/login@v2
if: matrix.os == 'windows-2022'
with:
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
allow-no-subscriptions: true
- name: Sign Windows artifacts with Azure Trusted Signing
uses: azure/trusted-signing-action@v0
if: matrix.os == 'windows-2022'
with:
endpoint: https://wus3.codesigning.azure.net/
trusted-signing-account-name: DbGate
certificate-profile-name: DbGate-Release
files-folder: app/dist
files-folder-filter: exe
timestamp-rfc3161: http://timestamp.acs.microsoft.com
timestamp-digest: SHA256
- name: Fix YML hashes
if: matrix.os == 'windows-2022'
run: |
yarn run fixYmlHashes
- name: Copy artifacts
run: |
mkdir artifacts
@@ -122,11 +99,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/*win_arm64.exe artifacts/dbgate-windows-beta-arm64.exe || 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
@@ -135,25 +109,19 @@ jobs:
mv app/dist/*.deb artifacts/ || true
mv app/dist/*.snap artifacts/ || true
mv app/dist/*.dmg artifacts/ || true
mv app/dist/*.blockmap artifacts/ || true
mv app/dist/*.flatpak artifacts/ || true
mv app/dist/*.yml artifacts/ || true
rm artifacts/builder-debug.yml
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v1
with:
name: ${{ matrix.os }}
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
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 {} ===" \;
-142
View File
@@ -1,142 +0,0 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Electron app check build
'on':
push:
tags:
- check-[0-9]+-[0-9]+-[0-9]+.[0-9]+
permissions:
id-token: write
contents: write
jobs:
build:
runs-on: ${{ matrix.os }}
environment: dbgate-app
strategy:
fail-fast: false
matrix:
os:
- macos-14
- windows-2022
- ubuntu-22.04
steps:
- name: Install python 3.11 (MacOS)
if: matrix.os == 'macos-14'
run: |
brew install python@3.11
echo "PYTHON=/opt/homebrew/bin/python3.11" >> $GITHUB_ENV
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 22.x
- name: adjustPackageJson
run: |
node adjustPackageJson --community
- name: yarn set timeout
run: |
yarn config set network-timeout 100000
- name: yarn install
run: |
yarn install
- name: setCurrentVersion
run: |
yarn setCurrentVersion
- name: fillPackagedPlugins
run: |
yarn fillPackagedPlugins
- name: Install Snapcraft
if: matrix.os == 'ubuntu-22.04'
uses: samuelmeuli/action-snapcraft@v1
- name: Publish Windows
if: matrix.os == 'windows-2022'
run: |
yarn run build:app
- name: Publish MacOS
if: matrix.os == 'macos-14'
run: |
yarn run build:app
env:
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 }}
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
- name: Publish Linux
if: matrix.os == 'ubuntu-22.04'
run: |
yarn run build:app
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
- name: Azure login (OIDC)
uses: azure/login@v2
if: matrix.os == 'windows-2022'
with:
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
allow-no-subscriptions: true
- name: Sign Windows artifacts with Azure Trusted Signing
uses: azure/trusted-signing-action@v0
if: matrix.os == 'windows-2022'
with:
endpoint: https://wus3.codesigning.azure.net/
trusted-signing-account-name: DbGate
certificate-profile-name: DbGate-Release
files-folder: app/dist
files-folder-filter: exe
timestamp-rfc3161: http://timestamp.acs.microsoft.com
timestamp-digest: SHA256
- name: Fix YML hashes
if: matrix.os == 'windows-2022'
run: |
yarn run fixYmlHashes
- name: Copy artifacts
run: |
mkdir artifacts
cp app/dist/*.deb artifacts/dbgate-check.deb || true
cp app/dist/*x86*.AppImage artifacts/dbgate-check.AppImage || true
cp app/dist/*arm64*.AppImage artifacts/dbgate-check-arm64.AppImage || true
cp app/dist/*armv7l*.AppImage artifacts/dbgate-check-armv7l.AppImage || true
cp app/dist/*win*.exe artifacts/dbgate-check.exe || true
cp app/dist/*win_x64.zip artifacts/dbgate-windows-check.zip || true
cp app/dist/*win_arm64.zip artifacts/dbgate-windows-check-arm64.zip || true
cp app/dist/*win_arm64.exe artifacts/dbgate-windows-check-arm64.exe || true
cp app/dist/*-mac_universal.dmg artifacts/dbgate-check.dmg || true
cp app/dist/*-mac_x64.dmg artifacts/dbgate-check-x64.dmg || true
cp app/dist/*-mac_arm64.dmg artifacts/dbgate-check-arm64.dmg || true
mv app/dist/*.snap artifacts/dbgate-check.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/*.blockmap artifacts/ || true
mv app/dist/*.yml artifacts/ || true
rm artifacts/builder-debug.yml
- 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 {} ===" \;
-196
View File
@@ -1,196 +0,0 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Electron app PREMIUM BETA
'on':
push:
tags:
- v[0-9]+.[0-9]+.[0-9]+-premium-beta.[0-9]+
permissions:
id-token: write
contents: write
jobs:
build:
runs-on: ${{ matrix.os }}
environment: dbgate-app
strategy:
fail-fast: false
matrix:
os:
- macos-14
- windows-2022
- ubuntu-22.04
steps:
- name: Install python 3.11 (MacOS)
if: matrix.os == 'macos-14'
run: |
brew install python@3.11
echo "PYTHON=/opt/homebrew/bin/python3.11" >> $GITHUB_ENV
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 22.x
- name: Checkout dbgate/dbgate-pro
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: 3b9ca48888d17d96806820c4e54bb047c18d6278
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
mv dbgate-pro/* ../dbgate-pro/
cd ..
mkdir dbgate-merged
cd dbgate-pro
cd sync
yarn
node sync.js --nowatch
cd ..
- name: adjustPackageJson
run: |
cd ..
cd dbgate-merged
node adjustPackageJson --premium
- name: 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: fillPackagedPlugins
run: |
cd ..
cd dbgate-merged
yarn fillPackagedPlugins
- name: Publish Windows
if: matrix.os == 'windows-2022'
run: |
cd ..
cd dbgate-merged
yarn run build:app
- name: Publish MacOS
if: matrix.os == 'macos-14'
run: |
cd ..
cd dbgate-merged
yarn run build:app
env:
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 }}
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
- name: Publish Linux
if: matrix.os == 'ubuntu-22.04'
run: |
cd ..
cd dbgate-merged
yarn run build:app
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
- name: Azure login (OIDC)
uses: azure/login@v2
if: matrix.os == 'windows-2022'
with:
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
allow-no-subscriptions: true
- name: Sign Windows artifacts with Azure Trusted Signing
uses: azure/trusted-signing-action@v0
if: matrix.os == 'windows-2022'
with:
endpoint: https://wus3.codesigning.azure.net/
trusted-signing-account-name: DbGate
certificate-profile-name: DbGate-Release
files-folder: ../dbgate-merged/app/dist
files-folder-filter: exe
timestamp-rfc3161: http://timestamp.acs.microsoft.com
timestamp-digest: SHA256
- name: Fix YML hashes
if: matrix.os == 'windows-2022'
run: |
cd ..
cd dbgate-merged
yarn run fixYmlHashes
- name: Copy artifacts
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/*win_arm64.exe artifacts/dbgate-windows-premium-beta-arm64.exe || true
cp ../dbgate-merged/app/dist/*-mac_universal.dmg artifacts/dbgate-premium-beta.dmg || true
cp ../dbgate-merged/app/dist/*-mac_x64.dmg artifacts/dbgate-premium-beta-x64.dmg || true
cp ../dbgate-merged/app/dist/*-mac_arm64.dmg artifacts/dbgate-premium-beta-arm64.dmg || true
mv ../dbgate-merged/app/dist/*.snap artifacts/dbgate-premium-beta.snap || true
mv ../dbgate-merged/app/dist/*.exe artifacts/ || true
mv ../dbgate-merged/app/dist/*.zip artifacts/ || true
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 }}
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
with:
files: artifacts/**
prerelease: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: 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 {} ===" \;
-196
View File
@@ -1,196 +0,0 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Electron app PREMIUM
'on':
push:
tags:
- v[0-9]+.[0-9]+.[0-9]+
permissions:
id-token: write
contents: write
jobs:
build:
runs-on: ${{ matrix.os }}
environment: dbgate-app
strategy:
fail-fast: false
matrix:
os:
- macos-14
- windows-2022
- ubuntu-22.04
steps:
- name: Install python 3.11 (MacOS)
if: matrix.os == 'macos-14'
run: |
brew install python@3.11
echo "PYTHON=/opt/homebrew/bin/python3.11" >> $GITHUB_ENV
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 22.x
- name: Checkout dbgate/dbgate-pro
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: 3b9ca48888d17d96806820c4e54bb047c18d6278
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
mv dbgate-pro/* ../dbgate-pro/
cd ..
mkdir dbgate-merged
cd dbgate-pro
cd sync
yarn
node sync.js --nowatch
cd ..
- name: adjustPackageJson
run: |
cd ..
cd dbgate-merged
node adjustPackageJson --premium
- name: 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: fillPackagedPlugins
run: |
cd ..
cd dbgate-merged
yarn fillPackagedPlugins
- name: Publish Windows
if: matrix.os == 'windows-2022'
run: |
cd ..
cd dbgate-merged
yarn run build:app
- name: Publish MacOS
if: matrix.os == 'macos-14'
run: |
cd ..
cd dbgate-merged
yarn run build:app
env:
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 }}
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
- name: Publish Linux
if: matrix.os == 'ubuntu-22.04'
run: |
cd ..
cd dbgate-merged
yarn run build:app
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
- name: Azure login (OIDC)
uses: azure/login@v2
if: matrix.os == 'windows-2022'
with:
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
allow-no-subscriptions: true
- name: Sign Windows artifacts with Azure Trusted Signing
uses: azure/trusted-signing-action@v0
if: matrix.os == 'windows-2022'
with:
endpoint: https://wus3.codesigning.azure.net/
trusted-signing-account-name: DbGate
certificate-profile-name: DbGate-Release
files-folder: ../dbgate-merged/app/dist
files-folder-filter: exe
timestamp-rfc3161: http://timestamp.acs.microsoft.com
timestamp-digest: SHA256
- name: Fix YML hashes
if: matrix.os == 'windows-2022'
run: |
cd ..
cd dbgate-merged
yarn run fixYmlHashes
- name: Copy artifacts
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/*win_arm64.exe artifacts/dbgate-windows-premium-latest-arm64.exe || 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 }}
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
with:
files: artifacts/**
prerelease: false
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 {} ===" \;
+89 -81
View File
@@ -1,31 +1,25 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Electron app
'on':
on:
push:
tags:
- v[0-9]+.[0-9]+.[0-9]+
permissions:
id-token: write
contents: write
- '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 }}
environment: dbgate-app
strategy:
fail-fast: false
matrix:
os:
- macos-14
- windows-2022
- ubuntu-22.04
# os: [ubuntu-22.04, windows-2016]
os: [macos-12, 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) }}
@@ -33,83 +27,62 @@ jobs:
- 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: fillNativeModulesElectron
run: |
yarn fillNativeModulesElectron
- name: fillPackagedPlugins
run: |
yarn fillPackagedPlugins
- name: Install Snapcraft
if: matrix.os == 'ubuntu-22.04'
uses: samuelmeuli/action-snapcraft@v1
- name: Publish Windows
if: matrix.os == 'windows-2022'
- name: Publish
run: |
yarn run build:app
- name: Publish MacOS
if: matrix.os == 'macos-14'
run: |
yarn run build:app
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }} # token for electron publish
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
# WIN_CSC_LINK: ${{ secrets.WINCERT_CERTIFICATE }}
# WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_PASSWORD }}
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
- name: Publish Linux
if: matrix.os == 'ubuntu-22.04'
run: |
yarn run build:app
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
- name: generatePadFile
run: |
yarn generatePadFile
- name: Azure login (OIDC)
uses: azure/login@v2
if: matrix.os == 'windows-2022'
with:
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
allow-no-subscriptions: true
- name: Sign Windows artifacts with Azure Trusted Signing
uses: azure/trusted-signing-action@v0
if: matrix.os == 'windows-2022'
with:
endpoint: https://wus3.codesigning.azure.net/
trusted-signing-account-name: DbGate
certificate-profile-name: DbGate-Release
files-folder: app/dist
files-folder-filter: exe
timestamp-rfc3161: http://timestamp.acs.microsoft.com
timestamp-digest: SHA256
- name: Fix YML hashes
if: matrix.os == 'windows-2022'
run: |
yarn run fixYmlHashes
- name: 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
@@ -118,45 +91,80 @@ 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/*win_arm64.exe artifacts/dbgate-windows-latest-arm64.exe || 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/*.blockmap artifacts/ || true
mv app/dist/*.snap artifacts/dbgate-latest.snap || true
mv app/dist/*.yml artifacts/ || true
rm artifacts/builder-debug.yml
- name: Copy PAD file
# - 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 latest.yml (windows)
if: matrix.os == 'windows-2022'
run: |
mv app/dist/latest.yml artifacts/latest.yml || true
mv app/dist/dbgate-pad.xml artifacts/ || true
- name: Copy latest-linux.yml
if: matrix.os == 'ubuntu-22.04'
run: |
mv app/dist/latest-linux.yml artifacts/latest-linux.yml || true
- name: Copy latest-mac.yml
if: matrix.os == 'macos-12'
run: |
mv app/dist/latest-mac.yml artifacts/latest-mac.yml || true
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v1
with:
name: ${{ matrix.os }}
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
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: |
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
-135
View File
@@ -1,135 +0,0 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Cloud images PREMIUM
'on':
push:
tags:
- v[0-9]+.[0-9]+.[0-9]+
- v[0-9]+.[0-9]+.[0-9]+-packer-beta.[0-9]+
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-22.04
steps:
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 22.x
- name: Install jq
run: |
sudo apt-get install jq -y
- name: Setup `packer`
uses: hashicorp/setup-packer@main
with:
version: latest
- name: Checkout dbgate/dbgate-pro
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: 3b9ca48888d17d96806820c4e54bb047c18d6278
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
mv dbgate-pro/* ../dbgate-pro/
cd ..
mkdir dbgate-merged
cd dbgate-pro
cd sync
yarn
node sync.js --nowatch
cd ..
- name: adjustPackageJson
run: |
cd ..
cd dbgate-merged
node adjustPackageJson --premium
- name: yarn install
run: |
cd ..
cd dbgate-merged
yarn install
- name: setCurrentVersion
run: |
cd ..
cd dbgate-merged
yarn setCurrentVersion
- name: Prepare packer build
run: |
cd ..
cd dbgate-merged
yarn run prepare:packer
cd packer
zip -r cloud-build.zip build
- name: Copy artifacts
run: |
mkdir artifacts
cp ../dbgate-merged/packer/cloud-build.zip artifacts/cloud-build.zip || true
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
with:
files: artifacts/**
prerelease: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run `packer init` for Azure
run: |
cd ../dbgate-merged/packer
packer init ./azure-ubuntu.pkr.hcl
- name: Run `packer build` for Azure
run: |
cd ../dbgate-merged/packer
packer build ./azure-ubuntu.pkr.hcl
- name: Run `packer init` for AWS
run: |
cd ../dbgate-merged/packer
packer init ./aws-ubuntu.pkr.hcl
env:
AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
AWS_DEFAULT_REGION: ${{secrets.AWS_DEFAULT_REGION}}
- name: Run `packer build` for AWS
run: |
cd ../dbgate-merged/packer
packer build ./aws-ubuntu.pkr.hcl
env:
AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
AWS_DEFAULT_REGION: ${{secrets.AWS_DEFAULT_REGION}}
- name: Delete old Azure VMs
run: |
cd ../dbgate-merged/packer
chmod +x delete-old-azure-images.sh
./delete-old-azure-images.sh
env:
AZURE_CLIENT_ID: ${{secrets.AZURE_CLIENT_ID}}
AZURE_CLIENT_SECRET: ${{secrets.AZURE_CLIENT_SECRET}}
AZURE_TENANT_ID: ${{secrets.AZURE_TENANT_ID}}
AZURE_SUBSCRIPTION_ID: ${{secrets.AZURE_SUBSCRIPTION_ID}}
- name: Delete old AMIs (AWS)
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}}
-100
View File
@@ -1,100 +0,0 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Docker image PREMIUM
'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 }}
strategy:
matrix:
os:
- ubuntu-22.04
steps:
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: dbgate/dbgate-premium
flavor: |
latest=false
tags: |
type=raw,value=beta,enable=${{ contains(github.ref_name, '-docker.') || contains(github.ref_name, '-beta.') }}
type=match,pattern=\d+.\d+.\d+,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
type=raw,value=latest,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 22.x
- name: Checkout dbgate/dbgate-pro
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: 3b9ca48888d17d96806820c4e54bb047c18d6278
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
mv dbgate-pro/* ../dbgate-pro/
cd ..
mkdir dbgate-merged
cd dbgate-pro
cd sync
yarn
node sync.js --nowatch
cd ..
- name: adjustPackageJson
run: |
cd ..
cd dbgate-merged
node adjustPackageJson --premium
- name: yarn install
run: |
cd ..
cd dbgate-merged
# yarn --version
# yarn config set network-timeout 300000
yarn install
- name: setCurrentVersion
run: |
cd ..
cd dbgate-merged
yarn setCurrentVersion
- name: Prepare docker image
run: |
cd ..
cd dbgate-merged
yarn run prepare:docker
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v3
with:
push: true
context: ../dbgate-merged/docker
tags: ${{ steps.meta.outputs.tags }}
platforms: linux/amd64,linux/arm64
+21 -21
View File
@@ -1,19 +1,21 @@
# --------------------------------------------------------------------------------------------
# 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]+
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-docker.[0-9]+'
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-22.04
os: [ubuntu-22.04]
steps:
- name: Context
env:
@@ -22,11 +24,13 @@ jobs:
- 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 +38,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,30 +52,23 @@ 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 22.x
- name: Use Node.js 18.x
uses: actions/setup-node@v1
with:
node-version: 22.x
- name: adjustPackageJson
run: |
node adjustPackageJson --community
node-version: 18.x
- name: yarn install
run: |
# yarn --version
# yarn config set network-timeout 300000
yarn install
- name: setCurrentVersion
run: |
yarn setCurrentVersion
- name: Prepare docker image
run: |
yarn run prepare:docker
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
@@ -78,6 +76,7 @@ jobs:
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v3
with:
@@ -85,6 +84,7 @@ jobs:
context: ./docker
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:
-103
View File
@@ -1,103 +0,0 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: NPM packages PREMIUM
'on':
push:
tags:
- v[0-9]+.[0-9]+.[0-9]+
- v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+
permissions:
id-token: write
contents: write
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-22.04
steps:
- name: Context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 22.x
- name: Checkout dbgate/dbgate-pro
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: 3b9ca48888d17d96806820c4e54bb047c18d6278
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
mv dbgate-pro/* ../dbgate-pro/
cd ..
mkdir dbgate-merged
cd dbgate-pro
cd sync
yarn
node sync.js --nowatch
cd ..
- name: adjustNpmPackageJsonPremium
run: |
cd ..
cd dbgate-merged
node adjustNpmPackageJsonPremium
- name: Update npm
run: npm install -g npm@latest
- 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: Compute npm dist-tag
run: |
if [[ "${GITHUB_REF_NAME}" =~ -alpha\. ]]; then
echo "NPM_TAG=alpha" >> $GITHUB_ENV
else
echo "NPM_TAG=latest" >> $GITHUB_ENV
fi
- name: Publish dbgate-api-premium
run: |
cd ..
cd dbgate-merged/packages/api
npm publish --tag "$NPM_TAG"
- name: Publish dbgate-web-premium
run: |
cd ..
cd dbgate-merged/packages/web
npm publish --tag "$NPM_TAG"
- name: Publish dbgate-serve-premium
run: |
cd ..
cd dbgate-merged/packages/serve
npm publish --tag "$NPM_TAG"
- name: Publish dbgate-plugin-cosmosdb
run: |
cd ..
cd dbgate-merged/plugins/dbgate-plugin-cosmosdb
npm publish --tag "$NPM_TAG"
- name: Publish dbgate-plugin-firestore
run: |
cd ..
cd dbgate-merged/plugins/dbgate-plugin-firestore
npm publish --tag "$NPM_TAG"
+68 -53
View File
@@ -1,22 +1,27 @@
# --------------------------------------------------------------------------------------------
# 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]+
permissions:
id-token: write
contents: write
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+'
# on:
# push:
# branches:
# - production
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-22.04
os: [ubuntu-22.04]
steps:
- name: Context
env:
@@ -25,111 +30,121 @@ jobs:
- 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: Update npm
run: npm install -g npm@latest
node-version: 18.x
- name: Configure NPM token
env:
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: Compute npm dist-tag
run: |
if [[ "${GITHUB_REF_NAME}" =~ -alpha\. ]]; then
echo "NPM_TAG=alpha" >> $GITHUB_ENV
else
echo "NPM_TAG=latest" >> $GITHUB_ENV
fi
- name: Publish types
working-directory: packages/types
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish tools
working-directory: packages/tools
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish sqltree
working-directory: packages/sqltree
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish api
working-directory: packages/api
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish datalib
working-directory: packages/datalib
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish filterparser
working-directory: packages/filterparser
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish web
working-directory: packages/web
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish dbgate (obsolete)
working-directory: packages/dbgate
run: |
npm publish
- name: Publish dbgate-serve
working-directory: packages/serve
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish dbmodel
working-directory: packages/dbmodel
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish dbgate-plugin-csv
working-directory: plugins/dbgate-plugin-csv
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish dbgate-plugin-xml
working-directory: plugins/dbgate-plugin-xml
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish dbgate-plugin-excel
working-directory: plugins/dbgate-plugin-excel
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish dbgate-plugin-mssql
working-directory: plugins/dbgate-plugin-mssql
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish dbgate-plugin-mysql
working-directory: plugins/dbgate-plugin-mysql
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish dbgate-plugin-mongo
working-directory: plugins/dbgate-plugin-mongo
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish dbgate-plugin-postgres
working-directory: plugins/dbgate-plugin-postgres
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish dbgate-plugin-sqlite
working-directory: plugins/dbgate-plugin-sqlite
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish dbgate-plugin-redis
working-directory: plugins/dbgate-plugin-redis
run: |
npm publish --tag "$NPM_TAG"
npm publish
- name: Publish dbgate-plugin-oracle
working-directory: plugins/dbgate-plugin-oracle
run: |
npm publish --tag "$NPM_TAG"
- name: Publish dbgate-plugin-clickhouse
working-directory: plugins/dbgate-plugin-clickhouse
run: |
npm publish --tag "$NPM_TAG"
- name: Publish dbgate-plugin-dbf
working-directory: plugins/dbgate-plugin-dbf
run: |
npm publish --tag "$NPM_TAG"
- name: Publish dbgate-plugin-cassandra
working-directory: plugins/dbgate-plugin-cassandra
run: |
npm publish --tag "$NPM_TAG"
npm publish
@@ -1,46 +0,0 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Build test containers
'on':
push:
branches:
- master
- develop
- feature/**
- hotfix/**
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
-36
View File
@@ -1,36 +0,0 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Diflow merge
'on':
push:
branches:
- master
jobs:
merge:
runs-on: ubuntu-latest
steps:
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 22.x
- name: Checkout dbgate/diflow
uses: actions/checkout@v2
with:
repository: dbgate/diflow
path: diflow
- name: Diflow install
run: |
cd diflow
npm install
npm run build
- name: Git config
run: |
git config --global user.email "info@dbgate.io"
git config --global user.name "Diflow"
- name: Diflow run
run: |
cd diflow
node dist/diflow.js sync -r https://DIFLOW_GIT_SECRET@github.com/dbgate/dbgate-diflow-config.git -b master
env:
DIFLOW_GIT_SECRET: ${{ secrets.DIFLOW_GIT_SECRET }}
-133
View File
@@ -1,133 +0,0 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Cypress tests with screenshots PREMIUM
'on':
push:
branches:
- master
- develop
- feature/**
- hotfix/**
jobs:
e2e-tests:
runs-on: ubuntu-latest
steps:
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 22.x
- uses: actions/checkout@v3
with:
fetch-depth: 1
- name: Checkout dbgate/dbgate-pro
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: 3b9ca48888d17d96806820c4e54bb047c18d6278
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
mv dbgate-pro/* ../dbgate-pro/
cd ..
mkdir dbgate-merged
cd dbgate-pro
cd sync
yarn
node sync.js --nowatch
cd ..
- name: yarn install
run: |
cd ../dbgate-merged
yarn install
- name: Build packer dist for cypress
run: |
cd ../dbgate-merged
yarn prepare:packer
- name: yarn install cypress
run: |
cd ../dbgate-merged
cd e2e-tests
yarn install
- name: Run Cypress tests
run: |
cd ../dbgate-merged
cd e2e-tests
yarn test:ci
- name: ls -R
run: |
cd ../dbgate-merged
ls -R
- name: Copy screenshots
run: |
mkdir screenshots
cp ../dbgate-merged/e2e-tests/screenshots/*.png screenshots/
- name: Upload E2E screenshots
uses: actions/upload-artifact@v4
with:
name: screenshots
path: screenshots
- name: Push E2E screenshots
if: ${{ github.ref_name == 'master' }}
run: |
git config --global user.email "info@dbgate.info"
git config --global user.name "GitHub Actions"
git clone https://${{ secrets.DIFLOW_GIT_SECRET }}@github.com/dbgate/dbgate-img.git
cp ../dbgate-merged/e2e-tests/screenshots/*.png dbgate-img/static/img
cd dbgate-img/static/img
git add .
git commit --amend --no-edit
git push --force
services:
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:
- '16012: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'
mongo:
image: mongo:4.4.29
env:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: Pwd2020Db
ports:
- '16010:27017'
redis:
image: redis
ports:
- '16011:6379'
mssql:
image: mcr.microsoft.com/mssql/server
ports:
- '16014:1433'
env:
ACCEPT_EULA: 'Y'
SA_PASSWORD: Pwd2020Db
MSSQL_PID: Express
oracle:
image: gvenzl/oracle-xe:21-slim
env:
ORACLE_PASSWORD: Pwd2020Db
ports:
- '16013:1521'
-51
View File
@@ -1,51 +0,0 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Update Workflows
'on':
push:
branches:
- master
paths:
- workflow-templates/**
jobs:
update-workflows:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
token: ${{ secrets.WORKFLOW_CHANGE_ACCESS_TOKEN }}
- name: git pull
run: |
git pull
- name: Set up Node
uses: actions/setup-node@v3
with:
node-version: 22
- name: Install dependencies
run: |
rm package.json
rm yarn.lock
yarn add -W js-yaml lodash
- name: Run workflow generation
run: |
node common/processWorkflows.js
- name: Git config
run: |
git config --global user.email "info@dbgate.io"
git config --global user.name "CI workflows"
- name: Commit changes
run: |
# Only commit if there are changes
if [[ -n "$(git status --porcelain)" ]]; then
git add .github/workflows
git commit -m "chore: auto-update github workflows"
else
echo "No changes to commit"
fi
- name: Push changes
uses: ad-m/github-push-action@v0.6.0
with:
github_token: ${{ secrets.WORKFLOW_CHANGE_ACCESS_TOKEN }}
branch: master
+44 -59
View File
@@ -1,23 +1,21 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Integration and unit tests
'on':
name: Run tests
on:
push:
branches:
- master
- develop
- feature/**
- hotfix/**
jobs:
all-tests:
test-runner:
runs-on: ubuntu-latest
container: node:18
steps:
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 22.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
@@ -27,6 +25,7 @@ jobs:
run: |
cd integration-tests
yarn test:ci
# yarn wait:ci
- name: Filter parser tests
if: always()
run: |
@@ -37,61 +36,47 @@ jobs:
run: |
cd packages/datalib
yarn test:ci
- name: Tools tests
- uses: tanmen/jest-reporter@v1
if: always()
run: |
cd packages/tools
yarn test:ci
with:
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 }}
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 }}
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:
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: bitnamilegacy/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'
cassandradb:
image: cassandra:5.0.2
ports:
- '15942:9042'
libsql:
image: ghcr.io/tursodatabase/libsql-server:latest
ports:
- '8080:8080'
firebird:
image: firebirdsql/firebird:latest
env:
FIREBIRD_DATABASE: mydatabase.fdb
FIREBIRD_USER: dbuser
FIREBIRD_PASSWORD: dbpassword
ISC_PASSWORD: masterkey
FIREBIRD_TRACE: false
FIREBIRD_USE_LEGACY_AUTH: true
ports:
- '3050:3050'
# cockroachdb:
# image: cockroachdb/cockroach
+3 -7
View File
@@ -24,15 +24,11 @@ docker/plugins
.env.development.local
.env.test.local
.env.production.local
.env.translation
npm-debug.log*
yarn-debug.log*
yarn-error.log*
app/src/nativeModulesContent.js
packages/api/src/nativeModulesContent.js
packages/api/src/packagedPluginsContent.js
.VSCodeCounter
packages/web/public/*.html
e2e-tests/screenshots/*.png
my_guitar_shop.db
.aider*
.VSCodeCounter
-1
View File
@@ -1 +0,0 @@
v24.4.1
+19 -40
View File
@@ -1,41 +1,20 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug App",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/packages/api/src/index.js",
"envFile": "${workspaceFolder}/packages/api/.env",
"args": ["--listen-api"],
"console": "integratedTerminal",
"restart": true,
"runtimeExecutable": "node",
"skipFiles": ["<node_internals>/**"]
},
{
"name": "Debug App (Break on Start)",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/packages/api/src/index.js",
"args": ["--listen-api"],
"envFile": "${workspaceFolder}/.env",
"console": "integratedTerminal",
"restart": true,
"runtimeExecutable": "node",
"skipFiles": ["<node_internals>/**"],
"stopOnEntry": true
},
{
"name": "Attach to Process",
"type": "node",
"request": "attach",
"port": 9229,
"restart": true,
"localRoot": "${workspaceFolder}",
"remoteRoot": "${workspaceFolder}",
"skipFiles": ["<node_internals>/**"]
}
]
}
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch API",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}/packages/api/src/index.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
]
}
]
}
+2 -472
View File
@@ -8,473 +8,7 @@ Builds:
- linux - application for linux
- win - application for Windows
## 6.7.1
- ADDED: LANGUAGE environment variable for the web version. #1266
- ADDED: New localizations (Italian, Portugese (Brazil), Japanese)
- ADDED: Option to detect language from browser settings in web version
- FIXED: Check updates option no longer available in 6.7.0 #1263
- FIXED: A MERGE statement must be terminated by a semi-colon (;), but dbgate stripped it. #1257
- ADDED: Show table size #552
- ADDED: Sort tables by size and by row count
- ADDED: Connect to Legacy MongoDB (Premium) #540
- FIXED: Fixed problems in saving team files in Team Premium edition
- CHANGED: Files are by default saved to team folders in Team Premium edition
- ADDED: Other files types supported in Team Premium edition (diagrams, query design, perspectives, import/export jobs, shell scripts, database compare jobs)
## 6.7.0
- ADDED: Added localization support, now you can use DbGate in multiple languages (French, Spanish, German, Czech, Slovak, Simplified Chinese) #347 #705 #939 #1079
- CHANGED: Solved many issues with binary fields, huge performance improvements in binary fields processing
- FIXED: Export to CSV produces empty file #1247
- CHANGED: Upgraded electron to version 38 #1243
- FIXED: PostgreSQL export to SQL and XML doesn't include bytea field contents #1228
- FIXED: Export CSV broken #1080
- FIXED: Inconsistent handling of hex-like strings #680
- FIXED: Export mongodb binary cell as binary file #292
- CHANGED: SSL is used automatically for connections to Azure databases
- ADDED: New export formats CSV for Excel, TSV
- FIXED: Horizontal scrolling on macOS trackpad/Magic Mouse #1250
## 6.6.12
- FIXED: Cannot paste license key on Mac (special commands like copy/paste were disabled on license screen)
## 6.6.11
- FIXED: Fixed theming on application startup
- CHANGED: Improved licensing page
## 6.6.10
- FIXED: License from environment variable is not refreshed #1245
- FIXED: connection closing / reconnecting #1237
- ADDED: retain history across multiple queries #1236
- ADDED: load CSVs to temp tables #1235
- FIXED: Not possible to scroll the data view horizontally by pressing shift and scroll mouse middle button on Mac #453
- FIXED: Expired trial workflow (Premium)
- ADDED: Column name collision resolving #1234 (MySQL)
## 6.6.8
- CHANGED: Windows executable now uses Azure trusted signing certificate
- CHANGED: NPM packages now use GitHub OIDC provenance signing for better security
- CHANGED: Some features moved to Premium edition (master/detail views, FK lookups, column expansion, split view, advanced export/import, data archives, grouping, macros)
## 6.6.6
- ADDED: Allow disable/re-enable filter #1174
- ADDED: Close right side tabs #1219
- ADDED: Ability disable execute current line in query editor #1209
- ADDED: Support for Redis Cluster #1204 (Premium)
## 6.6.5
- ADDED: SQL AI assistant - powered by database chat, could help you to write SQL queries (Premium)
- ADDED: Explain SQL error (powered by AI) (Premium)
- ADDED: Database chat (and SQL AI Assistant) now supports showing charts (Premium)
- FIXED: Fxied editing new files and roles (Team Premium)
- FIXED: Connection to standalone database could be now pinned
- FIXED: Cannot open up large JSON file #1215
## 6.6.4
- ADDED: AI Database chat now supports much more LLM models. (Premium)
- ADDED: Possibility to use your own API key with OPENAI-compatible providers (OpenRouter, Antropic...)
- ADDED: Possibility to use self-hosted own LLM (eg. Llama)
- ADDED: Team files - save SQL files and define shared charts, assign roles and users to these objects (Team Premium)
- FIXED: BUG: does no longer work with Cockroach DB #1202
- FIXED: DbGate Web UI Connections do not display 'Databases' #1199
- CHANGED: Redesign fof applications. Applications are now storted in single JSON file
- ADDED: Application editor (Premium)
- ADDED: Posibility to filter only tables with rows
- FIXED: Fixed several issues with large Firebird databases
- CHANGED: Community edition now supports shared folders in read-only mode
## 6.6.3
- FIXED: Error “db.getCollection(…).renameCollection is not a function” when renaming collection in dbGate #1198
- FIXED: Can't list databases from Azure SQL SERVER #1197
- ADDED: Save zoom level in electron apps
## 6.6.2
- ADDED: List of processes, ability to kill process (Server summary) #1178
- ADDED: Database and table permissions (Team Premium edition)
- ADDED: Redis search box - Scan all #1191
- FIXED: Optimalized loading SQL server with descriptions #1187
- CHANGED: Allow a much greater page size #1185
- FIXED: Optimalized loading SQL server with descriptions #1187
- FIXED: Executing queries for SQLite crash #1195
## 6.6.1
- ADDED: Support for Mongo shell (Premium) - #1114
- FIXED: Support for BLOB in Oracle #1181
- ADDED: Connect to named SQL Server instance #340
- ADDED: Support for SQL Server descriptions #1137
- ADDED: Application log viewer
- FIXED: Selecting default database in connection dialog
- CHANGED: Improved logging system, added related database and connection to logs metadata
## 6.6.0
- ADDED: Database chat - AI powered chatbot, which knows your database (Premium)
- ADDED: Firestore support (Premium)
- REMOVED: Query AI assistant (replaced by Database Chat) (Premium)
- FIXED: Chart permissions were ignored (Premium)
## 6.5.6
- ADDED: New object window - quick access to most common functions
- ADDED: Possibility to disable split query by empty line #1162
- ADDED: Possibility to opt out authentication #1152
- FIXED: Separate schema mode now works in Team Premium edition
- FIXED: Handled situation, when user enters expired license, which is already prolonged
- FIXED: Fixed some minor problems of charts
## 6.5.5
- ADDED: Administer cloud folder window
- CHANGED: Cloud menu redesign
- ADDED: Audit log (for Team Premium edition)
- ADDED: Added new timeline chart type (line chart with time axis)
- ADDED: Chart grouping (more measure determined from data)
- CHANGED: Improved chart autodetection - string X axis (with bar type), COUNT as measure, split different measures
- ADDED: Added chart data type detection
- FIXED: Fixed chart displaying problems
- FIXED: Fixed exporting chart to HTML
- CHANGED: Choose COUNT measure without selecting underlying ID field (use virtual __count)
- FIXED: Problems with authentification administration, especially for Postgres storage
- CHANGED: Anonymous autentification (in Team Premium) is now by default disabled
## 6.5.3
- CHANGED: Improved DbGate Cloud sign-in workflow
- FIXED: Some fixes and error handling in new charts engine
- ADDED: Charts - ability to choose aggregate function
- CHANGED: Improved About window
## 6.5.2
- CHANGED: Autodetecting charts is disabled by default #1145
- CHANGED: Improved chart displaying workflow
- ADDED: Ability to close chart
## 6.5.1
- FIXED: DbGate Cloud e-mail sign-in method for desktop clients
## 6.5.0
- ADDED: DbGate cloud - online storage for connections, SQL scripts and other objects
- ADDED: Public knowledge base - common SQL scripts for specific DB engines (table sizes, index stats etc.)
- ADDED: Query results could be visualised in charts (Premium)
- REMOVED: Chart from selection, active charts - replaced by query result charts
- ADDED: FirebirdSQL support
- ADDED: SQL front matter - properties of SQL script
- ADDED: Auto-execute SQL script on open (saved in SQL front matter)
- CHANGED: Smaller widget icon panel
- CHANGED: Applications and Single-connection mode removed from widget icon panel
- CHANGED: Temporarily disabled MongoDB profiler support
- FIXED: Pie chart distorted if settings change #838
- FIXED: SQL server generated insert statement should exclude computed and timestamp columns #1111
- ADDED: Added option "Show all columns when searching" #1118
- ADDED: Copy cells/rows (e.g. column names) from Structure view #1119
- ADDED: Setting "Show table aliases in code completion" #1122
- FIXED: Vulnerability - check file paths in web version
- FIXED: Very slow render of tables with very log cells
## 6.4.2
- ADDED: Source label to docker container #1105
- FIXED: DbGate restart needed to take effect after trigger is created/deleted on mariadb #1112
- ADDED: View PostgreSQL query console output #1108
- FIXED: Single quote generete MySql error #1107
- ADDED: Ability to limit query result count #1098
- CHANGED: Correct processing of bigint columns #1087 #1055 #583
- CHANGED: Improved and optimalized algorithm of loading redis keys #1062, #1034
- FIXED: Fixed loading Redis keys with :: in key name
## 6.4.0
- ADDED: DuckDB support
- ADDED: Data deployer (Premium)
- ADDED: Compare data between JSON lines file in archive and database table
- CHANGED: Data Duplicator => Data Replicator (suitable for update, create and delete data, much more customizable)
- REMOVED: Data duplicator GUI (replaced with Data Deployer)
- ADDED: Exporting to ZIP file
- ADDED: Download SQL and SQLite files
- ADDED: Upload SQLite files
- ADDED: Upload archive as ZIP folder (Premium)
- ADDED: Compress, uncompress archive folder (Premium)
- ADDED: Export connections and settings #357
- ADDED: Filtering by MongoDB ObjectId works now also without ObjectId(...) wrapper
- ADDED: Split queries using blank lines #1089
- FIXED: JSON-to-Grid only works if there is no newline #1085
- CHANGED: When running multiple commands in script, stop execution after first error #1070
- FIXED: Selection rectangle remains visible after closing JSONB edit cell value form #1031
- FIXED: Diplaying numeric FK column with right alignement #1021
- ADDED: Additional arguments for MySQL and PostgreSQL backup #1092
- CHANGED: Amazon and Azure instalations are not auto-upgraded by default
## 6.3.3
- CHANGED: New administration UI, redesigned administration of users, connections and roles
- ADDED: Encrypting passwords in team-premium edition
- ADDED: Show scale bar on map #1090
- FIXED: Fixed native backup/restore for MySQL+PostgreSQL over SSH tunnel #1092
- CHANGED: Column mapping dialog - fixes and improvements for copying from one existing table into another
- ADDED: Search in columns in table editor
- ADDED: Line Wrap for JSON viewer #768
### 6.3.2
- ADDED: "Use system theme" switch, use changed system theme without restart #1084
- ADDED: "Skip SETNAME instruction" option for Redis #1077
- FIXED: Clickhouse views are now available even for user with limited permissions #1076
- ADDED: Multiple-token search delimited with comma (=OR) in structure search boxes
- CHANGED: When filtering columns in data browser, data view shows only filtered columns
- ADDED: Advanced settings for diagrams (Premium)
- ADDED: Diagrams - zoom with Ctrl+mouse wheel
- FIXED: Scrollable diagram exports + scroll by mouse drag
- FIXED: Fixed many problems in diagrams when zoom is applied
- FIXED: Correctly end connection process after succesful/unsuccesful connect
### 6.3.0
- ADDED: Support for libSQL and Turso (Premium)
- ADDED: Native backup and restore database for MySQL and PostgreSQL (Premium)
- REMOVED: DbGate internal dump export for MySQL (replaced with call of mysqldump)
- REMOVED: Import SQL dump with internal DbGate capabilities (replaced by calling of mysql and psql utilities)
- FIXED: Many fixes in stream processing (imoprt/export), especialy for MongoDB
- ADDED: Indicating progress of import/export tasks, better error reporting
- CHANGED: #1060 - Changed shortcut for AI assistant
- ADDED: /health endpoint with diagnostic info
- FIXED: Linux Appimage crash => A JavaScript error occurred in the main process #1065 , #1067
### 6.2.1
- ADDED: Commit/rollback and autocommit in scripts #1039
- FIXED: Doesn't import all the records from MongoDB #1044
- ADDED: Show server name alongside database name in title of the tab group #1041
- ADDED: Can't open Sqlite through web #956
- FIXED: Crashed after text input at columns search #1049
- FIXED: Incorrect autojoin for foreign keys with more columns #1051
- FIXED: Scroll in XML cell view, XML view respect themes
- REMOVED: armv7l build for Linux (because of problems with glibc compatibility)
- CHANGED: Upgraded to node:22 for docker builds
- CHANGED: Upgraded SQLite engine version
### 6.2.0
- ADDED: Query AI Assistant (Premium)
- ADDED: Cassandra database support
- ADDED: XML cell data view
- FIXED: Filtering by value in Oracle #1009
- FIXED: Operand type clash: uniqueidentifier is incompatible with int #565
- FIXED: UX in administration
- FIXED: Error reporting of broken connections (sometimes it caused infinite loading of data grid)
- ADDED: Azure managed identity support (Team Premium)
- ADDED: Expanded JSON cell view
- CHANGED: Open real executed query, when datagrid shows loading error
### 6.1.6
- FIXED: Hotfix build process for premium edition
### 6.1.5
- FIXED: Serious security hotfix (for Docker and NPM, when using LOGIN and PASSWORD environment variables or LOGIN_PASSWORD_xxx)
- no changes for desktop app and for Team premium edition, when using storage DB
### 6.1.4
- CHANGED: Show Data/Structure button in one place #1015
- ADDED: Data view coloring (every second row) #1014
- ADDED: Pin icon for tab in preview mode (#1013)
- FIXED: Pin icon misplaced #1007
- ADDED: Set client name when connecting to redis #1004
- ADDED: Redis loading keys optimalization #1002
- ADDED: Browse redis keys with preview with keyboard
- FIXED: Cannot expand tables and views returned from search #1000
- ADDED: Expand all/Collapse all/Expand document commands in MongoDB JSON view #976
- ADDED: Configurable page size for MongoDB collection #976
- ADDED: Redis - SSL connection
- ADDED: Redis JSON format for String values #852
### 6.1.3
- FIXED: Fulltext search now shows correctly columns and SQL code lines
- ADDED: Configuration of SSH tunnel local host (IPv4 vs IPv6). Should fix majority of SSH tunnel problems
- FIXED: Handled SSH tunnel connection error, now it shows error instead of connecting forever
- ADDED: Support of triggers (SQLite)
- ADDED: Create, drop trigger
- ADDED: Support for MySQL scheduled events
- FIXED: Cannot connect to DB using askUser/askPassword mode #995
- FIXED: Filtering in Oracle #992
- ADDED: Open table in raw mode #991, #962
- ADDED: Introduced E2E Cypress tests, test refactor
### 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
- CHANGED: (Premium) Workflow for new installation (used in Docker and AWS distribution)
- ADDED: Show stored procedure and function parameters (MySQL, PostgreSQL, SQL Server, MariaDB) #348
- FIXED: Selected database has changed when closing database grouped tab #983
- ADDED: Add line break option to editor #823
- ADDED: Order or filter the indexes for huge tables #922
- ADDED: Preview mode for the top bar tab like vscode #767
- ADDED: Keyboard navigatioon between connections, databases and tables
- FIXED: Fixed some issues in connection search
- FIXED: Schema selection in Export does not provide all schemas #924
- CHANGED: Standardized Window menu in MacOS app
- FIXED: Typecast ::date is treated as a parameter #925
- FIXED: App crashes when trying to 'Open Structure' in a readonly connection #926
- FIXED: Selected database has changed when closing database grouped tab #938
- CHANGED: (Premium) Query designer and Query perspective designer moved to Premium editioin
- CHANGED: (Premium) Compare database tool - many improvements, moved to Premium edition
- ADDED: (Premium) Export DB model - exporting model to YAML folder, JSON or SQL folder
- CHANGED: Model deployer - many improvements, support of rename missing objects
- ADDED: (Premium) Premium NPM distribution
- CHANGED: (Premium) Amazon Redshift driver moved to Premium edition
- ADDED: Generated API documentation https://dbgate.org/docs/apidoc.html
- ADDED: NPM distribution now supports all dbgate database connectors, many improvements NPM packages
- CHANGED: Optimalized size of NPM plugins (eg. dbgate-plugin-mssql from 1.34 MB to 71 kB)
- CHANGED: Unsaved connections are now shown in "Recent and unsaved" folder after disconnect
- FIXED: Correctly show focused control, as defined by UX standards
- ADDED: Data duplicator - weak references
- ADDED: View JSON detail of log messages from export/import jobs and query executions
- ADDED: Rename procedure/function context menu
- ADDED: Show SQL quick view
### 5.5.6
- FIXED: DbGate process consumes 100% after UI closed - Mac, Linux (#917, #915)
- FIXED: Correctly closing connection behind SSH tunnel (#920)
- FIXED: Updating MongoDB documents on MongoDB 4 (#916)
- FIXED: (Premium) DbGate container correctly waits for underlying storage database, if database container is started after dbgate container is started
- FIXED: (Premium) Better handling of connection storage errors
### 5.5.5
- ADDED: AWS IAM authentication for MySQL, MariaDB, PostgreSQL (Premium)
- FIXED: Datitme filtering #912
- FIXED: Load redis keys
- ADDED: Query parameters #913
- FIXED: Data grid with hidden columns #911
- ADDED: Added buttons for one-click authentification methods (Anonymous, OAuth) (Team Premium)
- ADDED: Link for switching Admin/user login (Team Premium)
- FIXED: Save connection params in administration for MS SQL and Postgres storages (Team Premium)
### 5.5.4
- FIXED: correct handling when use LOGIN and PASSWORD env variables #903
- FIXED: fixed problems in dbmodel commandline tool
- ADDED: dbmodel - allow connection defined in environment variables
- FIXED: Load postgres schema on Azure #906
- FIXED: Oauth2 in combination with Google doesn't log payload #727
- CHANGED: Improved error reporting for unhandler errors
- CHANGED: Don't restart docker container in case of unhandler error
- FIXED: Crash when displaying specific data values from MongoDB #908
- ADDED: (Premium) Show purchase button after trial license is expired
### 5.5.3
- FIXED: Separate schema mode #894 - for databases with many schemas
- FIXED: Sort by UUID column in POstgreSQL #895
- ADDED: Load pg_dump outputs #893
- ADDED: Improved column mapping in import/export #330
- FIXED: Fixed some errors in create-table workflow
- CHANGED: Show single schema by default only if all objects are from default schema
- FIXED: MS Entra authentication for Azure SQL
### 5.5.2
- FIXED: MySQL, PostgreSQL readonly conections #900
### 5.5.1
- ADDED: Clickhouse support (#532)
- ADDED: MySQL - specify table engine, show table engine in table list
- FIXED: Hidden primary key name in PK editor for DB engines with anonymous PK (MySQL)
- CHANGED: Import/export dialog is now tacub instead of modal
- ADDED: Saving import/export job
- REMOVED: Ability to reopen export/import wizard from generated script. This was a bit hack, now you could save import/export job instead
- ADDED: Autodetect CSV delimited
- FIXED: Import CSV files with spaces around quotes
- ADDED: JSON file import
- ADDED: JSON export can export objects with ID field used as object key
- ADDED: JSON and JSON lines imports supports importing from web URL
- FIXED: Editing imported URL in job editor
- ADDED: Quick export from table data grid (#892)
- CHANGED: Create table workflow is reworked, you can specify schema and table name in table editor
- FIXED: After saving new table, table editor is reset to empty state
- ADDED: (PostgreSQL, SQL Server) - ability to filter objects by schema
- ADDED: (PostgreSQL, SQL Server) - Use separate schemas option - for databases with lot of schemas, only selected schema is loaded
- FIXED: Internal refactor of drivers, client objects are not more messed up with auxiliary fields
- ADDED: Copy connection error to clipboard after clicking on error icon
- FIXED: (MySQL) Fixed importing SQL dump exported from mysqldump (#702)
- FIXED: (PostgreSQL) Fixed filtering JSONB fields (#889)
- FIXED: OIDC authentication not working anymore (#891)
- ADDED: Added tests for import from CSV and JSON
- FIXED: multiple shortcuts handling #898
- ADDED: (Premium) MS Entra authentization for Azure SQL databases
### 5.4.4
- CHANGED: Improved autoupdate, notification is now in app
- CHANGED: Default behaviour of autoupdate, new version is downloaded after click of "Download" button
- ADDED: Ability to configure autoupdate (check only, check+download, don't check)
- ADDED: Option to run check for new version manually
- FIXED: Fixed autoupgrade channel for premium edition
- FIXED: Fixes following issues: #886, #865, #782, #375
### 5.4.2
- FIXED: DbGate now works correctly with Oracle 10g
- FIXED: Fixed update channel for premium edition
### 5.4.1
- FIXED: Broken older plugins #881
- ADDED: Premium edition - "Start trial" button
### 5.4.0
- ADDED: Support for CosmosDB (Premium only)
- ADDED: Administration UI (Premium only)
- ADDED: New application icon
- ADDED: MongoDB type support in data editing
- ADDED: MongoDB - posibility to remove field
- ADDED: Oracle - posibility to connect via SID
- FIXED: Many improvements in MongoDB filtering
- FIXED: Switch to form and back to table rows missing #343
- ADDED: Posibility to deactivate MongoDB Profiler #745
- ADDED: Ability to use Oracle thick driver - neccessary for connecting older Oracle servers #843
- FIXED: Connection permissions configuration is broken #860
- ADDED: ssh key file authentication option missing #876
- ADDED: Ability to reset layout #878
- FIXED: Script with escaped backslash causes erro #880
### 5.3.4
- FIXED: On blank system does not start (window does not appear) #862
- FIXED: Missing Execute, Export bar #861
### 5.3.3
- FIXED: The application Window is not visible when openning after changing monitor configuration. #856
- FIXED: Multi column filter is broken for Postgresql #855
- ADDED: Do not display internal timescaledb objects in postgres databases #839
- FIXED: When in splitview mode and Clicking "Refresh" button on the right side, will refresh the left side, and not the right side #810
- FIXED: Cannot filter by uuid field in psql #538
### 5.3.1
- FIXED: Column sorting on query tab not working #819
- FIXED: Postgres Connection stays in "Loading database structure" until reloading the page #826
- FIXED: Cannot read properties of undefined (reading 'length') on Tables #824
- FIXED: Redshift doesn't show tables when connected #816
### 5.3.0
- CHANGED: New Oracle driver, much better Oracle support. Works now also in docker distribution
- FIXED: Connection to oracle with service name #809
- ADDED: Connect to redis using a custom username #807
- FIXED: Unable to open SQL files #797
- FIXED: MongoDB query without columns #811
- ADDED: Switch connection for opened file #814
### 5.2.9
- FIXED: PostgresSQL doesn't show tables when connected #793 #805
- FIXED: MongoDB write operations fail #798 #802
- FIXED: Elecrron app logging losed most of log messages
- FIXED: Connection error with SSH tunnel
- ADDED: option to disable autoupgrades (with --disable-auto-upgrade)
- ADDED: Send error context to github gist
### 5.2.8
### Not released (5.2.8)
- FIXED: file menu save and save as not working
- FIXED: query editor on import/export screen overlaps with selector
- FIXED: Fixed inconsistencies in max/unmaximize window buttons
@@ -491,10 +25,6 @@ Builds:
- ADDED: Add copy name to table list
- FIXED: Make TabControl scrollable (#730)
- ADDED: Add copy to column list
- FIXED: Problems with SQLite + glibc in docker containers
- ADDED: Button for discard/reset changes (#759)
- FIXED: Don't show error dialog when subprocess fails, as DbGate handles this correctly (#751, #746, #542, #272)
### 5.2.7
- FIXED: fix body overflow when context menu height great than viewport #592
@@ -552,7 +82,7 @@ Builds:
- FIXED: Creating SQLite autoincrement column
- FIXED: Better error reporting from exports/import/dulicator
- CHANGED: Optimalizede OracleDB analysing algorithm
- ADDED: Multi column filter for perspectives
- ADDED: Mutli column filter for perspectives
- FIXED: Fixed some scenarios using tables from different DBs
- FIXED: Sessions with long-running queries are not killed
+21 -674
View File
@@ -1,674 +1,21 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
MIT License
Copyright (c) 2021 Jan Prochazka
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+15 -26
View File
@@ -12,32 +12,25 @@ DbGate is cross-platform database manager.
It's designed to be simple to use and effective, when working with more databases simultaneously.
But there are also many advanced features like schema compare, visual query designer, chart visualisation or batch export and import.
DbGate is licensed under GPL-3.0 license and is free to use for any purpose.
DbGate is licensed under MIT license and is completely free.
* Try it online - [demo.dbgate.org](https://demo.dbgate.org) - online demo application
* **Download** application for Windows, Linux or Mac from [dbgate.io](https://www.dbgate.io/download/)
* Looking for DbGate Community? **Download** from [dbgate.io](https://www.dbgate.io/download-community/)
* **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://docs.dbgate.io/scripting) ([API documentation](https://docs.dbgate.io/apidoc))
## Supported databases
* MySQL
* PostgreSQL
* SQL Server
* Oracle
* Oracle (experimental)
* MongoDB
* Redis
* SQLite
* Amazon Redshift (Premium)
* Amazon Redshift
* CockroachDB
* MariaDB
* CosmosDB (Premium)
* ClickHouse
* Apache Cassandra
* libSQL/Turso (Premium)
* DuckDB
* Firebird
* Firestore (Premium)
<!-- Learn more about DbGate features at the [DbGate website](https://dbgate.org/), or try our online [demo application](https://demo.dbgate.org) -->
<a href="https://raw.githubusercontent.com/dbgate/dbgate/master/img/screenshot1.png">
@@ -56,15 +49,13 @@ DbGate is licensed under GPL-3.0 license and is free to use for any purpose.
<!-- ![Screenshot](https://raw.githubusercontent.com/dbgate/dbgate/master/screenshot.png) -->
## Features
* Browse table data with many filtering options, Excel-like filters, multi-value filters
* Table data editing, with SQL change script preview
* Edit table schema, indexes, primary and foreign keys
* Compare and synchronize database structure
* ER diagram
* Light and dark theme, next themes available as plugins from github community
* Huge support for work with related data - master/detail views, foreign key lookups, expanding columns from related tables in flat data view
* Query designer - visual SQL query builder without writing SQL code. Complex conditions like WHERE NOT EXISTS.
* Query perspectives innovative nested table view over complex relational data, something like query designer on MongoDB databases
* Light and dark theme
* Master/detail views, foreign key lookups
* Query designer
* Form view for comfortable work with tables with many columns
* JSON view on MongoDB collections
* Explore tables, views, procedures, functions, MongoDB collections
@@ -76,25 +67,23 @@ DbGate is licensed under GPL-3.0 license and is free to use for any purpose.
* Mongo JavaScript editor, execute Mongo script (with NodeJs syntax)
* Redis tree view, generate script from keys, run Redis script
* Runs as application for Windows, Linux and Mac. Or in Docker container on server and in web Browser on client.
* Import, export from/to CSV, Excel, JSON, NDJSON, XML, DBF
* Import, export from/to CSV, Excel, JSON, NDJSON, XML
* Free table editor - quick table data editing (cleanup data after import/before export, prototype tables etc.)
* Archives - backup your data in NDJSON files on local filesystem (or on DbGate server, when using web application)
* NDJSON data viewer and editor - browse NDJSON data, edit data and structure directly on NDJSON files. Works also for big NDSON files
* Charts, export chart to HTML page
* AI powered database chat
* Show GEO data on map, export map to HTML page
* For detailed info, how to run DbGate in docker container, visit [docker hub](https://hub.docker.com/r/dbgate/dbgate)
* Extensible plugin architecture
* Perspectives - nested table view over complex relational data, query designer on MongoDB databases
## How to contribute
Any contributions are welcome. If you want to contribute without coding, consider following:
* Tell your friends about DbGate or share on social networks - when more people will use DbGate, it will grow to be better
* Purchase a [DbGate Premium](https://www.dbgate.io/purchase/premium/) license
* Write review on [Slant.co](https://www.slant.co/improve/options/41086/~dbgate-review) or [G2](https://www.g2.com/products/dbgate/reviews)
* 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)
* Add a SQL script to [Public Knowledge Base](https://github.com/dbgate/dbgate-knowledge-base)
* Where a small coding is acceptable for you, you could [create plugin](https://docs.dbgate.io/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!
@@ -189,4 +178,4 @@ yarn plugin # this compiles plugin and copies it into existing DbGate installati
After restarting DbGate, you could use your new plugin from DbGate.
## Logging
DbGate uses [pinomin logger](https://github.com/dbgate/pinomin). So by default, it produces JSON log messages into console and log files. If you want to see formatted logs, please use [pino-pretty](https://github.com/pinojs/pino-pretty) log formatter.
DbGate uses [pinomin logger](https://github.com/dbgate/pinomin). So by default, it produces JSON log messages into console and log files. If you want to see formatted logs, please use [pino-pretty](https://github.com/pinojs/pino-pretty) log formatter.
+4 -64
View File
@@ -1,75 +1,15 @@
const fs = require('fs');
const path = require('path');
const volatilePackages = require('./common/volatilePackages');
function adjustFile(file, isApp = false) {
function adjustFile(file) {
const json = JSON.parse(fs.readFileSync(file, { encoding: 'utf-8' }));
function processPackageFile(packageFile) {
const pluginJson = JSON.parse(fs.readFileSync(packageFile, { encoding: 'utf-8' }));
for (const depkey of ['dependencies', 'optionalDependencies']) {
for (const dependency of Object.keys(pluginJson[depkey] || {})) {
if (!volatilePackages.includes(dependency)) {
// add only voletile packages
continue;
}
if (!json[depkey]) {
json[depkey] = {};
}
if (json[depkey][dependency]) {
if (json[depkey][dependency] != pluginJson[depkey][dependency]) {
console.log(`Dependency ${dependency} in ${packageName} is different from ${file}`);
}
continue;
}
json[depkey][dependency] = pluginJson[depkey][dependency];
}
}
}
for (const packageName of fs.readdirSync('plugins')) {
if (!packageName.startsWith('dbgate-plugin-')) continue;
processPackageFile(path.join('plugins', packageName, 'package.json'));
}
if (isApp) {
// add volatile dependencies from api to app
processPackageFile(path.join('packages', 'api', 'package.json'));
}
if (process.platform != 'win32') {
delete json.optionalDependencies.msnodesqlv8;
}
if (process.argv.includes('--community')) {
delete json.optionalDependencies['mongodb-client-encryption'];
delete json.dependencies['@mongosh/service-provider-node-driver'];
delete json.dependencies['@mongosh/browser-runtime-electron'];
if (process.arch == 'arm64') {
delete json.optionalDependencies.oracledb;
}
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');
}
adjustFile('packages/api/package.json');
adjustFile('app/package.json', true);
fs.writeFileSync('common/useBundleExternals.js', "module.exports = 'true';", 'utf-8');
adjustFile('app/package.json');
+21 -674
View File
@@ -1,674 +1,21 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
MIT License
Copyright (c) 2021 Jan Prochazka
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 192 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 57 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 89 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 12 KiB

-39
View File
@@ -1,39 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>org.dbgate.DbGate</id>
<name>DbGate</name>
<summary>(no)SQL database client</summary>
<metadata_license>CC0-1.0</metadata_license>
<project_license>MIT</project_license>
<developer_name>Jan Prochazka</developer_name>
<description>
<p>DbGate is cross-platform database manager. It's designed to be simple to use and effective, when working with more databases simultaneously. But there are also many advanced features like schema compare, visual query designer, chart visualisation or batch export and import.</p>
</description>
<url type="homepage">https://dbgate.org/</url>
<url type="vcs-browser">https://github.com/dbgate/dbgate</url>
<url type="contact">https://dbgate.org/about/</url>
<url type="donation">https://github.com/sponsors/dbgate</url>
<url type="bugtracker">https://github.com/dbgate/dbgate/issues</url>
<launchable type="desktop-id">org.dbgate.DbGate.desktop</launchable>
<screenshots>
<screenshot type="default">
<image>
https://github.com/dbgate/dbgate/raw/c2abc83f994a56945c27fccea3df84b48005961f/img/screenshot1.png</image>
</screenshot>
<screenshot>
<image>
https://github.com/dbgate/dbgate/raw/c2abc83f994a56945c27fccea3df84b48005961f/img/screenshot2.png</image>
</screenshot>
</screenshots>
<content_rating type="oars-1.1"/>
<releases>
<release version="5.2.7" date="2024-05-13"/>
</releases>
</component>
+26 -28
View File
@@ -1,13 +1,12 @@
{
"name": "dbgate",
"version": "6.0.0-alpha.1",
"version": "5.0.0-alpha.1",
"private": true,
"author": "Jan Prochazka <jenasoft.database@gmail.com>",
"description": "Opensource database administration tool",
"dependencies": {
"electron-log": "^4.4.1",
"electron-updater": "^6.3.4",
"jsonwebtoken": "^9.0.2",
"electron-updater": "^4.6.1",
"lodash.clonedeepwith": "^4.5.0",
"patch-package": "^6.4.7"
},
@@ -19,6 +18,7 @@
"artifactName": "dbgate-${version}-${os}_${arch}.${ext}",
"appId": "org.dbgate",
"productName": "DbGate",
"afterSign": "electron-builder-notarize",
"asarUnpack": "**/*.node",
"mac": {
"category": "database",
@@ -27,21 +27,15 @@
"entitlements": "entitlements.mac.plist",
"entitlementsInherit": "entitlements.mac.plist",
"publish": [
{
"provider": "github",
"owner": "dbgate",
"repo": "dbgate"
}
"github"
],
"target": {
"target": "default",
"arch": [
"universal",
"x64",
"arm64"
"x64"
]
},
"notarize": true
}
},
"linux": {
"target": [
@@ -51,6 +45,7 @@
"target": "AppImage",
"arch": [
"x64",
"armv7l",
"arm64"
]
},
@@ -60,11 +55,7 @@
"category": "Development",
"synopsis": "Database manager for SQL Server, MySQL, PostgreSQL, MongoDB and SQLite",
"publish": [
{
"provider": "github",
"owner": "dbgate",
"repo": "dbgate"
}
"github"
]
},
"appImage": {
@@ -80,6 +71,11 @@
"ELECTRON_SNAP": "true"
}
},
"flatpak": {
"license": "LICENSE",
"runtimeVersion": "23.08",
"baseVersion": "23.08"
},
"win": {
"target": [
{
@@ -99,25 +95,21 @@
],
"icon": "icon.ico",
"publish": [
{
"provider": "github",
"owner": "dbgate",
"repo": "dbgate"
}
]
"github"
],
"rfc3161TimeStampServer": "http://sha256timestamp.ws.symantec.com/sha256/timestamp"
},
"files": [
"packages",
"src",
"icon.png",
"!node_modules/cpu-features/build/**"
"icon.png"
]
},
"homepage": "./",
"scripts": {
"start": "cross-env ELECTRON_START_URL=http://localhost:5001 DEVMODE=1 electron .",
"start:local": "cross-env electron .",
"dist": "electron-builder --publish never",
"dist": "cross-env DEBUG=@malept/flatpak-bundler electron-builder",
"build": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && yarn dist",
"build:local": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && yarn predist",
"postinstall": "yarn rebuild && patch-package",
@@ -128,7 +120,13 @@
"devDependencies": {
"copyfiles": "^2.2.0",
"cross-env": "^6.0.3",
"electron": "38.6.0",
"electron-builder": "25.1.8"
"electron": "30.0.2",
"electron-builder": "23.1.0",
"electron-builder-notarize": "^1.5.2"
},
"optionalDependencies": {
"better-sqlite3": "9.6.0",
"msnodesqlv8": "^4.2.1",
"oracledb": "^5.5.0"
}
}
+33 -201
View File
@@ -16,34 +16,16 @@ const BrowserWindow = electron.BrowserWindow;
const path = require('path');
const url = require('url');
const mainMenuDefinition = require('./mainMenuDefinition');
const { isProApp } = require('./proTools');
const updaterChannel = require('./updaterChannel');
const { settings } = require('cluster');
// require('@electron/remote/main').initialize();
const configRootPath = path.join(app.getPath('userData'), 'config-root.json');
let saveConfigOnExit = true;
let initialConfig = {};
let apiLoaded = false;
let mainModule;
// let getLogger;
// let loadLogsContent;
let appUpdateStatus = '';
let settingsJson = {};
function getTranslated(key) {
if (typeof key === 'string' && global.TRANSLATION_DATA?.[key]) {
return global.TRANSLATION_DATA?.[key];
}
if (typeof key?._transKey === 'string') {
return global.TRANSLATION_DATA?.[key._transKey] ?? key._transOptions?.defaultMessage;
}
return key;
}
process.on('uncaughtException', function (error) {
console.error('uncaughtException', error);
});
const isMac = () => os.platform() == 'darwin';
@@ -73,14 +55,9 @@ try {
let mainWindow;
let mainMenu;
let runCommandOnLoad = null;
let mainWindowMenuSet = false;
log.transports.file.level = 'debug';
autoUpdater.logger = log;
if (updaterChannel) {
autoUpdater.channel = updaterChannel;
autoUpdater.allowPrerelease = updaterChannel.includes('beta');
}
// TODO - create settings for this
// appUpdater.channel = 'beta';
@@ -96,22 +73,17 @@ function formatKeyText(keyText) {
return keyText.replace('CtrlOrCommand+', 'Ctrl+');
}
function commandItem(item, disableAll = false) {
function commandItem(item) {
const id = item.command;
const command = commands[id];
if (item.skipInApp) {
return { skip: true };
}
if (!command) {
return { skip: true };
}
return {
id,
label: command
? getTranslated(command.menuName) || getTranslated(command.toolbarName) || getTranslated(command.name)
: id,
label: command ? command.menuName || command.toolbarName || command.name : id,
accelerator: formatKeyText(command ? command.keyText : undefined),
enabled: command ? command.enabled && (!disableAll || command.systemCommand) : false,
enabled: command ? command.enabled : false,
click() {
if (mainWindow) {
mainWindow.webContents.send('run-command', id);
@@ -123,14 +95,14 @@ function commandItem(item, disableAll = false) {
};
}
function buildMenu(disableAll = false) {
let template = _cloneDeepWith(mainMenuDefinition({ editMenu: true, isMac: isMac() }), item => {
function buildMenu() {
let template = _cloneDeepWith(mainMenuDefinition({ editMenu: true }), item => {
if (item.divider) {
return { type: 'separator' };
}
if (item.command) {
return commandItem(item, disableAll);
return commandItem(item);
}
});
@@ -145,7 +117,7 @@ function buildMenu(disableAll = false) {
{
label: 'DbGate',
submenu: [
commandItem({ command: 'about.show' }, disableAll),
commandItem({ command: 'about.show' }),
{ role: 'services' },
{ role: 'hide' },
{ role: 'hideOthers' },
@@ -161,28 +133,22 @@ function buildMenu(disableAll = false) {
}
ipcMain.on('update-commands', async (event, arg) => {
const parsed = JSON.parse(arg);
commands = parsed.commands;
const isModalOpened = parsed.isModalOpened;
const dbgatePage = parsed.dbgatePage;
commands = JSON.parse(arg);
for (const key of Object.keys(commands)) {
const menu = mainMenu.getMenuItemById(key);
if (!menu) continue;
const command = commands[key];
// rebuild menu
if (global.TRANSLATION_DATA && (menu.label != command.text || menu.accelerator != command.keyText)) {
mainMenu = buildMenu(isModalOpened || !!dbgatePage);
if (menu.label != command.text || menu.accelerator != command.keyText) {
mainMenu = buildMenu();
Menu.setApplicationMenu(mainMenu);
if (!mainWindowMenuSet) {
mainWindow.setMenu(mainMenu);
mainWindowMenuSet = true;
}
// mainWindow.setMenu(mainMenu);
return;
}
menu.enabled = command.enabled && !isModalOpened && !dbgatePage;
menu.enabled = command.enabled;
}
});
ipcMain.on('quit-app', async (event, arg) => {
@@ -192,21 +158,6 @@ ipcMain.on('quit-app', async (event, arg) => {
mainWindow.close();
}
});
ipcMain.on('reset-settings', async (event, arg) => {
try {
saveConfigOnExit = false;
fs.unlinkSync(configRootPath);
console.log('Deleted file:', configRootPath);
} catch (err) {
console.log('Error deleting config-root:', err.message);
}
if (isMac()) {
app.quit();
} else {
mainWindow.close();
}
});
ipcMain.on('set-title', async (event, arg) => {
mainWindow.setTitle(arg);
});
@@ -225,19 +176,6 @@ ipcMain.on('app-started', async (event, arg) => {
if (initialConfig['winIsMaximized']) {
mainWindow.webContents.send('setIsMaximized', true);
}
if (autoUpdater.isUpdaterActive()) {
mainWindow.webContents.send('setAppUpdaterActive');
}
if (!process.env.DEVMODE) {
if (settingsJson['app.autoUpdateMode'] != 'skip') {
autoUpdater.autoDownload = settingsJson['app.autoUpdateMode'] == 'download';
autoUpdater.checkForUpdates();
}
}
if (initialConfig['winZoomLevel'] != null) {
mainWindow.webContents.zoomLevel = initialConfig['winZoomLevel'];
}
});
ipcMain.on('window-action', async (event, arg) => {
if (!mainWindow) {
@@ -311,26 +249,6 @@ ipcMain.handle('showItemInFolder', async (event, path) => {
ipcMain.handle('openExternal', async (event, url) => {
electron.shell.openExternal(url);
});
ipcMain.on('downloadUpdate', async (event, url) => {
autoUpdater.downloadUpdate();
changeAppUpdateStatus({
icon: 'icon loading',
message: `Downloading update...`,
});
});
ipcMain.on('applyUpdate', async (event, url) => {
autoUpdater.quitAndInstall(false, true);
});
ipcMain.on('check-for-updates', async (event, url) => {
autoUpdater.autoDownload = false;
autoUpdater.checkForUpdates();
});
ipcMain.on('translation-data', async (event, arg) => {
global.TRANSLATION_DATA = JSON.parse(arg);
mainMenu = buildMenu();
Menu.setApplicationMenu(mainMenu);
mainWindow.setMenu(mainMenu);
});
function fillMissingSettings(value) {
const res = {
@@ -343,32 +261,10 @@ function fillMissingSettings(value) {
return res;
}
function ensureBoundsVisible(bounds) {
const area = electron.screen.getDisplayMatching(bounds).workArea;
let { x, y, width, height } = bounds;
const isWithinDisplay =
x >= area.x && x + width <= area.x + area.width && y >= area.y && y + height <= area.y + area.height;
if (!isWithinDisplay) {
width = Math.min(width, area.width);
height = Math.min(height, area.height);
if (width < 400) width = 400;
if (height < 300) height = 300;
x = area.x; // + Math.round(area.width - width / 2);
y = area.y; // + Math.round(area.height - height / 2);
}
return { x, y, width, height };
}
function createWindow() {
const datadir = path.join(os.homedir(), '.dbgate');
let settingsJson = {};
try {
const datadir = path.join(os.homedir(), '.dbgate');
settingsJson = fillMissingSettings(
JSON.parse(fs.readFileSync(path.join(datadir, 'settings.json'), { encoding: 'utf-8' }))
);
@@ -377,22 +273,18 @@ function createWindow() {
settingsJson = fillMissingSettings({});
}
let bounds = initialConfig['winBounds'];
if (bounds) {
bounds = ensureBoundsVisible(bounds);
}
const bounds = initialConfig['winBounds'];
useNativeMenu = settingsJson['app.useNativeMenu'];
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
title: isProApp() ? 'DbGate Premium' : 'DbGate',
title: 'DbGate',
frame: useNativeMenu,
titleBarStyle: useNativeMenu ? undefined : 'hidden',
backgroundColor: electron.nativeTheme.shouldUseDarkColors ? '#111111' : undefined,
...bounds,
icon: os.platform() == 'win32' ? 'icon.ico' : path.resolve(__dirname, '../icon.png'),
partition: isProApp() ? 'persist:dbgate-premium' : 'persist:dbgate',
partition: 'persist:dbgate',
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
@@ -407,8 +299,8 @@ function createWindow() {
mainWindow.setFullScreen(true);
}
// mainMenu = buildMenu();
// mainWindow.setMenu(mainMenu);
mainMenu = buildMenu();
mainWindow.setMenu(mainMenu);
function loadMainWindow() {
const startUrl =
@@ -420,28 +312,23 @@ function createWindow() {
});
mainWindow.on('close', () => {
try {
if (saveConfigOnExit) {
fs.writeFileSync(
configRootPath,
JSON.stringify({
winBounds: mainWindow.getBounds(),
winIsMaximized: mainWindow.isMaximized(),
winZoomLevel: mainWindow.webContents.zoomLevel,
}),
'utf-8'
);
}
fs.writeFileSync(
configRootPath,
JSON.stringify({
winBounds: mainWindow.getBounds(),
winIsMaximized: mainWindow.isMaximized(),
}),
'utf-8'
);
} catch (err) {
console.log('Error saving config-root:', err.message);
}
});
// mainWindow.webContents.toggleDevTools();
mainWindow.loadURL(startUrl);
if (os.platform() == 'linux') {
mainWindow.setIcon(path.resolve(__dirname, '../icon.png'));
}
// mainWindow.webContents.toggleDevTools();
mainWindow.on('maximize', () => {
mainWindow.webContents.send('setIsMaximized', true);
@@ -450,11 +337,6 @@ function createWindow() {
mainWindow.on('unmaximize', () => {
mainWindow.webContents.send('setIsMaximized', false);
});
// app.on('browser-window-focus', () => {
// const bounds = ensureBoundsVisible(mainWindow.getBounds());
// mainWindow.setBounds(bounds);
// });
}
if (!apiLoaded) {
@@ -464,6 +346,7 @@ function createWindow() {
);
global.API_PACKAGE = apiPackage;
global.NATIVE_MODULES = path.join(__dirname, 'nativeModules');
// console.log('global.API_PACKAGE', global.API_PACKAGE);
const api = require(apiPackage);
@@ -495,61 +378,10 @@ function createWindow() {
});
}
function changeAppUpdateStatus(status) {
appUpdateStatus = status;
mainWindow.webContents.send('app-update-status', appUpdateStatus);
}
autoUpdater.on('checking-for-update', () => {
console.log('Checking for updates');
changeAppUpdateStatus({
icon: 'icon loading',
message: 'Checking for updates...',
});
});
autoUpdater.on('update-available', info => {
console.log('Update available', info);
if (autoUpdater.autoDownload) {
changeAppUpdateStatus({
icon: 'icon loading',
message: `Downloading update...`,
});
} else {
mainWindow.webContents.send('update-available', info.version);
changeAppUpdateStatus({
icon: 'icon download',
message: `Update available`,
});
}
});
autoUpdater.on('update-not-available', info => {
console.log('Update not available', info);
changeAppUpdateStatus({
icon: 'icon check',
message: `No new updates`,
});
});
autoUpdater.on('update-downloaded', info => {
console.log('Update downloaded from', info);
changeAppUpdateStatus({
icon: 'icon download',
message: `Downloaded ${info.version}`,
});
mainWindow.webContents.send('downloaded-new-version', info.version);
});
autoUpdater.on('error', error => {
changeAppUpdateStatus({
icon: 'icon error',
message: `Autoupdate error`,
});
console.error('Update error', error);
});
function onAppReady() {
if (!process.env.DEVMODE) {
autoUpdater.checkForUpdatesAndNotify();
}
createWindow();
}
+21 -41
View File
@@ -1,23 +1,17 @@
function _t(key, { defaultMessage, currentTranslations } = {}) {
return (currentTranslations || global.TRANSLATION_DATA)?.[key] || defaultMessage;
}
module.exports = ({ editMenu, isMac }, currentTranslations = null) => [
module.exports = ({ editMenu }) => [
{
label: _t('menu.file', { defaultMessage: 'File', currentTranslations }),
label: 'File',
submenu: [
{ command: 'new.connection', hideDisabled: true },
{ command: 'new.sqliteDatabase', hideDisabled: true },
{ command: 'new.duckdbDatabase', hideDisabled: true },
{ divider: true },
{ command: 'new.query', hideDisabled: true },
{ command: 'new.queryDesign', hideDisabled: true },
{ command: 'new.diagram', hideDisabled: true },
{ command: 'new.perspective', hideDisabled: true },
{ command: 'new.application', hideDisabled: true },
{ command: 'new.freetable', hideDisabled: true },
{ command: 'new.shell', hideDisabled: true },
{ command: 'new.jsonl', hideDisabled: true },
{ command: 'new.modelTransform', hideDisabled: true },
{ divider: true },
{ command: 'file.open', hideDisabled: true },
{ command: 'file.openArchive', hideDisabled: true },
@@ -30,9 +24,23 @@ module.exports = ({ editMenu, isMac }, currentTranslations = null) => [
{ command: 'app.disconnect', hideDisabled: true, skipInApp: true },
],
},
{
label: 'Window',
submenu: [
{ command: 'tabs.closeTab', hideDisabled: false },
{ command: 'tabs.closeAll', hideDisabled: false },
{ command: 'tabs.closeTabsWithCurrentDb', hideDisabled: false },
{ command: 'tabs.closeTabsButCurrentDb', hideDisabled: false },
{ divider: true },
{ command: 'app.zoomIn', hideDisabled: true },
{ command: 'app.zoomOut', hideDisabled: true },
{ command: 'app.zoomReset', hideDisabled: true },
],
},
editMenu
? {
label: _t('menu.edit', { defaultMessage: 'Edit', currentTranslations }),
label: 'Edit',
submenu: [
{ command: 'edit.undo' },
{ command: 'edit.redo' },
@@ -57,7 +65,7 @@ module.exports = ({ editMenu, isMac }, currentTranslations = null) => [
// ],
// },
{
label: _t('menu.view', { defaultMessage: 'View', currentTranslations }),
label: 'View',
submenu: [
{ command: 'app.reload', hideDisabled: true },
{ command: 'app.toggleDevTools', hideDisabled: true },
@@ -67,21 +75,10 @@ module.exports = ({ editMenu, isMac }, currentTranslations = null) => [
{ divider: true },
{ command: 'theme.changeTheme', hideDisabled: true },
{ command: 'settings.show' },
{ divider: true },
{ command: 'tabs.closeTab', hideDisabled: false },
{ command: 'tabs.closeAll', hideDisabled: false },
{ command: 'tabs.closeTabsWithCurrentDb', hideDisabled: false },
{ command: 'tabs.closeTabsButCurrentDb', hideDisabled: false },
{ divider: true },
{ command: 'app.zoomIn', hideDisabled: true },
{ command: 'app.zoomOut', hideDisabled: true },
{ command: 'app.zoomReset', hideDisabled: true },
{ divider: true },
{ command: 'app.showLogs', hideDisabled: true },
],
},
{
label: _t('menu.tools', { defaultMessage: 'Tools', currentTranslations }),
label: 'Tools',
submenu: [
{ command: 'database.search', hideDisabled: true },
{ command: 'commandPalette.show', hideDisabled: true },
@@ -93,36 +90,19 @@ module.exports = ({ editMenu, isMac }, currentTranslations = null) => [
{ divider: true },
{ command: 'folder.showLogs', hideDisabled: true },
{ command: 'folder.showData', hideDisabled: true },
{ command: 'app.resetSettings', hideDisabled: true },
{ divider: true },
{ command: 'app.exportConnections', hideDisabled: true },
{ command: 'app.importConnections', hideDisabled: true },
{ divider: true },
{ command: 'app.managePlugins', hideDisabled: true },
],
},
...(isMac
? [
{
role: 'window',
submenu: [{ role: 'minimize' }, { role: 'zoom' }, { type: 'separator' }, { role: 'front' }],
},
]
: []),
{
label: _t('menu.help', { defaultMessage: 'Help', currentTranslations }),
label: 'Help',
submenu: [
{ command: 'app.openDocs', hideDisabled: true },
{ command: 'app.openWeb', hideDisabled: true },
{ command: 'app.openIssue', hideDisabled: true },
{ command: 'app.openSponsoring', hideDisabled: true },
// { command: 'app.giveFeedback', hideDisabled: true },
{ divider: true },
{ command: 'settings.commands', hideDisabled: true },
{ command: 'tabs.changelog', hideDisabled: true },
{ command: 'about.show', hideDisabled: true },
{ divider: true },
{ command: 'app.checkForUpdates', hideDisabled: true },
],
},
];
+3
View File
@@ -0,0 +1,3 @@
const content = require('./nativeModulesContent');
module.exports = content;
-12
View File
@@ -1,12 +0,0 @@
function isProApp() {
return false;
}
function checkLicense(license) {
return null;
}
module.exports = {
isProApp,
checkLicense,
};
-1
View File
@@ -1 +0,0 @@
module.exports = null;
+1159 -1110
View File
File diff suppressed because it is too large Load Diff
-129
View File
@@ -1,129 +0,0 @@
#!/usr/bin/env node
// assign-dbgm-codes.mjs
import fs from 'fs/promises';
import path from 'path';
const PLACEHOLDER = 'DBGM-00000';
const CODE_RE = /DBGM-(\d{5})/g;
const JS_TS_RE = /\.(mjs|cjs|js|ts|jsx|tsx)$/i;
const IGNORE_DIRS = new Set([
'node_modules',
'.git',
'.hg',
'.svn',
'dist',
'build',
'out',
'.next',
'.turbo',
'.cache',
]);
const IGNORE_FILES = ['assign-dbgm-codes.mjs', 'package.json', 'README.md'];
// --- CLI ---
const args = process.argv.slice(2);
const dryRun = args.includes('--dry');
const rootArg = args.find(a => a !== '--dry') || process.cwd();
const root = path.resolve(rootArg);
// --- helpers ---
async function* walk(dir) {
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const e of entries) {
if (e.isDirectory()) {
if (IGNORE_DIRS.has(e.name)) continue;
yield* walk(path.join(dir, e.name));
} else if (e.isFile()) {
if (JS_TS_RE.test(e.name) && !IGNORE_FILES.includes(e.name)) yield path.join(dir, e.name);
}
}
}
function formatCode(n) {
return `DBGM-${String(n).padStart(5, '0')}`;
}
// Find the smallest positive integer not in `taken`
function makeNextCodeFn(taken) {
let n = 1;
// advance n to first free
while (taken.has(n)) n++;
return () => {
const code = n;
taken.add(code);
// move n to next free for next call
do {
n++;
} while (taken.has(n));
return formatCode(code);
};
}
// --- main ---
(async () => {
console.log(`Scanning: ${root} ${dryRun ? '(dry run)' : ''}`);
// 1) Collect all taken codes across the repo
const taken = new Set(); // numeric parts only
const files = [];
for await (const file of walk(root)) files.push(file);
await Promise.all(
files.map(async file => {
try {
const text = await fs.readFile(file, 'utf8');
for (const m of text.matchAll(CODE_RE)) {
const num = Number(m[1]);
if (Number.isInteger(num) && num > 0) taken.add(num);
}
} catch (err) {
console.warn(`! Failed to read ${file}: ${err.message}`);
}
})
);
console.log(`Found ${taken.size} occupied code(s).`);
// 2) Replace placeholders with next available unique code
const nextCode = makeNextCodeFn(taken);
let filesChanged = 0;
let placeholdersReplaced = 0;
for (const file of files) {
let text;
try {
text = await fs.readFile(file, 'utf8');
} catch (err) {
console.warn(`! Failed to read ${file}: ${err.message}`);
continue;
}
if (!text.includes(PLACEHOLDER)) continue;
let countInFile = 0;
const updated = text.replaceAll(PLACEHOLDER, () => {
countInFile++;
return nextCode();
});
if (countInFile > 0) {
placeholdersReplaced += countInFile;
filesChanged++;
console.log(`${dryRun ? '[dry]' : '[write]'} ${file}${countInFile} replacement(s)`);
if (!dryRun) {
try {
await fs.writeFile(file, updated, 'utf8');
} catch (err) {
console.warn(`! Failed to write ${file}: ${err.message}`);
}
}
}
}
console.log(`Done. Files changed: ${filesChanged}, placeholders replaced: ${placeholdersReplaced}.`);
})().catch(err => {
console.error(err);
process.exit(1);
});
-19
View File
@@ -1,19 +0,0 @@
const useBundleExternals = require('./useBundleExternals');
const getBundleExternals = require('./getBundleExternals');
function buildExternalsFromDependencies(packageJson) {
if (useBundleExternals == 'true') {
return getBundleExternals();
}
const { dependencies, optionalDependencies } = packageJson;
const externals = {};
for (let dep in dependencies || {}) {
externals[dep] = `commonjs ${dep}`;
}
for (let dep in optionalDependencies || {}) {
externals[dep] = `commonjs ${dep}`;
}
return externals;
}
module.exports = buildExternalsFromDependencies;
-33
View File
@@ -1,33 +0,0 @@
const directory = process.argv[2];
const fs = require('fs');
const volatilePackages = require('./volatilePackages');
const apiPackageJson = JSON.parse(fs.readFileSync(`packages/api/package.json`, { encoding: 'utf-8' }));
const dependencies = {};
const optionalDependencies = {};
for (const pkg of volatilePackages) {
if (pkg == 'msnodesqlv8' && process.platform != 'win32') {
continue;
}
if (apiPackageJson.dependencies[pkg]) {
dependencies[pkg] = apiPackageJson.dependencies[pkg];
}
if (apiPackageJson.optionalDependencies?.[pkg]) {
optionalDependencies[pkg] = apiPackageJson.optionalDependencies[pkg];
}
}
fs.writeFileSync(
`${directory}/package.json`,
JSON.stringify(
{
dependencies,
optionalDependencies,
},
null,
2
),
'utf-8'
);
-110
View File
@@ -1,110 +0,0 @@
import fs from 'node:fs/promises';
import { createHash } from 'node:crypto';
import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import YAML from 'yaml';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
async function sha512Base64(filePath) {
const buf = await fs.readFile(filePath);
const h = createHash('sha512');
h.update(buf);
return h.digest('base64');
}
async function fileSize(filePath) {
const st = await fs.stat(filePath);
return st.size;
}
async function fixOneYaml(ymlPath, distDir) {
let raw;
try {
raw = await fs.readFile(ymlPath, 'utf8');
} catch (e) {
console.error(`✗ Cannot read ${ymlPath}:`, e.message);
return;
}
let doc;
try {
doc = YAML.parse(raw);
} catch (e) {
console.error(`✗ Cannot parse YAML ${ymlPath}:`, e.message);
return;
}
if (!doc || !Array.isArray(doc.files)) {
console.warn(`! ${path.basename(ymlPath)} has no 'files' array — skipped.`);
return;
}
let changed = false;
// Update each files[i].sha512 and files[i].size based on files[i].url
for (const entry of doc.files) {
if (!entry?.url) continue;
const target = path.resolve(distDir, entry.url);
try {
const [hash, size] = await Promise.all([sha512Base64(target), fileSize(target)]);
if (entry.sha512 !== hash || entry.size !== size) {
console.log(`${path.basename(ymlPath)}: refresh ${entry.url}`);
entry.sha512 = hash;
entry.size = size;
changed = true;
}
} catch (e) {
console.warn(
`! Missing or unreadable file for ${entry.url} (referenced by ${path.basename(ymlPath)}): ${e.message}`
);
}
}
// Update top-level sha512 for the primary "path" file if present
if (doc.path) {
const primary = path.resolve(distDir, doc.path);
try {
const hash = await sha512Base64(primary);
if (doc.sha512 !== hash) {
console.log(`${path.basename(ymlPath)}: refresh top-level sha512 for path=${doc.path}`);
doc.sha512 = hash;
changed = true;
}
} catch (e) {
console.warn(`! Primary 'path' file not found for ${path.basename(ymlPath)}: ${doc.path} (${e.message})`);
}
}
if (changed) {
const out = YAML.stringify(doc);
await fs.writeFile(ymlPath, out, 'utf8');
console.log(`✓ Updated ${path.basename(ymlPath)}`);
} else {
console.log(`= No changes for ${path.basename(ymlPath)}`);
}
}
async function main() {
const distDir = path.resolve(process.argv[2] ?? path.join(__dirname, '..', 'app', 'dist'));
const entries = await fs.readdir(distDir);
const ymls = entries.filter(f => f.toLowerCase().endsWith('.yml'));
if (ymls.length === 0) {
console.warn(`No .yml files found in ${distDir}`);
return;
}
console.log(`Scanning ${distDir}`);
for (const y of ymls) {
await fixOneYaml(path.join(distDir, y), distDir);
}
}
main().catch(err => {
console.error(err);
process.exit(1);
});
-10
View File
@@ -1,10 +0,0 @@
const volatilePackages = require('./volatilePackages');
function getBundleExternals() {
return volatilePackages.reduce((acc, item) => {
acc[item] = `commonjs ${item}`;
return acc;
}, {});
}
module.exports = getBundleExternals;
-174
View File
@@ -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();
-43
View File
@@ -1,43 +0,0 @@
//@ts-check
const { getDefaultTranslations, getLanguageTranslations } = require('./helpers');
/**
* @param {string} language
*/
function getMissingTranslations(language) {
const source = getDefaultTranslations();
/** @type {Record<string, string>} */
let target;
try {
target = getLanguageTranslations(language);
} catch {
console.log(`Language ${language} not found, creating a new one`);
target = {};
}
let added = 0;
let removed = 0;
for (const key in source) {
if (!target[key]) {
target[key] = `*** ${source[key]}`;
added++;
}
}
for (const key in target) {
if (!source[key]) {
delete target[key];
removed++;
}
}
const newLength = Object.keys(target).length;
return { result: target, stats: { added, removed, newLength } };
}
module.exports = {
getMissingTranslations,
};
-16
View File
@@ -1,16 +0,0 @@
// @ts-check
//
const defaultLanguage = 'en';
/** @typedef {{ extensions: string[], directories: string[] }} ExtractConfig
/** @type {ExtractConfig} */
const defaultExtractConfig = {
extensions: ['.js', '.ts', '.svelte'],
directories: ['app', 'packages/web'],
};
module.exports = {
defaultLanguage,
defaultExtractConfig,
};
-85
View File
@@ -1,85 +0,0 @@
//@ts-check
const fs = require('fs');
const { promisify } = require('util');
const { getFiles } = require('./helpers');
const readFilePromise = promisify(fs.readFile);
const translationRegex = /_t\(\s*['"]([^'"]+)['"]\s*,\s*\{\s*defaultMessage\s*:\s*(?:'([^'\\]*(?:\\.[^'\\]*)*)'|"([^"\\]*(?:\\.[^"\\]*)*)"|\`([^`\\]*(?:\\.[^`\\]*)*(?:\{[^}]*\}[^`\\]*(?:\\.[^`\\]*)*)*)\`)(?:\s*,\s*[^}]*)*\s*\}/g;
/**
* @param {string} file
*
* @returns {Promise<Record<string, string>>}
*/
async function extractTranslationsFromFile(file) {
/** @type {Record<string, string>} */
const translations = {};
const content = await readFilePromise(file, 'utf-8');
let match;
while ((match = translationRegex.exec(content)) !== null) {
const [_, key, singleQuotedText, doubleQuotedText, templateLiteral] = match;
const defaultText = singleQuotedText || doubleQuotedText || templateLiteral;
translations[key] = defaultText;
}
return translations;
}
/** @typedef {{ ignoreDuplicates?: boolean }} ExtractOptions */
/**
* @param {string[]} directories
* @param {string[]} extensions
* @param {ExtractOptions} options
*
* @returns {Promise<Record<string, string>>}
*/
async function extractAllTranslations(directories, extensions, options = {}) {
const { ignoreDuplicates } = options;
try {
/** @type {Record<string, string>} */
const allTranslations = {};
/** @type {Record<string, string[]>} */
const translationKeyToFiles = {};
for (const dir of directories) {
const files = await getFiles(dir, extensions);
for (const file of files) {
const fileTranslations = await extractTranslationsFromFile(file);
for (const key in fileTranslations) {
if (!translationKeyToFiles[key]) {
translationKeyToFiles[key] = [];
}
translationKeyToFiles[key].push(file);
if (!ignoreDuplicates && allTranslations[key] && allTranslations[key] !== fileTranslations[key]) {
console.error(
`Different translations for the same key [${key}] found. ${file}: ${
fileTranslations[key]
}. Previous value: ${allTranslations[key]} was found in ${translationKeyToFiles[key].join(', ')}`
);
throw new Error(`Duplicate translation key found: ${key}`);
}
allTranslations[key] = fileTranslations[key];
}
}
}
return allTranslations;
} catch (error) {
console.error('Error extracting translations:', error);
throw error;
}
}
module.exports = {
extractTranslationsFromFile,
extractAllTranslations,
};
-198
View File
@@ -1,198 +0,0 @@
//@ts-check
const path = require('path');
const fs = require('fs');
const { defaultLanguage } = require('./constants');
const sortJsonKeysAlphabetically = require('./sortJsonKeysAlphabetically');
/**
* @param {string} file
* @param {string[]} extensions
*
* @returns {boolean}
*/
function hasValidExtension(file, extensions) {
return extensions.includes(path.extname(file).toLowerCase());
}
/**
* @param {string} dir
* @param {string[]} extensions
*
* @returns {Promise<string[]>}
*/
async function getFiles(dir, extensions) {
const files = await fs.promises.readdir(dir);
const allFiles = await Promise.all(
files.map(async file => {
const filePath = path.join(dir, file);
const stats = await fs.promises.stat(filePath);
if (stats.isDirectory()) {
return getFiles(filePath, extensions);
} else if (stats.isFile() && hasValidExtension(file, extensions)) {
const slashPath = filePath.replace(/\\/g, '/');
if (slashPath.includes('/node_modules/') || slashPath.includes('/build/') || slashPath.includes('/dist/')) {
return null;
}
return filePath;
}
return null;
})
);
const validFiles = /** @type {string[]} */ (allFiles.flat().filter(file => file !== null));
return validFiles;
}
/**
* @param {string | string[]} value
*
* @returns {string}
*/
function formatDefaultValue(value) {
if (Array.isArray(value)) {
return value.join(', ');
}
return value;
}
const scriptDir = getScriptDir();
/** @param {string} file
*
* @returns {string}
*/
function resolveFile(file) {
if (path.isAbsolute(file)) {
return file;
}
return path.resolve(scriptDir, '..', '..', file);
}
/** @param {string[]} dirs
*
* @returns {string[]}
*/
function resolveDirs(dirs) {
return dirs.map(resolveFile);
}
/**
* @param {string[]} extensions
*
* @returns {string[]}
*/
function resolveExtensions(extensions) {
return extensions.map(ext => (ext.startsWith('.') ? ext : `.${ext}`));
}
function getScriptDir() {
if (require.main?.filename) {
return path.dirname(require.main.filename);
}
if ('pkg' in process && process.pkg) {
return path.dirname(process.execPath);
}
return __dirname;
}
/**
* @param {string} file
*/
function ensureFileDirExists(file) {
const dir = path.dirname(file);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
}
/**
* @param {Record<string, string>} existingTranslations - Previously extracted translations
* @param {Record<string, string>} newTranslations - Newly extracted translations
* @returns {{ added: string[], removed: string[], updated: string[] }} Translation changes
*/
const getTranslationChanges = (existingTranslations, newTranslations) => {
const existingKeys = new Set(Object.keys(existingTranslations || {}));
const newKeys = new Set(Object.keys(newTranslations));
const added = [...newKeys].filter(key => !existingKeys.has(key));
const removed = [...existingKeys].filter(key => !newKeys.has(key));
const updated = [...newKeys].filter(
key => existingKeys.has(key) && existingTranslations[key] !== newTranslations[key]
);
return { added, removed, updated };
};
function getDefaultTranslations() {
return getLanguageTranslations(defaultLanguage);
}
/**
* @param {string} language
*
* @returns {Record<string, string>}
*/
function getLanguageTranslations(language) {
const file = resolveFile(`translations/${language}.json`);
const content = fs.readFileSync(file, 'utf-8');
return JSON.parse(content);
}
/**
* @param {string} language
* @param {Record<string, string>} translations
*/
function setLanguageTranslations(language, translations) {
const file = resolveFile(`translations/${language}.json`);
const sorted = sortJsonKeysAlphabetically(translations);
fs.writeFileSync(file, JSON.stringify(sorted, null, 2));
}
/**
* @param {string} language
* @param {Record<string, string>} newTranslations
*/
function updateLanguageTranslations(language, newTranslations) {
const translations = getLanguageTranslations(language);
const updatedTranslations = { ...translations, ...newTranslations };
const sorted = sortJsonKeysAlphabetically(updatedTranslations);
setLanguageTranslations(language, sorted);
}
function getAllLanguages() {
const dir = resolveFile('translations');
const files = fs.readdirSync(dir);
const languages = files.filter(file => file.endsWith('.json')).map(file => file.replace('.json', ''));
return languages;
}
function getAllNonDefaultLanguages() {
return getAllLanguages().filter(language => language !== defaultLanguage);
}
module.exports = {
hasValidExtension,
getFiles,
formatDefaultValue,
resolveFile,
resolveDirs,
resolveExtensions,
ensureFileDirExists,
getTranslationChanges,
getDefaultTranslations,
getLanguageTranslations,
setLanguageTranslations,
updateLanguageTranslations,
getAllLanguages,
getAllNonDefaultLanguages,
};
-3
View File
@@ -1,3 +0,0 @@
const { program } = require('./program');
program.parse();
-190
View File
@@ -1,190 +0,0 @@
//@ts-check
const fs = require('fs');
const { program } = require('commander');
const {
resolveDirs,
resolveExtensions,
getTranslationChanges,
setLanguageTranslations,
getAllNonDefaultLanguages,
updateLanguageTranslations,
getDefaultTranslations,
} = require('./helpers');
const { extractAllTranslations } = require('./extract');
const { getMissingTranslations } = require('./addMissing');
const { defaultLanguage, defaultExtractConfig } = require('./constants');
const { removeUnusedAllTranslations, removeUnusedForSignelLanguage } = require('./removeUnused');
/**
* @typedef {import('./constants').ExtractConfig & { verbose?: boolean, ignoreUnused?: boolean }} ExtractOptions
*/
program.name('dbgate-translations-cli').description('CLI tool for managing translation').version('1.0.0');
program
.command('extract')
.description('Extract translation keys from source files')
.option('-d, --directories <directories...>', 'directories to search', defaultExtractConfig.directories)
.option('-e, --extensions <extensions...>', 'file extensions to process', defaultExtractConfig.extensions)
.option('-r, --ignoreUnused', 'Ignore unused keys in the output file')
.option('-v, --verbose', 'verbose mode')
.action(async (/** @type {ExtractOptions} */ options) => {
try {
const { directories, extensions, verbose, ignoreUnused } = options;
const resolvedRirectories = resolveDirs(directories);
const resolvedExtensions = resolveExtensions(extensions);
const extractedTranslations = await extractAllTranslations(resolvedRirectories, resolvedExtensions);
const defaultTranslations = getDefaultTranslations();
const { added, removed, updated } = getTranslationChanges(defaultTranslations, extractedTranslations);
console.log('\nTranslation changes:');
console.log(`- Added: ${added.length} keys`);
console.log(`- ${ignoreUnused ? 'Unused' : 'Removed'}: ${removed.length} keys`);
console.log(`- Updated: ${updated.length} keys`);
console.log(`- Total: ${Object.keys(extractedTranslations).length} keys`);
if (verbose) {
if (added.length > 0) {
console.log('\nNew keys:');
added.forEach(key => console.log(` + ${key}`));
}
if (removed.length > 0) {
console.log('\nRemoved keys:');
removed.forEach(key => console.log(` - ${key}`));
}
if (updated.length > 0) {
console.log('\nUpdated keys:');
updated.forEach(key => {
console.log(` ~ ${key}`);
console.log(` Old: ${defaultLanguage[key]}`);
console.log(` New: ${extractedTranslations[key]}`);
});
}
}
if (ignoreUnused) {
console.log('New translations were saved. Unused keys are kept.\n');
updateLanguageTranslations(defaultLanguage, extractedTranslations);
if (verbose) {
console.log('\nUnused keys:');
for (const key of removed) {
console.log(`${key}: "${defaultTranslations[key]}"`);
}
}
} else {
console.log('Unused keys were removed.\n');
setLanguageTranslations(defaultLanguage, extractedTranslations);
}
} catch (error) {
console.error(error);
console.error('Error during extraction:', error.message);
process.exit(1);
}
});
const ALL_LANGUAGES = 'all';
/**
* @param {string} target
*/
function addMissingTranslations(target) {
console.log(`Adding missing keys for language: ${target}`);
const { result, stats } = getMissingTranslations(target);
console.log(`Added: ${stats.added}, Removed: ${stats.removed}, Total: ${stats.newLength}`);
setLanguageTranslations(target, result);
console.log(`New translations for ${target} were saved.`);
}
program
.command('add-missing')
.description('Add missing keys for a langauge to the translation file')
.option('-t, --target <target>', 'language to add missing translations to', ALL_LANGUAGES)
.action(options => {
try {
const { target } = options;
const languages = getAllNonDefaultLanguages();
if (target === ALL_LANGUAGES) {
console.log('Adding missing keys for all languages\n');
for (const language of languages) {
addMissingTranslations(language);
console.log();
}
} else {
addMissingTranslations(target);
}
} catch (error) {
console.error(error);
console.error('Error during add-missing:', error.message);
process.exit(1);
}
});
program
.command('remove-unused')
.description('Remove unused keys from the translation files')
.option('-t, --target <target>', 'language to add missing translations to', ALL_LANGUAGES)
.action(async options => {
try {
const { target } = options;
if (target === ALL_LANGUAGES) {
console.log('Removing unused keys from all languages\n');
await removeUnusedAllTranslations();
} else {
await removeUnusedForSignelLanguage(target);
}
} catch (error) {
console.error(error);
console.error('Error during add-missing:', error.message);
process.exit(1);
}
});
program
.command('check')
.description('Check if there are multiple default values for the same key')
.action(async () => {
try {
await extractAllTranslations(defaultExtractConfig.directories, defaultExtractConfig.extensions);
console.log('No problems found while extracting translations.');
} catch (error) {
console.error(error);
console.error('Error during check:', error.message);
process.exit(1);
}
});
program
.command('sort')
.description('Sort translation files by keys')
.action(() => {
try {
const languages = getAllNonDefaultLanguages();
for (const language of languages) {
const filePath = `./translations/${language}.json`;
const content = fs.readFileSync(filePath, 'utf-8');
const translations = JSON.parse(content);
const sortedTranslations = {};
Object.keys(translations)
.sort()
.forEach(key => {
// @ts-ignore
sortedTranslations[key] = translations[key];
});
fs.writeFileSync(filePath, JSON.stringify(sortedTranslations, null, 2), 'utf-8');
console.log(`Sorted translations for language: ${language}`);
}
} catch (error) {
console.error(error);
console.error('Error during sort:', error.message);
process.exit(1);
}
});
module.exports = { program };
-46
View File
@@ -1,46 +0,0 @@
// @ts-check
const { defaultExtractConfig } = require('./constants');
const { extractAllTranslations } = require('./extract');
const { getLanguageTranslations, getAllLanguages, setLanguageTranslations } = require('./helpers');
const { directories, extensions } = defaultExtractConfig;
/**
* @param {string} language
* @param {Record<string, string>} source
*/
function getUsedTranslations(language, source) {
const languageTranslations = getLanguageTranslations(language);
for (const key in languageTranslations) {
if (!(key in source)) {
delete languageTranslations[key];
}
}
return languageTranslations;
}
async function removeUnusedAllTranslations() {
const source = await extractAllTranslations(directories, extensions);
const languages = getAllLanguages();
for (const language of languages) {
const newTranslations = getUsedTranslations(language, source);
setLanguageTranslations(language, newTranslations);
}
}
/**
* @param {string} language
*/
async function removeUnusedForSignelLanguage(language) {
const source = await extractAllTranslations(directories, extensions);
const newTranslations = getUsedTranslations(language, source);
setLanguageTranslations(language, newTranslations);
}
module.exports = {
removeUnusedAllTranslations,
removeUnusedForSignelLanguage,
};
@@ -1,24 +0,0 @@
// @ts-check
/**
* @param {object|string} json
* @returns {object}
*/
function sortJsonKeysAlphabetically(json) {
const obj = typeof json === 'string' ? JSON.parse(json) : json;
if (obj === null || typeof obj !== 'object' || Array.isArray(obj)) {
return obj;
}
const sortedObj = Object.keys(obj)
.sort()
.reduce((result, key) => {
result[key] = obj[key];
return result;
}, {});
return sortedObj;
}
module.exports = sortJsonKeysAlphabetically;
-132
View File
@@ -1,132 +0,0 @@
require('dotenv').config({ path: '.env.translation' });
const fs = require('fs');
const path = require('path');
const OpenAI = require('openai');
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const translationsDir = path.join(__dirname, '../../translations');
const enFilePath = path.join(translationsDir, 'en.json');
const languageNames = {
'cs.json': 'Czech',
'de.json': 'German',
'es.json': 'Spanish',
'fr.json': 'French',
'it.json': 'Italian',
'ja.json': 'Japanese',
'pt.json': 'Portuguese',
'sk.json': 'Slovak',
'zh.json': 'Chinese'
};
// Read source (english)
const enTranslations = JSON.parse(fs.readFileSync(enFilePath, 'utf8'));
const enKeys = Object.keys(enTranslations);
// Get all translation files
const translationFiles = fs.readdirSync(translationsDir)
.filter(file => file.endsWith('.json') && file !== 'en.json')
.sort();
console.log(`Found ${enKeys.length} keys in en.json\n`);
console.log('='.repeat(80));
async function translateMissingIds({file, translations, missingIds}){
const languageName = languageNames[file];
if (!languageName) {
console.log(`No language name mapping for file: ${file}`);
return;
}
// Build object with only missing translations
const needed = {};
missingIds.forEach(key => {
needed[key] = enTranslations[key];
});
// Get all existing translations as style examples
const existingTranslations = {};
Object.keys(translations).forEach(key => {
if (translations[key] && !translations[key].startsWith('***')) {
existingTranslations[key] = {
en: enTranslations[key],
translated: translations[key]
};
}
});
const prompt = `You are a professional translator for DbGate, a database management application.
Translate the following English UI strings to ${languageName}.
IMPORTANT RULES:
1. Preserve ALL placeholders exactly as they appear: {plugin}, {columnNumber}, {0}, {1}, etc.
2. Maintain technical terminology appropriately for database software
3. Match the translation style, tone, and formality of the existing translations shown below
4. Keep the same level of brevity or verbosity as the existing translations
5. Return ONLY valid JSON - no markdown, no explanations, no code blocks
6. Use the same keys as provided
EXISTING TRANSLATIONS (for style reference):
${JSON.stringify(existingTranslations, null, 2)}
STRINGS TO TRANSLATE:
${JSON.stringify(needed, null, 2)}
Return format: {"key": "translated value", ...}`;
const response = await client.chat.completions.create({
model: 'gpt-5.1',
messages: [
{ role: 'system', content: 'You are a professional translator specializing in software localization. Match the style and tone of existing translations. Return only valid JSON.' },
{ role: 'user', content: prompt }
],
temperature: 0.2
});
let translatedJson = response.choices[0].message.content.trim();
// Remove markdown code blocks if present
translatedJson = translatedJson.replace(/^```json\n?/, '').replace(/\n?```$/, '');
return JSON.parse(translatedJson);
}
(async () => {
for (const file of translationFiles) {
const filePath = path.join(translationsDir, file);
const translations = JSON.parse(fs.readFileSync(filePath, 'utf8'));
const missingIds = enKeys.filter(key => !translations.hasOwnProperty(key) || (typeof translations[key] === 'string' && translations[key].startsWith('***')));
console.log(`\n${file.toUpperCase()}`);
console.log('-'.repeat(80));
if (missingIds.length === 0) {
console.log('✓ All translations complete!');
continue;
} else {
console.log(`Found ${missingIds.length} untranslated IDs\n`);
}
const newTranslations = await translateMissingIds({file, translations, missingIds});
if (!newTranslations) {
console.log(`Skipping file due to translation error: ${file}`);
continue;
}
for (const [key, value] of Object.entries(newTranslations)) {
translations[key] = value;
console.log(`Translated: ${key} => ${value}`);
}
fs.writeFileSync(filePath, JSON.stringify(translations, null, 2) + '\n', 'utf8');
console.log(`\n✓ Updated translations written to ${file}`);
}
console.log('\n' + '='.repeat(80));
console.log('Translation complete!\n');
})();
-1
View File
@@ -1 +0,0 @@
module.exports = 'false';
-30
View File
@@ -1,30 +0,0 @@
// these packages will be never bundled with webpack
const volatilePackages = [
'@clickhouse/client',
'bson', // this package is already bundled and is used in mongodb
'mongodb',
'mongodb-old',
'mongodb-client-encryption',
'tedious',
'msnodesqlv8',
'mysql2',
'oracledb',
'pg-copy-streams',
'pg',
'ioredis',
'node-redis-dump2',
'better-sqlite3',
'libsql',
'@azure/cosmos',
'@aws-sdk/rds-signer',
'activedirectory2',
'axios',
'ssh2',
'wkx',
'@duckdb/node-api',
'@mongosh/browser-runtime-electron',
'@mongosh/service-provider-node-driver',
];
module.exports = volatilePackages;
+22 -23
View File
@@ -1,6 +1,6 @@
# this compose file is for testing purposes only
# use it for testing docker containsers built on local machine
version: '3'
version: "3"
services:
dbgate:
build: docker
@@ -15,31 +15,31 @@ services:
volumes:
- dbgate-data:/root/.dbgate
# environment:
# WEB_ROOT: /dbgate
# CONNECTIONS: mssql
# LABEL_mssql: MS Sql
# SERVER_mssql: mssql
# USER_mssql: sa
# PORT_mssql: 1433
# PASSWORD_mssql: Pwd2020Db
# ENGINE_mssql: mssql@dbgate-plugin-mssql
proxy:
# image: nginx
build: test/nginx
ports:
- 8082:80
# CONNECTIONS: mssql
# LABEL_mssql: MS Sql
# SERVER_mssql: mssql
# USER_mssql: sa
# PORT_mssql: 1433
# PASSWORD_mssql: Pwd2020Db
# ENGINE_mssql: mssql@dbgate-plugin-mssql
# proxy:
# # image: nginx
# build: test/nginx
# ports:
# - 8082:80
volumes:
- /home/jena/test/chinook:/mnt/sqt
environment:
CONNECTIONS: sqlite
# volumes:
# - /home/jena/test/chinook:/mnt/sqt
# environment:
# CONNECTIONS: sqlite
LABEL_sqlite: sqt
FILE_sqlite: /mnt/sqt/Chinook.db
ENGINE_sqlite: sqlite@dbgate-plugin-sqlite
# LABEL_sqlite: sqt
# FILE_sqlite: /mnt/sqt/Chinook.db
# ENGINE_sqlite: sqlite@dbgate-plugin-sqlite
# mssql:
# image: mcr.microsoft.com/mssql/server
@@ -51,5 +51,4 @@ services:
volumes:
dbgate-data:
driver: local
driver: local
+13 -4
View File
@@ -1,12 +1,21 @@
FROM node:22
LABEL org.opencontainers.image.source="https://github.com/dbgate/dbgate"
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y \
curl \
gnupg \
iputils-ping \
iproute2 \
unixodbc \
&& rm -rf /var/lib/apt/lists/*
gcc \
g++ \
make
RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | gpg --dearmor -o /usr/share/keyrings/nodesource-archive-keyring.gpg \
&& echo "deb [signed-by=/usr/share/keyrings/nodesource-archive-keyring.gpg] https://deb.nodesource.com/node_18.x jammy main" | tee /etc/apt/sources.list.d/nodesource.list \
&& echo "deb-src [signed-by=/usr/share/keyrings/nodesource-archive-keyring.gpg] https://deb.nodesource.com/node_18.x jammy main" | tee -a /etc/apt/sources.list.d/nodesource.list \
&& apt-get update && apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/* \
&& npm install -g yarn
WORKDIR /home/dbgate-docker
-2
View File
@@ -1,7 +1,5 @@
FROM node:18-alpine
LABEL org.opencontainers.image.source="https://github.com/dbgate/dbgate"
WORKDIR /home/dbgate-docker
RUN apk --no-cache upgrade \
-8
View File
@@ -1,8 +0,0 @@
module.exports = {
mysql: true,
postgres: true,
mssql: true,
oracle: true,
sqlite: true,
mongo: true
};
-25
View File
@@ -1,25 +0,0 @@
const path = require('path');
const os = require('os');
const fs = require('fs');
const baseDir = path.join(os.homedir(), '.dbgate');
function clearTestingData() {
if (fs.existsSync(path.join(baseDir, 'connections-e2etests.jsonl'))) {
fs.unlinkSync(path.join(baseDir, 'connections-e2etests.jsonl'));
}
if (fs.existsSync(path.join(baseDir, 'settings-e2etests.json'))) {
fs.unlinkSync(path.join(baseDir, 'settings-e2etests.json'));
}
if (fs.existsSync(path.join(baseDir, 'files-e2etests'))) {
fs.rmdirSync(path.join(baseDir, 'files-e2etests'), { recursive: true });
}
if (fs.existsSync(path.join(baseDir, 'archive-e2etests'))) {
fs.rmdirSync(path.join(baseDir, 'archive-e2etests'), { recursive: true });
}
if (fs.existsSync(path.join(__dirname, 'tmpdata', 'my_guitar_shop.db'))) {
fs.unlinkSync(path.join(__dirname, 'tmpdata', 'my_guitar_shop.db'));
}
}
clearTestingData();
-7
View File
@@ -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"]
-27
View File
@@ -1,27 +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"
emailVerified: true
hash: "$2y$10$JcmlXnV1y7.egUdKwYNbseOnqYVIGc323gtvvHh4ZuSPZB30veYZy"
username: "test"
userID: "1234"
allowedScopes:
- openid
- email
- profile
@@ -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
-75
View File
@@ -1,75 +0,0 @@
const { defineConfig } = require('cypress');
const killPort = require('kill-port');
const waitOn = require('wait-on');
const { exec } = require('child_process');
const fs = require('fs');
const path = require('path');
module.exports = defineConfig({
e2e: {
// baseUrl: 'http://localhost:3000',
// trashAssetsBeforeRuns: false,
chromeWebSecurity: false,
setupNodeEvents(on, config) {
// implement node event listeners here
on('before:spec', async details => {
// console.log('********************* DETAILS *********************', JSON.stringify(details));
if (config.isInteractive) {
try {
await killPort(3000);
} catch (e) {
console.warn('Error killing process on port 3000:', e.message);
}
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;
case 'browse-data':
serverProcess = exec('yarn start:browse-data');
break;
case 'team':
serverProcess = exec('yarn start:team');
break;
case 'multi-sql':
serverProcess = exec('yarn start:multi-sql');
break;
case 'cloud':
serverProcess = exec('yarn start:cloud');
break;
case 'charts':
serverProcess = exec('yarn start:charts');
break;
}
await waitOn({ resources: ['http://localhost:3000'] });
serverProcess.stdout.on('data', data => {
console.log(data.toString());
});
serverProcess.stderr.on('data', data => {
console.error(data.toString());
});
}
});
on('after:screenshot', details => {
if (details.name) {
fs.renameSync(details.path, path.resolve(__dirname, `screenshots/${details.name}.png`));
}
});
// on('task', {
// renameFile({ from, to }) {
// fs.renameSync(from, to);
// },
// });
},
},
});
-135
View File
@@ -1,135 +0,0 @@
const path = require('path');
beforeEach(() => {
cy.visit('http://localhost:3000');
cy.viewport(1200, 900);
});
describe('Add connection', () => {
it('successfully loads', () => {
cy.contains('Database not selected');
});
it('adds connection', () => {
// cy.get('[data-testid=ConnectionList_buttonNewConnection]').click();
cy.get('[data-testid=ConnectionDriverFields_connectionType]').select('MySQL');
cy.themeshot('new-connection');
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.testid('ConnectionTab_buttonTest').click();
cy.contains('Connected:');
cy.testid('ConnectionTab_tabSshTunnel').click();
cy.testid('ConnectionTab_tabControlContent').themeshot('connection-sshtunnel-window', { padding: 50 });
cy.testid('ConnectionTab_tabSsl').click();
cy.testid('ConnectionTab_tabControlContent').themeshot('connection-ssl-window', { padding: 50 });
// 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.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('16012');
cy.get('[data-testid=ConnectionTab_buttonSave]').click();
cy.get('[data-testid=ConnectionTab_buttonConnect]').click();
cy.contains('performance_schema');
});
it('SSH connection - keyfile', () => {
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.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');
});
it('export connections', () => {
cy.testid('WidgetIconPanel_menu').click();
cy.contains('Tools').click();
cy.contains('Export connections').click();
cy.themeshot('export-connections');
});
it('configure LLM provider', () => {
cy.testid('WidgetIconPanel_settings').click();
cy.contains('Settings').click();
cy.contains('AI').click();
cy.testid('AiSupportedProvidersInfo_add_OpenRouter').click();
cy.testid('AiProviderCard_apikey_OpenRouter').clear().type('xxx');
cy.testid('AiProviderCard_testButton_OpenRouter').click();
cy.testid('AiProviderCard_statusValid_OpenRouter').should('exist');
cy.testid('AiProviderCard_editButton_OpenRouter').click();
cy.wait(1000);
cy.themeshot('llm-providers-settings');
});
});
-486
View File
@@ -1,486 +0,0 @@
Cypress.on('uncaught:exception', (err, runnable) => {
// if the error message matches the one about WorkerGlobalScope importScripts
if (err.message.includes("Failed to execute 'importScripts' on 'WorkerGlobalScope'")) {
// return false to let Cypress know we intentionally want to ignore this error
return false;
}
// otherwise let Cypress throw the error
});
beforeEach(() => {
cy.visit('http://localhost:3000');
cy.viewport(1250, 900);
});
describe('Data browser data', () => {
it('Export window', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Album').rightclick();
cy.contains('Export').click();
cy.contains('Export advanced').click();
cy.wait(1000);
// cy.testid('SourceTargetConfig_buttonCurrentArchive_target').click();
// cy.testid('FormTablesSelect_buttonAll_tables').click();
// cy.testid('SourceTargetConfig_tablesSelect_source').click();
// cy.find('.listContainer').contains('Album').click();
// cy.find('.listContainer').contains('Track').click();
// cy.wait(4000);
// cy.contains('All tables').click();
cy.contains('Run').click();
cy.contains('Finished job script');
cy.contains('Album.csv');
cy.testid('WidgetIconPanel_database').click();
cy.themeshot('configure-export-csv');
});
it('Data archive editor - macros', () => {
cy.testid('WidgetIconPanel_archive').click();
cy.contains('Album').click();
cy.testid('DataGrid_itemFilters').click();
cy.contains('Let There Be Rock').click();
cy.contains('Out Of Exile').click({ shiftKey: true });
cy.contains('Change text case').click();
cy.contains('AUDIOSLAVE');
cy.themeshot('data-archive-macros');
});
it('Load table data', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Album').click();
cy.contains('Let There Be Rock').click();
cy.contains('Rows: 347');
cy.realPress(['Control', 'ArrowRight']);
cy.contains('Aerosmith');
});
it('Filter model', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('SqlObjectList_search').clear().type('album');
cy.contains('Tables (1/11)');
cy.contains('347 rows, 65.5 KB, InnoDB');
cy.testid('SqlObjectList_searchMenuDropDown').click();
cy.contains('Column name').click();
cy.contains('Tables (2/11)');
cy.contains('AlbumId');
cy.contains('Column name').click();
cy.contains('AlbumId').should('not.exist');
cy.contains('Tables (1/11)');
});
it('Show raw data', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Album').rightclick();
cy.contains('Open raw data').click();
cy.contains('Let There Be Rock').click();
cy.contains('Rows: 347').should('not.exist');
cy.realPress(['Control', 'ArrowRight']);
cy.contains('Aerosmith').should('not.exist');
});
it('Data filter', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Album').click();
cy.testid('DataFilterControl_input_Title').type('Rock{enter}');
cy.contains('Rows: 7');
cy.testid('DataFilterControl_input_AlbumId').type('>10xxx{enter}');
cy.contains('Rows: 7');
cy.testid('DataFilterControl_filtermenu_Title').click();
// hide what is not needed
cy.testid('WidgetIconPanel_database').click();
cy.testid('DataGrid_itemReferences').click();
cy.themeshot('data-browser-filter');
cy.testid('DataGridCore_button_clearFilters').click();
cy.contains('Rows: 347');
});
it('Data grid screenshots', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Album').click();
cy.testid('TabsPanel_pinTabButton').click();
cy.contains('Genre').click();
cy.testid('TabsPanel_pinTabButton').click();
cy.contains('Playlist').click();
cy.testid('TabsPanel_pinTabButton').click();
cy.contains('Postgres-connection').click();
cy.contains('PgChinook').click();
cy.contains('customer').click();
cy.contains('Leonie').click();
cy.themeshot('common-data-browser');
cy.contains('invoice').click();
cy.contains('invoice_line (invoice_id)').click();
cy.themeshot('data-browser-master-detail');
cy.contains('9, Place Louis Barthou').click();
cy.contains('Switch to form').click();
cy.contains('Switch to table'); // test that we are in form view
cy.themeshot('data-browser-form-view');
});
it('Column search', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Customer').click();
cy.testid('ColumnManager_searchColumns').clear().type('name,id{enter}');
cy.contains('Company').should('not.exist');
cy.themeshot('data-browser-column-search');
});
it('SQL Gen', () => {
cy.contains('Postgres-connection').click();
cy.contains('PgChinook').rightclick();
cy.contains('SQL Generator').click();
cy.contains('Check all').click();
cy.themeshot('sql-generator');
});
it('Macros in DB', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Customer').click();
cy.contains('Leonie').click();
cy.contains('Ramos').click({ shiftKey: true });
cy.testid('DataGrid_itemColumns').click();
cy.testid('DataGrid_itemFilters').click();
cy.testid('DataGrid_itemReferences').click();
cy.testid('DataGrid_itemMacros').click();
cy.contains('Change text case').click();
cy.contains('NIELSEN');
cy.themeshot('data-browser-macros');
});
it('Perspectives', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Artist').rightclick();
cy.contains('Design perspective query').click();
cy.testid('PerspectiveNodeRow_check_Artist_Album').click();
cy.testid('PerspectiveNodeRow_expand_Artist_Album').click();
cy.testid('PerspectiveNodeRow_check_Artist_Album_Track').click();
// check track is loaded
cy.contains('Put The Finger On You');
cy.themeshot('perspective-designer');
});
it('Query editor - code completion', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Customer').rightclick();
cy.contains('SQL template').click();
cy.contains('CREATE TABLE').click();
cy.wait(1000);
cy.get('body').realPress('PageDown');
cy.get('body').realType('select * from Album where Album.');
// code completion
cy.contains('ArtistId');
cy.themeshot('query-editor-code-completion');
});
it('Query editor - join wizard', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('TabsPanel_buttonNewObject').click();
cy.testid('NewObjectModal_query').click();
cy.wait(1000);
cy.get('body').realType('select * from Invoice');
cy.get('body').realPress('{enter}');
cy.get('body').realPress(['Control', 'j']);
// JOIN wizard
cy.contains('INNER JOIN Customer ON Invoice.CustomerId = Customer.CustomerId');
cy.themeshot('query-editor-join-wizard');
});
it('Mongo JSON data view', () => {
cy.contains('Mongo-connection').click();
cy.contains('MgChinook').click();
cy.contains('Customer').click();
cy.testid('DataFilterControl_input_CustomerId').type('<=10{enter}');
// test filter
cy.contains('Rows: 10');
cy.contains('Helena').rightclick();
cy.contains('Open query').click();
cy.wait(1000);
cy.contains('Execute').click();
cy.testid('WidgetIconPanel_cell-data').click();
// test JSON view
cy.contains('Country: "Brazil"');
cy.themeshot('mongo-query-json-view');
});
it('SQL preview', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Customer').rightclick();
cy.contains('Show SQL').click();
// index should be part of create script
cy.contains('CREATE INDEX `IFK_CustomerSupportRepId`');
cy.themeshot('sql-preview-create-index');
});
it('Query designer', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('WidgetIconPanel_file').click();
cy.contains('customer').click();
// cy.contains('left join').rightclick();
cy.themeshot('query-designer');
});
it('Database diagram', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('WidgetIconPanel_file').click();
cy.contains('chinook-diagram').click();
cy.testid('WidgetIconPanel_file').click();
// check diagram is shown
cy.contains('MediaTypeId');
cy.themeshot('database-diagram');
});
// it('Charts', () => {
// cy.testid('WidgetIconPanel_file').click();
// cy.contains('pie-chart').click();
// cy.contains('line-chart').click();
// cy.testid('TabsPanel_buttonSplit').click();
// cy.testid('WidgetIconPanel_file').click();
// cy.themeshot('view-split-charts');
// });
it('Keyboard configuration', () => {
cy.testid('WidgetIconPanel_settings').click();
cy.contains('Keyboard shortcuts').click();
cy.contains('dataForm.refresh').click();
cy.testid('CommandModal_keyboardButton').click();
cy.themeshot('keyboard-configuration');
});
it('Command palette', () => {
cy.contains('Connections');
cy.testid('WidgetIconPanel_menu').click();
cy.contains('Tools').click();
cy.contains('Command palette').click();
// cy.realPress('F1');
cy.realPress('PageDown');
cy.realPress('PageDown');
cy.testid('CommandPalette_main').themeshot('command-palette', { padding: 50 });
});
it('About window', () => {
cy.contains('Connections');
cy.testid('WidgetIconPanel_menu').click();
cy.contains('Help').click();
cy.contains('About').click();
cy.testid('ModalBase_window').themeshot('about-window', { padding: 50 });
});
it('Show map', () => {
cy.contains('Postgres-connection').click();
cy.contains('PgGeoData').click();
cy.contains('cities').click();
// clicking column header doesn't work, TODO FIX in app!!!
// cy.contains('location').click();
cy.contains('14.2').click();
cy.contains('13.9').click({ shiftKey: true });
cy.testid('WidgetIconPanel_cell-data').click();
cy.wait(2000);
cy.themeshot('cell-map-view');
});
it('Search in connections', () => {
cy.testid('ConnectionList_search').type('my');
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('SqlObjectList_search').type('album');
cy.contains('Album').click();
cy.testid('SqlObjectList_searchMenuDropDown').click();
cy.contains('Column name').click();
cy.themeshot('search-in-connections');
});
it('Plugin tab', () => {
cy.testid('WidgetIconPanel_settings').click();
cy.contains('Manage plugins').click();
cy.contains('dbgate-plugin-theme-total-white').click();
// text from plugin markdown
cy.contains('Total white theme');
// wait for load logos
cy.wait(2000);
cy.themeshot('view-plugin-tab');
});
it('Edit mongo data JSON', () => {
// TODO FIX: Missing button+ctx menu Revert all changes, missing button+ctx menu add document
// TODO: Dark theme - not visible changed and deleted document
cy.contains('Mongo-connection').click();
cy.contains('MgChinook').click();
cy.contains('Customer').rightclick();
cy.contains('Open JSON').click();
cy.contains('Leonie').rightclick();
cy.contains('Edit document').click();
// cy.focused()
// .type('{downArrow}'.repeat(11))
// .type('{rightarrow}'.repeat(14))
// .type('{del}'.repeat(7)) // 4*delete
// .type('Italy'); // type "Italy"
Array.from({ length: 11 }).forEach(() => cy.realPress('ArrowDown'));
Array.from({ length: 14 }).forEach(() => cy.realPress('ArrowRight'));
Array.from({ length: 7 }).forEach(() => cy.realPress('Delete'));
cy.realType('Italy');
cy.testid('EditJsonModal_saveButton').click();
cy.contains('Helena').rightclick();
cy.contains('Delete document').click();
cy.contains('Save').click();
cy.themeshot('save-changes-mongodb');
});
it('Edit mongo data JSON', () => {
// TODO FIX: Auto expand cell view
cy.contains('Mongo-connection').click();
cy.contains('MgRivers').click();
cy.contains('RiverInfo').click();
cy.testid('ColumnManagerRow_expand_countries').click();
cy.testid('ColumnManagerRow_checkbox_countries.0').click();
cy.testid('ColumnManagerRow_checkbox_countries.1').click();
cy.testid('ColumnManagerRow_checkbox__id').click();
cy.testid('DataFilterControl_input_countries.1').type('EXISTS{enter}');
cy.testid('WidgetIconPanel_cell-data').click();
cy.themeshot('mongodb-json-cell-view');
});
it('Table structure editor', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Customer').rightclick();
cy.contains('Open structure').click();
cy.contains('varchar(40)');
cy.themeshot('table-structure-editor');
cy.contains('EmployeeId').click();
cy.contains('Ref column - Employee');
cy.themeshot('foreign-key-editor');
});
it('Compare database', () => {
// TODO FIX: SQL diff is not dark in dark mode
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('MyChangedChinook').rightclick();
cy.contains('Compare with').click();
cy.testid('CompareModelTab_gridObjects_Customer_Customer').click();
cy.testid('WidgetIconPanel_database').click();
cy.testid('CompareModelTab_tabDdl').click();
cy.themeshot('compare-database-models');
cy.contains('Settings').click();
cy.testid('CompareModelTab_tabOperations').click();
cy.themeshot('compare-database-settings');
});
it('Modify data', () => {
// TODO FIX: delete references cascade not working
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Employee').click();
cy.contains('Rows: 8');
cy.contains('Laura').click();
cy.contains('Laura').click();
cy.get('body').realType('Jane');
// cy.contains('Peacock').click();
// cy.testid('TableDataTab_deleteSelectedRows').click();
cy.contains('King').click();
cy.testid('TableDataTab_deleteSelectedRows').click();
cy.testid('TableDataTab_insertNewRow').click();
cy.get('body').realType('Novak');
cy.get('body').realPress('{enter}');
cy.realPress(['ArrowRight']);
cy.get('body').realType('Karel');
cy.testid('TableDataTab_save').click();
cy.contains('INSERT INTO `Employee`');
cy.contains("SET `FirstName`='Jane'");
cy.contains('DELETE FROM `Employee`');
cy.themeshot('data-browser-save-changes');
// cy.testid('ConfirmSqlModal_okButton').click();
// cy.contains('Cannot delete or update a parent row')
// cy.testid('ConfirmSqlModal_okButton').click();
// cy.testid('TableDataTab_save').click();
// cy.testid('ConfirmSqlModal_deleteReferencesCascade').click();
// cy.testid('ConfirmSqlModal_okButton').click();
cy.testid('ConfirmSqlModal_okButton').click();
cy.contains('Novak');
cy.contains('Rows: 8');
});
it('Export menu', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Album').click();
cy.testid('DataFilterControl_input_ArtistId').type('22{enter}');
// cy.contains('Presence').rightclick();
// cy.contains('Coda').rightclick();
// cy.testid('DropDownMenu-container-0').contains('Export').click();
cy.contains('Export').click();
// cy.wait(1000);
cy.themeshot('data-browser-export-menu');
});
it('MySQL native backup', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').rightclick();
cy.contains('Create database backup').click();
cy.contains('Customer');
cy.themeshot('mysql-backup-configuration');
});
it('View table YAML model', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').rightclick();
cy.contains('Export DB model').click();
cy.testid('ExportDbModelModal_archiveFolder').select('(Create new)');
cy.testid('InputTextModal_value').clear().type('test-model');
cy.testid('InputTextModal_ok').click();
cy.testid('ModalBase_window').themeshot('export-database-model-window', { padding: 50 });
cy.testid('ExportDbModelModal_exportButton').click();
cy.contains('Album').click();
cy.contains('autoIncrement');
cy.themeshot('database-model-table-yaml');
});
it('Data replicator', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('WidgetIconPanel_archive').click();
cy.contains('chinook-archive').rightclick();
cy.contains('Data deployer').click();
cy.contains('Dry run').click();
cy.testid('TableControl_row_2_checkbox').click();
cy.testid('TableControl_row_2').click();
cy.testid('DataDeploySettings_find_checkbox').click();
cy.testid('DataDeploySettings_create_checkbox').click();
cy.testid('WidgetIconPanel_archive').click();
cy.themeshot('data-deployer');
cy.testid('DataDeployTab_importIntoDb').click();
cy.testid('ConfirmDataDeployModal_okButton').click();
cy.contains('Replicated Customer, inserted 59 rows');
cy.contains('Finished job script');
cy.testid('DataDeployTab_importIntoDb').click();
cy.themeshot('data-replicator');
});
});
-207
View File
@@ -1,207 +0,0 @@
Cypress.on('uncaught:exception', (err, runnable) => {
// if the error message matches the one about WorkerGlobalScope importScripts
if (err.message.includes("Failed to execute 'importScripts' on 'WorkerGlobalScope'")) {
// return false to let Cypress know we intentionally want to ignore this error
return false;
}
// otherwise let Cypress throw the error
});
beforeEach(() => {
cy.visit('http://localhost:3000');
cy.viewport(1250, 900);
});
describe('Charts', () => {
it('Auto detect chart', () => {
cy.contains('MySql-connection').click();
cy.contains('charts_sample').click();
cy.testid('WidgetIconPanel_file').click();
cy.contains('chart1').click();
cy.contains('department_name');
// cy.testid('QueryTab_executeButton').click();
// cy.testid('QueryTab_openChartButton').click();
cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
cy.themeshot('choose-detected-chart');
});
it('Two line charts', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('TabsPanel_buttonNewObject').click();
cy.testid('NewObjectModal_query').click();
cy.wait(1000);
cy.get('body').realType('SELECT InvoiceDate, Total from Invoice');
cy.contains('Execute').click();
cy.contains('Open chart').click();
cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
cy.themeshot('two-line-charts');
});
it('Invoice naive autodetection', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('TabsPanel_buttonNewObject').click();
cy.testid('NewObjectModal_query').click();
cy.wait(1000);
cy.get('body').realType('SELECT * from Invoice');
cy.contains('Execute').click();
cy.contains('Open chart').click();
cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
cy.themeshot('chart-naive-autodetection');
});
it('Invoice by country - grouped chart', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('TabsPanel_buttonNewObject').click();
cy.testid('NewObjectModal_query').click();
cy.wait(1000);
cy.get('body').realType(
"SELECT InvoiceDate, Total, BillingCountry from Invoice where BillingCountry in ('USA', 'Canada', 'Brazil', 'France', 'Germany')"
);
cy.contains('Execute').click();
cy.contains('Open chart').click();
cy.testid('ChartSelector_chart_1').click();
cy.testid('JslChart_customizeButton').click();
cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
cy.themeshot('chart-grouped-autodetected');
cy.testid('ChartDefinitionEditor_chartTypeSelect').select('Bar');
cy.testid('ChartDefinitionEditor_xAxisTransformSelect').select('Date (Year)');
cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
cy.themeshot('chart-grouped-bars');
});
it('Public Knowledge base - show chart', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('WidgetIconPanel_cloud-public').click();
cy.testid('public-cloud-file-tag-mysql/folder-MySQL/tag-premium/top-tables-row-count.sql').click();
cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
cy.themeshot('public-knowledge-base-tables-sizes');
});
it('Auto detect chart', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Invoice').rightclick();
cy.contains('SQL template').click();
cy.contains('SELECT').click();
cy.testid('QueryTab_detectChartButton').click();
cy.testid('QueryTab_executeButton').click();
cy.contains('Chart 1').click();
cy.testid('ChartSelector_chart_0').click();
cy.testid('JslChart_customizeButton').click();
cy.testid('ChartDefinitionEditor_chartTypeSelect').select('Bar');
cy.testid('ChartDefinitionEditor_chartTypeSelect').select('Line');
cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
cy.themeshot('query-result-chart');
});
it('New object window', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Invoice').click();
cy.testid('WidgetIconPanel_addButton').click();
cy.contains('Compare database');
cy.themeshot('new-object-window');
});
it('Database chat - charts', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('TabsPanel_buttonNewObject').click();
cy.testid('NewObjectModal_databaseChat').click();
cy.wait(1000);
cy.get('body').realType('show me chart of most popular genres');
cy.get('body').realPress('{enter}');
cy.testid('DatabaseChatTab_executeAllQueries', { timeout: 30000 }).click();
cy.testid('chart-canvas', { timeout: 30000 }).should($c =>
expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/)
);
cy.themeshot('database-chat-chart');
});
it('Database chat', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('TabsPanel_buttonNewObject').click();
cy.testid('NewObjectModal_databaseChat').click();
cy.wait(1000);
cy.get('body').realType('find most popular artist');
cy.get('body').realPress('{enter}');
cy.testid('DatabaseChatTab_executeAllQueries', { timeout: 30000 }).click();
cy.wait(30000);
// cy.contains('Iron Maiden');
cy.themeshot('database-chat');
// cy.testid('DatabaseChatTab_promptInput').click();
// cy.get('body').realType('I need top 10 songs with the biggest income');
// cy.get('body').realPress('{enter}');
// cy.contains('Hot Girl', { timeout: 20000 });
// cy.wait(1000);
// cy.themeshot('database-chat');
});
it('Explain query error', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('TabsPanel_buttonNewObject').click();
cy.testid('NewObjectModal_query').click();
cy.wait(1000);
cy.get('body').realType('select * from Invoice2');
cy.contains('Execute').click();
cy.testid('MessageViewRow-explainErrorButton-1').click();
cy.testid('ChatCodeRenderer_useSqlButton', { timeout: 30000 });
cy.themeshot('explain-query-error');
});
it('Switch language', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('WidgetIconPanel_settings').click();
cy.contains('Settings').click();
cy.testid('SettingsModal_languageSelect').select('Deutsch');
cy.testid('ConfirmModal_okButton').click();
cy.testid('WidgetIconPanel_settings').click();
cy.contains('Einstellungen').click();
cy.contains('Lokalisierung');
cy.themeshot('switch-language-de');
cy.testid('SettingsModal_languageSelect').select('Français');
cy.testid('ConfirmModal_okButton').click();
cy.testid('WidgetIconPanel_settings').click();
cy.contains('Paramètres').click();
cy.contains('Localisation');
cy.themeshot('switch-language-fr');
cy.testid('SettingsModal_languageSelect').select('Español');
cy.testid('ConfirmModal_okButton').click();
cy.testid('WidgetIconPanel_settings').click();
cy.contains('Configuración').click();
cy.contains('Localización');
cy.themeshot('switch-language-es');
cy.testid('SettingsModal_languageSelect').select('Čeština');
cy.testid('ConfirmModal_okButton').click();
cy.testid('WidgetIconPanel_settings').click();
cy.contains('Nastavení').click();
cy.contains('Lokalizace');
cy.themeshot('switch-language-cs');
cy.testid('SettingsModal_languageSelect').select('中文');
cy.testid('ConfirmModal_okButton').click();
cy.testid('WidgetIconPanel_settings').click();
cy.contains('设置').click();
cy.contains('本地化');
cy.themeshot('switch-language-zh');
cy.testid('SettingsModal_languageSelect').select('English');
cy.testid('ConfirmModal_okButton').click();
cy.testid('WidgetIconPanel_settings');
});
});
-56
View File
@@ -1,56 +0,0 @@
Cypress.on('uncaught:exception', (err, runnable) => {
// if the error message matches the one about WorkerGlobalScope importScripts
if (err.message.includes("Failed to execute 'importScripts' on 'WorkerGlobalScope'")) {
// return false to let Cypress know we intentionally want to ignore this error
return false;
}
// otherwise let Cypress throw the error
});
beforeEach(() => {
cy.visit('http://localhost:3000');
cy.viewport(1250, 900);
});
describe('Cloud tests', () => {
it('Private cloud', () => {
cy.testid('WidgetIconPanel_cloudAccount');
cy.window().then(win => {
win.__loginToCloudTest('dbgate.test@gmail.com');
});
cy.contains('dbgate.test@gmail.com');
// cy.testid('WidgetIconPanel_cloudAccount').click();
// cy.origin('https://identity.dbgate.io', () => {
// cy.contains('Sign in with GitHub').click();
// });
// cy.origin('https://github.com', () => {
// cy.get('#login_field').type('dbgatetest');
// cy.get('#password').type('Pwd2020Db');
// cy.get('input[type="submit"]').click();
// });
// cy.wait(3000);
// cy.location('origin').then(origin => {
// if (origin === 'https://github.com') {
// // Still on github.com → an authorization step is waiting
// cy.origin('https://github.com', () => {
// // Try once, don't wait the full default timeout
// cy.get('button[data-octo-click="oauth_application_authorization"]', { timeout: 500, log: false }).click(); // if the button exists it will be clicked
// // if not, the short timeout elapses and we drop out
// });
// } else {
// // Already back on localhost nothing to authorize
// cy.log('OAuth redirect skipped the Authorize screen');
// }
// });
cy.contains('Testing Connections').rightclick();
cy.contains('Administrate access').click();
cy.contains('User email');
cy.themeshot('administer-shared-folder');
});
});
-203
View File
@@ -1,203 +0,0 @@
const localconfig = require('../../.localconfig');
const { formatQueryWithoutParams } = require('dbgate-tools');
global.DBGATE_PACKAGES = {
'dbgate-tools': require('dbgate-tools'),
};
function requireEngineDriver(engine) {
const [shortName, packageName] = engine.split('@');
const plugin = require(`../../../plugins/${packageName}/src/frontend/index`);
if (plugin.drivers) {
return plugin.drivers.find(x => x.engine == engine);
}
throw new Error(`Could not find engine driver ${engine}`);
}
Cypress.on('uncaught:exception', (err, runnable) => {
// if the error message matches the one about WorkerGlobalScope importScripts
if (err.message.includes("Failed to execute 'importScripts' on 'WorkerGlobalScope'")) {
// return false to let Cypress know we intentionally want to ignore this error
return false;
}
// otherwise let Cypress throw the error
});
beforeEach(() => {
cy.visit('http://localhost:3000');
cy.viewport(1250, 900);
});
function multiTest(testProps, testDefinition) {
if (localconfig.mysql) {
it('MySQL', () => testDefinition('MySql-connection', 'my_guitar_shop', 'mysql@dbgate-plugin-mysql'));
}
if (localconfig.postgres) {
it('Postgres', () => testDefinition('Postgres-connection', 'my_guitar_shop', 'postgres@dbgate-plugin-postgres'));
}
if (localconfig.mssql) {
it('Mssql', () => testDefinition('Mssql-connection', 'my_guitar_shop', 'mssql@dbgate-plugin-mssql'));
}
if (localconfig.oracle) {
it('Oracle', () =>
testDefinition('Oracle-connection', 'C##MY_GUITAR_SHOP', 'oracle@dbgate-plugin-oracle', {
implicitTransactions: true,
}));
}
if (localconfig.sqlite) {
it('Sqlite', () => testDefinition('Sqlite-connection', null, 'sqlite@dbgate-plugin-sqlite'));
}
if (localconfig.mongo && !testProps.skipMongo) {
it('MongoDB', () => testDefinition('Mongo-connection', 'my_guitar_shop', 'mongo@dbgate-plugin-mongo'));
}
}
describe('Transactions', () => {
multiTest({ skipMongo: true }, (connectionName, databaseName, engine, options = {}) => {
const driver = requireEngineDriver(engine);
const implicitTransactions = options.implicitTransactions ?? false;
cy.contains(connectionName).click();
if (databaseName) cy.contains(databaseName).click();
cy.testid('TabsPanel_buttonNewObject').click();
cy.testid('NewObjectModal_query').click();
cy.wait(1000);
cy.get('body').type(
formatQueryWithoutParams(driver, "INSERT INTO ~categories (~category_id, ~category_name) VALUES (5, 'test');")
);
// rollback
if (!implicitTransactions) {
cy.testid('QueryTab_beginTransactionButton').click();
cy.contains('Begin Transaction finished');
}
cy.testid('QueryTab_executeButton').click();
cy.contains('Query execution finished');
cy.testid('QueryTab_rollbackTransactionButton').click();
cy.contains('Rollback Transaction finished');
// should contain 4 rows
cy.testid('SqlObjectList_container').contains('categories').click();
cy.contains('Guitars').click();
cy.testid('TableDataTab_refreshGrid').click();
cy.contains('Rows: 4');
// commit
cy.contains('Query #1').click();
if (!implicitTransactions) {
cy.testid('QueryTab_beginTransactionButton').click();
cy.contains('Begin Transaction finished');
}
cy.testid('QueryTab_executeButton').click();
cy.contains('Query execution finished');
cy.testid('QueryTab_commitTransactionButton').click();
cy.contains('Commit Transaction finished');
// should contain 5 rows
cy.testid('SqlObjectList_container').contains('categories').click();
cy.contains('Guitars').click();
cy.testid('TableDataTab_refreshGrid').click();
cy.contains('Rows: 5');
});
});
describe('Backup table', () => {
multiTest({ skipMongo: true }, (connectionName, databaseName, engine, options = {}) => {
cy.contains(connectionName).click();
if (databaseName) cy.contains(databaseName).click();
cy.contains('customers').rightclick();
cy.contains('Create table backup').click();
cy.testid('ConfirmSqlModal_okButton').click();
cy.contains('_customers').click();
cy.contains('Rows: 8').should('be.visible');
});
});
describe('Truncate table', () => {
multiTest({ skipMongo: true }, (connectionName, databaseName, engine, options = {}) => {
cy.contains(connectionName).click();
if (databaseName) cy.contains(databaseName).click();
cy.contains('order_items').rightclick();
cy.contains('Truncate table').click();
cy.testid('ConfirmSqlModal_okButton').click();
cy.contains('order_items').click();
cy.contains('No rows loaded').should('be.visible');
});
});
describe('Drop table', () => {
multiTest({ skipMongo: true }, (connectionName, databaseName, engine, options = {}) => {
cy.contains(connectionName).click();
if (databaseName) cy.contains(databaseName).click();
cy.contains('order_items').rightclick();
cy.contains('Drop table').click();
cy.testid('ConfirmSqlModal_okButton').click();
cy.contains('order_items').should('not.exist');
});
});
describe('Import CSV', () => {
multiTest({}, (connectionName, databaseName, engine, options = {}) => {
cy.contains(connectionName).click();
if (databaseName) cy.contains(databaseName).click();
cy.testid('ConnectionList_container')
.contains(databaseName ?? connectionName)
.rightclick();
cy.contains('Import').click();
cy.get('input[type=file]').selectFile('cypress/fixtures/customers-20.csv', { force: true });
cy.contains('customers-20');
cy.testid('ImportExportTab_preview_content').contains('50ddd99fAdF48B3').should('be.visible');
cy.testid('ImportExportTab_executeButton').click();
cy.contains('20 rows written').should('be.visible');
cy.testid('SqlObjectList_refreshButton').click();
cy.testid('SqlObjectList_container').contains('customers-20').click();
cy.contains('Rows: 20').should('be.visible');
// cy.get('table tbody tr')
// .eq(1)
// .within(() => {
// cy.get('select').select('Append data');
// });
});
});
describe('Import CSV - source error', () => {
multiTest({}, (connectionName, databaseName, engine, options = {}) => {
cy.contains(connectionName).click();
if (databaseName) cy.contains(databaseName).click();
cy.testid('ConnectionList_container')
.contains(databaseName ?? connectionName)
.rightclick();
cy.contains('Import').click();
cy.get('input[type=file]').selectFile('cypress/fixtures/customers-20-err.csv', { force: true });
cy.contains('customers-20-err');
cy.testid('ImportExportTab_preview_content').contains('Invalid Closing Quote').should('be.visible');
cy.testid('ImportExportTab_executeButton').click();
cy.testid('ImportExportConfigurator_errorInfoIcon_customers-20-err').click();
cy.testid('ErrorMessageModal_message').contains('Invalid Closing Quote').should('be.visible');
});
});
describe('Import CSV - target error', () => {
multiTest({}, (connectionName, databaseName, engine, options = {}) => {
cy.contains(connectionName).click();
if (databaseName) cy.contains(databaseName).click();
cy.testid('ConnectionList_container')
.contains(databaseName ?? connectionName)
.rightclick();
cy.contains('Import').click();
cy.get('input[type=file]').selectFile('cypress/fixtures/customers-20.csv', { force: true });
cy.contains('customers-20');
cy.testid('ImportExportConfigurator_targetName_customers-20').clear().type('system."]`');
cy.testid('ImportExportTab_executeButton').click();
cy.testid('ImportExportConfigurator_errorInfoIcon_customers-20').click();
cy.testid('ErrorMessageModal_message').should('be.visible');
});
});
-49
View File
@@ -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-----
-14
View File
@@ -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');
});
});
-93
View File
@@ -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();
// });
});
-151
View File
@@ -1,151 +0,0 @@
Cypress.on('uncaught:exception', (err, runnable) => {
// if the error message matches the one about WorkerGlobalScope importScripts
if (err.message.includes("Failed to execute 'importScripts' on 'WorkerGlobalScope'")) {
// return false to let Cypress know we intentionally want to ignore this error
return false;
}
// otherwise let Cypress throw the error
});
beforeEach(() => {
cy.visit('http://localhost:3000');
cy.viewport(1250, 900);
});
describe('Team edition tests', () => {
it('Team edition screens', () => {
cy.testid('LoginPage_linkAdmin').click();
cy.testid('LoginPage_password').type('adminpwd');
cy.testid('LoginPage_submitLogin').click();
cy.testid('AdminMenuWidget_itemConnections').click();
cy.contains('New connection').click();
cy.testid('ConnectionDriverFields_connectionType').select('PostgreSQL');
cy.contains('not granted').should('not.exist');
cy.themeshot('connection-administration');
cy.testid('AdminMenuWidget_itemRoles').click();
cy.contains('logged-user').click();
cy.contains('not granted').should('not.exist');
cy.themeshot('role-administration');
cy.testid('AdminMenuWidget_itemUsers').click();
cy.contains('New user').click();
cy.contains('not granted').should('not.exist');
cy.themeshot('user-administration');
cy.testid('AdminMenuWidget_itemAuthentication').click();
cy.contains('Add authentication').click();
cy.contains('Use database login').click();
cy.contains('Add authentication').click();
cy.contains('OAuth 2.0').click();
cy.contains('not granted').should('not.exist');
cy.themeshot('authentication-administration');
});
it('OAuth authentication', () => {
cy.testid('LoginPage_linkAdmin').click();
cy.testid('LoginPage_password').type('adminpwd');
cy.testid('LoginPage_submitLogin').click();
cy.testid('AdminMenuWidget_itemAuthentication').click();
// cy.testid('AdminAuthForm_disableButton_local').click();
// cy.testid('AdminAuthForm_disableButton_none').click();
// fill OAuth
cy.contains('Add authentication').click();
cy.contains('OAuth 2.0').click();
cy.testid('AdminAuthForm_oauthAuth_oauth').type('http://localhost:16009/dex/auth');
cy.testid('AdminAuthForm_oauthToken_oauth').type('http://localhost:16009/dex/token');
cy.testid('AdminAuthForm_oauthScope_oauth').type('openid email profile');
cy.testid('AdminAuthForm_oauthClient_oauth').type('my-app');
cy.testid('AdminAuthForm_oauthClientSecret_oauth').type('my-secret');
cy.testid('AdminAuthForm_oauthLoginField_oauth').type('name');
cy.testid('AdminAuthForm_oauthSaveNotDefinedLogins_oauth').click();
cy.testid('AdminAuthForm_oauthEmailField_oauth').type('email');
cy.testid('AdminAuthTab_saveButton').click();
cy.testid('WidgetIconPanel_menu').click();
cy.contains('File').click();
cy.contains('Logout').click();
cy.testid('LoginPage_linkRegularUser').click();
// login two times
for (let index of [1, 2]) {
// login as OAuth
cy.testid('LoginPage_loginButton_OAuth 2.0').click();
// login on DEX
cy.get('#login').clear().type('test@example.com');
cy.get('#password').clear().type('test');
cy.get('#submit-login').click();
// logout
cy.testid('WidgetIconPanel_menu').click();
cy.contains('File').click();
cy.contains('Logout').click();
cy.testid('NotLoggedPage_loginButton').click();
}
// Logout and login again as admin
cy.testid('LoginPage_linkAdmin').click();
cy.testid('LoginPage_password').type('adminpwd');
cy.testid('LoginPage_submitLogin').click();
cy.testid('AdminMenuWidget_itemUsers').click();
cy.contains('test@example.com');
});
it('Audit logging', () => {
cy.testid('LoginPage_linkAdmin').click();
cy.testid('LoginPage_password').type('adminpwd');
cy.testid('LoginPage_submitLogin').click();
cy.testid('AdminMenuWidget_itemAuditLog').click();
cy.contains('Audit log is not enabled');
cy.testid('AdminMenuWidget_itemSettings').click();
cy.testid('AdminSettingsTab_auditLogCheckbox').click();
cy.testid('AdminMenuWidget_itemAuditLog').click();
cy.contains('No data for selected date');
cy.testid('AdminMenuWidget_itemConnections').click();
cy.contains('Open table').click();
cy.contains('displayName');
cy.get('.toolstrip').contains('Export').click();
cy.contains('CSV file').click();
cy.testid('AdminMenuWidget_itemUsers').click();
cy.contains('Open table').click();
cy.contains('login');
cy.get('.toolstrip').contains('Export').click();
cy.contains('XML file').click();
cy.testid('AdminMenuWidget_itemAuditLog').click();
cy.testid('AdminAuditLogTab_refreshButton').click();
cy.contains('Exporting query').click();
cy.themeshot('auditlog');
});
it('Edit database permissions', () => {
cy.testid('LoginPage_linkAdmin').click();
cy.testid('LoginPage_password').type('adminpwd');
cy.testid('LoginPage_submitLogin').click();
cy.testid('AdminMenuWidget_itemRoles').click();
cy.testid('AdminRolesTab_table').contains('superadmin').click();
cy.testid('AdminRolesTab_databases').click();
cy.testid('AdminDatabasesPermissionsGrid_addButton').click();
cy.testid('AdminDatabasesPermissionsGrid_addButton').click();
cy.testid('AdminDatabasesPermissionsGrid_addButton').click();
cy.testid('AdminListOrRegexEditor_1_regexInput').type('^Chinook[\\d]*$');
cy.testid('AdminListOrRegexEditor_2_listSwitch').click();
cy.testid('AdminListOrRegexEditor_2_listInput').type('Nortwind\nSales');
cy.testid('AdminDatabasesPermissionsGrid_roleSelect_0').select('-2');
cy.testid('AdminDatabasesPermissionsGrid_roleSelect_1').select('-3');
cy.testid('AdminDatabasesPermissionsGrid_roleSelect_2').select('-4');
cy.contains('not granted').should('not.exist');
cy.themeshot('database-permissions');
});
});
@@ -1,21 +0,0 @@
Index,Customer Id,First Name,Last Name,Company,City,Country,Phone 1,Phone 2,Email,Subscription Date,Website
1,50ddd99fAdF48B3,Jessica,Navarro,"Tran, Odom and Graham",Port Terranceview,Jersey,(883)287-7947,479-044-3187,wmcintyre@myers.net,2023-03-11,http://pennington.com/
"2,BD1AB97979DDcDe,Preston,Andrews,"Townsend, Lawrence and Davenport",Harringtonmouth,Croatia,188-270-5676x63873,001-428-148-4270,bradley63@jacobs.net,2023-11-15,http://burke.com/
3,0FDDD9aCa501acE,Melissa,Mckay,Rivas-Cooke,Oliviabury,Cook Islands,8257631531,001-650-689-5600x927,ugalloway@maxwell-mcclain.com,2025-01-25,https://patrick.com/
4,A7dA284B7c4AfaD,Frank,Livingston,"Lambert, Garner and Mathews",Mallorytown,Faroe Islands,766.182.6201x689,+1-476-912-2027x4370,tracie00@webster.biz,2021-03-27,https://www.hart.com/
5,38bb1624e4f8211,Ross,Mendoza,Cook and Sons,New Perry,Bolivia,001-440-468-2236,165.562.4328x9274,austincarmen@abbott.com,2024-12-12,http://harmon.com/
6,55c9Fda2BABFE1a,Jane,Tate,Knapp PLC,West Kathyshire,Morocco,001-606-447-0584x07975,(003)872-1307x285,carlosgomez@mcpherson-ramos.biz,2021-09-13,http://www.yu.com/
7,A15eccAc67cCc5b,Tanya,Chung,Frost Inc,South Julieburgh,United States of America,778-360-8301x268,+1-034-169-4237,onewton@crosby.com,2024-10-01,http://www.gill-velez.biz/
8,aFdab04acACaf90,Jackson,Moyer,Bowen Ltd,Port Triciabury,Bahrain,001-187-882-2891x169,154.903.2525,gabriela16@mejia.org,2023-06-20,http://www.david.biz/
9,A2EaeAd3c6529B9,Kelly,Douglas,Phillips PLC,Weissberg,Qatar,767.177.3199x5576,5156730935,wigginsmercedes@tanner.com,2021-06-30,https://gonzalez.net/
10,188175A5641d080,Mariah,Riddle,"Mata, Fuller and Good",Choiton,Namibia,092-993-3559x342,190.937.3937,eileen32@greer.biz,2021-04-17,http://www.bowen.info/
11,B2BA817C7bC09f0,Kristine,Pennington,"Koch, Diaz and Valdez",Port Rachael,Suriname,877.152.6488x921,790-804-9979x3290,tonya00@flynn.com,2024-03-28,https://www.rocha.net/
12,fFAD70B5Febc43a,Robert,Adams,Bender-Wolfe,Billfort,Tanzania,219-696-1912x93626,518-969-4058,jeffersoncolton@moss-ashley.com,2022-07-31,https://www.alvarez.com/
13,9a44524E1261Ed6,Franklin,Costa,Werner Group,North Bradley,Cook Islands,(895)448-4681x1999,648-345-3083x88242,marksmith@novak.com,2024-12-03,http://thornton.com/
14,0C360EfE17D06cc,Dan,Ballard,Sampson-Huff,Michaelchester,Sao Tome and Principe,+1-803-469-5237x2580,(729)574-6101x0605,molly54@acevedo.info,2022-10-24,https://www.sloan-gonzales.biz/
15,fb5cE8cb1eF2954,Clifford,Moyer,Fry-Whitehead,Lake Gary,Japan,(504)263-0450,247.514.1614x551,rhonda34@orr.com,2020-03-08,https://norton.com/
16,3e53DcaD1cB0054,Tonya,Durham,"Lowe, West and Reynolds",South Sylviaton,Brunei Darussalam,(613)893-8183,(461)399-6120,kiara96@meadows.biz,2022-08-04,https://www.reeves.com/
17,83fDDE5812EbEde,Dale,Bishop,Shaw-Ray,Lake Miranda,Congo,(082)202-9241,+1-413-610-1854x79378,bhoward@hodges.biz,2023-05-08,http://www.escobar.com/
18,8dB7ACe2C5758cE,Priscilla,Mills,Pope PLC,North Cliffordshire,South Georgia and the South Sandwich Islands,+1-465-802-4573x30191,044-393-6049x598,nathaniel28@hess.com,2020-09-08,https://www.watts.org/
19,c1092ebDaF2ceED,Alice,Bond,Chan-Liu,West Wesley,Lithuania,+1-333-285-8515,(715)759-3158x77103,jose92@peters.com,2024-05-30,http://www.marquez.com/
20,4d0c95579D095aF,Cole,Compton,Calderon PLC,Robertaville,Saudi Arabia,029.862.3387x470,001-319-474-2394,sspence@dorsey.com,2020-08-02,http://hamilton.net/
Can't render this file because it contains an unexpected character in line 3 and column 36.
@@ -1,21 +0,0 @@
Index,Customer Id,First Name,Last Name,Company,City,Country,Phone 1,Phone 2,Email,Subscription Date,Website
1,50ddd99fAdF48B3,Jessica,Navarro,"Tran, Odom and Graham",Port Terranceview,Jersey,(883)287-7947,479-044-3187,wmcintyre@myers.net,2023-03-11,http://pennington.com/
2,BD1AB97979DDcDe,Preston,Andrews,"Townsend, Lawrence and Davenport",Harringtonmouth,Croatia,188-270-5676x63873,001-428-148-4270,bradley63@jacobs.net,2023-11-15,http://burke.com/
3,0FDDD9aCa501acE,Melissa,Mckay,Rivas-Cooke,Oliviabury,Cook Islands,8257631531,001-650-689-5600x927,ugalloway@maxwell-mcclain.com,2025-01-25,https://patrick.com/
4,A7dA284B7c4AfaD,Frank,Livingston,"Lambert, Garner and Mathews",Mallorytown,Faroe Islands,766.182.6201x689,+1-476-912-2027x4370,tracie00@webster.biz,2021-03-27,https://www.hart.com/
5,38bb1624e4f8211,Ross,Mendoza,Cook and Sons,New Perry,Bolivia,001-440-468-2236,165.562.4328x9274,austincarmen@abbott.com,2024-12-12,http://harmon.com/
6,55c9Fda2BABFE1a,Jane,Tate,Knapp PLC,West Kathyshire,Morocco,001-606-447-0584x07975,(003)872-1307x285,carlosgomez@mcpherson-ramos.biz,2021-09-13,http://www.yu.com/
7,A15eccAc67cCc5b,Tanya,Chung,Frost Inc,South Julieburgh,United States of America,778-360-8301x268,+1-034-169-4237,onewton@crosby.com,2024-10-01,http://www.gill-velez.biz/
8,aFdab04acACaf90,Jackson,Moyer,Bowen Ltd,Port Triciabury,Bahrain,001-187-882-2891x169,154.903.2525,gabriela16@mejia.org,2023-06-20,http://www.david.biz/
9,A2EaeAd3c6529B9,Kelly,Douglas,Phillips PLC,Weissberg,Qatar,767.177.3199x5576,5156730935,wigginsmercedes@tanner.com,2021-06-30,https://gonzalez.net/
10,188175A5641d080,Mariah,Riddle,"Mata, Fuller and Good",Choiton,Namibia,092-993-3559x342,190.937.3937,eileen32@greer.biz,2021-04-17,http://www.bowen.info/
11,B2BA817C7bC09f0,Kristine,Pennington,"Koch, Diaz and Valdez",Port Rachael,Suriname,877.152.6488x921,790-804-9979x3290,tonya00@flynn.com,2024-03-28,https://www.rocha.net/
12,fFAD70B5Febc43a,Robert,Adams,Bender-Wolfe,Billfort,Tanzania,219-696-1912x93626,518-969-4058,jeffersoncolton@moss-ashley.com,2022-07-31,https://www.alvarez.com/
13,9a44524E1261Ed6,Franklin,Costa,Werner Group,North Bradley,Cook Islands,(895)448-4681x1999,648-345-3083x88242,marksmith@novak.com,2024-12-03,http://thornton.com/
14,0C360EfE17D06cc,Dan,Ballard,Sampson-Huff,Michaelchester,Sao Tome and Principe,+1-803-469-5237x2580,(729)574-6101x0605,molly54@acevedo.info,2022-10-24,https://www.sloan-gonzales.biz/
15,fb5cE8cb1eF2954,Clifford,Moyer,Fry-Whitehead,Lake Gary,Japan,(504)263-0450,247.514.1614x551,rhonda34@orr.com,2020-03-08,https://norton.com/
16,3e53DcaD1cB0054,Tonya,Durham,"Lowe, West and Reynolds",South Sylviaton,Brunei Darussalam,(613)893-8183,(461)399-6120,kiara96@meadows.biz,2022-08-04,https://www.reeves.com/
17,83fDDE5812EbEde,Dale,Bishop,Shaw-Ray,Lake Miranda,Congo,(082)202-9241,+1-413-610-1854x79378,bhoward@hodges.biz,2023-05-08,http://www.escobar.com/
18,8dB7ACe2C5758cE,Priscilla,Mills,Pope PLC,North Cliffordshire,South Georgia and the South Sandwich Islands,+1-465-802-4573x30191,044-393-6049x598,nathaniel28@hess.com,2020-09-08,https://www.watts.org/
19,c1092ebDaF2ceED,Alice,Bond,Chan-Liu,West Wesley,Lithuania,+1-333-285-8515,(715)759-3158x77103,jose92@peters.com,2024-05-30,http://www.marquez.com/
20,4d0c95579D095aF,Cole,Compton,Calderon PLC,Robertaville,Saudi Arabia,029.862.3387x470,001-319-474-2394,sspence@dorsey.com,2020-08-02,http://hamilton.net/
1 Index Customer Id First Name Last Name Company City Country Phone 1 Phone 2 Email Subscription Date Website
2 1 50ddd99fAdF48B3 Jessica Navarro Tran, Odom and Graham Port Terranceview Jersey (883)287-7947 479-044-3187 wmcintyre@myers.net 2023-03-11 http://pennington.com/
3 2 BD1AB97979DDcDe Preston Andrews Townsend, Lawrence and Davenport Harringtonmouth Croatia 188-270-5676x63873 001-428-148-4270 bradley63@jacobs.net 2023-11-15 http://burke.com/
4 3 0FDDD9aCa501acE Melissa Mckay Rivas-Cooke Oliviabury Cook Islands 8257631531 001-650-689-5600x927 ugalloway@maxwell-mcclain.com 2025-01-25 https://patrick.com/
5 4 A7dA284B7c4AfaD Frank Livingston Lambert, Garner and Mathews Mallorytown Faroe Islands 766.182.6201x689 +1-476-912-2027x4370 tracie00@webster.biz 2021-03-27 https://www.hart.com/
6 5 38bb1624e4f8211 Ross Mendoza Cook and Sons New Perry Bolivia 001-440-468-2236 165.562.4328x9274 austincarmen@abbott.com 2024-12-12 http://harmon.com/
7 6 55c9Fda2BABFE1a Jane Tate Knapp PLC West Kathyshire Morocco 001-606-447-0584x07975 (003)872-1307x285 carlosgomez@mcpherson-ramos.biz 2021-09-13 http://www.yu.com/
8 7 A15eccAc67cCc5b Tanya Chung Frost Inc South Julieburgh United States of America 778-360-8301x268 +1-034-169-4237 onewton@crosby.com 2024-10-01 http://www.gill-velez.biz/
9 8 aFdab04acACaf90 Jackson Moyer Bowen Ltd Port Triciabury Bahrain 001-187-882-2891x169 154.903.2525 gabriela16@mejia.org 2023-06-20 http://www.david.biz/
10 9 A2EaeAd3c6529B9 Kelly Douglas Phillips PLC Weissberg Qatar 767.177.3199x5576 5156730935 wigginsmercedes@tanner.com 2021-06-30 https://gonzalez.net/
11 10 188175A5641d080 Mariah Riddle Mata, Fuller and Good Choiton Namibia 092-993-3559x342 190.937.3937 eileen32@greer.biz 2021-04-17 http://www.bowen.info/
12 11 B2BA817C7bC09f0 Kristine Pennington Koch, Diaz and Valdez Port Rachael Suriname 877.152.6488x921 790-804-9979x3290 tonya00@flynn.com 2024-03-28 https://www.rocha.net/
13 12 fFAD70B5Febc43a Robert Adams Bender-Wolfe Billfort Tanzania 219-696-1912x93626 518-969-4058 jeffersoncolton@moss-ashley.com 2022-07-31 https://www.alvarez.com/
14 13 9a44524E1261Ed6 Franklin Costa Werner Group North Bradley Cook Islands (895)448-4681x1999 648-345-3083x88242 marksmith@novak.com 2024-12-03 http://thornton.com/
15 14 0C360EfE17D06cc Dan Ballard Sampson-Huff Michaelchester Sao Tome and Principe +1-803-469-5237x2580 (729)574-6101x0605 molly54@acevedo.info 2022-10-24 https://www.sloan-gonzales.biz/
16 15 fb5cE8cb1eF2954 Clifford Moyer Fry-Whitehead Lake Gary Japan (504)263-0450 247.514.1614x551 rhonda34@orr.com 2020-03-08 https://norton.com/
17 16 3e53DcaD1cB0054 Tonya Durham Lowe, West and Reynolds South Sylviaton Brunei Darussalam (613)893-8183 (461)399-6120 kiara96@meadows.biz 2022-08-04 https://www.reeves.com/
18 17 83fDDE5812EbEde Dale Bishop Shaw-Ray Lake Miranda Congo (082)202-9241 +1-413-610-1854x79378 bhoward@hodges.biz 2023-05-08 http://www.escobar.com/
19 18 8dB7ACe2C5758cE Priscilla Mills Pope PLC North Cliffordshire South Georgia and the South Sandwich Islands +1-465-802-4573x30191 044-393-6049x598 nathaniel28@hess.com 2020-09-08 https://www.watts.org/
20 19 c1092ebDaF2ceED Alice Bond Chan-Liu West Wesley Lithuania +1-333-285-8515 (715)759-3158x77103 jose92@peters.com 2024-05-30 http://www.marquez.com/
21 20 4d0c95579D095aF Cole Compton Calderon PLC Robertaville Saudi Arabia 029.862.3387x470 001-319-474-2394 sspence@dorsey.com 2020-08-02 http://hamilton.net/
-5
View File
@@ -1,5 +0,0 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}
-93
View File
@@ -1,93 +0,0 @@
const path = require('path');
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- 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.add(
'themeshot',
{
prevSubject: 'optional',
},
(subject, file, options) => {
cy.window().then(win => {
win.__changeCurrentTheme('theme-dark');
});
// cy.screenshot(`${file}-dark`, {
// onAfterScreenshot: (doc, props) => {
// cy.task('renameFile', {
// from: props.path,
// to: path.resolve(__dirname, `../../screenshots/${file}-dark.png`),
// });
// // fs.rename(props.path, path.resolve(path.join(__dirname, `../../screenshots/${file}-dark.png`)));
// },
// });
if (subject) {
cy.wrap(subject).screenshot(`${file}-dark`, options);
} else {
cy.screenshot(`${file}-dark`, options);
}
// .then(props => {
// return cy.task('renameFile', {
// from: props.path,
// to: path.resolve(__dirname, `../../screenshots/${file}-dark.png`),
// });
// });
cy.window().then(win => {
win.__changeCurrentTheme('theme-light');
});
if (subject) {
cy.wrap(subject).screenshot(`${file}-light`, options);
} else {
cy.screenshot(`${file}-light`, options);
}
// .then(props => {
// return cy.task('renameFile', {
// from: props.path,
// to: path.resolve(__dirname, `../../screenshots/${file}-light.png`),
// });
// });
// cy.screenshot(`${file}-light`, {
// onAfterScreenshot: (doc, props) => {
// cy.task('renameFile', {
// from: props.path,
// to: path.resolve(__dirname, `../../screenshots/${file}-light.png`),
// });
// // fs.rename(props.path, path.resolve(path.join(__dirname, `../../screenshots/${file}-light.png`)));
// },
// });
}
);
-52
View File
@@ -1,52 +0,0 @@
// ***********************************************************
// This example support/e2e.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
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();
};
});
});
});
// Cypress.Screenshot.defaults({
// onBeforeScreenshot() {
// if (window.Chart) {
// Object.values(window.Chart.instances).forEach(c => c.resize());
// }
// },
// });
@@ -1,6 +0,0 @@
{"__isStreamHeader":true,"pureName":"departments","schemaName":"dbo","objectId":1205579333,"createDate":"2025-06-12T10:30:34.083Z","modifyDate":"2025-06-12T10:30:34.120Z","contentHash":"2025-06-12T10:30:34.120Z","columns":[{"columnName":"id","dataType":"int","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"name","dataType":"varchar(100)","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false}],"primaryKey":{"constraintName":"PK__departme__3213E83FE8E7043D","schemaName":"dbo","pureName":"departments","constraintType":"primaryKey","columns":[{"columnName":"id"}]},"foreignKeys":[],"indexes":[],"uniques":[],"engine":"mssql@dbgate-plugin-mssql"}
{"id":1,"name":"IT"}
{"id":2,"name":"Marketing"}
{"id":3,"name":"Finance"}
{"id":4,"name":"Human Resources"}
{"id":5,"name":"Research and Development"}
@@ -1,12 +0,0 @@
name: departments
columns:
- name: id
type: int
default: null
notNull: true
- name: name
type: varchar(100)
default: null
notNull: true
primaryKey:
- id
@@ -1,39 +0,0 @@
{"__isStreamHeader":true,"pureName":"employee_project","schemaName":"dbo","objectId":1333579789,"createDate":"2025-06-12T10:30:34.133Z","modifyDate":"2025-06-12T10:30:34.133Z","contentHash":"2025-06-12T10:30:34.133Z","columns":[{"columnName":"employee_id","dataType":"int","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"project_id","dataType":"int","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"role","dataType":"varchar(50)","notNull":false,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false}],"primaryKey":{"constraintName":"PK__employee__2EE9924949ED9668","schemaName":"dbo","pureName":"employee_project","constraintType":"primaryKey","columns":[{"columnName":"employee_id"},{"columnName":"project_id"}]},"foreignKeys":[{"constraintName":"FK__employee___emplo__5165187F","constraintType":"foreignKey","schemaName":"dbo","pureName":"employee_project","refSchemaName":"dbo","refTableName":"employees","updateAction":"NO ACTION","deleteAction":"NO ACTION","columns":[{"columnName":"employee_id","refColumnName":"id"}]},{"constraintName":"FK__employee___proje__52593CB8","constraintType":"foreignKey","schemaName":"dbo","pureName":"employee_project","refSchemaName":"dbo","refTableName":"projects","updateAction":"NO ACTION","deleteAction":"NO ACTION","columns":[{"columnName":"project_id","refColumnName":"id"}]}],"indexes":[],"uniques":[],"engine":"mssql@dbgate-plugin-mssql"}
{"employee_id":1,"project_id":6,"role":"Manager"}
{"employee_id":1,"project_id":8,"role":"Developer"}
{"employee_id":2,"project_id":7,"role":"Tester"}
{"employee_id":2,"project_id":8,"role":"Developer"}
{"employee_id":3,"project_id":4,"role":"Analyst"}
{"employee_id":3,"project_id":6,"role":"Developer"}
{"employee_id":4,"project_id":2,"role":"Manager"}
{"employee_id":4,"project_id":4,"role":"Analyst"}
{"employee_id":4,"project_id":5,"role":"Analyst"}
{"employee_id":5,"project_id":5,"role":"Tester"}
{"employee_id":6,"project_id":1,"role":"Analyst"}
{"employee_id":6,"project_id":6,"role":"Tester"}
{"employee_id":6,"project_id":9,"role":"Manager"}
{"employee_id":7,"project_id":8,"role":"Manager"}
{"employee_id":8,"project_id":10,"role":"Analyst"}
{"employee_id":9,"project_id":2,"role":"Analyst"}
{"employee_id":9,"project_id":6,"role":"Analyst"}
{"employee_id":9,"project_id":7,"role":"Developer"}
{"employee_id":10,"project_id":2,"role":"Manager"}
{"employee_id":10,"project_id":6,"role":"Analyst"}
{"employee_id":11,"project_id":1,"role":"Tester"}
{"employee_id":12,"project_id":4,"role":"Tester"}
{"employee_id":13,"project_id":2,"role":"Developer"}
{"employee_id":13,"project_id":3,"role":"Analyst"}
{"employee_id":13,"project_id":7,"role":"Developer"}
{"employee_id":14,"project_id":3,"role":"Developer"}
{"employee_id":14,"project_id":9,"role":"Manager"}
{"employee_id":15,"project_id":1,"role":"Developer"}
{"employee_id":15,"project_id":5,"role":"Manager"}
{"employee_id":16,"project_id":3,"role":"Tester"}
{"employee_id":16,"project_id":5,"role":"Developer"}
{"employee_id":17,"project_id":6,"role":"Analyst"}
{"employee_id":18,"project_id":1,"role":"Tester"}
{"employee_id":18,"project_id":5,"role":"Tester"}
{"employee_id":18,"project_id":6,"role":"Manager"}
{"employee_id":19,"project_id":6,"role":"Analyst"}
{"employee_id":20,"project_id":2,"role":"Developer"}
{"employee_id":20,"project_id":4,"role":"Developer"}
@@ -1,18 +0,0 @@
name: employee_project
columns:
- name: employee_id
type: int
default: null
notNull: true
references: employees
- name: project_id
type: int
default: null
notNull: true
references: projects
- name: role
type: varchar(50)
default: null
primaryKey:
- employee_id
- project_id
@@ -1,21 +0,0 @@
{"__isStreamHeader":true,"pureName":"employees","schemaName":"dbo","objectId":1237579447,"createDate":"2025-06-12T10:30:34.113Z","modifyDate":"2025-06-12T12:35:22.140Z","contentHash":"2025-06-12T12:35:22.140Z","columns":[{"columnName":"id","dataType":"int","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"name","dataType":"varchar(100)","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"email","dataType":"varchar(100)","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"hire_date","dataType":"date","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"department_id","dataType":"int","notNull":false,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false}],"primaryKey":{"constraintName":"PK__employee__3213E83FE576E55A","schemaName":"dbo","pureName":"employees","constraintType":"primaryKey","columns":[{"columnName":"id"}]},"foreignKeys":[{"constraintName":"FK__employees__depar__4CA06362","constraintType":"foreignKey","schemaName":"dbo","pureName":"employees","refSchemaName":"dbo","refTableName":"departments","updateAction":"NO ACTION","deleteAction":"NO ACTION","columns":[{"columnName":"department_id","refColumnName":"id"}]}],"indexes":[],"uniques":[{"constraintName":"UQ__employee__AB6E6164E18D883F","columns":[{"columnName":"email"}]}],"engine":"mssql@dbgate-plugin-mssql"}
{"id":1,"name":"John Smith","email":"john.smith@example.com","hire_date":"2018-07-09T00:00:00.000Z","department_id":2}
{"id":2,"name":"Jane Garcia","email":"jane.garcia@example.com","hire_date":"2019-10-13T00:00:00.000Z","department_id":5}
{"id":3,"name":"Grace Smith","email":"grace.smith@example.com","hire_date":"2019-03-16T00:00:00.000Z","department_id":1}
{"id":4,"name":"Charlie Williams","email":"charlie.williams@example.com","hire_date":"2020-10-18T00:00:00.000Z","department_id":2}
{"id":5,"name":"Eve Brown","email":"eve.brown@example.com","hire_date":"2018-04-12T00:00:00.000Z","department_id":4}
{"id":6,"name":"Alice Moore","email":"alice.moore@example.com","hire_date":"2019-04-20T00:00:00.000Z","department_id":2}
{"id":7,"name":"Eve Williams","email":"eve.williams@example.com","hire_date":"2020-04-26T00:00:00.000Z","department_id":4}
{"id":8,"name":"Eve Jones","email":"eve.jones@example.com","hire_date":"2022-10-04T00:00:00.000Z","department_id":3}
{"id":9,"name":"Diana Miller","email":"diana.miller@example.com","hire_date":"2021-03-28T00:00:00.000Z","department_id":1}
{"id":10,"name":"Diana Smith","email":"diana.smith@example.com","hire_date":"2018-04-12T00:00:00.000Z","department_id":2}
{"id":11,"name":"Hank Johnson","email":"hank.johnson@example.com","hire_date":"2020-09-16T00:00:00.000Z","department_id":2}
{"id":12,"name":"Frank Miller","email":"frank.miller@example.com","hire_date":"2023-01-12T00:00:00.000Z","department_id":4}
{"id":13,"name":"Jane Brown","email":"jane.brown@example.com","hire_date":"2023-05-07T00:00:00.000Z","department_id":3}
{"id":14,"name":"Grace Davis","email":"grace.davis@example.com","hire_date":"2019-08-22T00:00:00.000Z","department_id":3}
{"id":15,"name":"Jane Black","email":"jane.black@example.com","hire_date":"2019-04-28T00:00:00.000Z","department_id":2}
{"id":16,"name":"Charlie Smith","email":"charlie.smith@example.com","hire_date":"2019-06-12T00:00:00.000Z","department_id":5}
{"id":17,"name":"Eve Johnson","email":"eve.johnson@example.com","hire_date":"2020-11-07T00:00:00.000Z","department_id":5}
{"id":18,"name":"Jane Johnson","email":"jane.johnson@example.com","hire_date":"2020-04-06T00:00:00.000Z","department_id":2}
{"id":19,"name":"Hank Brown","email":"hank.brown@example.com","hire_date":"2023-05-10T00:00:00.000Z","department_id":2}
{"id":20,"name":"Frank Jones","email":"frank.jones@example.com","hire_date":"2020-10-26T00:00:00.000Z","department_id":1}
@@ -1,28 +0,0 @@
name: employees
columns:
- name: id
type: int
default: null
notNull: true
- name: name
type: varchar(100)
default: null
notNull: true
- name: email
type: varchar(100)
default: null
notNull: true
- name: hire_date
type: date
default: null
notNull: true
- name: department_id
type: int
default: null
references: departments
primaryKey:
- id
uniques:
- name: UQ__employee__AB6E6164E18D883F
columns:
- email
@@ -1,141 +0,0 @@
{"__isStreamHeader":true,"pureName":"finance_reports","schemaName":"dbo","objectId":338100245,"createDate":"2025-06-23T12:15:08.727Z","modifyDate":"2025-06-23T12:15:08.750Z","contentHash":"2025-06-23T12:15:08.750Z","columns":[{"columnName":"id","dataType":"int","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"date","dataType":"date","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"profit","dataType":"money","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false}],"foreignKeys":[{"constraintName":"project_id","constraintType":"foreignKey","schemaName":"dbo","pureName":"finance_reports","refSchemaName":"dbo","refTableName":"projects","updateAction":"NO ACTION","deleteAction":"NO ACTION","columns":[{"columnName":"id","refColumnName":"id"}]}],"indexes":[],"uniques":[],"engine":"mssql@dbgate-plugin-mssql"}
{"id":1,"date":"2022-01-01T00:00:00.000Z","profit":73923.4}
{"id":1,"date":"2022-01-31T00:00:00.000Z","profit":21837.75}
{"id":1,"date":"2022-03-02T00:00:00.000Z","profit":67859.8}
{"id":1,"date":"2022-04-01T00:00:00.000Z","profit":77403.3}
{"id":1,"date":"2022-05-01T00:00:00.000Z","profit":84083.19}
{"id":1,"date":"2022-05-31T00:00:00.000Z","profit":30040.55}
{"id":1,"date":"2022-06-30T00:00:00.000Z","profit":50947.14}
{"id":1,"date":"2022-07-30T00:00:00.000Z","profit":63345.62}
{"id":1,"date":"2022-08-29T00:00:00.000Z","profit":23819.45}
{"id":1,"date":"2022-09-28T00:00:00.000Z","profit":-25919.19}
{"id":1,"date":"2022-10-28T00:00:00.000Z","profit":27967.6}
{"id":1,"date":"2022-11-27T00:00:00.000Z","profit":-37402.36}
{"id":1,"date":"2022-12-27T00:00:00.000Z","profit":94528.8}
{"id":1,"date":"2023-01-26T00:00:00.000Z","profit":29491.03}
{"id":1,"date":"2023-02-25T00:00:00.000Z","profit":81541.29}
{"id":2,"date":"2022-01-01T00:00:00.000Z","profit":18070.94}
{"id":2,"date":"2022-01-31T00:00:00.000Z","profit":-40609.87}
{"id":2,"date":"2022-03-02T00:00:00.000Z","profit":42435.51}
{"id":2,"date":"2022-04-01T00:00:00.000Z","profit":-11915.15}
{"id":2,"date":"2022-05-01T00:00:00.000Z","profit":-37417.4}
{"id":2,"date":"2022-05-31T00:00:00.000Z","profit":23028.66}
{"id":2,"date":"2022-06-30T00:00:00.000Z","profit":-6895.49}
{"id":2,"date":"2022-07-30T00:00:00.000Z","profit":63114.54}
{"id":2,"date":"2022-08-29T00:00:00.000Z","profit":94646.99}
{"id":2,"date":"2022-09-28T00:00:00.000Z","profit":99560.77}
{"id":2,"date":"2022-10-28T00:00:00.000Z","profit":62216.22}
{"id":2,"date":"2022-11-27T00:00:00.000Z","profit":85094.32}
{"id":2,"date":"2022-12-27T00:00:00.000Z","profit":-23378.37}
{"id":2,"date":"2023-01-26T00:00:00.000Z","profit":47635.86}
{"id":2,"date":"2023-02-25T00:00:00.000Z","profit":33727.72}
{"id":3,"date":"2022-01-01T00:00:00.000Z","profit":33088.03}
{"id":3,"date":"2022-01-31T00:00:00.000Z","profit":66668.91}
{"id":3,"date":"2022-03-02T00:00:00.000Z","profit":5344.27}
{"id":3,"date":"2022-04-01T00:00:00.000Z","profit":22122.99}
{"id":3,"date":"2022-05-01T00:00:00.000Z","profit":27342.01}
{"id":3,"date":"2022-05-31T00:00:00.000Z","profit":55479.42}
{"id":3,"date":"2022-06-30T00:00:00.000Z","profit":35956.11}
{"id":3,"date":"2022-07-30T00:00:00.000Z","profit":9667.12}
{"id":3,"date":"2022-08-29T00:00:00.000Z","profit":63430.18}
{"id":3,"date":"2022-09-28T00:00:00.000Z","profit":-4883.41}
{"id":3,"date":"2022-10-28T00:00:00.000Z","profit":38902.8}
{"id":3,"date":"2022-11-27T00:00:00.000Z","profit":-25500.13}
{"id":3,"date":"2022-12-27T00:00:00.000Z","profit":65074.21}
{"id":3,"date":"2023-01-26T00:00:00.000Z","profit":12570.27}
{"id":3,"date":"2023-02-25T00:00:00.000Z","profit":35418.36}
{"id":4,"date":"2022-01-01T00:00:00.000Z","profit":68282.98}
{"id":4,"date":"2022-01-31T00:00:00.000Z","profit":77778.99}
{"id":4,"date":"2022-03-02T00:00:00.000Z","profit":95490.49}
{"id":4,"date":"2022-04-01T00:00:00.000Z","profit":-44466.37}
{"id":4,"date":"2022-05-01T00:00:00.000Z","profit":40215.71}
{"id":4,"date":"2022-05-31T00:00:00.000Z","profit":-31228.87}
{"id":4,"date":"2022-06-30T00:00:00.000Z","profit":60667.69}
{"id":4,"date":"2022-07-30T00:00:00.000Z","profit":71439.16}
{"id":4,"date":"2022-08-29T00:00:00.000Z","profit":-25077.4}
{"id":4,"date":"2022-09-28T00:00:00.000Z","profit":-36128.2}
{"id":4,"date":"2022-10-28T00:00:00.000Z","profit":36727.68}
{"id":4,"date":"2022-11-27T00:00:00.000Z","profit":-24207.2}
{"id":4,"date":"2022-12-27T00:00:00.000Z","profit":63846.96}
{"id":5,"date":"2022-01-01T00:00:00.000Z","profit":21648.3}
{"id":5,"date":"2022-01-31T00:00:00.000Z","profit":59263.22}
{"id":5,"date":"2022-03-02T00:00:00.000Z","profit":49154.51}
{"id":5,"date":"2022-04-01T00:00:00.000Z","profit":34787.48}
{"id":5,"date":"2022-05-01T00:00:00.000Z","profit":-24120.19}
{"id":5,"date":"2022-05-31T00:00:00.000Z","profit":98437.86}
{"id":5,"date":"2022-06-30T00:00:00.000Z","profit":18614.77}
{"id":5,"date":"2022-07-30T00:00:00.000Z","profit":17680.34}
{"id":5,"date":"2022-08-29T00:00:00.000Z","profit":74406.86}
{"id":5,"date":"2022-09-28T00:00:00.000Z","profit":61845.3}
{"id":5,"date":"2022-10-28T00:00:00.000Z","profit":-37889.59}
{"id":5,"date":"2022-11-27T00:00:00.000Z","profit":76651.05}
{"id":5,"date":"2022-12-27T00:00:00.000Z","profit":58739.6}
{"id":5,"date":"2023-01-26T00:00:00.000Z","profit":82605.85}
{"id":6,"date":"2022-01-01T00:00:00.000Z","profit":-5206.8}
{"id":6,"date":"2022-01-31T00:00:00.000Z","profit":27498.27}
{"id":6,"date":"2022-03-02T00:00:00.000Z","profit":-2939.84}
{"id":6,"date":"2022-04-01T00:00:00.000Z","profit":-37261.08}
{"id":6,"date":"2022-05-01T00:00:00.000Z","profit":37069.04}
{"id":6,"date":"2022-05-31T00:00:00.000Z","profit":524.88}
{"id":6,"date":"2022-06-30T00:00:00.000Z","profit":-29620.85}
{"id":6,"date":"2022-07-30T00:00:00.000Z","profit":35540.81}
{"id":6,"date":"2022-08-29T00:00:00.000Z","profit":20608.94}
{"id":6,"date":"2022-09-28T00:00:00.000Z","profit":34809.33}
{"id":6,"date":"2022-10-28T00:00:00.000Z","profit":-44949.05}
{"id":6,"date":"2022-11-27T00:00:00.000Z","profit":-22524.26}
{"id":6,"date":"2022-12-27T00:00:00.000Z","profit":37841.58}
{"id":7,"date":"2022-01-01T00:00:00.000Z","profit":6903.17}
{"id":7,"date":"2022-01-31T00:00:00.000Z","profit":58480.84}
{"id":7,"date":"2022-03-02T00:00:00.000Z","profit":48217.34}
{"id":7,"date":"2022-04-01T00:00:00.000Z","profit":73592.44}
{"id":7,"date":"2022-05-01T00:00:00.000Z","profit":-21831.18}
{"id":7,"date":"2022-05-31T00:00:00.000Z","profit":-40926.16}
{"id":7,"date":"2022-06-30T00:00:00.000Z","profit":62299.5}
{"id":7,"date":"2022-07-30T00:00:00.000Z","profit":95376.53}
{"id":7,"date":"2022-08-29T00:00:00.000Z","profit":-13317.36}
{"id":7,"date":"2022-09-28T00:00:00.000Z","profit":81565.05}
{"id":7,"date":"2022-10-28T00:00:00.000Z","profit":77420.52}
{"id":7,"date":"2022-11-27T00:00:00.000Z","profit":-12052.47}
{"id":7,"date":"2022-12-27T00:00:00.000Z","profit":37742.07}
{"id":7,"date":"2023-01-26T00:00:00.000Z","profit":-8057.99}
{"id":8,"date":"2022-01-01T00:00:00.000Z","profit":27213.73}
{"id":8,"date":"2022-01-31T00:00:00.000Z","profit":34271.75}
{"id":8,"date":"2022-03-02T00:00:00.000Z","profit":-44549.47}
{"id":8,"date":"2022-04-01T00:00:00.000Z","profit":15236.34}
{"id":8,"date":"2022-05-01T00:00:00.000Z","profit":-27759.81}
{"id":8,"date":"2022-05-31T00:00:00.000Z","profit":7955.12}
{"id":8,"date":"2022-06-30T00:00:00.000Z","profit":-34484.38}
{"id":8,"date":"2022-07-30T00:00:00.000Z","profit":-49758.7}
{"id":8,"date":"2022-08-29T00:00:00.000Z","profit":-41990.86}
{"id":8,"date":"2022-09-28T00:00:00.000Z","profit":58123.01}
{"id":8,"date":"2022-10-28T00:00:00.000Z","profit":30128.78}
{"id":8,"date":"2022-11-27T00:00:00.000Z","profit":-10151.17}
{"id":8,"date":"2022-12-27T00:00:00.000Z","profit":54048.33}
{"id":8,"date":"2023-01-26T00:00:00.000Z","profit":-43123.17}
{"id":9,"date":"2022-01-01T00:00:00.000Z","profit":61031.83}
{"id":9,"date":"2022-01-31T00:00:00.000Z","profit":68577.58}
{"id":9,"date":"2022-03-02T00:00:00.000Z","profit":88698.97}
{"id":9,"date":"2022-04-01T00:00:00.000Z","profit":8906.03}
{"id":9,"date":"2022-05-01T00:00:00.000Z","profit":28824.73}
{"id":9,"date":"2022-05-31T00:00:00.000Z","profit":88280.34}
{"id":9,"date":"2022-06-30T00:00:00.000Z","profit":35266.09}
{"id":9,"date":"2022-07-30T00:00:00.000Z","profit":-38025.36}
{"id":9,"date":"2022-08-29T00:00:00.000Z","profit":-12118.53}
{"id":9,"date":"2022-09-28T00:00:00.000Z","profit":-27265.86}
{"id":9,"date":"2022-10-28T00:00:00.000Z","profit":56870.57}
{"id":9,"date":"2022-11-27T00:00:00.000Z","profit":88078.95}
{"id":9,"date":"2022-12-27T00:00:00.000Z","profit":-24059.67}
{"id":9,"date":"2023-01-26T00:00:00.000Z","profit":-13301.43}
{"id":10,"date":"2022-01-01T00:00:00.000Z","profit":-22479.23}
{"id":10,"date":"2022-01-31T00:00:00.000Z","profit":8106.27}
{"id":10,"date":"2022-03-02T00:00:00.000Z","profit":69372.19}
{"id":10,"date":"2022-04-01T00:00:00.000Z","profit":-11895.74}
{"id":10,"date":"2022-05-01T00:00:00.000Z","profit":-33206.5}
{"id":10,"date":"2022-05-31T00:00:00.000Z","profit":56073.34}
{"id":10,"date":"2022-06-30T00:00:00.000Z","profit":67488.3}
{"id":10,"date":"2022-07-30T00:00:00.000Z","profit":48529.23}
{"id":10,"date":"2022-08-29T00:00:00.000Z","profit":28680.2}
{"id":10,"date":"2022-09-28T00:00:00.000Z","profit":59311.16}
{"id":10,"date":"2022-10-28T00:00:00.000Z","profit":25315.78}
{"id":10,"date":"2022-11-27T00:00:00.000Z","profit":36116.38}
{"id":10,"date":"2022-12-27T00:00:00.000Z","profit":-42040.4}
@@ -1,15 +0,0 @@
name: finance_reports
columns:
- name: id
type: int
default: null
notNull: true
references: projects
- name: date
type: date
default: null
notNull: true
- name: profit
type: money
default: null
notNull: true
@@ -1,11 +0,0 @@
{"__isStreamHeader":true,"pureName":"projects","schemaName":"dbo","objectId":1301579675,"createDate":"2025-06-12T10:30:34.127Z","modifyDate":"2025-06-23T12:15:08.750Z","contentHash":"2025-06-23T12:15:08.750Z","columns":[{"columnName":"id","dataType":"int","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"name","dataType":"varchar(100)","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"start_date","dataType":"date","notNull":false,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"end_date","dataType":"date","notNull":false,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false}],"primaryKey":{"constraintName":"PK__projects__3213E83F26A7ED11","schemaName":"dbo","pureName":"projects","constraintType":"primaryKey","columns":[{"columnName":"id"}]},"foreignKeys":[],"indexes":[],"uniques":[],"engine":"mssql@dbgate-plugin-mssql"}
{"id":1,"name":"Apollo Upgrade","start_date":"2020-04-27T00:00:00.000Z","end_date":"2020-10-19T00:00:00.000Z"}
{"id":2,"name":"Market Expansion","start_date":"2022-08-04T00:00:00.000Z","end_date":"2023-06-20T00:00:00.000Z"}
{"id":3,"name":"AI Integration","start_date":"2020-05-11T00:00:00.000Z","end_date":"2021-07-10T00:00:00.000Z"}
{"id":4,"name":"Cost Reduction","start_date":"2022-01-08T00:00:00.000Z","end_date":"2022-07-12T00:00:00.000Z"}
{"id":5,"name":"Cloud Migration","start_date":"2021-01-11T00:00:00.000Z","end_date":"2021-05-27T00:00:00.000Z"}
{"id":6,"name":"Customer Portal","start_date":"2021-07-13T00:00:00.000Z","end_date":"2022-09-22T00:00:00.000Z"}
{"id":7,"name":"Data Lake","start_date":"2021-02-25T00:00:00.000Z","end_date":"2021-08-21T00:00:00.000Z"}
{"id":8,"name":"UX Overhaul","start_date":"2021-05-20T00:00:00.000Z","end_date":"2022-09-10T00:00:00.000Z"}
{"id":9,"name":"Security Hardening","start_date":"2021-05-28T00:00:00.000Z","end_date":"2022-07-28T00:00:00.000Z"}
{"id":10,"name":"Mobile App Revamp","start_date":"2021-11-17T00:00:00.000Z","end_date":"2022-06-04T00:00:00.000Z"}
@@ -1,18 +0,0 @@
name: projects
columns:
- name: id
type: int
default: null
notNull: true
- name: name
type: varchar(100)
default: null
notNull: true
- name: start_date
type: date
default: null
- name: end_date
type: date
default: null
primaryKey:
- id
-347
View File
@@ -1,347 +0,0 @@
{"AlbumId":1,"Title":"For Those About To Rock We Salute You","ArtistId":1}
{"AlbumId":2,"Title":"Balls to the Wall","ArtistId":2}
{"AlbumId":3,"Title":"Restless and Wild","ArtistId":2}
{"AlbumId":4,"Title":"Let There Be Rock","ArtistId":1}
{"AlbumId":5,"Title":"Big Ones","ArtistId":3}
{"AlbumId":6,"Title":"Jagged Little Pill","ArtistId":4}
{"AlbumId":7,"Title":"Facelift","ArtistId":5}
{"AlbumId":8,"Title":"Warner 25 Anos","ArtistId":6}
{"AlbumId":9,"Title":"Plays Metallica By Four Cellos","ArtistId":7}
{"AlbumId":10,"Title":"Audioslave","ArtistId":8}
{"AlbumId":11,"Title":"Out Of Exile","ArtistId":8}
{"AlbumId":12,"Title":"BackBeat Soundtrack","ArtistId":9}
{"AlbumId":13,"Title":"The Best Of Billy Cobham","ArtistId":10}
{"AlbumId":14,"Title":"Alcohol Fueled Brewtality Live! [Disc 1]","ArtistId":11}
{"AlbumId":15,"Title":"Alcohol Fueled Brewtality Live! [Disc 2]","ArtistId":11}
{"AlbumId":16,"Title":"Black Sabbath","ArtistId":12}
{"AlbumId":17,"Title":"Black Sabbath Vol. 4 (Remaster)","ArtistId":12}
{"AlbumId":18,"Title":"Body Count","ArtistId":13}
{"AlbumId":19,"Title":"Chemical Wedding","ArtistId":14}
{"AlbumId":20,"Title":"The Best Of Buddy Guy - The Millenium Collection","ArtistId":15}
{"AlbumId":21,"Title":"Prenda Minha","ArtistId":16}
{"AlbumId":22,"Title":"Sozinho Remix Ao Vivo","ArtistId":16}
{"AlbumId":23,"Title":"Minha Historia","ArtistId":17}
{"AlbumId":24,"Title":"Afrociberdelia","ArtistId":18}
{"AlbumId":25,"Title":"Da Lama Ao Caos","ArtistId":18}
{"AlbumId":26,"Title":"Acústico MTV [Live]","ArtistId":19}
{"AlbumId":27,"Title":"Cidade Negra - Hits","ArtistId":19}
{"AlbumId":28,"Title":"Na Pista","ArtistId":20}
{"AlbumId":29,"Title":"Axé Bahia 2001","ArtistId":21}
{"AlbumId":30,"Title":"BBC Sessions [Disc 1] [Live]","ArtistId":22}
{"AlbumId":31,"Title":"Bongo Fury","ArtistId":23}
{"AlbumId":32,"Title":"Carnaval 2001","ArtistId":21}
{"AlbumId":33,"Title":"Chill: Brazil (Disc 1)","ArtistId":24}
{"AlbumId":34,"Title":"Chill: Brazil (Disc 2)","ArtistId":6}
{"AlbumId":35,"Title":"Garage Inc. (Disc 1)","ArtistId":50}
{"AlbumId":36,"Title":"Greatest Hits II","ArtistId":51}
{"AlbumId":37,"Title":"Greatest Kiss","ArtistId":52}
{"AlbumId":38,"Title":"Heart of the Night","ArtistId":53}
{"AlbumId":39,"Title":"International Superhits","ArtistId":54}
{"AlbumId":40,"Title":"Into The Light","ArtistId":55}
{"AlbumId":41,"Title":"Meus Momentos","ArtistId":56}
{"AlbumId":42,"Title":"Minha História","ArtistId":57}
{"AlbumId":43,"Title":"MK III The Final Concerts [Disc 1]","ArtistId":58}
{"AlbumId":44,"Title":"Physical Graffiti [Disc 1]","ArtistId":22}
{"AlbumId":45,"Title":"Sambas De Enredo 2001","ArtistId":21}
{"AlbumId":46,"Title":"Supernatural","ArtistId":59}
{"AlbumId":47,"Title":"The Best of Ed Motta","ArtistId":37}
{"AlbumId":48,"Title":"The Essential Miles Davis [Disc 1]","ArtistId":68}
{"AlbumId":49,"Title":"The Essential Miles Davis [Disc 2]","ArtistId":68}
{"AlbumId":50,"Title":"The Final Concerts (Disc 2)","ArtistId":58}
{"AlbumId":51,"Title":"Up An' Atom","ArtistId":69}
{"AlbumId":52,"Title":"Vinícius De Moraes - Sem Limite","ArtistId":70}
{"AlbumId":53,"Title":"Vozes do MPB","ArtistId":21}
{"AlbumId":54,"Title":"Chronicle, Vol. 1","ArtistId":76}
{"AlbumId":55,"Title":"Chronicle, Vol. 2","ArtistId":76}
{"AlbumId":56,"Title":"Cássia Eller - Coleçăo Sem Limite [Disc 2]","ArtistId":77}
{"AlbumId":57,"Title":"Cássia Eller - Sem Limite [Disc 1]","ArtistId":77}
{"AlbumId":58,"Title":"Come Taste The Band","ArtistId":58}
{"AlbumId":59,"Title":"Deep Purple In Rock","ArtistId":58}
{"AlbumId":60,"Title":"Fireball","ArtistId":58}
{"AlbumId":61,"Title":"Knocking at Your Back Door: The Best Of Deep Purple in the 80's","ArtistId":58}
{"AlbumId":62,"Title":"Machine Head","ArtistId":58}
{"AlbumId":63,"Title":"Purpendicular","ArtistId":58}
{"AlbumId":64,"Title":"Slaves And Masters","ArtistId":58}
{"AlbumId":65,"Title":"Stormbringer","ArtistId":58}
{"AlbumId":66,"Title":"The Battle Rages On","ArtistId":58}
{"AlbumId":67,"Title":"Vault: Def Leppard's Greatest Hits","ArtistId":78}
{"AlbumId":68,"Title":"Outbreak","ArtistId":79}
{"AlbumId":69,"Title":"Djavan Ao Vivo - Vol. 02","ArtistId":80}
{"AlbumId":70,"Title":"Djavan Ao Vivo - Vol. 1","ArtistId":80}
{"AlbumId":71,"Title":"Elis Regina-Minha História","ArtistId":41}
{"AlbumId":72,"Title":"The Cream Of Clapton","ArtistId":81}
{"AlbumId":73,"Title":"Unplugged","ArtistId":81}
{"AlbumId":74,"Title":"Album Of The Year","ArtistId":82}
{"AlbumId":75,"Title":"Angel Dust","ArtistId":82}
{"AlbumId":76,"Title":"King For A Day Fool For A Lifetime","ArtistId":82}
{"AlbumId":77,"Title":"The Real Thing","ArtistId":82}
{"AlbumId":78,"Title":"Deixa Entrar","ArtistId":83}
{"AlbumId":79,"Title":"In Your Honor [Disc 1]","ArtistId":84}
{"AlbumId":80,"Title":"In Your Honor [Disc 2]","ArtistId":84}
{"AlbumId":81,"Title":"One By One","ArtistId":84}
{"AlbumId":82,"Title":"The Colour And The Shape","ArtistId":84}
{"AlbumId":83,"Title":"My Way: The Best Of Frank Sinatra [Disc 1]","ArtistId":85}
{"AlbumId":84,"Title":"Roda De Funk","ArtistId":86}
{"AlbumId":85,"Title":"As Cançőes de Eu Tu Eles","ArtistId":27}
{"AlbumId":86,"Title":"Quanta Gente Veio Ver (Live)","ArtistId":27}
{"AlbumId":87,"Title":"Quanta Gente Veio ver--Bônus De Carnaval","ArtistId":27}
{"AlbumId":88,"Title":"Faceless","ArtistId":87}
{"AlbumId":89,"Title":"American Idiot","ArtistId":54}
{"AlbumId":90,"Title":"Appetite for Destruction","ArtistId":88}
{"AlbumId":91,"Title":"Use Your Illusion I","ArtistId":88}
{"AlbumId":92,"Title":"Use Your Illusion II","ArtistId":88}
{"AlbumId":93,"Title":"Blue Moods","ArtistId":89}
{"AlbumId":94,"Title":"A Matter of Life and Death","ArtistId":90}
{"AlbumId":95,"Title":"A Real Dead One","ArtistId":90}
{"AlbumId":96,"Title":"A Real Live One","ArtistId":90}
{"AlbumId":97,"Title":"Brave New World","ArtistId":90}
{"AlbumId":98,"Title":"Dance Of Death","ArtistId":90}
{"AlbumId":99,"Title":"Fear Of The Dark","ArtistId":90}
{"AlbumId":100,"Title":"Iron Maiden","ArtistId":90}
{"AlbumId":101,"Title":"Killers","ArtistId":90}
{"AlbumId":102,"Title":"Live After Death","ArtistId":90}
{"AlbumId":103,"Title":"Live At Donington 1992 (Disc 1)","ArtistId":90}
{"AlbumId":104,"Title":"Live At Donington 1992 (Disc 2)","ArtistId":90}
{"AlbumId":105,"Title":"No Prayer For The Dying","ArtistId":90}
{"AlbumId":106,"Title":"Piece Of Mind","ArtistId":90}
{"AlbumId":107,"Title":"Powerslave","ArtistId":90}
{"AlbumId":108,"Title":"Rock In Rio [CD1]","ArtistId":90}
{"AlbumId":109,"Title":"Rock In Rio [CD2]","ArtistId":90}
{"AlbumId":110,"Title":"Seventh Son of a Seventh Son","ArtistId":90}
{"AlbumId":111,"Title":"Somewhere in Time","ArtistId":90}
{"AlbumId":112,"Title":"The Number of The Beast","ArtistId":90}
{"AlbumId":113,"Title":"The X Factor","ArtistId":90}
{"AlbumId":114,"Title":"Virtual XI","ArtistId":90}
{"AlbumId":115,"Title":"Sex Machine","ArtistId":91}
{"AlbumId":116,"Title":"Emergency On Planet Earth","ArtistId":92}
{"AlbumId":117,"Title":"Synkronized","ArtistId":92}
{"AlbumId":118,"Title":"The Return Of The Space Cowboy","ArtistId":92}
{"AlbumId":119,"Title":"Get Born","ArtistId":93}
{"AlbumId":120,"Title":"Are You Experienced?","ArtistId":94}
{"AlbumId":121,"Title":"Surfing with the Alien (Remastered)","ArtistId":95}
{"AlbumId":122,"Title":"Jorge Ben Jor 25 Anos","ArtistId":46}
{"AlbumId":123,"Title":"Jota Quest-1995","ArtistId":96}
{"AlbumId":124,"Title":"Cafezinho","ArtistId":97}
{"AlbumId":125,"Title":"Living After Midnight","ArtistId":98}
{"AlbumId":126,"Title":"Unplugged [Live]","ArtistId":52}
{"AlbumId":127,"Title":"BBC Sessions [Disc 2] [Live]","ArtistId":22}
{"AlbumId":128,"Title":"Coda","ArtistId":22}
{"AlbumId":129,"Title":"Houses Of The Holy","ArtistId":22}
{"AlbumId":130,"Title":"In Through The Out Door","ArtistId":22}
{"AlbumId":131,"Title":"IV","ArtistId":22}
{"AlbumId":132,"Title":"Led Zeppelin I","ArtistId":22}
{"AlbumId":133,"Title":"Led Zeppelin II","ArtistId":22}
{"AlbumId":134,"Title":"Led Zeppelin III","ArtistId":22}
{"AlbumId":135,"Title":"Physical Graffiti [Disc 2]","ArtistId":22}
{"AlbumId":136,"Title":"Presence","ArtistId":22}
{"AlbumId":137,"Title":"The Song Remains The Same (Disc 1)","ArtistId":22}
{"AlbumId":138,"Title":"The Song Remains The Same (Disc 2)","ArtistId":22}
{"AlbumId":139,"Title":"A TempestadeTempestade Ou O Livro Dos Dias","ArtistId":99}
{"AlbumId":140,"Title":"Mais Do Mesmo","ArtistId":99}
{"AlbumId":141,"Title":"Greatest Hits","ArtistId":100}
{"AlbumId":142,"Title":"Lulu Santos - RCA 100 Anos De Música - Álbum 01","ArtistId":101}
{"AlbumId":143,"Title":"Lulu Santos - RCA 100 Anos De Música - Álbum 02","ArtistId":101}
{"AlbumId":144,"Title":"Misplaced Childhood","ArtistId":102}
{"AlbumId":145,"Title":"Barulhinho Bom","ArtistId":103}
{"AlbumId":146,"Title":"Seek And Shall Find: More Of The Best (1963-1981)","ArtistId":104}
{"AlbumId":147,"Title":"The Best Of Men At Work","ArtistId":105}
{"AlbumId":148,"Title":"Black Album","ArtistId":50}
{"AlbumId":149,"Title":"Garage Inc. (Disc 2)","ArtistId":50}
{"AlbumId":150,"Title":"Kill 'Em All","ArtistId":50}
{"AlbumId":151,"Title":"Load","ArtistId":50}
{"AlbumId":152,"Title":"Master Of Puppets","ArtistId":50}
{"AlbumId":153,"Title":"ReLoad","ArtistId":50}
{"AlbumId":154,"Title":"Ride The Lightning","ArtistId":50}
{"AlbumId":155,"Title":"St. Anger","ArtistId":50}
{"AlbumId":156,"Title":"...And Justice For All","ArtistId":50}
{"AlbumId":157,"Title":"Miles Ahead","ArtistId":68}
{"AlbumId":158,"Title":"Milton Nascimento Ao Vivo","ArtistId":42}
{"AlbumId":159,"Title":"Minas","ArtistId":42}
{"AlbumId":160,"Title":"Ace Of Spades","ArtistId":106}
{"AlbumId":161,"Title":"Demorou...","ArtistId":108}
{"AlbumId":162,"Title":"Motley Crue Greatest Hits","ArtistId":109}
{"AlbumId":163,"Title":"From The Muddy Banks Of The Wishkah [Live]","ArtistId":110}
{"AlbumId":164,"Title":"Nevermind","ArtistId":110}
{"AlbumId":165,"Title":"Compositores","ArtistId":111}
{"AlbumId":166,"Title":"Olodum","ArtistId":112}
{"AlbumId":167,"Title":"Acústico MTV","ArtistId":113}
{"AlbumId":168,"Title":"Arquivo II","ArtistId":113}
{"AlbumId":169,"Title":"Arquivo Os Paralamas Do Sucesso","ArtistId":113}
{"AlbumId":170,"Title":"Bark at the Moon (Remastered)","ArtistId":114}
{"AlbumId":171,"Title":"Blizzard of Ozz","ArtistId":114}
{"AlbumId":172,"Title":"Diary of a Madman (Remastered)","ArtistId":114}
{"AlbumId":173,"Title":"No More Tears (Remastered)","ArtistId":114}
{"AlbumId":174,"Title":"Tribute","ArtistId":114}
{"AlbumId":175,"Title":"Walking Into Clarksdale","ArtistId":115}
{"AlbumId":176,"Title":"Original Soundtracks 1","ArtistId":116}
{"AlbumId":177,"Title":"The Beast Live","ArtistId":117}
{"AlbumId":178,"Title":"Live On Two Legs [Live]","ArtistId":118}
{"AlbumId":179,"Title":"Pearl Jam","ArtistId":118}
{"AlbumId":180,"Title":"Riot Act","ArtistId":118}
{"AlbumId":181,"Title":"Ten","ArtistId":118}
{"AlbumId":182,"Title":"Vs.","ArtistId":118}
{"AlbumId":183,"Title":"Dark Side Of The Moon","ArtistId":120}
{"AlbumId":184,"Title":"Os Căes Ladram Mas A Caravana Năo Pára","ArtistId":121}
{"AlbumId":185,"Title":"Greatest Hits I","ArtistId":51}
{"AlbumId":186,"Title":"News Of The World","ArtistId":51}
{"AlbumId":187,"Title":"Out Of Time","ArtistId":122}
{"AlbumId":188,"Title":"Green","ArtistId":124}
{"AlbumId":189,"Title":"New Adventures In Hi-Fi","ArtistId":124}
{"AlbumId":190,"Title":"The Best Of R.E.M.: The IRS Years","ArtistId":124}
{"AlbumId":191,"Title":"Cesta Básica","ArtistId":125}
{"AlbumId":192,"Title":"Raul Seixas","ArtistId":126}
{"AlbumId":193,"Title":"Blood Sugar Sex Magik","ArtistId":127}
{"AlbumId":194,"Title":"By The Way","ArtistId":127}
{"AlbumId":195,"Title":"Californication","ArtistId":127}
{"AlbumId":196,"Title":"Retrospective I (1974-1980)","ArtistId":128}
{"AlbumId":197,"Title":"Santana - As Years Go By","ArtistId":59}
{"AlbumId":198,"Title":"Santana Live","ArtistId":59}
{"AlbumId":199,"Title":"Maquinarama","ArtistId":130}
{"AlbumId":200,"Title":"O Samba Poconé","ArtistId":130}
{"AlbumId":201,"Title":"Judas 0: B-Sides and Rarities","ArtistId":131}
{"AlbumId":202,"Title":"Rotten Apples: Greatest Hits","ArtistId":131}
{"AlbumId":203,"Title":"A-Sides","ArtistId":132}
{"AlbumId":204,"Title":"Morning Dance","ArtistId":53}
{"AlbumId":205,"Title":"In Step","ArtistId":133}
{"AlbumId":206,"Title":"Core","ArtistId":134}
{"AlbumId":207,"Title":"Mezmerize","ArtistId":135}
{"AlbumId":208,"Title":"[1997] Black Light Syndrome","ArtistId":136}
{"AlbumId":209,"Title":"Live [Disc 1]","ArtistId":137}
{"AlbumId":210,"Title":"Live [Disc 2]","ArtistId":137}
{"AlbumId":211,"Title":"The Singles","ArtistId":138}
{"AlbumId":212,"Title":"Beyond Good And Evil","ArtistId":139}
{"AlbumId":213,"Title":"Pure Cult: The Best Of The Cult (For Rockers, Ravers, Lovers & Sinners) [UK]","ArtistId":139}
{"AlbumId":214,"Title":"The Doors","ArtistId":140}
{"AlbumId":215,"Title":"The Police Greatest Hits","ArtistId":141}
{"AlbumId":216,"Title":"Hot Rocks, 1964-1971 (Disc 1)","ArtistId":142}
{"AlbumId":217,"Title":"No Security","ArtistId":142}
{"AlbumId":218,"Title":"Voodoo Lounge","ArtistId":142}
{"AlbumId":219,"Title":"Tangents","ArtistId":143}
{"AlbumId":220,"Title":"Transmission","ArtistId":143}
{"AlbumId":221,"Title":"My Generation - The Very Best Of The Who","ArtistId":144}
{"AlbumId":222,"Title":"Serie Sem Limite (Disc 1)","ArtistId":145}
{"AlbumId":223,"Title":"Serie Sem Limite (Disc 2)","ArtistId":145}
{"AlbumId":224,"Title":"Acústico","ArtistId":146}
{"AlbumId":225,"Title":"Volume Dois","ArtistId":146}
{"AlbumId":226,"Title":"Battlestar Galactica: The Story So Far","ArtistId":147}
{"AlbumId":227,"Title":"Battlestar Galactica, Season 3","ArtistId":147}
{"AlbumId":228,"Title":"Heroes, Season 1","ArtistId":148}
{"AlbumId":229,"Title":"Lost, Season 3","ArtistId":149}
{"AlbumId":230,"Title":"Lost, Season 1","ArtistId":149}
{"AlbumId":231,"Title":"Lost, Season 2","ArtistId":149}
{"AlbumId":232,"Title":"Achtung Baby","ArtistId":150}
{"AlbumId":233,"Title":"All That You Can't Leave Behind","ArtistId":150}
{"AlbumId":234,"Title":"B-Sides 1980-1990","ArtistId":150}
{"AlbumId":235,"Title":"How To Dismantle An Atomic Bomb","ArtistId":150}
{"AlbumId":236,"Title":"Pop","ArtistId":150}
{"AlbumId":237,"Title":"Rattle And Hum","ArtistId":150}
{"AlbumId":238,"Title":"The Best Of 1980-1990","ArtistId":150}
{"AlbumId":239,"Title":"War","ArtistId":150}
{"AlbumId":240,"Title":"Zooropa","ArtistId":150}
{"AlbumId":241,"Title":"UB40 The Best Of - Volume Two [UK]","ArtistId":151}
{"AlbumId":242,"Title":"Diver Down","ArtistId":152}
{"AlbumId":243,"Title":"The Best Of Van Halen, Vol. I","ArtistId":152}
{"AlbumId":244,"Title":"Van Halen","ArtistId":152}
{"AlbumId":245,"Title":"Van Halen III","ArtistId":152}
{"AlbumId":246,"Title":"Contraband","ArtistId":153}
{"AlbumId":247,"Title":"Vinicius De Moraes","ArtistId":72}
{"AlbumId":248,"Title":"Ao Vivo [IMPORT]","ArtistId":155}
{"AlbumId":249,"Title":"The Office, Season 1","ArtistId":156}
{"AlbumId":250,"Title":"The Office, Season 2","ArtistId":156}
{"AlbumId":251,"Title":"The Office, Season 3","ArtistId":156}
{"AlbumId":252,"Title":"Un-Led-Ed","ArtistId":157}
{"AlbumId":253,"Title":"Battlestar Galactica (Classic), Season 1","ArtistId":158}
{"AlbumId":254,"Title":"Aquaman","ArtistId":159}
{"AlbumId":255,"Title":"Instant Karma: The Amnesty International Campaign to Save Darfur","ArtistId":150}
{"AlbumId":256,"Title":"Speak of the Devil","ArtistId":114}
{"AlbumId":257,"Title":"20th Century Masters - The Millennium Collection: The Best of Scorpions","ArtistId":179}
{"AlbumId":258,"Title":"House of Pain","ArtistId":180}
{"AlbumId":259,"Title":"Radio Brasil (O Som da Jovem Vanguarda) - Seleccao de Henrique Amaro","ArtistId":36}
{"AlbumId":260,"Title":"Cake: B-Sides and Rarities","ArtistId":196}
{"AlbumId":261,"Title":"LOST, Season 4","ArtistId":149}
{"AlbumId":262,"Title":"Quiet Songs","ArtistId":197}
{"AlbumId":263,"Title":"Muso Ko","ArtistId":198}
{"AlbumId":264,"Title":"Realize","ArtistId":199}
{"AlbumId":265,"Title":"Every Kind of Light","ArtistId":200}
{"AlbumId":266,"Title":"Duos II","ArtistId":201}
{"AlbumId":267,"Title":"Worlds","ArtistId":202}
{"AlbumId":268,"Title":"The Best of Beethoven","ArtistId":203}
{"AlbumId":269,"Title":"Temple of the Dog","ArtistId":204}
{"AlbumId":270,"Title":"Carry On","ArtistId":205}
{"AlbumId":271,"Title":"Revelations","ArtistId":8}
{"AlbumId":272,"Title":"Adorate Deum: Gregorian Chant from the Proper of the Mass","ArtistId":206}
{"AlbumId":273,"Title":"Allegri: Miserere","ArtistId":207}
{"AlbumId":274,"Title":"Pachelbel: Canon & Gigue","ArtistId":208}
{"AlbumId":275,"Title":"Vivaldi: The Four Seasons","ArtistId":209}
{"AlbumId":276,"Title":"Bach: Violin Concertos","ArtistId":210}
{"AlbumId":277,"Title":"Bach: Goldberg Variations","ArtistId":211}
{"AlbumId":278,"Title":"Bach: The Cello Suites","ArtistId":212}
{"AlbumId":279,"Title":"Handel: The Messiah (Highlights)","ArtistId":213}
{"AlbumId":280,"Title":"The World of Classical Favourites","ArtistId":214}
{"AlbumId":281,"Title":"Sir Neville Marriner: A Celebration","ArtistId":215}
{"AlbumId":282,"Title":"Mozart: Wind Concertos","ArtistId":216}
{"AlbumId":283,"Title":"Haydn: Symphonies 99 - 104","ArtistId":217}
{"AlbumId":284,"Title":"Beethoven: Symhonies Nos. 5 & 6","ArtistId":218}
{"AlbumId":285,"Title":"A Soprano Inspired","ArtistId":219}
{"AlbumId":286,"Title":"Great Opera Choruses","ArtistId":220}
{"AlbumId":287,"Title":"Wagner: Favourite Overtures","ArtistId":221}
{"AlbumId":288,"Title":"Fauré: Requiem, Ravel: Pavane & Others","ArtistId":222}
{"AlbumId":289,"Title":"Tchaikovsky: The Nutcracker","ArtistId":223}
{"AlbumId":290,"Title":"The Last Night of the Proms","ArtistId":224}
{"AlbumId":291,"Title":"Puccini: Madama Butterfly - Highlights","ArtistId":225}
{"AlbumId":292,"Title":"Holst: The Planets, Op. 32 & Vaughan Williams: Fantasies","ArtistId":226}
{"AlbumId":293,"Title":"Pavarotti's Opera Made Easy","ArtistId":227}
{"AlbumId":294,"Title":"Great Performances - Barber's Adagio and Other Romantic Favorites for Strings","ArtistId":228}
{"AlbumId":295,"Title":"Carmina Burana","ArtistId":229}
{"AlbumId":296,"Title":"A Copland Celebration, Vol. I","ArtistId":230}
{"AlbumId":297,"Title":"Bach: Toccata & Fugue in D Minor","ArtistId":231}
{"AlbumId":298,"Title":"Prokofiev: Symphony No.1","ArtistId":232}
{"AlbumId":299,"Title":"Scheherazade","ArtistId":233}
{"AlbumId":300,"Title":"Bach: The Brandenburg Concertos","ArtistId":234}
{"AlbumId":301,"Title":"Chopin: Piano Concertos Nos. 1 & 2","ArtistId":235}
{"AlbumId":302,"Title":"Mascagni: Cavalleria Rusticana","ArtistId":236}
{"AlbumId":303,"Title":"Sibelius: Finlandia","ArtistId":237}
{"AlbumId":304,"Title":"Beethoven Piano Sonatas: Moonlight & Pastorale","ArtistId":238}
{"AlbumId":305,"Title":"Great Recordings of the Century - Mahler: Das Lied von der Erde","ArtistId":240}
{"AlbumId":306,"Title":"Elgar: Cello Concerto & Vaughan Williams: Fantasias","ArtistId":241}
{"AlbumId":307,"Title":"Adams, John: The Chairman Dances","ArtistId":242}
{"AlbumId":308,"Title":"Tchaikovsky: 1812 Festival Overture, Op.49, Capriccio Italien & Beethoven: Wellington's Victory","ArtistId":243}
{"AlbumId":309,"Title":"Palestrina: Missa Papae Marcelli & Allegri: Miserere","ArtistId":244}
{"AlbumId":310,"Title":"Prokofiev: Romeo & Juliet","ArtistId":245}
{"AlbumId":311,"Title":"Strauss: Waltzes","ArtistId":226}
{"AlbumId":312,"Title":"Berlioz: Symphonie Fantastique","ArtistId":245}
{"AlbumId":313,"Title":"Bizet: Carmen Highlights","ArtistId":246}
{"AlbumId":314,"Title":"English Renaissance","ArtistId":247}
{"AlbumId":315,"Title":"Handel: Music for the Royal Fireworks (Original Version 1749)","ArtistId":208}
{"AlbumId":316,"Title":"Grieg: Peer Gynt Suites & Sibelius: Pelléas et Mélisande","ArtistId":248}
{"AlbumId":317,"Title":"Mozart Gala: Famous Arias","ArtistId":249}
{"AlbumId":318,"Title":"SCRIABIN: Vers la flamme","ArtistId":250}
{"AlbumId":319,"Title":"Armada: Music from the Courts of England and Spain","ArtistId":251}
{"AlbumId":320,"Title":"Mozart: Symphonies Nos. 40 & 41","ArtistId":248}
{"AlbumId":321,"Title":"Back to Black","ArtistId":252}
{"AlbumId":322,"Title":"Frank","ArtistId":252}
{"AlbumId":323,"Title":"Carried to Dust (Bonus Track Version)","ArtistId":253}
{"AlbumId":324,"Title":"Beethoven: Symphony No. 6 'Pastoral' Etc.","ArtistId":254}
{"AlbumId":325,"Title":"Bartok: Violin & Viola Concertos","ArtistId":255}
{"AlbumId":326,"Title":"Mendelssohn: A Midsummer Night's Dream","ArtistId":256}
{"AlbumId":327,"Title":"Bach: Orchestral Suites Nos. 1 - 4","ArtistId":257}
{"AlbumId":328,"Title":"Charpentier: Divertissements, Airs & Concerts","ArtistId":258}
{"AlbumId":329,"Title":"South American Getaway","ArtistId":259}
{"AlbumId":330,"Title":"Górecki: Symphony No. 3","ArtistId":260}
{"AlbumId":331,"Title":"Purcell: The Fairy Queen","ArtistId":261}
{"AlbumId":332,"Title":"The Ultimate Relexation Album","ArtistId":262}
{"AlbumId":333,"Title":"Purcell: Music for the Queen Mary","ArtistId":263}
{"AlbumId":334,"Title":"Weill: The Seven Deadly Sins","ArtistId":264}
{"AlbumId":335,"Title":"J.S. Bach: Chaconne, Suite in E Minor, Partita in E Major & Prelude, Fugue and Allegro","ArtistId":265}
{"AlbumId":336,"Title":"Prokofiev: Symphony No.5 & Stravinksy: Le Sacre Du Printemps","ArtistId":248}
{"AlbumId":337,"Title":"Szymanowski: Piano Works, Vol. 1","ArtistId":266}
{"AlbumId":338,"Title":"Nielsen: The Six Symphonies","ArtistId":267}
{"AlbumId":339,"Title":"Great Recordings of the Century: Paganini's 24 Caprices","ArtistId":268}
{"AlbumId":340,"Title":"Liszt - 12 Études D'Execution Transcendante","ArtistId":269}
{"AlbumId":341,"Title":"Great Recordings of the Century - Shubert: Schwanengesang, 4 Lieder","ArtistId":270}
{"AlbumId":342,"Title":"Locatelli: Concertos for Violin, Strings and Continuo, Vol. 3","ArtistId":271}
{"AlbumId":343,"Title":"Respighi:Pines of Rome","ArtistId":226}
{"AlbumId":344,"Title":"Schubert: The Late String Quartets & String Quintet (3 CD's)","ArtistId":272}
{"AlbumId":345,"Title":"Monteverdi: L'Orfeo","ArtistId":273}
{"AlbumId":346,"Title":"Mozart: Chamber Music","ArtistId":274}
{"AlbumId":347,"Title":"Koyaanisqatsi (Soundtrack from the Motion Picture)","ArtistId":275}
-275
View File
@@ -1,275 +0,0 @@
{"ArtistId":1,"Name":"AC/DC"}
{"ArtistId":2,"Name":"Accept"}
{"ArtistId":3,"Name":"Aerosmith"}
{"ArtistId":4,"Name":"Alanis Morissette"}
{"ArtistId":5,"Name":"Alice In Chains"}
{"ArtistId":6,"Name":"Antônio Carlos Jobim"}
{"ArtistId":7,"Name":"Apocalyptica"}
{"ArtistId":8,"Name":"Audioslave"}
{"ArtistId":9,"Name":"BackBeat"}
{"ArtistId":10,"Name":"Billy Cobham"}
{"ArtistId":11,"Name":"Black Label Society"}
{"ArtistId":12,"Name":"Black Sabbath"}
{"ArtistId":13,"Name":"Body Count"}
{"ArtistId":14,"Name":"Bruce Dickinson"}
{"ArtistId":15,"Name":"Buddy Guy"}
{"ArtistId":16,"Name":"Caetano Veloso"}
{"ArtistId":17,"Name":"Chico Buarque"}
{"ArtistId":18,"Name":"Chico Science & Naçăo Zumbi"}
{"ArtistId":19,"Name":"Cidade Negra"}
{"ArtistId":20,"Name":"Cláudio Zoli"}
{"ArtistId":21,"Name":"Various Artists"}
{"ArtistId":22,"Name":"Led Zeppelin"}
{"ArtistId":23,"Name":"Frank Zappa & Captain Beefheart"}
{"ArtistId":24,"Name":"Marcos Valle"}
{"ArtistId":25,"Name":"Milton Nascimento & Bebeto"}
{"ArtistId":26,"Name":"Azymuth"}
{"ArtistId":27,"Name":"Gilberto Gil"}
{"ArtistId":28,"Name":"Joăo Gilberto"}
{"ArtistId":29,"Name":"Bebel Gilberto"}
{"ArtistId":30,"Name":"Jorge Vercilo"}
{"ArtistId":31,"Name":"Baby Consuelo"}
{"ArtistId":32,"Name":"Ney Matogrosso"}
{"ArtistId":33,"Name":"Luiz Melodia"}
{"ArtistId":34,"Name":"Nando Reis"}
{"ArtistId":35,"Name":"Pedro Luís & A Parede"}
{"ArtistId":36,"Name":"O Rappa"}
{"ArtistId":37,"Name":"Ed Motta"}
{"ArtistId":38,"Name":"Banda Black Rio"}
{"ArtistId":39,"Name":"Fernanda Porto"}
{"ArtistId":40,"Name":"Os Cariocas"}
{"ArtistId":41,"Name":"Elis Regina"}
{"ArtistId":42,"Name":"Milton Nascimento"}
{"ArtistId":43,"Name":"A Cor Do Som"}
{"ArtistId":44,"Name":"Kid Abelha"}
{"ArtistId":45,"Name":"Sandra De Sá"}
{"ArtistId":46,"Name":"Jorge Ben"}
{"ArtistId":47,"Name":"Hermeto Pascoal"}
{"ArtistId":48,"Name":"Barăo Vermelho"}
{"ArtistId":49,"Name":"Edson, DJ Marky & DJ Patife Featuring Fernanda Porto"}
{"ArtistId":50,"Name":"Metallica"}
{"ArtistId":51,"Name":"Queen"}
{"ArtistId":52,"Name":"Kiss"}
{"ArtistId":53,"Name":"Spyro Gyra"}
{"ArtistId":54,"Name":"Green Day"}
{"ArtistId":55,"Name":"David Coverdale"}
{"ArtistId":56,"Name":"Gonzaguinha"}
{"ArtistId":57,"Name":"Os Mutantes"}
{"ArtistId":58,"Name":"Deep Purple"}
{"ArtistId":59,"Name":"Santana"}
{"ArtistId":60,"Name":"Santana Feat. Dave Matthews"}
{"ArtistId":61,"Name":"Santana Feat. Everlast"}
{"ArtistId":62,"Name":"Santana Feat. Rob Thomas"}
{"ArtistId":63,"Name":"Santana Feat. Lauryn Hill & Cee-Lo"}
{"ArtistId":64,"Name":"Santana Feat. The Project G&B"}
{"ArtistId":65,"Name":"Santana Feat. Maná"}
{"ArtistId":66,"Name":"Santana Feat. Eagle-Eye Cherry"}
{"ArtistId":67,"Name":"Santana Feat. Eric Clapton"}
{"ArtistId":68,"Name":"Miles Davis"}
{"ArtistId":69,"Name":"Gene Krupa"}
{"ArtistId":70,"Name":"Toquinho & Vinícius"}
{"ArtistId":71,"Name":"Vinícius De Moraes & Baden Powell"}
{"ArtistId":72,"Name":"Vinícius De Moraes"}
{"ArtistId":73,"Name":"Vinícius E Qurteto Em Cy"}
{"ArtistId":74,"Name":"Vinícius E Odette Lara"}
{"ArtistId":75,"Name":"Vinicius, Toquinho & Quarteto Em Cy"}
{"ArtistId":76,"Name":"Creedence Clearwater Revival"}
{"ArtistId":77,"Name":"Cássia Eller"}
{"ArtistId":78,"Name":"Def Leppard"}
{"ArtistId":79,"Name":"Dennis Chambers"}
{"ArtistId":80,"Name":"Djavan"}
{"ArtistId":81,"Name":"Eric Clapton"}
{"ArtistId":82,"Name":"Faith No More"}
{"ArtistId":83,"Name":"Falamansa"}
{"ArtistId":84,"Name":"Foo Fighters"}
{"ArtistId":85,"Name":"Frank Sinatra"}
{"ArtistId":86,"Name":"Funk Como Le Gusta"}
{"ArtistId":87,"Name":"Godsmack"}
{"ArtistId":88,"Name":"Guns N' Roses"}
{"ArtistId":89,"Name":"Incognito"}
{"ArtistId":90,"Name":"Iron Maiden"}
{"ArtistId":91,"Name":"James Brown"}
{"ArtistId":92,"Name":"Jamiroquai"}
{"ArtistId":93,"Name":"JET"}
{"ArtistId":94,"Name":"Jimi Hendrix"}
{"ArtistId":95,"Name":"Joe Satriani"}
{"ArtistId":96,"Name":"Jota Quest"}
{"ArtistId":97,"Name":"Joăo Suplicy"}
{"ArtistId":98,"Name":"Judas Priest"}
{"ArtistId":99,"Name":"Legiăo Urbana"}
{"ArtistId":100,"Name":"Lenny Kravitz"}
{"ArtistId":101,"Name":"Lulu Santos"}
{"ArtistId":102,"Name":"Marillion"}
{"ArtistId":103,"Name":"Marisa Monte"}
{"ArtistId":104,"Name":"Marvin Gaye"}
{"ArtistId":105,"Name":"Men At Work"}
{"ArtistId":106,"Name":"Motörhead"}
{"ArtistId":107,"Name":"Motörhead & Girlschool"}
{"ArtistId":108,"Name":"Mônica Marianno"}
{"ArtistId":109,"Name":"Mötley Crüe"}
{"ArtistId":110,"Name":"Nirvana"}
{"ArtistId":111,"Name":"O Terço"}
{"ArtistId":112,"Name":"Olodum"}
{"ArtistId":113,"Name":"Os Paralamas Do Sucesso"}
{"ArtistId":114,"Name":"Ozzy Osbourne"}
{"ArtistId":115,"Name":"Page & Plant"}
{"ArtistId":116,"Name":"Passengers"}
{"ArtistId":117,"Name":"Paul D'Ianno"}
{"ArtistId":118,"Name":"Pearl Jam"}
{"ArtistId":119,"Name":"Peter Tosh"}
{"ArtistId":120,"Name":"Pink Floyd"}
{"ArtistId":121,"Name":"Planet Hemp"}
{"ArtistId":122,"Name":"R.E.M. Feat. Kate Pearson"}
{"ArtistId":123,"Name":"R.E.M. Feat. KRS-One"}
{"ArtistId":124,"Name":"R.E.M."}
{"ArtistId":125,"Name":"Raimundos"}
{"ArtistId":126,"Name":"Raul Seixas"}
{"ArtistId":127,"Name":"Red Hot Chili Peppers"}
{"ArtistId":128,"Name":"Rush"}
{"ArtistId":129,"Name":"Simply Red"}
{"ArtistId":130,"Name":"Skank"}
{"ArtistId":131,"Name":"Smashing Pumpkins"}
{"ArtistId":132,"Name":"Soundgarden"}
{"ArtistId":133,"Name":"Stevie Ray Vaughan & Double Trouble"}
{"ArtistId":134,"Name":"Stone Temple Pilots"}
{"ArtistId":135,"Name":"System Of A Down"}
{"ArtistId":136,"Name":"Terry Bozzio, Tony Levin & Steve Stevens"}
{"ArtistId":137,"Name":"The Black Crowes"}
{"ArtistId":138,"Name":"The Clash"}
{"ArtistId":139,"Name":"The Cult"}
{"ArtistId":140,"Name":"The Doors"}
{"ArtistId":141,"Name":"The Police"}
{"ArtistId":142,"Name":"The Rolling Stones"}
{"ArtistId":143,"Name":"The Tea Party"}
{"ArtistId":144,"Name":"The Who"}
{"ArtistId":145,"Name":"Tim Maia"}
{"ArtistId":146,"Name":"Tităs"}
{"ArtistId":147,"Name":"Battlestar Galactica"}
{"ArtistId":148,"Name":"Heroes"}
{"ArtistId":149,"Name":"Lost"}
{"ArtistId":150,"Name":"U2"}
{"ArtistId":151,"Name":"UB40"}
{"ArtistId":152,"Name":"Van Halen"}
{"ArtistId":153,"Name":"Velvet Revolver"}
{"ArtistId":154,"Name":"Whitesnake"}
{"ArtistId":155,"Name":"Zeca Pagodinho"}
{"ArtistId":156,"Name":"The Office"}
{"ArtistId":157,"Name":"Dread Zeppelin"}
{"ArtistId":158,"Name":"Battlestar Galactica (Classic)"}
{"ArtistId":159,"Name":"Aquaman"}
{"ArtistId":160,"Name":"Christina Aguilera featuring BigElf"}
{"ArtistId":161,"Name":"Aerosmith & Sierra Leone's Refugee Allstars"}
{"ArtistId":162,"Name":"Los Lonely Boys"}
{"ArtistId":163,"Name":"Corinne Bailey Rae"}
{"ArtistId":164,"Name":"Dhani Harrison & Jakob Dylan"}
{"ArtistId":165,"Name":"Jackson Browne"}
{"ArtistId":166,"Name":"Avril Lavigne"}
{"ArtistId":167,"Name":"Big & Rich"}
{"ArtistId":168,"Name":"Youssou N'Dour"}
{"ArtistId":169,"Name":"Black Eyed Peas"}
{"ArtistId":170,"Name":"Jack Johnson"}
{"ArtistId":171,"Name":"Ben Harper"}
{"ArtistId":172,"Name":"Snow Patrol"}
{"ArtistId":173,"Name":"Matisyahu"}
{"ArtistId":174,"Name":"The Postal Service"}
{"ArtistId":175,"Name":"Jaguares"}
{"ArtistId":176,"Name":"The Flaming Lips"}
{"ArtistId":177,"Name":"Jack's Mannequin & Mick Fleetwood"}
{"ArtistId":178,"Name":"Regina Spektor"}
{"ArtistId":179,"Name":"Scorpions"}
{"ArtistId":180,"Name":"House Of Pain"}
{"ArtistId":181,"Name":"Xis"}
{"ArtistId":182,"Name":"Nega Gizza"}
{"ArtistId":183,"Name":"Gustavo & Andres Veiga & Salazar"}
{"ArtistId":184,"Name":"Rodox"}
{"ArtistId":185,"Name":"Charlie Brown Jr."}
{"ArtistId":186,"Name":"Pedro Luís E A Parede"}
{"ArtistId":187,"Name":"Los Hermanos"}
{"ArtistId":188,"Name":"Mundo Livre S/A"}
{"ArtistId":189,"Name":"Otto"}
{"ArtistId":190,"Name":"Instituto"}
{"ArtistId":191,"Name":"Naçăo Zumbi"}
{"ArtistId":192,"Name":"DJ Dolores & Orchestra Santa Massa"}
{"ArtistId":193,"Name":"Seu Jorge"}
{"ArtistId":194,"Name":"Sabotage E Instituto"}
{"ArtistId":195,"Name":"Stereo Maracana"}
{"ArtistId":196,"Name":"Cake"}
{"ArtistId":197,"Name":"Aisha Duo"}
{"ArtistId":198,"Name":"Habib Koité and Bamada"}
{"ArtistId":199,"Name":"Karsh Kale"}
{"ArtistId":200,"Name":"The Posies"}
{"ArtistId":201,"Name":"Luciana Souza/Romero Lubambo"}
{"ArtistId":202,"Name":"Aaron Goldberg"}
{"ArtistId":203,"Name":"Nicolaus Esterhazy Sinfonia"}
{"ArtistId":204,"Name":"Temple of the Dog"}
{"ArtistId":205,"Name":"Chris Cornell"}
{"ArtistId":206,"Name":"Alberto Turco & Nova Schola Gregoriana"}
{"ArtistId":207,"Name":"Richard Marlow & The Choir of Trinity College, Cambridge"}
{"ArtistId":208,"Name":"English Concert & Trevor Pinnock"}
{"ArtistId":209,"Name":"Anne-Sophie Mutter, Herbert Von Karajan & Wiener Philharmoniker"}
{"ArtistId":210,"Name":"Hilary Hahn, Jeffrey Kahane, Los Angeles Chamber Orchestra & Margaret Batjer"}
{"ArtistId":211,"Name":"Wilhelm Kempff"}
{"ArtistId":212,"Name":"Yo-Yo Ma"}
{"ArtistId":213,"Name":"Scholars Baroque Ensemble"}
{"ArtistId":214,"Name":"Academy of St. Martin in the Fields & Sir Neville Marriner"}
{"ArtistId":215,"Name":"Academy of St. Martin in the Fields Chamber Ensemble & Sir Neville Marriner"}
{"ArtistId":216,"Name":"Berliner Philharmoniker, Claudio Abbado & Sabine Meyer"}
{"ArtistId":217,"Name":"Royal Philharmonic Orchestra & Sir Thomas Beecham"}
{"ArtistId":218,"Name":"Orchestre Révolutionnaire et Romantique & John Eliot Gardiner"}
{"ArtistId":219,"Name":"Britten Sinfonia, Ivor Bolton & Lesley Garrett"}
{"ArtistId":220,"Name":"Chicago Symphony Chorus, Chicago Symphony Orchestra & Sir Georg Solti"}
{"ArtistId":221,"Name":"Sir Georg Solti & Wiener Philharmoniker"}
{"ArtistId":222,"Name":"Academy of St. Martin in the Fields, John Birch, Sir Neville Marriner & Sylvia McNair"}
{"ArtistId":223,"Name":"London Symphony Orchestra & Sir Charles Mackerras"}
{"ArtistId":224,"Name":"Barry Wordsworth & BBC Concert Orchestra"}
{"ArtistId":225,"Name":"Herbert Von Karajan, Mirella Freni & Wiener Philharmoniker"}
{"ArtistId":226,"Name":"Eugene Ormandy"}
{"ArtistId":227,"Name":"Luciano Pavarotti"}
{"ArtistId":228,"Name":"Leonard Bernstein & New York Philharmonic"}
{"ArtistId":229,"Name":"Boston Symphony Orchestra & Seiji Ozawa"}
{"ArtistId":230,"Name":"Aaron Copland & London Symphony Orchestra"}
{"ArtistId":231,"Name":"Ton Koopman"}
{"ArtistId":232,"Name":"Sergei Prokofiev & Yuri Temirkanov"}
{"ArtistId":233,"Name":"Chicago Symphony Orchestra & Fritz Reiner"}
{"ArtistId":234,"Name":"Orchestra of The Age of Enlightenment"}
{"ArtistId":235,"Name":"Emanuel Ax, Eugene Ormandy & Philadelphia Orchestra"}
{"ArtistId":236,"Name":"James Levine"}
{"ArtistId":237,"Name":"Berliner Philharmoniker & Hans Rosbaud"}
{"ArtistId":238,"Name":"Maurizio Pollini"}
{"ArtistId":239,"Name":"Academy of St. Martin in the Fields, Sir Neville Marriner & William Bennett"}
{"ArtistId":240,"Name":"Gustav Mahler"}
{"ArtistId":241,"Name":"Felix Schmidt, London Symphony Orchestra & Rafael Frühbeck de Burgos"}
{"ArtistId":242,"Name":"Edo de Waart & San Francisco Symphony"}
{"ArtistId":243,"Name":"Antal Doráti & London Symphony Orchestra"}
{"ArtistId":244,"Name":"Choir Of Westminster Abbey & Simon Preston"}
{"ArtistId":245,"Name":"Michael Tilson Thomas & San Francisco Symphony"}
{"ArtistId":246,"Name":"Chor der Wiener Staatsoper, Herbert Von Karajan & Wiener Philharmoniker"}
{"ArtistId":247,"Name":"The King's Singers"}
{"ArtistId":248,"Name":"Berliner Philharmoniker & Herbert Von Karajan"}
{"ArtistId":249,"Name":"Sir Georg Solti, Sumi Jo & Wiener Philharmoniker"}
{"ArtistId":250,"Name":"Christopher O'Riley"}
{"ArtistId":251,"Name":"Fretwork"}
{"ArtistId":252,"Name":"Amy Winehouse"}
{"ArtistId":253,"Name":"Calexico"}
{"ArtistId":254,"Name":"Otto Klemperer & Philharmonia Orchestra"}
{"ArtistId":255,"Name":"Yehudi Menuhin"}
{"ArtistId":256,"Name":"Philharmonia Orchestra & Sir Neville Marriner"}
{"ArtistId":257,"Name":"Academy of St. Martin in the Fields, Sir Neville Marriner & Thurston Dart"}
{"ArtistId":258,"Name":"Les Arts Florissants & William Christie"}
{"ArtistId":259,"Name":"The 12 Cellists of The Berlin Philharmonic"}
{"ArtistId":260,"Name":"Adrian Leaper & Doreen de Feis"}
{"ArtistId":261,"Name":"Roger Norrington, London Classical Players"}
{"ArtistId":262,"Name":"Charles Dutoit & L'Orchestre Symphonique de Montréal"}
{"ArtistId":263,"Name":"Equale Brass Ensemble, John Eliot Gardiner & Munich Monteverdi Orchestra and Choir"}
{"ArtistId":264,"Name":"Kent Nagano and Orchestre de l'Opéra de Lyon"}
{"ArtistId":265,"Name":"Julian Bream"}
{"ArtistId":266,"Name":"Martin Roscoe"}
{"ArtistId":267,"Name":"Göteborgs Symfoniker & Neeme Järvi"}
{"ArtistId":268,"Name":"Itzhak Perlman"}
{"ArtistId":269,"Name":"Michele Campanella"}
{"ArtistId":270,"Name":"Gerald Moore"}
{"ArtistId":271,"Name":"Mela Tenenbaum, Pro Musica Prague & Richard Kapp"}
{"ArtistId":272,"Name":"Emerson String Quartet"}
{"ArtistId":273,"Name":"C. Monteverdi, Nigel Rogers - Chiaroscuro; London Baroque; London Cornett & Sackbu"}
{"ArtistId":274,"Name":"Nash Ensemble"}
{"ArtistId":275,"Name":"Philip Glass Ensemble"}
@@ -1,59 +0,0 @@
{"CustomerId":1,"FirstName":"Luís","LastName":"Gonçalves","Company":"Embraer - Empresa Brasileira de Aeronáutica S.A.","Address":"Av. Brigadeiro Faria Lima, 2170","City":"Săo José dos Campos","State":"SP","Country":"Brazil","PostalCode":"12227-000","Phone":"+55 (12) 3923-5555","Fax":"+55 (12) 3923-5566","Email":"luisg@embraer.com.br","SupportRepId":3}
{"CustomerId":2,"FirstName":"Leonie","LastName":"Köhler","Company":null,"Address":"Theodor-Heuss-Straße 34","City":"Stuttgart","State":null,"Country":"Germany","PostalCode":"70174","Phone":"+49 0711 2842222","Fax":null,"Email":"leonekohler@surfeu.de","SupportRepId":5}
{"CustomerId":3,"FirstName":"François","LastName":"Tremblay","Company":null,"Address":"1498 rue Bélanger","City":"Montréal","State":"QC","Country":"Canada","PostalCode":"H2G 1A7","Phone":"+1 (514) 721-4711","Fax":null,"Email":"ftremblay@gmail.com","SupportRepId":3}
{"CustomerId":4,"FirstName":"Bjřrn","LastName":"Hansen","Company":null,"Address":"Ullevĺlsveien 14","City":"Oslo","State":null,"Country":"Norway","PostalCode":"0171","Phone":"+47 22 44 22 22","Fax":null,"Email":"bjorn.hansen@yahoo.no","SupportRepId":4}
{"CustomerId":5,"FirstName":"František","LastName":"Wichterlová","Company":"JetBrains s.r.o.","Address":"Klanova 9/506","City":"Prague","State":null,"Country":"Czech Republic","PostalCode":"14700","Phone":"+420 2 4172 5555","Fax":"+420 2 4172 5555","Email":"frantisekw@jetbrains.com","SupportRepId":4}
{"CustomerId":6,"FirstName":"Helena","LastName":"Holý","Company":null,"Address":"Rilská 3174/6","City":"Prague","State":null,"Country":"Czech Republic","PostalCode":"14300","Phone":"+420 2 4177 0449","Fax":null,"Email":"hholy@gmail.com","SupportRepId":5}
{"CustomerId":7,"FirstName":"Astrid","LastName":"Gruber","Company":null,"Address":"Rotenturmstraße 4, 1010 Innere Stadt","City":"Vienne","State":null,"Country":"Austria","PostalCode":"1010","Phone":"+43 01 5134505","Fax":null,"Email":"astrid.gruber@apple.at","SupportRepId":5}
{"CustomerId":8,"FirstName":"Daan","LastName":"Peeters","Company":null,"Address":"Grétrystraat 63","City":"Brussels","State":null,"Country":"Belgium","PostalCode":"1000","Phone":"+32 02 219 03 03","Fax":null,"Email":"daan_peeters@apple.be","SupportRepId":4}
{"CustomerId":9,"FirstName":"Kara","LastName":"Nielsen","Company":null,"Address":"Sřnder Boulevard 51","City":"Copenhagen","State":null,"Country":"Denmark","PostalCode":"1720","Phone":"+453 3331 9991","Fax":null,"Email":"kara.nielsen@jubii.dk","SupportRepId":4}
{"CustomerId":10,"FirstName":"Eduardo","LastName":"Martins","Company":"Woodstock Discos","Address":"Rua Dr. Falcăo Filho, 155","City":"Săo Paulo","State":"SP","Country":"Brazil","PostalCode":"01007-010","Phone":"+55 (11) 3033-5446","Fax":"+55 (11) 3033-4564","Email":"eduardo@woodstock.com.br","SupportRepId":4}
{"CustomerId":11,"FirstName":"Alexandre","LastName":"Rocha","Company":"Banco do Brasil S.A.","Address":"Av. Paulista, 2022","City":"Săo Paulo","State":"SP","Country":"Brazil","PostalCode":"01310-200","Phone":"+55 (11) 3055-3278","Fax":"+55 (11) 3055-8131","Email":"alero@uol.com.br","SupportRepId":5}
{"CustomerId":12,"FirstName":"Roberto","LastName":"Almeida","Company":"Riotur","Address":"Praça Pio X, 119","City":"Rio de Janeiro","State":"RJ","Country":"Brazil","PostalCode":"20040-020","Phone":"+55 (21) 2271-7000","Fax":"+55 (21) 2271-7070","Email":"roberto.almeida@riotur.gov.br","SupportRepId":3}
{"CustomerId":13,"FirstName":"Fernanda","LastName":"Ramos","Company":null,"Address":"Qe 7 Bloco G","City":"Brasília","State":"DF","Country":"Brazil","PostalCode":"71020-677","Phone":"+55 (61) 3363-5547","Fax":"+55 (61) 3363-7855","Email":"fernadaramos4@uol.com.br","SupportRepId":4}
{"CustomerId":14,"FirstName":"Mark","LastName":"Philips","Company":"Telus","Address":"8210 111 ST NW","City":"Edmonton","State":"AB","Country":"Canada","PostalCode":"T6G 2C7","Phone":"+1 (780) 434-4554","Fax":"+1 (780) 434-5565","Email":"mphilips12@shaw.ca","SupportRepId":5}
{"CustomerId":15,"FirstName":"Jennifer","LastName":"Peterson","Company":"Rogers Canada","Address":"700 W Pender Street","City":"Vancouver","State":"BC","Country":"Canada","PostalCode":"V6C 1G8","Phone":"+1 (604) 688-2255","Fax":"+1 (604) 688-8756","Email":"jenniferp@rogers.ca","SupportRepId":3}
{"CustomerId":16,"FirstName":"Frank","LastName":"Harris","Company":"Google Inc.","Address":"1600 Amphitheatre Parkway","City":"Mountain View","State":"CA","Country":"USA","PostalCode":"94043-1351","Phone":"+1 (650) 253-0000","Fax":"+1 (650) 253-0000","Email":"fharris@google.com","SupportRepId":4}
{"CustomerId":17,"FirstName":"Jack","LastName":"Smith","Company":"Microsoft Corporation","Address":"1 Microsoft Way","City":"Redmond","State":"WA","Country":"USA","PostalCode":"98052-8300","Phone":"+1 (425) 882-8080","Fax":"+1 (425) 882-8081","Email":"jacksmith@microsoft.com","SupportRepId":5}
{"CustomerId":18,"FirstName":"Michelle","LastName":"Brooks","Company":null,"Address":"627 Broadway","City":"New York","State":"NY","Country":"USA","PostalCode":"10012-2612","Phone":"+1 (212) 221-3546","Fax":"+1 (212) 221-4679","Email":"michelleb@aol.com","SupportRepId":3}
{"CustomerId":19,"FirstName":"Tim","LastName":"Goyer","Company":"Apple Inc.","Address":"1 Infinite Loop","City":"Cupertino","State":"CA","Country":"USA","PostalCode":"95014","Phone":"+1 (408) 996-1010","Fax":"+1 (408) 996-1011","Email":"tgoyer@apple.com","SupportRepId":3}
{"CustomerId":20,"FirstName":"Dan","LastName":"Miller","Company":null,"Address":"541 Del Medio Avenue","City":"Mountain View","State":"CA","Country":"USA","PostalCode":"94040-111","Phone":"+1 (650) 644-3358","Fax":null,"Email":"dmiller@comcast.com","SupportRepId":4}
{"CustomerId":21,"FirstName":"Kathy","LastName":"Chase","Company":null,"Address":"801 W 4th Street","City":"Reno","State":"NV","Country":"USA","PostalCode":"89503","Phone":"+1 (775) 223-7665","Fax":null,"Email":"kachase@hotmail.com","SupportRepId":5}
{"CustomerId":22,"FirstName":"Heather","LastName":"Leacock","Company":null,"Address":"120 S Orange Ave","City":"Orlando","State":"FL","Country":"USA","PostalCode":"32801","Phone":"+1 (407) 999-7788","Fax":null,"Email":"hleacock@gmail.com","SupportRepId":4}
{"CustomerId":23,"FirstName":"John","LastName":"Gordon","Company":null,"Address":"69 Salem Street","City":"Boston","State":"MA","Country":"USA","PostalCode":"2113","Phone":"+1 (617) 522-1333","Fax":null,"Email":"johngordon22@yahoo.com","SupportRepId":4}
{"CustomerId":24,"FirstName":"Frank","LastName":"Ralston","Company":null,"Address":"162 E Superior Street","City":"Chicago","State":"IL","Country":"USA","PostalCode":"60611","Phone":"+1 (312) 332-3232","Fax":null,"Email":"fralston@gmail.com","SupportRepId":3}
{"CustomerId":25,"FirstName":"Victor","LastName":"Stevens","Company":null,"Address":"319 N. Frances Street","City":"Madison","State":"WI","Country":"USA","PostalCode":"53703","Phone":"+1 (608) 257-0597","Fax":null,"Email":"vstevens@yahoo.com","SupportRepId":5}
{"CustomerId":26,"FirstName":"Richard","LastName":"Cunningham","Company":null,"Address":"2211 W Berry Street","City":"Fort Worth","State":"TX","Country":"USA","PostalCode":"76110","Phone":"+1 (817) 924-7272","Fax":null,"Email":"ricunningham@hotmail.com","SupportRepId":4}
{"CustomerId":27,"FirstName":"Patrick","LastName":"Gray","Company":null,"Address":"1033 N Park Ave","City":"Tucson","State":"AZ","Country":"USA","PostalCode":"85719","Phone":"+1 (520) 622-4200","Fax":null,"Email":"patrick.gray@aol.com","SupportRepId":4}
{"CustomerId":28,"FirstName":"Julia","LastName":"Barnett","Company":null,"Address":"302 S 700 E","City":"Salt Lake City","State":"UT","Country":"USA","PostalCode":"84102","Phone":"+1 (801) 531-7272","Fax":null,"Email":"jubarnett@gmail.com","SupportRepId":5}
{"CustomerId":29,"FirstName":"Robert","LastName":"Brown","Company":null,"Address":"796 Dundas Street West","City":"Toronto","State":"ON","Country":"Canada","PostalCode":"M6J 1V1","Phone":"+1 (416) 363-8888","Fax":null,"Email":"robbrown@shaw.ca","SupportRepId":3}
{"CustomerId":30,"FirstName":"Edward","LastName":"Francis","Company":null,"Address":"230 Elgin Street","City":"Ottawa","State":"ON","Country":"Canada","PostalCode":"K2P 1L7","Phone":"+1 (613) 234-3322","Fax":null,"Email":"edfrancis@yachoo.ca","SupportRepId":3}
{"CustomerId":31,"FirstName":"Martha","LastName":"Silk","Company":null,"Address":"194A Chain Lake Drive","City":"Halifax","State":"NS","Country":"Canada","PostalCode":"B3S 1C5","Phone":"+1 (902) 450-0450","Fax":null,"Email":"marthasilk@gmail.com","SupportRepId":5}
{"CustomerId":32,"FirstName":"Aaron","LastName":"Mitchell","Company":null,"Address":"696 Osborne Street","City":"Winnipeg","State":"MB","Country":"Canada","PostalCode":"R3L 2B9","Phone":"+1 (204) 452-6452","Fax":null,"Email":"aaronmitchell@yahoo.ca","SupportRepId":4}
{"CustomerId":33,"FirstName":"Ellie","LastName":"Sullivan","Company":null,"Address":"5112 48 Street","City":"Yellowknife","State":"NT","Country":"Canada","PostalCode":"X1A 1N6","Phone":"+1 (867) 920-2233","Fax":null,"Email":"ellie.sullivan@shaw.ca","SupportRepId":3}
{"CustomerId":34,"FirstName":"Joăo","LastName":"Fernandes","Company":null,"Address":"Rua da Assunçăo 53","City":"Lisbon","State":null,"Country":"Portugal","PostalCode":null,"Phone":"+351 (213) 466-111","Fax":null,"Email":"jfernandes@yahoo.pt","SupportRepId":4}
{"CustomerId":35,"FirstName":"Madalena","LastName":"Sampaio","Company":null,"Address":"Rua dos Campeőes Europeus de Viena, 4350","City":"Porto","State":null,"Country":"Portugal","PostalCode":null,"Phone":"+351 (225) 022-448","Fax":null,"Email":"masampaio@sapo.pt","SupportRepId":4}
{"CustomerId":36,"FirstName":"Hannah","LastName":"Schneider","Company":null,"Address":"Tauentzienstraße 8","City":"Berlin","State":null,"Country":"Germany","PostalCode":"10789","Phone":"+49 030 26550280","Fax":null,"Email":"hannah.schneider@yahoo.de","SupportRepId":5}
{"CustomerId":37,"FirstName":"Fynn","LastName":"Zimmermann","Company":null,"Address":"Berger Straße 10","City":"Frankfurt","State":null,"Country":"Germany","PostalCode":"60316","Phone":"+49 069 40598889","Fax":null,"Email":"fzimmermann@yahoo.de","SupportRepId":3}
{"CustomerId":38,"FirstName":"Niklas","LastName":"Schröder","Company":null,"Address":"Barbarossastraße 19","City":"Berlin","State":null,"Country":"Germany","PostalCode":"10779","Phone":"+49 030 2141444","Fax":null,"Email":"nschroder@surfeu.de","SupportRepId":3}
{"CustomerId":39,"FirstName":"Camille","LastName":"Bernard","Company":null,"Address":"4, Rue Milton","City":"Paris","State":null,"Country":"France","PostalCode":"75009","Phone":"+33 01 49 70 65 65","Fax":null,"Email":"camille.bernard@yahoo.fr","SupportRepId":4}
{"CustomerId":40,"FirstName":"Dominique","LastName":"Lefebvre","Company":null,"Address":"8, Rue Hanovre","City":"Paris","State":null,"Country":"France","PostalCode":"75002","Phone":"+33 01 47 42 71 71","Fax":null,"Email":"dominiquelefebvre@gmail.com","SupportRepId":4}
{"CustomerId":41,"FirstName":"Marc","LastName":"Dubois","Company":null,"Address":"11, Place Bellecour","City":"Lyon","State":null,"Country":"France","PostalCode":"69002","Phone":"+33 04 78 30 30 30","Fax":null,"Email":"marc.dubois@hotmail.com","SupportRepId":5}
{"CustomerId":42,"FirstName":"Wyatt","LastName":"Girard","Company":null,"Address":"9, Place Louis Barthou","City":"Bordeaux","State":null,"Country":"France","PostalCode":"33000","Phone":"+33 05 56 96 96 96","Fax":null,"Email":"wyatt.girard@yahoo.fr","SupportRepId":3}
{"CustomerId":43,"FirstName":"Isabelle","LastName":"Mercier","Company":null,"Address":"68, Rue Jouvence","City":"Dijon","State":null,"Country":"France","PostalCode":"21000","Phone":"+33 03 80 73 66 99","Fax":null,"Email":"isabelle_mercier@apple.fr","SupportRepId":3}
{"CustomerId":44,"FirstName":"Terhi","LastName":"Hämäläinen","Company":null,"Address":"Porthaninkatu 9","City":"Helsinki","State":null,"Country":"Finland","PostalCode":"00530","Phone":"+358 09 870 2000","Fax":null,"Email":"terhi.hamalainen@apple.fi","SupportRepId":3}
{"CustomerId":45,"FirstName":"Ladislav","LastName":"Kovács","Company":null,"Address":"Erzsébet krt. 58.","City":"Budapest","State":null,"Country":"Hungary","PostalCode":"H-1073","Phone":null,"Fax":null,"Email":"ladislav_kovacs@apple.hu","SupportRepId":3}
{"CustomerId":46,"FirstName":"Hugh","LastName":"O'Reilly","Company":null,"Address":"3 Chatham Street","City":"Dublin","State":"Dublin","Country":"Ireland","PostalCode":null,"Phone":"+353 01 6792424","Fax":null,"Email":"hughoreilly@apple.ie","SupportRepId":3}
{"CustomerId":47,"FirstName":"Lucas","LastName":"Mancini","Company":null,"Address":"Via Degli Scipioni, 43","City":"Rome","State":"RM","Country":"Italy","PostalCode":"00192","Phone":"+39 06 39733434","Fax":null,"Email":"lucas.mancini@yahoo.it","SupportRepId":5}
{"CustomerId":48,"FirstName":"Johannes","LastName":"Van der Berg","Company":null,"Address":"Lijnbaansgracht 120bg","City":"Amsterdam","State":"VV","Country":"Netherlands","PostalCode":"1016","Phone":"+31 020 6223130","Fax":null,"Email":"johavanderberg@yahoo.nl","SupportRepId":5}
{"CustomerId":49,"FirstName":"Stanislaw","LastName":"Wójcik","Company":null,"Address":"Ordynacka 10","City":"Warsaw","State":null,"Country":"Poland","PostalCode":"00-358","Phone":"+48 22 828 37 39","Fax":null,"Email":"stanislaw.wójcik@wp.pl","SupportRepId":4}
{"CustomerId":50,"FirstName":"Enrique","LastName":"Muńoz","Company":null,"Address":"C/ San Bernardo 85","City":"Madrid","State":null,"Country":"Spain","PostalCode":"28015","Phone":"+34 914 454 454","Fax":null,"Email":"enrique_munoz@yahoo.es","SupportRepId":5}
{"CustomerId":51,"FirstName":"Joakim","LastName":"Johansson","Company":null,"Address":"Celsiusg. 9","City":"Stockholm","State":null,"Country":"Sweden","PostalCode":"11230","Phone":"+46 08-651 52 52","Fax":null,"Email":"joakim.johansson@yahoo.se","SupportRepId":5}
{"CustomerId":52,"FirstName":"Emma","LastName":"Jones","Company":null,"Address":"202 Hoxton Street","City":"London","State":null,"Country":"United Kingdom","PostalCode":"N1 5LH","Phone":"+44 020 7707 0707","Fax":null,"Email":"emma_jones@hotmail.com","SupportRepId":3}
{"CustomerId":53,"FirstName":"Phil","LastName":"Hughes","Company":null,"Address":"113 Lupus St","City":"London","State":null,"Country":"United Kingdom","PostalCode":"SW1V 3EN","Phone":"+44 020 7976 5722","Fax":null,"Email":"phil.hughes@gmail.com","SupportRepId":3}
{"CustomerId":54,"FirstName":"Steve","LastName":"Murray","Company":null,"Address":"110 Raeburn Pl","City":"Edinburgh","State":null,"Country":"United Kingdom","PostalCode":"EH4 1HH","Phone":"+44 0131 315 3300","Fax":null,"Email":"steve.murray@yahoo.uk","SupportRepId":5}
{"CustomerId":55,"FirstName":"Mark","LastName":"Taylor","Company":null,"Address":"421 Bourke Street","City":"Sidney","State":"NSW","Country":"Australia","PostalCode":"2010","Phone":"+61 (02) 9332 3633","Fax":null,"Email":"mark.taylor@yahoo.au","SupportRepId":4}
{"CustomerId":56,"FirstName":"Diego","LastName":"Gutiérrez","Company":null,"Address":"307 Macacha Güemes","City":"Buenos Aires","State":null,"Country":"Argentina","PostalCode":"1106","Phone":"+54 (0)11 4311 4333","Fax":null,"Email":"diego.gutierrez@yahoo.ar","SupportRepId":4}
{"CustomerId":57,"FirstName":"Luis","LastName":"Rojas","Company":null,"Address":"Calle Lira, 198","City":"Santiago","State":null,"Country":"Chile","PostalCode":null,"Phone":"+56 (0)2 635 4444","Fax":null,"Email":"luisrojas@yahoo.cl","SupportRepId":5}
{"CustomerId":58,"FirstName":"Manoj","LastName":"Pareek","Company":null,"Address":"12,Community Centre","City":"Delhi","State":null,"Country":"India","PostalCode":"110017","Phone":"+91 0124 39883988","Fax":null,"Email":"manoj.pareek@rediff.com","SupportRepId":3}
{"CustomerId":59,"FirstName":"Puja","LastName":"Srivastava","Company":null,"Address":"3,Raj Bhavan Road","City":"Bangalore","State":null,"Country":"India","PostalCode":"560001","Phone":"+91 080 22289999","Fax":null,"Email":"puja_srivastava@yahoo.in","SupportRepId":3}

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