diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..c4e3047e4 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: dbgate +open_collective: dbgate diff --git a/.github/workflows/build-app-beta.yaml b/.github/workflows/build-app-beta.yaml index 7f33bd52e..33feb1c8f 100644 --- a/.github/workflows/build-app-beta.yaml +++ b/.github/workflows/build-app-beta.yaml @@ -35,6 +35,9 @@ jobs: - name: fillNativeModulesElectron run: | yarn fillNativeModulesElectron + - name: fillPackagedPlugins + run: | + yarn fillPackagedPlugins - name: Install Snapcraft if: matrix.os == 'ubuntu-18.04' uses: samuelmeuli/action-snapcraft@v1 diff --git a/.github/workflows/build-app.yaml b/.github/workflows/build-app.yaml index 5af9d11b1..86368c37d 100644 --- a/.github/workflows/build-app.yaml +++ b/.github/workflows/build-app.yaml @@ -39,6 +39,9 @@ jobs: - name: fillNativeModulesElectron run: | yarn fillNativeModulesElectron + - name: fillPackagedPlugins + run: | + yarn fillPackagedPlugins - name: Install Snapcraft if: matrix.os == 'ubuntu-18.04' uses: samuelmeuli/action-snapcraft@v1 diff --git a/.gitignore b/.gitignore index 718d20748..686ceb6c6 100644 --- a/.gitignore +++ b/.gitignore @@ -30,4 +30,5 @@ yarn-debug.log* yarn-error.log* app/src/nativeModulesContent.js packages/api/src/nativeModulesContent.js +packages/api/src/packagedPluginsContent.js .VSCodeCounter \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 094c306fa..ffb14e6c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # ChangeLog +### 4.2.2 +- CHANGED: Further startup optimalization (approx. 2 times quicker start of electron app) + +### 4.2.1 +- FIXED: Fixed+optimalized app startup (esp. on Windows) + ### 4.2.0 - ADDED: Support of SQLite database - ADDED: Support of Amazon Redshift database diff --git a/app/package.json b/app/package.json index b327f56b4..24f72c60b 100644 --- a/app/package.json +++ b/app/package.json @@ -39,7 +39,7 @@ "icon": "icon.png", "artifactName": "dbgate-linux-${version}.${ext}", "category": "Development", - "synopsis": "Database administration tool for MS SQL, MySQL and PostgreSQL", + "synopsis": "Database manager for SQL Server, MySQL, PostgreSQL, MongoDB and SQLite", "publish": [ "github" ] diff --git a/fillPackagedPlugins.js b/fillPackagedPlugins.js new file mode 100644 index 000000000..43ccd79ae --- /dev/null +++ b/fillPackagedPlugins.js @@ -0,0 +1,23 @@ +const fs = require('fs'); +const path = require('path'); + +function load() { + const plugins = {}; + + for (const packageName of fs.readdirSync('plugins')) { + if (!packageName.startsWith('dbgate-plugin-')) continue; + const dir = path.join('plugins', packageName); + const frontend = fs.readFileSync(path.join(dir, 'dist', 'frontend.js'), 'utf-8'); + const readme = fs.readFileSync(path.join(dir, 'README.md'), 'utf-8'); + const manifest = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf-8')); + plugins[packageName] = { + manifest, + frontend, + readme, + }; + } + + return plugins; +} + +fs.writeFileSync('packages/api/src/packagedPluginsContent.js', `module.exports = () => (${JSON.stringify(load())});`); diff --git a/package.json b/package.json index bd40048d4..6e4cf1ea4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "4.2.1-beta.1", + "version": "4.2.2", "name": "dbgate-all", "workspaces": [ "packages/*", @@ -32,6 +32,8 @@ "generatePadFile": "node generatePadFile", "fillNativeModules": "node fillNativeModules", "fillNativeModulesElectron": "node fillNativeModules --electron", + "fillPackagedPlugins": "node fillPackagedPlugins", + "resetPackagedPlugins": "node resetPackagedPlugins", "prettier": "prettier --write packages/api/src && prettier --write packages/datalib/src && prettier --write packages/filterparser/src && prettier --write packages/sqltree/src && prettier --write packages/tools/src && prettier --write packages/types && prettier --write packages/web/src && prettier --write app/src", "copy:docker:build": "copyfiles packages/api/dist/* docker -f && copyfiles packages/web/public/* docker -u 2 && copyfiles \"packages/web/public/**/*\" docker -u 2 && copyfiles \"plugins/dist/**/*\" docker/plugins -u 2", "prepare:docker": "yarn plugins:copydist && yarn build:web:docker && yarn build:api && yarn copy:docker:build", @@ -40,7 +42,7 @@ "ts:api": "yarn workspace dbgate-api ts", "ts:web": "yarn workspace dbgate-web ts", "ts": "yarn ts:api && yarn ts:web", - "postinstall": "yarn build:lib && patch-package && yarn fillNativeModules && yarn build:plugins:frontend" + "postinstall": "yarn resetPackagedPlugins && yarn build:lib && patch-package && yarn fillNativeModules && yarn build:plugins:frontend" }, "dependencies": { "concurrently": "^5.1.0", diff --git a/packages/api/src/controllers/plugins.js b/packages/api/src/controllers/plugins.js index 6800ba791..c45545285 100644 --- a/packages/api/src/controllers/plugins.js +++ b/packages/api/src/controllers/plugins.js @@ -9,10 +9,17 @@ const requirePlugin = require('../shell/requirePlugin'); const downloadPackage = require('../utility/downloadPackage'); const hasPermission = require('../utility/hasPermission'); const _ = require('lodash'); +const packagedPluginsContent = require('../packagedPluginsContent'); module.exports = { script_meta: 'get', async script({ packageName }) { + const packagedContent = packagedPluginsContent(); + + if (packagedContent && packagedContent[packageName]) { + return packagedContent[packageName].frontend; + } + const file1 = path.join(packagedPluginsDir(), packageName, 'dist', 'frontend.js'); const file2 = path.join(pluginsdir(), packageName, 'dist', 'frontend.js'); // @ts-ignore @@ -58,26 +65,37 @@ module.exports = { installed_meta: 'get', async installed() { - const files1 = await fs.readdir(packagedPluginsDir()); + const packagedContent = packagedPluginsContent(); + + const files1 = packagedContent ? _.keys(packagedContent) : await fs.readdir(packagedPluginsDir()); const files2 = await fs.readdir(pluginsdir()); const res = []; for (const packageName of _.union(files1, files2)) { if (!/^dbgate-plugin-.*$/.test(packageName)) continue; try { - const isPackaged = files1.includes(packageName); - const manifest = await fs - .readFile(path.join(isPackaged ? packagedPluginsDir() : pluginsdir(), packageName, 'package.json'), { - encoding: 'utf-8', - }) - .then(x => JSON.parse(x)); - const readmeFile = path.join(isPackaged ? packagedPluginsDir() : pluginsdir(), packageName, 'README.md'); - // @ts-ignore - if (await fs.exists(readmeFile)) { - manifest.readme = await fs.readFile(readmeFile, { encoding: 'utf-8' }); + if (packagedContent && packagedContent[packageName]) { + const manifest = { + ...packagedContent[packageName].manifest, + }; + manifest.isPackaged = true; + manifest.readme = packagedContent[packageName].readme; + res.push(manifest); + } else { + const isPackaged = files1.includes(packageName); + const manifest = await fs + .readFile(path.join(isPackaged ? packagedPluginsDir() : pluginsdir(), packageName, 'package.json'), { + encoding: 'utf-8', + }) + .then(x => JSON.parse(x)); + const readmeFile = path.join(isPackaged ? packagedPluginsDir() : pluginsdir(), packageName, 'README.md'); + // @ts-ignore + if (await fs.exists(readmeFile)) { + manifest.readme = await fs.readFile(readmeFile, { encoding: 'utf-8' }); + } + manifest.isPackaged = isPackaged; + res.push(manifest); } - manifest.isPackaged = isPackaged; - res.push(manifest); } catch (err) { console.log(`Skipped plugin ${packageName}, error:`, err.message); } diff --git a/packages/api/src/index.js b/packages/api/src/index.js index 87e072da4..9da36f975 100644 --- a/packages/api/src/index.js +++ b/packages/api/src/index.js @@ -1,5 +1,8 @@ const shell = require('./shell'); const processArgs = require('./utility/processArgs'); +const dbgateTools = require('dbgate-tools'); + +global['DBGATE_TOOLS'] = dbgateTools; if (processArgs.startProcess) { const proc = require('./proc'); diff --git a/packages/tools/src/DatabaseAnalyser.ts b/packages/tools/src/DatabaseAnalyser.ts index d99c31984..8891777a5 100644 --- a/packages/tools/src/DatabaseAnalyser.ts +++ b/packages/tools/src/DatabaseAnalyser.ts @@ -2,7 +2,7 @@ import { DatabaseInfo, DatabaseModification, EngineDriver } from 'dbgate-types'; import _sortBy from 'lodash/sortBy'; import _groupBy from 'lodash/groupBy'; import _pick from 'lodash/pick'; -import _ from 'lodash'; +import _compact from 'lodash/compact'; const fp_pick = arg => array => _pick(array, arg); export class DatabaseAnalyser { @@ -134,7 +134,7 @@ export class DatabaseAnalyser { return this.structure[objectTypeField] .filter(x => !items.find(y => x.objectId == y.objectId)) .map(x => ({ - oldName: _.pick(x, ['schemaName', 'pureName']), + oldName: _pick(x, ['schemaName', 'pureName']), objectId: x.objectId, action: 'remove', objectTypeField, @@ -175,7 +175,7 @@ export class DatabaseAnalyser { const action = obj ? { newName: { schemaName, pureName }, - oldName: _.pick(obj, ['schemaName', 'pureName']), + oldName: _pick(obj, ['schemaName', 'pureName']), action: 'change', objectTypeField: field, objectId, @@ -189,7 +189,7 @@ export class DatabaseAnalyser { res.push(action); } - return [..._.compact(res), ...this.getDeletedObjects(snapshot)]; + return [..._compact(res), ...this.getDeletedObjects(snapshot)]; } } diff --git a/packages/tools/src/SqlGenerator.ts b/packages/tools/src/SqlGenerator.ts index 7f25c6be0..9d7ecfe1c 100644 --- a/packages/tools/src/SqlGenerator.ts +++ b/packages/tools/src/SqlGenerator.ts @@ -7,7 +7,8 @@ import { TriggerInfo, ViewInfo, } from 'dbgate-types'; -import _ from 'lodash'; +import _flatten from 'lodash/flatten'; +import _uniqBy from 'lodash/uniqBy' import { SqlDumper } from './SqlDumper'; import { extendDatabaseInfo } from './structureTools'; @@ -122,9 +123,9 @@ export class SqlGenerator { createForeignKeys() { const fks = []; - if (this.options.createForeignKeys) fks.push(..._.flatten(this.tables.map(x => x.foreignKeys || []))); - if (this.options.createReferences) fks.push(..._.flatten(this.tables.map(x => x.dependencies || []))); - for (const fk of _.uniqBy(fks, 'constraintName')) { + if (this.options.createForeignKeys) fks.push(..._flatten(this.tables.map(x => x.foreignKeys || []))); + if (this.options.createReferences) fks.push(..._flatten(this.tables.map(x => x.dependencies || []))); + for (const fk of _uniqBy(fks, 'constraintName')) { this.dmp.createForeignKey(fk); if (this.checkDumper()) return; } @@ -152,7 +153,7 @@ export class SqlGenerator { } } if (this.options.createIndexes) { - for (const index of _.flatten(this.tables.map(x => x.indexes || []))) { + for (const index of _flatten(this.tables.map(x => x.indexes || []))) { this.dmp.createIndex(index); } } @@ -204,7 +205,7 @@ export class SqlGenerator { dropTables() { if (this.options.dropReferences) { - for (const fk of _.flatten(this.tables.map(x => x.dependencies || []))) { + for (const fk of _flatten(this.tables.map(x => x.dependencies || []))) { this.dmp.dropForeignKey(fk); } } diff --git a/packages/tools/src/settingsExtractors.ts b/packages/tools/src/settingsExtractors.ts index 843a4442b..a5a9c0dfb 100644 --- a/packages/tools/src/settingsExtractors.ts +++ b/packages/tools/src/settingsExtractors.ts @@ -1,11 +1,12 @@ -import _ from 'lodash'; +import _isNaN from 'lodash/isNaN'; +import _isNumber from 'lodash/isNumber'; export function extractIntSettingsValue(settings, name, defaultValue, min = null, max = null) { const parsed = parseInt(settings[name]); - if (_.isNaN(parsed)) { + if (_isNaN(parsed)) { return defaultValue; } - if (_.isNumber(parsed)) { + if (_isNumber(parsed)) { if (min != null && parsed < min) return min; if (max != null && parsed > max) return max; return parsed; diff --git a/packages/tools/src/structureTools.ts b/packages/tools/src/structureTools.ts index 38d1c45ea..6897090b9 100644 --- a/packages/tools/src/structureTools.ts +++ b/packages/tools/src/structureTools.ts @@ -1,8 +1,8 @@ import { DatabaseInfo } from 'dbgate-types'; -import _ from 'lodash'; +import _flatten from 'lodash/flatten'; export function addTableDependencies(db: DatabaseInfo): DatabaseInfo { - const allForeignKeys = _.flatten(db.tables.map(x => x.foreignKeys || [])); + const allForeignKeys = _flatten(db.tables.map(x => x.foreignKeys || [])); return { ...db, tables: db.tables.map(table => ({ diff --git a/packages/web/public/index.html b/packages/web/public/index.html index 55ed2489f..1a4b3dfc2 100644 --- a/packages/web/public/index.html +++ b/packages/web/public/index.html @@ -21,9 +21,25 @@ + +
+