Merge branch 'develop'

This commit is contained in:
Jan Prochazka
2021-12-30 11:04:51 +01:00
124 changed files with 1891 additions and 2076 deletions

View File

@@ -22,10 +22,10 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
fetch-depth: 1 fetch-depth: 1
- name: Use Node.js 12.x - name: Use Node.js 14.x
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 12.x node-version: 14.x
- name: yarn install - name: yarn install
run: | run: |
yarn install yarn install

View File

@@ -26,10 +26,10 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
fetch-depth: 1 fetch-depth: 1
- name: Use Node.js 12.x - name: Use Node.js 14.x
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 12.x node-version: 14.x
- name: yarn install - name: yarn install
run: | run: |
yarn install yarn install

View File

@@ -24,10 +24,10 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
fetch-depth: 1 fetch-depth: 1
- name: Use Node.js 12.x - name: Use Node.js 14.x
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 12.x node-version: 14.x
- name: yarn install - name: yarn install
run: | run: |
yarn install yarn install

View File

@@ -30,10 +30,10 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
fetch-depth: 1 fetch-depth: 1
- name: Use Node.js 12.x - name: Use Node.js 14.x
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 12.x node-version: 14.x
- name: yarn install - name: yarn install
run: | run: |
yarn install yarn install

View File

@@ -30,10 +30,10 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
fetch-depth: 1 fetch-depth: 1
- name: Use Node.js 12.x - name: Use Node.js 14.x
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 12.x node-version: 14.x
- name: Configure NPM token - name: Configure NPM token
env: env:

View File

@@ -8,7 +8,7 @@ on:
jobs: jobs:
test-runner: test-runner:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: node:12.22 container: node:14.18
steps: steps:
- name: Context - name: Context

View File

@@ -5,10 +5,8 @@
"author": "Jan Prochazka <jenasoft.database@gmail.com>", "author": "Jan Prochazka <jenasoft.database@gmail.com>",
"description": "Opensource database administration tool", "description": "Opensource database administration tool",
"dependencies": { "dependencies": {
"better-sqlite3-with-prebuilds": "^7.1.8", "electron-log": "^4.4.1",
"electron-log": "^4.3.1", "electron-updater": "^4.6.1",
"electron-store": "^5.1.1",
"electron-updater": "^4.3.5",
"patch-package": "^6.4.7" "patch-package": "^6.4.7"
}, },
"repository": { "repository": {
@@ -90,23 +88,25 @@
}, },
"homepage": "./", "homepage": "./",
"scripts": { "scripts": {
"start": "cross-env ELECTRON_START_URL=http://localhost:5000 electron .", "start": "cross-env ELECTRON_START_URL=http://localhost:5000 DEVMODE=1 electron .",
"start:local": "cross-env electron .", "start:local": "cross-env electron .",
"dist": "electron-builder", "dist": "electron-builder",
"build": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && yarn dist", "build": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && yarn dist",
"build:mac": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && node setMacPlatform x64 && yarn dist && node setMacPlatform arm64 && yarn dist", "build:mac": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && node setMacPlatform x64 && yarn dist && node setMacPlatform arm64 && yarn dist",
"build:local": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && yarn predist", "build:local": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && yarn predist",
"postinstall": "electron-builder install-app-deps && patch-package", "postinstall": "yarn rebuild && patch-package",
"rebuild": "electron-builder install-app-deps",
"predist": "copyfiles ../packages/api/dist/* packages && copyfiles \"../packages/web/public/*\" packages && copyfiles \"../packages/web/public/**/*\" packages && copyfiles --up 3 \"../plugins/dist/**/*\" packages/plugins" "predist": "copyfiles ../packages/api/dist/* packages && copyfiles \"../packages/web/public/*\" packages && copyfiles \"../packages/web/public/**/*\" packages && copyfiles --up 3 \"../plugins/dist/**/*\" packages/plugins"
}, },
"main": "src/electron.js", "main": "src/electron.js",
"devDependencies": { "devDependencies": {
"copyfiles": "^2.2.0", "copyfiles": "^2.2.0",
"cross-env": "^6.0.3", "cross-env": "^6.0.3",
"electron": "11.2.3", "electron": "13.6.3",
"electron-builder": "22.10.5" "electron-builder": "22.14.5"
}, },
"optionalDependencies": { "optionalDependencies": {
"msnodesqlv8": "^2.4.0" "better-sqlite3": "7.4.5",
"msnodesqlv8": "^2.4.4"
} }
} }

View File

