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

Compare commits

..

1 Commits

Author SHA1 Message Date
d743d486b8 chore(release): 0.5.5 2022-05-24 14:21:56 +02:00
321 changed files with 18164 additions and 66403 deletions

View File

@@ -174,200 +174,8 @@
"contributions": [
"translation"
]
},
{
"login": "brdtheo",
"name": "Théo Billardey",
"avatar_url": "https://avatars.githubusercontent.com/u/48206778?v=4",
"profile": "https://codepen.io/theo-billardey",
"contributions": [
"translation"
]
},
{
"login": "dyaskur",
"name": "Muhammad Dyas Yaskur",
"avatar_url": "https://avatars.githubusercontent.com/u/9539970?v=4",
"profile": "http://yaskur.net",
"contributions": [
"translation",
"code"
]
},
{
"login": "jimcat8",
"name": "tianci li",
"avatar_url": "https://avatars.githubusercontent.com/u/86754294?v=4",
"profile": "https://github.com/jimcat8",
"contributions": [
"translation"
]
},
{
"login": "555cider",
"name": "555cider",
"avatar_url": "https://avatars.githubusercontent.com/u/73565447?v=4",
"profile": "https://github.com/555cider",
"contributions": [
"translation"
]
},
{
"login": "m1khal3v",
"name": "Anton Mikhalev",
"avatar_url": "https://avatars.githubusercontent.com/u/41085561?v=4",
"profile": "https://github.com/m1khal3v",
"contributions": [
"translation"
]
},
{
"login": "64knl",
"name": "René",
"avatar_url": "https://avatars.githubusercontent.com/u/3864423?v=4",
"profile": "https://64k.nl/",
"contributions": [
"code",
"translation"
]
},
{
"login": "zxp19821005",
"name": "Woodenman",
"avatar_url": "https://avatars.githubusercontent.com/u/4915850?v=4",
"profile": "https://github.com/zxp19821005",
"contributions": [
"platform"
]
},
{
"login": "markusand",
"name": "Marc Vilella",
"avatar_url": "https://avatars.githubusercontent.com/u/12972543?v=4",
"profile": "https://github.com/markusand",
"contributions": [
"translation"
]
},
{
"login": "Lawondyss",
"name": "Ladislav Vondráček",
"avatar_url": "https://avatars.githubusercontent.com/u/272130?v=4",
"profile": "https://github.com/Lawondyss",
"contributions": [
"translation"
]
},
{
"login": "zvlad",
"name": "Vladyslav",
"avatar_url": "https://avatars.githubusercontent.com/u/9055134?v=4",
"profile": "https://github.com/zvlad",
"contributions": [
"translation"
]
},
{
"login": "bagusindrayana",
"name": "Bagus Indrayana",
"avatar_url": "https://avatars.githubusercontent.com/u/36830534?v=4",
"profile": "https://github.com/bagusindrayana",
"contributions": [
"code"
]
},
{
"login": "penguinlab",
"name": "Naoki Ishikawa",
"avatar_url": "https://avatars.githubusercontent.com/u/10959317?v=4",
"profile": "https://github.com/penguinlab",
"contributions": [
"translation"
]
},
{
"login": "mangas",
"name": "Filipe Azevedo",
"avatar_url": "https://avatars.githubusercontent.com/u/1640325?v=4",
"profile": "https://fazevedo.dev",
"contributions": [
"code"
]
},
{
"login": "zwei-c",
"name": "CHANG, CHIH WEI",
"avatar_url": "https://avatars.githubusercontent.com/u/55912811?v=4",
"profile": "https://github.com/zwei-c",
"contributions": [
"translation"
]
},
{
"login": "mirrorb",
"name": "GaoChun",
"avatar_url": "https://avatars.githubusercontent.com/u/34116207?v=4",
"profile": "https://github.com/mirrorb",
"contributions": [
"code"
]
},
{
"login": "LeviEyal",
"name": "Eyal Levi",
"avatar_url": "https://avatars.githubusercontent.com/u/48846533?v=4",
"profile": "https://github.com/LeviEyal",
"contributions": [
"translation"
]
},
{
"login": "SawGoD",
"name": "Nikita Karelikov",
"avatar_url": "https://avatars.githubusercontent.com/u/67802757?v=4",
"profile": "http://telegram.dog/SawGoD",
"contributions": [
"translation"
]
},
{
"login": "carvalhods",
"name": "David Carvalho",
"avatar_url": "https://avatars.githubusercontent.com/u/6569255?v=4",
"profile": "https://github.com/carvalhods",
"contributions": [
"platform"
]
},
{
"login": "r4f4dev",
"name": "r4f4dev",
"avatar_url": "https://avatars.githubusercontent.com/u/65920592?v=4",
"profile": "https://github.com/r4f4dev",
"contributions": [
"translation"
]
},
{
"login": "salvymc",
"name": "Salvatore Forino",
"avatar_url": "https://avatars.githubusercontent.com/u/10051897?v=4",
"profile": "https://github.com/salvymc",
"contributions": [
"code"
]
},
{
"login": "JoseGonzalez84",
"name": "José González",
"avatar_url": "https://avatars.githubusercontent.com/u/16820141?v=4",
"profile": "https://gadev.com.es/",
"contributions": [
"translation"
]
}
],
"contributorsPerLine": 7,
"skipCi": true,
"commitType": "docs"
"skipCi": true
}

View File

@@ -1,6 +1,4 @@
node_modules
assets
out
dist
build
misc
dist

View File

@@ -18,8 +18,7 @@
},
"plugins": [
"vue",
"@typescript-eslint",
"simple-import-sort"
"@typescript-eslint"
],
"rules": {
"space-infix-ops": "off",
@@ -92,8 +91,6 @@
}
}
],
"@typescript-eslint/no-var-requires": "off",
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error"
"@typescript-eslint/no-var-requires": "off"
}
}

4
.github/FUNDING.yml vendored
View File

@@ -1,6 +1,6 @@
# These are supported funding model platforms
github: [antares-sql,fabio286]
github: [fabio286]
patreon: #fabio286
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
@@ -9,4 +9,4 @@ community_bridge: # Replace with a single Community Bridge project-name e.g., cl
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: ['https://paypal.me/fabiodistasio']
custom: ['https://paypal.me/fabiodistasio']

View File

@@ -6,9 +6,6 @@
version: 2
updates:
- package-ecosystem: "npm"
allow:
- dependency-type: "production"
directory: "/"
schedule:
interval: "monthly"
target-branch: "develop"
interval: "weekly"

View File

@@ -1,45 +0,0 @@
name: Build & release [BETA]
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+'
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@v4
with:
ref: beta
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: |
npm i
npm install "dmg-license" --save-optional
- name: "Build"
run: npm run build
- name: Release
uses: ncipollo/release-action@v1
with:
artifacts: "build/*.AppImage,build/*.yml,build/*.deb,build/*.dmg,build/*.blockmap,build/*.zip,build/*.exe"
allowUpdates: true
draft: true
generateReleaseNotes: true

29
.github/workflows/build-linux.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: Build/release [linux]
on: push
jobs:
release:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
steps:
- name: Check out Git repository
uses: actions/checkout@v2
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v1
with:
node-version: 14
- name: Install dependencies
run: npm i
- name: Build/release Electron app
uses: samuelmeuli/action-electron-builder@v1
with:
github_token: ${{ secrets.github_token }}
release: ${{ startsWith(github.ref, 'refs/tags/v') }}

29
.github/workflows/build-mac.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: Build/release [mac]
on: push
jobs:
release:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest]
steps:
- name: Check out Git repository
uses: actions/checkout@v2
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v1
with:
node-version: 14
- name: Install dependencies
run: npm i
- name: Build/release Electron app
uses: samuelmeuli/action-electron-builder@v1
with:
github_token: ${{ secrets.github_token }}
release: ${{ startsWith(github.ref, 'refs/tags/v') }}

29
.github/workflows/build-win.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: Build/release [windows]
on: push
jobs:
release:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-2019]
steps:
- name: Check out Git repository
uses: actions/checkout@v2
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v1
with:
node-version: 14
- name: Install dependencies
run: npm i
- name: Build/release Electron app
uses: samuelmeuli/action-electron-builder@v1
with:
github_token: ${{ secrets.github_token }}
release: ${{ startsWith(github.ref, 'refs/tags/v') }}

View File

@@ -1,51 +0,0 @@
name: Build & release [STABLE]
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
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: Exit if not on master branch
if: contains(env.BRANCH_NAME, 'master') == false
run: |
echo "Wrong environment ${{env.BRANCH_NAME}}"
exit 0
- name: Check out Git repository
uses: actions/checkout@v4
with:
ref: master
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: |
npm i
npm install "dmg-license" --save-optional
- name: "Build"
run: npm run build
- name: Release
uses: ncipollo/release-action@v1
with:
artifacts: "build/*.AppImage,build/*.yml,build/*.deb,build/*.dmg,build/*.blockmap,build/*.zip,build/*.exe"
allowUpdates: true
draft: true
generateReleaseNotes: true

View File

@@ -25,7 +25,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.

View File

