@json-render/core 0.4.3 → 0.5.0

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/dist/index.d.ts CHANGED
@@ -1,7 +1,225 @@
1
1
  import { z } from 'zod';
2
2
 
3
3
  /**
4
- * Dynamic value - can be a literal or a path reference to data model
4
+ * Confirmation dialog configuration
5
+ */
6
+ interface ActionConfirm {
7
+ title: string;
8
+ message: string;
9
+ confirmLabel?: string;
10
+ cancelLabel?: string;
11
+ variant?: "default" | "danger";
12
+ }
13
+ /**
14
+ * Action success handler
15
+ */
16
+ type ActionOnSuccess = {
17
+ navigate: string;
18
+ } | {
19
+ set: Record<string, unknown>;
20
+ } | {
21
+ action: string;
22
+ };
23
+ /**
24
+ * Action error handler
25
+ */
26
+ type ActionOnError = {
27
+ set: Record<string, unknown>;
28
+ } | {
29
+ action: string;
30
+ };
31
+ /**
32
+ * Action binding — maps an event to an action invocation.
33
+ *
34
+ * Used inside the `on` field of a UIElement:
35
+ * ```json
36
+ * { "on": { "press": { "action": "setState", "params": { "path": "/x", "value": 1 } } } }
37
+ * ```
38
+ */
39
+ interface ActionBinding {
40
+ /** Action name (must be in catalog) */
41
+ action: string;
42
+ /** Parameters to pass to the action handler */
43
+ params?: Record<string, DynamicValue>;
44
+ /** Confirmation dialog before execution */
45
+ confirm?: ActionConfirm;
46
+ /** Handler after successful execution */
47
+ onSuccess?: ActionOnSuccess;
48
+ /** Handler after failed execution */
49
+ onError?: ActionOnError;
50
+ }
51
+ /**
52
+ * @deprecated Use ActionBinding instead
53
+ */
54
+ type Action = ActionBinding;
55
+ /**
56
+ * Schema for action confirmation
57
+ */
58
+ declare const ActionConfirmSchema: z.ZodObject<{
59
+ title: z.ZodString;
60
+ message: z.ZodString;
61
+ confirmLabel: z.ZodOptional<z.ZodString>;
62
+ cancelLabel: z.ZodOptional<z.ZodString>;
63
+ variant: z.ZodOptional<z.ZodEnum<{
64
+ default: "default";
65
+ danger: "danger";
66
+ }>>;
67
+ }, z.core.$strip>;
68
+ /**
69
+ * Schema for success handlers
70
+ */
71
+ declare const ActionOnSuccessSchema: z.ZodUnion<readonly [z.ZodObject<{
72
+ navigate: z.ZodString;
73
+ }, z.core.$strip>, z.ZodObject<{
74
+ set: z.ZodRecord<z.ZodString, z.ZodUnknown>;
75
+ }, z.core.$strip>, z.ZodObject<{
76
+ action: z.ZodString;
77
+ }, z.core.$strip>]>;
78
+ /**
79
+ * Schema for error handlers
80
+ */
81
+ declare const ActionOnErrorSchema: z.ZodUnion<readonly [z.ZodObject<{
82
+ set: z.ZodRecord<z.ZodString, z.ZodUnknown>;
83
+ }, z.core.$strip>, z.ZodObject<{
84
+ action: z.ZodString;
85
+ }, z.core.$strip>]>;
86
+ /**
87
+ * Full action binding schema
88
+ */
89
+ declare const ActionBindingSchema: z.ZodObject<{
90
+ action: z.ZodString;
91
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull, z.ZodObject<{
92
+ path: z.ZodString;
93
+ }, z.core.$strip>]>>>;
94
+ confirm: z.ZodOptional<z.ZodObject<{
95
+ title: z.ZodString;
96
+ message: z.ZodString;
97
+ confirmLabel: z.ZodOptional<z.ZodString>;
98
+ cancelLabel: z.ZodOptional<z.ZodString>;
99
+ variant: z.ZodOptional<z.ZodEnum<{
100
+ default: "default";
101
+ danger: "danger";
102
+ }>>;
103
+ }, z.core.$strip>>;
104
+ onSuccess: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
105
+ navigate: z.ZodString;
106
+ }, z.core.$strip>, z.ZodObject<{
107
+ set: z.ZodRecord<z.ZodString, z.ZodUnknown>;
108
+ }, z.core.$strip>, z.ZodObject<{
109
+ action: z.ZodString;
110
+ }, z.core.$strip>]>>;
111
+ onError: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
112
+ set: z.ZodRecord<z.ZodString, z.ZodUnknown>;
113
+ }, z.core.$strip>, z.ZodObject<{
114
+ action: z.ZodString;
115
+ }, z.core.$strip>]>>;
116
+ }, z.core.$strip>;
117
+ /**
118
+ * @deprecated Use ActionBindingSchema instead
119
+ */
120
+ declare const ActionSchema: z.ZodObject<{
121
+ action: z.ZodString;
122
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull, z.ZodObject<{
123
+ path: z.ZodString;
124
+ }, z.core.$strip>]>>>;
125
+ confirm: z.ZodOptional<z.ZodObject<{
126
+ title: z.ZodString;
127
+ message: z.ZodString;
128
+ confirmLabel: z.ZodOptional<z.ZodString>;
129
+ cancelLabel: z.ZodOptional<z.ZodString>;
130
+ variant: z.ZodOptional<z.ZodEnum<{
131
+ default: "default";
132
+ danger: "danger";
133
+ }>>;
134
+ }, z.core.$strip>>;
135
+ onSuccess: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
136
+ navigate: z.ZodString;
137
+ }, z.core.$strip>, z.ZodObject<{
138
+ set: z.ZodRecord<z.ZodString, z.ZodUnknown>;
139
+ }, z.core.$strip>, z.ZodObject<{
140
+ action: z.ZodString;
141
+ }, z.core.$strip>]>>;
142
+ onError: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
143
+ set: z.ZodRecord<z.ZodString, z.ZodUnknown>;
144
+ }, z.core.$strip>, z.ZodObject<{
145
+ action: z.ZodString;
146
+ }, z.core.$strip>]>>;
147
+ }, z.core.$strip>;
148
+ /**
149
+ * Action handler function signature
150
+ */
151
+ type ActionHandler<TParams = Record<string, unknown>, TResult = unknown> = (params: TParams) => Promise<TResult> | TResult;
152
+ /**
153
+ * Action definition in catalog
154
+ */
155
+ interface ActionDefinition<TParams = Record<string, unknown>> {
156
+ /** Zod schema for params validation */
157
+ params?: z.ZodType<TParams>;
158
+ /** Description for AI */
159
+ description?: string;
160
+ }
161
+ /**
162
+ * Resolved action with all dynamic values resolved
163
+ */
164
+ interface ResolvedAction {
165
+ action: string;
166
+ params: Record<string, unknown>;
167
+ confirm?: ActionConfirm;
168
+ onSuccess?: ActionOnSuccess;
169
+ onError?: ActionOnError;
170
+ }
171
+ /**
172
+ * Resolve all dynamic values in an action binding
173
+ */
174
+ declare function resolveAction(binding: ActionBinding, stateModel: StateModel): ResolvedAction;
175
+ /**
176
+ * Interpolate ${path} expressions in a string
177
+ */
178
+ declare function interpolateString(template: string, stateModel: StateModel): string;
179
+ /**
180
+ * Context for action execution
181
+ */
182
+ interface ActionExecutionContext {
183
+ /** The resolved action */
184
+ action: ResolvedAction;
185
+ /** The action handler from the host */
186
+ handler: ActionHandler;
187
+ /** Function to update state model */
188
+ setState: (path: string, value: unknown) => void;
189
+ /** Function to navigate */
190
+ navigate?: (path: string) => void;
191
+ /** Function to execute another action */
192
+ executeAction?: (name: string) => Promise<void>;
193
+ }
194
+ /**
195
+ * Execute an action with all callbacks
196
+ */
197
+ declare function executeAction(ctx: ActionExecutionContext): Promise<void>;
198
+ /**
199
+ * Helper to create action bindings
200
+ */
201
+ declare const actionBinding: {
202
+ /** Create a simple action binding */
203
+ simple: (actionName: string, params?: Record<string, DynamicValue>) => ActionBinding;
204
+ /** Create an action binding with confirmation */
205
+ withConfirm: (actionName: string, confirm: ActionConfirm, params?: Record<string, DynamicValue>) => ActionBinding;
206
+ /** Create an action binding with success handler */
207
+ withSuccess: (actionName: string, onSuccess: ActionOnSuccess, params?: Record<string, DynamicValue>) => ActionBinding;
208
+ };
209
+ /**
210
+ * @deprecated Use actionBinding instead
211
+ */
212
+ declare const action: {
213
+ /** Create a simple action binding */
214
+ simple: (actionName: string, params?: Record<string, DynamicValue>) => ActionBinding;
215
+ /** Create an action binding with confirmation */
216
+ withConfirm: (actionName: string, confirm: ActionConfirm, params?: Record<string, DynamicValue>) => ActionBinding;
217
+ /** Create an action binding with success handler */
218
+ withSuccess: (actionName: string, onSuccess: ActionOnSuccess, params?: Record<string, DynamicValue>) => ActionBinding;
219
+ };
220
+
221
+ /**
222
+ * Dynamic value - can be a literal or a path reference to state model
5
223
  */
