@jarenjs/json 0.9.2 → 0.34.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 (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
@@ -1,18 +1,82 @@
1
+ import { CodedError } from '@jarenjs/core/errors';
2
+ /**
3
+ * The runtime code table (the `CSV_CODES` shape): one entry per code
4
+ * the engine can raise, proven in sync with QUERY-FORMAT.md §10's
5
+ * normative tables by a test — the table cannot silently drift from
6
+ * the spec.
7
+ */
8
+ export declare const QUERY_CODES: Readonly<{
9
+ JQ0001: "object mixes $-prefixed and plain keys";
10
+ JQ0002: "unknown operator or $-key outside the vocabulary";
11
+ JQ0003: "known phrase with bad arity, value shape, or key combination";
12
+ JQ0004: "string starting $ is not a valid path or escape";
13
+ JQ0005: "variable reference neither bound nor a declared external";
14
+ JQ0006: "version envelope with unknown or non-string $query";
15
+ JQ0007: "duplicate variable binding within one phrase";
16
+ JQ0008: "schema operator in a query compiled without a type-test compiler";
17
+ JQ0009: "schema literal rejected by the type-test compiler";
18
+ JQ0010: "$call/$collation naming no registered function/collation";
19
+ JQ0011: "expression nesting deeper than limits.depth";
20
+ JQ2001: "runtime type error";
21
+ JQ2002: "$idiv/$mod by zero";
22
+ JQ2003: "EBV of a multi-item sequence";
23
+ JQ2004: "$map key expression not a single string";
24
+ JQ2005: "incomparable $orderby/$sort keys";
25
+ JQ2006: "reference to an unbound external parameter";
26
+ JQ2007: "resource guard: an operator result exceeding an implementation limit";
27
+ JQ2008: "schema assertion failure";
28
+ JQ2009: "an execution limit exceeded";
29
+ JQ2010: "a registered $call function threw";
30
+ JQ2011: "the input document is undefined";
31
+ }>;
32
+ /**
33
+ * Shared constructor body for the two query error classes: `cause`
34
+ * retains what host code threw, BY VALUE — set via an own property
35
+ * even for `undefined`, so presence is testable (the base's `hasOwn`
36
+ * options form, passed through unchanged).
37
+ */
38
+ declare class JsonQueryError extends CodedError {
39
+ /**
40
+ * @param {string} name - The public class name for `error.name`
41
+ * @param {string} code
42
+ * @param {string} reason
43
+ * @param {string} docPath
44
+ * @param {{ cause?: unknown }} [options]
45
+ */
46
+ constructor(name: string, code: string, reason: string, docPath: string, options?: {
47
+ cause?: unknown;
48
+ });
49
+ }
1
50
  /**
2
51
  * Error thrown when a query document is rejected at compile time
3
52
  * (`JQ0xxx` codes, QUERY-FORMAT.md section 10.2).
4
53
  */
5
- export declare class JsonQueryCompileError extends Error {
6
- code: any;
7
- docPath: any;
8
- constructor(code: any, message: any, docPath: any);
54
+ export declare class JsonQueryCompileError extends JsonQueryError {
55
+ /**
56
+ * @param {string} code
57
+ * @param {string} reason
58
+ * @param {string} docPath
59
+ * @param {{ cause?: unknown }} [options] - `cause` retains what a
60
+ * host hook (e.g. `compileTypeTest`) threw
61
+ */
62
+ constructor(code: string, reason: string, docPath: string, options?: {
63
+ cause?: unknown;
64
+ });
9
65
  }
10
66
  /**
11
67
  * Error thrown when evaluating a compiled query fails
12
68
  * (`JQ2xxx` codes, QUERY-FORMAT.md section 10.3).
13
69
  */
14
- export declare class JsonQueryRuntimeError extends Error {
15
- code: any;
16
- docPath: any;
17
- constructor(code: any, message: any, docPath: any);
70
+ export declare class JsonQueryRuntimeError extends JsonQueryError {
71
+ /**
72
+ * @param {string} code
73
+ * @param {string} reason
74
+ * @param {string} docPath
75
+ * @param {{ cause?: unknown }} [options] - `cause` retains what host
76
+ * code threw
77
+ */
78
+ constructor(code: string, reason: string, docPath: string, options?: {
79
+ cause?: unknown;
80
+ });
18
81
  }
82
+ export {};
@@ -1,10 +1,274 @@
1
- export { JsonQueryCompileError, JsonQueryRuntimeError } from './errors.js';
1
+ import { NODE_KINDS } from './normalize.js';
2
+ export { JsonQueryCompileError, JsonQueryRuntimeError, QUERY_CODES } from './errors.js';
3
+ export { NODE_KINDS };
4
+ export { annotateTypes, TYPE_TAGS } from './types.js';
5
+ export type JsonQueryLimits = {
6
+ /**
7
+ * - Caps every FLWOR phrase
8
+ * materialization and tightens `$range`'s resource guard; exceeding
9
+ * it is `JQ2009` (`$range` keeps its historical `JQ2007`).
10
+ */
11
+ sequenceItems?: number;
12
+ /**
13
+ * - Caps the final result at the
14
+ * query boundary (`JQ2009`); checked after evaluation, and
15
+ * deliberately bypassed by `first`/`exists`/`ebv`.
16
+ */
17
+ resultItems?: number;
18
+ /**
19
+ * - Caps expression-node evaluations
20
+ * (`JQ2009`). This is the one limit that bounds *work* rather than
21
+ * output, so it is also the one that costs: setting it compiles a
22
+ * counter check into every node, roughly halving throughput. A step
23
+ * is one node evaluation, not one primitive operation - a single
24
+ * node that loops internally (`$range` materialization, a general
25
+ * comparison's cross product) counts once.
26
+ */
27
+ steps?: number;
28
+ /**
29
+ * - Caps expression nesting, enforced at
30
+ * compile time (`JQ0011`). The language has no recursion, so the
31
+ * compiled closure tree's evaluation depth IS the document's static
32
+ * nesting: checking it once is exact and costs nothing to evaluate.
33
+ */
34
+ depth?: number;
35
+ };
36
+ export type JsonQueryOptions = {
37
+ /**
38
+ * Hook compiling a JSON Schema literal into a boolean item
39
+ * predicate, called once per schema literal at query compile time
40
+ * (QUERY-FORMAT.md section 8.11). `@jarenjs/validate/query` exports
41
+ * `createTypeTestCompiler()` producing one; any conforming
42
+ * implementation works - this package never imports the validator.
43
+ * Without a hook, the schema operators `$valid`/`$assert`/`$as` are
44
+ * compile error JQ0008.
45
+ */
46
+ compileTypeTest?: (schemaJson: any, docPath: string) => ((value: any) => boolean);
47
+ /**
48
+ * - Package-internal operator
49
+ * extension point, the operator analogue of `compileTypeTest` (used
50
+ * by the JSLT layer; not a public contract). A plain object of
51
+ * `name -> entry` following the operator registry contract; see
52
+ * normalizeQuery in normalize.js for the full shape. The published
53
+ * format vocabulary is unchanged: without extensions, documents
54
+ * using such operators fail JQ0002.
55
+ */
56
+ extensions?: object;
57
+ /**
58
+ * Registry of named trusted pure host functions for `$call`
59
+ * (QUERY-FORMAT.md section 8.12); an unregistered or empty name is
60
+ * rejected at compile time (JQ0010 / TypeError).
61
+ */
62
+ functions?: Record<string, (...args: any[]) => any>;
63
+ /**
64
+ * Registry of named pure compare functions for `$orderby`'s
65
+ * `$collation` member (QUERY-FORMAT.md section 6.6).
66
+ */
67
+ collations?: Record<string, (a: string, b: string) => number>;
68
+ /**
69
+ * Registry of custom JSONPath function extensions (RFC 9535 section
70
+ * 2.4), available inside the filters of every path string the
71
+ * document contains. Deliberately separate from `functions`: that
72
+ * registry extends the query vocabulary through `$call`, this one
73
+ * extends the RFC 9535 grammar the path strings are written in.
74
+ */
75
+ pathFunctions?: Record<string, import('../path.js').JSONPathFunction>;
76
+ /**
77
+ * - Enforced execution limits.
78
+ */
79
+ limits?: JsonQueryLimits;
80
+ /**
81
+ * - Closed-world compilation:
82
+ * the variable names (no `$` sigil) the document may leave free.
83
+ * Every other free variable is compile error `JQ0005` at its own
84
+ * reference site, so a query cannot silently acquire a parameter the
85
+ * host never meant to expose. `[]` declares none. Omitted, the open
86
+ * world of QUERY-FORMAT.md section 9 applies: use is the declaration.
87
+ */
88
+ externals?: readonly string[];
89
+ /**
90
+ * - On `compileJsonQuery`: additionally
91
+ * expose the normalized-form record (QUERY-FORMAT.md Appendix C.1) at
92
+ * `query.analysis`, from the same normalization. Compilation itself
93
+ * stays strict — schema hooks remain required.
94
+ */
95
+ analysis?: boolean;
96
+ };
97
+ export type JsonQueryAnalysis = {
98
+ /**
99
+ * - see the compatibility policy (C.7)
100
+ */
101
+ astVersion: number;
102
+ /**
103
+ * - the frozen node tree (C.3)
104
+ */
105
+ root: object;
106
+ externals: readonly {
107
+ name: string;
108
+ slot: number;
109
+ }[];
110
+ frameSize: number;
111
+ dependencies: Readonly<JsonQueryDependencies>;
112
+ limits: object | null;
113
+ };
114
+ export type JsonQueryDependencies = {
115
+ externals: readonly string[];
116
+ operators: readonly string[];
117
+ functions: readonly string[];
118
+ collations: readonly string[];
119
+ };
120
+ export type JsonQueryExplanation = {
121
+ externals: string[];
122
+ operators: string[];
123
+ functions: string[];
124
+ collations: string[];
125
+ limits: {
126
+ sequenceItems: number | null;
127
+ resultItems: number | null;
128
+ steps: number | null;
129
+ depth: number | null;
130
+ } | null;
131
+ };
132
+ export type CompiledJsonQuery = ((data: any, externals?: Record<string, any>) => any) & {
133
+ first: (data: any, externals?: Record<string, any>) => any;
134
+ exists: (data: any, externals?: Record<string, any>) => boolean;
135
+ ebv: (data: any, externals?: Record<string, any>) => boolean;
136
+ externals: readonly string[];
137
+ doc: any;
138
+ dependencies: Readonly<JsonQueryDependencies>;
139
+ explain: () => JsonQueryExplanation;
140
+ analysis?: Readonly<JsonQueryAnalysis>;
141
+ };
142
+ /**
143
+ * The enforced query limits (QUERY-FORMAT.md section 8.12). These are
144
+ * deterministic result/phrase-OUTPUT caps, not general resource
145
+ * budgets: they bound what a phrase or the query hands onward, never
146
+ * the memory, work, fan-out or recursion spent producing it (a group
147
+ * or order barrier may accumulate arbitrarily many items behind a
148
+ * small final result). Untrusted queries need worker isolation, not
149
+ * these limits.
150
+ * @typedef {Object} JsonQueryLimits
151
+ * @property {number} [sequenceItems] - Caps every FLWOR phrase
152
+ * materialization and tightens `$range`'s resource guard; exceeding
153
+ * it is `JQ2009` (`$range` keeps its historical `JQ2007`).
154
+ * @property {number} [resultItems] - Caps the final result at the
155
+ * query boundary (`JQ2009`); checked after evaluation, and
156
+ * deliberately bypassed by `first`/`exists`/`ebv`.
157
+ * @property {number} [steps] - Caps expression-node evaluations
158
+ * (`JQ2009`). This is the one limit that bounds *work* rather than
159
+ * output, so it is also the one that costs: setting it compiles a
160
+ * counter check into every node, roughly halving throughput. A step
161
+ * is one node evaluation, not one primitive operation - a single
162
+ * node that loops internally (`$range` materialization, a general
163
+ * comparison's cross product) counts once.
164
+ * @property {number} [depth] - Caps expression nesting, enforced at
165
+ * compile time (`JQ0011`). The language has no recursion, so the
166
+ * compiled closure tree's evaluation depth IS the document's static
167
+ * nesting: checking it once is exact and costs nothing to evaluate.
168
+ */
169
+ /**
170
+ * Compile options for {@link compileJsonQuery}.
171
+ * @typedef {Object} JsonQueryOptions
172
+ * @property {(schemaJson: any, docPath: string) => ((value: any) => boolean)} [compileTypeTest]
173
+ * Hook compiling a JSON Schema literal into a boolean item
174
+ * predicate, called once per schema literal at query compile time
175
+ * (QUERY-FORMAT.md section 8.11). `@jarenjs/validate/query` exports
176
+ * `createTypeTestCompiler()` producing one; any conforming
177
+ * implementation works - this package never imports the validator.
178
+ * Without a hook, the schema operators `$valid`/`$assert`/`$as` are
179
+ * compile error JQ0008.
180
+ * @property {object} [extensions] - Package-internal operator
181
+ * extension point, the operator analogue of `compileTypeTest` (used
182
+ * by the JSLT layer; not a public contract). A plain object of
183
+ * `name -> entry` following the operator registry contract; see
184
+ * normalizeQuery in normalize.js for the full shape. The published
185
+ * format vocabulary is unchanged: without extensions, documents
186
+ * using such operators fail JQ0002.
187
+ * @property {Record<string, (...args: any[]) => any>} [functions]
188
+ * Registry of named trusted pure host functions for `$call`
189
+ * (QUERY-FORMAT.md section 8.12); an unregistered or empty name is
190
+ * rejected at compile time (JQ0010 / TypeError).
191
+ * @property {Record<string, (a: string, b: string) => number>} [collations]
192
+ * Registry of named pure compare functions for `$orderby`'s
193
+ * `$collation` member (QUERY-FORMAT.md section 6.6).
194
+ * @property {Record<string, import('../path.js').JSONPathFunction>} [pathFunctions]
195
+ * Registry of custom JSONPath function extensions (RFC 9535 section
196
+ * 2.4), available inside the filters of every path string the
197
+ * document contains. Deliberately separate from `functions`: that
198
+ * registry extends the query vocabulary through `$call`, this one
199
+ * extends the RFC 9535 grammar the path strings are written in.
200
+ * @property {JsonQueryLimits} [limits] - Enforced execution limits.
201
+ * @property {readonly string[]} [externals] - Closed-world compilation:
202
+ * the variable names (no `$` sigil) the document may leave free.
203
+ * Every other free variable is compile error `JQ0005` at its own
204
+ * reference site, so a query cannot silently acquire a parameter the
205
+ * host never meant to expose. `[]` declares none. Omitted, the open
206
+ * world of QUERY-FORMAT.md section 9 applies: use is the declaration.
207
+ * @property {boolean} [analysis] - On `compileJsonQuery`: additionally
208
+ * expose the normalized-form record (QUERY-FORMAT.md Appendix C.1) at
209
+ * `query.analysis`, from the same normalization. Compilation itself
210
+ * stays strict — schema hooks remain required.
211
+ */
212
+ /**
213
+ * The published normalized-form record (QUERY-FORMAT.md Appendix C.1):
214
+ * what `analyzeQuery` returns and `compileJsonQuery`'s `analysis`
215
+ * option exposes.
216
+ * @typedef {Object} JsonQueryAnalysis
217
+ * @property {number} astVersion - see the compatibility policy (C.7)
218
+ * @property {object} root - the frozen node tree (C.3)
219
+ * @property {readonly { name: string, slot: number }[]} externals
220
+ * @property {number} frameSize
221
+ * @property {Readonly<JsonQueryDependencies>} dependencies
222
+ * @property {object | null} limits
223
+ */
224
+ /**
225
+ * The frozen dependency record of a compiled query (saved-rule
226
+ * vetting): the external names it binds, the operators it uses, and
227
+ * the registered functions/collations it resolved.
228
+ * @typedef {Object} JsonQueryDependencies
229
+ * @property {readonly string[]} externals
230
+ * @property {readonly string[]} operators
231
+ * @property {readonly string[]} functions
232
+ * @property {readonly string[]} collations
233
+ */
234
+ /**
235
+ * A plain-JSON explanation of a compiled query: its dependencies plus
236
+ * the enforced limits. A fresh value each `explain()` call.
237
+ * @typedef {Object} JsonQueryExplanation
238
+ * @property {string[]} externals
239
+ * @property {string[]} operators
240
+ * @property {string[]} functions
241
+ * @property {string[]} collations
242
+ * @property {{ sequenceItems: number | null, resultItems: number | null, steps: number | null, depth: number | null } | null} limits
243
+ */
244
+ /**
245
+ * The compiled query returned by {@link compileJsonQuery}: the query
246
+ * function itself, carrying its helper methods and metadata.
247
+ * @typedef {((data: any, externals?: Record<string, any>) => any) & {
248
+ * first: (data: any, externals?: Record<string, any>) => any,
249
+ * exists: (data: any, externals?: Record<string, any>) => boolean,
250
+ * ebv: (data: any, externals?: Record<string, any>) => boolean,
251
+ * externals: readonly string[],
252
+ * doc: any,
253
+ * dependencies: Readonly<JsonQueryDependencies>,
254
+ * explain: () => JsonQueryExplanation,
255
+ * analysis?: Readonly<JsonQueryAnalysis>,
256
+ * }} CompiledJsonQuery
257
+ */
2
258
  /**
3
259
  * Compile a Jaren JSON Query document into a reusable query function.
4
260
  *
5
261
  * The returned function applies the query to a JSON value and returns the
6
262
  * result as plain JSON: `undefined` for the empty sequence, the item
7
263
  * itself for a singleton result, an array of items for a longer sequence.
264
+ *
265
+ * The `data` argument MUST be a JSON value (section 2.1). The engine does
266
+ * not deep-validate it - that would cost a full walk per call - so a
267
+ * non-JSON value inside the document simply flows through as an opaque
268
+ * item. The single exception is `undefined`, rejected with `JQ2011`
269
+ * because this API already spends `undefined` on the empty sequence.
270
+ * An external bound to `undefined` reads as unbound (`JQ2006` on use).
271
+ *
8
272
  * It also carries helper methods and metadata:
9
273
  *
10
274
  * - `query(data, externals?)` - the query result as described above
@@ -22,26 +286,15 @@ export { JsonQueryCompileError, JsonQueryRuntimeError } from './errors.js';
22
286
  * external raises `JQ2006`.
23
287
  * - `query.doc` - a deeply frozen copy of the query document (the
24
288
  * caller's object is never frozen)
289
+ * - `query.dependencies` - what the query depends on (frozen JSON):
290
+ * external names, operators, registered functions and collations
291
+ * - `query.explain()` - a fresh plain-JSON explanation: the
292
+ * dependencies plus the enforced limits
25
293
  *
26
294
  * @param {any} doc - the query document (any JSON value; a bare RFC 9535
27
295
  * JSONPath string is the degenerate query)
28
- * @param {object} [options] - compile options
29
- * @param {(schemaJson: any, docPath: string) => ((value: any) => boolean)}
30
- * [options.compileTypeTest] - hook compiling a JSON Schema literal into
31
- * a boolean item predicate, called once per schema literal at query
32
- * compile time (QUERY-FORMAT.md section 8.11). `@jarenjs/validate/query`
33
- * exports `createTypeTestCompiler()` producing one; any conforming
34
- * implementation works - this package never imports the validator.
35
- * Without a hook, the schema operators `$valid`/`$assert`/`$as` are
36
- * compile error JQ0008.
37
- * @param {object} [options.extensions] - package-internal operator
38
- * extension point, the operator analogue of `compileTypeTest` (used by
39
- * the JSLT layer; not a public contract). A plain object of
40
- * `name -> entry` following the operator registry contract; see
41
- * normalizeQuery in normalize.js for the full shape. The published
42
- * format vocabulary is unchanged: without extensions, documents using
43
- * such operators fail JQ0002.
44
- * @returns {function} the compiled query function
296
+ * @param {JsonQueryOptions} [options] - compile options
297
+ * @returns {CompiledJsonQuery} the compiled query function
45
298
  * @throws {JsonQueryCompileError} when the document violates the format
46
299
  * @example
47
300
  * const q = compileJsonQuery({
@@ -51,15 +304,54 @@ export { JsonQueryCompileError, JsonQueryRuntimeError } from './errors.js';
51
304
  * q.externals; // ['max']
52
305
  * q(data, { max: 10 }); // { title: 'Sayings of the Century', cheap: true }
53
306
  */
54
- export declare function compileJsonQuery(doc: any, options?: {
55
- compileTypeTest?: (schemaJson: any, docPath: string) => ((value: any) => boolean);
56
- extensions?: object;
57
- }): Function;
307
+ export declare function compileJsonQuery(doc: any, options?: JsonQueryOptions): CompiledJsonQuery;
308
+ /**
309
+ * The version of the published normalized form (QUERY-FORMAT.md
310
+ * Appendix C.7): bumped when a node kind is added or removed, a
311
+ * published field is removed or retyped, or an appendix invariant
312
+ * changes. Adding an optional field is NOT a bump.
313
+ */
314
+ export declare const AST_VERSION = 1;
315
+ /**
316
+ * Analyse a query document WITHOUT compiling it: the engine's own
317
+ * normalized reading of the document — the frozen node tree, the
318
+ * externals in first-appearance order, the frame size and the
319
+ * dependency sets — published as the versioned contract of
320
+ * QUERY-FORMAT.md Appendix C. Another package walks this instead of
321
+ * re-implementing the grammar, and an unknown `kind` in its dispatch is
322
+ * a loud failure instead of a silent divergence.
323
+ *
324
+ * Analysis applies every JQ0xxx rejection compilation would, with one
325
+ * difference (Appendix C.1): schema literals do not require
326
+ * `options.compileTypeTest` — without the hook they normalize to `raw`
327
+ * nodes whose `test` is `null`, so a document can be analysed by a
328
+ * consumer that could not execute it. With the hook supplied, analysis
329
+ * compiles the predicates exactly as compilation would.
330
+ * @param {any} doc - the query document (any JSON value)
331
+ * @param {JsonQueryOptions} [options] - the same options as
332
+ * `compileJsonQuery`
333
+ * @returns {{ astVersion: number, root: object, externals: readonly
334
+ * { name: string, slot: number }[], frameSize: number,
335
+ * dependencies: Readonly<JsonQueryDependencies>, limits: object | null }}
336
+ * @throws {JsonQueryCompileError} on any JQ0xxx condition (except
337
+ * JQ0008, which analysis does not raise)
338
+ */
339
+ export declare function analyzeQuery(doc: any, options?: JsonQueryOptions): {
340
+ astVersion: number;
341
+ root: object;
342
+ externals: readonly {
343
+ name: string;
344
+ slot: number;
345
+ }[];
346
+ frameSize: number;
347
+ dependencies: Readonly<JsonQueryDependencies>;
348
+ limits: object | null;
349
+ };
58
350
  /**
59
351
  * Apply a Jaren JSON Query document to a JSON value in one call.
60
- * Compiled queries are cached: object documents by identity (WeakMap),
61
- * string documents (the degenerate JSONPath case) by value (FIFO, 512
62
- * entries - the same pattern as `queryJSONPath`).
352
+ * Compiled queries are cached: object documents by identity (weak),
353
+ * string documents (the degenerate JSONPath case) by value (bounded
354
+ * LRU, 512 entries the shared `@jarenjs/core/cache` primitive).
63
355
  * @param {any} doc - the query document
64
356
  * @param {any} data - the JSON value to query
65
357
  * @param {object} [externals] - external parameter bindings (`{ name: value }`)
@@ -1,3 +1,10 @@
1
+ /**
2
+ * The twelve node kinds of the normalized form, sorted — the published
3
+ * AST contract (QUERY-FORMAT.md Appendix C). An exhaustiveness gate
4
+ * asserts a corpus exercising every construct produces exactly this
5
+ * set, so a new kind cannot ship undocumented.
6
+ */
7
+ export declare const NODE_KINDS: readonly string[];
1
8
  /** Statically empty (the node always evaluates to the empty sequence). */
2
9
  export declare const CARD_ZERO = 0;
3
10
  /** Always exactly one item; compile.js skips all sequence checks. */
@@ -22,6 +29,15 @@ export declare function joinCard(a: number, b: number): number;
22
29
  * @returns {number}
23
30
  */
24
31
  export declare function sumCard(a: number, b: number): number;
32
+ /**
33
+ * Project a safe diagnostic string from whatever a host hook threw:
34
+ * no `.message` read on a raw value, no user coercion, no
35
+ * proxy-observable reflection — the compiler must never fail while
36
+ * describing a host failure.
37
+ * @param {unknown} e
38
+ * @returns {string}
39
+ */
40
+ export declare function hostFailureText(e: unknown): string;
25
41
  /**
26
42
  * Deep-copy a JSON value and freeze every object/array in the copy.
27
43
  * Used for `$const` values and the compiled query's `.doc` property, so
@@ -30,6 +46,14 @@ export declare function sumCard(a: number, b: number): number;
30
46
  * @returns {any} an independent, deeply frozen copy
31
47
  */
32
48
  export declare function deepFreezeCopy(value: any): any;
49
+ /**
50
+ * Collect the frame slots an expression subtree reads (variable
51
+ * references and path roots) into `out`. Over-approximation is safe.
52
+ * @param {object} node - a frozen AST node
53
+ * @param {Set<number>} out - accumulator of slot indexes
54
+ */
55
+ export declare function collectReadSlots(node: object, out: Set<number>): void;
56
+ export declare function isReservedQueryName(name: any): boolean;
33
57
  /**
34
58
  * Normalize a query document into the internal AST.
35
59
  * @param {any} doc - the query document (any JSON value)