@mmapp/react 0.1.0-alpha.1 → 0.1.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -0
- package/dist/index.d.mts +1378 -94
- package/dist/index.d.ts +1378 -94
- package/dist/index.js +1094 -1309
- package/dist/index.mjs +1038 -1296
- package/package.json +4 -3
- package/package.json.backup +0 -41
- package/src/Blueprint.ts +0 -216
- package/src/__tests__/Blueprint.test.ts +0 -106
- package/src/__tests__/action-context.test.ts +0 -166
- package/src/__tests__/actionCreators.test.ts +0 -179
- package/src/__tests__/builders.test.ts +0 -336
- package/src/__tests__/defineBlueprint-composition.test.ts +0 -106
- package/src/__tests__/factories.test.ts +0 -229
- package/src/__tests__/loader.test.ts +0 -159
- package/src/__tests__/logger.test.ts +0 -70
- package/src/__tests__/type-inference.test.ts +0 -160
- package/src/__tests__/typed-transitions.test.ts +0 -126
- package/src/__tests__/useModuleConfig.test.ts +0 -61
- package/src/actionCreators.ts +0 -132
- package/src/actions.ts +0 -547
- package/src/atoms/index.ts +0 -600
- package/src/authoring.ts +0 -92
- package/src/browser-player.ts +0 -783
- package/src/builders.ts +0 -1342
- package/src/components/ExperienceWorkflowBridge.tsx +0 -123
- package/src/components/PlayerProvider.tsx +0 -43
- package/src/components/atoms/index.tsx +0 -269
- package/src/components/index.ts +0 -36
- package/src/conditions.ts +0 -692
- package/src/config/defineBlueprint.ts +0 -329
- package/src/config/defineModel.ts +0 -753
- package/src/config/defineWorkspace.ts +0 -24
- package/src/core/WorkflowRuntime.ts +0 -153
- package/src/factories.ts +0 -425
- package/src/grammar/index.ts +0 -173
- package/src/hooks/index.ts +0 -106
- package/src/hooks/useAuth.ts +0 -288
- package/src/hooks/useChannel.ts +0 -304
- package/src/hooks/useComputed.ts +0 -154
- package/src/hooks/useDomainSubscription.ts +0 -110
- package/src/hooks/useDuringAction.ts +0 -99
- package/src/hooks/useExperienceState.ts +0 -59
- package/src/hooks/useExpressionLibrary.ts +0 -129
- package/src/hooks/useForm.ts +0 -352
- package/src/hooks/useGeolocation.ts +0 -207
- package/src/hooks/useMapView.ts +0 -259
- package/src/hooks/useMiddleware.ts +0 -291
- package/src/hooks/useModel.ts +0 -363
- package/src/hooks/useModule.ts +0 -59
- package/src/hooks/useModuleConfig.ts +0 -61
- package/src/hooks/useMutation.ts +0 -237
- package/src/hooks/useNotification.ts +0 -151
- package/src/hooks/useOnChange.ts +0 -30
- package/src/hooks/useOnEnter.ts +0 -59
- package/src/hooks/useOnEvent.ts +0 -37
- package/src/hooks/useOnExit.ts +0 -27
- package/src/hooks/useOnTransition.ts +0 -30
- package/src/hooks/usePackage.ts +0 -128
- package/src/hooks/useParams.ts +0 -33
- package/src/hooks/usePlayer.ts +0 -308
- package/src/hooks/useQuery.ts +0 -184
- package/src/hooks/useRealtimeQuery.ts +0 -222
- package/src/hooks/useRole.ts +0 -191
- package/src/hooks/useRouteParams.ts +0 -100
- package/src/hooks/useRouter.ts +0 -347
- package/src/hooks/useServerAction.ts +0 -178
- package/src/hooks/useServerState.ts +0 -284
- package/src/hooks/useToast.ts +0 -164
- package/src/hooks/useTransition.ts +0 -39
- package/src/hooks/useView.ts +0 -102
- package/src/hooks/useWhileIn.ts +0 -48
- package/src/hooks/useWorkflow.ts +0 -63
- package/src/index.ts +0 -465
- package/src/loader/experience-workflow-loader.ts +0 -192
- package/src/loader/index.ts +0 -6
- package/src/local/LocalEngine.ts +0 -388
- package/src/local/LocalEngineAdapter.ts +0 -175
- package/src/local/LocalEngineContext.ts +0 -30
- package/src/logger.ts +0 -37
- package/src/mixins.ts +0 -1160
- package/src/providers/RuntimeContext.ts +0 -20
- package/src/providers/WorkflowProvider.tsx +0 -28
- package/src/routing/instance-key.ts +0 -107
- package/src/server/transition-context.ts +0 -172
- package/src/testing/index.ts +0 -9
- package/src/testing/useBlueprintTestRunner.ts +0 -91
- package/src/testing/useGraphAnalysis.ts +0 -18
- package/src/testing/useTestRunner.ts +0 -77
- package/src/testing.ts +0 -995
- package/src/types/workflow-inference.ts +0 -158
- package/src/types.ts +0 -114
- package/tsconfig.json +0 -27
- package/vitest.config.ts +0 -8
package/dist/index.mjs
CHANGED
|
@@ -1,1087 +1,11 @@
|
|
|
1
|
-
// ../player-core/dist/index.mjs
|
|
2
|
-
var add = {
|
|
3
|
-
name: "add",
|
|
4
|
-
fn: (a, b) => Number(a) + Number(b),
|
|
5
|
-
arity: 2
|
|
6
|
-
};
|
|
7
|
-
var subtract = {
|
|
8
|
-
name: "subtract",
|
|
9
|
-
fn: (a, b) => Number(a) - Number(b),
|
|
10
|
-
arity: 2
|
|
11
|
-
};
|
|
12
|
-
var multiply = {
|
|
13
|
-
name: "multiply",
|
|
14
|
-
fn: (a, b) => Number(a) * Number(b),
|
|
15
|
-
arity: 2
|
|
16
|
-
};
|
|
17
|
-
var divide = {
|
|
18
|
-
name: "divide",
|
|
19
|
-
fn: (a, b) => {
|
|
20
|
-
const d = Number(b);
|
|
21
|
-
return d === 0 ? 0 : Number(a) / d;
|
|
22
|
-
},
|
|
23
|
-
arity: 2
|
|
24
|
-
};
|
|
25
|
-
var abs = {
|
|
26
|
-
name: "abs",
|
|
27
|
-
fn: (a) => Math.abs(Number(a)),
|
|
28
|
-
arity: 1
|
|
29
|
-
};
|
|
30
|
-
var round = {
|
|
31
|
-
name: "round",
|
|
32
|
-
fn: (a, decimals) => {
|
|
33
|
-
const d = decimals != null ? Number(decimals) : 0;
|
|
34
|
-
const factor = Math.pow(10, d);
|
|
35
|
-
return Math.round(Number(a) * factor) / factor;
|
|
36
|
-
},
|
|
37
|
-
arity: -1
|
|
38
|
-
};
|
|
39
|
-
var min = {
|
|
40
|
-
name: "min",
|
|
41
|
-
fn: (...args) => {
|
|
42
|
-
const nums = args.flat().map(Number).filter((n) => !isNaN(n));
|
|
43
|
-
return nums.length === 0 ? 0 : Math.min(...nums);
|
|
44
|
-
},
|
|
45
|
-
arity: -1
|
|
46
|
-
};
|
|
47
|
-
var max = {
|
|
48
|
-
name: "max",
|
|
49
|
-
fn: (...args) => {
|
|
50
|
-
const nums = args.flat().map(Number).filter((n) => !isNaN(n));
|
|
51
|
-
return nums.length === 0 ? 0 : Math.max(...nums);
|
|
52
|
-
},
|
|
53
|
-
arity: -1
|
|
54
|
-
};
|
|
55
|
-
var eq = {
|
|
56
|
-
name: "eq",
|
|
57
|
-
fn: (a, b) => a === b || String(a) === String(b),
|
|
58
|
-
arity: 2
|
|
59
|
-
};
|
|
60
|
-
var neq = {
|
|
61
|
-
name: "neq",
|
|
62
|
-
fn: (a, b) => a !== b && String(a) !== String(b),
|
|
63
|
-
arity: 2
|
|
64
|
-
};
|
|
65
|
-
var gt = {
|
|
66
|
-
name: "gt",
|
|
67
|
-
fn: (a, b) => Number(a) > Number(b),
|
|
68
|
-
arity: 2
|
|
69
|
-
};
|
|
70
|
-
var gte = {
|
|
71
|
-
name: "gte",
|
|
72
|
-
fn: (a, b) => Number(a) >= Number(b),
|
|
73
|
-
arity: 2
|
|
74
|
-
};
|
|
75
|
-
var lt = {
|
|
76
|
-
name: "lt",
|
|
77
|
-
fn: (a, b) => Number(a) < Number(b),
|
|
78
|
-
arity: 2
|
|
79
|
-
};
|
|
80
|
-
var lte = {
|
|
81
|
-
name: "lte",
|
|
82
|
-
fn: (a, b) => Number(a) <= Number(b),
|
|
83
|
-
arity: 2
|
|
84
|
-
};
|
|
85
|
-
var if_fn = {
|
|
86
|
-
name: "if",
|
|
87
|
-
fn: (cond, then, else_) => cond ? then : else_,
|
|
88
|
-
arity: 3
|
|
89
|
-
};
|
|
90
|
-
var and = {
|
|
91
|
-
name: "and",
|
|
92
|
-
fn: (...args) => args.every(Boolean),
|
|
93
|
-
arity: -1
|
|
94
|
-
};
|
|
95
|
-
var or = {
|
|
96
|
-
name: "or",
|
|
97
|
-
fn: (...args) => args.some(Boolean),
|
|
98
|
-
arity: -1
|
|
99
|
-
};
|
|
100
|
-
var not = {
|
|
101
|
-
name: "not",
|
|
102
|
-
fn: (a) => !a,
|
|
103
|
-
arity: 1
|
|
104
|
-
};
|
|
105
|
-
var coalesce = {
|
|
106
|
-
name: "coalesce",
|
|
107
|
-
fn: (...args) => {
|
|
108
|
-
for (const arg of args) {
|
|
109
|
-
if (arg != null) return arg;
|
|
110
|
-
}
|
|
111
|
-
return null;
|
|
112
|
-
},
|
|
113
|
-
arity: -1
|
|
114
|
-
};
|
|
115
|
-
var concat = {
|
|
116
|
-
name: "concat",
|
|
117
|
-
fn: (...args) => args.map(String).join(""),
|
|
118
|
-
arity: -1
|
|
119
|
-
};
|
|
120
|
-
var upper = {
|
|
121
|
-
name: "upper",
|
|
122
|
-
fn: (s) => String(s ?? "").toUpperCase(),
|
|
123
|
-
arity: 1
|
|
124
|
-
};
|
|
125
|
-
var lower = {
|
|
126
|
-
name: "lower",
|
|
127
|
-
fn: (s) => String(s ?? "").toLowerCase(),
|
|
128
|
-
arity: 1
|
|
129
|
-
};
|
|
130
|
-
var trim = {
|
|
131
|
-
name: "trim",
|
|
132
|
-
fn: (s) => String(s ?? "").trim(),
|
|
133
|
-
arity: 1
|
|
134
|
-
};
|
|
135
|
-
var format = {
|
|
136
|
-
name: "format",
|
|
137
|
-
fn: (template, ...args) => {
|
|
138
|
-
let result = String(template ?? "");
|
|
139
|
-
args.forEach((arg, i) => {
|
|
140
|
-
result = result.replace(`{${i}}`, String(arg ?? ""));
|
|
141
|
-
});
|
|
142
|
-
return result;
|
|
143
|
-
},
|
|
144
|
-
arity: -1
|
|
145
|
-
};
|
|
146
|
-
var length = {
|
|
147
|
-
name: "length",
|
|
148
|
-
fn: (v) => {
|
|
149
|
-
if (Array.isArray(v)) return v.length;
|
|
150
|
-
if (typeof v === "string") return v.length;
|
|
151
|
-
if (v && typeof v === "object") return Object.keys(v).length;
|
|
152
|
-
return 0;
|
|
153
|
-
},
|
|
154
|
-
arity: 1
|
|
155
|
-
};
|
|
156
|
-
var get = {
|
|
157
|
-
name: "get",
|
|
158
|
-
fn: (obj, path) => {
|
|
159
|
-
if (obj == null || typeof path !== "string") return void 0;
|
|
160
|
-
const parts = path.split(".");
|
|
161
|
-
let current = obj;
|
|
162
|
-
for (const part of parts) {
|
|
163
|
-
if (current == null || typeof current !== "object") return void 0;
|
|
164
|
-
current = current[part];
|
|
165
|
-
}
|
|
166
|
-
return current;
|
|
167
|
-
},
|
|
168
|
-
arity: 2
|
|
169
|
-
};
|
|
170
|
-
var includes = {
|
|
171
|
-
name: "includes",
|
|
172
|
-
fn: (collection, value) => {
|
|
173
|
-
if (Array.isArray(collection)) return collection.includes(value);
|
|
174
|
-
if (typeof collection === "string") return collection.includes(String(value));
|
|
175
|
-
return false;
|
|
176
|
-
},
|
|
177
|
-
arity: 2
|
|
178
|
-
};
|
|
179
|
-
var is_defined = {
|
|
180
|
-
name: "is_defined",
|
|
181
|
-
fn: (v) => v !== void 0 && v !== null,
|
|
182
|
-
arity: 1
|
|
183
|
-
};
|
|
184
|
-
var is_empty = {
|
|
185
|
-
name: "is_empty",
|
|
186
|
-
fn: (v) => {
|
|
187
|
-
if (v == null) return true;
|
|
188
|
-
if (typeof v === "string") return v.length === 0;
|
|
189
|
-
if (Array.isArray(v)) return v.length === 0;
|
|
190
|
-
if (typeof v === "object") return Object.keys(v).length === 0;
|
|
191
|
-
return false;
|
|
192
|
-
},
|
|
193
|
-
arity: 1
|
|
194
|
-
};
|
|
195
|
-
var is_null = {
|
|
196
|
-
name: "is_null",
|
|
197
|
-
fn: (v) => v === null || v === void 0,
|
|
198
|
-
arity: 1
|
|
199
|
-
};
|
|
200
|
-
var to_string = {
|
|
201
|
-
name: "to_string",
|
|
202
|
-
fn: (v) => {
|
|
203
|
-
if (v == null) return "";
|
|
204
|
-
if (typeof v === "object") return JSON.stringify(v);
|
|
205
|
-
return String(v);
|
|
206
|
-
},
|
|
207
|
-
arity: 1
|
|
208
|
-
};
|
|
209
|
-
var CORE_FUNCTIONS = [
|
|
210
|
-
// Math (8)
|
|
211
|
-
add,
|
|
212
|
-
subtract,
|
|
213
|
-
multiply,
|
|
214
|
-
divide,
|
|
215
|
-
abs,
|
|
216
|
-
round,
|
|
217
|
-
min,
|
|
218
|
-
max,
|
|
219
|
-
// Comparison (6)
|
|
220
|
-
eq,
|
|
221
|
-
neq,
|
|
222
|
-
gt,
|
|
223
|
-
gte,
|
|
224
|
-
lt,
|
|
225
|
-
lte,
|
|
226
|
-
// Logic (5)
|
|
227
|
-
if_fn,
|
|
228
|
-
and,
|
|
229
|
-
or,
|
|
230
|
-
not,
|
|
231
|
-
coalesce,
|
|
232
|
-
// String (6)
|
|
233
|
-
concat,
|
|
234
|
-
upper,
|
|
235
|
-
lower,
|
|
236
|
-
trim,
|
|
237
|
-
format,
|
|
238
|
-
length,
|
|
239
|
-
// Path (3)
|
|
240
|
-
get,
|
|
241
|
-
includes,
|
|
242
|
-
is_defined,
|
|
243
|
-
// Type (3)
|
|
244
|
-
is_empty,
|
|
245
|
-
is_null,
|
|
246
|
-
to_string
|
|
247
|
-
];
|
|
248
|
-
function buildFunctionMap(functions) {
|
|
249
|
-
const map = /* @__PURE__ */ new Map();
|
|
250
|
-
for (const fn of functions) {
|
|
251
|
-
map.set(fn.name, fn.fn);
|
|
252
|
-
}
|
|
253
|
-
return map;
|
|
254
|
-
}
|
|
255
|
-
var MAX_DEPTH = 50;
|
|
256
|
-
var Parser = class {
|
|
257
|
-
pos = 0;
|
|
258
|
-
depth = 0;
|
|
259
|
-
input;
|
|
260
|
-
constructor(input) {
|
|
261
|
-
this.input = input;
|
|
262
|
-
}
|
|
263
|
-
parse() {
|
|
264
|
-
this.skipWhitespace();
|
|
265
|
-
const node = this.parseExpression();
|
|
266
|
-
this.skipWhitespace();
|
|
267
|
-
if (this.pos < this.input.length) {
|
|
268
|
-
throw new Error(`Unexpected character at position ${this.pos}: '${this.input[this.pos]}'`);
|
|
269
|
-
}
|
|
270
|
-
return node;
|
|
271
|
-
}
|
|
272
|
-
guardDepth() {
|
|
273
|
-
if (++this.depth > MAX_DEPTH) {
|
|
274
|
-
throw new Error("Expression too deeply nested");
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
parseExpression() {
|
|
278
|
-
this.guardDepth();
|
|
279
|
-
try {
|
|
280
|
-
return this.parseTernary();
|
|
281
|
-
} finally {
|
|
282
|
-
this.depth--;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
parseTernary() {
|
|
286
|
-
let node = this.parseLogicalOr();
|
|
287
|
-
this.skipWhitespace();
|
|
288
|
-
if (this.peek() === "?") {
|
|
289
|
-
this.advance();
|
|
290
|
-
const consequent = this.parseExpression();
|
|
291
|
-
this.skipWhitespace();
|
|
292
|
-
this.expect(":");
|
|
293
|
-
const alternate = this.parseExpression();
|
|
294
|
-
node = { type: "ternary", condition: node, consequent, alternate };
|
|
295
|
-
}
|
|
296
|
-
return node;
|
|
297
|
-
}
|
|
298
|
-
parseLogicalOr() {
|
|
299
|
-
let left = this.parseLogicalAnd();
|
|
300
|
-
this.skipWhitespace();
|
|
301
|
-
while (this.match("||")) {
|
|
302
|
-
const right = this.parseLogicalAnd();
|
|
303
|
-
left = { type: "binary", operator: "||", left, right };
|
|
304
|
-
this.skipWhitespace();
|
|
305
|
-
}
|
|
306
|
-
return left;
|
|
307
|
-
}
|
|
308
|
-
parseLogicalAnd() {
|
|
309
|
-
let left = this.parseEquality();
|
|
310
|
-
this.skipWhitespace();
|
|
311
|
-
while (this.match("&&")) {
|
|
312
|
-
const right = this.parseEquality();
|
|
313
|
-
left = { type: "binary", operator: "&&", left, right };
|
|
314
|
-
this.skipWhitespace();
|
|
315
|
-
}
|
|
316
|
-
return left;
|
|
317
|
-
}
|
|
318
|
-
parseEquality() {
|
|
319
|
-
let left = this.parseComparison();
|
|
320
|
-
this.skipWhitespace();
|
|
321
|
-
while (true) {
|
|
322
|
-
if (this.match("==")) {
|
|
323
|
-
const right = this.parseComparison();
|
|
324
|
-
left = { type: "binary", operator: "==", left, right };
|
|
325
|
-
} else if (this.match("!=")) {
|
|
326
|
-
const right = this.parseComparison();
|
|
327
|
-
left = { type: "binary", operator: "!=", left, right };
|
|
328
|
-
} else {
|
|
329
|
-
break;
|
|
330
|
-
}
|
|
331
|
-
this.skipWhitespace();
|
|
332
|
-
}
|
|
333
|
-
return left;
|
|
334
|
-
}
|
|
335
|
-
parseComparison() {
|
|
336
|
-
let left = this.parseUnary();
|
|
337
|
-
this.skipWhitespace();
|
|
338
|
-
while (true) {
|
|
339
|
-
if (this.match(">=")) {
|
|
340
|
-
const right = this.parseUnary();
|
|
341
|
-
left = { type: "binary", operator: ">=", left, right };
|
|
342
|
-
} else if (this.match("<=")) {
|
|
343
|
-
const right = this.parseUnary();
|
|
344
|
-
left = { type: "binary", operator: "<=", left, right };
|
|
345
|
-
} else if (this.peek() === ">" && !this.lookAhead(">=")) {
|
|
346
|
-
this.advance();
|
|
347
|
-
const right = this.parseUnary();
|
|
348
|
-
left = { type: "binary", operator: ">", left, right };
|
|
349
|
-
} else if (this.peek() === "<" && !this.lookAhead("<=")) {
|
|
350
|
-
this.advance();
|
|
351
|
-
const right = this.parseUnary();
|
|
352
|
-
left = { type: "binary", operator: "<", left, right };
|
|
353
|
-
} else {
|
|
354
|
-
break;
|
|
355
|
-
}
|
|
356
|
-
this.skipWhitespace();
|
|
357
|
-
}
|
|
358
|
-
return left;
|
|
359
|
-
}
|
|
360
|
-
parseUnary() {
|
|
361
|
-
this.skipWhitespace();
|
|
362
|
-
if (this.peek() === "!") {
|
|
363
|
-
this.advance();
|
|
364
|
-
const operand = this.parseUnary();
|
|
365
|
-
return { type: "unary", operator: "!", operand };
|
|
366
|
-
}
|
|
367
|
-
if (this.peek() === "-") {
|
|
368
|
-
const nextChar = this.input[this.pos + 1];
|
|
369
|
-
if (nextChar !== void 0 && (nextChar >= "0" && nextChar <= "9" || nextChar === ".")) {
|
|
370
|
-
return this.parseCallChain();
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
return this.parseCallChain();
|
|
374
|
-
}
|
|
375
|
-
parseCallChain() {
|
|
376
|
-
let node = this.parsePrimary();
|
|
377
|
-
while (true) {
|
|
378
|
-
this.skipWhitespace();
|
|
379
|
-
if (this.peek() === "(") {
|
|
380
|
-
this.advance();
|
|
381
|
-
const args = this.parseArgList();
|
|
382
|
-
this.expect(")");
|
|
383
|
-
if (node.type === "identifier") {
|
|
384
|
-
node = { type: "call", name: node.name, args };
|
|
385
|
-
} else if (node.type === "path") {
|
|
386
|
-
const name = node.segments.join(".");
|
|
387
|
-
node = { type: "call", name, args };
|
|
388
|
-
} else if (node.type === "member") {
|
|
389
|
-
node = { type: "method_call", object: node.object, method: node.property, args };
|
|
390
|
-
} else {
|
|
391
|
-
throw new Error("Cannot call non-function");
|
|
392
|
-
}
|
|
393
|
-
} else if (this.peek() === ".") {
|
|
394
|
-
this.advance();
|
|
395
|
-
const prop = this.parseIdentifierName();
|
|
396
|
-
node = { type: "member", object: node, property: prop };
|
|
397
|
-
} else {
|
|
398
|
-
break;
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
return node;
|
|
402
|
-
}
|
|
403
|
-
parsePrimary() {
|
|
404
|
-
this.skipWhitespace();
|
|
405
|
-
const ch = this.peek();
|
|
406
|
-
if (ch === "(") {
|
|
407
|
-
this.advance();
|
|
408
|
-
const expr2 = this.parseExpression();
|
|
409
|
-
this.skipWhitespace();
|
|
410
|
-
this.expect(")");
|
|
411
|
-
return expr2;
|
|
412
|
-
}
|
|
413
|
-
if (ch === "'" || ch === '"') {
|
|
414
|
-
return this.parseString();
|
|
415
|
-
}
|
|
416
|
-
if (ch === "-" || ch >= "0" && ch <= "9") {
|
|
417
|
-
return this.parseNumber();
|
|
418
|
-
}
|
|
419
|
-
if (this.isIdentStart(ch)) {
|
|
420
|
-
return this.parseIdentifierOrPath();
|
|
421
|
-
}
|
|
422
|
-
throw new Error(
|
|
423
|
-
`Unexpected character at position ${this.pos}: '${ch || "EOF"}'`
|
|
424
|
-
);
|
|
425
|
-
}
|
|
426
|
-
parseString() {
|
|
427
|
-
const quote = this.advance();
|
|
428
|
-
let value = "";
|
|
429
|
-
while (this.pos < this.input.length && this.peek() !== quote) {
|
|
430
|
-
if (this.peek() === "\\") {
|
|
431
|
-
this.advance();
|
|
432
|
-
const esc = this.advance();
|
|
433
|
-
if (esc === "n") value += "\n";
|
|
434
|
-
else if (esc === "t") value += " ";
|
|
435
|
-
else if (esc === "r") value += "\r";
|
|
436
|
-
else value += esc;
|
|
437
|
-
} else {
|
|
438
|
-
value += this.advance();
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
if (this.pos >= this.input.length) {
|
|
442
|
-
throw new Error("Unterminated string literal");
|
|
443
|
-
}
|
|
444
|
-
this.advance();
|
|
445
|
-
return { type: "string", value };
|
|
446
|
-
}
|
|
447
|
-
parseNumber() {
|
|
448
|
-
let numStr = "";
|
|
449
|
-
if (this.peek() === "-") {
|
|
450
|
-
numStr += this.advance();
|
|
451
|
-
}
|
|
452
|
-
while (this.pos < this.input.length && (this.input[this.pos] >= "0" && this.input[this.pos] <= "9")) {
|
|
453
|
-
numStr += this.advance();
|
|
454
|
-
}
|
|
455
|
-
if (this.peek() === "." && this.pos + 1 < this.input.length && this.input[this.pos + 1] >= "0" && this.input[this.pos + 1] <= "9") {
|
|
456
|
-
numStr += this.advance();
|
|
457
|
-
while (this.pos < this.input.length && (this.input[this.pos] >= "0" && this.input[this.pos] <= "9")) {
|
|
458
|
-
numStr += this.advance();
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
return { type: "number", value: Number(numStr) };
|
|
462
|
-
}
|
|
463
|
-
parseIdentifierOrPath() {
|
|
464
|
-
const name = this.parseIdentifierName();
|
|
465
|
-
if (name === "true") return { type: "boolean", value: true };
|
|
466
|
-
if (name === "false") return { type: "boolean", value: false };
|
|
467
|
-
if (name === "null") return { type: "null" };
|
|
468
|
-
if (name === "undefined") return { type: "null" };
|
|
469
|
-
return { type: "identifier", name };
|
|
470
|
-
}
|
|
471
|
-
parseIdentifierName() {
|
|
472
|
-
let name = "";
|
|
473
|
-
if (this.peek() === "$") name += this.advance();
|
|
474
|
-
while (this.pos < this.input.length && this.isIdentPart(this.input[this.pos])) {
|
|
475
|
-
name += this.advance();
|
|
476
|
-
}
|
|
477
|
-
if (!name) {
|
|
478
|
-
throw new Error(`Expected identifier at position ${this.pos}`);
|
|
479
|
-
}
|
|
480
|
-
return name;
|
|
481
|
-
}
|
|
482
|
-
parseArgList() {
|
|
483
|
-
this.skipWhitespace();
|
|
484
|
-
if (this.peek() === ")") return [];
|
|
485
|
-
const args = [];
|
|
486
|
-
args.push(this.parseExpression());
|
|
487
|
-
this.skipWhitespace();
|
|
488
|
-
while (this.peek() === ",") {
|
|
489
|
-
this.advance();
|
|
490
|
-
args.push(this.parseExpression());
|
|
491
|
-
this.skipWhitespace();
|
|
492
|
-
}
|
|
493
|
-
return args;
|
|
494
|
-
}
|
|
495
|
-
// Character utilities
|
|
496
|
-
peek() {
|
|
497
|
-
return this.input[this.pos] ?? "";
|
|
498
|
-
}
|
|
499
|
-
advance() {
|
|
500
|
-
return this.input[this.pos++] ?? "";
|
|
501
|
-
}
|
|
502
|
-
match(str) {
|
|
503
|
-
if (this.input.startsWith(str, this.pos)) {
|
|
504
|
-
this.pos += str.length;
|
|
505
|
-
return true;
|
|
506
|
-
}
|
|
507
|
-
return false;
|
|
508
|
-
}
|
|
509
|
-
lookAhead(str) {
|
|
510
|
-
return this.input.startsWith(str, this.pos);
|
|
511
|
-
}
|
|
512
|
-
expect(ch) {
|
|
513
|
-
this.skipWhitespace();
|
|
514
|
-
if (this.peek() !== ch) {
|
|
515
|
-
throw new Error(`Expected '${ch}' at position ${this.pos}, got '${this.peek() || "EOF"}'`);
|
|
516
|
-
}
|
|
517
|
-
this.advance();
|
|
518
|
-
}
|
|
519
|
-
skipWhitespace() {
|
|
520
|
-
while (this.pos < this.input.length && " \n\r".includes(this.input[this.pos])) {
|
|
521
|
-
this.pos++;
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
isIdentStart(ch) {
|
|
525
|
-
return ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch === "_" || ch === "$";
|
|
526
|
-
}
|
|
527
|
-
isIdentPart(ch) {
|
|
528
|
-
return this.isIdentStart(ch) || ch >= "0" && ch <= "9";
|
|
529
|
-
}
|
|
530
|
-
};
|
|
531
|
-
function evaluateAST(node, context, fnMap) {
|
|
532
|
-
switch (node.type) {
|
|
533
|
-
case "number":
|
|
534
|
-
return node.value;
|
|
535
|
-
case "string":
|
|
536
|
-
return node.value;
|
|
537
|
-
case "boolean":
|
|
538
|
-
return node.value;
|
|
539
|
-
case "null":
|
|
540
|
-
return null;
|
|
541
|
-
case "identifier":
|
|
542
|
-
return resolvePath(node.name, context);
|
|
543
|
-
case "path":
|
|
544
|
-
return resolvePath(node.segments.join("."), context);
|
|
545
|
-
case "member": {
|
|
546
|
-
const obj = evaluateAST(node.object, context, fnMap);
|
|
547
|
-
if (obj == null || typeof obj !== "object") return void 0;
|
|
548
|
-
return obj[node.property];
|
|
549
|
-
}
|
|
550
|
-
case "call": {
|
|
551
|
-
const fn = fnMap.get(node.name);
|
|
552
|
-
if (!fn) return void 0;
|
|
553
|
-
const args = node.args.map((a) => evaluateAST(a, context, fnMap));
|
|
554
|
-
return fn(...args);
|
|
555
|
-
}
|
|
556
|
-
case "method_call": {
|
|
557
|
-
const obj = evaluateAST(node.object, context, fnMap);
|
|
558
|
-
if (obj != null && typeof obj === "object") {
|
|
559
|
-
const method = obj[node.method];
|
|
560
|
-
if (typeof method === "function") {
|
|
561
|
-
const args = node.args.map((a) => evaluateAST(a, context, fnMap));
|
|
562
|
-
return method.apply(obj, args);
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
return void 0;
|
|
566
|
-
}
|
|
567
|
-
case "unary": {
|
|
568
|
-
const operand = evaluateAST(node.operand, context, fnMap);
|
|
569
|
-
return !operand;
|
|
570
|
-
}
|
|
571
|
-
case "binary": {
|
|
572
|
-
if (node.operator === "&&") {
|
|
573
|
-
const left2 = evaluateAST(node.left, context, fnMap);
|
|
574
|
-
if (!left2) return left2;
|
|
575
|
-
return evaluateAST(node.right, context, fnMap);
|
|
576
|
-
}
|
|
577
|
-
if (node.operator === "||") {
|
|
578
|
-
const left2 = evaluateAST(node.left, context, fnMap);
|
|
579
|
-
if (left2) return left2;
|
|
580
|
-
return evaluateAST(node.right, context, fnMap);
|
|
581
|
-
}
|
|
582
|
-
const left = evaluateAST(node.left, context, fnMap);
|
|
583
|
-
const right = evaluateAST(node.right, context, fnMap);
|
|
584
|
-
switch (node.operator) {
|
|
585
|
-
// eslint-disable-next-line eqeqeq
|
|
586
|
-
case "==":
|
|
587
|
-
return left == right;
|
|
588
|
-
// eslint-disable-next-line eqeqeq
|
|
589
|
-
case "!=":
|
|
590
|
-
return left != right;
|
|
591
|
-
case ">":
|
|
592
|
-
return Number(left) > Number(right);
|
|
593
|
-
case "<":
|
|
594
|
-
return Number(left) < Number(right);
|
|
595
|
-
case ">=":
|
|
596
|
-
return Number(left) >= Number(right);
|
|
597
|
-
case "<=":
|
|
598
|
-
return Number(left) <= Number(right);
|
|
599
|
-
default:
|
|
600
|
-
return void 0;
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
case "ternary": {
|
|
604
|
-
const condition = evaluateAST(node.condition, context, fnMap);
|
|
605
|
-
return condition ? evaluateAST(node.consequent, context, fnMap) : evaluateAST(node.alternate, context, fnMap);
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
var MAX_CACHE = 500;
|
|
610
|
-
var astCache = /* @__PURE__ */ new Map();
|
|
611
|
-
function evictIfNeeded() {
|
|
612
|
-
if (astCache.size > MAX_CACHE) {
|
|
613
|
-
const keys = Array.from(astCache.keys());
|
|
614
|
-
const evictCount = Math.floor(MAX_CACHE * 0.25);
|
|
615
|
-
for (let i = 0; i < evictCount; i++) {
|
|
616
|
-
astCache.delete(keys[i]);
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
function parseAndCache(expr2) {
|
|
621
|
-
const cached = astCache.get(expr2);
|
|
622
|
-
if (cached) return cached;
|
|
623
|
-
const parser = new Parser(expr2);
|
|
624
|
-
const ast = parser.parse();
|
|
625
|
-
astCache.set(expr2, ast);
|
|
626
|
-
evictIfNeeded();
|
|
627
|
-
return ast;
|
|
628
|
-
}
|
|
629
|
-
var TEMPLATE_RE = /\{\{(.+?)\}\}/g;
|
|
630
|
-
function resolvePath(path, context) {
|
|
631
|
-
const parts = path.split(".");
|
|
632
|
-
let current = context;
|
|
633
|
-
for (const part of parts) {
|
|
634
|
-
if (current == null || typeof current !== "object") return void 0;
|
|
635
|
-
current = current[part];
|
|
636
|
-
}
|
|
637
|
-
return current;
|
|
638
|
-
}
|
|
639
|
-
function evaluateExpression(expr2, context, fnMap) {
|
|
640
|
-
const trimmed = expr2.trim();
|
|
641
|
-
if (trimmed === "true") return true;
|
|
642
|
-
if (trimmed === "false") return false;
|
|
643
|
-
if (trimmed === "null") return null;
|
|
644
|
-
if (trimmed === "undefined") return void 0;
|
|
645
|
-
const num = Number(trimmed);
|
|
646
|
-
if (!isNaN(num) && trimmed !== "") return num;
|
|
647
|
-
if (trimmed.startsWith("'") && trimmed.endsWith("'") || trimmed.startsWith('"') && trimmed.endsWith('"')) {
|
|
648
|
-
return trimmed.slice(1, -1);
|
|
649
|
-
}
|
|
650
|
-
if (/^[a-zA-Z_$][\w$.]*$/.test(trimmed)) {
|
|
651
|
-
return resolvePath(trimmed, context);
|
|
652
|
-
}
|
|
653
|
-
const ast = parseAndCache(trimmed);
|
|
654
|
-
return evaluateAST(ast, context, fnMap);
|
|
655
|
-
}
|
|
656
|
-
var WEB_FAILURE_POLICIES = {
|
|
657
|
-
VIEW_BINDING: {
|
|
658
|
-
on_error: "return_fallback",
|
|
659
|
-
fallback_value: "",
|
|
660
|
-
log_level: "warn"
|
|
661
|
-
},
|
|
662
|
-
EVENT_REACTION: {
|
|
663
|
-
on_error: "log_and_skip",
|
|
664
|
-
fallback_value: void 0,
|
|
665
|
-
log_level: "error"
|
|
666
|
-
},
|
|
667
|
-
DURING_ACTION: {
|
|
668
|
-
on_error: "log_and_skip",
|
|
669
|
-
fallback_value: void 0,
|
|
670
|
-
log_level: "error"
|
|
671
|
-
},
|
|
672
|
-
CONDITIONAL_VISIBILITY: {
|
|
673
|
-
on_error: "return_fallback",
|
|
674
|
-
fallback_value: true,
|
|
675
|
-
// Show by default if condition fails
|
|
676
|
-
log_level: "warn"
|
|
677
|
-
}
|
|
678
|
-
};
|
|
679
|
-
function createEvaluator(config) {
|
|
680
|
-
const allFunctions = [...CORE_FUNCTIONS, ...config.functions];
|
|
681
|
-
const fnMap = buildFunctionMap(allFunctions);
|
|
682
|
-
const policy = config.failurePolicy;
|
|
683
|
-
function handleError(expr2, error) {
|
|
684
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
685
|
-
if (policy.log_level === "error") {
|
|
686
|
-
console.error(`[player-core] Expression error: "${expr2}" \u2014 ${message}`);
|
|
687
|
-
} else if (policy.log_level === "warn") {
|
|
688
|
-
console.warn(`[player-core] Expression error: "${expr2}" \u2014 ${message}`);
|
|
689
|
-
}
|
|
690
|
-
switch (policy.on_error) {
|
|
691
|
-
case "throw":
|
|
692
|
-
throw error;
|
|
693
|
-
case "return_fallback":
|
|
694
|
-
return { value: policy.fallback_value, status: "fallback", error: message };
|
|
695
|
-
case "log_and_skip":
|
|
696
|
-
default:
|
|
697
|
-
return { value: policy.fallback_value, status: "error", error: message };
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
return {
|
|
701
|
-
evaluate(expression, context) {
|
|
702
|
-
try {
|
|
703
|
-
const value = evaluateExpression(expression, context, fnMap);
|
|
704
|
-
return { value, status: "ok" };
|
|
705
|
-
} catch (error) {
|
|
706
|
-
return handleError(expression, error);
|
|
707
|
-
}
|
|
708
|
-
},
|
|
709
|
-
evaluateTemplate(template, context) {
|
|
710
|
-
try {
|
|
711
|
-
if (!template.includes("{{")) {
|
|
712
|
-
return { value: template, status: "ok" };
|
|
713
|
-
}
|
|
714
|
-
const result = template.replace(TEMPLATE_RE, (_match, expr2) => {
|
|
715
|
-
const value = evaluateExpression(expr2, context, fnMap);
|
|
716
|
-
return value != null ? String(value) : "";
|
|
717
|
-
});
|
|
718
|
-
return { value: result, status: "ok" };
|
|
719
|
-
} catch (error) {
|
|
720
|
-
return handleError(template, error);
|
|
721
|
-
}
|
|
722
|
-
},
|
|
723
|
-
validate(expression) {
|
|
724
|
-
const errors = [];
|
|
725
|
-
try {
|
|
726
|
-
parseAndCache(expression);
|
|
727
|
-
} catch (e) {
|
|
728
|
-
errors.push(e instanceof Error ? e.message : String(e));
|
|
729
|
-
}
|
|
730
|
-
return { valid: errors.length === 0, errors };
|
|
731
|
-
}
|
|
732
|
-
};
|
|
733
|
-
}
|
|
734
|
-
var MAX_AUTO_CHAIN = 10;
|
|
735
|
-
var StateMachine = class {
|
|
736
|
-
evaluator;
|
|
737
|
-
actionHandlers;
|
|
738
|
-
listeners = /* @__PURE__ */ new Set();
|
|
739
|
-
instance;
|
|
740
|
-
constructor(definition, initialData = {}, config) {
|
|
741
|
-
this.evaluator = config.evaluator;
|
|
742
|
-
this.actionHandlers = config.actionHandlers ?? /* @__PURE__ */ new Map();
|
|
743
|
-
const startState = definition.states.find((s) => s.type === "START");
|
|
744
|
-
if (!startState) {
|
|
745
|
-
throw new Error(`No START state found in definition ${definition.slug}`);
|
|
746
|
-
}
|
|
747
|
-
this.instance = {
|
|
748
|
-
definition,
|
|
749
|
-
current_state: startState.name,
|
|
750
|
-
state_data: { ...initialData },
|
|
751
|
-
memory: {},
|
|
752
|
-
status: "ACTIVE"
|
|
753
|
-
};
|
|
754
|
-
}
|
|
755
|
-
/** Get the current instance snapshot (immutable copy) */
|
|
756
|
-
getSnapshot() {
|
|
757
|
-
return { ...this.instance, state_data: { ...this.instance.state_data }, memory: { ...this.instance.memory } };
|
|
758
|
-
}
|
|
759
|
-
/** Get current state name */
|
|
760
|
-
get currentState() {
|
|
761
|
-
return this.instance.current_state;
|
|
762
|
-
}
|
|
763
|
-
/** Get current state_data */
|
|
764
|
-
get stateData() {
|
|
765
|
-
return this.instance.state_data;
|
|
766
|
-
}
|
|
767
|
-
/** Get current status */
|
|
768
|
-
get status() {
|
|
769
|
-
return this.instance.status;
|
|
770
|
-
}
|
|
771
|
-
/** Subscribe to state machine events */
|
|
772
|
-
on(listener) {
|
|
773
|
-
this.listeners.add(listener);
|
|
774
|
-
return () => this.listeners.delete(listener);
|
|
775
|
-
}
|
|
776
|
-
/** Register an action handler */
|
|
777
|
-
registerAction(type, handler) {
|
|
778
|
-
this.actionHandlers.set(type, handler);
|
|
779
|
-
}
|
|
780
|
-
/** Execute a named transition */
|
|
781
|
-
async transition(transitionName, data) {
|
|
782
|
-
if (this.instance.status !== "ACTIVE") {
|
|
783
|
-
return {
|
|
784
|
-
success: false,
|
|
785
|
-
from_state: this.instance.current_state,
|
|
786
|
-
to_state: this.instance.current_state,
|
|
787
|
-
actions_executed: [],
|
|
788
|
-
error: `Cannot transition: instance status is ${this.instance.status}`
|
|
789
|
-
};
|
|
790
|
-
}
|
|
791
|
-
const transition2 = this.instance.definition.transitions.find(
|
|
792
|
-
(t) => t.name === transitionName && t.from.includes(this.instance.current_state)
|
|
793
|
-
);
|
|
794
|
-
if (!transition2) {
|
|
795
|
-
return {
|
|
796
|
-
success: false,
|
|
797
|
-
from_state: this.instance.current_state,
|
|
798
|
-
to_state: this.instance.current_state,
|
|
799
|
-
actions_executed: [],
|
|
800
|
-
error: `Transition "${transitionName}" not valid from state "${this.instance.current_state}"`
|
|
801
|
-
};
|
|
802
|
-
}
|
|
803
|
-
if (data) {
|
|
804
|
-
this.instance.state_data = { ...this.instance.state_data, ...data };
|
|
805
|
-
}
|
|
806
|
-
if (transition2.conditions && transition2.conditions.length > 0) {
|
|
807
|
-
const ctx = this.buildContext();
|
|
808
|
-
for (const condition of transition2.conditions) {
|
|
809
|
-
const result2 = this.evaluator.evaluate(condition, ctx);
|
|
810
|
-
if (!result2.value) {
|
|
811
|
-
return {
|
|
812
|
-
success: false,
|
|
813
|
-
from_state: this.instance.current_state,
|
|
814
|
-
to_state: this.instance.current_state,
|
|
815
|
-
actions_executed: [],
|
|
816
|
-
error: `Transition condition not met: ${condition}`
|
|
817
|
-
};
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
const result = await this.executeTransition(transition2);
|
|
822
|
-
if (result.success) {
|
|
823
|
-
await this.drainAutoTransitions();
|
|
824
|
-
}
|
|
825
|
-
return result;
|
|
826
|
-
}
|
|
827
|
-
/** Update state_data directly (for on_event set_field actions) */
|
|
828
|
-
setField(field2, value) {
|
|
829
|
-
this.instance.state_data = { ...this.instance.state_data, [field2]: value };
|
|
830
|
-
}
|
|
831
|
-
/** Update memory */
|
|
832
|
-
setMemory(key, value) {
|
|
833
|
-
this.instance.memory = { ...this.instance.memory, [key]: value };
|
|
834
|
-
}
|
|
835
|
-
/** Get available transitions from the current state */
|
|
836
|
-
getAvailableTransitions() {
|
|
837
|
-
return this.instance.definition.transitions.filter(
|
|
838
|
-
(t) => t.from.includes(this.instance.current_state) && !t.auto
|
|
839
|
-
);
|
|
840
|
-
}
|
|
841
|
-
/** Get the current state definition */
|
|
842
|
-
getCurrentStateDefinition() {
|
|
843
|
-
return this.instance.definition.states.find((s) => s.name === this.instance.current_state);
|
|
844
|
-
}
|
|
845
|
-
// ===========================================================================
|
|
846
|
-
// Private implementation
|
|
847
|
-
// ===========================================================================
|
|
848
|
-
async executeTransition(transition2) {
|
|
849
|
-
const fromState = this.instance.current_state;
|
|
850
|
-
const allActionsExecuted = [];
|
|
851
|
-
const fromStateDef = this.getCurrentStateDefinition();
|
|
852
|
-
if (fromStateDef?.on_exit) {
|
|
853
|
-
await this.executeActions(fromStateDef.on_exit, allActionsExecuted);
|
|
854
|
-
}
|
|
855
|
-
this.emit({
|
|
856
|
-
type: "state_exit",
|
|
857
|
-
instance_id: this.instance.definition.id,
|
|
858
|
-
from_state: fromState
|
|
859
|
-
});
|
|
860
|
-
if (transition2.actions) {
|
|
861
|
-
await this.executeActions(transition2.actions, allActionsExecuted);
|
|
862
|
-
}
|
|
863
|
-
this.instance.current_state = transition2.to;
|
|
864
|
-
const toStateDef = this.instance.definition.states.find((s) => s.name === transition2.to);
|
|
865
|
-
if (toStateDef?.type === "END") {
|
|
866
|
-
this.instance.status = "COMPLETED";
|
|
867
|
-
} else if (toStateDef?.type === "CANCELLED") {
|
|
868
|
-
this.instance.status = "CANCELLED";
|
|
869
|
-
}
|
|
870
|
-
this.emit({
|
|
871
|
-
type: "state_enter",
|
|
872
|
-
instance_id: this.instance.definition.id,
|
|
873
|
-
to_state: transition2.to
|
|
874
|
-
});
|
|
875
|
-
if (toStateDef?.on_enter) {
|
|
876
|
-
await this.executeActions(toStateDef.on_enter, allActionsExecuted);
|
|
877
|
-
}
|
|
878
|
-
this.emit({
|
|
879
|
-
type: "transition",
|
|
880
|
-
instance_id: this.instance.definition.id,
|
|
881
|
-
from_state: fromState,
|
|
882
|
-
to_state: transition2.to
|
|
883
|
-
});
|
|
884
|
-
return {
|
|
885
|
-
success: true,
|
|
886
|
-
from_state: fromState,
|
|
887
|
-
to_state: transition2.to,
|
|
888
|
-
actions_executed: allActionsExecuted
|
|
889
|
-
};
|
|
890
|
-
}
|
|
891
|
-
async drainAutoTransitions() {
|
|
892
|
-
for (let depth = 0; depth < MAX_AUTO_CHAIN; depth++) {
|
|
893
|
-
if (this.instance.status !== "ACTIVE") break;
|
|
894
|
-
const autoTransition = this.findMatchingAutoTransition();
|
|
895
|
-
if (!autoTransition) break;
|
|
896
|
-
const result = await this.executeTransition(autoTransition);
|
|
897
|
-
if (!result.success) break;
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
findMatchingAutoTransition() {
|
|
901
|
-
const candidates = this.instance.definition.transitions.filter(
|
|
902
|
-
(t) => t.auto && t.from.includes(this.instance.current_state)
|
|
903
|
-
);
|
|
904
|
-
const ctx = this.buildContext();
|
|
905
|
-
for (const candidate of candidates) {
|
|
906
|
-
if (!candidate.conditions || candidate.conditions.length === 0) {
|
|
907
|
-
return candidate;
|
|
908
|
-
}
|
|
909
|
-
const allMet = candidate.conditions.every((condition) => {
|
|
910
|
-
const result = this.evaluator.evaluate(condition, ctx);
|
|
911
|
-
return result.value === true;
|
|
912
|
-
});
|
|
913
|
-
if (allMet) return candidate;
|
|
914
|
-
}
|
|
915
|
-
return null;
|
|
916
|
-
}
|
|
917
|
-
async executeActions(actions, collector) {
|
|
918
|
-
const ctx = this.buildContext();
|
|
919
|
-
for (const action2 of actions) {
|
|
920
|
-
if (action2.condition) {
|
|
921
|
-
const condResult = this.evaluator.evaluate(action2.condition, ctx);
|
|
922
|
-
if (!condResult.value) continue;
|
|
923
|
-
}
|
|
924
|
-
const handler = this.actionHandlers.get(action2.type);
|
|
925
|
-
if (handler) {
|
|
926
|
-
try {
|
|
927
|
-
await handler(action2, ctx);
|
|
928
|
-
collector.push(action2);
|
|
929
|
-
this.emit({
|
|
930
|
-
type: "action_executed",
|
|
931
|
-
instance_id: this.instance.definition.id,
|
|
932
|
-
action: action2
|
|
933
|
-
});
|
|
934
|
-
} catch (error) {
|
|
935
|
-
this.emit({
|
|
936
|
-
type: "error",
|
|
937
|
-
instance_id: this.instance.definition.id,
|
|
938
|
-
action: action2,
|
|
939
|
-
error: error instanceof Error ? error.message : String(error)
|
|
940
|
-
});
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
buildContext() {
|
|
946
|
-
return {
|
|
947
|
-
state_data: this.instance.state_data,
|
|
948
|
-
memory: this.instance.memory,
|
|
949
|
-
current_state: this.instance.current_state,
|
|
950
|
-
status: this.instance.status,
|
|
951
|
-
// Spread state_data for direct field access (e.g., "title" instead of "state_data.title")
|
|
952
|
-
...this.instance.state_data
|
|
953
|
-
};
|
|
954
|
-
}
|
|
955
|
-
emit(event) {
|
|
956
|
-
for (const listener of this.listeners) {
|
|
957
|
-
try {
|
|
958
|
-
listener(event);
|
|
959
|
-
} catch {
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
};
|
|
964
|
-
var patternCache = /* @__PURE__ */ new Map();
|
|
965
|
-
var MAX_CACHE2 = 200;
|
|
966
|
-
function compilePattern(pattern) {
|
|
967
|
-
const cached = patternCache.get(pattern);
|
|
968
|
-
if (cached) return cached;
|
|
969
|
-
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "<<DOUBLESTAR>>").replace(/\*/g, "[^:.]+").replace(/<<DOUBLESTAR>>/g, ".*");
|
|
970
|
-
const regex = new RegExp(`^${escaped}$`);
|
|
971
|
-
if (patternCache.size >= MAX_CACHE2) {
|
|
972
|
-
const firstKey = patternCache.keys().next().value;
|
|
973
|
-
if (firstKey) patternCache.delete(firstKey);
|
|
974
|
-
}
|
|
975
|
-
patternCache.set(pattern, regex);
|
|
976
|
-
return regex;
|
|
977
|
-
}
|
|
978
|
-
function matchTopic(pattern, topic) {
|
|
979
|
-
return pattern.test(topic);
|
|
980
|
-
}
|
|
981
|
-
var EventBus = class {
|
|
982
|
-
subscriptions = [];
|
|
983
|
-
/**
|
|
984
|
-
* Subscribe to events matching a glob pattern.
|
|
985
|
-
* Returns an unsubscribe function.
|
|
986
|
-
*/
|
|
987
|
-
subscribe(pattern, handler) {
|
|
988
|
-
const regex = compilePattern(pattern);
|
|
989
|
-
const subscription = { pattern, regex, handler };
|
|
990
|
-
this.subscriptions.push(subscription);
|
|
991
|
-
return () => {
|
|
992
|
-
const idx = this.subscriptions.indexOf(subscription);
|
|
993
|
-
if (idx !== -1) this.subscriptions.splice(idx, 1);
|
|
994
|
-
};
|
|
995
|
-
}
|
|
996
|
-
/**
|
|
997
|
-
* Publish an event. All matching subscriptions fire (async).
|
|
998
|
-
* Errors in handlers are caught and logged, never propagated.
|
|
999
|
-
*/
|
|
1000
|
-
async publish(topic, payload = {}) {
|
|
1001
|
-
const event = { topic, payload };
|
|
1002
|
-
for (const sub of this.subscriptions) {
|
|
1003
|
-
if (matchTopic(sub.regex, topic)) {
|
|
1004
|
-
try {
|
|
1005
|
-
await sub.handler(event);
|
|
1006
|
-
} catch (error) {
|
|
1007
|
-
console.warn(
|
|
1008
|
-
`[player-core] Event handler error for pattern "${sub.pattern}" on topic "${topic}":`,
|
|
1009
|
-
error
|
|
1010
|
-
);
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
/**
|
|
1016
|
-
* Publish synchronously (fire-and-forget).
|
|
1017
|
-
* Useful when you don't need to await handler completion.
|
|
1018
|
-
*/
|
|
1019
|
-
emit(topic, payload = {}) {
|
|
1020
|
-
void this.publish(topic, payload);
|
|
1021
|
-
}
|
|
1022
|
-
/** Get count of active subscriptions */
|
|
1023
|
-
get size() {
|
|
1024
|
-
return this.subscriptions.length;
|
|
1025
|
-
}
|
|
1026
|
-
/** Remove all subscriptions */
|
|
1027
|
-
clear() {
|
|
1028
|
-
this.subscriptions.length = 0;
|
|
1029
|
-
}
|
|
1030
|
-
};
|
|
1031
|
-
var ActionDispatcher = class {
|
|
1032
|
-
handlers = /* @__PURE__ */ new Map();
|
|
1033
|
-
/** Register a handler for an action type */
|
|
1034
|
-
register(type, handler) {
|
|
1035
|
-
this.handlers.set(type, handler);
|
|
1036
|
-
}
|
|
1037
|
-
/** Unregister a handler */
|
|
1038
|
-
unregister(type) {
|
|
1039
|
-
this.handlers.delete(type);
|
|
1040
|
-
}
|
|
1041
|
-
/** Check if a handler is registered for the given type */
|
|
1042
|
-
has(type) {
|
|
1043
|
-
return this.handlers.has(type);
|
|
1044
|
-
}
|
|
1045
|
-
/**
|
|
1046
|
-
* Execute a list of actions sequentially.
|
|
1047
|
-
* Each action's condition is evaluated first (if present).
|
|
1048
|
-
* Missing handlers are skipped with a warning.
|
|
1049
|
-
*/
|
|
1050
|
-
async execute(actions, context, evaluator) {
|
|
1051
|
-
const results = [];
|
|
1052
|
-
for (const action2 of actions) {
|
|
1053
|
-
if (action2.condition && evaluator) {
|
|
1054
|
-
const condResult = evaluator.evaluate(action2.condition, context);
|
|
1055
|
-
if (!condResult.value) continue;
|
|
1056
|
-
}
|
|
1057
|
-
const handler = this.handlers.get(action2.type);
|
|
1058
|
-
if (!handler) {
|
|
1059
|
-
console.warn(`[player-core] No handler registered for action type "${action2.type}"`);
|
|
1060
|
-
results.push({ type: action2.type, success: false, error: `No handler for "${action2.type}"` });
|
|
1061
|
-
continue;
|
|
1062
|
-
}
|
|
1063
|
-
try {
|
|
1064
|
-
await handler(action2.config, context);
|
|
1065
|
-
results.push({ type: action2.type, success: true });
|
|
1066
|
-
} catch (error) {
|
|
1067
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1068
|
-
console.warn(`[player-core] Action "${action2.type}" failed: ${message}`);
|
|
1069
|
-
results.push({ type: action2.type, success: false, error: message });
|
|
1070
|
-
}
|
|
1071
|
-
}
|
|
1072
|
-
return results;
|
|
1073
|
-
}
|
|
1074
|
-
/** Get count of registered handlers */
|
|
1075
|
-
get size() {
|
|
1076
|
-
return this.handlers.size;
|
|
1077
|
-
}
|
|
1078
|
-
/** Remove all handlers */
|
|
1079
|
-
clear() {
|
|
1080
|
-
this.handlers.clear();
|
|
1081
|
-
}
|
|
1082
|
-
};
|
|
1083
|
-
|
|
1084
1
|
// src/core/WorkflowRuntime.ts
|
|
2
|
+
import {
|
|
3
|
+
StateMachine,
|
|
4
|
+
EventBus,
|
|
5
|
+
ActionDispatcher,
|
|
6
|
+
createEvaluator,
|
|
7
|
+
WEB_FAILURE_POLICIES
|
|
8
|
+
} from "@mmapp/player-core";
|
|
1085
9
|
var WorkflowRuntime = class {
|
|
1086
10
|
sm;
|
|
1087
11
|
eventBus;
|
|
@@ -1180,24 +104,24 @@ import { useEffect, useRef } from "react";
|
|
|
1180
104
|
import { createContext, useContext } from "react";
|
|
1181
105
|
var RuntimeContext = createContext(null);
|
|
1182
106
|
function useRuntimeContext() {
|
|
1183
|
-
const
|
|
1184
|
-
if (!
|
|
107
|
+
const runtime2 = useContext(RuntimeContext);
|
|
108
|
+
if (!runtime2) {
|
|
1185
109
|
throw new Error(
|
|
1186
110
|
"useRuntimeContext must be used within a WorkflowProvider or RuntimeContext.Provider"
|
|
1187
111
|
);
|
|
1188
112
|
}
|
|
1189
|
-
return
|
|
113
|
+
return runtime2;
|
|
1190
114
|
}
|
|
1191
115
|
|
|
1192
116
|
// src/hooks/useOnEnter.ts
|
|
1193
117
|
function useOnEnter(stateName, effect) {
|
|
1194
|
-
const
|
|
118
|
+
const runtime2 = useRuntimeContext();
|
|
1195
119
|
const effectRef = useRef(effect);
|
|
1196
120
|
effectRef.current = effect;
|
|
1197
121
|
const cleanupRef = useRef(null);
|
|
1198
122
|
const states = Array.isArray(stateName) ? stateName : [stateName];
|
|
1199
123
|
useEffect(() => {
|
|
1200
|
-
if (states.includes(
|
|
124
|
+
if (states.includes(runtime2.sm.currentState)) {
|
|
1201
125
|
const result = effectRef.current();
|
|
1202
126
|
if (result instanceof Promise) {
|
|
1203
127
|
result.then((cleanup) => {
|
|
@@ -1207,7 +131,7 @@ function useOnEnter(stateName, effect) {
|
|
|
1207
131
|
cleanupRef.current = result;
|
|
1208
132
|
}
|
|
1209
133
|
}
|
|
1210
|
-
const unsub =
|
|
134
|
+
const unsub = runtime2.sm.on((event) => {
|
|
1211
135
|
if (event.type === "state_enter" && event.to_state && states.includes(event.to_state)) {
|
|
1212
136
|
cleanupRef.current?.();
|
|
1213
137
|
const result = effectRef.current();
|
|
@@ -1228,34 +152,34 @@ function useOnEnter(stateName, effect) {
|
|
|
1228
152
|
unsub();
|
|
1229
153
|
cleanupRef.current?.();
|
|
1230
154
|
};
|
|
1231
|
-
}, [
|
|
155
|
+
}, [runtime2, ...states]);
|
|
1232
156
|
}
|
|
1233
157
|
|
|
1234
158
|
// src/hooks/useOnExit.ts
|
|
1235
159
|
import { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
1236
160
|
function useOnExit(stateName, effect) {
|
|
1237
|
-
const
|
|
161
|
+
const runtime2 = useRuntimeContext();
|
|
1238
162
|
const effectRef = useRef2(effect);
|
|
1239
163
|
effectRef.current = effect;
|
|
1240
164
|
const states = Array.isArray(stateName) ? stateName : [stateName];
|
|
1241
165
|
useEffect2(() => {
|
|
1242
|
-
const unsub =
|
|
166
|
+
const unsub = runtime2.sm.on((event) => {
|
|
1243
167
|
if (event.type === "state_exit" && event.from_state && states.includes(event.from_state)) {
|
|
1244
168
|
effectRef.current();
|
|
1245
169
|
}
|
|
1246
170
|
});
|
|
1247
171
|
return unsub;
|
|
1248
|
-
}, [
|
|
172
|
+
}, [runtime2, ...states]);
|
|
1249
173
|
}
|
|
1250
174
|
|
|
1251
175
|
// src/hooks/useOnTransition.ts
|
|
1252
176
|
import { useEffect as useEffect3, useRef as useRef3 } from "react";
|
|
1253
177
|
function useOnTransition(effect) {
|
|
1254
|
-
const
|
|
178
|
+
const runtime2 = useRuntimeContext();
|
|
1255
179
|
const effectRef = useRef3(effect);
|
|
1256
180
|
effectRef.current = effect;
|
|
1257
181
|
useEffect3(() => {
|
|
1258
|
-
const unsub =
|
|
182
|
+
const unsub = runtime2.sm.on((event) => {
|
|
1259
183
|
if (event.type === "transition") {
|
|
1260
184
|
effectRef.current({
|
|
1261
185
|
from: event.from_state,
|
|
@@ -1264,33 +188,33 @@ function useOnTransition(effect) {
|
|
|
1264
188
|
}
|
|
1265
189
|
});
|
|
1266
190
|
return unsub;
|
|
1267
|
-
}, [
|
|
191
|
+
}, [runtime2]);
|
|
1268
192
|
}
|
|
1269
193
|
|
|
1270
194
|
// src/hooks/useOnEvent.ts
|
|
1271
195
|
import { useEffect as useEffect4, useRef as useRef4 } from "react";
|
|
1272
196
|
function useOnEvent(pattern, handler, options) {
|
|
1273
|
-
const
|
|
197
|
+
const runtime2 = useRuntimeContext();
|
|
1274
198
|
const handlerRef = useRef4(handler);
|
|
1275
199
|
handlerRef.current = handler;
|
|
1276
200
|
useEffect4(() => {
|
|
1277
|
-
const unsub =
|
|
1278
|
-
if (options?.while &&
|
|
201
|
+
const unsub = runtime2.eventBus.subscribe(pattern, (event) => {
|
|
202
|
+
if (options?.while && runtime2.sm.currentState !== options.while) return;
|
|
1279
203
|
handlerRef.current(event);
|
|
1280
204
|
});
|
|
1281
205
|
return unsub;
|
|
1282
|
-
}, [
|
|
206
|
+
}, [runtime2, pattern, options?.while]);
|
|
1283
207
|
}
|
|
1284
208
|
|
|
1285
209
|
// src/hooks/useOnChange.ts
|
|
1286
210
|
import { useEffect as useEffect5, useRef as useRef5 } from "react";
|
|
1287
211
|
function useOnChange(field2, handler) {
|
|
1288
|
-
const
|
|
212
|
+
const runtime2 = useRuntimeContext();
|
|
1289
213
|
const handlerRef = useRef5(handler);
|
|
1290
214
|
handlerRef.current = handler;
|
|
1291
|
-
const prevRef = useRef5(
|
|
215
|
+
const prevRef = useRef5(runtime2.sm.stateData[field2]);
|
|
1292
216
|
useEffect5(() => {
|
|
1293
|
-
const unsub =
|
|
217
|
+
const unsub = runtime2.subscribe((snap) => {
|
|
1294
218
|
const newVal = snap.stateData[field2];
|
|
1295
219
|
if (newVal !== prevRef.current) {
|
|
1296
220
|
handlerRef.current(newVal, prevRef.current);
|
|
@@ -1298,13 +222,13 @@ function useOnChange(field2, handler) {
|
|
|
1298
222
|
}
|
|
1299
223
|
});
|
|
1300
224
|
return unsub;
|
|
1301
|
-
}, [
|
|
225
|
+
}, [runtime2, field2]);
|
|
1302
226
|
}
|
|
1303
227
|
|
|
1304
228
|
// src/hooks/useWhileIn.ts
|
|
1305
229
|
import { useEffect as useEffect6, useRef as useRef6 } from "react";
|
|
1306
230
|
function useWhileIn(stateName, intervalMs, effect) {
|
|
1307
|
-
const
|
|
231
|
+
const runtime2 = useRuntimeContext();
|
|
1308
232
|
const effectRef = useRef6(effect);
|
|
1309
233
|
effectRef.current = effect;
|
|
1310
234
|
useEffect6(() => {
|
|
@@ -1319,8 +243,8 @@ function useWhileIn(stateName, intervalMs, effect) {
|
|
|
1319
243
|
timer = null;
|
|
1320
244
|
}
|
|
1321
245
|
}
|
|
1322
|
-
if (
|
|
1323
|
-
const unsub =
|
|
246
|
+
if (runtime2.sm.currentState === stateName) startInterval();
|
|
247
|
+
const unsub = runtime2.sm.on((event) => {
|
|
1324
248
|
if (event.type === "state_enter" && event.to_state === stateName) startInterval();
|
|
1325
249
|
if (event.type === "state_exit" && event.from_state === stateName) stopInterval();
|
|
1326
250
|
});
|
|
@@ -1328,13 +252,13 @@ function useWhileIn(stateName, intervalMs, effect) {
|
|
|
1328
252
|
unsub();
|
|
1329
253
|
stopInterval();
|
|
1330
254
|
};
|
|
1331
|
-
}, [
|
|
255
|
+
}, [runtime2, stateName, intervalMs]);
|
|
1332
256
|
}
|
|
1333
257
|
|
|
1334
258
|
// src/hooks/useDuringAction.ts
|
|
1335
259
|
import { useEffect as useEffect7, useRef as useRef7 } from "react";
|
|
1336
260
|
function useDuringAction(config) {
|
|
1337
|
-
const
|
|
261
|
+
const runtime2 = useRuntimeContext();
|
|
1338
262
|
const actionRef = useRef7(config.action);
|
|
1339
263
|
actionRef.current = config.action;
|
|
1340
264
|
const states = Array.isArray(config.state) ? config.state : [config.state];
|
|
@@ -1372,10 +296,10 @@ function useDuringAction(config) {
|
|
|
1372
296
|
timer = null;
|
|
1373
297
|
}
|
|
1374
298
|
}
|
|
1375
|
-
if (states.includes(
|
|
299
|
+
if (states.includes(runtime2.sm.currentState)) {
|
|
1376
300
|
startAction();
|
|
1377
301
|
}
|
|
1378
|
-
const unsub =
|
|
302
|
+
const unsub = runtime2.sm.on((event) => {
|
|
1379
303
|
if (event.type === "state_enter" && event.to_state && states.includes(event.to_state)) {
|
|
1380
304
|
startAction();
|
|
1381
305
|
}
|
|
@@ -1387,7 +311,7 @@ function useDuringAction(config) {
|
|
|
1387
311
|
unsub();
|
|
1388
312
|
stopAction();
|
|
1389
313
|
};
|
|
1390
|
-
}, [
|
|
314
|
+
}, [runtime2, intervalMs, immediate, enabled, ...states]);
|
|
1391
315
|
}
|
|
1392
316
|
|
|
1393
317
|
// src/hooks/useQuery.ts
|
|
@@ -1880,29 +804,29 @@ function useServerState(instanceId, options = {}) {
|
|
|
1880
804
|
// src/hooks/useWorkflow.ts
|
|
1881
805
|
import { useState as useState7, useEffect as useEffect12, useMemo, useCallback as useCallback7 } from "react";
|
|
1882
806
|
function useWorkflow(definition, options) {
|
|
1883
|
-
const
|
|
807
|
+
const runtime2 = useMemo(() => new WorkflowRuntime({
|
|
1884
808
|
definition,
|
|
1885
809
|
initialData: options?.initialData,
|
|
1886
810
|
actionHandlers: options?.actionHandlers
|
|
1887
811
|
}), [definition.id]);
|
|
1888
|
-
const [snapshot, setSnapshot] = useState7(() =>
|
|
812
|
+
const [snapshot, setSnapshot] = useState7(() => runtime2.getSnapshot());
|
|
1889
813
|
useEffect12(() => {
|
|
1890
|
-
const unsub =
|
|
814
|
+
const unsub = runtime2.subscribe(setSnapshot);
|
|
1891
815
|
return unsub;
|
|
1892
|
-
}, [
|
|
816
|
+
}, [runtime2]);
|
|
1893
817
|
const transition2 = useCallback7(async (name, data) => {
|
|
1894
|
-
const result = await
|
|
818
|
+
const result = await runtime2.transition(name, data);
|
|
1895
819
|
options?.onTransition?.(result);
|
|
1896
820
|
return result;
|
|
1897
|
-
}, [
|
|
821
|
+
}, [runtime2, options?.onTransition]);
|
|
1898
822
|
const handle = {
|
|
1899
823
|
slug: definition.slug,
|
|
1900
824
|
...snapshot,
|
|
1901
825
|
transition: transition2,
|
|
1902
|
-
setField:
|
|
1903
|
-
setMemory:
|
|
1904
|
-
publishEvent:
|
|
1905
|
-
runtime
|
|
826
|
+
setField: runtime2.setField.bind(runtime2),
|
|
827
|
+
setMemory: runtime2.setMemory.bind(runtime2),
|
|
828
|
+
publishEvent: runtime2.publishEvent.bind(runtime2),
|
|
829
|
+
runtime: runtime2
|
|
1906
830
|
};
|
|
1907
831
|
return handle;
|
|
1908
832
|
}
|
|
@@ -1910,17 +834,17 @@ function useWorkflow(definition, options) {
|
|
|
1910
834
|
// src/hooks/useTransition.ts
|
|
1911
835
|
import { useCallback as useCallback8, useState as useState8 } from "react";
|
|
1912
836
|
function useTransition(transitionName, _config) {
|
|
1913
|
-
const
|
|
837
|
+
const runtime2 = useRuntimeContext();
|
|
1914
838
|
const [pending, setPending] = useState8(false);
|
|
1915
|
-
const available =
|
|
839
|
+
const available = runtime2.sm.getAvailableTransitions().some((t) => t.name === transitionName);
|
|
1916
840
|
const fire = useCallback8(async (data) => {
|
|
1917
841
|
setPending(true);
|
|
1918
842
|
try {
|
|
1919
|
-
return await
|
|
843
|
+
return await runtime2.transition(transitionName, data);
|
|
1920
844
|
} finally {
|
|
1921
845
|
setPending(false);
|
|
1922
846
|
}
|
|
1923
|
-
}, [
|
|
847
|
+
}, [runtime2, transitionName]);
|
|
1924
848
|
const handle = { fire, available, pending };
|
|
1925
849
|
return handle;
|
|
1926
850
|
}
|
|
@@ -1932,12 +856,12 @@ function setRoleHierarchy(hierarchy) {
|
|
|
1932
856
|
_globalHierarchy = hierarchy;
|
|
1933
857
|
}
|
|
1934
858
|
function useRole(roleName, options = {}) {
|
|
1935
|
-
const
|
|
859
|
+
const runtime2 = useRuntimeContext();
|
|
1936
860
|
const hierarchy = options.hierarchy ?? _globalHierarchy ?? [];
|
|
1937
861
|
const inheritPermissions = options.inheritPermissions ?? true;
|
|
1938
862
|
const result = useMemo2(() => {
|
|
1939
|
-
const snapshot =
|
|
1940
|
-
const definition =
|
|
863
|
+
const snapshot = runtime2.getSnapshot();
|
|
864
|
+
const definition = runtime2.config?.definition;
|
|
1941
865
|
const userRoles = snapshot.stateData?._userRoles ?? snapshot.stateData?.user_roles ?? [];
|
|
1942
866
|
let hasRole2 = userRoles.includes(roleName);
|
|
1943
867
|
if (!hasRole2 && hierarchy.length > 0) {
|
|
@@ -1985,7 +909,7 @@ function useRole(roleName, options = {}) {
|
|
|
1985
909
|
}
|
|
1986
910
|
}
|
|
1987
911
|
return { hasRole: hasRole2, permissions, roles: userRoles, highestRole };
|
|
1988
|
-
}, [
|
|
912
|
+
}, [runtime2, roleName, hierarchy, inheritPermissions]);
|
|
1989
913
|
const isAbove = useCallback9(
|
|
1990
914
|
(role) => {
|
|
1991
915
|
if (hierarchy.length === 0) return false;
|
|
@@ -2036,21 +960,21 @@ function useRole(roleName, options = {}) {
|
|
|
2036
960
|
// src/hooks/useParams.ts
|
|
2037
961
|
import { useMemo as useMemo3 } from "react";
|
|
2038
962
|
function useParams() {
|
|
2039
|
-
const
|
|
963
|
+
const runtime2 = useRuntimeContext();
|
|
2040
964
|
return useMemo3(() => {
|
|
2041
|
-
const snapshot =
|
|
965
|
+
const snapshot = runtime2.getSnapshot();
|
|
2042
966
|
const params = snapshot.stateData?._params ?? snapshot.memory?._callParams ?? {};
|
|
2043
967
|
return params;
|
|
2044
|
-
}, [
|
|
968
|
+
}, [runtime2]);
|
|
2045
969
|
}
|
|
2046
970
|
|
|
2047
971
|
// src/hooks/usePackage.ts
|
|
2048
972
|
import { useMemo as useMemo4 } from "react";
|
|
2049
973
|
function usePackage(packageSlug) {
|
|
2050
|
-
const
|
|
974
|
+
const runtime2 = useRuntimeContext();
|
|
2051
975
|
return useMemo4(() => {
|
|
2052
|
-
const snapshot =
|
|
2053
|
-
const definition =
|
|
976
|
+
const snapshot = runtime2.getSnapshot();
|
|
977
|
+
const definition = runtime2.config?.definition;
|
|
2054
978
|
const childDefs = definition?.child_definitions ?? [];
|
|
2055
979
|
const metadata = definition?.metadata ?? {};
|
|
2056
980
|
if (definition?.slug === packageSlug && definition?.category === "blueprint") {
|
|
@@ -2113,7 +1037,7 @@ function usePackage(packageSlug) {
|
|
|
2113
1037
|
isResolved: false,
|
|
2114
1038
|
dependencySlugs: []
|
|
2115
1039
|
};
|
|
2116
|
-
}, [
|
|
1040
|
+
}, [runtime2, packageSlug]);
|
|
2117
1041
|
}
|
|
2118
1042
|
|
|
2119
1043
|
// src/hooks/useRouter.ts
|
|
@@ -2239,16 +1163,16 @@ function useRouter(options = {}) {
|
|
|
2239
1163
|
};
|
|
2240
1164
|
setIsNavigating(true);
|
|
2241
1165
|
try {
|
|
2242
|
-
for (const
|
|
2243
|
-
const allowed = await
|
|
1166
|
+
for (const guard2 of guardsRef.current) {
|
|
1167
|
+
const allowed = await guard2(to, location);
|
|
2244
1168
|
if (!allowed) {
|
|
2245
1169
|
onRejectRef.current?.(to);
|
|
2246
1170
|
return false;
|
|
2247
1171
|
}
|
|
2248
1172
|
}
|
|
2249
1173
|
if (found?.route?.guards) {
|
|
2250
|
-
for (const
|
|
2251
|
-
const allowed = await
|
|
1174
|
+
for (const guard2 of found.route.guards) {
|
|
1175
|
+
const allowed = await guard2(to, location);
|
|
2252
1176
|
if (!allowed) {
|
|
2253
1177
|
if (found.route.redirectOnFail) {
|
|
2254
1178
|
const fullRedirect = basePathRef.current + found.route.redirectOnFail;
|
|
@@ -2674,7 +1598,7 @@ function useGeolocation(options = {}) {
|
|
|
2674
1598
|
const {
|
|
2675
1599
|
enableHighAccuracy = false,
|
|
2676
1600
|
maximumAge = 0,
|
|
2677
|
-
timeout = 1e4,
|
|
1601
|
+
timeout: timeout2 = 1e4,
|
|
2678
1602
|
watch = false,
|
|
2679
1603
|
enabled = true
|
|
2680
1604
|
} = options;
|
|
@@ -2685,8 +1609,8 @@ function useGeolocation(options = {}) {
|
|
|
2685
1609
|
const watchIdRef = useRef18(null);
|
|
2686
1610
|
const supported = typeof navigator !== "undefined" && "geolocation" in navigator;
|
|
2687
1611
|
const positionOptions = useMemo8(
|
|
2688
|
-
() => ({ enableHighAccuracy, maximumAge, timeout }),
|
|
2689
|
-
[enableHighAccuracy, maximumAge,
|
|
1612
|
+
() => ({ enableHighAccuracy, maximumAge, timeout: timeout2 }),
|
|
1613
|
+
[enableHighAccuracy, maximumAge, timeout2]
|
|
2690
1614
|
);
|
|
2691
1615
|
const handleSuccess = useCallback13((pos) => {
|
|
2692
1616
|
setPosition({
|
|
@@ -3046,7 +1970,7 @@ import { useState as useState16, useCallback as useCallback16, useMemo as useMem
|
|
|
3046
1970
|
function useForm(config) {
|
|
3047
1971
|
const {
|
|
3048
1972
|
initialValues,
|
|
3049
|
-
validate,
|
|
1973
|
+
validate: validate2,
|
|
3050
1974
|
fieldValidators,
|
|
3051
1975
|
onSubmit,
|
|
3052
1976
|
onError,
|
|
@@ -3059,8 +1983,8 @@ function useForm(config) {
|
|
|
3059
1983
|
const [isSubmitting, setIsSubmitting] = useState16(false);
|
|
3060
1984
|
const [submitCount, setSubmitCount] = useState16(0);
|
|
3061
1985
|
const initialRef = useRef20(initialValues);
|
|
3062
|
-
const validateRef = useRef20(
|
|
3063
|
-
validateRef.current =
|
|
1986
|
+
const validateRef = useRef20(validate2);
|
|
1987
|
+
validateRef.current = validate2;
|
|
3064
1988
|
const fieldValidatorsRef = useRef20(fieldValidators);
|
|
3065
1989
|
fieldValidatorsRef.current = fieldValidators;
|
|
3066
1990
|
const onSubmitRef = useRef20(onSubmit);
|
|
@@ -3277,7 +2201,7 @@ function useNotification() {
|
|
|
3277
2201
|
setPermission(result);
|
|
3278
2202
|
return result;
|
|
3279
2203
|
}, [supported]);
|
|
3280
|
-
const
|
|
2204
|
+
const notify3 = useCallback17(
|
|
3281
2205
|
(title, options = {}) => {
|
|
3282
2206
|
if (!supported || permission !== "granted") return null;
|
|
3283
2207
|
const {
|
|
@@ -3310,8 +2234,8 @@ function useNotification() {
|
|
|
3310
2234
|
[supported, permission]
|
|
3311
2235
|
);
|
|
3312
2236
|
return useMemo12(
|
|
3313
|
-
() => ({ permission, supported, requestPermission, notify:
|
|
3314
|
-
[permission, supported, requestPermission,
|
|
2237
|
+
() => ({ permission, supported, requestPermission, notify: notify3 }),
|
|
2238
|
+
[permission, supported, requestPermission, notify3]
|
|
3315
2239
|
);
|
|
3316
2240
|
}
|
|
3317
2241
|
|
|
@@ -3328,12 +2252,12 @@ function notifyListeners() {
|
|
|
3328
2252
|
}
|
|
3329
2253
|
function addToast(config) {
|
|
3330
2254
|
const id = `toast-${++_nextId}`;
|
|
3331
|
-
const
|
|
2255
|
+
const instance2 = {
|
|
3332
2256
|
...config,
|
|
3333
2257
|
id,
|
|
3334
2258
|
createdAt: Date.now()
|
|
3335
2259
|
};
|
|
3336
|
-
_toasts = [..._toasts,
|
|
2260
|
+
_toasts = [..._toasts, instance2];
|
|
3337
2261
|
const duration = config.duration ?? 5e3;
|
|
3338
2262
|
if (duration > 0) {
|
|
3339
2263
|
const timer = setTimeout(() => {
|
|
@@ -3384,8 +2308,191 @@ function useToast() {
|
|
|
3384
2308
|
);
|
|
3385
2309
|
}
|
|
3386
2310
|
|
|
2311
|
+
// src/hooks/useVisibility.ts
|
|
2312
|
+
import { useMemo as useMemo14 } from "react";
|
|
2313
|
+
function useVisibility(model2, role, playerType) {
|
|
2314
|
+
return useMemo14(() => {
|
|
2315
|
+
return computeVisibility(model2, role, playerType);
|
|
2316
|
+
}, [model2, role, playerType]);
|
|
2317
|
+
}
|
|
2318
|
+
function computeVisibility(model2, role, playerType) {
|
|
2319
|
+
const allFields = Object.keys(model2.fields || {});
|
|
2320
|
+
const allStates = Object.keys(model2.states || {});
|
|
2321
|
+
const vis = model2.orchestration?.visibility;
|
|
2322
|
+
if (!vis) {
|
|
2323
|
+
return makeResult(allFields, allStates);
|
|
2324
|
+
}
|
|
2325
|
+
let roleFields;
|
|
2326
|
+
let roleStates;
|
|
2327
|
+
let playerFields;
|
|
2328
|
+
if (role && vis.roles && vis.roles[role]) {
|
|
2329
|
+
const rv = vis.roles[role];
|
|
2330
|
+
roleFields = rv.fields === "*" ? "*" : [...rv.fields];
|
|
2331
|
+
roleStates = rv.states === "*" ? "*" : rv.states ? [...rv.states] : "*";
|
|
2332
|
+
}
|
|
2333
|
+
if (playerType && vis.players && vis.players[playerType]) {
|
|
2334
|
+
const pv = vis.players[playerType];
|
|
2335
|
+
playerFields = pv.fields === "*" ? "*" : [...pv.fields];
|
|
2336
|
+
}
|
|
2337
|
+
if (roleFields === void 0 && playerFields === void 0) {
|
|
2338
|
+
return makeResult(allFields, allStates);
|
|
2339
|
+
}
|
|
2340
|
+
let resolvedFields;
|
|
2341
|
+
if (roleFields === "*" && playerFields === "*") {
|
|
2342
|
+
resolvedFields = allFields;
|
|
2343
|
+
} else if (roleFields === "*") {
|
|
2344
|
+
resolvedFields = playerFields === void 0 ? allFields : playerFields;
|
|
2345
|
+
} else if (playerFields === "*") {
|
|
2346
|
+
resolvedFields = roleFields === void 0 ? allFields : roleFields;
|
|
2347
|
+
} else if (roleFields !== void 0 && playerFields !== void 0) {
|
|
2348
|
+
const roleSet = new Set(roleFields);
|
|
2349
|
+
resolvedFields = playerFields.filter((f) => roleSet.has(f));
|
|
2350
|
+
} else {
|
|
2351
|
+
resolvedFields = roleFields || playerFields || allFields;
|
|
2352
|
+
}
|
|
2353
|
+
const resolvedStates = roleStates === "*" || roleStates === void 0 ? allStates : roleStates;
|
|
2354
|
+
return makeResult(resolvedFields, resolvedStates);
|
|
2355
|
+
}
|
|
2356
|
+
function makeResult(fields, states) {
|
|
2357
|
+
const fieldSet = new Set(fields);
|
|
2358
|
+
const stateSet = new Set(states);
|
|
2359
|
+
return {
|
|
2360
|
+
visibleFields: fields,
|
|
2361
|
+
visibleStates: states,
|
|
2362
|
+
canSeeField: (f) => fieldSet.has(f),
|
|
2363
|
+
canSeeState: (s) => stateSet.has(s)
|
|
2364
|
+
};
|
|
2365
|
+
}
|
|
2366
|
+
|
|
2367
|
+
// src/hooks/usePresence.ts
|
|
2368
|
+
import { useState as useState19, useEffect as useEffect20, useCallback as useCallback19, useRef as useRef22 } from "react";
|
|
2369
|
+
var PRESENCE_EVENTS = {
|
|
2370
|
+
JOIN: "presence:join",
|
|
2371
|
+
LEAVE: "presence:leave",
|
|
2372
|
+
HEARTBEAT: "presence:heartbeat",
|
|
2373
|
+
EDIT_START: "presence:edit_start",
|
|
2374
|
+
EDIT_STOP: "presence:edit_stop"
|
|
2375
|
+
};
|
|
2376
|
+
function usePresence(instanceId, options = {}) {
|
|
2377
|
+
const {
|
|
2378
|
+
userId = "anonymous",
|
|
2379
|
+
userName = "Anonymous",
|
|
2380
|
+
wsUrl,
|
|
2381
|
+
enabled = true,
|
|
2382
|
+
heartbeatInterval = 15e3,
|
|
2383
|
+
staleTimeout = 45e3
|
|
2384
|
+
} = options;
|
|
2385
|
+
const channelName = `presence:${instanceId}`;
|
|
2386
|
+
const { publish, subscribe, connected } = useChannel(channelName, {
|
|
2387
|
+
wsUrl,
|
|
2388
|
+
enabled
|
|
2389
|
+
});
|
|
2390
|
+
const [viewers, setViewers] = useState19([]);
|
|
2391
|
+
const [editors, setEditors] = useState19([]);
|
|
2392
|
+
const viewersRef = useRef22(/* @__PURE__ */ new Map());
|
|
2393
|
+
const editorsRef = useRef22(/* @__PURE__ */ new Map());
|
|
2394
|
+
useEffect20(() => {
|
|
2395
|
+
if (!connected || !enabled) return;
|
|
2396
|
+
publish(PRESENCE_EVENTS.JOIN, { id: userId, name: userName, connectedAt: Date.now() });
|
|
2397
|
+
const hb = setInterval(() => {
|
|
2398
|
+
publish(PRESENCE_EVENTS.HEARTBEAT, { id: userId, name: userName });
|
|
2399
|
+
}, heartbeatInterval);
|
|
2400
|
+
return () => {
|
|
2401
|
+
clearInterval(hb);
|
|
2402
|
+
publish(PRESENCE_EVENTS.LEAVE, { id: userId });
|
|
2403
|
+
};
|
|
2404
|
+
}, [connected, enabled, userId, userName, heartbeatInterval, publish]);
|
|
2405
|
+
useEffect20(() => {
|
|
2406
|
+
if (!enabled) return;
|
|
2407
|
+
const cleanup = setInterval(() => {
|
|
2408
|
+
const now = Date.now();
|
|
2409
|
+
const stale = [];
|
|
2410
|
+
for (const [id, v] of viewersRef.current) {
|
|
2411
|
+
if (now - v.connectedAt > staleTimeout) stale.push(id);
|
|
2412
|
+
}
|
|
2413
|
+
if (stale.length > 0) {
|
|
2414
|
+
for (const id of stale) {
|
|
2415
|
+
viewersRef.current.delete(id);
|
|
2416
|
+
editorsRef.current.delete(id);
|
|
2417
|
+
}
|
|
2418
|
+
setViewers(Array.from(viewersRef.current.values()));
|
|
2419
|
+
setEditors(Array.from(editorsRef.current.values()));
|
|
2420
|
+
}
|
|
2421
|
+
}, staleTimeout / 3);
|
|
2422
|
+
return () => clearInterval(cleanup);
|
|
2423
|
+
}, [enabled, staleTimeout]);
|
|
2424
|
+
useEffect20(() => {
|
|
2425
|
+
if (!enabled) return;
|
|
2426
|
+
const unsubs = [];
|
|
2427
|
+
unsubs.push(subscribe(PRESENCE_EVENTS.JOIN, (data) => {
|
|
2428
|
+
if (data.id === userId) return;
|
|
2429
|
+
viewersRef.current.set(data.id, {
|
|
2430
|
+
id: data.id,
|
|
2431
|
+
name: data.name || "Anonymous",
|
|
2432
|
+
connectedAt: data.connectedAt || Date.now()
|
|
2433
|
+
});
|
|
2434
|
+
setViewers(Array.from(viewersRef.current.values()));
|
|
2435
|
+
}));
|
|
2436
|
+
unsubs.push(subscribe(PRESENCE_EVENTS.LEAVE, (data) => {
|
|
2437
|
+
viewersRef.current.delete(data.id);
|
|
2438
|
+
editorsRef.current.delete(data.id);
|
|
2439
|
+
setViewers(Array.from(viewersRef.current.values()));
|
|
2440
|
+
setEditors(Array.from(editorsRef.current.values()));
|
|
2441
|
+
}));
|
|
2442
|
+
unsubs.push(subscribe(PRESENCE_EVENTS.HEARTBEAT, (data) => {
|
|
2443
|
+
if (data.id === userId) return;
|
|
2444
|
+
const existing = viewersRef.current.get(data.id);
|
|
2445
|
+
if (existing) {
|
|
2446
|
+
existing.connectedAt = Date.now();
|
|
2447
|
+
} else {
|
|
2448
|
+
viewersRef.current.set(data.id, {
|
|
2449
|
+
id: data.id,
|
|
2450
|
+
name: data.name || "Anonymous",
|
|
2451
|
+
connectedAt: Date.now()
|
|
2452
|
+
});
|
|
2453
|
+
setViewers(Array.from(viewersRef.current.values()));
|
|
2454
|
+
}
|
|
2455
|
+
}));
|
|
2456
|
+
unsubs.push(subscribe(PRESENCE_EVENTS.EDIT_START, (data) => {
|
|
2457
|
+
if (data.id === userId) return;
|
|
2458
|
+
editorsRef.current.set(data.id, {
|
|
2459
|
+
id: data.id,
|
|
2460
|
+
name: data.name || "Anonymous",
|
|
2461
|
+
field: data.field,
|
|
2462
|
+
startedAt: Date.now()
|
|
2463
|
+
});
|
|
2464
|
+
setEditors(Array.from(editorsRef.current.values()));
|
|
2465
|
+
}));
|
|
2466
|
+
unsubs.push(subscribe(PRESENCE_EVENTS.EDIT_STOP, (data) => {
|
|
2467
|
+
editorsRef.current.delete(data.id);
|
|
2468
|
+
setEditors(Array.from(editorsRef.current.values()));
|
|
2469
|
+
}));
|
|
2470
|
+
return () => unsubs.forEach((fn) => fn());
|
|
2471
|
+
}, [enabled, userId, subscribe]);
|
|
2472
|
+
const startEditing = useCallback19((field2) => {
|
|
2473
|
+
publish(PRESENCE_EVENTS.EDIT_START, { id: userId, name: userName, field: field2 });
|
|
2474
|
+
}, [publish, userId, userName]);
|
|
2475
|
+
const stopEditing = useCallback19((_field) => {
|
|
2476
|
+
publish(PRESENCE_EVENTS.EDIT_STOP, { id: userId });
|
|
2477
|
+
}, [publish, userId]);
|
|
2478
|
+
const isEditing = useCallback19((field2) => {
|
|
2479
|
+
for (const editor of editorsRef.current.values()) {
|
|
2480
|
+
if (editor.field === field2 && editor.id !== userId) return true;
|
|
2481
|
+
}
|
|
2482
|
+
return false;
|
|
2483
|
+
}, [userId]);
|
|
2484
|
+
return {
|
|
2485
|
+
viewers,
|
|
2486
|
+
editors,
|
|
2487
|
+
viewerCount: viewers.length,
|
|
2488
|
+
isEditing,
|
|
2489
|
+
startEditing,
|
|
2490
|
+
stopEditing
|
|
2491
|
+
};
|
|
2492
|
+
}
|
|
2493
|
+
|
|
3387
2494
|
// src/hooks/useMiddleware.ts
|
|
3388
|
-
import { useState as
|
|
2495
|
+
import { useState as useState20, useEffect as useEffect21, useRef as useRef23, useMemo as useMemo15 } from "react";
|
|
3389
2496
|
function requireAuth(loginPath = "/login") {
|
|
3390
2497
|
return (ctx) => {
|
|
3391
2498
|
if (!ctx.token) {
|
|
@@ -3457,24 +2564,24 @@ function useMiddleware(middlewares, options = {}) {
|
|
|
3457
2564
|
watchPathname = true,
|
|
3458
2565
|
onRedirect
|
|
3459
2566
|
} = options;
|
|
3460
|
-
const [ready, setReady] =
|
|
3461
|
-
const [loading, setLoading] =
|
|
3462
|
-
const [redirect, setRedirect] =
|
|
3463
|
-
const [error, setError] =
|
|
3464
|
-
const [data, setData] =
|
|
3465
|
-
const [runKey, setRunKey] =
|
|
3466
|
-
const middlewaresRef =
|
|
2567
|
+
const [ready, setReady] = useState20(false);
|
|
2568
|
+
const [loading, setLoading] = useState20(true);
|
|
2569
|
+
const [redirect, setRedirect] = useState20(null);
|
|
2570
|
+
const [error, setError] = useState20(null);
|
|
2571
|
+
const [data, setData] = useState20({});
|
|
2572
|
+
const [runKey, setRunKey] = useState20(0);
|
|
2573
|
+
const middlewaresRef = useRef23(middlewares);
|
|
3467
2574
|
middlewaresRef.current = middlewares;
|
|
3468
|
-
const onRedirectRef =
|
|
2575
|
+
const onRedirectRef = useRef23(onRedirect);
|
|
3469
2576
|
onRedirectRef.current = onRedirect;
|
|
3470
|
-
const [pathname, setPathname] =
|
|
3471
|
-
|
|
2577
|
+
const [pathname, setPathname] = useState20(getPathname);
|
|
2578
|
+
useEffect21(() => {
|
|
3472
2579
|
if (!watchPathname) return;
|
|
3473
2580
|
const handler = () => setPathname(getPathname());
|
|
3474
2581
|
window.addEventListener("popstate", handler);
|
|
3475
2582
|
return () => window.removeEventListener("popstate", handler);
|
|
3476
2583
|
}, [watchPathname]);
|
|
3477
|
-
|
|
2584
|
+
useEffect21(() => {
|
|
3478
2585
|
if (!enabled) {
|
|
3479
2586
|
setReady(true);
|
|
3480
2587
|
setLoading(false);
|
|
@@ -3521,11 +2628,11 @@ function useMiddleware(middlewares, options = {}) {
|
|
|
3521
2628
|
cancelled = true;
|
|
3522
2629
|
};
|
|
3523
2630
|
}, [enabled, pathname, runKey]);
|
|
3524
|
-
const rerun =
|
|
2631
|
+
const rerun = useMemo15(
|
|
3525
2632
|
() => () => setRunKey((k) => k + 1),
|
|
3526
2633
|
[]
|
|
3527
2634
|
);
|
|
3528
|
-
return
|
|
2635
|
+
return useMemo15(
|
|
3529
2636
|
() => ({ ready, loading, redirect, error, data, rerun }),
|
|
3530
2637
|
[ready, loading, redirect, error, data, rerun]
|
|
3531
2638
|
);
|
|
@@ -3535,8 +2642,8 @@ function useMiddleware(middlewares, options = {}) {
|
|
|
3535
2642
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
3536
2643
|
import { jsx } from "react/jsx-runtime";
|
|
3537
2644
|
var defaultQueryClient = new QueryClient();
|
|
3538
|
-
function WorkflowProvider({ runtime, queryClient, children }) {
|
|
3539
|
-
return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient ?? defaultQueryClient, children: /* @__PURE__ */ jsx(RuntimeContext.Provider, { value:
|
|
2645
|
+
function WorkflowProvider({ runtime: runtime2, queryClient, children }) {
|
|
2646
|
+
return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient ?? defaultQueryClient, children: /* @__PURE__ */ jsx(RuntimeContext.Provider, { value: runtime2, children }) });
|
|
3540
2647
|
}
|
|
3541
2648
|
|
|
3542
2649
|
// src/local/LocalEngine.ts
|
|
@@ -3597,8 +2704,8 @@ var LocalWorkflowEngine = class {
|
|
|
3597
2704
|
* Process all pending events from a transition result.
|
|
3598
2705
|
* Emits locally and returns the events for P2P broadcast.
|
|
3599
2706
|
*/
|
|
3600
|
-
processPendingEvents(
|
|
3601
|
-
const events =
|
|
2707
|
+
processPendingEvents(instance2) {
|
|
2708
|
+
const events = instance2._pendingEvents;
|
|
3602
2709
|
if (!events?.length) return [];
|
|
3603
2710
|
for (const evt of events) {
|
|
3604
2711
|
this.emitEvent(evt);
|
|
@@ -3641,18 +2748,18 @@ var LocalWorkflowEngine = class {
|
|
|
3641
2748
|
};
|
|
3642
2749
|
}
|
|
3643
2750
|
/** Check if a transition can fire from the instance's current state */
|
|
3644
|
-
canTransition(
|
|
3645
|
-
const def = this.definitions.get(
|
|
2751
|
+
canTransition(instance2, transitionName) {
|
|
2752
|
+
const def = this.definitions.get(instance2.definitionSlug);
|
|
3646
2753
|
if (!def) return false;
|
|
3647
2754
|
const transition2 = def.transitions.find((t) => t.name === transitionName);
|
|
3648
2755
|
if (!transition2) return false;
|
|
3649
|
-
return transition2.from.includes(
|
|
2756
|
+
return transition2.from.includes(instance2.currentState);
|
|
3650
2757
|
}
|
|
3651
2758
|
/** Get all transitions available from the instance's current state */
|
|
3652
|
-
getAvailableTransitions(
|
|
3653
|
-
const def = this.definitions.get(
|
|
2759
|
+
getAvailableTransitions(instance2) {
|
|
2760
|
+
const def = this.definitions.get(instance2.definitionSlug);
|
|
3654
2761
|
if (!def) return [];
|
|
3655
|
-
return def.transitions.filter((t) => t.from.includes(
|
|
2762
|
+
return def.transitions.filter((t) => t.from.includes(instance2.currentState)).map((t) => t.name);
|
|
3656
2763
|
}
|
|
3657
2764
|
/**
|
|
3658
2765
|
* Apply a transition, returning a new WorkflowInstance (immutable).
|
|
@@ -3663,29 +2770,29 @@ var LocalWorkflowEngine = class {
|
|
|
3663
2770
|
* @returns New WorkflowInstance with updated state and version
|
|
3664
2771
|
* @throws If transition is not valid from current state
|
|
3665
2772
|
*/
|
|
3666
|
-
applyTransition(
|
|
3667
|
-
const def = this.definitions.get(
|
|
2773
|
+
applyTransition(instance2, transitionName, data) {
|
|
2774
|
+
const def = this.definitions.get(instance2.definitionSlug);
|
|
3668
2775
|
if (!def) {
|
|
3669
|
-
throw new Error(`Definition not found: ${
|
|
2776
|
+
throw new Error(`Definition not found: ${instance2.definitionSlug}`);
|
|
3670
2777
|
}
|
|
3671
2778
|
const transition2 = def.transitions.find((t) => t.name === transitionName);
|
|
3672
2779
|
if (!transition2) {
|
|
3673
2780
|
throw new Error(
|
|
3674
|
-
`Transition "${transitionName}" not found in ${
|
|
2781
|
+
`Transition "${transitionName}" not found in ${instance2.definitionSlug}`
|
|
3675
2782
|
);
|
|
3676
2783
|
}
|
|
3677
|
-
if (!transition2.from.includes(
|
|
2784
|
+
if (!transition2.from.includes(instance2.currentState)) {
|
|
3678
2785
|
throw new Error(
|
|
3679
|
-
`Transition "${transitionName}" cannot fire from state "${
|
|
2786
|
+
`Transition "${transitionName}" cannot fire from state "${instance2.currentState}" (allowed from: ${transition2.from.join(", ")})`
|
|
3680
2787
|
);
|
|
3681
2788
|
}
|
|
3682
|
-
const nextState = transition2.to ??
|
|
3683
|
-
const fields = data ? { ...
|
|
2789
|
+
const nextState = transition2.to ?? instance2.currentState;
|
|
2790
|
+
const fields = data ? { ...instance2.fields, ...data } : { ...instance2.fields };
|
|
3684
2791
|
let result = {
|
|
3685
|
-
...
|
|
2792
|
+
...instance2,
|
|
3686
2793
|
currentState: nextState,
|
|
3687
2794
|
fields,
|
|
3688
|
-
version:
|
|
2795
|
+
version: instance2.version + 1,
|
|
3689
2796
|
updatedAt: Date.now()
|
|
3690
2797
|
};
|
|
3691
2798
|
const targetStateDef = def.states.find((s) => s.name === nextState);
|
|
@@ -3758,14 +2865,14 @@ var LocalWorkflowEngine = class {
|
|
|
3758
2865
|
* Apply a transition only if the incoming version is newer.
|
|
3759
2866
|
* Used for P2P sync — skips stale transitions.
|
|
3760
2867
|
*/
|
|
3761
|
-
applyRemoteTransition(
|
|
3762
|
-
if (remoteVersion <=
|
|
2868
|
+
applyRemoteTransition(instance2, transitionName, data, remoteVersion) {
|
|
2869
|
+
if (remoteVersion <= instance2.version) {
|
|
3763
2870
|
return null;
|
|
3764
2871
|
}
|
|
3765
|
-
if (!this.canTransition(
|
|
2872
|
+
if (!this.canTransition(instance2, transitionName)) {
|
|
3766
2873
|
return null;
|
|
3767
2874
|
}
|
|
3768
|
-
const updated = this.applyTransition(
|
|
2875
|
+
const updated = this.applyTransition(instance2, transitionName, data);
|
|
3769
2876
|
return { ...updated, version: remoteVersion };
|
|
3770
2877
|
}
|
|
3771
2878
|
};
|
|
@@ -4031,6 +3138,155 @@ function defineModel(def) {
|
|
|
4031
3138
|
return def;
|
|
4032
3139
|
}
|
|
4033
3140
|
|
|
3141
|
+
// src/config/orchestration-presets.ts
|
|
3142
|
+
var SOLO = {
|
|
3143
|
+
strategy: "solo",
|
|
3144
|
+
evaluation: { pure: "local" },
|
|
3145
|
+
scheduling: { coordinator: "any" },
|
|
3146
|
+
events: { evaluator: "any-subscriber" },
|
|
3147
|
+
errorHandling: { strategy: "manual" },
|
|
3148
|
+
conflicts: { default: "last-writer-wins", fields: {} },
|
|
3149
|
+
visibility: { roles: {}, players: {} },
|
|
3150
|
+
presence: { enabled: false, showEditing: false, showViewing: false },
|
|
3151
|
+
services: {},
|
|
3152
|
+
actionRouting: {}
|
|
3153
|
+
};
|
|
3154
|
+
var CLIENT_SERVER = {
|
|
3155
|
+
strategy: "client-server",
|
|
3156
|
+
evaluation: { pure: "local" },
|
|
3157
|
+
scheduling: { coordinator: "server" },
|
|
3158
|
+
events: { evaluator: "server" },
|
|
3159
|
+
errorHandling: { strategy: "rollback" },
|
|
3160
|
+
conflicts: { default: "last-writer-wins", fields: {} },
|
|
3161
|
+
visibility: { roles: {}, players: {} },
|
|
3162
|
+
presence: { enabled: false, showEditing: false, showViewing: false },
|
|
3163
|
+
services: {},
|
|
3164
|
+
actionRouting: {}
|
|
3165
|
+
};
|
|
3166
|
+
var MULTI_CLIENT = {
|
|
3167
|
+
strategy: "multi-client",
|
|
3168
|
+
evaluation: { pure: "local" },
|
|
3169
|
+
scheduling: { coordinator: "server" },
|
|
3170
|
+
events: { evaluator: "server" },
|
|
3171
|
+
errorHandling: { strategy: "compensate" },
|
|
3172
|
+
conflicts: { default: "last-writer-wins", fields: {} },
|
|
3173
|
+
visibility: { roles: {}, players: {} },
|
|
3174
|
+
presence: { enabled: true, showEditing: true, showViewing: true, conflictHighlight: true },
|
|
3175
|
+
services: {},
|
|
3176
|
+
actionRouting: {}
|
|
3177
|
+
};
|
|
3178
|
+
var SERVICE_MESH = {
|
|
3179
|
+
strategy: "service-mesh",
|
|
3180
|
+
evaluation: { pure: "local" },
|
|
3181
|
+
scheduling: { coordinator: "server" },
|
|
3182
|
+
events: { evaluator: "all" },
|
|
3183
|
+
errorHandling: { strategy: "saga" },
|
|
3184
|
+
conflicts: { default: "first-write-wins", fields: {} },
|
|
3185
|
+
visibility: { roles: {}, players: {} },
|
|
3186
|
+
presence: { enabled: false, showEditing: false, showViewing: false },
|
|
3187
|
+
services: {},
|
|
3188
|
+
actionRouting: {}
|
|
3189
|
+
};
|
|
3190
|
+
var PEER_TO_PEER = {
|
|
3191
|
+
strategy: "peer-to-peer",
|
|
3192
|
+
evaluation: { pure: "local" },
|
|
3193
|
+
scheduling: { coordinator: "any" },
|
|
3194
|
+
events: { evaluator: "any-subscriber" },
|
|
3195
|
+
errorHandling: { strategy: "compensate" },
|
|
3196
|
+
conflicts: { default: "crdt", fields: {} },
|
|
3197
|
+
visibility: { roles: {}, players: {} },
|
|
3198
|
+
presence: { enabled: true, showEditing: true, showViewing: true, conflictHighlight: false },
|
|
3199
|
+
services: {},
|
|
3200
|
+
actionRouting: {}
|
|
3201
|
+
};
|
|
3202
|
+
var HYBRID = {
|
|
3203
|
+
strategy: "hybrid",
|
|
3204
|
+
evaluation: { pure: "local" },
|
|
3205
|
+
scheduling: { coordinator: "server" },
|
|
3206
|
+
events: { evaluator: "server" },
|
|
3207
|
+
errorHandling: { strategy: "saga" },
|
|
3208
|
+
conflicts: { default: "last-writer-wins", fields: {} },
|
|
3209
|
+
visibility: { roles: {}, players: {} },
|
|
3210
|
+
presence: { enabled: true, showEditing: true, showViewing: false, conflictHighlight: false },
|
|
3211
|
+
services: {},
|
|
3212
|
+
actionRouting: {}
|
|
3213
|
+
};
|
|
3214
|
+
var HEADLESS = {
|
|
3215
|
+
strategy: "headless",
|
|
3216
|
+
evaluation: { pure: "local" },
|
|
3217
|
+
// expression engine runs server-local (native Rust, fastest)
|
|
3218
|
+
scheduling: { coordinator: "server" },
|
|
3219
|
+
// server manages cron/interval/timeout
|
|
3220
|
+
events: { evaluator: "server" },
|
|
3221
|
+
// server matches events, no clients involved
|
|
3222
|
+
errorHandling: { strategy: "compensate" },
|
|
3223
|
+
conflicts: { default: "first-write-wins", fields: {} },
|
|
3224
|
+
// no concurrent clients
|
|
3225
|
+
visibility: { roles: {}, players: {} },
|
|
3226
|
+
presence: { enabled: false, showEditing: false, showViewing: false, conflictHighlight: false },
|
|
3227
|
+
services: {},
|
|
3228
|
+
actionRouting: {}
|
|
3229
|
+
};
|
|
3230
|
+
var ORCHESTRATION_PRESETS = {
|
|
3231
|
+
"solo": SOLO,
|
|
3232
|
+
"client-server": CLIENT_SERVER,
|
|
3233
|
+
"multi-client": MULTI_CLIENT,
|
|
3234
|
+
"service-mesh": SERVICE_MESH,
|
|
3235
|
+
"peer-to-peer": PEER_TO_PEER,
|
|
3236
|
+
"hybrid": HYBRID,
|
|
3237
|
+
"headless": HEADLESS,
|
|
3238
|
+
"custom": CLIENT_SERVER
|
|
3239
|
+
// custom uses client-server as base
|
|
3240
|
+
};
|
|
3241
|
+
var DEFAULT_RESOLVED = {
|
|
3242
|
+
strategy: "client-server",
|
|
3243
|
+
evaluation: { pure: "local" },
|
|
3244
|
+
scheduling: { coordinator: "server" },
|
|
3245
|
+
events: { evaluator: "server" },
|
|
3246
|
+
errorHandling: { strategy: "rollback" },
|
|
3247
|
+
conflicts: { default: "last-writer-wins", fields: {} },
|
|
3248
|
+
visibility: { roles: {}, players: {} },
|
|
3249
|
+
presence: { enabled: false, showEditing: false, showViewing: false, conflictHighlight: false },
|
|
3250
|
+
services: {},
|
|
3251
|
+
actionRouting: {}
|
|
3252
|
+
};
|
|
3253
|
+
function resolveOrchestration(config) {
|
|
3254
|
+
if (!config) return { ...DEFAULT_RESOLVED };
|
|
3255
|
+
const strategy = config.strategy || "client-server";
|
|
3256
|
+
const preset = ORCHESTRATION_PRESETS[strategy] || CLIENT_SERVER;
|
|
3257
|
+
return {
|
|
3258
|
+
strategy,
|
|
3259
|
+
evaluation: {
|
|
3260
|
+
pure: config.evaluation?.pure ?? preset.evaluation?.pure ?? "local"
|
|
3261
|
+
},
|
|
3262
|
+
scheduling: {
|
|
3263
|
+
coordinator: config.scheduling?.coordinator ?? preset.scheduling?.coordinator ?? "server"
|
|
3264
|
+
},
|
|
3265
|
+
events: {
|
|
3266
|
+
evaluator: config.events?.evaluator ?? preset.events?.evaluator ?? "server"
|
|
3267
|
+
},
|
|
3268
|
+
errorHandling: {
|
|
3269
|
+
strategy: config.errorHandling?.strategy ?? preset.errorHandling?.strategy ?? "rollback"
|
|
3270
|
+
},
|
|
3271
|
+
conflicts: {
|
|
3272
|
+
default: config.conflicts?.default ?? preset.conflicts?.default ?? "last-writer-wins",
|
|
3273
|
+
fields: { ...preset.conflicts?.fields || {}, ...config.conflicts?.fields || {} }
|
|
3274
|
+
},
|
|
3275
|
+
visibility: {
|
|
3276
|
+
roles: { ...preset.visibility?.roles || {}, ...config.visibility?.roles || {} },
|
|
3277
|
+
players: { ...preset.visibility?.players || {}, ...config.visibility?.players || {} }
|
|
3278
|
+
},
|
|
3279
|
+
presence: {
|
|
3280
|
+
enabled: config.presence?.enabled ?? preset.presence?.enabled ?? false,
|
|
3281
|
+
showEditing: config.presence?.showEditing ?? preset.presence?.showEditing ?? false,
|
|
3282
|
+
showViewing: config.presence?.showViewing ?? preset.presence?.showViewing ?? false,
|
|
3283
|
+
conflictHighlight: config.presence?.conflictHighlight ?? preset.presence?.conflictHighlight ?? false
|
|
3284
|
+
},
|
|
3285
|
+
services: { ...preset.services || {}, ...config.services || {} },
|
|
3286
|
+
actionRouting: { ...preset.actionRouting || {}, ...config.actionRouting || {} }
|
|
3287
|
+
};
|
|
3288
|
+
}
|
|
3289
|
+
|
|
4034
3290
|
// src/config/defineBlueprint.ts
|
|
4035
3291
|
function defineBlueprint(config) {
|
|
4036
3292
|
if (!config.slug) {
|
|
@@ -4144,13 +3400,13 @@ function inState(state2) {
|
|
|
4144
3400
|
function notInState(state2) {
|
|
4145
3401
|
return { type: "expression", expression: `current_state != "${state2}"` };
|
|
4146
3402
|
}
|
|
4147
|
-
function
|
|
3403
|
+
function and(...conditions) {
|
|
4148
3404
|
return { AND: conditions.map(normalize) };
|
|
4149
3405
|
}
|
|
4150
|
-
function
|
|
3406
|
+
function or(...conditions) {
|
|
4151
3407
|
return { OR: conditions.map(normalize) };
|
|
4152
3408
|
}
|
|
4153
|
-
function
|
|
3409
|
+
function not(condition) {
|
|
4154
3410
|
const c = normalize(condition);
|
|
4155
3411
|
if (c.type === "expression" && c.expression) {
|
|
4156
3412
|
return { type: "expression", expression: `NOT(${c.expression})` };
|
|
@@ -4195,7 +3451,7 @@ function refHasAnyRole(slug, lookupField, lookupValue, roles) {
|
|
|
4195
3451
|
}
|
|
4196
3452
|
|
|
4197
3453
|
// src/hooks/useModel.ts
|
|
4198
|
-
import { useCallback as
|
|
3454
|
+
import { useCallback as useCallback20, useRef as useRef24, useMemo as useMemo16 } from "react";
|
|
4199
3455
|
function getDefaultFields(definition) {
|
|
4200
3456
|
const defaults = {};
|
|
4201
3457
|
for (const [key, field2] of Object.entries(definition.fields)) {
|
|
@@ -4250,18 +3506,18 @@ function useModel(definition, options = {}) {
|
|
|
4250
3506
|
if (options.state) queryParams.state = options.state;
|
|
4251
3507
|
const query = useQuery(slug, queryParams);
|
|
4252
3508
|
const mutation = useMutation(slug);
|
|
4253
|
-
const
|
|
4254
|
-
const instanceId =
|
|
4255
|
-
const currentState =
|
|
4256
|
-
const instanceFields =
|
|
4257
|
-
const defaultFields =
|
|
4258
|
-
const fields =
|
|
3509
|
+
const instance2 = query.data?.[0];
|
|
3510
|
+
const instanceId = instance2?.id ?? null;
|
|
3511
|
+
const currentState = instance2?.currentState ?? "";
|
|
3512
|
+
const instanceFields = instance2?.fields ?? null;
|
|
3513
|
+
const defaultFields = useMemo16(() => getDefaultFields(definition), [definition]);
|
|
3514
|
+
const fields = useMemo16(() => {
|
|
4259
3515
|
if (!instanceFields) return defaultFields;
|
|
4260
3516
|
return { ...defaultFields, ...instanceFields };
|
|
4261
3517
|
}, [instanceFields, defaultFields]);
|
|
4262
|
-
const instanceIdRef =
|
|
3518
|
+
const instanceIdRef = useRef24(instanceId);
|
|
4263
3519
|
instanceIdRef.current = instanceId;
|
|
4264
|
-
const trigger =
|
|
3520
|
+
const trigger = useCallback20(async (name, input) => {
|
|
4265
3521
|
const id = instanceIdRef.current;
|
|
4266
3522
|
if (!id) {
|
|
4267
3523
|
throw new Error(`useModel(${slug}): No instance loaded. Cannot trigger '${name}'.`);
|
|
@@ -4269,12 +3525,12 @@ function useModel(definition, options = {}) {
|
|
|
4269
3525
|
await mutation.transition(id, name, input);
|
|
4270
3526
|
await query.refetch();
|
|
4271
3527
|
}, [slug, mutation, query]);
|
|
4272
|
-
const create =
|
|
3528
|
+
const create = useCallback20(async (input) => {
|
|
4273
3529
|
const id = await mutation.create(input);
|
|
4274
3530
|
await query.refetch();
|
|
4275
3531
|
return id;
|
|
4276
3532
|
}, [mutation, query]);
|
|
4277
|
-
const update =
|
|
3533
|
+
const update = useCallback20(async (fieldUpdates) => {
|
|
4278
3534
|
const id = instanceIdRef.current;
|
|
4279
3535
|
if (!id) {
|
|
4280
3536
|
throw new Error(`useModel(${slug}): No instance loaded. Cannot update.`);
|
|
@@ -4303,27 +3559,27 @@ function useCollection(definition, options = {}) {
|
|
|
4303
3559
|
const slug = definition.slug;
|
|
4304
3560
|
const query = useQuery(slug, options);
|
|
4305
3561
|
const mutation = useMutation(slug);
|
|
4306
|
-
const items =
|
|
4307
|
-
return (query.data || []).map((
|
|
4308
|
-
id:
|
|
4309
|
-
fields:
|
|
4310
|
-
state:
|
|
3562
|
+
const items = useMemo16(() => {
|
|
3563
|
+
return (query.data || []).map((instance2) => ({
|
|
3564
|
+
id: instance2.id,
|
|
3565
|
+
fields: instance2.fields ?? {},
|
|
3566
|
+
state: instance2.currentState ?? ""
|
|
4311
3567
|
}));
|
|
4312
3568
|
}, [query.data]);
|
|
4313
|
-
const trigger =
|
|
3569
|
+
const trigger = useCallback20(async (instanceId, name, input) => {
|
|
4314
3570
|
await mutation.transition(instanceId, name, input);
|
|
4315
3571
|
await query.refetch();
|
|
4316
3572
|
}, [mutation, query]);
|
|
4317
|
-
const create =
|
|
3573
|
+
const create = useCallback20(async (input) => {
|
|
4318
3574
|
const id = await mutation.create(input);
|
|
4319
3575
|
await query.refetch();
|
|
4320
3576
|
return id;
|
|
4321
3577
|
}, [mutation, query]);
|
|
4322
|
-
const update =
|
|
3578
|
+
const update = useCallback20(async (instanceId, fieldUpdates) => {
|
|
4323
3579
|
await mutation.update(instanceId, fieldUpdates);
|
|
4324
3580
|
await query.refetch();
|
|
4325
3581
|
}, [mutation, query]);
|
|
4326
|
-
const remove =
|
|
3582
|
+
const remove = useCallback20(async (instanceId) => {
|
|
4327
3583
|
await mutation.remove(instanceId);
|
|
4328
3584
|
await query.refetch();
|
|
4329
3585
|
}, [mutation, query]);
|
|
@@ -4347,7 +3603,7 @@ function useCollection(definition, options = {}) {
|
|
|
4347
3603
|
function stub(displayName) {
|
|
4348
3604
|
const Component = () => {
|
|
4349
3605
|
throw new Error(
|
|
4350
|
-
`<${displayName}> is a compile-time stub from @
|
|
3606
|
+
`<${displayName}> is a compile-time stub from @mmapp/react/atoms. It should only appear in .workflow.tsx files processed by the compiler. At runtime, use the ComponentTreeRenderer which resolves "${displayName}" from the component registry.`
|
|
4351
3607
|
);
|
|
4352
3608
|
};
|
|
4353
3609
|
Component.displayName = displayName;
|
|
@@ -4474,7 +3730,7 @@ function djb2Hash(str) {
|
|
|
4474
3730
|
}
|
|
4475
3731
|
|
|
4476
3732
|
// src/authoring.ts
|
|
4477
|
-
function
|
|
3733
|
+
function useState21(_defaultOrKey) {
|
|
4478
3734
|
return [void 0, () => {
|
|
4479
3735
|
}];
|
|
4480
3736
|
}
|
|
@@ -4485,10 +3741,10 @@ function defineWorkspace(config) {
|
|
|
4485
3741
|
}
|
|
4486
3742
|
|
|
4487
3743
|
// src/hooks/useModule.ts
|
|
4488
|
-
import { useMemo as
|
|
3744
|
+
import { useMemo as useMemo17 } from "react";
|
|
4489
3745
|
function useModule(slug, config = {}, options = {}) {
|
|
4490
3746
|
const { enabled = true } = options;
|
|
4491
|
-
return
|
|
3747
|
+
return useMemo17(() => ({
|
|
4492
3748
|
slug,
|
|
4493
3749
|
config,
|
|
4494
3750
|
isLoaded: enabled
|
|
@@ -4496,7 +3752,7 @@ function useModule(slug, config = {}, options = {}) {
|
|
|
4496
3752
|
}
|
|
4497
3753
|
|
|
4498
3754
|
// src/hooks/useModuleConfig.ts
|
|
4499
|
-
import { useMemo as
|
|
3755
|
+
import { useCallback as useCallback21, useMemo as useMemo18, useState as useState22 } from "react";
|
|
4500
3756
|
var installedModulesStore = [];
|
|
4501
3757
|
var configDefaultsStore = /* @__PURE__ */ new Map();
|
|
4502
3758
|
function setInstalledModules(modules) {
|
|
@@ -4512,12 +3768,65 @@ function getInstalledModules() {
|
|
|
4512
3768
|
return installedModulesStore;
|
|
4513
3769
|
}
|
|
4514
3770
|
function useModuleConfig(moduleSlug) {
|
|
4515
|
-
return
|
|
3771
|
+
return useMemo18(() => {
|
|
4516
3772
|
const installed = getInstalledModule(moduleSlug);
|
|
4517
3773
|
const defaults = configDefaultsStore.get(moduleSlug) ?? {};
|
|
4518
|
-
|
|
3774
|
+
const persisted = persistedConfigStore.get(moduleSlug) ?? {};
|
|
3775
|
+
return { ...defaults, ...persisted, ...installed?.config };
|
|
4519
3776
|
}, [moduleSlug]);
|
|
4520
3777
|
}
|
|
3778
|
+
var persistedConfigStore = /* @__PURE__ */ new Map();
|
|
3779
|
+
function setPersistedModuleConfig(moduleSlug, config) {
|
|
3780
|
+
persistedConfigStore.set(moduleSlug, config);
|
|
3781
|
+
}
|
|
3782
|
+
async function syncConfigDefaults(moduleSlug, defaults, definitionId) {
|
|
3783
|
+
const id = definitionId ?? activeDefinitionIdStore;
|
|
3784
|
+
if (!id) return;
|
|
3785
|
+
try {
|
|
3786
|
+
const moduleKey = `module_config.${moduleSlug}`;
|
|
3787
|
+
await updateDefinitionConfig({ [moduleKey]: defaults }, id);
|
|
3788
|
+
persistedConfigStore.set(moduleSlug, defaults);
|
|
3789
|
+
} catch (e) {
|
|
3790
|
+
console.warn(`[useModuleConfig] Failed to sync config for ${moduleSlug}:`, e);
|
|
3791
|
+
}
|
|
3792
|
+
}
|
|
3793
|
+
var activeDefinitionIdStore = null;
|
|
3794
|
+
var apiBaseUrlStore = "/api/v1/workflow";
|
|
3795
|
+
function setConfigContext(definitionId, apiBaseUrl) {
|
|
3796
|
+
activeDefinitionIdStore = definitionId;
|
|
3797
|
+
if (apiBaseUrl) apiBaseUrlStore = apiBaseUrl;
|
|
3798
|
+
}
|
|
3799
|
+
async function updateDefinitionConfig(values, definitionId) {
|
|
3800
|
+
const id = definitionId ?? activeDefinitionIdStore;
|
|
3801
|
+
if (!id) throw new Error("No active definition ID. Call setConfigContext() first.");
|
|
3802
|
+
const token = typeof localStorage !== "undefined" ? localStorage.getItem("auth_token") : null;
|
|
3803
|
+
const response = await fetch(`${apiBaseUrlStore}/definitions/${id}/config`, {
|
|
3804
|
+
method: "PATCH",
|
|
3805
|
+
headers: {
|
|
3806
|
+
"Content-Type": "application/json",
|
|
3807
|
+
...token ? { Authorization: `Bearer ${token}` } : {}
|
|
3808
|
+
},
|
|
3809
|
+
body: JSON.stringify(values)
|
|
3810
|
+
});
|
|
3811
|
+
if (!response.ok) {
|
|
3812
|
+
const err = await response.json().catch(() => ({ message: response.statusText }));
|
|
3813
|
+
throw new Error(err.message || `Failed to update config: ${response.status}`);
|
|
3814
|
+
}
|
|
3815
|
+
return response.json();
|
|
3816
|
+
}
|
|
3817
|
+
function useModuleConfigWithMutation(moduleSlug) {
|
|
3818
|
+
const config = useModuleConfig(moduleSlug);
|
|
3819
|
+
const [isSaving, setIsSaving] = useState22(false);
|
|
3820
|
+
const updateConfig = useCallback21(async (values) => {
|
|
3821
|
+
setIsSaving(true);
|
|
3822
|
+
try {
|
|
3823
|
+
return await updateDefinitionConfig(values);
|
|
3824
|
+
} finally {
|
|
3825
|
+
setIsSaving(false);
|
|
3826
|
+
}
|
|
3827
|
+
}, []);
|
|
3828
|
+
return { config, updateConfig, isSaving };
|
|
3829
|
+
}
|
|
4521
3830
|
|
|
4522
3831
|
// src/builders.ts
|
|
4523
3832
|
function handlerToAction(handler, qualifier) {
|
|
@@ -6021,7 +5330,7 @@ function approval(config = {}) {
|
|
|
6021
5330
|
}
|
|
6022
5331
|
function escalation(config) {
|
|
6023
5332
|
const {
|
|
6024
|
-
timeout,
|
|
5333
|
+
timeout: timeout2,
|
|
6025
5334
|
notifyRole = "admin",
|
|
6026
5335
|
fromState = "pending_approval",
|
|
6027
5336
|
escalatedState = "escalated"
|
|
@@ -6033,7 +5342,7 @@ function escalation(config) {
|
|
|
6033
5342
|
});
|
|
6034
5343
|
if (def.states[fromState]) {
|
|
6035
5344
|
def.states[fromState].timeout = {
|
|
6036
|
-
duration:
|
|
5345
|
+
duration: timeout2,
|
|
6037
5346
|
fallback: { transition: "escalate" }
|
|
6038
5347
|
};
|
|
6039
5348
|
}
|
|
@@ -6052,8 +5361,8 @@ function escalation(config) {
|
|
|
6052
5361
|
from: fromState,
|
|
6053
5362
|
to: escalatedState,
|
|
6054
5363
|
auto: true,
|
|
6055
|
-
description: `Auto-escalate after ${
|
|
6056
|
-
actions: [logEvent("escalated", { timeout })]
|
|
5364
|
+
description: `Auto-escalate after ${timeout2}`,
|
|
5365
|
+
actions: [logEvent("escalated", { timeout: timeout2 })]
|
|
6057
5366
|
}
|
|
6058
5367
|
});
|
|
6059
5368
|
return def;
|
|
@@ -6711,7 +6020,14 @@ function describeModel(def) {
|
|
|
6711
6020
|
}
|
|
6712
6021
|
|
|
6713
6022
|
// src/hooks/usePlayer.ts
|
|
6714
|
-
import { useCallback as
|
|
6023
|
+
import { useCallback as useCallback22, useEffect as useEffect22, useMemo as useMemo19, useRef as useRef25, useState as useState23 } from "react";
|
|
6024
|
+
import {
|
|
6025
|
+
StateMachine as StateMachine2,
|
|
6026
|
+
EventBus as EventBus2,
|
|
6027
|
+
ActionDispatcher as ActionDispatcher2,
|
|
6028
|
+
createEvaluator as createEvaluator2,
|
|
6029
|
+
WEB_FAILURE_POLICIES as WEB_FAILURE_POLICIES2
|
|
6030
|
+
} from "@mmapp/player-core";
|
|
6715
6031
|
|
|
6716
6032
|
// src/logger.ts
|
|
6717
6033
|
var debugEnabled = false;
|
|
@@ -6751,18 +6067,18 @@ function computePlayerState(sm) {
|
|
|
6751
6067
|
};
|
|
6752
6068
|
}
|
|
6753
6069
|
function usePlayer(config) {
|
|
6754
|
-
const configRef =
|
|
6070
|
+
const configRef = useRef25(config);
|
|
6755
6071
|
configRef.current = config;
|
|
6756
|
-
|
|
6072
|
+
useEffect22(() => {
|
|
6757
6073
|
if (config.debug) setPlayerDebug(true);
|
|
6758
6074
|
}, [config.debug]);
|
|
6759
|
-
const evaluator =
|
|
6760
|
-
return
|
|
6075
|
+
const evaluator = useMemo19(() => {
|
|
6076
|
+
return createEvaluator2({
|
|
6761
6077
|
functions: config.functions ?? [],
|
|
6762
|
-
failurePolicy:
|
|
6078
|
+
failurePolicy: WEB_FAILURE_POLICIES2.EVENT_REACTION
|
|
6763
6079
|
});
|
|
6764
6080
|
}, [config.definition.id]);
|
|
6765
|
-
const engine =
|
|
6081
|
+
const engine = useMemo19(() => {
|
|
6766
6082
|
const actionHandlers = /* @__PURE__ */ new Map();
|
|
6767
6083
|
if (config.actionHandlers) {
|
|
6768
6084
|
for (const [type, handler] of Object.entries(config.actionHandlers)) {
|
|
@@ -6790,14 +6106,14 @@ function usePlayer(config) {
|
|
|
6790
6106
|
});
|
|
6791
6107
|
}
|
|
6792
6108
|
});
|
|
6793
|
-
const sm2 = new
|
|
6109
|
+
const sm2 = new StateMachine2(
|
|
6794
6110
|
config.definition,
|
|
6795
6111
|
config.initialData ?? {},
|
|
6796
6112
|
{ evaluator, actionHandlers }
|
|
6797
6113
|
);
|
|
6798
6114
|
smRef = sm2;
|
|
6799
|
-
const eventBus2 = new
|
|
6800
|
-
const dispatcher = new
|
|
6115
|
+
const eventBus2 = new EventBus2();
|
|
6116
|
+
const dispatcher = new ActionDispatcher2();
|
|
6801
6117
|
dispatcher.register("set_field", (cfg) => {
|
|
6802
6118
|
if (smRef && typeof cfg.field === "string") {
|
|
6803
6119
|
smRef.setField(cfg.field, cfg.value);
|
|
@@ -6816,8 +6132,8 @@ function usePlayer(config) {
|
|
|
6816
6132
|
return { sm: sm2, eventBus: eventBus2, dispatcher };
|
|
6817
6133
|
}, [config.definition.id, evaluator]);
|
|
6818
6134
|
const { sm, eventBus } = engine;
|
|
6819
|
-
const [playerState, setPlayerState] =
|
|
6820
|
-
|
|
6135
|
+
const [playerState, setPlayerState] = useState23(() => computePlayerState(sm));
|
|
6136
|
+
useEffect22(() => {
|
|
6821
6137
|
const stateDef = sm.getCurrentStateDefinition();
|
|
6822
6138
|
if (!stateDef?.on_event?.length) return;
|
|
6823
6139
|
const unsubs = [];
|
|
@@ -6881,7 +6197,7 @@ function usePlayer(config) {
|
|
|
6881
6197
|
for (const unsub of unsubs) unsub();
|
|
6882
6198
|
};
|
|
6883
6199
|
}, [sm, eventBus, evaluator, engine.dispatcher, playerState.currentState]);
|
|
6884
|
-
|
|
6200
|
+
useEffect22(() => {
|
|
6885
6201
|
const unsub = sm.on((event) => {
|
|
6886
6202
|
if (event.type === "transition" || event.type === "state_enter") {
|
|
6887
6203
|
setPlayerState(computePlayerState(sm));
|
|
@@ -6897,7 +6213,7 @@ function usePlayer(config) {
|
|
|
6897
6213
|
});
|
|
6898
6214
|
return unsub;
|
|
6899
6215
|
}, [sm]);
|
|
6900
|
-
const transition2 =
|
|
6216
|
+
const transition2 = useCallback22(
|
|
6901
6217
|
async (name, data) => {
|
|
6902
6218
|
playerLog({
|
|
6903
6219
|
level: "info",
|
|
@@ -6924,20 +6240,20 @@ function usePlayer(config) {
|
|
|
6924
6240
|
},
|
|
6925
6241
|
[sm]
|
|
6926
6242
|
);
|
|
6927
|
-
const setField2 =
|
|
6243
|
+
const setField2 = useCallback22(
|
|
6928
6244
|
(field2, value) => {
|
|
6929
6245
|
sm.setField(field2, value);
|
|
6930
6246
|
setPlayerState(computePlayerState(sm));
|
|
6931
6247
|
},
|
|
6932
6248
|
[sm]
|
|
6933
6249
|
);
|
|
6934
|
-
const setMemory =
|
|
6250
|
+
const setMemory = useCallback22(
|
|
6935
6251
|
(key, value) => {
|
|
6936
6252
|
sm.setMemory(key, value);
|
|
6937
6253
|
},
|
|
6938
6254
|
[sm]
|
|
6939
6255
|
);
|
|
6940
|
-
const publishEvent =
|
|
6256
|
+
const publishEvent = useCallback22(
|
|
6941
6257
|
(topic, payload) => {
|
|
6942
6258
|
playerLog({
|
|
6943
6259
|
level: "debug",
|
|
@@ -6963,11 +6279,11 @@ function usePlayer(config) {
|
|
|
6963
6279
|
}
|
|
6964
6280
|
|
|
6965
6281
|
// src/hooks/useDomainSubscription.ts
|
|
6966
|
-
import { useEffect as
|
|
6282
|
+
import { useEffect as useEffect23, useRef as useRef26 } from "react";
|
|
6967
6283
|
function useDomainSubscription(eventBus, transport, config) {
|
|
6968
|
-
const configRef =
|
|
6284
|
+
const configRef = useRef26(config);
|
|
6969
6285
|
configRef.current = config;
|
|
6970
|
-
|
|
6286
|
+
useEffect23(() => {
|
|
6971
6287
|
if (!transport || config.enabled === false) return;
|
|
6972
6288
|
const unsub = transport.subscribe(
|
|
6973
6289
|
{
|
|
@@ -7020,11 +6336,11 @@ function useDomainSubscription(eventBus, transport, config) {
|
|
|
7020
6336
|
}
|
|
7021
6337
|
|
|
7022
6338
|
// src/hooks/useExperienceState.ts
|
|
7023
|
-
import { useCallback as
|
|
6339
|
+
import { useCallback as useCallback23, useRef as useRef27 } from "react";
|
|
7024
6340
|
function useExperienceState(player, selector) {
|
|
7025
|
-
const selectorRef =
|
|
6341
|
+
const selectorRef = useRef27(selector);
|
|
7026
6342
|
selectorRef.current = selector;
|
|
7027
|
-
const getSnapshot =
|
|
6343
|
+
const getSnapshot = useCallback23(() => {
|
|
7028
6344
|
return selectorRef.current({
|
|
7029
6345
|
currentState: player.currentState,
|
|
7030
6346
|
stateData: player.stateData,
|
|
@@ -7040,20 +6356,20 @@ function useStateField(player, field2, defaultValue) {
|
|
|
7040
6356
|
}
|
|
7041
6357
|
|
|
7042
6358
|
// src/hooks/useComputed.ts
|
|
7043
|
-
import { useMemo as
|
|
6359
|
+
import { useMemo as useMemo20, useRef as useRef28 } from "react";
|
|
7044
6360
|
function useComputed(_name, compute, options) {
|
|
7045
6361
|
const mode = options?.mode ?? "read-time";
|
|
7046
6362
|
const deps = options?.deps ?? [];
|
|
7047
|
-
const computeRef =
|
|
6363
|
+
const computeRef = useRef28(compute);
|
|
7048
6364
|
computeRef.current = compute;
|
|
7049
6365
|
if (mode === "read-time") {
|
|
7050
|
-
return
|
|
6366
|
+
return useMemo20(() => computeRef.current(), [
|
|
7051
6367
|
// We intentionally depend on deps.join to recompute when tracked fields change
|
|
7052
6368
|
// The actual dependency tracking happens at the compiler level
|
|
7053
6369
|
deps.join(",")
|
|
7054
6370
|
]);
|
|
7055
6371
|
}
|
|
7056
|
-
return
|
|
6372
|
+
return useMemo20(() => computeRef.current(), [deps.join(",")]);
|
|
7057
6373
|
}
|
|
7058
6374
|
function useComputedWithMeta(name, compute, options) {
|
|
7059
6375
|
const value = useComputed(name, compute, options);
|
|
@@ -7086,7 +6402,7 @@ function usePlayerContextSafe() {
|
|
|
7086
6402
|
}
|
|
7087
6403
|
|
|
7088
6404
|
// src/components/ExperienceWorkflowBridge.tsx
|
|
7089
|
-
import { useMemo as
|
|
6405
|
+
import { useMemo as useMemo21 } from "react";
|
|
7090
6406
|
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
7091
6407
|
function ExperienceWorkflowBridgeInner({
|
|
7092
6408
|
definition,
|
|
@@ -7104,7 +6420,7 @@ function ExperienceWorkflowBridgeInner({
|
|
|
7104
6420
|
actionHandlers,
|
|
7105
6421
|
debug
|
|
7106
6422
|
});
|
|
7107
|
-
const viewConfig =
|
|
6423
|
+
const viewConfig = useMemo21(() => {
|
|
7108
6424
|
if (!definition.state_views) return void 0;
|
|
7109
6425
|
return definition.state_views[player.currentState];
|
|
7110
6426
|
}, [definition.state_views, player.currentState]);
|
|
@@ -7460,7 +6776,7 @@ var BrowserPlayer = class {
|
|
|
7460
6776
|
this.ensureInitialized();
|
|
7461
6777
|
const id = crypto.randomUUID();
|
|
7462
6778
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7463
|
-
const
|
|
6779
|
+
const instance2 = {
|
|
7464
6780
|
id,
|
|
7465
6781
|
definitionId: options.definitionId ?? definitionSlug,
|
|
7466
6782
|
definitionSlug,
|
|
@@ -7472,15 +6788,15 @@ var BrowserPlayer = class {
|
|
|
7472
6788
|
createdAt: now,
|
|
7473
6789
|
updatedAt: now
|
|
7474
6790
|
};
|
|
7475
|
-
await this.putInstance(
|
|
6791
|
+
await this.putInstance(instance2);
|
|
7476
6792
|
this.log("info", `Instance created: ${id} (${definitionSlug})`);
|
|
7477
6793
|
this.emit({
|
|
7478
6794
|
type: "instance:created",
|
|
7479
6795
|
instanceId: id,
|
|
7480
|
-
data: { definitionSlug, currentState:
|
|
6796
|
+
data: { definitionSlug, currentState: instance2.currentState },
|
|
7481
6797
|
timestamp: Date.now()
|
|
7482
6798
|
});
|
|
7483
|
-
return
|
|
6799
|
+
return instance2;
|
|
7484
6800
|
}
|
|
7485
6801
|
/** Get an instance by ID. */
|
|
7486
6802
|
async getInstance(id) {
|
|
@@ -7489,13 +6805,13 @@ var BrowserPlayer = class {
|
|
|
7489
6805
|
}
|
|
7490
6806
|
/** Get the current state of an instance. */
|
|
7491
6807
|
async getState(id) {
|
|
7492
|
-
const
|
|
7493
|
-
if (!
|
|
6808
|
+
const instance2 = await this.getInstance(id);
|
|
6809
|
+
if (!instance2) return null;
|
|
7494
6810
|
return {
|
|
7495
|
-
currentState:
|
|
7496
|
-
status:
|
|
7497
|
-
stateData:
|
|
7498
|
-
lockVersion:
|
|
6811
|
+
currentState: instance2.currentState,
|
|
6812
|
+
status: instance2.status,
|
|
6813
|
+
stateData: instance2.stateData,
|
|
6814
|
+
lockVersion: instance2.lockVersion
|
|
7499
6815
|
};
|
|
7500
6816
|
}
|
|
7501
6817
|
/**
|
|
@@ -7506,34 +6822,34 @@ var BrowserPlayer = class {
|
|
|
7506
6822
|
*/
|
|
7507
6823
|
async transition(instanceId, transitionName, data = {}) {
|
|
7508
6824
|
this.ensureInitialized();
|
|
7509
|
-
const
|
|
7510
|
-
if (!
|
|
6825
|
+
const instance2 = await this.getInstanceFromDb(instanceId);
|
|
6826
|
+
if (!instance2) {
|
|
7511
6827
|
return {
|
|
7512
6828
|
success: false,
|
|
7513
6829
|
instance: null,
|
|
7514
6830
|
error: `Instance ${instanceId} not found`
|
|
7515
6831
|
};
|
|
7516
6832
|
}
|
|
7517
|
-
if (
|
|
6833
|
+
if (instance2.status !== "ACTIVE") {
|
|
7518
6834
|
return {
|
|
7519
6835
|
success: false,
|
|
7520
|
-
instance,
|
|
7521
|
-
error: `Instance is ${
|
|
6836
|
+
instance: instance2,
|
|
6837
|
+
error: `Instance is ${instance2.status}, cannot transition`
|
|
7522
6838
|
};
|
|
7523
6839
|
}
|
|
7524
6840
|
try {
|
|
7525
|
-
const newStateData = { ...
|
|
7526
|
-
const newLockVersion =
|
|
6841
|
+
const newStateData = { ...instance2.stateData, ...data };
|
|
6842
|
+
const newLockVersion = instance2.lockVersion + 1;
|
|
7527
6843
|
if (this.wasm.execute_transition) {
|
|
7528
6844
|
const request = {
|
|
7529
6845
|
instance: {
|
|
7530
|
-
id:
|
|
7531
|
-
definition_id:
|
|
7532
|
-
current_state:
|
|
7533
|
-
status:
|
|
6846
|
+
id: instance2.id,
|
|
6847
|
+
definition_id: instance2.definitionId,
|
|
6848
|
+
current_state: instance2.currentState,
|
|
6849
|
+
status: instance2.status,
|
|
7534
6850
|
state_data: newStateData,
|
|
7535
|
-
memory:
|
|
7536
|
-
execution_lock_version:
|
|
6851
|
+
memory: instance2.memory,
|
|
6852
|
+
execution_lock_version: instance2.lockVersion
|
|
7537
6853
|
},
|
|
7538
6854
|
transition_name: transitionName,
|
|
7539
6855
|
actor_id: this.peerId,
|
|
@@ -7542,26 +6858,26 @@ var BrowserPlayer = class {
|
|
|
7542
6858
|
const resultJson = this.wasm.execute_transition(JSON.stringify(request));
|
|
7543
6859
|
const result = JSON.parse(resultJson);
|
|
7544
6860
|
if (result.success === false || result.error) {
|
|
7545
|
-
return { success: false, instance, error: result.error ?? "Transition failed" };
|
|
6861
|
+
return { success: false, instance: instance2, error: result.error ?? "Transition failed" };
|
|
7546
6862
|
}
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
|
|
7550
|
-
|
|
6863
|
+
instance2.currentState = result.to_state ?? instance2.currentState;
|
|
6864
|
+
instance2.status = result.status ?? instance2.status;
|
|
6865
|
+
instance2.stateData = result.state_data ?? newStateData;
|
|
6866
|
+
instance2.memory = result.memory ?? instance2.memory;
|
|
7551
6867
|
} else {
|
|
7552
|
-
|
|
6868
|
+
instance2.stateData = newStateData;
|
|
7553
6869
|
}
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
await this.putInstance(
|
|
6870
|
+
instance2.lockVersion = newLockVersion;
|
|
6871
|
+
instance2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
6872
|
+
await this.putInstance(instance2);
|
|
7557
6873
|
this.log("info", `Transition: ${instanceId} ${transitionName}`);
|
|
7558
6874
|
this.emit({
|
|
7559
6875
|
type: "instance:transition",
|
|
7560
6876
|
instanceId,
|
|
7561
6877
|
data: {
|
|
7562
6878
|
transitionName,
|
|
7563
|
-
fromState:
|
|
7564
|
-
toState:
|
|
6879
|
+
fromState: instance2.currentState,
|
|
6880
|
+
toState: instance2.currentState,
|
|
7565
6881
|
lockVersion: newLockVersion
|
|
7566
6882
|
},
|
|
7567
6883
|
timestamp: Date.now()
|
|
@@ -7571,7 +6887,7 @@ var BrowserPlayer = class {
|
|
|
7571
6887
|
type: "TransitionReplication",
|
|
7572
6888
|
instance_id: instanceId,
|
|
7573
6889
|
transition_name: transitionName,
|
|
7574
|
-
state_data:
|
|
6890
|
+
state_data: instance2.stateData,
|
|
7575
6891
|
lock_version: newLockVersion
|
|
7576
6892
|
});
|
|
7577
6893
|
const envelope = this.wasm.sign_envelope(this.secretKeyHex, payload);
|
|
@@ -7581,11 +6897,11 @@ var BrowserPlayer = class {
|
|
|
7581
6897
|
envelope
|
|
7582
6898
|
}));
|
|
7583
6899
|
}
|
|
7584
|
-
return { success: true, instance };
|
|
6900
|
+
return { success: true, instance: instance2 };
|
|
7585
6901
|
} catch (err) {
|
|
7586
6902
|
const error = err instanceof Error ? err.message : String(err);
|
|
7587
6903
|
this.log("error", `Transition failed: ${error}`);
|
|
7588
|
-
return { success: false, instance, error };
|
|
6904
|
+
return { success: false, instance: instance2, error };
|
|
7589
6905
|
}
|
|
7590
6906
|
}
|
|
7591
6907
|
// ─── Subscriptions ──────────────────────────────────────────────────
|
|
@@ -7665,12 +6981,12 @@ var BrowserPlayer = class {
|
|
|
7665
6981
|
request.onerror = () => reject(request.error);
|
|
7666
6982
|
});
|
|
7667
6983
|
}
|
|
7668
|
-
async putInstance(
|
|
6984
|
+
async putInstance(instance2) {
|
|
7669
6985
|
if (!this.db) return;
|
|
7670
6986
|
return new Promise((resolve, reject) => {
|
|
7671
6987
|
const tx = this.db.transaction(INSTANCE_STORE_NAME, "readwrite");
|
|
7672
6988
|
const store = tx.objectStore(INSTANCE_STORE_NAME);
|
|
7673
|
-
store.put(
|
|
6989
|
+
store.put(instance2);
|
|
7674
6990
|
tx.oncomplete = () => resolve();
|
|
7675
6991
|
tx.onerror = () => reject(tx.error);
|
|
7676
6992
|
});
|
|
@@ -7817,9 +7133,381 @@ var BrowserPlayer = class {
|
|
|
7817
7133
|
}
|
|
7818
7134
|
}
|
|
7819
7135
|
};
|
|
7136
|
+
|
|
7137
|
+
// src/middleware-def.ts
|
|
7138
|
+
function defineMiddleware(def) {
|
|
7139
|
+
if (process.env.NODE_ENV !== "production") {
|
|
7140
|
+
if (!def.name || typeof def.name !== "string") {
|
|
7141
|
+
throw new Error("defineMiddleware: name is required and must be a string");
|
|
7142
|
+
}
|
|
7143
|
+
if (!def.match) {
|
|
7144
|
+
throw new Error("defineMiddleware: match pattern is required");
|
|
7145
|
+
}
|
|
7146
|
+
const patterns = Array.isArray(def.match) ? def.match : [def.match];
|
|
7147
|
+
for (const p of patterns) {
|
|
7148
|
+
if (typeof p !== "string") {
|
|
7149
|
+
throw new Error(`defineMiddleware: match pattern must be a string, got ${typeof p}`);
|
|
7150
|
+
}
|
|
7151
|
+
}
|
|
7152
|
+
if (def.priority !== void 0 && typeof def.priority !== "number") {
|
|
7153
|
+
throw new Error("defineMiddleware: priority must be a number");
|
|
7154
|
+
}
|
|
7155
|
+
if (!def.before && !def.after && !def.around) {
|
|
7156
|
+
throw new Error("defineMiddleware: at least one of before, after, or around must be provided");
|
|
7157
|
+
}
|
|
7158
|
+
}
|
|
7159
|
+
return def;
|
|
7160
|
+
}
|
|
7161
|
+
function extendMiddleware(base, overrides) {
|
|
7162
|
+
let introduce;
|
|
7163
|
+
if (base.introduce || overrides.introduce) {
|
|
7164
|
+
introduce = {
|
|
7165
|
+
fields: { ...base.introduce?.fields, ...overrides.introduce?.fields },
|
|
7166
|
+
states: { ...base.introduce?.states, ...overrides.introduce?.states },
|
|
7167
|
+
transitions: { ...base.introduce?.transitions, ...overrides.introduce?.transitions }
|
|
7168
|
+
};
|
|
7169
|
+
if (introduce.fields && Object.keys(introduce.fields).length === 0) introduce.fields = void 0;
|
|
7170
|
+
if (introduce.states && Object.keys(introduce.states).length === 0) introduce.states = void 0;
|
|
7171
|
+
if (introduce.transitions && Object.keys(introduce.transitions).length === 0) introduce.transitions = void 0;
|
|
7172
|
+
}
|
|
7173
|
+
const merged = {
|
|
7174
|
+
...base,
|
|
7175
|
+
...overrides,
|
|
7176
|
+
// Config is merged (overrides win per-key)
|
|
7177
|
+
config: base.config || overrides.config ? { ...base.config, ...overrides.config } : void 0
|
|
7178
|
+
};
|
|
7179
|
+
if (introduce) {
|
|
7180
|
+
merged.introduce = introduce;
|
|
7181
|
+
}
|
|
7182
|
+
if (process.env.NODE_ENV !== "production") {
|
|
7183
|
+
if (!merged.name || typeof merged.name !== "string") {
|
|
7184
|
+
throw new Error("extendMiddleware: resulting middleware must have a name");
|
|
7185
|
+
}
|
|
7186
|
+
if (!merged.match) {
|
|
7187
|
+
throw new Error("extendMiddleware: resulting middleware must have a match pattern");
|
|
7188
|
+
}
|
|
7189
|
+
if (!merged.before && !merged.after && !merged.around) {
|
|
7190
|
+
throw new Error("extendMiddleware: resulting middleware must have at least one of before, after, or around");
|
|
7191
|
+
}
|
|
7192
|
+
}
|
|
7193
|
+
return merged;
|
|
7194
|
+
}
|
|
7195
|
+
function withAuth(opts) {
|
|
7196
|
+
const _redirectTo = opts?.redirectTo;
|
|
7197
|
+
return {
|
|
7198
|
+
name: "mm:auth",
|
|
7199
|
+
match: "*:*:transition.execute",
|
|
7200
|
+
priority: 90,
|
|
7201
|
+
before(ctx) {
|
|
7202
|
+
if (!ctx.actor.id) {
|
|
7203
|
+
ctx.block(_redirectTo ? `redirect:${_redirectTo}` : "Authentication required");
|
|
7204
|
+
}
|
|
7205
|
+
}
|
|
7206
|
+
};
|
|
7207
|
+
}
|
|
7208
|
+
function withAuditLog(opts) {
|
|
7209
|
+
const _level = opts?.level ?? "info";
|
|
7210
|
+
return {
|
|
7211
|
+
name: "mm:audit-log",
|
|
7212
|
+
match: "*:*:transition.execute",
|
|
7213
|
+
priority: 0,
|
|
7214
|
+
after(ctx) {
|
|
7215
|
+
ctx.modify({
|
|
7216
|
+
__audit: {
|
|
7217
|
+
level: _level,
|
|
7218
|
+
actor: ctx.actor.id,
|
|
7219
|
+
transition: ctx.transition?.name,
|
|
7220
|
+
from: ctx.transition?.from,
|
|
7221
|
+
to: ctx.transition?.to,
|
|
7222
|
+
timestamp: ctx.timestamp
|
|
7223
|
+
}
|
|
7224
|
+
});
|
|
7225
|
+
}
|
|
7226
|
+
};
|
|
7227
|
+
}
|
|
7228
|
+
function withRateLimit(opts) {
|
|
7229
|
+
const _max = opts?.maxPerMinute ?? 60;
|
|
7230
|
+
return {
|
|
7231
|
+
name: "mm:rate-limit",
|
|
7232
|
+
match: "*:*:transition.execute",
|
|
7233
|
+
priority: 80,
|
|
7234
|
+
config: {
|
|
7235
|
+
maxPerMinute: { type: "number", default: _max }
|
|
7236
|
+
},
|
|
7237
|
+
before(ctx) {
|
|
7238
|
+
const fields = ctx.instance.fields;
|
|
7239
|
+
const counter = fields.__rateCounter || 0;
|
|
7240
|
+
if (counter >= _max) {
|
|
7241
|
+
ctx.block(`Rate limit exceeded: ${_max} per minute`);
|
|
7242
|
+
}
|
|
7243
|
+
}
|
|
7244
|
+
};
|
|
7245
|
+
}
|
|
7246
|
+
function withValidation(opts) {
|
|
7247
|
+
const _rules = opts?.rules ?? [];
|
|
7248
|
+
return {
|
|
7249
|
+
name: "mm:validation",
|
|
7250
|
+
match: "*:*:field.change",
|
|
7251
|
+
priority: 70,
|
|
7252
|
+
config: {
|
|
7253
|
+
rules: { type: "json", default: _rules }
|
|
7254
|
+
},
|
|
7255
|
+
before(ctx) {
|
|
7256
|
+
if (!ctx.field) return;
|
|
7257
|
+
for (const rule of _rules) {
|
|
7258
|
+
if (rule.fields.includes(ctx.field.name)) {
|
|
7259
|
+
ctx.block(rule.message);
|
|
7260
|
+
}
|
|
7261
|
+
}
|
|
7262
|
+
}
|
|
7263
|
+
};
|
|
7264
|
+
}
|
|
7265
|
+
function withMetrics(opts) {
|
|
7266
|
+
const _endpoint = opts?.endpoint;
|
|
7267
|
+
return {
|
|
7268
|
+
name: "mm:metrics",
|
|
7269
|
+
match: "*:*:*",
|
|
7270
|
+
priority: 100,
|
|
7271
|
+
config: {
|
|
7272
|
+
endpoint: { type: "string", default: _endpoint }
|
|
7273
|
+
},
|
|
7274
|
+
async around(ctx, next) {
|
|
7275
|
+
const start = ctx.timestamp;
|
|
7276
|
+
await next();
|
|
7277
|
+
const duration = Date.now() - start;
|
|
7278
|
+
ctx.modify({
|
|
7279
|
+
__metrics: {
|
|
7280
|
+
duration,
|
|
7281
|
+
endpoint: _endpoint,
|
|
7282
|
+
actor: ctx.actor.id
|
|
7283
|
+
}
|
|
7284
|
+
});
|
|
7285
|
+
}
|
|
7286
|
+
};
|
|
7287
|
+
}
|
|
7288
|
+
|
|
7289
|
+
// src/actor.ts
|
|
7290
|
+
function compileTimeOnly(name) {
|
|
7291
|
+
throw new Error(
|
|
7292
|
+
`${name}() is a compile-time function and cannot be called at runtime. Use \`mmrc build\` to compile your workflow.`
|
|
7293
|
+
);
|
|
7294
|
+
}
|
|
7295
|
+
var DEFAULT_SUPERVISION = {
|
|
7296
|
+
strategy: "escalate"
|
|
7297
|
+
};
|
|
7298
|
+
var DEFAULT_MAILBOX = {
|
|
7299
|
+
capacity: 1e3,
|
|
7300
|
+
overflow: "error",
|
|
7301
|
+
priority: "fifo"
|
|
7302
|
+
};
|
|
7303
|
+
function configureActor(config) {
|
|
7304
|
+
void config;
|
|
7305
|
+
return {
|
|
7306
|
+
__actor: true,
|
|
7307
|
+
supervision: config.supervision ?? DEFAULT_SUPERVISION,
|
|
7308
|
+
mailbox: config.mailbox ?? DEFAULT_MAILBOX,
|
|
7309
|
+
hierarchy: config.hierarchy ?? {}
|
|
7310
|
+
};
|
|
7311
|
+
}
|
|
7312
|
+
function spawnActor(_slug, _options) {
|
|
7313
|
+
compileTimeOnly("spawnActor");
|
|
7314
|
+
}
|
|
7315
|
+
function sendMessage(_instanceId, _action, _payload) {
|
|
7316
|
+
compileTimeOnly("sendMessage");
|
|
7317
|
+
}
|
|
7318
|
+
function isActorConfig(value) {
|
|
7319
|
+
return typeof value === "object" && value !== null && value.__actor === true;
|
|
7320
|
+
}
|
|
7321
|
+
|
|
7322
|
+
// src/constraints.ts
|
|
7323
|
+
var BUILT_IN_CONSTRAINTS = /* @__PURE__ */ new Set([
|
|
7324
|
+
"every state is reachable",
|
|
7325
|
+
"no deadlocks",
|
|
7326
|
+
"no unreachable states",
|
|
7327
|
+
"deterministic guards",
|
|
7328
|
+
"terminates",
|
|
7329
|
+
"no guard overlaps",
|
|
7330
|
+
"all roles defined",
|
|
7331
|
+
"all fields validated"
|
|
7332
|
+
]);
|
|
7333
|
+
function constraints(...rules) {
|
|
7334
|
+
if (process.env.NODE_ENV !== "production") {
|
|
7335
|
+
if (rules.length === 0) {
|
|
7336
|
+
throw new Error("constraints(): at least one constraint rule is required");
|
|
7337
|
+
}
|
|
7338
|
+
for (let i = 0; i < rules.length; i++) {
|
|
7339
|
+
const rule = rules[i];
|
|
7340
|
+
if (typeof rule !== "string" || rule.trim() === "") {
|
|
7341
|
+
throw new Error(
|
|
7342
|
+
`constraints(): rule at index ${i} must be a non-empty string, got ${typeof rule}`
|
|
7343
|
+
);
|
|
7344
|
+
}
|
|
7345
|
+
}
|
|
7346
|
+
}
|
|
7347
|
+
return {
|
|
7348
|
+
__constraints: true,
|
|
7349
|
+
rules: Object.freeze([...rules])
|
|
7350
|
+
};
|
|
7351
|
+
}
|
|
7352
|
+
function isConstraintDeclaration(value) {
|
|
7353
|
+
return typeof value === "object" && value !== null && value.__constraints === true && Array.isArray(value.rules);
|
|
7354
|
+
}
|
|
7355
|
+
function isBuiltInConstraint(rule) {
|
|
7356
|
+
return BUILT_IN_CONSTRAINTS.has(rule);
|
|
7357
|
+
}
|
|
7358
|
+
|
|
7359
|
+
// src/extend.ts
|
|
7360
|
+
function extend(base, options) {
|
|
7361
|
+
const _metadata = {
|
|
7362
|
+
__extend: true,
|
|
7363
|
+
base,
|
|
7364
|
+
options
|
|
7365
|
+
};
|
|
7366
|
+
throw new Error(
|
|
7367
|
+
`extend() is a compile-time declaration and cannot be called at runtime. Ensure your build pipeline includes the @mmapp/react-compiler Babel plugin or compile your workflow files with \`mmrc build\` before execution.
|
|
7368
|
+
|
|
7369
|
+
Base workflow: ${base?.name ?? "(anonymous)"}
|
|
7370
|
+
Derived slug: ${options.slug ?? "(not specified)"}`
|
|
7371
|
+
);
|
|
7372
|
+
return _metadata;
|
|
7373
|
+
}
|
|
7374
|
+
|
|
7375
|
+
// src/compose.ts
|
|
7376
|
+
function compose(workflow, ...mixins) {
|
|
7377
|
+
for (let i = 0; i < mixins.length; i++) {
|
|
7378
|
+
const mixin = mixins[i];
|
|
7379
|
+
if (!mixin || mixin.__mixin !== true) {
|
|
7380
|
+
throw new Error(
|
|
7381
|
+
`compose() argument ${i + 2} is not a valid WorkflowMixin. Each mixin must be created by a mixin factory (e.g. withAuditTrail(), withSoftDelete()). Received: ${typeof mixin === "object" ? JSON.stringify(mixin) : String(mixin)}`
|
|
7382
|
+
);
|
|
7383
|
+
}
|
|
7384
|
+
}
|
|
7385
|
+
const metadata = {
|
|
7386
|
+
__composed: true,
|
|
7387
|
+
workflow,
|
|
7388
|
+
mixins: Object.freeze([...mixins])
|
|
7389
|
+
};
|
|
7390
|
+
const composed = (async (...args) => {
|
|
7391
|
+
return workflow(...args);
|
|
7392
|
+
});
|
|
7393
|
+
Object.defineProperty(composed, "__composed", {
|
|
7394
|
+
value: metadata,
|
|
7395
|
+
writable: false,
|
|
7396
|
+
enumerable: false,
|
|
7397
|
+
configurable: false
|
|
7398
|
+
});
|
|
7399
|
+
Object.defineProperty(composed, "name", {
|
|
7400
|
+
value: `composed(${workflow.name || "anonymous"})`,
|
|
7401
|
+
writable: false,
|
|
7402
|
+
configurable: true
|
|
7403
|
+
});
|
|
7404
|
+
return composed;
|
|
7405
|
+
}
|
|
7406
|
+
|
|
7407
|
+
// src/imperative.ts
|
|
7408
|
+
function compileTimeOnly2(name) {
|
|
7409
|
+
throw new Error(
|
|
7410
|
+
`${name}() is a compile-time function and cannot be called at runtime. Use \`mmrc build\` to compile your workflow.`
|
|
7411
|
+
);
|
|
7412
|
+
}
|
|
7413
|
+
function compileTimeProxy(label) {
|
|
7414
|
+
return new Proxy(
|
|
7415
|
+
{},
|
|
7416
|
+
{
|
|
7417
|
+
get(_target, prop) {
|
|
7418
|
+
throw new Error(
|
|
7419
|
+
`Cannot access \`${label}.${String(prop)}\` at runtime. \`${label}\` is a compile-time constant. Use \`mmrc build\` to compile your workflow.`
|
|
7420
|
+
);
|
|
7421
|
+
}
|
|
7422
|
+
}
|
|
7423
|
+
);
|
|
7424
|
+
}
|
|
7425
|
+
function validate(_condition, _message, _severity) {
|
|
7426
|
+
compileTimeOnly2("validate");
|
|
7427
|
+
}
|
|
7428
|
+
function log(_event, _data) {
|
|
7429
|
+
compileTimeOnly2("log");
|
|
7430
|
+
}
|
|
7431
|
+
function notify2(_to, _message, _opts) {
|
|
7432
|
+
compileTimeOnly2("notify");
|
|
7433
|
+
}
|
|
7434
|
+
function emit(_event, _payload) {
|
|
7435
|
+
compileTimeOnly2("emit");
|
|
7436
|
+
}
|
|
7437
|
+
function requireRole2(..._roles) {
|
|
7438
|
+
compileTimeOnly2("requireRole");
|
|
7439
|
+
}
|
|
7440
|
+
function requireField(..._fields) {
|
|
7441
|
+
compileTimeOnly2("requireField");
|
|
7442
|
+
}
|
|
7443
|
+
function guard(_expression) {
|
|
7444
|
+
compileTimeOnly2("guard");
|
|
7445
|
+
}
|
|
7446
|
+
function every(_interval, _fn) {
|
|
7447
|
+
compileTimeOnly2("every");
|
|
7448
|
+
}
|
|
7449
|
+
function cron2(_expression, _fn) {
|
|
7450
|
+
compileTimeOnly2("cron");
|
|
7451
|
+
}
|
|
7452
|
+
function after(_delay, _fn) {
|
|
7453
|
+
compileTimeOnly2("after");
|
|
7454
|
+
}
|
|
7455
|
+
function on(_pattern, _handlerOrOpts) {
|
|
7456
|
+
compileTimeOnly2("on");
|
|
7457
|
+
}
|
|
7458
|
+
function timeout(_duration, _handler) {
|
|
7459
|
+
compileTimeOnly2("timeout");
|
|
7460
|
+
}
|
|
7461
|
+
function userAction(_name, _opts) {
|
|
7462
|
+
compileTimeOnly2("userAction");
|
|
7463
|
+
}
|
|
7464
|
+
function userChoice(_options) {
|
|
7465
|
+
compileTimeOnly2("userChoice");
|
|
7466
|
+
}
|
|
7467
|
+
function named(_name, _stateCall) {
|
|
7468
|
+
compileTimeOnly2("named");
|
|
7469
|
+
}
|
|
7470
|
+
function delay(_duration) {
|
|
7471
|
+
compileTimeOnly2("delay");
|
|
7472
|
+
}
|
|
7473
|
+
function allowTransition(_name, _opts) {
|
|
7474
|
+
compileTimeOnly2("allowTransition");
|
|
7475
|
+
}
|
|
7476
|
+
function restrict(_field, _opts) {
|
|
7477
|
+
compileTimeOnly2("restrict");
|
|
7478
|
+
}
|
|
7479
|
+
function visibleTo(..._roles) {
|
|
7480
|
+
compileTimeOnly2("visibleTo");
|
|
7481
|
+
}
|
|
7482
|
+
function editableBy(..._roles) {
|
|
7483
|
+
compileTimeOnly2("editableBy");
|
|
7484
|
+
}
|
|
7485
|
+
function editableIn(..._states) {
|
|
7486
|
+
compileTimeOnly2("editableIn");
|
|
7487
|
+
}
|
|
7488
|
+
function defineRoles(roles) {
|
|
7489
|
+
void roles;
|
|
7490
|
+
compileTimeOnly2("defineRoles");
|
|
7491
|
+
}
|
|
7492
|
+
function runtime(_target) {
|
|
7493
|
+
compileTimeOnly2("runtime");
|
|
7494
|
+
}
|
|
7495
|
+
function orchestration(config) {
|
|
7496
|
+
void config;
|
|
7497
|
+
compileTimeOnly2("orchestration");
|
|
7498
|
+
}
|
|
7499
|
+
function blueprint(_slug, _config) {
|
|
7500
|
+
compileTimeOnly2("blueprint");
|
|
7501
|
+
}
|
|
7502
|
+
function patch(_id, _overrides) {
|
|
7503
|
+
compileTimeOnly2("patch");
|
|
7504
|
+
}
|
|
7505
|
+
var actor = compileTimeProxy("actor");
|
|
7506
|
+
var instance = compileTimeProxy("instance");
|
|
7820
7507
|
export {
|
|
7821
7508
|
Accordion,
|
|
7822
7509
|
AnimatedBox,
|
|
7510
|
+
BUILT_IN_CONSTRAINTS,
|
|
7823
7511
|
Badge,
|
|
7824
7512
|
Blueprint,
|
|
7825
7513
|
BrowserPlayer,
|
|
@@ -7846,6 +7534,7 @@ export {
|
|
|
7846
7534
|
Modal,
|
|
7847
7535
|
ModelBuilder,
|
|
7848
7536
|
NavLink,
|
|
7537
|
+
ORCHESTRATION_PRESETS,
|
|
7849
7538
|
PlayerProvider,
|
|
7850
7539
|
RoleGuard,
|
|
7851
7540
|
Route,
|
|
@@ -7869,12 +7558,19 @@ export {
|
|
|
7869
7558
|
WorkflowProvider,
|
|
7870
7559
|
WorkflowRuntime,
|
|
7871
7560
|
action,
|
|
7872
|
-
|
|
7561
|
+
actor,
|
|
7562
|
+
after,
|
|
7563
|
+
allowTransition,
|
|
7564
|
+
and,
|
|
7873
7565
|
applyMixins,
|
|
7874
7566
|
approval,
|
|
7875
7567
|
assertModelValid,
|
|
7876
7568
|
cedar,
|
|
7569
|
+
compose,
|
|
7570
|
+
computeVisibility,
|
|
7571
|
+
configureActor,
|
|
7877
7572
|
connector,
|
|
7573
|
+
constraints,
|
|
7878
7574
|
createActions,
|
|
7879
7575
|
createCRUD,
|
|
7880
7576
|
createLocalDataResolver,
|
|
@@ -7883,16 +7579,26 @@ export {
|
|
|
7883
7579
|
cron,
|
|
7884
7580
|
crud,
|
|
7885
7581
|
defineBlueprint,
|
|
7582
|
+
blueprint as defineImperativeBlueprint,
|
|
7583
|
+
defineMiddleware,
|
|
7886
7584
|
defineModel,
|
|
7887
7585
|
defineModule,
|
|
7586
|
+
defineRoles,
|
|
7888
7587
|
defineWorkspace,
|
|
7588
|
+
delay,
|
|
7889
7589
|
deriveInstanceKey,
|
|
7890
7590
|
deriveInstanceKeySync,
|
|
7891
7591
|
describeModel,
|
|
7892
7592
|
deviceAction,
|
|
7893
7593
|
dmn,
|
|
7594
|
+
editableBy,
|
|
7595
|
+
editableIn,
|
|
7596
|
+
emit,
|
|
7894
7597
|
escalation,
|
|
7598
|
+
every,
|
|
7895
7599
|
expr,
|
|
7600
|
+
extend,
|
|
7601
|
+
extendMiddleware,
|
|
7896
7602
|
field,
|
|
7897
7603
|
fieldContains,
|
|
7898
7604
|
fieldEquals,
|
|
@@ -7907,12 +7613,21 @@ export {
|
|
|
7907
7613
|
getInstalledModule,
|
|
7908
7614
|
getInstalledModules,
|
|
7909
7615
|
graphql,
|
|
7616
|
+
guard,
|
|
7910
7617
|
hasAnyRole,
|
|
7911
7618
|
hasRole,
|
|
7619
|
+
cron2 as imperativeCron,
|
|
7620
|
+
log as imperativeLog,
|
|
7621
|
+
notify2 as imperativeNotify,
|
|
7622
|
+
requireRole2 as imperativeRequireRole,
|
|
7912
7623
|
inState,
|
|
7913
7624
|
inputEquals,
|
|
7914
7625
|
inputRequired,
|
|
7626
|
+
instance,
|
|
7915
7627
|
isActor,
|
|
7628
|
+
isActorConfig,
|
|
7629
|
+
isBuiltInConstraint,
|
|
7630
|
+
isConstraintDeclaration,
|
|
7916
7631
|
isCreator,
|
|
7917
7632
|
isOwner,
|
|
7918
7633
|
isPlayerDebug,
|
|
@@ -7922,28 +7637,39 @@ export {
|
|
|
7922
7637
|
loadExperienceWorkflow,
|
|
7923
7638
|
logEvent,
|
|
7924
7639
|
model,
|
|
7640
|
+
named,
|
|
7925
7641
|
normalizeDefinition,
|
|
7926
|
-
|
|
7642
|
+
not,
|
|
7927
7643
|
notInState,
|
|
7928
7644
|
notify,
|
|
7929
|
-
|
|
7645
|
+
on,
|
|
7646
|
+
or,
|
|
7647
|
+
orchestration,
|
|
7648
|
+
patch,
|
|
7930
7649
|
pipe,
|
|
7931
7650
|
playerLog,
|
|
7932
7651
|
prefetchData,
|
|
7933
7652
|
refHasAnyRole,
|
|
7934
7653
|
refHasRole,
|
|
7935
7654
|
requireAuth,
|
|
7655
|
+
requireField,
|
|
7936
7656
|
requireRole,
|
|
7657
|
+
resolveOrchestration,
|
|
7658
|
+
restrict,
|
|
7937
7659
|
review,
|
|
7660
|
+
runtime,
|
|
7661
|
+
sendMessage,
|
|
7938
7662
|
serverAction,
|
|
7939
7663
|
setAuthResolver,
|
|
7940
7664
|
setChannelTransport,
|
|
7665
|
+
setConfigContext,
|
|
7941
7666
|
setExpressionLibraryResolver,
|
|
7942
7667
|
setField,
|
|
7943
7668
|
setFields,
|
|
7944
7669
|
setInstalledModules,
|
|
7945
7670
|
setModuleConfigDefaults,
|
|
7946
7671
|
setMutationResolver,
|
|
7672
|
+
setPersistedModuleConfig,
|
|
7947
7673
|
setPlayerDebug,
|
|
7948
7674
|
setQueryResolver,
|
|
7949
7675
|
setRealtimeQueryResolver,
|
|
@@ -7952,10 +7678,14 @@ export {
|
|
|
7952
7678
|
setServerStateResolver,
|
|
7953
7679
|
setViewResolver,
|
|
7954
7680
|
spawn,
|
|
7681
|
+
spawnActor,
|
|
7955
7682
|
sql,
|
|
7956
7683
|
state,
|
|
7684
|
+
syncConfigDefaults,
|
|
7957
7685
|
testModel,
|
|
7686
|
+
timeout,
|
|
7958
7687
|
transition,
|
|
7688
|
+
updateDefinitionConfig,
|
|
7959
7689
|
useAuth,
|
|
7960
7690
|
useChannel,
|
|
7961
7691
|
useCollection,
|
|
@@ -7973,6 +7703,7 @@ export {
|
|
|
7973
7703
|
useModel,
|
|
7974
7704
|
useModule,
|
|
7975
7705
|
useModuleConfig,
|
|
7706
|
+
useModuleConfigWithMutation,
|
|
7976
7707
|
useMutation,
|
|
7977
7708
|
useNotification,
|
|
7978
7709
|
useOnChange,
|
|
@@ -7985,6 +7716,7 @@ export {
|
|
|
7985
7716
|
usePlayer,
|
|
7986
7717
|
usePlayerContext,
|
|
7987
7718
|
usePlayerContextSafe,
|
|
7719
|
+
usePresence,
|
|
7988
7720
|
useQuery,
|
|
7989
7721
|
useRealtimeQuery,
|
|
7990
7722
|
useRole,
|
|
@@ -7997,20 +7729,30 @@ export {
|
|
|
7997
7729
|
useToast,
|
|
7998
7730
|
useTransition,
|
|
7999
7731
|
useView,
|
|
7732
|
+
useVisibility,
|
|
8000
7733
|
useWhileIn,
|
|
8001
7734
|
useWorkflow,
|
|
8002
|
-
|
|
7735
|
+
useState21 as useWorkflowState,
|
|
7736
|
+
userAction,
|
|
7737
|
+
userChoice,
|
|
7738
|
+
validate,
|
|
8003
7739
|
validateExperienceWorkflow,
|
|
8004
7740
|
validateModel,
|
|
7741
|
+
visibleTo,
|
|
8005
7742
|
when,
|
|
7743
|
+
withAuditLog,
|
|
8006
7744
|
withAuditTrail,
|
|
7745
|
+
withAuth,
|
|
7746
|
+
withMetrics,
|
|
8007
7747
|
withOwnership,
|
|
8008
7748
|
withPagination,
|
|
8009
7749
|
withRBAC,
|
|
7750
|
+
withRateLimit,
|
|
8010
7751
|
withSearch,
|
|
8011
7752
|
withSlug,
|
|
8012
7753
|
withSoftDelete,
|
|
8013
7754
|
withTags,
|
|
8014
7755
|
withTimestamps,
|
|
7756
|
+
withValidation,
|
|
8015
7757
|
withVersioning
|
|
8016
7758
|
};
|