6
224
  type DynamicValue<T = unknown> = T | {
7
225
  path: string;
@@ -37,18 +255,32 @@ declare const DynamicBooleanSchema: z.ZodUnion<readonly [z.ZodBoolean, z.ZodObje
37
255
  * Base UI element structure for v2
38
256
  */
39
257
  interface UIElement<T extends string = string, P = Record<string, unknown>> {
40
- /** Unique key for reconciliation */
41
- key: string;
42
258
  /** Component type from the catalog */
43
259
  type: T;
44
260
  /** Component props */
45
261
  props: P;
46
262
  /** Child element keys (flat structure) */
47
263
  children?: string[];
48
- /** Parent element key (null for root) */
49
- parentKey?: string | null;
50
264
  /** Visibility condition */
51
265
  visible?: VisibilityCondition;
266
+ /** Event bindings — maps event names to action bindings */
267
+ on?: Record<string, ActionBinding | ActionBinding[]>;
268
+ /** Repeat children once per item in a state array */
269
+ repeat?: {
270
+ path: string;
271
+ key?: string;
272
+ };
273
+ }
274
+ /**
275
+ * Element with key and parentKey for use with flatToTree.
276
+ * When elements are in an array (not a keyed map), key and parentKey
277
+ * are needed to establish identity and parent-child relationships.
278
+ */
279
+ interface FlatElement<T extends string = string, P = Record<string, unknown>> extends UIElement<T, P> {
280
+ /** Unique key identifying this element */
281
+ key: string;
282
+ /** Parent element key (null for root) */
283
+ parentKey?: string | null;
52
284
  }
53
285
  /**
54
286
  * Visibility condition types
@@ -90,6 +322,9 @@ interface Spec {
90
322
  root: string;
91
323
  /** Flat map of elements by key */
92
324
  elements: Record<string, UIElement>;
325
+ /** Optional initial state to seed the state model.
326
+ * Components using statePath will read from / write to this state. */
327
+ state?: Record<string, unknown>;
93
328
  }
94
329
  /**
95
330
  * Auth state for visibility evaluation
@@ -99,9 +334,9 @@ interface AuthState {
99
334
  user?: Record<string, unknown>;
100
335
  }
101
336
  /**
102
- * Data model type
337
+ * State model type
103
338
  */
104
- type DataModel = Record<string, unknown>;
339
+ type StateModel = Record<string, unknown>;
105
340
  /**
106
341
  * Component schema definition using Zod
107
342
  */
@@ -111,30 +346,45 @@ type ComponentSchema = z.ZodType<Record<string, unknown>>;
111
346
  */
112
347
  type ValidationMode = "strict" | "warn" | "ignore";
113
348
  /**
114
- * JSON patch operation types
349
+ * JSON patch operation types (RFC 6902)
115
350
  */
116
- type PatchOp = "add" | "remove" | "replace" | "set";
351
+ type PatchOp = "add" | "remove" | "replace" | "move" | "copy" | "test";
117
352
  /**
118
- * JSON patch operation
353
+ * JSON patch operation (RFC 6902)
119
354
  */
120
355
  interface JsonPatch {
121
356
  op: PatchOp;
122
357
  path: string;
358
+ /** Required for add, replace, test */
123
359
  value?: unknown;
360
+ /** Required for move, copy (source location) */
361
+ from?: string;
124
362
  }
125
363
  /**
126
- * Resolve a dynamic value against a data model
364
+ * Resolve a dynamic value against a state model
127
365
  */
128
- declare function resolveDynamicValue<T>(value: DynamicValue<T>, dataModel: DataModel): T | undefined;
366
+ declare function resolveDynamicValue<T>(value: DynamicValue<T>, stateModel: StateModel): T | undefined;
129
367
  /**
130
- * Get a value from an object by JSON Pointer path
368
+ * Get a value from an object by JSON Pointer path (RFC 6901)
131
369
  */
132
370
  declare function getByPath(obj: unknown, path: string): unknown;
133
371
  /**
134
- * Set a value in an object by JSON Pointer path.
372
+ * Set a value in an object by JSON Pointer path (RFC 6901).
135
373
  * Automatically creates arrays when the path segment is a numeric index.
136
374
  */
137
375
  declare function setByPath(obj: Record<string, unknown>, path: string, value: unknown): void;
376
+ /**
377
+ * Add a value per RFC 6902 "add" semantics.
378
+ * For objects: create-or-replace the member.
379
+ * For arrays: insert before the given index, or append if "-".
380
+ */
381
+ declare function addByPath(obj: Record<string, unknown>, path: string, value: unknown): void;
382
+ /**
383
+ * Remove a value per RFC 6902 "remove" semantics.
384
+ * For objects: delete the property.
385
+ * For arrays: splice out the element at the given index.
386
+ */
387
+ declare function removeByPath(obj: Record<string, unknown>, path: string): void;
138
388
  /**
139
389
  * Find a form value from params and/or data.
140
390
  * Useful in action handlers to locate form input values regardless of path format.
@@ -165,8 +415,12 @@ type SpecStreamLine = JsonPatch;
165
415
  */
166
416
  declare function parseSpecStreamLine(line: string): SpecStreamLine | null;
167
417
  /**
168
- * Apply a single SpecStream patch to an object.
418
+ * Apply a single RFC 6902 JSON Patch operation to an object.
169
419
  * Mutates the object in place.
420
+ *
421
+ * Supports all six RFC 6902 operations: add, remove, replace, move, copy, test.
422
+ *
423
+ * @throws {Error} If a "test" operation fails (value mismatch).
170
424
  */
171
425
  declare function applySpecStreamPatch<T extends Record<string, unknown>>(obj: T, patch: SpecStreamLine): T;
172
426
  /**
@@ -174,8 +428,8 @@ declare function applySpecStreamPatch<T extends Record<string, unknown>>(obj: T,
174
428
  * Each line should be a patch operation.
175
429
  *
176
430
  * @example
177
- * const stream = `{"op":"set","path":"/name","value":"Alice"}
178
- * {"op":"set","path":"/age","value":30}`;
431
+ * const stream = `{"op":"add","path":"/name","value":"Alice"}
432
+ * {"op":"add","path":"/age","value":30}`;
179
433
  * const result = compileSpecStream(stream);
180
434
  * // { name: "Alice", age: 30 }
181
435
  */
@@ -245,7 +499,7 @@ declare const VisibilityConditionSchema: z.ZodType<VisibilityCondition>;
245
499
  * Context for evaluating visibility
246
500
  */
247
501
  interface VisibilityContext {
248
- dataModel: DataModel;
502
+ stateModel: StateModel;
249
503
  authState?: AuthState;
250
504
  }
251
505
  /**
@@ -295,171 +549,29 @@ declare const visibility: {
295
549
  };
296
550
 
297
551
  /**
298
- * Confirmation dialog configuration
299
- */
300
- interface ActionConfirm {
301
- title: string;
302
- message: string;
303
- confirmLabel?: string;
304
- cancelLabel?: string;
305
- variant?: "default" | "danger";
306
- }
307
- /**
308
- * Action success handler
309
- */
310
- type ActionOnSuccess = {
311
- navigate: string;
312
- } | {
313
- set: Record<string, unknown>;
314
- } | {
315
- action: string;
316
- };
317
- /**
318
- * Action error handler
552
+ * A prop expression that resolves to a value based on state.
553
+ *
554
+ * - `{ $path: string }` reads a value from the state model
555
+ * - `{ $cond, $then, $else }` conditionally picks a value
556
+ * - Any other value is a literal (passthrough)
319
557
  */
320
- type ActionOnError = {
321
- set: Record<string, unknown>;
558
+ type PropExpression<T = unknown> = T | {
559
+ $path: string;
322
560
  } | {
323
- action: string;
561
+ $cond: VisibilityCondition;
562
+ $then: PropExpression<T>;
563
+ $else: PropExpression<T>;
324
564
  };
325
565
  /**
326
- * Rich action definition
327
- */
328
- interface Action {
329
- /** Action name (must be in catalog) */
330
- name: string;
331
- /** Parameters to pass to the action handler */
332
- params?: Record<string, DynamicValue>;
333
- /** Confirmation dialog before execution */
334
- confirm?: ActionConfirm;
335
- /** Handler after successful execution */
336
- onSuccess?: ActionOnSuccess;
337
- /** Handler after failed execution */
338
- onError?: ActionOnError;
339
- }
340
- /**
341
- * Schema for action confirmation
342
- */
343
- declare const ActionConfirmSchema: z.ZodObject<{
344
- title: z.ZodString;
345
- message: z.ZodString;
346
- confirmLabel: z.ZodOptional<z.ZodString>;
347
- cancelLabel: z.ZodOptional<z.ZodString>;
348
- variant: z.ZodOptional<z.ZodEnum<{
349
- default: "default";
350
- danger: "danger";
351
- }>>;
352
- }, z.core.$strip>;
353
- /**
354
- * Schema for success handlers
355
- */
356
- declare const ActionOnSuccessSchema: z.ZodUnion<readonly [z.ZodObject<{
357
- navigate: z.ZodString;
358
- }, z.core.$strip>, z.ZodObject<{
359
- set: z.ZodRecord<z.ZodString, z.ZodUnknown>;
360
- }, z.core.$strip>, z.ZodObject<{
361
- action: z.ZodString;
362
- }, z.core.$strip>]>;
363
- /**
364
- * Schema for error handlers
365
- */
366
- declare const ActionOnErrorSchema: z.ZodUnion<readonly [z.ZodObject<{
367
- set: z.ZodRecord<z.ZodString, z.ZodUnknown>;
368
- }, z.core.$strip>, z.ZodObject<{
369
- action: z.ZodString;
370
- }, z.core.$strip>]>;
371
- /**
372
- * Full action schema
373
- */
374
- declare const ActionSchema: z.ZodObject<{
375
- name: z.ZodString;
376
- params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull, z.ZodObject<{
377
- path: z.ZodString;
378
- }, z.core.$strip>]>>>;
379
- confirm: z.ZodOptional<z.ZodObject<{
380
- title: z.ZodString;
381
- message: z.ZodString;
382
- confirmLabel: z.ZodOptional<z.ZodString>;
383
- cancelLabel: z.ZodOptional<z.ZodString>;
384
- variant: z.ZodOptional<z.ZodEnum<{
385
- default: "default";
386
- danger: "danger";
387
- }>>;
388
- }, z.core.$strip>>;
389
- onSuccess: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
390
- navigate: z.ZodString;
391
- }, z.core.$strip>, z.ZodObject<{
392
- set: z.ZodRecord<z.ZodString, z.ZodUnknown>;
393
- }, z.core.$strip>, z.ZodObject<{
394
- action: z.ZodString;
395
- }, z.core.$strip>]>>;
396
- onError: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
397
- set: z.ZodRecord<z.ZodString, z.ZodUnknown>;
398
- }, z.core.$strip>, z.ZodObject<{
399
- action: z.ZodString;
400
- }, z.core.$strip>]>>;
401
- }, z.core.$strip>;
402
- /**
403
- * Action handler function signature
404
- */
405
- type ActionHandler<TParams = Record<string, unknown>, TResult = unknown> = (params: TParams) => Promise<TResult> | TResult;
406
- /**
407
- * Action definition in catalog
408
- */
409
- interface ActionDefinition<TParams = Record<string, unknown>> {
410
- /** Zod schema for params validation */
411
- params?: z.ZodType<TParams>;
412
- /** Description for AI */
413
- description?: string;
414
- }
415
- /**
416
- * Resolved action with all dynamic values resolved
417
- */
418
- interface ResolvedAction {
419
- name: string;
420
- params: Record<string, unknown>;
421
- confirm?: ActionConfirm;
422
- onSuccess?: ActionOnSuccess;
423
- onError?: ActionOnError;
424
- }
425
- /**
426
- * Resolve all dynamic values in an action
566
+ * Resolve a single prop value that may contain expressions.
567
+ * Recursively resolves $path and $cond/$then/$else expressions.
427
568
  */
