terminusdb 12.0.2

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.
Files changed (86) hide show
  1. package/Contributing.md +36 -0
  2. package/LICENSE +201 -0
  3. package/README.md +175 -0
  4. package/RELEASE_NOTES.md +462 -0
  5. package/dist/index.html +22 -0
  6. package/dist/terminusdb-client.min.js +3 -0
  7. package/dist/terminusdb-client.min.js.LICENSE.txt +188 -0
  8. package/dist/terminusdb-client.min.js.map +1 -0
  9. package/dist/typescript/index.d.ts +14 -0
  10. package/dist/typescript/lib/accessControl.d.ts +554 -0
  11. package/dist/typescript/lib/axiosInstance.d.ts +2 -0
  12. package/dist/typescript/lib/connectionConfig.d.ts +381 -0
  13. package/dist/typescript/lib/const.d.ts +54 -0
  14. package/dist/typescript/lib/dispatchRequest.d.ts +17 -0
  15. package/dist/typescript/lib/errorMessage.d.ts +25 -0
  16. package/dist/typescript/lib/query/woqlBuilder.d.ts +75 -0
  17. package/dist/typescript/lib/query/woqlCore.d.ts +341 -0
  18. package/dist/typescript/lib/query/woqlDoc.d.ts +63 -0
  19. package/dist/typescript/lib/query/woqlLibrary.d.ts +718 -0
  20. package/dist/typescript/lib/query/woqlPrinter.d.ts +71 -0
  21. package/dist/typescript/lib/query/woqlQuery.d.ts +833 -0
  22. package/dist/typescript/lib/typedef.d.ts +624 -0
  23. package/dist/typescript/lib/utils.d.ts +199 -0
  24. package/dist/typescript/lib/valueHash.d.ts +146 -0
  25. package/dist/typescript/lib/viewer/chartConfig.d.ts +62 -0
  26. package/dist/typescript/lib/viewer/chooserConfig.d.ts +38 -0
  27. package/dist/typescript/lib/viewer/documentFrame.d.ts +44 -0
  28. package/dist/typescript/lib/viewer/frameConfig.d.ts +74 -0
  29. package/dist/typescript/lib/viewer/frameRule.d.ts +145 -0
  30. package/dist/typescript/lib/viewer/graphConfig.d.ts +73 -0
  31. package/dist/typescript/lib/viewer/objectFrame.d.ts +212 -0
  32. package/dist/typescript/lib/viewer/streamConfig.d.ts +23 -0
  33. package/dist/typescript/lib/viewer/tableConfig.d.ts +66 -0
  34. package/dist/typescript/lib/viewer/terminusRule.d.ts +75 -0
  35. package/dist/typescript/lib/viewer/viewConfig.d.ts +47 -0
  36. package/dist/typescript/lib/viewer/woqlChart.d.ts +1 -0
  37. package/dist/typescript/lib/viewer/woqlChooser.d.ts +56 -0
  38. package/dist/typescript/lib/viewer/woqlGraph.d.ts +26 -0
  39. package/dist/typescript/lib/viewer/woqlPaging.d.ts +1 -0
  40. package/dist/typescript/lib/viewer/woqlResult.d.ts +128 -0
  41. package/dist/typescript/lib/viewer/woqlRule.d.ts +96 -0
  42. package/dist/typescript/lib/viewer/woqlStream.d.ts +31 -0
  43. package/dist/typescript/lib/viewer/woqlTable.d.ts +102 -0
  44. package/dist/typescript/lib/viewer/woqlView.d.ts +49 -0
  45. package/dist/typescript/lib/woql.d.ts +1267 -0
  46. package/dist/typescript/lib/woqlClient.d.ts +1216 -0
  47. package/index.js +28 -0
  48. package/lib/.eslintrc +1 -0
  49. package/lib/accessControl.js +988 -0
  50. package/lib/axiosInstance.js +5 -0
  51. package/lib/connectionConfig.js +765 -0
  52. package/lib/const.js +59 -0
  53. package/lib/dispatchRequest.js +236 -0
  54. package/lib/errorMessage.js +110 -0
  55. package/lib/query/woqlBuilder.js +234 -0
  56. package/lib/query/woqlCore.js +934 -0
  57. package/lib/query/woqlDoc.js +177 -0
  58. package/lib/query/woqlLibrary.js +1015 -0
  59. package/lib/query/woqlPrinter.js +476 -0
  60. package/lib/query/woqlQuery.js +1865 -0
  61. package/lib/typedef.js +248 -0
  62. package/lib/utils.js +817 -0
  63. package/lib/valueHash.js_old +581 -0
  64. package/lib/viewer/chartConfig.js +411 -0
  65. package/lib/viewer/chooserConfig.js +234 -0
  66. package/lib/viewer/documentFrame.js +206 -0
  67. package/lib/viewer/frameConfig.js +469 -0
  68. package/lib/viewer/frameRule.js +519 -0
  69. package/lib/viewer/graphConfig.js +345 -0
  70. package/lib/viewer/objectFrame.js +1550 -0
  71. package/lib/viewer/streamConfig.js +82 -0
  72. package/lib/viewer/tableConfig.js +310 -0
  73. package/lib/viewer/terminusRule.js +196 -0
  74. package/lib/viewer/viewConfig.js +219 -0
  75. package/lib/viewer/woqlChart.js +17 -0
  76. package/lib/viewer/woqlChooser.js +171 -0
  77. package/lib/viewer/woqlGraph.js +295 -0
  78. package/lib/viewer/woqlPaging.js +148 -0
  79. package/lib/viewer/woqlResult.js +258 -0
  80. package/lib/viewer/woqlRule.js +312 -0
  81. package/lib/viewer/woqlStream.js +27 -0
  82. package/lib/viewer/woqlTable.js +332 -0
  83. package/lib/viewer/woqlView.js +107 -0
  84. package/lib/woql.js +1693 -0
  85. package/lib/woqlClient.js +2091 -0
  86. package/package.json +110 -0
