@mmapp/react-compiler 0.1.0-alpha.1 → 0.1.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. package/ATOM-PIPELINE.md +144 -0
  2. package/README.md +88 -40
  3. package/dist/babel/index.js +113 -6
  4. package/dist/babel/index.mjs +2 -2
  5. package/dist/chunk-3USIFFE4.mjs +2190 -0
  6. package/dist/chunk-45YMGEVT.mjs +186 -0
  7. package/dist/chunk-4FN2AISW.mjs +148 -0
  8. package/dist/chunk-4OPI5L7G.mjs +2593 -0
  9. package/dist/chunk-4RYTKOOJ.mjs +186 -0
  10. package/dist/chunk-5RKTOVR5.mjs +244 -0
  11. package/dist/chunk-5YDMOO4X.mjs +214 -0
  12. package/dist/chunk-64ZWEMLJ.mjs +148 -0
  13. package/dist/chunk-6XP4KSWQ.mjs +2190 -0
  14. package/dist/chunk-72QWL54I.mjs +175 -0
  15. package/dist/chunk-7B4TRI7C.mjs +4835 -0
  16. package/dist/chunk-7ZKGHTNB.mjs +4952 -0
  17. package/dist/chunk-CIESM3BP.mjs +33 -0
  18. package/dist/chunk-DE3ZGQAC.mjs +148 -0
  19. package/dist/chunk-DMCY3BBG.mjs +1933 -0
  20. package/dist/chunk-DPIK3PJS.mjs +244 -0
  21. package/dist/chunk-E5IVH4RE.mjs +186 -0
  22. package/dist/chunk-E6FZNUR5.mjs +4953 -0
  23. package/dist/chunk-EJRBDQDP.mjs +2607 -0
  24. package/dist/chunk-ELO4TXJL.mjs +186 -0
  25. package/dist/chunk-FKRO52XH.mjs +3446 -0
  26. package/dist/chunk-FL4YAKU6.mjs +4941 -0
  27. package/dist/chunk-FYT47UBU.mjs +5076 -0
  28. package/dist/chunk-GCLGPOJZ.mjs +148 -0
  29. package/dist/chunk-GXB4JOP7.mjs +5072 -0
  30. package/dist/chunk-HFXOUMTD.mjs +175 -0
  31. package/dist/chunk-HWIZ47US.mjs +214 -0
  32. package/dist/chunk-IB7MNPQL.mjs +4953 -0
  33. package/dist/chunk-ICSIHQCG.mjs +148 -0
  34. package/dist/chunk-JLA5VNQ3.mjs +186 -0
  35. package/dist/chunk-JQLWFCTM.mjs +214 -0
  36. package/dist/chunk-KFJJCQAL.mjs +148 -0
  37. package/dist/chunk-KJUIIEQE.mjs +186 -0
  38. package/dist/chunk-KNWTHRVQ.mjs +175 -0
  39. package/dist/chunk-KSG4XSZF.mjs +175 -0
  40. package/dist/chunk-LF5N6DOU.mjs +175 -0
  41. package/dist/chunk-LJQCM2IM.mjs +214 -0
  42. package/dist/chunk-NW6555WJ.mjs +186 -0
  43. package/dist/chunk-OMZE6VLQ.mjs +214 -0
  44. package/dist/chunk-P4BR7WVO.mjs +2190 -0
  45. package/dist/chunk-QQHVYH2X.mjs +244 -0
  46. package/dist/chunk-S5QLWLLT.mjs +186 -0
  47. package/dist/chunk-SCWGT2FY.mjs +2190 -0
  48. package/dist/chunk-SMKJUSB3.mjs +2190 -0
  49. package/dist/chunk-VCAY2KGM.mjs +175 -0
  50. package/dist/chunk-WECAV6QB.mjs +148 -0
  51. package/dist/chunk-WMKBXUCE.mjs +3228 -0
  52. package/dist/chunk-XAJ5BKKL.mjs +4947 -0
  53. package/dist/chunk-XG2X7AEA.mjs +175 -0
  54. package/dist/chunk-XG7Z23NQ.mjs +148 -0
  55. package/dist/chunk-XWZAOCQ7.mjs +2607 -0
  56. package/dist/chunk-Y6MA7ULW.mjs +148 -0
  57. package/dist/chunk-YMS7Q7LG.mjs +214 -0
  58. package/dist/chunk-ZA37XTGA.mjs +175 -0
  59. package/dist/cli/index.js +1616 -366
  60. package/dist/cli/index.mjs +8 -8
  61. package/dist/codemod/cli.mjs +1 -1
  62. package/dist/codemod/index.mjs +1 -1
  63. package/dist/dev-server-RmGHIntF.d.mts +113 -0
  64. package/dist/dev-server-RmGHIntF.d.ts +113 -0
  65. package/dist/dev-server.d.mts +1 -1
  66. package/dist/dev-server.d.ts +1 -1
  67. package/dist/dev-server.js +982 -53
  68. package/dist/dev-server.mjs +5 -5
  69. package/dist/envelope.js +113 -6
  70. package/dist/envelope.mjs +3 -3
  71. package/dist/index.d.mts +5 -1
  72. package/dist/index.d.ts +5 -1
  73. package/dist/index.js +992 -63
  74. package/dist/index.mjs +8 -8
  75. package/{src/cli/init.ts → dist/init-7JQMAAXS.mjs} +70 -95
  76. package/dist/init-EHO4VQ22.mjs +369 -0
  77. package/dist/init-UC3FWPIW.mjs +367 -0
  78. package/dist/init-UNSMVKIK.mjs +366 -0
  79. package/dist/init-UNV5XIDE.mjs +367 -0
  80. package/dist/project-compiler-2P4N4DR7.mjs +10 -0
  81. package/dist/project-compiler-D2LCC27O.mjs +10 -0
  82. package/dist/project-compiler-EJ3GANJE.mjs +10 -0
  83. package/dist/project-compiler-LOQKVRZJ.mjs +10 -0
  84. package/dist/project-compiler-RQ6OQKRM.mjs +10 -0
  85. package/dist/project-compiler-VWNNCHGO.mjs +10 -0
  86. package/dist/project-compiler-XVAAU4C5.mjs +10 -0
  87. package/dist/project-compiler-YES5FGMD.mjs +10 -0
  88. package/dist/project-compiler-ZKMQDLGU.mjs +10 -0
  89. package/dist/project-decompiler-FLXCEJHS.mjs +7 -0
  90. package/dist/project-decompiler-VLPR22QF.mjs +7 -0
  91. package/dist/pull-FUS5QYZS.mjs +109 -0
  92. package/dist/pull-LD5ENLGY.mjs +109 -0
  93. package/dist/testing/index.js +113 -6
  94. package/dist/testing/index.mjs +2 -2
  95. package/dist/vite/index.js +113 -6
  96. package/dist/vite/index.mjs +3 -3
  97. package/examples/uber-app/app/admin/fleet.tsx +19 -19
  98. package/package.json +4 -3
  99. package/compile-blueprint-chat.mjs +0 -99
  100. package/compile-blueprint-glass-console.mjs +0 -98
  101. package/compile-chat-defs.mjs +0 -92
  102. package/examples/uber-app/tests/payment.test.tsx +0 -129
  103. package/examples/uber-app/tests/ride-flow.test.tsx +0 -123
  104. package/package.json.backup +0 -86
  105. package/scripts/decompile.ts +0 -226
  106. package/scripts/seed-auth.ts +0 -267
  107. package/scripts/seed-uber.ts +0 -248
  108. package/scripts/validate-uber.ts +0 -119
  109. package/seed-blueprint-chat.mjs +0 -444
  110. package/seed-blueprint-glass-console.mjs +0 -445
  111. package/seed-compiled.mjs +0 -318
  112. package/src/RoundTripValidator.ts +0 -400
  113. package/src/__tests__/atom-rendering-coverage.test.ts +0 -680
  114. package/src/__tests__/auth-module-compilation.test.ts +0 -247
  115. package/src/__tests__/auth-template-compilation.test.ts +0 -589
  116. package/src/__tests__/change-extractor.test.ts +0 -142
  117. package/src/__tests__/cli-pull.test.ts +0 -73
  118. package/src/__tests__/cli-test.test.ts +0 -72
  119. package/src/__tests__/component-extractor.test.ts +0 -331
  120. package/src/__tests__/context-extractor.test.ts +0 -145
  121. package/src/__tests__/decompiler.test.ts +0 -718
  122. package/src/__tests__/define-blueprint.test.ts +0 -133
  123. package/src/__tests__/definition-validator.test.ts +0 -519
  124. package/src/__tests__/during-extractor.test.ts +0 -152
  125. package/src/__tests__/effect-extractor.test.ts +0 -107
  126. package/src/__tests__/event-emission.test.ts +0 -127
  127. package/src/__tests__/examples.test.ts +0 -236
  128. package/src/__tests__/full-blueprint-coverage.test.ts +0 -1221
  129. package/src/__tests__/golden-suite.test.ts +0 -403
  130. package/src/__tests__/grammar-island-extractor.test.ts +0 -289
  131. package/src/__tests__/instance-key.test.ts +0 -82
  132. package/src/__tests__/ir-migration.test.ts +0 -255
  133. package/src/__tests__/lock-file.test.ts +0 -117
  134. package/src/__tests__/model-extractor.test.ts +0 -195
  135. package/src/__tests__/model-field-acl.test.ts +0 -237
  136. package/src/__tests__/model-hooks.test.ts +0 -130
  137. package/src/__tests__/model-ref-resolution.test.ts +0 -268
  138. package/src/__tests__/model-roundtrip.test.ts +0 -502
  139. package/src/__tests__/model-runtime.test.ts +0 -112
  140. package/src/__tests__/model-transitions.test.ts +0 -183
  141. package/src/__tests__/nrt-action-trace.test.ts +0 -391
  142. package/src/__tests__/pipeline-hardening.test.ts +0 -413
  143. package/src/__tests__/project-compiler.test.ts +0 -546
  144. package/src/__tests__/project-decompiler.test.ts +0 -343
  145. package/src/__tests__/query-compilation.test.ts +0 -145
  146. package/src/__tests__/round-trip/PLAN.md +0 -158
  147. package/src/__tests__/round-trip/README.md +0 -52
  148. package/src/__tests__/round-trip/RESULTS.md +0 -86
  149. package/src/__tests__/round-trip/fixtures/data-heavy/main.workflow.tsx +0 -55
  150. package/src/__tests__/round-trip/fixtures/data-heavy/mm.config.ts +0 -11
  151. package/src/__tests__/round-trip/fixtures/data-heavy/models/contact.ts +0 -54
  152. package/src/__tests__/round-trip/fixtures/full-workflow/main.workflow.tsx +0 -79
  153. package/src/__tests__/round-trip/fixtures/full-workflow/mm.config.ts +0 -12
  154. package/src/__tests__/round-trip/fixtures/full-workflow/models/order.ts +0 -50
  155. package/src/__tests__/round-trip/fixtures/simple-crud/main.workflow.tsx +0 -25
  156. package/src/__tests__/round-trip/fixtures/simple-crud/mm.config.ts +0 -11
  157. package/src/__tests__/round-trip/fixtures/simple-crud/models/task.ts +0 -32
  158. package/src/__tests__/round-trip/fixtures/view-heavy/main.workflow.tsx +0 -79
  159. package/src/__tests__/round-trip/fixtures/view-heavy/mm.config.ts +0 -10
  160. package/src/__tests__/round-trip/round-trip.test.ts +0 -2598
  161. package/src/__tests__/round-trip-ir.test.ts +0 -300
  162. package/src/__tests__/round-trip.test.ts +0 -1212
  163. package/src/__tests__/route-merging.test.ts +0 -372
  164. package/src/__tests__/router-composition.test.ts +0 -489
  165. package/src/__tests__/router-extractor.test.ts +0 -176
  166. package/src/__tests__/server-action-extractor.test.ts +0 -128
  167. package/src/__tests__/smart-type-inference.test.ts +0 -365
  168. package/src/__tests__/source-envelope.test.ts +0 -284
  169. package/src/__tests__/source-fidelity.test.ts +0 -516
  170. package/src/__tests__/state-extractor.test.ts +0 -115
  171. package/src/__tests__/strict-mode.test.ts +0 -227
  172. package/src/__tests__/transition-effect-extractor.test.ts +0 -119
  173. package/src/__tests__/transition-extractor.test.ts +0 -68
  174. package/src/__tests__/ts-to-expression.test.ts +0 -462
  175. package/src/__tests__/type-generator.test.ts +0 -201
  176. package/src/__tests__/uber-validation.test.ts +0 -502
  177. package/src/action-compiler.ts +0 -361
  178. package/src/babel/emitters/experience-transform.ts +0 -199
  179. package/src/babel/emitters/ir-to-tsx-emitter.ts +0 -110
  180. package/src/babel/emitters/pure-form-emitter.ts +0 -1023
  181. package/src/babel/emitters/runtime-glue-emitter.ts +0 -39
  182. package/src/babel/extractors/change-extractor.ts +0 -199
  183. package/src/babel/extractors/component-extractor.ts +0 -907
  184. package/src/babel/extractors/computed-extractor.ts +0 -262
  185. package/src/babel/extractors/context-extractor.ts +0 -277
  186. package/src/babel/extractors/during-extractor.ts +0 -295
  187. package/src/babel/extractors/effect-extractor.ts +0 -340
  188. package/src/babel/extractors/event-extractor.ts +0 -235
  189. package/src/babel/extractors/grammar-island-extractor.ts +0 -302
  190. package/src/babel/extractors/model-extractor.ts +0 -1018
  191. package/src/babel/extractors/router-extractor.ts +0 -303
  192. package/src/babel/extractors/server-action-extractor.ts +0 -173
  193. package/src/babel/extractors/server-action-hook-extractor.ts +0 -72
  194. package/src/babel/extractors/server-state-extractor.ts +0 -88
  195. package/src/babel/extractors/state-extractor.ts +0 -214
  196. package/src/babel/extractors/transition-effect-extractor.ts +0 -176
  197. package/src/babel/extractors/transition-extractor.ts +0 -143
  198. package/src/babel/index.ts +0 -24
  199. package/src/babel/transpilers/ts-to-expression.ts +0 -674
  200. package/src/babel/visitor.ts +0 -807
  201. package/src/cli/auth.ts +0 -255
  202. package/src/cli/build.ts +0 -288
  203. package/src/cli/deploy.ts +0 -206
  204. package/src/cli/index.ts +0 -328
  205. package/src/cli/installer.ts +0 -261
  206. package/src/cli/lock-file.ts +0 -94
  207. package/src/cli/mmrc.ts +0 -22
  208. package/src/cli/pull.ts +0 -172
  209. package/src/cli/registry-client.ts +0 -175
  210. package/src/cli/test.ts +0 -397
  211. package/src/cli/type-generator.ts +0 -243
  212. package/src/codemod/__tests__/forward.test.ts +0 -239
  213. package/src/codemod/__tests__/reverse.test.ts +0 -145
  214. package/src/codemod/__tests__/round-trip.test.ts +0 -137
  215. package/src/codemod/annotation.ts +0 -97
  216. package/src/codemod/classify.ts +0 -197
  217. package/src/codemod/cli.ts +0 -207
  218. package/src/codemod/control-flow.ts +0 -409
  219. package/src/codemod/forward.ts +0 -244
  220. package/src/codemod/import-manager.ts +0 -171
  221. package/src/codemod/index.ts +0 -120
  222. package/src/codemod/reverse.ts +0 -197
  223. package/src/codemod/rules.ts +0 -174
  224. package/src/codemod/state-transform.ts +0 -126
  225. package/src/decompiler/ast-builder.ts +0 -538
  226. package/src/decompiler/config-generator.ts +0 -151
  227. package/src/decompiler/index.ts +0 -315
  228. package/src/decompiler/project-decompiler.ts +0 -1776
  229. package/src/decompiler/project.ts +0 -862
  230. package/src/decompiler/split-strategy.ts +0 -140
  231. package/src/decompiler/state-emitter.ts +0 -1053
  232. package/src/decompiler/sx-emitter.ts +0 -318
  233. package/src/decompiler/workspace-hydrator.ts +0 -189
  234. package/src/dev-server.ts +0 -238
  235. package/src/envelope/fs-tree.ts +0 -217
  236. package/src/envelope/source-envelope.ts +0 -264
  237. package/src/envelope.ts +0 -315
  238. package/src/incremental-compiler.ts +0 -401
  239. package/src/index.ts +0 -99
  240. package/src/model-compiler.ts +0 -277
  241. package/src/project-compiler.ts +0 -1629
  242. package/src/route-extractor.ts +0 -333
  243. package/src/testing/index.ts +0 -32
  244. package/src/testing/snapshot.ts +0 -252
  245. package/src/testing/test-utils.ts +0 -226
  246. package/src/types.ts +0 -68
  247. package/src/vite/index.ts +0 -288
  248. package/test-compile.mjs +0 -142
  249. package/tsconfig.json +0 -25
  250. package/tsup.config.ts +0 -23
  251. package/vitest.config.ts +0 -9
