dbgate-api 6.5.4 → 6.5.6

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.
@@ -12,6 +12,7 @@ const { testConnectionPermission } = require('../utility/hasPermission');
12
12
  const { MissingCredentialsError } = require('../utility/exceptions');
13
13
  const pipeForkLogs = require('../utility/pipeForkLogs');
14
14
  const { getLogger, extractErrorLogData } = require('dbgate-tools');
15
+ const { sendToAuditLog } = require('../utility/auditlog');
15
16
 
16
17
  const logger = getLogger('serverConnection');
17
18
 
@@ -145,6 +146,17 @@ module.exports = {
145
146
  if (conid == '__model') return [];
146
147
  testConnectionPermission(conid, req);
147
148
  const opened = await this.ensureOpened(conid);
149
+ sendToAuditLog(req, {
150
+ category: 'serverop',
151
+ component: 'ServerConnectionsController',
152
+ action: 'listDatabases',
153
+ event: 'databases.list',
154
+ severity: 'info',
155
+ conid,
156
+ sessionParam: `${conid}`,
157
+ sessionGroup: 'listDatabases',
158
+ message: `Loaded databases for connection`,
159
+ });
148
160
  return opened?.databases ?? [];
149
161
  },
150
162
 
@@ -11,6 +11,7 @@ const { appdir } = require('../utility/directories');
11
11
  const { getLogger, extractErrorLogData } = require('dbgate-tools');
12
12
  const pipeForkLogs = require('../utility/pipeForkLogs');
13
13
  const config = require('./config');
14
+ const { sendToAuditLog } = require('../utility/auditlog');
14
15
 
15
16
  const logger = getLogger('sessions');
16
17
 
@@ -146,12 +147,24 @@ module.exports = {
146
147
  },
147
148
 
148
149
  executeQuery_meta: true,