@@ -1,34 +0,0 @@
name: Create artifact [LINUX ARM64]
on:
workflow_dispatch: {}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
uses: actions/checkout@v4
with:
ref: master
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm i
- name: "Build"
run: npm run build -- --arm64 --linux deb AppImage
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: linux-build
retention-days: 3
path: |
build
!build/*-unpacked
!build/.icon-ico

View File

@@ -1,32 +0,0 @@
name: Create artifact [LINUX]
on:
workflow_dispatch: {}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm i
- name: "Build"
run: npm run build
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: linux-build
retention-days: 3
path: |
build
!build/*-unpacked
!build/.icon-ico

View File

@@ -1,60 +0,0 @@
name: Create artifact [MAC]
on:
workflow_dispatch: {}
jobs:
build:
runs-on: macos-latest
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: npm install & build
run: |
npm install
npm install "dmg-license" --save-optional
npm run build
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: macos-build
retention-days: 3
path: |
build
!build/*-unpacked
!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@v4
with:
node-version: 20
- name: npm install & build
run: |
npm install
npm install "dmg-license" --save-optional
npm run build
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: macos-build-beta
retention-days: 3
path: |
build
!build/*-unpacked
!build/.icon-ico

View File

@@ -1,32 +0,0 @@
name: Create artifact [WINDOWS APPX]
on:
workflow_dispatch: {}
jobs:
build:
runs-on: windows-2022
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm i
- name: "Build"
run: npm run build:appx
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: windows-build
retention-days: 3
path: |
build
!build/*-unpacked
!build/.icon-ico

View File

@@ -1,50 +0,0 @@
name: Create generated-rources.json
on:
workflow_dispatch: {}
jobs:
build:
runs-on: ubuntu-latest
steps:
# Install flatpak-node-generator
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install pipx
uses: CfirTsabari/actions-pipx@v1
- name: Install flatpak-node-generator
run: |
cd ../
git clone https://github.com/flatpak/flatpak-builder-tools.git
cd flatpak-builder-tools/node
pipx install .
# Install Antares
- name: Check out Git repository
uses: actions/checkout@v3
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 20
# - name: Delete old package-lock.json
# run: rm package-lock.json
- name: Install dependencies
run: npm i --lockfile-version 2
- name: Generate generated-sources.json
run: flatpak-node-generator npm -r package-lock.json --electron-node-headers
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: generated-sources
retention-days: 3
path: |
generated-sources.json

View File

@@ -1,33 +0,0 @@
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@v4
with:
ref: develop
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm i
- name: "Build"
run: npm run build

View File

@@ -1,10 +1,6 @@
name: Test end-to-end
name: Test end-to-end [linux]
on:
workflow_dispatch: {}
# push:
# branches:
# - develop
on: push
jobs:
release:
@@ -12,16 +8,16 @@ jobs:
strategy:
matrix:
os: [windows-latest]
os: [ubuntu-latest]
steps:
- name: Check out Git repository
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Install Node.js
uses: actions/setup-node@v4
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v1
with:
node-version: 20
node-version: 14
- name: Install dependencies
run: npm i

1
.gitignore vendored
View File

@@ -7,4 +7,5 @@ node_modules
thumbs.db
NOTES.md
*.txt
package-lock.json
*.heapsnapshot

View File

@@ -1 +0,0 @@
npx --no -- commitlint --edit $1

View File

@@ -1 +0,0 @@
npm run lint

BIN
.nvmrc

Binary file not shown.

View File

@@ -1,18 +1,16 @@
{
"extends": [
"stylelint-config-standard",
"stylelint-config-recommended-vue"
"stylelint-config-standard"
],
"fix": true,
"formatter": "verbose",
"customSyntax": "postcss-html",
"plugins": [
"stylelint-scss"
],
"rules": {
"at-rule-no-unknown": null,
"no-descending-specificity": null,
"font-family-no-missing-generic-family-keyword": null
"declaration-colon-newline-after": "always-multi-line"
},
"syntax": "scss"
}

11
.vscode/launch.json vendored
View File

@@ -5,6 +5,7 @@
"name": "Electron: Main",
"cwd": "${workspaceFolder}",
"port": 9222,
"protocol": "inspector",
"request": "attach",
"sourceMaps": true,
"type": "node",
@@ -17,6 +18,16 @@
"sourceMaps": true,
"type": "chrome",
"webRoot": "${workspaceFolder}"
},
{
"name": "Electron: Worker",
"cwd": "${workspaceFolder}",
"port": 9224,
"protocol": "inspector",
"request": "attach",
"sourceMaps": true,
"type": "node",
"timeout": 1000000
}
],
"compounds": [

View File

@@ -5,13 +5,8 @@
"MySQL",
"PostgreSQL",
"SQLite",
"Firebird SQL",
"Windows",
"translation",
"Linux",
"MacOS",
"deps",
"Flatpak"
"translation"
],
"svg.preview.background": "transparent"
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -44,7 +44,8 @@ In this folder is located the structure of Vue frontend application.
## Build
The command to build Antares SQL locally is `npm run build`.
The command to build Antares SQL locally is `npm run build:local`.
`build` command (without `:local`) is used exclusively by the GitHub Action.
## Conventions

132
README.md
View File

@@ -1,29 +1,24 @@
<!-- markdownlint-disable -->
<p align="center">
<img width="800" src="https://raw.githubusercontent.com/antares-sql/antares/master/docs/gh-logo.png">
<img width="800" src="https://raw.githubusercontent.com/Fabio286/antares/master/docs/gh-logo.png">
</p>
<!-- markdownlint-restore -->
# Antares SQL Client
![GitHub package.json version](https://img.shields.io/github/package-json/v/antares-sql/antares) ![GitHub](https://img.shields.io/github/license/antares-sql/antares) ![Test e2e](https://github.com/antares-sql/antares/actions/workflows/test-e2e-win.yml/badge.svg?branch=develop) ![Mastodon Follow](https://img.shields.io/mastodon/follow/%20110860460902482117?domain=https%3A%2F%2Ffosstodon.org&style=social) [![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)
![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) [![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.
Our target is to support as many databases as possible, and all major operating systems, including the ARM versions.
**At the moment this application is in development state, many features will come in future updates**, and supports only MySQL/MariaDB, PostgreSQL, SQLite and Firebird SQL.
However, there are all the features necessary to have a pleasant database management experience, so give it a chance and send us your feedback, we would really appreciate it.
**At the moment this application is in development state, many features will come in future updates**, and supports only MySQL/MariaDB, PostgreSQL and SQLite.
At the moment, however, there are all the features necessary to have a pleasant database management experience, so give it a chance and send us your feedback, we would really appreciate it.
We are actively working on it, hoping to provide new cool features, improvements and fixes as soon as possible.
🔗 If you are curious to try Antares you can download and install the [latest release](https://github.com/antares-sql/antares/releases/latest).
👁 To stay tuned for new releases follow Antares SQL on [Mastodon](https://fosstodon.org/@AntaresSQL).
🌟 Don't forget to **leave a star** if you appreciate this project.
🗳️ Polls:
- **[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)**
🔗 If you are curious to try Antares you can download and install the [latest release](https://github.com/Fabio286/antares/releases/latest).
👁 To stay tuned for new releases [follow Antares SQL](https://twitter.com/AntaresSQL) on Twitter.
🌟 Don't forget to **leave a star** if you appreciate this project.
## Current key features
@@ -35,11 +30,9 @@ We are actively working on it, hoping to provide new cool features, improvements
- Fake table data filler to generate tons of data for test purpose.
- Query suggestions and auto complete.
- Query history: search through the last 1000 queries.
- Save queries, notes or todo.
- SSH tunnel support.
- Manual commit mode.
- Import and export database dumps.
- Customizable keyboard shortcuts.
- Dark and light theme.
- Editor themes.
@@ -47,20 +40,20 @@ We are actively working on it, hoping to provide new cool features, improvements
Why are we developing an SQL client when there are a lot of them on the market?
The main goal is to develop a **forever 100% free (without paid premium feature)**, full featured, as possible community driven, cross platform and open source alternative, empowered by JavaScript ecosystem.
A modern application created with minimalism and simplicity in mind, with features in the right places, not hundreds of tiny buttons, nested tabs or submenues; productivity comes first.
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.
## Installation
Based on your operating system you can have one or more distribution formats to choose based on your preferences.
Since Antares SQL is a free software we don't have a budget to spend on annual licenses or certificates. This can result that on some platforms you might need to put in some additional work to install this app.
Since Antares SQL is a free software we haven't a budget to spend in annual licenses or certificates. This can result that on some platforms you need some additional passages to install this app.
### Linux
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).
On Linux you can simply download and run `.AppImage` distributions, install from Snap Store or from AUR.
### Windows
On Windows you can choose between downloading the app from Microsoft Store or downloading the `.exe` from our [website](https://antares-sql.app/downloads) or [this github repo](https://github.com/antares-sql/antares/releases/latest). Distributions that are not from Microsoft Store are not signed with a certificate, so to install you need to click on "More info" and then "Run anyway" on SmartScreen prompt.
On Windows you can choose between Microsoft Store and download `.exe` distribution. The latter lacks of a certificate, so to install you need to click on "More info" and then "Run anyway" on SmartScreen prompt.
### MacOS
@@ -68,8 +61,19 @@ On macOS you can run `.dmg` distribution following [this guide](https://support.
## Download
[<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/antares-sql/antares/releases/latest)**
[![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/) [![Get it from Microsoft Store](https://raw.githubusercontent.com/Fabio286/antares/gh-pages/src/assets/ms-store.png)](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)**
## Coming soon
This is a roadmap with major features will come in near future.
- Database tools.
- Users management (add/edit/delete).
- More context menu shortcuts.
- More keyboard shortcuts.
- Support for other databases.
- Apple Silicon distribution
## Currently supported
@@ -78,9 +82,8 @@ On macOS you can run `.dmg` distribution following [this guide](https://support.
- [x] MySQL/MariaDB
- [x] PostgreSQL
- [x] SQLite
- [x] Firebird SQL
- [ ] DuckDB
- [ ] SQL Server
- [ ] MSSQL
- [ ] OracleDB
- [ ] More...
### Operating Systems
@@ -99,9 +102,9 @@ On macOS you can run `.dmg` distribution following [this guide](https://support.
## How to contribute
- 🌍 [Translate Antares](https://github.com/antares-sql/antares/wiki/Translate-Antares)
- 📖 [Contributors Guide](https://github.com/antares-sql/antares/wiki/Contributors-Guide)
- 🚧 [Project Board](https://github.com/orgs/antares-sql/projects/3/views/2)
- 🌍 [Translate Antares](https://github.com/Fabio286/antares/wiki/Translate-Antares)
- 📖 [Contributors Guide](https://github.com/Fabio286/antares/wiki/Contributors-Guide)
- 🚧 [Project Board](https://github.com/antares-sql/antares/projects/1)
## Contributors ✨
@@ -111,59 +114,30 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://fabiodistasio.it/"><img src="https://avatars.githubusercontent.com/u/31471771?v=4?s=100" width="100px;" alt="Fabio Di Stasio"/><br /><sub><b>Fabio Di Stasio</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=Fabio286" title="Code">💻</a> <a href="#translation-Fabio286" title="Translation">🌍</a> <a href="https://github.com/antares-sql/antares/commits?author=Fabio286" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/giulioganci/"><img src="https://avatars.githubusercontent.com/u/4192159?v=4?s=100" width="100px;" alt="Giulio Ganci"/><br /><sub><b>Giulio Ganci</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=toriphes" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://christianratz.de/"><img src="https://avatars.githubusercontent.com/u/2630316?v=4?s=100" width="100px;" alt="Christian Ratz"/><br /><sub><b>Christian Ratz</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=digitalgopnik" title="Code">💻</a> <a href="#translation-digitalgopnik" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://reverb6821.github.io/"><img src="https://avatars.githubusercontent.com/u/55198803?v=4?s=100" width="100px;" alt="Giuseppe Gigliotti"/><br /><sub><b>Giuseppe Gigliotti</b></sub></a><br /><a href="#translation-reverb6821" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Mohd-PH"><img src="https://avatars.githubusercontent.com/u/9362157?v=4?s=100" width="100px;" alt="Mohd-PH"/><br /><sub><b>Mohd-PH</b></sub></a><br /><a href="#translation-Mohd-PH" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hongkfui"><img src="https://avatars.githubusercontent.com/u/37477191?v=4?s=100" width="100px;" alt="hongkfui"/><br /><sub><b>hongkfui</b></sub></a><br /><a href="#translation-hongkfui" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MrAnyx"><img src="https://avatars.githubusercontent.com/u/44176707?v=4?s=100" width="100px;" alt="Robin"/><br /><sub><b>Robin</b></sub></a><br /><a href="#translation-MrAnyx" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/daeleduardo"><img src="https://avatars.githubusercontent.com/u/8599078?v=4?s=100" width="100px;" alt="Daniel Eduardo"/><br /><sub><b>Daniel Eduardo</b></sub></a><br /><a href="#translation-daeleduardo" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://ngoquocdat.com/"><img src="https://avatars.githubusercontent.com/u/56961917?v=4?s=100" width="100px;" alt="Ngô Quốc Đạt"/><br /><sub><b>Ngô Quốc Đạt</b></sub></a><br /><a href="#translation-datlechin" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/IsamuSugi"><img src="https://avatars.githubusercontent.com/u/7746658?v=4?s=100" width="100px;" alt="Isamu Sugiura"/><br /><sub><b>Isamu Sugiura</b></sub></a><br /><a href="#translation-IsamuSugi" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://rsacchetto.nexxontech.it/"><img src="https://avatars.githubusercontent.com/u/18429412?v=4?s=100" width="100px;" alt="Riccardo Sacchetto"/><br /><sub><b>Riccardo Sacchetto</b></sub></a><br /><a href="#platform-Occhioverde" title="Packaging/porting to new platform">📦</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://kilianstallinger.com"><img src="https://avatars.githubusercontent.com/u/5290318?v=4?s=100" width="100px;" alt="Kilian Stallinger"/><br /><sub><b>Kilian Stallinger</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=kilianstallz" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wenj91"><img src="https://avatars.githubusercontent.com/u/12549338?v=4?s=100" width="100px;" alt="文杰"/><br /><sub><b>文杰</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=wenj91" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/goYou"><img src="https://avatars.githubusercontent.com/u/62732795?v=4?s=100" width="100px;" alt="goYou"/><br /><sub><b>goYou</b></sub></a><br /><a href="#translation-goYou" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/raliqala"><img src="https://avatars.githubusercontent.com/u/30502407?v=4?s=100" width="100px;" alt="Topollo"/><br /><sub><b>Topollo</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=raliqala" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SmileYzn"><img src="https://avatars.githubusercontent.com/u/5851851?v=4?s=100" width="100px;" alt="Cleverson"/><br /><sub><b>Cleverson</b></sub></a><br /><a href="#translation-SmileYzn" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fredatgithub"><img src="https://avatars.githubusercontent.com/u/6720055?v=4?s=100" width="100px;" alt="fred"/><br /><sub><b>fred</b></sub></a><br /><a href="#translation-fredatgithub" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xak666"><img src="https://avatars.githubusercontent.com/u/38811437?v=4?s=100" width="100px;" alt="xaka_xak"/><br /><sub><b>xaka_xak</b></sub></a><br /><a href="#translation-xak666" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://codepen.io/theo-billardey"><img src="https://avatars.githubusercontent.com/u/48206778?v=4?s=100" width="100px;" alt="Théo Billardey"/><br /><sub><b>Théo Billardey</b></sub></a><br /><a href="#translation-brdtheo" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://yaskur.net"><img src="https://avatars.githubusercontent.com/u/9539970?v=4?s=100" width="100px;" alt="Muhammad Dyas Yaskur"/><br /><sub><b>Muhammad Dyas Yaskur</b></sub></a><br /><a href="#translation-dyaskur" title="Translation">🌍</a> <a href="https://github.com/antares-sql/antares/commits?author=dyaskur" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jimcat8"><img src="https://avatars.githubusercontent.com/u/86754294?v=4?s=100" width="100px;" alt="tianci li"/><br /><sub><b>tianci li</b></sub></a><br /><a href="#translation-jimcat8" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/555cider"><img src="https://avatars.githubusercontent.com/u/73565447?v=4?s=100" width="100px;" alt="555cider"/><br /><sub><b>555cider</b></sub></a><br /><a href="#translation-555cider" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/m1khal3v"><img src="https://avatars.githubusercontent.com/u/41085561?v=4?s=100" width="100px;" alt="Anton Mikhalev"/><br /><sub><b>Anton Mikhalev</b></sub></a><br /><a href="#translation-m1khal3v" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://64k.nl/"><img src="https://avatars.githubusercontent.com/u/3864423?v=4?s=100" width="100px;" alt="René"/><br /><sub><b>René</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=64knl" title="Code">💻</a> <a href="#translation-64knl" title="Translation">🌍</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/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>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bagusindrayana"><img src="https://avatars.githubusercontent.com/u/36830534?v=4?s=100" width="100px;" alt="Bagus Indrayana"/><br /><sub><b>Bagus Indrayana</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=bagusindrayana" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/penguinlab"><img src="https://avatars.githubusercontent.com/u/10959317?v=4?s=100" width="100px;" alt="Naoki Ishikawa"/><br /><sub><b>Naoki Ishikawa</b></sub></a><br /><a href="#translation-penguinlab" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://fazevedo.dev"><img src="https://avatars.githubusercontent.com/u/1640325?v=4?s=100" width="100px;" alt="Filipe Azevedo"/><br /><sub><b>Filipe Azevedo</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=mangas" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zwei-c"><img src="https://avatars.githubusercontent.com/u/55912811?v=4?s=100" width="100px;" alt="CHANG, CHIH WEI"/><br /><sub><b>CHANG, CHIH WEI</b></sub></a><br /><a href="#translation-zwei-c" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mirrorb"><img src="https://avatars.githubusercontent.com/u/34116207?v=4?s=100" width="100px;" alt="GaoChun"/><br /><sub><b>GaoChun</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=mirrorb" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LeviEyal"><img src="https://avatars.githubusercontent.com/u/48846533?v=4?s=100" width="100px;" alt="Eyal Levi"/><br /><sub><b>Eyal Levi</b></sub></a><br /><a href="#translation-LeviEyal" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://telegram.dog/SawGoD"><img src="https://avatars.githubusercontent.com/u/67802757?v=4?s=100" width="100px;" alt="Nikita Karelikov"/><br /><sub><b>Nikita Karelikov</b></sub></a><br /><a href="#translation-SawGoD" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/carvalhods"><img src="https://avatars.githubusercontent.com/u/6569255?v=4?s=100" width="100px;" alt="David Carvalho"/><br /><sub><b>David Carvalho</b></sub></a><br /><a href="#platform-carvalhods" title="Packaging/porting to new platform">📦</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/r4f4dev"><img src="https://avatars.githubusercontent.com/u/65920592?v=4?s=100" width="100px;" alt="r4f4dev"/><br /><sub><b>r4f4dev</b></sub></a><br /><a href="#translation-r4f4dev" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/salvymc"><img src="https://avatars.githubusercontent.com/u/10051897?v=4?s=100" width="100px;" alt="Salvatore Forino"/><br /><sub><b>Salvatore Forino</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=salvymc" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://gadev.com.es/"><img src="https://avatars.githubusercontent.com/u/16820141?v=4?s=100" width="100px;" alt="José González"/><br /><sub><b>José González</b></sub></a><br /><a href="#translation-JoseGonzalez84" title="Translation">🌍</a></td>
</tr>
</tbody>
<tr>
<td align="center"><a href="https://fabiodistasio.it/"><img src="https://avatars.githubusercontent.com/u/31471771?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Fabio Di Stasio</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=Fabio286" title="Code">💻</a> <a href="#translation-Fabio286" title="Translation">🌍</a> <a href="https://github.com/antares-sql/antares/commits?author=Fabio286" title="Documentation">📖</a></td>
<td align="center"><a href="https://www.linkedin.com/in/giulioganci/"><img src="https://avatars.githubusercontent.com/u/4192159?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Giulio Ganci</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=toriphes" title="Code">💻</a></td>
<td align="center"><a href="https://christianratz.de/"><img src="https://avatars.githubusercontent.com/u/2630316?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Christian Ratz</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=digitalgopnik" title="Code">💻</a> <a href="#translation-digitalgopnik" title="Translation">🌍</a></td>
<td align="center"><a href="https://reverb6821.github.io/"><img src="https://avatars.githubusercontent.com/u/55198803?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Giuseppe Gigliotti</b></sub></a><br /><a href="#translation-reverb6821" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/Mohd-PH"><img src="https://avatars.githubusercontent.com/u/9362157?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mohd-PH</b></sub></a><br /><a href="#translation-Mohd-PH" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/hongkfui"><img src="https://avatars.githubusercontent.com/u/37477191?v=4?s=100" width="100px;" alt=""/><br /><sub><b>hongkfui</b></sub></a><br /><a href="#translation-hongkfui" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/MrAnyx"><img src="https://avatars.githubusercontent.com/u/44176707?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Robin</b></sub></a><br /><a href="#translation-MrAnyx" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/daeleduardo"><img src="https://avatars.githubusercontent.com/u/8599078?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Eduardo</b></sub></a><br /><a href="#translation-daeleduardo" title="Translation">🌍</a></td>
<td align="center"><a href="https://ngoquocdat.com/"><img src="https://avatars.githubusercontent.com/u/56961917?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ngô Quốc Đạt</b></sub></a><br /><a href="#translation-datlechin" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/IsamuSugi"><img src="https://avatars.githubusercontent.com/u/7746658?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Isamu Sugiura</b></sub></a><br /><a href="#translation-IsamuSugi" title="Translation">🌍</a></td>
<td align="center"><a href="http://rsacchetto.nexxontech.it/"><img src="https://avatars.githubusercontent.com/u/18429412?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Riccardo Sacchetto</b></sub></a><br /><a href="#platform-Occhioverde" title="Packaging/porting to new platform">📦</a></td>
<td align="center"><a href="https://kilianstallinger.com"><img src="https://avatars.githubusercontent.com/u/5290318?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kilian Stallinger</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=kilianstallz" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/wenj91"><img src="https://avatars.githubusercontent.com/u/12549338?v=4?s=100" width="100px;" alt=""/><br /><sub><b>文杰</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=wenj91" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/goYou"><img src="https://avatars.githubusercontent.com/u/62732795?v=4?s=100" width="100px;" alt=""/><br /><sub><b>goYou</b></sub></a><br /><a href="#translation-goYou" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/raliqala"><img src="https://avatars.githubusercontent.com/u/30502407?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Topollo</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=raliqala" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/SmileYzn"><img src="https://avatars.githubusercontent.com/u/5851851?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cleverson</b></sub></a><br /><a href="#translation-SmileYzn" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/fredatgithub"><img src="https://avatars.githubusercontent.com/u/6720055?v=4?s=100" width="100px;" alt=""/><br /><sub><b>fred</b></sub></a><br /><a href="#translation-fredatgithub" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/xak666"><img src="https://avatars.githubusercontent.com/u/38811437?v=4?s=100" width="100px;" alt=""/><br /><sub><b>xaka_xak</b></sub></a><br /><a href="#translation-xak666" title="Translation">🌍</a></td>
</tr>
</table>
<!-- markdownlint-restore -->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

View File

@@ -1,9 +0,0 @@
[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

@@ -1,34 +0,0 @@
<?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.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

View File

@@ -1,33 +0,0 @@
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
// TODO Add Scope Enum Here
// 'scope-enum': [2, 'always', ['yourscope', 'yourscope']],
'type-enum': [
2,
'always',
[
'feat',
'fix',
'docs',
'chore',
'style',
'refactor',
'build',
'ci',
'test',
'revert',
'perf'
]
],
'subject-case': [
2,
'never',
[
'upper-case',
'pascal-case',
'start-case'
]
]
}
};

View File

@@ -1,37 +1,76 @@
<svg xmlns="http://www.w3.org/2000/svg" style="isolation:isolate" width="182" height="56">
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- 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>
<clipPath id="prefix__a">
<path d="M0 0h182v56H0z" />
<clipPath id="_clipPath_tR1uglJ1Zei76xP861DY1TsjAiQWS9qF">
<rect width="182" height="56" />
</clipPath>
</defs>
<g clip-path="url(#prefix__a)">
<!-- <path d="M2.5.5h178a2 2 0 012 2v52a2 2 0 01-2 2H2.5a2 2 0" fill="#252525" stroke="#FFF" stroke-width="2"/> -->
<rect x="0" y="0" width="182" height="56" fill="#252525" stroke="#FFF" stroke-width="1" rx="0" />
<g fill-rule="evenodd" fill="#FFF">
<path
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" />
</g>
<g fill-rule="evenodd" fill="#1793D1">
<path
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>
<g clip-path="url(#_clipPath_tR1uglJ1Zei76xP861DY1TsjAiQWS9qF)">
<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">
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="stroke:none;fill:#252525;stroke-miterlimit:10;" />
<path
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
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" />
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 "
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 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>
<g clip-path="url(#_clipPath_NvFIpNfWUS6M4fZAtfyVzggsKR3URDoi)"><text transform="matrix(1,0,0,1,87.023,43.899)"
style="font-family:'Open Sans';font-weight:700;font-size:11px;font-style:normal;fill:#ffffff;stroke:none;">user
repository</text></g>
<defs>
<clipPath id="prefix__b">
<path transform="translate(87 32.142)" d="M0 0h86v14.98H0z" />
<clipPath id="_clipPath_NvFIpNfWUS6M4fZAtfyVzggsKR3URDoi">
<rect x="0" y="0" width="86" height="14.98" transform="matrix(1,0,0,1,87,32.142)" />
</clipPath>
</defs>
</g>

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

27405
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"name": "antares",
"productName": "Antares",
"version": "0.7.34",
"version": "0.5.5",
"description": "A modern, fast and productivity driven SQL client with a focus in UX.",
"license": "MIT",
"repository": "https://github.com/antares-sql/antares.git",
@@ -12,23 +12,22 @@
"compile:main": "webpack --mode=production --config webpack.main.config.js",
"compile:workers": "webpack --mode=production --config webpack.workers.config.js",
"compile:renderer": "webpack --mode=production --config webpack.renderer.config.js",
"build": "cross-env NODE_ENV=production npm run compile && electron-builder --publish never",
"build:appx": "npm run build -- --win appx",
"rebuild:electron": "rimraf ./dist && npm run postinstall && npm run devtools:install",
"build": "cross-env NODE_ENV=production npm run compile",
"build:local": "npm run build && electron-builder",
"build:appx": "npm run build:local -- --win appx",
"rebuild:electron": "rimraf ./dist && npm run postinstall",
"release": "standard-version",
"release:beta": "npm run release -- --prerelease beta",
"release:pre": "npm run release -- --prerelease alpha",
"devtools:install": "node scripts/devtoolsInstaller",
"postinstall": "electron-builder install-app-deps",
"translation:check": "ts-node ./scripts/translationCheck.ts",
"postinstall": "electron-builder install-app-deps && npm run devtools:install",
"test:e2e": "npm run compile && npm run test:e2e-dry",
"test:e2e-dry": "xvfb-maybe -- playwright test",
"lint": "eslint . --ext .js,.ts,.vue && stylelint \"./src/**/*.{css,scss,sass,vue}\"",
"lint:fix": "eslint . --ext .js,.ts,.vue --fix && stylelint \"./src/**/*.{css,scss,sass,vue}\" --fix",
"lint": "eslint . --ext .js,.vue && stylelint \"./src/**/*.{css,scss,sass,vue}\"",
"lint:fix": "eslint . --ext .js,.vue --fix && stylelint \"./src/**/*.{css,scss,sass,vue}\" --fix",
"contributors:add": "all-contributors add",
"contributors:generate": "all-contributors generate",
"prepare": "husky"
"contributors:generate": "all-contributors generate"
},
"author": "Fabio Di Stasio <info@fabiodistasio.it>",
"author": "Fabio Di Stasio <fabio286@gmail.com>",
"main": "./dist/main.js",
"antares": {
"devtoolsId": "nhdogjmejiglipccpnnnanhbledajbpd"
@@ -66,32 +65,23 @@
"target": [
{
"target": "deb",
"arch": [
"x64",
"armv7l"
]
"arch": "x64"
},
{
"target": "AppImage",
"arch": [
"x64",
"armv7l"
"armv7l",
"arm64"
]
}
],
"icon": "assets/linux",
"category": "Development"
},
"appImage": {
"license": "./LICENSE",
"category": "Development"
},
"nsis": {
"license": "./LICENSE",
"installerIcon": "assets/icon.ico",
"uninstallerIcon": "assets/icon.ico",
"installerHeader": "assets/icon.ico"
},
"portable": {
"artifactName": "${productName}-${version}-portable.exe"
},
@@ -119,100 +109,83 @@
}
},
"dependencies": {
"@electron/remote": "~2.1.2",
"@fabio286/ssh2-promise": "~1.0.4-b",
"@electron/remote": "~2.0.1",
"@faker-js/faker": "~6.1.2",
"@jamescoyle/vue-icon": "~0.1.2",
"@mdi/js": "~7.2.96",
"@mdi/font": "~6.1.95",
"@turf/helpers": "~6.5.0",
"@vue/compiler-sfc": "~3.2.33",
"@vueuse/core": "~10.4.1",
"ace-builds": "~1.34.1",
"babel-loader": "~8.2.3",
"better-sqlite3": "~10.0.0",
"chalk": "~4.1.2",
"ciaplu": "^2.2.0",
"cpu-features": "^0.0.10",
"cross-env": "~7.0.2",
"css-loader": "~6.5.0",
"electron-log": "~5.0.1",
"electron-store": "~8.1.0",
"@vscode/vscode-languagedetection": "~1.0.21",
"ace-builds": "~1.4.13",
"better-sqlite3": "~7.5.0",
"electron-log": "~4.4.1",
"electron-store": "~8.0.1",
"electron-updater": "~4.6.5",
"electron-window-state": "~5.0.3",
"encoding": "~0.1.13",
"file-loader": "~6.2.0",
"floating-vue": "~2.0.0-beta.20",
"html-webpack-plugin": "~5.5.0",
"json2php": "~0.0.7",
"leaflet": "~1.7.1",
"marked": "~12.0.0",
"mini-css-extract-plugin": "~2.4.5",
"moment": "~2.30.1",
"mysql2": "~3.9.7",
"node-firebird": "~1.1.8",
"node-loader": "~2.0.0",
"pg": "~8.11.5",
"marked": "~4.0.0",
"moment": "~2.29.1",
"mysql2": "~2.3.2",
"pg": "~8.7.1",
"pg-query-stream": "~4.2.3",
"pgsql-ast-parser": "~7.2.1",
"pinia": "~2.1.7",
"postcss-html": "~1.5.0",
"progress-webpack-plugin": "~1.0.12",
"rimraf": "~3.0.2",
"sass": "~1.42.1",
"sass-loader": "~12.3.0",
"pinia": "~2.0.13",
"source-map-support": "~0.5.20",
"spectre.css": "~0.5.9",
"sql-formatter": "~13.0.0",
"sql-highlight": "~4.4.0",
"style-loader": "~3.3.1",
"tree-kill": "~1.2.2",
"ts-loader": "~9.2.8",
"typescript": "~4.6.3",
"unzip-crx-3": "~0.2.0",
"sql-formatter": "~4.0.2",
"ssh2-promise": "~1.0.2",
"v-mask": "~2.3.0",
"vue": "~3.4.27",
"vue-i18n": "~9.13.1",
"vue-loader": "~16.8.3",
"vuedraggable": "~4.1.0",
"webpack": "^5.91.0",
"webpack-cli": "~4.9.1"
"vue": "~3.2.33",
"vue-i18n": "~9.1.9",
"vuedraggable": "~4.1.0"
},
"devDependencies": {
"@babel/eslint-parser": "~7.15.7",
"@babel/preset-env": "~7.15.8",
"@babel/preset-typescript": "~7.16.7",
"@commitlint/cli": "~19.0.3",
"@commitlint/config-conventional": "~19.0.3",
"@playwright/test": "~1.28.1",
"@playwright/test": "~1.21.1",
"@types/better-sqlite3": "~7.5.0",
"@types/leaflet": "~1.7.9",
"@types/marked": "~4.0.7",
"@types/node": "~17.0.23",
"@types/pg": "~8.6.5",
"@types/ssh2": "~1.11.6",
"@typescript-eslint/eslint-plugin": "~5.18.0",
"@typescript-eslint/parser": "~5.18.0",
"@vue/compiler-sfc": "~3.2.33",
"all-contributors-cli": "~6.20.0",
"electron": "~30.0.8",
"electron-builder": "~24.13.3",
"babel-loader": "~8.2.3",
"chalk": "~4.1.2",
"cross-env": "~7.0.2",
"css-loader": "~6.5.0",
"electron": "~17.4.3",
"electron-builder": "~23.0.3",
"eslint": "~7.32.0",
"eslint-config-standard": "~16.0.3",
"eslint-plugin-import": "~2.24.2",
"eslint-plugin-node": "~11.1.0",
"eslint-plugin-promise": "~5.2.0",
"eslint-plugin-simple-import-sort": "~10.0.0",
"eslint-plugin-vue": "~8.0.3",
"husky": "~9.0.11",
"playwright": "~1.28.1",
"playwright-core": "~1.28.1",
"file-loader": "~6.2.0",
"html-webpack-plugin": "~5.5.0",
"mini-css-extract-plugin": "~2.4.5",
"node-loader": "~2.0.0",
"playwright": "~1.21.1",
"playwright-core": "~1.21.1",
"progress-webpack-plugin": "~1.0.12",
"rimraf": "~3.0.2",
"sass": "~1.42.1",
"sass-loader": "~12.3.0",
"standard-version": "~9.3.1",
"stylelint": "^15.11.0",
"stylelint-config-recommended-vue": "~1.5.0",
"stylelint-config-standard": "~34.0.0",
"stylelint-scss": "~5.3.0",
"ts-node": "~10.9.1",
"style-loader": "~3.3.1",
"stylelint": "~13.13.1",
"stylelint-config-standard": "~22.0.0",
"stylelint-scss": "~3.21.0",
"tree-kill": "~1.2.2",
"ts-loader": "~9.2.8",
"typescript": "~4.6.3",
"unzip-crx-3": "~0.2.0",
"vue-eslint-parser": "~8.3.0",
"webpack-dev-server": "~4.11.1",
"vue-loader": "~16.8.3",
"webpack": "~5.60.0",
"webpack-cli": "~4.9.1",
"webpack-dev-server": "~4.4.0",
"xvfb-maybe": "~0.2.1"
}
}

