@mmapp/react-compiler 0.1.0-alpha.1

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 (314) hide show
  1. package/README.md +107 -0
  2. package/compile-blueprint-chat.mjs +99 -0
  3. package/compile-blueprint-glass-console.mjs +98 -0
  4. package/compile-chat-defs.mjs +92 -0
  5. package/dist/babel/index.d.mts +3 -0
  6. package/dist/babel/index.d.ts +3 -0
  7. package/dist/babel/index.js +4851 -0
  8. package/dist/babel/index.mjs +7 -0
  9. package/dist/chunk-26U577GB.mjs +3465 -0
  10. package/dist/chunk-2FBDFAX6.mjs +2362 -0
  11. package/dist/chunk-2L4QSMXG.mjs +175 -0
  12. package/dist/chunk-2REDFOER.mjs +931 -0
  13. package/dist/chunk-46YKSHQR.mjs +175 -0
  14. package/dist/chunk-4XHK6FWL.mjs +2058 -0
  15. package/dist/chunk-5M7DKKBC.mjs +215 -0
  16. package/dist/chunk-5VNJ7C6N.mjs +154 -0
  17. package/dist/chunk-6CQOAAMV.mjs +1803 -0
  18. package/dist/chunk-6SEVAAVT.mjs +3516 -0
  19. package/dist/chunk-6YLR5ZDA.mjs +2829 -0
  20. package/dist/chunk-AOGY2GK6.mjs +3292 -0
  21. package/dist/chunk-AXXUXRNA.mjs +1434 -0
  22. package/dist/chunk-CHLVKMQW.mjs +175 -0
  23. package/dist/chunk-CKGOZAB7.mjs +939 -0
  24. package/dist/chunk-D34RAZUX.mjs +2223 -0
  25. package/dist/chunk-EQGA6A6D.mjs +121 -0
  26. package/dist/chunk-EY2CSXYA.mjs +822 -0
  27. package/dist/chunk-FIQ65CDR.mjs +925 -0
  28. package/dist/chunk-FOZXJFAR.mjs +186 -0
  29. package/dist/chunk-FX6URXWN.mjs +186 -0
  30. package/dist/chunk-G7SMOWOL.mjs +828 -0
  31. package/dist/chunk-GGB4G5YY.mjs +175 -0
  32. package/dist/chunk-HLRGCCIL.mjs +4839 -0
  33. package/dist/chunk-HOIUP6IF.mjs +690 -0
  34. package/dist/chunk-I3AU7GRD.mjs +120 -0
  35. package/dist/chunk-ILFGMUVD.mjs +1933 -0
  36. package/dist/chunk-IPTX5MJU.mjs +3223 -0
  37. package/dist/chunk-ITGUSH2Z.mjs +2783 -0
  38. package/dist/chunk-IXHBCAMF.mjs +3306 -0
  39. package/dist/chunk-J7TWJ3TM.mjs +2784 -0
  40. package/dist/chunk-JDPLDGVF.mjs +4810 -0
  41. package/dist/chunk-K53XP2DL.mjs +148 -0
  42. package/dist/chunk-K5HX2SVL.mjs +1902 -0
  43. package/dist/chunk-KFGYOOVS.mjs +214 -0
  44. package/dist/chunk-KFVVOS5N.mjs +925 -0
  45. package/dist/chunk-L2OZ4CDV.mjs +113 -0
  46. package/dist/chunk-MIZV3TAN.mjs +3293 -0
  47. package/dist/chunk-NKKLQE5V.mjs +148 -0
  48. package/dist/chunk-NOW23XFZ.mjs +186 -0
  49. package/dist/chunk-NRXQKQ74.mjs +148 -0
  50. package/dist/chunk-OWI6XWCD.mjs +3375 -0
  51. package/dist/chunk-PRUMNNDI.mjs +3192 -0
  52. package/dist/chunk-QTBD5B3F.mjs +148 -0
  53. package/dist/chunk-SKSDPPNT.mjs +3788 -0
  54. package/dist/chunk-SP2YUS33.mjs +186 -0
  55. package/dist/chunk-SU4E6E7B.mjs +3153 -0
  56. package/dist/chunk-SYUUKW5A.mjs +3379 -0
  57. package/dist/chunk-UL2XZEMA.mjs +3128 -0
  58. package/dist/chunk-XMWUHQVV.mjs +939 -0
  59. package/dist/chunk-XZNEDRGN.mjs +3876 -0
  60. package/dist/chunk-Y6FXYEAI.mjs +10 -0
  61. package/dist/chunk-YFS6JMYO.mjs +3342 -0
  62. package/dist/chunk-Z6AIQ4KL.mjs +113 -0
  63. package/dist/cli/index.d.mts +1 -0
  64. package/dist/cli/index.d.ts +1 -0
  65. package/dist/cli/index.js +11585 -0
  66. package/dist/cli/index.mjs +701 -0
  67. package/dist/codemod/cli.d.mts +1 -0
  68. package/dist/codemod/cli.d.ts +1 -0
  69. package/dist/codemod/cli.js +1104 -0
  70. package/dist/codemod/cli.mjs +157 -0
  71. package/dist/codemod/index.d.mts +148 -0
  72. package/dist/codemod/index.d.ts +148 -0
  73. package/dist/codemod/index.js +981 -0
  74. package/dist/codemod/index.mjs +25 -0
  75. package/dist/dev-server-Bs_sz2DG.d.mts +111 -0
  76. package/dist/dev-server-Bs_sz2DG.d.ts +111 -0
  77. package/dist/dev-server-CjoufJ-u.d.mts +109 -0
  78. package/dist/dev-server-CjoufJ-u.d.ts +109 -0
  79. package/dist/dev-server.d.mts +3 -0
  80. package/dist/dev-server.d.ts +3 -0
  81. package/dist/dev-server.js +7603 -0
  82. package/dist/dev-server.mjs +11 -0
  83. package/dist/envelope-DD7v0v6E.d.mts +265 -0
  84. package/dist/envelope-DD7v0v6E.d.ts +265 -0
  85. package/dist/envelope-vCVjrHlo.d.mts +265 -0
  86. package/dist/envelope-vCVjrHlo.d.ts +265 -0
  87. package/dist/envelope.d.mts +2 -0
  88. package/dist/envelope.d.ts +2 -0
  89. package/dist/envelope.js +5184 -0
  90. package/dist/envelope.mjs +9 -0
  91. package/dist/index-B5gSgvnd.d.mts +44 -0
  92. package/dist/index-B5gSgvnd.d.ts +44 -0
  93. package/dist/index-Bs0MnR54.d.mts +103 -0
  94. package/dist/index-Bs0MnR54.d.ts +103 -0
  95. package/dist/index-DR0nNc_f.d.mts +101 -0
  96. package/dist/index-DR0nNc_f.d.ts +101 -0
  97. package/dist/index-revho_gS.d.mts +104 -0
  98. package/dist/index-revho_gS.d.ts +104 -0
  99. package/dist/index.d.mts +1099 -0
  100. package/dist/index.d.ts +1099 -0
  101. package/dist/index.js +10162 -0
  102. package/dist/index.mjs +372 -0
  103. package/dist/init-IXEE2RCF.mjs +340 -0
  104. package/dist/project-compiler-EGJUTAJU.mjs +10 -0
  105. package/dist/project-compiler-VFR6CSDX.mjs +10 -0
  106. package/dist/project-decompiler-5GY2KSG4.mjs +7 -0
  107. package/dist/pull-A2QUHW4K.mjs +109 -0
  108. package/dist/pull-JBEQWVPE.mjs +109 -0
  109. package/dist/testing/index.d.mts +211 -0
  110. package/dist/testing/index.d.ts +211 -0
  111. package/dist/testing/index.js +5106 -0
  112. package/dist/testing/index.mjs +247 -0
  113. package/dist/vite/index.d.mts +59 -0
  114. package/dist/vite/index.d.ts +59 -0
  115. package/dist/vite/index.js +5023 -0
  116. package/dist/vite/index.mjs +8 -0
  117. package/examples/README.md +72 -0
  118. package/examples/authentication/main.workflow.tsx +139 -0
  119. package/examples/authentication/mm.config.ts +22 -0
  120. package/examples/authentication/models/auth.ts +45 -0
  121. package/examples/authentication/pages/LoginPage.tsx +79 -0
  122. package/examples/authentication/pages/SignupPage.tsx +87 -0
  123. package/examples/counter.workflow.tsx +65 -0
  124. package/examples/dashboard.workflow.tsx +419 -0
  125. package/examples/invoice-approval/actions/invoice.server.ts +72 -0
  126. package/examples/invoice-approval/main.workflow.tsx +168 -0
  127. package/examples/invoice-approval/mm.config.ts +18 -0
  128. package/examples/invoice-approval/models/invoice.ts +46 -0
  129. package/examples/invoice-approval/pages/InvoiceDetailPage.tsx +175 -0
  130. package/examples/invoice-approval/pages/InvoiceFormPage.tsx +198 -0
  131. package/examples/invoice-approval/pages/InvoiceListPage.tsx +141 -0
  132. package/examples/todo-app.workflow.tsx +131 -0
  133. package/examples/uber-app/actions/matching.server.ts +177 -0
  134. package/examples/uber-app/actions/notifications.server.ts +176 -0
  135. package/examples/uber-app/actions/payments.server.ts +184 -0
  136. package/examples/uber-app/actions/pricing.server.ts +176 -0
  137. package/examples/uber-app/app/admin/analytics.tsx +102 -0
  138. package/examples/uber-app/app/admin/fleet.tsx +102 -0
  139. package/examples/uber-app/app/admin/surge-pricing.tsx +95 -0
  140. package/examples/uber-app/app/driver/dashboard.tsx +87 -0
  141. package/examples/uber-app/app/driver/earnings.tsx +101 -0
  142. package/examples/uber-app/app/driver/navigation.tsx +94 -0
  143. package/examples/uber-app/app/driver/ride-acceptance.tsx +103 -0
  144. package/examples/uber-app/app/rider/home.tsx +109 -0
  145. package/examples/uber-app/app/rider/payment-methods.tsx +134 -0
  146. package/examples/uber-app/app/rider/ride-history.tsx +90 -0
  147. package/examples/uber-app/app/rider/ride-tracking.tsx +108 -0
  148. package/examples/uber-app/components/DriverCard.tsx +176 -0
  149. package/examples/uber-app/components/MapView.tsx +216 -0
  150. package/examples/uber-app/components/RatingStars.tsx +227 -0
  151. package/examples/uber-app/components/RideCard.tsx +167 -0
  152. package/examples/uber-app/mm.config.ts +30 -0
  153. package/examples/uber-app/models/location.model.ts +70 -0
  154. package/examples/uber-app/models/payment.model.ts +87 -0
  155. package/examples/uber-app/models/rating.model.ts +54 -0
  156. package/examples/uber-app/models/ride.model.ts +118 -0
  157. package/examples/uber-app/models/user.model.ts +66 -0
  158. package/examples/uber-app/models/vehicle.model.ts +63 -0
  159. package/examples/uber-app/tests/payment.test.tsx +129 -0
  160. package/examples/uber-app/tests/ride-flow.test.tsx +123 -0
  161. package/examples/uber-app/workflows/dispute-resolution.workflow.tsx +205 -0
  162. package/examples/uber-app/workflows/driver-onboarding.workflow.tsx +227 -0
  163. package/examples/uber-app/workflows/payment-processing.workflow.tsx +223 -0
  164. package/examples/uber-app/workflows/ride-request.workflow.tsx +194 -0
  165. package/package.json +77 -0
  166. package/package.json.backup +86 -0
  167. package/scripts/decompile.ts +226 -0
  168. package/scripts/seed-auth.ts +267 -0
  169. package/scripts/seed-uber.ts +248 -0
  170. package/scripts/validate-uber.ts +119 -0
  171. package/seed-blueprint-chat.mjs +444 -0
  172. package/seed-blueprint-glass-console.mjs +445 -0
  173. package/seed-compiled.mjs +318 -0
  174. package/src/RoundTripValidator.ts +400 -0
  175. package/src/__tests__/atom-rendering-coverage.test.ts +680 -0
  176. package/src/__tests__/auth-module-compilation.test.ts +247 -0
  177. package/src/__tests__/auth-template-compilation.test.ts +589 -0
  178. package/src/__tests__/change-extractor.test.ts +142 -0
  179. package/src/__tests__/cli-pull.test.ts +73 -0
  180. package/src/__tests__/cli-test.test.ts +72 -0
  181. package/src/__tests__/component-extractor.test.ts +331 -0
  182. package/src/__tests__/context-extractor.test.ts +145 -0
  183. package/src/__tests__/decompiler.test.ts +718 -0
  184. package/src/__tests__/define-blueprint.test.ts +133 -0
  185. package/src/__tests__/definition-validator.test.ts +519 -0
  186. package/src/__tests__/during-extractor.test.ts +152 -0
  187. package/src/__tests__/effect-extractor.test.ts +107 -0
  188. package/src/__tests__/event-emission.test.ts +127 -0
  189. package/src/__tests__/examples.test.ts +236 -0
  190. package/src/__tests__/full-blueprint-coverage.test.ts +1221 -0
  191. package/src/__tests__/golden-suite.test.ts +403 -0
  192. package/src/__tests__/grammar-island-extractor.test.ts +289 -0
  193. package/src/__tests__/instance-key.test.ts +82 -0
  194. package/src/__tests__/ir-migration.test.ts +255 -0
  195. package/src/__tests__/lock-file.test.ts +117 -0
  196. package/src/__tests__/model-extractor.test.ts +195 -0
  197. package/src/__tests__/model-field-acl.test.ts +237 -0
  198. package/src/__tests__/model-hooks.test.ts +130 -0
  199. package/src/__tests__/model-ref-resolution.test.ts +268 -0
  200. package/src/__tests__/model-roundtrip.test.ts +502 -0
  201. package/src/__tests__/model-runtime.test.ts +112 -0
  202. package/src/__tests__/model-transitions.test.ts +183 -0
  203. package/src/__tests__/nrt-action-trace.test.ts +391 -0
  204. package/src/__tests__/pipeline-hardening.test.ts +413 -0
  205. package/src/__tests__/project-compiler.test.ts +546 -0
  206. package/src/__tests__/project-decompiler.test.ts +343 -0
  207. package/src/__tests__/query-compilation.test.ts +145 -0
  208. package/src/__tests__/round-trip/PLAN.md +158 -0
  209. package/src/__tests__/round-trip/README.md +52 -0
  210. package/src/__tests__/round-trip/RESULTS.md +86 -0
  211. package/src/__tests__/round-trip/fixtures/data-heavy/main.workflow.tsx +55 -0
  212. package/src/__tests__/round-trip/fixtures/data-heavy/mm.config.ts +11 -0
  213. package/src/__tests__/round-trip/fixtures/data-heavy/models/contact.ts +54 -0
  214. package/src/__tests__/round-trip/fixtures/full-workflow/main.workflow.tsx +79 -0
  215. package/src/__tests__/round-trip/fixtures/full-workflow/mm.config.ts +12 -0
  216. package/src/__tests__/round-trip/fixtures/full-workflow/models/order.ts +50 -0
  217. package/src/__tests__/round-trip/fixtures/simple-crud/main.workflow.tsx +25 -0
  218. package/src/__tests__/round-trip/fixtures/simple-crud/mm.config.ts +11 -0
  219. package/src/__tests__/round-trip/fixtures/simple-crud/models/task.ts +32 -0
  220. package/src/__tests__/round-trip/fixtures/view-heavy/main.workflow.tsx +79 -0
  221. package/src/__tests__/round-trip/fixtures/view-heavy/mm.config.ts +10 -0
  222. package/src/__tests__/round-trip/round-trip.test.ts +2598 -0
  223. package/src/__tests__/round-trip-ir.test.ts +300 -0
  224. package/src/__tests__/round-trip.test.ts +1212 -0
  225. package/src/__tests__/route-merging.test.ts +372 -0
  226. package/src/__tests__/router-composition.test.ts +489 -0
  227. package/src/__tests__/router-extractor.test.ts +176 -0
  228. package/src/__tests__/server-action-extractor.test.ts +128 -0
  229. package/src/__tests__/smart-type-inference.test.ts +365 -0
  230. package/src/__tests__/source-envelope.test.ts +284 -0
  231. package/src/__tests__/source-fidelity.test.ts +516 -0
  232. package/src/__tests__/state-extractor.test.ts +115 -0
  233. package/src/__tests__/strict-mode.test.ts +227 -0
  234. package/src/__tests__/transition-effect-extractor.test.ts +119 -0
  235. package/src/__tests__/transition-extractor.test.ts +68 -0
  236. package/src/__tests__/ts-to-expression.test.ts +462 -0
  237. package/src/__tests__/type-generator.test.ts +201 -0
  238. package/src/__tests__/uber-validation.test.ts +502 -0
  239. package/src/action-compiler.ts +361 -0
  240. package/src/babel/emitters/experience-transform.ts +199 -0
  241. package/src/babel/emitters/ir-to-tsx-emitter.ts +110 -0
  242. package/src/babel/emitters/pure-form-emitter.ts +1023 -0
  243. package/src/babel/emitters/runtime-glue-emitter.ts +39 -0
  244. package/src/babel/extractors/change-extractor.ts +199 -0
  245. package/src/babel/extractors/component-extractor.ts +907 -0
  246. package/src/babel/extractors/computed-extractor.ts +262 -0
  247. package/src/babel/extractors/context-extractor.ts +277 -0
  248. package/src/babel/extractors/during-extractor.ts +295 -0
  249. package/src/babel/extractors/effect-extractor.ts +340 -0
  250. package/src/babel/extractors/event-extractor.ts +235 -0
  251. package/src/babel/extractors/grammar-island-extractor.ts +302 -0
  252. package/src/babel/extractors/model-extractor.ts +1018 -0
  253. package/src/babel/extractors/router-extractor.ts +303 -0
  254. package/src/babel/extractors/server-action-extractor.ts +173 -0
  255. package/src/babel/extractors/server-action-hook-extractor.ts +72 -0
  256. package/src/babel/extractors/server-state-extractor.ts +88 -0
  257. package/src/babel/extractors/state-extractor.ts +214 -0
  258. package/src/babel/extractors/transition-effect-extractor.ts +176 -0
  259. package/src/babel/extractors/transition-extractor.ts +143 -0
  260. package/src/babel/index.ts +24 -0
  261. package/src/babel/transpilers/ts-to-expression.ts +674 -0
  262. package/src/babel/visitor.ts +807 -0
  263. package/src/cli/auth.ts +255 -0
  264. package/src/cli/build.ts +288 -0
  265. package/src/cli/deploy.ts +206 -0
  266. package/src/cli/index.ts +328 -0
  267. package/src/cli/init.ts +388 -0
  268. package/src/cli/installer.ts +261 -0
  269. package/src/cli/lock-file.ts +94 -0
  270. package/src/cli/mmrc.ts +22 -0
  271. package/src/cli/pull.ts +172 -0
  272. package/src/cli/registry-client.ts +175 -0
  273. package/src/cli/test.ts +397 -0
  274. package/src/cli/type-generator.ts +243 -0
  275. package/src/codemod/__tests__/forward.test.ts +239 -0
  276. package/src/codemod/__tests__/reverse.test.ts +145 -0
  277. package/src/codemod/__tests__/round-trip.test.ts +137 -0
  278. package/src/codemod/annotation.ts +97 -0
  279. package/src/codemod/classify.ts +197 -0
  280. package/src/codemod/cli.ts +207 -0
  281. package/src/codemod/control-flow.ts +409 -0
  282. package/src/codemod/forward.ts +244 -0
  283. package/src/codemod/import-manager.ts +171 -0
  284. package/src/codemod/index.ts +120 -0
  285. package/src/codemod/reverse.ts +197 -0
  286. package/src/codemod/rules.ts +174 -0
  287. package/src/codemod/state-transform.ts +126 -0
  288. package/src/decompiler/ast-builder.ts +538 -0
  289. package/src/decompiler/config-generator.ts +151 -0
  290. package/src/decompiler/index.ts +315 -0
  291. package/src/decompiler/project-decompiler.ts +1776 -0
  292. package/src/decompiler/project.ts +862 -0
  293. package/src/decompiler/split-strategy.ts +140 -0
  294. package/src/decompiler/state-emitter.ts +1053 -0
  295. package/src/decompiler/sx-emitter.ts +318 -0
  296. package/src/decompiler/workspace-hydrator.ts +189 -0
  297. package/src/dev-server.ts +238 -0
  298. package/src/envelope/fs-tree.ts +217 -0
  299. package/src/envelope/source-envelope.ts +264 -0
  300. package/src/envelope.ts +315 -0
  301. package/src/incremental-compiler.ts +401 -0
  302. package/src/index.ts +99 -0
  303. package/src/model-compiler.ts +277 -0
  304. package/src/project-compiler.ts +1629 -0
  305. package/src/route-extractor.ts +333 -0
  306. package/src/testing/index.ts +32 -0
  307. package/src/testing/snapshot.ts +252 -0
  308. package/src/testing/test-utils.ts +226 -0
  309. package/src/types.ts +68 -0
  310. package/src/vite/index.ts +288 -0
  311. package/test-compile.mjs +142 -0
  312. package/tsconfig.json +25 -0
  313. package/tsup.config.ts +23 -0
  314. package/vitest.config.ts +9 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,372 @@
