@constela/compiler 0.9.1 → 0.10.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/README.md +2 -0
- package/dist/index.d.ts +21 -2
- package/dist/index.js +86 -8
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -50,6 +50,8 @@ The compiler transforms JSON programs through three passes:
|
|
|
50
50
|
- **setPath** - Compiles to efficient path-based state updates
|
|
51
51
|
- **Key-based each** - Compiles key expressions for list diffing
|
|
52
52
|
- **WebSocket connections** - Compiles connection definitions and send/close actions
|
|
53
|
+
- **concat expression** - Compiles string concatenation expressions
|
|
54
|
+
- **Object payloads** - Supports object-shaped event handler payloads with expression fields
|
|
53
55
|
|
|
54
56
|
## CompiledProgram Structure
|
|
55
57
|
|
package/dist/index.d.ts
CHANGED
|
@@ -217,7 +217,26 @@ interface CompiledCloseStep {
|
|
|
217
217
|
do: 'close';
|
|
218
218
|
connection: string;
|
|
219
219
|
}
|
|
220
|
-
|
|
220
|
+
/**
|
|
221
|
+
* Compiled local action
|
|
222
|
+
*/
|
|
223
|
+
interface CompiledLocalAction {
|
|
224
|
+
name: string;
|
|
225
|
+
steps: CompiledActionStep[];
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Compiled local state node - wraps component with local state
|
|
229
|
+
*/
|
|
230
|
+
interface CompiledLocalStateNode {
|
|
231
|
+
kind: 'localState';
|
|
232
|
+
state: Record<string, {
|
|
233
|
+
type: string;
|
|
234
|
+
initial: unknown;
|
|
235
|
+
}>;
|
|
236
|
+
actions: Record<string, CompiledLocalAction>;
|
|
237
|
+
child: CompiledNode;
|
|
238
|
+
}
|
|
239
|
+
type CompiledNode = CompiledElementNode | CompiledTextNode | CompiledIfNode | CompiledEachNode | CompiledMarkdownNode | CompiledCodeNode | CompiledSlotNode | CompiledLocalStateNode;
|
|
221
240
|
interface CompiledElementNode {
|
|
222
241
|
kind: 'element';
|
|
223
242
|
tag: string;
|
|
@@ -459,4 +478,4 @@ declare function transformLayoutPass(layout: LayoutProgram, _context: LayoutAnal
|
|
|
459
478
|
*/
|
|
460
479
|
declare function composeLayoutWithPage(layout: CompiledProgram, page: CompiledProgram, layoutParams?: Record<string, Expression>, slots?: Record<string, ViewNode>): CompiledProgram;
|
|
461
480
|
|
|
462
|
-
export { type AnalysisContext, type AnalyzePassFailure, type AnalyzePassResult, type AnalyzePassSuccess, type CompileFailure, type CompileResult, type CompileSuccess, type CompiledAction, type CompiledActionStep, type CompiledBinExpr, type CompiledCallStep, type CompiledClipboardStep, type CompiledCloseStep, type CompiledCodeNode, type CompiledConcatExpr, type CompiledCondExpr, type CompiledDataExpr, type CompiledDisposeStep, type CompiledDomStep, type CompiledEachNode, type CompiledElementNode, type CompiledEventHandler, type CompiledExpression, type CompiledFetchStep, type CompiledGetExpr, type CompiledIfNode, type CompiledIfStep, type CompiledImportExpr, type CompiledImportStep, type CompiledIndexExpr, type CompiledLayoutProgram, type CompiledLifecycleHooks, type CompiledLitExpr, type CompiledMarkdownNode, type CompiledNavigateStep, type CompiledNode, type CompiledNotExpr, type CompiledParamExpr, 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 CompiledVarExpr, type LayoutAnalysisContext, type LayoutAnalysisFailure, type LayoutAnalysisResult, type LayoutAnalysisSuccess, type ValidatePassFailure, type ValidatePassResult, type ValidatePassSuccess, analyzeLayoutPass, analyzePass, compile, composeLayoutWithPage, transformLayoutPass, transformPass, validatePass };
|
|
481
|
+
export { type AnalysisContext, type AnalyzePassFailure, type AnalyzePassResult, type AnalyzePassSuccess, type CompileFailure, type CompileResult, type CompileSuccess, type CompiledAction, type CompiledActionStep, type CompiledBinExpr, type CompiledCallStep, type CompiledClipboardStep, type CompiledCloseStep, type CompiledCodeNode, type CompiledConcatExpr, type CompiledCondExpr, type CompiledDataExpr, type CompiledDisposeStep, type CompiledDomStep, type CompiledEachNode, type CompiledElementNode, type CompiledEventHandler, type CompiledExpression, type CompiledFetchStep, type CompiledGetExpr, type CompiledIfNode, type CompiledIfStep, type CompiledImportExpr, type CompiledImportStep, type CompiledIndexExpr, type CompiledLayoutProgram, type CompiledLifecycleHooks, type CompiledLitExpr, type CompiledLocalAction, type CompiledLocalStateNode, type CompiledMarkdownNode, type CompiledNavigateStep, type CompiledNode, type CompiledNotExpr, type CompiledParamExpr, 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 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
|
@@ -44,6 +44,8 @@ import {
|
|
|
44
44
|
createUndefinedRefError,
|
|
45
45
|
createUndefinedStyleError,
|
|
46
46
|
createUndefinedVariantError,
|
|
47
|
+
createUndefinedLocalStateError,
|
|
48
|
+
createLocalActionInvalidStepError,
|
|
47
49
|
findSimilarNames,
|
|
48
50
|
isEventHandler,
|
|
49
51
|
DATA_SOURCE_TYPES,
|
|
@@ -157,12 +159,19 @@ function checkDuplicateActions(ast2) {
|
|
|
157
159
|
function validateExpression(expr, path, context, scope, paramScope) {
|
|
158
160
|
const errors = [];
|
|
159
161
|
switch (expr.expr) {
|
|
160
|
-
case "state":
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
case "state": {
|
|
163
|
+
const isGlobalState = context.stateNames.has(expr.name);
|
|
164
|
+
const isLocalState = paramScope?.localStateNames?.has(expr.name) ?? false;
|
|
165
|
+
if (!isGlobalState && !isLocalState) {
|
|
166
|
+
const availableNames = /* @__PURE__ */ new Set([
|
|
167
|
+
...context.stateNames,
|
|
168
|
+
...paramScope?.localStateNames ?? []
|
|
169
|
+
]);
|
|
170
|
+
const errorOptions = createErrorOptionsWithSuggestion(expr.name, availableNames);
|
|
163
171
|
errors.push(createUndefinedStateError(expr.name, path, errorOptions));
|
|
164
172
|
}
|
|
165
173
|
break;
|
|
174
|
+
}
|
|
166
175
|
case "var":
|
|
167
176
|
if (!scope.has(expr.name)) {
|
|
168
177
|
errors.push(createUndefinedVarError(expr.name, path));
|
|
@@ -706,8 +715,14 @@ function validateViewNode(node, path, context, scope, options = { insideComponen
|
|
|
706
715
|
for (const [propName, propValue] of Object.entries(node.props)) {
|
|
707
716
|
const propPath = buildPath(path, "props", propName);
|
|
708
717
|
if (isEventHandler(propValue)) {
|
|
709
|
-
|
|
710
|
-
|
|
718
|
+
const isGlobalAction = context.actionNames.has(propValue.action);
|
|
719
|
+
const isLocalAction = paramScope?.localActionNames?.has(propValue.action) ?? false;
|
|
720
|
+
if (!isGlobalAction && !isLocalAction) {
|
|
721
|
+
const availableNames = /* @__PURE__ */ new Set([
|
|
722
|
+
...context.actionNames,
|
|
723
|
+
...paramScope?.localActionNames ?? []
|
|
724
|
+
]);
|
|
725
|
+
const errorOptions = createErrorOptionsWithSuggestion(propValue.action, availableNames);
|
|
711
726
|
errors.push(createUndefinedActionError(propValue.action, propPath, errorOptions));
|
|
712
727
|
}
|
|
713
728
|
if (propValue.payload) {
|
|
@@ -910,21 +925,58 @@ function detectComponentCycles(programAst, context) {
|
|
|
910
925
|
}
|
|
911
926
|
return errors;
|
|
912
927
|
}
|
|
928
|
+
function validateLocalActions(localActions, localStateNames, componentPath) {
|
|
929
|
+
const errors = [];
|
|
930
|
+
for (let i = 0; i < localActions.length; i++) {
|
|
931
|
+
const action = localActions[i];
|
|
932
|
+
if (!action) continue;
|
|
933
|
+
const actionPath = buildPath(componentPath, "localActions", i);
|
|
934
|
+
for (let j = 0; j < action.steps.length; j++) {
|
|
935
|
+
const step = action.steps[j];
|
|
936
|
+
if (!step) continue;
|
|
937
|
+
const stepPath = buildPath(actionPath, "steps", j);
|
|
938
|
+
const stepDo = step.do;
|
|
939
|
+
if (stepDo !== "set" && stepDo !== "update" && stepDo !== "setPath") {
|
|
940
|
+
errors.push(createLocalActionInvalidStepError(stepDo, stepPath));
|
|
941
|
+
continue;
|
|
942
|
+
}
|
|
943
|
+
if (!localStateNames.has(step.target)) {
|
|
944
|
+
const errorOptions = createErrorOptionsWithSuggestion(step.target, localStateNames);
|
|
945
|
+
errors.push(createUndefinedLocalStateError(step.target, buildPath(stepPath, "target"), errorOptions));
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
return errors;
|
|
950
|
+
}
|
|
913
951
|
function validateComponents(programAst, context) {
|
|
914
952
|
const errors = [];
|
|
915
953
|
if (!programAst.components) return errors;
|
|
916
954
|
for (const [name, def] of Object.entries(programAst.components)) {
|
|
955
|
+
const componentPath = buildPath("", "components", name);
|
|
956
|
+
const localStateNames = new Set(
|
|
957
|
+
def.localState ? Object.keys(def.localState) : []
|
|
958
|
+
);
|
|
959
|
+
const localActionNames = new Set(
|
|
960
|
+
def.localActions ? def.localActions.map((a) => a.name) : []
|
|
961
|
+
);
|
|
917
962
|
const paramNames = new Set(
|
|
918
963
|
def.params ? Object.keys(def.params) : []
|
|
919
964
|
);
|
|
920
965
|
const paramScope = {
|
|
921
966
|
params: paramNames,
|
|
922
|
-
componentName: name
|
|
967
|
+
componentName: name,
|
|
968
|
+
localStateNames,
|
|
969
|
+
localActionNames
|
|
923
970
|
};
|
|
971
|
+
if (def.localActions && def.localActions.length > 0) {
|
|
972
|
+
errors.push(
|
|
973
|
+
...validateLocalActions(def.localActions, localStateNames, componentPath)
|
|
974
|
+
);
|
|
975
|
+
}
|
|
924
976
|
errors.push(
|
|
925
977
|
...validateViewNode(
|
|
926
978
|
def.view,
|
|
927
|
-
buildPath(
|
|
979
|
+
buildPath(componentPath, "view"),
|
|
928
980
|
context,
|
|
929
981
|
/* @__PURE__ */ new Set(),
|
|
930
982
|
{ insideComponent: true, paramScope }
|
|
@@ -1480,7 +1532,16 @@ function transformViewNode(node, ctx) {
|
|
|
1480
1532
|
currentParams: params,
|
|
1481
1533
|
currentChildren: children
|
|
1482
1534
|
};
|
|
1483
|
-
|
|
1535
|
+
const expandedView = transformViewNode(def.view, newCtx);
|
|
1536
|
+
if (def.localState && Object.keys(def.localState).length > 0) {
|
|
1537
|
+
return {
|
|
1538
|
+
kind: "localState",
|
|
1539
|
+
state: transformLocalState(def.localState),
|
|
1540
|
+
actions: transformLocalActions(def.localActions ?? []),
|
|
1541
|
+
child: expandedView
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
return expandedView;
|
|
1484
1545
|
}
|
|
1485
1546
|
case "markdown":
|
|
1486
1547
|
return {
|
|
@@ -1519,6 +1580,23 @@ function transformState(state) {
|
|
|
1519
1580
|
}
|
|
1520
1581
|
return compiledState;
|
|
1521
1582
|
}
|
|
1583
|
+
function transformLocalState(localState) {
|
|
1584
|
+
const result = {};
|
|
1585
|
+
for (const [name, field] of Object.entries(localState)) {
|
|
1586
|
+
result[name] = { type: field.type, initial: field.initial };
|
|
1587
|
+
}
|
|
1588
|
+
return result;
|
|
1589
|
+
}
|
|
1590
|
+
function transformLocalActions(localActions) {
|
|
1591
|
+
const result = {};
|
|
1592
|
+
for (const action of localActions) {
|
|
1593
|
+
result[action.name] = {
|
|
1594
|
+
name: action.name,
|
|
1595
|
+
steps: action.steps.map(transformActionStep)
|
|
1596
|
+
};
|
|
1597
|
+
}
|
|
1598
|
+
return result;
|
|
1599
|
+
}
|
|
1522
1600
|
function transformActions(actions) {
|
|
1523
1601
|
const compiledActions = {};
|
|
1524
1602
|
for (const action of actions) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constela/compiler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.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.
|
|
18
|
+
"@constela/core": "0.10.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@types/node": "^20.10.0",
|