Skip to content

Commit 6f80fd8

Browse files
Jest 30, Express 5, Storybook 10, Tailwind 4
1 parent 013041e commit 6f80fd8

File tree

4 files changed

+23492
-17
lines changed

4 files changed

+23492
-17
lines changed

apps/storybook-addon/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@
8888
"zx": "^8.8.5"
8989
},
9090
"peerDependencies": {
91-
"storybook": "^9.0.0"
91+
"storybook": "^10.0.0"
9292
},
9393
"engines": {
9494
"node": ">=20"

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/docker/src/services/serve.ts

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import express from 'express';
2-
import { readFileSync, existsSync } from 'fs';
2+
import { resolve } from 'path';
33
import type { Logger } from '@walkeros/core';
44
import { VERSION } from '../version';
55

@@ -29,8 +29,8 @@ export async function runServeMode(
2929
// Host priority: ENV variable > config > default
3030
const host = process.env.HOST || config?.host || '0.0.0.0';
3131

32-
// File path: ENV variable > config > baked-in default
33-
const file = process.env.FILE || config?.file || '/app/web-serve.js';
32+
// File path: ENV variable > config > baked-in default (resolve to absolute)
33+
const file = resolve(process.env.FILE || config?.file || '/app/web-serve.js');
3434

3535
// Serve name (filename in URL): ENV variable > config > default
3636
const serveName = process.env.SERVE_NAME || config?.serveName || 'walker.js';
@@ -62,19 +62,38 @@ export async function runServeMode(
6262

6363
// Serve single file at custom URL path
6464
app.get(urlPath, (req, res) => {
65-
try {
66-
if (!existsSync(file)) {
67-
logger.error(`File not found: ${file}`);
68-
res.status(404).send('File not found');
69-
return;
65+
// Set content type before streaming
66+
res.type('application/javascript');
67+
68+
// Allow dotfiles since file paths may include dotfile directories
69+
res.sendFile(file, { dotfiles: 'allow' }, (err) => {
70+
if (err && !res.headersSent) {
71+
const errCode = (err as NodeJS.ErrnoException).code;
72+
// Express 5 uses HTTP-style errors with status/statusCode
73+
const errStatus =
74+
(err as { status?: number; statusCode?: number }).status ||
75+
(err as { status?: number; statusCode?: number }).statusCode;
76+
77+
// Log errors (except client disconnections)
78+
if (errCode !== 'ECONNABORTED') {
79+
logger.error(
80+
`sendFile error for ${file}: ${err.message} (code: ${errCode}, status: ${errStatus})`,
81+
);
82+
}
83+
84+
// Send appropriate error response (check both Node.js codes and HTTP status)
85+
if (
86+
errStatus === 404 ||
87+
errCode === 'ENOENT' ||
88+
errCode === 'EISDIR' ||
89+
errCode === 'ENOTDIR'
90+
) {
91+
res.status(404).send('File not found');
92+
} else if (errCode !== 'ECONNABORTED') {
93+
res.status(500).send('Internal server error');
94+
}
7095
}
71-
const content = readFileSync(file, 'utf-8');
72-
res.type('application/javascript').send(content);
73-
} catch (err) {
74-
const message = err instanceof Error ? err.message : String(err);
75-
logger.error(`Failed to read file: ${message}`);
76-
res.status(500).send('Internal server error');
77-
}
96+
});
7897
});
7998

8099
// Start server

0 commit comments

Comments
 (0)