@kubuild/schema 0.5.0 → 0.7.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
@@ -40,15 +40,23 @@ __export(index_exports, {
40
40
  ConditionOperatorSchema: () => ConditionOperatorSchema,
41
41
  CopyClipboardStepPayloadSchema: () => CopyClipboardStepPayloadSchema,
42
42
  CustomEventStepPayloadSchema: () => CustomEventStepPayloadSchema,
43
+ CustomTrackingProviderConfigSchema: () => CustomTrackingProviderConfigSchema,
44
+ CustomTrackingSecretsSchema: () => CustomTrackingSecretsSchema,
43
45
  DEFAULT_ANIMATION_CONFIG: () => DEFAULT_ANIMATION_CONFIG,
44
46
  DocumentMetadataSchema: () => DocumentMetadataSchema,
45
47
  FORM_CONFIG_JSON_SCHEMA_V1: () => FORM_CONFIG_JSON_SCHEMA_V1,
46
48
  FORM_FIELD_BINDING_JSON_SCHEMA_V1: () => FORM_FIELD_BINDING_JSON_SCHEMA_V1,
47
49
  FormConfigSchema: () => FormConfigSchema,
48
50
  FormFieldBindingSchema: () => FormFieldBindingSchema,
51
+ GoogleTrackingProviderConfigSchema: () => GoogleTrackingProviderConfigSchema,
52
+ GoogleTrackingSecretsSchema: () => GoogleTrackingSecretsSchema,
53
+ GtmTrackingProviderConfigSchema: () => GtmTrackingProviderConfigSchema,
54
+ LEGACY_TRACKING_SECRET_KEYS: () => LEGACY_TRACKING_SECRET_KEYS,
49
55
  MANIFEST_JSON_SCHEMA_V1: () => MANIFEST_JSON_SCHEMA_V1,
50
56
  ManifestAssetItemSchema: () => ManifestAssetItemSchema,
51
57
  ManifestSchema: () => ManifestSchema,
58
+ MetaTrackingProviderConfigSchema: () => MetaTrackingProviderConfigSchema,
59
+ MetaTrackingSecretsSchema: () => MetaTrackingSecretsSchema,
52
60
  NavigateStepPayloadSchema: () => NavigateStepPayloadSchema,
53
61
  NodeSchema: () => NodeSchema,
54
62
  OpenModalStepPayloadSchema: () => OpenModalStepPayloadSchema,
@@ -64,15 +72,30 @@ __export(index_exports, {
64
72
  SafeThumbnailObjectSchema: () => SafeThumbnailObjectSchema,
65
73
  SafeThumbnailSchema: () => SafeThumbnailSchema,
66
74
  SafeThumbnailUrlSchema: () => SafeThumbnailUrlSchema,
75
+ ServerTrackingEventSchema: () => ServerTrackingEventSchema,
67
76
  SetStateStepPayloadSchema: () => SetStateStepPayloadSchema,
68
77
  ShowToastStepPayloadSchema: () => ShowToastStepPayloadSchema,
78
+ StandardTrackingEventSchema: () => StandardTrackingEventSchema,
69
79
  StepPayloadSchemas: () => StepPayloadSchemas,
70
80
  StyleDefinitionSchema: () => StyleDefinitionSchema,
71
81
  StyleValueSchema: () => StyleValueSchema,
72
82
  TEMPLATE_RECORD_JSON_SCHEMA_V1: () => TEMPLATE_RECORD_JSON_SCHEMA_V1,
83
+ TRACKING_RELAY_PROTOCOL_VERSION: () => TRACKING_RELAY_PROTOCOL_VERSION,
73
84
  TemplatePackageRefSchema: () => TemplatePackageRefSchema,
74
85
  TemplateRecordSchema: () => TemplateRecordSchema,
75
86
  TemplateRequirementsSchema: () => TemplateRequirementsSchema,
87
+ TikTokTrackingProviderConfigSchema: () => TikTokTrackingProviderConfigSchema,
88
+ TikTokTrackingSecretsSchema: () => TikTokTrackingSecretsSchema,
89
+ ToggleModalStepPayloadSchema: () => ToggleModalStepPayloadSchema,
90
+ TrackEventProviderSchema: () => TrackEventProviderSchema,
91
+ TrackEventStepPayloadSchema: () => TrackEventStepPayloadSchema,
92
+ TrackingConfigSchema: () => TrackingConfigSchema,
93
+ TrackingDeliverySchema: () => TrackingDeliverySchema,
94
+ TrackingProviderTypeSchema: () => TrackingProviderTypeSchema,
95
+ TrackingRelayErrorCodeSchema: () => TrackingRelayErrorCodeSchema,
96
+ TrackingRelayProviderResultSchema: () => TrackingRelayProviderResultSchema,
97
+ TrackingRelayRequestSchema: () => TrackingRelayRequestSchema,
98
+ TrackingRelayResponseSchema: () => TrackingRelayResponseSchema,
76
99
  ValidateOnEventSchema: () => ValidateOnEventSchema,
77
100
  ValidationRuleSchema: () => ValidationRuleSchema,
78
101
  ValidationRuleTypeSchema: () => ValidationRuleTypeSchema,
@@ -85,6 +108,9 @@ __export(index_exports, {
85
108
  getManifestJsonSchema: () => getManifestJsonSchema,
86
109
  getPageDocumentJsonSchema: () => getPageDocumentJsonSchema,
87
110
  getTemplateRecordJsonSchema: () => getTemplateRecordJsonSchema,
111
+ getTrackingProviderSecretsJsonSchema: () => getTrackingProviderSecretsJsonSchema,
112
+ getTrackingRelayRequestJsonSchema: () => getTrackingRelayRequestJsonSchema,
113
+ getTrackingRelayResponseJsonSchema: () => getTrackingRelayResponseJsonSchema,
88
114
  isActionBinding: () => isActionBinding,
89
115
  isActionPipeline: () => isActionPipeline,
90
116
  isActionStep: () => isActionStep,
@@ -103,6 +129,9 @@ __export(index_exports, {
103
129
  isSafeThumbnail: () => isSafeThumbnail,
104
130
  isSafeThumbnailUrl: () => isSafeThumbnailUrl,
105
131
  isTemplateRecord: () => isTemplateRecord,
132
+ isTrackEventStepPayload: () => isTrackEventStepPayload,
133
+ isTrackingConfig: () => isTrackingConfig,
134
+ isTrackingRelayRequest: () => isTrackingRelayRequest,
106
135
  isValidateOnEvent: () => isValidateOnEvent,
107
136
  isValidationRule: () => isValidationRule,
108
137
  isValidationRuleType: () => isValidationRuleType,
@@ -121,11 +150,212 @@ __export(index_exports, {
121
150
  module.exports = __toCommonJS(index_exports);
122
151
 
123
152
  // src/document.ts
124
- var import_zod3 = require("zod");
153
+ var import_zod4 = require("zod");
125
154
 
126
155
  // src/actions.ts
156
+ var import_zod2 = require("zod");
157
+
158
+ // src/tracking.ts
127
159
  var import_zod = require("zod");
128
- var ActionTriggerTypeSchema = import_zod.z.enum([
160
+ var TrackingProviderTypeSchema = import_zod.z.enum([
161
+ "meta",
162
+ "google",
163
+ "gtm",
164
+ "tiktok",
165
+ "custom"
166
+ ]);
167
+ var TrackingDeliverySchema = import_zod.z.enum(["both", "client_only", "server_only"]);
168
+ var MetaTrackingProviderConfigSchema = import_zod.z.object({
169
+ enabled: import_zod.z.boolean().default(true),
170
+ /** Host credential id; the server resolves the CAPI access token from it. */
171
+ credentialId: import_zod.z.string().optional(),
172
+ /** Meta Pixel ID (e.g. 123456789012345) — public */
173
+ pixelId: import_zod.z.string().optional().default(""),
174
+ /** Enable Server-Side Conversions API (delivered through the host relay) */
175
+ capiEnabled: import_zod.z.boolean().optional().default(false),
176
+ /** Test Event Code from Meta Events Manager (e.g. "TEST12345") — not a secret */
177
+ testEventCode: import_zod.z.string().optional().default("")
178
+ });
179
+ var GoogleTrackingProviderConfigSchema = import_zod.z.object({
180
+ enabled: import_zod.z.boolean().default(true),
181
+ /** Host credential id; the server resolves the Measurement Protocol API secret from it. */
182
+ credentialId: import_zod.z.string().optional(),
183
+ /** GA4 Measurement ID (e.g. "G-XXXXXXXXXX") — public */
184
+ measurementId: import_zod.z.string().optional().default("")
185
+ });
186
+ var GtmTrackingProviderConfigSchema = import_zod.z.object({
187
+ enabled: import_zod.z.boolean().default(true),
188
+ /** Optional linked account/workspace credential ID */
189
+ credentialId: import_zod.z.string().optional(),
190
+ /** GTM Container ID (e.g. "GTM-XXXXXXX") — public */
191
+ containerId: import_zod.z.string().optional().default("")
192
+ });
193
+ var TikTokTrackingProviderConfigSchema = import_zod.z.object({
194
+ enabled: import_zod.z.boolean().default(true),
195
+ /** Host credential id; the server resolves the Events API access token from it. */
196
+ credentialId: import_zod.z.string().optional(),
197
+ /** TikTok Pixel ID (e.g. "C1234567890") — public */
198
+ pixelId: import_zod.z.string().optional().default(""),
199
+ /** Enable TikTok Events API (server-side, delivered through the host relay) */
200
+ eventsApiEnabled: import_zod.z.boolean().optional().default(false),
201
+ /** Test Event Code from TikTok Event Manager — not a secret */
202
+ testEventCode: import_zod.z.string().optional().default("")
203
+ });
204
+ var CustomTrackingProviderConfigSchema = import_zod.z.object({
205
+ enabled: import_zod.z.boolean().default(true),
206
+ /** Host credential id; the server resolves the webhook `endpointUrl` + `headers` from it. */
207
+ credentialId: import_zod.z.string().optional()
208
+ });
209
+ var LEGACY_TRACKING_SECRET_KEYS = Object.freeze({
210
+ meta: ["capiAccessToken", "serverRelayUrl"],
211
+ google: ["measurementProtocolSecret", "serverRelayUrl"],
212
+ gtm: ["serverRelayUrl"],
213
+ tiktok: ["accessToken", "serverRelayUrl"],
214
+ custom: ["endpointUrl", "headers"]
215
+ });
216
+ var TrackingConfigSchema = import_zod.z.object({
217
+ /** Master toggle: dynamically enables or disables all tracking operations */
218
+ enabled: import_zod.z.boolean().default(true),
219
+ /** When enabled, events are logged to console and can bypass live API calls for safe debugging */
220
+ debugMode: import_zod.z.boolean().optional().default(false),
221
+ /** Automatically trigger PageView event upon page load */
222
+ autoPageView: import_zod.z.boolean().optional().default(true),
223
+ /** Default delivery method when not explicitly overridden in an action step */
224
+ defaultDelivery: TrackingDeliverySchema.optional().default("both"),
225
+ /** Provider-specific settings */
226
+ providers: import_zod.z.object({
227
+ meta: MetaTrackingProviderConfigSchema.optional(),
228
+ google: GoogleTrackingProviderConfigSchema.optional(),
229
+ gtm: GtmTrackingProviderConfigSchema.optional(),
230
+ tiktok: TikTokTrackingProviderConfigSchema.optional(),
231
+ custom: CustomTrackingProviderConfigSchema.optional()
232
+ }).optional().default({})
233
+ });
234
+ var MetaTrackingSecretsSchema = import_zod.z.object({
235
+ /** System User access token for the Meta Graph API. */
236
+ capiAccessToken: import_zod.z.string().min(1)
237
+ });
238
+ var GoogleTrackingSecretsSchema = import_zod.z.object({
239
+ /** Measurement Protocol `api_secret`. */
240
+ measurementProtocolSecret: import_zod.z.string().min(1)
241
+ });
242
+ var TikTokTrackingSecretsSchema = import_zod.z.object({
243
+ /** Long-term Events API access token. */
244
+ accessToken: import_zod.z.string().min(1)
245
+ });
246
+ var CustomTrackingSecretsSchema = import_zod.z.object({
247
+ endpointUrl: import_zod.z.string().url(),
248
+ headers: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional()
249
+ });
250
+ var StandardTrackingEventSchema = import_zod.z.enum([
251
+ "PageView",
252
+ "ViewContent",
253
+ "AddToCart",
254
+ "InitiateCheckout",
255
+ "Purchase",
256
+ "Lead",
257
+ "Contact",
258
+ "CompleteRegistration",
259
+ "Subscribe",
260
+ "Search",
261
+ "SubmitApplication",
262
+ "Schedule"
263
+ ]);
264
+ var TrackEventProviderSchema = import_zod.z.enum(["all", "meta", "google", "gtm", "tiktok", "custom"]);
265
+ var TrackEventStepPayloadSchema = import_zod.z.object({
266
+ /** Event name: e.g. "Purchase", "Lead", or custom string */
267
+ eventName: import_zod.z.string().min(1, "Event name cannot be empty"),
268
+ /** Standard event vs custom event identifier */
269
+ eventType: import_zod.z.enum(["standard", "custom"]).optional().default("standard"),
270
+ /**
271
+ * Target provider: 'all' or a specific provider.
272
+ * 'gtm' pushes the event to `window.dataLayer` (client-side only).
273
+ */
274
+ provider: TrackEventProviderSchema.optional().default("all"),
275
+ /** Delivery channel: 'both', 'client_only', or 'server_only' */
276
+ delivery: TrackingDeliverySchema.optional().default("both"),
277
+ /**
278
+ * Deduplication Event ID.
279
+ * If omitted, a unique ID is automatically generated so Meta/TikTok CAPI
280
+ * deduplicates cleanly with the browser pixel.
281
+ */
282
+ eventId: import_zod.z.string().optional(),
283
+ /**
284
+ * Event parameters/properties (e.g. currency, value, content_name, order_id).
285
+ * Supports runtime variable interpolation (e.g. {{ form.price }} or {{ variables.currency }}).
286
+ */
287
+ params: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional().default({}),
288
+ /**
289
+ * User Data for advanced matching and server CAPI (e.g. email, phone, firstName, lastName).
290
+ * Supports runtime variable interpolation (e.g. {{ form.email }}).
291
+ */
292
+ userData: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional().default({}),
293
+ /** Step-level active toggle */
294
+ enabled: import_zod.z.boolean().optional().default(true)
295
+ });
296
+ var TRACKING_RELAY_PROTOCOL_VERSION = 1;
297
+ var ServerTrackingEventSchema = import_zod.z.object({
298
+ eventName: import_zod.z.string().min(1).max(256),
299
+ eventType: import_zod.z.enum(["standard", "custom"]).optional(),
300
+ eventId: import_zod.z.string().max(256).optional(),
301
+ /** Unix epoch seconds. */
302
+ eventTime: import_zod.z.number().int().nonnegative().optional(),
303
+ eventSourceUrl: import_zod.z.string().max(4096).optional(),
304
+ actionSource: import_zod.z.enum(["website", "app", "system_generated"]).optional(),
305
+ params: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional(),
306
+ /** Raw (unhashed) user data; the relay hashes PII per provider spec before forwarding. */
307
+ userData: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional(),
308
+ customData: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
309
+ });
310
+ var TrackingRelayRequestSchema = import_zod.z.object({
311
+ version: import_zod.z.literal(TRACKING_RELAY_PROTOCOL_VERSION),
312
+ event: ServerTrackingEventSchema,
313
+ provider: TrackEventProviderSchema.optional().default("all"),
314
+ /** Optional hint only; the relay uses the credentialId from its trusted config. */
315
+ credentialId: import_zod.z.string().max(256).optional(),
316
+ /** Host document/page id so the relay can look up the trusted tracking config. */
317
+ documentId: import_zod.z.string().max(256).optional()
318
+ });
319
+ var TrackingRelayProviderResultSchema = import_zod.z.object({
320
+ provider: import_zod.z.string(),
321
+ success: import_zod.z.boolean(),
322
+ status: import_zod.z.number().int().optional(),
323
+ skipped: import_zod.z.boolean().optional(),
324
+ reason: import_zod.z.string().optional(),
325
+ error: import_zod.z.string().optional()
326
+ });
327
+ var TrackingRelayErrorCodeSchema = import_zod.z.enum([
328
+ "INVALID_REQUEST",
329
+ "UNSUPPORTED_VERSION",
330
+ "FORBIDDEN_ORIGIN",
331
+ "METHOD_NOT_ALLOWED",
332
+ "CONFIG_NOT_FOUND",
333
+ "INTERNAL_ERROR"
334
+ ]);
335
+ var TrackingRelayResponseSchema = import_zod.z.object({
336
+ version: import_zod.z.literal(TRACKING_RELAY_PROTOCOL_VERSION),
337
+ success: import_zod.z.boolean(),
338
+ eventId: import_zod.z.string().optional(),
339
+ skipped: import_zod.z.boolean().optional(),
340
+ reason: import_zod.z.string().optional(),
341
+ results: import_zod.z.record(import_zod.z.string(), TrackingRelayProviderResultSchema).optional(),
342
+ error: import_zod.z.object({
343
+ code: TrackingRelayErrorCodeSchema,
344
+ message: import_zod.z.string()
345
+ }).optional()
346
+ });
347
+ function isTrackingConfig(value) {
348
+ return TrackingConfigSchema.safeParse(value).success;
349
+ }
350
+ function isTrackEventStepPayload(value) {
351
+ return TrackEventStepPayloadSchema.safeParse(value).success;
352
+ }
353
+ function isTrackingRelayRequest(value) {
354
+ return TrackingRelayRequestSchema.safeParse(value).success;
355
+ }
356
+
357
+ // src/actions.ts
358
+ var ActionTriggerTypeSchema = import_zod2.z.enum([
129
359
  "click",
130
360
  "submit",
131
361
  "change",
@@ -134,7 +364,7 @@ var ActionTriggerTypeSchema = import_zod.z.enum([
134
364
  "load"
135
365
  ]);
136
366
  var ActionTriggerSchema = ActionTriggerTypeSchema;
137
- var ActionStepTypeSchema = import_zod.z.enum([
367
+ var ActionStepTypeSchema = import_zod2.z.enum([
138
368
  "api_request",
139
369
  "navigate",
140
370
  "set_state",
@@ -142,10 +372,12 @@ var ActionStepTypeSchema = import_zod.z.enum([
142
372
  "show_toast",
143
373
  "open_modal",
144
374
  "close_modal",
375
+ "toggle_modal",
145
376
  "copy_clipboard",
146
- "custom_event"
377
+ "custom_event",
378
+ "track_event"
147
379
  ]);
148
- var ConditionOperatorSchema = import_zod.z.enum([
380
+ var ConditionOperatorSchema = import_zod2.z.enum([
149
381
  "equals",
150
382
  "not_equals",
151
383
  "contains",
@@ -158,10 +390,10 @@ var ConditionOperatorSchema = import_zod.z.enum([
158
390
  "lte",
159
391
  "regex"
160
392
  ]);
161
- var ActionStepConditionSchema = import_zod.z.object({
162
- field: import_zod.z.string().min(1, "Condition field cannot be empty"),
393
+ var ActionStepConditionSchema = import_zod2.z.object({
394
+ field: import_zod2.z.string().min(1, "Condition field cannot be empty"),
163
395
  operator: ConditionOperatorSchema,
164
- value: import_zod.z.unknown().optional()
396
+ value: import_zod2.z.unknown().optional()
165
397
  });
166
398
  var DANGEROUS_URL_PATTERN = /(javascript:|vbscript:|data:text\/html)/i;
167
399
  var DANGEROUS_SCRIPT_PATTERN = /<\s*script/i;
@@ -172,68 +404,81 @@ function isSafeActionUrl(url) {
172
404
  if (DANGEROUS_SCRIPT_PATTERN.test(trimmed)) return false;
173
405
  return true;
174
406
  }
175
- var SafeUrlStringSchema = import_zod.z.string().min(1, "URL cannot be empty").refine(isSafeActionUrl, {
407
+ var SafeUrlStringSchema = import_zod2.z.string().min(1, "URL cannot be empty").refine(isSafeActionUrl, {
176
408
  message: "URL contains disallowed or unsafe protocol/script pattern"
177
409
  });
178
- var SafeEventNameSchema = import_zod.z.string().min(1, "Event name cannot be empty").regex(/^[a-zA-Z0-9_\-:]+$/, {
410
+ var SafeEventNameSchema = import_zod2.z.string().min(1, "Event name cannot be empty").regex(/^[a-zA-Z0-9_\-:]+$/, {
179
411
  message: "Event name must contain only alphanumeric characters, dashes, colons, or underscores"
180
412
  });
181
- var ApiRequestStepPayloadSchema = import_zod.z.object({
413
+ var ApiRequestStepPayloadSchema = import_zod2.z.object({
182
414
  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()
415
+ method: import_zod2.z.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]).default("GET"),
416
+ headers: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.string()).optional(),
417
+ queryParams: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.union([import_zod2.z.string(), import_zod2.z.number(), import_zod2.z.boolean()])).optional(),
418
+ body: import_zod2.z.union([import_zod2.z.string(), import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()), import_zod2.z.array(import_zod2.z.unknown())]).optional(),
419
+ bodyFormat: import_zod2.z.enum(["json", "form-data", "formData", "urlencoded", "url-encoded", "raw", "text"]).optional(),
420
+ bodyType: import_zod2.z.enum(["json", "form-data", "formData", "urlencoded", "url-encoded", "raw", "text"]).optional(),
421
+ timeout: import_zod2.z.number().positive("Timeout must be greater than 0 ms").optional(),
422
+ responseMapping: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.string()).optional()
191
423
  });
192
- var NavigateStepPayloadSchema = import_zod.z.object({
424
+ var NavigateStepPayloadSchema = import_zod2.z.object({
193
425
  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()
426
+ target: import_zod2.z.enum(["_self", "_blank", "_parent", "_top"]).optional().default("_self"),
427
+ replace: import_zod2.z.boolean().optional(),
428
+ scroll: import_zod2.z.boolean().optional(),
429
+ behavior: import_zod2.z.enum(["smooth", "auto"]).optional()
198
430
  });
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")
431
+ var SetStateStepPayloadSchema = import_zod2.z.object({
432
+ key: import_zod2.z.string().min(1, "State key cannot be empty"),
433
+ value: import_zod2.z.unknown(),
434
+ scope: import_zod2.z.enum(["runtime", "document", "session", "local"]).optional().default("runtime")
203
435
  });
204
- var ResetFormStepPayloadSchema = import_zod.z.object({
205
- formId: import_zod.z.string().optional()
436
+ var ResetFormStepPayloadSchema = import_zod2.z.object({
437
+ formId: import_zod2.z.string().optional()
206
438
  });
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()
439
+ var ShowToastStepPayloadSchema = import_zod2.z.object({
440
+ message: import_zod2.z.string().min(1, "Toast message cannot be empty"),
441
+ type: import_zod2.z.enum(["success", "error", "warning", "info"]).optional().default("info"),
442
+ variant: import_zod2.z.enum(["success", "error", "warning", "info"]).optional(),
443
+ title: import_zod2.z.string().optional(),
444
+ duration: import_zod2.z.number().nonnegative("Duration must be >= 0 ms").optional(),
445
+ position: import_zod2.z.enum(["top-right", "top-left", "bottom-right", "bottom-left", "top-center", "bottom-center"]).optional()
214
446
  });
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()
447
+ var OpenModalStepPayloadSchema = import_zod2.z.object({
448
+ modalId: import_zod2.z.string().optional(),
449
+ modalNodeId: import_zod2.z.string().optional(),
450
+ toggle: import_zod2.z.boolean().optional()
219
451
  }).refine((data) => Boolean(data.modalId || data.modalNodeId), {
220
452
  message: "Modal ID or Modal Node ID cannot be empty"
221
453
  });
222
- var CloseModalStepPayloadSchema = import_zod.z.object({
223
- modalId: import_zod.z.string().optional(),
224
- modalNodeId: import_zod.z.string().optional()
454
+ var CloseModalStepPayloadSchema = import_zod2.z.object({
455
+ modalId: import_zod2.z.string().optional(),
456
+ modalNodeId: import_zod2.z.string().optional()
225
457
  });
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()
458
+ var ToggleModalStepPayloadSchema = import_zod2.z.object({
459
+ modalId: import_zod2.z.string().optional(),
460
+ modalNodeId: import_zod2.z.string().optional(),
461
+ targetNodeId: import_zod2.z.string().optional(),
462
+ nodeId: import_zod2.z.string().optional()
463
+ }).refine(
464
+ (data) => [data.modalId, data.modalNodeId, data.targetNodeId, data.nodeId].some(
465
+ (id) => typeof id === "string" && id.trim().length > 0
466
+ ),
467
+ {
468
+ message: "Modal ID or Modal Node ID cannot be empty"
469
+ }
470
+ );
471
+ var CopyClipboardStepPayloadSchema = import_zod2.z.object({
472
+ text: import_zod2.z.string().optional(),
473
+ value: import_zod2.z.unknown().optional(),
474
+ notify: import_zod2.z.boolean().optional(),
475
+ toastMessage: import_zod2.z.string().optional()
231
476
  });
232
- var CustomEventStepPayloadSchema = import_zod.z.object({
477
+ var CustomEventStepPayloadSchema = import_zod2.z.object({
233
478
  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)
479
+ detail: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional(),
480
+ bubbles: import_zod2.z.boolean().optional().default(true),
481
+ cancelable: import_zod2.z.boolean().optional().default(true)
237
482
  });
238
483
  var StepPayloadSchemas = {
239
484
  api_request: ApiRequestStepPayloadSchema,
@@ -243,30 +488,32 @@ var StepPayloadSchemas = {
243
488
  show_toast: ShowToastStepPayloadSchema,
244
489
  open_modal: OpenModalStepPayloadSchema,
245
490
  close_modal: CloseModalStepPayloadSchema,
491
+ toggle_modal: ToggleModalStepPayloadSchema,
246
492
  copy_clipboard: CopyClipboardStepPayloadSchema,
247
- custom_event: CustomEventStepPayloadSchema
493
+ custom_event: CustomEventStepPayloadSchema,
494
+ track_event: TrackEventStepPayloadSchema
248
495
  };
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"),
496
+ var ActionStepSchema = import_zod2.z.lazy(
497
+ () => import_zod2.z.object({
498
+ id: import_zod2.z.string().min(1, "Step ID cannot be empty"),
252
499
  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({}),
500
+ label: import_zod2.z.string().optional(),
501
+ payload: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional().default({}),
255
502
  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()
503
+ timeout: import_zod2.z.number().positive().optional(),
504
+ continueOnError: import_zod2.z.boolean().optional(),
505
+ onSuccess: import_zod2.z.array(ActionStepSchema).optional(),
506
+ onError: import_zod2.z.array(ActionStepSchema).optional()
260
507
  })
261
508
  );
262
- var ActionPipelineSchema = import_zod.z.object({
263
- id: import_zod.z.string().min(1, "Pipeline ID cannot be empty"),
509
+ var ActionPipelineSchema = import_zod2.z.object({
510
+ id: import_zod2.z.string().min(1, "Pipeline ID cannot be empty"),
264
511
  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")
512
+ label: import_zod2.z.string().optional(),
513
+ debounceMs: import_zod2.z.number().nonnegative("Debounce ms must be >= 0").optional(),
514
+ preventDuplicate: import_zod2.z.boolean().optional(),
515
+ enabled: import_zod2.z.boolean().optional().default(true),
516
+ steps: import_zod2.z.array(ActionStepSchema).min(1, "Action pipeline must contain at least one step")
270
517
  });
271
518
  function isActionTriggerType(value) {
272
519
  return ActionTriggerTypeSchema.safeParse(value).success;
@@ -291,9 +538,9 @@ function validateActionStepPayload(type, payload) {
291
538
  if (!schema) {
292
539
  return {
293
540
  success: false,
294
- error: new import_zod.z.ZodError([
541
+ error: new import_zod2.z.ZodError([
295
542
  {
296
- code: import_zod.z.ZodIssueCode.custom,
543
+ code: import_zod2.z.ZodIssueCode.custom,
297
544
  message: `Unknown step type: ${type}`,
298
545
  path: ["type"]
299
546
  }
@@ -381,8 +628,8 @@ function sanitizeActionPipeline(pipeline) {
381
628
  }
382
629
 
383
630
  // src/form.ts
384
- var import_zod2 = require("zod");
385
- var ValidationRuleTypeSchema = import_zod2.z.enum([
631
+ var import_zod3 = require("zod");
632
+ var ValidationRuleTypeSchema = import_zod3.z.enum([
386
633
  "required",
387
634
  "email",
388
635
  "url",
@@ -394,29 +641,29 @@ var ValidationRuleTypeSchema = import_zod2.z.enum([
394
641
  "match_field",
395
642
  "custom_regex"
396
643
  ]);
397
- var ValidateOnEventSchema = import_zod2.z.enum(["blur", "change", "submit"]);
398
- var ValidationRuleSchema = import_zod2.z.object({
644
+ var ValidateOnEventSchema = import_zod3.z.enum(["blur", "change", "submit"]);
645
+ var ValidationRuleSchema = import_zod3.z.object({
399
646
  type: ValidationRuleTypeSchema,
400
- value: import_zod2.z.unknown().optional(),
401
- message: import_zod2.z.string().min(1, "Validation error message cannot be empty")
647
+ value: import_zod3.z.unknown().optional(),
648
+ message: import_zod3.z.string().min(1, "Validation error message cannot be empty")
402
649
  });
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([]),
650
+ var FormFieldBindingSchema = import_zod3.z.object({
651
+ name: import_zod3.z.string().min(1, "Field name cannot be empty"),
652
+ label: import_zod3.z.string().optional(),
653
+ defaultValue: import_zod3.z.unknown().optional(),
654
+ rules: import_zod3.z.array(ValidationRuleSchema).optional().default([]),
408
655
  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()
656
+ transform: import_zod3.z.enum(["trim", "lowercase", "uppercase", "number"]).optional(),
657
+ disabled: import_zod3.z.boolean().optional(),
658
+ required: import_zod3.z.boolean().optional()
412
659
  });
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),
660
+ var FormConfigSchema = import_zod3.z.object({
661
+ formId: import_zod3.z.string().min(1, "Form ID cannot be empty"),
662
+ resetOnSubmit: import_zod3.z.boolean().optional().default(false),
663
+ scrollToFirstError: import_zod3.z.boolean().optional().default(true),
417
664
  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()
665
+ initialValues: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).optional(),
666
+ rules: import_zod3.z.array(ValidationRuleSchema).optional()
420
667
  });
421
668
  function isValidationRuleType(value) {
422
669
  return ValidationRuleTypeSchema.safeParse(value).success;
@@ -436,56 +683,56 @@ function isFormConfig(value) {
436
683
 
437
684
  // src/document.ts
438
685
  var SCHEMA_NAME = "stora.page";
439
- var CURRENT_SCHEMA_VERSION = "1.0.0";
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()
686
+ var CURRENT_SCHEMA_VERSION = "1.1.0";
687
+ var AssetReferenceSchema = import_zod4.z.object({
688
+ type: import_zod4.z.literal("asset"),
689
+ assetId: import_zod4.z.string().min(1, "Asset ID cannot be empty"),
690
+ filename: import_zod4.z.string().optional(),
691
+ mimeType: import_zod4.z.string().optional(),
692
+ fallbackUrl: import_zod4.z.string().url().optional()
446
693
  });
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()
694
+ var VariableBindingSchema = import_zod4.z.object({
695
+ type: import_zod4.z.literal("variable"),
696
+ key: import_zod4.z.string().min(1, "Variable key cannot be empty"),
697
+ fallback: import_zod4.z.unknown().optional()
451
698
  });
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()
699
+ var ActionBindingSchema = import_zod4.z.object({
700
+ type: import_zod4.z.string().min(1, "Action type cannot be empty"),
701
+ payload: import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown()).optional()
455
702
  });
456
703
  var DANGEROUS_STYLE_VALUE_PATTERN = /javascript:|expression\(|@import|<script|vbscript:|data:text\/html/i;
457
- var StyleValueSchema = import_zod3.z.union([
458
- import_zod3.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
704
+ var StyleValueSchema = import_zod4.z.union([
705
+ import_zod4.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
459
706
  message: "Style value contains a disallowed or unsafe pattern"
460
707
  }),
461
- import_zod3.z.number(),
462
- import_zod3.z.boolean(),
463
- import_zod3.z.null(),
464
- import_zod3.z.undefined()
708
+ import_zod4.z.number(),
709
+ import_zod4.z.boolean(),
710
+ import_zod4.z.null(),
711
+ import_zod4.z.undefined()
465
712
  ]);
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({
713
+ var StyleDefinitionSchema = import_zod4.z.record(import_zod4.z.string(), StyleValueSchema);
714
+ var PseudoStateStylesSchema = import_zod4.z.record(import_zod4.z.string(), StyleDefinitionSchema);
715
+ var ResponsiveStylesSchema = import_zod4.z.object({
469
716
  base: StyleDefinitionSchema.optional(),
470
717
  desktop: StyleDefinitionSchema.optional(),
471
718
  tablet: StyleDefinitionSchema.optional(),
472
719
  mobile: StyleDefinitionSchema.optional(),
473
720
  states: PseudoStateStylesSchema.optional()
474
721
  }).passthrough().default({});
475
- var AnimationConfigSchema = import_zod3.z.object({
476
- type: import_zod3.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
722
+ var AnimationConfigSchema = import_zod4.z.object({
723
+ type: import_zod4.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
477
724
  message: "Animation type contains a disallowed or unsafe pattern"
478
725
  }).optional().default("none"),
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), {
726
+ duration: import_zod4.z.number().min(0, "Duration must be non-negative").optional().default(600),
727
+ delay: import_zod4.z.number().min(0, "Delay must be non-negative").optional().default(0),
728
+ easing: import_zod4.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
482
729
  message: "Animation easing contains a disallowed or unsafe pattern"
483
730
  }).optional().default("ease-out"),
484
- once: import_zod3.z.boolean().optional().default(true),
485
- hoverEffect: import_zod3.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
731
+ once: import_zod4.z.boolean().optional().default(true),
732
+ hoverEffect: import_zod4.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
486
733
  message: "Hover effect contains a disallowed or unsafe pattern"
487
734
  }).optional().default("none"),
488
- loopEffect: import_zod3.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
735
+ loopEffect: import_zod4.z.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
489
736
  message: "Loop effect contains a disallowed or unsafe pattern"
490
737
  }).optional().default("none")
491
738
  });
@@ -498,16 +745,16 @@ var DEFAULT_ANIMATION_CONFIG = {
498
745
  hoverEffect: "none",
499
746
  loopEffect: "none"
500
747
  };
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({}),
748
+ var NodeSchema = import_zod4.z.lazy(
749
+ () => import_zod4.z.object({
750
+ id: import_zod4.z.string().min(1, "Node ID must be a non-empty string"),
751
+ type: import_zod4.z.string().min(1, "Node type must be a non-empty string"),
752
+ props: import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown()).optional().default({}),
506
753
  styles: ResponsiveStylesSchema.optional().default({}),
507
754
  animation: AnimationConfigSchema.optional(),
508
- actions: import_zod3.z.array(ActionPipelineSchema).optional(),
755
+ actions: import_zod4.z.array(ActionPipelineSchema).optional(),
509
756
  formConfig: FormConfigSchema.optional(),
510
- children: import_zod3.z.array(NodeSchema).optional().default([])
757
+ children: import_zod4.z.array(NodeSchema).optional().default([])
511
758
  })
512
759
  );
513
760
  var RootPageNodeSchema = NodeSchema.refine(
@@ -517,61 +764,64 @@ var RootPageNodeSchema = NodeSchema.refine(
517
764
  path: ["type"]
518
765
  }
519
766
  );
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()
767
+ var DocumentMetadataSchema = import_zod4.z.object({
768
+ title: import_zod4.z.string().min(1, "Title is required").default("Untitled Page"),
769
+ description: import_zod4.z.string().optional().default(""),
770
+ author: import_zod4.z.string().optional().default(""),
771
+ createdAt: import_zod4.z.string().optional(),
772
+ updatedAt: import_zod4.z.string().optional(),
773
+ tags: import_zod4.z.array(import_zod4.z.string()).optional().default([]),
774
+ category: import_zod4.z.string().optional().default("general"),
775
+ version: import_zod4.z.string().optional().default("1.0.0"),
776
+ custom: import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown()).optional(),
777
+ tracking: TrackingConfigSchema.optional()
530
778
  });
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),
779
+ var PageDocumentSchema = import_zod4.z.object({
780
+ schema: import_zod4.z.literal(SCHEMA_NAME),
781
+ version: import_zod4.z.string().min(1, "Schema version is required").default(CURRENT_SCHEMA_VERSION),
534
782
  metadata: DocumentMetadataSchema.optional(),
783
+ tracking: TrackingConfigSchema.optional(),
535
784
  document: RootPageNodeSchema
536
785
  });
537
786
  var PROJECT_SCHEMA_NAME = "stora.project";
538
787
  var CURRENT_PROJECT_SCHEMA_VERSION = "1.0.0";
539
788
  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"),
789
+ var ArtboardTypeSchema = import_zod4.z.enum(["page", "component"]);
790
+ var ArtboardSchema = import_zod4.z.object({
791
+ id: import_zod4.z.string().min(1, "Artboard ID is required"),
792
+ name: import_zod4.z.string().min(1, "Artboard name is required"),
544
793
  artboardType: ArtboardTypeSchema,
545
794
  /** Route for page artboards (e.g. "/about"). */
546
- slug: import_zod3.z.string().optional(),
795
+ slug: import_zod4.z.string().optional(),
547
796
  /**
548
797
  * For component artboards: the id that `open_modal` / `close_modal` actions target.
549
798
  * Mirrors the detached node's own `props.modalId` so ModalManager keeps working unchanged.
550
799
  */
551
- triggerId: import_zod3.z.string().optional(),
800
+ triggerId: import_zod4.z.string().optional(),
552
801
  /**
553
802
  * Viewport/breakpoint this artboard is currently authored at. Declared inline
554
803
  * (rather than imported) because viewport is otherwise an editor/renderer concept.
555
804
  */
556
- viewport: import_zod3.z.enum(["desktop", "tablet", "mobile"]).optional(),
805
+ viewport: import_zod4.z.enum(["desktop", "tablet", "mobile"]).optional(),
557
806
  /** Persisted artboard width in px, matching the canvas ViewportResizer's `width`. */
558
- width: import_zod3.z.number().positive().optional(),
807
+ width: import_zod4.z.number().positive().optional(),
559
808
  /**
560
809
  * Free position on the builder's infinite canvas, in unscaled canvas px. Absent means
561
810
  * "not placed yet" — the canvas then falls back to laying the artboard out in a row.
562
811
  */
563
- position: import_zod3.z.object({
564
- x: import_zod3.z.number(),
565
- y: import_zod3.z.number()
812
+ position: import_zod4.z.object({
813
+ x: import_zod4.z.number(),
814
+ y: import_zod4.z.number()
566
815
  }).optional(),
567
816
  document: PageDocumentSchema
568
817
  });
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),
818
+ var ProjectDocumentSchema = import_zod4.z.object({
819
+ schema: import_zod4.z.literal(PROJECT_SCHEMA_NAME),
820
+ version: import_zod4.z.string().min(1, "Schema version is required").default(CURRENT_PROJECT_SCHEMA_VERSION),
572
821
  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()
822
+ tracking: TrackingConfigSchema.optional(),
823
+ artboards: import_zod4.z.array(ArtboardSchema).min(1, "A project needs at least one artboard"),
824
+ activeArtboardId: import_zod4.z.string().optional()
575
825
  });
576
826
  function isAssetReference(value) {
577
827
  return AssetReferenceSchema.safeParse(value).success;
@@ -627,30 +877,30 @@ function validateNodeIdUniqueness(node) {
627
877
  }
628
878
 
629
879
  // src/manifest.ts
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()
880
+ var import_zod5 = require("zod");
881
+ var ManifestAssetItemSchema = import_zod5.z.object({
882
+ id: import_zod5.z.string().min(1, "Asset ID cannot be empty"),
883
+ path: import_zod5.z.string().min(1, "Asset archive path cannot be empty"),
884
+ mimeType: import_zod5.z.string().min(1, "MIME type cannot be empty"),
885
+ size: import_zod5.z.number().nonnegative("Asset size must be non-negative"),
886
+ checksum: import_zod5.z.string().optional()
637
887
  });
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()
888
+ var ManifestSchema = import_zod5.z.object({
889
+ schema: import_zod5.z.literal(SCHEMA_NAME).default(SCHEMA_NAME),
890
+ schemaVersion: import_zod5.z.string().min(1, "Schema version cannot be empty").default("1.0.0"),
891
+ packageVersion: import_zod5.z.string().min(1, "Package version cannot be empty").default("1.0.0"),
892
+ builderCompatibility: import_zod5.z.string().default(">=0.1.0"),
893
+ requiredComponents: import_zod5.z.array(import_zod5.z.string()).default([]),
894
+ requiredCapabilities: import_zod5.z.array(import_zod5.z.string()).default([]),
895
+ assets: import_zod5.z.array(ManifestAssetItemSchema).default([]),
896
+ createdAt: import_zod5.z.string().optional()
647
897
  });
648
898
  function isManifest(value) {
649
899
  return ManifestSchema.safeParse(value).success;
650
900
  }
651
901
 
652
902
  // src/template.ts
653
- var import_zod5 = require("zod");
903
+ var import_zod6 = require("zod");
654
904
  var DANGEROUS_URI_PATTERN = /^(javascript:|vbscript:|data:(?!image\/))|<script/i;
655
905
  function isSafeThumbnailUrl(url) {
656
906
  if (!url || typeof url !== "string") return false;
@@ -659,49 +909,49 @@ function isSafeThumbnailUrl(url) {
659
909
  if (DANGEROUS_URI_PATTERN.test(trimmed)) return false;
660
910
  return true;
661
911
  }
662
- var SafeThumbnailUrlSchema = import_zod5.z.string().min(1, "Thumbnail URL cannot be empty").refine(
912
+ var SafeThumbnailUrlSchema = import_zod6.z.string().min(1, "Thumbnail URL cannot be empty").refine(
663
913
  (url) => isSafeThumbnailUrl(url),
664
914
  { message: "Thumbnail URL contains an unsafe protocol or payload" }
665
915
  );
666
- var SafeThumbnailObjectSchema = import_zod5.z.object({
916
+ var SafeThumbnailObjectSchema = import_zod6.z.object({
667
917
  url: SafeThumbnailUrlSchema,
668
- alt: import_zod5.z.string().optional(),
669
- width: import_zod5.z.number().positive().optional(),
670
- height: import_zod5.z.number().positive().optional()
918
+ alt: import_zod6.z.string().optional(),
919
+ width: import_zod6.z.number().positive().optional(),
920
+ height: import_zod6.z.number().positive().optional()
671
921
  });
672
- var SafeThumbnailSchema = import_zod5.z.union([
922
+ var SafeThumbnailSchema = import_zod6.z.union([
673
923
  AssetReferenceSchema,
674
924
  SafeThumbnailObjectSchema,
675
925
  SafeThumbnailUrlSchema
676
926
  ]);
677
- var TemplatePackageRefSchema = import_zod5.z.object({
678
- path: import_zod5.z.string().optional(),
927
+ var TemplatePackageRefSchema = import_zod6.z.object({
928
+ path: import_zod6.z.string().optional(),
679
929
  url: SafeThumbnailUrlSchema.optional(),
680
- checksum: import_zod5.z.string().optional(),
681
- format: import_zod5.z.enum(["stora", "json"]).default("stora")
930
+ checksum: import_zod6.z.string().optional(),
931
+ format: import_zod6.z.enum(["stora", "json"]).default("stora")
682
932
  });
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([])
933
+ var TemplateRequirementsSchema = import_zod6.z.object({
934
+ requiredComponents: import_zod6.z.array(import_zod6.z.string()).default([]),
935
+ requiredCapabilities: import_zod6.z.array(import_zod6.z.string()).default([])
686
936
  });
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([]),
937
+ var TemplateRecordSchema = import_zod6.z.object({
938
+ id: import_zod6.z.string().min(1, "Template ID must be a non-empty string"),
939
+ name: import_zod6.z.string().min(1, "Template name must be a non-empty string"),
940
+ description: import_zod6.z.string().optional().default(""),
941
+ category: import_zod6.z.string().optional().default("general"),
942
+ tags: import_zod6.z.array(import_zod6.z.string()).optional().default([]),
693
943
  thumbnail: SafeThumbnailSchema.optional(),
694
- author: import_zod5.z.string().optional().default(""),
695
- version: import_zod5.z.string().optional().default("1.0.0"),
944
+ author: import_zod6.z.string().optional().default(""),
945
+ version: import_zod6.z.string().optional().default("1.0.0"),
696
946
  document: PageDocumentSchema.optional(),
697
947
  packageReference: TemplatePackageRefSchema.optional(),
698
948
  requirements: TemplateRequirementsSchema.default({
699
949
  requiredComponents: [],
700
950
  requiredCapabilities: []
701
951
  }),
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()
952
+ createdAt: import_zod6.z.string().optional(),
953
+ updatedAt: import_zod6.z.string().optional(),
954
+ custom: import_zod6.z.record(import_zod6.z.string(), import_zod6.z.unknown()).optional()
705
955
  });
706
956
  function isTemplateRecord(value) {
707
957
  return TemplateRecordSchema.safeParse(value).success;
@@ -713,7 +963,7 @@ function isSafeThumbnail(value) {
713
963
  // src/fixtures/starter-page.json
714
964
  var starter_page_default = {
715
965
  schema: "stora.page",
716
- version: "1.0.0",
966
+ version: "1.1.0",
717
967
  metadata: {
718
968
  title: "Welcome to KUBUILD",
719
969
  description: "A starter template built with KUBUILD portable web builder",
@@ -872,6 +1122,7 @@ var starter_page_default = {
872
1122
  var starterPageFixture = starter_page_default;
873
1123
 
874
1124
  // src/json-schema.ts
1125
+ var import_zod7 = require("zod");
875
1126
  var PAGE_DOCUMENT_JSON_SCHEMA_V1 = {
876
1127
  $schema: "http://json-schema.org/draft-07/schema#",
877
1128
  $id: "https://schema.stora.page/v1/page.json",
@@ -890,16 +1141,84 @@ var PAGE_DOCUMENT_JSON_SCHEMA_V1 = {
890
1141
  type: "string",
891
1142
  pattern: "^\\d+(\\.\\d+)*$",
892
1143
  description: "Schema version of the document",
893
- default: "1.0.0"
1144
+ default: "1.1.0"
894
1145
  },
895
1146
  metadata: {
896
1147
  $ref: "#/definitions/documentMetadata"
897
1148
  },
898
1149
  document: {
899
1150
  $ref: "#/definitions/rootPageNode"
1151
+ },
1152
+ tracking: {
1153
+ $ref: "#/definitions/trackingConfig"
900
1154
  }
901
1155
  },
902
1156
  definitions: {
1157
+ trackingConfig: {
1158
+ type: "object",
1159
+ description: "Tracking configuration. Contains only public ids, flags and opaque credential ids \u2014 secrets are host-owned.",
1160
+ properties: {
1161
+ enabled: { type: "boolean", default: true },
1162
+ debugMode: { type: "boolean", default: false },
1163
+ autoPageView: { type: "boolean", default: true },
1164
+ defaultDelivery: { type: "string", enum: ["both", "client_only", "server_only"], default: "both" },
1165
+ providers: {
1166
+ type: "object",
1167
+ properties: {
1168
+ meta: {
1169
+ type: "object",
1170
+ properties: {
1171
+ enabled: { type: "boolean" },
1172
+ credentialId: { type: "string" },
1173
+ pixelId: { type: "string" },
1174
+ capiEnabled: { type: "boolean" },
1175
+ testEventCode: { type: "string" }
1176
+ },
1177
+ additionalProperties: false
1178
+ },
1179
+ google: {
1180
+ type: "object",
1181
+ properties: {
1182
+ enabled: { type: "boolean" },
1183
+ credentialId: { type: "string" },
1184
+ measurementId: { type: "string" }
1185
+ },
1186
+ additionalProperties: false
1187
+ },
1188
+ gtm: {
1189
+ type: "object",
1190
+ properties: {
1191
+ enabled: { type: "boolean" },
1192
+ credentialId: { type: "string" },
1193
+ containerId: { type: "string" }
1194
+ },
1195
+ additionalProperties: false
1196
+ },
1197
+ tiktok: {
1198
+ type: "object",
1199
+ properties: {
1200
+ enabled: { type: "boolean" },
1201
+ credentialId: { type: "string" },
1202
+ pixelId: { type: "string" },
1203
+ eventsApiEnabled: { type: "boolean" },
1204
+ testEventCode: { type: "string" }
1205
+ },
1206
+ additionalProperties: false
1207
+ },
1208
+ custom: {
1209
+ type: "object",
1210
+ properties: {
1211
+ enabled: { type: "boolean" },
1212
+ credentialId: { type: "string" }
1213
+ },
1214
+ additionalProperties: false
1215
+ }
1216
+ },
1217
+ additionalProperties: false
1218
+ }
1219
+ },
1220
+ additionalProperties: false
1221
+ },
903
1222
  styleValue: {
904
1223
  type: ["string", "number", "boolean", "null"],
905
1224
  description: "A CSS property or design token value"
@@ -1039,8 +1358,10 @@ var PAGE_DOCUMENT_JSON_SCHEMA_V1 = {
1039
1358
  "show_toast",
1040
1359
  "open_modal",
1041
1360
  "close_modal",
1361
+ "toggle_modal",
1042
1362
  "copy_clipboard",
1043
- "custom_event"
1363
+ "custom_event",
1364
+ "track_event"
1044
1365
  ]
1045
1366
  },
1046
1367
  label: { type: "string" },
@@ -1561,8 +1882,10 @@ var ACTION_PIPELINE_JSON_SCHEMA_V1 = {
1561
1882
  "show_toast",
1562
1883
  "open_modal",
1563
1884
  "close_modal",
1885
+ "toggle_modal",
1564
1886
  "copy_clipboard",
1565
- "custom_event"
1887
+ "custom_event",
1888
+ "track_event"
1566
1889
  ]
1567
1890
  },
1568
1891
  label: { type: "string" },
@@ -1729,6 +2052,48 @@ var FORM_FIELD_BINDING_JSON_SCHEMA_V1 = {
1729
2052
  function getFormFieldBindingJsonSchema() {
1730
2053
  return FORM_FIELD_BINDING_JSON_SCHEMA_V1;
1731
2054
  }
2055
+ function toDraft7(schema, id, title, io) {
2056
+ return {
2057
+ ...import_zod7.z.toJSONSchema(schema, { target: "draft-7", io }),
2058
+ $id: id,
2059
+ title
2060
+ };
2061
+ }
2062
+ var trackingRelayRequestJsonSchema;
2063
+ var trackingRelayResponseJsonSchema;
2064
+ var trackingProviderSecretsJsonSchema;
2065
+ function getTrackingRelayRequestJsonSchema() {
2066
+ trackingRelayRequestJsonSchema ??= toDraft7(
2067
+ TrackingRelayRequestSchema,
2068
+ "https://schema.stora.page/v1/tracking-relay-request.json",
2069
+ "StoraTrackingRelayRequest",
2070
+ "input"
2071
+ );
2072
+ return trackingRelayRequestJsonSchema;
2073
+ }
2074
+ function getTrackingRelayResponseJsonSchema() {
2075
+ trackingRelayResponseJsonSchema ??= toDraft7(
2076
+ TrackingRelayResponseSchema,
2077
+ "https://schema.stora.page/v1/tracking-relay-response.json",
2078
+ "StoraTrackingRelayResponse",
2079
+ "output"
2080
+ );
2081
+ return trackingRelayResponseJsonSchema;
2082
+ }
2083
+ function getTrackingProviderSecretsJsonSchema() {
2084
+ trackingProviderSecretsJsonSchema ??= toDraft7(
2085
+ import_zod7.z.object({
2086
+ meta: MetaTrackingSecretsSchema.optional(),
2087
+ google: GoogleTrackingSecretsSchema.optional(),
2088
+ tiktok: TikTokTrackingSecretsSchema.optional(),
2089
+ custom: CustomTrackingSecretsSchema.optional()
2090
+ }),
2091
+ "https://schema.stora.page/v1/tracking-provider-secrets.json",
2092
+ "StoraTrackingProviderSecrets",
2093
+ "input"
2094
+ );
2095
+ return trackingProviderSecretsJsonSchema;
2096
+ }
1732
2097
  // Annotate the CommonJS export names for ESM import in node:
1733
2098
  0 && (module.exports = {
1734
2099
  ACTION_PIPELINE_JSON_SCHEMA_V1,
@@ -1751,15 +2116,23 @@ function getFormFieldBindingJsonSchema() {
1751
2116
  ConditionOperatorSchema,
1752
2117
  CopyClipboardStepPayloadSchema,
1753
2118
  CustomEventStepPayloadSchema,
2119
+ CustomTrackingProviderConfigSchema,
2120
+ CustomTrackingSecretsSchema,
1754
2121
  DEFAULT_ANIMATION_CONFIG,
1755
2122
  DocumentMetadataSchema,
1756
2123
  FORM_CONFIG_JSON_SCHEMA_V1,
1757
2124
  FORM_FIELD_BINDING_JSON_SCHEMA_V1,
1758
2125
  FormConfigSchema,
1759
2126
  FormFieldBindingSchema,
2127
+ GoogleTrackingProviderConfigSchema,
2128
+ GoogleTrackingSecretsSchema,
2129
+ GtmTrackingProviderConfigSchema,
2130
+ LEGACY_TRACKING_SECRET_KEYS,
1760
2131
  MANIFEST_JSON_SCHEMA_V1,
1761
2132
  ManifestAssetItemSchema,
1762
2133
  ManifestSchema,
2134
+ MetaTrackingProviderConfigSchema,
2135
+ MetaTrackingSecretsSchema,
1763
2136
  NavigateStepPayloadSchema,
1764
2137
  NodeSchema,
1765
2138
  OpenModalStepPayloadSchema,
@@ -1775,15 +2148,30 @@ function getFormFieldBindingJsonSchema() {
1775
2148
  SafeThumbnailObjectSchema,
1776
2149
  SafeThumbnailSchema,
1777
2150
  SafeThumbnailUrlSchema,
2151
+ ServerTrackingEventSchema,
1778
2152
  SetStateStepPayloadSchema,
1779
2153
  ShowToastStepPayloadSchema,
2154
+ StandardTrackingEventSchema,
1780
2155
  StepPayloadSchemas,
1781
2156
  StyleDefinitionSchema,
1782
2157
  StyleValueSchema,
1783
2158
  TEMPLATE_RECORD_JSON_SCHEMA_V1,
2159
+ TRACKING_RELAY_PROTOCOL_VERSION,
1784
2160
  TemplatePackageRefSchema,
1785
2161
  TemplateRecordSchema,
1786
2162
  TemplateRequirementsSchema,
2163
+ TikTokTrackingProviderConfigSchema,
2164
+ TikTokTrackingSecretsSchema,
2165
+ ToggleModalStepPayloadSchema,
2166
+ TrackEventProviderSchema,
2167
+ TrackEventStepPayloadSchema,
2168
+ TrackingConfigSchema,
2169
+ TrackingDeliverySchema,
2170
+ TrackingProviderTypeSchema,
2171
+ TrackingRelayErrorCodeSchema,
2172
+ TrackingRelayProviderResultSchema,
2173
+ TrackingRelayRequestSchema,
2174
+ TrackingRelayResponseSchema,
1787
2175
  ValidateOnEventSchema,
1788
2176
  ValidationRuleSchema,
1789
2177
  ValidationRuleTypeSchema,
@@ -1796,6 +2184,9 @@ function getFormFieldBindingJsonSchema() {
1796
2184
  getManifestJsonSchema,
1797
2185
  getPageDocumentJsonSchema,
1798
2186
  getTemplateRecordJsonSchema,
2187
+ getTrackingProviderSecretsJsonSchema,
2188
+ getTrackingRelayRequestJsonSchema,
2189
+ getTrackingRelayResponseJsonSchema,
1799
2190
  isActionBinding,
1800
2191
  isActionPipeline,
1801
2192
  isActionStep,
@@ -1814,6 +2205,9 @@ function getFormFieldBindingJsonSchema() {
1814
2205
  isSafeThumbnail,
1815
2206
  isSafeThumbnailUrl,
1816
2207
  isTemplateRecord,
2208
+ isTrackEventStepPayload,
2209
+ isTrackingConfig,
2210
+ isTrackingRelayRequest,
1817
2211
  isValidateOnEvent,
1818
2212
  isValidationRule,
1819
2213
  isValidationRuleType,