@constela/core 0.8.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -42,7 +42,7 @@ All fields except `version`, `state`, `actions`, and `view` are optional.
42
42
 
43
43
  ## Expression Types
44
44
 
45
- 12 expression types for constrained computation:
45
+ 13 expression types for constrained computation:
46
46
 
47
47
  | Type | JSON Example | Description |
48
48
  |------|-------------|-------------|
@@ -58,6 +58,7 @@ All fields except `version`, `state`, `actions`, and `view` are optional.
58
58
  | `import` | `{ "expr": "import", "name": "config" }` | External data |
59
59
  | `data` | `{ "expr": "data", "name": "posts" }` | Build-time data |
60
60
  | `ref` | `{ "expr": "ref", "name": "inputEl" }` | DOM element ref |
61
+ | `style` | `{ "expr": "style", "name": "button", "variants": {...} }` | Style reference |
61
62
 
62
63
  **Binary Operators:** `+`, `-`, `*`, `/`, `==`, `!=`, `<`, `<=`, `>`, `>=`, `&&`, `||`
63
64
 
@@ -78,6 +79,9 @@ All fields except `version`, `state`, `actions`, and `view` are optional.
78
79
  // Loop node
79
80
  { "kind": "each", "items": { "expr": "state", "name": "todos" }, "as": "item", "body": { ... } }
80
81
 
82
+ // Loop node with key (efficient diffing)
83
+ { "kind": "each", "items": { ... }, "as": "item", "key": { "expr": "var", "name": "item", "path": "id" }, "body": { ... } }
84
+
81
85
  // Component node
82
86
  { "kind": "component", "name": "Button", "props": { "label": { ... } } }
83
87
 
@@ -94,7 +98,7 @@ All fields except `version`, `state`, `actions`, and `view` are optional.
94
98
 
95
99
  ## Action Step Types
96
100
 
97
- 11 step types for declarative actions:
101
+ 14 step types for declarative actions:
98
102
 
99
103
  ```json
100
104
  // Set state value
@@ -104,6 +108,10 @@ All fields except `version`, `state`, `actions`, and `view` are optional.
104
108
  { "do": "update", "target": "count", "operation": "increment" }
105
109
  { "do": "update", "target": "todos", "operation": "push", "value": { ... } }
106
110
 
111
+ // Set nested path (fine-grained update)
112
+ { "do": "setPath", "target": "posts", "path": [5, "liked"], "value": { "expr": "lit", "value": true } }
113
+ { "do": "setPath", "target": "posts", "path": { "expr": "var", "name": "payload", "path": "index" }, "field": "liked", "value": { ... } }
114
+
107
115
  // HTTP request
108
116
  { "do": "fetch", "url": { ... }, "method": "GET", "onSuccess": [ ... ], "onError": [ ... ] }
109
117
 
@@ -130,6 +138,30 @@ All fields except `version`, `state`, `actions`, and `view` are optional.
130
138
 
131
139
  // DOM manipulation
132
140
  { "do": "dom", "operation": "addClass", "ref": "myElement", "value": { ... } }
141
+
142
+ // WebSocket send
143
+ { "do": "send", "connection": "chat", "data": { "expr": "state", "name": "inputText" } }
144
+
145
+ // WebSocket close
146
+ { "do": "close", "connection": "chat" }
147
+ ```
148
+
149
+ ## Connections
150
+
151
+ WebSocket connections for real-time data:
152
+
153
+ ```json
154
+ {
155
+ "connections": {
156
+ "chat": {
157
+ "type": "websocket",
158
+ "url": "wss://api.example.com/ws",
159
+ "onMessage": { "action": "handleMessage" },
160
+ "onOpen": { "action": "connectionOpened" },
161
+ "onClose": { "action": "connectionClosed" }
162
+ }
163
+ }
164
+ }
133
165
  ```
134
166
 
135
167
  **Update Operations:**
@@ -160,6 +192,54 @@ All fields except `version`, `state`, `actions`, and `view` are optional.
160
192
  }
