@constela/compiler 0.14.7 → 0.15.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
@@ -1,4 +1,4 @@
1
- import { Program, ConstelaError, Expression, LayoutProgram, ComponentDef, ViewNode } from '@constela/core';
1
+ import { Program, ConstelaError, Expression, IslandStrategy, IslandStrategyOptions, LayoutProgram, ComponentDef, ViewNode } from '@constela/core';
2
2
  export { createUndefinedVarError } from '@constela/core';
3
3
 
4
4
  /**
@@ -21,6 +21,7 @@ interface AnalysisContext {
21
21
  dataNames: Set<string>;
22
22
  refNames: Set<string>;
23
23
  styleNames: Set<string>;
24
+ islandIds: Set<string>;
24
25
  }
25
26
  interface AnalyzePassSuccess {
26
27
  ok: true;
@@ -102,7 +103,7 @@ interface CompiledAction {
102
103
  name: string;
103
104
  steps: CompiledActionStep[];
104
105
  }
105
- type CompiledActionStep = CompiledSetStep | CompiledUpdateStep | CompiledSetPathStep | CompiledFetchStep | CompiledStorageStep | CompiledClipboardStep | CompiledNavigateStep | CompiledImportStep | CompiledCallStep | CompiledSubscribeStep | CompiledDisposeStep | CompiledDomStep | CompiledIfStep | CompiledSendStep | CompiledCloseStep | CompiledDelayStep | CompiledIntervalStep | CompiledClearTimerStep | CompiledFocusStep | CompiledGenerateStep;
106
+ type CompiledActionStep = CompiledSetStep | CompiledUpdateStep | CompiledSetPathStep | CompiledFetchStep | CompiledStorageStep | CompiledClipboardStep | CompiledNavigateStep | CompiledImportStep | CompiledCallStep | CompiledSubscribeStep | CompiledDisposeStep | CompiledDomStep | CompiledIfStep | CompiledSendStep | CompiledCloseStep | CompiledDelayStep | CompiledIntervalStep | CompiledClearTimerStep | CompiledFocusStep | CompiledGenerateStep | CompiledSSEConnectStep | CompiledSSECloseStep | CompiledOptimisticStep | CompiledConfirmStep | CompiledRejectStep | CompiledBindStep | CompiledUnbindStep;
106
107
  interface CompiledSetStep {
107
108
  do: 'set';
108
109
  target: string;
@@ -278,6 +279,77 @@ interface CompiledGenerateStep {
278
279
  onSuccess?: CompiledActionStep[];
279
280
  onError?: CompiledActionStep[];
280
281
  }
282
+ /**
283
+ * Compiled SSE connect step
284
+ */
285
+ interface CompiledSSEConnectStep {
286
+ do: 'sseConnect';
287
+ connection: string;
288
+ url: CompiledExpression;
289
+ eventTypes?: string[];
290
+ reconnect?: {
291
+ enabled: boolean;
292
+ strategy: string;
293
+ maxRetries: number;
294
+ baseDelay: number;
295
+ maxDelay?: number;
296
+ };
297
+ onOpen?: CompiledActionStep[];
298
+ onMessage?: CompiledActionStep[];
299
+ onError?: CompiledActionStep[];
300
+ }
301
+ /**
302
+ * Compiled SSE close step
303
+ */
304
+ interface CompiledSSECloseStep {
305
+ do: 'sseClose';
306
+ connection: string;
307
+ }
308
+ /**
309
+ * Compiled optimistic step
310
+ */
311
+ interface CompiledOptimisticStep {
312
+ do: 'optimistic';
313
+ target: string;
314
+ path?: CompiledExpression;
315
+ value: CompiledExpression;
316
+ result?: string;
317
+ timeout?: number;
318
+ }
319
+ /**
320
+ * Compiled confirm step
321
+ */
322
+ interface CompiledConfirmStep {
323
+ do: 'confirm';
324
+ id: CompiledExpression;
325
+ }
326
+ /**
327
+ * Compiled reject step
328
+ */
329
+ interface CompiledRejectStep {
330
+ do: 'reject';
331
+ id: CompiledExpression;
332
+ }
333
+ /**
334
+ * Compiled bind step
335
+ */
336
+ interface CompiledBindStep {
337
+ do: 'bind';
338
+ connection: string;
339
+ eventType?: string;
340
+ target: string;
341
+ path?: CompiledExpression;
342
+ transform?: CompiledExpression;
343
+ patch?: boolean;
344
+ }
345
+ /**
346
+ * Compiled unbind step
347
+ */
348
+ interface CompiledUnbindStep {
349
+ do: 'unbind';
350
+ connection: string;
351
+ target: string;
352
+ }
281
353
  /**
282
354
  * Compiled local action
283
355
  */