@@ -0,0 +1,2091 @@
1
+ /* eslint-disable camelcase */
2
+ /* eslint-disable no-param-reassign */
3
+ /* eslint-disable no-underscore-dangle */
4
+ /* eslint-disable no-unused-vars */
5
+ /// /@ts-check
6
+ const FormData = require('form-data');
7
+ const fs = require('fs');
8
+ const { Buffer } = require('buffer');
9
+ const typedef = require('./typedef');
10
+ const CONST = require('./const');
11
+ const DispatchRequest = require('./dispatchRequest');
12
+ const ErrorMessage = require('./errorMessage');
13
+ const ConnectionConfig = require('./connectionConfig');
14
+ const WOQL = require('./woql');
15
+ const WOQLQuery = require('./query/woqlCore');
16
+
17
+ /**
18
+ * @typedef {Object} NamedResourceData
19
+ */
20
+
21
+ /**
22
+ * @license Apache Version 2
23
+ * @class
24
+ * @classdesc The core functionality of the TerminusDB javascript client is
25
+ * defined in the WOQLClient class - in the woqlClient.js file. This class provides
26
+ * methods which allow you to directly get and set all of the configuration and API
27
+ * endpoints of the client. The other parts of the WOQL core - connectionConfig.js
28
+ * and connectionCapabilities.js - are used by the client to store internal state - they
29
+ * should never have to be accessed directly. For situations where you want to communicate
30
+ * with a TerminusDB server API, the WOQLClient class is all you will need.
31
+ */
32
+ class WOQLClient {
33
+ connectionConfig = null;
34
+
35
+ databaseList = [];
36
+
37
+ organizationList = [];
38
+
39
+ /**
40
+ * @constructor
41
+ * @param {string} serverUrl - the terminusdb server url
42
+ * @param {typedef.ParamsObj} [params] - an object with the connection parameters
43
+ * @example
44
+ * //to connect with your local terminusDB. "key" is the password for the user
45
+ * //for admin, this is the initial password set during the installation
46
+ * const client = new TerminusClient.WOQLClient(SERVER_URL,{user:"admin",key:"myKey"})
47
+ * async function getSchema() {
48
+ * client.db("test")
49
+ * client.checkout("dev")
50
+ * const schema = await client.getSchema()
51
+ * }
52
+ * //The client has an internal state which defines what
53
+ * //organization / database / repository / branch / ref it is currently attached to
54
+ *
55
+ * //to connect with your TerminusDB Cloud Instance
56
+ * const client = new TerminusClient.WOQLClient('SERVER_CLOUD_URL/mycloudTeam',
57
+ * {user:"myemail@something.com", organization:'mycloudTeam'})
58
+ *
59
+ * client.setApiKey(MY_ACCESS_TOKEN)
60
+ *
61
+ * //to get the list of all organization's databases
62
+ * async function callGetDatabases(){
63
+ * const dbList = await client.getDatabases()
64
+ * console.log(dbList)
65
+ * }
66
+ *
67
+ * async function getSchema() {
68
+ * client.db("test")
69
+ * client.checkout("dev")
70
+ * const schema = await client.getSchema()
71
+ * }
72
+ */
73
+ constructor(serverUrl, params) {
74
+ this.connectionConfig = new ConnectionConfig(serverUrl, params);
75
+ }
76
+ }
77
+
78
+ /**
79
+ * set the api key to access the cloud resources
80
+ * @param {string} accessToken
81
+ */
82
+ WOQLClient.prototype.setApiKey = function (accessToken) {
83
+ const currentAuth = this.connectionConfig.localAuth() || {};
84
+ currentAuth.key = accessToken;
85
+ currentAuth.type = 'apikey';
86
+ this.connectionConfig.setLocalAuth(currentAuth);
87
+ };
88
+
89
+ /**
90
+ * add extra headers to your request
91
+ * @param {object} customHeaders
92
+ * @returns {object}
93
+ */
94
+
95
+ // eslint-disable-next-line consistent-return
96
+ WOQLClient.prototype.customHeaders = function (customHeaders) {
97
+ if (customHeaders) this._customHeaders = customHeaders;
98
+ else return this._customHeaders;
99
+ };
100
+
101
+ WOQLClient.prototype.CONST = CONST;
102
+
103
+ /**
104
+ * creates a copy of the client with identical internal state and context
105
+ * useful if we want to change context for a particular API call without changing
106
+ * the current client context
107
+ * @returns {WOQLClient} new client object with identical state to original but
108
+ * which can be manipulated independently
109
+ * @example
110
+ * let newClient = client.copy()
111
+ */
112
+ WOQLClient.prototype.copy = function () {
113
+ const other = new WOQLClient(this.server());
114
+ // other.connection = this.connection //keep same connection meta data - shared by copy
115
+ other.connectionConfig = this.connectionConfig.copy(); // new copy of current connection data
116
+ other.databaseList = this.databaseList;
117
+ return other;
118
+ };
119
+
120
+ /**
121
+ * Gets the current connected server url
122
+ * it can only be set creating a new WOQLCLient instance
123
+ * @returns {string}
124
+ */
125
+ WOQLClient.prototype.server = function () {
126
+ return this.connectionConfig.serverURL();
127
+ };
128
+
129
+ /**
130
+ * Retrieve the URL of the server’s API base that we are currently connected to
131
+ * @returns {string} the URL of the TerminusDB server api endpoint we are connected
132
+ * to (typically server() + “api/”)
133
+ * @example
134
+ * let api_url = client.api()
135
+ */
136
+ WOQLClient.prototype.api = function () {
137
+ return this.connectionConfig.apiURL();
138
+ };
139
+
140
+ /**
141
+ * Gets/Sets the client’s internal organization context value, if you change the organization
142
+ * name the databases list will be set to empty
143
+ * @param {string | boolean} [orgId] the organization id to set the context to
144
+ * @returns {string | boolean}
145
+ * @example
146
+ * client.organization("admin")
147
+ */
148
+ WOQLClient.prototype.organization = function (orgId) {
149
+ if (typeof orgId !== 'undefined') {
150
+ this.connectionConfig.setOrganization(orgId);
151
+ // we have to reset the databases list
152
+ this.databases([]);
153
+ }
154
+ return this.connectionConfig.organization();
155
+ };
156
+
157
+ /**
158
+ * Checks if a database exists
159
+ *
160
+ * Returns true if a DB exists and false if it doesn't. Other results
161
+ * throw an exception.
162
+ * @param {string} [orgName] the organization id to set the context to
163
+ * @param {string} [dbName] the db name to set the context to
164
+ * @returns {Promise}
165
+ * @example
166
+ * async function executeIfDatabaseExists(f){
167
+ * const hasDB = await client.hasDatabase("admin", "testdb")
168
+ * if (hasDB) {
169
+ * f()
170
+ * }
171
+ * }
172
+ */
173
+ WOQLClient.prototype.hasDatabase = async function (orgName, dbName) {
174
+ const dbCheckUrl = `${this.connectionConfig.apiURL()}db/${orgName}/${dbName}`;
175
+ return new Promise((resolve, reject) => {
176
+ this.dispatch(CONST.HEAD, dbCheckUrl).then((req) => {
177
+ resolve(true);
178
+ }).catch((err) => {
179
+ if (err.status === 404) {
180
+ resolve(false);
181
+ } else {
182
+ reject(err);
183
+ }
184
+ });
185
+ });
186
+ };
187
+
188
+ /**
189
+ * Gets the organization's databases list.
190
+ *
191
+ * If no organization has been set up, the function throws an exception
192
+ * @returns {Promise}
193
+ * @example
194
+ * async function callGetDatabases(){
195
+ * const dbList = await client.getDatabases()
196
+ * console.log(dbList)
197
+ * }
198
+ */
199
+ WOQLClient.prototype.getDatabases = async function () {
200
+ // return response
201
+ if (!this.connectionConfig.organization()) {
202
+ throw new Error('You need to set the organization name');
203
+ }
204
+ // when we will have the end point to get the databases only for the current organization
205
+ // we'll change this call
206
+ await this.getUserOrganizations();
207
+ const dbs = this.userOrganizations().find(
208
+ (element) => element.name === this.connectionConfig.organization(),
209
+ );
210
+ const dbList = dbs && dbs.databases ? dbs.databases : [];
211
+ this.databases(dbList);
212
+ return dbList;
213
+ };
214
+
215
+ /**
216
+ * Set/Get the organization's databases list (id, label, comment) that the current
217
+ * user has access to on the server.
218
+ * @param {array} [dbList] a list of databases the user has access to on the server, each having:
219
+ * @returns {array} the organization's databases list
220
+ * @example
221
+ * //to get the list of all organization's databases
222
+ * async function callGetDatabases(){
223
+ * await client.getDatabases()
224
+ * console.log(client.databases())
225
+ * }
226
+ *
227
+ */
228
+ WOQLClient.prototype.databases = function (dbList) {
229
+ if (dbList) this.databaseList = dbList;
230
+ return this.databaseList || [];
231
+ };
232
+
233
+ /**
234
+ * Gets the current user object as returned by the connect capabilities response
235
+ * user has fields: [id, name, notes, author]
236
+ * @returns {Object}
237
+ */
238
+ WOQLClient.prototype.user = function () {
239
+ // this is the locacal
240
+ return this.connectionConfig.user();
241
+ };
242
+
243
+ /**
244
+ * @desription Gets the user's organization id
245
+ * @returns {string} the user organization name
246
+ */
247
+ // this is something that need review
248
+ WOQLClient.prototype.userOrganization = function () {
249
+ return this.user();
250
+ };
251
+
252
+ /**
253
+ * Gets the database's details
254
+ * @param {string} [dbName] - the datbase name
255
+ * @returns {object} the database description object
256
+ */
257
+ WOQLClient.prototype.databaseInfo = function (dbName) {
258
+ // const dbIdVal = dbId || this.db();
259
+ // const orgIdVal = orgId || this.organization()
260
+ const database = this.databases().find((element) => element.name === dbName);
261
+ return database || {};
262
+ };
263
+
264
+ /**
265
+ * Sets / Gets the current database
266
+ * @param {string} [dbId] - the database id to set the context to
267
+ * @returns {string|boolean} - the current database or false
268
+ * @example
269
+ * client.db("mydb")
270
+ */
271
+ WOQLClient.prototype.db = function (dbId) {
272
+ if (typeof dbId !== 'undefined') {
273
+ this.connectionConfig.setDB(dbId);
274
+ }
275
+ return this.connectionConfig.dbid;
276
+ };
277
+
278
+ /**
279
+ *Sets the internal client context to allow it to talk to the server’s internal system database
280
+ *
281
+ */
282
+ WOQLClient.prototype.setSystemDb = function () {
283
+ this.db(this.connectionConfig.system_db);
284
+ };
285
+
286
+ /**
287
+ * Gets / Sets the client’s internal repository context value (defaults to ‘local’)
288
+ * @param {typedef.RepoType | string} [repoId] - default value is local
289
+ * @returns {string} the current repository id within the client context
290
+ * @example
291
+ * client.repo("origin")
292
+ */
293
+ WOQLClient.prototype.repo = function (repoId) {
294
+ if (typeof repoId !== 'undefined') {
295
+ this.connectionConfig.setRepo(repoId);
296
+ }
297
+ return this.connectionConfig.repo();
298
+ };
299
+
300
+ /**
301
+ * Gets/Sets the client’s internal branch context value (defaults to ‘main’)
302
+ * @param {string} [branchId] - the branch id to set the context to
303
+ * @returns {string} the current branch id within the client context
304
+ */
305
+ WOQLClient.prototype.checkout = function (branchId) {
306
+ if (typeof branchId !== 'undefined') {
307
+ this.connectionConfig.setBranch(branchId);
308
+ }
309
+ return this.connectionConfig.branch();
310
+ };
311
+
312
+ /**
313
+ * Sets / gets the current ref pointer (pointer to a commit within a branch)
314
+ * Reference ID or Commit ID are unique hashes that are created whenever a new commit is recorded
315
+ * @param {string} [commitId] - the reference ID or commit ID
316
+ * @returns {string|boolean} the current commit id within the client context
317
+ * @example
318
+ * client.ref("mkz98k2h3j8cqjwi3wxxzuyn7cr6cw7")
319
+ */
320
+ WOQLClient.prototype.ref = function (commitId) {
321
+ if (typeof commitId !== 'undefined') {
322
+ this.connectionConfig.setRef(commitId);
323
+ }
324
+ return this.connectionConfig.ref();
325
+ };
326
+
327
+ /**
328
+ * Sets/Gets set the database basic connection credential
329
+ * @param {typedef.CredentialObj} [newCredential]
330
+ * @returns {typedef.CredentialObj | boolean}
331
+ * @example
332
+ * client.localAuth({user:"admin","key":"mykey","type":"basic"})
333
+ */
334
+ WOQLClient.prototype.localAuth = function (newCredential) {
335
+ if (typeof newCredential !== 'undefined') {
336
+ this.connectionConfig.setLocalAuth(newCredential);
337
+ }
338
+ return this.connectionConfig.localAuth();
339
+ };
340
+ /**
341
+ * Use {@link #localAuth} instead.
342
+ * @deprecated
343
+ */
344
+
345
+ WOQLClient.prototype.local_auth = WOQLClient.prototype.localAuth;
346
+
347
+ /**
348
+ * Sets/Gets the jwt token for authentication
349
+ * we need this to connect 2 terminusdb server to each other for push, pull, clone actions
350
+ * @param {typedef.CredentialObj} [newCredential]
351
+ * @returns {typedef.CredentialObj | boolean}
352
+ * @example
353
+ * client.remoteAuth({"key":"dhfmnmjglkrelgkptohkn","type":"jwt"})
354
+ */
355
+ WOQLClient.prototype.remoteAuth = function (newCredential) {
356
+ if (typeof newCredential !== 'undefined') {
357
+ this.connectionConfig.setRemoteAuth(newCredential);
358
+ }
359
+ return this.connectionConfig.remoteAuth();
360
+ };
361
+
362
+ /**
363
+ * Use {@link #remoteAuth} instead.
364
+ * @deprecated
365
+ */
366
+
367
+ WOQLClient.prototype.remote_auth = WOQLClient.prototype.remoteAuth;
368
+
369
+ /**
370
+ * Gets the string that will be written into the commit log for the current user
371
+ * @returns {string} the current user
372
+ * @example
373
+ * client.author()
374
+ */
375
+ WOQLClient.prototype.author = function () {
376
+ // we have to review this with is the author in local and remote
377
+ // was a old functionality
378
+ // if (ignoreJwt) {
379
+ // this.connectionConfig.user(ignoreJwt)
380
+ // }
381
+ return this.connectionConfig.user();
382
+ };
383
+
384
+ /**
385
+ * @param {typedef.ParamsObj} params - a object with connection params
386
+ * @example sets several of the internal state values in a single call
387
+ * (similar to connect, but only sets internal client state, does not communicate with server)
388
+ * client.set({key: "mypass", branch: "dev", repo: "origin"})
389
+ */
390
+ WOQLClient.prototype.set = function (params) {
391
+ this.connectionConfig.update(params);
392
+ };
393
+
394
+ /**
395
+ * Generates a resource string for the required context
396
+ * of the current context for "commits" "meta" "branch" and "ref" special resources
397
+ * @param {typedef.ResourceType} resourceType - the type of resource string that is required - one
398
+ * of “db”, “meta”, “repo”, “commits”, “branch”, “ref”
399
+ * @param {string} [resourceId] - can be used to specify a specific branch / ref - if not supplied
400
+ * the current context will be used
401
+ * @returns {string} a resource string for the desired context
402
+ * @example
403
+ * const branch_resource = client.resource("branch")
404
+ */
405
+ // eslint-disable-next-line consistent-return
406
+ WOQLClient.prototype.resource = function (resourceType, resourceId) {
407
+ let base = `${this.organization()}/${this.db()}/`;
408
+ if (resourceType === 'db') return base;
409
+ if (resourceType === 'meta') return `${base}_meta`;
410
+ base += `${this.repo()}`;
411
+ if (resourceType === 'repo') return base;
412
+ if (resourceType === 'commits') return `${base}/_commits`;
413
+ const resourceIdValue = resourceId || (resourceType === 'ref' ? this.ref() : this.checkout());
414
+ if (resourceType === 'branch') return `${base}/branch/${resourceIdValue}`;
415
+ if (resourceType === 'ref') return `${base}/commit/${resourceIdValue}`;
416
+ };
417
+
418
+ /**
419
+ * You can call this to get the server info or override the start params
420
+ * configuration, this.connectionConfig.server will be used if present,
421
+ * or the promise will be rejected.
422
+ *
423
+ * @deprecated
424
+ *
425
+ * @param {typedef.ParamsObj} [params] - TerminusDB Server connection parameters
426
+ * @returns {Promise} the connection capabilities response object or an error object
427
+ * @example
428
+ * client.connect()
429
+ */
430
+ WOQLClient.prototype.connect = function (params) {
431
+ if (params) this.connectionConfig.update(params);
432
+ // unset the current server setting until successful connect
433
+ return this.dispatch(CONST.GET, this.connectionConfig.apiURLInfo()).then((response) => response);
434
+ };
435
+
436
+ /**
437
+ * Creates a new database in TerminusDB server
438
+ * @param {string} dbId - The id of the new database to be created
439
+ * @param {typedef.DbDetails} dbDetails - object containing details about the database to be created
440
+ * @param {string} [orgId] - optional organization id - if absent default local organization
441
+ * id is used
442
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
443
+ * @example
444
+ * //remember set schema:true if you need to add a schema graph
445
+ * client.createDatabase("mydb", {label: "My Database", comment: "Testing", schema: true})
446
+ */
447
+ // maybe we can pass only the detailObj it is have inside the dbid and org
448
+ WOQLClient.prototype.createDatabase = function (dbId, dbDetails, orgId) {
449
+ if (orgId) this.organization(orgId);
450
+ // console.log("createDatabase", orgId)
451
+ if (dbId) {
452
+ this.db(dbId);
453
+ // to be review
454
+ // console.log('____remoteURL_BFF__', this.connectionConfig.dbURL())
455
+ return this.dispatch(CONST.POST, this.connectionConfig.dbURL(), dbDetails);
456
+ }
457
+ const errmsg = `Create database parameter error - you must specify a valid database id - ${dbId} is invalid`;
458
+ return Promise.reject(
459
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.CREATE_DATABASE, errmsg)),
460
+ );
461
+ };
462
+
463
+ /**
464
+ * Update a database in TerminusDB server
465
+ * @param {typedef.DbDoc} dbDoc - object containing details about the database to be updated
466
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
467
+ * @example
468
+ * client.updateDatabase({id: "mydb", label: "My Database", comment: "Testing"})
469
+ */
470
+ WOQLClient.prototype.updateDatabase = function (dbDoc) {
471
+ const dbid = dbDoc.id || this.db();
472
+ this.organization(dbDoc.organization || this.organization());
473
+ if (dbid) {
474
+ this.db(dbid);
475
+ return this.dispatch(CONST.PUT, this.connectionConfig.dbURL(), dbDoc);
476
+ }
477
+ const errmsg = `Update database error - you must specify a valid database id - ${dbid} is invalid`;
478
+ return Promise.reject(
479
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.UPDATE_DATABASE, errmsg)),
480
+ );
481
+ };
482
+
483
+ /**
484
+ * Deletes a database from a TerminusDB server
485
+ * @param {string} dbId The id of the database to be deleted
486
+ * @param {string} [orgId] the id of the organization to which the database belongs
487
+ * (in desktop use, this will always be “admin”)
488
+ * @param {boolean} [force]
489
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
490
+ * @example
491
+ * client.deleteDatabase("mydb")
492
+ */
493
+ WOQLClient.prototype.deleteDatabase = function (dbId, orgId, force) {
494
+ const orgIdValue = orgId || this.organization();
495
+ this.organization(orgIdValue);
496
+ const payload = force ? { force: true } : null;
497
+ if (dbId && this.db(dbId)) {
498
+ return this.dispatch(CONST.DELETE, this.connectionConfig.dbURL(), payload);
499
+ }
500
+ const errmsg = `Delete database parameter error - you must specify a valid database id - ${dbId} is invalid`;
501
+ return Promise.reject(
502
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.DELETE, errmsg)),
503
+ );
504
+ };
505
+
506
+ /**
507
+ * Retrieve the contents of a graph within a TerminusDB as triples, encoded in
508
+ * the turtle (ttl) format
509
+ * @param {typedef.GraphType} graphType - type of graph to get triples from,
510
+ * either “instance” or “schema”
511
+ * @returns {Promise} A promise that returns the call response object (with
512
+ * the contents being a string representing a set of triples in turtle (ttl) format),
513
+ * or an Error if rejected.
514
+ * @example
515
+ * const turtle = await client.getTriples("schema", "alt")
516
+ */
517
+ WOQLClient.prototype.getTriples = function (graphType) {
518
+ if (graphType) {
519
+ return this.dispatch(
520
+ CONST.GET,
521
+ this.connectionConfig.triplesURL(graphType),
522
+ );
523
+ }
524
+ const errmsg = 'Get triples parameter error - you must specify a valid graph type (inference, instance, schema), and graph id';
525
+ return Promise.reject(
526
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.GET, errmsg)),
527
+ );
528
+ };
529
+
530
+ /**
531
+ * Replace the contents of the specified graph with the passed triples encoded
532
+ * in the turtle (ttl) format
533
+ * @param {string} graphType - type of graph |instance|schema|inference|
534
+ * @param {string} turtle - string encoding triples in turtle (ttl) format
535
+ * @param {string} commitMsg - Textual message describing the reason for the update
536
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
537
+ * @example
538
+ * client.updateTriples("schema", "alt", turtle_string, "dumping triples to graph alt")
539
+ */
540
+ WOQLClient.prototype.updateTriples = function (graphType, turtle, commitMsg) {
541
+ if (commitMsg && turtle && graphType) {
542
+ const commit = this.generateCommitInfo(commitMsg);
543
+ commit.turtle = turtle;
544
+ return this.dispatch(
545
+ CONST.UPDATE_TRIPLES,
546
+ this.connectionConfig.triplesURL(graphType),
547
+ commit,
548
+ );
549
+ }
550
+ const errmsg = 'Update triples parameter error - you must specify a valid graph id, graph type, turtle contents and commit message';
551
+ return Promise.reject(
552
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.UPDATE_TRIPLES, errmsg)),
553
+ );
554
+ };
555
+
556
+ /**
557
+ * Appends the passed turtle to the contents of a graph
558
+ * @param {string} graphType type of graph |instance|schema|inference|
559
+ * @param {string} turtle is a valid set of triples in turtle format (OWL)
560
+ * @param {string} commitMsg Textual message describing the reason for the update
561
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
562
+ */
563
+ WOQLClient.prototype.insertTriples = function (graphType, turtle, commitMsg) {
564
+ if (commitMsg && turtle && graphType) {
565
+ const commit = this.generateCommitInfo(commitMsg);
566
+ commit.turtle = turtle;
567
+ return this.dispatch(
568
+ CONST.INSERT_TRIPLES,
569
+ this.connectionConfig.triplesURL(graphType),
570
+ commit,
571
+ );
572
+ }
573
+ const errmsg = 'Update triples parameter error - you must specify a valid graph id, graph type, turtle contents and commit message';
574
+ return Promise.reject(
575
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.INSERT_TRIPLES, errmsg)),
576
+ );
577
+ };
578
+
579
+ /**
580
+ * Sends a message to the server
581
+ * @param {string} message - textual string
582
+ * @param {string} [pathname] - a server path to send the message to
583
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
584
+ */
585
+ WOQLClient.prototype.message = function (message, pathname) {
586
+ let url = this.api();
587
+ url += pathname ? this.api() + pathname : 'message';
588
+ return this.dispatch(CONST.GET, url, message).then((response) => response);
589
+ };
590
+
591
+ /**
592
+ * Sends an action to the server
593
+ * @param {string} actionName - structure of the action
594
+ * @param {object} [payload] - a request body call
595
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
596
+ */
597
+ WOQLClient.prototype.action = function (actionName, payload) {
598
+ const url = `${this.api()}action/${actionName}`;
599
+ return this.dispatch(CONST.ACTION, url, payload).then((response) => response);
600
+ };
601
+
602
+ /**
603
+ * Gets TerminusDB Server Information
604
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
605
+ * @example
606
+ * client.info()
607
+ */
608
+ WOQLClient.prototype.info = function () {
609
+ const url = `${this.api()}info`;
610
+ return this.dispatch(CONST.GET, url).then((response) => response);
611
+ };
612
+
613
+ // Get Resource objects from WOQL query
614
+ function getResourceObjects(queryObject, result_array) {
615
+ if (queryObject instanceof Array) {
616
+ for (let i = 0; i < queryObject.length; i += 1) {
617
+ getResourceObjects(queryObject[i], result_array);
618
+ }
619
+ } else {
620
+ const keys = Object.keys(queryObject);
621
+
622
+ for (let i = 0; i < keys.length; i += 1) {
623
+ if (keys[i] === 'resource') {
624
+ if (queryObject[keys[i]]['@type'] && queryObject[keys[i]]['@type'] === 'QueryResource') {
625
+ result_array.push(queryObject[keys[i]]);
626
+ }
627
+ }
628
+ if (queryObject[keys[i]] instanceof Object || queryObject[keys[i]] instanceof Array) {
629
+ getResourceObjects(queryObject[keys[i]], result_array);
630
+ }
631
+ }
632
+ }
633
+ }
634
+
635
+ /**
636
+ * Executes a WOQL query on the specified database and returns the results
637
+ * @param {WOQLQuery} woql - an instance of the WOQLQuery class
638
+ * @param {string} [commitMsg] - a message describing the reason for the change that will
639
+ * be written into the commit log (only relevant if the query contains an update)
640
+ * @param {boolean} [allWitnesses]
641
+ * @param {string} [lastDataVersion] the last data version tracking id.
642
+ * @param {boolean} [getDataVersion] If true the function will return object having result
643
+ * and dataVersion.
644
+ * @param {Array<NamedResourceData>} [resources] csv resources supplied as strings
645
+ * @returns {Promise} A promise that returns the call response object or object having *result*
646
+ * and *dataVersion* object if ***getDataVersion*** parameter is true, or an Error if rejected.
647
+ * @example
648
+ * const result = await client.query(WOQL.star())
649
+ */
650
+ WOQLClient.prototype.query = function (woql, commitMsg, allWitnesses, lastDataVersion = '', getDataVersion = false, resources = []) {
651
+ allWitnesses = allWitnesses || false;
652
+ commitMsg = commitMsg || 'Commit generated with javascript client without message';
653
+
654
+ const providedResourcesLookupMap = (resources ?? [])
655
+ .reduce((map, res) => ({ ...map, [(res.filename).split('/').pop()]: res.data }), {});
656
+
657
+ if (woql?.json && (!woql.containsUpdate() || commitMsg)) {
658
+ const doql = woql.containsUpdate() ? this.generateCommitInfo(commitMsg) : {};
659
+ doql.query = woql.json();
660
+
661
+ let postBody;
662
+ const resourceObjects = [];
663
+ getResourceObjects(doql.query, resourceObjects);
664
+
665
+ if (resourceObjects.length > 0) {
666
+ const formData = new FormData();
667
+
668
+ resourceObjects.forEach((resourceObject) => {
669
+ const providedResourceInsteadOfFile = typeof resourceObject.source.post === 'string'
670
+ ? providedResourcesLookupMap?.[resourceObject.source.post.split('/').pop()]
671
+ : undefined;
672
+
673
+ const fileName = resourceObject.source.post.split('/').pop();
674
+
675
+ if (providedResourceInsteadOfFile) {
676
+ formData.append('file', Buffer.from(providedResourceInsteadOfFile), { filename: fileName, contentType: 'application/csv' });
677
+ } else {
678
+ formData.append('file', fs.createReadStream(resourceObject.source.post));
679
+ }
680
+ resourceObject.source.post = fileName;
681
+ });
682
+
683
+ formData.append('payload', Buffer.from(JSON.stringify(doql)), { filename: 'body.json', contentType: 'application/json' });
684
+ if (formData.getHeaders) {
685
+ this.customHeaders(formData.getHeaders());
686
+ } else {
687
+ this.customHeaders({ 'Content-Type': 'multipart/form-data' });
688
+ }
689
+
690
+ postBody = formData;
691
+ } else {
692
+ postBody = doql;
693
+ }
694
+
695
+ if (allWitnesses) doql.all_witnesses = true;
696
+
697
+ if (typeof lastDataVersion === 'string' && lastDataVersion !== '') {
698
+ this.customHeaders({ 'TerminusDB-Data-Version': lastDataVersion });
699
+ }
700
+
701
+ // eslint-disable-next-line max-len
702
+ return this.dispatch(CONST.WOQL_QUERY, this.connectionConfig.queryURL(), postBody, getDataVersion);
703
+ }
704
+
705
+ let errmsg = 'WOQL query parameter error';
706
+ if (woql && woql.json && woql.containsUpdate() && !commitMsg) {
707
+ errmsg += ' - you must include a textual commit message to perform this update';
708
+ } else {
709
+ errmsg += ' - you must specify a valid WOQL Query';
710
+ }
711
+ return Promise.reject(
712
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.WOQL_QUERY, errmsg)),
713
+ );
714
+ };
715
+
716
+ /**
717
+ * Creates a new branch with a TerminusDB database, starting from the current context of
718
+ * the client (branch / ref)
719
+ * @param {string} newBranchId - local identifier of the new branch the ID of the new branch
720
+ * to be created
721
+ * @param {boolean} [isEmpty] - if isEmpty is true it will create a empty branch.
722
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
723
+ * @example
724
+ * client.branch("dev")
725
+ */
726
+ WOQLClient.prototype.branch = function (newBranchId, isEmpty) {
727
+ if (newBranchId) {
728
+ let source = this.ref()
729
+ ? { origin: `${this.organization()}/${this.db()}/${this.repo()}/commit/${this.ref()}` }
730
+ : {
731
+ origin: `${this.organization()}/${this.db()}/${this.repo()}/branch/${this.checkout()}`,
732
+ };
733
+
734
+ if (isEmpty && isEmpty === true) {
735
+ // @ts-ignore
736
+ source = {};
737
+ }
738
+ return this.dispatch(CONST.BRANCH, this.connectionConfig.branchURL(newBranchId), source);
739
+ }
740
+ const errmsg = 'Branch parameter error - you must specify a valid new branch id';
741
+ return Promise.reject(new Error(ErrorMessage.getInvalidParameterMessage(CONST.BRANCH, errmsg)));
742
+ };
743
+
744
+ /**
745
+ * Squash branch commits
746
+ * @param {string} branchId - local identifier of the new branch
747
+ * @param {string} commitMsg - Textual message describing the reason for the update
748
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
749
+ */
750
+ WOQLClient.prototype.squashBranch = function (branchId, commitMsg) {
751
+ if (commitMsg && branchId) {
752
+ const commit = this.generateCommitInfo(commitMsg);
753
+ return this.dispatch(
754
+ CONST.SQUASH_BRANCH,
755
+ this.connectionConfig.squashBranchURL(branchId),
756
+ commit,
757
+ );
758
+ }
759
+ const errmsg = 'Branch parameter error - you must specify a valid new branch id and a commit message';
760
+ return Promise.reject(
761
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.SQUASH_BRANCH, errmsg)),
762
+ );
763
+ };
764
+
765
+ /**
766
+ * Reset branch to a commit id, Reference ID or Commit ID are unique hashes that are
767
+ * created whenever a new commit is recorded
768
+ * @param {string} branchId - local identifier of the new branch
769
+ * @param {string} commitId - Reference ID or Commit ID
770
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
771
+ */
772
+ WOQLClient.prototype.resetBranch = function (branchId, commitId) {
773
+ if (commitId && branchId) {
774
+ // eslint-disable-next-line camelcase
775
+ return this.dispatch(
776
+ CONST.RESET_BRANCH,
777
+ this.connectionConfig.resetBranchUrl(branchId),
778
+ { commit_descriptor: commitId },
779
+ );
780
+ }
781
+ const errmsg = 'Branch parameter error - you must specify a valid new branch id and a commit message';
782
+ return Promise.reject(
783
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.RESET_BRANCH, errmsg)),
784
+ );
785
+ };
786
+
787
+ /**
788
+ * Optimize db branch
789
+ * @param {string} branchId - local identifier of the new branch
790
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
791
+ */
792
+ WOQLClient.prototype.optimizeBranch = function (branchId) {
793
+ if (branchId) {
794
+ return this.dispatch(
795
+ CONST.OPTIMIZE_SYSTEM,
796
+ this.connectionConfig.optimizeBranchUrl(branchId),
797
+ {},
798
+ );
799
+ }
800
+ const errmsg = 'Branch parameter error - you must specify a valid branch id';
801
+ return Promise.reject(new Error(ErrorMessage.getInvalidParameterMessage(CONST.BRANCH, errmsg)));
802
+ };
803
+
804
+ /**
805
+ * Deletes a branch from database
806
+ * @param {string} branchId - local identifier of the branch
807
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
808
+ */
809
+ WOQLClient.prototype.deleteBranch = function (branchId) {
810
+ if (branchId) {
811
+ return this.dispatch(CONST.DELETE, this.connectionConfig.branchURL(branchId));
812
+ }
813
+ const errmsg = 'Branch parameter error - you must specify a valid new branch id';
814
+ return Promise.reject(new Error(ErrorMessage.getInvalidParameterMessage(CONST.BRANCH, errmsg)));
815
+ };
816
+
817
+ /**
818
+ * Pull changes from a branch on a remote database to a branch on a local database
819
+ * @param {typedef.RemoteRepoDetails} remoteSourceRepo - an object describing the source of the pull
820
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
821
+ * @example
822
+ * client.pull({remote: "origin", remote_branch: "main", message: "Pulling from remote"})
823
+ */
824
+ WOQLClient.prototype.pull = function (remoteSourceRepo) {
825
+ const rc_args = this.prepareRevisionControlArgs(remoteSourceRepo);
826
+ if (rc_args && rc_args.remote && rc_args.remote_branch) {
827
+ return this.dispatch(CONST.PULL, this.connectionConfig.pullURL(), rc_args);
828
+ }
829
+ const errmsg = 'Pull parameter error - you must specify a valid remote source and branch to pull from';
830
+ return Promise.reject(new Error(ErrorMessage.getInvalidParameterMessage(CONST.PULL, errmsg)));
831
+ };
832
+
833
+ /**
834
+ * Fetch updates to a remote database to a remote repository with the local database
835
+ * @param {string} remoteId - if of the remote to fetch (eg: 'origin')
836
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
837
+ */
838
+ WOQLClient.prototype.fetch = function (remoteId) {
839
+ return this.dispatch(CONST.FETCH, this.connectionConfig.fetchURL(remoteId));
840
+ };
841
+
842
+ /**
843
+ * Push changes from a branch on a local database to a branch on a remote database
844
+ * @param {typedef.RemoteRepoDetails} remoteTargetRepo - an object describing the target of the push
845
+ * {remote: "origin", "remote_branch": "main", "author": "admin", "message": "message"}
846
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
847
+ * @example
848
+ * client.push({remote: "origin", remote_branch: "main", message: "Pulling from remote"})
849
+ */
850
+ WOQLClient.prototype.push = function (remoteTargetRepo) {
851
+ const rc_args = this.prepareRevisionControlArgs(remoteTargetRepo);
852
+ if (rc_args && rc_args.remote && rc_args.remote_branch) {
853
+ return this.dispatch(CONST.PUSH, this.connectionConfig.pushURL(), rc_args);
854
+ }
855
+ const errmsg = 'Push parameter error - you must specify a valid remote target';
856
+ return Promise.reject(new Error(ErrorMessage.getInvalidParameterMessage(CONST.PUSH, errmsg)));
857
+ };
858
+
859
+ /**
860
+ * Merges the passed branch into the current one using the rebase operation
861
+ * @param {object} rebaseSource - json describing the source branch to be used as a base
862
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
863
+ * @example
864
+ * //from the branch head
865
+ * client.rebase({rebase_from: "admin/db_name/local/branch/branch_name", message:
866
+ * "Merging from dev")
867
+ * //or from a commit id
868
+ * client.rebase({rebase_from: "admin/db_name/local/commit/9w8hk3y6rb8tjdy961de3i536ntkqd8",
869
+ * message: "Merging from dev")
870
+ */
871
+ WOQLClient.prototype.rebase = function (rebaseSource) {
872
+ const rc_args = this.prepareRevisionControlArgs(rebaseSource);
873
+ if (rc_args && rc_args.rebase_from) {
874
+ return this.dispatch(CONST.REBASE, this.connectionConfig.rebaseURL(), rc_args);
875
+ }
876
+ const errmsg = 'Rebase parameter error - you must specify a valid rebase source to rebase from';
877
+ return Promise.reject(
878
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.REBASE, errmsg)),
879
+ );
880
+ };
881
+
882
+ /**
883
+ * Reset the current branch HEAD to the specified commit path
884
+ * @param {string} commitPath - The commit path to set the current branch to
885
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
886
+ */
887
+ WOQLClient.prototype.reset = function (commitPath) {
888
+ return this.dispatch(CONST.RESET, this.connectionConfig.resetURL(), {
889
+ commit_descriptor: commitPath,
890
+ });
891
+ };
892
+
893
+ /**
894
+ * Creates a new remote connection for the database
895
+ * @param {string} remoteName - The name of the remote to create
896
+ * @param {string} remoteLocation - The URL of the remote repository
897
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
898
+ * @example
899
+ * client.createRemote("origin", "http://remote.server.com/org/db")
900
+ */
901
+ WOQLClient.prototype.createRemote = function (remoteName, remoteLocation) {
902
+ if (!remoteName || typeof remoteName !== 'string') {
903
+ const errmsg = 'Create remote parameter error - you must specify a valid remote name';
904
+ return Promise.reject(
905
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.CREATE_REMOTE, errmsg)),
906
+ );
907
+ }
908
+ if (!remoteLocation || typeof remoteLocation !== 'string') {
909
+ const errmsg = 'Create remote parameter error - you must specify a valid remote location URL';
910
+ return Promise.reject(
911
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.CREATE_REMOTE, errmsg)),
912
+ );
913
+ }
914
+ return this.dispatch(
915
+ CONST.POST,
916
+ this.connectionConfig.remoteURL(),
917
+ { remote_name: remoteName, remote_location: remoteLocation },
918
+ );
919
+ };
920
+
921
+ /**
922
+ * Gets information about a remote connection
923
+ * @param {string} remoteName - The name of the remote to retrieve
924
+ * @returns {Promise} A promise that returns the remote details, or an Error if rejected.
925
+ * @example
926
+ * const remote = await client.getRemote("origin")
927
+ */
928
+ WOQLClient.prototype.getRemote = function (remoteName) {
929
+ if (!remoteName || typeof remoteName !== 'string') {
930
+ const errmsg = 'Get remote parameter error - you must specify a valid remote name';
931
+ return Promise.reject(
932
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.GET_REMOTE, errmsg)),
933
+ );
934
+ }
935
+ const url = `${this.connectionConfig.remoteURL()}?remote_name=${encodeURIComponent(remoteName)}`;
936
+ return this.dispatch(CONST.GET, url);
937
+ };
938
+
939
+ /**
940
+ * Updates an existing remote connection
941
+ * @param {string} remoteName - The name of the remote to update
942
+ * @param {string} remoteLocation - The new URL for the remote repository
943
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
944
+ * @example
945
+ * client.updateRemote("origin", "http://new.remote.server.com/org/db")
946
+ */
947
+ WOQLClient.prototype.updateRemote = function (remoteName, remoteLocation) {
948
+ if (!remoteName || typeof remoteName !== 'string') {
949
+ const errmsg = 'Update remote parameter error - you must specify a valid remote name';
950
+ return Promise.reject(
951
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.UPDATE_REMOTE, errmsg)),
952
+ );
953
+ }
954
+ if (!remoteLocation || typeof remoteLocation !== 'string') {
955
+ const errmsg = 'Update remote parameter error - you must specify a valid remote location URL';
956
+ return Promise.reject(
957
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.UPDATE_REMOTE, errmsg)),
958
+ );
959
+ }
960
+ return this.dispatch(
961
+ CONST.PUT,
962
+ this.connectionConfig.remoteURL(),
963
+ { remote_name: remoteName, remote_location: remoteLocation },
964
+ );
965
+ };
966
+
967
+ /**
968
+ * Deletes a remote connection
969
+ * @param {string} remoteName - The name of the remote to delete
970
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
971
+ * @example
972
+ * client.deleteRemote("origin")
973
+ */
974
+ WOQLClient.prototype.deleteRemote = function (remoteName) {
975
+ if (!remoteName || typeof remoteName !== 'string') {
976
+ const errmsg = 'Delete remote parameter error - you must specify a valid remote name';
977
+ return Promise.reject(
978
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.DELETE_REMOTE, errmsg)),
979
+ );
980
+ }
981
+ const url = `${this.connectionConfig.remoteURL()}?remote_name=${encodeURIComponent(remoteName)}`;
982
+ return this.dispatch(CONST.DELETE, url);
983
+ };
984
+
985
+ /**
986
+ * Clones a remote repo and creates a local copy
987
+ * @param {typedef.CloneSourceDetails} cloneSource - object describing the source branch
988
+ * to be used as a base
989
+ * @param {string} newDbId - id of the new cloned database on the local server
990
+ * @param {string} [orgId] - id of the local organization that the new cloned database
991
+ * will be created in (in desktop mode this is always “admin”)
992
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
993
+ * @example
994
+ * client.clonedb({remote_url: "https://my.terminusdb.com/myorg/mydb", label "Cloned DB", comment: "Cloned from mydb"}, newid: "mydb")
995
+ */
996
+ WOQLClient.prototype.clonedb = function (cloneSource, newDbId, orgId) {
997
+ orgId = orgId || this.user_organization();
998
+ this.organization(orgId);
999
+ const rc_args = this.prepareRevisionControlArgs(cloneSource);
1000
+ if (newDbId && rc_args && rc_args.remote_url) {
1001
+ return this.dispatch(CONST.CLONE, this.connectionConfig.cloneURL(newDbId), rc_args);
1002
+ }
1003
+ const errmsg = 'Clone parameter error - you must specify a valid id for the cloned database';
1004
+ return Promise.reject(new Error(ErrorMessage.getInvalidParameterMessage(CONST.BRANCH, errmsg)));
1005
+ };
1006
+
1007
+ /**
1008
+ * Common request dispatch function
1009
+ * @property {string} action - the action name
1010
+ * @property {string} apiUrl - the server call endpoint
1011
+ * @property {object} [payload] - the post body
1012
+ * @property {boolean} [getDataVersion] - If true return response with data version
1013
+ * @property {boolean} [compress] - If true, compress the data if it is bigger than 1024 bytes
1014
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1015
+ */
1016
+ WOQLClient.prototype.dispatch = function (
1017
+ action,
1018
+ apiUrl,
1019
+ payload,
1020
+ getDataVersion,
1021
+ compress = false,
1022
+ ) {
1023
+ if (!apiUrl) {
1024
+ return Promise.reject(
1025
+ new Error(
1026
+ ErrorMessage.getInvalidParameterMessage(
1027
+ action,
1028
+ this.connectionConfig.connection_error,
1029
+ ),
1030
+ ),
1031
+ );
1032
+ }
1033
+ // I have to review this I don't want a call everytime
1034
+ /* if(this.connectionConfig.tokenParameter){
1035
+ const param = this.connectionConfig.tokenParameter
1036
+ axios.post(param.url,param.options).then(result=>result.data).then(data=>{
1037
+ if(data.access_token){
1038
+ console.log("ACCESS_TOKEN",data.access_token)
1039
+ this.localAuth({"key":data.access_token,"type":"jwt"})
1040
+ }
1041
+ return DispatchRequest(
1042
+ apiUrl,
1043
+ action,
1044
+ payload,
1045
+ this.localAuth(),
1046
+ this.remoteAuth(),
1047
+ this.customHeaders(),
1048
+ )
1049
+ })
1050
+ }else{ */
1051
+ return DispatchRequest(
1052
+ apiUrl,
1053
+ action,
1054
+ payload,
1055
+ this.localAuth(),
1056
+ this.remoteAuth(),
1057
+ this.customHeaders(),
1058
+ getDataVersion,
1059
+ compress,
1060
+ );
1061
+ // }
1062
+ };
1063
+
1064
+ /**
1065
+ * Generates the json structure for commit messages
1066
+ * @param {string} msg - textual string describing reason for the change
1067
+ * @param {string} [author] - optional author id string - if absent current user id will be used
1068
+ * @returns {object}
1069
+ */
1070
+ WOQLClient.prototype.generateCommitInfo = function (msg, author) {
1071
+ if (!author) {
1072
+ author = this.author();
1073
+ }
1074
+ const commitInfo = { commit_info: { author, message: msg } };
1075
+ return commitInfo;
1076
+ };
1077
+
1078
+ /**
1079
+ * Generates the json structure for commit descriptor
1080
+ * @param {string} commitId - a valid commit id o
1081
+ */
1082
+ WOQLClient.prototype.generateCommitDescriptor = function (commitId) {
1083
+ const cd = this.connectionConfig.commitDescriptorUrl(commitId);
1084
+ const ci = { commit_descriptor: cd };
1085
+ return ci;
1086
+ };
1087
+
1088
+ /**
1089
+ * Adds an author string (from the user object returned by connect) to the commit message.
1090
+ * @param {object} [rc_args]
1091
+ * @returns {object | boolean}
1092
+ */
1093
+ WOQLClient.prototype.prepareRevisionControlArgs = function (rc_args) {
1094
+ if (!rc_args || typeof rc_args !== 'object') return false;
1095
+ if (!rc_args.author) rc_args.author = this.author();
1096
+ return rc_args;
1097
+ };
1098
+
1099
+ /**
1100
+ * to add a new document or a list of new documents into the instance or the schema graph.
1101
+ * @param {object} json
1102
+ * @param {typedef.DocParamsPost} [params] - the post parameters {@link #typedef.DocParamsPost}
1103
+ * @param {string} [dbId] - the dbid
1104
+ * @param {message} [string] - the insert commit message
1105
+ * @param {string} [lastDataVersion] the last data version tracking id.
1106
+ * @param {boolean} [getDataVersion] If true the function will return object having result
1107
+ * and dataVersion.
1108
+ * @returns {Promise} A promise that returns the call response object or object having *result*
1109
+ * and *dataVersion* object if ***getDataVersion*** parameter is true, or an Error if rejected.
1110
+ * @example
1111
+ * const json = [{ "@type" : "Class",
1112
+ * "@id" : "Coordinate",
1113
+ * "@key" : { '@type' : 'Hash',
1114
+ * '@fields' : ['x','y'] },
1115
+ * "x" : "xsd:decimal",
1116
+ * "y" : "xsd:decimal" },
1117
+ * { "@type" : "Class",
1118
+ * "@id" : "Country",
1119
+ * "@key" : { '@type' : 'Lexical',
1120
+ * '@fields' : [name] },
1121
+ * "name" : "xsd:string",
1122
+ * "perimeter" : { "@type" : "List",
1123
+ * "@class" : "Coordinate" } }]
1124
+ * client.addDocument(json,{"graph_type":"schema"},"mydb","add new schema documents")
1125
+ *
1126
+ * //if we would like to override the entire schema
1127
+ * const json = [
1128
+ * {"@base": "terminusdb:///data/",
1129
+ * "@schema": "terminusdb:///schema#",
1130
+ * "@type": "@context"
1131
+ * },
1132
+ * {
1133
+ * "@id": "Person",
1134
+ * "@key": {
1135
+ * "@type": "Random"
1136
+ * },
1137
+ * "@type": "Class",
1138
+ * "name": {
1139
+ * "@class": "xsd:string",
1140
+ * "@type": "Optional"
1141
+ * }
1142
+ * }]
1143
+ *
1144
+ * // client.addDocument(json,{"graph_type":"schema","full_replace:true"},
1145
+ "mydb","update the all schema");
1146
+ *
1147
+ * // Here we will pass true to show how to get dataVersion
1148
+ *
1149
+ * const response = await client.addDocument(json, {"graph_type": "schema"},
1150
+ * "mydb",
1151
+ * "add new schema", '',
1152
+ * true
1153
+ * )
1154
+ * console.log(response);
1155
+ *
1156
+ * // This will output:
1157
+ * // {
1158
+ * // result: [ ...... ],
1159
+ * // dataVersion: 'branch:5fs681tlycnn6jh0ceiqcq4qs89pdfs'
1160
+ * // }
1161
+ *
1162
+ * // Now we can use the data version we recieved as a response in previous
1163
+ * // function call and used it is next function call as lastDataVersion
1164
+ *
1165
+ * const response1 = await client.addDocument(json, {"graph_type": "schema"},
1166
+ * "mydb",
1167
+ * "add new schema", response.dataVersion,
1168
+ * )
1169
+ */
1170
+ WOQLClient.prototype.addDocument = function (json, params, dbId, message = 'add a new document', lastDataVersion = '', getDataVersion = false, compress = false) {
1171
+ if (dbId) {
1172
+ this.db(dbId);
1173
+ }
1174
+
1175
+ if (typeof lastDataVersion === 'string' && lastDataVersion !== '') {
1176
+ this.customHeaders({ 'TerminusDB-Data-Version': lastDataVersion });
1177
+ }
1178
+ const docParams = params || {};
1179
+ docParams.author = this.author();
1180
+ docParams.message = message;
1181
+ return this.dispatch(
1182
+ CONST.POST,
1183
+ this.connectionConfig.documentURL(docParams),
1184
+ json,
1185
+ getDataVersion,
1186
+ compress,
1187
+ );
1188
+ };
1189
+
1190
+ /**
1191
+ * Use {@link #getDocument} instead.
1192
+ * @deprecated
1193
+ *
1194
+ * Retrieves all documents that match a given document template
1195
+ * @param {object} query - the query template
1196
+ * @param {typedef.DocParamsGet} [params] - the get parameters
1197
+ * @param {string} [dbId] - the database id
1198
+ * @param {string} [branch] - the database branch
1199
+ * @param {string} [lastDataVersion] the last data version tracking id.
1200
+ * @param {boolean} [getDataVersion] If true the function will return object having result
1201
+ * and dataVersion.
1202
+ * @returns {Promise} A promise that returns the call response object or object having *result*
1203
+ * and *dataVersion* object if ***getDataVersion*** parameter is true, or an Error if rejected.
1204
+ * @example
1205
+ * const query = {
1206
+ * "type": "Person",
1207
+ * "query": { "age": 42 },
1208
+ * }
1209
+ * client.queryDocument(query, {"as_list":true})
1210
+ *
1211
+ *
1212
+ * // Here we will pass true to show how to get dataVersion
1213
+ * const query = {
1214
+ * "type": "Person",
1215
+ * "query": { "age": 42 },
1216
+ * }
1217
+ *
1218
+ * const response = await client.queryDocument(query, {"as_list": true}, '', '','',true);
1219
+ * console.log(response);
1220
+ *
1221
+ * // This will output:
1222
+ * // {
1223
+ * // result: [
1224
+ * // {
1225
+ * // '@id': 'Person/052d60ffbd114bf5e7331b03f07fcb7',
1226
+ * // '@type': 'Person',
1227
+ * // age: 42,
1228
+ * // name: 'John',
1229
+ * // },
1230
+ * // ],
1231
+ * // dataVersion: 'branch:5fs681tlycnn6jh0ceiqcq4qs89pdfs'
1232
+ * // }
1233
+ *
1234
+ * // Now we can use the data version we recieved as a response in previous
1235
+ * // query and used it is next query as lastDataVersion
1236
+ * const query = {
1237
+ * "type": "Person",
1238
+ * "query": { "age": 18 },
1239
+ * }
1240
+ *
1241
+ * const response1 = await client.queryDocument(query, {"as_list": true}, '',
1242
+ * '',
1243
+ * response.dataVersion
1244
+ * );
1245
+ */
1246
+ WOQLClient.prototype.queryDocument = function (query, params, dbId, branch, lastDataVersion = '', getDataVersion = false) {
1247
+ if (dbId) {
1248
+ this.db(dbId);
1249
+ }
1250
+ if (branch) {
1251
+ this.checkout(branch);
1252
+ }
1253
+ if (typeof lastDataVersion === 'string' && lastDataVersion !== '') {
1254
+ this.customHeaders({ 'TerminusDB-Data-Version': lastDataVersion });
1255
+ }
1256
+
1257
+ return this.dispatch(
1258
+ CONST.QUERY_DOCUMENT,
1259
+ this.connectionConfig.documentURL(params),
1260
+ query,
1261
+ getDataVersion,
1262
+ );
1263
+ };
1264
+
1265
+ /**
1266
+ *
1267
+ * @param {typedef.DocParamsGet} [params] - the get parameters,
1268
+ * you can pass document query search template with the params
1269
+ * @param {string} [dbId] - the database id
1270
+ * @param {string} [branch] - the database branch
1271
+ * @param {string} [lastDataVersion] the last data version tracking id.
1272
+ * @param {boolean} [getDataVersion] If true the function will return object having result
1273
+ * and dataVersion.
1274
+ * @param {object} [query] document query search template
1275
+ * @returns {Promise} A promise that returns the call response object or object having *result*
1276
+ * and *dataVersion* object if ***getDataVersion*** parameter is true, or an Error if rejected.
1277
+ * @example
1278
+ * //return the schema graph as a json array
1279
+ * client.getDocument({"graph_type":"schema","as_list":true}).then(result={
1280
+ * console.log(result)
1281
+ * })
1282
+ *
1283
+ * //retutn the Country class document from the schema graph
1284
+ * client.getDocument({"graph_type":"schema","as_list":true,"id":"Country"}).then(result={
1285
+ * console.log(result)
1286
+ * })
1287
+ *
1288
+ * //pass a document query template to query the document interface
1289
+ * const queryTemplate = { "name": "Ireland"}
1290
+ * client.getDocument({"as_list":true, "@type":"Country"
1291
+ * query:queryTemplate}).then(result=>{
1292
+ * console.log(result)
1293
+ * })
1294
+ *
1295
+ *
1296
+ * // Here we will pass true to show how to get dataVersion
1297
+ * const response = await client.getDocument({"graph_type":"schema","as_list":true},
1298
+ * "",
1299
+ * "",
1300
+ * "",
1301
+ * true
1302
+ * )
1303
+ * console.log(response);
1304
+ *
1305
+ * // This will output:
1306
+ * // {
1307
+ * // result: [ ...... ],
1308
+ * // dataVersion: 'branch:5fs681tlycnn6jh0ceiqcq4qs89pdfs'
1309
+ * // }
1310
+ *
1311
+ * // Now we can use the data version we recieved as a response in previous
1312
+ * // function call and used it is next function call as lastDataVersion
1313
+ *
1314
+ * const response1 = await client.getDocument({"graph_type":"schema","as_list":true},
1315
+ * "",
1316
+ * "",
1317
+ * response.dataVersion,
1318
+ * )
1319
+ */
1320
+ // document interface
1321
+ WOQLClient.prototype.getDocument = function (params, dbId, branch, lastDataVersion = '', getDataVersion = false, query = undefined) {
1322
+ if (dbId) {
1323
+ this.db(dbId);
1324
+ }
1325
+ if (branch) {
1326
+ this.checkout(branch);
1327
+ }
1328
+ if (typeof lastDataVersion === 'string' && lastDataVersion !== '') {
1329
+ this.customHeaders({ 'TerminusDB-Data-Version': lastDataVersion });
1330
+ }
1331
+ let queryDoc;
1332
+ if (query) {
1333
+ queryDoc = query;
1334
+ } else if (params && typeof params === 'object' && params.query) {
1335
+ queryDoc = { query: params.query };
1336
+ delete params.query;
1337
+ }
1338
+ // if query we are send a get with a payload
1339
+
1340
+ if (queryDoc) {
1341
+ return this.dispatch(
1342
+ CONST.QUERY_DOCUMENT,
1343
+ this.connectionConfig.documentURL(params),
1344
+ queryDoc,
1345
+ getDataVersion,
1346
+ );
1347
+ }
1348
+
1349
+ return this.dispatch(CONST.GET, this.connectionConfig.documentURL(params), {}, getDataVersion);
1350
+ };
1351
+
1352
+ /**
1353
+ *
1354
+ * @param {object} json
1355
+ * @param {typedef.DocParamsPut} [params] - the Put parameters {@link #typedef.DocParamsPut}
1356
+ * @param {*} [dbId] - the database id
1357
+ * @param {*} [message] - the update commit message
1358
+ * @param {string} [lastDataVersion] the last data version tracking id.
1359
+ * @param {boolean} [getDataVersion] If true the function will return object having result
1360
+ * and dataVersion.
1361
+ * @param {boolean} [compress] If true, the function will create a new document if it doesn't exist.
1362
+ * @param {boolean} [create] Perform an *upsert* which inserts if the document
1363
+ * is not present (also works on nested documents)
1364
+ * @returns {Promise} A promise that returns the call response object or object having *result*
1365
+ * and *dataVersion* object if ***getDataVersion*** parameter is true, or an Error if rejected.
1366
+ * @example
1367
+ * client.updateDocument(
1368
+ * {
1369
+ * "@id": "Person",
1370
+ * "@key": {
1371
+ * "@type": "Random",
1372
+ * },
1373
+ * "@type": "Class",
1374
+ * label: "xsd:string",
1375
+ * },
1376
+ * { graph_type: "schema" }
1377
+ * );
1378
+ *
1379
+ *
1380
+ * // Here we will pass true to show how to get dataVersion
1381
+ *
1382
+ const response = await client.updateDocument(
1383
+ {
1384
+ "@id": "Person",
1385
+ "@key": {
1386
+ "@type": "Random",
1387
+ },
1388
+ "@type": "Class",
1389
+ label: "xsd:string",
1390
+ },
1391
+ { graph_type: "schema" },
1392
+ "",
1393
+ "",
1394
+ "",
1395
+ true
1396
+ );
1397
+ * console.log(response);
1398
+ *
1399
+ * // This will output:
1400
+ * // {
1401
+ * // result: [ ...... ],
1402
+ * // dataVersion: 'branch:5fs681tlycnn6jh0ceiqcq4qs89pdfs'
1403
+ * // }
1404
+ *
1405
+ * // Now we can use the data version we recieved as a response in previous
1406
+ * // function call and used it is next function call as lastDataVersion
1407
+ *
1408
+ * const response1 = await client.updateDocument(
1409
+ {
1410
+ "@id": "Person",
1411
+ "@key": {
1412
+ "@type": "Random",
1413
+ },
1414
+ "@type": "Class",
1415
+ label: "xsd:string",
1416
+ },
1417
+ { graph_type: "schema" },
1418
+ "",
1419
+ "",
1420
+ response.dataVersion
1421
+ );
1422
+ *
1423
+ * // update a document and create the linked document together
1424
+ * // we are update the document "Person/Person01"
1425
+ * // and create a new document {"@type": "Person","name": "child01"} at the same time
1426
+ * const response1 = await client.updateDocument(
1427
+ {
1428
+ "@id": "Person/Person01",
1429
+ "@type": "Person",
1430
+ "name": "Person01"
1431
+ "children":[{"@type": "Person","name": "child01"}]
1432
+ },{create:true})
1433
+ */
1434
+ WOQLClient.prototype.updateDocument = function (json, params, dbId, message = 'update document', lastDataVersion = '', getDataVersion = false, compress = false, create = false) {
1435
+ const docParams = params || {};
1436
+ docParams.author = this.author();
1437
+ docParams.message = message;
1438
+ if (create) {
1439
+ docParams.create = create;
1440
+ }
1441
+ if (dbId) {
1442
+ this.db(dbId);
1443
+ }
1444
+ if (typeof lastDataVersion === 'string' && lastDataVersion !== '') {
1445
+ this.customHeaders({ 'TerminusDB-Data-Version': lastDataVersion });
1446
+ }
1447
+ return this.dispatch(
1448
+ CONST.PUT,
1449
+ this.connectionConfig.documentURL(docParams),
1450
+ json,
1451
+ getDataVersion,
1452
+ compress,
1453
+ );
1454
+ };
1455
+
1456
+ /**
1457
+ * to delete the document
1458
+ * @param {typedef.DocParamsDelete} [params]
1459
+ * @param {string} [dbId] - the database id
1460
+ * @param {string} [message] - the delete message
1461
+ * @param {string} [lastDataVersion] the last data version tracking id.
1462
+ * @param {boolean} [getDataVersion] If true the function will return object having result
1463
+ * and dataVersion.
1464
+ * @returns {Promise} A promise that returns the call response object or object having *result*
1465
+ * and *dataVersion* object if ***getDataVersion*** parameter is true, or an Error if rejected.
1466
+ * @example
1467
+ * client.deleteDocument({"graph_type":"schema",id:['Country','Coordinate']})
1468
+ *
1469
+ *
1470
+ * // Here we will pass true to show how to get dataVersion
1471
+ *
1472
+ * const response = await client.deleteDocument({"graph_type":"schema",id:['Country','Coordinate']},
1473
+ * "",
1474
+ * "",
1475
+ * "",
1476
+ * true
1477
+ * )
1478
+ * console.log(response);
1479
+ *
1480
+ * // This will output:
1481
+ * // {
1482
+ * // result: [ ...... ],
1483
+ * // dataVersion: 'branch:5fs681tlycnn6jh0ceiqcq4qs89pdfs'
1484
+ * // }
1485
+ *
1486
+ * // Now we can use the data version we recieved as a response in previous
1487
+ * // function call and used it is next function call as lastDataVersion
1488
+ *
1489
+ * const response1 = await client.deleteDocument({"graph_type":"schema",
1490
+ * id:['Country','Coordinate']},
1491
+ * "",
1492
+ * "",
1493
+ * response.dataVersion,
1494
+ * )
1495
+ */
1496
+ WOQLClient.prototype.deleteDocument = function (params, dbId, message = 'delete document', lastDataVersion = '', getDataVersion = false) {
1497
+ const docParams = params || {};
1498
+ let payload = null;
1499
+ if (Array.isArray(params.id)) {
1500
+ payload = params.id;
1501
+ delete docParams.id;
1502
+ }
1503
+ docParams.author = this.author();
1504
+ docParams.message = message;
1505
+ if (dbId) {
1506
+ this.db(dbId);
1507
+ }
1508
+ if (typeof lastDataVersion === 'string' && lastDataVersion !== '') {
1509
+ this.customHeaders({ 'TerminusDB-Data-Version': lastDataVersion });
1510
+ }
1511
+ return this.dispatch(
1512
+ CONST.DELETE,
1513
+ this.connectionConfig.documentURL(docParams),
1514
+ payload,
1515
+ getDataVersion,
1516
+ );
1517
+ };
1518
+ /**
1519
+ * The purpose of this method is to quickly discover the supported fields of a particular type.
1520
+ * @param {string} [type] - If given, the type to get information for. If omitted, information
1521
+ * for all types is returned
1522
+ * @param {string} [dbId] - the database id
1523
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1524
+ * @example
1525
+ * client.getSchemaFrame("Country")
1526
+ */
1527
+ WOQLClient.prototype.getSchemaFrame = function (type, dbId) {
1528
+ let params;
1529
+ if (type) params = { type };
1530
+ if (dbId) {
1531
+ this.db(dbId);
1532
+ }
1533
+ return this.dispatch(CONST.GET, this.connectionConfig.jsonSchemaURL(params));
1534
+ };
1535
+
1536
+ /**
1537
+ * get the database schema in json format
1538
+ * @param {string} [dbId] - the database id
1539
+ * @param {string} [branch] - specific a branch/collection
1540
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1541
+ * @example
1542
+ * client.getSchema()
1543
+ */
1544
+ WOQLClient.prototype.getSchema = function (dbId, branch) {
1545
+ const params = { graph_type: 'schema', as_list: true };
1546
+ return this.getDocument(params, dbId, branch);
1547
+ };
1548
+
1549
+ /**
1550
+ * get all the schema classes (documents,subdocuments,abstracts)
1551
+ * @param {string} [dbId] - the database id
1552
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1553
+ * @example
1554
+ * client.getClasses()
1555
+ */
1556
+
1557
+ WOQLClient.prototype.getClasses = function (dbId) {
1558
+ const params = { graph_type: 'schema', as_list: true, type: 'sys:Class' };
1559
+ return this.getDocument(params, dbId);
1560
+ };
1561
+
1562
+ /**
1563
+ * get all the Enum Objects
1564
+ * @param {string} [dbId]
1565
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1566
+ * @example
1567
+ * client.getEnums()
1568
+ */
1569
+ WOQLClient.prototype.getEnums = function (dbId) {
1570
+ const params = { graph_type: 'schema', as_list: true, type: 'sys:Enum' };
1571
+ return this.getDocument(params, dbId);
1572
+ };
1573
+
1574
+ /**
1575
+ * get all the Document Classes (no abstract or subdocument)
1576
+ * @param {string} [dbId]
1577
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1578
+ * @example
1579
+ * client.getClassDocuments()
1580
+ */
1581
+ WOQLClient.prototype.getClassDocuments = function (dbId) {
1582
+ const params = { graph_type: 'schema', as_list: true, type: 'sys:Class' };
1583
+ return this.getDocument(params, dbId).then((result) => {
1584
+ let documents = [];
1585
+ if (result) {
1586
+ documents = result.filter((item) => !item['@subdocument'] && !item['@abstract']);
1587
+ }
1588
+ return documents;
1589
+ });
1590
+ };
1591
+
1592
+ /**
1593
+ * get the database collections list
1594
+ * @param {string} [dbId] - the database id
1595
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1596
+ * @example
1597
+ * client.getBranches()
1598
+ */
1599
+ WOQLClient.prototype.getBranches = function (dbId) {
1600
+ const params = { type: 'Branch', as_list: true };
1601
+ const branch = this.checkout();
1602
+ return this.getDocument(params, dbId, '_commits').then((result) => {
1603
+ const branchesObj = {};
1604
+ if (result) {
1605
+ result.forEach((item) => {
1606
+ branchesObj[item.name] = item;
1607
+ });
1608
+ }
1609
+ this.checkout(branch);
1610
+ return branchesObj;
1611
+ });
1612
+ // reset branch
1613
+ };
1614
+
1615
+ /**
1616
+ * get the database collections list
1617
+ * @param {number} [start=0] - where to start printing the commit
1618
+ * information in the log (starting from the head of the current branch)
1619
+ * @param {number} [count=1] - The number of total commit log records to return
1620
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1621
+ * @example
1622
+ * client.getCommitsLog(count=10)
1623
+ */
1624
+ WOQLClient.prototype.getCommitsLog = function (start = 0, count = 1) {
1625
+ return this.dispatch(
1626
+ CONST.GET,
1627
+ `${this.connectionConfig.log()}?start=${start}&count=${count}`,
1628
+ );
1629
+ };
1630
+
1631
+ /**
1632
+ * get the database prefixes object
1633
+ * @param {string} [dbId] - the database id
1634
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1635
+ * @example
1636
+ * client.getPrefixes()
1637
+ * //return object example
1638
+ * {
1639
+ * '@base': 'terminusdb:///data/',
1640
+ * '@schema': 'terminusdb:///schema#',
1641
+ * '@type': 'Context'}
1642
+ */
1643
+ WOQLClient.prototype.getPrefixes = function (dbId) {
1644
+ if (dbId) this.db(dbId);
1645
+ return this.dispatch(
1646
+ CONST.GET,
1647
+ this.connectionConfig.prefixesURL(),
1648
+ );
1649
+ };
1650
+
1651
+ /**
1652
+ * Get the list of the user's organizations and the database related
1653
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1654
+ * @example
1655
+ * async funtion callGetUserOrganizations(){
1656
+ * await getUserOrganizations()
1657
+ * console.log(client.userOrganizations())
1658
+ * }
1659
+ */
1660
+ WOQLClient.prototype.getUserOrganizations = function () {
1661
+ // this will be change to give back only the organizations list
1662
+ return this.dispatch(
1663
+ CONST.GET,
1664
+ this.connectionConfig.userOrganizationsURL(),
1665
+ ).then((response) => {
1666
+ const orgList = Array.isArray(response) ? response : [];
1667
+ this.userOrganizations(orgList);
1668
+ return orgList;
1669
+ });
1670
+ };
1671
+
1672
+ /**
1673
+ * Get/Set the list of the user's organizations (id, organization, label, comment).
1674
+ * @param {array} [orgList] a list of user's Organization
1675
+ * @returns {array} the user Organizations list
1676
+ * @example
1677
+ * async funtion callGetUserOrganizations(){
1678
+ * await client.getUserOrganizations()
1679
+ * console.log(client.userOrganizations())
1680
+ * }
1681
+ */
1682
+ WOQLClient.prototype.userOrganizations = function (orgList) {
1683
+ if (orgList) this.organizationList = orgList;
1684
+ return this.organizationList || [];
1685
+ };
1686
+
1687
+ /**
1688
+ * Apply a patch object to another object
1689
+ * @param {object} before - The current state of JSON document
1690
+ * @param {object} patch - The patch object
1691
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1692
+ * @example
1693
+ * client.patch(
1694
+ * { "@id" : "Person/Jane", "@type" : "Person", "name" : "Jane"},
1695
+ * { "name" : { "@op" : "ValueSwap", "@before" : "Jane", "@after": "Janine" }}
1696
+ * ).then(patchResult=>{
1697
+ * console.log(patchResult)
1698
+ * })
1699
+ * //result example
1700
+ * //{ "@id" : "Person/Jane", "@type" : "Person", "name" : "Jannet"}
1701
+ */
1702
+ WOQLClient.prototype.patch = function (before, patch) {
1703
+ if (typeof before !== 'object' || typeof patch !== 'object') {
1704
+ const errmsg = '"before" or "after" parameter error - you must specify a valid before and after json document';
1705
+
1706
+ return Promise.reject(
1707
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.PATCH, errmsg)),
1708
+ );
1709
+ }
1710
+ const payload = { before, patch };
1711
+
1712
+ return this.dispatch(
1713
+ CONST.POST,
1714
+ `${this.connectionConfig.apiURL()}patch`,
1715
+ payload,
1716
+ ).then((response) => response);
1717
+ };
1718
+
1719
+ /**
1720
+ * Apply a patch object to the current resource
1721
+ * @param {array} patch - The patch object
1722
+ * @param {string} message - The commit message
1723
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1724
+ * @example
1725
+ * const patch = [
1726
+ * {
1727
+ * "@id": "Obj/id1",
1728
+ * "name": {
1729
+ * "@op": "SwapValue",
1730
+ * "@before": "foo",
1731
+ * "@after": "bar"
1732
+ * }
1733
+ * },
1734
+ * {
1735
+ * "@id": "Obj/id2",
1736
+ * "name": {
1737
+ * "@op": "SwapValue",
1738
+ * "@before": "foo",
1739
+ * "@after": "bar"
1740
+ * }
1741
+ * }
1742
+ * ]
1743
+ * client.db("mydb")
1744
+ * client.checkout("mybranch")
1745
+ * client.patchResource(patch,"apply patch to mybranch").then(patchResult=>{
1746
+ * console.log(patchResult)
1747
+ * })
1748
+ * // result example
1749
+ * // ["Obj/id1",
1750
+ * // "Obj/id2"]
1751
+ * // or conflict error 409
1752
+ * // {
1753
+ * // "@type": "api:PatchError",
1754
+ * // "api:status": "api:conflict",
1755
+ * // "api:witnesses": [
1756
+ * // {
1757
+ * // "@op": "InsertConflict",
1758
+ * // "@id_already_exists": "Person/Jane"
1759
+ * // }
1760
+ * //]
1761
+ * //}
1762
+ */
1763
+ WOQLClient.prototype.patchResource = function (patch, message) {
1764
+ if (!Array.isArray(patch)) {
1765
+ const errmsg = '"patch" parameter error - you must specify a valid patch document';
1766
+
1767
+ return Promise.reject(
1768
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.PATCH, errmsg)),
1769
+ );
1770
+ }
1771
+ const payload = { patch, author: this.author(), message };
1772
+
1773
+ return this.dispatch(
1774
+ CONST.POST,
1775
+ this.connectionConfig.patchURL(),
1776
+ payload,
1777
+ ).then((response) => response);
1778
+ };
1779
+
1780
+ /**
1781
+ * Get the patch of difference between two documents.
1782
+ * @param {object} before - The current state of JSON document
1783
+ * @param {object} after - The updated state of JSON document
1784
+ * @param {object} [options] - {keep:{}} Options to send to the diff endpoint.
1785
+ * The diff api outputs the changes between the input,
1786
+ * in options you can list the properties that you would like to see in the diff result in any case.
1787
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1788
+ * @example
1789
+ * client.getJSONDiff(
1790
+ * { "@id": "Person/Jane", "@type": "Person", name: "Jane" },
1791
+ * { "@id": "Person/Jane", "@type": "Person", name: "Janine" }
1792
+ * ).then(diffResult=>{
1793
+ * console.log(diffResult)
1794
+ * })
1795
+ * //result example
1796
+ * //{'@id': 'Person/Jane',
1797
+ * // name: { '@after': 'Janine', '@before': 'Jane', '@op': 'SwapValue' }}
1798
+ */
1799
+ WOQLClient.prototype.getJSONDiff = function (before, after, options) {
1800
+ if (typeof before !== 'object' || typeof after !== 'object') {
1801
+ const errmsg = '"before" or "after" parameter error - you must specify a valid before or after json document';
1802
+
1803
+ return Promise.reject(
1804
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.GET_DIFF, errmsg)),
1805
+ );
1806
+ }
1807
+ const opt = (typeof options === 'undefined') ? {} : options;
1808
+ const payload = { before, after, ...opt };
1809
+
1810
+ return this.dispatch(
1811
+ CONST.POST,
1812
+ `${this.connectionConfig.apiURL()}diff`,
1813
+ payload,
1814
+ ).then((response) => response);
1815
+ };
1816
+
1817
+ /**
1818
+ * Get the patch of difference between two documents.
1819
+ * @param {string} dataVersion - The version from which to compare the object
1820
+ * @param {object} jsonObject - The updated state of JSON document
1821
+ * @param {string} id - The document id to be diffed
1822
+ * @param {object} [options] - {keep:{}} Options to send to the diff endpoint
1823
+ * the diff api outputs the changes between the input,
1824
+ * but you can list the properties that you would like to see in the diff result in any case.
1825
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1826
+ * @example
1827
+ * const jsonObj = { "@id": "Person/Jane", "@type": "Person", name: "Janine" }
1828
+ * client.getVersionObjectDiff("main",jsonObj
1829
+ * "Person/Jane").then(diffResp=>{
1830
+ * console.log(diffResp)
1831
+ * })
1832
+ */
1833
+ WOQLClient.prototype.getVersionObjectDiff = function (dataVersion, jsonObject, id, options) {
1834
+ if (typeof jsonObject !== 'object' || typeof dataVersion !== 'string' || typeof id !== 'string') {
1835
+ const errmsg = 'Parameters error - you must specify a valid jsonObject document, a valid branch or commit and a valid id';
1836
+
1837
+ return Promise.reject(
1838
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.GET_DIFF, errmsg)),
1839
+ );
1840
+ }
1841
+ const opt = options || {};
1842
+ const payload = {
1843
+ after: jsonObject,
1844
+ before_data_version: dataVersion,
1845
+ id,
1846
+ ...opt,
1847
+ };
1848
+ return this.dispatch(
1849
+ CONST.POST,
1850
+ this.connectionConfig.diffURL(),
1851
+ payload,
1852
+ ).then((response) => response);
1853
+ };
1854
+
1855
+ /**
1856
+ * Get the patch of difference between branches or commits.
1857
+ * @param {string} beforeVersion - Before branch/commit to compare
1858
+ * @param {string} afterVersion - After branch/commit to compare
1859
+ * @param {string} [id] - The document id to be diffed,
1860
+ * if it is omitted all the documents will be compared
1861
+ * @param {typedef.DiffObject} [options] - {keep:{},count:10,start:0}
1862
+ * Options to send to the diff endpoint.
1863
+ * The diff api outputs the changes between the input (branches or commits),
1864
+ * in options you can list the properties that you would like to see in the diff result in any case.
1865
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1866
+ * @example
1867
+ * //This is to view all the changes between two commits
1868
+ * const beforeCommit = "a73ssscfx0kke7z76083cgswszdxy6l"
1869
+ * const afterCommit = "73rqpooz65kbsheuno5dsayh71x7wf4"
1870
+ *
1871
+ * client.getVersionDiff( beforeCommit, afterCommit).then(diffResult=>{
1872
+ * console.log(diffResult)
1873
+ * })
1874
+ *
1875
+ * //This is to view the changes between two commits but only for the given document
1876
+ * client.getVersionDiff( beforeCommit, afterCommit, "Person/Tom").then(diffResult=>{
1877
+ * console.log(diffResult)
1878
+ * })
1879
+ *
1880
+ * //This is to view the changes between a branch (head) and a commit for the given document
1881
+ * client.getVersionDiff("main", afterCommit, "Person/Tom" ).then(diffResult=>{
1882
+ * console.log(diffResult)
1883
+ * })
1884
+ *
1885
+ * //This is to view the changes between two branches with the keep options
1886
+ * const options = {"keep":{"@id":true, "name": true}, start:0, count:10}
1887
+ * client.getVersionDiff("main","mybranch",options).then(diffResult=>{
1888
+ * console.log(diffResult)
1889
+ * })
1890
+ */
1891
+ WOQLClient.prototype.getVersionDiff = function (beforeVersion, afterVersion, id, options) {
1892
+ if (typeof beforeVersion !== 'string' || typeof afterVersion !== 'string') {
1893
+ const errmsg = 'Error, you have to provide a beforeVersion and afterVersion input';
1894
+
1895
+ return Promise.reject(
1896
+ new Error(ErrorMessage.getInvalidParameterMessage(CONST.GET_DIFF, errmsg)),
1897
+ );
1898
+ }
1899
+ const opt = options || {};
1900
+ const payload = {
1901
+ before_data_version: beforeVersion,
1902
+ after_data_version: afterVersion,
1903
+ ...opt,
1904
+ };
1905
+ if (id) {
1906
+ payload.document_id = id;
1907
+ }
1908
+ // console.log(this.connectionConfig.diffURL())
1909
+ return this.dispatch(
1910
+ CONST.POST,
1911
+ this.connectionConfig.diffURL(),
1912
+ payload,
1913
+ ).then((response) => response);
1914
+ };
1915
+
1916
+ /**
1917
+ * Diff two different commits and apply changes on the current branch/commit.
1918
+ * If you would like to change branch or commit before apply use client.checkout("branchName")
1919
+ * @param {string} beforeVersion - Before branch/commit to compare
1920
+ * @param {string} afterVersion - After branch/commit to compare
1921
+ * @param {string} message - apply commit message
1922
+ * @param {boolean} [matchFinalState] - the default value is false
1923
+ * @param {object} [options] - {keep:{}} Options to send to the apply endpoint
1924
+ * @example
1925
+ * client.checkout("mybranch")
1926
+ * client.apply("mybranch","mybranch_new","merge main").then(result=>{
1927
+ * console.log(result)
1928
+ * })
1929
+ */
1930
+ // eslint-disable-next-line max-len
1931
+ WOQLClient.prototype.apply = function (beforeVersion, afterVersion, message, matchFinalState, options) {
1932
+ const opt = options || {};
1933
+ const commitMsg = this.generateCommitInfo(message);
1934
+ const payload = {
1935
+ before_commit: beforeVersion,
1936
+ after_commit: afterVersion,
1937
+ ...commitMsg,
1938
+ ...opt,
1939
+ };
1940
+ if (matchFinalState) {
1941
+ payload.match_final_state = matchFinalState;
1942
+ }
1943
+ return this.dispatch(
1944
+ CONST.POST,
1945
+ this.connectionConfig.applyURL(),
1946
+ payload,
1947
+ ).then((response) => response);
1948
+ };
1949
+
1950
+ /**
1951
+ * Get the document's history for a specific database or branch
1952
+ * @param {string} id - id of document to report history of
1953
+ * @param {typedef.DocHistoryParams} [historyParams]
1954
+ * @example
1955
+ * //this will return the last 5 commits for the Person/Anna document
1956
+ * client.checkout("mybranch")
1957
+ * client.docHistory("Person/Anna",{start:0,count:5}).then(result=>{
1958
+ * console.log(result)
1959
+ * })
1960
+ * //this will return the last and the first commit for the Person/Anna document
1961
+ * client.docHistory("Person/Anna",{updated:true,created:true}).then(result=>{
1962
+ * console.log(result)
1963
+ * })
1964
+ */
1965
+ // eslint-disable-next-line max-len
1966
+ WOQLClient.prototype.getDocumentHistory = function (id, historyParams) {
1967
+ const params = historyParams || {};
1968
+ params.id = id;
1969
+ // Set default count to 10 if not specified
1970
+ if (params.count === undefined) {
1971
+ params.count = 10;
1972
+ }
1973
+ return this.dispatch(
1974
+ CONST.GET,
1975
+ this.connectionConfig.docHistoryURL(params),
1976
+ ).then((response) => response);
1977
+ };
1978
+
1979
+ /**
1980
+ * Call a custom Api endpoit
1981
+ * @param {string} requestType - The current state of JSON document
1982
+ * @param {string} customRequestURL - The patch object
1983
+ * @param {object} [payload] - the request payload
1984
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
1985
+ * @example
1986
+ * client.sendCustomRequest("GET", "http://localhost:3030/changes/").then(result=>{
1987
+ * console.log(result)
1988
+ * })
1989
+ */
1990
+ WOQLClient.prototype.sendCustomRequest = function (requestType, customRequestURL, payload) {
1991
+ return this.dispatch(
1992
+ requestType,
1993
+ customRequestURL,
1994
+ payload,
1995
+ ).then((response) => response);
1996
+ };
1997
+
1998
+ /**
1999
+ * Get a single prefix mapping
2000
+ * @param {string} prefixName - The prefix name (e.g., 'ex', 'schema')
2001
+ * @param {string} [dbId] - The database id
2002
+ * @returns {Promise<string>} A promise that returns the prefix IRI, or an Error if rejected.
2003
+ * @example
2004
+ * client.getPrefix("schema").then(uri => {
2005
+ * console.log(uri) // "http://schema.org/"
2006
+ * })
2007
+ */
2008
+ WOQLClient.prototype.getPrefix = function (prefixName, dbId) {
2009
+ if (dbId) {
2010
+ this.db(dbId);
2011
+ }
2012
+ const url = `${this.connectionConfig.prefixURL()}/${prefixName}`;
2013
+ return this.dispatch(CONST.GET, url).then((response) => response['api:prefix_uri']);
2014
+ };
2015
+
2016
+ /**
2017
+ * Add a new prefix mapping
2018
+ * @param {string} prefixName - The prefix name to create
2019
+ * @param {string} uri - The IRI (namespace URL) this prefix expands to
2020
+ * @param {string} [dbId] - The database id
2021
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
2022
+ * @example
2023
+ * client.addPrefix("ex", "http://example.org/").then(result => {
2024
+ * console.log("Prefix added successfully")
2025
+ * })
2026
+ */
2027
+ WOQLClient.prototype.addPrefix = function (prefixName, uri, dbId) {
2028
+ if (dbId) {
2029
+ this.db(dbId);
2030
+ }
2031
+ const url = `${this.connectionConfig.prefixURL()}/${prefixName}`;
2032
+ return this.dispatch(CONST.POST, url, { uri });
2033
+ };
2034
+
2035
+ /**
2036
+ * Update an existing prefix mapping
2037
+ * @param {string} prefixName - The prefix name to update
2038
+ * @param {string} uri - The new IRI for this prefix
2039
+ * @param {string} [dbId] - The database id
2040
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
2041
+ * @example
2042
+ * client.updatePrefix("ex", "http://example.com/").then(result => {
2043
+ * console.log("Prefix updated successfully")
2044
+ * })
2045
+ */
2046
+ WOQLClient.prototype.updatePrefix = function (prefixName, uri, dbId) {
2047
+ if (dbId) {
2048
+ this.db(dbId);
2049
+ }
2050
+ const url = `${this.connectionConfig.prefixURL()}/${prefixName}`;
2051
+ return this.dispatch(CONST.PUT, url, { uri });
2052
+ };
2053
+
2054
+ /**
2055
+ * Create or update a prefix mapping (upsert)
2056
+ * @param {string} prefixName - The prefix name
2057
+ * @param {string} uri - The IRI for this prefix
2058
+ * @param {string} [dbId] - The database id
2059
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
2060
+ * @example
2061
+ * client.upsertPrefix("ex", "http://example.org/").then(result => {
2062
+ * console.log("Prefix created or updated successfully")
2063
+ * })
2064
+ */
2065
+ WOQLClient.prototype.upsertPrefix = function (prefixName, uri, dbId) {
2066
+ if (dbId) {
2067
+ this.db(dbId);
2068
+ }
2069
+ const url = `${this.connectionConfig.prefixURL()}/${prefixName}?create=true`;
2070
+ return this.dispatch(CONST.PUT, url, { uri });
2071
+ };
2072
+
2073
+ /**
2074
+ * Delete a prefix mapping
2075
+ * @param {string} prefixName - The prefix name to delete
2076
+ * @param {string} [dbId] - The database id
2077
+ * @returns {Promise} A promise that returns the call response object, or an Error if rejected.
2078
+ * @example
2079
+ * client.deletePrefix("ex").then(result => {
2080
+ * console.log("Prefix deleted successfully")
2081
+ * })
2082
+ */
2083
+ WOQLClient.prototype.deletePrefix = function (prefixName, dbId) {
2084
+ if (dbId) {
2085
+ this.db(dbId);
2086
+ }
2087
+ const url = `${this.connectionConfig.prefixURL()}/${prefixName}`;
2088
+ return this.dispatch(CONST.DELETE, url);
2089
+ };
2090
+
2091
+ module.exports = WOQLClient;