package/dist/index.js CHANGED
@@ -445,25 +445,25 @@ function inferTransitionStates(transitions, states) {
445
445
  const stateArray = Array.from(states.values());
446
446
  const startStates = stateArray.filter((s) => s.type === "START");
447
447
  const regularStates = stateArray.filter((s) => s.type === "REGULAR");
448
- const needsInference = transitions.filter((t22) => t22.from.length === 0 || !t22.to);
448
+ const needsInference = transitions.filter((t23) => t23.from.length === 0 || !t23.to);
449
449
  if (needsInference.length === 0) return;
450
450
  if (startStates.length === 1 && regularStates.length > 0) {
451
- needsInference.forEach((t22, idx) => {
452
- if (t22.from.length === 0) {
453
- t22.from = [startStates[0].name];
451
+ needsInference.forEach((t23, idx) => {
452
+ if (t23.from.length === 0) {
453
+ t23.from = [startStates[0].name];
454
454
  }
455
- if (!t22.to) {
456
- t22.to = regularStates[idx % regularStates.length]?.name || startStates[0].name;
455
+ if (!t23.to) {
456
+ t23.to = regularStates[idx % regularStates.length]?.name || startStates[0].name;
457
457
  }
458
458
  });
459
459
  } else {
460
460
  const allStateNames = stateArray.map((s) => s.name);
461
- needsInference.forEach((t22, idx) => {
462
- if (t22.from.length === 0 && allStateNames.length > 0) {
463
- t22.from = [allStateNames[0]];
461
+ needsInference.forEach((t23, idx) => {
462
+ if (t23.from.length === 0 && allStateNames.length > 0) {
463
+ t23.from = [allStateNames[0]];
464
464
  }
465
- if (!t22.to && allStateNames.length > 1) {
466
- t22.to = allStateNames[Math.min(idx + 1, allStateNames.length - 1)];
465
+ if (!t23.to && allStateNames.length > 1) {
466
+ t23.to = allStateNames[Math.min(idx + 1, allStateNames.length - 1)];
467
467
  }
468
468
  });
469
469
  }
@@ -651,11 +651,128 @@ var init_event_extractor = __esm({
651
651
  });
652
652
 
653
653
  // src/babel/transpilers/ts-to-expression.ts
654
+ var ts_to_expression_exports = {};
655
+ __export(ts_to_expression_exports, {
656
+ transpile: () => transpile,
657
+ transpileBlock: () => transpileBlock,
658
+ transpileExpression: () => transpileExpression
659
+ });
654
660
  function transpileExpression(node, options = {}) {
655
661
  const ctx = new TranspileContext(options);
656
662
  const expr = ctx.visit(node);
657
663
  return { expression: expr, pure: ctx.isPure };
658
664
  }
665
+ function transpile(node, options = {}) {
666
+ return transpileExpression(node, options).expression;
667
+ }
668
+ function transpileBlock(node, options = {}) {
669
+ const ctx = new TranspileContext(options);
670
+ const lines = visitStatements(node.body, ctx);
671
+ return { expression: lines, pure: ctx.isPure };
672
+ }
673
+ function visitStatements(stmts, ctx) {
674
+ return stmts.map((s) => visitStatement(s, ctx)).join("\n");
675
+ }
676
+ function visitStatement(stmt, ctx) {
677
+ if (t5.isVariableDeclaration(stmt)) {
678
+ const keyword = ctx.allMutable || stmt.kind !== "const" ? "let" : "const";
679
+ const decls = stmt.declarations.map((d) => {
680
+ const init = d.init ? ctx.visit(d.init) : "null";
681
+ const lhs = declaratorPattern(d.id);
682
+ return `${keyword} ${lhs} = ${init}`;
683
+ });
684
+ return decls.join(";\n") + ";";
685
+ }
686
+ if (t5.isIfStatement(stmt)) {
687
+ const test = ctx.visit(stmt.test);
688
+ const consequent = visitBranchBody(stmt.consequent, ctx);
689
+ if (stmt.alternate) {
690
+ const alternate = visitBranchBody(stmt.alternate, ctx);
691
+ return `if (${test}) ${consequent} else ${alternate}`;
692
+ }
693
+ return `if (${test}) ${consequent}`;
694
+ }
695
+ if (t5.isForOfStatement(stmt)) {
696
+ const right = ctx.visit(stmt.right);
697
+ const varName = forOfPattern(stmt.left);
698
+ const body = visitBranchBody(stmt.body, ctx);
699
+ return `for (const ${varName} of ${right}) ${body}`;
700
+ }
701
+ if (t5.isWhileStatement(stmt)) {
702
+ const test = ctx.visit(stmt.test);
703
+ const body = visitBranchBody(stmt.body, ctx);
704
+ return `while (${test}) ${body}`;
705
+ }
706
+ if (t5.isReturnStatement(stmt)) {
707
+ if (!stmt.argument) return "return;";
708
+ return `return ${ctx.visit(stmt.argument)};`;
709
+ }
710
+ if (t5.isExpressionStatement(stmt)) {
711
+ return ctx.visit(stmt.expression) + ";";
712
+ }
713
+ if (t5.isBlockStatement(stmt)) {
714
+ const inner = visitStatements(stmt.body, ctx);
715
+ return `{
716
+ ${indent(inner)}
717
+ }`;
718
+ }
719
+ if (t5.isFunctionDeclaration(stmt) && stmt.id) {
720
+ const name = stmt.id.name;
721
+ const params = stmt.params.map((p) => t5.isIdentifier(p) ? p.name : "_").join(", ");
722
+ const body = visitStatements(stmt.body.body, ctx);
723
+ return `function ${name}(${params}) {
724
+ ${indent(body)}
725
+ }`;
726
+ }
727
+ return ctx.opaque(`[${stmt.type}]`) + ";";
728
+ }
729
+ function visitBranchBody(node, ctx) {
730
+ if (t5.isBlockStatement(node)) {
731
+ const inner2 = visitStatements(node.body, ctx);
732
+ return `{
733
+ ${indent(inner2)}
734
+ }`;
735
+ }
736
+ const inner = visitStatement(node, ctx);
737
+ return `{
738
+ ${indent(inner)}
739
+ }`;
740
+ }
741
+ function declaratorPattern(node) {
742
+ if (t5.isIdentifier(node)) return node.name;
743
+ if (t5.isObjectPattern(node)) {
744
+ const props = node.properties.map((p) => {
745
+ if (t5.isRestElement(p)) {
746
+ return `...${t5.isIdentifier(p.argument) ? p.argument.name : "_"}`;
747
+ }
748
+ if (t5.isObjectProperty(p)) {
749
+ const key = t5.isIdentifier(p.key) ? p.key.name : "_";
750
+ const val = t5.isIdentifier(p.value) ? p.value.name : t5.isAssignmentPattern(p.value) && t5.isIdentifier(p.value.left) ? p.value.left.name : "_";
751
+ return key === val ? key : `${key}: ${val}`;
752
+ }
753
+ return "_";
754
+ });
755
+ return `{ ${props.join(", ")} }`;
756
+ }
757
+ if (t5.isArrayPattern(node)) {
758
+ const elems = node.elements.map(
759
+ (e) => e === null ? "" : t5.isIdentifier(e) ? e.name : "_"
760
+ );
761
+ return `[${elems.join(", ")}]`;
762
+ }
763
+ return "_";
764
+ }
765
+ function forOfPattern(left) {
766
+ if (t5.isVariableDeclaration(left)) {
767
+ const d = left.declarations[0];
768
+ if (d) return declaratorPattern(d.id);
769
+ }
770
+ if (t5.isIdentifier(left)) return left.name;
771
+ return "_";
772
+ }
773
+ function indent(code) {
774
+ return code.split("\n").map((l) => " " + l).join("\n");
775
+ }
659
776
  function fallbackGenerate(node) {
660
777
  if (t5.isIdentifier(node)) return node.name;
661
778
  if (t5.isStringLiteral(node)) return `"${node.value.replace(/"/g, '\\"')}"`;
@@ -675,6 +792,8 @@ var init_ts_to_expression = __esm({
675
792
  this.localFieldMap = options.localFieldMap ?? /* @__PURE__ */ new Map();
676
793
  this.derivedVarMap = options.derivedVarMap ?? /* @__PURE__ */ new Map();
677
794
  this.setterToFieldMap = options.setterToFieldMap ?? /* @__PURE__ */ new Map();
795
+ this.parameterMap = options.parameterMap ?? /* @__PURE__ */ new Map();
796
+ this.allMutable = options.allMutable ?? false;
678
797
  }
679
798
  /**
680
799
  * Emit an opaque JS fallback, marking the result as impure.
@@ -696,6 +815,8 @@ var init_ts_to_expression = __esm({
696
815
  if (snakeName) return `$local.${snakeName}`;
697
816
  const derivedInit = this.derivedVarMap.get(node.name);
698
817
  if (derivedInit) return `(${this.visit(derivedInit)})`;
818
+ const paramField = this.parameterMap.get(node.name);
819
+ if (paramField) return paramField;
699
820
  if (node.name === "undefined") return "null";
700
821
  if (node.name === "NaN") return "null";
701
822
  if (node.name === "Infinity") return "null";
@@ -743,6 +864,9 @@ var init_ts_to_expression = __esm({
743
864
  if (t5.isNewExpression(node)) {
744
865
  return this.visitNew(node);
745
866
  }
867
+ if (t5.isAssignmentExpression(node) && node.operator === "=" && t5.isIdentifier(node.left)) {
868
+ return `${node.left.name} = ${this.visit(node.right)}`;
869
+ }
746
870
  return this.opaque(fallbackGenerate(node));
747
871
  }
748
872
  // ---------------------------------------------------------------------------
@@ -943,6 +1067,11 @@ var init_ts_to_expression = __esm({
943
1067
  return this.visitArrayHigherOrder("some", obj, args);
944
1068
  case "every":
945
1069
  return this.visitArrayHigherOrder("every", obj, args);
1070
+ // --- Array push: arr.push(item) → arr = push(arr, item) ---
1071
+ case "push": {
1072
+ const [item] = this.visitArgsList(args);
1073
+ return `${obj} = push(${obj}, ${item})`;
1074
+ }
946
1075
  // --- Array mutation-free methods ---
947
1076
  case "reverse":
948
1077
  return `reverse(${obj})`;
@@ -1747,7 +1876,7 @@ var init_component_extractor = __esm({
1747
1876
 
1748
1877
  // ../player-core/dist/index.mjs
1749
1878
  function normalizeCategory(primary, ...tags) {
1750
- const uniqueTags = [...new Set(tags.filter((t22) => t22 !== primary))];
1879
+ const uniqueTags = [...new Set(tags.filter((t23) => t23 !== primary))];
1751
1880
  uniqueTags.sort();
1752
1881
  return [primary, ...uniqueTags];
1753
1882
  }
@@ -2027,6 +2156,18 @@ function emitIR(extracted) {
2027
2156
  });
2028
2157
  stateNames.add(transition.to);
2029
2158
  }
2159
+ for (const from of transition.from) {
2160
+ if (from && !stateNames.has(from)) {
2161
+ stateArray.push({
2162
+ name: from,
2163
+ type: "REGULAR",
2164
+ on_enter: [],
2165
+ during: [],
2166
+ on_exit: []
2167
+ });
2168
+ stateNames.add(from);
2169
+ }
2170
+ }
2030
2171
  }
2031
2172
  const fieldNames = new Set(fields.map((f) => f.name));
2032
2173
  let normalizedView;
@@ -2462,16 +2603,16 @@ function emitWorkflowDefinition(extracted) {
2462
2603
  ...f.editable_when && { editable_when: f.editable_when },
2463
2604
  ...f.state_home && { state_home: f.state_home }
2464
2605
  }));
2465
- const transitions = ir.transitions.map((t22) => ({
2466
- name: t22.name,
2467
- from: t22.from,
2468
- to: t22.to,
2469
- description: t22.description || "",
2470
- roles: t22.roles || [],
2471
- auto: t22.auto || false,
2472
- conditions: t22.conditions || [],
2473
- actions: (t22.actions || []).map(convertAction),
2474
- required_fields: t22.required_fields || [],
2606
+ const transitions = ir.transitions.map((t23) => ({
2607
+ name: t23.name,
2608
+ from: t23.from,
2609
+ to: t23.to,
2610
+ description: t23.description || "",
2611
+ roles: t23.roles || [],
2612
+ auto: t23.auto || false,
2613
+ conditions: t23.conditions || [],
2614
+ actions: (t23.actions || []).map(convertAction),
2615
+ required_fields: t23.required_fields || [],
2475
2616
  priority: 0
2476
2617
  }));
2477
2618
  const state_data = {};
@@ -3255,7 +3396,7 @@ function resolveType(annotation) {
3255
3396
  }
3256
3397
  if (t15.isTSUnionType(annotation)) {
3257
3398
  const allLiterals = annotation.types.every(
3258
- (t22) => t15.isTSLiteralType(t22) && (t15.isStringLiteral(t22.literal) || t15.isNumericLiteral(t22.literal))
3399
+ (t23) => t15.isTSLiteralType(t23) && (t15.isStringLiteral(t23.literal) || t15.isNumericLiteral(t23.literal))
3259
3400
  );
3260
3401
  if (allLiterals) return "select";
3261
3402
  return "text";
@@ -3629,6 +3770,71 @@ function modelStateTypeToIR(type) {
3629
3770
  if (type === "final") return "END";
3630
3771
  return "REGULAR";
3631
3772
  }
3773
+ function parseActionArray(raw, actionCounter) {
3774
+ if (!Array.isArray(raw)) return [];
3775
+ const actions = [];
3776
+ for (const item of raw) {
3777
+ if (typeof item !== "object" || item === null) continue;
3778
+ const a = item;
3779
+ actions.push({
3780
+ id: a.id ? String(a.id) : `auto_${++actionCounter.value}`,
3781
+ type: String(a.type || a.action_type || "unknown"),
3782
+ mode: a.mode || "auto",
3783
+ config: a.config && typeof a.config === "object" ? a.config : {},
3784
+ ...a.condition ? { condition: String(a.condition) } : {}
3785
+ });
3786
+ }
3787
+ return actions;
3788
+ }
3789
+ function parseDuringArray(raw, actionCounter) {
3790
+ if (!Array.isArray(raw)) return [];
3791
+ const result = [];
3792
+ for (const item of raw) {
3793
+ if (typeof item !== "object" || item === null) continue;
3794
+ const d = item;
3795
+ result.push({
3796
+ id: d.id ? String(d.id) : `during_${++actionCounter.value}`,
3797
+ type: d.type || "interval",
3798
+ ...d.interval_ms != null ? { interval_ms: Number(d.interval_ms) } : {},
3799
+ ...d.cron ? { cron: String(d.cron) } : {},
3800
+ ...d.delay_ms != null ? { delay_ms: Number(d.delay_ms) } : {},
3801
+ ...d.condition ? { condition: String(d.condition) } : {},
3802
+ actions: parseActionArray(d.actions, actionCounter)
3803
+ });
3804
+ }
3805
+ return result;
3806
+ }
3807
+ function parseOnEventArray(raw, actionCounter) {
3808
+ if (!Array.isArray(raw)) return [];
3809
+ const result = [];
3810
+ for (const item of raw) {
3811
+ if (typeof item !== "object" || item === null) continue;
3812
+ const e = item;
3813
+ const actions = [];
3814
+ if (Array.isArray(e.actions)) {
3815
+ for (const a of e.actions) {
3816
+ if (typeof a !== "object" || a === null) continue;
3817
+ const act = a;
3818
+ actions.push({
3819
+ type: act.type || "set_field",
3820
+ ...act.field ? { field: String(act.field) } : {},
3821
+ ...act.expression ? { expression: String(act.expression) } : {},
3822
+ ...act.key ? { key: String(act.key) } : {},
3823
+ ...act.message ? { message: String(act.message) } : {},
3824
+ ...act.config && typeof act.config === "object" ? { config: act.config } : {},
3825
+ ...act.conditions && Array.isArray(act.conditions) ? { conditions: act.conditions.map(String) } : {}
3826
+ });
3827
+ }
3828
+ }
3829
+ result.push({
3830
+ match: String(e.match || ""),
3831
+ ...e.description ? { description: String(e.description) } : {},
3832
+ ...e.conditions && Array.isArray(e.conditions) ? { conditions: e.conditions.map(String) } : {},
3833
+ actions
3834
+ });
3835
+ }
3836
+ return result;
3837
+ }
3632
3838
  function extractDefineModelCall(programPath, compilerState, actionCounter) {
3633
3839
  for (const node of programPath.node.body) {
3634
3840
  if (!t15.isExportDefaultDeclaration(node)) continue;
@@ -3668,17 +3874,27 @@ function extractDefineModelCall(programPath, compilerState, actionCounter) {
3668
3874
  const statesObj = config.states;
3669
3875
  for (const [name, stateConfig] of Object.entries(statesObj)) {
3670
3876
  const stateType = modelStateTypeToIR(stateConfig.type);
3877
+ const on_enter = parseActionArray(stateConfig.on_enter, actionCounter);
3878
+ const on_exit = parseActionArray(stateConfig.on_exit, actionCounter);
3879
+ const during = parseDuringArray(stateConfig.during, actionCounter);
3880
+ const on_event = parseOnEventArray(stateConfig.on_event, actionCounter);
3671
3881
  if (!compilerState.states.has(name)) {
3672
3882
  compilerState.states.set(name, {
3673
3883
  name,
3674
3884
  type: stateType,
3675
3885
  description: stateConfig.description,
3676
- on_enter: [],
3677
- during: [],
3678
- on_exit: []
3886
+ on_enter,
3887
+ during,
3888
+ on_exit,
3889
+ ...on_event.length > 0 ? { on_event } : {}
3679
3890
  });
3680
3891
  } else {
3681
- compilerState.states.get(name).type = stateType;
3892
+ const existing = compilerState.states.get(name);
3893
+ existing.type = stateType;
3894
+ if (on_enter.length > 0) existing.on_enter = on_enter;
3895
+ if (on_exit.length > 0) existing.on_exit = on_exit;
3896
+ if (during.length > 0) existing.during = during;
3897
+ if (on_event.length > 0) existing.on_event = on_event;
3682
3898
  }
3683
3899
  }
3684
3900
  }
@@ -3716,13 +3932,21 @@ function extractDefineModelCall(programPath, compilerState, actionCounter) {
3716
3932
  if (transConfig.guard) {
3717
3933
  conditions.push(parseGuardExpression(String(transConfig.guard)));
3718
3934
  }
3935
+ if (transConfig.conditions && Array.isArray(transConfig.conditions)) {
3936
+ for (const cond of transConfig.conditions) {
3937
+ if (typeof cond === "object" && cond !== null) {
3938
+ conditions.push(cond);
3939
+ }
3940
+ }
3941
+ }
3942
+ const actions = parseActionArray(transConfig.actions, actionCounter);
3719
3943
  compilerState.transitions.push({
3720
3944
  name,
3721
3945
  from,
3722
3946
  to,
3723
3947
  description: transConfig.description,
3724
3948
  conditions: conditions.length > 0 ? conditions : void 0,
3725
- actions: [],
3949
+ actions,
3726
3950
  roles: transConfig.roles,
3727
3951
  auto: transConfig.auto,
3728
3952
  required_fields: transConfig.required_fields
@@ -4830,7 +5054,7 @@ function createVisitor(options = {}) {
4830
5054
  }
4831
5055
  }
4832
5056
  if (mode !== "strict") return;
4833
- if (source.startsWith("@mindmatrix/") || source === "react" || source.startsWith("react/") || source.startsWith(".") || source.startsWith("/")) {
5057
+ if (source.startsWith("@mindmatrix/") || source.startsWith("@mmapp/") || source === "react" || source.startsWith("react/") || source.startsWith(".") || source.startsWith("/")) {
4834
5058
  return;
4835
5059
  }
4836
5060
  const error = {
@@ -5244,7 +5468,7 @@ function compileModel(filename, source, options = {}) {
5244
5468
  ir,
5245
5469
  interfaceName,
5246
5470
  fieldNames: ir.fields.map((f) => f.name),
5247
- transitionNames: ir.transitions.map((t22) => t22.name),
5471
+ transitionNames: ir.transitions.map((t23) => t23.name),
5248
5472
  stateNames: ir.states.map((s) => s.name),
5249
5473
  hasFieldOptions: Object.keys(rawFieldOptions).length > 0,
5250
5474
  fieldOptions: rawFieldOptions
@@ -5664,6 +5888,520 @@ var init_action_compiler = __esm({
5664
5888
  }
5665
5889
  });
5666
5890
 
5891
+ // src/babel/extractors/action-extractor.ts
5892
+ function extractAction(source, filename) {
5893
+ let ast;
5894
+ try {
5895
+ ast = (0, import_parser2.parse)(source, {
5896
+ sourceType: "module",
5897
+ plugins: ["typescript"],
5898
+ strictMode: false
5899
+ });
5900
+ } catch {
5901
+ return null;
5902
+ }
5903
+ const result = findDefaultExportedFunction(ast);
5904
+ if (!result) return null;
5905
+ const { name, params, body, returnTypeAnnotation, isAsync } = result;
5906
+ const slug = toKebabCase(name);
5907
+ const warnings = [];
5908
+ const fields = params.map((p) => paramToField(p));
5909
+ const parameterMap = /* @__PURE__ */ new Map();
5910
+ for (const p of params) {
5911
+ const snakeName = toSnakeCase3(p.name);
5912
+ if (snakeName !== p.name) {
5913
+ parameterMap.set(p.name, snakeName);
5914
+ }
5915
+ }
5916
+ const humanName = name.replace(/([A-Z])/g, " $1").replace(/^./, (s) => s.toUpperCase()).trim();
5917
+ const metadata = {
5918
+ source_file: filename,
5919
+ source_function: name,
5920
+ provenance: {
5921
+ frontend: "react-compiler",
5922
+ source: "action-extractor",
5923
+ compiler_version: "2.0.0"
5924
+ }
5925
+ };
5926
+ if (returnTypeAnnotation) {
5927
+ metadata.return_type = returnTypeAnnotation;
5928
+ }
5929
+ if (isAsync) {
5930
+ const segments = splitAtAwaits(body.body);
5931
+ const hasAwaits = segments.some((s) => s.kind === "await");
5932
+ if (hasAwaits) {
5933
+ const rewritten = rewriteAwaitReferences(segments);
5934
+ const { states: states2, transitions: transitions2, bodyIsPure } = generateMultiStateIR(rewritten, warnings, parameterMap);
5935
+ if (!bodyIsPure) {
5936
+ warnings.push(`Async action '${name}' body contains untranslatable JS \u2014 wrapped in $expr() markers`);
5937
+ }
5938
+ const ir2 = {
5939
+ slug,
5940
+ name: humanName,
5941
+ version: "0.1.0",
5942
+ category: "action",
5943
+ fields,
5944
+ states: states2,
5945
+ transitions: transitions2,
5946
+ roles: [],
5947
+ metadata: { ...metadata, async: true }
5948
+ };
5949
+ return { ir: ir2, bodyIsPure, warnings };
5950
+ }
5951
+ }
5952
+ const transpileResult = transpileBlock(body, { allMutable: true, parameterMap });
5953
+ const bodyExpr = transpileResult.expression;
5954
+ if (!transpileResult.pure) {
5955
+ warnings.push(`Action '${name}' body contains untranslatable JS \u2014 wrapped in $expr() markers`);
5956
+ }
5957
+ const states = [
5958
+ {
5959
+ name: "ready",
5960
+ type: "START",
5961
+ on_enter: [],
5962
+ during: [],
5963
+ on_exit: []
5964
+ },
5965
+ {
5966
+ name: "done",
5967
+ type: "END",
5968
+ on_enter: [],
5969
+ during: [],
5970
+ on_exit: []
5971
+ }
5972
+ ];
5973
+ const transitions = [
5974
+ {
5975
+ name: "execute",
5976
+ from: ["ready"],
5977
+ to: "done",
5978
+ actions: [
5979
+ {
5980
+ id: "body",
5981
+ type: "eval",
5982
+ mode: "auto",
5983
+ config: {
5984
+ expression: bodyExpr
5985
+ }
5986
+ }
5987
+ ]
5988
+ }
5989
+ ];
5990
+ const ir = {
5991
+ slug,
5992
+ name: humanName,
5993
+ version: "0.1.0",
5994
+ category: "action",
5995
+ fields,
5996
+ states,
5997
+ transitions,
5998
+ roles: [],
5999
+ metadata
6000
+ };
6001
+ return { ir, bodyIsPure: transpileResult.pure, warnings };
6002
+ }
6003
+ function findDefaultExportedFunction(ast) {
6004
+ const topLevelVars = /* @__PURE__ */ new Map();
6005
+ for (const node of ast.program.body) {
6006
+ if (t22.isVariableDeclaration(node)) {
6007
+ for (const decl of node.declarations) {
6008
+ if (t22.isIdentifier(decl.id) && decl.init) {
6009
+ if (t22.isArrowFunctionExpression(decl.init) || t22.isFunctionExpression(decl.init)) {
6010
+ topLevelVars.set(decl.id.name, decl.init);
6011
+ }
6012
+ }
6013
+ }
6014
+ }
6015
+ }
6016
+ for (const node of ast.program.body) {
6017
+ if (t22.isExportDefaultDeclaration(node)) {
6018
+ const decl = node.declaration;
6019
+ if (t22.isFunctionDeclaration(decl) && decl.body) {
6020
+ const name = decl.id?.name ?? inferNameFromFile(decl) ?? "action";
6021
+ return extractFromFunction(name, decl.params, decl.body, decl.returnType, decl.async);
6022
+ }
6023
+ if (t22.isArrowFunctionExpression(decl) || t22.isFunctionExpression(decl)) {
6024
+ const name = t22.isFunctionExpression(decl) && decl.id ? decl.id.name : "action";
6025
+ const body = ensureBlock(decl.body);
6026
+ if (!body) return null;
6027
+ return extractFromFunction(name, decl.params, body, decl.returnType, decl.async);
6028
+ }
6029
+ if (t22.isIdentifier(decl)) {
6030
+ const fn = topLevelVars.get(decl.name);
6031
+ if (fn) {
6032
+ const body = ensureBlock(fn.body);
6033
+ if (!body) return null;
6034
+ return extractFromFunction(decl.name, fn.params, body, fn.returnType, fn.async);
6035
+ }
6036
+ }
6037
+ }
6038
+ }
6039
+ return null;
6040
+ }
6041
+ function extractFromFunction(name, params, body, returnType, isAsync = false) {
6042
+ const extracted = params.map((p) => extractParam(p));
6043
+ const returnTypeAnnotation = returnType && t22.isTSTypeAnnotation(returnType) ? serializeTSType(returnType.typeAnnotation) : void 0;
6044
+ return { name, params: extracted, body, returnTypeAnnotation, isAsync };
6045
+ }
6046
+ function ensureBlock(body) {
6047
+ if (t22.isBlockStatement(body)) return body;
6048
+ const ret = t22.returnStatement(body);
6049
+ return t22.blockStatement([ret]);
6050
+ }
6051
+ function inferNameFromFile(_node) {
6052
+ return null;
6053
+ }
6054
+ function extractParam(param) {
6055
+ if (t22.isIdentifier(param)) {
6056
+ return {
6057
+ name: param.name,
6058
+ typeAnnotation: param.typeAnnotation ? param.typeAnnotation.typeAnnotation : null,
6059
+ optional: param.optional ?? false
6060
+ };
6061
+ }
6062
+ if (t22.isAssignmentPattern(param)) {
6063
+ const inner = param.left;
6064
+ if (t22.isIdentifier(inner)) {
6065
+ return {
6066
+ name: inner.name,
6067
+ typeAnnotation: inner.typeAnnotation ? inner.typeAnnotation.typeAnnotation : null,
6068
+ optional: true,
6069
+ defaultValue: param.right
6070
+ };
6071
+ }
6072
+ }
6073
+ if (t22.isRestElement(param)) {
6074
+ const arg = param.argument;
6075
+ return {
6076
+ name: t22.isIdentifier(arg) ? arg.name : "rest",
6077
+ typeAnnotation: null,
6078
+ optional: true
6079
+ };
6080
+ }
6081
+ return { name: "params", typeAnnotation: null, optional: false };
6082
+ }
6083
+ function paramToField(param) {
6084
+ const fieldType = param.typeAnnotation ? tsTypeToFieldType2(param.typeAnnotation) : "text";
6085
+ const field = {
6086
+ name: toSnakeCase3(param.name),
6087
+ type: fieldType,
6088
+ required: !param.optional
6089
+ };
6090
+ if (param.defaultValue !== void 0) {
6091
+ field.default_value = extractLiteralDefault(param.defaultValue);
6092
+ }
6093
+ return field;
6094
+ }
6095
+ function extractLiteralDefault(expr) {
6096
+ if (!expr) return void 0;
6097
+ if (t22.isStringLiteral(expr)) return expr.value;
6098
+ if (t22.isNumericLiteral(expr)) return expr.value;
6099
+ if (t22.isBooleanLiteral(expr)) return expr.value;
6100
+ if (t22.isNullLiteral(expr)) return null;
6101
+ if (t22.isArrayExpression(expr) && expr.elements.length === 0) return [];
6102
+ if (t22.isObjectExpression(expr) && expr.properties.length === 0) return {};
6103
+ return void 0;
6104
+ }
6105
+ function tsTypeToFieldType2(tsType) {
6106
+ if (t22.isTSStringKeyword(tsType)) return "text";
6107
+ if (t22.isTSNumberKeyword(tsType)) return "number";
6108
+ if (t22.isTSBooleanKeyword(tsType)) return "boolean";
6109
+ if (t22.isTSObjectKeyword(tsType)) return "json";
6110
+ if (t22.isTSAnyKeyword(tsType) || t22.isTSUnknownKeyword(tsType)) return "json";
6111
+ if (t22.isTSArrayType(tsType)) return "json";
6112
+ if (t22.isTSUnionType(tsType)) {
6113
+ const nonNullable = tsType.types.filter(
6114
+ (t23) => !t22.isTSNullKeyword(t23) && !t22.isTSUndefinedKeyword(t23)
6115
+ );
6116
+ if (nonNullable.length === 1) {
6117
+ return tsTypeToFieldType2(nonNullable[0]);
6118
+ }
6119
+ if (nonNullable.every((t23) => t22.isTSLiteralType(t23) && t22.isStringLiteral(t23.literal))) {
6120
+ return "select";
6121
+ }
6122
+ return "text";
6123
+ }
6124
+ if (t22.isTSTypeReference(tsType) && t22.isIdentifier(tsType.typeName)) {
6125
+ const name = tsType.typeName.name;
6126
+ if (name === "Date") return "datetime";
6127
+ if (name === "string") return "text";
6128
+ if (name === "number") return "number";
6129
+ if (name === "boolean") return "boolean";
6130
+ }
6131
+ return "text";
6132
+ }
6133
+ function serializeTSType(tsType) {
6134
+ if (t22.isTSStringKeyword(tsType)) return "string";
6135
+ if (t22.isTSNumberKeyword(tsType)) return "number";
6136
+ if (t22.isTSBooleanKeyword(tsType)) return "boolean";
6137
+ if (t22.isTSVoidKeyword(tsType)) return "void";
6138
+ if (t22.isTSAnyKeyword(tsType)) return "any";
6139
+ if (t22.isTSTypeReference(tsType) && t22.isIdentifier(tsType.typeName)) {
6140
+ return tsType.typeName.name;
6141
+ }
6142
+ if (t22.isTSArrayType(tsType)) return `${serializeTSType(tsType.elementType)}[]`;
6143
+ if (t22.isTSPromiseType(tsType)) {
6144
+ return `Promise<${tsType.typeParameter ? serializeTSType(tsType.typeParameter.params[0]) : "unknown"}>`;
6145
+ }
6146
+ return "unknown";
6147
+ }
6148
+ function splitAtAwaits(body) {
6149
+ const segments = [];
6150
+ let current = [];
6151
+ let index = 0;
6152
+ for (const stmt of body) {
6153
+ const awaitInfo = extractAwait(stmt);
6154
+ if (!awaitInfo) {
6155
+ current.push(stmt);
6156
+ continue;
6157
+ }
6158
+ if (current.length > 0) {
6159
+ segments.push({ index: index++, kind: "sync", statements: current });
6160
+ current = [];
6161
+ }
6162
+ segments.push({
6163
+ index: index++,
6164
+ kind: "await",
6165
+ statements: [stmt],
6166
+ awaitTarget: awaitInfo.callee,
6167
+ awaitArgs: awaitInfo.args,
6168
+ resultBinding: awaitInfo.binding
6169
+ });
6170
+ }
6171
+ if (current.length > 0) {
6172
+ segments.push({ index: index++, kind: "sync", statements: current });
6173
+ }
6174
+ return segments;
6175
+ }
6176
+ function extractAwait(stmt) {
6177
+ if (t22.isVariableDeclaration(stmt)) {
6178
+ const decl = stmt.declarations[0];
6179
+ if (decl?.init && t22.isAwaitExpression(decl.init)) {
6180
+ const arg = decl.init.argument;
6181
+ if (t22.isCallExpression(arg)) {
6182
+ return {
6183
+ callee: getCalleeName(arg.callee),
6184
+ args: arg.arguments,
6185
+ binding: t22.isIdentifier(decl.id) ? decl.id.name : void 0
6186
+ };
6187
+ }
6188
+ }
6189
+ }
6190
+ if (t22.isExpressionStatement(stmt) && t22.isAwaitExpression(stmt.expression)) {
6191
+ const arg = stmt.expression.argument;
6192
+ if (t22.isCallExpression(arg)) {
6193
+ return {
6194
+ callee: getCalleeName(arg.callee),
6195
+ args: arg.arguments,
6196
+ binding: void 0
6197
+ };
6198
+ }
6199
+ }
6200
+ if (t22.isReturnStatement(stmt) && stmt.argument && t22.isAwaitExpression(stmt.argument)) {
6201
+ const arg = stmt.argument.argument;
6202
+ if (t22.isCallExpression(arg)) {
6203
+ return {
6204
+ callee: getCalleeName(arg.callee),
6205
+ args: arg.arguments,
6206
+ binding: void 0
6207
+ };
6208
+ }
6209
+ }
6210
+ return null;
6211
+ }
6212
+ function getCalleeName(callee) {
6213
+ if (t22.isIdentifier(callee)) return callee.name;
6214
+ if (t22.isMemberExpression(callee) && t22.isIdentifier(callee.object) && t22.isIdentifier(callee.property)) {
6215
+ return `${callee.object.name}_${callee.property.name}`;
6216
+ }
6217
+ return "unknown_action";
6218
+ }
6219
+ function rewriteAwaitReferences(segments) {
6220
+ const bindings = /* @__PURE__ */ new Map();
6221
+ const slugCounts = /* @__PURE__ */ new Map();
6222
+ return segments.map((seg) => {
6223
+ if (seg.kind === "await" && seg.resultBinding) {
6224
+ const slug = toSnakeCase3(seg.awaitTarget ?? "unknown");
6225
+ const count = (slugCounts.get(slug) ?? 0) + 1;
6226
+ slugCounts.set(slug, count);
6227
+ const key = count > 1 ? `${slug}_${count}` : slug;
6228
+ bindings.set(seg.resultBinding, `action_results.${key}`);
6229
+ }
6230
+ if (seg.kind === "sync" && bindings.size > 0) {
6231
+ return {
6232
+ ...seg,
6233
+ statements: seg.statements.map(
6234
+ (stmt) => rewriteIdentifiersInStatement(stmt, bindings)
6235
+ )
6236
+ };
6237
+ }
6238
+ return seg;
6239
+ });
6240
+ }
6241
+ function rewriteIdentifiersInStatement(stmt, _bindings) {
6242
+ return stmt;
6243
+ }
6244
+ function generateMultiStateIR(segments, _warnings, parameterMap) {
6245
+ const states = [];
6246
+ const transitions = [];
6247
+ let bodyIsPure = true;
6248
+ const awaitBindings = /* @__PURE__ */ new Map();
6249
+ const slugCounts = /* @__PURE__ */ new Map();
6250
+ for (const seg of segments) {
6251
+ if (seg.kind === "await" && seg.resultBinding) {
6252
+ const slug = toSnakeCase3(seg.awaitTarget ?? "unknown");
6253
+ const count = (slugCounts.get(slug) ?? 0) + 1;
6254
+ slugCounts.set(slug, count);
6255
+ const key = count > 1 ? `${slug}_${count}` : slug;
6256
+ awaitBindings.set(seg.resultBinding, `action_results.${key}`);
6257
+ }
6258
+ }
6259
+ states.push({ name: "ready", type: "START", on_enter: [], during: [], on_exit: [] });
6260
+ const usedStateNames = /* @__PURE__ */ new Set();
6261
+ let prevState = "ready";
6262
+ let transitionCount = 0;
6263
+ let pendingSyncStmts = [];
6264
+ for (const seg of segments) {
6265
+ if (seg.kind === "sync") {
6266
+ pendingSyncStmts.push(...seg.statements);
6267
+ continue;
6268
+ }
6269
+ const targetSlug = toSnakeCase3(seg.awaitTarget ?? "unknown");
6270
+ let stateName = `awaiting_${targetSlug}`;
6271
+ if (usedStateNames.has(stateName)) {
6272
+ let suffix = 2;
6273
+ while (usedStateNames.has(`${stateName}_${suffix}`)) suffix++;
6274
+ stateName = `${stateName}_${suffix}`;
6275
+ }
6276
+ usedStateNames.add(stateName);
6277
+ states.push({ name: stateName, type: "REGULAR", on_enter: [], during: [], on_exit: [] });
6278
+ const actions = [];
6279
+ if (pendingSyncStmts.length > 0) {
6280
+ const block = t22.blockStatement(pendingSyncStmts);
6281
+ const transpiled = transpileBlock(block, {
6282
+ allMutable: true,
6283
+ derivedVarMap: buildDerivedVarMap(awaitBindings),
6284
+ parameterMap
6285
+ });
6286
+ if (!transpiled.pure) bodyIsPure = false;
6287
+ actions.push({
6288
+ id: `pre_${transitionCount}`,
6289
+ type: "eval",
6290
+ mode: "auto",
6291
+ config: { expression: transpiled.expression }
6292
+ });
6293
+ pendingSyncStmts = [];
6294
+ }
6295
+ const callConfig = {
6296
+ definition_slug: seg.awaitTarget,
6297
+ result_key: targetSlug
6298
+ };
6299
+ if (seg.awaitArgs && seg.awaitArgs.length > 0) {
6300
+ const params = {};
6301
+ for (let i = 0; i < seg.awaitArgs.length; i++) {
6302
+ const arg = seg.awaitArgs[i];
6303
+ if (t22.isObjectExpression(arg)) {
6304
+ for (const prop2 of arg.properties) {
6305
+ if (t22.isObjectProperty(prop2) && t22.isIdentifier(prop2.key)) {
6306
+ const { expression: valExpr } = transpileArgExpression(prop2.value, awaitBindings);
6307
+ params[prop2.key.name] = valExpr;
6308
+ }
6309
+ }
6310
+ } else {
6311
+ const { expression: valExpr } = transpileArgExpression(arg, awaitBindings);
6312
+ params[`arg${i}`] = valExpr;
6313
+ }
6314
+ }
6315
+ if (Object.keys(params).length > 0) {
6316
+ callConfig.params = params;
6317
+ }
6318
+ }
6319
+ actions.push({
6320
+ id: `call_${targetSlug}`,
6321
+ type: "call_workflow",
6322
+ mode: "auto",
6323
+ config: callConfig
6324
+ });
6325
+ const transName = transitionCount === 0 ? "execute" : `on_${getStateSuffix(prevState)}_complete`;
6326
+ transitions.push({
6327
+ name: transName,
6328
+ from: [prevState],
6329
+ to: stateName,
6330
+ actions
6331
+ });
6332
+ prevState = stateName;
6333
+ transitionCount++;
6334
+ }
6335
+ states.push({ name: "done", type: "END", on_enter: [], during: [], on_exit: [] });
6336
+ const finalActions = [];
6337
+ if (pendingSyncStmts.length > 0) {
6338
+ const block = t22.blockStatement(pendingSyncStmts);
6339
+ const transpiled = transpileBlock(block, {
6340
+ allMutable: true,
6341
+ derivedVarMap: buildDerivedVarMap(awaitBindings),
6342
+ parameterMap
6343
+ });
6344
+ if (!transpiled.pure) bodyIsPure = false;
6345
+ finalActions.push({
6346
+ id: "post_final",
6347
+ type: "eval",
6348
+ mode: "auto",
6349
+ config: { expression: transpiled.expression }
6350
+ });
6351
+ }
6352
+ const finalTransName = transitionCount === 0 ? "execute" : `on_${getStateSuffix(prevState)}_complete`;
6353
+ transitions.push({
6354
+ name: finalTransName,
6355
+ from: [prevState],
6356
+ to: "done",
6357
+ actions: finalActions
6358
+ });
6359
+ return { states, transitions, bodyIsPure };
6360
+ }
6361
+ function getStateSuffix(stateName) {
6362
+ return stateName.replace(/^awaiting_/, "");
6363
+ }
6364
+ function transpileArgExpression(expr, bindings) {
6365
+ if (t22.isIdentifier(expr)) {
6366
+ const replacement = bindings.get(expr.name);
6367
+ if (replacement) return { expression: replacement };
6368
+ return { expression: `state_data.${toSnakeCase3(expr.name)}` };
6369
+ }
6370
+ if (t22.isMemberExpression(expr) && t22.isIdentifier(expr.object)) {
6371
+ const replacement = bindings.get(expr.object.name);
6372
+ if (replacement && t22.isIdentifier(expr.property)) {
6373
+ return { expression: `${replacement}.${expr.property.name}` };
6374
+ }
6375
+ }
6376
+ if (t22.isStringLiteral(expr)) return { expression: `'${expr.value}'` };
6377
+ if (t22.isNumericLiteral(expr)) return { expression: String(expr.value) };
6378
+ if (t22.isBooleanLiteral(expr)) return { expression: String(expr.value) };
6379
+ const { transpile: transpile2 } = (init_ts_to_expression(), __toCommonJS(ts_to_expression_exports));
6380
+ return { expression: transpile2(expr, { derivedVarMap: buildDerivedVarMap(bindings) }) };
6381
+ }
6382
+ function buildDerivedVarMap(bindings) {
6383
+ const map = /* @__PURE__ */ new Map();
6384
+ for (const [varName, path] of bindings) {
6385
+ map.set(varName, t22.identifier(path));
6386
+ }
6387
+ return map;
6388
+ }
6389
+ function toKebabCase(name) {
6390
+ return name.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
6391
+ }
6392
+ function toSnakeCase3(name) {
6393
+ return name.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
6394
+ }
6395
+ var import_parser2, t22;
6396
+ var init_action_extractor = __esm({
6397
+ "src/babel/extractors/action-extractor.ts"() {
6398
+ "use strict";
6399
+ import_parser2 = require("@babel/parser");
6400
+ t22 = __toESM(require("@babel/types"));
6401
+ init_ts_to_expression();
6402
+ }
6403
+ });
6404
+
5667
6405
  // src/incremental-compiler.ts
5668
6406
  function hashContent(content) {
5669
6407
  let hash = 5381;
@@ -6017,24 +6755,56 @@ function parseModuleManifest(source) {
6017
6755
  }
6018
6756
  if (contributions.length > 0) manifest.contributions = contributions;
6019
6757
  }
6758
+ const configSchemaBlock = extractObjectBlock(source, "configSchema");
6759
+ if (configSchemaBlock) {
6760
+ const configSchema = {};
6761
+ const modelSlugMatch = configSchemaBlock.match(/modelSlug:\s*['"]([^'"]+)['"]/);
6762
+ if (modelSlugMatch) configSchema.modelSlug = modelSlugMatch[1];
6763
+ const defaultsBlock = extractObjectBlock(configSchemaBlock, "defaults");
6764
+ if (defaultsBlock) {
6765
+ const defaults = {};
6766
+ const kvRegex = /(\w+):\s*(?:'([^']*)'|"([^"]*)"|(\d+(?:\.\d+)?)|(\btrue\b|\bfalse\b))/g;
6767
+ let kv;
6768
+ while ((kv = kvRegex.exec(defaultsBlock)) !== null) {
6769
+ const key = kv[1];
6770
+ const val = kv[2] ?? kv[3] ?? (kv[4] !== void 0 ? Number(kv[4]) : kv[5] === "true");
6771
+ defaults[key] = val;
6772
+ }
6773
+ configSchema.defaults = defaults;
6774
+ }
6775
+ manifest.configSchema = configSchema;
6776
+ }
6020
6777
  const depsBlock = extractArrayBlock(source, "dependencies");
6021
6778
  if (depsBlock) {
6022
6779
  const dependencies = [];
6023
- const depRegex = /\{\s*slug:\s*['"]([^'"]+)['"][^}]*\}/g;
6024
- let dm;
6025
- while ((dm = depRegex.exec(depsBlock)) !== null) {
6026
- const entry = { slug: dm[1] };
6027
- const verMatch = dm[0].match(/version:\s*['"]([^'"]+)['"]/);
6780
+ const depBlocks = extractNestedObjects(depsBlock);
6781
+ for (const block of depBlocks) {
6782
+ const slugMatch = block.match(/slug:\s*['"]([^'"]+)['"]/);
6783
+ if (!slugMatch) continue;
6784
+ const entry = { slug: slugMatch[1] };
6785
+ const verMatch = block.match(/version:\s*['"]([^'"]+)['"]/);
6028
6786
  if (verMatch) entry.version = verMatch[1];
6029
- const reqMatch = dm[0].match(/required:\s*(true|false)/);
6787
+ const reqMatch = block.match(/required:\s*(true|false)/);
6030
6788
  if (reqMatch) entry.required = reqMatch[1] === "true";
6031
- const prefixMatch = dm[0].match(/prefix:\s*['"]([^'"]+)['"]/);
6789
+ const prefixMatch = block.match(/prefix:\s*['"]([^'"]+)['"]/);
6032
6790
  if (prefixMatch) entry.routeConfig = { prefix: prefixMatch[1] };
6791
+ const configBlock = extractObjectBlock(block, "config");
6792
+ if (configBlock) {
6793
+ const config = {};
6794
+ const kvRegex = /(\w+):\s*(?:'([^']*)'|"([^"]*)"|(\d+(?:\.\d+)?)|(\btrue\b|\bfalse\b))/g;
6795
+ let kv;
6796
+ while ((kv = kvRegex.exec(configBlock)) !== null) {
6797
+ const key = kv[1];
6798
+ const val = kv[2] ?? kv[3] ?? (kv[4] !== void 0 ? Number(kv[4]) : kv[5] === "true");
6799
+ config[key] = val;
6800
+ }
6801
+ if (Object.keys(config).length > 0) entry.config = config;
6802
+ }
6033
6803
  dependencies.push(entry);
6034
6804
  }
6035
6805
  if (dependencies.length > 0) manifest.dependencies = dependencies;
6036
6806
  }
6037
- const hasRichFields = manifest.routes || manifest.actions || manifest.contributions || manifest.capabilities || manifest.dependencies;
6807
+ const hasRichFields = manifest.routes || manifest.actions || manifest.contributions || manifest.capabilities || manifest.dependencies || manifest.configSchema;
6038
6808
  return hasRichFields ? manifest : null;
6039
6809
  }
6040
6810
  function parseDependencyRouteConfigs(files) {
@@ -6130,6 +6900,9 @@ function isModelFile2(filename) {
6130
6900
  function isServerActionFile2(filename) {
6131
6901
  return /\.server\.(ts|tsx)$/.test(filename);
6132
6902
  }
6903
+ function isActionFile(filename) {
6904
+ return /^actions\/.*\.(ts|tsx)$/.test(filename) && !filename.endsWith(".server.ts") && !filename.endsWith(".test.ts") && !filename.endsWith(".test.tsx");
6905
+ }
6133
6906
  function isComponentFile(filename) {
6134
6907
  return /components\/.*\.(tsx?|jsx?)$/.test(filename) && !filename.endsWith(".test.ts") && !filename.endsWith(".test.tsx");
6135
6908
  }
@@ -6146,7 +6919,7 @@ function isModuleManifestFile(filename) {
6146
6919
  return /mm\.module\.(ts|tsx|js)$/.test(filename);
6147
6920
  }
6148
6921
  function isCompilableFile(filename) {
6149
- return isWorkflowFile(filename) || isModelFile2(filename) || isServerActionFile2(filename) || isPageFile2(filename) || isComponentFile(filename);
6922
+ return isWorkflowFile(filename) || isModelFile2(filename) || isServerActionFile2(filename) || isActionFile(filename) || isPageFile2(filename) || isComponentFile(filename);
6150
6923
  }
6151
6924
  function compileFile(filename, source, mode) {
6152
6925
  const errors = [];
@@ -6428,10 +7201,87 @@ function extractComponentProps(source) {
6428
7201
  if (!match) return [];
6429
7202
  return match[1].split(",").map((p) => p.trim().split(/[\s=:]/)[0].replace(/^\.{3}/, "").trim()).filter(Boolean);
6430
7203
  }
7204
+ function generateModuleTypeStubs(childDefinitions, _modelResults) {
7205
+ const stubs = {};
7206
+ for (const child of childDefinitions) {
7207
+ if (!child.slug) continue;
7208
+ const category = child.category;
7209
+ const isModel = category === "data" || Array.isArray(category) && category.includes("model") || Array.isArray(category) && category.includes("data");
7210
+ if (!isModel || !child.fields || child.fields.length === 0) continue;
7211
+ const interfaceName = slugToInterfaceName(child.slug) + "Fields";
7212
+ const lines = [
7213
+ `// Auto-generated type stub for model: ${child.slug}`,
7214
+ `// Do not edit \u2014 regenerated on each build.`,
7215
+ ``,
7216
+ `export interface ${interfaceName} {`
7217
+ ];
7218
+ for (const field of child.fields) {
7219
+ const tsType = irFieldTypeToTs(field.type || "string");
7220
+ const optional = field.required ? "" : "?";
7221
+ const desc = field.description;
7222
+ if (desc) {
7223
+ lines.push(` /** ${desc} */`);
7224
+ }
7225
+ lines.push(` ${field.name}${optional}: ${tsType};`);
7226
+ }
7227
+ lines.push(`}`);
7228
+ lines.push(``);
7229
+ lines.push(`export declare const ${slugToCamelCase(child.slug)}Slug: '${child.slug}';`);
7230
+ lines.push(``);
7231
+ stubs[`types/modules/${child.slug}.d.ts`] = lines.join("\n");
7232
+ }
7233
+ return stubs;
7234
+ }
7235
+ function slugToInterfaceName(slug) {
7236
+ return slug.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
7237
+ }
7238
+ function slugToCamelCase(slug) {
7239
+ const parts = slug.split("-");
7240
+ return parts[0] + parts.slice(1).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
7241
+ }
7242
+ function irFieldTypeToTs(type) {
7243
+ switch (type) {
7244
+ case "string":
7245
+ case "text":
7246
+ case "email":
7247
+ case "url":
7248
+ case "phone":
7249
+ case "slug":
7250
+ case "color":
7251
+ case "password":
7252
+ return "string";
7253
+ case "number":
7254
+ case "integer":
7255
+ case "float":
7256
+ case "currency":
7257
+ case "percent":
7258
+ return "number";
7259
+ case "boolean":
7260
+ case "toggle":
7261
+ return "boolean";
7262
+ case "date":
7263
+ case "datetime":
7264
+ case "timestamp":
7265
+ return "string";
7266
+ case "json":
7267
+ case "object":
7268
+ return "Record<string, unknown>";
7269
+ case "array":
7270
+ return "unknown[]";
7271
+ case "enum":
7272
+ return "string";
7273
+ case "file":
7274
+ case "image":
7275
+ return "string";
7276
+ default:
7277
+ return "unknown";
7278
+ }
7279
+ }
6431
7280
  function buildComposedResult(files, fileIRs, config, errors, warnings, options = {}) {
6432
7281
  const usePhase2 = options.usePhase2Modules !== false;
6433
7282
  const workflowIRs = [];
6434
7283
  const modelIRs = [];
7284
+ const actionDefinitionIRs = [];
6435
7285
  const serverActionEntries = [];
6436
7286
  let modelResults;
6437
7287
  let actionResult;
@@ -6470,6 +7320,17 @@ function buildComposedResult(files, fileIRs, config, errors, warnings, options =
6470
7320
  }
6471
7321
  }
6472
7322
  }
7323
+ for (const [filename, source] of Object.entries(files)) {
7324
+ if (isActionFile(filename)) {
7325
+ const result = extractAction(source, filename);
7326
+ if (result) {
7327
+ actionDefinitionIRs.push(result.ir);
7328
+ for (const w of result.warnings) {
7329
+ warnings.push({ file: filename, message: w, severity: "warning" });
7330
+ }
7331
+ }
7332
+ }
7333
+ }
6473
7334
  if (usePhase2) {
6474
7335
  const modelFiles = {};
6475
7336
  for (const [filename, source] of Object.entries(files)) {
@@ -6520,7 +7381,11 @@ function buildComposedResult(files, fileIRs, config, errors, warnings, options =
6520
7381
  });
6521
7382
  }
6522
7383
  }
6523
- const childDefinitions = [...workflowIRs, ...modelIRs];
7384
+ const childDefinitions = [
7385
+ ...workflowIRs,
7386
+ ...modelIRs,
7387
+ ...actionDefinitionIRs
7388
+ ];
6524
7389
  let routeTable = [];
6525
7390
  if (routeResult) {
6526
7391
  routeTable = routeResult.routes.map((r) => ({
@@ -6596,6 +7461,22 @@ function buildComposedResult(files, fileIRs, config, errors, warnings, options =
6596
7461
  }
6597
7462
  }
6598
7463
  }
7464
+ if (options.resolvedModules && options.resolvedModules.length > 0) {
7465
+ for (const mod of options.resolvedModules) {
7466
+ if (mod.serverActions && mod.serverActions.length > 0) {
7467
+ for (const action of mod.serverActions) {
7468
+ const namespacedName = `${mod.slug}:${action.name}`;
7469
+ if (!serverActionEntries.some((a) => a.name === namespacedName)) {
7470
+ serverActionEntries.push({
7471
+ ...action,
7472
+ name: namespacedName,
7473
+ sourceFile: `${mod.slug}/${action.sourceFile}`
7474
+ });
7475
+ }
7476
+ }
7477
+ }
7478
+ }
7479
+ }
6599
7480
  const allIRs = Object.values(fileIRs);
6600
7481
  const parentIR = mergeIRs(allIRs, config);
6601
7482
  if (!parentIR.metadata) parentIR.metadata = {};
@@ -6608,6 +7489,7 @@ function buildComposedResult(files, fileIRs, config, errors, warnings, options =
6608
7489
  parentMeta.composition = {
6609
7490
  workflowCount: workflowIRs.length,
6610
7491
  modelCount: modelIRs.length,
7492
+ actionCount: actionDefinitionIRs.length,
6611
7493
  serverActionCount: serverActionEntries.length,
6612
7494
  routeCount: routeTable.length,
6613
7495
  componentCount: Object.keys(componentDefinitions).length,
@@ -6639,6 +7521,20 @@ function buildComposedResult(files, fileIRs, config, errors, warnings, options =
6639
7521
  if (manifest?.contributions) {
6640
7522
  parentMeta.slot_contributions = manifest.contributions;
6641
7523
  }
7524
+ if (manifest?.configSchema) {
7525
+ parentMeta.configSchema = manifest.configSchema;
7526
+ }
7527
+ if (manifest?.dependencies) {
7528
+ const depConfigs = {};
7529
+ for (const dep of manifest.dependencies) {
7530
+ if (dep.config) {
7531
+ depConfigs[dep.slug] = dep.config;
7532
+ }
7533
+ }
7534
+ if (Object.keys(depConfigs).length > 0) {
7535
+ parentMeta.module_configs = depConfigs;
7536
+ }
7537
+ }
6642
7538
  const compilableFiles = Object.keys(files).filter(isCompilableFile);
6643
7539
  const importLinks = resolveImportLinks(files, compilableFiles);
6644
7540
  const pageExperiences = {};
@@ -6753,6 +7649,7 @@ function buildComposedResult(files, fileIRs, config, errors, warnings, options =
6753
7649
  }
6754
7650
  }
6755
7651
  }
7652
+ const typeStubs = generateModuleTypeStubs(childDefinitions, modelResults);
6756
7653
  return {
6757
7654
  ir: parentIR,
6758
7655
  childDefinitions,
@@ -6766,7 +7663,8 @@ function buildComposedResult(files, fileIRs, config, errors, warnings, options =
6766
7663
  importLinks,
6767
7664
  modelResults,
6768
7665
  actionResult,
6769
- routeResult
7666
+ routeResult,
7667
+ typeStubs
6770
7668
  };
6771
7669
  }
6772
7670
  function compileProject(files, options = {}) {
@@ -6810,6 +7708,7 @@ var init_project_compiler = __esm({
6810
7708
  init_model_compiler();
6811
7709
  init_route_extractor();
6812
7710
  init_action_compiler();
7711
+ init_action_extractor();
6813
7712
  init_incremental_compiler();
6814
7713
  IncrementalProjectCompiler = class {
6815
7714
  constructor() {
@@ -8148,20 +9047,20 @@ function normalizeFrom(from) {
8148
9047
  function correctFromFields(transitions) {
8149
9048
  if (transitions.length <= 1) return transitions;
8150
9049
  const fromValues = /* @__PURE__ */ new Set();
8151
- for (const t22 of transitions) {
8152
- const arr = normalizeFrom(t22.from);
9050
+ for (const t23 of transitions) {
9051
+ const arr = normalizeFrom(t23.from);
8153
9052
  for (const f of arr) fromValues.add(f);
8154
9053
  }
8155
9054
  if (fromValues.size !== 1) return transitions;
8156
9055
  const stateNames = /* @__PURE__ */ new Set([...fromValues]);
8157
- for (const t22 of transitions) {
8158
- stateNames.add(t22.to);
9056
+ for (const t23 of transitions) {
9057
+ stateNames.add(t23.to);
8159
9058
  }
8160
- const allNamesAreStates = transitions.every((t22) => stateNames.has(t22.name));
9059
+ const allNamesAreStates = transitions.every((t23) => stateNames.has(t23.name));
8161
9060
  if (!allNamesAreStates) return transitions;
8162
- return transitions.map((t22) => ({
8163
- ...t22,
8164
- from: [t22.name]
9061
+ return transitions.map((t23) => ({
9062
+ ...t23,
9063
+ from: [t23.name]
8165
9064
  }));
8166
9065
  }
8167
9066
  function addImport2(tracker, source, name) {
@@ -9013,7 +9912,7 @@ function compareTransitions(diffs, original, roundTripped) {
9013
9912
  severity: "error"
9014
9913
  });
9015
9914
  }
9016
- const rtMap = new Map(roundTripped.map((t22) => [t22.name, t22]));
9915
+ const rtMap = new Map(roundTripped.map((t23) => [t23.name, t23]));
9017
9916
  for (const transition of original) {
9018
9917
  const rt = rtMap.get(transition.name);
9019
9918
  if (!rt) {
@@ -9550,10 +10449,10 @@ ${output}`);
9550
10449
  fileMap[rel] = (0, import_fs3.readFileSync)(f, "utf-8");
9551
10450
  }
9552
10451
  (0, import_fs3.mkdirSync)(outDir, { recursive: true });
9553
- const result = compileProject2(fileMap, { mode });
9554
- const errors = result.errors.filter((e) => e.severity === "error");
9555
- const warnings = result.errors.filter((e) => e.severity === "warning");
9556
- const definitions2 = [result.ir];
10452
+ const result2 = compileProject2(fileMap, { mode });
10453
+ const errors = result2.errors.filter((e) => e.severity === "error");
10454
+ const warnings = result2.errors.filter((e) => e.severity === "warning");
10455
+ const definitions2 = [result2.ir];
9557
10456
  const errorDetails2 = [];
9558
10457
  for (const err of errors) {
9559
10458
  errorDetails2.push({ file: err.file, message: err.message, line: err.line });
@@ -9562,11 +10461,11 @@ ${output}`);
9562
10461
  for (const warn of warnings) {
9563
10462
  console.warn(` ! ${warn.file}${warn.line ? `:${warn.line}` : ""} ${warn.message}`);
9564
10463
  }
9565
- const irPath = (0, import_path2.join)(outDir, `${result.ir.slug}.workflow.json`);
9566
- (0, import_fs3.writeFileSync)(irPath, JSON.stringify(result.ir, null, 2), "utf-8");
10464
+ const irPath = (0, import_path2.join)(outDir, `${result2.ir.slug}.workflow.json`);
10465
+ (0, import_fs3.writeFileSync)(irPath, JSON.stringify(result2.ir, null, 2), "utf-8");
9567
10466
  console.log(` + ${(0, import_path2.basename)(irPath)}`);
9568
- const seenSlugs = /* @__PURE__ */ new Set([result.ir.slug]);
9569
- for (const child of result.childDefinitions) {
10467
+ const seenSlugs = /* @__PURE__ */ new Set([result2.ir.slug]);
10468
+ for (const child of result2.childDefinitions) {
9570
10469
  if (seenSlugs.has(child.slug)) continue;
9571
10470
  seenSlugs.add(child.slug);
9572
10471
  definitions2.push(child);
@@ -9596,14 +10495,14 @@ ${output}`);
9596
10495
  for (const file2 of allFiles) {
9597
10496
  try {
9598
10497
  const code = (0, import_fs3.readFileSync)(file2, "utf-8");
9599
- const result = (0, import_core6.transformSync)(code, {
10498
+ const result2 = (0, import_core6.transformSync)(code, {
9600
10499
  filename: file2,
9601
10500
  plugins: [[babelPlugin, { mode }]],
9602
10501
  parserOpts: { plugins: ["jsx", "typescript"], attachComment: true }
9603
10502
  });
9604
- const ir = result?.metadata?.mindmatrixIR;
9605
- const definition = result?.metadata?.mindmatrixDefinition;
9606
- const canonical = result?.metadata?.mindmatrixCanonical;
10503
+ const ir = result2?.metadata?.mindmatrixIR;
10504
+ const definition = result2?.metadata?.mindmatrixDefinition;
10505
+ const canonical = result2?.metadata?.mindmatrixCanonical;
9607
10506
  if (ir) {
9608
10507
  definitions.push(ir);
9609
10508
  const irErrors = ir.metadata?.errors;
@@ -9668,7 +10567,37 @@ ${output}`);
9668
10567
  }
9669
10568
  console.log(`
9670
10569
  [mindmatrix-react] Compiled ${compiled} workflows, ${errorCount} errors, ${warningCount} warnings`);
9671
- return { compiled, errors: errorCount, warnings: warningCount, definitions, errorDetails };
10570
+ const result = { compiled, errors: errorCount, warnings: warningCount, definitions, errorDetails };
10571
+ if (options.watch) {
10572
+ await startWatchMode(options);
10573
+ }
10574
+ return result;
10575
+ }
10576
+ async function startWatchMode(options) {
10577
+ const { watch: fsWatch } = await import("fs");
10578
+ const srcDir = options.src ?? "src/workflows";
10579
+ let debounce = null;
10580
+ console.log(`
10581
+ [mindmatrix-react] Watching ${srcDir} for changes... (Ctrl+C to stop)
10582
+ `);
10583
+ fsWatch(srcDir, { recursive: true }, (_event, filename) => {
10584
+ if (!filename) return;
10585
+ if (!filename.match(/\.(tsx?|jsx?)$/)) return;
10586
+ if (filename.includes("node_modules") || filename.includes("dist")) return;
10587
+ if (debounce) clearTimeout(debounce);
10588
+ debounce = setTimeout(async () => {
10589
+ const ts = (/* @__PURE__ */ new Date()).toLocaleTimeString();
10590
+ console.log(`
10591
+ [${ts}] Change detected: ${filename} \u2014 recompiling...`);
10592
+ try {
10593
+ await build({ ...options, watch: false, skipTypeCheck: true });
10594
+ } catch (e) {
10595
+ console.error(`[mindmatrix-react] Rebuild failed:`, e.message);
10596
+ }
10597
+ }, 300);
10598
+ });
10599
+ return new Promise(() => {
10600
+ });
9672
10601
  }
9673
10602
 
9674
10603
  // src/dev-server.ts