@kubuild/schema 0.1.0 → 0.3.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.cjs CHANGED
@@ -20,103 +20,472 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ ACTION_PIPELINE_JSON_SCHEMA_V1: () => ACTION_PIPELINE_JSON_SCHEMA_V1,
24
+ ARTBOARD_REFERENCE_NODE_TYPE: () => ARTBOARD_REFERENCE_NODE_TYPE,
23
25
  ActionBindingSchema: () => ActionBindingSchema,
26
+ ActionPipelineSchema: () => ActionPipelineSchema,
27
+ ActionStepConditionSchema: () => ActionStepConditionSchema,
28
+ ActionStepSchema: () => ActionStepSchema,
29
+ ActionStepTypeSchema: () => ActionStepTypeSchema,
30
+ ActionTriggerSchema: () => ActionTriggerSchema,
31
+ ActionTriggerTypeSchema: () => ActionTriggerTypeSchema,
24
32
  AnimationConfigSchema: () => AnimationConfigSchema,
33
+ ApiRequestStepPayloadSchema: () => ApiRequestStepPayloadSchema,
34
+ ArtboardSchema: () => ArtboardSchema,
35
+ ArtboardTypeSchema: () => ArtboardTypeSchema,
25
36
  AssetReferenceSchema: () => AssetReferenceSchema,
37
+ CURRENT_PROJECT_SCHEMA_VERSION: () => CURRENT_PROJECT_SCHEMA_VERSION,
26
38
  CURRENT_SCHEMA_VERSION: () => CURRENT_SCHEMA_VERSION,
39
+ CloseModalStepPayloadSchema: () => CloseModalStepPayloadSchema,
40
+ ConditionOperatorSchema: () => ConditionOperatorSchema,
41
+ CopyClipboardStepPayloadSchema: () => CopyClipboardStepPayloadSchema,
42
+ CustomEventStepPayloadSchema: () => CustomEventStepPayloadSchema,
27
43
  DEFAULT_ANIMATION_CONFIG: () => DEFAULT_ANIMATION_CONFIG,
28
44
  DocumentMetadataSchema: () => DocumentMetadataSchema,
45
+ FORM_CONFIG_JSON_SCHEMA_V1: () => FORM_CONFIG_JSON_SCHEMA_V1,
46
+ FORM_FIELD_BINDING_JSON_SCHEMA_V1: () => FORM_FIELD_BINDING_JSON_SCHEMA_V1,
47
+ FormConfigSchema: () => FormConfigSchema,
48
+ FormFieldBindingSchema: () => FormFieldBindingSchema,
29
49
  MANIFEST_JSON_SCHEMA_V1: () => MANIFEST_JSON_SCHEMA_V1,
30
50
  ManifestAssetItemSchema: () => ManifestAssetItemSchema,
31
51
  ManifestSchema: () => ManifestSchema,
52
+ NavigateStepPayloadSchema: () => NavigateStepPayloadSchema,
32
53
  NodeSchema: () => NodeSchema,
54
+ OpenModalStepPayloadSchema: () => OpenModalStepPayloadSchema,
33
55
  PAGE_DOCUMENT_JSON_SCHEMA_V1: () => PAGE_DOCUMENT_JSON_SCHEMA_V1,
56
+ PROJECT_SCHEMA_NAME: () => PROJECT_SCHEMA_NAME,
34
57
  PageDocumentSchema: () => PageDocumentSchema,
58
+ ProjectDocumentSchema: () => ProjectDocumentSchema,
35
59
  PseudoStateStylesSchema: () => PseudoStateStylesSchema,
60
+ ResetFormStepPayloadSchema: () => ResetFormStepPayloadSchema,
36
61
  ResponsiveStylesSchema: () => ResponsiveStylesSchema,
37
62
  RootPageNodeSchema: () => RootPageNodeSchema,
38
63
  SCHEMA_NAME: () => SCHEMA_NAME,
39
64
  SafeThumbnailObjectSchema: () => SafeThumbnailObjectSchema,
40
65
  SafeThumbnailSchema: () => SafeThumbnailSchema,
41
66
  SafeThumbnailUrlSchema: () => SafeThumbnailUrlSchema,
67
+ SetStateStepPayloadSchema: () => SetStateStepPayloadSchema,
68
+ ShowToastStepPayloadSchema: () => ShowToastStepPayloadSchema,
69
+ StepPayloadSchemas: () => StepPayloadSchemas,
42
70
  StyleDefinitionSchema: () => StyleDefinitionSchema,
43
71
  StyleValueSchema: () => StyleValueSchema,
44
72
  TEMPLATE_RECORD_JSON_SCHEMA_V1: () => TEMPLATE_RECORD_JSON_SCHEMA_V1,
45
73
  TemplatePackageRefSchema: () => TemplatePackageRefSchema,
46
74
  TemplateRecordSchema: () => TemplateRecordSchema,
47
75
  TemplateRequirementsSchema: () => TemplateRequirementsSchema,
76
+ ValidateOnEventSchema: () => ValidateOnEventSchema,
77
+ ValidationRuleSchema: () => ValidationRuleSchema,
78
+ ValidationRuleTypeSchema: () => ValidationRuleTypeSchema,
48
79
  VariableBindingSchema: () => VariableBindingSchema,
49
80
  collectNodeIds: () => collectNodeIds,
50
81
  generateDeterministicNodeId: () => generateDeterministicNodeId,
82
+ getActionPipelineJsonSchema: () => getActionPipelineJsonSchema,
83
+ getFormConfigJsonSchema: () => getFormConfigJsonSchema,
84
+ getFormFieldBindingJsonSchema: () => getFormFieldBindingJsonSchema,
51
85
  getManifestJsonSchema: () => getManifestJsonSchema,
52
86
  getPageDocumentJsonSchema: () => getPageDocumentJsonSchema,
53
87
  getTemplateRecordJsonSchema: () => getTemplateRecordJsonSchema,
54
88
  isActionBinding: () => isActionBinding,
89
+ isActionPipeline: () => isActionPipeline,
90
+ isActionStep: () => isActionStep,
91
+ isActionStepCondition: () => isActionStepCondition,
92
+ isActionStepType: () => isActionStepType,
93
+ isActionTriggerType: () => isActionTriggerType,
55
94
  isAnimationConfig: () => isAnimationConfig,
95
+ isArtboardReferenceNode: () => isArtboardReferenceNode,
56
96
  isAssetReference: () => isAssetReference,
97
+ isConditionOperator: () => isConditionOperator,
98
+ isFormConfig: () => isFormConfig,
99
+ isFormFieldBinding: () => isFormFieldBinding,
57
100
  isManifest: () => isManifest,
101
+ isProjectDocument: () => isProjectDocument,
102
+ isSafeActionUrl: () => isSafeActionUrl,
58
103
  isSafeThumbnail: () => isSafeThumbnail,
59
104
  isSafeThumbnailUrl: () => isSafeThumbnailUrl,
60
105
  isTemplateRecord: () => isTemplateRecord,
106
+ isValidateOnEvent: () => isValidateOnEvent,
107
+ isValidationRule: () => isValidationRule,
108
+ isValidationRuleType: () => isValidationRuleType,
61
109
  isVariableBinding: () => isVariableBinding,
110
+ looksLikeProjectDocument: () => looksLikeProjectDocument,
111
+ sanitizeActionPayload: () => sanitizeActionPayload,
112
+ sanitizeActionPipeline: () => sanitizeActionPipeline,
113
+ sanitizeActionStep: () => sanitizeActionStep,
114
+ sanitizeActionString: () => sanitizeActionString,
115
+ sanitizeActionUrl: () => sanitizeActionUrl,
116
+ sanitizeActionValue: () => sanitizeActionValue,
62
117
  starterPageFixture: () => starterPageFixture,
