@mmapp/react 0.1.0-alpha.3 → 0.1.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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,19 +162,28 @@ __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,
@@ -166,10 +203,12 @@ __export(index_exports, {
166
203
  setServerStateResolver: () => setServerStateResolver,
167
204
  setViewResolver: () => setViewResolver,
168
205
  spawn: () => spawn,
206
+ spawnActor: () => spawnActor,
169
207
  sql: () => sql,
170
208
  state: () => state,
171
209
  syncConfigDefaults: () => syncConfigDefaults,
172
210
  testModel: () => testModel,
211
+ timeout: () => timeout,
173
212
  transition: () => transition,
174
213
  updateDefinitionConfig: () => updateDefinitionConfig,
175
214
  useAuth: () => useAuth,
@@ -202,6 +241,7 @@ __export(index_exports, {
202
241
  usePlayer: () => usePlayer,
203
242
  usePlayerContext: () => usePlayerContext,
204
243
  usePlayerContextSafe: () => usePlayerContextSafe,
244
+ usePresence: () => usePresence,
205
245
  useQuery: () => useQuery,
206
246
  useRealtimeQuery: () => useRealtimeQuery,
207
247
  useRole: () => useRole,
@@ -214,1113 +254,37 @@ __export(index_exports, {
214
254
  useToast: () => useToast,
215
255
  useTransition: () => useTransition,
216
256
  useView: () => useView,
257
+ useVisibility: () => useVisibility,
217
258
  useWhileIn: () => useWhileIn,
218
259
  useWorkflow: () => useWorkflow,
219
- useWorkflowState: () => useState20,
260
+ useWorkflowState: () => useState21,
261
+ userAction: () => userAction,
262
+ userChoice: () => userChoice,
263
+ validate: () => validate,
220
264
  validateExperienceWorkflow: () => validateExperienceWorkflow,
221
265
  validateModel: () => validateModel,
266
+ visibleTo: () => visibleTo,
222
267
  when: () => when,
268
+ withAuditLog: () => withAuditLog,
223
269
  withAuditTrail: () => withAuditTrail,
270
+ withAuth: () => withAuth,
271
+ withMetrics: () => withMetrics,
224
272
  withOwnership: () => withOwnership,
225
273
  withPagination: () => withPagination,
226
274
  withRBAC: () => withRBAC,
275
+ withRateLimit: () => withRateLimit,
227
276
  withSearch: () => withSearch,
228
277
  withSlug: () => withSlug,
229
278
  withSoftDelete: () => withSoftDelete,
230
279
  withTags: () => withTags,
231
280
  withTimestamps: () => withTimestamps,
281
+ withValidation: () => withValidation,
232
282
  withVersioning: () => withVersioning
233
283
  });
234
284
  module.exports = __toCommonJS(index_exports);
235
285
 
236
- // ../player-core/dist/index.mjs
237
- var add = {
238
- name: "add",
239
- fn: (a, b) => Number(a) + Number(b),
240
- arity: 2
241
- };
242
- var subtract = {
243
- name: "subtract",
244
- fn: (a, b) => Number(a) - Number(b),
245
- arity: 2
246
- };
247
- var multiply = {
248
- name: "multiply",
249
- fn: (a, b) => Number(a) * Number(b),
250
- arity: 2
251
- };
252
- var divide = {
253
- name: "divide",
254
- fn: (a, b) => {
255
- const d = Number(b);
256
- return d === 0 ? 0 : Number(a) / d;
257
- },
258
- arity: 2
259
- };
260
- var abs = {
261
- name: "abs",
262
- fn: (a) => Math.abs(Number(a)),
263
- arity: 1
264
- };
265
- var round = {
266
- name: "round",
267
- fn: (a, decimals) => {
268
- const d = decimals != null ? Number(decimals) : 0;
269
- const factor = Math.pow(10, d);
270
- return Math.round(Number(a) * factor) / factor;
271
- },
272
- arity: -1
273
- };
274
- var min = {
275
- name: "min",
276
- fn: (...args) => {
277
- const nums = args.flat().map(Number).filter((n) => !isNaN(n));
278
- return nums.length === 0 ? 0 : Math.min(...nums);
279
- },
280
- arity: -1
281
- };
282
- var max = {
283
- name: "max",
284
- fn: (...args) => {
285
- const nums = args.flat().map(Number).filter((n) => !isNaN(n));
286
- return nums.length === 0 ? 0 : Math.max(...nums);
287
- },
288
- arity: -1
289
- };
290
- var eq = {
291
- name: "eq",
292
- fn: (a, b) => a === b || String(a) === String(b),
293
- arity: 2
294
- };
295
- var neq = {
296
- name: "neq",
297
- fn: (a, b) => a !== b && String(a) !== String(b),
298
- arity: 2
299
- };
300
- var gt = {
301
- name: "gt",
302
- fn: (a, b) => Number(a) > Number(b),
303
- arity: 2
304
- };
305
- var gte = {
306
- name: "gte",
307
- fn: (a, b) => Number(a) >= Number(b),
308
- arity: 2
309
- };
310
- var lt = {
311
- name: "lt",
312
- fn: (a, b) => Number(a) < Number(b),
313
- arity: 2
314
- };
315
- var lte = {
316
- name: "lte",
317
- fn: (a, b) => Number(a) <= Number(b),
318
- arity: 2
319
- };
320
- var if_fn = {
321
- name: "if",
322
- fn: (cond, then, else_) => cond ? then : else_,
323
- arity: 3
324
- };
325
- var and = {
326
- name: "and",
327
- fn: (...args) => args.every(Boolean),
328
- arity: -1
329
- };
330
- var or = {
331
- name: "or",
332
- fn: (...args) => args.some(Boolean),
333
- arity: -1
334
- };
335
- var not = {
336
- name: "not",
337
- fn: (a) => !a,
338
- arity: 1
339
- };
340
- var coalesce = {
341
- name: "coalesce",
342
- fn: (...args) => {
343
- for (const arg of args) {
344
- if (arg != null) return arg;
345
- }
346
- return null;
347
- },
348
- arity: -1
349
- };
350
- var concat = {
351
- name: "concat",
352
- fn: (...args) => args.map(String).join(""),
353
- arity: -1
354
- };
355
- var upper = {
356
- name: "upper",
357
- fn: (s) => String(s ?? "").toUpperCase(),
358
- arity: 1
359
- };
360
- var lower = {
361
- name: "lower",
362
- fn: (s) => String(s ?? "").toLowerCase(),
363
- arity: 1
364
- };
365
- var trim = {
366
- name: "trim",
367
- fn: (s) => String(s ?? "").trim(),
368
- arity: 1
369
- };
370
- var format = {
371
- name: "format",
372
- fn: (template, ...args) => {
373
- let result = String(template ?? "");
374
- args.forEach((arg, i) => {
375
- result = result.replace(`{${i}}`, String(arg ?? ""));
376
- });
377
- return result;
378
- },
379
- arity: -1
380
- };
381
- var length = {
382
- name: "length",
383
- fn: (v) => {
384
- if (Array.isArray(v)) return v.length;
385
- if (typeof v === "string") return v.length;
386
- if (v && typeof v === "object") return Object.keys(v).length;
387
- return 0;
388
- },
389
- arity: 1
390
- };
391
- var get = {
392
- name: "get",
393
- fn: (obj, path) => {
394
- if (obj == null || typeof path !== "string") return void 0;
395
- const parts = path.split(".");
396
- let current = obj;
397
- for (const part of parts) {
398
- if (current == null || typeof current !== "object") return void 0;
399
- current = current[part];
400
- }
401
- return current;
402
- },
403
- arity: 2
404
- };
405
- var includes = {
406
- name: "includes",
407
- fn: (collection, value) => {
408
- if (Array.isArray(collection)) return collection.includes(value);
409
- if (typeof collection === "string") return collection.includes(String(value));
410
- return false;
411
- },
412
- arity: 2
413
- };
414
- var is_defined = {
415
- name: "is_defined",
416
- fn: (v) => v !== void 0 && v !== null,
417
- arity: 1
418
- };
419
- var is_empty = {
420
- name: "is_empty",
421
- fn: (v) => {
422
- if (v == null) return true;
423
- if (typeof v === "string") return v.length === 0;
424
- if (Array.isArray(v)) return v.length === 0;
425
- if (typeof v === "object") return Object.keys(v).length === 0;
426
- return false;
427
- },
428
- arity: 1
429
- };
430
- var is_null = {
431
- name: "is_null",
432
- fn: (v) => v === null || v === void 0,
433
- arity: 1
434
- };
435
- var to_string = {
436
- name: "to_string",
437
- fn: (v) => {
438
- if (v == null) return "";
439
- if (typeof v === "object") return JSON.stringify(v);
440
- return String(v);
441
- },
442
- arity: 1
443
- };
444
- var CORE_FUNCTIONS = [
445
- // Math (8)
446
- add,
447
- subtract,
448
- multiply,
449
- divide,
450
- abs,
451
- round,
452
- min,
453
- max,
454
- // Comparison (6)
455
- eq,
456
- neq,
457
- gt,
458
- gte,
459
- lt,
460
- lte,
461
- // Logic (5)
462
- if_fn,
463
- and,
464
- or,
465
- not,
466
- coalesce,
467
- // String (6)
468
- concat,
469
- upper,
470
- lower,
471
- trim,
472
- format,
473
- length,
474
- // Path (3)
475
- get,
476
- includes,
477
- is_defined,
478
- // Type (3)
479
- is_empty,
480
- is_null,
481
- to_string
482
- ];
483
- function buildFunctionMap(functions) {
484
- const map = /* @__PURE__ */ new Map();
485
- for (const fn of functions) {
486
- map.set(fn.name, fn.fn);
487
- }
488
- return map;
489
- }
490
- var MAX_DEPTH = 50;
491
- var Parser = class {
492
- pos = 0;
493
- depth = 0;
494
- input;
495
- constructor(input) {
496
- this.input = input;
497
- }
498
- parse() {
499
- this.skipWhitespace();
500
- const node = this.parseExpression();
501
- this.skipWhitespace();
502
- if (this.pos < this.input.length) {
503
- throw new Error(`Unexpected character at position ${this.pos}: '${this.input[this.pos]}'`);
504
- }
505
- return node;
506
- }
507
- guardDepth() {
508
- if (++this.depth > MAX_DEPTH) {
509
- throw new Error("Expression too deeply nested");
510
- }
511
- }
512
- parseExpression() {
513
- this.guardDepth();
514
- try {
515
- return this.parseTernary();
516
- } finally {
517
- this.depth--;
518
- }
519
- }
520
- parseTernary() {
521
- let node = this.parseLogicalOr();
522
- this.skipWhitespace();
523
- if (this.peek() === "?") {
524
- this.advance();
525
- const consequent = this.parseExpression();
526
- this.skipWhitespace();
527
- this.expect(":");
528
- const alternate = this.parseExpression();
529
- node = { type: "ternary", condition: node, consequent, alternate };
530
- }
531
- return node;
532
- }
533
- parseLogicalOr() {
534
- let left = this.parseLogicalAnd();
535
- this.skipWhitespace();
536
- while (this.match("||")) {
537
- const right = this.parseLogicalAnd();
538
- left = { type: "binary", operator: "||", left, right };
539
- this.skipWhitespace();
540
- }
541
- return left;
542
- }
543
- parseLogicalAnd() {
544
- let left = this.parseEquality();
545
- this.skipWhitespace();
546
- while (this.match("&&")) {
547
- const right = this.parseEquality();
548
- left = { type: "binary", operator: "&&", left, right };
549
- this.skipWhitespace();
550
- }
551
- return left;
552
- }
553
- parseEquality() {
554
- let left = this.parseComparison();
555
- this.skipWhitespace();
556
- while (true) {
557
- if (this.match("==")) {
558
- const right = this.parseComparison();
559
- left = { type: "binary", operator: "==", left, right };
560
- } else if (this.match("!=")) {
561
- const right = this.parseComparison();
562
- left = { type: "binary", operator: "!=", left, right };
563
- } else {
564
- break;
565
- }
566
- this.skipWhitespace();
567
- }
568
- return left;
569
- }
570
- parseComparison() {
571
- let left = this.parseUnary();
572
- this.skipWhitespace();
573
- while (true) {
574
- if (this.match(">=")) {
575
- const right = this.parseUnary();
576
- left = { type: "binary", operator: ">=", left, right };
577
- } else if (this.match("<=")) {
578
- const right = this.parseUnary();
579
- left = { type: "binary", operator: "<=", left, right };
580
- } else if (this.peek() === ">" && !this.lookAhead(">=")) {
581
- this.advance();
582
- const right = this.parseUnary();
583
- left = { type: "binary", operator: ">", left, right };
584
- } else if (this.peek() === "<" && !this.lookAhead("<=")) {
585
- this.advance();
586
- const right = this.parseUnary();
587
- left = { type: "binary", operator: "<", left, right };
588
- } else {
589
- break;
590
- }
591
- this.skipWhitespace();
592
- }
593
- return left;
594
- }
595
- parseUnary() {
596
- this.skipWhitespace();
597
- if (this.peek() === "!") {
598
- this.advance();
599
- const operand = this.parseUnary();
600
- return { type: "unary", operator: "!", operand };
601
- }
602
- if (this.peek() === "-") {
603
- const nextChar = this.input[this.pos + 1];
604
- if (nextChar !== void 0 && (nextChar >= "0" && nextChar <= "9" || nextChar === ".")) {
605
- return this.parseCallChain();
606
- }
607
- }
608
- return this.parseCallChain();
609
- }
610
- parseCallChain() {
611
- let node = this.parsePrimary();
612
- while (true) {
613
- this.skipWhitespace();
614
- if (this.peek() === "(") {
615
- this.advance();
616
- const args = this.parseArgList();
617
- this.expect(")");
618
- if (node.type === "identifier") {
619
- node = { type: "call", name: node.name, args };
620
- } else if (node.type === "path") {
621
- const name = node.segments.join(".");
622
- node = { type: "call", name, args };
623
- } else if (node.type === "member") {
624
- node = { type: "method_call", object: node.object, method: node.property, args };
625
- } else {
626
- throw new Error("Cannot call non-function");
627
- }
628
- } else if (this.peek() === ".") {
629
- this.advance();
630
- const prop = this.parseIdentifierName();
631
- node = { type: "member", object: node, property: prop };
632
- } else {
633
- break;
634
- }
635
- }
636
- return node;
637
- }
638
- parsePrimary() {
639
- this.skipWhitespace();
640
- const ch = this.peek();
641
- if (ch === "(") {
642
- this.advance();
643
- const expr2 = this.parseExpression();
644
- this.skipWhitespace();
645
- this.expect(")");
646
- return expr2;
647
- }
648
- if (ch === "'" || ch === '"') {
649
- return this.parseString();
650
- }
651
- if (ch === "-" || ch >= "0" && ch <= "9") {
652
- return this.parseNumber();
653
- }
654
- if (this.isIdentStart(ch)) {
655
- return this.parseIdentifierOrPath();
656
- }
657
- throw new Error(
658
- `Unexpected character at position ${this.pos}: '${ch || "EOF"}'`
659
- );
660
- }
661
- parseString() {
662
- const quote = this.advance();
663
- let value = "";
664
- while (this.pos < this.input.length && this.peek() !== quote) {
665
- if (this.peek() === "\\") {
666
- this.advance();
667
- const esc = this.advance();
668
- if (esc === "n") value += "\n";
669
- else if (esc === "t") value += " ";
670
- else if (esc === "r") value += "\r";
671
- else value += esc;
672
- } else {
673
- value += this.advance();
674
- }
675
- }
676
- if (this.pos >= this.input.length) {
677
- throw new Error("Unterminated string literal");
678
- }
679
- this.advance();
680
- return { type: "string", value };
681
- }
682
- parseNumber() {
683
- let numStr = "";
684
- if (this.peek() === "-") {
685
- numStr += this.advance();
686
- }
687
- while (this.pos < this.input.length && (this.input[this.pos] >= "0" && this.input[this.pos] <= "9")) {
688
- numStr += this.advance();
689
- }
690
- if (this.peek() === "." && this.pos + 1 < this.input.length && this.input[this.pos + 1] >= "0" && this.input[this.pos + 1] <= "9") {
691
- numStr += this.advance();
692
- while (this.pos < this.input.length && (this.input[this.pos] >= "0" && this.input[this.pos] <= "9")) {
693
- numStr += this.advance();
694
- }
695
- }
696
- return { type: "number", value: Number(numStr) };
697
- }
698
- parseIdentifierOrPath() {
699
- const name = this.parseIdentifierName();
700
- if (name === "true") return { type: "boolean", value: true };
701
- if (name === "false") return { type: "boolean", value: false };
702
- if (name === "null") return { type: "null" };
703
- if (name === "undefined") return { type: "null" };
704
- return { type: "identifier", name };
705
- }
706
- parseIdentifierName() {
707
- let name = "";
708
- if (this.peek() === "$") name += this.advance();
709
- while (this.pos < this.input.length && this.isIdentPart(this.input[this.pos])) {
710
- name += this.advance();
711
- }
712
- if (!name) {
713
- throw new Error(`Expected identifier at position ${this.pos}`);
714
- }
715
- return name;
716
- }
717
- parseArgList() {
718
- this.skipWhitespace();
719
- if (this.peek() === ")") return [];
720
- const args = [];
721
- args.push(this.parseExpression());
722
- this.skipWhitespace();
723
- while (this.peek() === ",") {
724
- this.advance();
725
- args.push(this.parseExpression());
726
- this.skipWhitespace();
727
- }
728
- return args;
729
- }
730
- // Character utilities
731
- peek() {
732
- return this.input[this.pos] ?? "";
733
- }
734
- advance() {
735
- return this.input[this.pos++] ?? "";
736
- }
737
- match(str) {
738
- if (this.input.startsWith(str, this.pos)) {
739
- this.pos += str.length;
740
- return true;
741
- }
742
- return false;
743
- }
744
- lookAhead(str) {
745
- return this.input.startsWith(str, this.pos);
746
- }
747
- expect(ch) {
748
- this.skipWhitespace();
749
- if (this.peek() !== ch) {
750
- throw new Error(`Expected '${ch}' at position ${this.pos}, got '${this.peek() || "EOF"}'`);
751
- }
752
- this.advance();
753
- }
754
- skipWhitespace() {
755
- while (this.pos < this.input.length && " \n\r".includes(this.input[this.pos])) {
756
- this.pos++;
757
- }
758
- }
759
- isIdentStart(ch) {
760
- return ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch === "_" || ch === "$";
761
- }
762
- isIdentPart(ch) {
763
- return this.isIdentStart(ch) || ch >= "0" && ch <= "9";
764
- }
765
- };
766
- function evaluateAST(node, context, fnMap) {
767
- switch (node.type) {
768
- case "number":
769
- return node.value;
770
- case "string":
771
- return node.value;
772
- case "boolean":
773
- return node.value;
774
- case "null":
775
- return null;
776
- case "identifier":
777
- return resolvePath(node.name, context);
778
- case "path":
779
- return resolvePath(node.segments.join("."), context);
780
- case "member": {
781
- const obj = evaluateAST(node.object, context, fnMap);
782
- if (obj == null || typeof obj !== "object") return void 0;
783
- return obj[node.property];
784
- }
785
- case "call": {
786
- const fn = fnMap.get(node.name);
787
- if (!fn) return void 0;
788
- const args = node.args.map((a) => evaluateAST(a, context, fnMap));
789
- return fn(...args);
790
- }
791
- case "method_call": {
792
- const obj = evaluateAST(node.object, context, fnMap);
793
- if (obj != null && typeof obj === "object") {
794
- const method = obj[node.method];
795
- if (typeof method === "function") {
796
- const args = node.args.map((a) => evaluateAST(a, context, fnMap));
797
- return method.apply(obj, args);
798
- }
799
- }
800
- return void 0;
801
- }
802
- case "unary": {
803
- const operand = evaluateAST(node.operand, context, fnMap);
804
- return !operand;
805
- }
806
- case "binary": {
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
- if (node.operator === "||") {
813
- const left2 = evaluateAST(node.left, context, fnMap);
814
- if (left2) return left2;
815
- return evaluateAST(node.right, context, fnMap);
816
- }
817
- const left = evaluateAST(node.left, context, fnMap);
818
- const right = evaluateAST(node.right, context, fnMap);
819
- switch (node.operator) {
820
- // eslint-disable-next-line eqeqeq
821
- case "==":
822
- return left == right;
823
- // eslint-disable-next-line eqeqeq
824
- case "!=":
825
- return left != right;
826
- case ">":
827
- return Number(left) > Number(right);
828
- case "<":
829
- return Number(left) < Number(right);
830
- case ">=":
831
- return Number(left) >= Number(right);
832
- case "<=":
833
- return Number(left) <= Number(right);
834
- default:
835
- return void 0;
836
- }
837
- }
838
- case "ternary": {
839
- const condition = evaluateAST(node.condition, context, fnMap);
840
- return condition ? evaluateAST(node.consequent, context, fnMap) : evaluateAST(node.alternate, context, fnMap);
841
- }
842
- }
843
- }
844
- var MAX_CACHE = 500;
845
- var astCache = /* @__PURE__ */ new Map();
846
- function evictIfNeeded() {
847
- if (astCache.size > MAX_CACHE) {
848
- const keys = Array.from(astCache.keys());
849
- const evictCount = Math.floor(MAX_CACHE * 0.25);
850
- for (let i = 0; i < evictCount; i++) {
851
- astCache.delete(keys[i]);
852
- }
853
- }
854
- }
855
- function parseAndCache(expr2) {
856
- const cached = astCache.get(expr2);
857
- if (cached) return cached;
858
- const parser = new Parser(expr2);
859
- const ast = parser.parse();
860
- astCache.set(expr2, ast);
861
- evictIfNeeded();
862
- return ast;
863
- }
864
- var TEMPLATE_RE = /\{\{(.+?)\}\}/g;
865
- function resolvePath(path, context) {
866
- const parts = path.split(".");
867
- let current = context;
868
- for (const part of parts) {
869
- if (current == null || typeof current !== "object") return void 0;
870
- current = current[part];
871
- }
872
- return current;
873
- }
874
- function evaluateExpression(expr2, context, fnMap) {
875
- const trimmed = expr2.trim();
876
- if (trimmed === "true") return true;
877
- if (trimmed === "false") return false;
878
- if (trimmed === "null") return null;
879
- if (trimmed === "undefined") return void 0;
880
- const num = Number(trimmed);
881
- if (!isNaN(num) && trimmed !== "") return num;
882
- if (trimmed.startsWith("'") && trimmed.endsWith("'") || trimmed.startsWith('"') && trimmed.endsWith('"')) {
883
- return trimmed.slice(1, -1);
884
- }
885
- if (/^[a-zA-Z_$][\w$.]*$/.test(trimmed)) {
886
- return resolvePath(trimmed, context);
887
- }
888
- const ast = parseAndCache(trimmed);
889
- return evaluateAST(ast, context, fnMap);
890
- }
891
- var WEB_FAILURE_POLICIES = {
892
- VIEW_BINDING: {
893
- on_error: "return_fallback",
894
- fallback_value: "",
895
- log_level: "warn"
896
- },
897
- EVENT_REACTION: {
898
- on_error: "log_and_skip",
899
- fallback_value: void 0,
900
- log_level: "error"
901
- },
902
- DURING_ACTION: {
903
- on_error: "log_and_skip",
904
- fallback_value: void 0,
905
- log_level: "error"
906
- },
907
- CONDITIONAL_VISIBILITY: {
908
- on_error: "return_fallback",
909
- fallback_value: true,
910
- // Show by default if condition fails
911
- log_level: "warn"
912
- }
913
- };
914
- function createEvaluator(config) {
915
- const allFunctions = [...CORE_FUNCTIONS, ...config.functions];
916
- const fnMap = buildFunctionMap(allFunctions);
917
- const policy = config.failurePolicy;
918
- function handleError(expr2, error) {
919
- const message = error instanceof Error ? error.message : String(error);
920
- if (policy.log_level === "error") {
921
- console.error(`[player-core] Expression error: "${expr2}" \u2014 ${message}`);
922
- } else if (policy.log_level === "warn") {
923
- console.warn(`[player-core] Expression error: "${expr2}" \u2014 ${message}`);
924
- }
925
- switch (policy.on_error) {
926
- case "throw":
927
- throw error;
928
- case "return_fallback":
929
- return { value: policy.fallback_value, status: "fallback", error: message };
930
- case "log_and_skip":
931
- default:
932
- return { value: policy.fallback_value, status: "error", error: message };
933
- }
934
- }
935
- return {
936
- evaluate(expression, context) {
937
- try {
938
- const value = evaluateExpression(expression, context, fnMap);
939
- return { value, status: "ok" };
940
- } catch (error) {
941
- return handleError(expression, error);
942
- }
943
- },
944
- evaluateTemplate(template, context) {
945
- try {
946
- if (!template.includes("{{")) {
947
- return { value: template, status: "ok" };
948
- }
949
- const result = template.replace(TEMPLATE_RE, (_match, expr2) => {
950
- const value = evaluateExpression(expr2, context, fnMap);
951
- return value != null ? String(value) : "";
952
- });
953
- return { value: result, status: "ok" };
954
- } catch (error) {
955
- return handleError(template, error);
956
- }
957
- },
958
- validate(expression) {
959
- const errors = [];
960
- try {
961
- parseAndCache(expression);
962
- } catch (e) {
963
- errors.push(e instanceof Error ? e.message : String(e));
964
- }
965
- return { valid: errors.length === 0, errors };
966
- }
967
- };
968
- }
969
- var MAX_AUTO_CHAIN = 10;
970
- var StateMachine = class {
971
- evaluator;
972
- actionHandlers;
973
- listeners = /* @__PURE__ */ new Set();
974
- instance;
975
- constructor(definition, initialData = {}, config) {
976
- this.evaluator = config.evaluator;
977
- this.actionHandlers = config.actionHandlers ?? /* @__PURE__ */ new Map();
978
- const startState = definition.states.find((s) => s.type === "START");
979
- if (!startState) {
980
- throw new Error(`No START state found in definition ${definition.slug}`);
981
- }
982
- this.instance = {
983
- definition,
984
- current_state: startState.name,
985
- state_data: { ...initialData },
986
- memory: {},
987
- status: "ACTIVE"
988
- };
989
- }
990
- /** Get the current instance snapshot (immutable copy) */
991
- getSnapshot() {
992
- return { ...this.instance, state_data: { ...this.instance.state_data }, memory: { ...this.instance.memory } };
993
- }
994
- /** Get current state name */
995
- get currentState() {
996
- return this.instance.current_state;
997
- }
998
- /** Get current state_data */
999
- get stateData() {
1000
- return this.instance.state_data;
1001
- }
1002
- /** Get current status */
1003
- get status() {
1004
- return this.instance.status;
1005
- }
1006
- /** Subscribe to state machine events */
1007
- on(listener) {
1008
- this.listeners.add(listener);
1009
- return () => this.listeners.delete(listener);
1010
- }
1011
- /** Register an action handler */
1012
- registerAction(type, handler) {
1013
- this.actionHandlers.set(type, handler);
1014
- }
1015
- /** Execute a named transition */
1016
- async transition(transitionName, data) {
1017
- if (this.instance.status !== "ACTIVE") {
1018
- return {
1019
- success: false,
1020
- from_state: this.instance.current_state,
1021
- to_state: this.instance.current_state,
1022
- actions_executed: [],
1023
- error: `Cannot transition: instance status is ${this.instance.status}`
1024
- };
1025
- }
1026
- const transition2 = this.instance.definition.transitions.find(
1027
- (t) => t.name === transitionName && t.from.includes(this.instance.current_state)
1028
- );
1029
- if (!transition2) {
1030
- return {
1031
- success: false,
1032
- from_state: this.instance.current_state,
1033
- to_state: this.instance.current_state,
1034
- actions_executed: [],
1035
- error: `Transition "${transitionName}" not valid from state "${this.instance.current_state}"`
1036
- };
1037
- }
1038
- if (data) {
1039
- this.instance.state_data = { ...this.instance.state_data, ...data };
1040
- }
1041
- if (transition2.conditions && transition2.conditions.length > 0) {
1042
- const ctx = this.buildContext();
1043
- for (const condition of transition2.conditions) {
1044
- const result2 = this.evaluator.evaluate(condition, ctx);
1045
- if (!result2.value) {
1046
- return {
1047
- success: false,
1048
- from_state: this.instance.current_state,
1049
- to_state: this.instance.current_state,
1050
- actions_executed: [],
1051
- error: `Transition condition not met: ${condition}`
1052
- };
1053
- }
1054
- }
1055
- }
1056
- const result = await this.executeTransition(transition2);
1057
- if (result.success) {
1058
- await this.drainAutoTransitions();
1059
- }
1060
- return result;
1061
- }
1062
- /** Update state_data directly (for on_event set_field actions) */
1063
- setField(field2, value) {
1064
- this.instance.state_data = { ...this.instance.state_data, [field2]: value };
1065
- }
1066
- /** Update memory */
1067
- setMemory(key, value) {
1068
- this.instance.memory = { ...this.instance.memory, [key]: value };
1069
- }
1070
- /** Get available transitions from the current state */
1071
- getAvailableTransitions() {
1072
- return this.instance.definition.transitions.filter(
1073
- (t) => t.from.includes(this.instance.current_state) && !t.auto
1074
- );
1075
- }
1076
- /** Get the current state definition */
1077
- getCurrentStateDefinition() {
1078
- return this.instance.definition.states.find((s) => s.name === this.instance.current_state);
1079
- }
1080
- // ===========================================================================
1081
- // Private implementation
1082
- // ===========================================================================
1083
- async executeTransition(transition2) {
1084
- const fromState = this.instance.current_state;
1085
- const allActionsExecuted = [];
1086
- const fromStateDef = this.getCurrentStateDefinition();
1087
- if (fromStateDef?.on_exit) {
1088
- await this.executeActions(fromStateDef.on_exit, allActionsExecuted);
1089
- }
1090
- this.emit({
1091
- type: "state_exit",
1092
- instance_id: this.instance.definition.id,
1093
- from_state: fromState
1094
- });
1095
- if (transition2.actions) {
1096
- await this.executeActions(transition2.actions, allActionsExecuted);
1097
- }
1098
- this.instance.current_state = transition2.to;
1099
- const toStateDef = this.instance.definition.states.find((s) => s.name === transition2.to);
1100
- if (toStateDef?.type === "END") {
1101
- this.instance.status = "COMPLETED";
1102
- } else if (toStateDef?.type === "CANCELLED") {
1103
- this.instance.status = "CANCELLED";
1104
- }
1105
- this.emit({
1106
- type: "state_enter",
1107
- instance_id: this.instance.definition.id,
1108
- to_state: transition2.to
1109
- });
1110
- if (toStateDef?.on_enter) {
1111
- await this.executeActions(toStateDef.on_enter, allActionsExecuted);
1112
- }
1113
- this.emit({
1114
- type: "transition",
1115
- instance_id: this.instance.definition.id,
1116
- from_state: fromState,
1117
- to_state: transition2.to
1118
- });
1119
- return {
1120
- success: true,
1121
- from_state: fromState,
1122
- to_state: transition2.to,
1123
- actions_executed: allActionsExecuted
1124
- };
1125
- }
1126
- async drainAutoTransitions() {
1127
- for (let depth = 0; depth < MAX_AUTO_CHAIN; depth++) {
1128
- if (this.instance.status !== "ACTIVE") break;
1129
- const autoTransition = this.findMatchingAutoTransition();
1130
- if (!autoTransition) break;
1131
- const result = await this.executeTransition(autoTransition);
1132
- if (!result.success) break;
1133
- }
1134
- }
1135
- findMatchingAutoTransition() {
1136
- const candidates = this.instance.definition.transitions.filter(
1137
- (t) => t.auto && t.from.includes(this.instance.current_state)
1138
- );
1139
- const ctx = this.buildContext();
1140
- for (const candidate of candidates) {
1141
- if (!candidate.conditions || candidate.conditions.length === 0) {
1142
- return candidate;
1143
- }
1144
- const allMet = candidate.conditions.every((condition) => {
1145
- const result = this.evaluator.evaluate(condition, ctx);
1146
- return result.value === true;
1147
- });
1148
- if (allMet) return candidate;
1149
- }
1150
- return null;
1151
- }
1152
- async executeActions(actions, collector) {
1153
- const ctx = this.buildContext();
1154
- for (const action2 of actions) {
1155
- if (action2.condition) {
1156
- const condResult = this.evaluator.evaluate(action2.condition, ctx);
1157
- if (!condResult.value) continue;
1158
- }
1159
- const handler = this.actionHandlers.get(action2.type);
1160
- if (handler) {
1161
- try {
1162
- await handler(action2, ctx);
1163
- collector.push(action2);
1164
- this.emit({
1165
- type: "action_executed",
1166
- instance_id: this.instance.definition.id,
1167
- action: action2
1168
- });
1169
- } catch (error) {
1170
- this.emit({
1171
- type: "error",
1172
- instance_id: this.instance.definition.id,
1173
- action: action2,
1174
- error: error instanceof Error ? error.message : String(error)
1175
- });
1176
- }
1177
- }
1178
- }
1179
- }
1180
- buildContext() {
1181
- return {
1182
- state_data: this.instance.state_data,
1183
- memory: this.instance.memory,
1184
- current_state: this.instance.current_state,
1185
- status: this.instance.status,
1186
- // Spread state_data for direct field access (e.g., "title" instead of "state_data.title")
1187
- ...this.instance.state_data
1188
- };
1189
- }
1190
- emit(event) {
1191
- for (const listener of this.listeners) {
1192
- try {
1193
- listener(event);
1194
- } catch {
1195
- }
1196
- }
1197
- }
1198
- };
1199
- var patternCache = /* @__PURE__ */ new Map();
1200
- var MAX_CACHE2 = 200;
1201
- function compilePattern(pattern) {
1202
- const cached = patternCache.get(pattern);
1203
- if (cached) return cached;
1204
- const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "<<DOUBLESTAR>>").replace(/\*/g, "[^:.]+").replace(/<<DOUBLESTAR>>/g, ".*");
1205
- const regex = new RegExp(`^${escaped}$`);
1206
- if (patternCache.size >= MAX_CACHE2) {
1207
- const firstKey = patternCache.keys().next().value;
1208
- if (firstKey) patternCache.delete(firstKey);
1209
- }
1210
- patternCache.set(pattern, regex);
1211
- return regex;
1212
- }
1213
- function matchTopic(pattern, topic) {
1214
- return pattern.test(topic);
1215
- }
1216
- var EventBus = class {
1217
- subscriptions = [];
1218
- /**
1219
- * Subscribe to events matching a glob pattern.
1220
- * Returns an unsubscribe function.
1221
- */
1222
- subscribe(pattern, handler) {
1223
- const regex = compilePattern(pattern);
1224
- const subscription = { pattern, regex, handler };
1225
- this.subscriptions.push(subscription);
1226
- return () => {
1227
- const idx = this.subscriptions.indexOf(subscription);
1228
- if (idx !== -1) this.subscriptions.splice(idx, 1);
1229
- };
1230
- }
1231
- /**
1232
- * Publish an event. All matching subscriptions fire (async).
1233
- * Errors in handlers are caught and logged, never propagated.
1234
- */
1235
- async publish(topic, payload = {}) {
1236
- const event = { topic, payload };
1237
- for (const sub of this.subscriptions) {
1238
- if (matchTopic(sub.regex, topic)) {
1239
- try {
1240
- await sub.handler(event);
1241
- } catch (error) {
1242
- console.warn(
1243
- `[player-core] Event handler error for pattern "${sub.pattern}" on topic "${topic}":`,
1244
- error
1245
- );
1246
- }
1247
- }
1248
- }
1249
- }
1250
- /**
1251
- * Publish synchronously (fire-and-forget).
1252
- * Useful when you don't need to await handler completion.
1253
- */
1254
- emit(topic, payload = {}) {
1255
- void this.publish(topic, payload);
1256
- }
1257
- /** Get count of active subscriptions */
1258
- get size() {
1259
- return this.subscriptions.length;
1260
- }
1261
- /** Remove all subscriptions */
1262
- clear() {
1263
- this.subscriptions.length = 0;
1264
- }
1265
- };
1266
- var ActionDispatcher = class {
1267
- handlers = /* @__PURE__ */ new Map();
1268
- /** Register a handler for an action type */
1269
- register(type, handler) {
1270
- this.handlers.set(type, handler);
1271
- }
1272
- /** Unregister a handler */
1273
- unregister(type) {
1274
- this.handlers.delete(type);
1275
- }
1276
- /** Check if a handler is registered for the given type */
1277
- has(type) {
1278
- return this.handlers.has(type);
1279
- }
1280
- /**
1281
- * Execute a list of actions sequentially.
1282
- * Each action's condition is evaluated first (if present).
1283
- * Missing handlers are skipped with a warning.
1284
- */
1285
- async execute(actions, context, evaluator) {
1286
- const results = [];
1287
- for (const action2 of actions) {
1288
- if (action2.condition && evaluator) {
1289
- const condResult = evaluator.evaluate(action2.condition, context);
1290
- if (!condResult.value) continue;
1291
- }
1292
- const handler = this.handlers.get(action2.type);
1293
- if (!handler) {
1294
- console.warn(`[player-core] No handler registered for action type "${action2.type}" \u2014 unsupported action`);
1295
- results.push({ type: action2.type, success: false, error: `unsupported action: "${action2.type}"` });
1296
- continue;
1297
- }
1298
- try {
1299
- await handler(action2.config, context);
1300
- results.push({ type: action2.type, success: true });
1301
- } catch (error) {
1302
- const message = error instanceof Error ? error.message : String(error);
1303
- console.warn(`[player-core] Action "${action2.type}" failed: ${message}`);
1304
- results.push({ type: action2.type, success: false, error: message });
1305
- }
1306
- }
1307
- return results;
1308
- }
1309
- /** Get count of registered handlers */
1310
- get size() {
1311
- return this.handlers.size;
1312
- }
1313
- /** Get all registered action type names */
1314
- getRegisteredTypes() {
1315
- return Array.from(this.handlers.keys());
1316
- }
1317
- /** Remove all handlers */
1318
- clear() {
1319
- this.handlers.clear();
1320
- }
1321
- };
1322
-
1323
286
  // src/core/WorkflowRuntime.ts
287
+ var import_player_core = require("@mmapp/player-core");
1324
288
  var WorkflowRuntime = class {
1325
289
  sm;
1326
290
  eventBus;
@@ -1328,9 +292,9 @@ var WorkflowRuntime = class {
1328
292
  evaluator;
1329
293
  listeners = /* @__PURE__ */ new Set();
1330
294
  constructor(config) {
1331
- this.evaluator = createEvaluator({
295
+ this.evaluator = (0, import_player_core.createEvaluator)({
1332
296
  functions: [],
1333
- failurePolicy: WEB_FAILURE_POLICIES.EVENT_REACTION
297
+ failurePolicy: import_player_core.WEB_FAILURE_POLICIES.EVENT_REACTION
1334
298
  });
1335
299
  const actionHandlers = /* @__PURE__ */ new Map();
1336
300
  if (config.actionHandlers) {
@@ -1352,14 +316,14 @@ var WorkflowRuntime = class {
1352
316
  smRef.setMemory(action2.config.key, action2.config.value);
1353
317
  }
1354
318
  });
1355
- this.sm = new StateMachine(
319
+ this.sm = new import_player_core.StateMachine(
1356
320
  config.definition,
1357
321
  config.initialData ?? {},
1358
322
  { evaluator: this.evaluator, actionHandlers }
1359
323
  );
1360
324
  smRef = this.sm;
1361
- this.eventBus = new EventBus();
1362
- this.dispatcher = new ActionDispatcher();
325
+ this.eventBus = new import_player_core.EventBus();
326
+ this.dispatcher = new import_player_core.ActionDispatcher();
1363
327
  this.dispatcher.register("set_field", (cfg) => {
1364
328
  if (smRef && typeof cfg.field === "string") {
1365
329
  smRef.setField(cfg.field, cfg.value);
@@ -1419,24 +383,24 @@ var import_react2 = require("react");
1419
383
  var import_react = require("react");
1420
384
  var RuntimeContext = (0, import_react.createContext)(null);
1421
385
  function useRuntimeContext() {
1422
- const runtime = (0, import_react.useContext)(RuntimeContext);
1423
- if (!runtime) {
386
+ const runtime2 = (0, import_react.useContext)(RuntimeContext);
387
+ if (!runtime2) {
1424
388
  throw new Error(
1425
389
  "useRuntimeContext must be used within a WorkflowProvider or RuntimeContext.Provider"
1426
390
  );
1427
391
  }
1428
- return runtime;
392
+ return runtime2;
1429
393
  }
1430
394
 
1431
395
  // src/hooks/useOnEnter.ts
1432
396
  function useOnEnter(stateName, effect) {
1433
- const runtime = useRuntimeContext();
397
+ const runtime2 = useRuntimeContext();
1434
398
  const effectRef = (0, import_react2.useRef)(effect);
1435
399
  effectRef.current = effect;
1436
400
  const cleanupRef = (0, import_react2.useRef)(null);
1437
401
  const states = Array.isArray(stateName) ? stateName : [stateName];
1438
402
  (0, import_react2.useEffect)(() => {
1439
- if (states.includes(runtime.sm.currentState)) {
403
+ if (states.includes(runtime2.sm.currentState)) {
1440
404
  const result = effectRef.current();
1441
405
  if (result instanceof Promise) {
1442
406
  result.then((cleanup) => {
@@ -1446,7 +410,7 @@ function useOnEnter(stateName, effect) {
1446
410
  cleanupRef.current = result;
1447
411
  }
1448
412
  }
1449
- const unsub = runtime.sm.on((event) => {
413
+ const unsub = runtime2.sm.on((event) => {
1450
414
  if (event.type === "state_enter" && event.to_state && states.includes(event.to_state)) {
1451
415
  cleanupRef.current?.();
1452
416
  const result = effectRef.current();
@@ -1467,34 +431,34 @@ function useOnEnter(stateName, effect) {
1467
431
  unsub();
1468
432
  cleanupRef.current?.();
1469
433
  };
1470
- }, [runtime, ...states]);
434
+ }, [runtime2, ...states]);
1471
435
  }
1472
436
 
1473
437
  // src/hooks/useOnExit.ts
1474
438
  var import_react3 = require("react");
1475
439
  function useOnExit(stateName, effect) {
1476
- const runtime = useRuntimeContext();
440
+ const runtime2 = useRuntimeContext();
1477
441
  const effectRef = (0, import_react3.useRef)(effect);
1478
442
  effectRef.current = effect;
1479
443
  const states = Array.isArray(stateName) ? stateName : [stateName];
1480
444
  (0, import_react3.useEffect)(() => {
1481
- const unsub = runtime.sm.on((event) => {
445
+ const unsub = runtime2.sm.on((event) => {
1482
446
  if (event.type === "state_exit" && event.from_state && states.includes(event.from_state)) {
1483
447
  effectRef.current();
1484
448
  }
1485
449
  });
1486
450
  return unsub;
1487
- }, [runtime, ...states]);
451
+ }, [runtime2, ...states]);
1488
452
  }
1489
453
 
1490
454
  // src/hooks/useOnTransition.ts
1491
455
  var import_react4 = require("react");
1492
456
  function useOnTransition(effect) {
1493
- const runtime = useRuntimeContext();
457
+ const runtime2 = useRuntimeContext();
1494
458
  const effectRef = (0, import_react4.useRef)(effect);
1495
459
  effectRef.current = effect;
1496
460
  (0, import_react4.useEffect)(() => {
1497
- const unsub = runtime.sm.on((event) => {
461
+ const unsub = runtime2.sm.on((event) => {
1498
462
  if (event.type === "transition") {
1499
463
  effectRef.current({
1500
464
  from: event.from_state,
@@ -1503,33 +467,33 @@ function useOnTransition(effect) {
1503
467
  }
1504
468
  });
1505
469
  return unsub;
1506
- }, [runtime]);
470
+ }, [runtime2]);
1507
471
  }
1508
472
 
1509
473
  // src/hooks/useOnEvent.ts
1510
474
  var import_react5 = require("react");
1511
475
  function useOnEvent(pattern, handler, options) {
1512
- const runtime = useRuntimeContext();
476
+ const runtime2 = useRuntimeContext();
1513
477
  const handlerRef = (0, import_react5.useRef)(handler);
1514
478
  handlerRef.current = handler;
1515
479
  (0, import_react5.useEffect)(() => {
1516
- const unsub = runtime.eventBus.subscribe(pattern, (event) => {
1517
- 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;
1518
482
  handlerRef.current(event);
1519
483
  });
1520
484
  return unsub;
1521
- }, [runtime, pattern, options?.while]);
485
+ }, [runtime2, pattern, options?.while]);
1522
486
  }
1523
487
 
1524
488
  // src/hooks/useOnChange.ts
1525
489
  var import_react6 = require("react");
1526
490
  function useOnChange(field2, handler) {
1527
- const runtime = useRuntimeContext();
491
+ const runtime2 = useRuntimeContext();
1528
492
  const handlerRef = (0, import_react6.useRef)(handler);
1529
493
  handlerRef.current = handler;
1530
- const prevRef = (0, import_react6.useRef)(runtime.sm.stateData[field2]);
494
+ const prevRef = (0, import_react6.useRef)(runtime2.sm.stateData[field2]);
1531
495
  (0, import_react6.useEffect)(() => {
1532
- const unsub = runtime.subscribe((snap) => {
496
+ const unsub = runtime2.subscribe((snap) => {
1533
497
  const newVal = snap.stateData[field2];
1534
498
  if (newVal !== prevRef.current) {
1535
499
  handlerRef.current(newVal, prevRef.current);
@@ -1537,13 +501,13 @@ function useOnChange(field2, handler) {
1537
501
  }
1538
502
  });
1539
503
  return unsub;
1540
- }, [runtime, field2]);
504
+ }, [runtime2, field2]);
1541
505
  }
1542
506
 
1543
507
  // src/hooks/useWhileIn.ts
1544
508
  var import_react7 = require("react");
1545
509
  function useWhileIn(stateName, intervalMs, effect) {
1546
- const runtime = useRuntimeContext();
510
+ const runtime2 = useRuntimeContext();
1547
511
  const effectRef = (0, import_react7.useRef)(effect);
1548
512
  effectRef.current = effect;
1549
513
  (0, import_react7.useEffect)(() => {
@@ -1558,8 +522,8 @@ function useWhileIn(stateName, intervalMs, effect) {
1558
522
  timer = null;
1559
523
  }
1560
524
  }
1561
- if (runtime.sm.currentState === stateName) startInterval();
1562
- const unsub = runtime.sm.on((event) => {
525
+ if (runtime2.sm.currentState === stateName) startInterval();
526
+ const unsub = runtime2.sm.on((event) => {
1563
527
  if (event.type === "state_enter" && event.to_state === stateName) startInterval();
1564
528
  if (event.type === "state_exit" && event.from_state === stateName) stopInterval();
1565
529
  });
@@ -1567,13 +531,13 @@ function useWhileIn(stateName, intervalMs, effect) {
1567
531
  unsub();
1568
532
  stopInterval();
1569
533
  };
1570
- }, [runtime, stateName, intervalMs]);
534
+ }, [runtime2, stateName, intervalMs]);
1571
535
  }
1572
536
 
1573
537
  // src/hooks/useDuringAction.ts
1574
538
  var import_react8 = require("react");
1575
539
  function useDuringAction(config) {
1576
- const runtime = useRuntimeContext();
540
+ const runtime2 = useRuntimeContext();
1577
541
  const actionRef = (0, import_react8.useRef)(config.action);
1578
542
  actionRef.current = config.action;
1579
543
  const states = Array.isArray(config.state) ? config.state : [config.state];
@@ -1611,10 +575,10 @@ function useDuringAction(config) {
1611
575
  timer = null;
1612
576
  }
1613
577
  }
1614
- if (states.includes(runtime.sm.currentState)) {
578
+ if (states.includes(runtime2.sm.currentState)) {
1615
579
  startAction();
1616
580
  }
1617
- const unsub = runtime.sm.on((event) => {
581
+ const unsub = runtime2.sm.on((event) => {
1618
582
  if (event.type === "state_enter" && event.to_state && states.includes(event.to_state)) {
1619
583
  startAction();
1620
584
  }
@@ -1626,7 +590,7 @@ function useDuringAction(config) {
1626
590
  unsub();
1627
591
  stopAction();
1628
592
  };
1629
- }, [runtime, intervalMs, immediate, enabled, ...states]);
593
+ }, [runtime2, intervalMs, immediate, enabled, ...states]);
1630
594
  }
1631
595
 
1632
596
  // src/hooks/useQuery.ts
@@ -2119,29 +1083,29 @@ function useServerState(instanceId, options = {}) {
2119
1083
  // src/hooks/useWorkflow.ts
2120
1084
  var import_react15 = require("react");
2121
1085
  function useWorkflow(definition, options) {
2122
- const runtime = (0, import_react15.useMemo)(() => new WorkflowRuntime({
1086
+ const runtime2 = (0, import_react15.useMemo)(() => new WorkflowRuntime({
2123
1087
  definition,
2124
1088
  initialData: options?.initialData,
2125
1089
  actionHandlers: options?.actionHandlers
2126
1090
  }), [definition.id]);
2127
- const [snapshot, setSnapshot] = (0, import_react15.useState)(() => runtime.getSnapshot());
1091
+ const [snapshot, setSnapshot] = (0, import_react15.useState)(() => runtime2.getSnapshot());
2128
1092
  (0, import_react15.useEffect)(() => {
2129
- const unsub = runtime.subscribe(setSnapshot);
1093
+ const unsub = runtime2.subscribe(setSnapshot);
2130
1094
  return unsub;
2131
- }, [runtime]);
1095
+ }, [runtime2]);
2132
1096
  const transition2 = (0, import_react15.useCallback)(async (name, data) => {
2133
- const result = await runtime.transition(name, data);
1097
+ const result = await runtime2.transition(name, data);
2134
1098
  options?.onTransition?.(result);
2135
1099
  return result;
2136
- }, [runtime, options?.onTransition]);
1100
+ }, [runtime2, options?.onTransition]);
2137
1101
  const handle = {
2138
1102
  slug: definition.slug,
2139
1103
  ...snapshot,
2140
1104
  transition: transition2,
2141
- setField: runtime.setField.bind(runtime),
2142
- setMemory: runtime.setMemory.bind(runtime),
2143
- publishEvent: runtime.publishEvent.bind(runtime),
2144
- runtime
1105
+ setField: runtime2.setField.bind(runtime2),
1106
+ setMemory: runtime2.setMemory.bind(runtime2),
1107
+ publishEvent: runtime2.publishEvent.bind(runtime2),
1108
+ runtime: runtime2
2145
1109
  };
2146
1110
  return handle;
2147
1111
  }
@@ -2149,17 +1113,17 @@ function useWorkflow(definition, options) {
2149
1113
  // src/hooks/useTransition.ts
2150
1114
  var import_react16 = require("react");
2151
1115
  function useTransition(transitionName, _config) {
2152
- const runtime = useRuntimeContext();
1116
+ const runtime2 = useRuntimeContext();
2153
1117
  const [pending, setPending] = (0, import_react16.useState)(false);
2154
- const available = runtime.sm.getAvailableTransitions().some((t) => t.name === transitionName);
1118
+ const available = runtime2.sm.getAvailableTransitions().some((t) => t.name === transitionName);
2155
1119
  const fire = (0, import_react16.useCallback)(async (data) => {
2156
1120
  setPending(true);
2157
1121
  try {
2158
- return await runtime.transition(transitionName, data);
1122
+ return await runtime2.transition(transitionName, data);
2159
1123
  } finally {
2160
1124
  setPending(false);
2161
1125
  }
2162
- }, [runtime, transitionName]);
1126
+ }, [runtime2, transitionName]);
2163
1127
  const handle = { fire, available, pending };
2164
1128
  return handle;
2165
1129
  }
@@ -2171,12 +1135,12 @@ function setRoleHierarchy(hierarchy) {
2171
1135
  _globalHierarchy = hierarchy;
2172
1136
  }
2173
1137
  function useRole(roleName, options = {}) {
2174
- const runtime = useRuntimeContext();
1138
+ const runtime2 = useRuntimeContext();
2175
1139
  const hierarchy = options.hierarchy ?? _globalHierarchy ?? [];
2176
1140
  const inheritPermissions = options.inheritPermissions ?? true;
2177
1141
  const result = (0, import_react17.useMemo)(() => {
2178
- const snapshot = runtime.getSnapshot();
2179
- const definition = runtime.config?.definition;
1142
+ const snapshot = runtime2.getSnapshot();
1143
+ const definition = runtime2.config?.definition;
2180
1144
  const userRoles = snapshot.stateData?._userRoles ?? snapshot.stateData?.user_roles ?? [];
2181
1145
  let hasRole2 = userRoles.includes(roleName);
2182
1146
  if (!hasRole2 && hierarchy.length > 0) {
@@ -2224,7 +1188,7 @@ function useRole(roleName, options = {}) {
2224
1188
  }
2225
1189
  }
2226
1190
  return { hasRole: hasRole2, permissions, roles: userRoles, highestRole };
2227
- }, [runtime, roleName, hierarchy, inheritPermissions]);
1191
+ }, [runtime2, roleName, hierarchy, inheritPermissions]);
2228
1192
  const isAbove = (0, import_react17.useCallback)(
2229
1193
  (role) => {
2230
1194
  if (hierarchy.length === 0) return false;
@@ -2275,21 +1239,21 @@ function useRole(roleName, options = {}) {
2275
1239
  // src/hooks/useParams.ts
2276
1240
  var import_react18 = require("react");
2277
1241
  function useParams() {
2278
- const runtime = useRuntimeContext();
1242
+ const runtime2 = useRuntimeContext();
2279
1243
  return (0, import_react18.useMemo)(() => {
2280
- const snapshot = runtime.getSnapshot();
1244
+ const snapshot = runtime2.getSnapshot();
2281
1245
  const params = snapshot.stateData?._params ?? snapshot.memory?._callParams ?? {};
2282
1246
  return params;
2283
- }, [runtime]);
1247
+ }, [runtime2]);
2284
1248
  }
2285
1249
 
2286
1250
  // src/hooks/usePackage.ts
2287
1251
  var import_react19 = require("react");
2288
1252
  function usePackage(packageSlug) {
2289
- const runtime = useRuntimeContext();
1253
+ const runtime2 = useRuntimeContext();
2290
1254
  return (0, import_react19.useMemo)(() => {
2291
- const snapshot = runtime.getSnapshot();
2292
- const definition = runtime.config?.definition;
1255
+ const snapshot = runtime2.getSnapshot();
1256
+ const definition = runtime2.config?.definition;
2293
1257
  const childDefs = definition?.child_definitions ?? [];
2294
1258
  const metadata = definition?.metadata ?? {};
2295
1259
  if (definition?.slug === packageSlug && definition?.category === "blueprint") {
@@ -2352,7 +1316,7 @@ function usePackage(packageSlug) {
2352
1316
  isResolved: false,
2353
1317
  dependencySlugs: []
2354
1318
  };
2355
- }, [runtime, packageSlug]);
1319
+ }, [runtime2, packageSlug]);
2356
1320
  }
2357
1321
 
2358
1322
  // src/hooks/useRouter.ts
@@ -2478,16 +1442,16 @@ function useRouter(options = {}) {
2478
1442
  };
2479
1443
  setIsNavigating(true);
2480
1444
  try {
2481
- for (const guard of guardsRef.current) {
2482
- const allowed = await guard(to, location);
1445
+ for (const guard2 of guardsRef.current) {
1446
+ const allowed = await guard2(to, location);
2483
1447
  if (!allowed) {
2484
1448
  onRejectRef.current?.(to);
2485
1449
  return false;
2486
1450
  }
2487
1451
  }
2488
1452
  if (found?.route?.guards) {
2489
- for (const guard of found.route.guards) {
2490
- const allowed = await guard(to, location);
1453
+ for (const guard2 of found.route.guards) {
1454
+ const allowed = await guard2(to, location);
2491
1455
  if (!allowed) {
2492
1456
  if (found.route.redirectOnFail) {
2493
1457
  const fullRedirect = basePathRef.current + found.route.redirectOnFail;
@@ -2913,7 +1877,7 @@ function useGeolocation(options = {}) {
2913
1877
  const {
2914
1878
  enableHighAccuracy = false,
2915
1879
  maximumAge = 0,
2916
- timeout = 1e4,
1880
+ timeout: timeout2 = 1e4,
2917
1881
  watch = false,
2918
1882
  enabled = true
2919
1883
  } = options;
@@ -2924,8 +1888,8 @@ function useGeolocation(options = {}) {
2924
1888
  const watchIdRef = (0, import_react24.useRef)(null);
2925
1889
  const supported = typeof navigator !== "undefined" && "geolocation" in navigator;
2926
1890
  const positionOptions = (0, import_react24.useMemo)(
2927
- () => ({ enableHighAccuracy, maximumAge, timeout }),
2928
- [enableHighAccuracy, maximumAge, timeout]
1891
+ () => ({ enableHighAccuracy, maximumAge, timeout: timeout2 }),
1892
+ [enableHighAccuracy, maximumAge, timeout2]
2929
1893
  );
2930
1894
  const handleSuccess = (0, import_react24.useCallback)((pos) => {
2931
1895
  setPosition({
@@ -3285,7 +2249,7 @@ var import_react27 = require("react");
3285
2249
  function useForm(config) {
3286
2250
  const {
3287
2251
  initialValues,
3288
- validate,
2252
+ validate: validate2,
3289
2253
  fieldValidators,
3290
2254
  onSubmit,
3291
2255
  onError,
@@ -3298,8 +2262,8 @@ function useForm(config) {
3298
2262
  const [isSubmitting, setIsSubmitting] = (0, import_react27.useState)(false);
3299
2263
  const [submitCount, setSubmitCount] = (0, import_react27.useState)(0);
3300
2264
  const initialRef = (0, import_react27.useRef)(initialValues);
3301
- const validateRef = (0, import_react27.useRef)(validate);
3302
- validateRef.current = validate;
2265
+ const validateRef = (0, import_react27.useRef)(validate2);
2266
+ validateRef.current = validate2;
3303
2267
  const fieldValidatorsRef = (0, import_react27.useRef)(fieldValidators);
3304
2268
  fieldValidatorsRef.current = fieldValidators;
3305
2269
  const onSubmitRef = (0, import_react27.useRef)(onSubmit);
@@ -3516,7 +2480,7 @@ function useNotification() {
3516
2480
  setPermission(result);
3517
2481
  return result;
3518
2482
  }, [supported]);
3519
- const notify2 = (0, import_react28.useCallback)(
2483
+ const notify3 = (0, import_react28.useCallback)(
3520
2484
  (title, options = {}) => {
3521
2485
  if (!supported || permission !== "granted") return null;
3522
2486
  const {
@@ -3549,8 +2513,8 @@ function useNotification() {
3549
2513
  [supported, permission]
3550
2514
  );
3551
2515
  return (0, import_react28.useMemo)(
3552
- () => ({ permission, supported, requestPermission, notify: notify2 }),
3553
- [permission, supported, requestPermission, notify2]
2516
+ () => ({ permission, supported, requestPermission, notify: notify3 }),
2517
+ [permission, supported, requestPermission, notify3]
3554
2518
  );
3555
2519
  }
3556
2520
 
@@ -3567,12 +2531,12 @@ function notifyListeners() {
3567
2531
  }
3568
2532
  function addToast(config) {
3569
2533
  const id = `toast-${++_nextId}`;
3570
- const instance = {
2534
+ const instance2 = {
3571
2535
  ...config,
3572
2536
  id,
3573
2537
  createdAt: Date.now()
3574
2538
  };
3575
- _toasts = [..._toasts, instance];
2539
+ _toasts = [..._toasts, instance2];
3576
2540
  const duration = config.duration ?? 5e3;
3577
2541
  if (duration > 0) {
3578
2542
  const timer = setTimeout(() => {
@@ -3623,8 +2587,191 @@ function useToast() {
3623
2587
  );
3624
2588
  }
3625
2589
 
3626
- // src/hooks/useMiddleware.ts
2590
+ // src/hooks/useVisibility.ts
3627
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");
3628
2775
  function requireAuth(loginPath = "/login") {
3629
2776
  return (ctx) => {
3630
2777
  if (!ctx.token) {
@@ -3696,24 +2843,24 @@ function useMiddleware(middlewares, options = {}) {
3696
2843
  watchPathname = true,
3697
2844
  onRedirect
3698
2845
  } = options;
3699
- const [ready, setReady] = (0, import_react30.useState)(false);
3700
- const [loading, setLoading] = (0, import_react30.useState)(true);
3701
- const [redirect, setRedirect] = (0, import_react30.useState)(null);
3702
- const [error, setError] = (0, import_react30.useState)(null);
3703
- const [data, setData] = (0, import_react30.useState)({});
3704
- const [runKey, setRunKey] = (0, import_react30.useState)(0);
3705
- 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);
3706
2853
  middlewaresRef.current = middlewares;
3707
- const onRedirectRef = (0, import_react30.useRef)(onRedirect);
2854
+ const onRedirectRef = (0, import_react32.useRef)(onRedirect);
3708
2855
  onRedirectRef.current = onRedirect;
3709
- const [pathname, setPathname] = (0, import_react30.useState)(getPathname);
3710
- (0, import_react30.useEffect)(() => {
2856
+ const [pathname, setPathname] = (0, import_react32.useState)(getPathname);
2857
+ (0, import_react32.useEffect)(() => {
3711
2858
  if (!watchPathname) return;
3712
2859
  const handler = () => setPathname(getPathname());
3713
2860
  window.addEventListener("popstate", handler);
3714
2861
  return () => window.removeEventListener("popstate", handler);
3715
2862
  }, [watchPathname]);
3716
- (0, import_react30.useEffect)(() => {
2863
+ (0, import_react32.useEffect)(() => {
3717
2864
  if (!enabled) {
3718
2865
  setReady(true);
3719
2866
  setLoading(false);
@@ -3760,11 +2907,11 @@ function useMiddleware(middlewares, options = {}) {
3760
2907
  cancelled = true;
3761
2908
  };
3762
2909
  }, [enabled, pathname, runKey]);
3763
- const rerun = (0, import_react30.useMemo)(
2910
+ const rerun = (0, import_react32.useMemo)(
3764
2911
  () => () => setRunKey((k) => k + 1),
3765
2912
  []
3766
2913
  );
3767
- return (0, import_react30.useMemo)(
2914
+ return (0, import_react32.useMemo)(
3768
2915
  () => ({ ready, loading, redirect, error, data, rerun }),
3769
2916
  [ready, loading, redirect, error, data, rerun]
3770
2917
  );
@@ -3774,8 +2921,8 @@ function useMiddleware(middlewares, options = {}) {
3774
2921
  var import_react_query = require("@tanstack/react-query");
3775
2922
  var import_jsx_runtime = require("react/jsx-runtime");
3776
2923
  var defaultQueryClient = new import_react_query.QueryClient();
3777
- function WorkflowProvider({ runtime, queryClient, children }) {
3778
- 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 }) });
3779
2926
  }
3780
2927
 
3781
2928
  // src/local/LocalEngine.ts
@@ -3836,8 +2983,8 @@ var LocalWorkflowEngine = class {
3836
2983
  * Process all pending events from a transition result.
3837
2984
  * Emits locally and returns the events for P2P broadcast.
3838
2985
  */
3839
- processPendingEvents(instance) {
3840
- const events = instance._pendingEvents;
2986
+ processPendingEvents(instance2) {
2987
+ const events = instance2._pendingEvents;
3841
2988
  if (!events?.length) return [];
3842
2989
  for (const evt of events) {
3843
2990
  this.emitEvent(evt);
@@ -3880,18 +3027,18 @@ var LocalWorkflowEngine = class {
3880
3027
  };
3881
3028
  }
3882
3029
  /** Check if a transition can fire from the instance's current state */
3883
- canTransition(instance, transitionName) {
3884
- const def = this.definitions.get(instance.definitionSlug);
3030
+ canTransition(instance2, transitionName) {
3031
+ const def = this.definitions.get(instance2.definitionSlug);
3885
3032
  if (!def) return false;
3886
3033
  const transition2 = def.transitions.find((t) => t.name === transitionName);
3887
3034
  if (!transition2) return false;
3888
- return transition2.from.includes(instance.currentState);
3035
+ return transition2.from.includes(instance2.currentState);
3889
3036
  }
3890
3037
  /** Get all transitions available from the instance's current state */
3891
- getAvailableTransitions(instance) {
3892
- const def = this.definitions.get(instance.definitionSlug);
3038
+ getAvailableTransitions(instance2) {
3039
+ const def = this.definitions.get(instance2.definitionSlug);
3893
3040
  if (!def) return [];
3894
- 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);
3895
3042
  }
3896
3043
  /**
3897
3044
  * Apply a transition, returning a new WorkflowInstance (immutable).
@@ -3902,29 +3049,29 @@ var LocalWorkflowEngine = class {
3902
3049
  * @returns New WorkflowInstance with updated state and version
3903
3050
  * @throws If transition is not valid from current state
3904
3051
  */
3905
- applyTransition(instance, transitionName, data) {
3906
- const def = this.definitions.get(instance.definitionSlug);
3052
+ applyTransition(instance2, transitionName, data) {
3053
+ const def = this.definitions.get(instance2.definitionSlug);
3907
3054
  if (!def) {
3908
- throw new Error(`Definition not found: ${instance.definitionSlug}`);
3055
+ throw new Error(`Definition not found: ${instance2.definitionSlug}`);
3909
3056
  }
3910
3057
  const transition2 = def.transitions.find((t) => t.name === transitionName);
3911
3058
  if (!transition2) {
3912
3059
  throw new Error(
3913
- `Transition "${transitionName}" not found in ${instance.definitionSlug}`
3060
+ `Transition "${transitionName}" not found in ${instance2.definitionSlug}`
3914
3061
  );
3915
3062
  }
3916
- if (!transition2.from.includes(instance.currentState)) {
3063
+ if (!transition2.from.includes(instance2.currentState)) {
3917
3064
  throw new Error(
3918
- `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(", ")})`
3919
3066
  );
3920
3067
  }
3921
- const nextState = transition2.to ?? instance.currentState;
3922
- const fields = data ? { ...instance.fields, ...data } : { ...instance.fields };
3068
+ const nextState = transition2.to ?? instance2.currentState;
3069
+ const fields = data ? { ...instance2.fields, ...data } : { ...instance2.fields };
3923
3070
  let result = {
3924
- ...instance,
3071
+ ...instance2,
3925
3072
  currentState: nextState,
3926
3073
  fields,
3927
- version: instance.version + 1,
3074
+ version: instance2.version + 1,
3928
3075
  updatedAt: Date.now()
3929
3076
  };
3930
3077
  const targetStateDef = def.states.find((s) => s.name === nextState);
@@ -3997,23 +3144,23 @@ var LocalWorkflowEngine = class {
3997
3144
  * Apply a transition only if the incoming version is newer.
3998
3145
  * Used for P2P sync — skips stale transitions.
3999
3146
  */
4000
- applyRemoteTransition(instance, transitionName, data, remoteVersion) {
4001
- if (remoteVersion <= instance.version) {
3147
+ applyRemoteTransition(instance2, transitionName, data, remoteVersion) {
3148
+ if (remoteVersion <= instance2.version) {
4002
3149
  return null;
4003
3150
  }
4004
- if (!this.canTransition(instance, transitionName)) {
3151
+ if (!this.canTransition(instance2, transitionName)) {
4005
3152
  return null;
4006
3153
  }
4007
- const updated = this.applyTransition(instance, transitionName, data);
3154
+ const updated = this.applyTransition(instance2, transitionName, data);
4008
3155
  return { ...updated, version: remoteVersion };
4009
3156
  }
4010
3157
  };
4011
3158
 
4012
3159
  // src/local/LocalEngineContext.ts
4013
- var import_react31 = require("react");
4014
- var LocalEngineContext = (0, import_react31.createContext)(null);
3160
+ var import_react33 = require("react");
3161
+ var LocalEngineContext = (0, import_react33.createContext)(null);
4015
3162
  function useLocalEngine() {
4016
- return (0, import_react31.useContext)(LocalEngineContext);
3163
+ return (0, import_react33.useContext)(LocalEngineContext);
4017
3164
  }
4018
3165
  var LocalEngineProvider = LocalEngineContext.Provider;
4019
3166
 
@@ -4270,6 +3417,155 @@ function defineModel(def) {
4270
3417
  return def;
4271
3418
  }
4272
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
+
4273
3569
  // src/config/defineBlueprint.ts
4274
3570
  function defineBlueprint(config) {
4275
3571
  if (!config.slug) {
@@ -4383,13 +3679,13 @@ function inState(state2) {
4383
3679
  function notInState(state2) {
4384
3680
  return { type: "expression", expression: `current_state != "${state2}"` };
4385
3681
  }
4386
- function and2(...conditions) {
3682
+ function and(...conditions) {
4387
3683
  return { AND: conditions.map(normalize) };
4388
3684
  }
4389
- function or2(...conditions) {
3685
+ function or(...conditions) {
4390
3686
  return { OR: conditions.map(normalize) };
4391
3687
  }
4392
- function not2(condition) {
3688
+ function not(condition) {
4393
3689
  const c = normalize(condition);
4394
3690
  if (c.type === "expression" && c.expression) {
4395
3691
  return { type: "expression", expression: `NOT(${c.expression})` };
@@ -4434,7 +3730,7 @@ function refHasAnyRole(slug, lookupField, lookupValue, roles) {
4434
3730
  }
4435
3731
 
4436
3732
  // src/hooks/useModel.ts
4437
- var import_react32 = require("react");
3733
+ var import_react34 = require("react");
4438
3734
  function getDefaultFields(definition) {
4439
3735
  const defaults = {};
4440
3736
  for (const [key, field2] of Object.entries(definition.fields)) {
@@ -4489,18 +3785,18 @@ function useModel(definition, options = {}) {
4489
3785
  if (options.state) queryParams.state = options.state;
4490
3786
  const query = useQuery(slug, queryParams);
4491
3787
  const mutation = useMutation(slug);
4492
- const instance = query.data?.[0];
4493
- const instanceId = instance?.id ?? null;
4494
- const currentState = instance?.currentState ?? "";
4495
- const instanceFields = instance?.fields ?? null;
4496
- const defaultFields = (0, import_react32.useMemo)(() => getDefaultFields(definition), [definition]);
4497
- 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)(() => {
4498
3794
  if (!instanceFields) return defaultFields;
4499
3795
  return { ...defaultFields, ...instanceFields };
4500
3796
  }, [instanceFields, defaultFields]);
4501
- const instanceIdRef = (0, import_react32.useRef)(instanceId);
3797
+ const instanceIdRef = (0, import_react34.useRef)(instanceId);
4502
3798
  instanceIdRef.current = instanceId;
4503
- const trigger = (0, import_react32.useCallback)(async (name, input) => {
3799
+ const trigger = (0, import_react34.useCallback)(async (name, input) => {
4504
3800
  const id = instanceIdRef.current;
4505
3801
  if (!id) {
4506
3802
  throw new Error(`useModel(${slug}): No instance loaded. Cannot trigger '${name}'.`);
@@ -4508,12 +3804,12 @@ function useModel(definition, options = {}) {
4508
3804
  await mutation.transition(id, name, input);
4509
3805
  await query.refetch();
4510
3806
  }, [slug, mutation, query]);
4511
- const create = (0, import_react32.useCallback)(async (input) => {
3807
+ const create = (0, import_react34.useCallback)(async (input) => {
4512
3808
  const id = await mutation.create(input);
4513
3809
  await query.refetch();
4514
3810
  return id;
4515
3811
  }, [mutation, query]);
4516
- const update = (0, import_react32.useCallback)(async (fieldUpdates) => {
3812
+ const update = (0, import_react34.useCallback)(async (fieldUpdates) => {
4517
3813
  const id = instanceIdRef.current;
4518
3814
  if (!id) {
4519
3815
  throw new Error(`useModel(${slug}): No instance loaded. Cannot update.`);
@@ -4542,27 +3838,27 @@ function useCollection(definition, options = {}) {
4542
3838
  const slug = definition.slug;
4543
3839
  const query = useQuery(slug, options);
4544
3840
  const mutation = useMutation(slug);
4545
- const items = (0, import_react32.useMemo)(() => {
4546
- return (query.data || []).map((instance) => ({
4547
- id: instance.id,
4548
- fields: instance.fields ?? {},
4549
- 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 ?? ""
4550
3846
  }));
4551
3847
  }, [query.data]);
4552
- const trigger = (0, import_react32.useCallback)(async (instanceId, name, input) => {
3848
+ const trigger = (0, import_react34.useCallback)(async (instanceId, name, input) => {
4553
3849
  await mutation.transition(instanceId, name, input);
4554
3850
  await query.refetch();
4555
3851
  }, [mutation, query]);
4556
- const create = (0, import_react32.useCallback)(async (input) => {
3852
+ const create = (0, import_react34.useCallback)(async (input) => {
4557
3853
  const id = await mutation.create(input);
4558
3854
  await query.refetch();
4559
3855
  return id;
4560
3856
  }, [mutation, query]);
4561
- const update = (0, import_react32.useCallback)(async (instanceId, fieldUpdates) => {
3857
+ const update = (0, import_react34.useCallback)(async (instanceId, fieldUpdates) => {
4562
3858
  await mutation.update(instanceId, fieldUpdates);
4563
3859
  await query.refetch();
4564
3860
  }, [mutation, query]);
4565
- const remove = (0, import_react32.useCallback)(async (instanceId) => {
3861
+ const remove = (0, import_react34.useCallback)(async (instanceId) => {
4566
3862
  await mutation.remove(instanceId);
4567
3863
  await query.refetch();
4568
3864
  }, [mutation, query]);
@@ -4586,7 +3882,7 @@ function useCollection(definition, options = {}) {
4586
3882
  function stub(displayName) {
4587
3883
  const Component = () => {
4588
3884
  throw new Error(
4589
- `<${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.`
4590
3886
  );
4591
3887
  };
4592
3888
  Component.displayName = displayName;
@@ -4713,7 +4009,7 @@ function djb2Hash(str) {
4713
4009
  }
4714
4010
 
4715
4011
  // src/authoring.ts
4716
- function useState20(_defaultOrKey) {
4012
+ function useState21(_defaultOrKey) {
4717
4013
  return [void 0, () => {
4718
4014
  }];
4719
4015
  }
@@ -4724,10 +4020,10 @@ function defineWorkspace(config) {
4724
4020
  }
4725
4021
 
4726
4022
  // src/hooks/useModule.ts
4727
- var import_react33 = require("react");
4023
+ var import_react35 = require("react");
4728
4024
  function useModule(slug, config = {}, options = {}) {
4729
4025
  const { enabled = true } = options;
4730
- return (0, import_react33.useMemo)(() => ({
4026
+ return (0, import_react35.useMemo)(() => ({
4731
4027
  slug,
4732
4028
  config,
4733
4029
  isLoaded: enabled
@@ -4735,7 +4031,7 @@ function useModule(slug, config = {}, options = {}) {
4735
4031
  }
4736
4032
 
4737
4033
  // src/hooks/useModuleConfig.ts
4738
- var import_react34 = require("react");
4034
+ var import_react36 = require("react");
4739
4035
  var installedModulesStore = [];
4740
4036
  var configDefaultsStore = /* @__PURE__ */ new Map();
4741
4037
  function setInstalledModules(modules) {
@@ -4751,7 +4047,7 @@ function getInstalledModules() {
4751
4047
  return installedModulesStore;
4752
4048
  }
4753
4049
  function useModuleConfig(moduleSlug) {
4754
- return (0, import_react34.useMemo)(() => {
4050
+ return (0, import_react36.useMemo)(() => {
4755
4051
  const installed = getInstalledModule(moduleSlug);
4756
4052
  const defaults = configDefaultsStore.get(moduleSlug) ?? {};
4757
4053
  const persisted = persistedConfigStore.get(moduleSlug) ?? {};
@@ -4799,8 +4095,8 @@ async function updateDefinitionConfig(values, definitionId) {
4799
4095
  }
4800
4096
  function useModuleConfigWithMutation(moduleSlug) {
4801
4097
  const config = useModuleConfig(moduleSlug);
4802
- const [isSaving, setIsSaving] = (0, import_react34.useState)(false);
4803
- const updateConfig = (0, import_react34.useCallback)(async (values) => {
4098
+ const [isSaving, setIsSaving] = (0, import_react36.useState)(false);
4099
+ const updateConfig = (0, import_react36.useCallback)(async (values) => {
4804
4100
  setIsSaving(true);
4805
4101
  try {
4806
4102
  return await updateDefinitionConfig(values);
@@ -6313,7 +5609,7 @@ function approval(config = {}) {
6313
5609
  }
6314
5610
  function escalation(config) {
6315
5611
  const {
6316
- timeout,
5612
+ timeout: timeout2,
6317
5613
  notifyRole = "admin",
6318
5614
  fromState = "pending_approval",
6319
5615
  escalatedState = "escalated"
@@ -6325,7 +5621,7 @@ function escalation(config) {
6325
5621
  });
6326
5622
  if (def.states[fromState]) {
6327
5623
  def.states[fromState].timeout = {
6328
- duration: timeout,
5624
+ duration: timeout2,
6329
5625
  fallback: { transition: "escalate" }
6330
5626
  };
6331
5627
  }
@@ -6344,8 +5640,8 @@ function escalation(config) {
6344
5640
  from: fromState,
6345
5641
  to: escalatedState,
6346
5642
  auto: true,
6347
- description: `Auto-escalate after ${timeout}`,
6348
- actions: [logEvent("escalated", { timeout })]
5643
+ description: `Auto-escalate after ${timeout2}`,
5644
+ actions: [logEvent("escalated", { timeout: timeout2 })]
6349
5645
  }
6350
5646
  });
6351
5647
  return def;
@@ -7003,7 +6299,8 @@ function describeModel(def) {
7003
6299
  }
7004
6300
 
7005
6301
  // src/hooks/usePlayer.ts
7006
- var import_react35 = require("react");
6302
+ var import_react37 = require("react");
6303
+ var import_player_core2 = require("@mmapp/player-core");
7007
6304
 
7008
6305
  // src/logger.ts
7009
6306
  var debugEnabled = false;
@@ -7043,18 +6340,18 @@ function computePlayerState(sm) {
7043
6340
  };
7044
6341
  }
7045
6342
  function usePlayer(config) {
7046
- const configRef = (0, import_react35.useRef)(config);
6343
+ const configRef = (0, import_react37.useRef)(config);
7047
6344
  configRef.current = config;
7048
- (0, import_react35.useEffect)(() => {
6345
+ (0, import_react37.useEffect)(() => {
7049
6346
  if (config.debug) setPlayerDebug(true);
7050
6347
  }, [config.debug]);
7051
- const evaluator = (0, import_react35.useMemo)(() => {
7052
- return createEvaluator({
6348
+ const evaluator = (0, import_react37.useMemo)(() => {
6349
+ return (0, import_player_core2.createEvaluator)({
7053
6350
  functions: config.functions ?? [],
7054
- failurePolicy: WEB_FAILURE_POLICIES.EVENT_REACTION
6351
+ failurePolicy: import_player_core2.WEB_FAILURE_POLICIES.EVENT_REACTION
7055
6352
  });
7056
6353
  }, [config.definition.id]);
7057
- const engine = (0, import_react35.useMemo)(() => {
6354
+ const engine = (0, import_react37.useMemo)(() => {
7058
6355
  const actionHandlers = /* @__PURE__ */ new Map();
7059
6356
  if (config.actionHandlers) {
7060
6357
  for (const [type, handler] of Object.entries(config.actionHandlers)) {
@@ -7082,14 +6379,14 @@ function usePlayer(config) {
7082
6379
  });
7083
6380
  }
7084
6381
  });
7085
- const sm2 = new StateMachine(
6382
+ const sm2 = new import_player_core2.StateMachine(
7086
6383
  config.definition,
7087
6384
  config.initialData ?? {},
7088
6385
  { evaluator, actionHandlers }
7089
6386
  );
7090
6387
  smRef = sm2;
7091
- const eventBus2 = new EventBus();
7092
- const dispatcher = new ActionDispatcher();
6388
+ const eventBus2 = new import_player_core2.EventBus();
6389
+ const dispatcher = new import_player_core2.ActionDispatcher();
7093
6390
  dispatcher.register("set_field", (cfg) => {
7094
6391
  if (smRef && typeof cfg.field === "string") {
7095
6392
  smRef.setField(cfg.field, cfg.value);
@@ -7108,8 +6405,8 @@ function usePlayer(config) {
7108
6405
  return { sm: sm2, eventBus: eventBus2, dispatcher };
7109
6406
  }, [config.definition.id, evaluator]);
7110
6407
  const { sm, eventBus } = engine;
7111
- const [playerState, setPlayerState] = (0, import_react35.useState)(() => computePlayerState(sm));
7112
- (0, import_react35.useEffect)(() => {
6408
+ const [playerState, setPlayerState] = (0, import_react37.useState)(() => computePlayerState(sm));
6409
+ (0, import_react37.useEffect)(() => {
7113
6410
  const stateDef = sm.getCurrentStateDefinition();
7114
6411
  if (!stateDef?.on_event?.length) return;
7115
6412
  const unsubs = [];
@@ -7173,7 +6470,7 @@ function usePlayer(config) {
7173
6470
  for (const unsub of unsubs) unsub();
7174
6471
  };
7175
6472
  }, [sm, eventBus, evaluator, engine.dispatcher, playerState.currentState]);
7176
- (0, import_react35.useEffect)(() => {
6473
+ (0, import_react37.useEffect)(() => {
7177
6474
  const unsub = sm.on((event) => {
7178
6475
  if (event.type === "transition" || event.type === "state_enter") {
7179
6476
  setPlayerState(computePlayerState(sm));
@@ -7189,7 +6486,7 @@ function usePlayer(config) {
7189
6486
  });
7190
6487
  return unsub;
7191
6488
  }, [sm]);
7192
- const transition2 = (0, import_react35.useCallback)(
6489
+ const transition2 = (0, import_react37.useCallback)(
7193
6490
  async (name, data) => {
7194
6491
  playerLog({
7195
6492
  level: "info",
@@ -7216,20 +6513,20 @@ function usePlayer(config) {
7216
6513
  },
7217
6514
  [sm]
7218
6515
  );
7219
- const setField2 = (0, import_react35.useCallback)(
6516
+ const setField2 = (0, import_react37.useCallback)(
7220
6517
  (field2, value) => {
7221
6518
  sm.setField(field2, value);
7222
6519
  setPlayerState(computePlayerState(sm));
7223
6520
  },
7224
6521
  [sm]
7225
6522
  );
7226
- const setMemory = (0, import_react35.useCallback)(
6523
+ const setMemory = (0, import_react37.useCallback)(
7227
6524
  (key, value) => {
7228
6525
  sm.setMemory(key, value);
7229
6526
  },
7230
6527
  [sm]
7231
6528
  );
7232
- const publishEvent = (0, import_react35.useCallback)(
6529
+ const publishEvent = (0, import_react37.useCallback)(
7233
6530
  (topic, payload) => {
7234
6531
  playerLog({
7235
6532
  level: "debug",
@@ -7255,11 +6552,11 @@ function usePlayer(config) {
7255
6552
  }
7256
6553
 
7257
6554
  // src/hooks/useDomainSubscription.ts
7258
- var import_react36 = require("react");
6555
+ var import_react38 = require("react");
7259
6556
  function useDomainSubscription(eventBus, transport, config) {
7260
- const configRef = (0, import_react36.useRef)(config);
6557
+ const configRef = (0, import_react38.useRef)(config);
7261
6558
  configRef.current = config;
7262
- (0, import_react36.useEffect)(() => {
6559
+ (0, import_react38.useEffect)(() => {
7263
6560
  if (!transport || config.enabled === false) return;
7264
6561
  const unsub = transport.subscribe(
7265
6562
  {
@@ -7312,11 +6609,11 @@ function useDomainSubscription(eventBus, transport, config) {
7312
6609
  }
7313
6610
 
7314
6611
  // src/hooks/useExperienceState.ts
7315
- var import_react37 = require("react");
6612
+ var import_react39 = require("react");
7316
6613
  function useExperienceState(player, selector) {
7317
- const selectorRef = (0, import_react37.useRef)(selector);
6614
+ const selectorRef = (0, import_react39.useRef)(selector);
7318
6615
  selectorRef.current = selector;
7319
- const getSnapshot = (0, import_react37.useCallback)(() => {
6616
+ const getSnapshot = (0, import_react39.useCallback)(() => {
7320
6617
  return selectorRef.current({
7321
6618
  currentState: player.currentState,
7322
6619
  stateData: player.stateData,
@@ -7332,20 +6629,20 @@ function useStateField(player, field2, defaultValue) {
7332
6629
  }
7333
6630
 
7334
6631
  // src/hooks/useComputed.ts
7335
- var import_react38 = require("react");
6632
+ var import_react40 = require("react");
7336
6633
  function useComputed(_name, compute, options) {
7337
6634
  const mode = options?.mode ?? "read-time";
7338
6635
  const deps = options?.deps ?? [];
7339
- const computeRef = (0, import_react38.useRef)(compute);
6636
+ const computeRef = (0, import_react40.useRef)(compute);
7340
6637
  computeRef.current = compute;
7341
6638
  if (mode === "read-time") {
7342
- return (0, import_react38.useMemo)(() => computeRef.current(), [
6639
+ return (0, import_react40.useMemo)(() => computeRef.current(), [
7343
6640
  // We intentionally depend on deps.join to recompute when tracked fields change
7344
6641
  // The actual dependency tracking happens at the compiler level
7345
6642
  deps.join(",")
7346
6643
  ]);
7347
6644
  }
7348
- return (0, import_react38.useMemo)(() => computeRef.current(), [deps.join(",")]);
6645
+ return (0, import_react40.useMemo)(() => computeRef.current(), [deps.join(",")]);
7349
6646
  }
7350
6647
  function useComputedWithMeta(name, compute, options) {
7351
6648
  const value = useComputed(name, compute, options);
@@ -7360,25 +6657,25 @@ function useComputedWithMeta(name, compute, options) {
7360
6657
  }
7361
6658
 
7362
6659
  // src/components/PlayerProvider.tsx
7363
- var import_react39 = require("react");
6660
+ var import_react41 = require("react");
7364
6661
  var import_jsx_runtime2 = require("react/jsx-runtime");
7365
- var PlayerContext = (0, import_react39.createContext)(null);
6662
+ var PlayerContext = (0, import_react41.createContext)(null);
7366
6663
  function PlayerProvider({ player, children }) {
7367
6664
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PlayerContext.Provider, { value: player, children });
7368
6665
  }
7369
6666
  function usePlayerContext() {
7370
- const ctx = (0, import_react39.useContext)(PlayerContext);
6667
+ const ctx = (0, import_react41.useContext)(PlayerContext);
7371
6668
  if (!ctx) {
7372
6669
  throw new Error("usePlayerContext must be used within a <PlayerProvider>");
7373
6670
  }
7374
6671
  return ctx;
7375
6672
  }
7376
6673
  function usePlayerContextSafe() {
7377
- return (0, import_react39.useContext)(PlayerContext);
6674
+ return (0, import_react41.useContext)(PlayerContext);
7378
6675
  }
7379
6676
 
7380
6677
  // src/components/ExperienceWorkflowBridge.tsx
7381
- var import_react40 = require("react");
6678
+ var import_react42 = require("react");
7382
6679
  var import_jsx_runtime3 = require("react/jsx-runtime");
7383
6680
  function ExperienceWorkflowBridgeInner({
7384
6681
  definition,
@@ -7396,7 +6693,7 @@ function ExperienceWorkflowBridgeInner({
7396
6693
  actionHandlers,
7397
6694
  debug
7398
6695
  });
7399
- const viewConfig = (0, import_react40.useMemo)(() => {
6696
+ const viewConfig = (0, import_react42.useMemo)(() => {
7400
6697
  if (!definition.state_views) return void 0;
7401
6698
  return definition.state_views[player.currentState];
7402
6699
  }, [definition.state_views, player.currentState]);
@@ -7431,7 +6728,7 @@ function ExperienceWorkflowBridge(props) {
7431
6728
  }
7432
6729
 
7433
6730
  // src/components/atoms/index.tsx
7434
- var import_react41 = __toESM(require("react"));
6731
+ var import_react43 = __toESM(require("react"));
7435
6732
  var import_jsx_runtime4 = require("react/jsx-runtime");
7436
6733
 
7437
6734
  // src/loader/experience-workflow-loader.ts
@@ -7752,7 +7049,7 @@ var BrowserPlayer = class {
7752
7049
  this.ensureInitialized();
7753
7050
  const id = crypto.randomUUID();
7754
7051
  const now = (/* @__PURE__ */ new Date()).toISOString();
7755
- const instance = {
7052
+ const instance2 = {
7756
7053
  id,
7757
7054
  definitionId: options.definitionId ?? definitionSlug,
7758
7055
  definitionSlug,
@@ -7764,15 +7061,15 @@ var BrowserPlayer = class {
7764
7061
  createdAt: now,
7765
7062
  updatedAt: now
7766
7063
  };
7767
- await this.putInstance(instance);
7064
+ await this.putInstance(instance2);
7768
7065
  this.log("info", `Instance created: ${id} (${definitionSlug})`);
7769
7066
  this.emit({
7770
7067
  type: "instance:created",
7771
7068
  instanceId: id,
7772
- data: { definitionSlug, currentState: instance.currentState },
7069
+ data: { definitionSlug, currentState: instance2.currentState },
7773
7070
  timestamp: Date.now()
7774
7071
  });
7775
- return instance;
7072
+ return instance2;
7776
7073
  }
7777
7074
  /** Get an instance by ID. */
7778
7075
  async getInstance(id) {
@@ -7781,13 +7078,13 @@ var BrowserPlayer = class {
7781
7078
  }
7782
7079
  /** Get the current state of an instance. */
7783
7080
  async getState(id) {
7784
- const instance = await this.getInstance(id);
7785
- if (!instance) return null;
7081
+ const instance2 = await this.getInstance(id);
7082
+ if (!instance2) return null;
7786
7083
  return {
7787
- currentState: instance.currentState,
7788
- status: instance.status,
7789
- stateData: instance.stateData,
7790
- lockVersion: instance.lockVersion
7084
+ currentState: instance2.currentState,
7085
+ status: instance2.status,
7086
+ stateData: instance2.stateData,
7087
+ lockVersion: instance2.lockVersion
7791
7088
  };
7792
7089
  }
7793
7090
  /**
@@ -7798,34 +7095,34 @@ var BrowserPlayer = class {
7798
7095
  */
7799
7096
  async transition(instanceId, transitionName, data = {}) {
7800
7097
  this.ensureInitialized();
7801
- const instance = await this.getInstanceFromDb(instanceId);
7802
- if (!instance) {
7098
+ const instance2 = await this.getInstanceFromDb(instanceId);
7099
+ if (!instance2) {
7803
7100
  return {
7804
7101
  success: false,
7805
7102
  instance: null,
7806
7103
  error: `Instance ${instanceId} not found`
7807
7104
  };
7808
7105
  }
7809
- if (instance.status !== "ACTIVE") {
7106
+ if (instance2.status !== "ACTIVE") {
7810
7107
  return {
7811
7108
  success: false,
7812
- instance,
7813
- error: `Instance is ${instance.status}, cannot transition`
7109
+ instance: instance2,
7110
+ error: `Instance is ${instance2.status}, cannot transition`
7814
7111
  };
7815
7112
  }
7816
7113
  try {
7817
- const newStateData = { ...instance.stateData, ...data };
7818
- const newLockVersion = instance.lockVersion + 1;
7114
+ const newStateData = { ...instance2.stateData, ...data };
7115
+ const newLockVersion = instance2.lockVersion + 1;
7819
7116
  if (this.wasm.execute_transition) {
7820
7117
  const request = {
7821
7118
  instance: {
7822
- id: instance.id,
7823
- definition_id: instance.definitionId,
7824
- current_state: instance.currentState,
7825
- status: instance.status,
7119
+ id: instance2.id,
7120
+ definition_id: instance2.definitionId,
7121
+ current_state: instance2.currentState,
7122
+ status: instance2.status,
7826
7123
  state_data: newStateData,
7827
- memory: instance.memory,
7828
- execution_lock_version: instance.lockVersion
7124
+ memory: instance2.memory,
7125
+ execution_lock_version: instance2.lockVersion
7829
7126
  },
7830
7127
  transition_name: transitionName,
7831
7128
  actor_id: this.peerId,
@@ -7834,26 +7131,26 @@ var BrowserPlayer = class {
7834
7131
  const resultJson = this.wasm.execute_transition(JSON.stringify(request));
7835
7132
  const result = JSON.parse(resultJson);
7836
7133
  if (result.success === false || result.error) {
7837
- return { success: false, instance, error: result.error ?? "Transition failed" };
7134
+ return { success: false, instance: instance2, error: result.error ?? "Transition failed" };
7838
7135
  }
7839
- instance.currentState = result.to_state ?? instance.currentState;
7840
- instance.status = result.status ?? instance.status;
7841
- instance.stateData = result.state_data ?? newStateData;
7842
- 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;
7843
7140
  } else {
7844
- instance.stateData = newStateData;
7141
+ instance2.stateData = newStateData;
7845
7142
  }
7846
- instance.lockVersion = newLockVersion;
7847
- instance.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
7848
- await this.putInstance(instance);
7143
+ instance2.lockVersion = newLockVersion;
7144
+ instance2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
7145
+ await this.putInstance(instance2);
7849
7146
  this.log("info", `Transition: ${instanceId} ${transitionName}`);
7850
7147
  this.emit({
7851
7148
  type: "instance:transition",
7852
7149
  instanceId,
7853
7150
  data: {
7854
7151
  transitionName,
7855
- fromState: instance.currentState,
7856
- toState: instance.currentState,
7152
+ fromState: instance2.currentState,
7153
+ toState: instance2.currentState,
7857
7154
  lockVersion: newLockVersion
7858
7155
  },
7859
7156
  timestamp: Date.now()
@@ -7863,7 +7160,7 @@ var BrowserPlayer = class {
7863
7160
  type: "TransitionReplication",
7864
7161
  instance_id: instanceId,
7865
7162
  transition_name: transitionName,
7866
- state_data: instance.stateData,
7163
+ state_data: instance2.stateData,
7867
7164
  lock_version: newLockVersion
7868
7165
  });
7869
7166
  const envelope = this.wasm.sign_envelope(this.secretKeyHex, payload);
@@ -7873,11 +7170,11 @@ var BrowserPlayer = class {
7873
7170
  envelope
7874
7171
  }));
7875
7172
  }
7876
- return { success: true, instance };
7173
+ return { success: true, instance: instance2 };
7877
7174
  } catch (err) {
7878
7175
  const error = err instanceof Error ? err.message : String(err);
7879
7176
  this.log("error", `Transition failed: ${error}`);
7880
- return { success: false, instance, error };
7177
+ return { success: false, instance: instance2, error };
7881
7178
  }
7882
7179
  }
7883
7180
  // ─── Subscriptions ──────────────────────────────────────────────────
@@ -7957,12 +7254,12 @@ var BrowserPlayer = class {
7957
7254
  request.onerror = () => reject(request.error);
7958
7255
  });
7959
7256
  }
7960
- async putInstance(instance) {
7257
+ async putInstance(instance2) {
7961
7258
  if (!this.db) return;
7962
7259
  return new Promise((resolve, reject) => {
7963
7260
  const tx = this.db.transaction(INSTANCE_STORE_NAME, "readwrite");
7964
7261
  const store = tx.objectStore(INSTANCE_STORE_NAME);
7965
- store.put(instance);
7262
+ store.put(instance2);
7966
7263
  tx.oncomplete = () => resolve();
7967
7264
  tx.onerror = () => reject(tx.error);
7968
7265
  });
@@ -8109,10 +7406,382 @@ var BrowserPlayer = class {
8109
7406
  }
8110
7407
  }
8111
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");
8112
7780
  // Annotate the CommonJS export names for ESM import in node:
8113
7781
  0 && (module.exports = {
8114
7782
  Accordion,
8115
7783
  AnimatedBox,
7784
+ BUILT_IN_CONSTRAINTS,
8116
7785
  Badge,
8117
7786
  Blueprint,
8118
7787
  BrowserPlayer,
@@ -8139,6 +7808,7 @@ var BrowserPlayer = class {
8139
7808
  Modal,
8140
7809
  ModelBuilder,
8141
7810
  NavLink,
7811
+ ORCHESTRATION_PRESETS,
8142
7812
  PlayerProvider,
8143
7813
  RoleGuard,
8144
7814
  Route,
@@ -8162,12 +7832,19 @@ var BrowserPlayer = class {
8162
7832
  WorkflowProvider,
8163
7833
  WorkflowRuntime,
8164
7834
  action,
7835
+ actor,
7836
+ after,
7837
+ allowTransition,
8165
7838
  and,
8166
7839
  applyMixins,
8167
7840
  approval,
8168
7841
  assertModelValid,
8169
7842
  cedar,
7843
+ compose,
7844
+ computeVisibility,
7845
+ configureActor,
8170
7846
  connector,
7847
+ constraints,
8171
7848
  createActions,
8172
7849
  createCRUD,
8173
7850
  createLocalDataResolver,
@@ -8176,16 +7853,26 @@ var BrowserPlayer = class {
8176
7853
  cron,
8177
7854
  crud,
8178
7855
  defineBlueprint,
7856
+ defineImperativeBlueprint,
7857
+ defineMiddleware,
8179
7858
  defineModel,
8180
7859
  defineModule,
7860
+ defineRoles,
8181
7861
  defineWorkspace,
7862
+ delay,
8182
7863
  deriveInstanceKey,
8183
7864
  deriveInstanceKeySync,
8184
7865
  describeModel,
8185
7866
  deviceAction,
8186
7867
  dmn,
7868
+ editableBy,
7869
+ editableIn,
7870
+ emit,
8187
7871
  escalation,
7872
+ every,
8188
7873
  expr,
7874
+ extend,
7875
+ extendMiddleware,
8189
7876
  field,
8190
7877
  fieldContains,
8191
7878
  fieldEquals,
@@ -8200,12 +7887,21 @@ var BrowserPlayer = class {
8200
7887
  getInstalledModule,
8201
7888
  getInstalledModules,
8202
7889
  graphql,
7890
+ guard,
8203
7891
  hasAnyRole,
8204
7892
  hasRole,
7893
+ imperativeCron,
7894
+ imperativeLog,
7895
+ imperativeNotify,
7896
+ imperativeRequireRole,
8205
7897
  inState,
8206
7898
  inputEquals,
8207
7899
  inputRequired,
7900
+ instance,
8208
7901
  isActor,
7902
+ isActorConfig,
7903
+ isBuiltInConstraint,
7904
+ isConstraintDeclaration,
8209
7905
  isCreator,
8210
7906
  isOwner,
8211
7907
  isPlayerDebug,
@@ -8215,19 +7911,28 @@ var BrowserPlayer = class {
8215
7911
  loadExperienceWorkflow,
8216
7912
  logEvent,
8217
7913
  model,
7914
+ named,
8218
7915
  normalizeDefinition,
8219
7916
  not,
8220
7917
  notInState,
8221
7918
  notify,
7919
+ on,
8222
7920
  or,
7921
+ orchestration,
7922
+ patch,
8223
7923
  pipe,
8224
7924
  playerLog,
8225
7925
  prefetchData,
8226
7926
  refHasAnyRole,
8227
7927
  refHasRole,
8228
7928
  requireAuth,
7929
+ requireField,
8229
7930
  requireRole,
7931
+ resolveOrchestration,
7932
+ restrict,
8230
7933
  review,
7934
+ runtime,
7935
+ sendMessage,
8231
7936
  serverAction,
8232
7937
  setAuthResolver,
8233
7938
  setChannelTransport,
@@ -8247,10 +7952,12 @@ var BrowserPlayer = class {
8247
7952
  setServerStateResolver,
8248
7953
  setViewResolver,
8249
7954
  spawn,
7955
+ spawnActor,
8250
7956
  sql,
8251
7957
  state,
8252
7958
  syncConfigDefaults,
8253
7959
  testModel,
7960
+ timeout,
8254
7961
  transition,
8255
7962
  updateDefinitionConfig,
8256
7963
  useAuth,
@@ -8283,6 +7990,7 @@ var BrowserPlayer = class {
8283
7990
  usePlayer,
8284
7991
  usePlayerContext,
8285
7992
  usePlayerContextSafe,
7993
+ usePresence,
8286
7994
  useQuery,
8287
7995
  useRealtimeQuery,
8288
7996
  useRole,
@@ -8295,20 +8003,30 @@ var BrowserPlayer = class {
8295
8003
  useToast,
8296
8004
  useTransition,
8297
8005
  useView,
8006
+ useVisibility,
8298
8007
  useWhileIn,
8299
8008
  useWorkflow,
8300
8009
  useWorkflowState,
8010
+ userAction,
8011
+ userChoice,
8012
+ validate,
8301
8013
  validateExperienceWorkflow,
8302
8014
  validateModel,
8015
+ visibleTo,
8303
8016
  when,
8017
+ withAuditLog,
8304
8018
  withAuditTrail,
8019
+ withAuth,
8020
+ withMetrics,
8305
8021
  withOwnership,
8306
8022
  withPagination,
8307
8023
  withRBAC,
8024
+ withRateLimit,
8308
8025
  withSearch,
8309
8026
  withSlug,
8310
8027
  withSoftDelete,
8311
8028
  withTags,
8312
8029
  withTimestamps,
8030
+ withValidation,
8313
8031
  withVersioning
8314
8032
  });