@zenithbuild/cli 0.7.3 → 0.7.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/README.md +18 -13
- package/dist/adapters/adapter-netlify.d.ts +1 -1
- package/dist/adapters/adapter-netlify.js +56 -13
- package/dist/adapters/adapter-node.js +8 -0
- package/dist/adapters/adapter-static-export.d.ts +5 -0
- package/dist/adapters/adapter-static-export.js +115 -0
- package/dist/adapters/adapter-types.d.ts +3 -1
- package/dist/adapters/adapter-types.js +5 -2
- package/dist/adapters/adapter-vercel.d.ts +1 -1
- package/dist/adapters/adapter-vercel.js +70 -13
- package/dist/adapters/copy-hosted-page-runtime.d.ts +1 -0
- package/dist/adapters/copy-hosted-page-runtime.js +49 -0
- package/dist/adapters/resolve-adapter.js +4 -0
- package/dist/adapters/route-rules.d.ts +5 -0
- package/dist/adapters/route-rules.js +9 -0
- package/dist/adapters/validate-hosted-resource-routes.d.ts +1 -0
- package/dist/adapters/validate-hosted-resource-routes.js +13 -0
- package/dist/auth/route-auth.d.ts +6 -0
- package/dist/auth/route-auth.js +236 -0
- package/dist/build/compiler-runtime.d.ts +10 -9
- package/dist/build/compiler-runtime.js +58 -2
- package/dist/build/compiler-signal-expression.d.ts +1 -0
- package/dist/build/compiler-signal-expression.js +155 -0
- package/dist/build/expression-rewrites.d.ts +1 -6
- package/dist/build/expression-rewrites.js +61 -65
- package/dist/build/page-component-loop.d.ts +3 -13
- package/dist/build/page-component-loop.js +21 -46
- package/dist/build/page-ir-normalization.d.ts +0 -8
- package/dist/build/page-ir-normalization.js +13 -234
- package/dist/build/page-loop-state.d.ts +6 -9
- package/dist/build/page-loop-state.js +9 -8
- package/dist/build/page-loop.js +27 -22
- package/dist/build/scoped-identifier-rewrite.d.ts +37 -44
- package/dist/build/scoped-identifier-rewrite.js +28 -128
- package/dist/build/server-script.d.ts +3 -1
- package/dist/build/server-script.js +35 -5
- package/dist/build-output-manifest.d.ts +3 -2
- package/dist/build-output-manifest.js +3 -0
- package/dist/build.js +32 -18
- package/dist/component-instance-ir.js +158 -52
- package/dist/dev-build-session.js +20 -6
- package/dist/dev-server.js +152 -55
- package/dist/download-result.d.ts +14 -0
- package/dist/download-result.js +148 -0
- package/dist/framework-components/Image.zen +1 -1
- package/dist/images/materialization-plan.d.ts +1 -0
- package/dist/images/materialization-plan.js +6 -0
- package/dist/images/materialize.d.ts +5 -3
- package/dist/images/materialize.js +24 -109
- package/dist/images/router-manifest.d.ts +1 -0
- package/dist/images/router-manifest.js +49 -0
- package/dist/images/service.d.ts +13 -1
- package/dist/images/service.js +45 -15
- package/dist/index.js +8 -2
- package/dist/manifest.d.ts +15 -1
- package/dist/manifest.js +27 -7
- package/dist/preview.d.ts +13 -4
- package/dist/preview.js +261 -101
- package/dist/request-body.d.ts +1 -0
- package/dist/request-body.js +7 -0
- package/dist/request-origin.d.ts +2 -0
- package/dist/request-origin.js +45 -0
- package/dist/resource-manifest.d.ts +16 -0
- package/dist/resource-manifest.js +53 -0
- package/dist/resource-response.d.ts +34 -0
- package/dist/resource-response.js +71 -0
- package/dist/resource-route-module.d.ts +15 -0
- package/dist/resource-route-module.js +129 -0
- package/dist/route-check-support.d.ts +1 -0
- package/dist/route-check-support.js +4 -0
- package/dist/server-contract.d.ts +29 -6
- package/dist/server-contract.js +304 -42
- package/dist/server-error.d.ts +4 -0
- package/dist/server-error.js +36 -0
- package/dist/server-output.d.ts +4 -1
- package/dist/server-output.js +71 -10
- package/dist/server-runtime/node-server.js +67 -31
- package/dist/server-runtime/route-render.d.ts +27 -3
- package/dist/server-runtime/route-render.js +94 -53
- package/dist/server-script-composition.d.ts +13 -5
- package/dist/server-script-composition.js +29 -11
- package/dist/static-export-paths.d.ts +3 -0
- package/dist/static-export-paths.js +160 -0
- package/package.json +6 -3
|
@@ -1,29 +1,9 @@
|
|
|
1
1
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
|
|
4
|
-
hydrate: () => () => { },
|
|
5
|
-
signal: (value) => value,
|
|
6
|
-
state: (value) => value,
|
|
7
|
-
ref: () => ({ current: null }),
|
|
8
|
-
zeneffect: () => () => { },
|
|
9
|
-
zenEffect: () => () => { },
|
|
10
|
-
zenMount: () => { },
|
|
11
|
-
zenWindow: () => undefined,
|
|
12
|
-
zenDocument: () => undefined,
|
|
13
|
-
zenOn: () => () => { },
|
|
14
|
-
zenResize: () => () => { },
|
|
15
|
-
collectRefs: (...refs) => refs.filter(Boolean)
|
|
16
|
-
};
|
|
3
|
+
import { renderImageHtmlWithPayload, replaceImageMarkers, serializeImageProps } from './runtime.js';
|
|
17
4
|
function escapeRegex(value) {
|
|
18
5
|
return value.replace(/[|\\{}()[\]^$+?.]/g, '\\$&');
|
|
19
6
|
}
|
|
20
|
-
function escapeHtml(value) {
|
|
21
|
-
return String(value ?? '')
|
|
22
|
-
.replace(/&/g, '&')
|
|
23
|
-
.replace(/"/g, '"')
|
|
24
|
-
.replace(/</g, '<')
|
|
25
|
-
.replace(/>/g, '>');
|
|
26
|
-
}
|
|
27
7
|
function parseMarkerSelector(selector) {
|
|
28
8
|
const match = selector.match(/^\[([^\]=]+)=["']([^"']+)["']\]$/);
|
|
29
9
|
if (!match)
|
|
@@ -41,7 +21,7 @@ function upsertAttributeMarkup(attributes, attrName, value) {
|
|
|
41
21
|
if (value === null || value === undefined || value === false || value === '') {
|
|
42
22
|
return attributes.replace(attrPattern, '');
|
|
43
23
|
}
|
|
44
|
-
const serialized = ` ${trimmedName}="${
|
|
24
|
+
const serialized = ` ${trimmedName}="${String(value)}"`;
|
|
45
25
|
if (attrPattern.test(attributes)) {
|
|
46
26
|
return attributes.replace(attrPattern, serialized);
|
|
47
27
|
}
|
|
@@ -52,7 +32,7 @@ function applyAttributeMarker(html, selector, attrName, value) {
|
|
|
52
32
|
if (!parsed)
|
|
53
33
|
return html;
|
|
54
34
|
const markerRe = new RegExp(`<([A-Za-z][\\w:-]*)([^>]*\\s${escapeRegex(parsed.attrName)}=(["'])${escapeRegex(parsed.attrValue)}\\3[^>]*)>`, 'g');
|
|
55
|
-
return html.replace(markerRe, (
|
|
35
|
+
return html.replace(markerRe, (_match, tagName, attrs) => {
|
|
56
36
|
const nextAttrs = upsertAttributeMarkup(String(attrs || ''), attrName, value);
|
|
57
37
|
return `<${tagName}${nextAttrs}>`;
|
|
58
38
|
});
|
|
@@ -65,95 +45,33 @@ function applyInnerHtmlMarker(html, selector, value) {
|
|
|
65
45
|
const replacement = value === null || value === undefined || value === false ? '' : String(value);
|
|
66
46
|
return html.replace(markerRe, (_match, tagName, attrs) => `<${tagName}${attrs}>${replacement}</${tagName}>`);
|
|
67
47
|
}
|
|
68
|
-
function
|
|
69
|
-
|
|
70
|
-
if (/(^|\n)\s*import\s+/m.test(next)) {
|
|
71
|
-
throw new Error('[Zenith:Image] Cannot materialize page asset with unresolved imports');
|
|
72
|
-
}
|
|
73
|
-
next = next.replace(/^export\s+default\s+function\s+/gm, 'function ');
|
|
74
|
-
next = next.replace(/^export\s+function\s+/gm, 'function ');
|
|
75
|
-
next = next.replace(/^export\s+const\s+/gm, 'const ');
|
|
76
|
-
next = next.replace(/^export\s+let\s+/gm, 'let ');
|
|
77
|
-
next = next.replace(/^export\s+var\s+/gm, 'var ');
|
|
78
|
-
next = next.replace(/\bexport\s*\{[^}]*\};?/g, '');
|
|
79
|
-
return next;
|
|
80
|
-
}
|
|
81
|
-
async function evaluatePageModule(assetPath, payload, ssrData, routePathname) {
|
|
82
|
-
const source = stripModuleSyntax(await readFile(assetPath, 'utf8'));
|
|
83
|
-
const runtimeNames = Object.keys(RUNTIME_EXPORTS);
|
|
84
|
-
const evaluator = new Function('runtime', 'payload', 'ssrData', 'routePathname', [
|
|
85
|
-
'"use strict";',
|
|
86
|
-
`const { ${runtimeNames.join(', ')} } = runtime;`,
|
|
87
|
-
'const document = {};',
|
|
88
|
-
'const location = { pathname: routePathname || "/" };',
|
|
89
|
-
'const Document = class ZenithServerDocument {};',
|
|
90
|
-
'const globalThis = {',
|
|
91
|
-
' __zenith_image_runtime: payload,',
|
|
92
|
-
' document,',
|
|
93
|
-
' location,',
|
|
94
|
-
' Document',
|
|
95
|
-
'};',
|
|
96
|
-
'if (ssrData && typeof ssrData === "object" && !Array.isArray(ssrData)) {',
|
|
97
|
-
' globalThis.__zenith_ssr_data = ssrData;',
|
|
98
|
-
'}',
|
|
99
|
-
'globalThis.globalThis = globalThis;',
|
|
100
|
-
'globalThis.window = globalThis;',
|
|
101
|
-
'globalThis.self = globalThis;',
|
|
102
|
-
source,
|
|
103
|
-
'return {',
|
|
104
|
-
' __zenith_markers: typeof __zenith_markers !== "undefined" ? __zenith_markers : [],',
|
|
105
|
-
' __zenith_expression_bindings: typeof __zenith_expression_bindings !== "undefined" ? __zenith_expression_bindings : [],',
|
|
106
|
-
' __zenith_expr_fns: typeof __zenith_expr_fns !== "undefined" ? __zenith_expr_fns : []',
|
|
107
|
-
'};'
|
|
108
|
-
].join('\n'));
|
|
109
|
-
return evaluator(RUNTIME_EXPORTS, payload, ssrData, routePathname);
|
|
48
|
+
function isPlainObject(value) {
|
|
49
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
110
50
|
}
|
|
111
|
-
function
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
params: {},
|
|
115
|
-
props: {},
|
|
116
|
-
ssrData: ssrData || {},
|
|
117
|
-
componentBindings: {},
|
|
118
|
-
zenhtml: null,
|
|
119
|
-
fragment: null
|
|
120
|
-
};
|
|
51
|
+
function hasUnmaterializedImageMarkers(html) {
|
|
52
|
+
const matches = html.match(/<span\b[^>]*\bdata-zx-(?:data-zenith-image|unsafeHTML)=(["'])[^"']+\1[^>]*>/gi) || [];
|
|
53
|
+
return matches.some((tag) => /\sdata-zenith-image=/.test(tag) === false);
|
|
121
54
|
}
|
|
122
55
|
export async function materializeImageMarkup(options) {
|
|
123
|
-
const { html,
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
const namespace = await evaluatePageModule(pageAssetPath, payload, ssrData, routePathname);
|
|
128
|
-
if (!namespace) {
|
|
129
|
-
return html;
|
|
130
|
-
}
|
|
131
|
-
const markers = Array.isArray(namespace.__zenith_markers) ? namespace.__zenith_markers : [];
|
|
132
|
-
const bindings = Array.isArray(namespace.__zenith_expression_bindings) ? namespace.__zenith_expression_bindings : [];
|
|
133
|
-
const exprFns = Array.isArray(namespace.__zenith_expr_fns) ? namespace.__zenith_expr_fns : [];
|
|
134
|
-
if (markers.length === 0 || bindings.length === 0 || exprFns.length === 0) {
|
|
56
|
+
const { html, payload, imageMaterialization = [] } = options;
|
|
57
|
+
const entries = Array.isArray(imageMaterialization) ? imageMaterialization : [];
|
|
58
|
+
if (typeof html !== 'string' || html.length === 0) {
|
|
135
59
|
return html;
|
|
136
60
|
}
|
|
137
|
-
const markerByIndex = new Map(markers.map((marker) => [marker.index, marker]));
|
|
138
61
|
let nextHtml = html;
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
const marker = markerByIndex.get(Number(binding.marker_index));
|
|
142
|
-
const exprFn = Number.isInteger(binding.fn_index) ? exprFns[binding.fn_index] : null;
|
|
143
|
-
if (!marker ||
|
|
144
|
-
typeof exprFn !== 'function' ||
|
|
145
|
-
marker.kind !== 'attr' ||
|
|
146
|
-
typeof marker.selector !== 'string' ||
|
|
147
|
-
marker.selector.includes('data-zx-data-zenith-image') === false &&
|
|
148
|
-
marker.selector.includes('data-zx-innerHTML') === false) {
|
|
62
|
+
for (const entry of entries) {
|
|
63
|
+
if (!entry || typeof entry.selector !== 'string' || !isPlainObject(entry.props)) {
|
|
149
64
|
continue;
|
|
150
65
|
}
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
66
|
+
const encodedProps = serializeImageProps(entry.props);
|
|
67
|
+
const renderedHtml = renderImageHtmlWithPayload(entry.props, payload);
|
|
68
|
+
nextHtml = applyAttributeMarker(nextHtml, entry.selector, 'data-zenith-image', encodedProps);
|
|
69
|
+
nextHtml = applyInnerHtmlMarker(nextHtml, entry.selector, renderedHtml);
|
|
70
|
+
}
|
|
71
|
+
nextHtml = replaceImageMarkers(nextHtml, payload);
|
|
72
|
+
if (hasUnmaterializedImageMarkers(nextHtml)) {
|
|
73
|
+
throw new Error('[Zenith:Image] Unresolved Image markers require a compiler-owned image materialization artifact. ' +
|
|
74
|
+
'Dynamic image props are currently unsupported.');
|
|
157
75
|
}
|
|
158
76
|
return nextHtml;
|
|
159
77
|
}
|
|
@@ -175,11 +93,9 @@ export async function materializeImageMarkupInHtmlFiles(options) {
|
|
|
175
93
|
continue;
|
|
176
94
|
}
|
|
177
95
|
const outputPath = typeof route.output === 'string' ? route.output.replace(/^\//, '') : '';
|
|
178
|
-
|
|
179
|
-
if (!outputPath || !assetPath)
|
|
96
|
+
if (!outputPath)
|
|
180
97
|
continue;
|
|
181
98
|
const fullHtmlPath = join(distDir, outputPath);
|
|
182
|
-
const fullAssetPath = join(distDir, assetPath);
|
|
183
99
|
let html = '';
|
|
184
100
|
try {
|
|
185
101
|
html = await readFile(fullHtmlPath, 'utf8');
|
|
@@ -189,9 +105,8 @@ export async function materializeImageMarkupInHtmlFiles(options) {
|
|
|
189
105
|
}
|
|
190
106
|
const nextHtml = await materializeImageMarkup({
|
|
191
107
|
html,
|
|
192
|
-
pageAssetPath: fullAssetPath,
|
|
193
108
|
payload,
|
|
194
|
-
|
|
109
|
+
imageMaterialization: Array.isArray(route.image_materialization) ? route.image_materialization : []
|
|
195
110
|
});
|
|
196
111
|
if (nextHtml !== html) {
|
|
197
112
|
await writeFile(fullHtmlPath, nextHtml, 'utf8');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function injectImageMaterializationIntoRouterManifest(distDir: any, envelopes: any): Promise<void>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
export async function injectImageMaterializationIntoRouterManifest(distDir, envelopes) {
|
|
4
|
+
const manifestPath = join(distDir, 'assets', 'router-manifest.json');
|
|
5
|
+
let parsed;
|
|
6
|
+
try {
|
|
7
|
+
parsed = JSON.parse(await readFile(manifestPath, 'utf8'));
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const routes = Array.isArray(parsed?.routes) ? parsed.routes : null;
|
|
13
|
+
if (!routes) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const serverMetadataByRoute = new Map();
|
|
17
|
+
for (const envelope of Array.isArray(envelopes) ? envelopes : []) {
|
|
18
|
+
const route = typeof envelope?.route === 'string' ? envelope.route : '';
|
|
19
|
+
if (!route) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
const routeIr = envelope?.ir && typeof envelope.ir === 'object' ? envelope.ir : {};
|
|
23
|
+
serverMetadataByRoute.set(route, {
|
|
24
|
+
guard_module_ref: routeIr.guard_module_ref || null,
|
|
25
|
+
load_module_ref: routeIr.load_module_ref || null,
|
|
26
|
+
action_module_ref: routeIr.action_module_ref || null,
|
|
27
|
+
has_guard: routeIr.has_guard === true,
|
|
28
|
+
has_load: routeIr.has_load === true,
|
|
29
|
+
has_action: routeIr.has_action === true
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
for (const route of routes) {
|
|
33
|
+
const routePath = typeof route?.path === 'string' ? route.path : '';
|
|
34
|
+
if (!routePath) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const serverMetadata = serverMetadataByRoute.get(routePath);
|
|
38
|
+
if (!serverMetadata) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
route.guard_module_ref = serverMetadata.guard_module_ref;
|
|
42
|
+
route.load_module_ref = serverMetadata.load_module_ref;
|
|
43
|
+
route.action_module_ref = serverMetadata.action_module_ref;
|
|
44
|
+
route.has_guard = serverMetadata.has_guard;
|
|
45
|
+
route.has_load = serverMetadata.has_load;
|
|
46
|
+
route.has_action = serverMetadata.has_action;
|
|
47
|
+
}
|
|
48
|
+
await writeFile(manifestPath, `${JSON.stringify(parsed, null, 2)}\n`, 'utf8');
|
|
49
|
+
}
|
package/dist/images/service.d.ts
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
export function buildImageArtifacts(options: any): Promise<{
|
|
2
2
|
manifest: {};
|
|
3
3
|
}>;
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* @param {Request | { url?: string } | null | undefined} request
|
|
6
|
+
* @param {{ requestUrl?: URL | string, projectRoot: string, config?: Record<string, unknown> }} options
|
|
7
|
+
* @returns {Promise<Response>}
|
|
8
|
+
*/
|
|
9
|
+
export function handleImageFetchRequest(request: Request | {
|
|
10
|
+
url?: string;
|
|
11
|
+
} | null | undefined, options: {
|
|
12
|
+
requestUrl?: URL | string;
|
|
13
|
+
projectRoot: string;
|
|
14
|
+
config?: Record<string, unknown>;
|
|
15
|
+
}): Promise<Response>;
|
|
16
|
+
export function handleImageRequest(_req: any, res: any, options: any): Promise<boolean>;
|
package/dist/images/service.js
CHANGED
|
@@ -220,7 +220,29 @@ function remoteCachePaths(cacheDir, cacheKey) {
|
|
|
220
220
|
metaPath: join(cacheDir, `${cacheKey}.json`)
|
|
221
221
|
};
|
|
222
222
|
}
|
|
223
|
-
|
|
223
|
+
function createJsonResponse(status, payload) {
|
|
224
|
+
return new Response(JSON.stringify(payload), {
|
|
225
|
+
status,
|
|
226
|
+
headers: {
|
|
227
|
+
'Content-Type': 'application/json'
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
function createBufferResponse(status, contentType, buffer, cacheSeconds) {
|
|
232
|
+
return new Response(buffer, {
|
|
233
|
+
status,
|
|
234
|
+
headers: {
|
|
235
|
+
'Content-Type': contentType,
|
|
236
|
+
'Cache-Control': `public, max-age=${cacheSeconds}`
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
async function sendResponse(res, response) {
|
|
241
|
+
res.writeHead(response.status, Object.fromEntries(response.headers.entries()));
|
|
242
|
+
const body = await response.arrayBuffer();
|
|
243
|
+
res.end(Buffer.from(body));
|
|
244
|
+
}
|
|
245
|
+
async function createImageResponse(options) {
|
|
224
246
|
const { requestUrl, projectRoot, config: rawConfig } = options;
|
|
225
247
|
const config = normalizeImageConfig(rawConfig);
|
|
226
248
|
const url = requestUrl instanceof URL ? requestUrl : new URL(String(requestUrl));
|
|
@@ -230,14 +252,10 @@ export async function handleImageRequest(req, res, options) {
|
|
|
230
252
|
const format = normalizeImageFormat(url.searchParams.get('f') || '');
|
|
231
253
|
const quality = Number.isInteger(requestedQuality) && requestedQuality > 0 ? requestedQuality : config.quality;
|
|
232
254
|
if (!remoteUrl) {
|
|
233
|
-
|
|
234
|
-
res.end(JSON.stringify({ error: 'missing_url' }));
|
|
235
|
-
return true;
|
|
255
|
+
return createJsonResponse(400, { error: 'missing_url' });
|
|
236
256
|
}
|
|
237
257
|
if (!Number.isInteger(width) || width <= 0) {
|
|
238
|
-
|
|
239
|
-
res.end(JSON.stringify({ error: 'invalid_width' }));
|
|
240
|
-
return true;
|
|
258
|
+
return createJsonResponse(400, { error: 'invalid_width' });
|
|
241
259
|
}
|
|
242
260
|
try {
|
|
243
261
|
const remote = await validateRemoteTarget(remoteUrl, config);
|
|
@@ -253,8 +271,7 @@ export async function handleImageRequest(req, res, options) {
|
|
|
253
271
|
const contentType = typeof parsedMeta?.contentType === 'string'
|
|
254
272
|
? parsedMeta.contentType
|
|
255
273
|
: mimeTypeForFormat(format || 'jpg');
|
|
256
|
-
|
|
257
|
-
return true;
|
|
274
|
+
return createBufferResponse(200, contentType, cached, config.minimumCacheTTL);
|
|
258
275
|
}
|
|
259
276
|
const response = await fetch(remote, {
|
|
260
277
|
headers: {
|
|
@@ -288,15 +305,28 @@ export async function handleImageRequest(req, res, options) {
|
|
|
288
305
|
format: targetFormat
|
|
289
306
|
}, null, 2)}\n`, 'utf8')
|
|
290
307
|
]);
|
|
291
|
-
|
|
292
|
-
return true;
|
|
308
|
+
return createBufferResponse(200, mimeTypeForFormat(targetFormat), output, config.minimumCacheTTL);
|
|
293
309
|
}
|
|
294
310
|
catch (error) {
|
|
295
|
-
|
|
296
|
-
res.end(JSON.stringify({
|
|
311
|
+
return createJsonResponse(400, {
|
|
297
312
|
error: 'image_request_failed',
|
|
298
313
|
message: error instanceof Error ? error.message : String(error)
|
|
299
|
-
})
|
|
300
|
-
return true;
|
|
314
|
+
});
|
|
301
315
|
}
|
|
302
316
|
}
|
|
317
|
+
/**
|
|
318
|
+
* @param {Request | { url?: string } | null | undefined} request
|
|
319
|
+
* @param {{ requestUrl?: URL | string, projectRoot: string, config?: Record<string, unknown> }} options
|
|
320
|
+
* @returns {Promise<Response>}
|
|
321
|
+
*/
|
|
322
|
+
export async function handleImageFetchRequest(request, options) {
|
|
323
|
+
return createImageResponse({
|
|
324
|
+
...options,
|
|
325
|
+
requestUrl: request?.url || options?.requestUrl
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
export async function handleImageRequest(_req, res, options) {
|
|
329
|
+
const response = await createImageResponse(options);
|
|
330
|
+
await sendResponse(res, response);
|
|
331
|
+
return true;
|
|
332
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -88,9 +88,15 @@ export async function cli(args, cwd) {
|
|
|
88
88
|
printUsage(logger);
|
|
89
89
|
process.exit(0);
|
|
90
90
|
}
|
|
91
|
-
if (!command
|
|
91
|
+
if (!command) {
|
|
92
92
|
printUsage(logger);
|
|
93
|
-
process.exit(
|
|
93
|
+
process.exit(0);
|
|
94
|
+
}
|
|
95
|
+
if (!COMMANDS.includes(command)) {
|
|
96
|
+
logger.print(`Unknown command: ${command}`);
|
|
97
|
+
logger.print('');
|
|
98
|
+
printUsage(logger);
|
|
99
|
+
process.exit(1);
|
|
94
100
|
}
|
|
95
101
|
const projectRoot = resolve(cwd || process.cwd());
|
|
96
102
|
const config = await loadConfig(projectRoot);
|
package/dist/manifest.d.ts
CHANGED
|
@@ -2,9 +2,16 @@
|
|
|
2
2
|
* @typedef {{
|
|
3
3
|
* path: string,
|
|
4
4
|
* file: string,
|
|
5
|
+
* route_kind?: 'page' | 'resource',
|
|
5
6
|
* path_kind: 'static' | 'dynamic',
|
|
6
7
|
* render_mode: 'prerender' | 'server',
|
|
7
|
-
* params: string[]
|
|
8
|
+
* params: string[],
|
|
9
|
+
* server_script?: string,
|
|
10
|
+
* server_script_path?: string,
|
|
11
|
+
* has_guard?: boolean,
|
|
12
|
+
* has_load?: boolean,
|
|
13
|
+
* has_action?: boolean,
|
|
14
|
+
* export_paths?: string[]
|
|
8
15
|
* }} ManifestEntry
|
|
9
16
|
*/
|
|
10
17
|
/**
|
|
@@ -29,7 +36,14 @@ export function serializeManifest(entries: ManifestEntry[]): string;
|
|
|
29
36
|
export type ManifestEntry = {
|
|
30
37
|
path: string;
|
|
31
38
|
file: string;
|
|
39
|
+
route_kind?: "page" | "resource";
|
|
32
40
|
path_kind: "static" | "dynamic";
|
|
33
41
|
render_mode: "prerender" | "server";
|
|
34
42
|
params: string[];
|
|
43
|
+
server_script?: string;
|
|
44
|
+
server_script_path?: string;
|
|
45
|
+
has_guard?: boolean;
|
|
46
|
+
has_load?: boolean;
|
|
47
|
+
has_action?: boolean;
|
|
48
|
+
export_paths?: string[];
|
|
35
49
|
};
|
package/dist/manifest.js
CHANGED
|
@@ -18,14 +18,23 @@ import { readFileSync } from 'node:fs';
|
|
|
18
18
|
import { readdir, stat } from 'node:fs/promises';
|
|
19
19
|
import { join, relative, sep, basename, extname, dirname } from 'node:path';
|
|
20
20
|
import { extractServerScript } from './build/server-script.js';
|
|
21
|
+
import { analyzeResourceRouteModule, isResourceRouteFile } from './resource-route-module.js';
|
|
21
22
|
import { composeServerScriptEnvelope, resolveAdjacentServerModules } from './server-script-composition.js';
|
|
23
|
+
import { validateStaticExportPaths } from './static-export-paths.js';
|
|
22
24
|
/**
|
|
23
25
|
* @typedef {{
|
|
24
26
|
* path: string,
|
|
25
27
|
* file: string,
|
|
28
|
+
* route_kind?: 'page' | 'resource',
|
|
26
29
|
* path_kind: 'static' | 'dynamic',
|
|
27
30
|
* render_mode: 'prerender' | 'server',
|
|
28
|
-
* params: string[]
|
|
31
|
+
* params: string[],
|
|
32
|
+
* server_script?: string,
|
|
33
|
+
* server_script_path?: string,
|
|
34
|
+
* has_guard?: boolean,
|
|
35
|
+
* has_load?: boolean,
|
|
36
|
+
* has_action?: boolean,
|
|
37
|
+
* export_paths?: string[]
|
|
29
38
|
* }} ManifestEntry
|
|
30
39
|
*/
|
|
31
40
|
/**
|
|
@@ -75,32 +84,41 @@ async function _scanDir(dir, root, ext, compilerOpts) {
|
|
|
75
84
|
}
|
|
76
85
|
else if (item.endsWith(ext)) {
|
|
77
86
|
const routePath = _fileToRoute(fullPath, root, ext);
|
|
78
|
-
entries.push(
|
|
87
|
+
entries.push(buildPageManifestEntry({
|
|
79
88
|
fullPath,
|
|
80
89
|
root,
|
|
81
90
|
routePath,
|
|
82
91
|
compilerOpts
|
|
83
92
|
}));
|
|
84
93
|
}
|
|
94
|
+
else if (isResourceRouteFile(item)) {
|
|
95
|
+
entries.push(analyzeResourceRouteModule(fullPath, root));
|
|
96
|
+
}
|
|
85
97
|
}
|
|
86
98
|
return entries;
|
|
87
99
|
}
|
|
88
|
-
function
|
|
100
|
+
function buildPageManifestEntry({ fullPath, root, routePath, compilerOpts }) {
|
|
89
101
|
const rawSource = readFileSync(fullPath, 'utf8');
|
|
90
102
|
const inlineServerScript = extractServerScript(rawSource, fullPath, compilerOpts).serverScript;
|
|
91
|
-
const { guardPath, loadPath } = resolveAdjacentServerModules(fullPath);
|
|
103
|
+
const { guardPath, loadPath, actionPath } = resolveAdjacentServerModules(fullPath);
|
|
92
104
|
const composed = composeServerScriptEnvelope({
|
|
93
105
|
sourceFile: fullPath,
|
|
94
106
|
inlineServerScript,
|
|
95
107
|
adjacentGuardPath: guardPath,
|
|
96
|
-
adjacentLoadPath: loadPath
|
|
108
|
+
adjacentLoadPath: loadPath,
|
|
109
|
+
adjacentActionPath: actionPath
|
|
97
110
|
});
|
|
111
|
+
const exportPaths = Array.isArray(composed.serverScript?.export_paths)
|
|
112
|
+
? validateStaticExportPaths(routePath, composed.serverScript.export_paths, fullPath)
|
|
113
|
+
: [];
|
|
98
114
|
return {
|
|
99
115
|
path: routePath,
|
|
100
116
|
file: relative(root, fullPath),
|
|
117
|
+
route_kind: 'page',
|
|
101
118
|
path_kind: _isDynamic(routePath) ? 'dynamic' : 'static',
|
|
102
119
|
render_mode: composed.serverScript && composed.serverScript.prerender !== true ? 'server' : 'prerender',
|
|
103
|
-
params: extractRouteParams(routePath)
|
|
120
|
+
params: extractRouteParams(routePath),
|
|
121
|
+
...(exportPaths.length > 0 ? { export_paths: exportPaths } : {})
|
|
104
122
|
};
|
|
105
123
|
}
|
|
106
124
|
function extractRouteParams(routePath) {
|
|
@@ -324,7 +342,9 @@ function segmentWeight(segment) {
|
|
|
324
342
|
* @returns {string}
|
|
325
343
|
*/
|
|
326
344
|
export function serializeManifest(entries) {
|
|
327
|
-
const lines = entries
|
|
345
|
+
const lines = entries
|
|
346
|
+
.filter((entry) => entry?.route_kind !== 'resource')
|
|
347
|
+
.map((e) => {
|
|
328
348
|
const hasParams = _isDynamic(e.path);
|
|
329
349
|
const loader = hasParams
|
|
330
350
|
? `(params) => import('./pages/${e.file}')`
|
package/dist/preview.d.ts
CHANGED
|
@@ -37,20 +37,27 @@ export function createPreviewServer(options: {
|
|
|
37
37
|
* @returns {Promise<PreviewRoute[]>}
|
|
38
38
|
*/
|
|
39
39
|
export function loadRouteManifest(distDir: string): Promise<PreviewRoute[]>;
|
|
40
|
+
export function loadRouteSurfaceState(distDir: any, fallbackBasePath?: string): Promise<{
|
|
41
|
+
basePath: string;
|
|
42
|
+
pageRoutes: any;
|
|
43
|
+
resourceRoutes: any[];
|
|
44
|
+
}>;
|
|
40
45
|
/**
|
|
41
|
-
* @param {{ source: string, sourcePath: string, params: Record<string, string>, requestUrl?: string, requestMethod?: string, requestHeaders?: Record<string, string | string[] | undefined>, routePattern?: string, routeFile?: string, routeId?: string }} input
|
|
42
|
-
* @returns {Promise<{ result: { kind: string, [key: string]: unknown }, trace: { guard: string, load: string } }>}
|
|
46
|
+
* @param {{ source: string, sourcePath: string, params: Record<string, string>, requestUrl?: string, requestMethod?: string, requestHeaders?: Record<string, string | string[] | undefined>, requestBodyBuffer?: Buffer | null, routePattern?: string, routeFile?: string, routeId?: string, routeKind?: 'page' | 'resource' }} input
|
|
47
|
+
* @returns {Promise<{ result: { kind: string, [key: string]: unknown }, trace: { guard: string, action: string, load: string }, status?: number, setCookies?: string[] }>}
|
|
43
48
|
*/
|
|
44
|
-
export function executeServerRoute({ source, sourcePath, params, requestUrl, requestMethod, requestHeaders, routePattern, routeFile, routeId, guardOnly }: {
|
|
49
|
+
export function executeServerRoute({ source, sourcePath, params, requestUrl, requestMethod, requestHeaders, requestBodyBuffer, routePattern, routeFile, routeId, routeKind, guardOnly }: {
|
|
45
50
|
source: string;
|
|
46
51
|
sourcePath: string;
|
|
47
52
|
params: Record<string, string>;
|
|
48
53
|
requestUrl?: string;
|
|
49
54
|
requestMethod?: string;
|
|
50
55
|
requestHeaders?: Record<string, string | string[] | undefined>;
|
|
56
|
+
requestBodyBuffer?: Buffer | null;
|
|
51
57
|
routePattern?: string;
|
|
52
58
|
routeFile?: string;
|
|
53
59
|
routeId?: string;
|
|
60
|
+
routeKind?: "page" | "resource";
|
|
54
61
|
}): Promise<{
|
|
55
62
|
result: {
|
|
56
63
|
kind: string;
|
|
@@ -58,10 +65,12 @@ export function executeServerRoute({ source, sourcePath, params, requestUrl, req
|
|
|
58
65
|
};
|
|
59
66
|
trace: {
|
|
60
67
|
guard: string;
|
|
68
|
+
action: string;
|
|
61
69
|
load: string;
|
|
62
70
|
};
|
|
71
|
+
status?: number;
|
|
72
|
+
setCookies?: string[];
|
|
63
73
|
}>;
|
|
64
|
-
export function defaultRouteDenyMessage(status: any): "Unauthorized" | "Forbidden" | "Not Found" | "Internal Server Error";
|
|
65
74
|
/**
|
|
66
75
|
* @param {{ source: string, sourcePath: string, params: Record<string, string>, requestUrl?: string, requestMethod?: string, requestHeaders?: Record<string, string | string[] | undefined>, routePattern?: string, routeFile?: string, routeId?: string }} input
|
|
67
76
|
* @returns {Promise<Record<string, unknown> | null>}
|