428
- declare function resolveAction(action: Action, dataModel: DataModel): ResolvedAction;
569
+ declare function resolvePropValue(value: unknown, ctx: VisibilityContext): unknown;
429
570
  /**
430
- * Interpolate ${path} expressions in a string
431
- */
432
- declare function interpolateString(template: string, dataModel: DataModel): string;
433
- /**
434
- * Context for action execution
571
+ * Resolve all prop values in an element's props object.
572
+ * Returns a new props object with all expressions resolved.
435
573
  */
436
- interface ActionExecutionContext {
437
- /** The resolved action */
438
- action: ResolvedAction;
439
- /** The action handler from the host */
440
- handler: ActionHandler;
441
- /** Function to update data model */
442
- setData: (path: string, value: unknown) => void;
443
- /** Function to navigate */
444
- navigate?: (path: string) => void;
445
- /** Function to execute another action */
446
- executeAction?: (name: string) => Promise<void>;
447
- }
448
- /**
449
- * Execute an action with all callbacks
450
- */
451
- declare function executeAction(ctx: ActionExecutionContext): Promise<void>;
452
- /**
453
- * Helper to create actions
454
- */
455
- declare const action: {
456
- /** Create a simple action */
457
- simple: (name: string, params?: Record<string, DynamicValue>) => Action;
458
- /** Create an action with confirmation */
459
- withConfirm: (name: string, confirm: ActionConfirm, params?: Record<string, DynamicValue>) => Action;
460
- /** Create an action with success handler */
461
- withSuccess: (name: string, onSuccess: ActionOnSuccess, params?: Record<string, DynamicValue>) => Action;
462
- };
574
+ declare function resolveElementProps(props: Record<string, unknown>, ctx: VisibilityContext): Record<string, unknown>;
463
575
 
