chore(deps): upgrade express 4 -> 5 in daemon (#2311)

* chore(deps): upgrade express 4.22.1 -> 5.2.1 and @types/express

Breaking changes addressed:
- Renamed all bare wildcard route segments from * to *splat across
  src/server.ts, src/static-resource-routes.ts, src/project-routes.ts,
  src/import-export-routes.ts, and all three test stubs that define
  app.get/options/delete routes using /raw/* or /raw/* patterns
- Updated wildcard param access from (req.params as any)[0] / req.params[0]
  to Array.isArray(req.params.splat) ? req.params.splat.join('/') : String(...)
  to handle the Express 5 / path-to-regexp v8 change where wildcard params
  are now string[] instead of string
- Updated app.get('*') SPA fallback to app.get('/*splat') in server.ts
- Annotated five connector route handlers with Request<{ connectorId: string }>
  so the typed param resolves as string, not string | string[], fixing the
  10 TS2345 / TS2322 errors that surfaced when @types/express moved to 5.0.6
- Fixed two app.listen() beforeAll callbacks in origin-validation.test.ts to
  accept and propagate the optional Error argument Express 5 now passes to
  the listen callback, resolving TS2769 overload mismatch

* chore(nix): refresh daemonHash for rebased lockfile

* fix(daemon): await res.sendFile() in async route handlers for Express 5 compatibility

Express 5 res.sendFile() returns a Promise. Without await, async route
handlers return before the response is sent, causing Express to call
next() and fall through to a 404. Add await to all res.sendFile() calls
in async handlers in static-resource-routes.ts and server.ts.

* fix(daemon): use readFile+send for spritesheet route instead of sendFile

Express 5 res.sendFile() returns undefined (not a Promise). ENOENT errors
call next() asynchronously after the route handler's try/catch has returned,
causing unhandled 404 responses. Replacing with fs.promises.readFile + res.send
keeps the error path fully within the handler's try/catch.

---------

Co-authored-by: Patrick A <259201958+eefynet@users.noreply.github.com>
This commit is contained in:
Patrick A 2026-05-25 23:16:48 -04:00 committed by GitHub
parent 01f80d4b06
commit 7bc11b398d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 81 additions and 296 deletions

View file

@ -46,7 +46,7 @@
"blake3-wasm": "2.1.5",
"cheerio": "1.2.0",
"chokidar": "5.0.0",
"express": "4.22.1",
"express": "5.2.1",
"jszip": "3.10.1",
"multer": "2.1.1",
"posthog-node": "5.34.6",
@ -56,7 +56,7 @@
},
"devDependencies": {
"@types/better-sqlite3": "7.6.13",
"@types/express": "4.17.25",
"@types/express": "5.0.6",
"@types/multer": "2.1.0",
"@types/node": "20.19.39",
"typescript": "5.9.3",

View file

@ -589,7 +589,7 @@ export function registerConnectorRoutes(app: Express, options: RegisterConnector
}
});
app.get('/api/connectors/:connectorId', async (req: Request, res: Response) => {
app.get('/api/connectors/:connectorId', async (req: Request<{ connectorId: string }>, res: Response) => {
try {
const connectorId = req.params.connectorId;
if (!connectorId) return options.sendApiError(res, 400, 'CONNECTOR_NOT_FOUND', 'connectorId is required');
@ -625,7 +625,7 @@ export function registerConnectorRoutes(app: Express, options: RegisterConnector
}
});
app.post('/api/connectors/:connectorId/connect', requireLocalDaemonRequest, async (req: Request, res: Response) => {
app.post('/api/connectors/:connectorId/connect', requireLocalDaemonRequest, async (req: Request<{ connectorId: string }>, res: Response) => {
try {
const connectorId = req.params.connectorId;
if (!connectorId) return options.sendApiError(res, 400, 'CONNECTOR_NOT_FOUND', 'connectorId is required');
@ -653,7 +653,7 @@ export function registerConnectorRoutes(app: Express, options: RegisterConnector
}
});
app.get('/api/connectors/oauth/callback/:connectorId', async (req: Request, res: Response) => {
app.get('/api/connectors/oauth/callback/:connectorId', async (req: Request<{ connectorId: string }>, res: Response) => {
try {
const connectorId = req.params.connectorId;
if (!connectorId) return options.sendApiError(res, 400, 'CONNECTOR_NOT_FOUND', 'connectorId is required');
@ -674,7 +674,7 @@ export function registerConnectorRoutes(app: Express, options: RegisterConnector
}
});
app.post('/api/connectors/:connectorId/authorization/cancel', requireLocalDaemonRequest, async (req: Request, res: Response) => {
app.post('/api/connectors/:connectorId/authorization/cancel', requireLocalDaemonRequest, async (req: Request<{ connectorId: string }>, res: Response) => {
try {
const connectorId = req.params.connectorId;
if (!connectorId) return options.sendApiError(res, 400, 'CONNECTOR_NOT_FOUND', 'connectorId is required');
@ -684,7 +684,7 @@ export function registerConnectorRoutes(app: Express, options: RegisterConnector
}
});
app.delete('/api/connectors/:connectorId/connection', requireLocalDaemonRequest, async (req: Request, res: Response) => {
app.delete('/api/connectors/:connectorId/connection', requireLocalDaemonRequest, async (req: Request<{ connectorId: string }>, res: Response) => {
try {
const connectorId = req.params.connectorId;
if (!connectorId) return options.sendApiError(res, 400, 'CONNECTOR_NOT_FOUND', 'connectorId is required');

View file

@ -494,7 +494,7 @@ export function registerProjectExportRoutes(app: Express, ctx: RegisterProjectEx
//
// See nexu-io/open-design#368 and the architecture lock at
// https://github.com/nexu-io/open-design/issues/368#issuecomment-4366243218.
app.get('/api/projects/:id/export/*', async (req, res) => {
app.get('/api/projects/:id/export/*splat', async (req, res) => {
try {
if (!isSafeId(req.params.id)) {
return sendApiError(res, 400, 'BAD_REQUEST', 'invalid project id');
@ -512,7 +512,8 @@ export function registerProjectExportRoutes(app: Express, ctx: RegisterProjectEx
}
const project = getProject(db, req.params.id);
const relPath = (req.params as any)[0];
const splatParam = req.params.splat;
const relPath = Array.isArray(splatParam) ? splatParam.join('/') : String(splatParam ?? '');
// PR #1312 round-5 (lefarcen P2): stat the owner file BEFORE
// readProjectFile so a 100 MiB owner HTML is rejected after a

View file

@ -872,7 +872,7 @@ export function registerProjectFileRoutes(app: Express, ctx: RegisterProjectFile
// Preflight for the raw file route. Current artifact fetches are simple GETs
// (no preflight needed), but an explicit handler future-proofs the route if
// artifacts ever add custom request headers.
app.options('/api/projects/:id/raw/*', (req, res) => {
app.options('/api/projects/:id/raw/*splat', (req, res) => {
if (req.headers.origin === 'null') {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET');
@ -881,9 +881,10 @@ export function registerProjectFileRoutes(app: Express, ctx: RegisterProjectFile
res.sendStatus(204);
});
app.get('/api/projects/:id/raw/*', async (req, res) => {
app.get('/api/projects/:id/raw/*splat', async (req, res) => {
try {
const relPath = (req.params as any)[0];
const splatParam = req.params.splat;
const relPath = Array.isArray(splatParam) ? splatParam.join('/') : String(splatParam ?? '');
const project = getProject(db, req.params.id);
// PreviewModal loads artifact HTML via srcdoc, giving the iframe Origin: "null".
// data: URIs, file://, and some sandboxed iframes also send null — all are
@ -957,10 +958,12 @@ export function registerProjectFileRoutes(app: Express, ctx: RegisterProjectFile
}
});
app.delete('/api/projects/:id/raw/*', async (req, res) => {
app.delete('/api/projects/:id/raw/*splat', async (req, res) => {
try {
const project = getProject(db, req.params.id);
await deleteProjectFile(PROJECTS_DIR, req.params.id, (req.params as any)[0], project?.metadata);
const splatParam = req.params.splat;
const rawSplat = Array.isArray(splatParam) ? splatParam.join('/') : String(splatParam ?? '');
await deleteProjectFile(PROJECTS_DIR, req.params.id, rawSplat, project?.metadata);
/** @type {import('@open-design/contracts').DeleteProjectFileResponse} */
const body = { ok: true };
res.json(body);
@ -1002,13 +1005,15 @@ export function registerProjectFileRoutes(app: Express, ctx: RegisterProjectFile
}
});
app.get('/api/projects/:id/files/*', async (req, res) => {
app.get('/api/projects/:id/files/*splat', async (req, res) => {
try {
const project = getProject(db, req.params.id);
const splatParam = req.params.splat;
const fileSplat = Array.isArray(splatParam) ? splatParam.join('/') : String(splatParam ?? '');
const file = await readProjectFile(
PROJECTS_DIR,
req.params.id,
(req.params as any)[0],
fileSplat,
project?.metadata,
);
res.type(file.mime).send(file.buffer);

View file

@ -1130,7 +1130,7 @@ export function resolveStaticSpaFallbackPath(req, staticDir) {
}
export function registerStaticSpaFallback(app, staticDir) {
app.get('*', (req, res, next) => {
app.get('/*splat', (req, res, next) => {
const indexPath = resolveStaticSpaFallbackPath(req, staticDir);
if (indexPath == null) return next();
res.sendFile(indexPath);
@ -5722,7 +5722,8 @@ export async function startServer({
res.setHeader('Access-Control-Allow-Origin', 'null');
}
res.setHeader('Cache-Control', 'no-store');
res.sendFile(sheet.absPath);
const buf = await fs.promises.readFile(sheet.absPath);
res.send(buf);
} catch (err) {
res.status(500).type('text/plain').send(String(err));
}
@ -6945,11 +6946,12 @@ export async function startServer({
});
});
app.get('/api/plugins/:id/asset/*', async (req, res) => {
app.get('/api/plugins/:id/asset/*splat', async (req, res) => {
try {
const plugin = getInstalledPlugin(db, req.params.id);
if (!plugin) return res.status(404).json({ error: 'plugin not found' });
const relpath = String(req.params[0] ?? '');
const splatParam = req.params.splat;
const relpath = Array.isArray(splatParam) ? splatParam.join('/') : String(splatParam ?? '');
// Reject obvious traversal up-front; the path resolution below
// normalizes again, but this catches the easy cases without
// touching disk.
@ -7749,14 +7751,15 @@ export async function startServer({
// The example response above rewrites `./assets/<file>` into a request
// against this route; we still keep the on-disk paths human-friendly so
// contributors can preview `example.html` straight from disk.
app.get('/api/skills/:id/assets/*', async (req, res) => {
app.get('/api/skills/:id/assets/*splat', async (req, res) => {
try {
const skills = await listAllSkills();
const skill = findSkillById(skills, req.params.id);
if (!skill) {
return res.status(404).type('text/plain').send('skill not found');
}
const relPath = String(req.params[0] || '');
const splatParam = req.params.splat;
const relPath = Array.isArray(splatParam) ? splatParam.join('/') : String(splatParam || '');
const assetsRoot = path.resolve(skill.dir, 'assets');
const target = path.resolve(assetsRoot, relPath);
if (target !== assetsRoot && !target.startsWith(assetsRoot + path.sep)) {
@ -7771,7 +7774,7 @@ export async function startServer({
if (req.headers.origin === 'null') {
res.header('Access-Control-Allow-Origin', '*');
}
res.type(mimeFor(target)).sendFile(target);
await res.type(mimeFor(target)).sendFile(target);
} catch (err) {
res.status(500).type('text/plain').send(String(err));
}
@ -8813,7 +8816,7 @@ export async function startServer({
// Preflight for the raw file route. Current artifact fetches are simple GETs
// (no preflight needed), but an explicit handler future-proofs the route if
// artifacts ever add custom request headers.
app.options('/api/projects/:id/raw/*', (req, res) => {
app.options('/api/projects/:id/raw/*splat', (req, res) => {
if (req.headers.origin === 'null') {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET');
@ -8822,9 +8825,10 @@ export async function startServer({
res.sendStatus(204);
});
app.get('/api/projects/:id/raw/*', async (req, res) => {
app.get('/api/projects/:id/raw/*splat', async (req, res) => {
try {
const relPath = req.params[0];
const splatParam = req.params.splat;
const relPath = Array.isArray(splatParam) ? splatParam.join('/') : String(splatParam ?? '');
const project = getProject(db, req.params.id);
const file = await readProjectFile(PROJECTS_DIR, req.params.id, relPath, project?.metadata);
// PreviewModal loads artifact HTML via srcdoc, giving the iframe Origin: "null".
@ -8881,10 +8885,12 @@ export async function startServer({
}
});
app.delete('/api/projects/:id/raw/*', async (req, res) => {
app.delete('/api/projects/:id/raw/*splat', async (req, res) => {
try {
const project = getProject(db, req.params.id);
await deleteProjectFile(PROJECTS_DIR, req.params.id, req.params[0], project?.metadata);
const splatParam = req.params.splat;
const rawSplat = Array.isArray(splatParam) ? splatParam.join('/') : String(splatParam ?? '');
await deleteProjectFile(PROJECTS_DIR, req.params.id, rawSplat, project?.metadata);
/** @type {import('@open-design/contracts').DeleteProjectFileResponse} */
const body = { ok: true };
res.json(body);
@ -8926,13 +8932,15 @@ export async function startServer({
}
});
app.get('/api/projects/:id/files/*', async (req, res) => {
app.get('/api/projects/:id/files/*splat', async (req, res) => {
try {
const project = getProject(db, req.params.id);
const splatParam = req.params.splat;
const fileSplat = Array.isArray(splatParam) ? splatParam.join('/') : String(splatParam ?? '');
const file = await readProjectFile(
PROJECTS_DIR,
req.params.id,
req.params[0],
fileSplat,
project?.metadata,
);
res.type(file.mime).send(file.buffer);

View file

@ -284,7 +284,8 @@ export function registerStaticResourceRoutes(app: Express, ctx: RegisterStaticRe
res.setHeader('Access-Control-Allow-Origin', 'null');
}
res.setHeader('Cache-Control', 'no-store');
res.sendFile(sheet.absPath);
const buf = await fs.promises.readFile(sheet.absPath);
res.send(buf);
} catch (err: any) {
res.status(500).type('text/plain').send(String(err));
}
@ -502,7 +503,7 @@ export function registerStaticResourceRoutes(app: Express, ctx: RegisterStaticRe
// The example response above rewrites `./assets/<file>` into a request
// against this route; we still keep the on-disk paths human-friendly so
// contributors can preview `example.html` straight from disk.
app.get('/api/skills/:id/assets/*', async (req, res) => {
app.get('/api/skills/:id/assets/*splat', async (req, res) => {
try {
// Same rationale as /example above — assets need to resolve whether
// the owning skill folder lives under skills/ or design-templates/.
@ -511,7 +512,8 @@ export function registerStaticResourceRoutes(app: Express, ctx: RegisterStaticRe
if (!skill) {
return res.status(404).type('text/plain').send('skill not found');
}
const relPath = String((req.params as any)[0] || '');
const splatParam = req.params.splat;
const relPath = Array.isArray(splatParam) ? splatParam.join('/') : String(splatParam || '');
const assetsRoot = path.resolve(skill.dir, 'assets');
const target = path.resolve(assetsRoot, relPath);
if (target !== assetsRoot && !target.startsWith(assetsRoot + path.sep)) {
@ -526,7 +528,7 @@ export function registerStaticResourceRoutes(app: Express, ctx: RegisterStaticRe
if (req.headers.origin === 'null') {
res.header('Access-Control-Allow-Origin', '*');
}
res.type(mimeFor(target)).sendFile(target);
await res.type(mimeFor(target)).sendFile(target);
} catch (err: any) {
res.status(500).type('text/plain').send(String(err));
}

View file

@ -51,7 +51,7 @@ function makeDaemonApp(opts: DaemonAppOpts = {}): Express {
app.get('/api/projects/:id/files', (_req, res) => res.json({ files }));
app.get('/api/projects/:id/raw/*', (_req, res) => {
app.get('/api/projects/:id/raw/*splat', (_req, res) => {
const headers: Record<string, string> = { 'content-type': contentType };
if (contentLength != null) headers['content-length'] = String(contentLength);
res.set(headers).send(fileContent);

View file

@ -19,7 +19,7 @@ interface TextContent {
function makeDaemonApp(text: string, contentType = 'text/plain'): Express {
const app = express();
app.get('/api/projects/:id/raw/*', (_req, res) => {
app.get('/api/projects/:id/raw/*splat', (_req, res) => {
res.set({ 'content-type': contentType }).send(text);
});
return app;

View file

@ -132,14 +132,17 @@ describe('daemon origin validation middleware', () => {
beforeAll(
() =>
new Promise<void>((resolve) => {
new Promise<void>((resolve, reject) => {
// Start on port 0 to get a dynamic port, then rebuild with real port
const tempApp = makeTestApp(0);
const tempServer = tempApp.listen(0, '127.0.0.1', () => {
port = getListeningPort(tempServer);
tempServer.close(() => {
const realApp = makeTestApp(port);
server = realApp.listen(port, '127.0.0.1', resolve);
server = realApp.listen(port, '127.0.0.1', (err?: Error) => {
if (err) reject(err);
else resolve();
});
});
});
}),
@ -448,14 +451,17 @@ describe('origin validation: non-loopback bind host', () => {
beforeAll(
() =>
new Promise<void>((resolve) => {
new Promise<void>((resolve, reject) => {
// Start on port 0 to get a dynamic port, then rebuild with real port
const tempApp = makeTestApp(0, nonLoopbackHost);
const tempServer = tempApp.listen(0, '127.0.0.1', () => {
port = getListeningPort(tempServer);
tempServer.close(() => {
const realApp = makeTestApp(port, nonLoopbackHost);
server = realApp.listen(port, '127.0.0.1', resolve);
server = realApp.listen(port, '127.0.0.1', (err?: Error) => {
if (err) reject(err);
else resolve();
});
});
});
}),

View file

@ -7,7 +7,7 @@ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
function makeTestApp() {
const app = express();
app.options('/api/projects/:id/raw/*', (req, res) => {
app.options('/api/projects/:id/raw/*splat', (req, res) => {
if (req.headers.origin === 'null') {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET');
@ -16,7 +16,7 @@ function makeTestApp() {
res.sendStatus(204);
});
app.get('/api/projects/:id/raw/*', (req, res) => {
app.get('/api/projects/:id/raw/*splat', (req, res) => {
if (req.headers.origin === 'null') {
res.header('Access-Control-Allow-Origin', '*');
}

View file

@ -8,6 +8,6 @@
# 1. Temporarily set the consuming `hash = lib.fakeHash;`
# 2. Run the relevant nix build/flake check
# 3. Copy the expected hash printed by Nix into the matching field below
daemonHash = "sha256-enohbA0Ha41vTime/L7oa8S7wX6P2+aQAc2MpvtYLcE=";
daemonHash = "sha256-tqxFDNPQjoKUWp4sLtPVCUu7ltIL/ufeyr6UKOWYw6A=";
webHash = "sha256-74loUCL+WcaZO4AAMnSpNeBhDz1Y9TMgFRPbyaOfPAk=";
}

View file

@ -83,8 +83,8 @@ importers:
specifier: 5.0.0
version: 5.0.0
express:
specifier: 4.22.1
version: 4.22.1
specifier: 5.2.1
version: 5.2.1
jszip:
specifier: 3.10.1
version: 3.10.1
@ -108,8 +108,8 @@ importers:
specifier: 7.6.13
version: 7.6.13
'@types/express':
specifier: 4.17.25
version: 4.17.25
specifier: 5.0.6
version: 5.0.6
'@types/multer':
specifier: 2.1.0
version: 2.1.0
@ -2001,11 +2001,11 @@ packages:
'@types/estree@1.0.8':
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
'@types/express-serve-static-core@4.19.8':
resolution: {integrity: sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==}
'@types/express-serve-static-core@5.1.1':
resolution: {integrity: sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==}
'@types/express@4.17.25':
resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==}
'@types/express@5.0.6':
resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==}
'@types/fs-extra@9.0.13':
resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==}
@ -2028,9 +2028,6 @@ packages:
'@types/mdast@4.0.4':
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
'@types/mime@1.3.5':
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
'@types/ms@2.1.0':
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
@ -2081,14 +2078,11 @@ packages:
'@types/sax@1.2.7':
resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==}
'@types/send@0.17.6':
resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==}
'@types/send@1.2.1':
resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==}
'@types/serve-static@1.15.10':
resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==}
'@types/serve-static@2.2.0':
resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==}
'@types/tough-cookie@4.0.5':
resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==}
@ -2180,10 +2174,6 @@ packages:
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
engines: {node: '>=6.5'}
accepts@1.3.8:
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
engines: {node: '>= 0.6'}
accepts@2.0.0:
resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
engines: {node: '>= 0.6'}
@ -2265,9 +2255,6 @@ packages:
resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
engines: {node: '>= 0.4'}
array-flatten@1.1.1:
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
array-iterate@2.0.1:
resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==}
@ -2340,10 +2327,6 @@ packages:
blake3-wasm@2.1.5:
resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==}
body-parser@1.20.5:
resolution: {integrity: sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
body-parser@2.2.2:
resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==}
engines: {node: '>=18'}
@ -2518,10 +2501,6 @@ packages:
resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==}
engines: {'0': node >= 6.0}
content-disposition@0.5.4:
resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
engines: {node: '>= 0.6'}
content-disposition@1.1.0:
resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==}
engines: {node: '>=18'}
@ -2536,9 +2515,6 @@ packages:
cookie-es@1.2.3:
resolution: {integrity: sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==}
cookie-signature@1.0.7:
resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==}
cookie-signature@1.2.2:
resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==}
engines: {node: '>=6.6.0'}
@ -2603,14 +2579,6 @@ packages:
resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==}
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
debug@2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
engines: {node: '>=6.0'}
@ -2664,10 +2632,6 @@ packages:
destr@2.0.5:
resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==}
destroy@1.2.0:
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
detect-libc@2.1.2:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
@ -2892,10 +2856,6 @@ packages:
peerDependencies:
express: '>= 4.11'
express@4.22.1:
resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==}
engines: {node: '>= 0.10.0'}
express@5.2.1:
resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==}
engines: {node: '>= 18'}
@ -2962,10 +2922,6 @@ packages:
filelist@1.0.6:
resolution: {integrity: sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==}
finalhandler@1.3.2:
resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==}
engines: {node: '>= 0.8'}
finalhandler@2.1.1:
resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==}
engines: {node: '>= 18.0.0'}
@ -2996,10 +2952,6 @@ packages:
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
engines: {node: '>= 0.6'}
fresh@0.5.2:
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
engines: {node: '>= 0.6'}
fresh@2.0.0:
resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
engines: {node: '>= 0.8'}
@ -3192,10 +3144,6 @@ packages:
engines: {node: ^8.11.2 || >=10}
os: [darwin]
iconv-lite@0.4.24:
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
engines: {node: '>=0.10.0'}
iconv-lite@0.6.3:
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
engines: {node: '>=0.10.0'}
@ -3540,17 +3488,10 @@ packages:
resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==}
engines: {node: '>= 0.8'}
merge-descriptors@1.0.3:
resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==}
merge-descriptors@2.0.0:
resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==}
engines: {node: '>=18'}
methods@1.1.2:
resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
engines: {node: '>= 0.6'}
micromark-core-commonmark@2.0.3:
resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
@ -3651,11 +3592,6 @@ packages:
resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==}
engines: {node: '>=18'}
mime@1.6.0:
resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
engines: {node: '>=4'}
hasBin: true
mime@2.6.0:
resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==}
engines: {node: '>=4.0.0'}
@ -3706,9 +3642,6 @@ packages:
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
engines: {node: '>=10'}
ms@2.0.0:
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@ -3727,10 +3660,6 @@ packages:
napi-build-utils@2.0.0:
resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==}
negotiator@0.6.3:
resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
engines: {node: '>= 0.6'}
negotiator@1.0.0:
resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
engines: {node: '>= 0.6'}
@ -3924,9 +3853,6 @@ packages:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
path-to-regexp@0.1.13:
resolution: {integrity: sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==}
path-to-regexp@8.4.2:
resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==}
@ -4085,10 +4011,6 @@ packages:
resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
engines: {node: '>= 0.6'}
raw-body@2.5.3:
resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==}
engines: {node: '>= 0.8'}
raw-body@3.0.2:
resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==}
engines: {node: '>= 0.10'}
@ -4265,10 +4187,6 @@ packages:
engines: {node: '>=10'}
hasBin: true
send@0.19.2:
resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==}
engines: {node: '>= 0.8.0'}
send@1.2.1:
resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==}
engines: {node: '>= 18'}
@ -4277,10 +4195,6 @@ packages:
resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==}
engines: {node: '>=10'}
serve-static@1.16.3:
resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==}
engines: {node: '>= 0.8.0'}
serve-static@2.2.1:
resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==}
engines: {node: '>= 18'}
@ -4728,10 +4642,6 @@ packages:
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
utils-merge@1.0.1:
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
engines: {node: '>= 0.4.0'}
vary@1.1.2:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
@ -6425,19 +6335,18 @@ snapshots:
'@types/estree@1.0.8': {}
'@types/express-serve-static-core@4.19.8':
'@types/express-serve-static-core@5.1.1':
dependencies:
'@types/node': 24.12.2
'@types/qs': 6.15.0
'@types/range-parser': 1.2.7
'@types/send': 1.2.1
'@types/express@4.17.25':
'@types/express@5.0.6':
dependencies:
'@types/body-parser': 1.19.6
'@types/express-serve-static-core': 4.19.8
'@types/qs': 6.15.0
'@types/serve-static': 1.15.10
'@types/express-serve-static-core': 5.1.1
'@types/serve-static': 2.2.0
'@types/fs-extra@9.0.13':
dependencies:
@ -6466,13 +6375,11 @@ snapshots:
dependencies:
'@types/unist': 3.0.3
'@types/mime@1.3.5': {}
'@types/ms@2.1.0': {}
'@types/multer@2.1.0':
dependencies:
'@types/express': 4.17.25
'@types/express': 5.0.6
'@types/nlcst@2.0.3':
dependencies:
@ -6528,20 +6435,14 @@ snapshots:
dependencies:
'@types/node': 24.12.2
'@types/send@0.17.6':
dependencies:
'@types/mime': 1.3.5
'@types/node': 24.12.2
'@types/send@1.2.1':
dependencies:
'@types/node': 24.12.2
'@types/serve-static@1.15.10':
'@types/serve-static@2.2.0':
dependencies:
'@types/http-errors': 2.0.5
'@types/node': 24.12.2
'@types/send': 0.17.6
'@types/tough-cookie@4.0.5': {}
@ -6670,11 +6571,6 @@ snapshots:
dependencies:
event-target-shim: 5.0.1
accepts@1.3.8:
dependencies:
mime-types: 2.1.35
negotiator: 0.6.3
accepts@2.0.0:
dependencies:
mime-types: 3.0.2
@ -6782,8 +6678,6 @@ snapshots:
aria-query@5.3.2: {}
array-flatten@1.1.1: {}
array-iterate@2.0.1: {}
assert-plus@1.0.0:
@ -6928,23 +6822,6 @@ snapshots:
blake3-wasm@2.1.5: {}
body-parser@1.20.5:
dependencies:
bytes: 3.1.2
content-type: 1.0.5
debug: 2.6.9
depd: 2.0.0
destroy: 1.2.0
http-errors: 2.0.1
iconv-lite: 0.4.24
on-finished: 2.4.1
qs: 6.15.2
raw-body: 2.5.3
type-is: 1.6.18
unpipe: 1.0.0
transitivePeerDependencies:
- supports-color
body-parser@2.2.2:
dependencies:
bytes: 3.1.2
@ -7145,10 +7022,6 @@ snapshots:
readable-stream: 3.6.2
typedarray: 0.0.6
content-disposition@0.5.4:
dependencies:
safe-buffer: 5.2.1
content-disposition@1.1.0: {}
content-type@1.0.5: {}
@ -7157,8 +7030,6 @@ snapshots:
cookie-es@1.2.3: {}
cookie-signature@1.0.7: {}
cookie-signature@1.2.2: {}
cookie@0.7.2: {}
@ -7228,10 +7099,6 @@ snapshots:
transitivePeerDependencies:
- '@noble/hashes'
debug@2.6.9:
dependencies:
ms: 2.0.0
debug@4.4.3:
dependencies:
ms: 2.1.3
@ -7274,8 +7141,6 @@ snapshots:
destr@2.0.5: {}
destroy@1.2.0: {}
detect-libc@2.1.2: {}
detect-node@2.1.0:
@ -7572,42 +7437,6 @@ snapshots:
express: 5.2.1
ip-address: 10.2.0
express@4.22.1:
dependencies:
accepts: 1.3.8
array-flatten: 1.1.1
body-parser: 1.20.5
content-disposition: 0.5.4
content-type: 1.0.5
cookie: 0.7.2
cookie-signature: 1.0.7
debug: 2.6.9
depd: 2.0.0
encodeurl: 2.0.0
escape-html: 1.0.3
etag: 1.8.1
finalhandler: 1.3.2
fresh: 0.5.2
http-errors: 2.0.1
merge-descriptors: 1.0.3
methods: 1.1.2
on-finished: 2.4.1
parseurl: 1.3.3
path-to-regexp: 0.1.13
proxy-addr: 2.0.7
qs: 6.15.2
range-parser: 1.2.1
safe-buffer: 5.2.1
send: 0.19.2
serve-static: 1.16.3
setprototypeof: 1.2.0
statuses: 2.0.2
type-is: 1.6.18
utils-merge: 1.0.1
vary: 1.1.2
transitivePeerDependencies:
- supports-color
express@5.2.1:
dependencies:
accepts: 2.0.0
@ -7708,18 +7537,6 @@ snapshots:
dependencies:
minimatch: 5.1.9
finalhandler@1.3.2:
dependencies:
debug: 2.6.9
encodeurl: 2.0.0
escape-html: 1.0.3
on-finished: 2.4.1
parseurl: 1.3.3
statuses: 2.0.2
unpipe: 1.0.0
transitivePeerDependencies:
- supports-color
finalhandler@2.1.1:
dependencies:
debug: 4.4.3
@ -7758,8 +7575,6 @@ snapshots:
forwarded@0.2.0: {}
fresh@0.5.2: {}
fresh@2.0.0: {}
fs-constants@1.0.0: {}
@ -8058,10 +7873,6 @@ snapshots:
node-addon-api: 1.7.2
optional: true
iconv-lite@0.4.24:
dependencies:
safer-buffer: 2.1.2
iconv-lite@0.6.3:
dependencies:
safer-buffer: 2.1.2
@ -8429,12 +8240,8 @@ snapshots:
media-typer@1.1.0: {}
merge-descriptors@1.0.3: {}
merge-descriptors@2.0.0: {}
methods@1.1.2: {}
micromark-core-commonmark@2.0.3:
dependencies:
decode-named-character-reference: 1.3.0
@ -8638,8 +8445,6 @@ snapshots:
dependencies:
mime-db: 1.54.0
mime@1.6.0: {}
mime@2.6.0: {}
mimic-response@1.0.1: {}
@ -8678,8 +8483,6 @@ snapshots:
mrmime@2.0.1: {}
ms@2.0.0: {}
ms@2.1.3: {}
muggle-string@0.4.1: {}
@ -8695,8 +8498,6 @@ snapshots:
napi-build-utils@2.0.0: {}
negotiator@0.6.3: {}
negotiator@1.0.0: {}
neotraverse@0.6.18: {}
@ -8875,8 +8676,6 @@ snapshots:
path-key@3.1.1: {}
path-to-regexp@0.1.13: {}
path-to-regexp@8.4.2: {}
pathe@2.0.3: {}
@ -9032,13 +8831,6 @@ snapshots:
range-parser@1.2.1: {}
raw-body@2.5.3:
dependencies:
bytes: 3.1.2
http-errors: 2.0.1
iconv-lite: 0.4.24
unpipe: 1.0.0
raw-body@3.0.2:
dependencies:
bytes: 3.1.2
@ -9298,24 +9090,6 @@ snapshots:
semver@7.7.4: {}
send@0.19.2:
dependencies:
debug: 2.6.9
depd: 2.0.0
destroy: 1.2.0
encodeurl: 2.0.0
escape-html: 1.0.3
etag: 1.8.1
fresh: 0.5.2
http-errors: 2.0.1
mime: 1.6.0
ms: 2.1.3
on-finished: 2.4.1
range-parser: 1.2.1
statuses: 2.0.2
transitivePeerDependencies:
- supports-color
send@1.2.1:
dependencies:
debug: 4.4.3
@ -9337,15 +9111,6 @@ snapshots:
type-fest: 0.13.1
optional: true
serve-static@1.16.3:
dependencies:
encodeurl: 2.0.0
escape-html: 1.0.3
parseurl: 1.3.3
send: 0.19.2
transitivePeerDependencies:
- supports-color
serve-static@2.2.1:
dependencies:
encodeurl: 2.0.0
@ -9784,8 +9549,6 @@ snapshots:
util-deprecate@1.0.2: {}
utils-merge@1.0.1: {}
vary@1.1.2: {}
verror@1.10.1: