dbgate-api 6.8.1 → 7.0.0-alpha.10

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": "6.8.1",
4
+ "version": "7.0.0-alpha.10",
5
5
  "homepage": "https://dbgate.org/",
6
6
  "repository": {
7
7
  "type": "git",
@@ -30,10 +30,10 @@
30
30
  "compare-versions": "^3.6.0",
31
31
  "cors": "^2.8.5",
32
32
  "cross-env": "^6.0.3",
33
- "dbgate-datalib": "^6.8.1",
33
+ "dbgate-datalib": "^7.0.0-alpha.10",
34
34
  "dbgate-query-splitter": "^4.11.9",
35
- "dbgate-sqltree": "^6.8.1",
36
- "dbgate-tools": "^6.8.1",
35
+ "dbgate-sqltree": "^7.0.0-alpha.10",
36
+ "dbgate-tools": "^7.0.0-alpha.10",
37
37
  "debug": "^4.3.4",
38
38
  "diff": "^5.0.0",
39
39
  "diff2html": "^3.4.13",
@@ -87,7 +87,7 @@
87
87
  "devDependencies": {
88
88
  "@types/fs-extra": "^9.0.11",
89
89
  "@types/lodash": "^4.14.149",
90
- "dbgate-types": "^6.8.1",
90
+ "dbgate-types": "^7.0.0-alpha.10",
91
91
  "env-cmd": "^10.1.0",
92
92
  "jsdoc-to-markdown": "^9.0.5",
93
93
  "node-loader": "^1.0.2",
@@ -393,6 +393,12 @@ module.exports = {
393
393
  return null;
394
394
  },
395
395
 
396
+ dispatchRedisKeysChanged_meta: true,
397
+ dispatchRedisKeysChanged({ conid, database }) {
398
+ socket.emit(`redis-keys-changed-${conid}-${database}`);
399
+ return null;
400
+ },
401
+
396
402
  loadKeys_meta: true,
397
403
  async loadKeys({ conid, database, root, filter, limit }, req) {
398
404
  await testConnectionPermission(conid, req);
@@ -494,6 +500,20 @@ module.exports = {
494
500
  return res.result || null;
495
501
  },
496
502
 
503
+ multiCallMethod_meta: true,
504
+ async multiCallMethod({ conid, database, callList }, req) {
505
+ await testConnectionPermission(conid, req);
506
+
507
+ const opened = await this.ensureOpened(conid, database);
508
+ const res = await this.sendRequest(opened, { msgtype: 'multiCallMethod', callList });
509
+ if (res.errorMessage) {
510
+ return {
511
+ errorMessage: res.errorMessage,
512
+ };
513
+ }
514
+ return res.result || null;
515
+ },
516
+
497
517
  status_meta: true,
498
518
  async status({ conid, database }, req) {
499
519
  if (!conid) {
@@ -68,6 +68,7 @@ module.exports = {
68
68
  await fs.unlink(path.join(filesdir(), folder, file));
69
69
  socket.emitChanged(`files-changed`, { folder });
70
70
  socket.emitChanged(`all-files-changed`);
71
+ this.emitChangedFolder(folder);
71
72
  return true;
72
73
  },
73
74
 
@@ -140,6 +141,15 @@ module.exports = {
140
141
  return deserialize(format, text);
141
142
  },
142
143
 
144
+ emitChangedFolder(folder) {
145
+ if (folder == 'themes') {
146
+ socket.emitChanged(`file-themes-changed`);
147
+ }
148
+ if (folder == 'favorites') {
149
+ socket.emitChanged('files-changed-favorites');
150
+ }
151
+ },
152
+
143
153
  save_meta: true,
144
154
  async save({ folder, file, data, format }, req) {
145
155
  const loadedPermissions = await loadPermissionsFromRequest(req);
@@ -173,6 +183,8 @@ module.exports = {
173
183
  if (folder == 'shell') {
174
184
  scheduler.reload();
175
185
  }
186
+ this.emitChangedFolder(folder);
187
+
176
188
  return true;
177
189
  }
178
190
  },
@@ -240,8 +252,8 @@ module.exports = {
240
252
  },
241
253
 
242
254
  exportDiagram_meta: true,
243
- async exportDiagram({ filePath, html, css, themeType, themeClassName, watermark }) {
244
- await fs.writeFile(filePath, getDiagramExport(html, css, themeType, themeClassName, watermark));
255
+ async exportDiagram({ filePath, html, css, themeType, themeVariables, watermark }) {
256
+ await fs.writeFile(filePath, getDiagramExport(html, css, themeType, themeVariables, watermark));
245
257
  return true;
246
258
  },
247
259
 
@@ -346,4 +358,20 @@ module.exports = {
346
358
  }
347
359
  return res;
348
360
  },
361
+
362
+ getFileThemes_meta: true,
363
+ async getFileThemes(_params, req) {
364
+ const loadedPermissions = await loadPermissionsFromRequest(req);
365
+ if (!hasPermission(`files/themes/read`, loadedPermissions)) return [];
366
+ const dir = path.join(filesdir(), 'themes');
367
+ if (!(await fs.exists(dir))) return [];
368
+ const files = await fs.readdir(dir);
369
+ const res = [];
370
+ for (const file of files) {
371
+ const filePath = path.join(dir, file);
372
+ const text = await fs.readFile(filePath, { encoding: 'utf-8' });
373
+ res.push(JSON.parse(text));
374
+ }
375
+ return res;
376
+ },
349
377
  };
@@ -1,5 +1,5 @@
1
1
 
2
2
  module.exports = {
3
- version: '6.8.1',
4
- buildTime: '2025-12-22T10:53:13.010Z'
3
+ version: '7.0.0-alpha.10',
4
+ buildTime: '2026-01-22T08:39:44.429Z'
5
5
  };
package/src/index.js CHANGED
@@ -147,6 +147,7 @@ const shell = require('./shell/index');
147
147
  global.DBGATE_PACKAGES = {
148
148
  'dbgate-tools': require('dbgate-tools'),
149
149
  'dbgate-sqltree': require('dbgate-sqltree'),
150
+ 'dbgate-datalib': require('dbgate-datalib'),
150
151
  };
151
152
 
152
153
  if (processArgs.startProcess) {
@@ -368,6 +368,107 @@ async function handleSaveTableData({ msgid, changeSet }) {
368
368
  }
369
369
  }
370
370
 
371
+ async function handleMultiCallMethod({ msgid, callList }) {
372
+ try {
373
+ const driver = requireEngineDriver(storedConnection);
374
+ await driver.invokeMethodCallList(dbhan, callList);
375
+
376
+ // for (const change of changeSet.changes) {
377
+ // if (change.type === 'string') {
378
+ // await driver.query(dbhan, `SET "${change.key}" "${change.value}"`);
379
+ // } else if (change.type === 'json') {
380
+ // await driver.query(dbhan, `JSON.SET "${change.key}" $ '${change.value.replace(/'/g, "\\'")}'`);
381
+ // } else if (change.type === 'hash') {
382
+ // if (change.updates && Array.isArray(change.updates)) {
383
+ // for (const update of change.updates) {
384
+ // await driver.query(dbhan, `HSET "${change.key}" "${update.key}" "${update.value}"`);
385
+
386
+ // if (update.ttl !== undefined && update.ttl !== null && update.ttl !== -1) {
387
+ // try {
388
+ // await dbhan.client.call('HEXPIRE', change.key, update.ttl, 'FIELDS', 1, update.key);
389
+ // } catch (e) {}
390
+ // }
391
+ // }
392
+ // }
393
+ // if (change.inserts && Array.isArray(change.inserts)) {
394
+ // for (const insert of change.inserts) {
395
+ // await driver.query(dbhan, `HSET "${change.key}" "${insert.key}" "${insert.value}"`);
396
+
397
+ // if (insert.ttl !== undefined && insert.ttl !== null && insert.ttl !== -1) {
398
+ // try {
399
+ // await dbhan.client.call('HEXPIRE', change.key, insert.ttl, 'FIELDS', 1, insert.key);
400
+ // } catch (e) {}
401
+ // }
402
+ // }
403
+ // }
404
+ // if (change.deletes && Array.isArray(change.deletes)) {
405
+ // for (const delKey of change.deletes) {
406
+ // await driver.query(dbhan, `HDEL "${change.key}" "${delKey}"`);
407
+ // }
408
+ // }
409
+ // } else if (change.type === 'zset') {
410
+ // if (change.updates && Array.isArray(change.updates)) {
411
+ // for (const update of change.updates) {
412
+ // await driver.query(dbhan, `ZADD "${change.key}" ${update.score} "${update.member}"`);
413
+ // }
414
+ // }
415
+ // if (change.inserts && Array.isArray(change.inserts)) {
416
+ // for (const insert of change.inserts) {
417
+ // await driver.query(dbhan, `ZADD "${change.key}" ${insert.score} "${insert.member}"`);
418
+ // }
419
+ // }
420
+ // if (change.deletes && Array.isArray(change.deletes)) {
421
+ // for (const delMember of change.deletes) {
422
+ // await driver.query(dbhan, `ZREM "${change.key}" "${delMember}"`);
423
+ // }
424
+ // }
425
+ // } else if (change.type === 'list') {
426
+ // if (change.updates && Array.isArray(change.updates)) {
427
+ // for (const update of change.updates) {
428
+ // await driver.query(dbhan, `LSET "${change.key}" ${update.index} "${update.value}"`);
429
+ // }
430
+ // }
431
+ // if (change.inserts && Array.isArray(change.inserts)) {
432
+ // for (const insert of change.inserts) {
433
+ // await driver.query(dbhan, `RPUSH "${change.key}" "${insert.value}"`);
434
+ // }
435
+ // }
436
+ // } else if (change.type === 'set') {
437
+ // if (change.inserts && Array.isArray(change.inserts)) {
438
+ // for (const insert of change.inserts) {
439
+ // await driver.query(dbhan, `SADD "${change.key}" "${insert.value}"`);
440
+ // }
441
+ // }
442
+ // if (change.deletes && Array.isArray(change.deletes)) {
443
+ // for (const delValue of change.deletes) {
444
+ // await driver.query(dbhan, `SREM "${change.key}" "${delValue}"`);
445
+ // }
446
+ // }
447
+ // } else if (change.type === 'stream') {
448
+ // if (change.inserts && Array.isArray(change.inserts)) {
449
+ // for (const insert of change.inserts) {
450
+ // const streamId = insert.id === '*' || !insert.id ? '*' : insert.id;
451
+ // await driver.query(dbhan, `XADD "${change.key}" ${streamId} value "${insert.value}"`);
452
+ // }
453
+ // }
454
+ // if (change.deletes && Array.isArray(change.deletes)) {
455
+ // for (const delId of change.deletes) {
456
+ // await driver.query(dbhan, `XDEL "${change.key}" "${delId}"`);
457
+ // }
458
+ // }
459
+ // }
460
+ // }
461
+
462
+ process.send({ msgtype: 'response', msgid });
463
+ } catch (err) {
464
+ process.send({
465
+ msgtype: 'response',
466
+ msgid,
467
+ errorMessage: extractErrorMessage(err, 'Error saving Redis data'),
468
+ });
469
+ }
470
+ }
471
+
371
472
  async function handleSqlPreview({ msgid, objects, options }) {
372
473
  await waitStructure();
373
474
  const driver = requireEngineDriver(storedConnection);
@@ -501,6 +602,7 @@ const messageHandlers = {
501
602
  schemaList: handleSchemaList,
502
603
  executeSessionQuery: handleExecuteSessionQuery,
503
604
  evalJsonScript: handleEvalJsonScript,
605
+ multiCallMethod: handleMultiCallMethod,
504
606
  // runCommand: handleRunCommand,
505
607
  };
506
608
 
@@ -1498,6 +1498,86 @@ module.exports = {
1498
1498
  ]
1499
1499
  }
1500
1500
  },
1501
+ {
1502
+ "pureName": "role_team_folders",
1503
+ "columns": [
1504
+ {
1505
+ "pureName": "role_team_folders",
1506
+ "columnName": "id",
1507
+ "dataType": "int",
1508
+ "autoIncrement": true,
1509
+ "notNull": true
1510
+ },
1511
+ {
1512
+ "pureName": "role_team_folders",
1513
+ "columnName": "role_id",
1514
+ "dataType": "int",
1515
+ "notNull": true
1516
+ },
1517
+ {
1518
+ "pureName": "role_team_folders",
1519
+ "columnName": "team_folder_id",
1520
+ "dataType": "int",
1521
+ "notNull": true
1522
+ },
1523
+ {
1524
+ "pureName": "role_team_folders",
1525
+ "columnName": "allow_read_files",
1526
+ "dataType": "int",
1527
+ "notNull": false
1528
+ },
1529
+ {
1530
+ "pureName": "role_team_folders",
1531
+ "columnName": "allow_write_files",
1532
+ "dataType": "int",
1533
+ "notNull": false
1534
+ },
1535
+ {
1536
+ "pureName": "role_team_folders",
1537
+ "columnName": "allow_use_files",
1538
+ "dataType": "int",
1539
+ "notNull": false
1540
+ }
1541
+ ],
1542
+ "foreignKeys": [
1543
+ {
1544
+ "constraintType": "foreignKey",
1545
+ "constraintName": "FK_role_team_folders_role_id",
1546
+ "pureName": "role_team_folders",
1547
+ "refTableName": "roles",
1548
+ "deleteAction": "CASCADE",
1549
+ "columns": [
1550
+ {
1551
+ "columnName": "role_id",
1552
+ "refColumnName": "id"
1553
+ }
1554
+ ]
1555
+ },
1556
+ {
1557
+ "constraintType": "foreignKey",
1558
+ "constraintName": "FK_role_team_folders_team_folder_id",
1559
+ "pureName": "role_team_folders",
1560
+ "refTableName": "team_folders",
1561
+ "deleteAction": "CASCADE",
1562
+ "columns": [
1563
+ {
1564
+ "columnName": "team_folder_id",
1565
+ "refColumnName": "id"
1566
+ }
1567
+ ]
1568
+ }
1569
+ ],
1570
+ "primaryKey": {
1571
+ "pureName": "role_team_folders",
1572
+ "constraintType": "primaryKey",
1573
+ "constraintName": "PK_role_team_folders",
1574
+ "columns": [
1575
+ {
1576
+ "columnName": "id"
1577
+ }
1578
+ ]
1579
+ }
1580
+ },
1501
1581
  {
1502
1582
  "pureName": "table_permission_roles",
1503
1583
  "columns": [
@@ -1655,6 +1735,14 @@ module.exports = {
1655
1735
  "columnName": "metadata",
1656
1736
  "dataType": "varchar(1000)",
1657
1737
  "notNull": false
1738
+ },
1739
+ {
1740
+ "pureName": "team_files",
1741
+ "columnName": "team_folder_id",
1742
+ "dataType": "int",
1743
+ "notNull": true,
1744
+ "defaultValue": -1,
1745
+ "defaultConstraint": "DF_team_files_team_folder_id"
1658
1746
  }
1659
1747
  ],
1660
1748
  "foreignKeys": [
@@ -1681,6 +1769,18 @@ module.exports = {
1681
1769
  "refColumnName": "id"
1682
1770
  }
1683
1771
  ]
1772
+ },
1773
+ {
1774
+ "constraintType": "foreignKey",
1775
+ "constraintName": "FK_team_files_team_folder_id",
1776
+ "pureName": "team_files",
1777
+ "refTableName": "team_folders",
1778
+ "columns": [
1779
+ {
1780
+ "columnName": "team_folder_id",
1781
+ "refColumnName": "id"
1782
+ }
1783
+ ]
1684
1784
  }
1685
1785
  ],
1686
1786
  "primaryKey": {
@@ -1765,6 +1865,41 @@ module.exports = {
1765
1865
  }
1766
1866
  ]
1767
1867
  },
1868
+ {
1869
+ "pureName": "team_folders",
1870
+ "columns": [
1871
+ {
1872
+ "pureName": "team_folders",
1873
+ "columnName": "id",
1874
+ "dataType": "int",
1875
+ "autoIncrement": true,
1876
+ "notNull": true
1877
+ },
1878
+ {
1879
+ "pureName": "team_folders",
1880
+ "columnName": "folder_name",
1881
+ "dataType": "varchar(250)",
1882
+ "notNull": false
1883
+ }
1884
+ ],
1885
+ "foreignKeys": [],
1886
+ "primaryKey": {
1887
+ "pureName": "team_folders",
1888
+ "constraintType": "primaryKey",
1889
+ "constraintName": "PK_team_folders",
1890
+ "columns": [
1891
+ {
1892
+ "columnName": "id"
1893
+ }
1894
+ ]
1895
+ },
1896
+ "preloadedRows": [
1897
+ {
1898
+ "id": -1,
1899
+ "folder_name": "default"
1900
+ }
1901
+ ]
1902
+ },
1768
1903
  {
1769
1904
  "pureName": "users",
1770
1905
  "columns": [
@@ -2363,6 +2498,86 @@ module.exports = {
2363
2498
  }
2364
2499
  ]
2365
2500
  }
2501
+ },
2502
+ {
2503
+ "pureName": "user_team_folders",
2504
+ "columns": [
2505
+ {
2506
+ "pureName": "user_team_folders",
2507
+ "columnName": "id",
2508
+ "dataType": "int",
2509
+ "autoIncrement": true,
2510
+ "notNull": true
2511
+ },
2512
+ {
2513
+ "pureName": "user_team_folders",
2514
+ "columnName": "user_id",
2515
+ "dataType": "int",
2516
+ "notNull": true
2517
+ },
2518
+ {
2519
+ "pureName": "user_team_folders",
2520
+ "columnName": "team_folder_id",
2521
+ "dataType": "int",
2522
+ "notNull": true
2523
+ },
2524
+ {
2525
+ "pureName": "user_team_folders",
2526
+ "columnName": "allow_read_files",
2527
+ "dataType": "int",
2528
+ "notNull": false
2529
+ },
2530
+ {
2531
+ "pureName": "user_team_folders",
2532
+ "columnName": "allow_write_files",
2533
+ "dataType": "int",
2534
+ "notNull": false
2535
+ },
2536
+ {
2537
+ "pureName": "user_team_folders",
2538
+ "columnName": "allow_use_files",
2539
+ "dataType": "int",
2540
+ "notNull": false
2541
+ }
2542
+ ],
2543
+ "foreignKeys": [
2544
+ {
2545
+ "constraintType": "foreignKey",
2546
+ "constraintName": "FK_user_team_folders_user_id",
2547
+ "pureName": "user_team_folders",
2548
+ "refTableName": "users",
2549
+ "deleteAction": "CASCADE",
2550
+ "columns": [
2551
+ {
2552
+ "columnName": "user_id",
2553
+ "refColumnName": "id"
2554
+ }
2555
+ ]
2556
+ },
2557
+ {
2558
+ "constraintType": "foreignKey",
2559
+ "constraintName": "FK_user_team_folders_team_folder_id",
2560
+ "pureName": "user_team_folders",
2561
+ "refTableName": "team_folders",
2562
+ "deleteAction": "CASCADE",
2563
+ "columns": [
2564
+ {
2565
+ "columnName": "team_folder_id",
2566
+ "refColumnName": "id"
2567
+ }
2568
+ ]
2569
+ }
2570
+ ],
2571
+ "primaryKey": {
2572
+ "pureName": "user_team_folders",
2573
+ "constraintType": "primaryKey",
2574
+ "constraintName": "PK_user_team_folders",
2575
+ "columns": [
2576
+ {
2577
+ "columnName": "id"
2578
+ }
2579
+ ]
2580
+ }
2366
2581
  }
