dbgate-api 4.7.0 → 4.7.3-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/src/controllers/apps.js +13 -0
- package/src/controllers/config.js +46 -21
- package/src/controllers/databaseConnections.js +1 -1
- package/src/controllers/files.js +3 -2
- package/src/controllers/serverConnections.js +1 -1
- package/src/currentVersion.js +2 -2
- package/src/main.js +9 -29
- package/src/shell/copyStream.js +36 -7
- package/src/utility/ColumnMapTransformStream.js +21 -0
- package/src/utility/freeTableStorage.js +1 -1
- package/src/utility/getExpressPath.js +10 -0
- package/src/utility/socket.js +1 -0
- package/src/utility/useController.js +2 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dbgate-api",
|
|
3
3
|
"main": "src/index.js",
|
|
4
|
-
"version": "4.7.
|
|
4
|
+
"version": "4.7.3-alpha.2",
|
|
5
5
|
"homepage": "https://dbgate.org/",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"compare-versions": "^3.6.0",
|
|
26
26
|
"cors": "^2.8.5",
|
|
27
27
|
"cross-env": "^6.0.3",
|
|
28
|
-
"dbgate-query-splitter": "^4.7.
|
|
29
|
-
"dbgate-sqltree": "^4.7.
|
|
30
|
-
"dbgate-tools": "^4.7.
|
|
28
|
+
"dbgate-query-splitter": "^4.7.3-alpha.2",
|
|
29
|
+
"dbgate-sqltree": "^4.7.3-alpha.2",
|
|
30
|
+
"dbgate-tools": "^4.7.3-alpha.2",
|
|
31
31
|
"diff": "^5.0.0",
|
|
32
32
|
"diff2html": "^3.4.13",
|
|
33
33
|
"eslint": "^6.8.0",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@types/fs-extra": "^9.0.11",
|
|
65
65
|
"@types/lodash": "^4.14.149",
|
|
66
|
-
"dbgate-types": "^4.7.
|
|
66
|
+
"dbgate-types": "^4.7.3-alpha.2",
|
|
67
67
|
"env-cmd": "^10.1.0",
|
|
68
68
|
"node-loader": "^1.0.2",
|
|
69
69
|
"nodemon": "^2.0.2",
|
package/src/controllers/apps.js
CHANGED
|
@@ -27,6 +27,7 @@ module.exports = {
|
|
|
27
27
|
|
|
28
28
|
files_meta: true,
|
|
29
29
|
async files({ folder }) {
|
|
30
|
+
if (!folder) return [];
|
|
30
31
|
const dir = path.join(appdir(), folder);
|
|
31
32
|
if (!(await fs.exists(dir))) return [];
|
|
32
33
|
const files = await fs.readdir(dir);
|
|
@@ -264,4 +265,16 @@ module.exports = {
|
|
|
264
265
|
|
|
265
266
|
return true;
|
|
266
267
|
},
|
|
268
|
+
|
|
269
|
+
createConfigFile_meta: true,
|
|
270
|
+
async createConfigFile({ appFolder, fileName, content }) {
|
|
271
|
+
const file = path.join(appdir(), appFolder, fileName);
|
|
272
|
+
if (!(await fs.exists(file))) {
|
|
273
|
+
await fs.writeFile(file, JSON.stringify(content, undefined, 2));
|
|
274
|
+
socket.emitChanged(`app-files-changed-${appFolder}`);
|
|
275
|
+
socket.emitChanged('used-apps-changed');
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
return false;
|
|
279
|
+
},
|
|
267
280
|
};
|
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
const fs = require('fs-extra');
|
|
2
|
+
const os = require('os');
|
|
2
3
|
const path = require('path');
|
|
3
4
|
const axios = require('axios');
|
|
4
5
|
const { datadir } = require('../utility/directories');
|
|
5
6
|
const hasPermission = require('../utility/hasPermission');
|
|
6
7
|
const socket = require('../utility/socket');
|
|
7
8
|
const _ = require('lodash');
|
|
9
|
+
const AsyncLock = require('async-lock');
|
|
8
10
|
|
|
9
11
|
const currentVersion = require('../currentVersion');
|
|
10
12
|
const platformInfo = require('../utility/platformInfo');
|
|
11
13
|
const connections = require('../controllers/connections');
|
|
12
14
|
|
|
15
|
+
const lock = new AsyncLock();
|
|
16
|
+
|
|
13
17
|
module.exports = {
|
|
14
|
-
settingsValue: {},
|
|
18
|
+
// settingsValue: {},
|
|
15
19
|
|
|
16
|
-
async _init() {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
},
|
|
20
|
+
// async _init() {
|
|
21
|
+
// try {
|
|
22
|
+
// this.settingsValue = JSON.parse(await fs.readFile(path.join(datadir(), 'settings.json'), { encoding: 'utf-8' }));
|
|
23
|
+
// } catch (err) {
|
|
24
|
+
// this.settingsValue = {};
|
|
25
|
+
// }
|
|
26
|
+
// },
|
|
23
27
|
|
|
24
28
|
get_meta: true,
|
|
25
29
|
async get() {
|
|
@@ -40,24 +44,45 @@ module.exports = {
|
|
|
40
44
|
|
|
41
45
|
getSettings_meta: true,
|
|
42
46
|
async getSettings() {
|
|
43
|
-
|
|
47
|
+
try {
|
|
48
|
+
return this.fillMissingSettings(
|
|
49
|
+
JSON.parse(await fs.readFile(path.join(datadir(), 'settings.json'), { encoding: 'utf-8' }))
|
|
50
|
+
);
|
|
51
|
+
} catch (err) {
|
|
52
|
+
return this.fillMissingSettings({});
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
fillMissingSettings(value) {
|
|
57
|
+
const res = {
|
|
58
|
+
...value,
|
|
59
|
+
};
|
|
60
|
+
if (value['app.useNativeMenu'] !== true && value['app.useNativeMenu'] !== false) {
|
|
61
|
+
res['app.useNativeMenu'] = os.platform() == 'darwin' ? true : false;
|
|
62
|
+
}
|
|
63
|
+
return res;
|
|
44
64
|
},
|
|
45
65
|
|
|
46
66
|
updateSettings_meta: true,
|
|
47
67
|
async updateSettings(values) {
|
|
48
68
|
if (!hasPermission(`settings/change`)) return false;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
69
|
+
|
|
70
|
+
const res = await lock.acquire('update', async () => {
|
|
71
|
+
const currentValue = await this.getSettings();
|
|
72
|
+
try {
|
|
73
|
+
const updated = {
|
|
74
|
+
...currentValue,
|
|
75
|
+
...values,
|
|
76
|
+
};
|
|
77
|
+
await fs.writeFile(path.join(datadir(), 'settings.json'), JSON.stringify(updated, undefined, 2));
|
|
78
|
+
// this.settingsValue = updated;
|
|
79
|
+
socket.emitChanged(`settings-changed`);
|
|
80
|
+
return updated;
|
|
81
|
+
} catch (err) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return res;
|
|
61
86
|
},
|
|
62
87
|
|
|
63
88
|
changelog_meta: true,
|
|
@@ -110,7 +110,7 @@ module.exports = {
|
|
|
110
110
|
msgtype: 'connect',
|
|
111
111
|
connection: { ...connection, database },
|
|
112
112
|
structure: lastClosed ? lastClosed.structure : null,
|
|
113
|
-
globalSettings: config.
|
|
113
|
+
globalSettings: await config.getSettings(),
|
|
114
114
|
});
|
|
115
115
|
return newOpened;
|
|
116
116
|
},
|
package/src/controllers/files.js
CHANGED
|
@@ -98,6 +98,7 @@ module.exports = {
|
|
|
98
98
|
const app = folder.substring('app:'.length);
|
|
99
99
|
await fs.writeFile(path.join(appdir(), app, file), serialize(format, data));
|
|
100
100
|
socket.emitChanged(`app-files-changed-${app}`);
|
|
101
|
+
socket.emitChanged('used-apps-changed');
|
|
101
102
|
apps.emitChangedDbApp(folder);
|
|
102
103
|
return true;
|
|
103
104
|
} else {
|
|
@@ -141,8 +142,8 @@ module.exports = {
|
|
|
141
142
|
},
|
|
142
143
|
|
|
143
144
|
generateUploadsFile_meta: true,
|
|
144
|
-
async generateUploadsFile() {
|
|
145
|
-
const fileName = `${uuidv1()}
|
|
145
|
+
async generateUploadsFile({ extension }) {
|
|
146
|
+
const fileName = `${uuidv1()}.${extension || 'html'}`;
|
|
146
147
|
return {
|
|
147
148
|
fileName,
|
|
148
149
|
filePath: path.join(uploadsdir(), fileName),
|
|
@@ -69,7 +69,7 @@ module.exports = {
|
|
|
69
69
|
if (newOpened.disconnected) return;
|
|
70
70
|
this.close(conid, false);
|
|
71
71
|
});
|
|
72
|
-
subprocess.send({ msgtype: 'connect', ...connection, globalSettings: config.
|
|
72
|
+
subprocess.send({ msgtype: 'connect', ...connection, globalSettings: await config.getSettings() });
|
|
73
73
|
return newOpened;
|
|
74
74
|
});
|
|
75
75
|
return res;
|
package/src/currentVersion.js
CHANGED
package/src/main.js
CHANGED
|
@@ -28,8 +28,7 @@ const queryHistory = require('./controllers/queryHistory');
|
|
|
28
28
|
|
|
29
29
|
const { rundir } = require('./utility/directories');
|
|
30
30
|
const platformInfo = require('./utility/platformInfo');
|
|
31
|
-
|
|
32
|
-
let checkLocalhostOrigin = null;
|
|
31
|
+
const getExpressPath = require('./utility/getExpressPath');
|
|
33
32
|
|
|
34
33
|
function start() {
|
|
35
34
|
// console.log('process.argv', process.argv);
|
|
@@ -50,32 +49,13 @@ function start() {
|
|
|
50
49
|
);
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
app.use(function (req, res, next) {
|
|
54
|
-
if (checkLocalhostOrigin) {
|
|
55
|
-
if (
|
|
56
|
-
req.headers.origin &&
|
|
57
|
-
req.headers.origin != checkLocalhostOrigin &&
|
|
58
|
-
req.headers.origin != `http://${checkLocalhostOrigin}`
|
|
59
|
-
) {
|
|
60
|
-
console.log('API origin check FAILED');
|
|
61
|
-
console.log('HEADERS', { ...req.headers, authorization: '***' });
|
|
62
|
-
return res.status(403).json({ error: 'Not authorized!' });
|
|
63
|
-
}
|
|
64
|
-
if (!req.headers.origin && req.headers.host != checkLocalhostOrigin) {
|
|
65
|
-
console.log('API host check FAILED');
|
|
66
|
-
console.log('HEADERS', { ...req.headers, authorization: '***' });
|
|
67
|
-
return res.status(403).json({ error: 'Not authorized!' });
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
next();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
52
|
app.use(cors());
|
|
74
53
|
|
|
75
|
-
app.get('/stream', async function (req, res) {
|
|
54
|
+
app.get(getExpressPath('/stream'), async function (req, res) {
|
|
76
55
|
res.set({
|
|
77
56
|
'Cache-Control': 'no-cache',
|
|
78
57
|
'Content-Type': 'text/event-stream',
|
|
58
|
+
'X-Accel-Buffering': 'no',
|
|
79
59
|
Connection: 'keep-alive',
|
|
80
60
|
});
|
|
81
61
|
res.flushHeaders();
|
|
@@ -88,7 +68,7 @@ function start() {
|
|
|
88
68
|
app.use(bodyParser.json({ limit: '50mb' }));
|
|
89
69
|
|
|
90
70
|
app.use(
|
|
91
|
-
'/uploads',
|
|
71
|
+
getExpressPath('/uploads'),
|
|
92
72
|
fileUpload({
|
|
93
73
|
limits: { fileSize: 4 * 1024 * 1024 },
|
|
94
74
|
})
|
|
@@ -100,21 +80,21 @@ function start() {
|
|
|
100
80
|
// app.use('/pages', express.static(process.env.PAGES_DIRECTORY));
|
|
101
81
|
// }
|
|
102
82
|
|
|
103
|
-
app.use('/runners/data', express.static(rundir()));
|
|
83
|
+
app.use(getExpressPath('/runners/data'), express.static(rundir()));
|
|
104
84
|
|
|
105
85
|
if (platformInfo.isDocker) {
|
|
106
86
|
// server static files inside docker container
|
|
107
|
-
app.use(express.static('/home/dbgate-docker/public'));
|
|
87
|
+
app.use(getExpressPath('/'), express.static('/home/dbgate-docker/public'));
|
|
108
88
|
} else {
|
|
109
89
|
if (!platformInfo.isNpmDist) {
|
|
110
|
-
app.get('/', (req, res) => {
|
|
90
|
+
app.get(getExpressPath('/'), (req, res) => {
|
|
111
91
|
res.send('DbGate API');
|
|
112
92
|
});
|
|
113
93
|
}
|
|
114
94
|
}
|
|
115
95
|
|
|
116
96
|
if (platformInfo.isNpmDist) {
|
|
117
|
-
app.use(express.static(path.join(__dirname, '../../dbgate-web/public')));
|
|
97
|
+
app.use(getExpressPath('/'), express.static(path.join(__dirname, '../../dbgate-web/public')));
|
|
118
98
|
getPort({ port: 5000 }).then(port => {
|
|
119
99
|
server.listen(port, () => {
|
|
120
100
|
console.log(`DbGate API listening on port ${port}`);
|
|
@@ -165,4 +145,4 @@ function initializeElectronSender(electronSender) {
|
|
|
165
145
|
socket.setElectronSender(electronSender);
|
|
166
146
|
}
|
|
167
147
|
|
|
168
|
-
module.exports = { start, useAllControllers, initializeElectronSender };
|
|
148
|
+
module.exports = { start, useAllControllers, initializeElectronSender, configController: config };
|
package/src/shell/copyStream.js
CHANGED
|
@@ -1,18 +1,47 @@
|
|
|
1
1
|
const EnsureStreamHeaderStream = require('../utility/EnsureStreamHeaderStream');
|
|
2
|
+
const Stream = require('stream');
|
|
3
|
+
const ColumnMapTransformStream = require('../utility/ColumnMapTransformStream');
|
|
4
|
+
|
|
5
|
+
function copyStream(input, output, options) {
|
|
6
|
+
const { columns } = options || {};
|
|
7
|
+
|
|
8
|
+
const transforms = [];
|
|
9
|
+
if (columns) {
|
|
10
|
+
transforms.push(new ColumnMapTransformStream(columns));
|
|
11
|
+
}
|
|
12
|
+
if (output.requireFixedStructure) {
|
|
13
|
+
transforms.push(new EnsureStreamHeaderStream());
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// return new Promise((resolve, reject) => {
|
|
17
|
+
// Stream.pipeline(input, ...transforms, output, err => {
|
|
18
|
+
// if (err) {
|
|
19
|
+
// reject(err);
|
|
20
|
+
// } else {
|
|
21
|
+
// resolve();
|
|
22
|
+
// }
|
|
23
|
+
// });
|
|
24
|
+
// });
|
|
2
25
|
|
|
3
|
-
function copyStream(input, output) {
|
|
4
26
|
return new Promise((resolve, reject) => {
|
|
5
27
|
const finisher = output['finisher'] || output;
|
|
6
28
|
finisher.on('finish', resolve);
|
|
7
29
|
finisher.on('error', reject);
|
|
8
30
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} else {
|
|
14
|
-
input.pipe(output);
|
|
31
|
+
let lastStream = input;
|
|
32
|
+
for (const tran of transforms) {
|
|
33
|
+
lastStream.pipe(tran);
|
|
34
|
+
lastStream = tran;
|
|
15
35
|
}
|
|
36
|
+
lastStream.pipe(output);
|
|
37
|
+
|
|
38
|
+
// if (output.requireFixedStructure) {
|
|
39
|
+
// const ensureHeader = new EnsureStreamHeaderStream();
|
|
40
|
+
// input.pipe(ensureHeader);
|
|
41
|
+
// ensureHeader.pipe(output);
|
|
42
|
+
// } else {
|
|
43
|
+
// input.pipe(output);
|
|
44
|
+
// }
|
|
16
45
|
});
|
|
17
46
|
}
|
|
18
47
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const stream = require('stream');
|
|
2
|
+
const { transformRowUsingColumnMap } = require('dbgate-tools');
|
|
3
|
+
|
|
4
|
+
class ColumnMapTransformStream extends stream.Transform {
|
|
5
|
+
constructor(columns) {
|
|
6
|
+
super({ objectMode: true });
|
|
7
|
+
this.columns = columns;
|
|
8
|
+
}
|
|
9
|
+
_transform(chunk, encoding, done) {
|
|
10
|
+
if (chunk.__isStreamHeader) {
|
|
11
|
+
// skip stream header
|
|
12
|
+
done();
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
this.push(transformRowUsingColumnMap(chunk, this.columns));
|
|
17
|
+
done();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = ColumnMapTransformStream;
|
|
@@ -3,7 +3,7 @@ const fs = require('fs-extra');
|
|
|
3
3
|
async function saveFreeTableData(file, data) {
|
|
4
4
|
const { structure, rows } = data;
|
|
5
5
|
const fileStream = fs.createWriteStream(file);
|
|
6
|
-
await fileStream.write(JSON.stringify(structure) + '\n');
|
|
6
|
+
await fileStream.write(JSON.stringify({ __isStreamHeader: true, ...structure }) + '\n');
|
|
7
7
|
for (const row of rows) {
|
|
8
8
|
await fileStream.write(JSON.stringify(row) + '\n');
|
|
9
9
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
function getExpressPath(path) {
|
|
2
|
+
path = path.replace(/\/*$/, '').replace(/^\/*/, '');
|
|
3
|
+
const root = (process.env.WEB_ROOT || '').replace(/^\/*/, '').replace(/\/*$/, '');
|
|
4
|
+
if (root) {
|
|
5
|
+
return `/${root}/${path}`;
|
|
6
|
+
}
|
|
7
|
+
return `/${path}`;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
module.exports = getExpressPath;
|
package/src/utility/socket.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
2
|
const express = require('express');
|
|
3
|
+
const getExpressPath = require('./getExpressPath');
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* @param {string} route
|
|
@@ -74,6 +75,6 @@ module.exports = function useController(app, electron, route, controller) {
|
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
if (app) {
|
|
77
|
-
app.use(route, router);
|
|
78
|
+
app.use(getExpressPath(route), router);
|
|
78
79
|
}
|
|
79
80
|
};
|