@mmapp/react-compiler 0.1.0-alpha.1 → 0.1.0-alpha.5
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/ATOM-PIPELINE.md +144 -0
- package/README.md +88 -40
- package/dist/babel/index.js +2814 -277
- package/dist/babel/index.mjs +2 -2
- package/dist/chunk-3USIFFE4.mjs +2190 -0
- package/dist/chunk-45YMGEVT.mjs +186 -0
- package/dist/chunk-4FN2AISW.mjs +148 -0
- package/dist/chunk-4OPI5L7G.mjs +2593 -0
- package/dist/chunk-4RYTKOOJ.mjs +186 -0
- package/dist/chunk-52XHYD2V.mjs +214 -0
- package/dist/chunk-5GUFFFGL.mjs +148 -0
- package/dist/chunk-5RKTOVR5.mjs +244 -0
- package/dist/chunk-5YDMOO4X.mjs +214 -0
- package/dist/chunk-64ZWEMLJ.mjs +148 -0
- package/dist/chunk-6XP4KSWQ.mjs +2190 -0
- package/dist/chunk-72QWL54I.mjs +175 -0
- package/dist/chunk-7B4TRI7C.mjs +4835 -0
- package/dist/chunk-7ZKGHTNB.mjs +4952 -0
- package/dist/chunk-CIESM3BP.mjs +33 -0
- package/dist/chunk-DE3ZGQAC.mjs +148 -0
- package/dist/chunk-DMCY3BBG.mjs +1933 -0
- package/dist/chunk-DPIK3PJS.mjs +244 -0
- package/dist/chunk-E5IVH4RE.mjs +186 -0
- package/dist/chunk-E6FZNUR5.mjs +4953 -0
- package/dist/chunk-EJRBDQDP.mjs +2607 -0
- package/dist/chunk-ELO4TXJL.mjs +186 -0
- package/dist/chunk-EO6SYNCG.mjs +175 -0
- package/dist/chunk-FKRO52XH.mjs +3446 -0
- package/dist/chunk-FL4YAKU6.mjs +4941 -0
- package/dist/chunk-FYT47UBU.mjs +5076 -0
- package/dist/chunk-GCLGPOJZ.mjs +148 -0
- package/dist/chunk-GXB4JOP7.mjs +5072 -0
- package/dist/chunk-HFXOUMTD.mjs +175 -0
- package/dist/chunk-HWIZ47US.mjs +214 -0
- package/dist/chunk-IB7MNPQL.mjs +4953 -0
- package/dist/chunk-ICSIHQCG.mjs +148 -0
- package/dist/chunk-J7JUAHS4.mjs +186 -0
- package/dist/chunk-JLA5VNQ3.mjs +186 -0
- package/dist/chunk-JQLWFCTM.mjs +214 -0
- package/dist/chunk-KFJJCQAL.mjs +148 -0
- package/dist/chunk-KJUIIEQE.mjs +186 -0
- package/dist/chunk-KNWTHRVQ.mjs +175 -0
- package/dist/chunk-KSG4XSZF.mjs +175 -0
- package/dist/chunk-LF5N6DOU.mjs +175 -0
- package/dist/chunk-LJQCM2IM.mjs +214 -0
- package/dist/chunk-NTB7OEX2.mjs +2918 -0
- package/dist/chunk-NW6555WJ.mjs +186 -0
- package/dist/chunk-OMZE6VLQ.mjs +214 -0
- package/dist/chunk-OPJKP747.mjs +7506 -0
- package/dist/chunk-P4BR7WVO.mjs +2190 -0
- package/dist/chunk-QQHVYH2X.mjs +244 -0
- package/dist/chunk-S5QLWLLT.mjs +186 -0
- package/dist/chunk-SCWGT2FY.mjs +2190 -0
- package/dist/chunk-SMKJUSB3.mjs +2190 -0
- package/dist/chunk-THFYE5ZX.mjs +244 -0
- package/dist/chunk-VCAY2KGM.mjs +175 -0
- package/dist/chunk-WBYMW4NQ.mjs +3450 -0
- package/dist/chunk-WECAV6QB.mjs +148 -0
- package/dist/chunk-WMKBXUCE.mjs +3228 -0
- package/dist/chunk-XAJ5BKKL.mjs +4947 -0
- package/dist/chunk-XG2X7AEA.mjs +175 -0
- package/dist/chunk-XG7Z23NQ.mjs +148 -0
- package/dist/chunk-XWZAOCQ7.mjs +2607 -0
- package/dist/chunk-Y6MA7ULW.mjs +148 -0
- package/dist/chunk-YMS7Q7LG.mjs +214 -0
- package/dist/chunk-ZA37XTGA.mjs +175 -0
- package/dist/cli/index.js +13189 -6838
- package/dist/cli/index.mjs +140 -22
- package/dist/codemod/cli.mjs +1 -1
- package/dist/codemod/index.mjs +1 -1
- package/dist/config-PL24KEWL.mjs +219 -0
- package/dist/dev-server-RmGHIntF.d.mts +113 -0
- package/dist/dev-server-RmGHIntF.d.ts +113 -0
- package/dist/dev-server.d.mts +1 -1
- package/dist/dev-server.d.ts +1 -1
- package/dist/dev-server.js +4135 -440
- package/dist/dev-server.mjs +5 -5
- package/dist/envelope.js +2812 -275
- package/dist/envelope.mjs +3 -3
- package/dist/index.d.mts +161 -2
- package/dist/index.d.ts +161 -2
- package/dist/index.js +4429 -428
- package/dist/index.mjs +217 -9
- package/{src/cli/init.ts → dist/init-7JQMAAXS.mjs} +70 -95
- package/dist/init-DQDX3QK6.mjs +369 -0
- package/dist/init-EHO4VQ22.mjs +369 -0
- package/dist/init-UC3FWPIW.mjs +367 -0
- package/dist/init-UNSMVKIK.mjs +366 -0
- package/dist/init-UNV5XIDE.mjs +367 -0
- package/dist/project-compiler-2P4N4DR7.mjs +10 -0
- package/dist/project-compiler-D2LCC27O.mjs +10 -0
- package/dist/project-compiler-EJ3GANJE.mjs +10 -0
- package/dist/project-compiler-LOQKVRZJ.mjs +10 -0
- package/dist/project-compiler-OP2VVGJQ.mjs +10 -0
- package/dist/project-compiler-RQ6OQKRM.mjs +10 -0
- package/dist/project-compiler-VWNNCHGO.mjs +10 -0
- package/dist/project-compiler-XVAAU4C5.mjs +10 -0
- package/dist/project-compiler-YES5FGMD.mjs +10 -0
- package/dist/project-compiler-ZKMQDLGU.mjs +10 -0
- package/dist/project-decompiler-FLXCEJHS.mjs +7 -0
- package/dist/project-decompiler-US7GAVIC.mjs +7 -0
- package/dist/project-decompiler-VLPR22QF.mjs +7 -0
- package/dist/pull-FUS5QYZS.mjs +109 -0
- package/dist/pull-LD5ENLGY.mjs +109 -0
- package/dist/pull-P44LDRWB.mjs +109 -0
- package/dist/testing/index.js +2822 -285
- package/dist/testing/index.mjs +2 -2
- package/dist/verify-SEIXUGN4.mjs +1833 -0
- package/dist/vite/index.js +2815 -278
- package/dist/vite/index.mjs +3 -3
- package/examples/uber-app/app/admin/fleet.tsx +19 -19
- package/package.json +16 -6
- package/compile-blueprint-chat.mjs +0 -99
- package/compile-blueprint-glass-console.mjs +0 -98
- package/compile-chat-defs.mjs +0 -92
- package/examples/uber-app/tests/payment.test.tsx +0 -129
- package/examples/uber-app/tests/ride-flow.test.tsx +0 -123
- package/package.json.backup +0 -86
- package/scripts/decompile.ts +0 -226
- package/scripts/seed-auth.ts +0 -267
- package/scripts/seed-uber.ts +0 -248
- package/scripts/validate-uber.ts +0 -119
- package/seed-blueprint-chat.mjs +0 -444
- package/seed-blueprint-glass-console.mjs +0 -445
- package/seed-compiled.mjs +0 -318
- package/src/RoundTripValidator.ts +0 -400
- package/src/__tests__/atom-rendering-coverage.test.ts +0 -680
- package/src/__tests__/auth-module-compilation.test.ts +0 -247
- package/src/__tests__/auth-template-compilation.test.ts +0 -589
- package/src/__tests__/change-extractor.test.ts +0 -142
- package/src/__tests__/cli-pull.test.ts +0 -73
- package/src/__tests__/cli-test.test.ts +0 -72
- package/src/__tests__/component-extractor.test.ts +0 -331
- package/src/__tests__/context-extractor.test.ts +0 -145
- package/src/__tests__/decompiler.test.ts +0 -718
- package/src/__tests__/define-blueprint.test.ts +0 -133
- package/src/__tests__/definition-validator.test.ts +0 -519
- package/src/__tests__/during-extractor.test.ts +0 -152
- package/src/__tests__/effect-extractor.test.ts +0 -107
- package/src/__tests__/event-emission.test.ts +0 -127
- package/src/__tests__/examples.test.ts +0 -236
- package/src/__tests__/full-blueprint-coverage.test.ts +0 -1221
- package/src/__tests__/golden-suite.test.ts +0 -403
- package/src/__tests__/grammar-island-extractor.test.ts +0 -289
- package/src/__tests__/instance-key.test.ts +0 -82
- package/src/__tests__/ir-migration.test.ts +0 -255
- package/src/__tests__/lock-file.test.ts +0 -117
- package/src/__tests__/model-extractor.test.ts +0 -195
- package/src/__tests__/model-field-acl.test.ts +0 -237
- package/src/__tests__/model-hooks.test.ts +0 -130
- package/src/__tests__/model-ref-resolution.test.ts +0 -268
- package/src/__tests__/model-roundtrip.test.ts +0 -502
- package/src/__tests__/model-runtime.test.ts +0 -112
- package/src/__tests__/model-transitions.test.ts +0 -183
- package/src/__tests__/nrt-action-trace.test.ts +0 -391
- package/src/__tests__/pipeline-hardening.test.ts +0 -413
- package/src/__tests__/project-compiler.test.ts +0 -546
- package/src/__tests__/project-decompiler.test.ts +0 -343
- package/src/__tests__/query-compilation.test.ts +0 -145
- package/src/__tests__/round-trip/PLAN.md +0 -158
- package/src/__tests__/round-trip/README.md +0 -52
- package/src/__tests__/round-trip/RESULTS.md +0 -86
- package/src/__tests__/round-trip/fixtures/data-heavy/main.workflow.tsx +0 -55
- package/src/__tests__/round-trip/fixtures/data-heavy/mm.config.ts +0 -11
- package/src/__tests__/round-trip/fixtures/data-heavy/models/contact.ts +0 -54
- package/src/__tests__/round-trip/fixtures/full-workflow/main.workflow.tsx +0 -79
- package/src/__tests__/round-trip/fixtures/full-workflow/mm.config.ts +0 -12
- package/src/__tests__/round-trip/fixtures/full-workflow/models/order.ts +0 -50
- package/src/__tests__/round-trip/fixtures/simple-crud/main.workflow.tsx +0 -25
- package/src/__tests__/round-trip/fixtures/simple-crud/mm.config.ts +0 -11
- package/src/__tests__/round-trip/fixtures/simple-crud/models/task.ts +0 -32
- package/src/__tests__/round-trip/fixtures/view-heavy/main.workflow.tsx +0 -79
- package/src/__tests__/round-trip/fixtures/view-heavy/mm.config.ts +0 -10
- package/src/__tests__/round-trip/round-trip.test.ts +0 -2598
- package/src/__tests__/round-trip-ir.test.ts +0 -300
- package/src/__tests__/round-trip.test.ts +0 -1212
- package/src/__tests__/route-merging.test.ts +0 -372
- package/src/__tests__/router-composition.test.ts +0 -489
- package/src/__tests__/router-extractor.test.ts +0 -176
- package/src/__tests__/server-action-extractor.test.ts +0 -128
- package/src/__tests__/smart-type-inference.test.ts +0 -365
- package/src/__tests__/source-envelope.test.ts +0 -284
- package/src/__tests__/source-fidelity.test.ts +0 -516
- package/src/__tests__/state-extractor.test.ts +0 -115
- package/src/__tests__/strict-mode.test.ts +0 -227
- package/src/__tests__/transition-effect-extractor.test.ts +0 -119
- package/src/__tests__/transition-extractor.test.ts +0 -68
- package/src/__tests__/ts-to-expression.test.ts +0 -462
- package/src/__tests__/type-generator.test.ts +0 -201
- package/src/__tests__/uber-validation.test.ts +0 -502
- package/src/action-compiler.ts +0 -361
- package/src/babel/emitters/experience-transform.ts +0 -199
- package/src/babel/emitters/ir-to-tsx-emitter.ts +0 -110
- package/src/babel/emitters/pure-form-emitter.ts +0 -1023
- package/src/babel/emitters/runtime-glue-emitter.ts +0 -39
- package/src/babel/extractors/change-extractor.ts +0 -199
- package/src/babel/extractors/component-extractor.ts +0 -907
- package/src/babel/extractors/computed-extractor.ts +0 -262
- package/src/babel/extractors/context-extractor.ts +0 -277
- package/src/babel/extractors/during-extractor.ts +0 -295
- package/src/babel/extractors/effect-extractor.ts +0 -340
- package/src/babel/extractors/event-extractor.ts +0 -235
- package/src/babel/extractors/grammar-island-extractor.ts +0 -302
- package/src/babel/extractors/model-extractor.ts +0 -1018
- package/src/babel/extractors/router-extractor.ts +0 -303
- package/src/babel/extractors/server-action-extractor.ts +0 -173
- package/src/babel/extractors/server-action-hook-extractor.ts +0 -72
- package/src/babel/extractors/server-state-extractor.ts +0 -88
- package/src/babel/extractors/state-extractor.ts +0 -214
- package/src/babel/extractors/transition-effect-extractor.ts +0 -176
- package/src/babel/extractors/transition-extractor.ts +0 -143
- package/src/babel/index.ts +0 -24
- package/src/babel/transpilers/ts-to-expression.ts +0 -674
- package/src/babel/visitor.ts +0 -807
- package/src/cli/auth.ts +0 -255
- package/src/cli/build.ts +0 -288
- package/src/cli/deploy.ts +0 -206
- package/src/cli/index.ts +0 -328
- package/src/cli/installer.ts +0 -261
- package/src/cli/lock-file.ts +0 -94
- package/src/cli/mmrc.ts +0 -22
- package/src/cli/pull.ts +0 -172
- package/src/cli/registry-client.ts +0 -175
- package/src/cli/test.ts +0 -397
- package/src/cli/type-generator.ts +0 -243
- package/src/codemod/__tests__/forward.test.ts +0 -239
- package/src/codemod/__tests__/reverse.test.ts +0 -145
- package/src/codemod/__tests__/round-trip.test.ts +0 -137
- package/src/codemod/annotation.ts +0 -97
- package/src/codemod/classify.ts +0 -197
- package/src/codemod/cli.ts +0 -207
- package/src/codemod/control-flow.ts +0 -409
- package/src/codemod/forward.ts +0 -244
- package/src/codemod/import-manager.ts +0 -171
- package/src/codemod/index.ts +0 -120
- package/src/codemod/reverse.ts +0 -197
- package/src/codemod/rules.ts +0 -174
- package/src/codemod/state-transform.ts +0 -126
- package/src/decompiler/ast-builder.ts +0 -538
- package/src/decompiler/config-generator.ts +0 -151
- package/src/decompiler/index.ts +0 -315
- package/src/decompiler/project-decompiler.ts +0 -1776
- package/src/decompiler/project.ts +0 -862
- package/src/decompiler/split-strategy.ts +0 -140
- package/src/decompiler/state-emitter.ts +0 -1053
- package/src/decompiler/sx-emitter.ts +0 -318
- package/src/decompiler/workspace-hydrator.ts +0 -189
- package/src/dev-server.ts +0 -238
- package/src/envelope/fs-tree.ts +0 -217
- package/src/envelope/source-envelope.ts +0 -264
- package/src/envelope.ts +0 -315
- package/src/incremental-compiler.ts +0 -401
- package/src/index.ts +0 -99
- package/src/model-compiler.ts +0 -277
- package/src/project-compiler.ts +0 -1629
- package/src/route-extractor.ts +0 -333
- package/src/testing/index.ts +0 -32
- package/src/testing/snapshot.ts +0 -252
- package/src/testing/test-utils.ts +0 -226
- package/src/types.ts +0 -68
- package/src/vite/index.ts +0 -288
- package/test-compile.mjs +0 -142
- package/tsconfig.json +0 -25
- package/tsup.config.ts +0 -23
- package/vitest.config.ts +0 -9
package/dist/envelope.js
CHANGED
|
@@ -40,7 +40,7 @@ var import_glob = require("glob");
|
|
|
40
40
|
var import_core = require("@babel/core");
|
|
41
41
|
|
|
42
42
|
// src/babel/visitor.ts
|
|
43
|
-
var
|
|
43
|
+
var t21 = __toESM(require("@babel/types"));
|
|
44
44
|
|
|
45
45
|
// src/babel/extractors/state-extractor.ts
|
|
46
46
|
var t = __toESM(require("@babel/types"));
|
|
@@ -446,25 +446,25 @@ function inferTransitionStates(transitions, states) {
|
|
|
446
446
|
const stateArray = Array.from(states.values());
|
|
447
447
|
const startStates = stateArray.filter((s) => s.type === "START");
|
|
448
448
|
const regularStates = stateArray.filter((s) => s.type === "REGULAR");
|
|
449
|
-
const needsInference = transitions.filter((
|
|
449
|
+
const needsInference = transitions.filter((t22) => t22.from.length === 0 || !t22.to);
|
|
450
450
|
if (needsInference.length === 0) return;
|
|
451
451
|
if (startStates.length === 1 && regularStates.length > 0) {
|
|
452
|
-
needsInference.forEach((
|
|
453
|
-
if (
|
|
454
|
-
|
|
452
|
+
needsInference.forEach((t22, idx) => {
|
|
453
|
+
if (t22.from.length === 0) {
|
|
454
|
+
t22.from = [startStates[0].name];
|
|
455
455
|
}
|
|
456
|
-
if (!
|
|
457
|
-
|
|
456
|
+
if (!t22.to) {
|
|
457
|
+
t22.to = regularStates[idx % regularStates.length]?.name || startStates[0].name;
|
|
458
458
|
}
|
|
459
459
|
});
|
|
460
460
|
} else {
|
|
461
461
|
const allStateNames = stateArray.map((s) => s.name);
|
|
462
|
-
needsInference.forEach((
|
|
463
|
-
if (
|
|
464
|
-
|
|
462
|
+
needsInference.forEach((t22, idx) => {
|
|
463
|
+
if (t22.from.length === 0 && allStateNames.length > 0) {
|
|
464
|
+
t22.from = [allStateNames[0]];
|
|
465
465
|
}
|
|
466
|
-
if (!
|
|
467
|
-
|
|
466
|
+
if (!t22.to && allStateNames.length > 1) {
|
|
467
|
+
t22.to = allStateNames[Math.min(idx + 1, allStateNames.length - 1)];
|
|
468
468
|
}
|
|
469
469
|
});
|
|
470
470
|
}
|
|
@@ -654,6 +654,8 @@ var TranspileContext = class {
|
|
|
654
654
|
this.localFieldMap = options.localFieldMap ?? /* @__PURE__ */ new Map();
|
|
655
655
|
this.derivedVarMap = options.derivedVarMap ?? /* @__PURE__ */ new Map();
|
|
656
656
|
this.setterToFieldMap = options.setterToFieldMap ?? /* @__PURE__ */ new Map();
|
|
657
|
+
this.parameterMap = options.parameterMap ?? /* @__PURE__ */ new Map();
|
|
658
|
+
this.allMutable = options.allMutable ?? false;
|
|
657
659
|
}
|
|
658
660
|
/**
|
|
659
661
|
* Emit an opaque JS fallback, marking the result as impure.
|
|
@@ -675,6 +677,8 @@ var TranspileContext = class {
|
|
|
675
677
|
if (snakeName) return `$local.${snakeName}`;
|
|
676
678
|
const derivedInit = this.derivedVarMap.get(node.name);
|
|
677
679
|
if (derivedInit) return `(${this.visit(derivedInit)})`;
|
|
680
|
+
const paramField = this.parameterMap.get(node.name);
|
|
681
|
+
if (paramField) return paramField;
|
|
678
682
|
if (node.name === "undefined") return "null";
|
|
679
683
|
if (node.name === "NaN") return "null";
|
|
680
684
|
if (node.name === "Infinity") return "null";
|
|
@@ -722,6 +726,9 @@ var TranspileContext = class {
|
|
|
722
726
|
if (t5.isNewExpression(node)) {
|
|
723
727
|
return this.visitNew(node);
|
|
724
728
|
}
|
|
729
|
+
if (t5.isAssignmentExpression(node) && node.operator === "=" && t5.isIdentifier(node.left)) {
|
|
730
|
+
return `${node.left.name} = ${this.visit(node.right)}`;
|
|
731
|
+
}
|
|
725
732
|
return this.opaque(fallbackGenerate(node));
|
|
726
733
|
}
|
|
727
734
|
// ---------------------------------------------------------------------------
|
|
@@ -922,6 +929,11 @@ var TranspileContext = class {
|
|
|
922
929
|
return this.visitArrayHigherOrder("some", obj, args);
|
|
923
930
|
case "every":
|
|
924
931
|
return this.visitArrayHigherOrder("every", obj, args);
|
|
932
|
+
// --- Array push: arr.push(item) → arr = push(arr, item) ---
|
|
933
|
+
case "push": {
|
|
934
|
+
const [item] = this.visitArgsList(args);
|
|
935
|
+
return `${obj} = push(${obj}, ${item})`;
|
|
936
|
+
}
|
|
925
937
|
// --- Array mutation-free methods ---
|
|
926
938
|
case "reverse":
|
|
927
939
|
return `reverse(${obj})`;
|
|
@@ -2757,6 +2769,71 @@ function modelStateTypeToIR(type) {
|
|
|
2757
2769
|
if (type === "final") return "END";
|
|
2758
2770
|
return "REGULAR";
|
|
2759
2771
|
}
|
|
2772
|
+
function parseActionArray(raw, actionCounter) {
|
|
2773
|
+
if (!Array.isArray(raw)) return [];
|
|
2774
|
+
const actions = [];
|
|
2775
|
+
for (const item of raw) {
|
|
2776
|
+
if (typeof item !== "object" || item === null) continue;
|
|
2777
|
+
const a = item;
|
|
2778
|
+
actions.push({
|
|
2779
|
+
id: a.id ? String(a.id) : `auto_${++actionCounter.value}`,
|
|
2780
|
+
type: String(a.type || a.action_type || "unknown"),
|
|
2781
|
+
mode: a.mode || "auto",
|
|
2782
|
+
config: a.config && typeof a.config === "object" ? a.config : {},
|
|
2783
|
+
...a.condition ? { condition: String(a.condition) } : {}
|
|
2784
|
+
});
|
|
2785
|
+
}
|
|
2786
|
+
return actions;
|
|
2787
|
+
}
|
|
2788
|
+
function parseDuringArray(raw, actionCounter) {
|
|
2789
|
+
if (!Array.isArray(raw)) return [];
|
|
2790
|
+
const result = [];
|
|
2791
|
+
for (const item of raw) {
|
|
2792
|
+
if (typeof item !== "object" || item === null) continue;
|
|
2793
|
+
const d = item;
|
|
2794
|
+
result.push({
|
|
2795
|
+
id: d.id ? String(d.id) : `during_${++actionCounter.value}`,
|
|
2796
|
+
type: d.type || "interval",
|
|
2797
|
+
...d.interval_ms != null ? { interval_ms: Number(d.interval_ms) } : {},
|
|
2798
|
+
...d.cron ? { cron: String(d.cron) } : {},
|
|
2799
|
+
...d.delay_ms != null ? { delay_ms: Number(d.delay_ms) } : {},
|
|
2800
|
+
...d.condition ? { condition: String(d.condition) } : {},
|
|
2801
|
+
actions: parseActionArray(d.actions, actionCounter)
|
|
2802
|
+
});
|
|
2803
|
+
}
|
|
2804
|
+
return result;
|
|
2805
|
+
}
|
|
2806
|
+
function parseOnEventArray(raw, actionCounter) {
|
|
2807
|
+
if (!Array.isArray(raw)) return [];
|
|
2808
|
+
const result = [];
|
|
2809
|
+
for (const item of raw) {
|
|
2810
|
+
if (typeof item !== "object" || item === null) continue;
|
|
2811
|
+
const e = item;
|
|
2812
|
+
const actions = [];
|
|
2813
|
+
if (Array.isArray(e.actions)) {
|
|
2814
|
+
for (const a of e.actions) {
|
|
2815
|
+
if (typeof a !== "object" || a === null) continue;
|
|
2816
|
+
const act = a;
|
|
2817
|
+
actions.push({
|
|
2818
|
+
type: act.type || "set_field",
|
|
2819
|
+
...act.field ? { field: String(act.field) } : {},
|
|
2820
|
+
...act.expression ? { expression: String(act.expression) } : {},
|
|
2821
|
+
...act.key ? { key: String(act.key) } : {},
|
|
2822
|
+
...act.message ? { message: String(act.message) } : {},
|
|
2823
|
+
...act.config && typeof act.config === "object" ? { config: act.config } : {},
|
|
2824
|
+
...act.conditions && Array.isArray(act.conditions) ? { conditions: act.conditions.map(String) } : {}
|
|
2825
|
+
});
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
result.push({
|
|
2829
|
+
match: String(e.match || ""),
|
|
2830
|
+
...e.description ? { description: String(e.description) } : {},
|
|
2831
|
+
...e.conditions && Array.isArray(e.conditions) ? { conditions: e.conditions.map(String) } : {},
|
|
2832
|
+
actions
|
|
2833
|
+
});
|
|
2834
|
+
}
|
|
2835
|
+
return result;
|
|
2836
|
+
}
|
|
2760
2837
|
function extractDefineModelCall(programPath, compilerState, actionCounter) {
|
|
2761
2838
|
for (const node of programPath.node.body) {
|
|
2762
2839
|
if (!t11.isExportDefaultDeclaration(node)) continue;
|
|
@@ -2796,17 +2873,29 @@ function extractDefineModelCall(programPath, compilerState, actionCounter) {
|
|
|
2796
2873
|
const statesObj = config.states;
|
|
2797
2874
|
for (const [name, stateConfig] of Object.entries(statesObj)) {
|
|
2798
2875
|
const stateType = modelStateTypeToIR(stateConfig.type);
|
|
2876
|
+
const on_enter = parseActionArray(stateConfig.on_enter, actionCounter);
|
|
2877
|
+
const on_exit = parseActionArray(stateConfig.on_exit, actionCounter);
|
|
2878
|
+
const during = parseDuringArray(stateConfig.during, actionCounter);
|
|
2879
|
+
const on_event = parseOnEventArray(stateConfig.on_event, actionCounter);
|
|
2880
|
+
const stateRuntime = stateConfig.runtime;
|
|
2799
2881
|
if (!compilerState.states.has(name)) {
|
|
2800
2882
|
compilerState.states.set(name, {
|
|
2801
2883
|
name,
|
|
2802
2884
|
type: stateType,
|
|
2803
2885
|
description: stateConfig.description,
|
|
2804
|
-
on_enter
|
|
2805
|
-
during
|
|
2806
|
-
on_exit
|
|
2886
|
+
on_enter,
|
|
2887
|
+
during,
|
|
2888
|
+
on_exit,
|
|
2889
|
+
...on_event.length > 0 ? { on_event } : {},
|
|
2890
|
+
...stateRuntime ? { runtime: stateRuntime } : {}
|
|
2807
2891
|
});
|
|
2808
2892
|
} else {
|
|
2809
|
-
compilerState.states.get(name)
|
|
2893
|
+
const existing = compilerState.states.get(name);
|
|
2894
|
+
existing.type = stateType;
|
|
2895
|
+
if (on_enter.length > 0) existing.on_enter = on_enter;
|
|
2896
|
+
if (on_exit.length > 0) existing.on_exit = on_exit;
|
|
2897
|
+
if (during.length > 0) existing.during = during;
|
|
2898
|
+
if (on_event.length > 0) existing.on_event = on_event;
|
|
2810
2899
|
}
|
|
2811
2900
|
}
|
|
2812
2901
|
}
|
|
@@ -2844,16 +2933,26 @@ function extractDefineModelCall(programPath, compilerState, actionCounter) {
|
|
|
2844
2933
|
if (transConfig.guard) {
|
|
2845
2934
|
conditions.push(parseGuardExpression(String(transConfig.guard)));
|
|
2846
2935
|
}
|
|
2936
|
+
if (transConfig.conditions && Array.isArray(transConfig.conditions)) {
|
|
2937
|
+
for (const cond of transConfig.conditions) {
|
|
2938
|
+
if (typeof cond === "object" && cond !== null) {
|
|
2939
|
+
conditions.push(cond);
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2942
|
+
}
|
|
2943
|
+
const actions = parseActionArray(transConfig.actions, actionCounter);
|
|
2944
|
+
const transRuntime = transConfig.runtime;
|
|
2847
2945
|
compilerState.transitions.push({
|
|
2848
2946
|
name,
|
|
2849
2947
|
from,
|
|
2850
2948
|
to,
|
|
2851
2949
|
description: transConfig.description,
|
|
2852
2950
|
conditions: conditions.length > 0 ? conditions : void 0,
|
|
2853
|
-
actions
|
|
2951
|
+
actions,
|
|
2854
2952
|
roles: transConfig.roles,
|
|
2855
2953
|
auto: transConfig.auto,
|
|
2856
|
-
required_fields: transConfig.required_fields
|
|
2954
|
+
required_fields: transConfig.required_fields,
|
|
2955
|
+
...transRuntime ? { runtime: transRuntime } : {}
|
|
2857
2956
|
});
|
|
2858
2957
|
}
|
|
2859
2958
|
}
|
|
@@ -2870,6 +2969,9 @@ function extractDefineModelCall(programPath, compilerState, actionCounter) {
|
|
|
2870
2969
|
if (config.metadata && typeof config.metadata === "object") {
|
|
2871
2970
|
compilerState.metadata.modelMetadata = config.metadata;
|
|
2872
2971
|
}
|
|
2972
|
+
if (config.orchestration && typeof config.orchestration === "object" && !Array.isArray(config.orchestration)) {
|
|
2973
|
+
compilerState.metadata.orchestration = config.orchestration;
|
|
2974
|
+
}
|
|
2873
2975
|
return true;
|
|
2874
2976
|
}
|
|
2875
2977
|
return false;
|
|
@@ -3044,162 +3146,2018 @@ function extractModelFile(path, state) {
|
|
|
3044
3146
|
}
|
|
3045
3147
|
}
|
|
3046
3148
|
|
|
3047
|
-
// src/babel/extractors/
|
|
3149
|
+
// src/babel/extractors/flow-extractor.ts
|
|
3048
3150
|
var t12 = __toESM(require("@babel/types"));
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3151
|
+
|
|
3152
|
+
// src/babel/extractors/workflow-shorthand.ts
|
|
3153
|
+
function makeState(name, type) {
|
|
3154
|
+
return {
|
|
3155
|
+
name,
|
|
3156
|
+
type,
|
|
3157
|
+
on_enter: [],
|
|
3158
|
+
during: [],
|
|
3159
|
+
on_exit: []
|
|
3160
|
+
};
|
|
3052
3161
|
}
|
|
3053
|
-
function
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3162
|
+
function makeTransition(name, from, to) {
|
|
3163
|
+
return {
|
|
3164
|
+
name,
|
|
3165
|
+
from: [from],
|
|
3166
|
+
to,
|
|
3167
|
+
actions: []
|
|
3168
|
+
};
|
|
3169
|
+
}
|
|
3170
|
+
function dedupeTransitions(ts) {
|
|
3171
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3172
|
+
const out = [];
|
|
3173
|
+
for (const t22 of ts) {
|
|
3174
|
+
const key = `${t22.name}::${t22.from.join(",")}::${t22.to}`;
|
|
3175
|
+
if (!seen.has(key)) {
|
|
3176
|
+
seen.add(key);
|
|
3177
|
+
out.push(t22);
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
return out;
|
|
3181
|
+
}
|
|
3182
|
+
var TOKEN_RE = /(<->)|<-(\w+)-|(<-)|(?:-(\w+)->)|(->)|(\|)|([a-zA-Z_]\w*)/g;
|
|
3183
|
+
function tokenize(line) {
|
|
3184
|
+
const tokens = [];
|
|
3185
|
+
let m;
|
|
3186
|
+
TOKEN_RE.lastIndex = 0;
|
|
3187
|
+
while ((m = TOKEN_RE.exec(line)) !== null) {
|
|
3188
|
+
if (m[1]) {
|
|
3189
|
+
tokens.push({ kind: "arrow", direction: "bidirectional" });
|
|
3190
|
+
} else if (m[2]) {
|
|
3191
|
+
tokens.push({ kind: "arrow", direction: "backward", name: m[2] });
|
|
3192
|
+
} else if (m[3]) {
|
|
3193
|
+
tokens.push({ kind: "arrow", direction: "backward" });
|
|
3194
|
+
} else if (m[4]) {
|
|
3195
|
+
tokens.push({ kind: "arrow", direction: "forward", name: m[4] });
|
|
3196
|
+
} else if (m[5]) {
|
|
3197
|
+
tokens.push({ kind: "arrow", direction: "forward" });
|
|
3198
|
+
} else if (m[6]) {
|
|
3199
|
+
tokens.push({ kind: "branch" });
|
|
3200
|
+
} else if (m[7]) {
|
|
3201
|
+
tokens.push({ kind: "state", name: m[7] });
|
|
3202
|
+
}
|
|
3203
|
+
}
|
|
3204
|
+
return tokens;
|
|
3205
|
+
}
|
|
3206
|
+
function parseTokens(tokens, stateMap, transitions, outgoingCounts) {
|
|
3207
|
+
let lastState = null;
|
|
3208
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
3209
|
+
const tok = tokens[i];
|
|
3210
|
+
if (tok.kind === "state") {
|
|
3211
|
+
stateMap.set(tok.name, stateMap.has(tok.name) ? stateMap.get(tok.name) : true);
|
|
3212
|
+
lastState = tok.name;
|
|
3213
|
+
continue;
|
|
3214
|
+
}
|
|
3215
|
+
if (tok.kind === "branch") {
|
|
3216
|
+
continue;
|
|
3217
|
+
}
|
|
3218
|
+
if (tok.kind === "arrow") {
|
|
3219
|
+
let nextIdx = i + 1;
|
|
3220
|
+
const targets = [];
|
|
3221
|
+
while (nextIdx < tokens.length) {
|
|
3222
|
+
const next = tokens[nextIdx];
|
|
3223
|
+
if (next.kind === "state") {
|
|
3224
|
+
targets.push(next.name);
|
|
3225
|
+
stateMap.set(next.name, stateMap.has(next.name) ? stateMap.get(next.name) : true);
|
|
3226
|
+
nextIdx++;
|
|
3227
|
+
if (nextIdx < tokens.length && tokens[nextIdx].kind === "branch") {
|
|
3228
|
+
nextIdx++;
|
|
3229
|
+
continue;
|
|
3230
|
+
}
|
|
3231
|
+
break;
|
|
3232
|
+
} else {
|
|
3233
|
+
nextIdx++;
|
|
3065
3234
|
}
|
|
3066
3235
|
}
|
|
3067
|
-
if (
|
|
3068
|
-
for (const
|
|
3069
|
-
if (
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3236
|
+
if (lastState && targets.length > 0) {
|
|
3237
|
+
for (const target of targets) {
|
|
3238
|
+
if (tok.direction === "forward" || tok.direction === "bidirectional") {
|
|
3239
|
+
const name = tok.name || `to_${target}`;
|
|
3240
|
+
transitions.push(makeTransition(name, lastState, target));
|
|
3241
|
+
outgoingCounts.set(lastState, (outgoingCounts.get(lastState) || 0) + 1);
|
|
3242
|
+
}
|
|
3243
|
+
if (tok.direction === "backward" || tok.direction === "bidirectional") {
|
|
3244
|
+
const name = tok.name || `to_${lastState}`;
|
|
3245
|
+
transitions.push(makeTransition(name, target, lastState));
|
|
3246
|
+
outgoingCounts.set(target, (outgoingCounts.get(target) || 0) + 1);
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
lastState = targets[targets.length > 1 ? 0 : 0];
|
|
3250
|
+
if (targets.length === 1) {
|
|
3251
|
+
lastState = targets[0];
|
|
3252
|
+
}
|
|
3253
|
+
i = nextIdx - 1;
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3258
|
+
function parseMultiLine(lines) {
|
|
3259
|
+
const allStateNames = [];
|
|
3260
|
+
const allTransitions = [];
|
|
3261
|
+
const stateMap = /* @__PURE__ */ new Map();
|
|
3262
|
+
const outgoingCounts = /* @__PURE__ */ new Map();
|
|
3263
|
+
for (const line of lines) {
|
|
3264
|
+
const trimmed = line.trim();
|
|
3265
|
+
if (!trimmed) continue;
|
|
3266
|
+
const tokens = tokenize(trimmed);
|
|
3267
|
+
const hasStates = tokens.some((t22) => t22.kind === "state");
|
|
3268
|
+
const hasForwardArrows = tokens.some(
|
|
3269
|
+
(t22) => t22.kind === "arrow" && (t22.direction === "forward" || t22.direction === "bidirectional")
|
|
3270
|
+
);
|
|
3271
|
+
if (hasStates && hasForwardArrows) {
|
|
3272
|
+
for (const tok of tokens) {
|
|
3273
|
+
if (tok.kind === "state" && !allStateNames.includes(tok.name)) {
|
|
3274
|
+
allStateNames.push(tok.name);
|
|
3275
|
+
}
|
|
3276
|
+
}
|
|
3277
|
+
parseTokens(tokens, stateMap, allTransitions, outgoingCounts);
|
|
3278
|
+
} else if (!hasStates && tokens.some((t22) => t22.kind === "arrow")) {
|
|
3279
|
+
let arrowIndex = 0;
|
|
3280
|
+
for (const tok of tokens) {
|
|
3281
|
+
if (tok.kind === "arrow") {
|
|
3282
|
+
if (arrowIndex < allStateNames.length - 1) {
|
|
3283
|
+
const left = allStateNames[arrowIndex];
|
|
3284
|
+
const right = allStateNames[arrowIndex + 1];
|
|
3285
|
+
if (tok.direction === "backward" || tok.direction === "bidirectional") {
|
|
3286
|
+
const name = tok.name || `to_${left}`;
|
|
3287
|
+
allTransitions.push(makeTransition(name, right, left));
|
|
3288
|
+
outgoingCounts.set(right, (outgoingCounts.get(right) || 0) + 1);
|
|
3289
|
+
}
|
|
3290
|
+
if (tok.direction === "forward" || tok.direction === "bidirectional") {
|
|
3291
|
+
const name = tok.name || `to_${right}`;
|
|
3292
|
+
allTransitions.push(makeTransition(name, left, right));
|
|
3293
|
+
outgoingCounts.set(left, (outgoingCounts.get(left) || 0) + 1);
|
|
3082
3294
|
}
|
|
3083
|
-
serverActions.push(action);
|
|
3084
3295
|
}
|
|
3296
|
+
arrowIndex++;
|
|
3297
|
+
}
|
|
3298
|
+
}
|
|
3299
|
+
} else if (hasStates) {
|
|
3300
|
+
parseTokens(tokens, stateMap, allTransitions, outgoingCounts);
|
|
3301
|
+
for (const tok of tokens) {
|
|
3302
|
+
if (tok.kind === "state" && !allStateNames.includes(tok.name)) {
|
|
3303
|
+
allStateNames.push(tok.name);
|
|
3085
3304
|
}
|
|
3086
3305
|
}
|
|
3087
3306
|
}
|
|
3088
3307
|
}
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3308
|
+
return { stateNames: allStateNames, transitions: dedupeTransitions(allTransitions) };
|
|
3309
|
+
}
|
|
3310
|
+
function parseArrowSyntax(arrow) {
|
|
3311
|
+
const lines = arrow.split("\n");
|
|
3312
|
+
const { stateNames, transitions } = parseMultiLine(lines);
|
|
3313
|
+
if (stateNames.length === 0) {
|
|
3314
|
+
return { states: [], transitions: [] };
|
|
3315
|
+
}
|
|
3316
|
+
const hasOutgoing = /* @__PURE__ */ new Set();
|
|
3317
|
+
for (const t22 of transitions) {
|
|
3318
|
+
for (const from of t22.from) {
|
|
3319
|
+
hasOutgoing.add(from);
|
|
3320
|
+
}
|
|
3321
|
+
}
|
|
3322
|
+
const states = stateNames.map((name, idx) => {
|
|
3323
|
+
let type = "REGULAR";
|
|
3324
|
+
if (idx === 0) {
|
|
3325
|
+
type = "START";
|
|
3326
|
+
} else if (!hasOutgoing.has(name)) {
|
|
3327
|
+
type = "END";
|
|
3328
|
+
}
|
|
3329
|
+
return makeState(name, type);
|
|
3330
|
+
});
|
|
3331
|
+
return { states, transitions };
|
|
3332
|
+
}
|
|
3333
|
+
function parseFieldRecord(fields) {
|
|
3334
|
+
return Object.entries(fields).map(([name, typeStr]) => {
|
|
3335
|
+
let required = false;
|
|
3336
|
+
let raw = typeStr.trim();
|
|
3337
|
+
if (raw.endsWith("!")) {
|
|
3338
|
+
required = true;
|
|
3339
|
+
raw = raw.slice(0, -1).trim();
|
|
3340
|
+
}
|
|
3341
|
+
let defaultValue;
|
|
3342
|
+
const eqIdx = raw.indexOf("=");
|
|
3343
|
+
let typePart = raw;
|
|
3344
|
+
if (eqIdx !== -1) {
|
|
3345
|
+
typePart = raw.slice(0, eqIdx).trim();
|
|
3346
|
+
const valStr = raw.slice(eqIdx + 1).trim();
|
|
3347
|
+
try {
|
|
3348
|
+
defaultValue = JSON.parse(valStr);
|
|
3349
|
+
} catch {
|
|
3350
|
+
defaultValue = valStr;
|
|
3351
|
+
}
|
|
3352
|
+
}
|
|
3353
|
+
const TYPE_MAP = {
|
|
3354
|
+
string: "text",
|
|
3355
|
+
str: "text",
|
|
3356
|
+
text: "text",
|
|
3357
|
+
number: "number",
|
|
3358
|
+
num: "number",
|
|
3359
|
+
int: "number",
|
|
3360
|
+
integer: "number",
|
|
3361
|
+
float: "number",
|
|
3362
|
+
bool: "boolean",
|
|
3363
|
+
boolean: "boolean",
|
|
3364
|
+
date: "date",
|
|
3365
|
+
datetime: "datetime",
|
|
3366
|
+
email: "email",
|
|
3367
|
+
url: "url",
|
|
3368
|
+
json: "json",
|
|
3369
|
+
object: "json",
|
|
3370
|
+
array: "json",
|
|
3371
|
+
select: "select",
|
|
3372
|
+
enum: "select",
|
|
3373
|
+
file: "file",
|
|
3374
|
+
image: "image",
|
|
3375
|
+
currency: "currency",
|
|
3376
|
+
phone: "phone",
|
|
3377
|
+
address: "address",
|
|
3378
|
+
rich_text: "rich_text",
|
|
3379
|
+
richtext: "rich_text",
|
|
3380
|
+
color: "color",
|
|
3381
|
+
rating: "rating"
|
|
3382
|
+
};
|
|
3383
|
+
const fieldType = TYPE_MAP[typePart.toLowerCase()] || typePart;
|
|
3384
|
+
const field = {
|
|
3385
|
+
name,
|
|
3386
|
+
type: fieldType
|
|
3387
|
+
};
|
|
3388
|
+
if (required) field.required = true;
|
|
3389
|
+
if (defaultValue !== void 0) field.default_value = defaultValue;
|
|
3390
|
+
return field;
|
|
3391
|
+
});
|
|
3392
|
+
}
|
|
3393
|
+
function parseWorkflowShorthand(slug, fieldsOrArrow, arrowString) {
|
|
3394
|
+
let fields = [];
|
|
3395
|
+
let arrow;
|
|
3396
|
+
if (typeof fieldsOrArrow === "string") {
|
|
3397
|
+
arrow = fieldsOrArrow;
|
|
3398
|
+
} else {
|
|
3399
|
+
fields = parseFieldRecord(fieldsOrArrow);
|
|
3400
|
+
arrow = arrowString || "";
|
|
3092
3401
|
}
|
|
3402
|
+
const { states, transitions } = parseArrowSyntax(arrow);
|
|
3403
|
+
return { slug, fields, states, transitions };
|
|
3093
3404
|
}
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3405
|
+
|
|
3406
|
+
// src/babel/extractors/flow-extractor.ts
|
|
3407
|
+
function isImperativeWorkflowFile(path, _filename) {
|
|
3408
|
+
for (const node of path.node.body) {
|
|
3409
|
+
if (t12.isExportDefaultDeclaration(node)) {
|
|
3410
|
+
const decl = node.declaration;
|
|
3411
|
+
if (t12.isFunctionDeclaration(decl) && decl.async && decl.params.length > 0) {
|
|
3412
|
+
const param = decl.params[0];
|
|
3413
|
+
if (t12.isIdentifier(param) && param.typeAnnotation) {
|
|
3414
|
+
return true;
|
|
3415
|
+
}
|
|
3416
|
+
}
|
|
3417
|
+
if (t12.isCallExpression(decl) && t12.isIdentifier(decl.callee) && decl.callee.name === "workflow") {
|
|
3418
|
+
return true;
|
|
3419
|
+
}
|
|
3105
3420
|
}
|
|
3106
3421
|
}
|
|
3107
|
-
return
|
|
3422
|
+
return false;
|
|
3108
3423
|
}
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3424
|
+
var VALIDATION_FNS = /* @__PURE__ */ new Set(["validate", "assert"]);
|
|
3425
|
+
function roleCondition(role) {
|
|
3426
|
+
return { type: "role", field: role, operator: "eq", value: true };
|
|
3427
|
+
}
|
|
3428
|
+
var TS_TYPE_MAP = {
|
|
3429
|
+
Date: "datetime",
|
|
3430
|
+
Record: "json",
|
|
3431
|
+
Map: "json",
|
|
3432
|
+
Set: "json",
|
|
3433
|
+
URL: "url"
|
|
3434
|
+
};
|
|
3435
|
+
var NAME_TYPE_MAP = {
|
|
3436
|
+
email: "email",
|
|
3437
|
+
url: "url",
|
|
3438
|
+
website: "url",
|
|
3439
|
+
phone: "phone"
|
|
3440
|
+
};
|
|
3441
|
+
function resolveType2(annotation) {
|
|
3442
|
+
if (t12.isTSStringKeyword(annotation)) return "text";
|
|
3443
|
+
if (t12.isTSNumberKeyword(annotation)) return "number";
|
|
3444
|
+
if (t12.isTSBooleanKeyword(annotation)) return "boolean";
|
|
3445
|
+
if (t12.isTSTypeReference(annotation) && t12.isIdentifier(annotation.typeName)) {
|
|
3446
|
+
const name = annotation.typeName.name;
|
|
3447
|
+
if (TS_TYPE_MAP[name]) return TS_TYPE_MAP[name];
|
|
3448
|
+
if (name === "Array") return "multi_select";
|
|
3449
|
+
return name.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
|
|
3450
|
+
}
|
|
3451
|
+
if (t12.isTSArrayType(annotation)) return "multi_select";
|
|
3452
|
+
if (t12.isTSUnionType(annotation)) {
|
|
3453
|
+
const allLiterals = annotation.types.every(
|
|
3454
|
+
(t22) => t12.isTSLiteralType(t22) && (t12.isStringLiteral(t22.literal) || t12.isNumericLiteral(t22.literal))
|
|
3455
|
+
);
|
|
3456
|
+
if (allLiterals) return "select";
|
|
3457
|
+
return "text";
|
|
3458
|
+
}
|
|
3459
|
+
if (t12.isTSLiteralType(annotation) && t12.isStringLiteral(annotation.literal)) return "text";
|
|
3460
|
+
if (t12.isTSLiteralType(annotation) && t12.isNumericLiteral(annotation.literal)) return "number";
|
|
3461
|
+
return "text";
|
|
3462
|
+
}
|
|
3463
|
+
function extractUnionOptions2(annotation) {
|
|
3464
|
+
if (!t12.isTSUnionType(annotation)) return void 0;
|
|
3465
|
+
const options = [];
|
|
3466
|
+
for (const member of annotation.types) {
|
|
3467
|
+
if (t12.isTSLiteralType(member) && t12.isStringLiteral(member.literal)) {
|
|
3468
|
+
options.push(member.literal.value);
|
|
3114
3469
|
}
|
|
3115
3470
|
}
|
|
3116
|
-
return void 0;
|
|
3471
|
+
return options.length > 0 ? options : void 0;
|
|
3117
3472
|
}
|
|
3118
|
-
function
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3473
|
+
function extractFieldsFromInterface2(declaration) {
|
|
3474
|
+
const fields = [];
|
|
3475
|
+
for (const member of declaration.body.body) {
|
|
3476
|
+
if (!t12.isTSPropertySignature(member)) continue;
|
|
3477
|
+
if (!t12.isIdentifier(member.key)) continue;
|
|
3478
|
+
const name = member.key.name;
|
|
3479
|
+
const required = !member.optional;
|
|
3480
|
+
const typeAnno = member.typeAnnotation;
|
|
3481
|
+
let fieldType = typeAnno ? resolveType2(typeAnno.typeAnnotation) : "text";
|
|
3482
|
+
if (NAME_TYPE_MAP[name]) fieldType = NAME_TYPE_MAP[name];
|
|
3483
|
+
const field = {
|
|
3484
|
+
name,
|
|
3485
|
+
type: fieldType,
|
|
3486
|
+
label: name.replace(/([A-Z])/g, " $1").replace(/^./, (c) => c.toUpperCase()),
|
|
3487
|
+
required,
|
|
3488
|
+
default_value: getDefaultForType(fieldType)
|
|
3489
|
+
};
|
|
3490
|
+
if (typeAnno) {
|
|
3491
|
+
const options = extractUnionOptions2(typeAnno.typeAnnotation);
|
|
3492
|
+
if (options) {
|
|
3493
|
+
field.validation = { options };
|
|
3126
3494
|
}
|
|
3127
3495
|
}
|
|
3496
|
+
fields.push(field);
|
|
3128
3497
|
}
|
|
3129
|
-
return
|
|
3498
|
+
return fields;
|
|
3130
3499
|
}
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3500
|
+
function getDefaultForType(type) {
|
|
3501
|
+
switch (type) {
|
|
3502
|
+
case "text":
|
|
3503
|
+
case "email":
|
|
3504
|
+
case "url":
|
|
3505
|
+
case "phone":
|
|
3506
|
+
case "select":
|
|
3507
|
+
return "";
|
|
3508
|
+
case "number":
|
|
3509
|
+
case "currency":
|
|
3510
|
+
return 0;
|
|
3511
|
+
case "boolean":
|
|
3512
|
+
return false;
|
|
3513
|
+
case "multi_select":
|
|
3514
|
+
return [];
|
|
3515
|
+
case "json":
|
|
3516
|
+
return {};
|
|
3517
|
+
default:
|
|
3518
|
+
return null;
|
|
3519
|
+
}
|
|
3520
|
+
}
|
|
3521
|
+
function extractNodeValue2(node) {
|
|
3522
|
+
if (t12.isStringLiteral(node)) return node.value;
|
|
3523
|
+
if (t12.isNumericLiteral(node)) return node.value;
|
|
3524
|
+
if (t12.isBooleanLiteral(node)) return node.value;
|
|
3525
|
+
if (t12.isNullLiteral(node)) return null;
|
|
3526
|
+
if (t12.isArrayExpression(node)) {
|
|
3527
|
+
return node.elements.map((el) => {
|
|
3528
|
+
if (!el || t12.isSpreadElement(el)) return null;
|
|
3529
|
+
return extractNodeValue2(el);
|
|
3530
|
+
});
|
|
3531
|
+
}
|
|
3532
|
+
if (t12.isObjectExpression(node)) {
|
|
3533
|
+
const obj = {};
|
|
3534
|
+
for (const prop of node.properties) {
|
|
3535
|
+
if (!t12.isObjectProperty(prop)) continue;
|
|
3536
|
+
const key = t12.isIdentifier(prop.key) ? prop.key.name : t12.isStringLiteral(prop.key) ? prop.key.value : null;
|
|
3537
|
+
if (key) obj[key] = extractNodeValue2(prop.value);
|
|
3149
3538
|
}
|
|
3539
|
+
return obj;
|
|
3150
3540
|
}
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
entry.variableName = parent.node.id.name;
|
|
3541
|
+
if (t12.isTemplateLiteral(node)) {
|
|
3542
|
+
return node.quasis.map((q) => q.value.raw).join("${}");
|
|
3154
3543
|
}
|
|
3155
|
-
if (
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3544
|
+
if (t12.isIdentifier(node)) {
|
|
3545
|
+
if (node.name === "undefined") return void 0;
|
|
3546
|
+
return node.name;
|
|
3547
|
+
}
|
|
3548
|
+
if (t12.isMemberExpression(node)) {
|
|
3549
|
+
return memberExprToString(node);
|
|
3550
|
+
}
|
|
3551
|
+
if (t12.isTSAsExpression(node)) return extractNodeValue2(node.expression);
|
|
3552
|
+
if (t12.isArrowFunctionExpression(node) || t12.isFunctionExpression(node)) {
|
|
3553
|
+
return "[Function]";
|
|
3554
|
+
}
|
|
3555
|
+
return "[Expression]";
|
|
3159
3556
|
}
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
const
|
|
3167
|
-
const
|
|
3168
|
-
const
|
|
3169
|
-
|
|
3170
|
-
|
|
3557
|
+
function memberExprToString(node) {
|
|
3558
|
+
const obj = t12.isIdentifier(node.object) ? node.object.name : t12.isMemberExpression(node.object) ? memberExprToString(node.object) : "[object]";
|
|
3559
|
+
const prop = t12.isIdentifier(node.property) ? node.property.name : t12.isStringLiteral(node.property) ? node.property.value : "[property]";
|
|
3560
|
+
return `${obj}.${prop}`;
|
|
3561
|
+
}
|
|
3562
|
+
function analyzeStateFn(fn, paramName, actionCounter) {
|
|
3563
|
+
const onEnter = [];
|
|
3564
|
+
const validations = [];
|
|
3565
|
+
const conditions = [];
|
|
3566
|
+
const roles = [];
|
|
3567
|
+
const requiredFields = [];
|
|
3568
|
+
const during = [];
|
|
3569
|
+
const onEvent = [];
|
|
3570
|
+
let timeout;
|
|
3571
|
+
let runtime;
|
|
3572
|
+
if (!fn.body || !t12.isBlockStatement(fn.body)) {
|
|
3573
|
+
return { onEnter, validations, conditions, roles, requiredFields, during, onEvent, timeout, runtime };
|
|
3574
|
+
}
|
|
3575
|
+
for (const stmt of fn.body.body) {
|
|
3576
|
+
processStatement(stmt, paramName, actionCounter, {
|
|
3577
|
+
onEnter,
|
|
3578
|
+
validations,
|
|
3579
|
+
conditions,
|
|
3580
|
+
roles,
|
|
3581
|
+
requiredFields,
|
|
3582
|
+
during,
|
|
3583
|
+
onEvent,
|
|
3584
|
+
setTimeout: (t22) => {
|
|
3585
|
+
timeout = t22;
|
|
3586
|
+
},
|
|
3587
|
+
setRuntime: (r) => {
|
|
3588
|
+
runtime = r;
|
|
3589
|
+
}
|
|
3590
|
+
});
|
|
3171
3591
|
}
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3592
|
+
return { onEnter, validations, conditions, roles, requiredFields, during, onEvent, timeout, runtime };
|
|
3593
|
+
}
|
|
3594
|
+
function processStatement(stmt, paramName, actionCounter, ctx) {
|
|
3595
|
+
if (t12.isExpressionStatement(stmt)) {
|
|
3596
|
+
processExpression(stmt.expression, paramName, actionCounter, ctx);
|
|
3597
|
+
return;
|
|
3598
|
+
}
|
|
3599
|
+
if (t12.isIfStatement(stmt)) {
|
|
3600
|
+
const testStr = expressionToIR(stmt.test, paramName);
|
|
3601
|
+
if (t12.isBlockStatement(stmt.consequent)) {
|
|
3602
|
+
for (const inner of stmt.consequent.body) {
|
|
3603
|
+
processStatement(inner, paramName, actionCounter, {
|
|
3604
|
+
...ctx,
|
|
3605
|
+
ifCondition: testStr
|
|
3606
|
+
});
|
|
3177
3607
|
}
|
|
3178
3608
|
}
|
|
3609
|
+
return;
|
|
3179
3610
|
}
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
} else if (t14.isObjectPattern(parent.node.id)) {
|
|
3185
|
-
const props = parent.node.id.properties.filter((p) => t14.isObjectProperty(p) && t14.isIdentifier(p.key)).map((p) => p.key.name);
|
|
3186
|
-
if (props.length > 0) {
|
|
3187
|
-
entry.variableName = props.join(", ");
|
|
3611
|
+
if (t12.isVariableDeclaration(stmt)) {
|
|
3612
|
+
for (const decl of stmt.declarations) {
|
|
3613
|
+
if (decl.init && t12.isAwaitExpression(decl.init)) {
|
|
3614
|
+
processExpression(decl.init, paramName, actionCounter, ctx);
|
|
3188
3615
|
}
|
|
3189
3616
|
}
|
|
3190
3617
|
}
|
|
3191
|
-
if (!compilerState.metadata) compilerState.metadata = {};
|
|
3192
|
-
const meta = compilerState.metadata;
|
|
3193
|
-
if (!meta.serverStateSubscriptions) meta.serverStateSubscriptions = [];
|
|
3194
|
-
meta.serverStateSubscriptions.push(entry);
|
|
3195
|
-
meta.requiresSSE = true;
|
|
3196
3618
|
}
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3619
|
+
function processExpression(expr, paramName, actionCounter, ctx) {
|
|
3620
|
+
if (t12.isAssignmentExpression(expr) && t12.isMemberExpression(expr.left)) {
|
|
3621
|
+
const left = memberExprToString(expr.left);
|
|
3622
|
+
if (left.startsWith(`${paramName}.`)) {
|
|
3623
|
+
const field = left.slice(paramName.length + 1);
|
|
3624
|
+
const valueExpr = expressionToIR(expr.right, paramName);
|
|
3625
|
+
const action = {
|
|
3626
|
+
id: `auto_${++actionCounter.value}`,
|
|
3627
|
+
type: "set_field",
|
|
3628
|
+
mode: "auto",
|
|
3629
|
+
config: { field, expression: valueExpr },
|
|
3630
|
+
...ctx.ifCondition ? { condition: ctx.ifCondition } : {}
|
|
3631
|
+
};
|
|
3632
|
+
ctx.onEnter.push(action);
|
|
3633
|
+
return;
|
|
3634
|
+
}
|
|
3635
|
+
}
|
|
3636
|
+
if (t12.isAssignmentExpression(expr) && expr.operator !== "=" && t12.isMemberExpression(expr.left)) {
|
|
3637
|
+
const left = memberExprToString(expr.left);
|
|
3638
|
+
if (left.startsWith(`${paramName}.`)) {
|
|
3639
|
+
const field = left.slice(paramName.length + 1);
|
|
3640
|
+
const op = expr.operator.replace("=", "");
|
|
3641
|
+
const valueExpr = expressionToIR(expr.right, paramName);
|
|
3642
|
+
const action = {
|
|
3643
|
+
id: `auto_${++actionCounter.value}`,
|
|
3644
|
+
type: "set_field",
|
|
3645
|
+
mode: "auto",
|
|
3646
|
+
config: { field, expression: `state_data.${field} ${op} ${valueExpr}` },
|
|
3647
|
+
...ctx.ifCondition ? { condition: ctx.ifCondition } : {}
|
|
3648
|
+
};
|
|
3649
|
+
ctx.onEnter.push(action);
|
|
3650
|
+
return;
|
|
3651
|
+
}
|
|
3652
|
+
}
|
|
3653
|
+
if (t12.isCallExpression(expr) || t12.isAwaitExpression(expr) && t12.isCallExpression(expr.argument)) {
|
|
3654
|
+
const call = t12.isAwaitExpression(expr) ? expr.argument : expr;
|
|
3655
|
+
const fnName = t12.isIdentifier(call.callee) ? call.callee.name : t12.isMemberExpression(call.callee) && t12.isIdentifier(call.callee.property) ? call.callee.property.name : null;
|
|
3656
|
+
if (!fnName) return;
|
|
3657
|
+
if (VALIDATION_FNS.has(fnName)) {
|
|
3658
|
+
extractValidation(call, paramName, ctx);
|
|
3659
|
+
return;
|
|
3660
|
+
}
|
|
3661
|
+
if (fnName === "log") {
|
|
3662
|
+
const event = call.arguments[0] ? extractNodeValue2(call.arguments[0]) : "";
|
|
3663
|
+
const data = call.arguments[1] ? extractNodeValue2(call.arguments[1]) : void 0;
|
|
3664
|
+
ctx.onEnter.push({
|
|
3665
|
+
id: `auto_${++actionCounter.value}`,
|
|
3666
|
+
type: "log_event",
|
|
3667
|
+
mode: "auto",
|
|
3668
|
+
config: { event: String(event), ...data ? { data } : {} },
|
|
3669
|
+
...ctx.ifCondition ? { condition: ctx.ifCondition } : {}
|
|
3670
|
+
});
|
|
3671
|
+
return;
|
|
3672
|
+
}
|
|
3673
|
+
if (fnName === "notify") {
|
|
3674
|
+
const to = call.arguments[0] ? expressionToIR(call.arguments[0], paramName) : "";
|
|
3675
|
+
const message = call.arguments[1] ? extractNodeValue2(call.arguments[1]) : "";
|
|
3676
|
+
const opts = call.arguments[2] ? extractNodeValue2(call.arguments[2]) : {};
|
|
3677
|
+
ctx.onEnter.push({
|
|
3678
|
+
id: `auto_${++actionCounter.value}`,
|
|
3679
|
+
type: "send_notification",
|
|
3680
|
+
mode: "auto",
|
|
3681
|
+
config: {
|
|
3682
|
+
to: String(to),
|
|
3683
|
+
message: String(message),
|
|
3684
|
+
...opts
|
|
3685
|
+
},
|
|
3686
|
+
...ctx.ifCondition ? { condition: ctx.ifCondition } : {}
|
|
3687
|
+
});
|
|
3688
|
+
return;
|
|
3689
|
+
}
|
|
3690
|
+
if (fnName === "emit") {
|
|
3691
|
+
const event = call.arguments[0] ? extractNodeValue2(call.arguments[0]) : "";
|
|
3692
|
+
const payload = call.arguments[1] ? extractNodeValue2(call.arguments[1]) : void 0;
|
|
3693
|
+
ctx.onEnter.push({
|
|
3694
|
+
id: `auto_${++actionCounter.value}`,
|
|
3695
|
+
type: "emit_event",
|
|
3696
|
+
mode: "auto",
|
|
3697
|
+
config: { event: String(event), ...payload ? { payload } : {} },
|
|
3698
|
+
...ctx.ifCondition ? { condition: ctx.ifCondition } : {}
|
|
3699
|
+
});
|
|
3700
|
+
return;
|
|
3701
|
+
}
|
|
3702
|
+
if (fnName === "requireRole") {
|
|
3703
|
+
for (const arg of call.arguments) {
|
|
3704
|
+
if (t12.isStringLiteral(arg)) ctx.roles.push(arg.value);
|
|
3705
|
+
}
|
|
3706
|
+
return;
|
|
3707
|
+
}
|
|
3708
|
+
if (fnName === "requireField") {
|
|
3709
|
+
for (const arg of call.arguments) {
|
|
3710
|
+
if (t12.isStringLiteral(arg)) ctx.requiredFields.push(arg.value);
|
|
3711
|
+
}
|
|
3712
|
+
return;
|
|
3713
|
+
}
|
|
3714
|
+
if (fnName === "runtime") {
|
|
3715
|
+
if (call.arguments[0] && t12.isStringLiteral(call.arguments[0])) {
|
|
3716
|
+
ctx.setRuntime(call.arguments[0].value);
|
|
3717
|
+
}
|
|
3718
|
+
return;
|
|
3719
|
+
}
|
|
3720
|
+
if (fnName === "guard") {
|
|
3721
|
+
if (call.arguments[0] && t12.isStringLiteral(call.arguments[0])) {
|
|
3722
|
+
ctx.conditions.push({ expression: call.arguments[0].value });
|
|
3723
|
+
}
|
|
3724
|
+
return;
|
|
3725
|
+
}
|
|
3726
|
+
if (fnName === "every") {
|
|
3727
|
+
const interval = call.arguments[0] && t12.isStringLiteral(call.arguments[0]) ? call.arguments[0].value : "1h";
|
|
3728
|
+
const intervalMs = parseDuration(interval);
|
|
3729
|
+
const opts = call.arguments[1] ? extractNodeValue2(call.arguments[1]) : {};
|
|
3730
|
+
const duringAction = {
|
|
3731
|
+
id: `during_${++actionCounter.value}`,
|
|
3732
|
+
type: "interval",
|
|
3733
|
+
interval_ms: intervalMs,
|
|
3734
|
+
...typeof opts === "object" && opts !== null && opts.when ? { condition: opts.when } : {},
|
|
3735
|
+
actions: []
|
|
3736
|
+
// Placeholder — body analysis would extract inner actions
|
|
3737
|
+
};
|
|
3738
|
+
ctx.during.push(duringAction);
|
|
3739
|
+
return;
|
|
3740
|
+
}
|
|
3741
|
+
if (fnName === "cron") {
|
|
3742
|
+
const cronExpr = call.arguments[0] && t12.isStringLiteral(call.arguments[0]) ? call.arguments[0].value : "* * * * *";
|
|
3743
|
+
ctx.during.push({
|
|
3744
|
+
id: `during_${++actionCounter.value}`,
|
|
3745
|
+
type: "cron",
|
|
3746
|
+
cron: cronExpr,
|
|
3747
|
+
actions: []
|
|
3748
|
+
});
|
|
3749
|
+
return;
|
|
3750
|
+
}
|
|
3751
|
+
if (fnName === "after") {
|
|
3752
|
+
const delay = call.arguments[0] && t12.isStringLiteral(call.arguments[0]) ? call.arguments[0].value : "1h";
|
|
3753
|
+
ctx.during.push({
|
|
3754
|
+
id: `during_${++actionCounter.value}`,
|
|
3755
|
+
type: "timeout",
|
|
3756
|
+
delay_ms: parseDuration(delay),
|
|
3757
|
+
actions: []
|
|
3758
|
+
});
|
|
3759
|
+
return;
|
|
3760
|
+
}
|
|
3761
|
+
if (fnName === "on" && !t12.isAwaitExpression(expr)) {
|
|
3762
|
+
const pattern = call.arguments[0] && t12.isStringLiteral(call.arguments[0]) ? call.arguments[0].value : "*";
|
|
3763
|
+
const opts = call.arguments[1] ? extractNodeValue2(call.arguments[1]) : {};
|
|
3764
|
+
const optsObj = typeof opts === "object" && opts !== null ? opts : {};
|
|
3765
|
+
ctx.onEvent.push({
|
|
3766
|
+
match: pattern,
|
|
3767
|
+
...optsObj.when ? { conditions: [String(optsObj.when)] } : {},
|
|
3768
|
+
actions: []
|
|
3769
|
+
});
|
|
3770
|
+
return;
|
|
3771
|
+
}
|
|
3772
|
+
if (fnName === "timeout") {
|
|
3773
|
+
const duration = call.arguments[0] && t12.isStringLiteral(call.arguments[0]) ? call.arguments[0].value : "1h";
|
|
3774
|
+
const opts = call.arguments[1] ? extractNodeValue2(call.arguments[1]) : {};
|
|
3775
|
+
const optsObj = typeof opts === "object" && opts !== null ? opts : {};
|
|
3776
|
+
ctx.setTimeout({
|
|
3777
|
+
duration,
|
|
3778
|
+
fallback: {
|
|
3779
|
+
...optsObj.transition ? { transition: String(optsObj.transition) } : {},
|
|
3780
|
+
...optsObj.action ? { action: String(optsObj.action) } : {}
|
|
3781
|
+
}
|
|
3782
|
+
});
|
|
3783
|
+
return;
|
|
3784
|
+
}
|
|
3785
|
+
if (fnName === "restrict") {
|
|
3786
|
+
return;
|
|
3787
|
+
}
|
|
3788
|
+
}
|
|
3789
|
+
}
|
|
3790
|
+
function extractValidation(call, paramName, ctx) {
|
|
3791
|
+
const condArg = call.arguments[0];
|
|
3792
|
+
const msgArg = call.arguments[1];
|
|
3793
|
+
const sevArg = call.arguments[2];
|
|
3794
|
+
const message = msgArg && t12.isStringLiteral(msgArg) ? msgArg.value : "Validation failed";
|
|
3795
|
+
const severity = sevArg && t12.isStringLiteral(sevArg) && sevArg.value === "warning" ? "warning" : "error";
|
|
3796
|
+
if (!condArg) return;
|
|
3797
|
+
const field = extractFieldFromCondition(condArg, paramName);
|
|
3798
|
+
const exprStr = expressionToIR(condArg, paramName);
|
|
3799
|
+
if (field) {
|
|
3800
|
+
const validation = {};
|
|
3801
|
+
if (t12.isBinaryExpression(condArg) && (condArg.operator === ">" || condArg.operator === ">=")) {
|
|
3802
|
+
if (isLengthAccess(condArg.left, paramName, field) && t12.isNumericLiteral(condArg.right)) {
|
|
3803
|
+
validation.minLength = condArg.right.value + (condArg.operator === ">" ? 1 : 0);
|
|
3804
|
+
} else if (isFieldAccess(condArg.left, paramName, field) && t12.isNumericLiteral(condArg.right)) {
|
|
3805
|
+
validation.min = condArg.right.value + (condArg.operator === ">" ? 1e-3 : 0);
|
|
3806
|
+
}
|
|
3807
|
+
}
|
|
3808
|
+
if (t12.isBinaryExpression(condArg) && (condArg.operator === "<" || condArg.operator === "<=")) {
|
|
3809
|
+
if (isFieldAccess(condArg.left, paramName, field) && t12.isNumericLiteral(condArg.right)) {
|
|
3810
|
+
validation.max = condArg.right.value;
|
|
3811
|
+
}
|
|
3812
|
+
}
|
|
3813
|
+
if (t12.isCallExpression(condArg) && t12.isMemberExpression(condArg.callee) && t12.isRegExpLiteral(condArg.callee.object) && t12.isIdentifier(condArg.callee.property) && condArg.callee.property.name === "test") {
|
|
3814
|
+
if (!validation.rules) validation.rules = [];
|
|
3815
|
+
validation.rules.push({
|
|
3816
|
+
expression: `MATCHES(value, "${condArg.callee.object.pattern}")`,
|
|
3817
|
+
message: "",
|
|
3818
|
+
// Will be set from the validate() message arg
|
|
3819
|
+
severity: "error"
|
|
3820
|
+
});
|
|
3821
|
+
}
|
|
3822
|
+
ctx.validations.push({ field, validation, message, severity });
|
|
3823
|
+
} else {
|
|
3824
|
+
ctx.validations.push({
|
|
3825
|
+
field: "__cross__",
|
|
3826
|
+
validation: { rules: [{ expression: exprStr, message, severity }] },
|
|
3827
|
+
message,
|
|
3828
|
+
severity
|
|
3829
|
+
});
|
|
3830
|
+
}
|
|
3831
|
+
}
|
|
3832
|
+
function extractFieldFromCondition(node, paramName) {
|
|
3833
|
+
if (t12.isMemberExpression(node)) {
|
|
3834
|
+
const str = memberExprToString(node);
|
|
3835
|
+
if (str.startsWith(`${paramName}.`)) {
|
|
3836
|
+
const parts = str.slice(paramName.length + 1).split(".");
|
|
3837
|
+
return parts[0];
|
|
3838
|
+
}
|
|
3839
|
+
}
|
|
3840
|
+
if (t12.isBinaryExpression(node)) {
|
|
3841
|
+
return extractFieldFromCondition(node.left, paramName) || extractFieldFromCondition(node.right, paramName);
|
|
3842
|
+
}
|
|
3843
|
+
if (t12.isCallExpression(node) && t12.isMemberExpression(node.callee)) {
|
|
3844
|
+
return extractFieldFromCondition(node.callee.object, paramName);
|
|
3845
|
+
}
|
|
3846
|
+
if (t12.isCallExpression(node) && t12.isMemberExpression(node.callee) && t12.isRegExpLiteral(node.callee.object) && node.arguments[0]) {
|
|
3847
|
+
return extractFieldFromCondition(node.arguments[0], paramName);
|
|
3848
|
+
}
|
|
3849
|
+
if (t12.isLogicalExpression(node)) {
|
|
3850
|
+
return extractFieldFromCondition(node.left, paramName) || extractFieldFromCondition(node.right, paramName);
|
|
3851
|
+
}
|
|
3852
|
+
if (t12.isUnaryExpression(node)) {
|
|
3853
|
+
return extractFieldFromCondition(node.argument, paramName);
|
|
3854
|
+
}
|
|
3855
|
+
return null;
|
|
3856
|
+
}
|
|
3857
|
+
function isLengthAccess(node, paramName, field) {
|
|
3858
|
+
if (!t12.isMemberExpression(node)) return false;
|
|
3859
|
+
const str = memberExprToString(node);
|
|
3860
|
+
return str === `${paramName}.${field}.length`;
|
|
3861
|
+
}
|
|
3862
|
+
function isFieldAccess(node, paramName, field) {
|
|
3863
|
+
if (!t12.isMemberExpression(node)) return false;
|
|
3864
|
+
const str = memberExprToString(node);
|
|
3865
|
+
return str === `${paramName}.${field}`;
|
|
3866
|
+
}
|
|
3867
|
+
function expressionToIR(node, paramName) {
|
|
3868
|
+
if (t12.isStringLiteral(node)) return `"${node.value}"`;
|
|
3869
|
+
if (t12.isNumericLiteral(node)) return String(node.value);
|
|
3870
|
+
if (t12.isBooleanLiteral(node)) return String(node.value);
|
|
3871
|
+
if (t12.isNullLiteral(node)) return "null";
|
|
3872
|
+
if (t12.isIdentifier(node)) {
|
|
3873
|
+
if (node.name === paramName) return "state_data";
|
|
3874
|
+
if (node.name === "actor") return "context";
|
|
3875
|
+
if (node.name === "instance") return "instance";
|
|
3876
|
+
return node.name;
|
|
3877
|
+
}
|
|
3878
|
+
if (t12.isMemberExpression(node)) {
|
|
3879
|
+
const str = memberExprToString(node);
|
|
3880
|
+
if (str.startsWith(`${paramName}.`)) return "state_data." + str.slice(paramName.length + 1);
|
|
3881
|
+
if (str.startsWith("actor.")) return "context." + str.slice(6);
|
|
3882
|
+
if (str.startsWith("Date.")) {
|
|
3883
|
+
if (str === "Date.now") return "NOW()";
|
|
3884
|
+
}
|
|
3885
|
+
return str;
|
|
3886
|
+
}
|
|
3887
|
+
if (t12.isCallExpression(node)) {
|
|
3888
|
+
if (t12.isMemberExpression(node.callee) && t12.isIdentifier(node.callee.property)) {
|
|
3889
|
+
const obj = expressionToIR(node.callee.object, paramName);
|
|
3890
|
+
const method = node.callee.property.name;
|
|
3891
|
+
if (method === "now" && obj === "Date") return "NOW()";
|
|
3892
|
+
if (method === "includes") {
|
|
3893
|
+
const arg = node.arguments[0] ? expressionToIR(node.arguments[0], paramName) : "";
|
|
3894
|
+
return `CONTAINS(${obj}, ${arg})`;
|
|
3895
|
+
}
|
|
3896
|
+
if (method === "length") return `LEN(${obj})`;
|
|
3897
|
+
}
|
|
3898
|
+
if (t12.isIdentifier(node.callee) && node.callee.name === "Date") {
|
|
3899
|
+
if (t12.isMemberExpression(node) && t12.isIdentifier(node.property) && node.property.name === "now") {
|
|
3900
|
+
return "NOW()";
|
|
3901
|
+
}
|
|
3902
|
+
}
|
|
3903
|
+
return "[call]";
|
|
3904
|
+
}
|
|
3905
|
+
if (t12.isBinaryExpression(node)) {
|
|
3906
|
+
const left = expressionToIR(node.left, paramName);
|
|
3907
|
+
const right = expressionToIR(node.right, paramName);
|
|
3908
|
+
return `${left} ${node.operator} ${right}`;
|
|
3909
|
+
}
|
|
3910
|
+
if (t12.isLogicalExpression(node)) {
|
|
3911
|
+
const left = expressionToIR(node.left, paramName);
|
|
3912
|
+
const right = expressionToIR(node.right, paramName);
|
|
3913
|
+
const op = node.operator === "&&" ? "AND" : node.operator === "||" ? "OR" : node.operator;
|
|
3914
|
+
return `${left} ${op} ${right}`;
|
|
3915
|
+
}
|
|
3916
|
+
if (t12.isUnaryExpression(node)) {
|
|
3917
|
+
if (node.operator === "!") return `NOT(${expressionToIR(node.argument, paramName)})`;
|
|
3918
|
+
return `${node.operator}${expressionToIR(node.argument, paramName)}`;
|
|
3919
|
+
}
|
|
3920
|
+
if (t12.isConditionalExpression(node)) {
|
|
3921
|
+
return `IF(${expressionToIR(node.test, paramName)}, ${expressionToIR(node.consequent, paramName)}, ${expressionToIR(node.alternate, paramName)})`;
|
|
3922
|
+
}
|
|
3923
|
+
if (t12.isTemplateLiteral(node)) {
|
|
3924
|
+
const parts = [];
|
|
3925
|
+
for (let i = 0; i < node.quasis.length; i++) {
|
|
3926
|
+
parts.push(node.quasis[i].value.raw);
|
|
3927
|
+
if (i < node.expressions.length) {
|
|
3928
|
+
parts.push(`{{ ${expressionToIR(node.expressions[i], paramName)} }}`);
|
|
3929
|
+
}
|
|
3930
|
+
}
|
|
3931
|
+
return `"${parts.join("")}"`;
|
|
3932
|
+
}
|
|
3933
|
+
if (t12.isRegExpLiteral(node)) return node.pattern;
|
|
3934
|
+
return "[expr]";
|
|
3935
|
+
}
|
|
3936
|
+
function extractCallSequence(body, paramName, localFnNames, importedFns) {
|
|
3937
|
+
const calls = [];
|
|
3938
|
+
for (const stmt of body.body) {
|
|
3939
|
+
extractCallsFromStatement(stmt, paramName, localFnNames, importedFns, calls);
|
|
3940
|
+
}
|
|
3941
|
+
return calls;
|
|
3942
|
+
}
|
|
3943
|
+
function extractCallsFromStatement(stmt, paramName, localFnNames, importedFns, calls, condition) {
|
|
3944
|
+
if (t12.isExpressionStatement(stmt)) {
|
|
3945
|
+
const expr = stmt.expression;
|
|
3946
|
+
if (t12.isAwaitExpression(expr)) {
|
|
3947
|
+
const call = extractWorkflowCall(expr.argument, paramName, localFnNames, importedFns);
|
|
3948
|
+
if (call) {
|
|
3949
|
+
if (condition) call.condition = condition;
|
|
3950
|
+
calls.push(call);
|
|
3951
|
+
}
|
|
3952
|
+
}
|
|
3953
|
+
if (t12.isCallExpression(expr) && t12.isIdentifier(expr.callee) && expr.callee.name === "allowTransition") {
|
|
3954
|
+
}
|
|
3955
|
+
}
|
|
3956
|
+
if (t12.isVariableDeclaration(stmt)) {
|
|
3957
|
+
for (const decl of stmt.declarations) {
|
|
3958
|
+
if (decl.init && t12.isAwaitExpression(decl.init)) {
|
|
3959
|
+
const call = extractWorkflowCall(decl.init.argument, paramName, localFnNames, importedFns);
|
|
3960
|
+
if (call) {
|
|
3961
|
+
if (condition) call.condition = condition;
|
|
3962
|
+
calls.push(call);
|
|
3963
|
+
}
|
|
3964
|
+
}
|
|
3965
|
+
}
|
|
3966
|
+
}
|
|
3967
|
+
if (t12.isIfStatement(stmt)) {
|
|
3968
|
+
const condStr = expressionToIR(stmt.test, paramName);
|
|
3969
|
+
if (t12.isBlockStatement(stmt.consequent)) {
|
|
3970
|
+
for (const inner of stmt.consequent.body) {
|
|
3971
|
+
extractCallsFromStatement(inner, paramName, localFnNames, importedFns, calls, condStr);
|
|
3972
|
+
}
|
|
3973
|
+
}
|
|
3974
|
+
if (stmt.alternate) {
|
|
3975
|
+
const negCond = `NOT(${condStr})`;
|
|
3976
|
+
if (t12.isBlockStatement(stmt.alternate)) {
|
|
3977
|
+
for (const inner of stmt.alternate.body) {
|
|
3978
|
+
extractCallsFromStatement(inner, paramName, localFnNames, importedFns, calls, negCond);
|
|
3979
|
+
}
|
|
3980
|
+
} else if (t12.isIfStatement(stmt.alternate)) {
|
|
3981
|
+
extractCallsFromStatement(stmt.alternate, paramName, localFnNames, importedFns, calls);
|
|
3982
|
+
}
|
|
3983
|
+
}
|
|
3984
|
+
}
|
|
3985
|
+
if (t12.isTryStatement(stmt)) {
|
|
3986
|
+
const tryBlockCalls = [];
|
|
3987
|
+
if (stmt.block) {
|
|
3988
|
+
for (const inner of stmt.block.body) {
|
|
3989
|
+
extractCallsFromStatement(inner, paramName, localFnNames, importedFns, tryBlockCalls, condition);
|
|
3990
|
+
}
|
|
3991
|
+
}
|
|
3992
|
+
calls.push(...tryBlockCalls);
|
|
3993
|
+
if (stmt.handler && stmt.handler.body) {
|
|
3994
|
+
const catchBody = stmt.handler.body;
|
|
3995
|
+
const compensationActions = [];
|
|
3996
|
+
const catchParamName = stmt.handler.param && t12.isIdentifier(stmt.handler.param) ? stmt.handler.param.name : "error";
|
|
3997
|
+
const hasReturn = catchBody.body.some((s) => t12.isReturnStatement(s));
|
|
3998
|
+
for (const inner of catchBody.body) {
|
|
3999
|
+
if (t12.isReturnStatement(inner)) continue;
|
|
4000
|
+
extractCallsFromStatement(inner, paramName, localFnNames, importedFns, compensationActions, condition);
|
|
4001
|
+
}
|
|
4002
|
+
calls.push({
|
|
4003
|
+
type: "stateCall",
|
|
4004
|
+
name: `__compensation_${calls.length}`,
|
|
4005
|
+
options: {
|
|
4006
|
+
__isCompensation: true,
|
|
4007
|
+
__tryBlockCallNames: tryBlockCalls.map((c) => c.name),
|
|
4008
|
+
__compensationCalls: compensationActions,
|
|
4009
|
+
__hasReturn: hasReturn,
|
|
4010
|
+
__catchParam: catchParamName,
|
|
4011
|
+
__catchBody: catchBody
|
|
4012
|
+
}
|
|
4013
|
+
});
|
|
4014
|
+
}
|
|
4015
|
+
}
|
|
4016
|
+
if (t12.isSwitchStatement(stmt)) {
|
|
4017
|
+
}
|
|
4018
|
+
}
|
|
4019
|
+
function extractWorkflowCall(node, paramName, localFnNames, importedFns) {
|
|
4020
|
+
if (t12.isCallExpression(node)) {
|
|
4021
|
+
const callee = node.callee;
|
|
4022
|
+
if (t12.isIdentifier(callee) && callee.name === "named" && node.arguments.length >= 2) {
|
|
4023
|
+
const name = t12.isStringLiteral(node.arguments[0]) ? node.arguments[0].value : "";
|
|
4024
|
+
const inner = node.arguments[1];
|
|
4025
|
+
if (t12.isCallExpression(inner) || t12.isAwaitExpression(inner)) {
|
|
4026
|
+
const innerNode = t12.isAwaitExpression(inner) ? inner.argument : inner;
|
|
4027
|
+
const innerCall = extractWorkflowCall(innerNode, paramName, localFnNames, importedFns);
|
|
4028
|
+
if (innerCall) {
|
|
4029
|
+
innerCall.transitionName = name;
|
|
4030
|
+
return innerCall;
|
|
4031
|
+
}
|
|
4032
|
+
}
|
|
4033
|
+
return null;
|
|
4034
|
+
}
|
|
4035
|
+
if (t12.isIdentifier(callee) && callee.name === "userAction") {
|
|
4036
|
+
const name = node.arguments[0] && t12.isStringLiteral(node.arguments[0]) ? node.arguments[0].value : "action";
|
|
4037
|
+
const opts = node.arguments[1] ? extractNodeValue2(node.arguments[1]) : {};
|
|
4038
|
+
return { type: "userAction", name, options: opts };
|
|
4039
|
+
}
|
|
4040
|
+
if (t12.isIdentifier(callee) && callee.name === "userChoice") {
|
|
4041
|
+
const choices = node.arguments[0] ? extractNodeValue2(node.arguments[0]) : {};
|
|
4042
|
+
return { type: "userChoice", name: "choice", choices };
|
|
4043
|
+
}
|
|
4044
|
+
if (t12.isIdentifier(callee) && callee.name === "delay") {
|
|
4045
|
+
const duration = node.arguments[0] && t12.isStringLiteral(node.arguments[0]) ? node.arguments[0].value : "0";
|
|
4046
|
+
return { type: "delay", name: `delay_${duration}` };
|
|
4047
|
+
}
|
|
4048
|
+
if (t12.isIdentifier(callee) && callee.name === "on") {
|
|
4049
|
+
const pattern = node.arguments[0] && t12.isStringLiteral(node.arguments[0]) ? node.arguments[0].value : "*";
|
|
4050
|
+
const opts = node.arguments[1] ? extractNodeValue2(node.arguments[1]) : {};
|
|
4051
|
+
opts.__eventPattern = pattern;
|
|
4052
|
+
return { type: "awaitOn", name: pattern.replace(/[^a-zA-Z0-9]/g, "_"), options: opts };
|
|
4053
|
+
}
|
|
4054
|
+
if (t12.isMemberExpression(callee) && t12.isIdentifier(callee.object) && callee.object.name === "Promise" && t12.isIdentifier(callee.property)) {
|
|
4055
|
+
if (callee.property.name === "all" && node.arguments[0] && t12.isArrayExpression(node.arguments[0])) {
|
|
4056
|
+
const parallelCalls = [];
|
|
4057
|
+
for (const el of node.arguments[0].elements) {
|
|
4058
|
+
if (!el || t12.isSpreadElement(el)) continue;
|
|
4059
|
+
const innerNode = t12.isAwaitExpression(el) ? el.argument : el;
|
|
4060
|
+
const c = extractWorkflowCall(innerNode, paramName, localFnNames, importedFns);
|
|
4061
|
+
if (c) parallelCalls.push(c);
|
|
4062
|
+
}
|
|
4063
|
+
return { type: "promiseAll", name: "parallel", parallelCalls };
|
|
4064
|
+
}
|
|
4065
|
+
if (callee.property.name === "race" && node.arguments[0] && t12.isArrayExpression(node.arguments[0])) {
|
|
4066
|
+
const parallelCalls = [];
|
|
4067
|
+
for (const el of node.arguments[0].elements) {
|
|
4068
|
+
if (!el || t12.isSpreadElement(el)) continue;
|
|
4069
|
+
const innerNode = t12.isAwaitExpression(el) ? el.argument : el;
|
|
4070
|
+
const c = extractWorkflowCall(innerNode, paramName, localFnNames, importedFns);
|
|
4071
|
+
if (c) parallelCalls.push(c);
|
|
4072
|
+
}
|
|
4073
|
+
return { type: "promiseRace", name: "race", parallelCalls };
|
|
4074
|
+
}
|
|
4075
|
+
}
|
|
4076
|
+
if (t12.isIdentifier(callee) && localFnNames.has(callee.name)) {
|
|
4077
|
+
return { type: "stateCall", name: callee.name };
|
|
4078
|
+
}
|
|
4079
|
+
if (t12.isIdentifier(callee) && importedFns.has(callee.name)) {
|
|
4080
|
+
return {
|
|
4081
|
+
type: "serviceCall",
|
|
4082
|
+
name: callee.name,
|
|
4083
|
+
importSource: importedFns.get(callee.name)
|
|
4084
|
+
};
|
|
4085
|
+
}
|
|
4086
|
+
}
|
|
4087
|
+
return null;
|
|
4088
|
+
}
|
|
4089
|
+
function extractAllowTransitions(body) {
|
|
4090
|
+
const result = [];
|
|
4091
|
+
for (const stmt of body.body) {
|
|
4092
|
+
if (!t12.isExpressionStatement(stmt)) continue;
|
|
4093
|
+
const expr = stmt.expression;
|
|
4094
|
+
if (!t12.isCallExpression(expr)) continue;
|
|
4095
|
+
if (!t12.isIdentifier(expr.callee) || expr.callee.name !== "allowTransition") continue;
|
|
4096
|
+
const nameArg = expr.arguments[0];
|
|
4097
|
+
const optsArg = expr.arguments[1];
|
|
4098
|
+
if (!t12.isStringLiteral(nameArg)) continue;
|
|
4099
|
+
const name = nameArg.value;
|
|
4100
|
+
const opts = optsArg && t12.isObjectExpression(optsArg) ? extractNodeValue2(optsArg) : {};
|
|
4101
|
+
let from = [];
|
|
4102
|
+
if (typeof opts.from === "string") from = [opts.from];
|
|
4103
|
+
else if (Array.isArray(opts.from)) from = opts.from.map(String);
|
|
4104
|
+
result.push({
|
|
4105
|
+
name,
|
|
4106
|
+
from,
|
|
4107
|
+
to: String(opts.to || ""),
|
|
4108
|
+
...opts.roles ? { roles: opts.roles } : {},
|
|
4109
|
+
...opts.require ? { require: opts.require } : {},
|
|
4110
|
+
...opts.when ? { when: String(opts.when) } : {}
|
|
4111
|
+
});
|
|
4112
|
+
}
|
|
4113
|
+
return result;
|
|
4114
|
+
}
|
|
4115
|
+
function parseDuration(str) {
|
|
4116
|
+
const match = str.match(/^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d|w)$/);
|
|
4117
|
+
if (!match) return 0;
|
|
4118
|
+
const value = parseFloat(match[1]);
|
|
4119
|
+
switch (match[2]) {
|
|
4120
|
+
case "ms":
|
|
4121
|
+
return value;
|
|
4122
|
+
case "s":
|
|
4123
|
+
return value * 1e3;
|
|
4124
|
+
case "m":
|
|
4125
|
+
return value * 6e4;
|
|
4126
|
+
case "h":
|
|
4127
|
+
return value * 36e5;
|
|
4128
|
+
case "d":
|
|
4129
|
+
return value * 864e5;
|
|
4130
|
+
case "w":
|
|
4131
|
+
return value * 6048e5;
|
|
4132
|
+
default:
|
|
4133
|
+
return 0;
|
|
4134
|
+
}
|
|
4135
|
+
}
|
|
4136
|
+
function toSnakeCase2(name) {
|
|
4137
|
+
return name.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
4138
|
+
}
|
|
4139
|
+
function fnNameToSlug(name) {
|
|
4140
|
+
return name.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
|
|
4141
|
+
}
|
|
4142
|
+
function extractStateDataRefs(expression) {
|
|
4143
|
+
const refs = [];
|
|
4144
|
+
const regex = /state_data\.(\w+)/g;
|
|
4145
|
+
let match;
|
|
4146
|
+
while ((match = regex.exec(expression)) !== null) {
|
|
4147
|
+
refs.push(match[1]);
|
|
4148
|
+
}
|
|
4149
|
+
return [...new Set(refs)];
|
|
4150
|
+
}
|
|
4151
|
+
function detectComputedFieldsFromActions(compilerState, stateFnInfos) {
|
|
4152
|
+
for (const [, info] of stateFnInfos) {
|
|
4153
|
+
for (const action of info.onEnter) {
|
|
4154
|
+
if (action.type !== "set_field") continue;
|
|
4155
|
+
const config = action.config;
|
|
4156
|
+
if (!config?.field || !config?.expression) continue;
|
|
4157
|
+
const targetField = config.field;
|
|
4158
|
+
const expression = config.expression;
|
|
4159
|
+
const refs = extractStateDataRefs(expression);
|
|
4160
|
+
const deps = refs.filter((r) => r !== targetField);
|
|
4161
|
+
if (deps.length === 0) continue;
|
|
4162
|
+
const field = compilerState.fields.find((f) => f.name === targetField);
|
|
4163
|
+
if (field) {
|
|
4164
|
+
field.computed = expression;
|
|
4165
|
+
field.computed_deps = deps;
|
|
4166
|
+
}
|
|
4167
|
+
}
|
|
4168
|
+
}
|
|
4169
|
+
}
|
|
4170
|
+
function detectComputedFieldGetters(path, paramName, paramTypeName, compilerState) {
|
|
4171
|
+
for (const node of path.node.body) {
|
|
4172
|
+
if (!t12.isFunctionDeclaration(node)) continue;
|
|
4173
|
+
if (node.async) continue;
|
|
4174
|
+
if (!node.id) continue;
|
|
4175
|
+
if (node.params.length !== 1) continue;
|
|
4176
|
+
const fnParam = node.params[0];
|
|
4177
|
+
if (!t12.isIdentifier(fnParam)) continue;
|
|
4178
|
+
if (fnParam.typeAnnotation && t12.isTSTypeAnnotation(fnParam.typeAnnotation)) {
|
|
4179
|
+
const typeAnno = fnParam.typeAnnotation.typeAnnotation;
|
|
4180
|
+
if (t12.isTSTypeReference(typeAnno) && t12.isIdentifier(typeAnno.typeName)) {
|
|
4181
|
+
if (typeAnno.typeName.name !== paramTypeName) continue;
|
|
4182
|
+
} else {
|
|
4183
|
+
continue;
|
|
4184
|
+
}
|
|
4185
|
+
} else {
|
|
4186
|
+
continue;
|
|
4187
|
+
}
|
|
4188
|
+
const hasReturnType = node.returnType && t12.isTSTypeAnnotation(node.returnType);
|
|
4189
|
+
if (!node.body || !t12.isBlockStatement(node.body)) continue;
|
|
4190
|
+
const returnStmt = node.body.body.find(
|
|
4191
|
+
(s) => t12.isReturnStatement(s)
|
|
4192
|
+
);
|
|
4193
|
+
if (!returnStmt?.argument) continue;
|
|
4194
|
+
const getterParamName = fnParam.name;
|
|
4195
|
+
const expression = expressionToIR(returnStmt.argument, getterParamName);
|
|
4196
|
+
const deps = extractStateDataRefs(expression);
|
|
4197
|
+
if (deps.length === 0) continue;
|
|
4198
|
+
const fieldName = node.id.name;
|
|
4199
|
+
let field = compilerState.fields.find((f) => f.name === fieldName);
|
|
4200
|
+
if (field) {
|
|
4201
|
+
field.computed = expression;
|
|
4202
|
+
field.computed_deps = deps;
|
|
4203
|
+
} else {
|
|
4204
|
+
let fieldType = "text";
|
|
4205
|
+
if (hasReturnType) {
|
|
4206
|
+
const retType = node.returnType.typeAnnotation;
|
|
4207
|
+
fieldType = resolveType2(retType);
|
|
4208
|
+
}
|
|
4209
|
+
compilerState.fields.push({
|
|
4210
|
+
name: fieldName,
|
|
4211
|
+
type: fieldType,
|
|
4212
|
+
label: fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (c) => c.toUpperCase()),
|
|
4213
|
+
required: false,
|
|
4214
|
+
computed: expression,
|
|
4215
|
+
computed_deps: deps
|
|
4216
|
+
});
|
|
4217
|
+
}
|
|
4218
|
+
}
|
|
4219
|
+
}
|
|
4220
|
+
function extractImperativeWorkflow(path, state) {
|
|
4221
|
+
const compilerState = state;
|
|
4222
|
+
if (!compilerState.actionCounter) compilerState.actionCounter = 0;
|
|
4223
|
+
const actionCounter = { value: compilerState.actionCounter };
|
|
4224
|
+
const importedFns = /* @__PURE__ */ new Map();
|
|
4225
|
+
const stdLibImports = /* @__PURE__ */ new Set();
|
|
4226
|
+
for (const node of path.node.body) {
|
|
4227
|
+
if (t12.isImportDeclaration(node)) {
|
|
4228
|
+
const source = node.source.value;
|
|
4229
|
+
for (const spec of node.specifiers) {
|
|
4230
|
+
const localName = spec.local.name;
|
|
4231
|
+
if (source.includes("@mmapp/react") || source.includes("@mindmatrix/react")) {
|
|
4232
|
+
stdLibImports.add(localName);
|
|
4233
|
+
} else {
|
|
4234
|
+
importedFns.set(localName, source);
|
|
4235
|
+
}
|
|
4236
|
+
}
|
|
4237
|
+
}
|
|
4238
|
+
}
|
|
4239
|
+
for (const node of path.node.body) {
|
|
4240
|
+
if (t12.isExportDefaultDeclaration(node) && t12.isCallExpression(node.declaration)) {
|
|
4241
|
+
const call = node.declaration;
|
|
4242
|
+
if (t12.isIdentifier(call.callee) && call.callee.name === "workflow") {
|
|
4243
|
+
const slugArg = call.arguments[0] && t12.isStringLiteral(call.arguments[0]) ? call.arguments[0].value : "workflow";
|
|
4244
|
+
let fieldsOrArrow = "";
|
|
4245
|
+
let arrowString;
|
|
4246
|
+
if (call.arguments.length === 2) {
|
|
4247
|
+
const arg1 = call.arguments[1];
|
|
4248
|
+
if (t12.isStringLiteral(arg1)) {
|
|
4249
|
+
fieldsOrArrow = arg1.value;
|
|
4250
|
+
} else if (t12.isTemplateLiteral(arg1)) {
|
|
4251
|
+
fieldsOrArrow = arg1.quasis.map((q) => q.value.raw).join("");
|
|
4252
|
+
} else if (t12.isObjectExpression(arg1)) {
|
|
4253
|
+
fieldsOrArrow = extractNodeValue2(arg1);
|
|
4254
|
+
}
|
|
4255
|
+
} else if (call.arguments.length >= 3) {
|
|
4256
|
+
const arg1 = call.arguments[1];
|
|
4257
|
+
const arg2 = call.arguments[2];
|
|
4258
|
+
if (t12.isObjectExpression(arg1)) {
|
|
4259
|
+
fieldsOrArrow = extractNodeValue2(arg1);
|
|
4260
|
+
}
|
|
4261
|
+
if (t12.isStringLiteral(arg2)) {
|
|
4262
|
+
arrowString = arg2.value;
|
|
4263
|
+
} else if (t12.isTemplateLiteral(arg2)) {
|
|
4264
|
+
arrowString = arg2.quasis.map((q) => q.value.raw).join("");
|
|
4265
|
+
}
|
|
4266
|
+
}
|
|
4267
|
+
const result = parseWorkflowShorthand(slugArg, fieldsOrArrow, arrowString);
|
|
4268
|
+
compilerState.metadata.slug = result.slug;
|
|
4269
|
+
compilerState.metadata.category = "workflow";
|
|
4270
|
+
compilerState.fields.push(...result.fields);
|
|
4271
|
+
for (const s of result.states) {
|
|
4272
|
+
compilerState.states.set(s.name, s);
|
|
4273
|
+
}
|
|
4274
|
+
compilerState.transitions.push(...result.transitions);
|
|
4275
|
+
compilerState.actionCounter = actionCounter.value;
|
|
4276
|
+
return;
|
|
4277
|
+
}
|
|
4278
|
+
}
|
|
4279
|
+
}
|
|
4280
|
+
let parentFn = null;
|
|
4281
|
+
let parentName = "";
|
|
4282
|
+
let paramName = "";
|
|
4283
|
+
let paramTypeName = "";
|
|
4284
|
+
for (const node of path.node.body) {
|
|
4285
|
+
if (t12.isExportDefaultDeclaration(node) && t12.isFunctionDeclaration(node.declaration)) {
|
|
4286
|
+
const fn = node.declaration;
|
|
4287
|
+
if (fn.async && fn.params.length > 0) {
|
|
4288
|
+
parentFn = fn;
|
|
4289
|
+
parentName = fn.id?.name || "workflow";
|
|
4290
|
+
const param = fn.params[0];
|
|
4291
|
+
if (t12.isIdentifier(param)) {
|
|
4292
|
+
paramName = param.name;
|
|
4293
|
+
if (param.typeAnnotation && t12.isTSTypeAnnotation(param.typeAnnotation)) {
|
|
4294
|
+
const typeAnno = param.typeAnnotation.typeAnnotation;
|
|
4295
|
+
if (t12.isTSTypeReference(typeAnno) && t12.isIdentifier(typeAnno.typeName)) {
|
|
4296
|
+
paramTypeName = typeAnno.typeName.name;
|
|
4297
|
+
}
|
|
4298
|
+
}
|
|
4299
|
+
}
|
|
4300
|
+
}
|
|
4301
|
+
}
|
|
4302
|
+
}
|
|
4303
|
+
if (!parentFn || !paramName) return;
|
|
4304
|
+
const slug = fnNameToSlug(parentName.replace(/Workflow$/, ""));
|
|
4305
|
+
compilerState.metadata.slug = slug;
|
|
4306
|
+
compilerState.metadata.category = "workflow";
|
|
4307
|
+
for (const node of path.node.body) {
|
|
4308
|
+
if (t12.isTSInterfaceDeclaration(node) && node.id.name === paramTypeName) {
|
|
4309
|
+
const fields = extractFieldsFromInterface2(node);
|
|
4310
|
+
compilerState.fields.push(...fields);
|
|
4311
|
+
compilerState.metadata.name = paramTypeName;
|
|
4312
|
+
}
|
|
4313
|
+
if (t12.isExportNamedDeclaration(node) && t12.isTSInterfaceDeclaration(node.declaration) && node.declaration.id.name === paramTypeName) {
|
|
4314
|
+
const fields = extractFieldsFromInterface2(node.declaration);
|
|
4315
|
+
compilerState.fields.push(...fields);
|
|
4316
|
+
compilerState.metadata.name = paramTypeName;
|
|
4317
|
+
}
|
|
4318
|
+
}
|
|
4319
|
+
const localFns = /* @__PURE__ */ new Map();
|
|
4320
|
+
const localFnNames = /* @__PURE__ */ new Set();
|
|
4321
|
+
for (const node of path.node.body) {
|
|
4322
|
+
if (t12.isFunctionDeclaration(node) && node.async && node.id) {
|
|
4323
|
+
if (node.id.name !== parentName) {
|
|
4324
|
+
localFns.set(node.id.name, node);
|
|
4325
|
+
localFnNames.add(node.id.name);
|
|
4326
|
+
}
|
|
4327
|
+
}
|
|
4328
|
+
if (t12.isExportNamedDeclaration(node) && t12.isFunctionDeclaration(node.declaration) && node.declaration.async && node.declaration.id) {
|
|
4329
|
+
if (node.declaration.id.name !== parentName) {
|
|
4330
|
+
localFns.set(node.declaration.id.name, node.declaration);
|
|
4331
|
+
localFnNames.add(node.declaration.id.name);
|
|
4332
|
+
}
|
|
4333
|
+
}
|
|
4334
|
+
}
|
|
4335
|
+
for (const node of path.node.body) {
|
|
4336
|
+
if (t12.isExportNamedDeclaration(node) && t12.isVariableDeclaration(node.declaration)) {
|
|
4337
|
+
for (const decl of node.declaration.declarations) {
|
|
4338
|
+
if (t12.isIdentifier(decl.id) && decl.id.name === "defaults" && t12.isObjectExpression(decl.init)) {
|
|
4339
|
+
const defaults = extractNodeValue2(decl.init);
|
|
4340
|
+
for (const [name, value] of Object.entries(defaults)) {
|
|
4341
|
+
const field = compilerState.fields.find((f) => f.name === name);
|
|
4342
|
+
if (field && value !== void 0) {
|
|
4343
|
+
field.default_value = value;
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4346
|
+
}
|
|
4347
|
+
}
|
|
4348
|
+
}
|
|
4349
|
+
}
|
|
4350
|
+
const stateFnInfos = /* @__PURE__ */ new Map();
|
|
4351
|
+
for (const [name, fn] of localFns) {
|
|
4352
|
+
const fnParamName = fn.params[0] && t12.isIdentifier(fn.params[0]) ? fn.params[0].name : paramName;
|
|
4353
|
+
const analysis = analyzeStateFn(fn, fnParamName, actionCounter);
|
|
4354
|
+
stateFnInfos.set(name, {
|
|
4355
|
+
name,
|
|
4356
|
+
node: fn,
|
|
4357
|
+
params: fn.params.map((p) => t12.isIdentifier(p) ? p.name : ""),
|
|
4358
|
+
...analysis
|
|
4359
|
+
});
|
|
4360
|
+
}
|
|
4361
|
+
detectComputedFieldsFromActions(compilerState, stateFnInfos);
|
|
4362
|
+
detectComputedFieldGetters(path, paramName, paramTypeName, compilerState);
|
|
4363
|
+
const callSequence = extractCallSequence(
|
|
4364
|
+
parentFn.body,
|
|
4365
|
+
paramName,
|
|
4366
|
+
localFnNames,
|
|
4367
|
+
importedFns
|
|
4368
|
+
);
|
|
4369
|
+
const allowTransitions = extractAllowTransitions(parentFn.body);
|
|
4370
|
+
const referencedStates = /* @__PURE__ */ new Set();
|
|
4371
|
+
let firstStateName = "";
|
|
4372
|
+
let prevStateName = "";
|
|
4373
|
+
let transitionIndex = 0;
|
|
4374
|
+
for (const call of callSequence) {
|
|
4375
|
+
const stateName = toSnakeCase2(call.name);
|
|
4376
|
+
switch (call.type) {
|
|
4377
|
+
case "stateCall": {
|
|
4378
|
+
if (call.name.startsWith("__compensation_") && call.options?.__isCompensation) {
|
|
4379
|
+
const compOpts = call.options;
|
|
4380
|
+
const tryCallNames = compOpts.__tryBlockCallNames || [];
|
|
4381
|
+
const compensationCalls = compOpts.__compensationCalls || [];
|
|
4382
|
+
const hasReturn = compOpts.__hasReturn;
|
|
4383
|
+
const catchBody = compOpts.__catchBody;
|
|
4384
|
+
const compIndex = ++transitionIndex;
|
|
4385
|
+
const compStateName = `compensation_${compIndex}`;
|
|
4386
|
+
const compActions = [];
|
|
4387
|
+
if (catchBody) {
|
|
4388
|
+
for (const innerStmt of catchBody.body) {
|
|
4389
|
+
if (t12.isReturnStatement(innerStmt)) continue;
|
|
4390
|
+
if (t12.isExpressionStatement(innerStmt)) {
|
|
4391
|
+
const innerExpr = innerStmt.expression;
|
|
4392
|
+
if (t12.isAssignmentExpression(innerExpr) && t12.isMemberExpression(innerExpr.left)) {
|
|
4393
|
+
const left = memberExprToString(innerExpr.left);
|
|
4394
|
+
if (left.startsWith(`${paramName}.`)) {
|
|
4395
|
+
const field = left.slice(paramName.length + 1);
|
|
4396
|
+
const valueExpr = expressionToIR(innerExpr.right, paramName);
|
|
4397
|
+
compActions.push({
|
|
4398
|
+
id: `auto_${++actionCounter.value}`,
|
|
4399
|
+
type: "set_field",
|
|
4400
|
+
mode: "auto",
|
|
4401
|
+
config: { field, expression: valueExpr }
|
|
4402
|
+
});
|
|
4403
|
+
}
|
|
4404
|
+
}
|
|
4405
|
+
if (t12.isAwaitExpression(innerExpr) && t12.isCallExpression(innerExpr.argument)) {
|
|
4406
|
+
const innerCall = innerExpr.argument;
|
|
4407
|
+
const fnName = t12.isIdentifier(innerCall.callee) ? innerCall.callee.name : null;
|
|
4408
|
+
if (fnName && importedFns.has(fnName)) {
|
|
4409
|
+
compActions.push({
|
|
4410
|
+
id: `auto_${++actionCounter.value}`,
|
|
4411
|
+
type: "call_workflow",
|
|
4412
|
+
mode: "auto",
|
|
4413
|
+
config: { definition_slug: fnNameToSlug(fnName), blocking: true }
|
|
4414
|
+
});
|
|
4415
|
+
}
|
|
4416
|
+
if (fnName === "log") {
|
|
4417
|
+
const event = innerCall.arguments[0] ? extractNodeValue2(innerCall.arguments[0]) : "";
|
|
4418
|
+
compActions.push({
|
|
4419
|
+
id: `auto_${++actionCounter.value}`,
|
|
4420
|
+
type: "log_event",
|
|
4421
|
+
mode: "auto",
|
|
4422
|
+
config: { event: String(event) }
|
|
4423
|
+
});
|
|
4424
|
+
}
|
|
4425
|
+
if (fnName === "notify") {
|
|
4426
|
+
const to = innerCall.arguments[0] ? expressionToIR(innerCall.arguments[0], paramName) : "";
|
|
4427
|
+
const message = innerCall.arguments[1] ? extractNodeValue2(innerCall.arguments[1]) : "";
|
|
4428
|
+
compActions.push({
|
|
4429
|
+
id: `auto_${++actionCounter.value}`,
|
|
4430
|
+
type: "send_notification",
|
|
4431
|
+
mode: "auto",
|
|
4432
|
+
config: { to: String(to), message: String(message) }
|
|
4433
|
+
});
|
|
4434
|
+
}
|
|
4435
|
+
if (fnName === "emit") {
|
|
4436
|
+
const event = innerCall.arguments[0] ? extractNodeValue2(innerCall.arguments[0]) : "";
|
|
4437
|
+
compActions.push({
|
|
4438
|
+
id: `auto_${++actionCounter.value}`,
|
|
4439
|
+
type: "emit_event",
|
|
4440
|
+
mode: "auto",
|
|
4441
|
+
config: { event: String(event) }
|
|
4442
|
+
});
|
|
4443
|
+
}
|
|
4444
|
+
}
|
|
4445
|
+
if (t12.isCallExpression(innerExpr)) {
|
|
4446
|
+
const fnName = t12.isIdentifier(innerExpr.callee) ? innerExpr.callee.name : null;
|
|
4447
|
+
if (fnName === "log") {
|
|
4448
|
+
const event = innerExpr.arguments[0] ? extractNodeValue2(innerExpr.arguments[0]) : "";
|
|
4449
|
+
compActions.push({
|
|
4450
|
+
id: `auto_${++actionCounter.value}`,
|
|
4451
|
+
type: "log_event",
|
|
4452
|
+
mode: "auto",
|
|
4453
|
+
config: { event: String(event) }
|
|
4454
|
+
});
|
|
4455
|
+
}
|
|
4456
|
+
if (fnName === "notify") {
|
|
4457
|
+
const to = innerExpr.arguments[0] ? expressionToIR(innerExpr.arguments[0], paramName) : "";
|
|
4458
|
+
const message = innerExpr.arguments[1] ? extractNodeValue2(innerExpr.arguments[1]) : "";
|
|
4459
|
+
compActions.push({
|
|
4460
|
+
id: `auto_${++actionCounter.value}`,
|
|
4461
|
+
type: "send_notification",
|
|
4462
|
+
mode: "auto",
|
|
4463
|
+
config: { to: String(to), message: String(message) }
|
|
4464
|
+
});
|
|
4465
|
+
}
|
|
4466
|
+
if (fnName === "emit") {
|
|
4467
|
+
const event = innerExpr.arguments[0] ? extractNodeValue2(innerExpr.arguments[0]) : "";
|
|
4468
|
+
compActions.push({
|
|
4469
|
+
id: `auto_${++actionCounter.value}`,
|
|
4470
|
+
type: "emit_event",
|
|
4471
|
+
mode: "auto",
|
|
4472
|
+
config: { event: String(event) }
|
|
4473
|
+
});
|
|
4474
|
+
}
|
|
4475
|
+
}
|
|
4476
|
+
}
|
|
4477
|
+
if (t12.isIfStatement(innerStmt) && t12.isBlockStatement(innerStmt.consequent)) {
|
|
4478
|
+
const condStr = expressionToIR(innerStmt.test, paramName);
|
|
4479
|
+
for (const ifInner of innerStmt.consequent.body) {
|
|
4480
|
+
if (t12.isExpressionStatement(ifInner)) {
|
|
4481
|
+
const ifExpr = ifInner.expression;
|
|
4482
|
+
if (t12.isAssignmentExpression(ifExpr) && t12.isMemberExpression(ifExpr.left)) {
|
|
4483
|
+
const left = memberExprToString(ifExpr.left);
|
|
4484
|
+
if (left.startsWith(`${paramName}.`)) {
|
|
4485
|
+
const field = left.slice(paramName.length + 1);
|
|
4486
|
+
const valueExpr = expressionToIR(ifExpr.right, paramName);
|
|
4487
|
+
compActions.push({
|
|
4488
|
+
id: `auto_${++actionCounter.value}`,
|
|
4489
|
+
type: "set_field",
|
|
4490
|
+
mode: "auto",
|
|
4491
|
+
config: { field, expression: valueExpr },
|
|
4492
|
+
condition: condStr
|
|
4493
|
+
});
|
|
4494
|
+
}
|
|
4495
|
+
}
|
|
4496
|
+
if (t12.isAwaitExpression(ifExpr) && t12.isCallExpression(ifExpr.argument)) {
|
|
4497
|
+
const ifCall = ifExpr.argument;
|
|
4498
|
+
const fnName = t12.isIdentifier(ifCall.callee) ? ifCall.callee.name : null;
|
|
4499
|
+
if (fnName && importedFns.has(fnName)) {
|
|
4500
|
+
compActions.push({
|
|
4501
|
+
id: `auto_${++actionCounter.value}`,
|
|
4502
|
+
type: "call_workflow",
|
|
4503
|
+
mode: "auto",
|
|
4504
|
+
config: { definition_slug: fnNameToSlug(fnName), blocking: true },
|
|
4505
|
+
condition: condStr
|
|
4506
|
+
});
|
|
4507
|
+
}
|
|
4508
|
+
}
|
|
4509
|
+
}
|
|
4510
|
+
}
|
|
4511
|
+
}
|
|
4512
|
+
}
|
|
4513
|
+
}
|
|
4514
|
+
for (const cc of compensationCalls) {
|
|
4515
|
+
if (cc.type === "serviceCall") {
|
|
4516
|
+
compActions.push({
|
|
4517
|
+
id: `auto_${++actionCounter.value}`,
|
|
4518
|
+
type: "call_workflow",
|
|
4519
|
+
mode: "auto",
|
|
4520
|
+
config: { definition_slug: fnNameToSlug(cc.name), blocking: true }
|
|
4521
|
+
});
|
|
4522
|
+
}
|
|
4523
|
+
}
|
|
4524
|
+
compilerState.states.set(compStateName, {
|
|
4525
|
+
name: compStateName,
|
|
4526
|
+
type: hasReturn ? "END" : "REGULAR",
|
|
4527
|
+
on_enter: compActions,
|
|
4528
|
+
during: [],
|
|
4529
|
+
on_exit: []
|
|
4530
|
+
});
|
|
4531
|
+
for (const tryCallName of tryCallNames) {
|
|
4532
|
+
let tryStateName;
|
|
4533
|
+
if (localFnNames.has(tryCallName)) {
|
|
4534
|
+
tryStateName = toSnakeCase2(tryCallName);
|
|
4535
|
+
} else if (importedFns.has(tryCallName)) {
|
|
4536
|
+
tryStateName = `awaiting_${toSnakeCase2(tryCallName)}`;
|
|
4537
|
+
} else {
|
|
4538
|
+
tryStateName = toSnakeCase2(tryCallName);
|
|
4539
|
+
}
|
|
4540
|
+
if (compilerState.states.has(tryStateName)) {
|
|
4541
|
+
compilerState.transitions.push({
|
|
4542
|
+
name: `error_to_${compStateName}`,
|
|
4543
|
+
from: [tryStateName],
|
|
4544
|
+
to: compStateName,
|
|
4545
|
+
conditions: [{ expression: "error != null" }],
|
|
4546
|
+
actions: [],
|
|
4547
|
+
auto: true
|
|
4548
|
+
});
|
|
4549
|
+
}
|
|
4550
|
+
}
|
|
4551
|
+
if (!hasReturn) {
|
|
4552
|
+
prevStateName = compStateName;
|
|
4553
|
+
}
|
|
4554
|
+
break;
|
|
4555
|
+
}
|
|
4556
|
+
referencedStates.add(call.name);
|
|
4557
|
+
if (!firstStateName) firstStateName = stateName;
|
|
4558
|
+
const info = stateFnInfos.get(call.name);
|
|
4559
|
+
if (info && !compilerState.states.has(stateName)) {
|
|
4560
|
+
compilerState.states.set(stateName, {
|
|
4561
|
+
name: stateName,
|
|
4562
|
+
type: !firstStateName || stateName === toSnakeCase2(callSequence[0]?.name || "") ? "START" : "REGULAR",
|
|
4563
|
+
on_enter: info.onEnter,
|
|
4564
|
+
during: info.during,
|
|
4565
|
+
on_exit: [],
|
|
4566
|
+
...info.onEvent.length > 0 ? { on_event: info.onEvent } : {},
|
|
4567
|
+
...info.timeout ? { timeout: info.timeout } : {},
|
|
4568
|
+
...info.runtime ? { runtime: info.runtime } : {}
|
|
4569
|
+
});
|
|
4570
|
+
} else if (!compilerState.states.has(stateName)) {
|
|
4571
|
+
compilerState.states.set(stateName, {
|
|
4572
|
+
name: stateName,
|
|
4573
|
+
type: "REGULAR",
|
|
4574
|
+
on_enter: [],
|
|
4575
|
+
during: [],
|
|
4576
|
+
on_exit: []
|
|
4577
|
+
});
|
|
4578
|
+
}
|
|
4579
|
+
if (prevStateName && prevStateName !== stateName) {
|
|
4580
|
+
const transName = call.transitionName || `to_${stateName}`;
|
|
4581
|
+
const conditions = [];
|
|
4582
|
+
if (call.condition) {
|
|
4583
|
+
conditions.push({ expression: call.condition });
|
|
4584
|
+
}
|
|
4585
|
+
if (info?.roles.length) {
|
|
4586
|
+
for (const role of info.roles) {
|
|
4587
|
+
conditions.push(roleCondition(role));
|
|
4588
|
+
}
|
|
4589
|
+
}
|
|
4590
|
+
compilerState.transitions.push({
|
|
4591
|
+
name: transName,
|
|
4592
|
+
from: [prevStateName],
|
|
4593
|
+
to: stateName,
|
|
4594
|
+
conditions: conditions.length > 0 ? conditions : void 0,
|
|
4595
|
+
actions: [],
|
|
4596
|
+
...info?.requiredFields.length ? { required_fields: info.requiredFields } : {},
|
|
4597
|
+
auto: true
|
|
4598
|
+
});
|
|
4599
|
+
}
|
|
4600
|
+
prevStateName = stateName;
|
|
4601
|
+
break;
|
|
4602
|
+
}
|
|
4603
|
+
case "userAction": {
|
|
4604
|
+
const awaitState = `awaiting_${call.name}`;
|
|
4605
|
+
if (!compilerState.states.has(awaitState)) {
|
|
4606
|
+
compilerState.states.set(awaitState, {
|
|
4607
|
+
name: awaitState,
|
|
4608
|
+
type: "REGULAR",
|
|
4609
|
+
on_enter: [],
|
|
4610
|
+
during: [],
|
|
4611
|
+
on_exit: []
|
|
4612
|
+
});
|
|
4613
|
+
}
|
|
4614
|
+
if (prevStateName) {
|
|
4615
|
+
compilerState.transitions.push({
|
|
4616
|
+
name: `to_${awaitState}`,
|
|
4617
|
+
from: [prevStateName],
|
|
4618
|
+
to: awaitState,
|
|
4619
|
+
actions: [],
|
|
4620
|
+
auto: true,
|
|
4621
|
+
...call.condition ? { conditions: [{ expression: call.condition }] } : {}
|
|
4622
|
+
});
|
|
4623
|
+
}
|
|
4624
|
+
const opts = call.options || {};
|
|
4625
|
+
const conditions = [];
|
|
4626
|
+
if (opts.roles && Array.isArray(opts.roles)) {
|
|
4627
|
+
for (const role of opts.roles) {
|
|
4628
|
+
conditions.push(roleCondition(role));
|
|
4629
|
+
}
|
|
4630
|
+
}
|
|
4631
|
+
if (opts.when && typeof opts.when === "string") {
|
|
4632
|
+
conditions.push({ expression: opts.when });
|
|
4633
|
+
}
|
|
4634
|
+
compilerState.transitions.push({
|
|
4635
|
+
name: call.name,
|
|
4636
|
+
from: [awaitState],
|
|
4637
|
+
to: "",
|
|
4638
|
+
// Will be resolved later (next state in sequence)
|
|
4639
|
+
conditions: conditions.length > 0 ? conditions : void 0,
|
|
4640
|
+
actions: [],
|
|
4641
|
+
...opts.require ? { required_fields: opts.require } : {}
|
|
4642
|
+
});
|
|
4643
|
+
prevStateName = awaitState;
|
|
4644
|
+
break;
|
|
4645
|
+
}
|
|
4646
|
+
case "userChoice": {
|
|
4647
|
+
const choiceState = prevStateName || "choice";
|
|
4648
|
+
if (call.choices) {
|
|
4649
|
+
for (const [optionName, optionConfig] of Object.entries(call.choices)) {
|
|
4650
|
+
const config = optionConfig;
|
|
4651
|
+
const conditions = [];
|
|
4652
|
+
if (config.roles && Array.isArray(config.roles)) {
|
|
4653
|
+
for (const role of config.roles) {
|
|
4654
|
+
conditions.push(roleCondition(role));
|
|
4655
|
+
}
|
|
4656
|
+
}
|
|
4657
|
+
if (config.when && typeof config.when === "string") {
|
|
4658
|
+
conditions.push({ expression: config.when });
|
|
4659
|
+
}
|
|
4660
|
+
compilerState.transitions.push({
|
|
4661
|
+
name: optionName,
|
|
4662
|
+
from: [choiceState],
|
|
4663
|
+
to: "",
|
|
4664
|
+
// Resolved by switch/case handling
|
|
4665
|
+
conditions: conditions.length > 0 ? conditions : void 0,
|
|
4666
|
+
actions: [],
|
|
4667
|
+
...config.require ? { required_fields: config.require } : {}
|
|
4668
|
+
});
|
|
4669
|
+
}
|
|
4670
|
+
}
|
|
4671
|
+
break;
|
|
4672
|
+
}
|
|
4673
|
+
case "serviceCall": {
|
|
4674
|
+
const serviceSlug = fnNameToSlug(call.name);
|
|
4675
|
+
const serviceState = `awaiting_${toSnakeCase2(call.name)}`;
|
|
4676
|
+
compilerState.states.set(serviceState, {
|
|
4677
|
+
name: serviceState,
|
|
4678
|
+
type: "REGULAR",
|
|
4679
|
+
on_enter: [{
|
|
4680
|
+
id: `auto_${++actionCounter.value}`,
|
|
4681
|
+
type: "call_workflow",
|
|
4682
|
+
mode: "auto",
|
|
4683
|
+
config: {
|
|
4684
|
+
definition_slug: serviceSlug,
|
|
4685
|
+
blocking: true
|
|
4686
|
+
}
|
|
4687
|
+
}],
|
|
4688
|
+
during: [],
|
|
4689
|
+
on_exit: []
|
|
4690
|
+
});
|
|
4691
|
+
if (prevStateName) {
|
|
4692
|
+
compilerState.transitions.push({
|
|
4693
|
+
name: `call_${toSnakeCase2(call.name)}`,
|
|
4694
|
+
from: [prevStateName],
|
|
4695
|
+
to: serviceState,
|
|
4696
|
+
actions: [],
|
|
4697
|
+
auto: true,
|
|
4698
|
+
...call.condition ? { conditions: [{ expression: call.condition }] } : {}
|
|
4699
|
+
});
|
|
4700
|
+
}
|
|
4701
|
+
prevStateName = serviceState;
|
|
4702
|
+
break;
|
|
4703
|
+
}
|
|
4704
|
+
case "awaitOn": {
|
|
4705
|
+
const eventState = `awaiting_${call.name}`;
|
|
4706
|
+
const opts = call.options || {};
|
|
4707
|
+
const eventPattern = opts.__eventPattern ? String(opts.__eventPattern) : call.name.replace(/_/g, ":");
|
|
4708
|
+
const awaitOnMetadata = {
|
|
4709
|
+
event_pattern: eventPattern
|
|
4710
|
+
};
|
|
4711
|
+
if (opts.when && typeof opts.when === "string") {
|
|
4712
|
+
awaitOnMetadata.event_condition = String(opts.when);
|
|
4713
|
+
}
|
|
4714
|
+
if (opts.timeout) {
|
|
4715
|
+
awaitOnMetadata.event_timeout = String(opts.timeout);
|
|
4716
|
+
}
|
|
4717
|
+
const awaitState = {
|
|
4718
|
+
name: eventState,
|
|
4719
|
+
type: "REGULAR",
|
|
4720
|
+
on_enter: [],
|
|
4721
|
+
during: [],
|
|
4722
|
+
on_exit: [],
|
|
4723
|
+
...opts.timeout ? { timeout: { duration: String(opts.timeout) } } : {}
|
|
4724
|
+
};
|
|
4725
|
+
if (awaitOnMetadata) awaitState.metadata = awaitOnMetadata;
|
|
4726
|
+
compilerState.states.set(eventState, awaitState);
|
|
4727
|
+
if (prevStateName) {
|
|
4728
|
+
compilerState.transitions.push({
|
|
4729
|
+
name: `await_${call.name}`,
|
|
4730
|
+
from: [prevStateName],
|
|
4731
|
+
to: eventState,
|
|
4732
|
+
actions: [],
|
|
4733
|
+
auto: true,
|
|
4734
|
+
...call.condition ? { conditions: [{ expression: call.condition }] } : {}
|
|
4735
|
+
});
|
|
4736
|
+
}
|
|
4737
|
+
const eventConditions = [];
|
|
4738
|
+
if (opts.when && typeof opts.when === "string") {
|
|
4739
|
+
eventConditions.push({ expression: String(opts.when) });
|
|
4740
|
+
}
|
|
4741
|
+
compilerState.transitions.push({
|
|
4742
|
+
name: `${call.name}_matched`,
|
|
4743
|
+
from: [eventState],
|
|
4744
|
+
to: "",
|
|
4745
|
+
// Resolved to next state
|
|
4746
|
+
conditions: eventConditions.length > 0 ? eventConditions : void 0,
|
|
4747
|
+
actions: [],
|
|
4748
|
+
auto: true
|
|
4749
|
+
});
|
|
4750
|
+
prevStateName = eventState;
|
|
4751
|
+
break;
|
|
4752
|
+
}
|
|
4753
|
+
case "promiseAll": {
|
|
4754
|
+
const parallelState = `parallel_${++transitionIndex}`;
|
|
4755
|
+
const parallelActions = [];
|
|
4756
|
+
for (const pc of call.parallelCalls || []) {
|
|
4757
|
+
if (pc.type === "serviceCall") {
|
|
4758
|
+
parallelActions.push({
|
|
4759
|
+
id: `auto_${++actionCounter.value}`,
|
|
4760
|
+
type: "call_workflow",
|
|
4761
|
+
mode: "auto",
|
|
4762
|
+
config: {
|
|
4763
|
+
definition_slug: fnNameToSlug(pc.name),
|
|
4764
|
+
blocking: true
|
|
4765
|
+
}
|
|
4766
|
+
});
|
|
4767
|
+
}
|
|
4768
|
+
}
|
|
4769
|
+
compilerState.states.set(parallelState, {
|
|
4770
|
+
name: parallelState,
|
|
4771
|
+
type: "REGULAR",
|
|
4772
|
+
on_enter: parallelActions,
|
|
4773
|
+
during: [],
|
|
4774
|
+
on_exit: []
|
|
4775
|
+
});
|
|
4776
|
+
if (prevStateName) {
|
|
4777
|
+
compilerState.transitions.push({
|
|
4778
|
+
name: `to_${parallelState}`,
|
|
4779
|
+
from: [prevStateName],
|
|
4780
|
+
to: parallelState,
|
|
4781
|
+
actions: [],
|
|
4782
|
+
auto: true
|
|
4783
|
+
});
|
|
4784
|
+
}
|
|
4785
|
+
prevStateName = parallelState;
|
|
4786
|
+
break;
|
|
4787
|
+
}
|
|
4788
|
+
case "delay": {
|
|
4789
|
+
const delayState = `delay_${++transitionIndex}`;
|
|
4790
|
+
const durationMatch = call.name.match(/delay_(.+)/);
|
|
4791
|
+
const duration = durationMatch ? durationMatch[1] : "0";
|
|
4792
|
+
compilerState.states.set(delayState, {
|
|
4793
|
+
name: delayState,
|
|
4794
|
+
type: "REGULAR",
|
|
4795
|
+
on_enter: [],
|
|
4796
|
+
during: [],
|
|
4797
|
+
on_exit: [],
|
|
4798
|
+
timeout: { duration, fallback: {} }
|
|
4799
|
+
});
|
|
4800
|
+
if (prevStateName) {
|
|
4801
|
+
compilerState.transitions.push({
|
|
4802
|
+
name: `to_${delayState}`,
|
|
4803
|
+
from: [prevStateName],
|
|
4804
|
+
to: delayState,
|
|
4805
|
+
actions: [],
|
|
4806
|
+
auto: true
|
|
4807
|
+
});
|
|
4808
|
+
}
|
|
4809
|
+
prevStateName = delayState;
|
|
4810
|
+
break;
|
|
4811
|
+
}
|
|
4812
|
+
}
|
|
4813
|
+
}
|
|
4814
|
+
if (prevStateName && compilerState.states.has(prevStateName)) {
|
|
4815
|
+
const lastState = compilerState.states.get(prevStateName);
|
|
4816
|
+
const hasOutgoing = compilerState.transitions.some((t22) => t22.from.includes(prevStateName));
|
|
4817
|
+
if (!hasOutgoing) {
|
|
4818
|
+
lastState.type = "END";
|
|
4819
|
+
}
|
|
4820
|
+
}
|
|
4821
|
+
if (firstStateName && compilerState.states.has(firstStateName)) {
|
|
4822
|
+
compilerState.states.get(firstStateName).type = "START";
|
|
4823
|
+
}
|
|
4824
|
+
for (let i = 0; i < compilerState.transitions.length; i++) {
|
|
4825
|
+
const trans = compilerState.transitions[i];
|
|
4826
|
+
if (trans.to === "" && i + 1 < compilerState.transitions.length) {
|
|
4827
|
+
const nextTrans = compilerState.transitions[i + 1];
|
|
4828
|
+
if (nextTrans.to) {
|
|
4829
|
+
trans.to = nextTrans.to;
|
|
4830
|
+
} else if (nextTrans.from.length > 0) {
|
|
4831
|
+
}
|
|
4832
|
+
}
|
|
4833
|
+
}
|
|
4834
|
+
const stateSequence = callSequence.filter((c) => c.type === "stateCall" || c.type === "serviceCall" || c.type === "userAction" || c.type === "awaitOn").map((c) => {
|
|
4835
|
+
if (c.type === "stateCall") return toSnakeCase2(c.name);
|
|
4836
|
+
if (c.type === "userAction") return `awaiting_${c.name}`;
|
|
4837
|
+
if (c.type === "serviceCall") return `awaiting_${toSnakeCase2(c.name)}`;
|
|
4838
|
+
if (c.type === "awaitOn") return `awaiting_${c.name}`;
|
|
4839
|
+
return c.name;
|
|
4840
|
+
});
|
|
4841
|
+
for (const trans of compilerState.transitions) {
|
|
4842
|
+
if (trans.to === "") {
|
|
4843
|
+
const fromState = trans.from[0];
|
|
4844
|
+
const idx = stateSequence.indexOf(fromState);
|
|
4845
|
+
if (idx >= 0 && idx + 1 < stateSequence.length) {
|
|
4846
|
+
trans.to = stateSequence[idx + 1];
|
|
4847
|
+
}
|
|
4848
|
+
}
|
|
4849
|
+
}
|
|
4850
|
+
for (const at of allowTransitions) {
|
|
4851
|
+
const resolvedTo = at.to === "$self" ? "__self__" : toSnakeCase2(at.to);
|
|
4852
|
+
const resolvedFrom = at.from.map((f) => toSnakeCase2(f));
|
|
4853
|
+
const conditions = [];
|
|
4854
|
+
if (at.roles) {
|
|
4855
|
+
for (const role of at.roles) {
|
|
4856
|
+
conditions.push(roleCondition(role));
|
|
4857
|
+
}
|
|
4858
|
+
}
|
|
4859
|
+
if (at.when) {
|
|
4860
|
+
conditions.push({ expression: at.when });
|
|
4861
|
+
}
|
|
4862
|
+
if (resolvedTo !== "__self__" && !compilerState.states.has(resolvedTo)) {
|
|
4863
|
+
compilerState.states.set(resolvedTo, {
|
|
4864
|
+
name: resolvedTo,
|
|
4865
|
+
type: "REGULAR",
|
|
4866
|
+
on_enter: [],
|
|
4867
|
+
during: [],
|
|
4868
|
+
on_exit: []
|
|
4869
|
+
});
|
|
4870
|
+
}
|
|
4871
|
+
if (resolvedTo === "__self__") {
|
|
4872
|
+
for (const from of resolvedFrom) {
|
|
4873
|
+
compilerState.transitions.push({
|
|
4874
|
+
name: at.name,
|
|
4875
|
+
from: [from],
|
|
4876
|
+
to: from,
|
|
4877
|
+
conditions: conditions.length > 0 ? conditions : void 0,
|
|
4878
|
+
actions: [],
|
|
4879
|
+
...at.require ? { required_fields: at.require } : {}
|
|
4880
|
+
});
|
|
4881
|
+
}
|
|
4882
|
+
} else {
|
|
4883
|
+
compilerState.transitions.push({
|
|
4884
|
+
name: at.name,
|
|
4885
|
+
from: resolvedFrom,
|
|
4886
|
+
to: resolvedTo,
|
|
4887
|
+
conditions: conditions.length > 0 ? conditions : void 0,
|
|
4888
|
+
actions: [],
|
|
4889
|
+
...at.require ? { required_fields: at.require } : {}
|
|
4890
|
+
});
|
|
4891
|
+
}
|
|
4892
|
+
}
|
|
4893
|
+
for (const [, info] of stateFnInfos) {
|
|
4894
|
+
for (const v of info.validations) {
|
|
4895
|
+
if (v.field === "__cross__") continue;
|
|
4896
|
+
const field = compilerState.fields.find((f) => f.name === v.field);
|
|
4897
|
+
if (field) {
|
|
4898
|
+
if (!field.validation) field.validation = {};
|
|
4899
|
+
Object.assign(field.validation, v.validation);
|
|
4900
|
+
if (v.validation.rules) {
|
|
4901
|
+
if (!field.validation.rules) field.validation.rules = [];
|
|
4902
|
+
field.validation.rules.push(...v.validation.rules);
|
|
4903
|
+
}
|
|
4904
|
+
}
|
|
4905
|
+
}
|
|
4906
|
+
}
|
|
4907
|
+
for (const node of path.node.body) {
|
|
4908
|
+
if (t12.isExportNamedDeclaration(node) && t12.isVariableDeclaration(node.declaration)) {
|
|
4909
|
+
for (const decl of node.declaration.declarations) {
|
|
4910
|
+
if (t12.isIdentifier(decl.id) && decl.id.name === "roles" && decl.init) {
|
|
4911
|
+
let rolesObj = null;
|
|
4912
|
+
if (t12.isCallExpression(decl.init) && t12.isIdentifier(decl.init.callee) && decl.init.callee.name === "defineRoles" && t12.isObjectExpression(decl.init.arguments[0])) {
|
|
4913
|
+
rolesObj = decl.init.arguments[0];
|
|
4914
|
+
} else if (t12.isObjectExpression(decl.init)) {
|
|
4915
|
+
rolesObj = decl.init;
|
|
4916
|
+
}
|
|
4917
|
+
if (rolesObj) {
|
|
4918
|
+
const roles = extractNodeValue2(rolesObj);
|
|
4919
|
+
if (!compilerState.metadata.roles) compilerState.metadata.roles = {};
|
|
4920
|
+
for (const [roleName, roleConfig] of Object.entries(roles)) {
|
|
4921
|
+
compilerState.metadata.roles[roleName] = roleConfig;
|
|
4922
|
+
}
|
|
4923
|
+
}
|
|
4924
|
+
}
|
|
4925
|
+
if (t12.isIdentifier(decl.id) && decl.id.name === "fieldAccess" && t12.isObjectExpression(decl.init)) {
|
|
4926
|
+
const access = extractNodeValue2(decl.init);
|
|
4927
|
+
for (const [fieldName, config] of Object.entries(access)) {
|
|
4928
|
+
const field = compilerState.fields.find((f) => f.name === fieldName);
|
|
4929
|
+
if (field) {
|
|
4930
|
+
if (config.visibleTo) field.visible_to_roles = config.visibleTo;
|
|
4931
|
+
if (config.editableBy) field.editable_by_roles = config.editableBy;
|
|
4932
|
+
if (config.editableIn) field.editable_in_states = config.editableIn;
|
|
4933
|
+
}
|
|
4934
|
+
}
|
|
4935
|
+
}
|
|
4936
|
+
if (t12.isIdentifier(decl.id) && decl.id.name === "config" && decl.init) {
|
|
4937
|
+
if (t12.isCallExpression(decl.init) && t12.isIdentifier(decl.init.callee) && decl.init.callee.name === "orchestration" && t12.isObjectExpression(decl.init.arguments[0])) {
|
|
4938
|
+
compilerState.metadata.orchestration = extractNodeValue2(decl.init.arguments[0]);
|
|
4939
|
+
}
|
|
4940
|
+
}
|
|
4941
|
+
}
|
|
4942
|
+
}
|
|
4943
|
+
}
|
|
4944
|
+
for (const node of path.node.body) {
|
|
4945
|
+
if (t12.isExportNamedDeclaration(node) && t12.isVariableDeclaration(node.declaration)) {
|
|
4946
|
+
for (const decl of node.declaration.declarations) {
|
|
4947
|
+
if (t12.isIdentifier(decl.id) && decl.id.name === "fields" && t12.isObjectExpression(decl.init)) {
|
|
4948
|
+
const fieldsConfig = extractNodeValue2(decl.init);
|
|
4949
|
+
for (const [name, config] of Object.entries(fieldsConfig)) {
|
|
4950
|
+
const field = compilerState.fields.find((f) => f.name === name);
|
|
4951
|
+
if (!field) continue;
|
|
4952
|
+
if (typeof config === "string") {
|
|
4953
|
+
if (config.includes("!")) field.required = true;
|
|
4954
|
+
} else if (typeof config === "object" && config !== null) {
|
|
4955
|
+
const cfg = config;
|
|
4956
|
+
if (cfg.required) field.required = true;
|
|
4957
|
+
if (cfg.min !== void 0 || cfg.max !== void 0 || cfg.minLength !== void 0 || cfg.maxLength !== void 0 || cfg.pattern !== void 0) {
|
|
4958
|
+
if (!field.validation) field.validation = {};
|
|
4959
|
+
if (cfg.min !== void 0) field.validation.min = Number(cfg.min);
|
|
4960
|
+
if (cfg.max !== void 0) field.validation.max = Number(cfg.max);
|
|
4961
|
+
if (cfg.minLength !== void 0) field.validation.minLength = Number(cfg.minLength);
|
|
4962
|
+
if (cfg.maxLength !== void 0) field.validation.maxLength = Number(cfg.maxLength);
|
|
4963
|
+
if (cfg.pattern !== void 0) {
|
|
4964
|
+
if (!field.validation.rules) field.validation.rules = [];
|
|
4965
|
+
field.validation.rules.push({
|
|
4966
|
+
expression: `MATCHES(value, "${String(cfg.pattern)}")`,
|
|
4967
|
+
message: "Invalid format",
|
|
4968
|
+
severity: "error"
|
|
4969
|
+
});
|
|
4970
|
+
}
|
|
4971
|
+
}
|
|
4972
|
+
if (cfg.default !== void 0) field.default_value = cfg.default;
|
|
4973
|
+
}
|
|
4974
|
+
}
|
|
4975
|
+
}
|
|
4976
|
+
}
|
|
4977
|
+
}
|
|
4978
|
+
}
|
|
4979
|
+
compilerState.transitions = compilerState.transitions.filter((t22) => t22.to !== "");
|
|
4980
|
+
for (const trans of compilerState.transitions) {
|
|
4981
|
+
for (const from of trans.from) {
|
|
4982
|
+
if (!compilerState.states.has(from)) {
|
|
4983
|
+
compilerState.states.set(from, {
|
|
4984
|
+
name: from,
|
|
4985
|
+
type: "REGULAR",
|
|
4986
|
+
on_enter: [],
|
|
4987
|
+
during: [],
|
|
4988
|
+
on_exit: []
|
|
4989
|
+
});
|
|
4990
|
+
}
|
|
4991
|
+
}
|
|
4992
|
+
if (!compilerState.states.has(trans.to)) {
|
|
4993
|
+
compilerState.states.set(trans.to, {
|
|
4994
|
+
name: trans.to,
|
|
4995
|
+
type: "REGULAR",
|
|
4996
|
+
on_enter: [],
|
|
4997
|
+
during: [],
|
|
4998
|
+
on_exit: []
|
|
4999
|
+
});
|
|
5000
|
+
}
|
|
5001
|
+
}
|
|
5002
|
+
compilerState.actionCounter = actionCounter.value;
|
|
5003
|
+
}
|
|
5004
|
+
|
|
5005
|
+
// src/babel/extractors/server-action-extractor.ts
|
|
5006
|
+
var t13 = __toESM(require("@babel/types"));
|
|
5007
|
+
function isServerActionFile(filename) {
|
|
5008
|
+
if (!filename) return false;
|
|
5009
|
+
return /\.server\.(ts|tsx|js|jsx)$/.test(filename);
|
|
5010
|
+
}
|
|
5011
|
+
function extractServerActions(path, state) {
|
|
5012
|
+
const compilerState = state;
|
|
5013
|
+
const serverActions = [];
|
|
5014
|
+
for (const node of path.node.body) {
|
|
5015
|
+
if (t13.isExportNamedDeclaration(node)) {
|
|
5016
|
+
const decl = node.declaration;
|
|
5017
|
+
if (t13.isFunctionDeclaration(decl) && decl.id) {
|
|
5018
|
+
const action = extractFunctionAction(decl);
|
|
5019
|
+
if (action) {
|
|
5020
|
+
const comments = node.leadingComments || decl.leadingComments || [];
|
|
5021
|
+
action.description = extractDescription(comments);
|
|
5022
|
+
serverActions.push(action);
|
|
5023
|
+
}
|
|
5024
|
+
}
|
|
5025
|
+
if (t13.isVariableDeclaration(decl)) {
|
|
5026
|
+
for (const varDecl of decl.declarations) {
|
|
5027
|
+
if (!t13.isIdentifier(varDecl.id)) continue;
|
|
5028
|
+
const init = varDecl.init;
|
|
5029
|
+
if (t13.isArrowFunctionExpression(init) || t13.isFunctionExpression(init)) {
|
|
5030
|
+
const action = {
|
|
5031
|
+
name: varDecl.id.name,
|
|
5032
|
+
async: init.async || false,
|
|
5033
|
+
params: init.params.filter((p) => t13.isIdentifier(p)).map((p) => p.name)
|
|
5034
|
+
};
|
|
5035
|
+
if (init.params.length > 0) {
|
|
5036
|
+
const firstParam = init.params[0];
|
|
5037
|
+
if (t13.isIdentifier(firstParam) && firstParam.typeAnnotation) {
|
|
5038
|
+
action.contextType = extractTypeName(firstParam.typeAnnotation);
|
|
5039
|
+
}
|
|
5040
|
+
}
|
|
5041
|
+
serverActions.push(action);
|
|
5042
|
+
}
|
|
5043
|
+
}
|
|
5044
|
+
}
|
|
5045
|
+
}
|
|
5046
|
+
}
|
|
5047
|
+
if (serverActions.length > 0) {
|
|
5048
|
+
if (!compilerState.metadata) compilerState.metadata = {};
|
|
5049
|
+
compilerState.metadata.serverActions = serverActions;
|
|
5050
|
+
}
|
|
5051
|
+
}
|
|
5052
|
+
function extractFunctionAction(decl) {
|
|
5053
|
+
if (!decl.id) return null;
|
|
5054
|
+
const action = {
|
|
5055
|
+
name: decl.id.name,
|
|
5056
|
+
async: decl.async || false,
|
|
5057
|
+
params: decl.params.filter((p) => t13.isIdentifier(p)).map((p) => p.name)
|
|
5058
|
+
};
|
|
5059
|
+
if (decl.params.length > 0) {
|
|
5060
|
+
const firstParam = decl.params[0];
|
|
5061
|
+
if (t13.isIdentifier(firstParam) && firstParam.typeAnnotation) {
|
|
5062
|
+
action.contextType = extractTypeName(firstParam.typeAnnotation);
|
|
5063
|
+
}
|
|
5064
|
+
}
|
|
5065
|
+
return action;
|
|
5066
|
+
}
|
|
5067
|
+
function extractTypeName(annotation) {
|
|
5068
|
+
if (t13.isTSTypeAnnotation(annotation)) {
|
|
5069
|
+
const typeNode = annotation.typeAnnotation;
|
|
5070
|
+
if (t13.isTSTypeReference(typeNode) && t13.isIdentifier(typeNode.typeName)) {
|
|
5071
|
+
return typeNode.typeName.name;
|
|
5072
|
+
}
|
|
5073
|
+
}
|
|
5074
|
+
return void 0;
|
|
5075
|
+
}
|
|
5076
|
+
function extractDescription(comments) {
|
|
5077
|
+
for (const comment of comments) {
|
|
5078
|
+
if (comment.type !== "CommentBlock") continue;
|
|
5079
|
+
const lines = comment.value.split("\n");
|
|
5080
|
+
for (const line of lines) {
|
|
5081
|
+
const trimmed = line.replace(/^\s*\*\s?/, "").trim();
|
|
5082
|
+
if (trimmed && !trimmed.startsWith("@")) {
|
|
5083
|
+
return trimmed;
|
|
5084
|
+
}
|
|
5085
|
+
}
|
|
5086
|
+
}
|
|
5087
|
+
return void 0;
|
|
5088
|
+
}
|
|
5089
|
+
|
|
5090
|
+
// src/babel/extractors/server-action-hook-extractor.ts
|
|
5091
|
+
var t14 = __toESM(require("@babel/types"));
|
|
5092
|
+
function extractServerActionHook(path, state) {
|
|
5093
|
+
const args = path.node.arguments;
|
|
5094
|
+
if (args.length < 1) return;
|
|
5095
|
+
const nameArg = args[0];
|
|
5096
|
+
if (!t14.isStringLiteral(nameArg)) return;
|
|
5097
|
+
const compilerState = state;
|
|
5098
|
+
const entry = {
|
|
5099
|
+
name: nameArg.value
|
|
5100
|
+
};
|
|
5101
|
+
if (args.length > 1 && t14.isObjectExpression(args[1])) {
|
|
5102
|
+
for (const prop of args[1].properties) {
|
|
5103
|
+
if (!t14.isObjectProperty(prop) || !t14.isIdentifier(prop.key)) continue;
|
|
5104
|
+
if (prop.key.name === "instanceId" && t14.isStringLiteral(prop.value)) {
|
|
5105
|
+
entry.staticInstanceId = prop.value.value;
|
|
5106
|
+
}
|
|
5107
|
+
}
|
|
5108
|
+
}
|
|
5109
|
+
const parent = path.parentPath;
|
|
5110
|
+
if (parent?.isVariableDeclarator() && t14.isIdentifier(parent.node.id)) {
|
|
5111
|
+
entry.variableName = parent.node.id.name;
|
|
5112
|
+
}
|
|
5113
|
+
if (!compilerState.metadata) compilerState.metadata = {};
|
|
5114
|
+
const meta = compilerState.metadata;
|
|
5115
|
+
if (!meta.serverActionHooks) meta.serverActionHooks = [];
|
|
5116
|
+
meta.serverActionHooks.push(entry);
|
|
5117
|
+
}
|
|
5118
|
+
|
|
5119
|
+
// src/babel/extractors/server-state-extractor.ts
|
|
5120
|
+
var t15 = __toESM(require("@babel/types"));
|
|
5121
|
+
function extractServerState(path, state) {
|
|
5122
|
+
const args = path.node.arguments;
|
|
5123
|
+
if (args.length < 1) return;
|
|
5124
|
+
const compilerState = state;
|
|
5125
|
+
const entry = {};
|
|
5126
|
+
const instanceArg = args[0];
|
|
5127
|
+
if (t15.isStringLiteral(instanceArg)) {
|
|
5128
|
+
entry.staticInstanceId = instanceArg.value;
|
|
5129
|
+
}
|
|
5130
|
+
if (args.length > 1 && t15.isObjectExpression(args[1])) {
|
|
5131
|
+
for (const prop of args[1].properties) {
|
|
5132
|
+
if (!t15.isObjectProperty(prop) || !t15.isIdentifier(prop.key)) continue;
|
|
5133
|
+
if (prop.key.name === "enabled" && t15.isBooleanLiteral(prop.value)) {
|
|
5134
|
+
if (!prop.value.value) entry.disabled = true;
|
|
5135
|
+
}
|
|
5136
|
+
}
|
|
5137
|
+
}
|
|
5138
|
+
const parent = path.parentPath;
|
|
5139
|
+
if (parent?.isVariableDeclarator()) {
|
|
5140
|
+
if (t15.isIdentifier(parent.node.id)) {
|
|
5141
|
+
entry.variableName = parent.node.id.name;
|
|
5142
|
+
} else if (t15.isObjectPattern(parent.node.id)) {
|
|
5143
|
+
const props = parent.node.id.properties.filter((p) => t15.isObjectProperty(p) && t15.isIdentifier(p.key)).map((p) => p.key.name);
|
|
5144
|
+
if (props.length > 0) {
|
|
5145
|
+
entry.variableName = props.join(", ");
|
|
5146
|
+
}
|
|
5147
|
+
}
|
|
5148
|
+
}
|
|
5149
|
+
if (!compilerState.metadata) compilerState.metadata = {};
|
|
5150
|
+
const meta = compilerState.metadata;
|
|
5151
|
+
if (!meta.serverStateSubscriptions) meta.serverStateSubscriptions = [];
|
|
5152
|
+
meta.serverStateSubscriptions.push(entry);
|
|
5153
|
+
meta.requiresSSE = true;
|
|
5154
|
+
}
|
|
5155
|
+
|
|
5156
|
+
// src/babel/extractors/grammar-island-extractor.ts
|
|
5157
|
+
var t16 = __toESM(require("@babel/types"));
|
|
5158
|
+
var GRAMMAR_TAGS = /* @__PURE__ */ new Set(["cedar", "sql", "cron", "dmn", "graphql", "jsonpath"]);
|
|
5159
|
+
function parseCedar(source) {
|
|
5160
|
+
const policies = [];
|
|
3203
5161
|
const policyRegex = /(permit|forbid)\s*\(([^)]*)\)(?:\s*when\s*\{([^}]*)\})?/g;
|
|
3204
5162
|
let match;
|
|
3205
5163
|
while ((match = policyRegex.exec(source)) !== null) {
|
|
@@ -3277,7 +5235,7 @@ function parseDmn(source) {
|
|
|
3277
5235
|
}
|
|
3278
5236
|
function extractGrammarIsland(path, state, slug) {
|
|
3279
5237
|
const tag = path.node.tag;
|
|
3280
|
-
if (!
|
|
5238
|
+
if (!t16.isIdentifier(tag)) return;
|
|
3281
5239
|
const tagName = tag.name;
|
|
3282
5240
|
if (!GRAMMAR_TAGS.has(tagName)) return;
|
|
3283
5241
|
const compilerState = state;
|
|
@@ -3287,7 +5245,7 @@ function extractGrammarIsland(path, state, slug) {
|
|
|
3287
5245
|
rawSource += quasi.quasis[i].value.raw;
|
|
3288
5246
|
if (i < quasi.expressions.length) {
|
|
3289
5247
|
const expr = quasi.expressions[i];
|
|
3290
|
-
if (
|
|
5248
|
+
if (t16.isIdentifier(expr)) {
|
|
3291
5249
|
rawSource += `\${${expr.name}}`;
|
|
3292
5250
|
} else {
|
|
3293
5251
|
rawSource += `\${expr_${i}}`;
|
|
@@ -3331,16 +5289,16 @@ function extractGrammarIslands(path, state) {
|
|
|
3331
5289
|
path.traverse({
|
|
3332
5290
|
TaggedTemplateExpression(templatePath) {
|
|
3333
5291
|
const tag = templatePath.node.tag;
|
|
3334
|
-
if (!
|
|
5292
|
+
if (!t16.isIdentifier(tag) || !GRAMMAR_TAGS.has(tag.name)) return;
|
|
3335
5293
|
let slug = "unnamed";
|
|
3336
5294
|
const parent = templatePath.parentPath;
|
|
3337
|
-
if (parent && parent.isVariableDeclarator() &&
|
|
5295
|
+
if (parent && parent.isVariableDeclarator() && t16.isIdentifier(parent.node.id)) {
|
|
3338
5296
|
slug = parent.node.id.name;
|
|
3339
5297
|
}
|
|
3340
|
-
if (parent && parent.isObjectProperty() &&
|
|
5298
|
+
if (parent && parent.isObjectProperty() && t16.isIdentifier(parent.node.key)) {
|
|
3341
5299
|
slug = parent.node.key.name;
|
|
3342
5300
|
}
|
|
3343
|
-
if (parent && parent.isObjectProperty() &&
|
|
5301
|
+
if (parent && parent.isObjectProperty() && t16.isStringLiteral(parent.node.key)) {
|
|
3344
5302
|
slug = parent.node.key.value;
|
|
3345
5303
|
}
|
|
3346
5304
|
extractGrammarIsland(templatePath, state, slug);
|
|
@@ -3349,12 +5307,12 @@ function extractGrammarIslands(path, state) {
|
|
|
3349
5307
|
}
|
|
3350
5308
|
|
|
3351
5309
|
// src/babel/extractors/context-extractor.ts
|
|
3352
|
-
var
|
|
5310
|
+
var t17 = __toESM(require("@babel/types"));
|
|
3353
5311
|
function hasContextCreation(path) {
|
|
3354
5312
|
let found = false;
|
|
3355
5313
|
path.traverse({
|
|
3356
5314
|
CallExpression(callPath) {
|
|
3357
|
-
if (
|
|
5315
|
+
if (t17.isIdentifier(callPath.node.callee, { name: "createContext" })) {
|
|
3358
5316
|
found = true;
|
|
3359
5317
|
callPath.stop();
|
|
3360
5318
|
}
|
|
@@ -3370,9 +5328,9 @@ function extractContextWorkflows(path, state) {
|
|
|
3370
5328
|
// Detect: const XContext = createContext(...)
|
|
3371
5329
|
VariableDeclarator(declPath) {
|
|
3372
5330
|
const init = declPath.node.init;
|
|
3373
|
-
if (!init || !
|
|
3374
|
-
if (!
|
|
3375
|
-
if (!
|
|
5331
|
+
if (!init || !t17.isCallExpression(init)) return;
|
|
5332
|
+
if (!t17.isIdentifier(init.callee, { name: "createContext" })) return;
|
|
5333
|
+
if (!t17.isIdentifier(declPath.node.id)) return;
|
|
3376
5334
|
const contextName = declPath.node.id.name;
|
|
3377
5335
|
contextNames.set(contextName, contextName);
|
|
3378
5336
|
const workflow = {
|
|
@@ -3381,25 +5339,25 @@ function extractContextWorkflows(path, state) {
|
|
|
3381
5339
|
reducerActions: []
|
|
3382
5340
|
};
|
|
3383
5341
|
const typeParams = init.typeParameters;
|
|
3384
|
-
if (typeParams &&
|
|
5342
|
+
if (typeParams && t17.isTSTypeParameterInstantiation(typeParams)) {
|
|
3385
5343
|
const typeArg = typeParams.params[0];
|
|
3386
|
-
if (
|
|
5344
|
+
if (t17.isTSTypeReference(typeArg) && t17.isIdentifier(typeArg.typeName)) {
|
|
3387
5345
|
const interfaceName = typeArg.typeName.name;
|
|
3388
|
-
|
|
5346
|
+
extractFieldsFromInterface3(path, interfaceName, workflow);
|
|
3389
5347
|
}
|
|
3390
5348
|
}
|
|
3391
|
-
if (init.arguments.length > 0 &&
|
|
5349
|
+
if (init.arguments.length > 0 && t17.isObjectExpression(init.arguments[0])) {
|
|
3392
5350
|
workflow.initialState = extractObjectLiteral2(init.arguments[0]);
|
|
3393
5351
|
}
|
|
3394
5352
|
contextWorkflows.push(workflow);
|
|
3395
5353
|
},
|
|
3396
5354
|
// Detect useReducer(reducer, initialState) and extract reducer cases
|
|
3397
5355
|
CallExpression(callPath) {
|
|
3398
|
-
if (!
|
|
5356
|
+
if (!t17.isIdentifier(callPath.node.callee, { name: "useReducer" })) return;
|
|
3399
5357
|
const args = callPath.node.arguments;
|
|
3400
5358
|
if (args.length < 1) return;
|
|
3401
5359
|
const reducerArg = args[0];
|
|
3402
|
-
if (!
|
|
5360
|
+
if (!t17.isIdentifier(reducerArg)) return;
|
|
3403
5361
|
const reducerName = reducerArg.name;
|
|
3404
5362
|
const actions = extractReducerActions(path, reducerName);
|
|
3405
5363
|
if (contextWorkflows.length > 0) {
|
|
@@ -3415,13 +5373,13 @@ function extractContextWorkflows(path, state) {
|
|
|
3415
5373
|
meta.contextWorkflows = contextWorkflows;
|
|
3416
5374
|
}
|
|
3417
5375
|
}
|
|
3418
|
-
function
|
|
5376
|
+
function extractFieldsFromInterface3(path, interfaceName, workflow) {
|
|
3419
5377
|
path.traverse({
|
|
3420
5378
|
TSInterfaceDeclaration(ifacePath) {
|
|
3421
|
-
if (!
|
|
5379
|
+
if (!t17.isIdentifier(ifacePath.node.id, { name: interfaceName })) return;
|
|
3422
5380
|
for (const prop of ifacePath.node.body.body) {
|
|
3423
|
-
if (!
|
|
3424
|
-
if (!
|
|
5381
|
+
if (!t17.isTSPropertySignature(prop)) continue;
|
|
5382
|
+
if (!t17.isIdentifier(prop.key)) continue;
|
|
3425
5383
|
const field = {
|
|
3426
5384
|
name: prop.key.name,
|
|
3427
5385
|
type: extractTSType(prop.typeAnnotation),
|
|
@@ -3433,20 +5391,20 @@ function extractFieldsFromInterface2(path, interfaceName, workflow) {
|
|
|
3433
5391
|
});
|
|
3434
5392
|
}
|
|
3435
5393
|
function extractTSType(annotation) {
|
|
3436
|
-
if (!annotation || !
|
|
5394
|
+
if (!annotation || !t17.isTSTypeAnnotation(annotation)) return "unknown";
|
|
3437
5395
|
const typeNode = annotation.typeAnnotation;
|
|
3438
|
-
if (
|
|
3439
|
-
if (
|
|
3440
|
-
if (
|
|
3441
|
-
if (
|
|
3442
|
-
if (
|
|
5396
|
+
if (t17.isTSStringKeyword(typeNode)) return "string";
|
|
5397
|
+
if (t17.isTSNumberKeyword(typeNode)) return "number";
|
|
5398
|
+
if (t17.isTSBooleanKeyword(typeNode)) return "boolean";
|
|
5399
|
+
if (t17.isTSArrayType(typeNode)) return `${extractTSTypeNode(typeNode.elementType)}[]`;
|
|
5400
|
+
if (t17.isTSTypeReference(typeNode) && t17.isIdentifier(typeNode.typeName)) return typeNode.typeName.name;
|
|
3443
5401
|
return "unknown";
|
|
3444
5402
|
}
|
|
3445
5403
|
function extractTSTypeNode(node) {
|
|
3446
|
-
if (
|
|
3447
|
-
if (
|
|
3448
|
-
if (
|
|
3449
|
-
if (
|
|
5404
|
+
if (t17.isTSStringKeyword(node)) return "string";
|
|
5405
|
+
if (t17.isTSNumberKeyword(node)) return "number";
|
|
5406
|
+
if (t17.isTSBooleanKeyword(node)) return "boolean";
|
|
5407
|
+
if (t17.isTSTypeReference(node) && t17.isIdentifier(node.typeName)) return node.typeName.name;
|
|
3450
5408
|
return "unknown";
|
|
3451
5409
|
}
|
|
3452
5410
|
function extractReducerActions(path, reducerName) {
|
|
@@ -3458,7 +5416,7 @@ function extractReducerActions(path, reducerName) {
|
|
|
3458
5416
|
SwitchStatement(switchPath) {
|
|
3459
5417
|
for (const switchCase of switchPath.node.cases) {
|
|
3460
5418
|
if (!switchCase.test) continue;
|
|
3461
|
-
if (
|
|
5419
|
+
if (t17.isStringLiteral(switchCase.test)) {
|
|
3462
5420
|
actions.push({
|
|
3463
5421
|
type: switchCase.test.value
|
|
3464
5422
|
});
|
|
@@ -3473,24 +5431,576 @@ function extractReducerActions(path, reducerName) {
|
|
|
3473
5431
|
function extractObjectLiteral2(obj) {
|
|
3474
5432
|
const result = {};
|
|
3475
5433
|
for (const prop of obj.properties) {
|
|
3476
|
-
if (!
|
|
3477
|
-
if (
|
|
3478
|
-
else if (
|
|
3479
|
-
else if (
|
|
3480
|
-
else if (
|
|
3481
|
-
else if (
|
|
3482
|
-
else if (
|
|
5434
|
+
if (!t17.isObjectProperty(prop) || !t17.isIdentifier(prop.key)) continue;
|
|
5435
|
+
if (t17.isStringLiteral(prop.value)) result[prop.key.name] = prop.value.value;
|
|
5436
|
+
else if (t17.isNumericLiteral(prop.value)) result[prop.key.name] = prop.value.value;
|
|
5437
|
+
else if (t17.isBooleanLiteral(prop.value)) result[prop.key.name] = prop.value.value;
|
|
5438
|
+
else if (t17.isNullLiteral(prop.value)) result[prop.key.name] = null;
|
|
5439
|
+
else if (t17.isArrayExpression(prop.value)) result[prop.key.name] = [];
|
|
5440
|
+
else if (t17.isObjectExpression(prop.value)) result[prop.key.name] = extractObjectLiteral2(prop.value);
|
|
5441
|
+
}
|
|
5442
|
+
return result;
|
|
5443
|
+
}
|
|
5444
|
+
|
|
5445
|
+
// src/babel/extractors/middleware-extractor.ts
|
|
5446
|
+
var t18 = __toESM(require("@babel/types"));
|
|
5447
|
+
var BUILTIN_FACTORIES = /* @__PURE__ */ new Set([
|
|
5448
|
+
"withAuth",
|
|
5449
|
+
"withAuditLog",
|
|
5450
|
+
"withRateLimit",
|
|
5451
|
+
"withValidation",
|
|
5452
|
+
"withMetrics"
|
|
5453
|
+
]);
|
|
5454
|
+
function hasMiddleware(path) {
|
|
5455
|
+
for (const node of path.node.body) {
|
|
5456
|
+
if (t18.isExportDefaultDeclaration(node)) {
|
|
5457
|
+
const decl = node.declaration;
|
|
5458
|
+
if (isDefineMiddlewareCall(decl) || isBuiltinFactoryCall(decl)) {
|
|
5459
|
+
return true;
|
|
5460
|
+
}
|
|
5461
|
+
}
|
|
5462
|
+
if (t18.isExportNamedDeclaration(node) && node.declaration) {
|
|
5463
|
+
if (t18.isVariableDeclaration(node.declaration)) {
|
|
5464
|
+
for (const declarator of node.declaration.declarations) {
|
|
5465
|
+
if (declarator.init && (isDefineMiddlewareCall(declarator.init) || isBuiltinFactoryCall(declarator.init))) {
|
|
5466
|
+
return true;
|
|
5467
|
+
}
|
|
5468
|
+
}
|
|
5469
|
+
}
|
|
5470
|
+
}
|
|
5471
|
+
if (t18.isVariableDeclaration(node)) {
|
|
5472
|
+
for (const declarator of node.declarations) {
|
|
5473
|
+
if (declarator.init && (isDefineMiddlewareCall(declarator.init) || isBuiltinFactoryCall(declarator.init))) {
|
|
5474
|
+
return true;
|
|
5475
|
+
}
|
|
5476
|
+
}
|
|
5477
|
+
}
|
|
5478
|
+
}
|
|
5479
|
+
return false;
|
|
5480
|
+
}
|
|
5481
|
+
function isDefineMiddlewareCall(node) {
|
|
5482
|
+
return t18.isCallExpression(node) && t18.isIdentifier(node.callee) && node.callee.name === "defineMiddleware";
|
|
5483
|
+
}
|
|
5484
|
+
function isBuiltinFactoryCall(node) {
|
|
5485
|
+
return t18.isCallExpression(node) && t18.isIdentifier(node.callee) && BUILTIN_FACTORIES.has(node.callee.name);
|
|
5486
|
+
}
|
|
5487
|
+
function extractMiddleware(path, state) {
|
|
5488
|
+
const compilerState = state;
|
|
5489
|
+
if (!compilerState.metadata) compilerState.metadata = {};
|
|
5490
|
+
const meta = compilerState.metadata;
|
|
5491
|
+
if (!meta.middleware) meta.middleware = [];
|
|
5492
|
+
const middlewareList = meta.middleware;
|
|
5493
|
+
path.traverse({
|
|
5494
|
+
CallExpression(callPath) {
|
|
5495
|
+
const callee = callPath.node.callee;
|
|
5496
|
+
if (!t18.isIdentifier(callee)) return;
|
|
5497
|
+
if (callee.name === "defineMiddleware") {
|
|
5498
|
+
const extracted = extractDefineMiddleware(callPath);
|
|
5499
|
+
if (extracted) middlewareList.push(extracted);
|
|
5500
|
+
} else if (BUILTIN_FACTORIES.has(callee.name)) {
|
|
5501
|
+
const extracted = extractBuiltinFactory(callee.name, callPath);
|
|
5502
|
+
if (extracted) middlewareList.push(extracted);
|
|
5503
|
+
}
|
|
5504
|
+
}
|
|
5505
|
+
});
|
|
5506
|
+
}
|
|
5507
|
+
function extractDefineMiddleware(callPath) {
|
|
5508
|
+
const args = callPath.node.arguments;
|
|
5509
|
+
if (args.length < 1 || !t18.isObjectExpression(args[0])) return null;
|
|
5510
|
+
const obj = args[0];
|
|
5511
|
+
let name = "unnamed";
|
|
5512
|
+
let match = [];
|
|
5513
|
+
let priority = 0;
|
|
5514
|
+
const before = [];
|
|
5515
|
+
const after = [];
|
|
5516
|
+
let hasAround = false;
|
|
5517
|
+
let config;
|
|
5518
|
+
for (const prop of obj.properties) {
|
|
5519
|
+
if (!t18.isObjectProperty(prop) && !t18.isObjectMethod(prop)) continue;
|
|
5520
|
+
const key = t18.isObjectProperty(prop) ? prop.key : prop.key;
|
|
5521
|
+
const keyName = t18.isIdentifier(key) ? key.name : t18.isStringLiteral(key) ? key.value : null;
|
|
5522
|
+
if (!keyName) continue;
|
|
5523
|
+
switch (keyName) {
|
|
5524
|
+
case "name":
|
|
5525
|
+
if (t18.isObjectProperty(prop) && t18.isStringLiteral(prop.value)) {
|
|
5526
|
+
name = prop.value.value;
|
|
5527
|
+
}
|
|
5528
|
+
break;
|
|
5529
|
+
case "match":
|
|
5530
|
+
if (t18.isObjectProperty(prop)) {
|
|
5531
|
+
if (t18.isStringLiteral(prop.value)) {
|
|
5532
|
+
match = [prop.value.value];
|
|
5533
|
+
} else if (t18.isArrayExpression(prop.value)) {
|
|
5534
|
+
match = prop.value.elements.filter((el) => t18.isStringLiteral(el)).map((el) => el.value);
|
|
5535
|
+
}
|
|
5536
|
+
}
|
|
5537
|
+
break;
|
|
5538
|
+
case "priority":
|
|
5539
|
+
if (t18.isObjectProperty(prop) && t18.isNumericLiteral(prop.value)) {
|
|
5540
|
+
priority = prop.value.value;
|
|
5541
|
+
}
|
|
5542
|
+
break;
|
|
5543
|
+
case "config":
|
|
5544
|
+
if (t18.isObjectProperty(prop) && t18.isObjectExpression(prop.value)) {
|
|
5545
|
+
config = extractConfigSchema(prop.value);
|
|
5546
|
+
}
|
|
5547
|
+
break;
|
|
5548
|
+
case "before":
|
|
5549
|
+
if (t18.isObjectMethod(prop)) {
|
|
5550
|
+
extractActionsFromBody(prop.body, before);
|
|
5551
|
+
} else if (t18.isObjectProperty(prop)) {
|
|
5552
|
+
const val = prop.value;
|
|
5553
|
+
if (t18.isFunctionExpression(val) || t18.isArrowFunctionExpression(val)) {
|
|
5554
|
+
const body = t18.isBlockStatement(val.body) ? val.body : null;
|
|
5555
|
+
if (body) extractActionsFromBody(body, before);
|
|
5556
|
+
}
|
|
5557
|
+
}
|
|
5558
|
+
break;
|
|
5559
|
+
case "after":
|
|
5560
|
+
if (t18.isObjectMethod(prop)) {
|
|
5561
|
+
extractActionsFromBody(prop.body, after);
|
|
5562
|
+
} else if (t18.isObjectProperty(prop)) {
|
|
5563
|
+
const val = prop.value;
|
|
5564
|
+
if (t18.isFunctionExpression(val) || t18.isArrowFunctionExpression(val)) {
|
|
5565
|
+
const body = t18.isBlockStatement(val.body) ? val.body : null;
|
|
5566
|
+
if (body) extractActionsFromBody(body, after);
|
|
5567
|
+
}
|
|
5568
|
+
}
|
|
5569
|
+
break;
|
|
5570
|
+
case "around":
|
|
5571
|
+
hasAround = true;
|
|
5572
|
+
break;
|
|
5573
|
+
}
|
|
5574
|
+
}
|
|
5575
|
+
return { name, match, priority, before, after, hasAround, config };
|
|
5576
|
+
}
|
|
5577
|
+
function extractBuiltinFactory(factoryName, callPath) {
|
|
5578
|
+
const args = callPath.node.arguments;
|
|
5579
|
+
const opts = args.length > 0 && t18.isObjectExpression(args[0]) ? args[0] : null;
|
|
5580
|
+
switch (factoryName) {
|
|
5581
|
+
case "withAuth": {
|
|
5582
|
+
let redirectTo;
|
|
5583
|
+
if (opts) {
|
|
5584
|
+
for (const prop of opts.properties) {
|
|
5585
|
+
if (t18.isObjectProperty(prop) && t18.isIdentifier(prop.key) && prop.key.name === "redirectTo" && t18.isStringLiteral(prop.value)) {
|
|
5586
|
+
redirectTo = prop.value.value;
|
|
5587
|
+
}
|
|
5588
|
+
}
|
|
5589
|
+
}
|
|
5590
|
+
return {
|
|
5591
|
+
name: "mm:auth",
|
|
5592
|
+
match: ["*:*:transition.execute"],
|
|
5593
|
+
priority: 90,
|
|
5594
|
+
before: [{ type: "block", args: { condition: "!ctx.actor.id", reason: redirectTo ? `redirect:${redirectTo}` : "Authentication required" } }],
|
|
5595
|
+
after: [],
|
|
5596
|
+
hasAround: false,
|
|
5597
|
+
factory: "withAuth"
|
|
5598
|
+
};
|
|
5599
|
+
}
|
|
5600
|
+
case "withAuditLog": {
|
|
5601
|
+
let level = "info";
|
|
5602
|
+
if (opts) {
|
|
5603
|
+
for (const prop of opts.properties) {
|
|
5604
|
+
if (t18.isObjectProperty(prop) && t18.isIdentifier(prop.key) && prop.key.name === "level" && t18.isStringLiteral(prop.value)) {
|
|
5605
|
+
level = prop.value.value;
|
|
5606
|
+
}
|
|
5607
|
+
}
|
|
5608
|
+
}
|
|
5609
|
+
return {
|
|
5610
|
+
name: "mm:audit-log",
|
|
5611
|
+
match: ["*:*:transition.execute"],
|
|
5612
|
+
priority: 0,
|
|
5613
|
+
before: [],
|
|
5614
|
+
after: [{ type: "modify", args: { __audit: { level } } }],
|
|
5615
|
+
hasAround: false,
|
|
5616
|
+
factory: "withAuditLog"
|
|
5617
|
+
};
|
|
5618
|
+
}
|
|
5619
|
+
case "withRateLimit": {
|
|
5620
|
+
let maxPerMinute = 60;
|
|
5621
|
+
if (opts) {
|
|
5622
|
+
for (const prop of opts.properties) {
|
|
5623
|
+
if (t18.isObjectProperty(prop) && t18.isIdentifier(prop.key) && prop.key.name === "maxPerMinute" && t18.isNumericLiteral(prop.value)) {
|
|
5624
|
+
maxPerMinute = prop.value.value;
|
|
5625
|
+
}
|
|
5626
|
+
}
|
|
5627
|
+
}
|
|
5628
|
+
return {
|
|
5629
|
+
name: "mm:rate-limit",
|
|
5630
|
+
match: ["*:*:transition.execute"],
|
|
5631
|
+
priority: 80,
|
|
5632
|
+
before: [{ type: "block", args: { condition: `counter >= ${maxPerMinute}`, reason: `Rate limit exceeded: ${maxPerMinute} per minute` } }],
|
|
5633
|
+
after: [],
|
|
5634
|
+
hasAround: false,
|
|
5635
|
+
config: { maxPerMinute: { type: "number", default: maxPerMinute } },
|
|
5636
|
+
factory: "withRateLimit"
|
|
5637
|
+
};
|
|
5638
|
+
}
|
|
5639
|
+
case "withValidation": {
|
|
5640
|
+
const rules = [];
|
|
5641
|
+
if (opts) {
|
|
5642
|
+
for (const prop of opts.properties) {
|
|
5643
|
+
if (t18.isObjectProperty(prop) && t18.isIdentifier(prop.key) && prop.key.name === "rules" && t18.isArrayExpression(prop.value)) {
|
|
5644
|
+
for (const el of prop.value.elements) {
|
|
5645
|
+
if (!t18.isObjectExpression(el)) continue;
|
|
5646
|
+
let fields = [];
|
|
5647
|
+
let check = "";
|
|
5648
|
+
let message = "";
|
|
5649
|
+
for (const rp of el.properties) {
|
|
5650
|
+
if (!t18.isObjectProperty(rp) || !t18.isIdentifier(rp.key)) continue;
|
|
5651
|
+
if (rp.key.name === "fields" && t18.isArrayExpression(rp.value)) {
|
|
5652
|
+
fields = rp.value.elements.filter((e) => t18.isStringLiteral(e)).map((e) => e.value);
|
|
5653
|
+
}
|
|
5654
|
+
if (rp.key.name === "check" && t18.isStringLiteral(rp.value)) {
|
|
5655
|
+
check = rp.value.value;
|
|
5656
|
+
}
|
|
5657
|
+
if (rp.key.name === "message" && t18.isStringLiteral(rp.value)) {
|
|
5658
|
+
message = rp.value.value;
|
|
5659
|
+
}
|
|
5660
|
+
}
|
|
5661
|
+
if (fields.length > 0) rules.push({ fields, check, message });
|
|
5662
|
+
}
|
|
5663
|
+
}
|
|
5664
|
+
}
|
|
5665
|
+
}
|
|
5666
|
+
return {
|
|
5667
|
+
name: "mm:validation",
|
|
5668
|
+
match: ["*:*:field.change"],
|
|
5669
|
+
priority: 70,
|
|
5670
|
+
before: rules.map((r) => ({ type: "validate", args: { fields: r.fields, check: r.check, message: r.message } })),
|
|
5671
|
+
after: [],
|
|
5672
|
+
hasAround: false,
|
|
5673
|
+
config: { rules: { type: "json", default: rules } },
|
|
5674
|
+
factory: "withValidation"
|
|
5675
|
+
};
|
|
5676
|
+
}
|
|
5677
|
+
case "withMetrics": {
|
|
5678
|
+
let endpoint;
|
|
5679
|
+
if (opts) {
|
|
5680
|
+
for (const prop of opts.properties) {
|
|
5681
|
+
if (t18.isObjectProperty(prop) && t18.isIdentifier(prop.key) && prop.key.name === "endpoint" && t18.isStringLiteral(prop.value)) {
|
|
5682
|
+
endpoint = prop.value.value;
|
|
5683
|
+
}
|
|
5684
|
+
}
|
|
5685
|
+
}
|
|
5686
|
+
return {
|
|
5687
|
+
name: "mm:metrics",
|
|
5688
|
+
match: ["*:*:*"],
|
|
5689
|
+
priority: 100,
|
|
5690
|
+
before: [],
|
|
5691
|
+
after: [],
|
|
5692
|
+
hasAround: true,
|
|
5693
|
+
config: { endpoint: { type: "string", default: endpoint } },
|
|
5694
|
+
factory: "withMetrics"
|
|
5695
|
+
};
|
|
5696
|
+
}
|
|
5697
|
+
default:
|
|
5698
|
+
return null;
|
|
5699
|
+
}
|
|
5700
|
+
}
|
|
5701
|
+
function extractActionsFromBody(body, actions) {
|
|
5702
|
+
for (const stmt of body.body) {
|
|
5703
|
+
if (t18.isExpressionStatement(stmt) && t18.isCallExpression(stmt.expression)) {
|
|
5704
|
+
const call = stmt.expression;
|
|
5705
|
+
if (t18.isMemberExpression(call.callee) && t18.isIdentifier(call.callee.property)) {
|
|
5706
|
+
const method = call.callee.property.name;
|
|
5707
|
+
if (method === "block" && call.arguments.length > 0) {
|
|
5708
|
+
const arg = call.arguments[0];
|
|
5709
|
+
actions.push({
|
|
5710
|
+
type: "block",
|
|
5711
|
+
args: { reason: t18.isStringLiteral(arg) ? arg.value : "<expression>" }
|
|
5712
|
+
});
|
|
5713
|
+
} else if (method === "modify" && call.arguments.length > 0) {
|
|
5714
|
+
const arg = call.arguments[0];
|
|
5715
|
+
actions.push({
|
|
5716
|
+
type: "modify",
|
|
5717
|
+
args: t18.isObjectExpression(arg) ? extractStaticObject(arg) : {}
|
|
5718
|
+
});
|
|
5719
|
+
} else if (method === "skip") {
|
|
5720
|
+
actions.push({ type: "skip" });
|
|
5721
|
+
}
|
|
5722
|
+
}
|
|
5723
|
+
}
|
|
5724
|
+
if (t18.isIfStatement(stmt)) {
|
|
5725
|
+
if (t18.isBlockStatement(stmt.consequent)) {
|
|
5726
|
+
extractActionsFromBody(stmt.consequent, actions);
|
|
5727
|
+
} else if (t18.isExpressionStatement(stmt.consequent)) {
|
|
5728
|
+
extractActionsFromBody(
|
|
5729
|
+
t18.blockStatement([stmt.consequent]),
|
|
5730
|
+
actions
|
|
5731
|
+
);
|
|
5732
|
+
}
|
|
5733
|
+
}
|
|
5734
|
+
}
|
|
5735
|
+
}
|
|
5736
|
+
function extractStaticObject(obj) {
|
|
5737
|
+
const result = {};
|
|
5738
|
+
for (const prop of obj.properties) {
|
|
5739
|
+
if (!t18.isObjectProperty(prop)) continue;
|
|
5740
|
+
const key = t18.isIdentifier(prop.key) ? prop.key.name : t18.isStringLiteral(prop.key) ? prop.key.value : null;
|
|
5741
|
+
if (!key) continue;
|
|
5742
|
+
const val = prop.value;
|
|
5743
|
+
if (t18.isStringLiteral(val)) result[key] = val.value;
|
|
5744
|
+
else if (t18.isNumericLiteral(val)) result[key] = val.value;
|
|
5745
|
+
else if (t18.isBooleanLiteral(val)) result[key] = val.value;
|
|
5746
|
+
else if (t18.isNullLiteral(val)) result[key] = null;
|
|
5747
|
+
else if (t18.isObjectExpression(val)) result[key] = extractStaticObject(val);
|
|
5748
|
+
else if (t18.isMemberExpression(val)) {
|
|
5749
|
+
result[key] = memberExprToString2(val);
|
|
5750
|
+
} else {
|
|
5751
|
+
result[key] = "<expression>";
|
|
5752
|
+
}
|
|
3483
5753
|
}
|
|
3484
5754
|
return result;
|
|
3485
5755
|
}
|
|
5756
|
+
function memberExprToString2(expr) {
|
|
5757
|
+
const parts = [];
|
|
5758
|
+
let current = expr;
|
|
5759
|
+
while (t18.isMemberExpression(current)) {
|
|
5760
|
+
if (t18.isIdentifier(current.property)) {
|
|
5761
|
+
parts.unshift(current.property.name);
|
|
5762
|
+
}
|
|
5763
|
+
current = current.object;
|
|
5764
|
+
}
|
|
5765
|
+
if (t18.isIdentifier(current)) {
|
|
5766
|
+
parts.unshift(current.name);
|
|
5767
|
+
}
|
|
5768
|
+
return "$" + parts.join(".");
|
|
5769
|
+
}
|
|
5770
|
+
function extractConfigSchema(obj) {
|
|
5771
|
+
const schema = {};
|
|
5772
|
+
for (const prop of obj.properties) {
|
|
5773
|
+
if (!t18.isObjectProperty(prop) || !t18.isIdentifier(prop.key)) continue;
|
|
5774
|
+
if (!t18.isObjectExpression(prop.value)) continue;
|
|
5775
|
+
const entry = { type: "string" };
|
|
5776
|
+
for (const inner of prop.value.properties) {
|
|
5777
|
+
if (!t18.isObjectProperty(inner) || !t18.isIdentifier(inner.key)) continue;
|
|
5778
|
+
if (inner.key.name === "type" && t18.isStringLiteral(inner.value)) {
|
|
5779
|
+
entry.type = inner.value.value;
|
|
5780
|
+
}
|
|
5781
|
+
if (inner.key.name === "default") {
|
|
5782
|
+
if (t18.isStringLiteral(inner.value)) entry.default = inner.value.value;
|
|
5783
|
+
else if (t18.isNumericLiteral(inner.value)) entry.default = inner.value.value;
|
|
5784
|
+
else if (t18.isBooleanLiteral(inner.value)) entry.default = inner.value.value;
|
|
5785
|
+
}
|
|
5786
|
+
}
|
|
5787
|
+
schema[prop.key.name] = entry;
|
|
5788
|
+
}
|
|
5789
|
+
return schema;
|
|
5790
|
+
}
|
|
5791
|
+
|
|
5792
|
+
// src/babel/extractors/constraint-extractor.ts
|
|
5793
|
+
var t19 = __toESM(require("@babel/types"));
|
|
5794
|
+
var BUILTIN_CONSTRAINTS = /* @__PURE__ */ new Set([
|
|
5795
|
+
"every state is reachable",
|
|
5796
|
+
"no deadlocks",
|
|
5797
|
+
"no unreachable states",
|
|
5798
|
+
"deterministic guards",
|
|
5799
|
+
"terminates",
|
|
5800
|
+
"no guard overlaps",
|
|
5801
|
+
"all roles defined",
|
|
5802
|
+
"all fields validated"
|
|
5803
|
+
]);
|
|
5804
|
+
function hasConstraints(path) {
|
|
5805
|
+
for (const node of path.node.body) {
|
|
5806
|
+
if (t19.isExportNamedDeclaration(node) && node.declaration) {
|
|
5807
|
+
if (t19.isVariableDeclaration(node.declaration)) {
|
|
5808
|
+
for (const declarator of node.declaration.declarations) {
|
|
5809
|
+
if (declarator.init && isConstraintsCall(declarator.init)) {
|
|
5810
|
+
return true;
|
|
5811
|
+
}
|
|
5812
|
+
}
|
|
5813
|
+
}
|
|
5814
|
+
}
|
|
5815
|
+
if (t19.isVariableDeclaration(node)) {
|
|
5816
|
+
for (const declarator of node.declarations) {
|
|
5817
|
+
if (declarator.init && isConstraintsCall(declarator.init)) {
|
|
5818
|
+
return true;
|
|
5819
|
+
}
|
|
5820
|
+
}
|
|
5821
|
+
}
|
|
5822
|
+
if (t19.isExpressionStatement(node) && isConstraintsCall(node.expression)) {
|
|
5823
|
+
return true;
|
|
5824
|
+
}
|
|
5825
|
+
}
|
|
5826
|
+
return false;
|
|
5827
|
+
}
|
|
5828
|
+
function isConstraintsCall(node) {
|
|
5829
|
+
return t19.isCallExpression(node) && t19.isIdentifier(node.callee) && node.callee.name === "constraints";
|
|
5830
|
+
}
|
|
5831
|
+
function extractConstraints(path, state) {
|
|
5832
|
+
const compilerState = state;
|
|
5833
|
+
if (!compilerState.metadata) compilerState.metadata = {};
|
|
5834
|
+
const meta = compilerState.metadata;
|
|
5835
|
+
if (!meta.constraints) meta.constraints = [];
|
|
5836
|
+
const constraintList = meta.constraints;
|
|
5837
|
+
path.traverse({
|
|
5838
|
+
CallExpression(callPath) {
|
|
5839
|
+
const callee = callPath.node.callee;
|
|
5840
|
+
if (!t19.isIdentifier(callee) || callee.name !== "constraints") return;
|
|
5841
|
+
const args = callPath.node.arguments;
|
|
5842
|
+
for (const arg of args) {
|
|
5843
|
+
if (t19.isStringLiteral(arg)) {
|
|
5844
|
+
constraintList.push({
|
|
5845
|
+
rule: arg.value,
|
|
5846
|
+
type: BUILTIN_CONSTRAINTS.has(arg.value) ? "builtin" : "custom"
|
|
5847
|
+
});
|
|
5848
|
+
}
|
|
5849
|
+
}
|
|
5850
|
+
}
|
|
5851
|
+
});
|
|
5852
|
+
}
|
|
3486
5853
|
|
|
3487
|
-
//
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
5854
|
+
// src/babel/extractors/actor-extractor.ts
|
|
5855
|
+
var t20 = __toESM(require("@babel/types"));
|
|
5856
|
+
function hasActorConfig(path) {
|
|
5857
|
+
for (const node of path.node.body) {
|
|
5858
|
+
if (t20.isExportNamedDeclaration(node) && node.declaration) {
|
|
5859
|
+
if (t20.isVariableDeclaration(node.declaration)) {
|
|
5860
|
+
for (const declarator of node.declaration.declarations) {
|
|
5861
|
+
if (declarator.init && isActorCall(declarator.init)) {
|
|
5862
|
+
return true;
|
|
5863
|
+
}
|
|
5864
|
+
}
|
|
5865
|
+
}
|
|
5866
|
+
}
|
|
5867
|
+
if (t20.isVariableDeclaration(node)) {
|
|
5868
|
+
for (const declarator of node.declarations) {
|
|
5869
|
+
if (declarator.init && isActorCall(declarator.init)) {
|
|
5870
|
+
return true;
|
|
5871
|
+
}
|
|
5872
|
+
}
|
|
5873
|
+
}
|
|
5874
|
+
if (t20.isExpressionStatement(node) && isActorCall(node.expression)) {
|
|
5875
|
+
return true;
|
|
5876
|
+
}
|
|
5877
|
+
}
|
|
5878
|
+
return false;
|
|
5879
|
+
}
|
|
5880
|
+
function isActorCall(node) {
|
|
5881
|
+
return t20.isCallExpression(node) && t20.isIdentifier(node.callee) && (node.callee.name === "configureActor" || node.callee.name === "spawnActor");
|
|
5882
|
+
}
|
|
5883
|
+
function extractActorConfig(path, state) {
|
|
5884
|
+
const compilerState = state;
|
|
5885
|
+
if (!compilerState.metadata) compilerState.metadata = {};
|
|
5886
|
+
const meta = compilerState.metadata;
|
|
5887
|
+
if (!meta.actor) {
|
|
5888
|
+
meta.actor = {
|
|
5889
|
+
supervision: { strategy: "escalate" },
|
|
5890
|
+
mailbox: {},
|
|
5891
|
+
hierarchy: {},
|
|
5892
|
+
spawns: []
|
|
5893
|
+
};
|
|
5894
|
+
}
|
|
5895
|
+
const actorConfig = meta.actor;
|
|
5896
|
+
path.traverse({
|
|
5897
|
+
CallExpression(callPath) {
|
|
5898
|
+
const callee = callPath.node.callee;
|
|
5899
|
+
if (!t20.isIdentifier(callee)) return;
|
|
5900
|
+
if (callee.name === "configureActor") {
|
|
5901
|
+
extractConfigureActor(callPath, actorConfig);
|
|
5902
|
+
} else if (callee.name === "spawnActor") {
|
|
5903
|
+
extractSpawnActor(callPath, actorConfig);
|
|
5904
|
+
}
|
|
5905
|
+
}
|
|
5906
|
+
});
|
|
5907
|
+
}
|
|
5908
|
+
function extractConfigureActor(callPath, actorConfig) {
|
|
5909
|
+
const args = callPath.node.arguments;
|
|
5910
|
+
if (args.length < 1 || !t20.isObjectExpression(args[0])) return;
|
|
5911
|
+
const obj = args[0];
|
|
5912
|
+
for (const prop of obj.properties) {
|
|
5913
|
+
if (!t20.isObjectProperty(prop) || !t20.isIdentifier(prop.key)) continue;
|
|
5914
|
+
switch (prop.key.name) {
|
|
5915
|
+
case "supervision":
|
|
5916
|
+
if (t20.isObjectExpression(prop.value)) {
|
|
5917
|
+
actorConfig.supervision = extractSupervision(prop.value);
|
|
5918
|
+
}
|
|
5919
|
+
break;
|
|
5920
|
+
case "mailbox":
|
|
5921
|
+
if (t20.isObjectExpression(prop.value)) {
|
|
5922
|
+
actorConfig.mailbox = extractMailbox(prop.value);
|
|
5923
|
+
}
|
|
5924
|
+
break;
|
|
5925
|
+
case "hierarchy":
|
|
5926
|
+
if (t20.isObjectExpression(prop.value)) {
|
|
5927
|
+
actorConfig.hierarchy = extractStaticObj(prop.value);
|
|
5928
|
+
}
|
|
5929
|
+
break;
|
|
5930
|
+
}
|
|
5931
|
+
}
|
|
5932
|
+
}
|
|
5933
|
+
function extractSpawnActor(callPath, actorConfig) {
|
|
5934
|
+
const args = callPath.node.arguments;
|
|
5935
|
+
if (args.length < 1 || !t20.isStringLiteral(args[0])) return;
|
|
5936
|
+
const spawn = { slug: args[0].value };
|
|
5937
|
+
if (args.length > 1 && t20.isObjectExpression(args[1])) {
|
|
5938
|
+
for (const prop of args[1].properties) {
|
|
5939
|
+
if (!t20.isObjectProperty(prop) || !t20.isIdentifier(prop.key)) continue;
|
|
5940
|
+
if (prop.key.name === "supervision" && t20.isObjectExpression(prop.value)) {
|
|
5941
|
+
spawn.supervision = extractSupervision(prop.value);
|
|
5942
|
+
} else if (prop.key.name === "blocking" && t20.isBooleanLiteral(prop.value)) {
|
|
5943
|
+
spawn.blocking = prop.value.value;
|
|
5944
|
+
}
|
|
5945
|
+
}
|
|
5946
|
+
}
|
|
5947
|
+
actorConfig.spawns.push(spawn);
|
|
5948
|
+
}
|
|
5949
|
+
function extractSupervision(obj) {
|
|
5950
|
+
const result = { strategy: "escalate" };
|
|
5951
|
+
for (const prop of obj.properties) {
|
|
5952
|
+
if (!t20.isObjectProperty(prop) || !t20.isIdentifier(prop.key)) continue;
|
|
5953
|
+
switch (prop.key.name) {
|
|
5954
|
+
case "strategy":
|
|
5955
|
+
if (t20.isStringLiteral(prop.value)) result.strategy = prop.value.value;
|
|
5956
|
+
break;
|
|
5957
|
+
case "maxRetries":
|
|
5958
|
+
if (t20.isNumericLiteral(prop.value)) result.maxRetries = prop.value.value;
|
|
5959
|
+
break;
|
|
5960
|
+
case "retryWindow":
|
|
5961
|
+
if (t20.isStringLiteral(prop.value)) result.retryWindow = prop.value.value;
|
|
5962
|
+
break;
|
|
5963
|
+
case "backoff":
|
|
5964
|
+
if (t20.isStringLiteral(prop.value)) result.backoff = prop.value.value;
|
|
5965
|
+
break;
|
|
5966
|
+
}
|
|
5967
|
+
}
|
|
5968
|
+
return result;
|
|
5969
|
+
}
|
|
5970
|
+
function extractMailbox(obj) {
|
|
5971
|
+
const result = {};
|
|
5972
|
+
for (const prop of obj.properties) {
|
|
5973
|
+
if (!t20.isObjectProperty(prop) || !t20.isIdentifier(prop.key)) continue;
|
|
5974
|
+
switch (prop.key.name) {
|
|
5975
|
+
case "capacity":
|
|
5976
|
+
if (t20.isNumericLiteral(prop.value)) result.capacity = prop.value.value;
|
|
5977
|
+
break;
|
|
5978
|
+
case "overflow":
|
|
5979
|
+
if (t20.isStringLiteral(prop.value)) result.overflow = prop.value.value;
|
|
5980
|
+
break;
|
|
5981
|
+
case "priority":
|
|
5982
|
+
if (t20.isStringLiteral(prop.value)) result.priority = prop.value.value;
|
|
5983
|
+
break;
|
|
5984
|
+
}
|
|
5985
|
+
}
|
|
5986
|
+
return result;
|
|
5987
|
+
}
|
|
5988
|
+
function extractStaticObj(obj) {
|
|
5989
|
+
const result = {};
|
|
5990
|
+
for (const prop of obj.properties) {
|
|
5991
|
+
if (!t20.isObjectProperty(prop) || !t20.isIdentifier(prop.key)) continue;
|
|
5992
|
+
const val = prop.value;
|
|
5993
|
+
if (t20.isStringLiteral(val)) result[prop.key.name] = val.value;
|
|
5994
|
+
else if (t20.isNumericLiteral(val)) result[prop.key.name] = val.value;
|
|
5995
|
+
else if (t20.isBooleanLiteral(val)) result[prop.key.name] = val.value;
|
|
5996
|
+
else if (t20.isNullLiteral(val)) result[prop.key.name] = null;
|
|
5997
|
+
}
|
|
5998
|
+
return result;
|
|
3492
5999
|
}
|
|
3493
6000
|
|
|
6001
|
+
// src/babel/emitters/pure-form-emitter.ts
|
|
6002
|
+
var import_player_core = require("@mindmatrix/player-core");
|
|
6003
|
+
|
|
3494
6004
|
// src/babel/emitters/experience-transform.ts
|
|
3495
6005
|
function transformToFrontend(node) {
|
|
3496
6006
|
const result = {
|
|
@@ -3708,7 +6218,7 @@ function normalizeViewNode(node, fieldNames) {
|
|
|
3708
6218
|
}
|
|
3709
6219
|
return node;
|
|
3710
6220
|
}
|
|
3711
|
-
function
|
|
6221
|
+
function toSnakeCase3(str) {
|
|
3712
6222
|
return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
3713
6223
|
}
|
|
3714
6224
|
function convertAction(action) {
|
|
@@ -3776,6 +6286,18 @@ function emitIR(extracted) {
|
|
|
3776
6286
|
});
|
|
3777
6287
|
stateNames.add(transition.to);
|
|
3778
6288
|
}
|
|
6289
|
+
for (const from of transition.from) {
|
|
6290
|
+
if (from && !stateNames.has(from)) {
|
|
6291
|
+
stateArray.push({
|
|
6292
|
+
name: from,
|
|
6293
|
+
type: "REGULAR",
|
|
6294
|
+
on_enter: [],
|
|
6295
|
+
during: [],
|
|
6296
|
+
on_exit: []
|
|
6297
|
+
});
|
|
6298
|
+
stateNames.add(from);
|
|
6299
|
+
}
|
|
6300
|
+
}
|
|
3779
6301
|
}
|
|
3780
6302
|
const fieldNames = new Set(fields.map((f) => f.name));
|
|
3781
6303
|
let normalizedView;
|
|
@@ -3791,7 +6313,7 @@ function emitIR(extracted) {
|
|
|
3791
6313
|
if (fields.length > 0) {
|
|
3792
6314
|
const localDefaults = {};
|
|
3793
6315
|
for (const f of fields) {
|
|
3794
|
-
localDefaults[
|
|
6316
|
+
localDefaults[toSnakeCase3(f.name)] = f.default_value ?? null;
|
|
3795
6317
|
}
|
|
3796
6318
|
if (!normalizedView.config) normalizedView.config = {};
|
|
3797
6319
|
normalizedView.config.localDefaults = localDefaults;
|
|
@@ -3870,7 +6392,7 @@ function liftAction(action) {
|
|
|
3870
6392
|
}
|
|
3871
6393
|
return {
|
|
3872
6394
|
slug: action.id,
|
|
3873
|
-
category: normalizeCategory("expression", "mutation", action.type),
|
|
6395
|
+
category: (0, import_player_core.normalizeCategory)("expression", "mutation", action.type),
|
|
3874
6396
|
parts: parts.length > 0 ? parts : void 0
|
|
3875
6397
|
};
|
|
3876
6398
|
}
|
|
@@ -3900,7 +6422,7 @@ function liftSchedule(during) {
|
|
|
3900
6422
|
for (const action of during.actions) {
|
|
3901
6423
|
parts.push({
|
|
3902
6424
|
slug: "do",
|
|
3903
|
-
category: normalizeCategory("expression", "mutation", action.type),
|
|
6425
|
+
category: (0, import_player_core.normalizeCategory)("expression", "mutation", action.type),
|
|
3904
6426
|
parts: Object.entries(action.config || {}).map(([key, value]) => ({
|
|
3905
6427
|
slug: key,
|
|
3906
6428
|
category: ["atom"],
|
|
@@ -3910,7 +6432,7 @@ function liftSchedule(during) {
|
|
|
3910
6432
|
}
|
|
3911
6433
|
return {
|
|
3912
6434
|
slug: during.id,
|
|
3913
|
-
category: normalizeCategory("schedule", during.type),
|
|
6435
|
+
category: (0, import_player_core.normalizeCategory)("schedule", during.type),
|
|
3914
6436
|
parts
|
|
3915
6437
|
};
|
|
3916
6438
|
}
|
|
@@ -3923,14 +6445,14 @@ function liftState(state) {
|
|
|
3923
6445
|
if (state.on_enter && state.on_enter.length > 0) {
|
|
3924
6446
|
parts.push({
|
|
3925
6447
|
slug: "on_enter",
|
|
3926
|
-
category: normalizeCategory("expression", "sequence"),
|
|
6448
|
+
category: (0, import_player_core.normalizeCategory)("expression", "sequence"),
|
|
3927
6449
|
parts: state.on_enter.map(liftAction)
|
|
3928
6450
|
});
|
|
3929
6451
|
}
|
|
3930
6452
|
if (state.on_exit && state.on_exit.length > 0) {
|
|
3931
6453
|
parts.push({
|
|
3932
6454
|
slug: "on_exit",
|
|
3933
|
-
category: normalizeCategory("expression", "sequence"),
|
|
6455
|
+
category: (0, import_player_core.normalizeCategory)("expression", "sequence"),
|
|
3934
6456
|
parts: state.on_exit.map(liftAction)
|
|
3935
6457
|
});
|
|
3936
6458
|
}
|
|
@@ -3941,7 +6463,7 @@ function liftState(state) {
|
|
|
3941
6463
|
}
|
|
3942
6464
|
return {
|
|
3943
6465
|
slug: state.name,
|
|
3944
|
-
category: normalizeCategory("state", ...tags),
|
|
6466
|
+
category: (0, import_player_core.normalizeCategory)("state", ...tags),
|
|
3945
6467
|
parts: parts.length > 0 ? parts : void 0
|
|
3946
6468
|
};
|
|
3947
6469
|
}
|
|
@@ -3964,17 +6486,17 @@ function liftTransition(transition) {
|
|
|
3964
6486
|
if (transition.actions && transition.actions.length > 0) {
|
|
3965
6487
|
parts.push({
|
|
3966
6488
|
slug: "actions",
|
|
3967
|
-
category: normalizeCategory("expression", "sequence"),
|
|
6489
|
+
category: (0, import_player_core.normalizeCategory)("expression", "sequence"),
|
|
3968
6490
|
parts: transition.actions.map(liftAction)
|
|
3969
6491
|
});
|
|
3970
6492
|
}
|
|
3971
6493
|
if (transition.conditions && transition.conditions.length > 0) {
|
|
3972
6494
|
parts.push({
|
|
3973
6495
|
slug: "conditions",
|
|
3974
|
-
category: normalizeCategory("expression", "guard"),
|
|
6496
|
+
category: (0, import_player_core.normalizeCategory)("expression", "guard"),
|
|
3975
6497
|
parts: transition.conditions.map((c, i) => ({
|
|
3976
6498
|
slug: `condition_${i}`,
|
|
3977
|
-
category: normalizeCategory("expression", c.type || "condition"),
|
|
6499
|
+
category: (0, import_player_core.normalizeCategory)("expression", c.type || "condition"),
|
|
3978
6500
|
parts: c.expression ? [{ slug: c.expression, category: ["binding"] }] : void 0
|
|
3979
6501
|
}))
|
|
3980
6502
|
});
|
|
@@ -4013,7 +6535,7 @@ function liftField(field) {
|
|
|
4013
6535
|
}
|
|
4014
6536
|
return {
|
|
4015
6537
|
slug: field.name,
|
|
4016
|
-
category: normalizeCategory("field", field.type),
|
|
6538
|
+
category: (0, import_player_core.normalizeCategory)("field", field.type),
|
|
4017
6539
|
parts: parts.length > 0 ? parts : void 0
|
|
4018
6540
|
};
|
|
4019
6541
|
}
|
|
@@ -4036,20 +6558,20 @@ function liftView(node) {
|
|
|
4036
6558
|
if (match) {
|
|
4037
6559
|
parts.push({
|
|
4038
6560
|
slug: key,
|
|
4039
|
-
category: normalizeCategory("expression", "effect", "transition"),
|
|
6561
|
+
category: (0, import_player_core.normalizeCategory)("expression", "effect", "transition"),
|
|
4040
6562
|
parts: [{ slug: match[1], category: ["ref"] }]
|
|
4041
6563
|
});
|
|
4042
6564
|
} else {
|
|
4043
6565
|
parts.push({
|
|
4044
6566
|
slug: key,
|
|
4045
|
-
category: normalizeCategory("expression", "binding"),
|
|
6567
|
+
category: (0, import_player_core.normalizeCategory)("expression", "binding"),
|
|
4046
6568
|
parts: [{ slug: String(expr), category: ["binding"] }]
|
|
4047
6569
|
});
|
|
4048
6570
|
}
|
|
4049
6571
|
} else {
|
|
4050
6572
|
parts.push({
|
|
4051
6573
|
slug: key,
|
|
4052
|
-
category: normalizeCategory("expression", "binding"),
|
|
6574
|
+
category: (0, import_player_core.normalizeCategory)("expression", "binding"),
|
|
4053
6575
|
parts: [{ slug: String(expr), category: ["binding"] }]
|
|
4054
6576
|
});
|
|
4055
6577
|
}
|
|
@@ -4060,20 +6582,20 @@ function liftView(node) {
|
|
|
4060
6582
|
if (eqMatch) {
|
|
4061
6583
|
parts.push({
|
|
4062
6584
|
slug: "visible_when",
|
|
4063
|
-
category: normalizeCategory("expression", "guard"),
|
|
6585
|
+
category: (0, import_player_core.normalizeCategory)("expression", "guard"),
|
|
4064
6586
|
parts: [{
|
|
4065
6587
|
slug: "body",
|
|
4066
|
-
category: normalizeCategory("expression", "eq"),
|
|
6588
|
+
category: (0, import_player_core.normalizeCategory)("expression", "eq"),
|
|
4067
6589
|
parts: [
|
|
4068
|
-
{ slug: "lhs", category: normalizeCategory("expression", "path"), parts: [{ slug: eqMatch[1], category: ["binding"] }] },
|
|
4069
|
-
{ slug: "rhs", category: normalizeCategory("expression", "literal"), parts: [{ slug: eqMatch[2], category: ["literal"] }] }
|
|
6590
|
+
{ slug: "lhs", category: (0, import_player_core.normalizeCategory)("expression", "path"), parts: [{ slug: eqMatch[1], category: ["binding"] }] },
|
|
6591
|
+
{ slug: "rhs", category: (0, import_player_core.normalizeCategory)("expression", "literal"), parts: [{ slug: eqMatch[2], category: ["literal"] }] }
|
|
4070
6592
|
]
|
|
4071
6593
|
}]
|
|
4072
6594
|
});
|
|
4073
6595
|
} else {
|
|
4074
6596
|
parts.push({
|
|
4075
6597
|
slug: "visible_when",
|
|
4076
|
-
category: normalizeCategory("expression", "guard"),
|
|
6598
|
+
category: (0, import_player_core.normalizeCategory)("expression", "guard"),
|
|
4077
6599
|
parts: [{ slug: node.visible_when, category: ["binding"] }]
|
|
4078
6600
|
});
|
|
4079
6601
|
}
|
|
@@ -4085,7 +6607,7 @@ function liftView(node) {
|
|
|
4085
6607
|
}
|
|
4086
6608
|
return {
|
|
4087
6609
|
slug: node.id,
|
|
4088
|
-
category: normalizeCategory("view", componentTag),
|
|
6610
|
+
category: (0, import_player_core.normalizeCategory)("view", componentTag),
|
|
4089
6611
|
parts: parts.length > 0 ? parts : void 0
|
|
4090
6612
|
};
|
|
4091
6613
|
}
|
|
@@ -4106,7 +6628,7 @@ function emitCanonical(extracted, sourceFilename) {
|
|
|
4106
6628
|
}
|
|
4107
6629
|
parts.push({
|
|
4108
6630
|
slug: "manifest",
|
|
4109
|
-
category: normalizeCategory("meta", "manifest"),
|
|
6631
|
+
category: (0, import_player_core.normalizeCategory)("meta", "manifest"),
|
|
4110
6632
|
parts: [
|
|
4111
6633
|
{
|
|
4112
6634
|
slug: "workflows",
|
|
@@ -4127,7 +6649,7 @@ function emitCanonical(extracted, sourceFilename) {
|
|
|
4127
6649
|
let categoryArray;
|
|
4128
6650
|
if (category.includes("/")) {
|
|
4129
6651
|
const [primary, ...tags] = category.split("/");
|
|
4130
|
-
categoryArray = normalizeCategory(primary, ...tags);
|
|
6652
|
+
categoryArray = (0, import_player_core.normalizeCategory)(primary, ...tags);
|
|
4131
6653
|
} else {
|
|
4132
6654
|
categoryArray = [category];
|
|
4133
6655
|
}
|
|
@@ -4189,7 +6711,7 @@ function emitWorkflowDefinition(extracted) {
|
|
|
4189
6711
|
on_event: (s.on_event || []).map(convertOnEvent)
|
|
4190
6712
|
}));
|
|
4191
6713
|
const fields = ir.fields.map((f) => ({
|
|
4192
|
-
name:
|
|
6714
|
+
name: toSnakeCase3(f.name),
|
|
4193
6715
|
field_type: f.type,
|
|
4194
6716
|
label: f.label || f.name.replace(/([A-Z])/g, " $1").replace(/^./, (c) => c.toUpperCase()),
|
|
4195
6717
|
required: f.required || false,
|
|
@@ -4205,16 +6727,16 @@ function emitWorkflowDefinition(extracted) {
|
|
|
4205
6727
|
...f.editable_when && { editable_when: f.editable_when },
|
|
4206
6728
|
...f.state_home && { state_home: f.state_home }
|
|
4207
6729
|
}));
|
|
4208
|
-
const transitions = ir.transitions.map((
|
|
4209
|
-
name:
|
|
4210
|
-
from:
|
|
4211
|
-
to:
|
|
4212
|
-
description:
|
|
4213
|
-
roles:
|
|
4214
|
-
auto:
|
|
4215
|
-
conditions:
|
|
4216
|
-
actions: (
|
|
4217
|
-
required_fields:
|
|
6730
|
+
const transitions = ir.transitions.map((t22) => ({
|
|
6731
|
+
name: t22.name,
|
|
6732
|
+
from: t22.from,
|
|
6733
|
+
to: t22.to,
|
|
6734
|
+
description: t22.description || "",
|
|
6735
|
+
roles: t22.roles || [],
|
|
6736
|
+
auto: t22.auto || false,
|
|
6737
|
+
conditions: t22.conditions || [],
|
|
6738
|
+
actions: (t22.actions || []).map(convertAction),
|
|
6739
|
+
required_fields: t22.required_fields || [],
|
|
4218
6740
|
priority: 0
|
|
4219
6741
|
}));
|
|
4220
6742
|
const state_data = {};
|
|
@@ -4232,7 +6754,7 @@ function emitWorkflowDefinition(extracted) {
|
|
|
4232
6754
|
if (extracted.fields.length > 0) {
|
|
4233
6755
|
const localDefaults = {};
|
|
4234
6756
|
for (const f of extracted.fields) {
|
|
4235
|
-
localDefaults[
|
|
6757
|
+
localDefaults[toSnakeCase3(f.name)] = f.default_value ?? null;
|
|
4236
6758
|
}
|
|
4237
6759
|
if (!viewRoot.config) viewRoot.config = {};
|
|
4238
6760
|
viewRoot.config.localDefaults = localDefaults;
|
|
@@ -4295,8 +6817,8 @@ function compilerStateToWorkflow(state, metadata) {
|
|
|
4295
6817
|
function resolveSlugArg(args, state) {
|
|
4296
6818
|
if (args.length < 1) return null;
|
|
4297
6819
|
const slugArg = args[0];
|
|
4298
|
-
if (
|
|
4299
|
-
if (
|
|
6820
|
+
if (t21.isStringLiteral(slugArg)) return slugArg.value;
|
|
6821
|
+
if (t21.isIdentifier(slugArg)) {
|
|
4300
6822
|
const compilerState = state;
|
|
4301
6823
|
const meta = compilerState.metadata;
|
|
4302
6824
|
const resolvedSlugs = meta.__modelImportSlugs;
|
|
@@ -4322,43 +6844,43 @@ function extractQueryDataSource(path, state) {
|
|
|
4322
6844
|
slug,
|
|
4323
6845
|
query: "list"
|
|
4324
6846
|
};
|
|
4325
|
-
if (args.length > 1 &&
|
|
6847
|
+
if (args.length > 1 && t21.isObjectExpression(args[1])) {
|
|
4326
6848
|
for (const prop of args[1].properties) {
|
|
4327
|
-
if (!
|
|
6849
|
+
if (!t21.isObjectProperty(prop) || !t21.isIdentifier(prop.key)) continue;
|
|
4328
6850
|
const key = prop.key.name;
|
|
4329
6851
|
const val = prop.value;
|
|
4330
6852
|
switch (key) {
|
|
4331
6853
|
case "limit":
|
|
4332
|
-
if (
|
|
6854
|
+
if (t21.isNumericLiteral(val)) {
|
|
4333
6855
|
dataSource.pageSize = val.value;
|
|
4334
6856
|
dataSource.paginated = true;
|
|
4335
6857
|
}
|
|
4336
6858
|
break;
|
|
4337
6859
|
case "orderBy":
|
|
4338
|
-
if (
|
|
6860
|
+
if (t21.isStringLiteral(val)) {
|
|
4339
6861
|
dataSource.sort = val.value;
|
|
4340
6862
|
}
|
|
4341
6863
|
break;
|
|
4342
6864
|
case "order":
|
|
4343
|
-
if (
|
|
6865
|
+
if (t21.isStringLiteral(val) && dataSource.sort) {
|
|
4344
6866
|
dataSource.sort = `${dataSource.sort}:${val.value}`;
|
|
4345
6867
|
}
|
|
4346
6868
|
break;
|
|
4347
6869
|
case "search":
|
|
4348
|
-
if (
|
|
6870
|
+
if (t21.isStringLiteral(val)) {
|
|
4349
6871
|
dataSource.search = val.value;
|
|
4350
6872
|
}
|
|
4351
6873
|
break;
|
|
4352
6874
|
case "searchFields":
|
|
4353
|
-
if (
|
|
4354
|
-
dataSource.searchFields = val.elements.filter((el) =>
|
|
6875
|
+
if (t21.isArrayExpression(val)) {
|
|
6876
|
+
dataSource.searchFields = val.elements.filter((el) => t21.isStringLiteral(el)).map((el) => el.value);
|
|
4355
6877
|
}
|
|
4356
6878
|
break;
|
|
4357
6879
|
case "filter":
|
|
4358
|
-
if (
|
|
6880
|
+
if (t21.isObjectExpression(val)) {
|
|
4359
6881
|
const filter = {};
|
|
4360
6882
|
for (const fp of val.properties) {
|
|
4361
|
-
if (
|
|
6883
|
+
if (t21.isObjectProperty(fp) && t21.isIdentifier(fp.key) && t21.isStringLiteral(fp.value)) {
|
|
4362
6884
|
filter[fp.key.name] = fp.value.value;
|
|
4363
6885
|
}
|
|
4364
6886
|
}
|
|
@@ -4368,19 +6890,19 @@ function extractQueryDataSource(path, state) {
|
|
|
4368
6890
|
}
|
|
4369
6891
|
break;
|
|
4370
6892
|
case "state":
|
|
4371
|
-
if (
|
|
6893
|
+
if (t21.isStringLiteral(val)) {
|
|
4372
6894
|
if (!dataSource.filter) dataSource.filter = {};
|
|
4373
6895
|
dataSource.filter.current_state = val.value;
|
|
4374
6896
|
}
|
|
4375
6897
|
break;
|
|
4376
6898
|
case "groupBy":
|
|
4377
|
-
if (
|
|
6899
|
+
if (t21.isStringLiteral(val)) {
|
|
4378
6900
|
dataSource.groupBy = val.value;
|
|
4379
6901
|
}
|
|
4380
6902
|
break;
|
|
4381
6903
|
case "facets":
|
|
4382
|
-
if (
|
|
4383
|
-
dataSource.facets = val.elements.filter((el) =>
|
|
6904
|
+
if (t21.isArrayExpression(val)) {
|
|
6905
|
+
dataSource.facets = val.elements.filter((el) => t21.isStringLiteral(el)).map((el) => el.value);
|
|
4384
6906
|
}
|
|
4385
6907
|
break;
|
|
4386
6908
|
}
|
|
@@ -4404,17 +6926,17 @@ function extractMutationDataSource(path, state) {
|
|
|
4404
6926
|
}
|
|
4405
6927
|
function extractDuringAction(path, state) {
|
|
4406
6928
|
const args = path.node.arguments;
|
|
4407
|
-
if (args.length < 1 || !
|
|
6929
|
+
if (args.length < 1 || !t21.isObjectExpression(args[0])) return;
|
|
4408
6930
|
const compilerState = state;
|
|
4409
6931
|
const config = args[0];
|
|
4410
6932
|
let stateName;
|
|
4411
6933
|
let intervalMs = 1e3;
|
|
4412
6934
|
for (const prop of config.properties) {
|
|
4413
|
-
if (!
|
|
4414
|
-
if (prop.key.name === "state" &&
|
|
6935
|
+
if (!t21.isObjectProperty(prop) || !t21.isIdentifier(prop.key)) continue;
|
|
6936
|
+
if (prop.key.name === "state" && t21.isStringLiteral(prop.value)) {
|
|
4415
6937
|
stateName = prop.value.value;
|
|
4416
6938
|
}
|
|
4417
|
-
if (prop.key.name === "intervalMs" &&
|
|
6939
|
+
if (prop.key.name === "intervalMs" && t21.isNumericLiteral(prop.value)) {
|
|
4418
6940
|
intervalMs = prop.value.value;
|
|
4419
6941
|
}
|
|
4420
6942
|
}
|
|
@@ -4440,7 +6962,7 @@ function extractDuringAction(path, state) {
|
|
|
4440
6962
|
}
|
|
4441
6963
|
function extractRoleDependency(path, state) {
|
|
4442
6964
|
const args = path.node.arguments;
|
|
4443
|
-
if (args.length < 1 || !
|
|
6965
|
+
if (args.length < 1 || !t21.isStringLiteral(args[0])) return;
|
|
4444
6966
|
const compilerState = state;
|
|
4445
6967
|
if (!compilerState.metadata) compilerState.metadata = {};
|
|
4446
6968
|
const meta = compilerState.metadata;
|
|
@@ -4451,7 +6973,7 @@ function extractRoleDependency(path, state) {
|
|
|
4451
6973
|
}
|
|
4452
6974
|
function extractViewDependency(path, state) {
|
|
4453
6975
|
const args = path.node.arguments;
|
|
4454
|
-
if (args.length < 1 || !
|
|
6976
|
+
if (args.length < 1 || !t21.isStringLiteral(args[0])) return;
|
|
4455
6977
|
const compilerState = state;
|
|
4456
6978
|
if (!compilerState.metadata) compilerState.metadata = {};
|
|
4457
6979
|
const meta = compilerState.metadata;
|
|
@@ -4468,7 +6990,7 @@ function extractParamsUsage(_path, state) {
|
|
|
4468
6990
|
}
|
|
4469
6991
|
function extractLibraryDependency(path, state) {
|
|
4470
6992
|
const args = path.node.arguments;
|
|
4471
|
-
if (args.length < 1 || !
|
|
6993
|
+
if (args.length < 1 || !t21.isStringLiteral(args[0])) return;
|
|
4472
6994
|
const compilerState = state;
|
|
4473
6995
|
if (!compilerState.metadata) compilerState.metadata = {};
|
|
4474
6996
|
const meta = compilerState.metadata;
|
|
@@ -4548,15 +7070,15 @@ function createVisitor(options = {}) {
|
|
|
4548
7070
|
}
|
|
4549
7071
|
}
|
|
4550
7072
|
const exportDeclaration = program.body.find(
|
|
4551
|
-
(node) =>
|
|
7073
|
+
(node) => t21.isExportNamedDeclaration(node) || t21.isExportDefaultDeclaration(node)
|
|
4552
7074
|
);
|
|
4553
7075
|
if (exportDeclaration) {
|
|
4554
7076
|
if (exportDeclaration.leadingComments) {
|
|
4555
7077
|
extractMetadataFromComments(exportDeclaration.leadingComments, compilerState.metadata);
|
|
4556
7078
|
}
|
|
4557
|
-
if (
|
|
7079
|
+
if (t21.isExportNamedDeclaration(exportDeclaration)) {
|
|
4558
7080
|
const declaration = exportDeclaration.declaration;
|
|
4559
|
-
if (
|
|
7081
|
+
if (t21.isFunctionDeclaration(declaration)) {
|
|
4560
7082
|
if (declaration.id) {
|
|
4561
7083
|
compilerState.metadata.name = declaration.id.name;
|
|
4562
7084
|
}
|
|
@@ -4564,16 +7086,16 @@ function createVisitor(options = {}) {
|
|
|
4564
7086
|
extractMetadataFromComments(declaration.leadingComments, compilerState.metadata);
|
|
4565
7087
|
}
|
|
4566
7088
|
}
|
|
4567
|
-
} else if (
|
|
7089
|
+
} else if (t21.isExportDefaultDeclaration(exportDeclaration)) {
|
|
4568
7090
|
const declaration = exportDeclaration.declaration;
|
|
4569
|
-
if (
|
|
7091
|
+
if (t21.isFunctionDeclaration(declaration)) {
|
|
4570
7092
|
if (declaration.id) {
|
|
4571
7093
|
compilerState.metadata.name = declaration.id.name;
|
|
4572
7094
|
}
|
|
4573
7095
|
if (declaration.leadingComments) {
|
|
4574
7096
|
extractMetadataFromComments(declaration.leadingComments, compilerState.metadata);
|
|
4575
7097
|
}
|
|
4576
|
-
} else if (
|
|
7098
|
+
} else if (t21.isIdentifier(declaration)) {
|
|
4577
7099
|
compilerState.metadata.name = declaration.name;
|
|
4578
7100
|
}
|
|
4579
7101
|
}
|
|
@@ -4584,7 +7106,13 @@ function createVisitor(options = {}) {
|
|
|
4584
7106
|
compilerState.metadata.__slugAutoFallback = true;
|
|
4585
7107
|
}
|
|
4586
7108
|
Object.assign(state, compilerState);
|
|
4587
|
-
if (
|
|
7109
|
+
if (isImperativeWorkflowFile(_path, state.filename)) {
|
|
7110
|
+
extractImperativeWorkflow(_path, state);
|
|
7111
|
+
state.__isModelFile = true;
|
|
7112
|
+
if (!compilerState.metadata.category) {
|
|
7113
|
+
compilerState.metadata.category = "workflow";
|
|
7114
|
+
}
|
|
7115
|
+
} else if (isModelFile(_path, state.filename)) {
|
|
4588
7116
|
extractModelFile(_path, state);
|
|
4589
7117
|
state.__isModelFile = true;
|
|
4590
7118
|
if (!compilerState.metadata.category) {
|
|
@@ -4595,6 +7123,15 @@ function createVisitor(options = {}) {
|
|
|
4595
7123
|
if (hasContextCreation(_path)) {
|
|
4596
7124
|
extractContextWorkflows(_path, state);
|
|
4597
7125
|
}
|
|
7126
|
+
if (hasMiddleware(_path)) {
|
|
7127
|
+
extractMiddleware(_path, state);
|
|
7128
|
+
}
|
|
7129
|
+
if (hasConstraints(_path)) {
|
|
7130
|
+
extractConstraints(_path, state);
|
|
7131
|
+
}
|
|
7132
|
+
if (hasActorConfig(_path)) {
|
|
7133
|
+
extractActorConfig(_path, state);
|
|
7134
|
+
}
|
|
4598
7135
|
if (isServerActionFile(state.filename)) {
|
|
4599
7136
|
extractServerActions(_path, state);
|
|
4600
7137
|
state.__isServerActionFile = true;
|
|
@@ -4630,7 +7167,7 @@ function createVisitor(options = {}) {
|
|
|
4630
7167
|
// Main hook extraction dispatcher
|
|
4631
7168
|
CallExpression(path, state) {
|
|
4632
7169
|
const callee = path.node.callee;
|
|
4633
|
-
if (!
|
|
7170
|
+
if (!t21.isIdentifier(callee)) return;
|
|
4634
7171
|
const compilerState = state;
|
|
4635
7172
|
const hookName = callee.name;
|
|
4636
7173
|
if (mode === "strict" && STRICT_BANNED_HOOKS[hookName]) {
|
|
@@ -4722,13 +7259,13 @@ function createVisitor(options = {}) {
|
|
|
4722
7259
|
if (!meta.__modelImports) meta.__modelImports = {};
|
|
4723
7260
|
const imports = meta.__modelImports;
|
|
4724
7261
|
for (const specifier of path.node.specifiers) {
|
|
4725
|
-
if (
|
|
7262
|
+
if (t21.isImportDefaultSpecifier(specifier) || t21.isImportSpecifier(specifier)) {
|
|
4726
7263
|
imports[specifier.local.name] = source;
|
|
4727
7264
|
}
|
|
4728
7265
|
}
|
|
4729
7266
|
}
|
|
4730
7267
|
if (mode !== "strict") return;
|
|
4731
|
-
if (source.startsWith("@mindmatrix/") || source === "react" || source.startsWith("react/") || source.startsWith(".") || source.startsWith("/")) {
|
|
7268
|
+
if (source.startsWith("@mindmatrix/") || source.startsWith("@mmapp/") || source === "react" || source.startsWith("react/") || source.startsWith(".") || source.startsWith("/")) {
|
|
4732
7269
|
return;
|
|
4733
7270
|
}
|
|
4734
7271
|
const error = {
|
|
@@ -4755,8 +7292,8 @@ function createVisitor(options = {}) {
|
|
|
4755
7292
|
if (!compilerState.metadata) return;
|
|
4756
7293
|
const id = path.node.id;
|
|
4757
7294
|
const init = path.node.init;
|
|
4758
|
-
if (
|
|
4759
|
-
if (!
|
|
7295
|
+
if (t21.isArrayPattern(id)) return;
|
|
7296
|
+
if (!t21.isIdentifier(id) || !init || !t21.isExpression(init)) return;
|
|
4760
7297
|
const parentFn = path.getFunctionParent();
|
|
4761
7298
|
if (!parentFn) return;
|
|
4762
7299
|
const parentNode = parentFn.parentPath;
|
|
@@ -4764,17 +7301,17 @@ function createVisitor(options = {}) {
|
|
|
4764
7301
|
let isExportedByName = false;
|
|
4765
7302
|
if (!isExportedDirectly && parentNode?.isVariableDeclarator()) {
|
|
4766
7303
|
const varId = parentNode.node.id;
|
|
4767
|
-
if (
|
|
7304
|
+
if (t21.isIdentifier(varId)) {
|
|
4768
7305
|
isExportedByName = varId.name === compilerState.metadata?.name;
|
|
4769
7306
|
}
|
|
4770
7307
|
}
|
|
4771
7308
|
if (!isExportedDirectly && !isExportedByName) return;
|
|
4772
|
-
if (
|
|
7309
|
+
if (t21.isCallExpression(init) && t21.isIdentifier(init.callee)) {
|
|
4773
7310
|
const callee = init.callee.name;
|
|
4774
7311
|
if (callee === "useQuery") {
|
|
4775
|
-
registerDerivedVar(id.name,
|
|
4776
|
-
|
|
4777
|
-
|
|
7312
|
+
registerDerivedVar(id.name, t21.optionalMemberExpression(
|
|
7313
|
+
t21.identifier("$instance"),
|
|
7314
|
+
t21.identifier(id.name),
|
|
4778
7315
|
false,
|
|
4779
7316
|
// computed
|
|
4780
7317
|
true
|
|
@@ -4783,23 +7320,23 @@ function createVisitor(options = {}) {
|
|
|
4783
7320
|
return;
|
|
4784
7321
|
}
|
|
4785
7322
|
if (callee === "useMutation") {
|
|
4786
|
-
registerDerivedVar(id.name,
|
|
4787
|
-
|
|
4788
|
-
|
|
7323
|
+
registerDerivedVar(id.name, t21.memberExpression(
|
|
7324
|
+
t21.identifier("$action"),
|
|
7325
|
+
t21.identifier("transition")
|
|
4789
7326
|
));
|
|
4790
7327
|
return;
|
|
4791
7328
|
}
|
|
4792
7329
|
if (callee === "useServerAction") {
|
|
4793
|
-
registerDerivedVar(id.name,
|
|
4794
|
-
|
|
4795
|
-
|
|
7330
|
+
registerDerivedVar(id.name, t21.memberExpression(
|
|
7331
|
+
t21.identifier("$action"),
|
|
7332
|
+
t21.identifier("serverAction")
|
|
4796
7333
|
));
|
|
4797
7334
|
return;
|
|
4798
7335
|
}
|
|
4799
7336
|
if (callee === "useServerState") {
|
|
4800
|
-
registerDerivedVar(id.name,
|
|
4801
|
-
|
|
4802
|
-
|
|
7337
|
+
registerDerivedVar(id.name, t21.optionalMemberExpression(
|
|
7338
|
+
t21.identifier("$instance"),
|
|
7339
|
+
t21.identifier("serverState"),
|
|
4803
7340
|
false,
|
|
4804
7341
|
true
|
|
4805
7342
|
));
|
|
@@ -4807,12 +7344,12 @@ function createVisitor(options = {}) {
|
|
|
4807
7344
|
}
|
|
4808
7345
|
if (callee === "useMemo" && init.arguments.length >= 1) {
|
|
4809
7346
|
const callback = init.arguments[0];
|
|
4810
|
-
if (
|
|
4811
|
-
if (
|
|
7347
|
+
if (t21.isArrowFunctionExpression(callback)) {
|
|
7348
|
+
if (t21.isExpression(callback.body)) {
|
|
4812
7349
|
registerDerivedVar(id.name, callback.body);
|
|
4813
|
-
} else if (
|
|
4814
|
-
const retStmt = callback.body.body.find((s) =>
|
|
4815
|
-
if (retStmt?.argument &&
|
|
7350
|
+
} else if (t21.isBlockStatement(callback.body)) {
|
|
7351
|
+
const retStmt = callback.body.body.find((s) => t21.isReturnStatement(s));
|
|
7352
|
+
if (retStmt?.argument && t21.isExpression(retStmt.argument)) {
|
|
4816
7353
|
registerDerivedVar(id.name, retStmt.argument);
|
|
4817
7354
|
}
|
|
4818
7355
|
}
|
|
@@ -4827,7 +7364,7 @@ function createVisitor(options = {}) {
|
|
|
4827
7364
|
// Only extract from the exported component function's direct return,
|
|
4828
7365
|
// not from nested callbacks (Each render functions, helper components, etc.).
|
|
4829
7366
|
ReturnStatement(path, state) {
|
|
4830
|
-
if (!
|
|
7367
|
+
if (!t21.isJSXElement(path.node.argument) && !t21.isJSXFragment(path.node.argument)) return;
|
|
4831
7368
|
const parentFn = path.getFunctionParent();
|
|
4832
7369
|
if (!parentFn) return;
|
|
4833
7370
|
const parentNode = parentFn.parentPath;
|
|
@@ -4835,7 +7372,7 @@ function createVisitor(options = {}) {
|
|
|
4835
7372
|
let isExportedByName = false;
|
|
4836
7373
|
if (!isExportedDirectly && parentNode?.isVariableDeclarator()) {
|
|
4837
7374
|
const varId = parentNode.node.id;
|
|
4838
|
-
if (
|
|
7375
|
+
if (t21.isIdentifier(varId)) {
|
|
4839
7376
|
isExportedByName = varId.name === state.metadata?.name;
|
|
4840
7377
|
}
|
|
4841
7378
|
}
|