1
1
mirror of https://github.com/Fabio286/antares.git synced 2025-06-05 21:59:22 +02:00

Compare commits

..

67 Commits

Author SHA1 Message Date
861b704344 chore(release): 0.7.20-beta.1 2023-12-02 14:22:32 +01:00
9ce53165e8 chore: post merge cleanup 2023-12-02 14:21:34 +01:00
62614dceb9 Merge pull request #727 from antares-sql/flatpak-experiments
Flatpak experiments
2023-12-02 14:12:51 +01:00
8774dd44e6 Merge branch 'develop' into flatpak-experiments 2023-12-02 14:12:18 +01:00
f0ae01ca5e Merge branch 'develop' of https://github.com/antares-sql/antares into develop 2023-12-02 12:11:35 +01:00
03be777c2a refactor: worker threads to import sql dump instead of process 2023-12-02 11:35:20 +01:00
45a695ac0a refactor: improvements in worker implementation 2023-12-02 11:21:48 +01:00
c176841b75 refactor: worker threads to export sql dump instead of process 2023-12-02 09:31:54 +01:00
329246e2d8 refactor: minor refactor 2023-12-01 20:05:30 +01:00
e26809f260 fix(Flatpak): import/export schema not working 2023-12-01 14:18:40 +01:00
f13d4e6dce feat: copy element names on sidebar from context menu, closes #718 2023-11-29 18:15:22 +01:00
879de91516 refactor: minor refactor 2023-11-27 18:35:56 +01:00
38b32bfb28 build: process.exit on devtoolsInstaller 2023-11-27 13:37:24 +01:00
315d9d84c2 feat: logging errors on log file 2023-11-27 13:36:56 +01:00
c3d96cb35b refactor(Flatpak): temporarily disable import/export feature 2023-11-26 17:49:12 +01:00
05bd7672e1 chore: update package-lock.json 2023-11-26 17:28:45 +01:00
390bf88bb8 refactor: inport/export change for flatpak 2023-11-26 16:42:30 +01:00
984aa893d3 refactor: temporary disable windows process validation 2023-11-24 10:18:44 +01:00
1ac816eaa9 Merge branch 'master' of https://github.com/antares-sql/antares into develop 2023-11-16 18:30:05 +01:00
6f25fcbc05 ci: update workflow files 2023-11-16 18:16:41 +01:00
bc44465132 Merge branch 'master' of https://github.com/antares-sql/antares into develop 2023-11-16 18:09:51 +01:00
634a442213 ci: update workflow files 2023-11-16 18:01:40 +01:00
93fe28d07d chore(release): 0.7.20-beta.0 2023-11-15 21:36:27 +01:00
77a78078b2 chore(deps): update electron-builder 2023-11-14 15:14:59 +01:00
0da31254a9 Merge branch 'master' of https://github.com/antares-sql/antares into beta 2023-11-14 14:36:50 +01:00
b1aeabf2b6 ci: update gh actions scripts 2023-11-14 14:36:31 +01:00
f1c857fca9 chore(deps): update better-sqlite3 2023-11-14 10:38:26 +01:00
169f610b2e fix: error with multiple sessions in non-dev environment 2023-11-13 18:08:29 +01:00
075f542dc8 feat: ability to open multiple app sessions 2023-11-12 18:05:11 +01:00
664b2181be Merge pull request #712 from 64knl/feat/update-nl-translation
feat: Update Dutch translation
2023-11-12 15:43:15 +01:00
1bc95b0c2c fix: missing open folder icon for trigger, function and other database elements on sidebar 2023-11-10 18:12:07 +01:00
Rene
8628711374 feat: nl string updates 2023-11-10 15:21:22 +01:00
186fc18363 fix(Firebird SQL): error "Cannot read properties of null" connecting to some databases, fixes #708 2023-11-09 18:49:56 +01:00
e14302bdc0 feat(translation): add Ukrainian language, thanks to #707 2023-11-06 18:01:19 +01:00
13afc8bffd Merge pull request #710 from antares-sql/all-contributors/add-zvlad
docs: add zvlad as a contributor for translation
2023-11-06 09:15:12 +01:00
allcontributors[bot]
811be75c73 docs: update .all-contributorsrc [skip ci] 2023-11-06 08:14:38 +00:00
allcontributors[bot]
bddec52b40 docs: update README.md [skip ci] 2023-11-06 08:14:37 +00:00
e34af5bfa4 chore: update README.md 2023-11-03 18:26:58 +01:00
3322a06fed Merge pull request #703 from jimcat8/cn_main
Updated zh-CN.ts file
2023-11-03 13:17:19 +01:00
tianci
74040cee44 update 2023-11-02 17:52:13 +08:00
tianci
27c904e7f4 Updated zh-CN.ts file 2023-11-02 16:51:13 +08:00
6876dd6063 chore: add flathub badge in README.md 2023-11-02 09:25:13 +01:00
4d676a41cd chode: add flatpak assets 2023-11-01 12:12:14 +01:00
19d9f56f08 chore(release): 0.7.19 2023-11-01 09:43:50 +01:00
4c89578188 Merge branch 'develop' of https://github.com/antares-sql/antares into beta 2023-11-01 09:42:59 +01:00
f6fb266771 fix: table field changes not saved on text fields if pressing enter on textarea modal 2023-10-31 17:57:58 +01:00
3e739bcaa2 chore(release): 0.7.19-beta.2 2023-10-29 11:47:08 +01:00
debc1da289 fix: ssh tunnel keep-alive not working properly 2023-10-28 19:09:19 +02:00
3c2e2be40f chore: regenerate package-lock.json 2023-10-28 18:47:06 +02:00
581ec6a25d Merge branch 'develop' of https://github.com/antares-sql/antares into develop 2023-10-28 18:25:03 +02:00
d30a978cd6 refactor: replace ssh2-promise with @fabio286/ssh2-promise 2023-10-28 18:25:01 +02:00
0015f2e860 Merge branch 'master' of https://github.com/antares-sql/antares into develop 2023-10-28 11:58:06 +02:00
389e6624d8 chore: update stylelint dependencies 2023-10-28 11:55:18 +02:00
275344eb8b chore(release): 0.7.19-beta.1 2023-10-26 01:07:15 +02:00
cf24adf99e Merge branch 'develop' of https://github.com/antares-sql/antares into beta 2023-10-26 01:06:54 +02:00
2eae580e18 chore: update electron 2023-10-22 19:04:31 +02:00
e4eb27d503 feat(MySQL): RLIKE and NOT RLIKE regular expression filters, closes #688 2023-10-18 18:08:01 +02:00
580973fd04 chore(release): 0.7.19-beta.0 2023-10-14 15:04:00 +02:00
215ab783ab chore: email change 2023-10-14 15:03:09 +02:00
72148e991c Merge branch 'master' of https://github.com/antares-sql/antares into develop 2023-10-13 09:23:41 +02:00
6e4c16741a chore: Update CODE_OF_CONDUCT.md 2023-10-13 09:22:04 +02:00
9f9c63bfcc feat: "now" and "random" options added in datetime related data in insert rows tool, closes #402 2023-10-10 18:36:35 +02:00
c0dcf30e73 fix: IN and NOT IN filters not working properly, fixes #687 2023-10-09 18:13:30 +02:00
ddd290c903 fix: timeout issue on long time sql import 2023-10-03 18:19:16 +02:00
267c017921 chore(release): 0.7.18 2023-10-03 09:31:58 +02:00
b3b698b3a2 fix: hotfix for Microsoft Store unauthorized process 2023-10-03 09:31:26 +02:00
71ac3a5164 chore(release): 0.7.17 2023-09-30 16:46:49 +02:00
71 changed files with 19726 additions and 3857 deletions

View File

@@ -257,6 +257,15 @@
"contributions": [ "contributions": [
"translation" "translation"
] ]
},
{
"login": "zvlad",
"name": "Vladyslav",
"avatar_url": "https://avatars.githubusercontent.com/u/9055134?v=4",
"profile": "https://github.com/zvlad",
"contributions": [
"translation"
]
} }
], ],
"contributorsPerLine": 7, "contributorsPerLine": 7,

View File

@@ -13,8 +13,9 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: false
matrix: matrix:
os: [macos-11, ubuntu-latest, windows-latest] os: [macos-latest, ubuntu-latest, windows-latest]
steps: steps:
- name: Check out Git repository - name: Check out Git repository
@@ -25,7 +26,7 @@ jobs:
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 20
- name: Install dependencies - name: Install dependencies
run: npm i run: npm i

View File

@@ -13,8 +13,9 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: false
matrix: matrix:
os: [macos-11, ubuntu-latest, windows-latest] os: [macos-latest, ubuntu-latest, windows-latest]
steps: steps:
- name: Exit if not on master branch - name: Exit if not on master branch
@@ -31,7 +32,7 @@ jobs:
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 16 node-version: 20
- name: Install dependencies - name: Install dependencies
run: npm i run: npm i

View File

@@ -5,7 +5,7 @@ on:
jobs: jobs:
build: build:
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
steps: steps:
- name: Check out Git repository - name: Check out Git repository
uses: actions/checkout@v3 uses: actions/checkout@v3
@@ -13,7 +13,7 @@ jobs:
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 16 node-version: 20
- name: Install dependencies - name: Install dependencies
run: npm i run: npm i

View File

