dbgate-api 5.4.5-alpha.5 → 5.5.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dbgate-api",
3
3
  "main": "src/index.js",
4
- "version": "5.4.5-alpha.5",
4
+ "version": "5.5.1",
5
5
  "homepage": "https://dbgate.org/",
6
6
  "repository": {
7
7
  "type": "git",
@@ -26,10 +26,10 @@
26
26
  "compare-versions": "^3.6.0",
27
27
  "cors": "^2.8.5",
28
28
  "cross-env": "^6.0.3",
29
- "dbgate-datalib": "^5.4.5-alpha.5",
29
+ "dbgate-datalib": "^5.5.1",
30
30
  "dbgate-query-splitter": "^4.10.3",
31
- "dbgate-sqltree": "^5.4.5-alpha.5",
32
- "dbgate-tools": "^5.4.5-alpha.5",
31
+ "dbgate-sqltree": "^5.5.1",
32
+ "dbgate-tools": "^5.5.1",
33
33
  "debug": "^4.3.4",
34
34
  "diff": "^5.0.0",
35
35
  "diff2html": "^3.4.13",
@@ -57,6 +57,7 @@
57
57
  "rimraf": "^3.0.0",
58
58
  "simple-encryptor": "^4.0.0",
59
59
  "ssh2": "^1.11.0",
60
+ "stream-json": "^1.8.0",
60
61
  "tar": "^6.0.5"
61
62
  },
62
63
  "scripts": {
@@ -74,7 +75,7 @@
74
75
  "devDependencies": {
75
76
  "@types/fs-extra": "^9.0.11",
76
77
  "@types/lodash": "^4.14.149",
77
- "dbgate-types": "^5.4.5-alpha.5",
78
+ "dbgate-types": "^5.5.1",
78
79
  "env-cmd": "^10.1.0",
79
80
  "node-loader": "^1.0.2",
80
81
  "nodemon": "^2.0.2",
@@ -76,6 +76,7 @@ function getPortalCollections() {
76
76
  allowedDatabases: process.env[`ALLOWED_DATABASES_${id}`]?.replace(/\|/g, '\n'),
77
77
  allowedDatabasesRegex: process.env[`ALLOWED_DATABASES_REGEX_${id}`],
78
78
  parent: process.env[`PARENT_${id}`] || undefined,
79
+ useSeparateSchemas: !!process.env[`USE_SEPARATE_SCHEMAS_${id}`],
79
80
 
80
81
  // SSH tunnel
81
82
  useSshTunnel: process.env[`USE_SSH_${id}`],
@@ -213,6 +213,17 @@ module.exports = {
213
213
  return res.result || null;
214
214
  },
215
215
 
216
+ schemaList_meta: true,
217
+ async schemaList({ conid, database }, req) {
218
+ testConnectionPermission(conid, req);
219
+ return this.loadDataCore('schemaList', { conid, database });
220
+ },
221
+
222
+ dispatchDatabaseChangedEvent_meta: true,
223
+ dispatchDatabaseChangedEvent({ event, conid, database }) {
224
+ socket.emitChanged(event, { conid, database });
225
+ },
226
+
216
227
  loadKeys_meta: true,
217
228
  async loadKeys({ conid, database, root, filter }, req) {
218
229
  testConnectionPermission(conid, req);
@@ -18,11 +18,14 @@ function readFirstLine(file) {
18
18
  }
19
19
  if (reader.hasNextLine()) {
20
20
  reader.nextLine((err, line) => {
21
- if (err) reject(err);
22
- resolve(line);
21
+ if (err) {
22
+ reader.close(() => reject(err)); // Ensure reader is closed on error
23
+ return;
24
+ }
25
+ reader.close(() => resolve(line)); // Ensure reader is closed after reading
23
26
  });
24
27
  } else {
25
- resolve(null);
28
+ reader.close(() => resolve(null)); // Properly close if no lines are present
26
29
  }
27
30
  });
28
31
  });
