@constela/compiler 0.2.0 → 0.3.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
@@ -77,6 +77,8 @@ interface CompiledUpdateStep {
77
77
  target: string;
78
78
  operation: string;
79
79
  value?: CompiledExpression;
80
+ index?: CompiledExpression;
81
+ deleteCount?: CompiledExpression;
80
82
  }
81
83
  interface CompiledFetchStep {
82
84
  do: 'fetch';
@@ -112,7 +114,7 @@ interface CompiledEachNode {
112
114
  key?: CompiledExpression;
113
115
  body: CompiledNode;
114
116
  }
115
- type CompiledExpression = CompiledLitExpr | CompiledStateExpr | CompiledVarExpr | CompiledBinExpr | CompiledNotExpr;
117
+ type CompiledExpression = CompiledLitExpr | CompiledStateExpr | CompiledVarExpr | CompiledBinExpr | CompiledNotExpr | CompiledCondExpr | CompiledGetExpr;
116
118
  interface CompiledLitExpr {
117
119
  expr: 'lit';
118
120
  value: string | number | boolean | null | unknown[];
@@ -136,6 +138,17 @@ interface CompiledNotExpr {
136
138
  expr: 'not';
137
139
  operand: CompiledExpression;
138
140
  }
141
+ interface CompiledCondExpr {
142
+ expr: 'cond';
143
+ if: CompiledExpression;
144
+ then: CompiledExpression;
145
+ else: CompiledExpression;
146
+ }
147
+ interface CompiledGetExpr {
148
+ expr: 'get';
149
+ base: CompiledExpression;
150
+ path: string;
151
+ }
139
152
  interface CompiledEventHandler {
140
153
  event: string;
141
154
  action: string;
@@ -200,4 +213,4 @@ type ValidatePassResult = ValidatePassSuccess | ValidatePassFailure;
200
213
  */
201
214
  declare function validatePass(input: unknown): ValidatePassResult;
202
215
 
203
- export { type AnalysisContext, type AnalyzePassFailure, type AnalyzePassResult, type AnalyzePassSuccess, type CompileFailure, type CompileResult, type CompileSuccess, type CompiledAction, type CompiledActionStep, type CompiledEachNode, type CompiledElementNode, type CompiledEventHandler, type CompiledExpression, type CompiledIfNode, type CompiledNode, type CompiledProgram, type CompiledTextNode, type ValidatePassFailure, type ValidatePassResult, type ValidatePassSuccess, analyzePass, compile, transformPass, validatePass };
216
+ export { type AnalysisContext, type AnalyzePassFailure, type AnalyzePassResult, type AnalyzePassSuccess, type CompileFailure, type CompileResult, type CompileSuccess, type CompiledAction, type CompiledActionStep, type CompiledEachNode, type CompiledElementNode, type CompiledEventHandler, type CompiledExpression, type CompiledFetchStep, type CompiledIfNode, type CompiledNode, type CompiledProgram, type CompiledSetStep, type CompiledTextNode, type CompiledUpdateStep, type ValidatePassFailure, type ValidatePassResult, type ValidatePassSuccess, analyzePass, compile, transformPass, validatePass };
package/dist/index.js CHANGED
@@ -25,6 +25,8 @@ import {
25
25
  createComponentCycleError,
26
26
  createUndefinedParamError,
27
27
  createSchemaError,
28
+ createOperationInvalidForTypeError,
29
+ createOperationMissingFieldError,
28
30
  isEventHandler
29
31
  } from "@constela/core";
30
32
  function buildPath(base, ...segments) {
@@ -78,6 +80,14 @@ function validateExpression(expr, path, context, scope, paramScope) {
78
80
  break;
79
81
  case "lit":
80
82
  break;
83
+ case "cond":
84
+ errors.push(...validateExpression(expr.if, buildPath(path, "if"), context, scope, paramScope));
85
+ errors.push(...validateExpression(expr.then, buildPath(path, "then"), context, scope, paramScope));
86
+ errors.push(...validateExpression(expr.else, buildPath(path, "else"), context, scope, paramScope));
87
+ break;
88
+ case "get":
89
+ errors.push(...validateExpression(expr.base, buildPath(path, "base"), context, scope, paramScope));
90
+ break;
81
91
  }
82
92
  return errors;
83
93
  }
@@ -92,16 +102,50 @@ function validateActionStep(step, path, context) {
92
102
  ...validateExpressionStateOnly(step.value, buildPath(path, "value"), context)
93
103
  );
94
104
  break;
95
- case "update":
105
+ case "update": {
96
106
  if (!context.stateNames.has(step.target)) {
97
107
  errors.push(createUndefinedStateError(step.target, buildPath(path, "target")));
108
+ } else {
109
+ const stateField = ast.state[step.target];
110
+ if (stateField) {
111
+ const stateType = stateField.type;
112
+ const op = step.operation;
113
+ if (op === "toggle" && stateType !== "boolean") {
114
+ errors.push(createOperationInvalidForTypeError(op, stateType, buildPath(path, "operation")));
115
+ }
116
+ if (op === "merge" && stateType !== "object") {
117
+ errors.push(createOperationInvalidForTypeError(op, stateType, buildPath(path, "operation")));
118
+ }
119
+ if ((op === "increment" || op === "decrement") && stateType !== "number") {
120
+ errors.push(createOperationInvalidForTypeError(op, stateType, buildPath(path, "operation")));
121
+ }
122
+ if ((op === "push" || op === "pop" || op === "remove" || op === "replaceAt" || op === "insertAt" || op === "splice") && stateType !== "list") {
123
+ errors.push(createOperationInvalidForTypeError(op, stateType, buildPath(path, "operation")));
124
+ }
125
+ if (op === "merge" && !step.value) {
126
+ errors.push(createOperationMissingFieldError(op, "value", path));
127
+ }
128
+ if ((op === "replaceAt" || op === "insertAt") && (!step.index || !step.value)) {
129
+ if (!step.index) errors.push(createOperationMissingFieldError(op, "index", path));
130
+ if (!step.value) errors.push(createOperationMissingFieldError(op, "value", path));
131
+ }
132
+ if (op === "splice" && (!step.index || !step.deleteCount)) {
133
+ if (!step.index) errors.push(createOperationMissingFieldError(op, "index", path));
134
+ if (!step.deleteCount) errors.push(createOperationMissingFieldError(op, "deleteCount", path));
135
+ }
136
+ }
98
137
  }
99
138
  if (step.value) {
100
- errors.push(
101
- ...validateExpressionStateOnly(step.value, buildPath(path, "value"), context)
102
- );
139
+ errors.push(...validateExpressionStateOnly(step.value, buildPath(path, "value"), context));
140
+ }
141
+ if (step.index) {
142
+ errors.push(...validateExpressionStateOnly(step.index, buildPath(path, "index"), context));
143
+ }
144
+ if (step.deleteCount) {
145
+ errors.push(...validateExpressionStateOnly(step.deleteCount, buildPath(path, "deleteCount"), context));
103
146
  }
104
147
  break;
148
+ }
105
149
  case "fetch":
106
150
  errors.push(
107
151
  ...validateExpressionStateOnly(step.url, buildPath(path, "url"), context)
@@ -154,6 +198,14 @@ function validateExpressionStateOnly(expr, path, context) {
154
198
  break;
155
199
  case "lit":
156
200
  break;
201
+ case "cond":
202
+ errors.push(...validateExpressionStateOnly(expr.if, buildPath(path, "if"), context));
203
+ errors.push(...validateExpressionStateOnly(expr.then, buildPath(path, "then"), context));
204
+ errors.push(...validateExpressionStateOnly(expr.else, buildPath(path, "else"), context));
205
+ break;
206
+ case "get":
207
+ errors.push(...validateExpressionStateOnly(expr.base, buildPath(path, "base"), context));
208
+ break;
157
209
  }
158
210
  return errors;
159
211
  }
@@ -187,6 +239,22 @@ function validateExpressionInEventPayload(expr, path, context, scope) {
187
239
  break;
188
240
  case "lit":
189
241
  break;
242
+ case "cond":
243
+ errors.push(
244
+ ...validateExpressionInEventPayload(expr.if, buildPath(path, "if"), context, scope)
245
+ );
246
+ errors.push(
247
+ ...validateExpressionInEventPayload(expr.then, buildPath(path, "then"), context, scope)
248
+ );
249
+ errors.push(
250
+ ...validateExpressionInEventPayload(expr.else, buildPath(path, "else"), context, scope)
251
+ );
252
+ break;
253
+ case "get":
254
+ errors.push(
255
+ ...validateExpressionInEventPayload(expr.base, buildPath(path, "base"), context, scope)
256
+ );
257
+ break;
190
258
  }
191
259
  return errors;
192
260
  }
@@ -507,6 +575,19 @@ function transformExpression(expr, ctx) {
507
575
  }
508
576
  return { expr: "lit", value: null };
509
577
  }
578
+ case "cond":
579
+ return {
580
+ expr: "cond",
581
+ if: transformExpression(expr.if, ctx),
582
+ then: transformExpression(expr.then, ctx),
583
+ else: transformExpression(expr.else, ctx)
584
+ };
585
+ case "get":
586
+ return {
587
+ expr: "get",
588
+ base: transformExpression(expr.base, ctx),
589
+ path: expr.path
590
+ };
510
591
  }
511
592
  }
512
593
  function transformEventHandler(handler, ctx) {
@@ -537,6 +618,12 @@ function transformActionStep(step) {
537
618
  if (step.value) {
538
619
  updateStep.value = transformExpression(step.value, emptyContext);
539
620
  }
621
+ if (step.index) {
622
+ updateStep.index = transformExpression(step.index, emptyContext);
623
+ }
624
+ if (step.deleteCount) {
625
+ updateStep.deleteCount = transformExpression(step.deleteCount, emptyContext);
626
+ }
540
627
  return updateStep;
541
628
  }
542
629
  case "fetch": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constela/compiler",
3
- "version": "0.2.0",
3
+ "version": "0.3.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.2.0"
18
+ "@constela/core": "0.3.0"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/node": "^20.10.0",