464
576
  /**
465
577
  * Validation check definition
@@ -551,7 +663,7 @@ interface ValidationContext {
551
663
  /** Current value to validate */
552
664
  value: unknown;
553
665
  /** Full data model for resolving paths */
554
- dataModel: DataModel;
666
+ stateModel: StateModel;
555
667
  /** Custom validation functions from catalog */
556
668
  customFunctions?: Record<string, ValidationFunction>;
557
669
  }
@@ -582,6 +694,81 @@ declare const check: {
582
694
  matches: (otherPath: string, message?: string) => ValidationCheck;
583
695
  };
584
696
 
697
+ /**
698
+ * Severity level for validation issues.
699
+ */
700
+ type SpecIssueSeverity = "error" | "warning";
701
+ /**
702
+ * A single validation issue found in a spec.
703
+ */
704
+ interface SpecIssue {
705
+ /** Severity: errors should be fixed, warnings are informational */
706
+ severity: SpecIssueSeverity;
707
+ /** Human-readable description of the issue */
708
+ message: string;
709
+ /** The element key where the issue was found (if applicable) */
710
+ elementKey?: string;
711
+ /** Machine-readable issue code for programmatic handling */
712
+ code: "missing_root" | "root_not_found" | "missing_child" | "visible_in_props" | "orphaned_element" | "empty_spec" | "on_in_props" | "repeat_in_props";
713
+ }
714
+ /**
715
+ * Result of spec structural validation.
716
+ */
717
+ interface SpecValidationIssues {
718
+ /** Whether the spec passed validation (no errors; warnings are OK) */
719
+ valid: boolean;
720
+ /** List of issues found */
721
+ issues: SpecIssue[];
722
+ }
723
+ /**
724
+ * Options for validateSpec.
725
+ */
726
+ interface ValidateSpecOptions {
727
+ /**
728
+ * Whether to check for orphaned elements (elements not reachable from root).
729
+ * Defaults to false since orphans are harmless (just unused).
730
+ */
731
+ checkOrphans?: boolean;
732
+ }
733
+ /**
734
+ * Validate a spec for structural integrity.
735
+ *
736
+ * Checks for common AI-generation errors:
737
+ * - Missing or empty root
738
+ * - Root element not found in elements map
739
+ * - Children referencing non-existent elements
740
+ * - `visible` placed inside `props` instead of on the element
741
+ * - Orphaned elements (optional)
742
+ *
743
+ * @example
744
+ * ```ts
745
+ * const result = validateSpec(spec);
746
+ * if (!result.valid) {
747
+ * console.log("Spec errors:", result.issues);
748
+ * }
749
+ * ```
750
+ */
751
+ declare function validateSpec(spec: Spec, options?: ValidateSpecOptions): SpecValidationIssues;
752
+ /**
753
+ * Auto-fix common spec issues in-place and return a corrected copy.
754
+ *
755
+ * Currently fixes:
756
+ * - `visible` inside `props` → moved to element level
757
+ * - `on` inside `props` → moved to element level
758
+ * - `repeat` inside `props` → moved to element level
759
+ *
760
+ * Returns the fixed spec and a list of fixes applied.
761
+ */
762
+ declare function autoFixSpec(spec: Spec): {
763
+ spec: Spec;
764
+ fixes: string[];
765
+ };
766
+ /**
767
+ * Format validation issues into a human-readable string suitable for
768
+ * inclusion in a repair prompt sent back to the AI.
769
+ */
770
+ declare function formatSpecIssues(issues: SpecIssue[]): string;
771
+
585
772
  /**
586
773
  * Schema builder primitives
587
774
  */
