@jarenjs/json 0.9.2 → 0.34.0

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 (74) hide show
  1. package/ARCHITECTURE.md +86 -13
  2. package/README.md +248 -23
  3. package/dist/types/canonical.d.ts +37 -0
  4. package/dist/types/cow.d.ts +28 -0
  5. package/dist/types/errors.d.ts +45 -0
  6. package/dist/types/index.d.ts +3 -0
  7. package/dist/types/jslt/errors.d.ts +15 -8
  8. package/dist/types/jslt/index.d.ts +22 -0
  9. package/dist/types/jslt/packs/finance.d.ts +119 -0
  10. package/dist/types/jslt/packs/index.d.ts +310 -0
  11. package/dist/types/jslt/packs/math.d.ts +159 -0
  12. package/dist/types/jslt/packs/stats.d.ts +48 -0
  13. package/dist/types/jslt/registry.d.ts +65 -0
  14. package/dist/types/jtlt/errors.d.ts +3 -6
  15. package/dist/types/option-variants.d.ts +29 -0
  16. package/dist/types/patch.d.ts +214 -0
  17. package/dist/types/path.d.ts +139 -9
  18. package/dist/types/pointer.d.ts +100 -9
  19. package/dist/types/query/compile.d.ts +12 -0
  20. package/dist/types/query/errors.d.ts +72 -8
  21. package/dist/types/query/index.d.ts +317 -25
  22. package/dist/types/query/normalize.d.ts +24 -0
  23. package/dist/types/query/operators.d.ts +241 -1
  24. package/dist/types/query/runtime.d.ts +5 -8
  25. package/dist/types/query/types.d.ts +34 -0
  26. package/dist/types/segments.d.ts +31 -0
  27. package/dist/types/write.d.ts +204 -0
  28. package/dist/types/xquery/parse.d.ts +2 -3
  29. package/docs/JSLT-FORMAT.md +74 -3
  30. package/docs/JSLT-PRELUDE.md +1 -1
  31. package/docs/QUERY-FORMAT.md +695 -33
  32. package/package.json +18 -4
  33. package/schemas/geojson.draft-07.schema.json +323 -0
  34. package/schemas/geojson.jaren.schema.json +863 -0
  35. package/schemas/geojson.schema.json +172 -0
  36. package/schemas/jaren-jslt.authoring.schema.json +142 -0
  37. package/schemas/jaren-jslt.draft-07.schema.json +152 -11
  38. package/schemas/jaren-jslt.llm-profile.schema.json +782 -0
  39. package/schemas/jaren-jslt.schema.json +152 -11
  40. package/schemas/jaren-query.draft-07.schema.json +152 -11
  41. package/schemas/jaren-query.llm-profile.schema.json +619 -0
  42. package/schemas/jaren-query.schema.json +82 -15
  43. package/src/basic.js +1 -1
  44. package/src/canonical.js +170 -0
  45. package/src/cow.js +106 -0
  46. package/src/errors.js +68 -0
  47. package/src/index.js +3 -0
  48. package/src/jslt/dispatch.js +178 -28
  49. package/src/jslt/errors.js +19 -14
  50. package/src/jslt/index.js +37 -29
  51. package/src/jslt/packs/finance.js +49 -0
  52. package/src/jslt/packs/index.js +18 -0
  53. package/src/jslt/packs/math.js +46 -0
  54. package/src/jslt/packs/stats.js +65 -0
  55. package/src/jslt/registry.js +200 -0
  56. package/src/jslt/stylesheet.js +14 -23
  57. package/src/jtlt/desugar.js +2 -3
  58. package/src/jtlt/errors.js +6 -12
  59. package/src/jtlt/index.js +12 -29
  60. package/src/jtlt/template.js +9 -18
  61. package/src/option-variants.js +54 -0
  62. package/src/patch.js +1052 -0
  63. package/src/path.js +319 -52
  64. package/src/pointer.js +225 -44
  65. package/src/query/compile.js +790 -75
  66. package/src/query/errors.js +72 -12
  67. package/src/query/index.js +274 -42
  68. package/src/query/normalize.js +489 -78
  69. package/src/query/operators.js +620 -23
  70. package/src/query/runtime.js +5 -19
  71. package/src/query/types.js +213 -0
  72. package/src/segments.js +409 -64
  73. package/src/write.js +660 -0
  74. package/src/xquery/parse.js +37 -53
