@mmapp/react-compiler 0.1.0-alpha.17 → 0.1.0-alpha.19

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 (190) hide show
  1. package/dist/babel/index.d.mts +1 -1
  2. package/dist/babel/index.d.ts +1 -1
  3. package/dist/babel/index.js +9 -6
  4. package/dist/babel/index.mjs +1 -1
  5. package/dist/chunk-26U577GB.mjs +3465 -0
  6. package/dist/chunk-2FBDFAX6.mjs +2362 -0
  7. package/dist/chunk-2REDFOER.mjs +931 -0
  8. package/dist/{chunk-FPAMQXKB.mjs → chunk-2UTXM2QX.mjs} +10 -20
  9. package/dist/chunk-2YDQTFAL.mjs +879 -0
  10. package/dist/chunk-2ZRKQE74.mjs +175 -0
  11. package/dist/chunk-3QHG2JWV.mjs +154 -0
  12. package/dist/chunk-466OWSTT.mjs +186 -0
  13. package/dist/chunk-467SFYOD.mjs +3127 -0
  14. package/dist/chunk-4AIJO7DZ.mjs +214 -0
  15. package/dist/chunk-4D43TZYL.mjs +7495 -0
  16. package/dist/chunk-4HX4PI4R.mjs +734 -0
  17. package/dist/chunk-4VU56NTZ.mjs +544 -0
  18. package/dist/chunk-4XHK6FWL.mjs +2058 -0
  19. package/dist/chunk-52C2JKH2.mjs +186 -0
  20. package/dist/chunk-52XHYD2V.mjs +214 -0
  21. package/dist/chunk-5GUFFFGL.mjs +148 -0
  22. package/dist/chunk-5N2FDDS6.mjs +214 -0
  23. package/dist/chunk-5ZSJXWZT.mjs +1646 -0
  24. package/dist/chunk-6CQOAAMV.mjs +1803 -0
  25. package/dist/chunk-6SEVAAVT.mjs +3516 -0
  26. package/dist/chunk-6YLR5ZDA.mjs +2829 -0
  27. package/dist/chunk-77UJB356.mjs +244 -0
  28. package/dist/chunk-7QOAJPQF.mjs +774 -0
  29. package/dist/chunk-A5RCMIBP.mjs +1795 -0
  30. package/dist/chunk-A63R3GKH.mjs +1803 -0
  31. package/dist/chunk-ABNTZXF5.mjs +951 -0
  32. package/dist/chunk-ADHWW56I.mjs +214 -0
  33. package/dist/chunk-AOGY2GK6.mjs +3292 -0
  34. package/dist/chunk-AXXUXRNA.mjs +1434 -0
  35. package/dist/chunk-BZLU5YK5.mjs +1025 -0
  36. package/dist/chunk-C7XCDDBH.mjs +1802 -0
  37. package/dist/chunk-CHLVKMQW.mjs +175 -0
  38. package/dist/chunk-CKGOZAB7.mjs +939 -0
  39. package/dist/chunk-CSXYDIVC.mjs +214 -0
  40. package/dist/chunk-CXTV4VGG.mjs +148 -0
  41. package/dist/chunk-D34RAZUX.mjs +2223 -0
  42. package/dist/chunk-DDIC7WM6.mjs +3127 -0
  43. package/dist/chunk-DPUQOBU6.mjs +4810 -0
  44. package/dist/chunk-E6MDVTGT.mjs +148 -0
  45. package/dist/chunk-EGKMUEM6.mjs +544 -0
  46. package/dist/chunk-EO6SYNCG.mjs +175 -0
  47. package/dist/chunk-EQGA6A6D.mjs +121 -0
  48. package/dist/chunk-EY2CSXYA.mjs +822 -0
  49. package/dist/chunk-FF5BQVII.mjs +148 -0
  50. package/dist/chunk-FIQ65CDR.mjs +925 -0
  51. package/dist/chunk-FOZXJFAR.mjs +186 -0
  52. package/dist/chunk-G2IAZ5Q6.mjs +148 -0
  53. package/dist/chunk-G7SMOWOL.mjs +828 -0
  54. package/dist/chunk-GK7NU6DO.mjs +214 -0
  55. package/dist/chunk-GMW45YVD.mjs +868 -0
  56. package/dist/chunk-HDSCPEHY.mjs +4061 -0
  57. package/dist/chunk-HJELFNEA.mjs +186 -0
  58. package/dist/chunk-HOIUP6IF.mjs +690 -0
  59. package/dist/chunk-HRJGDPNE.mjs +148 -0
  60. package/dist/chunk-I3AU7GRD.mjs +120 -0
  61. package/dist/chunk-I3VQQJZ6.mjs +2843 -0
  62. package/dist/chunk-IPTX5MJU.mjs +3223 -0
  63. package/dist/chunk-ITGUSH2Z.mjs +2783 -0
  64. package/dist/chunk-IXHBCAMF.mjs +3306 -0
  65. package/dist/chunk-J7JUAHS4.mjs +186 -0
  66. package/dist/chunk-J7TWJ3TM.mjs +2784 -0
  67. package/dist/chunk-JDPLDGVF.mjs +4810 -0
  68. package/dist/chunk-JK72MQ4N.mjs +877 -0
  69. package/dist/chunk-K2HHCAS2.mjs +148 -0
  70. package/dist/chunk-K5HX2SVL.mjs +1902 -0
  71. package/dist/chunk-KAUEQ2F3.mjs +148 -0
  72. package/dist/chunk-KFVVOS5N.mjs +925 -0
  73. package/dist/chunk-KIH4AN3Y.mjs +154 -0
  74. package/dist/chunk-KPDMN5IX.mjs +175 -0
  75. package/dist/chunk-LZL2IRCH.mjs +186 -0
  76. package/dist/chunk-MIZV3TAN.mjs +3293 -0
  77. package/dist/chunk-MRH4J7IX.mjs +2846 -0
  78. package/dist/chunk-NKBL5GUC.mjs +186 -0
  79. package/dist/chunk-NQCNSCF6.mjs +148 -0
  80. package/dist/chunk-NRP5J3BR.mjs +4811 -0
  81. package/dist/chunk-NTB7OEX2.mjs +2918 -0
  82. package/dist/chunk-NUPJYPFU.mjs +801 -0
  83. package/dist/chunk-NVQUTSQX.mjs +3128 -0
  84. package/dist/chunk-OGMG64EY.mjs +148 -0
  85. package/dist/chunk-OL5B2HTH.mjs +175 -0
  86. package/dist/chunk-OPJKP747.mjs +7506 -0
  87. package/dist/chunk-OQLGGBNE.mjs +2918 -0
  88. package/dist/chunk-OW4AQUDL.mjs +544 -0
  89. package/dist/chunk-OWI6XWCD.mjs +3375 -0
  90. package/dist/chunk-OZT2EAF2.mjs +2776 -0
  91. package/dist/chunk-PBRBRKIQ.mjs +175 -0
  92. package/dist/chunk-PRUMNNDI.mjs +3192 -0
  93. package/dist/chunk-QPNHDTSM.mjs +4839 -0
  94. package/dist/chunk-RNEIAJDR.mjs +897 -0
  95. package/dist/chunk-RY7POBNT.mjs +3127 -0
  96. package/dist/chunk-S6FJ4DXL.mjs +1813 -0
  97. package/dist/chunk-SU4E6E7B.mjs +3153 -0
  98. package/dist/chunk-SYUUKW5A.mjs +3379 -0
  99. package/dist/chunk-THB5SX2S.mjs +113 -0
  100. package/dist/chunk-THFYE5ZX.mjs +244 -0
  101. package/dist/chunk-TK3QMXIP.mjs +2921 -0
  102. package/dist/chunk-TRR2NPAV.mjs +248 -0
  103. package/dist/chunk-TTTTOT7P.mjs +1803 -0
  104. package/dist/chunk-TXONBY6A.mjs +7509 -0
  105. package/dist/chunk-U2PX3JSY.mjs +1933 -0
  106. package/dist/chunk-UASOWKDI.mjs +186 -0
  107. package/dist/chunk-UDDTWG5J.mjs +734 -0
  108. package/dist/chunk-UIWLAQCL.mjs +175 -0
  109. package/dist/chunk-UL2XZEMA.mjs +3128 -0
  110. package/dist/chunk-US3AVDAI.mjs +3456 -0
  111. package/dist/chunk-V5DIDOTT.mjs +148 -0
  112. package/dist/chunk-VLTKQDJ3.mjs +244 -0
  113. package/dist/chunk-VVC42PTS.mjs +175 -0
  114. package/dist/chunk-VX3T3NIR.mjs +897 -0
  115. package/dist/chunk-WBYMW4NQ.mjs +3450 -0
  116. package/dist/chunk-XMWUHQVV.mjs +939 -0
  117. package/dist/chunk-Y6FXYEAI.mjs +10 -0
  118. package/dist/chunk-YCWC2SCO.mjs +148 -0
  119. package/dist/chunk-YFS6JMYO.mjs +3342 -0
  120. package/dist/chunk-ZE67HOSN.mjs +148 -0
  121. package/dist/chunk-ZSK5TPIV.mjs +148 -0
  122. package/dist/cli/index.js +317 -656
  123. package/dist/cli/index.mjs +8 -8
  124. package/dist/config-PL24KEWL.mjs +219 -0
  125. package/dist/dev-server-Bs_sz2DG.d.mts +111 -0
  126. package/dist/dev-server-Bs_sz2DG.d.ts +111 -0
  127. package/dist/dev-server-RmGHIntF.d.mts +113 -0
  128. package/dist/dev-server-RmGHIntF.d.ts +113 -0
  129. package/dist/dev-server.js +194 -526
  130. package/dist/dev-server.mjs +4 -4
  131. package/dist/engine-binary-KQB23JDR.mjs +97 -0
  132. package/dist/envelope-DD7v0v6E.d.mts +265 -0
  133. package/dist/envelope-DD7v0v6E.d.ts +265 -0
  134. package/dist/envelope.js +9 -6
  135. package/dist/envelope.mjs +2 -2
  136. package/dist/index-B5gSgvnd.d.mts +44 -0
  137. package/dist/index-B5gSgvnd.d.ts +44 -0
  138. package/dist/index-Bs0MnR54.d.mts +103 -0
  139. package/dist/index-Bs0MnR54.d.ts +103 -0
  140. package/dist/index-DR0nNc_f.d.mts +101 -0
  141. package/dist/index-DR0nNc_f.d.ts +101 -0
  142. package/dist/index-revho_gS.d.mts +104 -0
  143. package/dist/index-revho_gS.d.ts +104 -0
  144. package/dist/index-vQjwYekL.d.mts +104 -0
  145. package/dist/index-vQjwYekL.d.ts +104 -0
  146. package/dist/index.d.mts +2 -2
  147. package/dist/index.d.ts +2 -2
  148. package/dist/index.js +198 -528
  149. package/dist/index.mjs +9 -8
  150. package/dist/init-2XLTUF7O.mjs +407 -0
  151. package/dist/init-7FJENUDK.mjs +407 -0
  152. package/dist/init-DQDX3QK6.mjs +369 -0
  153. package/dist/init-K3GVM4JS.mjs +538 -0
  154. package/dist/init-NXS5BJN3.mjs +454 -0
  155. package/dist/init-UC3FWPIW.mjs +367 -0
  156. package/dist/init-UNV5XIDE.mjs +367 -0
  157. package/dist/project-compiler-2HOPO7GC.mjs +10 -0
  158. package/dist/project-compiler-D245L5QR.mjs +10 -0
  159. package/dist/project-compiler-FUQRMB4X.mjs +10 -0
  160. package/dist/project-compiler-LA5OBI5P.mjs +10 -0
  161. package/dist/project-compiler-OP2VVGJQ.mjs +10 -0
  162. package/dist/project-compiler-PZNFE6AH.mjs +10 -0
  163. package/dist/project-compiler-QBVF6MFI.mjs +10 -0
  164. package/dist/project-compiler-VFR6CSDX.mjs +10 -0
  165. package/dist/project-compiler-WMJZA4UH.mjs +10 -0
  166. package/dist/project-compiler-XXS27TZT.mjs +10 -0
  167. package/dist/project-compiler-YYGDSHY5.mjs +10 -0
  168. package/dist/project-decompiler-5GY2KSG4.mjs +7 -0
  169. package/dist/project-decompiler-7I2OMUVY.mjs +7 -0
  170. package/dist/project-decompiler-US7GAVIC.mjs +7 -0
  171. package/dist/pull-2Q53HF3H.mjs +107 -0
  172. package/dist/pull-5AFHD3QG.mjs +109 -0
  173. package/dist/pull-65GUSX6F.mjs +109 -0
  174. package/dist/pull-6LVI4LMM.mjs +109 -0
  175. package/dist/pull-A2QUHW4K.mjs +109 -0
  176. package/dist/pull-B6T5BUKV.mjs +109 -0
  177. package/dist/pull-CKHWZT33.mjs +109 -0
  178. package/dist/pull-GM74ERRT.mjs +109 -0
  179. package/dist/pull-JBEQWVPE.mjs +109 -0
  180. package/dist/pull-P44LDRWB.mjs +109 -0
  181. package/dist/pull-W2US3T3E.mjs +109 -0
  182. package/dist/testing/index.js +9 -6
  183. package/dist/testing/index.mjs +1 -1
  184. package/dist/verify-3PPS4XAM.mjs +1833 -0
  185. package/dist/verify-GKEH5FZQ.mjs +1833 -0
  186. package/dist/verify-HDKUNHZ4.mjs +1833 -0
  187. package/dist/verify-SEIXUGN4.mjs +1833 -0
  188. package/dist/vite/index.js +10 -7
  189. package/dist/vite/index.mjs +2 -2
  190. package/package.json +2 -2
