@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,159 @@
1
+ # JSLT Prelude — a template layer over Jaren JSON Query
2
+
3
+ **Status: design prelude, superseded; implemented by the
4
+ [`jslt` module](../src/jslt/) under the contract in
5
+ [JSLT-FORMAT.md](./JSLT-FORMAT.md).**
6
+ This document is kept as design history: it recorded the design direction
7
+ for the JSLT layer so that the decisions taken in the query engine and its
8
+ type system (QUERY-FORMAT.md §6.8, §8.11) could be judged against what they
9
+ must eventually carry. Names, operator spellings, and section numbers here
10
+ were provisional; JSLT-FORMAT.md §1.4 lists where the final calls differ.
11
+ For the JSLT layer, JSLT-FORMAT.md is authoritative.
12
+
13
+ ## 1. Thesis
14
+
15
+ XSLT's enduring idea is *declarative dispatch*: a stylesheet is a set of
16
+ template rules, each saying "when you meet a node shaped like this, produce
17
+ that", and a recursive `apply-templates` engine does the walking. Its
18
+ enduring pain is that "shaped like this" (XPath patterns) and "typed like
19
+ this" (XML Schema) are two disjoint languages bolted together, with a third
20
+ (XSLT's own instruction vocabulary) for the output side.
21
+
22
+ The Jaren stack can collapse all three into vocabularies it already has:
23
+
24
+ - **matching** — RFC 9535 JSONPath, already compiled by this package;
25
+ - **typing** — JSON Schema, already compiled by `@jarenjs/validate` and
26
+ already embedded in query documents through the `compileTypeTest` hook
27
+ (`$valid`/`$assert`/`$as`);
28
+ - **producing** — the Jaren JSON Query language itself, whose documents are
29
+ JSON values the way XSLT stylesheets are XML documents.
30
+
31
+ A JSLT stylesheet is therefore **one JSON document, compiled by one stack**,
32
+ where a template's *match* condition and its *type* condition are the same
33
+ kind of object. That is the "better than XSLT/XSD" claim in one sentence:
34
+ XSLT 2.0 needed `schema-aware` processors and `typed value` ceremony to let
35
+ patterns see types; here a schema *is* a pattern.
36
+
37
+ ## 2. The stylesheet document
38
+
39
+ A stylesheet is a JSON document holding an **ordered list of template
40
+ rules**. Each rule is an object of the shape
41
+
42
+ - `match` — what the rule fires on. Either a JSONPath string (structural
43
+ position: "any node selected by this path"), a JSON Schema under a
44
+ `$schema-match` wrapper (shape: "any value valid against this schema"), or
45
+ both — position *and* shape must hold. The schema is compiled once through
46
+ the same `compileTypeTest` hook the query engine uses; match testing is a
47
+ hot-path boolean closure, exactly like `$valid`.
48
+ - `mode` (optional) — a name partitioning the rule set, as in XSLT: the
49
+ same input walked twice for a table of contents and for body rendering.
50
+ - `priority` (optional) — a number for explicit conflict resolution.
51
+ - `body` — a Jaren JSON Query expression producing the output for the
52
+ matched value. Inside the body, the matched value is the query input `$`
53
+ (no context-item drift, per the query spec), and an `$apply` operator
54
+ recurses.
55
+
56
+ Illustrative sketch (spellings provisional):
57
+
58
+ ```json
59
+ [ { "match": { "$schema-match": { "type": "object", "required": ["isbn"] } },
60
+ "body": { "title": "$.title", "children": { "$apply": "$.chapters[*]" } } },
61
+ { "match": "$..price", "body": { "$mul": ["$", 1.21] } } ]
62
+ ```
63
+
64
+ ## 3. `$apply` — the apply-templates operator
65
+
66
+ `{"$apply": selector}` (optionally with a `mode`) evaluates the selector,
67
+ then, for each resulting item, finds the highest-ranking matching rule and
68
+ evaluates its body with that item as the new input; results concatenate as
69
+ an ordinary sequence. It is the XSLT `apply-templates` instruction, and like
70
+ it, `$apply` is what turns a rule list from a big `switch` into a recursive
71
+ transformation engine: bodies do not know or care what the children look
72
+ like — the dispatcher re-decides per child.
73
+
74
+ **Conflict resolution** (the intuition, not yet the algorithm): explicit
75
+ `priority` wins first; then **schema specificity** — a rule whose schema
76
+ states more about the value (a `required` member list over a bare
77
+ `"type": "object"`, a `const` over an `enum` over a type) beats a vaguer
78
+ one, the analogue of XSLT's pattern-specificity defaults; document order
79
+ breaks the remaining ties, later rules winning so that user rules appended
80
+ after a library's override it. Quantifying "states more" is an open design
81
+ task (§6) — XSLT's numeric default-priority table is the cautionary tale to
82
+ beat.
83
+
84
+ ## 4. Identity and default rules; copy depth
85
+
86
+ XSLT ships built-in rules that make the empty stylesheet a useful program;
87
+ JSLT should too. Two dispositions cover the useful defaults:
88
+
89
+ - **deep-copy** (identity): an unmatched value is copied verbatim,
90
+ subtree and all. The empty stylesheet is the identity transform; each
91
+ added rule is a surgical override — the "modify one field in a deep
92
+ document" use case that motivates most template engines.
93
+ - **shallow-copy**: an unmatched container is rebuilt (object member by
94
+ member, array element by element) with `$apply` recursing into each
95
+ child, so deeper rules still fire inside otherwise-untouched regions.
96
+ This is XSLT 3.0's `on-no-match="shallow-copy"`, and is the right default
97
+ *mode* for annotate-in-place transformations.
98
+
99
+ Which disposition applies should be a per-stylesheet (or per-mode)
100
+ declaration, not a per-rule one.
101
+
102
+ ## 5. Compilation model
103
+
104
+ Nothing new is needed at the bottom of the stack; the layer compiles to the
105
+ machinery this package already exposes:
106
+
107
+ - Every `match` path compiles through the existing segment engine; every
108
+ `$schema-match` compiles once through `compileTypeTest` — the stylesheet
109
+ compiler takes the same `options.compileTypeTest` hook as
110
+ `compileJsonQuery` and stays validator-agnostic, preserving the
111
+ dependency direction (validate → json, never the reverse).
112
+ - Every `body` compiles with `compileJsonQuery`; `$apply` is the only new
113
+ operator, and it closes over the compiled dispatch table.
114
+ - Dispatch itself is a compiled closure chain: rules partition by mode at
115
+ compile time, and within a mode the match tests run in rank order —
116
+ cheap structural discriminators (type tags, required members) can be
117
+ hoisted into a pre-filter the way the query compiler specializes
118
+ singletons today.
119
+
120
+ ## 6. Non-goals of this prelude, and open questions
121
+
122
+ Out of scope for the prelude (deliberately unresolved):
123
+
124
+ - **Streaming.** XSLT 3.0's streamability rules are a research program of
125
+ their own; the query engine materializes sequences, and JSLT inherits
126
+ that. Revisit only with the lazy-iteration roadmap item.
127
+ - **Modes vs functions.** Whether modes stay (XSLT experience says they are
128
+ indispensable) or collapse into named, parameterized rule sets — i.e.
129
+ whether JSLT grows function values before the query language does.
130
+ - **Vocabulary placement.** Whether `$apply` belongs in the core query
131
+ operator registry (making every query document potentially a template
132
+ body) or in a separate `jslt` module that layers its own phrase shapes —
133
+ current lean: a separate module, keeping the query language's closed
134
+ vocabulary small and the format schema honest.
135
+ - **Rule-set schema.** The stylesheet document needs its own published JSON
136
+ Schema twin-set, like the query format's, so LLM structured output can
137
+ emit stylesheets too (QUERY-FORMAT.md appendix B applies verbatim).
138
+ - **Schema-aware static optimization** — the delicious one. A compiled
139
+ match schema is knowledge: if the input's own schema proves a rule can
140
+ never fire in a mode, drop it from that dispatch chain; if it proves a
141
+ path selects at most one node, the dispatcher gets the singleton fast
142
+ path. The cardinality analysis in the query compiler is the seed of this.
143
+
144
+ ## 7. Position in the roadmap
145
+
146
+ The intended consumers, in order:
147
+
148
+ 1. **`@jarenjs/forms`** — computed views: form state is a JSON document,
149
+ view models are transformations of it, and template dispatch on schema
150
+ shape is exactly how a form renderer picks widgets. The stylesheet
151
+ compiled-closure model matches the package's compile-once philosophy.
152
+ 2. **`@jarenjs/jslt`** — the eventual standalone package: stylesheet
153
+ compiler, `$apply` dispatcher, default-rule library, its own docs and
154
+ schema artifacts, with this package and `@jarenjs/validate` as peers.
155
+
156
+ The groundwork this prelude assumed — schema literals inside query
157
+ documents, the compile-time `compileTypeTest` hook, per-item validation
158
+ semantics — shipped with the type-system work order; the next concrete step
159
+ is the `$apply` dispatch prototype behind a `jslt` module boundary.