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