View File

@@ -59,43 +59,47 @@ async function restartElectron () {
console.error(chalk.red(data.toString()));
});
electronProcess.on('exit', () => {
electronProcess.on('exit', (code, signal) => {
if (!manualRestart) process.exit(0);
});
}
function startWorkers () {
const compiler = webpack(workersConfig);
const { name } = compiler;
compiler.hooks.afterEmit.tap('afterEmit', () => {
console.log(chalk.gray(`\nCompiled ${name} script!`));
console.log(chalk.gray(`\nWatching file changes for ${name} script...`));
});
compiler.watch({ aggregateTimeout: 500 }, err => {
if (err) console.error(chalk.red(err));
});
}
function startMain () {
const compiler = webpack(mainConfig);
const { name } = compiler;
const webpackSetup = webpack([mainConfig, workersConfig]);
compiler.hooks.afterEmit.tap('afterEmit', async () => {
console.log(chalk.gray(`\nCompiled ${name} script!`));
webpackSetup.compilers.forEach((compiler) => {
const { name } = compiler;
manualRestart = true;
await restartElectron();
startWorkers();
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!`));
setTimeout(() => {
manualRestart = false;
}, 2500);
manualRestart = true;
await restartElectron();
console.log(chalk.gray(`\nWatching file changes for ${name} script...`));
setTimeout(() => {
manualRestart = false;
}, 2500);
console.log(
chalk.gray(`\nWatching file changes for ${name} script...`)
);
});
break;
}
});
compiler.watch({ aggregateTimeout: 500 }, err => {
webpackSetup.watch({ aggregateTimeout: 500 }, err => {
if (err) console.error(chalk.red(err));
});
}
@@ -110,8 +114,8 @@ function startRenderer (callback) {
});
const server = new WebpackDevServer(compiler, {
port: 9080,
hot: true,
port: 9080,
client: {
overlay: true,
logging: 'warn'

View File

@@ -1,4 +1,3 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-check
const fs = require('fs');
const path = require('path');
@@ -7,18 +6,13 @@ const unzip = require('unzip-crx-3');
const { antares } = require('../package.json');
const extensionID = antares.devtoolsId;
const chromiumVersion = '124';
const destFolder = path.resolve(__dirname, `../misc/${extensionID}`);
const filePath = path.resolve(__dirname, `${destFolder}/${extensionID}.crx`);
const fileUrl = `https://clients2.google.com/service/update2/crx?response=redirect&acceptformat=crx2,crx3&x=id%3D${extensionID}%26uc&prodversion=${chromiumVersion}`;
if (!fs.existsSync(destFolder))
fs.mkdirSync(destFolder, { recursive: true });
const filePath = path.resolve(__dirname, `${destFolder}${extensionID}.crx`);
const fileUrl = `https://clients2.google.com/service/update2/crx?response=redirect&acceptformat=crx2,crx3&x=id%3D${extensionID}%26uc&prodversion=32`;
const fileStream = fs.createWriteStream(filePath);
const downloadFile = url => {
return /** @type {Promise<void>} */(new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
const request = https.get(url);
request.on('response', response => {
@@ -38,7 +32,7 @@ const downloadFile = url => {
});
request.on('error', reject);
request.end();
}));
});
};
(async () => {
@@ -47,7 +41,6 @@ const downloadFile = url => {
await unzip(filePath, destFolder);
fs.unlinkSync(filePath);
fs.unlinkSync(`${destFolder}/package.json`);// <- Avoid to display annoyng npm script in vscode
process.exit();
}
catch (error) {
console.log(error);

View File

@@ -1,45 +0,0 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { enUS } from '../src/renderer/i18n/en-US';
import { localesNames } from '../src/renderer/i18n/supported-locales';
const locale = process.argv[2];
let fullCount = 0;
let checkCount = 0;
if (!locale) {
console.log('Please specify locale code as first argument.');
process.exit();
}
if (!Object.keys(localesNames).includes(locale)) {
console.log(`Translation ${locale} not fount in supported locales.`);
process.exit();
}
console.log('Checking missing translations for:', locale);
const i18nFile = require(`../src/renderer/i18n/${locale}`)[locale.replace('-', '')];
for (const group in enUS) {
// @ts-ignore
fullCount += Object.keys(enUS[group]).length;
if (!Object.keys(i18nFile).includes(group)) {
console.log(`Group "\u001b[31m${group}\u001b[0m" missing!`);
continue;
}
// @ts-ignore
for (const term in enUS[group]) {
if (!Object.keys(i18nFile[group]).includes(term))
console.log(`Translation "\u001b[33m${group}.${term}\u001b[0m" missing!`);
// @ts-ignore
else if (i18nFile[group][term] === enUS[group][term]) {
console.log(`Term "\u001b[36m${group}.${term}\u001b[0m" not translated!`);
checkCount++;
}
else
checkCount++;
}
}
console.log(checkCount, 'of', fullCount, 'strings are present in', locale, `(\u001b[32m${(checkCount*100/fullCount).toFixed(1)}%\u001b[0m)`);

View File

@@ -4,7 +4,7 @@ summary: Open source SQL client made to be simple and complete.
description: |
Antares is an SQL client that aims to become an useful and complete tool, especially for developers.
The target is to support as many databases as possible, and all major operating systems, including the ARM versions.
base: core22
base: core20
grade: stable
confinement: strict
@@ -31,10 +31,10 @@ parts:
fi
# Get the latest releases json
echo "Get GitHub releases..."
wget --quiet https://api.github.com/repos/fabio286/antares/releases -O releases.json
wget --quiet https://api.github.com/repos/fabio286/antares/releases/latest -O releases.json
# Get the version from the tag_name and the download URL.
VERSION=$(jq . releases.json | grep tag_name | head -1 | cut -d'"' -f4 | sed s'/release-//')
DEB_URL=$(cat releases.json | jq -r ".[0].assets[] | select(.name | test(\"${FILTER}\")) | .browser_download_url")
VERSION=$(jq . releases.json | grep tag_name | cut -d'"' -f4 | sed s'/release-//')
DEB_URL=$(cat releases.json | jq -r ".assets[] | select(.name | test(\"${FILTER}\")) | .browser_download_url")
DEB=$(basename "${DEB_URL}")
echo "Downloading ${DEB_URL}..."
wget --quiet "${DEB_URL}" -O "${SNAPCRAFT_PART_INSTALL}/${DEB}"
@@ -79,7 +79,7 @@ parts:
- libdb5.3
- libdbus-1-3
- libexpat1
- libffi8
- libffi7
- libgcc-s1
- libgcrypt20
- libglib2.0-0
@@ -87,9 +87,9 @@ parts:
- libgnutls30
- libgpg-error0
- libgssapi-krb5-2
- libhogweed6
- libhogweed5
- libidn2-0
- libjson-c5
- libjson-c4
- libk5crypto3
- libkeyutils1
- libkrb5-3
@@ -97,12 +97,12 @@ parts:
- liblz4-1
- liblzma5
- libmount1
- libnettle8
- libnettle7
- libp11-kit0
- libpcre2-8-0
- libselinux1
- libsqlite3-0
- libssl3
- libssl1.1
- libstdc++6
- libsystemd0
- libtasn1-6
@@ -119,10 +119,10 @@ parts:
cleanup:
after: [antares]
plugin: nil
build-snaps: [gnome-42-2204]
build-snaps: [gnome-3-38-2004]
override-prime: |
set -eux
cd /snap/gnome-42-2204/current
cd /snap/gnome-3-38-2004/current
find . -type f,l -exec rm -f $SNAPCRAFT_PRIME/{} \;
mdns-lookup:
@@ -136,7 +136,7 @@ parts:
- libnss-mdns
override-prime: |
set -eux
sed -Ee 's/^\s*hosts:(\s+)files/hosts:\1files mdns4_minimal \[NOTFOUND=return\]/' /snap/core22/current/etc/nsswitch.conf > $SNAPCRAFT_STAGE/etc/nsswitch.conf
sed -Ee 's/^\s*hosts:(\s+)files/hosts:\1files mdns4_minimal \[NOTFOUND=return\]/' /snap/core20/current/etc/nsswitch.conf > $SNAPCRAFT_STAGE/etc/nsswitch.conf
snapcraftctl prime
prime:
- lib/$SNAPCRAFT_ARCH_TRIPLET/libnss_mdns4_minimal*
@@ -146,7 +146,10 @@ apps:
antares:
command: opt/Antares/antares --no-sandbox
desktop: usr/share/applications/antares.desktop
extensions: [gnome]
extensions: [gnome-3-38]
environment:
# Fallback to XWayland if running in a Wayland session.
DISABLE_WAYLAND: 1
plugs:
- browser-support
- cups-control

View File

@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
export default class {
static get _methods () {
return [
@@ -51,7 +50,6 @@ export default class {
{ name: 'collation', 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: 'future', group: 'date', types: ['string', 'datetime'] },
// { name: 'between', group: 'date', types: ['string'] },
@@ -141,7 +139,7 @@ export default class {
{ name: 'arrayElement', group: 'random', types: ['string'] },
{ name: 'arrayElements', group: 'random', types: ['string'] },
{ name: 'objectElement', group: 'random', types: ['string'] },
{ name: 'uuid', group: 'random', types: ['string', 'uuid'] },
{ name: 'uuid', group: 'random', types: ['string'] },
{ name: 'boolean', group: 'random', types: ['string'] },
{ name: 'word', group: 'random', types: ['string'] },
{ name: 'words', group: 'random', types: ['string'] },
@@ -162,9 +160,7 @@ export default class {
{ name: 'filePath', 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: 'random', group: 'time', types: ['string', 'time'] },
{ name: 'vehicle', group: 'vehicle', types: ['string'] },
{ name: 'manufacturer', group: 'vehicle', types: ['string'] },
@@ -184,7 +180,7 @@ export default class {
acc[curr.group] = new Set(curr.types);
return acc;
}, {} as any);
}, {});
const groupsArr = [];
@@ -202,12 +198,12 @@ export default class {
});
}
static getGroupsByType (type: string) {
static getGroupsByType (type) {
if (!type) return [];
return this.getGroups().filter(group => group.types.includes(type));
}
static getMethods ({ type, group }: {type: string; group: string}) {
static getMethods ({ type, group }) {
return this._methods.filter(method => method.group === group && method.types.includes(type)).sort((a, b) => {
if (a.name < b.name)
return -1;

View File

@@ -1,15 +1,8 @@
import { Customizations } from '../interfaces/customizations';
// Everything OFF
export const defaults: Customizations = {
module.exports = {
// Defaults
defaultPort: null,
defaultUser: null,
defaultDatabase: null,
dataTypes: [],
indexTypes: [],
foreignActions: [],
operators: ['=', '!=', '>', '<', '>=', '<=', 'IN', 'NOT IN', 'LIKE', 'NOT LIKE', 'BETWEEN', 'IS NULL', 'IS NOT NULL'],
// Core
database: false,
collations: false,
@@ -19,7 +12,6 @@ export const defaults: Customizations = {
sshConnection: false,
fileConnection: false,
cancelQueries: false,
singleConnectionMode: false,
// Tools
processesList: false,
usersManagement: false,
@@ -33,12 +25,10 @@ export const defaults: Customizations = {
routines: false,
functions: false,
schedulers: false,
// Misc
// Settings
elementsWrapper: '',
stringsWrapper: '"',
tableAdd: false,
tableTruncateDisableFKCheck: false,
tableDdl: false,
viewAdd: false,
triggerAdd: false,
triggerFunctionAdd: false,
@@ -52,10 +42,9 @@ export const defaults: Customizations = {
exportByChunks: false,
schemaImport: false,
tableSettings: false,
tableOptions: false,
tableArray: false,
tableRealCount: false,
tableDuplicate: false,
tableCheck: false,
viewSettings: false,
triggerSettings: false,
triggerFunctionSettings: false,
@@ -79,25 +68,24 @@ export const defaults: Customizations = {
viewUpdateOption: false,
procedureDeterministic: false,
procedureDataAccess: false,
procedureSql: null,
procedureSql: false,
procedureContext: false,
procedureContextValues: [],
procedureLanguage: false,
functionDeterministic: false,
functionDataAccess: false,
functionSql: null,
functionSql: false,
functionContext: false,
functionLanguage: false,
triggerSql: null,
triggerSql: false,
triggerStatementInCreation: false,
triggerMultipleEvents: false,
triggerTableInName: false,
triggerUpdateColumns: false,
triggerOnlyRename: false,
triggerEnableDisable: false,
triggerFunctionSql: null,
triggerFunctionlanguages: null,
triggerFunctionSql: false,
triggerFunctionlanguages: false,
parametersLength: false,
languages: null,
languages: false,
readOnlyMode: false
};

View File

@@ -1,63 +0,0 @@
import firebirdTypes from '../data-types/firebird';
import { Customizations } from '../interfaces/customizations';
import { defaults } from './defaults';
export const customizations: Customizations = {
...defaults,
// Defaults
defaultPort: 3050,
defaultUser: 'SYSDBA',
defaultDatabase: null,
dataTypes: firebirdTypes,
indexTypes: [
'PRIMARY',
// 'CHECK',
'UNIQUE'
],
foreignActions: [
'RESTRICT',
'NO ACTION',
'CASCADE',
'SET NULL',
'SET DEFAULT'
],
// Core
database: true,
collations: false,
engines: false,
connectionSchema: false,
sslConnection: false,
sshConnection: false,
fileConnection: false,
cancelQueries: false,
// Tools
processesList: false,
usersManagement: false,
variables: false,
// Structure
schemas: false,
tables: true,
views: true,
triggers: true,
routines: true,
functions: false,
// Settings
elementsWrapper: '"',
stringsWrapper: '\'',
tableAdd: true,
tableSettings: true,
tableRealCount: true,
viewAdd: true,
viewSettings: true,
triggerAdd: true,
triggerMultipleEvents: true,
triggerSql: 'BEGIN\r\n\r\nEND',
routineAdd: true,
procedureContext: true,
procedureContextValues: ['IN', 'OUT'],
procedureSql: 'BEGIN\r\n\r\nEND',
parametersLength: true,
indexes: true,
foreigns: true,
nullable: true
};

View File

@@ -0,0 +1,6 @@
module.exports = {
maria: require('./mysql'),
mysql: require('./mysql'),
pg: require('./postgresql'),
sqlite: require('./sqlite')
};

View File

@@ -1,19 +0,0 @@
import * as firebird from 'common/customizations/firebird';
import * as mysql from 'common/customizations/mysql';
import * as postgresql from 'common/customizations/postgresql';
import * as sqlite from 'common/customizations/sqlite';
import { Customizations } from 'common/interfaces/customizations';
export default {
maria: mysql.customizations,
mysql: mysql.customizations,
pg: postgresql.customizations,
sqlite: sqlite.customizations,
firebird: firebird.customizations
} as {
maria: Customizations;
mysql: Customizations;
pg: Customizations;
sqlite: Customizations;
firebird: Customizations;
};

View File

@@ -1,27 +1,11 @@
import mysqlTypes from '../data-types/mysql';
import { Customizations } from '../interfaces/customizations';
import { defaults } from './defaults';
const defaults = require('./defaults');
export const customizations: Customizations = {
module.exports = {
...defaults,
// Defaults
defaultPort: 3306,
defaultUser: 'root',
defaultDatabase: null,
dataTypes: mysqlTypes,
operators: ['=', '!=', '>', '<', '>=', '<=', 'IN', 'NOT IN', 'LIKE', 'NOT LIKE', 'RLIKE', 'NOT RLIKE', 'BETWEEN', 'IS NULL', 'IS NOT NULL'],
indexTypes: [
'PRIMARY',
'INDEX',
'UNIQUE',
'FULLTEXT'
],
foreignActions: [
'RESTRICT',
'CASCADE',
'SET NULL',
'NO ACTION'
],
// Core
connectionSchema: true,
collations: true,
@@ -29,7 +13,6 @@ export const customizations: Customizations = {
sslConnection: true,
sshConnection: true,
cancelQueries: true,
singleConnectionMode: true,
// Tools
processesList: true,
// Structure
@@ -41,13 +24,9 @@ export const customizations: Customizations = {
functions: true,
schedulers: true,
// Settings
elementsWrapper: '`',
elementsWrapper: '',
stringsWrapper: '"',
tableAdd: true,
tableTruncateDisableFKCheck: true,
tableDuplicate: true,
tableDdl: true,
tableCheck: true,
viewAdd: true,
triggerAdd: true,
routineAdd: true,
@@ -70,6 +49,7 @@ export const customizations: Customizations = {
unsigned: true,
nullable: true,
zerofill: true,
tableOptions: true,
autoIncrement: true,
comment: true,
collation: true,
@@ -82,7 +62,6 @@ export const customizations: Customizations = {
procedureDataAccess: true,
procedureSql: 'BEGIN\r\n\r\nEND',
procedureContext: true,
procedureContextValues: ['IN', 'OUT', 'INOUT'],
triggerSql: 'BEGIN\r\n\r\nEND',
functionDeterministic: true,
functionDataAccess: true,

View File

@@ -1,25 +1,11 @@
import postgresqlTypes from '../data-types/postgresql';
import { Customizations } from '../interfaces/customizations';
import { defaults } from './defaults';
const defaults = require('./defaults');
export const customizations: Customizations = {
module.exports = {
...defaults,
// Defaults
defaultPort: 5432,
defaultUser: 'postgres',
defaultDatabase: 'postgres',
dataTypes: postgresqlTypes,
indexTypes: [
'PRIMARY',
'INDEX',
'UNIQUE'
],
foreignActions: [
'RESTRICT',
'CASCADE',
'SET NULL',
'NO ACTION'
],
// Core
database: true,
sslConnection: true,
@@ -31,19 +17,15 @@ export const customizations: Customizations = {
schemas: true,
tables: true,
views: true,
materializedViews: true,
triggers: true,
triggerFunctions: true,
routines: true,
functions: true,
// Misc
// Settings
elementsWrapper: '"',
stringsWrapper: '\'',
tableAdd: true,
tableDuplicate: true,
tableDdl: true,
viewAdd: true,
materializedViewAdd: true,
triggerAdd: true,
triggerFunctionAdd: true,
routineAdd: true,
@@ -54,7 +36,6 @@ export const customizations: Customizations = {
databaseEdit: false,
tableSettings: true,
viewSettings: true,
materializedViewSettings: true,
triggerSettings: true,
triggerFunctionSettings: true,
routineSettings: true,
@@ -62,11 +43,9 @@ export const customizations: Customizations = {
indexes: true,
foreigns: true,
nullable: true,
comment: true,
tableArray: true,
procedureSql: '$procedure$\r\n\r\n$procedure$',
procedureContext: true,
procedureContextValues: ['IN', 'OUT', 'INOUT'],
procedureLanguage: true,
functionSql: '$function$\r\n\r\n$function$',
triggerFunctionSql: '$function$\r\nBEGIN\r\n\r\nEND\r\n$function$',

View File

@@ -1,21 +1,4 @@
import sqliteTypes from '../data-types/sqlite';
import { Customizations } from '../interfaces/customizations';
import { defaults } from './defaults';
export const customizations: Customizations = {
...defaults,
dataTypes: sqliteTypes,
indexTypes: [
'PRIMARY',
'INDEX',
'UNIQUE'
],
foreignActions: [
'RESTRICT',
'CASCADE',
'SET NULL',
'NO ACTION'
],
module.exports = {
// Core
fileConnection: true,
// Structure
@@ -27,7 +10,6 @@ export const customizations: Customizations = {
elementsWrapper: '"',
stringsWrapper: '\'',
tableAdd: true,
tableDuplicate: true,
viewAdd: true,
triggerAdd: true,
schemaEdit: false,

View File

@@ -1,136 +0,0 @@
import { TypesGroup } from 'common/interfaces/antares';
export default [
{
group: 'integer',
types: [
{
name: 'SMALLINT',
length: false,
collation: false,
unsigned: true,
zerofill: true
},
{
name: 'INTEGER',
length: false,
collation: false,
unsigned: true,
zerofill: true
},
{
name: 'BIGINT',
length: false,
collation: false,
unsigned: true,
zerofill: true
}
]
},
{
group: 'float',
types: [
{
name: 'DECIMAL',
length: true,
scale: true,
collation: false,
unsigned: false,
zerofill: false
},
{
name: 'NUMERIC',
length: true,
scale: true,
collation: false,
unsigned: false,
zerofill: false
},
{
name: 'FLOAT',
length: false,
collation: false,
unsigned: false,
zerofill: false
},
{
name: 'DOUBLE PRECISION',
length: false,
collation: false,
unsigned: false,
zerofill: false
}
]
},
{
group: 'string',
types: [
{
name: 'CHAR',
length: true,
collation: true,
unsigned: false,
zerofill: false
},
{
name: 'VARCHAR',
length: true,
collation: true,
unsigned: false,
zerofill: false
},
{
name: 'BLOB-TEXT',
length: false,
collation: true,
unsigned: false,
zerofill: false
}
]
},
{
group: 'binary',
types: [
{
name: 'BLOB',
length: false,
collation: false,
unsigned: false,
zerofill: false
},
{
name: 'CHAR-BINARY',
length: false,
collation: false,
unsigned: false,
zerofill: false
}
]
},
{
group: 'time',
types: [
{
name: 'DATE',
length: false,
collation: false,
unsigned: false,
zerofill: false
},
{
name: 'TIME',
length: true,
collation: false,
unsigned: false,
zerofill: false
},
{
name: 'TIMESTAMP',
length: false,
collation: false,
unsigned: false,
zerofill: false
}
]
}
] as TypesGroup[];

View File

@@ -1,6 +1,4 @@
import { TypesGroup } from 'common/interfaces/antares';
export default [
module.exports = [
{
group: 'integer',
types: [
@@ -54,7 +52,6 @@ export default [
{
name: 'FLOAT',
length: true,
scale: true,
collation: false,
unsigned: false,
zerofill: false
@@ -309,4 +306,4 @@ export default [
}
]
}
] as TypesGroup[];
];

View File

@@ -1,6 +1,4 @@
import { TypesGroup } from 'common/interfaces/antares';
export default [
module.exports = [
{
group: 'integer',
types: [
@@ -66,7 +64,7 @@ export default [
group: 'monetary',
types: [
{
name: 'MONEY',
name: 'money',
length: false,
unsigned: true
}
@@ -292,4 +290,4 @@ export default [
}
]
}
] as TypesGroup[];
];

View File

@@ -1,25 +1,16 @@
import { TypesGroup } from 'common/interfaces/antares';
export default [
module.exports = [
{
group: 'integer',
types: [
{
name: 'INT',
length: 10,
collation: false,
unsigned: true,
zerofill: true
},
{
name: 'INTEGER',
length: true,
collation: false,
unsigned: true,
zerofill: true
},
{
name: 'INTEGER UNSIGNED',
name: 'INTEGER',
length: true,
collation: false,
unsigned: true,
@@ -143,4 +134,4 @@ export default [
}
]
}
] as TypesGroup[];
];

View File

@@ -10,8 +10,7 @@ export const LONG_TEXT = [
'MEDIUMTEXT',
'LONGTEXT',
'JSON',
'VARBINARY',
'BLOB-TEXT'
'VARBINARY'
];
export const ARRAY = [
@@ -30,14 +29,14 @@ export const NUMBER = [
'SMALLINT',
'MEDIUMINT',
'BIGINT',
'DECIMAL',
'NUMERIC',
'INTEGER',
'SMALLSERIAL',
'SERIAL',
'BIGSERIAL',
'OID',
'XID',
'INT64'
'XID'
];
export const FLOAT = [
@@ -49,12 +48,6 @@ export const FLOAT = [
'MONEY'
];
export const IS_BIGINT = [
'BIGINT',
'BIGSERIAL',
'DOUBLE PRECISION'
];
export const BOOLEAN = [
'BOOL',
'BOOLEAN'
@@ -85,9 +78,7 @@ export const BLOB = [
'TINYBLOB',
'MEDIUMBLOB',
'LONGBLOB',
'LONG_BLOB',
'BYTEA',
'CHAR-BINARY'
'BYTEA'
];
export const BIT = [
@@ -95,14 +86,6 @@ export const BIT = [
'BIT VARYING'
];
export const BINARY = [
'BINARY'
];
export const UUID = [
'UUID'
];
export const SPATIAL = [
'POINT',
'LINESTRING',

View File

@@ -0,0 +1,6 @@
module.exports = [
'PRIMARY',
'INDEX',
'UNIQUE',
'FULLTEXT'
];

View File

@@ -0,0 +1,5 @@
module.exports = [
'PRIMARY',
'INDEX',
'UNIQUE'
];

View File

@@ -0,0 +1,5 @@
module.exports = [
'PRIMARY',
'INDEX',
'UNIQUE'
];

View File

@@ -1,40 +1,30 @@
import SSHConfig from '@fabio286/ssh2-promise/lib/sshConfig';
import * as mysql from 'mysql2/promise';
import * as pg from 'pg';
import { FirebirdSQLClient } from 'src/main/libs/clients/FirebirdSQLClient';
import MysqlExporter from 'src/main/libs/exporters/sql/MysqlExporter';
import PostgreSQLExporter from 'src/main/libs/exporters/sql/PostgreSQLExporter';
import MySQLImporter from 'src/main/libs/importers/sql/MySQLlImporter';
import PostgreSQLImporter from 'src/main/libs/importers/sql/PostgreSQLImporter';
import SSHConfig from 'ssh2-promise/lib/sshConfig';
import { MySQLClient } from '../../main/libs/clients/MySQLClient';
import { PostgreSQLClient } from '../../main/libs/clients/PostgreSQLClient';
import { SQLiteClient } from '../../main/libs/clients/SQLiteClient';
export type Client = MySQLClient | PostgreSQLClient | SQLiteClient | FirebirdSQLClient
export type ClientCode = 'mysql' | 'maria' | 'pg' | 'sqlite' | 'firebird'
export type Client = MySQLClient | PostgreSQLClient | SQLiteClient
export type ClientCode = 'mysql' | 'maria' | 'pg' | 'sqlite'
export type Exporter = MysqlExporter | PostgreSQLExporter
export type Importer = MySQLImporter | PostgreSQLImporter
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export interface IpcResponse<T = any> {
status: 'success' | 'error' | 'abort';
response?: T;
}
/**
* Pasameters needed to create a new Antares connection to a database
*/
export interface ClientParams {
client: ClientCode;
uid?: string;
params:
mysql.ConnectionOptions & {schema: string; ssl?: mysql.SslOptions; ssh?: SSHConfig; readonly: boolean}
| pg.ClientConfig & {schema: string; ssl?: mysql.SslOptions; ssh?: SSHConfig; readonly: boolean}
| { databasePath: string; readonly: boolean };
poolSize?: number;
logger?: () => void;
querySplitter?: (sql: string, clieng?: string) => string[];
}
/**
@@ -53,12 +43,10 @@ export interface ConnectionParams {
password: string;
ask: boolean;
readonly: boolean;
singleConnectionMode: boolean;
ssl: boolean;
cert?: string;
key?: string;
ca?: string;
connString?: string;
untrustedConnection: boolean;
ciphers?: string;
ssh: boolean;
@@ -68,7 +56,6 @@ export interface ConnectionParams {
sshKey?: string;
sshPort?: number;
sshPassphrase?: string;
sshKeepAliveInterval?: number;
}
export interface TypeInformations {
@@ -80,32 +67,12 @@ export interface TypeInformations {
zerofill: boolean;
}
export interface TypesGroup {
group: string;
types: TypeInformations[];
}
// Tables
export interface TableInfos {
name: string;
type: string;
rows: number;
engine: string;
comment: string;
size: number | false;
collation: string;
autoIncrement?: boolean;
}
export type TableOptions = Partial<TableInfos>;
export interface TableField {
// eslint-disable-next-line camelcase
_antares_id?: string;
name: string;
key: string;
type: string;
schema: string;
table?: string;
numPrecision?: number;
numLength?: number;
datePrecision?: number;
@@ -115,8 +82,7 @@ export interface TableField {
unsigned?: boolean;
zerofill?: boolean;
order?: number;
default?: string;
defaultType?: string;
default?: number | string;
enumValues?: string;
charset?: string;
collation?: string;
@@ -126,16 +92,9 @@ export interface TableField {
comment?: string;
after?: string;
orgName?: string;
length?: number | false;
alias: string;
tableAlias: string;
orgTable: string;
key?: 'pri' | 'uni' | '';
}
export interface TableIndex {
// eslint-disable-next-line camelcase
_antares_id?: string;
name: string;
fields: string[];
type: string;
@@ -148,8 +107,6 @@ export interface TableIndex {
}
export interface TableForeign {
// eslint-disable-next-line camelcase
_antares_id?: string;
constraintName: string;
refSchema: string;
table: string;
@@ -161,11 +118,13 @@ export interface TableForeign {
oldName?: string;
}
export interface TableCheck {
// eslint-disable-next-line camelcase
_antares_id?: string;
export interface TableOptions {
name: string;
clause: string;
type?: 'table' | 'view';
engine?: string;
comment?: string;
collation?: string;
autoIncrement?: number;
}
export interface CreateTableParams {
@@ -175,7 +134,6 @@ export interface CreateTableParams {
fields: TableField[];
foreigns: TableForeign[];
indexes: TableIndex[];
checks?: TableCheck[];
options: TableOptions;
}
@@ -203,16 +161,10 @@ export interface AlterTableParams {
changes: TableForeign[];
deletions: TableForeign[];
};
checkChanges?: {
additions: TableCheck[];
changes: TableCheck[];
deletions: TableCheck[];
};
options: TableOptions;
}
// Views
export type ViewInfos = TableInfos
export interface CreateViewParams {
schema: string;
name: string;
@@ -228,19 +180,6 @@ export interface AlterViewParams extends CreateViewParams {
}
// Triggers
export interface TriggerInfos {
name: string;
statement: string;
timing: string;
definer: string;
event: string;
table: string;
sqlMode: string;
created: Date;
charset: string;
enabled?: boolean;
}
export interface CreateTriggerParams {
definer?: string;
schema: string;
@@ -256,38 +195,13 @@ export interface AlterTriggerParams extends CreateTriggerParams {
}
// Routines & Functions
export interface FunctionParam {
// eslint-disable-next-line camelcase
_antares_id: string;
context: string;
name: string;
type: string;
length: number;
}
export interface RoutineInfos {
name: string;
type?: string;
definer: string;
created?: string;
sql?: string;
updated?: string;
comment?: string;
charset?: string;
security?: string;
language?: string;
dataAccess?: string;
deterministic?: boolean;
parameters?: FunctionParam[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
returns?: any;
returnsLength?: number;
}
export type FunctionInfos = RoutineInfos
export type TriggerFunctionInfos = FunctionInfos
export interface CreateRoutineParams {
name: string;
parameters?: FunctionParam[];
@@ -325,7 +239,7 @@ export interface AlterFunctionParams extends CreateFunctionParams {
}
// Events
export interface EventInfos {
export interface CreateEventParams {
definer?: string;
schema: string;
name: string;
@@ -334,39 +248,16 @@ export interface EventInfos {
starts: string;
ends: string;
at: string;
preserve: boolean;
preserve: string;
state: string;
comment: string;
enabled?: boolean;
sql: string;
}
export type CreateEventParams = EventInfos;
export interface AlterEventParams extends CreateEventParams {
oldName?: string;
}
// Schema
export interface SchemaInfos {
name: string;
size: number;
tables: TableInfos[];
functions: FunctionInfos[];
procedures: RoutineInfos[];
triggers: TriggerInfos[];
schedulers: EventInfos[];
}
export interface CollationInfos {
charset: string;
collation: string;
compiled: boolean;
default: boolean;
id: string | number;
sortLen: number;
}
// Query
export interface QueryBuilderObject {
schema: string;
@@ -379,7 +270,8 @@ export interface QueryBuilderObject {
offset: number;
join: string[];
update: string[];
insert: Record<string, string | boolean | number>[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
insert: {[key: string]: any}[];
delete: boolean;
}
@@ -393,10 +285,17 @@ export interface QueryParams {
tabUid?: string;
}
/**
* @deprecated Use TableFIeld
*/
export type QueryField = TableField
export interface QueryField {
name: string;
alias: string;
orgName: string;
schema: string;
table: string;
tableAlias: string;
orgTable: string;
type: string;
length: number;
}
export interface QueryForeign {
schema: string;

View File

@@ -1,106 +0,0 @@
import { TypesGroup } from './antares';
import { TableFilterOperator } from './tableApis';
export interface Customizations {
// Defaults
defaultPort?: number;
defaultUser?: string;
defaultDatabase?: string;
dataTypes?: TypesGroup[];
indexTypes?: string[];
foreignActions?: string[];
operators?: TableFilterOperator[];
// Core
database?: boolean;
collations?: boolean;
engines?: boolean;
connectionSchema?: boolean;
sslConnection?: boolean;
sshConnection?: boolean;
fileConnection?: boolean;
cancelQueries?: boolean;
singleConnectionMode?: boolean;
// Tools
processesList?: boolean;
usersManagement?: boolean;
variables?: boolean;
// Structure
schemas?: boolean;
tables?: boolean;
views?: boolean;
materializedViews?: boolean;
triggers?: boolean;
triggerFunctions?: boolean;
routines?: boolean;
functions?: boolean;
schedulers?: boolean;
// Misc
elementsWrapper: string;
stringsWrapper: string;
tableAdd?: boolean;
tableSettings?: boolean;
tableDuplicate?: boolean;
tableArray?: boolean;
tableRealCount?: boolean;
tableTruncateDisableFKCheck?: boolean;
tableCheck?: boolean;
tableDdl?: boolean;
viewAdd?: boolean;
viewSettings?: boolean;
materializedViewAdd?: boolean;
materializedViewSettings?: boolean;
triggerAdd?: boolean;
triggerFunctionAdd?: boolean;
routineAdd?: boolean;
functionAdd?: boolean;
schedulerAdd?: boolean;
databaseEdit?: boolean;
schemaEdit?: boolean;
schemaDrop?: boolean;
schemaExport?: boolean;
exportByChunks?: boolean;
schemaImport?: boolean;
triggerSettings?: boolean;
triggerFunctionSettings?: boolean;
routineSettings?: boolean;
functionSettings?: boolean;
schedulerSettings?: boolean;
indexes?: boolean;
foreigns?: boolean;
sortableFields?: boolean;
unsigned?: boolean;
nullable?: boolean;
nullablePrimary?: boolean;
zerofill?: boolean;
autoIncrement?: boolean;
comment?: boolean;
collation?: boolean;
definer?: boolean;
onUpdate?: boolean;
viewAlgorithm?: boolean;
viewSqlSecurity?: boolean;
viewUpdateOption?: boolean;
procedureDeterministic?: boolean;
procedureDataAccess?: boolean;
procedureSql?: string;
procedureContext?: boolean;
procedureContextValues?: string[];
procedureLanguage?: boolean;
functionDeterministic?: boolean;
functionDataAccess?: boolean;
functionSql?: string;
functionContext?: boolean;
functionLanguage?: boolean;
triggerSql?: string;
triggerStatementInCreation?: boolean;
triggerMultipleEvents?: boolean;
triggerTableInName?: boolean;
triggerUpdateColumns?: boolean;
triggerOnlyRename?: boolean;
triggerEnableDisable?: boolean;
triggerFunctionSql?: string;
triggerFunctionlanguages?: string[];
parametersLength?: boolean;
languages?: string[];
readOnlyMode?: boolean;
}

View File

@@ -7,13 +7,13 @@ export interface TableParams {
export interface ExportOptions {
schema: string;
tables: {
table: string;
includeStructure: boolean;
includeContent: boolean;
includeDropStatement: boolean;
}[];
includes: Record<string, boolean>;
includes: {
functions: boolean;
views: boolean;
triggers: boolean;
routines: boolean;
schedulers: boolean;
};
outputFormat: 'sql' | 'sql.zip';
outputFile: string;
sqlInsertAfter: number;

View File

View File

@@ -1,50 +1,20 @@
import { UsableLocale } from '@faker-js/faker';
export interface TableUpdateParams {
uid: string;
schema: string;
table: string;
primary?: string;
id: number | string;
content: number | string | boolean | Date | Blob | null;
type: string;
field: string;
}
export interface TableDeleteParams {
uid: string;
schema: string;
table: string;
primary?: string;
field: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
rows: Record<string, any>;
}
export type TableFilterOperator = '=' | '!=' | '>' | '<' | '>=' | '<=' | 'IN' | 'NOT IN' | 'LIKE' | 'NOT LIKE' | 'RLIKE' | 'NOT RLIKE' | 'BETWEEN' | 'IS NULL' | 'IS NOT NULL'
export interface TableFilterClausole {
active: boolean;
field: string;
op:TableFilterOperator;
value: '';
value2: '';
}
export interface InsertRowsParams {
uid: string;
schema: string;
table: string;
row: Record<string, {
group: string;
method: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
params: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any;
length: number;
}>;
row: {[key: string]: {
group: string;
method: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
params: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any;
length: number;
};
};
repeat: number;
fields: Record<string, string>;
fields: {[key: string]: string};
locale: UsableLocale;
}

View File

@@ -0,0 +1,7 @@
'use strict';
export function bufferToBase64 (buf) {
const binstr = Array.prototype.map.call(buf, ch => {
return String.fromCharCode(ch);
}).join('');
return btoa(binstr);
}

View File

@@ -1,6 +0,0 @@
export function bufferToBase64 (buf: Buffer) {
const binstr = Array.prototype.map.call(buf, (ch: number) => {
return String.fromCharCode(ch);
}).join('');
return Buffer.from(binstr, 'binary').toString('base64');
}

View File

@@ -1,28 +0,0 @@
import * as crypto from 'crypto';
const algorithm = 'aes-256-gcm';
function encrypt (text: string, password: string) {
const iv = crypto.randomBytes(16);
const key = crypto.scryptSync(password, 'antares', 32);
const cipher = crypto.createCipheriv(algorithm, key, iv);
const encrypted = Buffer.concat([cipher.update(text), cipher.final()]);
const authTag = cipher.getAuthTag();
return {
iv: iv.toString('hex'),
authTag: authTag.toString('hex'),
content: encrypted.toString('hex')
};
}
function decrypt (hash: { iv: string; content: string; authTag: string }, password: string) {
const key = crypto.scryptSync(password, 'antares', 32);
const decipher = crypto.createDecipheriv(algorithm, key, Buffer.from(hash.iv, 'hex'));
decipher.setAuthTag(Buffer.from(hash.authTag, 'hex'));
const decrpyted = decipher.update(hash.content, 'hex', 'utf8') + decipher.final('utf8');
return decrpyted;
}
export { decrypt, encrypt };

View File

@@ -1,17 +0,0 @@
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,4 +1,5 @@
export function formatBytes (bytes: number, decimals = 2) {
'use strict';
export function formatBytes (bytes, decimals = 2) {
if (bytes === 0) return '0 Bytes';
const k = 1024;

View File

@@ -0,0 +1,10 @@
/**
*
* @param {any[]} array
* @returns {number}
*/
export function getArrayDepth (array) {
return Array.isArray(array)
? 1 + Math.max(0, ...array.map(getArrayDepth))
: 0;
}

View File

@@ -1,6 +0,0 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
export function getArrayDepth (array: any[]): number {
return Array.isArray(array)
? 1 + Math.max(0, ...array.map(getArrayDepth))
: 0;
}

View File

@@ -1,3 +1,5 @@
'use strict';
const lookup = {
0: '0000',
1: '0001',
@@ -21,11 +23,15 @@ const lookup = {
D: '1101',
E: '1110',
F: '1111'
} as const;
};
export type HexChar = keyof typeof lookup
export default function hexToBinary (hex: HexChar[]) {
/**
* Converts hexadecimal string to binary string
*
* @param {string} hex Hexadecimal string
* @returns {string} Binary string
*/
export default function hexToBinary (hex) {
let binary = '';
for (let i = 0; i < hex.length; i++)
binary += lookup[hex[i]];

View File

@@ -1,190 +0,0 @@
import { match } from 'ciaplu';
function isJSON (str: string) {
try {
if (!['{', '['].includes(str.trim()[0]))
return false;
JSON.parse(str);
return true;
}
catch (_) {
return false;
}
}
function isHTML (str: string) {
const tags = [
'a',
'abbr',
'address',
'area',
'article',
'aside',
'audio',
'b',
'base',
'bdi',
'bdo',
'blockquote',
'body',
'br',
'button',
'canvas',
'caption',
'cite',
'code',
'col',
'colgroup',
'data',
'datalist',
'dd',
'del',
'details',
'dfn',
'dialog',
'div',
'dl',
'dt',
'em',
'embed',
'fieldset',
'figcaption',
'figure',
'footer',
'form',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'head',
'header',
'hgroup',
'hr',
'html',
'i',
'iframe',
'img',
'input',
'ins',
'kbd',
'label',
'legend',
'li',
'link',
'main',
'map',
'mark',
'math',
'menu',
'menuitem',
'meta',
'meter',
'nav',
'noscript',
'object',
'ol',
'optgroup',
'option',
'output',
'p',
'param',
'picture',
'pre',
'progress',
'q',
'rb',
'rp',
'rt',
'rtc',
'ruby',
's',
'samp',
'script',
'section',
'select',
'slot',
'small',
'source',
'span',
'strong',
'style',
'sub',
'summary',
'sup',
'svg',
'table',
'tbody',
'td',
'template',
'textarea',
'tfoot',
'th',
'thead',
'time',
'title',
'tr',
'track',
'u',
'ul',
'var',
'video',
'wbr'
];
const doc = new DOMParser().parseFromString(str, 'text/html');
const lowerStr = str.toLowerCase();
if (Array.from(doc.body.childNodes).some(node => node.nodeType === 1))
return tags.some((tag) => lowerStr.includes(`<${tag}>`));
return false;
}
function isSVG (str: string) {
const doc = new DOMParser().parseFromString(str, 'text/xml');
const lowerStr = str.toLowerCase();
const errorNode = doc.querySelector('parsererror');
if (!errorNode)
return lowerStr.includes('<svg');
return false;
}
function isXML (str: string) {
const doc = new DOMParser().parseFromString(str, 'text/xml');
const errorNode = doc.querySelector('parsererror');
return !errorNode;
}
function isMD (str: string) {
const mdChecks = [
'# ',
'`',
'- ',
'+ ',
'* ',
'1. ',
'**',
'__',
'~~',
'>> ',
'](http',
'![',
'[ ]',
'[x]'
];
return mdChecks.some((tag) => str.includes(tag));
}
export function langDetector (str: string) {
return match(str)
.when(() => !str || !str.trim().length, () => 'text')
.when(isJSON, () => 'json')
.when(isHTML, () => 'html')
.when(isSVG, () => 'svg')
.when(isXML, () => 'xml')
.when(isMD, () => 'markdown')
.otherwise(() => 'text')
.return();
}

View File

@@ -0,0 +1,46 @@
'use strict';
export function mimeFromHex (hex) {
switch (hex.substring(0, 4)) { // 2 bytes
case '424D':
return { ext: 'bmp', mime: 'image/bmp' };
case '1F8B':
return { ext: 'tar.gz', mime: 'application/gzip' };
case '0B77':
return { ext: 'ac3', mime: 'audio/vnd.dolby.dd-raw' };
case '7801':
return { ext: 'dmg', mime: 'application/x-apple-diskimage' };
case '4D5A':
return { ext: 'exe', mime: 'application/x-msdownload' };
case '1FA0':
case '1F9D':
return { ext: 'Z', mime: 'application/x-compress' };
default:
switch (hex.substring(0, 6)) { // 3 bytes
case 'FFD8FF':
return { ext: 'jpg', mime: 'image/jpeg' };
case '4949BC':
return { ext: 'jxr', mime: 'image/vnd.ms-photo' };
case '425A68':
return { ext: 'bz2', mime: 'application/x-bzip2' };
default:
switch (hex) { // 4 bytes
case '89504E47':
return { ext: 'png', mime: 'image/png' };
case '47494638':
return { ext: 'gif', mime: 'image/gif' };
case '25504446':
return { ext: 'pdf', mime: 'application/pdf' };
case '504B0304':
return { ext: 'zip', mime: 'application/zip' };
case '425047FB':
return { ext: 'bpg', mime: 'image/bpg' };
case '4D4D002A':
return { ext: 'tif', mime: 'image/tiff' };
case '00000100':
return { ext: 'ico', mime: 'image/x-icon' };
default:
return { ext: '', mime: 'unknown ' + hex };
}
}
}
}

View File

@@ -1,25 +0,0 @@
import { match } from 'ciaplu';
export function mimeFromHex (hex: string) {
return match(hex.substring(0, 4)) // 2 bytes
.with('424D', () => ({ ext: 'bmp', mime: 'image/bmp' }))
.with('1F8B', () => ({ ext: 'tar.gz', mime: 'application/gzip' }))
.with('0B77', () => ({ ext: 'ac3', mime: 'audio/vnd.dolby.dd-raw' }))
.with('7801', () => ({ ext: 'dmg', mime: 'application/x-apple-diskimage' }))
.with('4D5A', () => ({ ext: 'exe', mime: 'application/x-msdownload' }))
.when((val) => ['1FA0', '1F9D'].includes(val), () => ({ ext: 'Z', mime: 'application/x-compress' }))
.extracting(() => hex.substring(0, 6)) // 3 bytes
.with('FFD8FF', () => ({ ext: 'jpg', mime: 'image/jpeg' }))
.with('4949BC', () => ({ ext: 'jxr', mime: 'image/vnd.ms-photo' }))
.with('425A68', () => ({ ext: 'bz2', mime: 'application/x-bzip2' }))
.extracting(() => hex) // 4 bytes
.with('89504E47', () => ({ ext: 'png', mime: 'image/png' }))
.with('47494638', () => ({ ext: 'gif', mime: 'image/gif' }))
.with('25504446', () => ({ ext: 'pdf', mime: 'application/pdf' }))
.with('504B0304', () => ({ ext: 'zip', mime: 'application/zip' }))
.with('425047FB', () => ({ ext: 'bpg', mime: 'image/bpg' }))
.with('4D4D002A', () => ({ ext: 'tif', mime: 'image/tiff' }))
.with('00000100', () => ({ ext: 'ico', mime: 'image/x-icon' }))
.otherwise(() => ({ ext: '', mime: 'unknown ' + hex }))
.return();
}

View File

@@ -1,86 +0,0 @@
import { ClientCode } from 'common/interfaces/antares';
export const querySplitter =(sql: string, dbType: ClientCode): string[] => {
const queries: string[] = [];
let currentQuery = '';
let insideBlock = false;
let insideString = false;
let stringDelimiter: string | null = null;
let insideDollarTag = false;
let dollarTagDelimiter: string | null = null;
// Regex patterns for BEGIN-END blocks, dollar tags in PostgreSQL, and semicolons
const beginRegex = /\bBEGIN\b/i;
const endRegex = /\bEND\b;/i;
const dollarTagRegex = /\$(\w+)?\$/; // Matches $tag$ or $$
// Split on semicolons, keeping semicolons attached to the lines
const lines = sql.split(/(?<=;)/);
for (let line of lines) {
line = line.trim();
if (!line) continue;
for (let i = 0; i < line.length; i++) {
const char = line[i];
// Handle string boundaries
if ((char === '\'' || char === '"') && (!insideString || char === stringDelimiter)) {
if (!insideString) {
insideString = true;
stringDelimiter = char;
}
else {
insideString = false;
stringDelimiter = null;
}
}
currentQuery += char;
if (dbType === 'pg') {
// Handle dollar-quoted blocks in PostgreSQL
if (!insideString && line.slice(i).match(dollarTagRegex)) {
const match = line.slice(i).match(dollarTagRegex);
if (match) {
const tag = match[0];
if (!insideDollarTag) {
insideDollarTag = true;
dollarTagDelimiter = tag;
currentQuery += tag;
i += tag.length - 1;
}
else if (dollarTagDelimiter === tag) {
insideDollarTag = false;
dollarTagDelimiter = null;
currentQuery += tag;
i += tag.length - 1;
}
}
}
}
// Check BEGIN-END blocks
if (!insideString && !insideDollarTag) {
if (beginRegex.test(line))
insideBlock = true;
if (insideBlock && endRegex.test(line))
insideBlock = false;
}
}
// Append the query if we encounter a semicolon outside a BEGIN-END block, outside a string, and outside dollar tags
if (!insideBlock && !insideString && !insideDollarTag && /;\s*$/.test(line)) {
queries.push(currentQuery.trim());
currentQuery = '';
}
}
// Add any remaining query
if (currentQuery.trim())
queries.push(currentQuery.trim());
return queries;
};

View File

@@ -0,0 +1,20 @@
/* eslint-disable no-useless-escape */
// eslint-disable-next-line no-control-regex
const pattern = /[\0\x08\x09\x1a\n\r"'\\\%]/gm;
const regex = new RegExp(pattern);
/**
* Escapes a string
*
* @param {String} string
* @returns {String}
*/
function sqlEscaper (string) {
return string.replace(regex, char => {
const m = ['\\0', '\\x08', '\\x09', '\\x1a', '\\n', '\\r', '\'', '\"', '\\', '\\\\', '%'];
const r = ['\\\\0', '\\\\b', '\\\\t', '\\\\z', '\\\\n', '\\\\r', '\\\'', '\\\"', '\\\\', '\\\\\\\\', '\%'];
return r[m.indexOf(char)] || char;
});
}
export { sqlEscaper };

View File

@@ -1,229 +0,0 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-useless-escape */
import { lineString, point, polygon } from '@turf/helpers';
import { BIT, BLOB, DATE, DATETIME, FLOAT, IS_MULTI_SPATIAL, NUMBER, SPATIAL, TEXT_SEARCH } from 'common/fieldTypes';
import * as antares from 'common/interfaces/antares';
import * as moment from 'moment';
import customizations from '../customizations';
import { ClientCode } from '../interfaces/antares';
import { getArrayDepth } from './getArrayDepth';
import hexToBinary, { HexChar } from './hexToBinary';
/**
* Escapes a string fo SQL use
*
* @param { String } string
* @returns { String } Escaped string
*/
export const sqlEscaper = (string: string): string => {
// eslint-disable-next-line no-control-regex
const pattern = /[\0\x08\x09\x1a\n\r"'\\\%]/gm;
const regex = new RegExp(pattern);
return string.replace(regex, char => {
const m = ['\\0', '\\x08', '\\x09', '\\x1a', '\\n', '\\r', '\'', '\"', '\\', '\\\\', '%'];
const r = ['\\\\0', '\\\\b', '\\\\t', '\\\\z', '\\\\n', '\\\\r', '\\\'', '\\\"', '\\\\', '\\\\\\\\', '\%'];
return r[m.indexOf(char)] || char;
});
};
export const objectToGeoJSON = (val: any) => {
if (Array.isArray(val)) {
if (getArrayDepth(val) === 1)
return lineString(val.reduce((acc, curr) => [...acc, [curr.x, curr.y]], []));
else
return polygon(val.map(arr => arr.reduce((acc: any, curr: any) => [...acc, [curr.x, curr.y]], [])));
}
else
return point([val.x, val.y]);
};
export const escapeAndQuote = (val: string, client: ClientCode) => {
const { stringsWrapper: sw } = customizations[client];
// eslint-disable-next-line no-control-regex
const CHARS_TO_ESCAPE = sw === '"' ? /[\0\b\t\n\r\x1a"'\\]/g : /[\0\b\t\n\r\x1a'\\]/g;
const CHARS_ESCAPE_MAP: Record<string, string> = {
'\0': '\\0',
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\r': '\\r',
'\x1a': '\\Z',
'\'': '\\\'',
'\\': '\\\\'
};
if (sw === '"')
CHARS_ESCAPE_MAP['"'] = '\\"';
let chunkIndex = CHARS_TO_ESCAPE.lastIndex = 0;
let escapedVal = '';
let match;
while ((match = CHARS_TO_ESCAPE.exec(val))) {
escapedVal += val.slice(chunkIndex, match.index) + CHARS_ESCAPE_MAP[match[0]];
chunkIndex = CHARS_TO_ESCAPE.lastIndex;
}
if (chunkIndex === 0)
return `${sw}${val}${sw}`;
if (chunkIndex < val.length)
return `${sw}${escapedVal + val.slice(chunkIndex)}${sw}`;
return `${sw}${escapedVal}${sw}`;
};
export const valueToSqlString = (args: {
val: any;
client: ClientCode;
field: {type: string; datePrecision?: number; precision?: number | false; isArray?: boolean};
}): string => {
let parsedValue;
const { val, client, field } = args;
const { stringsWrapper: sw } = customizations[client];
if (val === null)
parsedValue = 'NULL';
else if (DATE.includes(field.type)) {
parsedValue = moment(val).isValid()
? escapeAndQuote(moment(val).format('YYYY-MM-DD'), client)
: val;
}
else if (DATETIME.includes(field.type)) {
let datePrecision = '';
for (let i = 0; i < field.datePrecision; i++)
datePrecision += i === 0 ? '.S' : 'S';
parsedValue = moment(val).isValid()
? escapeAndQuote(moment(val).format(`YYYY-MM-DD HH:mm:ss${datePrecision}`), client)
: escapeAndQuote(val, client);
}
else if ('isArray' in field && field.isArray) {
let localVal;
if (Array.isArray(val)) {
localVal = JSON
.stringify(val)
.replaceAll('[', '{')
.replaceAll(']', '}');
}
else {
localVal = typeof val === 'string'
? val
.replaceAll('[', '{')
.replaceAll(']', '}')
: '';
}
parsedValue = `'${localVal}'`;
}
else if (TEXT_SEARCH.includes(field.type))
parsedValue = `'${val.replaceAll('\'', '\'\'')}'`;
else if (BIT.includes(field.type))
parsedValue = `b'${hexToBinary(Buffer.from(new Uint8Array(Object.values(val))).toString('hex') as undefined as HexChar[])}'`;
else if (BLOB.includes(field.type)) {
let buffer: Buffer;
if (val instanceof Uint8Array)
buffer = Buffer.from(val);
else
buffer = val;
if (['mysql', 'maria'].includes(client))
parsedValue = `X'${buffer.toString('hex').toUpperCase()}'`;
else if (client === 'pg')
parsedValue = `decode('${buffer.toString('hex').toUpperCase()}', 'hex')`;
}
else if (NUMBER.includes(field.type))
parsedValue = val;
else if (FLOAT.includes(field.type))
parsedValue = parseFloat(val);
else if (SPATIAL.includes(field.type)) {
let geoJson;
if (IS_MULTI_SPATIAL.includes(field.type)) {
const features = [];
for (const element of val)
features.push(objectToGeoJSON(element));
geoJson = {
type: 'FeatureCollection',
features
};
}
else
geoJson = objectToGeoJSON(val);
parsedValue = `ST_GeomFromGeoJSON('${JSON.stringify(geoJson)}')`;
}
else if (val === '') parsedValue = `${sw}${sw}`;
else {
parsedValue = typeof val === 'string'
? escapeAndQuote(val, client)
: typeof val === 'object'
? escapeAndQuote(JSON.stringify(val), client)
: val;
}
return parsedValue;
};
export const jsonToSqlInsert = (args: {
json: Record<string, any>[];
client: ClientCode;
fields: Record<string, {type: string; datePrecision: number}>;
table: string;
options?: {sqlInsertAfter: number; sqlInsertDivider: 'bytes' | 'rows'};
}) => {
const { client, json, fields, table, options } = args;
const sqlInsertAfter = options && options.sqlInsertAfter ? options.sqlInsertAfter : 1;
const sqlInsertDivider = options && options.sqlInsertDivider ? options.sqlInsertDivider : 'rows';
const { elementsWrapper: ew } = customizations[client];
const fieldNames = Object.keys(json[0]).map(key => `${ew}${key.split('.').pop()}${ew}`);
let insertStmt = `INSERT INTO ${ew}${table}${ew} (${fieldNames.join(', ')}) VALUES `;
let insertsString = '';
let queryLength = 0;
let rowsWritten = 0;
for (const row of json) {
const values = [];
values.push(Object.keys(row).map(key => (
valueToSqlString({ val: row[key], client, field: fields[key] })
)));
if (
(sqlInsertDivider === 'bytes' && queryLength >= sqlInsertAfter * 1024) ||
(sqlInsertDivider === 'rows' && rowsWritten === sqlInsertAfter)
) {
insertsString += insertStmt+';';
insertStmt = `\nINSERT INTO ${ew}${table}${ew} (${fieldNames.join(', ')}) VALUES `;
rowsWritten = 0;
}
rowsWritten++;
if (rowsWritten > 1) insertStmt += ',\n';
insertStmt += `(${values.join(',')})`;
queryLength = insertStmt.length;
}
if (rowsWritten > 0)
insertsString += insertStmt+';';
return insertsString;
};
export const formatJsonForSqlWhere = (jsonValue: object, clientType: antares.ClientCode) => {
const formattedValue = JSON.stringify(jsonValue);
switch (clientType) {
case 'mysql':
return ` = CAST('${formattedValue}' AS JSON)`;
case 'maria':
return ` = '${formattedValue}'`;
case 'pg':
return `::text = '${formattedValue}'`;
case 'firebird':
case 'sqlite':
default:
return ` = '${formattedValue}'`;
}
};

View File

@@ -0,0 +1,8 @@
/**
* @export
* @param {String} [prefix]
* @returns {String} Unique ID
*/
export function uidGen (prefix) {
return (prefix ? `${prefix}:` : '') + Math.random().toString(36).substr(2, 9).toUpperCase();
}

View File

@@ -1,3 +0,0 @@
export function uidGen (prefix?: string) {
return (prefix ? `${prefix}:` : '') + Math.random().toString(36).substring(2, 11).toUpperCase();
}

View File

@@ -1,185 +0,0 @@
export const shortcutEvents: Record<string, { i18n: string; i18nParam?: string | number; context?: 'tab' | 'main' }> = {
'run-or-reload': { i18n: 'application.runOrReload', context: 'tab' },
'open-new-tab': { i18n: 'application.openNewTab', context: 'tab' },
'close-tab': { i18n: 'application.closeTab', context: 'tab' },
'format-query': { i18n: 'database.formatQuery', context: 'tab' },
'kill-query': { i18n: 'database.killQuery', context: 'tab' },
'query-history': { i18n: 'database.queryHistory', context: 'tab' },
'clear-query': { i18n: 'database.clearQuery', context: 'tab' },
// 'save-file': { i18n: 'application.saveFile', context: 'tab' },
'open-file': { i18n: 'application.openFile', context: 'tab' },
'save-file-as': { i18n: 'application.saveFileAs', context: 'tab' },
'next-tab': { i18n: 'application.nextTab' },
'prev-tab': { i18n: 'application.previousTab' },
'open-all-connections': { i18n: 'application.openAllConnections' },
'open-filter': { i18n: 'application.openFilter' },
'next-page': { i18n: 'application.nextResultsPage' },
'prev-page': { i18n: 'application.previousResultsPage' },
'toggle-console': { i18n: 'application.toggleConsole' },
'save-content': { i18n: 'application.saveContent' },
'create-connection': { i18n: 'connection.createNewConnection' },
'open-settings': { i18n: 'application.openSettings' },
'open-scratchpad': { i18n: 'application.openNotes' },
setFullScreen: { i18n: 'application.fullScreen', context: 'main' },
setZoomIn: { i18n: 'application.zoomIn', context: 'main' },
setZoomOut: { i18n: 'application.zoomOut', context: 'main' },
setZoomReset: { i18n: 'application.zoomReset', context: 'main' }
};
interface ShortcutRecord {
event: string;
isFunction?: boolean;
keys: Electron.Accelerator[] | string[];
/** Needed for default shortcuts */
os: NodeJS.Platform[];
}
/**
* Default shortcuts
*/
const shortcuts: ShortcutRecord[] = [
{
event: 'run-or-reload',
keys: ['F5'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'setFullScreen',
isFunction: true,
keys: ['F11'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'setZoomIn',
isFunction: true,
keys: ['CommandOrControl+='],
os: ['darwin', 'linux', 'win32']
},
{
event: 'setZoomOut',
isFunction: true,
keys: ['CommandOrControl+-'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'setZoomReset',
isFunction: true,
keys: ['CommandOrControl+0'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'save-content',
keys: ['CommandOrControl+S'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'kill-query',
keys: ['CommandOrControl+K'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'format-query',
keys: ['CommandOrControl+B'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'clear-query',
keys: ['CommandOrControl+Alt+W'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'query-history',
keys: ['CommandOrControl+G'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'open-new-tab',
keys: ['CommandOrControl+T'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'close-tab',
keys: ['CommandOrControl+W'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'next-tab',
keys: ['Alt+CommandOrControl+Right'],
os: ['darwin', 'win32']
},
{
event: 'prev-tab',
keys: ['Alt+CommandOrControl+Left'],
os: ['darwin', 'win32']
},
{
event: 'next-tab',
keys: ['CommandOrControl+PageDown'],
os: ['linux', 'win32']
},
{
event: 'prev-tab',
keys: ['CommandOrControl+PageUp'],
os: ['linux', 'win32']
},
{
event: 'open-filter',
keys: ['CommandOrControl+F'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'next-page',
keys: ['CommandOrControl+Right'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'prev-page',
keys: ['CommandOrControl+Left'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'open-all-connections',
keys: ['Shift+CommandOrControl+Space'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'toggle-console',
keys: ['CommandOrControl+F12'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'toggle-console',
keys: ['CommandOrControl+`'],
os: ['darwin', 'linux', 'win32']
},
// {
// event: 'save-file',
// keys: ['CommandOrControl+S'],
// os: ['darwin', 'linux', 'win32']
// },
{
event: 'open-file',
keys: ['CommandOrControl+O'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'save-file-as',
keys: ['Shift+CommandOrControl+S'],
os: ['darwin', 'linux', 'win32']
}
];
for (let i = 1; i <= 9; i++) {
shortcutEvents[`select-tab-${i}`] = {
i18n: 'application.selectTabNumber',
i18nParam: i
};
shortcuts.push({
event: `select-tab-${i}`,
keys: [`CommandOrControl+${i}`],
os: ['darwin', 'linux', 'win32']
});
}
export { ShortcutRecord, shortcuts };

View File

@@ -1,111 +1,20 @@
import { app, dialog, ipcMain, safeStorage } from 'electron';
import * as Store from 'electron-store';
import * as fs from 'fs';
import { validateSender } from '../libs/misc/validateSender';
import { ShortcutRegister } from '../libs/ShortcutRegister';
import { app, ipcMain, dialog } from 'electron';
export default () => {
ipcMain.on('close-app', (event) => {
if (!validateSender(event.senderFrame)) {
return {
status: 'error',
response: 'Unauthorized process'
};
}
ipcMain.on('close-app', () => {
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: ''
});
try {
const encrypted = sessionStore.get('key') as string;
const key = safeStorage.decryptString(Buffer.from(encrypted, 'utf-8'));
event.returnValue = key;
}
catch (error) {
event.returnValue = false;
}
ipcMain.on('get-key', async event => {
const key = false;
event.returnValue = key;
});
ipcMain.handle('show-open-dialog', (event, options) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
return dialog.showOpenDialog(options);
});
ipcMain.handle('show-save-dialog', (event, options) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
return dialog.showSaveDialog(options);
});
ipcMain.handle('get-download-dir-path', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
ipcMain.handle('get-download-dir-path', () => {
return app.getPath('downloads');
});
ipcMain.handle('resotre-default-shortcuts', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
const shortCutRegister = ShortcutRegister.getInstance();
shortCutRegister.restoreDefaults();
});
ipcMain.handle('reload-shortcuts', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
const shortCutRegister = ShortcutRegister.getInstance();
shortCutRegister.reload();
});
ipcMain.handle('update-shortcuts', (event, shortcuts) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
const shortCutRegister = ShortcutRegister.getInstance();
shortCutRegister.updateShortcuts(shortcuts);
});
ipcMain.handle('unregister-shortcuts', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
const shortCutRegister = ShortcutRegister.getInstance();
shortCutRegister.unregister();
});
ipcMain.handle('read-file', (event, { filePath, encoding }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const content = fs.readFileSync(filePath, encoding);
return content;
}
catch (error) {
return { status: 'error', response: error.toString() };
}
});
ipcMain.handle('write-file', (event, filePath, content) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
fs.writeFileSync(filePath, content, 'utf-8');
return { status: 'success' };
}
catch (error) {
return { status: 'error', response: error.toString() };
}
});
};

View File

@@ -1,32 +1,17 @@
import * as antares from 'common/interfaces/antares';
import { ipcMain } from 'electron';
import * as fs from 'fs';
import { ipcMain } from 'electron';
import { ClientsFactory } from '../libs/ClientsFactory';
import { SslOptions } from 'mysql2';
import { ClientsFactory } from '../libs/ClientsFactory';
import { validateSender } from '../libs/misc/validateSender';
const isAborting: Record<string, boolean> = {};
export default (connections: Record<string, antares.Client>) => {
export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('test-connection', async (event, conn: antares.ConnectionParams) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
let isLocalAborted = false;
const abortChecker = setInterval(() => { // Intercepts abort request
if (isAborting[conn.uid]) {
isAborting[conn.uid] = false;
isLocalAborted = true;
clearInterval(abortChecker);
}
}, 50);
const params = {
host: conn.host,
port: +conn.port,
user: conn.user,
password: conn.password,
readonly: conn.readonly,
connectionString: conn.connString,
database: '',
schema: '',
databasePath: '',
@@ -38,7 +23,6 @@ export default (connections: Record<string, antares.Client>) => {
port: number;
privateKey: string;
passphrase: string;
keepaliveInterval: number;
}
};
@@ -64,40 +48,25 @@ export default (connections: Record<string, antares.Client>) => {
username: conn.sshUser,
password: conn.sshPass,
port: conn.sshPort ? conn.sshPort : 22,
privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : undefined,
passphrase: conn.sshPassphrase,
keepaliveInterval: conn.sshKeepAliveInterval ? conn.sshKeepAliveInterval*1000 : undefined
privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : null,
passphrase: conn.sshPassphrase
};
}
try {
const connection = await ClientsFactory.getClient({
uid: conn.uid,
client: conn.client,
params
});
await connection.connect();
if (isLocalAborted) {
connection.destroy();
return;
}
await connection.ping();
await connection.select('1+1').run();
connection.destroy();
clearInterval(abortChecker);
return { status: 'success' };
}
catch (error) {
clearInterval(abortChecker);
if (error instanceof AggregateError)
throw new Error(error.errors.reduce((acc, curr) => acc +' | '+ curr.message, ''));
else if (!isLocalAborted)
return { status: 'error', response: error.toString() };
else
return { status: 'abort', response: 'Connection aborted' };
catch (err) {
return { status: 'error', response: err.toString() };
}
});
@@ -106,17 +75,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('connect', async (event, conn: antares.ConnectionParams) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
let isLocalAborted = false;
const abortChecker = setInterval(() => { // Intercepts abort request
if (isAborting[conn.uid]) {
isAborting[conn.uid] = false;
isLocalAborted = true;
clearInterval(abortChecker);
}
}, 50);
const params = {
host: conn.host,
port: +conn.port,
@@ -124,7 +82,6 @@ export default (connections: Record<string, antares.Client>) => {
password: conn.password,
application_name: 'Antares SQL',
readonly: conn.readonly,
connectionString: conn.connString,
database: '',
schema: '',
databasePath: '',
@@ -136,7 +93,6 @@ export default (connections: Record<string, antares.Client>) => {
port: number;
privateKey: string;
passphrase: string;
keepaliveInterval: number;
}
};
@@ -166,53 +122,31 @@ export default (connections: Record<string, antares.Client>) => {
password: conn.sshPass,
port: conn.sshPort ? conn.sshPort : 22,
privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : null,
passphrase: conn.sshPassphrase,
keepaliveInterval: conn.sshKeepAliveInterval ? conn.sshKeepAliveInterval*1000 : null
passphrase: conn.sshPassphrase
};
}
try {
const connection = ClientsFactory.getClient({
uid: conn.uid,
client: conn.client,
params,
poolSize: conn.singleConnectionMode ? 0 : 5
poolSize: 5
});
await connection.connect();
if (isLocalAborted) {
connection.destroy();
return { status: 'abort', response: 'Connection aborted' };
}
const structure = await connection.getStructure(new Set());
if (isLocalAborted) {
connection.destroy();
return { status: 'abort', response: 'Connection aborted' };
}
connections[conn.uid] = connection;
clearInterval(abortChecker);
return { status: 'success', response: structure };
}
catch (err) {
clearInterval(abortChecker);
if (!isLocalAborted)
return { status: 'error', response: err.toString() };
else
return { status: 'abort', response: 'Connection aborted' };
return { status: 'error', response: err.toString() };
}
});
ipcMain.on('abort-connection', (event, uid) => {
isAborting[uid] = true;
});
ipcMain.handle('disconnect', (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
connections[uid].destroy();
delete connections[uid];
});

View File

@@ -1,18 +0,0 @@
import * as antares from 'common/interfaces/antares';
import { ipcMain } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: Record<string, antares.Client>) => {
ipcMain.handle('get-databases', async (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[uid].getDatabases();
return { status: 'success', response: result };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
};

View File

@@ -1,12 +1,8 @@
import * as antares from 'common/interfaces/antares';
import { ipcMain } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: Record<string, antares.Client>) => {
export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('get-function-informations', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[params.uid].getFunctionInformations(params);
return { status: 'success', response: result };
@@ -17,8 +13,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('drop-function', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].dropFunction(params);
return { status: 'success' };
@@ -29,8 +23,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('alter-function', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].alterFunction(params);
return { status: 'success' };
@@ -41,8 +33,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('alter-trigger-function', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].alterTriggerFunction(params);
return { status: 'success' };
@@ -53,8 +43,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('create-function', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].createFunction(params);
return { status: 'success' };
@@ -65,8 +53,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('create-trigger-function', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].createTriggerFunction(params);
return { status: 'success' };

View File

@@ -1,19 +1,18 @@
import * as antares from 'common/interfaces/antares';
import application from './application';
import connection from './connection';
import database from './database';
import functions from './functions';
import routines from './routines';
import schedulers from './schedulers';
import schema from './schema';
import tables from './tables';
import triggers from './triggers';
import updates from './updates';
import users from './users';
import views from './views';
import triggers from './triggers';
import routines from './routines';
import functions from './functions';
import schedulers from './schedulers';
import updates from './updates';
import application from './application';
import schema from './schema';
import users from './users';
const connections: Record<string, antares.Client> = {};
const connections: {[key: string]: antares.Client} = {};
export default () => {
connection(connections);
@@ -23,7 +22,6 @@ export default () => {
routines(connections);
functions(connections);
schedulers(connections);
database(connections);
schema(connections);
users(connections);
updates();

View File

@@ -1,12 +1,8 @@
import * as antares from 'common/interfaces/antares';
import { ipcMain } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: Record<string, antares.Client>) => {
export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('get-routine-informations', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[params.uid].getRoutineInformations(params);
return { status: 'success', response: result };
@@ -17,8 +13,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('drop-routine', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].dropRoutine(params);
return { status: 'success' };
@@ -29,8 +23,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('alter-routine', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].alterRoutine(params);
return { status: 'success' };
@@ -41,8 +33,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('create-routine', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].createRoutine(params);
return { status: 'success' };

View File

@@ -1,12 +1,8 @@
import * as antares from 'common/interfaces/antares';
import { ipcMain } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: Record<string, antares.Client>) => {
export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('get-scheduler-informations', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[params.uid].getEventInformations(params);
return { status: 'success', response: result };
@@ -17,8 +13,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('drop-scheduler', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].dropEvent(params);
return { status: 'success' };
@@ -29,8 +23,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('alter-scheduler', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].alterEvent(params);
return { status: 'success' };
@@ -41,8 +33,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('create-scheduler', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].createEvent(params);
return { status: 'success' };
@@ -53,8 +43,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('toggle-scheduler', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
if (!params.enabled)
await connections[params.uid].enableEvent({ ...params });

View File

@@ -1,18 +1,17 @@
import * as antares from 'common/interfaces/antares';
import * as workers from 'common/interfaces/workers';
import { dialog, ipcMain } from 'electron';
import * as fs from 'fs';
import { Worker } from 'worker_threads';
import * as path from 'path';
import { ChildProcess, fork } from 'child_process';
import { ipcMain, dialog } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
const isDevelopment = process.env.NODE_ENV !== 'production';
export default (connections: Record<string, antares.Client>) => {
let exporter: Worker = null;
let importer: Worker = null;
export default (connections: {[key: string]: antares.Client}) => {
let exporter: ChildProcess = null;
let importer: ChildProcess = null;
ipcMain.handle('create-schema', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].createSchema(params);
@@ -24,8 +23,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('update-schema', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].alterSchema(params);
@@ -37,8 +34,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('delete-schema', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].dropSchema(params);
@@ -50,8 +45,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('get-schema-collation', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const collation = await connections[params.uid].getDatabaseCollation(
params
@@ -68,10 +61,8 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('get-structure', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const structure: unknown = await connections[params.uid].getStructure(
const structure = await connections[params.uid].getStructure(
params.schemas
);
@@ -83,8 +74,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('get-collations', async (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[uid].getCollations();
@@ -96,8 +85,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('get-variables', async (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[uid].getVariables();
@@ -109,10 +96,8 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('get-engines', async (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result: unknown = await connections[uid].getEngines();
const result = await connections[uid].getEngines();
return { status: 'success', response: result };
}
@@ -122,8 +107,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('get-version', async (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[uid].getVersion();
@@ -135,8 +118,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('get-processes', async (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[uid].getProcesses();
@@ -148,8 +129,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('kill-process', async (event, { uid, pid }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[uid].killProcess(pid);
@@ -161,8 +140,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('use-schema', async (event, { uid, schema }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (!schema) return;
try {
@@ -175,8 +152,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('raw-query', async (event, { uid, query, schema, tabUid, autocommit }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (!query) return;
try {
@@ -185,7 +160,8 @@ export default (connections: Record<string, antares.Client>) => {
details: true,
schema,
tabUid,
autocommit
autocommit,
comments: false
});
return { status: 'success', response: result };
@@ -196,12 +172,7 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('export', (event, { uid, type, tables, ...rest }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (exporter !== null) {
exporter.terminate();
return;
}
if (exporter !== null) return;
return new Promise((resolve/*, reject */) => {
(async () => {
@@ -224,12 +195,11 @@ export default (connections: Record<string, antares.Client>) => {
}
}
// Init exporter thread
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
exporter = new Worker(new URL('../workers/exporter', import.meta.url));
exporter.postMessage({
// Init exporter process
exporter = fork(isDevelopment ? './dist/exporter.js' : path.resolve(__dirname, './exporter.js'), [], {
execArgv: isDevelopment ? ['--inspect=9224'] : undefined
});
exporter.send({
type: 'init',
client: {
name: type,
@@ -240,34 +210,32 @@ export default (connections: Record<string, antares.Client>) => {
});
// Exporter message listener
exporter.on('message', (message: workers.WorkerIpcMessage) => {
const { type, payload } = message;
exporter.on('message', ({ type, payload }: workers.WorkerIpcMessage) => {
switch (type) {
case 'export-progress':
event.sender.send('export-progress', payload);
break;
case 'end':
setTimeout(() => { // Ensures that writing thread has finished
exporter?.terminate();
setTimeout(() => { // Ensures that writing process has finished
exporter.kill();
exporter = null;
}, 500);
}, 2000);
resolve({ status: 'success', response: payload });
break;
case 'cancel':
exporter?.terminate();
exporter.kill();
exporter = null;
resolve({ status: 'error', response: 'Operation cancelled' });
break;
case 'error':
exporter?.terminate();
exporter.kill();
exporter = null;
resolve({ status: 'error', response: payload });
break;
}
});
exporter.on('close', code => {
exporter.on('exit', code => {
exporter = null;
resolve({ status: 'error', response: `Operation ended with code: ${code}` });
});
@@ -275,9 +243,7 @@ export default (connections: Record<string, antares.Client>) => {
});
});
ipcMain.handle('abort-export', async (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
ipcMain.handle('abort-export', async () => {
let willAbort = false;
if (exporter) {
@@ -291,7 +257,7 @@ export default (connections: Record<string, antares.Client>) => {
if (result.response === 1) {
willAbort = true;
exporter.postMessage({ type: 'cancel' });
exporter.send({ type: 'cancel' });
}
}
@@ -299,32 +265,24 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('import-sql', async (event, options) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (importer !== null) {
importer.terminate();
return;
}
if (importer !== null) return;
return new Promise((resolve/*, reject */) => {
(async () => {
const dbConfig = await connections[options.uid].getDbConfig();
// Init importer thread
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
importer = new Worker(new URL('../workers/importer', import.meta.url));
importer.postMessage({
// Init importer process
importer = fork(isDevelopment ? './dist/importer.js' : path.resolve(__dirname, './importer.js'), [], {
execArgv: isDevelopment ? ['--inspect=9224'] : undefined
});
importer.send({
type: 'init',
dbConfig,
options
});
// Importer message listener
importer.on('message', (message: workers.WorkerIpcMessage) => {
const { type, payload } = message;
importer.on('message', ({ type, payload }: workers.WorkerIpcMessage) => {
switch (type) {
case 'import-progress':
event.sender.send('import-progress', payload);
@@ -334,35 +292,28 @@ export default (connections: Record<string, antares.Client>) => {
break;
case 'end':
setTimeout(() => { // Ensures that writing process has finished
importer?.terminate();
importer?.kill();
importer = null;
}, 2000);
resolve({ status: 'success', response: payload });
break;
case 'cancel':
importer.terminate();
importer.kill();
importer = null;
resolve({ status: 'error', response: 'Operation cancelled' });
break;
case 'error':
importer.terminate();
importer.kill();
importer = null;
resolve({ status: 'error', response: payload });
break;
}
});
importer.on('close', code => {
importer = null;
resolve({ status: 'error', response: `Operation ended with code: ${code}` });
});
})();
});
});
ipcMain.handle('abort-import-sql', async (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
ipcMain.handle('abort-import-sql', async () => {
let willAbort = false;
if (importer) {
@@ -376,7 +327,7 @@ export default (connections: Record<string, antares.Client>) => {
if (result.response === 1) {
willAbort = true;
importer.postMessage({ type: 'cancel' });
importer.send({ type: 'cancel' });
}
}
@@ -384,8 +335,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('kill-tab-query', async (event, { uid, tabUid }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (!tabUid) return;
try {
@@ -398,8 +347,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('commit-tab', async (event, { uid, tabUid }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (!tabUid) return;
try {
@@ -412,8 +359,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('rollback-tab', async (event, { uid, tabUid }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (!tabUid) return;
try {
@@ -426,8 +371,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('destroy-connection-to-commit', async (event, { uid, tabUid }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (!tabUid) return;
try {

View File

@@ -1,19 +1,15 @@
import customizations from 'common/customizations';
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 { InsertRowsParams } from 'common/interfaces/tableApis';
import { fakerCustom } from 'common/libs/fakerCustom';
import { formatJsonForSqlWhere, sqlEscaper } from 'common/libs/sqlUtils';
import { ipcMain } from 'electron';
import * as fs from 'fs';
import { faker } from '@faker-js/faker';
import * as moment from 'moment';
import { sqlEscaper } from 'common/libs/sqlEscaper';
import { TEXT, LONG_TEXT, ARRAY, TEXT_SEARCH, NUMBER, FLOAT, BLOB, BIT, DATE, DATETIME } from 'common/fieldTypes';
import * as customizations from 'common/customizations';
import fs from 'fs';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: Record<string, antares.Client>) => {
export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('get-table-columns', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[params.uid].getTableColumns(params);
return { status: 'success', response: result };
@@ -24,8 +20,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('get-table-data', async (event, { uid, schema, table, limit, page, sortParams, where }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const offset = (page - 1) * limit;
const query = connections[uid]
@@ -51,8 +45,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('get-table-count', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[params.uid].getTableApproximateCount(params);
return { status: 'success', response: result };
@@ -63,8 +55,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('get-table-options', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[params.uid].getTableOptions(params);
return { status: 'success', response: result };
@@ -75,8 +65,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('get-table-indexes', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[params.uid].getTableIndexes(params);
@@ -87,35 +75,7 @@ export default (connections: Record<string, antares.Client>) => {
}
});
ipcMain.handle('get-table-checks', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[params.uid].getTableChecks(params);
return { status: 'success', response: result };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
ipcMain.handle('get-table-ddl', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[params.uid].getTableDll(params);
return { status: 'success', response: result };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
ipcMain.handle('get-key-usage', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[params.uid].getKeyUsage(params);
@@ -127,8 +87,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('update-table-cell', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
delete params.row._antares_id;
const { stringsWrapper: sw } = customizations[connections[params.uid]._client];
@@ -146,8 +104,9 @@ export default (connections: Record<string, antares.Client>) => {
escapedParam = `"${sqlEscaper(params.content)}"`;
break;
case 'pg':
escapedParam = `'${params.content.replaceAll('\'', '\'\'')}'`;
break;
case 'sqlite':
case 'firebird':
escapedParam = `'${params.content.replaceAll('\'', '\'\'')}'`;
break;
}
@@ -167,7 +126,6 @@ export default (connections: Record<string, antares.Client>) => {
escapedParam = `0x${fileBlob.toString('hex')}`;
break;
case 'pg':
case 'firebird':
fileBlob = fs.readFileSync(params.content);
escapedParam = `decode('${fileBlob.toString('hex')}', 'hex')`;
break;
@@ -185,7 +143,6 @@ export default (connections: Record<string, antares.Client>) => {
escapedParam = '\'\'';
break;
case 'pg':
case 'firebird':
escapedParam = 'decode(\'\', \'hex\')';
break;
case 'sqlite':
@@ -198,19 +155,6 @@ export default (connections: Record<string, antares.Client>) => {
escapedParam = `b'${sqlEscaper(params.content)}'`;
reload = true;
}
else if (BOOLEAN.includes(params.type)) {
switch (connections[params.uid]._client) {
case 'mysql':
case 'maria':
case 'pg':
case 'firebird':
escapedParam = params.content;
break;
case 'sqlite':
escapedParam = Number(params.content === 'true');
break;
}
}
else if (params.content === null)
escapedParam = 'NULL';
else
@@ -227,19 +171,13 @@ export default (connections: Record<string, antares.Client>) => {
}
else {
const { orgRow } = params;
delete orgRow._antares_id;
reload = true;
for (const key in orgRow) {
if (typeof orgRow[key] === 'string')
orgRow[key] = ` = '${orgRow[key]}'`;
else if (typeof orgRow[key] === 'object' && orgRow[key] !== null)
orgRow[key] = formatJsonForSqlWhere(orgRow[key], connections[params.uid]._client);
else if (orgRow[key] === null)
orgRow[key] = `IS ${orgRow[key]}`;
else
orgRow[key] = `= ${orgRow[key]}`;
orgRow[key] = `'${orgRow[key]}'`;
orgRow[key] = `= ${orgRow[key]}`;
}
await connections[params.uid]
@@ -259,11 +197,9 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('delete-table-rows', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (params.primary) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const idString = params.rows.map((row: Record<string, any>) => {
const idString = params.rows.map((row: {[key: string]: any}) => {
const fieldName = Object.keys(row)[0].includes('.') ? `${params.table}.${params.primary}` : params.primary;
return typeof row[fieldName] === 'string'
@@ -272,11 +208,10 @@ export default (connections: Record<string, antares.Client>) => {
}).join(',');
try {
const result: unknown = await connections[params.uid]
const result = await connections[params.uid]
.schema(params.schema)
.delete(params.table)
.where({ [params.primary]: `IN (${idString})` })
.limit(params.rows.length)
.run();
return { status: 'success', response: result };
@@ -292,10 +227,7 @@ export default (connections: Record<string, antares.Client>) => {
if (typeof row[key] === 'string')
row[key] = `'${row[key]}'`;
if (row[key] === null)
row[key] = 'IS NULL';
else
row[key] = `= ${row[key]}`;
row[key] = `= ${row[key]}`;
}
await connections[params.uid]
@@ -314,14 +246,84 @@ export default (connections: Record<string, antares.Client>) => {
}
});
ipcMain.handle('insert-table-fake-rows', async (event, params: InsertRowsParams) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
ipcMain.handle('insert-table-rows', async (event, params) => {
try { // TODO: move to client classes
const rows: Record<string, string | number | boolean | Date | Buffer>[] = [];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const insertObj: {[key: string]: any} = {};
for (const key in params.row) {
const type = params.fields[key];
let escapedParam;
if (params.row[key] === null)
escapedParam = 'NULL';
else if ([...NUMBER, ...FLOAT].includes(type))
escapedParam = +params.row[key];
else if ([...TEXT, ...LONG_TEXT].includes(type)) {
switch (connections[params.uid]._client) {
case 'mysql':
case 'maria':
escapedParam = `"${sqlEscaper(params.row[key].value)}"`;
break;
case 'pg':
escapedParam = `'${params.row[key].value.replaceAll('\'', '\'\'')}'`;
break;
}
}
else if (BLOB.includes(type)) {
if (params.row[key].value) {
let fileBlob;
switch (connections[params.uid]._client) {
case 'mysql':
case 'maria':
fileBlob = fs.readFileSync(params.row[key].value);
escapedParam = `0x${fileBlob.toString('hex')}`;
break;
case 'pg':
fileBlob = fs.readFileSync(params.row[key].value);
escapedParam = `decode('${fileBlob.toString('hex')}', 'hex')`;
break;
}
}
else {
switch (connections[params.uid]._client) {
case 'mysql':
case 'maria':
escapedParam = '""';
break;
case 'pg':
escapedParam = 'decode(\'\', \'hex\')';
break;
}
}
}
insertObj[key] = escapedParam;
}
const rows = new Array(+params.repeat).fill(insertObj);
await connections[params.uid]
.schema(params.schema)
.into(params.table)
.insert(rows)
.run();
return { status: 'success' };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
ipcMain.handle('insert-table-fake-rows', async (event, params: InsertRowsParams) => {
try { // TODO: move to client classes
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const rows: {[key: string]: any}[] = [];
for (let i = 0; i < +params.repeat; i++) {
const insertObj: Record<string, string | number | boolean | Date | Buffer> = {};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const insertObj: {[key: string]: any} = {};
for (const key in params.row) {
const type = params.fields[key];
@@ -339,8 +341,6 @@ export default (connections: Record<string, antares.Client>) => {
escapedParam = `"${sqlEscaper(params.row[key].value)}"`;
break;
case 'pg':
case 'sqlite':
case 'firebird':
escapedParam = `'${params.row[key].value.replaceAll('\'', '\'\'')}'`;
break;
}
@@ -381,39 +381,29 @@ export default (connections: Record<string, antares.Client>) => {
insertObj[key] = escapedParam;
}
else { // Faker value
const parsedParams: Record<string, string | number | boolean | Date | Buffer> = {};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const parsedParams: {[key: string]: any} = {};
let fakeValue;
if (params.locale)
fakerCustom.locale = params.locale;
faker.locale = params.locale;
if (Object.keys(params.row[key].params).length) {
Object.keys(params.row[key].params).forEach(param => {
if (!isNaN(params.row[key].params[param]))// Converts string numerics params to number
parsedParams[param] = Number(params.row[key].params[param]);
if (!isNaN(params.row[key].params[param]))
parsedParams[param] = +params.row[key].params[param];
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
fakeValue = (fakerCustom as any)[params.row[key].group][params.row[key].method](parsedParams);
fakeValue = (faker as any)[params.row[key].group][params.row[key].method](parsedParams);
}
else
// eslint-disable-next-line @typescript-eslint/no-explicit-any
fakeValue = (fakerCustom as any)[params.row[key].group][params.row[key].method]();
fakeValue = (faker as any)[params.row[key].group][params.row[key].method]();
if (typeof fakeValue === 'string') {
if (params.row[key].length)
fakeValue = fakeValue.substring(0, params.row[key].length);
switch (connections[params.uid]._client) {
case 'mysql':
case 'maria':
fakeValue = `'${sqlEscaper(fakeValue)}'`;
break;
case 'pg':
case 'sqlite':
case 'firebird':
fakeValue = `'${fakeValue.replaceAll('\'', '\'\'')}'`;
break;
}
fakeValue = fakeValue.substr(0, params.row[key].length);
fakeValue = `'${sqlEscaper(fakeValue)}'`;
}
else if ([...DATE, ...DATETIME].includes(type))
fakeValue = `'${moment(fakeValue).format('YYYY-MM-DD HH:mm:ss.SSSSSS')}'`;
@@ -439,8 +429,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('get-foreign-list', async (event, { uid, schema, table, column, description }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const query = connections[uid]
.select(`${column} AS foreign_column`)
@@ -451,20 +439,7 @@ export default (connections: Record<string, antares.Client>) => {
if (description)
query.select(`LEFT(${description}, 20) AS foreign_description`);
const results = await query.run<Record<string, string>>();
const parsedResults: Record<string, string>[] = [];
for (const row of results.rows) {
const remappedRow: Record<string, string> = {};
for (const key in row)
remappedRow[key.toLowerCase()] = row[key];// Thanks Firebird -.-
parsedResults.push(remappedRow);
}
results.rows = parsedResults;
const results = await query.run();
return { status: 'success', response: results };
}
@@ -474,8 +449,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('create-table', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].createTable(params);
return { status: 'success' };
@@ -486,8 +459,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('alter-table', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].alterTable(params);
return { status: 'success' };
@@ -498,8 +469,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('duplicate-table', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].duplicateTable(params);
return { status: 'success' };
@@ -510,8 +479,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('truncate-table', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].truncateTable(params);
return { status: 'success' };
@@ -522,8 +489,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('drop-table', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].dropTable(params);
return { status: 'success' };

View File

@@ -1,12 +1,8 @@
import * as antares from 'common/interfaces/antares';
import { ipcMain } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: Record<string, antares.Client>) => {
export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('get-trigger-informations', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[params.uid].getTriggerInformations(params);
return { status: 'success', response: result };
@@ -17,8 +13,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('drop-trigger', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].dropTrigger(params);
return { status: 'success' };
@@ -29,8 +23,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('alter-trigger', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].alterTrigger(params);
return { status: 'success' };
@@ -41,8 +33,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('create-trigger', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].createTrigger(params);
return { status: 'success' };
@@ -53,8 +43,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('toggle-trigger', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
if (!params.enabled)
await connections[params.uid].enableTrigger(params);

View File

@@ -1,21 +1,11 @@
import { ipcMain } from 'electron';
import * as log from 'electron-log/main';
import * as Store from 'electron-store';
import { autoUpdater } from 'electron-updater';
const persistentStore = new Store({
name: 'settings',
clearInvalidConfig: true,
migrations: {
'0.7.15': store => {
store.set('allow_prerelease', false);
}
}
});
import Store from 'electron-store';
const persistentStore = new Store({ name: 'settings' });
const isMacOS = process.platform === 'darwin';
let mainWindow: Electron.IpcMainEvent;
autoUpdater.allowPrerelease = persistentStore.get('allow_prerelease', false) as boolean;
autoUpdater.allowPrerelease = persistentStore.get('allow_prerelease', true) as boolean;
export default () => {
ipcMain.on('check-for-updates', event => {
@@ -52,15 +42,15 @@ export default () => {
mainWindow.reply('update-not-available');
});
autoUpdater.on('download-progress', event => {
mainWindow.reply('download-progress', event);
autoUpdater.on('download-progress', data => {
mainWindow.reply('download-progress', data);
});
autoUpdater.on('update-downloaded', () => {
mainWindow.reply('update-downloaded');
});
log.transports.file.level = 'info';
// log.transports.console.format = '{h}:{i}:{s} {text}';
autoUpdater.logger = log;
// autoUpdater.logger = require('electron-log');
// autoUpdater.logger.transports.console.format = '{h}:{i}:{s} {text}';
// autoUpdater.logger.transports.file.level = 'info';
};

View File

@@ -1,12 +1,8 @@
import * as antares from 'common/interfaces/antares';
import { ipcMain } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: Record<string, antares.Client>) => {
export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('get-users', async (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[uid].getUsers();
return { status: 'success', response: result };

View File

@@ -1,12 +1,8 @@
import * as antares from 'common/interfaces/antares';
import { ipcMain } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: Record<string, antares.Client>) => {
export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('get-view-informations', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[params.uid].getViewInformations(params);
return { status: 'success', response: result };
@@ -17,8 +13,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('drop-view', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].dropView(params);
return { status: 'success' };
@@ -29,8 +23,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('alter-view', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].alterView(params);
return { status: 'success' };
@@ -41,8 +33,6 @@ export default (connections: Record<string, antares.Client>) => {
});
ipcMain.handle('create-view', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].createView(params);
return { status: 'success' };
@@ -51,52 +41,4 @@ export default (connections: Record<string, antares.Client>) => {
return { status: 'error', response: err.toString() };
}
});
ipcMain.handle('get-materialized-view-informations', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
const result = await connections[params.uid].getMaterializedViewInformations(params);
return { status: 'success', response: result };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
ipcMain.handle('drop-materialized-view', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].dropMaterializedView(params);
return { status: 'success' };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
ipcMain.handle('alter-materialized-view', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].alterView(params);
return { status: 'success' };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
ipcMain.handle('create-materialized-view', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try {
await connections[params.uid].createMaterializedView(params);
return { status: 'success' };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
};

View File

@@ -1,32 +1,31 @@
import * as antares from 'common/interfaces/antares';
import mysql from 'mysql2/promise';
import * as pg from 'pg';
import SSH2Promise = require('@fabio286/ssh2-promise');
import { querySplitter } from 'common/libs/querySplitter';
import SSH2Promise from 'ssh2-promise';
import { ipcLogger, LoggerLevel } from '../misc/ipcLogger';
const queryLogger = (sql: string) => {
// Remove comments, newlines and multiple spaces
const escapedSql = sql.replace(/(\/\*(.|[\r\n])*?\*\/)|(--(.*|[\r\n]))/gm, '').replace(/\s\s+/g, ' ');
console.log(escapedSql);
};
/**
* As Simple As Possible Query Builder Core
*/
export abstract class BaseClient {
export class AntaresCore {
_client: antares.ClientCode;
protected _cUid: string
protected _params: mysql.ConnectionOptions | pg.ClientConfig | { databasePath: string; readonly: boolean};
protected _poolSize: number;
protected _ssh?: SSH2Promise;
protected _logger: (args: {content: string; cUid: string; level: LoggerLevel}) => void;
protected _querySplitter: (sql: string, client: antares.ClientCode) => string[];
protected _logger: (sql: string) => void;
protected _queryDefaults: antares.QueryBuilderObject;
protected _query: antares.QueryBuilderObject;
constructor (args: antares.ClientParams) {
this._client = args.client;
this._cUid = args.uid;
this._params = args.params;
this._poolSize = args.poolSize || undefined;
this._logger = args.logger || ipcLogger;
this._querySplitter = args.querySplitter || querySplitter;
this._logger = args.logger || queryLogger;
this._queryDefaults = {
schema: '',
@@ -131,7 +130,7 @@ export abstract class BaseClient {
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
insert (arr: Record<string, any>[]) {
insert (arr: {[key: string]: any}[]) {
this._query.insert = [...this._query.insert, ...arr];
return this;
}
@@ -157,10 +156,6 @@ export abstract class BaseClient {
throw new Error('Method "getDbConfig" not implemented');
}
getDatabases () {
throw new Error('Method "getDatabases" not implemented');
}
createSchema (...args: any) {
throw new Error('Method "createSchema" not implemented');
}
@@ -173,14 +168,6 @@ export abstract class BaseClient {
throw new Error('Method "dropSchema" not implemented');
}
getTableChecks (...args: any) {
throw new Error('Method "getTableDll" not implemented');
}
getTableDll (...args: any) {
throw new Error('Method "getTableDll" not implemented');
}
getDatabaseCollation (...args: any) {
throw new Error('Method "getDatabaseCollation" not implemented');
}
@@ -233,18 +220,6 @@ export abstract class BaseClient {
throw new Error('Method "getVariables" not implemented');
}
getMaterializedViewInformations (...args: any) {
throw new Error('Method "getMaterializedViewInformations" not implemented');
}
dropMaterializedView (...args: any) {
throw new Error('Method "dropMaterializedView" not implemented');
}
createMaterializedView (...args: any) {
throw new Error('Method "createMaterializedView" not implemented');
}
getEventInformations (...args: any) {
throw new Error('Method "getEventInformations" not implemented');
}

View File

@@ -1,6 +1,4 @@
import * as antares from 'common/interfaces/antares';
import { FirebirdSQLClient } from './clients/FirebirdSQLClient';
import { MySQLClient } from './clients/MySQLClient';
import { PostgreSQLClient } from './clients/PostgreSQLClient';
import { SQLiteClient } from './clients/SQLiteClient';
@@ -15,8 +13,6 @@ export class ClientsFactory {
return new PostgreSQLClient(args);
case 'sqlite':
return new SQLiteClient(args);
case 'firebird':
return new FirebirdSQLClient(args);
default:
throw new Error(`Unknown database client: ${args.client}`);
}

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