dbgate-api 4.6.3 → 4.7.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 +4 -0
- package/src/controllers/archive.js +7 -0
- package/src/controllers/config.js +46 -21
- package/src/controllers/databaseConnections.js +3 -2
- package/src/controllers/jsldata.js +22 -3
- package/src/controllers/queryHistory.js +1 -1
- package/src/controllers/serverConnections.js +1 -1
- package/src/currentVersion.js +2 -2
- package/src/main.js +9 -29
- package/src/proc/databaseConnectionProcess.js +7 -1
- package/src/shell/copyStream.js +8 -3
- package/src/shell/jsonArrayWriter.js +1 -4
- package/src/shell/jsonLinesReader.js +7 -7
- package/src/shell/jsonLinesWriter.js +1 -5
- package/src/shell/sqlDataWriter.js +1 -5
- package/src/utility/EnsureStreamHeaderStream.js +1 -5
- package/src/utility/JsonLinesDatastore.js +26 -6
- package/src/utility/getExpressPath.js +10 -0
- package/src/utility/socket.js +4 -2
- package/src/utility/useController.js +2 -1
- package/webpack.config.js +7 -4
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dbgate-api",
|
|
3
3
|
"main": "src/index.js",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.7.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.
|
|
29
|
-
"dbgate-sqltree": "^4.
|
|
30
|
-
"dbgate-tools": "^4.
|
|
28
|
+
"dbgate-query-splitter": "^4.7.2",
|
|
29
|
+
"dbgate-sqltree": "^4.7.2",
|
|
30
|
+
"dbgate-tools": "^4.7.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.
|
|
66
|
+
"dbgate-types": "^4.7.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
|
@@ -21,11 +21,13 @@ module.exports = {
|
|
|
21
21
|
const name = await this.getNewAppFolder({ name: folder });
|
|
22
22
|
await fs.mkdir(path.join(appdir(), name));
|
|
23
23
|
socket.emitChanged('app-folders-changed');
|
|
24
|
+
this.emitChangedDbApp(folder);
|
|
24
25
|
return name;
|
|
25
26
|
},
|
|
26
27
|
|
|
27
28
|
files_meta: true,
|
|
28
29
|
async files({ folder }) {
|
|
30
|
+
if (!folder) return [];
|
|
29
31
|
const dir = path.join(appdir(), folder);
|
|
30
32
|
if (!(await fs.exists(dir))) return [];
|
|
31
33
|
const files = await fs.readdir(dir);
|
|
@@ -93,6 +95,8 @@ module.exports = {
|
|
|
93
95
|
if (!folder) throw new Error('Missing folder parameter');
|
|
94
96
|
await fs.rmdir(path.join(appdir(), folder), { recursive: true });
|
|
95
97
|
socket.emitChanged(`app-folders-changed`);
|
|
98
|
+
socket.emitChanged(`app-files-changed-${folder}`);
|
|
99
|
+
socket.emitChanged('used-apps-changed');
|
|
96
100
|
},
|
|
97
101
|
|
|
98
102
|
async getNewAppFolder({ name }) {
|
|
@@ -141,6 +141,13 @@ module.exports = {
|
|
|
141
141
|
});
|
|
142
142
|
},
|
|
143
143
|
|
|
144
|
+
saveText_meta: true,
|
|
145
|
+
async saveText({ folder, file, text }) {
|
|
146
|
+
await fs.writeFile(path.join(resolveArchiveFolder(folder), `${file}.jsonl`), text);
|
|
147
|
+
socket.emitChanged(`archive-files-changed-${folder}`);
|
|
148
|
+
return true;
|
|
149
|
+
},
|
|
150
|
+
|
|
144
151
|
async getNewArchiveFolder({ database }) {
|
|
145
152
|
const isLink = database.endsWith(database);
|
|
146
153
|
const name = isLink ? database.slice(0, -5) : database;
|
|
@@ -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,
|
|
@@ -62,9 +62,10 @@ module.exports = {
|
|
|
62
62
|
delete this.requests[msgid];
|
|
63
63
|
},
|
|
64
64
|
handle_status(conid, database, { status }) {
|
|
65
|
+
// console.log('HANDLE SET STATUS', status);
|
|
65
66
|
const existing = this.opened.find(x => x.conid == conid && x.database == database);
|
|
66
67
|
if (!existing) return;
|
|
67
|
-
if (existing.status
|
|
68
|
+
if (existing.status && status && existing.status.counter > status.counter) return;
|
|
68
69
|
existing.status = status;
|
|
69
70
|
socket.emitChanged(`database-status-changed-${conid}-${database}`);
|
|
70
71
|
},
|
|
@@ -109,7 +110,7 @@ module.exports = {
|
|
|
109
110
|
msgtype: 'connect',
|
|
110
111
|
connection: { ...connection, database },
|
|
111
112
|
structure: lastClosed ? lastClosed.structure : null,
|
|
112
|
-
globalSettings: config.
|
|
113
|
+
globalSettings: await config.getSettings(),
|
|
113
114
|
});
|
|
114
115
|
return newOpened;
|
|
115
116
|
},
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const lineReader = require('line-reader');
|
|
3
3
|
const _ = require('lodash');
|
|
4
|
+
const { __ } = require('lodash/fp');
|
|
4
5
|
const DatastoreProxy = require('../utility/DatastoreProxy');
|
|
5
6
|
const { saveFreeTableData } = require('../utility/freeTableStorage');
|
|
6
7
|
const getJslFileName = require('../utility/getJslFileName');
|
|
@@ -10,7 +11,10 @@ const socket = require('../utility/socket');
|
|
|
10
11
|
function readFirstLine(file) {
|
|
11
12
|
return new Promise((resolve, reject) => {
|
|
12
13
|
lineReader.open(file, (err, reader) => {
|
|
13
|
-
if (err)
|
|
14
|
+
if (err) {
|
|
15
|
+
reject(err);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
14
18
|
if (reader.hasNextLine()) {
|
|
15
19
|
reader.nextLine((err, line) => {
|
|
16
20
|
if (err) reject(err);
|
|
@@ -108,7 +112,16 @@ module.exports = {
|
|
|
108
112
|
async getInfo({ jslid }) {
|
|
109
113
|
const file = getJslFileName(jslid);
|
|
110
114
|
const firstLine = await readFirstLine(file);
|
|
111
|
-
if (firstLine)
|
|
115
|
+
if (firstLine) {
|
|
116
|
+
const parsed = JSON.parse(firstLine);
|
|
117
|
+
if (parsed.__isStreamHeader) {
|
|
118
|
+
return parsed;
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
__isStreamHeader: true,
|
|
122
|
+
__isDynamicStructure: true,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
112
125
|
return null;
|
|
113
126
|
},
|
|
114
127
|
|
|
@@ -132,7 +145,7 @@ module.exports = {
|
|
|
132
145
|
},
|
|
133
146
|
|
|
134
147
|
async notifyChangedStats(stats) {
|
|
135
|
-
console.log('SENDING STATS', JSON.stringify(stats));
|
|
148
|
+
// console.log('SENDING STATS', JSON.stringify(stats));
|
|
136
149
|
const datastore = this.datastores[stats.jslid];
|
|
137
150
|
if (datastore) await datastore.notifyChanged();
|
|
138
151
|
socket.emit(`jsldata-stats-${stats.jslid}`, stats);
|
|
@@ -151,4 +164,10 @@ module.exports = {
|
|
|
151
164
|
saveFreeTableData(getJslFileName(jslid), data);
|
|
152
165
|
return true;
|
|
153
166
|
},
|
|
167
|
+
|
|
168
|
+
saveText_meta: true,
|
|
169
|
+
async saveText({ jslid, text }) {
|
|
170
|
+
await fs.promises.writeFile(getJslFileName(jslid), text);
|
|
171
|
+
return true;
|
|
172
|
+
},
|
|
154
173
|
};
|
|
@@ -48,7 +48,7 @@ module.exports = {
|
|
|
48
48
|
async write({ data }) {
|
|
49
49
|
const fileName = path.join(datadir(), 'query-history.jsonl');
|
|
50
50
|
await fs.appendFile(fileName, JSON.stringify(data) + '\n');
|
|
51
|
-
socket.
|
|
51
|
+
socket.emit('query-history-changed');
|
|
52
52
|
return 'OK';
|
|
53
53
|
},
|
|
54
54
|
};
|
|
@@ -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 };
|
|
@@ -18,6 +18,12 @@ let lastStatus = null;
|
|
|
18
18
|
let analysedTime = 0;
|
|
19
19
|
let serverVersion;
|
|
20
20
|
|
|
21
|
+
let statusCounter = 0;
|
|
22
|
+
function getStatusCounter() {
|
|
23
|
+
statusCounter += 1;
|
|
24
|
+
return statusCounter;
|
|
25
|
+
}
|
|
26
|
+
|
|
21
27
|
async function checkedAsyncCall(promise) {
|
|
22
28
|
try {
|
|
23
29
|
const res = await promise;
|
|
@@ -79,7 +85,7 @@ function handleSyncModel() {
|
|
|
79
85
|
function setStatus(status) {
|
|
80
86
|
const statusString = stableStringify(status);
|
|
81
87
|
if (lastStatus != statusString) {
|
|
82
|
-
process.send({ msgtype: 'status', status });
|
|
88
|
+
process.send({ msgtype: 'status', status: { ...status, counter: getStatusCounter() } });
|
|
83
89
|
lastStatus = statusString;
|
|
84
90
|
}
|
|
85
91
|
}
|
package/src/shell/copyStream.js
CHANGED
|
@@ -2,12 +2,17 @@ const EnsureStreamHeaderStream = require('../utility/EnsureStreamHeaderStream');
|
|
|
2
2
|
|
|
3
3
|
function copyStream(input, output) {
|
|
4
4
|
return new Promise((resolve, reject) => {
|
|
5
|
-
const ensureHeader = new EnsureStreamHeaderStream();
|
|
6
5
|
const finisher = output['finisher'] || output;
|
|
7
6
|
finisher.on('finish', resolve);
|
|
8
7
|
finisher.on('error', reject);
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
|
|
9
|
+
if (output.requireFixedStructure) {
|
|
10
|
+
const ensureHeader = new EnsureStreamHeaderStream();
|
|
11
|
+
input.pipe(ensureHeader);
|
|
12
|
+
ensureHeader.pipe(output);
|
|
13
|
+
} else {
|
|
14
|
+
input.pipe(output);
|
|
15
|
+
}
|
|
11
16
|
});
|
|
12
17
|
}
|
|
13
18
|
|
|
@@ -11,10 +11,7 @@ class StringifyStream extends stream.Transform {
|
|
|
11
11
|
let skip = false;
|
|
12
12
|
|
|
13
13
|
if (!this.wasHeader) {
|
|
14
|
-
skip =
|
|
15
|
-
chunk.__isStreamHeader ||
|
|
16
|
-
// TODO remove isArray test
|
|
17
|
-
Array.isArray(chunk.columns);
|
|
14
|
+
skip = chunk.__isStreamHeader;
|
|
18
15
|
this.wasHeader = true;
|
|
19
16
|
}
|
|
20
17
|
if (!skip) {
|
|
@@ -12,14 +12,14 @@ class ParseStream extends stream.Transform {
|
|
|
12
12
|
_transform(chunk, encoding, done) {
|
|
13
13
|
const obj = JSON.parse(chunk);
|
|
14
14
|
if (!this.wasHeader) {
|
|
15
|
-
if (
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
if (!obj.__isStreamHeader) {
|
|
16
|
+
this.push({
|
|
17
|
+
__isStreamHeader: true,
|
|
18
|
+
__isDynamicStructure: true,
|
|
19
|
+
// columns: Object.keys(obj).map(columnName => ({ columnName })),
|
|
20
|
+
});
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
this.wasHeader = true;
|
|
24
24
|
}
|
|
25
25
|
if (!this.limitRows || this.rowsWritten < this.limitRows) {
|
|
@@ -10,11 +10,7 @@ class StringifyStream extends stream.Transform {
|
|
|
10
10
|
_transform(chunk, encoding, done) {
|
|
11
11
|
let skip = false;
|
|
12
12
|
if (!this.wasHeader) {
|
|
13
|
-
skip =
|
|
14
|
-
(chunk.__isStreamHeader ||
|
|
15
|
-
// TODO remove isArray test
|
|
16
|
-
Array.isArray(chunk.columns)) &&
|
|
17
|
-
!this.header;
|
|
13
|
+
skip = (chunk.__isStreamHeader && !this.header) || (chunk.__isStreamHeader && chunk.__isDynamicStructure);
|
|
18
14
|
this.wasHeader = true;
|
|
19
15
|
}
|
|
20
16
|
if (!skip) {
|
|
@@ -14,11 +14,7 @@ class SqlizeStream extends stream.Transform {
|
|
|
14
14
|
_transform(chunk, encoding, done) {
|
|
15
15
|
let skip = false;
|
|
16
16
|
if (!this.wasHeader) {
|
|
17
|
-
if (
|
|
18
|
-
chunk.__isStreamHeader ||
|
|
19
|
-
// TODO remove isArray test
|
|
20
|
-
Array.isArray(chunk.columns)
|
|
21
|
-
) {
|
|
17
|
+
if (chunk.__isStreamHeader) {
|
|
22
18
|
skip = true;
|
|
23
19
|
this.tableName = chunk.pureName;
|
|
24
20
|
if (chunk.engine) {
|
|
@@ -13,11 +13,7 @@ class EnsureStreamHeaderStream extends stream.Transform {
|
|
|
13
13
|
return;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
if (
|
|
17
|
-
!chunk.__isStreamHeader &&
|
|
18
|
-
// TODO remove isArray test
|
|
19
|
-
!Array.isArray(chunk.columns)
|
|
20
|
-
) {
|
|
16
|
+
if (!chunk.__isStreamHeader) {
|
|
21
17
|
this.push({
|
|
22
18
|
__isStreamHeader: true,
|
|
23
19
|
__isComputedStructure: true,
|
|
@@ -27,6 +27,7 @@ class JsonLinesDatastore {
|
|
|
27
27
|
this.reader = null;
|
|
28
28
|
this.readedDataRowCount = 0;
|
|
29
29
|
this.readedSchemaRow = false;
|
|
30
|
+
// this.firstRowToBeReturned = null;
|
|
30
31
|
this.notifyChangedCallback = null;
|
|
31
32
|
this.currentFilter = null;
|
|
32
33
|
}
|
|
@@ -37,6 +38,7 @@ class JsonLinesDatastore {
|
|
|
37
38
|
this.reader = null;
|
|
38
39
|
this.readedDataRowCount = 0;
|
|
39
40
|
this.readedSchemaRow = false;
|
|
41
|
+
// this.firstRowToBeReturned = null;
|
|
40
42
|
this.currentFilter = null;
|
|
41
43
|
reader.close(() => {});
|
|
42
44
|
}
|
|
@@ -61,6 +63,11 @@ class JsonLinesDatastore {
|
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
async _readLine(parse) {
|
|
66
|
+
// if (this.firstRowToBeReturned) {
|
|
67
|
+
// const res = this.firstRowToBeReturned;
|
|
68
|
+
// this.firstRowToBeReturned = null;
|
|
69
|
+
// return res;
|
|
70
|
+
// }
|
|
64
71
|
for (;;) {
|
|
65
72
|
const line = await fetchNextLineFromReader(this.reader);
|
|
66
73
|
if (!line) {
|
|
@@ -70,7 +77,11 @@ class JsonLinesDatastore {
|
|
|
70
77
|
|
|
71
78
|
if (!this.readedSchemaRow) {
|
|
72
79
|
this.readedSchemaRow = true;
|
|
73
|
-
|
|
80
|
+
const parsedLine = JSON.parse(line);
|
|
81
|
+
if (parsedLine.__isStreamHeader) {
|
|
82
|
+
// skip to next line
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
74
85
|
}
|
|
75
86
|
if (this.currentFilter) {
|
|
76
87
|
const parsedLine = JSON.parse(line);
|
|
@@ -130,11 +141,21 @@ class JsonLinesDatastore {
|
|
|
130
141
|
this.reader = reader;
|
|
131
142
|
this.currentFilter = filter;
|
|
132
143
|
}
|
|
133
|
-
if (!this.readedSchemaRow) {
|
|
134
|
-
|
|
135
|
-
|
|
144
|
+
// if (!this.readedSchemaRow) {
|
|
145
|
+
// const line = await this._readLine(true); // skip structure
|
|
146
|
+
// if (!line.__isStreamHeader) {
|
|
147
|
+
// // line contains data
|
|
148
|
+
// this.firstRowToBeReturned = line;
|
|
149
|
+
// }
|
|
150
|
+
// }
|
|
136
151
|
while (this.readedDataRowCount < offset) {
|
|
137
|
-
await this._readLine(false);
|
|
152
|
+
const line = await this._readLine(false);
|
|
153
|
+
if (line == null) break;
|
|
154
|
+
// if (this.firstRowToBeReturned) {
|
|
155
|
+
// this.firstRowToBeReturned = null;
|
|
156
|
+
// } else {
|
|
157
|
+
// await this._readLine(false);
|
|
158
|
+
// }
|
|
138
159
|
}
|
|
139
160
|
}
|
|
140
161
|
|
|
@@ -148,7 +169,6 @@ class JsonLinesDatastore {
|
|
|
148
169
|
res.push(line);
|
|
149
170
|
}
|
|
150
171
|
});
|
|
151
|
-
// console.log('RETURN', res.length);
|
|
152
172
|
return res;
|
|
153
173
|
}
|
|
154
174
|
}
|
|
@@ -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
|
@@ -5,6 +5,7 @@ let init = '';
|
|
|
5
5
|
module.exports = {
|
|
6
6
|
setSseResponse(value) {
|
|
7
7
|
sseResponse = value;
|
|
8
|
+
setInterval(() => this.emit('ping'), 29 * 1000);
|
|
8
9
|
},
|
|
9
10
|
setElectronSender(value) {
|
|
10
11
|
electronSender = value;
|
|
@@ -23,7 +24,8 @@ module.exports = {
|
|
|
23
24
|
}
|
|
24
25
|
},
|
|
25
26
|
emitChanged(key) {
|
|
26
|
-
|
|
27
|
-
this.emit(key);
|
|
27
|
+
// console.log('EMIT CHANGED', key);
|
|
28
|
+
this.emit('changed-cache', key);
|
|
29
|
+
// this.emit(key);
|
|
28
30
|
},
|
|
29
31
|
};
|
|
@@ -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
|
};
|
package/webpack.config.js
CHANGED
|
@@ -10,16 +10,16 @@ var config = {
|
|
|
10
10
|
target: 'node',
|
|
11
11
|
node: {
|
|
12
12
|
__dirname: false,
|
|
13
|
-
},
|
|
13
|
+
},
|
|
14
14
|
output: {
|
|
15
15
|
path: path.resolve(__dirname, 'dist'),
|
|
16
16
|
filename: 'bundle.js',
|
|
17
17
|
libraryTarget: 'commonjs2',
|
|
18
18
|
},
|
|
19
19
|
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
20
|
+
// optimization: {
|
|
21
|
+
// minimize: false,
|
|
22
|
+
// },
|
|
23
23
|
|
|
24
24
|
module: {
|
|
25
25
|
rules: [
|
|
@@ -45,6 +45,9 @@ var config = {
|
|
|
45
45
|
},
|
|
46
46
|
}),
|
|
47
47
|
],
|
|
48
|
+
externals: {
|
|
49
|
+
'better-sqlite3': 'commonjs better-sqlite3',
|
|
50
|
+
},
|
|
48
51
|
};
|
|
49
52
|
|
|
50
53
|
module.exports = config;
|