@mmapp/react 0.1.0-alpha.1 → 0.1.0-alpha.10

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.
Files changed (94) hide show
  1. package/README.md +112 -0
  2. package/dist/index.d.mts +1378 -94
  3. package/dist/index.d.ts +1378 -94
  4. package/dist/index.js +1094 -1309
  5. package/dist/index.mjs +1038 -1296
  6. package/package.json +4 -3
  7. package/package.json.backup +0 -41
  8. package/src/Blueprint.ts +0 -216
  9. package/src/__tests__/Blueprint.test.ts +0 -106
  10. package/src/__tests__/action-context.test.ts +0 -166
  11. package/src/__tests__/actionCreators.test.ts +0 -179
  12. package/src/__tests__/builders.test.ts +0 -336
  13. package/src/__tests__/defineBlueprint-composition.test.ts +0 -106
  14. package/src/__tests__/factories.test.ts +0 -229
  15. package/src/__tests__/loader.test.ts +0 -159
  16. package/src/__tests__/logger.test.ts +0 -70
  17. package/src/__tests__/type-inference.test.ts +0 -160
  18. package/src/__tests__/typed-transitions.test.ts +0 -126
  19. package/src/__tests__/useModuleConfig.test.ts +0 -61
  20. package/src/actionCreators.ts +0 -132
  21. package/src/actions.ts +0 -547
  22. package/src/atoms/index.ts +0 -600
  23. package/src/authoring.ts +0 -92
  24. package/src/browser-player.ts +0 -783
  25. package/src/builders.ts +0 -1342
  26. package/src/components/ExperienceWorkflowBridge.tsx +0 -123
  27. package/src/components/PlayerProvider.tsx +0 -43
  28. package/src/components/atoms/index.tsx +0 -269
  29. package/src/components/index.ts +0 -36
  30. package/src/conditions.ts +0 -692
  31. package/src/config/defineBlueprint.ts +0 -329
  32. package/src/config/defineModel.ts +0 -753
  33. package/src/config/defineWorkspace.ts +0 -24
  34. package/src/core/WorkflowRuntime.ts +0 -153
  35. package/src/factories.ts +0 -425
  36. package/src/grammar/index.ts +0 -173
  37. package/src/hooks/index.ts +0 -106
  38. package/src/hooks/useAuth.ts +0 -288
  39. package/src/hooks/useChannel.ts +0 -304
  40. package/src/hooks/useComputed.ts +0 -154
  41. package/src/hooks/useDomainSubscription.ts +0 -110
  42. package/src/hooks/useDuringAction.ts +0 -99
  43. package/src/hooks/useExperienceState.ts +0 -59
  44. package/src/hooks/useExpressionLibrary.ts +0 -129
  45. package/src/hooks/useForm.ts +0 -352
  46. package/src/hooks/useGeolocation.ts +0 -207
  47. package/src/hooks/useMapView.ts +0 -259
  48. package/src/hooks/useMiddleware.ts +0 -291
  49. package/src/hooks/useModel.ts +0 -363
  50. package/src/hooks/useModule.ts +0 -59
  51. package/src/hooks/useModuleConfig.ts +0 -61
  52. package/src/hooks/useMutation.ts +0 -237
  53. package/src/hooks/useNotification.ts +0 -151
  54. package/src/hooks/useOnChange.ts +0 -30
  55. package/src/hooks/useOnEnter.ts +0 -59
  56. package/src/hooks/useOnEvent.ts +0 -37
  57. package/src/hooks/useOnExit.ts +0 -27
  58. package/src/hooks/useOnTransition.ts +0 -30
  59. package/src/hooks/usePackage.ts +0 -128
  60. package/src/hooks/useParams.ts +0 -33
  61. package/src/hooks/usePlayer.ts +0 -308
  62. package/src/hooks/useQuery.ts +0 -184
  63. package/src/hooks/useRealtimeQuery.ts +0 -222
  64. package/src/hooks/useRole.ts +0 -191
  65. package/src/hooks/useRouteParams.ts +0 -100
  66. package/src/hooks/useRouter.ts +0 -347
  67. package/src/hooks/useServerAction.ts +0 -178
  68. package/src/hooks/useServerState.ts +0 -284
  69. package/src/hooks/useToast.ts +0 -164
  70. package/src/hooks/useTransition.ts +0 -39
  71. package/src/hooks/useView.ts +0 -102
  72. package/src/hooks/useWhileIn.ts +0 -48
  73. package/src/hooks/useWorkflow.ts +0 -63
  74. package/src/index.ts +0 -465
  75. package/src/loader/experience-workflow-loader.ts +0 -192
  76. package/src/loader/index.ts +0 -6
  77. package/src/local/LocalEngine.ts +0 -388
  78. package/src/local/LocalEngineAdapter.ts +0 -175
  79. package/src/local/LocalEngineContext.ts +0 -30
  80. package/src/logger.ts +0 -37
  81. package/src/mixins.ts +0 -1160
  82. package/src/providers/RuntimeContext.ts +0 -20
  83. package/src/providers/WorkflowProvider.tsx +0 -28
  84. package/src/routing/instance-key.ts +0 -107
  85. package/src/server/transition-context.ts +0 -172
  86. package/src/testing/index.ts +0 -9
  87. package/src/testing/useBlueprintTestRunner.ts +0 -91
  88. package/src/testing/useGraphAnalysis.ts +0 -18
  89. package/src/testing/useTestRunner.ts +0 -77
  90. package/src/testing.ts +0 -995
  91. package/src/types/workflow-inference.ts +0 -158
  92. package/src/types.ts +0 -114
  93. package/tsconfig.json +0 -27
  94. package/vitest.config.ts +0 -8
package/dist/index.js CHANGED
@@ -32,6 +32,7 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  Accordion: () => Accordion,
34
34
  AnimatedBox: () => AnimatedBox,
35
+ BUILT_IN_CONSTRAINTS: () => BUILT_IN_CONSTRAINTS,
35
36
  Badge: () => Badge,
36
37
  Blueprint: () => Blueprint,
37
38
  BrowserPlayer: () => BrowserPlayer,
