@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.
- package/ATOM-PIPELINE.md +144 -0
- package/README.md +88 -40
- package/dist/babel/index.js +2814 -277
- 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-52XHYD2V.mjs +214 -0
- package/dist/chunk-5GUFFFGL.mjs +148 -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-EO6SYNCG.mjs +175 -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-J7JUAHS4.mjs +186 -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-NTB7OEX2.mjs +2918 -0
- package/dist/chunk-NW6555WJ.mjs +186 -0
- package/dist/chunk-OMZE6VLQ.mjs +214 -0
- package/dist/chunk-OPJKP747.mjs +7506 -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-THFYE5ZX.mjs +244 -0
- package/dist/chunk-VCAY2KGM.mjs +175 -0
- package/dist/chunk-WBYMW4NQ.mjs +3450 -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 +13189 -6838
- package/dist/cli/index.mjs +140 -22
- package/dist/codemod/cli.mjs +1 -1
- package/dist/codemod/index.mjs +1 -1
- package/dist/config-PL24KEWL.mjs +219 -0
- 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 +4135 -440
- package/dist/dev-server.mjs +5 -5
- package/dist/envelope.js +2812 -275
- package/dist/envelope.mjs +3 -3
- package/dist/index.d.mts +161 -2
- package/dist/index.d.ts +161 -2
- package/dist/index.js +4429 -428
- package/dist/index.mjs +217 -9
- package/{src/cli/init.ts → dist/init-7JQMAAXS.mjs} +70 -95
- package/dist/init-DQDX3QK6.mjs +369 -0
- 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-OP2VVGJQ.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-US7GAVIC.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/pull-P44LDRWB.mjs +109 -0
- package/dist/testing/index.js +2822 -285
- package/dist/testing/index.mjs +2 -2
- package/dist/verify-SEIXUGN4.mjs +1833 -0
- package/dist/vite/index.js +2815 -278
- package/dist/vite/index.mjs +3 -3
- package/examples/uber-app/app/admin/fleet.tsx +19 -19
- package/package.json +16 -6
- 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,303 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Router Extractor — derives a router workflow from file-based routing structure.
|
|
3
|
-
*
|
|
4
|
-
* Converts a set of page file paths into an IRWorkflowDefinition where:
|
|
5
|
-
* - Each page → a state
|
|
6
|
-
* - navigation calls → transitions
|
|
7
|
-
* - layout files → context boundaries
|
|
8
|
-
* - [param] segments → parameterized states
|
|
9
|
-
*
|
|
10
|
-
* INPUT (file paths):
|
|
11
|
-
* app/page.tsx → state HOME (START)
|
|
12
|
-
* app/chat/page.tsx → state CHAT
|
|
13
|
-
* app/chat/[channelId]/page.tsx → state CHAT_CHANNEL
|
|
14
|
-
* app/settings/page.tsx → state SETTINGS
|
|
15
|
-
*
|
|
16
|
-
* OUTPUT:
|
|
17
|
-
* IRWorkflowDefinition with states, transitions, and route metadata
|
|
18
|
-
*
|
|
19
|
-
* This is a standalone utility — it doesn't run as part of the Babel visitor.
|
|
20
|
-
* Instead, it's called by the build pipeline with a list of discovered files.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import type {
|
|
24
|
-
IRWorkflowDefinition,
|
|
25
|
-
IRStateDefinition,
|
|
26
|
-
IRTransitionDefinition,
|
|
27
|
-
IRFieldDefinition,
|
|
28
|
-
} from '@mindmatrix/player-core';
|
|
29
|
-
|
|
30
|
-
// =============================================================================
|
|
31
|
-
// Types
|
|
32
|
-
// =============================================================================
|
|
33
|
-
|
|
34
|
-
export interface PageFile {
|
|
35
|
-
/** Relative path from app root (e.g., 'chat/[channelId]/page.tsx') */
|
|
36
|
-
relativePath: string;
|
|
37
|
-
/** Absolute file path */
|
|
38
|
-
absolutePath: string;
|
|
39
|
-
/** Exported component name (if detectable) */
|
|
40
|
-
componentName?: string;
|
|
41
|
-
/** Whether this is a layout file */
|
|
42
|
-
isLayout?: boolean;
|
|
43
|
-
/** Navigation targets found in the file (paths navigated to) */
|
|
44
|
-
navigationTargets?: string[];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export interface RouteState {
|
|
48
|
-
/** State name (e.g., 'CHAT_CHANNEL') */
|
|
49
|
-
name: string;
|
|
50
|
-
/** Route path (e.g., '/chat/:channelId') */
|
|
51
|
-
path: string;
|
|
52
|
-
/** Dynamic parameters (e.g., ['channelId']) */
|
|
53
|
-
params: string[];
|
|
54
|
-
/** Layout boundary this route belongs to */
|
|
55
|
-
layoutBoundary?: string;
|
|
56
|
-
/** Source page file */
|
|
57
|
-
sourceFile: string;
|
|
58
|
-
/** State type */
|
|
59
|
-
type: 'START' | 'REGULAR';
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export interface RouterExtractionOptions {
|
|
63
|
-
/** Blueprint slug for the router workflow */
|
|
64
|
-
slug?: string;
|
|
65
|
-
/** Root directory name (defaults to 'app') */
|
|
66
|
-
rootDir?: string;
|
|
67
|
-
/** Page file naming convention */
|
|
68
|
-
pageFileName?: string;
|
|
69
|
-
/** Layout file naming convention */
|
|
70
|
-
layoutFileName?: string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// =============================================================================
|
|
74
|
-
// Path → State Name conversion
|
|
75
|
-
// =============================================================================
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Converts a route path to a state name.
|
|
79
|
-
* 'chat/[channelId]' → 'CHAT_CHANNEL'
|
|
80
|
-
* '' (root) → 'HOME'
|
|
81
|
-
*/
|
|
82
|
-
export function pathToStateName(routePath: string): string {
|
|
83
|
-
if (!routePath || routePath === '' || routePath === '/') return 'HOME';
|
|
84
|
-
|
|
85
|
-
return routePath
|
|
86
|
-
.split('/')
|
|
87
|
-
.filter(Boolean)
|
|
88
|
-
.map((segment) => {
|
|
89
|
-
// [param] → strip brackets
|
|
90
|
-
if (segment.startsWith('[') && segment.endsWith(']')) {
|
|
91
|
-
return segment.slice(1, -1);
|
|
92
|
-
}
|
|
93
|
-
return segment;
|
|
94
|
-
})
|
|
95
|
-
.join('_')
|
|
96
|
-
.replace(/([a-z])([A-Z])/g, '$1_$2')
|
|
97
|
-
.toUpperCase()
|
|
98
|
-
.replace(/-/g, '_');
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Converts a route path to a URL pattern.
|
|
103
|
-
* 'chat/[channelId]/page.tsx' → '/chat/:channelId'
|
|
104
|
-
*/
|
|
105
|
-
export function pathToUrlPattern(relativePath: string, pageFileName = 'page.tsx'): string {
|
|
106
|
-
// Remove page filename
|
|
107
|
-
let routePath = relativePath.replace(new RegExp(`/?${pageFileName.replace('.', '\\.')}$`), '');
|
|
108
|
-
|
|
109
|
-
// Convert [param] to :param
|
|
110
|
-
routePath = routePath.replace(/\[([^\]]+)\]/g, ':$1');
|
|
111
|
-
|
|
112
|
-
// Ensure leading slash
|
|
113
|
-
return '/' + routePath;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Extracts dynamic parameters from a route path.
|
|
118
|
-
* 'chat/[channelId]/page.tsx' → ['channelId']
|
|
119
|
-
*/
|
|
120
|
-
export function extractParams(relativePath: string): string[] {
|
|
121
|
-
const params: string[] = [];
|
|
122
|
-
const paramRegex = /\[([^\]]+)\]/g;
|
|
123
|
-
let match: RegExpExecArray | null;
|
|
124
|
-
while ((match = paramRegex.exec(relativePath)) !== null) {
|
|
125
|
-
params.push(match[1]);
|
|
126
|
-
}
|
|
127
|
-
return params;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// =============================================================================
|
|
131
|
-
// Main extraction
|
|
132
|
-
// =============================================================================
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Extracts a router workflow from a set of page files.
|
|
136
|
-
*/
|
|
137
|
-
export function extractRouterWorkflow(
|
|
138
|
-
pages: PageFile[],
|
|
139
|
-
options: RouterExtractionOptions = {}
|
|
140
|
-
): IRWorkflowDefinition {
|
|
141
|
-
const {
|
|
142
|
-
slug = 'app-router',
|
|
143
|
-
pageFileName = 'page.tsx',
|
|
144
|
-
layoutFileName = 'layout.tsx',
|
|
145
|
-
} = options;
|
|
146
|
-
|
|
147
|
-
// Separate page files from layout files
|
|
148
|
-
const pageFiles = pages.filter((p) => !p.isLayout && p.relativePath.endsWith(pageFileName));
|
|
149
|
-
const layoutFiles = pages.filter((p) => p.isLayout || p.relativePath.endsWith(layoutFileName));
|
|
150
|
-
|
|
151
|
-
// Build route states
|
|
152
|
-
const routeStates: RouteState[] = [];
|
|
153
|
-
const stateMap = new Map<string, RouteState>();
|
|
154
|
-
|
|
155
|
-
for (const page of pageFiles) {
|
|
156
|
-
const routePath = page.relativePath.replace(new RegExp(`/?${pageFileName.replace('.', '\\.')}$`), '');
|
|
157
|
-
const stateName = pathToStateName(routePath);
|
|
158
|
-
const urlPattern = pathToUrlPattern(page.relativePath, pageFileName);
|
|
159
|
-
const params = extractParams(page.relativePath);
|
|
160
|
-
|
|
161
|
-
// Find layout boundary
|
|
162
|
-
const layoutBoundary = findLayoutBoundary(page.relativePath, layoutFiles);
|
|
163
|
-
|
|
164
|
-
const routeState: RouteState = {
|
|
165
|
-
name: stateName,
|
|
166
|
-
path: urlPattern,
|
|
167
|
-
params,
|
|
168
|
-
layoutBoundary,
|
|
169
|
-
sourceFile: page.relativePath,
|
|
170
|
-
type: stateName === 'HOME' ? 'START' : 'REGULAR',
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
routeStates.push(routeState);
|
|
174
|
-
stateMap.set(stateName, routeState);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Ensure HOME exists
|
|
178
|
-
if (!stateMap.has('HOME') && routeStates.length > 0) {
|
|
179
|
-
routeStates[0].type = 'START';
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Build IR states
|
|
183
|
-
const states: IRStateDefinition[] = routeStates.map((rs) => ({
|
|
184
|
-
name: rs.name,
|
|
185
|
-
type: rs.type,
|
|
186
|
-
description: `Route: ${rs.path}`,
|
|
187
|
-
on_enter: [],
|
|
188
|
-
during: [],
|
|
189
|
-
on_exit: [],
|
|
190
|
-
}));
|
|
191
|
-
|
|
192
|
-
// Build transitions from navigation targets
|
|
193
|
-
const transitions: IRTransitionDefinition[] = [];
|
|
194
|
-
let transitionId = 0;
|
|
195
|
-
|
|
196
|
-
for (const page of pageFiles) {
|
|
197
|
-
if (!page.navigationTargets) continue;
|
|
198
|
-
const fromPath = page.relativePath.replace(new RegExp(`/?${pageFileName.replace('.', '\\.')}$`), '');
|
|
199
|
-
const fromState = pathToStateName(fromPath);
|
|
200
|
-
|
|
201
|
-
for (const target of page.navigationTargets) {
|
|
202
|
-
// Convert target path to state name
|
|
203
|
-
const targetPath = target.replace(/^\//, '').replace(/\/page\.(tsx|ts|jsx|js)$/, '');
|
|
204
|
-
const toState = pathToStateName(targetPath);
|
|
205
|
-
|
|
206
|
-
// Only create transition if target state exists
|
|
207
|
-
if (stateMap.has(toState) || toState === fromState) continue;
|
|
208
|
-
|
|
209
|
-
// Create navigate transition
|
|
210
|
-
const transitionName = `navigate_to_${toState.toLowerCase()}`;
|
|
211
|
-
transitions.push({
|
|
212
|
-
name: transitionName,
|
|
213
|
-
from: [fromState],
|
|
214
|
-
to: toState,
|
|
215
|
-
actions: [],
|
|
216
|
-
conditions: [],
|
|
217
|
-
});
|
|
218
|
-
transitionId++;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Add universal back/navigate transitions
|
|
223
|
-
if (routeStates.length > 1) {
|
|
224
|
-
// Add a generic navigate_home transition from all non-home states
|
|
225
|
-
for (const rs of routeStates) {
|
|
226
|
-
if (rs.type !== 'START') {
|
|
227
|
-
transitions.push({
|
|
228
|
-
name: `navigate_home_from_${rs.name.toLowerCase()}`,
|
|
229
|
-
from: [rs.name],
|
|
230
|
-
to: 'HOME',
|
|
231
|
-
actions: [],
|
|
232
|
-
conditions: [],
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// Build fields for route parameters
|
|
239
|
-
const fields: IRFieldDefinition[] = [];
|
|
240
|
-
const seenParams = new Set<string>();
|
|
241
|
-
|
|
242
|
-
for (const rs of routeStates) {
|
|
243
|
-
for (const param of rs.params) {
|
|
244
|
-
if (seenParams.has(param)) continue;
|
|
245
|
-
seenParams.add(param);
|
|
246
|
-
fields.push({
|
|
247
|
-
name: param,
|
|
248
|
-
type: 'text',
|
|
249
|
-
required: false,
|
|
250
|
-
default_value: '',
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// Build route metadata
|
|
256
|
-
const routeMetadata = routeStates.map((rs) => ({
|
|
257
|
-
state: rs.name,
|
|
258
|
-
path: rs.path,
|
|
259
|
-
params: rs.params,
|
|
260
|
-
layoutBoundary: rs.layoutBoundary,
|
|
261
|
-
sourceFile: rs.sourceFile,
|
|
262
|
-
}));
|
|
263
|
-
|
|
264
|
-
return {
|
|
265
|
-
slug,
|
|
266
|
-
name: 'Router',
|
|
267
|
-
version: '1.0.0',
|
|
268
|
-
description: 'Auto-derived router workflow from file-based routing',
|
|
269
|
-
category: 'router',
|
|
270
|
-
fields,
|
|
271
|
-
states,
|
|
272
|
-
transitions,
|
|
273
|
-
roles: [],
|
|
274
|
-
tags: [{ tag_name: 'auto-derived' }, { tag_name: 'router' }],
|
|
275
|
-
metadata: {
|
|
276
|
-
runtime: 'local',
|
|
277
|
-
routes: routeMetadata,
|
|
278
|
-
layoutBoundaries: layoutFiles.map((l) => l.relativePath),
|
|
279
|
-
},
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Finds the nearest layout boundary for a page file.
|
|
285
|
-
*/
|
|
286
|
-
function findLayoutBoundary(
|
|
287
|
-
pageRelativePath: string,
|
|
288
|
-
layoutFiles: PageFile[]
|
|
289
|
-
): string | undefined {
|
|
290
|
-
const layoutPaths = layoutFiles.map((l) => l.relativePath);
|
|
291
|
-
|
|
292
|
-
// Walk up the directory tree to find nearest layout
|
|
293
|
-
const parts = pageRelativePath.split('/');
|
|
294
|
-
for (let i = parts.length - 1; i >= 0; i--) {
|
|
295
|
-
const dir = parts.slice(0, i).join('/');
|
|
296
|
-
const layoutPath = dir ? `${dir}/layout.tsx` : 'layout.tsx';
|
|
297
|
-
if (layoutPaths.includes(layoutPath)) {
|
|
298
|
-
return layoutPath;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
return undefined;
|
|
303
|
-
}
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Server Action Extractor — extracts exported functions from *.server.ts files.
|
|
3
|
-
*
|
|
4
|
-
* Server action files define backend-side handlers that are referenced in
|
|
5
|
-
* model hooks and transition actions.
|
|
6
|
-
*
|
|
7
|
-
* INPUT (actions.server.ts):
|
|
8
|
-
* export async function notifyMembers(ctx: TransitionContext) {
|
|
9
|
-
* const members = await ctx.refs('member', { channel_id: ctx.env.instance_id });
|
|
10
|
-
* for (const m of members) {
|
|
11
|
-
* await ctx.emit('notification:send', { user_id: m.stateData.user_id });
|
|
12
|
-
* }
|
|
13
|
-
* }
|
|
14
|
-
*
|
|
15
|
-
* export function logDeactivation(ctx: TransitionContext) {
|
|
16
|
-
* ctx.log('Channel deactivated', { channel_id: ctx.env.instance_id });
|
|
17
|
-
* }
|
|
18
|
-
*
|
|
19
|
-
* OUTPUT (stored in compilerState metadata.serverActions[]):
|
|
20
|
-
* [
|
|
21
|
-
* { name: 'notifyMembers', async: true, params: ['ctx'] },
|
|
22
|
-
* { name: 'logDeactivation', async: false, params: ['ctx'] },
|
|
23
|
-
* ]
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
import type { NodePath } from '@babel/traverse';
|
|
27
|
-
import * as t from '@babel/types';
|
|
28
|
-
import type { CompilerState } from '../../types';
|
|
29
|
-
|
|
30
|
-
// =============================================================================
|
|
31
|
-
// Types
|
|
32
|
-
// =============================================================================
|
|
33
|
-
|
|
34
|
-
export interface ServerAction {
|
|
35
|
-
/** Function name. */
|
|
36
|
-
name: string;
|
|
37
|
-
/** Whether the function is async. */
|
|
38
|
-
async: boolean;
|
|
39
|
-
/** Parameter names. */
|
|
40
|
-
params: string[];
|
|
41
|
-
/** TypeScript type of first parameter (if any). */
|
|
42
|
-
contextType?: string;
|
|
43
|
-
/** Description from JSDoc (if any). */
|
|
44
|
-
description?: string;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// =============================================================================
|
|
48
|
-
// Detection
|
|
49
|
-
// =============================================================================
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Checks if a file is a server action file.
|
|
53
|
-
* Convention: filename ends with .server.ts or .server.tsx
|
|
54
|
-
*/
|
|
55
|
-
export function isServerActionFile(filename: string | undefined): boolean {
|
|
56
|
-
if (!filename) return false;
|
|
57
|
-
return /\.server\.(ts|tsx|js|jsx)$/.test(filename);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// =============================================================================
|
|
61
|
-
// Extraction
|
|
62
|
-
// =============================================================================
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Extracts all exported functions from a server action file.
|
|
66
|
-
*/
|
|
67
|
-
export function extractServerActions(path: NodePath<t.Program>, state: any): void {
|
|
68
|
-
const compilerState = state as CompilerState;
|
|
69
|
-
const serverActions: ServerAction[] = [];
|
|
70
|
-
|
|
71
|
-
for (const node of path.node.body) {
|
|
72
|
-
// export function name(ctx) { ... }
|
|
73
|
-
if (t.isExportNamedDeclaration(node)) {
|
|
74
|
-
const decl = node.declaration;
|
|
75
|
-
|
|
76
|
-
if (t.isFunctionDeclaration(decl) && decl.id) {
|
|
77
|
-
const action = extractFunctionAction(decl);
|
|
78
|
-
if (action) {
|
|
79
|
-
// Extract description from leading comments
|
|
80
|
-
const comments = node.leadingComments || decl.leadingComments || [];
|
|
81
|
-
action.description = extractDescription(comments);
|
|
82
|
-
serverActions.push(action);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// export const name = async (ctx) => { ... }
|
|
87
|
-
if (t.isVariableDeclaration(decl)) {
|
|
88
|
-
for (const varDecl of decl.declarations) {
|
|
89
|
-
if (!t.isIdentifier(varDecl.id)) continue;
|
|
90
|
-
const init = varDecl.init;
|
|
91
|
-
if (t.isArrowFunctionExpression(init) || t.isFunctionExpression(init)) {
|
|
92
|
-
const action: ServerAction = {
|
|
93
|
-
name: varDecl.id.name,
|
|
94
|
-
async: init.async || false,
|
|
95
|
-
params: init.params
|
|
96
|
-
.filter((p): p is t.Identifier => t.isIdentifier(p))
|
|
97
|
-
.map((p) => p.name),
|
|
98
|
-
};
|
|
99
|
-
// Extract context type from first param
|
|
100
|
-
if (init.params.length > 0) {
|
|
101
|
-
const firstParam = init.params[0];
|
|
102
|
-
if (t.isIdentifier(firstParam) && firstParam.typeAnnotation) {
|
|
103
|
-
action.contextType = extractTypeName(firstParam.typeAnnotation);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
serverActions.push(action);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Store in compiler state metadata
|
|
114
|
-
if (serverActions.length > 0) {
|
|
115
|
-
if (!compilerState.metadata) compilerState.metadata = {};
|
|
116
|
-
(compilerState.metadata as Record<string, unknown>).serverActions = serverActions;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Extracts a ServerAction from a FunctionDeclaration.
|
|
122
|
-
*/
|
|
123
|
-
function extractFunctionAction(decl: t.FunctionDeclaration): ServerAction | null {
|
|
124
|
-
if (!decl.id) return null;
|
|
125
|
-
|
|
126
|
-
const action: ServerAction = {
|
|
127
|
-
name: decl.id.name,
|
|
128
|
-
async: decl.async || false,
|
|
129
|
-
params: decl.params
|
|
130
|
-
.filter((p): p is t.Identifier => t.isIdentifier(p))
|
|
131
|
-
.map((p) => p.name),
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
// Extract context type from first param
|
|
135
|
-
if (decl.params.length > 0) {
|
|
136
|
-
const firstParam = decl.params[0];
|
|
137
|
-
if (t.isIdentifier(firstParam) && firstParam.typeAnnotation) {
|
|
138
|
-
action.contextType = extractTypeName(firstParam.typeAnnotation);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return action;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Extracts a type name from a type annotation.
|
|
147
|
-
*/
|
|
148
|
-
function extractTypeName(annotation: t.TypeAnnotation | t.TSTypeAnnotation | t.Noop): string | undefined {
|
|
149
|
-
if (t.isTSTypeAnnotation(annotation)) {
|
|
150
|
-
const typeNode = annotation.typeAnnotation;
|
|
151
|
-
if (t.isTSTypeReference(typeNode) && t.isIdentifier(typeNode.typeName)) {
|
|
152
|
-
return typeNode.typeName.name;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
return undefined;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Extracts a description from JSDoc comments.
|
|
160
|
-
*/
|
|
161
|
-
function extractDescription(comments: readonly t.Comment[]): string | undefined {
|
|
162
|
-
for (const comment of comments) {
|
|
163
|
-
if (comment.type !== 'CommentBlock') continue;
|
|
164
|
-
const lines = comment.value.split('\n');
|
|
165
|
-
for (const line of lines) {
|
|
166
|
-
const trimmed = line.replace(/^\s*\*\s?/, '').trim();
|
|
167
|
-
if (trimmed && !trimmed.startsWith('@')) {
|
|
168
|
-
return trimmed;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return undefined;
|
|
173
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Server Action Hook Extractor — extracts useServerAction() calls from .workflow.tsx.
|
|
3
|
-
*
|
|
4
|
-
* INPUT:
|
|
5
|
-
* const approve = useServerAction('approve-order', { instanceId: orderId });
|
|
6
|
-
*
|
|
7
|
-
* OUTPUT (stored in compilerState metadata.serverActionHooks[]):
|
|
8
|
-
* [{ name: 'approve-order', variableName: 'approve' }]
|
|
9
|
-
*
|
|
10
|
-
* The extracted info tells the runtime that this workflow depends on a
|
|
11
|
-
* server-side action endpoint and needs the action to be available at
|
|
12
|
-
* POST /api/v1/workflow/instances/{id}/actions/{name}.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import type { NodePath } from '@babel/traverse';
|
|
16
|
-
import * as t from '@babel/types';
|
|
17
|
-
import type { CompilerState } from '../../types';
|
|
18
|
-
|
|
19
|
-
// =============================================================================
|
|
20
|
-
// Types
|
|
21
|
-
// =============================================================================
|
|
22
|
-
|
|
23
|
-
export interface ServerActionHookEntry {
|
|
24
|
-
/** The action name (first argument to useServerAction). */
|
|
25
|
-
name: string;
|
|
26
|
-
/** The variable name the hook result is assigned to. */
|
|
27
|
-
variableName?: string;
|
|
28
|
-
/** Static instance ID if provided as a string literal. */
|
|
29
|
-
staticInstanceId?: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// =============================================================================
|
|
33
|
-
// Extraction
|
|
34
|
-
// =============================================================================
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Extracts useServerAction('name', { instanceId }) calls into metadata.
|
|
38
|
-
*/
|
|
39
|
-
export function extractServerActionHook(path: NodePath<t.CallExpression>, state: any): void {
|
|
40
|
-
const args = path.node.arguments;
|
|
41
|
-
if (args.length < 1) return;
|
|
42
|
-
|
|
43
|
-
const nameArg = args[0];
|
|
44
|
-
if (!t.isStringLiteral(nameArg)) return;
|
|
45
|
-
|
|
46
|
-
const compilerState = state as CompilerState;
|
|
47
|
-
const entry: ServerActionHookEntry = {
|
|
48
|
-
name: nameArg.value,
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
// Extract static instanceId if provided as string literal in options
|
|
52
|
-
if (args.length > 1 && t.isObjectExpression(args[1])) {
|
|
53
|
-
for (const prop of args[1].properties) {
|
|
54
|
-
if (!t.isObjectProperty(prop) || !t.isIdentifier(prop.key)) continue;
|
|
55
|
-
if (prop.key.name === 'instanceId' && t.isStringLiteral(prop.value)) {
|
|
56
|
-
entry.staticInstanceId = prop.value.value;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Try to get the variable name from the parent VariableDeclarator
|
|
62
|
-
const parent = path.parentPath;
|
|
63
|
-
if (parent?.isVariableDeclarator() && t.isIdentifier(parent.node.id)) {
|
|
64
|
-
entry.variableName = parent.node.id.name;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Store in compiler state metadata
|
|
68
|
-
if (!compilerState.metadata) compilerState.metadata = {};
|
|
69
|
-
const meta = compilerState.metadata as Record<string, unknown>;
|
|
70
|
-
if (!meta.serverActionHooks) meta.serverActionHooks = [];
|
|
71
|
-
(meta.serverActionHooks as ServerActionHookEntry[]).push(entry);
|
|
72
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Server State Extractor — extracts useServerState() calls from .workflow.tsx.
|
|
3
|
-
*
|
|
4
|
-
* INPUT:
|
|
5
|
-
* const { state, stateData, loading } = useServerState(instanceId);
|
|
6
|
-
* const order = useServerState('static-id', { onStateChange: handleChange });
|
|
7
|
-
*
|
|
8
|
-
* OUTPUT (stored in compilerState metadata.serverStateSubscriptions[]):
|
|
9
|
-
* [{ variableName: undefined, staticInstanceId: undefined }]
|
|
10
|
-
* [{ variableName: 'order', staticInstanceId: 'static-id' }]
|
|
11
|
-
*
|
|
12
|
-
* The extracted info tells the runtime that this workflow subscribes to
|
|
13
|
-
* real-time server state via SSE at /api/v1/workflow/events.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import type { NodePath } from '@babel/traverse';
|
|
17
|
-
import * as t from '@babel/types';
|
|
18
|
-
import type { CompilerState } from '../../types';
|
|
19
|
-
|
|
20
|
-
// =============================================================================
|
|
21
|
-
// Types
|
|
22
|
-
// =============================================================================
|
|
23
|
-
|
|
24
|
-
export interface ServerStateEntry {
|
|
25
|
-
/** The variable name the hook result is assigned to. */
|
|
26
|
-
variableName?: string;
|
|
27
|
-
/** Static instance ID if provided as a string literal. */
|
|
28
|
-
staticInstanceId?: string;
|
|
29
|
-
/** Whether the enabled option is explicitly set to false. */
|
|
30
|
-
disabled?: boolean;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// =============================================================================
|
|
34
|
-
// Extraction
|
|
35
|
-
// =============================================================================
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Extracts useServerState(instanceId, options?) calls into metadata.
|
|
39
|
-
*/
|
|
40
|
-
export function extractServerState(path: NodePath<t.CallExpression>, state: any): void {
|
|
41
|
-
const args = path.node.arguments;
|
|
42
|
-
if (args.length < 1) return;
|
|
43
|
-
|
|
44
|
-
const compilerState = state as CompilerState;
|
|
45
|
-
const entry: ServerStateEntry = {};
|
|
46
|
-
|
|
47
|
-
// First arg: instance ID (could be string literal or variable)
|
|
48
|
-
const instanceArg = args[0];
|
|
49
|
-
if (t.isStringLiteral(instanceArg)) {
|
|
50
|
-
entry.staticInstanceId = instanceArg.value;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Second arg: options object
|
|
54
|
-
if (args.length > 1 && t.isObjectExpression(args[1])) {
|
|
55
|
-
for (const prop of args[1].properties) {
|
|
56
|
-
if (!t.isObjectProperty(prop) || !t.isIdentifier(prop.key)) continue;
|
|
57
|
-
if (prop.key.name === 'enabled' && t.isBooleanLiteral(prop.value)) {
|
|
58
|
-
if (!prop.value.value) entry.disabled = true;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Try to get the variable name from the parent VariableDeclarator
|
|
64
|
-
const parent = path.parentPath;
|
|
65
|
-
if (parent?.isVariableDeclarator()) {
|
|
66
|
-
if (t.isIdentifier(parent.node.id)) {
|
|
67
|
-
entry.variableName = parent.node.id.name;
|
|
68
|
-
} else if (t.isObjectPattern(parent.node.id)) {
|
|
69
|
-
// Destructured: const { state, stateData } = useServerState(...)
|
|
70
|
-
// Record the property names for documentation, use first as variableName
|
|
71
|
-
const props = parent.node.id.properties
|
|
72
|
-
.filter((p): p is t.ObjectProperty => t.isObjectProperty(p) && t.isIdentifier(p.key))
|
|
73
|
-
.map((p) => (p.key as t.Identifier).name);
|
|
74
|
-
if (props.length > 0) {
|
|
75
|
-
entry.variableName = props.join(', ');
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Store in compiler state metadata
|
|
81
|
-
if (!compilerState.metadata) compilerState.metadata = {};
|
|
82
|
-
const meta = compilerState.metadata as Record<string, unknown>;
|
|
83
|
-
if (!meta.serverStateSubscriptions) meta.serverStateSubscriptions = [];
|
|
84
|
-
(meta.serverStateSubscriptions as ServerStateEntry[]).push(entry);
|
|
85
|
-
|
|
86
|
-
// Also flag that this workflow requires SSE connectivity
|
|
87
|
-
meta.requiresSSE = true;
|
|
88
|
-
}
|