@json-render/core 0.4.3 → 0.4.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.
- package/README.md +8 -6
- package/dist/index.d.mts +39 -13
- package/dist/index.d.ts +39 -13
- package/dist/index.js +149 -29
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +147 -29
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -116,14 +116,16 @@ while (streaming) {
|
|
|
116
116
|
const finalSpec = compiler.getResult();
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
SpecStream format (each line is a
|
|
119
|
+
SpecStream format uses [RFC 6902 JSON Patch](https://datatracker.ietf.org/doc/html/rfc6902) operations (each line is a patch):
|
|
120
120
|
|
|
121
121
|
```jsonl
|
|
122
|
-
{"op":"
|
|
123
|
-
{"op":"
|
|
124
|
-
{"op":"
|
|
122
|
+
{"op":"add","path":"/root/type","value":"Card"}
|
|
123
|
+
{"op":"add","path":"/root/props","value":{"title":"Hello"}}
|
|
124
|
+
{"op":"add","path":"/root/children/0","value":{"type":"Button","props":{"label":"Click"}}}
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
+
All six RFC 6902 operations are supported: `add`, `remove`, `replace`, `move`, `copy`, `test`.
|
|
128
|
+
|
|
127
129
|
### Low-Level Utilities
|
|
128
130
|
|
|
129
131
|
```typescript
|
|
@@ -134,8 +136,8 @@ import {
|
|
|
134
136
|
} from "@json-render/core";
|
|
135
137
|
|
|
136
138
|
// Parse a single line
|
|
137
|
-
const patch = parseSpecStreamLine('{"op":"
|
|
138
|
-
// { op: "
|
|
139
|
+
const patch = parseSpecStreamLine('{"op":"add","path":"/root","value":{}}');
|
|
140
|
+
// { op: "add", path: "/root", value: {} }
|
|
139
141
|
|
|
140
142
|
// Apply a patch to an object
|
|
141
143
|
const obj = {};
|
package/dist/index.d.mts
CHANGED
|
@@ -37,19 +37,26 @@ declare const DynamicBooleanSchema: z.ZodUnion<readonly [z.ZodBoolean, z.ZodObje
|
|
|
37
37
|
* Base UI element structure for v2
|
|
38
38
|
*/
|
|
39
39
|
interface UIElement<T extends string = string, P = Record<string, unknown>> {
|
|
40
|
-
/** Unique key for reconciliation */
|
|
41
|
-
key: string;
|
|
42
40
|
/** Component type from the catalog */
|
|
43
41
|
type: T;
|
|
44
42
|
/** Component props */
|
|
45
43
|
props: P;
|
|
46
44
|
/** Child element keys (flat structure) */
|
|
47
45
|
children?: string[];
|
|
48
|
-
/** Parent element key (null for root) */
|
|
49
|
-
parentKey?: string | null;
|
|
50
46
|
/** Visibility condition */
|
|
51
47
|
visible?: VisibilityCondition;
|
|
52
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Element with key and parentKey for use with flatToTree.
|
|
51
|
+
* When elements are in an array (not a keyed map), key and parentKey
|
|
52
|
+
* are needed to establish identity and parent-child relationships.
|
|
53
|
+
*/
|
|
54
|
+
interface FlatElement<T extends string = string, P = Record<string, unknown>> extends UIElement<T, P> {
|
|
55
|
+
/** Unique key identifying this element */
|
|
56
|
+
key: string;
|
|
57
|
+
/** Parent element key (null for root) */
|
|
58
|
+
parentKey?: string | null;
|
|
59
|
+
}
|
|
53
60
|
/**
|
|
54
61
|
* Visibility condition types
|
|
55
62
|
*/
|
|
@@ -111,30 +118,45 @@ type ComponentSchema = z.ZodType<Record<string, unknown>>;
|
|
|
111
118
|
*/
|
|
112
119
|
type ValidationMode = "strict" | "warn" | "ignore";
|
|
113
120
|
/**
|
|
114
|
-
* JSON patch operation types
|
|
121
|
+
* JSON patch operation types (RFC 6902)
|
|
115
122
|
*/
|
|
116
|
-
type PatchOp = "add" | "remove" | "replace" | "
|
|
123
|
+
type PatchOp = "add" | "remove" | "replace" | "move" | "copy" | "test";
|
|
117
124
|
/**
|
|
118
|
-
* JSON patch operation
|
|
125
|
+
* JSON patch operation (RFC 6902)
|
|
119
126
|
*/
|
|
120
127
|
interface JsonPatch {
|
|
121
128
|
op: PatchOp;
|
|
122
129
|
path: string;
|
|
130
|
+
/** Required for add, replace, test */
|
|
123
131
|
value?: unknown;
|
|
132
|
+
/** Required for move, copy (source location) */
|
|
133
|
+
from?: string;
|
|
124
134
|
}
|
|
125
135
|
/**
|
|
126
136
|
* Resolve a dynamic value against a data model
|
|
127
137
|
*/
|
|
128
138
|
declare function resolveDynamicValue<T>(value: DynamicValue<T>, dataModel: DataModel): T | undefined;
|
|
129
139
|
/**
|
|
130
|
-
* Get a value from an object by JSON Pointer path
|
|
140
|
+
* Get a value from an object by JSON Pointer path (RFC 6901)
|
|
131
141
|
*/
|
|
132
142
|
declare function getByPath(obj: unknown, path: string): unknown;
|
|
133
143
|
/**
|
|
134
|
-
* Set a value in an object by JSON Pointer path.
|
|
144
|
+
* Set a value in an object by JSON Pointer path (RFC 6901).
|
|
135
145
|
* Automatically creates arrays when the path segment is a numeric index.
|
|
136
146
|
*/
|
|
137
147
|
declare function setByPath(obj: Record<string, unknown>, path: string, value: unknown): void;
|
|
148
|
+
/**
|
|
149
|
+
* Add a value per RFC 6902 "add" semantics.
|
|
150
|
+
* For objects: create-or-replace the member.
|
|
151
|
+
* For arrays: insert before the given index, or append if "-".
|
|
152
|
+
*/
|
|
153
|
+
declare function addByPath(obj: Record<string, unknown>, path: string, value: unknown): void;
|
|
154
|
+
/**
|
|
155
|
+
* Remove a value per RFC 6902 "remove" semantics.
|
|
156
|
+
* For objects: delete the property.
|
|
157
|
+
* For arrays: splice out the element at the given index.
|
|
158
|
+
*/
|
|
159
|
+
declare function removeByPath(obj: Record<string, unknown>, path: string): void;
|
|
138
160
|
/**
|
|
139
161
|
* Find a form value from params and/or data.
|
|
140
162
|
* Useful in action handlers to locate form input values regardless of path format.
|
|
@@ -165,8 +187,12 @@ type SpecStreamLine = JsonPatch;
|
|
|
165
187
|
*/
|
|
166
188
|
declare function parseSpecStreamLine(line: string): SpecStreamLine | null;
|
|
167
189
|
/**
|
|
168
|
-
* Apply a single
|
|
190
|
+
* Apply a single RFC 6902 JSON Patch operation to an object.
|
|
169
191
|
* Mutates the object in place.
|
|
192
|
+
*
|
|
193
|
+
* Supports all six RFC 6902 operations: add, remove, replace, move, copy, test.
|
|
194
|
+
*
|
|
195
|
+
* @throws {Error} If a "test" operation fails (value mismatch).
|
|
170
196
|
*/
|
|
171
197
|
declare function applySpecStreamPatch<T extends Record<string, unknown>>(obj: T, patch: SpecStreamLine): T;
|
|
172
198
|
/**
|
|
@@ -174,8 +200,8 @@ declare function applySpecStreamPatch<T extends Record<string, unknown>>(obj: T,
|
|
|
174
200
|
* Each line should be a patch operation.
|
|
175
201
|
*
|
|
176
202
|
* @example
|
|
177
|
-
* const stream = `{"op":"
|
|
178
|
-
* {"op":"
|
|
203
|
+
* const stream = `{"op":"add","path":"/name","value":"Alice"}
|
|
204
|
+
* {"op":"add","path":"/age","value":30}`;
|
|
179
205
|
* const result = compileSpecStream(stream);
|
|
180
206
|
* // { name: "Alice", age: 30 }
|
|
181
207
|
*/
|
|
@@ -874,4 +900,4 @@ interface SystemPromptOptions {
|
|
|
874
900
|
*/
|
|
875
901
|
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
902
|
|
|
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 };
|
|
903
|
+
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 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 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, addByPath, applySpecStreamPatch, builtInValidationFunctions, check, compileSpecStream, createCatalog, createSpecStreamCompiler, defineCatalog, defineSchema, evaluateLogicExpression, evaluateVisibility, executeAction, findFormValue, generateCatalogPrompt, generateSystemPrompt, getByPath, interpolateString, parseSpecStreamLine, removeByPath, resolveAction, resolveDynamicValue, runValidation, runValidationCheck, setByPath, visibility };
|
package/dist/index.d.ts
CHANGED
|
@@ -37,19 +37,26 @@ declare const DynamicBooleanSchema: z.ZodUnion<readonly [z.ZodBoolean, z.ZodObje
|
|
|
37
37
|
* Base UI element structure for v2
|
|
38
38
|
*/
|
|
39
39
|
interface UIElement<T extends string = string, P = Record<string, unknown>> {
|
|
40
|
-
/** Unique key for reconciliation */
|
|
41
|
-
key: string;
|
|
42
40
|
/** Component type from the catalog */
|
|
43
41
|
type: T;
|
|
44
42
|
/** Component props */
|
|
45
43
|
props: P;
|
|
46
44
|
/** Child element keys (flat structure) */
|
|
47
45
|
children?: string[];
|
|
48
|
-
/** Parent element key (null for root) */
|
|
49
|
-
parentKey?: string | null;
|
|
50
46
|
/** Visibility condition */
|
|
51
47
|
visible?: VisibilityCondition;
|
|
52
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Element with key and parentKey for use with flatToTree.
|
|
51
|
+
* When elements are in an array (not a keyed map), key and parentKey
|
|
52
|
+
* are needed to establish identity and parent-child relationships.
|
|
53
|
+
*/
|
|
54
|
+
interface FlatElement<T extends string = string, P = Record<string, unknown>> extends UIElement<T, P> {
|
|
55
|
+
/** Unique key identifying this element */
|
|
56
|
+
key: string;
|
|
57
|
+
/** Parent element key (null for root) */
|
|
58
|
+
parentKey?: string | null;
|
|
59
|
+
}
|
|
53
60
|
/**
|
|
54
61
|
* Visibility condition types
|
|
55
62
|
*/
|
|
@@ -111,30 +118,45 @@ type ComponentSchema = z.ZodType<Record<string, unknown>>;
|
|
|
111
118
|
*/
|
|
112
119
|
type ValidationMode = "strict" | "warn" | "ignore";
|
|
113
120
|
/**
|
|
114
|
-
* JSON patch operation types
|
|
121
|
+
* JSON patch operation types (RFC 6902)
|
|
115
122
|
*/
|
|
116
|
-
type PatchOp = "add" | "remove" | "replace" | "
|
|
123
|
+
type PatchOp = "add" | "remove" | "replace" | "move" | "copy" | "test";
|
|
117
124
|
/**
|
|
118
|
-
* JSON patch operation
|
|
125
|
+
* JSON patch operation (RFC 6902)
|
|
119
126
|
*/
|
|
120
127
|
interface JsonPatch {
|
|
121
128
|
op: PatchOp;
|
|
122
129
|
path: string;
|
|
130
|
+
/** Required for add, replace, test */
|
|
123
131
|
value?: unknown;
|
|
132
|
+
/** Required for move, copy (source location) */
|
|
133
|
+
from?: string;
|
|
124
134
|
}
|
|
125
135
|
/**
|
|
126
136
|
* Resolve a dynamic value against a data model
|
|
127
137
|
*/
|
|
128
138
|
declare function resolveDynamicValue<T>(value: DynamicValue<T>, dataModel: DataModel): T | undefined;
|
|
129
139
|
/**
|
|
130
|
-
* Get a value from an object by JSON Pointer path
|
|
140
|
+
* Get a value from an object by JSON Pointer path (RFC 6901)
|
|
131
141
|
*/
|
|
132
142
|
declare function getByPath(obj: unknown, path: string): unknown;
|
|
133
143
|
/**
|
|
134
|
-
* Set a value in an object by JSON Pointer path.
|
|
144
|
+
* Set a value in an object by JSON Pointer path (RFC 6901).
|
|
135
145
|
* Automatically creates arrays when the path segment is a numeric index.
|
|
136
146
|
*/
|
|
137
147
|
declare function setByPath(obj: Record<string, unknown>, path: string, value: unknown): void;
|
|
148
|
+
/**
|
|
149
|
+
* Add a value per RFC 6902 "add" semantics.
|
|
150
|
+
* For objects: create-or-replace the member.
|
|
151
|
+
* For arrays: insert before the given index, or append if "-".
|
|
152
|
+
*/
|
|
153
|
+
declare function addByPath(obj: Record<string, unknown>, path: string, value: unknown): void;
|
|
154
|
+
/**
|
|
155
|
+
* Remove a value per RFC 6902 "remove" semantics.
|
|
156
|
+
* For objects: delete the property.
|
|
157
|
+
* For arrays: splice out the element at the given index.
|
|
158
|
+
*/
|
|
159
|
+
declare function removeByPath(obj: Record<string, unknown>, path: string): void;
|
|
138
160
|
/**
|
|
139
161
|
* Find a form value from params and/or data.
|
|
140
162
|
* Useful in action handlers to locate form input values regardless of path format.
|
|
@@ -165,8 +187,12 @@ type SpecStreamLine = JsonPatch;
|
|
|
165
187
|
*/
|
|
166
188
|
declare function parseSpecStreamLine(line: string): SpecStreamLine | null;
|
|
167
189
|
/**
|
|
168
|
-
* Apply a single
|
|
190
|
+
* Apply a single RFC 6902 JSON Patch operation to an object.
|
|
169
191
|
* Mutates the object in place.
|
|
192
|
+
*
|
|
193
|
+
* Supports all six RFC 6902 operations: add, remove, replace, move, copy, test.
|
|
194
|
+
*
|
|
195
|
+
* @throws {Error} If a "test" operation fails (value mismatch).
|
|
170
196
|
*/
|
|
171
197
|
declare function applySpecStreamPatch<T extends Record<string, unknown>>(obj: T, patch: SpecStreamLine): T;
|
|
172
198
|
/**
|
|
@@ -174,8 +200,8 @@ declare function applySpecStreamPatch<T extends Record<string, unknown>>(obj: T,
|
|
|
174
200
|
* Each line should be a patch operation.
|
|
175
201
|
*
|
|
176
202
|
* @example
|
|
177
|
-
* const stream = `{"op":"
|
|
178
|
-
* {"op":"
|
|
203
|
+
* const stream = `{"op":"add","path":"/name","value":"Alice"}
|
|
204
|
+
* {"op":"add","path":"/age","value":30}`;
|
|
179
205
|
* const result = compileSpecStream(stream);
|
|
180
206
|
* // { name: "Alice", age: 30 }
|
|
181
207
|
*/
|
|
@@ -874,4 +900,4 @@ interface SystemPromptOptions {
|
|
|
874
900
|
*/
|
|
875
901
|
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
902
|
|
|
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 };
|
|
903
|
+
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 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 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, addByPath, applySpecStreamPatch, builtInValidationFunctions, check, compileSpecStream, createCatalog, createSpecStreamCompiler, defineCatalog, defineSchema, evaluateLogicExpression, evaluateVisibility, executeAction, findFormValue, generateCatalogPrompt, generateSystemPrompt, getByPath, interpolateString, parseSpecStreamLine, removeByPath, resolveAction, resolveDynamicValue, runValidation, runValidationCheck, setByPath, visibility };
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ __export(index_exports, {
|
|
|
33
33
|
ValidationConfigSchema: () => ValidationConfigSchema,
|
|
34
34
|
VisibilityConditionSchema: () => VisibilityConditionSchema,
|
|
35
35
|
action: () => action,
|
|
36
|
+
addByPath: () => addByPath,
|
|
36
37
|
applySpecStreamPatch: () => applySpecStreamPatch,
|
|
37
38
|
builtInValidationFunctions: () => builtInValidationFunctions,
|
|
38
39
|
check: () => check,
|
|
@@ -50,6 +51,7 @@ __export(index_exports, {
|
|
|
50
51
|
getByPath: () => getByPath,
|
|
51
52
|
interpolateString: () => interpolateString,
|
|
52
53
|
parseSpecStreamLine: () => parseSpecStreamLine,
|
|
54
|
+
removeByPath: () => removeByPath,
|
|
53
55
|
resolveAction: () => resolveAction,
|
|
54
56
|
resolveDynamicValue: () => resolveDynamicValue,
|
|
55
57
|
runValidation: () => runValidation,
|
|
@@ -89,17 +91,27 @@ function resolveDynamicValue(value, dataModel) {
|
|
|
89
91
|
}
|
|
90
92
|
return value;
|
|
91
93
|
}
|
|
94
|
+
function unescapeJsonPointer(token) {
|
|
95
|
+
return token.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
96
|
+
}
|
|
97
|
+
function parseJsonPointer(path) {
|
|
98
|
+
const raw = path.startsWith("/") ? path.slice(1).split("/") : path.split("/");
|
|
99
|
+
return raw.map(unescapeJsonPointer);
|
|
100
|
+
}
|
|
92
101
|
function getByPath(obj, path) {
|
|
93
102
|
if (!path || path === "/") {
|
|
94
103
|
return obj;
|
|
95
104
|
}
|
|
96
|
-
const segments =
|
|
105
|
+
const segments = parseJsonPointer(path);
|
|
97
106
|
let current = obj;
|
|
98
107
|
for (const segment of segments) {
|
|
99
108
|
if (current === null || current === void 0) {
|
|
100
109
|
return void 0;
|
|
101
110
|
}
|
|
102
|
-
if (
|
|
111
|
+
if (Array.isArray(current)) {
|
|
112
|
+
const index = parseInt(segment, 10);
|
|
113
|
+
current = current[index];
|
|
114
|
+
} else if (typeof current === "object") {
|
|
103
115
|
current = current[segment];
|
|
104
116
|
} else {
|
|
105
117
|
return void 0;
|
|
@@ -111,13 +123,13 @@ function isNumericIndex(str) {
|
|
|
111
123
|
return /^\d+$/.test(str);
|
|
112
124
|
}
|
|
113
125
|
function setByPath(obj, path, value) {
|
|
114
|
-
const segments =
|
|
126
|
+
const segments = parseJsonPointer(path);
|
|
115
127
|
if (segments.length === 0) return;
|
|
116
128
|
let current = obj;
|
|
117
129
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
118
130
|
const segment = segments[i];
|
|
119
131
|
const nextSegment = segments[i + 1];
|
|
120
|
-
const nextIsNumeric = nextSegment !== void 0 && isNumericIndex(nextSegment);
|
|
132
|
+
const nextIsNumeric = nextSegment !== void 0 && (isNumericIndex(nextSegment) || nextSegment === "-");
|
|
121
133
|
if (Array.isArray(current)) {
|
|
122
134
|
const index = parseInt(segment, 10);
|
|
123
135
|
if (current[index] === void 0 || typeof current[index] !== "object") {
|
|
@@ -133,12 +145,95 @@ function setByPath(obj, path, value) {
|
|
|
133
145
|
}
|
|
134
146
|
const lastSegment = segments[segments.length - 1];
|
|
135
147
|
if (Array.isArray(current)) {
|
|
136
|
-
|
|
137
|
-
|
|
148
|
+
if (lastSegment === "-") {
|
|
149
|
+
current.push(value);
|
|
150
|
+
} else {
|
|
151
|
+
const index = parseInt(lastSegment, 10);
|
|
152
|
+
current[index] = value;
|
|
153
|
+
}
|
|
154
|
+
} else {
|
|
155
|
+
current[lastSegment] = value;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function addByPath(obj, path, value) {
|
|
159
|
+
const segments = parseJsonPointer(path);
|
|
160
|
+
if (segments.length === 0) return;
|
|
161
|
+
let current = obj;
|
|
162
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
163
|
+
const segment = segments[i];
|
|
164
|
+
const nextSegment = segments[i + 1];
|
|
165
|
+
const nextIsNumeric = nextSegment !== void 0 && (isNumericIndex(nextSegment) || nextSegment === "-");
|
|
166
|
+
if (Array.isArray(current)) {
|
|
167
|
+
const index = parseInt(segment, 10);
|
|
168
|
+
if (current[index] === void 0 || typeof current[index] !== "object") {
|
|
169
|
+
current[index] = nextIsNumeric ? [] : {};
|
|
170
|
+
}
|
|
171
|
+
current = current[index];
|
|
172
|
+
} else {
|
|
173
|
+
if (!(segment in current) || typeof current[segment] !== "object") {
|
|
174
|
+
current[segment] = nextIsNumeric ? [] : {};
|
|
175
|
+
}
|
|
176
|
+
current = current[segment];
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const lastSegment = segments[segments.length - 1];
|
|
180
|
+
if (Array.isArray(current)) {
|
|
181
|
+
if (lastSegment === "-") {
|
|
182
|
+
current.push(value);
|
|
183
|
+
} else {
|
|
184
|
+
const index = parseInt(lastSegment, 10);
|
|
185
|
+
current.splice(index, 0, value);
|
|
186
|
+
}
|
|
138
187
|
} else {
|
|
139
188
|
current[lastSegment] = value;
|
|
140
189
|
}
|
|
141
190
|
}
|
|
191
|
+
function removeByPath(obj, path) {
|
|
192
|
+
const segments = parseJsonPointer(path);
|
|
193
|
+
if (segments.length === 0) return;
|
|
194
|
+
let current = obj;
|
|
195
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
196
|
+
const segment = segments[i];
|
|
197
|
+
if (Array.isArray(current)) {
|
|
198
|
+
const index = parseInt(segment, 10);
|
|
199
|
+
if (current[index] === void 0 || typeof current[index] !== "object") {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
current = current[index];
|
|
203
|
+
} else {
|
|
204
|
+
if (!(segment in current) || typeof current[segment] !== "object") {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
current = current[segment];
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const lastSegment = segments[segments.length - 1];
|
|
211
|
+
if (Array.isArray(current)) {
|
|
212
|
+
const index = parseInt(lastSegment, 10);
|
|
213
|
+
if (index >= 0 && index < current.length) {
|
|
214
|
+
current.splice(index, 1);
|
|
215
|
+
}
|
|
216
|
+
} else {
|
|
217
|
+
delete current[lastSegment];
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function deepEqual(a, b) {
|
|
221
|
+
if (a === b) return true;
|
|
222
|
+
if (a === null || b === null) return false;
|
|
223
|
+
if (typeof a !== typeof b) return false;
|
|
224
|
+
if (typeof a !== "object") return false;
|
|
225
|
+
if (Array.isArray(a)) {
|
|
226
|
+
if (!Array.isArray(b)) return false;
|
|
227
|
+
if (a.length !== b.length) return false;
|
|
228
|
+
return a.every((item, i) => deepEqual(item, b[i]));
|
|
229
|
+
}
|
|
230
|
+
const aObj = a;
|
|
231
|
+
const bObj = b;
|
|
232
|
+
const aKeys = Object.keys(aObj);
|
|
233
|
+
const bKeys = Object.keys(bObj);
|
|
234
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
235
|
+
return aKeys.every((key) => deepEqual(aObj[key], bObj[key]));
|
|
236
|
+
}
|
|
142
237
|
function findFormValue(fieldName, params, data) {
|
|
143
238
|
if (params?.[fieldName] !== void 0) {
|
|
144
239
|
const val = params[fieldName];
|
|
@@ -187,10 +282,38 @@ function parseSpecStreamLine(line) {
|
|
|
187
282
|
}
|
|
188
283
|
}
|
|
189
284
|
function applySpecStreamPatch(obj, patch) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
285
|
+
switch (patch.op) {
|
|
286
|
+
case "add":
|
|
287
|
+
addByPath(obj, patch.path, patch.value);
|
|
288
|
+
break;
|
|
289
|
+
case "replace":
|
|
290
|
+
setByPath(obj, patch.path, patch.value);
|
|
291
|
+
break;
|
|
292
|
+
case "remove":
|
|
293
|
+
removeByPath(obj, patch.path);
|
|
294
|
+
break;
|
|
295
|
+
case "move": {
|
|
296
|
+
if (!patch.from) break;
|
|
297
|
+
const moveValue = getByPath(obj, patch.from);
|
|
298
|
+
removeByPath(obj, patch.from);
|
|
299
|
+
addByPath(obj, patch.path, moveValue);
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
case "copy": {
|
|
303
|
+
if (!patch.from) break;
|
|
304
|
+
const copyValue = getByPath(obj, patch.from);
|
|
305
|
+
addByPath(obj, patch.path, copyValue);
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
case "test": {
|
|
309
|
+
const actual = getByPath(obj, patch.path);
|
|
310
|
+
if (!deepEqual(actual, patch.value)) {
|
|
311
|
+
throw new Error(
|
|
312
|
+
`Test operation failed: value at "${patch.path}" does not match`
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
194
317
|
}
|
|
195
318
|
return obj;
|
|
196
319
|
}
|
|
@@ -933,10 +1056,10 @@ function generatePrompt(catalog, options) {
|
|
|
933
1056
|
lines.push("");
|
|
934
1057
|
lines.push("Example output (each line is a separate JSON object):");
|
|
935
1058
|
lines.push("");
|
|
936
|
-
lines.push(`{"op":"
|
|
937
|
-
{"op":"
|
|
938
|
-
{"op":"
|
|
939
|
-
{"op":"
|
|
1059
|
+
lines.push(`{"op":"add","path":"/root","value":"card-1"}
|
|
1060
|
+
{"op":"add","path":"/elements/card-1","value":{"type":"Card","props":{"title":"Dashboard"},"children":["metric-1","chart-1"]}}
|
|
1061
|
+
{"op":"add","path":"/elements/metric-1","value":{"type":"Metric","props":{"label":"Revenue","valuePath":"analytics.revenue","format":"currency"},"children":[]}}
|
|
1062
|
+
{"op":"add","path":"/elements/chart-1","value":{"type":"Chart","props":{"type":"bar","dataPath":"analytics.salesByRegion"},"children":[]}}`);
|
|
940
1063
|
lines.push("");
|
|
941
1064
|
const components = catalog.data.components;
|
|
942
1065
|
if (components) {
|
|
@@ -963,12 +1086,11 @@ function generatePrompt(catalog, options) {
|
|
|
963
1086
|
lines.push("RULES:");
|
|
964
1087
|
const baseRules = [
|
|
965
1088
|
"Output ONLY JSONL patches - one JSON object per line, no markdown, no code fences",
|
|
966
|
-
'First line sets root: {"op":"
|
|
967
|
-
'Then add each element: {"op":"
|
|
1089
|
+
'First line sets root: {"op":"add","path":"/root","value":"<root-key>"}',
|
|
1090
|
+
'Then add each element: {"op":"add","path":"/elements/<key>","value":{...}}',
|
|
968
1091
|
"ONLY use components listed above",
|
|
969
|
-
"Each element value needs:
|
|
970
|
-
"Use unique keys (e.g., 'header', 'metric-1', 'chart-revenue')"
|
|
971
|
-
"Root element's parentKey is empty string, children reference their parent's key"
|
|
1092
|
+
"Each element value needs: type, props, children (array of child keys)",
|
|
1093
|
+
"Use unique keys for the element map entries (e.g., 'header', 'metric-1', 'chart-revenue')"
|
|
972
1094
|
];
|
|
973
1095
|
const allRules = [...baseRules, ...customRules];
|
|
974
1096
|
allRules.forEach((rule, i) => {
|
|
@@ -1124,22 +1246,18 @@ function createCatalog(config) {
|
|
|
1124
1246
|
const componentSchemas = componentNames.map((componentName) => {
|
|
1125
1247
|
const def = components[componentName];
|
|
1126
1248
|
return import_zod6.z.object({
|
|
1127
|
-
key: import_zod6.z.string(),
|
|
1128
1249
|
type: import_zod6.z.literal(componentName),
|
|
1129
1250
|
props: def.props,
|
|
1130
1251
|
children: import_zod6.z.array(import_zod6.z.string()).optional(),
|
|
1131
|
-
parentKey: import_zod6.z.string().nullable().optional(),
|
|
1132
1252
|
visible: VisibilityConditionSchema.optional()
|
|
1133
1253
|
});
|
|
1134
1254
|
});
|
|
1135
1255
|
let elementSchema;
|
|
1136
1256
|
if (componentSchemas.length === 0) {
|
|
1137
1257
|
elementSchema = import_zod6.z.object({
|
|
1138
|
-
key: import_zod6.z.string(),
|
|
1139
1258
|
type: import_zod6.z.string(),
|
|
1140
1259
|
props: import_zod6.z.record(import_zod6.z.string(), import_zod6.z.unknown()),
|
|
1141
1260
|
children: import_zod6.z.array(import_zod6.z.string()).optional(),
|
|
1142
|
-
parentKey: import_zod6.z.string().nullable().optional(),
|
|
1143
1261
|
visible: VisibilityConditionSchema.optional()
|
|
1144
1262
|
});
|
|
1145
1263
|
} else if (componentSchemas.length === 1) {
|
|
@@ -1360,21 +1478,21 @@ function generateSystemPrompt(catalog, options = {}) {
|
|
|
1360
1478
|
}
|
|
1361
1479
|
lines.push("");
|
|
1362
1480
|
}
|
|
1363
|
-
lines.push("OUTPUT FORMAT (JSONL):");
|
|
1364
|
-
lines.push('{"op":"
|
|
1481
|
+
lines.push("OUTPUT FORMAT (JSONL, RFC 6902 JSON Patch):");
|
|
1482
|
+
lines.push('{"op":"add","path":"/root","value":"element-key"}');
|
|
1365
1483
|
lines.push(
|
|
1366
|
-
'{"op":"add","path":"/elements/key","value":{"
|
|
1484
|
+
'{"op":"add","path":"/elements/key","value":{"type":"...","props":{...},"children":[...]}}'
|
|
1367
1485
|
);
|
|
1368
1486
|
lines.push('{"op":"remove","path":"/elements/key"}');
|
|
1369
1487
|
lines.push("");
|
|
1370
1488
|
lines.push("RULES:");
|
|
1371
1489
|
const baseRules = [
|
|
1372
|
-
|
|
1373
|
-
|
|
1490
|
+
'First line sets /root to root element key: {"op":"add","path":"/root","value":"<key>"}',
|
|
1491
|
+
'Add elements with /elements/{key}: {"op":"add","path":"/elements/<key>","value":{...}}',
|
|
1374
1492
|
"Remove elements with op:remove - also update the parent's children array to exclude the removed key",
|
|
1375
1493
|
"Children array contains string keys, not objects",
|
|
1376
1494
|
"Parent first, then children",
|
|
1377
|
-
"Each element needs:
|
|
1495
|
+
"Each element needs: type, props",
|
|
1378
1496
|
"ONLY use props listed above - never invent new props"
|
|
1379
1497
|
];
|
|
1380
1498
|
const allRules = [...baseRules, ...customRules];
|
|
@@ -1405,6 +1523,7 @@ function generateSystemPrompt(catalog, options = {}) {
|
|
|
1405
1523
|
ValidationConfigSchema,
|
|
1406
1524
|
VisibilityConditionSchema,
|
|
1407
1525
|
action,
|
|
1526
|
+
addByPath,
|
|
1408
1527
|
applySpecStreamPatch,
|
|
1409
1528
|
builtInValidationFunctions,
|
|
1410
1529
|
check,
|
|
@@ -1422,6 +1541,7 @@ function generateSystemPrompt(catalog, options = {}) {
|
|
|
1422
1541
|
getByPath,
|
|
1423
1542
|
interpolateString,
|
|
1424
1543
|
parseSpecStreamLine,
|
|
1544
|
+
removeByPath,
|
|
1425
1545
|
resolveAction,
|
|
1426
1546
|
resolveDynamicValue,
|
|
1427
1547
|
runValidation,
|