@nocobase/plugin-workflow-json-query 1.9.0-beta.17

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 (50) hide show
  1. package/LICENSE.txt +172 -0
  2. package/README.md +1 -0
  3. package/client.d.ts +2 -0
  4. package/client.js +1 -0
  5. package/dist/client/index.d.ts +23 -0
  6. package/dist/client/index.js +10 -0
  7. package/dist/client/instruction.d.ts +167 -0
  8. package/dist/externalVersion.js +19 -0
  9. package/dist/index.d.ts +17 -0
  10. package/dist/index.js +42 -0
  11. package/dist/locale/en-US.json +13 -0
  12. package/dist/locale/index.d.ts +10 -0
  13. package/dist/locale/index.js +42 -0
  14. package/dist/locale/zh-CN.json +14 -0
  15. package/dist/node_modules/jmespath/LICENSE +13 -0
  16. package/dist/node_modules/jmespath/artifacts/jmespath.min.js +2 -0
  17. package/dist/node_modules/jmespath/bower.json +24 -0
  18. package/dist/node_modules/jmespath/jmespath.js +1 -0
  19. package/dist/node_modules/jmespath/jp.js +23 -0
  20. package/dist/node_modules/jmespath/package.json +1 -0
  21. package/dist/node_modules/jsonata/LICENSE +19 -0
  22. package/dist/node_modules/jsonata/jsonata-es5.js +9875 -0
  23. package/dist/node_modules/jsonata/jsonata-es5.min.js +1 -0
  24. package/dist/node_modules/jsonata/jsonata.d.ts +72 -0
  25. package/dist/node_modules/jsonata/jsonata.js +1 -0
  26. package/dist/node_modules/jsonata/jsonata.min.js +1 -0
  27. package/dist/node_modules/jsonata/package.json +1 -0
  28. package/dist/node_modules/jsonpath-plus/LICENSE +22 -0
  29. package/dist/node_modules/jsonpath-plus/bin/jsonpath-cli.js +36 -0
  30. package/dist/node_modules/jsonpath-plus/dist/index-browser-esm.js +2158 -0
  31. package/dist/node_modules/jsonpath-plus/dist/index-browser-esm.min.js +2 -0
  32. package/dist/node_modules/jsonpath-plus/dist/index-browser-umd.cjs +2166 -0
  33. package/dist/node_modules/jsonpath-plus/dist/index-browser-umd.min.cjs +2 -0
  34. package/dist/node_modules/jsonpath-plus/dist/index-node-cjs.cjs +1 -0
  35. package/dist/node_modules/jsonpath-plus/dist/index-node-esm.js +2068 -0
  36. package/dist/node_modules/jsonpath-plus/package.json +1 -0
  37. package/dist/node_modules/jsonpath-plus/src/Safe-Script.js +200 -0
  38. package/dist/node_modules/jsonpath-plus/src/jsonpath-browser.js +102 -0
  39. package/dist/node_modules/jsonpath-plus/src/jsonpath-node.js +8 -0
  40. package/dist/node_modules/jsonpath-plus/src/jsonpath.d.ts +226 -0
  41. package/dist/node_modules/jsonpath-plus/src/jsonpath.js +784 -0
  42. package/dist/server/JSONQueryInstruction.d.ts +42 -0
  43. package/dist/server/JSONQueryInstruction.js +99 -0
  44. package/dist/server/Plugin.d.ts +24 -0
  45. package/dist/server/Plugin.js +62 -0
  46. package/dist/server/index.d.ts +17 -0
  47. package/dist/server/index.js +42 -0
  48. package/package.json +31 -0
  49. package/server.d.ts +2 -0
  50. package/server.js +1 -0
