@databehave/schema 0.1.2 → 0.1.4

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 (77) hide show
  1. package/dist/dataset/dataset.d.ts +47 -0
  2. package/dist/dataset/dataset.d.ts.map +1 -0
  3. package/dist/dataset/dataset.js +96 -0
  4. package/dist/dataset/dataset.js.map +1 -0
  5. package/dist/dataset/relate.d.ts +32 -0
  6. package/dist/dataset/relate.d.ts.map +1 -0
  7. package/dist/dataset/relate.js +46 -0
  8. package/dist/dataset/relate.js.map +1 -0
  9. package/dist/foundation/axes.d.ts +101 -0
  10. package/dist/foundation/axes.d.ts.map +1 -0
  11. package/dist/foundation/axes.js +42 -0
  12. package/dist/foundation/axes.js.map +1 -0
  13. package/dist/foundation/errors.d.ts +99 -0
  14. package/dist/foundation/errors.d.ts.map +1 -0
  15. package/dist/foundation/errors.js +91 -0
  16. package/dist/foundation/errors.js.map +1 -0
  17. package/dist/foundation/hash.d.ts +12 -0
  18. package/dist/foundation/hash.d.ts.map +1 -0
  19. package/dist/foundation/hash.js +21 -0
  20. package/dist/foundation/hash.js.map +1 -0
  21. package/dist/foundation/ir.d.ts +91 -0
  22. package/dist/foundation/ir.d.ts.map +1 -0
  23. package/dist/foundation/ir.js +16 -0
  24. package/dist/foundation/ir.js.map +1 -0
  25. package/dist/foundation/prng.d.ts +27 -0
  26. package/dist/foundation/prng.d.ts.map +1 -0
  27. package/dist/foundation/prng.js +56 -0
  28. package/dist/foundation/prng.js.map +1 -0
  29. package/dist/foundation/types.d.ts +116 -0
  30. package/dist/foundation/types.d.ts.map +1 -0
  31. package/dist/foundation/types.js +188 -0
  32. package/dist/foundation/types.js.map +1 -0
  33. package/dist/foundation/walk.d.ts +72 -0
  34. package/dist/foundation/walk.d.ts.map +1 -0
  35. package/dist/foundation/walk.js +265 -0
  36. package/dist/foundation/walk.js.map +1 -0
  37. package/dist/generator/engine.d.ts +100 -0
  38. package/dist/generator/engine.d.ts.map +1 -0
  39. package/dist/generator/engine.js +575 -0
  40. package/dist/generator/engine.js.map +1 -0
  41. package/dist/generator/replay.d.ts +42 -0
  42. package/dist/generator/replay.d.ts.map +1 -0
  43. package/dist/generator/replay.js +61 -0
  44. package/dist/generator/replay.js.map +1 -0
  45. package/dist/generator/trace.d.ts +49 -0
  46. package/dist/generator/trace.d.ts.map +1 -0
  47. package/dist/generator/trace.js +38 -0
  48. package/dist/generator/trace.js.map +1 -0
  49. package/dist/index.d.ts +31 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +34 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/internal.d.ts +22 -0
  54. package/dist/internal.d.ts.map +1 -0
  55. package/dist/internal.js +25 -0
  56. package/dist/internal.js.map +1 -0
  57. package/dist/schema/composites.d.ts +104 -0
  58. package/dist/schema/composites.d.ts.map +1 -0
  59. package/dist/schema/composites.js +134 -0
  60. package/dist/schema/composites.js.map +1 -0
  61. package/dist/schema/conditional.d.ts +28 -0
  62. package/dist/schema/conditional.d.ts.map +1 -0
  63. package/dist/schema/conditional.js +52 -0
  64. package/dist/schema/conditional.js.map +1 -0
  65. package/dist/schema/decimal.d.ts +33 -0
  66. package/dist/schema/decimal.d.ts.map +1 -0
  67. package/dist/schema/decimal.js +39 -0
  68. package/dist/schema/decimal.js.map +1 -0
  69. package/dist/schema/primitives.d.ts +47 -0
  70. package/dist/schema/primitives.d.ts.map +1 -0
  71. package/dist/schema/primitives.js +78 -0
  72. package/dist/schema/primitives.js.map +1 -0
  73. package/dist/validator/parse.d.ts +22 -0
  74. package/dist/validator/parse.d.ts.map +1 -0
  75. package/dist/validator/parse.js +427 -0
  76. package/dist/validator/parse.js.map +1 -0
  77. package/package.json +3 -1