118
+ validateActionStepPayload: () => validateActionStepPayload,
63
119
  validateNodeIdUniqueness: () => validateNodeIdUniqueness
64
120
  });
65
121
  module.exports = __toCommonJS(index_exports);
66
122
 
67
123
  // src/document.ts
124
+ var import_zod3 = require("zod");
125
+
126
+ // src/actions.ts
68
127
  var import_zod = require("zod");
128
+ var ActionTriggerTypeSchema = import_zod.z.enum([
129
+ "click",
130
+ "submit",
131
+ "change",
132
+ "blur",
133
+ "focus",
134
+ "load"
135
+ ]);
136
+ var ActionTriggerSchema = ActionTriggerTypeSchema;
137
+ var ActionStepTypeSchema = import_zod.z.enum([
138
+ "api_request",
139
+ "navigate",
140
+ "set_state",
141
+ "reset_form",
142
+ "show_toast",
143
+ "open_modal",
144
+ "close_modal",
145
+ "copy_clipboard",
146
+ "custom_event"
147
+ ]);
148
+ var ConditionOperatorSchema = import_zod.z.enum([
149
+ "equals",
150
+ "not_equals",
151
+ "contains",
152
+ "not_contains",
153
+ "is_truthy",
154
+ "is_falsy",
155
+ "gt",
156
+ "gte",
157
+ "lt",
158
+ "lte",
159
+ "regex"
160
+ ]);
161
+ var ActionStepConditionSchema = import_zod.z.object({
162
+ field: import_zod.z.string().min(1, "Condition field cannot be empty"),
163
+ operator: ConditionOperatorSchema,
164
+ value: import_zod.z.unknown().optional()
165
+ });
166
+ var DANGEROUS_URL_PATTERN = /(javascript:|vbscript:|data:text\/html)/i;
167
+ var DANGEROUS_SCRIPT_PATTERN = /<\s*script/i;
168
+ function isSafeActionUrl(url) {
169
+ if (!url || typeof url !== "string") return false;
170
+ const trimmed = url.trim();
171
+ if (DANGEROUS_URL_PATTERN.test(trimmed)) return false;
172
+ if (DANGEROUS_SCRIPT_PATTERN.test(trimmed)) return false;
173
+ return true;
174
+ }
175
+ var SafeUrlStringSchema = import_zod.z.string().min(1, "URL cannot be empty").refine(isSafeActionUrl, {
176
+ message: "URL contains disallowed or unsafe protocol/script pattern"
177
+ });
178
+ var SafeEventNameSchema = import_zod.z.string().min(1, "Event name cannot be empty").regex(/^[a-zA-Z0-9_\-:]+$/, {
179
+ message: "Event name must contain only alphanumeric characters, dashes, colons, or underscores"
180
+ });
181
+ var ApiRequestStepPayloadSchema = import_zod.z.object({
182
+ url: SafeUrlStringSchema,
183
+ method: import_zod.z.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]).default("GET"),
184
+ headers: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional(),
185
+ queryParams: import_zod.z.record(import_zod.z.string(), import_zod.z.union([import_zod.z.string(), import_zod.z.number(), import_zod.z.boolean()])).optional(),
186
+ body: import_zod.z.union([import_zod.z.string(), import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()), import_zod.z.array(import_zod.z.unknown())]).optional(),
187
+ bodyFormat: import_zod.z.enum(["json", "form-data", "formData", "urlencoded", "url-encoded", "raw", "text"]).optional(),
188
+ bodyType: import_zod.z.enum(["json", "form-data", "formData", "urlencoded", "url-encoded", "raw", "text"]).optional(),
189
+ timeout: import_zod.z.number().positive("Timeout must be greater than 0 ms").optional(),
190
+ responseMapping: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional()
191
+ });
192
+ var NavigateStepPayloadSchema = import_zod.z.object({
193
+ url: SafeUrlStringSchema,
194
+ target: import_zod.z.enum(["_self", "_blank", "_parent", "_top"]).optional().default("_self"),
195
+ replace: import_zod.z.boolean().optional(),
196
+ scroll: import_zod.z.boolean().optional(),
197
+ behavior: import_zod.z.enum(["smooth", "auto"]).optional()
198
+ });
199
+ var SetStateStepPayloadSchema = import_zod.z.object({
200
+ key: import_zod.z.string().min(1, "State key cannot be empty"),
201
+ value: import_zod.z.unknown(),
202
+ scope: import_zod.z.enum(["runtime", "document", "session", "local"]).optional().default("runtime")
203
+ });
204
+ var ResetFormStepPayloadSchema = import_zod.z.object({
205
+ formId: import_zod.z.string().optional()
206
+ });
207
+ var ShowToastStepPayloadSchema = import_zod.z.object({
208
+ message: import_zod.z.string().min(1, "Toast message cannot be empty"),
209
+ type: import_zod.z.enum(["success", "error", "warning", "info"]).optional().default("info"),
210
+ variant: import_zod.z.enum(["success", "error", "warning", "info"]).optional(),
211
+ title: import_zod.z.string().optional(),
212
+ duration: import_zod.z.number().nonnegative("Duration must be >= 0 ms").optional(),
213
+ position: import_zod.z.enum(["top-right", "top-left", "bottom-right", "bottom-left", "top-center", "bottom-center"]).optional()
214
+ });
215
+ var OpenModalStepPayloadSchema = import_zod.z.object({
216
+ modalId: import_zod.z.string().optional(),
217
+ modalNodeId: import_zod.z.string().optional(),
218
+ toggle: import_zod.z.boolean().optional()
219
+ }).refine((data) => Boolean(data.modalId || data.modalNodeId), {
220
+ message: "Modal ID or Modal Node ID cannot be empty"
221
+ });
222
+ var CloseModalStepPayloadSchema = import_zod.z.object({
223
+ modalId: import_zod.z.string().optional(),
224
+ modalNodeId: import_zod.z.string().optional()
225
+ });
226
+ var CopyClipboardStepPayloadSchema = import_zod.z.object({
227
+ text: import_zod.z.string().optional(),
228
+ value: import_zod.z.unknown().optional(),
229
+ notify: import_zod.z.boolean().optional(),
230
+ toastMessage: import_zod.z.string().optional()
231
+ });
232
+ var CustomEventStepPayloadSchema = import_zod.z.object({
233
+ eventName: SafeEventNameSchema,
234
+ detail: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional(),
235
+ bubbles: import_zod.z.boolean().optional().default(true),
236
+ cancelable: import_zod.z.boolean().optional().default(true)
237
+ });
238
+ var StepPayloadSchemas = {
239
+ api_request: ApiRequestStepPayloadSchema,
240
+ navigate: NavigateStepPayloadSchema,
241
+ set_state: SetStateStepPayloadSchema,
242
+ reset_form: ResetFormStepPayloadSchema,
243
+ show_toast: ShowToastStepPayloadSchema,
244
+ open_modal: OpenModalStepPayloadSchema,
245
+ close_modal: CloseModalStepPayloadSchema,
246
+ copy_clipboard: CopyClipboardStepPayloadSchema,
247
+ custom_event: CustomEventStepPayloadSchema
248
+ };
249
+ var ActionStepSchema = import_zod.z.lazy(
250
+ () => import_zod.z.object({
251
+ id: import_zod.z.string().min(1, "Step ID cannot be empty"),
252
+ type: ActionStepTypeSchema,
253
+ label: import_zod.z.string().optional(),
254
+ payload: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional().default({}),
255
+ condition: ActionStepConditionSchema.optional(),
256
+ timeout: import_zod.z.number().positive().optional(),
257
+ continueOnError: import_zod.z.boolean().optional(),
258
+ onSuccess: import_zod.z.array(ActionStepSchema).optional(),
259
+ onError: import_zod.z.array(ActionStepSchema).optional()
260
+ })
261
+ );
262
+ var ActionPipelineSchema = import_zod.z.object({
263
+ id: import_zod.z.string().min(1, "Pipeline ID cannot be empty"),
264
+ trigger: ActionTriggerTypeSchema,
265
+ label: import_zod.z.string().optional(),
266
+ debounceMs: import_zod.z.number().nonnegative("Debounce ms must be >= 0").optional(),
267
+ preventDuplicate: import_zod.z.boolean().optional(),
268
+ enabled: import_zod.z.boolean().optional().default(true),
269
+ steps: import_zod.z.array(ActionStepSchema).min(1, "Action pipeline must contain at least one step")
270
+ });
271
+ function isActionTriggerType(value) {
272
+ return ActionTriggerTypeSchema.safeParse(value).success;
273
+ }
274
+ function isActionStepType(value) {
275
+ return ActionStepTypeSchema.safeParse(value).success;
276
+ }
277
+ function isConditionOperator(value) {
278
+ return ConditionOperatorSchema.safeParse(value).success;
279
+ }
280
+ function isActionStepCondition(value) {
281
+ return ActionStepConditionSchema.safeParse(value).success;
282
+ }
283
+ function isActionStep(value) {
284
+ return ActionStepSchema.safeParse(value).success;
285
+ }
286
+ function isActionPipeline(value) {
287
+ return ActionPipelineSchema.safeParse(value).success;
288
+ }
289
+ function validateActionStepPayload(type, payload) {
290
+ const schema = StepPayloadSchemas[type];
291
+ if (!schema) {
292
+ return {
293
+ success: false,
294
+ error: new import_zod.z.ZodError([
295
+ {
296
+ code: import_zod.z.ZodIssueCode.custom,
297
+ message: `Unknown step type: ${type}`,
298
+ path: ["type"]
299
+ }
300
+ ])
301
+ };
302
+ }
303
+ const result = schema.safeParse(payload);
304
+ if (result.success) {
305
+ return { success: true, data: result.data };
306
+ }
307
+ return { success: false, error: result.error };
308
+ }
309
+ function sanitizeActionUrl(url, fallback = "") {
310
+ if (typeof url !== "string") return fallback;
311
+ const trimmed = url.trim();
312
+ if (!isSafeActionUrl(trimmed)) {
313
+ return fallback;
314
+ }
315
+ return trimmed;
316
+ }
317
+ function sanitizeActionString(value, fallback = "") {
318
+ if (typeof value !== "string") return fallback;
319
+ if (DANGEROUS_SCRIPT_PATTERN.test(value)) {
320
+ return value.replace(/<\s*script[^>]*>[\s\S]*?<\s*\/\s*script\s*>/gi, "").replace(/<\s*script[^>]*>/gi, "");
321
+ }
322
+ return value;
323
+ }
324
+ function sanitizeActionValue(value) {
325
+ if (value === null || value === void 0) return value;
326
+ if (typeof value === "string") {
327
+ const trimmed = value.trim();
328
+ if (DANGEROUS_URL_PATTERN.test(trimmed)) {
329
+ return "";
330
+ }
331
+ return sanitizeActionString(value);
332
+ }
333
+ if (Array.isArray(value)) {
334
+ return value.map((item) => sanitizeActionValue(item));
335
+ }
336
+ if (typeof value === "object") {
337
+ const result = {};
338
+ for (const [k, v] of Object.entries(value)) {
339
+ if (/^(url|href|src|endpoint|targetUrl)$/i.test(k) && typeof v === "string") {
340
+ result[k] = sanitizeActionUrl(v);
341
+ } else {
342
+ result[k] = sanitizeActionValue(v);
343
+ }
344
+ }
345
+ return result;
346
+ }
347
+ return value;
348
+ }
349
+ function sanitizeActionPayload(payload) {
350
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
351
+ return {};
352
+ }
353
+ return sanitizeActionValue(payload);
354
+ }
355
+ function sanitizeActionStep(step) {
356
+ const sanitized = {
357
+ ...step,
358
+ label: step.label ? sanitizeActionString(step.label) : step.label,
359
+ payload: sanitizeActionPayload(step.payload)
360
+ };
361
+ if (step.condition && step.condition.value !== void 0) {
362
+ sanitized.condition = {
363
+ ...step.condition,
364
+ value: sanitizeActionValue(step.condition.value)
365
+ };
366
+ }
367
+ if (step.onSuccess && Array.isArray(step.onSuccess)) {
368
+ sanitized.onSuccess = step.onSuccess.map((s) => sanitizeActionStep(s));
369
+ }
370
+ if (step.onError && Array.isArray(step.onError)) {
371
+ sanitized.onError = step.onError.map((s) => sanitizeActionStep(s));
372
+ }
373
+ return sanitized;
374
+ }
375
+ function sanitizeActionPipeline(pipeline) {
376
+ return {
377
+ ...pipeline,
378
+ label: pipeline.label ? sanitizeActionString(pipeline.label) : pipeline.label,
379
+ steps: Array.isArray(pipeline.steps) ? pipeline.steps.map((s) => sanitizeActionStep(s)) : []
380
+ };
381
+ }
382
+
383
+ // src/form.ts
384
+ var import_zod2 = require("zod");
385
+ var ValidationRuleTypeSchema = import_zod2.z.enum([
386
+ "required",
387
+ "email",
388
+ "url",
389
+ "min_length",
390
+ "max_length",
391
+ "numeric_min",
392
+ "numeric_max",
393
+ "pattern",
394
+ "match_field",
395
+ "custom_regex"
396
+ ]);
397
+ var ValidateOnEventSchema = import_zod2.z.enum(["blur", "change", "submit"]);
398
+ var ValidationRuleSchema = import_zod2.z.object({
399
+ type: ValidationRuleTypeSchema,
400
+ value: import_zod2.z.unknown().optional(),
401
+ message: import_zod2.z.string().min(1, "Validation error message cannot be empty")
402
+ });
403
+ var FormFieldBindingSchema = import_zod2.z.object({
404
+ name: import_zod2.z.string().min(1, "Field name cannot be empty"),
405
+ label: import_zod2.z.string().optional(),
406
+ defaultValue: import_zod2.z.unknown().optional(),
407
+ rules: import_zod2.z.array(ValidationRuleSchema).optional().default([]),
408
+ validateOn: ValidateOnEventSchema.optional().default("blur"),
409
+ transform: import_zod2.z.enum(["trim", "lowercase", "uppercase", "number"]).optional(),
410
+ disabled: import_zod2.z.boolean().optional(),
411
+ required: import_zod2.z.boolean().optional()
412
+ });
413
+ var FormConfigSchema = import_zod2.z.object({
414
+ formId: import_zod2.z.string().min(1, "Form ID cannot be empty"),
415
+ resetOnSubmit: import_zod2.z.boolean().optional().default(false),
416
+ scrollToFirstError: import_zod2.z.boolean().optional().default(true),
417
+ validateOn: ValidateOnEventSchema.optional().default("blur"),
418
+ initialValues: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional(),
419
+ rules: import_zod2.z.array(ValidationRuleSchema).optional()
420
+ });
421
+ function isValidationRuleType(value) {
422
+ return ValidationRuleTypeSchema.safeParse(value).success;
423
+ }
424
+ function isValidationRule(value) {
425
+ return ValidationRuleSchema.safeParse(value).success;
426
+ }
427
+ function isValidateOnEvent(value) {
428
+ return ValidateOnEventSchema.safeParse(value).success;
429
+ }
430
+ function isFormFieldBinding(value) {
431
+ return FormFieldBindingSchema.safeParse(value).success;
432
+ }
433
+ function isFormConfig(value) {
434
+ return FormConfigSchema.safeParse(value).success;
435
+ }
436
+
437
+ // src/document.ts
69
438
  var SCHEMA_NAME = "stora.page";