@@ -638,6 +825,8 @@ interface Schema<TDef extends SchemaDefinition = SchemaDefinition> {
638
825
  readonly definition: TDef;
639
826
  /** Custom prompt template for this schema */
640
827
  readonly promptTemplate?: PromptTemplate;
828
+ /** Default rules baked into the schema (injected before customRules) */
829
+ readonly defaultRules?: string[];
641
830
  /** Create a catalog from this schema */
642
831
  createCatalog<TCatalog extends InferCatalogInput<TDef["catalog"]>>(catalog: TCatalog): Catalog$1<TDef, TCatalog>;
643
832
  }
@@ -698,6 +887,8 @@ type PromptTemplate<TCatalog = unknown> = (context: PromptContext<TCatalog>) =>
698
887
  interface SchemaOptions<TCatalog = unknown> {
699
888
  /** Custom prompt template for this schema */
700
889
  promptTemplate?: PromptTemplate<TCatalog>;
890
+ /** Default rules baked into the schema (injected before customRules in prompts) */
891
+ defaultRules?: string[];
701
892
  }
702
893
  /**
703
894
  * Spec validation result
@@ -776,6 +967,41 @@ declare function defineSchema<TDef extends SchemaDefinition>(builder: (s: Schema
776
967
  */
777
968
  declare function defineCatalog<TDef extends SchemaDefinition, TCatalog extends InferCatalogInput<TDef["catalog"]>>(schema: Schema<TDef>, catalog: TCatalog): Catalog$1<TDef, TCatalog>;