@@ -0,0 +1,265 @@
1
+ /**
2
+ * Extensibility API — IR walker and IR-to-builder reconstruction.
3
+ *
4
+ * databehave intentionally ships no CLI, no OpenAPI ingestion, no zod adapter,
5
+ * no GUI — these belong in *external* packages. This module exposes the
6
+ * minimum surface those packages need:
7
+ *
8
+ * - `walkSchema(node, visitor)` : pre/post-order traversal with paths
9
+ * - `fromIR(node)` : reconstruct a `Schema` builder from IR
10
+ *
11
+ * Combined with the already-public `SchemaNode`, `Modifiers`, `Axes`,
12
+ * `mock`, `parse`, `mockDataset`, `createTrace`, and `seedFromString` /
13
+ * `rngFromString`, this is the full extension contract.
14
+ *
15
+ * Extension authors do NOT subclass `Schema`. They build IR (or compose
16
+ * existing builders) and call `fromIR` to obtain a typed builder back.
17
+ */
18
+ import { arr, enum_, literal, obj, tuple, union, } from '../schema/composites.js';
19
+ import { discriminated } from '../schema/conditional.js';
20
+ import { decimal } from '../schema/decimal.js';
21
+ import { bool, int, null_, num, str } from '../schema/primitives.js';
22
+ import { SchemaConflictError } from './errors.js';
23
+ import { Schema } from './types.js';
24
+ /**
25
+ * Depth-first pre/post-order traversal of a schema IR tree.
26
+ *
27
+ * The visitor receives every node (including composites) with its
28
+ * JSON-pointer-style path. Use this to power codegen (OpenAPI, zod, SQL DDL,
29
+ * documentation) without coupling to the builder classes.
30
+ */
31
+ export const walkSchema = (schemaOrNode, visitor) => {
32
+ const root = schemaOrNode instanceof Schema ? schemaOrNode._node : schemaOrNode;
33
+ walk(root, [], visitor);
34
+ };
35
+ const walk = (node, path, v) => {
36
+ const shouldDescend = v.enter ? v.enter(node, path) !== false : true;
37
+ if (shouldDescend) {
38
+ switch (node.kind) {
39
+ case 'object':
40
+ for (const k of Object.keys(node.fields)) {
41
+ walk(node.fields[k], [...path, k], v);
42
+ }
43
+ break;
44
+ case 'array':
45
+ walk(node.item, [...path, '[]'], v);
46
+ break;
47
+ case 'tuple':
48
+ node.items.forEach((it, i) => walk(it, [...path, i], v));
49
+ break;
50
+ case 'union':
51
+ node.options.forEach((o, i) => walk(o, [...path, `|${i}`], v));
52
+ break;
53
+ case 'discriminated': {
54
+ // Positional `|i` tags mirror `union` so codegen tools can treat
55
+ // both as ordered alternatives.
56
+ const tags = Object.keys(node.branches);
57
+ tags.forEach((tag, i) => walk(node.branches[tag], [...path, `|${i}`], v));
58
+ break;
59
+ }
60
+ default:
61
+ break;
62
+ }
63
+ }
64
+ v.leave?.(node, path);
65
+ };
66
+ /**
67
+ * Reconstruct a `Schema` builder from an IR node.
68
+ *
69
+ * Modifiers (`nullable`, `optional`, `default`, `describe`, axes) are
70
+ * preserved. Returns `Schema<unknown>` — extension authors that know the shape
71
+ * statically can cast to a more precise type.
72
+ */
73
+ export const fromIR = (node) => {
74
+ const base = buildBase(node);
75
+ return applyMods(base, node);
76
+ };
77
+ const buildBase = (node) => {
78
+ switch (node.kind) {
79
+ case 'string': {
80
+ let s = str();
81
+ if (node.min !== undefined)
82
+ s = s.min(node.min);
83
+ if (node.max !== undefined)
84
+ s = s.max(node.max);
85
+ if (node.pattern !== undefined)
86
+ s = s.pattern(node.pattern);
87
+ return s;
88
+ }
89
+ case 'number': {
90
+ let n = node.int ? int() : num();
91
+ if (node.min !== undefined)
92
+ n = n.min(node.min);
93
+ if (node.max !== undefined)
94
+ n = n.max(node.max);
95
+ return n;
96
+ }
97
+ case 'decimal': {
98
+ let d = decimal(node.precision, node.scale);
99
+ if (node.min !== undefined)
100
+ d = d.min(node.min);
101
+ if (node.max !== undefined)
102
+ d = d.max(node.max);
103
+ return d;
104
+ }
105
+ case 'boolean':
106
+ return bool();
107
+ case 'null':
108
+ return null_();
109
+ case 'literal':
110
+ return literal(node.value);
111
+ case 'enum':
112
+ return enum_(node.values);
113
+ case 'object': {
114
+ const fields = {};
115
+ for (const k of Object.keys(node.fields)) {
116
+ fields[k] = fromIR(node.fields[k]);
117
+ }
118
+ return obj(fields);
119
+ }
120
+ case 'array': {
121
+ let a = arr(fromIR(node.item));
122
+ if (node.length !== undefined)
123
+ a = a.length(node.length);
124
+ else {
125
+ if (node.minLength !== undefined)
126
+ a = a.min(node.minLength);
127
+ if (node.maxLength !== undefined)
128
+ a = a.max(node.maxLength);
129
+ }
130
+ return a;
131
+ }
132
+ case 'tuple': {
133
+ const items = node.items.map((it) => fromIR(it));
134
+ return tuple(...items);
135
+ }
136
+ case 'union': {
137
+ const opts = node.options.map((o) => fromIR(o));
138
+ return union(...opts);
139
+ }
140
+ case 'discriminated': {
141
+ // Reconstruct the branches as object schemas and feed them back to the
142
+ // builder. Round-tripping preserves the discriminator key.
143
+ const branchSchemas = {};
144
+ for (const tag of Object.keys(node.branches)) {
145
+ branchSchemas[tag] = fromIR(node.branches[tag]);
146
+ }
147
+ return discriminated(node.key, branchSchemas);
148
+ }
149
+ }
150
+ };
151
+ const applyMods = (schema, node) => {
152
+ const mods = node.mods;
153
+ if (mods === undefined)
154
+ return schema;
155
+ let out = schema;
156
+ if (mods.nullable === true)
157
+ out = out.nullable();
158
+ if (mods.optional === true)
159
+ out = out.optional();
160
+ if (mods.hasDefault === true)
161
+ out = out.default(mods.defaultValue);
162
+ if (mods.description !== undefined)
163
+ out = out.describe(mods.description);
164
+ if (mods.axes !== undefined) {
165
+ // Use the public axes-replay helper instead of reaching through a
166
+ // protected method via a cast.
167
+ out = out._applyAxes(mods.axes);
168
+ }
169
+ return out;
170
+ };
171
+ // ── IR versioning ──────────────────────────────────────────────────────
172
+ //
173
+ // The wire envelope ships a `$databehaveVersion` so a node serialised
174
+ // by one MAJOR cannot silently load into an incompatible one. Bare
175
+ // `SchemaNode`s remain accepted by `fromIR` for backward compatibility
176
+ // with in-process extension authors; cross-process / on-disk callers
177
+ // should round-trip through `serializeSchema` / `deserializeSchema`.
178
+ /** Current IR contract version. Bumped on every MAJOR release. */
179
+ export const IR_VERSION = 1;
180
+ /**
181
+ * Wrap a schema's IR in a versioned envelope safe for serialisation
182
+ * (JSON, disk, IPC). Pair with {@link deserializeSchema} on the
183
+ * receiving end.
184
+ *
185
+ * Throws {@link SchemaConflictError} (`code: 'serialize.closure-axis'`)
186
+ * when any node in the tree carries a closure-bearing axis — `derived`,
187
+ * `invariants`, or an `occasionally` override whose `value` is a
188
+ * function. Closures cannot survive a JSON round-trip, so encoding such
189
+ * a schema would silently drop the axis on the receiving end and
190
+ * produce subtly wrong values. The check is loud at the encode site so
191
+ * callers reach for {@link replay} or hand-coded carriers instead.
192
+ */
193
+ export const serializeSchema = (schema) => {
194
+ assertNoClosureAxes(schema._node, []);
195
+ return {
196
+ $databehaveVersion: IR_VERSION,
197
+ node: schema._node,
198
+ };
199
+ };
200
+ const assertNoClosureAxes = (node, path) => {
201
+ const axes = node.mods?.axes;
202
+ if (axes !== undefined) {
203
+ if (typeof axes.derived === 'function') {
204
+ throw new SchemaConflictError(`serializeSchema: axis 'derived' carries a closure that cannot be JSON-serialised`, [...path, 'axes', 'derived'], 'closures cannot survive JSON round-trip — keep derivedFrom() at the call site', 'serialize.closure-axis');
205
+ }
206
+ if (axes.invariants !== undefined && axes.invariants.length > 0) {
207
+ const idx = axes.invariants.findIndex((fn) => typeof fn === 'function');
208
+ if (idx >= 0) {
209
+ throw new SchemaConflictError(`serializeSchema: axis 'invariants[${idx}]' carries a closure that cannot be JSON-serialised`, [...path, 'axes', 'invariants', idx], 'closures cannot survive JSON round-trip — keep invariant() at the call site', 'serialize.closure-axis');
210
+ }
211
+ }
212
+ if (axes.occasionally !== undefined) {
213
+ const idx = axes.occasionally.findIndex((o) => typeof o.value === 'function');
214
+ if (idx >= 0) {
215
+ throw new SchemaConflictError(`serializeSchema: axis 'occasionally[${idx}].value' carries a closure that cannot be JSON-serialised`, [...path, 'axes', 'occasionally', idx, 'value'], 'closures cannot survive JSON round-trip — keep occasionally() at the call site', 'serialize.closure-axis');
216
+ }
217
+ }
218
+ }
219
+ switch (node.kind) {
220
+ case 'object':
221
+ for (const k of Object.keys(node.fields)) {
222
+ assertNoClosureAxes(node.fields[k], [...path, k]);
223
+ }
224
+ return;
225
+ case 'array':
226
+ assertNoClosureAxes(node.item, [...path, '[]']);
227
+ return;
228
+ case 'tuple':
229
+ node.items.forEach((it, i) => assertNoClosureAxes(it, [...path, i]));
230
+ return;
231
+ case 'union':
232
+ node.options.forEach((o, i) => assertNoClosureAxes(o, [...path, `|${i}`]));
233
+ return;
234
+ case 'discriminated': {
235
+ const tags = Object.keys(node.branches);
236
+ tags.forEach((tag, i) => assertNoClosureAxes(node.branches[tag], [...path, `|${i}`]));
237
+ return;
238
+ }
239
+ default:
240
+ return;
241
+ }
242
+ };
243
+ /**
244
+ * Inverse of {@link serializeSchema}. Throws when the envelope was
245
+ * produced by an incompatible MAJOR version — the failure is loud
246
+ * because silently loading a node with a renamed or removed field
247
+ * would manifest as a subtle generation/parse bug far from the cause.
248
+ */
249
+ export const deserializeSchema = (envelope) => {
250
+ if (typeof envelope !== 'object' || envelope === null) {
251
+ throw new TypeError(`databehave/deserializeSchema: expected an envelope object, got ${typeof envelope}`);
252
+ }
253
+ const v = envelope.$databehaveVersion;
254
+ if (v !== IR_VERSION) {
255
+ throw new Error(`databehave/deserializeSchema: incompatible IR version ` +
256
+ `(envelope=${JSON.stringify(v)}, this build=${IR_VERSION}). ` +
257
+ `Re-serialise with the matching databehave MAJOR.`);
258
+ }
259
+ const node = envelope.node;
260
+ if (typeof node !== 'object' || node === null) {
261
+ throw new TypeError('databehave/deserializeSchema: envelope.node must be an IR object');
262
+ }
263
+ return fromIR(node);
264
+ };
265
+ //# sourceMappingURL=walk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walk.js","sourceRoot":"","sources":["../../src/foundation/walk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Generator engine — turns a SchemaNode + context into a deterministic value.
3
+ *
4
+ * Wires the data-schema axes into the sampling pipeline.
5
+ * Resolution priority during sampling:
6
+ *
7
+ * 1. invariants (rejection-sample until they hold; bounded by MAX_ATTEMPTS)
8
+ * 2. identity (handled at dataset layer; not seen here)
9
+ * 3. derived (computed from sibling/root context — skip sampling entirely)
10
+ * 4. conditional (union / discriminated branch selection)
11
+ * 5. domain (closed candidate set)
12
+ * 6. distribution (weighted / normal / typical)
13
+ * 7. type (fall-back bounds from the IR)
14
+ */
15
+ import type { GenContext } from '../foundation/axes.js';
16
+ import type { SchemaNode } from '../foundation/ir.js';
17
+ import { type Rng } from '../foundation/prng.js';
18
+ import type { Infer, Schema } from '../foundation/types.js';
19
+ import type { TraceCollector } from './trace.js';
20
+ /**
21
+ * Per-leaf stable-seed hook.
22
+ *
23
+ * Called for every leaf-value sampling (string/number/decimal/boolean/enum/domain).
24
+ * Return a non-empty string to deterministically reseed *just this leaf*
25
+ * (path-scoped) — useful for snapshot/CI runs where a subset of rows must
26
+ * stay identical regardless of the outer `seed`.
27
+ * Return `null`/`undefined`/`''` to fall back to the shared rng (normal random).
28
+ *
29
+ * Composite kinds (object/array/tuple/union) are unaffected; their children
30
+ * re-enter this hook with their own path.
31
+ */
32
+ export type StableByFn = (ctx: GenContext) => string | null | undefined;
33
+ /**
34
+ * Per-modifier probabilities for random injection during generation.
35
+ *
36
+ * These are opt-in. With the default `{ default: 0, optional: 0, nullable: 0 }`
37
+ * `mock()` always samples a real value for the underlying type and never
38
+ * silently substitutes the modifier short-circuit. Set a non-zero probability
39
+ * to exercise the `undefined` / `null` / default-value paths.
40
+ */
41
+ export type ModifierProbs = {
42
+ /** Probability that `.default(v)` returns `v` instead of sampling. */
43
+ readonly default?: number;
44
+ /** Probability that `.optional()` returns `undefined`. */
45
+ readonly optional?: number;
46
+ /** Probability that `.nullable()` returns `null`. */
47
+ readonly nullable?: number;
48
+ };
49
+ export type MockOptions = {
50
+ /** Override the deterministic seed. Either a string or unsigned 32-bit int. */
51
+ readonly seed?: string | number;
52
+ /** Caller-supplied context channel exposed to derived/invariants as `ctx.input`. */
53
+ readonly input?: Readonly<Record<string, unknown>>;
54
+ /** Top-level row index (used by `mockDataset` so per-row derived can read `ctx.index`). */
55
+ readonly index?: number;
56
+ /** Optional trace collector — receives one entry per resolved field. */
57
+ readonly trace?: TraceCollector;
58
+ /** Reseed leaf sampling deterministically from a caller-chosen key. */
59
+ readonly stableBy?: StableByFn;
60
+ /**
61
+ * Probabilities used for modifier short-circuits during sampling.
62
+ *
63
+ * Defaults are **all zero** — modifiers do not inject randomness unless you
64
+ * explicitly opt in. This makes `mock()` exercise the underlying type by
65
+ * default (e.g. `mock(str().optional())` always returns a string).
66
+ */
67
+ readonly modifierProbs?: ModifierProbs;
68
+ /**
69
+ * Override the PRNG factory used when `seed` is a number.
70
+ *
71
+ * Defaults to {@link mulberry32}. When `seed` is a string the seed is
72
+ * first hashed (`seedFromString`) and then handed to this factory.
73
+ *
74
+ * Useful for tests that need to inject a constant or recorded RNG to
75
+ * exercise probability-driven branches deterministically. Production
76
+ * callers should leave this unset — `mulberry32` is the seeded default
77
+ * the determinism contract is calibrated against, and swapping it
78
+ * perturbs the output sequence.
79
+ */
80
+ readonly prng?: (seed: number) => Rng;
81
+ };
82
+ /**
83
+ * Generate a value that conforms to the given schema.
84
+ *
85
+ * Deterministic: identical `schema` + `options.seed` always yields the same
86
+ * value, on every machine, every run.
87
+ */
88
+ export declare const mock: <S extends Schema>(schema: S, options?: MockOptions) => Infer<S>;
89
+ export type GenState = {
90
+ rng: Rng;
91
+ rootSeed: string;
92
+ root: unknown;
93
+ modifierProbs: Required<ModifierProbs>;
94
+ input?: Readonly<Record<string, unknown>>;
95
+ rootIndex?: number;
96
+ trace?: TraceCollector;
97
+ stableBy?: StableByFn;
98
+ };
99
+ export declare const generateNode: (node: SchemaNode, path: readonly (string | number)[], parent: Readonly<Record<string, unknown>>, state: GenState) => unknown;
100
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/generator/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAMV,UAAU,EAEX,MAAM,uBAAuB,CAAA;AAE9B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAA6C,KAAK,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAC3F,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,UAAU,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;AAEvE;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC/B,oFAAoF;IACpF,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAClD,2FAA2F;IAC3F,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,wEAAwE;IACxE,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,CAAA;IAC/B,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAA;IAC9B;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAA;IACtC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,CAAA;CACtC,CAAA;AAMD;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,MAAM,EAAE,QAAQ,CAAC,EAAE,UAAS,WAAgB,KAAG,KAAK,CAAC,CAAC,CAiCpF,CAAA;AAMD,MAAM,MAAM,QAAQ,GAAG;IACrB,GAAG,EAAE,GAAG,CAAA;IACR,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,OAAO,CAAA;IACb,aAAa,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAA;IACtC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IACzC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,cAAc,CAAA;IACtB,QAAQ,CAAC,EAAE,UAAU,CAAA;CACtB,CAAA;AA0DD,eAAO,MAAM,YAAY,GACvB,MAAM,UAAU,EAChB,MAAM,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAClC,QAAQ,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACzC,OAAO,QAAQ,KACd,OA6DF,CAAA"}