@@ -297,7 +369,39 @@ interface CompiledLocalStateNode {
297
369
  actions: Record<string, CompiledLocalAction>;
298
370
  child: CompiledNode;
299
371
  }
300
- type CompiledNode = CompiledElementNode | CompiledTextNode | CompiledIfNode | CompiledEachNode | CompiledMarkdownNode | CompiledCodeNode | CompiledSlotNode | CompiledPortalNode | CompiledLocalStateNode;
372
+ /**
373
+ * Compiled island node - represents an interactive island in the Islands Architecture
374
+ */
375
+ interface CompiledIslandNode {
376
+ kind: 'island';
377
+ id: string;
378
+ strategy: IslandStrategy;
379
+ strategyOptions?: IslandStrategyOptions;
380
+ content: CompiledNode;
381
+ state?: Record<string, {
382
+ type: string;
383
+ initial: unknown;
384
+ }>;
385
+ actions?: Record<string, CompiledAction>;
386
+ }
387
+ /**
388
+ * Compiled suspense node - represents an async boundary with fallback
389
+ */
390
+ interface CompiledSuspenseNode {
391
+ kind: 'suspense';
392
+ id: string;
393
+ fallback: CompiledNode;
394
+ content: CompiledNode;
395
+ }
396
+ /**
397
+ * Compiled error boundary node - represents an error handling boundary
398
+ */
399
+ interface CompiledErrorBoundaryNode {
400
+ kind: 'errorBoundary';
401
+ fallback: CompiledNode;
402
+ content: CompiledNode;
403
+ }
404
+ type CompiledNode = CompiledElementNode | CompiledTextNode | CompiledIfNode | CompiledEachNode | CompiledMarkdownNode | CompiledCodeNode | CompiledSlotNode | CompiledPortalNode | CompiledLocalStateNode | CompiledIslandNode | CompiledSuspenseNode | CompiledErrorBoundaryNode;
301
405
  interface CompiledElementNode {
302
406
  kind: 'element';
303
407
  tag: string;
@@ -576,4 +680,4 @@ declare function transformLayoutPass(layout: LayoutProgram, _context: LayoutAnal
576
680
  */
577
681
  declare function composeLayoutWithPage(layout: CompiledProgram, page: CompiledProgram, layoutParams?: Record<string, Expression>, slots?: Record<string, ViewNode>): CompiledProgram;
578
682
 
579
- export { type AnalysisContext, type AnalyzePassFailure, type AnalyzePassResult, type AnalyzePassSuccess, type CompileFailure, type CompileResult, type CompileSuccess, type CompiledAction, type CompiledActionStep, type CompiledArrayExpr, type CompiledBinExpr, type CompiledCallExpr, type CompiledCallStep, type CompiledClearTimerStep, type CompiledClipboardStep, type CompiledCloseStep, type CompiledCodeNode, type CompiledConcatExpr, type CompiledCondExpr, type CompiledDataExpr, type CompiledDelayStep, type CompiledDisposeStep, type CompiledDomStep, type CompiledEachNode, type CompiledElementNode, type CompiledEventHandler, type CompiledEventHandlerOptions, type CompiledExpression, type CompiledFetchStep, type CompiledFocusStep, type CompiledGenerateStep, type CompiledGetExpr, type CompiledIfNode, type CompiledIfStep, type CompiledImportExpr, type CompiledImportStep, type CompiledIndexExpr, type CompiledIntervalStep, type CompiledLambdaExpr, type CompiledLayoutProgram, type CompiledLifecycleHooks, type CompiledLitExpr, type CompiledLocalAction, type CompiledLocalStateNode, type CompiledMarkdownNode, type CompiledNavigateStep, type CompiledNode, type CompiledNotExpr, type CompiledParamExpr, type CompiledPortalNode, type CompiledProgram, type CompiledRefExpr, type CompiledRouteDefinition, type CompiledRouteExpr, type CompiledSendStep, type CompiledSetPathStep, type CompiledSetStep, type CompiledSlotNode, type CompiledStateExpr, type CompiledStorageStep, type CompiledStyleExpr, type CompiledSubscribeStep, type CompiledTextNode, type CompiledUpdateStep, type CompiledValidityExpr, type CompiledVarExpr, type LayoutAnalysisContext, type LayoutAnalysisFailure, type LayoutAnalysisResult, type LayoutAnalysisSuccess, type ValidatePassFailure, type ValidatePassResult, type ValidatePassSuccess, analyzeLayoutPass, analyzePass, compile, composeLayoutWithPage, transformLayoutPass, transformPass, validatePass };
683
+ export { type AnalysisContext, type AnalyzePassFailure, type AnalyzePassResult, type AnalyzePassSuccess, type CompileFailure, type CompileResult, type CompileSuccess, type CompiledAction, type CompiledActionStep, type CompiledArrayExpr, type CompiledBinExpr, type CompiledBindStep, type CompiledCallExpr, type CompiledCallStep, type CompiledClearTimerStep, type CompiledClipboardStep, type CompiledCloseStep, type CompiledCodeNode, type CompiledConcatExpr, type CompiledCondExpr, type CompiledConfirmStep, type CompiledDataExpr, type CompiledDelayStep, type CompiledDisposeStep, type CompiledDomStep, type CompiledEachNode, type CompiledElementNode, type CompiledErrorBoundaryNode, type CompiledEventHandler, type CompiledEventHandlerOptions, type CompiledExpression, type CompiledFetchStep, type CompiledFocusStep, type CompiledGenerateStep, type CompiledGetExpr, type CompiledIfNode, type CompiledIfStep, type CompiledImportExpr, type CompiledImportStep, type CompiledIndexExpr, type CompiledIntervalStep, type CompiledIslandNode, type CompiledLambdaExpr, type CompiledLayoutProgram, type CompiledLifecycleHooks, type CompiledLitExpr, type CompiledLocalAction, type CompiledLocalStateNode, type CompiledMarkdownNode, type CompiledNavigateStep, type CompiledNode, type CompiledNotExpr, type CompiledOptimisticStep, type CompiledParamExpr, type CompiledPortalNode, type CompiledProgram, type CompiledRefExpr, type CompiledRejectStep, type CompiledRouteDefinition, type CompiledRouteExpr, type CompiledSSECloseStep, type CompiledSSEConnectStep, type CompiledSendStep, type CompiledSetPathStep, type CompiledSetStep, type CompiledSlotNode, type CompiledStateExpr, type CompiledStorageStep, type CompiledStyleExpr, type CompiledSubscribeStep, type CompiledSuspenseNode, type CompiledTextNode, type CompiledUnbindStep, type CompiledUpdateStep, type CompiledValidityExpr, type CompiledVarExpr, type LayoutAnalysisContext, type LayoutAnalysisFailure, type LayoutAnalysisResult, type LayoutAnalysisSuccess, type ValidatePassFailure, type ValidatePassResult, type ValidatePassSuccess, analyzeLayoutPass, analyzePass, compile, composeLayoutWithPage, transformLayoutPass, transformPass, validatePass };
package/dist/index.js CHANGED
@@ -46,6 +46,7 @@ import {
46
46
  createUndefinedVariantError,
47
47
  createUndefinedLocalStateError,
48
48
  createLocalActionInvalidStepError,
49
+ createDuplicateIslandIdError,
49
50
  findSimilarNames,
50
51
  isEventHandler,
51
52
  DATA_SOURCE_TYPES,
@@ -141,7 +142,8 @@ function collectContext(programAst) {
141
142
  const styleNames = new Set(
142
143
  programAst.styles ? Object.keys(programAst.styles) : []
143
144
  );
144
- return { stateNames, actionNames, componentNames, routeParams, importNames, dataNames, refNames, styleNames };
145
+ const islandIds = /* @__PURE__ */ new Set();
146
+ return { stateNames, actionNames, componentNames, routeParams, importNames, dataNames, refNames, styleNames, islandIds };
145
147
  }
146
148
  function checkDuplicateActions(ast2) {
147
149
  const errors = [];
@@ -911,6 +913,57 @@ function validateViewNode(node, path, context, scope, options = { insideComponen
911
913
  );
912
914
  }
913
915
  break;
916
+ case "island": {
917
+ if (context.islandIds.has(node.id)) {
918
+ errors.push(createDuplicateIslandIdError(node.id, path));
919
+ } else {
920
+ context.islandIds.add(node.id);
921
+ }
922
+ const islandStateNames = new Set(
923
+ node.state ? Object.keys(node.state) : []
924
+ );
925
+ const islandActionNames = new Set(
926
+ node.actions ? node.actions.map((a) => a.name) : []
927
+ );
928
+ const islandParamScope = {
929
+ params: /* @__PURE__ */ new Set(),
930
+ componentName: `island:${node.id}`,
931
+ localStateNames: islandStateNames,
932
+ localActionNames: islandActionNames
933
+ };
934
+ errors.push(
935
+ ...validateViewNode(
936
+ node.content,
937
+ buildPath(path, "content"),
938
+ context,
939
+ scope,
940
+ { ...options, paramScope: islandParamScope }
941
+ )
942
+ );
943
+ if (node.actions) {
944
+ for (let i = 0; i < node.actions.length; i++) {
945
+ const action = node.actions[i];
946
+ if (!action) continue;
947
+ for (let j = 0; j < action.steps.length; j++) {
948
+ const step = action.steps[j];
949
+ if (!step) continue;
950
+ if (step.do === "set" || step.do === "update" || step.do === "setPath") {
951
+ const target = step.target;
952
+ if (!islandStateNames.has(target) && !context.stateNames.has(target)) {
953
+ errors.push(
954
+ createUndefinedStateError(
955
+ target,
956
+ buildPath(path, "actions", i, "steps", j, "target"),
957
+ createErrorOptionsWithSuggestion(target, /* @__PURE__ */ new Set([...islandStateNames, ...context.stateNames]))
958
+ )
959
+ );
960
+ }
961
+ }
962
+ }
963
+ }
964
+ }
965
+ break;
966
+ }
914
967
  }
915
968
  return errors;
916
969
  }
@@ -1687,6 +1740,62 @@ function transformActionStep(step) {
1687
1740
  }
1688
1741
  return compiledGenerateStep;
1689
1742
  }
1743
+ // ==================== Realtime Steps ====================
1744
+ case "sseConnect": {
1745
+ const sseStep = step;
1746
+ const compiled = {
1747
+ do: "sseConnect",
1748
+ connection: sseStep.connection,
1749
+ url: transformExpression(sseStep.url, emptyContext)
1750
+ };
1751
+ if (sseStep.eventTypes) compiled.eventTypes = sseStep.eventTypes;
1752
+ if (sseStep.reconnect) compiled.reconnect = sseStep.reconnect;
1753
+ if (sseStep.onOpen) compiled.onOpen = sseStep.onOpen.map(transformActionStep);
1754
+ if (sseStep.onMessage) compiled.onMessage = sseStep.onMessage.map(transformActionStep);
1755
+ if (sseStep.onError) compiled.onError = sseStep.onError.map(transformActionStep);
1756
+ return compiled;
1757
+ }
1758
+ case "sseClose": {
1759
+ const sseCloseStep = step;
1760
+ return { do: "sseClose", connection: sseCloseStep.connection };
1761
+ }
1762
+ case "optimistic": {
1763
+ const optStep = step;
1764
+ const compiled = {
1765
+ do: "optimistic",
1766
+ target: optStep.target,
1767
+ value: transformExpression(optStep.value, emptyContext)
1768
+ };
1769
+ if (optStep.path) compiled.path = transformExpression(optStep.path, emptyContext);
1770
+ if (optStep.result) compiled.result = optStep.result;
1771
+ if (optStep.timeout) compiled.timeout = optStep.timeout;
1772
+ return compiled;
1773
+ }
1774
+ case "confirm": {
1775
+ const confirmStep = step;
1776
+ return { do: "confirm", id: transformExpression(confirmStep.id, emptyContext) };
1777
+ }
1778
+ case "reject": {
1779
+ const rejectStep = step;
1780
+ return { do: "reject", id: transformExpression(rejectStep.id, emptyContext) };
1781
+ }
1782
+ case "bind": {
1783
+ const bindStep = step;
1784
+ const compiled = {
1785
+ do: "bind",
1786
+ connection: bindStep.connection,
1787
+ target: bindStep.target
1788
+ };
1789
+ if (bindStep.eventType) compiled.eventType = bindStep.eventType;
1790
+ if (bindStep.path) compiled.path = transformExpression(bindStep.path, emptyContext);
1791
+ if (bindStep.transform) compiled.transform = transformExpression(bindStep.transform, emptyContext);
1792
+ if (bindStep.patch) compiled.patch = bindStep.patch;
1793
+ return compiled;
1794
+ }
1795
+ case "unbind": {
1796
+ const unbindStep = step;
1797
+ return { do: "unbind", connection: unbindStep.connection, target: unbindStep.target };
1798
+ }
1690
1799
  }
