@zenithbuild/cli 0.7.10 → 0.7.12
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/README.md +14 -2
- package/dist/adapters/adapter-netlify-static.d.ts +2 -5
- package/dist/adapters/adapter-netlify.d.ts +2 -5
- package/dist/adapters/adapter-netlify.js +22 -5
- package/dist/adapters/adapter-types.d.ts +32 -13
- package/dist/adapters/adapter-types.js +0 -59
- package/dist/adapters/adapter-vercel-static.d.ts +2 -5
- package/dist/adapters/adapter-vercel.d.ts +2 -5
- package/dist/adapters/adapter-vercel.js +21 -6
- package/dist/adapters/copy-hosted-page-runtime.d.ts +2 -1
- package/dist/adapters/copy-hosted-page-runtime.js +68 -3
- package/dist/adapters/resolve-adapter.d.ts +6 -4
- package/dist/build/compiler-runtime.js +3 -0
- package/dist/build/expression-rewrites.d.ts +3 -1
- package/dist/build/expression-rewrites.js +14 -2
- package/dist/build/page-component-loop.d.ts +1 -0
- package/dist/build/page-component-loop.js +66 -6
- package/dist/build/page-ir-normalization.js +7 -0
- package/dist/build/page-loop-state.d.ts +2 -4
- package/dist/build/page-loop-state.js +17 -9
- package/dist/build/page-loop.js +18 -8
- package/dist/build/scoped-expression-context.d.ts +5 -0
- package/dist/build/scoped-expression-context.js +133 -0
- package/dist/build/server-script.js +13 -36
- package/dist/build/type-declarations.d.ts +2 -1
- package/dist/build/type-declarations.js +29 -52
- package/dist/build-output-manifest.d.ts +10 -6
- package/dist/build-output-manifest.js +4 -1
- package/dist/build.js +11 -2
- package/dist/component-instance-ir.js +1 -0
- package/dist/component-occurrences.d.ts +9 -0
- package/dist/component-occurrences.js +18 -0
- package/dist/config-plugins.d.ts +12 -0
- package/dist/config-plugins.js +100 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.js +56 -5
- package/dist/dev-build-session/helpers.js +27 -7
- package/dist/dev-build-session/session.js +19 -10
- package/dist/dev-server/build-error-response.d.ts +21 -0
- package/dist/dev-server/build-error-response.js +48 -0
- package/dist/dev-server/port-fallback.d.ts +15 -0
- package/dist/dev-server/port-fallback.js +61 -0
- package/dist/dev-server/request-handler.js +58 -5
- package/dist/dev-server/watcher.js +15 -0
- package/dist/dev-server.d.ts +5 -2
- package/dist/dev-server.js +129 -49
- package/dist/global-middleware-runtime-source.d.ts +15 -0
- package/dist/global-middleware-runtime-source.js +62 -0
- package/dist/global-middleware.d.ts +13 -0
- package/dist/global-middleware.js +252 -0
- package/dist/images/remote-fetch.d.ts +12 -0
- package/dist/images/remote-fetch.js +257 -0
- package/dist/images/service.d.ts +10 -0
- package/dist/images/service.js +9 -46
- package/dist/index.js +12 -2
- package/dist/manifest.d.ts +9 -1
- package/dist/manifest.js +70 -25
- package/dist/preview/request-handler.js +78 -5
- package/dist/preview/server-runner.d.ts +7 -2
- package/dist/preview/server-runner.js +19 -6
- package/dist/preview/server-script-runner-template.js +97 -29
- package/dist/resource-response.js +25 -8
- package/dist/resource-route-module.js +5 -22
- package/dist/route-classification.d.ts +11 -0
- package/dist/route-classification.js +21 -0
- package/dist/route-handler-export-analysis.d.ts +22 -0
- package/dist/route-handler-export-analysis.js +41 -0
- package/dist/scoped-server-data/analyze-owner-file.d.ts +3 -0
- package/dist/scoped-server-data/analyze-owner-file.js +149 -0
- package/dist/scoped-server-data/diagnostics.d.ts +18 -0
- package/dist/scoped-server-data/diagnostics.js +32 -0
- package/dist/scoped-server-data/lowering.d.ts +27 -0
- package/dist/scoped-server-data/lowering.js +242 -0
- package/dist/scoped-server-data/manifest-integration.d.ts +4 -0
- package/dist/scoped-server-data/manifest-integration.js +125 -0
- package/dist/scoped-server-data/owner-scanner.d.ts +6 -0
- package/dist/scoped-server-data/owner-scanner.js +55 -0
- package/dist/scoped-server-data/parse-owner-server-block.d.ts +12 -0
- package/dist/scoped-server-data/parse-owner-server-block.js +35 -0
- package/dist/scoped-server-data/runtime.d.ts +24 -0
- package/dist/scoped-server-data/runtime.js +121 -0
- package/dist/scoped-server-data/serialization-set.d.ts +2 -0
- package/dist/scoped-server-data/serialization-set.js +52 -0
- package/dist/scoped-server-data/static-props.d.ts +12 -0
- package/dist/scoped-server-data/static-props.js +307 -0
- package/dist/scoped-server-data/type-declarations.d.ts +10 -0
- package/dist/scoped-server-data/type-declarations.js +368 -0
- package/dist/scoped-server-data/types.d.ts +74 -0
- package/dist/scoped-server-data/types.js +1 -0
- package/dist/server-contract/auth-control-flow.d.ts +1 -0
- package/dist/server-contract/auth-control-flow.js +10 -0
- package/dist/server-contract/resolve.d.ts +19 -0
- package/dist/server-contract/resolve.js +85 -13
- package/dist/server-contract/resolved-envelope.d.ts +9 -0
- package/dist/server-contract/resolved-envelope.js +14 -0
- package/dist/server-contract/stage.js +1 -10
- package/dist/server-module-output.d.ts +9 -0
- package/dist/server-module-output.js +250 -0
- package/dist/server-output.d.ts +7 -1
- package/dist/server-output.js +144 -195
- package/dist/server-route-names.d.ts +2 -0
- package/dist/server-route-names.js +38 -0
- package/dist/server-runtime/matched-route-pipeline.d.ts +1 -0
- package/dist/server-runtime/matched-route-pipeline.js +1 -0
- package/dist/server-runtime/node-server.js +26 -3
- package/dist/server-runtime/route-render.d.ts +12 -3
- package/dist/server-runtime/route-render.js +67 -13
- package/dist/types/generate-env-dts.js +2 -44
- package/dist/types/zenith-env-dts.d.ts +4 -0
- package/dist/types/zenith-env-dts.js +96 -0
- package/package.json +3 -6
|
@@ -4,6 +4,7 @@ import { cloneComponentIrForInstance } from '../component-instance-ir.js';
|
|
|
4
4
|
import { renderPropsLiteralFromAttrs } from './scoped-identifier-rewrite.js';
|
|
5
5
|
import { extractTemplate, isDocumentMode } from '../resolve-components.js';
|
|
6
6
|
import { buildComponentExpressionRewrite, mergeExpressionRewriteMaps, resolveStateKeyFromBindings } from './expression-rewrites.js';
|
|
7
|
+
import { applyScopedDataContextToExpressionRewrite, resolveScopedExpressionContext } from './scoped-expression-context.js';
|
|
7
8
|
import { mergeComponentIr } from './merge-component-ir.js';
|
|
8
9
|
import { stripStyleBlocks } from './compiler-runtime.js';
|
|
9
10
|
import { extractDeclaredIdentifiers } from './typescript-expression-utils.js';
|
|
@@ -17,6 +18,55 @@ function createEmptyExpressionRewrite() {
|
|
|
17
18
|
sequence: []
|
|
18
19
|
};
|
|
19
20
|
}
|
|
21
|
+
const SERVER_CONST_RE = /(?:^|\n)\s*const\s+([A-Za-z_$][\w$]*)\s*=/g;
|
|
22
|
+
function stripOwnerServerBlocks(source) {
|
|
23
|
+
return String(source || '').replace(/<script\b([^>]*)>([\s\S]*?)<\/script>/gi, (full, attrs) => {
|
|
24
|
+
if (/\bserver\b/i.test(String(attrs || ''))) {
|
|
25
|
+
return '';
|
|
26
|
+
}
|
|
27
|
+
return full;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function collectServerConstNames(source) {
|
|
31
|
+
const names = [];
|
|
32
|
+
for (const match of String(source || '').matchAll(SERVER_CONST_RE)) {
|
|
33
|
+
const name = String(match[1] || '');
|
|
34
|
+
if (name && !names.includes(name)) {
|
|
35
|
+
names.push(name);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return names;
|
|
39
|
+
}
|
|
40
|
+
function createClientPlaceholderPrelude(source, strippedSource) {
|
|
41
|
+
const names = [];
|
|
42
|
+
String(source || '').replace(/<script\b([^>]*)>([\s\S]*?)<\/script>/gi, (full, attrs, body) => {
|
|
43
|
+
if (/\bserver\b/i.test(String(attrs || ''))) {
|
|
44
|
+
for (const name of collectServerConstNames(body)) {
|
|
45
|
+
const refRe = new RegExp(`\\b${escapeRegExp(name)}\\b`);
|
|
46
|
+
if (refRe.test(strippedSource) && !names.includes(name)) {
|
|
47
|
+
names.push(name);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return full;
|
|
52
|
+
});
|
|
53
|
+
if (names.length === 0) {
|
|
54
|
+
return '';
|
|
55
|
+
}
|
|
56
|
+
return [
|
|
57
|
+
'<script lang="ts">',
|
|
58
|
+
...names.map((name) => `const ${name} = undefined;`),
|
|
59
|
+
'</script>',
|
|
60
|
+
''
|
|
61
|
+
].join('\n');
|
|
62
|
+
}
|
|
63
|
+
function prepareOwnerClientCompileSource(source) {
|
|
64
|
+
const strippedSource = stripOwnerServerBlocks(source);
|
|
65
|
+
return stripStyleBlocks(`${createClientPlaceholderPrelude(source, strippedSource)}${strippedSource}`);
|
|
66
|
+
}
|
|
67
|
+
function escapeRegExp(value) {
|
|
68
|
+
return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
69
|
+
}
|
|
20
70
|
async function resolveComponentIr({ compPath, componentSource, compilerOpts, compilerBin, timedRunCompiler, cooperativeYield, componentIrCache, compilerTotals, pageStats, startupProfile, emitCompilerWarning }) {
|
|
21
71
|
let compIr;
|
|
22
72
|
if (componentIrCache.has(compPath)) {
|
|
@@ -27,7 +77,7 @@ async function resolveComponentIr({ compPath, componentSource, compilerOpts, com
|
|
|
27
77
|
else {
|
|
28
78
|
await cooperativeYield();
|
|
29
79
|
const componentCompileStartedAt = performance.now();
|
|
30
|
-
compIr = timedRunCompiler('component', compPath,
|
|
80
|
+
compIr = timedRunCompiler('component', compPath, prepareOwnerClientCompileSource(componentSource), compilerOpts, { compilerToolchain: compilerBin, onWarning: emitCompilerWarning });
|
|
31
81
|
pageStats.pageComponentCompileMs += startupProfile.roundMs(performance.now() - componentCompileStartedAt);
|
|
32
82
|
compilerTotals.componentCacheMisses += 1;
|
|
33
83
|
pageStats.pageComponentCacheMisses += 1;
|
|
@@ -72,7 +122,7 @@ async function resolveOwnerRewriteContext({ occurrence, sourceFile, compilerOpts
|
|
|
72
122
|
pageComponentLoopBreakdown.ownerSourceReadMs += startupProfile.roundMs(performance.now() - ownerSourceReadStartedAt);
|
|
73
123
|
await cooperativeYield();
|
|
74
124
|
const ownerCompileStartedAt = performance.now();
|
|
75
|
-
ownerIr = timedRunCompiler('component', ownerPath,
|
|
125
|
+
ownerIr = timedRunCompiler('component', ownerPath, prepareOwnerClientCompileSource(ownerSource), compilerOpts, { compilerToolchain: compilerBin, onWarning: emitCompilerWarning });
|
|
76
126
|
pageStats.pageComponentCompileMs += startupProfile.roundMs(performance.now() - ownerCompileStartedAt);
|
|
77
127
|
compilerTotals.componentCacheMisses += 1;
|
|
78
128
|
pageStats.pageComponentCacheMisses += 1;
|
|
@@ -136,6 +186,7 @@ export async function buildPageOwnerContext({ componentOccurrences, sourceFile,
|
|
|
136
186
|
}
|
|
137
187
|
export async function runPageComponentLoop({ componentOccurrences, occurrenceCountByPath, sourceFile, registry, compilerOpts, compilerBin, timedRunCompiler, cooperativeYield, startupProfile, compilerTotals, emitCompilerWarning, componentIrCache, componentDocumentModeCache, componentExpressionRewriteCache, expressionRewriteMetrics, pageOwnerExpressionRewrite, pageIr, pageIrMergeCache, seenStaticImports, pageExpressionRewriteMap, pageExpressionBindingMap, pageAmbiguousExpressionMap, knownRefKeys, componentOccurrencePlans, imagePropsLiterals, pagePhase, pageBindingResolutionBreakdown, pageMergeBreakdown, pageComponentLoopBreakdown, hoistedCodeTransformCache, pageStats }) {
|
|
138
188
|
let componentInstanceCounter = 0;
|
|
189
|
+
const scopedOccurrenceIndexByOwnerKey = new Map();
|
|
139
190
|
for (const occurrence of componentOccurrences) {
|
|
140
191
|
await cooperativeYield();
|
|
141
192
|
const compName = occurrence.name;
|
|
@@ -146,7 +197,9 @@ export async function runPageComponentLoop({ componentOccurrences, occurrenceCou
|
|
|
146
197
|
const componentSourceReadStartedAt = performance.now();
|
|
147
198
|
const componentSource = readFileSync(compPath, 'utf8');
|
|
148
199
|
pageComponentLoopBreakdown.componentSourceReadMs += startupProfile.roundMs(performance.now() - componentSourceReadStartedAt);
|
|
149
|
-
const occurrenceCount = occurrenceCountByPath.get(compPath)
|
|
200
|
+
const occurrenceCount = occurrenceCountByPath.get(compPath)
|
|
201
|
+
|| occurrenceCountByPath.get(compName)
|
|
202
|
+
|| 0;
|
|
150
203
|
const compIr = await resolveComponentIr({
|
|
151
204
|
compPath,
|
|
152
205
|
componentSource,
|
|
@@ -175,6 +228,10 @@ export async function runPageComponentLoop({ componentOccurrences, occurrenceCou
|
|
|
175
228
|
pageComponentLoopBreakdown,
|
|
176
229
|
startupProfile
|
|
177
230
|
});
|
|
231
|
+
const scopedContext = resolveScopedExpressionContext(pageIr, compPath, scopedOccurrenceIndexByOwnerKey);
|
|
232
|
+
const scopedExpressionRewrite = scopedContext
|
|
233
|
+
? applyScopedDataContextToExpressionRewrite(expressionRewrite, scopedContext)
|
|
234
|
+
: expressionRewrite;
|
|
178
235
|
const { attrExpressionRewrite } = await resolveOwnerRewriteContext({
|
|
179
236
|
occurrence,
|
|
180
237
|
sourceFile,
|
|
@@ -220,13 +277,16 @@ export async function runPageComponentLoop({ componentOccurrences, occurrenceCou
|
|
|
220
277
|
}, seenStaticImports, knownRefKeys, pageIrMergeCache, pageMergeBreakdown, hoistedCodeTransformCache);
|
|
221
278
|
pagePhase.mergeMs += startupProfile.roundMs(performance.now() - mergeStartedAt);
|
|
222
279
|
if (useIsolatedInstance) {
|
|
280
|
+
const scopedInstanceRewrite = scopedContext
|
|
281
|
+
? applyScopedDataContextToExpressionRewrite(instanceState.instanceRewrite, scopedContext)
|
|
282
|
+
: instanceState.instanceRewrite;
|
|
223
283
|
componentOccurrencePlans.push({
|
|
224
|
-
rewrite:
|
|
225
|
-
expressionSequence:
|
|
284
|
+
rewrite: scopedInstanceRewrite,
|
|
285
|
+
expressionSequence: scopedInstanceRewrite.sequence,
|
|
226
286
|
refSequence: instanceState.refIdentifierPairs
|
|
227
287
|
});
|
|
228
288
|
continue;
|
|
229
289
|
}
|
|
230
|
-
mergeExpressionRewriteMaps(pageExpressionRewriteMap, pageExpressionBindingMap, pageAmbiguousExpressionMap,
|
|
290
|
+
mergeExpressionRewriteMaps(pageExpressionRewriteMap, pageExpressionBindingMap, pageAmbiguousExpressionMap, scopedExpressionRewrite, pageIrMergeCache, pageBindingResolutionBreakdown);
|
|
231
291
|
}
|
|
232
292
|
}
|
|
@@ -50,6 +50,12 @@ export function applyExpressionRewrites(pageIr, expressionMap, bindingMap, ambig
|
|
|
50
50
|
if (rewritten && rewritten !== current && bindings[index].literal === current) {
|
|
51
51
|
bindings[index].literal = rewritten;
|
|
52
52
|
}
|
|
53
|
+
if (rewrittenBinding &&
|
|
54
|
+
typeof bindings[index].scoped_data_key === 'string' &&
|
|
55
|
+
bindings[index].scoped_data_key.length > 0 &&
|
|
56
|
+
!(typeof rewrittenBinding.scoped_data_key === 'string' && rewrittenBinding.scoped_data_key.length > 0)) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
53
59
|
if (rewrittenBinding) {
|
|
54
60
|
bindings[index].compiled_expr = rewrittenBinding.compiled_expr;
|
|
55
61
|
bindings[index].signal_index = rewrittenBinding.signal_index;
|
|
@@ -57,6 +63,7 @@ export function applyExpressionRewrites(pageIr, expressionMap, bindingMap, ambig
|
|
|
57
63
|
bindings[index].state_index = rewrittenBinding.state_index;
|
|
58
64
|
bindings[index].component_instance = rewrittenBinding.component_instance;
|
|
59
65
|
bindings[index].component_binding = rewrittenBinding.component_binding;
|
|
66
|
+
bindings[index].scoped_data_key = rewrittenBinding.scoped_data_key;
|
|
60
67
|
}
|
|
61
68
|
else if (rewritten && rewritten !== current && bindings[index].compiled_expr === current) {
|
|
62
69
|
bindings[index].compiled_expr = rewritten;
|
|
@@ -169,15 +169,13 @@ export function createPageLoopExecutionState(): {
|
|
|
169
169
|
envelopes: never[];
|
|
170
170
|
};
|
|
171
171
|
export function preparePageIrForMerge(pageIr: any): void;
|
|
172
|
-
export function applyServerEnvelopeToPageIr({ pageIr, composedServer,
|
|
172
|
+
export function applyServerEnvelopeToPageIr({ pageIr, composedServer, entry, srcDir, sourceFile, scopedMetadata }: {
|
|
173
173
|
pageIr: any;
|
|
174
174
|
composedServer: any;
|
|
175
|
-
hasGuard: any;
|
|
176
|
-
hasLoad: any;
|
|
177
|
-
hasAction: any;
|
|
178
175
|
entry: any;
|
|
179
176
|
srcDir: any;
|
|
180
177
|
sourceFile: any;
|
|
178
|
+
scopedMetadata: any;
|
|
181
179
|
}): void;
|
|
182
180
|
export function buildOccurrenceCountByPath(componentOccurrences: any): Map<any, any>;
|
|
183
181
|
export function createPageBuildState(): {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { relative } from 'node:path';
|
|
2
|
+
import { classifyPageRoute } from '../route-classification.js';
|
|
3
|
+
import { assertNoScopedServerBuildErrors } from '../manifest.js';
|
|
2
4
|
import { createBindingResolutionTotals, createComponentLoopPhaseTotals, createMergePhaseTotals, createOccurrenceApplyPhaseTotals, createPagePhaseTotals, createScopedRewritePhaseTotals } from './page-loop-metrics.js';
|
|
3
5
|
export function createPageLoopState() {
|
|
4
6
|
return {
|
|
@@ -46,22 +48,28 @@ export function preparePageIrForMerge(pageIr) {
|
|
|
46
48
|
pageIr.hoisted.state = pageIr.hoisted.state || [];
|
|
47
49
|
pageIr.hoisted.code = pageIr.hoisted.code || [];
|
|
48
50
|
}
|
|
49
|
-
export function applyServerEnvelopeToPageIr({ pageIr, composedServer,
|
|
51
|
+
export function applyServerEnvelopeToPageIr({ pageIr, composedServer, entry, srcDir, sourceFile, scopedMetadata }) {
|
|
52
|
+
assertNoScopedServerBuildErrors(scopedMetadata.diagnostics, entry.file);
|
|
53
|
+
const classification = classifyPageRoute({
|
|
54
|
+
file: entry.file,
|
|
55
|
+
serverScript: composedServer.serverScript,
|
|
56
|
+
hasScopedServerData: scopedMetadata.hasScopedServerData
|
|
57
|
+
});
|
|
50
58
|
if (composedServer.serverScript) {
|
|
51
59
|
const { has_action: _unusedHasAction, export_paths: _unusedExportPaths, ...serverScript } = composedServer.serverScript;
|
|
52
60
|
pageIr.server_script = serverScript;
|
|
53
|
-
pageIr.prerender =
|
|
61
|
+
pageIr.prerender = classification.prerender;
|
|
54
62
|
if (pageIr.ssr_data === undefined) {
|
|
55
63
|
pageIr.ssr_data = null;
|
|
56
64
|
}
|
|
57
65
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
pageIr.
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
pageIr.has_guard = classification.hasGuard;
|
|
67
|
+
pageIr.has_load = classification.hasLoad;
|
|
68
|
+
pageIr.has_action = classification.hasAction;
|
|
69
|
+
pageIr.has_scoped_server_data = scopedMetadata.hasScopedServerData;
|
|
70
|
+
pageIr.scoped_server_data = scopedMetadata.hasScopedServerData
|
|
71
|
+
? scopedMetadata.scopedServerData
|
|
72
|
+
: [];
|
|
65
73
|
pageIr.guard_module_ref = composedServer.guardPath ? relative(srcDir, composedServer.guardPath).replaceAll('\\', '/') : null;
|
|
66
74
|
pageIr.load_module_ref = composedServer.loadPath ? relative(srcDir, composedServer.loadPath).replaceAll('\\', '/') : null;
|
|
67
75
|
pageIr.action_module_ref = composedServer.actionPath ? relative(srcDir, composedServer.actionPath).replaceAll('\\', '/') : null;
|
package/dist/build/page-loop.js
CHANGED
|
@@ -14,6 +14,7 @@ import { deferComponentRuntimeBlock } from './hoisted-code-transforms.js';
|
|
|
14
14
|
import { addBreakdown, emitPageLoopSummary, recordPageProfile } from './page-loop-metrics.js';
|
|
15
15
|
import { applyServerEnvelopeToPageIr, buildOccurrenceCountByPath, createPageBuildState, createPageLoopCaches, createPageLoopExecutionState } from './page-loop-state.js';
|
|
16
16
|
import { extractServerScript } from './server-script.js';
|
|
17
|
+
import { analyzeRouteScopedServerMetadata } from '../manifest.js';
|
|
17
18
|
/**
|
|
18
19
|
* @param {{
|
|
19
20
|
* manifest: Array<{ path: string, file: string }>
|
|
@@ -56,13 +57,20 @@ export async function buildPageEnvelopes(input) {
|
|
|
56
57
|
const expandedStartedAt = performance.now();
|
|
57
58
|
const { expandedSource } = expandComponents(rawSource, registry, sourceFile);
|
|
58
59
|
pageExpandMs = startupProfile.roundMs(performance.now() - expandedStartedAt);
|
|
60
|
+
const usesInternalExpandedSource = expandedSource !== rawSource;
|
|
61
|
+
if (usesInternalExpandedSource) {
|
|
62
|
+
const rawServerExtracted = extractServerScript(rawSource, sourceFile, compilerOpts);
|
|
63
|
+
timedRunCompiler('page', sourceFile, rawServerExtracted.source, compilerOpts, { compilerToolchain: compilerBin, onWarning: emitCompilerWarning });
|
|
64
|
+
}
|
|
59
65
|
const expandedServerExtractStartedAt = performance.now();
|
|
60
66
|
const extractedServer = extractServerScript(expandedSource, sourceFile, compilerOpts);
|
|
61
67
|
pagePhase.serverExtractMs += startupProfile.roundMs(performance.now() - expandedServerExtractStartedAt);
|
|
62
68
|
const compileSource = extractedServer.source;
|
|
63
69
|
await cooperativeYield();
|
|
64
70
|
const pageCompileStartedAt = performance.now();
|
|
65
|
-
let pageIr = timedRunCompiler('page', sourceFile, compileSource,
|
|
71
|
+
let pageIr = timedRunCompiler('page', sourceFile, compileSource, usesInternalExpandedSource
|
|
72
|
+
? { ...compilerOpts, internalAllowUnboundMarkup: true }
|
|
73
|
+
: compilerOpts, { compilerToolchain: compilerBin, onWarning: emitCompilerWarning });
|
|
66
74
|
pageCompileMs = startupProfile.roundMs(performance.now() - pageCompileStartedAt);
|
|
67
75
|
const composedServer = composeServerScriptEnvelope({
|
|
68
76
|
sourceFile,
|
|
@@ -71,18 +79,20 @@ export async function buildPageEnvelopes(input) {
|
|
|
71
79
|
adjacentLoadPath: adjacentLoad,
|
|
72
80
|
adjacentActionPath: adjacentAction
|
|
73
81
|
});
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
82
|
+
const scopedMetadata = analyzeRouteScopedServerMetadata({
|
|
83
|
+
pageSource: rawSource,
|
|
84
|
+
pageFile: sourceFile,
|
|
85
|
+
registry,
|
|
86
|
+
srcDir,
|
|
87
|
+
compilerOpts
|
|
88
|
+
});
|
|
77
89
|
applyServerEnvelopeToPageIr({
|
|
78
90
|
pageIr,
|
|
79
91
|
composedServer,
|
|
80
|
-
hasGuard,
|
|
81
|
-
hasLoad,
|
|
82
|
-
hasAction,
|
|
83
92
|
entry,
|
|
84
93
|
srcDir,
|
|
85
|
-
sourceFile
|
|
94
|
+
sourceFile,
|
|
95
|
+
scopedMetadata
|
|
86
96
|
});
|
|
87
97
|
const pageIrMergeCache = createPageIrMergeCache(pageIr);
|
|
88
98
|
const seenStaticImports = new Set();
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export function applyScopedDataContextToExpressionRewrite(componentRewrite: any, scopedContext: any): any;
|
|
2
|
+
export function resolveScopedExpressionContext(pageIr: any, compPath: any, occurrenceIndexByOwnerKey: any): {
|
|
3
|
+
scopedDataKey: any;
|
|
4
|
+
serializedVariableNames: any;
|
|
5
|
+
} | null;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
function escapeRegExp(value) {
|
|
2
|
+
return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
3
|
+
}
|
|
4
|
+
function scopedDataKey(scopedContext) {
|
|
5
|
+
return typeof scopedContext?.scopedDataKey === 'string' && scopedContext.scopedDataKey.length > 0
|
|
6
|
+
? scopedContext.scopedDataKey
|
|
7
|
+
: null;
|
|
8
|
+
}
|
|
9
|
+
function scopedDataExpressionForSource(expression, scopedContext) {
|
|
10
|
+
const match = String(expression || '').trim().match(/^([A-Za-z_$][\w$]*)([\s\S]*)$/);
|
|
11
|
+
if (!match)
|
|
12
|
+
return null;
|
|
13
|
+
const root = match[1];
|
|
14
|
+
const rest = match[2] || '';
|
|
15
|
+
if (root === 'data' || root === 'ssr')
|
|
16
|
+
return `${root}${rest}`;
|
|
17
|
+
for (const name of Array.isArray(scopedContext?.serializedVariableNames) ? scopedContext.serializedVariableNames : []) {
|
|
18
|
+
if (typeof name === 'string' &&
|
|
19
|
+
name.length > 0 &&
|
|
20
|
+
(root === name || new RegExp(`(?:^|_)${escapeRegExp(name)}(?:__inst\\d+)?$`).test(root))) {
|
|
21
|
+
return `data.${name}${rest}`;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
function scopedExpressionCandidate(raw, rewritten, binding, scopedContext) {
|
|
27
|
+
if (!scopedDataKey(scopedContext))
|
|
28
|
+
return null;
|
|
29
|
+
for (const candidate of [rewritten, binding?.compiled_expr, binding?.literal, raw]) {
|
|
30
|
+
const scopedExpression = scopedDataExpressionForSource(candidate, scopedContext);
|
|
31
|
+
if (scopedExpression)
|
|
32
|
+
return scopedExpression;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function createScopedBinding(scopedExpression, scopedContext, baseBinding = null) {
|
|
37
|
+
return scopedExpression
|
|
38
|
+
? {
|
|
39
|
+
...(baseBinding && typeof baseBinding === 'object' ? baseBinding : {}),
|
|
40
|
+
compiled_expr: scopedExpression,
|
|
41
|
+
literal: scopedExpression,
|
|
42
|
+
signal_index: null,
|
|
43
|
+
signal_indices: [],
|
|
44
|
+
state_index: null,
|
|
45
|
+
component_instance: null,
|
|
46
|
+
component_binding: null,
|
|
47
|
+
scoped_data_key: scopedDataKey(scopedContext)
|
|
48
|
+
}
|
|
49
|
+
: null;
|
|
50
|
+
}
|
|
51
|
+
function applyScopedContextToBinding(binding, scopedContext, fallbackExpression = null) {
|
|
52
|
+
if (!binding || typeof binding !== 'object' || !scopedDataKey(scopedContext))
|
|
53
|
+
return binding;
|
|
54
|
+
const scopedExpression = scopedDataExpressionForSource(binding.compiled_expr, scopedContext)
|
|
55
|
+
|| scopedDataExpressionForSource(binding.literal, scopedContext)
|
|
56
|
+
|| scopedDataExpressionForSource(fallbackExpression, scopedContext);
|
|
57
|
+
return scopedExpression ? createScopedBinding(scopedExpression, scopedContext, binding) : binding;
|
|
58
|
+
}
|
|
59
|
+
function hasScopedBinding(binding) {
|
|
60
|
+
return typeof binding?.scoped_data_key === 'string' && binding.scoped_data_key.length > 0;
|
|
61
|
+
}
|
|
62
|
+
export function applyScopedDataContextToExpressionRewrite(componentRewrite, scopedContext) {
|
|
63
|
+
if (!componentRewrite || !scopedDataKey(scopedContext))
|
|
64
|
+
return componentRewrite;
|
|
65
|
+
const next = {
|
|
66
|
+
map: new Map(),
|
|
67
|
+
bindings: new Map(),
|
|
68
|
+
signals: componentRewrite.signals,
|
|
69
|
+
stateBindings: componentRewrite.stateBindings,
|
|
70
|
+
ambiguous: new Set(componentRewrite.ambiguous),
|
|
71
|
+
sequence: []
|
|
72
|
+
};
|
|
73
|
+
for (const item of Array.isArray(componentRewrite.sequence) ? componentRewrite.sequence : []) {
|
|
74
|
+
const scopedBinding = applyScopedContextToBinding(item.binding, scopedContext, item.rewritten || item.raw);
|
|
75
|
+
const scopedExpression = scopedExpressionCandidate(item.raw, item.rewritten, scopedBinding, scopedContext);
|
|
76
|
+
next.sequence.push({
|
|
77
|
+
raw: item.raw,
|
|
78
|
+
rewritten: scopedExpression || item.rewritten,
|
|
79
|
+
binding: hasScopedBinding(scopedBinding)
|
|
80
|
+
? scopedBinding
|
|
81
|
+
: createScopedBinding(scopedExpression, scopedContext)
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
for (const [raw, binding] of componentRewrite.bindings.entries()) {
|
|
85
|
+
next.bindings.set(raw, applyScopedContextToBinding(binding, scopedContext, raw));
|
|
86
|
+
}
|
|
87
|
+
for (const [raw, rewritten] of componentRewrite.map.entries()) {
|
|
88
|
+
const binding = next.bindings.get(raw);
|
|
89
|
+
next.map.set(raw, scopedExpressionCandidate(raw, rewritten, binding, scopedContext) || rewritten);
|
|
90
|
+
}
|
|
91
|
+
return next;
|
|
92
|
+
}
|
|
93
|
+
function normalizeSourcePath(value) {
|
|
94
|
+
return String(value || '').replaceAll('\\', '/');
|
|
95
|
+
}
|
|
96
|
+
function ownerKeyMatchesPath(ownerKey, filePath) {
|
|
97
|
+
const key = normalizeSourcePath(ownerKey);
|
|
98
|
+
const file = normalizeSourcePath(filePath);
|
|
99
|
+
return key.length > 0 && (file === key || file.endsWith(`/${key}`));
|
|
100
|
+
}
|
|
101
|
+
export function resolveScopedExpressionContext(pageIr, compPath, occurrenceIndexByOwnerKey) {
|
|
102
|
+
const entries = Array.isArray(pageIr?.scoped_server_data) ? pageIr.scoped_server_data : [];
|
|
103
|
+
const matches = entries.filter((entry) => entry &&
|
|
104
|
+
typeof entry === 'object' &&
|
|
105
|
+
(entry.ownerKind === 'layout' || entry.ownerKind === 'component') &&
|
|
106
|
+
ownerKeyMatchesPath(entry.ownerKey, compPath));
|
|
107
|
+
const entry = matches.length === 1 ? matches[0] : null;
|
|
108
|
+
if (!entry || typeof entry.ownerKey !== 'string')
|
|
109
|
+
return null;
|
|
110
|
+
let scopedDataKey = null;
|
|
111
|
+
if (entry.ownerKind === 'layout') {
|
|
112
|
+
scopedDataKey = `layout:${entry.ownerKey}`;
|
|
113
|
+
}
|
|
114
|
+
else if (entry.ownerKind === 'component' && entry.instanceStrategy === 'per-instance') {
|
|
115
|
+
const index = occurrenceIndexByOwnerKey.get(entry.ownerKey) || 0;
|
|
116
|
+
occurrenceIndexByOwnerKey.set(entry.ownerKey, index + 1);
|
|
117
|
+
const instance = Array.isArray(entry.instances) ? entry.instances[index] : null;
|
|
118
|
+
scopedDataKey = typeof instance?.key === 'string' && instance.key.length > 0
|
|
119
|
+
? instance.key
|
|
120
|
+
: `component:${entry.ownerKey}:o${index}`;
|
|
121
|
+
}
|
|
122
|
+
else if (entry.ownerKind === 'component') {
|
|
123
|
+
scopedDataKey = `component:${entry.ownerKey}`;
|
|
124
|
+
}
|
|
125
|
+
return scopedDataKey
|
|
126
|
+
? {
|
|
127
|
+
scopedDataKey,
|
|
128
|
+
serializedVariableNames: Array.isArray(entry.serializedVariableNames)
|
|
129
|
+
? entry.serializedVariableNames
|
|
130
|
+
: []
|
|
131
|
+
}
|
|
132
|
+
: null;
|
|
133
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { findNextKnownComponentTag } from '../component-tag-parser.js';
|
|
3
|
+
import { readRouteHandlerExport } from '../route-handler-export-analysis.js';
|
|
3
4
|
import { extractStaticExportPaths } from '../static-export-paths.js';
|
|
4
5
|
/**
|
|
5
6
|
* @param {string} source
|
|
@@ -56,40 +57,25 @@ export function extractServerScript(source, sourceFile, compilerOpts = {}) {
|
|
|
56
57
|
` Reason: <script server> block is empty\n` +
|
|
57
58
|
` Example: export const data = { ... }`);
|
|
58
59
|
}
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
const hasLoad = Boolean(loadFnMatch || loadConstParenMatch || loadConstSingleArgMatch);
|
|
63
|
-
const loadMatchCount = Number(Boolean(loadFnMatch)) +
|
|
64
|
-
Number(Boolean(loadConstParenMatch)) +
|
|
65
|
-
Number(Boolean(loadConstSingleArgMatch));
|
|
66
|
-
if (loadMatchCount > 1) {
|
|
60
|
+
const loadExport = readRouteHandlerExport(serverSource, 'load');
|
|
61
|
+
const hasLoad = loadExport.hasExport;
|
|
62
|
+
if (loadExport.matchCount > 1) {
|
|
67
63
|
throw new Error(`Zenith server script contract violation:\n` +
|
|
68
64
|
` File: ${sourceFile}\n` +
|
|
69
65
|
` Reason: multiple load exports detected\n` +
|
|
70
66
|
` Example: keep exactly one export const load = async (ctx) => ({ ... })`);
|
|
71
67
|
}
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
const hasGuard = Boolean(guardFnMatch || guardConstParenMatch || guardConstSingleArgMatch);
|
|
76
|
-
const guardMatchCount = Number(Boolean(guardFnMatch)) +
|
|
77
|
-
Number(Boolean(guardConstParenMatch)) +
|
|
78
|
-
Number(Boolean(guardConstSingleArgMatch));
|
|
79
|
-
if (guardMatchCount > 1) {
|
|
68
|
+
const guardExport = readRouteHandlerExport(serverSource, 'guard');
|
|
69
|
+
const hasGuard = guardExport.hasExport;
|
|
70
|
+
if (guardExport.matchCount > 1) {
|
|
80
71
|
throw new Error(`Zenith server script contract violation:\n` +
|
|
81
72
|
` File: ${sourceFile}\n` +
|
|
82
73
|
` Reason: multiple guard exports detected\n` +
|
|
83
74
|
` Example: keep exactly one export const guard = async (ctx) => ({ ... })`);
|
|
84
75
|
}
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
const hasAction = Boolean(actionFnMatch || actionConstParenMatch || actionConstSingleArgMatch);
|
|
89
|
-
const actionMatchCount = Number(Boolean(actionFnMatch)) +
|
|
90
|
-
Number(Boolean(actionConstParenMatch)) +
|
|
91
|
-
Number(Boolean(actionConstSingleArgMatch));
|
|
92
|
-
if (actionMatchCount > 1) {
|
|
76
|
+
const actionExport = readRouteHandlerExport(serverSource, 'action');
|
|
77
|
+
const hasAction = actionExport.hasExport;
|
|
78
|
+
if (actionExport.matchCount > 1) {
|
|
93
79
|
throw new Error(`Zenith server script contract violation:\n` +
|
|
94
80
|
` File: ${sourceFile}\n` +
|
|
95
81
|
` Reason: multiple action exports detected\n` +
|
|
@@ -112,10 +98,7 @@ export function extractServerScript(source, sourceFile, compilerOpts = {}) {
|
|
|
112
98
|
` Example: use only export const data or export const load`);
|
|
113
99
|
}
|
|
114
100
|
if (hasLoad) {
|
|
115
|
-
|
|
116
|
-
const paramsText = String((loadFnMatch || loadConstParenMatch)?.[1] || '').trim();
|
|
117
|
-
const arity = singleArg ? 1 : paramsText.length === 0 ? 0 : paramsText.split(',').length;
|
|
118
|
-
if (arity !== 1) {
|
|
101
|
+
if (loadExport.arity !== null && loadExport.arity !== 1) {
|
|
119
102
|
throw new Error(`Zenith server script contract violation:\n` +
|
|
120
103
|
` File: ${sourceFile}\n` +
|
|
121
104
|
` Reason: load(ctx) must accept exactly one argument\n` +
|
|
@@ -123,10 +106,7 @@ export function extractServerScript(source, sourceFile, compilerOpts = {}) {
|
|
|
123
106
|
}
|
|
124
107
|
}
|
|
125
108
|
if (hasGuard) {
|
|
126
|
-
|
|
127
|
-
const paramsText = String((guardFnMatch || guardConstParenMatch)?.[1] || '').trim();
|
|
128
|
-
const arity = singleArg ? 1 : paramsText.length === 0 ? 0 : paramsText.split(',').length;
|
|
129
|
-
if (arity !== 1) {
|
|
109
|
+
if (guardExport.arity !== null && guardExport.arity !== 1) {
|
|
130
110
|
throw new Error(`Zenith server script contract violation:\n` +
|
|
131
111
|
` File: ${sourceFile}\n` +
|
|
132
112
|
` Reason: guard(ctx) must accept exactly one argument\n` +
|
|
@@ -134,10 +114,7 @@ export function extractServerScript(source, sourceFile, compilerOpts = {}) {
|
|
|
134
114
|
}
|
|
135
115
|
}
|
|
136
116
|
if (hasAction) {
|
|
137
|
-
|
|
138
|
-
const paramsText = String((actionFnMatch || actionConstParenMatch)?.[1] || '').trim();
|
|
139
|
-
const arity = singleArg ? 1 : paramsText.length === 0 ? 0 : paramsText.split(',').length;
|
|
140
|
-
if (arity !== 1) {
|
|
117
|
+
if (actionExport.arity !== null && actionExport.arity !== 1) {
|
|
141
118
|
throw new Error(`Zenith server script contract violation:\n` +
|
|
142
119
|
` File: ${sourceFile}\n` +
|
|
143
120
|
` Reason: action(ctx) must accept exactly one argument\n` +
|
|
@@ -4,13 +4,14 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export function deriveProjectRootFromPagesDir(pagesDir: string): string;
|
|
6
6
|
/**
|
|
7
|
-
* @param {{ manifest: Array<{ path: string, file: string }>, pagesDir: string }} input
|
|
7
|
+
* @param {{ manifest: Array<{ path: string, file: string, scoped_server_data?: import('../scoped-server-data/types.js').ManifestScopedServerDataEntry[] }>, pagesDir: string }} input
|
|
8
8
|
* @returns {Promise<void>}
|
|
9
9
|
*/
|
|
10
10
|
export function ensureZenithTypeDeclarations(input: {
|
|
11
11
|
manifest: Array<{
|
|
12
12
|
path: string;
|
|
13
13
|
file: string;
|
|
14
|
+
scoped_server_data?: import("../scoped-server-data/types.js").ManifestScopedServerDataEntry[];
|
|
14
15
|
}>;
|
|
15
16
|
pagesDir: string;
|
|
16
17
|
}): Promise<void>;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { mkdir } from 'node:fs/promises';
|
|
3
3
|
import { basename, dirname, join, resolve } from 'node:path';
|
|
4
|
+
import { renderZenithEnvDts } from '../types/zenith-env-dts.js';
|
|
5
|
+
const SCOPED_SERVER_TYPE_DECLARATIONS_HELPER_UNAVAILABLE = '[Zenith:ScopedServerData] Type declaration helper is unavailable. Run the CLI build step before generating scoped server data type declarations.';
|
|
6
|
+
let scopedTypeDeclarationRendererPromise = null;
|
|
4
7
|
/**
|
|
5
8
|
* @param {string} targetPath
|
|
6
9
|
* @param {string} next
|
|
@@ -61,58 +64,25 @@ function renderZenithRouteDts(manifest) {
|
|
|
61
64
|
return `${lines.join('\n')}\n`;
|
|
62
65
|
}
|
|
63
66
|
/**
|
|
64
|
-
* @returns {string}
|
|
67
|
+
* @returns {Promise<(input: { manifest: Array<{ scoped_server_data?: import('../scoped-server-data/types.js').ManifestScopedServerDataEntry[] }>, srcDir: string }) => string>}
|
|
65
68
|
*/
|
|
66
|
-
function
|
|
67
|
-
|
|
68
|
-
'
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
' interface RouteMeta {',
|
|
84
|
-
' id: string;',
|
|
85
|
-
' file: string;',
|
|
86
|
-
' pattern: string;',
|
|
87
|
-
' }',
|
|
88
|
-
'',
|
|
89
|
-
' interface LoadContext {',
|
|
90
|
-
' params: Params;',
|
|
91
|
-
' url: URL;',
|
|
92
|
-
' request: Request;',
|
|
93
|
-
' route: RouteMeta;',
|
|
94
|
-
' }',
|
|
95
|
-
'',
|
|
96
|
-
' type Load<T extends PageData = PageData> = (ctx: LoadContext) => Promise<T> | T;',
|
|
97
|
-
'',
|
|
98
|
-
' interface Fragment {',
|
|
99
|
-
' __zenith_fragment: true;',
|
|
100
|
-
' mount: (anchor: Node | null) => void;',
|
|
101
|
-
' unmount: () => void;',
|
|
102
|
-
' }',
|
|
103
|
-
'',
|
|
104
|
-
' type Renderable =',
|
|
105
|
-
' | string',
|
|
106
|
-
' | number',
|
|
107
|
-
' | boolean',
|
|
108
|
-
' | null',
|
|
109
|
-
' | undefined',
|
|
110
|
-
' | Renderable[]',
|
|
111
|
-
' | Fragment;',
|
|
112
|
-
' }',
|
|
113
|
-
'}',
|
|
114
|
-
''
|
|
115
|
-
].join('\n');
|
|
69
|
+
async function getScopedServerDataTypeRenderer() {
|
|
70
|
+
if (!scopedTypeDeclarationRendererPromise) {
|
|
71
|
+
scopedTypeDeclarationRendererPromise = import('../scoped-server-data/type-declarations.js')
|
|
72
|
+
.then((helper) => {
|
|
73
|
+
if (typeof helper.renderScopedServerDataDts !== 'function') {
|
|
74
|
+
throw new Error(SCOPED_SERVER_TYPE_DECLARATIONS_HELPER_UNAVAILABLE);
|
|
75
|
+
}
|
|
76
|
+
return helper.renderScopedServerDataDts;
|
|
77
|
+
})
|
|
78
|
+
.catch((error) => {
|
|
79
|
+
if (error && error.message === SCOPED_SERVER_TYPE_DECLARATIONS_HELPER_UNAVAILABLE) {
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
throw new Error(SCOPED_SERVER_TYPE_DECLARATIONS_HELPER_UNAVAILABLE);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return scopedTypeDeclarationRendererPromise;
|
|
116
86
|
}
|
|
117
87
|
/**
|
|
118
88
|
* @param {string} pagesDir
|
|
@@ -127,17 +97,24 @@ export function deriveProjectRootFromPagesDir(pagesDir) {
|
|
|
127
97
|
return parent;
|
|
128
98
|
}
|
|
129
99
|
/**
|
|
130
|
-
* @param {{ manifest: Array<{ path: string, file: string }>, pagesDir: string }} input
|
|
100
|
+
* @param {{ manifest: Array<{ path: string, file: string, scoped_server_data?: import('../scoped-server-data/types.js').ManifestScopedServerDataEntry[] }>, pagesDir: string }} input
|
|
131
101
|
* @returns {Promise<void>}
|
|
132
102
|
*/
|
|
133
103
|
export async function ensureZenithTypeDeclarations(input) {
|
|
134
104
|
const projectRoot = deriveProjectRootFromPagesDir(input.pagesDir);
|
|
105
|
+
const srcDir = dirname(resolve(input.pagesDir));
|
|
135
106
|
const zenithDir = resolve(projectRoot, '.zenith');
|
|
136
107
|
await mkdir(zenithDir, { recursive: true });
|
|
137
108
|
const envPath = join(zenithDir, 'zenith-env.d.ts');
|
|
138
109
|
const routesPath = join(zenithDir, 'zenith-routes.d.ts');
|
|
110
|
+
const scopedPath = join(zenithDir, 'zenith-scoped-server-data.d.ts');
|
|
111
|
+
const renderScopedServerDataDts = await getScopedServerDataTypeRenderer();
|
|
139
112
|
writeIfChanged(envPath, renderZenithEnvDts());
|
|
140
113
|
writeIfChanged(routesPath, renderZenithRouteDts(input.manifest));
|
|
114
|
+
writeIfChanged(scopedPath, renderScopedServerDataDts({
|
|
115
|
+
manifest: input.manifest,
|
|
116
|
+
srcDir
|
|
117
|
+
}));
|
|
141
118
|
const tsconfigPath = resolve(projectRoot, 'tsconfig.json');
|
|
142
119
|
if (!existsSync(tsconfigPath)) {
|
|
143
120
|
return;
|