@jarenjs/json 0.9.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 (57) hide show
  1. package/ARCHITECTURE.md +175 -0
  2. package/LICENSE +21 -0
  3. package/README.md +471 -0
  4. package/dist/types/basic.d.ts +32 -0
  5. package/dist/types/index.d.ts +4 -0
  6. package/dist/types/jslt/dispatch.d.ts +11 -0
  7. package/dist/types/jslt/errors.d.ts +18 -0
  8. package/dist/types/jslt/index.d.ts +53 -0
  9. package/dist/types/jslt/stylesheet.d.ts +8 -0
  10. package/dist/types/jtlt/desugar.d.ts +19 -0
  11. package/dist/types/jtlt/errors.d.ts +18 -0
  12. package/dist/types/jtlt/index.d.ts +57 -0
  13. package/dist/types/jtlt/template.d.ts +8 -0
  14. package/dist/types/jtlt/writer.d.ts +6 -0
  15. package/dist/types/path.d.ts +235 -0
  16. package/dist/types/pointer.d.ts +114 -0
  17. package/dist/types/query/compile.d.ts +21 -0
  18. package/dist/types/query/errors.d.ts +18 -0
  19. package/dist/types/query/index.d.ts +70 -0
  20. package/dist/types/query/normalize.d.ts +68 -0
  21. package/dist/types/query/operators.d.ts +424 -0
  22. package/dist/types/query/runtime.d.ts +93 -0
  23. package/dist/types/segments.d.ts +62 -0
  24. package/dist/types/xquery/index.d.ts +19 -0
  25. package/dist/types/xquery/parse.d.ts +20 -0
  26. package/docs/JSLT-FORMAT.md +861 -0
  27. package/docs/JSLT-PRELUDE.md +159 -0
  28. package/docs/JTLT-FORMAT.md +659 -0
  29. package/docs/QUERY-FORMAT.md +1221 -0
  30. package/docs/XQUERY-FRONTEND.md +321 -0
  31. package/package.json +81 -0
  32. package/schemas/jaren-jslt.draft-07.schema.json +776 -0
  33. package/schemas/jaren-jslt.schema.json +776 -0
  34. package/schemas/jaren-query.draft-07.schema.json +613 -0
  35. package/schemas/jaren-query.schema.json +375 -0
  36. package/src/basic.js +300 -0
  37. package/src/index.js +4 -0
  38. package/src/jslt/dispatch.js +934 -0
  39. package/src/jslt/errors.js +34 -0
  40. package/src/jslt/index.js +121 -0
  41. package/src/jslt/stylesheet.js +234 -0
  42. package/src/jtlt/desugar.js +231 -0
  43. package/src/jtlt/errors.js +34 -0
  44. package/src/jtlt/index.js +155 -0
  45. package/src/jtlt/template.js +130 -0
  46. package/src/jtlt/writer.js +110 -0
  47. package/src/path.js +977 -0
  48. package/src/pointer.js +453 -0
  49. package/src/query/compile.js +817 -0
  50. package/src/query/errors.js +33 -0
  51. package/src/query/index.js +150 -0
  52. package/src/query/normalize.js +1047 -0
  53. package/src/query/operators.js +1253 -0
  54. package/src/query/runtime.js +233 -0
  55. package/src/segments.js +627 -0
  56. package/src/xquery/index.js +35 -0
  57. package/src/xquery/parse.js +1647 -0
