@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.
- package/ARCHITECTURE.md +175 -0
- package/LICENSE +21 -0
- package/README.md +471 -0
- package/dist/types/basic.d.ts +32 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/jslt/dispatch.d.ts +11 -0
- package/dist/types/jslt/errors.d.ts +18 -0
- package/dist/types/jslt/index.d.ts +53 -0
- package/dist/types/jslt/stylesheet.d.ts +8 -0
- package/dist/types/jtlt/desugar.d.ts +19 -0
- package/dist/types/jtlt/errors.d.ts +18 -0
- package/dist/types/jtlt/index.d.ts +57 -0
- package/dist/types/jtlt/template.d.ts +8 -0
- package/dist/types/jtlt/writer.d.ts +6 -0
- package/dist/types/path.d.ts +235 -0
- package/dist/types/pointer.d.ts +114 -0
- package/dist/types/query/compile.d.ts +21 -0
- package/dist/types/query/errors.d.ts +18 -0
- package/dist/types/query/index.d.ts +70 -0
- package/dist/types/query/normalize.d.ts +68 -0
- package/dist/types/query/operators.d.ts +424 -0
- package/dist/types/query/runtime.d.ts +93 -0
- package/dist/types/segments.d.ts +62 -0
- package/dist/types/xquery/index.d.ts +19 -0
- package/dist/types/xquery/parse.d.ts +20 -0
- package/docs/JSLT-FORMAT.md +861 -0
- package/docs/JSLT-PRELUDE.md +159 -0
- package/docs/JTLT-FORMAT.md +659 -0
- package/docs/QUERY-FORMAT.md +1221 -0
- package/docs/XQUERY-FRONTEND.md +321 -0
- package/package.json +81 -0
- package/schemas/jaren-jslt.draft-07.schema.json +776 -0
- package/schemas/jaren-jslt.schema.json +776 -0
- package/schemas/jaren-query.draft-07.schema.json +613 -0
- package/schemas/jaren-query.schema.json +375 -0
- package/src/basic.js +300 -0
- package/src/index.js +4 -0
- package/src/jslt/dispatch.js +934 -0
- package/src/jslt/errors.js +34 -0
- package/src/jslt/index.js +121 -0
- package/src/jslt/stylesheet.js +234 -0
- package/src/jtlt/desugar.js +231 -0
- package/src/jtlt/errors.js +34 -0
- package/src/jtlt/index.js +155 -0
- package/src/jtlt/template.js +130 -0
- package/src/jtlt/writer.js +110 -0
- package/src/path.js +977 -0
- package/src/pointer.js +453 -0
- package/src/query/compile.js +817 -0
- package/src/query/errors.js +33 -0
- package/src/query/index.js +150 -0
- package/src/query/normalize.js +1047 -0
- package/src/query/operators.js +1253 -0
- package/src/query/runtime.js +233 -0
- package/src/segments.js +627 -0
- package/src/xquery/index.js +35 -0
- 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.
|