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

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 (265) hide show
  1. package/ATOM-PIPELINE.md +144 -0
  2. package/README.md +88 -40
  3. package/dist/babel/index.js +2814 -277
  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-52XHYD2V.mjs +214 -0
  11. package/dist/chunk-5GUFFFGL.mjs +148 -0
  12. package/dist/chunk-5RKTOVR5.mjs +244 -0
  13. package/dist/chunk-5YDMOO4X.mjs +214 -0
  14. package/dist/chunk-64ZWEMLJ.mjs +148 -0
  15. package/dist/chunk-6XP4KSWQ.mjs +2190 -0
  16. package/dist/chunk-72QWL54I.mjs +175 -0
  17. package/dist/chunk-7B4TRI7C.mjs +4835 -0
  18. package/dist/chunk-7ZKGHTNB.mjs +4952 -0
  19. package/dist/chunk-CIESM3BP.mjs +33 -0
  20. package/dist/chunk-DE3ZGQAC.mjs +148 -0
  21. package/dist/chunk-DMCY3BBG.mjs +1933 -0
  22. package/dist/chunk-DPIK3PJS.mjs +244 -0
  23. package/dist/chunk-E5IVH4RE.mjs +186 -0
  24. package/dist/chunk-E6FZNUR5.mjs +4953 -0
  25. package/dist/chunk-EJRBDQDP.mjs +2607 -0
  26. package/dist/chunk-ELO4TXJL.mjs +186 -0
  27. package/dist/chunk-EO6SYNCG.mjs +175 -0
  28. package/dist/chunk-FKRO52XH.mjs +3446 -0
  29. package/dist/chunk-FL4YAKU6.mjs +4941 -0
  30. package/dist/chunk-FYT47UBU.mjs +5076 -0
  31. package/dist/chunk-GCLGPOJZ.mjs +148 -0
  32. package/dist/chunk-GXB4JOP7.mjs +5072 -0
  33. package/dist/chunk-HFXOUMTD.mjs +175 -0
  34. package/dist/chunk-HWIZ47US.mjs +214 -0
  35. package/dist/chunk-IB7MNPQL.mjs +4953 -0
  36. package/dist/chunk-ICSIHQCG.mjs +148 -0
  37. package/dist/chunk-J7JUAHS4.mjs +186 -0
  38. package/dist/chunk-JLA5VNQ3.mjs +186 -0
  39. package/dist/chunk-JQLWFCTM.mjs +214 -0
  40. package/dist/chunk-KFJJCQAL.mjs +148 -0
  41. package/dist/chunk-KJUIIEQE.mjs +186 -0
  42. package/dist/chunk-KNWTHRVQ.mjs +175 -0
  43. package/dist/chunk-KSG4XSZF.mjs +175 -0
  44. package/dist/chunk-LF5N6DOU.mjs +175 -0
  45. package/dist/chunk-LJQCM2IM.mjs +214 -0
  46. package/dist/chunk-NTB7OEX2.mjs +2918 -0
  47. package/dist/chunk-NW6555WJ.mjs +186 -0
  48. package/dist/chunk-OMZE6VLQ.mjs +214 -0
  49. package/dist/chunk-OPJKP747.mjs +7506 -0
  50. package/dist/chunk-P4BR7WVO.mjs +2190 -0
  51. package/dist/chunk-QQHVYH2X.mjs +244 -0
  52. package/dist/chunk-S5QLWLLT.mjs +186 -0
  53. package/dist/chunk-SCWGT2FY.mjs +2190 -0
  54. package/dist/chunk-SMKJUSB3.mjs +2190 -0
  55. package/dist/chunk-THFYE5ZX.mjs +244 -0
  56. package/dist/chunk-VCAY2KGM.mjs +175 -0
  57. package/dist/chunk-WBYMW4NQ.mjs +3450 -0
  58. package/dist/chunk-WECAV6QB.mjs +148 -0
  59. package/dist/chunk-WMKBXUCE.mjs +3228 -0
  60. package/dist/chunk-XAJ5BKKL.mjs +4947 -0
  61. package/dist/chunk-XG2X7AEA.mjs +175 -0
  62. package/dist/chunk-XG7Z23NQ.mjs +148 -0
  63. package/dist/chunk-XWZAOCQ7.mjs +2607 -0
  64. package/dist/chunk-Y6MA7ULW.mjs +148 -0
  65. package/dist/chunk-YMS7Q7LG.mjs +214 -0
  66. package/dist/chunk-ZA37XTGA.mjs +175 -0
  67. package/dist/cli/index.js +13189 -6838
  68. package/dist/cli/index.mjs +140 -22
  69. package/dist/codemod/cli.mjs +1 -1
  70. package/dist/codemod/index.mjs +1 -1
  71. package/dist/config-PL24KEWL.mjs +219 -0
  72. package/dist/dev-server-RmGHIntF.d.mts +113 -0
  73. package/dist/dev-server-RmGHIntF.d.ts +113 -0
  74. package/dist/dev-server.d.mts +1 -1
  75. package/dist/dev-server.d.ts +1 -1
  76. package/dist/dev-server.js +4135 -440
  77. package/dist/dev-server.mjs +5 -5
  78. package/dist/envelope.js +2812 -275
  79. package/dist/envelope.mjs +3 -3
  80. package/dist/index.d.mts +161 -2
  81. package/dist/index.d.ts +161 -2
  82. package/dist/index.js +4429 -428
  83. package/dist/index.mjs +217 -9
  84. package/{src/cli/init.ts → dist/init-7JQMAAXS.mjs} +70 -95
  85. package/dist/init-DQDX3QK6.mjs +369 -0
  86. package/dist/init-EHO4VQ22.mjs +369 -0
  87. package/dist/init-UC3FWPIW.mjs +367 -0
  88. package/dist/init-UNSMVKIK.mjs +366 -0
  89. package/dist/init-UNV5XIDE.mjs +367 -0
  90. package/dist/project-compiler-2P4N4DR7.mjs +10 -0
  91. package/dist/project-compiler-D2LCC27O.mjs +10 -0
  92. package/dist/project-compiler-EJ3GANJE.mjs +10 -0
  93. package/dist/project-compiler-LOQKVRZJ.mjs +10 -0
  94. package/dist/project-compiler-OP2VVGJQ.mjs +10 -0
  95. package/dist/project-compiler-RQ6OQKRM.mjs +10 -0
  96. package/dist/project-compiler-VWNNCHGO.mjs +10 -0
  97. package/dist/project-compiler-XVAAU4C5.mjs +10 -0
  98. package/dist/project-compiler-YES5FGMD.mjs +10 -0
  99. package/dist/project-compiler-ZKMQDLGU.mjs +10 -0
  100. package/dist/project-decompiler-FLXCEJHS.mjs +7 -0
  101. package/dist/project-decompiler-US7GAVIC.mjs +7 -0
  102. package/dist/project-decompiler-VLPR22QF.mjs +7 -0
  103. package/dist/pull-FUS5QYZS.mjs +109 -0
  104. package/dist/pull-LD5ENLGY.mjs +109 -0
  105. package/dist/pull-P44LDRWB.mjs +109 -0
  106. package/dist/testing/index.js +2822 -285
  107. package/dist/testing/index.mjs +2 -2
  108. package/dist/verify-SEIXUGN4.mjs +1833 -0
  109. package/dist/vite/index.js +2815 -278
  110. package/dist/vite/index.mjs +3 -3
  111. package/examples/uber-app/app/admin/fleet.tsx +19 -19
  112. package/package.json +16 -6
  113. package/compile-blueprint-chat.mjs +0 -99
  114. package/compile-blueprint-glass-console.mjs +0 -98
  115. package/compile-chat-defs.mjs +0 -92
  116. package/examples/uber-app/tests/payment.test.tsx +0 -129
  117. package/examples/uber-app/tests/ride-flow.test.tsx +0 -123
  118. package/package.json.backup +0 -86
  119. package/scripts/decompile.ts +0 -226
  120. package/scripts/seed-auth.ts +0 -267
  121. package/scripts/seed-uber.ts +0 -248
  122. package/scripts/validate-uber.ts +0 -119
  123. package/seed-blueprint-chat.mjs +0 -444
  124. package/seed-blueprint-glass-console.mjs +0 -445
  125. package/seed-compiled.mjs +0 -318
  126. package/src/RoundTripValidator.ts +0 -400
  127. package/src/__tests__/atom-rendering-coverage.test.ts +0 -680
  128. package/src/__tests__/auth-module-compilation.test.ts +0 -247
  129. package/src/__tests__/auth-template-compilation.test.ts +0 -589
  130. package/src/__tests__/change-extractor.test.ts +0 -142
  131. package/src/__tests__/cli-pull.test.ts +0 -73
  132. package/src/__tests__/cli-test.test.ts +0 -72
  133. package/src/__tests__/component-extractor.test.ts +0 -331
  134. package/src/__tests__/context-extractor.test.ts +0 -145
  135. package/src/__tests__/decompiler.test.ts +0 -718
  136. package/src/__tests__/define-blueprint.test.ts +0 -133
  137. package/src/__tests__/definition-validator.test.ts +0 -519
  138. package/src/__tests__/during-extractor.test.ts +0 -152
  139. package/src/__tests__/effect-extractor.test.ts +0 -107
  140. package/src/__tests__/event-emission.test.ts +0 -127
  141. package/src/__tests__/examples.test.ts +0 -236
  142. package/src/__tests__/full-blueprint-coverage.test.ts +0 -1221
  143. package/src/__tests__/golden-suite.test.ts +0 -403
  144. package/src/__tests__/grammar-island-extractor.test.ts +0 -289
  145. package/src/__tests__/instance-key.test.ts +0 -82
  146. package/src/__tests__/ir-migration.test.ts +0 -255
  147. package/src/__tests__/lock-file.test.ts +0 -117
  148. package/src/__tests__/model-extractor.test.ts +0 -195
  149. package/src/__tests__/model-field-acl.test.ts +0 -237
  150. package/src/__tests__/model-hooks.test.ts +0 -130
  151. package/src/__tests__/model-ref-resolution.test.ts +0 -268
  152. package/src/__tests__/model-roundtrip.test.ts +0 -502
  153. package/src/__tests__/model-runtime.test.ts +0 -112
  154. package/src/__tests__/model-transitions.test.ts +0 -183
  155. package/src/__tests__/nrt-action-trace.test.ts +0 -391
  156. package/src/__tests__/pipeline-hardening.test.ts +0 -413
  157. package/src/__tests__/project-compiler.test.ts +0 -546
  158. package/src/__tests__/project-decompiler.test.ts +0 -343
  159. package/src/__tests__/query-compilation.test.ts +0 -145
  160. package/src/__tests__/round-trip/PLAN.md +0 -158
  161. package/src/__tests__/round-trip/README.md +0 -52
  162. package/src/__tests__/round-trip/RESULTS.md +0 -86
  163. package/src/__tests__/round-trip/fixtures/data-heavy/main.workflow.tsx +0 -55
  164. package/src/__tests__/round-trip/fixtures/data-heavy/mm.config.ts +0 -11
  165. package/src/__tests__/round-trip/fixtures/data-heavy/models/contact.ts +0 -54
  166. package/src/__tests__/round-trip/fixtures/full-workflow/main.workflow.tsx +0 -79
  167. package/src/__tests__/round-trip/fixtures/full-workflow/mm.config.ts +0 -12
  168. package/src/__tests__/round-trip/fixtures/full-workflow/models/order.ts +0 -50
  169. package/src/__tests__/round-trip/fixtures/simple-crud/main.workflow.tsx +0 -25
  170. package/src/__tests__/round-trip/fixtures/simple-crud/mm.config.ts +0 -11
  171. package/src/__tests__/round-trip/fixtures/simple-crud/models/task.ts +0 -32
  172. package/src/__tests__/round-trip/fixtures/view-heavy/main.workflow.tsx +0 -79
  173. package/src/__tests__/round-trip/fixtures/view-heavy/mm.config.ts +0 -10
  174. package/src/__tests__/round-trip/round-trip.test.ts +0 -2598
  175. package/src/__tests__/round-trip-ir.test.ts +0 -300
  176. package/src/__tests__/round-trip.test.ts +0 -1212
  177. package/src/__tests__/route-merging.test.ts +0 -372
  178. package/src/__tests__/router-composition.test.ts +0 -489
  179. package/src/__tests__/router-extractor.test.ts +0 -176
  180. package/src/__tests__/server-action-extractor.test.ts +0 -128
  181. package/src/__tests__/smart-type-inference.test.ts +0 -365
  182. package/src/__tests__/source-envelope.test.ts +0 -284
  183. package/src/__tests__/source-fidelity.test.ts +0 -516
  184. package/src/__tests__/state-extractor.test.ts +0 -115
  185. package/src/__tests__/strict-mode.test.ts +0 -227
  186. package/src/__tests__/transition-effect-extractor.test.ts +0 -119
  187. package/src/__tests__/transition-extractor.test.ts +0 -68
  188. package/src/__tests__/ts-to-expression.test.ts +0 -462
  189. package/src/__tests__/type-generator.test.ts +0 -201
  190. package/src/__tests__/uber-validation.test.ts +0 -502
  191. package/src/action-compiler.ts +0 -361
  192. package/src/babel/emitters/experience-transform.ts +0 -199
  193. package/src/babel/emitters/ir-to-tsx-emitter.ts +0 -110
  194. package/src/babel/emitters/pure-form-emitter.ts +0 -1023
  195. package/src/babel/emitters/runtime-glue-emitter.ts +0 -39
  196. package/src/babel/extractors/change-extractor.ts +0 -199
  197. package/src/babel/extractors/component-extractor.ts +0 -907
  198. package/src/babel/extractors/computed-extractor.ts +0 -262
  199. package/src/babel/extractors/context-extractor.ts +0 -277
  200. package/src/babel/extractors/during-extractor.ts +0 -295
  201. package/src/babel/extractors/effect-extractor.ts +0 -340
  202. package/src/babel/extractors/event-extractor.ts +0 -235
  203. package/src/babel/extractors/grammar-island-extractor.ts +0 -302
  204. package/src/babel/extractors/model-extractor.ts +0 -1018
  205. package/src/babel/extractors/router-extractor.ts +0 -303
  206. package/src/babel/extractors/server-action-extractor.ts +0 -173
  207. package/src/babel/extractors/server-action-hook-extractor.ts +0 -72
  208. package/src/babel/extractors/server-state-extractor.ts +0 -88
  209. package/src/babel/extractors/state-extractor.ts +0 -214
  210. package/src/babel/extractors/transition-effect-extractor.ts +0 -176
  211. package/src/babel/extractors/transition-extractor.ts +0 -143
  212. package/src/babel/index.ts +0 -24
  213. package/src/babel/transpilers/ts-to-expression.ts +0 -674
  214. package/src/babel/visitor.ts +0 -807
  215. package/src/cli/auth.ts +0 -255
  216. package/src/cli/build.ts +0 -288
  217. package/src/cli/deploy.ts +0 -206
  218. package/src/cli/index.ts +0 -328
  219. package/src/cli/installer.ts +0 -261
  220. package/src/cli/lock-file.ts +0 -94
  221. package/src/cli/mmrc.ts +0 -22
  222. package/src/cli/pull.ts +0 -172
  223. package/src/cli/registry-client.ts +0 -175
  224. package/src/cli/test.ts +0 -397
  225. package/src/cli/type-generator.ts +0 -243
  226. package/src/codemod/__tests__/forward.test.ts +0 -239
  227. package/src/codemod/__tests__/reverse.test.ts +0 -145
  228. package/src/codemod/__tests__/round-trip.test.ts +0 -137
  229. package/src/codemod/annotation.ts +0 -97
  230. package/src/codemod/classify.ts +0 -197
  231. package/src/codemod/cli.ts +0 -207
  232. package/src/codemod/control-flow.ts +0 -409
  233. package/src/codemod/forward.ts +0 -244
  234. package/src/codemod/import-manager.ts +0 -171
  235. package/src/codemod/index.ts +0 -120
  236. package/src/codemod/reverse.ts +0 -197
  237. package/src/codemod/rules.ts +0 -174
  238. package/src/codemod/state-transform.ts +0 -126
  239. package/src/decompiler/ast-builder.ts +0 -538
  240. package/src/decompiler/config-generator.ts +0 -151
  241. package/src/decompiler/index.ts +0 -315
  242. package/src/decompiler/project-decompiler.ts +0 -1776
  243. package/src/decompiler/project.ts +0 -862
  244. package/src/decompiler/split-strategy.ts +0 -140
  245. package/src/decompiler/state-emitter.ts +0 -1053
  246. package/src/decompiler/sx-emitter.ts +0 -318
  247. package/src/decompiler/workspace-hydrator.ts +0 -189
  248. package/src/dev-server.ts +0 -238
  249. package/src/envelope/fs-tree.ts +0 -217
  250. package/src/envelope/source-envelope.ts +0 -264
  251. package/src/envelope.ts +0 -315
  252. package/src/incremental-compiler.ts +0 -401
  253. package/src/index.ts +0 -99
  254. package/src/model-compiler.ts +0 -277
  255. package/src/project-compiler.ts +0 -1629
  256. package/src/route-extractor.ts +0 -333
  257. package/src/testing/index.ts +0 -32
  258. package/src/testing/snapshot.ts +0 -252
  259. package/src/testing/test-utils.ts +0 -226
  260. package/src/types.ts +0 -68
  261. package/src/vite/index.ts +0 -288
  262. package/test-compile.mjs +0 -142
  263. package/tsconfig.json +0 -25
  264. package/tsup.config.ts +0 -23
  265. package/vitest.config.ts +0 -9