778
969
 
970
+ /**
971
+ * Options for building a user prompt.
972
+ */
973
+ interface UserPromptOptions {
974
+ /** The user's text prompt */
975
+ prompt: string;
976
+ /** Existing spec to refine (triggers patch-only mode) */
977
+ currentSpec?: Spec | null;
978
+ /** Runtime state context to include */
979
+ state?: Record<string, unknown> | null;
980
+ /** Maximum length for the user's text prompt (applied before wrapping) */
981
+ maxPromptLength?: number;
982
+ }
983
+ /**
984
+ * Build a user prompt for AI generation.
985
+ *
986
+ * Handles common patterns that every consuming app needs:
987
+ * - Truncating the user's prompt to a max length
988
+ * - Including the current spec for refinement (patch-only mode)
989
+ * - Including runtime state context
990
+ *
991
+ * @example
992
+ * ```ts
993
+ * // Fresh generation
994
+ * buildUserPrompt({ prompt: "create a todo app" })
995
+ *
996
+ * // Refinement with existing spec
997
+ * buildUserPrompt({ prompt: "add a dark mode toggle", currentSpec: spec })
998
+ *
999
+ * // With state context
1000
+ * buildUserPrompt({ prompt: "show my data", state: { todos: [] } })
1001
+ * ```
1002
+ */
1003
+ declare function buildUserPrompt(options: UserPromptOptions): string;
1004
+
779
1005
  /**
780
1006
  * Component definition with visibility and validation support
781
1007
  */