@@ -52,11 +52,15 @@ import {
52
52
  CC_AT,
53
53
  CC_LBRACKET,
54
54
  CC_RBRACKET,
55
- CC_UNDERSCORE,
56
55
  CC_PIPE,
57
56
  isDigitCode,
57
+ isNameStartCode,
58
+ isNameCharCode,
58
59
  } from '@jarenjs/core/scan';
59
60
 
61
+ import { setObjectMember } from '@jarenjs/core/object';
62
+ import { LabeledSyntaxError } from '../errors.js';
63
+
60
64
  const CC_HASH = 0x23;
61
65
  const CC_PERCENT = 0x25;
62
66
  const CC_PLUS = 0x2B;
@@ -73,12 +77,9 @@ const hasOwn = Object.hasOwn;
73
77
  * subset (mirrors JSONPathSyntaxError: `source` and `position` locate the
74
78
  * offending token).
75
79
  */
76
- export class XQuerySyntaxError extends SyntaxError {
80
+ export class XQuerySyntaxError extends LabeledSyntaxError {
77
81
  constructor(message, source, position) {
78
- super(`Invalid XQuery: ${message} at position ${position} in '${source}'`);
79
- this.name = 'XQuerySyntaxError';
80
- this.source = source;
81
- this.position = position;
82
+ super('XQuerySyntaxError', 'XQuery', message, source, position);
82
83
  }
83
84
  }
84
85
 
@@ -215,16 +216,6 @@ function emitString(s) {
215
216
  return s.charCodeAt(0) === CC_DOLLAR ? '$' + s : s;
216
217
  }
217
218
 
218
- // own-property assignment for emitted objects keyed by user-controlled
219
- // names: a plain `obj[name] =` would follow the prototype chain for
220
- // '__proto__' and silently drop the member
221
- function setMember(obj, name, value) {
222
- if (name === '__proto__')
223
- Object.defineProperty(obj, name, { value, enumerable: true, writable: true, configurable: true });
224
- else
225
- obj[name] = value;
226
- }
227
-
228
219
  // member names foldable into RFC 9535 dot shorthand; everything else
229
220
  // (NCNames with '-', '.', or non-ASCII) uses the bracketed name selector.
230
221
  // NCNames can never contain a quote or backslash, so no escaping needed.
@@ -245,16 +236,9 @@ function isEmptySeqExpr(e) {
245
236
 
246
237
  //#region parser
247
238
 
248
- function isNameFirstCode(c) {
249
- return (c >= 0x41 && c <= 0x5A) // A-Z
250
- || (c >= 0x61 && c <= 0x7A) // a-z
251
- || c === CC_UNDERSCORE
252
- || c >= 0x80; // any non-ASCII code unit
253
- }
254
-
255
239
  // XML NameChar, pragmatically: name start, digits, '-' and '.'
256
- function isNameCharCode(c) {
257
- return isNameFirstCode(c) || isDigitCode(c) || c === CC_MINUS || c === CC_DOT;
240
+ function isXmlNameCharCode(c) {
241
+ return isNameCharCode(c) || c === CC_MINUS || c === CC_DOT;
258
242
  }
259
243
 
260
244
  /**
@@ -320,7 +304,7 @@ export function parseXQuery(source) {
320
304
 
321
305
  function parseNCName() {
322
306
  const start = pos;
323
- if (!isNameFirstCode(cc(pos)))
307
+ if (!isNameStartCode(cc(pos)))
324
308
  fail('expected a name');
325
309
  while (pos < len) {
326
310
  const c = source.charCodeAt(pos);
@@ -332,7 +316,7 @@ export function parseXQuery(source) {
332
316
  pos += 2;
333
317
  continue;
334
318
  }
335
- if (!isNameCharCode(c))
319
+ if (!isXmlNameCharCode(c))
336
320
  break;
337
321
  pos++;
338
322
  }
@@ -344,7 +328,7 @@ export function parseXQuery(source) {
344
328
  function tryKeyword(word) {
345
329
  const save = pos;
346
330
  skipWS();
347
- if (isNameFirstCode(cc(pos))) {
331
+ if (isNameStartCode(cc(pos))) {
348
332
  const at = pos;
349
333
  if (parseNCName() === word)
350
334
  return at;
@@ -356,7 +340,7 @@ export function parseXQuery(source) {
356
340
  function expectKeyword(word) {
357
341
  skipWS();
358
342
  const at = pos;
359
- if (!isNameFirstCode(cc(pos)) || parseNCName() !== word)
343
+ if (!isNameStartCode(cc(pos)) || parseNCName() !== word)
360
344
  fail(`expected '${word}'`, at);
361
345
  }
362
346
 
@@ -371,7 +355,7 @@ export function parseXQuery(source) {
371
355
  const name = parseNCName();
372
356
  if (name === 'Q' && cc(pos) === CC_LBRACE)
373
357
  fail("unsupported construct 'URI-qualified name'", at);
374
- if (cc(pos) === CC_COLON && isNameFirstCode(cc(pos + 1)))
358
+ if (cc(pos) === CC_COLON && isNameStartCode(cc(pos + 1)))
375
359
  fail("unsupported construct 'namespaced variable'", at);
376
360
  if (!VAR_NAME_RE.test(name))
377
361
  fail(`unsupported variable name '${name}'`, at);
@@ -446,7 +430,7 @@ export function parseXQuery(source) {
446
430
  // XQuery A.2.2: a numeric literal must not be followed directly by
447
431
  // '.' or a name start character (e.g. `10div 3` is not `10 div 3`)
448
432
  const n = cc(pos);
449
- if (n === CC_DOT || isNameFirstCode(n))
433
+ if (n === CC_DOT || isNameStartCode(n))
450
434
  fail('a numeric literal must be followed by a delimiter');
451
435
  const value = Number(source.slice(start, pos));
452
436
  // an overflowing DoubleLiteral is a valid XQuery double (INF) but has
@@ -481,7 +465,7 @@ export function parseXQuery(source) {
481
465
  function parseExprSingle() {
482
466
  skipWS();
483
467
  const at = pos;
484
- if (isNameFirstCode(cc(pos))) {
468
+ if (isNameStartCode(cc(pos))) {
485
469
  const save = pos;
486
470
  const ident = parseNCName();
487
471
  skipWS();
@@ -489,7 +473,7 @@ export function parseXQuery(source) {
489
473
  if (ident === 'for' || ident === 'let') {
490
474
  if (next === CC_DOLLAR)
491
475
  return parseFlwor(ident);
492
- if (ident === 'for' && isNameFirstCode(next)) {
476
+ if (ident === 'for' && isNameStartCode(next)) {
493
477
  const save2 = pos;
494
478
  const w = parseNCName();
495
479
  pos = save2;
@@ -520,7 +504,7 @@ export function parseXQuery(source) {
520
504
  for (;;) {
521
505
  const save = pos;
522
506
  skipWS();
523
- if (isNameFirstCode(cc(pos)) && parseNCName() === 'or') {
507
+ if (isNameStartCode(cc(pos)) && parseNCName() === 'or') {
524
508
  if (items === null)
525
509
  items = [first];
526
510
  items.push(parseAnd());
@@ -537,7 +521,7 @@ export function parseXQuery(source) {
537
521
  for (;;) {
538
522
  const save = pos;
539
523
  skipWS();
540
- if (isNameFirstCode(cc(pos)) && parseNCName() === 'and') {
524
+ if (isNameStartCode(cc(pos)) && parseNCName() === 'and') {
541
525
  if (items === null)
542
526
  items = [first];
543
527
  items.push(parseComparison());
@@ -594,7 +578,7 @@ export function parseXQuery(source) {
594
578
  op = '$gt';
595
579
  }
596
580
  }
597
- else if (isNameFirstCode(c)) {
581
+ else if (isNameStartCode(c)) {
598
582
  const ident = parseNCName();
599
583
  if (hasOwn(VALUE_COMPS, ident))
600
584
  op = VALUE_COMPS[ident];
@@ -641,7 +625,7 @@ export function parseXQuery(source) {
641
625
  const first = parseAdditive();
642
626
  const save = pos;
643
627
  skipWS();
644
- if (isNameFirstCode(cc(pos)) && parseNCName() === 'to')
628
+ if (isNameStartCode(cc(pos)) && parseNCName() === 'to')
645
629
  return { '$range': [first, parseAdditive()] };
646
630
  pos = save;
647
631
  return first;
@@ -684,7 +668,7 @@ export function parseXQuery(source) {
684
668
  expr = { '$mul': [expr, parseUnary()] };
685
669
  continue;
686
670
  }
687
- if (isNameFirstCode(c)) {
671
+ if (isNameStartCode(c)) {
688
672
  const ident = parseNCName();
689
673
  if (ident === 'div') {
690
674
  expr = { '$div': [expr, parseUnary()] };
@@ -763,7 +747,7 @@ export function parseXQuery(source) {
763
747
  }
764
748
  if (isDigitCode(c))
765
749
  return { index: parseLookupIndex() };
766
- if (isNameFirstCode(c))
750
+ if (isNameStartCode(c))
767
751
  return { name: parseNCName() };
768
752
  if (c === CC_LPAREN)
769
753
  fail("unsupported construct 'parenthesized lookup key'");
@@ -774,7 +758,7 @@ export function parseXQuery(source) {
774
758
  const at = pos;
775
759
  while (isDigitCode(cc(pos)))
776
760
  pos++;
777
- if (cc(pos) === CC_DOT || isNameFirstCode(cc(pos)))
761
+ if (cc(pos) === CC_DOT || isNameStartCode(cc(pos)))
778
762
  fail('expected an integer lookup key', at);
779
763
  const n = Number(source.slice(at, pos));
780
764
  if (!Number.isSafeInteger(n))
@@ -867,7 +851,7 @@ export function parseXQuery(source) {
867
851
  fail("unsupported construct 'node constructor'", at);
868
852
  if (c === CC_BACKTICK)
869
853
  fail("unsupported construct 'string constructor'", at);
870
- if (isNameFirstCode(c))
854
+ if (isNameStartCode(c))
871
855
  return parseNamedPrimary(at);
872
856
  return fail('expected an expression');
873
857
  }
@@ -1008,7 +992,7 @@ export function parseXQuery(source) {
1008
992
  if (plain) {
1009
993
  const out = {};
1010
994
  for (let i = 0; i < keys.length; i++)
1011
- setMember(out, keys[i], values[i]);
995
+ setObjectMember(out, keys[i], values[i]);
1012
996
  return out;
1013
997
  }
1014
998
  const pairs = new Array(keys.length);
@@ -1021,7 +1005,7 @@ export function parseXQuery(source) {
1021
1005
  let name = parseNCName();
1022
1006
  let written = name;
1023
1007
  let prefix = null;
1024
- if (cc(pos) === CC_COLON && isNameFirstCode(cc(pos + 1))) {
1008
+ if (cc(pos) === CC_COLON && isNameStartCode(cc(pos + 1))) {
1025
1009
  pos++;
1026
1010
  prefix = name;
1027
1011
  name = parseNCName();
@@ -1169,7 +1153,7 @@ export function parseXQuery(source) {
1169
1153
  groups.push(group);
1170
1154
  group = {};
1171
1155
  }
1172
- setMember(group, name, bindings[i][1]);
1156
+ setObjectMember(group, name, bindings[i][1]);
1173
1157
  }
1174
1158
  groups.push(group);
1175
1159
  let out = cond;
@@ -1198,7 +1182,7 @@ export function parseXQuery(source) {
1198
1182
  for (;;) {
1199
1183
  skipWS();
1200
1184
  const at = pos;
1201
- if (!isNameFirstCode(cc(pos)))
1185
+ if (!isNameStartCode(cc(pos)))
1202
1186
  fail('expected a FLWOR clause');
1203
1187
  const kw = parseNCName();
1204
1188
  if (kw === 'for' || kw === 'let') {
@@ -1244,7 +1228,7 @@ export function parseXQuery(source) {
1244
1228
  skipWS();
1245
1229
  if (cc(pos) === CC_DOLLAR)
1246
1230
  return;
1247
- if (kw === 'for' && isNameFirstCode(cc(pos))) {
1231
+ if (kw === 'for' && isNameStartCode(cc(pos))) {
1248
1232
  const save = pos;
1249
1233
  const w = parseNCName();
1250
1234
  pos = save;
@@ -1444,7 +1428,7 @@ export function parseXQuery(source) {
1444
1428
  if (c.kind === 'for') {
1445
1429
  if (forObj === null)
1446
1430
  forObj = {};
1447
- setMember(forObj, c.name, c.atName === null ? c.expr : { '$in': c.expr, '$at': c.atName });
1431
+ setObjectMember(forObj, c.name, c.atName === null ? c.expr : { '$in': c.expr, '$at': c.atName });
1448
1432
  names.add(c.name);
1449
1433
  if (c.atName !== null)
1450
1434
  names.add(c.atName);
@@ -1453,7 +1437,7 @@ export function parseXQuery(source) {
1453
1437
  else {
1454
1438
  if (letObj === null)
1455
1439
  letObj = {};
1456
- setMember(letObj, c.name, c.expr);
1440
+ setObjectMember(letObj, c.name, c.expr);
1457
1441
  names.add(c.name);
1458
1442
  }
1459
1443
  lastSlot = slot;
@@ -1477,7 +1461,7 @@ export function parseXQuery(source) {
1477
1461
  fail(`duplicate variable '$${g.name}'`, g.at);
1478
1462
  if (names.has(g.name))
1479
1463
  fail(`unsupported construct 'group by' rebinding variable '$${g.name}'`, g.at);
1480
- setMember(groupObj, g.name, g.expr);
1464
+ setObjectMember(groupObj, g.name, g.expr);
1481
1465
  }
1482
1466
  for (let k = 0; k < c.keys.length; k++)
1483
1467
  names.add(c.keys[k].name);
@@ -1533,7 +1517,7 @@ export function parseXQuery(source) {
1533
1517
  if (tryKeyword('xquery') < 0)
1534
1518
  return;
1535
1519
  skipWS();
1536
- if (!isNameFirstCode(cc(pos))) {
1520
+ if (!isNameStartCode(cc(pos))) {
1537
1521
  pos = save;
1538
1522
  return;
1539
1523
  }
@@ -1598,7 +1582,7 @@ export function parseXQuery(source) {
1598
1582
  const save = pos;
1599
1583
  skipWS();
1600
1584
  const at = pos;
1601
- if (!isNameFirstCode(cc(pos))) {
1585
+ if (!isNameStartCode(cc(pos))) {
1602
1586
  pos = save;
1603
1587
  return;
1604
1588
  }
@@ -1607,7 +1591,7 @@ export function parseXQuery(source) {
1607
1591
  skipWS();
1608
1592
  if (cc(pos) === CC_PERCENT)
1609
1593
  fail("unsupported construct 'annotation'");
1610
- if (!isNameFirstCode(cc(pos)))
1594
+ if (!isNameStartCode(cc(pos)))
1611
1595
  fail('expected a declaration keyword');
1612
1596
  const kind = parseNCName();
1613
1597
  if (kind === 'variable') {
@@ -1618,7 +1602,7 @@ export function parseXQuery(source) {
1618
1602
  }
1619
1603
  if (w === 'import') {
1620
1604
  skipWS();
1621
- const kind = isNameFirstCode(cc(pos)) ? parseNCName() : 'declaration';
1605
+ const kind = isNameStartCode(cc(pos)) ? parseNCName() : 'declaration';
1622
1606
  fail(`unsupported construct 'import ${kind}'`, at);
1623
1607
  }
1624
1608
  if (w === 'module')