@@ -13,7 +13,7 @@ jobs:
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 16 node-version: 20
- name: npm install & build - name: npm install & build
run: | run: |
@@ -29,3 +29,30 @@ jobs:
build build
!build/*-unpacked !build/*-unpacked
!build/.icon-ico !build/.icon-ico
build-beta:
runs-on: macos-latest
steps:
- name: Check out Git repository
uses: actions/checkout@v3
with:
ref: beta
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 20
- name: npm install & build
run: |
npm install
npm run build
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: macos-build-beta
retention-days: 3
path: |
build
!build/*-unpacked
!build/.icon-ico

33
.github/workflows/test-builds.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Test build [DEVELOP]
on:
workflow_dispatch: {}
env:
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
jobs:
release:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
steps:
- name: Check out Git repository
uses: actions/checkout@v3
with:
ref: develop
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 20
- name: Install dependencies
run: npm i
- name: "Build"
run: npm run build

BIN
.nvmrc Normal file

Binary file not shown.

View File

@@ -10,7 +10,8 @@
"translation", "translation",
"Linux", "Linux",
"MacOS", "MacOS",
"deps" "deps",
"Flatpak"
], ],
"svg.preview.background": "transparent" "svg.preview.background": "transparent"
} }

View File

@@ -2,6 +2,78 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [0.7.20-beta.1](https://github.com/antares-sql/antares/compare/v0.7.20-beta.0...v0.7.20-beta.1) (2023-12-02)
### Features
* copy element names on sidebar from context menu, closes [#718](https://github.com/antares-sql/antares/issues/718) ([f13d4e6](https://github.com/antares-sql/antares/commit/f13d4e6dceb70b0c7cb8d56ddfb5f00e938571cc))
* logging errors on log file ([315d9d8](https://github.com/antares-sql/antares/commit/315d9d84c2caa29852d68bd189750b2a4028d953))
### Bug Fixes
* **Flatpak:** import/export schema not working ([e26809f](https://github.com/antares-sql/antares/commit/e26809f260099ba194bf5d00671cae14d438197b))
### [0.7.20-beta.0](https://github.com/antares-sql/antares/compare/v0.7.19...v0.7.20-beta.0) (2023-11-15)
### Features
* ability to open multiple app sessions ([075f542](https://github.com/antares-sql/antares/commit/075f542dc8f4a48bef07b86b78c40d03fcdccc56))
* nl string updates ([8628711](https://github.com/antares-sql/antares/commit/8628711374269c29c4b1e6722fe66b0d8179477e))
* **translation:** add Ukrainian language, thanks to [#707](https://github.com/antares-sql/antares/issues/707) ([e14302b](https://github.com/antares-sql/antares/commit/e14302bdc0038b84a1a06089753205149cd1a92b))
### Bug Fixes
* error with multiple sessions in non-dev environment ([169f610](https://github.com/antares-sql/antares/commit/169f610b2ee4857661ec3da7f04b628fec21f1f0))
* **Firebird SQL:** error "Cannot read properties of null" connecting to some databases, fixes [#708](https://github.com/antares-sql/antares/issues/708) ([186fc18](https://github.com/antares-sql/antares/commit/186fc18363b6f14678465a8e38d85b1319e47b50))
* missing open folder icon for trigger, function and other database elements on sidebar ([1bc95b0](https://github.com/antares-sql/antares/commit/1bc95b0c2cd91bbf0410a23266e23bbbf2a71995))
### [0.7.19](https://github.com/antares-sql/antares/compare/v0.7.19-beta.2...v0.7.19) (2023-11-01)
### Bug Fixes
* table field changes not saved on text fields if pressing enter on textarea modal ([f6fb266](https://github.com/antares-sql/antares/commit/f6fb266771f2d798c8ae42b997c1e33520cf21c3))
### [0.7.19-beta.2](https://github.com/antares-sql/antares/compare/v0.7.19-beta.1...v0.7.19-beta.2) (2023-10-29)
### Bug Fixes
* ssh tunnel keep-alive not working properly ([debc1da](https://github.com/antares-sql/antares/commit/debc1da289d5e35d59adf69d094b329cf93af536))
### [0.7.19-beta.1](https://github.com/antares-sql/antares/compare/v0.7.19-beta.0...v0.7.19-beta.1) (2023-10-25)
### Features
* **MySQL:** RLIKE and NOT RLIKE regular expression filters, closes [#688](https://github.com/antares-sql/antares/issues/688) ([e4eb27d](https://github.com/antares-sql/antares/commit/e4eb27d503e8f912178359c01c62a9b523d17848))
### [0.7.19-beta.0](https://github.com/antares-sql/antares/compare/v0.7.18...v0.7.19-beta.0) (2023-10-14)
### Features
* "now" and "random" options added in datetime related data in insert rows tool, closes [#402](https://github.com/antares-sql/antares/issues/402) ([9f9c63b](https://github.com/antares-sql/antares/commit/9f9c63bfcc3423bfeef143cd835f48c62900a799))
### Bug Fixes
* IN and NOT IN filters not working properly, fixes [#687](https://github.com/antares-sql/antares/issues/687) ([c0dcf30](https://github.com/antares-sql/antares/commit/c0dcf30e73a69b25b01ba31d21b27c1983ed2db6))
* timeout issue on long time sql import ([ddd290c](https://github.com/antares-sql/antares/commit/ddd290c90344241eaa70cb528552e942fd7edec0))
### [0.7.18](https://github.com/antares-sql/antares/compare/v0.7.17...v0.7.18) (2023-10-03)
### Bug Fixes
* hotfix for Microsoft Store unauthorized process ([b3b698b](https://github.com/antares-sql/antares/commit/b3b698b3a23a3c848921ab40fc0fec5d8178ef0e))
### [0.7.17](https://github.com/antares-sql/antares/compare/v0.7.17-beta.2...v0.7.17) (2023-09-30)
### [0.7.17-beta.2](https://github.com/antares-sql/antares/compare/v0.7.17-beta.1...v0.7.17-beta.2) (2023-09-28) ### [0.7.17-beta.2](https://github.com/antares-sql/antares/compare/v0.7.17-beta.1...v0.7.17-beta.2) (2023-09-28)

View File

@@ -61,7 +61,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at reported to the community leaders responsible for enforcement at
fabio286@gmail.com. info@fabiodistasio.it.
All complaints will be reviewed and investigated promptly and fairly. All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the All community leaders are obligated to respect the privacy and security of the

View File

@@ -7,8 +7,7 @@
# Antares SQL Client # Antares SQL Client
![GitHub package.json version](https://img.shields.io/github/package-json/v/fabio286/antares) ![GitHub](https://img.shields.io/github/license/fabio286/antares) [![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Ffabio286%2Fantares%2Fbadge&style=flat)](https://actions-badge.atrox.dev/fabio286/antares/goto) [![antares](https://snapcraft.io/antares/badge.svg)](https://snapcraft.io/antares) [![antares](https://snapcraft.io/antares/trending.svg?name=0)](https://snapcraft.io/antares) ![GitHub package.json version](https://img.shields.io/github/package-json/v/fabio286/antares) ![GitHub](https://img.shields.io/github/license/fabio286/antares) [![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Ffabio286%2Fantares%2Fbadge&style=flat)](https://actions-badge.atrox.dev/fabio286/antares/goto) ![Mastodon Follow](https://img.shields.io/mastodon/follow/%20110860460902482117?domain=https%3A%2F%2Ffosstodon.org&style=social) [![Twitter Follow](https://img.shields.io/twitter/follow/AntaresSQL?style=social)](https://twitter.com/AntaresSQL) [![Plant a Tree](https://raw.githubusercontent.com/Fabio286/treedom-badge/master/svg/plant-a-tree.svg)](https://www.treedom.net/en/user/fabio-di-stasio/event/antares-for-the-planet)
![Mastodon Follow](https://img.shields.io/mastodon/follow/%20110860460902482117?domain=https%3A%2F%2Ffosstodon.org&style=social) [![Twitter Follow](https://img.shields.io/twitter/follow/AntaresSQL?style=social)](https://twitter.com/AntaresSQL) [![Plant a Tree](https://raw.githubusercontent.com/Fabio286/treedom-badge/master/svg/plant-a-tree.svg)](https://www.treedom.net/en/user/fabio-di-stasio/event/antares-for-the-planet)
Antares is an SQL client based on [Electron.js](https://github.com/electron/electron) and [Vue.js](https://github.com/vuejs/vue) that aims to become a useful tool, especially for developers. Antares is an SQL client based on [Electron.js](https://github.com/electron/electron) and [Vue.js](https://github.com/vuejs/vue) that aims to become a useful tool, especially for developers.
Our target is to support as many databases as possible, and all major operating systems, including the ARM versions. Our target is to support as many databases as possible, and all major operating systems, including the ARM versions.
@@ -21,7 +20,8 @@ We are actively working on it, hoping to provide new cool features, improvements
👁 To stay tuned for new releases follow Antares SQL on [Mastodon](https://fosstodon.org/@AntaresSQL) or [Twitter](https://twitter.com/AntaresSQL). 👁 To stay tuned for new releases follow Antares SQL on [Mastodon](https://fosstodon.org/@AntaresSQL) or [Twitter](https://twitter.com/AntaresSQL).
🌟 Don't forget to **leave a star** if you appreciate this project. 🌟 Don't forget to **leave a star** if you appreciate this project.
🗳️ Polls: 🗳️ Polls:
- **[Which is the main OS you use Antares on?](https://github.com/antares-sql/antares/discussions/379)** - **[Which is the main OS you use Antares on?](https://github.com/antares-sql/antares/discussions/379)**
- **[Which database do you use the most?](https://github.com/antares-sql/antares/discussions/594)** - **[Which database do you use the most?](https://github.com/antares-sql/antares/discussions/594)**
@@ -55,7 +55,7 @@ Since Antares SQL is a free software we don't have a budget to spend on annual l
### Linux ### Linux
On Linux you can simply download and run the `.AppImage` distribution, install from Snap Store, from AUR or from our [PPA repository](https://github.com/antares-sql/antares-ppa). On Linux you can simply download and run the `.AppImage` distribution, install from FlatHub, Snap Store, AUR or from our [PPA repository](https://github.com/antares-sql/antares-ppa).
### Windows ### Windows
@@ -67,8 +67,8 @@ On macOS you can run `.dmg` distribution following [this guide](https://support.
## Download ## Download
[![Get it from the Snap Store](https://snapcraft.io/static/images/badges/en/snap-store-black.svg)](https://snapcraft.io/antares) [![Get it from AUR](https://raw.githubusercontent.com/Fabio286/antares/3e00c4bae6e036300c752c1a40c5a038fea9c169/docs/aur-badge.svg)](https://aur.archlinux.org/packages/antares-sql-bin) [<img src="https://developer.microsoft.com/store/badges/images/English_get-it-from-MS.png" style="height: 56px">](https://www.microsoft.com/p/antares-sql-client/9nhtb9sq51r1?cid=storebadge&ocid=badge&rtc=1&activetab=pivot:overviewtab) [<img height='56' alt='Download on Flathub' src='https://dl.flathub.org/assets/badges/flathub-badge-en.svg'/>](https://flathub.org/apps/it.fabiodistasio.AntaresSQL) [![Get it from the Snap Store](https://snapcraft.io/static/images/badges/en/snap-store-black.svg)](https://snapcraft.io/antares) [![Get it from AUR](https://raw.githubusercontent.com/antares-sql/antares/master/docs/aur-badge.svg)](https://aur.archlinux.org/packages/antares-sql-bin) [<img src="https://developer.microsoft.com/store/badges/images/English_get-it-from-MS.png" style="height: 56px">](https://www.microsoft.com/p/antares-sql-client/9nhtb9sq51r1?cid=storebadge&ocid=badge&rtc=1&activetab=pivot:overviewtab)
🚀 **[Other Downloads](https://github.com/Fabio286/antares/releases/latest)** 🚀 **[Other Downloads](https://github.com/antares-sql/antares/releases/latest)**
## Coming soon ## Coming soon
@@ -155,6 +155,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zxp19821005"><img src="https://avatars.githubusercontent.com/u/4915850?v=4?s=100" width="100px;" alt="Woodenman"/><br /><sub><b>Woodenman</b></sub></a><br /><a href="#platform-zxp19821005" title="Packaging/porting to new platform">📦</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/zxp19821005"><img src="https://avatars.githubusercontent.com/u/4915850?v=4?s=100" width="100px;" alt="Woodenman"/><br /><sub><b>Woodenman</b></sub></a><br /><a href="#platform-zxp19821005" title="Packaging/porting to new platform">📦</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/markusand"><img src="https://avatars.githubusercontent.com/u/12972543?v=4?s=100" width="100px;" alt="Marc Vilella"/><br /><sub><b>Marc Vilella</b></sub></a><br /><a href="#translation-markusand" title="Translation">🌍</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/markusand"><img src="https://avatars.githubusercontent.com/u/12972543?v=4?s=100" width="100px;" alt="Marc Vilella"/><br /><sub><b>Marc Vilella</b></sub></a><br /><a href="#translation-markusand" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Lawondyss"><img src="https://avatars.githubusercontent.com/u/272130?v=4?s=100" width="100px;" alt="Ladislav Vondráček"/><br /><sub><b>Ladislav Vondráček</b></sub></a><br /><a href="#translation-Lawondyss" title="Translation">🌍</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/Lawondyss"><img src="https://avatars.githubusercontent.com/u/272130?v=4?s=100" width="100px;" alt="Ladislav Vondráček"/><br /><sub><b>Ladislav Vondráček</b></sub></a><br /><a href="#translation-Lawondyss" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zvlad"><img src="https://avatars.githubusercontent.com/u/9055134?v=4?s=100" width="100px;" alt="Vladyslav"/><br /><sub><b>Vladyslav</b></sub></a><br /><a href="#translation-zvlad" title="Translation">🌍</a></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@@ -0,0 +1,9 @@
[Desktop Entry]
Name=Antares SQL
Exec=startantares
Terminal=false
Type=Application
Icon=it.fabiodistasio.AntaresSQL
StartupWMClass=antares
Comment=A modern, fast and productivity driven SQL client with a focus in UX
Categories=Development;

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>it.fabiodistasio.AntaresSQL</id>
<name>Antares SQL</name>
<metadata_license>CC0-1.0</metadata_license>
<project_license>MIT</project_license>
<developer_name>Fabio Di Stasio</developer_name>
<summary>A modern, fast and productivity driven SQL client with a focus in UX</summary>
<url type="homepage">https://antares-sql.app/</url>
<url type="bugtracker">https://github.com/antares-sql/antares/issues</url>
<url type="help">https://github.com/antares-sql/antares/discussions</url>
<url type="donation">https://paypal.me/fabiodistasio</url>
<description>
<p>Antares is an SQL client that aims to become an useful and complete tool, especially for developers. </p>
<p>The main goal is to develop a totally free, full featured, cross platform and open source alternative.
A modern application created with minimalism and semplicity in mind, with features in the right places, not hundreds of tiny buttons, nested tabs or submenu; productivity comes first.</p>
<p>Supported database: </p>
<ul>
<li>MySQL/MariaDB</li>
<li>PostgreSQL</li>
<li>SQLite</li>
<li>Firebird SQL</li>
</ul>
</description>
<screenshots>
<screenshot type="default">
<image type="source">https://lh3.googleusercontent.com/drive-viewer/AK7aPaC00fbmJIUcfwSPv-hjoxEmHS8NapR8qyOqOpopMIdcDFqYKNDs5mdIK08hnhZdHMrozTfR4Hx3Yj6bQ0zgfStEEFhxWg=s1600</image>
</screenshot>
</screenshots>
<content_rating type="oars-1.1" />
<releases>
<release version="v0.7.19" date="2023-11-01"/>
</releases>
</component>

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -1,76 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns="http://www.w3.org/2000/svg" style="isolation:isolate" width="182" height="56">
<!-- Generator: Gravit.io --><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
style="isolation:isolate" viewBox="0 0 182 56" width="182px" height="56px">
<defs> <defs>
<clipPath id="_clipPath_tR1uglJ1Zei76xP861DY1TsjAiQWS9qF"> <clipPath id="prefix__a">
<rect width="182" height="56" /> <path d="M0 0h182v56H0z" />
</clipPath> </clipPath>
</defs> </defs>
<g clip-path="url(#_clipPath_tR1uglJ1Zei76xP861DY1TsjAiQWS9qF)"> <g clip-path="url(#prefix__a)">
<path <!-- <path d="M2.5.5h178a2 2 0 012 2v52a2 2 0 01-2 2H2.5a2 2 0" fill="#252525" stroke="#FFF" stroke-width="2"/> -->
d="M 2.5 0.5 L 180.5 0.5 C 181.604 0.5 182.5 1.396 182.5 2.5 L 182.5 54.5 C 182.5 55.604 181.604 56.5 180.5 56.5 L 2.5 56.5 C 1.396 56.5 0.5 55.604 0.5 54.5 L 0.5 2.5 C 0.5 1.396 1.396 0.5 2.5 0.5 Z" <rect x="0" y="0" width="182" height="56" fill="#252525" stroke="#FFF" stroke-width="1" rx="0" />
style="stroke:none;fill:#252525;stroke-miterlimit:10;" />
<path <g fill-rule="evenodd" fill="#FFF">
d="M 2.5 0.5 L 180.5 0.5 C 181.604 0.5 182.5 1.396 182.5 2.5 L 182.5 54.5 C 182.5 55.604 181.604 56.5 180.5 56.5 L 2.5 56.5 C 1.396 56.5 0.5 55.604 0.5 54.5 L 0.5 2.5 C 0.5 1.396 1.396 0.5 2.5 0.5 Z"
style="fill:none;stroke:#CDCDCD;stroke-width:1;stroke-miterlimit:2;" />
<g>
<g>
<path
d=" M 60.898 13.777 C 58.555 13.774 56.61 14.254 55.858 14.516 L 55.083 18.697 C 55.081 18.712 58.937 17.669 60.635 17.73 C 63.447 17.831 63.706 18.805 63.656 20.119 C 63.704 20.196 62.931 18.931 60.498 18.889 C 57.43 18.836 53.098 19.976 53.104 24.608 C 53.022 29.818 56.997 31.351 59.704 31.379 C 62.138 31.335 63.279 30.458 63.904 29.988 C 64.726 29.129 65.665 28.265 66.561 27.229 C 65.714 28.77 64.978 29.835 64.213 30.651 L 64.213 31.339 L 67.913 30.716 L 67.938 20.66 C 67.901 19.237 68.754 13.791 60.898 13.777 Z M 60.367 22.533 C 61.9 22.554 63.659 23.31 63.662 25.129 C 63.669 26.784 61.589 27.674 60.235 27.66 C 58.881 27.646 57.085 26.596 57.077 24.982 C 57.103 23.54 58.771 22.496 60.367 22.533 Z "
fill-rule="evenodd" fill="rgb(255,255,255)" />
<path
d=" M 70.378 14.707 L 70.352 31.36 L 74.662 30.529 L 74.67 21.087 C 74.671 19.681 76.679 18.039 79.198 18.065 C 79.733 17.097 80.738 14.625 80.983 14.062 C 75.354 14.049 75.282 15.68 74.303 16.483 C 74.293 14.952 74.3 14.033 74.3 14.033 L 70.378 14.707 L 70.378 14.707 Z "
fill-rule="evenodd" fill="rgb(255,255,255)" />
<path
d=" M 94.632 16.893 C 94.591 16.873 92.385 14.312 87.949 14.292 C 83.795 14.223 79.135 15.834 79.061 22.8 C 79.097 28.925 83.537 31.318 87.973 31.365 C 92.72 31.414 94.609 28.396 94.722 28.322 C 94.156 27.83 92.034 25.728 92.034 25.728 C 92.034 25.728 90.709 27.615 88.138 27.639 C 85.566 27.664 83.331 25.651 83.299 22.844 C 83.266 20.036 85.354 18.515 88.157 18.392 C 90.584 18.392 91.984 19.959 91.984 19.959 L 94.632 16.893 L 94.632 16.893 Z "
fill-rule="evenodd" fill="rgb(255,255,255)" />
<path
d=" M 100.065 8.879 L 95.996 9.835 L 96.026 31.526 L 100.034 30.802 L 100.08 20.595 C 100.089 19.524 101.628 17.88 104.2 17.933 C 106.658 17.958 107.207 19.571 107.201 19.775 L 107.272 31.592 L 111.224 30.894 L 111.239 18.363 C 111.265 17.157 108.598 14.61 104.311 14.592 C 102.273 14.596 101.145 15.057 100.571 15.397 C 99.588 16.156 98.466 16.883 97.362 17.811 C 98.382 16.501 99.239 15.595 100.075 14.921 L 100.065 8.879 L 100.065 8.879 Z "
fill-rule="evenodd" fill="rgb(255,255,255)" />
</g>
<g>
<path
d=" M 114.673 9.441 L 116.508 8.982 L 116.595 30.85 L 114.73 31.168 L 114.673 9.441 L 114.673 9.441 Z "
fill-rule="evenodd" fill="rgb(23,147,209)" />
<path
d=" M 119.663 15.968 L 121.271 15.252 L 121.285 30.932 L 119.731 31.253 L 119.663 15.968 L 119.663 15.968 Z M 119.28 10.314 L 120.577 9.255 L 121.655 10.454 L 120.357 11.54 L 119.28 10.314 L 119.28 10.314 Z "
fill-rule="evenodd" fill="rgb(23,147,209)" />
<path
d=" M 124.296 15.682 L 126.131 15.308 L 126.14 18.586 C 126.14 18.727 127.148 14.924 132.008 15.009 C 136.727 15.035 137.499 18.688 137.473 19.507 L 137.531 31.034 L 135.922 31.384 L 135.913 19.998 C 135.932 19.665 135.178 16.853 131.843 16.843 C 128.509 16.833 126.199 19.265 126.203 20.818 L 126.229 30.848 L 124.365 31.335 L 124.296 15.682 L 124.296 15.682 Z "
fill-rule="evenodd" fill="rgb(23,147,209)" />
<path
d=" M 153.547 31.117 L 151.711 31.492 L 151.703 28.214 C 151.703 28.073 150.694 31.876 145.835 31.791 C 141.116 31.765 140.344 28.112 140.37 27.293 L 140.311 15.765 L 142.261 15.372 L 142.292 26.758 C 142.292 27.069 142.665 29.947 145.999 29.957 C 149.334 29.967 151.669 27.949 151.686 24.911 L 151.662 15.928 L 153.477 15.464 L 153.547 31.117 L 153.547 31.117 Z "
fill-rule="evenodd" fill="rgb(23,147,209)" />
<path
d=" M 157.144 15.553 L 155.857 16.56 L 160.792 23.018 L 155.529 30.478 L 156.894 31.492 L 161.841 24.563 L 166.948 31.656 L 168.211 30.649 L 162.738 23.065 L 167.104 16.933 L 165.762 15.797 L 161.785 21.472 L 157.144 15.553 L 157.144 15.553 Z "
fill-rule="evenodd" fill="rgb(23,147,209)" />
</g>
<path <path
d=" M 33.112 3.879 C 30.965 9.143 29.67 12.587 27.279 17.695 C 28.745 19.248 30.544 21.058 33.466 23.101 C 30.325 21.809 28.182 20.511 26.581 19.164 C 23.521 25.549 18.728 34.643 9 52.121 C 16.645 47.707 22.572 44.986 28.095 43.948 C 27.858 42.928 27.723 41.824 27.733 40.673 L 27.742 40.428 C 27.863 35.53 30.411 31.763 33.43 32.019 C 36.448 32.274 38.794 36.455 38.673 41.353 C 38.65 42.275 38.546 43.162 38.364 43.984 C 43.828 45.053 49.691 47.767 57.233 52.121 C 55.746 49.383 54.419 46.915 53.151 44.565 C 51.154 43.017 49.072 41.003 44.823 38.822 C 47.743 39.581 49.834 40.456 51.464 41.435 C 38.575 17.439 37.532 14.251 33.112 3.879 Z " d="M60.898 13.777c-2.343-.003-4.288.477-5.04.739l-.775 4.181c-.002.015 3.854-1.028 5.552-.967 2.812.101 3.071 1.075 3.021 2.389.048.077-.725-1.188-3.158-1.23-3.068-.053-7.4 1.087-7.394 5.719-.082 5.21 3.893 6.743 6.6 6.771 2.434-.044 3.575-.921 4.2-1.391.822-.859 1.761-1.723 2.657-2.759-.847 1.541-1.583 2.606-2.348 3.422v.688l3.7-.623.025-10.056c-.037-1.423.816-6.869-7.04-6.883zm-.531 8.756c1.533.021 3.292.777 3.295 2.596.007 1.655-2.073 2.545-3.427 2.531-1.354-.014-3.15-1.064-3.158-2.678.026-1.442 1.694-2.486 3.29-2.449zM70.378 14.707l-.026 16.653 4.31-.831.008-9.442c.001-1.406 2.009-3.048 4.528-3.022.535-.968 1.54-3.44 1.785-4.003-5.629-.013-5.701 1.618-6.68 2.421-.01-1.531-.003-2.45-.003-2.45l-3.922.674zM94.632 16.893c-.041-.02-2.247-2.581-6.683-2.601-4.154-.069-8.814 1.542-8.888 8.508.036 6.125 4.476 8.518 8.912 8.565 4.747.049 6.636-2.969 6.749-3.043-.566-.492-2.688-2.594-2.688-2.594s-1.325 1.887-3.896 1.911c-2.572.025-4.807-1.988-4.839-4.795-.033-2.808 2.055-4.329 4.858-4.452 2.427 0 3.827 1.567 3.827 1.567l2.648-3.066zM100.065 8.879l-4.069.956.03 21.691 4.008-.724.046-10.207c.009-1.071 1.548-2.715 4.12-2.662 2.458.025 3.007 1.638 3.001 1.842l.071 11.817 3.952-.698.015-12.531c.026-1.206-2.641-3.753-6.928-3.771-2.038.004-3.166.465-3.74.805-.983.759-2.105 1.486-3.209 2.414 1.02-1.31 1.877-2.216 2.713-2.89l-.01-6.042z" />
fill-rule="evenodd" fill="rgb(23,147,209)" />
<g>
<path
d=" M 170.614 30.156 L 170.614 28.802 L 170.109 28.802 L 170.109 28.621 L 171.325 28.621 L 171.325 28.802 L 170.817 28.802 L 170.817 30.156 L 170.614 30.156 Z "
fill="rgb(23,147,209)" />
<path
d=" M 171.536 30.156 L 171.536 28.621 L 171.842 28.621 L 172.205 29.708 C 172.238 29.809 172.263 29.884 172.278 29.935 C 172.295 29.879 172.323 29.797 172.36 29.689 L 172.727 28.621 L 173 28.621 L 173 30.156 L 172.804 30.156 L 172.804 28.871 L 172.358 30.156 L 172.175 30.156 L 171.732 28.849 L 171.732 30.156 L 171.536 30.156 Z "
fill="rgb(23,147,209)" />
</g>
<g>
<path
d=" M 57.471 47.815 L 57.471 46.493 L 56.977 46.493 L 56.977 46.316 L 58.166 46.316 L 58.166 46.493 L 57.67 46.493 L 57.67 47.815 L 57.471 47.815 Z "
fill="rgb(23,147,209)" />
<path
d=" M 58.372 47.815 L 58.372 46.316 L 58.671 46.316 L 59.026 47.377 C 59.059 47.476 59.083 47.55 59.098 47.599 C 59.115 47.545 59.141 47.465 59.177 47.359 L 59.536 46.316 L 59.803 46.316 L 59.803 47.815 L 59.612 47.815 L 59.612 46.56 L 59.176 47.815 L 58.997 47.815 L 58.564 46.539 L 58.564 47.815 L 58.372 47.815"
fill="rgb(23,147,209)" />
</g>
</g> </g>
<g clip-path="url(#_clipPath_NvFIpNfWUS6M4fZAtfyVzggsKR3URDoi)"><text transform="matrix(1,0,0,1,87.023,43.899)" <g fill-rule="evenodd" fill="#1793D1">
style="font-family:'Open Sans';font-weight:700;font-size:11px;font-style:normal;fill:#ffffff;stroke:none;">user <path
repository</text></g> d="M114.673 9.441l1.835-.459.087 21.868-1.865.318-.057-21.727zM119.663 15.968l1.608-.716.014 15.68-1.554.321-.068-15.285zm-.383-5.654l1.297-1.059 1.078 1.199-1.298 1.086-1.077-1.226zM124.296 15.682l1.835-.374.009 3.278c0 .141 1.008-3.662 5.868-3.577 4.719.026 5.491 3.679 5.465 4.498l.058 11.527-1.609.35-.009-11.386c.019-.333-.735-3.145-4.07-3.155-3.334-.01-5.644 2.422-5.64 3.975l.026 10.03-1.864.487-.069-15.653zM153.547 31.117l-1.836.375-.008-3.278c0-.141-1.009 3.662-5.868 3.577-4.719-.026-5.491-3.679-5.465-4.498l-.059-11.528 1.95-.393.031 11.386c0 .311.373 3.189 3.707 3.199 3.335.01 5.67-2.008 5.687-5.046l-.024-8.983 1.815-.464.07 15.653zM157.144 15.553l-1.287 1.007 4.935 6.458-5.263 7.46 1.365 1.014 4.947-6.929 5.107 7.093 1.263-1.007-5.473-7.584 4.366-6.132-1.342-1.136-3.977 5.675-4.641-5.919z" />
</g>
<path
d="M33.112 3.879c-2.147 5.264-3.442 8.708-5.833 13.816 1.466 1.553 3.265 3.363 6.187 5.406-3.141-1.292-5.284-2.59-6.885-3.937C23.521 25.549 18.728 34.643 9 52.121c7.645-4.414 13.572-7.135 19.095-8.173a13.965 13.965 0 01-.362-3.275l.009-.245c.121-4.898 2.669-8.665 5.688-8.409 3.018.255 5.364 4.436 5.243 9.334a13.819 13.819 0 01-.309 2.631c5.464 1.069 11.327 3.783 18.869 8.137-1.487-2.738-2.814-5.206-4.082-7.556-1.997-1.548-4.079-3.562-8.328-5.743 2.92.759 5.011 1.634 6.641 2.613C38.575 17.439 37.532 14.251 33.112 3.879z"
fill-rule="evenodd" fill="#1793D1" />
<g fill="#1793D1">
<path
d="M170.614 30.156v-1.354h-.505v-.181h1.216v.181h-.508v1.354h-.203zM171.536 30.156v-1.535h.306l.363 1.087c.033.101.058.176.073.227a8.63 8.63 0 01.082-.246l.367-1.068H173v1.535h-.196v-1.285l-.446 1.285h-.183l-.443-1.307v1.307h-.196z" />
</g>
<g fill="#1793D1">
<path
d="M57.471 47.815v-1.322h-.494v-.177h1.189v.177h-.496v1.322h-.199zM58.372 47.815v-1.499h.299l.355 1.061.072.222c.017-.054.043-.134.079-.24l.359-1.043h.267v1.499h-.191V46.56l-.436 1.255h-.179l-.433-1.276v1.276h-.192" />
</g>
<g clip-path="url(#prefix__b)"><text transform="translate(95.023 43.899)" font-family="sans-serif"
font-weight="700" font-size="10" fill="#fff">user repository</text></g>
<defs> <defs>
<clipPath id="_clipPath_NvFIpNfWUS6M4fZAtfyVzggsKR3URDoi"> <clipPath id="prefix__b">
<rect x="0" y="0" width="86" height="14.98" transform="matrix(1,0,0,1,87,32.142)" /> <path transform="translate(87 32.142)" d="M0 0h86v14.98H0z" />
</clipPath> </clipPath>
</defs> </defs>
</g> </g>

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

21278
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{ {
"name": "antares", "name": "antares",
"productName": "Antares", "productName": "Antares",
"version": "0.7.17-beta.2", "version": "0.7.20-beta.1",
"description": "A modern, fast and productivity driven SQL client with a focus in UX.", "description": "A modern, fast and productivity driven SQL client with a focus in UX.",
"license": "MIT", "license": "MIT",
"repository": "https://github.com/antares-sql/antares.git", "repository": "https://github.com/antares-sql/antares.git",
@@ -27,7 +27,7 @@
"contributors:add": "all-contributors add", "contributors:add": "all-contributors add",
"contributors:generate": "all-contributors generate" "contributors:generate": "all-contributors generate"
}, },
"author": "Fabio Di Stasio <fabio286@gmail.com>", "author": "Fabio Di Stasio <info@fabiodistasio.it>",
"main": "./dist/main.js", "main": "./dist/main.js",
"antares": { "antares": {
"devtoolsId": "nhdogjmejiglipccpnnnanhbledajbpd" "devtoolsId": "nhdogjmejiglipccpnnnanhbledajbpd"
@@ -119,14 +119,15 @@
}, },
"dependencies": { "dependencies": {
"@electron/remote": "~2.0.1", "@electron/remote": "~2.0.1",
"@fabio286/ssh2-promise": "~1.0.4-b",
"@faker-js/faker": "~6.1.2", "@faker-js/faker": "~6.1.2",
"@jamescoyle/vue-icon": "~0.1.2", "@jamescoyle/vue-icon": "~0.1.2",
"@mdi/js": "~7.2.96", "@mdi/js": "~7.2.96",
"@turf/helpers": "~6.5.0", "@turf/helpers": "~6.5.0",
"@vueuse/core": "~10.4.1", "@vueuse/core": "~10.4.1",
"ace-builds": "~1.24.1", "ace-builds": "~1.24.1",
"better-sqlite3": "~8.0.0", "better-sqlite3": "~9.1.1",
"electron-log": "~4.4.1", "electron-log": "~5.0.1",
"electron-store": "~8.1.0", "electron-store": "~8.1.0",
"electron-updater": "~4.6.5", "electron-updater": "~4.6.5",
"electron-window-state": "~5.0.3", "electron-window-state": "~5.0.3",
@@ -146,7 +147,6 @@
"source-map-support": "~0.5.20", "source-map-support": "~0.5.20",
"spectre.css": "~0.5.9", "spectre.css": "~0.5.9",
"sql-formatter": "~13.0.0", "sql-formatter": "~13.0.0",
"ssh2-promise": "~1.0.2",
"v-mask": "~2.3.0", "v-mask": "~2.3.0",
"vue": "~3.3.4", "vue": "~3.3.4",
"vue-i18n": "~9.2.2", "vue-i18n": "~9.2.2",
@@ -171,8 +171,8 @@
"chalk": "~4.1.2", "chalk": "~4.1.2",
"cross-env": "~7.0.2", "cross-env": "~7.0.2",
"css-loader": "~6.5.0", "css-loader": "~6.5.0",
"electron": "~22.3.23", "electron": "~22.3.27",
"electron-builder": "~22.10.3", "electron-builder": "~24.6.4",
"eslint": "~7.32.0", "eslint": "~7.32.0",
"eslint-config-standard": "~16.0.3", "eslint-config-standard": "~16.0.3",
"eslint-plugin-import": "~2.24.2", "eslint-plugin-import": "~2.24.2",
@@ -193,10 +193,10 @@
"sass-loader": "~12.3.0", "sass-loader": "~12.3.0",
"standard-version": "~9.3.1", "standard-version": "~9.3.1",
"style-loader": "~3.3.1", "style-loader": "~3.3.1",
"stylelint": "~14.9.1", "stylelint": "^15.11.0",
"stylelint-config-recommended-vue": "~1.4.0", "stylelint-config-recommended-vue": "~1.5.0",
"stylelint-config-standard": "~26.0.0", "stylelint-config-standard": "~34.0.0",
"stylelint-scss": "~4.3.0", "stylelint-scss": "~5.3.0",
"tree-kill": "~1.2.2", "tree-kill": "~1.2.2",
"ts-loader": "~9.2.8", "ts-loader": "~9.2.8",
"ts-node": "~10.9.1", "ts-node": "~10.9.1",
@@ -208,10 +208,5 @@
"webpack-cli": "~4.9.1", "webpack-cli": "~4.9.1",
"webpack-dev-server": "~4.11.1", "webpack-dev-server": "~4.11.1",
"xvfb-maybe": "~0.2.1" "xvfb-maybe": "~0.2.1"
},
"overrides": {
"ssh2-promise": {
"ssh2": "github:Fabio286/ssh2"
}
} }
} }

View File

@@ -63,43 +63,39 @@ async function restartElectron () {
if (!manualRestart) process.exit(0); if (!manualRestart) process.exit(0);
}); });
} }
function startWorkers () {
const compiler = webpack(workersConfig);
const { name } = compiler;
function startMain () { compiler.hooks.afterEmit.tap('afterEmit', () => {
const webpackSetup = webpack([mainConfig, workersConfig]); console.log(chalk.gray(`\nCompiled ${name} script!`));
console.log(chalk.gray(`\nWatching file changes for ${name} script...`));
webpackSetup.compilers.forEach((compiler) => {
const { name } = compiler;
switch (name) {
case 'workers':
compiler.hooks.afterEmit.tap('afterEmit', async () => {
console.log(chalk.gray(`\nCompiled ${name} script!`));
console.log(
chalk.gray(`\nWatching file changes for ${name} script...`)
);
});
break;
case 'main':
default:
compiler.hooks.afterEmit.tap('afterEmit', async () => {
console.log(chalk.gray(`\nCompiled ${name} script!`));
manualRestart = true;
await restartElectron();
setTimeout(() => {
manualRestart = false;
}, 2500);
console.log(
chalk.gray(`\nWatching file changes for ${name} script...`)
);
});
break;
}
}); });
webpackSetup.watch({ aggregateTimeout: 500 }, err => { compiler.watch({ aggregateTimeout: 500 }, err => {
if (err) console.error(chalk.red(err));
});
}
function startMain () {
const compiler = webpack(mainConfig);
const { name } = compiler;
compiler.hooks.afterEmit.tap('afterEmit', async () => {
console.log(chalk.gray(`\nCompiled ${name} script!`));
manualRestart = true;
await restartElectron();
startWorkers();
setTimeout(() => {
manualRestart = false;
}, 2500);
console.log(chalk.gray(`\nWatching file changes for ${name} script...`));
});
compiler.watch({ aggregateTimeout: 500 }, err => {
if (err) console.error(chalk.red(err)); if (err) console.error(chalk.red(err));
}); });
} }

View File

@@ -42,6 +42,7 @@ const downloadFile = url => {
await unzip(filePath, destFolder); await unzip(filePath, destFolder);
fs.unlinkSync(filePath); fs.unlinkSync(filePath);
fs.unlinkSync(`${destFolder}/package.json`);// <- Avoid to display annoyng npm script in vscode fs.unlinkSync(`${destFolder}/package.json`);// <- Avoid to display annoyng npm script in vscode
process.exit();
} }
catch (error) { catch (error) {
console.log(error); console.log(error);

View File

@@ -51,6 +51,7 @@ export default class {
{ name: 'collation', group: 'database', types: ['string'] }, { name: 'collation', group: 'database', types: ['string'] },
{ name: 'engine', group: 'database', types: ['string'] }, { name: 'engine', group: 'database', types: ['string'] },
{ name: 'now', group: 'date', types: ['string', 'datetime'] },
{ name: 'past', group: 'date', types: ['string', 'datetime'] }, { name: 'past', group: 'date', types: ['string', 'datetime'] },
{ name: 'future', group: 'date', types: ['string', 'datetime'] }, { name: 'future', group: 'date', types: ['string', 'datetime'] },
// { name: 'between', group: 'date', types: ['string'] }, // { name: 'between', group: 'date', types: ['string'] },
@@ -161,7 +162,9 @@ export default class {
{ name: 'filePath', group: 'system', types: ['string'] }, { name: 'filePath', group: 'system', types: ['string'] },
{ name: 'semver', group: 'system', types: ['string'] }, { name: 'semver', group: 'system', types: ['string'] },
{ name: 'now', group: 'time', types: ['string', 'time'] },
{ name: 'recent', group: 'time', types: ['string', 'time'] }, { name: 'recent', group: 'time', types: ['string', 'time'] },
{ name: 'random', group: 'time', types: ['string', 'time'] },
{ name: 'vehicle', group: 'vehicle', types: ['string'] }, { name: 'vehicle', group: 'vehicle', types: ['string'] },
{ name: 'manufacturer', group: 'vehicle', types: ['string'] }, { name: 'manufacturer', group: 'vehicle', types: ['string'] },

View File

@@ -9,6 +9,7 @@ export const defaults: Customizations = {
dataTypes: [], dataTypes: [],
indexTypes: [], indexTypes: [],
foreignActions: [], foreignActions: [],
operators: ['=', '!=', '>', '<', '>=', '<=', 'IN', 'NOT IN', 'LIKE', 'NOT LIKE', 'BETWEEN', 'IS NULL', 'IS NOT NULL'],
// Core // Core
database: false, database: false,
collations: false, collations: false,

View File

@@ -9,6 +9,7 @@ export const customizations: Customizations = {
defaultUser: 'root', defaultUser: 'root',
defaultDatabase: null, defaultDatabase: null,
dataTypes: mysqlTypes, dataTypes: mysqlTypes,
operators: ['=', '!=', '>', '<', '>=', '<=', 'IN', 'NOT IN', 'LIKE', 'NOT LIKE', 'RLIKE', 'NOT RLIKE', 'BETWEEN', 'IS NULL', 'IS NOT NULL'],
indexTypes: [ indexTypes: [
'PRIMARY', 'PRIMARY',
'INDEX', 'INDEX',

View File

@@ -1,3 +1,4 @@
import SSHConfig from '@fabio286/ssh2-promise/lib/sshConfig';
import * as mysql from 'mysql2/promise'; import * as mysql from 'mysql2/promise';
import * as pg from 'pg'; import * as pg from 'pg';
import { FirebirdSQLClient } from 'src/main/libs/clients/FirebirdSQLClient'; import { FirebirdSQLClient } from 'src/main/libs/clients/FirebirdSQLClient';
@@ -5,7 +6,6 @@ import MysqlExporter from 'src/main/libs/exporters/sql/MysqlExporter';
import PostgreSQLExporter from 'src/main/libs/exporters/sql/PostgreSQLExporter'; import PostgreSQLExporter from 'src/main/libs/exporters/sql/PostgreSQLExporter';
import MySQLImporter from 'src/main/libs/importers/sql/MySQLlImporter'; import MySQLImporter from 'src/main/libs/importers/sql/MySQLlImporter';
import PostgreSQLImporter from 'src/main/libs/importers/sql/PostgreSQLImporter'; import PostgreSQLImporter from 'src/main/libs/importers/sql/PostgreSQLImporter';
import SSHConfig from 'ssh2-promise/lib/sshConfig';
import { MySQLClient } from '../../main/libs/clients/MySQLClient'; import { MySQLClient } from '../../main/libs/clients/MySQLClient';
import { PostgreSQLClient } from '../../main/libs/clients/PostgreSQLClient'; import { PostgreSQLClient } from '../../main/libs/clients/PostgreSQLClient';
@@ -363,8 +363,7 @@ export interface QueryBuilderObject {
offset: number; offset: number;
join: string[]; join: string[];
update: string[]; update: string[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any insert: {[key: string]: string | boolean | number }[];
insert: {[key: string]: any}[];
delete: boolean; delete: boolean;
} }

View File

@@ -1,4 +1,5 @@
import { TypesGroup } from './antares'; import { TypesGroup } from './antares';
import { TableFilterOperator } from './tableApis';
export interface Customizations { export interface Customizations {
// Defaults // Defaults
@@ -8,6 +9,7 @@ export interface Customizations {
dataTypes?: TypesGroup[]; dataTypes?: TypesGroup[];
indexTypes?: string[]; indexTypes?: string[];
foreignActions?: string[]; foreignActions?: string[];
operators?: TableFilterOperator[];
// Core // Core
database?: boolean; database?: boolean;
collations?: boolean; collations?: boolean;

View File

@@ -21,7 +21,7 @@ export interface TableDeleteParams {
rows: {[key: string]: any}; rows: {[key: string]: any};
} }
export type TableFilterOperator = '=' | '!=' | '>' | '<' | '>=' | '<=' | 'IN' | 'NOT IN' | 'LIKE' | 'NOT LIKE' | 'BETWEEN' | 'IS NULL' | 'IS NOT NULL' export type TableFilterOperator = '=' | '!=' | '>' | '<' | '>=' | '<=' | 'IN' | 'NOT IN' | 'LIKE' | 'NOT LIKE' | 'RLIKE' | 'NOT RLIKE' | 'BETWEEN' | 'IS NULL' | 'IS NOT NULL'
export interface TableFilterClausole { export interface TableFilterClausole {
active: boolean; active: boolean;

View File

@@ -0,0 +1,17 @@
import { faker } from '@faker-js/faker';
import * as moment from 'moment';
export const fakerCustom = {
seed: faker.seed,
setLocale: faker.setLocale,
...faker,
date: {
now: () => moment().format('YYYY-MM-DD HH:mm:ss'),
...faker.date
},
time: {
now: () => moment().format('HH:mm:ss'),
random: () => moment(faker.date.recent()).format('HH:mm:ss'),
...faker.time
}
};

View File

@@ -1,14 +1,46 @@
import { app, dialog, ipcMain } from 'electron'; import { app, dialog, ipcMain, safeStorage } from 'electron';
import * as Store from 'electron-store';
import { validateSender } from '../libs/misc/validateSender'; import { validateSender } from '../libs/misc/validateSender';
import { ShortcutRegister } from '../libs/ShortcutRegister'; import { ShortcutRegister } from '../libs/ShortcutRegister';
export default () => { export default () => {
ipcMain.on('close-app', (event) => { ipcMain.on('close-app', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' }; if (!validateSender(event.senderFrame)) {
return {
status: 'error',
response: 'Unauthorized process'
};
}
app.exit(); app.exit();
}); });
ipcMain.on('set-key', (event, key) => {
if (safeStorage.isEncryptionAvailable()) {
const sessionStore = new Store({
name: 'session',
fileExtension: ''
});
const encrypted = safeStorage.encryptString(key);
sessionStore.set('key', encrypted);
event.returnValue = true;
}
});
ipcMain.on('get-key', (event) => {
if (!safeStorage.isEncryptionAvailable()) {
event.returnValue = false;
return;
}
const sessionStore = new Store({
name: 'session',
fileExtension: ''
});
const encrypted = sessionStore.get('key') as string;
const key = safeStorage.decryptString(Buffer.from(encrypted, 'utf-8'));
event.returnValue = key;
});
ipcMain.handle('show-open-dialog', (event, options) => { ipcMain.handle('show-open-dialog', (event, options) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' }; if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
return dialog.showOpenDialog(options); return dialog.showOpenDialog(options);

View File

@@ -55,7 +55,7 @@ export default (connections: {[key: string]: antares.Client}) => {
port: conn.sshPort ? conn.sshPort : 22, port: conn.sshPort ? conn.sshPort : 22,
privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : null, privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : null,
passphrase: conn.sshPassphrase, passphrase: conn.sshPassphrase,
keepaliveInterval: conn.sshKeepAliveInterval ?? conn.sshKeepAliveInterval*1000 keepaliveInterval: conn.sshKeepAliveInterval ? conn.sshKeepAliveInterval*1000 : null
}; };
} }
@@ -137,7 +137,7 @@ export default (connections: {[key: string]: antares.Client}) => {
port: conn.sshPort ? conn.sshPort : 22, port: conn.sshPort ? conn.sshPort : 22,
privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : null, privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : null,
passphrase: conn.sshPassphrase, passphrase: conn.sshPassphrase,
keepaliveInterval: conn.sshKeepAliveInterval ?? conn.sshKeepAliveInterval*1000 keepaliveInterval: conn.sshKeepAliveInterval ? conn.sshKeepAliveInterval*1000 : null
}; };
} }

View File

@@ -1,17 +1,14 @@
import { ChildProcess, fork } from 'child_process';
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import * as workers from 'common/interfaces/workers'; import * as workers from 'common/interfaces/workers';
import { dialog, ipcMain } from 'electron'; import { dialog, ipcMain } from 'electron';
import * as fs from 'fs'; import * as fs from 'fs';
import * as path from 'path'; import { Worker } from 'worker_threads';
import { validateSender } from '../libs/misc/validateSender'; import { validateSender } from '../libs/misc/validateSender';
const isDevelopment = process.env.NODE_ENV !== 'production';
export default (connections: {[key: string]: antares.Client}) => { export default (connections: {[key: string]: antares.Client}) => {
let exporter: ChildProcess = null; let exporter: Worker = null;
let importer: ChildProcess = null; let importer: Worker = null;
ipcMain.handle('create-schema', async (event, params) => { ipcMain.handle('create-schema', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' }; if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
@@ -202,7 +199,7 @@ export default (connections: {[key: string]: antares.Client}) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' }; if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (exporter !== null) { if (exporter !== null) {
exporter.kill(); exporter.terminate();
return; return;
} }
@@ -227,11 +224,12 @@ export default (connections: {[key: string]: antares.Client}) => {
} }
} }
// Init exporter process // Init exporter thread
exporter = fork(isDevelopment ? './dist/exporter.js' : path.resolve(__dirname, './exporter.js'), [], { // eslint-disable-next-line @typescript-eslint/ban-ts-comment
execArgv: isDevelopment ? ['--inspect=9224'] : undefined // @ts-ignore
}); exporter = new Worker(new URL('../workers/exporter', import.meta.url));
exporter.send({
exporter.postMessage({
type: 'init', type: 'init',
client: { client: {
name: type, name: type,
@@ -242,32 +240,43 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
// Exporter message listener // Exporter message listener
exporter.on('message', ({ type, payload }: workers.WorkerIpcMessage) => { exporter.stdout.on('data', (buff: Buffer) => {
let message;
try { // Ignore non-JSON data (console.log output)
message = JSON.parse(buff.toString());
}
catch (_) {
if (process.env.NODE_ENV === 'development') console.log('EXPORTER:', buff.toString());
return;
}
const { type, payload } = message as workers.WorkerIpcMessage;
switch (type) { switch (type) {
case 'export-progress': case 'export-progress':
event.sender.send('export-progress', payload); event.sender.send('export-progress', payload);
break; break;
case 'end': case 'end':
setTimeout(() => { // Ensures that writing process has finished setTimeout(() => { // Ensures that writing thread has finished
exporter.kill(); exporter?.terminate();
exporter = null; exporter = null;
}, 2000); }, 2000);
resolve({ status: 'success', response: payload }); resolve({ status: 'success', response: payload });
break; break;
case 'cancel': case 'cancel':
exporter.kill(); exporter?.terminate();
exporter = null; exporter = null;
resolve({ status: 'error', response: 'Operation cancelled' }); resolve({ status: 'error', response: 'Operation cancelled' });
break; break;
case 'error': case 'error':
exporter.kill(); exporter?.terminate();
exporter = null; exporter = null;
resolve({ status: 'error', response: payload }); resolve({ status: 'error', response: payload });
break; break;
} }
}); });
exporter.on('exit', code => { exporter.on('close', code => {
exporter = null; exporter = null;
resolve({ status: 'error', response: `Operation ended with code: ${code}` }); resolve({ status: 'error', response: `Operation ended with code: ${code}` });
}); });
@@ -291,7 +300,7 @@ export default (connections: {[key: string]: antares.Client}) => {
if (result.response === 1) { if (result.response === 1) {
willAbort = true; willAbort = true;
exporter.send({ type: 'cancel' }); exporter.postMessage({ type: 'cancel' });
} }
} }
@@ -302,7 +311,7 @@ export default (connections: {[key: string]: antares.Client}) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' }; if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (importer !== null) { if (importer !== null) {
importer.kill(); importer.terminate();
return; return;
} }
@@ -310,18 +319,30 @@ export default (connections: {[key: string]: antares.Client}) => {
(async () => { (async () => {
const dbConfig = await connections[options.uid].getDbConfig(); const dbConfig = await connections[options.uid].getDbConfig();
// Init importer process // Init importer thread
importer = fork(isDevelopment ? './dist/importer.js' : path.resolve(__dirname, './importer.js'), [], { // eslint-disable-next-line @typescript-eslint/ban-ts-comment
execArgv: isDevelopment ? ['--inspect=9224'] : undefined // @ts-ignore
}); importer = new Worker(new URL('../workers/importer', import.meta.url));
importer.send({
importer.postMessage({
type: 'init', type: 'init',
dbConfig, dbConfig,
options options
}); });
// Importer message listener // Importer message listener
importer.on('message', ({ type, payload }: workers.WorkerIpcMessage) => { importer.stdout.on('data', (buff: Buffer) => {
let message;
try { // Ignore non-JSON data (console.log output)
message = JSON.parse(buff.toString());
}
catch (_) {
if (process.env.NODE_ENV === 'development') console.log('IMPORTER:', buff.toString());
return;
}
const { type, payload } = message as workers.WorkerIpcMessage;
switch (type) { switch (type) {
case 'import-progress': case 'import-progress':
event.sender.send('import-progress', payload); event.sender.send('import-progress', payload);
@@ -331,23 +352,28 @@ export default (connections: {[key: string]: antares.Client}) => {
break; break;
case 'end': case 'end':
setTimeout(() => { // Ensures that writing process has finished setTimeout(() => { // Ensures that writing process has finished
importer?.kill(); importer?.terminate();
importer = null; importer = null;
}, 2000); }, 2000);
resolve({ status: 'success', response: payload }); resolve({ status: 'success', response: payload });
break; break;
case 'cancel': case 'cancel':
importer.kill(); importer.terminate();
importer = null; importer = null;
resolve({ status: 'error', response: 'Operation cancelled' }); resolve({ status: 'error', response: 'Operation cancelled' });
break; break;
case 'error': case 'error':
importer.kill(); importer.terminate();
importer = null; importer = null;
resolve({ status: 'error', response: payload }); resolve({ status: 'error', response: payload });
break; break;
} }
}); });
importer.on('close', code => {
importer = null;
resolve({ status: 'error', response: `Operation ended with code: ${code}` });
});
})(); })();
}); });
}); });
@@ -368,7 +394,7 @@ export default (connections: {[key: string]: antares.Client}) => {
if (result.response === 1) { if (result.response === 1) {
willAbort = true; willAbort = true;
importer.send({ type: 'cancel' }); importer.postMessage({ type: 'cancel' });
} }
} }

View File

@@ -1,8 +1,8 @@
import { faker } from '@faker-js/faker';
import customizations from 'common/customizations'; import customizations from 'common/customizations';
import { ARRAY, BIT, BLOB, BOOLEAN, DATE, DATETIME, FLOAT, LONG_TEXT, NUMBER, TEXT, TEXT_SEARCH } from 'common/fieldTypes'; import { ARRAY, BIT, BLOB, BOOLEAN, DATE, DATETIME, FLOAT, LONG_TEXT, NUMBER, TEXT, TEXT_SEARCH } from 'common/fieldTypes';
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import { InsertRowsParams } from 'common/interfaces/tableApis'; import { InsertRowsParams } from 'common/interfaces/tableApis';
import { fakerCustom } from 'common/libs/fakerCustom';
import { sqlEscaper } from 'common/libs/sqlUtils'; import { sqlEscaper } from 'common/libs/sqlUtils';
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import * as fs from 'fs'; import * as fs from 'fs';
@@ -371,19 +371,19 @@ export default (connections: {[key: string]: antares.Client}) => {
let fakeValue; let fakeValue;
if (params.locale) if (params.locale)
faker.locale = params.locale; fakerCustom.locale = params.locale;
if (Object.keys(params.row[key].params).length) { if (Object.keys(params.row[key].params).length) {
Object.keys(params.row[key].params).forEach(param => { Object.keys(params.row[key].params).forEach(param => {
if (!isNaN(params.row[key].params[param])) if (!isNaN(params.row[key].params[param]))// Converts string numerics params to number
parsedParams[param] = +params.row[key].params[param]; parsedParams[param] = Number(params.row[key].params[param]);
}); });
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
fakeValue = (faker as any)[params.row[key].group][params.row[key].method](parsedParams); fakeValue = (fakerCustom as any)[params.row[key].group][params.row[key].method](parsedParams);
} }
else else
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
fakeValue = (faker as any)[params.row[key].group][params.row[key].method](); fakeValue = (fakerCustom as any)[params.row[key].group][params.row[key].method]();
if (typeof fakeValue === 'string') { if (typeof fakeValue === 'string') {
if (params.row[key].length) if (params.row[key].length)

View File

@@ -1,4 +1,5 @@
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import * as log from 'electron-log/main';
import * as Store from 'electron-store'; import * as Store from 'electron-store';
import { autoUpdater } from 'electron-updater'; import { autoUpdater } from 'electron-updater';
@@ -59,7 +60,7 @@ export default () => {
mainWindow.reply('update-downloaded'); mainWindow.reply('update-downloaded');
}); });
// autoUpdater.logger = require('electron-log'); log.transports.file.level = 'info';
// autoUpdater.logger.transports.console.format = '{h}:{i}:{s} {text}'; // log.transports.console.format = '{h}:{i}:{s} {text}';
// autoUpdater.logger.transports.file.level = 'info'; autoUpdater.logger = log;
}; };

View File

@@ -1,7 +1,7 @@
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import mysql from 'mysql2/promise'; import mysql from 'mysql2/promise';
import * as pg from 'pg'; import * as pg from 'pg';
import SSH2Promise from 'ssh2-promise'; import SSH2Promise = require('@fabio286/ssh2-promise');
const queryLogger = ({ sql, cUid }: {sql: string; cUid: string}) => { const queryLogger = ({ sql, cUid }: {sql: string; cUid: string}) => {
// Remove comments, newlines and multiple spaces // Remove comments, newlines and multiple spaces
@@ -10,13 +10,13 @@ const queryLogger = ({ sql, cUid }: {sql: string; cUid: string}) => {
const mainWindow = require('electron').webContents.fromId(1); const mainWindow = require('electron').webContents.fromId(1);
mainWindow.send('query-log', { cUid, sql: escapedSql, date: new Date() }); mainWindow.send('query-log', { cUid, sql: escapedSql, date: new Date() });
} }
if (process.env.NODE_ENV === 'development') console.log(escapedSql); if (process.env.NODE_ENV === 'development' && process.type === 'browser') console.log(escapedSql);
}; };
/** /**
* As Simple As Possible Query Builder Core * As Simple As Possible Query Builder Core
*/ */
export abstract class AntaresCore { export abstract class BaseClient {
_client: antares.ClientCode; _client: antares.ClientCode;
protected _cUid: string protected _cUid: string
protected _params: mysql.ConnectionOptions | pg.ClientConfig | { databasePath: string; readonly: boolean}; protected _params: mysql.ConnectionOptions | pg.ClientConfig | { databasePath: string; readonly: boolean};

View File

@@ -4,9 +4,9 @@ import * as antares from 'common/interfaces/antares';
import * as firebird from 'node-firebird'; import * as firebird from 'node-firebird';
import * as path from 'path'; import * as path from 'path';
import { AntaresCore } from '../AntaresCore'; import { BaseClient } from './BaseClient';
export class FirebirdSQLClient extends AntaresCore { export class FirebirdSQLClient extends BaseClient {
private _schema?: string; private _schema?: string;
private _runningConnections: Map<string, number>; private _runningConnections: Map<string, number>;
private _connectionsToCommit: Map<string, firebird.Transaction>; private _connectionsToCommit: Map<string, firebird.Transaction>;
@@ -118,6 +118,10 @@ export class FirebirdSQLClient extends AntaresCore {
return null; return null;
} }
getDatabases (): null[] {
return [];
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
async getStructure (_schemas: Set<string>) { async getStructure (_schemas: Set<string>) {
interface TableResult { interface TableResult {
@@ -157,10 +161,10 @@ export class FirebirdSQLClient extends AntaresCore {
const { rows: tables } = await this.raw<antares.QueryResult<TableResult>>(` const { rows: tables } = await this.raw<antares.QueryResult<TableResult>>(`
SELECT SELECT
rdb$relation_name AS name, rdb$relation_name AS NAME,
rdb$format AS format, rdb$format AS FORMAT,
rdb$description AS description, rdb$description AS DESCRIPTION,
'table' AS type 'table' AS TYPE
FROM RDB$RELATIONS a FROM RDB$RELATIONS a
WHERE COALESCE(RDB$SYSTEM_FLAG, 0) = 0 WHERE COALESCE(RDB$SYSTEM_FLAG, 0) = 0
AND RDB$RELATION_TYPE = 0 AND RDB$RELATION_TYPE = 0
@@ -168,8 +172,8 @@ export class FirebirdSQLClient extends AntaresCore {
const { rows: views } = await this.raw<antares.QueryResult<TableResult>>(` const { rows: views } = await this.raw<antares.QueryResult<TableResult>>(`
SELECT SELECT
DISTINCT RDB$VIEW_NAME AS name, DISTINCT RDB$VIEW_NAME AS NAME,
'view' AS type 'view' AS TYPE
FROM RDB$VIEW_RELATIONS FROM RDB$VIEW_RELATIONS
`); `);
@@ -177,9 +181,9 @@ export class FirebirdSQLClient extends AntaresCore {
const { rows: triggers } = await this.raw<antares.QueryResult<TriggersResult>>(` const { rows: triggers } = await this.raw<antares.QueryResult<TriggersResult>>(`
SELECT SELECT
RDB$TRIGGER_NAME as name, RDB$TRIGGER_NAME as NAME,
RDB$RELATION_NAME as relation, RDB$RELATION_NAME as RELATION,
RDB$TRIGGER_SOURCE as source RDB$TRIGGER_SOURCE as SOURCE
FROM RDB$TRIGGERS FROM RDB$TRIGGERS
WHERE RDB$SYSTEM_FLAG=0 WHERE RDB$SYSTEM_FLAG=0
ORDER BY RDB$TRIGGER_NAME; ORDER BY RDB$TRIGGER_NAME;
@@ -208,8 +212,8 @@ export class FirebirdSQLClient extends AntaresCore {
schemaSize += tableSize; schemaSize += tableSize;
return { return {
name: table.NAME.trim(), name: table.NAME?.trim(),
type: table.TYPE.trim(), type: table.TYPE?.trim(),
rows: false, rows: false,
size: false size: false
}; };
@@ -218,8 +222,8 @@ export class FirebirdSQLClient extends AntaresCore {
// TRIGGERS // TRIGGERS
const remappedTriggers = triggersArr.map(trigger => { const remappedTriggers = triggersArr.map(trigger => {
return { return {
name: trigger.NAME.trim(), name: trigger.NAME?.trim(),
table: trigger.RELATION.trim(), table: trigger.RELATION?.trim(),
statement: trigger.SOURCE statement: trigger.SOURCE
}; };
}); });
@@ -227,7 +231,7 @@ export class FirebirdSQLClient extends AntaresCore {
// PROCEDURES // PROCEDURES
const remappedProcedures = proceduresArr.map(procedure => { const remappedProcedures = proceduresArr.map(procedure => {
return { return {
name: procedure.NAME.trim(), name: procedure.NAME?.trim(),
definer: procedure.DEFINER, definer: procedure.DEFINER,
comment: procedure.COMMENT?.trim() comment: procedure.COMMENT?.trim()
}; };

View File

@@ -1,12 +1,12 @@
import SSH2Promise = require('@fabio286/ssh2-promise');
import SSHConfig from '@fabio286/ssh2-promise/lib/sshConfig';
import dataTypes from 'common/data-types/mysql'; import dataTypes from 'common/data-types/mysql';
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import * as mysql from 'mysql2/promise'; import * as mysql from 'mysql2/promise';
import { AntaresCore } from '../AntaresCore'; import { BaseClient } from './BaseClient';
import SSH2Promise = require('ssh2-promise');
import SSHConfig from 'ssh2-promise/lib/sshConfig';
export class MySQLClient extends AntaresCore { export class MySQLClient extends BaseClient {
private _schema?: string; private _schema?: string;
private _runningConnections: Map<string, number>; private _runningConnections: Map<string, number>;
private _connectionsToCommit: Map<string, mysql.Connection | mysql.PoolConnection>; private _connectionsToCommit: Map<string, mysql.Connection | mysql.PoolConnection>;
@@ -168,7 +168,10 @@ export class MySQLClient extends AntaresCore {
dbConfig.port = tunnel.localPort; dbConfig.port = tunnel.localPort;
} }
catch (err) { catch (err) {
if (this._ssh) this._ssh.close(); if (this._ssh) {
this._ssh.close();
this._ssh.closeTunnel();
}
throw err; throw err;
} }
} }
@@ -187,7 +190,10 @@ export class MySQLClient extends AntaresCore {
this._connection.end(); this._connection.end();
clearInterval(this._keepaliveTimer); clearInterval(this._keepaliveTimer);
this._keepaliveTimer = undefined; this._keepaliveTimer = undefined;
if (this._ssh) this._ssh.close(); if (this._ssh) {
this._ssh.close();
this._ssh.closeTunnel();
}
} }
async getConnection () { async getConnection () {
@@ -256,9 +262,12 @@ export class MySQLClient extends AntaresCore {
} }
private async keepAlive () { private async keepAlive () {
const connection = await (this._connection as mysql.Pool).getConnection(); try {
await connection.ping(); const connection = await (this._connection as mysql.Pool).getConnection();
connection.release(); await connection.ping();
connection.release();
}
catch (_) {}
} }
use (schema: string) { use (schema: string) {

View File

@@ -1,13 +1,13 @@
import SSH2Promise = require('@fabio286/ssh2-promise');
import SSHConfig from '@fabio286/ssh2-promise/lib/sshConfig';
import dataTypes from 'common/data-types/postgresql'; import dataTypes from 'common/data-types/postgresql';
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import * as pg from 'pg'; import * as pg from 'pg';
import * as pgAst from 'pgsql-ast-parser'; import * as pgAst from 'pgsql-ast-parser';
import { AntaresCore } from '../AntaresCore';
import SSH2Promise = require('ssh2-promise');
import SSHConfig from 'ssh2-promise/lib/sshConfig';
import { ConnectionOptions } from 'tls'; import { ConnectionOptions } from 'tls';
import { BaseClient } from './BaseClient';
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
function pgToString (value: any) { function pgToString (value: any) {
return value.toString(); return value.toString();
@@ -81,7 +81,7 @@ type builtinsTypes =
'JSONB' | 'JSONB' |
'REGNAMESPACE' | 'REGNAMESPACE' |
'REGROLE'; 'REGROLE';
export class PostgreSQLClient extends AntaresCore { export class PostgreSQLClient extends BaseClient {
private _schema?: string; private _schema?: string;
private _runningConnections: Map<string, number>; private _runningConnections: Map<string, number>;
private _connectionsToCommit: Map<string, pg.Client | pg.PoolClient>; private _connectionsToCommit: Map<string, pg.Client | pg.PoolClient>;
@@ -180,7 +180,10 @@ export class PostgreSQLClient extends AntaresCore {
dbConfig.port = tunnel.localPort; dbConfig.port = tunnel.localPort;
} }
catch (err) { catch (err) {
if (this._ssh) this._ssh.close(); if (this._ssh) {
this._ssh.close();
this._ssh.closeTunnel();
}
throw err; throw err;
} }
} }
@@ -236,13 +239,19 @@ export class PostgreSQLClient extends AntaresCore {
this._connection.end(); this._connection.end();
clearInterval(this._keepaliveTimer); clearInterval(this._keepaliveTimer);
this._keepaliveTimer = undefined; this._keepaliveTimer = undefined;
if (this._ssh) this._ssh.close(); if (this._ssh) {
this._ssh.close();
this._ssh.closeTunnel();
}
} }
private async keepAlive () { private async keepAlive () {
const connection = await this._connection.connect() as pg.PoolClient; try {
await connection.query('SELECT 1+1'); const connection = await this._connection.connect() as pg.PoolClient;
connection.release(); await connection.query('SELECT 1+1');
connection.release();
}
catch (_) {}
} }
use (schema: string, connection?: pg.Client | pg.PoolClient) { use (schema: string, connection?: pg.Client | pg.PoolClient) {

View File

@@ -3,9 +3,9 @@ import dataTypes from 'common/data-types/sqlite';
import { DATETIME, FLOAT, NUMBER, TIME } from 'common/fieldTypes'; import { DATETIME, FLOAT, NUMBER, TIME } from 'common/fieldTypes';
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import { AntaresCore } from '../AntaresCore'; import { BaseClient } from './BaseClient';
export class SQLiteClient extends AntaresCore { export class SQLiteClient extends BaseClient {
private _schema?: string; private _schema?: string;
private _connectionsToCommit: Map<string, sqlite.Database>; private _connectionsToCommit: Map<string, sqlite.Database>;
protected _connection?: sqlite.Database; protected _connection?: sqlite.Database;

View File

@@ -1,6 +1,5 @@
import * as exporter from 'common/interfaces/exporter'; import * as exporter from 'common/interfaces/exporter';
import { valueToSqlString } from 'common/libs/sqlUtils'; import { valueToSqlString } from 'common/libs/sqlUtils';
import * as mysql from 'mysql2/promise';
import { MySQLClient } from '../../clients/MySQLClient'; import { MySQLClient } from '../../clients/MySQLClient';
import { SqlExporter } from './SqlExporter'; import { SqlExporter } from './SqlExporter';
@@ -334,12 +333,10 @@ CREATE TABLE \`${view.Name}\`(
} }
async _queryStream (sql: string) { async _queryStream (sql: string) {
if (process.env.NODE_ENV === 'development') console.log('EXPORTER:', sql); const connection = await this._client.getConnection();
const isPool = 'getConnection' in this._client._connection;
const connection = isPool ? await (this._client._connection as mysql.Pool).getConnection() : this._client._connection;
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const stream = (connection as any).connection.query(sql).stream(); const stream = (connection as any).connection.query(sql).stream();
const dispose = () => (connection as mysql.PoolConnection).release(); const dispose = () => connection.end();
stream.on('end', dispose); stream.on('end', dispose);
stream.on('error', dispose); stream.on('error', dispose);

View File

@@ -425,7 +425,6 @@ SET row_security = off;\n\n\n`;
} }
async _queryStream (sql: string) { async _queryStream (sql: string) {
if (process.env.NODE_ENV === 'development') console.log('EXPORTER:', sql);
const connection = await this._client.getConnection(); const connection = await this._client.getConnection();
const query = new QueryStream(sql, null); const query = new QueryStream(sql, null);
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any

View File

@@ -33,8 +33,8 @@ export default class MySQLImporter extends BaseImporter {
parser.on('error', reject); parser.on('error', reject);
parser.on('close', async () => { parser.on('close', async () => {
console.log('TOTAL QUERIES', queryCount); // console.log('TOTAL QUERIES', queryCount);
console.log('import end'); // console.log('import end');
resolve(); resolve();
}); });

View File

@@ -33,8 +33,8 @@ export default class PostgreSQLImporter extends BaseImporter {
parser.on('error', reject); parser.on('error', reject);
parser.on('close', async () => { parser.on('close', async () => {
console.log('TOTAL QUERIES', queryCount); // console.log('TOTAL QUERIES', queryCount);
console.log('import end'); // console.log('import end');
resolve(); resolve();
}); });

View File

@@ -6,6 +6,7 @@ const isWindows = process.platform === 'win32';
const indexPath = path.resolve(__dirname, 'index.html').split(path.sep).join('/'); const indexPath = path.resolve(__dirname, 'index.html').split(path.sep).join('/');
export function validateSender (frame: WebFrameMain) { export function validateSender (frame: WebFrameMain) {
if (isWindows) return true; // TEMP HOTFIX
const frameUrl = new URL(frame.url); const frameUrl = new URL(frame.url);
const prefix = isWindows ? 'file:///' : 'file://'; const prefix = isWindows ? 'file:///' : 'file://';
const framePath = frameUrl.href.replace(prefix, ''); const framePath = frameUrl.href.replace(prefix, '');

View File

@@ -1,5 +1,6 @@
import * as remoteMain from '@electron/remote/main'; import * as remoteMain from '@electron/remote/main';
import { app, BrowserWindow, ipcMain, nativeImage } from 'electron'; import { app, BrowserWindow, ipcMain, nativeImage, safeStorage } from 'electron';
import * as log from 'electron-log/main';
import * as Store from 'electron-store'; import * as Store from 'electron-store';
import * as windowStateKeeper from 'electron-window-state'; import * as windowStateKeeper from 'electron-window-state';
import * as path from 'path'; import * as path from 'path';
@@ -8,6 +9,7 @@ import ipcHandlers from './ipc-handlers';
import { OsMenu, ShortcutRegister } from './libs/ShortcutRegister'; import { OsMenu, ShortcutRegister } from './libs/ShortcutRegister';
Store.initRenderer(); Store.initRenderer();
log.errorHandler.startCatching();
const settingsStore = new Store({ name: 'settings' }); const settingsStore = new Store({ name: 'settings' });
const appTheme = settingsStore.get('application_theme'); const appTheme = settingsStore.get('application_theme');
const isDevelopment = process.env.NODE_ENV !== 'production'; const isDevelopment = process.env.NODE_ENV !== 'production';
@@ -78,80 +80,80 @@ async function createMainWindow () {
return window; return window;
} }
if (!gotTheLock) app.quit(); require('@electron/remote/main').initialize();
else {
require('@electron/remote/main').initialize();
// Initialize ipcHandlers // Initialize ipcHandlers
ipcHandlers(); ipcHandlers();
ipcMain.on('refresh-theme-settings', () => { ipcMain.on('refresh-theme-settings', () => {
const appTheme = settingsStore.get('application_theme'); const appTheme = settingsStore.get('application_theme');
if (isWindows && mainWindow) { if (isWindows && mainWindow) {
mainWindow.setTitleBarOverlay({ mainWindow.setTitleBarOverlay({
color: appTheme === 'dark' ? '#3f3f3f' : '#fff', color: appTheme === 'dark' ? '#3f3f3f' : '#fff',
symbolColor: appTheme === 'dark' ? '#fff' : '#000' symbolColor: appTheme === 'dark' ? '#fff' : '#000'
});
}
});
ipcMain.on('change-window-title', (_, title: string) => {
if (mainWindow) mainWindow.setTitle(title);
});
// quit application when all windows are closed
app.on('window-all-closed', () => {
// on macOS it is common for applications to stay open until the user explicitly quits
if (!isMacOS) app.quit();
});
app.on('activate', async () => {
// on macOS it is common to re-create a window even after all windows have been closed
if (mainWindow === null)
mainWindow = await createMainWindow();
});
// create main BrowserWindow when electron is ready
app.on('ready', async () => {
mainWindowState = windowStateKeeper({
defaultWidth: 1024,
defaultHeight: 800
}); });
}
});
ipcMain.on('change-window-title', (_, title: string) => {
if (mainWindow) mainWindow.setTitle(title);
});
// quit application when all windows are closed
app.on('window-all-closed', () => {
// on macOS it is common for applications to stay open until the user explicitly quits
if (!isMacOS) app.quit();
});
app.on('activate', async () => {
// on macOS it is common to re-create a window even after all windows have been closed
if (mainWindow === null)
mainWindow = await createMainWindow(); mainWindow = await createMainWindow();
createAppMenu(); });
if (isWindows) // create main BrowserWindow when electron is ready
mainWindow.show(); app.on('ready', async () => {
if (!gotTheLock && !safeStorage.isEncryptionAvailable()) // Disable multiple instances if is not possible to share session keys
app.quit();
// if (isDevelopment) mainWindowState = windowStateKeeper({
// mainWindow.webContents.openDevTools(); defaultWidth: 1024,
defaultHeight: 800
process.on('uncaughtException', error => {
mainWindow.webContents.send('unhandled-exception', error);
});
process.on('unhandledRejection', error => {
mainWindow.webContents.send('unhandled-exception', error);
});
}); });
app.on('browser-window-created', (event, window) => { mainWindow = await createMainWindow();
if (isDevelopment) { createAppMenu();
const { antares } = require('../../package.json');
const extensionPath = path.resolve(__dirname, `../../misc/${antares.devtoolsId}`);
window.webContents.session.loadExtension(extensionPath, { allowFileAccess: true }).catch(console.error);
}
window.webContents.on('will-navigate', (e) => { // Prevent browser navigation if (isWindows)
e.preventDefault(); mainWindow.show();
});
window.webContents.on('did-create-window', (w) => { // Close new windows // if (isDevelopment)
w.close(); // mainWindow.webContents.openDevTools();
});
process.on('uncaughtException', error => {
mainWindow.webContents.send('unhandled-exception', error);
}); });
}
process.on('unhandledRejection', error => {
mainWindow.webContents.send('unhandled-exception', error);
});
});
app.on('browser-window-created', (event, window) => {
if (isDevelopment) {
const { antares } = require('../../package.json');
const extensionPath = path.resolve(__dirname, `../../misc/${antares.devtoolsId}`);
window.webContents.session.loadExtension(extensionPath, { allowFileAccess: true }).catch(console.error);
}
window.webContents.on('will-navigate', (e) => { // Prevent browser navigation
e.preventDefault();
});
window.webContents.on('did-create-window', (w) => { // Close new windows
w.close();
});
});
function createAppMenu () { function createAppMenu () {
const menuTemplate: OsMenu = { const menuTemplate: OsMenu = {

View File

@@ -1,5 +1,7 @@
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import * as log from 'electron-log/main';
import * as fs from 'fs'; import * as fs from 'fs';
import { parentPort } from 'worker_threads';
import { MySQLClient } from '../libs/clients/MySQLClient'; import { MySQLClient } from '../libs/clients/MySQLClient';
import { PostgreSQLClient } from '../libs/clients/PostgreSQLClient'; import { PostgreSQLClient } from '../libs/clients/PostgreSQLClient';
@@ -8,63 +10,78 @@ import MysqlExporter from '../libs/exporters/sql/MysqlExporter';
import PostgreSQLExporter from '../libs/exporters/sql/PostgreSQLExporter'; import PostgreSQLExporter from '../libs/exporters/sql/PostgreSQLExporter';
let exporter: antares.Exporter; let exporter: antares.Exporter;
process.on('message', async ({ type, client, tables, options }: any) => { log.transports.file.fileName = 'workers.log';
log.transports.console = null;
log.errorHandler.startCatching();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const exportHandler = async (data: any) => {
const { type, client, tables, options } = data;
if (type === 'init') { if (type === 'init') {
const connection = await ClientsFactory.getClient({ try {
client: client.name, const connection = await ClientsFactory.getClient({
params: client.config, client: client.name,
poolSize: 5 params: client.config,
}) as MySQLClient | PostgreSQLClient; poolSize: 5
await connection.connect(); }) as MySQLClient | PostgreSQLClient;
await connection.connect();
switch (client.name) { switch (client.name) {
case 'mysql': case 'mysql':
case 'maria': case 'maria':
exporter = new MysqlExporter(connection as MySQLClient, tables, options); exporter = new MysqlExporter(connection as MySQLClient, tables, options);
break; break;
case 'pg': case 'pg':
exporter = new PostgreSQLExporter(connection as PostgreSQLClient, tables, options); exporter = new PostgreSQLExporter(connection as PostgreSQLClient, tables, options);
break; break;
default: default:
process.send({ parentPort.postMessage({
type: 'error',
payload: `"${client.name}" exporter not aviable`
});
return;
}
exporter.once('error', err => {
log.error(err.toString());
parentPort.postMessage({
type: 'error', type: 'error',
payload: `"${client.name}" exporter not aviable` payload: err.toString()
}); });
return; });
}
exporter.once('error', err => { exporter.once('end', () => {
console.error(err); parentPort.postMessage({
process.send({ type: 'end',
payload: { cancelled: exporter.isCancelled }
});
});
exporter.once('cancel', () => {
fs.unlinkSync(exporter.outputFile);
parentPort.postMessage({ type: 'cancel' });
});
exporter.on('progress', state => {
parentPort.postMessage({
type: 'export-progress',
payload: state
});
});
exporter.run();
}
catch (err) {
log.error(err.toString());
parentPort.postMessage({
type: 'error', type: 'error',
payload: err.toString() payload: err.toString()
}); });
}); }
exporter.once('end', () => {
process.send({
type: 'end',
payload: { cancelled: exporter.isCancelled }
});
connection.destroy();
});
exporter.once('cancel', () => {
fs.unlinkSync(exporter.outputFile);
process.send({ type: 'cancel' });
});
exporter.on('progress', state => {
process.send({
type: 'export-progress',
payload: state
});
});
exporter.run();
} }
else if (type === 'cancel') else if (type === 'cancel')
exporter.cancel(); exporter.cancel();
}); };
process.on('beforeExit', console.log); parentPort.on('message', exportHandler);

View File

@@ -1,8 +1,10 @@
import SSHConfig from '@fabio286/ssh2-promise/lib/sshConfig';
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import { ImportOptions } from 'common/interfaces/importer'; import { ImportOptions } from 'common/interfaces/importer';
import * as log from 'electron-log/main';
import * as mysql from 'mysql2'; import * as mysql from 'mysql2';
import * as pg from 'pg'; import * as pg from 'pg';
import SSHConfig from 'ssh2-promise/lib/sshConfig'; import { parentPort } from 'worker_threads';
import { MySQLClient } from '../libs/clients/MySQLClient'; import { MySQLClient } from '../libs/clients/MySQLClient';
import { PostgreSQLClient } from '../libs/clients/PostgreSQLClient'; import { PostgreSQLClient } from '../libs/clients/PostgreSQLClient';
@@ -11,14 +13,18 @@ import MySQLImporter from '../libs/importers/sql/MySQLlImporter';
import PostgreSQLImporter from '../libs/importers/sql/PostgreSQLImporter'; import PostgreSQLImporter from '../libs/importers/sql/PostgreSQLImporter';
let importer: antares.Importer; let importer: antares.Importer;
// eslint-disable-next-line @typescript-eslint/no-explicit-any log.transports.file.fileName = 'workers.log';
process.on('message', async ({ type, dbConfig, options }: { log.transports.console = null;
log.errorHandler.startCatching();
const importHandler = async (data: {
type: string; type: string;
dbConfig: mysql.ConnectionOptions & { schema: string; ssl?: mysql.SslOptions; ssh?: SSHConfig; readonly: boolean } dbConfig: mysql.ConnectionOptions & { schema: string; ssl?: mysql.SslOptions; ssh?: SSHConfig; readonly: boolean }
| pg.ClientConfig & { schema: string; ssl?: mysql.SslOptions; ssh?: SSHConfig; readonly: boolean } | pg.ClientConfig & { schema: string; ssl?: mysql.SslOptions; ssh?: SSHConfig; readonly: boolean }
| { databasePath: string; readonly: boolean }; | { databasePath: string; readonly: boolean };
options: ImportOptions; options: ImportOptions;
}) => { }) => {
const { type, dbConfig, options } = data;
if (type === 'init') { if (type === 'init') {
try { try {
const connection = await ClientsFactory.getClient({ const connection = await ClientsFactory.getClient({
@@ -41,7 +47,7 @@ process.on('message', async ({ type, dbConfig, options }: {
importer = new PostgreSQLImporter(pool as unknown as pg.PoolClient, options); importer = new PostgreSQLImporter(pool as unknown as pg.PoolClient, options);
break; break;
default: default:
process.send({ parentPort.postMessage({
type: 'error', type: 'error',
payload: `"${options.type}" importer not aviable` payload: `"${options.type}" importer not aviable`
}); });
@@ -49,33 +55,33 @@ process.on('message', async ({ type, dbConfig, options }: {
} }
importer.once('error', err => { importer.once('error', err => {
console.error(err); log.error(err.toString());
process.send({ parentPort.postMessage({
type: 'error', type: 'error',
payload: err.toString() payload: err.toString()
}); });
}); });
importer.once('end', () => { importer.once('end', () => {
process.send({ parentPort.postMessage({
type: 'end', type: 'end',
payload: { cancelled: importer.isCancelled } payload: { cancelled: importer.isCancelled }
}); });
}); });
importer.once('cancel', () => { importer.once('cancel', () => {
process.send({ type: 'cancel' }); parentPort.postMessage({ type: 'cancel' });
}); });
importer.on('progress', state => { importer.on('progress', state => {
process.send({ parentPort.postMessage({
type: 'import-progress', type: 'import-progress',
payload: state payload: state
}); });
}); });
importer.on('query-error', state => { importer.on('query-error', state => {
process.send({ parentPort.postMessage({
type: 'query-error', type: 'query-error',
payload: state payload: state
}); });
@@ -84,8 +90,8 @@ process.on('message', async ({ type, dbConfig, options }: {
importer.run(); importer.run();
} }
catch (err) { catch (err) {
console.error(err); log.error(err.toString());
process.send({ parentPort.postMessage({
type: 'error', type: 'error',
payload: err.toString() payload: err.toString()
}); });
@@ -93,20 +99,6 @@ process.on('message', async ({ type, dbConfig, options }: {
} }
else if (type === 'cancel') else if (type === 'cancel')
importer.cancel(); importer.cancel();
}); };
process.on('uncaughtException', (err) => { parentPort.on('message', importHandler);
console.error(err);
process.send({
type: 'error',
payload: err.toString()
});
});
process.on('unhandledRejection', (err) => {
console.error(err);
process.send({
type: 'error',
payload: err.toString()
});
});

View File

@@ -133,6 +133,7 @@ import BaseIcon from '@/components/BaseIcon.vue';
import BaseVirtualScroll from '@/components/BaseVirtualScroll.vue'; import BaseVirtualScroll from '@/components/BaseVirtualScroll.vue';
import { useFilters } from '@/composables/useFilters'; import { useFilters } from '@/composables/useFilters';
import { useFocusTrap } from '@/composables/useFocusTrap'; import { useFocusTrap } from '@/composables/useFocusTrap';
import { copyText } from '@/libs/copyText';
import { useConnectionsStore } from '@/stores/connections'; import { useConnectionsStore } from '@/stores/connections';
import { HistoryRecord, useHistoryStore } from '@/stores/history'; import { HistoryRecord, useHistoryStore } from '@/stores/history';
@@ -173,7 +174,7 @@ watch(searchTerm, () => {
}); });
const copyQuery = (sql: string) => { const copyQuery = (sql: string) => {
navigator.clipboard.writeText(sql); copyText(sql);
}; };
const deleteQuery = (query: HistoryRecord[]) => { const deleteQuery = (query: HistoryRecord[]) => {

View File

@@ -161,6 +161,7 @@ import ModalProcessesListContext from '@/components/ModalProcessesListContext.vu
import ModalProcessesListRow from '@/components/ModalProcessesListRow.vue'; import ModalProcessesListRow from '@/components/ModalProcessesListRow.vue';
import { useFocusTrap } from '@/composables/useFocusTrap'; import { useFocusTrap } from '@/composables/useFocusTrap';
import Schema from '@/ipc-api/Schema'; import Schema from '@/ipc-api/Schema';
import { copyText } from '@/libs/copyText';
import { useConnectionsStore } from '@/stores/connections'; import { useConnectionsStore } from '@/stores/connections';
import { useNotificationsStore } from '@/stores/notifications'; import { useNotificationsStore } from '@/stores/notifications';
@@ -322,13 +323,13 @@ const closeContext = () => {
const copyCell = () => { const copyCell = () => {
const row = results.value.find(row => Number(row.id) === selectedRow.value); const row = results.value.find(row => Number(row.id) === selectedRow.value);
const valueToCopy = row[selectedCell.value.field]; const valueToCopy = row[selectedCell.value.field];
navigator.clipboard.writeText(valueToCopy); copyText(valueToCopy);
}; };
const copyRow = () => { const copyRow = () => {
const row = results.value.find(row => Number(row.id) === selectedRow.value); const row = results.value.find(row => Number(row.id) === selectedRow.value);
const rowToCopy = JSON.parse(JSON.stringify(row)); const rowToCopy = JSON.parse(JSON.stringify(row));
navigator.clipboard.writeText(JSON.stringify(rowToCopy)); copyText(JSON.stringify(rowToCopy));
}; };
const closeModal = () => emit('close'); const closeModal = () => emit('close');

View File

@@ -15,6 +15,14 @@
:size="18" :size="18"
/> {{ t('connection.disconnect') }}</span> /> {{ t('connection.disconnect') }}</span>
</div> </div>
<div class="context-element" @click.stop="showAppearanceModal">
<span class="d-flex">
<BaseIcon
class="text-light mt-1 mr-1"
icon-name="mdiBrushVariant"
:size="18"
/> {{ t('application.appearance') }}</span>
</div>
<div <div
v-if="!contextConnection.isFolder" v-if="!contextConnection.isFolder"
class="context-element" class="context-element"
@@ -27,14 +35,6 @@
:size="18" :size="18"
/> {{ t('general.duplicate') }}</span> /> {{ t('general.duplicate') }}</span>
</div> </div>
<div class="context-element" @click.stop="showAppearanceModal">
<span class="d-flex">
<BaseIcon
class="text-light mt-1 mr-1"
icon-name="mdiBrushVariant"
:size="18"
/> {{ t('application.appearance') }}</span>
</div>
<div class="context-element" @click="showConfirmModal"> <div class="context-element" @click="showConfirmModal">
<span class="d-flex"> <span class="d-flex">
<BaseIcon <BaseIcon

View File

@@ -11,7 +11,7 @@
> >
<div class="workspace-explorebar-header"> <div class="workspace-explorebar-header">
<div <div
v-if="customizations.database" v-if="customizations.database && databases.length"
class="workspace-explorebar-database-switch" class="workspace-explorebar-database-switch"
:title="t('database.switchDatabase')" :title="t('database.switchDatabase')"
> >

View File

@@ -55,6 +55,14 @@
/> {{ t('general.disable') }} /> {{ t('general.disable') }}
</span> </span>
</div> </div>
<div class="context-element" @click="copyName(selectedMisc.name)">
<span class="d-flex">
<BaseIcon
class="text-light mt-1 mr-1"
icon-name="mdiContentCopy"
:size="18"
/> {{ t('general.copyName') }}</span>
</div>
<div class="context-element" @click="showDeleteModal"> <div class="context-element" @click="showDeleteModal">
<span class="d-flex"> <span class="d-flex">
<BaseIcon <BaseIcon
@@ -108,6 +116,7 @@ import Functions from '@/ipc-api/Functions';
import Routines from '@/ipc-api/Routines'; import Routines from '@/ipc-api/Routines';
import Schedulers from '@/ipc-api/Schedulers'; import Schedulers from '@/ipc-api/Schedulers';
import Triggers from '@/ipc-api/Triggers'; import Triggers from '@/ipc-api/Triggers';
import { copyText } from '@/libs/copyText';
import { useNotificationsStore } from '@/stores/notifications'; import { useNotificationsStore } from '@/stores/notifications';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
@@ -163,6 +172,11 @@ const deleteMessage = computed(() => {
} }
}); });
const copyName = (name: string) => {
copyText(name);
closeContext();
};
const showDeleteModal = () => { const showDeleteModal = () => {
isDeleteModal.value = true; isDeleteModal.value = true;
}; };

View File

@@ -79,6 +79,11 @@
icon-name="mdiFolderCog" icon-name="mdiFolderCog"
:size="18" :size="18"
/> />
<BaseIcon
class="misc-icon open-folder mr-1"
icon-name="mdiFolderOpen"
:size="18"
/>
{{ t('database.trigger', 2) }} {{ t('database.trigger', 2) }}
</summary> </summary>
<div class="accordion-body"> <div class="accordion-body">
@@ -134,6 +139,11 @@
icon-name="mdiFolderSync" icon-name="mdiFolderSync"
:size="18" :size="18"
/> />
<BaseIcon
class="misc-icon open-folder mr-1"
icon-name="mdiFolderOpen"
:size="18"
/>
{{ t('database.storedRoutine', 2) }} {{ t('database.storedRoutine', 2) }}
</summary> </summary>
<div class="accordion-body"> <div class="accordion-body">
@@ -177,6 +187,11 @@
:size="18" :size="18"
:style="`min-width: 18px`" :style="`min-width: 18px`"
/> />
<BaseIcon
class="misc-icon open-folder mr-1"
icon-name="mdiFolderOpen"
:size="18"
/>
{{ t('database.triggerFunction', 2) }} {{ t('database.triggerFunction', 2) }}
</summary> </summary>
<div class="accordion-body"> <div class="accordion-body">
@@ -218,6 +233,11 @@
icon-name="mdiFolderMove" icon-name="mdiFolderMove"
:size="18" :size="18"
/> />
<BaseIcon
class="misc-icon open-folder mr-1"
icon-name="mdiFolderOpen"
:size="18"
/>
{{ t('database.function', 2) }} {{ t('database.function', 2) }}
</summary> </summary>
<div class="accordion-body"> <div class="accordion-body">
@@ -260,6 +280,11 @@
icon-name="mdiFolderClock" icon-name="mdiFolderClock"
:size="18" :size="18"
/> />
<BaseIcon
class="misc-icon open-folder mr-1"
icon-name="mdiFolderOpen"
:size="18"
/>
{{ t('database.scheduler', 2) }} {{ t('database.scheduler', 2) }}
</summary> </summary>
<div class="accordion-body"> <div class="accordion-body">
@@ -645,10 +670,19 @@ defineExpose({ selectSchema, schemaAccordion });
.database-misc { .database-misc {
margin-left: 1.6rem; margin-left: 1.6rem;
.accordion[open] .accordion-header > .misc-icon:first-child::before { .open-folder {
content: "\F0770"; display: none;
} }
.accordion[open] .accordion-header {
> .misc-icon {
display: none;
&.open-folder {
display: initial;
}
}
}
.accordion-body { .accordion-body {
margin-bottom: 0.2rem; margin-bottom: 0.2rem;
} }

View File

@@ -102,6 +102,14 @@
</div> </div>
</div> </div>
</div> </div>
<div class="context-element" @click="copyName(selectedSchema)">
<span class="d-flex">
<BaseIcon
class="text-light mt-1 mr-1"
icon-name="mdiContentCopy"
:size="18"
/> {{ t('general.copyName') }}</span>
</div>
<div <div
v-if="workspace.customizations.schemaExport" v-if="workspace.customizations.schemaExport"
class="context-element" class="context-element"
@@ -198,6 +206,7 @@ import ModalEditSchema from '@/components/ModalEditSchema.vue';
import ModalImportSchema from '@/components/ModalImportSchema.vue'; import ModalImportSchema from '@/components/ModalImportSchema.vue';
import Application from '@/ipc-api/Application'; import Application from '@/ipc-api/Application';
import Schema from '@/ipc-api/Schema'; import Schema from '@/ipc-api/Schema';
import { copyText } from '@/libs/copyText';
import { useNotificationsStore } from '@/stores/notifications'; import { useNotificationsStore } from '@/stores/notifications';
import { useSchemaExportStore } from '@/stores/schemaExport'; import { useSchemaExportStore } from '@/stores/schemaExport';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
@@ -268,6 +277,11 @@ const openCreateSchedulerTab = () => {
emit('open-create-scheduler-tab'); emit('open-create-scheduler-tab');
}; };
const copyName = (name: string) => {
copyText(name);
closeContext();
};
const showDeleteModal = () => { const showDeleteModal = () => {
isDeleteModal.value = true; isDeleteModal.value = true;
}; };

View File

@@ -15,6 +15,14 @@
:size="18" :size="18"
/> {{ t('application.settings') }}</span> /> {{ t('application.settings') }}</span>
</div> </div>
<div class="context-element" @click="copyName(selectedTable.name)">
<span class="d-flex">
<BaseIcon
class="text-light mt-1 mr-1"
icon-name="mdiContentCopy"
:size="18"
/> {{ t('general.copyName') }}</span>
</div>
<div <div
v-if="selectedTable && selectedTable.type === 'table' && customizations.schemaExport" v-if="selectedTable && selectedTable.type === 'table' && customizations.schemaExport"
class="context-element" class="context-element"
@@ -130,6 +138,7 @@ import ConfirmModal from '@/components/BaseConfirmModal.vue';
import BaseContextMenu from '@/components/BaseContextMenu.vue'; import BaseContextMenu from '@/components/BaseContextMenu.vue';
import BaseIcon from '@/components/BaseIcon.vue'; import BaseIcon from '@/components/BaseIcon.vue';
import Tables from '@/ipc-api/Tables'; import Tables from '@/ipc-api/Tables';
import { copyText } from '@/libs/copyText';
import { useNotificationsStore } from '@/stores/notifications'; import { useNotificationsStore } from '@/stores/notifications';
import { useSchemaExportStore } from '@/stores/schemaExport'; import { useSchemaExportStore } from '@/stores/schemaExport';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
@@ -170,6 +179,11 @@ const showTableExportModal = () => {
closeContext(); closeContext();
}; };
const copyName = (name: string) => {
copyText(name);
closeContext();
};
const showDeleteModal = () => { const showDeleteModal = () => {
isDeleteModal.value = true; isDeleteModal.value = true;
}; };

View File

@@ -52,6 +52,7 @@ import { useI18n } from 'vue-i18n';
import BaseContextMenu from '@/components/BaseContextMenu.vue'; import BaseContextMenu from '@/components/BaseContextMenu.vue';
import BaseIcon from '@/components/BaseIcon.vue'; import BaseIcon from '@/components/BaseIcon.vue';
import { copyText } from '@/libs/copyText';
import { useConsoleStore } from '@/stores/console'; import { useConsoleStore } from '@/stores/console';
const { t } = useI18n(); const { t } = useI18n();
@@ -100,7 +101,7 @@ const contextMenu = (event: MouseEvent, wLog: {date: Date; sql: string}) => {
}; };
const copyQuery = () => { const copyQuery = () => {
navigator.clipboard.writeText(contextQuery.value); copyText(contextQuery.value);
isContext.value = false; isContext.value = false;
}; };

View File

@@ -27,11 +27,7 @@
:title="t('general.cancel')" :title="t('general.cancel')"
@click="killTabQuery()" @click="killTabQuery()"
> >
<BaseIcon <BaseIcon icon-name="mdiWindowClose" :size="24" />
class="mr-1"
icon-name="mdiWindowCLose"
:size="24"
/>
<span class="d-invisible pr-1">{{ t('general.run') }}</span> <span class="d-invisible pr-1">{{ t('general.run') }}</span>
</button> </button>
<button <button

View File

@@ -3,7 +3,7 @@
ref="tableWrapper" ref="tableWrapper"
class="vscroll no-outline" class="vscroll no-outline"
tabindex="0" tabindex="0"
:style="{'height': resultsSize+'px'}" :style="{ 'height': resultsSize + 'px' }"
@blur="deselectRows" @blur="deselectRows"
@focus="hasFocus = true" @focus="hasFocus = true"
@keyup.delete="showDeleteConfirmModal" @keyup.delete="showDeleteConfirmModal"
@@ -28,7 +28,7 @@
v-for="(result, index) in resultsWithRows" v-for="(result, index) in resultsWithRows"
:key="index" :key="index"
class="tab-item" class="tab-item"
:class="{'active': resultsetIndex === index}" :class="{ 'active': resultsetIndex === index }"
@click="selectResultset(index)" @click="selectResultset(index)"
> >
<a>{{ result.fields ? result.fields[0]?.table : '' }} ({{ result.rows.length }})</a> <a>{{ result.fields ? result.fields[0]?.table : '' }} ({{ result.rows.length }})</a>
@@ -57,7 +57,7 @@
<span>{{ field.alias || field.name }}</span> <span>{{ field.alias || field.name }}</span>
<BaseIcon <BaseIcon
v-if="isSortable && currentSort === field.name || currentSort === `${field.table}.${field.name}`" v-if="isSortable && currentSort === field.name || currentSort === `${field.table}.${field.name}`"
:icon-name="currentSortDir === 'asc' ? 'mdiSortAscending':'mdiSortDescending'" :icon-name="currentSortDir === 'asc' ? 'mdiSortAscending' : 'mdiSortDescending'"
:size="18" :size="18"
class="sort-icon ml-1" class="sort-icon ml-1"
/> />
@@ -90,7 +90,7 @@
:fields="fieldsObj" :fields="fieldsObj"
:key-usage="keyUsage" :key-usage="keyUsage"
:element-type="elementType" :element-type="elementType"
:class="{'selected': selectedRows.includes(row._antares_id)}" :class="{ 'selected': selectedRows.includes(row._antares_id) }"
:selected="selectedRows.includes(row._antares_id)" :selected="selectedRows.includes(row._antares_id)"
:selected-cell="selectedRows.length === 1 && selectedRows.includes(row._antares_id) ? selectedField : null" :selected-cell="selectedRows.length === 1 && selectedRows.includes(row._antares_id) ? selectedField : null"
@start-editing="isEditingRow = true" @start-editing="isEditingRow = true"
@@ -163,7 +163,7 @@
<BaseSelect <BaseSelect
v-model="sqlExportOptions.sqlInsertDivider" v-model="sqlExportOptions.sqlInsertDivider"
class="form-select" class="form-select"
:options="[{value: 'bytes', label: 'KiB'}, {value: 'rows', label: t('database.row', 2)}]" :options="[{ value: 'bytes', label: 'KiB' }, { value: 'rows', label: t('database.row', 2) }]"
/> />
</div> </div>
</div> </div>
@@ -208,9 +208,9 @@
v-model="csvExportOptions.stringDelimiter" v-model="csvExportOptions.stringDelimiter"
class="form-select" class="form-select"
:options="[ :options="[
{value: '', label: t('general.none')}, { value: '', label: t('general.none') },
{value: 'single', label: t('general.singleQuote')}, { value: 'single', label: t('general.singleQuote') },
{value: 'double', label: t('general.doubleQuote')} { value: 'double', label: t('general.doubleQuote') }
]" ]"
/> />
</div> </div>
@@ -235,7 +235,10 @@
</label> </label>
</div> </div>
<div class="column col-7"> <div class="column col-7">
<label class="form-switch d-inline-block" @click.prevent="csvExportOptions.header = !csvExportOptions.header"> <label
class="form-switch d-inline-block"
@click.prevent="csvExportOptions.header = !csvExportOptions.header"
>
<input type="checkbox" :checked="csvExportOptions.header"> <input type="checkbox" :checked="csvExportOptions.header">
<i class="form-icon" /> <i class="form-icon" />
</label> </label>
@@ -249,10 +252,10 @@
<script setup lang="ts"> <script setup lang="ts">
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
import faker from '@faker-js/faker';
import { BLOB, DATE, DATETIME, LONG_TEXT, TEXT, TIME } from 'common/fieldTypes'; import { BLOB, DATE, DATETIME, LONG_TEXT, TEXT, TIME } from 'common/fieldTypes';
import { QueryResult, TableField } from 'common/interfaces/antares'; import { QueryResult, TableField } from 'common/interfaces/antares';
import { TableUpdateParams } from 'common/interfaces/tableApis'; import { TableUpdateParams } from 'common/interfaces/tableApis';
import { fakerCustom } from 'common/libs/fakerCustom';
import { jsonToSqlInsert } from 'common/libs/sqlUtils'; import { jsonToSqlInsert } from 'common/libs/sqlUtils';
import { uidGen } from 'common/libs/uidGen'; import { uidGen } from 'common/libs/uidGen';
import * as json2php from 'json2php'; import * as json2php from 'json2php';
@@ -267,6 +270,7 @@ import BaseSelect from '@/components/BaseSelect.vue';
import BaseVirtualScroll from '@/components/BaseVirtualScroll.vue'; import BaseVirtualScroll from '@/components/BaseVirtualScroll.vue';
import TableContext from '@/components/WorkspaceTabQueryTableContext.vue'; import TableContext from '@/components/WorkspaceTabQueryTableContext.vue';
import WorkspaceTabQueryTableRow from '@/components/WorkspaceTabQueryTableRow.vue'; import WorkspaceTabQueryTableRow from '@/components/WorkspaceTabQueryTableRow.vue';
import { copyText } from '@/libs/copyText';
import { unproxify } from '@/libs/unproxify'; import { unproxify } from '@/libs/unproxify';
import { useConsoleStore } from '@/stores/console'; import { useConsoleStore } from '@/stores/console';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
@@ -299,7 +303,7 @@ const emit = defineEmits([
'duplicate-row' 'duplicate-row'
]); ]);
const resultTable: Ref<Component & {updateWindow: () => void}> = ref(null); const resultTable: Ref<Component & { updateWindow: () => void }> = ref(null);
const tableWrapper: Ref<HTMLDivElement> = ref(null); const tableWrapper: Ref<HTMLDivElement> = ref(null);
const table: Ref<HTMLDivElement> = ref(null); const table: Ref<HTMLDivElement> = ref(null);
const resultsSize = ref(0); const resultsSize = ref(0);
@@ -377,7 +381,7 @@ const keyUsage = computed(() => resultsWithRows.value.length ? resultsWithRows.v
const fieldsObj = computed(() => { const fieldsObj = computed(() => {
if (sortedResults.value.length) { if (sortedResults.value.length) {
const fieldsObj: {[key: string]: TableField} = {}; const fieldsObj: { [key: string]: TableField } = {};
for (const key in sortedResults.value[0]) { for (const key in sortedResults.value[0]) {
if (key === '_antares_id') continue; if (key === '_antares_id') continue;
@@ -483,7 +487,7 @@ const resizeResults = () => {
const refreshScroller = () => resizeResults(); const refreshScroller = () => resizeResults();
const updateField = (payload: { field: string; type: string; content: any }, row: {[key: string]: any}) => { const updateField = (payload: { field: string; type: string; content: any }, row: { [key: string]: any }) => {
const orgRow: any = localResults.value.find((lr: any) => lr._antares_id === row._antares_id); const orgRow: any = localResults.value.find((lr: any) => lr._antares_id === row._antares_id);
Object.keys(orgRow).forEach(key => { // remap the row Object.keys(orgRow).forEach(key => { // remap the row
@@ -568,7 +572,7 @@ const copyCell = () => {
let valueToCopy = row[cellName]; let valueToCopy = row[cellName];
if (typeof valueToCopy === 'object') if (typeof valueToCopy === 'object')
valueToCopy = JSON.stringify(valueToCopy); valueToCopy = JSON.stringify(valueToCopy);
navigator.clipboard.writeText(valueToCopy); copyText(valueToCopy);
}; };
const copyRow = (format: string) => { const copyRow = (format: string) => {
@@ -590,7 +594,7 @@ const copyRow = (format: string) => {
} }
if (format === 'json') if (format === 'json')
navigator.clipboard.writeText(JSON.stringify(contentToCopy)); copyText(JSON.stringify(contentToCopy));
else if (format === 'sql') { else if (format === 'sql') {
if (!Array.isArray(contentToCopy)) contentToCopy = [contentToCopy]; if (!Array.isArray(contentToCopy)) contentToCopy = [contentToCopy];
@@ -598,11 +602,11 @@ const copyRow = (format: string) => {
json: contentToCopy, json: contentToCopy,
client: workspaceClient.value, client: workspaceClient.value,
fields: fieldsObj.value as { fields: fieldsObj.value as {
[key: string]: {type: string; datePrecision: number}; [key: string]: { type: string; datePrecision: number };
}, },
table: getTable(resultsetIndex.value) table: getTable(resultsetIndex.value)
}); });
navigator.clipboard.writeText(sqlInserts); copyText(sqlInserts);
} }
else if (format === 'csv') { else if (format === 'csv') {
const csv = []; const csv = [];
@@ -614,7 +618,7 @@ const copyRow = (format: string) => {
for (const row of contentToCopy) for (const row of contentToCopy)
csv.push(Object.values(row).map(col => typeof col === 'string' ? `"${col}"` : col).join(';')); csv.push(Object.values(row).map(col => typeof col === 'string' ? `"${col}"` : col).join(';'));
navigator.clipboard.writeText(csv.join('\n')); copyText(csv.join('\n'));
} }
else if (format === 'html') { else if (format === 'html') {
const arrayContent = new Array<string[]>(); const arrayContent = new Array<string[]>();
@@ -637,7 +641,7 @@ const copyRow = (format: string) => {
if (!Array.isArray(contentToCopy)) contentToCopy = [contentToCopy]; if (!Array.isArray(contentToCopy)) contentToCopy = [contentToCopy];
const printer = json2php.make({ linebreak: '\n', indent: '\t', shortArraySyntax: true }); const printer = json2php.make({ linebreak: '\n', indent: '\t', shortArraySyntax: true });
const phpString = printer(contentToCopy); const phpString = printer(contentToCopy);
navigator.clipboard.writeText(phpString); copyText(phpString);
} }
}; };
@@ -670,28 +674,18 @@ const fillCell = (event: { name: string; group: string; type: string }) => {
datePrecision += i === 0 ? '.S' : 'S'; datePrecision += i === 0 ? '.S' : 'S';
} }
if (event.group === 'custom') { fakeValue = (fakerCustom as any)[event.group][event.name]();
if (event.type === 'time' && event.name === 'now') if (['string', 'number'].includes(typeof fakeValue)) {
fakeValue = moment().format(`HH:mm:ss${datePrecision}`); if (typeof fakeValue === 'number')
else if (event.type === 'time' && event.name === 'random') fakeValue = String(fakeValue);
fakeValue = moment(faker.date.recent()).format(`HH:mm:ss${datePrecision}`);
else if (event.type === 'datetime' && event.name === 'now')
fakeValue = moment().format(`YYYY-MM-DD HH:mm:ss${datePrecision}`);
}
else {
fakeValue = (faker as any)[event.group][event.name]();
if (['string', 'number'].includes(typeof fakeValue)) {
if (typeof fakeValue === 'number')
fakeValue = String(fakeValue);
if (selectedCell.value.length) if (selectedCell.value.length)
fakeValue = fakeValue.substring(0, selectedCell.value.length < 1024 ? Number(selectedCell.value.length) : 1024); fakeValue = fakeValue.substring(0, selectedCell.value.length < 1024 ? Number(selectedCell.value.length) : 1024);
}
else if ([...DATE, ...DATETIME].includes(selectedCell.value.type))
fakeValue = moment(fakeValue).format(`YYYY-MM-DD HH:mm:ss${datePrecision}`);
else if (TIME.includes(selectedCell.value.type))
fakeValue = moment(fakeValue).format(`HH:mm:ss${datePrecision}`);
} }
else if ([...DATE, ...DATETIME].includes(selectedCell.value.type))
fakeValue = moment(fakeValue).format(`YYYY-MM-DD HH:mm:ss${datePrecision}`);
else if (TIME.includes(selectedCell.value.type))
fakeValue = moment(fakeValue).format(`HH:mm:ss${datePrecision}`);
const params = { const params = {
primary: primaryField.value?.name, primary: primaryField.value?.name,
@@ -859,12 +853,12 @@ const downloadTable = (format: 'csv' | 'json' | 'sql' | 'php', table: string, po
type: format, type: format,
content: rows, content: rows,
fields: JSON.parse(JSON.stringify(fieldsObj.value)) as { fields: JSON.parse(JSON.stringify(fieldsObj.value)) as {
[key: string]: {type: string; datePrecision: number}; [key: string]: { type: string; datePrecision: number };
}, },
client: workspaceClient.value, client: workspaceClient.value,
table, table,
sqlOptions: popup ? { ...sqlExportOptions.value }: null, sqlOptions: popup ? { ...sqlExportOptions.value } : null,
csvOptions: popup ? { ...csvExportOptions.value }: null csvOptions: popup ? { ...csvExportOptions.value } : null
}); });
}; };
@@ -885,7 +879,7 @@ const onKey = async (e: KeyboardEvent) => {
const copyType = defaultCopyType.value; const copyType = defaultCopyType.value;
if (selectedRows.value.length >= 1) { if (selectedRows.value.length >= 1) {
if (selectedRows.value.length === 1 && copyType === 'cell') if (selectedRows.value.length === 1 && copyType === 'cell')
await navigator.clipboard.writeText(scrollElement.value.querySelector('.td.selected').innerText); await copyText(scrollElement.value.querySelector('.td.selected').innerText);
else if (selectedRows.value.length > 1 && copyType === 'cell') else if (selectedRows.value.length > 1 && copyType === 'cell')
copyRow('html'); copyRow('html');
else else
@@ -897,7 +891,7 @@ const onKey = async (e: KeyboardEvent) => {
if (!(e.ctrlKey || e.metaKey) && (e.code.includes('Arrow') || e.code === 'Tab') && sortedResults.value.length > 0 && !e.altKey) { if (!(e.ctrlKey || e.metaKey) && (e.code.includes('Arrow') || e.code === 'Tab') && sortedResults.value.length > 0 && !e.altKey) {
e.preventDefault(); e.preventDefault();
const aviableFields= Object.keys(sortedResults.value[0]).slice(0, -1); // removes _antares_id const aviableFields = Object.keys(sortedResults.value[0]).slice(0, -1); // removes _antares_id
if (!selectedField.value) if (!selectedField.value)
selectedField.value = aviableFields[0]; selectedField.value = aviableFields[0];
@@ -914,8 +908,8 @@ const onKey = async (e: KeyboardEvent) => {
nextIndex = selectedIndex + 1; nextIndex = selectedIndex + 1;
nextFieldIndex = selectedFieldIndex; nextFieldIndex = selectedFieldIndex;
if (nextIndex > sortedResults.value.length -1) if (nextIndex > sortedResults.value.length - 1)
nextIndex = sortedResults.value.length -1; nextIndex = sortedResults.value.length - 1;
break; break;
case 'ArrowUp': case 'ArrowUp':
@@ -931,7 +925,7 @@ const onKey = async (e: KeyboardEvent) => {
nextIndex = selectedIndex; nextIndex = selectedIndex;
nextFieldIndex = selectedFieldIndex + 1; nextFieldIndex = selectedFieldIndex + 1;
if (nextFieldIndex > aviableFields.length -1) if (nextFieldIndex > aviableFields.length - 1)
nextFieldIndex = 0; nextFieldIndex = 0;
break; break;
@@ -941,7 +935,7 @@ const onKey = async (e: KeyboardEvent) => {
nextFieldIndex = selectedFieldIndex - 1; nextFieldIndex = selectedFieldIndex - 1;
if (nextFieldIndex < 0) if (nextFieldIndex < 0)
nextFieldIndex = aviableFields.length -1; nextFieldIndex = aviableFields.length - 1;
break; break;
@@ -950,11 +944,11 @@ const onKey = async (e: KeyboardEvent) => {
if (e.shiftKey) { if (e.shiftKey) {
nextFieldIndex = selectedFieldIndex - 1; nextFieldIndex = selectedFieldIndex - 1;
if (nextFieldIndex < 0) if (nextFieldIndex < 0)
nextFieldIndex = aviableFields.length -1; nextFieldIndex = aviableFields.length - 1;
} }
else { else {
nextFieldIndex = selectedFieldIndex + 1; nextFieldIndex = selectedFieldIndex + 1;
if (nextFieldIndex > aviableFields.length -1) if (nextFieldIndex > aviableFields.length - 1)
nextFieldIndex = 0; nextFieldIndex = 0;
} }
} }
@@ -1049,32 +1043,33 @@ onUnmounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.vscroll { .vscroll {
height: 1000px; height: 1000px;
overflow: auto; overflow: auto;
overflow-anchor: none; overflow-anchor: none;
} }
.column-resizable { .column-resizable {
&:hover,
&:active { &:hover,
resize: horizontal; &:active {
overflow: hidden; resize: horizontal;
} overflow: hidden;
}
} }
.table-column-title { .table-column-title {
display: flex; display: flex;
align-items: center; align-items: center;
} }
.sort-icon { .sort-icon {
font-size: 0.7rem; font-size: 0.7rem;
line-height: 1; line-height: 1;
margin-left: 0.2rem; margin-left: 0.2rem;
} }
.result-tabs { .result-tabs {
background: transparent !important; background: transparent !important;
margin: 0; margin: 0;
} }
</style> </style>

View File

@@ -197,13 +197,13 @@ const fakerMethods = {
{ name: 'amount', group: 'finance' } { name: 'amount', group: 'finance' }
], ],
datetime: [ datetime: [
{ name: 'now', group: 'custom' }, { name: 'now', group: 'date' },
{ name: 'past', group: 'date' }, { name: 'past', group: 'date' },
{ name: 'future', group: 'date' } { name: 'future', group: 'date' }
], ],
time: [ time: [
{ name: 'now', group: 'custom' }, { name: 'now', group: 'time' },
{ name: 'random', group: 'custom' } { name: 'random', group: 'time' }
], ],
uuid: [ uuid: [
{ name: 'uuid', group: 'random' } { name: 'uuid', group: 'random' }

View File

@@ -580,7 +580,7 @@ const onKey = (e: KeyboardEvent) => {
if (!editingField.value && e.key === 'Enter') if (!editingField.value && e.key === 'Enter')
return editON(props.selectedCell); return editON(props.selectedCell);
if (editingField.value && e.key === 'Enter' && !isBaseSelectField.value) if (editingField.value && e.key === 'Enter' && !isBaseSelectField.value && !isTextareaEditor.value)
return editOFF(); return editOFF();
if (editingField.value && e.key === 'Escape') { if (editingField.value && e.key === 'Escape') {

View File

@@ -183,6 +183,7 @@
<WorkspaceTabTableFilters <WorkspaceTabTableFilters
v-if="isSearch" v-if="isSearch"
:fields="fields" :fields="fields"
:is-quering="isQuering"
:conn-client="connection.client" :conn-client="connection.client"
@filter="updateFilters" @filter="updateFilters"
@filter-change="onFilterChange" @filter-change="onFilterChange"

View File

@@ -9,6 +9,7 @@
<input <input
v-model="row.active" v-model="row.active"
type="checkbox" type="checkbox"
:disabled="isQuering"
@change="doFilter" @change="doFilter"
><i class="form-icon" /> ><i class="form-icon" />
</label> </label>
@@ -18,11 +19,13 @@
:options="fields" :options="fields"
option-track-by="name" option-track-by="name"
option-label="name" option-label="name"
:disabled="isQuering"
/> />
<BaseSelect <BaseSelect
v-model="row.op" v-model="row.op"
class="form-select ml-2 col-auto select-sm" class="form-select ml-2 col-auto select-sm"
:options="operators" :options="operators"
:disabled="isQuering"
/> />
<div class="workspace-table-filters-row-value ml-2"> <div class="workspace-table-filters-row-value ml-2">
<input <input
@@ -30,12 +33,14 @@
v-model="row.value" v-model="row.value"
type="text" type="text"
class="form-input input-sm" class="form-input input-sm"
:disabled="isQuering"
> >
<input <input
v-if="row.op === 'BETWEEN'" v-if="row.op === 'BETWEEN'"
v-model="row.value2" v-model="row.value2"
type="text" type="text"
class="form-input ml-2 input-sm" class="form-input ml-2 input-sm"
:disabled="isQuering"
> >
</div> </div>
<button <button
@@ -87,15 +92,14 @@ const { t } = useI18n();
const props = defineProps({ const props = defineProps({
fields: Array as Prop<TableField[]>, fields: Array as Prop<TableField[]>,
connClient: String as Prop<ClientCode> connClient: String as Prop<ClientCode>,
isQuering: Boolean
}); });
const emit = defineEmits(['filter-change', 'filter']); const emit = defineEmits(['filter-change', 'filter']);
const rows = ref([]); const rows = ref([]);
const operators = ref<TableFilterOperator[]>([ const operators: TableFilterOperator[] = customizations[props.connClient].operators;
'=', '!=', '>', '<', '>=', '<=', 'IN', 'NOT IN', 'LIKE', 'NOT LIKE', 'BETWEEN', 'IS NULL', 'IS NOT NULL'
]);
const clientCustomizations = computed(() => customizations[props.connClient]); const clientCustomizations = computed(() => customizations[props.connClient]);
@@ -122,7 +126,7 @@ const createClausole = (filter: TableFilterClausole) => {
const { elementsWrapper: ew, stringsWrapper: sw } = clientCustomizations.value; const { elementsWrapper: ew, stringsWrapper: sw } = clientCustomizations.value;
let value; let value;
if (isNumeric) { if (isNumeric && !['IN', 'NOT IN', 'RLIKE', 'NOT RLIKE'].includes(filter.op)) {
if (isNaN(Number(filter.value))) if (isNaN(Number(filter.value)))
filter.value = ''; filter.value = '';
if (isNaN(Number(filter.value2))) if (isNaN(Number(filter.value2)))
@@ -145,7 +149,7 @@ const createClausole = (filter: TableFilterClausole) => {
val = val.trim(); val = val.trim();
return isNumeric ? val : `${sw}${val}${sw}`; return isNumeric ? val : `${sw}${val}${sw}`;
}).join(','); }).join(',');
value = `(${filter.value})`; value = `(${value})`;
break; break;
case 'IS NULL': case 'IS NULL':
case 'IS NOT NULL': case 'IS NOT NULL':

View File

@@ -65,7 +65,8 @@ export const enUS = {
actionSuccessful: '{action} successful', actionSuccessful: '{action} successful',
outputFormat: 'Output format', outputFormat: 'Output format',
singleFile: 'Single {ext} file', singleFile: 'Single {ext} file',
zipCompressedFile: 'ZIP compressed {ext} file' zipCompressedFile: 'ZIP compressed {ext} file',
copyName: 'Copy name'
}, },
connection: { // Database connection connection: { // Database connection
connectionName: 'Connection name', connectionName: 'Connection name',

View File

@@ -14,6 +14,7 @@ import { koKR } from './ko-KR';
import { nlNL } from './nl-NL'; import { nlNL } from './nl-NL';
import { ptBR } from './pt-BR'; import { ptBR } from './pt-BR';
import { ruRU } from './ru-RU'; import { ruRU } from './ru-RU';
import { ukUA } from './uk-UA';
import { viVN } from './vi-VN'; import { viVN } from './vi-VN';
import { zhCN } from './zh-CN'; import { zhCN } from './zh-CN';
const messages = { const messages = {
@@ -32,7 +33,8 @@ const messages = {
'ko-KR': koKR, 'ko-KR': koKR,
'nl-NL': nlNL, 'nl-NL': nlNL,
'ca-ES': caES, 'ca-ES': caES,
'cs-CZ': csCZ 'cs-CZ': csCZ,
'uk-UA': ukUA
}; };
type NestedPartial<T> = { type NestedPartial<T> = {

View File

@@ -24,17 +24,17 @@ export const nlNL = {
clear: 'Wis', clear: 'Wis',
seconds: 'Seconden', seconds: 'Seconden',
options: 'Opties', options: 'Opties',
discard: 'Discard', discard: 'Verwerp',
stay: 'Stay', stay: 'Stay',
author: 'Auteur', author: 'Auteur',
upload: 'Upload', upload: 'Upload',
browse: 'Blader', browse: 'Blader',
content: 'Content', content: 'Content',
cut: 'Cut', cut: 'Knip',
copy: 'Kopieer', copy: 'Kopieer',
paste: 'Plak', paste: 'Plak',
tools: 'Gereedschap', tools: 'Gereedschap',
format: 'Format', format: 'Formatteer',
all: 'Alle', all: 'Alle',
duplicate: 'Dupliceer', duplicate: 'Dupliceer',
new: 'Nieuw', new: 'Nieuw',
@@ -48,7 +48,7 @@ export const nlNL = {
disabled: 'Uitgeschakeld', disabled: 'Uitgeschakeld',
enable: 'Inschakelen', enable: 'Inschakelen',
disable: 'Uitschakelen', disable: 'Uitschakelen',
contributors: 'Contributors', contributors: 'Bijdragers',
pin: 'Vastzetten', pin: 'Vastzetten',
unpin: 'Losmaken', unpin: 'Losmaken',
folder: 'Folder | Folders', folder: 'Folder | Folders',
@@ -129,7 +129,7 @@ export const nlNL = {
scheduler: 'Scheduler | Schedulers', scheduler: 'Scheduler | Schedulers',
event: 'Event', event: 'Event',
parameters: 'Parameters', parameters: 'Parameters',
function: 'Functiw | Functies', function: 'Functie | Functies',
deterministic: 'Deterministic', deterministic: 'Deterministic',
context: 'Context', context: 'Context',
export: 'Export', export: 'Export',
@@ -138,10 +138,10 @@ export const nlNL = {
timing: 'Timing', timing: 'Timing',
state: 'State', state: 'State',
execution: 'Execution', execution: 'Execution',
starts: 'Starts', starts: 'Start',
ends: 'Ends', ends: 'Eindigt',
variables: 'Variabelen', variables: 'Variabelen',
processes: 'Processes', processes: 'Processen',
database: 'Database', database: 'Database',
array: 'Array', array: 'Array',
structure: 'Structuur', structure: 'Structuur',
@@ -254,9 +254,9 @@ export const nlNL = {
queryHistory: 'Query geschiedenis', queryHistory: 'Query geschiedenis',
clearQuery: 'Wis query', clearQuery: 'Wis query',
fillCell: 'Vul cel', fillCell: 'Vul cel',
executeSelectedQuery: 'Execute selected query', executeSelectedQuery: 'Voer geselecteerde query uit',
noResultsPresent: 'Geen resultaten beschikbaar', noResultsPresent: 'Geen resultaten beschikbaar',
sqlExportOptions: 'SQL export options', sqlExportOptions: 'SQL export opties',
targetTable: 'Doeltabel', targetTable: 'Doeltabel',
switchDatabase: 'Wissel van database', switchDatabase: 'Wissel van database',
importQueryErrors: 'Waarschuwing: {n} fout is opgetreden | Waarschuwing: {n} fouten opgetreden', importQueryErrors: 'Waarschuwing: {n} fout is opgetreden | Waarschuwing: {n} fouten opgetreden',
@@ -275,7 +275,7 @@ export const nlNL = {
application: 'Applicatie', application: 'Applicatie',
editor: 'Editor', editor: 'Editor',
scratchpad: 'Kladblok', scratchpad: 'Kladblok',
changelog: 'Changelog', changelog: 'Wijzigingslogboek',
small: 'Klein', small: 'Klein',
medium: 'Medium', medium: 'Medium',
large: 'Groot', large: 'Groot',
@@ -296,11 +296,11 @@ export const nlNL = {
restartToInstall: 'Herstart Antares om te installeren', restartToInstall: 'Herstart Antares om te installeren',
notificationsTimeout: 'Notifications timeout', notificationsTimeout: 'Notifications timeout',
openNewTab: 'Open een nieuw tabblad', openNewTab: 'Open een nieuw tabblad',
unsavedChanges: 'Onopgeslagen wijzigingen', unsavedChanges: 'Niet opgeslagen wijzigingen',
discardUnsavedChanges: 'Je hebt onopgeslagen wijzigingen. Closing this tab these changes will be discarded.', discardUnsavedChanges: 'Je hebt niet opgeslagen wijzigingen. Closing this tab these changes will be discarded.',
applicationTheme: 'Applicatie thema', applicationTheme: 'Applicatiethema',
editorTheme: 'Editor Theme', editorTheme: 'Editor Thema',
wrapLongLines: 'Wrap long lines', wrapLongLines: 'Lange regels afbreken',
includeBetaUpdates: 'Include beta updates', includeBetaUpdates: 'Include beta updates',
markdownSupported: 'Markdown wordt ondersteund', markdownSupported: 'Markdown wordt ondersteund',
plantATree: 'Plant een boom', plantATree: 'Plant een boom',
@@ -310,7 +310,7 @@ export const nlNL = {
closeTab: 'Sluit tabblad', closeTab: 'Sluit tabblad',
goToDownloadPage: 'Ga naar de downloadpagina', goToDownloadPage: 'Ga naar de downloadpagina',
disableBlur: 'Vervagen uitschakelen', disableBlur: 'Vervagen uitschakelen',
missingOrIncompleteTranslation: 'Missing or incomplete translation?', missingOrIncompleteTranslation: 'Onvolledige of ontbrekende vertaling?',
findOutHowToContribute: 'Ontdek hoe je kunt bijdragen', findOutHowToContribute: 'Ontdek hoe je kunt bijdragen',
disableScratchpad: 'Kladblok uitschakelen', disableScratchpad: 'Kladblok uitschakelen',
reportABug: 'Bug melden', reportABug: 'Bug melden',
@@ -338,9 +338,9 @@ export const nlNL = {
folderName: 'Foldernaam', folderName: 'Foldernaam',
deleteFolder: 'Verwijder folder', deleteFolder: 'Verwijder folder',
editConnectionAppearance: 'Edit connection appearance', editConnectionAppearance: 'Edit connection appearance',
defaultCopyType: 'Default copy type', defaultCopyType: 'Kopieer standaard',
showTableSize: 'Show table size in sidebar', showTableSize: 'Toon tabelgrootte in de sidebar',
showTableSizeDescription: 'MySQL/MariaDB only. Enable this option may affects performance on schema with many tables.', showTableSizeDescription: 'Alleen voor MySQL/MariaDB. Bij schema\'s met veel tabellen kan dit de snelheid beïnvloeden.',
searchForSchemas: 'Zoek naar schemas', searchForSchemas: 'Zoek naar schemas',
searchForElements: 'Zoek naar elementen', searchForElements: 'Zoek naar elementen',
switchSearchMethod: 'Switch search method', switchSearchMethod: 'Switch search method',
@@ -370,36 +370,36 @@ export const nlNL = {
password: 'Wachtwoord' password: 'Wachtwoord'
}, },
faker: { faker: {
address: 'Address', address: 'Adres',
commerce: 'Commerce', commerce: 'Commerce',
company: 'Company', company: 'Company',
database: 'Database', database: 'Database',
date: 'Date', date: 'Datum',
finance: 'Finance', finance: 'Finance',
git: 'Git', git: 'Git',
hacker: 'Hacker', hacker: 'Hacker',
internet: 'Internet', internet: 'Internet',
lorem: 'Lorem', lorem: 'Lorem',
name: 'Name', name: 'Naam',
music: 'Music', music: 'Muziek',
phone: 'Phone', phone: 'Telefoon',
random: 'Random', random: 'Random',
system: 'System', system: 'System',
time: 'Time', time: 'Tijd',
vehicle: 'Vehicle', vehicle: 'Voertuig',
zipCode: 'Zip code', zipCode: 'Postcode',
zipCodeByState: 'Zip code by state', zipCodeByState: 'Zip code by state',
city: 'City', city: 'Woonplaats',
cityPrefix: 'City prefix', cityPrefix: 'City prefix',
citySuffix: 'City suffix', citySuffix: 'City suffix',
streetName: 'Street name', streetName: 'Straatnaam',
streetAddress: 'Street address', streetAddress: 'Street address',
streetSuffix: 'Street suffix', streetSuffix: 'Street suffix',
streetPrefix: 'Street prefix', streetPrefix: 'Street prefix',
secondaryAddress: 'Secondary address', secondaryAddress: 'Secondary address',
county: 'County', county: 'County',
country: 'Country', country: 'Land',
countryCode: 'Country code', countryCode: 'Landcode',
state: 'State', state: 'State',
stateAbbr: 'State abbreviation', stateAbbr: 'State abbreviation',
latitude: 'Latitude', latitude: 'Latitude',
@@ -408,11 +408,11 @@ export const nlNL = {
cardinalDirection: 'Cardinal direction', cardinalDirection: 'Cardinal direction',
ordinalDirection: 'Ordinal direction', ordinalDirection: 'Ordinal direction',
nearbyGPSCoordinate: 'Nearby GPS coordinate', nearbyGPSCoordinate: 'Nearby GPS coordinate',
timeZone: 'Time zone', timeZone: 'Tijdzone',
color: 'Color', color: 'Kleur',
department: 'Department', department: 'Afdeling',
productName: 'Product name', productName: 'Productnaam',
price: 'Price', price: 'Prijs',
productAdjective: 'Product adjective', productAdjective: 'Product adjective',
productMaterial: 'Product material', productMaterial: 'Product material',
product: 'Product', product: 'Product',
@@ -453,7 +453,7 @@ export const nlNL = {
litecoinAddress: 'Litecoin address', litecoinAddress: 'Litecoin address',
creditCardNumber: 'Credit card number', creditCardNumber: 'Credit card number',
creditCardCVV: 'Credit card CVV', creditCardCVV: 'Credit card CVV',
ethereumAddress: 'Ethereum address', ethereumAddress: 'Ethereum adres',
iban: 'IBAN', iban: 'IBAN',
bic: 'BIC', bic: 'BIC',
transactionDescription: 'Transaction description', transactionDescription: 'Transaction description',
@@ -464,14 +464,14 @@ export const nlNL = {
shortSha: 'Short SHA', shortSha: 'Short SHA',
abbreviation: 'Abbreviation', abbreviation: 'Abbreviation',
adjective: 'Adjective', adjective: 'Adjective',
noun: 'Noun', noun: 'Zelfstandig naamwoord',
verb: 'Verb', verb: 'Werkwoord',
ingverb: 'Ingverb', ingverb: 'Ingverb',
phrase: 'Phrase', phrase: 'Zin',
avatar: 'Avatar', avatar: 'Avatar',
email: 'Email', email: 'E-mailadres',
exampleEmail: 'Voorbeeld email', exampleEmail: 'Voorbeeld email',
userName: 'Gebuikersnaam', userName: 'Gebruikersnaam',
protocol: 'Protocol', protocol: 'Protocol',
url: 'Url', url: 'Url',
domainName: 'Domeinnaam', domainName: 'Domeinnaam',
@@ -482,8 +482,8 @@ export const nlNL = {
userAgent: 'User agent', userAgent: 'User agent',
mac: 'Mac', mac: 'Mac',
password: 'Wachtwoord', password: 'Wachtwoord',
word: 'Word', word: 'Woord',
words: 'Words', words: 'Woorden',
sentence: 'Zin', sentence: 'Zin',
slug: 'Slug', slug: 'Slug',
sentences: 'Zinnen', sentences: 'Zinnen',

View File

@@ -14,5 +14,6 @@ export const localesNames: {[key: string]: string} = {
'ko-KR': '한국어', 'ko-KR': '한국어',
'nl-NL': 'Nederlands', 'nl-NL': 'Nederlands',
'ca-ES': 'Català', 'ca-ES': 'Català',
'cs-CZ': 'Čeština' 'cs-CZ': 'Čeština',
'uk-UA': 'Українська'
}; };

550
src/renderer/i18n/uk-UA.ts Normal file
View File

@@ -0,0 +1,550 @@
export const ukUA = {
general: { // Загальні терміни для загальних цілей
edit: 'Редагувати',
save: 'Зберегти',
close: 'Закрити',
delete: 'Видалити',
confirm: 'Підтвердити',
cancel: 'Скасувати',
send: 'Надіслати',
refresh: 'Оновити',
autoRefresh: 'Автоматичне оновлення',
version: 'Версія',
donate: 'Пожертвувати',
run: 'Запустити',
results: 'Результати',
size: 'Розмір',
mimeType: 'Тип MIME',
download: 'Завантажити',
add: 'Додати',
data: 'Дані',
properties: 'Властивості',
name: 'Назва',
clear: 'Очистити',
options: 'Параметри',
insert: 'Вставити',
discard: 'Відкинути',
stay: 'Залишити',
author: 'Автор',
upload: 'Завантажити',
browse: 'Переглянути',
content: 'Вміст',
cut: 'Вирізати',
copy: 'Копіювати',
paste: 'Вставити',
duplicate: 'Дублювати',
tools: 'Інструменти',
seconds: 'Секунди',
all: 'Усі',
new: 'Новий',
select: 'Вибрати',
change: 'Змінити',
include: 'Включити',
includes: 'Включає',
completed: 'Завершено',
aborted: 'Перервано',
disabled: 'Вимкнено',
enable: 'Увімкнути',
disable: 'Вимкнути',
contributors: 'Учасники',
pin: 'Закріпити',
unpin: 'Відкріпити',
folder: 'Папка | Папки',
none: 'Нічого',
singleQuote: 'Одинарна лапка',
doubleQuote: 'Подвійна лапка',
deleteConfirm: 'Ви підтверджуєте скасування',
uploadFile: 'Завантажити файл',
format: 'Формат', // Форматування коду
history: 'Історія',
filter: 'Фільтр',
manualValue: 'Власне значення',
selectAll: 'Вибрати все',
pageNumber: 'Номер сторінки',
directoryPath: 'Шлях до каталогу',
actionSuccessful: '{action} успішно виконано',
outputFormat: 'Формат виводу',
singleFile: 'Один файл {ext}',
zipCompressedFile: 'ZIP-стиснутий файл {ext}'
},
connection: { // Підключення до бази даних
connectionName: 'Назва підключення',
hostName: 'Ім"я хоста',
client: 'Клієнт',
port: 'Порт',
user: 'Користувач',
password: 'Пароль',
credentials: 'Облікові дані',
connect: 'Підключити',
connected: 'Підключено',
disconnect: 'Відключити',
disconnected: 'Відключено',
ssl: 'SSL',
enableSsl: 'Увімкнути SSL',
privateKey: 'Приватний ключ',
certificate: 'Сертифікат',
caCertificate: 'CA-сертифікат',
ciphers: 'Шифри',
untrustedConnection: 'Ненадійне підключення',
passphrase: 'Пароль до ключа',
sshTunnel: 'SSH-тунель',
enableSsh: 'Увімкнути SSH',
connectionString: 'Рядок підключення',
addConnection: 'Додати підключення',
createConnection: 'Створити підключення',
createNewConnection: 'Створити нове підключення',
askCredentials: 'Запитати облікові дані',
testConnection: 'Перевірити підключення',
editConnection: 'Редагувати підключення',
deleteConnection: 'Видалити підключення',
connectionSuccessfullyMade: 'Підключення успішно виконано!',
readOnlyMode: 'Режим тільки для читання',
allConnections: 'Усі підключення',
searchForConnections: 'Пошук підключень',
keepAliveInterval: 'Інтервал утримання зв"язку'
},
database: { // Терміни, пов'язані з базою даних
schema: 'Схема',
type: 'Тип',
insert: 'Вставити',
indexes: 'Індекси',
foreignKeys: 'Зовнішні ключі',
length: 'Довжина',
unsigned: 'Беззнаковий',
default: 'За замовчуванням',
comment: 'Коментар',
key: 'Ключ | Ключі',
order: 'Порядок',
expression: 'Вираз',
autoIncrement: 'Авто-інкремент',
engine: 'Двигун',
field: 'Поле | Поля',
approximately: 'Приблизно',
total: 'Загально',
table: 'Таблиця | Таблиці',
view: 'Вид | Види',
definer: 'Визначник',
algorithm: 'Алгоритм',
trigger: 'Тригер | Тригери',
storedRoutine: 'Збережена процедура | Збережені процедури',
scheduler: 'Планувальник | Планувальники',
event: 'Подія',
parameters: 'Параметри',
function: 'Функція | Функції',
deterministic: 'Детермінована',
context: 'Контекст',
export: 'Експорт',
import: 'Імпорт',
returns: 'Повертає',
timing: 'Часування',
state: 'Стан',
execution: 'Виконання',
starts: 'Починається',
ends: 'Закінчується',
variables: 'Змінні',
processes: 'Процеси',
database: 'База даних',
array: 'Масив',
structure: 'Структура',
row: 'Рядок | Рядки',
cell: 'Комірка | Комірки',
triggerFunction: 'Функція тригера | Функції тригера',
routine: 'Процедура | Процедури',
drop: 'Видалити',
commit: 'Закріпити',
rollback: 'Скасувати',
ddl: 'DDL',
collation: 'Колація',
resultsTable: 'Таблиця результатів',
unableEditFieldWithoutPrimary: 'Неможливо редагувати поле без первинного ключа в наборі результатів',
editCell: 'Редагувати комірку',
deleteRows: 'Видалити рядок | Видалити {count} рядків',
confirmToDeleteRows: 'Ви підтверджуєте видалення одного рядка? | Ви підтверджуєте видалення {count} рядків?',
addNewRow: 'Додати новий рядок',
numberOfInserts: 'Кількість вставок',
affectedRows: 'Підпадають під дію рядки',
createNewDatabase: 'Створити нову базу даних',
databaseName: 'Назва бази даних',
serverDefault: 'За замовчуванням на сервері',
deleteDatabase: 'Видалити базу даних',
editDatabase: 'Редагувати базу даних',
clearChanges: 'Скасувати зміни',
addNewField: 'Додати нове поле',
manageIndexes: 'Управління індексами',
manageForeignKeys: 'Управління зовнішніми ключами',
allowNull: 'Допускати NULL',
zeroFill: 'Заповнювати нулями',
customValue: 'Власне значення',
onUpdate: 'При оновленні',
deleteField: 'Видалити поле',
createNewIndex: 'Створити новий індекс',
addToIndex: 'Додати до індексу',
createNewTable: 'Створити нову таблицю',
emptyTable: 'Очистити таблицю',
duplicateTable: 'Дублювати таблицю',
deleteTable: 'Видалити таблицю',
exportTable: 'Експорт таблиці',
emptyConfirm: 'Ви підтверджуєте очищення',
thereAreNoIndexes: 'Немає індексів',
thereAreNoForeign: 'Немає зовнішніх ключів',
createNewForeign: 'Створити новий зовнішній ключ',
referenceTable: 'Таблиця посилання',
referenceField: 'Поле посилання',
foreignFields: 'Зовнішні поля',
invalidDefault: 'Недійсне значення за замовчуванням',
onDelete: 'При видаленні',
selectStatement: 'Оператор SELECT',
triggerStatement: 'Оператор тригера',
sqlSecurity: 'Безпека SQL',
updateOption: 'Опція оновлення',
deleteView: 'Видалити вид',
createNewView: 'Створити новий вид',
deleteTrigger: 'Видалити тригер',
createNewTrigger: 'Створити новий тригер',
currentUser: 'Поточний користувач',
routineBody: 'Тіло процедури',
dataAccess: 'Доступ до даних',
thereAreNoParameters: 'Немає параметрів',
createNewParameter: 'Створити новий параметр',
createNewRoutine: 'Створити нову збережену процедуру',
deleteRoutine: 'Видалити збережену процедуру',
functionBody: 'Тіло функції',
createNewFunction: 'Створити нову функцію',
deleteFunction: 'Видалити функцію',
schedulerBody: 'Тіло планувальника',
createNewScheduler: 'Створити новий планувальник',
deleteScheduler: 'Видалити планувальник',
preserveOnCompletion: 'Зберегти при завершенні',
tableFiller: 'Заповнювач таблиць',
fakeDataLanguage: 'Мова вигаданих даних',
queryDuration: 'Тривалість запиту',
setNull: 'Встановити NULL',
processesList: 'Список процесів',
processInfo: 'Інформація про процес',
manageUsers: 'Управління користувачами',
createNewSchema: 'Створити нову схему',
schemaName: 'Назва схеми',
editSchema: 'Редагувати схему',
deleteSchema: 'Видалити схему',
noSchema: 'Немає схеми',
runQuery: 'Виконати запит',
thereAreNoTableFields: 'Немає полів таблиці',
newTable: 'Нова таблиця',
newView: 'Новий вид',
newTrigger: 'Новий тригер',
newRoutine: 'Нова збережена процедура',
newFunction: 'Нова функція',
newScheduler: 'Новий планувальник',
newTriggerFunction: 'Нова функція тригера',
thereIsNoQueriesYet: 'Поки що немає запитів',
searchForQueries: 'Пошук запитів',
killProcess: 'Завершити процес',
exportSchema: 'Експорт схеми',
importSchema: 'Імпорт схеми',
newInsertStmtEvery: 'Новий оператор INSERT кожні',
processingTableExport: 'Обробка {table}',
fetchingTableExport: 'Отримання даних {table}',
writingTableExport: 'Запис даних {table}',
checkAllTables: 'Позначити всі таблиці',
uncheckAllTables: 'Зняти позначку з усіх таблиць',
killQuery: 'Завершити запит',
insertRow: 'Вставити рядок | Вставити рядки',
commitMode: 'Режим закріплення',
autoCommit: 'Автоматичне закріплення',
manualCommit: 'Ручне закріплення',
importQueryErrors: 'Попередження: сталася помилка: {n} помилка | Попередження: сталася помилка: {n} помилки',
executedQueries: '{n} виконаний запит | {n} виконаних запитів',
disableFKChecks: 'Вимкнути перевірку зовнішніх ключів',
formatQuery: 'Форматування запиту',
queryHistory: 'Історія запитів',
clearQuery: 'Очистити запит',
fillCell: 'Заповнити комірку',
executeSelectedQuery: 'Виконати вибраний запит',
noResultsPresent: 'Відсутні результати',
sqlExportOptions: 'Опції експорту SQL',
targetTable: 'Цільова таблиця',
switchDatabase: 'Перемкнути базу даних',
searchForElements: 'Пошук елементів',
searchForSchemas: 'Пошук схем'
},
application: { // Терміни, пов'язані з додатком
settings: 'Налаштування',
scratchpad: 'Блокнот',
disableScratchpad: 'Вимкнути блокнот',
console: 'Консоль',
general: 'Загальне',
themes: 'Теми',
update: 'Оновлення',
about: 'Про програму',
language: 'Мова',
shortcuts: 'Скорочення',
key: 'Клавіша | Клавіші', // Клавіша клавіатури
event: 'Подія',
light: 'Світлий',
dark: 'Темний',
autoCompletion: 'Автодоповнення',
application: 'Додаток',
editor: 'Редактор',
changelog: 'Журнал змін',
small: 'Маленький',
medium: 'Середній',
large: 'Великий',
appearance: 'Вигляд',
color: 'Колір',
label: 'Мітка',
icon: 'Іконка',
fileName: 'Ім"я файлу',
choseFile: 'Обрати файл',
data: 'Дані',
password: 'Пароль',
required: 'Обов"язково',
madeWithJS: 'Створено з 💛 і JavaScript!',
checkForUpdates: 'Перевірити оновлення',
noUpdatesAvailable: 'Оновлень немає',
checkingForUpdate: 'Перевірка оновлення',
checkFailure: 'Перевірка не вдалася, спробуйте пізніше',
updateAvailable: 'Доступно оновлення',
downloadingUpdate: 'Завантаження оновлення',
updateDownloaded: 'Оновлення завантажено',
restartToInstall: 'Перезапустіть Antares, щоб встановити',
includeBetaUpdates: 'Включити бета-оновлення',
notificationsTimeout: 'Таймаут сповіщень',
openNewTab: 'Відкрити нову вкладку',
unsavedChanges: 'Незбережені зміни',
discardUnsavedChanges: 'У вас є незбережені зміни. Закривши цю вкладку, ці зміни будуть скасовані.',
applicationTheme: 'Тема додатка',
editorTheme: 'Тема редактора',
wrapLongLines: 'Переносити довгі рядки',
markdownSupported: 'Підтримка Markdown',
plantATree: 'Посадити дерево',
dataTabPageSize: 'Розмір сторінки вкладки DATA',
noOpenTabs: 'Немає відкритих вкладок, перейдіть на панель зліва або:',
restorePreviousSession: 'Відновити попередню сесію',
closeTab: 'Закрити вкладку',
goToDownloadPage: 'Перейти на сторінку завантаження',
disableBlur: 'Вимкнути розмиття',
missingOrIncompleteTranslation: 'Відсутній або неповний переклад?',
findOutHowToContribute: 'Дізнайтеся, як внести свій внесок',
reportABug: 'Повідомити про помилку',
nextTab: 'Наступна вкладка',
previousTab: 'Попередня вкладка',
selectTabNumber: 'Вибрати вкладку номер {param}',
toggleConsole: 'Перемкнути консоль',
addShortcut: 'Додати скорочення',
editShortcut: 'Редагувати скорочення',
deleteShortcut: 'Видалити скорочення',
restoreDefaults: 'Відновити значення за замовчуванням',
restoreDefaultsQuestion: 'Ви підтверджуєте відновлення значень за замовчуванням?',
registerAShortcut: 'Зареєструвати скорочення',
invalidShortcutMessage: 'Недійсна комбінація, продовжте введення',
shortcutAlreadyExists: 'Скорочення вже існує',
saveContent: 'Зберегти вміст',
openAllConnections: 'Відкрити всі підключення',
openSettings: 'Відкрити налаштування',
openScratchpad: 'Відкрити блокнот',
runOrReload: 'Запустити або перезавантажити',
openFilter: 'Відкрити фільтр',
nextResultsPage: 'Наступна сторінка результатів',
previousResultsPage: 'Попередня сторінка результатів',
editFolder: 'Редагувати теку',
folderName: 'Назва теки',
deleteFolder: 'Видалити теку',
editConnectionAppearance: 'Редагувати вигляд підключення',
defaultCopyType: 'Тип копіювання за замовчуванням',
showTableSize: 'Показувати розмір таблиці в бічній панелі',
showTableSizeDescription: 'Тільки для MySQL/MariaDB. Увімкнення цієї опції може вплинути на продуктивність в схемах з багатьма таблицями.',
switchSearchMethod: 'Перемкнути метод пошуку',
phpArray: 'Масив PHP',
closeAllTabs: 'Закрити всі вкладки',
closeOtherTabs: 'Закрити інші вкладки',
closeTabsToLeft: 'Закрити вкладки ліворуч',
closeTabsToRight: 'Закрити вкладки праворуч',
csvFieldDelimiter: 'Роздільник полів для CSV',
csvLinesTerminator: 'Роздільник рядків для CSV',
csvStringDelimiter: 'Роздільник рядків для CSV',
csvIncludeHeader: 'Включити заголовок для CSV',
csvExportOptions: 'Опції експорту CSV',
exportData: 'Експорт даних',
exportDataExplanation: 'Експорт збережених підключень до Antares. Вам буде запропоновано ввести пароль для шифрування експортованого файлу.',
importData: 'Імпорт даних',
importDataExplanation: 'Імпорт файлу .antares, який містить підключення. Вам потрібно буде ввести пароль, встановлений під час експорту.',
includeConnectionPasswords: 'Включити паролі підключень',
includeFolders: 'Включити теки',
encryptionPassword: 'Пароль для шифрування',
encryptionPasswordError: 'Пароль для шифрування повинен містити щонайменше 8 символів.',
ignoreDuplicates: 'Ігнорувати дублікати',
wrongImportPassword: 'Неправильний пароль для імпорту',
wrongFileFormat: 'Неправильний формат файлу',
dataImportSuccess: 'Дані успішно імпортовано'
},
faker: { // Методи Faker.js, використовувані в випадково згенерованому вмісті
address: 'Адреса',
commerce: 'Комерція',
company: 'Компанія',
database: 'База даних',
date: 'Дата',
finance: 'Фінанси',
git: 'Git',
hacker: 'Хакер',
internet: 'Інтернет',
lorem: 'Lorem',
name: 'Ім"я',
music: 'Музика',
phone: 'Телефон',
random: 'Випадково',
system: 'Система',
time: 'Час',
vehicle: 'Транспортний засіб',
zipCode: 'Поштовий індекс',
zipCodeByState: 'Поштовий індекс за станом',
city: 'Місто',
cityPrefix: 'Префікс міста',
citySuffix: 'Суфікс міста',
streetName: 'Назва вулиці',
streetAddress: 'Адреса вулиці',
streetSuffix: 'Суфікс вулиці',
streetPrefix: 'Префікс вулиці',
secondaryAddress: 'Додаткова адреса',
county: 'Округ',
country: 'Країна',
countryCode: 'Код країни',
state: 'Штат',
stateAbbr: 'Скорочення назви штату',
latitude: 'Широта',
longitude: 'Довгота',
direction: 'Напрям',
cardinalDirection: 'Кардинальний напрям',
ordinalDirection: 'Ординальний напрям',
nearbyGPSCoordinate: 'Ближча координата GPS',
timeZone: 'Часовий пояс',
color: 'Колір',
department: 'Відділ',
productName: 'Назва продукту',
price: 'Ціна',
productAdjective: 'Прикметник продукту',
productMaterial: 'Матеріал продукту',
product: 'Продукт',
productDescription: 'Опис продукту',
suffixes: 'Суфікси',
companyName: 'Назва компанії',
companySuffix: 'Суфікс компанії',
catchPhrase: 'Захоплива фраза',
bs: 'БС',
catchPhraseAdjective: 'Прикметник захопливої фрази',
catchPhraseDescriptor: 'Опис захопливої фрази',
catchPhraseNoun: 'Іменник захопливої фрази',
bsAdjective: 'Прикметник БС',
bsBuzz: 'БС буз',
bsNoun: 'Іменник БС',
column: 'Стовпець',
type: 'Тип',
collation: 'Спільність',
engine: 'Двигун',
past: 'Минуле',
now: 'Зараз',
future: 'Майбутнє',
between: 'Між',
recent: 'Останнє',
soon: 'Незабаром',
month: 'Місяць',
weekday: 'День тижня',
account: 'Рахунок',
accountName: 'Назва рахунку',
routingNumber: 'Номер маршрутизації',
mask: 'Маска',
amount: 'Сума',
transactionType: 'Тип транзакції',
currencyCode: 'Код валюти',
currencyName: 'Назва валюти',
currencySymbol: 'Символ валюти',
bitcoinAddress: 'Адреса Bitcoin',
litecoinAddress: 'Адреса Litecoin',
creditCardNumber: 'Номер кредитної картки',
creditCardCVV: 'CVV кредитної картки',
ethereumAddress: 'Адреса Ethereum',
iban: 'IBAN',
bic: 'BIC',
transactionDescription: 'Опис транзакції',
branch: 'Відділення',
commitEntry: 'Запис коміту',
commitMessage: 'Повідомлення коміту',
commitSha: 'SHA коміту',
shortSha: 'Короткий SHA',
abbreviation: 'Абревіатура',
adjective: 'Прикметник',
noun: 'Іменник',
verb: 'Дієслово',
ingverb: 'Дієприкметник',
phrase: 'Фраза',
avatar: 'Аватар',
email: 'Електронна пошта',
exampleEmail: 'Приклад електронної пошти',
userName: 'Ім"я користувача',
protocol: 'Протокол',
url: 'URL',
domainName: 'Ім"я домену',
domainSuffix: 'Суфікс домену',
domainWord: 'Слово домену',
ip: 'IP-адреса',
ipv6: 'IPv6',
userAgent: 'User-Agent',
mac: 'MAC-адреса',
password: 'Пароль',
word: 'Слово',
words: 'Слова',
sentence: 'Речення',
slug: 'URL-посилання',
sentences: 'Речення',
paragraph: 'Абзац',
paragraphs: 'Абзаци',
text: 'Текст',
lines: 'Рядки',
genre: 'Жанр',
firstName: 'Ім"я',
lastName: 'Прізвище',
middleName: 'По батькові',
findName: 'Повне ім\'я',
jobTitle: 'Посада',
gender: 'Стать',
prefix: 'Префікс',
suffix: 'Суфікс',
title: 'Заголовок',
jobDescriptor: 'Опис посади',
jobArea: 'Сфера діяльності',
jobType: 'Тип посади',
phoneNumber: 'Номер телефону',
phoneNumberFormat: 'Формат номеру телефону',
phoneFormats: 'Формати номерів телефону',
number: 'Число',
float: 'Дійсне число',
arrayElement: 'Елемент масиву',
arrayElements: 'Елементи масиву',
objectElement: 'Елемент об"єкта',
uuid: 'UUID',
boolean: 'Логічний тип',
image: 'Зображення',
locale: 'Локаль',
alpha: 'Літера',
alphaNumeric: 'Літера або число',
hexaDecimal: 'Шістнадцяткове число',
fileName: 'Назва файлу',
commonFileName: 'Загальна назва файлу',
mimeType: 'MIME-тип',
commonFileType: 'Загальний тип файлу',
commonFileExt: 'Загальний розширення файлу',
fileType: 'Тип файлу',
fileExt: 'Розширення файлу',
directoryPath: 'Шлях до каталогу',
filePath: 'Шлях до файлу',
semver: 'Семантичний номер версії',
manufacturer: 'Виробник',
model: 'Модель',
fuel: 'Паливо',
vin: 'VIN'
}
};

View File

@@ -1,5 +1,5 @@
export const zhCN = { export const zhCN = {
general: { general: { // 通用术语
edit: '编辑', edit: '编辑',
save: '保存', save: '保存',
close: '关闭', close: '关闭',
@@ -13,17 +13,16 @@ export const zhCN = {
donate: '捐赠', donate: '捐赠',
run: '运行', run: '运行',
results: '结果', results: '结果',
size: '尺寸', size: '大小',
mimeType: 'MIME类型', mimeType: 'MIME类型',
download: '下载', download: '下载',
add: '新增', add: '新增',
data: '数据', data: '数据',
properties: '属性', properties: '属性',
insert: '插入',
name: '名称', name: '名称',
clear: '清除', clear: '清除',
seconds: '秒',
options: '选项', options: '选项',
insert: '插入',
discard: '丢弃', discard: '丢弃',
stay: '等待', stay: '等待',
author: '作者', author: '作者',
@@ -33,27 +32,32 @@ export const zhCN = {
cut: '剪切', cut: '剪切',
copy: '复制', copy: '复制',
paste: '粘贴', paste: '粘贴',
tools: '工具',
format: '格式',
all: '全部',
duplicate: '重复', duplicate: '重复',
tools: '工具',
seconds: '秒',
all: '全部',
new: '新', new: '新',
history: '历史',
select: '选择', select: '选择',
filter: '过滤器',
change: '变更', change: '变更',
include: '包含',
includes: '包含', includes: '包含',
completed: '已完成', completed: '已完成',
aborted: '中止', aborted: '中止',
disabled: '禁用', disabled: '禁用',
enable: '启', enable: '启',
disable: '禁用', disable: '禁用',
contributors: '贡献者', contributors: '贡献者',
pin: '固定', pin: '固定',
unpin: '取消固定', unpin: '取消固定',
folder: '文件夹 | 文件夹', folder: '文件夹 | 文件夹',
none: '无',
singleQuote: '单引号',
doubleQuote: '双引号',
deleteConfirm: '您是否确认取消', deleteConfirm: '您是否确认取消',
uploadFile: '上传文件', uploadFile: '上传文件',
format: '格式码', // 格式码
history: '历史',
filter: '过滤器',
manualValue: '手动值', manualValue: '手动值',
selectAll: '选择全部', selectAll: '选择全部',
pageNumber: '页数', pageNumber: '页数',
@@ -63,10 +67,10 @@ export const zhCN = {
singleFile: '单个 {ext} 文件', singleFile: '单个 {ext} 文件',
zipCompressedFile: 'ZIP 压缩 {ext} 文件' zipCompressedFile: 'ZIP 压缩 {ext} 文件'
}, },
connection: { connection: { // 数据库连接
connectionName: '连接名称', connectionName: '连接名称',
client: '数据库类型',
hostName: '主机名', hostName: '主机名',
client: '数据库类型',
port: '端口', port: '端口',
user: '用户', user: '用户',
password: '密码', password: '密码',
@@ -76,12 +80,15 @@ export const zhCN = {
disconnect: '断开连接', disconnect: '断开连接',
disconnected: '断开连接', disconnected: '断开连接',
ssl: 'SSL', ssl: 'SSL',
enableSsl: '启用 SSL',
privateKey: '私钥', privateKey: '私钥',
certificate: '证书', certificate: '证书',
caCertificate: 'CA 证书', caCertificate: 'CA 证书',
ciphers: '密码', ciphers: '密码',
sshTunnel: 'SSH 隧道', untrustedConnection: '不受信任的连接',
passphrase: '密码短语', passphrase: '密码短语',
sshTunnel: 'SSH 隧道',
enableSsh: '启用 SSH',
connectionString: '连接字符串', connectionString: '连接字符串',
addConnection: '添加连接', addConnection: '添加连接',
createConnection: '创建连接', createConnection: '创建连接',
@@ -91,23 +98,22 @@ export const zhCN = {
editConnection: '编辑连接', editConnection: '编辑连接',
deleteConnection: '删除连接', deleteConnection: '删除连接',
connectionSuccessfullyMade: '连接成功了!', connectionSuccessfullyMade: '连接成功了!',
enableSsl: '启用 SSL',
enableSsh: '启用 SSH',
readOnlyMode: '只读模式', readOnlyMode: '只读模式',
untrustedConnection: '不受信任的连接',
allConnections: '所有连接', allConnections: '所有连接',
searchForConnections: '搜索连接' searchForConnections: '搜索连接',
keepAliveInterval: '保持活跃间隔'
}, },
database: { database: { // 数据库相关术语
schema: '模式(schema)', schema: '模式(schema)',
type: '类型', type: '类型',
insert: '插入',
indexes: '索引',
foreignKeys: '外键', foreignKeys: '外键',
length: '长度', length: '长度',
unsigned: '无符号', unsigned: '无符号',
default: '默认', default: '默认',
comment: '注释', comment: '注释',
collation: '排序规则', key: '键 | 键',
key: '键位 | 键位',
order: '排序', order: '排序',
expression: '表达式', expression: '表达式',
autoIncrement: '自动增量', autoIncrement: '自动增量',
@@ -115,9 +121,8 @@ export const zhCN = {
field: '字段 | 字段', field: '字段 | 字段',
approximately: '大约', approximately: '大约',
total: '总计', total: '总计',
table: '表', table: '表 | 表',
view: '视图', view: '视图 | 视图',
indexes: '索引',
definer: '定义者', definer: '定义者',
algorithm: '算法', algorithm: '算法',
trigger: '触发器 | 触发器', trigger: '触发器 | 触发器',
@@ -139,16 +144,18 @@ export const zhCN = {
variables: '变量', variables: '变量',
processes: '进程', processes: '进程',
database: '数据库', database: '数据库',
array: '数', array: '数',
structure: '结构', structure: '结构',
row: '行 | 行', row: '行 | 行',
cell: '单元格 | 单元格', cell: '单元格 | 单元格',
triggerFunction: '触发函数 | 触发函数', triggerFunction: '触发函数 | 触发函数',
routine: '例程', routine: '例程 | 例程',
drop: '丢弃',
commit: '提交', commit: '提交',
rollback: '回滚', rollback: '回滚',
ddl: '数据定义语言',
collation: '排序规则',
resultsTable: '结果表', resultsTable: '结果表',
drop: '下降',
unableEditFieldWithoutPrimary: '无法编辑结果集中一个没有主键的字段', unableEditFieldWithoutPrimary: '无法编辑结果集中一个没有主键的字段',
editCell: '编辑单元格', editCell: '编辑单元格',
deleteRows: '删除行 | 删除 {count} 行', deleteRows: '删除行 | 删除 {count} 行',
@@ -161,7 +168,7 @@ export const zhCN = {
serverDefault: '默认服务器', serverDefault: '默认服务器',
deleteDatabase: '删除数据库', deleteDatabase: '删除数据库',
editDatabase: '编辑数据库', editDatabase: '编辑数据库',
clearChanges: '清除更', clearChanges: '清除更',
addNewField: '添加新字段', addNewField: '添加新字段',
manageIndexes: '管理索引', manageIndexes: '管理索引',
manageForeignKeys: '管理外键', manageForeignKeys: '管理外键',
@@ -174,7 +181,9 @@ export const zhCN = {
addToIndex: '添加到索引', addToIndex: '添加到索引',
createNewTable: '创建新表', createNewTable: '创建新表',
emptyTable: '清空表', emptyTable: '清空表',
duplicateTable: '重复表',
deleteTable: '删除表', deleteTable: '删除表',
exportTable: '导出表',
emptyConfirm: '您是否确认清空', emptyConfirm: '您是否确认清空',
thereAreNoIndexes: '没有索引', thereAreNoIndexes: '没有索引',
thereAreNoForeign: '没有外键', thereAreNoForeign: '没有外键',
@@ -182,7 +191,7 @@ export const zhCN = {
referenceTable: '参考表', referenceTable: '参考表',
referenceField: '参考字段', referenceField: '参考字段',
foreignFields: '外键字段', foreignFields: '外键字段',
invalidDefault: '无效默认值', invalidDefault: '无效默认值',
onDelete: '在删除', onDelete: '在删除',
selectStatement: '选择语句', selectStatement: '选择语句',
triggerStatement: '触发器语句', triggerStatement: '触发器语句',
@@ -205,10 +214,10 @@ export const zhCN = {
schedulerBody: '调度器主体', schedulerBody: '调度器主体',
createNewScheduler: '创建新调度器', createNewScheduler: '创建新调度器',
deleteScheduler: '删除调度器', deleteScheduler: '删除调度器',
preserveOnCompletion: '完成时保', preserveOnCompletion: '完成时保',
tableFiller: '表填充器', tableFiller: '表填充器',
fakeDataLanguage: '伪造的数据语言', fakeDataLanguage: '伪造的数据语言',
queryDuration: '查询时间', queryDuration: '查询持续时间',
setNull: '设置 NULL', setNull: '设置 NULL',
processesList: '进程列表', processesList: '进程列表',
processInfo: '进程信息', processInfo: '进程信息',
@@ -217,7 +226,6 @@ export const zhCN = {
schemaName: '模式名称', schemaName: '模式名称',
editSchema: '编辑模式', editSchema: '编辑模式',
deleteSchema: '删除模式', deleteSchema: '删除模式',
duplicateTable: '重复的表',
noSchema: '没有模式', noSchema: '没有模式',
runQuery: '运行查询', runQuery: '运行查询',
thereAreNoTableFields: '没有表的字段', thereAreNoTableFields: '没有表的字段',
@@ -227,7 +235,7 @@ export const zhCN = {
newRoutine: '新例程', newRoutine: '新例程',
newFunction: '新函数', newFunction: '新函数',
newScheduler: '新调度器', newScheduler: '新调度器',
newTriggerFunction: '新触发函数', newTriggerFunction: '新触发函数',
thereIsNoQueriesYet: '目前还没有任何查询', thereIsNoQueriesYet: '目前还没有任何查询',
searchForQueries: '搜索查询', searchForQueries: '搜索查询',
killProcess: '终止进程', killProcess: '终止进程',
@@ -237,45 +245,59 @@ export const zhCN = {
processingTableExport: '处理 {table}', processingTableExport: '处理 {table}',
fetchingTableExport: '正在获取 {table} 数据', fetchingTableExport: '正在获取 {table} 数据',
writingTableExport: '正在写入 {table} 数据', writingTableExport: '正在写入 {table} 数据',
checkAllTables: '勾选所有表', checkAllTables: '检查所有表',
uncheckAllTables: '不勾选所有表', uncheckAllTables: '不检查所有表',
killQuery: '取消查询', killQuery: '终止查询',
insertRow: '插入行 | 插入多行', insertRow: '插入行 | 插入多行',
commitMode: '提交模式', commitMode: '提交模式',
autoCommit: '自动提交', autoCommit: '自动提交',
manualCommit: '手动提交', manualCommit: '手动提交',
importQueryErrors: '警告: 发生了 {n} 个错误 | 警告: 发生了 {n} 个错误',
executedQueries: '{n} 个查询已执行 | {n} 个查询已执行',
disableFKChecks: '禁用外键检查', disableFKChecks: '禁用外键检查',
formatQuery: '格式查询', formatQuery: '格式查询',
queryHistory: '查询历史', queryHistory: '查询历史',
clearQuery: '清除查询', clearQuery: '清除查询',
fillCell: '填充单元格', fillCell: '填充单元格',
executeSelectedQuery: '执行所选查询', executeSelectedQuery: '执行所选查询',
importQueryErrors: '警告: 发生了 {n} 个错误 | 警告: 发生了 {n} 个错误', noResultsPresent: '没有结果',
executedQueries: '{n} 个查询已执行 | {n} 个查询已执行' sqlExportOptions: 'SQL 导出选项',
targetTable: '目标表',
switchDatabase: '切换数据库',
searchForElements: '搜索元素',
searchForSchemas: '搜索模式(schema)'
}, },
application: { application: { // 应用程序相关术语
settings: '设置', settings: '设置',
scratchpad: '草稿栏',
disableScratchpad: '禁用草稿栏',
console: '控制台',
general: '常规', general: '常规',
themes: '主题', themes: '主题',
update: '更新', update: '更新',
about: '关于', about: '关于',
language: '语言', language: '语言',
shortcuts: '快捷方式',
key: '按键 | 按键', // 键盘按键
event: '事件',
light: '明亮', light: '明亮',
dark: '暗黑', dark: '暗黑',
autoCompletion: '自动完成', autoCompletion: '自动完成',
application: '应用程序', application: '应用程序',
editor: '编辑器', editor: '编辑器',
scratchpad: '草稿栏',
changelog: '变更日志', changelog: '变更日志',
small: '小', small: '小',
medium: '中', medium: '中',
large: '大', large: '大',
console: '控制台',
shortcuts: '快捷键',
appearance: '外观', appearance: '外观',
color: '颜色', color: '颜色',
label: '标签', label: '标签',
icon: '图标', icon: '图标',
fileName: '文件名称',
choseFile: '选择文件',
data: '数据',
password: '密码',
required: '依赖',
madeWithJS: '使用 💛 和 JavaScript 制作!', madeWithJS: '使用 💛 和 JavaScript 制作!',
checkForUpdates: '检查更新', checkForUpdates: '检查更新',
noUpdatesAvailable: '无可用更新', noUpdatesAvailable: '无可用更新',
@@ -285,14 +307,14 @@ export const zhCN = {
downloadingUpdate: '正在下载更新', downloadingUpdate: '正在下载更新',
updateDownloaded: '已下载更新', updateDownloaded: '已下载更新',
restartToInstall: '重启 Antares 以进行安装', restartToInstall: '重启 Antares 以进行安装',
includeBetaUpdates: '包含测试版更新',
notificationsTimeout: '通知超时', notificationsTimeout: '通知超时',
openNewTab: '打开一个新标签', openNewTab: '打开一个新标签',
unsavedChanges: '未保存的更', unsavedChanges: '未保存的更',
discardUnsavedChanges: '您有一些未保存的更, 关闭此标签将放弃这些更.', discardUnsavedChanges: '您有一些未保存的更, 关闭此标签将放弃这些更.',
applicationTheme: '应用程序主题', applicationTheme: '应用程序主题',
editorTheme: '编辑器主题', editorTheme: '编辑器主题',
wrapLongLines: '将长行换行显示', wrapLongLines: '将长行换行显示',
includeBetaUpdates: '包含测试版的更新',
markdownSupported: '支持 Markdown', markdownSupported: '支持 Markdown',
plantATree: '种植一棵树', plantATree: '种植一棵树',
dataTabPageSize: '数据标签的页面大小', dataTabPageSize: '数据标签的页面大小',
@@ -303,22 +325,21 @@ export const zhCN = {
disableBlur: '禁用模糊', disableBlur: '禁用模糊',
missingOrIncompleteTranslation: '有缺失或不完整的翻译?', missingOrIncompleteTranslation: '有缺失或不完整的翻译?',
findOutHowToContribute: '了解如何做出贡献', findOutHowToContribute: '了解如何做出贡献',
disableScratchpad: '禁用草稿栏',
reportABug: '报告错误', reportABug: '报告错误',
nextTab: '下一个标签', nextTab: '下一个标签',
previousTab: '上一个标签', previousTab: '上一个标签',
selectTabNumber: '选择标签编号 {param}', selectTabNumber: '选择标签编号 {param}',
toggleConsole: '切换控制台', toggleConsole: '切换控制台',
addShortcut: '添加快捷', addShortcut: '添加快捷方式',
editShortcut: '编辑快捷', editShortcut: '编辑快捷方式',
deleteShortcut: '删除快捷', deleteShortcut: '删除快捷方式',
restoreDefaults: '恢复默认', restoreDefaults: '恢复默认',
restoreDefaultsQuestion: '是否确认恢复默认值?', restoreDefaultsQuestion: '是否确认恢复默认值?',
registerAShortcut: '注册快捷', registerAShortcut: '注册快捷方式',
invalidShortcutMessage: '无效组合,请继续入', invalidShortcutMessage: '无效组合,请继续入',
shortcutAlreadyExists: '快捷键已经存在', shortcutAlreadyExists: '快捷方式已存在',
saveContent: '保存内容', saveContent: '保存内容',
openAllConnections: '打开全部连接', openAllConnections: '打开所有连接',
openSettings: '打开设置', openSettings: '打开设置',
openScratchpad: '打开草稿栏', openScratchpad: '打开草稿栏',
runOrReload: '运行或重新加载', runOrReload: '运行或重新加载',
@@ -332,9 +353,31 @@ export const zhCN = {
defaultCopyType: '默认复制类型', defaultCopyType: '默认复制类型',
showTableSize: '在侧边栏显示表大小', showTableSize: '在侧边栏显示表大小',
showTableSizeDescription: '仅限 MySQL/MariaDB. 启用此选项可能会影响许多表的模式(schema)的性能.', showTableSizeDescription: '仅限 MySQL/MariaDB. 启用此选项可能会影响许多表的模式(schema)的性能.',
searchForElements: '搜索元素' switchSearchMethod: '切换搜索方法',
phpArray: 'PHP 数组',
closeAllTabs: '关闭所有标签',
closeOtherTabs: '关闭其他标签',
closeTabsToLeft: '关闭左侧的标签',
closeTabsToRight: '关闭右侧的标签',
csvFieldDelimiter: '字段分隔符',
csvLinesTerminator: '行终止符',
csvStringDelimiter: '字符串分隔符',
csvIncludeHeader: '包含页眉',
csvExportOptions: 'CSV 导出选项',
exportData: '导出数据',
exportDataExplanation: '将保存的连接导出到 Antares. 系统将要求您输入密码以加密导出的文件.',
importData: '导入数据',
importDataExplanation: '导入包含连接的 .antares 文件. 您需要输入在导出过程中定义的密码.',
includeConnectionPasswords: '包含连接密码',
includeFolders: '包含文件夹',
encryptionPassword: '加密密码',
encryptionPasswordError: '加密密码的长度必须至少为 8 个字符.',
ignoreDuplicates: '忽略重复',
wrongImportPassword: '错误的导入密码',
wrongFileFormat: '错误的文件格式',
dataImportSuccess: '数据已成功导入'
}, },
faker: { faker: { // Faker.js 方法,用于随机生成的内容
address: '地址', address: '地址',
commerce: '商业', commerce: '商业',
company: '公司', company: '公司',

View File

@@ -0,0 +1,7 @@
/**
* Copy a string on clipboard
* @param text
*/
export const copyText = (text: string) => {
navigator.clipboard.writeText(text);
};

View File

@@ -1,11 +1,12 @@
import { ConnectionParams } from 'common/interfaces/antares'; import { ConnectionParams } from 'common/interfaces/antares';
import { uidGen } from 'common/libs/uidGen'; import { uidGen } from 'common/libs/uidGen';
import * as crypto from 'crypto'; import * as crypto from 'crypto';
import { ipcRenderer } from 'electron';
import * as Store from 'electron-store'; import * as Store from 'electron-store';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
const key = localStorage.getItem('key'); let key = localStorage.getItem('key');
export interface SidebarElement { export interface SidebarElement {
isFolder: boolean; isFolder: boolean;
@@ -17,10 +18,21 @@ export interface SidebarElement {
icon?: null | string; icon?: null | string;
} }
if (!key) if (!key) { // If no key in local storace
localStorage.setItem('key', crypto.randomBytes(16).toString('hex')); const storedKey = ipcRenderer.sendSync('get-key');// Ask for key stored on disk
if (!storedKey) { // Of nop stored key on disk
const newKey = crypto.randomBytes(16).toString('hex');
localStorage.setItem('key', newKey);
key = newKey;
}
else {
localStorage.setItem('key', storedKey);
key = storedKey;
}
}
else else
localStorage.setItem('key', key); ipcRenderer.send('set-key', key);
const persistentStore = new Store({ const persistentStore = new Store({
name: 'connections', name: 'connections',

View File

@@ -2,9 +2,18 @@ import * as Store from 'electron-store';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
const persistentStore = new Store({ name: 'notes' }); const persistentStore = new Store({ name: 'notes' });
export interface ConnectionNote {
uid: string;
note: string;
date: Date;
}
export const useScratchpadStore = defineStore('scratchpad', { export const useScratchpadStore = defineStore('scratchpad', {
state: () => ({ state: () => ({
notes: persistentStore.get('notes', '# HOW TO SUPPORT ANTARES\n\n- [ ] Leave a star to Antares [GitHub repo](https://github.com/antares-sql/antares)\n- [ ] Send feedbacks and advices\n- [ ] Report for bugs\n- [ ] If you enjoy, share Antares with friends\n\n# ABOUT SCRATCHPAD\n\nThis is a scratchpad where you can save your **personal notes**. It supports `markdown` format, but you are free to use plain text.\nThis content is just a placeholder, feel free to clear it to make space for your notes.\n') as string /** Global notes */
notes: persistentStore.get('notes', '# HOW TO SUPPORT ANTARES\n\n- [ ] Leave a star to Antares [GitHub repo](https://github.com/antares-sql/antares)\n- [ ] Send feedbacks and advices\n- [ ] Report for bugs\n- [ ] If you enjoy, share Antares with friends\n\n# ABOUT SCRATCHPAD\n\nThis is a scratchpad where you can save your **personal notes**. It supports `markdown` format, but you are free to use plain text.\nThis content is just a placeholder, feel free to clear it to make space for your notes.\n') as string,
/** Connection specific notes */
connectionNotes: persistentStore.get('connectionNotes', {}) as {[k: string]: ConnectionNote}
}), }),
actions: { actions: {
changeNotes (notes: string) { changeNotes (notes: string) {

View File

@@ -4,109 +4,109 @@ declare module '@/App.vue';
declare module 'v-mask'; declare module 'v-mask';
declare module 'json2php'; declare module 'json2php';
declare module 'vuedraggable' {// <- to export as default declare module 'vuedraggable' {// <- to export as default
const draggableComponent: import('vue').DefineComponent<{ const draggableComponent: import('vue').DefineComponent<{
list: { list: {
type: ArrayConstructor; type: ArrayConstructor;
required: boolean; required: boolean;
default: any; default: any;
}; };
modelValue: { modelValue: {
type: ArrayConstructor; type: ArrayConstructor;
required: boolean; required: boolean;
default: any; default: any;
}; };
itemKey: { itemKey: {
type: (FunctionConstructor | StringConstructor)[]; type: (FunctionConstructor | StringConstructor)[];
required: boolean; required: boolean;
}; };
clone: { clone: {
type: FunctionConstructor; type: FunctionConstructor;
default: (original: any) => any; default: (original: any) => any;
}; };
tag: { tag: {
type: StringConstructor; type: StringConstructor;
default: string; default: string;
}; };
move: { move: {
type: FunctionConstructor; type: FunctionConstructor;
default: any; default: any;
}; };
componentData: { componentData: {
type: ObjectConstructor; type: ObjectConstructor;
required: boolean; required: boolean;
default: any; default: any;
}; };
}, unknown, { }, unknown, {
error: boolean; error: boolean;
}, { }, {
realList(): any; realList(): any;
getKey(): any; getKey(): any;
}, { }, {
getUnderlyingVm(domElement: any): any; getUnderlyingVm(domElement: any): any;
getUnderlyingPotencialDraggableComponent(htmElement: any): any; getUnderlyingPotencialDraggableComponent(htmElement: any): any;
emitChanges(evt: any): void; emitChanges(evt: any): void;
alterList(onList: any): void; alterList(onList: any): void;
spliceList(): void; spliceList(): void;
updatePosition(oldIndex: any, newIndex: any): void; updatePosition(oldIndex: any, newIndex: any): void;
getRelatedContextFromMoveEvent({ to, related }: { getRelatedContextFromMoveEvent({ to, related }: {
to: any; to: any;
related: any; related: any;
}): any; }): any;
getVmIndexFromDomIndex(domIndex: any): any; getVmIndexFromDomIndex(domIndex: any): any;
onDragStart(evt: any): void; onDragStart(evt: any): void;
onDragAdd(evt: any): void; onDragAdd(evt: any): void;
onDragRemove(evt: any): void; onDragRemove(evt: any): void;
onDragUpdate(evt: any): void; onDragUpdate(evt: any): void;
computeFutureIndex(relatedContext: any, evt: any): any; computeFutureIndex(relatedContext: any, evt: any): any;
onDragMove(evt: any, originalEvent: any): any; onDragMove(evt: any, originalEvent: any): any;
onDragEnd(): void; onDragEnd(): void;
}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, any[], any, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly<{ }, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, any[], any, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly<{
move: Function; move: Function;
tag: string; tag: string;
clone: Function; clone: Function;
list: unknown[]; list: unknown[];
modelValue: unknown[]; modelValue: unknown[];
componentData: Record<string, any>; componentData: Record<string, any>;
} & { } & {
itemKey?: string | Function; itemKey?: string | Function;
}>, { }>, {
move: Function; move: Function;
tag: string; tag: string;
clone: Function; clone: Function;
list: unknown[]; list: unknown[];
modelValue: unknown[]; modelValue: unknown[];
componentData: Record<string, any>; componentData: Record<string, any>;
}>; }>;
export = draggableComponent; export = draggableComponent;
} }
declare const SvgIcon: import('vue').DefineComponent<{ declare const SvgIcon: import('vue').DefineComponent<{
type: { type: {
type: StringConstructor; type: StringConstructor;
default: string; default: string;
}; };
path: { path: {
type: StringConstructor; type: StringConstructor;
default: string; default: string;
}; };
size: { size: {
type: NumberConstructor; type: NumberConstructor;
optional: boolean; optional: boolean;
}; };
viewbox: { viewbox: {
type: StringConstructor; type: StringConstructor;
optional: boolean; optional: boolean;
}; };
flip: { flip: {
type: StringConstructor; type: StringConstructor;
optional: boolean; optional: boolean;
}; };
rotate: { rotate: {
type: NumberConstructor; type: NumberConstructor;
optional: boolean; optional: boolean;
}; };
}>; }>;
declare module '@jamescoyle/vue-icon' { declare module '@jamescoyle/vue-icon' {
export default SvgIcon; export default SvgIcon;
} }

View File

@@ -19,7 +19,15 @@ module.exports = { // Main
output: { output: {
libraryTarget: 'commonjs2', libraryTarget: 'commonjs2',
path: path.join(__dirname, 'dist'), path: path.join(__dirname, 'dist'),
filename: '[name].js' filename: '[name].js',
assetModuleFilename: (pathData) => {
const { filename } = pathData;
if (filename.endsWith('.ts'))
return '[name].js';
else
return '[name][ext]';
}
}, },
node: { node: {
global: true, global: true,
@@ -43,7 +51,8 @@ module.exports = { // Main
new ProgressPlugin(true), new ProgressPlugin(true),
new webpack.DefinePlugin({ new webpack.DefinePlugin({
'process.env': { 'process.env': {
PACKAGE_VERSION: `"${version}"` PACKAGE_VERSION: `"${version}"`,
DISTRIBUTION: `"${process.env.DISTRIBUTION || 'none'}"`
} }
}) })
], ],

View File

@@ -62,7 +62,8 @@ const config = {
new ProgressPlugin(true), new ProgressPlugin(true),
new webpack.DefinePlugin({ new webpack.DefinePlugin({
'process.env': { 'process.env': {
PACKAGE_VERSION: `"${version}"` PACKAGE_VERSION: `"${version}"`,
DISTRIBUTION: `"${process.env.DISTRIBUTION || 'none'}"`
} }
}) })
] ]