@zenithbuild/cli 0.7.4 → 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 +5 -3
- package/dist/adapters/adapter-netlify.d.ts +1 -1
- package/dist/adapters/adapter-netlify.js +56 -14
- 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 -14
- 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 +1 -1
- package/dist/build/compiler-runtime.js +8 -2
- package/dist/build/page-loop-state.js +1 -1
- package/dist/build/server-script.d.ts +2 -1
- package/dist/build/server-script.js +7 -3
- package/dist/build-output-manifest.d.ts +3 -2
- package/dist/build-output-manifest.js +3 -0
- package/dist/build.js +29 -17
- package/dist/dev-server.js +79 -25
- package/dist/download-result.d.ts +14 -0
- package/dist/download-result.js +148 -0
- package/dist/images/service.d.ts +13 -1
- package/dist/images/service.js +45 -15
- package/dist/manifest.d.ts +15 -1
- package/dist/manifest.js +24 -5
- package/dist/preview.d.ts +11 -3
- package/dist/preview.js +188 -62
- package/dist/request-body.d.ts +0 -1
- package/dist/request-body.js +0 -6
- 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.js +1 -1
- package/dist/server-contract.d.ts +24 -16
- package/dist/server-contract.js +217 -25
- package/dist/server-error.d.ts +1 -1
- package/dist/server-error.js +2 -0
- package/dist/server-output.d.ts +2 -1
- package/dist/server-output.js +59 -11
- package/dist/server-runtime/node-server.js +34 -4
- package/dist/server-runtime/route-render.d.ts +25 -1
- package/dist/server-runtime/route-render.js +81 -29
- package/dist/server-script-composition.d.ts +4 -2
- package/dist/server-script-composition.js +6 -3
- package/dist/static-export-paths.d.ts +3 -0
- package/dist/static-export-paths.js +160 -0
- package/package.json +3 -3
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { resolveRequestRoute } from './server/resolve-request-route.js';
|
|
2
|
+
function skipWhitespace(source, start) {
|
|
3
|
+
let index = start;
|
|
4
|
+
while (index < source.length) {
|
|
5
|
+
const char = source[index];
|
|
6
|
+
if (/\s/.test(char)) {
|
|
7
|
+
index += 1;
|
|
8
|
+
continue;
|
|
9
|
+
}
|
|
10
|
+
if (source.startsWith('//', index)) {
|
|
11
|
+
const nextLine = source.indexOf('\n', index + 2);
|
|
12
|
+
return nextLine === -1 ? source.length : skipWhitespace(source, nextLine + 1);
|
|
13
|
+
}
|
|
14
|
+
if (source.startsWith('/*', index)) {
|
|
15
|
+
const close = source.indexOf('*/', index + 2);
|
|
16
|
+
if (close === -1) {
|
|
17
|
+
throw new Error('[Zenith] Unterminated block comment in exportPaths literal.');
|
|
18
|
+
}
|
|
19
|
+
index = close + 2;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
return index;
|
|
25
|
+
}
|
|
26
|
+
function parseQuotedStringLiteral(source, start, sourceFile) {
|
|
27
|
+
const quote = source[start];
|
|
28
|
+
if (quote !== '"' && quote !== '\'') {
|
|
29
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths must be a literal array of string paths.`);
|
|
30
|
+
}
|
|
31
|
+
let index = start + 1;
|
|
32
|
+
let value = '';
|
|
33
|
+
while (index < source.length) {
|
|
34
|
+
const char = source[index];
|
|
35
|
+
if (char === '\\') {
|
|
36
|
+
const next = source[index + 1];
|
|
37
|
+
if (next === undefined) {
|
|
38
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths contains an invalid escape sequence.`);
|
|
39
|
+
}
|
|
40
|
+
value += char + next;
|
|
41
|
+
index += 2;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (char === quote) {
|
|
45
|
+
try {
|
|
46
|
+
return {
|
|
47
|
+
value: JSON.parse(`"${value.replace(/"/g, '\\"')}"`),
|
|
48
|
+
nextIndex: index + 1
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths contains an invalid string literal.`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (char === '\n' || char === '\r') {
|
|
56
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths string literals must stay on one line.`);
|
|
57
|
+
}
|
|
58
|
+
value += char;
|
|
59
|
+
index += 1;
|
|
60
|
+
}
|
|
61
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths contains an unterminated string literal.`);
|
|
62
|
+
}
|
|
63
|
+
function parseStringArrayLiteral(source, start, sourceFile) {
|
|
64
|
+
if (source[start] !== '[') {
|
|
65
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths must be assigned a literal array of string paths.`);
|
|
66
|
+
}
|
|
67
|
+
const values = [];
|
|
68
|
+
let index = start + 1;
|
|
69
|
+
while (index < source.length) {
|
|
70
|
+
index = skipWhitespace(source, index);
|
|
71
|
+
if (source[index] === ']') {
|
|
72
|
+
return { values, nextIndex: index + 1 };
|
|
73
|
+
}
|
|
74
|
+
const parsed = parseQuotedStringLiteral(source, index, sourceFile);
|
|
75
|
+
values.push(parsed.value);
|
|
76
|
+
index = skipWhitespace(source, parsed.nextIndex);
|
|
77
|
+
if (source[index] === ',') {
|
|
78
|
+
index += 1;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (source[index] === ']') {
|
|
82
|
+
return { values, nextIndex: index + 1 };
|
|
83
|
+
}
|
|
84
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths must be a comma-delimited literal array of string paths.`);
|
|
85
|
+
}
|
|
86
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths array is missing a closing "]".`);
|
|
87
|
+
}
|
|
88
|
+
function normalizeConcretePath(value, sourceFile) {
|
|
89
|
+
if (typeof value !== 'string') {
|
|
90
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths entries must be strings.`);
|
|
91
|
+
}
|
|
92
|
+
const trimmed = value.trim();
|
|
93
|
+
if (!trimmed.startsWith('/')) {
|
|
94
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths entries must start with "/".`);
|
|
95
|
+
}
|
|
96
|
+
if (trimmed.includes('://') || trimmed.startsWith('//')) {
|
|
97
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths entries must be same-origin pathnames.`);
|
|
98
|
+
}
|
|
99
|
+
if (trimmed.includes('?') || trimmed.includes('#') || /[\r\n]/.test(trimmed)) {
|
|
100
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths entries must be pathnames without query or hash.`);
|
|
101
|
+
}
|
|
102
|
+
const segments = trimmed
|
|
103
|
+
.split('/')
|
|
104
|
+
.filter(Boolean)
|
|
105
|
+
.map((segment) => segment.trim())
|
|
106
|
+
.filter((segment) => segment.length > 0);
|
|
107
|
+
for (const segment of segments) {
|
|
108
|
+
if (segment === '.' || segment === '..') {
|
|
109
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths entries must not contain path traversal segments.`);
|
|
110
|
+
}
|
|
111
|
+
if (segment.startsWith(':') || segment.startsWith('*')) {
|
|
112
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths entries must be concrete public URLs.`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return segments.length === 0 ? '/' : `/${segments.join('/')}`;
|
|
116
|
+
}
|
|
117
|
+
export function extractStaticExportPaths(source, sourceFile) {
|
|
118
|
+
const match = /\bexport\s+const\s+exportPaths\b/.exec(String(source || ''));
|
|
119
|
+
if (!match) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
const equalsIndex = String(source || '').indexOf('=', match.index + match[0].length);
|
|
123
|
+
if (equalsIndex === -1) {
|
|
124
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths must use the form export const exportPaths = [...].`);
|
|
125
|
+
}
|
|
126
|
+
const valueStart = skipWhitespace(String(source || ''), equalsIndex + 1);
|
|
127
|
+
const { values } = parseStringArrayLiteral(String(source || ''), valueStart, sourceFile);
|
|
128
|
+
return values.map((value) => normalizeConcretePath(value, sourceFile));
|
|
129
|
+
}
|
|
130
|
+
export function validateStaticExportPaths(routePath, exportPaths, sourceFile) {
|
|
131
|
+
if (!Array.isArray(exportPaths)) {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
const deduped = [];
|
|
135
|
+
const seen = new Set();
|
|
136
|
+
for (const rawPath of exportPaths) {
|
|
137
|
+
const concretePath = normalizeConcretePath(rawPath, sourceFile);
|
|
138
|
+
if (seen.has(concretePath)) {
|
|
139
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths contains a duplicate path "${concretePath}".`);
|
|
140
|
+
}
|
|
141
|
+
seen.add(concretePath);
|
|
142
|
+
const resolved = resolveRequestRoute(new URL(concretePath, 'http://localhost'), [{ path: routePath }]);
|
|
143
|
+
if (!resolved.matched || resolved.route?.path !== routePath) {
|
|
144
|
+
throw new Error(`[Zenith] ${sourceFile}: exportPaths entry "${concretePath}" does not match route "${routePath}".`);
|
|
145
|
+
}
|
|
146
|
+
deduped.push(concretePath);
|
|
147
|
+
}
|
|
148
|
+
return deduped;
|
|
149
|
+
}
|
|
150
|
+
export function toStaticHtmlFilePath(pathname) {
|
|
151
|
+
const normalized = normalizeConcretePath(pathname, 'static-export');
|
|
152
|
+
if (normalized === '/') {
|
|
153
|
+
return 'index.html';
|
|
154
|
+
}
|
|
155
|
+
const relativePath = normalized.replace(/^\//, '');
|
|
156
|
+
if (/\.[a-zA-Z0-9]+$/.test(relativePath)) {
|
|
157
|
+
return relativePath;
|
|
158
|
+
}
|
|
159
|
+
return `${relativePath}/index.html`;
|
|
160
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenithbuild/cli",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "Deterministic project orchestrator for Zenith framework",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"prepublishOnly": "npm run build"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@zenithbuild/compiler": "0.7.
|
|
42
|
-
"@zenithbuild/bundler": "0.7.
|
|
41
|
+
"@zenithbuild/compiler": "0.7.5",
|
|
42
|
+
"@zenithbuild/bundler": "0.7.5",
|
|
43
43
|
"picocolors": "^1.1.1",
|
|
44
44
|
"sharp": "^0.34.4"
|
|
45
45
|
},
|