@mmapp/react-compiler 0.1.0-alpha.3 → 0.1.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth-3UK75242.mjs +17 -0
- package/dist/babel/index.d.mts +2 -2
- package/dist/babel/index.d.ts +2 -2
- package/dist/babel/index.js +2736 -306
- package/dist/babel/index.mjs +1 -1
- package/dist/chunk-52XHYD2V.mjs +214 -0
- package/dist/chunk-5FTDWKHH.mjs +244 -0
- package/dist/chunk-5GUFFFGL.mjs +148 -0
- package/dist/chunk-7JRAEFRB.mjs +7510 -0
- package/dist/chunk-7T6Q5KAA.mjs +7506 -0
- package/dist/chunk-ABYPKRSB.mjs +215 -0
- package/dist/chunk-BZEXUPDH.mjs +175 -0
- package/dist/chunk-EO6SYNCG.mjs +175 -0
- package/dist/chunk-HRYR54PT.mjs +175 -0
- package/dist/chunk-J3M4GUS7.mjs +161 -0
- package/dist/chunk-J7JUAHS4.mjs +186 -0
- package/dist/chunk-JRGFBWTN.mjs +2918 -0
- package/dist/chunk-NTB7OEX2.mjs +2918 -0
- package/dist/chunk-O4AUS7EU.mjs +148 -0
- package/dist/chunk-OPJKP747.mjs +7506 -0
- package/dist/chunk-R2DD5GTY.mjs +186 -0
- package/dist/chunk-THFYE5ZX.mjs +244 -0
- package/dist/chunk-UDDTWG5J.mjs +734 -0
- package/dist/chunk-VLTKQDJ3.mjs +244 -0
- package/dist/chunk-WBYMW4NQ.mjs +3450 -0
- package/dist/chunk-WVYY32LD.mjs +939 -0
- package/dist/chunk-XDVM4YHX.mjs +3450 -0
- package/dist/chunk-Z2G5RZ4H.mjs +186 -0
- package/dist/chunk-ZE3KCHBM.mjs +2918 -0
- package/dist/cli/index.js +10378 -4107
- package/dist/cli/index.mjs +224 -183
- package/dist/codemod/cli.js +1 -1
- package/dist/codemod/cli.mjs +1 -1
- package/dist/codemod/index.d.mts +3 -3
- package/dist/codemod/index.d.ts +3 -3
- package/dist/codemod/index.js +1 -1
- package/dist/codemod/index.mjs +1 -1
- package/dist/config-PL24KEWL.mjs +219 -0
- package/dist/deploy-YAJGW6II.mjs +9 -0
- package/dist/dev-server-CrQ041KP.d.mts +79 -0
- package/dist/dev-server-CrQ041KP.d.ts +79 -0
- package/dist/dev-server.d.mts +2 -2
- package/dist/dev-server.d.ts +2 -2
- package/dist/dev-server.js +4319 -421
- package/dist/dev-server.mjs +4 -4
- package/dist/envelope-ChEkuHij.d.mts +265 -0
- package/dist/envelope-ChEkuHij.d.ts +265 -0
- package/dist/envelope.d.mts +2 -2
- package/dist/envelope.d.ts +2 -2
- package/dist/envelope.js +2734 -304
- package/dist/envelope.mjs +2 -2
- package/dist/index-CEKyyazf.d.mts +104 -0
- package/dist/index-CEKyyazf.d.ts +104 -0
- package/dist/index.d.mts +164 -9
- package/dist/index.d.ts +164 -9
- package/dist/index.js +4730 -734
- package/dist/index.mjs +216 -8
- package/dist/init-7FJENUDK.mjs +407 -0
- package/dist/init-DQDX3QK6.mjs +369 -0
- package/dist/project-compiler-NNK32MPG.mjs +10 -0
- package/dist/project-compiler-OP2VVGJQ.mjs +10 -0
- package/dist/project-compiler-ZB4RUYVL.mjs +10 -0
- package/dist/project-decompiler-U55HQUHW.mjs +7 -0
- package/dist/project-decompiler-US7GAVIC.mjs +7 -0
- package/dist/pull-KOL2QAYQ.mjs +109 -0
- package/dist/pull-P44LDRWB.mjs +109 -0
- package/dist/seed-KOGEPGOJ.mjs +154 -0
- package/dist/server-VW6UPCHO.mjs +277 -0
- package/dist/testing/index.d.mts +8 -8
- package/dist/testing/index.d.ts +8 -8
- package/dist/testing/index.js +2744 -314
- package/dist/testing/index.mjs +1 -1
- package/dist/verify-BYHUKARQ.mjs +1833 -0
- package/dist/verify-OQDEQYMS.mjs +1833 -0
- package/dist/verify-SEIXUGN4.mjs +1833 -0
- package/dist/vite/index.d.mts +1 -1
- package/dist/vite/index.d.ts +1 -1
- package/dist/vite/index.js +2735 -305
- package/dist/vite/index.mjs +2 -2
- package/examples/authentication/main.workflow.tsx +1 -1
- package/examples/authentication/mm.config.ts +1 -1
- package/examples/authentication/pages/LoginPage.tsx +2 -2
- package/examples/authentication/pages/SignupPage.tsx +2 -2
- package/examples/counter.workflow.tsx +1 -1
- package/examples/dashboard.workflow.tsx +1 -1
- package/examples/invoice-approval/actions/invoice.server.ts +1 -1
- package/examples/invoice-approval/main.workflow.tsx +1 -1
- package/examples/invoice-approval/mm.config.ts +1 -1
- package/examples/invoice-approval/pages/InvoiceDetailPage.tsx +1 -1
- package/examples/invoice-approval/pages/InvoiceFormPage.tsx +1 -1
- package/examples/invoice-approval/pages/InvoiceListPage.tsx +1 -1
- package/examples/todo-app.workflow.tsx +1 -1
- package/examples/uber-app/actions/matching.server.ts +1 -1
- package/examples/uber-app/actions/notifications.server.ts +1 -1
- package/examples/uber-app/actions/payments.server.ts +1 -1
- package/examples/uber-app/actions/pricing.server.ts +1 -1
- package/examples/uber-app/app/admin/analytics.tsx +2 -2
- package/examples/uber-app/app/admin/fleet.tsx +2 -2
- package/examples/uber-app/app/admin/surge-pricing.tsx +2 -2
- package/examples/uber-app/app/driver/dashboard.tsx +2 -2
- package/examples/uber-app/app/driver/earnings.tsx +2 -2
- package/examples/uber-app/app/driver/navigation.tsx +2 -2
- package/examples/uber-app/app/driver/ride-acceptance.tsx +2 -2
- package/examples/uber-app/app/rider/home.tsx +2 -2
- package/examples/uber-app/app/rider/payment-methods.tsx +2 -2
- package/examples/uber-app/app/rider/ride-history.tsx +2 -2
- package/examples/uber-app/app/rider/ride-tracking.tsx +2 -2
- package/examples/uber-app/components/DriverCard.tsx +1 -1
- package/examples/uber-app/components/MapView.tsx +3 -3
- package/examples/uber-app/components/RatingStars.tsx +2 -2
- package/examples/uber-app/components/RideCard.tsx +1 -1
- package/examples/uber-app/mm.config.ts +1 -1
- package/examples/uber-app/workflows/dispute-resolution.workflow.tsx +2 -2
- package/examples/uber-app/workflows/driver-onboarding.workflow.tsx +2 -2
- package/examples/uber-app/workflows/payment-processing.workflow.tsx +2 -2
- package/examples/uber-app/workflows/ride-request.workflow.tsx +2 -2
- package/package.json +8 -3
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
|
}
|
|
@@ -2877,6 +2877,7 @@ function extractDefineModelCall(programPath, compilerState, actionCounter) {
|
|
|
2877
2877
|
const on_exit = parseActionArray(stateConfig.on_exit, actionCounter);
|
|
2878
2878
|
const during = parseDuringArray(stateConfig.during, actionCounter);
|
|
2879
2879
|
const on_event = parseOnEventArray(stateConfig.on_event, actionCounter);
|
|
2880
|
+
const stateRuntime = stateConfig.runtime;
|
|
2880
2881
|
if (!compilerState.states.has(name)) {
|
|
2881
2882
|
compilerState.states.set(name, {
|
|
2882
2883
|
name,
|
|
@@ -2885,7 +2886,8 @@ function extractDefineModelCall(programPath, compilerState, actionCounter) {
|
|
|
2885
2886
|
on_enter,
|
|
2886
2887
|
during,
|
|
2887
2888
|
on_exit,
|
|
2888
|
-
...on_event.length > 0 ? { on_event } : {}
|
|
2889
|
+
...on_event.length > 0 ? { on_event } : {},
|
|
2890
|
+
...stateRuntime ? { runtime: stateRuntime } : {}
|
|
2889
2891
|
});
|
|
2890
2892
|
} else {
|
|
2891
2893
|
const existing = compilerState.states.get(name);
|
|
@@ -2939,6 +2941,7 @@ function extractDefineModelCall(programPath, compilerState, actionCounter) {
|
|
|
2939
2941
|
}
|
|
2940
2942
|
}
|
|
2941
2943
|
const actions = parseActionArray(transConfig.actions, actionCounter);
|
|
2944
|
+
const transRuntime = transConfig.runtime;
|
|
2942
2945
|
compilerState.transitions.push({
|
|
2943
2946
|
name,
|
|
2944
2947
|
from,
|
|
@@ -2948,7 +2951,8 @@ function extractDefineModelCall(programPath, compilerState, actionCounter) {
|
|
|
2948
2951
|
actions,
|
|
2949
2952
|
roles: transConfig.roles,
|
|
2950
2953
|
auto: transConfig.auto,
|
|
2951
|
-
required_fields: transConfig.required_fields
|
|
2954
|
+
required_fields: transConfig.required_fields,
|
|
2955
|
+
...transRuntime ? { runtime: transRuntime } : {}
|
|
2952
2956
|
});
|
|
2953
2957
|
}
|
|
2954
2958
|
}
|
|
@@ -2965,6 +2969,9 @@ function extractDefineModelCall(programPath, compilerState, actionCounter) {
|
|
|
2965
2969
|
if (config.metadata && typeof config.metadata === "object") {
|
|
2966
2970
|
compilerState.metadata.modelMetadata = config.metadata;
|
|
2967
2971
|
}
|
|
2972
|
+
if (config.orchestration && typeof config.orchestration === "object" && !Array.isArray(config.orchestration)) {
|
|
2973
|
+
compilerState.metadata.orchestration = config.orchestration;
|
|
2974
|
+
}
|
|
2968
2975
|
return true;
|
|
2969
2976
|
}
|
|
2970
2977
|
return false;
|
|
@@ -3139,195 +3146,2051 @@ function extractModelFile(path, state) {
|
|
|
3139
3146
|
}
|
|
3140
3147
|
}
|
|
3141
3148
|
|
|
3142
|
-
// src/babel/extractors/
|
|
3149
|
+
// src/babel/extractors/flow-extractor.ts
|
|
3143
3150
|
var t12 = __toESM(require("@babel/types"));
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
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
|
+
};
|
|
3147
3161
|
}
|
|
3148
|
-
function
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
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++;
|
|
3160
3234
|
}
|
|
3161
3235
|
}
|
|
3162
|
-
if (
|
|
3163
|
-
for (const
|
|
3164
|
-
if (
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
const firstParam = init.params[0];
|
|
3174
|
-
if (t12.isIdentifier(firstParam) && firstParam.typeAnnotation) {
|
|
3175
|
-
action.contextType = extractTypeName(firstParam.typeAnnotation);
|
|
3176
|
-
}
|
|
3177
|
-
}
|
|
3178
|
-
serverActions.push(action);
|
|
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);
|
|
3179
3247
|
}
|
|
3180
3248
|
}
|
|
3249
|
+
lastState = targets[targets.length > 1 ? 0 : 0];
|
|
3250
|
+
if (targets.length === 1) {
|
|
3251
|
+
lastState = targets[0];
|
|
3252
|
+
}
|
|
3253
|
+
i = nextIdx - 1;
|
|
3181
3254
|
}
|
|
3182
3255
|
}
|
|
3183
3256
|
}
|
|
3184
|
-
if (serverActions.length > 0) {
|
|
3185
|
-
if (!compilerState.metadata) compilerState.metadata = {};
|
|
3186
|
-
compilerState.metadata.serverActions = serverActions;
|
|
3187
|
-
}
|
|
3188
3257
|
}
|
|
3189
|
-
function
|
|
3190
|
-
|
|
3191
|
-
const
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
const
|
|
3198
|
-
|
|
3199
|
-
|
|
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);
|
|
3294
|
+
}
|
|
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);
|
|
3304
|
+
}
|
|
3305
|
+
}
|
|
3200
3306
|
}
|
|
3201
3307
|
}
|
|
3202
|
-
return
|
|
3308
|
+
return { stateNames: allStateNames, transitions: dedupeTransitions(allTransitions) };
|
|
3203
3309
|
}
|
|
3204
|
-
function
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
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);
|
|
3209
3320
|
}
|
|
3210
3321
|
}
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
if (
|
|
3216
|
-
|
|
3217
|
-
for (const line of lines) {
|
|
3218
|
-
const trimmed = line.replace(/^\s*\*\s?/, "").trim();
|
|
3219
|
-
if (trimmed && !trimmed.startsWith("@")) {
|
|
3220
|
-
return trimmed;
|
|
3221
|
-
}
|
|
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";
|
|
3222
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 || "";
|
|
3223
3401
|
}
|
|
3224
|
-
|
|
3402
|
+
const { states, transitions } = parseArrowSyntax(arrow);
|
|
3403
|
+
return { slug, fields, states, transitions };
|
|
3225
3404
|
}
|
|
3226
3405
|
|
|
3227
|
-
// src/babel/extractors/
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
if (!t13.isObjectProperty(prop) || !t13.isIdentifier(prop.key)) continue;
|
|
3241
|
-
if (prop.key.name === "instanceId" && t13.isStringLiteral(prop.value)) {
|
|
3242
|
-
entry.staticInstanceId = prop.value.value;
|
|
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;
|
|
3243
3419
|
}
|
|
3244
3420
|
}
|
|
3245
3421
|
}
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3422
|
+
return false;
|
|
3423
|
+
}
|
|
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";
|
|
3249
3458
|
}
|
|
3250
|
-
if (
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
meta.serverActionHooks.push(entry);
|
|
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";
|
|
3254
3462
|
}
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
const entry = {};
|
|
3263
|
-
const instanceArg = args[0];
|
|
3264
|
-
if (t14.isStringLiteral(instanceArg)) {
|
|
3265
|
-
entry.staticInstanceId = instanceArg.value;
|
|
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);
|
|
3469
|
+
}
|
|
3266
3470
|
}
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3471
|
+
return options.length > 0 ? options : void 0;
|
|
3472
|
+
}
|
|
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 };
|
|
3272
3494
|
}
|
|
3273
3495
|
}
|
|
3496
|
+
fields.push(field);
|
|
3274
3497
|
}
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3498
|
+
return fields;
|
|
3499
|
+
}
|
|
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);
|
|
3284
3538
|
}
|
|
3539
|
+
return obj;
|
|
3285
3540
|
}
|
|
3286
|
-
if (
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3541
|
+
if (t12.isTemplateLiteral(node)) {
|
|
3542
|
+
return node.quasis.map((q) => q.value.raw).join("${}");
|
|
3543
|
+
}
|
|
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]";
|
|
3291
3556
|
}
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
const
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
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
|
+
});
|
|
3591
|
+
}
|
|
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
|
+
});
|
|
3314
3607
|
}
|
|
3315
3608
|
}
|
|
3316
|
-
|
|
3317
|
-
|
|
3609
|
+
return;
|
|
3610
|
+
}
|
|
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);
|
|
3615
|
+
}
|
|
3318
3616
|
}
|
|
3319
|
-
policies.push(policy);
|
|
3320
3617
|
}
|
|
3321
|
-
return { policies };
|
|
3322
3618
|
}
|
|
3323
|
-
function
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
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("@mmapp/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 = [];
|
|
5161
|
+
const policyRegex = /(permit|forbid)\s*\(([^)]*)\)(?:\s*when\s*\{([^}]*)\})?/g;
|
|
5162
|
+
let match;
|
|
5163
|
+
while ((match = policyRegex.exec(source)) !== null) {
|
|
5164
|
+
const [, effect, scope, condition] = match;
|
|
5165
|
+
const parts = scope.split(",").map((s) => s.trim());
|
|
5166
|
+
const policy = {
|
|
5167
|
+
effect,
|
|
5168
|
+
conditions: []
|
|
5169
|
+
};
|
|
5170
|
+
for (const part of parts) {
|
|
5171
|
+
if (part.startsWith("principal")) {
|
|
5172
|
+
policy.principal = part;
|
|
5173
|
+
} else if (part.startsWith("action")) {
|
|
5174
|
+
policy.action = part;
|
|
5175
|
+
} else if (part.startsWith("resource")) {
|
|
5176
|
+
policy.resource = part;
|
|
5177
|
+
}
|
|
5178
|
+
}
|
|
5179
|
+
if (condition) {
|
|
5180
|
+
policy.conditions.push(condition.trim());
|
|
5181
|
+
}
|
|
5182
|
+
policies.push(policy);
|
|
5183
|
+
}
|
|
5184
|
+
return { policies };
|
|
5185
|
+
}
|
|
5186
|
+
function parseCron(source) {
|
|
5187
|
+
const trimmed = source.trim();
|
|
5188
|
+
const parts = trimmed.split(/\s+/);
|
|
5189
|
+
const valid = parts.length === 5;
|
|
5190
|
+
return {
|
|
5191
|
+
expression: trimmed,
|
|
5192
|
+
fields: {
|
|
5193
|
+
minute: parts[0] || "*",
|
|
3331
5194
|
hour: parts[1] || "*",
|
|
3332
5195
|
dayOfMonth: parts[2] || "*",
|
|
3333
5196
|
month: parts[3] || "*",
|
|
@@ -3372,7 +5235,7 @@ function parseDmn(source) {
|
|
|
3372
5235
|
}
|
|
3373
5236
|
function extractGrammarIsland(path, state, slug) {
|
|
3374
5237
|
const tag = path.node.tag;
|
|
3375
|
-
if (!
|
|
5238
|
+
if (!t16.isIdentifier(tag)) return;
|
|
3376
5239
|
const tagName = tag.name;
|
|
3377
5240
|
if (!GRAMMAR_TAGS.has(tagName)) return;
|
|
3378
5241
|
const compilerState = state;
|
|
@@ -3382,7 +5245,7 @@ function extractGrammarIsland(path, state, slug) {
|
|
|
3382
5245
|
rawSource += quasi.quasis[i].value.raw;
|
|
3383
5246
|
if (i < quasi.expressions.length) {
|
|
3384
5247
|
const expr = quasi.expressions[i];
|
|
3385
|
-
if (
|
|
5248
|
+
if (t16.isIdentifier(expr)) {
|
|
3386
5249
|
rawSource += `\${${expr.name}}`;
|
|
3387
5250
|
} else {
|
|
3388
5251
|
rawSource += `\${expr_${i}}`;
|
|
@@ -3426,16 +5289,16 @@ function extractGrammarIslands(path, state) {
|
|
|
3426
5289
|
path.traverse({
|
|
3427
5290
|
TaggedTemplateExpression(templatePath) {
|
|
3428
5291
|
const tag = templatePath.node.tag;
|
|
3429
|
-
if (!
|
|
5292
|
+
if (!t16.isIdentifier(tag) || !GRAMMAR_TAGS.has(tag.name)) return;
|
|
3430
5293
|
let slug = "unnamed";
|
|
3431
5294
|
const parent = templatePath.parentPath;
|
|
3432
|
-
if (parent && parent.isVariableDeclarator() &&
|
|
5295
|
+
if (parent && parent.isVariableDeclarator() && t16.isIdentifier(parent.node.id)) {
|
|
3433
5296
|
slug = parent.node.id.name;
|
|
3434
5297
|
}
|
|
3435
|
-
if (parent && parent.isObjectProperty() &&
|
|
5298
|
+
if (parent && parent.isObjectProperty() && t16.isIdentifier(parent.node.key)) {
|
|
3436
5299
|
slug = parent.node.key.name;
|
|
3437
5300
|
}
|
|
3438
|
-
if (parent && parent.isObjectProperty() &&
|
|
5301
|
+
if (parent && parent.isObjectProperty() && t16.isStringLiteral(parent.node.key)) {
|
|
3439
5302
|
slug = parent.node.key.value;
|
|
3440
5303
|
}
|
|
3441
5304
|
extractGrammarIsland(templatePath, state, slug);
|
|
@@ -3444,12 +5307,12 @@ function extractGrammarIslands(path, state) {
|
|
|
3444
5307
|
}
|
|
3445
5308
|
|
|
3446
5309
|
// src/babel/extractors/context-extractor.ts
|
|
3447
|
-
var
|
|
5310
|
+
var t17 = __toESM(require("@babel/types"));
|
|
3448
5311
|
function hasContextCreation(path) {
|
|
3449
5312
|
let found = false;
|
|
3450
5313
|
path.traverse({
|
|
3451
5314
|
CallExpression(callPath) {
|
|
3452
|
-
if (
|
|
5315
|
+
if (t17.isIdentifier(callPath.node.callee, { name: "createContext" })) {
|
|
3453
5316
|
found = true;
|
|
3454
5317
|
callPath.stop();
|
|
3455
5318
|
}
|
|
@@ -3465,9 +5328,9 @@ function extractContextWorkflows(path, state) {
|
|
|
3465
5328
|
// Detect: const XContext = createContext(...)
|
|
3466
5329
|
VariableDeclarator(declPath) {
|
|
3467
5330
|
const init = declPath.node.init;
|
|
3468
|
-
if (!init || !
|
|
3469
|
-
if (!
|
|
3470
|
-
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;
|
|
3471
5334
|
const contextName = declPath.node.id.name;
|
|
3472
5335
|
contextNames.set(contextName, contextName);
|
|
3473
5336
|
const workflow = {
|
|
@@ -3476,25 +5339,25 @@ function extractContextWorkflows(path, state) {
|
|
|
3476
5339
|
reducerActions: []
|
|
3477
5340
|
};
|
|
3478
5341
|
const typeParams = init.typeParameters;
|
|
3479
|
-
if (typeParams &&
|
|
5342
|
+
if (typeParams && t17.isTSTypeParameterInstantiation(typeParams)) {
|
|
3480
5343
|
const typeArg = typeParams.params[0];
|
|
3481
|
-
if (
|
|
5344
|
+
if (t17.isTSTypeReference(typeArg) && t17.isIdentifier(typeArg.typeName)) {
|
|
3482
5345
|
const interfaceName = typeArg.typeName.name;
|
|
3483
|
-
|
|
5346
|
+
extractFieldsFromInterface3(path, interfaceName, workflow);
|
|
3484
5347
|
}
|
|
3485
5348
|
}
|
|
3486
|
-
if (init.arguments.length > 0 &&
|
|
5349
|
+
if (init.arguments.length > 0 && t17.isObjectExpression(init.arguments[0])) {
|
|
3487
5350
|
workflow.initialState = extractObjectLiteral2(init.arguments[0]);
|
|
3488
5351
|
}
|
|
3489
5352
|
contextWorkflows.push(workflow);
|
|
3490
5353
|
},
|
|
3491
5354
|
// Detect useReducer(reducer, initialState) and extract reducer cases
|
|
3492
5355
|
CallExpression(callPath) {
|
|
3493
|
-
if (!
|
|
5356
|
+
if (!t17.isIdentifier(callPath.node.callee, { name: "useReducer" })) return;
|
|
3494
5357
|
const args = callPath.node.arguments;
|
|
3495
5358
|
if (args.length < 1) return;
|
|
3496
5359
|
const reducerArg = args[0];
|
|
3497
|
-
if (!
|
|
5360
|
+
if (!t17.isIdentifier(reducerArg)) return;
|
|
3498
5361
|
const reducerName = reducerArg.name;
|
|
3499
5362
|
const actions = extractReducerActions(path, reducerName);
|
|
3500
5363
|
if (contextWorkflows.length > 0) {
|
|
@@ -3510,13 +5373,13 @@ function extractContextWorkflows(path, state) {
|
|
|
3510
5373
|
meta.contextWorkflows = contextWorkflows;
|
|
3511
5374
|
}
|
|
3512
5375
|
}
|
|
3513
|
-
function
|
|
5376
|
+
function extractFieldsFromInterface3(path, interfaceName, workflow) {
|
|
3514
5377
|
path.traverse({
|
|
3515
5378
|
TSInterfaceDeclaration(ifacePath) {
|
|
3516
|
-
if (!
|
|
5379
|
+
if (!t17.isIdentifier(ifacePath.node.id, { name: interfaceName })) return;
|
|
3517
5380
|
for (const prop of ifacePath.node.body.body) {
|
|
3518
|
-
if (!
|
|
3519
|
-
if (!
|
|
5381
|
+
if (!t17.isTSPropertySignature(prop)) continue;
|
|
5382
|
+
if (!t17.isIdentifier(prop.key)) continue;
|
|
3520
5383
|
const field = {
|
|
3521
5384
|
name: prop.key.name,
|
|
3522
5385
|
type: extractTSType(prop.typeAnnotation),
|
|
@@ -3528,20 +5391,20 @@ function extractFieldsFromInterface2(path, interfaceName, workflow) {
|
|
|
3528
5391
|
});
|
|
3529
5392
|
}
|
|
3530
5393
|
function extractTSType(annotation) {
|
|
3531
|
-
if (!annotation || !
|
|
5394
|
+
if (!annotation || !t17.isTSTypeAnnotation(annotation)) return "unknown";
|
|
3532
5395
|
const typeNode = annotation.typeAnnotation;
|
|
3533
|
-
if (
|
|
3534
|
-
if (
|
|
3535
|
-
if (
|
|
3536
|
-
if (
|
|
3537
|
-
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;
|
|
3538
5401
|
return "unknown";
|
|
3539
5402
|
}
|
|
3540
5403
|
function extractTSTypeNode(node) {
|
|
3541
|
-
if (
|
|
3542
|
-
if (
|
|
3543
|
-
if (
|
|
3544
|
-
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;
|
|
3545
5408
|
return "unknown";
|
|
3546
5409
|
}
|
|
3547
5410
|
function extractReducerActions(path, reducerName) {
|
|
@@ -3553,7 +5416,7 @@ function extractReducerActions(path, reducerName) {
|
|
|
3553
5416
|
SwitchStatement(switchPath) {
|
|
3554
5417
|
for (const switchCase of switchPath.node.cases) {
|
|
3555
5418
|
if (!switchCase.test) continue;
|
|
3556
|
-
if (
|
|
5419
|
+
if (t17.isStringLiteral(switchCase.test)) {
|
|
3557
5420
|
actions.push({
|
|
3558
5421
|
type: switchCase.test.value
|
|
3559
5422
|
});
|
|
@@ -3568,24 +5431,576 @@ function extractReducerActions(path, reducerName) {
|
|
|
3568
5431
|
function extractObjectLiteral2(obj) {
|
|
3569
5432
|
const result = {};
|
|
3570
5433
|
for (const prop of obj.properties) {
|
|
3571
|
-
if (!
|
|
3572
|
-
if (
|
|
3573
|
-
else if (
|
|
3574
|
-
else if (
|
|
3575
|
-
else if (
|
|
3576
|
-
else if (
|
|
3577
|
-
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
|
+
}
|
|
3578
5753
|
}
|
|
3579
5754
|
return result;
|
|
3580
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
|
+
}
|
|
3581
5853
|
|
|
3582
|
-
//
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
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;
|
|
3587
5999
|
}
|
|
3588
6000
|
|
|
6001
|
+
// src/babel/emitters/pure-form-emitter.ts
|
|
6002
|
+
var import_player_core = require("@mmapp/player-core");
|
|
6003
|
+
|
|
3589
6004
|
// src/babel/emitters/experience-transform.ts
|
|
3590
6005
|
function transformToFrontend(node) {
|
|
3591
6006
|
const result = {
|
|
@@ -3803,7 +6218,7 @@ function normalizeViewNode(node, fieldNames) {
|
|
|
3803
6218
|
}
|
|
3804
6219
|
return node;
|
|
3805
6220
|
}
|
|
3806
|
-
function
|
|
6221
|
+
function toSnakeCase3(str) {
|
|
3807
6222
|
return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
3808
6223
|
}
|
|
3809
6224
|
function convertAction(action) {
|
|
@@ -3898,7 +6313,7 @@ function emitIR(extracted) {
|
|
|
3898
6313
|
if (fields.length > 0) {
|
|
3899
6314
|
const localDefaults = {};
|
|
3900
6315
|
for (const f of fields) {
|
|
3901
|
-
localDefaults[
|
|
6316
|
+
localDefaults[toSnakeCase3(f.name)] = f.default_value ?? null;
|
|
3902
6317
|
}
|
|
3903
6318
|
if (!normalizedView.config) normalizedView.config = {};
|
|
3904
6319
|
normalizedView.config.localDefaults = localDefaults;
|
|
@@ -3977,7 +6392,7 @@ function liftAction(action) {
|
|
|
3977
6392
|
}
|
|
3978
6393
|
return {
|
|
3979
6394
|
slug: action.id,
|
|
3980
|
-
category: normalizeCategory("expression", "mutation", action.type),
|
|
6395
|
+
category: (0, import_player_core.normalizeCategory)("expression", "mutation", action.type),
|
|
3981
6396
|
parts: parts.length > 0 ? parts : void 0
|
|
3982
6397
|
};
|
|
3983
6398
|
}
|
|
@@ -4007,7 +6422,7 @@ function liftSchedule(during) {
|
|
|
4007
6422
|
for (const action of during.actions) {
|
|
4008
6423
|
parts.push({
|
|
4009
6424
|
slug: "do",
|
|
4010
|
-
category: normalizeCategory("expression", "mutation", action.type),
|
|
6425
|
+
category: (0, import_player_core.normalizeCategory)("expression", "mutation", action.type),
|
|
4011
6426
|
parts: Object.entries(action.config || {}).map(([key, value]) => ({
|
|
4012
6427
|
slug: key,
|
|
4013
6428
|
category: ["atom"],
|
|
@@ -4017,7 +6432,7 @@ function liftSchedule(during) {
|
|
|
4017
6432
|
}
|
|
4018
6433
|
return {
|
|
4019
6434
|
slug: during.id,
|
|
4020
|
-
category: normalizeCategory("schedule", during.type),
|
|
6435
|
+
category: (0, import_player_core.normalizeCategory)("schedule", during.type),
|
|
4021
6436
|
parts
|
|
4022
6437
|
};
|
|
4023
6438
|
}
|
|
@@ -4030,14 +6445,14 @@ function liftState(state) {
|
|
|
4030
6445
|
if (state.on_enter && state.on_enter.length > 0) {
|
|
4031
6446
|
parts.push({
|
|
4032
6447
|
slug: "on_enter",
|
|
4033
|
-
category: normalizeCategory("expression", "sequence"),
|
|
6448
|
+
category: (0, import_player_core.normalizeCategory)("expression", "sequence"),
|
|
4034
6449
|
parts: state.on_enter.map(liftAction)
|
|
4035
6450
|
});
|
|
4036
6451
|
}
|
|
4037
6452
|
if (state.on_exit && state.on_exit.length > 0) {
|
|
4038
6453
|
parts.push({
|
|
4039
6454
|
slug: "on_exit",
|
|
4040
|
-
category: normalizeCategory("expression", "sequence"),
|
|
6455
|
+
category: (0, import_player_core.normalizeCategory)("expression", "sequence"),
|
|
4041
6456
|
parts: state.on_exit.map(liftAction)
|
|
4042
6457
|
});
|
|
4043
6458
|
}
|
|
@@ -4048,7 +6463,7 @@ function liftState(state) {
|
|
|
4048
6463
|
}
|
|
4049
6464
|
return {
|
|
4050
6465
|
slug: state.name,
|
|
4051
|
-
category: normalizeCategory("state", ...tags),
|
|
6466
|
+
category: (0, import_player_core.normalizeCategory)("state", ...tags),
|
|
4052
6467
|
parts: parts.length > 0 ? parts : void 0
|
|
4053
6468
|
};
|
|
4054
6469
|
}
|
|
@@ -4071,17 +6486,17 @@ function liftTransition(transition) {
|
|
|
4071
6486
|
if (transition.actions && transition.actions.length > 0) {
|
|
4072
6487
|
parts.push({
|
|
4073
6488
|
slug: "actions",
|
|
4074
|
-
category: normalizeCategory("expression", "sequence"),
|
|
6489
|
+
category: (0, import_player_core.normalizeCategory)("expression", "sequence"),
|
|
4075
6490
|
parts: transition.actions.map(liftAction)
|
|
4076
6491
|
});
|
|
4077
6492
|
}
|
|
4078
6493
|
if (transition.conditions && transition.conditions.length > 0) {
|
|
4079
6494
|
parts.push({
|
|
4080
6495
|
slug: "conditions",
|
|
4081
|
-
category: normalizeCategory("expression", "guard"),
|
|
6496
|
+
category: (0, import_player_core.normalizeCategory)("expression", "guard"),
|
|
4082
6497
|
parts: transition.conditions.map((c, i) => ({
|
|
4083
6498
|
slug: `condition_${i}`,
|
|
4084
|
-
category: normalizeCategory("expression", c.type || "condition"),
|
|
6499
|
+
category: (0, import_player_core.normalizeCategory)("expression", c.type || "condition"),
|
|
4085
6500
|
parts: c.expression ? [{ slug: c.expression, category: ["binding"] }] : void 0
|
|
4086
6501
|
}))
|
|
4087
6502
|
});
|
|
@@ -4120,7 +6535,7 @@ function liftField(field) {
|
|
|
4120
6535
|
}
|
|
4121
6536
|
return {
|
|
4122
6537
|
slug: field.name,
|
|
4123
|
-
category: normalizeCategory("field", field.type),
|
|
6538
|
+
category: (0, import_player_core.normalizeCategory)("field", field.type),
|
|
4124
6539
|
parts: parts.length > 0 ? parts : void 0
|
|
4125
6540
|
};
|
|
4126
6541
|
}
|
|
@@ -4143,20 +6558,20 @@ function liftView(node) {
|
|
|
4143
6558
|
if (match) {
|
|
4144
6559
|
parts.push({
|
|
4145
6560
|
slug: key,
|
|
4146
|
-
category: normalizeCategory("expression", "effect", "transition"),
|
|
6561
|
+
category: (0, import_player_core.normalizeCategory)("expression", "effect", "transition"),
|
|
4147
6562
|
parts: [{ slug: match[1], category: ["ref"] }]
|
|
4148
6563
|
});
|
|
4149
6564
|
} else {
|
|
4150
6565
|
parts.push({
|
|
4151
6566
|
slug: key,
|
|
4152
|
-
category: normalizeCategory("expression", "binding"),
|
|
6567
|
+
category: (0, import_player_core.normalizeCategory)("expression", "binding"),
|
|
4153
6568
|
parts: [{ slug: String(expr), category: ["binding"] }]
|
|
4154
6569
|
});
|
|
4155
6570
|
}
|
|
4156
6571
|
} else {
|
|
4157
6572
|
parts.push({
|
|
4158
6573
|
slug: key,
|
|
4159
|
-
category: normalizeCategory("expression", "binding"),
|
|
6574
|
+
category: (0, import_player_core.normalizeCategory)("expression", "binding"),
|
|
4160
6575
|
parts: [{ slug: String(expr), category: ["binding"] }]
|
|
4161
6576
|
});
|
|
4162
6577
|
}
|
|
@@ -4167,20 +6582,20 @@ function liftView(node) {
|
|
|
4167
6582
|
if (eqMatch) {
|
|
4168
6583
|
parts.push({
|
|
4169
6584
|
slug: "visible_when",
|
|
4170
|
-
category: normalizeCategory("expression", "guard"),
|
|
6585
|
+
category: (0, import_player_core.normalizeCategory)("expression", "guard"),
|
|
4171
6586
|
parts: [{
|
|
4172
6587
|
slug: "body",
|
|
4173
|
-
category: normalizeCategory("expression", "eq"),
|
|
6588
|
+
category: (0, import_player_core.normalizeCategory)("expression", "eq"),
|
|
4174
6589
|
parts: [
|
|
4175
|
-
{ slug: "lhs", category: normalizeCategory("expression", "path"), parts: [{ slug: eqMatch[1], category: ["binding"] }] },
|
|
4176
|
-
{ 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"] }] }
|
|
4177
6592
|
]
|
|
4178
6593
|
}]
|
|
4179
6594
|
});
|
|
4180
6595
|
} else {
|
|
4181
6596
|
parts.push({
|
|
4182
6597
|
slug: "visible_when",
|
|
4183
|
-
category: normalizeCategory("expression", "guard"),
|
|
6598
|
+
category: (0, import_player_core.normalizeCategory)("expression", "guard"),
|
|
4184
6599
|
parts: [{ slug: node.visible_when, category: ["binding"] }]
|
|
4185
6600
|
});
|
|
4186
6601
|
}
|
|
@@ -4192,7 +6607,7 @@ function liftView(node) {
|
|
|
4192
6607
|
}
|
|
4193
6608
|
return {
|
|
4194
6609
|
slug: node.id,
|
|
4195
|
-
category: normalizeCategory("view", componentTag),
|
|
6610
|
+
category: (0, import_player_core.normalizeCategory)("view", componentTag),
|
|
4196
6611
|
parts: parts.length > 0 ? parts : void 0
|
|
4197
6612
|
};
|
|
4198
6613
|
}
|
|
@@ -4213,7 +6628,7 @@ function emitCanonical(extracted, sourceFilename) {
|
|
|
4213
6628
|
}
|
|
4214
6629
|
parts.push({
|
|
4215
6630
|
slug: "manifest",
|
|
4216
|
-
category: normalizeCategory("meta", "manifest"),
|
|
6631
|
+
category: (0, import_player_core.normalizeCategory)("meta", "manifest"),
|
|
4217
6632
|
parts: [
|
|
4218
6633
|
{
|
|
4219
6634
|
slug: "workflows",
|
|
@@ -4234,7 +6649,7 @@ function emitCanonical(extracted, sourceFilename) {
|
|
|
4234
6649
|
let categoryArray;
|
|
4235
6650
|
if (category.includes("/")) {
|
|
4236
6651
|
const [primary, ...tags] = category.split("/");
|
|
4237
|
-
categoryArray = normalizeCategory(primary, ...tags);
|
|
6652
|
+
categoryArray = (0, import_player_core.normalizeCategory)(primary, ...tags);
|
|
4238
6653
|
} else {
|
|
4239
6654
|
categoryArray = [category];
|
|
4240
6655
|
}
|
|
@@ -4296,7 +6711,7 @@ function emitWorkflowDefinition(extracted) {
|
|
|
4296
6711
|
on_event: (s.on_event || []).map(convertOnEvent)
|
|
4297
6712
|
}));
|
|
4298
6713
|
const fields = ir.fields.map((f) => ({
|
|
4299
|
-
name:
|
|
6714
|
+
name: toSnakeCase3(f.name),
|
|
4300
6715
|
field_type: f.type,
|
|
4301
6716
|
label: f.label || f.name.replace(/([A-Z])/g, " $1").replace(/^./, (c) => c.toUpperCase()),
|
|
4302
6717
|
required: f.required || false,
|
|
@@ -4312,16 +6727,16 @@ function emitWorkflowDefinition(extracted) {
|
|
|
4312
6727
|
...f.editable_when && { editable_when: f.editable_when },
|
|
4313
6728
|
...f.state_home && { state_home: f.state_home }
|
|
4314
6729
|
}));
|
|
4315
|
-
const transitions = ir.transitions.map((
|
|
4316
|
-
name:
|
|
4317
|
-
from:
|
|
4318
|
-
to:
|
|
4319
|
-
description:
|
|
4320
|
-
roles:
|
|
4321
|
-
auto:
|
|
4322
|
-
conditions:
|
|
4323
|
-
actions: (
|
|
4324
|
-
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 || [],
|
|
4325
6740
|
priority: 0
|
|
4326
6741
|
}));
|
|
4327
6742
|
const state_data = {};
|
|
@@ -4339,7 +6754,7 @@ function emitWorkflowDefinition(extracted) {
|
|
|
4339
6754
|
if (extracted.fields.length > 0) {
|
|
4340
6755
|
const localDefaults = {};
|
|
4341
6756
|
for (const f of extracted.fields) {
|
|
4342
|
-
localDefaults[
|
|
6757
|
+
localDefaults[toSnakeCase3(f.name)] = f.default_value ?? null;
|
|
4343
6758
|
}
|
|
4344
6759
|
if (!viewRoot.config) viewRoot.config = {};
|
|
4345
6760
|
viewRoot.config.localDefaults = localDefaults;
|
|
@@ -4402,8 +6817,8 @@ function compilerStateToWorkflow(state, metadata) {
|
|
|
4402
6817
|
function resolveSlugArg(args, state) {
|
|
4403
6818
|
if (args.length < 1) return null;
|
|
4404
6819
|
const slugArg = args[0];
|
|
4405
|
-
if (
|
|
4406
|
-
if (
|
|
6820
|
+
if (t21.isStringLiteral(slugArg)) return slugArg.value;
|
|
6821
|
+
if (t21.isIdentifier(slugArg)) {
|
|
4407
6822
|
const compilerState = state;
|
|
4408
6823
|
const meta = compilerState.metadata;
|
|
4409
6824
|
const resolvedSlugs = meta.__modelImportSlugs;
|
|
@@ -4429,43 +6844,43 @@ function extractQueryDataSource(path, state) {
|
|
|
4429
6844
|
slug,
|
|
4430
6845
|
query: "list"
|
|
4431
6846
|
};
|
|
4432
|
-
if (args.length > 1 &&
|
|
6847
|
+
if (args.length > 1 && t21.isObjectExpression(args[1])) {
|
|
4433
6848
|
for (const prop of args[1].properties) {
|
|
4434
|
-
if (!
|
|
6849
|
+
if (!t21.isObjectProperty(prop) || !t21.isIdentifier(prop.key)) continue;
|
|
4435
6850
|
const key = prop.key.name;
|
|
4436
6851
|
const val = prop.value;
|
|
4437
6852
|
switch (key) {
|
|
4438
6853
|
case "limit":
|
|
4439
|
-
if (
|
|
6854
|
+
if (t21.isNumericLiteral(val)) {
|
|
4440
6855
|
dataSource.pageSize = val.value;
|
|
4441
6856
|
dataSource.paginated = true;
|
|
4442
6857
|
}
|
|
4443
6858
|
break;
|
|
4444
6859
|
case "orderBy":
|
|
4445
|
-
if (
|
|
6860
|
+
if (t21.isStringLiteral(val)) {
|
|
4446
6861
|
dataSource.sort = val.value;
|
|
4447
6862
|
}
|
|
4448
6863
|
break;
|
|
4449
6864
|
case "order":
|
|
4450
|
-
if (
|
|
6865
|
+
if (t21.isStringLiteral(val) && dataSource.sort) {
|
|
4451
6866
|
dataSource.sort = `${dataSource.sort}:${val.value}`;
|
|
4452
6867
|
}
|
|
4453
6868
|
break;
|
|
4454
6869
|
case "search":
|
|
4455
|
-
if (
|
|
6870
|
+
if (t21.isStringLiteral(val)) {
|
|
4456
6871
|
dataSource.search = val.value;
|
|
4457
6872
|
}
|
|
4458
6873
|
break;
|
|
4459
6874
|
case "searchFields":
|
|
4460
|
-
if (
|
|
4461
|
-
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);
|
|
4462
6877
|
}
|
|
4463
6878
|
break;
|
|
4464
6879
|
case "filter":
|
|
4465
|
-
if (
|
|
6880
|
+
if (t21.isObjectExpression(val)) {
|
|
4466
6881
|
const filter = {};
|
|
4467
6882
|
for (const fp of val.properties) {
|
|
4468
|
-
if (
|
|
6883
|
+
if (t21.isObjectProperty(fp) && t21.isIdentifier(fp.key) && t21.isStringLiteral(fp.value)) {
|
|
4469
6884
|
filter[fp.key.name] = fp.value.value;
|
|
4470
6885
|
}
|
|
4471
6886
|
}
|
|
@@ -4475,19 +6890,19 @@ function extractQueryDataSource(path, state) {
|
|
|
4475
6890
|
}
|
|
4476
6891
|
break;
|
|
4477
6892
|
case "state":
|
|
4478
|
-
if (
|
|
6893
|
+
if (t21.isStringLiteral(val)) {
|
|
4479
6894
|
if (!dataSource.filter) dataSource.filter = {};
|
|
4480
6895
|
dataSource.filter.current_state = val.value;
|
|
4481
6896
|
}
|
|
4482
6897
|
break;
|
|
4483
6898
|
case "groupBy":
|
|
4484
|
-
if (
|
|
6899
|
+
if (t21.isStringLiteral(val)) {
|
|
4485
6900
|
dataSource.groupBy = val.value;
|
|
4486
6901
|
}
|
|
4487
6902
|
break;
|
|
4488
6903
|
case "facets":
|
|
4489
|
-
if (
|
|
4490
|
-
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);
|
|
4491
6906
|
}
|
|
4492
6907
|
break;
|
|
4493
6908
|
}
|
|
@@ -4511,17 +6926,17 @@ function extractMutationDataSource(path, state) {
|
|
|
4511
6926
|
}
|
|
4512
6927
|
function extractDuringAction(path, state) {
|
|
4513
6928
|
const args = path.node.arguments;
|
|
4514
|
-
if (args.length < 1 || !
|
|
6929
|
+
if (args.length < 1 || !t21.isObjectExpression(args[0])) return;
|
|
4515
6930
|
const compilerState = state;
|
|
4516
6931
|
const config = args[0];
|
|
4517
6932
|
let stateName;
|
|
4518
6933
|
let intervalMs = 1e3;
|
|
4519
6934
|
for (const prop of config.properties) {
|
|
4520
|
-
if (!
|
|
4521
|
-
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)) {
|
|
4522
6937
|
stateName = prop.value.value;
|
|
4523
6938
|
}
|
|
4524
|
-
if (prop.key.name === "intervalMs" &&
|
|
6939
|
+
if (prop.key.name === "intervalMs" && t21.isNumericLiteral(prop.value)) {
|
|
4525
6940
|
intervalMs = prop.value.value;
|
|
4526
6941
|
}
|
|
4527
6942
|
}
|
|
@@ -4547,7 +6962,7 @@ function extractDuringAction(path, state) {
|
|
|
4547
6962
|
}
|
|
4548
6963
|
function extractRoleDependency(path, state) {
|
|
4549
6964
|
const args = path.node.arguments;
|
|
4550
|
-
if (args.length < 1 || !
|
|
6965
|
+
if (args.length < 1 || !t21.isStringLiteral(args[0])) return;
|
|
4551
6966
|
const compilerState = state;
|
|
4552
6967
|
if (!compilerState.metadata) compilerState.metadata = {};
|
|
4553
6968
|
const meta = compilerState.metadata;
|
|
@@ -4558,7 +6973,7 @@ function extractRoleDependency(path, state) {
|
|
|
4558
6973
|
}
|
|
4559
6974
|
function extractViewDependency(path, state) {
|
|
4560
6975
|
const args = path.node.arguments;
|
|
4561
|
-
if (args.length < 1 || !
|
|
6976
|
+
if (args.length < 1 || !t21.isStringLiteral(args[0])) return;
|
|
4562
6977
|
const compilerState = state;
|
|
4563
6978
|
if (!compilerState.metadata) compilerState.metadata = {};
|
|
4564
6979
|
const meta = compilerState.metadata;
|
|
@@ -4575,7 +6990,7 @@ function extractParamsUsage(_path, state) {
|
|
|
4575
6990
|
}
|
|
4576
6991
|
function extractLibraryDependency(path, state) {
|
|
4577
6992
|
const args = path.node.arguments;
|
|
4578
|
-
if (args.length < 1 || !
|
|
6993
|
+
if (args.length < 1 || !t21.isStringLiteral(args[0])) return;
|
|
4579
6994
|
const compilerState = state;
|
|
4580
6995
|
if (!compilerState.metadata) compilerState.metadata = {};
|
|
4581
6996
|
const meta = compilerState.metadata;
|
|
@@ -4655,15 +7070,15 @@ function createVisitor(options = {}) {
|
|
|
4655
7070
|
}
|
|
4656
7071
|
}
|
|
4657
7072
|
const exportDeclaration = program.body.find(
|
|
4658
|
-
(node) =>
|
|
7073
|
+
(node) => t21.isExportNamedDeclaration(node) || t21.isExportDefaultDeclaration(node)
|
|
4659
7074
|
);
|
|
4660
7075
|
if (exportDeclaration) {
|
|
4661
7076
|
if (exportDeclaration.leadingComments) {
|
|
4662
7077
|
extractMetadataFromComments(exportDeclaration.leadingComments, compilerState.metadata);
|
|
4663
7078
|
}
|
|
4664
|
-
if (
|
|
7079
|
+
if (t21.isExportNamedDeclaration(exportDeclaration)) {
|
|
4665
7080
|
const declaration = exportDeclaration.declaration;
|
|
4666
|
-
if (
|
|
7081
|
+
if (t21.isFunctionDeclaration(declaration)) {
|
|
4667
7082
|
if (declaration.id) {
|
|
4668
7083
|
compilerState.metadata.name = declaration.id.name;
|
|
4669
7084
|
}
|
|
@@ -4671,16 +7086,16 @@ function createVisitor(options = {}) {
|
|
|
4671
7086
|
extractMetadataFromComments(declaration.leadingComments, compilerState.metadata);
|
|
4672
7087
|
}
|
|
4673
7088
|
}
|
|
4674
|
-
} else if (
|
|
7089
|
+
} else if (t21.isExportDefaultDeclaration(exportDeclaration)) {
|
|
4675
7090
|
const declaration = exportDeclaration.declaration;
|
|
4676
|
-
if (
|
|
7091
|
+
if (t21.isFunctionDeclaration(declaration)) {
|
|
4677
7092
|
if (declaration.id) {
|
|
4678
7093
|
compilerState.metadata.name = declaration.id.name;
|
|
4679
7094
|
}
|
|
4680
7095
|
if (declaration.leadingComments) {
|
|
4681
7096
|
extractMetadataFromComments(declaration.leadingComments, compilerState.metadata);
|
|
4682
7097
|
}
|
|
4683
|
-
} else if (
|
|
7098
|
+
} else if (t21.isIdentifier(declaration)) {
|
|
4684
7099
|
compilerState.metadata.name = declaration.name;
|
|
4685
7100
|
}
|
|
4686
7101
|
}
|
|
@@ -4691,7 +7106,13 @@ function createVisitor(options = {}) {
|
|
|
4691
7106
|
compilerState.metadata.__slugAutoFallback = true;
|
|
4692
7107
|
}
|
|
4693
7108
|
Object.assign(state, compilerState);
|
|
4694
|
-
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)) {
|
|
4695
7116
|
extractModelFile(_path, state);
|
|
4696
7117
|
state.__isModelFile = true;
|
|
4697
7118
|
if (!compilerState.metadata.category) {
|
|
@@ -4702,6 +7123,15 @@ function createVisitor(options = {}) {
|
|
|
4702
7123
|
if (hasContextCreation(_path)) {
|
|
4703
7124
|
extractContextWorkflows(_path, state);
|
|
4704
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
|
+
}
|
|
4705
7135
|
if (isServerActionFile(state.filename)) {
|
|
4706
7136
|
extractServerActions(_path, state);
|
|
4707
7137
|
state.__isServerActionFile = true;
|
|
@@ -4737,13 +7167,13 @@ function createVisitor(options = {}) {
|
|
|
4737
7167
|
// Main hook extraction dispatcher
|
|
4738
7168
|
CallExpression(path, state) {
|
|
4739
7169
|
const callee = path.node.callee;
|
|
4740
|
-
if (!
|
|
7170
|
+
if (!t21.isIdentifier(callee)) return;
|
|
4741
7171
|
const compilerState = state;
|
|
4742
7172
|
const hookName = callee.name;
|
|
4743
7173
|
if (mode === "strict" && STRICT_BANNED_HOOKS[hookName]) {
|
|
4744
7174
|
const error = {
|
|
4745
7175
|
code: STRICT_BANNED_HOOKS[hookName],
|
|
4746
|
-
message: `${hookName}() is not allowed in strict mode. Use @
|
|
7176
|
+
message: `${hookName}() is not allowed in strict mode. Use @mmapp/react effect hooks instead.`,
|
|
4747
7177
|
line: path.node.loc?.start.line,
|
|
4748
7178
|
column: path.node.loc?.start.column,
|
|
4749
7179
|
severity: "error"
|
|
@@ -4829,18 +7259,18 @@ function createVisitor(options = {}) {
|
|
|
4829
7259
|
if (!meta.__modelImports) meta.__modelImports = {};
|
|
4830
7260
|
const imports = meta.__modelImports;
|
|
4831
7261
|
for (const specifier of path.node.specifiers) {
|
|
4832
|
-
if (
|
|
7262
|
+
if (t21.isImportDefaultSpecifier(specifier) || t21.isImportSpecifier(specifier)) {
|
|
4833
7263
|
imports[specifier.local.name] = source;
|
|
4834
7264
|
}
|
|
4835
7265
|
}
|
|
4836
7266
|
}
|
|
4837
7267
|
if (mode !== "strict") return;
|
|
4838
|
-
if (source.startsWith("@
|
|
7268
|
+
if (source.startsWith("@mmapp/") || source.startsWith("@mmapp/") || source === "react" || source.startsWith("react/") || source.startsWith(".") || source.startsWith("/")) {
|
|
4839
7269
|
return;
|
|
4840
7270
|
}
|
|
4841
7271
|
const error = {
|
|
4842
7272
|
code: "STRICT_FORBIDDEN_IMPORT",
|
|
4843
|
-
message: `Import from '${source}' is not allowed in strict mode. Only @
|
|
7273
|
+
message: `Import from '${source}' is not allowed in strict mode. Only @mmapp/* and relative imports are permitted.`,
|
|
4844
7274
|
line: path.node.loc?.start.line,
|
|
4845
7275
|
column: path.node.loc?.start.column,
|
|
4846
7276
|
severity: "error"
|
|
@@ -4862,8 +7292,8 @@ function createVisitor(options = {}) {
|
|
|
4862
7292
|
if (!compilerState.metadata) return;
|
|
4863
7293
|
const id = path.node.id;
|
|
4864
7294
|
const init = path.node.init;
|
|
4865
|
-
if (
|
|
4866
|
-
if (!
|
|
7295
|
+
if (t21.isArrayPattern(id)) return;
|
|
7296
|
+
if (!t21.isIdentifier(id) || !init || !t21.isExpression(init)) return;
|
|
4867
7297
|
const parentFn = path.getFunctionParent();
|
|
4868
7298
|
if (!parentFn) return;
|
|
4869
7299
|
const parentNode = parentFn.parentPath;
|
|
@@ -4871,17 +7301,17 @@ function createVisitor(options = {}) {
|
|
|
4871
7301
|
let isExportedByName = false;
|
|
4872
7302
|
if (!isExportedDirectly && parentNode?.isVariableDeclarator()) {
|
|
4873
7303
|
const varId = parentNode.node.id;
|
|
4874
|
-
if (
|
|
7304
|
+
if (t21.isIdentifier(varId)) {
|
|
4875
7305
|
isExportedByName = varId.name === compilerState.metadata?.name;
|
|
4876
7306
|
}
|
|
4877
7307
|
}
|
|
4878
7308
|
if (!isExportedDirectly && !isExportedByName) return;
|
|
4879
|
-
if (
|
|
7309
|
+
if (t21.isCallExpression(init) && t21.isIdentifier(init.callee)) {
|
|
4880
7310
|
const callee = init.callee.name;
|
|
4881
7311
|
if (callee === "useQuery") {
|
|
4882
|
-
registerDerivedVar(id.name,
|
|
4883
|
-
|
|
4884
|
-
|
|
7312
|
+
registerDerivedVar(id.name, t21.optionalMemberExpression(
|
|
7313
|
+
t21.identifier("$instance"),
|
|
7314
|
+
t21.identifier(id.name),
|
|
4885
7315
|
false,
|
|
4886
7316
|
// computed
|
|
4887
7317
|
true
|
|
@@ -4890,23 +7320,23 @@ function createVisitor(options = {}) {
|
|
|
4890
7320
|
return;
|
|
4891
7321
|
}
|
|
4892
7322
|
if (callee === "useMutation") {
|
|
4893
|
-
registerDerivedVar(id.name,
|
|
4894
|
-
|
|
4895
|
-
|
|
7323
|
+
registerDerivedVar(id.name, t21.memberExpression(
|
|
7324
|
+
t21.identifier("$action"),
|
|
7325
|
+
t21.identifier("transition")
|
|
4896
7326
|
));
|
|
4897
7327
|
return;
|
|
4898
7328
|
}
|
|
4899
7329
|
if (callee === "useServerAction") {
|
|
4900
|
-
registerDerivedVar(id.name,
|
|
4901
|
-
|
|
4902
|
-
|
|
7330
|
+
registerDerivedVar(id.name, t21.memberExpression(
|
|
7331
|
+
t21.identifier("$action"),
|
|
7332
|
+
t21.identifier("serverAction")
|
|
4903
7333
|
));
|
|
4904
7334
|
return;
|
|
4905
7335
|
}
|
|
4906
7336
|
if (callee === "useServerState") {
|
|
4907
|
-
registerDerivedVar(id.name,
|
|
4908
|
-
|
|
4909
|
-
|
|
7337
|
+
registerDerivedVar(id.name, t21.optionalMemberExpression(
|
|
7338
|
+
t21.identifier("$instance"),
|
|
7339
|
+
t21.identifier("serverState"),
|
|
4910
7340
|
false,
|
|
4911
7341
|
true
|
|
4912
7342
|
));
|
|
@@ -4914,12 +7344,12 @@ function createVisitor(options = {}) {
|
|
|
4914
7344
|
}
|
|
4915
7345
|
if (callee === "useMemo" && init.arguments.length >= 1) {
|
|
4916
7346
|
const callback = init.arguments[0];
|
|
4917
|
-
if (
|
|
4918
|
-
if (
|
|
7347
|
+
if (t21.isArrowFunctionExpression(callback)) {
|
|
7348
|
+
if (t21.isExpression(callback.body)) {
|
|
4919
7349
|
registerDerivedVar(id.name, callback.body);
|
|
4920
|
-
} else if (
|
|
4921
|
-
const retStmt = callback.body.body.find((s) =>
|
|
4922
|
-
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)) {
|
|
4923
7353
|
registerDerivedVar(id.name, retStmt.argument);
|
|
4924
7354
|
}
|
|
4925
7355
|
}
|
|
@@ -4934,7 +7364,7 @@ function createVisitor(options = {}) {
|
|
|
4934
7364
|
// Only extract from the exported component function's direct return,
|
|
4935
7365
|
// not from nested callbacks (Each render functions, helper components, etc.).
|
|
4936
7366
|
ReturnStatement(path, state) {
|
|
4937
|
-
if (!
|
|
7367
|
+
if (!t21.isJSXElement(path.node.argument) && !t21.isJSXFragment(path.node.argument)) return;
|
|
4938
7368
|
const parentFn = path.getFunctionParent();
|
|
4939
7369
|
if (!parentFn) return;
|
|
4940
7370
|
const parentNode = parentFn.parentPath;
|
|
@@ -4942,7 +7372,7 @@ function createVisitor(options = {}) {
|
|
|
4942
7372
|
let isExportedByName = false;
|
|
4943
7373
|
if (!isExportedDirectly && parentNode?.isVariableDeclarator()) {
|
|
4944
7374
|
const varId = parentNode.node.id;
|
|
4945
|
-
if (
|
|
7375
|
+
if (t21.isIdentifier(varId)) {
|
|
4946
7376
|
isExportedByName = varId.name === state.metadata?.name;
|
|
4947
7377
|
}
|
|
4948
7378
|
}
|