@@ -874,4 +1100,4 @@ interface SystemPromptOptions {
874
1100
  */
875
1101
  declare function generateSystemPrompt<TComponents extends Record<string, ComponentDefinition>, TActions extends Record<string, ActionDefinition>, TFunctions extends Record<string, ValidationFunction>>(catalog: Catalog<TComponents, TActions, TFunctions>, options?: SystemPromptOptions): string;
876
1102
 
877
- export { type Action, type ActionConfirm, ActionConfirmSchema, type ActionDefinition, type ActionExecutionContext, type ActionHandler, type ActionOnError, ActionOnErrorSchema, type ActionOnSuccess, ActionOnSuccessSchema, ActionSchema, type AuthState, type Catalog$1 as Catalog, type CatalogConfig, type ComponentDefinition, type ComponentSchema, type DataModel, type DynamicBoolean, DynamicBooleanSchema, type DynamicNumber, DynamicNumberSchema, type DynamicString, DynamicStringSchema, type DynamicValue, DynamicValueSchema, type InferActionParams, type InferCatalogActions, type InferCatalogComponentProps, type InferCatalogComponents, type InferCatalogInput, type InferComponentProps, type InferSpec, type JsonPatch, type Catalog as LegacyCatalog, type LogicExpression, LogicExpressionSchema, type PatchOp, type PromptContext, type PromptOptions, type PromptTemplate, type ResolvedAction, type Schema, type SchemaBuilder, type SchemaDefinition, type SchemaOptions, type SchemaType, type Spec, type SpecStreamCompiler, type SpecStreamLine, type SpecValidationResult, type SystemPromptOptions, type UIElement, type ValidationCheck, type ValidationCheckResult, ValidationCheckSchema, type ValidationConfig, ValidationConfigSchema, type ValidationContext, type ValidationFunction, type ValidationFunctionDefinition, type ValidationMode, type ValidationResult, type VisibilityCondition, VisibilityConditionSchema, type VisibilityContext, action, applySpecStreamPatch, builtInValidationFunctions, check, compileSpecStream, createCatalog, createSpecStreamCompiler, defineCatalog, defineSchema, evaluateLogicExpression, evaluateVisibility, executeAction, findFormValue, generateCatalogPrompt, generateSystemPrompt, getByPath, interpolateString, parseSpecStreamLine, resolveAction, resolveDynamicValue, runValidation, runValidationCheck, setByPath, visibility };
1103
+ export { type Action, type ActionBinding, ActionBindingSchema, type ActionConfirm, ActionConfirmSchema, type ActionDefinition, type ActionExecutionContext, type ActionHandler, type ActionOnError, ActionOnErrorSchema, type ActionOnSuccess, ActionOnSuccessSchema, ActionSchema, type AuthState, type Catalog$1 as Catalog, type CatalogConfig, type ComponentDefinition, type ComponentSchema, type DynamicBoolean, DynamicBooleanSchema, type DynamicNumber, DynamicNumberSchema, type DynamicString, DynamicStringSchema, type DynamicValue, DynamicValueSchema, type FlatElement, type InferActionParams, type InferCatalogActions, type InferCatalogComponentProps, type InferCatalogComponents, type InferCatalogInput, type InferComponentProps, type InferSpec, type JsonPatch, type Catalog as LegacyCatalog, type LogicExpression, LogicExpressionSchema, type PatchOp, type PromptContext, type PromptOptions, type PromptTemplate, type PropExpression, type ResolvedAction, type Schema, type SchemaBuilder, type SchemaDefinition, type SchemaOptions, type SchemaType, type Spec, type SpecIssue, type SpecIssueSeverity, type SpecStreamCompiler, type SpecStreamLine, type SpecValidationIssues, type SpecValidationResult, type StateModel, type SystemPromptOptions, type UIElement, type UserPromptOptions, type ValidateSpecOptions, type ValidationCheck, type ValidationCheckResult, ValidationCheckSchema, type ValidationConfig, ValidationConfigSchema, type ValidationContext, type ValidationFunction, type ValidationFunctionDefinition, type ValidationMode, type ValidationResult, type VisibilityCondition, VisibilityConditionSchema, type VisibilityContext, action, actionBinding, addByPath, applySpecStreamPatch, autoFixSpec, buildUserPrompt, builtInValidationFunctions, check, compileSpecStream, createCatalog, createSpecStreamCompiler, defineCatalog, defineSchema, evaluateLogicExpression, evaluateVisibility, executeAction, findFormValue, formatSpecIssues, generateCatalogPrompt, generateSystemPrompt, getByPath, interpolateString, parseSpecStreamLine, removeByPath, resolveAction, resolveDynamicValue, resolveElementProps, resolvePropValue, runValidation, runValidationCheck, setByPath, validateSpec, visibility };