149
- async executeQuery({ sesid, sql, autoCommit, autoDetectCharts, limitRows, frontMatter }) {
150
+ async executeQuery({ sesid, sql, autoCommit, autoDetectCharts, limitRows, frontMatter }, req) {
150
151
  const session = this.opened.find(x => x.sesid == sesid);
151
152
  if (!session) {
152
153
  throw new Error('Invalid session');
153
154
  }
154
155
 
156
+ sendToAuditLog(req, {
157
+ category: 'dbop',
158
+ component: 'SessionController',
159
+ action: 'executeQuery',
160
+ event: 'query.execute',
161
+ severity: 'info',
162
+ detail: sql,
163
+ conid: session.conid,
164
+ database: session.database,
165
+ message: 'Executing query',
166
+ });
167
+
155
168
  logger.info({ sesid, sql }, 'Processing query');
156
169
  this.dispatchMessage(sesid, 'Query execution started');
157
170
  session.subprocess.send({
@@ -31,6 +31,11 @@ module.exports = {
31
31
  return {};
32
32
  },
33
33
 
34
+ sendAuditLog_meta: true,
35
+ async sendAuditLog({}) {
36
+ return null;
37
+ },
38
+
34
39
  startRefreshLicense() {},
35
40
 
36
41
  async getUsedEngines() {
@@ -1,5 +1,5 @@
1
1
 
2
2
  module.exports = {
3
- version: '6.5.4',
4
- buildTime: '2025-06-20T15:05:12.349Z'
3
+ version: '6.5.6',
4
+ buildTime: '2025-07-17T07:05:52.324Z'
5
5
  };
@@ -14,7 +14,7 @@ const crypto = require('crypto');
14
14
  * @param {object} options.driver - driver object. If not provided, it will be loaded from connection
15
15
  * @param {object} options.analysedStructure - analysed structure of the database. If not provided, it will be loaded
16
16
  * @param {string} options.modelFolder - folder with model files (YAML files for tables, SQL files for views, procedures, ...)
17
- * @param {import('dbgate-tools').DatabaseModelFile[]} options.loadedDbModel - loaded database model - collection of yaml and SQL files loaded into array
17
+ * @param {import('dbgate-tools').DatabaseModelFile[] | import('dbgate-types').DatabaseInfo} options.loadedDbModel - loaded database model - collection of yaml and SQL files loaded into array
18
18
  * @param {function[]} options.modelTransforms - array of functions for transforming model
19
19
  * @param {object} options.dbdiffOptionsExtra - extra options for dbdiff
20
20
  * @param {string} options.ignoreNameRegex - regex for ignoring objects by name
@@ -23,7 +23,7 @@ const { connectUtility } = require('../utility/connectUtility');
23
23
  * @param {object} options.driver - driver object. If not provided, it will be loaded from connection
24
24
  * @param {object} options.analysedStructure - analysed structure of the database. If not provided, it will be loaded
25
25
  * @param {string} options.modelFolder - folder with model files (YAML files for tables, SQL files for views, procedures, ...)
26
- * @param {import('dbgate-tools').DatabaseModelFile[]} options.loadedDbModel - loaded database model - collection of yaml and SQL files loaded into array
26
+ * @param {import('dbgate-tools').DatabaseModelFile[] | import('dbgate-types').DatabaseInfo} options.loadedDbModel - loaded database model - collection of yaml and SQL files loaded into array
27
27
  * @param {function[]} options.modelTransforms - array of functions for transforming model
28
28
  * @param {object} options.dbdiffOptionsExtra - extra options for dbdiff
29
29
  * @param {string} options.ignoreNameRegex - regex for ignoring objects by name
@@ -3,7 +3,7 @@ const fs = require('fs-extra');
3
3
  const executeQuery = require('./executeQuery');
4
4
  const { connectUtility } = require('../utility/connectUtility');
5
5
  const requireEngineDriver = require('../utility/requireEngineDriver');
6
- const { getAlterDatabaseScript, DatabaseAnalyser, runCommandOnDriver } = require('dbgate-tools');
6
+ const { getAlterDatabaseScript, DatabaseAnalyser, runCommandOnDriver, adaptDatabaseInfo } = require('dbgate-tools');
7
7
  const importDbModel = require('../utility/importDbModel');
8
8
  const jsonLinesReader = require('./jsonLinesReader');
9
9
  const tableWriter = require('./tableWriter');
@@ -26,10 +26,7 @@ async function importDbFromFolder({ connection, systemConnection, driver, folder
26
26
  if (driver?.databaseEngineTypes?.includes('sql')) {
27
27
  const model = await importDbModel(folder);
28
28
 
29
- let modelAdapted = {
30
- ...model,
31
- tables: model.tables.map(table => driver.adaptTableInfo(table)),
32
- };
29
+ let modelAdapted = adaptDatabaseInfo(model, driver);
33
30
  for (const transform of modelTransforms || []) {
34
31
  modelAdapted = transform(modelAdapted);
35
32
  }
@@ -1,5 +1,192 @@
1
1
  module.exports = {
2
2
  "tables": [
3
+ {
4
+ "pureName": "audit_log",
5
+ "columns": [
6
+ {
7
+ "pureName": "audit_log",
8
+ "columnName": "id",
9
+ "dataType": "int",
10
+ "autoIncrement": true,
11
+ "notNull": true
12
+ },
13
+ {
14
+ "pureName": "audit_log",
15
+ "columnName": "created",
16
+ "dataType": "bigint",
17
+ "notNull": true
18
+ },
19
+ {
20
+ "pureName": "audit_log",
21
+ "columnName": "modified",
22
+ "dataType": "bigint",
23
+ "notNull": false
24
+ },
25
+ {
26
+ "pureName": "audit_log",
27
+ "columnName": "user_id",
28
+ "dataType": "int",
29
+ "notNull": false
30
+ },
31
+ {
32
+ "pureName": "audit_log",
33
+ "columnName": "user_login",
34
+ "dataType": "varchar(250)",
35
+ "notNull": false
36
+ },
37
+ {
38
+ "pureName": "audit_log",
39
+ "columnName": "category",
40
+ "dataType": "varchar(50)",
41
+ "notNull": false
42
+ },
43
+ {
44
+ "pureName": "audit_log",
45
+ "columnName": "component",
46
+ "dataType": "varchar(50)",
47
+ "notNull": false
48
+ },
49
+ {
50
+ "pureName": "audit_log",
51
+ "columnName": "action",
52
+ "dataType": "varchar(50)",
53
+ "notNull": false
54
+ },
55
+ {
56
+ "pureName": "audit_log",
57
+ "columnName": "severity",
58
+ "dataType": "varchar(50)",
59
+ "notNull": false
60
+ },
61
+ {
62
+ "pureName": "audit_log",
63
+ "columnName": "event",
64
+ "dataType": "varchar(100)",
65
+ "notNull": false
66
+ },
67
+ {
68
+ "pureName": "audit_log",
69
+ "columnName": "message",
70
+ "dataType": "varchar(250)",
71
+ "notNull": false
72
+ },
73
+ {
74
+ "pureName": "audit_log",
75
+ "columnName": "detail",
76
+ "dataType": "varchar(1000)",
77
+ "notNull": false
78
+ },
79
+ {
80
+ "pureName": "audit_log",
81
+ "columnName": "detail_full_length",
82
+ "dataType": "int",
83
+ "notNull": false
84
+ },
85
+ {
86
+ "pureName": "audit_log",
87
+ "columnName": "session_id",
88
+ "dataType": "varchar(200)",
89
+ "notNull": false
90
+ },
91
+ {
92
+ "pureName": "audit_log",
93
+ "columnName": "session_group",
94
+ "dataType": "varchar(50)",
95
+ "notNull": false
96
+ },
97
+ {
98
+ "pureName": "audit_log",
99
+ "columnName": "session_param",
100
+ "dataType": "varchar(200)",
101
+ "notNull": false
102
+ },
103
+ {
104
+ "pureName": "audit_log",
105
+ "columnName": "conid",
106
+ "dataType": "varchar(100)",
107
+ "notNull": false
108
+ },
109
+ {
110
+ "pureName": "audit_log",
111
+ "columnName": "connection_data",
112
+ "dataType": "varchar(1000)",
113
+ "notNull": false
114
+ },
115
+ {
116
+ "pureName": "audit_log",
117
+ "columnName": "database",
118
+ "dataType": "varchar(200)",
119
+ "notNull": false
120
+ },
121
+ {
122
+ "pureName": "audit_log",
123
+ "columnName": "schema_name",
124
+ "dataType": "varchar(100)",
125
+ "notNull": false
126
+ },
127
+ {
128
+ "pureName": "audit_log",
129
+ "columnName": "pure_name",
130
+ "dataType": "varchar(100)",
131
+ "notNull": false
132
+ },
133
+ {
134
+ "pureName": "audit_log",
135
+ "columnName": "sumint_1",
136
+ "dataType": "int",
137
+ "notNull": false
138
+ },
139
+ {
140
+ "pureName": "audit_log",
141
+ "columnName": "sumint_2",
142
+ "dataType": "int",
143
+ "notNull": false
144
+ }
145
+ ],
146
+ "foreignKeys": [
147
+ {
148
+ "constraintType": "foreignKey",
149
+ "constraintName": "FK_audit_log_user_id",
150
+ "pureName": "audit_log",
151
+ "refTableName": "users",
152
+ "deleteAction": "SET NULL",
153
+ "columns": [
154
+ {
155
+ "columnName": "user_id",
156
+ "refColumnName": "id"
157
+ }
158
+ ]
159
+ }
160
+ ],
161
+ "indexes": [
162
+ {
163
+ "constraintName": "idx_audit_log_session",
164
+ "pureName": "audit_log",
165
+ "constraintType": "index",
166
+ "columns": [
167
+ {
168
+ "columnName": "session_group"
169
+ },
170
+ {
171
+ "columnName": "session_id"
172
+ },
173
+ {
174
+ "columnName": "session_param"
175
+ }
176
+ ]
177
+ }
178
+ ],
179
+ "primaryKey": {
180
+ "pureName": "audit_log",
181
+ "constraintType": "primaryKey",
182
+ "constraintName": "PK_audit_log",
183
+ "columns": [
184
+ {
185
+ "columnName": "id"
186
+ }
187
+ ]
188
+ }
189
+ },
3
190
  {
4
191
  "pureName": "auth_methods",
5
192
  "columns": [
@@ -50,6 +237,7 @@ module.exports = {
50
237
  "primaryKey": {
51
238
  "pureName": "auth_methods",
52
239
  "constraintType": "primaryKey",
240
+ "constraintName": "PK_auth_methods",
53
241
  "columns": [
54
242
  {
55
243
  "columnName": "id"
@@ -61,7 +249,8 @@ module.exports = {
61
249
  "id": -1,
62
250
  "amoid": "790ca4d2-7f01-4800-955b-d691b890cc50",
63
251
  "name": "Anonymous",
64
- "type": "none"
252
+ "type": "none",
253
+ "is_disabled": 1
65
254
  },
66
255
  {
67
256
  "id": -2,
@@ -69,6 +258,9 @@ module.exports = {
69
258
  "name": "Local",
70
259
  "type": "local"
71
260
  }
261
+ ],
262
+ "preloadedRowsInsertOnly": [
263
+ "is_disabled"
72
264
  ]
73
265
  },
74
266
  {
@@ -103,6 +295,7 @@ module.exports = {
103
295
  "foreignKeys": [
104
296
  {
105
297
  "constraintType": "foreignKey",
298
+ "constraintName": "FK_auth_methods_config_auth_method_id",
106
299
  "pureName": "auth_methods_config",
107
300
  "refTableName": "auth_methods",
108
301
  "deleteAction": "CASCADE",
@@ -114,9 +307,25 @@ module.exports = {
114
307
  ]
115
308
  }
116
309
  ],
310
+ "uniques": [
311
+ {
312
+ "constraintName": "UQ_auth_methods_config_auth_method_id_key",
313
+ "pureName": "auth_methods_config",
314
+ "constraintType": "unique",
315
+ "columns": [
316
+ {
317
+ "columnName": "auth_method_id"
318
+ },
319
+ {
320
+ "columnName": "key"
321
+ }
322
+ ]
323
+ }
324
+ ],
117
325
  "primaryKey": {
118
326
  "pureName": "auth_methods_config",
119
327
  "constraintType": "primaryKey",
328
+ "constraintName": "PK_auth_methods_config",
120
329
  "columns": [
121
330
  {
122
331
  "columnName": "id"
@@ -154,9 +363,25 @@ module.exports = {
154
363
  }
155
364
  ],
156
365
  "foreignKeys": [],
366
+ "uniques": [
367
+ {
368
+ "constraintName": "UQ_config_group_key",
369
+ "pureName": "config",
370
+ "constraintType": "unique",
371
+ "columns": [
372
+ {
373
+ "columnName": "group"
374
+ },
375
+ {
376
+ "columnName": "key"
377
+ }
378
+ ]
379
+ }
380
+ ],
157
381
  "primaryKey": {
158
382
  "pureName": "config",
159
383
  "constraintType": "primaryKey",
384
+ "constraintName": "PK_config",
160
385
  "columns": [
161
386
  {
162
387
  "columnName": "id"
@@ -294,6 +519,12 @@ module.exports = {
294
519
  "dataType": "int",
295
520
  "notNull": false
296
521
  },
522
+ {
523
+ "pureName": "connections",
524
+ "columnName": "useSeparateSchemas",
525
+ "dataType": "int",
526
+ "notNull": false
527
+ },
297
528
  {
298
529
  "pureName": "connections",
299
530
  "columnName": "defaultDatabase",
@@ -449,6 +680,7 @@ module.exports = {
449
680
  "primaryKey": {
450
681
  "pureName": "connections",
451
682
  "constraintType": "primaryKey",
683
+ "constraintName": "PK_connections",
452
684
  "columns": [
453
685
  {
454
686
  "columnName": "id"
@@ -477,6 +709,7 @@ module.exports = {
477
709
  "primaryKey": {
478
710
  "pureName": "roles",
479
711
  "constraintType": "primaryKey",
712
+ "constraintName": "PK_roles",
480
713
  "columns": [
481
714
  {
482
715
  "columnName": "id"
@@ -524,6 +757,7 @@ module.exports = {
524
757
  "foreignKeys": [
525
758
  {
526
759
  "constraintType": "foreignKey",
760
+ "constraintName": "FK_role_connections_role_id",
527
761
  "pureName": "role_connections",
528
762
  "refTableName": "roles",
529
763
  "deleteAction": "CASCADE",
@@ -536,6 +770,7 @@ module.exports = {
536
770
  },
537
771
  {
538
772
  "constraintType": "foreignKey",
773
+ "constraintName": "FK_role_connections_connection_id",
539
774
  "pureName": "role_connections",
540
775
  "refTableName": "connections",
541
776
  "deleteAction": "CASCADE",
@@ -550,6 +785,7 @@ module.exports = {
550
785
  "primaryKey": {
551
786
  "pureName": "role_connections",
552
787
  "constraintType": "primaryKey",
788
+ "constraintName": "PK_role_connections",
553
789
  "columns": [
554
790
  {
555
791
  "columnName": "id"
@@ -583,6 +819,7 @@ module.exports = {
583
819
  "foreignKeys": [
584
820
  {
585
821
  "constraintType": "foreignKey",
822
+ "constraintName": "FK_role_permissions_role_id",
586
823
  "pureName": "role_permissions",
587
824
  "refTableName": "roles",
588
825
  "deleteAction": "CASCADE",
@@ -597,6 +834,7 @@ module.exports = {
597
834
  "primaryKey": {
598
835
  "pureName": "role_permissions",
599
836
  "constraintType": "primaryKey",
837
+ "constraintName": "PK_role_permissions",
600
838
  "columns": [
601
839
  {
602
840
  "columnName": "id"
@@ -637,6 +875,7 @@ module.exports = {
637
875
  "primaryKey": {
638
876
  "pureName": "users",
639
877
  "constraintType": "primaryKey",
878
+ "constraintName": "PK_users",
640
879
  "columns": [
641
880
  {
642
881
  "columnName": "id"
@@ -670,6 +909,7 @@ module.exports = {
670
909
  "foreignKeys": [
671
910
  {
672
911
  "constraintType": "foreignKey",
912
+ "constraintName": "FK_user_connections_user_id",
673
913
  "pureName": "user_connections",
674
914
  "refTableName": "users",
675
915
  "deleteAction": "CASCADE",
@@ -682,6 +922,7 @@ module.exports = {
682
922
  },
683
923
  {
684
924
  "constraintType": "foreignKey",
925
+ "constraintName": "FK_user_connections_connection_id",
685
926
  "pureName": "user_connections",
686
927
  "refTableName": "connections",
687
928
  "deleteAction": "CASCADE",
@@ -696,6 +937,7 @@ module.exports = {
696
937
  "primaryKey": {
697
938
  "pureName": "user_connections",
698
939
  "constraintType": "primaryKey",
940
+ "constraintName": "PK_user_connections",
699
941
  "columns": [
700
942
  {
701
943
  "columnName": "id"
@@ -729,6 +971,7 @@ module.exports = {
729
971
  "foreignKeys": [
730
972
  {
731
973
  "constraintType": "foreignKey",
974
+ "constraintName": "FK_user_permissions_user_id",
732
975
  "pureName": "user_permissions",
733
976
  "refTableName": "users",
734
977
  "deleteAction": "CASCADE",
@@ -743,6 +986,7 @@ module.exports = {
743
986
  "primaryKey": {
744
987
  "pureName": "user_permissions",
745
988
  "constraintType": "primaryKey",
989
+ "constraintName": "PK_user_permissions",
746
990
  "columns": [
747
991
  {
748
992
  "columnName": "id"
@@ -776,6 +1020,7 @@ module.exports = {
776
1020
  "foreignKeys": [
777
1021
  {
778
1022
  "constraintType": "foreignKey",
1023
+ "constraintName": "FK_user_roles_user_id",
779
1024
  "pureName": "user_roles",
780
1025
  "refTableName": "users",
781
1026
  "deleteAction": "CASCADE",
@@ -788,6 +1033,7 @@ module.exports = {
788
1033
  },
789
1034
  {
790
1035
  "constraintType": "foreignKey",
1036
+ "constraintName": "FK_user_roles_role_id",
791
1037
  "pureName": "user_roles",
792
1038
  "refTableName": "roles",
793
1039
  "deleteAction": "CASCADE",
@@ -802,6 +1048,7 @@ module.exports = {
802
1048
  "primaryKey": {
803
1049
  "pureName": "user_roles",
804
1050
  "constraintType": "primaryKey",
1051
+ "constraintName": "PK_user_roles",
805
1052
  "columns": [
806
1053
  {
807
1054
  "columnName": "id"
@@ -815,5 +1062,6 @@ module.exports = {
815
1062
  "matviews": [],
816
1063
  "functions": [],
817
1064
  "procedures": [],
818
- "triggers": []
1065
+ "triggers": [],
1066
+ "schedulerEvents": []
819
1067
  };
@@ -0,0 +1,9 @@
1
+ // only in DbGate Premium
2
+
3
+ async function sendToAuditLog(req, props) {}
4
+ async function logJsonRunnerScript(req, script) {}
5
+
6
+ module.exports = {
7
+ sendToAuditLog,
8
+ logJsonRunnerScript,
9
+ };
@@ -40,6 +40,12 @@ function getLicenseHttpHeaders() {
40
40
  return {};
41
41
  }
42
42
 
43
+ async function tryToGetRefreshedLicense(oldLicenseKey) {
44
+ return {
45
+ status: 'error',
46
+ };
47
+ }
48
+
43
49
  module.exports = {
44
50
  isAuthProxySupported,
45
51
  authProxyGetRedirectUrl,
@@ -52,4 +58,5 @@ module.exports = {
52
58
  callCompleteOnCursorApi,
53
59
  callRefactorSqlQueryApi,
54
60
  getLicenseHttpHeaders,
61
+ tryToGetRefreshedLicense,
55
62
  };
@@ -1,4 +1,5 @@
1
1
  const axios = require('axios');
2
+ const crypto = require('crypto');
2
3
  const fs = require('fs-extra');
3
4
  const _ = require('lodash');
4
5
  const path = require('path');
@@ -34,11 +35,12 @@ const DBGATE_CLOUD_URL = process.env.LOCAL_DBGATE_CLOUD
34
35
  ? 'https://cloud.dbgate.udolni.net'
35
36
  : 'https://cloud.dbgate.io';
36
37
 
37
- async function createDbGateIdentitySession(client) {
38
+ async function createDbGateIdentitySession(client, redirectUri) {
38
39
  const resp = await axios.default.post(
39
40
  `${DBGATE_IDENTITY_URL}/api/create-session`,
40
41
  {
41
42
  client,
43
+ redirectUri,
42
44
  },
43
45
  {
44
46
  headers: {
@@ -70,7 +72,7 @@ function startCloudTokenChecking(sid, callback) {
70
72
  });
71
73
  // console.log('CHECK RESP:', resp.data);
72
74
 
73
- if (resp.data.email) {
75
+ if (resp.data?.email) {
74
76
  clearInterval(interval);
75
77
  callback(resp.data);
76
78
  }
@@ -80,6 +82,34 @@ function startCloudTokenChecking(sid, callback) {
80
82
  }, 500);
81
83
  }
82
84
 
85
+ async function readCloudTokenHolder(sid) {
86
+ const resp = await axios.default.get(`${DBGATE_IDENTITY_URL}/api/get-token/${sid}`, {
87
+ headers: {
88
+ ...getLicenseHttpHeaders(),
89
+ },
90
+ });
91
+ if (resp.data?.email) {
92
+ return resp.data;
93
+ }
94
+ return null;
95
+ }
96
+
97
+ async function readCloudTestTokenHolder(email) {
98
+ const resp = await axios.default.post(
99
+ `${DBGATE_IDENTITY_URL}/api/test-token`,
100
+ { email },
101
+ {
102
+ headers: {
103
+ ...getLicenseHttpHeaders(),
104
+ },
105
+ }
106
+ );
107
+ if (resp.data?.email) {
108
+ return resp.data;
109
+ }
110
+ return null;
111
+ }
112
+
83
113
  async function loadCloudFiles() {
84
114
  try {
85
115
  const fileContent = await fs.readFile(path.join(datadir(), 'cloud-files.jsonl'), 'utf-8');
@@ -187,7 +217,7 @@ async function updateCloudFiles(isRefresh) {
187
217
  {
188
218
  headers: {
189
219
  ...getLicenseHttpHeaders(),
190
- ...(await getCloudSigninHeaders()),
220
+ ...(await getCloudInstanceHeaders()),
191
221
  'x-app-version': currentVersion.version,
192
222
  },
193
223
  }
@@ -271,6 +301,17 @@ async function callCloudApiGet(endpoint, signinHolder = null, additionalHeaders
271
301
  return resp.data;
272
302
  }
273
303
 
304
+ async function getCloudInstanceHeaders() {
305
+ if (!(await fs.exists(path.join(datadir(), 'cloud-instance.txt')))) {
306
+ const newInstanceId = crypto.randomUUID();
307
+ await fs.writeFile(path.join(datadir(), 'cloud-instance.txt'), newInstanceId);
308
+ }
309
+ const instanceId = await fs.readFile(path.join(datadir(), 'cloud-instance.txt'), 'utf-8');
310
+ return {
311
+ 'x-cloud-instance': instanceId,
312
+ };
313
+ }
314
+
274
315
  async function callCloudApiPost(endpoint, body, signinHolder = null) {
275
316
  if (!signinHolder) {
276
317
  signinHolder = await getCloudSigninHolder();
@@ -396,4 +437,6 @@ module.exports = {
396
437
  loadCachedCloudConnection,
397
438
  putCloudContent,
398
439
  removeCloudCachedConnection,
440
+ readCloudTokenHolder,
441
+ readCloudTestTokenHolder,
399
442
  };