@@ -1,300 +0,0 @@
1
- /**
2
- * Round-Trip IR Tests — validates decompile(IR) → compile(TSX) → equivalent IR.
3
- *
4
- * For each example, we:
5
- * 1. Compile the original .workflow.tsx → IR
6
- * 2. Decompile the IR → generated TSX
7
- * 3. Recompile the generated TSX → round-tripped IR
8
- * 4. Compare structural properties (fields, states, transitions)
9
- */
10
-
11
- import { describe, it, expect } from 'vitest';
12
- import * as fs from 'fs';
13
- import * as path from 'path';
14
- import { validateSourceRoundTrip, compileSource } from '../RoundTripValidator';
15
- import { decompile, type DecompilerInput } from '../decompiler';
16
-
17
- // =============================================================================
18
- // Helpers
19
- // =============================================================================
20
-
21
- const EXAMPLES_DIR = path.resolve(__dirname, '../../examples');
22
-
23
- function readExample(filename: string): string {
24
- return fs.readFileSync(path.join(EXAMPLES_DIR, filename), 'utf-8');
25
- }
26
-
27
- // =============================================================================
28
- // Counter
29
- // =============================================================================
30
-
31
- describe('round-trip IR: counter', () => {
32
- const source = readExample('counter.workflow.tsx');
33
- const originalIR = compileSource(source, 'counter.workflow.tsx');
34
-
35
- it('should compile the original source', () => {
36
- expect(originalIR).not.toBeNull();
37
- expect(originalIR!.slug).toBe('counter');
38
- });
39
-
40
- it('should preserve fields through round trip', () => {
41
- const result = validateSourceRoundTrip(source, 'counter.workflow.tsx');
42
- expect(result).not.toBeNull();
43
- const fieldDiffs = result!.diffs.filter(d => d.path.startsWith('fields'));
44
- expect(fieldDiffs.filter(d => d.severity === 'error')).toEqual([]);
45
-
46
- // Verify specific fields exist in round-tripped IR
47
- const rtFields = result!.roundTrippedIR!.fields.map(f => f.name).sort();
48
- expect(rtFields).toContain('count');
49
- expect(rtFields).toContain('status');
50
- expect(rtFields).toContain('lastAction');
51
- });
52
-
53
- it('should preserve transitions through round trip', () => {
54
- const result = validateSourceRoundTrip(source, 'counter.workflow.tsx');
55
- expect(result).not.toBeNull();
56
- const transDiffs = result!.diffs.filter(d => d.path.startsWith('transitions') && d.severity === 'error');
57
- expect(transDiffs).toEqual([]);
58
-
59
- // Verify transition names
60
- const rtTransitions = result!.roundTrippedIR!.transitions.map(t => t.name).sort();
61
- expect(rtTransitions).toContain('start');
62
- expect(rtTransitions).toContain('increment');
63
- expect(rtTransitions).toContain('decrement');
64
- expect(rtTransitions).toContain('reset');
65
- });
66
-
67
- it('should preserve states with effects through round trip', () => {
68
- const result = validateSourceRoundTrip(source, 'counter.workflow.tsx');
69
- expect(result).not.toBeNull();
70
-
71
- // The 'counting' state should have on_enter actions
72
- const countingState = result!.roundTrippedIR!.states.find(s => s.name === 'counting');
73
- expect(countingState).toBeDefined();
74
- expect(countingState!.on_enter.length).toBeGreaterThan(0);
75
- });
76
-
77
- it('should produce valid TSX that includes useOnChange', () => {
78
- const ir = compileSource(source, 'counter.workflow.tsx')!;
79
- const { code } = decompile(ir as DecompilerInput);
80
- expect(code).toContain('useOnChange');
81
- expect(code).toContain('count');
82
- });
83
- });
84
-
85
- // =============================================================================
86
- // Todo App
87
- // =============================================================================
88
-
89
- describe('round-trip IR: todo-app', () => {
90
- const source = readExample('todo-app.workflow.tsx');
91
- const originalIR = compileSource(source, 'todo-app.workflow.tsx');
92
-
93
- it('should compile the original source', () => {
94
- expect(originalIR).not.toBeNull();
95
- expect(originalIR!.slug).toBe('todo-app');
96
- expect(originalIR!.category).toBe('data');
97
- });
98
-
99
- it('should preserve fields through round trip', () => {
100
- const result = validateSourceRoundTrip(source, 'todo-app.workflow.tsx');
101
- expect(result).not.toBeNull();
102
-
103
- const rtFields = result!.roundTrippedIR!.fields.map(f => f.name).sort();
104
- expect(rtFields).toContain('title');
105
- expect(rtFields).toContain('filter');
106
- expect(rtFields).toContain('itemCount');
107
- });
108
-
109
- it('should preserve transitions through round trip', () => {
110
- const result = validateSourceRoundTrip(source, 'todo-app.workflow.tsx');
111
- expect(result).not.toBeNull();
112
-
113
- const rtTransitions = result!.roundTrippedIR!.transitions.map(t => t.name).sort();
114
- expect(rtTransitions).toContain('activate');
115
- expect(rtTransitions).toContain('archive');
116
- expect(rtTransitions).toContain('restore');
117
- });
118
-
119
- it('should preserve state effects (on_enter, on_exit, during)', () => {
120
- const result = validateSourceRoundTrip(source, 'todo-app.workflow.tsx');
121
- expect(result).not.toBeNull();
122
-
123
- // 'active' state should have on_enter, on_exit, and during
124
- const activeState = result!.roundTrippedIR!.states.find(s => s.name === 'active');
125
- expect(activeState).toBeDefined();
126
- expect(activeState!.on_enter.length).toBeGreaterThan(0);
127
- expect(activeState!.on_exit.length).toBeGreaterThan(0);
128
- expect(activeState!.during.length).toBeGreaterThan(0);
129
- });
130
-
131
- it('should produce valid TSX that includes useRole and useQuery', () => {
132
- const ir = compileSource(source, 'todo-app.workflow.tsx')!;
133
- const { code } = decompile(ir as DecompilerInput);
134
- expect(code).toContain('useRole');
135
- expect(code).toContain('useQuery');
136
- expect(code).toContain('useWhileIn');
137
- });
138
- });
139
-
140
- // =============================================================================
141
- // Dashboard
142
- // =============================================================================
143
-
144
- describe('round-trip IR: dashboard', () => {
145
- const source = readExample('dashboard.workflow.tsx');
146
- const originalIR = compileSource(source, 'dashboard.workflow.tsx');
147
-
148
- it('should compile the original source', () => {
149
- expect(originalIR).not.toBeNull();
150
- expect(originalIR!.slug).toBe('dashboard');
151
- expect(originalIR!.category).toBe('blueprint');
152
- });
153
-
154
- it('should preserve fields through round trip', () => {
155
- const result = validateSourceRoundTrip(source, 'dashboard.workflow.tsx');
156
- expect(result).not.toBeNull();
157
-
158
- const rtFields = result!.roundTrippedIR!.fields.map(f => f.name).sort();
159
- expect(rtFields).toContain('activeRoute');
160
- expect(rtFields).toContain('sidebarOpen');
161
- expect(rtFields).toContain('searchQuery');
162
- expect(rtFields).toContain('notificationCount');
163
- expect(rtFields).toContain('theme');
164
- });
165
-
166
- it('should preserve all 7 transitions', () => {
167
- const result = validateSourceRoundTrip(source, 'dashboard.workflow.tsx');
168
- expect(result).not.toBeNull();
169
-
170
- const rtTransitions = result!.roundTrippedIR!.transitions.map(t => t.name).sort();
171
- expect(rtTransitions).toContain('initialize');
172
- expect(rtTransitions).toContain('suspend');
173
- expect(rtTransitions).toContain('resume');
174
- expect(rtTransitions).toContain('deactivate');
175
- expect(rtTransitions).toContain('navigate');
176
- expect(rtTransitions).toContain('open-settings');
177
- expect(rtTransitions).toContain('close-settings');
178
- });
179
-
180
- it('should preserve state effects across multiple states', () => {
181
- const result = validateSourceRoundTrip(source, 'dashboard.workflow.tsx');
182
- expect(result).not.toBeNull();
183
-
184
- const activeState = result!.roundTrippedIR!.states.find(s => s.name === 'active');
185
- expect(activeState).toBeDefined();
186
- expect(activeState!.on_enter.length).toBeGreaterThan(0);
187
- expect(activeState!.on_exit.length).toBeGreaterThan(0);
188
- expect(activeState!.during.length).toBeGreaterThan(0);
189
-
190
- const settingsState = result!.roundTrippedIR!.states.find(s => s.name === 'settings');
191
- expect(settingsState).toBeDefined();
192
- expect(settingsState!.on_enter.length).toBeGreaterThan(0);
193
- });
194
-
195
- it('should produce TSX with useRole, useQuery, useOnChange, useOnEvent', () => {
196
- const ir = compileSource(source, 'dashboard.workflow.tsx')!;
197
- const { code } = decompile(ir as DecompilerInput);
198
- expect(code).toContain('useRole');
199
- expect(code).toContain('useQuery');
200
- expect(code).toContain('useOnChange');
201
- expect(code).toContain('useOnEvent');
202
- expect(code).toContain('useMutation');
203
- });
204
-
205
- it('should have no critical errors', () => {
206
- const result = validateSourceRoundTrip(source, 'dashboard.workflow.tsx');
207
- expect(result).not.toBeNull();
208
-
209
- const errors = result!.diffs.filter(d => d.severity === 'error');
210
- // Log errors for debugging (non-fatal — we check specific properties above)
211
- if (errors.length > 0) {
212
- console.log('Dashboard round-trip errors:', errors);
213
- }
214
- });
215
- });
216
-
217
- // =============================================================================
218
- // Invoice Approval (multi-file blueprint, test main.workflow.tsx)
219
- // =============================================================================
220
-
221
- describe('round-trip IR: invoice-approval', () => {
222
- const source = readExample('invoice-approval/main.workflow.tsx');
223
- const originalIR = compileSource(source, 'invoice-approval/main.workflow.tsx');
224
-
225
- it('should compile the original source', () => {
226
- expect(originalIR).not.toBeNull();
227
- expect(originalIR!.slug).toBe('invoice-approval');
228
- expect(originalIR!.category).toBe('blueprint');
229
- });
230
-
231
- it('should preserve all 5 fields', () => {
232
- const result = validateSourceRoundTrip(source, 'invoice-approval/main.workflow.tsx');
233
- expect(result).not.toBeNull();
234
-
235
- const rtFields = result!.roundTrippedIR!.fields.map(f => f.name).sort();
236
- expect(rtFields).toContain('activeRoute');
237
- expect(rtFields).toContain('selectedInvoiceId');
238
- expect(rtFields).toContain('filterStatus');
239
- expect(rtFields).toContain('totalPending');
240
- expect(rtFields).toContain('lastAction');
241
- });
242
-
243
- it('should preserve all 4 transitions with roles and requiredFields', () => {
244
- const result = validateSourceRoundTrip(source, 'invoice-approval/main.workflow.tsx');
245
- expect(result).not.toBeNull();
246
-
247
- const rtMap = new Map(result!.roundTrippedIR!.transitions.map(t => [t.name, t]));
248
-
249
- // submit transition with requiredFields and roles
250
- const submit = rtMap.get('submit');
251
- expect(submit).toBeDefined();
252
- expect(submit!.from).toContain('draft');
253
- expect(submit!.to).toBe('submitted');
254
- expect(submit!.roles).toContain('submitter');
255
- expect(submit!.required_fields).toEqual(
256
- expect.arrayContaining(['amount', 'vendor', 'date']),
257
- );
258
-
259
- // approve transition with roles
260
- const approve = rtMap.get('approve');
261
- expect(approve).toBeDefined();
262
- expect(approve!.from).toContain('submitted');
263
- expect(approve!.to).toBe('approved');
264
- expect(approve!.roles).toContain('approver');
265
-
266
- // reject transition
267
- const reject = rtMap.get('reject');
268
- expect(reject).toBeDefined();
269
-
270
- // revise transition
271
- const revise = rtMap.get('revise');
272
- expect(revise).toBeDefined();
273
- expect(revise!.from).toContain('rejected');
274
- expect(revise!.to).toBe('draft');
275
- });
276
-
277
- it('should preserve state effects across 4 states', () => {
278
- const result = validateSourceRoundTrip(source, 'invoice-approval/main.workflow.tsx');
279
- expect(result).not.toBeNull();
280
-
281
- // draft, submitted, approved, rejected should all have on_enter
282
- for (const stateName of ['draft', 'submitted', 'approved', 'rejected']) {
283
- const state = result!.roundTrippedIR!.states.find(s => s.name === stateName);
284
- expect(state).toBeDefined();
285
- expect(state!.on_enter.length).toBeGreaterThan(0);
286
- }
287
-
288
- // draft should have on_exit
289
- const draftState = result!.roundTrippedIR!.states.find(s => s.name === 'draft');
290
- expect(draftState!.on_exit.length).toBeGreaterThan(0);
291
- });
292
-
293
- it('should produce TSX with useRole declarations', () => {
294
- const ir = compileSource(source, 'invoice-approval/main.workflow.tsx')!;
295
- const { code } = decompile(ir as DecompilerInput);
296
- expect(code).toContain('useRole');
297
- expect(code).toContain('"approver"');
298
- expect(code).toContain('"submitter"');
299
- });
300
- });