@@ -0,0 +1,784 @@
1
+ /* eslint-disable camelcase -- Convenient for escaping */
2
+
3
+ import {SafeScript} from './Safe-Script.js';
4
+
5
+ /**
6
+ * @typedef {null|boolean|number|string|object|GenericArray} JSONObject
7
+ */
8
+
9
+ /**
10
+ * @typedef {any} AnyItem
11
+ */
12
+
13
+ /**
14
+ * @typedef {any} AnyResult
15
+ */
16
+
17
+ /**
18
+ * Copies array and then pushes item into it.
19
+ * @param {GenericArray} arr Array to copy and into which to push
20
+ * @param {AnyItem} item Array item to add (to end)
21
+ * @returns {GenericArray} Copy of the original array
22
+ */
23
+ function push (arr, item) {
24
+ arr = arr.slice();
25
+ arr.push(item);
26
+ return arr;
27
+ }
28
+ /**
29
+ * Copies array and then unshifts item into it.
30
+ * @param {AnyItem} item Array item to add (to beginning)
31
+ * @param {GenericArray} arr Array to copy and into which to unshift
32
+ * @returns {GenericArray} Copy of the original array
33
+ */
34
+ function unshift (item, arr) {
35
+ arr = arr.slice();
36
+ arr.unshift(item);
37
+ return arr;
38
+ }
39
+
40
+ /**
41
+ * Caught when JSONPath is used without `new` but rethrown if with `new`
42
+ * @extends Error
43
+ */
44
+ class NewError extends Error {
45
+ /**
46
+ * @param {AnyResult} value The evaluated scalar value
47
+ */
48
+ constructor (value) {
49
+ super(
50
+ 'JSONPath should not be called with "new" (it prevents return ' +
51
+ 'of (unwrapped) scalar values)'
52
+ );
53
+ this.avoidNew = true;
54
+ this.value = value;
55
+ this.name = 'NewError';
56
+ }
57
+ }
58
+
59
+ /**
60
+ * @typedef {object} ReturnObject
61
+ * @property {string} path
62
+ * @property {JSONObject} value
63
+ * @property {object|GenericArray} parent
64
+ * @property {string} parentProperty
65
+ */
66
+
67
+ /**
68
+ * @callback JSONPathCallback
69
+ * @param {string|object} preferredOutput
70
+ * @param {"value"|"property"} type
71
+ * @param {ReturnObject} fullRetObj
72
+ * @returns {void}
73
+ */
74
+
75
+ /**
76
+ * @callback OtherTypeCallback
77
+ * @param {JSONObject} val
78
+ * @param {string} path
79
+ * @param {object|GenericArray} parent
80
+ * @param {string} parentPropName
81
+ * @returns {boolean}
82
+ */
83
+
84
+ /**
85
+ * @typedef {any} ContextItem
86
+ */
87
+
88
+ /**
89
+ * @typedef {any} EvaluatedResult
90
+ */
91
+
92
+ /**
93
+ * @callback EvalCallback
94
+ * @param {string} code
95
+ * @param {ContextItem} context
96
+ * @returns {EvaluatedResult}
97
+ */
98
+
99
+ /**
100
+ * @typedef {typeof SafeScript} EvalClass
101
+ */
102
+
103
+ /**
104
+ * @typedef {object} JSONPathOptions
105
+ * @property {JSON} json
106
+ * @property {string|string[]} path
107
+ * @property {"value"|"path"|"pointer"|"parent"|"parentProperty"|
108
+ * "all"} [resultType="value"]
109
+ * @property {boolean} [flatten=false]
110
+ * @property {boolean} [wrap=true]
111
+ * @property {object} [sandbox={}]
112
+ * @property {EvalCallback|EvalClass|'safe'|'native'|
113
+ * boolean} [eval = 'safe']
114
+ * @property {object|GenericArray|null} [parent=null]
115
+ * @property {string|null} [parentProperty=null]
116
+ * @property {JSONPathCallback} [callback]
117
+ * @property {OtherTypeCallback} [otherTypeCallback] Defaults to
118
+ * function which throws on encountering `@other`
119
+ * @property {boolean} [autostart=true]
120
+ */
121
+
122
+ /**
123
+ * @param {string|JSONPathOptions} opts If a string, will be treated as `expr`
124
+ * @param {string} [expr] JSON path to evaluate
125
+ * @param {JSON} [obj] JSON object to evaluate against
126
+ * @param {JSONPathCallback} [callback] Passed 3 arguments: 1) desired payload
127
+ * per `resultType`, 2) `"value"|"property"`, 3) Full returned object with
128
+ * all payloads
129
+ * @param {OtherTypeCallback} [otherTypeCallback] If `@other()` is at the end
130
+ * of one's query, this will be invoked with the value of the item, its
131
+ * path, its parent, and its parent's property name, and it should return
132
+ * a boolean indicating whether the supplied value belongs to the "other"
133
+ * type or not (or it may handle transformations and return `false`).
134
+ * @returns {JSONPath}
135
+ * @class
136
+ */
137
+ function JSONPath (opts, expr, obj, callback, otherTypeCallback) {
138
+ // eslint-disable-next-line no-restricted-syntax -- Allow for pseudo-class
139
+ if (!(this instanceof JSONPath)) {
140
+ try {
141
+ return new JSONPath(opts, expr, obj, callback, otherTypeCallback);
142
+ } catch (e) {
143
+ if (!e.avoidNew) {
144
+ throw e;
145
+ }
146
+ return e.value;
147
+ }
148
+ }
149
+
150
+ if (typeof opts === 'string') {
151
+ otherTypeCallback = callback;
152
+ callback = obj;
153
+ obj = expr;
154
+ expr = opts;
155
+ opts = null;
156
+ }
157
+ const optObj = opts && typeof opts === 'object';
158
+ opts = opts || {};
159
+ this.json = opts.json || obj;
160
+ this.path = opts.path || expr;
161
+ this.resultType = opts.resultType || 'value';
162
+ this.flatten = opts.flatten || false;
163
+ this.wrap = Object.hasOwn(opts, 'wrap') ? opts.wrap : true;
164
+ this.sandbox = opts.sandbox || {};
165
+ this.eval = opts.eval === undefined ? 'safe' : opts.eval;
166
+ this.ignoreEvalErrors = (typeof opts.ignoreEvalErrors === 'undefined')
167
+ ? false
168
+ : opts.ignoreEvalErrors;
169
+ this.parent = opts.parent || null;
170
+ this.parentProperty = opts.parentProperty || null;
171
+ this.callback = opts.callback || callback || null;
172
+ this.otherTypeCallback = opts.otherTypeCallback ||
173
+ otherTypeCallback ||
174
+ function () {
175
+ throw new TypeError(
176
+ 'You must supply an otherTypeCallback callback option ' +
177
+ 'with the @other() operator.'
178
+ );
179
+ };
180
+
181
+ if (opts.autostart !== false) {
182
+ const args = {
183
+ path: (optObj ? opts.path : expr)
184
+ };
185
+ if (!optObj) {
186
+ args.json = obj;
187
+ } else if ('json' in opts) {
188
+ args.json = opts.json;
189
+ }
190
+ const ret = this.evaluate(args);
191
+ if (!ret || typeof ret !== 'object') {
192
+ throw new NewError(ret);
193
+ }
194
+ return ret;
195
+ }
196
+ }
197
+
198
+ // PUBLIC METHODS
199
+ JSONPath.prototype.evaluate = function (
200
+ expr, json, callback, otherTypeCallback
201
+ ) {
202
+ let currParent = this.parent,
203
+ currParentProperty = this.parentProperty;
204
+ let {flatten, wrap} = this;
205
+
206
+ this.currResultType = this.resultType;
207
+ this.currEval = this.eval;
208
+ this.currSandbox = this.sandbox;
209
+ callback = callback || this.callback;
210
+ this.currOtherTypeCallback = otherTypeCallback || this.otherTypeCallback;
211
+
212
+ json = json || this.json;
213
+ expr = expr || this.path;
214
+ if (expr && typeof expr === 'object' && !Array.isArray(expr)) {
215
+ if (!expr.path && expr.path !== '') {
216
+ throw new TypeError(
217
+ 'You must supply a "path" property when providing an object ' +
218
+ 'argument to JSONPath.evaluate().'
219
+ );
220
+ }
221
+ if (!(Object.hasOwn(expr, 'json'))) {
222
+ throw new TypeError(
223
+ 'You must supply a "json" property when providing an object ' +
224
+ 'argument to JSONPath.evaluate().'
225
+ );
226
+ }
227
+ ({json} = expr);
228
+ flatten = Object.hasOwn(expr, 'flatten') ? expr.flatten : flatten;
229
+ this.currResultType = Object.hasOwn(expr, 'resultType')
230
+ ? expr.resultType
231
+ : this.currResultType;
232
+ this.currSandbox = Object.hasOwn(expr, 'sandbox')
233
+ ? expr.sandbox
234
+ : this.currSandbox;
235
+ wrap = Object.hasOwn(expr, 'wrap') ? expr.wrap : wrap;
236
+ this.currEval = Object.hasOwn(expr, 'eval')
237
+ ? expr.eval
238
+ : this.currEval;
239
+ callback = Object.hasOwn(expr, 'callback') ? expr.callback : callback;
240
+ this.currOtherTypeCallback = Object.hasOwn(expr, 'otherTypeCallback')
241
+ ? expr.otherTypeCallback
242
+ : this.currOtherTypeCallback;
243
+ currParent = Object.hasOwn(expr, 'parent') ? expr.parent : currParent;
244
+ currParentProperty = Object.hasOwn(expr, 'parentProperty')
245
+ ? expr.parentProperty
246
+ : currParentProperty;
247
+ expr = expr.path;
248
+ }
249
+ currParent = currParent || null;
250
+ currParentProperty = currParentProperty || null;
251
+
252
+ if (Array.isArray(expr)) {
253
+ expr = JSONPath.toPathString(expr);
254
+ }
255
+ if ((!expr && expr !== '') || !json) {
256
+ return undefined;
257
+ }
258
+
259
+ const exprList = JSONPath.toPathArray(expr);
260
+ if (exprList[0] === '$' && exprList.length > 1) {
261
+ exprList.shift();
262
+ }
263
+ this._hasParentSelector = null;
264
+ const result = this
265
+ ._trace(
266
+ exprList, json, ['$'], currParent, currParentProperty, callback
267
+ )
268
+ .filter(function (ea) {
269
+ return ea && !ea.isParentSelector;
270
+ });
271
+
272
+ if (!result.length) {
273
+ return wrap ? [] : undefined;
274
+ }
275
+ if (!wrap && result.length === 1 && !result[0].hasArrExpr) {
276
+ return this._getPreferredOutput(result[0]);
277
+ }
278
+ return result.reduce((rslt, ea) => {
279
+ const valOrPath = this._getPreferredOutput(ea);
280
+ if (flatten && Array.isArray(valOrPath)) {
281
+ rslt = rslt.concat(valOrPath);
282
+ } else {
283
+ rslt.push(valOrPath);
284
+ }
285
+ return rslt;
286
+ }, []);
287
+ };
288
+
289
+ // PRIVATE METHODS
290
+
291
+ JSONPath.prototype._getPreferredOutput = function (ea) {
292
+ const resultType = this.currResultType;
293
+ switch (resultType) {
294
+ case 'all': {
295
+ const path = Array.isArray(ea.path)
296
+ ? ea.path
297
+ : JSONPath.toPathArray(ea.path);
298
+ ea.pointer = JSONPath.toPointer(path);
299
+ ea.path = typeof ea.path === 'string'
300
+ ? ea.path
301
+ : JSONPath.toPathString(ea.path);
302
+ return ea;
303
+ } case 'value': case 'parent': case 'parentProperty':
304
+ return ea[resultType];
305
+ case 'path':
306
+ return JSONPath.toPathString(ea[resultType]);
307
+ case 'pointer':
308
+ return JSONPath.toPointer(ea.path);
309
+ default:
310
+ throw new TypeError('Unknown result type');
311
+ }
312
+ };
313
+
314
+ JSONPath.prototype._handleCallback = function (fullRetObj, callback, type) {
315
+ if (callback) {
316
+ const preferredOutput = this._getPreferredOutput(fullRetObj);
317
+ fullRetObj.path = typeof fullRetObj.path === 'string'
318
+ ? fullRetObj.path
319
+ : JSONPath.toPathString(fullRetObj.path);
320
+ // eslint-disable-next-line n/callback-return -- No need to return
321
+ callback(preferredOutput, type, fullRetObj);
322
+ }
323
+ };
324
+
325
+ /**
326
+ *
327
+ * @param {string} expr
328
+ * @param {JSONObject} val
329
+ * @param {string} path
330
+ * @param {object|GenericArray} parent
331
+ * @param {string} parentPropName
332
+ * @param {JSONPathCallback} callback
333
+ * @param {boolean} hasArrExpr
334
+ * @param {boolean} literalPriority
335
+ * @returns {ReturnObject|ReturnObject[]}
336
+ */
337
+ JSONPath.prototype._trace = function (
338
+ expr, val, path, parent, parentPropName, callback, hasArrExpr,
339
+ literalPriority
340
+ ) {
341
+ // No expr to follow? return path and value as the result of
342
+ // this trace branch
343
+ let retObj;
344
+ if (!expr.length) {
345
+ retObj = {
346
+ path,
347
+ value: val,
348
+ parent,
349
+ parentProperty: parentPropName,
350
+ hasArrExpr
351
+ };
352
+ this._handleCallback(retObj, callback, 'value');
353
+ return retObj;
354
+ }
355
+
356
+ const loc = expr[0], x = expr.slice(1);
357
+
358
+ // We need to gather the return value of recursive trace calls in order to
359
+ // do the parent sel computation.
360
+ const ret = [];
361
+ /**
362
+ *
363
+ * @param {ReturnObject|ReturnObject[]} elems
364
+ * @returns {void}
365
+ */
366
+ function addRet (elems) {
367
+ if (Array.isArray(elems)) {
368
+ // This was causing excessive stack size in Node (with or
369
+ // without Babel) against our performance test:
370
+ // `ret.push(...elems);`
371
+ elems.forEach((t) => {
372
+ ret.push(t);
373
+ });
374
+ } else {
375
+ ret.push(elems);
376
+ }
377
+ }
378
+ if ((typeof loc !== 'string' || literalPriority) && val &&
379
+ Object.hasOwn(val, loc)
380
+ ) { // simple case--directly follow property
381
+ addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback,
382
+ hasArrExpr));
383
+ // eslint-disable-next-line unicorn/prefer-switch -- Part of larger `if`
384
+ } else if (loc === '*') { // all child properties
385
+ this._walk(val, (m) => {
386
+ addRet(this._trace(
387
+ x, val[m], push(path, m), val, m, callback, true, true
388
+ ));
389
+ });
390
+ } else if (loc === '..') { // all descendent parent properties
391
+ // Check remaining expression with val's immediate children
392
+ addRet(
393
+ this._trace(x, val, path, parent, parentPropName, callback,
394
+ hasArrExpr)
395
+ );
396
+ this._walk(val, (m) => {
397
+ // We don't join m and x here because we only want parents,
398
+ // not scalar values
399
+ if (typeof val[m] === 'object') {
400
+ // Keep going with recursive descent on val's
401
+ // object children
402
+ addRet(this._trace(
403
+ expr.slice(), val[m], push(path, m), val, m, callback, true
404
+ ));
405
+ }
406
+ });
407
+ // The parent sel computation is handled in the frame above using the
408
+ // ancestor object of val
409
+ } else if (loc === '^') {
410
+ // This is not a final endpoint, so we do not invoke the callback here
411
+ this._hasParentSelector = true;
412
+ return {
413
+ path: path.slice(0, -1),
414
+ expr: x,
415
+ isParentSelector: true
416
+ };
417
+ } else if (loc === '~') { // property name
418
+ retObj = {
419
+ path: push(path, loc),
420
+ value: parentPropName,
421
+ parent,
422
+ parentProperty: null
423
+ };
424
+ this._handleCallback(retObj, callback, 'property');
425
+ return retObj;
426
+ } else if (loc === '$') { // root only
427
+ addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
428
+ } else if ((/^(-?\d*):(-?\d*):?(\d*)$/u).test(loc)) { // [start:end:step] Python slice syntax
429
+ addRet(
430
+ this._slice(loc, x, val, path, parent, parentPropName, callback)
431
+ );
432
+ } else if (loc.indexOf('?(') === 0) { // [?(expr)] (filtering)
433
+ if (this.currEval === false) {
434
+ throw new Error('Eval [?(expr)] prevented in JSONPath expression.');
435
+ }
436
+ const safeLoc = loc.replace(/^\?\((.*?)\)$/u, '$1');
437
+ // check for a nested filter expression
438
+ const nested = (/@.?([^?]*)[['](\??\(.*?\))(?!.\)\])[\]']/gu).exec(safeLoc);
439
+ if (nested) {
440
+ // find if there are matches in the nested expression
441
+ // add them to the result set if there is at least one match
442
+ this._walk(val, (m) => {
443
+ const npath = [nested[2]];
444
+ const nvalue = nested[1]
445
+ ? val[m][nested[1]]
446
+ : val[m];
447
+ const filterResults = this._trace(npath, nvalue, path,
448
+ parent, parentPropName, callback, true);
449
+ if (filterResults.length > 0) {
450
+ addRet(this._trace(x, val[m], push(path, m), val,
451
+ m, callback, true));
452
+ }
453
+ });
454
+ } else {
455
+ this._walk(val, (m) => {
456
+ if (this._eval(safeLoc, val[m], m, path, parent,
457
+ parentPropName)) {
458
+ addRet(this._trace(x, val[m], push(path, m), val, m,
459
+ callback, true));
460
+ }
461
+ });
462
+ }
463
+ } else if (loc[0] === '(') { // [(expr)] (dynamic property/index)
464
+ if (this.currEval === false) {
465
+ throw new Error('Eval [(expr)] prevented in JSONPath expression.');
466
+ }
467
+ // As this will resolve to a property name (but we don't know it
468
+ // yet), property and parent information is relative to the
469
+ // parent of the property to which this expression will resolve
470
+ addRet(this._trace(unshift(
471
+ this._eval(
472
+ loc, val, path.at(-1),
473
+ path.slice(0, -1), parent, parentPropName
474
+ ),
475
+ x
476
+ ), val, path, parent, parentPropName, callback, hasArrExpr));
477
+ } else if (loc[0] === '@') { // value type: @boolean(), etc.
478
+ let addType = false;
479
+ const valueType = loc.slice(1, -2);
480
+ switch (valueType) {
481
+ case 'scalar':
482
+ if (!val || !(['object', 'function'].includes(typeof val))) {
483
+ addType = true;
484
+ }
485
+ break;
486
+ case 'boolean': case 'string': case 'undefined': case 'function':
487
+ if (typeof val === valueType) {
488
+ addType = true;
489
+ }
490
+ break;
491
+ case 'integer':
492
+ if (Number.isFinite(val) && !(val % 1)) {
493
+ addType = true;
494
+ }
495
+ break;
496
+ case 'number':
497
+ if (Number.isFinite(val)) {
498
+ addType = true;
499
+ }
500
+ break;
501
+ case 'nonFinite':
502
+ if (typeof val === 'number' && !Number.isFinite(val)) {
503
+ addType = true;
504
+ }
505
+ break;
506
+ case 'object':
507
+ if (val && typeof val === valueType) {
508
+ addType = true;
509
+ }
510
+ break;
511
+ case 'array':
512
+ if (Array.isArray(val)) {
513
+ addType = true;
514
+ }
515
+ break;
516
+ case 'other':
517
+ addType = this.currOtherTypeCallback(
518
+ val, path, parent, parentPropName
519
+ );
520
+ break;
521
+ case 'null':
522
+ if (val === null) {
523
+ addType = true;
524
+ }
525
+ break;
526
+ /* c8 ignore next 2 */
527
+ default:
528
+ throw new TypeError('Unknown value type ' + valueType);
529
+ }
530
+ if (addType) {
531
+ retObj = {path, value: val, parent, parentProperty: parentPropName};
532
+ this._handleCallback(retObj, callback, 'value');
533
+ return retObj;
534
+ }
535
+ // `-escaped property
536
+ } else if (loc[0] === '`' && val && Object.hasOwn(val, loc.slice(1))) {
537
+ const locProp = loc.slice(1);
538
+ addRet(this._trace(
539
+ x, val[locProp], push(path, locProp), val, locProp, callback,
540
+ hasArrExpr, true
541
+ ));
542
+ } else if (loc.includes(',')) { // [name1,name2,...]
543
+ const parts = loc.split(',');
544
+ for (const part of parts) {
545
+ addRet(this._trace(
546
+ unshift(part, x), val, path, parent, parentPropName, callback,
547
+ true
548
+ ));
549
+ }
550
+ // simple case--directly follow property
551
+ } else if (
552
+ !literalPriority && val && Object.hasOwn(val, loc)
553
+ ) {
554
+ addRet(
555
+ this._trace(x, val[loc], push(path, loc), val, loc, callback,
556
+ hasArrExpr, true)
557
+ );
558
+ }
559
+
560
+ // We check the resulting values for parent selections. For parent
561
+ // selections we discard the value object and continue the trace with the
562
+ // current val object
563
+ if (this._hasParentSelector) {
564
+ for (let t = 0; t < ret.length; t++) {
565
+ const rett = ret[t];
566
+ if (rett && rett.isParentSelector) {
567
+ const tmp = this._trace(
568
+ rett.expr, val, rett.path, parent, parentPropName, callback,
569
+ hasArrExpr
570
+ );
571
+ if (Array.isArray(tmp)) {
572
+ ret[t] = tmp[0];
573
+ const tl = tmp.length;
574
+ for (let tt = 1; tt < tl; tt++) {
575
+ // eslint-disable-next-line @stylistic/max-len -- Long
576
+ // eslint-disable-next-line sonarjs/updated-loop-counter -- Convenient
577
+ t++;
578
+ ret.splice(t, 0, tmp[tt]);
579
+ }
580
+ } else {
581
+ ret[t] = tmp;
582
+ }
583
+ }
584
+ }
585
+ }
586
+ return ret;
587
+ };
588
+
589
+ JSONPath.prototype._walk = function (val, f) {
590
+ if (Array.isArray(val)) {
591
+ const n = val.length;
592
+ for (let i = 0; i < n; i++) {
593
+ f(i);
594
+ }
595
+ } else if (val && typeof val === 'object') {
596
+ Object.keys(val).forEach((m) => {
597
+ f(m);
598
+ });
599
+ }
600
+ };
601
+
602
+ JSONPath.prototype._slice = function (
603
+ loc, expr, val, path, parent, parentPropName, callback
604
+ ) {
605
+ if (!Array.isArray(val)) {
606
+ return undefined;
607
+ }
608
+ const len = val.length, parts = loc.split(':'),
609
+ step = (parts[2] && Number.parseInt(parts[2])) || 1;
610
+ let start = (parts[0] && Number.parseInt(parts[0])) || 0,
611
+ end = (parts[1] && Number.parseInt(parts[1])) || len;
612
+ start = (start < 0) ? Math.max(0, start + len) : Math.min(len, start);
613
+ end = (end < 0) ? Math.max(0, end + len) : Math.min(len, end);
614
+ const ret = [];
615
+ for (let i = start; i < end; i += step) {
616
+ const tmp = this._trace(
617
+ unshift(i, expr), val, path, parent, parentPropName, callback, true
618
+ );
619
+ // Should only be possible to be an array here since first part of
620
+ // ``unshift(i, expr)` passed in above would not be empty, nor `~`,
621
+ // nor begin with `@` (as could return objects)
622
+ // This was causing excessive stack size in Node (with or
623
+ // without Babel) against our performance test: `ret.push(...tmp);`
624
+ tmp.forEach((t) => {
625
+ ret.push(t);
626
+ });
627
+ }
628
+ return ret;
629
+ };
630
+
631
+ JSONPath.prototype._eval = function (
632
+ code, _v, _vname, path, parent, parentPropName
633
+ ) {
634
+ this.currSandbox._$_parentProperty = parentPropName;
635
+ this.currSandbox._$_parent = parent;
636
+ this.currSandbox._$_property = _vname;
637
+ this.currSandbox._$_root = this.json;
638
+ this.currSandbox._$_v = _v;
639
+
640
+ const containsPath = code.includes('@path');
641
+ if (containsPath) {
642
+ this.currSandbox._$_path = JSONPath.toPathString(path.concat([_vname]));
643
+ }
644
+
645
+ const scriptCacheKey = this.currEval + 'Script:' + code;
646
+ if (!JSONPath.cache[scriptCacheKey]) {
647
+ let script = code
648
+ .replaceAll('@parentProperty', '_$_parentProperty')
649
+ .replaceAll('@parent', '_$_parent')
650
+ .replaceAll('@property', '_$_property')
651
+ .replaceAll('@root', '_$_root')
652
+ .replaceAll(/@([.\s)[])/gu, '_$_v$1');
653
+ if (containsPath) {
654
+ script = script.replaceAll('@path', '_$_path');
655
+ }
656
+ if (
657
+ this.currEval === 'safe' ||
658
+ this.currEval === true ||
659
+ this.currEval === undefined
660
+ ) {
661
+ JSONPath.cache[scriptCacheKey] = new this.safeVm.Script(script);
662
+ } else if (this.currEval === 'native') {
663
+ JSONPath.cache[scriptCacheKey] = new this.vm.Script(script);
664
+ } else if (
665
+ typeof this.currEval === 'function' &&
666
+ this.currEval.prototype &&
667
+ Object.hasOwn(this.currEval.prototype, 'runInNewContext')
668
+ ) {
669
+ const CurrEval = this.currEval;
670
+ JSONPath.cache[scriptCacheKey] = new CurrEval(script);
671
+ } else if (typeof this.currEval === 'function') {
672
+ JSONPath.cache[scriptCacheKey] = {
673
+ runInNewContext: (context) => this.currEval(script, context)
674
+ };
675
+ } else {
676
+ throw new TypeError(`Unknown "eval" property "${this.currEval}"`);
677
+ }
678
+ }
679
+
680
+ try {
681
+ return JSONPath.cache[scriptCacheKey].runInNewContext(this.currSandbox);
682
+ } catch (e) {
683
+ if (this.ignoreEvalErrors) {
684
+ return false;
685
+ }
686
+ throw new Error('jsonPath: ' + e.message + ': ' + code);
687
+ }
688
+ };
689
+
690
+ // PUBLIC CLASS PROPERTIES AND METHODS
691
+
692
+ // Could store the cache object itself
693
+ JSONPath.cache = {};
694
+
695
+ /**
696
+ * @param {string[]} pathArr Array to convert
697
+ * @returns {string} The path string
698
+ */
699
+ JSONPath.toPathString = function (pathArr) {
700
+ const x = pathArr, n = x.length;
701
+ let p = '$';
702
+ for (let i = 1; i < n; i++) {
703
+ if (!(/^(~|\^|@.*?\(\))$/u).test(x[i])) {
704
+ p += (/^[0-9*]+$/u).test(x[i]) ? ('[' + x[i] + ']') : ("['" + x[i] + "']");
705
+ }
706
+ }
707
+ return p;
708
+ };
709
+
710
+ /**
711
+ * @param {string} pointer JSON Path
712
+ * @returns {string} JSON Pointer
713
+ */
714
+ JSONPath.toPointer = function (pointer) {
715
+ const x = pointer, n = x.length;
716
+ let p = '';
717
+ for (let i = 1; i < n; i++) {
718
+ if (!(/^(~|\^|@.*?\(\))$/u).test(x[i])) {
719
+ p += '/' + x[i].toString()
720
+ .replaceAll('~', '~0')
721
+ .replaceAll('/', '~1');
722
+ }
723
+ }
724
+ return p;
725
+ };
726
+
727
+ /**
728
+ * @param {string} expr Expression to convert
729
+ * @returns {string[]}
730
+ */
731
+ JSONPath.toPathArray = function (expr) {
732
+ const {cache} = JSONPath;
733
+ if (cache[expr]) {
734
+ return cache[expr].concat();
735
+ }
736
+ const subx = [];
737
+ const normalized = expr
738
+ // Properties
739
+ .replaceAll(
740
+ /@(?:null|boolean|number|string|integer|undefined|nonFinite|scalar|array|object|function|other)\(\)/gu,
741
+ ';$&;'
742
+ )
743
+ // Parenthetical evaluations (filtering and otherwise), directly
744
+ // within brackets or single quotes
745
+ .replaceAll(/[['](\??\(.*?\))[\]'](?!.\])/gu, function ($0, $1) {
746
+ return '[#' + (subx.push($1) - 1) + ']';
747
+ })
748
+ // Escape periods and tildes within properties
749
+ .replaceAll(/\[['"]([^'\]]*)['"]\]/gu, function ($0, prop) {
750
+ return "['" + prop
751
+ .replaceAll('.', '%@%')
752
+ .replaceAll('~', '%%@@%%') +
753
+ "']";
754
+ })
755
+ // Properties operator
756
+ .replaceAll('~', ';~;')
757
+ // Split by property boundaries
758
+ .replaceAll(/['"]?\.['"]?(?![^[]*\])|\[['"]?/gu, ';')
759
+ // Reinsert periods within properties
760
+ .replaceAll('%@%', '.')
761
+ // Reinsert tildes within properties
762
+ .replaceAll('%%@@%%', '~')
763
+ // Parent
764
+ .replaceAll(/(?:;)?(\^+)(?:;)?/gu, function ($0, ups) {
765
+ return ';' + ups.split('').join(';') + ';';
766
+ })
767
+ // Descendents
768
+ .replaceAll(/;;;|;;/gu, ';..;')
769
+ // Remove trailing
770
+ .replaceAll(/;$|'?\]|'$/gu, '');
771
+
772
+ const exprList = normalized.split(';').map(function (exp) {
773
+ const match = exp.match(/#(\d+)/u);
774
+ return !match || !match[1] ? exp : subx[match[1]];
775
+ });
776
+ cache[expr] = exprList;
777
+ return cache[expr].concat();
778
+ };
779
+
780
+ JSONPath.prototype.safeVm = {
781
+ Script: SafeScript
782
+ };
783
+
784
+ export {JSONPath};