@zenithbuild/cli 0.6.13 → 0.6.17
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/dist/dev-server.js +149 -4
- package/package.json +2 -2
package/dist/dev-server.js
CHANGED
|
@@ -115,6 +115,112 @@ export async function createDevServer(options) {
|
|
|
115
115
|
...details
|
|
116
116
|
});
|
|
117
117
|
}
|
|
118
|
+
function _classifyNotFound(pathname) {
|
|
119
|
+
const lower = String(pathname || '').toLowerCase();
|
|
120
|
+
if (lower.startsWith('/__zenith_dev/'))
|
|
121
|
+
return 'dev_internal';
|
|
122
|
+
if (lower.startsWith('/__zenith/'))
|
|
123
|
+
return 'zenith_internal';
|
|
124
|
+
if (lower.startsWith('/_assets/')
|
|
125
|
+
|| lower.startsWith('/assets/')
|
|
126
|
+
|| lower.endsWith('.css')
|
|
127
|
+
|| lower.endsWith('.js')
|
|
128
|
+
|| lower.endsWith('.map')
|
|
129
|
+
|| lower.endsWith('.json')) {
|
|
130
|
+
return 'asset';
|
|
131
|
+
}
|
|
132
|
+
return 'page';
|
|
133
|
+
}
|
|
134
|
+
function _routeFileHint(pathname) {
|
|
135
|
+
const normalized = String(pathname || '/').replace(/\/+$/, '');
|
|
136
|
+
if (normalized === '' || normalized === '/') {
|
|
137
|
+
return 'src/pages/index.zen';
|
|
138
|
+
}
|
|
139
|
+
return `src/pages${normalized}.zen`;
|
|
140
|
+
}
|
|
141
|
+
function _infer404Cause(category) {
|
|
142
|
+
if (category === 'dev_internal' || category === 'zenith_internal') {
|
|
143
|
+
if (buildStatus === 'error') {
|
|
144
|
+
return 'initial build failed';
|
|
145
|
+
}
|
|
146
|
+
return 'unknown Zenith dev endpoint';
|
|
147
|
+
}
|
|
148
|
+
if (category === 'asset') {
|
|
149
|
+
if (buildStatus === 'error') {
|
|
150
|
+
return 'initial build failed';
|
|
151
|
+
}
|
|
152
|
+
return 'asset not emitted by latest build';
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
function _looksLikeJsonRequest(req, pathname) {
|
|
157
|
+
const accept = String(req.headers.accept || '').toLowerCase();
|
|
158
|
+
const secFetchDest = String(req.headers['sec-fetch-dest'] || '').toLowerCase();
|
|
159
|
+
if (accept.includes('application/json') || accept.includes('application/problem+json')) {
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
if (pathname.endsWith('.json')) {
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
return secFetchDest === 'empty';
|
|
166
|
+
}
|
|
167
|
+
function _buildNotFoundPayload(pathname, category, cause) {
|
|
168
|
+
const payload = {
|
|
169
|
+
kind: 'zenith_dev_not_found',
|
|
170
|
+
category,
|
|
171
|
+
requestedPath: pathname,
|
|
172
|
+
buildId,
|
|
173
|
+
buildStatus,
|
|
174
|
+
cause: cause || ''
|
|
175
|
+
};
|
|
176
|
+
if (category === 'asset') {
|
|
177
|
+
payload.hint = buildStatus === 'error'
|
|
178
|
+
? 'Dev server is running but initial build failed; fix compile errors and refresh.'
|
|
179
|
+
: 'Check emitted assets in dist and verify the requested path.';
|
|
180
|
+
if (pathname.endsWith('.css')) {
|
|
181
|
+
payload.expectedCssHref = currentCssHref || null;
|
|
182
|
+
payload.hint = buildStatus === 'error'
|
|
183
|
+
? `Dev server is running but initial build failed; expected CSS at ${currentCssHref || '<none>'}.`
|
|
184
|
+
: `Requested CSS is missing; expected current href ${currentCssHref || '<none>'}.`;
|
|
185
|
+
}
|
|
186
|
+
return payload;
|
|
187
|
+
}
|
|
188
|
+
if (category === 'dev_internal' || category === 'zenith_internal') {
|
|
189
|
+
payload.hint = buildStatus === 'error'
|
|
190
|
+
? 'Dev server is running but initial build failed; restart after fixing compile errors.'
|
|
191
|
+
: 'Check Zenith dev endpoint path and dev client version.';
|
|
192
|
+
payload.docsLink = '/docs/documentation/contracts/hmr-v1-contract.md';
|
|
193
|
+
return payload;
|
|
194
|
+
}
|
|
195
|
+
const routeFile = _routeFileHint(pathname);
|
|
196
|
+
payload.routeFile = routeFile;
|
|
197
|
+
payload.cause = `no route file found at ${routeFile}`;
|
|
198
|
+
payload.hint = `Create ${routeFile} or verify router manifest output.`;
|
|
199
|
+
return payload;
|
|
200
|
+
}
|
|
201
|
+
function _renderNotFoundHtml(payload) {
|
|
202
|
+
const escaped = (value) => String(value || '')
|
|
203
|
+
.replaceAll('&', '&')
|
|
204
|
+
.replaceAll('<', '<')
|
|
205
|
+
.replaceAll('>', '>');
|
|
206
|
+
const details = [
|
|
207
|
+
`Requested: ${payload.requestedPath}`,
|
|
208
|
+
`Category: ${payload.category}`,
|
|
209
|
+
`Build: ${payload.buildStatus} (id=${payload.buildId})`,
|
|
210
|
+
`Cause: ${payload.cause}`,
|
|
211
|
+
payload.expectedCssHref ? `Expected CSS href: ${payload.expectedCssHref}` : '',
|
|
212
|
+
`Hint: ${payload.hint || 'Inspect dev server output.'}`,
|
|
213
|
+
payload.docsLink ? `Docs: ${payload.docsLink}` : ''
|
|
214
|
+
].filter(Boolean).join('\n');
|
|
215
|
+
return [
|
|
216
|
+
'<!DOCTYPE html>',
|
|
217
|
+
'<html><head><meta charset="utf-8"><title>Zenith Dev 404</title></head>',
|
|
218
|
+
'<body style="font-family: ui-monospace, SFMono-Regular, Menlo, monospace; padding: 20px; background: #101216; color: #e6edf3;">',
|
|
219
|
+
'<h1 style="margin-top:0;">Zenith Dev 404</h1>',
|
|
220
|
+
`<pre style="white-space: pre-wrap; line-height: 1.5;">${escaped(details)}</pre>`,
|
|
221
|
+
'</body></html>'
|
|
222
|
+
].join('');
|
|
223
|
+
}
|
|
118
224
|
function _pickCssAsset(assets) {
|
|
119
225
|
if (!Array.isArray(assets) || assets.length === 0) {
|
|
120
226
|
return '';
|
|
@@ -303,6 +409,21 @@ export async function createDevServer(options) {
|
|
|
303
409
|
return;
|
|
304
410
|
}
|
|
305
411
|
if (pathname === '/__zenith_dev/styles.css') {
|
|
412
|
+
if (buildStatus === 'error') {
|
|
413
|
+
const reason = typeof buildError?.message === 'string' && buildError.message.length > 0
|
|
414
|
+
? buildError.message
|
|
415
|
+
: 'initial build failed';
|
|
416
|
+
const summary = reason.length > 280 ? `${reason.slice(0, 277)}...` : reason;
|
|
417
|
+
res.writeHead(503, {
|
|
418
|
+
'Content-Type': 'text/css; charset=utf-8',
|
|
419
|
+
'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate',
|
|
420
|
+
'Pragma': 'no-cache',
|
|
421
|
+
'Expires': '0',
|
|
422
|
+
'X-Zenith-Dev-Error': 'build-failed'
|
|
423
|
+
});
|
|
424
|
+
res.end(`/* zenith-dev: css unavailable because build failed */\n/* cause: ${summary} */\n/* expected href: ${currentCssHref || '<none>'} */`);
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
306
427
|
if (typeof currentCssContent === 'string' && currentCssContent.length > 0) {
|
|
307
428
|
res.writeHead(200, {
|
|
308
429
|
'Content-Type': 'text/css; charset=utf-8',
|
|
@@ -504,14 +625,38 @@ export async function createDevServer(options) {
|
|
|
504
625
|
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
505
626
|
res.end(content);
|
|
506
627
|
}
|
|
507
|
-
catch {
|
|
628
|
+
catch (error) {
|
|
629
|
+
const category = _classifyNotFound(pathname);
|
|
630
|
+
const cause = _infer404Cause(category);
|
|
631
|
+
const payload = _buildNotFoundPayload(pathname, category, cause);
|
|
632
|
+
if (buildStatus === 'error' && typeof buildError?.message === 'string') {
|
|
633
|
+
payload.buildError = buildError.message.length > 600
|
|
634
|
+
? `${buildError.message.slice(0, 597)}...`
|
|
635
|
+
: buildError.message;
|
|
636
|
+
}
|
|
637
|
+
const displayCategory = category === 'page' ? 'page' : 'asset';
|
|
638
|
+
logger.warn(`404 ${displayCategory}: ${pathname} (buildId=${buildId}) -> cause: ${payload.cause || cause || 'not found'}`);
|
|
508
639
|
_trace404(req, url, {
|
|
509
640
|
reason: 'not_found',
|
|
641
|
+
category,
|
|
642
|
+
cause: payload.cause || cause || 'not_found',
|
|
510
643
|
staticRoot: staticRootFor404,
|
|
511
|
-
resolvedPath: resolvedPathFor404
|
|
644
|
+
resolvedPath: resolvedPathFor404,
|
|
645
|
+
error: error instanceof Error ? error.message : String(error || '')
|
|
646
|
+
});
|
|
647
|
+
if (_looksLikeJsonRequest(req, pathname)) {
|
|
648
|
+
res.writeHead(404, {
|
|
649
|
+
'Content-Type': 'application/json',
|
|
650
|
+
'Cache-Control': 'no-store'
|
|
651
|
+
});
|
|
652
|
+
res.end(JSON.stringify(payload));
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
res.writeHead(404, {
|
|
656
|
+
'Content-Type': 'text/html; charset=utf-8',
|
|
657
|
+
'Cache-Control': 'no-store'
|
|
512
658
|
});
|
|
513
|
-
res.
|
|
514
|
-
res.end('404 Not Found');
|
|
659
|
+
res.end(_renderNotFoundHtml(payload));
|
|
515
660
|
}
|
|
516
661
|
});
|
|
517
662
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenithbuild/cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.17",
|
|
4
4
|
"description": "Deterministic project orchestrator for Zenith framework",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"prepublishOnly": "npm run build"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@zenithbuild/compiler": "0.6.
|
|
37
|
+
"@zenithbuild/compiler": "0.6.17",
|
|
38
38
|
"picocolors": "^1.1.1"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|