@constela/core 0.3.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -10,6 +10,14 @@ declare const UPDATE_OPERATIONS: readonly ["increment", "decrement", "push", "po
10
10
  type UpdateOperation = (typeof UPDATE_OPERATIONS)[number];
11
11
  declare const HTTP_METHODS: readonly ["GET", "POST", "PUT", "DELETE"];
12
12
  type HttpMethod = (typeof HTTP_METHODS)[number];
13
+ declare const STORAGE_OPERATIONS: readonly ["get", "set", "remove"];
14
+ type StorageOperation = (typeof STORAGE_OPERATIONS)[number];
15
+ declare const STORAGE_TYPES: readonly ["local", "session"];
16
+ type StorageType = (typeof STORAGE_TYPES)[number];
17
+ declare const CLIPBOARD_OPERATIONS: readonly ["write", "read"];
18
+ type ClipboardOperation = (typeof CLIPBOARD_OPERATIONS)[number];
19
+ declare const NAVIGATE_TARGETS: readonly ["_self", "_blank"];
20
+ type NavigateTarget = (typeof NAVIGATE_TARGETS)[number];
13
21
  declare const PARAM_TYPES: readonly ["string", "number", "boolean", "json"];
14
22
  type ParamType = (typeof PARAM_TYPES)[number];
15
23
  interface ParamDef {
@@ -79,7 +87,31 @@ interface GetExpr {
79
87
  base: Expression;
80
88
  path: string;
81
89
  }
82
- type Expression = LitExpr | StateExpr | VarExpr | BinExpr | NotExpr | ParamExpr | CondExpr | GetExpr;
90
+ /**
91
+ * Route expression - references route parameters
92
+ */
93
+ interface RouteExpr {
94
+ expr: 'route';
95
+ name: string;
96
+ source?: 'param' | 'query' | 'path';
97
+ }
98
+ /**
99
+ * Import expression - references imported external data
100
+ */
101
+ interface ImportExpr {
102
+ expr: 'import';
103
+ name: string;
104
+ path?: string;
105
+ }
106
+ /**
107
+ * Data expression - references loaded data from data sources
108
+ */
109
+ interface DataExpr {
110
+ expr: 'data';
111
+ name: string;
112
+ path?: string;
113
+ }
114
+ type Expression = LitExpr | StateExpr | VarExpr | BinExpr | NotExpr | ParamExpr | CondExpr | GetExpr | RouteExpr | ImportExpr | DataExpr;
83
115
  /**
84
116
  * Number state field
85
117
  */
@@ -164,7 +196,40 @@ interface FetchStep {
164
196
  onSuccess?: ActionStep[];
165
197
  onError?: ActionStep[];
166
198
  }
167
- type ActionStep = SetStep | UpdateStep | FetchStep;
199
+ /**
200
+ * Storage step - localStorage/sessionStorage operations
201
+ */
202
+ interface StorageStep {
203
+ do: 'storage';
204
+ operation: StorageOperation;
205
+ key: Expression;
206
+ value?: Expression;
207
+ storage: StorageType;
208
+ result?: string;
209
+ onSuccess?: ActionStep[];
210
+ onError?: ActionStep[];
211
+ }
212
+ /**
213
+ * Clipboard step - clipboard API operations
214
+ */
215
+ interface ClipboardStep {
216
+ do: 'clipboard';
217
+ operation: ClipboardOperation;
218
+ value?: Expression;
219
+ result?: string;
220
+ onSuccess?: ActionStep[];
221
+ onError?: ActionStep[];
222
+ }
223
+ /**
224
+ * Navigate step - page navigation
225
+ */
226
+ interface NavigateStep {
227
+ do: 'navigate';
228
+ url: Expression;
229
+ target?: NavigateTarget;
230
+ replace?: boolean;
231
+ }
232
+ type ActionStep = SetStep | UpdateStep | FetchStep | StorageStep | ClipboardStep | NavigateStep;
168
233
  /**
169
234
  * Event handler - binds an event to an action
170
235
  */
@@ -227,26 +292,109 @@ interface ComponentNode {
227
292
  }
228
293
  /**
229
294
  * Slot node - placeholder for children in component definition
295
+ * For layouts, can have an optional name for named slots
230
296
  */
231
297
  interface SlotNode {
232
298
  kind: 'slot';
299
+ name?: string;
300
+ }
301
+ /**
302
+ * Markdown node - renders markdown content
303
+ */
304
+ interface MarkdownNode {
305
+ kind: 'markdown';
306
+ content: Expression;
233
307
  }
234
- type ViewNode = ElementNode | TextNode | IfNode | EachNode | ComponentNode | SlotNode;
308
+ /**
309
+ * Code node - renders syntax-highlighted code
310
+ */
311
+ interface CodeNode {
312
+ kind: 'code';
313
+ language: Expression;
314
+ content: Expression;
315
+ }
316
+ type ViewNode = ElementNode | TextNode | IfNode | EachNode | ComponentNode | SlotNode | MarkdownNode | CodeNode;
235
317
  interface ComponentDef {
236
318
  params?: Record<string, ParamDef>;
237
319
  view: ViewNode;
238
320
  }
321
+ /**
322
+ * Data transform types for build-time content loading
323
+ */
324
+ declare const DATA_TRANSFORMS: readonly ["mdx", "yaml", "csv"];
325
+ type DataTransform = (typeof DATA_TRANSFORMS)[number];
326
+ /**
327
+ * Data source types
328
+ */
329
+ declare const DATA_SOURCE_TYPES: readonly ["glob", "file", "api"];
330
+ type DataSourceType = (typeof DATA_SOURCE_TYPES)[number];
331
+ /**
332
+ * Data source for build-time content loading
333
+ */
334
+ interface DataSource {
335
+ type: DataSourceType;
336
+ pattern?: string;
337
+ path?: string;
338
+ url?: string;
339
+ transform?: DataTransform;
340
+ }
341
+ /**
342
+ * Static paths definition for SSG
343
+ */
344
+ interface StaticPathsDefinition {
345
+ source: string;
346
+ params: Record<string, Expression>;
347
+ }
348
+ /**
349
+ * Route definition for a page
350
+ */
351
+ interface RouteDefinition {
352
+ path: string;
353
+ title?: Expression;
354
+ layout?: string;
355
+ meta?: Record<string, Expression>;
356
+ getStaticPaths?: StaticPathsDefinition;
357
+ }
358
+ /**
359
+ * Lifecycle hooks for component/page lifecycle events
360
+ */
361
+ interface LifecycleHooks {
362
+ onMount?: string;
363
+ onUnmount?: string;
364
+ onRouteEnter?: string;
365
+ onRouteLeave?: string;
366
+ }
239
367
  /**
240
368
  * Program - the root of a Constela AST
241
369
  */
242
370
  interface Program {
243
371
  version: '1.0';
372
+ route?: RouteDefinition;
373
+ imports?: Record<string, string>;
374
+ data?: Record<string, DataSource>;
375
+ lifecycle?: LifecycleHooks;
244
376
  state: Record<string, StateField>;
245
377
  actions: ActionDefinition[];
246
378
  view: ViewNode;
247
379
  components?: Record<string, ComponentDef>;
248
380
  }
249
381
  type ConstelaAst = Program;
382
+ /**
383
+ * Layout program - a special type of program that wraps page content
384
+ * Must contain at least one SlotNode in the view tree
385
+ */
386
+ interface LayoutProgram {
387
+ version: '1.0';
388
+ type: 'layout';
389
+ state?: Record<string, StateField>;
390
+ actions?: ActionDefinition[];
391
+ view: ViewNode;
392
+ components?: Record<string, ComponentDef>;
393
+ }
394
+ /**
395
+ * Union type for both regular Program and LayoutProgram
396
+ */
397
+ type ConstelaProgram = Program | LayoutProgram;
250
398
 
251
399
  /**
252
400
  * Type Guards for Constela AST Types
@@ -310,6 +458,30 @@ declare function isCondExpr(value: unknown): value is CondExpr;
310
458
  * Use the AST validator for full recursive validation instead.
311
459
  */
312
460
  declare function isGetExpr(value: unknown): value is GetExpr;
461
+ /**
462
+ * Checks if value is a route expression
463
+ */
464
+ declare function isRouteExpr(value: unknown): value is RouteExpr;
465
+ /**
466
+ * Checks if value is an import expression
467
+ */
468
+ declare function isImportExpr(value: unknown): value is ImportExpr;
469
+ /**
470
+ * Checks if value is a data expression
471
+ */
472
+ declare function isDataExpr(value: unknown): value is DataExpr;
473
+ /**
474
+ * Checks if value is a data source
475
+ */
476
+ declare function isDataSource(value: unknown): value is DataSource;
477
+ /**
478
+ * Checks if value is a static paths definition
479
+ */
480
+ declare function isStaticPathsDefinition(value: unknown): value is StaticPathsDefinition;
481
+ /**
482
+ * Checks if value is a route definition
483
+ */
484
+ declare function isRouteDefinition(value: unknown): value is RouteDefinition;
313
485
  /**
314
486
  * Checks if value is any valid expression
315
487
  */
@@ -338,6 +510,14 @@ declare function isComponentNode(value: unknown): value is ComponentNode;
338
510
  * Checks if value is a slot node
339
511
  */
340
512
  declare function isSlotNode(value: unknown): value is SlotNode;
513
+ /**
514
+ * Checks if value is a markdown node
515
+ */
516
+ declare function isMarkdownNode(value: unknown): value is MarkdownNode;
517
+ /**
518
+ * Checks if value is a code node
519
+ */
520
+ declare function isCodeNode(value: unknown): value is CodeNode;
341
521
  /**
342
522
  * Checks if value is any valid view node
343
523
  */
@@ -354,6 +534,18 @@ declare function isUpdateStep(value: unknown): value is UpdateStep;
354
534
  * Checks if value is a fetch step
355
535
  */
356
536
  declare function isFetchStep(value: unknown): value is FetchStep;
537
+ /**
538
+ * Checks if value is a storage step
539
+ */
540
+ declare function isStorageStep(value: unknown): value is StorageStep;
541
+ /**
542
+ * Checks if value is a clipboard step
543
+ */
544
+ declare function isClipboardStep(value: unknown): value is ClipboardStep;
545
+ /**
546
+ * Checks if value is a navigate step
547
+ */
548
+ declare function isNavigateStep(value: unknown): value is NavigateStep;
357
549
  /**
358
550
  * Checks if value is any valid action step
359
551
  */
@@ -386,6 +578,23 @@ declare function isStateField(value: unknown): value is StateField;
386
578
  * Checks if value is an event handler
387
579
  */
388
580
  declare function isEventHandler(value: unknown): value is EventHandler;
581
+ /**
582
+ * Checks if value is a layout program
583
+ */
584
+ declare function isLayoutProgram(value: unknown): value is LayoutProgram;
585
+ /**
586
+ * Checks if value is a named slot node (slot with a name property)
587
+ */
588
+ declare function isNamedSlotNode(value: unknown): value is SlotNode & {
589
+ name: string;
590
+ };
591
+ /**
592
+ * Checks if value is a lifecycle hooks object
593
+ *
594
+ * Lifecycle hooks are permissive - they allow unknown properties for extensibility.
595
+ * Only known properties are validated to be strings.
596
+ */
597
+ declare function isLifecycleHooks(value: unknown): value is LifecycleHooks;
389
598
 
390
599
  /**
391
600
  * Error Types for Constela
@@ -393,7 +602,7 @@ declare function isEventHandler(value: unknown): value is EventHandler;
393
602
  * This module defines error types, the ConstelaError class,
394
603
  * and factory functions for creating specific errors.
395
604
  */
396
- type ErrorCode = 'SCHEMA_INVALID' | 'UNDEFINED_STATE' | 'UNDEFINED_ACTION' | 'VAR_UNDEFINED' | 'DUPLICATE_ACTION' | 'UNSUPPORTED_VERSION' | 'COMPONENT_NOT_FOUND' | 'COMPONENT_PROP_MISSING' | 'COMPONENT_CYCLE' | 'COMPONENT_PROP_TYPE' | 'PARAM_UNDEFINED' | 'OPERATION_INVALID_FOR_TYPE' | 'OPERATION_MISSING_FIELD' | 'OPERATION_UNKNOWN' | 'EXPR_INVALID_BASE' | 'EXPR_INVALID_CONDITION' | 'EXPR_COND_ELSE_REQUIRED';
605
+ type ErrorCode = 'SCHEMA_INVALID' | 'UNDEFINED_STATE' | 'UNDEFINED_ACTION' | 'VAR_UNDEFINED' | 'DUPLICATE_ACTION' | 'UNSUPPORTED_VERSION' | 'COMPONENT_NOT_FOUND' | 'COMPONENT_PROP_MISSING' | 'COMPONENT_CYCLE' | 'COMPONENT_PROP_TYPE' | 'PARAM_UNDEFINED' | 'OPERATION_INVALID_FOR_TYPE' | 'OPERATION_MISSING_FIELD' | 'OPERATION_UNKNOWN' | 'EXPR_INVALID_BASE' | 'EXPR_INVALID_CONDITION' | 'EXPR_COND_ELSE_REQUIRED' | 'UNDEFINED_ROUTE_PARAM' | 'ROUTE_NOT_DEFINED' | 'UNDEFINED_IMPORT' | 'IMPORTS_NOT_DEFINED' | 'LAYOUT_MISSING_SLOT' | 'LAYOUT_NOT_FOUND' | 'INVALID_SLOT_NAME' | 'DUPLICATE_SLOT_NAME' | 'DUPLICATE_DEFAULT_SLOT' | 'SLOT_IN_LOOP' | 'INVALID_DATA_SOURCE' | 'UNDEFINED_DATA_SOURCE' | 'DATA_NOT_DEFINED' | 'UNDEFINED_DATA' | 'INVALID_STORAGE_OPERATION' | 'INVALID_STORAGE_TYPE' | 'STORAGE_SET_MISSING_VALUE' | 'INVALID_CLIPBOARD_OPERATION' | 'CLIPBOARD_WRITE_MISSING_VALUE' | 'INVALID_NAVIGATE_TARGET';
397
606
  /**
398
607
  * Custom error class for Constela validation errors
399
608
  */
@@ -474,6 +683,86 @@ declare function createOperationUnknownError(operation: string, path?: string):
474
683
  * Creates a cond else required error
475
684
  */
476
685
  declare function createCondElseRequiredError(path?: string): ConstelaError;
686
+ /**
687
+ * Creates an undefined route param error
688
+ */
689
+ declare function createUndefinedRouteParamError(paramName: string, path?: string): ConstelaError;
690
+ /**
691
+ * Creates a route not defined error
692
+ */
693
+ declare function createRouteNotDefinedError(path?: string): ConstelaError;
694
+ /**
695
+ * Creates an undefined import reference error
696
+ */
697
+ declare function createUndefinedImportError(importName: string, path?: string): ConstelaError;
698
+ /**
699
+ * Creates an imports not defined error
700
+ */
701
+ declare function createImportsNotDefinedError(path?: string): ConstelaError;
702
+ /**
703
+ * Creates a layout missing slot error
704
+ */
705
+ declare function createLayoutMissingSlotError(path?: string): ConstelaError;
706
+ /**
707
+ * Creates a layout not found error
708
+ */
709
+ declare function createLayoutNotFoundError(layoutName: string, path?: string): ConstelaError;
710
+ /**
711
+ * Creates an invalid slot name error
712
+ */
713
+ declare function createInvalidSlotNameError(slotName: string, layoutName: string, path?: string): ConstelaError;
714
+ /**
715
+ * Creates a duplicate slot name error
716
+ */
717
+ declare function createDuplicateSlotNameError(slotName: string, path?: string): ConstelaError;
718
+ /**
719
+ * Creates a duplicate default slot error
720
+ */
721
+ declare function createDuplicateDefaultSlotError(path?: string): ConstelaError;
722
+ /**
723
+ * Creates a slot in loop error
724
+ */
725
+ declare function createSlotInLoopError(path?: string): ConstelaError;
726
+ /**
727
+ * Creates an invalid data source error
728
+ */
729
+ declare function createInvalidDataSourceError(dataName: string, reason: string, path?: string): ConstelaError;
730
+ /**
731
+ * Creates an undefined data source error (for getStaticPaths)
732
+ */
733
+ declare function createUndefinedDataSourceError(sourceName: string, path?: string): ConstelaError;
734
+ /**
735
+ * Creates a data not defined error (for data or getStaticPaths used without data field)
736
+ */
737
+ declare function createDataNotDefinedError(path?: string): ConstelaError;
738
+ /**
739
+ * Creates an undefined data error (for DataExpr references)
740
+ */
741
+ declare function createUndefinedDataError(dataName: string, path?: string): ConstelaError;
742
+ /**
743
+ * Creates an invalid storage operation error
744
+ */
745
+ declare function createInvalidStorageOperationError(operation: string, path?: string): ConstelaError;
746
+ /**
747
+ * Creates an invalid storage type error
748
+ */
749
+ declare function createInvalidStorageTypeError(storageType: string, path?: string): ConstelaError;
750
+ /**
751
+ * Creates a storage set missing value error
752
+ */
753
+ declare function createStorageSetMissingValueError(path?: string): ConstelaError;
754
+ /**
755
+ * Creates an invalid clipboard operation error
756
+ */
757
+ declare function createInvalidClipboardOperationError(operation: string, path?: string): ConstelaError;
758
+ /**
759
+ * Creates a clipboard write missing value error
760
+ */
761
+ declare function createClipboardWriteMissingValueError(path?: string): ConstelaError;
762
+ /**
763
+ * Creates an invalid navigate target error
764
+ */
765
+ declare function createInvalidNavigateTargetError(target: string, path?: string): ConstelaError;
477
766
 
478
767
  /**
479
768
  * AST Validator for Constela
@@ -921,6 +1210,10 @@ declare const astSchema: {
921
1210
  readonly $ref: "#/$defs/ComponentNode";
922
1211
  }, {
923
1212
  readonly $ref: "#/$defs/SlotNode";
1213
+ }, {
1214
+ readonly $ref: "#/$defs/MarkdownNode";
1215
+ }, {
1216
+ readonly $ref: "#/$defs/CodeNode";
924
1217
  }];
925
1218
  };
926
1219
  readonly ElementNode: {
@@ -1050,6 +1343,37 @@ declare const astSchema: {
1050
1343
  };
1051
1344
  };
1052
1345
  };
1346
+ readonly MarkdownNode: {
1347
+ readonly type: "object";
1348
+ readonly required: readonly ["kind", "content"];
1349
+ readonly additionalProperties: false;
1350
+ readonly properties: {
1351
+ readonly kind: {
1352
+ readonly type: "string";
1353
+ readonly const: "markdown";
1354
+ };
1355
+ readonly content: {
1356
+ readonly $ref: "#/$defs/Expression";
1357
+ };
1358
+ };
1359
+ };
1360
+ readonly CodeNode: {
1361
+ readonly type: "object";
1362
+ readonly required: readonly ["kind", "language", "content"];
1363
+ readonly additionalProperties: false;
1364
+ readonly properties: {
1365
+ readonly kind: {
1366
+ readonly type: "string";
1367
+ readonly const: "code";
1368
+ };
1369
+ readonly language: {
1370
+ readonly $ref: "#/$defs/Expression";
1371
+ };
1372
+ readonly content: {
1373
+ readonly $ref: "#/$defs/Expression";
1374
+ };
1375
+ };
1376
+ };
1053
1377
  readonly ParamDef: {
1054
1378
  readonly type: "object";
1055
1379
  readonly required: readonly ["type"];
@@ -1083,4 +1407,4 @@ declare const astSchema: {
1083
1407
  };
1084
1408
  };
1085
1409
 
1086
- export { type ActionDefinition, type ActionStep, BINARY_OPERATORS, type BinExpr, type BinaryOperator, type BooleanField, type ComponentDef, type ComponentNode, type CondExpr, type ConstelaAst, ConstelaError, type EachNode, type ElementNode, type ErrorCode, type EventHandler, type Expression, type FetchStep, type GetExpr, HTTP_METHODS, type HttpMethod, type IfNode, type ListField, type LitExpr, type NotExpr, type NumberField, type ObjectField, PARAM_TYPES, type ParamDef, type ParamExpr, type ParamType, type Program, type SetStep, type SlotNode, type StateExpr, type StateField, type StringField, type TextNode, UPDATE_OPERATIONS, type UpdateOperation, type UpdateStep, type ValidationFailure, type ValidationResult, type ValidationSuccess, type VarExpr, type ViewNode, astSchema, createComponentCycleError, createComponentNotFoundError, createComponentPropMissingError, createComponentPropTypeError, createCondElseRequiredError, createDuplicateActionError, createOperationInvalidForTypeError, createOperationMissingFieldError, createOperationUnknownError, createSchemaError, createUndefinedActionError, createUndefinedParamError, createUndefinedStateError, createUndefinedVarError, createUnsupportedVersionError, isActionStep, isBinExpr, isBooleanField, isComponentNode, isCondExpr, isConstelaError, isEachNode, isElementNode, isEventHandler, isExpression, isFetchStep, isGetExpr, isIfNode, isListField, isLitExpr, isNotExpr, isNumberField, isObjectField, isParamExpr, isSetStep, isSlotNode, isStateExpr, isStateField, isStringField, isTextNode, isUpdateStep, isVarExpr, isViewNode, validateAst };
1410
+ export { type ActionDefinition, type ActionStep, BINARY_OPERATORS, type BinExpr, type BinaryOperator, type BooleanField, CLIPBOARD_OPERATIONS, type ClipboardOperation, type ClipboardStep, type CodeNode, type ComponentDef, type ComponentNode, type CondExpr, type ConstelaAst, ConstelaError, type ConstelaProgram, DATA_SOURCE_TYPES, DATA_TRANSFORMS, type DataExpr, type DataSource, type DataSourceType, type DataTransform, type EachNode, type ElementNode, type ErrorCode, type EventHandler, type Expression, type FetchStep, type GetExpr, HTTP_METHODS, type HttpMethod, type IfNode, type ImportExpr, type LayoutProgram, type LifecycleHooks, type ListField, type LitExpr, type MarkdownNode, NAVIGATE_TARGETS, type NavigateStep, type NavigateTarget, type NotExpr, type NumberField, type ObjectField, PARAM_TYPES, type ParamDef, type ParamExpr, type ParamType, type Program, type RouteDefinition, type RouteExpr, STORAGE_OPERATIONS, STORAGE_TYPES, type SetStep, type SlotNode, type StateExpr, type StateField, type StaticPathsDefinition, type StorageOperation, type StorageStep, type StorageType, type StringField, type TextNode, UPDATE_OPERATIONS, type UpdateOperation, type UpdateStep, type ValidationFailure, type ValidationResult, type ValidationSuccess, type VarExpr, type ViewNode, astSchema, createClipboardWriteMissingValueError, createComponentCycleError, createComponentNotFoundError, createComponentPropMissingError, createComponentPropTypeError, createCondElseRequiredError, createDataNotDefinedError, createDuplicateActionError, createDuplicateDefaultSlotError, createDuplicateSlotNameError, createImportsNotDefinedError, createInvalidClipboardOperationError, createInvalidDataSourceError, createInvalidNavigateTargetError, createInvalidSlotNameError, createInvalidStorageOperationError, createInvalidStorageTypeError, createLayoutMissingSlotError, createLayoutNotFoundError, createOperationInvalidForTypeError, createOperationMissingFieldError, createOperationUnknownError, createRouteNotDefinedError, createSchemaError, createSlotInLoopError, createStorageSetMissingValueError, createUndefinedActionError, createUndefinedDataError, createUndefinedDataSourceError, createUndefinedImportError, createUndefinedParamError, createUndefinedRouteParamError, createUndefinedStateError, createUndefinedVarError, createUnsupportedVersionError, isActionStep, isBinExpr, isBooleanField, isClipboardStep, isCodeNode, isComponentNode, isCondExpr, isConstelaError, isDataExpr, isDataSource, isEachNode, isElementNode, isEventHandler, isExpression, isFetchStep, isGetExpr, isIfNode, isImportExpr, isLayoutProgram, isLifecycleHooks, isListField, isLitExpr, isMarkdownNode, isNamedSlotNode, isNavigateStep, isNotExpr, isNumberField, isObjectField, isParamExpr, isRouteDefinition, isRouteExpr, isSetStep, isSlotNode, isStateExpr, isStateField, isStaticPathsDefinition, isStorageStep, isStringField, isTextNode, isUpdateStep, isVarExpr, isViewNode, validateAst };
package/dist/index.js CHANGED
@@ -26,7 +26,13 @@ var UPDATE_OPERATIONS = [
26
26
  "splice"
27
27
  ];
28
28
  var HTTP_METHODS = ["GET", "POST", "PUT", "DELETE"];
29
+ var STORAGE_OPERATIONS = ["get", "set", "remove"];
30
+ var STORAGE_TYPES = ["local", "session"];
31
+ var CLIPBOARD_OPERATIONS = ["write", "read"];
32
+ var NAVIGATE_TARGETS = ["_self", "_blank"];
29
33
  var PARAM_TYPES = ["string", "number", "boolean", "json"];
34
+ var DATA_TRANSFORMS = ["mdx", "yaml", "csv"];
35
+ var DATA_SOURCE_TYPES = ["glob", "file", "api"];
30
36
 
31
37
  // src/types/guards.ts
32
38
  function isObject(value) {
@@ -84,8 +90,71 @@ function isGetExpr(value) {
84
90
  if (typeof value["path"] !== "string") return false;
85
91
  return true;
86
92
  }
93
+ function isRouteExpr(value) {
94
+ if (!isObject(value)) return false;
95
+ if (value["expr"] !== "route") return false;
96
+ if (typeof value["name"] !== "string") return false;
97
+ if ("source" in value && value["source"] !== void 0) {
98
+ const validSources = ["param", "query", "path"];
99
+ if (!validSources.includes(value["source"])) return false;
100
+ }
101
+ return true;
102
+ }
103
+ function isImportExpr(value) {
104
+ if (!isObject(value)) return false;
105
+ if (value["expr"] !== "import") return false;
106
+ if (typeof value["name"] !== "string") return false;
107
+ if ("path" in value && value["path"] !== void 0) {
108
+ if (typeof value["path"] !== "string") return false;
109
+ }
110
+ return true;
111
+ }
112
+ function isDataExpr(value) {
113
+ if (!isObject(value)) return false;
114
+ if (value["expr"] !== "data") return false;
115
+ if (typeof value["name"] !== "string") return false;
116
+ if ("path" in value && value["path"] !== void 0) {
117
+ if (typeof value["path"] !== "string") return false;
118
+ }
119
+ return true;
120
+ }
121
+ function isDataSource(value) {
122
+ if (!isObject(value)) return false;
123
+ const type = value["type"];
124
+ if (!DATA_SOURCE_TYPES.includes(type)) {
125
+ return false;
126
+ }
127
+ if ("transform" in value && value["transform"] !== void 0) {
128
+ if (!DATA_TRANSFORMS.includes(value["transform"])) {
129
+ return false;
130
+ }
131
+ }
132
+ switch (type) {
133
+ case "glob":
134
+ if (typeof value["pattern"] !== "string") return false;
135
+ break;
136
+ case "file":
137
+ if (typeof value["path"] !== "string") return false;
138
+ break;
139
+ case "api":
140
+ if (typeof value["url"] !== "string") return false;
141
+ break;
142
+ }
143
+ return true;
144
+ }
145
+ function isStaticPathsDefinition(value) {
146
+ if (!isObject(value)) return false;
147
+ if (typeof value["source"] !== "string") return false;
148
+ if (!("params" in value) || !isObject(value["params"])) return false;
149
+ return true;
150
+ }
151
+ function isRouteDefinition(value) {
152
+ if (!isObject(value)) return false;
153
+ if (typeof value["path"] !== "string") return false;
154
+ return true;
155
+ }
87
156
  function isExpression(value) {
88
- return isLitExpr(value) || isStateExpr(value) || isVarExpr(value) || isBinExpr(value) || isNotExpr(value) || isParamExpr(value) || isCondExpr(value) || isGetExpr(value);
157
+ return isLitExpr(value) || isStateExpr(value) || isVarExpr(value) || isBinExpr(value) || isNotExpr(value) || isParamExpr(value) || isCondExpr(value) || isGetExpr(value) || isRouteExpr(value) || isImportExpr(value) || isDataExpr(value);
89
158
  }
90
159
  function isElementNode(value) {
91
160
  if (!isObject(value)) return false;
@@ -128,8 +197,20 @@ function isSlotNode(value) {
128
197
  if (!isObject(value)) return false;
129
198
  return value["kind"] === "slot";
130
199
  }
200
+ function isMarkdownNode(value) {
201
+ if (!isObject(value)) return false;
202
+ if (value["kind"] !== "markdown") return false;
203
+ return "content" in value && isObject(value["content"]);
204
+ }
205
+ function isCodeNode(value) {
206
+ if (!isObject(value)) return false;
207
+ if (value["kind"] !== "code") return false;
208
+ if (!("language" in value) || !isObject(value["language"])) return false;
209
+ if (!("content" in value) || !isObject(value["content"])) return false;
210
+ return true;
211
+ }
131
212
  function isViewNode(value) {
132
- return isElementNode(value) || isTextNode(value) || isIfNode(value) || isEachNode(value) || isComponentNode(value) || isSlotNode(value);
213
+ return isElementNode(value) || isTextNode(value) || isIfNode(value) || isEachNode(value) || isComponentNode(value) || isSlotNode(value) || isMarkdownNode(value) || isCodeNode(value);
133
214
  }
134
215
  function isSetStep(value) {
135
216
  if (!isObject(value)) return false;
@@ -158,8 +239,39 @@ function isFetchStep(value) {
158
239
  }
159
240
  return true;
160
241
  }
242
+ function isStorageStep(value) {
243
+ if (!isObject(value)) return false;
244
+ if (value["do"] !== "storage") return false;
245
+ if (!STORAGE_OPERATIONS.includes(value["operation"])) {
246
+ return false;
247
+ }
248
+ if (!STORAGE_TYPES.includes(value["storage"])) {
249
+ return false;
250
+ }
251
+ if (!("key" in value)) return false;
252
+ return true;
253
+ }
254
+ function isClipboardStep(value) {
255
+ if (!isObject(value)) return false;
256
+ if (value["do"] !== "clipboard") return false;
257
+ if (!CLIPBOARD_OPERATIONS.includes(value["operation"])) {
258
+ return false;
259
+ }
260
+ return true;
261
+ }
262
+ function isNavigateStep(value) {
263
+ if (!isObject(value)) return false;
264
+ if (value["do"] !== "navigate") return false;
265
+ if (!("url" in value)) return false;
266
+ if ("target" in value && value["target"] !== void 0) {
267
+ if (!NAVIGATE_TARGETS.includes(value["target"])) {
268
+ return false;
269
+ }
270
+ }
271
+ return true;
272
+ }
161
273
  function isActionStep(value) {
162
- return isSetStep(value) || isUpdateStep(value) || isFetchStep(value);
274
+ return isSetStep(value) || isUpdateStep(value) || isFetchStep(value) || isStorageStep(value) || isClipboardStep(value) || isNavigateStep(value);
163
275
  }
164
276
  function isNumberField(value) {
165
277
  if (!isObject(value)) return false;
@@ -195,6 +307,37 @@ function isEventHandler(value) {
195
307
  if (!("action" in value) || typeof value["action"] !== "string") return false;
196
308
  return true;
197
309
  }
310
+ function isLayoutProgram(value) {
311
+ if (!isObject(value)) return false;
312
+ if (value["version"] !== "1.0") return false;
313
+ if (value["type"] !== "layout") return false;
314
+ if (!("view" in value)) return false;
315
+ return true;
316
+ }
317
+ function isNamedSlotNode(value) {
318
+ if (!isObject(value)) return false;
319
+ if (value["kind"] !== "slot") return false;
320
+ if (typeof value["name"] !== "string") return false;
321
+ return true;
322
+ }
323
+ function isLifecycleHooks(value) {
324
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
325
+ return false;
326
+ }
327
+ const obj = value;
328
+ const knownFields = ["onMount", "onUnmount", "onRouteEnter", "onRouteLeave"];
329
+ for (const key of knownFields) {
330
+ if (key in obj && obj[key] !== void 0) {
331
+ if (typeof obj[key] !== "string") return false;
332
+ }
333
+ }
334
+ for (const key of Object.keys(obj)) {
335
+ if (!knownFields.includes(key)) {
336
+ if (typeof obj[key] !== "string") return false;
337
+ }
338
+ }
339
+ return true;
340
+ }
198
341
 
199
342
  // src/types/error.ts
200
343
  var ConstelaError = class _ConstelaError extends Error {
@@ -322,12 +465,152 @@ function createCondElseRequiredError(path) {
322
465
  path
323
466
  );
324
467
  }
468
+ function createUndefinedRouteParamError(paramName, path) {
469
+ return new ConstelaError(
470
+ "UNDEFINED_ROUTE_PARAM",
471
+ `Undefined route param reference: '${paramName}' is not defined in route path`,
472
+ path
473
+ );
474
+ }
475
+ function createRouteNotDefinedError(path) {
476
+ return new ConstelaError(
477
+ "ROUTE_NOT_DEFINED",
478
+ `Route expression used but no route is defined in the program`,
479
+ path
480
+ );
481
+ }
482
+ function createUndefinedImportError(importName, path) {
483
+ return new ConstelaError(
484
+ "UNDEFINED_IMPORT",
485
+ `Undefined import reference: '${importName}' is not defined in imports`,
486
+ path
487
+ );
488
+ }
489
+ function createImportsNotDefinedError(path) {
490
+ return new ConstelaError(
491
+ "IMPORTS_NOT_DEFINED",
492
+ `Import expression used but no imports are defined in the program`,
493
+ path
494
+ );
495
+ }
496
+ function createLayoutMissingSlotError(path) {
497
+ return new ConstelaError(
498
+ "LAYOUT_MISSING_SLOT",
499
+ `Layout must contain at least one slot node for page content`,
500
+ path
501
+ );
502
+ }
503
+ function createLayoutNotFoundError(layoutName, path) {
504
+ return new ConstelaError(
505
+ "LAYOUT_NOT_FOUND",
506
+ `Layout '${layoutName}' is not found`,
507
+ path
508
+ );
509
+ }
510
+ function createInvalidSlotNameError(slotName, layoutName, path) {
511
+ return new ConstelaError(
512
+ "INVALID_SLOT_NAME",
513
+ `Named slot '${slotName}' does not exist in layout '${layoutName}'`,
514
+ path
515
+ );
516
+ }
517
+ function createDuplicateSlotNameError(slotName, path) {
518
+ return new ConstelaError(
519
+ "DUPLICATE_SLOT_NAME",
520
+ `Duplicate named slot '${slotName}' found in layout`,
521
+ path
522
+ );
523
+ }
524
+ function createDuplicateDefaultSlotError(path) {
525
+ return new ConstelaError(
526
+ "DUPLICATE_DEFAULT_SLOT",
527
+ `Layout contains multiple default (unnamed) slots`,
528
+ path
529
+ );
530
+ }
531
+ function createSlotInLoopError(path) {
532
+ return new ConstelaError(
533
+ "SLOT_IN_LOOP",
534
+ `Slot cannot be placed inside a loop (each node) as it would render multiple times`,
535
+ path
536
+ );
537
+ }
538
+ function createInvalidDataSourceError(dataName, reason, path) {
539
+ return new ConstelaError(
540
+ "INVALID_DATA_SOURCE",
541
+ `Invalid data source '${dataName}': ${reason}`,
542
+ path
543
+ );
544
+ }
545
+ function createUndefinedDataSourceError(sourceName, path) {
546
+ return new ConstelaError(
547
+ "UNDEFINED_DATA_SOURCE",
548
+ `Undefined data source reference: '${sourceName}' is not defined in data`,
549
+ path
550
+ );
551
+ }
552
+ function createDataNotDefinedError(path) {
553
+ return new ConstelaError(
554
+ "DATA_NOT_DEFINED",
555
+ `Data expression or getStaticPaths used but no data is defined in the program`,
556
+ path
557
+ );
558
+ }
559
+ function createUndefinedDataError(dataName, path) {
560
+ return new ConstelaError(
561
+ "UNDEFINED_DATA",
562
+ `Undefined data reference: '${dataName}' is not defined in data`,
563
+ path
564
+ );
565
+ }
566
+ function createInvalidStorageOperationError(operation, path) {
567
+ return new ConstelaError(
568
+ "INVALID_STORAGE_OPERATION",
569
+ `Invalid storage operation: '${operation}'. Valid operations are: get, set, remove`,
570
+ path
571
+ );
572
+ }
573
+ function createInvalidStorageTypeError(storageType, path) {
574
+ return new ConstelaError(
575
+ "INVALID_STORAGE_TYPE",
576
+ `Invalid storage type: '${storageType}'. Valid types are: local, session`,
577
+ path
578
+ );
579
+ }
580
+ function createStorageSetMissingValueError(path) {
581
+ return new ConstelaError(
582
+ "STORAGE_SET_MISSING_VALUE",
583
+ `Storage 'set' operation requires a 'value' field`,
584
+ path
585
+ );
586
+ }
587
+ function createInvalidClipboardOperationError(operation, path) {
588
+ return new ConstelaError(
589
+ "INVALID_CLIPBOARD_OPERATION",
590
+ `Invalid clipboard operation: '${operation}'. Valid operations are: write, read`,
591
+ path
592
+ );
593
+ }
594
+ function createClipboardWriteMissingValueError(path) {
595
+ return new ConstelaError(
596
+ "CLIPBOARD_WRITE_MISSING_VALUE",
597
+ `Clipboard 'write' operation requires a 'value' field`,
598
+ path
599
+ );
600
+ }
601
+ function createInvalidNavigateTargetError(target, path) {
602
+ return new ConstelaError(
603
+ "INVALID_NAVIGATE_TARGET",
604
+ `Invalid navigate target: '${target}'. Valid targets are: _self, _blank`,
605
+ path
606
+ );
607
+ }
325
608
 
326
609
  // src/schema/validator.ts
327
610
  function isObject2(value) {
328
611
  return typeof value === "object" && value !== null && !Array.isArray(value);
329
612
  }
330
- var VALID_VIEW_KINDS = ["element", "text", "if", "each", "component", "slot"];
613
+ var VALID_VIEW_KINDS = ["element", "text", "if", "each", "component", "slot", "markdown", "code"];
331
614
  var VALID_EXPR_TYPES = ["lit", "state", "var", "bin", "not", "param", "cond", "get"];
332
615
  var VALID_PARAM_TYPES = ["string", "number", "boolean", "json"];
333
616
  var VALID_ACTION_TYPES = ["set", "update", "fetch"];
@@ -344,7 +627,7 @@ function validateViewNode(node, path) {
344
627
  return { path: path + "/kind", message: "kind is required" };
345
628
  }
346
629
  if (!VALID_VIEW_KINDS.includes(kind)) {
347
- return { path: path + "/kind", message: "must be one of: element, text, if, each, component, slot" };
630
+ return { path: path + "/kind", message: "must be one of: element, text, if, each, component, slot, markdown, code" };
348
631
  }
349
632
  switch (kind) {
350
633
  case "element":
@@ -426,6 +709,23 @@ function validateViewNode(node, path) {
426
709
  break;
427
710
  case "slot":
428
711
  break;
712
+ case "markdown":
713
+ if (!("content" in node)) {
714
+ return { path: path + "/content", message: "content is required" };
715
+ }
716
+ return validateExpression(node["content"], path + "/content");
717
+ case "code":
718
+ if (!("language" in node)) {
719
+ return { path: path + "/language", message: "language is required" };
720
+ }
721
+ if (!("content" in node)) {
722
+ return { path: path + "/content", message: "content is required" };
723
+ }
724
+ {
725
+ const langError = validateExpression(node["language"], path + "/language");
726
+ if (langError) return langError;
727
+ return validateExpression(node["content"], path + "/content");
728
+ }
429
729
  }
430
730
  return null;
431
731
  }
@@ -1137,7 +1437,9 @@ var astSchema = {
1137
1437
  { $ref: "#/$defs/IfNode" },
1138
1438
  { $ref: "#/$defs/EachNode" },
1139
1439
  { $ref: "#/$defs/ComponentNode" },
1140
- { $ref: "#/$defs/SlotNode" }
1440
+ { $ref: "#/$defs/SlotNode" },
1441
+ { $ref: "#/$defs/MarkdownNode" },
1442
+ { $ref: "#/$defs/CodeNode" }
1141
1443
  ]
1142
1444
  },
1143
1445
  ElementNode: {
@@ -1220,6 +1522,25 @@ var astSchema = {
1220
1522
  kind: { type: "string", const: "slot" }
1221
1523
  }
1222
1524
  },
1525
+ MarkdownNode: {
1526
+ type: "object",
1527
+ required: ["kind", "content"],
1528
+ additionalProperties: false,
1529
+ properties: {
1530
+ kind: { type: "string", const: "markdown" },
1531
+ content: { $ref: "#/$defs/Expression" }
1532
+ }
1533
+ },
1534
+ CodeNode: {
1535
+ type: "object",
1536
+ required: ["kind", "language", "content"],
1537
+ additionalProperties: false,
1538
+ properties: {
1539
+ kind: { type: "string", const: "code" },
1540
+ language: { $ref: "#/$defs/Expression" },
1541
+ content: { $ref: "#/$defs/Expression" }
1542
+ }
1543
+ },
1223
1544
  // ==================== Component Definition ====================
1224
1545
  ParamDef: {
1225
1546
  type: "object",
@@ -1249,32 +1570,62 @@ var astSchema = {
1249
1570
  };
1250
1571
  export {
1251
1572
  BINARY_OPERATORS,
1573
+ CLIPBOARD_OPERATIONS,
1252
1574
  ConstelaError,
1575
+ DATA_SOURCE_TYPES,
1576
+ DATA_TRANSFORMS,
1253
1577
  HTTP_METHODS,
1578
+ NAVIGATE_TARGETS,
1254
1579
  PARAM_TYPES,
1580
+ STORAGE_OPERATIONS,
1581
+ STORAGE_TYPES,
1255
1582
  UPDATE_OPERATIONS,
1256
1583
  astSchema,
1584
+ createClipboardWriteMissingValueError,
1257
1585
  createComponentCycleError,
1258
1586
  createComponentNotFoundError,
1259
1587
  createComponentPropMissingError,
1260
1588
  createComponentPropTypeError,
1261
1589
  createCondElseRequiredError,
1590
+ createDataNotDefinedError,
1262
1591
  createDuplicateActionError,
1592
+ createDuplicateDefaultSlotError,
1593
+ createDuplicateSlotNameError,
1594
+ createImportsNotDefinedError,
1595
+ createInvalidClipboardOperationError,
1596
+ createInvalidDataSourceError,
1597
+ createInvalidNavigateTargetError,
1598
+ createInvalidSlotNameError,
1599
+ createInvalidStorageOperationError,
1600
+ createInvalidStorageTypeError,
1601
+ createLayoutMissingSlotError,
1602
+ createLayoutNotFoundError,
1263
1603
  createOperationInvalidForTypeError,
1264
1604
  createOperationMissingFieldError,
1265
1605
  createOperationUnknownError,
1606
+ createRouteNotDefinedError,
1266
1607
  createSchemaError,
1608
+ createSlotInLoopError,
1609
+ createStorageSetMissingValueError,
1267
1610
  createUndefinedActionError,
1611
+ createUndefinedDataError,
1612
+ createUndefinedDataSourceError,
1613
+ createUndefinedImportError,
1268
1614
  createUndefinedParamError,
1615
+ createUndefinedRouteParamError,
1269
1616
  createUndefinedStateError,
1270
1617
  createUndefinedVarError,
1271
1618
  createUnsupportedVersionError,
1272
1619
  isActionStep,
1273
1620
  isBinExpr,
1274
1621
  isBooleanField,
1622
+ isClipboardStep,
1623
+ isCodeNode,
1275
1624
  isComponentNode,
1276
1625
  isCondExpr,
1277
1626
  isConstelaError,
1627
+ isDataExpr,
1628
+ isDataSource,
1278
1629
  isEachNode,
1279
1630
  isElementNode,
1280
1631
  isEventHandler,
@@ -1282,16 +1633,26 @@ export {
1282
1633
  isFetchStep,
1283
1634
  isGetExpr,
1284
1635
  isIfNode,
1636
+ isImportExpr,
1637
+ isLayoutProgram,
1638
+ isLifecycleHooks,
1285
1639
  isListField,
1286
1640
  isLitExpr,
1641
+ isMarkdownNode,
1642
+ isNamedSlotNode,
1643
+ isNavigateStep,
1287
1644
  isNotExpr,
1288
1645
  isNumberField,
1289
1646
  isObjectField,
1290
1647
  isParamExpr,
1648
+ isRouteDefinition,
1649
+ isRouteExpr,
1291
1650
  isSetStep,
1292
1651
  isSlotNode,
1293
1652
  isStateExpr,
1294
1653
  isStateField,
1654
+ isStaticPathsDefinition,
1655
+ isStorageStep,
1295
1656
  isStringField,
1296
1657
  isTextNode,
1297
1658
  isUpdateStep,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constela/core",
3
- "version": "0.3.3",
3
+ "version": "0.5.0",
4
4
  "description": "Core types, schema, and validator for Constela UI framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",