@@ -6468,7 +6468,8 @@ function convertOnEvent(sub) {
6468
6468
  };
6469
6469
  }
6470
6470
  function emitIR(extracted) {
6471
- const { slug, name, version, description, category, fields, states, transitions } = extracted;
6471
+ const { slug, name, version, description, category: rawCategory, fields, states, transitions } = extracted;
6472
+ const category = Array.isArray(rawCategory) ? rawCategory : [rawCategory];
6472
6473
  const stateArray = Array.from(states.values());
6473
6474
  if (stateArray.length === 0) {
6474
6475
  stateArray.push({
@@ -6856,13 +6857,15 @@ function emitCanonical(extracted, sourceFilename) {
6856
6857
  }
6857
6858
  ]
6858
6859
  });
6859
- const category = extracted.category;
6860
+ const rawCat = extracted.category;
6860
6861
  let categoryArray;
6861
- if (category.includes("/")) {
6862
- const [primary, ...tags] = category.split("/");
6862
+ if (Array.isArray(rawCat)) {
6863
+ categoryArray = rawCat;
6864
+ } else if (rawCat.includes("/")) {
6865
+ const [primary, ...tags] = rawCat.split("/");
6863
6866
  categoryArray = (0, import_player_core.normalizeCategory)(primary, ...tags);
6864
6867
  } else {
6865
- categoryArray = [category];
6868
+ categoryArray = [rawCat];
6866
6869
  }
6867
6870
  return {
6868
6871
  slug: ir.slug,
@@ -7009,7 +7012,7 @@ function compilerStateToWorkflow(state, metadata) {
7009
7012
  name: metadata.name || "Workflow",
7010
7013
  version: metadata.version || "0.1.0",
7011
7014
  description: metadata.description,
7012
- category: metadata.category || "workflow",
7015
+ category: metadata.categoryArray ? metadata.categoryArray : [metadata.category || "workflow"],
7013
7016
  fields: state.fields || [],
7014
7017
  states: state.states || /* @__PURE__ */ new Map(),
7015
7018
  transitions: state.transitions || [],
@@ -7787,7 +7790,7 @@ function extractRouterWorkflow(pages, options = {}) {
7787
7790
  name: "Router",
7788
7791
  version: "1.0.0",
7789
7792
  description: "Auto-derived router workflow from file-based routing",
7790
- category: "router",
7793
+ category: ["router"],
7791
7794
  fields,
7792
7795
  states,
7793
7796
  transitions,
@@ -7886,7 +7889,8 @@ function compileModel(filename, source, options = {}) {
7886
7889
  parserOpts: { plugins: parserPlugins, attachComment: true }
7887
7890
  });
7888
7891
  const ir = babelResult?.metadata?.mindmatrixIR ?? createEmptyModelIR(interfaceName);
7889
- ir.category = options.categoryOverride || annotation.category || "data";
7892
+ const catOverride = options.categoryOverride || annotation.category || "data";
7893
+ ir.category = Array.isArray(catOverride) ? catOverride : [catOverride];
7890
7894
  if (options.slugOverride) {
7891
7895
  ir.slug = options.slugOverride;
7892
7896
  }
@@ -7950,7 +7954,7 @@ function createEmptyModelIR(interfaceName) {
7950
7954
  name: interfaceName,
7951
7955
  version: "1.0.0",
7952
7956
  description: "Data model: " + interfaceName,
7953
- category: "data",
7957
+ category: ["data"],
7954
7958
  fields: [],
7955
7959
  states: [{
7956
7960
  name: "draft",
@@ -8118,7 +8122,7 @@ function buildRouterIR(routes, layouts, allParams, slugPrefix) {
8118
8122
  name: "Router",
8119
8123
  version: "1.0.0",
8120
8124
  description: "Auto-generated router from app/ directory structure",
8121
- category: "router",
8125
+ category: ["router"],
8122
8126
  fields,
8123
8127
  states,
8124
8128
  transitions,
@@ -8367,7 +8371,7 @@ function extractAction(source, filename) {
8367
8371
  slug,
8368
8372
  name: humanName,
8369
8373
  version: "0.1.0",
8370
- category: "action",
8374
+ category: ["action"],
8371
8375
  fields,
8372
8376
  states: states2,
8373
8377
  transitions: transitions2,
@@ -8419,7 +8423,7 @@ function extractAction(source, filename) {
8419
8423
  slug,
8420
8424
  name: humanName,
8421
8425
  version: "0.1.0",
8422
- category: "action",
8426
+ category: ["action"],
8423
8427
  fields,
8424
8428
  states,
8425
8429
  transitions,
@@ -9856,7 +9860,7 @@ function applyConfig(ir, config) {
9856
9860
  if (config.name) ir.name = config.name;
9857
9861
  if (config.version) ir.version = config.version;
9858
9862
  if (config.description !== void 0) ir.description = config.description;
9859
- if (config.category) ir.category = config.category;
9863
+ if (config.category) ir.category = Array.isArray(config.category) ? config.category : [config.category];
9860
9864
  if (!ir.metadata) ir.metadata = {};
9861
9865
  ir.metadata.stable_id = "def-" + ir.slug;
9862
9866
  ir.metadata.provenance = {
@@ -9872,7 +9876,7 @@ function createEmptyIR(config) {
9872
9876
  name: config.name || "Project",
9873
9877
  version: config.version || "0.1.0",
9874
9878
  description: config.description,
9875
- category: config.category || "workflow",
9879
+ category: Array.isArray(config.category) ? config.category : [config.category || "workflow"],
9876
9880
  fields: [],
9877
9881
  states: [{
9878
9882
  name: "draft",
@@ -10030,8 +10034,10 @@ function buildComposedResult(files, fileIRs, config, errors, warnings, options =
10030
10034
  if (isWorkflowFile(filename)) {
10031
10035
  workflowIRs.push(ir);
10032
10036
  } else if (isModelFile2(filename)) {
10033
- if (!ir.category || ir.category === "workflow") {
10034
- ir.category = "data";
10037
+ const cat = ir.category;
10038
+ const isDefault = !cat || cat === "workflow" || Array.isArray(cat) && cat.length === 1 && cat[0] === "workflow";
10039
+ if (isDefault) {
10040
+ ir.category = ["data"];
10035
10041
  }
10036
10042
  modelIRs.push(ir);
10037
10043
  } else if (isServerActionFile2(filename)) {
@@ -11171,7 +11177,7 @@ function mindmatrixReact(options) {
11171
11177
  slug: ir.slug,
11172
11178
  name: ir.name,
11173
11179
  version: ir.version,
11174
- category: ir.category || "workflow",
11180
+ category: ir.category || ["workflow"],
11175
11181
  fields: ir.fields || [],
11176
11182
  states: ir.states || [],
11177
11183
  transitions: ir.transitions || [],
@@ -11705,425 +11711,6 @@ async function startWatchMode(options) {
11705
11711
  });
11706
11712
  }
11707
11713
 
11708
- // src/cli/local-server.ts
11709
- var http = __toESM(require("http"));
11710
- var import_node_crypto = require("crypto");
11711
- var MemoryStore = class {
11712
- constructor() {
11713
- this.definitions = /* @__PURE__ */ new Map();
11714
- this.instances = /* @__PURE__ */ new Map();
11715
- this.slugIndex = /* @__PURE__ */ new Map();
11716
- }
11717
- // slug → id
11718
- // ── Definitions ──────────────────────────────────────────────────────
11719
- createDefinition(input) {
11720
- if (this.slugIndex.has(input.slug)) {
11721
- const existing = this.definitions.get(this.slugIndex.get(input.slug));
11722
- if (existing) return existing;
11723
- }
11724
- const now = (/* @__PURE__ */ new Date()).toISOString();
11725
- const def = {
11726
- id: input.id ?? (0, import_node_crypto.randomUUID)(),
11727
- slug: input.slug,
11728
- name: input.name,
11729
- version: input.version ?? "1.0.0",
11730
- description: input.description ?? null,
11731
- category: input.category ?? "workflow",
11732
- fields: input.fields ?? [],
11733
- states: input.states ?? [],
11734
- transitions: input.transitions ?? [],
11735
- roles: input.roles ?? [],
11736
- experience: input.experience ?? null,
11737
- metadata: input.metadata ?? {},
11738
- child_definitions: input.child_definitions ?? [],
11739
- is_immutable: input.is_immutable ?? false,
11740
- tags: input.tags ?? [],
11741
- inline_tags: input.inline_tags ?? [],
11742
- created_at: now,
11743
- updated_at: now
11744
- };
11745
- this.definitions.set(def.id, def);
11746
- this.slugIndex.set(def.slug, def.id);
11747
- return def;
11748
- }
11749
- getDefinition(idOrSlug) {
11750
- const byId = this.definitions.get(idOrSlug);
11751
- if (byId) return byId;
11752
- const id = this.slugIndex.get(idOrSlug);
11753
- if (id) return this.definitions.get(id);
11754
- return void 0;
11755
- }
11756
- listDefinitions(opts) {
11757
- let items = Array.from(this.definitions.values());
11758
- if (opts?.category) {
11759
- items = items.filter((d) => d.category === opts.category);
11760
- }
11761
- const total = items.length;
11762
- const offset = opts?.offset ?? 0;
11763
- const limit = opts?.limit ?? 50;
11764
- items = items.slice(offset, offset + limit);
11765
- return { items, total };
11766
- }
11767
- patchDefinition(id, patch) {
11768
- const def = this.definitions.get(id);
11769
- if (!def) return void 0;
11770
- Object.assign(def, patch, { updated_at: (/* @__PURE__ */ new Date()).toISOString() });
11771
- return def;
11772
- }
11773
- deleteDefinition(id) {
11774
- const def = this.definitions.get(id);
11775
- if (!def) return false;
11776
- this.slugIndex.delete(def.slug);
11777
- this.definitions.delete(id);
11778
- return true;
11779
- }
11780
- // ── Instances ────────────────────────────────────────────────────────
11781
- createInstance(input) {
11782
- const def = this.getDefinition(input.definition_id) ?? this.getDefinition(input.definition_slug);
11783
- if (!def) return null;
11784
- const initialState = def.states.find((s) => s.type === "START" || s.type === "initial");
11785
- const stateName = initialState?.name ?? "initial";
11786
- const stateData = {};
11787
- for (const field of def.fields) {
11788
- if (field.default_value !== void 0) {
11789
- stateData[field.name] = field.default_value;
11790
- }
11791
- }
11792
- Object.assign(stateData, input.state_data ?? {});
11793
- const now = (/* @__PURE__ */ new Date()).toISOString();
11794
- const inst = {
11795
- id: (0, import_node_crypto.randomUUID)(),
11796
- definition_id: def.id,
11797
- definition_slug: def.slug,
11798
- current_state: stateName,
11799
- state_data: stateData,
11800
- execution_lock_version: 0,
11801
- event_log: [{
11802
- event_type: "transition",
11803
- message: `Instance created in state '${stateName}'`,
11804
- timestamp: now
11805
- }],
11806
- created_at: now,
11807
- updated_at: now
11808
- };
11809
- this.instances.set(inst.id, inst);
11810
- return inst;
11811
- }
11812
- getInstance(id) {
11813
- return this.instances.get(id);
11814
- }
11815
- listInstances(opts) {
11816
- let items = Array.from(this.instances.values());
11817
- if (opts?.definition_id) {
11818
- items = items.filter((i) => i.definition_id === opts.definition_id);
11819
- }
11820
- const total = items.length;
11821
- const offset = opts?.offset ?? 0;
11822
- const limit = opts?.limit ?? 50;
11823
- items = items.slice(offset, offset + limit);
11824
- return { items, total };
11825
- }
11826
- // ── Execute Action (Transition) ──────────────────────────────────────
11827
- executeAction(input) {
11828
- const def = this.getDefinition(input.definition_id);
11829
- if (!def) return { success: false, error: "Definition not found" };
11830
- let inst;
11831
- if (input.instance_id) {
11832
- const existing = this.instances.get(input.instance_id);
11833
- if (!existing) return { success: false, error: "Instance not found" };
11834
- inst = existing;
11835
- } else {
11836
- const created = this.createInstance({
11837
- definition_id: def.id,
11838
- definition_slug: def.slug,
11839
- state_data: input.payload
11840
- });
11841
- if (!created) return { success: false, error: "Failed to create instance" };
11842
- inst = created;
11843
- }
11844
- if (input.payload && input.instance_id) {
11845
- Object.assign(inst.state_data, input.payload);
11846
- }
11847
- const transition = def.transitions.find((t23) => t23.name === input.action_name && t23.from.includes(inst.current_state));
11848
- if (!transition) {
11849
- return {
11850
- success: false,
11851
- instance_id: inst.id,
11852
- from_state: inst.current_state,
11853
- to_state: null,
11854
- state_data: inst.state_data,
11855
- error: `No transition '${input.action_name}' from state '${inst.current_state}'`
11856
- };
11857
- }
11858
- const fromState = inst.current_state;
11859
- const now = (/* @__PURE__ */ new Date()).toISOString();
11860
- const events = [];
11861
- let lastEvalResult = null;
11862
- events.push({ event_type: "transition", message: `Transition '${transition.name}' started: ${fromState} \u2192 ${transition.to}`, timestamp: now });
11863
- for (const action of transition.actions ?? []) {
11864
- try {
11865
- if (action.type === "set_field") {
11866
- const field = action.config?.field;
11867
- if (action.config?.expression) {
11868
- const expr = action.config.expression;
11869
- const result = this.evaluateSimpleExpression(expr, inst.state_data);
11870
- inst.state_data[field] = result;
11871
- } else if (action.config?.value !== void 0) {
11872
- inst.state_data[field] = action.config.value;
11873
- }
11874
- events.push({ event_type: "action_executed", message: `transition action 'set_field' succeeded`, timestamp: now });
11875
- } else if (action.type === "eval") {
11876
- const expr = action.config?.expression;
11877
- lastEvalResult = this.evaluateSimpleExpression(expr, inst.state_data);
11878
- events.push({ event_type: "action_executed", message: `transition action 'eval' succeeded`, timestamp: now });
11879
- } else {
11880
- events.push({ event_type: "action_executed", message: `transition action '${action.type}' succeeded (no-op in local mode)`, timestamp: now });
11881
- }
11882
- } catch (err) {
11883
- const msg = err instanceof Error ? err.message : String(err);
11884
- events.push({ event_type: "action_failed", message: `transition action '${action.type}' failed: ${msg}`, timestamp: now });
11885
- return {
11886
- success: false,
11887
- instance_id: inst.id,
11888
- from_state: fromState,
11889
- to_state: null,
11890
- state_data: inst.state_data,
11891
- event_log: events,
11892
- error: `transition action failed: ${msg}`
11893
- };
11894
- }
11895
- }
11896
- inst.current_state = transition.to;
11897
- inst.execution_lock_version++;
11898
- inst.updated_at = now;
11899
- events.push({ event_type: "transition", message: `State changed: ${fromState} \u2192 ${transition.to}`, timestamp: now });
11900
- inst.event_log.push(...events);
11901
- return {
11902
- success: true,
11903
- instance_id: inst.id,
11904
- from_state: fromState,
11905
- to_state: transition.to,
11906
- state_data: inst.state_data,
11907
- result: lastEvalResult,
11908
- event_log: events
11909
- };
11910
- }
11911
- /**
11912
- * Minimal expression evaluator for local dev mode.
11913
- * Handles: field references, arithmetic, string literals, simple comparisons.
11914
- * Does NOT handle: while loops, if/else, function calls, multi-statement blocks.
11915
- * For full evaluation, use mm-napi when available.
11916
- */
11917
- evaluateSimpleExpression(expr, context) {
11918
- if (context[expr] !== void 0) return context[expr];
11919
- const arithMatch = expr.match(/^(\w+)\s*([+\-*/])\s*(\d+(?:\.\d+)?)$/);
11920
- if (arithMatch) {
11921
- const [, field, op, numStr] = arithMatch;
11922
- const left = Number(context[field] ?? 0);
11923
- const right = Number(numStr);
11924
- switch (op) {
11925
- case "+":
11926
- return left + right;
11927
- case "-":
11928
- return left - right;
11929
- case "*":
11930
- return left * right;
11931
- case "/":
11932
- return right !== 0 ? left / right : 0;
11933
- }
11934
- }
11935
- if (/^\d+(\.\d+)?$/.test(expr.trim())) {
11936
- return Number(expr.trim());
11937
- }
11938
- const strMatch = expr.match(/^["'](.*)["']$/);
11939
- if (strMatch) return strMatch[1];
11940
- try {
11941
- const keys = Object.keys(context);
11942
- const values = Object.values(context);
11943
- const fn = new Function(...keys, `"use strict"; return (${expr});`);
11944
- return fn(...values);
11945
- } catch {
11946
- return null;
11947
- }
11948
- }
11949
- };
11950
- async function startLocalServer(options = {}) {
11951
- const { port = 4200, noAuth = true } = options;
11952
- const store = new MemoryStore();
11953
- const startedAt = (/* @__PURE__ */ new Date()).toISOString();
11954
- function json(res, status, body) {
11955
- const data = JSON.stringify(body);
11956
- res.writeHead(status, {
11957
- "Content-Type": "application/json",
11958
- "Access-Control-Allow-Origin": "*",
11959
- "Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
11960
- "Access-Control-Allow-Headers": "Content-Type, Authorization",
11961
- "Content-Length": Buffer.byteLength(data)
11962
- });
11963
- res.end(data);
11964
- }
11965
- function readBody(req) {
11966
- return new Promise((resolve2, reject) => {
11967
- const chunks = [];
11968
- req.on("data", (chunk) => chunks.push(chunk));
11969
- req.on("end", () => resolve2(Buffer.concat(chunks).toString()));
11970
- req.on("error", reject);
11971
- });
11972
- }
11973
- function parseQuery(url) {
11974
- const idx = url.indexOf("?");
11975
- if (idx === -1) return {};
11976
- const params = {};
11977
- const qs = url.slice(idx + 1);
11978
- for (const pair of qs.split("&")) {
11979
- const [k, v] = pair.split("=");
11980
- if (k) params[decodeURIComponent(k)] = decodeURIComponent(v ?? "");
11981
- }
11982
- return params;
11983
- }
11984
- const server = http.createServer(async (req, res) => {
11985
- const method = req.method?.toUpperCase() ?? "GET";
11986
- const rawUrl = req.url ?? "/";
11987
- const queryStart = rawUrl.indexOf("?");
11988
- const path = queryStart >= 0 ? rawUrl.slice(0, queryStart) : rawUrl;
11989
- const query = parseQuery(rawUrl);
11990
- if (method === "OPTIONS") {
11991
- res.writeHead(204, {
11992
- "Access-Control-Allow-Origin": "*",
11993
- "Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
11994
- "Access-Control-Allow-Headers": "Content-Type, Authorization",
11995
- "Access-Control-Max-Age": "86400"
11996
- });
11997
- res.end();
11998
- return;
11999
- }
12000
- try {
12001
- if (path === "/health" && method === "GET") {
12002
- return json(res, 200, {
12003
- status: "ok",
12004
- service: "mm-local-dev",
12005
- mode: "in-memory",
12006
- started_at: startedAt,
12007
- definitions: store.definitions.size,
12008
- instances: store.instances.size
12009
- });
12010
- }
12011
- if (path === "/api/v1/auth/login" && (method === "POST" || method === "GET")) {
12012
- return json(res, 200, {
12013
- token: "dev-token-local",
12014
- user: {
12015
- id: "dev-user-001",
12016
- email: "dev@localhost",
12017
- role: "admin",
12018
- name: "Local Developer"
12019
- }
12020
- });
12021
- }
12022
- if (path === "/api/v1/workflow/definitions" && method === "GET") {
12023
- const result = store.listDefinitions({
12024
- category: query.category,
12025
- limit: query.limit ? parseInt(query.limit, 10) : void 0,
12026
- offset: query.offset ? parseInt(query.offset, 10) : void 0
12027
- });
12028
- if (query.slug) {
12029
- const def = store.getDefinition(query.slug);
12030
- return json(res, 200, { items: def ? [def] : [], total: def ? 1 : 0 });
12031
- }
12032
- return json(res, 200, result);
12033
- }
12034
- const defMatch = path.match(/^\/api\/v1\/workflow\/definitions\/([^/]+)$/);
12035
- if (defMatch && method === "GET") {
12036
- const def = store.getDefinition(defMatch[1]);
12037
- if (!def) return json(res, 404, { error: "Not found" });
12038
- return json(res, 200, def);
12039
- }
12040
- if (path === "/api/v1/workflow/definitions" && method === "POST") {
12041
- const body = JSON.parse(await readBody(req));
12042
- const def = store.createDefinition(body);
12043
- return json(res, 201, def);
12044
- }
12045
- if (defMatch && method === "PATCH") {
12046
- const body = JSON.parse(await readBody(req));
12047
- const updated = store.patchDefinition(defMatch[1], body);
12048
- if (!updated) return json(res, 404, { error: "Not found" });
12049
- return json(res, 200, updated);
12050
- }
12051
- if (defMatch && method === "DELETE") {
12052
- const deleted = store.deleteDefinition(defMatch[1]);
12053
- if (!deleted) return json(res, 404, { error: "Not found" });
12054
- return json(res, 204, null);
12055
- }
12056
- if (path === "/api/v1/workflow/instances" && method === "GET") {
12057
- const result = store.listInstances({
12058
- definition_id: query.definition_id,
12059
- limit: query.limit ? parseInt(query.limit, 10) : void 0,
12060
- offset: query.offset ? parseInt(query.offset, 10) : void 0
12061
- });
12062
- return json(res, 200, result);
12063
- }
12064
- if (path === "/api/v1/workflow/instances" && method === "POST") {
12065
- const body = JSON.parse(await readBody(req));
12066
- const inst = store.createInstance(body);
12067
- if (!inst) return json(res, 404, { error: "Definition not found" });
12068
- return json(res, 201, inst);
12069
- }
12070
- const instMatch = path.match(/^\/api\/v1\/workflow\/instances\/([^/]+)$/);
12071
- if (instMatch && method === "GET") {
12072
- const inst = store.getInstance(instMatch[1]);
12073
- if (!inst) return json(res, 404, { error: "Not found" });
12074
- return json(res, 200, inst);
12075
- }
12076
- if (path === "/api/v1/workflow/execute-action" && method === "POST") {
12077
- const body = JSON.parse(await readBody(req));
12078
- const result = store.executeAction(body);
12079
- return json(res, 200, result);
12080
- }
12081
- const dataMatch = path.match(/^\/api\/v1\/data\/([^/]+)$/);
12082
- if (dataMatch && method === "GET") {
12083
- const def = store.getDefinition(dataMatch[1]);
12084
- if (!def) return json(res, 404, { error: "Not found" });
12085
- const instances = store.listInstances({ definition_id: def.id });
12086
- return json(res, 200, instances);
12087
- }
12088
- if (path.startsWith("/api/v1/")) {
12089
- return json(res, 501, { error: "Not implemented in local dev mode", path, method });
12090
- }
12091
- return json(res, 404, { error: "Not found", path });
12092
- } catch (err) {
12093
- const message = err instanceof Error ? err.message : String(err);
12094
- console.error(`[mm-local] ${method} ${path} \u2014 Error: ${message}`);
12095
- return json(res, 500, { error: message });
12096
- }
12097
- });
12098
- return new Promise((resolve2, reject) => {
12099
- server.on("error", (err) => {
12100
- if (err.code === "EADDRINUSE") {
12101
- reject(new Error(`Port ${port} is already in use. Is another server running?`));
12102
- } else {
12103
- reject(err);
12104
- }
12105
- });
12106
- server.listen(port, () => {
12107
- console.log(`[mm-local] Local API server running at http://localhost:${port}`);
12108
- console.log(`[mm-local] Mode: in-memory (data lost on restart)`);
12109
- console.log(`[mm-local] Auth: disabled (all requests accepted)`);
12110
- resolve2({
12111
- server,
12112
- port,
12113
- store,
12114
- async close() {
12115
- return new Promise((res) => {
12116
- server.close(() => {
12117
- console.log("[mm-local] Local API server stopped");
12118
- res();
12119
- });
12120
- });
12121
- }
12122
- });
12123
- });
12124
- });
12125
- }
12126
-
12127
11714
  // src/dev-server.ts
12128
11715
  var currentErrors = null;
12129
11716
  function escapeHtml(s) {
@@ -12300,34 +11887,33 @@ async function createDevServer(options = {}) {
12300
11887
  open = false
12301
11888
  } = options;
12302
11889
  const clients = /* @__PURE__ */ new Set();
12303
- let localServer = null;
12304
11890
  let apiUrl;
12305
- let isLocalMode = false;
12306
- if (rawApiUrl === "local") {
12307
- localServer = await startLocalServer({ port: 4200 });
12308
- apiUrl = "http://localhost:4200/api/v1";
12309
- isLocalMode = true;
12310
- } else if (rawApiUrl === "auto") {
12311
- const defaultRemote = "https://dev.mindmatrix.club/api/v1";
12312
- const remoteHealth = await checkBackendHealth(defaultRemote);
12313
- if (remoteHealth.ok) {
12314
- apiUrl = defaultRemote;
12315
- } else {
12316
- const localHealth = await checkBackendHealth("http://localhost:4200/api/v1");
12317
- if (localHealth.ok) {
12318
- apiUrl = "http://localhost:4200/api/v1";
11891
+ if (rawApiUrl === "local" || rawApiUrl === "auto") {
11892
+ const localHealth = await checkBackendHealth("http://localhost:4200/api/v1");
11893
+ if (localHealth.ok) {
11894
+ apiUrl = "http://localhost:4200/api/v1";
11895
+ } else if (rawApiUrl === "auto") {
11896
+ const defaultRemote = "https://dev.mindmatrix.club/api/v1";
11897
+ const remoteHealth = await checkBackendHealth(defaultRemote);
11898
+ if (remoteHealth.ok) {
11899
+ apiUrl = defaultRemote;
12319
11900
  } else {
12320
- console.log("[mm-dev] No backend detected \u2014 starting local in-memory API server...");
12321
- localServer = await startLocalServer({ port: 4200 });
11901
+ console.error("[mm-dev] No backend detected. Start the engine first:");
11902
+ console.error(" mmrc dev (auto-starts engine)");
11903
+ console.error(" mmrc engine start (manual start)");
11904
+ console.error("[mm-dev] Or specify a remote API: mmrc dev --api-url https://...");
12322
11905
  apiUrl = "http://localhost:4200/api/v1";
12323
- isLocalMode = true;
12324
11906
  }
11907
+ } else {
11908
+ console.error("[mm-dev] Local engine not running on port 4200.");
11909
+ console.error(" Start it with: mmrc dev (or mmrc engine start)");
11910
+ apiUrl = "http://localhost:4200/api/v1";
12325
11911
  }
12326
11912
  } else {
12327
11913
  apiUrl = rawApiUrl;
12328
11914
  }
12329
- const token = isLocalMode ? "dev-token-local" : await resolveDevToken(apiUrl, explicitToken);
12330
- const health = isLocalMode ? { ok: true, version: "local", db: "in-memory" } : await checkBackendHealth(apiUrl);
11915
+ const token = await resolveDevToken(apiUrl, explicitToken);
11916
+ const health = await checkBackendHealth(apiUrl);
12331
11917
  let initialSlug, initialCompiled = 0, initialDeployed = false, initialErrors = 0;
12332
11918
  if (token && health.ok) {
12333
11919
  const r = await initialBuildDeploy(src, outDir, mode, apiUrl, token);
@@ -12387,74 +11973,163 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
12387
11973
  `;
12388
11974
  }
12389
11975
  };
12390
- const devHtml = `<!DOCTYPE html>
11976
+ const { existsSync: fsExists } = await import("fs");
11977
+ const projectIndexPath = require("path").join(process.cwd(), "index.html");
11978
+ const hasProjectIndex = fsExists(projectIndexPath);
11979
+ if (!hasProjectIndex) {
11980
+ const { writeFileSync: fsWrite } = await import("fs");
11981
+ fsWrite(projectIndexPath, `<!DOCTYPE html>
12391
11982
  <html lang="en">
12392
11983
  <head>
12393
11984
  <meta charset="UTF-8">
12394
11985
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
12395
11986
  <title>MindMatrix Dev</title>
12396
- <style>
12397
- * { margin: 0; padding: 0; box-sizing: border-box; }
12398
- body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #fafafa; color: #111; }
12399
- #root { min-height: 100vh; }
12400
- .mm-loading { display: flex; align-items: center; justify-content: center; min-height: 100vh; flex-direction: column; gap: 12px; }
12401
- .mm-loading h1 { font-size: 20px; font-weight: 600; color: #333; }
12402
- .mm-loading p { color: #888; font-size: 14px; }
12403
- </style>
12404
11987
  </head>
12405
11988
  <body>
12406
- <div id="root">
12407
- <div class="mm-loading">
12408
- <h1>MindMatrix Dev</h1>
12409
- <p>Loading...</p>
12410
- </div>
12411
- </div>
12412
- <script type="module">
12413
- import React from 'react';
12414
- import { createRoot } from 'react-dom/client';
11989
+ <div id="root"></div>
11990
+ <script type="module" src="/__mm_dev_entry.tsx"></script>
11991
+ </body>
11992
+ </html>`, "utf-8");
11993
+ }
11994
+ const devEntryPlugin = {
11995
+ name: "mindmatrix-dev-entry",
11996
+ resolveId(id) {
11997
+ if (id === "/__mm_dev_entry.tsx") return id;
11998
+ return null;
11999
+ },
12000
+ load(id) {
12001
+ if (id !== "/__mm_dev_entry.tsx") return null;
12002
+ return `
12003
+ import React, { useState, useEffect } from 'react';
12004
+ import { createRoot } from 'react-dom/client';
12005
+ import { DevPlayer } from '@mmapp/react/player';
12006
+ import { PlayerProvider, ExperienceRenderer, createApiResolver } from '@mmapp/react/player';
12415
12007
 
12416
- function App() {
12417
- const [data, setData] = React.useState({ definitions: [], instances: [] });
12418
- const [error, setError] = React.useState(null);
12008
+ // Detect API base URL \u2014 proxy through dev server or use direct URL
12009
+ const API_BASE = window.location.origin + '/api/v1';
12010
+ const resolver = createApiResolver({ baseUrl: API_BASE, token: () => localStorage.getItem('auth_token') });
12419
12011
 
12420
- React.useEffect(() => {
12421
- fetch('/api/v1/workflow/definitions')
12422
- .then(r => r.ok ? r.json() : Promise.reject('API ' + r.status))
12423
- .then(defs => setData(d => ({ ...d, definitions: Array.isArray(defs) ? defs : defs.data || [] })))
12424
- .catch(e => setError(String(e)));
12425
- }, []);
12012
+ /**
12013
+ * Prepare experience tree for rendering.
12014
+ * Attaches metadata.dataSources to the root node and remaps
12015
+ * dataSource slugs to use definition-relative naming.
12016
+ *
12017
+ * @param definition - The main blueprint definition
12018
+ * @param allDefinitions - ALL definitions from the API (used for slug resolution)
12019
+ */
12020
+ function prepareTree(definition, allDefinitions) {
12021
+ const exp = definition.experience;
12022
+ if (!exp || typeof exp !== 'object') return null;
12426
12023
 
12427
- if (error) return React.createElement('div', { style: { padding: 40 } },
12428
- React.createElement('h1', null, 'MindMatrix Dev'),
12429
- React.createElement('p', { style: { color: '#c00', marginTop: 8 } }, 'API Error: ' + error),
12430
- React.createElement('p', { style: { color: '#888', marginTop: 8 } }, 'The engine is running but the API returned an error. This may be an auth issue in SQLite mode.')
12431
- );
12024
+ const meta = definition.metadata || {};
12025
+ const dataSources = meta.dataSources || [];
12026
+ const mutationTargets = meta.mutationTargets || [];
12432
12027
 
12433
- return React.createElement('div', { style: { padding: 40, maxWidth: 800 } },
12434
- React.createElement('h1', { style: { marginBottom: 16 } }, 'MindMatrix Dev'),
12435
- React.createElement('p', { style: { color: '#666', marginBottom: 24 } },
12436
- data.definitions.length + ' definition(s) deployed'),
12437
- data.definitions.map((def, i) =>
12438
- React.createElement('div', { key: i, style: { border: '1px solid #ddd', borderRadius: 8, padding: 16, marginBottom: 12, background: '#fff' } },
12439
- React.createElement('h3', { style: { marginBottom: 4 } }, def.name || def.slug || 'Unnamed'),
12440
- React.createElement('p', { style: { color: '#888', fontSize: 13 } },
12441
- 'slug: ' + (def.slug || '?') + ' | states: ' + (def.states?.length || 0) + ' | fields: ' + (def.fields?.length || 0))
12442
- )
12443
- ),
12444
- data.definitions.length === 0 && React.createElement('p', { style: { color: '#888' } },
12445
- 'No definitions deployed yet. Edit your model files and save \u2014 mmrc dev will auto-compile and deploy.')
12446
- );
12028
+ // Build a slug map from ALL deployed definitions
12029
+ // This resolves bare model names (e.g. "item") to full slugs (e.g. "tutorial-1-item")
12030
+ const blueprintSlug = definition.slug || '';
12031
+ const allSlugs = (allDefinitions || []).map(d => d.slug).filter(Boolean);
12032
+
12033
+ function resolveSlug(bareSlug) {
12034
+ if (!bareSlug) return bareSlug;
12035
+ // Already a full slug (contains hyphen matching a known definition)
12036
+ if (allSlugs.includes(bareSlug)) return bareSlug;
12037
+ // Try blueprint-prefixed slug: "item" \u2192 "tutorial-1-item"
12038
+ const prefixed = blueprintSlug + '-' + bareSlug;
12039
+ if (allSlugs.includes(prefixed)) return prefixed;
12040
+ // Try matching by suffix across all definitions
12041
+ const match = allSlugs.find(s => s.endsWith('-' + bareSlug));
12042
+ if (match) return match;
12043
+ // Return original (will attempt as-is)
12044
+ return bareSlug;
12045
+ }
12046
+
12047
+ // Clone root node and attach dataSources
12048
+ const root = { ...exp };
12049
+ if (dataSources.length > 0 && !root.dataSources) {
12050
+ root.dataSources = dataSources.map(ds => ({
12051
+ ...ds,
12052
+ slug: resolveSlug(ds.slug),
12053
+ }));
12054
+ }
12055
+
12056
+ // Remap mutation targets the same way
12057
+ if (mutationTargets.length > 0) {
12058
+ const resolvedTargets = mutationTargets.map(t => resolveSlug(t));
12059
+ root.config = { ...(root.config || {}), _mutationTargets: resolvedTargets };
12060
+ }
12061
+
12062
+ return root;
12063
+ }
12064
+
12065
+ function App() {
12066
+ const [tree, setTree] = useState(null);
12067
+ const [error, setError] = useState(null);
12068
+
12069
+ useEffect(() => {
12070
+ async function loadTree() {
12071
+ try {
12072
+ const res = await fetch(API_BASE + '/workflow/definitions');
12073
+ const json = await res.json();
12074
+ const items = json.items || json.data || [];
12075
+ // Find the main blueprint definition (has experience tree)
12076
+ const main = items.find(d => d.experience && !(Array.isArray(d.category) ? d.category.includes('data') : d.category === 'data')) || items.find(d => d.experience) || items[0];
12077
+ if (main?.experience) {
12078
+ const prepared = prepareTree(main, items);
12079
+ if (prepared) {
12080
+ setTree(prepared);
12081
+ return;
12082
+ }
12083
+ }
12084
+ if (main) {
12085
+ // No experience tree \u2014 show definition info
12086
+ setTree({
12087
+ type: 'Stack',
12088
+ props: { style: { padding: 40, gap: 16 } },
12089
+ children: [
12090
+ { type: 'Text', props: { children: main.name || main.slug, style: { fontSize: 24, fontWeight: 'bold' } } },
12091
+ { type: 'Text', props: { children: (main.states?.length || 0) + ' states, ' + (main.fields?.length || 0) + ' fields', style: { color: '#666' } } },
12092
+ ...items.map((d, i) => ({
12093
+ type: 'Card',
12094
+ props: { key: i, style: { padding: 16, border: '1px solid #ddd', borderRadius: 8 } },
12095
+ children: [
12096
+ { type: 'Text', props: { children: d.name || d.slug, style: { fontWeight: 600 } } },
12097
+ { type: 'Text', props: { children: 'slug: ' + d.slug + ' | ' + (d.states?.length || 0) + ' states', style: { fontSize: 13, color: '#888' } } },
12098
+ ],
12099
+ })),
12100
+ ],
12101
+ });
12102
+ }
12103
+ } catch (e) {
12104
+ setError(e.message);
12105
+ }
12447
12106
  }
12107
+ loadTree();
12108
+ }, []);
12448
12109
 
12449
- createRoot(document.getElementById('root')).render(React.createElement(App));
12450
- </script>
12451
- </body>
12452
- </html>`;
12453
- const { mkdtempSync, writeFileSync: writeFileSync5 } = await import("fs");
12454
- const { join: join4 } = await import("path");
12455
- const { tmpdir } = await import("os");
12456
- const devRoot = mkdtempSync(join4(tmpdir(), "mm-dev-"));
12457
- writeFileSync5(join4(devRoot, "index.html"), devHtml, "utf-8");
12110
+ if (error) return React.createElement('div', { style: { padding: 40 } },
12111
+ React.createElement('h1', null, 'MindMatrix Dev'),
12112
+ React.createElement('p', { style: { color: '#c00' } }, 'Error: ' + error)
12113
+ );
12114
+
12115
+ if (!tree) return React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh' } },
12116
+ React.createElement('p', null, 'Loading...')
12117
+ );
12118
+
12119
+ // If tree has 'component' field, use ExperienceRenderer; otherwise legacy DevPlayer
12120
+ if (tree.component) {
12121
+ return React.createElement(PlayerProvider, { resolver },
12122
+ React.createElement(ExperienceRenderer, { tree, className: 'mm-experience-root' })
12123
+ );
12124
+ }
12125
+
12126
+ return React.createElement(DevPlayer, { tree, title: document.title || 'MindMatrix Dev' });
12127
+ }
12128
+
12129
+ createRoot(document.getElementById('root')).render(React.createElement(App));
12130
+ `;
12131
+ }
12132
+ };
12458
12133
  let deployInFlight = false;
12459
12134
  const compileDeployPlugin = {
12460
12135
  name: "mindmatrix-dev-compile-deploy",
@@ -12485,16 +12160,16 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
12485
12160
  }
12486
12161
  };
12487
12162
  const viteConfig = {
12488
- // Physical index.html lives in a temp dir so Vite serves it natively.
12489
- root: devRoot,
12490
- // Pre-bundle React so Vite doesn't warn about missing entry point.
12163
+ // Use the blueprint directory as Vite root (has node_modules with React).
12164
+ root: process.cwd(),
12165
+ // Pre-bundle React and the player for fast dev startup.
12491
12166
  optimizeDeps: { include: ["react", "react-dom/client"] },
12492
12167
  server: {
12493
12168
  port,
12494
12169
  open,
12495
12170
  host: true,
12496
12171
  // Allow serving files from the real project directory (fs.allow).
12497
- fs: { allow: [devRoot, process.cwd(), ".."] },
12172
+ fs: { allow: [process.cwd(), ".."] },
12498
12173
  proxy: {
12499
12174
  "/api": { target: proxyTarget, changeOrigin: true, secure: true, ws: true },
12500
12175
  "/health": { target: proxyTarget, changeOrigin: true, secure: true },
@@ -12504,6 +12179,7 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
12504
12179
  plugins: [
12505
12180
  mindmatrixReact(pluginOpts),
12506
12181
  compileDeployPlugin,
12182
+ devEntryPlugin,
12507
12183
  devPlayerPlugin,
12508
12184
  { name: "mindmatrix-error-overlay", configureServer(server) {
12509
12185
  server.middlewares.use(errorOverlayMiddleware());
@@ -12511,8 +12187,8 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
12511
12187
  ],
12512
12188
  logLevel: "warn"
12513
12189
  };
12514
- const { createServer: createServer2 } = await import("vite");
12515
- const vite = await createServer2(viteConfig);
12190
+ const { createServer } = await import("vite");
12191
+ const vite = await createServer(viteConfig);
12516
12192
  await vite.listen();
12517
12193
  const resolvedPort = vite.config.server.port ?? port;
12518
12194
  if (enableWs && vite.httpServer) {
@@ -12530,7 +12206,7 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
12530
12206
  } catch {
12531
12207
  }
12532
12208
  }
12533
- printBanner({ port: resolvedPort, apiUrl: isLocalMode ? `${apiUrl} (local in-memory)` : apiUrl, src, include, health, token: !!token, compiled: initialCompiled, deployed: initialDeployed, slug: initialSlug, errors: initialErrors });
12209
+ printBanner({ port: resolvedPort, apiUrl, src, include, health, token: !!token, compiled: initialCompiled, deployed: initialDeployed, slug: initialSlug, errors: initialErrors });
12534
12210
  return {
12535
12211
  vite,
12536
12212
  port: resolvedPort,
@@ -12562,14 +12238,6 @@ createRoot(document.getElementById('root')).render(React.createElement(App));
12562
12238
  clients.clear();
12563
12239
  currentErrors = null;
12564
12240
  await vite.close();
12565
- if (localServer) {
12566
- await localServer.close();
12567
- }
12568
- try {
12569
- const { rmSync } = await import("fs");
12570
- rmSync(devRoot, { recursive: true, force: true });
12571
- } catch {
12572
- }
12573
12241
  }
12574
12242
  };
12575
12243
  }