@@ -0,0 +1,776 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://jarenjs.dev/schemas/jaren-jslt/0.1/draft-07",
4
+ "title": "Jaren JSLT format 0.1",
5
+ "description": "Structural grammar of Jaren JSLT stylesheet documents (see packages/json/docs/JSLT-FORMAT.md). Rule bodies mechanically reuse the committed Jaren JSON Query grammar plus the body-local $apply phrase; the query schema itself is unchanged. This schema enforces document shapes, closed vocabularies, path syntax when format assertion is enabled, and structurally expressible body rules. The compiler remains authoritative for JT0xxx rules JSON Schema cannot express: conflict-rank semantics, reserved root/path externals, compileTypeTest hook requirements, schema-literal compilation, and the literal-string second position of a two-item $apply argument list. Authored in a draft-neutral keyword subset; the draft-07 twin is a mechanical derivation.",
6
+ "allOf": [
7
+ {
8
+ "$ref": "#/definitions/stylesheetDocument"
9
+ }
10
+ ],
11
+ "definitions": {
12
+ "stylesheetDocument": {
13
+ "description": "A JSLT stylesheet is either a bare array of rules or the versioned envelope object.",
14
+ "oneOf": [
15
+ {
16
+ "type": "array",
17
+ "items": {
18
+ "$ref": "#/definitions/rule"
19
+ }
20
+ },
21
+ {
22
+ "$ref": "#/definitions/stylesheetEnvelope"
23
+ }
24
+ ]
25
+ },
26
+ "stylesheetEnvelope": {
27
+ "description": "Versioned stylesheet envelope. Unknown members are rejected; per-mode declarations only override unmatched disposition.",
28
+ "type": "object",
29
+ "properties": {
30
+ "$jslt": {
31
+ "const": "0.1"
32
+ },
33
+ "rules": {
34
+ "type": "array",
35
+ "items": {
36
+ "$ref": "#/definitions/rule"
37
+ }
38
+ },
39
+ "unmatched": {
40
+ "$ref": "#/definitions/dispositionValue"
41
+ },
42
+ "modes": {
43
+ "$ref": "#/definitions/modesMap"
44
+ }
45
+ },
46
+ "required": [
47
+ "$jslt",
48
+ "rules"
49
+ ],
50
+ "additionalProperties": false
51
+ },
52
+ "rule": {
53
+ "description": "One closed template rule. The compiler is authoritative for rank ordering, reserved external bindings, hook availability, and body runtime semantics (JT0xxx/JT2xxx).",
54
+ "type": "object",
55
+ "properties": {
56
+ "match": {
57
+ "$ref": "#/definitions/matchSpec"
58
+ },
59
+ "mode": {
60
+ "type": "string"
61
+ },
62
+ "priority": {
63
+ "type": "number"
64
+ },
65
+ "body": {
66
+ "$ref": "#/definitions/queryDocument"
67
+ }
68
+ },
69
+ "required": [
70
+ "body"
71
+ ],
72
+ "additionalProperties": false
73
+ },
74
+ "matchSpec": {
75
+ "description": "A positional RFC 9535 JSONPath match, a shape match using an annotation-only JSON Schema literal, or both conditions in one closed object.",
76
+ "oneOf": [
77
+ {
78
+ "type": "string",
79
+ "format": "json-path"
80
+ },
81
+ {
82
+ "type": "object",
83
+ "properties": {
84
+ "path": {
85
+ "type": "string",
86
+ "format": "json-path"
87
+ },
88
+ "schema": {
89
+ "$ref": "#/definitions/schemaLiteral"
90
+ }
91
+ },
92
+ "anyOf": [
93
+ {
94
+ "required": [
95
+ "path"
96
+ ]
97
+ },
98
+ {
99
+ "required": [
100
+ "schema"
101
+ ]
102
+ }
103
+ ],
104
+ "additionalProperties": false
105
+ }
106
+ ]
107
+ },
108
+ "dispositionValue": {
109
+ "description": "Built-in behavior for unmatched values: share unchanged subtrees, rebuild fresh containers, or raise JT2003.",
110
+ "enum": [
111
+ "share",
112
+ "fresh",
113
+ "error"
114
+ ]
115
+ },
116
+ "modesMap": {
117
+ "description": "Mode name to unmatched-disposition override. Modes need not otherwise be declared.",
118
+ "type": "object",
119
+ "additionalProperties": {
120
+ "$ref": "#/definitions/modeConfig"
121
+ }
122
+ },
123
+ "modeConfig": {
124
+ "type": "object",
125
+ "properties": {
126
+ "unmatched": {
127
+ "$ref": "#/definitions/dispositionValue"
128
+ }
129
+ },
130
+ "required": [
131
+ "unmatched"
132
+ ],
133
+ "additionalProperties": false
134
+ },
135
+ "queryDocument": {
136
+ "description": "A query document is either the version envelope or a bare expression (a bare RFC 9535 JSONPath string is the degenerate query).",
137
+ "oneOf": [
138
+ {
139
+ "$ref": "#/definitions/versionEnvelope"
140
+ },
141
+ {
142
+ "$ref": "#/definitions/expression"
143
+ }
144
+ ]
145
+ },
146
+ "versionEnvelope": {
147
+ "description": "Top-level version envelope. Only recognized at the top level of a query document.",
148
+ "type": "object",
149
+ "properties": {
150
+ "$query": {
151
+ "const": "0.1"
152
+ },
153
+ "$expr": {
154
+ "$ref": "#/definitions/expression"
155
+ }
156
+ },
157
+ "required": [
158
+ "$query",
159
+ "$expr"
160
+ ],
161
+ "additionalProperties": false
162
+ },
163
+ "expression": {
164
+ "description": "Any expression per the encoding rules: scalars are literals, strings split on the leading '$', arrays are array constructors, objects partition into map constructors (no $-prefixed key) and operator phrases (all keys $-prefixed).",
165
+ "oneOf": [
166
+ {
167
+ "$ref": "#/definitions/scalarLiteral"
168
+ },
169
+ {
170
+ "$ref": "#/definitions/stringExpression"
171
+ },
172
+ {
173
+ "$ref": "#/definitions/arrayConstructor"
174
+ },
175
+ {
176
+ "$ref": "#/definitions/objectExpression"
177
+ }
178
+ ]
179
+ },
180
+ "scalarLiteral": {
181
+ "description": "Numbers, booleans and null are literal items.",
182
+ "type": [
183
+ "null",
184
+ "boolean",
185
+ "number"
186
+ ]
187
+ },
188
+ "stringExpression": {
189
+ "description": "Rule 2: a string starting with '$' is a query expression ('$$' escapes a literal); any other string is a literal.",
190
+ "type": "string",
191
+ "anyOf": [
192
+ {
193
+ "$ref": "#/definitions/literalString"
194
+ },
195
+ {
196
+ "$ref": "#/definitions/escapedStringLiteral"
197
+ },
198
+ {
199
+ "$ref": "#/definitions/absolutePathString"
200
+ },
201
+ {
202
+ "$ref": "#/definitions/variablePathString"
203
+ }
204
+ ]
205
+ },
206
+ "literalString": {
207
+ "description": "A string that does not start with '$' denotes itself.",
208
+ "type": "string",
209
+ "pattern": "^([^$]|$)"
210
+ },
211
+ "escapedStringLiteral": {
212
+ "description": "A string starting with '$$' denotes the literal string with one leading '$' dropped.",
213
+ "type": "string",
214
+ "pattern": "^\\$\\$"
215
+ },
216
+ "absolutePathString": {
217
+ "description": "An absolute RFC 9535 JSONPath query rooted at the input document: '$' alone or starting '$.', '$[' or '$..'. The json-path format asserts the full RFC 9535 grammar where format assertion is enabled (format is annotation-only by default from draft 2020-12).",
218
+ "type": "string",
219
+ "pattern": "^\\$($|[.\\[])",
220
+ "format": "json-path"
221
+ },
222
+ "variablePathString": {
223
+ "description": "A variable-rooted path: '$name' with name matching [A-Za-z_][A-Za-z0-9_]*, optionally followed by RFC 9535 segments. Only the head is pattern-checked; the full segment grammar is enforced by the compiler (JQ0004).",
224
+ "type": "string",
225
+ "pattern": "^\\$[A-Za-z_][A-Za-z0-9_]*($|[.\\[])"
226
+ },
227
+ "arrayConstructor": {
228
+ "description": "An array in expression position constructs an array; element results are concatenated per XQuery sequence flattening.",
229
+ "type": "array",
230
+ "items": {
231
+ "$ref": "#/definitions/expression"
232
+ }
233
+ },
234
+ "objectExpression": {
235
+ "description": "Rule 1: objects partition by $-prefixed keys. A mixed object matches neither branch and is invalid (JQ0001).",
236
+ "oneOf": [
237
+ {
238
+ "$ref": "#/definitions/mapConstructor"
239
+ },
240
+ {
241
+ "$ref": "#/definitions/constPhrase"
242
+ },
243
+ {
244
+ "$ref": "#/definitions/mapPhrase"
245
+ },
246
+ {
247
+ "$ref": "#/definitions/flworPhrase"
248
+ },
249
+ {
250
+ "$ref": "#/definitions/somePhrase"
251
+ },
252
+ {
253
+ "$ref": "#/definitions/everyPhrase"
254
+ },
255
+ {
256
+ "$ref": "#/definitions/unaryOperatorPhrase"
257
+ },
258
+ {
259
+ "$ref": "#/definitions/binaryOperatorPhrase"
260
+ },
261
+ {
262
+ "$ref": "#/definitions/variadicOperatorPhrase"
263
+ },
264
+ {
265
+ "$ref": "#/definitions/nonEmptyVariadicOperatorPhrase"
266
+ },
267
+ {
268
+ "$ref": "#/definitions/conditionalArityOperatorPhrase"
269
+ },
270
+ {
271
+ "$ref": "#/definitions/stringJoinPhrase"
272
+ },
273
+ {
274
+ "$ref": "#/definitions/replacePhrase"
275
+ },
276
+ {
277
+ "$ref": "#/definitions/schemaOperatorPhrase"
278
+ },
279
+ {
280
+ "$ref": "#/definitions/applyPhrase"
281
+ }
282
+ ]
283
+ },
284
+ "mapConstructor": {
285
+ "description": "An object with no $-prefixed key: keys are literal member names, values are expressions. Use $map or $const for member names that start with '$'.",
286
+ "type": "object",
287
+ "patternProperties": {
288
+ "^\\$": false
289
+ },
290
+ "additionalProperties": {
291
+ "$ref": "#/definitions/expression"
292
+ }
293
+ },
294
+ "constPhrase": {
295
+ "description": "Quote: the value is returned verbatim, nothing inside is evaluated.",
296
+ "type": "object",
297
+ "properties": {
298
+ "$const": true
299
+ },
300
+ "required": [
301
+ "$const"
302
+ ],
303
+ "additionalProperties": false
304
+ },
305
+ "mapPhrase": {
306
+ "description": "General map constructor for computed keys or keys starting with '$'. Each entry is a [keyExpr, valueExpr] pair; keyExpr must evaluate to a single string at runtime (JQ2004); later pairs win on duplicate keys.",
307
+ "type": "object",
308
+ "properties": {
309
+ "$map": {
310
+ "type": "array",
311
+ "items": {
312
+ "$ref": "#/definitions/mapEntry"
313
+ }
314
+ }
315
+ },
316
+ "required": [
317
+ "$map"
318
+ ],
319
+ "additionalProperties": false
320
+ },
321
+ "mapEntry": {
322
+ "description": "One [keyExpr, valueExpr] pair of a $map phrase.",
323
+ "type": "array",
324
+ "items": {
325
+ "$ref": "#/definitions/expression"
326
+ },
327
+ "minItems": 2,
328
+ "maxItems": 2
329
+ },
330
+ "flworPhrase": {
331
+ "description": "FLWOR phrase. Clauses apply in the fixed semantic order $for, $let, $as, $where, $groupby, $orderby, $count, $return regardless of JSON key order (D7); interleavings are expressed by nesting phrases. $return is required, plus at least one of $for/$let.",
332
+ "type": "object",
333
+ "properties": {
334
+ "$for": {
335
+ "$ref": "#/definitions/forBindings"
336
+ },
337
+ "$let": {
338
+ "$ref": "#/definitions/bindingMap"
339
+ },
340
+ "$as": {
341
+ "$ref": "#/definitions/asClause"
342
+ },
343
+ "$where": {
344
+ "$ref": "#/definitions/expression"
345
+ },
346
+ "$groupby": {
347
+ "$ref": "#/definitions/bindingMap"
348
+ },
349
+ "$orderby": {
350
+ "$ref": "#/definitions/orderBySpec"
351
+ },
352
+ "$count": {
353
+ "$ref": "#/definitions/variableName"
354
+ },
355
+ "$return": {
356
+ "$ref": "#/definitions/expression"
357
+ }
358
+ },
359
+ "required": [
360
+ "$return"
361
+ ],
362
+ "anyOf": [
363
+ {
364
+ "required": [
365
+ "$for"
366
+ ]
367
+ },
368
+ {
369
+ "required": [
370
+ "$let"
371
+ ]
372
+ }
373
+ ],
374
+ "additionalProperties": false
375
+ },
376
+ "variableName": {
377
+ "type": "string",
378
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
379
+ },
380
+ "forBindings": {
381
+ "description": "Iteration bindings: variable name to source expression or extended {$in, $at} binding. Bindings nest left-to-right in document key order and may be correlated; key-order-hostile producers should nest phrases instead.",
382
+ "type": "object",
383
+ "minProperties": 1,
384
+ "propertyNames": {
385
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
386
+ },
387
+ "additionalProperties": {
388
+ "$ref": "#/definitions/forSource"
389
+ }
390
+ },
391
+ "forSource": {
392
+ "oneOf": [
393
+ {
394
+ "$ref": "#/definitions/expression"
395
+ },
396
+ {
397
+ "$ref": "#/definitions/extendedForBinding"
398
+ }
399
+ ]
400
+ },
401
+ "extendedForBinding": {
402
+ "description": "Extended $for binding: iterates $in and binds $at to the 0-based (D6) position variable.",
403
+ "type": "object",
404
+ "properties": {
405
+ "$in": {
406
+ "$ref": "#/definitions/expression"
407
+ },
408
+ "$at": {
409
+ "$ref": "#/definitions/variableName"
410
+ }
411
+ },
412
+ "required": [
413
+ "$in",
414
+ "$at"
415
+ ],
416
+ "additionalProperties": false
417
+ },
418
+ "bindingMap": {
419
+ "description": "Variable name to expression map, used by $let, $groupby and quantifier bindings.",
420
+ "type": "object",
421
+ "minProperties": 1,
422
+ "propertyNames": {
423
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
424
+ },
425
+ "additionalProperties": {
426
+ "$ref": "#/definitions/expression"
427
+ }
428
+ },
429
+ "orderBySpec": {
430
+ "description": "A single key spec or a major-to-minor list of key specs. An array value is by specification ALWAYS a list of key specs, so the single form excludes arrays; write a single array-constructor key as {\"$key\": [...]}.",
431
+ "oneOf": [
432
+ {
433
+ "$ref": "#/definitions/singleOrderByKey"
434
+ },
435
+ {
436
+ "type": "array",
437
+ "items": {
438
+ "$ref": "#/definitions/orderByKey"
439
+ },
440
+ "minItems": 1
441
+ }
442
+ ]
443
+ },
444
+ "singleOrderByKey": {
445
+ "description": "A key spec in non-list position: any non-array expression, or the explicit {$key, $dir, $empty} form.",
446
+ "oneOf": [
447
+ {
448
+ "$ref": "#/definitions/scalarLiteral"
449
+ },
450
+ {
451
+ "$ref": "#/definitions/stringExpression"
452
+ },
453
+ {
454
+ "$ref": "#/definitions/objectExpression"
455
+ },
456
+ {
457
+ "$ref": "#/definitions/orderByKeySpec"
458
+ }
459
+ ]
460
+ },
461
+ "orderByKey": {
462
+ "oneOf": [
463
+ {
464
+ "$ref": "#/definitions/expression"
465
+ },
466
+ {
467
+ "$ref": "#/definitions/orderByKeySpec"
468
+ }
469
+ ]
470
+ },
471
+ "orderByKeySpec": {
472
+ "description": "Explicit order key: direction defaults to 'asc', empty-sequence placement to 'least'.",
473
+ "type": "object",
474
+ "properties": {
475
+ "$key": {
476
+ "$ref": "#/definitions/expression"
477
+ },
478
+ "$dir": {
479
+ "enum": [
480
+ "asc",
481
+ "desc"
482
+ ]
483
+ },
484
+ "$empty": {
485
+ "enum": [
486
+ "least",
487
+ "greatest"
488
+ ]
489
+ }
490
+ },
491
+ "required": [
492
+ "$key"
493
+ ],
494
+ "additionalProperties": false
495
+ },
496
+ "somePhrase": {
497
+ "description": "Existential quantifier: true iff some binding tuple satisfies the EBV of $satisfies; short-circuits.",
498
+ "type": "object",
499
+ "properties": {
500
+ "$some": {
501
+ "$ref": "#/definitions/bindingMap"
502
+ },
503
+ "$satisfies": {
504
+ "$ref": "#/definitions/expression"
505
+ }
506
+ },
507
+ "required": [
508
+ "$some",
509
+ "$satisfies"
510
+ ],
511
+ "additionalProperties": false
512
+ },
513
+ "everyPhrase": {
514
+ "description": "Universal quantifier: true iff every binding tuple satisfies the EBV of $satisfies; short-circuits.",
515
+ "type": "object",
516
+ "properties": {
517
+ "$every": {
518
+ "$ref": "#/definitions/bindingMap"
519
+ },
520
+ "$satisfies": {
521
+ "$ref": "#/definitions/expression"
522
+ }
523
+ },
524
+ "required": [
525
+ "$every",
526
+ "$satisfies"
527
+ ],
528
+ "additionalProperties": false
529
+ },
530
+ "unaryOperatorPhrase": {
531
+ "description": "Operators whose value is a single operand expression.",
532
+ "type": "object",
533
+ "minProperties": 1,
534
+ "maxProperties": 1,
535
+ "propertyNames": {
536
+ "enum": [
537
+ "$exists",
538
+ "$empty",
539
+ "$not",
540
+ "$neg",
541
+ "$count",
542
+ "$sum",
543
+ "$avg",
544
+ "$min",
545
+ "$max",
546
+ "$distinct",
547
+ "$reverse",
548
+ "$sort",
549
+ "$head",
550
+ "$tail",
551
+ "$upper",
552
+ "$lower",
553
+ "$string-length",
554
+ "$normalize-space",
555
+ "$string",
556
+ "$number",
557
+ "$boolean",
558
+ "$is-string",
559
+ "$is-number",
560
+ "$is-boolean",
561
+ "$is-null",
562
+ "$is-array",
563
+ "$is-object"
564
+ ]
565
+ },
566
+ "additionalProperties": {
567
+ "$ref": "#/definitions/expression"
568
+ }
569
+ },
570
+ "binaryOperatorPhrase": {
571
+ "description": "Operators whose value is an array of exactly two operand expressions.",
572
+ "type": "object",
573
+ "minProperties": 1,
574
+ "maxProperties": 1,
575
+ "propertyNames": {
576
+ "enum": [
577
+ "$eq",
578
+ "$ne",
579
+ "$lt",
580
+ "$le",
581
+ "$gt",
582
+ "$ge",
583
+ "$add",
584
+ "$sub",
585
+ "$mul",
586
+ "$div",
587
+ "$idiv",
588
+ "$mod",
589
+ "$contains",
590
+ "$starts-with",
591
+ "$ends-with",
592
+ "$match",
593
+ "$search",
594
+ "$index-of",
595
+ "$range",
596
+ "$get",
597
+ "$default"
598
+ ]
599
+ },
600
+ "additionalProperties": {
601
+ "type": "array",
602
+ "items": {
603
+ "$ref": "#/definitions/expression"
604
+ },
605
+ "minItems": 2,
606
+ "maxItems": 2
607
+ }
608
+ },
609
+ "variadicOperatorPhrase": {
610
+ "description": "Variadic operators accepting zero or more operand expressions.",
611
+ "type": "object",
612
+ "minProperties": 1,
613
+ "maxProperties": 1,
614
+ "propertyNames": {
615
+ "enum": [
616
+ "$seq",
617
+ "$concat"
618
+ ]
619
+ },
620
+ "additionalProperties": {
621
+ "type": "array",
622
+ "items": {
623
+ "$ref": "#/definitions/expression"
624
+ }
625
+ }
626
+ },
627
+ "nonEmptyVariadicOperatorPhrase": {
628
+ "description": "Variadic operators requiring at least one operand expression.",
629
+ "type": "object",
630
+ "minProperties": 1,
631
+ "maxProperties": 1,
632
+ "propertyNames": {
633
+ "enum": [
634
+ "$and",
635
+ "$or",
636
+ "$coalesce"
637
+ ]
638
+ },
639
+ "additionalProperties": {
640
+ "type": "array",
641
+ "items": {
642
+ "$ref": "#/definitions/expression"
643
+ },
644
+ "minItems": 1
645
+ }
646
+ },
647
+ "conditionalArityOperatorPhrase": {
648
+ "description": "Operators taking two or three operand expressions: $if [cond, then, else?], $substring [str, start, len?], $subsequence [seq, start, len?].",
649
+ "type": "object",
650
+ "minProperties": 1,
651
+ "maxProperties": 1,
652
+ "propertyNames": {
653
+ "enum": [
654
+ "$if",
655
+ "$substring",
656
+ "$subsequence"
657
+ ]
658
+ },
659
+ "additionalProperties": {
660
+ "type": "array",
661
+ "items": {
662
+ "$ref": "#/definitions/expression"
663
+ },
664
+ "minItems": 2,
665
+ "maxItems": 3
666
+ }
667
+ },
668
+ "stringJoinPhrase": {
669
+ "description": "$string-join [seq, separator?]: one or two operand expressions.",
670
+ "type": "object",
671
+ "properties": {
672
+ "$string-join": {
673
+ "type": "array",
674
+ "items": {
675
+ "$ref": "#/definitions/expression"
676
+ },
677
+ "minItems": 1,
678
+ "maxItems": 2
679
+ }
680
+ },
681
+ "required": [
682
+ "$string-join"
683
+ ],
684
+ "additionalProperties": false
685
+ },
686
+ "replacePhrase": {
687
+ "description": "$replace [input, pattern, replacement]: exactly three operand expressions (I-Regexp has no flags argument, D5).",
688
+ "type": "object",
689
+ "properties": {
690
+ "$replace": {
691
+ "type": "array",
692
+ "items": {
693
+ "$ref": "#/definitions/expression"
694
+ },
695
+ "minItems": 3,
696
+ "maxItems": 3
697
+ }
698
+ },
699
+ "required": [
700
+ "$replace"
701
+ ],
702
+ "additionalProperties": false
703
+ },
704
+ "schemaLiteral": {
705
+ "description": "A JSON Schema literal, taken verbatim - never interpreted as a query expression, so JSON Schema's $-prefixed keywords ($ref, $defs, ...) do not collide with Rule 1. Deliberately unconstrained (a true schema is draft-neutral by definition): embedded schemas are not meta-validated by this artifact; the consumer's type-test compiler is authoritative (JQ0009)."
706
+ },
707
+ "schemaOperatorPhrase": {
708
+ "description": "Schema operators $valid/$assert: [expr, schema] - exactly two elements, an operand expression and a verbatim JSON Schema literal. Tuple validation is outside the draft-neutral subset, so both positions validate uniformly as schema literals here; the operand position is normalized as an ordinary expression by the compiler (JQ0xxx).",
709
+ "type": "object",
710
+ "minProperties": 1,
711
+ "maxProperties": 1,
712
+ "propertyNames": {
713
+ "enum": [
714
+ "$valid",
715
+ "$assert"
716
+ ]
717
+ },
718
+ "additionalProperties": {
719
+ "type": "array",
720
+ "items": {
721
+ "$ref": "#/definitions/schemaLiteral"
722
+ },
723
+ "minItems": 2,
724
+ "maxItems": 2
725
+ }
726
+ },
727
+ "asClause": {
728
+ "description": "The $as clause: variable-name to JSON Schema literal members, applied per tuple after $for/$let binding and before $where. Each name must be bound by the same phrase's $for (including $at names) or $let - a compiler rule (JQ0005); each binding validates per item at runtime (JQ2008).",
729
+ "type": "object",
730
+ "minProperties": 1,
731
+ "propertyNames": {
732
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
733
+ },
734
+ "additionalProperties": {
735
+ "$ref": "#/definitions/schemaLiteral"
736
+ }
737
+ },
738
+ "applyPhrase": {
739
+ "description": "JSLT body-only $apply phrase. A non-array value is any expression except an array constructor. An array value is the argument list [selector] or [selector, mode]. The draft-neutral subset has no positional-array keyword, so the compiler remains authoritative that a two-item list's second item is a literal string (JT0007 wrapping JQ0003).",
740
+ "type": "object",
741
+ "properties": {
742
+ "$apply": {
743
+ "oneOf": [
744
+ {
745
+ "description": "Bare selector form: any non-array expression.",
746
+ "oneOf": [
747
+ {
748
+ "$ref": "#/definitions/scalarLiteral"
749
+ },
750
+ {
751
+ "$ref": "#/definitions/stringExpression"
752
+ },
753
+ {
754
+ "$ref": "#/definitions/objectExpression"
755
+ }
756
+ ]
757
+ },
758
+ {
759
+ "description": "Argument-list form: [selector] or [selector, mode]. Items are expressions uniformly for draft neutrality; the compiler enforces the literal-string mode position.",
760
+ "type": "array",
761
+ "items": {
762
+ "$ref": "#/definitions/expression"
763
+ },
764
+ "minItems": 1,
765
+ "maxItems": 2
766
+ }
767
+ ]
768
+ }
769
+ },
770
+ "required": [
771
+ "$apply"
772
+ ],
773
+ "additionalProperties": false
774
+ }
775
+ }
776
+ }