@zenithbuild/cli 0.6.17 → 0.7.0

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 (64) hide show
  1. package/dist/build/compiler-runtime.d.ts +59 -0
  2. package/dist/build/compiler-runtime.js +277 -0
  3. package/dist/build/expression-rewrites.d.ts +88 -0
  4. package/dist/build/expression-rewrites.js +372 -0
  5. package/dist/build/hoisted-code-transforms.d.ts +44 -0
  6. package/dist/build/hoisted-code-transforms.js +316 -0
  7. package/dist/build/merge-component-ir.d.ts +16 -0
  8. package/dist/build/merge-component-ir.js +257 -0
  9. package/dist/build/page-component-loop.d.ts +92 -0
  10. package/dist/build/page-component-loop.js +257 -0
  11. package/dist/build/page-ir-normalization.d.ts +23 -0
  12. package/dist/build/page-ir-normalization.js +370 -0
  13. package/dist/build/page-loop-metrics.d.ts +100 -0
  14. package/dist/build/page-loop-metrics.js +131 -0
  15. package/dist/build/page-loop-state.d.ts +261 -0
  16. package/dist/build/page-loop-state.js +92 -0
  17. package/dist/build/page-loop.d.ts +33 -0
  18. package/dist/build/page-loop.js +217 -0
  19. package/dist/build/scoped-identifier-rewrite.d.ts +112 -0
  20. package/dist/build/scoped-identifier-rewrite.js +245 -0
  21. package/dist/build/server-script.d.ts +41 -0
  22. package/dist/build/server-script.js +210 -0
  23. package/dist/build/type-declarations.d.ts +16 -0
  24. package/dist/build/type-declarations.js +158 -0
  25. package/dist/build/typescript-expression-utils.d.ts +23 -0
  26. package/dist/build/typescript-expression-utils.js +272 -0
  27. package/dist/build.d.ts +10 -18
  28. package/dist/build.js +74 -2261
  29. package/dist/component-instance-ir.d.ts +2 -2
  30. package/dist/component-instance-ir.js +146 -39
  31. package/dist/component-occurrences.js +63 -15
  32. package/dist/config.d.ts +66 -0
  33. package/dist/config.js +86 -0
  34. package/dist/debug-script.d.ts +1 -0
  35. package/dist/debug-script.js +8 -0
  36. package/dist/dev-build-session.d.ts +23 -0
  37. package/dist/dev-build-session.js +421 -0
  38. package/dist/dev-server.js +256 -54
  39. package/dist/framework-components/Image.zen +316 -0
  40. package/dist/images/materialize.d.ts +17 -0
  41. package/dist/images/materialize.js +200 -0
  42. package/dist/images/payload.d.ts +18 -0
  43. package/dist/images/payload.js +65 -0
  44. package/dist/images/runtime.d.ts +4 -0
  45. package/dist/images/runtime.js +254 -0
  46. package/dist/images/service.d.ts +4 -0
  47. package/dist/images/service.js +302 -0
  48. package/dist/images/shared.d.ts +58 -0
  49. package/dist/images/shared.js +306 -0
  50. package/dist/index.js +2 -17
  51. package/dist/manifest.js +45 -0
  52. package/dist/preview.d.ts +4 -1
  53. package/dist/preview.js +59 -6
  54. package/dist/resolve-components.js +20 -3
  55. package/dist/server-contract.js +3 -2
  56. package/dist/server-script-composition.d.ts +39 -0
  57. package/dist/server-script-composition.js +133 -0
  58. package/dist/startup-profile.d.ts +10 -0
  59. package/dist/startup-profile.js +62 -0
  60. package/dist/toolchain-paths.d.ts +1 -0
  61. package/dist/toolchain-paths.js +31 -0
  62. package/dist/version-check.d.ts +2 -1
  63. package/dist/version-check.js +12 -5
  64. package/package.json +5 -4