70
439
  var CURRENT_SCHEMA_VERSION = "1.0.0";
71
- var AssetReferenceSchema = import_zod.z.object({
72
- type: import_zod.z.literal("asset"),
73
- assetId: import_zod.z.string().min(1, "Asset ID cannot be empty"),
74
- filename: import_zod.z.string().optional(),
75
- mimeType: import_zod.z.string().optional(),
76
- fallbackUrl: import_zod.z.string().url().optional()
77
- });
78
- var VariableBindingSchema = import_zod.z.object({
79
- type: import_zod.z.literal("variable"),
80
- key: import_zod.z.string().min(1, "Variable key cannot be empty"),
81
- fallback: import_zod.z.unknown().optional()
82
- });
83
- var ActionBindingSchema = import_zod.z.object({
84
- type: import_zod.z.string().min(1, "Action type cannot be empty"),
85
- payload: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
440
+ var AssetReferenceSchema = import_zod3.z.object({
441
+ type: import_zod3.z.literal("asset"),
442
+ assetId: import_zod3.z.string().min(1, "Asset ID cannot be empty"),
443
+ filename: import_zod3.z.string().optional(),
444
+ mimeType: import_zod3.z.string().optional(),
445
+ fallbackUrl: import_zod3.z.string().url().optional()
446
+ });
447
+ var VariableBindingSchema = import_zod3.z.object({
448
+ type: import_zod3.z.literal("variable"),
449
+ key: import_zod3.z.string().min(1, "Variable key cannot be empty"),
450
+ fallback: import_zod3.z.unknown().optional()
451
+ });
452
+ var ActionBindingSchema = import_zod3.z.object({
453
+ type: import_zod3.z.string().min(1, "Action type cannot be empty"),
454
+ payload: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).optional()
86
455
  });
87
456
  var DANGEROUS_STYLE_VALUE_PATTERN = /javascript:|expression\(|@import|<script|vbscript:|data:text\/html/i;
88
- var StyleValueSchema = import_zod.z.union([
89
- import_zod.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
457
+ var StyleValueSchema = import_zod3.z.union([
458
+ import_zod3.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
90
459
  message: "Style value contains a disallowed or unsafe pattern"
91
460
  }),
92
- import_zod.z.number(),
93
- import_zod.z.boolean(),
94
- import_zod.z.null(),
95
- import_zod.z.undefined()
461
+ import_zod3.z.number(),
462
+ import_zod3.z.boolean(),
463
+ import_zod3.z.null(),
464
+ import_zod3.z.undefined()
96
465
  ]);
97
- var StyleDefinitionSchema = import_zod.z.record(import_zod.z.string(), StyleValueSchema);
98
- var PseudoStateStylesSchema = import_zod.z.record(import_zod.z.string(), StyleDefinitionSchema);
99
- var ResponsiveStylesSchema = import_zod.z.object({
466
+ var StyleDefinitionSchema = import_zod3.z.record(import_zod3.z.string(), StyleValueSchema);
467
+ var PseudoStateStylesSchema = import_zod3.z.record(import_zod3.z.string(), StyleDefinitionSchema);
468
+ var ResponsiveStylesSchema = import_zod3.z.object({
100
469
  base: StyleDefinitionSchema.optional(),
101
470
  desktop: StyleDefinitionSchema.optional(),
102
471
  tablet: StyleDefinitionSchema.optional(),
103
472
  mobile: StyleDefinitionSchema.optional(),
104
473
  states: PseudoStateStylesSchema.optional()
105
474
  }).passthrough().default({});
106
- var AnimationConfigSchema = import_zod.z.object({
107
- type: import_zod.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
475
+ var AnimationConfigSchema = import_zod3.z.object({
476
+ type: import_zod3.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
108
477
  message: "Animation type contains a disallowed or unsafe pattern"
109
478
  }).optional().default("none"),
110
- duration: import_zod.z.number().min(0, "Duration must be non-negative").optional().default(600),
111
- delay: import_zod.z.number().min(0, "Delay must be non-negative").optional().default(0),
112
- easing: import_zod.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
479
+ duration: import_zod3.z.number().min(0, "Duration must be non-negative").optional().default(600),
480
+ delay: import_zod3.z.number().min(0, "Delay must be non-negative").optional().default(0),
481
+ easing: import_zod3.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
113
482
  message: "Animation easing contains a disallowed or unsafe pattern"
114
483
  }).optional().default("ease-out"),
115
- once: import_zod.z.boolean().optional().default(true),
116
- hoverEffect: import_zod.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
484
+ once: import_zod3.z.boolean().optional().default(true),
485
+ hoverEffect: import_zod3.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
117
486
  message: "Hover effect contains a disallowed or unsafe pattern"
118
487
  }).optional().default("none"),
119
- loopEffect: import_zod.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
488
+ loopEffect: import_zod3.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
120
489
  message: "Loop effect contains a disallowed or unsafe pattern"
121
490
  }).optional().default("none")