1
+ import {
2
+ IncrementalCache,
3
+ IncrementalProjectCompiler,
4
+ buildDependencyGraph,
5
+ compileActions,
6
+ compileModel,
7
+ compileModels,
8
+ compileProject,
9
+ computeTransitiveDirtySet,
10
+ extractImports,
11
+ extractRoutes,
12
+ hashContent,
13
+ resolveActionReferences,
14
+ resolveImport,
15
+ topologicalSort
16
+ } from "./chunk-ILFGMUVD.mjs";
17
+ import {
18
+ decompile,
19
+ decompileProject,
20
+ shouldDecompileAsProject
21
+ } from "./chunk-SU4E6E7B.mjs";
22
+ import {
23
+ createDevServer
24
+ } from "./chunk-NRXQKQ74.mjs";
25
+ import "./chunk-46YKSHQR.mjs";
26
+ import {
27
+ buildEnvelope
28
+ } from "./chunk-FX6URXWN.mjs";
29
+ import {
30
+ deploy
31
+ } from "./chunk-EQGA6A6D.mjs";
32
+ import {
33
+ build
34
+ } from "./chunk-KFGYOOVS.mjs";
35
+ import {
36
+ computeEnvelopeId,
37
+ createSourceEnvelope,
38
+ detectFileRole,
39
+ diffEnvelopes,
40
+ diffFsTrees,
41
+ envelopesEqual,
42
+ filterByRole,
43
+ generateFsTree
44
+ } from "./chunk-5M7DKKBC.mjs";
45
+ import {
46
+ babelPlugin,
47
+ compilerStateToWorkflow,
48
+ createVisitor,
49
+ emitCanonical,
50
+ emitCompiledOutput,
51
+ emitIR,
52
+ emitPureForm,
53
+ extractComponents,
54
+ extractComputed,
55
+ extractEffects,
56
+ extractEvents,
57
+ extractStates,
58
+ extractTransitions,
59
+ transformToFrontend
60
+ } from "./chunk-HLRGCCIL.mjs";
61
+ import "./chunk-Y6FXYEAI.mjs";
62
+
63
+ // src/babel/emitters/ir-to-tsx-emitter.ts
64
+ function decompileToTSX(definition, options) {
65
+ return decompile(definition, options);
66
+ }
67
+ function normalizeDecompilerInput(definition) {
68
+ const input = { ...definition };
69
+ if (!input.experience) {
70
+ const views = definition.views;
71
+ if (views?.default) {
72
+ input.experience = views.default;
73
+ }
74
+ }
75
+ if (!input.experience && definition.metadata?.experience) {
76
+ input.experience = definition.metadata.experience;
77
+ }
78
+ return input;
79
+ }
80
+
81
+ // src/RoundTripValidator.ts
82
+ import { transformSync } from "@babel/core";
83
+ function validateRoundTrip(definition) {
84
+ const { code: generatedSource } = decompile(definition, {
85
+ includeAnnotation: true
86
+ });
87
+ let roundTrippedIR = null;
88
+ try {
89
+ const result = transformSync(generatedSource, {
90
+ filename: `${definition.slug}.workflow.tsx`,
91
+ plugins: [[babelPlugin, { mode: "infer" }]],
92
+ parserOpts: { plugins: ["typescript", "jsx"], attachComment: true }
93
+ });
94
+ roundTrippedIR = result?.metadata?.mindmatrixIR ?? null;
95
+ } catch (err) {
96
+ return {
97
+ success: false,
98
+ generatedSource,
99
+ originalIR: definition,
100
+ roundTrippedIR: null,
101
+ diffs: [{
102
+ path: "<compile>",
103
+ expected: "valid compilation",
104
+ actual: `compilation failed: ${err.message}`,
105
+ severity: "error"
106
+ }]
107
+ };
108
+ }
109
+ if (!roundTrippedIR) {
110
+ return {
111
+ success: false,
112
+ generatedSource,
113
+ originalIR: definition,
114
+ roundTrippedIR: null,
115
+ diffs: [{
116
+ path: "<compile>",
117
+ expected: "IR output",
118
+ actual: "no IR produced",
119
+ severity: "error"
120
+ }]
121
+ };
122
+ }
123
+ const diffs = compareIR(definition, roundTrippedIR);
124
+ return {
125
+ success: diffs.filter((d) => d.severity === "error").length === 0,
126
+ generatedSource,
127
+ originalIR: definition,
128
+ roundTrippedIR,
129
+ diffs
130
+ };
131
+ }
132
+ function compareIR(original, roundTripped) {
133
+ const diffs = [];
134
+ comparePrimitive(diffs, "slug", original.slug, roundTripped.slug);
135
+ comparePrimitive(diffs, "version", original.version, roundTripped.version);
136
+ comparePrimitive(diffs, "category", original.category, roundTripped.category);
137
+ compareFields(diffs, original.fields, roundTripped.fields);
138
+ compareStates(diffs, original.states, roundTripped.states);
139
+ compareTransitions(diffs, original.transitions, roundTripped.transitions);
140
+ const origEvents = original.on_event ?? [];
141
+ const rtEvents = roundTripped.on_event ?? [];
142
+ if (origEvents.length !== rtEvents.length) {
143
+ diffs.push({
144
+ path: "on_event.length",
145
+ expected: origEvents.length,
146
+ actual: rtEvents.length,
147
+ severity: origEvents.length > 0 ? "error" : "warning"
148
+ });
149
+ }
150
+ return diffs;
151
+ }
152
+ function comparePrimitive(diffs, path, expected, actual) {
153
+ if (expected !== actual) {
154
+ diffs.push({ path, expected, actual, severity: "error" });
155
+ }
156
+ }
157
+ function compareFields(diffs, original, roundTripped) {
158
+ const origFields = original.filter((f) => !f.computed);
159
+ if (origFields.length !== roundTripped.length) {
160
+ diffs.push({
161
+ path: "fields.length",
162
+ expected: origFields.length,
163
+ actual: roundTripped.length,
164
+ severity: "error"
165
+ });
166
+ }
167
+ const rtMap = new Map(roundTripped.map((f) => [f.name, f]));
168
+ for (const field of origFields) {
169
+ const rt = rtMap.get(field.name);
170
+ if (!rt) {
171
+ diffs.push({
172
+ path: `fields[${field.name}]`,
173
+ expected: field.name,
174
+ actual: void 0,
175
+ severity: "error"
176
+ });
177
+ continue;
178
+ }
179
+ if (field.type !== rt.type && !isCompatibleType(field.type, rt.type)) {
180
+ diffs.push({
181
+ path: `fields[${field.name}].type`,
182
+ expected: field.type,
183
+ actual: rt.type,
184
+ severity: "warning"
185
+ });
186
+ }
187
+ }
188
+ }
189
+ function isCompatibleType(original, roundTripped) {
190
+ const stringTypes = ["text", "rich_text", "email", "url", "phone", "color", "select"];
191
+ const numberTypes = ["number", "currency", "percentage", "rating", "duration", "auto_number"];
192
+ if (stringTypes.includes(original) && stringTypes.includes(roundTripped)) return true;
193
+ if (numberTypes.includes(original) && numberTypes.includes(roundTripped)) return true;
194
+ return false;
195
+ }
196
+ function compareStates(diffs, original, roundTripped) {
197
+ const rtMap = new Map(roundTripped.map((s) => [s.name, s]));
198
+ for (const state of original) {
199
+ const hasActions = state.on_enter.length > 0 || state.on_exit.length > 0 || state.during.length > 0;
200
+ const rt = rtMap.get(state.name);
201
+ if (!rt && hasActions) {
202
+ diffs.push({
203
+ path: `states[${state.name}]`,
204
+ expected: state.name,
205
+ actual: void 0,
206
+ severity: "error"
207
+ });
208
+ continue;
209
+ }
210
+ if (!rt) continue;
211
+ if (state.on_enter.length !== rt.on_enter.length) {
212
+ diffs.push({
213
+ path: `states[${state.name}].on_enter.length`,
214
+ expected: state.on_enter.length,
215
+ actual: rt.on_enter.length,
216
+ severity: state.on_enter.length > 0 ? "error" : "warning"
217
+ });
218
+ }
219
+ if (state.on_exit.length !== rt.on_exit.length) {
220
+ diffs.push({
221
+ path: `states[${state.name}].on_exit.length`,
222
+ expected: state.on_exit.length,
223
+ actual: rt.on_exit.length,
224
+ severity: state.on_exit.length > 0 ? "error" : "warning"
225
+ });
226
+ }
227
+ if (state.during.length !== rt.during.length) {
228
+ diffs.push({
229
+ path: `states[${state.name}].during.length`,
230
+ expected: state.during.length,
231
+ actual: rt.during.length,
232
+ severity: state.during.length > 0 ? "error" : "warning"
233
+ });
234
+ }
235
+ }
236
+ }
237
+ function compareTransitions(diffs, original, roundTripped) {
238
+ if (original.length !== roundTripped.length) {
239
+ diffs.push({
240
+ path: "transitions.length",
241
+ expected: original.length,
242
+ actual: roundTripped.length,
243
+ severity: "error"
244
+ });
245
+ }
246
+ const rtMap = new Map(roundTripped.map((t) => [t.name, t]));
247
+ for (const transition of original) {
248
+ const rt = rtMap.get(transition.name);
249
+ if (!rt) {
250
+ diffs.push({
251
+ path: `transitions[${transition.name}]`,
252
+ expected: transition.name,
253
+ actual: void 0,
254
+ severity: "error"
255
+ });
256
+ continue;
257
+ }
258
+ if (transition.to !== rt.to) {
259
+ diffs.push({
260
+ path: `transitions[${transition.name}].to`,
261
+ expected: transition.to,
262
+ actual: rt.to,
263
+ severity: "error"
264
+ });
265
+ }
266
+ const origFrom = [...transition.from].sort();
267
+ const rtFrom = [...rt.from].sort();
268
+ if (JSON.stringify(origFrom) !== JSON.stringify(rtFrom)) {
269
+ diffs.push({
270
+ path: `transitions[${transition.name}].from`,
271
+ expected: origFrom,
272
+ actual: rtFrom,
273
+ severity: "error"
274
+ });
275
+ }
276
+ const origRoles = [...transition.roles ?? []].sort();
277
+ const rtRoles = [...rt.roles ?? []].sort();
278
+ if (JSON.stringify(origRoles) !== JSON.stringify(rtRoles)) {
279
+ diffs.push({
280
+ path: `transitions[${transition.name}].roles`,
281
+ expected: origRoles,
282
+ actual: rtRoles,
283
+ severity: "error"
284
+ });
285
+ }
286
+ const origReq = [...transition.required_fields ?? []].sort();
287
+ const rtReq = [...rt.required_fields ?? []].sort();
288
+ if (JSON.stringify(origReq) !== JSON.stringify(rtReq)) {
289
+ diffs.push({
290
+ path: `transitions[${transition.name}].required_fields`,
291
+ expected: origReq,
292
+ actual: rtReq,
293
+ severity: "error"
294
+ });
295
+ }
296
+ if (!!transition.auto !== !!rt.auto) {
297
+ diffs.push({
298
+ path: `transitions[${transition.name}].auto`,
299
+ expected: transition.auto,
300
+ actual: rt.auto,
301
+ severity: "error"
302
+ });
303
+ }
304
+ }
305
+ }
306
+ function compileSource(source, filename = "test.workflow.tsx") {
307
+ try {
308
+ const result = transformSync(source, {
309
+ filename,
310
+ plugins: [[babelPlugin, { mode: "infer" }]],
311
+ parserOpts: { plugins: ["typescript", "jsx"], attachComment: true }
312
+ });
313
+ return result?.metadata?.mindmatrixIR ?? null;
314
+ } catch {
315
+ return null;
316
+ }
317
+ }
318
+ function validateSourceRoundTrip(source, filename = "test.workflow.tsx") {
319
+ const ir = compileSource(source, filename);
320
+ if (!ir) return null;
321
+ return validateRoundTrip(ir);
322
+ }
323
+ export {
324
+ IncrementalCache,
325
+ IncrementalProjectCompiler,
326
+ babelPlugin,
327
+ build,
328
+ buildDependencyGraph,
329
+ buildEnvelope,
330
+ compileActions,
331
+ compileModel,
332
+ compileModels,
333
+ compileProject,
334
+ compileSource,
335
+ compilerStateToWorkflow,
336
+ computeEnvelopeId,
337
+ computeTransitiveDirtySet,
338
+ createDevServer,
339
+ createSourceEnvelope,
340
+ createVisitor,
341
+ decompile,
342
+ decompileProject,
343
+ decompileToTSX,
344
+ deploy,
345
+ detectFileRole,
346
+ diffEnvelopes,
347
+ diffFsTrees,
348
+ emitCanonical,
349
+ emitCompiledOutput,
350
+ emitIR,
351
+ emitPureForm,
352
+ envelopesEqual,
353
+ extractComponents,
354
+ extractComputed,
355
+ extractEffects,
356
+ extractEvents,
357
+ extractImports,
358
+ extractRoutes,
359
+ extractStates,
360
+ extractTransitions,
361
+ filterByRole,
362
+ generateFsTree,
363
+ hashContent,
364
+ normalizeDecompilerInput,
365
+ resolveActionReferences,
366
+ resolveImport,
367
+ shouldDecompileAsProject,
368
+ topologicalSort,
369
+ transformToFrontend,
370
+ validateRoundTrip,
371
+ validateSourceRoundTrip
372
+ };
@@ -0,0 +1,340 @@
1
+ import "./chunk-Y6FXYEAI.mjs";
2
+
3
+ // src/cli/init.ts
4
+ import { mkdirSync, writeFileSync, existsSync } from "fs";
5
+ import { join } from "path";
6
+ function toTitleCase(slug) {
7
+ return slug.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
8
+ }
9
+ function toPascalCase(slug) {
10
+ return slug.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
11
+ }
12
+ function generatePackageJson(name) {
13
+ return JSON.stringify(
14
+ {
15
+ name: `@mindmatrix/blueprint-${name}`,
16
+ version: "0.1.0",
17
+ private: true,
18
+ type: "module",
19
+ scripts: {
20
+ build: "mmrc build --src . --out dist",
21
+ dev: "mmrc dev --src . --port 5199",
22
+ deploy: "mmrc deploy --build --src ."
23
+ },
24
+ dependencies: {
25
+ "@mindmatrix/react": "workspace:*"
26
+ }
27
+ },
28
+ null,
29
+ 2
30
+ );
31
+ }
32
+ function generateMmConfig(name, opts) {
33
+ const title = toTitleCase(name);
34
+ const desc = opts.description ?? `${title} blueprint.`;
35
+ const icon = opts.icon ?? "box";
36
+ const author = opts.author ?? "MindMatrix";
37
+ return `import { defineBlueprint } from '@mindmatrix/react';
38
+
39
+ export default defineBlueprint({
40
+ slug: '${name}',
41
+ name: '${title}',
42
+ version: '1.0.0',
43
+ description: '${desc}',
44
+ author: '${author}',
45
+ icon: '${icon}',
46
+ mode: 'infer',
47
+ defaultRuntime: 'collaborative',
48
+
49
+ models: [
50
+ 'models/item',
51
+ ],
52
+
53
+ routes: [
54
+ { path: '/', view: 'app/page', label: 'Home' },
55
+ ],
56
+
57
+ dependencies: [],
58
+ });
59
+ `;
60
+ }
61
+ function generateModel(name) {
62
+ const modelSlug = `${name}-item`;
63
+ const pascal = toPascalCase(name);
64
+ return `/**
65
+ * ${pascal} Item \u2014 data model with lifecycle states.
66
+ *
67
+ * States: draft \u2192 active \u2192 archived
68
+ */
69
+
70
+ import { defineModel } from '@mindmatrix/react';
71
+
72
+ export interface ${pascal}ItemFields {
73
+ title: string;
74
+ description: string;
75
+ priority: 'low' | 'medium' | 'high';
76
+ createdAt: number;
77
+ }
78
+
79
+ export default defineModel({
80
+ slug: '${modelSlug}',
81
+ version: '1.0.0',
82
+ category: ['model', '${name}'],
83
+
84
+ fields: {
85
+ title: { type: 'string', required: true },
86
+ description: { type: 'string', default: '' },
87
+ priority: { type: 'string', default: 'medium', enum: ['low', 'medium', 'high'] },
88
+ createdAt: { type: 'number', default: 0 },
89
+ },
90
+
91
+ states: {
92
+ draft: {
93
+ type: 'initial',
94
+ onEnter: [
95
+ { id: 'set-created', type: 'set_field', mode: 'auto', config: { field: 'createdAt', expression: 'NOW()' } },
96
+ ],
97
+ },
98
+ active: {
99
+ onEnter: [
100
+ { id: 'log-activated', type: 'log_event', mode: 'auto', config: { event: '${modelSlug}.activated' } },
101
+ ],
102
+ },
103
+ archived: {
104
+ type: 'end',
105
+ },
106
+ },
107
+
108
+ transitions: {
109
+ activate: {
110
+ from: 'draft',
111
+ to: 'active',
112
+ description: 'Publish this item',
113
+ },
114
+ archive: {
115
+ from: 'active',
116
+ to: 'archived',
117
+ description: 'Archive this item',
118
+ },
119
+ },
120
+ });
121
+ `;
122
+ }
123
+ function generateLayout(name) {
124
+ const title = toTitleCase(name);
125
+ return `/**
126
+ * @workflow slug="${name}-layout" version="1.0.0" category="view"
127
+ *
128
+ * Root layout with sidebar navigation.
129
+ */
130
+
131
+ import {
132
+ Row,
133
+ Stack,
134
+ Slot,
135
+ Text,
136
+ Icon,
137
+ Button,
138
+ Divider,
139
+ } from '@mindmatrix/react/atoms';
140
+ import { useRouter } from '@mindmatrix/react';
141
+
142
+ export default function Layout({ children }: { children: React.ReactNode }) {
143
+ const router = useRouter();
144
+
145
+ return (
146
+ <Row gap={0} height="100vh" overflow="hidden">
147
+ {/* Sidebar */}
148
+ <Stack
149
+ width={240}
150
+ borderRight="1px solid token:border"
151
+ height="100vh"
152
+ background="token:surface"
153
+ >
154
+ <Row padding={12} gap={8} align="center" borderBottom="1px solid token:border">
155
+ <Icon name="box" size={20} color="token:primary" />
156
+ <Text variant="label" size="sm" value="${title}" />
157
+ </Row>
158
+
159
+ <Stack padding={8} gap={4}>
160
+ <Button variant="ghost" onPress={() => router.push('/')}>
161
+ <Row gap={8} align="center">
162
+ <Icon name="home" size={16} />
163
+ <Text size="sm" value="Home" />
164
+ </Row>
165
+ </Button>
166
+ <Button variant="ghost" onPress={() => router.push('/settings')}>
167
+ <Row gap={8} align="center">
168
+ <Icon name="settings" size={16} />
169
+ <Text size="sm" value="Settings" />
170
+ </Row>
171
+ </Button>
172
+ </Stack>
173
+
174
+ <Divider />
175
+ <Stack flex={1} />
176
+ <Row padding={12}>
177
+ <Text variant="muted" size="xs" value="v1.0.0" />
178
+ </Row>
179
+ </Stack>
180
+
181
+ {/* Main content */}
182
+ <Stack flex={1} overflow="auto">
183
+ {children}
184
+ </Stack>
185
+ </Row>
186
+ );
187
+ }
188
+ `;
189
+ }
190
+ function generatePage(name) {
191
+ const title = toTitleCase(name);
192
+ const pascal = toPascalCase(name);
193
+ return `/**
194
+ * @workflow slug="${name}-home" version="1.0.0" category="page"
195
+ *
196
+ * Index page \u2014 lists items with create and search.
197
+ */
198
+
199
+ import itemModel from '../models/item';
200
+ import {
201
+ useQuery, useMutation, useRouter, useState,
202
+ Stack, Row, Text, Button, Icon, Card, Show, Each, TextInput, Badge,
203
+ } from '@mindmatrix/react';
204
+
205
+ const PRIORITY_COLORS: Record<string, string> = {
206
+ high: 'token:error',
207
+ medium: 'token:warning',
208
+ low: 'token:success',
209
+ };
210
+
211
+ export default function ${pascal}Home() {
212
+ const { data: items, loading } = useQuery(itemModel);
213
+ const mutation = useMutation(itemModel);
214
+ const router = useRouter();
215
+ const [search, setSearch] = useState('');
216
+
217
+ const activeItems = items.filter(i => i.state !== 'archived');
218
+ const filtered = activeItems.filter(i =>
219
+ i.fields.title.toLowerCase().includes(search.toLowerCase())
220
+ );
221
+
222
+ const handleCreate = async () => {
223
+ await mutation.create({ title: 'New Item', priority: 'medium' });
224
+ };
225
+
226
+ return (
227
+ <Stack gap={24} padding={24}>
228
+ {/* Header */}
229
+ <Row justify="space-between" align="center">
230
+ <Stack gap={4}>
231
+ <Text variant="h3" weight="bold" value="${title}" />
232
+ <Text variant="muted" size="sm" value={\`\${activeItems.length} items\`} />
233
+ </Stack>
234
+ <Button variant="primary" onPress={handleCreate}>
235
+ <Row gap={6} align="center">
236
+ <Icon name="plus" size={16} />
237
+ <Text value="Add Item" />
238
+ </Row>
239
+ </Button>
240
+ </Row>
241
+
242
+ {/* Search */}
243
+ <TextInput
244
+ value={search}
245
+ onChange={setSearch}
246
+ placeholder="Search items..."
247
+ />
248
+
249
+ {/* Loading */}
250
+ <Show when={loading}>
251
+ <Card padding={32}>
252
+ <Stack align="center">
253
+ <Text variant="muted" value="Loading..." />
254
+ </Stack>
255
+ </Card>
256
+ </Show>
257
+
258
+ {/* Empty state */}
259
+ <Show when={!loading && filtered.length === 0}>
260
+ <Card padding={32}>
261
+ <Stack align="center" gap={12}>
262
+ <Icon name="inbox" size={40} color="token:muted" />
263
+ <Text variant="muted" value="No items yet" />
264
+ <Button variant="outline" onPress={handleCreate}>
265
+ <Text value="Create your first item" />
266
+ </Button>
267
+ </Stack>
268
+ </Card>
269
+ </Show>
270
+
271
+ {/* Item list */}
272
+ <Show when={!loading && filtered.length > 0}>
273
+ <Stack gap={4}>
274
+ <Each items={filtered} keyField="id">
275
+ {(item) => (
276
+ <Card padding={12}>
277
+ <Row align="center" gap={12}>
278
+ <Stack flex={1} gap={2}>
279
+ <Text weight="medium" value={item.fields.title} />
280
+ <Show when={!!item.fields.description}>
281
+ <Text size="sm" variant="muted" value={item.fields.description} />
282
+ </Show>
283
+ </Stack>
284
+ <Badge value={item.fields.priority} />
285
+ <Badge value={item.state} variant={item.state === 'active' ? 'success' : 'default'} />
286
+ </Row>
287
+ </Card>
288
+ )}
289
+ </Each>
290
+ </Stack>
291
+ </Show>
292
+ </Stack>
293
+ );
294
+ }
295
+ `;
296
+ }
297
+ async function init(options) {
298
+ const { name } = options;
299
+ if (!/^[a-z][a-z0-9-]*$/.test(name)) {
300
+ console.error(`[mmrc] Error: Blueprint name must be lowercase alphanumeric with hyphens (got "${name}")`);
301
+ process.exit(1);
302
+ }
303
+ const cwd = process.cwd();
304
+ const packagesDir = existsSync(join(cwd, "packages")) ? join(cwd, "packages") : cwd;
305
+ const blueprintDir = join(packagesDir, `blueprint-${name}`);
306
+ if (existsSync(blueprintDir)) {
307
+ console.error(`[mmrc] Error: Directory already exists: ${blueprintDir}`);
308
+ process.exit(1);
309
+ }
310
+ console.log(`[mmrc] Creating blueprint: ${name}
311
+ `);
312
+ mkdirSync(join(blueprintDir, "models"), { recursive: true });
313
+ mkdirSync(join(blueprintDir, "app"), { recursive: true });
314
+ const files = [
315
+ ["package.json", generatePackageJson(name)],
316
+ ["mm.config.ts", generateMmConfig(name, options)],
317
+ ["models/item.ts", generateModel(name)],
318
+ ["app/layout.tsx", generateLayout(name)],
319
+ ["app/page.tsx", generatePage(name)]
320
+ ];
321
+ for (const [relPath, content] of files) {
322
+ const fullPath = join(blueprintDir, relPath);
323
+ writeFileSync(fullPath, content, "utf-8");
324
+ console.log(` + ${relPath}`);
325
+ }
326
+ const title = toTitleCase(name);
327
+ console.log(`
328
+ [mmrc] Blueprint "${title}" created at:
329
+ ${blueprintDir}
330
+
331
+ Next steps:
332
+ 1. cd ${blueprintDir.startsWith(cwd) ? blueprintDir.slice(cwd.length + 1) : blueprintDir}
333
+ 2. mmrc dev # Start dev server
334
+ 3. mmrc build # Compile to IR
335
+ 4. mmrc deploy --build # Build + deploy to backend
336
+ `);
337
+ }
338
+ export {
339
+ init
340
+ };