diff --git a/fillNativeModules.js b/fillNativeModules.js index 780292b5..61dea66e 100644 --- a/fillNativeModules.js +++ b/fillNativeModules.js @@ -5,6 +5,7 @@ let fillContent = ''; if (process.platform == 'win32') { fillContent += `content.msnodesqlv8 = () => require('msnodesqlv8');`; } +fillContent += `content['better-sqlite3'] = () => require('better-sqlite3');`; const getContent = (empty) => ` // this file is generated automatically by script fillNativeModules.js, do not edit it manually diff --git a/packages/api/package.json b/packages/api/package.json index 3879b8e6..713060ad 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -19,6 +19,7 @@ "dependencies": { "async-lock": "^1.2.4", "axios": "^0.19.0", + "better-sqlite3": "^7.1.5", "body-parser": "^1.19.0", "bufferutil": "^4.0.1", "byline": "^5.0.0", diff --git a/packages/types/engines.d.ts b/packages/types/engines.d.ts index 26b0116a..c5dbc29a 100644 --- a/packages/types/engines.d.ts +++ b/packages/types/engines.d.ts @@ -38,6 +38,7 @@ export interface EngineDriver { title: string; defaultPort?: number; supportsDatabaseUrl?: boolean; + isFileDatabase?: boolean; databaseUrlPlaceholder?: string; connect({ server, port, user, password, database }): any; query(pool: any, sql: string): Promise; diff --git a/packages/web/src/modals/ConnectionModalDriverFields.svelte b/packages/web/src/modals/ConnectionModalDriverFields.svelte index f8bffb91..8db57a9d 100644 --- a/packages/web/src/modals/ConnectionModalDriverFields.svelte +++ b/packages/web/src/modals/ConnectionModalDriverFields.svelte @@ -9,9 +9,12 @@ import FormTextField from '../forms/FormTextField.svelte'; import { extensions } from '../stores'; +import getElectron from '../utility/getElectron'; import { useAuthTypes } from '../utility/metadataLoaders'; const { values } = getFormContext(); + const electron = getElectron(); + $: authType = $values.authType; $: engine = $values.engine; $: useDatabaseUrl = $values.useDatabaseUrl; @@ -27,10 +30,12 @@ name="engine" options={[ { label: '(select driver)', value: '' }, - ...$extensions.drivers.map(driver => ({ - value: driver.engine, - label: driver.title, - })), + ...$extensions.drivers + .filter(driver => !driver.isFileDatabase || electron) + .map(driver => ({ + value: driver.engine, + label: driver.title, + })), ]} /> diff --git a/plugins/dbgate-plugin-sqlite/.gitignore b/plugins/dbgate-plugin-sqlite/.gitignore new file mode 100644 index 00000000..1dad8826 --- /dev/null +++ b/plugins/dbgate-plugin-sqlite/.gitignore @@ -0,0 +1,25 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +build +dist +lib + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/plugins/dbgate-plugin-sqlite/README.md b/plugins/dbgate-plugin-sqlite/README.md new file mode 100644 index 00000000..b4794341 --- /dev/null +++ b/plugins/dbgate-plugin-sqlite/README.md @@ -0,0 +1,6 @@ +[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier) +[![NPM version](https://img.shields.io/npm/v/dbgate-plugin-sqlite.svg)](https://www.npmjs.com/package/dbgate-plugin-sqlite) + +# dbgate-plugin-sqlite + +Use DbGate for install of this plugin diff --git a/plugins/dbgate-plugin-sqlite/icon.svg b/plugins/dbgate-plugin-sqlite/icon.svg new file mode 100644 index 00000000..cfe0335e --- /dev/null +++ b/plugins/dbgate-plugin-sqlite/icon.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + diff --git a/plugins/dbgate-plugin-sqlite/package.json b/plugins/dbgate-plugin-sqlite/package.json new file mode 100644 index 00000000..e6280a2a --- /dev/null +++ b/plugins/dbgate-plugin-sqlite/package.json @@ -0,0 +1,32 @@ +{ + "name": "dbgate-plugin-sqlite", + "main": "dist/backend.js", + "version": "1.0.0", + "license": "MIT", + "keywords": [ + "dbgate", + "dbgateplugin", + "sqlite" + ], + "files": [ + "dist" + ], + "scripts": { + "build:frontend": "webpack --config webpack-frontend.config", + "build:frontend:watch": "webpack --watch --config webpack-frontend.config", + "build:backend": "webpack --config webpack-backend.config.js", + "build": "yarn build:frontend && yarn build:backend", + "plugin": "yarn build && yarn pack && dbgate-plugin dbgate-plugin-sqlite", + "copydist": "yarn build && yarn pack && dbgate-copydist ../dist/dbgate-plugin-sqlite", + "plugout": "dbgate-plugout dbgate-plugin-sqlite", + "prepublishOnly": "yarn build" + }, + "devDependencies": { + "dbgate-tools": "^4.1.1", + "dbgate-plugin-tools": "^1.0.4", + "byline": "^5.0.0", + "webpack": "^4.42.0", + "webpack-cli": "^3.3.11" + } + } + \ No newline at end of file diff --git a/plugins/dbgate-plugin-sqlite/prettier.config.js b/plugins/dbgate-plugin-sqlite/prettier.config.js new file mode 100644 index 00000000..40648407 --- /dev/null +++ b/plugins/dbgate-plugin-sqlite/prettier.config.js @@ -0,0 +1,8 @@ +module.exports = { + trailingComma: 'es5', + tabWidth: 2, + semi: true, + singleQuote: true, + arrowParen: 'avoid', + printWidth: 120, +}; diff --git a/plugins/dbgate-plugin-sqlite/src/backend/Analyser.js b/plugins/dbgate-plugin-sqlite/src/backend/Analyser.js new file mode 100644 index 00000000..3e176ddc --- /dev/null +++ b/plugins/dbgate-plugin-sqlite/src/backend/Analyser.js @@ -0,0 +1,9 @@ +const { DatabaseAnalyser } = require('dbgate-tools'); + +class Analyser extends DatabaseAnalyser { + constructor(pool, driver) { + super(pool, driver); + } +} + +module.exports = Analyser; diff --git a/plugins/dbgate-plugin-sqlite/src/backend/driver.js b/plugins/dbgate-plugin-sqlite/src/backend/driver.js new file mode 100644 index 00000000..ea7a583f --- /dev/null +++ b/plugins/dbgate-plugin-sqlite/src/backend/driver.js @@ -0,0 +1,63 @@ +const _ = require('lodash'); +const stream = require('stream'); +const driverBase = require('../frontend/driver'); +const Analyser = require('./Analyser'); + +let sqlite3; + +/** @type {import('dbgate-types').EngineDriver} */ +const driver = { + ...driverBase, + analyserClass: Analyser, + async connect({ server, port, user, password, database }) { + const pool = new NativePool({ + server, + port, + user, + password, + database, + }); + await pool.connect(); + return pool; + }, + // @ts-ignore + async query(pool, sql) { + return { + rows: [], + columns: [], + }; + }, + async stream(pool, sql, options) { + return null; + }, + async readQuery(pool, sql, structure) { + const pass = new stream.PassThrough({ + objectMode: true, + highWaterMark: 100, + }); + + // pass.write(structure) + // pass.write(row1) + // pass.write(row2) + // pass.end() + + return pass; + }, + async writeTable(pool, name, options) { + return createBulkInsertStreamBase(this, stream, pool, name, options); + }, + async getVersion(pool) { + return { version: '1.0.0' }; + }, + async listDatabases(pool) { + return [{ name: 'db1' }, { name: 'db2' }]; + }, +}; + +driver.initialize = (dbgateEnv) => { + if (dbgateEnv.nativeModules && dbgateEnv.nativeModules['better-sqlite3']) { + sqlite3 = dbgateEnv.nativeModules['better-sqlite3'](); + } +}; + +module.exports = driver; diff --git a/plugins/dbgate-plugin-sqlite/src/backend/index.js b/plugins/dbgate-plugin-sqlite/src/backend/index.js new file mode 100644 index 00000000..4812dbd5 --- /dev/null +++ b/plugins/dbgate-plugin-sqlite/src/backend/index.js @@ -0,0 +1,6 @@ +const driver = require('./driver'); + +module.exports = { + packageName: 'dbgate-plugin-sqlite', + driver, +}; diff --git a/plugins/dbgate-plugin-sqlite/src/frontend/Dumper.js b/plugins/dbgate-plugin-sqlite/src/frontend/Dumper.js new file mode 100644 index 00000000..afcc6473 --- /dev/null +++ b/plugins/dbgate-plugin-sqlite/src/frontend/Dumper.js @@ -0,0 +1,6 @@ +const { SqlDumper } = require('dbgate-tools'); + +class Dumper extends SqlDumper { +} + +module.exports = Dumper; diff --git a/plugins/dbgate-plugin-sqlite/src/frontend/driver.js b/plugins/dbgate-plugin-sqlite/src/frontend/driver.js new file mode 100644 index 00000000..7eeb2a07 --- /dev/null +++ b/plugins/dbgate-plugin-sqlite/src/frontend/driver.js @@ -0,0 +1,27 @@ +const { driverBase } = require('dbgate-tools'); +const Dumper = require('./Dumper'); + +/** @type {import('dbgate-types').SqlDialect} */ +const dialect = { + limitSelect: true, + rangeSelect: true, + offsetFetchRangeSyntax: true, + stringEscapeChar: "'", + fallbackDataType: 'nvarchar(max)', + quoteIdentifier(s) { + return `[${s}]`; + }, +}; + + +/** @type {import('dbgate-types').EngineDriver} */ +const driver = { + ...driverBase, + dumperClass: Dumper, + dialect, + engine: 'sqlite@dbgate-plugin-sqlite', + title: 'SQLite', + isFileDatabase: true, +}; + +module.exports = driver; diff --git a/plugins/dbgate-plugin-sqlite/src/frontend/index.js b/plugins/dbgate-plugin-sqlite/src/frontend/index.js new file mode 100644 index 00000000..acb656b9 --- /dev/null +++ b/plugins/dbgate-plugin-sqlite/src/frontend/index.js @@ -0,0 +1,6 @@ +import driver from './driver'; + +export default { + packageName: 'dbgate-plugin-sqlite', + driver, +}; diff --git a/plugins/dbgate-plugin-sqlite/webpack-backend.config.js b/plugins/dbgate-plugin-sqlite/webpack-backend.config.js new file mode 100644 index 00000000..e75357df --- /dev/null +++ b/plugins/dbgate-plugin-sqlite/webpack-backend.config.js @@ -0,0 +1,23 @@ +var webpack = require('webpack'); +var path = require('path'); + +var config = { + context: __dirname + '/src/backend', + + entry: { + app: './index.js', + }, + target: 'node', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'backend.js', + libraryTarget: 'commonjs2', + }, + + // uncomment for disable minimalization + // optimization: { + // minimize: false, + // }, +}; + +module.exports = config; diff --git a/plugins/dbgate-plugin-sqlite/webpack-frontend.config.js b/plugins/dbgate-plugin-sqlite/webpack-frontend.config.js new file mode 100644 index 00000000..db07de29 --- /dev/null +++ b/plugins/dbgate-plugin-sqlite/webpack-frontend.config.js @@ -0,0 +1,24 @@ +var webpack = require("webpack"); +var path = require("path"); + +var config = { + context: __dirname + "/src/frontend", + + entry: { + app: "./index.js", + }, + target: "web", + output: { + path: path.resolve(__dirname, "dist"), + filename: "frontend.js", + libraryTarget: "var", + library: 'plugin', + }, + + // uncomment for disable minimalization + // optimization: { + // minimize: false, + // }, +}; + +module.exports = config; diff --git a/yarn.lock b/yarn.lock index 41aeb66b..8de02223 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1431,6 +1431,15 @@ better-assert@~1.0.0: dependencies: callsite "1.0.0" +better-sqlite3@^7.1.5: + version "7.1.5" + resolved "https://registry.yarnpkg.com/better-sqlite3/-/better-sqlite3-7.1.5.tgz#3eb0fcc81bed463ddf2da4a02aad7e02726205c0" + integrity sha512-HX5dN0zLllJLQOJP2tXqV42bvjXPnbe/Nl5o6nD1jj99h0148B39zbfGZVoJBLtDAd/CJc4Zdm8K+GhHIq84IQ== + dependencies: + bindings "^1.5.0" + prebuild-install "^6.0.1" + tar "^6.1.0" + big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -2478,7 +2487,7 @@ date-utils@*: resolved "https://registry.yarnpkg.com/date-utils/-/date-utils-1.2.21.tgz#61fb16cdc1274b3c9acaaffe9fc69df8720a2b64" integrity sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q= -dbgate-plugin-tools@^1.0.7: +dbgate-plugin-tools@^1.0.4, dbgate-plugin-tools@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/dbgate-plugin-tools/-/dbgate-plugin-tools-1.0.7.tgz#b03d456dd0bfee77281189898e51e15b9593a35c" integrity sha512-KI5MfU+gqD067SXBo+5PPSj0415znfKczKCjRbFNCWbFnvDp5aV0816Lk6ZNTHAAMXuZe6gGHey92Ky+BLEsXQ== @@ -6075,6 +6084,13 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-abi@^2.21.0: + version "2.26.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.26.0.tgz#355d5d4bc603e856f74197adbf3f5117a396ba40" + integrity sha512-ag/Vos/mXXpWLLAYWsAoQdgS+gW7IwvgMLOgqopm/DbzAjazLltzgzpVMsFlgmo9TzG5hGXeaBZx2AI731RIsQ== + dependencies: + semver "^5.4.1" + node-abi@^2.7.0: version "2.19.3" resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.19.3.tgz#252f5dcab12dad1b5503b2d27eddd4733930282d" @@ -6968,6 +6984,26 @@ prebuild-install@^6.0.0: tunnel-agent "^0.6.0" which-pm-runs "^1.0.0" +prebuild-install@^6.0.1: + version "6.1.2" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-6.1.2.tgz#6ce5fc5978feba5d3cbffedca0682b136a0b5bff" + integrity sha512-PzYWIKZeP+967WuKYXlTOhYBgGOvTRSfaKI89XnfJ0ansRAH7hDU45X+K+FZeI1Wb/7p/NnuctPH3g0IqKUuSQ== + dependencies: + detect-libc "^1.0.3" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" + napi-build-utils "^1.0.1" + node-abi "^2.21.0" + noop-logger "^0.1.1" + npmlog "^4.0.1" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^3.0.3" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"