mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-05-01 15:33:57 +00:00
Merge branch 'develop'
This commit is contained in:
4
.github/workflows/build-app-beta.yaml
vendored
4
.github/workflows/build-app-beta.yaml
vendored
@@ -22,10 +22,10 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js 12.x
|
||||
- name: Use Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12.x
|
||||
node-version: 14.x
|
||||
- name: yarn install
|
||||
run: |
|
||||
yarn install
|
||||
|
||||
4
.github/workflows/build-app.yaml
vendored
4
.github/workflows/build-app.yaml
vendored
@@ -26,10 +26,10 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js 12.x
|
||||
- name: Use Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12.x
|
||||
node-version: 14.x
|
||||
- name: yarn install
|
||||
run: |
|
||||
yarn install
|
||||
|
||||
4
.github/workflows/build-docker-beta.yaml
vendored
4
.github/workflows/build-docker-beta.yaml
vendored
@@ -24,10 +24,10 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js 12.x
|
||||
- name: Use Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12.x
|
||||
node-version: 14.x
|
||||
- name: yarn install
|
||||
run: |
|
||||
yarn install
|
||||
|
||||
4
.github/workflows/build-docker.yaml
vendored
4
.github/workflows/build-docker.yaml
vendored
@@ -30,10 +30,10 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js 12.x
|
||||
- name: Use Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12.x
|
||||
node-version: 14.x
|
||||
- name: yarn install
|
||||
run: |
|
||||
yarn install
|
||||
|
||||
4
.github/workflows/build-npm.yaml
vendored
4
.github/workflows/build-npm.yaml
vendored
@@ -30,10 +30,10 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js 12.x
|
||||
- name: Use Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12.x
|
||||
node-version: 14.x
|
||||
|
||||
- name: Configure NPM token
|
||||
env:
|
||||
|
||||
2
.github/workflows/run-tests.yaml
vendored
2
.github/workflows/run-tests.yaml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
jobs:
|
||||
test-runner:
|
||||
runs-on: ubuntu-latest
|
||||
container: node:12.22
|
||||
container: node:14.18
|
||||
|
||||
steps:
|
||||
- name: Context
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
"author": "Jan Prochazka <jenasoft.database@gmail.com>",
|
||||
"description": "Opensource database administration tool",
|
||||
"dependencies": {
|
||||
"better-sqlite3-with-prebuilds": "^7.1.8",
|
||||
"electron-log": "^4.3.1",
|
||||
"electron-store": "^5.1.1",
|
||||
"electron-updater": "^4.3.5",
|
||||
"electron-log": "^4.4.1",
|
||||
"electron-updater": "^4.6.1",
|
||||
"patch-package": "^6.4.7"
|
||||
},
|
||||
"repository": {
|
||||
@@ -90,23 +88,25 @@
|
||||
},
|
||||
"homepage": "./",
|
||||
"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 .",
|
||||
"dist": "electron-builder",
|
||||
"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: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"
|
||||
},
|
||||
"main": "src/electron.js",
|
||||
"devDependencies": {
|
||||
"copyfiles": "^2.2.0",
|
||||
"cross-env": "^6.0.3",
|
||||
"electron": "11.2.3",
|
||||
"electron-builder": "22.10.5"
|
||||
"electron": "13.6.3",
|
||||
"electron-builder": "22.14.5"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"msnodesqlv8": "^2.4.0"
|
||||
"better-sqlite3": "7.4.5",
|
||||
"msnodesqlv8": "^2.4.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
const electron = require('electron');
|
||||
const os = require('os');
|
||||
const fs = require('fs');
|
||||
const { Menu, ipcMain } = require('electron');
|
||||
const { fork } = require('child_process');
|
||||
const { autoUpdater } = require('electron-updater');
|
||||
const Store = require('electron-store');
|
||||
const log = require('electron-log');
|
||||
|
||||
// Module to control application life.
|
||||
@@ -14,7 +13,17 @@ const BrowserWindow = electron.BrowserWindow;
|
||||
const path = require('path');
|
||||
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
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
@@ -36,7 +45,7 @@ function commandItem(id) {
|
||||
accelerator: command ? command.keyText : undefined,
|
||||
enabled: command ? command.enabled : false,
|
||||
click() {
|
||||
mainWindow.webContents.executeJavaScript(`dbgate_runCommand('${id}')`);
|
||||
mainWindow.webContents.send('run-command', id);
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -49,7 +58,7 @@ function buildMenu() {
|
||||
commandItem('new.connection'),
|
||||
commandItem('new.sqliteDatabase'),
|
||||
commandItem('new.modelCompare'),
|
||||
commandItem('new.freetable'),
|
||||
commandItem('new.freetable'),
|
||||
{ type: 'separator' },
|
||||
commandItem('file.open'),
|
||||
commandItem('file.openArchive'),
|
||||
@@ -99,25 +108,25 @@ function buildMenu() {
|
||||
{
|
||||
label: 'dbgate.org',
|
||||
click() {
|
||||
require('electron').shell.openExternal('https://dbgate.org');
|
||||
electron.shell.openExternal('https://dbgate.org');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'DbGate on GitHub',
|
||||
click() {
|
||||
require('electron').shell.openExternal('https://github.com/dbgate/dbgate');
|
||||
electron.shell.openExternal('https://github.com/dbgate/dbgate');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'DbGate on docker hub',
|
||||
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',
|
||||
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'),
|
||||
@@ -146,10 +155,27 @@ ipcMain.on('update-commands', async (event, arg) => {
|
||||
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() {
|
||||
const bounds = store.get('winBounds');
|
||||
|
||||
const bounds = initialConfig['winBounds'];
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
@@ -158,10 +184,11 @@ function createWindow() {
|
||||
icon: os.platform() == 'win32' ? 'icon.ico' : path.resolve(__dirname, '../icon.png'),
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
enableRemoteModule: true,
|
||||
contextIsolation: false,
|
||||
},
|
||||
});
|
||||
if (store.get('winIsMaximized')) {
|
||||
|
||||
if (initialConfig['winIsMaximized']) {
|
||||
mainWindow.maximize();
|
||||
}
|
||||
|
||||
@@ -176,12 +203,15 @@ function createWindow() {
|
||||
protocol: 'file:',
|
||||
slashes: true,
|
||||
});
|
||||
mainWindow.webContents.on('did-finish-load', function () {
|
||||
// hideSplash();
|
||||
});
|
||||
mainWindow.on('close', () => {
|
||||
store.set('winBounds', mainWindow.getBounds());
|
||||
store.set('winIsMaximized', mainWindow.isMaximized());
|
||||
fs.writeFileSync(
|
||||
configRootPath,
|
||||
JSON.stringify({
|
||||
winBounds: mainWindow.getBounds(),
|
||||
winIsMaximized: mainWindow.isMaximized(),
|
||||
}),
|
||||
'utf-8'
|
||||
);
|
||||
});
|
||||
mainWindow.loadURL(startUrl);
|
||||
if (os.platform() == 'linux') {
|
||||
@@ -189,31 +219,27 @@ function createWindow() {
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.ELECTRON_START_URL) {
|
||||
loadMainWindow();
|
||||
} else {
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
const apiPackage = path.join(
|
||||
__dirname,
|
||||
process.env.DEVMODE ? '../../packages/api/src/index' : '../packages/api/dist/bundle.js'
|
||||
);
|
||||
|
||||
// and load the index.html of the app.
|
||||
// mainWindow.loadURL('http://localhost:3000');
|
||||
global.API_PACKAGE = apiPackage;
|
||||
global.NATIVE_MODULES = path.join(__dirname, 'nativeModules');
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools();
|
||||
// console.log('global.API_PACKAGE', global.API_PACKAGE);
|
||||
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.
|
||||
mainWindow.on('closed', function () {
|
||||
@@ -225,7 +251,9 @@ function createWindow() {
|
||||
}
|
||||
|
||||
function onAppReady() {
|
||||
autoUpdater.checkForUpdatesAndNotify();
|
||||
if (!process.env.DEVMODE) {
|
||||
autoUpdater.checkForUpdatesAndNotify();
|
||||
}
|
||||
createWindow();
|
||||
}
|
||||
|
||||
|
||||
1643
app/yarn.lock
1643
app/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
FROM node:12-alpine
|
||||
FROM node:14-alpine
|
||||
|
||||
WORKDIR /home/dbgate-docker
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ let fillContent = '';
|
||||
if (process.platform == 'win32') {
|
||||
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) => `
|
||||
// this file is generated automatically by script fillNativeModules.js, do not edit it manually
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"version": "4.4.5-beta.2",
|
||||
"version": "4.4.5-beta.24",
|
||||
"name": "dbgate-all",
|
||||
"workspaces": [
|
||||
"packages/*",
|
||||
@@ -9,6 +9,7 @@
|
||||
],
|
||||
"scripts": {
|
||||
"start:api": "yarn workspace dbgate-api start",
|
||||
"start:app": "cd app && yarn start",
|
||||
"start:api:portal": "yarn workspace dbgate-api start:portal",
|
||||
"start:api:covid": "yarn workspace dbgate-api start:covid",
|
||||
"start:web": "yarn workspace dbgate-web dev",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
DEVMODE=1
|
||||
|
||||
CONNECTIONS=mysql,postgres
|
||||
CONNECTIONS=mysql,postgres,mongo,mongo2
|
||||
|
||||
LABEL_mysql=MySql localhost
|
||||
SERVER_mysql=localhost
|
||||
@@ -15,3 +15,13 @@ USER_postgres=postgres
|
||||
PASSWORD_postgres=test
|
||||
PORT_postgres=5433
|
||||
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
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
"dependencies": {
|
||||
"async-lock": "^1.2.4",
|
||||
"axios": "^0.21.1",
|
||||
"better-sqlite3-with-prebuilds": "^7.1.8",
|
||||
"body-parser": "^1.19.0",
|
||||
"bufferutil": "^4.0.1",
|
||||
"byline": "^5.0.0",
|
||||
@@ -39,6 +38,7 @@
|
||||
"fs-reverse": "^0.0.3",
|
||||
"get-port": "^5.1.1",
|
||||
"http": "^0.0.0",
|
||||
"is-electron": "^2.2.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"json-stable-stringify": "^1.0.1",
|
||||
"line-reader": "^0.4.0",
|
||||
@@ -49,7 +49,6 @@
|
||||
"node-ssh-forward": "^0.7.2",
|
||||
"portfinder": "^1.0.28",
|
||||
"simple-encryptor": "^4.0.0",
|
||||
"socket.io": "^2.3.0",
|
||||
"tar": "^6.0.5",
|
||||
"uuid": "^3.4.0"
|
||||
},
|
||||
@@ -74,6 +73,7 @@
|
||||
"webpack-cli": "^3.3.11"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"msnodesqlv8": "^2.4.0"
|
||||
"better-sqlite3": "7.4.5",
|
||||
"msnodesqlv8": "^2.4.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ const { saveFreeTableData } = require('../utility/freeTableStorage');
|
||||
const loadFilesRecursive = require('../utility/loadFilesRecursive');
|
||||
|
||||
module.exports = {
|
||||
folders_meta: 'get',
|
||||
folders_meta: true,
|
||||
async folders() {
|
||||
const folders = await fs.readdir(archivedir());
|
||||
return [
|
||||
@@ -27,14 +27,14 @@ module.exports = {
|
||||
];
|
||||
},
|
||||
|
||||
createFolder_meta: 'post',
|
||||
createFolder_meta: true,
|
||||
async createFolder({ folder }) {
|
||||
await fs.mkdir(path.join(archivedir(), folder));
|
||||
socket.emitChanged('archive-folders-changed');
|
||||
return true;
|
||||
},
|
||||
|
||||
createLink_meta: 'post',
|
||||
createLink_meta: true,
|
||||
async createLink({ linkedFolder }) {
|
||||
const folder = await this.getNewArchiveFolder({ database: path.parse(linkedFolder).name + '.link' });
|
||||
fs.writeFile(path.join(archivedir(), folder), linkedFolder);
|
||||
@@ -43,7 +43,7 @@ module.exports = {
|
||||
return folder;
|
||||
},
|
||||
|
||||
files_meta: 'get',
|
||||
files_meta: true,
|
||||
async files({ folder }) {
|
||||
const dir = resolveArchiveFolder(folder);
|
||||
if (!(await fs.exists(dir))) return [];
|
||||
@@ -70,23 +70,23 @@ module.exports = {
|
||||
];
|
||||
},
|
||||
|
||||
refreshFiles_meta: 'post',
|
||||
refreshFiles_meta: true,
|
||||
async refreshFiles({ folder }) {
|
||||
socket.emitChanged(`archive-files-changed-${folder}`);
|
||||
},
|
||||
|
||||
refreshFolders_meta: 'post',
|
||||
refreshFolders_meta: true,
|
||||
async refreshFolders() {
|
||||
socket.emitChanged(`archive-folders-changed`);
|
||||
},
|
||||
|
||||
deleteFile_meta: 'post',
|
||||
deleteFile_meta: true,
|
||||
async deleteFile({ folder, file, fileType }) {
|
||||
await fs.unlink(path.join(resolveArchiveFolder(folder), `${file}.${fileType}`));
|
||||
socket.emitChanged(`archive-files-changed-${folder}`);
|
||||
},
|
||||
|
||||
renameFile_meta: 'post',
|
||||
renameFile_meta: true,
|
||||
async renameFile({ folder, file, newFile, fileType }) {
|
||||
await fs.rename(
|
||||
path.join(resolveArchiveFolder(folder), `${file}.${fileType}`),
|
||||
@@ -95,14 +95,14 @@ module.exports = {
|
||||
socket.emitChanged(`archive-files-changed-${folder}`);
|
||||
},
|
||||
|
||||
renameFolder_meta: 'post',
|
||||
renameFolder_meta: true,
|
||||
async renameFolder({ folder, newFolder }) {
|
||||
const uniqueName = await this.getNewArchiveFolder({ database: newFolder });
|
||||
await fs.rename(path.join(archivedir(), folder), path.join(archivedir(), uniqueName));
|
||||
socket.emitChanged(`archive-folders-changed`);
|
||||
},
|
||||
|
||||
deleteFolder_meta: 'post',
|
||||
deleteFolder_meta: true,
|
||||
async deleteFolder({ folder }) {
|
||||
if (!folder) throw new Error('Missing folder parameter');
|
||||
if (folder.endsWith('.link')) {
|
||||
@@ -113,14 +113,14 @@ module.exports = {
|
||||
socket.emitChanged(`archive-folders-changed`);
|
||||
},
|
||||
|
||||
saveFreeTable_meta: 'post',
|
||||
saveFreeTable_meta: true,
|
||||
async saveFreeTable({ folder, file, data }) {
|
||||
await saveFreeTableData(path.join(resolveArchiveFolder(folder), `${file}.jsonl`), data);
|
||||
socket.emitChanged(`archive-files-changed-${folder}`);
|
||||
return true;
|
||||
},
|
||||
|
||||
loadFreeTable_meta: 'post',
|
||||
loadFreeTable_meta: true,
|
||||
async loadFreeTable({ folder, file }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fileStream = fs.createReadStream(path.join(resolveArchiveFolder(folder), `${file}.jsonl`));
|
||||
|
||||
@@ -21,7 +21,7 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
get_meta: 'get',
|
||||
get_meta: true,
|
||||
async get() {
|
||||
const permissions = process.env.PERMISSIONS ? process.env.PERMISSIONS.split(',') : null;
|
||||
|
||||
@@ -33,17 +33,17 @@ module.exports = {
|
||||
};
|
||||
},
|
||||
|
||||
platformInfo_meta: 'get',
|
||||
platformInfo_meta: true,
|
||||
async platformInfo() {
|
||||
return platformInfo;
|
||||
},
|
||||
|
||||
getSettings_meta: 'get',
|
||||
getSettings_meta: true,
|
||||
async getSettings() {
|
||||
return this.settingsValue;
|
||||
},
|
||||
|
||||
updateSettings_meta: 'post',
|
||||
updateSettings_meta: true,
|
||||
async updateSettings(values) {
|
||||
if (!hasPermission(`settings/change`)) return false;
|
||||
try {
|
||||
@@ -60,7 +60,7 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
changelog_meta: 'get',
|
||||
changelog_meta: true,
|
||||
async changelog() {
|
||||
const resp = await axios.default.get('https://raw.githubusercontent.com/dbgate/dbgate/master/CHANGELOG.md');
|
||||
return resp.data;
|
||||
|
||||
@@ -8,6 +8,9 @@ const { datadir, filesdir } = require('../utility/directories');
|
||||
const socket = require('../utility/socket');
|
||||
const { encryptConnection } = require('../utility/crypting');
|
||||
const { handleProcessCommunication } = require('../utility/processComm');
|
||||
const { pickSafeConnectionInfo } = require('../utility/crypting');
|
||||
|
||||
const processArgs = require('../utility/processArgs');
|
||||
|
||||
function getNamedArgs() {
|
||||
const res = {};
|
||||
@@ -37,7 +40,7 @@ function getDatabaseFileLabel(databaseFile) {
|
||||
|
||||
function getPortalCollections() {
|
||||
if (process.env.CONNECTIONS) {
|
||||
return _.compact(process.env.CONNECTIONS.split(',')).map(id => ({
|
||||
const connections = _.compact(process.env.CONNECTIONS.split(',')).map(id => ({
|
||||
_id: id,
|
||||
engine: process.env[`ENGINE_${id}`],
|
||||
server: process.env[`SERVER_${id}`],
|
||||
@@ -45,11 +48,22 @@ function getPortalCollections() {
|
||||
password: process.env[`PASSWORD_${id}`],
|
||||
port: process.env[`PORT_${id}`],
|
||||
databaseUrl: process.env[`URL_${id}`],
|
||||
useDatabaseUrl: !!process.env[`URL_${id}`],
|
||||
databaseFile: process.env[`FILE_${id}`],
|
||||
defaultDatabase: process.env[`DATABASE_${id}`],
|
||||
singleDatabase: !!process.env[`DATABASE_${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();
|
||||
@@ -126,29 +140,34 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
list_meta: 'get',
|
||||
list_meta: true,
|
||||
async list() {
|
||||
return portalConnections || this.datastore.find();
|
||||
},
|
||||
|
||||
test_meta: {
|
||||
method: 'post',
|
||||
raw: true,
|
||||
},
|
||||
test(req, res) {
|
||||
const subprocess = fork(process.argv[1], ['--start-process', 'connectProcess', ...process.argv.slice(3)]);
|
||||
subprocess.on('message', resp => {
|
||||
if (handleProcessCommunication(resp, subprocess)) return;
|
||||
// @ts-ignore
|
||||
const { msgtype } = resp;
|
||||
if (msgtype == 'connected' || msgtype == 'error') {
|
||||
res.json(resp);
|
||||
}
|
||||
test_meta: true,
|
||||
test(connection) {
|
||||
const subprocess = fork(global['API_PACKAGE'] || process.argv[1], [
|
||||
'--is-forked-api',
|
||||
'--start-process',
|
||||
'connectProcess',
|
||||
...processArgs.getPassArgs(),
|
||||
// ...process.argv.slice(3),
|
||||
]);
|
||||
subprocess.send(connection);
|
||||
return new Promise(resolve => {
|
||||
subprocess.on('message', resp => {
|
||||
if (handleProcessCommunication(resp, subprocess)) return;
|
||||
// @ts-ignore
|
||||
const { msgtype } = resp;
|
||||
if (msgtype == 'connected' || msgtype == 'error') {
|
||||
resolve(resp);
|
||||
}
|
||||
});
|
||||
});
|
||||
subprocess.send(req.body);
|
||||
},
|
||||
|
||||
save_meta: 'post',
|
||||
save_meta: true,
|
||||
async save(connection) {
|
||||
if (portalConnections) return;
|
||||
let res;
|
||||
@@ -162,7 +181,7 @@ module.exports = {
|
||||
return res;
|
||||
},
|
||||
|
||||
update_meta: 'post',
|
||||
update_meta: true,
|
||||
async update({ _id, values }) {
|
||||
if (portalConnections) return;
|
||||
const res = await this.datastore.update({ _id }, { $set: values });
|
||||
@@ -170,7 +189,7 @@ module.exports = {
|
||||
return res;
|
||||
},
|
||||
|
||||
updateDatabase_meta: 'post',
|
||||
updateDatabase_meta: true,
|
||||
async updateDatabase({ conid, database, values }) {
|
||||
if (portalConnections) return;
|
||||
const conn = await this.datastore.find({ _id: conid });
|
||||
@@ -185,7 +204,7 @@ module.exports = {
|
||||
return res;
|
||||
},
|
||||
|
||||
delete_meta: 'post',
|
||||
delete_meta: true,
|
||||
async delete(connection) {
|
||||
if (portalConnections) return;
|
||||
const res = await this.datastore.remove(_.pick(connection, '_id'));
|
||||
@@ -193,14 +212,14 @@ module.exports = {
|
||||
return res;
|
||||
},
|
||||
|
||||
get_meta: 'get',
|
||||
get_meta: true,
|
||||
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 });
|
||||
return res[0];
|
||||
return res[0] || null;
|
||||
},
|
||||
|
||||
newSqliteDatabase_meta: 'post',
|
||||
newSqliteDatabase_meta: true,
|
||||
async newSqliteDatabase({ file }) {
|
||||
const sqliteDir = path.join(filesdir(), 'sqlite');
|
||||
if (!(await fs.exists(sqliteDir))) {
|
||||
|
||||
@@ -25,6 +25,7 @@ const requireEngineDriver = require('../utility/requireEngineDriver');
|
||||
const generateDeploySql = require('../shell/generateDeploySql');
|
||||
const { createTwoFilesPatch } = require('diff');
|
||||
const diff2htmlPage = require('../utility/diff2htmlPage');
|
||||
const processArgs = require('../utility/processArgs');
|
||||
|
||||
module.exports = {
|
||||
/** @type {import('dbgate-types').OpenedDatabaseConnection[]} */
|
||||
@@ -74,10 +75,12 @@ module.exports = {
|
||||
const existing = this.opened.find(x => x.conid == conid && x.database == database);
|
||||
if (existing) return existing;
|
||||
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',
|
||||
'databaseConnectionProcess',
|
||||
...process.argv.slice(3),
|
||||
...processArgs.getPassArgs(),
|
||||
// ...process.argv.slice(3),
|
||||
]);
|
||||
const lastClosed = this.closed[`${conid}/${database}`];
|
||||
const newOpened = {
|
||||
@@ -121,7 +124,7 @@ module.exports = {
|
||||
return promise;
|
||||
},
|
||||
|
||||
queryData_meta: 'post',
|
||||
queryData_meta: true,
|
||||
async queryData({ conid, database, sql }) {
|
||||
console.log(`Processing query, conid=${conid}, database=${database}, sql=${sql}`);
|
||||
const opened = await this.ensureOpened(conid, database);
|
||||
@@ -132,7 +135,7 @@ module.exports = {
|
||||
return res;
|
||||
},
|
||||
|
||||
runScript_meta: 'post',
|
||||
runScript_meta: true,
|
||||
async runScript({ conid, database, sql }) {
|
||||
console.log(`Processing script, conid=${conid}, database=${database}, sql=${sql}`);
|
||||
const opened = await this.ensureOpened(conid, database);
|
||||
@@ -140,21 +143,21 @@ module.exports = {
|
||||
return res;
|
||||
},
|
||||
|
||||
collectionData_meta: 'post',
|
||||
collectionData_meta: true,
|
||||
async collectionData({ conid, database, options }) {
|
||||
const opened = await this.ensureOpened(conid, database);
|
||||
const res = await this.sendRequest(opened, { msgtype: 'collectionData', options });
|
||||
return res.result;
|
||||
},
|
||||
|
||||
updateCollection_meta: 'post',
|
||||
updateCollection_meta: true,
|
||||
async updateCollection({ conid, database, changeSet }) {
|
||||
const opened = await this.ensureOpened(conid, database);
|
||||
const res = await this.sendRequest(opened, { msgtype: 'updateCollection', changeSet });
|
||||
return res.result;
|
||||
},
|
||||
|
||||
status_meta: 'get',
|
||||
status_meta: true,
|
||||
async status({ conid, database }) {
|
||||
const existing = this.opened.find(x => x.conid == conid && x.database == database);
|
||||
if (existing) {
|
||||
@@ -176,7 +179,7 @@ module.exports = {
|
||||
};
|
||||
},
|
||||
|
||||
ping_meta: 'post',
|
||||
ping_meta: true,
|
||||
async ping({ conid, 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 }) {
|
||||
if (!keepOpen) this.close(conid, database);
|
||||
|
||||
@@ -200,7 +203,7 @@ module.exports = {
|
||||
return { status: 'ok' };
|
||||
},
|
||||
|
||||
syncModel_meta: 'post',
|
||||
syncModel_meta: true,
|
||||
async syncModel({ conid, database }) {
|
||||
const conn = await this.ensureOpened(conid, database);
|
||||
conn.subprocess.send({ msgtype: 'syncModel' });
|
||||
@@ -224,13 +227,13 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
disconnect_meta: 'post',
|
||||
disconnect_meta: true,
|
||||
async disconnect({ conid, database }) {
|
||||
await this.close(conid, database, true);
|
||||
return { status: 'ok' };
|
||||
},
|
||||
|
||||
structure_meta: 'get',
|
||||
structure_meta: true,
|
||||
async structure({ conid, database }) {
|
||||
if (conid == '__model') {
|
||||
const model = await importDbModel(database);
|
||||
@@ -247,13 +250,14 @@ module.exports = {
|
||||
// };
|
||||
},
|
||||
|
||||
serverVersion_meta: 'get',
|
||||
serverVersion_meta: true,
|
||||
async serverVersion({ conid, database }) {
|
||||
if (!conid) return null;
|
||||
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 }) {
|
||||
// wait for structure
|
||||
await this.structure({ conid, database });
|
||||
@@ -263,7 +267,7 @@ module.exports = {
|
||||
return res;
|
||||
},
|
||||
|
||||
exportModel_meta: 'post',
|
||||
exportModel_meta: true,
|
||||
async exportModel({ conid, database }) {
|
||||
const archiveFolder = await archive.getNewArchiveFolder({ database });
|
||||
await fs.mkdir(path.join(archivedir(), archiveFolder));
|
||||
@@ -273,10 +277,13 @@ module.exports = {
|
||||
return { archiveFolder };
|
||||
},
|
||||
|
||||
generateDeploySql_meta: 'post',
|
||||
generateDeploySql_meta: true,
|
||||
async generateDeploySql({ conid, database, archiveFolder }) {
|
||||
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;
|
||||
|
||||
// const connection = await connections.get({ conid });
|
||||
@@ -285,7 +292,7 @@ module.exports = {
|
||||
// analysedStructure: await this.structure({ conid, database }),
|
||||
// modelFolder: resolveArchiveFolder(archiveFolder),
|
||||
// });
|
||||
|
||||
|
||||
// const deployedModel = generateDbPairingId(await importDbModel(path.join(archivedir(), archiveFolder)));
|
||||
// const currentModel = generateDbPairingId(await this.structure({ conid, database }));
|
||||
// const currentModelPaired = matchPairedObjects(deployedModel, currentModel);
|
||||
@@ -300,7 +307,7 @@ module.exports = {
|
||||
// };
|
||||
// return sql;
|
||||
},
|
||||
// runCommand_meta: 'post',
|
||||
// runCommand_meta: true,
|
||||
// async runCommand({ conid, database, sql }) {
|
||||
// console.log(`Running SQL command , conid=${conid}, database=${database}, sql=${sql}`);
|
||||
// const opened = await this.ensureOpened(conid, database);
|
||||
@@ -343,7 +350,7 @@ module.exports = {
|
||||
return res;
|
||||
},
|
||||
|
||||
generateDbDiffReport_meta: 'post',
|
||||
generateDbDiffReport_meta: true,
|
||||
async generateDbDiffReport({ filePath, sourceConid, sourceDatabase, targetConid, targetDatabase }) {
|
||||
const unifiedDiff = await this.getUnifiedDiff({ sourceConid, sourceDatabase, targetConid, targetDatabase });
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ function deserialize(format, text) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
list_meta: 'get',
|
||||
list_meta: true,
|
||||
async list({ folder }) {
|
||||
if (!hasPermission(`files/${folder}/read`)) return [];
|
||||
const dir = path.join(filesdir(), folder);
|
||||
@@ -29,7 +29,7 @@ module.exports = {
|
||||
return files;
|
||||
},
|
||||
|
||||
listAll_meta: 'get',
|
||||
listAll_meta: true,
|
||||
async listAll() {
|
||||
const folders = await fs.readdir(filesdir());
|
||||
const res = [];
|
||||
@@ -42,7 +42,7 @@ module.exports = {
|
||||
return res;
|
||||
},
|
||||
|
||||
delete_meta: 'post',
|
||||
delete_meta: true,
|
||||
async delete({ folder, file }) {
|
||||
if (!hasPermission(`files/${folder}/write`)) return;
|
||||
await fs.unlink(path.join(filesdir(), folder, file));
|
||||
@@ -50,7 +50,7 @@ module.exports = {
|
||||
socket.emitChanged(`all-files-changed`);
|
||||
},
|
||||
|
||||
rename_meta: 'post',
|
||||
rename_meta: true,
|
||||
async rename({ folder, file, newFile }) {
|
||||
if (!hasPermission(`files/${folder}/write`)) return;
|
||||
await fs.rename(path.join(filesdir(), folder, file), path.join(filesdir(), folder, newFile));
|
||||
@@ -58,7 +58,7 @@ module.exports = {
|
||||
socket.emitChanged(`all-files-changed`);
|
||||
},
|
||||
|
||||
copy_meta: 'post',
|
||||
copy_meta: true,
|
||||
async copy({ folder, file, newFile }) {
|
||||
if (!hasPermission(`files/${folder}/write`)) return;
|
||||
await fs.copyFile(path.join(filesdir(), folder, file), path.join(filesdir(), folder, newFile));
|
||||
@@ -66,7 +66,7 @@ module.exports = {
|
||||
socket.emitChanged(`all-files-changed`);
|
||||
},
|
||||
|
||||
load_meta: 'post',
|
||||
load_meta: true,
|
||||
async load({ folder, file, format }) {
|
||||
if (folder.startsWith('archive:')) {
|
||||
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 }) {
|
||||
if (folder.startsWith('archive:')) {
|
||||
const dir = resolveArchiveFolder(folder.substring('archive:'.length));
|
||||
@@ -101,12 +101,12 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
saveAs_meta: 'post',
|
||||
saveAs_meta: true,
|
||||
async saveAs({ filePath, data, format }) {
|
||||
await fs.writeFile(filePath, serialize(format, data));
|
||||
},
|
||||
|
||||
favorites_meta: 'get',
|
||||
favorites_meta: true,
|
||||
async favorites() {
|
||||
if (!hasPermission(`files/favorites/read`)) return [];
|
||||
const dir = path.join(filesdir(), 'favorites');
|
||||
@@ -125,7 +125,7 @@ module.exports = {
|
||||
return res;
|
||||
},
|
||||
|
||||
generateUploadsFile_meta: 'get',
|
||||
generateUploadsFile_meta: true,
|
||||
async generateUploadsFile() {
|
||||
const fileName = `${uuidv1()}.html`;
|
||||
return {
|
||||
@@ -134,7 +134,7 @@ module.exports = {
|
||||
};
|
||||
},
|
||||
|
||||
exportChart_meta: 'post',
|
||||
exportChart_meta: true,
|
||||
async exportChart({ filePath, title, config, image }) {
|
||||
const fileName = path.parse(filePath).base;
|
||||
const imageFile = fileName.replace('.html', '-preview.png');
|
||||
|
||||
@@ -104,7 +104,7 @@ module.exports = {
|
||||
return datastore;
|
||||
},
|
||||
|
||||
getInfo_meta: 'get',
|
||||
getInfo_meta: true,
|
||||
async getInfo({ jslid }) {
|
||||
const file = getJslFileName(jslid);
|
||||
const firstLine = await readFirstLine(file);
|
||||
@@ -112,13 +112,13 @@ module.exports = {
|
||||
return null;
|
||||
},
|
||||
|
||||
getRows_meta: 'post',
|
||||
getRows_meta: true,
|
||||
async getRows({ jslid, offset, limit, filters }) {
|
||||
const datastore = await this.ensureDatastore(jslid);
|
||||
return datastore.getRows(offset, limit, _.isEmpty(filters) ? null : filters);
|
||||
},
|
||||
|
||||
getStats_meta: 'get',
|
||||
getStats_meta: true,
|
||||
getStats({ jslid }) {
|
||||
const file = `${getJslFileName(jslid)}.stats`;
|
||||
if (fs.existsSync(file)) {
|
||||
@@ -146,7 +146,7 @@ module.exports = {
|
||||
// }
|
||||
},
|
||||
|
||||
saveFreeTable_meta: 'post',
|
||||
saveFreeTable_meta: true,
|
||||
async saveFreeTable({ jslid, data }) {
|
||||
saveFreeTableData(getJslFileName(jslid), data);
|
||||
return true;
|
||||
|
||||
@@ -7,14 +7,14 @@ function pickObjectNames(array) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
// tableData_meta: 'get',
|
||||
// tableData_meta: true,
|
||||
// async tableData({ conid, database, schemaName, pureName }) {
|
||||
// const opened = await databaseConnections.ensureOpened(conid, database);
|
||||
// const res = await databaseConnections.sendRequest(opened, { msgtype: 'tableData', schemaName, pureName });
|
||||
// return res;
|
||||
// },
|
||||
|
||||
listObjects_meta: 'get',
|
||||
listObjects_meta: true,
|
||||
async listObjects({ conid, database }) {
|
||||
const opened = await databaseConnections.ensureOpened(conid, database);
|
||||
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 }) {
|
||||
const opened = await databaseConnections.ensureOpened(conid, database);
|
||||
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 }) {
|
||||
const opened = await databaseConnections.ensureOpened(conid, database);
|
||||
const res = opened.structure[objectTypeField].find(x => x.pureName == pureName && x.schemaName == schemaName);
|
||||
|
||||
@@ -12,7 +12,7 @@ const _ = require('lodash');
|
||||
const packagedPluginsContent = require('../packagedPluginsContent');
|
||||
|
||||
module.exports = {
|
||||
script_meta: 'get',
|
||||
script_meta: true,
|
||||
async script({ packageName }) {
|
||||
const packagedContent = packagedPluginsContent();
|
||||
|
||||
@@ -30,7 +30,7 @@ module.exports = {
|
||||
return data;
|
||||
},
|
||||
|
||||
search_meta: 'get',
|
||||
search_meta: true,
|
||||
async search({ filter }) {
|
||||
// DOCS: https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md#get-v1search
|
||||
const resp = await axios.default.get(
|
||||
@@ -40,7 +40,7 @@ module.exports = {
|
||||
return (objects || []).map(x => x.package);
|
||||
},
|
||||
|
||||
info_meta: 'get',
|
||||
info_meta: true,
|
||||
async info({ packageName }) {
|
||||
try {
|
||||
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() {
|
||||
const packagedContent = packagedPluginsContent();
|
||||
|
||||
@@ -107,7 +107,7 @@ module.exports = {
|
||||
// await fs.writeFile(path.join(datadir(), 'removed-plugins'), this.removedPlugins.join('\n'));
|
||||
// },
|
||||
|
||||
install_meta: 'post',
|
||||
install_meta: true,
|
||||
async install({ packageName }) {
|
||||
if (!hasPermission(`plugins/install`)) return;
|
||||
const dir = path.join(pluginsdir(), packageName);
|
||||
@@ -120,7 +120,7 @@ module.exports = {
|
||||
// await this.saveRemovePlugins();
|
||||
},
|
||||
|
||||
uninstall_meta: 'post',
|
||||
uninstall_meta: true,
|
||||
async uninstall({ packageName }) {
|
||||
if (!hasPermission(`plugins/install`)) return;
|
||||
const dir = path.join(pluginsdir(), packageName);
|
||||
@@ -130,7 +130,7 @@ module.exports = {
|
||||
await this.saveRemovePlugins();
|
||||
},
|
||||
|
||||
upgrade_meta: 'post',
|
||||
upgrade_meta: true,
|
||||
async upgrade({ packageName }) {
|
||||
if (!hasPermission(`plugins/install`)) return;
|
||||
const dir = path.join(pluginsdir(), packageName);
|
||||
@@ -143,13 +143,13 @@ module.exports = {
|
||||
socket.emitChanged(`installed-plugins-changed`);
|
||||
},
|
||||
|
||||
command_meta: 'post',
|
||||
command_meta: true,
|
||||
async command({ packageName, command, args }) {
|
||||
const content = requirePlugin(packageName);
|
||||
return content.commands[command](args);
|
||||
},
|
||||
|
||||
authTypes_meta: 'get',
|
||||
authTypes_meta: true,
|
||||
async authTypes({ engine }) {
|
||||
const packageName = extractPackageName(engine);
|
||||
const content = requirePlugin(packageName);
|
||||
|
||||
@@ -34,7 +34,7 @@ function readCore(reader, skip, limit, filter) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
read_meta: 'get',
|
||||
read_meta: true,
|
||||
async read({ skip, limit, filter }) {
|
||||
const fileName = path.join(datadir(), 'query-history.jsonl');
|
||||
// @ts-ignore
|
||||
@@ -44,7 +44,7 @@ module.exports = {
|
||||
return res;
|
||||
},
|
||||
|
||||
write_meta: 'post',
|
||||
write_meta: true,
|
||||
async write({ data }) {
|
||||
const fileName = path.join(datadir(), 'query-history.jsonl');
|
||||
await fs.appendFile(fileName, JSON.stringify(data) + '\n');
|
||||
|
||||
@@ -8,6 +8,7 @@ const { fork } = require('child_process');
|
||||
const { rundir, uploadsdir, pluginsdir, getPluginBackendPath, packagedPluginList } = require('../utility/directories');
|
||||
const { extractShellApiPlugins, extractShellApiFunctionName } = require('dbgate-tools');
|
||||
const { handleProcessCommunication } = require('../utility/processComm');
|
||||
const processArgs = require('../utility/processArgs');
|
||||
|
||||
function extractPlugins(script) {
|
||||
const requireRegex = /\s*\/\/\s*@require\s+([^\s]+)\s*\n/g;
|
||||
@@ -98,15 +99,22 @@ module.exports = {
|
||||
const pluginNames = _.union(fs.readdirSync(pluginsdir()), packagedPluginList);
|
||||
console.log(`RUNNING SCRIPT ${scriptFile}`);
|
||||
// const subprocess = fork(scriptFile, ['--checkParent', '--max-old-space-size=8192'], {
|
||||
const subprocess = fork(scriptFile, ['--checkParent', ...process.argv.slice(3)], {
|
||||
cwd: directory,
|
||||
stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
|
||||
env: {
|
||||
...process.env,
|
||||
DBGATE_API: global['dbgateApiModulePath'] || process.argv[1],
|
||||
..._.fromPairs(pluginNames.map(name => [`PLUGIN_${_.camelCase(name)}`, getPluginBackendPath(name)])),
|
||||
},
|
||||
});
|
||||
const subprocess = fork(
|
||||
scriptFile,
|
||||
[
|
||||
'--checkParent', // ...process.argv.slice(3)
|
||||
...processArgs.getPassArgs(),
|
||||
],
|
||||
{
|
||||
cwd: directory,
|
||||
stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
|
||||
env: {
|
||||
...process.env,
|
||||
DBGATE_API: global['API_PACKAGE'] || global['dbgateApiModulePath'] || process.argv[1],
|
||||
..._.fromPairs(pluginNames.map(name => [`PLUGIN_${_.camelCase(name)}`, getPluginBackendPath(name)])),
|
||||
},
|
||||
}
|
||||
);
|
||||
const pipeDispatcher = severity => data =>
|
||||
this.dispatchMessage(runid, { severity, message: data.toString().trim() });
|
||||
|
||||
@@ -136,21 +144,21 @@ module.exports = {
|
||||
if (handleProcessCommunication(message, subprocess)) return;
|
||||
this[`handle_${msgtype}`](runid, message);
|
||||
});
|
||||
return newOpened;
|
||||
return _.pick(newOpened, ['runid']);
|
||||
},
|
||||
|
||||
start_meta: 'post',
|
||||
start_meta: true,
|
||||
async start({ script }) {
|
||||
const runid = uuidv1();
|
||||
return this.startCore(runid, scriptTemplate(script, false));
|
||||
},
|
||||
|
||||
getNodeScript_meta: 'post',
|
||||
getNodeScript_meta: true,
|
||||
async getNodeScript({ script }) {
|
||||
return scriptTemplate(script, true);
|
||||
},
|
||||
|
||||
cancel_meta: 'post',
|
||||
cancel_meta: true,
|
||||
async cancel({ runid }) {
|
||||
const runner = this.opened.find(x => x.runid == runid);
|
||||
if (!runner) {
|
||||
@@ -160,7 +168,7 @@ module.exports = {
|
||||
return { state: 'ok' };
|
||||
},
|
||||
|
||||
files_meta: 'get',
|
||||
files_meta: true,
|
||||
async files({ runid }) {
|
||||
const directory = path.join(rundir(), runid);
|
||||
const files = await fs.readdir(directory);
|
||||
@@ -176,7 +184,7 @@ module.exports = {
|
||||
return res;
|
||||
},
|
||||
|
||||
loadReader_meta: 'post',
|
||||
loadReader_meta: true,
|
||||
async loadReader({ functionName, props }) {
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const runid = uuidv1();
|
||||
|
||||
@@ -6,6 +6,7 @@ const AsyncLock = require('async-lock');
|
||||
const { handleProcessCommunication } = require('../utility/processComm');
|
||||
const lock = new AsyncLock();
|
||||
const config = require('./config');
|
||||
const processArgs = require('../utility/processArgs');
|
||||
|
||||
module.exports = {
|
||||
opened: [],
|
||||
@@ -37,10 +38,12 @@ module.exports = {
|
||||
const existing = this.opened.find(x => x.conid == conid);
|
||||
if (existing) return existing;
|
||||
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',
|
||||
'serverConnectionProcess',
|
||||
...process.argv.slice(3),
|
||||
...processArgs.getPassArgs(),
|
||||
// ...process.argv.slice(3),
|
||||
]);
|
||||
const newOpened = {
|
||||
conid,
|
||||
@@ -86,25 +89,25 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
disconnect_meta: 'post',
|
||||
disconnect_meta: true,
|
||||
async disconnect({ conid }) {
|
||||
await this.close(conid, true);
|
||||
return { status: 'ok' };
|
||||
},
|
||||
|
||||
listDatabases_meta: 'get',
|
||||
listDatabases_meta: true,
|
||||
async listDatabases({ conid }) {
|
||||
const opened = await this.ensureOpened(conid);
|
||||
return opened.databases;
|
||||
},
|
||||
|
||||
version_meta: 'get',
|
||||
version_meta: true,
|
||||
async version({ conid }) {
|
||||
const opened = await this.ensureOpened(conid);
|
||||
return opened.version;
|
||||
},
|
||||
|
||||
serverStatus_meta: 'get',
|
||||
serverStatus_meta: true,
|
||||
async serverStatus() {
|
||||
return {
|
||||
...this.closed,
|
||||
@@ -112,7 +115,7 @@ module.exports = {
|
||||
};
|
||||
},
|
||||
|
||||
ping_meta: 'post',
|
||||
ping_meta: true,
|
||||
async ping({ connections }) {
|
||||
await Promise.all(
|
||||
_.uniq(connections).map(async conid => {
|
||||
@@ -128,7 +131,7 @@ module.exports = {
|
||||
return { status: 'ok' };
|
||||
},
|
||||
|
||||
refresh_meta: 'post',
|
||||
refresh_meta: true,
|
||||
async refresh({ conid, keepOpen }) {
|
||||
if (!keepOpen) this.close(conid);
|
||||
|
||||
@@ -136,7 +139,7 @@ module.exports = {
|
||||
return { status: 'ok' };
|
||||
},
|
||||
|
||||
createDatabase_meta: 'post',
|
||||
createDatabase_meta: true,
|
||||
async createDatabase({ conid, name }) {
|
||||
const opened = await this.ensureOpened(conid);
|
||||
opened.subprocess.send({ msgtype: 'createDatabase', name });
|
||||
|
||||
@@ -5,6 +5,7 @@ const socket = require('../utility/socket');
|
||||
const { fork } = require('child_process');
|
||||
const jsldata = require('./jsldata');
|
||||
const { handleProcessCommunication } = require('../utility/processComm');
|
||||
const processArgs = require('../utility/processArgs');
|
||||
|
||||
module.exports = {
|
||||
/** @type {import('dbgate-types').OpenedSession[]} */
|
||||
@@ -61,11 +62,17 @@ module.exports = {
|
||||
|
||||
handle_ping() {},
|
||||
|
||||
create_meta: 'post',
|
||||
create_meta: true,
|
||||
async create({ conid, database }) {
|
||||
const sesid = uuidv1();
|
||||
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 = {
|
||||
conid,
|
||||
database,
|
||||
@@ -81,10 +88,10 @@ module.exports = {
|
||||
this[`handle_${msgtype}`](sesid, message);
|
||||
});
|
||||
subprocess.send({ msgtype: 'connect', ...connection, database });
|
||||
return newOpened;
|
||||
return _.pick(newOpened, ['conid', 'database', 'sesid']);
|
||||
},
|
||||
|
||||
executeQuery_meta: 'post',
|
||||
executeQuery_meta: true,
|
||||
async executeQuery({ sesid, sql }) {
|
||||
const session = this.opened.find(x => x.sesid == sesid);
|
||||
if (!session) {
|
||||
@@ -98,7 +105,7 @@ module.exports = {
|
||||
return { state: 'ok' };
|
||||
},
|
||||
|
||||
// cancel_meta: 'post',
|
||||
// cancel_meta: true,
|
||||
// async cancel({ sesid }) {
|
||||
// const session = this.opened.find((x) => x.sesid == sesid);
|
||||
// if (!session) {
|
||||
@@ -108,7 +115,7 @@ module.exports = {
|
||||
// return { state: 'ok' };
|
||||
// },
|
||||
|
||||
kill_meta: 'post',
|
||||
kill_meta: true,
|
||||
async kill({ sesid }) {
|
||||
const session = this.opened.find(x => x.sesid == sesid);
|
||||
if (!session) {
|
||||
@@ -119,7 +126,7 @@ module.exports = {
|
||||
return { state: 'ok' };
|
||||
},
|
||||
|
||||
// runCommand_meta: 'post',
|
||||
// runCommand_meta: true,
|
||||
// async runCommand({ conid, database, sql }) {
|
||||
// console.log(`Running SQL command , conid=${conid}, database=${database}, sql=${sql}`);
|
||||
// const opened = await this.ensureOpened(conid, database);
|
||||
|
||||
@@ -8,7 +8,7 @@ if (processArgs.startProcess) {
|
||||
const proc = require('./proc');
|
||||
const module = proc[processArgs.startProcess];
|
||||
module.start();
|
||||
} else if (!module['parent'] && !processArgs.checkParent) {
|
||||
} else if (!processArgs.checkParent && !global['API_PACKAGE'] && !global['dbgateApiModulePath']) {
|
||||
const main = require('./main');
|
||||
|
||||
main.start();
|
||||
|
||||
@@ -4,12 +4,8 @@ const bodyParser = require('body-parser');
|
||||
const fileUpload = require('express-fileupload');
|
||||
const http = require('http');
|
||||
const cors = require('cors');
|
||||
const io = require('socket.io');
|
||||
const fs = require('fs');
|
||||
const getPort = require('get-port');
|
||||
const childProcessChecker = require('./utility/childProcessChecker');
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
|
||||
const useController = require('./utility/useController');
|
||||
const socket = require('./utility/socket');
|
||||
@@ -31,10 +27,7 @@ const queryHistory = require('./controllers/queryHistory');
|
||||
|
||||
const { rundir } = require('./utility/directories');
|
||||
const platformInfo = require('./utility/platformInfo');
|
||||
const processArgs = require('./utility/processArgs');
|
||||
const timingSafeCheckToken = require('./utility/timingSafeCheckToken');
|
||||
|
||||
let authorization = null;
|
||||
let checkLocalhostOrigin = null;
|
||||
|
||||
function start() {
|
||||
@@ -43,7 +36,6 @@ function start() {
|
||||
const app = express();
|
||||
|
||||
const server = http.createServer(app);
|
||||
socket.set(io(server));
|
||||
|
||||
if (process.env.LOGIN && process.env.PASSWORD) {
|
||||
app.use(
|
||||
@@ -58,9 +50,6 @@ function start() {
|
||||
}
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
if (authorization && !timingSafeCheckToken(req.headers.authorization, authorization)) {
|
||||
return res.status(403).json({ error: 'Not authorized!' });
|
||||
}
|
||||
if (checkLocalhostOrigin) {
|
||||
if (
|
||||
req.headers.origin &&
|
||||
@@ -81,6 +70,20 @@ function start() {
|
||||
});
|
||||
|
||||
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(
|
||||
@@ -90,20 +93,7 @@ function start() {
|
||||
})
|
||||
);
|
||||
|
||||
useController(app, '/connections', connections);
|
||||
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);
|
||||
useAllControllers(app, null);
|
||||
|
||||
// if (process.env.PAGES_DIRECTORY) {
|
||||
// app.use('/pages', express.static(process.env.PAGES_DIRECTORY));
|
||||
@@ -122,19 +112,7 @@ function start() {
|
||||
}
|
||||
}
|
||||
|
||||
if (processArgs.dynport) {
|
||||
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) {
|
||||
if (platformInfo.isNpmDist) {
|
||||
app.use(express.static(path.join(__dirname, '../../dbgate-web/public')));
|
||||
getPort({ port: 5000 }).then(port => {
|
||||
server.listen(port, () => {
|
||||
@@ -142,8 +120,47 @@ function start() {
|
||||
});
|
||||
});
|
||||
} else {
|
||||
server.listen(3000);
|
||||
const port = process.env.PORT || 3000;
|
||||
console.log('DbGate API listening on port', port);
|
||||
server.listen(port);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
module.exports = { start };
|
||||
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 };
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
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);
|
||||
|
||||
// @ts-ignore
|
||||
module.exports = redirectFile ? __non_webpack_require__(redirectFile) : require('./nativeModulesContent');
|
||||
function requireDynamic(file) {
|
||||
try {
|
||||
// @ts-ignore
|
||||
return __non_webpack_require__(redirectFile);
|
||||
} catch (err) {
|
||||
return require(redirectFile);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = redirectFile ? requireDynamic(redirectFile) : require('./nativeModulesContent');
|
||||
|
||||
@@ -2,17 +2,9 @@ const childProcessChecker = require('../utility/childProcessChecker');
|
||||
const requireEngineDriver = require('../utility/requireEngineDriver');
|
||||
const connectUtility = require('../utility/connectUtility');
|
||||
const { handleProcessCommunication } = require('../utility/processComm');
|
||||
const { pickSafeConnectionInfo } = require('../utility/crypting');
|
||||
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}
|
||||
|
||||
Error JSON: ${JSON.stringify(e, undefined, 2)}
|
||||
|
||||
@@ -270,6 +270,7 @@ function start() {
|
||||
try {
|
||||
await handleMessage(message);
|
||||
} catch (e) {
|
||||
console.error('Error in DB connection', e);
|
||||
process.send({ msgtype: 'error', error: e.message });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const { fork } = require('child_process');
|
||||
const uuidv1 = require('uuid/v1');
|
||||
const { handleProcessCommunication } = require('./processComm');
|
||||
const processArgs = require('../utility/processArgs');
|
||||
|
||||
class DatastoreProxy {
|
||||
constructor(file) {
|
||||
@@ -29,7 +30,13 @@ class DatastoreProxy {
|
||||
|
||||
async ensureSubprocess() {
|
||||
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 => {
|
||||
// @ts-ignore
|
||||
|
||||
@@ -2,6 +2,7 @@ const crypto = require('crypto');
|
||||
const simpleEncryptor = require('simple-encryptor');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const _ = require('lodash');
|
||||
|
||||
const { datadir } = require('./directories');
|
||||
|
||||
@@ -81,8 +82,18 @@ function decryptConnection(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 = {
|
||||
loadEncryptionKey,
|
||||
encryptConnection,
|
||||
decryptConnection,
|
||||
pickSafeConnectionInfo,
|
||||
};
|
||||
|
||||
@@ -41,6 +41,10 @@ const archivedir = dirFunc('archive');
|
||||
const filesdir = dirFunc('files');
|
||||
|
||||
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) {
|
||||
return path.resolve(__dirname, '../../../../plugins');
|
||||
}
|
||||
@@ -53,6 +57,12 @@ function packagedPluginsDir() {
|
||||
}
|
||||
if (platformInfo.isElectronBundle) {
|
||||
return path.resolve(__dirname, '../../plugins');
|
||||
|
||||
// if (platformInfo.isForkedApi) {
|
||||
// return path.resolve(__dirname, '../plugins');
|
||||
// } else {
|
||||
// return path.resolve(__dirname, '../../plugins');
|
||||
// }
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const processArgs = require('./processArgs');
|
||||
const isElectron = require('is-electron');
|
||||
|
||||
const platform = process.env.OS_OVERRIDE ? process.env.OS_OVERRIDE : process.platform;
|
||||
const isWindows = platform === 'win32';
|
||||
@@ -10,6 +11,7 @@ const isLinux = platform === 'linux';
|
||||
const isDocker = fs.existsSync('/home/dbgate-docker/public');
|
||||
const isDevMode = process.env.DEVMODE == '1';
|
||||
const isNpmDist = !!global['dbgateApiModulePath'];
|
||||
const isForkedApi = processArgs.isForkedApi;
|
||||
|
||||
// function moduleAvailable(name) {
|
||||
// try {
|
||||
@@ -20,14 +22,14 @@ const isNpmDist = !!global['dbgateApiModulePath'];
|
||||
// }
|
||||
// }
|
||||
|
||||
const isElectronBundle = processArgs.isElectronBundle;
|
||||
|
||||
const platformInfo = {
|
||||
isWindows,
|
||||
isMac,
|
||||
isLinux,
|
||||
isDocker,
|
||||
isElectronBundle,
|
||||
isElectronBundle: isElectron() && !isDevMode,
|
||||
isForkedApi,
|
||||
isElectron: isElectron(),
|
||||
isDevMode,
|
||||
isNpmDist,
|
||||
isSnap: process.env.ELECTRON_SNAP == 'true',
|
||||
|
||||
@@ -7,15 +7,17 @@ function getNamedArg(name) {
|
||||
}
|
||||
|
||||
const checkParent = process.argv.includes('--checkParent');
|
||||
const dynport = process.argv.includes('--dynport');
|
||||
const nativeModules = getNamedArg('--native-modules');
|
||||
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 = {
|
||||
checkParent,
|
||||
nativeModules,
|
||||
startProcess,
|
||||
dynport,
|
||||
isElectronBundle,
|
||||
isForkedApi,
|
||||
getPassArgs,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const _ = require('lodash');
|
||||
const requirePlugin = require('../shell/requirePlugin');
|
||||
const { pickSafeConnectionInfo } = require('./crypting');
|
||||
|
||||
/** @returns {import('dbgate-types').EngineDriver} */
|
||||
function requireEngineDriver(connection) {
|
||||
@@ -10,14 +11,14 @@ function requireEngineDriver(connection) {
|
||||
engine = connection.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('@')) {
|
||||
const [shortName, packageName] = engine.split('@');
|
||||
const plugin = requirePlugin(packageName);
|
||||
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;
|
||||
|
||||
@@ -1,19 +1,29 @@
|
||||
let socket = null;
|
||||
let sseResponse = null;
|
||||
let electronSender = null;
|
||||
let init = '';
|
||||
|
||||
module.exports = {
|
||||
set(value) {
|
||||
socket = value;
|
||||
setSseResponse(value) {
|
||||
sseResponse = value;
|
||||
},
|
||||
get() {
|
||||
return socket;
|
||||
setElectronSender(value) {
|
||||
electronSender = value;
|
||||
},
|
||||
emit(message, data) {
|
||||
// console.log('EMIT:', message, data);
|
||||
socket.emit(message, data);
|
||||
if (electronSender) {
|
||||
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) {
|
||||
// console.log('EMIT_CHANGED:', key);
|
||||
socket.emit('clean-cache', key);
|
||||
socket.emit(key);
|
||||
this.emit('clean-cache', key);
|
||||
this.emit(key);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@ const express = require('express');
|
||||
/**
|
||||
* @param {string} route
|
||||
*/
|
||||
module.exports = function useController(app, route, controller) {
|
||||
module.exports = function useController(app, electron, route, controller) {
|
||||
const router = express.Router();
|
||||
|
||||
if (controller._init) {
|
||||
@@ -23,24 +23,39 @@ module.exports = function useController(app, route, controller) {
|
||||
const meta = controller[`${key}_meta`];
|
||||
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 rawParams = false;
|
||||
|
||||
if (_.isString(meta)) {
|
||||
method = meta;
|
||||
}
|
||||
// if (_.isString(meta)) {
|
||||
// method = meta;
|
||||
// }
|
||||
if (_.isPlainObject(meta)) {
|
||||
method = meta.method;
|
||||
raw = meta.raw;
|
||||
rawParams = meta.rawParams;
|
||||
}
|
||||
|
||||
const route = `/${_.kebabCase(key)}`;
|
||||
if (raw) {
|
||||
router[method](route, controller[key]);
|
||||
router[method](routeAction, controller[key]);
|
||||
} else {
|
||||
router[method](route, async (req, res) => {
|
||||
router[method](routeAction, async (req, res) => {
|
||||
// if (controller._init && !controller._init_called) {
|
||||
// await controller._init();
|
||||
// controller._init_called = true;
|
||||
@@ -58,5 +73,7 @@ module.exports = function useController(app, route, controller) {
|
||||
}
|
||||
}
|
||||
|
||||
app.use(route, router);
|
||||
if (app) {
|
||||
app.use(route, router);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -43,9 +43,7 @@
|
||||
"rollup-plugin-livereload": "^2.0.0",
|
||||
"rollup-plugin-svelte": "^7.0.0",
|
||||
"rollup-plugin-terser": "^7.0.0",
|
||||
"rollup-plugin-web-worker-loader": "^1.6.1",
|
||||
"sirv-cli": "^1.0.0",
|
||||
"socket.io-client": "^2.3.0",
|
||||
"sql-formatter": "^2.3.3",
|
||||
"svelte": "^3.43.0",
|
||||
"svelte-check": "^1.0.0",
|
||||
|
||||
@@ -7,10 +7,8 @@ import { terser } from 'rollup-plugin-terser';
|
||||
import sveltePreprocess from 'svelte-preprocess';
|
||||
import typescript from '@rollup/plugin-typescript';
|
||||
import replace from '@rollup/plugin-replace';
|
||||
import webWorkerLoader from 'rollup-plugin-web-worker-loader';
|
||||
import css from 'rollup-plugin-css-only';
|
||||
|
||||
|
||||
const production = !process.env.ROLLUP_WATCH;
|
||||
|
||||
function serve() {
|
||||
@@ -34,77 +32,96 @@ function serve() {
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
input: 'src/main.ts',
|
||||
output: {
|
||||
sourcemap: true,
|
||||
format: 'iife',
|
||||
name: 'app',
|
||||
file: 'public/build/bundle.js',
|
||||
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(),
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
copy({
|
||||
targets: [
|
||||
{
|
||||
src: '../../node_modules/@mdi/font/css/materialdesignicons.css',
|
||||
dest: 'public/build/fonts/',
|
||||
|
||||
{
|
||||
input: 'src/main.ts',
|
||||
output: {
|
||||
sourcemap: true,
|
||||
format: 'iife',
|
||||
name: 'app',
|
||||
file: 'public/build/bundle.js',
|
||||
},
|
||||
plugins: [
|
||||
copy({
|
||||
targets: [
|
||||
{
|
||||
src: '../../node_modules/@mdi/font/css/materialdesignicons.css',
|
||||
dest: 'public/build/fonts/',
|
||||
},
|
||||
{
|
||||
src: '../../node_modules/@mdi/font/fonts/*',
|
||||
dest: 'public/build/fonts/',
|
||||
},
|
||||
{
|
||||
src: '../../node_modules/diff2html/bundles/css/diff2html.min.css',
|
||||
dest: 'public/build/',
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
||||
replace({
|
||||
'process.env.API_URL': JSON.stringify(process.env.API_URL),
|
||||
}),
|
||||
|
||||
svelte({
|
||||
preprocess: sveltePreprocess({ sourceMap: !production }),
|
||||
compilerOptions: {
|
||||
// enable run-time checks when not in production
|
||||
dev: !production,
|
||||
},
|
||||
{
|
||||
src: '../../node_modules/@mdi/font/fonts/*',
|
||||
dest: 'public/build/fonts/',
|
||||
},
|
||||
{
|
||||
src: '../../node_modules/diff2html/bundles/css/diff2html.min.css',
|
||||
dest: 'public/build/',
|
||||
},
|
||||
],
|
||||
}),
|
||||
}),
|
||||
// we'll extract any component CSS out into
|
||||
// a separate file - better for performance
|
||||
css({ output: 'bundle.css' }),
|
||||
|
||||
replace({
|
||||
'process.env.API_URL': JSON.stringify(process.env.API_URL),
|
||||
}),
|
||||
// If you have external dependencies installed from
|
||||
// npm, you'll most likely need these plugins. In
|
||||
// some cases you'll need additional configuration -
|
||||
// consult the documentation for details:
|
||||
// https://github.com/rollup/plugins/tree/master/packages/commonjs
|
||||
resolve({
|
||||
browser: true,
|
||||
dedupe: ['svelte'],
|
||||
}),
|
||||
commonjs(),
|
||||
typescript({
|
||||
sourceMap: !production,
|
||||
inlineSources: !production,
|
||||
}),
|
||||
|
||||
svelte({
|
||||
preprocess: sveltePreprocess({ sourceMap: !production }),
|
||||
compilerOptions: {
|
||||
// enable run-time checks when not in production
|
||||
dev: !production,
|
||||
},
|
||||
}),
|
||||
// we'll extract any component CSS out into
|
||||
// a separate file - better for performance
|
||||
css({ output: 'bundle.css' }),
|
||||
// In dev mode, call `npm run start` once
|
||||
// the bundle has been generated
|
||||
!production && serve(),
|
||||
|
||||
// If you have external dependencies installed from
|
||||
// npm, you'll most likely need these plugins. In
|
||||
// some cases you'll need additional configuration -
|
||||
// consult the documentation for details:
|
||||
// https://github.com/rollup/plugins/tree/master/packages/commonjs
|
||||
resolve({
|
||||
browser: true,
|
||||
dedupe: ['svelte'],
|
||||
}),
|
||||
commonjs(),
|
||||
typescript({
|
||||
sourceMap: !production,
|
||||
inlineSources: !production,
|
||||
}),
|
||||
// Watch the `public` directory and refresh the
|
||||
// browser on changes when not in production
|
||||
!production && livereload('public'),
|
||||
|
||||
// In dev mode, call `npm run start` once
|
||||
// the bundle has been generated
|
||||
!production && serve(),
|
||||
|
||||
// Watch the `public` directory and refresh the
|
||||
// browser on changes when not in production
|
||||
!production && livereload('public'),
|
||||
|
||||
// If we're building for production (npm run build
|
||||
// instead of npm run dev), minify
|
||||
production && terser(),
|
||||
|
||||
webWorkerLoader(),
|
||||
],
|
||||
watch: {
|
||||
clearScreen: false,
|
||||
// If we're building for production (npm run build
|
||||
// instead of npm run dev), minify
|
||||
production && terser(),
|
||||
],
|
||||
watch: {
|
||||
clearScreen: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
];
|
||||
|
||||
@@ -7,20 +7,37 @@
|
||||
|
||||
import PluginsProvider from './plugins/PluginsProvider.svelte';
|
||||
import Screen from './Screen.svelte';
|
||||
import { loadingPluginStore } from './stores';
|
||||
import { loadingPluginStore, subscribeApiDependendStores } from './stores';
|
||||
import { setAppLoaded } from './utility/appLoadManager';
|
||||
import axiosInstance from './utility/axiosInstance';
|
||||
import ErrorHandler from './utility/ErrorHandler.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;
|
||||
|
||||
async function loadApi() {
|
||||
// if (shouldWaitForElectronInitialize()) {
|
||||
// setTimeout(loadApi, 100);
|
||||
// return;
|
||||
// }
|
||||
|
||||
try {
|
||||
const settings = await axiosInstance.get('config/get-settings');
|
||||
const connections = await axiosInstance.get('connections/list');
|
||||
const config = await axiosInstance.get('config/get');
|
||||
loadedApi = settings?.data && connections?.data && config?.data;
|
||||
// console.log('************** LOADING API');
|
||||
|
||||
const settings = await apiCall('config/get-settings');
|
||||
const connections = await apiCall('connections/list');
|
||||
const config = await apiCall('config/get');
|
||||
loadedApi = settings && connections && config;
|
||||
|
||||
if (loadedApi) {
|
||||
subscribeApiDependendStores();
|
||||
subscribeConnectionPingers();
|
||||
subscribePermissionCompiler();
|
||||
}
|
||||
|
||||
if (!loadedApi) {
|
||||
console.log('API not initialized correctly, trying again in 1s');
|
||||
setTimeout(loadApi, 1000);
|
||||
@@ -43,14 +60,13 @@
|
||||
setAppLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<DataGridRowHeightMeter />
|
||||
<ErrorHandler />
|
||||
<CommandListener />
|
||||
|
||||
{#if loadedApi}
|
||||
<DataGridRowHeightMeter />
|
||||
<CommandListener />
|
||||
<PluginsProvider />
|
||||
{#if $loadingPluginStore?.loaded}
|
||||
<OpenTabsOnStartup />
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
const connProps: any = {};
|
||||
let tooltip = undefined;
|
||||
|
||||
const resp = await axiosInstance.post('files/load', {
|
||||
const resp = await apiCall('files/load', {
|
||||
folder: 'archive:' + folderName,
|
||||
file: fileName + '.' + fileType,
|
||||
format: 'text',
|
||||
@@ -36,7 +36,7 @@
|
||||
...connProps,
|
||||
},
|
||||
},
|
||||
{ editor: resp.data }
|
||||
{ editor: resp }
|
||||
);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,6 @@
|
||||
|
||||
import { archiveFilesAsDataSheets, currentArchive, extensions, getCurrentDatabase } from '../stores';
|
||||
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import createQuickExportMenu from '../utility/createQuickExportMenu';
|
||||
import { exportElectronFile } from '../utility/exportElectronFile';
|
||||
import openNewTab from '../utility/openNewTab';
|
||||
@@ -82,6 +81,7 @@
|
||||
markArchiveFileAsDataSheet,
|
||||
markArchiveFileAsReadonly,
|
||||
} from '../utility/archiveTools';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let data;
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
label: 'New file name',
|
||||
header: 'Rename file',
|
||||
onConfirm: newFile => {
|
||||
axiosInstance.post('archive/rename-file', {
|
||||
apiCall('archive/rename-file', {
|
||||
file: data.fileName,
|
||||
folder: data.folderName,
|
||||
fileType: data.fileType,
|
||||
@@ -105,7 +105,7 @@
|
||||
showModal(ConfirmModal, {
|
||||
message: `Really delete file ${data.fileName}?`,
|
||||
onConfirm: () => {
|
||||
axiosInstance.post('archive/delete-file', {
|
||||
apiCall('archive/delete-file', {
|
||||
file: data.fileName,
|
||||
folder: data.folderName,
|
||||
fileType: data.fileType,
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
import { currentArchive, currentDatabase } from '../stores';
|
||||
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import openNewTab from '../utility/openNewTab';
|
||||
import AppObjectCore from './AppObjectCore.svelte';
|
||||
import newQuery from '../query/newQuery';
|
||||
@@ -17,6 +16,7 @@
|
||||
import ConfirmModal from '../modals/ConfirmModal.svelte';
|
||||
import InputTextModal from '../modals/InputTextModal.svelte';
|
||||
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let data;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
? `Really delete link to folder ${data.name}? Folder content remains untouched.`
|
||||
: `Really delete folder ${data.name}?`,
|
||||
onConfirm: () => {
|
||||
axiosInstance.post('archive/delete-folder', { folder: data.name });
|
||||
apiCall('archive/delete-folder', { folder: data.name });
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -41,7 +41,7 @@
|
||||
label: 'New folder name',
|
||||
header: 'Rename folder',
|
||||
onConfirm: async newFolder => {
|
||||
await axiosInstance.post('archive/rename-folder', {
|
||||
await apiCall('archive/rename-folder', {
|
||||
folder: data.name,
|
||||
newFolder: newFolder + suffix,
|
||||
});
|
||||
@@ -78,16 +78,16 @@ await dbgateApi.deployDb(${JSON.stringify(
|
||||
};
|
||||
|
||||
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,
|
||||
database: $currentDatabase.name,
|
||||
archiveFolder: data.name,
|
||||
});
|
||||
|
||||
if (resp.data.errorMessage) {
|
||||
showModal(ErrorMessageModal, { message: resp.data.errorMessage });
|
||||
if (resp.errorMessage) {
|
||||
showModal(ErrorMessageModal, { message: resp.errorMessage });
|
||||
} else {
|
||||
newQuery({ initialData: resp.data.sql });
|
||||
newQuery({ initialData: resp.sql });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
import _ from 'lodash';
|
||||
import AppObjectCore from './AppObjectCore.svelte';
|
||||
import { currentDatabase, extensions, getCurrentConfig, getOpenedConnections, openedConnections } from '../stores';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { filterName } from 'dbgate-tools';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import ConnectionModal from '../modals/ConnectionModal.svelte';
|
||||
@@ -29,6 +28,7 @@
|
||||
import getConnectionLabel from '../utility/getConnectionLabel';
|
||||
import { getDatabaseList } from '../utility/metadataLoaders';
|
||||
import { getLocalStorage } from '../utility/storageCache';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let data;
|
||||
export let passProps;
|
||||
@@ -44,14 +44,14 @@
|
||||
const handleConnect = () => {
|
||||
if (data.singleDatabase) {
|
||||
$currentDatabase = { connection: data, name: data.defaultDatabase };
|
||||
axiosInstance.post('database-connections/refresh', {
|
||||
apiCall('database-connections/refresh', {
|
||||
conid: data._id,
|
||||
database: data.defaultDatabase,
|
||||
keepOpen: true,
|
||||
});
|
||||
} else {
|
||||
$openedConnections = _.uniq([...$openedConnections, data._id]);
|
||||
axiosInstance.post('server-connections/refresh', {
|
||||
apiCall('server-connections/refresh', {
|
||||
conid: data._id,
|
||||
keepOpen: true,
|
||||
});
|
||||
@@ -61,16 +61,16 @@
|
||||
const getContextMenu = () => {
|
||||
const config = getCurrentConfig();
|
||||
const handleRefresh = () => {
|
||||
axiosInstance.post('server-connections/refresh', { conid: data._id });
|
||||
apiCall('server-connections/refresh', { conid: data._id });
|
||||
};
|
||||
const handleDisconnect = () => {
|
||||
openedConnections.update(list => list.filter(x => x != data._id));
|
||||
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 (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);
|
||||
}
|
||||
@@ -81,11 +81,11 @@
|
||||
const handleDelete = () => {
|
||||
showModal(ConfirmModal, {
|
||||
message: `Really delete connection ${getConnectionLabel(data)}?`,
|
||||
onConfirm: () => axiosInstance.post('connections/delete', data),
|
||||
onConfirm: () => apiCall('connections/delete', data),
|
||||
});
|
||||
};
|
||||
const handleDuplicate = () => {
|
||||
axiosInstance.post('connections/save', {
|
||||
apiCall('connections/save', {
|
||||
...data,
|
||||
_id: undefined,
|
||||
displayName: `${getConnectionLabel(data)} - copy`,
|
||||
@@ -97,7 +97,7 @@
|
||||
value: 'newdb',
|
||||
label: 'Database name',
|
||||
onConfirm: name =>
|
||||
axiosInstance.post('server-connections/create-database', {
|
||||
apiCall('server-connections/create-database', {
|
||||
conid: data._id,
|
||||
name,
|
||||
}),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script lang="ts" context="module">
|
||||
export const extractKey = props => props.name;
|
||||
const electron = getElectron();
|
||||
|
||||
export function getDatabaseMenuItems(connection, name, $extensions, $currentDatabase) {
|
||||
const handleNewQuery = () => {
|
||||
@@ -48,13 +47,11 @@
|
||||
header: 'Create collection',
|
||||
onConfirm: async newCollection => {
|
||||
const dbid = { conid: connection._id, database: name };
|
||||
await axiosInstance.request({
|
||||
url: 'database-connections/run-script',
|
||||
method: 'post',
|
||||
params: dbid,
|
||||
data: { sql: `db.createCollection('${newCollection}')` },
|
||||
await apiCall('database-connections/run-script', {
|
||||
...dbid,
|
||||
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 electron = getElectron();
|
||||
if (electron) {
|
||||
axiosInstance.post('database-connections/disconnect', { conid: connection._id, database: name });
|
||||
apiCall('database-connections/disconnect', { conid: connection._id, database: name });
|
||||
}
|
||||
currentDatabase.set(null);
|
||||
};
|
||||
|
||||
const handleExportModel = async () => {
|
||||
const resp = await axiosInstance.post('database-connections/export-model', {
|
||||
const resp = await apiCall('database-connections/export-model', {
|
||||
conid: connection._id,
|
||||
database: name,
|
||||
});
|
||||
currentArchive.set(resp.data.archiveFolder);
|
||||
currentArchive.set(resp.archiveFolder);
|
||||
selectedWidget.set('archive');
|
||||
showSnackbarSuccess(`Saved to archive ${resp.data.archiveFolder}`);
|
||||
showSnackbarSuccess(`Saved to archive ${resp.archiveFolder}`);
|
||||
};
|
||||
|
||||
const handleCompareWithCurrentDb = () => {
|
||||
@@ -173,7 +171,6 @@
|
||||
pinnedDatabases,
|
||||
selectedWidget,
|
||||
} from '../stores';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import getElectron from '../utility/getElectron';
|
||||
import openNewTab from '../utility/openNewTab';
|
||||
import AppObjectCore from './AppObjectCore.svelte';
|
||||
@@ -182,6 +179,7 @@
|
||||
import InputTextModal from '../modals/InputTextModal.svelte';
|
||||
import { getDatabaseInfo } from '../utility/metadataLoaders';
|
||||
import { openJsonDocument } from '../tabs/JsonTab.svelte';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let data;
|
||||
export let passProps;
|
||||
|
||||
@@ -408,9 +408,9 @@
|
||||
import { exportElectronFile } from '../utility/exportElectronFile';
|
||||
import createQuickExportMenu from '../utility/createQuickExportMenu';
|
||||
import ConfirmSqlModal from '../modals/ConfirmSqlModal.svelte';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { alterDatabaseDialog, renameDatabaseObjectDialog } from '../utility/alterDatabaseTools';
|
||||
import ConfirmModal from '../modals/ConfirmModal.svelte';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let data;
|
||||
export let passProps;
|
||||
@@ -559,13 +559,11 @@
|
||||
message: `Really drop collection ${data.pureName}?`,
|
||||
onConfirm: async () => {
|
||||
const dbid = _.pick(data, ['conid', 'database']);
|
||||
await axiosInstance.request({
|
||||
url: 'database-connections/run-script',
|
||||
method: 'post',
|
||||
params: dbid,
|
||||
data: { sql: `db.dropCollection('${data.pureName}')` },
|
||||
await apiCall('database-connections/run-script', {
|
||||
...dbid,
|
||||
sql: `db.dropCollection('${data.pureName}')`,
|
||||
});
|
||||
axiosInstance.post('database-connections/sync-model', dbid);
|
||||
apiCall('database-connections/sync-model', dbid);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
const { icon, tabComponent, title, props, tabdata } = favorite;
|
||||
let tabdataNew = tabdata;
|
||||
if (props.savedFile) {
|
||||
const resp = await axiosInstance.post('files/load', {
|
||||
const resp = await apiCall('files/load', {
|
||||
folder: props.savedFolder,
|
||||
file: props.savedFile,
|
||||
format: props.savedFormat,
|
||||
});
|
||||
tabdataNew = {
|
||||
...tabdata,
|
||||
editor: resp.data,
|
||||
editor: resp,
|
||||
};
|
||||
}
|
||||
openNewTab(
|
||||
@@ -30,13 +30,13 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import openNewTab from '../utility/openNewTab';
|
||||
import { copyTextToClipboard } from '../utility/clipboard';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import ConfirmModal from '../modals/ConfirmModal.svelte';
|
||||
import getElectron from '../utility/getElectron';
|
||||
import FavoriteModal from '../modals/FavoriteModal.svelte';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let data;
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
};
|
||||
|
||||
const editFavoriteJson = async () => {
|
||||
const resp = await axiosInstance.post('files/load', {
|
||||
const resp = await apiCall('files/load', {
|
||||
folder: 'favorites',
|
||||
file: data.file,
|
||||
format: 'text',
|
||||
@@ -64,7 +64,7 @@
|
||||
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, {
|
||||
message: `Really delete favorite ${data.title}?`,
|
||||
onConfirm: () => {
|
||||
axiosInstance.post('files/delete', { file: data.file, folder: 'favorites' });
|
||||
apiCall('files/delete', { file: data.file, folder: 'favorites' });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -74,8 +74,8 @@
|
||||
import { showModal } from '../modals/modalTools';
|
||||
|
||||
import { currentDatabase } from '../stores';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import getConnectionLabel from '../utility/getConnectionLabel';
|
||||
import hasPermission from '../utility/hasPermission';
|
||||
import openNewTab from '../utility/openNewTab';
|
||||
@@ -114,7 +114,7 @@
|
||||
showModal(ConfirmModal, {
|
||||
message: `Really delete file ${data.file}?`,
|
||||
onConfirm: () => {
|
||||
axiosInstance.post('files/delete', data);
|
||||
apiCall('files/delete', data);
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -125,7 +125,7 @@
|
||||
label: 'New file name',
|
||||
header: 'Rename file',
|
||||
onConfirm: newFile => {
|
||||
axiosInstance.post('files/rename', { ...data, newFile });
|
||||
apiCall('files/rename', { ...data, newFile });
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -136,13 +136,13 @@
|
||||
label: 'New file name',
|
||||
header: 'Rename file',
|
||||
onConfirm: newFile => {
|
||||
axiosInstance.post('files/copy', { ...data, newFile });
|
||||
apiCall('files/copy', { ...data, newFile });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
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 = {};
|
||||
let tooltip = undefined;
|
||||
@@ -168,7 +168,7 @@
|
||||
...connProps,
|
||||
},
|
||||
},
|
||||
{ editor: resp.data }
|
||||
{ editor: resp }
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<script lang="ts">
|
||||
import { onMount, afterUpdate, onDestroy } from 'svelte';
|
||||
import registerCommand from '../commands/registerCommand';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
import contextMenu, { getContextMenu, registerMenu } from '../utility/contextMenu';
|
||||
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
||||
@@ -61,7 +61,7 @@
|
||||
|
||||
export async function exportChart() {
|
||||
saveFileToDisk(async filePath => {
|
||||
await axiosInstance.post('files/export-chart', {
|
||||
await apiCall('files/export-chart', {
|
||||
title,
|
||||
filePath,
|
||||
config: {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { dumpSqlSelect, Select } from 'dbgate-sqltree';
|
||||
import { EngineDriver } from 'dbgate-types';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import _ from 'lodash';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export async function loadChartStructure(driver: EngineDriver, conid, database, sql) {
|
||||
const select: Select = {
|
||||
@@ -16,9 +16,9 @@ export async function loadChartStructure(driver: EngineDriver, conid, database,
|
||||
|
||||
const dmp = driver.createDumper();
|
||||
dumpSqlSelect(dmp, select);
|
||||
const resp = await axiosInstance.post('database-connections/query-data', { conid, database, sql: dmp.s });
|
||||
if (resp.data.errorMessage) throw new Error(resp.data.errorMessage);
|
||||
return resp.data.columns.map(x => x.columnName);
|
||||
const resp = await apiCall('database-connections/query-data', { conid, database, sql: dmp.s });
|
||||
if (resp.errorMessage) throw new Error(resp.errorMessage);
|
||||
return resp.columns.map(x => x.columnName);
|
||||
}
|
||||
|
||||
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();
|
||||
dumpSqlSelect(dmp, select);
|
||||
const resp = await axiosInstance.post('database-connections/query-data', { conid, database, sql: dmp.s });
|
||||
let { rows, columns, errorMessage } = resp.data;
|
||||
const resp = await apiCall('database-connections/query-data', { conid, database, sql: dmp.s });
|
||||
let { rows, columns, errorMessage } = resp;
|
||||
if (errorMessage) {
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<script context="module">
|
||||
const electron = getElectron();
|
||||
|
||||
registerCommand({
|
||||
id: 'commandPalette.show',
|
||||
category: 'Command palette',
|
||||
@@ -20,7 +18,7 @@
|
||||
category: 'Database',
|
||||
toolbarName: 'Database search',
|
||||
name: 'Search',
|
||||
keyText: electron ? 'Ctrl+P' : 'F3',
|
||||
keyText: isElectronAvailable() ? 'Ctrl+P' : 'F3',
|
||||
onClick: () => visibleCommandPalette.set('database'),
|
||||
testEnabled: () => getVisibleCommandPalette() != 'database',
|
||||
});
|
||||
@@ -75,7 +73,7 @@
|
||||
} from '../stores';
|
||||
import clickOutside from '../utility/clickOutside';
|
||||
import getConnectionLabel from '../utility/getConnectionLabel';
|
||||
import getElectron from '../utility/getElectron';
|
||||
import { isElectronAvailable } from '../utility/getElectron';
|
||||
import keycodes from '../utility/keycodes';
|
||||
import { useConnectionList, useDatabaseInfo } from '../utility/metadataLoaders';
|
||||
import { getLocalStorage } from '../utility/storageCache';
|
||||
|
||||
@@ -2,9 +2,7 @@ import _ from 'lodash';
|
||||
import { currentDatabase, getCurrentDatabase } from '../stores';
|
||||
import getElectron from '../utility/getElectron';
|
||||
import registerCommand from './registerCommand';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
|
||||
const electron = getElectron();
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
registerCommand({
|
||||
id: 'database.changeState',
|
||||
@@ -22,19 +20,20 @@ registerCommand({
|
||||
{
|
||||
text: 'Sync model',
|
||||
onClick: () => {
|
||||
axiosInstance.post('database-connections/sync-model', dbid);
|
||||
apiCall('database-connections/sync-model', dbid);
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Reopen',
|
||||
onClick: () => {
|
||||
axiosInstance.post('database-connections/refresh', dbid);
|
||||
apiCall('database-connections/refresh', dbid);
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Disconnect',
|
||||
onClick: () => {
|
||||
if (electron) axiosInstance.post('database-connections/disconnect', dbid);
|
||||
const electron = getElectron();
|
||||
if (electron) apiCall('database-connections/disconnect', dbid);
|
||||
currentDatabase.set(null);
|
||||
},
|
||||
},
|
||||
|
||||
@@ -18,8 +18,6 @@ export default function runCommand(id) {
|
||||
}
|
||||
}
|
||||
|
||||
window['dbgate_runCommand'] = runCommand;
|
||||
|
||||
export function runGroupCommand(group) {
|
||||
const commandsValue = getCommands();
|
||||
const values = Object.values(commandsValue) as GlobalCommand[];
|
||||
@@ -32,3 +30,4 @@ export function findCommand(id) {
|
||||
const command = commandsValue[id];
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,15 +18,14 @@ import { getCurrentConfig, getCurrentDatabase } from '../stores';
|
||||
import './recentDatabaseSwitch';
|
||||
import './changeDatabaseStatusCommand';
|
||||
import hasPermission from '../utility/hasPermission';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import _ from 'lodash';
|
||||
import { findEngineDriver } from 'dbgate-tools';
|
||||
import { openArchiveFolder } from '../utility/openArchiveFolder';
|
||||
import InputTextModal from '../modals/InputTextModal.svelte';
|
||||
import { removeLocalStorage } from '../utility/storageCache';
|
||||
import { showSnackbarSuccess } from '../utility/snackbar';
|
||||
|
||||
const electron = getElectron();
|
||||
import { apiCall } from '../utility/api';
|
||||
import runCommand from './runCommand';
|
||||
|
||||
function themeCommand(theme: ThemeDefinition) {
|
||||
return {
|
||||
@@ -123,7 +122,7 @@ registerCommand({
|
||||
label: 'New archive folder name',
|
||||
header: 'Create archive folder',
|
||||
onConfirm: async folder => {
|
||||
axiosInstance.post('archive/create-folder', { folder });
|
||||
apiCall('archive/create-folder', { folder });
|
||||
},
|
||||
});
|
||||
},
|
||||
@@ -190,13 +189,8 @@ registerCommand({
|
||||
label: 'New collection name',
|
||||
header: 'Create collection',
|
||||
onConfirm: async newCollection => {
|
||||
await axiosInstance.request({
|
||||
url: 'database-connections/run-script',
|
||||
method: 'post',
|
||||
params: dbid,
|
||||
data: { sql: `db.createCollection('${newCollection}')` },
|
||||
});
|
||||
axiosInstance.post('database-connections/sync-model', dbid);
|
||||
await apiCall('database-connections/run-script', { ...dbid, sql: `db.createCollection('${newCollection}')` });
|
||||
apiCall('database-connections/sync-model', dbid);
|
||||
},
|
||||
});
|
||||
},
|
||||
@@ -258,8 +252,8 @@ registerCommand({
|
||||
label: 'New database name',
|
||||
header: 'Create SQLite database',
|
||||
onConfirm: async file => {
|
||||
const resp = await axiosInstance.post('connections/new-sqlite-database', { file });
|
||||
const connection = resp.data;
|
||||
const resp = await apiCall('connections/new-sqlite-database', { file });
|
||||
const connection = resp;
|
||||
currentDatabase.set({ connection, name: `${file}.sqlite` });
|
||||
},
|
||||
});
|
||||
@@ -316,22 +310,22 @@ registerCommand({
|
||||
group: 'redo',
|
||||
});
|
||||
|
||||
if (electron) {
|
||||
registerCommand({
|
||||
id: 'file.open',
|
||||
category: 'File',
|
||||
name: 'Open',
|
||||
keyText: 'Ctrl+O',
|
||||
onClick: openElectronFile,
|
||||
});
|
||||
registerCommand({
|
||||
id: 'file.open',
|
||||
category: 'File',
|
||||
name: 'Open',
|
||||
keyText: 'Ctrl+O',
|
||||
testEnabled: () => getElectron() != null,
|
||||
onClick: openElectronFile,
|
||||
});
|
||||
|
||||
registerCommand({
|
||||
id: 'file.openArchive',
|
||||
category: 'File',
|
||||
name: 'Open DB Model/Archive',
|
||||
onClick: openArchiveFolder,
|
||||
});
|
||||
}
|
||||
registerCommand({
|
||||
id: 'file.openArchive',
|
||||
category: 'File',
|
||||
name: 'Open DB Model/Archive',
|
||||
testEnabled: () => getElectron() != null,
|
||||
onClick: openArchiveFolder,
|
||||
});
|
||||
|
||||
registerCommand({
|
||||
id: 'file.import',
|
||||
@@ -419,14 +413,13 @@ if (hasPermission('settings/change')) {
|
||||
});
|
||||
}
|
||||
|
||||
if (electron) {
|
||||
registerCommand({
|
||||
id: 'file.exit',
|
||||
category: 'File',
|
||||
name: 'Exit',
|
||||
onClick: () => electron.remote.getCurrentWindow().close(),
|
||||
});
|
||||
}
|
||||
registerCommand({
|
||||
id: 'file.exit',
|
||||
category: 'File',
|
||||
name: 'Exit',
|
||||
testEnabled: () => getElectron() != null,
|
||||
onClick: () => getElectron().send('close-window'),
|
||||
});
|
||||
|
||||
export function registerFileCommands({
|
||||
idPrefix,
|
||||
@@ -541,3 +534,8 @@ export function registerFileCommands({
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const electron = getElectron();
|
||||
if (electron) {
|
||||
electron.addEventListener('run-command', (e, commandId) => runCommand(commandId));
|
||||
}
|
||||
|
||||
@@ -63,26 +63,20 @@
|
||||
export async function loadCollectionDataPage(props, offset, limit) {
|
||||
const { conid, database } = props;
|
||||
|
||||
const response = await axiosInstance.request({
|
||||
url: 'database-connections/collection-data',
|
||||
method: 'post',
|
||||
params: {
|
||||
conid,
|
||||
database,
|
||||
},
|
||||
data: {
|
||||
options: {
|
||||
pureName: props.pureName,
|
||||
limit,
|
||||
skip: offset,
|
||||
condition: buildGridMongoCondition(props),
|
||||
sort: buildMongoSort(props),
|
||||
},
|
||||
const response = await apiCall('database-connections/collection-data', {
|
||||
conid,
|
||||
database,
|
||||
options: {
|
||||
pureName: props.pureName,
|
||||
limit,
|
||||
skip: offset,
|
||||
condition: buildGridMongoCondition(props),
|
||||
sort: buildMongoSort(props),
|
||||
},
|
||||
});
|
||||
|
||||
if (response.data.errorMessage) return response.data;
|
||||
return response.data.rows;
|
||||
if (response.errorMessage) return response;
|
||||
return response.rows;
|
||||
}
|
||||
|
||||
function dataPageAvailable(props) {
|
||||
@@ -95,23 +89,17 @@
|
||||
async function loadRowCount(props) {
|
||||
const { conid, database } = props;
|
||||
|
||||
const response = await axiosInstance.request({
|
||||
url: 'database-connections/collection-data',
|
||||
method: 'post',
|
||||
params: {
|
||||
conid,
|
||||
database,
|
||||
},
|
||||
data: {
|
||||
options: {
|
||||
pureName: props.pureName,
|
||||
countDocuments: true,
|
||||
condition: buildGridMongoCondition(props),
|
||||
},
|
||||
const response = await apiCall('database-connections/collection-data', {
|
||||
conid,
|
||||
database,
|
||||
options: {
|
||||
pureName: props.pureName,
|
||||
countDocuments: true,
|
||||
condition: buildGridMongoCondition(props),
|
||||
},
|
||||
});
|
||||
|
||||
return response.data.count;
|
||||
return response.count;
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -127,8 +115,8 @@
|
||||
import ImportExportModal from '../modals/ImportExportModal.svelte';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import { extensions } from '../stores';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { registerMenu } from '../utility/contextMenu';
|
||||
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
||||
import createQuickExportMenu from '../utility/createQuickExportMenu';
|
||||
|
||||
@@ -262,7 +262,6 @@
|
||||
import createReducer from '../utility/createReducer';
|
||||
import keycodes from '../utility/keycodes';
|
||||
import { copyRowsFormat, selectedCellsCallback } from '../stores';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import {
|
||||
copyRowsFormatDefs,
|
||||
copyRowsToClipboard,
|
||||
@@ -285,6 +284,7 @@
|
||||
import { findCommand } from '../commands/runCommand';
|
||||
import { openJsonDocument } from '../tabs/JsonTab.svelte';
|
||||
import EditJsonModal from '../modals/EditJsonModal.svelte';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let onLoadNextData = undefined;
|
||||
export let grider = undefined;
|
||||
@@ -404,7 +404,7 @@
|
||||
}
|
||||
|
||||
export async function reconnect() {
|
||||
await axiosInstance.post('database-connections/refresh', { conid, database });
|
||||
await apiCall('database-connections/refresh', { conid, database });
|
||||
display.reload();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { createGridCache, createGridConfig, JslGridDisplay } from 'dbgate-datalib';
|
||||
import { writable } from 'svelte/store';
|
||||
import socket from '../utility/socket';
|
||||
import useEffect from '../utility/useEffect';
|
||||
import { useApiCall } from '../utility/api';
|
||||
|
||||
import useFetch from '../utility/useFetch';
|
||||
import DataGrid from './DataGrid.svelte';
|
||||
import JslDataGridCore from './JslDataGridCore.svelte';
|
||||
|
||||
@@ -12,11 +10,7 @@
|
||||
|
||||
let loadedRows;
|
||||
|
||||
$: info = useFetch({
|
||||
params: { jslid },
|
||||
url: 'jsldata/get-info',
|
||||
defaultValue: {},
|
||||
});
|
||||
$: info = useApiCall('jsldata/get-info', { jslid }, {});
|
||||
|
||||
// $: columns = ($info && $info.columns) || [];
|
||||
const config = writable(createGridConfig());
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
async function loadDataPage(props, offset, limit) {
|
||||
const { jslid, display } = props;
|
||||
|
||||
const response = await axiosInstance.post('jsldata/get-rows', {
|
||||
const response = await apiCall('jsldata/get-rows', {
|
||||
jslid,
|
||||
offset,
|
||||
limit,
|
||||
filters: display ? display.compileFilters() : null,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
function dataPageAvailable(props) {
|
||||
@@ -30,16 +30,9 @@
|
||||
async function loadRowCount(props) {
|
||||
const { jslid } = props;
|
||||
|
||||
const response = await axiosInstance.request({
|
||||
url: 'jsldata/get-stats',
|
||||
method: 'get',
|
||||
params: {
|
||||
jslid,
|
||||
},
|
||||
});
|
||||
return response.data.rowCount;
|
||||
const response = await apiCall('jsldata/get-stats', { jslid });
|
||||
return response.rowCount;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -48,13 +41,12 @@
|
||||
import ImportExportModal from '../modals/ImportExportModal.svelte';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import { extensions } from '../stores';
|
||||
import { apiCall, apiOff, apiOn } from '../utility/api';
|
||||
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { registerMenu } from '../utility/contextMenu';
|
||||
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
||||
import createQuickExportMenu from '../utility/createQuickExportMenu';
|
||||
import { exportElectronFile } from '../utility/exportElectronFile';
|
||||
import socket from '../utility/socket';
|
||||
import useEffect from '../utility/useEffect';
|
||||
|
||||
import LoadingDataGridCore from './LoadingDataGridCore.svelte';
|
||||
@@ -82,9 +74,9 @@
|
||||
$: effect = useEffect(() => onJslId(jslid));
|
||||
function onJslId(jslidVal) {
|
||||
if (jslidVal) {
|
||||
socket.on(`jsldata-stats-${jslidVal}`, handleJslDataStats);
|
||||
apiOn(`jsldata-stats-${jslidVal}`, handleJslDataStats);
|
||||
return () => {
|
||||
socket.off(`jsldata-stats-${jslidVal}`, handleJslDataStats);
|
||||
apiOff(`jsldata-stats-${jslidVal}`, handleJslDataStats);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -140,7 +132,6 @@
|
||||
},
|
||||
{ command: 'jslTableGrid.export', tag: 'export' }
|
||||
);
|
||||
|
||||
</script>
|
||||
|
||||
<LoadingDataGridCore
|
||||
|
||||
@@ -31,18 +31,14 @@
|
||||
|
||||
const sql = display.getPageQuery(offset, limit);
|
||||
|
||||
const response = await axiosInstance.request({
|
||||
url: 'database-connections/query-data',
|
||||
method: 'post',
|
||||
params: {
|
||||
conid,
|
||||
database,
|
||||
},
|
||||
data: { sql },
|
||||
const response = await apiCall('database-connections/query-data', {
|
||||
conid,
|
||||
database,
|
||||
sql,
|
||||
});
|
||||
|
||||
if (response.data.errorMessage) return response.data;
|
||||
return response.data.rows;
|
||||
if (response.errorMessage) return response;
|
||||
return response.rows;
|
||||
}
|
||||
|
||||
function dataPageAvailable(props) {
|
||||
@@ -56,17 +52,13 @@
|
||||
|
||||
const sql = display.getCountQuery();
|
||||
|
||||
const response = await axiosInstance.request({
|
||||
url: 'database-connections/query-data',
|
||||
method: 'post',
|
||||
params: {
|
||||
conid,
|
||||
database,
|
||||
},
|
||||
data: { sql },
|
||||
const response = await apiCall('database-connections/query-data', {
|
||||
conid,
|
||||
database,
|
||||
sql,
|
||||
});
|
||||
|
||||
return parseInt(response.data.rows[0].count);
|
||||
return parseInt(response.rows[0].count);
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -77,8 +69,8 @@
|
||||
import ImportExportModal from '../modals/ImportExportModal.svelte';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import { extensions } from '../stores';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { registerMenu } from '../utility/contextMenu';
|
||||
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
||||
import createQuickExportMenu from '../utility/createQuickExportMenu';
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import InputTextModal from '../modals/InputTextModal.svelte';
|
||||
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
import { useArchiveFolders } from '../utility/metadataLoaders';
|
||||
import { getFormContext } from './FormProviderCore.svelte';
|
||||
@@ -34,7 +34,7 @@
|
||||
];
|
||||
|
||||
const createOption = folder => {
|
||||
axiosInstance.post('archive/create-folder', { folder });
|
||||
apiCall('archive/create-folder', { folder });
|
||||
setFieldValue(name, folder);
|
||||
};
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
|
||||
const { values, setFieldValue } = getFormContext();
|
||||
|
||||
function handleBrowse() {
|
||||
async function handleBrowse() {
|
||||
const electron = getElectron();
|
||||
if (!electron) return;
|
||||
const filePaths = electron.remote.dialog.showOpenDialogSync(electron.remote.getCurrentWindow(), {
|
||||
const filePaths = await electron.showOpenDialog({
|
||||
defaultPath: values[name],
|
||||
properties: ['showHiddenFiles'],
|
||||
filters: [{ name: 'All Files', extensions: ['*'] }],
|
||||
|
||||
@@ -174,8 +174,8 @@
|
||||
import FontIcon from '../icons/FontIcon.svelte';
|
||||
import DictionaryLookupModal from '../modals/DictionaryLookupModal.svelte';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { copyTextToClipboard, extractRowCopiedValue } from '../utility/clipboard';
|
||||
import contextMenu, { getContextMenu, registerMenu } from '../utility/contextMenu';
|
||||
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
||||
@@ -260,7 +260,7 @@
|
||||
}
|
||||
|
||||
export async function reconnect() {
|
||||
await axiosInstance.post('database-connections/refresh', { conid, database });
|
||||
await apiCall('database-connections/refresh', { conid, database });
|
||||
formDisplay.reload();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,25 +4,21 @@
|
||||
|
||||
if (!sql) return null;
|
||||
|
||||
const response = await axiosInstance.request({
|
||||
url: 'database-connections/query-data',
|
||||
method: 'post',
|
||||
params: {
|
||||
conid,
|
||||
database,
|
||||
},
|
||||
data: { sql },
|
||||
const response = await apiCall('database-connections/query-data', {
|
||||
conid,
|
||||
database,
|
||||
sql,
|
||||
});
|
||||
|
||||
if (response.data.errorMessage) return response.data;
|
||||
return response.data.rows[0];
|
||||
if (response.errorMessage) return response;
|
||||
return response.rows[0];
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import ChangeSetFormer from './ChangeSetFormer';
|
||||
import FormView from './FormView.svelte';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let formDisplay;
|
||||
export let changeSetState;
|
||||
@@ -122,42 +118,6 @@
|
||||
$: former = new ChangeSetFormer(rowData, changeSetState, dispatchChangeSet, formDisplay);
|
||||
|
||||
$: 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>
|
||||
|
||||
<FormView
|
||||
{...$$props}
|
||||
{former}
|
||||
isLoading={isLoadingData}
|
||||
{allRowCount}
|
||||
{rowCountBefore}
|
||||
onNavigate={handleNavigate}
|
||||
/>
|
||||
<FormView {...$$props} {former} isLoading={isLoadingData} {allRowCount} {rowCountBefore} onNavigate={handleNavigate} />
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
import DataGridCore from '../datagrid/DataGridCore.svelte';
|
||||
import ImportExportModal from '../modals/ImportExportModal.svelte';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { apiCall } from '../utility/api';
|
||||
import { registerMenu } from '../utility/contextMenu';
|
||||
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
||||
import FreeTableGrider from './FreeTableGrider';
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
export async function exportGrid() {
|
||||
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 = {};
|
||||
initialValues.sourceStorageType = 'jsldata';
|
||||
initialValues.sourceJslId = jslid;
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
|
||||
let isLoading = false;
|
||||
|
||||
const electron = getElectron();
|
||||
const { values } = getFormContext();
|
||||
|
||||
const handleClick = async () => {
|
||||
const files = electron.remote.dialog.showOpenDialogSync(electron.remote.getCurrentWindow(), {
|
||||
const electron = getElectron();
|
||||
const files = await electron.showOpenDialog({
|
||||
properties: ['openFile', 'multiSelections'],
|
||||
filters: getFileFilters($extensions, $values.sourceStorageType),
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import RowsArrayGrider from '../datagrid/RowsArrayGrider';
|
||||
import ErrorInfo from '../elements/ErrorInfo.svelte';
|
||||
import LoadingInfo from '../elements/LoadingInfo.svelte';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let reader;
|
||||
|
||||
@@ -27,14 +27,16 @@
|
||||
}
|
||||
errorMessage = null;
|
||||
isLoading = true;
|
||||
const resp = await axiosInstance.post('runners/load-reader', sourceReader);
|
||||
const resp = await apiCall('runners/load-reader', sourceReader);
|
||||
// @ts-ignore
|
||||
model = resp.data;
|
||||
grider = new RowsArrayGrider(resp.data.rows);
|
||||
model = resp;
|
||||
grider = new RowsArrayGrider(resp.rows);
|
||||
isLoading = false;
|
||||
} catch (err) {
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import ColorSelector from '../forms/ColorSelector.svelte';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { apiCall } from '../utility/api';
|
||||
import { useConnectionColor } from '../utility/useConnectionColor';
|
||||
import ModalBase from './ModalBase.svelte';
|
||||
|
||||
@@ -27,13 +27,13 @@
|
||||
value = e.detail;
|
||||
|
||||
if (database) {
|
||||
axiosInstance.post('connections/update-database', {
|
||||
apiCall('connections/update-database', {
|
||||
conid,
|
||||
database,
|
||||
values: { connectionColor: e.detail },
|
||||
});
|
||||
} else {
|
||||
axiosInstance.post('connections/update', {
|
||||
apiCall('connections/update', {
|
||||
_id: conid,
|
||||
values: { connectionColor: e.detail },
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
import FormTextField from '../forms/FormTextField.svelte';
|
||||
import FontIcon from '../icons/FontIcon.svelte';
|
||||
import { commandsSettings } from '../stores';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { apiCall } from '../utility/api';
|
||||
import KeyboardModal from './KeyboardModal.svelte';
|
||||
import ModalBase from './ModalBase.svelte';
|
||||
import { closeCurrentModal, showModal } from './modalTools';
|
||||
@@ -42,7 +42,7 @@
|
||||
value="OK"
|
||||
on:click={e => {
|
||||
closeCurrentModal();
|
||||
axiosInstance.post('config/update-settings', {
|
||||
apiCall('config/update-settings', {
|
||||
commands: {
|
||||
...$commandsSettings,
|
||||
[command.id]: {
|
||||
@@ -58,7 +58,7 @@
|
||||
value="Reset"
|
||||
on:click={() => {
|
||||
closeCurrentModal();
|
||||
axiosInstance.post('config/update-settings', {
|
||||
apiCall('config/update-settings', {
|
||||
commands: _.omit($commandsSettings, [command.id]),
|
||||
});
|
||||
}}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
import FormProvider from '../forms/FormProvider.svelte';
|
||||
import FormSubmit from '../forms/FormSubmit.svelte';
|
||||
import FontIcon from '../icons/FontIcon.svelte';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import TabControl from '../elements/TabControl.svelte';
|
||||
import ConnectionModalDriverFields from './ConnectionModalDriverFields.svelte';
|
||||
import ConnectionModalSshTunnelFields from './ConnectionModalSshTunnelFields.svelte';
|
||||
@@ -21,6 +20,7 @@
|
||||
import { extensions } from '../stores';
|
||||
import _ from 'lodash';
|
||||
import { getDatabaseFileLabel } from '../utility/getConnectionLabel';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let connection;
|
||||
|
||||
@@ -38,11 +38,11 @@
|
||||
isTesting = true;
|
||||
testIdRef.update(x => x + 1);
|
||||
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;
|
||||
|
||||
isTesting = false;
|
||||
sqlConnectResult = resp.data;
|
||||
sqlConnectResult = resp;
|
||||
}
|
||||
|
||||
function handleCancelTest() {
|
||||
@@ -70,10 +70,9 @@
|
||||
let connection = _.omit(e.detail, omitProps);
|
||||
if (driver?.beforeConnectionSave) connection = driver?.beforeConnectionSave(connection);
|
||||
|
||||
axiosInstance.post('connections/save', connection);
|
||||
apiCall('connections/save', connection);
|
||||
closeCurrentModal();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<FormProviderCore template={FormFieldTemplateLarge} {values}>
|
||||
@@ -156,5 +155,4 @@
|
||||
.error-result {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import { closeCurrentModal, showModal } from './modalTools';
|
||||
import DefineDictionaryDescriptionModal from './DefineDictionaryDescriptionModal.svelte';
|
||||
import ScrollableTableControl from '../elements/ScrollableTableControl.svelte';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { getTableInfo } from '../utility/metadataLoaders';
|
||||
import { getDictionaryDescription } from '../utility/dictionaryDescriptionTools';
|
||||
import { onMount } from 'svelte';
|
||||
@@ -15,6 +14,7 @@
|
||||
import SearchInput from '../elements/SearchInput.svelte';
|
||||
import FormTextField from '../forms/FormTextField.svelte';
|
||||
import _ from 'lodash';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let onConfirm;
|
||||
export let conid;
|
||||
@@ -100,17 +100,13 @@
|
||||
dumpSqlSelect(dmp, select);
|
||||
|
||||
isLoading = true;
|
||||
const response = await axiosInstance.request({
|
||||
url: 'database-connections/query-data',
|
||||
method: 'post',
|
||||
params: {
|
||||
conid,
|
||||
database,
|
||||
},
|
||||
data: { sql: dmp.s },
|
||||
const response = await apiCall('database-connections/query-data', {
|
||||
conid,
|
||||
database,
|
||||
sql: dmp.s,
|
||||
});
|
||||
|
||||
rows = response.data.rows;
|
||||
rows = response.rows;
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
import hasPermission from '../utility/hasPermission';
|
||||
import localforage from 'localforage';
|
||||
import ModalBase from './ModalBase.svelte';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import uuidv1 from 'uuid/v1';
|
||||
import { closeCurrentModal } from './modalTools';
|
||||
import { copyTextToClipboard } from '../utility/clipboard';
|
||||
@@ -14,8 +13,9 @@
|
||||
import FormCheckboxField from '../forms/FormCheckboxField.svelte';
|
||||
import FormValues from '../forms/FormValues.svelte';
|
||||
import FormSelectField from '../forms/FormSelectField.svelte';
|
||||
import FormSubmit from '../forms/FormSubmit.svelte';
|
||||
import FormButton from '../forms/FormButton.svelte';
|
||||
import FormSubmit from '../forms/FormSubmit.svelte';
|
||||
import FormButton from '../forms/FormButton.svelte';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let editingData;
|
||||
export let savingTab;
|
||||
@@ -69,7 +69,7 @@ import FormButton from '../forms/FormButton.svelte';
|
||||
const saveTab = async values => {
|
||||
const data = await getTabSaveData(values);
|
||||
|
||||
axiosInstance.post('files/save', {
|
||||
apiCall('files/save', {
|
||||
folder: 'favorites',
|
||||
file: uuidv1(),
|
||||
format: 'json',
|
||||
@@ -78,18 +78,18 @@ import FormButton from '../forms/FormButton.svelte';
|
||||
};
|
||||
|
||||
const saveFile = async values => {
|
||||
const oldDataResp = await axiosInstance.post('files/load', {
|
||||
const oldDataResp = await apiCall('files/load', {
|
||||
folder: 'favorites',
|
||||
file: editingData.file,
|
||||
format: 'json',
|
||||
});
|
||||
|
||||
axiosInstance.post('files/save', {
|
||||
apiCall('files/save', {
|
||||
folder: 'favorites',
|
||||
file: editingData.file,
|
||||
format: 'json',
|
||||
data: {
|
||||
...oldDataResp.data,
|
||||
...oldDataResp,
|
||||
...values,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
import RunnerOutputFiles from '../query/RunnerOutputFiles.svelte';
|
||||
import SocketMessageView from '../query/SocketMessageView.svelte';
|
||||
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 openNewTab from '../utility/openNewTab';
|
||||
import socket from '../utility/socket';
|
||||
import useEffect from '../utility/useEffect';
|
||||
import WidgetColumnBar from '../widgets/WidgetColumnBar.svelte';
|
||||
import WidgetColumnBarItem from '../widgets/WidgetColumnBarItem.svelte';
|
||||
@@ -67,9 +66,9 @@
|
||||
|
||||
function registerRunnerDone(rid) {
|
||||
if (rid) {
|
||||
socket.on(`runner-done-${rid}`, handleRunnerDone);
|
||||
apiOn(`runner-done-${rid}`, handleRunnerDone);
|
||||
return () => {
|
||||
socket.off(`runner-done-${rid}`, handleRunnerDone);
|
||||
apiOff(`runner-done-${rid}`, handleRunnerDone);
|
||||
};
|
||||
} else {
|
||||
return () => {};
|
||||
@@ -81,8 +80,8 @@
|
||||
const handleRunnerDone = () => {
|
||||
busy = false;
|
||||
if (refreshArchiveFolderRef.get()) {
|
||||
axiosInstance.post('archive/refresh-folders', {});
|
||||
axiosInstance.post('archive/refresh-files', { folder: refreshArchiveFolderRef.get() });
|
||||
apiCall('archive/refresh-folders', {});
|
||||
apiCall('archive/refresh-files', { folder: refreshArchiveFolderRef.get() });
|
||||
$currentArchive = refreshArchiveFolderRef.get();
|
||||
$selectedWidget = 'archive';
|
||||
}
|
||||
@@ -108,8 +107,8 @@
|
||||
const script = await createImpExpScript($extensions, values);
|
||||
executeNumber += 1;
|
||||
let runid = runnerId;
|
||||
const resp = await axiosInstance.post('runners/start', { script });
|
||||
runid = resp.data.runid;
|
||||
const resp = await apiCall('runners/start', { script });
|
||||
runid = resp.runid;
|
||||
runnerId = runid;
|
||||
|
||||
if (values.targetStorageType == 'archive') {
|
||||
@@ -120,7 +119,7 @@
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
axiosInstance.post('runners/cancel', {
|
||||
apiCall('runners/cancel', {
|
||||
runid: runnerId,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
import FormProvider from '../forms/FormProvider.svelte';
|
||||
import FormSubmit from '../forms/FormSubmit.svelte';
|
||||
import FormTextField from '../forms/FormTextField.svelte';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import getElectron from '../utility/getElectron';
|
||||
import ModalBase from './ModalBase.svelte';
|
||||
import { closeCurrentModal } from './modalTools';
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
const handleSubmit = async e => {
|
||||
const { name } = e.detail;
|
||||
await axiosInstance.post('files/save', { folder, file: name, data, format });
|
||||
await apiCall('files/save', { folder, file: name, data, format });
|
||||
closeCurrentModal();
|
||||
if (onSave) {
|
||||
onSave(name, {
|
||||
@@ -38,7 +38,7 @@
|
||||
const parsed = path.parse(filePath);
|
||||
// if (!parsed.ext) filePath += `.${fileExtension}`;
|
||||
|
||||
await axiosInstance.post('files/save-as', { filePath, data, format });
|
||||
await apiCall('files/save-as', { filePath, data, format });
|
||||
closeCurrentModal();
|
||||
|
||||
if (onSave) {
|
||||
@@ -61,8 +61,8 @@
|
||||
<FormStyledButton
|
||||
type="button"
|
||||
value="Save to disk"
|
||||
on:click={() => {
|
||||
const file = electron.remote.dialog.showSaveDialogSync(electron.remote.getCurrentWindow(), {
|
||||
on:click={async () => {
|
||||
const file = await electron.showSaveDialog({
|
||||
filters: [
|
||||
{ name: `${fileExtension.toUpperCase()} files`, extensions: [fileExtension] },
|
||||
{ name: `All files`, extensions: ['*'] },
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
import FontIcon from '../icons/FontIcon.svelte';
|
||||
import SqlEditor from '../query/SqlEditor.svelte';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import createRef from '../utility/createRef';
|
||||
import { useDatabaseInfo } from '../utility/metadataLoaders';
|
||||
import WidgetColumnBar from '../widgets/WidgetColumnBar.svelte';
|
||||
@@ -32,6 +31,7 @@
|
||||
import ErrorInfo from '../elements/ErrorInfo.svelte';
|
||||
import LoadingInfo from '../elements/LoadingInfo.svelte';
|
||||
import { getObjectTypeFieldLabel } from '../utility/common';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let conid;
|
||||
export let database;
|
||||
@@ -86,7 +86,7 @@
|
||||
const loadid = uuidv1();
|
||||
loadRef.set(loadid);
|
||||
busy = true;
|
||||
const response = await axiosInstance.post('database-connections/sql-preview', {
|
||||
const response = await apiCall('database-connections/sql-preview', {
|
||||
conid,
|
||||
database,
|
||||
objects,
|
||||
@@ -96,7 +96,7 @@
|
||||
// newer load exists
|
||||
return;
|
||||
}
|
||||
const { sql, isTruncated, isError, errorMessage } = response.data || {};
|
||||
const { sql, isTruncated, isError, errorMessage } = response || {};
|
||||
|
||||
truncated = isTruncated;
|
||||
if (isError) {
|
||||
@@ -127,7 +127,6 @@
|
||||
);
|
||||
closeCurrentModal();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<FormProviderCore values={valuesStore} template={FormFieldTemplateTiny}>
|
||||
@@ -257,5 +256,4 @@
|
||||
.dbname {
|
||||
color: var(--theme-font-3);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import { closeCurrentModal, showModal } from './modalTools';
|
||||
import DefineDictionaryDescriptionModal from './DefineDictionaryDescriptionModal.svelte';
|
||||
import ScrollableTableControl from '../elements/ScrollableTableControl.svelte';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { getDictionaryDescription } from '../utility/dictionaryDescriptionTools';
|
||||
import { onMount } from 'svelte';
|
||||
import { dumpSqlSelect } from 'dbgate-sqltree';
|
||||
@@ -14,6 +13,7 @@
|
||||
import SearchInput from '../elements/SearchInput.svelte';
|
||||
import FormTextField from '../forms/FormTextField.svelte';
|
||||
import _ from 'lodash';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let onConfirm;
|
||||
export let conid;
|
||||
@@ -34,7 +34,7 @@
|
||||
let checkedKeys = [];
|
||||
|
||||
async function reload() {
|
||||
const dmp = driver.createDumper();
|
||||
const dmp = driver.createDumper();
|
||||
const select = {
|
||||
commandType: 'select',
|
||||
distinct: true,
|
||||
@@ -85,17 +85,13 @@
|
||||
dumpSqlSelect(dmp, select);
|
||||
|
||||
isLoading = true;
|
||||
const response = await axiosInstance.request({
|
||||
url: 'database-connections/query-data',
|
||||
method: 'post',
|
||||
params: {
|
||||
conid,
|
||||
database,
|
||||
},
|
||||
data: { sql: dmp.s },
|
||||
const response = await apiCall('database-connections/query-data', {
|
||||
conid,
|
||||
database,
|
||||
sql: dmp.s,
|
||||
});
|
||||
|
||||
rows = response.data.rows;
|
||||
rows = response.rows;
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,20 +3,14 @@
|
||||
|
||||
import SearchBoxWrapper from '../elements/SearchBoxWrapper.svelte';
|
||||
import SearchInput from '../elements/SearchInput.svelte';
|
||||
import useFetch from '../utility/useFetch';
|
||||
import { useApiCall } from '../utility/api';
|
||||
import WidgetsInnerContainer from '../widgets/WidgetsInnerContainer.svelte';
|
||||
import PluginsList from './PluginsList.svelte';
|
||||
|
||||
let filter = '';
|
||||
let search = '';
|
||||
|
||||
$: plugins = useFetch({
|
||||
url: 'plugins/search',
|
||||
params: {
|
||||
filter: search,
|
||||
},
|
||||
defaultValue: [],
|
||||
});
|
||||
$: plugins = useApiCall('plugins/search', { filter: search }, []);
|
||||
|
||||
const setDebouncedFilter = _.debounce(value => (search = value), 500);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts" context="module">
|
||||
const dbgateEnv = {
|
||||
axios: axiosInstance,
|
||||
apiCall,
|
||||
};
|
||||
|
||||
async function loadPlugins(pluginsDict, installedPlugins) {
|
||||
@@ -14,14 +14,10 @@
|
||||
loaded: false,
|
||||
loadingPackageName: installed.name,
|
||||
});
|
||||
const resp = await axiosInstance.request({
|
||||
method: 'get',
|
||||
url: 'plugins/script',
|
||||
params: {
|
||||
packageName: installed.name,
|
||||
},
|
||||
const resp = await apiCall('plugins/script', {
|
||||
packageName: installed.name,
|
||||
});
|
||||
const module = eval(`${resp.data}; plugin`);
|
||||
const module = eval(`${resp}; plugin`);
|
||||
console.log('Loaded plugin', module);
|
||||
const moduleContent = module.__esModule ? module.default : module;
|
||||
if (moduleContent.initialize) moduleContent.initialize(dbgateEnv);
|
||||
@@ -55,17 +51,16 @@
|
||||
};
|
||||
return extensions;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import _ from 'lodash';
|
||||
import { extensions, loadingPluginStore } from '../stores';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { useInstalledPlugins } from '../utility/metadataLoaders';
|
||||
import { buildFileFormats, buildQuickExports } from './fileformats';
|
||||
import { buildThemes } from './themes';
|
||||
import dbgateTools from 'dbgate-tools';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
let pluginsDict = {};
|
||||
const installedPlugins = useInstalledPlugins();
|
||||
@@ -87,5 +82,4 @@
|
||||
.filter(x => x.content);
|
||||
|
||||
$: $extensions = buildExtensions(plugins);
|
||||
|
||||
</script>
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
import _ from 'lodash';
|
||||
import { handleCommandKeyDown } from '../commands/CommandListener.svelte';
|
||||
import resizeObserver from '../utility/resizeObserver';
|
||||
// @ts-ignore
|
||||
import QueryParserWorker from 'web-worker:./QueryParserWorker';
|
||||
import queryParserWorkerFallback from './queryParserWorkerFallback';
|
||||
|
||||
const EDITOR_ID = `svelte-ace-editor-div:${Math.floor(Math.random() * 10000000000)}`;
|
||||
@@ -138,11 +136,14 @@
|
||||
if (enabled) {
|
||||
if (!queryParserWorker) {
|
||||
try {
|
||||
queryParserWorker = new QueryParserWorker();
|
||||
queryParserWorker = new Worker('build/query-parser-worker.js');
|
||||
// console.log('WORKER', queryParserWorker);
|
||||
queryParserWorker.onmessage = e => {
|
||||
processParserResult(e.data);
|
||||
};
|
||||
} catch (err) {
|
||||
// console.error('WORKER ERROR', err);
|
||||
console.log('WORKER ERROR, using fallback worker', err.message);
|
||||
queryParserWorker = 'fallback';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import JslDataGrid from '../datagrid/JslDataGrid.svelte';
|
||||
import TabControl from '../elements/TabControl.svelte';
|
||||
import { allResultsInOneTabDefault } from '../stores';
|
||||
import socket from '../utility/socket';
|
||||
import { apiOff, apiOn } from '../utility/api';
|
||||
import useEffect from '../utility/useEffect';
|
||||
import AllResultsTab from './AllResultsTab.svelte';
|
||||
|
||||
@@ -66,9 +66,9 @@
|
||||
});
|
||||
function onSession(sid) {
|
||||
if (sid) {
|
||||
socket.on(`session-recordset-${sid}`, handleResultSet);
|
||||
apiOn(`session-recordset-${sid}`, handleResultSet);
|
||||
return () => {
|
||||
socket.off(`session-recordset-${sid}`, handleResultSet);
|
||||
apiOff(`session-recordset-${sid}`, handleResultSet);
|
||||
};
|
||||
}
|
||||
return () => {};
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<script>
|
||||
import ErrorInfo from '../elements/ErrorInfo.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 getElectron from '../utility/getElectron';
|
||||
import resolveApi from '../utility/resolveApi';
|
||||
import socket from '../utility/socket';
|
||||
import useEffect from '../utility/useEffect';
|
||||
|
||||
export let runnerId;
|
||||
@@ -22,9 +21,9 @@
|
||||
|
||||
function registerRunnerDone(rid) {
|
||||
if (rid) {
|
||||
socket.on(`runner-done-${rid}`, handleRunnerDone);
|
||||
apiOn(`runner-done-${rid}`, handleRunnerDone);
|
||||
return () => {
|
||||
socket.off(`runner-done-${rid}`, handleRunnerDone);
|
||||
apiOff(`runner-done-${rid}`, handleRunnerDone);
|
||||
};
|
||||
} else {
|
||||
return () => {};
|
||||
@@ -34,8 +33,8 @@
|
||||
$: $effect;
|
||||
|
||||
const handleRunnerDone = async () => {
|
||||
const resp = await axiosInstance.get(`runners/files?runid=${runnerId}`);
|
||||
files = resp.data;
|
||||
const resp = await apiCall('runners/files', { runid: runnerId });
|
||||
files = resp;
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -78,8 +77,8 @@
|
||||
slot="1"
|
||||
let:row
|
||||
href="#"
|
||||
on:click={() => {
|
||||
const file = electron.remote.dialog.showSaveDialogSync(electron.remote.getCurrentWindow(), {});
|
||||
on:click={async () => {
|
||||
const file = await electron.showSaveDialog({});
|
||||
if (file) {
|
||||
const fs = window.require('fs');
|
||||
fs.copyFile(row.path, file, () => {});
|
||||
@@ -94,7 +93,7 @@
|
||||
let:row
|
||||
href="#"
|
||||
on:click={() => {
|
||||
electron.remote.shell.showItemInFolder(row.path);
|
||||
electron.showItemInFolder(row.path);
|
||||
}}
|
||||
>
|
||||
show
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<script lang="ts">
|
||||
import _ from 'lodash';
|
||||
import ErrorInfo from '../elements/ErrorInfo.svelte';
|
||||
import { apiOff, apiOn } from '../utility/api';
|
||||
import createRef from '../utility/createRef';
|
||||
|
||||
import socket from '../utility/socket';
|
||||
|
||||
import useEffect from '../utility/useEffect';
|
||||
|
||||
import MessageView from './MessageView.svelte';
|
||||
@@ -30,9 +29,9 @@
|
||||
|
||||
$: effect = useEffect(() => {
|
||||
if (eventName) {
|
||||
socket.on(eventName, handleInfo);
|
||||
apiOn(eventName, handleInfo);
|
||||
return () => {
|
||||
socket.off(eventName, handleInfo);
|
||||
apiOff(eventName, handleInfo);
|
||||
};
|
||||
}
|
||||
return () => {};
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
import ModalBase from '../modals/ModalBase.svelte';
|
||||
import { closeCurrentModal } from '../modals/modalTools';
|
||||
import { getCurrentSettings, getVisibleToolbar, getZoomKoef, visibleToolbar, zoomKoef } from '../stores';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
function handleOk(e) {
|
||||
axiosInstance.post(
|
||||
apiCall(
|
||||
'config/update-settings',
|
||||
_.omitBy(e.detail, (v, k) => k.startsWith(':'))
|
||||
);
|
||||
|
||||
@@ -44,7 +44,7 @@ export const activeTab = derived([openedTabs], ([$openedTabs]) => $openedTabs.fi
|
||||
export const recentDatabases = writableWithStorage([], 'recentDatabases');
|
||||
export const pinnedDatabases = writableWithStorage([], 'pinnedDatabases');
|
||||
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 archiveFilesAsDataSheets = writableWithStorage([], 'archiveFilesAsDataSheets');
|
||||
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)
|
||||
);
|
||||
|
||||
const electron = getElectron();
|
||||
|
||||
subscribeCssVariable(selectedWidget, x => (x ? 1 : 0), '--dim-visible-left-panel');
|
||||
subscribeCssVariable(visibleToolbar, x => (x ? 1 : 0), '--dim-visible-toolbar');
|
||||
subscribeCssVariable(leftPanelWidth, x => `${x}px`, '--dim-left-panel-width');
|
||||
@@ -119,9 +117,9 @@ let commandsValue = null;
|
||||
commands.subscribe(value => {
|
||||
commandsValue = value;
|
||||
|
||||
const electron = getElectron();
|
||||
if (electron) {
|
||||
const { ipcRenderer } = electron;
|
||||
ipcRenderer.send('update-commands', JSON.stringify(value));
|
||||
electron.send('update-commands', JSON.stringify(value));
|
||||
}
|
||||
});
|
||||
export const getCommands = () => commandsValue;
|
||||
@@ -132,15 +130,7 @@ activeTab.subscribe(value => {
|
||||
});
|
||||
export const getActiveTab = () => activeTabValue;
|
||||
|
||||
const currentConfigStore = useConfig();
|
||||
let currentConfigValue = null;
|
||||
currentConfigStore.subscribe(value => {
|
||||
currentConfigValue = value;
|
||||
invalidateCommands();
|
||||
if (value.singleDatabase) {
|
||||
currentDatabase.set(value.singleDatabase);
|
||||
}
|
||||
});
|
||||
export const getCurrentConfig = () => currentConfigValue;
|
||||
|
||||
let recentDatabasesValue = null;
|
||||
@@ -163,10 +153,6 @@ currentDatabase.subscribe(value => {
|
||||
export const getCurrentDatabase = () => currentDatabaseValue;
|
||||
|
||||
let currentSettingsValue = null;
|
||||
useSettings().subscribe(value => {
|
||||
currentSettingsValue = value;
|
||||
invalidateCommands();
|
||||
});
|
||||
export const getCurrentSettings = () => currentSettingsValue || {};
|
||||
|
||||
let extensionsValue = null;
|
||||
@@ -180,3 +166,19 @@ openedConnections.subscribe(value => {
|
||||
openedConnectionsValue = value;
|
||||
});
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,16 +6,15 @@
|
||||
import { onMount } from 'svelte';
|
||||
import LoadingInfo from '../elements/LoadingInfo.svelte';
|
||||
import Markdown from '../elements/Markdown.svelte';
|
||||
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
let isLoading = false;
|
||||
let text = null;
|
||||
|
||||
const handleLoad = async () => {
|
||||
isLoading = true;
|
||||
const resp = await axiosInstance.get('config/changelog');
|
||||
text = resp.data;
|
||||
const resp = await apiCall('config/changelog');
|
||||
text = resp;
|
||||
isLoading = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
import LoadingInfo from '../elements/LoadingInfo.svelte';
|
||||
|
||||
import useEditorData from '../query/useEditorData';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { getContextMenu, registerMenu } from '../utility/contextMenu';
|
||||
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
||||
import createUndoReducer from '../utility/createUndoReducer';
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
import { extensions } from '../stores';
|
||||
import CollectionJsonView from '../jsonview/CollectionJsonView.svelte';
|
||||
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
|
||||
import ConfirmNoSqlModal from '../modals/ConfirmNoSqlModal.svelte';
|
||||
@@ -50,6 +49,7 @@
|
||||
import ChangeSetGrider from '../datagrid/ChangeSetGrider';
|
||||
import { setContext } from 'svelte';
|
||||
import _ from 'lodash';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let tabid;
|
||||
export let conid;
|
||||
@@ -91,16 +91,12 @@
|
||||
// $: console.log('LOADED ROWS MONGO', loadedRows);
|
||||
|
||||
async function handleConfirmChange(changeSet) {
|
||||
const resp = await axiosInstance.request({
|
||||
url: 'database-connections/update-collection',
|
||||
method: 'post',
|
||||
params: {
|
||||
conid,
|
||||
database,
|
||||
},
|
||||
data: { changeSet },
|
||||
const resp = await apiCall('database-connections/update-collection', {
|
||||
conid,
|
||||
database,
|
||||
changeSet,
|
||||
});
|
||||
const { errorMessage } = resp.data || {};
|
||||
const { errorMessage } = resp || {};
|
||||
if (errorMessage) {
|
||||
showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage });
|
||||
} else {
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
import SqlEditor from '../query/SqlEditor.svelte';
|
||||
import useEditorData from '../query/useEditorData';
|
||||
import { extensions } from '../stores';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { apiCall } from '../utility/api';
|
||||
import { changeTab } from '../utility/common';
|
||||
import contextMenu, { getContextMenu, registerMenu } from '../utility/contextMenu';
|
||||
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
||||
@@ -228,7 +228,7 @@
|
||||
|
||||
export async function showReport() {
|
||||
saveFileToDisk(async filePath => {
|
||||
await axiosInstance.post('database-connections/generate-db-diff-report', {
|
||||
await apiCall('database-connections/generate-db-diff-report', {
|
||||
filePath,
|
||||
sourceConid: $values?.sourceConid,
|
||||
sourceDatabase: $values?.sourceDatabase,
|
||||
@@ -261,11 +261,11 @@
|
||||
}
|
||||
|
||||
export function refreshModels() {
|
||||
axiosInstance.post('database-connections/sync-model', {
|
||||
apiCall('database-connections/sync-model', {
|
||||
conid: $values?.targetConid,
|
||||
database: $values?.targetDatabase,
|
||||
});
|
||||
axiosInstance.post('database-connections/sync-model', {
|
||||
apiCall('database-connections/sync-model', {
|
||||
conid: $values?.sourceConid,
|
||||
database: $values?.sourceDatabase,
|
||||
});
|
||||
@@ -275,18 +275,13 @@
|
||||
const conid = $values?.targetConid;
|
||||
const database = $values?.targetDatabase;
|
||||
|
||||
const resp = await axiosInstance.request({
|
||||
url: 'database-connections/run-script',
|
||||
method: 'post',
|
||||
params: { conid, database },
|
||||
data: { sql },
|
||||
});
|
||||
const { errorMessage } = resp.data || {};
|
||||
const resp = await apiCall('database-connections/run-script', { conid, database, sql });
|
||||
const { errorMessage } = resp || {};
|
||||
if (errorMessage) {
|
||||
showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage });
|
||||
} else {
|
||||
$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');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,11 +38,11 @@
|
||||
import AceEditor from '../query/AceEditor.svelte';
|
||||
import useEditorData from '../query/useEditorData';
|
||||
import invalidateCommands from '../commands/invalidateCommands';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
|
||||
import { openFavorite } from '../appobj/FavoriteFileAppObject.svelte';
|
||||
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let tabid;
|
||||
export let savedFile;
|
||||
@@ -97,7 +97,7 @@
|
||||
export function save() {
|
||||
try {
|
||||
const data = JSON.parse(getData());
|
||||
axiosInstance.post('files/save', {
|
||||
apiCall('files/save', {
|
||||
file: savedFile,
|
||||
folder: 'favorites',
|
||||
format: 'json',
|
||||
|
||||
@@ -41,8 +41,8 @@
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import SaveArchiveModal from '../modals/SaveArchiveModal.svelte';
|
||||
import useEditorData from '../query/useEditorData';
|
||||
import { apiCall } from '../utility/api';
|
||||
import { markArchiveFileAsDataSheet } from '../utility/archiveTools';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { changeTab } from '../utility/common';
|
||||
import { registerMenu } from '../utility/contextMenu';
|
||||
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
||||
@@ -61,10 +61,7 @@
|
||||
|
||||
const { setEditorData, editorState } = useEditorData({
|
||||
tabid,
|
||||
loadFromArgs:
|
||||
initialArgs && initialArgs.functionName
|
||||
? () => axiosInstance.post('runners/load-reader', initialArgs).then(x => x.data)
|
||||
: null,
|
||||
loadFromArgs: initialArgs && initialArgs.functionName ? () => apiCall('runners/load-reader', initialArgs) : null,
|
||||
onInitialData: value => {
|
||||
dispatchModel({ type: 'reset', value });
|
||||
},
|
||||
@@ -84,7 +81,7 @@
|
||||
}
|
||||
|
||||
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 => ({
|
||||
...tab,
|
||||
title: file,
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
import { onMount } from 'svelte';
|
||||
import LoadingInfo from '../elements/LoadingInfo.svelte';
|
||||
import Markdown from '../elements/Markdown.svelte';
|
||||
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let savedFile;
|
||||
|
||||
@@ -16,12 +15,12 @@
|
||||
|
||||
const handleLoad = async () => {
|
||||
isLoading = true;
|
||||
const resp = await axiosInstance.post('files/load', {
|
||||
const resp = await apiCall('files/load', {
|
||||
folder: 'markdown',
|
||||
file: savedFile,
|
||||
format: 'text',
|
||||
});
|
||||
text = resp.data;
|
||||
text = resp;
|
||||
isLoading = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -7,33 +7,28 @@
|
||||
import FormStyledButton from '../elements/FormStyledButton.svelte';
|
||||
import Markdown from '../elements/Markdown.svelte';
|
||||
import { extractPluginAuthor, extractPluginIcon } from '../plugins/manifestExtractors';
|
||||
import { apiCall, useApiCall } from '../utility/api';
|
||||
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import hasPermission from '../utility/hasPermission';
|
||||
|
||||
import { useInstalledPlugins } from '../utility/metadataLoaders';
|
||||
import useFetch from '../utility/useFetch';
|
||||
|
||||
export let packageName;
|
||||
|
||||
$: installed = useInstalledPlugins();
|
||||
$: info = useFetch({
|
||||
params: { packageName },
|
||||
url: 'plugins/info',
|
||||
defaultValue: null,
|
||||
});
|
||||
$: info = useApiCall('plugins/info', { packageName }, null);
|
||||
$: readme = $info?.readme;
|
||||
$: manifest = $info?.manifest;
|
||||
$: isPackaged = $info?.isPackaged;
|
||||
|
||||
const handleInstall = async () => {
|
||||
axiosInstance.post('plugins/install', { packageName });
|
||||
apiCall('plugins/install', { packageName });
|
||||
};
|
||||
const handleUninstall = async () => {
|
||||
axiosInstance.post('plugins/uninstall', { packageName });
|
||||
apiCall('plugins/uninstall', { packageName });
|
||||
};
|
||||
const handleUpgrade = async () => {
|
||||
axiosInstance.post('plugins/upgrade', { packageName });
|
||||
apiCall('plugins/upgrade', { packageName });
|
||||
};
|
||||
|
||||
$: installedFound = $installed?.find(x => x.name == packageName);
|
||||
|
||||
@@ -21,10 +21,8 @@
|
||||
import SqlEditor from '../query/SqlEditor.svelte';
|
||||
import useEditorData from '../query/useEditorData';
|
||||
import { extensions } from '../stores';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { changeTab } from '../utility/common';
|
||||
import { useConnectionInfo } from '../utility/metadataLoaders';
|
||||
import socket from '../utility/socket';
|
||||
import SocketMessageView from '../query/SocketMessageView.svelte';
|
||||
import useEffect from '../utility/useEffect';
|
||||
import ResultTabs from '../query/ResultTabs.svelte';
|
||||
@@ -38,6 +36,7 @@
|
||||
import QueryDesignColumns from '../elements/QueryDesignColumns.svelte';
|
||||
import useTimerLabel from '../utility/useTimerLabel';
|
||||
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
||||
import { apiCall, apiOff, apiOn } from '../utility/api';
|
||||
|
||||
export let tabid;
|
||||
export let conid;
|
||||
@@ -62,9 +61,9 @@
|
||||
});
|
||||
function onSession(sid) {
|
||||
if (sid) {
|
||||
socket.on(`session-done-${sid}`, handleSessionDone);
|
||||
apiOn(`session-done-${sid}`, handleSessionDone);
|
||||
return () => {
|
||||
socket.off(`session-done-${sid}`, handleSessionDone);
|
||||
apiOff(`session-done-${sid}`, handleSessionDone);
|
||||
};
|
||||
}
|
||||
return () => {};
|
||||
@@ -105,23 +104,23 @@
|
||||
|
||||
let sesid = sessionId;
|
||||
if (!sesid) {
|
||||
const resp = await axiosInstance.post('sessions/create', {
|
||||
const resp = await apiCall('sessions/create', {
|
||||
conid,
|
||||
database,
|
||||
});
|
||||
sesid = resp.data.sesid;
|
||||
sesid = resp.sesid;
|
||||
sessionId = sesid;
|
||||
}
|
||||
busy = true;
|
||||
timerLabel.start();
|
||||
await axiosInstance.post('sessions/execute-query', {
|
||||
await apiCall('sessions/execute-query', {
|
||||
sesid,
|
||||
sql: sqlPreview,
|
||||
});
|
||||
}
|
||||
|
||||
export async function kill() {
|
||||
await axiosInstance.post('sessions/kill', {
|
||||
await apiCall('sessions/kill', {
|
||||
sesid: sessionId,
|
||||
});
|
||||
sessionId = null;
|
||||
|
||||
@@ -52,10 +52,8 @@
|
||||
import useEditorData from '../query/useEditorData';
|
||||
import { extensions } from '../stores';
|
||||
import applyScriptTemplate from '../utility/applyScriptTemplate';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { changeTab } from '../utility/common';
|
||||
import { getDatabaseInfo, useConnectionInfo } from '../utility/metadataLoaders';
|
||||
import socket from '../utility/socket';
|
||||
import SocketMessageView from '../query/SocketMessageView.svelte';
|
||||
import useEffect from '../utility/useEffect';
|
||||
import ResultTabs from '../query/ResultTabs.svelte';
|
||||
@@ -69,6 +67,7 @@
|
||||
import AceEditor from '../query/AceEditor.svelte';
|
||||
import StatusBarTabItem from '../widgets/StatusBarTabItem.svelte';
|
||||
import { showSnackbarError } from '../utility/snackbar';
|
||||
import { apiCall, apiOff, apiOn } from '../utility/api';
|
||||
|
||||
export let tabid;
|
||||
export let conid;
|
||||
@@ -95,9 +94,9 @@
|
||||
});
|
||||
function onSession(sid) {
|
||||
if (sid) {
|
||||
socket.on(`session-done-${sid}`, handleSessionDone);
|
||||
apiOn(`session-done-${sid}`, handleSessionDone);
|
||||
return () => {
|
||||
socket.off(`session-done-${sid}`, handleSessionDone);
|
||||
apiOff(`session-done-${sid}`, handleSessionDone);
|
||||
};
|
||||
}
|
||||
return () => {};
|
||||
@@ -150,20 +149,20 @@
|
||||
|
||||
let sesid = sessionId;
|
||||
if (!sesid) {
|
||||
const resp = await axiosInstance.post('sessions/create', {
|
||||
const resp = await apiCall('sessions/create', {
|
||||
conid,
|
||||
database,
|
||||
});
|
||||
sesid = resp.data.sesid;
|
||||
sesid = resp.sesid;
|
||||
sessionId = sesid;
|
||||
}
|
||||
busy = true;
|
||||
timerLabel.start();
|
||||
await axiosInstance.post('sessions/execute-query', {
|
||||
await apiCall('sessions/execute-query', {
|
||||
sesid,
|
||||
sql,
|
||||
});
|
||||
await axiosInstance.post('query-history/write', {
|
||||
await apiCall('query-history/write', {
|
||||
data: {
|
||||
sql,
|
||||
conid,
|
||||
@@ -184,7 +183,7 @@
|
||||
}
|
||||
|
||||
export async function kill() {
|
||||
await axiosInstance.post('sessions/kill', {
|
||||
await apiCall('sessions/kill', {
|
||||
sesid: sessionId,
|
||||
});
|
||||
sessionId = null;
|
||||
|
||||
@@ -48,12 +48,11 @@
|
||||
import AceEditor from '../query/AceEditor.svelte';
|
||||
import RunnerOutputPane from '../query/RunnerOutputPane.svelte';
|
||||
import useEditorData from '../query/useEditorData';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { apiCall, apiOff, apiOn } from '../utility/api';
|
||||
import { copyTextToClipboard } from '../utility/clipboard';
|
||||
import { changeTab } from '../utility/common';
|
||||
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
||||
import { showSnackbarError } from '../utility/snackbar';
|
||||
import socket from '../utility/socket';
|
||||
import useEffect from '../utility/useEffect';
|
||||
import useTimerLabel from '../utility/useTimerLabel';
|
||||
|
||||
@@ -101,9 +100,9 @@
|
||||
|
||||
function registerRunnerDone(rid) {
|
||||
if (rid) {
|
||||
socket.on(`runner-done-${rid}`, handleRunnerDone);
|
||||
apiOn(`runner-done-${rid}`, handleRunnerDone);
|
||||
return () => {
|
||||
socket.off(`runner-done-${rid}`, handleRunnerDone);
|
||||
apiOff(`runner-done-${rid}`, handleRunnerDone);
|
||||
};
|
||||
} else {
|
||||
return () => {};
|
||||
@@ -140,8 +139,8 @@
|
||||
}
|
||||
|
||||
export async function copyNodeScript() {
|
||||
const resp = await axiosInstance.post('runners/get-node-script', { script: getActiveScript() });
|
||||
copyTextToClipboard(resp.data);
|
||||
const resp = await apiCall('runners/get-node-script', { script: getActiveScript() });
|
||||
copyTextToClipboard(resp);
|
||||
}
|
||||
|
||||
// export function openWizardEnabled() {
|
||||
@@ -172,10 +171,10 @@
|
||||
executeNumber += 1;
|
||||
|
||||
let runid = runnerId;
|
||||
const resp = await axiosInstance.post('runners/start', {
|
||||
const resp = await apiCall('runners/start', {
|
||||
script: getActiveScript(),
|
||||
});
|
||||
runid = resp.data.runid;
|
||||
runid = resp.runid;
|
||||
runnerId = runid;
|
||||
busy = true;
|
||||
timerLabel.start();
|
||||
@@ -186,7 +185,7 @@
|
||||
}
|
||||
|
||||
export function kill() {
|
||||
axiosInstance.post('runners/cancel', {
|
||||
apiCall('runners/cancel', {
|
||||
runid: runnerId,
|
||||
});
|
||||
timerLabel.stop();
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
import { writable } from 'svelte/store';
|
||||
import createUndoReducer from '../utility/createUndoReducer';
|
||||
import invalidateCommands from '../commands/invalidateCommands';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
|
||||
import { useConnectionInfo, useDatabaseInfo } from '../utility/metadataLoaders';
|
||||
@@ -53,6 +52,7 @@
|
||||
import openNewTab from '../utility/openNewTab';
|
||||
import { getBoolSettingsValue } from '../settings/settingsTools';
|
||||
import { setContext } from 'svelte';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let tabid;
|
||||
export let conid;
|
||||
@@ -70,16 +70,8 @@
|
||||
const [changeSetStore, dispatchChangeSet] = createUndoReducer(createChangeSet());
|
||||
|
||||
async function handleConfirmSql(sql) {
|
||||
const resp = await axiosInstance.request({
|
||||
url: 'database-connections/run-script',
|
||||
method: 'post',
|
||||
params: {
|
||||
conid,
|
||||
database,
|
||||
},
|
||||
data: { sql },
|
||||
});
|
||||
const { errorMessage } = resp.data || {};
|
||||
const resp = await apiCall('database-connections/run-script', { conid, database, sql });
|
||||
const { errorMessage } = resp || {};
|
||||
if (errorMessage) {
|
||||
showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage });
|
||||
} else {
|
||||
|
||||
@@ -51,13 +51,13 @@
|
||||
import { useConnectionInfo, useDatabaseInfo, useDbCore } from '../utility/metadataLoaders';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import ConfirmSqlModal from '../modals/ConfirmSqlModal.svelte';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
|
||||
import { showSnackbarSuccess } from '../utility/snackbar';
|
||||
import InputTextModal from '../modals/InputTextModal.svelte';
|
||||
import { changeTab } from '../utility/common';
|
||||
import StatusBarTabItem from '../widgets/StatusBarTabItem.svelte';
|
||||
import openNewTab from '../utility/openNewTab';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export let tabid;
|
||||
export let conid;
|
||||
@@ -130,16 +130,8 @@
|
||||
}
|
||||
|
||||
async function handleConfirmSql(sql, createTableName) {
|
||||
const resp = await axiosInstance.request({
|
||||
url: 'database-connections/run-script',
|
||||
method: 'post',
|
||||
params: {
|
||||
conid,
|
||||
database,
|
||||
},
|
||||
data: { sql },
|
||||
});
|
||||
const { errorMessage } = resp.data || {};
|
||||
const resp = await apiCall('database-connections/run-script', { conid, database, sql });
|
||||
const { errorMessage } = resp || {};
|
||||
if (errorMessage) {
|
||||
showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage });
|
||||
} 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');
|
||||
clearEditorData();
|
||||
}
|
||||
}
|
||||
|
||||
export async function reset() {
|
||||
await axiosInstance.post('database-connections/sync-model', { conid, database });
|
||||
await apiCall('database-connections/sync-model', { conid, database });
|
||||
clearEditorData();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import localforage from 'localforage';
|
||||
import _ from 'lodash';
|
||||
import { openedTabs } from '../stores';
|
||||
import { getLocalStorage, setLocalStorage } from './storageCache';
|
||||
|
||||
let counter = 0;
|
||||
|
||||
@@ -5,7 +5,7 @@ import { showModal } from '../modals/modalTools';
|
||||
import { getExtensions } from '../stores';
|
||||
import { getConnectionInfo, getDatabaseInfo } from './metadataLoaders';
|
||||
import ConfirmSqlModal from '../modals/ConfirmSqlModal.svelte';
|
||||
import axiosInstance from './axiosInstance';
|
||||
import { apiCall } from './api';
|
||||
|
||||
export async function alterDatabaseDialog(conid, database, updateFunc) {
|
||||
const conn = await getConnectionInfo({ conid });
|
||||
@@ -21,16 +21,8 @@ export async function alterDatabaseDialog(conid, database, updateFunc) {
|
||||
sql,
|
||||
recreates,
|
||||
onConfirm: async () => {
|
||||
const resp = await axiosInstance.request({
|
||||
url: 'database-connections/run-script',
|
||||
method: 'post',
|
||||
params: {
|
||||
conid,
|
||||
database,
|
||||
},
|
||||
data: { sql },
|
||||
});
|
||||
await axiosInstance.post('database-connections/sync-model', { conid, database });
|
||||
const resp = await apiCall('database-connections/run-script', { conid, database, sql });
|
||||
await apiCall('database-connections/sync-model', { conid, database });
|
||||
},
|
||||
engine: driver.engine,
|
||||
});
|
||||
|
||||
89
packages/web/src/utility/api.ts
Normal file
89
packages/web/src/utility/api.ts
Normal 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
Reference in New Issue
Block a user