dbgate-api 4.6.3 → 4.7.0
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 +3 -0
- package/src/controllers/archive.js +7 -0
- package/src/controllers/databaseConnections.js +2 -1
- package/src/controllers/jsldata.js +22 -3
- package/src/controllers/queryHistory.js +1 -1
- package/src/currentVersion.js +2 -2
- 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/socket.js +3 -2
- 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.0",
|
|
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.0",
|
|
29
|
+
"dbgate-sqltree": "^4.7.0",
|
|
30
|
+
"dbgate-tools": "^4.7.0",
|
|
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.0",
|
|
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,6 +21,7 @@ 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
|
|
|
@@ -93,6 +94,8 @@ module.exports = {
|
|
|
93
94
|
if (!folder) throw new Error('Missing folder parameter');
|
|
94
95
|
await fs.rmdir(path.join(appdir(), folder), { recursive: true });
|
|
95
96
|
socket.emitChanged(`app-folders-changed`);
|
|
97
|
+
socket.emitChanged(`app-files-changed-${folder}`);
|
|
98
|
+
socket.emitChanged('used-apps-changed');
|
|
96
99
|
},
|
|
97
100
|
|
|
98
101
|
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;
|
|
@@ -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
|
},
|
|
@@ -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
|
};
|
package/src/currentVersion.js
CHANGED
|
@@ -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
|
}
|
package/src/utility/socket.js
CHANGED
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;
|