diff --git a/.changeset/green-crabs-add.md b/.changeset/green-crabs-add.md new file mode 100644 index 00000000..f19dadf4 --- /dev/null +++ b/.changeset/green-crabs-add.md @@ -0,0 +1,5 @@ +--- +'@ice/pkg': minor +--- + +feat: support builtin dev server diff --git a/packages/pkg/package.json b/packages/pkg/package.json index 933a44d5..456c272c 100644 --- a/packages/pkg/package.json +++ b/packages/pkg/package.json @@ -54,14 +54,17 @@ "chokidar": "^3.5.3", "cli-spinners": "^2.9.2", "consola": "^3.4.2", + "cors": "^2.8.5", "debug": "^4.3.3", "es-module-lexer": "^1.3.1", "es-toolkit": "^1.32.0", + "express": "^5.2.1", "figures": "^6.1.0", "fs-extra": "^10.0.0", "get-tsconfig": "^4.13.0", "globby": "^11.0.4", "gzip-size": "^7.0.0", + "http-proxy-middleware": "^3.0.5", "magic-string": "^0.25.7", "oxc-transform": "~0.89.0", "picocolors": "^1.0.0", @@ -79,7 +82,9 @@ }, "devDependencies": { "@types/babel__core": "^7.1.20", + "@types/cors": "^2.8.19", "@types/debug": "^4.1.12", + "@types/express": "^5.0.6", "@types/fs-extra": "^9.0.13", "@types/semver": "^7.7.1", "cssnano": "^5.1.15", diff --git a/packages/pkg/src/cli.ts b/packages/pkg/src/cli.ts index 70ea1915..f33b99bd 100644 --- a/packages/pkg/src/cli.ts +++ b/packages/pkg/src/cli.ts @@ -45,6 +45,9 @@ const cli = cac('ice-pkg'); .option('--rootDir ', 'specify root directory', { default: process.cwd(), }) + .option('--server', 'Override server config', {}) + .option('--port ', 'Override default server port', {}) + .option('--host ', 'Override default server host', {}) .action(async (options) => { delete options['--']; const { rootDir, ...commandArgs } = options; diff --git a/packages/pkg/src/commands/start.ts b/packages/pkg/src/commands/start.ts index 721e24ce..4bd23824 100644 --- a/packages/pkg/src/commands/start.ts +++ b/packages/pkg/src/commands/start.ts @@ -4,9 +4,10 @@ import type { OutputResult, Context, WatchChangedFile, BuildTask } from '../type import { RunnerLinerTerminalReporter } from '../helpers/runnerReporter.js'; import { getTaskRunners } from '../helpers/getTaskRunners.js'; import { RunnerScheduler } from '../helpers/runnerScheduler.js'; +import { createServer } from '../server/createServer.js'; export default async function start(context: Context) { - const { applyHook, commandArgs } = context; + const { applyHook, commandArgs, userConfig } = context; const buildTasks = context.getTaskConfig() as BuildTask[]; const taskConfigs = buildTasks.map(({ config }) => config); @@ -26,6 +27,14 @@ export default async function start(context: Context) { }); const watcher = createWatcher(taskConfigs); + const serverConfig = commandArgs.server !== undefined ? commandArgs.server : userConfig.server; + const devServer = serverConfig + ? createServer({ + ...(serverConfig === true ? {} : serverConfig), + ...(commandArgs.port ? { port: commandArgs.port } : {}), + ...(commandArgs.host ? { host: commandArgs.host } : {}), + }) + : null; const batchHandler = createBatchChangeHandler(runChangedCompile); batchHandler.beginBlock(); @@ -43,6 +52,8 @@ export default async function start(context: Context) { await applyHook('after.start.compile', outputResults); + await devServer?.listen(); + devServer?.printUrls(); batchHandler.endBlock(); async function runChangedCompile(changedFiles: WatchChangedFile[]) { diff --git a/packages/pkg/src/config/cliOptions.ts b/packages/pkg/src/config/cliOptions.ts index 38a73d9d..7db1c916 100644 --- a/packages/pkg/src/config/cliOptions.ts +++ b/packages/pkg/src/config/cliOptions.ts @@ -10,6 +10,10 @@ function getCliOptions() { return mergeValueToTaskConfig(config, 'analyzer', analyzer); }, }, + { + name: 'server', + commands: ['start'], + }, ]; return cliOptions; } diff --git a/packages/pkg/src/config/schema.ts b/packages/pkg/src/config/schema.ts index 5a9c1dfd..371c4946 100644 --- a/packages/pkg/src/config/schema.ts +++ b/packages/pkg/src/config/schema.ts @@ -21,8 +21,8 @@ export const bundleSchema = z.object({ .union([ z.boolean(), z.object({ - js: z.union([z.boolean(), z.function()]), - css: z.union([z.boolean(), z.function()]), + js: z.union([z.boolean(), z.function()]).optional(), + css: z.union([z.boolean(), z.function()]).optional(), }), ]) .optional(), @@ -32,6 +32,25 @@ export const bundleSchema = z.object({ codeSplitting: z.boolean().optional(), }); +export const serverPublicDirOptionSchema = z.object({ + name: z.string().optional(), +}); + +export const serverPublicDirOptionWithStringSchema = z.union([z.string(), serverPublicDirOptionSchema]); + +export const serverSchema = z.object({ + publicDir: z + .union([serverPublicDirOptionWithStringSchema, z.array(serverPublicDirOptionWithStringSchema)]) + .optional(), + port: z.number().optional(), + https: z.any().optional(), + host: z.string().optional(), + headers: z.record(z.string(), z.union([z.string(), z.string().array()])).optional(), + cors: z.union([z.boolean(), z.any()]).optional(), + proxy: z.union([z.record(z.string(), z.union([z.string(), z.any()])), z.any().array()]).optional(), + autoServeBundle: z.boolean().optional(), +}); + export const userConfigSchema = z.object({ entry: z.union([z.string(), z.string().array(), z.record(z.string(), z.string())]).optional(), alias: z.record(z.string(), z.string()).optional(), @@ -52,6 +71,7 @@ export const userConfigSchema = z.object({ generator: z.enum(['tsc', 'oxc']).optional(), }), ]), + server: z.union([z.boolean(), serverSchema]).optional(), }); export type UserConfigSchemaType = z.infer; diff --git a/packages/pkg/src/server/createServer.ts b/packages/pkg/src/server/createServer.ts new file mode 100644 index 00000000..bd090565 --- /dev/null +++ b/packages/pkg/src/server/createServer.ts @@ -0,0 +1,189 @@ +import { ServerUserConfig } from '../types.js'; +import type Express from 'express'; +import express from 'express'; +import http from 'node:http'; +import https from 'node:https'; +import http2 from 'node:http2'; +import path from 'node:path'; +import fs from 'node:fs'; +import { createProxyMiddleware } from 'http-proxy-middleware'; +import { consola } from 'consola'; +import pc from 'picocolors'; +import cors from 'cors'; +import { getAddressUrls } from './utils.js'; + +export const DEFAULT_PORT = 5138; +export const DEFAULT_HOST = '0.0.0.0'; + +export interface PkgServer { + app: Express.Application; + httpServer: import('node:http').Server | import('node:https').Server | import('node:http2').Http2SecureServer | null; + listen: () => Promise<{ + port: number; + urls: string[]; + server: { + close: () => Promise; + }; + }>; + port: number; + close: () => Promise; + printUrls: () => void; +} + +export function createServer(serverConfig: ServerUserConfig): PkgServer { + const { + port: configPort = DEFAULT_PORT, + host = DEFAULT_HOST, + publicDir: publicDirConfig, + headers, + cors: corsConfig, + proxy, + autoServeBundle = true, + https: httpsConfig, + } = serverConfig; + const app = express(); + + if (headers) { + app.use((req, res, next) => { + Object.entries(headers).forEach(([key, value]) => { + if (Array.isArray(value)) { + value.forEach((v) => res.setHeader(key, v)); + } else { + res.setHeader(key, value); + } + }); + next(); + }); + } + + if (proxy) { + if (Array.isArray(proxy)) { + proxy.forEach((p) => app.use(createProxyMiddleware(p))); + } else { + Object.entries(proxy).forEach(([context, options]) => { + if (typeof options === 'string') { + app.use(context, createProxyMiddleware({ target: options, changeOrigin: true })); + } else { + app.use(context, createProxyMiddleware(options)); + } + }); + } + } + + if (corsConfig !== false) { + const options = corsConfig === true ? undefined : corsConfig; + app.use(cors(options)); + } + + if (autoServeBundle) { + app.use(express.static(path.resolve(process.cwd(), 'dist'))); + } + + if (publicDirConfig) { + const dirs = Array.isArray(publicDirConfig) ? publicDirConfig : [publicDirConfig]; + dirs.forEach((dir) => { + let publicDir: string | undefined; + if (typeof dir === 'string') { + publicDir = dir; + } else if (typeof dir === 'object') { + publicDir = dir.name; + } + + if (publicDir) { + const staticPath = path.resolve(process.cwd(), publicDir); + if (fs.existsSync(staticPath)) { + app.use(express.static(staticPath)); + } + } + }); + } + + let httpServer: http.Server | https.Server | http2.Http2SecureServer; + + if (httpsConfig) { + if (proxy) { + // http-proxy-middleware is not compatible with HTTP/2 + httpServer = https.createServer(httpsConfig as https.ServerOptions, app); + } else { + httpServer = http2.createSecureServer( + { + allowHTTP1: true, + maxSessionMemory: 1024, + ...httpsConfig, + }, + // @ts-expect-error req type mismatch + app, + ); + } + } else { + httpServer = http.createServer(app); + } + + let resolvedPort = configPort; + + const devServerAPI: PkgServer = { + app: app, + httpServer, + get port() { + return resolvedPort; + }, + listen: async () => { + const findPort = async (startPort: number): Promise => { + return new Promise((resolve, reject) => { + const s = http.createServer(); + s.on('error', (err: any) => { + if (err.code === 'EADDRINUSE') { + s.close(); + resolve(findPort(startPort + 1)); + } else { + reject(err); + } + }); + s.listen(startPort, host, () => { + s.close(() => resolve(startPort)); + }); + }); + }; + + resolvedPort = await findPort(resolvedPort); + + return new Promise((resolve) => { + httpServer.listen(resolvedPort, host, () => { + const hostname = host === '0.0.0.0' ? 'localhost' : host; + const protocol = httpsConfig ? 'https' : 'http'; + const urls = [`${protocol}://${hostname}:${resolvedPort}`]; + resolve({ + port: resolvedPort, + urls, + server: { + close: devServerAPI.close, + }, + }); + }); + }); + }, + close: async () => { + if (httpServer.listening) { + return new Promise((resolve, reject) => { + httpServer.close((err) => { + if (err) reject(err); + else resolve(); + }); + }); + } + }, + printUrls: () => { + const protocol = httpsConfig ? 'https' : 'http'; + const urls = getAddressUrls(protocol, resolvedPort, host); + // eslint-disable-next-line no-console + console.log(); + urls.forEach(({ label, url }) => { + consola.log(`${label}${pc.cyan(url)}`); + }); + // eslint-disable-next-line no-console + console.log(); + }, + }; + + return devServerAPI; +} diff --git a/packages/pkg/src/server/utils.ts b/packages/pkg/src/server/utils.ts new file mode 100644 index 00000000..5c144440 --- /dev/null +++ b/packages/pkg/src/server/utils.ts @@ -0,0 +1,41 @@ +import os from 'node:os'; +import pc from 'picocolors'; + +export const getIpv4Interfaces = () => { + const interfaces = os.networkInterfaces(); + const ipv4Interfaces: os.NetworkInterfaceInfo[] = []; + + Object.values(interfaces).forEach((key) => { + key?.forEach((detail) => { + // 'IPv4' is in Node <= 17, from 18 it's a number 4 or 6 + if (detail.family === 'IPv4' || (detail.family as any) === 4) { + ipv4Interfaces.push(detail); + } + }); + }); + return ipv4Interfaces; +}; + +export const getAddressUrls = (protocol: string, port: number, host: string) => { + const LOCAL_LABEL = ` ${pc.green('➜')} ${pc.bold('Local')}: `; + const NETWORK_LABEL = ` ${pc.green('➜')} ${pc.bold('Network')}: `; + + if (host && host !== '0.0.0.0') { + return [{ label: LOCAL_LABEL, url: `${protocol}://${host}:${port}` }]; + } + + const urls: Array<{ label: string; url: string }> = []; + const interfaces = getIpv4Interfaces(); + let hasLocal = false; + interfaces.forEach((detail) => { + if (detail.internal || detail.address === '127.0.0.1' || detail.address === '::1') { + if (!hasLocal) { + urls.push({ label: LOCAL_LABEL, url: `${protocol}://localhost:${port}` }); + hasLocal = true; + } + } else { + urls.push({ label: NETWORK_LABEL, url: `${protocol}://${detail.address}:${port}` }); + } + }); + return urls; +}; diff --git a/packages/pkg/src/types.ts b/packages/pkg/src/types.ts index 0b76b796..655e3447 100644 --- a/packages/pkg/src/types.ts +++ b/packages/pkg/src/types.ts @@ -1,5 +1,4 @@ import * as swc from '@swc/core'; - import type { RollupOptions, SourceMapInput, ModuleJSON, RollupOutput } from 'rollup'; import type { Context as _Context, @@ -16,6 +15,10 @@ import cssnano from 'cssnano'; import { TransformOptions } from '@babel/core'; import { ALL_FORMAT_MODULES, ALL_FORMAT_TARGET, NODE_FORMAT_MODULE } from './constants.js'; import { RslibConfig } from '@rslib/core'; +import type { SecureServerSessionOptions } from 'node:http2'; +import { ServerOptions as HttpsServerOptions } from 'node:https'; +import { CorsOptions } from 'cors'; +import type { Options as HttpProxyMiddlewareOptions } from 'http-proxy-middleware'; export type StylesRollupPluginOptions = Parameters[0]; @@ -293,6 +296,12 @@ export interface UserConfig { * "bundle mode" means bundle everything up by using Rollup */ bundle?: BundleUserConfig; + + /** + * Server config + * @default false + */ + server?: boolean | ServerUserConfig; } export type PluginUserConfig = string | [string, Json?] | Plugin; @@ -511,3 +520,65 @@ export interface PackageJson { peerDependencies?: Record; [k: string]: string | Record | undefined; } + +export interface ServerPublicDirOptions { + /** + * The name of the public directory, can be set as a relative path or an absolute path. + */ + name?: string; +} + +export type ServerPublicDirOptionsWithString = ServerPublicDirOptions | string; + +export type ServerPublicDir = ServerPublicDirOptionsWithString | ServerPublicDirOptionsWithString[]; + +export type ServerProxyConfig = Record | HttpProxyMiddlewareOptions[]; + +export interface ServerUserConfig { + /** + * Serving static files from the directory + * @default { name: 'public', copyOnBuild: 'auto', watch: false } + */ + publicDir?: ServerPublicDir; + /** + * Specify a port number for server to listen. + * @default 5138 + * - 5 => nothing, just a prefix + * - 1 => i + * - 3 => c => three + * - 8 => e => eight + */ + port?: number; + /** + * Configure HTTPS options to enable HTTPS server. + * When enabled, HTTP server will be disabled. + */ + https?: HttpsServerOptions | SecureServerSessionOptions; + /** + * Specify the host that the server listens to. + * @default '0.0.0.0' + */ + host?: string; + /** + * Adds headers to all responses. + */ + headers?: Record; + /** + * Configure CORS for the dev server or preview server. + * - object: enable CORS with the specified options. + * - true: enable CORS with default options (allow all origins, not recommended). + * - false: disable CORS. + * @link https://github.com/expressjs/cors + */ + cors?: boolean | CorsOptions; + /** + * Configure proxy rules for the dev server or preview server to proxy requests to + * the specified service. + */ + proxy?: ServerProxyConfig; + /** + * Whether to enable serve bundled files in the server + * @default true + */ + autoServeBundle?: boolean; +} diff --git a/packages/pkg/tests/server/createServer.test.ts b/packages/pkg/tests/server/createServer.test.ts new file mode 100644 index 00000000..a7062353 --- /dev/null +++ b/packages/pkg/tests/server/createServer.test.ts @@ -0,0 +1,160 @@ +import { describe, it, expect, vi, afterEach, beforeAll, afterAll } from 'vitest'; +import { createServer, PkgServer } from '../../src/server/createServer'; +import { ServerUserConfig } from '../../src/types'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import type { IncomingMessage, ServerResponse } from 'http'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const FIXTURES_DIR = path.join(__dirname, 'fixtures'); + +// Mock http-proxy-middleware before import +vi.mock('http-proxy-middleware', () => { + return { + createProxyMiddleware: vi.fn((opts) => { + const target = typeof opts === 'string' ? opts : opts.target; + return (_req: IncomingMessage, res: ServerResponse, _next: unknown) => { + res.setHeader('X-Proxy-Target', target || 'unknown'); + res.end('proxied'); + }; + }), + }; +}); + +describe('createServer', () => { + let serverInstance: PkgServer | null; + let baseUrl: string; + + // Mock process.cwd to point to fixtures directory + beforeAll(() => { + vi.spyOn(process, 'cwd').mockReturnValue(FIXTURES_DIR); + }); + + afterEach(async () => { + if (serverInstance) { + await serverInstance.close(); + serverInstance = null; + } + vi.clearAllMocks(); + }); + + afterAll(() => { + vi.restoreAllMocks(); + }); + + // Helper to start server + const startServer = async (config: ServerUserConfig) => { + serverInstance = createServer(config); + const { port } = await serverInstance.listen(); + baseUrl = `http://localhost:${port}`; + return serverInstance; + }; + + it('should serve static files from default public directory', async () => { + await startServer({}); + const res = await fetch(`${baseUrl}/index.html`); + expect(res.status).toBe(404); + }); + + it('should serve static files from custom public directory', async () => { + await startServer({ publicDir: { name: 'public' } }); + const res = await fetch(`${baseUrl}/index.html`); + const text = await res.text(); + expect(res.status).toBe(200); + expect(text).toContain('Default Public'); + }); + + it('should serve bundled files from dist directory when autoServeBundle is true', async () => { + await startServer({ autoServeBundle: true }); + const res = await fetch(`${baseUrl}/index.js`); + const text = await res.text(); + expect(res.status).toBe(200); + expect(text).toContain("console.log('bundle')"); + }); + + it('should not serve bundled files when autoServeBundle is false', async () => { + await startServer({ autoServeBundle: false }); + const res = await fetch(`${baseUrl}/index.js`); + expect(res.status).toBe(404); + }); + + it('should set custom headers', async () => { + await startServer({ + headers: { + 'X-Custom-Header': 'foo', + }, + }); + const res = await fetch(`${baseUrl}/index.html`); + expect(res.headers.get('X-Custom-Header')).toBe('foo'); + }); + + it('should enable cors by default', async () => { + await startServer({}); + const res = await fetch(`${baseUrl}/index.html`, { + method: 'OPTIONS', + }); + expect(res.headers.get('Access-Control-Allow-Origin')).toBe('*'); + }); + + it('should configure cors', async () => { + await startServer({ + cors: { origin: 'http://example.com' }, + }); + const res = await fetch(`${baseUrl}/index.html`, { + method: 'OPTIONS', + headers: { + Origin: 'http://example.com', + 'Access-Control-Request-Method': 'GET', + }, + }); + + expect(res.headers.get('Access-Control-Allow-Origin')).toBe('http://example.com'); + }); + + it('should disable cors when set to false', async () => { + await startServer({ cors: false }); + const res = await fetch(`${baseUrl}/index.html`, { + method: 'OPTIONS', + }); + expect(res.headers.get('Access-Control-Allow-Origin')).toBeNull(); + }); + + it('should configure proxy (object)', async () => { + await startServer({ + proxy: { + '/api': { + target: 'http://api.example.com', + changeOrigin: true, + }, + }, + }); + const res = await fetch(`${baseUrl}/api/users`); + expect(res.headers.get('X-Proxy-Target')).toBe('http://api.example.com'); + const text = await res.text(); + expect(text).toBe('proxied'); + }); + + it('should configure proxy (string shortcut)', async () => { + await startServer({ + proxy: { + '/api': 'http://api.shortcut.com', + }, + }); + const res = await fetch(`${baseUrl}/api/users`); + expect(res.headers.get('X-Proxy-Target')).toBe('http://api.shortcut.com'); + }); + + it('should configure proxy (array)', async () => { + await startServer({ + proxy: [ + { + target: 'http://api.array.com', + }, + ], + }); + // Array config mounts middleware globally using app.use(createProxyMiddleware(options)) + const res = await fetch(`${baseUrl}/any/path`); + expect(res.headers.get('X-Proxy-Target')).toBe('http://api.array.com'); + }); +}); diff --git a/packages/pkg/tests/server/fixtures/.gitignore b/packages/pkg/tests/server/fixtures/.gitignore new file mode 100644 index 00000000..6159c12c --- /dev/null +++ b/packages/pkg/tests/server/fixtures/.gitignore @@ -0,0 +1 @@ +!*/ \ No newline at end of file diff --git a/packages/pkg/tests/server/fixtures/dist/index.js b/packages/pkg/tests/server/fixtures/dist/index.js new file mode 100644 index 00000000..d6571dd2 --- /dev/null +++ b/packages/pkg/tests/server/fixtures/dist/index.js @@ -0,0 +1 @@ +console.log('bundle'); \ No newline at end of file diff --git a/packages/pkg/tests/server/fixtures/public/index.html b/packages/pkg/tests/server/fixtures/public/index.html new file mode 100644 index 00000000..b62e08fe --- /dev/null +++ b/packages/pkg/tests/server/fixtures/public/index.html @@ -0,0 +1 @@ +

Default Public

\ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ae375a53..ce7c1339 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -382,6 +382,9 @@ importers: consola: specifier: ^3.4.2 version: 3.4.2 + cors: + specifier: ^2.8.5 + version: 2.8.5 debug: specifier: ^4.3.3 version: 4.4.3 @@ -391,6 +394,9 @@ importers: es-toolkit: specifier: ^1.32.0 version: 1.32.0 + express: + specifier: ^5.2.1 + version: 5.2.1 figures: specifier: ^6.1.0 version: 6.1.0 @@ -406,6 +412,9 @@ importers: gzip-size: specifier: ^7.0.0 version: 7.0.0 + http-proxy-middleware: + specifier: ^3.0.5 + version: 3.0.5 magic-string: specifier: ^0.25.7 version: 0.25.9 @@ -452,9 +461,15 @@ importers: '@types/babel__core': specifier: ^7.1.20 version: 7.1.20 + '@types/cors': + specifier: ^2.8.19 + version: 2.8.19 '@types/debug': specifier: ^4.1.12 version: 4.1.12 + '@types/express': + specifier: ^5.0.6 + version: 5.0.6 '@types/fs-extra': specifier: ^9.0.13 version: 9.0.13 @@ -3417,6 +3432,9 @@ packages: '@types/connect@3.4.35': resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} + '@types/cors@2.8.19': + resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==} + '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -3438,9 +3456,15 @@ packages: '@types/express-serve-static-core@4.19.7': resolution: {integrity: sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==} + '@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==} @@ -3465,6 +3489,9 @@ packages: '@types/http-errors@2.0.5': resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} + '@types/http-proxy@1.17.17': + resolution: {integrity: sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==} + '@types/http-proxy@1.17.9': resolution: {integrity: sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==} @@ -3594,6 +3621,9 @@ packages: '@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/sockjs@0.3.36': resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} @@ -3823,6 +3853,10 @@ packages: 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'} + acorn-globals@7.0.1: resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} @@ -4176,6 +4210,10 @@ packages: resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} 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'} + bonjour-service@1.3.0: resolution: {integrity: sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==} @@ -4567,6 +4605,10 @@ packages: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} + content-disposition@1.0.1: + resolution: {integrity: sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==} + engines: {node: '>=18'} + content-type@1.0.5: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} @@ -4593,6 +4635,10 @@ packages: cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} + cookie@0.7.1: resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} @@ -4618,6 +4664,10 @@ packages: core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + cosmiconfig@7.0.1: resolution: {integrity: sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==} engines: {node: '>=10'} @@ -5580,6 +5630,10 @@ packages: resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} + express@5.2.1: + resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} + engines: {node: '>= 18'} + extend-shallow@2.0.1: resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} engines: {node: '>=0.10.0'} @@ -5676,6 +5730,10 @@ packages: resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} engines: {node: '>= 0.8'} + finalhandler@2.1.1: + resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} + engines: {node: '>= 18.0.0'} + find-cache-dir@4.0.0: resolution: {integrity: sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==} engines: {node: '>=14.16'} @@ -5749,6 +5807,10 @@ packages: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} @@ -6094,6 +6156,10 @@ packages: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + http-parser-js@0.5.8: resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==} @@ -6110,6 +6176,10 @@ packages: '@types/express': optional: true + http-proxy-middleware@3.0.5: + resolution: {integrity: sha512-GLZZm1X38BPY4lkXA01jhwxvDoOkkXqjgVyUzVxiEK4iuRu03PZoYHhHRwxnfhQMDuaxi3vVri0YgSro/1oWqg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + http-proxy@1.18.1: resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} engines: {node: '>=8.0.0'} @@ -6154,6 +6224,10 @@ packages: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} + iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + engines: {node: '>=0.10.0'} + icss-utils@5.1.0: resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} engines: {node: ^10 || ^12 || >= 14} @@ -6443,6 +6517,9 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + is-reference@1.2.1: resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} @@ -7139,6 +7216,10 @@ packages: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} + media-typer@1.1.0: + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} + memfs@4.51.0: resolution: {integrity: sha512-4zngfkVM/GpIhC8YazOsM6E8hoB33NP0BCESPOA6z7qaL6umPJNqkO8CNYaLV2FB2MV6H1O3x2luHHOSqppv+A==} @@ -7161,6 +7242,10 @@ packages: 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'} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -7323,6 +7408,10 @@ packages: resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} engines: {node: '>= 0.6'} + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} @@ -7450,6 +7539,10 @@ packages: 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'} + neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} @@ -7796,6 +7889,9 @@ packages: path-to-regexp@3.3.0: resolution: {integrity: sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==} + path-to-regexp@8.3.0: + resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==} + path-type@3.0.0: resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} engines: {node: '>=4'} @@ -8546,6 +8642,10 @@ packages: resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} engines: {node: '>=0.6'} + qs@6.14.1: + resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==} + engines: {node: '>=0.6'} + query-string@8.2.0: resolution: {integrity: sha512-tUZIw8J0CawM5wyGBiDOAp7ObdRQh4uBor/fUR9ZjmbZVvw95OD9If4w3MQxr99rg0DJZ/9CIORcpEqU5hQG7g==} engines: {node: '>=14.16'} @@ -8582,6 +8682,10 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} + raw-body@3.0.2: + resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} + engines: {node: '>= 0.10'} + rc@1.2.8: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true @@ -8890,6 +8994,10 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + router@2.2.0: + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} + rsbuild-plugin-dts@0.9.1: resolution: {integrity: sha512-04pkKrebuajsCpC8Vj2z4n6NFFxUYAdUdqSQRFGkGhdmururoDFYW0k9+ZQq9XrSQTlB01F/HFv5mAc0dwG/Qg==} engines: {node: '>=16.7.0'} @@ -9129,6 +9237,10 @@ packages: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} + send@1.2.1: + resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} + engines: {node: '>= 18'} + serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} @@ -9143,6 +9255,10 @@ packages: resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} + serve-static@2.2.1: + resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} + engines: {node: '>= 18'} + set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} @@ -9352,6 +9468,10 @@ packages: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + std-env@3.10.0: resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} @@ -9813,6 +9933,10 @@ packages: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} + type-is@2.0.1: + resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} + engines: {node: '>= 0.6'} + typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} @@ -14105,6 +14229,10 @@ snapshots: dependencies: '@types/node': 20.19.25 + '@types/cors@2.8.19': + dependencies: + '@types/node': 20.19.25 + '@types/debug@4.1.12': dependencies: '@types/ms': 2.1.0 @@ -14134,6 +14262,13 @@ snapshots: '@types/range-parser': 1.2.4 '@types/send': 1.2.1 + '@types/express-serve-static-core@5.1.1': + dependencies: + '@types/node': 20.19.25 + '@types/qs': 6.9.7 + '@types/range-parser': 1.2.4 + '@types/send': 1.2.1 + '@types/express@4.17.25': dependencies: '@types/body-parser': 1.19.2 @@ -14141,6 +14276,12 @@ snapshots: '@types/qs': 6.9.7 '@types/serve-static': 1.15.10 + '@types/express@5.0.6': + dependencies: + '@types/body-parser': 1.19.2 + '@types/express-serve-static-core': 5.1.1 + '@types/serve-static': 2.2.0 + '@types/fs-extra@9.0.13': dependencies: '@types/node': 20.19.25 @@ -14163,6 +14304,10 @@ snapshots: '@types/http-errors@2.0.5': {} + '@types/http-proxy@1.17.17': + dependencies: + '@types/node': 20.19.25 + '@types/http-proxy@1.17.9': dependencies: '@types/node': 20.19.25 @@ -14305,6 +14450,11 @@ snapshots: '@types/node': 20.19.25 '@types/send': 0.17.6 + '@types/serve-static@2.2.0': + dependencies: + '@types/http-errors': 2.0.5 + '@types/node': 20.19.25 + '@types/sockjs@0.3.36': dependencies: '@types/node': 20.19.25 @@ -14605,6 +14755,11 @@ snapshots: mime-types: 2.1.35 negotiator: 0.6.3 + accepts@2.0.0: + dependencies: + mime-types: 3.0.1 + negotiator: 1.0.0 + acorn-globals@7.0.1: dependencies: acorn: 8.15.0 @@ -15015,6 +15170,20 @@ snapshots: transitivePeerDependencies: - supports-color + body-parser@2.2.2: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 4.4.3 + http-errors: 2.0.0 + iconv-lite: 0.7.2 + on-finished: 2.4.1 + qs: 6.14.1 + raw-body: 3.0.2 + type-is: 2.0.1 + transitivePeerDependencies: + - supports-color + bonjour-service@1.3.0: dependencies: fast-deep-equal: 3.1.3 @@ -15446,6 +15615,8 @@ snapshots: dependencies: safe-buffer: 5.2.1 + content-disposition@1.0.1: {} + content-type@1.0.5: {} conventional-changelog-angular@5.0.13: @@ -15476,6 +15647,8 @@ snapshots: cookie-signature@1.0.6: {} + cookie-signature@1.2.2: {} + cookie@0.7.1: {} copy-anything@2.0.6: @@ -15503,6 +15676,11 @@ snapshots: core-util-is@1.0.3: {} + cors@2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + cosmiconfig@7.0.1: dependencies: '@types/parse-json': 4.0.0 @@ -16640,6 +16818,39 @@ snapshots: transitivePeerDependencies: - supports-color + express@5.2.1: + dependencies: + accepts: 2.0.0 + body-parser: 2.2.2 + content-disposition: 1.0.1 + content-type: 1.0.5 + cookie: 0.7.1 + cookie-signature: 1.2.2 + debug: 4.4.3 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.1 + fresh: 2.0.0 + http-errors: 2.0.0 + merge-descriptors: 2.0.0 + mime-types: 3.0.1 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.7 + qs: 6.14.1 + range-parser: 1.2.1 + router: 2.2.0 + send: 1.2.1 + serve-static: 2.2.1 + statuses: 2.0.1 + type-is: 2.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + extend-shallow@2.0.1: dependencies: is-extendable: 0.1.1 @@ -16740,6 +16951,17 @@ snapshots: transitivePeerDependencies: - supports-color + finalhandler@2.1.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + find-cache-dir@4.0.0: dependencies: common-path-prefix: 3.0.0 @@ -16809,6 +17031,8 @@ snapshots: fresh@0.5.2: {} + fresh@2.0.0: {} + fs-extra@10.1.0: dependencies: graceful-fs: 4.2.11 @@ -17283,6 +17507,14 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + http-parser-js@0.5.8: {} http-proxy-agent@5.0.0: @@ -17305,6 +17537,17 @@ snapshots: transitivePeerDependencies: - debug + http-proxy-middleware@3.0.5: + dependencies: + '@types/http-proxy': 1.17.17 + debug: 4.4.3 + http-proxy: 1.18.1(debug@4.4.3) + is-glob: 4.0.3 + is-plain-object: 5.0.0 + micromatch: 4.0.8 + transitivePeerDependencies: + - supports-color + http-proxy@1.18.1(debug@4.4.3): dependencies: eventemitter3: 4.0.7 @@ -17355,6 +17598,10 @@ snapshots: dependencies: safer-buffer: 2.1.2 + iconv-lite@0.7.2: + dependencies: + safer-buffer: 2.1.2 + icss-utils@5.1.0(postcss@8.5.6): dependencies: postcss: 8.5.6 @@ -17593,6 +17840,8 @@ snapshots: is-potential-custom-element-name@1.0.1: {} + is-promise@4.0.0: {} + is-reference@1.2.1: dependencies: '@types/estree': 1.0.8 @@ -18656,6 +18905,8 @@ snapshots: media-typer@0.3.0: {} + media-typer@1.1.0: {} + memfs@4.51.0: dependencies: '@jsonjoy.com/json-pack': 1.21.0(tslib@2.8.1) @@ -18699,6 +18950,8 @@ snapshots: merge-descriptors@1.0.3: {} + merge-descriptors@2.0.0: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -19023,6 +19276,10 @@ snapshots: dependencies: mime-db: 1.54.0 + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + mime@1.6.0: {} mimic-fn@2.1.0: {} @@ -19118,6 +19375,8 @@ snapshots: negotiator@0.6.3: {} + negotiator@1.0.0: {} + neo-async@2.6.2: {} nice-try@1.0.5: {} @@ -19516,6 +19775,8 @@ snapshots: path-to-regexp@3.3.0: {} + path-to-regexp@8.3.0: {} + path-type@3.0.0: dependencies: pify: 3.0.0 @@ -20254,6 +20515,10 @@ snapshots: dependencies: side-channel: 1.1.0 + qs@6.14.1: + dependencies: + side-channel: 1.1.0 + query-string@8.2.0: dependencies: decode-uri-component: 0.4.1 @@ -20285,6 +20550,13 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 + raw-body@3.0.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.7.2 + unpipe: 1.0.0 + rc@1.2.8: dependencies: deep-extend: 0.6.0 @@ -20731,6 +21003,16 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.53.2 fsevents: 2.3.3 + router@2.2.0: + dependencies: + debug: 4.4.3 + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.3.0 + transitivePeerDependencies: + - supports-color + rsbuild-plugin-dts@0.9.1(@rsbuild/core@1.3.22)(typescript@5.9.2): dependencies: '@ast-grep/napi': 0.37.0 @@ -20950,6 +21232,22 @@ snapshots: transitivePeerDependencies: - supports-color + send@1.2.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.1 + mime-types: 3.0.2 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + serialize-javascript@6.0.2: dependencies: randombytes: 2.1.0 @@ -20985,6 +21283,15 @@ snapshots: transitivePeerDependencies: - supports-color + serve-static@2.2.1: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.1 + transitivePeerDependencies: + - supports-color + set-blocking@2.0.0: {} set-function-length@1.2.2: @@ -21212,6 +21519,8 @@ snapshots: statuses@2.0.1: {} + statuses@2.0.2: {} + std-env@3.10.0: {} stop-iteration-iterator@1.1.0: @@ -21750,6 +22059,12 @@ snapshots: media-typer: 0.3.0 mime-types: 2.1.35 + type-is@2.0.1: + dependencies: + content-type: 1.0.5 + media-typer: 1.1.0 + mime-types: 3.0.1 + typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4