@constela/compiler 0.5.0 → 0.6.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 +49 -3
- package/dist/index.js +202 -8
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ interface AnalysisContext {
|
|
|
19
19
|
routeParams: Set<string>;
|
|
20
20
|
importNames: Set<string>;
|
|
21
21
|
dataNames: Set<string>;
|
|
22
|
+
refNames: Set<string>;
|
|
22
23
|
}
|
|
23
24
|
interface AnalyzePassSuccess {
|
|
24
25
|
ok: true;
|
|
@@ -86,7 +87,7 @@ interface CompiledAction {
|
|
|
86
87
|
name: string;
|
|
87
88
|
steps: CompiledActionStep[];
|
|
88
89
|
}
|
|
89
|
-
type CompiledActionStep = CompiledSetStep | CompiledUpdateStep | CompiledFetchStep | CompiledStorageStep | CompiledClipboardStep | CompiledNavigateStep;
|
|
90
|
+
type CompiledActionStep = CompiledSetStep | CompiledUpdateStep | CompiledFetchStep | CompiledStorageStep | CompiledClipboardStep | CompiledNavigateStep | CompiledImportStep | CompiledCallStep | CompiledSubscribeStep | CompiledDisposeStep;
|
|
90
91
|
interface CompiledSetStep {
|
|
91
92
|
do: 'set';
|
|
92
93
|
target: string;
|
|
@@ -133,10 +134,55 @@ interface CompiledNavigateStep {
|
|
|
133
134
|
target?: '_self' | '_blank';
|
|
134
135
|
replace?: boolean;
|
|
135
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Compiled ref expression
|
|
139
|
+
*/
|
|
140
|
+
interface CompiledRefExpr {
|
|
141
|
+
expr: 'ref';
|
|
142
|
+
name: string;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Compiled import step
|
|
146
|
+
*/
|
|
147
|
+
interface CompiledImportStep {
|
|
148
|
+
do: 'import';
|
|
149
|
+
module: string;
|
|
150
|
+
result: string;
|
|
151
|
+
onSuccess?: CompiledActionStep[];
|
|
152
|
+
onError?: CompiledActionStep[];
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Compiled call step
|
|
156
|
+
*/
|
|
157
|
+
interface CompiledCallStep {
|
|
158
|
+
do: 'call';
|
|
159
|
+
target: CompiledExpression;
|
|
160
|
+
args?: CompiledExpression[];
|
|
161
|
+
result?: string;
|
|
162
|
+
onSuccess?: CompiledActionStep[];
|
|
163
|
+
onError?: CompiledActionStep[];
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Compiled subscribe step
|
|
167
|
+
*/
|
|
168
|
+
interface CompiledSubscribeStep {
|
|
169
|
+
do: 'subscribe';
|
|
170
|
+
target: CompiledExpression;
|
|
171
|
+
event: string;
|
|
172
|
+
action: string;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Compiled dispose step
|
|
176
|
+
*/
|
|
177
|
+
interface CompiledDisposeStep {
|
|
178
|
+
do: 'dispose';
|
|
179
|
+
target: CompiledExpression;
|
|
180
|
+
}
|
|
136
181
|
type CompiledNode = CompiledElementNode | CompiledTextNode | CompiledIfNode | CompiledEachNode | CompiledMarkdownNode | CompiledCodeNode;
|
|
137
182
|
interface CompiledElementNode {
|
|
138
183
|
kind: 'element';
|
|
139
184
|
tag: string;
|
|
185
|
+
ref?: string;
|
|
140
186
|
props?: Record<string, CompiledExpression | CompiledEventHandler>;
|
|
141
187
|
children?: CompiledNode[];
|
|
142
188
|
}
|
|
@@ -167,7 +213,7 @@ interface CompiledCodeNode {
|
|
|
167
213
|
language: CompiledExpression;
|
|
168
214
|
content: CompiledExpression;
|
|
169
215
|
}
|
|
170
|
-
type CompiledExpression = CompiledLitExpr | CompiledStateExpr | CompiledVarExpr | CompiledBinExpr | CompiledNotExpr | CompiledCondExpr | CompiledGetExpr | CompiledRouteExpr | CompiledImportExpr;
|
|
216
|
+
type CompiledExpression = CompiledLitExpr | CompiledStateExpr | CompiledVarExpr | CompiledBinExpr | CompiledNotExpr | CompiledCondExpr | CompiledGetExpr | CompiledRouteExpr | CompiledImportExpr | CompiledRefExpr;
|
|
171
217
|
interface CompiledLitExpr {
|
|
172
218
|
expr: 'lit';
|
|
173
219
|
value: string | number | boolean | null | unknown[];
|
|
@@ -344,4 +390,4 @@ declare function transformLayoutPass(layout: LayoutProgram, _context: LayoutAnal
|
|
|
344
390
|
*/
|
|
345
391
|
declare function composeLayoutWithPage(layout: CompiledProgram, page: CompiledProgram, slots?: Record<string, ViewNode>): CompiledProgram;
|
|
346
392
|
|
|
347
|
-
export { type AnalysisContext, type AnalyzePassFailure, type AnalyzePassResult, type AnalyzePassSuccess, type CompileFailure, type CompileResult, type CompileSuccess, type CompiledAction, type CompiledActionStep, type CompiledClipboardStep, type CompiledCodeNode, type CompiledEachNode, type CompiledElementNode, type CompiledEventHandler, type CompiledExpression, type CompiledFetchStep, type CompiledIfNode, type CompiledImportExpr, type CompiledLayoutProgram, type CompiledLifecycleHooks, type CompiledMarkdownNode, type CompiledNavigateStep, type CompiledNode, type CompiledProgram, type CompiledRouteDefinition, type CompiledRouteExpr, type CompiledSetStep, type CompiledStorageStep, type CompiledTextNode, type CompiledUpdateStep, type LayoutAnalysisContext, type LayoutAnalysisFailure, type LayoutAnalysisResult, type LayoutAnalysisSuccess, type ValidatePassFailure, type ValidatePassResult, type ValidatePassSuccess, analyzeLayoutPass, analyzePass, compile, composeLayoutWithPage, transformLayoutPass, transformPass, validatePass };
|
|
393
|
+
export { type AnalysisContext, type AnalyzePassFailure, type AnalyzePassResult, type AnalyzePassSuccess, type CompileFailure, type CompileResult, type CompileSuccess, type CompiledAction, type CompiledActionStep, type CompiledCallStep, type CompiledClipboardStep, type CompiledCodeNode, type CompiledDisposeStep, type CompiledEachNode, type CompiledElementNode, type CompiledEventHandler, type CompiledExpression, type CompiledFetchStep, type CompiledIfNode, type CompiledImportExpr, type CompiledImportStep, type CompiledLayoutProgram, type CompiledLifecycleHooks, type CompiledMarkdownNode, type CompiledNavigateStep, type CompiledNode, type CompiledProgram, type CompiledRefExpr, type CompiledRouteDefinition, type CompiledRouteExpr, type CompiledSetStep, type CompiledStorageStep, type CompiledSubscribeStep, type CompiledTextNode, type CompiledUpdateStep, 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
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
createInvalidClipboardOperationError,
|
|
42
42
|
createClipboardWriteMissingValueError,
|
|
43
43
|
createInvalidNavigateTargetError,
|
|
44
|
+
createUndefinedRefError,
|
|
44
45
|
isEventHandler,
|
|
45
46
|
DATA_SOURCE_TYPES,
|
|
46
47
|
DATA_TRANSFORMS,
|
|
@@ -62,22 +63,68 @@ function extractRouteParams(path) {
|
|
|
62
63
|
}
|
|
63
64
|
return params;
|
|
64
65
|
}
|
|
65
|
-
function
|
|
66
|
-
const
|
|
67
|
-
|
|
66
|
+
function collectRefs(node) {
|
|
67
|
+
const refs = /* @__PURE__ */ new Set();
|
|
68
|
+
switch (node.kind) {
|
|
69
|
+
case "element":
|
|
70
|
+
if (node.ref) {
|
|
71
|
+
refs.add(node.ref);
|
|
72
|
+
}
|
|
73
|
+
if (node.children) {
|
|
74
|
+
for (const child of node.children) {
|
|
75
|
+
for (const ref of collectRefs(child)) {
|
|
76
|
+
refs.add(ref);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
case "if":
|
|
82
|
+
for (const ref of collectRefs(node.then)) {
|
|
83
|
+
refs.add(ref);
|
|
84
|
+
}
|
|
85
|
+
if (node.else) {
|
|
86
|
+
for (const ref of collectRefs(node.else)) {
|
|
87
|
+
refs.add(ref);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
break;
|
|
91
|
+
case "each":
|
|
92
|
+
for (const ref of collectRefs(node.body)) {
|
|
93
|
+
refs.add(ref);
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
case "component":
|
|
97
|
+
if (node.children) {
|
|
98
|
+
for (const child of node.children) {
|
|
99
|
+
for (const ref of collectRefs(child)) {
|
|
100
|
+
refs.add(ref);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
break;
|
|
105
|
+
case "text":
|
|
106
|
+
case "slot":
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
return refs;
|
|
110
|
+
}
|
|
111
|
+
function collectContext(programAst) {
|
|
112
|
+
const stateNames = new Set(Object.keys(programAst.state));
|
|
113
|
+
const actionNames = new Set(programAst.actions.map((a) => a.name));
|
|
68
114
|
const componentNames = new Set(
|
|
69
|
-
|
|
115
|
+
programAst.components ? Object.keys(programAst.components) : []
|
|
70
116
|
);
|
|
71
117
|
const routeParams = new Set(
|
|
72
|
-
|
|
118
|
+
programAst.route ? extractRouteParams(programAst.route.path) : []
|
|
73
119
|
);
|
|
74
120
|
const importNames = new Set(
|
|
75
|
-
|
|
121
|
+
programAst.imports ? Object.keys(programAst.imports) : []
|
|
76
122
|
);
|
|
77
123
|
const dataNames = new Set(
|
|
78
|
-
|
|
124
|
+
programAst.data ? Object.keys(programAst.data) : []
|
|
79
125
|
);
|
|
80
|
-
|
|
126
|
+
const refNames = collectRefs(programAst.view);
|
|
127
|
+
return { stateNames, actionNames, componentNames, routeParams, importNames, dataNames, refNames };
|
|
81
128
|
}
|
|
82
129
|
function checkDuplicateActions(ast2) {
|
|
83
130
|
const errors = [];
|
|
@@ -137,6 +184,12 @@ function validateExpression(expr, path, context, scope, paramScope) {
|
|
|
137
184
|
}
|
|
138
185
|
break;
|
|
139
186
|
}
|
|
187
|
+
case "ref": {
|
|
188
|
+
if (!context.refNames.has(expr.name)) {
|
|
189
|
+
errors.push(createUndefinedRefError(expr.name, path));
|
|
190
|
+
}
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
140
193
|
case "bin":
|
|
141
194
|
errors.push(...validateExpression(expr.left, buildPath(path, "left"), context, scope, paramScope));
|
|
142
195
|
errors.push(...validateExpression(expr.right, buildPath(path, "right"), context, scope, paramScope));
|
|
@@ -322,6 +375,79 @@ function validateActionStep(step, path, context) {
|
|
|
322
375
|
}
|
|
323
376
|
break;
|
|
324
377
|
}
|
|
378
|
+
case "import": {
|
|
379
|
+
const importStep = step;
|
|
380
|
+
if (importStep.onSuccess) {
|
|
381
|
+
for (let i = 0; i < importStep.onSuccess.length; i++) {
|
|
382
|
+
const successStep = importStep.onSuccess[i];
|
|
383
|
+
if (successStep === void 0) continue;
|
|
384
|
+
errors.push(
|
|
385
|
+
...validateActionStep(successStep, buildPath(path, "onSuccess", i), context)
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
if (importStep.onError) {
|
|
390
|
+
for (let i = 0; i < importStep.onError.length; i++) {
|
|
391
|
+
const errorStep = importStep.onError[i];
|
|
392
|
+
if (errorStep === void 0) continue;
|
|
393
|
+
errors.push(
|
|
394
|
+
...validateActionStep(errorStep, buildPath(path, "onError", i), context)
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
case "call": {
|
|
401
|
+
const callStep = step;
|
|
402
|
+
errors.push(
|
|
403
|
+
...validateExpressionStateOnly(callStep.target, buildPath(path, "target"), context)
|
|
404
|
+
);
|
|
405
|
+
if (callStep.args) {
|
|
406
|
+
for (let i = 0; i < callStep.args.length; i++) {
|
|
407
|
+
const arg = callStep.args[i];
|
|
408
|
+
if (arg === void 0) continue;
|
|
409
|
+
errors.push(
|
|
410
|
+
...validateExpressionStateOnly(arg, buildPath(path, "args", i), context)
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
if (callStep.onSuccess) {
|
|
415
|
+
for (let i = 0; i < callStep.onSuccess.length; i++) {
|
|
416
|
+
const successStep = callStep.onSuccess[i];
|
|
417
|
+
if (successStep === void 0) continue;
|
|
418
|
+
errors.push(
|
|
419
|
+
...validateActionStep(successStep, buildPath(path, "onSuccess", i), context)
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
if (callStep.onError) {
|
|
424
|
+
for (let i = 0; i < callStep.onError.length; i++) {
|
|
425
|
+
const errorStep = callStep.onError[i];
|
|
426
|
+
if (errorStep === void 0) continue;
|
|
427
|
+
errors.push(
|
|
428
|
+
...validateActionStep(errorStep, buildPath(path, "onError", i), context)
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
case "subscribe": {
|
|
435
|
+
const subscribeStep = step;
|
|
436
|
+
errors.push(
|
|
437
|
+
...validateExpressionStateOnly(subscribeStep.target, buildPath(path, "target"), context)
|
|
438
|
+
);
|
|
439
|
+
if (!context.actionNames.has(subscribeStep.action)) {
|
|
440
|
+
errors.push(createUndefinedActionError(subscribeStep.action, buildPath(path, "action")));
|
|
441
|
+
}
|
|
442
|
+
break;
|
|
443
|
+
}
|
|
444
|
+
case "dispose": {
|
|
445
|
+
const disposeStep = step;
|
|
446
|
+
errors.push(
|
|
447
|
+
...validateExpressionStateOnly(disposeStep.target, buildPath(path, "target"), context)
|
|
448
|
+
);
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
325
451
|
}
|
|
326
452
|
return errors;
|
|
327
453
|
}
|
|
@@ -362,6 +488,12 @@ function validateExpressionStateOnly(expr, path, context) {
|
|
|
362
488
|
}
|
|
363
489
|
break;
|
|
364
490
|
}
|
|
491
|
+
case "ref": {
|
|
492
|
+
if (!context.refNames.has(expr.name)) {
|
|
493
|
+
errors.push(createUndefinedRefError(expr.name, path));
|
|
494
|
+
}
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
365
497
|
case "bin":
|
|
366
498
|
errors.push(...validateExpressionStateOnly(expr.left, buildPath(path, "left"), context));
|
|
367
499
|
errors.push(...validateExpressionStateOnly(expr.right, buildPath(path, "right"), context));
|
|
@@ -421,6 +553,12 @@ function validateExpressionInEventPayload(expr, path, context, scope) {
|
|
|
421
553
|
}
|
|
422
554
|
break;
|
|
423
555
|
}
|
|
556
|
+
case "ref": {
|
|
557
|
+
if (!context.refNames.has(expr.name)) {
|
|
558
|
+
errors.push(createUndefinedRefError(expr.name, path));
|
|
559
|
+
}
|
|
560
|
+
break;
|
|
561
|
+
}
|
|
424
562
|
case "bin":
|
|
425
563
|
errors.push(
|
|
426
564
|
...validateExpressionInEventPayload(expr.left, buildPath(path, "left"), context, scope)
|
|
@@ -912,6 +1050,8 @@ function transformExpression(expr, ctx) {
|
|
|
912
1050
|
}
|
|
913
1051
|
return dataExpr;
|
|
914
1052
|
}
|
|
1053
|
+
case "ref":
|
|
1054
|
+
return { expr: "ref", name: expr.name };
|
|
915
1055
|
}
|
|
916
1056
|
}
|
|
917
1057
|
function transformEventHandler(handler, ctx) {
|
|
@@ -1028,6 +1168,57 @@ function transformActionStep(step) {
|
|
|
1028
1168
|
}
|
|
1029
1169
|
return compiledNavigateStep;
|
|
1030
1170
|
}
|
|
1171
|
+
case "import": {
|
|
1172
|
+
const importStep = step;
|
|
1173
|
+
const compiledImportStep = {
|
|
1174
|
+
do: "import",
|
|
1175
|
+
module: importStep.module,
|
|
1176
|
+
result: importStep.result
|
|
1177
|
+
};
|
|
1178
|
+
if (importStep.onSuccess) {
|
|
1179
|
+
compiledImportStep.onSuccess = importStep.onSuccess.map(transformActionStep);
|
|
1180
|
+
}
|
|
1181
|
+
if (importStep.onError) {
|
|
1182
|
+
compiledImportStep.onError = importStep.onError.map(transformActionStep);
|
|
1183
|
+
}
|
|
1184
|
+
return compiledImportStep;
|
|
1185
|
+
}
|
|
1186
|
+
case "call": {
|
|
1187
|
+
const callStep = step;
|
|
1188
|
+
const compiledCallStep = {
|
|
1189
|
+
do: "call",
|
|
1190
|
+
target: transformExpression(callStep.target, emptyContext)
|
|
1191
|
+
};
|
|
1192
|
+
if (callStep.args) {
|
|
1193
|
+
compiledCallStep.args = callStep.args.map((arg) => transformExpression(arg, emptyContext));
|
|
1194
|
+
}
|
|
1195
|
+
if (callStep.result) {
|
|
1196
|
+
compiledCallStep.result = callStep.result;
|
|
1197
|
+
}
|
|
1198
|
+
if (callStep.onSuccess) {
|
|
1199
|
+
compiledCallStep.onSuccess = callStep.onSuccess.map(transformActionStep);
|
|
1200
|
+
}
|
|
1201
|
+
if (callStep.onError) {
|
|
1202
|
+
compiledCallStep.onError = callStep.onError.map(transformActionStep);
|
|
1203
|
+
}
|
|
1204
|
+
return compiledCallStep;
|
|
1205
|
+
}
|
|
1206
|
+
case "subscribe": {
|
|
1207
|
+
const subscribeStep = step;
|
|
1208
|
+
return {
|
|
1209
|
+
do: "subscribe",
|
|
1210
|
+
target: transformExpression(subscribeStep.target, emptyContext),
|
|
1211
|
+
event: subscribeStep.event,
|
|
1212
|
+
action: subscribeStep.action
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
case "dispose": {
|
|
1216
|
+
const disposeStep = step;
|
|
1217
|
+
return {
|
|
1218
|
+
do: "dispose",
|
|
1219
|
+
target: transformExpression(disposeStep.target, emptyContext)
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1031
1222
|
}
|
|
1032
1223
|
}
|
|
1033
1224
|
function flattenSlotChildren(children, ctx) {
|
|
@@ -1050,6 +1241,9 @@ function transformViewNode(node, ctx) {
|
|
|
1050
1241
|
kind: "element",
|
|
1051
1242
|
tag: node.tag
|
|
1052
1243
|
};
|
|
1244
|
+
if (node.ref) {
|
|
1245
|
+
compiledElement.ref = node.ref;
|
|
1246
|
+
}
|
|
1053
1247
|
if (node.props) {
|
|
1054
1248
|
compiledElement.props = {};
|
|
1055
1249
|
for (const [propName, propValue] of Object.entries(node.props)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constela/compiler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.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.6.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@types/node": "^20.10.0",
|