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,934 @@
1
+ /* eslint-disable no-underscore-dangle */
2
+ /* eslint-disable no-use-before-define */
3
+ /* eslint-disable guard-for-in */
4
+ /* eslint-disable no-restricted-syntax */
5
+ /* eslint-disable no-unused-vars */
6
+ /* eslint-disable consistent-return */
7
+ /* eslint-disable camelcase */
8
+ /* eslint-disable no-redeclare */
9
+ /* eslint-disable no-plusplus */
10
+ /* eslint-disable block-scoped-var */
11
+ /* eslint-disable no-var */
12
+ /* eslint-disable vars-on-top */
13
+ /* eslint-disable no-param-reassign */
14
+ /// /@ts-check
15
+ const UTILS = require('../utils');
16
+ const WOQLPrinter = require('./woqlPrinter');
17
+ const { Var, Vars, Doc } = require('./woqlDoc');
18
+
19
+ // eslint-disable-next-line no-unused-vars
20
+ const typedef = require('../typedef');
21
+
22
+ /**
23
+ * @typedef {Object} WOQLJson - JSON-LD representation of a WOQL query
24
+ * @property {string} @type - The WOQL operation type
25
+ * @property {*} [subject] - Subject for triple patterns
26
+ * @property {*} [predicate] - Predicate for triple patterns
27
+ * @property {*} [object] - Object for triple patterns
28
+ * @property {WOQLJson[]} [and] - Array of queries for 'And' operations
29
+ * @property {WOQLJson[]} [or] - Array of queries for 'Or' operations
30
+ * @property {WOQLJson} [query] - Nested query
31
+ * @property {string[]} [variables] - Variable list for 'Select' operations
32
+ * @property {string} [graph] - Graph identifier
33
+ * @property {*} [consequent] - Consequent for path queries
34
+ * @property {string} [path_pattern] - Pattern for path queries
35
+ */
36
+
37
+ /**
38
+ * defines the internal functions of the woql query object - the
39
+ * language API is defined in WOQLQuery
40
+ * @module WOQLQuery
41
+ * @constructor
42
+ * @param {object} [query] json-ld query for initialisation
43
+ * @returns {WOQLQuery}
44
+ */
45
+ /* function WOQLQuery(query) {
46
+ this.query = query || {};
47
+ this.errors = [];
48
+ this.cursor = this.query;
49
+ this.chain_ended = false;
50
+ this.contains_update = false;
51
+ // operators which preserve global paging
52
+ this.paging_transitive_properties = ['select', 'from', 'start', 'when', 'opt', 'limit'];
53
+
54
+ this.update_operators = [
55
+ 'AddTriple',
56
+ 'DeleteTriple',
57
+ 'AddQuad',
58
+ 'DeleteQuad',
59
+ 'InsertDocument',
60
+ 'DeleteDocument',
61
+ 'UpdateDocument',
62
+ ];
63
+
64
+ this.vocab = this.loadDefaultVocabulary();
65
+ // object used to accumulate triples from fragments to support usage like node("x").label("y");
66
+ this.tripleBuilder = false;
67
+ return this;
68
+ } */
69
+
70
+ class WOQLQuery {
71
+ triple_builder_context = {};
72
+
73
+ query = null;
74
+
75
+ counter = 1;
76
+
77
+ errors = [];
78
+
79
+ cursor = {};
80
+
81
+ chain_ended = false;
82
+
83
+ contains_update = false;
84
+
85
+ // operators which preserve global paging
86
+ paging_transitive_properties = ['select', 'from', 'start', 'when', 'opt', 'limit'];
87
+
88
+ update_operators = [
89
+ 'AddTriple',
90
+ 'DeleteTriple',
91
+ 'AddQuad',
92
+ 'DeleteQuad',
93
+ 'InsertDocument',
94
+ 'DeleteDocument',
95
+ 'UpdateDocument',
96
+ ];
97
+
98
+ vocab = this.loadDefaultVocabulary();
99
+
100
+ // object used to accumulate triples from fragments to support usage like node("x").label("y");
101
+ tripleBuilder = false;
102
+ /**
103
+ * defines the internal functions of the woql query object - the
104
+ * language API is defined in WOQLQuery
105
+ * @module WOQLQuery
106
+ * @constructor
107
+ * @param {object} [query] json-ld query for initialisation
108
+ * @returns {WOQLQuery}
109
+ */
110
+
111
+ constructor(query) {
112
+ this.query = query || {};
113
+ // this.errors = [];
114
+ this.cursor = this.query;
115
+
116
+ // eslint-disable-next-line no-constructor-return
117
+ return this;
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Basic Error handling
123
+ */
124
+ WOQLQuery.prototype.parameterError = function (msg) {
125
+ this.errors.push({ type: this.cursor['@type'], message: msg });
126
+ return this;
127
+ };
128
+
129
+ WOQLQuery.prototype.hasErrors = function () {
130
+ return this.errors.length > 0;
131
+ };
132
+
133
+ /**
134
+ * Internal library function which adds a subquery and sets the cursor
135
+ */
136
+ WOQLQuery.prototype.addSubQuery = function (Subq) {
137
+ if (Subq) {
138
+ this.cursor.query = this.jobj(Subq);
139
+ } else {
140
+ const nv = {};
141
+ this.cursor.query = nv;
142
+ this.cursor = nv;
143
+ }
144
+ return this;
145
+ };
146
+
147
+ /**
148
+ * Does this query contain an update
149
+ */
150
+ WOQLQuery.prototype.containsUpdate = function (json) {
151
+ json = json || this.query;
152
+ if (this.update_operators.indexOf(json['@type']) !== -1) return true;
153
+ if (json.consequent && this.containsUpdate(json.consequent)) return true;
154
+ if (json.query) return this.containsUpdate(json.query);
155
+ if (json.and) {
156
+ for (var i = 0; i < json.and.length; i++) {
157
+ if (this.containsUpdate(json.and[i])) return true;
158
+ }
159
+ }
160
+ if (json.or) {
161
+ for (var i = 0; i < json.or.length; i++) {
162
+ if (this.containsUpdate(json.or[i])) return true;
163
+ }
164
+ }
165
+
166
+ return false;
167
+ };
168
+
169
+ /**
170
+ * Called to inidicate that this query will cause an update to the DB
171
+ */
172
+ WOQLQuery.prototype.updated = function () {
173
+ this.contains_update = true;
174
+ return this;
175
+ };
176
+
177
+ /**
178
+ * A bunch of internal functions for formatting values for JSON-LD translation
179
+ */
180
+
181
+ /**
182
+ * Wraps the passed value in a json-ld literal carriage
183
+ */
184
+ WOQLQuery.prototype.jlt = function (val, type) {
185
+ if (!type) type = 'xsd:string';
186
+ else type = type.indexOf(':') === -1 ? `xsd:${type}` : type;
187
+ return { '@type': type, '@value': val };
188
+ };
189
+
190
+ WOQLQuery.prototype.varj = function (varb) {
191
+ if (varb instanceof Var) varb = varb.name;
192
+ if (varb.substring(0, 2) === 'v:') varb = varb.substring(2);
193
+ if (typeof varb === 'string') {
194
+ return {
195
+ '@type': 'Value',
196
+ variable: varb,
197
+ };
198
+ }
199
+ return varb;
200
+ };
201
+
202
+ WOQLQuery.prototype.rawVar = function (varb) {
203
+ if (varb instanceof Var) return varb.name;
204
+ if (varb.substring(0, 2) === 'v:') varb = varb.substring(2);
205
+ return varb;
206
+ };
207
+
208
+ WOQLQuery.prototype.rawVarList = function (vl) {
209
+ const ret = [];
210
+ for (let i = 0; i < vl.length; i++) {
211
+ const co = this.rawVar(vl[i]);
212
+ ret.push(co);
213
+ }
214
+ return ret;
215
+ };
216
+
217
+ /**
218
+ * Transforms a javascript representation of a query into a json object if needs be
219
+ */
220
+ WOQLQuery.prototype.jobj = function (qobj) {
221
+ if (qobj.json) {
222
+ return qobj.json();
223
+ }
224
+ if (qobj === true) return { '@type': 'True' };
225
+ return qobj;
226
+ // return new WOQLQuery.json(qobj);
227
+ };
228
+
229
+ /**
230
+ * Wraps the elements of an AS variable in the appropriate json-ld
231
+ */
232
+ WOQLQuery.prototype.asv = function (colname_or_index, variable, type) {
233
+ const asvar = {};
234
+ if (typeof colname_or_index === 'number') {
235
+ asvar['@type'] = 'Column';
236
+ asvar.indicator = { '@type': 'Indicator', index: colname_or_index };
237
+ } else if (typeof colname_or_index === 'string') {
238
+ asvar['@type'] = 'Column';
239
+ asvar.indicator = { '@type': 'Indicator', name: colname_or_index };
240
+ }
241
+ if (variable instanceof Var) {
242
+ asvar.variable = variable.name;
243
+ } else if (variable.substring(0, 2) === 'v:') {
244
+ asvar.variable = variable.substring(2);
245
+ } else {
246
+ asvar.variable = variable;
247
+ }
248
+ if (type) asvar.type = type;
249
+ return asvar;
250
+ };
251
+
252
+ /**
253
+ * JSON LD Format Descriptor
254
+ * @param {object} opts
255
+ */
256
+ WOQLQuery.prototype.wform = function (opts) {
257
+ if (opts && opts.type) {
258
+ this.cursor.format = {
259
+ '@type': 'Format',
260
+ format_type: { '@value': opts.type, '@type': 'xsd:string' },
261
+ };
262
+ if (typeof opts.format_header !== 'undefined') {
263
+ const h = !!opts.format_header;
264
+ this.cursor.format.format_header = {
265
+ '@value': h,
266
+ '@type': 'xsd:boolean',
267
+ };
268
+ }
269
+ }
270
+ return this;
271
+ };
272
+
273
+ /**
274
+ * Wraps arithmetic operators in the appropriate json-ld
275
+ */
276
+ WOQLQuery.prototype.arop = function (arg) {
277
+ if (typeof arg === 'object') {
278
+ return this.jobj(this.cleanArithmeticValue(arg));
279
+ }
280
+ return this.cleanArithmeticValue(arg, 'xsd:decimal');
281
+ };
282
+
283
+ /**
284
+ * takes input that can be either a string (variable name)
285
+ * or an array - each element of the array is a member of the list
286
+ */
287
+ WOQLQuery.prototype.dataList = function (wvar, string_only) {
288
+ if (typeof wvar === 'string') return this.expandDataVariable(wvar, true);
289
+ if (Array.isArray(wvar)) {
290
+ const ret = [];
291
+ for (let i = 0; i < wvar.length; i++) {
292
+ const co = this.cleanDataValue(wvar[i]);
293
+ ret.push(co);
294
+ }
295
+ return ret;
296
+ }
297
+ };
298
+
299
+ /**
300
+ * takes a list of input that can be any value
301
+ */
302
+ WOQLQuery.prototype.valueList = function (wvar, string_only) {
303
+ if (typeof wvar === 'string') return this.expandValueVariable(wvar, true);
304
+ if (Array.isArray(wvar)) {
305
+ const ret = [];
306
+ for (let i = 0; i < wvar.length; i++) {
307
+ let co = this.cleanObject(wvar[i]);
308
+ if (typeof co === 'string') co = { node: co };
309
+ ret.push(co);
310
+ }
311
+ return ret;
312
+ }
313
+ };
314
+
315
+ /**
316
+ * creates an unadorned variable name list
317
+ */
318
+ WOQLQuery.prototype.vlist = function (list) {
319
+ const vl = [];
320
+ for (let i = 0; i < list.length; i++) {
321
+ const v = this.expandValueVariable(list[i]);
322
+ vl.push(v.variable);
323
+ }
324
+ return vl;
325
+ };
326
+
327
+ /**
328
+ * Wraps data values
329
+ */
330
+ WOQLQuery.prototype.dataValueList = function (list) {
331
+ const dvl = [];
332
+ for (let i = 0; i < list.length; i++) {
333
+ const o = this.cleanDataValue(list[i]);
334
+ dvl.push(o);
335
+ }
336
+ return dvl;
337
+ };
338
+
339
+ /**
340
+ * Transforms whatever is passed in as the subject into the appropriate json-ld for variable or id
341
+ */
342
+ WOQLQuery.prototype.cleanSubject = function (s) {
343
+ /**
344
+ * @type {any}
345
+ */
346
+ let subj = false;
347
+ if (s instanceof Var) {
348
+ return this.expandNodeVariable(s);
349
+ } if (typeof s === 'object') {
350
+ return s;
351
+ } if (typeof s === 'string') {
352
+ if (s.indexOf('v:') !== -1) subj = s;
353
+ else subj = s;
354
+ return this.expandNodeVariable(subj);
355
+ }
356
+ this.parameterError('Subject must be a URI string');
357
+ return `${s}`;
358
+ };
359
+
360
+ /**
361
+ * Transforms whatever is passed in as the predicate (id or variable) into the
362
+ * appropriate json-ld form
363
+ */
364
+ WOQLQuery.prototype.cleanPredicate = function (p) {
365
+ /**
366
+ * @type {any}
367
+ */
368
+ let pred = false;
369
+ if (p instanceof Var) return this.expandNodeVariable(p);
370
+ if (typeof p === 'object') return p;
371
+ if (typeof p !== 'string') {
372
+ this.parameterError('Predicate must be a URI string');
373
+ return `${p}`;
374
+ }
375
+ if (p.indexOf(':') !== -1) pred = p;
376
+ else if (this.wellKnownPredicate(p)) pred = p;// this.vocab[p]
377
+ else pred = p;// 'scm'
378
+ // else pred = 'scm:' + p
379
+ return this.expandNodeVariable(pred);
380
+ };
381
+
382
+ WOQLQuery.prototype.wellKnownPredicate = function (p, noxsd) {
383
+ if (this.vocab && this.vocab[p]) {
384
+ const full = this.vocab[p];
385
+ const start = full.substring(0, 3);
386
+ if (full === 'system:abstract' || start === 'xdd' || start === 'xsd') return false;
387
+ return true;
388
+ }
389
+ return false;
390
+ };
391
+
392
+ WOQLQuery.prototype.cleanPathPredicate = function (p) {
393
+ let pred = false;
394
+ if (p.indexOf(':') !== -1) pred = p;
395
+ else if (this.wellKnownPredicate(p)) pred = this.vocab[p];
396
+ else pred = p; // 'scm:' + p
397
+ return pred;
398
+ };
399
+
400
+ /**
401
+ * Transforms whatever is passed in as the object of
402
+ * a triple into the appropriate json-ld form (variable, literal or id)
403
+ */
404
+ WOQLQuery.prototype.cleanObject = function (o, t) {
405
+ const obj = { '@type': 'Value' };
406
+ if (o instanceof Var) {
407
+ return this.expandValueVariable(o);
408
+ } if (o instanceof Doc) {
409
+ return o.encoded;
410
+ } if (typeof o === 'string') {
411
+ if (o.indexOf('v:') !== -1) {
412
+ return this.expandValueVariable(o);
413
+ }
414
+ obj.node = o;
415
+ } else if (typeof o === 'number') {
416
+ t = t || 'xsd:decimal';
417
+ obj.data = this.jlt(o, t);
418
+ } else if (typeof o === 'boolean') {
419
+ t = t || 'xsd:boolean';
420
+ obj.data = this.jlt(o, t);
421
+ } else if (Array.isArray(o)) {
422
+ const res = [];
423
+ for (let i = 0; i < o.length; i++) {
424
+ res.push(this.cleanObject(o[i]));
425
+ }
426
+ obj.list = res;
427
+ } else if (typeof o === 'object' && o) {
428
+ if (typeof o['@value'] !== 'undefined') {
429
+ obj.data = o;
430
+ } else {
431
+ return o;
432
+ }
433
+ }
434
+ return obj;
435
+ };
436
+
437
+ WOQLQuery.prototype.cleanDataValue = function (o, t) {
438
+ const obj = { '@type': 'DataValue' };
439
+ if (o instanceof Var) {
440
+ return this.expandDataVariable(o);
441
+ }
442
+ if (o instanceof Doc) {
443
+ return o.encoded;
444
+ }
445
+ if (typeof o === 'string') {
446
+ if (o.indexOf('v:') !== -1) {
447
+ return this.expandDataVariable(o);
448
+ }
449
+ obj.data = this.jlt(o, t);
450
+ } else if (typeof o === 'number') {
451
+ t = t || 'xsd:decimal';
452
+ obj.data = this.jlt(o, t);
453
+ } else if (typeof o === 'boolean') {
454
+ t = t || 'xsd:boolean';
455
+ obj.data = this.jlt(o, t);
456
+ } else if (Array.isArray(o)) {
457
+ const res = [];
458
+ for (let i = 0; i < o.length; i++) {
459
+ res.push(this.cleanDataValue(o[i]));
460
+ }
461
+ obj.list = res;
462
+ } else if (typeof o === 'object' && o) {
463
+ if (o['@value']) obj.data = o;
464
+ else return o;
465
+ }
466
+ return obj;
467
+ };
468
+
469
+ WOQLQuery.prototype.cleanArithmeticValue = function (o, t) {
470
+ const obj = { '@type': 'ArithmeticValue' };
471
+ if (o instanceof Var) {
472
+ return this.expandArithmeticVariable(o);
473
+ } if (typeof o === 'string') {
474
+ if (o.indexOf('v:') !== -1) {
475
+ return this.expandArithmeticVariable(o);
476
+ }
477
+ obj.data = this.jlt(o, t);
478
+ } else if (typeof o === 'number') {
479
+ t = t || 'xsd:decimal';
480
+ obj.data = this.jlt(o, t);
481
+ } else if (typeof o === 'object' && o) {
482
+ if (o['@value']) obj.data = o;
483
+ else return o;
484
+ }
485
+ return obj;
486
+ };
487
+
488
+ WOQLQuery.prototype.cleanNodeValue = function (o, t) {
489
+ const obj = { '@type': 'NodeValue' };
490
+ if (o instanceof Var) {
491
+ return this.expandNodeVariable(o);
492
+ } if (typeof o === 'string') {
493
+ if (o.indexOf('v:') !== -1) {
494
+ return this.expandNodeVariable(o);
495
+ }
496
+ obj.node = o;
497
+ } else if (typeof o === 'object' && o) {
498
+ return o;
499
+ }
500
+ return obj;
501
+ };
502
+
503
+ /**
504
+ * Transforms a graph filter or graph id into the proper json-ld form
505
+ */
506
+ WOQLQuery.prototype.cleanGraph = function (g) {
507
+ return g;
508
+ };
509
+
510
+ /**
511
+ * Transforms strings that start with v: into variable json-ld structures
512
+ * @param varname - will be transformed if it starts with v:
513
+ */
514
+ WOQLQuery.prototype.expandVariable = function (varname, type, always) {
515
+ if (varname instanceof Var) {
516
+ return {
517
+ '@type': type,
518
+ variable: varname.name,
519
+ };
520
+ } if (varname.substring(0, 2) === 'v:' || always) {
521
+ if (varname.substring(0, 2) === 'v:') varname = varname.substring(2);
522
+ return {
523
+ '@type': type,
524
+ variable: varname,
525
+ };
526
+ }
527
+ return {
528
+ '@type': type,
529
+ node: varname,
530
+ };
531
+ };
532
+
533
+ WOQLQuery.prototype.expandValueVariable = function (varname, always) {
534
+ return this.expandVariable(varname, 'Value', always);
535
+ };
536
+
537
+ WOQLQuery.prototype.expandNodeVariable = function (varname, always) {
538
+ return this.expandVariable(varname, 'NodeValue', always);
539
+ };
540
+
541
+ WOQLQuery.prototype.expandDataVariable = function (varname, always) {
542
+ return this.expandVariable(varname, 'DataValue', always);
543
+ };
544
+
545
+ WOQLQuery.prototype.expandArithmeticVariable = function (varname, always) {
546
+ return this.expandVariable(varname, 'ArithmeticValue', always);
547
+ };
548
+
549
+ WOQLQuery.prototype.defaultContext = function (DB_IRI) {
550
+ const def = {};
551
+ for (const pref in UTILS.standard_urls) {
552
+ def[pref] = UTILS.standard_urls[pref];
553
+ }
554
+ def.scm = `${DB_IRI}/schema#`;
555
+ def.doc = `${DB_IRI}/data/`;
556
+ return def;
557
+ };
558
+
559
+ /**
560
+ * Retrieves the value of the current json-ld context
561
+ */
562
+ WOQLQuery.prototype.getContext = function (q) {
563
+ q = q || this.query;
564
+ for (const prop of Object.keys(q)) {
565
+ if (prop === '@context') return q[prop];
566
+ if (this.paging_transitive_properties.indexOf(prop) !== -1) {
567
+ const nq = q[prop][1];
568
+ const nc = this.getContext(nq);
569
+ if (nc) return nc;
570
+ }
571
+ }
572
+ };
573
+
574
+ /**
575
+ * sets the value of the current json-ld context on a full query scope
576
+ */
577
+ WOQLQuery.prototype.context = function (c) {
578
+ this.query['@context'] = c;
579
+ };
580
+
581
+ /**
582
+ * vocabulary elements that can be used without prefixes in woql.js queries
583
+ */
584
+ WOQLQuery.prototype.loadDefaultVocabulary = function () {
585
+ const vocab = {};
586
+ // vocab.type = 'rdf:type'
587
+ // vocab.label = 'rdfs:label'
588
+ vocab.Class = 'owl:Class';
589
+ vocab.DatatypeProperty = 'owl:DatatypeProperty';
590
+ vocab.ObjectProperty = 'owl:ObjectProperty';
591
+ vocab.Document = 'system:Document';
592
+ vocab.abstract = 'system:abstract';
593
+ vocab.comment = 'rdfs:comment';
594
+ vocab.range = 'rdfs:range';
595
+ vocab.domain = 'rdfs:domain';
596
+ vocab.subClassOf = 'rdfs:subClassOf';
597
+ vocab.string = 'xsd:string';
598
+ vocab.integer = 'xsd:integer';
599
+ vocab.decimal = 'xsd:decimal';
600
+ vocab.boolean = 'xdd:boolean';
601
+ vocab.email = 'xdd:email';
602
+ vocab.json = 'xdd:json';
603
+ vocab.dateTime = 'xsd:dateTime';
604
+ vocab.date = 'xsd:date';
605
+ vocab.coordinate = 'xdd:coordinate';
606
+ vocab.line = 'xdd:coordinatePolyline';
607
+ vocab.polygon = 'xdd:coordinatePolygon';
608
+ return vocab;
609
+ };
610
+
611
+ /**
612
+ * Provides the query with a 'vocabulary' a list of well known predicates that can be used without
613
+ * prefixes mapping: id: prefix:id ...
614
+ */
615
+ WOQLQuery.prototype.setVocabulary = function (vocab) {
616
+ this.vocab = vocab;
617
+ };
618
+
619
+ WOQLQuery.prototype.getVocabulary = function (vocab) {
620
+ return this.vocab;
621
+ };
622
+
623
+ /**
624
+ * Use instead woqlclient.query('myWOQLQuery')
625
+ * @deprecated
626
+ * Executes the query using the passed client to connect to a server
627
+ *
628
+ */
629
+ WOQLQuery.prototype.execute = function (client, commit_msg) {
630
+ return client.query(this, commit_msg);
631
+ };
632
+
633
+ /**
634
+ * converts back and forward from json
635
+ * if the argument is present, the current query is set to it,
636
+ * if the argument is not present, the current json version of this query is returned
637
+ * @param {WOQLJson} [json] - a query in json format
638
+ * @returns {WOQLQuery | WOQLJson} Returns WOQLQuery when setting (for chaining),
639
+ * or WOQLJson when getting
640
+ */
641
+ WOQLQuery.prototype.json = function (json) {
642
+ if (json) {
643
+ this.query = copyJSON(json);
644
+ return this;
645
+ }
646
+ return copyJSON(this.query, true);
647
+ };
648
+
649
+ /**
650
+ * Returns a script version of the query
651
+ *
652
+ * @param {string} [clang] - either "js" or "python"
653
+ */
654
+ WOQLQuery.prototype.prettyPrint = function (clang = 'js') {
655
+ const printer = new WOQLPrinter(this.vocab, clang);
656
+ return printer.printJSON(this.query);
657
+ };
658
+
659
+ /**
660
+ * Finds the last woql element that has a subject in it and returns the json for that
661
+ * used for triplebuilder to chain further calls - when they may be inside ands or ors or subqueries
662
+ * @param {object} json
663
+ */
664
+ WOQLQuery.prototype.findLastSubject = function (json) {
665
+ if (json && json.and) {
666
+ for (var i = json.and.length - 1; i >= 0; i--) {
667
+ const lqs = this.findLastSubject(json.and[i]);
668
+ if (lqs) return lqs;
669
+ }
670
+ }
671
+ if (json && json.or) {
672
+ for (var i = json.or.length - 1; i >= 0; i--) {
673
+ const lqs = this.findLastSubject(json.or[i]);
674
+ if (lqs) return lqs;
675
+ }
676
+ }
677
+ if (json && json.query) {
678
+ const ls = this.findLastSubject(json.query);
679
+ if (ls) return ls;
680
+ }
681
+ // check for cardinality here
682
+ if (json && json.subject) {
683
+ return json;
684
+ }
685
+ return false;
686
+ };
687
+
688
+ /**
689
+ * Finds the last woql element that has a subject in that is a property id
690
+ * used for triplebuilder to chain further calls - when they may be inside ands or ors or subqueries
691
+ * @param {object} json
692
+ */
693
+ WOQLQuery.prototype.findLastProperty = function (json) {
694
+ if (json && json.and) {
695
+ for (var i = json.and.length - 1; i >= 0; i--) {
696
+ const lqs = this.findLastProperty(json.and[i]);
697
+ if (lqs) return lqs;
698
+ }
699
+ }
700
+ if (json && json.or) {
701
+ for (var i = json.or.length - 1; i >= 0; i--) {
702
+ const lqs = this.findLastProperty(json.or[i]);
703
+ if (lqs) return lqs;
704
+ }
705
+ }
706
+ if (json && json.query) {
707
+ const ls = this.findLastProperty(json.query);
708
+ if (ls) return ls;
709
+ }
710
+ if (
711
+ json
712
+ && json.subject
713
+ && this._is_property_triple(json.predicate, json.object)
714
+ ) {
715
+ return json;
716
+ }
717
+ return false;
718
+ };
719
+
720
+ WOQLQuery.prototype._is_property_triple = function (pred, obj) {
721
+ const pred_str = pred.node ? pred.node : pred;
722
+ const obj_str = obj.node ? obj.node : obj;
723
+ if (obj_str === 'owl:ObjectProperty' || obj_str === 'owl:DatatypeProperty') return true;
724
+ if (pred_str === 'rdfs:domain' || pred_str === 'rdfs:range') return true;
725
+ return false;
726
+ };
727
+
728
+ /**
729
+ * Turns a textual path pattern into a JSON-LD description
730
+ */
731
+ WOQLQuery.prototype.compilePathPattern = function (pat) {
732
+ const toks = tokenize(pat);
733
+ if (toks && toks.length) return tokensToJSON(toks, this);
734
+ this.parameterError(`Pattern error - could not be parsed ${pat}`);
735
+ };
736
+
737
+ /**
738
+ * Tokenizes the pattern into a sequence of tokens which may be clauses or operators
739
+ * @param {string} pat
740
+ */
741
+ function tokenize(pat) {
742
+ let parts = getClauseAndRemainder(pat);
743
+ const seq = [];
744
+ while (parts.length === 2) {
745
+ seq.push(parts[0]);
746
+ parts = getClauseAndRemainder(parts[1]);
747
+ }
748
+ seq.push(parts[0]);
749
+ return seq;
750
+ }
751
+
752
+ /**
753
+ * Breaks a graph pattern up into two parts - the next clause, and the remainder of the string
754
+ * @param {string} pat - graph pattern fragment
755
+ */
756
+ function getClauseAndRemainder(pat) {
757
+ pat = pat.trim();
758
+ let open = 1;
759
+ // if there is a parentheses, we treat it as a clause and go to the end
760
+ if (pat.charAt(0) === '(') {
761
+ for (var i = 1; i < pat.length; i++) {
762
+ if (pat.charAt(i) === '(') open++;
763
+ else if (pat.charAt(i) === ')') open--;
764
+ if (open === 0) {
765
+ const rem = pat.substring(i + 1).trim();
766
+ if (rem) return [pat.substring(1, i), rem];
767
+ // eslint-disable-next-line max-len
768
+ return getClauseAndRemainder(pat.substring(1, i)); // whole thing surrounded by parentheses, strip them out and reparse
769
+ }
770
+ }
771
+ return [];
772
+ }
773
+ if (pat[0] === '+' || pat[0] === ',' || pat[0] === '|' || pat[0] === '*') {
774
+ const ret = [pat[0]];
775
+ if (pat.substring(1)) ret.push(pat.substring(1));
776
+ return ret;
777
+ }
778
+ if (pat.charAt(0) === '{') {
779
+ const ret = [pat.substring(0, pat.indexOf('}') + 1)];
780
+ if (pat.substring(pat.indexOf('}') + 1)) ret.push(pat.substring(pat.indexOf('}') + 1));
781
+ return ret;
782
+ }
783
+ for (var i = 1; i < pat.length; i++) {
784
+ if (pat[i] === ',' || pat[i] === '|' || pat[i] === '+' || pat[i] === '{' || pat[i] === '*') return [pat.substring(0, i), pat.substring(i)];
785
+ }
786
+ return [pat];
787
+ }
788
+
789
+ function compilePredicate(pp, q) {
790
+ if (pp.indexOf('<') !== -1 && pp.indexOf('>') !== -1) {
791
+ const pred = pp.slice(1, pp.length - 1);
792
+ // eslint-disable-next-line no-multi-assign,no-constant-condition
793
+ const cleaned = pred === '.' ? null : q.cleanPathPredicate(pred);
794
+ return {
795
+ '@type': 'PathOr',
796
+ or: [{
797
+ '@type': 'InversePathPredicate',
798
+ predicate: cleaned,
799
+ },
800
+ {
801
+ '@type': 'PathPredicate',
802
+ predicate: cleaned,
803
+ }],
804
+ };
805
+ } if (pp.indexOf('<') !== -1) {
806
+ const pred = pp.slice(1, pp.length);
807
+ const cleaned = pred === '.' ? null : q.cleanPathPredicate(pred);
808
+ return { '@type': 'InversePathPredicate', predicate: cleaned };
809
+ } if (pp.indexOf('>') !== -1) {
810
+ const pred = pp.slice(0, pp.length - 1);
811
+ const cleaned = pred === '.' ? null : q.cleanPathPredicate(pred);
812
+ return { '@type': 'PathPredicate', predicate: cleaned };
813
+ }
814
+ const cleaned = pp === '.' ? null : q.cleanPathPredicate(pp);
815
+ return { '@type': 'PathPredicate', predicate: cleaned };
816
+ }
817
+
818
+ /**
819
+ * Turns a sequence of tokens into the appropriate JSON-LD
820
+ * @param {Array} seq
821
+ * @param {*} q
822
+ */
823
+ function tokensToJSON(seq, q) {
824
+ if (seq.length === 1) {
825
+ // may need to be further tokenized
826
+ const ntoks = tokenize(seq[0]);
827
+ if (ntoks.length === 1) {
828
+ // only a single element in clause - cannot be further tokenised
829
+ const tok = ntoks[0].trim();
830
+ return compilePredicate(tok, q);
831
+ }
832
+ return tokensToJSON(ntoks, q);
833
+ } if (seq.indexOf('|') !== -1) {
834
+ // binds most loosely
835
+ const left = seq.slice(0, seq.indexOf('|'));
836
+ const right = seq.slice(seq.indexOf('|') + 1);
837
+ return {
838
+ '@type': 'PathOr',
839
+ or: [tokensToJSON(left, q), tokensToJSON(right, q)],
840
+ };
841
+ } if (seq.indexOf(',') !== -1) {
842
+ // binds tighter
843
+ const first = seq.slice(0, seq.indexOf(','));
844
+ const second = seq.slice(seq.indexOf(',') + 1);
845
+ return {
846
+ '@type': 'PathSequence',
847
+ sequence: [tokensToJSON(first, q), tokensToJSON(second, q)],
848
+ };
849
+ } if (seq[1] === '+') {
850
+ // binds tightest of all
851
+ return {
852
+ '@type': 'PathPlus',
853
+ plus: tokensToJSON([seq[0]], q),
854
+ };
855
+ } if (seq[1] === '*') {
856
+ // binds tightest of all
857
+ return {
858
+ '@type': 'PathStar',
859
+ star: tokensToJSON([seq[0]], q),
860
+ };
861
+ } if (seq[1].charAt(0) === '{') {
862
+ // binds tightest of all
863
+ // we need a test here
864
+ const meat = seq[1].substring(1, seq[1].length - 1).split(',');
865
+ return {
866
+ '@type': 'PathTimes',
867
+ from: meat[0],
868
+ to: meat[1],
869
+ times: tokensToJSON([seq[0]], q),
870
+ };
871
+ }
872
+ // shouldn't get here - error
873
+ q.parameterError(`Pattern error - could not be parsed ${seq[0]}`);
874
+ return {
875
+ '@type': 'PathPredicate',
876
+ 'rdfs:label': `failed to parse query ${seq[0]}`,
877
+ };
878
+ }
879
+
880
+ /**
881
+ * Creates a copy of the passed json representation of a woql query
882
+ * Performing tidying up in doing so - strips out empty queries, rolls up
883
+ * ands and ors with single entries
884
+ *
885
+ * @param {object} orig
886
+ * @returns {object} copy of the passed json object
887
+ */
888
+ function copyJSON(orig, rollup) {
889
+ if (Array.isArray(orig)) return orig;
890
+ if (rollup) {
891
+ if (orig['@type'] === 'And') {
892
+ if (!orig.and || !orig.and.length) return {};
893
+ if (orig.and.length === 1) return copyJSON(orig.and[0], rollup);
894
+ } else if (orig['@type'] === 'Or') {
895
+ if (!orig.or || !orig.or.length) return {};
896
+ if (orig.or.length === 1) return copyJSON(orig.or[0], rollup);
897
+ }
898
+
899
+ if (typeof orig.query !== 'undefined' && orig['@type'] !== 'Comment') {
900
+ if (!orig.query['@type']) return {};
901
+ } else if (orig['@type'] === 'Comment' && orig.comment) {
902
+ if (!orig.query || !orig.query['@type']) return { '@type': 'Comment', comment: orig.comment };
903
+ }
904
+ if (typeof orig.consequent !== 'undefined') {
905
+ if (!orig.consequent['@type']) return {};
906
+ }
907
+ }
908
+ const nuj = {};
909
+ for (const k in orig) {
910
+ const part = orig[k];
911
+ if (Array.isArray(part)) {
912
+ const nupart = [];
913
+ for (let j = 0; j < part.length; j++) {
914
+ if (typeof part[j] === 'object') {
915
+ const sub = copyJSON(part[j], rollup);
916
+ if (!sub || !UTILS.empty(sub)) nupart.push(sub);
917
+ } else {
918
+ nupart.push(part[j]);
919
+ }
920
+ }
921
+ nuj[k] = nupart;
922
+ } else if (part === null) {
923
+ // do nothing
924
+ } else if (typeof part === 'object') {
925
+ const q = copyJSON(part, rollup);
926
+ if (!q || !UTILS.empty(q)) nuj[k] = q;
927
+ } else {
928
+ nuj[k] = part;
929
+ }
930
+ }
931
+ return nuj;
932
+ }
933
+
934
+ module.exports = WOQLQuery;