dbgate-api-premium 5.5.7-alpha.45
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/.env +19 -0
- package/.yarnrc +2 -0
- package/README.md +1 -0
- package/env/dblogin/.env +14 -0
- package/env/portal/.env +70 -0
- package/env/singledb/.env +17 -0
- package/env/storage/.env +43 -0
- package/package.json +89 -0
- package/src/auth/authCommon.js +16 -0
- package/src/auth/authProvider.js +343 -0
- package/src/auth/storageAuthProvider.js +393 -0
- package/src/controllers/apps.js +280 -0
- package/src/controllers/archive.js +217 -0
- package/src/controllers/auth.js +136 -0
- package/src/controllers/config.js +271 -0
- package/src/controllers/connections.js +486 -0
- package/src/controllers/databaseConnections.js +561 -0
- package/src/controllers/files.js +222 -0
- package/src/controllers/jsldata.js +296 -0
- package/src/controllers/metadata.js +47 -0
- package/src/controllers/plugins.js +216 -0
- package/src/controllers/queryHistory.js +54 -0
- package/src/controllers/runners.js +234 -0
- package/src/controllers/scheduler.js +46 -0
- package/src/controllers/serverConnections.js +271 -0
- package/src/controllers/sessions.js +243 -0
- package/src/controllers/storage.js +380 -0
- package/src/controllers/storageDb.js +215 -0
- package/src/controllers/uploads.js +133 -0
- package/src/currentVersion.js +5 -0
- package/src/gistSecret.js +2 -0
- package/src/index.js +139 -0
- package/src/main.js +202 -0
- package/src/packagedPluginsContent.js +1 -0
- package/src/proc/connectProcess.js +38 -0
- package/src/proc/databaseConnectionProcess.js +431 -0
- package/src/proc/index.js +15 -0
- package/src/proc/jslDatastoreProcess.js +60 -0
- package/src/proc/serverConnectionProcess.js +188 -0
- package/src/proc/sessionProcess.js +390 -0
- package/src/proc/sshForwardProcess.js +75 -0
- package/src/shell/archiveReader.js +11 -0
- package/src/shell/archiveWriter.js +22 -0
- package/src/shell/autoIndexForeignKeysTransform.js +19 -0
- package/src/shell/collectorWriter.js +33 -0
- package/src/shell/consoleObjectWriter.js +16 -0
- package/src/shell/copyStream.js +48 -0
- package/src/shell/dataDuplicator.js +63 -0
- package/src/shell/dataTypeMapperTransform.js +21 -0
- package/src/shell/dbModelToJson.js +16 -0
- package/src/shell/deployDb.js +56 -0
- package/src/shell/download.js +15 -0
- package/src/shell/dropAllDbObjects.js +42 -0
- package/src/shell/dumpDatabase.js +49 -0
- package/src/shell/executeQuery.js +39 -0
- package/src/shell/fakeObjectReader.js +35 -0
- package/src/shell/finalizer.js +12 -0
- package/src/shell/generateDeploySql.js +95 -0
- package/src/shell/generateModelSql.js +30 -0
- package/src/shell/importDatabase.js +85 -0
- package/src/shell/index.js +80 -0
- package/src/shell/initializeApiEnvironment.js +9 -0
- package/src/shell/jslDataReader.js +9 -0
- package/src/shell/jsonLinesReader.js +52 -0
- package/src/shell/jsonLinesWriter.js +36 -0
- package/src/shell/jsonReader.js +84 -0
- package/src/shell/jsonToDbModel.js +9 -0
- package/src/shell/jsonWriter.js +97 -0
- package/src/shell/loadDatabase.js +27 -0
- package/src/shell/loadFile.js +10 -0
- package/src/shell/modifyJsonLinesReader.js +148 -0
- package/src/shell/queryReader.js +30 -0
- package/src/shell/registerPlugins.js +9 -0
- package/src/shell/requirePlugin.js +43 -0
- package/src/shell/runScript.js +19 -0
- package/src/shell/sqlDataWriter.js +52 -0
- package/src/shell/sqlTextReplacementTransform.js +32 -0
- package/src/shell/tableReader.js +39 -0
- package/src/shell/tableWriter.js +18 -0
- package/src/storageModel.js +819 -0
- package/src/utility/ColumnMapTransformStream.js +21 -0
- package/src/utility/DatastoreProxy.js +106 -0
- package/src/utility/EnsureStreamHeaderStream.js +31 -0
- package/src/utility/JsonLinesDatabase.js +148 -0
- package/src/utility/JsonLinesDatastore.js +232 -0
- package/src/utility/LineReader.js +88 -0
- package/src/utility/SSHConnection.js +251 -0
- package/src/utility/authProxy.js +133 -0
- package/src/utility/checkLicense.js +186 -0
- package/src/utility/childProcessChecker.js +21 -0
- package/src/utility/cleanDirectory.js +24 -0
- package/src/utility/cloudUpgrade.js +61 -0
- package/src/utility/connectUtility.js +111 -0
- package/src/utility/crypting.js +105 -0
- package/src/utility/diff2htmlPage.js +8 -0
- package/src/utility/directories.js +179 -0
- package/src/utility/downloadPackage.js +51 -0
- package/src/utility/downloader.js +25 -0
- package/src/utility/exceptions.js +9 -0
- package/src/utility/exportDbModel.js +31 -0
- package/src/utility/exportDbModelSql.js +80 -0
- package/src/utility/getChartExport.js +55 -0
- package/src/utility/getDiagramExport.js +25 -0
- package/src/utility/getExpressPath.js +10 -0
- package/src/utility/getJslFileName.js +16 -0
- package/src/utility/getMapExport.js +77 -0
- package/src/utility/hardwareFingerprint.js +89 -0
- package/src/utility/hasPermission.js +101 -0
- package/src/utility/importDbModel.js +9 -0
- package/src/utility/loadFilesRecursive.js +20 -0
- package/src/utility/loadModelFolder.js +29 -0
- package/src/utility/loadModelTransform.js +36 -0
- package/src/utility/pipeForkLogs.js +19 -0
- package/src/utility/platformInfo.js +62 -0
- package/src/utility/processArgs.js +39 -0
- package/src/utility/processComm.js +18 -0
- package/src/utility/requireEngineDriver.js +26 -0
- package/src/utility/requirePluginFunction.js +16 -0
- package/src/utility/socket.js +68 -0
- package/src/utility/sshTunnel.js +106 -0
- package/src/utility/sshTunnelProxy.js +36 -0
- package/src/utility/timingSafeCheckToken.js +9 -0
- package/src/utility/useController.js +99 -0
- package/tsconfig.json +13 -0
- package/webpack.config.js +55 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
const stableStringify = require('json-stable-stringify');
|
|
2
|
+
const { splitQuery } = require('dbgate-query-splitter');
|
|
3
|
+
const childProcessChecker = require('../utility/childProcessChecker');
|
|
4
|
+
const {
|
|
5
|
+
extractBoolSettingsValue,
|
|
6
|
+
extractIntSettingsValue,
|
|
7
|
+
getLogger,
|
|
8
|
+
isCompositeDbName,
|
|
9
|
+
dbNameLogCategory,
|
|
10
|
+
extractErrorMessage,
|
|
11
|
+
extractErrorLogData,
|
|
12
|
+
} = require('dbgate-tools');
|
|
13
|
+
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
14
|
+
const connectUtility = require('../utility/connectUtility');
|
|
15
|
+
const { handleProcessCommunication } = require('../utility/processComm');
|
|
16
|
+
const { SqlGenerator } = require('dbgate-tools');
|
|
17
|
+
const generateDeploySql = require('../shell/generateDeploySql');
|
|
18
|
+
const { dumpSqlSelect } = require('dbgate-sqltree');
|
|
19
|
+
|
|
20
|
+
const logger = getLogger('dbconnProcess');
|
|
21
|
+
|
|
22
|
+
let dbhan;
|
|
23
|
+
let storedConnection;
|
|
24
|
+
let afterConnectCallbacks = [];
|
|
25
|
+
let afterAnalyseCallbacks = [];
|
|
26
|
+
let analysedStructure = null;
|
|
27
|
+
let lastPing = null;
|
|
28
|
+
let lastStatusString = null;
|
|
29
|
+
let lastStatus = null;
|
|
30
|
+
let analysedTime = 0;
|
|
31
|
+
let serverVersion;
|
|
32
|
+
|
|
33
|
+
let statusCounter = 0;
|
|
34
|
+
function getStatusCounter() {
|
|
35
|
+
statusCounter += 1;
|
|
36
|
+
return statusCounter;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function checkedAsyncCall(promise) {
|
|
40
|
+
try {
|
|
41
|
+
const res = await promise;
|
|
42
|
+
return res;
|
|
43
|
+
} catch (err) {
|
|
44
|
+
setStatus({
|
|
45
|
+
name: 'error',
|
|
46
|
+
message: extractErrorMessage(err, 'Checked call error'),
|
|
47
|
+
});
|
|
48
|
+
// console.error(err);
|
|
49
|
+
setTimeout(() => process.exit(1), 1000);
|
|
50
|
+
throw err;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let loadingModel = false;
|
|
55
|
+
|
|
56
|
+
async function handleFullRefresh() {
|
|
57
|
+
if (storedConnection.useSeparateSchemas && !isCompositeDbName(dbhan?.database)) {
|
|
58
|
+
resolveAnalysedPromises();
|
|
59
|
+
// skip loading DB structure
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
loadingModel = true;
|
|
64
|
+
const driver = requireEngineDriver(storedConnection);
|
|
65
|
+
setStatusName('loadStructure');
|
|
66
|
+
analysedStructure = await checkedAsyncCall(driver.analyseFull(dbhan, serverVersion));
|
|
67
|
+
analysedTime = new Date().getTime();
|
|
68
|
+
process.send({ msgtype: 'structure', structure: analysedStructure });
|
|
69
|
+
process.send({ msgtype: 'structureTime', analysedTime });
|
|
70
|
+
setStatusName('ok');
|
|
71
|
+
|
|
72
|
+
loadingModel = false;
|
|
73
|
+
resolveAnalysedPromises();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function handleIncrementalRefresh(forceSend) {
|
|
77
|
+
if (storedConnection.useSeparateSchemas && !isCompositeDbName(dbhan?.database)) {
|
|
78
|
+
resolveAnalysedPromises();
|
|
79
|
+
// skip loading DB structure
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
loadingModel = true;
|
|
83
|
+
const driver = requireEngineDriver(storedConnection);
|
|
84
|
+
setStatusName('checkStructure');
|
|
85
|
+
const newStructure = await checkedAsyncCall(driver.analyseIncremental(dbhan, analysedStructure, serverVersion));
|
|
86
|
+
analysedTime = new Date().getTime();
|
|
87
|
+
if (newStructure != null) {
|
|
88
|
+
analysedStructure = newStructure;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (forceSend || newStructure != null) {
|
|
92
|
+
process.send({ msgtype: 'structure', structure: analysedStructure });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
process.send({ msgtype: 'structureTime', analysedTime });
|
|
96
|
+
setStatusName('ok');
|
|
97
|
+
loadingModel = false;
|
|
98
|
+
resolveAnalysedPromises();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function handleSyncModel({ isFullRefresh }) {
|
|
102
|
+
if (loadingModel) return;
|
|
103
|
+
if (isFullRefresh) handleFullRefresh();
|
|
104
|
+
else handleIncrementalRefresh();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function setStatus(status) {
|
|
108
|
+
const newStatus = { ...lastStatus, ...status };
|
|
109
|
+
const statusString = stableStringify(newStatus);
|
|
110
|
+
if (lastStatusString != statusString) {
|
|
111
|
+
process.send({ msgtype: 'status', status: { ...newStatus, counter: getStatusCounter() } });
|
|
112
|
+
lastStatusString = statusString;
|
|
113
|
+
lastStatus = newStatus;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function setStatusName(name) {
|
|
118
|
+
setStatus({ name, message: null });
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function readVersion() {
|
|
122
|
+
const driver = requireEngineDriver(storedConnection);
|
|
123
|
+
const version = await driver.getVersion(dbhan);
|
|
124
|
+
logger.debug(`Got server version: ${version.version}`);
|
|
125
|
+
process.send({ msgtype: 'version', version });
|
|
126
|
+
serverVersion = version;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async function handleConnect({ connection, structure, globalSettings }) {
|
|
130
|
+
storedConnection = connection;
|
|
131
|
+
lastPing = new Date().getTime();
|
|
132
|
+
|
|
133
|
+
if (!structure) setStatusName('pending');
|
|
134
|
+
const driver = requireEngineDriver(storedConnection);
|
|
135
|
+
dbhan = await checkedAsyncCall(connectUtility(driver, storedConnection, 'app'));
|
|
136
|
+
logger.debug(
|
|
137
|
+
`Connected to database, driver: ${storedConnection.engine}, separate schemas: ${
|
|
138
|
+
storedConnection.useSeparateSchemas ? 'YES' : 'NO'
|
|
139
|
+
}, 'DB: ${dbNameLogCategory(dbhan.database)} }`
|
|
140
|
+
);
|
|
141
|
+
dbhan.feedback = feedback => setStatus({ feedback });
|
|
142
|
+
await checkedAsyncCall(readVersion());
|
|
143
|
+
if (structure) {
|
|
144
|
+
analysedStructure = structure;
|
|
145
|
+
handleIncrementalRefresh(true);
|
|
146
|
+
} else {
|
|
147
|
+
handleFullRefresh();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (extractBoolSettingsValue(globalSettings, 'connection.autoRefresh', false)) {
|
|
151
|
+
setInterval(
|
|
152
|
+
handleIncrementalRefresh,
|
|
153
|
+
extractIntSettingsValue(globalSettings, 'connection.autoRefreshInterval', 30, 3, 3600) * 1000
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
for (const [resolve] of afterConnectCallbacks) {
|
|
158
|
+
resolve();
|
|
159
|
+
}
|
|
160
|
+
afterConnectCallbacks = [];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function waitConnected() {
|
|
164
|
+
if (dbhan) return Promise.resolve();
|
|
165
|
+
return new Promise((resolve, reject) => {
|
|
166
|
+
afterConnectCallbacks.push([resolve, reject]);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function waitStructure() {
|
|
171
|
+
if (analysedStructure) return Promise.resolve();
|
|
172
|
+
return new Promise((resolve, reject) => {
|
|
173
|
+
afterAnalyseCallbacks.push([resolve, reject]);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function resolveAnalysedPromises() {
|
|
178
|
+
for (const [resolve] of afterAnalyseCallbacks) {
|
|
179
|
+
resolve();
|
|
180
|
+
}
|
|
181
|
+
afterAnalyseCallbacks = [];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async function handleRunScript({ msgid, sql, useTransaction }, skipReadonlyCheck = false) {
|
|
185
|
+
await waitConnected();
|
|
186
|
+
const driver = requireEngineDriver(storedConnection);
|
|
187
|
+
try {
|
|
188
|
+
if (!skipReadonlyCheck) ensureExecuteCustomScript(driver);
|
|
189
|
+
await driver.script(dbhan, sql, { useTransaction });
|
|
190
|
+
process.send({ msgtype: 'response', msgid });
|
|
191
|
+
} catch (err) {
|
|
192
|
+
process.send({
|
|
193
|
+
msgtype: 'response',
|
|
194
|
+
msgid,
|
|
195
|
+
errorMessage: extractErrorMessage(err, 'Error executing SQL script'),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async function handleRunOperation({ msgid, operation, useTransaction }, skipReadonlyCheck = false) {
|
|
201
|
+
await waitConnected();
|
|
202
|
+
const driver = requireEngineDriver(storedConnection);
|
|
203
|
+
try {
|
|
204
|
+
if (!skipReadonlyCheck) ensureExecuteCustomScript(driver);
|
|
205
|
+
await driver.operation(dbhan, operation, { useTransaction });
|
|
206
|
+
process.send({ msgtype: 'response', msgid });
|
|
207
|
+
} catch (err) {
|
|
208
|
+
process.send({
|
|
209
|
+
msgtype: 'response',
|
|
210
|
+
msgid,
|
|
211
|
+
errorMessage: extractErrorMessage(err, 'Error executing DB operation'),
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
async function handleQueryData({ msgid, sql }, skipReadonlyCheck = false) {
|
|
217
|
+
await waitConnected();
|
|
218
|
+
const driver = requireEngineDriver(storedConnection);
|
|
219
|
+
try {
|
|
220
|
+
if (!skipReadonlyCheck) ensureExecuteCustomScript(driver);
|
|
221
|
+
// console.log(sql);
|
|
222
|
+
const res = await driver.query(dbhan, sql);
|
|
223
|
+
process.send({ msgtype: 'response', msgid, ...res });
|
|
224
|
+
} catch (err) {
|
|
225
|
+
process.send({
|
|
226
|
+
msgtype: 'response',
|
|
227
|
+
msgid,
|
|
228
|
+
errorMessage: extractErrorMessage(err, 'Error executing SQL script'),
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async function handleSqlSelect({ msgid, select }) {
|
|
234
|
+
const driver = requireEngineDriver(storedConnection);
|
|
235
|
+
const dmp = driver.createDumper();
|
|
236
|
+
dumpSqlSelect(dmp, select);
|
|
237
|
+
return handleQueryData({ msgid, sql: dmp.s }, true);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async function handleDriverDataCore(msgid, callMethod, { logName }) {
|
|
241
|
+
await waitConnected();
|
|
242
|
+
const driver = requireEngineDriver(storedConnection);
|
|
243
|
+
try {
|
|
244
|
+
const result = await callMethod(driver);
|
|
245
|
+
process.send({ msgtype: 'response', msgid, result });
|
|
246
|
+
} catch (err) {
|
|
247
|
+
logger.error(extractErrorLogData(err, { logName }), `Error when handling message ${logName}`);
|
|
248
|
+
process.send({ msgtype: 'response', msgid, errorMessage: extractErrorMessage(err, 'Error executing DB data') });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
async function handleSchemaList({ msgid }) {
|
|
253
|
+
logger.debug('Loading schema list');
|
|
254
|
+
return handleDriverDataCore(msgid, driver => driver.listSchemas(dbhan), { logName: 'listSchemas' });
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async function handleCollectionData({ msgid, options }) {
|
|
258
|
+
return handleDriverDataCore(msgid, driver => driver.readCollection(dbhan, options), { logName: 'readCollection' });
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
async function handleLoadKeys({ msgid, root, filter }) {
|
|
262
|
+
return handleDriverDataCore(msgid, driver => driver.loadKeys(dbhan, root, filter), { logName: 'loadKeys' });
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async function handleExportKeys({ msgid, options }) {
|
|
266
|
+
return handleDriverDataCore(msgid, driver => driver.exportKeys(dbhan, options), { logName: 'exportKeys' });
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async function handleLoadKeyInfo({ msgid, key }) {
|
|
270
|
+
return handleDriverDataCore(msgid, driver => driver.loadKeyInfo(dbhan, key), { logName: 'loadKeyInfo' });
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
async function handleCallMethod({ msgid, method, args }) {
|
|
274
|
+
return handleDriverDataCore(
|
|
275
|
+
msgid,
|
|
276
|
+
driver => {
|
|
277
|
+
if (storedConnection.isReadOnly) {
|
|
278
|
+
throw new Error('Connection is read only, cannot call custom methods');
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
ensureExecuteCustomScript(driver);
|
|
282
|
+
return driver.callMethod(dbhan, method, args);
|
|
283
|
+
},
|
|
284
|
+
{ logName: `callMethod:${method}` }
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
async function handleLoadKeyTableRange({ msgid, key, cursor, count }) {
|
|
289
|
+
return handleDriverDataCore(msgid, driver => driver.loadKeyTableRange(dbhan, key, cursor, count), {
|
|
290
|
+
logName: 'loadKeyTableRange',
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async function handleLoadFieldValues({ msgid, schemaName, pureName, field, search }) {
|
|
295
|
+
return handleDriverDataCore(msgid, driver => driver.loadFieldValues(dbhan, { schemaName, pureName }, field, search), {
|
|
296
|
+
logName: 'loadFieldValues',
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function ensureExecuteCustomScript(driver) {
|
|
301
|
+
if (driver.readOnlySessions) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
if (storedConnection.isReadOnly) {
|
|
305
|
+
throw new Error('Connection is read only');
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
async function handleUpdateCollection({ msgid, changeSet }) {
|
|
310
|
+
await waitConnected();
|
|
311
|
+
const driver = requireEngineDriver(storedConnection);
|
|
312
|
+
try {
|
|
313
|
+
ensureExecuteCustomScript(driver);
|
|
314
|
+
const result = await driver.updateCollection(dbhan, changeSet);
|
|
315
|
+
process.send({ msgtype: 'response', msgid, result });
|
|
316
|
+
} catch (err) {
|
|
317
|
+
process.send({ msgtype: 'response', msgid, errorMessage: extractErrorMessage(err, 'Error updating collection') });
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
async function handleSqlPreview({ msgid, objects, options }) {
|
|
322
|
+
await waitStructure();
|
|
323
|
+
const driver = requireEngineDriver(storedConnection);
|
|
324
|
+
|
|
325
|
+
try {
|
|
326
|
+
const dmp = driver.createDumper();
|
|
327
|
+
const generator = new SqlGenerator(analysedStructure, options, objects, dmp, driver, dbhan);
|
|
328
|
+
|
|
329
|
+
await generator.dump();
|
|
330
|
+
process.send({ msgtype: 'response', msgid, sql: dmp.s, isTruncated: generator.isTruncated });
|
|
331
|
+
if (generator.isUnhandledException) {
|
|
332
|
+
setTimeout(async () => {
|
|
333
|
+
logger.error('Exiting because of unhandled exception');
|
|
334
|
+
await driver.close(dbhan);
|
|
335
|
+
process.exit(0);
|
|
336
|
+
}, 500);
|
|
337
|
+
}
|
|
338
|
+
} catch (err) {
|
|
339
|
+
process.send({
|
|
340
|
+
msgtype: 'response',
|
|
341
|
+
msgid,
|
|
342
|
+
isError: true,
|
|
343
|
+
errorMessage: extractErrorMessage(err, 'Error generating SQL preview'),
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
async function handleGenerateDeploySql({ msgid, modelFolder }) {
|
|
349
|
+
await waitStructure();
|
|
350
|
+
|
|
351
|
+
try {
|
|
352
|
+
const res = await generateDeploySql({
|
|
353
|
+
systemConnection: dbhan,
|
|
354
|
+
connection: storedConnection,
|
|
355
|
+
analysedStructure,
|
|
356
|
+
modelFolder,
|
|
357
|
+
});
|
|
358
|
+
process.send({ ...res, msgtype: 'response', msgid });
|
|
359
|
+
} catch (err) {
|
|
360
|
+
process.send({
|
|
361
|
+
msgtype: 'response',
|
|
362
|
+
msgid,
|
|
363
|
+
isError: true,
|
|
364
|
+
errorMessage: extractErrorMessage(err, 'Error generating deploy SQL'),
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// async function handleRunCommand({ msgid, sql }) {
|
|
370
|
+
// await waitConnected();
|
|
371
|
+
// const driver = engines(storedConnection);
|
|
372
|
+
// const res = await driver.query(systemConnection, sql);
|
|
373
|
+
// process.send({ msgtype: 'response', msgid, ...res });
|
|
374
|
+
// }
|
|
375
|
+
|
|
376
|
+
function handlePing() {
|
|
377
|
+
lastPing = new Date().getTime();
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const messageHandlers = {
|
|
381
|
+
connect: handleConnect,
|
|
382
|
+
queryData: handleQueryData,
|
|
383
|
+
runScript: handleRunScript,
|
|
384
|
+
runOperation: handleRunOperation,
|
|
385
|
+
updateCollection: handleUpdateCollection,
|
|
386
|
+
collectionData: handleCollectionData,
|
|
387
|
+
loadKeys: handleLoadKeys,
|
|
388
|
+
loadKeyInfo: handleLoadKeyInfo,
|
|
389
|
+
callMethod: handleCallMethod,
|
|
390
|
+
loadKeyTableRange: handleLoadKeyTableRange,
|
|
391
|
+
sqlPreview: handleSqlPreview,
|
|
392
|
+
ping: handlePing,
|
|
393
|
+
syncModel: handleSyncModel,
|
|
394
|
+
generateDeploySql: handleGenerateDeploySql,
|
|
395
|
+
loadFieldValues: handleLoadFieldValues,
|
|
396
|
+
sqlSelect: handleSqlSelect,
|
|
397
|
+
exportKeys: handleExportKeys,
|
|
398
|
+
schemaList: handleSchemaList,
|
|
399
|
+
// runCommand: handleRunCommand,
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
async function handleMessage({ msgtype, ...other }) {
|
|
403
|
+
const handler = messageHandlers[msgtype];
|
|
404
|
+
await handler(other);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function start() {
|
|
408
|
+
childProcessChecker();
|
|
409
|
+
|
|
410
|
+
setInterval(async () => {
|
|
411
|
+
const time = new Date().getTime();
|
|
412
|
+
if (time - lastPing > 40 * 1000) {
|
|
413
|
+
logger.info('Database connection not alive, exiting');
|
|
414
|
+
const driver = requireEngineDriver(storedConnection);
|
|
415
|
+
await driver.close(dbhan);
|
|
416
|
+
process.exit(0);
|
|
417
|
+
}
|
|
418
|
+
}, 10 * 1000);
|
|
419
|
+
|
|
420
|
+
process.on('message', async message => {
|
|
421
|
+
if (handleProcessCommunication(message)) return;
|
|
422
|
+
try {
|
|
423
|
+
await handleMessage(message);
|
|
424
|
+
} catch (err) {
|
|
425
|
+
logger.error(extractErrorLogData(err), 'Error in DB connection');
|
|
426
|
+
process.send({ msgtype: 'error', error: extractErrorMessage(err, 'Error processing message') });
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
module.exports = { start };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const connectProcess = require('./connectProcess');
|
|
2
|
+
const databaseConnectionProcess = require('./databaseConnectionProcess');
|
|
3
|
+
const serverConnectionProcess = require('./serverConnectionProcess');
|
|
4
|
+
const sessionProcess = require('./sessionProcess');
|
|
5
|
+
const jslDatastoreProcess = require('./jslDatastoreProcess');
|
|
6
|
+
const sshForwardProcess = require('./sshForwardProcess');
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
connectProcess,
|
|
10
|
+
databaseConnectionProcess,
|
|
11
|
+
serverConnectionProcess,
|
|
12
|
+
sessionProcess,
|
|
13
|
+
jslDatastoreProcess,
|
|
14
|
+
sshForwardProcess,
|
|
15
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const childProcessChecker = require('../utility/childProcessChecker');
|
|
2
|
+
const JsonLinesDatastore = require('../utility/JsonLinesDatastore');
|
|
3
|
+
const { handleProcessCommunication } = require('../utility/processComm');
|
|
4
|
+
|
|
5
|
+
let lastPing = null;
|
|
6
|
+
let datastore = new JsonLinesDatastore();
|
|
7
|
+
|
|
8
|
+
function handlePing() {
|
|
9
|
+
lastPing = new Date().getTime();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function handleOpen({ file }) {
|
|
13
|
+
handlePing();
|
|
14
|
+
datastore = new JsonLinesDatastore(file);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function handleRead({ msgid, offset, limit }) {
|
|
18
|
+
handlePing();
|
|
19
|
+
const rows = await datastore.getRows(offset, limit);
|
|
20
|
+
process.send({ msgtype: 'response', msgid, rows });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function handleNotify({ msgid }) {
|
|
24
|
+
await datastore.notifyChanged();
|
|
25
|
+
process.send({ msgtype: 'notify', msgid });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const messageHandlers = {
|
|
29
|
+
open: handleOpen,
|
|
30
|
+
read: handleRead,
|
|
31
|
+
ping: handlePing,
|
|
32
|
+
notify: handleNotify,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
async function handleMessage({ msgtype, ...other }) {
|
|
36
|
+
const handler = messageHandlers[msgtype];
|
|
37
|
+
await handler(other);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function start() {
|
|
41
|
+
childProcessChecker();
|
|
42
|
+
|
|
43
|
+
setInterval(() => {
|
|
44
|
+
const time = new Date().getTime();
|
|
45
|
+
if (time - lastPing > 60 * 1000) {
|
|
46
|
+
process.exit(0);
|
|
47
|
+
}
|
|
48
|
+
}, 60 * 1000);
|
|
49
|
+
|
|
50
|
+
process.on('message', async message => {
|
|
51
|
+
if (handleProcessCommunication(message)) return;
|
|
52
|
+
try {
|
|
53
|
+
await handleMessage(message);
|
|
54
|
+
} catch (e) {
|
|
55
|
+
process.send({ msgtype: 'error', error: e.message });
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = { start };
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
const stableStringify = require('json-stable-stringify');
|
|
2
|
+
const { extractBoolSettingsValue, extractIntSettingsValue, getLogger, extractErrorLogData } = require('dbgate-tools');
|
|
3
|
+
const childProcessChecker = require('../utility/childProcessChecker');
|
|
4
|
+
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
5
|
+
const connectUtility = require('../utility/connectUtility');
|
|
6
|
+
const { handleProcessCommunication } = require('../utility/processComm');
|
|
7
|
+
const logger = getLogger('srvconnProcess');
|
|
8
|
+
|
|
9
|
+
let dbhan;
|
|
10
|
+
let storedConnection;
|
|
11
|
+
let lastDatabases = null;
|
|
12
|
+
let lastStatus = null;
|
|
13
|
+
let lastPing = null;
|
|
14
|
+
let afterConnectCallbacks = [];
|
|
15
|
+
|
|
16
|
+
async function handleRefresh() {
|
|
17
|
+
const driver = requireEngineDriver(storedConnection);
|
|
18
|
+
try {
|
|
19
|
+
let databases = await driver.listDatabases(dbhan);
|
|
20
|
+
if (storedConnection?.allowedDatabases?.trim()) {
|
|
21
|
+
const allowedDatabaseList = storedConnection.allowedDatabases
|
|
22
|
+
.split('\n')
|
|
23
|
+
.map(x => x.trim().toLowerCase())
|
|
24
|
+
.filter(x => x);
|
|
25
|
+
databases = databases.filter(x => allowedDatabaseList.includes(x.name.toLocaleLowerCase()));
|
|
26
|
+
}
|
|
27
|
+
if (storedConnection?.allowedDatabasesRegex?.trim()) {
|
|
28
|
+
const regex = new RegExp(storedConnection.allowedDatabasesRegex, 'i');
|
|
29
|
+
databases = databases.filter(x => regex.test(x.name));
|
|
30
|
+
}
|
|
31
|
+
setStatusName('ok');
|
|
32
|
+
const databasesString = stableStringify(databases);
|
|
33
|
+
if (lastDatabases != databasesString) {
|
|
34
|
+
process.send({ msgtype: 'databases', databases });
|
|
35
|
+
lastDatabases = databasesString;
|
|
36
|
+
}
|
|
37
|
+
} catch (err) {
|
|
38
|
+
setStatus({
|
|
39
|
+
name: 'error',
|
|
40
|
+
message: err.message,
|
|
41
|
+
});
|
|
42
|
+
logger.error(extractErrorLogData(err), 'Error refreshing server databases');
|
|
43
|
+
setTimeout(() => process.exit(1), 1000);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function readVersion() {
|
|
48
|
+
const driver = requireEngineDriver(storedConnection);
|
|
49
|
+
const version = await driver.getVersion(dbhan);
|
|
50
|
+
process.send({ msgtype: 'version', version });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function setStatus(status) {
|
|
54
|
+
const statusString = stableStringify(status);
|
|
55
|
+
if (lastStatus != statusString) {
|
|
56
|
+
process.send({ msgtype: 'status', status });
|
|
57
|
+
lastStatus = statusString;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function setStatusName(name) {
|
|
62
|
+
setStatus({ name });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function handleConnect(connection) {
|
|
66
|
+
storedConnection = connection;
|
|
67
|
+
const { globalSettings } = storedConnection;
|
|
68
|
+
setStatusName('pending');
|
|
69
|
+
lastPing = new Date().getTime();
|
|
70
|
+
|
|
71
|
+
const driver = requireEngineDriver(storedConnection);
|
|
72
|
+
try {
|
|
73
|
+
dbhan = await connectUtility(driver, storedConnection, 'app');
|
|
74
|
+
readVersion();
|
|
75
|
+
handleRefresh();
|
|
76
|
+
if (extractBoolSettingsValue(globalSettings, 'connection.autoRefresh', false)) {
|
|
77
|
+
setInterval(
|
|
78
|
+
handleRefresh,
|
|
79
|
+
extractIntSettingsValue(globalSettings, 'connection.autoRefreshInterval', 30, 5, 3600) * 1000
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
} catch (err) {
|
|
83
|
+
setStatus({
|
|
84
|
+
name: 'error',
|
|
85
|
+
message: err.message,
|
|
86
|
+
});
|
|
87
|
+
logger.error(extractErrorLogData(err), 'Error connecting to server');
|
|
88
|
+
setTimeout(() => process.exit(1), 1000);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
for (const [resolve] of afterConnectCallbacks) {
|
|
92
|
+
resolve();
|
|
93
|
+
}
|
|
94
|
+
afterConnectCallbacks = [];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function waitConnected() {
|
|
98
|
+
if (dbhan) return Promise.resolve();
|
|
99
|
+
return new Promise((resolve, reject) => {
|
|
100
|
+
afterConnectCallbacks.push([resolve, reject]);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function handlePing() {
|
|
105
|
+
lastPing = new Date().getTime();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async function handleDatabaseOp(op, { msgid, name }) {
|
|
109
|
+
try {
|
|
110
|
+
const driver = requireEngineDriver(storedConnection);
|
|
111
|
+
dbhan = await connectUtility(driver, storedConnection, 'app');
|
|
112
|
+
if (driver[op]) {
|
|
113
|
+
await driver[op](dbhan, name);
|
|
114
|
+
} else {
|
|
115
|
+
const dmp = driver.createDumper();
|
|
116
|
+
dmp[op](name);
|
|
117
|
+
logger.info({ sql: dmp.s }, 'Running script');
|
|
118
|
+
await driver.query(dbhan, dmp.s, { discardResult: true });
|
|
119
|
+
}
|
|
120
|
+
await handleRefresh();
|
|
121
|
+
|
|
122
|
+
process.send({ msgtype: 'response', msgid, status: 'ok' });
|
|
123
|
+
} catch (err) {
|
|
124
|
+
process.send({ msgtype: 'response', msgid, errorMessage: err.message });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function handleDriverDataCore(msgid, callMethod) {
|
|
129
|
+
await waitConnected();
|
|
130
|
+
const driver = requireEngineDriver(storedConnection);
|
|
131
|
+
try {
|
|
132
|
+
const result = await callMethod(driver);
|
|
133
|
+
process.send({ msgtype: 'response', msgid, result });
|
|
134
|
+
} catch (err) {
|
|
135
|
+
process.send({ msgtype: 'response', msgid, errorMessage: err.message });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async function handleServerSummary({ msgid }) {
|
|
140
|
+
return handleDriverDataCore(msgid, driver => driver.serverSummary(dbhan));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async function handleSummaryCommand({ msgid, command, row }) {
|
|
144
|
+
return handleDriverDataCore(msgid, driver => driver.summaryCommand(dbhan, command, row));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const messageHandlers = {
|
|
148
|
+
connect: handleConnect,
|
|
149
|
+
ping: handlePing,
|
|
150
|
+
serverSummary: handleServerSummary,
|
|
151
|
+
summaryCommand: handleSummaryCommand,
|
|
152
|
+
createDatabase: props => handleDatabaseOp('createDatabase', props),
|
|
153
|
+
dropDatabase: props => handleDatabaseOp('dropDatabase', props),
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
async function handleMessage({ msgtype, ...other }) {
|
|
157
|
+
const handler = messageHandlers[msgtype];
|
|
158
|
+
await handler(other);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function start() {
|
|
162
|
+
childProcessChecker();
|
|
163
|
+
|
|
164
|
+
setInterval(async () => {
|
|
165
|
+
const time = new Date().getTime();
|
|
166
|
+
if (time - lastPing > 40 * 1000) {
|
|
167
|
+
logger.info('Server connection not alive, exiting');
|
|
168
|
+
const driver = requireEngineDriver(storedConnection);
|
|
169
|
+
await driver.close(dbhan);
|
|
170
|
+
process.exit(0);
|
|
171
|
+
}
|
|
172
|
+
}, 10 * 1000);
|
|
173
|
+
|
|
174
|
+
process.on('message', async message => {
|
|
175
|
+
if (handleProcessCommunication(message)) return;
|
|
176
|
+
try {
|
|
177
|
+
await handleMessage(message);
|
|
178
|
+
} catch (err) {
|
|
179
|
+
setStatus({
|
|
180
|
+
name: 'error',
|
|
181
|
+
message: err.message,
|
|
182
|
+
});
|
|
183
|
+
logger.error(extractErrorLogData(err), `Error processing message ${message?.['msgtype']}`);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
module.exports = { start };
|