@@ -1,5 +1,5 @@
1
1
 
2
2
  module.exports = {
3
- version: '5.4.5-alpha.5',
4
- buildTime: '2024-09-13T11:38:16.179Z'
3
+ version: '5.5.1',
4
+ buildTime: '2024-09-25T07:31:46.919Z'
5
5
  };
@@ -11,7 +11,7 @@ const { dumpSqlSelect } = require('dbgate-sqltree');
11
11
 
12
12
  const logger = getLogger('dbconnProcess');
13
13
 
14
- let systemConnection;
14
+ let dbhan;
15
15
  let storedConnection;
16
16
  let afterConnectCallbacks = [];
17
17
  let afterAnalyseCallbacks = [];
@@ -49,7 +49,7 @@ async function handleFullRefresh() {
49
49
  loadingModel = true;
50
50
  const driver = requireEngineDriver(storedConnection);
51
51
  setStatusName('loadStructure');
52
- analysedStructure = await checkedAsyncCall(driver.analyseFull(systemConnection, serverVersion));
52
+ analysedStructure = await checkedAsyncCall(driver.analyseFull(dbhan, serverVersion));
53
53
  analysedTime = new Date().getTime();
54
54
  process.send({ msgtype: 'structure', structure: analysedStructure });
55
55
  process.send({ msgtype: 'structureTime', analysedTime });
@@ -63,9 +63,7 @@ async function handleIncrementalRefresh(forceSend) {
63
63
  loadingModel = true;
64
64
  const driver = requireEngineDriver(storedConnection);
65
65
  setStatusName('checkStructure');
66
- const newStructure = await checkedAsyncCall(
67
- driver.analyseIncremental(systemConnection, analysedStructure, serverVersion)
68
- );
66
+ const newStructure = await checkedAsyncCall(driver.analyseIncremental(dbhan, analysedStructure, serverVersion));
69
67
  analysedTime = new Date().getTime();
70
68
  if (newStructure != null) {
71
69
  analysedStructure = newStructure;
@@ -103,7 +101,7 @@ function setStatusName(name) {
103
101
 
104
102
  async function readVersion() {
105
103
  const driver = requireEngineDriver(storedConnection);
106
- const version = await driver.getVersion(systemConnection);
104
+ const version = await driver.getVersion(dbhan);
107
105
  process.send({ msgtype: 'version', version });
108
106
  serverVersion = version;
109
107
  }
@@ -114,8 +112,8 @@ async function handleConnect({ connection, structure, globalSettings }) {
114
112
 
115
113
  if (!structure) setStatusName('pending');
116
114
  const driver = requireEngineDriver(storedConnection);
117
- systemConnection = await checkedAsyncCall(connectUtility(driver, storedConnection, 'app'));
118
- systemConnection.feedback = feedback => setStatus({ feedback });
115
+ dbhan = await checkedAsyncCall(connectUtility(driver, storedConnection, 'app'));
116
+ dbhan.feedback = feedback => setStatus({ feedback });
119
117
  await checkedAsyncCall(readVersion());
120
118
  if (structure) {
121
119
  analysedStructure = structure;
@@ -138,7 +136,7 @@ async function handleConnect({ connection, structure, globalSettings }) {
138
136
  }
139
137
 
140
138
  function waitConnected() {
141
- if (systemConnection) return Promise.resolve();
139
+ if (dbhan) return Promise.resolve();
142
140
  return new Promise((resolve, reject) => {
143
141
  afterConnectCallbacks.push([resolve, reject]);
144
142
  });
@@ -163,7 +161,7 @@ async function handleRunScript({ msgid, sql, useTransaction }, skipReadonlyCheck
163
161
  const driver = requireEngineDriver(storedConnection);
164
162
  try {
165
163
  if (!skipReadonlyCheck) ensureExecuteCustomScript(driver);
166
- await driver.script(systemConnection, sql, { useTransaction });
164
+ await driver.script(dbhan, sql, { useTransaction });
167
165
  process.send({ msgtype: 'response', msgid });
168
166
  } catch (err) {
169
167
  process.send({ msgtype: 'response', msgid, errorMessage: err.message });
@@ -175,7 +173,7 @@ async function handleRunOperation({ msgid, operation, useTransaction }, skipRead
175
173
  const driver = requireEngineDriver(storedConnection);
176
174
  try {
177
175
  if (!skipReadonlyCheck) ensureExecuteCustomScript(driver);
178
- await driver.operation(systemConnection, operation, { useTransaction });
176
+ await driver.operation(dbhan, operation, { useTransaction });
179
177
  process.send({ msgtype: 'response', msgid });
180
178
  } catch (err) {
181
179
  process.send({ msgtype: 'response', msgid, errorMessage: err.message });
@@ -188,7 +186,7 @@ async function handleQueryData({ msgid, sql }, skipReadonlyCheck = false) {
188
186
  try {
189
187
  if (!skipReadonlyCheck) ensureExecuteCustomScript(driver);
190
188
  // console.log(sql);
191
- const res = await driver.query(systemConnection, sql);
189
+ const res = await driver.query(dbhan, sql);
192
190
  process.send({ msgtype: 'response', msgid, ...res });
193
191
  } catch (err) {
194
192
  process.send({ msgtype: 'response', msgid, errorMessage: err.message || 'Error executing SQL script' });
@@ -202,52 +200,64 @@ async function handleSqlSelect({ msgid, select }) {
202
200
  return handleQueryData({ msgid, sql: dmp.s }, true);
203
201
  }
204
202
 
205
- async function handleDriverDataCore(msgid, callMethod) {
203
+ async function handleDriverDataCore(msgid, callMethod, { logName }) {
206
204
  await waitConnected();
207
205
  const driver = requireEngineDriver(storedConnection);
208
206
  try {
209
207
  const result = await callMethod(driver);
210
208
  process.send({ msgtype: 'response', msgid, result });
211
209
  } catch (err) {
210
+ logger.error(err, `Error when handling message ${logName}`);
212
211
  process.send({ msgtype: 'response', msgid, errorMessage: err.message });
213
212
  }
214
213
  }
215
214
 
215
+ async function handleSchemaList({ msgid }) {
216
+ logger.debug('Loading schema list');
217
+ return handleDriverDataCore(msgid, driver => driver.listSchemas(dbhan), { logName: 'listSchemas' });
218
+ }
219
+
216
220
  async function handleCollectionData({ msgid, options }) {
217
- return handleDriverDataCore(msgid, driver => driver.readCollection(systemConnection, options));
221
+ return handleDriverDataCore(msgid, driver => driver.readCollection(dbhan, options), { logName: 'readCollection' });
218
222
  }
219
223
 
220
224
  async function handleLoadKeys({ msgid, root, filter }) {
221
- return handleDriverDataCore(msgid, driver => driver.loadKeys(systemConnection, root, filter));
225
+ return handleDriverDataCore(msgid, driver => driver.loadKeys(dbhan, root, filter), { logName: 'loadKeys' });
222
226
  }
223
227
 
224
228
  async function handleExportKeys({ msgid, options }) {
225
- return handleDriverDataCore(msgid, driver => driver.exportKeys(systemConnection, options));
229
+ return handleDriverDataCore(msgid, driver => driver.exportKeys(dbhan, options), { logName: 'exportKeys' });
226
230
  }
227
231
 
228
232
  async function handleLoadKeyInfo({ msgid, key }) {
229
- return handleDriverDataCore(msgid, driver => driver.loadKeyInfo(systemConnection, key));
233
+ return handleDriverDataCore(msgid, driver => driver.loadKeyInfo(dbhan, key), { logName: 'loadKeyInfo' });
230
234
  }
231
235
 
232
236
  async function handleCallMethod({ msgid, method, args }) {
233
- return handleDriverDataCore(msgid, driver => {
234
- if (storedConnection.isReadOnly) {
235
- throw new Error('Connection is read only, cannot call custom methods');
236
- }
237
-
238
- ensureExecuteCustomScript(driver);
239
- return driver.callMethod(systemConnection, method, args);
240
- });
237
+ return handleDriverDataCore(
238
+ msgid,
239
+ driver => {
240
+ if (storedConnection.isReadOnly) {
241
+ throw new Error('Connection is read only, cannot call custom methods');
242
+ }
243
+
244
+ ensureExecuteCustomScript(driver);
245
+ return driver.callMethod(dbhan, method, args);
246
+ },
247
+ { logName: `callMethod:${method}` }
248
+ );
241
249
  }
242
250
 
243
251
  async function handleLoadKeyTableRange({ msgid, key, cursor, count }) {
244
- return handleDriverDataCore(msgid, driver => driver.loadKeyTableRange(systemConnection, key, cursor, count));
252
+ return handleDriverDataCore(msgid, driver => driver.loadKeyTableRange(dbhan, key, cursor, count), {
253
+ logName: 'loadKeyTableRange',
254
+ });
245
255
  }
246
256
 
247
257
  async function handleLoadFieldValues({ msgid, schemaName, pureName, field, search }) {
248
- return handleDriverDataCore(msgid, driver =>
249
- driver.loadFieldValues(systemConnection, { schemaName, pureName }, field, search)
250
- );
258
+ return handleDriverDataCore(msgid, driver => driver.loadFieldValues(dbhan, { schemaName, pureName }, field, search), {
259
+ logName: 'loadFieldValues',
260
+ });
251
261
  }
252
262
 
253
263
  function ensureExecuteCustomScript(driver) {
@@ -264,7 +274,7 @@ async function handleUpdateCollection({ msgid, changeSet }) {
264
274
  const driver = requireEngineDriver(storedConnection);
265
275
  try {
266
276
  ensureExecuteCustomScript(driver);
267
- const result = await driver.updateCollection(systemConnection, changeSet);
277
+ const result = await driver.updateCollection(dbhan, changeSet);
268
278
  process.send({ msgtype: 'response', msgid, result });
269
279
  } catch (err) {
270
280
  process.send({ msgtype: 'response', msgid, errorMessage: err.message });
@@ -277,7 +287,7 @@ async function handleSqlPreview({ msgid, objects, options }) {
277
287
 
278
288
  try {
279
289
  const dmp = driver.createDumper();
280
- const generator = new SqlGenerator(analysedStructure, options, objects, dmp, driver, systemConnection);
290
+ const generator = new SqlGenerator(analysedStructure, options, objects, dmp, driver, dbhan);
281
291
 
282
292
  await generator.dump();
283
293
  process.send({ msgtype: 'response', msgid, sql: dmp.s, isTruncated: generator.isTruncated });
@@ -297,7 +307,7 @@ async function handleGenerateDeploySql({ msgid, modelFolder }) {
297
307
 
298
308
  try {
299
309
  const res = await generateDeploySql({
300
- systemConnection,
310
+ systemConnection: dbhan,
301
311
  connection: storedConnection,
302
312
  analysedStructure,
303
313
  modelFolder,
@@ -337,6 +347,7 @@ const messageHandlers = {
337
347
  loadFieldValues: handleLoadFieldValues,
338
348
  sqlSelect: handleSqlSelect,
339
349
  exportKeys: handleExportKeys,
350
+ schemaList: handleSchemaList,
340
351
  // runCommand: handleRunCommand,
341
352
  };
342
353
 
@@ -16,7 +16,7 @@ class ImportStream extends stream.Transform {
16
16
  }
17
17
  async _transform(chunk, encoding, cb) {
18
18
  try {
19
- await this.driver.script(this.pool, chunk);
19
+ await this.driver.script(this.pool, chunk, { queryOptions: { importSqlDump: true } });
20
20
  } catch (err) {
21
21
  this.emit('error', err.message);
22
22
  }
@@ -47,7 +47,9 @@ async function importDatabase({ connection = undefined, systemConnection = undef
47
47
  const pool = systemConnection || (await connectUtility(driver, connection, 'write'));
48
48
  logger.info(`Connected.`);
49
49
 
50
+ logger.info(`Input file: ${inputFile}`);
50
51
  const downloadedFile = await download(inputFile);
52
+ logger.info(`Downloaded file: ${downloadedFile}`);
51
53
 
52
54
  const fileStream = fs.createReadStream(downloadedFile, 'utf-8');
53
55
  const splittedStream = splitQueryStream(fileStream, driver.getQuerySplitterOptions('script'));
@@ -6,7 +6,7 @@ const copyStream = require('./copyStream');
6
6
  const fakeObjectReader = require('./fakeObjectReader');
7
7
  const consoleObjectWriter = require('./consoleObjectWriter');
8
8
  const jsonLinesWriter = require('./jsonLinesWriter');
9
- const jsonArrayWriter = require('./jsonArrayWriter');
9
+ const jsonWriter = require('./jsonWriter');
10
10
  const jsonLinesReader = require('./jsonLinesReader');
11
11
  const sqlDataWriter = require('./sqlDataWriter');
12
12
  const jslDataReader = require('./jslDataReader');
@@ -29,6 +29,7 @@ const modifyJsonLinesReader = require('./modifyJsonLinesReader');
29
29
  const dataDuplicator = require('./dataDuplicator');
30
30
  const dbModelToJson = require('./dbModelToJson');
31
31
  const jsonToDbModel = require('./jsonToDbModel');
32
+ const jsonReader = require('./jsonReader');
32
33
 
33
34
  const dbgateApi = {
34
35
  queryReader,
@@ -37,8 +38,9 @@ const dbgateApi = {
37
38
  tableReader,
38
39
  copyStream,
39
40
  jsonLinesWriter,
40
- jsonArrayWriter,
41
41
  jsonLinesReader,
42
+ jsonReader,
43
+ jsonWriter,
42
44
  sqlDataWriter,
43
45
  fakeObjectReader,
44
46
  consoleObjectWriter,
@@ -2,6 +2,7 @@ const fs = require('fs');
2
2
  const stream = require('stream');
3
3
  const byline = require('byline');
4
4
  const { getLogger } = require('dbgate-tools');
5
+ const download = require('./download');
5
6
  const logger = getLogger('jsonLinesReader');
6
7
 
7
8
  class ParseStream extends stream.Transform {
@@ -35,8 +36,10 @@ class ParseStream extends stream.Transform {
35
36
  async function jsonLinesReader({ fileName, encoding = 'utf-8', limitRows = undefined }) {
36
37
  logger.info(`Reading file ${fileName}`);
37
38
 
39
+ const downloadedFile = await download(fileName);
40
+
38
41
  const fileStream = fs.createReadStream(
39
- fileName,
42
+ downloadedFile,
40
43
  // @ts-ignore
41
44
  encoding
42
45
  );
@@ -0,0 +1,84 @@
1
+ const fs = require('fs');
2
+ const stream = require('stream');
3
+ const byline = require('byline');
4
+ const { getLogger } = require('dbgate-tools');
5
+ const { parser } = require('stream-json');
6
+ const { pick } = require('stream-json/filters/Pick');
7
+ const { streamArray } = require('stream-json/streamers/StreamArray');
8
+ const { streamObject } = require('stream-json/streamers/StreamObject');
9
+ const download = require('./download');
10
+
11
+ const logger = getLogger('jsonReader');
12
+
13
+
14
+ class ParseStream extends stream.Transform {
15
+ constructor({ limitRows, jsonStyle, keyField }) {
16
+ super({ objectMode: true });
17
+ this.wasHeader = false;
18
+ this.limitRows = limitRows;
19
+ this.jsonStyle = jsonStyle;
20
+ this.keyField = keyField || '_key';
21
+ this.rowsWritten = 0;
22
+ }
23
+ _transform(chunk, encoding, done) {
24
+ if (!this.wasHeader) {
25
+ this.push({
26
+ __isStreamHeader: true,
27
+ __isDynamicStructure: true,
28
+ });
29
+
30
+ this.wasHeader = true;
31
+ }
32
+ if (!this.limitRows || this.rowsWritten < this.limitRows) {
33
+ if (this.jsonStyle === 'object') {
34
+ this.push({
35
+ ...chunk.value,
36
+ [this.keyField]: chunk.key,
37
+ });
38
+ } else {
39
+ this.push(chunk.value);
40
+ }
41
+
42
+ this.rowsWritten += 1;
43
+ }
44
+ done();
45
+ }
46
+ }
47
+
48
+ async function jsonReader({
49
+ fileName,
50
+ jsonStyle,
51
+ keyField = '_key',
52
+ rootField = null,
53
+ encoding = 'utf-8',
54
+ limitRows = undefined,
55
+ }) {
56
+ logger.info(`Reading file ${fileName}`);
57
+
58
+ const downloadedFile = await download(fileName);
59
+ const fileStream = fs.createReadStream(
60
+ downloadedFile,
61
+ // @ts-ignore
62
+ encoding
63
+ );
64
+ const parseJsonStream = parser();
65
+ fileStream.pipe(parseJsonStream);
66
+
67
+ const parseStream = new ParseStream({ limitRows, jsonStyle, keyField });
68
+
69
+ const tramsformer = jsonStyle === 'object' ? streamObject() : streamArray();
70
+
71
+ if (rootField) {
72
+ const filterStream = pick({ filter: rootField });
73
+ parseJsonStream.pipe(filterStream);
74
+ filterStream.pipe(tramsformer);
75
+ } else {
76
+ parseJsonStream.pipe(tramsformer);
77
+ }
78
+
79
+ tramsformer.pipe(parseStream);
80
+
81
+ return parseStream;
82
+ }
83
+
84
+ module.exports = jsonReader;
@@ -0,0 +1,97 @@
1
+ const { getLogger } = require('dbgate-tools');
2
+ const fs = require('fs');
3
+ const stream = require('stream');
4
+ const _ = require('lodash');
5
+
6
+ const logger = getLogger('jsonArrayWriter');
7
+
8
+ class StringifyStream extends stream.Transform {
9
+ constructor({ jsonStyle, keyField, rootField }) {
10
+ super({ objectMode: true });
11
+ this.wasHeader = false;
12
+ this.wasRecord = false;
13
+ this.jsonStyle = jsonStyle;
14
+ this.keyField = keyField || '_key';
15
+ this.rootField = rootField;
16
+ }
17
+ _transform(chunk, encoding, done) {
18
+ let skip = false;
19
+
20
+ if (!this.wasHeader) {
21
+ skip = chunk.__isStreamHeader;
22
+ this.wasHeader = true;
23
+ }
24
+ if (!skip) {
25
+ if (!this.wasRecord) {
26
+ if (this.rootField) {
27
+ if (this.jsonStyle === 'object') {
28
+ this.push(`{"${this.rootField}": {\n`);
29
+ } else {
30
+ this.push(`{"${this.rootField}": [\n`);
31
+ }
32
+ } else {
33
+ if (this.jsonStyle === 'object') {
34
+ this.push('{\n');
35
+ } else {
36
+ this.push('[\n');
37
+ }
38
+ }
39
+ } else {
40
+ this.push(',\n');
41
+ }
42
+ this.wasRecord = true;
43
+
44
+ if (this.jsonStyle === 'object') {
45
+ const key = chunk[this.keyField] ?? chunk[Object.keys(chunk)[0]];
46
+ this.push(`"${key}": ${JSON.stringify(_.omit(chunk, [this.keyField]))}`);
47
+ } else {
48
+ this.push(JSON.stringify(chunk));
49
+ }
50
+ }
51
+ done();
52
+ }
53
+
54
+ _flush(done) {
55
+ if (!this.wasRecord) {
56
+ if (this.rootField) {
57
+ if (this.jsonStyle === 'object') {
58
+ this.push(`{"${this.rootField}": {}}\n`);
59
+ } else {
60
+ this.push(`{"${this.rootField}": []}\n`);
61
+ }
62
+ } else {
63
+ if (this.jsonStyle === 'object') {
64
+ this.push('{}\n');
65
+ } else {
66
+ this.push('[]\n');
67
+ }
68
+ }
69
+ } else {
70
+ if (this.rootField) {
71
+ if (this.jsonStyle === 'object') {
72
+ this.push('\n}}\n');
73
+ } else {
74
+ this.push('\n]}\n');
75
+ }
76
+ } else {
77
+ if (this.jsonStyle === 'object') {
78
+ this.push('\n}\n');
79
+ } else {
80
+ this.push('\n]\n');
81
+ }
82
+ }
83
+ }
84
+ done();
85
+ }
86
+ }
87
+
88
+ async function jsonWriter({ fileName, jsonStyle, keyField = '_key', rootField, encoding = 'utf-8' }) {
89
+ logger.info(`Writing file ${fileName}`);
90
+ const stringify = new StringifyStream({ jsonStyle, keyField, rootField });
91
+ const fileStream = fs.createWriteStream(fileName, encoding);
92
+ stringify.pipe(fileStream);
93
+ stringify['finisher'] = fileStream;
94
+ return stringify;
95
+ }
96
+
97
+ module.exports = jsonWriter;
@@ -66,7 +66,7 @@ class ParseStream extends stream.Transform {
66
66
  ...obj,
67
67
  ...update.fields,
68
68
  },
69
- (v, k) => v.$$undefined$$
69
+ (v, k) => v?.$$undefined$$
70
70
  );
71
71
  }
72
72
  }
@@ -11,7 +11,7 @@ async function runScript(func) {
11
11
  await func();
12
12
  process.exit(0);
13
13
  } catch (err) {
14
- logger.error({ err }, `Error running script: ${err.message}`);
14
+ logger.error({ err }, `Error running script: ${err.message || err}`);
15
15
  process.exit(1);
16
16
  }
17
17
  }
@@ -1,52 +0,0 @@
1
- const { getLogger } = require('dbgate-tools');
2
- const fs = require('fs');
3
- const stream = require('stream');
4
-
5
- const logger = getLogger('jsonArrayWriter');
6
-
7
- class StringifyStream extends stream.Transform {
8
- constructor() {
9
- super({ objectMode: true });
10
- this.wasHeader = false;
11
- this.wasRecord = false;
12
- }
13
- _transform(chunk, encoding, done) {
14
- let skip = false;
15
-
16
- if (!this.wasHeader) {
17
- skip = chunk.__isStreamHeader;
18
- this.wasHeader = true;
19
- }
20
- if (!skip) {
21
- if (!this.wasRecord) {
22
- this.push('[\n');
23
- } else {
24
- this.push(',\n');
25
- }
26
- this.wasRecord = true;
27
-
28
- this.push(JSON.stringify(chunk));
29
- }
30
- done();
31
- }
32
-
33
- _flush(done) {
34
- if (!this.wasRecord) {
35
- this.push('[]\n');
36
- } else {
37
- this.push('\n]\n');
38
- }
39
- done();
40
- }
41
- }
42
-
43
- async function jsonArrayWriter({ fileName, encoding = 'utf-8' }) {
44
- logger.info(`Writing file ${fileName}`);
45
- const stringify = new StringifyStream();
46
- const fileStream = fs.createWriteStream(fileName, encoding);
47
- stringify.pipe(fileStream);
48
- stringify['finisher'] = fileStream;
49
- return stringify;
50
- }
51
-
52
- module.exports = jsonArrayWriter;