@@ -1,9 +1,8 @@
const electron = require('electron'); const electron = require('electron');
const os = require('os'); const os = require('os');
const fs = require('fs');
const { Menu, ipcMain } = require('electron'); const { Menu, ipcMain } = require('electron');
const { fork } = require('child_process');
const { autoUpdater } = require('electron-updater'); const { autoUpdater } = require('electron-updater');
const Store = require('electron-store');
const log = require('electron-log'); const log = require('electron-log');
// Module to control application life. // Module to control application life.
@@ -14,7 +13,17 @@ const BrowserWindow = electron.BrowserWindow;
const path = require('path'); const path = require('path');
const url = require('url'); const url = require('url');
const store = new Store(); // require('@electron/remote/main').initialize();
const configRootPath = path.join(app.getPath('userData'), 'config-root.json');
let initialConfig = {};
try {
initialConfig = JSON.parse(fs.readFileSync(configRootPath, { encoding: 'utf-8' }));
} catch (err) {
console.log('Error loading config-root:', err.message);
initialConfig = {};
}
// Keep a global reference of the window object, if you don't, the window will // Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected. // be closed automatically when the JavaScript object is garbage collected.
@@ -36,7 +45,7 @@ function commandItem(id) {
accelerator: command ? command.keyText : undefined, accelerator: command ? command.keyText : undefined,
enabled: command ? command.enabled : false, enabled: command ? command.enabled : false,
click() { click() {
mainWindow.webContents.executeJavaScript(`dbgate_runCommand('${id}')`); mainWindow.webContents.send('run-command', id);
}, },
}; };
} }
@@ -99,25 +108,25 @@ function buildMenu() {
{ {
label: 'dbgate.org', label: 'dbgate.org',
click() { click() {
require('electron').shell.openExternal('https://dbgate.org'); electron.shell.openExternal('https://dbgate.org');
}, },
}, },
{ {
label: 'DbGate on GitHub', label: 'DbGate on GitHub',
click() { click() {
require('electron').shell.openExternal('https://github.com/dbgate/dbgate'); electron.shell.openExternal('https://github.com/dbgate/dbgate');
}, },
}, },
{ {
label: 'DbGate on docker hub', label: 'DbGate on docker hub',
click() { click() {
require('electron').shell.openExternal('https://hub.docker.com/r/dbgate/dbgate'); electron.shell.openExternal('https://hub.docker.com/r/dbgate/dbgate');
}, },
}, },
{ {
label: 'Report problem or feature request', label: 'Report problem or feature request',
click() { click() {
require('electron').shell.openExternal('https://github.com/dbgate/dbgate/issues/new'); electron.shell.openExternal('https://github.com/dbgate/dbgate/issues/new');
}, },
}, },
commandItem('tabs.changelog'), commandItem('tabs.changelog'),
@@ -146,10 +155,27 @@ ipcMain.on('update-commands', async (event, arg) => {
menu.enabled = command.enabled; menu.enabled = command.enabled;
} }
}); });
ipcMain.on('close-window', async (event, arg) => {
mainWindow.close();
});
ipcMain.handle('showOpenDialog', async (event, options) => {
const res = electron.dialog.showOpenDialogSync(mainWindow, options);
return res;
});
ipcMain.handle('showSaveDialog', async (event, options) => {
const res = electron.dialog.showSaveDialogSync(mainWindow, options);
return res;
});
ipcMain.handle('showItemInFolder', async (event, path) => {
electron.shell.showItemInFolder(path);
});
ipcMain.handle('openExternal', async (event, url) => {
electron.shell.openExternal(url);
});
function createWindow() { function createWindow() {
const bounds = store.get('winBounds'); const bounds = initialConfig['winBounds'];
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 1200, width: 1200,
height: 800, height: 800,
@@ -158,10 +184,11 @@ function createWindow() {
icon: os.platform() == 'win32' ? 'icon.ico' : path.resolve(__dirname, '../icon.png'), icon: os.platform() == 'win32' ? 'icon.ico' : path.resolve(__dirname, '../icon.png'),
webPreferences: { webPreferences: {
nodeIntegration: true, nodeIntegration: true,
enableRemoteModule: true, contextIsolation: false,
}, },
}); });
if (store.get('winIsMaximized')) {
if (initialConfig['winIsMaximized']) {
mainWindow.maximize(); mainWindow.maximize();
} }
@@ -176,12 +203,15 @@ function createWindow() {
protocol: 'file:', protocol: 'file:',
slashes: true, slashes: true,
}); });
mainWindow.webContents.on('did-finish-load', function () {
// hideSplash();
});
mainWindow.on('close', () => { mainWindow.on('close', () => {
store.set('winBounds', mainWindow.getBounds()); fs.writeFileSync(
store.set('winIsMaximized', mainWindow.isMaximized()); configRootPath,
JSON.stringify({
winBounds: mainWindow.getBounds(),
winIsMaximized: mainWindow.isMaximized(),
}),
'utf-8'
);
}); });
mainWindow.loadURL(startUrl); mainWindow.loadURL(startUrl);
if (os.platform() == 'linux') { if (os.platform() == 'linux') {
@@ -189,31 +219,27 @@ function createWindow() {
} }
} }
if (process.env.ELECTRON_START_URL) { const apiPackage = path.join(
loadMainWindow(); __dirname,
} else { process.env.DEVMODE ? '../../packages/api/src/index' : '../packages/api/dist/bundle.js'
const apiProcess = fork(path.join(__dirname, '../packages/api/dist/bundle.js'), [ );
'--dynport',
'--is-electron-bundle',
'--native-modules',
path.join(__dirname, 'nativeModules'),
// '../../../src/nativeModules'
]);
apiProcess.on('message', msg => {
if (msg.msgtype == 'listening') {
const { port, authorization } = msg;
global['port'] = port;
global['authorization'] = authorization;
loadMainWindow();
}
});
}
// and load the index.html of the app. global.API_PACKAGE = apiPackage;
// mainWindow.loadURL('http://localhost:3000'); global.NATIVE_MODULES = path.join(__dirname, 'nativeModules');
// Open the DevTools. // console.log('global.API_PACKAGE', global.API_PACKAGE);
// mainWindow.webContents.openDevTools(); const api = require(apiPackage);
// console.log(
// 'REQUIRED',
// path.resolve(
// path.join(__dirname, process.env.DEVMODE ? '../../packages/api/src/index' : '../packages/api/dist/bundle.js')
// )
// );
const main = api.getMainModule();
main.initializeElectronSender(mainWindow.webContents);
main.useAllControllers(null, electron);
loadMainWindow();
// Emitted when the window is closed. // Emitted when the window is closed.
mainWindow.on('closed', function () { mainWindow.on('closed', function () {
@@ -225,7 +251,9 @@ function createWindow() {
} }
function onAppReady() { function onAppReady() {
if (!process.env.DEVMODE) {
autoUpdater.checkForUpdatesAndNotify(); autoUpdater.checkForUpdatesAndNotify();
}
createWindow(); createWindow();
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
FROM node:12-alpine FROM node:14-alpine
WORKDIR /home/dbgate-docker WORKDIR /home/dbgate-docker

View File

@@ -5,7 +5,7 @@ let fillContent = '';
if (process.platform == 'win32') { if (process.platform == 'win32') {
fillContent += `content.msnodesqlv8 = () => require('msnodesqlv8');`; fillContent += `content.msnodesqlv8 = () => require('msnodesqlv8');`;
} }
fillContent += `content['better-sqlite3-with-prebuilds'] = () => require('better-sqlite3-with-prebuilds');`; fillContent += `content['better-sqlite3'] = () => require('better-sqlite3');`;
const getContent = (empty) => ` const getContent = (empty) => `
// this file is generated automatically by script fillNativeModules.js, do not edit it manually // this file is generated automatically by script fillNativeModules.js, do not edit it manually

View File

@@ -1,6 +1,6 @@
{ {
"private": true, "private": true,
"version": "4.4.5-beta.2", "version": "4.4.5-beta.24",
"name": "dbgate-all", "name": "dbgate-all",
"workspaces": [ "workspaces": [
"packages/*", "packages/*",
@@ -9,6 +9,7 @@
], ],
"scripts": { "scripts": {
"start:api": "yarn workspace dbgate-api start", "start:api": "yarn workspace dbgate-api start",
"start:app": "cd app && yarn start",
"start:api:portal": "yarn workspace dbgate-api start:portal", "start:api:portal": "yarn workspace dbgate-api start:portal",
"start:api:covid": "yarn workspace dbgate-api start:covid", "start:api:covid": "yarn workspace dbgate-api start:covid",
"start:web": "yarn workspace dbgate-web dev", "start:web": "yarn workspace dbgate-web dev",

View File

@@ -1,6 +1,6 @@
DEVMODE=1 DEVMODE=1
CONNECTIONS=mysql,postgres CONNECTIONS=mysql,postgres,mongo,mongo2
LABEL_mysql=MySql localhost LABEL_mysql=MySql localhost
SERVER_mysql=localhost SERVER_mysql=localhost
@@ -15,3 +15,13 @@ USER_postgres=postgres
PASSWORD_postgres=test PASSWORD_postgres=test
PORT_postgres=5433 PORT_postgres=5433
ENGINE_postgres=postgres@dbgate-plugin-postgres ENGINE_postgres=postgres@dbgate-plugin-postgres
LABEL_mongo=Mongo URL
URL_mongo=mongodb://localhost:27017
ENGINE_mongo=mongo@dbgate-plugin-mongo
LABEL_mongo2=Mongo Server
SERVER_mongo2=localhost
ENGINE_mongo2=mongo@dbgate-plugin-mongo
# docker run -p 3000:3000 -e CONNECTIONS=mongo -e URL_mongo=mongodb://localhost:27017 -e ENGINE_mongo=mongo@dbgate-plugin-mongo -e LABEL_mongo=mongo dbgate/dbgate:beta

View File

@@ -19,7 +19,6 @@
"dependencies": { "dependencies": {
"async-lock": "^1.2.4", "async-lock": "^1.2.4",
"axios": "^0.21.1", "axios": "^0.21.1",
"better-sqlite3-with-prebuilds": "^7.1.8",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"bufferutil": "^4.0.1", "bufferutil": "^4.0.1",
"byline": "^5.0.0", "byline": "^5.0.0",
@@ -39,6 +38,7 @@
"fs-reverse": "^0.0.3", "fs-reverse": "^0.0.3",
"get-port": "^5.1.1", "get-port": "^5.1.1",
"http": "^0.0.0", "http": "^0.0.0",
"is-electron": "^2.2.1",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"json-stable-stringify": "^1.0.1", "json-stable-stringify": "^1.0.1",
"line-reader": "^0.4.0", "line-reader": "^0.4.0",
@@ -49,7 +49,6 @@
"node-ssh-forward": "^0.7.2", "node-ssh-forward": "^0.7.2",
"portfinder": "^1.0.28", "portfinder": "^1.0.28",
"simple-encryptor": "^4.0.0", "simple-encryptor": "^4.0.0",
"socket.io": "^2.3.0",
"tar": "^6.0.5", "tar": "^6.0.5",
"uuid": "^3.4.0" "uuid": "^3.4.0"
}, },
@@ -74,6 +73,7 @@
"webpack-cli": "^3.3.11" "webpack-cli": "^3.3.11"
}, },
"optionalDependencies": { "optionalDependencies": {
"msnodesqlv8": "^2.4.0" "better-sqlite3": "7.4.5",
"msnodesqlv8": "^2.4.4"
} }
} }

View File

@@ -10,7 +10,7 @@ const { saveFreeTableData } = require('../utility/freeTableStorage');
const loadFilesRecursive = require('../utility/loadFilesRecursive'); const loadFilesRecursive = require('../utility/loadFilesRecursive');
module.exports = { module.exports = {
folders_meta: 'get', folders_meta: true,
async folders() { async folders() {
const folders = await fs.readdir(archivedir()); const folders = await fs.readdir(archivedir());
return [ return [
@@ -27,14 +27,14 @@ module.exports = {
]; ];
}, },
createFolder_meta: 'post', createFolder_meta: true,
async createFolder({ folder }) { async createFolder({ folder }) {
await fs.mkdir(path.join(archivedir(), folder)); await fs.mkdir(path.join(archivedir(), folder));
socket.emitChanged('archive-folders-changed'); socket.emitChanged('archive-folders-changed');
return true; return true;
}, },
createLink_meta: 'post', createLink_meta: true,
async createLink({ linkedFolder }) { async createLink({ linkedFolder }) {
const folder = await this.getNewArchiveFolder({ database: path.parse(linkedFolder).name + '.link' }); const folder = await this.getNewArchiveFolder({ database: path.parse(linkedFolder).name + '.link' });
fs.writeFile(path.join(archivedir(), folder), linkedFolder); fs.writeFile(path.join(archivedir(), folder), linkedFolder);
@@ -43,7 +43,7 @@ module.exports = {
return folder; return folder;
}, },
files_meta: 'get', files_meta: true,
async files({ folder }) { async files({ folder }) {
const dir = resolveArchiveFolder(folder); const dir = resolveArchiveFolder(folder);
if (!(await fs.exists(dir))) return []; if (!(await fs.exists(dir))) return [];
@@ -70,23 +70,23 @@ module.exports = {
]; ];
}, },
refreshFiles_meta: 'post', refreshFiles_meta: true,
async refreshFiles({ folder }) { async refreshFiles({ folder }) {
socket.emitChanged(`archive-files-changed-${folder}`); socket.emitChanged(`archive-files-changed-${folder}`);
}, },
refreshFolders_meta: 'post', refreshFolders_meta: true,
async refreshFolders() { async refreshFolders() {
socket.emitChanged(`archive-folders-changed`); socket.emitChanged(`archive-folders-changed`);
}, },
deleteFile_meta: 'post', deleteFile_meta: true,
async deleteFile({ folder, file, fileType }) { async deleteFile({ folder, file, fileType }) {
await fs.unlink(path.join(resolveArchiveFolder(folder), `${file}.${fileType}`)); await fs.unlink(path.join(resolveArchiveFolder(folder), `${file}.${fileType}`));
socket.emitChanged(`archive-files-changed-${folder}`); socket.emitChanged(`archive-files-changed-${folder}`);
}, },
renameFile_meta: 'post', renameFile_meta: true,
async renameFile({ folder, file, newFile, fileType }) { async renameFile({ folder, file, newFile, fileType }) {
await fs.rename( await fs.rename(
path.join(resolveArchiveFolder(folder), `${file}.${fileType}`), path.join(resolveArchiveFolder(folder), `${file}.${fileType}`),
@@ -95,14 +95,14 @@ module.exports = {
socket.emitChanged(`archive-files-changed-${folder}`); socket.emitChanged(`archive-files-changed-${folder}`);
}, },
renameFolder_meta: 'post', renameFolder_meta: true,
async renameFolder({ folder, newFolder }) { async renameFolder({ folder, newFolder }) {
const uniqueName = await this.getNewArchiveFolder({ database: newFolder }); const uniqueName = await this.getNewArchiveFolder({ database: newFolder });
await fs.rename(path.join(archivedir(), folder), path.join(archivedir(), uniqueName)); await fs.rename(path.join(archivedir(), folder), path.join(archivedir(), uniqueName));
socket.emitChanged(`archive-folders-changed`); socket.emitChanged(`archive-folders-changed`);
}, },
deleteFolder_meta: 'post', deleteFolder_meta: true,
async deleteFolder({ folder }) { async deleteFolder({ folder }) {
if (!folder) throw new Error('Missing folder parameter'); if (!folder) throw new Error('Missing folder parameter');
if (folder.endsWith('.link')) { if (folder.endsWith('.link')) {
@@ -113,14 +113,14 @@ module.exports = {
socket.emitChanged(`archive-folders-changed`); socket.emitChanged(`archive-folders-changed`);
}, },
saveFreeTable_meta: 'post', saveFreeTable_meta: true,
async saveFreeTable({ folder, file, data }) { async saveFreeTable({ folder, file, data }) {
await saveFreeTableData(path.join(resolveArchiveFolder(folder), `${file}.jsonl`), data); await saveFreeTableData(path.join(resolveArchiveFolder(folder), `${file}.jsonl`), data);
socket.emitChanged(`archive-files-changed-${folder}`); socket.emitChanged(`archive-files-changed-${folder}`);
return true; return true;
}, },
loadFreeTable_meta: 'post', loadFreeTable_meta: true,
async loadFreeTable({ folder, file }) { async loadFreeTable({ folder, file }) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const fileStream = fs.createReadStream(path.join(resolveArchiveFolder(folder), `${file}.jsonl`)); const fileStream = fs.createReadStream(path.join(resolveArchiveFolder(folder), `${file}.jsonl`));

View File

@@ -21,7 +21,7 @@ module.exports = {
} }
}, },
get_meta: 'get', get_meta: true,
async get() { async get() {
const permissions = process.env.PERMISSIONS ? process.env.PERMISSIONS.split(',') : null; const permissions = process.env.PERMISSIONS ? process.env.PERMISSIONS.split(',') : null;
@@ -33,17 +33,17 @@ module.exports = {
}; };
}, },
platformInfo_meta: 'get', platformInfo_meta: true,
async platformInfo() { async platformInfo() {
return platformInfo; return platformInfo;
}, },
getSettings_meta: 'get', getSettings_meta: true,
async getSettings() { async getSettings() {
return this.settingsValue; return this.settingsValue;
}, },
updateSettings_meta: 'post', updateSettings_meta: true,
async updateSettings(values) { async updateSettings(values) {
if (!hasPermission(`settings/change`)) return false; if (!hasPermission(`settings/change`)) return false;
try { try {
@@ -60,7 +60,7 @@ module.exports = {
} }
}, },
changelog_meta: 'get', changelog_meta: true,
async changelog() { async changelog() {
const resp = await axios.default.get('https://raw.githubusercontent.com/dbgate/dbgate/master/CHANGELOG.md'); const resp = await axios.default.get('https://raw.githubusercontent.com/dbgate/dbgate/master/CHANGELOG.md');
return resp.data; return resp.data;

View File

@@ -8,6 +8,9 @@ const { datadir, filesdir } = require('../utility/directories');
const socket = require('../utility/socket'); const socket = require('../utility/socket');
const { encryptConnection } = require('../utility/crypting'); const { encryptConnection } = require('../utility/crypting');
const { handleProcessCommunication } = require('../utility/processComm'); const { handleProcessCommunication } = require('../utility/processComm');
const { pickSafeConnectionInfo } = require('../utility/crypting');
const processArgs = require('../utility/processArgs');
function getNamedArgs() { function getNamedArgs() {
const res = {}; const res = {};
@@ -37,7 +40,7 @@ function getDatabaseFileLabel(databaseFile) {
function getPortalCollections() { function getPortalCollections() {
if (process.env.CONNECTIONS) { if (process.env.CONNECTIONS) {
return _.compact(process.env.CONNECTIONS.split(',')).map(id => ({ const connections = _.compact(process.env.CONNECTIONS.split(',')).map(id => ({
_id: id, _id: id,
engine: process.env[`ENGINE_${id}`], engine: process.env[`ENGINE_${id}`],
server: process.env[`SERVER_${id}`], server: process.env[`SERVER_${id}`],
@@ -45,11 +48,22 @@ function getPortalCollections() {
password: process.env[`PASSWORD_${id}`], password: process.env[`PASSWORD_${id}`],
port: process.env[`PORT_${id}`], port: process.env[`PORT_${id}`],
databaseUrl: process.env[`URL_${id}`], databaseUrl: process.env[`URL_${id}`],
useDatabaseUrl: !!process.env[`URL_${id}`],
databaseFile: process.env[`FILE_${id}`], databaseFile: process.env[`FILE_${id}`],
defaultDatabase: process.env[`DATABASE_${id}`], defaultDatabase: process.env[`DATABASE_${id}`],
singleDatabase: !!process.env[`DATABASE_${id}`], singleDatabase: !!process.env[`DATABASE_${id}`],
displayName: process.env[`LABEL_${id}`], displayName: process.env[`LABEL_${id}`],
})); }));
console.log('Using connections from ENV variables:');
console.log(JSON.stringify(connections.map(pickSafeConnectionInfo), undefined, 2));
const noengine = connections.filter(x => !x.engine);
if (noengine.length > 0) {
console.log(
'Warning: Invalid CONNECTIONS configutation, missing ENGINE for connection ID:',
noengine.map(x => x._id)
);
}
return connections;
} }
const args = getNamedArgs(); const args = getNamedArgs();
@@ -126,29 +140,34 @@ module.exports = {
} }
}, },
list_meta: 'get', list_meta: true,
async list() { async list() {
return portalConnections || this.datastore.find(); return portalConnections || this.datastore.find();
}, },
test_meta: { test_meta: true,
method: 'post', test(connection) {
raw: true, const subprocess = fork(global['API_PACKAGE'] || process.argv[1], [
}, '--is-forked-api',
test(req, res) { '--start-process',
const subprocess = fork(process.argv[1], ['--start-process', 'connectProcess', ...process.argv.slice(3)]); 'connectProcess',
...processArgs.getPassArgs(),
// ...process.argv.slice(3),
]);
subprocess.send(connection);
return new Promise(resolve => {
subprocess.on('message', resp => { subprocess.on('message', resp => {
if (handleProcessCommunication(resp, subprocess)) return; if (handleProcessCommunication(resp, subprocess)) return;
// @ts-ignore // @ts-ignore
const { msgtype } = resp; const { msgtype } = resp;
if (msgtype == 'connected' || msgtype == 'error') { if (msgtype == 'connected' || msgtype == 'error') {
res.json(resp); resolve(resp);
} }
}); });
subprocess.send(req.body); });
}, },
save_meta: 'post', save_meta: true,
async save(connection) { async save(connection) {
if (portalConnections) return; if (portalConnections) return;
let res; let res;
@@ -162,7 +181,7 @@ module.exports = {
return res; return res;
}, },
update_meta: 'post', update_meta: true,
async update({ _id, values }) { async update({ _id, values }) {
if (portalConnections) return; if (portalConnections) return;
const res = await this.datastore.update({ _id }, { $set: values }); const res = await this.datastore.update({ _id }, { $set: values });
@@ -170,7 +189,7 @@ module.exports = {
return res; return res;
}, },
updateDatabase_meta: 'post', updateDatabase_meta: true,
async updateDatabase({ conid, database, values }) { async updateDatabase({ conid, database, values }) {
if (portalConnections) return; if (portalConnections) return;
const conn = await this.datastore.find({ _id: conid }); const conn = await this.datastore.find({ _id: conid });
@@ -185,7 +204,7 @@ module.exports = {
return res; return res;
}, },
delete_meta: 'post', delete_meta: true,
async delete(connection) { async delete(connection) {
if (portalConnections) return; if (portalConnections) return;
const res = await this.datastore.remove(_.pick(connection, '_id')); const res = await this.datastore.remove(_.pick(connection, '_id'));
@@ -193,14 +212,14 @@ module.exports = {
return res; return res;
}, },
get_meta: 'get', get_meta: true,
async get({ conid }) { async get({ conid }) {
if (portalConnections) return portalConnections.find(x => x._id == conid); if (portalConnections) return portalConnections.find(x => x._id == conid) || null;
const res = await this.datastore.find({ _id: conid }); const res = await this.datastore.find({ _id: conid });
return res[0]; return res[0] || null;
}, },
newSqliteDatabase_meta: 'post', newSqliteDatabase_meta: true,
async newSqliteDatabase({ file }) { async newSqliteDatabase({ file }) {
const sqliteDir = path.join(filesdir(), 'sqlite'); const sqliteDir = path.join(filesdir(), 'sqlite');
if (!(await fs.exists(sqliteDir))) { if (!(await fs.exists(sqliteDir))) {

View File

@@ -25,6 +25,7 @@ const requireEngineDriver = require('../utility/requireEngineDriver');
const generateDeploySql = require('../shell/generateDeploySql'); const generateDeploySql = require('../shell/generateDeploySql');
const { createTwoFilesPatch } = require('diff'); const { createTwoFilesPatch } = require('diff');
const diff2htmlPage = require('../utility/diff2htmlPage'); const diff2htmlPage = require('../utility/diff2htmlPage');
const processArgs = require('../utility/processArgs');
module.exports = { module.exports = {
/** @type {import('dbgate-types').OpenedDatabaseConnection[]} */ /** @type {import('dbgate-types').OpenedDatabaseConnection[]} */
@@ -74,10 +75,12 @@ module.exports = {
const existing = this.opened.find(x => x.conid == conid && x.database == database); const existing = this.opened.find(x => x.conid == conid && x.database == database);
if (existing) return existing; if (existing) return existing;
const connection = await connections.get({ conid }); const connection = await connections.get({ conid });
const subprocess = fork(process.argv[1], [ const subprocess = fork(global['API_PACKAGE'] || process.argv[1], [
'--is-forked-api',
'--start-process', '--start-process',
'databaseConnectionProcess', 'databaseConnectionProcess',
...process.argv.slice(3), ...processArgs.getPassArgs(),
// ...process.argv.slice(3),
]); ]);
const lastClosed = this.closed[`${conid}/${database}`]; const lastClosed = this.closed[`${conid}/${database}`];
const newOpened = { const newOpened = {
@@ -121,7 +124,7 @@ module.exports = {
return promise; return promise;
}, },
queryData_meta: 'post', queryData_meta: true,
async queryData({ conid, database, sql }) { async queryData({ conid, database, sql }) {
console.log(`Processing query, conid=${conid}, database=${database}, sql=${sql}`); console.log(`Processing query, conid=${conid}, database=${database}, sql=${sql}`);
const opened = await this.ensureOpened(conid, database); const opened = await this.ensureOpened(conid, database);
@@ -132,7 +135,7 @@ module.exports = {
return res; return res;
}, },
runScript_meta: 'post', runScript_meta: true,
async runScript({ conid, database, sql }) { async runScript({ conid, database, sql }) {
console.log(`Processing script, conid=${conid}, database=${database}, sql=${sql}`); console.log(`Processing script, conid=${conid}, database=${database}, sql=${sql}`);
const opened = await this.ensureOpened(conid, database); const opened = await this.ensureOpened(conid, database);
@@ -140,21 +143,21 @@ module.exports = {
return res; return res;
}, },
collectionData_meta: 'post', collectionData_meta: true,
async collectionData({ conid, database, options }) { async collectionData({ conid, database, options }) {
const opened = await this.ensureOpened(conid, database); const opened = await this.ensureOpened(conid, database);
const res = await this.sendRequest(opened, { msgtype: 'collectionData', options }); const res = await this.sendRequest(opened, { msgtype: 'collectionData', options });
return res.result; return res.result;
}, },
updateCollection_meta: 'post', updateCollection_meta: true,
async updateCollection({ conid, database, changeSet }) { async updateCollection({ conid, database, changeSet }) {
const opened = await this.ensureOpened(conid, database); const opened = await this.ensureOpened(conid, database);
const res = await this.sendRequest(opened, { msgtype: 'updateCollection', changeSet }); const res = await this.sendRequest(opened, { msgtype: 'updateCollection', changeSet });
return res.result; return res.result;
}, },
status_meta: 'get', status_meta: true,
async status({ conid, database }) { async status({ conid, database }) {
const existing = this.opened.find(x => x.conid == conid && x.database == database); const existing = this.opened.find(x => x.conid == conid && x.database == database);
if (existing) { if (existing) {
@@ -176,7 +179,7 @@ module.exports = {
}; };
}, },
ping_meta: 'post', ping_meta: true,
async ping({ conid, database }) { async ping({ conid, database }) {
let existing = this.opened.find(x => x.conid == conid && x.database == database); let existing = this.opened.find(x => x.conid == conid && x.database == database);
@@ -192,7 +195,7 @@ module.exports = {
}; };
}, },
refresh_meta: 'post', refresh_meta: true,
async refresh({ conid, database, keepOpen }) { async refresh({ conid, database, keepOpen }) {
if (!keepOpen) this.close(conid, database); if (!keepOpen) this.close(conid, database);
@@ -200,7 +203,7 @@ module.exports = {
return { status: 'ok' }; return { status: 'ok' };
}, },
syncModel_meta: 'post', syncModel_meta: true,
async syncModel({ conid, database }) { async syncModel({ conid, database }) {
const conn = await this.ensureOpened(conid, database); const conn = await this.ensureOpened(conid, database);
conn.subprocess.send({ msgtype: 'syncModel' }); conn.subprocess.send({ msgtype: 'syncModel' });
@@ -224,13 +227,13 @@ module.exports = {
} }
}, },
disconnect_meta: 'post', disconnect_meta: true,
async disconnect({ conid, database }) { async disconnect({ conid, database }) {
await this.close(conid, database, true); await this.close(conid, database, true);
return { status: 'ok' }; return { status: 'ok' };
}, },
structure_meta: 'get', structure_meta: true,
async structure({ conid, database }) { async structure({ conid, database }) {
if (conid == '__model') { if (conid == '__model') {
const model = await importDbModel(database); const model = await importDbModel(database);
@@ -247,13 +250,14 @@ module.exports = {
// }; // };
}, },
serverVersion_meta: 'get', serverVersion_meta: true,
async serverVersion({ conid, database }) { async serverVersion({ conid, database }) {
if (!conid) return null;
const opened = await this.ensureOpened(conid, database); const opened = await this.ensureOpened(conid, database);
return opened.serverVersion; return opened.serverVersion || null;
}, },
sqlPreview_meta: 'post', sqlPreview_meta: true,
async sqlPreview({ conid, database, objects, options }) { async sqlPreview({ conid, database, objects, options }) {
// wait for structure // wait for structure
await this.structure({ conid, database }); await this.structure({ conid, database });
@@ -263,7 +267,7 @@ module.exports = {
return res; return res;
}, },
exportModel_meta: 'post', exportModel_meta: true,
async exportModel({ conid, database }) { async exportModel({ conid, database }) {
const archiveFolder = await archive.getNewArchiveFolder({ database }); const archiveFolder = await archive.getNewArchiveFolder({ database });
await fs.mkdir(path.join(archivedir(), archiveFolder)); await fs.mkdir(path.join(archivedir(), archiveFolder));
@@ -273,10 +277,13 @@ module.exports = {
return { archiveFolder }; return { archiveFolder };
}, },
generateDeploySql_meta: 'post', generateDeploySql_meta: true,
async generateDeploySql({ conid, database, archiveFolder }) { async generateDeploySql({ conid, database, archiveFolder }) {
const opened = await this.ensureOpened(conid, database); const opened = await this.ensureOpened(conid, database);
const res = await this.sendRequest(opened, { msgtype: 'generateDeploySql', modelFolder: resolveArchiveFolder(archiveFolder) }); const res = await this.sendRequest(opened, {
msgtype: 'generateDeploySql',
modelFolder: resolveArchiveFolder(archiveFolder),
});
return res; return res;
// const connection = await connections.get({ conid }); // const connection = await connections.get({ conid });
@@ -300,7 +307,7 @@ module.exports = {
// }; // };
// return sql; // return sql;
}, },
// runCommand_meta: 'post', // runCommand_meta: true,
// async runCommand({ conid, database, sql }) { // async runCommand({ conid, database, sql }) {
// console.log(`Running SQL command , conid=${conid}, database=${database}, sql=${sql}`); // console.log(`Running SQL command , conid=${conid}, database=${database}, sql=${sql}`);
// const opened = await this.ensureOpened(conid, database); // const opened = await this.ensureOpened(conid, database);
@@ -343,7 +350,7 @@ module.exports = {
return res; return res;
}, },
generateDbDiffReport_meta: 'post', generateDbDiffReport_meta: true,
async generateDbDiffReport({ filePath, sourceConid, sourceDatabase, targetConid, targetDatabase }) { async generateDbDiffReport({ filePath, sourceConid, sourceDatabase, targetConid, targetDatabase }) {
const unifiedDiff = await this.getUnifiedDiff({ sourceConid, sourceDatabase, targetConid, targetDatabase }); const unifiedDiff = await this.getUnifiedDiff({ sourceConid, sourceDatabase, targetConid, targetDatabase });

View File

@@ -20,7 +20,7 @@ function deserialize(format, text) {
} }
module.exports = { module.exports = {
list_meta: 'get', list_meta: true,
async list({ folder }) { async list({ folder }) {
if (!hasPermission(`files/${folder}/read`)) return []; if (!hasPermission(`files/${folder}/read`)) return [];
const dir = path.join(filesdir(), folder); const dir = path.join(filesdir(), folder);
@@ -29,7 +29,7 @@ module.exports = {
return files; return files;
}, },
listAll_meta: 'get', listAll_meta: true,
async listAll() { async listAll() {
const folders = await fs.readdir(filesdir()); const folders = await fs.readdir(filesdir());
const res = []; const res = [];
@@ -42,7 +42,7 @@ module.exports = {
return res; return res;
}, },
delete_meta: 'post', delete_meta: true,
async delete({ folder, file }) { async delete({ folder, file }) {
if (!hasPermission(`files/${folder}/write`)) return; if (!hasPermission(`files/${folder}/write`)) return;
await fs.unlink(path.join(filesdir(), folder, file)); await fs.unlink(path.join(filesdir(), folder, file));
@@ -50,7 +50,7 @@ module.exports = {
socket.emitChanged(`all-files-changed`); socket.emitChanged(`all-files-changed`);
}, },
rename_meta: 'post', rename_meta: true,
async rename({ folder, file, newFile }) { async rename({ folder, file, newFile }) {
if (!hasPermission(`files/${folder}/write`)) return; if (!hasPermission(`files/${folder}/write`)) return;
await fs.rename(path.join(filesdir(), folder, file), path.join(filesdir(), folder, newFile)); await fs.rename(path.join(filesdir(), folder, file), path.join(filesdir(), folder, newFile));
@@ -58,7 +58,7 @@ module.exports = {
socket.emitChanged(`all-files-changed`); socket.emitChanged(`all-files-changed`);
}, },
copy_meta: 'post', copy_meta: true,
async copy({ folder, file, newFile }) { async copy({ folder, file, newFile }) {
if (!hasPermission(`files/${folder}/write`)) return; if (!hasPermission(`files/${folder}/write`)) return;
await fs.copyFile(path.join(filesdir(), folder, file), path.join(filesdir(), folder, newFile)); await fs.copyFile(path.join(filesdir(), folder, file), path.join(filesdir(), folder, newFile));
@@ -66,7 +66,7 @@ module.exports = {
socket.emitChanged(`all-files-changed`); socket.emitChanged(`all-files-changed`);
}, },
load_meta: 'post', load_meta: true,
async load({ folder, file, format }) { async load({ folder, file, format }) {
if (folder.startsWith('archive:')) { if (folder.startsWith('archive:')) {
const text = await fs.readFile(path.join(resolveArchiveFolder(folder.substring('archive:'.length)), file), { const text = await fs.readFile(path.join(resolveArchiveFolder(folder.substring('archive:'.length)), file), {
@@ -80,7 +80,7 @@ module.exports = {
} }
}, },
save_meta: 'post', save_meta: true,
async save({ folder, file, data, format }) { async save({ folder, file, data, format }) {
if (folder.startsWith('archive:')) { if (folder.startsWith('archive:')) {
const dir = resolveArchiveFolder(folder.substring('archive:'.length)); const dir = resolveArchiveFolder(folder.substring('archive:'.length));
@@ -101,12 +101,12 @@ module.exports = {
} }
}, },
saveAs_meta: 'post', saveAs_meta: true,
async saveAs({ filePath, data, format }) { async saveAs({ filePath, data, format }) {
await fs.writeFile(filePath, serialize(format, data)); await fs.writeFile(filePath, serialize(format, data));
}, },
favorites_meta: 'get', favorites_meta: true,
async favorites() { async favorites() {
if (!hasPermission(`files/favorites/read`)) return []; if (!hasPermission(`files/favorites/read`)) return [];
const dir = path.join(filesdir(), 'favorites'); const dir = path.join(filesdir(), 'favorites');
@@ -125,7 +125,7 @@ module.exports = {
return res; return res;
}, },
generateUploadsFile_meta: 'get', generateUploadsFile_meta: true,
async generateUploadsFile() { async generateUploadsFile() {
const fileName = `${uuidv1()}.html`; const fileName = `${uuidv1()}.html`;
return { return {
@@ -134,7 +134,7 @@ module.exports = {
}; };
}, },
exportChart_meta: 'post', exportChart_meta: true,
async exportChart({ filePath, title, config, image }) { async exportChart({ filePath, title, config, image }) {
const fileName = path.parse(filePath).base; const fileName = path.parse(filePath).base;
const imageFile = fileName.replace('.html', '-preview.png'); const imageFile = fileName.replace('.html', '-preview.png');

View File

@@ -104,7 +104,7 @@ module.exports = {
return datastore; return datastore;
}, },
getInfo_meta: 'get', getInfo_meta: true,
async getInfo({ jslid }) { async getInfo({ jslid }) {
const file = getJslFileName(jslid); const file = getJslFileName(jslid);
const firstLine = await readFirstLine(file); const firstLine = await readFirstLine(file);
@@ -112,13 +112,13 @@ module.exports = {
return null; return null;
}, },
getRows_meta: 'post', getRows_meta: true,
async getRows({ jslid, offset, limit, filters }) { async getRows({ jslid, offset, limit, filters }) {
const datastore = await this.ensureDatastore(jslid); const datastore = await this.ensureDatastore(jslid);
return datastore.getRows(offset, limit, _.isEmpty(filters) ? null : filters); return datastore.getRows(offset, limit, _.isEmpty(filters) ? null : filters);
}, },
getStats_meta: 'get', getStats_meta: true,
getStats({ jslid }) { getStats({ jslid }) {
const file = `${getJslFileName(jslid)}.stats`; const file = `${getJslFileName(jslid)}.stats`;
if (fs.existsSync(file)) { if (fs.existsSync(file)) {
@@ -146,7 +146,7 @@ module.exports = {
// } // }
}, },
saveFreeTable_meta: 'post', saveFreeTable_meta: true,
async saveFreeTable({ jslid, data }) { async saveFreeTable({ jslid, data }) {
saveFreeTableData(getJslFileName(jslid), data); saveFreeTableData(getJslFileName(jslid), data);
return true; return true;

View File

@@ -7,14 +7,14 @@ function pickObjectNames(array) {
} }
module.exports = { module.exports = {
// tableData_meta: 'get', // tableData_meta: true,
// async tableData({ conid, database, schemaName, pureName }) { // async tableData({ conid, database, schemaName, pureName }) {
// const opened = await databaseConnections.ensureOpened(conid, database); // const opened = await databaseConnections.ensureOpened(conid, database);
// const res = await databaseConnections.sendRequest(opened, { msgtype: 'tableData', schemaName, pureName }); // const res = await databaseConnections.sendRequest(opened, { msgtype: 'tableData', schemaName, pureName });
// return res; // return res;
// }, // },
listObjects_meta: 'get', listObjects_meta: true,
async listObjects({ conid, database }) { async listObjects({ conid, database }) {
const opened = await databaseConnections.ensureOpened(conid, database); const opened = await databaseConnections.ensureOpened(conid, database);
const types = ['tables', 'collections', 'views', 'procedures', 'functions', 'triggers']; const types = ['tables', 'collections', 'views', 'procedures', 'functions', 'triggers'];
@@ -27,7 +27,7 @@ module.exports = {
); );
}, },
tableInfo_meta: 'get', tableInfo_meta: true,
async tableInfo({ conid, database, schemaName, pureName }) { async tableInfo({ conid, database, schemaName, pureName }) {
const opened = await databaseConnections.ensureOpened(conid, database); const opened = await databaseConnections.ensureOpened(conid, database);
const table = opened.structure.tables.find(x => x.pureName == pureName && x.schemaName == schemaName); const table = opened.structure.tables.find(x => x.pureName == pureName && x.schemaName == schemaName);
@@ -38,7 +38,7 @@ module.exports = {
}; };
}, },
sqlObjectInfo_meta: 'get', sqlObjectInfo_meta: true,
async sqlObjectInfo({ objectTypeField, conid, database, schemaName, pureName }) { async sqlObjectInfo({ objectTypeField, conid, database, schemaName, pureName }) {
const opened = await databaseConnections.ensureOpened(conid, database); const opened = await databaseConnections.ensureOpened(conid, database);
const res = opened.structure[objectTypeField].find(x => x.pureName == pureName && x.schemaName == schemaName); const res = opened.structure[objectTypeField].find(x => x.pureName == pureName && x.schemaName == schemaName);

View File

@@ -12,7 +12,7 @@ const _ = require('lodash');
const packagedPluginsContent = require('../packagedPluginsContent'); const packagedPluginsContent = require('../packagedPluginsContent');
module.exports = { module.exports = {
script_meta: 'get', script_meta: true,
async script({ packageName }) { async script({ packageName }) {
const packagedContent = packagedPluginsContent(); const packagedContent = packagedPluginsContent();
@@ -30,7 +30,7 @@ module.exports = {
return data; return data;
}, },
search_meta: 'get', search_meta: true,
async search({ filter }) { async search({ filter }) {
// DOCS: https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md#get-v1search // DOCS: https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md#get-v1search
const resp = await axios.default.get( const resp = await axios.default.get(
@@ -40,7 +40,7 @@ module.exports = {
return (objects || []).map(x => x.package); return (objects || []).map(x => x.package);
}, },
info_meta: 'get', info_meta: true,
async info({ packageName }) { async info({ packageName }) {
try { try {
const infoResp = await axios.default.get(`https://registry.npmjs.org/${packageName}`); const infoResp = await axios.default.get(`https://registry.npmjs.org/${packageName}`);
@@ -63,7 +63,7 @@ module.exports = {
} }
}, },
installed_meta: 'get', installed_meta: true,
async installed() { async installed() {
const packagedContent = packagedPluginsContent(); const packagedContent = packagedPluginsContent();
@@ -107,7 +107,7 @@ module.exports = {
// await fs.writeFile(path.join(datadir(), 'removed-plugins'), this.removedPlugins.join('\n')); // await fs.writeFile(path.join(datadir(), 'removed-plugins'), this.removedPlugins.join('\n'));
// }, // },
install_meta: 'post', install_meta: true,
async install({ packageName }) { async install({ packageName }) {
if (!hasPermission(`plugins/install`)) return; if (!hasPermission(`plugins/install`)) return;
const dir = path.join(pluginsdir(), packageName); const dir = path.join(pluginsdir(), packageName);
@@ -120,7 +120,7 @@ module.exports = {
// await this.saveRemovePlugins(); // await this.saveRemovePlugins();
}, },
uninstall_meta: 'post', uninstall_meta: true,
async uninstall({ packageName }) { async uninstall({ packageName }) {
if (!hasPermission(`plugins/install`)) return; if (!hasPermission(`plugins/install`)) return;
const dir = path.join(pluginsdir(), packageName); const dir = path.join(pluginsdir(), packageName);
@@ -130,7 +130,7 @@ module.exports = {
await this.saveRemovePlugins(); await this.saveRemovePlugins();
}, },
upgrade_meta: 'post', upgrade_meta: true,
async upgrade({ packageName }) { async upgrade({ packageName }) {
if (!hasPermission(`plugins/install`)) return; if (!hasPermission(`plugins/install`)) return;
const dir = path.join(pluginsdir(), packageName); const dir = path.join(pluginsdir(), packageName);
@@ -143,13 +143,13 @@ module.exports = {
socket.emitChanged(`installed-plugins-changed`); socket.emitChanged(`installed-plugins-changed`);
}, },
command_meta: 'post', command_meta: true,
async command({ packageName, command, args }) { async command({ packageName, command, args }) {
const content = requirePlugin(packageName); const content = requirePlugin(packageName);
return content.commands[command](args); return content.commands[command](args);
}, },
authTypes_meta: 'get', authTypes_meta: true,
async authTypes({ engine }) { async authTypes({ engine }) {
const packageName = extractPackageName(engine); const packageName = extractPackageName(engine);
const content = requirePlugin(packageName); const content = requirePlugin(packageName);

View File

@@ -34,7 +34,7 @@ function readCore(reader, skip, limit, filter) {
} }
module.exports = { module.exports = {
read_meta: 'get', read_meta: true,
async read({ skip, limit, filter }) { async read({ skip, limit, filter }) {
const fileName = path.join(datadir(), 'query-history.jsonl'); const fileName = path.join(datadir(), 'query-history.jsonl');
// @ts-ignore // @ts-ignore
@@ -44,7 +44,7 @@ module.exports = {
return res; return res;
}, },
write_meta: 'post', write_meta: true,
async write({ data }) { async write({ data }) {
const fileName = path.join(datadir(), 'query-history.jsonl'); const fileName = path.join(datadir(), 'query-history.jsonl');
await fs.appendFile(fileName, JSON.stringify(data) + '\n'); await fs.appendFile(fileName, JSON.stringify(data) + '\n');

View File

@@ -8,6 +8,7 @@ const { fork } = require('child_process');
const { rundir, uploadsdir, pluginsdir, getPluginBackendPath, packagedPluginList } = require('../utility/directories'); const { rundir, uploadsdir, pluginsdir, getPluginBackendPath, packagedPluginList } = require('../utility/directories');
const { extractShellApiPlugins, extractShellApiFunctionName } = require('dbgate-tools'); const { extractShellApiPlugins, extractShellApiFunctionName } = require('dbgate-tools');
const { handleProcessCommunication } = require('../utility/processComm'); const { handleProcessCommunication } = require('../utility/processComm');
const processArgs = require('../utility/processArgs');
function extractPlugins(script) { function extractPlugins(script) {
const requireRegex = /\s*\/\/\s*@require\s+([^\s]+)\s*\n/g; const requireRegex = /\s*\/\/\s*@require\s+([^\s]+)\s*\n/g;
@@ -98,15 +99,22 @@ module.exports = {
const pluginNames = _.union(fs.readdirSync(pluginsdir()), packagedPluginList); const pluginNames = _.union(fs.readdirSync(pluginsdir()), packagedPluginList);
console.log(`RUNNING SCRIPT ${scriptFile}`); console.log(`RUNNING SCRIPT ${scriptFile}`);
// const subprocess = fork(scriptFile, ['--checkParent', '--max-old-space-size=8192'], { // const subprocess = fork(scriptFile, ['--checkParent', '--max-old-space-size=8192'], {
const subprocess = fork(scriptFile, ['--checkParent', ...process.argv.slice(3)], { const subprocess = fork(
scriptFile,
[
'--checkParent', // ...process.argv.slice(3)
...processArgs.getPassArgs(),
],
{
cwd: directory, cwd: directory,
stdio: ['ignore', 'pipe', 'pipe', 'ipc'], stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
env: { env: {
...process.env, ...process.env,
DBGATE_API: global['dbgateApiModulePath'] || process.argv[1], DBGATE_API: global['API_PACKAGE'] || global['dbgateApiModulePath'] || process.argv[1],
..._.fromPairs(pluginNames.map(name => [`PLUGIN_${_.camelCase(name)}`, getPluginBackendPath(name)])), ..._.fromPairs(pluginNames.map(name => [`PLUGIN_${_.camelCase(name)}`, getPluginBackendPath(name)])),
}, },
}); }
);
const pipeDispatcher = severity => data => const pipeDispatcher = severity => data =>
this.dispatchMessage(runid, { severity, message: data.toString().trim() }); this.dispatchMessage(runid, { severity, message: data.toString().trim() });
@@ -136,21 +144,21 @@ module.exports = {
if (handleProcessCommunication(message, subprocess)) return; if (handleProcessCommunication(message, subprocess)) return;
this[`handle_${msgtype}`](runid, message); this[`handle_${msgtype}`](runid, message);
}); });
return newOpened; return _.pick(newOpened, ['runid']);
}, },
start_meta: 'post', start_meta: true,
async start({ script }) { async start({ script }) {
const runid = uuidv1(); const runid = uuidv1();
return this.startCore(runid, scriptTemplate(script, false)); return this.startCore(runid, scriptTemplate(script, false));
}, },
getNodeScript_meta: 'post', getNodeScript_meta: true,
async getNodeScript({ script }) { async getNodeScript({ script }) {
return scriptTemplate(script, true); return scriptTemplate(script, true);
}, },
cancel_meta: 'post', cancel_meta: true,
async cancel({ runid }) { async cancel({ runid }) {
const runner = this.opened.find(x => x.runid == runid); const runner = this.opened.find(x => x.runid == runid);
if (!runner) { if (!runner) {
@@ -160,7 +168,7 @@ module.exports = {
return { state: 'ok' }; return { state: 'ok' };
}, },
files_meta: 'get', files_meta: true,
async files({ runid }) { async files({ runid }) {
const directory = path.join(rundir(), runid); const directory = path.join(rundir(), runid);
const files = await fs.readdir(directory); const files = await fs.readdir(directory);
@@ -176,7 +184,7 @@ module.exports = {
return res; return res;
}, },
loadReader_meta: 'post', loadReader_meta: true,
async loadReader({ functionName, props }) { async loadReader({ functionName, props }) {
const promise = new Promise((resolve, reject) => { const promise = new Promise((resolve, reject) => {
const runid = uuidv1(); const runid = uuidv1();

View File

@@ -6,6 +6,7 @@ const AsyncLock = require('async-lock');
const { handleProcessCommunication } = require('../utility/processComm'); const { handleProcessCommunication } = require('../utility/processComm');
const lock = new AsyncLock(); const lock = new AsyncLock();
const config = require('./config'); const config = require('./config');
const processArgs = require('../utility/processArgs');
module.exports = { module.exports = {
opened: [], opened: [],
@@ -37,10 +38,12 @@ module.exports = {
const existing = this.opened.find(x => x.conid == conid); const existing = this.opened.find(x => x.conid == conid);
if (existing) return existing; if (existing) return existing;
const connection = await connections.get({ conid }); const connection = await connections.get({ conid });
const subprocess = fork(process.argv[1], [ const subprocess = fork(global['API_PACKAGE'] || process.argv[1], [
'--is-forked-api',
'--start-process', '--start-process',
'serverConnectionProcess', 'serverConnectionProcess',
...process.argv.slice(3), ...processArgs.getPassArgs(),
// ...process.argv.slice(3),
]); ]);
const newOpened = { const newOpened = {
conid, conid,
@@ -86,25 +89,25 @@ module.exports = {
} }
}, },
disconnect_meta: 'post', disconnect_meta: true,
async disconnect({ conid }) { async disconnect({ conid }) {
await this.close(conid, true); await this.close(conid, true);
return { status: 'ok' }; return { status: 'ok' };
}, },
listDatabases_meta: 'get', listDatabases_meta: true,
async listDatabases({ conid }) { async listDatabases({ conid }) {
const opened = await this.ensureOpened(conid); const opened = await this.ensureOpened(conid);
return opened.databases; return opened.databases;
}, },
version_meta: 'get', version_meta: true,
async version({ conid }) { async version({ conid }) {
const opened = await this.ensureOpened(conid); const opened = await this.ensureOpened(conid);
return opened.version; return opened.version;
}, },
serverStatus_meta: 'get', serverStatus_meta: true,
async serverStatus() { async serverStatus() {
return { return {
...this.closed, ...this.closed,
@@ -112,7 +115,7 @@ module.exports = {
}; };
}, },
ping_meta: 'post', ping_meta: true,
async ping({ connections }) { async ping({ connections }) {
await Promise.all( await Promise.all(
_.uniq(connections).map(async conid => { _.uniq(connections).map(async conid => {
@@ -128,7 +131,7 @@ module.exports = {
return { status: 'ok' }; return { status: 'ok' };
}, },
refresh_meta: 'post', refresh_meta: true,
async refresh({ conid, keepOpen }) { async refresh({ conid, keepOpen }) {
if (!keepOpen) this.close(conid); if (!keepOpen) this.close(conid);
@@ -136,7 +139,7 @@ module.exports = {
return { status: 'ok' }; return { status: 'ok' };
}, },
createDatabase_meta: 'post', createDatabase_meta: true,
async createDatabase({ conid, name }) { async createDatabase({ conid, name }) {
const opened = await this.ensureOpened(conid); const opened = await this.ensureOpened(conid);
opened.subprocess.send({ msgtype: 'createDatabase', name }); opened.subprocess.send({ msgtype: 'createDatabase', name });

View File

@@ -5,6 +5,7 @@ const socket = require('../utility/socket');
const { fork } = require('child_process'); const { fork } = require('child_process');
const jsldata = require('./jsldata'); const jsldata = require('./jsldata');
const { handleProcessCommunication } = require('../utility/processComm'); const { handleProcessCommunication } = require('../utility/processComm');
const processArgs = require('../utility/processArgs');
module.exports = { module.exports = {
/** @type {import('dbgate-types').OpenedSession[]} */ /** @type {import('dbgate-types').OpenedSession[]} */
@@ -61,11 +62,17 @@ module.exports = {
handle_ping() {}, handle_ping() {},
create_meta: 'post', create_meta: true,
async create({ conid, database }) { async create({ conid, database }) {
const sesid = uuidv1(); const sesid = uuidv1();
const connection = await connections.get({ conid }); const connection = await connections.get({ conid });
const subprocess = fork(process.argv[1], ['--start-process', 'sessionProcess', ...process.argv.slice(3)]); const subprocess = fork(global['API_PACKAGE'] || process.argv[1], [
'--is-forked-api',
'--start-process',
'sessionProcess',
...processArgs.getPassArgs(),
// ...process.argv.slice(3),
]);
const newOpened = { const newOpened = {
conid, conid,
database, database,
@@ -81,10 +88,10 @@ module.exports = {
this[`handle_${msgtype}`](sesid, message); this[`handle_${msgtype}`](sesid, message);
}); });
subprocess.send({ msgtype: 'connect', ...connection, database }); subprocess.send({ msgtype: 'connect', ...connection, database });
return newOpened; return _.pick(newOpened, ['conid', 'database', 'sesid']);
}, },
executeQuery_meta: 'post', executeQuery_meta: true,
async executeQuery({ sesid, sql }) { async executeQuery({ sesid, sql }) {
const session = this.opened.find(x => x.sesid == sesid); const session = this.opened.find(x => x.sesid == sesid);
if (!session) { if (!session) {
@@ -98,7 +105,7 @@ module.exports = {
return { state: 'ok' }; return { state: 'ok' };
}, },
// cancel_meta: 'post', // cancel_meta: true,
// async cancel({ sesid }) { // async cancel({ sesid }) {
// const session = this.opened.find((x) => x.sesid == sesid); // const session = this.opened.find((x) => x.sesid == sesid);
// if (!session) { // if (!session) {
@@ -108,7 +115,7 @@ module.exports = {
// return { state: 'ok' }; // return { state: 'ok' };
// }, // },
kill_meta: 'post', kill_meta: true,
async kill({ sesid }) { async kill({ sesid }) {
const session = this.opened.find(x => x.sesid == sesid); const session = this.opened.find(x => x.sesid == sesid);
if (!session) { if (!session) {
@@ -119,7 +126,7 @@ module.exports = {
return { state: 'ok' }; return { state: 'ok' };
}, },
// runCommand_meta: 'post', // runCommand_meta: true,
// async runCommand({ conid, database, sql }) { // async runCommand({ conid, database, sql }) {
// console.log(`Running SQL command , conid=${conid}, database=${database}, sql=${sql}`); // console.log(`Running SQL command , conid=${conid}, database=${database}, sql=${sql}`);
// const opened = await this.ensureOpened(conid, database); // const opened = await this.ensureOpened(conid, database);

View File

@@ -8,7 +8,7 @@ if (processArgs.startProcess) {
const proc = require('./proc'); const proc = require('./proc');
const module = proc[processArgs.startProcess]; const module = proc[processArgs.startProcess];
module.start(); module.start();
} else if (!module['parent'] && !processArgs.checkParent) { } else if (!processArgs.checkParent && !global['API_PACKAGE'] && !global['dbgateApiModulePath']) {
const main = require('./main'); const main = require('./main');
main.start(); main.start();

View File

@@ -4,12 +4,8 @@ const bodyParser = require('body-parser');
const fileUpload = require('express-fileupload'); const fileUpload = require('express-fileupload');
const http = require('http'); const http = require('http');
const cors = require('cors'); const cors = require('cors');
const io = require('socket.io');
const fs = require('fs');
const getPort = require('get-port'); const getPort = require('get-port');
const childProcessChecker = require('./utility/childProcessChecker');
const path = require('path'); const path = require('path');
const crypto = require('crypto');
const useController = require('./utility/useController'); const useController = require('./utility/useController');
const socket = require('./utility/socket'); const socket = require('./utility/socket');
@@ -31,10 +27,7 @@ const queryHistory = require('./controllers/queryHistory');
const { rundir } = require('./utility/directories'); const { rundir } = require('./utility/directories');
const platformInfo = require('./utility/platformInfo'); const platformInfo = require('./utility/platformInfo');
const processArgs = require('./utility/processArgs');
const timingSafeCheckToken = require('./utility/timingSafeCheckToken');
let authorization = null;
let checkLocalhostOrigin = null; let checkLocalhostOrigin = null;
function start() { function start() {
@@ -43,7 +36,6 @@ function start() {
const app = express(); const app = express();
const server = http.createServer(app); const server = http.createServer(app);
socket.set(io(server));
if (process.env.LOGIN && process.env.PASSWORD) { if (process.env.LOGIN && process.env.PASSWORD) {
app.use( app.use(
@@ -58,9 +50,6 @@ function start() {
} }
app.use(function (req, res, next) { app.use(function (req, res, next) {
if (authorization && !timingSafeCheckToken(req.headers.authorization, authorization)) {
return res.status(403).json({ error: 'Not authorized!' });
}
if (checkLocalhostOrigin) { if (checkLocalhostOrigin) {
if ( if (
req.headers.origin && req.headers.origin &&
@@ -81,6 +70,20 @@ function start() {
}); });
app.use(cors()); app.use(cors());
app.get('/stream', async function (req, res) {
res.set({
'Cache-Control': 'no-cache',
'Content-Type': 'text/event-stream',
Connection: 'keep-alive',
});
res.flushHeaders();
// Tell the client to retry every 10 seconds if connectivity is lost
res.write('retry: 10000\n\n');
socket.setSseResponse(res);
});
app.use(bodyParser.json({ limit: '50mb' })); app.use(bodyParser.json({ limit: '50mb' }));
app.use( app.use(
@@ -90,20 +93,7 @@ function start() {
}) })
); );
useController(app, '/connections', connections); useAllControllers(app, null);
useController(app, '/server-connections', serverConnections);
useController(app, '/database-connections', databaseConnections);
useController(app, '/metadata', metadata);
useController(app, '/sessions', sessions);
useController(app, '/runners', runners);
useController(app, '/jsldata', jsldata);
useController(app, '/config', config);
useController(app, '/archive', archive);
useController(app, '/uploads', uploads);
useController(app, '/plugins', plugins);
useController(app, '/files', files);
useController(app, '/scheduler', scheduler);
useController(app, '/query-history', queryHistory);
// if (process.env.PAGES_DIRECTORY) { // if (process.env.PAGES_DIRECTORY) {
// app.use('/pages', express.static(process.env.PAGES_DIRECTORY)); // app.use('/pages', express.static(process.env.PAGES_DIRECTORY));
@@ -122,19 +112,7 @@ function start() {
} }
} }
if (processArgs.dynport) { if (platformInfo.isNpmDist) {
childProcessChecker();
authorization = crypto.randomBytes(32).toString('hex');
getPort().then(port => {
checkLocalhostOrigin = `localhost:${port}`;
server.listen(port, () => {
console.log(`DbGate API listening on port ${port}`);
process.send({ msgtype: 'listening', port, authorization });
});
});
} else if (platformInfo.isNpmDist) {
app.use(express.static(path.join(__dirname, '../../dbgate-web/public'))); app.use(express.static(path.join(__dirname, '../../dbgate-web/public')));
getPort({ port: 5000 }).then(port => { getPort({ port: 5000 }).then(port => {
server.listen(port, () => { server.listen(port, () => {
@@ -142,8 +120,47 @@ function start() {
}); });
}); });
} else { } else {
server.listen(3000); const port = process.env.PORT || 3000;
} console.log('DbGate API listening on port', port);
server.listen(port);
} }
module.exports = { start }; function shutdown() {
console.log('\nShutting down DbGate API server');
server.close(() => {
console.log('Server shut down, terminating');
process.exit(0);
});
setTimeout(() => {
console.log('Server close timeout, terminating');
process.exit(0);
}, 1000);
}
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
process.on('SIGBREAK', shutdown);
}
function useAllControllers(app, electron) {
useController(app, electron, '/connections', connections);
useController(app, electron, '/server-connections', serverConnections);
useController(app, electron, '/database-connections', databaseConnections);
useController(app, electron, '/metadata', metadata);
useController(app, electron, '/sessions', sessions);
useController(app, electron, '/runners', runners);
useController(app, electron, '/jsldata', jsldata);
useController(app, electron, '/config', config);
useController(app, electron, '/archive', archive);
useController(app, electron, '/uploads', uploads);
useController(app, electron, '/plugins', plugins);
useController(app, electron, '/files', files);
useController(app, electron, '/scheduler', scheduler);
useController(app, electron, '/query-history', queryHistory);
}
function initializeElectronSender(electronSender) {
socket.setElectronSender(electronSender);
}
module.exports = { start, useAllControllers, initializeElectronSender };

View File

@@ -1,5 +1,13 @@
const argIndex = process.argv.indexOf('--native-modules'); const argIndex = process.argv.indexOf('--native-modules');
const redirectFile = argIndex > 0 ? process.argv[argIndex + 1] : null; const redirectFile = global['NATIVE_MODULES'] || (argIndex > 0 ? process.argv[argIndex + 1] : null);
function requireDynamic(file) {
try {
// @ts-ignore // @ts-ignore
module.exports = redirectFile ? __non_webpack_require__(redirectFile) : require('./nativeModulesContent'); return __non_webpack_require__(redirectFile);
} catch (err) {
return require(redirectFile);
}
}
module.exports = redirectFile ? requireDynamic(redirectFile) : require('./nativeModulesContent');

View File

@@ -2,17 +2,9 @@ const childProcessChecker = require('../utility/childProcessChecker');
const requireEngineDriver = require('../utility/requireEngineDriver'); const requireEngineDriver = require('../utility/requireEngineDriver');
const connectUtility = require('../utility/connectUtility'); const connectUtility = require('../utility/connectUtility');
const { handleProcessCommunication } = require('../utility/processComm'); const { handleProcessCommunication } = require('../utility/processComm');
const { pickSafeConnectionInfo } = require('../utility/crypting');
const _ = require('lodash'); const _ = require('lodash');
function pickSafeConnectionInfo(connection) {
return _.mapValues(connection, (v, k) => {
if (k == 'engine' || k == 'port' || k == 'authType' || k == 'sshMode' || k == 'passwordMode') return v;
if (v === null || v === true || v === false) return v;
if (v) return '***';
return undefined;
});
}
const formatErrorDetail = (e, connection) => `${e.stack} const formatErrorDetail = (e, connection) => `${e.stack}
Error JSON: ${JSON.stringify(e, undefined, 2)} Error JSON: ${JSON.stringify(e, undefined, 2)}

View File

@@ -270,6 +270,7 @@ function start() {
try { try {
await handleMessage(message); await handleMessage(message);
} catch (e) { } catch (e) {
console.error('Error in DB connection', e);
process.send({ msgtype: 'error', error: e.message }); process.send({ msgtype: 'error', error: e.message });
} }
}); });

View File

@@ -1,6 +1,7 @@
const { fork } = require('child_process'); const { fork } = require('child_process');
const uuidv1 = require('uuid/v1'); const uuidv1 = require('uuid/v1');
const { handleProcessCommunication } = require('./processComm'); const { handleProcessCommunication } = require('./processComm');
const processArgs = require('../utility/processArgs');
class DatastoreProxy { class DatastoreProxy {
constructor(file) { constructor(file) {
@@ -29,7 +30,13 @@ class DatastoreProxy {
async ensureSubprocess() { async ensureSubprocess() {
if (!this.subprocess) { if (!this.subprocess) {
this.subprocess = fork(process.argv[1], ['--start-process', 'jslDatastoreProcess', ...process.argv.slice(3)]); this.subprocess = fork(global['API_PACKAGE'] || process.argv[1], [
'--is-forked-api',
'--start-process',
'jslDatastoreProcess',
...processArgs.getPassArgs(),
// ...process.argv.slice(3),
]);
this.subprocess.on('message', message => { this.subprocess.on('message', message => {
// @ts-ignore // @ts-ignore

View File

@@ -2,6 +2,7 @@ const crypto = require('crypto');
const simpleEncryptor = require('simple-encryptor'); const simpleEncryptor = require('simple-encryptor');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const _ = require('lodash');
const { datadir } = require('./directories'); const { datadir } = require('./directories');
@@ -81,8 +82,18 @@ function decryptConnection(connection) {
return connection; return connection;
} }
function pickSafeConnectionInfo(connection) {
return _.mapValues(connection, (v, k) => {
if (k == 'engine' || k == 'port' || k == 'authType' || k == 'sshMode' || k == 'passwordMode') return v;
if (v === null || v === true || v === false) return v;
if (v) return '***';
return undefined;
});
}
module.exports = { module.exports = {
loadEncryptionKey, loadEncryptionKey,
encryptConnection, encryptConnection,
decryptConnection, decryptConnection,
pickSafeConnectionInfo,
}; };

View File

@@ -41,6 +41,10 @@ const archivedir = dirFunc('archive');
const filesdir = dirFunc('files'); const filesdir = dirFunc('files');
function packagedPluginsDir() { function packagedPluginsDir() {
// console.log('CALL DIR FROM', new Error('xxx').stack);
// console.log('__dirname', __dirname);
// console.log('platformInfo.isElectronBundle', platformInfo.isElectronBundle);
// console.log('platformInfo.isForkedApi', platformInfo.isForkedApi);
if (platformInfo.isDevMode) { if (platformInfo.isDevMode) {
return path.resolve(__dirname, '../../../../plugins'); return path.resolve(__dirname, '../../../../plugins');
} }
@@ -53,6 +57,12 @@ function packagedPluginsDir() {
} }
if (platformInfo.isElectronBundle) { if (platformInfo.isElectronBundle) {
return path.resolve(__dirname, '../../plugins'); return path.resolve(__dirname, '../../plugins');
// if (platformInfo.isForkedApi) {
// return path.resolve(__dirname, '../plugins');
// } else {
// return path.resolve(__dirname, '../../plugins');
// }
} }
return null; return null;
} }

View File

@@ -2,6 +2,7 @@ const fs = require('fs');
const os = require('os'); const os = require('os');
const path = require('path'); const path = require('path');
const processArgs = require('./processArgs'); const processArgs = require('./processArgs');
const isElectron = require('is-electron');
const platform = process.env.OS_OVERRIDE ? process.env.OS_OVERRIDE : process.platform; const platform = process.env.OS_OVERRIDE ? process.env.OS_OVERRIDE : process.platform;
const isWindows = platform === 'win32'; const isWindows = platform === 'win32';
@@ -10,6 +11,7 @@ const isLinux = platform === 'linux';
const isDocker = fs.existsSync('/home/dbgate-docker/public'); const isDocker = fs.existsSync('/home/dbgate-docker/public');
const isDevMode = process.env.DEVMODE == '1'; const isDevMode = process.env.DEVMODE == '1';
const isNpmDist = !!global['dbgateApiModulePath']; const isNpmDist = !!global['dbgateApiModulePath'];
const isForkedApi = processArgs.isForkedApi;
// function moduleAvailable(name) { // function moduleAvailable(name) {
// try { // try {
@@ -20,14 +22,14 @@ const isNpmDist = !!global['dbgateApiModulePath'];
// } // }
// } // }
const isElectronBundle = processArgs.isElectronBundle;
const platformInfo = { const platformInfo = {
isWindows, isWindows,
isMac, isMac,
isLinux, isLinux,
isDocker, isDocker,
isElectronBundle, isElectronBundle: isElectron() && !isDevMode,
isForkedApi,
isElectron: isElectron(),
isDevMode, isDevMode,
isNpmDist, isNpmDist,
isSnap: process.env.ELECTRON_SNAP == 'true', isSnap: process.env.ELECTRON_SNAP == 'true',

View File

@@ -7,15 +7,17 @@ function getNamedArg(name) {
} }
const checkParent = process.argv.includes('--checkParent'); const checkParent = process.argv.includes('--checkParent');
const dynport = process.argv.includes('--dynport');
const nativeModules = getNamedArg('--native-modules');
const startProcess = getNamedArg('--start-process'); const startProcess = getNamedArg('--start-process');
const isElectronBundle = process.argv.includes('--is-electron-bundle'); const isForkedApi = process.argv.includes('--is-forked-api');
function getPassArgs() {
if (global['NATIVE_MODULES']) return ['--native-modules', global['NATIVE_MODULES']];
return [];
}
module.exports = { module.exports = {
checkParent, checkParent,
nativeModules,
startProcess, startProcess,
dynport, isForkedApi,
isElectronBundle, getPassArgs,
}; };

View File

@@ -1,5 +1,6 @@
const _ = require('lodash'); const _ = require('lodash');
const requirePlugin = require('../shell/requirePlugin'); const requirePlugin = require('../shell/requirePlugin');
const { pickSafeConnectionInfo } = require('./crypting');
/** @returns {import('dbgate-types').EngineDriver} */ /** @returns {import('dbgate-types').EngineDriver} */
function requireEngineDriver(connection) { function requireEngineDriver(connection) {
@@ -10,14 +11,14 @@ function requireEngineDriver(connection) {
engine = connection.engine; engine = connection.engine;
} }
if (!engine) { if (!engine) {
throw new Error('Could not get driver from connection'); throw new Error(`Could not get driver from connection ${JSON.stringify(pickSafeConnectionInfo(connection))}`);
} }
if (engine.includes('@')) { if (engine.includes('@')) {
const [shortName, packageName] = engine.split('@'); const [shortName, packageName] = engine.split('@');
const plugin = requirePlugin(packageName); const plugin = requirePlugin(packageName);
return plugin.drivers.find(x => x.engine == engine); return plugin.drivers.find(x => x.engine == engine);
} }
throw new Error(`Could not found engine driver ${engine}`); throw new Error(`Could not find engine driver ${engine}`);
} }
module.exports = requireEngineDriver; module.exports = requireEngineDriver;

View File

@@ -1,19 +1,29 @@
let socket = null; let sseResponse = null;
let electronSender = null;
let init = '';
module.exports = { module.exports = {
set(value) { setSseResponse(value) {
socket = value; sseResponse = value;
}, },
get() { setElectronSender(value) {
return socket; electronSender = value;
}, },
emit(message, data) { emit(message, data) {
// console.log('EMIT:', message, data); if (electronSender) {
socket.emit(message, data); electronSender.send(message, data == null ? null : data);
} else if (sseResponse) {
if (init) {
sseResponse.write(init);
init = '';
}
sseResponse.write(`event: ${message}\ndata: ${JSON.stringify(data == null ? null : data)}\n\n`);
} else {
init += sseResponse;
}
}, },
emitChanged(key) { emitChanged(key) {
// console.log('EMIT_CHANGED:', key); this.emit('clean-cache', key);
socket.emit('clean-cache', key); this.emit(key);
socket.emit(key);
}, },
}; };

View File

@@ -4,7 +4,7 @@ const express = require('express');
/** /**
* @param {string} route * @param {string} route
*/ */
module.exports = function useController(app, route, controller) { module.exports = function useController(app, electron, route, controller) {
const router = express.Router(); const router = express.Router();
if (controller._init) { if (controller._init) {
@@ -23,24 +23,39 @@ module.exports = function useController(app, route, controller) {
const meta = controller[`${key}_meta`]; const meta = controller[`${key}_meta`];
if (!meta) continue; if (!meta) continue;
let method = 'get'; const routeAction = `/${_.kebabCase(key)}`;
if (electron) {
if (meta === true) {
const handler = `${route.substring(1)}-${_.kebabCase(key)}`;
// console.log('REGISTERING HANDLER', handler);
electron.ipcMain.handle(handler, async (event, args) => {
const data = await controller[key](args);
// console.log('HANDLED API', handler, data);
return data;
});
}
continue;
}
let method = 'post';
let raw = false; let raw = false;
let rawParams = false; let rawParams = false;
if (_.isString(meta)) { // if (_.isString(meta)) {
method = meta; // method = meta;
} // }
if (_.isPlainObject(meta)) { if (_.isPlainObject(meta)) {
method = meta.method; method = meta.method;
raw = meta.raw; raw = meta.raw;
rawParams = meta.rawParams; rawParams = meta.rawParams;
} }
const route = `/${_.kebabCase(key)}`;
if (raw) { if (raw) {
router[method](route, controller[key]); router[method](routeAction, controller[key]);
} else { } else {
router[method](route, async (req, res) => { router[method](routeAction, async (req, res) => {
// if (controller._init && !controller._init_called) { // if (controller._init && !controller._init_called) {
// await controller._init(); // await controller._init();
// controller._init_called = true; // controller._init_called = true;
@@ -58,5 +73,7 @@ module.exports = function useController(app, route, controller) {
} }
} }
if (app) {
app.use(route, router); app.use(route, router);
}
}; };

View File

@@ -43,9 +43,7 @@
"rollup-plugin-livereload": "^2.0.0", "rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-svelte": "^7.0.0", "rollup-plugin-svelte": "^7.0.0",
"rollup-plugin-terser": "^7.0.0", "rollup-plugin-terser": "^7.0.0",
"rollup-plugin-web-worker-loader": "^1.6.1",
"sirv-cli": "^1.0.0", "sirv-cli": "^1.0.0",
"socket.io-client": "^2.3.0",
"sql-formatter": "^2.3.3", "sql-formatter": "^2.3.3",
"svelte": "^3.43.0", "svelte": "^3.43.0",
"svelte-check": "^1.0.0", "svelte-check": "^1.0.0",

View File

@@ -7,10 +7,8 @@ import { terser } from 'rollup-plugin-terser';
import sveltePreprocess from 'svelte-preprocess'; import sveltePreprocess from 'svelte-preprocess';
import typescript from '@rollup/plugin-typescript'; import typescript from '@rollup/plugin-typescript';
import replace from '@rollup/plugin-replace'; import replace from '@rollup/plugin-replace';
import webWorkerLoader from 'rollup-plugin-web-worker-loader';
import css from 'rollup-plugin-css-only'; import css from 'rollup-plugin-css-only';
const production = !process.env.ROLLUP_WATCH; const production = !process.env.ROLLUP_WATCH;
function serve() { function serve() {
@@ -34,7 +32,27 @@ function serve() {
}; };
} }
export default { export default [
{
input: 'src/query/QueryParserWorker.js',
output: {
sourcemap: true,
format: 'iife',
file: 'public/build/query-parser-worker.js',
},
plugins: [
commonjs(),
resolve({
browser: true,
}),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser(),
],
},
{
input: 'src/main.ts', input: 'src/main.ts',
output: { output: {
sourcemap: true, sourcemap: true,
@@ -101,10 +119,9 @@ export default {
// If we're building for production (npm run build // If we're building for production (npm run build
// instead of npm run dev), minify // instead of npm run dev), minify
production && terser(), production && terser(),
webWorkerLoader(),
], ],
watch: { watch: {
clearScreen: false, clearScreen: true,
}, },
}; },
];

View File

@@ -7,20 +7,37 @@
import PluginsProvider from './plugins/PluginsProvider.svelte'; import PluginsProvider from './plugins/PluginsProvider.svelte';
import Screen from './Screen.svelte'; import Screen from './Screen.svelte';
import { loadingPluginStore } from './stores'; import { loadingPluginStore, subscribeApiDependendStores } from './stores';
import { setAppLoaded } from './utility/appLoadManager'; import { setAppLoaded } from './utility/appLoadManager';
import axiosInstance from './utility/axiosInstance';
import ErrorHandler from './utility/ErrorHandler.svelte'; import ErrorHandler from './utility/ErrorHandler.svelte';
import OpenTabsOnStartup from './utility/OpenTabsOnStartup.svelte'; import OpenTabsOnStartup from './utility/OpenTabsOnStartup.svelte';
// import { shouldWaitForElectronInitialize } from './utility/getElectron';
import { subscribeConnectionPingers } from './utility/connectionsPinger';
import { subscribePermissionCompiler } from './utility/hasPermission';
import { apiCall } from './utility/api';
let loadedApi = false; let loadedApi = false;
async function loadApi() { async function loadApi() {
// if (shouldWaitForElectronInitialize()) {
// setTimeout(loadApi, 100);
// return;
// }
try { try {
const settings = await axiosInstance.get('config/get-settings'); // console.log('************** LOADING API');
const connections = await axiosInstance.get('connections/list');
const config = await axiosInstance.get('config/get'); const settings = await apiCall('config/get-settings');
loadedApi = settings?.data && connections?.data && config?.data; const connections = await apiCall('connections/list');
const config = await apiCall('config/get');
loadedApi = settings && connections && config;
if (loadedApi) {
subscribeApiDependendStores();
subscribeConnectionPingers();
subscribePermissionCompiler();
}
if (!loadedApi) { if (!loadedApi) {
console.log('API not initialized correctly, trying again in 1s'); console.log('API not initialized correctly, trying again in 1s');
setTimeout(loadApi, 1000); setTimeout(loadApi, 1000);
@@ -43,14 +60,13 @@
setAppLoaded(); setAppLoaded();
} }
} }
</script> </script>
<DataGridRowHeightMeter />
<ErrorHandler /> <ErrorHandler />
<CommandListener />
{#if loadedApi} {#if loadedApi}
<DataGridRowHeightMeter />
<CommandListener />
<PluginsProvider /> <PluginsProvider />
{#if $loadingPluginStore?.loaded} {#if $loadingPluginStore?.loaded}
<OpenTabsOnStartup /> <OpenTabsOnStartup />

View File

@@ -16,7 +16,7 @@
const connProps: any = {}; const connProps: any = {};
let tooltip = undefined; let tooltip = undefined;
const resp = await axiosInstance.post('files/load', { const resp = await apiCall('files/load', {
folder: 'archive:' + folderName, folder: 'archive:' + folderName,
file: fileName + '.' + fileType, file: fileName + '.' + fileType,
format: 'text', format: 'text',
@@ -36,7 +36,7 @@
...connProps, ...connProps,
}, },
}, },
{ editor: resp.data } { editor: resp }
); );
} }
@@ -69,7 +69,6 @@
import { archiveFilesAsDataSheets, currentArchive, extensions, getCurrentDatabase } from '../stores'; import { archiveFilesAsDataSheets, currentArchive, extensions, getCurrentDatabase } from '../stores';
import axiosInstance from '../utility/axiosInstance';
import createQuickExportMenu from '../utility/createQuickExportMenu'; import createQuickExportMenu from '../utility/createQuickExportMenu';
import { exportElectronFile } from '../utility/exportElectronFile'; import { exportElectronFile } from '../utility/exportElectronFile';
import openNewTab from '../utility/openNewTab'; import openNewTab from '../utility/openNewTab';
@@ -82,6 +81,7 @@
markArchiveFileAsDataSheet, markArchiveFileAsDataSheet,
markArchiveFileAsReadonly, markArchiveFileAsReadonly,
} from '../utility/archiveTools'; } from '../utility/archiveTools';
import { apiCall } from '../utility/api';
export let data; export let data;
@@ -91,7 +91,7 @@
label: 'New file name', label: 'New file name',
header: 'Rename file', header: 'Rename file',
onConfirm: newFile => { onConfirm: newFile => {
axiosInstance.post('archive/rename-file', { apiCall('archive/rename-file', {
file: data.fileName, file: data.fileName,
folder: data.folderName, folder: data.folderName,
fileType: data.fileType, fileType: data.fileType,
@@ -105,7 +105,7 @@
showModal(ConfirmModal, { showModal(ConfirmModal, {
message: `Really delete file ${data.fileName}?`, message: `Really delete file ${data.fileName}?`,
onConfirm: () => { onConfirm: () => {
axiosInstance.post('archive/delete-file', { apiCall('archive/delete-file', {
file: data.fileName, file: data.fileName,
folder: data.folderName, folder: data.folderName,
fileType: data.fileType, fileType: data.fileType,

View File

@@ -9,7 +9,6 @@
import { currentArchive, currentDatabase } from '../stores'; import { currentArchive, currentDatabase } from '../stores';
import axiosInstance from '../utility/axiosInstance';
import openNewTab from '../utility/openNewTab'; import openNewTab from '../utility/openNewTab';
import AppObjectCore from './AppObjectCore.svelte'; import AppObjectCore from './AppObjectCore.svelte';
import newQuery from '../query/newQuery'; import newQuery from '../query/newQuery';
@@ -17,6 +16,7 @@
import ConfirmModal from '../modals/ConfirmModal.svelte'; import ConfirmModal from '../modals/ConfirmModal.svelte';
import InputTextModal from '../modals/InputTextModal.svelte'; import InputTextModal from '../modals/InputTextModal.svelte';
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte'; import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
import { apiCall } from '../utility/api';
export let data; export let data;
@@ -26,7 +26,7 @@
? `Really delete link to folder ${data.name}? Folder content remains untouched.` ? `Really delete link to folder ${data.name}? Folder content remains untouched.`
: `Really delete folder ${data.name}?`, : `Really delete folder ${data.name}?`,
onConfirm: () => { onConfirm: () => {
axiosInstance.post('archive/delete-folder', { folder: data.name }); apiCall('archive/delete-folder', { folder: data.name });
}, },
}); });
}; };
@@ -41,7 +41,7 @@
label: 'New folder name', label: 'New folder name',
header: 'Rename folder', header: 'Rename folder',
onConfirm: async newFolder => { onConfirm: async newFolder => {
await axiosInstance.post('archive/rename-folder', { await apiCall('archive/rename-folder', {
folder: data.name, folder: data.name,
newFolder: newFolder + suffix, newFolder: newFolder + suffix,
}); });
@@ -78,16 +78,16 @@ await dbgateApi.deployDb(${JSON.stringify(
}; };
const handleGenerateDeploySql = async () => { const handleGenerateDeploySql = async () => {
const resp = await axiosInstance.post('database-connections/generate-deploy-sql', { const resp = await apiCall('database-connections/generate-deploy-sql', {
conid: $currentDatabase.connection._id, conid: $currentDatabase.connection._id,
database: $currentDatabase.name, database: $currentDatabase.name,
archiveFolder: data.name, archiveFolder: data.name,
}); });
if (resp.data.errorMessage) { if (resp.errorMessage) {
showModal(ErrorMessageModal, { message: resp.data.errorMessage }); showModal(ErrorMessageModal, { message: resp.errorMessage });
} else { } else {
newQuery({ initialData: resp.data.sql }); newQuery({ initialData: resp.sql });
} }
}; };

View File

@@ -17,7 +17,6 @@
import _ from 'lodash'; import _ from 'lodash';
import AppObjectCore from './AppObjectCore.svelte'; import AppObjectCore from './AppObjectCore.svelte';
import { currentDatabase, extensions, getCurrentConfig, getOpenedConnections, openedConnections } from '../stores'; import { currentDatabase, extensions, getCurrentConfig, getOpenedConnections, openedConnections } from '../stores';
import axiosInstance from '../utility/axiosInstance';
import { filterName } from 'dbgate-tools'; import { filterName } from 'dbgate-tools';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import ConnectionModal from '../modals/ConnectionModal.svelte'; import ConnectionModal from '../modals/ConnectionModal.svelte';
@@ -29,6 +28,7 @@
import getConnectionLabel from '../utility/getConnectionLabel'; import getConnectionLabel from '../utility/getConnectionLabel';
import { getDatabaseList } from '../utility/metadataLoaders'; import { getDatabaseList } from '../utility/metadataLoaders';
import { getLocalStorage } from '../utility/storageCache'; import { getLocalStorage } from '../utility/storageCache';
import { apiCall } from '../utility/api';
export let data; export let data;
export let passProps; export let passProps;
@@ -44,14 +44,14 @@
const handleConnect = () => { const handleConnect = () => {
if (data.singleDatabase) { if (data.singleDatabase) {
$currentDatabase = { connection: data, name: data.defaultDatabase }; $currentDatabase = { connection: data, name: data.defaultDatabase };
axiosInstance.post('database-connections/refresh', { apiCall('database-connections/refresh', {
conid: data._id, conid: data._id,
database: data.defaultDatabase, database: data.defaultDatabase,
keepOpen: true, keepOpen: true,
}); });
} else { } else {
$openedConnections = _.uniq([...$openedConnections, data._id]); $openedConnections = _.uniq([...$openedConnections, data._id]);
axiosInstance.post('server-connections/refresh', { apiCall('server-connections/refresh', {
conid: data._id, conid: data._id,
keepOpen: true, keepOpen: true,
}); });
@@ -61,16 +61,16 @@
const getContextMenu = () => { const getContextMenu = () => {
const config = getCurrentConfig(); const config = getCurrentConfig();
const handleRefresh = () => { const handleRefresh = () => {
axiosInstance.post('server-connections/refresh', { conid: data._id }); apiCall('server-connections/refresh', { conid: data._id });
}; };
const handleDisconnect = () => { const handleDisconnect = () => {
openedConnections.update(list => list.filter(x => x != data._id)); openedConnections.update(list => list.filter(x => x != data._id));
if (electron) { if (electron) {
axiosInstance.post('server-connections/disconnect', { conid: data._id }); apiCall('server-connections/disconnect', { conid: data._id });
} }
if (_.get($currentDatabase, 'connection._id') == data._id) { if (_.get($currentDatabase, 'connection._id') == data._id) {
if (electron) { if (electron) {
axiosInstance.post('database-connections/disconnect', { conid: data._id, database: $currentDatabase.name }); apiCall('database-connections/disconnect', { conid: data._id, database: $currentDatabase.name });
} }
currentDatabase.set(null); currentDatabase.set(null);
} }
@@ -81,11 +81,11 @@
const handleDelete = () => { const handleDelete = () => {
showModal(ConfirmModal, { showModal(ConfirmModal, {
message: `Really delete connection ${getConnectionLabel(data)}?`, message: `Really delete connection ${getConnectionLabel(data)}?`,
onConfirm: () => axiosInstance.post('connections/delete', data), onConfirm: () => apiCall('connections/delete', data),
}); });
}; };
const handleDuplicate = () => { const handleDuplicate = () => {
axiosInstance.post('connections/save', { apiCall('connections/save', {
...data, ...data,
_id: undefined, _id: undefined,
displayName: `${getConnectionLabel(data)} - copy`, displayName: `${getConnectionLabel(data)} - copy`,
@@ -97,7 +97,7 @@
value: 'newdb', value: 'newdb',
label: 'Database name', label: 'Database name',
onConfirm: name => onConfirm: name =>
axiosInstance.post('server-connections/create-database', { apiCall('server-connections/create-database', {
conid: data._id, conid: data._id,
name, name,
}), }),

View File

@@ -1,6 +1,5 @@
<script lang="ts" context="module"> <script lang="ts" context="module">
export const extractKey = props => props.name; export const extractKey = props => props.name;
const electron = getElectron();
export function getDatabaseMenuItems(connection, name, $extensions, $currentDatabase) { export function getDatabaseMenuItems(connection, name, $extensions, $currentDatabase) {
const handleNewQuery = () => { const handleNewQuery = () => {
@@ -48,13 +47,11 @@
header: 'Create collection', header: 'Create collection',
onConfirm: async newCollection => { onConfirm: async newCollection => {
const dbid = { conid: connection._id, database: name }; const dbid = { conid: connection._id, database: name };
await axiosInstance.request({ await apiCall('database-connections/run-script', {
url: 'database-connections/run-script', ...dbid,
method: 'post', sql: `db.createCollection('${newCollection}')`,
params: dbid,
data: { sql: `db.createCollection('${newCollection}')` },
}); });
axiosInstance.post('database-connections/sync-model', dbid); await apiCall('database-connections/sync-model', dbid);
}, },
}); });
}; };
@@ -89,20 +86,21 @@
}; };
const handleDisconnect = () => { const handleDisconnect = () => {
const electron = getElectron();
if (electron) { if (electron) {
axiosInstance.post('database-connections/disconnect', { conid: connection._id, database: name }); apiCall('database-connections/disconnect', { conid: connection._id, database: name });
} }
currentDatabase.set(null); currentDatabase.set(null);
}; };
const handleExportModel = async () => { const handleExportModel = async () => {
const resp = await axiosInstance.post('database-connections/export-model', { const resp = await apiCall('database-connections/export-model', {
conid: connection._id, conid: connection._id,
database: name, database: name,
}); });
currentArchive.set(resp.data.archiveFolder); currentArchive.set(resp.archiveFolder);
selectedWidget.set('archive'); selectedWidget.set('archive');
showSnackbarSuccess(`Saved to archive ${resp.data.archiveFolder}`); showSnackbarSuccess(`Saved to archive ${resp.archiveFolder}`);
}; };
const handleCompareWithCurrentDb = () => { const handleCompareWithCurrentDb = () => {
@@ -173,7 +171,6 @@
pinnedDatabases, pinnedDatabases,
selectedWidget, selectedWidget,
} from '../stores'; } from '../stores';
import axiosInstance from '../utility/axiosInstance';
import getElectron from '../utility/getElectron'; import getElectron from '../utility/getElectron';
import openNewTab from '../utility/openNewTab'; import openNewTab from '../utility/openNewTab';
import AppObjectCore from './AppObjectCore.svelte'; import AppObjectCore from './AppObjectCore.svelte';
@@ -182,6 +179,7 @@
import InputTextModal from '../modals/InputTextModal.svelte'; import InputTextModal from '../modals/InputTextModal.svelte';
import { getDatabaseInfo } from '../utility/metadataLoaders'; import { getDatabaseInfo } from '../utility/metadataLoaders';
import { openJsonDocument } from '../tabs/JsonTab.svelte'; import { openJsonDocument } from '../tabs/JsonTab.svelte';
import { apiCall } from '../utility/api';
export let data; export let data;
export let passProps; export let passProps;

View File

@@ -408,9 +408,9 @@
import { exportElectronFile } from '../utility/exportElectronFile'; import { exportElectronFile } from '../utility/exportElectronFile';
import createQuickExportMenu from '../utility/createQuickExportMenu'; import createQuickExportMenu from '../utility/createQuickExportMenu';
import ConfirmSqlModal from '../modals/ConfirmSqlModal.svelte'; import ConfirmSqlModal from '../modals/ConfirmSqlModal.svelte';
import axiosInstance from '../utility/axiosInstance';
import { alterDatabaseDialog, renameDatabaseObjectDialog } from '../utility/alterDatabaseTools'; import { alterDatabaseDialog, renameDatabaseObjectDialog } from '../utility/alterDatabaseTools';
import ConfirmModal from '../modals/ConfirmModal.svelte'; import ConfirmModal from '../modals/ConfirmModal.svelte';
import { apiCall } from '../utility/api';
export let data; export let data;
export let passProps; export let passProps;
@@ -559,13 +559,11 @@
message: `Really drop collection ${data.pureName}?`, message: `Really drop collection ${data.pureName}?`,
onConfirm: async () => { onConfirm: async () => {
const dbid = _.pick(data, ['conid', 'database']); const dbid = _.pick(data, ['conid', 'database']);
await axiosInstance.request({ await apiCall('database-connections/run-script', {
url: 'database-connections/run-script', ...dbid,
method: 'post', sql: `db.dropCollection('${data.pureName}')`,
params: dbid,
data: { sql: `db.dropCollection('${data.pureName}')` },
}); });
axiosInstance.post('database-connections/sync-model', dbid); apiCall('database-connections/sync-model', dbid);
}, },
}); });
} else { } else {

View File

@@ -7,14 +7,14 @@
const { icon, tabComponent, title, props, tabdata } = favorite; const { icon, tabComponent, title, props, tabdata } = favorite;
let tabdataNew = tabdata; let tabdataNew = tabdata;
if (props.savedFile) { if (props.savedFile) {
const resp = await axiosInstance.post('files/load', { const resp = await apiCall('files/load', {
folder: props.savedFolder, folder: props.savedFolder,
file: props.savedFile, file: props.savedFile,
format: props.savedFormat, format: props.savedFormat,
}); });
tabdataNew = { tabdataNew = {
...tabdata, ...tabdata,
editor: resp.data, editor: resp,
}; };
} }
openNewTab( openNewTab(
@@ -30,13 +30,13 @@
</script> </script>
<script lang="ts"> <script lang="ts">
import axiosInstance from '../utility/axiosInstance';
import openNewTab from '../utility/openNewTab'; import openNewTab from '../utility/openNewTab';
import { copyTextToClipboard } from '../utility/clipboard'; import { copyTextToClipboard } from '../utility/clipboard';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import ConfirmModal from '../modals/ConfirmModal.svelte'; import ConfirmModal from '../modals/ConfirmModal.svelte';
import getElectron from '../utility/getElectron'; import getElectron from '../utility/getElectron';
import FavoriteModal from '../modals/FavoriteModal.svelte'; import FavoriteModal from '../modals/FavoriteModal.svelte';
import { apiCall } from '../utility/api';
export let data; export let data;
@@ -47,7 +47,7 @@
}; };
const editFavoriteJson = async () => { const editFavoriteJson = async () => {
const resp = await axiosInstance.post('files/load', { const resp = await apiCall('files/load', {
folder: 'favorites', folder: 'favorites',
file: data.file, file: data.file,
format: 'text', format: 'text',
@@ -64,7 +64,7 @@
savedFolder: 'favorites', savedFolder: 'favorites',
}, },
}, },
{ editor: JSON.stringify(JSON.parse(resp.data), null, 2) } { editor: JSON.stringify(JSON.parse(resp), null, 2) }
); );
}; };
@@ -76,7 +76,7 @@
showModal(ConfirmModal, { showModal(ConfirmModal, {
message: `Really delete favorite ${data.title}?`, message: `Really delete favorite ${data.title}?`,
onConfirm: () => { onConfirm: () => {
axiosInstance.post('files/delete', { file: data.file, folder: 'favorites' }); apiCall('files/delete', { file: data.file, folder: 'favorites' });
}, },
}); });
}; };

View File

@@ -74,8 +74,8 @@
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import { currentDatabase } from '../stores'; import { currentDatabase } from '../stores';
import { apiCall } from '../utility/api';
import axiosInstance from '../utility/axiosInstance';
import getConnectionLabel from '../utility/getConnectionLabel'; import getConnectionLabel from '../utility/getConnectionLabel';
import hasPermission from '../utility/hasPermission'; import hasPermission from '../utility/hasPermission';
import openNewTab from '../utility/openNewTab'; import openNewTab from '../utility/openNewTab';
@@ -114,7 +114,7 @@
showModal(ConfirmModal, { showModal(ConfirmModal, {
message: `Really delete file ${data.file}?`, message: `Really delete file ${data.file}?`,
onConfirm: () => { onConfirm: () => {
axiosInstance.post('files/delete', data); apiCall('files/delete', data);
}, },
}); });
}; };
@@ -125,7 +125,7 @@
label: 'New file name', label: 'New file name',
header: 'Rename file', header: 'Rename file',
onConfirm: newFile => { onConfirm: newFile => {
axiosInstance.post('files/rename', { ...data, newFile }); apiCall('files/rename', { ...data, newFile });
}, },
}); });
}; };
@@ -136,13 +136,13 @@
label: 'New file name', label: 'New file name',
header: 'Rename file', header: 'Rename file',
onConfirm: newFile => { onConfirm: newFile => {
axiosInstance.post('files/copy', { ...data, newFile }); apiCall('files/copy', { ...data, newFile });
}, },
}); });
}; };
async function openTab() { async function openTab() {
const resp = await axiosInstance.post('files/load', { folder, file: data.file, format: handler.format }); const resp = await apiCall('files/load', { folder, file: data.file, format: handler.format });
const connProps: any = {}; const connProps: any = {};
let tooltip = undefined; let tooltip = undefined;
@@ -168,7 +168,7 @@
...connProps, ...connProps,
}, },
}, },
{ editor: resp.data } { editor: resp }
); );
} }
</script> </script>

View File

@@ -20,7 +20,7 @@
<script lang="ts"> <script lang="ts">
import { onMount, afterUpdate, onDestroy } from 'svelte'; import { onMount, afterUpdate, onDestroy } from 'svelte';
import registerCommand from '../commands/registerCommand'; import registerCommand from '../commands/registerCommand';
import axiosInstance from '../utility/axiosInstance'; import { apiCall } from '../utility/api';
import contextMenu, { getContextMenu, registerMenu } from '../utility/contextMenu'; import contextMenu, { getContextMenu, registerMenu } from '../utility/contextMenu';
import createActivator, { getActiveComponent } from '../utility/createActivator'; import createActivator, { getActiveComponent } from '../utility/createActivator';
@@ -61,7 +61,7 @@
export async function exportChart() { export async function exportChart() {
saveFileToDisk(async filePath => { saveFileToDisk(async filePath => {
await axiosInstance.post('files/export-chart', { await apiCall('files/export-chart', {
title, title,
filePath, filePath,
config: { config: {

View File

@@ -1,7 +1,7 @@
import { dumpSqlSelect, Select } from 'dbgate-sqltree'; import { dumpSqlSelect, Select } from 'dbgate-sqltree';
import { EngineDriver } from 'dbgate-types'; import { EngineDriver } from 'dbgate-types';
import axiosInstance from '../utility/axiosInstance';
import _ from 'lodash'; import _ from 'lodash';
import { apiCall } from '../utility/api';
export async function loadChartStructure(driver: EngineDriver, conid, database, sql) { export async function loadChartStructure(driver: EngineDriver, conid, database, sql) {
const select: Select = { const select: Select = {
@@ -16,9 +16,9 @@ export async function loadChartStructure(driver: EngineDriver, conid, database,
const dmp = driver.createDumper(); const dmp = driver.createDumper();
dumpSqlSelect(dmp, select); dumpSqlSelect(dmp, select);
const resp = await axiosInstance.post('database-connections/query-data', { conid, database, sql: dmp.s }); const resp = await apiCall('database-connections/query-data', { conid, database, sql: dmp.s });
if (resp.data.errorMessage) throw new Error(resp.data.errorMessage); if (resp.errorMessage) throw new Error(resp.errorMessage);
return resp.data.columns.map(x => x.columnName); return resp.columns.map(x => x.columnName);
} }
export async function loadChartData(driver: EngineDriver, conid, database, sql, config) { export async function loadChartData(driver: EngineDriver, conid, database, sql, config) {
@@ -74,8 +74,8 @@ export async function loadChartData(driver: EngineDriver, conid, database, sql,
const dmp = driver.createDumper(); const dmp = driver.createDumper();
dumpSqlSelect(dmp, select); dumpSqlSelect(dmp, select);
const resp = await axiosInstance.post('database-connections/query-data', { conid, database, sql: dmp.s }); const resp = await apiCall('database-connections/query-data', { conid, database, sql: dmp.s });
let { rows, columns, errorMessage } = resp.data; let { rows, columns, errorMessage } = resp;
if (errorMessage) { if (errorMessage) {
throw new Error(errorMessage); throw new Error(errorMessage);
} }

View File

@@ -1,6 +1,4 @@
<script context="module"> <script context="module">
const electron = getElectron();
registerCommand({ registerCommand({
id: 'commandPalette.show', id: 'commandPalette.show',
category: 'Command palette', category: 'Command palette',
@@ -20,7 +18,7 @@
category: 'Database', category: 'Database',
toolbarName: 'Database search', toolbarName: 'Database search',
name: 'Search', name: 'Search',
keyText: electron ? 'Ctrl+P' : 'F3', keyText: isElectronAvailable() ? 'Ctrl+P' : 'F3',
onClick: () => visibleCommandPalette.set('database'), onClick: () => visibleCommandPalette.set('database'),
testEnabled: () => getVisibleCommandPalette() != 'database', testEnabled: () => getVisibleCommandPalette() != 'database',
}); });
@@ -75,7 +73,7 @@
} from '../stores'; } from '../stores';
import clickOutside from '../utility/clickOutside'; import clickOutside from '../utility/clickOutside';
import getConnectionLabel from '../utility/getConnectionLabel'; import getConnectionLabel from '../utility/getConnectionLabel';
import getElectron from '../utility/getElectron'; import { isElectronAvailable } from '../utility/getElectron';
import keycodes from '../utility/keycodes'; import keycodes from '../utility/keycodes';
import { useConnectionList, useDatabaseInfo } from '../utility/metadataLoaders'; import { useConnectionList, useDatabaseInfo } from '../utility/metadataLoaders';
import { getLocalStorage } from '../utility/storageCache'; import { getLocalStorage } from '../utility/storageCache';

View File

@@ -2,9 +2,7 @@ import _ from 'lodash';
import { currentDatabase, getCurrentDatabase } from '../stores'; import { currentDatabase, getCurrentDatabase } from '../stores';
import getElectron from '../utility/getElectron'; import getElectron from '../utility/getElectron';
import registerCommand from './registerCommand'; import registerCommand from './registerCommand';
import axiosInstance from '../utility/axiosInstance'; import { apiCall } from '../utility/api';
const electron = getElectron();
registerCommand({ registerCommand({
id: 'database.changeState', id: 'database.changeState',
@@ -22,19 +20,20 @@ registerCommand({
{ {
text: 'Sync model', text: 'Sync model',
onClick: () => { onClick: () => {
axiosInstance.post('database-connections/sync-model', dbid); apiCall('database-connections/sync-model', dbid);
}, },
}, },
{ {
text: 'Reopen', text: 'Reopen',
onClick: () => { onClick: () => {
axiosInstance.post('database-connections/refresh', dbid); apiCall('database-connections/refresh', dbid);
}, },
}, },
{ {
text: 'Disconnect', text: 'Disconnect',
onClick: () => { onClick: () => {
if (electron) axiosInstance.post('database-connections/disconnect', dbid); const electron = getElectron();
if (electron) apiCall('database-connections/disconnect', dbid);
currentDatabase.set(null); currentDatabase.set(null);
}, },
}, },

View File

@@ -18,8 +18,6 @@ export default function runCommand(id) {
} }
} }
window['dbgate_runCommand'] = runCommand;
export function runGroupCommand(group) { export function runGroupCommand(group) {
const commandsValue = getCommands(); const commandsValue = getCommands();
const values = Object.values(commandsValue) as GlobalCommand[]; const values = Object.values(commandsValue) as GlobalCommand[];
@@ -32,3 +30,4 @@ export function findCommand(id) {
const command = commandsValue[id]; const command = commandsValue[id];
return command; return command;
} }

View File

@@ -18,15 +18,14 @@ import { getCurrentConfig, getCurrentDatabase } from '../stores';
import './recentDatabaseSwitch'; import './recentDatabaseSwitch';
import './changeDatabaseStatusCommand'; import './changeDatabaseStatusCommand';
import hasPermission from '../utility/hasPermission'; import hasPermission from '../utility/hasPermission';
import axiosInstance from '../utility/axiosInstance';
import _ from 'lodash'; import _ from 'lodash';
import { findEngineDriver } from 'dbgate-tools'; import { findEngineDriver } from 'dbgate-tools';
import { openArchiveFolder } from '../utility/openArchiveFolder'; import { openArchiveFolder } from '../utility/openArchiveFolder';
import InputTextModal from '../modals/InputTextModal.svelte'; import InputTextModal from '../modals/InputTextModal.svelte';
import { removeLocalStorage } from '../utility/storageCache'; import { removeLocalStorage } from '../utility/storageCache';
import { showSnackbarSuccess } from '../utility/snackbar'; import { showSnackbarSuccess } from '../utility/snackbar';
import { apiCall } from '../utility/api';
const electron = getElectron(); import runCommand from './runCommand';
function themeCommand(theme: ThemeDefinition) { function themeCommand(theme: ThemeDefinition) {
return { return {
@@ -123,7 +122,7 @@ registerCommand({
label: 'New archive folder name', label: 'New archive folder name',
header: 'Create archive folder', header: 'Create archive folder',
onConfirm: async folder => { onConfirm: async folder => {
axiosInstance.post('archive/create-folder', { folder }); apiCall('archive/create-folder', { folder });
}, },
}); });
}, },
@@ -190,13 +189,8 @@ registerCommand({
label: 'New collection name', label: 'New collection name',
header: 'Create collection', header: 'Create collection',
onConfirm: async newCollection => { onConfirm: async newCollection => {
await axiosInstance.request({ await apiCall('database-connections/run-script', { ...dbid, sql: `db.createCollection('${newCollection}')` });
url: 'database-connections/run-script', apiCall('database-connections/sync-model', dbid);
method: 'post',
params: dbid,
data: { sql: `db.createCollection('${newCollection}')` },
});
axiosInstance.post('database-connections/sync-model', dbid);
}, },
}); });
}, },
@@ -258,8 +252,8 @@ registerCommand({
label: 'New database name', label: 'New database name',
header: 'Create SQLite database', header: 'Create SQLite database',
onConfirm: async file => { onConfirm: async file => {
const resp = await axiosInstance.post('connections/new-sqlite-database', { file }); const resp = await apiCall('connections/new-sqlite-database', { file });
const connection = resp.data; const connection = resp;
currentDatabase.set({ connection, name: `${file}.sqlite` }); currentDatabase.set({ connection, name: `${file}.sqlite` });
}, },
}); });
@@ -316,12 +310,12 @@ registerCommand({
group: 'redo', group: 'redo',
}); });
if (electron) {
registerCommand({ registerCommand({
id: 'file.open', id: 'file.open',
category: 'File', category: 'File',
name: 'Open', name: 'Open',
keyText: 'Ctrl+O', keyText: 'Ctrl+O',
testEnabled: () => getElectron() != null,
onClick: openElectronFile, onClick: openElectronFile,
}); });
@@ -329,9 +323,9 @@ if (electron) {
id: 'file.openArchive', id: 'file.openArchive',
category: 'File', category: 'File',
name: 'Open DB Model/Archive', name: 'Open DB Model/Archive',
testEnabled: () => getElectron() != null,
onClick: openArchiveFolder, onClick: openArchiveFolder,
}); });
}
registerCommand({ registerCommand({
id: 'file.import', id: 'file.import',
@@ -419,14 +413,13 @@ if (hasPermission('settings/change')) {
}); });
} }
if (electron) {
registerCommand({ registerCommand({
id: 'file.exit', id: 'file.exit',
category: 'File', category: 'File',
name: 'Exit', name: 'Exit',
onClick: () => electron.remote.getCurrentWindow().close(), testEnabled: () => getElectron() != null,
onClick: () => getElectron().send('close-window'),
}); });
}
export function registerFileCommands({ export function registerFileCommands({
idPrefix, idPrefix,
@@ -541,3 +534,8 @@ export function registerFileCommands({
}); });
} }
} }
const electron = getElectron();
if (electron) {
electron.addEventListener('run-command', (e, commandId) => runCommand(commandId));
}

View File

@@ -63,14 +63,9 @@
export async function loadCollectionDataPage(props, offset, limit) { export async function loadCollectionDataPage(props, offset, limit) {
const { conid, database } = props; const { conid, database } = props;
const response = await axiosInstance.request({ const response = await apiCall('database-connections/collection-data', {
url: 'database-connections/collection-data',
method: 'post',
params: {
conid, conid,
database, database,
},
data: {
options: { options: {
pureName: props.pureName, pureName: props.pureName,
limit, limit,
@@ -78,11 +73,10 @@
condition: buildGridMongoCondition(props), condition: buildGridMongoCondition(props),
sort: buildMongoSort(props), sort: buildMongoSort(props),
}, },
},
}); });
if (response.data.errorMessage) return response.data; if (response.errorMessage) return response;
return response.data.rows; return response.rows;
} }
function dataPageAvailable(props) { function dataPageAvailable(props) {
@@ -95,23 +89,17 @@
async function loadRowCount(props) { async function loadRowCount(props) {
const { conid, database } = props; const { conid, database } = props;
const response = await axiosInstance.request({ const response = await apiCall('database-connections/collection-data', {
url: 'database-connections/collection-data',
method: 'post',
params: {
conid, conid,
database, database,
},
data: {
options: { options: {
pureName: props.pureName, pureName: props.pureName,
countDocuments: true, countDocuments: true,
condition: buildGridMongoCondition(props), condition: buildGridMongoCondition(props),
}, },
},
}); });
return response.data.count; return response.count;
} }
</script> </script>
@@ -127,8 +115,8 @@
import ImportExportModal from '../modals/ImportExportModal.svelte'; import ImportExportModal from '../modals/ImportExportModal.svelte';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import { extensions } from '../stores'; import { extensions } from '../stores';
import { apiCall } from '../utility/api';
import axiosInstance from '../utility/axiosInstance';
import { registerMenu } from '../utility/contextMenu'; import { registerMenu } from '../utility/contextMenu';
import createActivator, { getActiveComponent } from '../utility/createActivator'; import createActivator, { getActiveComponent } from '../utility/createActivator';
import createQuickExportMenu from '../utility/createQuickExportMenu'; import createQuickExportMenu from '../utility/createQuickExportMenu';

View File

@@ -262,7 +262,6 @@
import createReducer from '../utility/createReducer'; import createReducer from '../utility/createReducer';
import keycodes from '../utility/keycodes'; import keycodes from '../utility/keycodes';
import { copyRowsFormat, selectedCellsCallback } from '../stores'; import { copyRowsFormat, selectedCellsCallback } from '../stores';
import axiosInstance from '../utility/axiosInstance';
import { import {
copyRowsFormatDefs, copyRowsFormatDefs,
copyRowsToClipboard, copyRowsToClipboard,
@@ -285,6 +284,7 @@
import { findCommand } from '../commands/runCommand'; import { findCommand } from '../commands/runCommand';
import { openJsonDocument } from '../tabs/JsonTab.svelte'; import { openJsonDocument } from '../tabs/JsonTab.svelte';
import EditJsonModal from '../modals/EditJsonModal.svelte'; import EditJsonModal from '../modals/EditJsonModal.svelte';
import { apiCall } from '../utility/api';
export let onLoadNextData = undefined; export let onLoadNextData = undefined;
export let grider = undefined; export let grider = undefined;
@@ -404,7 +404,7 @@
} }
export async function reconnect() { export async function reconnect() {
await axiosInstance.post('database-connections/refresh', { conid, database }); await apiCall('database-connections/refresh', { conid, database });
display.reload(); display.reload();
} }

View File

@@ -1,10 +1,8 @@
<script lang="ts"> <script lang="ts">
import { createGridCache, createGridConfig, JslGridDisplay } from 'dbgate-datalib'; import { createGridCache, createGridConfig, JslGridDisplay } from 'dbgate-datalib';
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
import socket from '../utility/socket'; import { useApiCall } from '../utility/api';
import useEffect from '../utility/useEffect';
import useFetch from '../utility/useFetch';
import DataGrid from './DataGrid.svelte'; import DataGrid from './DataGrid.svelte';
import JslDataGridCore from './JslDataGridCore.svelte'; import JslDataGridCore from './JslDataGridCore.svelte';
@@ -12,11 +10,7 @@
let loadedRows; let loadedRows;
$: info = useFetch({ $: info = useApiCall('jsldata/get-info', { jslid }, {});
params: { jslid },
url: 'jsldata/get-info',
defaultValue: {},
});
// $: columns = ($info && $info.columns) || []; // $: columns = ($info && $info.columns) || [];
const config = writable(createGridConfig()); const config = writable(createGridConfig());

View File

@@ -13,14 +13,14 @@
async function loadDataPage(props, offset, limit) { async function loadDataPage(props, offset, limit) {
const { jslid, display } = props; const { jslid, display } = props;
const response = await axiosInstance.post('jsldata/get-rows', { const response = await apiCall('jsldata/get-rows', {
jslid, jslid,
offset, offset,
limit, limit,
filters: display ? display.compileFilters() : null, filters: display ? display.compileFilters() : null,
}); });
return response.data; return response;
} }
function dataPageAvailable(props) { function dataPageAvailable(props) {
@@ -30,16 +30,9 @@
async function loadRowCount(props) { async function loadRowCount(props) {
const { jslid } = props; const { jslid } = props;
const response = await axiosInstance.request({ const response = await apiCall('jsldata/get-stats', { jslid });
url: 'jsldata/get-stats', return response.rowCount;
method: 'get',
params: {
jslid,
},
});
return response.data.rowCount;
} }
</script> </script>
<script lang="ts"> <script lang="ts">
@@ -48,13 +41,12 @@
import ImportExportModal from '../modals/ImportExportModal.svelte'; import ImportExportModal from '../modals/ImportExportModal.svelte';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import { extensions } from '../stores'; import { extensions } from '../stores';
import { apiCall, apiOff, apiOn } from '../utility/api';
import axiosInstance from '../utility/axiosInstance';
import { registerMenu } from '../utility/contextMenu'; import { registerMenu } from '../utility/contextMenu';
import createActivator, { getActiveComponent } from '../utility/createActivator'; import createActivator, { getActiveComponent } from '../utility/createActivator';
import createQuickExportMenu from '../utility/createQuickExportMenu'; import createQuickExportMenu from '../utility/createQuickExportMenu';
import { exportElectronFile } from '../utility/exportElectronFile'; import { exportElectronFile } from '../utility/exportElectronFile';
import socket from '../utility/socket';
import useEffect from '../utility/useEffect'; import useEffect from '../utility/useEffect';
import LoadingDataGridCore from './LoadingDataGridCore.svelte'; import LoadingDataGridCore from './LoadingDataGridCore.svelte';
@@ -82,9 +74,9 @@
$: effect = useEffect(() => onJslId(jslid)); $: effect = useEffect(() => onJslId(jslid));
function onJslId(jslidVal) { function onJslId(jslidVal) {
if (jslidVal) { if (jslidVal) {
socket.on(`jsldata-stats-${jslidVal}`, handleJslDataStats); apiOn(`jsldata-stats-${jslidVal}`, handleJslDataStats);
return () => { return () => {
socket.off(`jsldata-stats-${jslidVal}`, handleJslDataStats); apiOff(`jsldata-stats-${jslidVal}`, handleJslDataStats);
}; };
} }
} }
@@ -140,7 +132,6 @@
}, },
{ command: 'jslTableGrid.export', tag: 'export' } { command: 'jslTableGrid.export', tag: 'export' }
); );
</script> </script>
<LoadingDataGridCore <LoadingDataGridCore

View File

@@ -31,18 +31,14 @@
const sql = display.getPageQuery(offset, limit); const sql = display.getPageQuery(offset, limit);
const response = await axiosInstance.request({ const response = await apiCall('database-connections/query-data', {
url: 'database-connections/query-data',
method: 'post',
params: {
conid, conid,
database, database,
}, sql,
data: { sql },
}); });
if (response.data.errorMessage) return response.data; if (response.errorMessage) return response;
return response.data.rows; return response.rows;
} }
function dataPageAvailable(props) { function dataPageAvailable(props) {
@@ -56,17 +52,13 @@
const sql = display.getCountQuery(); const sql = display.getCountQuery();
const response = await axiosInstance.request({ const response = await apiCall('database-connections/query-data', {
url: 'database-connections/query-data',
method: 'post',
params: {
conid, conid,
database, database,
}, sql,
data: { sql },
}); });
return parseInt(response.data.rows[0].count); return parseInt(response.rows[0].count);
} }
</script> </script>
@@ -77,8 +69,8 @@
import ImportExportModal from '../modals/ImportExportModal.svelte'; import ImportExportModal from '../modals/ImportExportModal.svelte';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import { extensions } from '../stores'; import { extensions } from '../stores';
import { apiCall } from '../utility/api';
import axiosInstance from '../utility/axiosInstance';
import { registerMenu } from '../utility/contextMenu'; import { registerMenu } from '../utility/contextMenu';
import createActivator, { getActiveComponent } from '../utility/createActivator'; import createActivator, { getActiveComponent } from '../utility/createActivator';
import createQuickExportMenu from '../utility/createQuickExportMenu'; import createQuickExportMenu from '../utility/createQuickExportMenu';

View File

@@ -2,7 +2,7 @@
import InputTextModal from '../modals/InputTextModal.svelte'; import InputTextModal from '../modals/InputTextModal.svelte';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import axiosInstance from '../utility/axiosInstance'; import { apiCall } from '../utility/api';
import { useArchiveFolders } from '../utility/metadataLoaders'; import { useArchiveFolders } from '../utility/metadataLoaders';
import { getFormContext } from './FormProviderCore.svelte'; import { getFormContext } from './FormProviderCore.svelte';
@@ -34,7 +34,7 @@
]; ];
const createOption = folder => { const createOption = folder => {
axiosInstance.post('archive/create-folder', { folder }); apiCall('archive/create-folder', { folder });
setFieldValue(name, folder); setFieldValue(name, folder);
}; };

View File

@@ -11,10 +11,10 @@
const { values, setFieldValue } = getFormContext(); const { values, setFieldValue } = getFormContext();
function handleBrowse() { async function handleBrowse() {
const electron = getElectron(); const electron = getElectron();
if (!electron) return; if (!electron) return;
const filePaths = electron.remote.dialog.showOpenDialogSync(electron.remote.getCurrentWindow(), { const filePaths = await electron.showOpenDialog({
defaultPath: values[name], defaultPath: values[name],
properties: ['showHiddenFiles'], properties: ['showHiddenFiles'],
filters: [{ name: 'All Files', extensions: ['*'] }], filters: [{ name: 'All Files', extensions: ['*'] }],

View File

@@ -174,8 +174,8 @@
import FontIcon from '../icons/FontIcon.svelte'; import FontIcon from '../icons/FontIcon.svelte';
import DictionaryLookupModal from '../modals/DictionaryLookupModal.svelte'; import DictionaryLookupModal from '../modals/DictionaryLookupModal.svelte';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import { apiCall } from '../utility/api';
import axiosInstance from '../utility/axiosInstance';
import { copyTextToClipboard, extractRowCopiedValue } from '../utility/clipboard'; import { copyTextToClipboard, extractRowCopiedValue } from '../utility/clipboard';
import contextMenu, { getContextMenu, registerMenu } from '../utility/contextMenu'; import contextMenu, { getContextMenu, registerMenu } from '../utility/contextMenu';
import createActivator, { getActiveComponent } from '../utility/createActivator'; import createActivator, { getActiveComponent } from '../utility/createActivator';
@@ -260,7 +260,7 @@
} }
export async function reconnect() { export async function reconnect() {
await axiosInstance.post('database-connections/refresh', { conid, database }); await apiCall('database-connections/refresh', { conid, database });
formDisplay.reload(); formDisplay.reload();
} }

View File

@@ -4,25 +4,21 @@
if (!sql) return null; if (!sql) return null;
const response = await axiosInstance.request({ const response = await apiCall('database-connections/query-data', {
url: 'database-connections/query-data',
method: 'post',
params: {
conid, conid,
database, database,
}, sql,
data: { sql },
}); });
if (response.data.errorMessage) return response.data; if (response.errorMessage) return response;
return response.data.rows[0]; return response.rows[0];
} }
</script> </script>
<script lang="ts"> <script lang="ts">
import axiosInstance from '../utility/axiosInstance';
import ChangeSetFormer from './ChangeSetFormer'; import ChangeSetFormer from './ChangeSetFormer';
import FormView from './FormView.svelte'; import FormView from './FormView.svelte';
import { apiCall } from '../utility/api';
export let formDisplay; export let formDisplay;
export let changeSetState; export let changeSetState;
@@ -122,42 +118,6 @@
$: former = new ChangeSetFormer(rowData, changeSetState, dispatchChangeSet, formDisplay); $: former = new ChangeSetFormer(rowData, changeSetState, dispatchChangeSet, formDisplay);
$: if (onReferenceSourceChanged && rowData) onReferenceSourceChanged([rowData], loadedTime); $: if (onReferenceSourceChanged && rowData) onReferenceSourceChanged([rowData], loadedTime);
// async function handleConfirmSql(sql) {
// const resp = await axiosInstance.request({
// url: 'database-connections/query-data',
// method: 'post',
// params: {
// conid,
// database,
// },
// data: { sql },
// });
// const { errorMessage } = resp.data || {};
// if (errorMessage) {
// showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage });
// } else {
// dispatchChangeSet({ type: 'reset', value: createChangeSet() });
// formDisplay.reload();
// }
// }
// function handleSave() {
// const script = changeSetToSql(changeSetState && changeSetState.value, formDisplay.dbinfo);
// const sql = scriptToSql(formDisplay.driver, script);
// showModal(ConfirmSqlModal, {
// sql,
// onConfirm: () => handleConfirmSql(sql),
// engine: formDisplay.engine,
// });
// }
</script> </script>
<FormView <FormView {...$$props} {former} isLoading={isLoadingData} {allRowCount} {rowCountBefore} onNavigate={handleNavigate} />
{...$$props}
{former}
isLoading={isLoadingData}
{allRowCount}
{rowCountBefore}
onNavigate={handleNavigate}
/>

View File

@@ -20,7 +20,7 @@
import DataGridCore from '../datagrid/DataGridCore.svelte'; import DataGridCore from '../datagrid/DataGridCore.svelte';
import ImportExportModal from '../modals/ImportExportModal.svelte'; import ImportExportModal from '../modals/ImportExportModal.svelte';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import axiosInstance from '../utility/axiosInstance'; import { apiCall } from '../utility/api';
import { registerMenu } from '../utility/contextMenu'; import { registerMenu } from '../utility/contextMenu';
import createActivator, { getActiveComponent } from '../utility/createActivator'; import createActivator, { getActiveComponent } from '../utility/createActivator';
import FreeTableGrider from './FreeTableGrider'; import FreeTableGrider from './FreeTableGrider';
@@ -45,7 +45,7 @@
export async function exportGrid() { export async function exportGrid() {
const jslid = uuidv1(); const jslid = uuidv1();
await axiosInstance.post('jsldata/save-free-table', { jslid, data: modelState.value }); await apiCall('jsldata/save-free-table', { jslid, data: modelState.value });
const initialValues: any = {}; const initialValues: any = {};
initialValues.sourceStorageType = 'jsldata'; initialValues.sourceStorageType = 'jsldata';
initialValues.sourceJslId = jslid; initialValues.sourceJslId = jslid;

View File

@@ -19,11 +19,11 @@
let isLoading = false; let isLoading = false;
const electron = getElectron();
const { values } = getFormContext(); const { values } = getFormContext();
const handleClick = async () => { const handleClick = async () => {
const files = electron.remote.dialog.showOpenDialogSync(electron.remote.getCurrentWindow(), { const electron = getElectron();
const files = await electron.showOpenDialog({
properties: ['openFile', 'multiSelections'], properties: ['openFile', 'multiSelections'],
filters: getFileFilters($extensions, $values.sourceStorageType), filters: getFileFilters($extensions, $values.sourceStorageType),
}); });

View File

@@ -6,7 +6,7 @@
import RowsArrayGrider from '../datagrid/RowsArrayGrider'; import RowsArrayGrider from '../datagrid/RowsArrayGrider';
import ErrorInfo from '../elements/ErrorInfo.svelte'; import ErrorInfo from '../elements/ErrorInfo.svelte';
import LoadingInfo from '../elements/LoadingInfo.svelte'; import LoadingInfo from '../elements/LoadingInfo.svelte';
import axiosInstance from '../utility/axiosInstance'; import { apiCall } from '../utility/api';
export let reader; export let reader;
@@ -27,14 +27,16 @@
} }
errorMessage = null; errorMessage = null;
isLoading = true; isLoading = true;
const resp = await axiosInstance.post('runners/load-reader', sourceReader); const resp = await apiCall('runners/load-reader', sourceReader);
// @ts-ignore // @ts-ignore
model = resp.data; model = resp;
grider = new RowsArrayGrider(resp.data.rows); grider = new RowsArrayGrider(resp.rows);
isLoading = false; isLoading = false;
} catch (err) { } catch (err) {
isLoading = false; isLoading = false;
errorMessage = (err && err.response && err.response.data && err.response.data.error) || 'Loading failed'; // errorMessage = (err && err.response && err.response.data && err.response.data.error) || 'Loading failed';
// TODO API
errorMessage = 'Loading failed';
console.error(err.response); console.error(err.response);
} }
}; };

View File

@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import ColorSelector from '../forms/ColorSelector.svelte'; import ColorSelector from '../forms/ColorSelector.svelte';
import axiosInstance from '../utility/axiosInstance'; import { apiCall } from '../utility/api';
import { useConnectionColor } from '../utility/useConnectionColor'; import { useConnectionColor } from '../utility/useConnectionColor';
import ModalBase from './ModalBase.svelte'; import ModalBase from './ModalBase.svelte';
@@ -27,13 +27,13 @@
value = e.detail; value = e.detail;
if (database) { if (database) {
axiosInstance.post('connections/update-database', { apiCall('connections/update-database', {
conid, conid,
database, database,
values: { connectionColor: e.detail }, values: { connectionColor: e.detail },
}); });
} else { } else {
axiosInstance.post('connections/update', { apiCall('connections/update', {
_id: conid, _id: conid,
values: { connectionColor: e.detail }, values: { connectionColor: e.detail },
}); });

View File

@@ -11,7 +11,7 @@
import FormTextField from '../forms/FormTextField.svelte'; import FormTextField from '../forms/FormTextField.svelte';
import FontIcon from '../icons/FontIcon.svelte'; import FontIcon from '../icons/FontIcon.svelte';
import { commandsSettings } from '../stores'; import { commandsSettings } from '../stores';
import axiosInstance from '../utility/axiosInstance'; import { apiCall } from '../utility/api';
import KeyboardModal from './KeyboardModal.svelte'; import KeyboardModal from './KeyboardModal.svelte';
import ModalBase from './ModalBase.svelte'; import ModalBase from './ModalBase.svelte';
import { closeCurrentModal, showModal } from './modalTools'; import { closeCurrentModal, showModal } from './modalTools';
@@ -42,7 +42,7 @@
value="OK" value="OK"
on:click={e => { on:click={e => {
closeCurrentModal(); closeCurrentModal();
axiosInstance.post('config/update-settings', { apiCall('config/update-settings', {
commands: { commands: {
...$commandsSettings, ...$commandsSettings,
[command.id]: { [command.id]: {
@@ -58,7 +58,7 @@
value="Reset" value="Reset"
on:click={() => { on:click={() => {
closeCurrentModal(); closeCurrentModal();
axiosInstance.post('config/update-settings', { apiCall('config/update-settings', {
commands: _.omit($commandsSettings, [command.id]), commands: _.omit($commandsSettings, [command.id]),
}); });
}} }}

View File

@@ -4,7 +4,6 @@
import FormProvider from '../forms/FormProvider.svelte'; import FormProvider from '../forms/FormProvider.svelte';
import FormSubmit from '../forms/FormSubmit.svelte'; import FormSubmit from '../forms/FormSubmit.svelte';
import FontIcon from '../icons/FontIcon.svelte'; import FontIcon from '../icons/FontIcon.svelte';
import axiosInstance from '../utility/axiosInstance';
import TabControl from '../elements/TabControl.svelte'; import TabControl from '../elements/TabControl.svelte';
import ConnectionModalDriverFields from './ConnectionModalDriverFields.svelte'; import ConnectionModalDriverFields from './ConnectionModalDriverFields.svelte';
import ConnectionModalSshTunnelFields from './ConnectionModalSshTunnelFields.svelte'; import ConnectionModalSshTunnelFields from './ConnectionModalSshTunnelFields.svelte';
@@ -21,6 +20,7 @@
import { extensions } from '../stores'; import { extensions } from '../stores';
import _ from 'lodash'; import _ from 'lodash';
import { getDatabaseFileLabel } from '../utility/getConnectionLabel'; import { getDatabaseFileLabel } from '../utility/getConnectionLabel';
import { apiCall } from '../utility/api';
export let connection; export let connection;
@@ -38,11 +38,11 @@
isTesting = true; isTesting = true;
testIdRef.update(x => x + 1); testIdRef.update(x => x + 1);
const testid = testIdRef.get(); const testid = testIdRef.get();
const resp = await axiosInstance.post('connections/test', e.detail); const resp = await apiCall('connections/test', e.detail);
if (testIdRef.get() != testid) return; if (testIdRef.get() != testid) return;
isTesting = false; isTesting = false;
sqlConnectResult = resp.data; sqlConnectResult = resp;
} }
function handleCancelTest() { function handleCancelTest() {
@@ -70,10 +70,9 @@
let connection = _.omit(e.detail, omitProps); let connection = _.omit(e.detail, omitProps);
if (driver?.beforeConnectionSave) connection = driver?.beforeConnectionSave(connection); if (driver?.beforeConnectionSave) connection = driver?.beforeConnectionSave(connection);
axiosInstance.post('connections/save', connection); apiCall('connections/save', connection);
closeCurrentModal(); closeCurrentModal();
} }
</script> </script>
<FormProviderCore template={FormFieldTemplateLarge} {values}> <FormProviderCore template={FormFieldTemplateLarge} {values}>
@@ -156,5 +155,4 @@
.error-result { .error-result {
white-space: normal; white-space: normal;
} }
</style> </style>

View File

@@ -6,7 +6,6 @@
import { closeCurrentModal, showModal } from './modalTools'; import { closeCurrentModal, showModal } from './modalTools';
import DefineDictionaryDescriptionModal from './DefineDictionaryDescriptionModal.svelte'; import DefineDictionaryDescriptionModal from './DefineDictionaryDescriptionModal.svelte';
import ScrollableTableControl from '../elements/ScrollableTableControl.svelte'; import ScrollableTableControl from '../elements/ScrollableTableControl.svelte';
import axiosInstance from '../utility/axiosInstance';
import { getTableInfo } from '../utility/metadataLoaders'; import { getTableInfo } from '../utility/metadataLoaders';
import { getDictionaryDescription } from '../utility/dictionaryDescriptionTools'; import { getDictionaryDescription } from '../utility/dictionaryDescriptionTools';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
@@ -15,6 +14,7 @@
import SearchInput from '../elements/SearchInput.svelte'; import SearchInput from '../elements/SearchInput.svelte';
import FormTextField from '../forms/FormTextField.svelte'; import FormTextField from '../forms/FormTextField.svelte';
import _ from 'lodash'; import _ from 'lodash';
import { apiCall } from '../utility/api';
export let onConfirm; export let onConfirm;
export let conid; export let conid;
@@ -100,17 +100,13 @@
dumpSqlSelect(dmp, select); dumpSqlSelect(dmp, select);
isLoading = true; isLoading = true;
const response = await axiosInstance.request({ const response = await apiCall('database-connections/query-data', {
url: 'database-connections/query-data',
method: 'post',
params: {
conid, conid,
database, database,
}, sql: dmp.s,
data: { sql: dmp.s },
}); });
rows = response.data.rows; rows = response.rows;
isLoading = false; isLoading = false;
} }

View File

@@ -5,7 +5,6 @@
import hasPermission from '../utility/hasPermission'; import hasPermission from '../utility/hasPermission';
import localforage from 'localforage'; import localforage from 'localforage';
import ModalBase from './ModalBase.svelte'; import ModalBase from './ModalBase.svelte';
import axiosInstance from '../utility/axiosInstance';
import uuidv1 from 'uuid/v1'; import uuidv1 from 'uuid/v1';
import { closeCurrentModal } from './modalTools'; import { closeCurrentModal } from './modalTools';
import { copyTextToClipboard } from '../utility/clipboard'; import { copyTextToClipboard } from '../utility/clipboard';
@@ -16,6 +15,7 @@
import FormSelectField from '../forms/FormSelectField.svelte'; import FormSelectField from '../forms/FormSelectField.svelte';
import FormSubmit from '../forms/FormSubmit.svelte'; import FormSubmit from '../forms/FormSubmit.svelte';
import FormButton from '../forms/FormButton.svelte'; import FormButton from '../forms/FormButton.svelte';
import { apiCall } from '../utility/api';
export let editingData; export let editingData;
export let savingTab; export let savingTab;
@@ -69,7 +69,7 @@ import FormButton from '../forms/FormButton.svelte';
const saveTab = async values => { const saveTab = async values => {
const data = await getTabSaveData(values); const data = await getTabSaveData(values);
axiosInstance.post('files/save', { apiCall('files/save', {
folder: 'favorites', folder: 'favorites',
file: uuidv1(), file: uuidv1(),
format: 'json', format: 'json',
@@ -78,18 +78,18 @@ import FormButton from '../forms/FormButton.svelte';
}; };
const saveFile = async values => { const saveFile = async values => {
const oldDataResp = await axiosInstance.post('files/load', { const oldDataResp = await apiCall('files/load', {
folder: 'favorites', folder: 'favorites',
file: editingData.file, file: editingData.file,
format: 'json', format: 'json',
}); });
axiosInstance.post('files/save', { apiCall('files/save', {
folder: 'favorites', folder: 'favorites',
file: editingData.file, file: editingData.file,
format: 'json', format: 'json',
data: { data: {
...oldDataResp.data, ...oldDataResp,
...values, ...values,
}, },
}); });

View File

@@ -16,10 +16,9 @@
import RunnerOutputFiles from '../query/RunnerOutputFiles.svelte'; import RunnerOutputFiles from '../query/RunnerOutputFiles.svelte';
import SocketMessageView from '../query/SocketMessageView.svelte'; import SocketMessageView from '../query/SocketMessageView.svelte';
import { currentArchive, currentDatabase, extensions, selectedWidget } from '../stores'; import { currentArchive, currentDatabase, extensions, selectedWidget } from '../stores';
import axiosInstance from '../utility/axiosInstance'; import { apiCall, apiOff, apiOn } from '../utility/api';
import createRef from '../utility/createRef'; import createRef from '../utility/createRef';
import openNewTab from '../utility/openNewTab'; import openNewTab from '../utility/openNewTab';
import socket from '../utility/socket';
import useEffect from '../utility/useEffect'; import useEffect from '../utility/useEffect';
import WidgetColumnBar from '../widgets/WidgetColumnBar.svelte'; import WidgetColumnBar from '../widgets/WidgetColumnBar.svelte';
import WidgetColumnBarItem from '../widgets/WidgetColumnBarItem.svelte'; import WidgetColumnBarItem from '../widgets/WidgetColumnBarItem.svelte';
@@ -67,9 +66,9 @@
function registerRunnerDone(rid) { function registerRunnerDone(rid) {
if (rid) { if (rid) {
socket.on(`runner-done-${rid}`, handleRunnerDone); apiOn(`runner-done-${rid}`, handleRunnerDone);
return () => { return () => {
socket.off(`runner-done-${rid}`, handleRunnerDone); apiOff(`runner-done-${rid}`, handleRunnerDone);
}; };
} else { } else {
return () => {}; return () => {};
@@ -81,8 +80,8 @@
const handleRunnerDone = () => { const handleRunnerDone = () => {
busy = false; busy = false;
if (refreshArchiveFolderRef.get()) { if (refreshArchiveFolderRef.get()) {
axiosInstance.post('archive/refresh-folders', {}); apiCall('archive/refresh-folders', {});
axiosInstance.post('archive/refresh-files', { folder: refreshArchiveFolderRef.get() }); apiCall('archive/refresh-files', { folder: refreshArchiveFolderRef.get() });
$currentArchive = refreshArchiveFolderRef.get(); $currentArchive = refreshArchiveFolderRef.get();
$selectedWidget = 'archive'; $selectedWidget = 'archive';
} }
@@ -108,8 +107,8 @@
const script = await createImpExpScript($extensions, values); const script = await createImpExpScript($extensions, values);
executeNumber += 1; executeNumber += 1;
let runid = runnerId; let runid = runnerId;
const resp = await axiosInstance.post('runners/start', { script }); const resp = await apiCall('runners/start', { script });
runid = resp.data.runid; runid = resp.runid;
runnerId = runid; runnerId = runid;
if (values.targetStorageType == 'archive') { if (values.targetStorageType == 'archive') {
@@ -120,7 +119,7 @@
}; };
const handleCancel = () => { const handleCancel = () => {
axiosInstance.post('runners/cancel', { apiCall('runners/cancel', {
runid: runnerId, runid: runnerId,
}); });
}; };

View File

@@ -4,8 +4,8 @@
import FormProvider from '../forms/FormProvider.svelte'; import FormProvider from '../forms/FormProvider.svelte';
import FormSubmit from '../forms/FormSubmit.svelte'; import FormSubmit from '../forms/FormSubmit.svelte';
import FormTextField from '../forms/FormTextField.svelte'; import FormTextField from '../forms/FormTextField.svelte';
import { apiCall } from '../utility/api';
import axiosInstance from '../utility/axiosInstance';
import getElectron from '../utility/getElectron'; import getElectron from '../utility/getElectron';
import ModalBase from './ModalBase.svelte'; import ModalBase from './ModalBase.svelte';
import { closeCurrentModal } from './modalTools'; import { closeCurrentModal } from './modalTools';
@@ -22,7 +22,7 @@
const handleSubmit = async e => { const handleSubmit = async e => {
const { name } = e.detail; const { name } = e.detail;
await axiosInstance.post('files/save', { folder, file: name, data, format }); await apiCall('files/save', { folder, file: name, data, format });
closeCurrentModal(); closeCurrentModal();
if (onSave) { if (onSave) {
onSave(name, { onSave(name, {
@@ -38,7 +38,7 @@
const parsed = path.parse(filePath); const parsed = path.parse(filePath);
// if (!parsed.ext) filePath += `.${fileExtension}`; // if (!parsed.ext) filePath += `.${fileExtension}`;
await axiosInstance.post('files/save-as', { filePath, data, format }); await apiCall('files/save-as', { filePath, data, format });
closeCurrentModal(); closeCurrentModal();
if (onSave) { if (onSave) {
@@ -61,8 +61,8 @@
<FormStyledButton <FormStyledButton
type="button" type="button"
value="Save to disk" value="Save to disk"
on:click={() => { on:click={async () => {
const file = electron.remote.dialog.showSaveDialogSync(electron.remote.getCurrentWindow(), { const file = await electron.showSaveDialog({
filters: [ filters: [
{ name: `${fileExtension.toUpperCase()} files`, extensions: [fileExtension] }, { name: `${fileExtension.toUpperCase()} files`, extensions: [fileExtension] },
{ name: `All files`, extensions: ['*'] }, { name: `All files`, extensions: ['*'] },

View File

@@ -18,7 +18,6 @@
import FontIcon from '../icons/FontIcon.svelte'; import FontIcon from '../icons/FontIcon.svelte';
import SqlEditor from '../query/SqlEditor.svelte'; import SqlEditor from '../query/SqlEditor.svelte';
import axiosInstance from '../utility/axiosInstance';
import createRef from '../utility/createRef'; import createRef from '../utility/createRef';
import { useDatabaseInfo } from '../utility/metadataLoaders'; import { useDatabaseInfo } from '../utility/metadataLoaders';
import WidgetColumnBar from '../widgets/WidgetColumnBar.svelte'; import WidgetColumnBar from '../widgets/WidgetColumnBar.svelte';
@@ -32,6 +31,7 @@
import ErrorInfo from '../elements/ErrorInfo.svelte'; import ErrorInfo from '../elements/ErrorInfo.svelte';
import LoadingInfo from '../elements/LoadingInfo.svelte'; import LoadingInfo from '../elements/LoadingInfo.svelte';
import { getObjectTypeFieldLabel } from '../utility/common'; import { getObjectTypeFieldLabel } from '../utility/common';
import { apiCall } from '../utility/api';
export let conid; export let conid;
export let database; export let database;
@@ -86,7 +86,7 @@
const loadid = uuidv1(); const loadid = uuidv1();
loadRef.set(loadid); loadRef.set(loadid);
busy = true; busy = true;
const response = await axiosInstance.post('database-connections/sql-preview', { const response = await apiCall('database-connections/sql-preview', {
conid, conid,
database, database,
objects, objects,
@@ -96,7 +96,7 @@
// newer load exists // newer load exists
return; return;
} }
const { sql, isTruncated, isError, errorMessage } = response.data || {}; const { sql, isTruncated, isError, errorMessage } = response || {};
truncated = isTruncated; truncated = isTruncated;
if (isError) { if (isError) {
@@ -127,7 +127,6 @@
); );
closeCurrentModal(); closeCurrentModal();
} }
</script> </script>
<FormProviderCore values={valuesStore} template={FormFieldTemplateTiny}> <FormProviderCore values={valuesStore} template={FormFieldTemplateTiny}>
@@ -257,5 +256,4 @@
.dbname { .dbname {
color: var(--theme-font-3); color: var(--theme-font-3);
} }
</style> </style>

View File

@@ -6,7 +6,6 @@
import { closeCurrentModal, showModal } from './modalTools'; import { closeCurrentModal, showModal } from './modalTools';
import DefineDictionaryDescriptionModal from './DefineDictionaryDescriptionModal.svelte'; import DefineDictionaryDescriptionModal from './DefineDictionaryDescriptionModal.svelte';
import ScrollableTableControl from '../elements/ScrollableTableControl.svelte'; import ScrollableTableControl from '../elements/ScrollableTableControl.svelte';
import axiosInstance from '../utility/axiosInstance';
import { getDictionaryDescription } from '../utility/dictionaryDescriptionTools'; import { getDictionaryDescription } from '../utility/dictionaryDescriptionTools';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { dumpSqlSelect } from 'dbgate-sqltree'; import { dumpSqlSelect } from 'dbgate-sqltree';
@@ -14,6 +13,7 @@
import SearchInput from '../elements/SearchInput.svelte'; import SearchInput from '../elements/SearchInput.svelte';
import FormTextField from '../forms/FormTextField.svelte'; import FormTextField from '../forms/FormTextField.svelte';
import _ from 'lodash'; import _ from 'lodash';
import { apiCall } from '../utility/api';
export let onConfirm; export let onConfirm;
export let conid; export let conid;
@@ -85,17 +85,13 @@
dumpSqlSelect(dmp, select); dumpSqlSelect(dmp, select);
isLoading = true; isLoading = true;
const response = await axiosInstance.request({ const response = await apiCall('database-connections/query-data', {
url: 'database-connections/query-data',
method: 'post',
params: {
conid, conid,
database, database,
}, sql: dmp.s,
data: { sql: dmp.s },
}); });
rows = response.data.rows; rows = response.rows;
isLoading = false; isLoading = false;
} }

View File

@@ -3,20 +3,14 @@
import SearchBoxWrapper from '../elements/SearchBoxWrapper.svelte'; import SearchBoxWrapper from '../elements/SearchBoxWrapper.svelte';
import SearchInput from '../elements/SearchInput.svelte'; import SearchInput from '../elements/SearchInput.svelte';
import useFetch from '../utility/useFetch'; import { useApiCall } from '../utility/api';
import WidgetsInnerContainer from '../widgets/WidgetsInnerContainer.svelte'; import WidgetsInnerContainer from '../widgets/WidgetsInnerContainer.svelte';
import PluginsList from './PluginsList.svelte'; import PluginsList from './PluginsList.svelte';
let filter = ''; let filter = '';
let search = ''; let search = '';
$: plugins = useFetch({ $: plugins = useApiCall('plugins/search', { filter: search }, []);
url: 'plugins/search',
params: {
filter: search,
},
defaultValue: [],
});
const setDebouncedFilter = _.debounce(value => (search = value), 500); const setDebouncedFilter = _.debounce(value => (search = value), 500);

View File

@@ -1,6 +1,6 @@
<script lang="ts" context="module"> <script lang="ts" context="module">
const dbgateEnv = { const dbgateEnv = {
axios: axiosInstance, apiCall,
}; };
async function loadPlugins(pluginsDict, installedPlugins) { async function loadPlugins(pluginsDict, installedPlugins) {
@@ -14,14 +14,10 @@
loaded: false, loaded: false,
loadingPackageName: installed.name, loadingPackageName: installed.name,
}); });
const resp = await axiosInstance.request({ const resp = await apiCall('plugins/script', {
method: 'get',
url: 'plugins/script',
params: {
packageName: installed.name, packageName: installed.name,
},
}); });
const module = eval(`${resp.data}; plugin`); const module = eval(`${resp}; plugin`);
console.log('Loaded plugin', module); console.log('Loaded plugin', module);
const moduleContent = module.__esModule ? module.default : module; const moduleContent = module.__esModule ? module.default : module;
if (moduleContent.initialize) moduleContent.initialize(dbgateEnv); if (moduleContent.initialize) moduleContent.initialize(dbgateEnv);
@@ -55,17 +51,16 @@
}; };
return extensions; return extensions;
} }
</script> </script>
<script lang="ts"> <script lang="ts">
import _ from 'lodash'; import _ from 'lodash';
import { extensions, loadingPluginStore } from '../stores'; import { extensions, loadingPluginStore } from '../stores';
import axiosInstance from '../utility/axiosInstance';
import { useInstalledPlugins } from '../utility/metadataLoaders'; import { useInstalledPlugins } from '../utility/metadataLoaders';
import { buildFileFormats, buildQuickExports } from './fileformats'; import { buildFileFormats, buildQuickExports } from './fileformats';
import { buildThemes } from './themes'; import { buildThemes } from './themes';
import dbgateTools from 'dbgate-tools'; import dbgateTools from 'dbgate-tools';
import { apiCall } from '../utility/api';
let pluginsDict = {}; let pluginsDict = {};
const installedPlugins = useInstalledPlugins(); const installedPlugins = useInstalledPlugins();
@@ -87,5 +82,4 @@
.filter(x => x.content); .filter(x => x.content);
$: $extensions = buildExtensions(plugins); $: $extensions = buildExtensions(plugins);
</script> </script>

View File

@@ -25,8 +25,6 @@
import _ from 'lodash'; import _ from 'lodash';
import { handleCommandKeyDown } from '../commands/CommandListener.svelte'; import { handleCommandKeyDown } from '../commands/CommandListener.svelte';
import resizeObserver from '../utility/resizeObserver'; import resizeObserver from '../utility/resizeObserver';
// @ts-ignore
import QueryParserWorker from 'web-worker:./QueryParserWorker';
import queryParserWorkerFallback from './queryParserWorkerFallback'; import queryParserWorkerFallback from './queryParserWorkerFallback';
const EDITOR_ID = `svelte-ace-editor-div:${Math.floor(Math.random() * 10000000000)}`; const EDITOR_ID = `svelte-ace-editor-div:${Math.floor(Math.random() * 10000000000)}`;
@@ -138,11 +136,14 @@
if (enabled) { if (enabled) {
if (!queryParserWorker) { if (!queryParserWorker) {
try { try {
queryParserWorker = new QueryParserWorker(); queryParserWorker = new Worker('build/query-parser-worker.js');
// console.log('WORKER', queryParserWorker);
queryParserWorker.onmessage = e => { queryParserWorker.onmessage = e => {
processParserResult(e.data); processParserResult(e.data);
}; };
} catch (err) { } catch (err) {
// console.error('WORKER ERROR', err);
console.log('WORKER ERROR, using fallback worker', err.message);
queryParserWorker = 'fallback'; queryParserWorker = 'fallback';
} }
} }

View File

@@ -6,7 +6,7 @@
import JslDataGrid from '../datagrid/JslDataGrid.svelte'; import JslDataGrid from '../datagrid/JslDataGrid.svelte';
import TabControl from '../elements/TabControl.svelte'; import TabControl from '../elements/TabControl.svelte';
import { allResultsInOneTabDefault } from '../stores'; import { allResultsInOneTabDefault } from '../stores';
import socket from '../utility/socket'; import { apiOff, apiOn } from '../utility/api';
import useEffect from '../utility/useEffect'; import useEffect from '../utility/useEffect';
import AllResultsTab from './AllResultsTab.svelte'; import AllResultsTab from './AllResultsTab.svelte';
@@ -66,9 +66,9 @@
}); });
function onSession(sid) { function onSession(sid) {
if (sid) { if (sid) {
socket.on(`session-recordset-${sid}`, handleResultSet); apiOn(`session-recordset-${sid}`, handleResultSet);
return () => { return () => {
socket.off(`session-recordset-${sid}`, handleResultSet); apiOff(`session-recordset-${sid}`, handleResultSet);
}; };
} }
return () => {}; return () => {};

View File

@@ -1,12 +1,11 @@
<script> <script>
import ErrorInfo from '../elements/ErrorInfo.svelte'; import ErrorInfo from '../elements/ErrorInfo.svelte';
import TableControl from '../elements/TableControl.svelte'; import TableControl from '../elements/TableControl.svelte';
import { apiOff, apiOn, apiCall } from '../utility/api';
import axiosInstance from '../utility/axiosInstance';
import formatFileSize from '../utility/formatFileSize'; import formatFileSize from '../utility/formatFileSize';
import getElectron from '../utility/getElectron'; import getElectron from '../utility/getElectron';
import resolveApi from '../utility/resolveApi'; import resolveApi from '../utility/resolveApi';
import socket from '../utility/socket';
import useEffect from '../utility/useEffect'; import useEffect from '../utility/useEffect';
export let runnerId; export let runnerId;
@@ -22,9 +21,9 @@
function registerRunnerDone(rid) { function registerRunnerDone(rid) {
if (rid) { if (rid) {
socket.on(`runner-done-${rid}`, handleRunnerDone); apiOn(`runner-done-${rid}`, handleRunnerDone);
return () => { return () => {
socket.off(`runner-done-${rid}`, handleRunnerDone); apiOff(`runner-done-${rid}`, handleRunnerDone);
}; };
} else { } else {
return () => {}; return () => {};
@@ -34,8 +33,8 @@
$: $effect; $: $effect;
const handleRunnerDone = async () => { const handleRunnerDone = async () => {
const resp = await axiosInstance.get(`runners/files?runid=${runnerId}`); const resp = await apiCall('runners/files', { runid: runnerId });
files = resp.data; files = resp;
}; };
</script> </script>
@@ -78,8 +77,8 @@
slot="1" slot="1"
let:row let:row
href="#" href="#"
on:click={() => { on:click={async () => {
const file = electron.remote.dialog.showSaveDialogSync(electron.remote.getCurrentWindow(), {}); const file = await electron.showSaveDialog({});
if (file) { if (file) {
const fs = window.require('fs'); const fs = window.require('fs');
fs.copyFile(row.path, file, () => {}); fs.copyFile(row.path, file, () => {});
@@ -94,7 +93,7 @@
let:row let:row
href="#" href="#"
on:click={() => { on:click={() => {
electron.remote.shell.showItemInFolder(row.path); electron.showItemInFolder(row.path);
}} }}
> >
show show

View File

@@ -1,10 +1,9 @@
<script lang="ts"> <script lang="ts">
import _ from 'lodash'; import _ from 'lodash';
import ErrorInfo from '../elements/ErrorInfo.svelte'; import ErrorInfo from '../elements/ErrorInfo.svelte';
import { apiOff, apiOn } from '../utility/api';
import createRef from '../utility/createRef'; import createRef from '../utility/createRef';
import socket from '../utility/socket';
import useEffect from '../utility/useEffect'; import useEffect from '../utility/useEffect';
import MessageView from './MessageView.svelte'; import MessageView from './MessageView.svelte';
@@ -30,9 +29,9 @@
$: effect = useEffect(() => { $: effect = useEffect(() => {
if (eventName) { if (eventName) {
socket.on(eventName, handleInfo); apiOn(eventName, handleInfo);
return () => { return () => {
socket.off(eventName, handleInfo); apiOff(eventName, handleInfo);
}; };
} }
return () => {}; return () => {};

View File

@@ -13,10 +13,10 @@
import ModalBase from '../modals/ModalBase.svelte'; import ModalBase from '../modals/ModalBase.svelte';
import { closeCurrentModal } from '../modals/modalTools'; import { closeCurrentModal } from '../modals/modalTools';
import { getCurrentSettings, getVisibleToolbar, getZoomKoef, visibleToolbar, zoomKoef } from '../stores'; import { getCurrentSettings, getVisibleToolbar, getZoomKoef, visibleToolbar, zoomKoef } from '../stores';
import axiosInstance from '../utility/axiosInstance'; import { apiCall } from '../utility/api';
function handleOk(e) { function handleOk(e) {
axiosInstance.post( apiCall(
'config/update-settings', 'config/update-settings',
_.omitBy(e.detail, (v, k) => k.startsWith(':')) _.omitBy(e.detail, (v, k) => k.startsWith(':'))
); );

View File

@@ -44,7 +44,7 @@ export const activeTab = derived([openedTabs], ([$openedTabs]) => $openedTabs.fi
export const recentDatabases = writableWithStorage([], 'recentDatabases'); export const recentDatabases = writableWithStorage([], 'recentDatabases');
export const pinnedDatabases = writableWithStorage([], 'pinnedDatabases'); export const pinnedDatabases = writableWithStorage([], 'pinnedDatabases');
export const pinnedTables = writableWithStorage([], 'pinnedTables'); export const pinnedTables = writableWithStorage([], 'pinnedTables');
export const commandsSettings = derived(useSettings(), (config: any) => (config || {}).commands || {}); export const commandsSettings = writable({});
export const allResultsInOneTabDefault = writableWithStorage(false, 'allResultsInOneTabDefault'); export const allResultsInOneTabDefault = writableWithStorage(false, 'allResultsInOneTabDefault');
export const archiveFilesAsDataSheets = writableWithStorage([], 'archiveFilesAsDataSheets'); export const archiveFilesAsDataSheets = writableWithStorage([], 'archiveFilesAsDataSheets');
export const commandsCustomized = derived([commands, commandsSettings], ([$commands, $commandsSettings]) => export const commandsCustomized = derived([commands, commandsSettings], ([$commands, $commandsSettings]) =>
@@ -74,8 +74,6 @@ export const currentThemeDefinition = derived([currentTheme, extensions], ([$cur
$extensions.themes.find(x => x.className == $currentTheme) $extensions.themes.find(x => x.className == $currentTheme)
); );
const electron = getElectron();
subscribeCssVariable(selectedWidget, x => (x ? 1 : 0), '--dim-visible-left-panel'); subscribeCssVariable(selectedWidget, x => (x ? 1 : 0), '--dim-visible-left-panel');
subscribeCssVariable(visibleToolbar, x => (x ? 1 : 0), '--dim-visible-toolbar'); subscribeCssVariable(visibleToolbar, x => (x ? 1 : 0), '--dim-visible-toolbar');
subscribeCssVariable(leftPanelWidth, x => `${x}px`, '--dim-left-panel-width'); subscribeCssVariable(leftPanelWidth, x => `${x}px`, '--dim-left-panel-width');
@@ -119,9 +117,9 @@ let commandsValue = null;
commands.subscribe(value => { commands.subscribe(value => {
commandsValue = value; commandsValue = value;
const electron = getElectron();
if (electron) { if (electron) {
const { ipcRenderer } = electron; electron.send('update-commands', JSON.stringify(value));
ipcRenderer.send('update-commands', JSON.stringify(value));
} }
}); });
export const getCommands = () => commandsValue; export const getCommands = () => commandsValue;
@@ -132,15 +130,7 @@ activeTab.subscribe(value => {
}); });
export const getActiveTab = () => activeTabValue; export const getActiveTab = () => activeTabValue;
const currentConfigStore = useConfig();
let currentConfigValue = null; let currentConfigValue = null;
currentConfigStore.subscribe(value => {
currentConfigValue = value;
invalidateCommands();
if (value.singleDatabase) {
currentDatabase.set(value.singleDatabase);
}
});
export const getCurrentConfig = () => currentConfigValue; export const getCurrentConfig = () => currentConfigValue;
let recentDatabasesValue = null; let recentDatabasesValue = null;
@@ -163,10 +153,6 @@ currentDatabase.subscribe(value => {
export const getCurrentDatabase = () => currentDatabaseValue; export const getCurrentDatabase = () => currentDatabaseValue;
let currentSettingsValue = null; let currentSettingsValue = null;
useSettings().subscribe(value => {
currentSettingsValue = value;
invalidateCommands();
});
export const getCurrentSettings = () => currentSettingsValue || {}; export const getCurrentSettings = () => currentSettingsValue || {};
let extensionsValue = null; let extensionsValue = null;
@@ -180,3 +166,19 @@ openedConnections.subscribe(value => {
openedConnectionsValue = value; openedConnectionsValue = value;
}); });
export const getOpenedConnections = () => openedConnectionsValue; export const getOpenedConnections = () => openedConnectionsValue;
export function subscribeApiDependendStores() {
useSettings().subscribe(value => {
currentSettingsValue = value;
commandsSettings.set((value || {}).commands || {});
invalidateCommands();
});
useConfig().subscribe(value => {
currentConfigValue = value;
invalidateCommands();
if (value.singleDatabase) {
currentDatabase.set(value.singleDatabase);
}
});
}

View File

@@ -6,16 +6,15 @@
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import LoadingInfo from '../elements/LoadingInfo.svelte'; import LoadingInfo from '../elements/LoadingInfo.svelte';
import Markdown from '../elements/Markdown.svelte'; import Markdown from '../elements/Markdown.svelte';
import { apiCall } from '../utility/api';
import axiosInstance from '../utility/axiosInstance';
let isLoading = false; let isLoading = false;
let text = null; let text = null;
const handleLoad = async () => { const handleLoad = async () => {
isLoading = true; isLoading = true;
const resp = await axiosInstance.get('config/changelog'); const resp = await apiCall('config/changelog');
text = resp.data; text = resp;
isLoading = false; isLoading = false;
}; };

View File

@@ -26,7 +26,6 @@
import LoadingInfo from '../elements/LoadingInfo.svelte'; import LoadingInfo from '../elements/LoadingInfo.svelte';
import useEditorData from '../query/useEditorData'; import useEditorData from '../query/useEditorData';
import axiosInstance from '../utility/axiosInstance';
import { getContextMenu, registerMenu } from '../utility/contextMenu'; import { getContextMenu, registerMenu } from '../utility/contextMenu';
import createActivator, { getActiveComponent } from '../utility/createActivator'; import createActivator, { getActiveComponent } from '../utility/createActivator';
import createUndoReducer from '../utility/createUndoReducer'; import createUndoReducer from '../utility/createUndoReducer';

View File

@@ -40,7 +40,6 @@
import { extensions } from '../stores'; import { extensions } from '../stores';
import CollectionJsonView from '../jsonview/CollectionJsonView.svelte'; import CollectionJsonView from '../jsonview/CollectionJsonView.svelte';
import createActivator, { getActiveComponent } from '../utility/createActivator'; import createActivator, { getActiveComponent } from '../utility/createActivator';
import axiosInstance from '../utility/axiosInstance';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte'; import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
import ConfirmNoSqlModal from '../modals/ConfirmNoSqlModal.svelte'; import ConfirmNoSqlModal from '../modals/ConfirmNoSqlModal.svelte';
@@ -50,6 +49,7 @@
import ChangeSetGrider from '../datagrid/ChangeSetGrider'; import ChangeSetGrider from '../datagrid/ChangeSetGrider';
import { setContext } from 'svelte'; import { setContext } from 'svelte';
import _ from 'lodash'; import _ from 'lodash';
import { apiCall } from '../utility/api';
export let tabid; export let tabid;
export let conid; export let conid;
@@ -91,16 +91,12 @@
// $: console.log('LOADED ROWS MONGO', loadedRows); // $: console.log('LOADED ROWS MONGO', loadedRows);
async function handleConfirmChange(changeSet) { async function handleConfirmChange(changeSet) {
const resp = await axiosInstance.request({ const resp = await apiCall('database-connections/update-collection', {
url: 'database-connections/update-collection',
method: 'post',
params: {
conid, conid,
database, database,
}, changeSet,
data: { changeSet },
}); });
const { errorMessage } = resp.data || {}; const { errorMessage } = resp || {};
if (errorMessage) { if (errorMessage) {
showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage }); showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage });
} else { } else {

View File

@@ -154,7 +154,7 @@
import SqlEditor from '../query/SqlEditor.svelte'; import SqlEditor from '../query/SqlEditor.svelte';
import useEditorData from '../query/useEditorData'; import useEditorData from '../query/useEditorData';
import { extensions } from '../stores'; import { extensions } from '../stores';
import axiosInstance from '../utility/axiosInstance'; import { apiCall } from '../utility/api';
import { changeTab } from '../utility/common'; import { changeTab } from '../utility/common';
import contextMenu, { getContextMenu, registerMenu } from '../utility/contextMenu'; import contextMenu, { getContextMenu, registerMenu } from '../utility/contextMenu';
import createActivator, { getActiveComponent } from '../utility/createActivator'; import createActivator, { getActiveComponent } from '../utility/createActivator';
@@ -228,7 +228,7 @@
export async function showReport() { export async function showReport() {
saveFileToDisk(async filePath => { saveFileToDisk(async filePath => {
await axiosInstance.post('database-connections/generate-db-diff-report', { await apiCall('database-connections/generate-db-diff-report', {
filePath, filePath,
sourceConid: $values?.sourceConid, sourceConid: $values?.sourceConid,
sourceDatabase: $values?.sourceDatabase, sourceDatabase: $values?.sourceDatabase,
@@ -261,11 +261,11 @@
} }
export function refreshModels() { export function refreshModels() {
axiosInstance.post('database-connections/sync-model', { apiCall('database-connections/sync-model', {
conid: $values?.targetConid, conid: $values?.targetConid,
database: $values?.targetDatabase, database: $values?.targetDatabase,
}); });
axiosInstance.post('database-connections/sync-model', { apiCall('database-connections/sync-model', {
conid: $values?.sourceConid, conid: $values?.sourceConid,
database: $values?.sourceDatabase, database: $values?.sourceDatabase,
}); });
@@ -275,18 +275,13 @@
const conid = $values?.targetConid; const conid = $values?.targetConid;
const database = $values?.targetDatabase; const database = $values?.targetDatabase;
const resp = await axiosInstance.request({ const resp = await apiCall('database-connections/run-script', { conid, database, sql });
url: 'database-connections/run-script', const { errorMessage } = resp || {};
method: 'post',
params: { conid, database },
data: { sql },
});
const { errorMessage } = resp.data || {};
if (errorMessage) { if (errorMessage) {
showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage }); showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage });
} else { } else {
$values = _.omitBy($values, (v, k) => k.startsWith('isChecked_')); $values = _.omitBy($values, (v, k) => k.startsWith('isChecked_'));
await axiosInstance.post('database-connections/sync-model', { conid, database }); await apiCall('database-connections/sync-model', { conid, database });
showSnackbarSuccess('Saved to database'); showSnackbarSuccess('Saved to database');
} }
} }

View File

@@ -38,11 +38,11 @@
import AceEditor from '../query/AceEditor.svelte'; import AceEditor from '../query/AceEditor.svelte';
import useEditorData from '../query/useEditorData'; import useEditorData from '../query/useEditorData';
import invalidateCommands from '../commands/invalidateCommands'; import invalidateCommands from '../commands/invalidateCommands';
import axiosInstance from '../utility/axiosInstance';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte'; import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
import { openFavorite } from '../appobj/FavoriteFileAppObject.svelte'; import { openFavorite } from '../appobj/FavoriteFileAppObject.svelte';
import createActivator, { getActiveComponent } from '../utility/createActivator'; import createActivator, { getActiveComponent } from '../utility/createActivator';
import { apiCall } from '../utility/api';
export let tabid; export let tabid;
export let savedFile; export let savedFile;
@@ -97,7 +97,7 @@
export function save() { export function save() {
try { try {
const data = JSON.parse(getData()); const data = JSON.parse(getData());
axiosInstance.post('files/save', { apiCall('files/save', {
file: savedFile, file: savedFile,
folder: 'favorites', folder: 'favorites',
format: 'json', format: 'json',

View File

@@ -41,8 +41,8 @@
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import SaveArchiveModal from '../modals/SaveArchiveModal.svelte'; import SaveArchiveModal from '../modals/SaveArchiveModal.svelte';
import useEditorData from '../query/useEditorData'; import useEditorData from '../query/useEditorData';
import { apiCall } from '../utility/api';
import { markArchiveFileAsDataSheet } from '../utility/archiveTools'; import { markArchiveFileAsDataSheet } from '../utility/archiveTools';
import axiosInstance from '../utility/axiosInstance';
import { changeTab } from '../utility/common'; import { changeTab } from '../utility/common';
import { registerMenu } from '../utility/contextMenu'; import { registerMenu } from '../utility/contextMenu';
import createActivator, { getActiveComponent } from '../utility/createActivator'; import createActivator, { getActiveComponent } from '../utility/createActivator';
@@ -61,10 +61,7 @@
const { setEditorData, editorState } = useEditorData({ const { setEditorData, editorState } = useEditorData({
tabid, tabid,
loadFromArgs: loadFromArgs: initialArgs && initialArgs.functionName ? () => apiCall('runners/load-reader', initialArgs) : null,
initialArgs && initialArgs.functionName
? () => axiosInstance.post('runners/load-reader', initialArgs).then(x => x.data)
: null,
onInitialData: value => { onInitialData: value => {
dispatchModel({ type: 'reset', value }); dispatchModel({ type: 'reset', value });
}, },
@@ -84,7 +81,7 @@
} }
const doSave = async (folder, file) => { const doSave = async (folder, file) => {
await axiosInstance.post('archive/save-free-table', { folder, file, data: $modelState.value }); await apiCall('archive/save-free-table', { folder, file, data: $modelState.value });
changeTab(tabid, tab => ({ changeTab(tabid, tab => ({
...tab, ...tab,
title: file, title: file,

View File

@@ -6,8 +6,7 @@
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import LoadingInfo from '../elements/LoadingInfo.svelte'; import LoadingInfo from '../elements/LoadingInfo.svelte';
import Markdown from '../elements/Markdown.svelte'; import Markdown from '../elements/Markdown.svelte';
import { apiCall } from '../utility/api';
import axiosInstance from '../utility/axiosInstance';
export let savedFile; export let savedFile;
@@ -16,12 +15,12 @@
const handleLoad = async () => { const handleLoad = async () => {
isLoading = true; isLoading = true;
const resp = await axiosInstance.post('files/load', { const resp = await apiCall('files/load', {
folder: 'markdown', folder: 'markdown',
file: savedFile, file: savedFile,
format: 'text', format: 'text',
}); });
text = resp.data; text = resp;
isLoading = false; isLoading = false;
}; };

View File

@@ -7,33 +7,28 @@
import FormStyledButton from '../elements/FormStyledButton.svelte'; import FormStyledButton from '../elements/FormStyledButton.svelte';
import Markdown from '../elements/Markdown.svelte'; import Markdown from '../elements/Markdown.svelte';
import { extractPluginAuthor, extractPluginIcon } from '../plugins/manifestExtractors'; import { extractPluginAuthor, extractPluginIcon } from '../plugins/manifestExtractors';
import { apiCall, useApiCall } from '../utility/api';
import axiosInstance from '../utility/axiosInstance';
import hasPermission from '../utility/hasPermission'; import hasPermission from '../utility/hasPermission';
import { useInstalledPlugins } from '../utility/metadataLoaders'; import { useInstalledPlugins } from '../utility/metadataLoaders';
import useFetch from '../utility/useFetch';
export let packageName; export let packageName;
$: installed = useInstalledPlugins(); $: installed = useInstalledPlugins();
$: info = useFetch({ $: info = useApiCall('plugins/info', { packageName }, null);
params: { packageName },
url: 'plugins/info',
defaultValue: null,
});
$: readme = $info?.readme; $: readme = $info?.readme;
$: manifest = $info?.manifest; $: manifest = $info?.manifest;
$: isPackaged = $info?.isPackaged; $: isPackaged = $info?.isPackaged;
const handleInstall = async () => { const handleInstall = async () => {
axiosInstance.post('plugins/install', { packageName }); apiCall('plugins/install', { packageName });
}; };
const handleUninstall = async () => { const handleUninstall = async () => {
axiosInstance.post('plugins/uninstall', { packageName }); apiCall('plugins/uninstall', { packageName });
}; };
const handleUpgrade = async () => { const handleUpgrade = async () => {
axiosInstance.post('plugins/upgrade', { packageName }); apiCall('plugins/upgrade', { packageName });
}; };
$: installedFound = $installed?.find(x => x.name == packageName); $: installedFound = $installed?.find(x => x.name == packageName);

View File

@@ -21,10 +21,8 @@
import SqlEditor from '../query/SqlEditor.svelte'; import SqlEditor from '../query/SqlEditor.svelte';
import useEditorData from '../query/useEditorData'; import useEditorData from '../query/useEditorData';
import { extensions } from '../stores'; import { extensions } from '../stores';
import axiosInstance from '../utility/axiosInstance';
import { changeTab } from '../utility/common'; import { changeTab } from '../utility/common';
import { useConnectionInfo } from '../utility/metadataLoaders'; import { useConnectionInfo } from '../utility/metadataLoaders';
import socket from '../utility/socket';
import SocketMessageView from '../query/SocketMessageView.svelte'; import SocketMessageView from '../query/SocketMessageView.svelte';
import useEffect from '../utility/useEffect'; import useEffect from '../utility/useEffect';
import ResultTabs from '../query/ResultTabs.svelte'; import ResultTabs from '../query/ResultTabs.svelte';
@@ -38,6 +36,7 @@
import QueryDesignColumns from '../elements/QueryDesignColumns.svelte'; import QueryDesignColumns from '../elements/QueryDesignColumns.svelte';
import useTimerLabel from '../utility/useTimerLabel'; import useTimerLabel from '../utility/useTimerLabel';
import createActivator, { getActiveComponent } from '../utility/createActivator'; import createActivator, { getActiveComponent } from '../utility/createActivator';
import { apiCall, apiOff, apiOn } from '../utility/api';
export let tabid; export let tabid;
export let conid; export let conid;
@@ -62,9 +61,9 @@
}); });
function onSession(sid) { function onSession(sid) {
if (sid) { if (sid) {
socket.on(`session-done-${sid}`, handleSessionDone); apiOn(`session-done-${sid}`, handleSessionDone);
return () => { return () => {
socket.off(`session-done-${sid}`, handleSessionDone); apiOff(`session-done-${sid}`, handleSessionDone);
}; };
} }
return () => {}; return () => {};
@@ -105,23 +104,23 @@
let sesid = sessionId; let sesid = sessionId;
if (!sesid) { if (!sesid) {
const resp = await axiosInstance.post('sessions/create', { const resp = await apiCall('sessions/create', {
conid, conid,
database, database,
}); });
sesid = resp.data.sesid; sesid = resp.sesid;
sessionId = sesid; sessionId = sesid;
} }
busy = true; busy = true;
timerLabel.start(); timerLabel.start();
await axiosInstance.post('sessions/execute-query', { await apiCall('sessions/execute-query', {
sesid, sesid,
sql: sqlPreview, sql: sqlPreview,
}); });
} }
export async function kill() { export async function kill() {
await axiosInstance.post('sessions/kill', { await apiCall('sessions/kill', {
sesid: sessionId, sesid: sessionId,
}); });
sessionId = null; sessionId = null;

View File

@@ -52,10 +52,8 @@
import useEditorData from '../query/useEditorData'; import useEditorData from '../query/useEditorData';
import { extensions } from '../stores'; import { extensions } from '../stores';
import applyScriptTemplate from '../utility/applyScriptTemplate'; import applyScriptTemplate from '../utility/applyScriptTemplate';
import axiosInstance from '../utility/axiosInstance';
import { changeTab } from '../utility/common'; import { changeTab } from '../utility/common';
import { getDatabaseInfo, useConnectionInfo } from '../utility/metadataLoaders'; import { getDatabaseInfo, useConnectionInfo } from '../utility/metadataLoaders';
import socket from '../utility/socket';
import SocketMessageView from '../query/SocketMessageView.svelte'; import SocketMessageView from '../query/SocketMessageView.svelte';
import useEffect from '../utility/useEffect'; import useEffect from '../utility/useEffect';
import ResultTabs from '../query/ResultTabs.svelte'; import ResultTabs from '../query/ResultTabs.svelte';
@@ -69,6 +67,7 @@
import AceEditor from '../query/AceEditor.svelte'; import AceEditor from '../query/AceEditor.svelte';
import StatusBarTabItem from '../widgets/StatusBarTabItem.svelte'; import StatusBarTabItem from '../widgets/StatusBarTabItem.svelte';
import { showSnackbarError } from '../utility/snackbar'; import { showSnackbarError } from '../utility/snackbar';
import { apiCall, apiOff, apiOn } from '../utility/api';
export let tabid; export let tabid;
export let conid; export let conid;
@@ -95,9 +94,9 @@
}); });
function onSession(sid) { function onSession(sid) {
if (sid) { if (sid) {
socket.on(`session-done-${sid}`, handleSessionDone); apiOn(`session-done-${sid}`, handleSessionDone);
return () => { return () => {
socket.off(`session-done-${sid}`, handleSessionDone); apiOff(`session-done-${sid}`, handleSessionDone);
}; };
} }
return () => {}; return () => {};
@@ -150,20 +149,20 @@
let sesid = sessionId; let sesid = sessionId;
if (!sesid) { if (!sesid) {
const resp = await axiosInstance.post('sessions/create', { const resp = await apiCall('sessions/create', {
conid, conid,
database, database,
}); });
sesid = resp.data.sesid; sesid = resp.sesid;
sessionId = sesid; sessionId = sesid;
} }
busy = true; busy = true;
timerLabel.start(); timerLabel.start();
await axiosInstance.post('sessions/execute-query', { await apiCall('sessions/execute-query', {
sesid, sesid,
sql, sql,
}); });
await axiosInstance.post('query-history/write', { await apiCall('query-history/write', {
data: { data: {
sql, sql,
conid, conid,
@@ -184,7 +183,7 @@
} }
export async function kill() { export async function kill() {
await axiosInstance.post('sessions/kill', { await apiCall('sessions/kill', {
sesid: sessionId, sesid: sessionId,
}); });
sessionId = null; sessionId = null;

View File

@@ -48,12 +48,11 @@
import AceEditor from '../query/AceEditor.svelte'; import AceEditor from '../query/AceEditor.svelte';
import RunnerOutputPane from '../query/RunnerOutputPane.svelte'; import RunnerOutputPane from '../query/RunnerOutputPane.svelte';
import useEditorData from '../query/useEditorData'; import useEditorData from '../query/useEditorData';
import axiosInstance from '../utility/axiosInstance'; import { apiCall, apiOff, apiOn } from '../utility/api';
import { copyTextToClipboard } from '../utility/clipboard'; import { copyTextToClipboard } from '../utility/clipboard';
import { changeTab } from '../utility/common'; import { changeTab } from '../utility/common';
import createActivator, { getActiveComponent } from '../utility/createActivator'; import createActivator, { getActiveComponent } from '../utility/createActivator';
import { showSnackbarError } from '../utility/snackbar'; import { showSnackbarError } from '../utility/snackbar';
import socket from '../utility/socket';
import useEffect from '../utility/useEffect'; import useEffect from '../utility/useEffect';
import useTimerLabel from '../utility/useTimerLabel'; import useTimerLabel from '../utility/useTimerLabel';
@@ -101,9 +100,9 @@
function registerRunnerDone(rid) { function registerRunnerDone(rid) {
if (rid) { if (rid) {
socket.on(`runner-done-${rid}`, handleRunnerDone); apiOn(`runner-done-${rid}`, handleRunnerDone);
return () => { return () => {
socket.off(`runner-done-${rid}`, handleRunnerDone); apiOff(`runner-done-${rid}`, handleRunnerDone);
}; };
} else { } else {
return () => {}; return () => {};
@@ -140,8 +139,8 @@
} }
export async function copyNodeScript() { export async function copyNodeScript() {
const resp = await axiosInstance.post('runners/get-node-script', { script: getActiveScript() }); const resp = await apiCall('runners/get-node-script', { script: getActiveScript() });
copyTextToClipboard(resp.data); copyTextToClipboard(resp);
} }
// export function openWizardEnabled() { // export function openWizardEnabled() {
@@ -172,10 +171,10 @@
executeNumber += 1; executeNumber += 1;
let runid = runnerId; let runid = runnerId;
const resp = await axiosInstance.post('runners/start', { const resp = await apiCall('runners/start', {
script: getActiveScript(), script: getActiveScript(),
}); });
runid = resp.data.runid; runid = resp.runid;
runnerId = runid; runnerId = runid;
busy = true; busy = true;
timerLabel.start(); timerLabel.start();
@@ -186,7 +185,7 @@
} }
export function kill() { export function kill() {
axiosInstance.post('runners/cancel', { apiCall('runners/cancel', {
runid: runnerId, runid: runnerId,
}); });
timerLabel.stop(); timerLabel.stop();

View File

@@ -38,7 +38,6 @@
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
import createUndoReducer from '../utility/createUndoReducer'; import createUndoReducer from '../utility/createUndoReducer';
import invalidateCommands from '../commands/invalidateCommands'; import invalidateCommands from '../commands/invalidateCommands';
import axiosInstance from '../utility/axiosInstance';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte'; import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
import { useConnectionInfo, useDatabaseInfo } from '../utility/metadataLoaders'; import { useConnectionInfo, useDatabaseInfo } from '../utility/metadataLoaders';
@@ -53,6 +52,7 @@
import openNewTab from '../utility/openNewTab'; import openNewTab from '../utility/openNewTab';
import { getBoolSettingsValue } from '../settings/settingsTools'; import { getBoolSettingsValue } from '../settings/settingsTools';
import { setContext } from 'svelte'; import { setContext } from 'svelte';
import { apiCall } from '../utility/api';
export let tabid; export let tabid;
export let conid; export let conid;
@@ -70,16 +70,8 @@
const [changeSetStore, dispatchChangeSet] = createUndoReducer(createChangeSet()); const [changeSetStore, dispatchChangeSet] = createUndoReducer(createChangeSet());
async function handleConfirmSql(sql) { async function handleConfirmSql(sql) {
const resp = await axiosInstance.request({ const resp = await apiCall('database-connections/run-script', { conid, database, sql });
url: 'database-connections/run-script', const { errorMessage } = resp || {};
method: 'post',
params: {
conid,
database,
},
data: { sql },
});
const { errorMessage } = resp.data || {};
if (errorMessage) { if (errorMessage) {
showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage }); showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage });
} else { } else {

View File

@@ -51,13 +51,13 @@
import { useConnectionInfo, useDatabaseInfo, useDbCore } from '../utility/metadataLoaders'; import { useConnectionInfo, useDatabaseInfo, useDbCore } from '../utility/metadataLoaders';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import ConfirmSqlModal from '../modals/ConfirmSqlModal.svelte'; import ConfirmSqlModal from '../modals/ConfirmSqlModal.svelte';
import axiosInstance from '../utility/axiosInstance';
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte'; import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
import { showSnackbarSuccess } from '../utility/snackbar'; import { showSnackbarSuccess } from '../utility/snackbar';
import InputTextModal from '../modals/InputTextModal.svelte'; import InputTextModal from '../modals/InputTextModal.svelte';
import { changeTab } from '../utility/common'; import { changeTab } from '../utility/common';
import StatusBarTabItem from '../widgets/StatusBarTabItem.svelte'; import StatusBarTabItem from '../widgets/StatusBarTabItem.svelte';
import openNewTab from '../utility/openNewTab'; import openNewTab from '../utility/openNewTab';
import { apiCall } from '../utility/api';
export let tabid; export let tabid;
export let conid; export let conid;
@@ -130,16 +130,8 @@
} }
async function handleConfirmSql(sql, createTableName) { async function handleConfirmSql(sql, createTableName) {
const resp = await axiosInstance.request({ const resp = await apiCall('database-connections/run-script', { conid, database, sql });
url: 'database-connections/run-script', const { errorMessage } = resp || {};
method: 'post',
params: {
conid,
database,
},
data: { sql },
});
const { errorMessage } = resp.data || {};
if (errorMessage) { if (errorMessage) {
showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage }); showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage });
} else { } else {
@@ -154,14 +146,14 @@
})); }));
} }
await axiosInstance.post('database-connections/sync-model', { conid, database }); await apiCall('database-connections/sync-model', { conid, database });
showSnackbarSuccess('Saved to database'); showSnackbarSuccess('Saved to database');
clearEditorData(); clearEditorData();
} }
} }
export async function reset() { export async function reset() {
await axiosInstance.post('database-connections/sync-model', { conid, database }); await apiCall('database-connections/sync-model', { conid, database });
clearEditorData(); clearEditorData();
} }

View File

@@ -1,7 +1,6 @@
<script lang="ts"> <script lang="ts">
import localforage from 'localforage'; import localforage from 'localforage';
import _ from 'lodash'; import _ from 'lodash';
import { openedTabs } from '../stores';
import { getLocalStorage, setLocalStorage } from './storageCache'; import { getLocalStorage, setLocalStorage } from './storageCache';
let counter = 0; let counter = 0;

View File

@@ -5,7 +5,7 @@ import { showModal } from '../modals/modalTools';
import { getExtensions } from '../stores'; import { getExtensions } from '../stores';
import { getConnectionInfo, getDatabaseInfo } from './metadataLoaders'; import { getConnectionInfo, getDatabaseInfo } from './metadataLoaders';
import ConfirmSqlModal from '../modals/ConfirmSqlModal.svelte'; import ConfirmSqlModal from '../modals/ConfirmSqlModal.svelte';
import axiosInstance from './axiosInstance'; import { apiCall } from './api';
export async function alterDatabaseDialog(conid, database, updateFunc) { export async function alterDatabaseDialog(conid, database, updateFunc) {
const conn = await getConnectionInfo({ conid }); const conn = await getConnectionInfo({ conid });
@@ -21,16 +21,8 @@ export async function alterDatabaseDialog(conid, database, updateFunc) {
sql, sql,
recreates, recreates,
onConfirm: async () => { onConfirm: async () => {
const resp = await axiosInstance.request({ const resp = await apiCall('database-connections/run-script', { conid, database, sql });
url: 'database-connections/run-script', await apiCall('database-connections/sync-model', { conid, database });
method: 'post',
params: {
conid,
database,
},
data: { sql },
});
await axiosInstance.post('database-connections/sync-model', { conid, database });
}, },
engine: driver.engine, engine: driver.engine,
}); });

View File

@@ -0,0 +1,89 @@
import resolveApi, { resolveApiHeaders } from './resolveApi';
import { writable } from 'svelte/store';
import { cacheClean } from './cache';
import getElectron from './getElectron';
// import socket from './socket';
let eventSource;
let cacheCleanerRegistered;
function wantEventSource() {
if (!eventSource) {
eventSource = new EventSource(`${resolveApi()}/stream`);
// eventSource.addEventListener('clean-cache', e => cacheClean(JSON.parse(e.data)));
}
}
export async function apiCall(route: string, args: {} = undefined) {
const electron = getElectron();
if (electron) {
// console.log('CALLING API', route.replace('/', '-'), JSON.stringify(args == null ? null : args));
const resp = await electron.invoke(route.replace('/', '-'), args);
return resp;
} else {
const resp = await fetch(`${resolveApi()}/${route}`, {
method: 'POST',
cache: 'no-cache',
headers: {
'Content-Type': 'application/json',
...resolveApiHeaders(),
},
body: JSON.stringify(args),
});
return resp.json();
}
}
const apiHandlers = new WeakMap();
export function apiOn(event: string, handler: Function) {
const electron = getElectron();
if (electron) {
if (!apiHandlers.has(handler)) {
const handlerProxy = (e, data) => {
handler(data);
};
apiHandlers.set(handler, handlerProxy);
}
electron.addEventListener(event, apiHandlers.get(handler));
} else {
wantEventSource();
if (!apiHandlers.has(handler)) {
const handlerProxy = e => {
// console.log('RECEIVED', e.type, JSON.parse(e.data));
handler(JSON.parse(e.data));
};
apiHandlers.set(handler, handlerProxy);
}
eventSource.addEventListener(event, apiHandlers.get(handler));
}
if (!cacheCleanerRegistered) {
cacheCleanerRegistered = true;
apiOn('clean-cache', reloadTrigger => cacheClean(reloadTrigger));
}
}
export function apiOff(event: string, handler: Function) {
const electron = getElectron();
if (apiHandlers.has(handler)) {
if (electron) {
electron.removeEventListener(event, apiHandlers.get(handler));
} else {
wantEventSource();
eventSource.removeEventListener(event, apiHandlers.get(handler));
}
}
}
export function useApiCall(route, args, defaultValue) {
const result = writable(defaultValue);
apiCall(route, args).then(resp => {
result.set(resp);
});
return result;
}

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