1691
1800
  }
1692
1801
  function flattenSlotChildren(children, ctx) {
@@ -1831,6 +1940,46 @@ function transformViewNode(node, ctx) {
1831
1940
  children: compiledChildren
1832
1941
  };
1833
1942
  }
1943
+ case "island": {
1944
+ const islandNode = node;
1945
+ const compiledIsland = {
1946
+ kind: "island",
1947
+ id: islandNode.id,
1948
+ strategy: islandNode.strategy,
1949
+ content: transformViewNode(islandNode.content, ctx)
1950
+ };
1951
+ if (islandNode.strategyOptions) {
1952
+ compiledIsland.strategyOptions = islandNode.strategyOptions;
1953
+ }
1954
+ if (islandNode.state) {
1955
+ compiledIsland.state = transformState(islandNode.state);
1956
+ }
1957
+ if (islandNode.actions && islandNode.actions.length > 0) {
1958
+ compiledIsland.actions = transformActions(islandNode.actions);
1959
+ }
1960
+ return compiledIsland;
1961
+ }
1962
+ case "suspense": {
1963
+ const suspenseNode = node;
1964
+ return {
1965
+ kind: "suspense",
1966
+ id: suspenseNode.id,
1967
+ fallback: transformViewNode(suspenseNode.fallback, ctx),
1968
+ content: transformViewNode(suspenseNode.content, ctx)
1969
+ };
1970
+ }
1971
+ case "errorBoundary": {
1972
+ const errorBoundaryNode = node;
1973
+ return {
1974
+ kind: "errorBoundary",
1975
+ fallback: transformViewNode(errorBoundaryNode.fallback, ctx),
1976
+ content: transformViewNode(errorBoundaryNode.content, ctx)
1977
+ };
1978
+ }
1979
+ default: {
1980
+ const _exhaustiveCheck = node;
1981
+ throw new Error(`Unknown node kind: ${JSON.stringify(_exhaustiveCheck)}`);
1982
+ }
1834
1983
  }