2367
2582
  ],
2368
2583
  "collections": [],
@@ -69,6 +69,15 @@ function extractImportEntitiesFromEnv(env) {
69
69
  conid: crypto.randomUUID(),
70
70
  _id: undefined,
71
71
  id: index + 1, // autoincrement id
72
+
73
+ useDatabaseUrl: conn.useDatabaseUrl ? 1 : 0,
74
+ isReadOnly: conn.isReadOnly ? 1 : 0,
75
+ useSeparateSchemas: conn.useSeparateSchemas ? 1 : 0,
76
+ trustServerCertificate: conn.trustServerCertificate ? 1 : 0,
77
+ singleDatabase: conn.singleDatabase ? 1 : 0,
78
+ useSshTunnel: conn.useSshTunnel ? 1 : 0,
79
+ useSsl: conn.useSsl ? 1 : 0,
80
+ sslRejectUnauthorized: conn.sslRejectUnauthorized ? 1 : 0,
72
81
  }));
73
82
 
74
83
  const connectionEnvIdToDbId = {};
@@ -1,21 +1,29 @@
1
- const getDiagramExport = (html, css, themeType, themeClassName, watermark) => {
1
+ const getDiagramExport = (html, css, themeType, themeVariables, watermark) => {
2
2
  const watermarkHtml = watermark
3
3
  ? `
4
- <div style="position: fixed; bottom: 0; right: 0; padding: 5px; font-size: 12px; color: var(--theme-font-2); background-color: var(--theme-bg-2); border-top-left-radius: 5px; border: 1px solid var(--theme-border);">
4
+ <div style="position: fixed; bottom: 0; right: 0; padding: 5px; font-size: 12px; color: var(--theme-generic-font-grayed); background-color: var(--theme-datagrid-background); border-top-left-radius: 5px; border: var(--theme-card-border);">
5
5
  ${watermark}
6
6
  </div>
7
7
  `
8
8
  : '';
9
+
10
+ // Convert theme variables object to CSS custom properties
11
+ const themeVariablesCSS = themeVariables
12
+ ? `:root {\n${Object.entries(themeVariables).map(([key, value]) => ` ${key}: ${value};`).join('\n')}\n}`
13
+ : '';
14
+
9
15
  return `<html>
10
16
  <meta charset='utf-8'>
11
17
 
12
18
  <head>
13
19
  <style>
20
+ ${themeVariablesCSS}
21
+
14
22
  ${css}
15
23
 
16
24
  body {
17
- background: var(--theme-bg-1);
18
- color: var(--theme-font-1);
25
+ background: var(--theme-datagrid-background);
26
+ color: var(--theme-generic-font);
19
27
  }
20
28
  </style>
21
29
 
@@ -55,7 +63,7 @@ const getDiagramExport = (html, css, themeType, themeClassName, watermark) => {
55
63
  </script>
56
64
  </head>
57
65
 
58
- <body class='${themeType == 'dark' ? 'theme-type-dark' : 'theme-type-light'} ${themeClassName}' style='user-select:none; cursor:pointer'>
66
+ <body class='${themeType == 'dark' ? 'theme-type-dark' : 'theme-type-light'}' style='user-select:none; cursor:pointer'>
59
67
  ${html}
60
68
  ${watermarkHtml}
61
69
  </body>