161
193
  ```
162
194
 
195
+ ## Style System
196
+
197
+ Define reusable style presets with variants (similar to CVA/Tailwind Variants):
198
+
199
+ ```json
200
+ {
201
+ "styles": {
202
+ "button": {
203
+ "base": "px-4 py-2 rounded font-medium",
204
+ "variants": {
205
+ "variant": {
206
+ "primary": "bg-blue-500 text-white",
207
+ "secondary": "bg-gray-200 text-gray-800"
208
+ },
209
+ "size": {
210
+ "sm": "text-sm",
211
+ "md": "text-base",
212
+ "lg": "text-lg"
213
+ }
214
+ },
215
+ "defaultVariants": {
216
+ "variant": "primary",
217
+ "size": "md"
218
+ }
219
+ }
220
+ }
221
+ }
222
+ ```
223
+
224
+ Use styles with `StyleExpr`:
225
+
226
+ ```json
227
+ {
228
+ "kind": "element",
229
+ "tag": "button",
230
+ "props": {
231
+ "className": {
232
+ "expr": "style",
233
+ "name": "button",
234
+ "variants": {
235
+ "variant": { "expr": "lit", "value": "primary" },
236
+ "size": { "expr": "state", "name": "buttonSize" }
237
+ }
238
+ }
239
+ }
240
+ }
241
+ ```
242
+
163
243
  ## Error Codes
164
244
 
165
245
  | Code | Description |
@@ -191,6 +271,20 @@ All fields except `version`, `state`, `actions`, and `view` are optional.
191
271
  | `INVALID_STORAGE_OPERATION` | Invalid storage operation |
192
272
  | `INVALID_CLIPBOARD_OPERATION` | Invalid clipboard operation |
193
273
  | `INVALID_NAVIGATE_TARGET` | Invalid navigate target |
274
+ | `UNDEFINED_STYLE` | Reference to undefined style preset |
275
+ | `UNDEFINED_VARIANT` | Reference to undefined style variant |
276
+
277
+ ### Error Suggestions
278
+
279
+ Errors for undefined references include "Did you mean?" suggestions using Levenshtein distance:
280
+
281
+ ```typescript
282
+ import { findSimilarNames } from '@constela/core';
283
+
284
+ const candidates = new Set(['counter', 'items', 'query']);
285
+ const similar = findSimilarNames('count', candidates);
286
+ // Returns: ['counter'] - similar names within distance 2
287
+ ```
194
288
 
195
289
  ## Internal API
196
290
 
package/dist/index.d.ts CHANGED
@@ -135,7 +135,14 @@ interface StyleExpr {
135
135
  name: string;
136
136
  variants?: Record<string, Expression>;
137
137
  }
138
- type Expression = LitExpr | StateExpr | VarExpr | BinExpr | NotExpr | ParamExpr | CondExpr | GetExpr | RouteExpr | ImportExpr | DataExpr | RefExpr | IndexExpr | StyleExpr;
138
+ /**
139
+ * Concat expression - concatenates multiple expressions into a string
140
+ */
141
+ interface ConcatExpr {
142
+ expr: 'concat';
143
+ items: Expression[];
144
+ }
145
+ type Expression = LitExpr | StateExpr | VarExpr | BinExpr | NotExpr | ParamExpr | CondExpr | GetExpr | RouteExpr | ImportExpr | DataExpr | RefExpr | IndexExpr | StyleExpr | ConcatExpr;
139
146
  /**
140
147
  * Number state field
141
148
  */
@@ -208,6 +215,22 @@ interface UpdateStep {
208
215
  index?: Expression;
209
216
  deleteCount?: Expression;
210
217
  }
218
+ /**
219
+ * SetPath step - sets a value at a specific path within a state field
220
+ *
221
+ * This enables fine-grained state updates like `posts[5].liked = true`
222
+ * without re-creating the entire state.
223
+ *
224
+ * @property target - The state field name (e.g., "posts")
225
+ * @property path - The path within the state field (Expression that evaluates to string or array)
226
+ * @property value - The value to set at the path
227
+ */
228
+ interface SetPathStep {
229
+ do: 'setPath';
230
+ target: string;
231
+ path: Expression;
232
+ value: Expression;
233
+ }
211
234
  /**
212
235
  * Fetch step - makes an HTTP request
213
236
  */
@@ -302,7 +325,22 @@ interface DomStep {
302
325
  value?: Expression;
303
326
  attribute?: string;
304
327
  }
305
- type ActionStep = SetStep | UpdateStep | FetchStep | StorageStep | ClipboardStep | NavigateStep | ImportStep | CallStep | SubscribeStep | DisposeStep | DomStep;
328
+ /**
329
+ * Send step - sends data through a named WebSocket connection
330
+ */
331
+ interface SendStep {
332
+ do: 'send';
333
+ connection: string;
334
+ data: Expression;
335
+ }
336
+ /**
337
+ * Close step - closes a named WebSocket connection
338
+ */
339
+ interface CloseStep {
340
+ do: 'close';
341
+ connection: string;
342
+ }
343
+ type ActionStep = SetStep | UpdateStep | SetPathStep | FetchStep | StorageStep | ClipboardStep | NavigateStep | ImportStep | CallStep | SubscribeStep | DisposeStep | DomStep | SendStep | CloseStep;
306
344
  /**
307
345
  * Event handler - binds an event to an action
308
346
  */
@@ -580,6 +618,10 @@ declare function isRefExpr(value: unknown): value is RefExpr;
580
618
  * Checks if value is a style expression
581
619
  */
582
620
  declare function isStyleExpr(value: unknown): value is StyleExpr;
621
+ /**
622
+ * Checks if value is a concat expression
623
+ */
624
+ declare function isConcatExpr(value: unknown): value is ConcatExpr;
583
625
  /**
584
626
  * Checks if value is a data source
585
627
  */
@@ -1678,4 +1720,4 @@ declare const astSchema: {
1678
1720
  };
1679
1721
  };
1680
1722
 
1681
- export { type ActionDefinition, type ActionStep, BINARY_OPERATORS, type BinExpr, type BinaryOperator, type BooleanField, CLIPBOARD_OPERATIONS, type CallStep, type ClipboardOperation, type ClipboardStep, type CodeNode, type ComponentDef, type ComponentNode, type ComponentsRef, type CompoundVariant, type CondExpr, type ConstelaAst, ConstelaError, type ConstelaProgram, DATA_SOURCE_TYPES, DATA_TRANSFORMS, type DataExpr, type DataSource, type DataSourceType, type DataTransform, type DisposeStep, type DomStep, type EachNode, type ElementNode, type ErrorCode, type ErrorOptions, type EventHandler, type Expression, type FetchStep, type GetExpr, HTTP_METHODS, type HttpMethod, type IfNode, type ImportExpr, type ImportStep, 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 RefExpr, 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 StyleExpr, type StylePreset, type SubscribeStep, 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, createUndefinedRefError, createUndefinedRouteParamError, createUndefinedStateError, createUndefinedStyleError, createUndefinedVarError, createUndefinedVariantError, createUnsupportedVersionError, findSimilarNames, isActionStep, isBinExpr, isBooleanField, isCallStep, isClipboardStep, isCodeNode, isComponentNode, isCondExpr, isConstelaError, isDataExpr, isDataSource, isDisposeStep, isEachNode, isElementNode, isEventHandler, isExpression, isFetchStep, isGetExpr, isIfNode, isImportExpr, isImportStep, isLayoutProgram, isLifecycleHooks, isListField, isLitExpr, isMarkdownNode, isNamedSlotNode, isNavigateStep, isNotExpr, isNumberField, isObjectField, isParamExpr, isRefExpr, isRouteDefinition, isRouteExpr, isSetStep, isSlotNode, isStateExpr, isStateField, isStaticPathsDefinition, isStorageStep, isStringField, isStyleExpr, isSubscribeStep, isTextNode, isUpdateStep, isVarExpr, isViewNode, validateAst };
1723
+ export { type ActionDefinition, type ActionStep, BINARY_OPERATORS, type BinExpr, type BinaryOperator, type BooleanField, CLIPBOARD_OPERATIONS, type CallStep, type ClipboardOperation, type ClipboardStep, type CloseStep, type CodeNode, type ComponentDef, type ComponentNode, type ComponentsRef, type CompoundVariant, type ConcatExpr, type CondExpr, type ConstelaAst, ConstelaError, type ConstelaProgram, DATA_SOURCE_TYPES, DATA_TRANSFORMS, type DataExpr, type DataSource, type DataSourceType, type DataTransform, type DisposeStep, type DomStep, type EachNode, type ElementNode, type ErrorCode, type ErrorOptions, type EventHandler, type Expression, type FetchStep, type GetExpr, HTTP_METHODS, type HttpMethod, type IfNode, type ImportExpr, type ImportStep, 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 RefExpr, type RouteDefinition, type RouteExpr, STORAGE_OPERATIONS, STORAGE_TYPES, type SendStep, type SetPathStep, type SetStep, type SlotNode, type StateExpr, type StateField, type StaticPathsDefinition, type StorageOperation, type StorageStep, type StorageType, type StringField, type StyleExpr, type StylePreset, type SubscribeStep, 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, createUndefinedRefError, createUndefinedRouteParamError, createUndefinedStateError, createUndefinedStyleError, createUndefinedVarError, createUndefinedVariantError, createUnsupportedVersionError, findSimilarNames, isActionStep, isBinExpr, isBooleanField, isCallStep, isClipboardStep, isCodeNode, isComponentNode, isConcatExpr, isCondExpr, isConstelaError, isDataExpr, isDataSource, isDisposeStep, isEachNode, isElementNode, isEventHandler, isExpression, isFetchStep, isGetExpr, isIfNode, isImportExpr, isImportStep, isLayoutProgram, isLifecycleHooks, isListField, isLitExpr, isMarkdownNode, isNamedSlotNode, isNavigateStep, isNotExpr, isNumberField, isObjectField, isParamExpr, isRefExpr, isRouteDefinition, isRouteExpr, isSetStep, isSlotNode, isStateExpr, isStateField, isStaticPathsDefinition, isStorageStep, isStringField, isStyleExpr, isSubscribeStep, isTextNode, isUpdateStep, isVarExpr, isViewNode, validateAst };
package/dist/index.js CHANGED
@@ -139,6 +139,9 @@ function isStyleExpr(value) {
139
139
  }
140
140
  return true;
141
141
  }
142
+ function isConcatExpr(value) {
143
+ return typeof value === "object" && value !== null && value.expr === "concat" && Array.isArray(value.items);
144
+ }
142
145
  function isDataSource(value) {
143
146
  if (!isObject(value)) return false;
144
147
  const type = value["type"];
@@ -175,7 +178,7 @@ function isRouteDefinition(value) {
175
178
  return true;
176
179
  }
177
180
  function isExpression(value) {
178
- return isLitExpr(value) || isStateExpr(value) || isVarExpr(value) || isBinExpr(value) || isNotExpr(value) || isParamExpr(value) || isCondExpr(value) || isGetExpr(value) || isRouteExpr(value) || isImportExpr(value) || isDataExpr(value) || isRefExpr(value) || isIndexExpr(value) || isStyleExpr(value);
181
+ return isLitExpr(value) || isStateExpr(value) || isVarExpr(value) || isBinExpr(value) || isNotExpr(value) || isParamExpr(value) || isCondExpr(value) || isGetExpr(value) || isRouteExpr(value) || isImportExpr(value) || isDataExpr(value) || isRefExpr(value) || isIndexExpr(value) || isStyleExpr(value) || isConcatExpr(value);
179
182
  }
180
183
  function isElementNode(value) {
181
184
  if (!isObject(value)) return false;
@@ -1904,6 +1907,7 @@ export {
1904
1907
  isClipboardStep,
1905
1908
  isCodeNode,
1906
1909
  isComponentNode,
1910
+ isConcatExpr,
1907
1911
  isCondExpr,
1908
1912
  isConstelaError,
1909
1913
  isDataExpr,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constela/core",
3
- "version": "0.8.0",
3
+ "version": "0.9.1",
4
4
  "description": "Core types, schema, and validator for Constela UI framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",