@mmapp/react-compiler 0.1.0-alpha.1 → 0.1.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ATOM-PIPELINE.md +144 -0
- package/README.md +88 -40
- package/dist/babel/index.js +113 -6
- package/dist/babel/index.mjs +2 -2
- package/dist/chunk-3USIFFE4.mjs +2190 -0
- package/dist/chunk-45YMGEVT.mjs +186 -0
- package/dist/chunk-4FN2AISW.mjs +148 -0
- package/dist/chunk-4OPI5L7G.mjs +2593 -0
- package/dist/chunk-4RYTKOOJ.mjs +186 -0
- package/dist/chunk-5RKTOVR5.mjs +244 -0
- package/dist/chunk-5YDMOO4X.mjs +214 -0
- package/dist/chunk-64ZWEMLJ.mjs +148 -0
- package/dist/chunk-6XP4KSWQ.mjs +2190 -0
- package/dist/chunk-72QWL54I.mjs +175 -0
- package/dist/chunk-7B4TRI7C.mjs +4835 -0
- package/dist/chunk-7ZKGHTNB.mjs +4952 -0
- package/dist/chunk-CIESM3BP.mjs +33 -0
- package/dist/chunk-DE3ZGQAC.mjs +148 -0
- package/dist/chunk-DMCY3BBG.mjs +1933 -0
- package/dist/chunk-DPIK3PJS.mjs +244 -0
- package/dist/chunk-E5IVH4RE.mjs +186 -0
- package/dist/chunk-E6FZNUR5.mjs +4953 -0
- package/dist/chunk-EJRBDQDP.mjs +2607 -0
- package/dist/chunk-ELO4TXJL.mjs +186 -0
- package/dist/chunk-FKRO52XH.mjs +3446 -0
- package/dist/chunk-FL4YAKU6.mjs +4941 -0
- package/dist/chunk-FYT47UBU.mjs +5076 -0
- package/dist/chunk-GCLGPOJZ.mjs +148 -0
- package/dist/chunk-GXB4JOP7.mjs +5072 -0
- package/dist/chunk-HFXOUMTD.mjs +175 -0
- package/dist/chunk-HWIZ47US.mjs +214 -0
- package/dist/chunk-IB7MNPQL.mjs +4953 -0
- package/dist/chunk-ICSIHQCG.mjs +148 -0
- package/dist/chunk-JLA5VNQ3.mjs +186 -0
- package/dist/chunk-JQLWFCTM.mjs +214 -0
- package/dist/chunk-KFJJCQAL.mjs +148 -0
- package/dist/chunk-KJUIIEQE.mjs +186 -0
- package/dist/chunk-KNWTHRVQ.mjs +175 -0
- package/dist/chunk-KSG4XSZF.mjs +175 -0
- package/dist/chunk-LF5N6DOU.mjs +175 -0
- package/dist/chunk-LJQCM2IM.mjs +214 -0
- package/dist/chunk-NW6555WJ.mjs +186 -0
- package/dist/chunk-OMZE6VLQ.mjs +214 -0
- package/dist/chunk-P4BR7WVO.mjs +2190 -0
- package/dist/chunk-QQHVYH2X.mjs +244 -0
- package/dist/chunk-S5QLWLLT.mjs +186 -0
- package/dist/chunk-SCWGT2FY.mjs +2190 -0
- package/dist/chunk-SMKJUSB3.mjs +2190 -0
- package/dist/chunk-VCAY2KGM.mjs +175 -0
- package/dist/chunk-WECAV6QB.mjs +148 -0
- package/dist/chunk-WMKBXUCE.mjs +3228 -0
- package/dist/chunk-XAJ5BKKL.mjs +4947 -0
- package/dist/chunk-XG2X7AEA.mjs +175 -0
- package/dist/chunk-XG7Z23NQ.mjs +148 -0
- package/dist/chunk-XWZAOCQ7.mjs +2607 -0
- package/dist/chunk-Y6MA7ULW.mjs +148 -0
- package/dist/chunk-YMS7Q7LG.mjs +214 -0
- package/dist/chunk-ZA37XTGA.mjs +175 -0
- package/dist/cli/index.js +1616 -366
- package/dist/cli/index.mjs +8 -8
- package/dist/codemod/cli.mjs +1 -1
- package/dist/codemod/index.mjs +1 -1
- package/dist/dev-server-RmGHIntF.d.mts +113 -0
- package/dist/dev-server-RmGHIntF.d.ts +113 -0
- package/dist/dev-server.d.mts +1 -1
- package/dist/dev-server.d.ts +1 -1
- package/dist/dev-server.js +982 -53
- package/dist/dev-server.mjs +5 -5
- package/dist/envelope.js +113 -6
- package/dist/envelope.mjs +3 -3
- package/dist/index.d.mts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +992 -63
- package/dist/index.mjs +8 -8
- package/{src/cli/init.ts → dist/init-7JQMAAXS.mjs} +70 -95
- package/dist/init-EHO4VQ22.mjs +369 -0
- package/dist/init-UC3FWPIW.mjs +367 -0
- package/dist/init-UNSMVKIK.mjs +366 -0
- package/dist/init-UNV5XIDE.mjs +367 -0
- package/dist/project-compiler-2P4N4DR7.mjs +10 -0
- package/dist/project-compiler-D2LCC27O.mjs +10 -0
- package/dist/project-compiler-EJ3GANJE.mjs +10 -0
- package/dist/project-compiler-LOQKVRZJ.mjs +10 -0
- package/dist/project-compiler-RQ6OQKRM.mjs +10 -0
- package/dist/project-compiler-VWNNCHGO.mjs +10 -0
- package/dist/project-compiler-XVAAU4C5.mjs +10 -0
- package/dist/project-compiler-YES5FGMD.mjs +10 -0
- package/dist/project-compiler-ZKMQDLGU.mjs +10 -0
- package/dist/project-decompiler-FLXCEJHS.mjs +7 -0
- package/dist/project-decompiler-VLPR22QF.mjs +7 -0
- package/dist/pull-FUS5QYZS.mjs +109 -0
- package/dist/pull-LD5ENLGY.mjs +109 -0
- package/dist/testing/index.js +113 -6
- package/dist/testing/index.mjs +2 -2
- package/dist/vite/index.js +113 -6
- package/dist/vite/index.mjs +3 -3
- package/examples/uber-app/app/admin/fleet.tsx +19 -19
- package/package.json +4 -3
- package/compile-blueprint-chat.mjs +0 -99
- package/compile-blueprint-glass-console.mjs +0 -98
- package/compile-chat-defs.mjs +0 -92
- package/examples/uber-app/tests/payment.test.tsx +0 -129
- package/examples/uber-app/tests/ride-flow.test.tsx +0 -123
- package/package.json.backup +0 -86
- package/scripts/decompile.ts +0 -226
- package/scripts/seed-auth.ts +0 -267
- package/scripts/seed-uber.ts +0 -248
- package/scripts/validate-uber.ts +0 -119
- package/seed-blueprint-chat.mjs +0 -444
- package/seed-blueprint-glass-console.mjs +0 -445
- package/seed-compiled.mjs +0 -318
- package/src/RoundTripValidator.ts +0 -400
- package/src/__tests__/atom-rendering-coverage.test.ts +0 -680
- package/src/__tests__/auth-module-compilation.test.ts +0 -247
- package/src/__tests__/auth-template-compilation.test.ts +0 -589
- package/src/__tests__/change-extractor.test.ts +0 -142
- package/src/__tests__/cli-pull.test.ts +0 -73
- package/src/__tests__/cli-test.test.ts +0 -72
- package/src/__tests__/component-extractor.test.ts +0 -331
- package/src/__tests__/context-extractor.test.ts +0 -145
- package/src/__tests__/decompiler.test.ts +0 -718
- package/src/__tests__/define-blueprint.test.ts +0 -133
- package/src/__tests__/definition-validator.test.ts +0 -519
- package/src/__tests__/during-extractor.test.ts +0 -152
- package/src/__tests__/effect-extractor.test.ts +0 -107
- package/src/__tests__/event-emission.test.ts +0 -127
- package/src/__tests__/examples.test.ts +0 -236
- package/src/__tests__/full-blueprint-coverage.test.ts +0 -1221
- package/src/__tests__/golden-suite.test.ts +0 -403
- package/src/__tests__/grammar-island-extractor.test.ts +0 -289
- package/src/__tests__/instance-key.test.ts +0 -82
- package/src/__tests__/ir-migration.test.ts +0 -255
- package/src/__tests__/lock-file.test.ts +0 -117
- package/src/__tests__/model-extractor.test.ts +0 -195
- package/src/__tests__/model-field-acl.test.ts +0 -237
- package/src/__tests__/model-hooks.test.ts +0 -130
- package/src/__tests__/model-ref-resolution.test.ts +0 -268
- package/src/__tests__/model-roundtrip.test.ts +0 -502
- package/src/__tests__/model-runtime.test.ts +0 -112
- package/src/__tests__/model-transitions.test.ts +0 -183
- package/src/__tests__/nrt-action-trace.test.ts +0 -391
- package/src/__tests__/pipeline-hardening.test.ts +0 -413
- package/src/__tests__/project-compiler.test.ts +0 -546
- package/src/__tests__/project-decompiler.test.ts +0 -343
- package/src/__tests__/query-compilation.test.ts +0 -145
- package/src/__tests__/round-trip/PLAN.md +0 -158
- package/src/__tests__/round-trip/README.md +0 -52
- package/src/__tests__/round-trip/RESULTS.md +0 -86
- package/src/__tests__/round-trip/fixtures/data-heavy/main.workflow.tsx +0 -55
- package/src/__tests__/round-trip/fixtures/data-heavy/mm.config.ts +0 -11
- package/src/__tests__/round-trip/fixtures/data-heavy/models/contact.ts +0 -54
- package/src/__tests__/round-trip/fixtures/full-workflow/main.workflow.tsx +0 -79
- package/src/__tests__/round-trip/fixtures/full-workflow/mm.config.ts +0 -12
- package/src/__tests__/round-trip/fixtures/full-workflow/models/order.ts +0 -50
- package/src/__tests__/round-trip/fixtures/simple-crud/main.workflow.tsx +0 -25
- package/src/__tests__/round-trip/fixtures/simple-crud/mm.config.ts +0 -11
- package/src/__tests__/round-trip/fixtures/simple-crud/models/task.ts +0 -32
- package/src/__tests__/round-trip/fixtures/view-heavy/main.workflow.tsx +0 -79
- package/src/__tests__/round-trip/fixtures/view-heavy/mm.config.ts +0 -10
- package/src/__tests__/round-trip/round-trip.test.ts +0 -2598
- package/src/__tests__/round-trip-ir.test.ts +0 -300
- package/src/__tests__/round-trip.test.ts +0 -1212
- package/src/__tests__/route-merging.test.ts +0 -372
- package/src/__tests__/router-composition.test.ts +0 -489
- package/src/__tests__/router-extractor.test.ts +0 -176
- package/src/__tests__/server-action-extractor.test.ts +0 -128
- package/src/__tests__/smart-type-inference.test.ts +0 -365
- package/src/__tests__/source-envelope.test.ts +0 -284
- package/src/__tests__/source-fidelity.test.ts +0 -516
- package/src/__tests__/state-extractor.test.ts +0 -115
- package/src/__tests__/strict-mode.test.ts +0 -227
- package/src/__tests__/transition-effect-extractor.test.ts +0 -119
- package/src/__tests__/transition-extractor.test.ts +0 -68
- package/src/__tests__/ts-to-expression.test.ts +0 -462
- package/src/__tests__/type-generator.test.ts +0 -201
- package/src/__tests__/uber-validation.test.ts +0 -502
- package/src/action-compiler.ts +0 -361
- package/src/babel/emitters/experience-transform.ts +0 -199
- package/src/babel/emitters/ir-to-tsx-emitter.ts +0 -110
- package/src/babel/emitters/pure-form-emitter.ts +0 -1023
- package/src/babel/emitters/runtime-glue-emitter.ts +0 -39
- package/src/babel/extractors/change-extractor.ts +0 -199
- package/src/babel/extractors/component-extractor.ts +0 -907
- package/src/babel/extractors/computed-extractor.ts +0 -262
- package/src/babel/extractors/context-extractor.ts +0 -277
- package/src/babel/extractors/during-extractor.ts +0 -295
- package/src/babel/extractors/effect-extractor.ts +0 -340
- package/src/babel/extractors/event-extractor.ts +0 -235
- package/src/babel/extractors/grammar-island-extractor.ts +0 -302
- package/src/babel/extractors/model-extractor.ts +0 -1018
- package/src/babel/extractors/router-extractor.ts +0 -303
- package/src/babel/extractors/server-action-extractor.ts +0 -173
- package/src/babel/extractors/server-action-hook-extractor.ts +0 -72
- package/src/babel/extractors/server-state-extractor.ts +0 -88
- package/src/babel/extractors/state-extractor.ts +0 -214
- package/src/babel/extractors/transition-effect-extractor.ts +0 -176
- package/src/babel/extractors/transition-extractor.ts +0 -143
- package/src/babel/index.ts +0 -24
- package/src/babel/transpilers/ts-to-expression.ts +0 -674
- package/src/babel/visitor.ts +0 -807
- package/src/cli/auth.ts +0 -255
- package/src/cli/build.ts +0 -288
- package/src/cli/deploy.ts +0 -206
- package/src/cli/index.ts +0 -328
- package/src/cli/installer.ts +0 -261
- package/src/cli/lock-file.ts +0 -94
- package/src/cli/mmrc.ts +0 -22
- package/src/cli/pull.ts +0 -172
- package/src/cli/registry-client.ts +0 -175
- package/src/cli/test.ts +0 -397
- package/src/cli/type-generator.ts +0 -243
- package/src/codemod/__tests__/forward.test.ts +0 -239
- package/src/codemod/__tests__/reverse.test.ts +0 -145
- package/src/codemod/__tests__/round-trip.test.ts +0 -137
- package/src/codemod/annotation.ts +0 -97
- package/src/codemod/classify.ts +0 -197
- package/src/codemod/cli.ts +0 -207
- package/src/codemod/control-flow.ts +0 -409
- package/src/codemod/forward.ts +0 -244
- package/src/codemod/import-manager.ts +0 -171
- package/src/codemod/index.ts +0 -120
- package/src/codemod/reverse.ts +0 -197
- package/src/codemod/rules.ts +0 -174
- package/src/codemod/state-transform.ts +0 -126
- package/src/decompiler/ast-builder.ts +0 -538
- package/src/decompiler/config-generator.ts +0 -151
- package/src/decompiler/index.ts +0 -315
- package/src/decompiler/project-decompiler.ts +0 -1776
- package/src/decompiler/project.ts +0 -862
- package/src/decompiler/split-strategy.ts +0 -140
- package/src/decompiler/state-emitter.ts +0 -1053
- package/src/decompiler/sx-emitter.ts +0 -318
- package/src/decompiler/workspace-hydrator.ts +0 -189
- package/src/dev-server.ts +0 -238
- package/src/envelope/fs-tree.ts +0 -217
- package/src/envelope/source-envelope.ts +0 -264
- package/src/envelope.ts +0 -315
- package/src/incremental-compiler.ts +0 -401
- package/src/index.ts +0 -99
- package/src/model-compiler.ts +0 -277
- package/src/project-compiler.ts +0 -1629
- package/src/route-extractor.ts +0 -333
- package/src/testing/index.ts +0 -32
- package/src/testing/snapshot.ts +0 -252
- package/src/testing/test-utils.ts +0 -226
- package/src/types.ts +0 -68
- package/src/vite/index.ts +0 -288
- package/test-compile.mjs +0 -142
- package/tsconfig.json +0 -25
- package/tsup.config.ts +0 -23
- package/vitest.config.ts +0 -9
|
@@ -1,413 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pipeline Hardening Tests — end-to-end validation of the full
|
|
3
|
-
* compiler → validator → migration → NRT pipeline.
|
|
4
|
-
*
|
|
5
|
-
* Tests the complete lifecycle:
|
|
6
|
-
* 1. React source → Babel compiler → IR definition
|
|
7
|
-
* 2. IR definition → validator → issues
|
|
8
|
-
* 3. IR definition → migration → normalized format
|
|
9
|
-
* 4. NRT types → comparator → diff
|
|
10
|
-
*
|
|
11
|
-
* These tests cover edge cases and cross-cutting concerns
|
|
12
|
-
* not addressed by individual phase tests.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { describe, it, expect } from 'vitest';
|
|
16
|
-
import { transformSync } from '@babel/core';
|
|
17
|
-
import babelPlugin from '../babel';
|
|
18
|
-
import { validateDefinition, isViableDefinition } from '@mindmatrix/player-core';
|
|
19
|
-
import { normalizeDefinition, detectIRVersion } from '@mindmatrix/player-core';
|
|
20
|
-
import type { IRWorkflowDefinition } from '@mindmatrix/player-core';
|
|
21
|
-
|
|
22
|
-
// =============================================================================
|
|
23
|
-
// Helpers
|
|
24
|
-
// =============================================================================
|
|
25
|
-
|
|
26
|
-
function compile(code: string, mode: 'strict' | 'infer' = 'infer'): IRWorkflowDefinition | null {
|
|
27
|
-
const result = transformSync(code, {
|
|
28
|
-
filename: 'test.workflow.tsx',
|
|
29
|
-
plugins: [[babelPlugin, { mode }]],
|
|
30
|
-
parserOpts: { plugins: ['jsx', 'typescript'], attachComment: true },
|
|
31
|
-
});
|
|
32
|
-
return (result as any)?.metadata?.mindmatrixIR ?? null;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// =============================================================================
|
|
36
|
-
// Full Pipeline: Compile → Validate → Migrate
|
|
37
|
-
// =============================================================================
|
|
38
|
-
|
|
39
|
-
describe('Full Pipeline', () => {
|
|
40
|
-
it('should compile a basic workflow and pass validation', () => {
|
|
41
|
-
const code = `
|
|
42
|
-
/** @workflow slug="pipeline-test" version="1.0.0" */
|
|
43
|
-
import { useState, useOnEnter, useTransition } from '@mindmatrix/react';
|
|
44
|
-
|
|
45
|
-
export default function PipelineTest() {
|
|
46
|
-
const [status, setStatus] = useState('idle');
|
|
47
|
-
const [active, setActive] = useState(false);
|
|
48
|
-
|
|
49
|
-
useOnEnter('idle', () => { setStatus('waiting'); });
|
|
50
|
-
useOnEnter('active', () => { setActive(true); });
|
|
51
|
-
useTransition('activate', { from: 'idle', to: 'active' });
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<Stack>
|
|
55
|
-
<Text>{status}</Text>
|
|
56
|
-
<Button onPress={() => {}}>Go</Button>
|
|
57
|
-
</Stack>
|
|
58
|
-
);
|
|
59
|
-
}`;
|
|
60
|
-
|
|
61
|
-
const ir = compile(code);
|
|
62
|
-
expect(ir).not.toBeNull();
|
|
63
|
-
expect(ir!.slug).toBe('pipeline-test');
|
|
64
|
-
|
|
65
|
-
// Validate
|
|
66
|
-
const validation = validateDefinition(ir!);
|
|
67
|
-
expect(validation.valid).toBe(true);
|
|
68
|
-
expect(validation.summary.stateCount).toBeGreaterThan(0);
|
|
69
|
-
expect(validation.summary.fieldCount).toBeGreaterThan(0);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('should compile a multi-state workflow and validate references', () => {
|
|
73
|
-
const code = `
|
|
74
|
-
/** @workflow slug="multi-state" version="1.0.0" */
|
|
75
|
-
import { useState, useOnEnter, useOnExit, useTransition } from '@mindmatrix/react';
|
|
76
|
-
|
|
77
|
-
export default function MultiState() {
|
|
78
|
-
const [count, setCount] = useState(0);
|
|
79
|
-
const [label, setLabel] = useState('start');
|
|
80
|
-
|
|
81
|
-
useOnEnter('idle', () => { setLabel('idle'); });
|
|
82
|
-
useOnEnter('active', () => { setLabel('active'); setCount(0); });
|
|
83
|
-
useOnExit('active', () => { setLabel('leaving'); });
|
|
84
|
-
|
|
85
|
-
useTransition('begin', { from: 'idle', to: 'active' });
|
|
86
|
-
useTransition('finish', { from: 'active', to: 'idle' });
|
|
87
|
-
|
|
88
|
-
return (
|
|
89
|
-
<Stack>
|
|
90
|
-
<Heading>State: {label}</Heading>
|
|
91
|
-
<Text>Count: {count}</Text>
|
|
92
|
-
</Stack>
|
|
93
|
-
);
|
|
94
|
-
}`;
|
|
95
|
-
|
|
96
|
-
const ir = compile(code);
|
|
97
|
-
expect(ir).not.toBeNull();
|
|
98
|
-
|
|
99
|
-
// Should have 2 states
|
|
100
|
-
expect(ir!.states.length).toBe(2);
|
|
101
|
-
expect(ir!.states.map(s => s.name).sort()).toEqual(['active', 'idle']);
|
|
102
|
-
|
|
103
|
-
// Should have 2 transitions
|
|
104
|
-
expect(ir!.transitions.length).toBe(2);
|
|
105
|
-
|
|
106
|
-
// Validate — all references should be clean
|
|
107
|
-
const validation = validateDefinition(ir!);
|
|
108
|
-
const refIssues = validation.issues.filter(i => i.category === 'referential');
|
|
109
|
-
expect(refIssues).toHaveLength(0);
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it('should detect compiled output as v1.0 and migrate', () => {
|
|
113
|
-
const code = `
|
|
114
|
-
/** @workflow slug="migration-test" version="1.0.0" */
|
|
115
|
-
import { useState, useTransition } from '@mindmatrix/react';
|
|
116
|
-
|
|
117
|
-
export default function MigrationTest() {
|
|
118
|
-
const [value, setValue] = useState('');
|
|
119
|
-
useTransition('submit');
|
|
120
|
-
return <Stack><Text>{value}</Text></Stack>;
|
|
121
|
-
}`;
|
|
122
|
-
|
|
123
|
-
const ir = compile(code);
|
|
124
|
-
expect(ir).not.toBeNull();
|
|
125
|
-
|
|
126
|
-
// Compiled output uses state_type/action_type/field_type (v1.0 format)
|
|
127
|
-
const asRecord = ir as unknown as Record<string, unknown>;
|
|
128
|
-
|
|
129
|
-
// Check if it needs migration
|
|
130
|
-
const version = detectIRVersion(asRecord);
|
|
131
|
-
// Our compiler outputs v1.0 format (with state_type, field_type)
|
|
132
|
-
// This is fine — the migration layer handles it
|
|
133
|
-
expect(['1.0', '1.1', '1.2']).toContain(version);
|
|
134
|
-
|
|
135
|
-
// Normalize to current
|
|
136
|
-
const migrated = normalizeDefinition(asRecord);
|
|
137
|
-
expect(migrated.definition.slug).toBe('migration-test');
|
|
138
|
-
expect(migrated.definition.states.length).toBeGreaterThan(0);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it('should validate compiled output with experience tree', () => {
|
|
142
|
-
const code = `
|
|
143
|
-
/** @workflow slug="experience-test" version="1.0.0" */
|
|
144
|
-
import { useState, useTransition } from '@mindmatrix/react';
|
|
145
|
-
|
|
146
|
-
export default function ExperienceTest() {
|
|
147
|
-
const [name, setName] = useState('');
|
|
148
|
-
|
|
149
|
-
useTransition('save');
|
|
150
|
-
|
|
151
|
-
return (
|
|
152
|
-
<Stack>
|
|
153
|
-
<Heading>Hello {name}</Heading>
|
|
154
|
-
<Row>
|
|
155
|
-
<Button onPress={() => {}}>Save</Button>
|
|
156
|
-
<Button onPress={() => {}}>Cancel</Button>
|
|
157
|
-
</Row>
|
|
158
|
-
</Stack>
|
|
159
|
-
);
|
|
160
|
-
}`;
|
|
161
|
-
|
|
162
|
-
const ir = compile(code);
|
|
163
|
-
expect(ir).not.toBeNull();
|
|
164
|
-
|
|
165
|
-
// Should have experience tree in metadata
|
|
166
|
-
expect(ir!.metadata?.experience).toBeDefined();
|
|
167
|
-
|
|
168
|
-
// Validate with known components
|
|
169
|
-
const validation = validateDefinition(ir!, {
|
|
170
|
-
knownComponents: ['Stack', 'Heading', 'Text', 'Row', 'Button', 'Card'],
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
// No experience errors expected for known components
|
|
174
|
-
const expErrors = validation.issues.filter(
|
|
175
|
-
i => i.category === 'experience' && i.severity === 'error'
|
|
176
|
-
);
|
|
177
|
-
expect(expErrors).toHaveLength(0);
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it('should compile useWhileIn and validate during actions', () => {
|
|
181
|
-
const code = `
|
|
182
|
-
/** @workflow slug="during-test" version="1.0.0" */
|
|
183
|
-
import { useState, useWhileIn, useTransition } from '@mindmatrix/react';
|
|
184
|
-
|
|
185
|
-
export default function DuringTest() {
|
|
186
|
-
const [tick, setTick] = useState(0);
|
|
187
|
-
|
|
188
|
-
useWhileIn('active', 500, () => { setTick(tick + 1); });
|
|
189
|
-
useTransition('start');
|
|
190
|
-
|
|
191
|
-
return <Stack><Text>{tick}</Text></Stack>;
|
|
192
|
-
}`;
|
|
193
|
-
|
|
194
|
-
const ir = compile(code);
|
|
195
|
-
expect(ir).not.toBeNull();
|
|
196
|
-
|
|
197
|
-
// Find the active state
|
|
198
|
-
const activeState = ir!.states.find(s => s.name === 'active');
|
|
199
|
-
expect(activeState).toBeDefined();
|
|
200
|
-
expect(activeState!.during.length).toBeGreaterThan(0);
|
|
201
|
-
expect(activeState!.during[0].interval_ms).toBe(500);
|
|
202
|
-
|
|
203
|
-
// Validate — during action should be structurally valid
|
|
204
|
-
const validation = validateDefinition(ir!);
|
|
205
|
-
const duringIssues = validation.issues.filter(i => i.code.startsWith('DURING_'));
|
|
206
|
-
expect(duringIssues).toHaveLength(0);
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
it('should compile useOnEvent and validate event subscriptions', () => {
|
|
210
|
-
const code = `
|
|
211
|
-
/** @workflow slug="event-test" version="1.0.0" */
|
|
212
|
-
import { useState, useOnEvent, useOnEnter, useTransition } from '@mindmatrix/react';
|
|
213
|
-
|
|
214
|
-
export default function EventTest() {
|
|
215
|
-
const [alert, setAlert] = useState('');
|
|
216
|
-
|
|
217
|
-
useOnEnter('idle', () => { setAlert(''); });
|
|
218
|
-
useOnEnter('acknowledged', () => { setAlert('ack'); });
|
|
219
|
-
useOnEvent('system:alert', (payload) => { setAlert('received'); });
|
|
220
|
-
useTransition('ack', { from: 'idle', to: 'acknowledged' });
|
|
221
|
-
|
|
222
|
-
return <Stack><Text>{alert}</Text></Stack>;
|
|
223
|
-
}`;
|
|
224
|
-
|
|
225
|
-
const ir = compile(code);
|
|
226
|
-
expect(ir).not.toBeNull();
|
|
227
|
-
// Events should be present (either on states or workflow level)
|
|
228
|
-
const hasEvents = ir!.states.some(s => s.on_event && s.on_event.length > 0) ||
|
|
229
|
-
(ir!.on_event && ir!.on_event.length > 0);
|
|
230
|
-
// The definition should be valid with proper from/to on transitions
|
|
231
|
-
const validation = validateDefinition(ir!);
|
|
232
|
-
expect(validation.valid).toBe(true);
|
|
233
|
-
});
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
// =============================================================================
|
|
237
|
-
// Strict Mode Validation
|
|
238
|
-
// =============================================================================
|
|
239
|
-
|
|
240
|
-
describe('Strict Mode Pipeline', () => {
|
|
241
|
-
it('should produce warnings for useEffect in strict mode', () => {
|
|
242
|
-
const code = `
|
|
243
|
-
/** @workflow slug="strict-test" version="1.0.0" */
|
|
244
|
-
import { useState, useEffect } from 'react';
|
|
245
|
-
import { useTransition } from '@mindmatrix/react';
|
|
246
|
-
|
|
247
|
-
export default function StrictTest() {
|
|
248
|
-
const [x, setX] = useState(0);
|
|
249
|
-
useEffect(() => { console.log('effect'); }, []);
|
|
250
|
-
useTransition('go');
|
|
251
|
-
return <Stack><Text>{x}</Text></Stack>;
|
|
252
|
-
}`;
|
|
253
|
-
|
|
254
|
-
const ir = compile(code, 'strict');
|
|
255
|
-
// The IR may still be produced but with errors/warnings in metadata
|
|
256
|
-
if (ir) {
|
|
257
|
-
const errors = (ir.metadata as any)?.errors;
|
|
258
|
-
const warnings = (ir.metadata as any)?.warnings;
|
|
259
|
-
const allIssues = [...(errors || []), ...(warnings || [])];
|
|
260
|
-
// In strict mode, useEffect should produce a diagnostic
|
|
261
|
-
const hasStrictIssue = allIssues.some((i: any) =>
|
|
262
|
-
i.code === 'STRICT_USE_EFFECT' || i.message?.includes('useEffect')
|
|
263
|
-
);
|
|
264
|
-
expect(hasStrictIssue).toBe(true);
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
// =============================================================================
|
|
270
|
-
// isViableDefinition Guard
|
|
271
|
-
// =============================================================================
|
|
272
|
-
|
|
273
|
-
describe('isViableDefinition Guard', () => {
|
|
274
|
-
it('should accept compiled workflow output', () => {
|
|
275
|
-
const code = `
|
|
276
|
-
/** @workflow slug="viable-test" version="1.0.0" */
|
|
277
|
-
import { useState, useTransition } from '@mindmatrix/react';
|
|
278
|
-
|
|
279
|
-
export default function ViableTest() {
|
|
280
|
-
const [x, setX] = useState(0);
|
|
281
|
-
useTransition('go');
|
|
282
|
-
return <Stack><Text>{x}</Text></Stack>;
|
|
283
|
-
}`;
|
|
284
|
-
|
|
285
|
-
const ir = compile(code);
|
|
286
|
-
expect(isViableDefinition(ir)).toBe(true);
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
it('should reject malformed output', () => {
|
|
290
|
-
expect(isViableDefinition(null)).toBe(false);
|
|
291
|
-
expect(isViableDefinition({})).toBe(false);
|
|
292
|
-
expect(isViableDefinition({ slug: 'test' })).toBe(false);
|
|
293
|
-
expect(isViableDefinition({ slug: 'test', states: [] })).toBe(false);
|
|
294
|
-
});
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
// =============================================================================
|
|
298
|
-
// Cross-Phase Integration
|
|
299
|
-
// =============================================================================
|
|
300
|
-
|
|
301
|
-
describe('Cross-Phase Integration', () => {
|
|
302
|
-
it('should handle workflow with all hook types', () => {
|
|
303
|
-
const code = `
|
|
304
|
-
/** @workflow slug="all-hooks" version="2.0.0" */
|
|
305
|
-
import { useState, useOnEnter, useOnExit, useTransition, useOnEvent, useWhileIn, useOnChange } from '@mindmatrix/react';
|
|
306
|
-
|
|
307
|
-
export default function AllHooks() {
|
|
308
|
-
const [count, setCount] = useState(0);
|
|
309
|
-
const [status, setStatus] = useState('draft');
|
|
310
|
-
const [alerts, setAlerts] = useState(0);
|
|
311
|
-
|
|
312
|
-
useOnEnter('draft', () => { setStatus('drafting'); });
|
|
313
|
-
useOnExit('draft', () => { setStatus('leaving-draft'); });
|
|
314
|
-
useOnEnter('active', () => { setCount(0); });
|
|
315
|
-
useWhileIn('active', 1000, () => { setCount(count + 1); });
|
|
316
|
-
useOnEvent('system:tick', () => { setAlerts(alerts + 1); });
|
|
317
|
-
useOnChange('status', () => { setAlerts(0); });
|
|
318
|
-
|
|
319
|
-
useTransition('activate', { from: 'draft', to: 'active' });
|
|
320
|
-
useTransition('deactivate', { from: 'active', to: 'draft' });
|
|
321
|
-
|
|
322
|
-
return (
|
|
323
|
-
<Stack>
|
|
324
|
-
<Heading>All Hooks Test</Heading>
|
|
325
|
-
<Text>Count: {count}</Text>
|
|
326
|
-
<Text>Status: {status}</Text>
|
|
327
|
-
<Text>Alerts: {alerts}</Text>
|
|
328
|
-
<Row>
|
|
329
|
-
<Button onPress={() => {}}>Activate</Button>
|
|
330
|
-
<Button onPress={() => {}}>Deactivate</Button>
|
|
331
|
-
</Row>
|
|
332
|
-
</Stack>
|
|
333
|
-
);
|
|
334
|
-
}`;
|
|
335
|
-
|
|
336
|
-
const ir = compile(code);
|
|
337
|
-
expect(ir).not.toBeNull();
|
|
338
|
-
expect(ir!.slug).toBe('all-hooks');
|
|
339
|
-
expect(ir!.version).toBe('2.0.0');
|
|
340
|
-
expect(ir!.states.length).toBe(2);
|
|
341
|
-
expect(ir!.transitions.length).toBe(2);
|
|
342
|
-
expect(ir!.fields.length).toBe(3);
|
|
343
|
-
|
|
344
|
-
// Validate
|
|
345
|
-
const validation = validateDefinition(ir!);
|
|
346
|
-
// Should be valid (all refs are correct)
|
|
347
|
-
expect(validation.valid).toBe(true);
|
|
348
|
-
|
|
349
|
-
// Should have experience tree
|
|
350
|
-
expect(ir!.metadata?.experience).toBeDefined();
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
it('should handle empty workflow gracefully', () => {
|
|
354
|
-
const code = `
|
|
355
|
-
/** @workflow slug="empty" version="1.0.0" */
|
|
356
|
-
import { useState } from '@mindmatrix/react';
|
|
357
|
-
|
|
358
|
-
export default function Empty() {
|
|
359
|
-
const [x] = useState(0);
|
|
360
|
-
return <Stack><Text>Empty</Text></Stack>;
|
|
361
|
-
}`;
|
|
362
|
-
|
|
363
|
-
const ir = compile(code);
|
|
364
|
-
// Even a minimal workflow should compile
|
|
365
|
-
if (ir) {
|
|
366
|
-
const validation = validateDefinition(ir);
|
|
367
|
-
// May have warnings about missing transitions but should still be structurally valid
|
|
368
|
-
expect(validation.issues.filter(i => i.severity === 'error').length).toBeLessThanOrEqual(1);
|
|
369
|
-
}
|
|
370
|
-
});
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
// =============================================================================
|
|
374
|
-
// NRT Type Compatibility
|
|
375
|
-
// =============================================================================
|
|
376
|
-
|
|
377
|
-
describe('NRT Type Compatibility', () => {
|
|
378
|
-
it('should create valid NRT structure from compiled experience tree', () => {
|
|
379
|
-
const code = `
|
|
380
|
-
/** @workflow slug="nrt-compat" version="1.0.0" */
|
|
381
|
-
import { useState, useTransition } from '@mindmatrix/react';
|
|
382
|
-
|
|
383
|
-
export default function NRTCompat() {
|
|
384
|
-
const [name, setName] = useState('world');
|
|
385
|
-
useTransition('greet');
|
|
386
|
-
|
|
387
|
-
return (
|
|
388
|
-
<Stack>
|
|
389
|
-
<Heading>Hello {name}</Heading>
|
|
390
|
-
<Button onPress={() => {}}>Greet</Button>
|
|
391
|
-
</Stack>
|
|
392
|
-
);
|
|
393
|
-
}`;
|
|
394
|
-
|
|
395
|
-
const ir = compile(code);
|
|
396
|
-
expect(ir).not.toBeNull();
|
|
397
|
-
|
|
398
|
-
const experience = ir!.metadata?.experience as any;
|
|
399
|
-
expect(experience).toBeDefined();
|
|
400
|
-
|
|
401
|
-
// Experience tree should have the right shape for NRT export
|
|
402
|
-
expect(experience.id).toBeDefined();
|
|
403
|
-
expect(experience.component).toBe('Stack');
|
|
404
|
-
expect(experience.children).toBeDefined();
|
|
405
|
-
expect(experience.children.length).toBeGreaterThan(0);
|
|
406
|
-
|
|
407
|
-
// Each child should have an id and component
|
|
408
|
-
for (const child of experience.children) {
|
|
409
|
-
expect(child.id).toBeDefined();
|
|
410
|
-
expect(child.component).toBeDefined();
|
|
411
|
-
}
|
|
412
|
-
});
|
|
413
|
-
});
|