122
491
  });
@@ -129,14 +498,16 @@ var DEFAULT_ANIMATION_CONFIG = {
129
498
  hoverEffect: "none",
130
499
  loopEffect: "none"
131
500
  };
132
- var NodeSchema = import_zod.z.lazy(
133
- () => import_zod.z.object({
134
- id: import_zod.z.string().min(1, "Node ID must be a non-empty string"),
135
- type: import_zod.z.string().min(1, "Node type must be a non-empty string"),
136
- props: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional().default({}),
501
+ var NodeSchema = import_zod3.z.lazy(
502
+ () => import_zod3.z.object({
503
+ id: import_zod3.z.string().min(1, "Node ID must be a non-empty string"),
504
+ type: import_zod3.z.string().min(1, "Node type must be a non-empty string"),
505
+ props: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).optional().default({}),
137
506
  styles: ResponsiveStylesSchema.optional().default({}),
138
507
  animation: AnimationConfigSchema.optional(),
139
- children: import_zod.z.array(NodeSchema).optional().default([])
508
+ actions: import_zod3.z.array(ActionPipelineSchema).optional(),
509
+ formConfig: FormConfigSchema.optional(),
510
+ children: import_zod3.z.array(NodeSchema).optional().default([])
140
511
  })
141
512
  );
142
513
  var RootPageNodeSchema = NodeSchema.refine(
@@ -146,23 +517,62 @@ var RootPageNodeSchema = NodeSchema.refine(
146
517
  path: ["type"]
147
518
  }
148
519
  );
149
- var DocumentMetadataSchema = import_zod.z.object({
150
- title: import_zod.z.string().min(1, "Title is required").default("Untitled Page"),
151
- description: import_zod.z.string().optional().default(""),
152
- author: import_zod.z.string().optional().default(""),
153
- createdAt: import_zod.z.string().optional(),
154
- updatedAt: import_zod.z.string().optional(),
155
- tags: import_zod.z.array(import_zod.z.string()).optional().default([]),
156
- category: import_zod.z.string().optional().default("general"),
157
- version: import_zod.z.string().optional().default("1.0.0"),
158
- custom: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
159
- });
160
- var PageDocumentSchema = import_zod.z.object({
161
- schema: import_zod.z.literal(SCHEMA_NAME),
162
- version: import_zod.z.string().min(1, "Schema version is required").default(CURRENT_SCHEMA_VERSION),
520
+ var DocumentMetadataSchema = import_zod3.z.object({
521
+ title: import_zod3.z.string().min(1, "Title is required").default("Untitled Page"),
522
+ description: import_zod3.z.string().optional().default(""),
523
+ author: import_zod3.z.string().optional().default(""),
524
+ createdAt: import_zod3.z.string().optional(),
525
+ updatedAt: import_zod3.z.string().optional(),
526
+ tags: import_zod3.z.array(import_zod3.z.string()).optional().default([]),
527
+ category: import_zod3.z.string().optional().default("general"),
528
+ version: import_zod3.z.string().optional().default("1.0.0"),
529
+ custom: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).optional()
530
+ });
531
+ var PageDocumentSchema = import_zod3.z.object({
532
+ schema: import_zod3.z.literal(SCHEMA_NAME),
533
+ version: import_zod3.z.string().min(1, "Schema version is required").default(CURRENT_SCHEMA_VERSION),
163
534
  metadata: DocumentMetadataSchema.optional(),
164
535
  document: RootPageNodeSchema
165
536
  });
537
+ var PROJECT_SCHEMA_NAME = "stora.project";
538
+ var CURRENT_PROJECT_SCHEMA_VERSION = "1.0.0";
539
+ var ARTBOARD_REFERENCE_NODE_TYPE = "artboard-reference";
540
+ var ArtboardTypeSchema = import_zod3.z.enum(["page", "component"]);
541
+ var ArtboardSchema = import_zod3.z.object({
542
+ id: import_zod3.z.string().min(1, "Artboard ID is required"),
543
+ name: import_zod3.z.string().min(1, "Artboard name is required"),
544
+ artboardType: ArtboardTypeSchema,
545
+ /** Route for page artboards (e.g. "/about"). */
546
+ slug: import_zod3.z.string().optional(),
547
+ /**
548
+ * For component artboards: the id that `open_modal` / `close_modal` actions target.
549
+ * Mirrors the detached node's own `props.modalId` so ModalManager keeps working unchanged.
550
+ */
551
+ triggerId: import_zod3.z.string().optional(),
552
+ /**
553
+ * Viewport/breakpoint this artboard is currently authored at. Declared inline
554
+ * (rather than imported) because viewport is otherwise an editor/renderer concept.
555
+ */
556
+ viewport: import_zod3.z.enum(["desktop", "tablet", "mobile"]).optional(),
557
+ /** Persisted artboard width in px, matching the canvas ViewportResizer's `width`. */
558
+ width: import_zod3.z.number().positive().optional(),
559
+ /**
560
+ * Free position on the builder's infinite canvas, in unscaled canvas px. Absent means
561
+ * "not placed yet" — the canvas then falls back to laying the artboard out in a row.
562
+ */
563
+ position: import_zod3.z.object({
564
+ x: import_zod3.z.number(),
565
+ y: import_zod3.z.number()
566
+ }).optional(),
567
+ document: PageDocumentSchema
568
+ });
569
+ var ProjectDocumentSchema = import_zod3.z.object({
570
+ schema: import_zod3.z.literal(PROJECT_SCHEMA_NAME),
571
+ version: import_zod3.z.string().min(1, "Schema version is required").default(CURRENT_PROJECT_SCHEMA_VERSION),
572
+ metadata: DocumentMetadataSchema.optional(),
573
+ artboards: import_zod3.z.array(ArtboardSchema).min(1, "A project needs at least one artboard"),
574
+ activeArtboardId: import_zod3.z.string().optional()
575
+ });
166
576
  function isAssetReference(value) {
167
577
  return AssetReferenceSchema.safeParse(value).success;
168
578
  }
@@ -175,6 +585,17 @@ function isActionBinding(value) {
175
585
  function isAnimationConfig(value) {
176
586
  return AnimationConfigSchema.safeParse(value).success;
177
587
  }
588
+ function isProjectDocument(value) {
589
+ return ProjectDocumentSchema.safeParse(value).success;
590
+ }
591
+ function looksLikeProjectDocument(value) {
592
+ if (typeof value !== "object" || value === null) return false;
593
+ const candidate = value;
594
+ return candidate.schema === PROJECT_SCHEMA_NAME || Array.isArray(candidate.artboards);
595
+ }
596
+ function isArtboardReferenceNode(node) {
597
+ return node.type === ARTBOARD_REFERENCE_NODE_TYPE;
598
+ }
178
599
  function generateDeterministicNodeId(prefix, indexOrKey) {
179
600
  const cleanPrefix = prefix.toLowerCase().replace(/[^a-z0-9_-]/g, "-");
180
601
  return `${cleanPrefix}_${indexOrKey}`;
@@ -206,30 +627,30 @@ function validateNodeIdUniqueness(node) {
206
627
  }
207
628
 
208
629
  // src/manifest.ts
209
- var import_zod2 = require("zod");
210
- var ManifestAssetItemSchema = import_zod2.z.object({
211
- id: import_zod2.z.string().min(1, "Asset ID cannot be empty"),
212
- path: import_zod2.z.string().min(1, "Asset archive path cannot be empty"),
213
- mimeType: import_zod2.z.string().min(1, "MIME type cannot be empty"),
214
- size: import_zod2.z.number().nonnegative("Asset size must be non-negative"),
215
- checksum: import_zod2.z.string().optional()
216
- });
217
- var ManifestSchema = import_zod2.z.object({
218
- schema: import_zod2.z.literal(SCHEMA_NAME).default(SCHEMA_NAME),
219
- schemaVersion: import_zod2.z.string().min(1, "Schema version cannot be empty").default("1.0.0"),
220
- packageVersion: import_zod2.z.string().min(1, "Package version cannot be empty").default("1.0.0"),
221
- builderCompatibility: import_zod2.z.string().default(">=0.1.0"),
222
- requiredComponents: import_zod2.z.array(import_zod2.z.string()).default([]),
223
- requiredCapabilities: import_zod2.z.array(import_zod2.z.string()).default([]),
224
- assets: import_zod2.z.array(ManifestAssetItemSchema).default([]),
225
- createdAt: import_zod2.z.string().optional()
630
+ var import_zod4 = require("zod");
631
+ var ManifestAssetItemSchema = import_zod4.z.object({
632
+ id: import_zod4.z.string().min(1, "Asset ID cannot be empty"),
633
+ path: import_zod4.z.string().min(1, "Asset archive path cannot be empty"),
634
+ mimeType: import_zod4.z.string().min(1, "MIME type cannot be empty"),
635
+ size: import_zod4.z.number().nonnegative("Asset size must be non-negative"),
636
+ checksum: import_zod4.z.string().optional()
637
+ });
638
+ var ManifestSchema = import_zod4.z.object({
639
+ schema: import_zod4.z.literal(SCHEMA_NAME).default(SCHEMA_NAME),
640
+ schemaVersion: import_zod4.z.string().min(1, "Schema version cannot be empty").default("1.0.0"),
641
+ packageVersion: import_zod4.z.string().min(1, "Package version cannot be empty").default("1.0.0"),
642
+ builderCompatibility: import_zod4.z.string().default(">=0.1.0"),
643
+ requiredComponents: import_zod4.z.array(import_zod4.z.string()).default([]),
644
+ requiredCapabilities: import_zod4.z.array(import_zod4.z.string()).default([]),
645
+ assets: import_zod4.z.array(ManifestAssetItemSchema).default([]),
646
+ createdAt: import_zod4.z.string().optional()
226
647
  });
227
648
  function isManifest(value) {
228
649
  return ManifestSchema.safeParse(value).success;
229
650
  }
230
651
 
231
652
  // src/template.ts
232
- var import_zod3 = require("zod");
653
+ var import_zod5 = require("zod");
233
654
  var DANGEROUS_URI_PATTERN = /^(javascript:|vbscript:|data:(?!image\/))|<script/i;
234
655
  function isSafeThumbnailUrl(url) {
235
656
  if (!url || typeof url !== "string") return false;
@@ -238,49 +659,49 @@ function isSafeThumbnailUrl(url) {
238
659
  if (DANGEROUS_URI_PATTERN.test(trimmed)) return false;
239
660
  return true;
240
661
  }
241
- var SafeThumbnailUrlSchema = import_zod3.z.string().min(1, "Thumbnail URL cannot be empty").refine(
662
+ var SafeThumbnailUrlSchema = import_zod5.z.string().min(1, "Thumbnail URL cannot be empty").refine(
242
663
  (url) => isSafeThumbnailUrl(url),
243
664
  { message: "Thumbnail URL contains an unsafe protocol or payload" }
244
665
  );
245
- var SafeThumbnailObjectSchema = import_zod3.z.object({
666
+ var SafeThumbnailObjectSchema = import_zod5.z.object({
246
667
  url: SafeThumbnailUrlSchema,
247
- alt: import_zod3.z.string().optional(),
248
- width: import_zod3.z.number().positive().optional(),
249
- height: import_zod3.z.number().positive().optional()
668
+ alt: import_zod5.z.string().optional(),
669
+ width: import_zod5.z.number().positive().optional(),
670
+ height: import_zod5.z.number().positive().optional()
250
671
  });
251
- var SafeThumbnailSchema = import_zod3.z.union([
672
+ var SafeThumbnailSchema = import_zod5.z.union([
252
673
  AssetReferenceSchema,
253
674
  SafeThumbnailObjectSchema,
254
675
  SafeThumbnailUrlSchema
255
676
  ]);
256
- var TemplatePackageRefSchema = import_zod3.z.object({
257
- path: import_zod3.z.string().optional(),
677
+ var TemplatePackageRefSchema = import_zod5.z.object({
678
+ path: import_zod5.z.string().optional(),
258
679
  url: SafeThumbnailUrlSchema.optional(),
259
- checksum: import_zod3.z.string().optional(),
260
- format: import_zod3.z.enum(["stora", "json"]).default("stora")
680
+ checksum: import_zod5.z.string().optional(),
681
+ format: import_zod5.z.enum(["stora", "json"]).default("stora")
261
682
  });
262
- var TemplateRequirementsSchema = import_zod3.z.object({
263
- requiredComponents: import_zod3.z.array(import_zod3.z.string()).default([]),
264
- requiredCapabilities: import_zod3.z.array(import_zod3.z.string()).default([])
683
+ var TemplateRequirementsSchema = import_zod5.z.object({
684
+ requiredComponents: import_zod5.z.array(import_zod5.z.string()).default([]),
685
+ requiredCapabilities: import_zod5.z.array(import_zod5.z.string()).default([])
265
686
  });
266
- var TemplateRecordSchema = import_zod3.z.object({
267
- id: import_zod3.z.string().min(1, "Template ID must be a non-empty string"),
268
- name: import_zod3.z.string().min(1, "Template name must be a non-empty string"),
269
- description: import_zod3.z.string().optional().default(""),
270
- category: import_zod3.z.string().optional().default("general"),
271
- tags: import_zod3.z.array(import_zod3.z.string()).optional().default([]),
687
+ var TemplateRecordSchema = import_zod5.z.object({
688
+ id: import_zod5.z.string().min(1, "Template ID must be a non-empty string"),
689
+ name: import_zod5.z.string().min(1, "Template name must be a non-empty string"),
690
+ description: import_zod5.z.string().optional().default(""),
691
+ category: import_zod5.z.string().optional().default("general"),
692
+ tags: import_zod5.z.array(import_zod5.z.string()).optional().default([]),
272
693
  thumbnail: SafeThumbnailSchema.optional(),
273
- author: import_zod3.z.string().optional().default(""),
274
- version: import_zod3.z.string().optional().default("1.0.0"),
694
+ author: import_zod5.z.string().optional().default(""),
695
+ version: import_zod5.z.string().optional().default("1.0.0"),
275
696
  document: PageDocumentSchema.optional(),
276
697
  packageReference: TemplatePackageRefSchema.optional(),
277
698
  requirements: TemplateRequirementsSchema.default({
278
699
  requiredComponents: [],
279
700
  requiredCapabilities: []
280
701
  }),
281
- createdAt: import_zod3.z.string().optional(),
282
- updatedAt: import_zod3.z.string().optional(),
283
- custom: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).optional()
702
+ createdAt: import_zod5.z.string().optional(),
703
+ updatedAt: import_zod5.z.string().optional(),
704
+ custom: import_zod5.z.record(import_zod5.z.string(), import_zod5.z.unknown()).optional()
284
705
  });
285
706
  function isTemplateRecord(value) {
286
707
  return TemplateRecordSchema.safeParse(value).success;
@@ -600,6 +1021,111 @@ var PAGE_DOCUMENT_JSON_SCHEMA_V1 = {
600
1021
  },
601
1022
  additionalProperties: false
602
1023
  },
1024
+ actionStep: {
1025
+ type: "object",
1026
+ required: ["id", "type"],
1027
+ properties: {
1028
+ id: {
1029
+ type: "string",
1030
+ minLength: 1
1031
+ },
1032
+ type: {
1033
+ type: "string",
1034
+ enum: [
1035
+ "api_request",
1036
+ "navigate",
1037
+ "set_state",
1038
+ "reset_form",
1039
+ "show_toast",
1040
+ "open_modal",
1041
+ "close_modal",
1042
+ "copy_clipboard",
1043
+ "custom_event"
1044
+ ]
1045
+ },
1046
+ label: { type: "string" },
1047
+ payload: { type: "object" },
1048
+ condition: {
1049
+ type: "object",
1050
+ required: ["field", "operator"],
1051
+ properties: {
1052
+ field: { type: "string", minLength: 1 },
1053
+ operator: {
1054
+ type: "string",
1055
+ enum: [
1056
+ "equals",
1057
+ "not_equals",
1058
+ "contains",
1059
+ "not_contains",
1060
+ "is_truthy",
1061
+ "is_falsy",
1062
+ "gt",
1063
+ "gte",
1064
+ "lt",
1065
+ "lte",
1066
+ "regex"
1067
+ ]
1068
+ },
1069
+ value: {}
1070
+ },
1071
+ additionalProperties: false
1072
+ },
1073
+ timeout: { type: "number", minimum: 1 },
1074
+ continueOnError: { type: "boolean" },
1075
+ onSuccess: {
1076
+ type: "array",
1077
+ items: { $ref: "#/definitions/actionStep" }
1078
+ },
1079
+ onError: {
1080
+ type: "array",
1081
+ items: { $ref: "#/definitions/actionStep" }
1082
+ }
1083
+ },
1084
+ additionalProperties: false
1085
+ },
1086
+ actionPipeline: {
1087
+ type: "object",
1088
+ required: ["id", "trigger", "steps"],
1089
+ properties: {
1090
+ id: {
1091
+ type: "string",
1092
+ minLength: 1
1093
+ },
1094
+ trigger: {
1095
+ type: "string",
1096
+ enum: ["click", "submit", "change", "blur", "focus", "load"]
1097
+ },
1098
+ label: { type: "string" },
1099
+ debounceMs: { type: "number", minimum: 0 },
1100
+ preventDuplicate: { type: "boolean" },
1101
+ enabled: { type: "boolean", default: true },
1102
+ steps: {
1103
+ type: "array",
1104
+ items: { $ref: "#/definitions/actionStep" },
1105
+ minItems: 1
1106
+ }
1107
+ },
1108
+ additionalProperties: false
1109
+ },
1110
+ formConfig: {
1111
+ type: "object",
1112
+ required: ["formId"],
1113
+ properties: {
1114
+ formId: {
1115
+ type: "string",
1116
+ minLength: 1
1117
+ },
1118
+ resetOnSubmit: { type: "boolean", default: false },
1119
+ scrollToFirstError: { type: "boolean", default: true },
1120
+ validateOn: {
1121
+ type: "string",
1122
+ enum: ["blur", "change", "submit"],
1123
+ default: "blur"
1124
+ },
1125
+ initialValues: { type: "object" }
1126
+ },
1127
+ additionalProperties: false
1128
+ },
603
1129
  node: {
604
1130
  type: "object",
605
1131
  required: ["id", "type"],
@@ -625,6 +1151,17 @@ var PAGE_DOCUMENT_JSON_SCHEMA_V1 = {
625
1151
  animation: {
626
1152
  $ref: "#/definitions/animationConfig"
627
1153
  },
1154
+ actions: {
1155
+ type: "array",
1156
+ items: {
1157
+ $ref: "#/definitions/actionPipeline"
1158
+ },
1159
+ description: "Multi-step action pipelines bound to component events"
1160
+ },
1161
+ formConfig: {
1162
+ $ref: "#/definitions/formConfig",
1163
+ description: "Form container configuration and behavior"
1164
+ },
628
1165
  children: {
629
1166
  type: "array",
630
1167
  items: {
@@ -961,48 +1498,335 @@ var TEMPLATE_RECORD_JSON_SCHEMA_V1 = {
961
1498
  function getTemplateRecordJsonSchema() {
962
1499
  return TEMPLATE_RECORD_JSON_SCHEMA_V1;
963
1500
  }
1501
+ var ACTION_PIPELINE_JSON_SCHEMA_V1 = {
1502
+ $schema: "http://json-schema.org/draft-07/schema#",
1503
+ $id: "https://schema.stora.page/v1/action-pipeline.json",
1504
+ title: "StoraActionPipeline",
1505
+ description: "Action Pipeline schema definition for KUBUILD event workflows",
1506
+ type: "object",
1507
+ required: ["id", "trigger", "steps"],
1508
+ additionalProperties: false,
1509
+ properties: {
1510
+ id: {
1511
+ type: "string",
1512
+ minLength: 1,
1513
+ description: "Unique pipeline identifier"
1514
+ },
1515
+ trigger: {
1516
+ type: "string",
1517
+ enum: ["click", "submit", "change", "blur", "focus", "load"],
1518
+ description: "DOM or component event that triggers the action pipeline"
1519
+ },
1520
+ label: {
1521
+ type: "string",
1522
+ description: "Human readable label for the action pipeline"
1523
+ },
1524
+ debounceMs: {
1525
+ type: "number",
1526
+ minimum: 0,
1527
+ description: "Debounce duration in milliseconds"
1528
+ },
1529
+ preventDuplicate: {
1530
+ type: "boolean",
1531
+ description: "Prevent concurrent duplicate pipeline executions"
1532
+ },
1533
+ enabled: {
1534
+ type: "boolean",
1535
+ default: true,
1536
+ description: "Whether the pipeline is currently active"
1537
+ },
1538
+ steps: {
1539
+ type: "array",
1540
+ items: { $ref: "#/definitions/actionStep" },
1541
+ minItems: 1,
1542
+ description: "Ordered sequence of action steps to execute"
1543
+ }
1544
+ },
1545
+ definitions: {
1546
+ actionStep: {
1547
+ type: "object",
1548
+ required: ["id", "type"],
1549
+ properties: {
1550
+ id: {
1551
+ type: "string",
1552
+ minLength: 1
1553
+ },
1554
+ type: {
1555
+ type: "string",
1556
+ enum: [
1557
+ "api_request",
1558
+ "navigate",
1559
+ "set_state",
1560
+ "reset_form",
1561
+ "show_toast",
1562
+ "open_modal",
1563
+ "close_modal",
1564
+ "copy_clipboard",
1565
+ "custom_event"
1566
+ ]
1567
+ },
1568
+ label: { type: "string" },
1569
+ payload: { type: "object" },
1570
+ condition: {
1571
+ type: "object",
1572
+ required: ["field", "operator"],
1573
+ properties: {
1574
+ field: { type: "string", minLength: 1 },
1575
+ operator: {
1576
+ type: "string",
1577
+ enum: [
1578
+ "equals",
1579
+ "not_equals",
1580
+ "contains",
1581
+ "not_contains",
1582
+ "is_truthy",
1583
+ "is_falsy",
1584
+ "gt",
1585
+ "gte",
1586
+ "lt",
1587
+ "lte",
1588
+ "regex"
1589
+ ]
1590
+ },
1591
+ value: {}
1592
+ },
1593
+ additionalProperties: false
1594
+ },
1595
+ timeout: { type: "number", minimum: 1 },
1596
+ continueOnError: { type: "boolean" },
1597
+ onSuccess: {
1598
+ type: "array",
1599
+ items: { $ref: "#/definitions/actionStep" }
1600
+ },
1601
+ onError: {
1602
+ type: "array",
1603
+ items: { $ref: "#/definitions/actionStep" }
1604
+ }
1605
+ },
1606
+ additionalProperties: false
1607
+ }
1608
+ }
1609
+ };
1610
+ function getActionPipelineJsonSchema() {
1611
+ return ACTION_PIPELINE_JSON_SCHEMA_V1;
1612
+ }
1613
+ var FORM_CONFIG_JSON_SCHEMA_V1 = {
1614
+ $schema: "http://json-schema.org/draft-07/schema#",
1615
+ $id: "https://schema.stora.page/v1/form-config.json",
1616
+ title: "StoraFormConfig",
1617
+ description: "Form container configuration and behavior definition for KUBUILD",
1618
+ type: "object",
1619
+ required: ["formId"],
1620
+ additionalProperties: false,
1621
+ properties: {
1622
+ formId: {
1623
+ type: "string",
1624
+ minLength: 1,
1625
+ description: "Unique identifier for the form boundary"
1626
+ },
1627
+ resetOnSubmit: {
1628
+ type: "boolean",
1629
+ default: false,
1630
+ description: "Whether to reset form field values after successful submission"
1631
+ },
1632
+ scrollToFirstError: {
1633
+ type: "boolean",
1634
+ default: true,
1635
+ description: "Auto-scroll viewport to the first invalid input on validation failure"
1636
+ },
1637
+ validateOn: {
1638
+ type: "string",
1639
+ enum: ["blur", "change", "submit"],
1640
+ default: "blur",
1641
+ description: "Default trigger event for field validation evaluation"
1642
+ },
1643
+ initialValues: {
1644
+ type: "object",
1645
+ description: "Initial state values populated in form fields"
1646
+ }
1647
+ }
1648
+ };
1649
+ function getFormConfigJsonSchema() {
1650
+ return FORM_CONFIG_JSON_SCHEMA_V1;
1651
+ }
1652
+ var FORM_FIELD_BINDING_JSON_SCHEMA_V1 = {
1653
+ $schema: "http://json-schema.org/draft-07/schema#",
1654
+ $id: "https://schema.stora.page/v1/form-field-binding.json",
1655
+ title: "StoraFormFieldBinding",
1656
+ description: "Form field binding definition connecting input elements to form state runtime",
1657
+ type: "object",
1658
+ required: ["name"],
1659
+ additionalProperties: false,
1660
+ properties: {
1661
+ name: {
1662
+ type: "string",
1663
+ minLength: 1,
1664
+ description: "Field state property key"
1665
+ },
1666
+ label: {
1667
+ type: "string",
1668
+ description: "Display label for the field"
1669
+ },
1670
+ defaultValue: {
1671
+ description: "Initial default value if not overridden by form initialValues"
1672
+ },
1673
+ rules: {
1674
+ type: "array",
1675
+ items: { $ref: "#/definitions/validationRule" },
1676
+ default: [],
1677
+ description: "Validation rules applied to the field value"
1678
+ },
1679
+ validateOn: {
1680
+ type: "string",
1681
+ enum: ["blur", "change", "submit"],
1682
+ default: "blur",
1683
+ description: "Field-specific validation trigger timing"
1684
+ },
1685
+ transform: {
1686
+ type: "string",
1687
+ enum: ["trim", "lowercase", "uppercase", "number"],
1688
+ description: "Value transformation applied prior to validation and state storage"
1689
+ },
1690
+ disabled: {
1691
+ type: "boolean",
1692
+ description: "Whether the field is disabled"
1693
+ },
1694
+ required: {
1695
+ type: "boolean",
1696
+ description: "Whether the field is required (shorthand rule)"
1697
+ }
1698
+ },
1699
+ definitions: {
1700
+ validationRule: {
1701
+ type: "object",
1702
+ required: ["type", "message"],
1703
+ properties: {
1704
+ type: {
1705
+ type: "string",
1706
+ enum: [
1707
+ "required",
1708
+ "email",
1709
+ "url",
1710
+ "min_length",
1711
+ "max_length",
1712
+ "numeric_min",
1713
+ "numeric_max",
1714
+ "pattern",
1715
+ "match_field",
1716
+ "custom_regex"
1717
+ ]
1718
+ },
1719
+ value: {},
1720
+ message: {
1721
+ type: "string",
1722
+ minLength: 1
1723
+ }
1724
+ },
1725
+ additionalProperties: false
1726
+ }
1727
+ }
1728
+ };
1729
+ function getFormFieldBindingJsonSchema() {
1730
+ return FORM_FIELD_BINDING_JSON_SCHEMA_V1;
1731
+ }
964
1732
  // Annotate the CommonJS export names for ESM import in node:
965
1733
  0 && (module.exports = {
1734
+ ACTION_PIPELINE_JSON_SCHEMA_V1,
1735
+ ARTBOARD_REFERENCE_NODE_TYPE,
966
1736
  ActionBindingSchema,
1737
+ ActionPipelineSchema,
1738
+ ActionStepConditionSchema,
1739
+ ActionStepSchema,
1740
+ ActionStepTypeSchema,
1741
+ ActionTriggerSchema,
1742
+ ActionTriggerTypeSchema,
967
1743
  AnimationConfigSchema,
1744
+ ApiRequestStepPayloadSchema,
1745
+ ArtboardSchema,
1746
+ ArtboardTypeSchema,
968
1747
  AssetReferenceSchema,
1748
+ CURRENT_PROJECT_SCHEMA_VERSION,
969
1749
  CURRENT_SCHEMA_VERSION,
1750
+ CloseModalStepPayloadSchema,
1751
+ ConditionOperatorSchema,
1752
+ CopyClipboardStepPayloadSchema,
1753
+ CustomEventStepPayloadSchema,
970
1754
  DEFAULT_ANIMATION_CONFIG,
971
1755
  DocumentMetadataSchema,
1756
+ FORM_CONFIG_JSON_SCHEMA_V1,
1757
+ FORM_FIELD_BINDING_JSON_SCHEMA_V1,
1758
+ FormConfigSchema,
1759
+ FormFieldBindingSchema,
972
1760
  MANIFEST_JSON_SCHEMA_V1,
973
1761
  ManifestAssetItemSchema,
974
1762
  ManifestSchema,
1763
+ NavigateStepPayloadSchema,
975
1764
  NodeSchema,
1765
+ OpenModalStepPayloadSchema,
976
1766
  PAGE_DOCUMENT_JSON_SCHEMA_V1,
1767
+ PROJECT_SCHEMA_NAME,
977
1768
  PageDocumentSchema,
1769
+ ProjectDocumentSchema,
978
1770
  PseudoStateStylesSchema,
1771
+ ResetFormStepPayloadSchema,
979
1772
  ResponsiveStylesSchema,
980
1773
  RootPageNodeSchema,
981
1774
  SCHEMA_NAME,
982
1775
  SafeThumbnailObjectSchema,
983
1776
  SafeThumbnailSchema,
984
1777
  SafeThumbnailUrlSchema,
1778
+ SetStateStepPayloadSchema,
1779
+ ShowToastStepPayloadSchema,
1780
+ StepPayloadSchemas,
985
1781
  StyleDefinitionSchema,
986
1782
  StyleValueSchema,
987
1783
  TEMPLATE_RECORD_JSON_SCHEMA_V1,
988
1784
  TemplatePackageRefSchema,
989
1785
  TemplateRecordSchema,
990
1786
  TemplateRequirementsSchema,
1787
+ ValidateOnEventSchema,
1788
+ ValidationRuleSchema,
1789
+ ValidationRuleTypeSchema,
991
1790
  VariableBindingSchema,
992
1791
  collectNodeIds,
993
1792
  generateDeterministicNodeId,
1793
+ getActionPipelineJsonSchema,
1794
+ getFormConfigJsonSchema,
1795
+ getFormFieldBindingJsonSchema,
994
1796
  getManifestJsonSchema,
995
1797
  getPageDocumentJsonSchema,
996
1798
  getTemplateRecordJsonSchema,
997
1799
  isActionBinding,
1800
+ isActionPipeline,
1801
+ isActionStep,
1802
+ isActionStepCondition,
1803
+ isActionStepType,
1804
+ isActionTriggerType,
998
1805
  isAnimationConfig,
1806
+ isArtboardReferenceNode,
999
1807
  isAssetReference,
1808
+ isConditionOperator,
1809
+ isFormConfig,
1810
+ isFormFieldBinding,
1000
1811
  isManifest,
1812
+ isProjectDocument,
1813
+ isSafeActionUrl,
1001
1814
  isSafeThumbnail,
1002
1815
  isSafeThumbnailUrl,
1003
1816
  isTemplateRecord,
1817
+ isValidateOnEvent,
1818
+ isValidationRule,
1819
+ isValidationRuleType,
1004
1820
  isVariableBinding,
1821
+ looksLikeProjectDocument,
1822
+ sanitizeActionPayload,
1823
+ sanitizeActionPipeline,
1824
+ sanitizeActionStep,
1825
+ sanitizeActionString,
1826
+ sanitizeActionUrl,
1827
+ sanitizeActionValue,
1005
1828
  starterPageFixture,
1829
+ validateActionStepPayload,
1006
1830
  validateNodeIdUniqueness
1007
1831
  });
1008
1832
  //# sourceMappingURL=index.cjs.map