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