@@ -0,0 +1,217 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { performance } from 'node:perf_hooks';
4
+ import { applyOccurrenceRewritePlans } from '../component-instance-ir.js';
5
+ import { collectExpandedComponentOccurrences } from '../component-occurrences.js';
6
+ import { expandComponents } from '../resolve-components.js';
7
+ import { composeServerScriptEnvelope, resolveAdjacentServerModules } from '../server-script-composition.js';
8
+ import { createTimedCompilerRunner } from './compiler-runtime.js';
9
+ import { buildComponentExpressionRewrite, mergeExpressionRewriteMaps, resolveRewrittenBindingMetadata } from './expression-rewrites.js';
10
+ import { createPageIrMergeCache } from './merge-component-ir.js';
11
+ import { buildPageOwnerContext, runPageComponentLoop } from './page-component-loop.js';
12
+ import { applyExpressionRewrites, applyScopedIdentifierRewrites, normalizeExpressionBindingDependencies, normalizeExpressionPayload, normalizeHoistedSourcePayload, rewriteLegacyMarkupIdentifiers, rewriteRefBindingIdentifiers, synthesizeSignalBackedCompiledExpressions } from './page-ir-normalization.js';
13
+ import { addBreakdown, emitPageLoopSummary, recordPageProfile } from './page-loop-metrics.js';
14
+ import { applyServerEnvelopeToPageIr, buildOccurrenceCountByPath, createPageBuildState, createPageLoopCaches, createPageLoopExecutionState } from './page-loop-state.js';
15
+ import { buildScopedIdentifierRewrite } from './scoped-identifier-rewrite.js';
16
+ import { extractServerScript } from './server-script.js';
17
+ /**
18
+ * @param {{
19
+ * manifest: Array<{ path: string, file: string }>
20
+ * pagesDir: string
21
+ * srcDir: string
22
+ * registry: Map<string, string>
23
+ * compilerOpts: object
24
+ * compilerBin: string|object
25
+ * softNavigationEnabled: boolean
26
+ * startupProfile: ReturnType<import('../startup-profile.js').createStartupProfiler>
27
+ * compilerTotals: Record<string, number>
28
+ * emitCompilerWarning: (line: string) => void
29
+ * }} input
30
+ * @returns {Promise<{ envelopes: object[], expressionRewriteMetrics: Record<string, number> }>}
31
+ */
32
+ export async function buildPageEnvelopes(input) {
33
+ const { manifest, pagesDir, srcDir, registry, compilerOpts, compilerBin, softNavigationEnabled, startupProfile, compilerTotals, emitCompilerWarning } = input;
34
+ const cacheState = input.pageLoopCaches || createPageLoopCaches();
35
+ const executionState = createPageLoopExecutionState();
36
+ const { componentIrCache, componentDocumentModeCache, componentExpressionRewriteCache, templateExpressionCache, hoistedCodeTransformCache } = cacheState;
37
+ const { expressionRewriteMetrics, pagePhaseTotals, occurrenceApplyPhaseTotals, bindingResolutionTotals, scopedRewritePhaseTotals, mergePhaseTotals, componentLoopPhaseTotals, pageProfiles, envelopes } = executionState;
38
+ async function cooperativeYield() {
39
+ await new Promise((resolve) => setImmediate(resolve));
40
+ }
41
+ const timedRunCompiler = createTimedCompilerRunner(startupProfile, compilerTotals);
42
+ const pageLoopStartedAt = performance.now();
43
+ for (const entry of manifest) {
44
+ const pageStartedAt = performance.now();
45
+ let { pagePhase, pageOccurrenceApplyBreakdown, pageBindingResolutionBreakdown, pageScopedRewriteBreakdown, pageMergeBreakdown, pageComponentLoopBreakdown, pageExpandMs, pageCompileMs, pageOwnerCompileMs, pageComponentCompileMs, pageComponentCacheHits, pageComponentCacheMisses } = createPageBuildState();
46
+ await cooperativeYield();
47
+ const sourceFile = join(pagesDir, entry.file);
48
+ const rawSource = readFileSync(sourceFile, 'utf8');
49
+ const occurrenceCollectStartedAt = performance.now();
50
+ const componentOccurrences = collectExpandedComponentOccurrences(rawSource, registry, sourceFile);
51
+ pagePhase.occurrenceCollectMs = startupProfile.roundMs(performance.now() - occurrenceCollectStartedAt);
52
+ const pageOwnerExtractStartedAt = performance.now();
53
+ const pageOwnerSource = extractServerScript(rawSource, sourceFile, compilerOpts).source;
54
+ pagePhase.serverExtractMs += startupProfile.roundMs(performance.now() - pageOwnerExtractStartedAt);
55
+ const { guardPath: adjacentGuard, loadPath: adjacentLoad } = resolveAdjacentServerModules(sourceFile);
56
+ const expandedStartedAt = performance.now();
57
+ const { expandedSource } = expandComponents(rawSource, registry, sourceFile);
58
+ pageExpandMs = startupProfile.roundMs(performance.now() - expandedStartedAt);
59
+ const expandedServerExtractStartedAt = performance.now();
60
+ const extractedServer = extractServerScript(expandedSource, sourceFile, compilerOpts);
61
+ pagePhase.serverExtractMs += startupProfile.roundMs(performance.now() - expandedServerExtractStartedAt);
62
+ const compileSource = extractedServer.source;
63
+ await cooperativeYield();
64
+ const pageCompileStartedAt = performance.now();
65
+ const pageIr = timedRunCompiler('page', sourceFile, compileSource, compilerOpts, { compilerToolchain: compilerBin, onWarning: emitCompilerWarning });
66
+ pageCompileMs = startupProfile.roundMs(performance.now() - pageCompileStartedAt);
67
+ const composedServer = composeServerScriptEnvelope({
68
+ sourceFile,
69
+ inlineServerScript: extractedServer.serverScript,
70
+ adjacentGuardPath: adjacentGuard,
71
+ adjacentLoadPath: adjacentLoad
72
+ });
73
+ const hasGuard = composedServer.serverScript?.has_guard === true;
74
+ const hasLoad = composedServer.serverScript?.has_load === true;
75
+ applyServerEnvelopeToPageIr({
76
+ pageIr,
77
+ composedServer,
78
+ hasGuard,
79
+ hasLoad,
80
+ entry,
81
+ srcDir,
82
+ sourceFile
83
+ });
84
+ const pageIrMergeCache = createPageIrMergeCache(pageIr);
85
+ const seenStaticImports = new Set();
86
+ const occurrenceCountByPath = buildOccurrenceCountByPath(componentOccurrences);
87
+ const pageExpressionRewriteMap = new Map();
88
+ const pageExpressionBindingMap = new Map();
89
+ const pageAmbiguousExpressionMap = new Set();
90
+ const knownRefKeys = new Set();
91
+ const componentOccurrencePlans = [];
92
+ const { pageOwnerCompileMs: resolvedPageOwnerCompileMs, pageOwnerExpressionRewrite, pageOwnerScopeRewrite } = await buildPageOwnerContext({
93
+ componentOccurrences,
94
+ sourceFile,
95
+ pageOwnerSource,
96
+ compilerOpts,
97
+ compilerBin,
98
+ timedRunCompiler,
99
+ cooperativeYield,
100
+ templateExpressionCache,
101
+ expressionRewriteMetrics,
102
+ startupProfile
103
+ });
104
+ pageOwnerCompileMs = resolvedPageOwnerCompileMs;
105
+ const pageSelfRewriteStartedAt = performance.now();
106
+ const pageSelfExpressionRewrite = buildComponentExpressionRewrite(sourceFile, compileSource, pageIr, compilerOpts, compilerBin, templateExpressionCache, expressionRewriteMetrics);
107
+ pagePhase.selfRewriteMs = startupProfile.roundMs(performance.now() - pageSelfRewriteStartedAt);
108
+ mergeExpressionRewriteMaps(pageExpressionRewriteMap, pageExpressionBindingMap, pageAmbiguousExpressionMap, pageSelfExpressionRewrite, pageIrMergeCache, pageBindingResolutionBreakdown);
109
+ const componentLoopStartedAt = performance.now();
110
+ const pageStats = {
111
+ pageComponentCompileMs,
112
+ pageComponentCacheHits,
113
+ pageComponentCacheMisses
114
+ };
115
+ await runPageComponentLoop({
116
+ componentOccurrences,
117
+ occurrenceCountByPath,
118
+ sourceFile,
119
+ registry,
120
+ compilerOpts,
121
+ compilerBin,
122
+ timedRunCompiler,
123
+ cooperativeYield,
124
+ startupProfile,
125
+ compilerTotals,
126
+ emitCompilerWarning,
127
+ componentIrCache,
128
+ componentDocumentModeCache,
129
+ componentExpressionRewriteCache,
130
+ templateExpressionCache,
131
+ expressionRewriteMetrics,
132
+ pageOwnerExpressionRewrite,
133
+ pageOwnerScopeRewrite,
134
+ pageIr,
135
+ pageIrMergeCache,
136
+ seenStaticImports,
137
+ pageExpressionRewriteMap,
138
+ pageExpressionBindingMap,
139
+ pageAmbiguousExpressionMap,
140
+ knownRefKeys,
141
+ componentOccurrencePlans,
142
+ pagePhase,
143
+ pageBindingResolutionBreakdown,
144
+ pageMergeBreakdown,
145
+ pageComponentLoopBreakdown,
146
+ hoistedCodeTransformCache,
147
+ pageStats
148
+ });
149
+ pageComponentCompileMs = pageStats.pageComponentCompileMs;
150
+ pageComponentCacheHits = pageStats.pageComponentCacheHits;
151
+ pageComponentCacheMisses = pageStats.pageComponentCacheMisses;
152
+ pagePhase.componentLoopMs = startupProfile.roundMs(performance.now() - componentLoopStartedAt);
153
+ const occurrencePlanApplyStartedAt = performance.now();
154
+ applyOccurrenceRewritePlans(pageIr, componentOccurrencePlans, (rewrite, binding) => resolveRewrittenBindingMetadata(pageIrMergeCache, rewrite, binding, pageBindingResolutionBreakdown), pageOccurrenceApplyBreakdown);
155
+ pagePhase.occurrencePlanApplyMs = startupProfile.roundMs(performance.now() - occurrencePlanApplyStartedAt);
156
+ const expressionApplyStartedAt = performance.now();
157
+ applyExpressionRewrites(pageIr, pageExpressionRewriteMap, pageExpressionBindingMap, pageAmbiguousExpressionMap);
158
+ pagePhase.expressionApplyMs = startupProfile.roundMs(performance.now() - expressionApplyStartedAt);
159
+ const scopedRewriteStartedAt = performance.now();
160
+ const scopedRewritePlanStartedAt = performance.now();
161
+ const scopedRewritePlan = buildScopedIdentifierRewrite(pageIr);
162
+ pagePhase.scopedRewritePlanMs = startupProfile.roundMs(performance.now() - scopedRewritePlanStartedAt);
163
+ const scopedRewriteApplyStartedAt = performance.now();
164
+ applyScopedIdentifierRewrites(pageIr, scopedRewritePlan, pageScopedRewriteBreakdown);
165
+ pagePhase.scopedRewriteApplyMs = startupProfile.roundMs(performance.now() - scopedRewriteApplyStartedAt);
166
+ pagePhase.scopedRewriteMs = startupProfile.roundMs(performance.now() - scopedRewriteStartedAt);
167
+ const normalizeStartedAt = performance.now();
168
+ synthesizeSignalBackedCompiledExpressions(pageIr);
169
+ normalizeExpressionPayload(pageIr);
170
+ normalizeHoistedSourcePayload(pageIr);
171
+ normalizeExpressionBindingDependencies(pageIr);
172
+ rewriteLegacyMarkupIdentifiers(pageIr);
173
+ rewriteRefBindingIdentifiers(pageIr, knownRefKeys);
174
+ pagePhase.normalizeMs = startupProfile.roundMs(performance.now() - normalizeStartedAt);
175
+ addBreakdown(pagePhaseTotals, pagePhase);
176
+ addBreakdown(occurrenceApplyPhaseTotals, pageOccurrenceApplyBreakdown);
177
+ addBreakdown(bindingResolutionTotals, pageBindingResolutionBreakdown);
178
+ addBreakdown(scopedRewritePhaseTotals, pageScopedRewriteBreakdown);
179
+ addBreakdown(mergePhaseTotals, pageMergeBreakdown);
180
+ addBreakdown(componentLoopPhaseTotals, pageComponentLoopBreakdown);
181
+ envelopes.push({
182
+ route: entry.path,
183
+ file: sourceFile,
184
+ ir: pageIr,
185
+ router: softNavigationEnabled
186
+ });
187
+ recordPageProfile({
188
+ pageProfiles,
189
+ entry,
190
+ componentOccurrences: componentOccurrences.length,
191
+ pageExpandMs,
192
+ pageCompileMs,
193
+ pageOwnerCompileMs,
194
+ pageComponentCompileMs,
195
+ pageComponentCacheHits,
196
+ pageComponentCacheMisses,
197
+ pagePhase,
198
+ startupProfile,
199
+ pageStartedAt
200
+ });
201
+ }
202
+ emitPageLoopSummary({
203
+ startupProfile,
204
+ manifest,
205
+ pageLoopStartedAt,
206
+ compilerTotals,
207
+ expressionRewriteMetrics,
208
+ pagePhaseTotals,
209
+ occurrenceApplyPhaseTotals,
210
+ bindingResolutionTotals,
211
+ scopedRewritePhaseTotals,
212
+ mergePhaseTotals,
213
+ componentLoopPhaseTotals,
214
+ pageProfiles
215
+ });
216
+ return { envelopes, expressionRewriteMetrics };
217
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * @param {object | null | undefined} ir
3
+ * @returns {{ map: Map<string, string>, ambiguous: Set<string> }}
4
+ */
5
+ export function buildScopedIdentifierRewrite(ir: object | null | undefined): {
6
+ map: Map<string, string>;
7
+ ambiguous: Set<string>;
8
+ };
9
+ /**
10
+ * @param {string} expr
11
+ * @param {{
12
+ * expressionRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null,
13
+ * scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
14
+ * } | null} rewriteContext
15
+ * @returns {string}
16
+ */
17
+ export function rewritePropsExpression(expr: string, rewriteContext?: {
18
+ expressionRewrite?: {
19
+ map?: Map<string, string>;
20
+ ambiguous?: Set<string>;
21
+ } | null;
22
+ scopeRewrite?: {
23
+ map?: Map<string, string>;
24
+ ambiguous?: Set<string>;
25
+ } | null;
26
+ } | null): string;
27
+ /**
28
+ * @param {string | null | undefined} compiledExpr
29
+ * @param {{
30
+ * signals?: Array<{ state_index?: number }>,
31
+ * stateBindings?: Array<{ key?: string }>
32
+ * } | null | undefined} expressionRewrite
33
+ * @returns {string | null}
34
+ */
35
+ export function resolveCompiledPropsExpression(compiledExpr: string | null | undefined, expressionRewrite?: {
36
+ signals?: Array<{
37
+ state_index?: number;
38
+ }>;
39
+ stateBindings?: Array<{
40
+ key?: string;
41
+ }>;
42
+ } | null | undefined): string | null;
43
+ /**
44
+ * @param {string} expr
45
+ * @param {{
46
+ * expressionRewrite?: {
47
+ * map?: Map<string, string>,
48
+ * bindings?: Map<string, { compiled_expr?: string | null }>,
49
+ * ambiguous?: Set<string>,
50
+ * signals?: Array<{ state_index?: number }>,
51
+ * stateBindings?: Array<{ key?: string }>
52
+ * } | null,
53
+ * scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
54
+ * } | null} rewriteContext
55
+ * @returns {string}
56
+ */
57
+ export function resolvePropsValueCode(expr: string, rewriteContext?: {
58
+ expressionRewrite?: {
59
+ map?: Map<string, string>;
60
+ bindings?: Map<string, {
61
+ compiled_expr?: string | null;
62
+ }>;
63
+ ambiguous?: Set<string>;
64
+ signals?: Array<{
65
+ state_index?: number;
66
+ }>;
67
+ stateBindings?: Array<{
68
+ key?: string;
69
+ }>;
70
+ } | null;
71
+ scopeRewrite?: {
72
+ map?: Map<string, string>;
73
+ ambiguous?: Set<string>;
74
+ } | null;
75
+ } | null): string;
76
+ /**
77
+ * @param {string} attrs
78
+ * @param {{
79
+ * expressionRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null,
80
+ * scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
81
+ * } | null} rewriteContext
82
+ * @returns {string}
83
+ */
84
+ export function renderPropsLiteralFromAttrs(attrs: string, rewriteContext?: {
85
+ expressionRewrite?: {
86
+ map?: Map<string, string>;
87
+ ambiguous?: Set<string>;
88
+ } | null;
89
+ scopeRewrite?: {
90
+ map?: Map<string, string>;
91
+ ambiguous?: Set<string>;
92
+ } | null;
93
+ } | null): string;
94
+ /**
95
+ * @param {string} source
96
+ * @param {string} attrs
97
+ * @param {{
98
+ * expressionRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null,
99
+ * scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
100
+ * } | null} rewriteContext
101
+ * @returns {string}
102
+ */
103
+ export function injectPropsPrelude(source: string, attrs: string, rewriteContext?: {
104
+ expressionRewrite?: {
105
+ map?: Map<string, string>;
106
+ ambiguous?: Set<string>;
107
+ } | null;
108
+ scopeRewrite?: {
109
+ map?: Map<string, string>;
110
+ ambiguous?: Set<string>;
111
+ } | null;
112
+ } | null): string;
@@ -0,0 +1,245 @@
1
+ import { extractDeclaredIdentifiers, normalizeTypeScriptExpression, renderObjectKey, rewriteIdentifiersWithinExpression } from './typescript-expression-utils.js';
2
+ /**
3
+ * @param {string} value
4
+ * @returns {string | null}
5
+ */
6
+ function deriveScopedIdentifierAlias(value) {
7
+ const ident = String(value || '').trim();
8
+ if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(ident)) {
9
+ return null;
10
+ }
11
+ const parts = ident.split('_').filter(Boolean);
12
+ const candidate = parts.length > 1 ? parts[parts.length - 1] : ident;
13
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(candidate) ? candidate : ident;
14
+ }
15
+ /**
16
+ * @param {Map<string, string>} map
17
+ * @param {Set<string>} ambiguous
18
+ * @param {string | null} raw
19
+ * @param {string | null} rewritten
20
+ */
21
+ function recordScopedIdentifierRewrite(map, ambiguous, raw, rewritten) {
22
+ if (typeof raw !== 'string' || raw.length === 0 || typeof rewritten !== 'string' || rewritten.length === 0) {
23
+ return;
24
+ }
25
+ const existing = map.get(raw);
26
+ if (existing && existing !== rewritten) {
27
+ map.delete(raw);
28
+ ambiguous.add(raw);
29
+ return;
30
+ }
31
+ if (!ambiguous.has(raw)) {
32
+ map.set(raw, rewritten);
33
+ }
34
+ }
35
+ /**
36
+ * @param {object | null | undefined} ir
37
+ * @returns {{ map: Map<string, string>, ambiguous: Set<string> }}
38
+ */
39
+ export function buildScopedIdentifierRewrite(ir) {
40
+ const out = { map: new Map(), ambiguous: new Set() };
41
+ if (!ir || typeof ir !== 'object') {
42
+ return out;
43
+ }
44
+ const stateBindings = Array.isArray(ir?.hoisted?.state) ? ir.hoisted.state : [];
45
+ for (const stateEntry of stateBindings) {
46
+ const key = typeof stateEntry?.key === 'string' ? stateEntry.key : null;
47
+ recordScopedIdentifierRewrite(out.map, out.ambiguous, deriveScopedIdentifierAlias(key), key);
48
+ }
49
+ const functionBindings = Array.isArray(ir?.hoisted?.functions) ? ir.hoisted.functions : [];
50
+ for (const fnName of functionBindings) {
51
+ if (typeof fnName !== 'string') {
52
+ continue;
53
+ }
54
+ recordScopedIdentifierRewrite(out.map, out.ambiguous, deriveScopedIdentifierAlias(fnName), fnName);
55
+ }
56
+ const declarations = Array.isArray(ir?.hoisted?.declarations) ? ir.hoisted.declarations : [];
57
+ for (const declaration of declarations) {
58
+ if (typeof declaration !== 'string') {
59
+ continue;
60
+ }
61
+ for (const identifier of extractDeclaredIdentifiers(declaration)) {
62
+ recordScopedIdentifierRewrite(out.map, out.ambiguous, deriveScopedIdentifierAlias(identifier), identifier);
63
+ }
64
+ }
65
+ return out;
66
+ }
67
+ /**
68
+ * @param {string} expr
69
+ * @param {{
70
+ * expressionRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null,
71
+ * scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
72
+ * } | null} rewriteContext
73
+ * @returns {string}
74
+ */
75
+ export function rewritePropsExpression(expr, rewriteContext = null) {
76
+ const trimmed = String(expr || '').trim();
77
+ if (!trimmed) {
78
+ return trimmed;
79
+ }
80
+ const expressionMap = rewriteContext?.expressionRewrite?.map;
81
+ const expressionAmbiguous = rewriteContext?.expressionRewrite?.ambiguous;
82
+ if (expressionMap instanceof Map &&
83
+ !(expressionAmbiguous instanceof Set && expressionAmbiguous.has(trimmed))) {
84
+ const exact = expressionMap.get(trimmed);
85
+ if (typeof exact === 'string' && exact.length > 0) {
86
+ return normalizeTypeScriptExpression(exact);
87
+ }
88
+ }
89
+ const scopeMap = rewriteContext?.scopeRewrite?.map;
90
+ const scopeAmbiguous = rewriteContext?.scopeRewrite?.ambiguous;
91
+ const rootMatch = trimmed.match(/^([A-Za-z_$][A-Za-z0-9_$]*)([\s\S]*)$/);
92
+ if (!(scopeMap instanceof Map)) {
93
+ return normalizeTypeScriptExpression(trimmed);
94
+ }
95
+ if (!rootMatch) {
96
+ return rewriteIdentifiersWithinExpression(trimmed, scopeMap, scopeAmbiguous);
97
+ }
98
+ const root = rootMatch[1];
99
+ if (scopeAmbiguous instanceof Set && scopeAmbiguous.has(root)) {
100
+ return rewriteIdentifiersWithinExpression(trimmed, scopeMap, scopeAmbiguous);
101
+ }
102
+ const rewrittenRoot = scopeMap.get(root);
103
+ if (typeof rewrittenRoot !== 'string' || rewrittenRoot.length === 0 || rewrittenRoot === root) {
104
+ return rewriteIdentifiersWithinExpression(trimmed, scopeMap, scopeAmbiguous);
105
+ }
106
+ if (rootMatch[2].trim().length === 0) {
107
+ return normalizeTypeScriptExpression(rewrittenRoot);
108
+ }
109
+ const rewrittenExpr = rewriteIdentifiersWithinExpression(trimmed, scopeMap, scopeAmbiguous);
110
+ return typeof rewrittenExpr === 'string' && rewrittenExpr.length > 0
111
+ ? rewrittenExpr
112
+ : normalizeTypeScriptExpression(`${rewrittenRoot}${rootMatch[2]}`);
113
+ }
114
+ /**
115
+ * @param {string | null | undefined} compiledExpr
116
+ * @param {{
117
+ * signals?: Array<{ state_index?: number }>,
118
+ * stateBindings?: Array<{ key?: string }>
119
+ * } | null | undefined} expressionRewrite
120
+ * @returns {string | null}
121
+ */
122
+ export function resolveCompiledPropsExpression(compiledExpr, expressionRewrite = null) {
123
+ const source = typeof compiledExpr === 'string' ? compiledExpr.trim() : '';
124
+ if (!source) {
125
+ return null;
126
+ }
127
+ const signals = Array.isArray(expressionRewrite?.signals) ? expressionRewrite.signals : [];
128
+ const stateBindings = Array.isArray(expressionRewrite?.stateBindings) ? expressionRewrite.stateBindings : [];
129
+ const resolved = source.replace(/signalMap\.get\((\d+)\)(?:\.get\(\))?/g, (full, rawIndex) => {
130
+ const signalIndex = Number.parseInt(rawIndex, 10);
131
+ if (!Number.isInteger(signalIndex)) {
132
+ return full;
133
+ }
134
+ const signal = signals[signalIndex];
135
+ const stateIndex = signal?.state_index;
136
+ const stateKey = Number.isInteger(stateIndex) ? stateBindings[stateIndex]?.key : null;
137
+ if (typeof stateKey !== 'string' || stateKey.length === 0) {
138
+ return full;
139
+ }
140
+ return full.endsWith('.get()') ? `${stateKey}.get()` : stateKey;
141
+ });
142
+ return normalizeTypeScriptExpression(resolved);
143
+ }
144
+ /**
145
+ * @param {string} expr
146
+ * @param {{
147
+ * expressionRewrite?: {
148
+ * map?: Map<string, string>,
149
+ * bindings?: Map<string, { compiled_expr?: string | null }>,
150
+ * ambiguous?: Set<string>,
151
+ * signals?: Array<{ state_index?: number }>,
152
+ * stateBindings?: Array<{ key?: string }>
153
+ * } | null,
154
+ * scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
155
+ * } | null} rewriteContext
156
+ * @returns {string}
157
+ */
158
+ export function resolvePropsValueCode(expr, rewriteContext = null) {
159
+ const trimmed = String(expr || '').trim();
160
+ if (!trimmed) {
161
+ return trimmed;
162
+ }
163
+ const expressionRewrite = rewriteContext?.expressionRewrite;
164
+ const expressionAmbiguous = expressionRewrite?.ambiguous;
165
+ if (!(expressionAmbiguous instanceof Set && expressionAmbiguous.has(trimmed))) {
166
+ const binding = expressionRewrite?.bindings instanceof Map
167
+ ? expressionRewrite.bindings.get(trimmed)
168
+ : null;
169
+ const compiled = resolveCompiledPropsExpression(binding?.compiled_expr, expressionRewrite);
170
+ if (typeof compiled === 'string' && compiled.length > 0) {
171
+ return compiled;
172
+ }
173
+ const exact = expressionRewrite?.map instanceof Map
174
+ ? expressionRewrite.map.get(trimmed)
175
+ : null;
176
+ if (typeof exact === 'string' && exact.length > 0) {
177
+ return normalizeTypeScriptExpression(exact);
178
+ }
179
+ }
180
+ return rewritePropsExpression(trimmed, rewriteContext);
181
+ }
182
+ /**
183
+ * @param {string} attrs
184
+ * @param {{
185
+ * expressionRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null,
186
+ * scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
187
+ * } | null} rewriteContext
188
+ * @returns {string}
189
+ */
190
+ export function renderPropsLiteralFromAttrs(attrs, rewriteContext = null) {
191
+ const src = String(attrs || '').trim();
192
+ if (!src) {
193
+ return '{}';
194
+ }
195
+ const entries = [];
196
+ const attrRe = /([A-Za-z_$][A-Za-z0-9_$-]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|\{([\s\S]*?)\}))?/g;
197
+ let match;
198
+ while ((match = attrRe.exec(src)) !== null) {
199
+ const rawName = match[1];
200
+ if (!rawName || rawName.startsWith('on:')) {
201
+ continue;
202
+ }
203
+ const doubleQuoted = match[2];
204
+ const singleQuoted = match[3];
205
+ const expressionValue = match[4];
206
+ let valueCode = 'true';
207
+ if (doubleQuoted !== undefined) {
208
+ valueCode = JSON.stringify(doubleQuoted);
209
+ }
210
+ else if (singleQuoted !== undefined) {
211
+ valueCode = JSON.stringify(singleQuoted);
212
+ }
213
+ else if (expressionValue !== undefined) {
214
+ const trimmed = String(expressionValue).trim();
215
+ valueCode = trimmed.length > 0 ? resolvePropsValueCode(trimmed, rewriteContext) : 'undefined';
216
+ }
217
+ entries.push(`${renderObjectKey(rawName)}: ${valueCode}`);
218
+ }
219
+ if (entries.length === 0) {
220
+ return '{}';
221
+ }
222
+ return `{ ${entries.join(', ')} }`;
223
+ }
224
+ /**
225
+ * @param {string} source
226
+ * @param {string} attrs
227
+ * @param {{
228
+ * expressionRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null,
229
+ * scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
230
+ * } | null} rewriteContext
231
+ * @returns {string}
232
+ */
233
+ export function injectPropsPrelude(source, attrs, rewriteContext = null) {
234
+ if (typeof source !== 'string' || source.trim().length === 0) {
235
+ return source;
236
+ }
237
+ if (!/\bprops\b/.test(source)) {
238
+ return source;
239
+ }
240
+ if (/\b(?:const|let|var)\s+props\b/.test(source)) {
241
+ return source;
242
+ }
243
+ const propsLiteral = renderPropsLiteralFromAttrs(attrs, rewriteContext);
244
+ return `var props = ${propsLiteral};\n${source}`;
245
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @param {string} source
3
+ * @param {string} sourceFile
4
+ * @param {object} [compilerOpts]
5
+ * @returns {{ source: string, serverScript: { source: string, prerender: boolean, has_guard: boolean, has_load: boolean, source_path: string } | null }}
6
+ */
7
+ export function extractServerScript(source: string, sourceFile: string, compilerOpts?: object): {
8
+ source: string;
9
+ serverScript: {
10
+ source: string;
11
+ prerender: boolean;
12
+ has_guard: boolean;
13
+ has_load: boolean;
14
+ source_path: string;
15
+ } | null;
16
+ };
17
+ /**
18
+ * @param {string} source
19
+ * @param {Map<string, string>} registry
20
+ * @param {string | null} [ownerPath]
21
+ * @returns {Map<string, Array<{ attrs: string, ownerPath: string | null }>>}
22
+ */
23
+ export function collectComponentUsageAttrs(source: string, registry: Map<string, string>, ownerPath?: string | null): Map<string, Array<{
24
+ attrs: string;
25
+ ownerPath: string | null;
26
+ }>>;
27
+ /**
28
+ * @param {string} source
29
+ * @param {Map<string, string>} registry
30
+ * @param {string | null} [ownerPath]
31
+ * @param {Set<string>} [visitedFiles]
32
+ * @param {Map<string, Array<{ attrs: string, ownerPath: string | null }>>} [out]
33
+ * @returns {Map<string, Array<{ attrs: string, ownerPath: string | null }>>}
34
+ */
35
+ export function collectRecursiveComponentUsageAttrs(source: string, registry: Map<string, string>, ownerPath?: string | null, visitedFiles?: Set<string>, out?: Map<string, Array<{
36
+ attrs: string;
37
+ ownerPath: string | null;
38
+ }>>): Map<string, Array<{
39
+ attrs: string;
40
+ ownerPath: string | null;
41
+ }>>;