1835
1984
  }
1836
1985
  function transformState(state) {
@@ -2672,6 +2821,52 @@ function transformViewNode2(node, ctx) {
2672
2821
  (child) => transformViewNode2(child, ctx)
2673
2822
  )
2674
2823
  };
2824
+ case "island": {
2825
+ const islandNode = node;
2826
+ const compiledIsland = {
2827
+ kind: "island",
2828
+ id: islandNode.id,
2829
+ strategy: islandNode.strategy,
2830
+ content: transformViewNode2(islandNode.content, ctx)
2831
+ };
2832
+ if (islandNode.strategyOptions) {
2833
+ compiledIsland.strategyOptions = islandNode.strategyOptions;
2834
+ }
2835
+ if (islandNode.state) {
2836
+ compiledIsland.state = transformLocalState2(islandNode.state);
2837
+ }
2838
+ if (islandNode.actions && islandNode.actions.length > 0) {
2839
+ compiledIsland.actions = {};
2840
+ for (const action of islandNode.actions) {
2841
+ compiledIsland.actions[action.name] = {
2842
+ name: action.name,
2843
+ steps: action.steps.map((s) => transformActionStep2(s))
2844
+ };
2845
+ }
2846
+ }
2847
+ return compiledIsland;
2848
+ }
2849
+ case "suspense": {
2850
+ const suspenseNode = node;
2851
+ return {
2852
+ kind: "suspense",
2853
+ id: suspenseNode.id,
2854
+ fallback: transformViewNode2(suspenseNode.fallback, ctx),
2855
+ content: transformViewNode2(suspenseNode.content, ctx)
2856
+ };
2857
+ }
2858
+ case "errorBoundary": {
2859
+ const errorBoundaryNode = node;
2860
+ return {
2861
+ kind: "errorBoundary",
2862
+ fallback: transformViewNode2(errorBoundaryNode.fallback, ctx),
2863
+ content: transformViewNode2(errorBoundaryNode.content, ctx)
2864
+ };
2865
+ }
2866
+ default: {
2867
+ const _exhaustiveCheck = node;
2868
+ throw new Error(`Unknown node kind: ${JSON.stringify(_exhaustiveCheck)}`);
2869
+ }
2675
2870
  }
2676
2871
  }
2677
2872
  function transformLayoutPass(layout, _context) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constela/compiler",
3
- "version": "0.14.7",
3
+ "version": "0.15.0",
4
4
  "description": "Compiler for Constela UI framework - AST to Program transformation",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -15,7 +15,7 @@
15
15
  "dist"
16
16
  ],
17
17
  "dependencies": {
18
- "@constela/core": "0.16.2"
18
+ "@constela/core": "0.17.0"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/node": "^20.10.0",