@@ -58,6 +59,7 @@ __export(index_exports, {
58
59
  Modal: () => Modal,
59
60
  ModelBuilder: () => ModelBuilder,
60
61
  NavLink: () => NavLink,
62
+ ORCHESTRATION_PRESETS: () => ORCHESTRATION_PRESETS,
61
63
  PlayerProvider: () => PlayerProvider,
62
64
  RoleGuard: () => RoleGuard,
63
65
  Route: () => Route,
@@ -81,12 +83,19 @@ __export(index_exports, {
81
83
  WorkflowProvider: () => WorkflowProvider,
82
84
  WorkflowRuntime: () => WorkflowRuntime,
83
85
  action: () => action,
84
- and: () => and2,
86
+ actor: () => actor,
87
+ after: () => after,
88
+ allowTransition: () => allowTransition,
89
+ and: () => and,
85
90
  applyMixins: () => applyMixins,
86
91
  approval: () => approval,
87
92
  assertModelValid: () => assertModelValid,
88
93
  cedar: () => cedar,
94
+ compose: () => compose,
95
+ computeVisibility: () => computeVisibility,
96
+ configureActor: () => configureActor,
89
97
  connector: () => connector,
98
+ constraints: () => constraints,
90
99
  createActions: () => createActions,
91
100
  createCRUD: () => createCRUD,
92
101
  createLocalDataResolver: () => createLocalDataResolver,
@@ -95,16 +104,26 @@ __export(index_exports, {
95
104
  cron: () => cron,
96
105
  crud: () => crud,
97
106
  defineBlueprint: () => defineBlueprint,
107
+ defineImperativeBlueprint: () => blueprint,
108
+ defineMiddleware: () => defineMiddleware,
98
109
  defineModel: () => defineModel,
99
110
  defineModule: () => defineModule,
111
+ defineRoles: () => defineRoles,
100
112
  defineWorkspace: () => defineWorkspace,
113
+ delay: () => delay,
101
114
  deriveInstanceKey: () => deriveInstanceKey,
102
115
  deriveInstanceKeySync: () => deriveInstanceKeySync,
103
116
  describeModel: () => describeModel,
104
117
  deviceAction: () => deviceAction,
105
118
  dmn: () => dmn,
119
+ editableBy: () => editableBy,
120
+ editableIn: () => editableIn,
121
+ emit: () => emit,
106
122
  escalation: () => escalation,
123
+ every: () => every,
107
124
  expr: () => expr,
125
+ extend: () => extend,
126
+ extendMiddleware: () => extendMiddleware,
108
127
  field: () => field,
109
128
  fieldContains: () => fieldContains,
110
129
  fieldEquals: () => fieldEquals,
@@ -119,12 +138,21 @@ __export(index_exports, {
119
138
  getInstalledModule: () => getInstalledModule,
120
139
  getInstalledModules: () => getInstalledModules,
121
140
  graphql: () => graphql,
141
+ guard: () => guard,
122
142
  hasAnyRole: () => hasAnyRole,
123
143
  hasRole: () => hasRole,
144
+ imperativeCron: () => cron2,
145
+ imperativeLog: () => log,
146
+ imperativeNotify: () => notify2,
147
+ imperativeRequireRole: () => requireRole2,
124
148
  inState: () => inState,
125
149
  inputEquals: () => inputEquals,
126
150
  inputRequired: () => inputRequired,
151
+ instance: () => instance,
127
152
  isActor: () => isActor,
153
+ isActorConfig: () => isActorConfig,
154
+ isBuiltInConstraint: () => isBuiltInConstraint,
155
+ isConstraintDeclaration: () => isConstraintDeclaration,
128
156
  isCreator: () => isCreator,
129
157
  isOwner: () => isOwner,
130
158
  isPlayerDebug: () => isPlayerDebug,
@@ -134,28 +162,39 @@ __export(index_exports, {
134
162
  loadExperienceWorkflow: () => loadExperienceWorkflow,
135
163
  logEvent: () => logEvent,
136
164
  model: () => model,
165
+ named: () => named,
137
166
  normalizeDefinition: () => normalizeDefinition,
138
- not: () => not2,
167
+ not: () => not,
139
168
  notInState: () => notInState,
140
169
  notify: () => notify,
141
- or: () => or2,
170
+ on: () => on,
171
+ or: () => or,
172
+ orchestration: () => orchestration,
173
+ patch: () => patch,
142
174
  pipe: () => pipe,
143
175
  playerLog: () => playerLog,
144
176
  prefetchData: () => prefetchData,
145
177
  refHasAnyRole: () => refHasAnyRole,
146
178
  refHasRole: () => refHasRole,
147
179
  requireAuth: () => requireAuth,
180
+ requireField: () => requireField,
148
181
  requireRole: () => requireRole,
182
+ resolveOrchestration: () => resolveOrchestration,
183
+ restrict: () => restrict,
149
184
  review: () => review,
185
+ runtime: () => runtime,
186
+ sendMessage: () => sendMessage,
150
187
  serverAction: () => serverAction,
151
188
  setAuthResolver: () => setAuthResolver,
152
189
  setChannelTransport: () => setChannelTransport,
190
+ setConfigContext: () => setConfigContext,
153
191
  setExpressionLibraryResolver: () => setExpressionLibraryResolver,
154
192
  setField: () => setField,
155
193
  setFields: () => setFields,
156
194
  setInstalledModules: () => setInstalledModules,
157
195
  setModuleConfigDefaults: () => setModuleConfigDefaults,
158
196
  setMutationResolver: () => setMutationResolver,
197
+ setPersistedModuleConfig: () => setPersistedModuleConfig,
159
198
  setPlayerDebug: () => setPlayerDebug,
160
199
  setQueryResolver: () => setQueryResolver,
161
200
  setRealtimeQueryResolver: () => setRealtimeQueryResolver,
@@ -164,10 +203,14 @@ __export(index_exports, {
164
203
  setServerStateResolver: () => setServerStateResolver,
165
204
  setViewResolver: () => setViewResolver,
166
205
  spawn: () => spawn,
206
+ spawnActor: () => spawnActor,
167
207
  sql: () => sql,
168
208
  state: () => state,
209
+ syncConfigDefaults: () => syncConfigDefaults,
169
210
  testModel: () => testModel,
211
+ timeout: () => timeout,
170
212
  transition: () => transition,
213
+ updateDefinitionConfig: () => updateDefinitionConfig,
171
214
  useAuth: () => useAuth,
172
215
  useChannel: () => useChannel,
173
216
  useCollection: () => useCollection,
@@ -185,6 +228,7 @@ __export(index_exports, {
185
228
  useModel: () => useModel,
186
229
  useModule: () => useModule,
187
230
  useModuleConfig: () => useModuleConfig,
231
+ useModuleConfigWithMutation: () => useModuleConfigWithMutation,
188
232
  useMutation: () => useMutation,
189
233
  useNotification: () => useNotification,
190
234
  useOnChange: () => useOnChange,
@@ -197,6 +241,7 @@ __export(index_exports, {
197
241
  usePlayer: () => usePlayer,
198
242
  usePlayerContext: () => usePlayerContext,
199
243
  usePlayerContextSafe: () => usePlayerContextSafe,
244
+ usePresence: () => usePresence,
200
245
  useQuery: () => useQuery,
201
246
  useRealtimeQuery: () => useRealtimeQuery,
202
247
  useRole: () => useRole,
@@ -209,1109 +254,37 @@ __export(index_exports, {
209
254
  useToast: () => useToast,
210
255
  useTransition: () => useTransition,
211
256
  useView: () => useView,
257
+ useVisibility: () => useVisibility,
212
258
  useWhileIn: () => useWhileIn,
213
259
  useWorkflow: () => useWorkflow,
214
- useWorkflowState: () => useState20,
260
+ useWorkflowState: () => useState21,
261
+ userAction: () => userAction,
262
+ userChoice: () => userChoice,
263
+ validate: () => validate,
215
264
  validateExperienceWorkflow: () => validateExperienceWorkflow,
216
265
  validateModel: () => validateModel,
266
+ visibleTo: () => visibleTo,
217
267
  when: () => when,
268
+ withAuditLog: () => withAuditLog,
218
269
  withAuditTrail: () => withAuditTrail,
270
+ withAuth: () => withAuth,
271
+ withMetrics: () => withMetrics,
219
272
  withOwnership: () => withOwnership,
220
273
  withPagination: () => withPagination,
221
274
  withRBAC: () => withRBAC,
275
+ withRateLimit: () => withRateLimit,
222
276
  withSearch: () => withSearch,
223
277
  withSlug: () => withSlug,
224
278
  withSoftDelete: () => withSoftDelete,
225
279
  withTags: () => withTags,
226
280
  withTimestamps: () => withTimestamps,
281
+ withValidation: () => withValidation,
227
282
  withVersioning: () => withVersioning
228
283
  });
229
284
  module.exports = __toCommonJS(index_exports);
230
285
 
231
- // ../player-core/dist/index.mjs
232
- var add = {
233
- name: "add",
234
- fn: (a, b) => Number(a) + Number(b),
235
- arity: 2
236
- };
237
- var subtract = {
238
- name: "subtract",
239
- fn: (a, b) => Number(a) - Number(b),
240
- arity: 2
241
- };
242
- var multiply = {
243
- name: "multiply",
244
- fn: (a, b) => Number(a) * Number(b),
245
- arity: 2
246
- };
247
- var divide = {
248
- name: "divide",
249
- fn: (a, b) => {
250
- const d = Number(b);
251
- return d === 0 ? 0 : Number(a) / d;
252
- },
253
- arity: 2
254
- };
255
- var abs = {
256
- name: "abs",
257
- fn: (a) => Math.abs(Number(a)),
258
- arity: 1
259
- };
260
- var round = {
261
- name: "round",
262
- fn: (a, decimals) => {
263
- const d = decimals != null ? Number(decimals) : 0;
264
- const factor = Math.pow(10, d);
265
- return Math.round(Number(a) * factor) / factor;
266
- },
267
- arity: -1
268
- };
269
- var min = {
270
- name: "min",
271
- fn: (...args) => {
272
- const nums = args.flat().map(Number).filter((n) => !isNaN(n));
273
- return nums.length === 0 ? 0 : Math.min(...nums);
274
- },
275
- arity: -1
276
- };
277
- var max = {
278
- name: "max",
279
- fn: (...args) => {
280
- const nums = args.flat().map(Number).filter((n) => !isNaN(n));
281
- return nums.length === 0 ? 0 : Math.max(...nums);
282
- },
283
- arity: -1
284
- };
285
- var eq = {
286
- name: "eq",
287
- fn: (a, b) => a === b || String(a) === String(b),
288
- arity: 2
289
- };
290
- var neq = {
291
- name: "neq",
292
- fn: (a, b) => a !== b && String(a) !== String(b),
293
- arity: 2
294
- };
295
- var gt = {
296
- name: "gt",
297
- fn: (a, b) => Number(a) > Number(b),
298
- arity: 2
299
- };
300
- var gte = {
301
- name: "gte",
302
- fn: (a, b) => Number(a) >= Number(b),
303
- arity: 2
304
- };
305
- var lt = {
306
- name: "lt",
307
- fn: (a, b) => Number(a) < Number(b),
308
- arity: 2
309
- };
310
- var lte = {
311
- name: "lte",
312
- fn: (a, b) => Number(a) <= Number(b),
313
- arity: 2
314
- };
315
- var if_fn = {
316
- name: "if",
317
- fn: (cond, then, else_) => cond ? then : else_,
318
- arity: 3
319
- };
320
- var and = {
321
- name: "and",
322
- fn: (...args) => args.every(Boolean),
323
- arity: -1
324
- };
325
- var or = {
326
- name: "or",
327
- fn: (...args) => args.some(Boolean),
328
- arity: -1
329
- };
330
- var not = {
331
- name: "not",
332
- fn: (a) => !a,
333
- arity: 1
334
- };
335
- var coalesce = {
336
- name: "coalesce",
337
- fn: (...args) => {
338
- for (const arg of args) {
339
- if (arg != null) return arg;
340
- }
341
- return null;
342
- },
343
- arity: -1
344
- };
345
- var concat = {
346
- name: "concat",
347
- fn: (...args) => args.map(String).join(""),
348
- arity: -1
349
- };
350
- var upper = {
351
- name: "upper",
352
- fn: (s) => String(s ?? "").toUpperCase(),
353
- arity: 1
354
- };
355
- var lower = {
356
- name: "lower",
357
- fn: (s) => String(s ?? "").toLowerCase(),
358
- arity: 1
359
- };
360
- var trim = {
361
- name: "trim",
362
- fn: (s) => String(s ?? "").trim(),
363
- arity: 1
364
- };
365
- var format = {
366
- name: "format",
367
- fn: (template, ...args) => {
368
- let result = String(template ?? "");
369
- args.forEach((arg, i) => {
370
- result = result.replace(`{${i}}`, String(arg ?? ""));
371
- });
372
- return result;
373
- },
374
- arity: -1
375
- };
376
- var length = {
377
- name: "length",
378
- fn: (v) => {
379
- if (Array.isArray(v)) return v.length;
380
- if (typeof v === "string") return v.length;
381
- if (v && typeof v === "object") return Object.keys(v).length;
382
- return 0;
383
- },
384
- arity: 1
385
- };
386
- var get = {
387
- name: "get",
388
- fn: (obj, path) => {
389
- if (obj == null || typeof path !== "string") return void 0;
390
- const parts = path.split(".");
391
- let current = obj;
392
- for (const part of parts) {
393
- if (current == null || typeof current !== "object") return void 0;
394
- current = current[part];
395
- }
396
- return current;
397
- },
398
- arity: 2
399
- };
400
- var includes = {
401
- name: "includes",
402
- fn: (collection, value) => {
403
- if (Array.isArray(collection)) return collection.includes(value);
404
- if (typeof collection === "string") return collection.includes(String(value));
405
- return false;
406
- },
407
- arity: 2
408
- };
409
- var is_defined = {
410
- name: "is_defined",
411
- fn: (v) => v !== void 0 && v !== null,
412
- arity: 1
413
- };
414
- var is_empty = {
415
- name: "is_empty",
416
- fn: (v) => {
417
- if (v == null) return true;
418
- if (typeof v === "string") return v.length === 0;
419
- if (Array.isArray(v)) return v.length === 0;
420
- if (typeof v === "object") return Object.keys(v).length === 0;
421
- return false;
422
- },
423
- arity: 1
424
- };
425
- var is_null = {
426
- name: "is_null",
427
- fn: (v) => v === null || v === void 0,
428
- arity: 1
429
- };
430
- var to_string = {
431
- name: "to_string",
432
- fn: (v) => {
433
- if (v == null) return "";
434
- if (typeof v === "object") return JSON.stringify(v);
435
- return String(v);
436
- },
437
- arity: 1
438
- };
439
- var CORE_FUNCTIONS = [
440
- // Math (8)
441
- add,
442
- subtract,
443
- multiply,
444
- divide,
445
- abs,
446
- round,
447
- min,
448
- max,
449
- // Comparison (6)
450
- eq,
451
- neq,
452
- gt,
453
- gte,
454
- lt,
455
- lte,
456
- // Logic (5)
457
- if_fn,
458
- and,
459
- or,
460
- not,
461
- coalesce,
462
- // String (6)
463
- concat,
464
- upper,
465
- lower,
466
- trim,
467
- format,
468
- length,
469
- // Path (3)
470
- get,
471
- includes,
472
- is_defined,
473
- // Type (3)
474
- is_empty,
475
- is_null,
476
- to_string
477
- ];
478
- function buildFunctionMap(functions) {
479
- const map = /* @__PURE__ */ new Map();
480
- for (const fn of functions) {
481
- map.set(fn.name, fn.fn);
482
- }
483
- return map;
484
- }
485
- var MAX_DEPTH = 50;
486
- var Parser = class {
487
- pos = 0;
488
- depth = 0;
489
- input;
490
- constructor(input) {
491
- this.input = input;
492
- }
493
- parse() {
494
- this.skipWhitespace();
495
- const node = this.parseExpression();
496
- this.skipWhitespace();
497
- if (this.pos < this.input.length) {
498
- throw new Error(`Unexpected character at position ${this.pos}: '${this.input[this.pos]}'`);
499
- }
500
- return node;
501
- }
502
- guardDepth() {
503
- if (++this.depth > MAX_DEPTH) {
504
- throw new Error("Expression too deeply nested");
505
- }
506
- }
507
- parseExpression() {
508
- this.guardDepth();
509
- try {
510
- return this.parseTernary();
511
- } finally {
512
- this.depth--;
513
- }
514
- }
515
- parseTernary() {
516
- let node = this.parseLogicalOr();
517
- this.skipWhitespace();
518
- if (this.peek() === "?") {
519
- this.advance();
520
- const consequent = this.parseExpression();
521
- this.skipWhitespace();
522
- this.expect(":");
523
- const alternate = this.parseExpression();
524
- node = { type: "ternary", condition: node, consequent, alternate };
525
- }
526
- return node;
527
- }
528
- parseLogicalOr() {
529
- let left = this.parseLogicalAnd();
530
- this.skipWhitespace();
531
- while (this.match("||")) {
532
- const right = this.parseLogicalAnd();
533
- left = { type: "binary", operator: "||", left, right };
534
- this.skipWhitespace();
535
- }
536
- return left;
537
- }
538
- parseLogicalAnd() {
539
- let left = this.parseEquality();
540
- this.skipWhitespace();
541
- while (this.match("&&")) {
542
- const right = this.parseEquality();
543
- left = { type: "binary", operator: "&&", left, right };
544
- this.skipWhitespace();
545
- }
546
- return left;
547
- }
548
- parseEquality() {
549
- let left = this.parseComparison();
550
- this.skipWhitespace();
551
- while (true) {
552
- if (this.match("==")) {
553
- const right = this.parseComparison();
554
- left = { type: "binary", operator: "==", left, right };
555
- } else if (this.match("!=")) {
556
- const right = this.parseComparison();
557
- left = { type: "binary", operator: "!=", left, right };
558
- } else {
559
- break;
560
- }
561
- this.skipWhitespace();
562
- }
563
- return left;
564
- }
565
- parseComparison() {
566
- let left = this.parseUnary();
567
- this.skipWhitespace();
568
- while (true) {
569
- if (this.match(">=")) {
570
- const right = this.parseUnary();
571
- left = { type: "binary", operator: ">=", left, right };
572
- } else if (this.match("<=")) {
573
- const right = this.parseUnary();
574
- left = { type: "binary", operator: "<=", left, right };
575
- } else if (this.peek() === ">" && !this.lookAhead(">=")) {
576
- this.advance();
577
- const right = this.parseUnary();
578
- left = { type: "binary", operator: ">", left, right };
579
- } else if (this.peek() === "<" && !this.lookAhead("<=")) {
580
- this.advance();
581
- const right = this.parseUnary();
582
- left = { type: "binary", operator: "<", left, right };
583
- } else {
584
- break;
585
- }
586
- this.skipWhitespace();
587
- }
588
- return left;
589
- }
590
- parseUnary() {
591
- this.skipWhitespace();
592
- if (this.peek() === "!") {
593
- this.advance();
594
- const operand = this.parseUnary();
595
- return { type: "unary", operator: "!", operand };
596
- }
597
- if (this.peek() === "-") {
598
- const nextChar = this.input[this.pos + 1];
599
- if (nextChar !== void 0 && (nextChar >= "0" && nextChar <= "9" || nextChar === ".")) {
600
- return this.parseCallChain();
601
- }
602
- }
603
- return this.parseCallChain();
604
- }
605
- parseCallChain() {
606
- let node = this.parsePrimary();
607
- while (true) {
608
- this.skipWhitespace();
609
- if (this.peek() === "(") {
610
- this.advance();
611
- const args = this.parseArgList();
612
- this.expect(")");
613
- if (node.type === "identifier") {
614
- node = { type: "call", name: node.name, args };
615
- } else if (node.type === "path") {
616
- const name = node.segments.join(".");
617
- node = { type: "call", name, args };
618
- } else if (node.type === "member") {
619
- node = { type: "method_call", object: node.object, method: node.property, args };
620
- } else {
621
- throw new Error("Cannot call non-function");
622
- }
623
- } else if (this.peek() === ".") {
624
- this.advance();
625
- const prop = this.parseIdentifierName();
626
- node = { type: "member", object: node, property: prop };
627
- } else {
628
- break;
629
- }
630
- }
631
- return node;
632
- }
633
- parsePrimary() {
634
- this.skipWhitespace();
635
- const ch = this.peek();
636
- if (ch === "(") {
637
- this.advance();
638
- const expr2 = this.parseExpression();
639
- this.skipWhitespace();
640
- this.expect(")");
641
- return expr2;
642
- }
643
- if (ch === "'" || ch === '"') {
644
- return this.parseString();
645
- }
646
- if (ch === "-" || ch >= "0" && ch <= "9") {
647
- return this.parseNumber();
648
- }
649
- if (this.isIdentStart(ch)) {
650
- return this.parseIdentifierOrPath();
651
- }
652
- throw new Error(
653
- `Unexpected character at position ${this.pos}: '${ch || "EOF"}'`
654
- );
655
- }
656
- parseString() {
657
- const quote = this.advance();
658
- let value = "";
659
- while (this.pos < this.input.length && this.peek() !== quote) {
660
- if (this.peek() === "\\") {
661
- this.advance();
662
- const esc = this.advance();
663
- if (esc === "n") value += "\n";
664
- else if (esc === "t") value += " ";
665
- else if (esc === "r") value += "\r";
666
- else value += esc;
667
- } else {
668
- value += this.advance();
669
- }
670
- }
671
- if (this.pos >= this.input.length) {
672
- throw new Error("Unterminated string literal");
673
- }
674
- this.advance();
675
- return { type: "string", value };
676
- }
677
- parseNumber() {
678
- let numStr = "";
679
- if (this.peek() === "-") {
680
- numStr += this.advance();
681
- }
682
- while (this.pos < this.input.length && (this.input[this.pos] >= "0" && this.input[this.pos] <= "9")) {
683
- numStr += this.advance();
684
- }
685
- if (this.peek() === "." && this.pos + 1 < this.input.length && this.input[this.pos + 1] >= "0" && this.input[this.pos + 1] <= "9") {
686
- numStr += this.advance();
687
- while (this.pos < this.input.length && (this.input[this.pos] >= "0" && this.input[this.pos] <= "9")) {
688
- numStr += this.advance();
689
- }
690
- }
691
- return { type: "number", value: Number(numStr) };
692
- }
693
- parseIdentifierOrPath() {
694
- const name = this.parseIdentifierName();
695
- if (name === "true") return { type: "boolean", value: true };
696
- if (name === "false") return { type: "boolean", value: false };
697
- if (name === "null") return { type: "null" };
698
- if (name === "undefined") return { type: "null" };
699
- return { type: "identifier", name };
700
- }
701
- parseIdentifierName() {
702
- let name = "";
703
- if (this.peek() === "$") name += this.advance();
704
- while (this.pos < this.input.length && this.isIdentPart(this.input[this.pos])) {
705
- name += this.advance();
706
- }
707
- if (!name) {
708
- throw new Error(`Expected identifier at position ${this.pos}`);
709
- }
710
- return name;
711
- }
712
- parseArgList() {
713
- this.skipWhitespace();
714
- if (this.peek() === ")") return [];
715
- const args = [];
716
- args.push(this.parseExpression());
717
- this.skipWhitespace();
718
- while (this.peek() === ",") {
719
- this.advance();
720
- args.push(this.parseExpression());
721
- this.skipWhitespace();
722
- }
723
- return args;
724
- }
725
- // Character utilities
726
- peek() {
727
- return this.input[this.pos] ?? "";
728
- }
729
- advance() {
730
- return this.input[this.pos++] ?? "";
731
- }
732
- match(str) {
733
- if (this.input.startsWith(str, this.pos)) {
734
- this.pos += str.length;
735
- return true;
736
- }
737
- return false;
738
- }
739
- lookAhead(str) {
740
- return this.input.startsWith(str, this.pos);
741
- }
742
- expect(ch) {
743
- this.skipWhitespace();
744
- if (this.peek() !== ch) {
745
- throw new Error(`Expected '${ch}' at position ${this.pos}, got '${this.peek() || "EOF"}'`);
746
- }
747
- this.advance();
748
- }
749
- skipWhitespace() {
750
- while (this.pos < this.input.length && " \n\r".includes(this.input[this.pos])) {
751
- this.pos++;
752
- }
753
- }
754
- isIdentStart(ch) {
755
- return ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch === "_" || ch === "$";
756
- }
757
- isIdentPart(ch) {
758
- return this.isIdentStart(ch) || ch >= "0" && ch <= "9";
759
- }
760
- };
761
- function evaluateAST(node, context, fnMap) {
762
- switch (node.type) {
763
- case "number":
764
- return node.value;
765
- case "string":
766
- return node.value;
767
- case "boolean":
768
- return node.value;
769
- case "null":
770
- return null;
771
- case "identifier":
772
- return resolvePath(node.name, context);
773
- case "path":
774
- return resolvePath(node.segments.join("."), context);
775
- case "member": {
776
- const obj = evaluateAST(node.object, context, fnMap);
777
- if (obj == null || typeof obj !== "object") return void 0;
778
- return obj[node.property];
779
- }
780
- case "call": {
781
- const fn = fnMap.get(node.name);
782
- if (!fn) return void 0;
783
- const args = node.args.map((a) => evaluateAST(a, context, fnMap));
784
- return fn(...args);
785
- }
786
- case "method_call": {
787
- const obj = evaluateAST(node.object, context, fnMap);
788
- if (obj != null && typeof obj === "object") {
789
- const method = obj[node.method];
790
- if (typeof method === "function") {
791
- const args = node.args.map((a) => evaluateAST(a, context, fnMap));
792
- return method.apply(obj, args);
793
- }
794
- }
795
- return void 0;
796
- }
797
- case "unary": {
798
- const operand = evaluateAST(node.operand, context, fnMap);
799
- return !operand;
800
- }
801
- case "binary": {
802
- if (node.operator === "&&") {
803
- const left2 = evaluateAST(node.left, context, fnMap);
804
- if (!left2) return left2;
805
- return evaluateAST(node.right, context, fnMap);
806
- }
807
- if (node.operator === "||") {
808
- const left2 = evaluateAST(node.left, context, fnMap);
809
- if (left2) return left2;
810
- return evaluateAST(node.right, context, fnMap);
811
- }
812
- const left = evaluateAST(node.left, context, fnMap);
813
- const right = evaluateAST(node.right, context, fnMap);
814
- switch (node.operator) {
815
- // eslint-disable-next-line eqeqeq
816
- case "==":
817
- return left == right;
818
- // eslint-disable-next-line eqeqeq
819
- case "!=":
820
- return left != right;
821
- case ">":
822
- return Number(left) > Number(right);
823
- case "<":
824
- return Number(left) < Number(right);
825
- case ">=":
826
- return Number(left) >= Number(right);
827
- case "<=":
828
- return Number(left) <= Number(right);
829
- default:
830
- return void 0;
831
- }
832
- }
833
- case "ternary": {
834
- const condition = evaluateAST(node.condition, context, fnMap);
835
- return condition ? evaluateAST(node.consequent, context, fnMap) : evaluateAST(node.alternate, context, fnMap);
836
- }
837
- }
838
- }
839
- var MAX_CACHE = 500;
840
- var astCache = /* @__PURE__ */ new Map();
841
- function evictIfNeeded() {
842
- if (astCache.size > MAX_CACHE) {
843
- const keys = Array.from(astCache.keys());
844
- const evictCount = Math.floor(MAX_CACHE * 0.25);
845
- for (let i = 0; i < evictCount; i++) {
846
- astCache.delete(keys[i]);
847
- }
848
- }
849
- }
850
- function parseAndCache(expr2) {
851
- const cached = astCache.get(expr2);
852
- if (cached) return cached;
853
- const parser = new Parser(expr2);
854
- const ast = parser.parse();
855
- astCache.set(expr2, ast);
856
- evictIfNeeded();
857
- return ast;
858
- }
859
- var TEMPLATE_RE = /\{\{(.+?)\}\}/g;
860
- function resolvePath(path, context) {
861
- const parts = path.split(".");
862
- let current = context;
863
- for (const part of parts) {
864
- if (current == null || typeof current !== "object") return void 0;
865
- current = current[part];
866
- }
867
- return current;
868
- }
869
- function evaluateExpression(expr2, context, fnMap) {
870
- const trimmed = expr2.trim();
871
- if (trimmed === "true") return true;
872
- if (trimmed === "false") return false;
873
- if (trimmed === "null") return null;
874
- if (trimmed === "undefined") return void 0;
875
- const num = Number(trimmed);
876
- if (!isNaN(num) && trimmed !== "") return num;
877
- if (trimmed.startsWith("'") && trimmed.endsWith("'") || trimmed.startsWith('"') && trimmed.endsWith('"')) {
878
- return trimmed.slice(1, -1);
879
- }
880
- if (/^[a-zA-Z_$][\w$.]*$/.test(trimmed)) {
881
- return resolvePath(trimmed, context);
882
- }
883
- const ast = parseAndCache(trimmed);
884
- return evaluateAST(ast, context, fnMap);
885
- }
886
- var WEB_FAILURE_POLICIES = {
887
- VIEW_BINDING: {
888
- on_error: "return_fallback",
889
- fallback_value: "",
890
- log_level: "warn"
891
- },
892
- EVENT_REACTION: {
893
- on_error: "log_and_skip",
894
- fallback_value: void 0,
895
- log_level: "error"
896
- },
897
- DURING_ACTION: {
898
- on_error: "log_and_skip",
899
- fallback_value: void 0,
900
- log_level: "error"
901
- },
902
- CONDITIONAL_VISIBILITY: {
903
- on_error: "return_fallback",
904
- fallback_value: true,
905
- // Show by default if condition fails
906
- log_level: "warn"
907
- }
908
- };
909
- function createEvaluator(config) {
910
- const allFunctions = [...CORE_FUNCTIONS, ...config.functions];
911
- const fnMap = buildFunctionMap(allFunctions);
912
- const policy = config.failurePolicy;
913
- function handleError(expr2, error) {
914
- const message = error instanceof Error ? error.message : String(error);
915
- if (policy.log_level === "error") {
916
- console.error(`[player-core] Expression error: "${expr2}" \u2014 ${message}`);
917
- } else if (policy.log_level === "warn") {
918
- console.warn(`[player-core] Expression error: "${expr2}" \u2014 ${message}`);
919
- }
920
- switch (policy.on_error) {
921
- case "throw":
922
- throw error;
923
- case "return_fallback":
924
- return { value: policy.fallback_value, status: "fallback", error: message };
925
- case "log_and_skip":
926
- default:
927
- return { value: policy.fallback_value, status: "error", error: message };
928
- }
929
- }
930
- return {
931
- evaluate(expression, context) {
932
- try {
933
- const value = evaluateExpression(expression, context, fnMap);
934
- return { value, status: "ok" };
935
- } catch (error) {
936
- return handleError(expression, error);
937
- }
938
- },
939
- evaluateTemplate(template, context) {
940
- try {
941
- if (!template.includes("{{")) {
942
- return { value: template, status: "ok" };
943
- }
944
- const result = template.replace(TEMPLATE_RE, (_match, expr2) => {
945
- const value = evaluateExpression(expr2, context, fnMap);
946
- return value != null ? String(value) : "";
947
- });
948
- return { value: result, status: "ok" };
949
- } catch (error) {
950
- return handleError(template, error);
951
- }
952
- },
953
- validate(expression) {
954
- const errors = [];
955
- try {
956
- parseAndCache(expression);
957
- } catch (e) {
958
- errors.push(e instanceof Error ? e.message : String(e));
959
- }
960
- return { valid: errors.length === 0, errors };
961
- }
962
- };
963
- }
964
- var MAX_AUTO_CHAIN = 10;
965
- var StateMachine = class {
966
- evaluator;
967
- actionHandlers;
968
- listeners = /* @__PURE__ */ new Set();
969
- instance;
970
- constructor(definition, initialData = {}, config) {
971
- this.evaluator = config.evaluator;
972
- this.actionHandlers = config.actionHandlers ?? /* @__PURE__ */ new Map();
973
- const startState = definition.states.find((s) => s.type === "START");
974
- if (!startState) {
975
- throw new Error(`No START state found in definition ${definition.slug}`);
976
- }
977
- this.instance = {
978
- definition,
979
- current_state: startState.name,
980
- state_data: { ...initialData },
981
- memory: {},
982
- status: "ACTIVE"
983
- };
984
- }
985
- /** Get the current instance snapshot (immutable copy) */
986
- getSnapshot() {
987
- return { ...this.instance, state_data: { ...this.instance.state_data }, memory: { ...this.instance.memory } };
988
- }
989
- /** Get current state name */
990
- get currentState() {
991
- return this.instance.current_state;
992
- }
993
- /** Get current state_data */
994
- get stateData() {
995
- return this.instance.state_data;
996
- }
997
- /** Get current status */
998
- get status() {
999
- return this.instance.status;
1000
- }
1001
- /** Subscribe to state machine events */
1002
- on(listener) {
1003
- this.listeners.add(listener);
1004
- return () => this.listeners.delete(listener);
1005
- }
1006
- /** Register an action handler */
1007
- registerAction(type, handler) {
1008
- this.actionHandlers.set(type, handler);
1009
- }
1010
- /** Execute a named transition */
1011
- async transition(transitionName, data) {
1012
- if (this.instance.status !== "ACTIVE") {
1013
- return {
1014
- success: false,
1015
- from_state: this.instance.current_state,
1016
- to_state: this.instance.current_state,
1017
- actions_executed: [],
1018
- error: `Cannot transition: instance status is ${this.instance.status}`
1019
- };
1020
- }
1021
- const transition2 = this.instance.definition.transitions.find(
1022
- (t) => t.name === transitionName && t.from.includes(this.instance.current_state)
1023
- );
1024
- if (!transition2) {
1025
- return {
1026
- success: false,
1027
- from_state: this.instance.current_state,
1028
- to_state: this.instance.current_state,
1029
- actions_executed: [],
1030
- error: `Transition "${transitionName}" not valid from state "${this.instance.current_state}"`
1031
- };
1032
- }
1033
- if (data) {
1034
- this.instance.state_data = { ...this.instance.state_data, ...data };
1035
- }
1036
- if (transition2.conditions && transition2.conditions.length > 0) {
1037
- const ctx = this.buildContext();
1038
- for (const condition of transition2.conditions) {
1039
- const result2 = this.evaluator.evaluate(condition, ctx);
1040
- if (!result2.value) {
1041
- return {
1042
- success: false,
1043
- from_state: this.instance.current_state,
1044
- to_state: this.instance.current_state,
1045
- actions_executed: [],
1046
- error: `Transition condition not met: ${condition}`
1047
- };
1048
- }
1049
- }
1050
- }
1051
- const result = await this.executeTransition(transition2);
1052
- if (result.success) {
1053
- await this.drainAutoTransitions();
1054
- }
1055
- return result;
1056
- }
1057
- /** Update state_data directly (for on_event set_field actions) */
1058
- setField(field2, value) {
1059
- this.instance.state_data = { ...this.instance.state_data, [field2]: value };
1060
- }
1061
- /** Update memory */
1062
- setMemory(key, value) {
1063
- this.instance.memory = { ...this.instance.memory, [key]: value };
1064
- }
1065
- /** Get available transitions from the current state */
1066
- getAvailableTransitions() {
1067
- return this.instance.definition.transitions.filter(
1068
- (t) => t.from.includes(this.instance.current_state) && !t.auto
1069
- );
1070
- }
1071
- /** Get the current state definition */
1072
- getCurrentStateDefinition() {
1073
- return this.instance.definition.states.find((s) => s.name === this.instance.current_state);
1074
- }
1075
- // ===========================================================================
1076
- // Private implementation
1077
- // ===========================================================================
1078
- async executeTransition(transition2) {
1079
- const fromState = this.instance.current_state;
1080
- const allActionsExecuted = [];
1081
- const fromStateDef = this.getCurrentStateDefinition();
1082
- if (fromStateDef?.on_exit) {
1083
- await this.executeActions(fromStateDef.on_exit, allActionsExecuted);
1084
- }
1085
- this.emit({
1086
- type: "state_exit",
1087
- instance_id: this.instance.definition.id,
1088
- from_state: fromState
1089
- });
1090
- if (transition2.actions) {
1091
- await this.executeActions(transition2.actions, allActionsExecuted);
1092
- }
1093
- this.instance.current_state = transition2.to;
1094
- const toStateDef = this.instance.definition.states.find((s) => s.name === transition2.to);
1095
- if (toStateDef?.type === "END") {
1096
- this.instance.status = "COMPLETED";
1097
- } else if (toStateDef?.type === "CANCELLED") {
1098
- this.instance.status = "CANCELLED";
1099
- }
1100
- this.emit({
1101
- type: "state_enter",
1102
- instance_id: this.instance.definition.id,
1103
- to_state: transition2.to
1104
- });
1105
- if (toStateDef?.on_enter) {
1106
- await this.executeActions(toStateDef.on_enter, allActionsExecuted);
1107
- }
1108
- this.emit({
1109
- type: "transition",
1110
- instance_id: this.instance.definition.id,
1111
- from_state: fromState,
1112
- to_state: transition2.to
1113
- });
1114
- return {
1115
- success: true,
1116
- from_state: fromState,
1117
- to_state: transition2.to,
1118
- actions_executed: allActionsExecuted
1119
- };
1120
- }
1121
- async drainAutoTransitions() {
1122
- for (let depth = 0; depth < MAX_AUTO_CHAIN; depth++) {
1123
- if (this.instance.status !== "ACTIVE") break;
1124
- const autoTransition = this.findMatchingAutoTransition();
1125
- if (!autoTransition) break;
1126
- const result = await this.executeTransition(autoTransition);
1127
- if (!result.success) break;
1128
- }
1129
- }
1130
- findMatchingAutoTransition() {
1131
- const candidates = this.instance.definition.transitions.filter(
1132
- (t) => t.auto && t.from.includes(this.instance.current_state)
1133
- );
1134
- const ctx = this.buildContext();
1135
- for (const candidate of candidates) {
1136
- if (!candidate.conditions || candidate.conditions.length === 0) {
1137
- return candidate;
1138
- }
1139
- const allMet = candidate.conditions.every((condition) => {
1140
- const result = this.evaluator.evaluate(condition, ctx);
1141
- return result.value === true;
1142
- });
1143
- if (allMet) return candidate;
1144
- }
1145
- return null;
1146
- }
1147
- async executeActions(actions, collector) {
1148
- const ctx = this.buildContext();
1149
- for (const action2 of actions) {
1150
- if (action2.condition) {
1151
- const condResult = this.evaluator.evaluate(action2.condition, ctx);
1152
- if (!condResult.value) continue;
1153
- }
1154
- const handler = this.actionHandlers.get(action2.type);
1155
- if (handler) {
1156
- try {
1157
- await handler(action2, ctx);
1158
- collector.push(action2);
1159
- this.emit({
1160
- type: "action_executed",
1161
- instance_id: this.instance.definition.id,
1162
- action: action2
1163
- });
1164
- } catch (error) {
1165
- this.emit({
1166
- type: "error",
1167
- instance_id: this.instance.definition.id,
1168
- action: action2,
1169
- error: error instanceof Error ? error.message : String(error)
1170
- });
1171
- }
1172
- }
1173
- }
1174
- }
1175
- buildContext() {
1176
- return {
1177
- state_data: this.instance.state_data,
1178
- memory: this.instance.memory,
1179
- current_state: this.instance.current_state,
1180
- status: this.instance.status,
1181
- // Spread state_data for direct field access (e.g., "title" instead of "state_data.title")
1182
- ...this.instance.state_data
1183
- };
1184
- }
1185
- emit(event) {
1186
- for (const listener of this.listeners) {
1187
- try {
1188
- listener(event);
1189
- } catch {
1190
- }
1191
- }
1192
- }
1193
- };
1194
- var patternCache = /* @__PURE__ */ new Map();
1195
- var MAX_CACHE2 = 200;
1196
- function compilePattern(pattern) {
1197
- const cached = patternCache.get(pattern);
1198
- if (cached) return cached;
1199
- const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "<<DOUBLESTAR>>").replace(/\*/g, "[^:.]+").replace(/<<DOUBLESTAR>>/g, ".*");
1200
- const regex = new RegExp(`^${escaped}$`);
1201
- if (patternCache.size >= MAX_CACHE2) {
1202
- const firstKey = patternCache.keys().next().value;
1203
- if (firstKey) patternCache.delete(firstKey);
1204
- }
1205
- patternCache.set(pattern, regex);
1206
- return regex;
1207
- }
1208
- function matchTopic(pattern, topic) {
1209
- return pattern.test(topic);
1210
- }
1211
- var EventBus = class {
1212
- subscriptions = [];
1213
- /**
1214
- * Subscribe to events matching a glob pattern.
1215
- * Returns an unsubscribe function.
1216
- */
1217
- subscribe(pattern, handler) {
1218
- const regex = compilePattern(pattern);
1219
- const subscription = { pattern, regex, handler };
1220
- this.subscriptions.push(subscription);
1221
- return () => {
1222
- const idx = this.subscriptions.indexOf(subscription);
1223
- if (idx !== -1) this.subscriptions.splice(idx, 1);
1224
- };
1225
- }
1226
- /**
1227
- * Publish an event. All matching subscriptions fire (async).
1228
- * Errors in handlers are caught and logged, never propagated.
1229
- */
1230
- async publish(topic, payload = {}) {
1231
- const event = { topic, payload };
1232
- for (const sub of this.subscriptions) {
1233
- if (matchTopic(sub.regex, topic)) {
1234
- try {
1235
- await sub.handler(event);
1236
- } catch (error) {
1237
- console.warn(
1238
- `[player-core] Event handler error for pattern "${sub.pattern}" on topic "${topic}":`,
1239
- error
1240
- );
1241
- }
1242
- }
1243
- }
1244
- }
1245
- /**
1246
- * Publish synchronously (fire-and-forget).
1247
- * Useful when you don't need to await handler completion.
1248
- */
1249
- emit(topic, payload = {}) {
1250
- void this.publish(topic, payload);
1251
- }
1252
- /** Get count of active subscriptions */
1253
- get size() {
1254
- return this.subscriptions.length;
1255
- }
1256
- /** Remove all subscriptions */
1257
- clear() {
1258
- this.subscriptions.length = 0;
1259
- }
1260
- };
1261
- var ActionDispatcher = class {
1262
- handlers = /* @__PURE__ */ new Map();
1263
- /** Register a handler for an action type */
1264
- register(type, handler) {
1265
- this.handlers.set(type, handler);
1266
- }
1267
- /** Unregister a handler */
1268
- unregister(type) {
1269
- this.handlers.delete(type);
1270
- }
1271
- /** Check if a handler is registered for the given type */
1272
- has(type) {
1273
- return this.handlers.has(type);
1274
- }
1275
- /**
1276
- * Execute a list of actions sequentially.
1277
- * Each action's condition is evaluated first (if present).
1278
- * Missing handlers are skipped with a warning.
1279
- */
1280
- async execute(actions, context, evaluator) {
1281
- const results = [];
1282
- for (const action2 of actions) {
1283
- if (action2.condition && evaluator) {
1284
- const condResult = evaluator.evaluate(action2.condition, context);
1285
- if (!condResult.value) continue;
1286
- }
1287
- const handler = this.handlers.get(action2.type);
1288
- if (!handler) {
1289
- console.warn(`[player-core] No handler registered for action type "${action2.type}"`);
1290
- results.push({ type: action2.type, success: false, error: `No handler for "${action2.type}"` });
1291
- continue;
1292
- }
1293
- try {
1294
- await handler(action2.config, context);
1295
- results.push({ type: action2.type, success: true });
1296
- } catch (error) {
1297
- const message = error instanceof Error ? error.message : String(error);
1298
- console.warn(`[player-core] Action "${action2.type}" failed: ${message}`);
1299
- results.push({ type: action2.type, success: false, error: message });
1300
- }
1301
- }
1302
- return results;
1303
- }
1304
- /** Get count of registered handlers */
1305
- get size() {
1306
- return this.handlers.size;
1307
- }
1308
- /** Remove all handlers */
1309
- clear() {
1310
- this.handlers.clear();
1311
- }
1312
- };
1313
-
1314
286
  // src/core/WorkflowRuntime.ts
287
+ var import_player_core = require("@mmapp/player-core");
1315
288
  var WorkflowRuntime = class {
1316
289
  sm;
1317
290
  eventBus;
@@ -1319,9 +292,9 @@ var WorkflowRuntime = class {
1319
292
  evaluator;
1320
293
  listeners = /* @__PURE__ */ new Set();
1321
294
  constructor(config) {
1322
- this.evaluator = createEvaluator({
295
+ this.evaluator = (0, import_player_core.createEvaluator)({
1323
296
  functions: [],
1324
- failurePolicy: WEB_FAILURE_POLICIES.EVENT_REACTION
297
+ failurePolicy: import_player_core.WEB_FAILURE_POLICIES.EVENT_REACTION
1325
298
  });
1326
299
  const actionHandlers = /* @__PURE__ */ new Map();
1327
300
  if (config.actionHandlers) {
@@ -1343,14 +316,14 @@ var WorkflowRuntime = class {
1343
316
  smRef.setMemory(action2.config.key, action2.config.value);
1344
317
  }
1345
318
  });
1346
- this.sm = new StateMachine(
319
+ this.sm = new import_player_core.StateMachine(
1347
320
  config.definition,
1348
321
  config.initialData ?? {},
1349
322
  { evaluator: this.evaluator, actionHandlers }
1350
323
  );
1351
324
  smRef = this.sm;
1352
- this.eventBus = new EventBus();
1353
- this.dispatcher = new ActionDispatcher();
325
+ this.eventBus = new import_player_core.EventBus();
326
+ this.dispatcher = new import_player_core.ActionDispatcher();
1354
327
  this.dispatcher.register("set_field", (cfg) => {
1355
328
  if (smRef && typeof cfg.field === "string") {
1356
329
  smRef.setField(cfg.field, cfg.value);
@@ -1410,24 +383,24 @@ var import_react2 = require("react");
1410
383
  var import_react = require("react");
1411
384
  var RuntimeContext = (0, import_react.createContext)(null);
1412
385
  function useRuntimeContext() {
1413
- const runtime = (0, import_react.useContext)(RuntimeContext);
1414
- if (!runtime) {
386
+ const runtime2 = (0, import_react.useContext)(RuntimeContext);
387
+ if (!runtime2) {
1415
388
  throw new Error(
1416
389
  "useRuntimeContext must be used within a WorkflowProvider or RuntimeContext.Provider"
1417
390
  );
1418
391
  }
1419
- return runtime;
392
+ return runtime2;
1420
393
  }
1421
394
 
1422
395
  // src/hooks/useOnEnter.ts
1423
396
  function useOnEnter(stateName, effect) {
1424
- const runtime = useRuntimeContext();
397
+ const runtime2 = useRuntimeContext();
1425
398
  const effectRef = (0, import_react2.useRef)(effect);
1426
399
  effectRef.current = effect;
1427
400
  const cleanupRef = (0, import_react2.useRef)(null);
1428
401
  const states = Array.isArray(stateName) ? stateName : [stateName];
1429
402
  (0, import_react2.useEffect)(() => {
1430
- if (states.includes(runtime.sm.currentState)) {
403
+ if (states.includes(runtime2.sm.currentState)) {
1431
404
  const result = effectRef.current();
1432
405
  if (result instanceof Promise) {
1433
406
  result.then((cleanup) => {
@@ -1437,7 +410,7 @@ function useOnEnter(stateName, effect) {
1437
410
  cleanupRef.current = result;
1438
411
  }
1439
412
  }
1440
- const unsub = runtime.sm.on((event) => {
413
+ const unsub = runtime2.sm.on((event) => {
1441
414
  if (event.type === "state_enter" && event.to_state && states.includes(event.to_state)) {
1442
415
  cleanupRef.current?.();
1443
416
  const result = effectRef.current();
@@ -1458,34 +431,34 @@ function useOnEnter(stateName, effect) {
1458
431
  unsub();
1459
432
  cleanupRef.current?.();
1460
433
  };
1461
- }, [runtime, ...states]);
434
+ }, [runtime2, ...states]);
1462
435
  }
1463
436
 
1464
437
  // src/hooks/useOnExit.ts
1465
438
  var import_react3 = require("react");
1466
439
  function useOnExit(stateName, effect) {
1467
- const runtime = useRuntimeContext();
440
+ const runtime2 = useRuntimeContext();
1468
441
  const effectRef = (0, import_react3.useRef)(effect);
1469
442
  effectRef.current = effect;
1470
443
  const states = Array.isArray(stateName) ? stateName : [stateName];
1471
444
  (0, import_react3.useEffect)(() => {
1472
- const unsub = runtime.sm.on((event) => {
445
+ const unsub = runtime2.sm.on((event) => {
1473
446
  if (event.type === "state_exit" && event.from_state && states.includes(event.from_state)) {
1474
447
  effectRef.current();
1475
448
  }
1476
449
  });
1477
450
  return unsub;
1478
- }, [runtime, ...states]);
451
+ }, [runtime2, ...states]);
1479
452
  }
1480
453
 
1481
454
  // src/hooks/useOnTransition.ts
1482
455
  var import_react4 = require("react");
1483
456
  function useOnTransition(effect) {
1484
- const runtime = useRuntimeContext();
457
+ const runtime2 = useRuntimeContext();
1485
458
  const effectRef = (0, import_react4.useRef)(effect);
1486
459
  effectRef.current = effect;
1487
460
  (0, import_react4.useEffect)(() => {
1488
- const unsub = runtime.sm.on((event) => {
461
+ const unsub = runtime2.sm.on((event) => {
1489
462
  if (event.type === "transition") {
1490
463
  effectRef.current({
1491
464
  from: event.from_state,
@@ -1494,33 +467,33 @@ function useOnTransition(effect) {
1494
467
  }
1495
468
  });
1496
469
  return unsub;
1497
- }, [runtime]);
470
+ }, [runtime2]);
1498
471
  }
1499
472
 
1500
473
  // src/hooks/useOnEvent.ts
1501
474
  var import_react5 = require("react");
1502
475
  function useOnEvent(pattern, handler, options) {
1503
- const runtime = useRuntimeContext();
476
+ const runtime2 = useRuntimeContext();
1504
477
  const handlerRef = (0, import_react5.useRef)(handler);
1505
478
  handlerRef.current = handler;
1506
479
  (0, import_react5.useEffect)(() => {
1507
- const unsub = runtime.eventBus.subscribe(pattern, (event) => {
1508
- if (options?.while && runtime.sm.currentState !== options.while) return;
480
+ const unsub = runtime2.eventBus.subscribe(pattern, (event) => {
481
+ if (options?.while && runtime2.sm.currentState !== options.while) return;
1509
482
  handlerRef.current(event);
1510
483
  });
1511
484
  return unsub;
1512
- }, [runtime, pattern, options?.while]);
485
+ }, [runtime2, pattern, options?.while]);
1513
486
  }
1514
487
 
1515
488
  // src/hooks/useOnChange.ts
1516
489
  var import_react6 = require("react");
1517
490
  function useOnChange(field2, handler) {
1518
- const runtime = useRuntimeContext();
491
+ const runtime2 = useRuntimeContext();
1519
492
  const handlerRef = (0, import_react6.useRef)(handler);
1520
493
  handlerRef.current = handler;
1521
- const prevRef = (0, import_react6.useRef)(runtime.sm.stateData[field2]);
494
+ const prevRef = (0, import_react6.useRef)(runtime2.sm.stateData[field2]);
1522
495
  (0, import_react6.useEffect)(() => {
1523
- const unsub = runtime.subscribe((snap) => {
496
+ const unsub = runtime2.subscribe((snap) => {
1524
497
  const newVal = snap.stateData[field2];
1525
498
  if (newVal !== prevRef.current) {
1526
499
  handlerRef.current(newVal, prevRef.current);
@@ -1528,13 +501,13 @@ function useOnChange(field2, handler) {
1528
501
  }
1529
502
  });
1530
503
  return unsub;
1531
- }, [runtime, field2]);
504
+ }, [runtime2, field2]);
1532
505
  }
1533
506
 
1534
507
  // src/hooks/useWhileIn.ts
1535
508
  var import_react7 = require("react");
1536
509
  function useWhileIn(stateName, intervalMs, effect) {
1537
- const runtime = useRuntimeContext();
510
+ const runtime2 = useRuntimeContext();
1538
511
  const effectRef = (0, import_react7.useRef)(effect);
1539
512
  effectRef.current = effect;
1540
513
  (0, import_react7.useEffect)(() => {
@@ -1549,8 +522,8 @@ function useWhileIn(stateName, intervalMs, effect) {
1549
522
  timer = null;
1550
523
  }
1551
524
  }
1552
- if (runtime.sm.currentState === stateName) startInterval();
1553
- const unsub = runtime.sm.on((event) => {
525
+ if (runtime2.sm.currentState === stateName) startInterval();
526
+ const unsub = runtime2.sm.on((event) => {
1554
527
  if (event.type === "state_enter" && event.to_state === stateName) startInterval();
1555
528
  if (event.type === "state_exit" && event.from_state === stateName) stopInterval();
1556
529
  });
@@ -1558,13 +531,13 @@ function useWhileIn(stateName, intervalMs, effect) {
1558
531
  unsub();
1559
532
  stopInterval();
1560
533
  };
1561
- }, [runtime, stateName, intervalMs]);
534
+ }, [runtime2, stateName, intervalMs]);
1562
535
  }
1563
536
 
1564
537
  // src/hooks/useDuringAction.ts
1565
538
  var import_react8 = require("react");
1566
539
  function useDuringAction(config) {
1567
- const runtime = useRuntimeContext();
540
+ const runtime2 = useRuntimeContext();
1568
541
  const actionRef = (0, import_react8.useRef)(config.action);
1569
542
  actionRef.current = config.action;
1570
543
  const states = Array.isArray(config.state) ? config.state : [config.state];
@@ -1602,10 +575,10 @@ function useDuringAction(config) {
1602
575
  timer = null;
1603
576
  }
1604
577
  }
1605
- if (states.includes(runtime.sm.currentState)) {
578
+ if (states.includes(runtime2.sm.currentState)) {
1606
579
  startAction();
1607
580
  }
1608
- const unsub = runtime.sm.on((event) => {
581
+ const unsub = runtime2.sm.on((event) => {
1609
582
  if (event.type === "state_enter" && event.to_state && states.includes(event.to_state)) {
1610
583
  startAction();
1611
584
  }
@@ -1617,7 +590,7 @@ function useDuringAction(config) {
1617
590
  unsub();
1618
591
  stopAction();
1619
592
  };
1620
- }, [runtime, intervalMs, immediate, enabled, ...states]);
593
+ }, [runtime2, intervalMs, immediate, enabled, ...states]);
1621
594
  }
1622
595
 
1623
596
  // src/hooks/useQuery.ts
@@ -2110,29 +1083,29 @@ function useServerState(instanceId, options = {}) {
2110
1083
  // src/hooks/useWorkflow.ts
2111
1084
  var import_react15 = require("react");
2112
1085
  function useWorkflow(definition, options) {
2113
- const runtime = (0, import_react15.useMemo)(() => new WorkflowRuntime({
1086
+ const runtime2 = (0, import_react15.useMemo)(() => new WorkflowRuntime({
2114
1087
  definition,
2115
1088
  initialData: options?.initialData,
2116
1089
  actionHandlers: options?.actionHandlers
2117
1090
  }), [definition.id]);
2118
- const [snapshot, setSnapshot] = (0, import_react15.useState)(() => runtime.getSnapshot());
1091
+ const [snapshot, setSnapshot] = (0, import_react15.useState)(() => runtime2.getSnapshot());
2119
1092
  (0, import_react15.useEffect)(() => {
2120
- const unsub = runtime.subscribe(setSnapshot);
1093
+ const unsub = runtime2.subscribe(setSnapshot);
2121
1094
  return unsub;
2122
- }, [runtime]);
1095
+ }, [runtime2]);
2123
1096
  const transition2 = (0, import_react15.useCallback)(async (name, data) => {
2124
- const result = await runtime.transition(name, data);
1097
+ const result = await runtime2.transition(name, data);
2125
1098
  options?.onTransition?.(result);
2126
1099
  return result;
2127
- }, [runtime, options?.onTransition]);
1100
+ }, [runtime2, options?.onTransition]);
2128
1101
  const handle = {
2129
1102
  slug: definition.slug,
2130
1103
  ...snapshot,
2131
1104
  transition: transition2,
2132
- setField: runtime.setField.bind(runtime),
2133
- setMemory: runtime.setMemory.bind(runtime),
2134
- publishEvent: runtime.publishEvent.bind(runtime),
2135
- runtime
1105
+ setField: runtime2.setField.bind(runtime2),
1106
+ setMemory: runtime2.setMemory.bind(runtime2),
1107
+ publishEvent: runtime2.publishEvent.bind(runtime2),
1108
+ runtime: runtime2
2136
1109
  };
2137
1110
  return handle;
2138
1111
  }
@@ -2140,17 +1113,17 @@ function useWorkflow(definition, options) {
2140
1113
  // src/hooks/useTransition.ts
2141
1114
  var import_react16 = require("react");
2142
1115
  function useTransition(transitionName, _config) {
2143
- const runtime = useRuntimeContext();
1116
+ const runtime2 = useRuntimeContext();
2144
1117
  const [pending, setPending] = (0, import_react16.useState)(false);
2145
- const available = runtime.sm.getAvailableTransitions().some((t) => t.name === transitionName);
1118
+ const available = runtime2.sm.getAvailableTransitions().some((t) => t.name === transitionName);
2146
1119
  const fire = (0, import_react16.useCallback)(async (data) => {
2147
1120
  setPending(true);
2148
1121
  try {
2149
- return await runtime.transition(transitionName, data);
1122
+ return await runtime2.transition(transitionName, data);
2150
1123
  } finally {
2151
1124
  setPending(false);
2152
1125
  }
2153
- }, [runtime, transitionName]);
1126
+ }, [runtime2, transitionName]);
2154
1127
  const handle = { fire, available, pending };
2155
1128
  return handle;
2156
1129
  }
@@ -2162,12 +1135,12 @@ function setRoleHierarchy(hierarchy) {
2162
1135
  _globalHierarchy = hierarchy;
2163
1136
  }
2164
1137
  function useRole(roleName, options = {}) {
2165
- const runtime = useRuntimeContext();
1138
+ const runtime2 = useRuntimeContext();
2166
1139
  const hierarchy = options.hierarchy ?? _globalHierarchy ?? [];
2167
1140
  const inheritPermissions = options.inheritPermissions ?? true;
2168
1141
  const result = (0, import_react17.useMemo)(() => {
2169
- const snapshot = runtime.getSnapshot();
2170
- const definition = runtime.config?.definition;
1142
+ const snapshot = runtime2.getSnapshot();
1143
+ const definition = runtime2.config?.definition;
2171
1144
  const userRoles = snapshot.stateData?._userRoles ?? snapshot.stateData?.user_roles ?? [];
2172
1145
  let hasRole2 = userRoles.includes(roleName);
2173
1146
  if (!hasRole2 && hierarchy.length > 0) {
@@ -2215,7 +1188,7 @@ function useRole(roleName, options = {}) {
2215
1188
  }
2216
1189
  }
2217
1190
  return { hasRole: hasRole2, permissions, roles: userRoles, highestRole };
2218
- }, [runtime, roleName, hierarchy, inheritPermissions]);
1191
+ }, [runtime2, roleName, hierarchy, inheritPermissions]);
2219
1192
  const isAbove = (0, import_react17.useCallback)(
2220
1193
  (role) => {
2221
1194
  if (hierarchy.length === 0) return false;
@@ -2266,21 +1239,21 @@ function useRole(roleName, options = {}) {
2266
1239
  // src/hooks/useParams.ts
2267
1240
  var import_react18 = require("react");
2268
1241
  function useParams() {
2269
- const runtime = useRuntimeContext();
1242
+ const runtime2 = useRuntimeContext();
2270
1243
  return (0, import_react18.useMemo)(() => {
2271
- const snapshot = runtime.getSnapshot();
1244
+ const snapshot = runtime2.getSnapshot();
2272
1245
  const params = snapshot.stateData?._params ?? snapshot.memory?._callParams ?? {};
2273
1246
  return params;
2274
- }, [runtime]);
1247
+ }, [runtime2]);
2275
1248
  }
2276
1249
 
2277
1250
  // src/hooks/usePackage.ts
2278
1251
  var import_react19 = require("react");
2279
1252
  function usePackage(packageSlug) {
2280
- const runtime = useRuntimeContext();
1253
+ const runtime2 = useRuntimeContext();
2281
1254
  return (0, import_react19.useMemo)(() => {
2282
- const snapshot = runtime.getSnapshot();
2283
- const definition = runtime.config?.definition;
1255
+ const snapshot = runtime2.getSnapshot();
1256
+ const definition = runtime2.config?.definition;
2284
1257
  const childDefs = definition?.child_definitions ?? [];
2285
1258
  const metadata = definition?.metadata ?? {};
2286
1259
  if (definition?.slug === packageSlug && definition?.category === "blueprint") {
@@ -2343,7 +1316,7 @@ function usePackage(packageSlug) {
2343
1316
  isResolved: false,
2344
1317
  dependencySlugs: []
2345
1318
  };
2346
- }, [runtime, packageSlug]);
1319
+ }, [runtime2, packageSlug]);
2347
1320
  }
2348
1321
 
2349
1322
  // src/hooks/useRouter.ts
@@ -2469,16 +1442,16 @@ function useRouter(options = {}) {
2469
1442
  };
2470
1443
  setIsNavigating(true);
2471
1444
  try {
2472
- for (const guard of guardsRef.current) {
2473
- const allowed = await guard(to, location);
1445
+ for (const guard2 of guardsRef.current) {
1446
+ const allowed = await guard2(to, location);
2474
1447
  if (!allowed) {
2475
1448
  onRejectRef.current?.(to);
2476
1449
  return false;
2477
1450
  }
2478
1451
  }
2479
1452
  if (found?.route?.guards) {
2480
- for (const guard of found.route.guards) {
2481
- const allowed = await guard(to, location);
1453
+ for (const guard2 of found.route.guards) {
1454
+ const allowed = await guard2(to, location);
2482
1455
  if (!allowed) {
2483
1456
  if (found.route.redirectOnFail) {
2484
1457
  const fullRedirect = basePathRef.current + found.route.redirectOnFail;
@@ -2904,7 +1877,7 @@ function useGeolocation(options = {}) {
2904
1877
  const {
2905
1878
  enableHighAccuracy = false,
2906
1879
  maximumAge = 0,
2907
- timeout = 1e4,
1880
+ timeout: timeout2 = 1e4,
2908
1881
  watch = false,
2909
1882
  enabled = true
2910
1883
  } = options;
@@ -2915,8 +1888,8 @@ function useGeolocation(options = {}) {
2915
1888
  const watchIdRef = (0, import_react24.useRef)(null);
2916
1889
  const supported = typeof navigator !== "undefined" && "geolocation" in navigator;
2917
1890
  const positionOptions = (0, import_react24.useMemo)(
2918
- () => ({ enableHighAccuracy, maximumAge, timeout }),
2919
- [enableHighAccuracy, maximumAge, timeout]
1891
+ () => ({ enableHighAccuracy, maximumAge, timeout: timeout2 }),
1892
+ [enableHighAccuracy, maximumAge, timeout2]
2920
1893
  );
2921
1894
  const handleSuccess = (0, import_react24.useCallback)((pos) => {
2922
1895
  setPosition({
@@ -3276,7 +2249,7 @@ var import_react27 = require("react");
3276
2249
  function useForm(config) {
3277
2250
  const {
3278
2251
  initialValues,
3279
- validate,
2252
+ validate: validate2,
3280
2253
  fieldValidators,
3281
2254
  onSubmit,
3282
2255
  onError,
@@ -3289,8 +2262,8 @@ function useForm(config) {
3289
2262
  const [isSubmitting, setIsSubmitting] = (0, import_react27.useState)(false);
3290
2263
  const [submitCount, setSubmitCount] = (0, import_react27.useState)(0);
3291
2264
  const initialRef = (0, import_react27.useRef)(initialValues);
3292
- const validateRef = (0, import_react27.useRef)(validate);
3293
- validateRef.current = validate;
2265
+ const validateRef = (0, import_react27.useRef)(validate2);
2266
+ validateRef.current = validate2;
3294
2267
  const fieldValidatorsRef = (0, import_react27.useRef)(fieldValidators);
3295
2268
  fieldValidatorsRef.current = fieldValidators;
3296
2269
  const onSubmitRef = (0, import_react27.useRef)(onSubmit);
@@ -3507,7 +2480,7 @@ function useNotification() {
3507
2480
  setPermission(result);
3508
2481
  return result;
3509
2482
  }, [supported]);
3510
- const notify2 = (0, import_react28.useCallback)(
2483
+ const notify3 = (0, import_react28.useCallback)(
3511
2484
  (title, options = {}) => {
3512
2485
  if (!supported || permission !== "granted") return null;
3513
2486
  const {
@@ -3540,8 +2513,8 @@ function useNotification() {
3540
2513
  [supported, permission]
3541
2514
  );
3542
2515
  return (0, import_react28.useMemo)(
3543
- () => ({ permission, supported, requestPermission, notify: notify2 }),
3544
- [permission, supported, requestPermission, notify2]
2516
+ () => ({ permission, supported, requestPermission, notify: notify3 }),
2517
+ [permission, supported, requestPermission, notify3]
3545
2518
  );
3546
2519
  }
3547
2520
 
@@ -3558,12 +2531,12 @@ function notifyListeners() {
3558
2531
  }
3559
2532
  function addToast(config) {
3560
2533
  const id = `toast-${++_nextId}`;
3561
- const instance = {
2534
+ const instance2 = {
3562
2535
  ...config,
3563
2536
  id,
3564
2537
  createdAt: Date.now()
3565
2538
  };
3566
- _toasts = [..._toasts, instance];
2539
+ _toasts = [..._toasts, instance2];
3567
2540
  const duration = config.duration ?? 5e3;
3568
2541
  if (duration > 0) {
3569
2542
  const timer = setTimeout(() => {
@@ -3614,8 +2587,191 @@ function useToast() {
3614
2587
  );
3615
2588
  }
3616
2589
 
3617
- // src/hooks/useMiddleware.ts
2590
+ // src/hooks/useVisibility.ts
3618
2591
  var import_react30 = require("react");
2592
+ function useVisibility(model2, role, playerType) {
2593
+ return (0, import_react30.useMemo)(() => {
2594
+ return computeVisibility(model2, role, playerType);
2595
+ }, [model2, role, playerType]);
2596
+ }
2597
+ function computeVisibility(model2, role, playerType) {
2598
+ const allFields = Object.keys(model2.fields || {});
2599
+ const allStates = Object.keys(model2.states || {});
2600
+ const vis = model2.orchestration?.visibility;
2601
+ if (!vis) {
2602
+ return makeResult(allFields, allStates);
2603
+ }
2604
+ let roleFields;
2605
+ let roleStates;
2606
+ let playerFields;
2607
+ if (role && vis.roles && vis.roles[role]) {
2608
+ const rv = vis.roles[role];
2609
+ roleFields = rv.fields === "*" ? "*" : [...rv.fields];
2610
+ roleStates = rv.states === "*" ? "*" : rv.states ? [...rv.states] : "*";
2611
+ }
2612
+ if (playerType && vis.players && vis.players[playerType]) {
2613
+ const pv = vis.players[playerType];
2614
+ playerFields = pv.fields === "*" ? "*" : [...pv.fields];
2615
+ }
2616
+ if (roleFields === void 0 && playerFields === void 0) {
2617
+ return makeResult(allFields, allStates);
2618
+ }
2619
+ let resolvedFields;
2620
+ if (roleFields === "*" && playerFields === "*") {
2621
+ resolvedFields = allFields;
2622
+ } else if (roleFields === "*") {
2623
+ resolvedFields = playerFields === void 0 ? allFields : playerFields;
2624
+ } else if (playerFields === "*") {
2625
+ resolvedFields = roleFields === void 0 ? allFields : roleFields;
2626
+ } else if (roleFields !== void 0 && playerFields !== void 0) {
2627
+ const roleSet = new Set(roleFields);
2628
+ resolvedFields = playerFields.filter((f) => roleSet.has(f));
2629
+ } else {
2630
+ resolvedFields = roleFields || playerFields || allFields;
2631
+ }
2632
+ const resolvedStates = roleStates === "*" || roleStates === void 0 ? allStates : roleStates;
2633
+ return makeResult(resolvedFields, resolvedStates);
2634
+ }
2635
+ function makeResult(fields, states) {
2636
+ const fieldSet = new Set(fields);
2637
+ const stateSet = new Set(states);
2638
+ return {
2639
+ visibleFields: fields,
2640
+ visibleStates: states,
2641
+ canSeeField: (f) => fieldSet.has(f),
2642
+ canSeeState: (s) => stateSet.has(s)
2643
+ };
2644
+ }
2645
+
2646
+ // src/hooks/usePresence.ts
2647
+ var import_react31 = require("react");
2648
+ var PRESENCE_EVENTS = {
2649
+ JOIN: "presence:join",
2650
+ LEAVE: "presence:leave",
2651
+ HEARTBEAT: "presence:heartbeat",
2652
+ EDIT_START: "presence:edit_start",
2653
+ EDIT_STOP: "presence:edit_stop"
2654
+ };
2655
+ function usePresence(instanceId, options = {}) {
2656
+ const {
2657
+ userId = "anonymous",
2658
+ userName = "Anonymous",
2659
+ wsUrl,
2660
+ enabled = true,
2661
+ heartbeatInterval = 15e3,
2662
+ staleTimeout = 45e3
2663
+ } = options;
2664
+ const channelName = `presence:${instanceId}`;
2665
+ const { publish, subscribe, connected } = useChannel(channelName, {
2666
+ wsUrl,
2667
+ enabled
2668
+ });
2669
+ const [viewers, setViewers] = (0, import_react31.useState)([]);
2670
+ const [editors, setEditors] = (0, import_react31.useState)([]);
2671
+ const viewersRef = (0, import_react31.useRef)(/* @__PURE__ */ new Map());
2672
+ const editorsRef = (0, import_react31.useRef)(/* @__PURE__ */ new Map());
2673
+ (0, import_react31.useEffect)(() => {
2674
+ if (!connected || !enabled) return;
2675
+ publish(PRESENCE_EVENTS.JOIN, { id: userId, name: userName, connectedAt: Date.now() });
2676
+ const hb = setInterval(() => {
2677
+ publish(PRESENCE_EVENTS.HEARTBEAT, { id: userId, name: userName });
2678
+ }, heartbeatInterval);
2679
+ return () => {
2680
+ clearInterval(hb);
2681
+ publish(PRESENCE_EVENTS.LEAVE, { id: userId });
2682
+ };
2683
+ }, [connected, enabled, userId, userName, heartbeatInterval, publish]);
2684
+ (0, import_react31.useEffect)(() => {
2685
+ if (!enabled) return;
2686
+ const cleanup = setInterval(() => {
2687
+ const now = Date.now();
2688
+ const stale = [];
2689
+ for (const [id, v] of viewersRef.current) {
2690
+ if (now - v.connectedAt > staleTimeout) stale.push(id);
2691
+ }
2692
+ if (stale.length > 0) {
2693
+ for (const id of stale) {
2694
+ viewersRef.current.delete(id);
2695
+ editorsRef.current.delete(id);
2696
+ }
2697
+ setViewers(Array.from(viewersRef.current.values()));
2698
+ setEditors(Array.from(editorsRef.current.values()));
2699
+ }
2700
+ }, staleTimeout / 3);
2701
+ return () => clearInterval(cleanup);
2702
+ }, [enabled, staleTimeout]);
2703
+ (0, import_react31.useEffect)(() => {
2704
+ if (!enabled) return;
2705
+ const unsubs = [];
2706
+ unsubs.push(subscribe(PRESENCE_EVENTS.JOIN, (data) => {
2707
+ if (data.id === userId) return;
2708
+ viewersRef.current.set(data.id, {
2709
+ id: data.id,
2710
+ name: data.name || "Anonymous",
2711
+ connectedAt: data.connectedAt || Date.now()
2712
+ });
2713
+ setViewers(Array.from(viewersRef.current.values()));
2714
+ }));
2715
+ unsubs.push(subscribe(PRESENCE_EVENTS.LEAVE, (data) => {
2716
+ viewersRef.current.delete(data.id);
2717
+ editorsRef.current.delete(data.id);
2718
+ setViewers(Array.from(viewersRef.current.values()));
2719
+ setEditors(Array.from(editorsRef.current.values()));
2720
+ }));
2721
+ unsubs.push(subscribe(PRESENCE_EVENTS.HEARTBEAT, (data) => {
2722
+ if (data.id === userId) return;
2723
+ const existing = viewersRef.current.get(data.id);
2724
+ if (existing) {
2725
+ existing.connectedAt = Date.now();
2726
+ } else {
2727
+ viewersRef.current.set(data.id, {
2728
+ id: data.id,
2729
+ name: data.name || "Anonymous",
2730
+ connectedAt: Date.now()
2731
+ });
2732
+ setViewers(Array.from(viewersRef.current.values()));
2733
+ }
2734
+ }));
2735
+ unsubs.push(subscribe(PRESENCE_EVENTS.EDIT_START, (data) => {
2736
+ if (data.id === userId) return;
2737
+ editorsRef.current.set(data.id, {
2738
+ id: data.id,
2739
+ name: data.name || "Anonymous",
2740
+ field: data.field,
2741
+ startedAt: Date.now()
2742
+ });
2743
+ setEditors(Array.from(editorsRef.current.values()));
2744
+ }));
2745
+ unsubs.push(subscribe(PRESENCE_EVENTS.EDIT_STOP, (data) => {
2746
+ editorsRef.current.delete(data.id);
2747
+ setEditors(Array.from(editorsRef.current.values()));
2748
+ }));
2749
+ return () => unsubs.forEach((fn) => fn());
2750
+ }, [enabled, userId, subscribe]);
2751
+ const startEditing = (0, import_react31.useCallback)((field2) => {
2752
+ publish(PRESENCE_EVENTS.EDIT_START, { id: userId, name: userName, field: field2 });
2753
+ }, [publish, userId, userName]);
2754
+ const stopEditing = (0, import_react31.useCallback)((_field) => {
2755
+ publish(PRESENCE_EVENTS.EDIT_STOP, { id: userId });
2756
+ }, [publish, userId]);
2757
+ const isEditing = (0, import_react31.useCallback)((field2) => {
2758
+ for (const editor of editorsRef.current.values()) {
2759
+ if (editor.field === field2 && editor.id !== userId) return true;
2760
+ }
2761
+ return false;
2762
+ }, [userId]);
2763
+ return {
2764
+ viewers,
2765
+ editors,
2766
+ viewerCount: viewers.length,
2767
+ isEditing,
2768
+ startEditing,
2769
+ stopEditing
2770
+ };
2771
+ }
2772
+
2773
+ // src/hooks/useMiddleware.ts
2774
+ var import_react32 = require("react");
3619
2775
  function requireAuth(loginPath = "/login") {
3620
2776
  return (ctx) => {
3621
2777
  if (!ctx.token) {
@@ -3687,24 +2843,24 @@ function useMiddleware(middlewares, options = {}) {
3687
2843
  watchPathname = true,
3688
2844
  onRedirect
3689
2845
  } = options;
3690
- const [ready, setReady] = (0, import_react30.useState)(false);
3691
- const [loading, setLoading] = (0, import_react30.useState)(true);
3692
- const [redirect, setRedirect] = (0, import_react30.useState)(null);
3693
- const [error, setError] = (0, import_react30.useState)(null);
3694
- const [data, setData] = (0, import_react30.useState)({});
3695
- const [runKey, setRunKey] = (0, import_react30.useState)(0);
3696
- const middlewaresRef = (0, import_react30.useRef)(middlewares);
2846
+ const [ready, setReady] = (0, import_react32.useState)(false);
2847
+ const [loading, setLoading] = (0, import_react32.useState)(true);
2848
+ const [redirect, setRedirect] = (0, import_react32.useState)(null);
2849
+ const [error, setError] = (0, import_react32.useState)(null);
2850
+ const [data, setData] = (0, import_react32.useState)({});
2851
+ const [runKey, setRunKey] = (0, import_react32.useState)(0);
2852
+ const middlewaresRef = (0, import_react32.useRef)(middlewares);
3697
2853
  middlewaresRef.current = middlewares;
3698
- const onRedirectRef = (0, import_react30.useRef)(onRedirect);
2854
+ const onRedirectRef = (0, import_react32.useRef)(onRedirect);
3699
2855
  onRedirectRef.current = onRedirect;
3700
- const [pathname, setPathname] = (0, import_react30.useState)(getPathname);
3701
- (0, import_react30.useEffect)(() => {
2856
+ const [pathname, setPathname] = (0, import_react32.useState)(getPathname);
2857
+ (0, import_react32.useEffect)(() => {
3702
2858
  if (!watchPathname) return;
3703
2859
  const handler = () => setPathname(getPathname());
3704
2860
  window.addEventListener("popstate", handler);
3705
2861
  return () => window.removeEventListener("popstate", handler);
3706
2862
  }, [watchPathname]);
3707
- (0, import_react30.useEffect)(() => {
2863
+ (0, import_react32.useEffect)(() => {
3708
2864
  if (!enabled) {
3709
2865
  setReady(true);
3710
2866
  setLoading(false);
@@ -3751,11 +2907,11 @@ function useMiddleware(middlewares, options = {}) {
3751
2907
  cancelled = true;
3752
2908
  };
3753
2909
  }, [enabled, pathname, runKey]);
3754
- const rerun = (0, import_react30.useMemo)(
2910
+ const rerun = (0, import_react32.useMemo)(
3755
2911
  () => () => setRunKey((k) => k + 1),
3756
2912
  []
3757
2913
  );
3758
- return (0, import_react30.useMemo)(
2914
+ return (0, import_react32.useMemo)(
3759
2915
  () => ({ ready, loading, redirect, error, data, rerun }),
3760
2916
  [ready, loading, redirect, error, data, rerun]
3761
2917
  );
@@ -3765,8 +2921,8 @@ function useMiddleware(middlewares, options = {}) {
3765
2921
  var import_react_query = require("@tanstack/react-query");
3766
2922
  var import_jsx_runtime = require("react/jsx-runtime");
3767
2923
  var defaultQueryClient = new import_react_query.QueryClient();
3768
- function WorkflowProvider({ runtime, queryClient, children }) {
3769
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_query.QueryClientProvider, { client: queryClient ?? defaultQueryClient, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RuntimeContext.Provider, { value: runtime, children }) });
2924
+ function WorkflowProvider({ runtime: runtime2, queryClient, children }) {
2925
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_query.QueryClientProvider, { client: queryClient ?? defaultQueryClient, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RuntimeContext.Provider, { value: runtime2, children }) });
3770
2926
  }
3771
2927
 
3772
2928
  // src/local/LocalEngine.ts
@@ -3827,8 +2983,8 @@ var LocalWorkflowEngine = class {
3827
2983
  * Process all pending events from a transition result.
3828
2984
  * Emits locally and returns the events for P2P broadcast.
3829
2985
  */
3830
- processPendingEvents(instance) {
3831
- const events = instance._pendingEvents;
2986
+ processPendingEvents(instance2) {
2987
+ const events = instance2._pendingEvents;
3832
2988
  if (!events?.length) return [];
3833
2989
  for (const evt of events) {
3834
2990
  this.emitEvent(evt);
@@ -3871,18 +3027,18 @@ var LocalWorkflowEngine = class {
3871
3027
  };
3872
3028
  }
3873
3029
  /** Check if a transition can fire from the instance's current state */
3874
- canTransition(instance, transitionName) {
3875
- const def = this.definitions.get(instance.definitionSlug);
3030
+ canTransition(instance2, transitionName) {
3031
+ const def = this.definitions.get(instance2.definitionSlug);
3876
3032
  if (!def) return false;
3877
3033
  const transition2 = def.transitions.find((t) => t.name === transitionName);
3878
3034
  if (!transition2) return false;
3879
- return transition2.from.includes(instance.currentState);
3035
+ return transition2.from.includes(instance2.currentState);
3880
3036
  }
3881
3037
  /** Get all transitions available from the instance's current state */
3882
- getAvailableTransitions(instance) {
3883
- const def = this.definitions.get(instance.definitionSlug);
3038
+ getAvailableTransitions(instance2) {
3039
+ const def = this.definitions.get(instance2.definitionSlug);
3884
3040
  if (!def) return [];
3885
- return def.transitions.filter((t) => t.from.includes(instance.currentState)).map((t) => t.name);
3041
+ return def.transitions.filter((t) => t.from.includes(instance2.currentState)).map((t) => t.name);
3886
3042
  }
3887
3043
  /**
3888
3044
  * Apply a transition, returning a new WorkflowInstance (immutable).
@@ -3893,29 +3049,29 @@ var LocalWorkflowEngine = class {
3893
3049
  * @returns New WorkflowInstance with updated state and version
3894
3050
  * @throws If transition is not valid from current state
3895
3051
  */
3896
- applyTransition(instance, transitionName, data) {
3897
- const def = this.definitions.get(instance.definitionSlug);
3052
+ applyTransition(instance2, transitionName, data) {
3053
+ const def = this.definitions.get(instance2.definitionSlug);
3898
3054
  if (!def) {
3899
- throw new Error(`Definition not found: ${instance.definitionSlug}`);
3055
+ throw new Error(`Definition not found: ${instance2.definitionSlug}`);
3900
3056
  }
3901
3057
  const transition2 = def.transitions.find((t) => t.name === transitionName);
3902
3058
  if (!transition2) {
3903
3059
  throw new Error(
3904
- `Transition "${transitionName}" not found in ${instance.definitionSlug}`
3060
+ `Transition "${transitionName}" not found in ${instance2.definitionSlug}`
3905
3061
  );
3906
3062
  }
3907
- if (!transition2.from.includes(instance.currentState)) {
3063
+ if (!transition2.from.includes(instance2.currentState)) {
3908
3064
  throw new Error(
3909
- `Transition "${transitionName}" cannot fire from state "${instance.currentState}" (allowed from: ${transition2.from.join(", ")})`
3065
+ `Transition "${transitionName}" cannot fire from state "${instance2.currentState}" (allowed from: ${transition2.from.join(", ")})`
3910
3066
  );
3911
3067
  }
3912
- const nextState = transition2.to ?? instance.currentState;
3913
- const fields = data ? { ...instance.fields, ...data } : { ...instance.fields };
3068
+ const nextState = transition2.to ?? instance2.currentState;
3069
+ const fields = data ? { ...instance2.fields, ...data } : { ...instance2.fields };
3914
3070
  let result = {
3915
- ...instance,
3071
+ ...instance2,
3916
3072
  currentState: nextState,
3917
3073
  fields,
3918
- version: instance.version + 1,
3074
+ version: instance2.version + 1,
3919
3075
  updatedAt: Date.now()
3920
3076
  };
3921
3077
  const targetStateDef = def.states.find((s) => s.name === nextState);
@@ -3988,23 +3144,23 @@ var LocalWorkflowEngine = class {
3988
3144
  * Apply a transition only if the incoming version is newer.
3989
3145
  * Used for P2P sync — skips stale transitions.
3990
3146
  */
3991
- applyRemoteTransition(instance, transitionName, data, remoteVersion) {
3992
- if (remoteVersion <= instance.version) {
3147
+ applyRemoteTransition(instance2, transitionName, data, remoteVersion) {
3148
+ if (remoteVersion <= instance2.version) {
3993
3149
  return null;
3994
3150
  }
3995
- if (!this.canTransition(instance, transitionName)) {
3151
+ if (!this.canTransition(instance2, transitionName)) {
3996
3152
  return null;
3997
3153
  }
3998
- const updated = this.applyTransition(instance, transitionName, data);
3154
+ const updated = this.applyTransition(instance2, transitionName, data);
3999
3155
  return { ...updated, version: remoteVersion };
4000
3156
  }
4001
3157
  };
4002
3158
 
4003
3159
  // src/local/LocalEngineContext.ts
4004
- var import_react31 = require("react");
4005
- var LocalEngineContext = (0, import_react31.createContext)(null);
3160
+ var import_react33 = require("react");
3161
+ var LocalEngineContext = (0, import_react33.createContext)(null);
4006
3162
  function useLocalEngine() {
4007
- return (0, import_react31.useContext)(LocalEngineContext);
3163
+ return (0, import_react33.useContext)(LocalEngineContext);
4008
3164
  }
4009
3165
  var LocalEngineProvider = LocalEngineContext.Provider;
4010
3166
 
@@ -4261,6 +3417,155 @@ function defineModel(def) {
4261
3417
  return def;
4262
3418
  }
4263
3419
 
3420
+ // src/config/orchestration-presets.ts
3421
+ var SOLO = {
3422
+ strategy: "solo",
3423
+ evaluation: { pure: "local" },
3424
+ scheduling: { coordinator: "any" },
3425
+ events: { evaluator: "any-subscriber" },
3426
+ errorHandling: { strategy: "manual" },
3427
+ conflicts: { default: "last-writer-wins", fields: {} },
3428
+ visibility: { roles: {}, players: {} },
3429
+ presence: { enabled: false, showEditing: false, showViewing: false },
3430
+ services: {},
3431
+ actionRouting: {}
3432
+ };
3433
+ var CLIENT_SERVER = {
3434
+ strategy: "client-server",
3435
+ evaluation: { pure: "local" },
3436
+ scheduling: { coordinator: "server" },
3437
+ events: { evaluator: "server" },
3438
+ errorHandling: { strategy: "rollback" },
3439
+ conflicts: { default: "last-writer-wins", fields: {} },
3440
+ visibility: { roles: {}, players: {} },
3441
+ presence: { enabled: false, showEditing: false, showViewing: false },
3442
+ services: {},
3443
+ actionRouting: {}
3444
+ };
3445
+ var MULTI_CLIENT = {
3446
+ strategy: "multi-client",
3447
+ evaluation: { pure: "local" },
3448
+ scheduling: { coordinator: "server" },
3449
+ events: { evaluator: "server" },
3450
+ errorHandling: { strategy: "compensate" },
3451
+ conflicts: { default: "last-writer-wins", fields: {} },
3452
+ visibility: { roles: {}, players: {} },
3453
+ presence: { enabled: true, showEditing: true, showViewing: true, conflictHighlight: true },
3454
+ services: {},
3455
+ actionRouting: {}
3456
+ };
3457
+ var SERVICE_MESH = {
3458
+ strategy: "service-mesh",
3459
+ evaluation: { pure: "local" },
3460
+ scheduling: { coordinator: "server" },
3461
+ events: { evaluator: "all" },
3462
+ errorHandling: { strategy: "saga" },
3463
+ conflicts: { default: "first-write-wins", fields: {} },
3464
+ visibility: { roles: {}, players: {} },
3465
+ presence: { enabled: false, showEditing: false, showViewing: false },
3466
+ services: {},
3467
+ actionRouting: {}
3468
+ };
3469
+ var PEER_TO_PEER = {
3470
+ strategy: "peer-to-peer",
3471
+ evaluation: { pure: "local" },
3472
+ scheduling: { coordinator: "any" },
3473
+ events: { evaluator: "any-subscriber" },
3474
+ errorHandling: { strategy: "compensate" },
3475
+ conflicts: { default: "crdt", fields: {} },
3476
+ visibility: { roles: {}, players: {} },
3477
+ presence: { enabled: true, showEditing: true, showViewing: true, conflictHighlight: false },
3478
+ services: {},
3479
+ actionRouting: {}
3480
+ };
3481
+ var HYBRID = {
3482
+ strategy: "hybrid",
3483
+ evaluation: { pure: "local" },
3484
+ scheduling: { coordinator: "server" },
3485
+ events: { evaluator: "server" },
3486
+ errorHandling: { strategy: "saga" },
3487
+ conflicts: { default: "last-writer-wins", fields: {} },
3488
+ visibility: { roles: {}, players: {} },
3489
+ presence: { enabled: true, showEditing: true, showViewing: false, conflictHighlight: false },
3490
+ services: {},
3491
+ actionRouting: {}
3492
+ };
3493
+ var HEADLESS = {
3494
+ strategy: "headless",
3495
+ evaluation: { pure: "local" },
3496
+ // expression engine runs server-local (native Rust, fastest)
3497
+ scheduling: { coordinator: "server" },
3498
+ // server manages cron/interval/timeout
3499
+ events: { evaluator: "server" },
3500
+ // server matches events, no clients involved
3501
+ errorHandling: { strategy: "compensate" },
3502
+ conflicts: { default: "first-write-wins", fields: {} },
3503
+ // no concurrent clients
3504
+ visibility: { roles: {}, players: {} },
3505
+ presence: { enabled: false, showEditing: false, showViewing: false, conflictHighlight: false },
3506
+ services: {},
3507
+ actionRouting: {}
3508
+ };
3509
+ var ORCHESTRATION_PRESETS = {
3510
+ "solo": SOLO,
3511
+ "client-server": CLIENT_SERVER,
3512
+ "multi-client": MULTI_CLIENT,
3513
+ "service-mesh": SERVICE_MESH,
3514
+ "peer-to-peer": PEER_TO_PEER,
3515
+ "hybrid": HYBRID,
3516
+ "headless": HEADLESS,
3517
+ "custom": CLIENT_SERVER
3518
+ // custom uses client-server as base
3519
+ };
3520
+ var DEFAULT_RESOLVED = {
3521
+ strategy: "client-server",
3522
+ evaluation: { pure: "local" },
3523
+ scheduling: { coordinator: "server" },
3524
+ events: { evaluator: "server" },
3525
+ errorHandling: { strategy: "rollback" },
3526
+ conflicts: { default: "last-writer-wins", fields: {} },
3527
+ visibility: { roles: {}, players: {} },
3528
+ presence: { enabled: false, showEditing: false, showViewing: false, conflictHighlight: false },
3529
+ services: {},
3530
+ actionRouting: {}
3531
+ };
3532
+ function resolveOrchestration(config) {
3533
+ if (!config) return { ...DEFAULT_RESOLVED };
3534
+ const strategy = config.strategy || "client-server";
3535
+ const preset = ORCHESTRATION_PRESETS[strategy] || CLIENT_SERVER;
3536
+ return {
3537
+ strategy,
3538
+ evaluation: {
3539
+ pure: config.evaluation?.pure ?? preset.evaluation?.pure ?? "local"
3540
+ },
3541
+ scheduling: {
3542
+ coordinator: config.scheduling?.coordinator ?? preset.scheduling?.coordinator ?? "server"
3543
+ },
3544
+ events: {
3545
+ evaluator: config.events?.evaluator ?? preset.events?.evaluator ?? "server"
3546
+ },
3547
+ errorHandling: {
3548
+ strategy: config.errorHandling?.strategy ?? preset.errorHandling?.strategy ?? "rollback"
3549
+ },
3550
+ conflicts: {
3551
+ default: config.conflicts?.default ?? preset.conflicts?.default ?? "last-writer-wins",
3552
+ fields: { ...preset.conflicts?.fields || {}, ...config.conflicts?.fields || {} }
3553
+ },
3554
+ visibility: {
3555
+ roles: { ...preset.visibility?.roles || {}, ...config.visibility?.roles || {} },
3556
+ players: { ...preset.visibility?.players || {}, ...config.visibility?.players || {} }
3557
+ },
3558
+ presence: {
3559
+ enabled: config.presence?.enabled ?? preset.presence?.enabled ?? false,
3560
+ showEditing: config.presence?.showEditing ?? preset.presence?.showEditing ?? false,
3561
+ showViewing: config.presence?.showViewing ?? preset.presence?.showViewing ?? false,
3562
+ conflictHighlight: config.presence?.conflictHighlight ?? preset.presence?.conflictHighlight ?? false
3563
+ },
3564
+ services: { ...preset.services || {}, ...config.services || {} },
3565
+ actionRouting: { ...preset.actionRouting || {}, ...config.actionRouting || {} }
3566
+ };
3567
+ }
3568
+
4264
3569
  // src/config/defineBlueprint.ts
4265
3570
  function defineBlueprint(config) {
4266
3571
  if (!config.slug) {
@@ -4374,13 +3679,13 @@ function inState(state2) {
4374
3679
  function notInState(state2) {
4375
3680
  return { type: "expression", expression: `current_state != "${state2}"` };
4376
3681
  }
4377
- function and2(...conditions) {
3682
+ function and(...conditions) {
4378
3683
  return { AND: conditions.map(normalize) };
4379
3684
  }
4380
- function or2(...conditions) {
3685
+ function or(...conditions) {
4381
3686
  return { OR: conditions.map(normalize) };
4382
3687
  }
4383
- function not2(condition) {
3688
+ function not(condition) {
4384
3689
  const c = normalize(condition);
4385
3690
  if (c.type === "expression" && c.expression) {
4386
3691
  return { type: "expression", expression: `NOT(${c.expression})` };
@@ -4425,7 +3730,7 @@ function refHasAnyRole(slug, lookupField, lookupValue, roles) {
4425
3730
  }
4426
3731
 
4427
3732
  // src/hooks/useModel.ts
4428
- var import_react32 = require("react");
3733
+ var import_react34 = require("react");
4429
3734
  function getDefaultFields(definition) {
4430
3735
  const defaults = {};
4431
3736
  for (const [key, field2] of Object.entries(definition.fields)) {
@@ -4480,18 +3785,18 @@ function useModel(definition, options = {}) {
4480
3785
  if (options.state) queryParams.state = options.state;
4481
3786
  const query = useQuery(slug, queryParams);
4482
3787
  const mutation = useMutation(slug);
4483
- const instance = query.data?.[0];
4484
- const instanceId = instance?.id ?? null;
4485
- const currentState = instance?.currentState ?? "";
4486
- const instanceFields = instance?.fields ?? null;
4487
- const defaultFields = (0, import_react32.useMemo)(() => getDefaultFields(definition), [definition]);
4488
- const fields = (0, import_react32.useMemo)(() => {
3788
+ const instance2 = query.data?.[0];
3789
+ const instanceId = instance2?.id ?? null;
3790
+ const currentState = instance2?.currentState ?? "";
3791
+ const instanceFields = instance2?.fields ?? null;
3792
+ const defaultFields = (0, import_react34.useMemo)(() => getDefaultFields(definition), [definition]);
3793
+ const fields = (0, import_react34.useMemo)(() => {
4489
3794
  if (!instanceFields) return defaultFields;
4490
3795
  return { ...defaultFields, ...instanceFields };
4491
3796
  }, [instanceFields, defaultFields]);
4492
- const instanceIdRef = (0, import_react32.useRef)(instanceId);
3797
+ const instanceIdRef = (0, import_react34.useRef)(instanceId);
4493
3798
  instanceIdRef.current = instanceId;
4494
- const trigger = (0, import_react32.useCallback)(async (name, input) => {
3799
+ const trigger = (0, import_react34.useCallback)(async (name, input) => {
4495
3800
  const id = instanceIdRef.current;
4496
3801
  if (!id) {
4497
3802
  throw new Error(`useModel(${slug}): No instance loaded. Cannot trigger '${name}'.`);
@@ -4499,12 +3804,12 @@ function useModel(definition, options = {}) {
4499
3804
  await mutation.transition(id, name, input);
4500
3805
  await query.refetch();
4501
3806
  }, [slug, mutation, query]);
4502
- const create = (0, import_react32.useCallback)(async (input) => {
3807
+ const create = (0, import_react34.useCallback)(async (input) => {
4503
3808
  const id = await mutation.create(input);
4504
3809
  await query.refetch();
4505
3810
  return id;
4506
3811
  }, [mutation, query]);
4507
- const update = (0, import_react32.useCallback)(async (fieldUpdates) => {
3812
+ const update = (0, import_react34.useCallback)(async (fieldUpdates) => {
4508
3813
  const id = instanceIdRef.current;
4509
3814
  if (!id) {
4510
3815
  throw new Error(`useModel(${slug}): No instance loaded. Cannot update.`);
@@ -4533,27 +3838,27 @@ function useCollection(definition, options = {}) {
4533
3838
  const slug = definition.slug;
4534
3839
  const query = useQuery(slug, options);
4535
3840
  const mutation = useMutation(slug);
4536
- const items = (0, import_react32.useMemo)(() => {
4537
- return (query.data || []).map((instance) => ({
4538
- id: instance.id,
4539
- fields: instance.fields ?? {},
4540
- state: instance.currentState ?? ""
3841
+ const items = (0, import_react34.useMemo)(() => {
3842
+ return (query.data || []).map((instance2) => ({
3843
+ id: instance2.id,
3844
+ fields: instance2.fields ?? {},
3845
+ state: instance2.currentState ?? ""
4541
3846
  }));
4542
3847
  }, [query.data]);
4543
- const trigger = (0, import_react32.useCallback)(async (instanceId, name, input) => {
3848
+ const trigger = (0, import_react34.useCallback)(async (instanceId, name, input) => {
4544
3849
  await mutation.transition(instanceId, name, input);
4545
3850
  await query.refetch();
4546
3851
  }, [mutation, query]);
4547
- const create = (0, import_react32.useCallback)(async (input) => {
3852
+ const create = (0, import_react34.useCallback)(async (input) => {
4548
3853
  const id = await mutation.create(input);
4549
3854
  await query.refetch();
4550
3855
  return id;
4551
3856
  }, [mutation, query]);
4552
- const update = (0, import_react32.useCallback)(async (instanceId, fieldUpdates) => {
3857
+ const update = (0, import_react34.useCallback)(async (instanceId, fieldUpdates) => {
4553
3858
  await mutation.update(instanceId, fieldUpdates);
4554
3859
  await query.refetch();
4555
3860
  }, [mutation, query]);
4556
- const remove = (0, import_react32.useCallback)(async (instanceId) => {
3861
+ const remove = (0, import_react34.useCallback)(async (instanceId) => {
4557
3862
  await mutation.remove(instanceId);
4558
3863
  await query.refetch();
4559
3864
  }, [mutation, query]);
@@ -4577,7 +3882,7 @@ function useCollection(definition, options = {}) {
4577
3882
  function stub(displayName) {
4578
3883
  const Component = () => {
4579
3884
  throw new Error(
4580
- `<${displayName}> is a compile-time stub from @mindmatrix/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.`
3885
+ `<${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.`
4581
3886
  );
4582
3887
  };
4583
3888
  Component.displayName = displayName;
@@ -4704,7 +4009,7 @@ function djb2Hash(str) {
4704
4009
  }
4705
4010
 
4706
4011
  // src/authoring.ts
4707
- function useState20(_defaultOrKey) {
4012
+ function useState21(_defaultOrKey) {
4708
4013
  return [void 0, () => {
4709
4014
  }];
4710
4015
  }
@@ -4715,10 +4020,10 @@ function defineWorkspace(config) {
4715
4020
  }
4716
4021
 
4717
4022
  // src/hooks/useModule.ts
4718
- var import_react33 = require("react");
4023
+ var import_react35 = require("react");
4719
4024
  function useModule(slug, config = {}, options = {}) {
4720
4025
  const { enabled = true } = options;
4721
- return (0, import_react33.useMemo)(() => ({
4026
+ return (0, import_react35.useMemo)(() => ({
4722
4027
  slug,
4723
4028
  config,
4724
4029
  isLoaded: enabled
@@ -4726,7 +4031,7 @@ function useModule(slug, config = {}, options = {}) {
4726
4031
  }
4727
4032
 
4728
4033
  // src/hooks/useModuleConfig.ts
4729
- var import_react34 = require("react");
4034
+ var import_react36 = require("react");
4730
4035
  var installedModulesStore = [];
4731
4036
  var configDefaultsStore = /* @__PURE__ */ new Map();
4732
4037
  function setInstalledModules(modules) {
@@ -4742,12 +4047,65 @@ function getInstalledModules() {
4742
4047
  return installedModulesStore;
4743
4048
  }
4744
4049
  function useModuleConfig(moduleSlug) {
4745
- return (0, import_react34.useMemo)(() => {
4050
+ return (0, import_react36.useMemo)(() => {
4746
4051
  const installed = getInstalledModule(moduleSlug);
4747
4052
  const defaults = configDefaultsStore.get(moduleSlug) ?? {};
4748
- return { ...defaults, ...installed?.config };
4053
+ const persisted = persistedConfigStore.get(moduleSlug) ?? {};
4054
+ return { ...defaults, ...persisted, ...installed?.config };
4749
4055
  }, [moduleSlug]);
4750
4056
  }
4057
+ var persistedConfigStore = /* @__PURE__ */ new Map();
4058
+ function setPersistedModuleConfig(moduleSlug, config) {
4059
+ persistedConfigStore.set(moduleSlug, config);
4060
+ }
4061
+ async function syncConfigDefaults(moduleSlug, defaults, definitionId) {
4062
+ const id = definitionId ?? activeDefinitionIdStore;
4063
+ if (!id) return;
4064
+ try {
4065
+ const moduleKey = `module_config.${moduleSlug}`;
4066
+ await updateDefinitionConfig({ [moduleKey]: defaults }, id);
4067
+ persistedConfigStore.set(moduleSlug, defaults);
4068
+ } catch (e) {
4069
+ console.warn(`[useModuleConfig] Failed to sync config for ${moduleSlug}:`, e);
4070
+ }
4071
+ }
4072
+ var activeDefinitionIdStore = null;
4073
+ var apiBaseUrlStore = "/api/v1/workflow";
4074
+ function setConfigContext(definitionId, apiBaseUrl) {
4075
+ activeDefinitionIdStore = definitionId;
4076
+ if (apiBaseUrl) apiBaseUrlStore = apiBaseUrl;
4077
+ }
4078
+ async function updateDefinitionConfig(values, definitionId) {
4079
+ const id = definitionId ?? activeDefinitionIdStore;
4080
+ if (!id) throw new Error("No active definition ID. Call setConfigContext() first.");
4081
+ const token = typeof localStorage !== "undefined" ? localStorage.getItem("auth_token") : null;
4082
+ const response = await fetch(`${apiBaseUrlStore}/definitions/${id}/config`, {
4083
+ method: "PATCH",
4084
+ headers: {
4085
+ "Content-Type": "application/json",
4086
+ ...token ? { Authorization: `Bearer ${token}` } : {}
4087
+ },
4088
+ body: JSON.stringify(values)
4089
+ });
4090
+ if (!response.ok) {
4091
+ const err = await response.json().catch(() => ({ message: response.statusText }));
4092
+ throw new Error(err.message || `Failed to update config: ${response.status}`);
4093
+ }
4094
+ return response.json();
4095
+ }
4096
+ function useModuleConfigWithMutation(moduleSlug) {
4097
+ const config = useModuleConfig(moduleSlug);
4098
+ const [isSaving, setIsSaving] = (0, import_react36.useState)(false);
4099
+ const updateConfig = (0, import_react36.useCallback)(async (values) => {
4100
+ setIsSaving(true);
4101
+ try {
4102
+ return await updateDefinitionConfig(values);
4103
+ } finally {
4104
+ setIsSaving(false);
4105
+ }
4106
+ }, []);
4107
+ return { config, updateConfig, isSaving };
4108
+ }
4751
4109
 
4752
4110
  // src/builders.ts
4753
4111
  function handlerToAction(handler, qualifier) {
@@ -6251,7 +5609,7 @@ function approval(config = {}) {
6251
5609
  }
6252
5610
  function escalation(config) {
6253
5611
  const {
6254
- timeout,
5612
+ timeout: timeout2,
6255
5613
  notifyRole = "admin",
6256
5614
  fromState = "pending_approval",
6257
5615
  escalatedState = "escalated"
@@ -6263,7 +5621,7 @@ function escalation(config) {
6263
5621
  });
6264
5622
  if (def.states[fromState]) {
6265
5623
  def.states[fromState].timeout = {
6266
- duration: timeout,
5624
+ duration: timeout2,
6267
5625
  fallback: { transition: "escalate" }
6268
5626
  };
6269
5627
  }
@@ -6282,8 +5640,8 @@ function escalation(config) {
6282
5640
  from: fromState,
6283
5641
  to: escalatedState,
6284
5642
  auto: true,
6285
- description: `Auto-escalate after ${timeout}`,
6286
- actions: [logEvent("escalated", { timeout })]
5643
+ description: `Auto-escalate after ${timeout2}`,
5644
+ actions: [logEvent("escalated", { timeout: timeout2 })]
6287
5645
  }
6288
5646
  });
6289
5647
  return def;
@@ -6941,7 +6299,8 @@ function describeModel(def) {
6941
6299
  }
6942
6300
 
6943
6301
  // src/hooks/usePlayer.ts
6944
- var import_react35 = require("react");
6302
+ var import_react37 = require("react");
6303
+ var import_player_core2 = require("@mmapp/player-core");
6945
6304
 
6946
6305
  // src/logger.ts
6947
6306
  var debugEnabled = false;
@@ -6981,18 +6340,18 @@ function computePlayerState(sm) {
6981
6340
  };
6982
6341
  }
6983
6342
  function usePlayer(config) {
6984
- const configRef = (0, import_react35.useRef)(config);
6343
+ const configRef = (0, import_react37.useRef)(config);
6985
6344
  configRef.current = config;
6986
- (0, import_react35.useEffect)(() => {
6345
+ (0, import_react37.useEffect)(() => {
6987
6346
  if (config.debug) setPlayerDebug(true);
6988
6347
  }, [config.debug]);
6989
- const evaluator = (0, import_react35.useMemo)(() => {
6990
- return createEvaluator({
6348
+ const evaluator = (0, import_react37.useMemo)(() => {
6349
+ return (0, import_player_core2.createEvaluator)({
6991
6350
  functions: config.functions ?? [],
6992
- failurePolicy: WEB_FAILURE_POLICIES.EVENT_REACTION
6351
+ failurePolicy: import_player_core2.WEB_FAILURE_POLICIES.EVENT_REACTION
6993
6352
  });
6994
6353
  }, [config.definition.id]);
6995
- const engine = (0, import_react35.useMemo)(() => {
6354
+ const engine = (0, import_react37.useMemo)(() => {
6996
6355
  const actionHandlers = /* @__PURE__ */ new Map();
6997
6356
  if (config.actionHandlers) {
6998
6357
  for (const [type, handler] of Object.entries(config.actionHandlers)) {
@@ -7020,14 +6379,14 @@ function usePlayer(config) {
7020
6379
  });
7021
6380
  }
7022
6381
  });
7023
- const sm2 = new StateMachine(
6382
+ const sm2 = new import_player_core2.StateMachine(
7024
6383
  config.definition,
7025
6384
  config.initialData ?? {},
7026
6385
  { evaluator, actionHandlers }
7027
6386
  );
7028
6387
  smRef = sm2;
7029
- const eventBus2 = new EventBus();
7030
- const dispatcher = new ActionDispatcher();
6388
+ const eventBus2 = new import_player_core2.EventBus();
6389
+ const dispatcher = new import_player_core2.ActionDispatcher();
7031
6390
  dispatcher.register("set_field", (cfg) => {
7032
6391
  if (smRef && typeof cfg.field === "string") {
7033
6392
  smRef.setField(cfg.field, cfg.value);
@@ -7046,8 +6405,8 @@ function usePlayer(config) {
7046
6405
  return { sm: sm2, eventBus: eventBus2, dispatcher };
7047
6406
  }, [config.definition.id, evaluator]);
7048
6407
  const { sm, eventBus } = engine;
7049
- const [playerState, setPlayerState] = (0, import_react35.useState)(() => computePlayerState(sm));
7050
- (0, import_react35.useEffect)(() => {
6408
+ const [playerState, setPlayerState] = (0, import_react37.useState)(() => computePlayerState(sm));
6409
+ (0, import_react37.useEffect)(() => {
7051
6410
  const stateDef = sm.getCurrentStateDefinition();
7052
6411
  if (!stateDef?.on_event?.length) return;
7053
6412
  const unsubs = [];
@@ -7111,7 +6470,7 @@ function usePlayer(config) {
7111
6470
  for (const unsub of unsubs) unsub();
7112
6471
  };
7113
6472
  }, [sm, eventBus, evaluator, engine.dispatcher, playerState.currentState]);
7114
- (0, import_react35.useEffect)(() => {
6473
+ (0, import_react37.useEffect)(() => {
7115
6474
  const unsub = sm.on((event) => {
7116
6475
  if (event.type === "transition" || event.type === "state_enter") {
7117
6476
  setPlayerState(computePlayerState(sm));
@@ -7127,7 +6486,7 @@ function usePlayer(config) {
7127
6486
  });
7128
6487
  return unsub;
7129
6488
  }, [sm]);
7130
- const transition2 = (0, import_react35.useCallback)(
6489
+ const transition2 = (0, import_react37.useCallback)(
7131
6490
  async (name, data) => {
7132
6491
  playerLog({
7133
6492
  level: "info",
@@ -7154,20 +6513,20 @@ function usePlayer(config) {
7154
6513
  },
7155
6514
  [sm]
7156
6515
  );
7157
- const setField2 = (0, import_react35.useCallback)(
6516
+ const setField2 = (0, import_react37.useCallback)(
7158
6517
  (field2, value) => {
7159
6518
  sm.setField(field2, value);
7160
6519
  setPlayerState(computePlayerState(sm));
7161
6520
  },
7162
6521
  [sm]
7163
6522
  );
7164
- const setMemory = (0, import_react35.useCallback)(
6523
+ const setMemory = (0, import_react37.useCallback)(
7165
6524
  (key, value) => {
7166
6525
  sm.setMemory(key, value);
7167
6526
  },
7168
6527
  [sm]
7169
6528
  );
7170
- const publishEvent = (0, import_react35.useCallback)(
6529
+ const publishEvent = (0, import_react37.useCallback)(
7171
6530
  (topic, payload) => {
7172
6531
  playerLog({
7173
6532
  level: "debug",
@@ -7193,11 +6552,11 @@ function usePlayer(config) {
7193
6552
  }
7194
6553
 
7195
6554
  // src/hooks/useDomainSubscription.ts
7196
- var import_react36 = require("react");
6555
+ var import_react38 = require("react");
7197
6556
  function useDomainSubscription(eventBus, transport, config) {
7198
- const configRef = (0, import_react36.useRef)(config);
6557
+ const configRef = (0, import_react38.useRef)(config);
7199
6558
  configRef.current = config;
7200
- (0, import_react36.useEffect)(() => {
6559
+ (0, import_react38.useEffect)(() => {
7201
6560
  if (!transport || config.enabled === false) return;
7202
6561
  const unsub = transport.subscribe(
7203
6562
  {
@@ -7250,11 +6609,11 @@ function useDomainSubscription(eventBus, transport, config) {
7250
6609
  }
7251
6610
 
7252
6611
  // src/hooks/useExperienceState.ts
7253
- var import_react37 = require("react");
6612
+ var import_react39 = require("react");
7254
6613
  function useExperienceState(player, selector) {
7255
- const selectorRef = (0, import_react37.useRef)(selector);
6614
+ const selectorRef = (0, import_react39.useRef)(selector);
7256
6615
  selectorRef.current = selector;
7257
- const getSnapshot = (0, import_react37.useCallback)(() => {
6616
+ const getSnapshot = (0, import_react39.useCallback)(() => {
7258
6617
  return selectorRef.current({
7259
6618
  currentState: player.currentState,
7260
6619
  stateData: player.stateData,
@@ -7270,20 +6629,20 @@ function useStateField(player, field2, defaultValue) {
7270
6629
  }
7271
6630
 
7272
6631
  // src/hooks/useComputed.ts
7273
- var import_react38 = require("react");
6632
+ var import_react40 = require("react");
7274
6633
  function useComputed(_name, compute, options) {
7275
6634
  const mode = options?.mode ?? "read-time";
7276
6635
  const deps = options?.deps ?? [];
7277
- const computeRef = (0, import_react38.useRef)(compute);
6636
+ const computeRef = (0, import_react40.useRef)(compute);
7278
6637
  computeRef.current = compute;
7279
6638
  if (mode === "read-time") {
7280
- return (0, import_react38.useMemo)(() => computeRef.current(), [
6639
+ return (0, import_react40.useMemo)(() => computeRef.current(), [
7281
6640
  // We intentionally depend on deps.join to recompute when tracked fields change
7282
6641
  // The actual dependency tracking happens at the compiler level
7283
6642
  deps.join(",")
7284
6643
  ]);
7285
6644
  }
7286
- return (0, import_react38.useMemo)(() => computeRef.current(), [deps.join(",")]);
6645
+ return (0, import_react40.useMemo)(() => computeRef.current(), [deps.join(",")]);
7287
6646
  }
7288
6647
  function useComputedWithMeta(name, compute, options) {
7289
6648
  const value = useComputed(name, compute, options);
@@ -7298,25 +6657,25 @@ function useComputedWithMeta(name, compute, options) {
7298
6657
  }
7299
6658
 
7300
6659
  // src/components/PlayerProvider.tsx
7301
- var import_react39 = require("react");
6660
+ var import_react41 = require("react");
7302
6661
  var import_jsx_runtime2 = require("react/jsx-runtime");
7303
- var PlayerContext = (0, import_react39.createContext)(null);
6662
+ var PlayerContext = (0, import_react41.createContext)(null);
7304
6663
  function PlayerProvider({ player, children }) {
7305
6664
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PlayerContext.Provider, { value: player, children });
7306
6665
  }
7307
6666
  function usePlayerContext() {
7308
- const ctx = (0, import_react39.useContext)(PlayerContext);
6667
+ const ctx = (0, import_react41.useContext)(PlayerContext);
7309
6668
  if (!ctx) {
7310
6669
  throw new Error("usePlayerContext must be used within a <PlayerProvider>");
7311
6670
  }
7312
6671
  return ctx;
7313
6672
  }
7314
6673
  function usePlayerContextSafe() {
7315
- return (0, import_react39.useContext)(PlayerContext);
6674
+ return (0, import_react41.useContext)(PlayerContext);
7316
6675
  }
7317
6676
 
7318
6677
  // src/components/ExperienceWorkflowBridge.tsx
7319
- var import_react40 = require("react");
6678
+ var import_react42 = require("react");
7320
6679
  var import_jsx_runtime3 = require("react/jsx-runtime");
7321
6680
  function ExperienceWorkflowBridgeInner({
7322
6681
  definition,
@@ -7334,7 +6693,7 @@ function ExperienceWorkflowBridgeInner({
7334
6693
  actionHandlers,
7335
6694
  debug
7336
6695
  });
7337
- const viewConfig = (0, import_react40.useMemo)(() => {
6696
+ const viewConfig = (0, import_react42.useMemo)(() => {
7338
6697
  if (!definition.state_views) return void 0;
7339
6698
  return definition.state_views[player.currentState];
7340
6699
  }, [definition.state_views, player.currentState]);
@@ -7369,7 +6728,7 @@ function ExperienceWorkflowBridge(props) {
7369
6728
  }
7370
6729
 
7371
6730
  // src/components/atoms/index.tsx
7372
- var import_react41 = __toESM(require("react"));
6731
+ var import_react43 = __toESM(require("react"));
7373
6732
  var import_jsx_runtime4 = require("react/jsx-runtime");
7374
6733
 
7375
6734
  // src/loader/experience-workflow-loader.ts
@@ -7690,7 +7049,7 @@ var BrowserPlayer = class {
7690
7049
  this.ensureInitialized();
7691
7050
  const id = crypto.randomUUID();
7692
7051
  const now = (/* @__PURE__ */ new Date()).toISOString();
7693
- const instance = {
7052
+ const instance2 = {
7694
7053
  id,
7695
7054
  definitionId: options.definitionId ?? definitionSlug,
7696
7055
  definitionSlug,
@@ -7702,15 +7061,15 @@ var BrowserPlayer = class {
7702
7061
  createdAt: now,
7703
7062
  updatedAt: now
7704
7063
  };
7705
- await this.putInstance(instance);
7064
+ await this.putInstance(instance2);
7706
7065
  this.log("info", `Instance created: ${id} (${definitionSlug})`);
7707
7066
  this.emit({
7708
7067
  type: "instance:created",
7709
7068
  instanceId: id,
7710
- data: { definitionSlug, currentState: instance.currentState },
7069
+ data: { definitionSlug, currentState: instance2.currentState },
7711
7070
  timestamp: Date.now()
7712
7071
  });
7713
- return instance;
7072
+ return instance2;
7714
7073
  }
7715
7074
  /** Get an instance by ID. */
7716
7075
  async getInstance(id) {
@@ -7719,13 +7078,13 @@ var BrowserPlayer = class {
7719
7078
  }
7720
7079
  /** Get the current state of an instance. */
7721
7080
  async getState(id) {
7722
- const instance = await this.getInstance(id);
7723
- if (!instance) return null;
7081
+ const instance2 = await this.getInstance(id);
7082
+ if (!instance2) return null;
7724
7083
  return {
7725
- currentState: instance.currentState,
7726
- status: instance.status,
7727
- stateData: instance.stateData,
7728
- lockVersion: instance.lockVersion
7084
+ currentState: instance2.currentState,
7085
+ status: instance2.status,
7086
+ stateData: instance2.stateData,
7087
+ lockVersion: instance2.lockVersion
7729
7088
  };
7730
7089
  }
7731
7090
  /**
@@ -7736,34 +7095,34 @@ var BrowserPlayer = class {
7736
7095
  */
7737
7096
  async transition(instanceId, transitionName, data = {}) {
7738
7097
  this.ensureInitialized();
7739
- const instance = await this.getInstanceFromDb(instanceId);
7740
- if (!instance) {
7098
+ const instance2 = await this.getInstanceFromDb(instanceId);
7099
+ if (!instance2) {
7741
7100
  return {
7742
7101
  success: false,
7743
7102
  instance: null,
7744
7103
  error: `Instance ${instanceId} not found`
7745
7104
  };
7746
7105
  }
7747
- if (instance.status !== "ACTIVE") {
7106
+ if (instance2.status !== "ACTIVE") {
7748
7107
  return {
7749
7108
  success: false,
7750
- instance,
7751
- error: `Instance is ${instance.status}, cannot transition`
7109
+ instance: instance2,
7110
+ error: `Instance is ${instance2.status}, cannot transition`
7752
7111
  };
7753
7112
  }
7754
7113
  try {
7755
- const newStateData = { ...instance.stateData, ...data };
7756
- const newLockVersion = instance.lockVersion + 1;
7114
+ const newStateData = { ...instance2.stateData, ...data };
7115
+ const newLockVersion = instance2.lockVersion + 1;
7757
7116
  if (this.wasm.execute_transition) {
7758
7117
  const request = {
7759
7118
  instance: {
7760
- id: instance.id,
7761
- definition_id: instance.definitionId,
7762
- current_state: instance.currentState,
7763
- status: instance.status,
7119
+ id: instance2.id,
7120
+ definition_id: instance2.definitionId,
7121
+ current_state: instance2.currentState,
7122
+ status: instance2.status,
7764
7123
  state_data: newStateData,
7765
- memory: instance.memory,
7766
- execution_lock_version: instance.lockVersion
7124
+ memory: instance2.memory,
7125
+ execution_lock_version: instance2.lockVersion
7767
7126
  },
7768
7127
  transition_name: transitionName,
7769
7128
  actor_id: this.peerId,
@@ -7772,26 +7131,26 @@ var BrowserPlayer = class {
7772
7131
  const resultJson = this.wasm.execute_transition(JSON.stringify(request));
7773
7132
  const result = JSON.parse(resultJson);
7774
7133
  if (result.success === false || result.error) {
7775
- return { success: false, instance, error: result.error ?? "Transition failed" };
7134
+ return { success: false, instance: instance2, error: result.error ?? "Transition failed" };
7776
7135
  }
7777
- instance.currentState = result.to_state ?? instance.currentState;
7778
- instance.status = result.status ?? instance.status;
7779
- instance.stateData = result.state_data ?? newStateData;
7780
- instance.memory = result.memory ?? instance.memory;
7136
+ instance2.currentState = result.to_state ?? instance2.currentState;
7137
+ instance2.status = result.status ?? instance2.status;
7138
+ instance2.stateData = result.state_data ?? newStateData;
7139
+ instance2.memory = result.memory ?? instance2.memory;
7781
7140
  } else {
7782
- instance.stateData = newStateData;
7141
+ instance2.stateData = newStateData;
7783
7142
  }
7784
- instance.lockVersion = newLockVersion;
7785
- instance.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
7786
- await this.putInstance(instance);
7143
+ instance2.lockVersion = newLockVersion;
7144
+ instance2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
7145
+ await this.putInstance(instance2);
7787
7146
  this.log("info", `Transition: ${instanceId} ${transitionName}`);
7788
7147
  this.emit({
7789
7148
  type: "instance:transition",
7790
7149
  instanceId,
7791
7150
  data: {
7792
7151
  transitionName,
7793
- fromState: instance.currentState,
7794
- toState: instance.currentState,
7152
+ fromState: instance2.currentState,
7153
+ toState: instance2.currentState,
7795
7154
  lockVersion: newLockVersion
7796
7155
  },
7797
7156
  timestamp: Date.now()
@@ -7801,7 +7160,7 @@ var BrowserPlayer = class {
7801
7160
  type: "TransitionReplication",
7802
7161
  instance_id: instanceId,
7803
7162
  transition_name: transitionName,
7804
- state_data: instance.stateData,
7163
+ state_data: instance2.stateData,
7805
7164
  lock_version: newLockVersion
7806
7165
  });
7807
7166
  const envelope = this.wasm.sign_envelope(this.secretKeyHex, payload);
@@ -7811,11 +7170,11 @@ var BrowserPlayer = class {
7811
7170
  envelope
7812
7171
  }));
7813
7172
  }
7814
- return { success: true, instance };
7173
+ return { success: true, instance: instance2 };
7815
7174
  } catch (err) {
7816
7175
  const error = err instanceof Error ? err.message : String(err);
7817
7176
  this.log("error", `Transition failed: ${error}`);
7818
- return { success: false, instance, error };
7177
+ return { success: false, instance: instance2, error };
7819
7178
  }
7820
7179
  }
7821
7180
  // ─── Subscriptions ──────────────────────────────────────────────────
@@ -7895,12 +7254,12 @@ var BrowserPlayer = class {
7895
7254
  request.onerror = () => reject(request.error);
7896
7255
  });
7897
7256
  }
7898
- async putInstance(instance) {
7257
+ async putInstance(instance2) {
7899
7258
  if (!this.db) return;
7900
7259
  return new Promise((resolve, reject) => {
7901
7260
  const tx = this.db.transaction(INSTANCE_STORE_NAME, "readwrite");
7902
7261
  const store = tx.objectStore(INSTANCE_STORE_NAME);
7903
- store.put(instance);
7262
+ store.put(instance2);
7904
7263
  tx.oncomplete = () => resolve();
7905
7264
  tx.onerror = () => reject(tx.error);
7906
7265
  });
@@ -8047,10 +7406,382 @@ var BrowserPlayer = class {
8047
7406
  }
8048
7407
  }
8049
7408
  };
7409
+
7410
+ // src/middleware-def.ts
7411
+ function defineMiddleware(def) {
7412
+ if (process.env.NODE_ENV !== "production") {
7413
+ if (!def.name || typeof def.name !== "string") {
7414
+ throw new Error("defineMiddleware: name is required and must be a string");
7415
+ }
7416
+ if (!def.match) {
7417
+ throw new Error("defineMiddleware: match pattern is required");
7418
+ }
7419
+ const patterns = Array.isArray(def.match) ? def.match : [def.match];
7420
+ for (const p of patterns) {
7421
+ if (typeof p !== "string") {
7422
+ throw new Error(`defineMiddleware: match pattern must be a string, got ${typeof p}`);
7423
+ }
7424
+ }
7425
+ if (def.priority !== void 0 && typeof def.priority !== "number") {
7426
+ throw new Error("defineMiddleware: priority must be a number");
7427
+ }
7428
+ if (!def.before && !def.after && !def.around) {
7429
+ throw new Error("defineMiddleware: at least one of before, after, or around must be provided");
7430
+ }
7431
+ }
7432
+ return def;
7433
+ }
7434
+ function extendMiddleware(base, overrides) {
7435
+ let introduce;
7436
+ if (base.introduce || overrides.introduce) {
7437
+ introduce = {
7438
+ fields: { ...base.introduce?.fields, ...overrides.introduce?.fields },
7439
+ states: { ...base.introduce?.states, ...overrides.introduce?.states },
7440
+ transitions: { ...base.introduce?.transitions, ...overrides.introduce?.transitions }
7441
+ };
7442
+ if (introduce.fields && Object.keys(introduce.fields).length === 0) introduce.fields = void 0;
7443
+ if (introduce.states && Object.keys(introduce.states).length === 0) introduce.states = void 0;
7444
+ if (introduce.transitions && Object.keys(introduce.transitions).length === 0) introduce.transitions = void 0;
7445
+ }
7446
+ const merged = {
7447
+ ...base,
7448
+ ...overrides,
7449
+ // Config is merged (overrides win per-key)
7450
+ config: base.config || overrides.config ? { ...base.config, ...overrides.config } : void 0
7451
+ };
7452
+ if (introduce) {
7453
+ merged.introduce = introduce;
7454
+ }
7455
+ if (process.env.NODE_ENV !== "production") {
7456
+ if (!merged.name || typeof merged.name !== "string") {
7457
+ throw new Error("extendMiddleware: resulting middleware must have a name");
7458
+ }
7459
+ if (!merged.match) {
7460
+ throw new Error("extendMiddleware: resulting middleware must have a match pattern");
7461
+ }
7462
+ if (!merged.before && !merged.after && !merged.around) {
7463
+ throw new Error("extendMiddleware: resulting middleware must have at least one of before, after, or around");
7464
+ }
7465
+ }
7466
+ return merged;
7467
+ }
7468
+ function withAuth(opts) {
7469
+ const _redirectTo = opts?.redirectTo;
7470
+ return {
7471
+ name: "mm:auth",
7472
+ match: "*:*:transition.execute",
7473
+ priority: 90,
7474
+ before(ctx) {
7475
+ if (!ctx.actor.id) {
7476
+ ctx.block(_redirectTo ? `redirect:${_redirectTo}` : "Authentication required");
7477
+ }
7478
+ }
7479
+ };
7480
+ }
7481
+ function withAuditLog(opts) {
7482
+ const _level = opts?.level ?? "info";
7483
+ return {
7484
+ name: "mm:audit-log",
7485
+ match: "*:*:transition.execute",
7486
+ priority: 0,
7487
+ after(ctx) {
7488
+ ctx.modify({
7489
+ __audit: {
7490
+ level: _level,
7491
+ actor: ctx.actor.id,
7492
+ transition: ctx.transition?.name,
7493
+ from: ctx.transition?.from,
7494
+ to: ctx.transition?.to,
7495
+ timestamp: ctx.timestamp
7496
+ }
7497
+ });
7498
+ }
7499
+ };
7500
+ }
7501
+ function withRateLimit(opts) {
7502
+ const _max = opts?.maxPerMinute ?? 60;
7503
+ return {
7504
+ name: "mm:rate-limit",
7505
+ match: "*:*:transition.execute",
7506
+ priority: 80,
7507
+ config: {
7508
+ maxPerMinute: { type: "number", default: _max }
7509
+ },
7510
+ before(ctx) {
7511
+ const fields = ctx.instance.fields;
7512
+ const counter = fields.__rateCounter || 0;
7513
+ if (counter >= _max) {
7514
+ ctx.block(`Rate limit exceeded: ${_max} per minute`);
7515
+ }
7516
+ }
7517
+ };
7518
+ }
7519
+ function withValidation(opts) {
7520
+ const _rules = opts?.rules ?? [];
7521
+ return {
7522
+ name: "mm:validation",
7523
+ match: "*:*:field.change",
7524
+ priority: 70,
7525
+ config: {
7526
+ rules: { type: "json", default: _rules }
7527
+ },
7528
+ before(ctx) {
7529
+ if (!ctx.field) return;
7530
+ for (const rule of _rules) {
7531
+ if (rule.fields.includes(ctx.field.name)) {
7532
+ ctx.block(rule.message);
7533
+ }
7534
+ }
7535
+ }
7536
+ };
7537
+ }
7538
+ function withMetrics(opts) {
7539
+ const _endpoint = opts?.endpoint;
7540
+ return {
7541
+ name: "mm:metrics",
7542
+ match: "*:*:*",
7543
+ priority: 100,
7544
+ config: {
7545
+ endpoint: { type: "string", default: _endpoint }
7546
+ },
7547
+ async around(ctx, next) {
7548
+ const start = ctx.timestamp;
7549
+ await next();
7550
+ const duration = Date.now() - start;
7551
+ ctx.modify({
7552
+ __metrics: {
7553
+ duration,
7554
+ endpoint: _endpoint,
7555
+ actor: ctx.actor.id
7556
+ }
7557
+ });
7558
+ }
7559
+ };
7560
+ }
7561
+
7562
+ // src/actor.ts
7563
+ function compileTimeOnly(name) {
7564
+ throw new Error(
7565
+ `${name}() is a compile-time function and cannot be called at runtime. Use \`mmrc build\` to compile your workflow.`
7566
+ );
7567
+ }
7568
+ var DEFAULT_SUPERVISION = {
7569
+ strategy: "escalate"
7570
+ };
7571
+ var DEFAULT_MAILBOX = {
7572
+ capacity: 1e3,
7573
+ overflow: "error",
7574
+ priority: "fifo"
7575
+ };
7576
+ function configureActor(config) {
7577
+ void config;
7578
+ return {
7579
+ __actor: true,
7580
+ supervision: config.supervision ?? DEFAULT_SUPERVISION,
7581
+ mailbox: config.mailbox ?? DEFAULT_MAILBOX,
7582
+ hierarchy: config.hierarchy ?? {}
7583
+ };
7584
+ }
7585
+ function spawnActor(_slug, _options) {
7586
+ compileTimeOnly("spawnActor");
7587
+ }
7588
+ function sendMessage(_instanceId, _action, _payload) {
7589
+ compileTimeOnly("sendMessage");
7590
+ }
7591
+ function isActorConfig(value) {
7592
+ return typeof value === "object" && value !== null && value.__actor === true;
7593
+ }
7594
+
7595
+ // src/constraints.ts
7596
+ var BUILT_IN_CONSTRAINTS = /* @__PURE__ */ new Set([
7597
+ "every state is reachable",
7598
+ "no deadlocks",
7599
+ "no unreachable states",
7600
+ "deterministic guards",
7601
+ "terminates",
7602
+ "no guard overlaps",
7603
+ "all roles defined",
7604
+ "all fields validated"
7605
+ ]);
7606
+ function constraints(...rules) {
7607
+ if (process.env.NODE_ENV !== "production") {
7608
+ if (rules.length === 0) {
7609
+ throw new Error("constraints(): at least one constraint rule is required");
7610
+ }
7611
+ for (let i = 0; i < rules.length; i++) {
7612
+ const rule = rules[i];
7613
+ if (typeof rule !== "string" || rule.trim() === "") {
7614
+ throw new Error(
7615
+ `constraints(): rule at index ${i} must be a non-empty string, got ${typeof rule}`
7616
+ );
7617
+ }
7618
+ }
7619
+ }
7620
+ return {
7621
+ __constraints: true,
7622
+ rules: Object.freeze([...rules])
7623
+ };
7624
+ }
7625
+ function isConstraintDeclaration(value) {
7626
+ return typeof value === "object" && value !== null && value.__constraints === true && Array.isArray(value.rules);
7627
+ }
7628
+ function isBuiltInConstraint(rule) {
7629
+ return BUILT_IN_CONSTRAINTS.has(rule);
7630
+ }
7631
+
7632
+ // src/extend.ts
7633
+ function extend(base, options) {
7634
+ const _metadata = {
7635
+ __extend: true,
7636
+ base,
7637
+ options
7638
+ };
7639
+ throw new Error(
7640
+ `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.
7641
+
7642
+ Base workflow: ${base?.name ?? "(anonymous)"}
7643
+ Derived slug: ${options.slug ?? "(not specified)"}`
7644
+ );
7645
+ return _metadata;
7646
+ }
7647
+
7648
+ // src/compose.ts
7649
+ function compose(workflow, ...mixins) {
7650
+ for (let i = 0; i < mixins.length; i++) {
7651
+ const mixin = mixins[i];
7652
+ if (!mixin || mixin.__mixin !== true) {
7653
+ throw new Error(
7654
+ `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)}`
7655
+ );
7656
+ }
7657
+ }
7658
+ const metadata = {
7659
+ __composed: true,
7660
+ workflow,
7661
+ mixins: Object.freeze([...mixins])
7662
+ };
7663
+ const composed = (async (...args) => {
7664
+ return workflow(...args);
7665
+ });
7666
+ Object.defineProperty(composed, "__composed", {
7667
+ value: metadata,
7668
+ writable: false,
7669
+ enumerable: false,
7670
+ configurable: false
7671
+ });
7672
+ Object.defineProperty(composed, "name", {
7673
+ value: `composed(${workflow.name || "anonymous"})`,
7674
+ writable: false,
7675
+ configurable: true
7676
+ });
7677
+ return composed;
7678
+ }
7679
+
7680
+ // src/imperative.ts
7681
+ function compileTimeOnly2(name) {
7682
+ throw new Error(
7683
+ `${name}() is a compile-time function and cannot be called at runtime. Use \`mmrc build\` to compile your workflow.`
7684
+ );
7685
+ }
7686
+ function compileTimeProxy(label) {
7687
+ return new Proxy(
7688
+ {},
7689
+ {
7690
+ get(_target, prop) {
7691
+ throw new Error(
7692
+ `Cannot access \`${label}.${String(prop)}\` at runtime. \`${label}\` is a compile-time constant. Use \`mmrc build\` to compile your workflow.`
7693
+ );
7694
+ }
7695
+ }
7696
+ );
7697
+ }
7698
+ function validate(_condition, _message, _severity) {
7699
+ compileTimeOnly2("validate");
7700
+ }
7701
+ function log(_event, _data) {
7702
+ compileTimeOnly2("log");
7703
+ }
7704
+ function notify2(_to, _message, _opts) {
7705
+ compileTimeOnly2("notify");
7706
+ }
7707
+ function emit(_event, _payload) {
7708
+ compileTimeOnly2("emit");
7709
+ }
7710
+ function requireRole2(..._roles) {
7711
+ compileTimeOnly2("requireRole");
7712
+ }
7713
+ function requireField(..._fields) {
7714
+ compileTimeOnly2("requireField");
7715
+ }
7716
+ function guard(_expression) {
7717
+ compileTimeOnly2("guard");
7718
+ }
7719
+ function every(_interval, _fn) {
7720
+ compileTimeOnly2("every");
7721
+ }
7722
+ function cron2(_expression, _fn) {
7723
+ compileTimeOnly2("cron");
7724
+ }
7725
+ function after(_delay, _fn) {
7726
+ compileTimeOnly2("after");
7727
+ }
7728
+ function on(_pattern, _handlerOrOpts) {
7729
+ compileTimeOnly2("on");
7730
+ }
7731
+ function timeout(_duration, _handler) {
7732
+ compileTimeOnly2("timeout");
7733
+ }
7734
+ function userAction(_name, _opts) {
7735
+ compileTimeOnly2("userAction");
7736
+ }
7737
+ function userChoice(_options) {
7738
+ compileTimeOnly2("userChoice");
7739
+ }
7740
+ function named(_name, _stateCall) {
7741
+ compileTimeOnly2("named");
7742
+ }
7743
+ function delay(_duration) {
7744
+ compileTimeOnly2("delay");
7745
+ }
7746
+ function allowTransition(_name, _opts) {
7747
+ compileTimeOnly2("allowTransition");
7748
+ }
7749
+ function restrict(_field, _opts) {
7750
+ compileTimeOnly2("restrict");
7751
+ }
7752
+ function visibleTo(..._roles) {
7753
+ compileTimeOnly2("visibleTo");
7754
+ }
7755
+ function editableBy(..._roles) {
7756
+ compileTimeOnly2("editableBy");
7757
+ }
7758
+ function editableIn(..._states) {
7759
+ compileTimeOnly2("editableIn");
7760
+ }
7761
+ function defineRoles(roles) {
7762
+ void roles;
7763
+ compileTimeOnly2("defineRoles");
7764
+ }
7765
+ function runtime(_target) {
7766
+ compileTimeOnly2("runtime");
7767
+ }
7768
+ function orchestration(config) {
7769
+ void config;
7770
+ compileTimeOnly2("orchestration");
7771
+ }
7772
+ function blueprint(_slug, _config) {
7773
+ compileTimeOnly2("blueprint");
7774
+ }
7775
+ function patch(_id, _overrides) {
7776
+ compileTimeOnly2("patch");
7777
+ }
7778
+ var actor = compileTimeProxy("actor");
7779
+ var instance = compileTimeProxy("instance");
8050
7780
  // Annotate the CommonJS export names for ESM import in node:
8051
7781
  0 && (module.exports = {
8052
7782
  Accordion,
8053
7783
  AnimatedBox,
7784
+ BUILT_IN_CONSTRAINTS,
8054
7785
  Badge,
8055
7786
  Blueprint,
8056
7787
  BrowserPlayer,
@@ -8077,6 +7808,7 @@ var BrowserPlayer = class {
8077
7808
  Modal,
8078
7809
  ModelBuilder,
8079
7810
  NavLink,
7811
+ ORCHESTRATION_PRESETS,
8080
7812
  PlayerProvider,
8081
7813
  RoleGuard,
8082
7814
  Route,
@@ -8100,12 +7832,19 @@ var BrowserPlayer = class {
8100
7832
  WorkflowProvider,
8101
7833
  WorkflowRuntime,
8102
7834
  action,
7835
+ actor,
7836
+ after,
7837
+ allowTransition,
8103
7838
  and,
8104
7839
  applyMixins,
8105
7840
  approval,
8106
7841
  assertModelValid,
8107
7842
  cedar,
7843
+ compose,
7844
+ computeVisibility,
7845
+ configureActor,
8108
7846
  connector,
7847
+ constraints,
8109
7848
  createActions,
8110
7849
  createCRUD,
8111
7850
  createLocalDataResolver,
@@ -8114,16 +7853,26 @@ var BrowserPlayer = class {
8114
7853
  cron,
8115
7854
  crud,
8116
7855
  defineBlueprint,
7856
+ defineImperativeBlueprint,
7857
+ defineMiddleware,
8117
7858
  defineModel,
8118
7859
  defineModule,
7860
+ defineRoles,
8119
7861
  defineWorkspace,
7862
+ delay,
8120
7863
  deriveInstanceKey,
8121
7864
  deriveInstanceKeySync,
8122
7865
  describeModel,
8123
7866
  deviceAction,
8124
7867
  dmn,
7868
+ editableBy,
7869
+ editableIn,
7870
+ emit,
8125
7871
  escalation,
7872
+ every,
8126
7873
  expr,
7874
+ extend,
7875
+ extendMiddleware,
8127
7876
  field,
8128
7877
  fieldContains,
8129
7878
  fieldEquals,
@@ -8138,12 +7887,21 @@ var BrowserPlayer = class {
8138
7887
  getInstalledModule,
8139
7888
  getInstalledModules,
8140
7889
  graphql,
7890
+ guard,
8141
7891
  hasAnyRole,
8142
7892
  hasRole,
7893
+ imperativeCron,
7894
+ imperativeLog,
7895
+ imperativeNotify,
7896
+ imperativeRequireRole,
8143
7897
  inState,
8144
7898
  inputEquals,
8145
7899
  inputRequired,
7900
+ instance,
8146
7901
  isActor,
7902
+ isActorConfig,
7903
+ isBuiltInConstraint,
7904
+ isConstraintDeclaration,
8147
7905
  isCreator,
8148
7906
  isOwner,
8149
7907
  isPlayerDebug,
@@ -8153,28 +7911,39 @@ var BrowserPlayer = class {
8153
7911
  loadExperienceWorkflow,
8154
7912
  logEvent,
8155
7913
  model,
7914
+ named,
8156
7915
  normalizeDefinition,
8157
7916
  not,
8158
7917
  notInState,
8159
7918
  notify,
7919
+ on,
8160
7920
  or,
7921
+ orchestration,
7922
+ patch,
8161
7923
  pipe,
8162
7924
  playerLog,
8163
7925
  prefetchData,
8164
7926
  refHasAnyRole,
8165
7927
  refHasRole,
8166
7928
  requireAuth,
7929
+ requireField,
8167
7930
  requireRole,
7931
+ resolveOrchestration,
7932
+ restrict,
8168
7933
  review,
7934
+ runtime,
7935
+ sendMessage,
8169
7936
  serverAction,
8170
7937
  setAuthResolver,
8171
7938
  setChannelTransport,
7939
+ setConfigContext,
8172
7940
  setExpressionLibraryResolver,
8173
7941
  setField,
8174
7942
  setFields,
8175
7943
  setInstalledModules,
8176
7944
  setModuleConfigDefaults,
8177
7945
  setMutationResolver,
7946
+ setPersistedModuleConfig,
8178
7947
  setPlayerDebug,
8179
7948
  setQueryResolver,
8180
7949
  setRealtimeQueryResolver,
@@ -8183,10 +7952,14 @@ var BrowserPlayer = class {
8183
7952
  setServerStateResolver,
8184
7953
  setViewResolver,
8185
7954
  spawn,
7955
+ spawnActor,
8186
7956
  sql,
8187
7957
  state,
7958
+ syncConfigDefaults,
8188
7959
  testModel,
7960
+ timeout,
8189
7961
  transition,
7962
+ updateDefinitionConfig,
8190
7963
  useAuth,
8191
7964
  useChannel,
8192
7965
  useCollection,
@@ -8204,6 +7977,7 @@ var BrowserPlayer = class {
8204
7977
  useModel,
8205
7978
  useModule,
8206
7979
  useModuleConfig,
7980
+ useModuleConfigWithMutation,
8207
7981
  useMutation,
8208
7982
  useNotification,
8209
7983
  useOnChange,
@@ -8216,6 +7990,7 @@ var BrowserPlayer = class {
8216
7990
  usePlayer,
8217
7991
  usePlayerContext,
8218
7992
  usePlayerContextSafe,
7993
+ usePresence,
8219
7994
  useQuery,
8220
7995
  useRealtimeQuery,
8221
7996
  useRole,
@@ -8228,20 +8003,30 @@ var BrowserPlayer = class {
8228
8003
  useToast,
8229
8004
  useTransition,
8230
8005
  useView,
8006
+ useVisibility,
8231
8007
  useWhileIn,
8232
8008
  useWorkflow,
8233
8009
  useWorkflowState,
8010
+ userAction,
8011
+ userChoice,
8012
+ validate,
8234
8013
  validateExperienceWorkflow,
8235
8014
  validateModel,
8015
+ visibleTo,
8236
8016
  when,
8017
+ withAuditLog,
8237
8018
  withAuditTrail,
8019
+ withAuth,
8020
+ withMetrics,
8238
8021
  withOwnership,
8239
8022
  withPagination,
8240
8023
  withRBAC,
8024
+ withRateLimit,
8241
8025
  withSearch,
8242
8026
  withSlug,
8243
8027
  withSoftDelete,
8244
8028
  withTags,
8245
8029
  withTimestamps,
8030
+ withValidation,
8246
8031
  withVersioning
8247
8032
  });