From a848e97b6e1abac452896d290a5daa6125e23bf9 Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Sat, 4 Oct 2025 13:54:23 +0800 Subject: [PATCH 1/3] separate nitro via dedicated vite plugin --- examples/basic/vite.config.ts | 3 +- examples/experiments/vite.config.ts | 10 +- packages/start/package.json | 3 +- packages/start/src/config/dev-server.ts | 139 ++++ packages/start/src/config/fs-routes/index.ts | 252 ++++---- packages/start/src/config/index.ts | 612 +++++++++--------- packages/start/src/config/nitro-v2-plugin.ts | 212 ++++++ packages/start/src/config/nitroPlugin.ts | 298 --------- packages/start/src/config/output-directory.ts | 35 + packages/start/src/config/resolve-entries.ts | 0 packages/start/src/constants.ts | 26 +- packages/start/src/server/handler.ts | 278 ++++---- .../src/server/manifest/prod-ssr-manifest.ts | 163 ++--- packages/start/tsconfig.json | 16 +- 14 files changed, 1107 insertions(+), 940 deletions(-) create mode 100644 packages/start/src/config/dev-server.ts create mode 100644 packages/start/src/config/nitro-v2-plugin.ts delete mode 100644 packages/start/src/config/nitroPlugin.ts create mode 100644 packages/start/src/config/output-directory.ts create mode 100644 packages/start/src/config/resolve-entries.ts diff --git a/examples/basic/vite.config.ts b/examples/basic/vite.config.ts index f244fc1d1..917f05a22 100644 --- a/examples/basic/vite.config.ts +++ b/examples/basic/vite.config.ts @@ -1,6 +1,7 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import { defineConfig } from "vite"; export default defineConfig({ - plugins: [solidStart()] + plugins: [solidStart(), nitroV2Plugin({ preset: "node-server" })], }); diff --git a/examples/experiments/vite.config.ts b/examples/experiments/vite.config.ts index b530e6163..cecd8b944 100644 --- a/examples/experiments/vite.config.ts +++ b/examples/experiments/vite.config.ts @@ -1,10 +1,10 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import { defineConfig } from "vite"; export default defineConfig({ - plugins: [ - solidStart({ - middleware: "./src/middleware.ts" - }) - ] + plugins: [ + solidStart({ middleware: "./src/middleware.ts" }), + nitroV2Plugin({ preset: "vercel" }), + ], }); diff --git a/packages/start/package.json b/packages/start/package.json index d0aceea65..ebd5c8d1d 100644 --- a/packages/start/package.json +++ b/packages/start/package.json @@ -17,7 +17,8 @@ "./server/spa": "./dist/server/spa/index.jsx", "./client/spa": "./dist/client/spa/index.jsx", "./middleware": "./dist/middleware/index.jsx", - "./http": "./dist/http.js" + "./http": "./dist/server/http.js", + "./nitro-v2-plugin": "./dist/config/nitro-v2-plugin.js" }, "dependencies": { "@babel/core": "^7.28.3", diff --git a/packages/start/src/config/dev-server.ts b/packages/start/src/config/dev-server.ts new file mode 100644 index 000000000..0f51911b4 --- /dev/null +++ b/packages/start/src/config/dev-server.ts @@ -0,0 +1,139 @@ +import { + createApp, + createEvent, + type EventHandler, + eventHandler, + getHeader, +} from "h3"; +import { + type Connect, + isRunnableDevEnvironment, + type PluginOption, + type ViteDevServer, +} from "vite"; +import { VITE_ENVIRONMENT_NAMES } from "../constants.js"; + +export function devServerPlugin(): PluginOption { + return { + name: "solid-start:dev-server-plugin", + configureServer(viteDevServer) { + (globalThis as any).VITE_DEV_SERVER = viteDevServer; + return async () => { + removeHtmlMiddlewares(viteDevServer); + + const serverEnv = + viteDevServer.environments[VITE_ENVIRONMENT_NAMES.server]; + + if (!serverEnv) throw new Error("Server environment not found"); + if (!isRunnableDevEnvironment(serverEnv)) + throw new Error("Server environment is not runnable"); + + const h3App = createApp(); + + h3App.use( + eventHandler(async (event) => { + const serverEntry: { + default: EventHandler; + } = await serverEnv.runner.import("./src/entry-server.tsx"); + + return await serverEntry.default(event).catch((e: unknown) => { + console.error(e); + viteDevServer.ssrFixStacktrace(e as Error); + + if ( + getHeader(event, "content-type")?.includes("application/json") + ) { + return Response.json( + { + status: 500, + error: "Internal Server Error", + message: + "An unexpected error occurred. Please try again later.", + timestamp: new Date().toISOString(), + }, + { + status: 500, + headers: { + "Content-Type": "application/json", + }, + }, + ); + } + + return new Response( + ` + + + + + Error + + + + + + `, + { + status: 500, + headers: { + "Content-Type": "text/html", + }, + }, + ); + }); + }), + ); + + viteDevServer.middlewares.use(async (req, res) => { + const event = createEvent(req, res); + event.context.viteDevServer = viteDevServer; + await h3App.handler(event); + }); + }; + }, + }; +} + +/** + * Removes Vite internal middleware + * + * @param server + */ +function removeHtmlMiddlewares(server: ViteDevServer) { + const html_middlewares = [ + "viteIndexHtmlMiddleware", + "vite404Middleware", + "viteSpaFallbackMiddleware", + ]; + for (let i = server.middlewares.stack.length - 1; i > 0; i--) { + if ( + html_middlewares.includes( + // @ts-expect-error + server.middlewares.stack[i].handle.name, + ) + ) { + server.middlewares.stack.splice(i, 1); + } + } +} + +/** + * Formats error for SSR message in error overlay + * @param req + * @param error + * @returns + */ +function prepareError(req: Connect.IncomingMessage, error: unknown) { + const e = error as Error; + return { + message: `An error occured while server rendering ${req.url}:\n\n\t${ + typeof e === "string" ? e : e.message + } `, + stack: typeof e === "string" ? "" : e.stack, + }; +} diff --git a/packages/start/src/config/fs-routes/index.ts b/packages/start/src/config/fs-routes/index.ts index 900c9a437..c35fafce3 100644 --- a/packages/start/src/config/fs-routes/index.ts +++ b/packages/start/src/config/fs-routes/index.ts @@ -1,7 +1,7 @@ import { relative } from "node:path"; import type { PluginOption } from "vite"; -import { VITE_ENVIRONMENTS } from "../../constants.js"; +import { VITE_ENVIRONMENT_NAMES } from "../../constants.js"; import { fileSystemWatcher } from "./fs-watcher.js"; import type { BaseFileSystemRouter } from "./router.js"; import { treeShake } from "./tree-shake.js"; @@ -9,139 +9,143 @@ import { treeShake } from "./tree-shake.js"; export const moduleId = "solid-start:routes"; export interface FsRoutesArgs { - routers: Record<"client" | "ssr", BaseFileSystemRouter>; + routers: Record<"client" | "ssr", BaseFileSystemRouter>; } export function fsRoutes({ routers }: FsRoutesArgs): Array { - (globalThis as any).ROUTERS = routers; - - return [ - { - name: "solid-start-fs-routes", - enforce: "pre", - resolveId(id) { - if (id === moduleId) return id; - }, - async load(id) { - const root = this.environment.config.root; - const isBuild = this.environment.mode === "build"; - - if (id !== moduleId) return; - const js = jsCode(); - - const router = (globalThis as any).ROUTERS[this.environment.name]; - - const routes = await router.getRoutes(); - - let routesCode = JSON.stringify(routes ?? [], (k, v) => { - if (v === undefined) return undefined; - - if (k.startsWith("$$")) { - const buildId = `${v.src}?${v.pick.map((p: any) => `pick=${p}`).join("&")}`; - - /** - * @type {{ [key: string]: string }} - */ - const refs: Record = {}; - for (var pick of v.pick) { - refs[pick] = js.addNamedImport(pick, buildId); - } - return { - require: `_$() => ({ ${Object.entries(refs) - .map(([pick, namedImport]) => `'${pick}': ${namedImport}`) - .join(", ")} })$_` - // src: isBuild ? relative(root, buildId) : buildId - }; - } else if (k.startsWith("$")) { - const buildId = `${v.src}?${v.pick.map((p: any) => `pick=${p}`).join("&")}`; - return { - src: relative(root, buildId), - build: isBuild ? `_$() => import(/* @vite-ignore */ '${buildId}')$_` : undefined, - import: - this.environment.name === VITE_ENVIRONMENTS.server - ? `_$() => import(/* @vite-ignore */ '${buildId}')$_` - : `_$(() => clientManifestImport('${relative(root, buildId)}'))$_` - }; - } - return v; - }); - - routesCode = routesCode.replaceAll('"_$(', "(").replaceAll(')$_"', ")"); - - const code = ` + (globalThis as any).ROUTERS = routers; + + return [ + { + name: "solid-start-fs-routes", + enforce: "pre", + resolveId(id) { + if (id === moduleId) return id; + }, + async load(id) { + const root = this.environment.config.root; + const isBuild = this.environment.mode === "build"; + + if (id !== moduleId) return; + const js = jsCode(); + + const router = (globalThis as any).ROUTERS[this.environment.name]; + + const routes = await router.getRoutes(); + + let routesCode = JSON.stringify(routes ?? [], (k, v) => { + if (v === undefined) return undefined; + + if (k.startsWith("$$")) { + const buildId = `${v.src}?${v.pick.map((p: any) => `pick=${p}`).join("&")}`; + + /** + * @type {{ [key: string]: string }} + */ + const refs: Record = {}; + for (var pick of v.pick) { + refs[pick] = js.addNamedImport(pick, buildId); + } + return { + require: `_$() => ({ ${Object.entries(refs) + .map(([pick, namedImport]) => `'${pick}': ${namedImport}`) + .join(", ")} })$_`, + // src: isBuild ? relative(root, buildId) : buildId + }; + } else if (k.startsWith("$")) { + const buildId = `${v.src}?${v.pick.map((p: any) => `pick=${p}`).join("&")}`; + return { + src: relative(root, buildId), + build: isBuild + ? `_$() => import(/* @vite-ignore */ '${buildId}')$_` + : undefined, + import: + this.environment.name === VITE_ENVIRONMENT_NAMES.server + ? `_$() => import(/* @vite-ignore */ '${buildId}')$_` + : `_$(() => clientManifestImport('${relative(root, buildId)}'))$_`, + }; + } + return v; + }); + + routesCode = routesCode.replaceAll('"_$(', "(").replaceAll(')$_"', ")"); + + const code = ` ${js.getImportStatements()} -${this.environment.name === VITE_ENVIRONMENTS.server - ? "" - : ` +${ + this.environment.name === VITE_ENVIRONMENT_NAMES.server + ? "" + : ` import { getClientManifest } from "solid-start:get-client-manifest"; function clientManifestImport(id) { return getClientManifest().import(id) }` - } +} export default ${routesCode}`; - return code; - } - }, - treeShake(), - fileSystemWatcher(routers) - ]; + return code; + }, + }, + treeShake(), + fileSystemWatcher(routers), + ]; } function jsCode() { - let imports = new Map(); - let vars = 0; - - function addImport(p: any) { - let id = imports.get(p); - if (!id) { - id = {}; - imports.set(p, id); - } - - let d = "routeData" + vars++; - id["default"] = d; - return d; - } - - function addNamedImport(name: string | number, p: any) { - let id = imports.get(p); - if (!id) { - id = {}; - imports.set(p, id); - } - - let d = "routeData" + vars++; - id[name] = d; - return d; - } - - const getNamedExport = (p: any) => { - let id = imports.get(p); - - delete id["default"]; - - return Object.keys(id).length > 0 - ? `{ ${Object.keys(id) - .map(k => `${k} as ${id[k]}`) - .join(", ")} }` - : ""; - }; - - const getImportStatements = () => { - return `${[...imports.keys()] - .map( - i => - `import ${imports.get(i).default - ? `${imports.get(i).default}${Object.keys(imports.get(i)).length > 1 ? ", " : ""}` - : "" - } ${getNamedExport(i)} from '${i}';` - ) - .join("\n")}`; - }; - - return { - addImport, - addNamedImport, - getImportStatements - }; + const imports = new Map(); + let vars = 0; + + function addImport(p: any) { + let id = imports.get(p); + if (!id) { + id = {}; + imports.set(p, id); + } + + const d = "routeData" + vars++; + id["default"] = d; + return d; + } + + function addNamedImport(name: string | number, p: any) { + let id = imports.get(p); + if (!id) { + id = {}; + imports.set(p, id); + } + + const d = "routeData" + vars++; + id[name] = d; + return d; + } + + const getNamedExport = (p: any) => { + const id = imports.get(p); + + delete id["default"]; + + return Object.keys(id).length > 0 + ? `{ ${Object.keys(id) + .map((k) => `${k} as ${id[k]}`) + .join(", ")} }` + : ""; + }; + + const getImportStatements = () => { + return `${[...imports.keys()] + .map( + (i) => + `import ${ + imports.get(i).default + ? `${imports.get(i).default}${Object.keys(imports.get(i)).length > 1 ? ", " : ""}` + : "" + } ${getNamedExport(i)} from '${i}';`, + ) + .join("\n")}`; + }; + + return { + addImport, + addNamedImport, + getImportStatements, + }; } diff --git a/packages/start/src/config/index.ts b/packages/start/src/config/index.ts index 74f28bb95..59cce21dd 100644 --- a/packages/start/src/config/index.ts +++ b/packages/start/src/config/index.ts @@ -1,326 +1,354 @@ -import { TanStackServerFnPluginEnv } from "@tanstack/server-functions-plugin"; -import { defu } from "defu"; import { globSync } from "node:fs"; -import path, { extname, isAbsolute, join, normalize } from "node:path"; +import { extname, isAbsolute, join, normalize } from "node:path"; import { fileURLToPath } from "node:url"; -import { normalizePath, type PluginOption, type Rollup, type ViteDevServer } from "vite"; +import { TanStackServerFnPluginEnv } from "@tanstack/server-functions-plugin"; +import { defu } from "defu"; +import { + normalizePath, + type PluginOption, + type Rollup, + type ViteDevServer, +} from "vite"; import solid, { type Options as SolidOptions } from "vite-plugin-solid"; -import { CLIENT_BASE_PATH, DEFAULT_EXTENSIONS, VIRTUAL_MODULES, VITE_ENVIRONMENTS } from "../constants.js"; +import { + DEFAULT_EXTENSIONS, + ENTRY_POINTS, + VIRTUAL_MODULES, + VITE_ENVIRONMENT_NAMES, + type ViteEnvironmentNames, +} from "../constants.js"; import { isCssModulesFile } from "../server/collect-styles.js"; import { getSsrDevManifest } from "../server/manifest/dev-ssr-manifest.js"; -import { SolidStartClientFileRouter, SolidStartServerFileRouter } from "./fs-router.js"; +import { devServerPlugin } from "./dev-server.js"; +import { + SolidStartClientFileRouter, + SolidStartServerFileRouter, +} from "./fs-router.js"; import { fsRoutes } from "./fs-routes/index.js"; import type { BaseFileSystemRouter } from "./fs-routes/router.js"; import { - clientDistDir, - nitroPlugin, - serverDistDir, - ssrEntryFile, - type UserNitroConfig -} from "./nitroPlugin.js"; - -export type { UserNitroConfig } from "./nitroPlugin.js"; + getClientOutputDirectory, + getOutputDirectory, + getServerOutputDirectory, +} from "./output-directory.js"; export interface SolidStartOptions { - solid?: Partial; - ssr?: boolean; - routeDir?: string; - extensions?: string[]; - server?: UserNitroConfig; - middleware?: string; + solid?: Partial; + ssr?: boolean; + routeDir?: string; + extensions?: string[]; + middleware?: string; } const absolute = (path: string, root: string) => - path ? (isAbsolute(path) ? path : join(root, path)) : path; + path ? (isAbsolute(path) ? path : join(root, path)) : path; + +function solidStartVitePlugin( + options?: SolidStartOptions, +): Array { + const start = defu(options ?? {}, { + appRoot: "./src", + routeDir: "./routes", + ssr: true, + devOverlay: true, + experimental: { + islands: false, + }, + solid: {}, + extensions: [], + }); + const extensions = [...DEFAULT_EXTENSIONS, ...(start.extensions || [])]; -// this needs to live outside of the TanStackStartVitePlugin since it will be invoked multiple times by vite -let ssrBundle: Rollup.OutputBundle; + const routeDir = join(start.appRoot, start.routeDir); -function solidStartVitePlugin(options?: SolidStartOptions): Array { - const start = defu(options ?? {}, { - appRoot: "./src", - routeDir: "./routes", - ssr: true, - devOverlay: true, - experimental: { - islands: false - }, - solid: {}, - server: { - ...options?.server, - routeRules: { - "/_build/assets/**": { - headers: { "cache-control": "public, immutable, max-age=31536000" } - } - }, - experimental: { - asyncContext: true - } - }, - extensions: [] - }); - const extensions = [...DEFAULT_EXTENSIONS, ...(start.extensions || [])]; + const root = process.cwd(); + const appEntryPath = globSync(join(root, start.appRoot, "app.{j,t}sx"))[0]; + if (!appEntryPath) { + throw new Error(`Could not find an app jsx/tsx entry in ${start.appRoot}.`); + } + const entryExtension = extname(appEntryPath); - const routeDir = join(start.appRoot, start.routeDir); + const handlers = { + client: `${start.appRoot}/entry-client${entryExtension}`, + server: `${start.appRoot}/entry-server${entryExtension}`, + }; - const root = process.cwd(); - const appEntryPath = globSync(join(root, start.appRoot, "app.{j,t}sx"))[0]; - if (!appEntryPath) { - throw new Error(`Could not find an app jsx/tsx entry in ${start.appRoot}.`); - } - const entryExtension = extname(appEntryPath); + return [ + { + name: "solid-start:vite-config", + enforce: "pre", + configEnvironment(name) { + return { + define: { + "import.meta.env.SSR": JSON.stringify( + name === VITE_ENVIRONMENT_NAMES.server, + ), + }, + }; + }, + async config(viteConfig, env) { + const clientInput = [handlers.client]; - const handlers = { - client: `${start.appRoot}/entry-client${entryExtension}`, - server: `${start.appRoot}/entry-server${entryExtension}` - }; + if (env.command === "build") { + const clientRouter: BaseFileSystemRouter = (globalThis as any).ROUTERS + .client; + for (const route of await clientRouter.getRoutes()) { + for (const [key, value] of Object.entries(route)) { + if (value && key.startsWith("$") && !key.startsWith("$$")) { + function toRouteId(route: any) { + return `${route.src}?${route.pick.map((p: string) => `pick=${p}`).join("&")}`; + } - return [ - { - name: "solid-start:vite-config", - enforce: "pre", - configEnvironment(name) { - return { - define: { - "import.meta.env.SSR": JSON.stringify(name === VITE_ENVIRONMENTS.server) - } - }; - }, - async config(_, env) { - const clientInput = [handlers.client]; + clientInput.push(toRouteId(value)); + } + } + } + } - if (env.command === "build") { - const clientRouter: BaseFileSystemRouter = (globalThis as any).ROUTERS.client - for (const route of await clientRouter.getRoutes()) { - for (const [key, value] of Object.entries(route)) { - if (value && key.startsWith("$") && !key.startsWith("$$")) { - function toRouteId(route: any) { - return `${route.src}?${route.pick.map((p: string) => `pick=${p}`).join("&")}`; - } + return { + appType: viteConfig.appType ?? "custom", + build: { assetsDir: "_build/assets" }, + environments: { + [VITE_ENVIRONMENT_NAMES.client]: { + consumer: "client", + build: { + manifest: true, + outDir: getClientOutputDirectory(viteConfig), + rollupOptions: { + input: ENTRY_POINTS.client, + }, + }, + }, + [VITE_ENVIRONMENT_NAMES.server]: { + consumer: "server", + build: { + ssr: true, + rollupOptions: { + input: + viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server] + ?.build?.rollupOptions?.input ?? ENTRY_POINTS.server, + }, + outDir: getServerOutputDirectory(viteConfig), + copyPublicDir: + viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server] + ?.build?.copyPublicDir ?? false, + }, + }, + }, + resolve: { + alias: { + "#start/app": appEntryPath, + "~": join(process.cwd(), start.appRoot), + ...(!start.ssr + ? { + "@solidjs/start/server": "@solidjs/start/server/spa", + "@solidjs/start/client": "@solidjs/start/client/spa", + } + : {}), + [ENTRY_POINTS.client]: handlers.client, + [ENTRY_POINTS.server]: handlers.server, + }, + }, + define: { + "import.meta.env.MANIFEST": `globalThis.MANIFEST`, + "import.meta.env.START_SSR": JSON.stringify(start.ssr), + "import.meta.env.START_APP_ENTRY": `"${normalizePath(appEntryPath)}"`, + "import.meta.env.START_CLIENT_ENTRY": `"${normalizePath(handlers.client)}"`, + "import.meta.env.SERVER_BASE_URL": JSON.stringify( + viteConfig.base ?? "", + ), + "import.meta.env.START_DEV_OVERLAY": JSON.stringify( + start.devOverlay, + ), + }, + builder: { + sharedPlugins: true, + async buildApp(builder) { + const client = + builder.environments[VITE_ENVIRONMENT_NAMES.client]; + const server = + builder.environments[VITE_ENVIRONMENT_NAMES.server]; - clientInput.push(toRouteId(value)); - } - } - } - } + if (!client) { + throw new Error("Client environment not found"); + } - return { - base: env.command === "build" ? `/${CLIENT_BASE_PATH}` : undefined, - environments: { - [VITE_ENVIRONMENTS.client]: { - consumer: "client", - build: { - copyPublicDir: false, - write: true, - manifest: true, - rollupOptions: { - input: clientInput, - output: { - dir: path.resolve(process.cwd(), clientDistDir, CLIENT_BASE_PATH) - }, - external: ["node:fs", "node:path", "node:os", "node:crypto"], - treeshake: true, - preserveEntrySignatures: "exports-only", - } - } - }, - [VITE_ENVIRONMENTS.server]: { - consumer: "server", - build: { - ssr: true, - write: true, - manifest: true, - copyPublicDir: false, - rollupOptions: { - output: { - dir: path.resolve(process.cwd(), serverDistDir), - entryFileNames: ssrEntryFile - }, - plugins: [ - { - name: "capture-output", - generateBundle(options, bundle) { - // TODO can this hook be called more than once? - ssrBundle = bundle; - } - } - ] as Array - }, - commonjsOptions: { - include: [/node_modules/] - } - } - } - }, - resolve: { - alias: { - "#start/app": appEntryPath, - "~": join(process.cwd(), start.appRoot), - ...(!start.ssr - ? { - "@solidjs/start/server": "@solidjs/start/server/spa", - "@solidjs/start/client": "@solidjs/start/client/spa" - } - : {}) - } - }, - define: { - "import.meta.env.MANIFEST": `globalThis.MANIFEST`, - "import.meta.env.START_SSR": JSON.stringify(start.ssr), - "import.meta.env.START_APP_ENTRY": `"${normalizePath(appEntryPath)}"`, - "import.meta.env.START_CLIENT_ENTRY": `"${normalizePath(handlers.client)}"`, - "import.meta.env.SERVER_BASE_URL": JSON.stringify((start.server as any).baseURL ?? ""), - "import.meta.env.START_DEV_OVERLAY": JSON.stringify(start.devOverlay), - } - }; - } - }, - css(), - fsRoutes({ - routers: { - client: - new SolidStartClientFileRouter({ - dir: absolute(routeDir, root), - extensions - }), - ssr: - new SolidStartServerFileRouter({ - dir: absolute(routeDir, root), - extensions, - dataOnly: !start.ssr - }) - } - }), - // Must be placed after fsRoutes, as treeShake will remove the - // server fn exports added in by this plugin - TanStackServerFnPluginEnv({ - // This is the ID that will be available to look up and import - // our server function manifest and resolve its module - manifestVirtualImportId: VIRTUAL_MODULES.serverFnManifest, - client: { - envName: VITE_ENVIRONMENTS.client, - getRuntimeCode: () => - `import { createServerReference } from "${normalize( - fileURLToPath(new URL("../server/server-runtime.js", import.meta.url)) - )}"`, - replacer: opts => - `createServerReference(${() => { }}, '${opts.functionId}', '${opts.extractedFilename}')` - }, - server: { - envName: VITE_ENVIRONMENTS.server, - getRuntimeCode: () => - `import { createServerReference } from '${normalize( - fileURLToPath(new URL("../server/server-fns-runtime.js", import.meta.url)) - )}'`, - replacer: opts => - `createServerReference(${opts.fn}, '${opts.functionId}', '${opts.extractedFilename}')` - } - }), - { - name: "solid-start:manifest-plugin", - enforce: "pre", - async resolveId(id) { - if (id === VIRTUAL_MODULES.clientViteManifest) return `\0${VIRTUAL_MODULES.clientViteManifest}`; - if (id === VIRTUAL_MODULES.getClientManifest) - return this.resolve(new URL("../server/manifest/client-manifest", import.meta.url).pathname); - if (id === VIRTUAL_MODULES.getManifest) { - return this.environment.config.consumer === "client" ? - this.resolve(new URL("../server/manifest/client-manifest", import.meta.url).pathname) : - this.resolve(new URL("../server/manifest/ssr-manifest", import.meta.url).pathname); - } - if (id === VIRTUAL_MODULES.middleware) { - if (start.middleware) return await this.resolve(start.middleware); + if (!server) { + throw new Error("SSR environment not found"); + } - return `\0${VIRTUAL_MODULES.middleware}`; - } - }, - async load(id) { - if (id === `\0${VIRTUAL_MODULES.clientViteManifest}`) { - let clientViteManifest: Record>; + if (!client.isBuilt) { + // Build the client bundle first + await builder.build(client); + } + if (!server.isBuilt) { + // Build the SSR bundle + await builder.build(server); + } + }, + }, + }; + }, + }, + css(), + fsRoutes({ + routers: { + client: new SolidStartClientFileRouter({ + dir: absolute(routeDir, root), + extensions, + }), + ssr: new SolidStartServerFileRouter({ + dir: absolute(routeDir, root), + extensions, + dataOnly: !start.ssr, + }), + }, + }), + // Must be placed after fsRoutes, as treeShake will remove the + // server fn exports added in by this plugin + TanStackServerFnPluginEnv({ + // This is the ID that will be available to look up and import + // our server function manifest and resolve its module + manifestVirtualImportId: VIRTUAL_MODULES.serverFnManifest, + client: { + envName: VITE_ENVIRONMENT_NAMES.client, + getRuntimeCode: () => + `import { createServerReference } from "${normalize( + fileURLToPath( + new URL("../server/server-runtime.js", import.meta.url), + ), + )}"`, + replacer: (opts) => + `createServerReference(${() => {}}, '${opts.functionId}', '${opts.extractedFilename}')`, + }, + server: { + envName: VITE_ENVIRONMENT_NAMES.server, + getRuntimeCode: () => + `import { createServerReference } from '${normalize( + fileURLToPath( + new URL("../server/server-fns-runtime.js", import.meta.url), + ), + )}'`, + replacer: (opts) => + `createServerReference(${opts.fn}, '${opts.functionId}', '${opts.extractedFilename}')`, + }, + }), + { + name: "solid-start:manifest-plugin", + enforce: "pre", + async resolveId(id) { + if (id === VIRTUAL_MODULES.clientViteManifest) + return `\0${VIRTUAL_MODULES.clientViteManifest}`; + if (id === VIRTUAL_MODULES.middleware) + return `\0${VIRTUAL_MODULES.middleware}`; + if (id === VIRTUAL_MODULES.getClientManifest) + return this.resolve( + new URL("../server/manifest/client-manifest", import.meta.url) + .pathname, + ); + if (id === VIRTUAL_MODULES.getManifest) { + return this.environment.config.consumer === "client" + ? this.resolve( + new URL("../server/manifest/client-manifest", import.meta.url) + .pathname, + ) + : this.resolve( + new URL("../server/manifest/ssr-manifest", import.meta.url) + .pathname, + ); + } + if (id === VIRTUAL_MODULES.middleware) { + if (start.middleware) return await this.resolve(start.middleware); + } + }, + async load(id) { + if (id === `\0${VIRTUAL_MODULES.clientViteManifest}`) { + let clientViteManifest: Record> = {}; - if (this.environment.config.command === "serve") { - clientViteManifest = {}; - } else { - const entry = Object.values(globalThis.START_CLIENT_BUNDLE).find( - v => "isEntry" in v && v.isEntry - ); - if (!entry) throw new Error("No client entry found"); + if (this.environment.config.command === "serve") { + clientViteManifest = {}; + } else { + const entry = Object.values(globalThis.START_CLIENT_BUNDLE).find( + (v) => "isEntry" in v && v.isEntry, + ); + if (!entry) throw new Error("No client entry found"); - clientViteManifest = JSON.parse( - (globalThis.START_CLIENT_BUNDLE[".vite/manifest.json"] as any).source - ); - } + clientViteManifest = JSON.parse( + (globalThis.START_CLIENT_BUNDLE[".vite/manifest.json"] as any) + .source, + ); + } - return `export const clientViteManifest = ${JSON.stringify(clientViteManifest)};`; - } - else if (id === `\0${VIRTUAL_MODULES.middleware}`) return "export default {};" - else if (id.startsWith("/@manifest")) { - const [path, query] = id.split("?"); - const params = new URLSearchParams(query); - if (!path || !query) return; - if (path.endsWith("assets")) { - const id = params.get("id"); - if (!id) { - throw new Error("Missing id to get assets."); - } - return `export default ${JSON.stringify( - await getSsrDevManifest("server").getAssets(id) - )}`; - } - } - } - }, - nitroPlugin({ root: process.cwd() }, () => ssrBundle, start.server as UserNitroConfig), - { - name: "solid-start:capture-client-bundle", - enforce: "post", - generateBundle(_options, bundle) { - globalThis.START_CLIENT_BUNDLE = bundle; - } - }, - solid({ - ...start.solid, - ssr: true, - extensions: extensions.map(ext => `.${ext}`) - }) - ]; + return `export const clientViteManifest = ${JSON.stringify(clientViteManifest)};`; + } else if (id === `\0${VIRTUAL_MODULES.middleware}`) { + return "export default {};"; + } else if (id.startsWith("/@manifest")) { + const [path, query] = id.split("?"); + const params = new URLSearchParams(query); + if (!path || !query) return; + if (path.endsWith("assets")) { + const id = params.get("id"); + if (!id) { + throw new Error("Missing id to get assets."); + } + return `export default ${JSON.stringify( + await getSsrDevManifest("server").getAssets(id), + )}`; + } + } + }, + }, + devServerPlugin(), + { + name: "solid-start:capture-client-bundle", + enforce: "post", + generateBundle(_options, bundle) { + globalThis.START_CLIENT_BUNDLE = bundle; + }, + }, + solid({ + ...start.solid, + ssr: true, + extensions: extensions.map((ext) => `.${ext}`), + }), + ]; } export { solidStartVitePlugin as solidStart }; function css(): PluginOption { - let viteServer!: ViteDevServer; - let cssModules: Record = {}; + let viteServer!: ViteDevServer; + const cssModules: Record = {}; - return { - name: "solid-start:css-hmr", - configureServer(dev) { - viteServer = dev; - }, - async handleHotUpdate({ file, server }) { - if (file.endsWith(".css")) { - const resp = await server.transformRequest(file); - if (!resp) return; - const json = resp.code - .match(/const __vite__css = .*\n/)?.[0] - ?.slice("const __vite__css = ".length); - if (!json) return; - resp.code = JSON.parse(json); - viteServer.ws.send({ - type: "custom", - event: "css-update", - data: { - file, - contents: resp.code - } - }); - } - }, - transform(code, id) { - if (isCssModulesFile(id)) { - cssModules[id] = code; - } - } - }; + return { + name: "solid-start:css-hmr", + configureServer(dev) { + viteServer = dev; + }, + async handleHotUpdate({ file, server }) { + if (file.endsWith(".css")) { + const resp = await server.transformRequest(file); + if (!resp) return; + const json = resp.code + .match(/const __vite__css = .*\n/)?.[0] + ?.slice("const __vite__css = ".length); + if (!json) return; + resp.code = JSON.parse(json); + viteServer.ws.send({ + type: "custom", + event: "css-update", + data: { + file, + contents: resp.code, + }, + }); + } + }, + transform(code, id) { + if (isCssModulesFile(id)) { + cssModules[id] = code; + } + }, + }; } diff --git a/packages/start/src/config/nitro-v2-plugin.ts b/packages/start/src/config/nitro-v2-plugin.ts new file mode 100644 index 000000000..af51c7e1c --- /dev/null +++ b/packages/start/src/config/nitro-v2-plugin.ts @@ -0,0 +1,212 @@ +import { dirname, resolve } from "node:path"; +import { + build, + copyPublicAssets, + createNitro, + type NitroConfig, + prepare, + prerender, +} from "nitropack"; +import type { + EnvironmentOptions, + PluginOption, + ResolvedConfig, + Rollup, +} from "vite"; +import { VITE_ENVIRONMENT_NAMES } from "../constants.js"; + +let ssrBundle: Rollup.OutputBundle; +let ssrEntryFile: string; + +function isFullUrl(str: string): boolean { + try { + new URL(str); + return true; + } catch { + return false; + } +} + +export function nitroV2Plugin(nitroConfig?: NitroConfig): PluginOption { + let resolvedConfig: ResolvedConfig; + return { + name: "solid-start:nitro-v2-plugin", + generateBundle: { + handler(_options, bundle) { + if (this.environment.name !== "ssr") { + return; + } + + // find entry point of ssr bundle + let entryFile: string | undefined; + for (const [_name, file] of Object.entries(bundle)) { + if (file.type === "chunk") { + if (file.isEntry) { + if (entryFile !== undefined) { + this.error( + `Multiple entry points found for service "${this.environment.name}". Only one entry point is allowed.`, + ); + } + entryFile = file.fileName; + } + } + } + if (entryFile === undefined) { + this.error( + `No entry point found for service "${this.environment.name}".`, + ); + } + ssrEntryFile = entryFile!; + ssrBundle = bundle; + }, + }, + configEnvironment(name) { + if (name === VITE_ENVIRONMENT_NAMES.server) { + return { + build: { + commonjsOptions: { + include: [], + }, + ssr: true, + sourcemap: true, + rollupOptions: { + input: "~/entry-server.tsx", + }, + }, + } satisfies EnvironmentOptions; + } + + return null; + }, + configResolved(config) { + resolvedConfig = config; + }, + config(_, env) { + if (env.command !== "build") { + return; + } + + return { + environments: { + ssr: { + consumer: "server", + build: { + ssr: true, + // we don't write to the file system as the below 'capture-output' plugin will + // capture the output and write it to the virtual file system + write: false, + copyPublicDir: false, + }, + }, + }, + builder: { + sharedPlugins: true, + async buildApp(builder) { + const clientEnv = + builder.environments[VITE_ENVIRONMENT_NAMES.client]; + const serverEnv = + builder.environments[VITE_ENVIRONMENT_NAMES.server]; + + if (!clientEnv) throw new Error("Client environment not found"); + if (!serverEnv) throw new Error("SSR environment not found"); + + await builder.build(clientEnv); + await builder.build(serverEnv); + + const virtualEntry = "#solid-start/entry"; + const baseURL = !isFullUrl(resolvedConfig.base) + ? resolvedConfig.base + : undefined; + + const config: NitroConfig = { + baseURL, + typescript: { + generateTsConfig: false, + generateRuntimeConfigTypes: false, + }, + publicAssets: [{ dir: clientEnv.config.build.outDir }], + ...nitroConfig, + routeRules: { + ...nitroConfig?.routeRules, + [`/${clientEnv.config.build.assetsDir}/**`]: { + headers: { + "cache-control": "public, immutable, max-age=31536000", + }, + }, + }, + experimental: { + asyncContext: true, + ...nitroConfig?.experimental, + }, + renderer: ssrEntryFile, + rollupConfig: { + ...nitroConfig?.rollupConfig, + plugins: [virtualBundlePlugin(ssrBundle) as any], + }, + virtual: { + ...nitroConfig?.virtual, + [virtualEntry]: `import { fromWebHandler } from 'h3' + import handler from '${ssrEntryFile}' + export default fromWebHandler(handler.fetch)`, + }, + }; + + const nitro = await createNitro(config); + + await prepare(nitro); + await copyPublicAssets(nitro); + await prerender(nitro); + await build(nitro); + + await nitro.close(); + }, + }, + }; + }, + }; +} + +function virtualBundlePlugin(ssrBundle: Rollup.OutputBundle): PluginOption { + type VirtualModule = { code: string; map: string | null }; + const _modules = new Map(); + + // group chunks and source maps + for (const [fileName, content] of Object.entries(ssrBundle)) { + if (content.type === "chunk") { + const virtualModule: VirtualModule = { + code: content.code, + map: null, + }; + const maybeMap = ssrBundle[`${fileName}.map`]; + if (maybeMap && maybeMap.type === "asset") { + virtualModule.map = maybeMap.source as string; + } + _modules.set(fileName, virtualModule); + _modules.set(resolve(fileName), virtualModule); + } + } + + return { + name: "virtual-bundle", + resolveId(id, importer) { + if (_modules.has(id)) { + return resolve(id); + } + + if (importer) { + const resolved = resolve(dirname(importer), id); + if (_modules.has(resolved)) { + return resolved; + } + } + return null; + }, + load(id) { + const m = _modules.get(id); + if (!m) { + return null; + } + return m; + }, + }; +} diff --git a/packages/start/src/config/nitroPlugin.ts b/packages/start/src/config/nitroPlugin.ts deleted file mode 100644 index be5d16418..000000000 --- a/packages/start/src/config/nitroPlugin.ts +++ /dev/null @@ -1,298 +0,0 @@ -import { - createApp, - createEvent, - type EventHandler, - eventHandler, - getHeader, -} from "h3"; -import { - build, - copyPublicAssets, - createNitro, - type Nitro, - type NitroConfig, - prepare, - prerender, -} from "nitropack"; -import { promises as fsp } from "node:fs"; -import path, { dirname, resolve } from "node:path"; -import { - type Connect, - type EnvironmentOptions, - isRunnableDevEnvironment, - type PluginOption, - type Rollup, - type ViteDevServer, -} from "vite"; -import { VITE_ENVIRONMENTS } from "../constants.js"; - -export const clientDistDir = "node_modules/.solid-start/client-dist"; -export const serverDistDir = "node_modules/.solid-start/server-dist"; -export const ssrEntryFile = "ssr.mjs"; - -export type UserNitroConfig = Omit< - NitroConfig, - "dev" | "publicAssets" | "renderer" | "rollupConfig" ->; - -export function nitroPlugin( - options: { root: string }, - getSsrBundle: () => Rollup.OutputBundle, - nitroConfig?: UserNitroConfig, -): Array { - return [ - { - name: "solid-start-nitro-dev-server", - configureServer(viteDevServer) { - (globalThis as any).VITE_DEV_SERVER = viteDevServer; - return async () => { - removeHtmlMiddlewares(viteDevServer); - - const serverEnv = viteDevServer.environments[VITE_ENVIRONMENTS.server]; - - if (!serverEnv) throw new Error("Server environment not found"); - if (!isRunnableDevEnvironment(serverEnv)) - throw new Error("Server environment is not runnable"); - - const h3App = createApp(); - - h3App.use( - eventHandler(async (event) => { - const serverEntry: { - default: EventHandler; - } = await serverEnv.runner.import("./src/entry-server.tsx"); - - return await serverEntry.default(event).catch((e: unknown) => { - console.error(e); - viteDevServer.ssrFixStacktrace(e as Error); - - if ( - getHeader(event, "content-type")?.includes("application/json") - ) { - return Response.json( - { - status: 500, - error: "Internal Server Error", - message: - "An unexpected error occurred. Please try again later.", - timestamp: new Date().toISOString(), - }, - { - status: 500, - headers: { - "Content-Type": "application/json", - }, - }, - ); - } - - return new Response( - ` - - - - - Error - - - - - - `, - { - status: 500, - headers: { - "Content-Type": "text/html", - }, - }, - ); - }); - }), - ); - - viteDevServer.middlewares.use(async (req, res) => { - const event = createEvent(req, res); - event.context.viteDevServer = viteDevServer; - await h3App.handler(event); - }); - }; - }, - }, - { - name: "solid-start-vite-plugin-nitro", - configEnvironment(name) { - if (name === VITE_ENVIRONMENTS.server) { - return { - build: { - commonjsOptions: { - include: [], - }, - ssr: true, - sourcemap: true, - rollupOptions: { - input: "~/entry-server.tsx", - }, - }, - } satisfies EnvironmentOptions; - } - - return null; - }, - config() { - return { - builder: { - sharedPlugins: true, - async buildApp(builder) { - const clientEnv = builder.environments[VITE_ENVIRONMENTS.client]; - const serverEnv = builder.environments[VITE_ENVIRONMENTS.server]; - - if (!clientEnv) throw new Error("Client environment not found"); - if (!serverEnv) throw new Error("SSR environment not found"); - - await builder.build(clientEnv); - await builder.build(serverEnv); - - const resolvedNitroConfig: NitroConfig = { - compatibilityDate: "2024-11-19", - logLevel: 3, - preset: "node-server", - typescript: { - generateTsConfig: false, - generateRuntimeConfigTypes: false, - }, - ...nitroConfig, - dev: false, - publicAssets: [ - { dir: path.resolve(options.root, clientDistDir) }, - ], - renderer: ssrEntryFile, - rollupConfig: { - plugins: [virtualBundlePlugin(getSsrBundle()) as any], - }, - }; - - const nitro = await createNitro(resolvedNitroConfig); - - await buildNitroEnvironment(nitro, () => build(nitro)); - }, - }, - }; - }, - }, - ]; -} - -export async function buildNitroEnvironment( - nitro: Nitro, - build: () => Promise, -) { - await prepare(nitro); - await copyPublicAssets(nitro); - await prerender(nitro); - await build(); - - const publicDir = nitro.options.output.publicDir; - - // As a part of the build process, the `.vite/` directory - // is copied over from `node_modules/.tanstack-start/client-dist/` - // to the `publicDir` (e.g. `.output/public/`). - // This directory (containing the vite manifest) should not be - // included in the final build, so we remove it here. - const viteDir = path.resolve(publicDir, ".vite"); - if (await fsp.stat(viteDir).catch(() => false)) { - await fsp.rm(viteDir, { recursive: true, force: true }); - } - - await nitro.close(); -} - -function virtualBundlePlugin(ssrBundle: Rollup.OutputBundle): PluginOption { - type VirtualModule = { code: string; map: string | null }; - const _modules = new Map(); - - // group chunks and source maps - for (const [fileName, content] of Object.entries(ssrBundle)) { - if (content.type === "chunk") { - const virtualModule: VirtualModule = { - code: content.code, - map: null, - }; - const maybeMap = ssrBundle[`${fileName}.map`]; - if (maybeMap && maybeMap.type === "asset") { - virtualModule.map = maybeMap.source as string; - } - _modules.set(fileName, virtualModule); - _modules.set(resolve(fileName), virtualModule); - } - } - - return { - name: "virtual-bundle", - resolveId(id, importer) { - if (_modules.has(id)) { - return resolve(id); - } - - if (importer) { - const resolved = resolve(dirname(importer), id); - if (_modules.has(resolved)) { - return resolved; - } - } - return null; - }, - load(id) { - const m = _modules.get(id); - if (!m) { - return null; - } - return m; - }, - }; -} - -/** - * Removes Vite internal middleware - * - * @param server - */ -function removeHtmlMiddlewares(server: ViteDevServer) { - const html_middlewares = [ - "viteIndexHtmlMiddleware", - "vite404Middleware", - "viteSpaFallbackMiddleware", - ]; - for (let i = server.middlewares.stack.length - 1; i > 0; i--) { - if ( - html_middlewares.includes( - // @ts-expect-error - server.middlewares.stack[i].handle.name, - ) - ) { - server.middlewares.stack.splice(i, 1); - } - } -} - -/** - * Formats error for SSR message in error overlay - * @param req - * @param error - * @returns - */ -function prepareError(req: Connect.IncomingMessage, error: unknown) { - const e = error as Error; - return { - message: `An error occured while server rendering ${req.url}:\n\n\t${typeof e === "string" ? e : e.message - } `, - stack: typeof e === "string" ? "" : e.stack, - }; -} diff --git a/packages/start/src/config/output-directory.ts b/packages/start/src/config/output-directory.ts new file mode 100644 index 000000000..c79646a1e --- /dev/null +++ b/packages/start/src/config/output-directory.ts @@ -0,0 +1,35 @@ +import { join } from "pathe"; +import type { UserConfig } from "vite"; +import { + VITE_ENVIRONMENT_NAMES, + type ViteEnvironmentNames, +} from "../constants.js"; + +export function getClientOutputDirectory(userConfig: UserConfig) { + return getOutputDirectory( + userConfig, + VITE_ENVIRONMENT_NAMES.client, + "client", + ); +} + +export function getServerOutputDirectory(userConfig: UserConfig) { + return getOutputDirectory( + userConfig, + VITE_ENVIRONMENT_NAMES.server, + "server", + ); +} + +export function getOutputDirectory( + userConfig: UserConfig, + environmentName: ViteEnvironmentNames, + directoryName: string, +) { + const rootOutputDirectory = userConfig.build?.outDir ?? "dist"; + + return ( + userConfig.environments?.[environmentName]?.build?.outDir ?? + join(rootOutputDirectory, directoryName) + ); +} diff --git a/packages/start/src/config/resolve-entries.ts b/packages/start/src/config/resolve-entries.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/start/src/constants.ts b/packages/start/src/constants.ts index 539f5e039..4113721ef 100644 --- a/packages/start/src/constants.ts +++ b/packages/start/src/constants.ts @@ -3,14 +3,22 @@ export const DEFAULT_EXTENSIONS = ["js", "jsx", "ts", "tsx"]; export const CLIENT_BASE_PATH = "_build"; export const VIRTUAL_MODULES = { - clientViteManifest: "solid-start:client-vite-manifest", - getClientManifest: "solid-start:get-client-manifest", - getManifest: "solid-start:get-manifest", - middleware: "solid-start:middleware", - serverFnManifest: "solidstart:server-fn-manifest" + clientViteManifest: "solid-start:client-vite-manifest", + getClientManifest: "solid-start:get-client-manifest", + getManifest: "solid-start:get-manifest", + middleware: "solid-start:middleware", + serverFnManifest: "solidstart:server-fn-manifest", } as const; -export const VITE_ENVIRONMENTS = { - client: "client", - server: "ssr" -} +export const VITE_ENVIRONMENT_NAMES = { + client: "client", + server: "ssr", +}; + +export type ViteEnvironmentNames = + (typeof VITE_ENVIRONMENT_NAMES)[keyof typeof VITE_ENVIRONMENT_NAMES]; + +export const ENTRY_POINTS = { + client: "virtual:solid-start-client-entry", + server: "virtual:solid-start-server-entry", +} as const; diff --git a/packages/start/src/server/handler.ts b/packages/start/src/server/handler.ts index 4a03dcd99..a8c08ee4e 100644 --- a/packages/start/src/server/handler.ts +++ b/packages/start/src/server/handler.ts @@ -1,154 +1,176 @@ -import { eventHandler, getCookie, getResponseHeaders, type H3Event, setCookie } from "h3"; +import middleware from "solid-start:middleware"; +import { + eventHandler, + getCookie, + getResponseHeaders, + type H3Event, + setCookie, +} from "h3"; import { join } from "pathe"; import type { JSX } from "solid-js"; import { sharedConfig } from "solid-js"; import { getRequestEvent, renderToStream, renderToString } from "solid-js/web"; import { provideRequestEvent } from "solid-js/web/storage"; -import middleware from "solid-start:middleware"; import { createRoutes } from "../router.jsx"; import { getFetchEvent } from "./fetchEvent.js"; +import { getSsrManifest } from "./manifest/ssr-manifest.js"; import { matchAPIRoute } from "./routes.js"; import { handleServerFunction } from "./server-functions-handler.js"; -import type { APIEvent, FetchEvent, HandlerOptions, PageEvent } from "./types.js"; -import { getSsrManifest } from "./manifest/ssr-manifest.js"; +import type { + APIEvent, + FetchEvent, + HandlerOptions, + PageEvent, +} from "./types.js"; const SERVER_FN_BASE = "/_server"; export function createBaseHandler( - createPageEvent: (e: FetchEvent) => Promise, - fn: (context: PageEvent) => JSX.Element, - options: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise) = {} + createPageEvent: (e: FetchEvent) => Promise, + fn: (context: PageEvent) => JSX.Element, + options: + | HandlerOptions + | ((context: PageEvent) => HandlerOptions | Promise) = {}, ) { - const handler = eventHandler({ - ...middleware, - handler: async (e: H3Event) => { - const event = getRequestEvent()!; - const url = new URL(event.request.url); - const pathname = url.pathname; - - const serverFunctionTest = join("/", SERVER_FN_BASE); - if (pathname.startsWith(serverFunctionTest)) { - const serverFnResponse = await handleServerFunction(e); - - if (serverFnResponse instanceof Response) return serverFnResponse; - - return new Response(serverFnResponse as any, { - headers: getResponseHeaders(e) as any - }); - } - - const match = matchAPIRoute(pathname, event.request.method); - if (match) { - const mod = await match.handler.import(); - const fn = - event.request.method === "HEAD" ? mod["HEAD"] || mod["GET"] : mod[event.request.method]; - (event as APIEvent).params = match.params || {}; - // @ts-expect-error - sharedConfig.context = { event }; - const res = await fn!(event); - if (res !== undefined) return res; - if (event.request.method !== "GET") { - throw new Error( - `API handler for ${event.request.method} "${event.request.url}" did not return a response.` - ); - } - if (!match.isPage) return; - } - - const context = await createPageEvent(event); - - const resolvedOptions = - typeof options === "function" ? await options(context) : { ...options }; - const mode = resolvedOptions.mode || "stream"; - if (resolvedOptions.nonce) context.nonce = resolvedOptions.nonce; - - if (mode === "sync" || !import.meta.env.START_SSR) { - const html = renderToString(() => { - (sharedConfig.context as any).event = context; - return fn(context); - }); - context.complete = true; - - // insert redirect handling here - - return html; - } - - const _stream = renderToStream(() => { - (sharedConfig.context as any).event = context; - return fn(context); - }, resolvedOptions); - const stream = _stream as typeof _stream & Promise // stream has a hidden 'then' method - - // insert redirect handling here - - if (mode === "async") return stream - - const { writable, readable } = new TransformStream(); - stream.pipeTo(writable); - return readable; - } - }); - - return eventHandler((e: H3Event) => provideRequestEvent(getFetchEvent(e), () => handler(e))); + const handler = eventHandler({ + ...middleware, + handler: async (e: H3Event) => { + const event = getRequestEvent()!; + const url = new URL(event.request.url); + const pathname = url.pathname; + + const serverFunctionTest = join("/", SERVER_FN_BASE); + if (pathname.startsWith(serverFunctionTest)) { + const serverFnResponse = await handleServerFunction(e); + + if (serverFnResponse instanceof Response) return serverFnResponse; + + return new Response(serverFnResponse as any, { + headers: getResponseHeaders(e) as any, + }); + } + + const match = matchAPIRoute(pathname, event.request.method); + if (match) { + const mod = await match.handler.import(); + const fn = + event.request.method === "HEAD" + ? mod["HEAD"] || mod["GET"] + : mod[event.request.method]; + (event as APIEvent).params = match.params || {}; + // @ts-expect-error + sharedConfig.context = { event }; + const res = await fn!(event); + if (res !== undefined) return res; + if (event.request.method !== "GET") { + throw new Error( + `API handler for ${event.request.method} "${event.request.url}" did not return a response.`, + ); + } + if (!match.isPage) return; + } + + const context = await createPageEvent(event); + + const resolvedOptions = + typeof options === "function" ? await options(context) : { ...options }; + const mode = resolvedOptions.mode || "stream"; + if (resolvedOptions.nonce) context.nonce = resolvedOptions.nonce; + + if (mode === "sync" || !import.meta.env.START_SSR) { + const html = renderToString(() => { + (sharedConfig.context as any).event = context; + return fn(context); + }); + context.complete = true; + + // insert redirect handling here + + return html; + } + + const _stream = renderToStream(() => { + (sharedConfig.context as any).event = context; + return fn(context); + }, resolvedOptions); + const stream = _stream as typeof _stream & Promise; // stream has a hidden 'then' method + + // insert redirect handling here + + if (mode === "async") return stream; + + const { writable, readable } = new TransformStream(); + stream.pipeTo(writable); + return readable; + }, + }); + + return eventHandler((e: H3Event) => + provideRequestEvent(getFetchEvent(e), () => handler(e)), + ); } export function createHandler( - fn: (context: PageEvent) => JSX.Element, - options: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise) = {} + fn: (context: PageEvent) => JSX.Element, + options: + | HandlerOptions + | ((context: PageEvent) => HandlerOptions | Promise) = {}, ) { - return createBaseHandler(createPageEvent, fn, options) + return createBaseHandler(createPageEvent, fn, options); } export async function createPageEvent(ctx: FetchEvent) { - ctx.response.headers.set("Content-Type", "text/html"); - // const prevPath = ctx.request.headers.get("x-solid-referrer"); - // const mutation = ctx.request.headers.get("x-solid-mutation") === "true"; - const manifest = getSsrManifest('client'); - const pageEvent: PageEvent = Object.assign(ctx, { - manifest: 'json' in manifest ? await manifest.json() : {}, - assets: [ - ...(await manifest.getAssets(import.meta.env.START_CLIENT_ENTRY)), - ...(await manifest.getAssets(import.meta.env.START_APP_ENTRY)), - // ...(import.meta.env.START_ISLANDS - // ? (await serverManifest.inputs[serverManifest.handler]!.assets()).filter( - // s => (s as any).attrs.rel !== "modulepreload" - // ) - // : []) - ], - router: { - submission: initFromFlash(ctx) as any - }, - routes: createRoutes(), - // prevUrl: prevPath || "", - // mutation: mutation, - // $type: FETCH_EVENT, - complete: false, - $islands: new Set() - }); - - return pageEvent; + ctx.response.headers.set("Content-Type", "text/html"); + // const prevPath = ctx.request.headers.get("x-solid-referrer"); + // const mutation = ctx.request.headers.get("x-solid-mutation") === "true"; + const manifest = getSsrManifest("client"); + const pageEvent: PageEvent = Object.assign(ctx, { + manifest: "json" in manifest ? await manifest.json() : {}, + assets: [ + ...(await manifest.getAssets(import.meta.env.START_CLIENT_ENTRY)), + ...(await manifest.getAssets(import.meta.env.START_APP_ENTRY)), + // ...(import.meta.env.START_ISLANDS + // ? (await serverManifest.inputs[serverManifest.handler]!.assets()).filter( + // s => (s as any).attrs.rel !== "modulepreload" + // ) + // : []) + ], + router: { + submission: initFromFlash(ctx) as any, + }, + routes: createRoutes(), + // prevUrl: prevPath || "", + // mutation: mutation, + // $type: FETCH_EVENT, + complete: false, + $islands: new Set(), + }); + + return pageEvent; } function initFromFlash(ctx: FetchEvent) { - const flash = getCookie(ctx.nativeEvent, "flash"); - if (!flash) return; - try { - const param = JSON.parse(flash); - if (!param || !param.result) return; - const input = [...param.input.slice(0, -1), new Map(param.input[param.input.length - 1])]; - const result = param.error ? new Error(param.result) : param.result; - return { - input, - url: param.url, - pending: false, - result: param.thrown ? undefined : result, - error: param.thrown ? result : undefined - }; - } catch (e) { - console.error(e); - } finally { - setCookie(ctx.nativeEvent, "flash", "", { maxAge: 0 }); - } + const flash = getCookie(ctx.nativeEvent, "flash"); + if (!flash) return; + try { + const param = JSON.parse(flash); + if (!param || !param.result) return; + const input = [ + ...param.input.slice(0, -1), + new Map(param.input[param.input.length - 1]), + ]; + const result = param.error ? new Error(param.result) : param.result; + return { + input, + url: param.url, + pending: false, + result: param.thrown ? undefined : result, + error: param.thrown ? result : undefined, + }; + } catch (e) { + console.error(e); + } finally { + setCookie(ctx.nativeEvent, "flash", "", { maxAge: 0 }); + } } diff --git a/packages/start/src/server/manifest/prod-ssr-manifest.ts b/packages/start/src/server/manifest/prod-ssr-manifest.ts index 90908bf8f..f07214301 100644 --- a/packages/start/src/server/manifest/prod-ssr-manifest.ts +++ b/packages/start/src/server/manifest/prod-ssr-manifest.ts @@ -1,90 +1,109 @@ -import { clientViteManifest } from "solid-start:client-vite-manifest" +import { clientViteManifest } from "solid-start:client-vite-manifest"; import { join } from "pathe"; -import type { Asset } from "../renderAsset.jsx"; import { CLIENT_BASE_PATH } from "../../constants.js"; +import type { Asset } from "../renderAsset.jsx"; // Only reads from client manifest atm, might need server support for islands export function getSsrProdManifest() { - const viteManifest = clientViteManifest; - return { - path(id: string) { - const viteManifestEntry = clientViteManifest[id /*import.meta.env.START_CLIENT_ENTRY*/]; - if (!viteManifestEntry) throw new Error("No entry found in vite manifest"); + const viteManifest = clientViteManifest; + return { + path(id: string) { + const viteManifestEntry = + clientViteManifest[id /*import.meta.env.START_CLIENT_ENTRY*/]; + if (!viteManifestEntry) + throw new Error("No entry found in vite manifest"); - return `/${CLIENT_BASE_PATH}/${viteManifestEntry.file}`; - }, - async getAssets(id) { - return createHtmlTagsForAssets( - findAssetsInViteManifest(clientViteManifest, id), - ); - }, - async json() { - const json: Record = {}; + return `/${CLIENT_BASE_PATH}/${viteManifestEntry.file}`; + }, + async getAssets(id) { + return createHtmlTagsForAssets( + findAssetsInViteManifest(clientViteManifest, id), + ); + }, + async json() { + const json: Record = {}; - const entryKeys = Object.keys(viteManifest) - .filter((id) => viteManifest[id]?.isEntry) - .map((id) => id); + const entryKeys = Object.keys(viteManifest) + .filter( + (id) => viteManifest[id]?.isEntry || viteManifest[id]?.isDynamicEntry, + ) + .map((id) => id); - for (const entryKey of entryKeys) { - json[entryKey] = { - output: join("/", CLIENT_BASE_PATH, viteManifest[entryKey]!.file), - assets: await this.getAssets(entryKey) - }; - } + for (const entryKey of entryKeys) { + json[entryKey] = { + output: join("/", CLIENT_BASE_PATH, viteManifest[entryKey]!.file), + assets: await this.getAssets(entryKey), + }; + } - return json - }, - } satisfies StartManifest & { json(): Promise>, path(id: string): string }; + return json; + }, + } satisfies StartManifest & { + json(): Promise>; + path(id: string): string; + }; } function createHtmlTagsForAssets(assets: string[]) { - return assets - .filter( - (asset) => - asset.endsWith(".css") || - asset.endsWith(".js") || - asset.endsWith(".mjs"), - ) - .map((asset) => ({ - tag: "link", - attrs: { - href: join("/", CLIENT_BASE_PATH, asset), - key: join("/", CLIENT_BASE_PATH, asset), - ...(asset.endsWith(".css") - ? { rel: "stylesheet", fetchPriority: "high" } - : { rel: "modulepreload" }), - }, - })); + return assets + .filter( + (asset) => + asset.endsWith(".css") || + asset.endsWith(".js") || + asset.endsWith(".mjs"), + ) + .map((asset) => ({ + tag: "link", + attrs: { + href: join("/", CLIENT_BASE_PATH, asset), + key: join("/", CLIENT_BASE_PATH, asset), + ...(asset.endsWith(".css") + ? { rel: "stylesheet", fetchPriority: "high" } + : { rel: "modulepreload" }), + }, + })); } -function findAssetsInViteManifest(manifest: any, id: string, assetMap = new Map(), stack: string[] = []) { - if (stack.includes(id)) { - return []; - } +function findAssetsInViteManifest( + manifest: any, + id: string, + assetMap = new Map(), + stack: string[] = [], +) { + if (stack.includes(id)) { + return []; + } - const cached = assetMap.get(id); - if (cached) { - return cached; - } - const chunk = manifest[id]; - if (!chunk) { - return []; - } + const cached = assetMap.get(id); + if (cached) { + return cached; + } + const chunk = manifest[id]; + if (!chunk) { + return []; + } - const assets = [ - ...(chunk.assets?.filter(Boolean) || []), - ...(chunk.css?.filter(Boolean) || []) - ]; - if (chunk.imports) { - stack.push(id); - for (let i = 0, l = chunk.imports.length; i < l; i++) { - assets.push(...findAssetsInViteManifest(manifest, chunk.imports[i], assetMap, stack)); - } - stack.pop(); - } - assets.push(chunk.file); - const all = Array.from(new Set(assets)); - assetMap.set(id, all); + const assets = [ + ...(chunk.assets?.filter(Boolean) || []), + ...(chunk.css?.filter(Boolean) || []), + ]; + if (chunk.imports) { + stack.push(id); + for (let i = 0, l = chunk.imports.length; i < l; i++) { + assets.push( + ...findAssetsInViteManifest( + manifest, + chunk.imports[i], + assetMap, + stack, + ), + ); + } + stack.pop(); + } + assets.push(chunk.file); + const all = Array.from(new Set(assets)); + assetMap.set(id, all); - return all; + return all; } diff --git a/packages/start/tsconfig.json b/packages/start/tsconfig.json index a03949583..14cc4a01e 100644 --- a/packages/start/tsconfig.json +++ b/packages/start/tsconfig.json @@ -1,8 +1,8 @@ { "compilerOptions": { "target": "ESNext", - "module": "NodeNext", - "moduleResolution": "NodeNext", + "module": "preserve", + "moduleResolution": "bundler", "strict": true, "noUncheckedIndexedAccess": true, "allowSyntheticDefaultImports": true, @@ -12,14 +12,10 @@ "allowJs": true, "isolatedModules": true, "outDir": "./dist", + "rootDir": "./src", "declaration": true, "skipLibCheck": true, - "types": [ - "vite/client" - ] + "types": ["vite/client"] }, - "include": [ - "./src", - "./src/env.d.ts" - ] -} \ No newline at end of file + "include": ["./src", "./src/env.d.ts"] +} From a3d7669905ee9cb1a9fc5c22d2a6ec9e55b141ab Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Sat, 4 Oct 2025 15:39:12 +0800 Subject: [PATCH 2/3] works with cloudflare too + add nitro to examples --- examples/bare/vite.config.ts | 6 +- examples/basic/package.json | 1 + examples/basic/vite.config.ts | 5 +- examples/notes/vite.config.ts | 3 +- examples/pnpm-lock.yaml | 751 ++++++++++++++++++ examples/todomvc/vite.config.ts | 3 +- examples/with-auth/vite.config.ts | 5 +- examples/with-authjs/vite.config.ts | 3 +- examples/with-drizzle/vite.config.ts | 3 +- examples/with-mdx/vite.config.ts | 2 + examples/with-prisma/vite.config.ts | 3 +- examples/with-solid-styled/vite.config.ts | 4 +- examples/with-solidbase/vite.config.ts | 13 +- examples/with-strict-csp/vite.config.ts | 4 +- examples/with-tailwindcss/vite.config.ts | 4 +- examples/with-tanstack-router/vite.config.ts | 3 +- examples/with-trpc/vite.config.ts | 3 +- examples/with-unocss/vite.config.ts | 3 +- examples/with-vitest/vite.config.ts | 3 +- packages/start/package.json | 1 + packages/start/src/config/fs-routes/index.ts | 2 +- packages/start/src/config/index.ts | 4 +- packages/start/src/config/nitro-v2-plugin.ts | 22 +- packages/start/src/config/resolve-entries.ts | 0 packages/start/src/constants.ts | 3 +- packages/start/src/server/collect-styles.ts | 2 +- packages/start/src/server/entry.ts | 6 + packages/start/src/server/handler.ts | 6 +- .../src/server/manifest/dev-ssr-manifest.ts | 6 +- .../src/server/manifest/prod-ssr-manifest.ts | 9 +- packages/start/src/virtual.d.ts | 4 + 31 files changed, 826 insertions(+), 61 deletions(-) delete mode 100644 packages/start/src/config/resolve-entries.ts create mode 100644 packages/start/src/server/entry.ts diff --git a/examples/bare/vite.config.ts b/examples/bare/vite.config.ts index f244fc1d1..87c484cd5 100644 --- a/examples/bare/vite.config.ts +++ b/examples/bare/vite.config.ts @@ -1,6 +1,10 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import { defineConfig } from "vite"; export default defineConfig({ - plugins: [solidStart()] + plugins: [ + solidStart(), + nitroV2Plugin() + ] }); diff --git a/examples/basic/package.json b/examples/basic/package.json index 17b835d08..9491e4e79 100644 --- a/examples/basic/package.json +++ b/examples/basic/package.json @@ -6,6 +6,7 @@ "build": "vite build" }, "dependencies": { + "@cloudflare/vite-plugin": "^1.13.10", "@solidjs/meta": "^0.29.4", "@solidjs/router": "^0.15.0", "@solidjs/start": "file:../../packages/start", diff --git a/examples/basic/vite.config.ts b/examples/basic/vite.config.ts index 917f05a22..cba6e8b62 100644 --- a/examples/basic/vite.config.ts +++ b/examples/basic/vite.config.ts @@ -3,5 +3,8 @@ import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import { defineConfig } from "vite"; export default defineConfig({ - plugins: [solidStart(), nitroV2Plugin({ preset: "node-server" })], + plugins: [ + solidStart(), + nitroV2Plugin() + ], }); diff --git a/examples/notes/vite.config.ts b/examples/notes/vite.config.ts index f244fc1d1..fd34baaa4 100644 --- a/examples/notes/vite.config.ts +++ b/examples/notes/vite.config.ts @@ -1,6 +1,7 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import { defineConfig } from "vite"; export default defineConfig({ - plugins: [solidStart()] + plugins: [solidStart(), nitroV2Plugin()] }); diff --git a/examples/pnpm-lock.yaml b/examples/pnpm-lock.yaml index 76846f533..0de2de08a 100644 --- a/examples/pnpm-lock.yaml +++ b/examples/pnpm-lock.yaml @@ -27,6 +27,9 @@ importers: basic: dependencies: + '@cloudflare/vite-plugin': + specifier: ^1.13.10 + version: 1.13.10(vite@7.1.3(@types/node@24.3.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.8.1))(workerd@1.20251001.0)(wrangler@4.42.0) '@solidjs/meta': specifier: ^0.29.4 version: 0.29.4(solid-js@1.9.9) @@ -748,11 +751,60 @@ packages: resolution: {integrity: sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==} engines: {node: '>=18.0.0'} + '@cloudflare/unenv-preset@2.7.6': + resolution: {integrity: sha512-ykG2nd3trk6jbknRCH69xL3RpGLLbKCrbTbWSOvKEq7s4jH06yLrQlRr/q9IU+dK9p1JY1EXqhFK7VG5KqhzmQ==} + peerDependencies: + unenv: 2.0.0-rc.21 + workerd: ^1.20250927.0 + peerDependenciesMeta: + workerd: + optional: true + + '@cloudflare/vite-plugin@1.13.10': + resolution: {integrity: sha512-zQaCbzGDAMhjZqXfulpUgBL/D4qsoP1oHVk2LyseKJ47PMq2cHWnbISOi3RONvKxpGyct7ACjA4JEhbFlu5GNQ==} + peerDependencies: + vite: ^6.1.0 || ^7.0.0 + wrangler: ^4.42.0 + + '@cloudflare/workerd-darwin-64@1.20251001.0': + resolution: {integrity: sha512-y1ST/cCscaRewWRnsHZdWbgiLJbki5UMGd0hMo/FLqjlztwPeDgQ5CGm5jMiCDdw/IBCpWxEukftPYR34rWNog==} + engines: {node: '>=16'} + cpu: [x64] + os: [darwin] + + '@cloudflare/workerd-darwin-arm64@1.20251001.0': + resolution: {integrity: sha512-+z4QHHZ/Yix82zLFYS+ZS2UV09IENFPwDCEKUWfnrM9Km2jOOW3Ua4hJNob1EgQUYs8fFZo7k5O/tpwxMsSbbQ==} + engines: {node: '>=16'} + cpu: [arm64] + os: [darwin] + + '@cloudflare/workerd-linux-64@1.20251001.0': + resolution: {integrity: sha512-hGS+O2V9Mm2XjJUaB9ZHMA5asDUaDjKko42e+accbew0PQR7zrAl1afdII6hMqCLV4tk4GAjvhv281pN4g48rg==} + engines: {node: '>=16'} + cpu: [x64] + os: [linux] + + '@cloudflare/workerd-linux-arm64@1.20251001.0': + resolution: {integrity: sha512-QYaMK+pRgt28N7CX1JlJ+ToegJF9LxzqdT7MjWqPgVj9D2WTyIhBVYl3wYjJRcgOlnn+DRt42+li4T64CPEeuA==} + engines: {node: '>=16'} + cpu: [arm64] + os: [linux] + + '@cloudflare/workerd-windows-64@1.20251001.0': + resolution: {integrity: sha512-ospnDR/FlyRvrv9DSHuxDAXmzEBLDUiAHQrQHda1iUH9HqxnNQ8giz9VlPfq7NIRc7bQ1ZdIYPGLJOY4Q366Ng==} + engines: {node: '>=16'} + cpu: [x64] + os: [win32] + '@corvu/utils@0.4.2': resolution: {integrity: sha512-Ox2kYyxy7NoXdKWdHeDEjZxClwzO4SKM8plAaVwmAJPxHMqA0rLOoAsa+hBDwRLpctf+ZRnAd/ykguuJidnaTA==} peerDependencies: solid-js: ^1.8 + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + '@csstools/color-helpers@5.1.0': resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} engines: {node: '>=18'} @@ -814,6 +866,9 @@ packages: search-insights: optional: true + '@emnapi/runtime@1.5.0': + resolution: {integrity: sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==} + '@esbuild-kit/core-utils@3.3.2': resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} deprecated: 'Merged into tsx: https://tsx.is' @@ -840,6 +895,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.25.4': + resolution: {integrity: sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.18.20': resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} engines: {node: '>=12'} @@ -870,6 +931,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.25.4': + resolution: {integrity: sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.18.20': resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} engines: {node: '>=12'} @@ -900,6 +967,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.25.4': + resolution: {integrity: sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.18.20': resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} engines: {node: '>=12'} @@ -930,6 +1003,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.25.4': + resolution: {integrity: sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.18.20': resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} engines: {node: '>=12'} @@ -960,6 +1039,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.25.4': + resolution: {integrity: sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.18.20': resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} engines: {node: '>=12'} @@ -990,6 +1075,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.25.4': + resolution: {integrity: sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.18.20': resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} engines: {node: '>=12'} @@ -1020,6 +1111,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.25.4': + resolution: {integrity: sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.18.20': resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} engines: {node: '>=12'} @@ -1050,6 +1147,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.25.4': + resolution: {integrity: sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.18.20': resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} engines: {node: '>=12'} @@ -1080,6 +1183,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.25.4': + resolution: {integrity: sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.18.20': resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} engines: {node: '>=12'} @@ -1110,6 +1219,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.25.4': + resolution: {integrity: sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.18.20': resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} engines: {node: '>=12'} @@ -1140,6 +1255,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.25.4': + resolution: {integrity: sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.18.20': resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} engines: {node: '>=12'} @@ -1170,6 +1291,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.25.4': + resolution: {integrity: sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.18.20': resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} engines: {node: '>=12'} @@ -1200,6 +1327,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.25.4': + resolution: {integrity: sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.18.20': resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} engines: {node: '>=12'} @@ -1230,6 +1363,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.25.4': + resolution: {integrity: sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.18.20': resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} engines: {node: '>=12'} @@ -1260,6 +1399,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.25.4': + resolution: {integrity: sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.18.20': resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} engines: {node: '>=12'} @@ -1290,6 +1435,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.25.4': + resolution: {integrity: sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.18.20': resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} engines: {node: '>=12'} @@ -1320,12 +1471,24 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.25.4': + resolution: {integrity: sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-arm64@0.25.10': resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-arm64@0.25.4': + resolution: {integrity: sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.18.20': resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} engines: {node: '>=12'} @@ -1356,6 +1519,12 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.25.4': + resolution: {integrity: sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.23.1': resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} engines: {node: '>=18'} @@ -1368,6 +1537,12 @@ packages: cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.25.4': + resolution: {integrity: sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.18.20': resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} engines: {node: '>=12'} @@ -1398,6 +1573,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.25.4': + resolution: {integrity: sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openharmony-arm64@0.25.10': resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==} engines: {node: '>=18'} @@ -1434,6 +1615,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.25.4': + resolution: {integrity: sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.18.20': resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} engines: {node: '>=12'} @@ -1464,6 +1651,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.25.4': + resolution: {integrity: sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.18.20': resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} engines: {node: '>=12'} @@ -1494,6 +1687,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.25.4': + resolution: {integrity: sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.18.20': resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} engines: {node: '>=12'} @@ -1524,6 +1723,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.25.4': + resolution: {integrity: sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.7.0': resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1600,6 +1805,111 @@ packages: '@iconify/utils@2.3.0': resolution: {integrity: sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==} + '@img/sharp-darwin-arm64@0.33.5': + resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.33.5': + resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.0.4': + resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.0.4': + resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.0.4': + resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.0.5': + resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.0.4': + resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.0.4': + resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.33.5': + resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.33.5': + resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-s390x@0.33.5': + resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.33.5': + resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.33.5': + resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.33.5': + resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.33.5': + resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-ia32@0.33.5': + resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.33.5': + resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + '@internationalized/date@3.8.2': resolution: {integrity: sha512-/wENk7CbvLbkUvX1tu0mwq49CVkkWpkXubGel6birjRPyo6uQ4nQpnq5xZu823zRCwwn82zgHrvgF1vZyvmVgA==} @@ -1636,6 +1946,9 @@ packages: '@jridgewell/trace-mapping@0.3.30': resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==} + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@kobalte/core@0.13.11': resolution: {integrity: sha512-hK7TYpdib/XDb/r/4XDBFaO9O+3ZHz4ZWryV4/3BfES+tSQVgg2IJupDnztKXB0BqbSRy/aWlHKw1SPtNPYCFQ==} peerDependencies: @@ -1813,6 +2126,9 @@ packages: '@prisma/get-platform@5.22.0': resolution: {integrity: sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q==} + '@remix-run/node-fetch-server@0.8.1': + resolution: {integrity: sha512-J1dev372wtJqmqn9U/qbpbZxbJSQrogNN2+Qv1lKlpATpe/WQ9aCZfl/xSb9d2Rgh1IyLSvNxZAXPZxruO6Xig==} + '@rollup/plugin-alias@5.1.1': resolution: {integrity: sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==} engines: {node: '>=14.0.0'} @@ -2765,6 +3081,15 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + acorn@8.15.0: resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} @@ -2923,6 +3248,9 @@ packages: bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + blake3-wasm@2.1.5: + resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} + boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -3078,6 +3406,13 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} @@ -3542,6 +3877,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.25.4: + resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -3668,6 +4008,10 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} + exit-hook@2.2.1: + resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} + engines: {node: '>=6'} + expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} @@ -3817,6 +4161,10 @@ packages: get-port-please@3.2.0: resolution: {integrity: sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==} + get-port@7.1.0: + resolution: {integrity: sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==} + engines: {node: '>=16'} + get-proto@1.0.1: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} @@ -3846,6 +4194,9 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true @@ -4076,6 +4427,9 @@ packages: is-alphanumerical@2.0.1: resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + is-arrayish@0.3.4: + resolution: {integrity: sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==} + is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -4770,6 +5124,11 @@ packages: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} + miniflare@4.20251001.0: + resolution: {integrity: sha512-OHd31D2LT8JH+85nVXClV0Z18jxirCohzKNAcZs/fgt4mIkUDtidX3VqR3ovAM0jWooNxrFhB9NSs3iDbiJF7Q==} + engines: {node: '>=18.0.0'} + hasBin: true + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -5419,6 +5778,10 @@ packages: setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + sharp@0.33.5: + resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -5443,6 +5806,9 @@ packages: simple-get@4.0.1: resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + simple-swizzle@0.2.4: + resolution: {integrity: sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==} + sirv@3.0.1: resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==} engines: {node: '>=18'} @@ -5539,6 +5905,10 @@ packages: std-env@3.9.0: resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + stoppable@1.1.0: + resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} + engines: {node: '>=4', npm: '>=6'} + streamx@2.22.0: resolution: {integrity: sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==} @@ -5825,6 +6195,10 @@ packages: undici-types@7.10.0: resolution: {integrity: sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==} + undici@7.14.0: + resolution: {integrity: sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==} + engines: {node: '>=20.18.1'} + unenv@1.10.0: resolution: {integrity: sha512-wY5bskBQFL9n3Eca5XnhH6KbUo/tfvkwm9OpcdCvLaeA7piBNbavbOKJySEwQ1V0RH6HvNlSAFRTpvTqgKRQXQ==} @@ -6346,6 +6720,21 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + workerd@1.20251001.0: + resolution: {integrity: sha512-oT/K4YWNhmwpVmGeaHNmF7mLRfgjszlVr7lJtpS4jx5khmxmMzWZEEQRrJEpgzeHP6DOq9qWLPNT0bjMK7TchQ==} + engines: {node: '>=16'} + hasBin: true + + wrangler@4.42.0: + resolution: {integrity: sha512-OZXiUSfGD66OVkncDbjZtqrsH6bWPRQMYc6RmMbkzYm/lEvJ8lvARKcqDgEyq8zDAgJAivlMQLyPtKQoVjQ/4g==} + engines: {node: '>=18.0.0'} + hasBin: true + peerDependencies: + '@cloudflare/workers-types': ^4.20251001.0 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -6361,6 +6750,18 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + ws@8.18.3: resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} engines: {node: '>=10.0.0'} @@ -6411,6 +6812,9 @@ packages: youch-core@0.3.3: resolution: {integrity: sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==} + youch@4.1.0-beta.10: + resolution: {integrity: sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==} + youch@4.1.0-beta.11: resolution: {integrity: sha512-sQi6PERyO/mT8w564ojOVeAlYTtVQmC2GaktQAf+IdI75/GKIggosBuvyVXvEV+FATAT6RbLdIjFoiIId4ozoQ==} @@ -6418,6 +6822,9 @@ packages: resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} engines: {node: '>= 14'} + zod@3.22.3: + resolution: {integrity: sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==} + zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} @@ -6873,11 +7280,53 @@ snapshots: dependencies: mime: 3.0.0 + '@cloudflare/unenv-preset@2.7.6(unenv@2.0.0-rc.21)(workerd@1.20251001.0)': + dependencies: + unenv: 2.0.0-rc.21 + optionalDependencies: + workerd: 1.20251001.0 + + '@cloudflare/vite-plugin@1.13.10(vite@7.1.3(@types/node@24.3.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.8.1))(workerd@1.20251001.0)(wrangler@4.42.0)': + dependencies: + '@cloudflare/unenv-preset': 2.7.6(unenv@2.0.0-rc.21)(workerd@1.20251001.0) + '@remix-run/node-fetch-server': 0.8.1 + get-port: 7.1.0 + miniflare: 4.20251001.0 + picocolors: 1.1.1 + tinyglobby: 0.2.15 + unenv: 2.0.0-rc.21 + vite: 7.1.3(@types/node@24.3.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.8.1) + wrangler: 4.42.0 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - workerd + + '@cloudflare/workerd-darwin-64@1.20251001.0': + optional: true + + '@cloudflare/workerd-darwin-arm64@1.20251001.0': + optional: true + + '@cloudflare/workerd-linux-64@1.20251001.0': + optional: true + + '@cloudflare/workerd-linux-arm64@1.20251001.0': + optional: true + + '@cloudflare/workerd-windows-64@1.20251001.0': + optional: true + '@corvu/utils@0.4.2(solid-js@1.9.9)': dependencies: '@floating-ui/dom': 1.7.4 solid-js: 1.9.9 + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + '@csstools/color-helpers@5.1.0': {} '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': @@ -6931,6 +7380,11 @@ snapshots: transitivePeerDependencies: - '@algolia/client-search' + '@emnapi/runtime@1.5.0': + dependencies: + tslib: 2.8.1 + optional: true + '@esbuild-kit/core-utils@3.3.2': dependencies: esbuild: 0.18.20 @@ -6950,6 +7404,9 @@ snapshots: '@esbuild/aix-ppc64@0.25.10': optional: true + '@esbuild/aix-ppc64@0.25.4': + optional: true + '@esbuild/android-arm64@0.18.20': optional: true @@ -6965,6 +7422,9 @@ snapshots: '@esbuild/android-arm64@0.25.10': optional: true + '@esbuild/android-arm64@0.25.4': + optional: true + '@esbuild/android-arm@0.18.20': optional: true @@ -6980,6 +7440,9 @@ snapshots: '@esbuild/android-arm@0.25.10': optional: true + '@esbuild/android-arm@0.25.4': + optional: true + '@esbuild/android-x64@0.18.20': optional: true @@ -6995,6 +7458,9 @@ snapshots: '@esbuild/android-x64@0.25.10': optional: true + '@esbuild/android-x64@0.25.4': + optional: true + '@esbuild/darwin-arm64@0.18.20': optional: true @@ -7010,6 +7476,9 @@ snapshots: '@esbuild/darwin-arm64@0.25.10': optional: true + '@esbuild/darwin-arm64@0.25.4': + optional: true + '@esbuild/darwin-x64@0.18.20': optional: true @@ -7025,6 +7494,9 @@ snapshots: '@esbuild/darwin-x64@0.25.10': optional: true + '@esbuild/darwin-x64@0.25.4': + optional: true + '@esbuild/freebsd-arm64@0.18.20': optional: true @@ -7040,6 +7512,9 @@ snapshots: '@esbuild/freebsd-arm64@0.25.10': optional: true + '@esbuild/freebsd-arm64@0.25.4': + optional: true + '@esbuild/freebsd-x64@0.18.20': optional: true @@ -7055,6 +7530,9 @@ snapshots: '@esbuild/freebsd-x64@0.25.10': optional: true + '@esbuild/freebsd-x64@0.25.4': + optional: true + '@esbuild/linux-arm64@0.18.20': optional: true @@ -7070,6 +7548,9 @@ snapshots: '@esbuild/linux-arm64@0.25.10': optional: true + '@esbuild/linux-arm64@0.25.4': + optional: true + '@esbuild/linux-arm@0.18.20': optional: true @@ -7085,6 +7566,9 @@ snapshots: '@esbuild/linux-arm@0.25.10': optional: true + '@esbuild/linux-arm@0.25.4': + optional: true + '@esbuild/linux-ia32@0.18.20': optional: true @@ -7100,6 +7584,9 @@ snapshots: '@esbuild/linux-ia32@0.25.10': optional: true + '@esbuild/linux-ia32@0.25.4': + optional: true + '@esbuild/linux-loong64@0.18.20': optional: true @@ -7115,6 +7602,9 @@ snapshots: '@esbuild/linux-loong64@0.25.10': optional: true + '@esbuild/linux-loong64@0.25.4': + optional: true + '@esbuild/linux-mips64el@0.18.20': optional: true @@ -7130,6 +7620,9 @@ snapshots: '@esbuild/linux-mips64el@0.25.10': optional: true + '@esbuild/linux-mips64el@0.25.4': + optional: true + '@esbuild/linux-ppc64@0.18.20': optional: true @@ -7145,6 +7638,9 @@ snapshots: '@esbuild/linux-ppc64@0.25.10': optional: true + '@esbuild/linux-ppc64@0.25.4': + optional: true + '@esbuild/linux-riscv64@0.18.20': optional: true @@ -7160,6 +7656,9 @@ snapshots: '@esbuild/linux-riscv64@0.25.10': optional: true + '@esbuild/linux-riscv64@0.25.4': + optional: true + '@esbuild/linux-s390x@0.18.20': optional: true @@ -7175,6 +7674,9 @@ snapshots: '@esbuild/linux-s390x@0.25.10': optional: true + '@esbuild/linux-s390x@0.25.4': + optional: true + '@esbuild/linux-x64@0.18.20': optional: true @@ -7190,9 +7692,15 @@ snapshots: '@esbuild/linux-x64@0.25.10': optional: true + '@esbuild/linux-x64@0.25.4': + optional: true + '@esbuild/netbsd-arm64@0.25.10': optional: true + '@esbuild/netbsd-arm64@0.25.4': + optional: true + '@esbuild/netbsd-x64@0.18.20': optional: true @@ -7208,12 +7716,18 @@ snapshots: '@esbuild/netbsd-x64@0.25.10': optional: true + '@esbuild/netbsd-x64@0.25.4': + optional: true + '@esbuild/openbsd-arm64@0.23.1': optional: true '@esbuild/openbsd-arm64@0.25.10': optional: true + '@esbuild/openbsd-arm64@0.25.4': + optional: true + '@esbuild/openbsd-x64@0.18.20': optional: true @@ -7229,6 +7743,9 @@ snapshots: '@esbuild/openbsd-x64@0.25.10': optional: true + '@esbuild/openbsd-x64@0.25.4': + optional: true + '@esbuild/openharmony-arm64@0.25.10': optional: true @@ -7247,6 +7764,9 @@ snapshots: '@esbuild/sunos-x64@0.25.10': optional: true + '@esbuild/sunos-x64@0.25.4': + optional: true + '@esbuild/win32-arm64@0.18.20': optional: true @@ -7262,6 +7782,9 @@ snapshots: '@esbuild/win32-arm64@0.25.10': optional: true + '@esbuild/win32-arm64@0.25.4': + optional: true + '@esbuild/win32-ia32@0.18.20': optional: true @@ -7277,6 +7800,9 @@ snapshots: '@esbuild/win32-ia32@0.25.10': optional: true + '@esbuild/win32-ia32@0.25.4': + optional: true + '@esbuild/win32-x64@0.18.20': optional: true @@ -7292,6 +7818,9 @@ snapshots: '@esbuild/win32-x64@0.25.10': optional: true + '@esbuild/win32-x64@0.25.4': + optional: true + '@eslint-community/eslint-utils@4.7.0(eslint@8.57.1)': dependencies: eslint: 8.57.1 @@ -7396,6 +7925,81 @@ snapshots: transitivePeerDependencies: - supports-color + '@img/sharp-darwin-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.4 + optional: true + + '@img/sharp-darwin-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.0.5': + optional: true + + '@img/sharp-libvips-linux-s390x@1.0.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + optional: true + + '@img/sharp-linux-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.4 + optional: true + + '@img/sharp-linux-arm@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.5 + optional: true + + '@img/sharp-linux-s390x@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.4 + optional: true + + '@img/sharp-linux-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + optional: true + + '@img/sharp-wasm32@0.33.5': + dependencies: + '@emnapi/runtime': 1.5.0 + optional: true + + '@img/sharp-win32-ia32@0.33.5': + optional: true + + '@img/sharp-win32-x64@0.33.5': + optional: true + '@internationalized/date@3.8.2': dependencies: '@swc/helpers': 0.5.17 @@ -7443,6 +8047,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + '@kobalte/core@0.13.11(solid-js@1.9.9)': dependencies: '@floating-ui/dom': 1.7.4 @@ -7662,6 +8271,8 @@ snapshots: dependencies: '@prisma/debug': 5.22.0 + '@remix-run/node-fetch-server@0.8.1': {} + '@rollup/plugin-alias@5.1.1(rollup@4.52.3)': optionalDependencies: rollup: 4.52.3 @@ -9004,6 +9615,10 @@ snapshots: dependencies: acorn: 8.15.0 + acorn-walk@8.3.2: {} + + acorn@8.14.0: {} + acorn@8.15.0: {} agent-base@7.1.3: {} @@ -9175,6 +9790,8 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 + blake3-wasm@2.1.5: {} + boolbase@1.0.0: {} boxen@8.0.1: @@ -9341,6 +9958,16 @@ snapshots: color-name@1.1.4: {} + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.4 + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + colorette@2.0.20: {} combined-stream@1.0.8: @@ -9747,6 +10374,34 @@ snapshots: '@esbuild/win32-ia32': 0.25.10 '@esbuild/win32-x64': 0.25.10 + esbuild@0.25.4: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.4 + '@esbuild/android-arm': 0.25.4 + '@esbuild/android-arm64': 0.25.4 + '@esbuild/android-x64': 0.25.4 + '@esbuild/darwin-arm64': 0.25.4 + '@esbuild/darwin-x64': 0.25.4 + '@esbuild/freebsd-arm64': 0.25.4 + '@esbuild/freebsd-x64': 0.25.4 + '@esbuild/linux-arm': 0.25.4 + '@esbuild/linux-arm64': 0.25.4 + '@esbuild/linux-ia32': 0.25.4 + '@esbuild/linux-loong64': 0.25.4 + '@esbuild/linux-mips64el': 0.25.4 + '@esbuild/linux-ppc64': 0.25.4 + '@esbuild/linux-riscv64': 0.25.4 + '@esbuild/linux-s390x': 0.25.4 + '@esbuild/linux-x64': 0.25.4 + '@esbuild/netbsd-arm64': 0.25.4 + '@esbuild/netbsd-x64': 0.25.4 + '@esbuild/openbsd-arm64': 0.25.4 + '@esbuild/openbsd-x64': 0.25.4 + '@esbuild/sunos-x64': 0.25.4 + '@esbuild/win32-arm64': 0.25.4 + '@esbuild/win32-ia32': 0.25.4 + '@esbuild/win32-x64': 0.25.4 + escalade@3.2.0: {} escape-html@1.0.3: {} @@ -9922,6 +10577,8 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 + exit-hook@2.2.1: {} + expand-template@2.0.3: {} expect-type@1.2.2: {} @@ -10059,6 +10716,8 @@ snapshots: get-port-please@3.2.0: {} + get-port@7.1.0: {} + get-proto@1.0.1: dependencies: dunder-proto: 1.0.1 @@ -10091,6 +10750,8 @@ snapshots: dependencies: is-glob: 4.0.3 + glob-to-regexp@0.4.1: {} + glob@10.4.5: dependencies: foreground-child: 3.3.0 @@ -10481,6 +11142,8 @@ snapshots: is-alphabetical: 2.0.1 is-decimal: 2.0.1 + is-arrayish@0.3.4: {} + is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 @@ -11600,6 +12263,24 @@ snapshots: min-indent@1.0.1: {} + miniflare@4.20251001.0: + dependencies: + '@cspotcode/source-map-support': 0.8.1 + acorn: 8.14.0 + acorn-walk: 8.3.2 + exit-hook: 2.2.1 + glob-to-regexp: 0.4.1 + sharp: 0.33.5 + stoppable: 1.1.0 + undici: 7.14.0 + workerd: 1.20251001.0 + ws: 8.18.0 + youch: 4.1.0-beta.10 + zod: 3.22.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -12436,6 +13117,32 @@ snapshots: setprototypeof@1.2.0: {} + sharp@0.33.5: + dependencies: + color: 4.2.3 + detect-libc: 2.0.4 + semver: 7.7.2 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.5 + '@img/sharp-darwin-x64': 0.33.5 + '@img/sharp-libvips-darwin-arm64': 1.0.4 + '@img/sharp-libvips-darwin-x64': 1.0.4 + '@img/sharp-libvips-linux-arm': 1.0.5 + '@img/sharp-libvips-linux-arm64': 1.0.4 + '@img/sharp-libvips-linux-s390x': 1.0.4 + '@img/sharp-libvips-linux-x64': 1.0.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + '@img/sharp-linux-arm': 0.33.5 + '@img/sharp-linux-arm64': 0.33.5 + '@img/sharp-linux-s390x': 0.33.5 + '@img/sharp-linux-x64': 0.33.5 + '@img/sharp-linuxmusl-arm64': 0.33.5 + '@img/sharp-linuxmusl-x64': 0.33.5 + '@img/sharp-wasm32': 0.33.5 + '@img/sharp-win32-ia32': 0.33.5 + '@img/sharp-win32-x64': 0.33.5 + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -12465,6 +13172,10 @@ snapshots: once: 1.4.0 simple-concat: 1.0.1 + simple-swizzle@0.2.4: + dependencies: + is-arrayish: 0.3.4 + sirv@3.0.1: dependencies: '@polka/url': 1.0.0-next.29 @@ -12554,6 +13265,8 @@ snapshots: std-env@3.9.0: {} + stoppable@1.1.0: {} + streamx@2.22.0: dependencies: fast-fifo: 1.3.2 @@ -12861,6 +13574,8 @@ snapshots: undici-types@7.10.0: optional: true + undici@7.14.0: {} + unenv@1.10.0: dependencies: consola: 3.4.2 @@ -13670,6 +14385,30 @@ snapshots: word-wrap@1.2.5: {} + workerd@1.20251001.0: + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20251001.0 + '@cloudflare/workerd-darwin-arm64': 1.20251001.0 + '@cloudflare/workerd-linux-64': 1.20251001.0 + '@cloudflare/workerd-linux-arm64': 1.20251001.0 + '@cloudflare/workerd-windows-64': 1.20251001.0 + + wrangler@4.42.0: + dependencies: + '@cloudflare/kv-asset-handler': 0.4.0 + '@cloudflare/unenv-preset': 2.7.6(unenv@2.0.0-rc.21)(workerd@1.20251001.0) + blake3-wasm: 2.1.5 + esbuild: 0.25.4 + miniflare: 4.20251001.0 + path-to-regexp: 6.3.0 + unenv: 2.0.0-rc.21 + workerd: 1.20251001.0 + optionalDependencies: + fsevents: 2.3.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -13690,6 +14429,8 @@ snapshots: wrappy@1.0.2: {} + ws@8.18.0: {} + ws@8.18.3: {} xml-name-validator@5.0.0: {} @@ -13723,6 +14464,14 @@ snapshots: '@poppinss/exception': 1.2.2 error-stack-parser-es: 1.0.5 + youch@4.1.0-beta.10: + dependencies: + '@poppinss/colors': 4.1.5 + '@poppinss/dumper': 0.6.4 + '@speed-highlight/core': 1.2.7 + cookie: 1.0.2 + youch-core: 0.3.3 + youch@4.1.0-beta.11: dependencies: '@poppinss/colors': 4.1.5 @@ -13737,6 +14486,8 @@ snapshots: compress-commons: 6.0.2 readable-stream: 4.7.0 + zod@3.22.3: {} + zod@3.25.76: {} zwitch@2.0.4: {} diff --git a/examples/todomvc/vite.config.ts b/examples/todomvc/vite.config.ts index f244fc1d1..fd34baaa4 100644 --- a/examples/todomvc/vite.config.ts +++ b/examples/todomvc/vite.config.ts @@ -1,6 +1,7 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import { defineConfig } from "vite"; export default defineConfig({ - plugins: [solidStart()] + plugins: [solidStart(), nitroV2Plugin()] }); diff --git a/examples/with-auth/vite.config.ts b/examples/with-auth/vite.config.ts index ee07eac66..41f000e94 100644 --- a/examples/with-auth/vite.config.ts +++ b/examples/with-auth/vite.config.ts @@ -1,4 +1,5 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import tailwindcss from "@tailwindcss/vite"; import { defineConfig } from "vite"; @@ -6,8 +7,8 @@ export default defineConfig({ plugins: [ solidStart({ ssr: true, // false for client-side rendering only - server: { preset: "" } // your deployment }), - tailwindcss() + tailwindcss(), + nitroV2Plugin() ] }); diff --git a/examples/with-authjs/vite.config.ts b/examples/with-authjs/vite.config.ts index ca8abc1dc..fd34baaa4 100644 --- a/examples/with-authjs/vite.config.ts +++ b/examples/with-authjs/vite.config.ts @@ -1,6 +1,7 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import { defineConfig } from "vite"; export default defineConfig({ - plugins: [solidStart({ ssr: true })] + plugins: [solidStart(), nitroV2Plugin()] }); diff --git a/examples/with-drizzle/vite.config.ts b/examples/with-drizzle/vite.config.ts index d760a7e8b..3a8e2b547 100644 --- a/examples/with-drizzle/vite.config.ts +++ b/examples/with-drizzle/vite.config.ts @@ -1,7 +1,8 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import { defineConfig } from "vite"; export default defineConfig({ - plugins: [solidStart()], + plugins: [solidStart(), nitroV2Plugin()], ssr: { external: ["drizzle-orm"] } }); diff --git a/examples/with-mdx/vite.config.ts b/examples/with-mdx/vite.config.ts index a0b99e648..480f68ae4 100644 --- a/examples/with-mdx/vite.config.ts +++ b/examples/with-mdx/vite.config.ts @@ -1,4 +1,5 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import { defineConfig } from "vite"; /* @ts-ignore */ import pkg from "@vinxi/plugin-mdx"; @@ -14,5 +15,6 @@ export default defineConfig({ solidStart({ extensions: ["mdx", "md"], }), + nitroV2Plugin() ] }); diff --git a/examples/with-prisma/vite.config.ts b/examples/with-prisma/vite.config.ts index d7a302d48..148115f2d 100644 --- a/examples/with-prisma/vite.config.ts +++ b/examples/with-prisma/vite.config.ts @@ -1,7 +1,8 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import { defineConfig } from "vite"; export default defineConfig({ - plugins: [solidStart()], + plugins: [solidStart(), nitroV2Plugin()], ssr: { external: ["@prisma/client"] } }); diff --git a/examples/with-solid-styled/vite.config.ts b/examples/with-solid-styled/vite.config.ts index d7852eea4..22e71231d 100644 --- a/examples/with-solid-styled/vite.config.ts +++ b/examples/with-solid-styled/vite.config.ts @@ -1,4 +1,5 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import solidStyled from "unplugin-solid-styled"; import type { PluginOption } from "vite"; import { defineConfig } from "vite"; @@ -11,6 +12,7 @@ export default defineConfig({ include: "src/**/*.tsx", exclude: "node_modules/**/*.{ts,js}" } - }) as PluginOption + }) as PluginOption, + nitroV2Plugin() ] }); diff --git a/examples/with-solidbase/vite.config.ts b/examples/with-solidbase/vite.config.ts index 68794c5d9..62a918775 100644 --- a/examples/with-solidbase/vite.config.ts +++ b/examples/with-solidbase/vite.config.ts @@ -1,5 +1,6 @@ import { solidBase } from "@kobalte/solidbase/config"; import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import { defineConfig } from "vite"; export default defineConfig({ @@ -31,13 +32,11 @@ export default defineConfig({ } } }), - solidStart({ - extensions: ["md", "mdx"], - server: { - prerender: { - crawlLinks: true - } + solidStart({ extensions: ["md", "mdx"] }), + nitroV2Plugin({ + prerender: { + crawlLinks: true } - }), + }) ] }); diff --git a/examples/with-strict-csp/vite.config.ts b/examples/with-strict-csp/vite.config.ts index f08277b95..b62d22ba2 100644 --- a/examples/with-strict-csp/vite.config.ts +++ b/examples/with-strict-csp/vite.config.ts @@ -1,10 +1,12 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import { defineConfig } from "vite"; export default defineConfig({ plugins: [ solidStart({ middleware: "src/middleware.ts" - }) + }), + nitroV2Plugin() ] }); diff --git a/examples/with-tailwindcss/vite.config.ts b/examples/with-tailwindcss/vite.config.ts index 33a5f4391..81af577d3 100644 --- a/examples/with-tailwindcss/vite.config.ts +++ b/examples/with-tailwindcss/vite.config.ts @@ -1,8 +1,8 @@ - import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import tailwindcss from "@tailwindcss/vite"; import { defineConfig } from "vite"; export default defineConfig({ - plugins: [solidStart(), tailwindcss()] + plugins: [solidStart(), tailwindcss(), nitroV2Plugin()] }); diff --git a/examples/with-tanstack-router/vite.config.ts b/examples/with-tanstack-router/vite.config.ts index d543c67a2..a6d204281 100644 --- a/examples/with-tanstack-router/vite.config.ts +++ b/examples/with-tanstack-router/vite.config.ts @@ -1,7 +1,8 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import { TanStackRouterVite } from "@tanstack/router-plugin/vite"; import { defineConfig } from "vite"; export default defineConfig({ - plugins: [solidStart(), TanStackRouterVite({ target: "solid" })] + plugins: [solidStart(), TanStackRouterVite({ target: "solid" }), nitroV2Plugin()] }); diff --git a/examples/with-trpc/vite.config.ts b/examples/with-trpc/vite.config.ts index f244fc1d1..fd34baaa4 100644 --- a/examples/with-trpc/vite.config.ts +++ b/examples/with-trpc/vite.config.ts @@ -1,6 +1,7 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import { defineConfig } from "vite"; export default defineConfig({ - plugins: [solidStart()] + plugins: [solidStart(), nitroV2Plugin()] }); diff --git a/examples/with-unocss/vite.config.ts b/examples/with-unocss/vite.config.ts index ba100a8f5..a81099920 100644 --- a/examples/with-unocss/vite.config.ts +++ b/examples/with-unocss/vite.config.ts @@ -1,7 +1,8 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import UnoCSS from "unocss/vite"; import { defineConfig } from "vite"; export default defineConfig({ - plugins: [UnoCSS(), solidStart()] + plugins: [UnoCSS(), solidStart(), nitroV2Plugin()] }); diff --git a/examples/with-vitest/vite.config.ts b/examples/with-vitest/vite.config.ts index f244fc1d1..fd34baaa4 100644 --- a/examples/with-vitest/vite.config.ts +++ b/examples/with-vitest/vite.config.ts @@ -1,6 +1,7 @@ import { solidStart } from "@solidjs/start/config"; +import { nitroV2Plugin } from "@solidjs/start/nitro-v2-plugin"; import { defineConfig } from "vite"; export default defineConfig({ - plugins: [solidStart()] + plugins: [solidStart(), nitroV2Plugin()] }); diff --git a/packages/start/package.json b/packages/start/package.json index ebd5c8d1d..2a17c3445 100644 --- a/packages/start/package.json +++ b/packages/start/package.json @@ -12,6 +12,7 @@ ".": "./dist/index.js", "./config": "./dist/config/index.js", "./server": "./dist/server/index.jsx", + "./server/entry": "./dist/server/entry.js", "./client": "./dist/client/index.jsx", "./router": "./dist/router.jsx", "./server/spa": "./dist/server/spa/index.jsx", diff --git a/packages/start/src/config/fs-routes/index.ts b/packages/start/src/config/fs-routes/index.ts index c35fafce3..8a4dacf6a 100644 --- a/packages/start/src/config/fs-routes/index.ts +++ b/packages/start/src/config/fs-routes/index.ts @@ -1,4 +1,4 @@ -import { relative } from "node:path"; +import { relative } from "pathe"; import type { PluginOption } from "vite"; import { VITE_ENVIRONMENT_NAMES } from "../../constants.js"; diff --git a/packages/start/src/config/index.ts b/packages/start/src/config/index.ts index 59cce21dd..0b21fe0b9 100644 --- a/packages/start/src/config/index.ts +++ b/packages/start/src/config/index.ts @@ -128,12 +128,12 @@ function solidStartVitePlugin( input: viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server] ?.build?.rollupOptions?.input ?? ENTRY_POINTS.server, + treeshake: true }, outDir: getServerOutputDirectory(viteConfig), copyPublicDir: viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server] - ?.build?.copyPublicDir ?? false, - }, + ?.build?.copyPublicDir ?? false, }, }, }, resolve: { diff --git a/packages/start/src/config/nitro-v2-plugin.ts b/packages/start/src/config/nitro-v2-plugin.ts index af51c7e1c..a75164074 100644 --- a/packages/start/src/config/nitro-v2-plugin.ts +++ b/packages/start/src/config/nitro-v2-plugin.ts @@ -60,24 +60,6 @@ export function nitroV2Plugin(nitroConfig?: NitroConfig): PluginOption { ssrBundle = bundle; }, }, - configEnvironment(name) { - if (name === VITE_ENVIRONMENT_NAMES.server) { - return { - build: { - commonjsOptions: { - include: [], - }, - ssr: true, - sourcemap: true, - rollupOptions: { - input: "~/entry-server.tsx", - }, - }, - } satisfies EnvironmentOptions; - } - - return null; - }, configResolved(config) { resolvedConfig = config; }, @@ -138,7 +120,7 @@ export function nitroV2Plugin(nitroConfig?: NitroConfig): PluginOption { asyncContext: true, ...nitroConfig?.experimental, }, - renderer: ssrEntryFile, + renderer: virtualEntry, rollupConfig: { ...nitroConfig?.rollupConfig, plugins: [virtualBundlePlugin(ssrBundle) as any], @@ -147,7 +129,7 @@ export function nitroV2Plugin(nitroConfig?: NitroConfig): PluginOption { ...nitroConfig?.virtual, [virtualEntry]: `import { fromWebHandler } from 'h3' import handler from '${ssrEntryFile}' - export default fromWebHandler(handler.fetch)`, + export default handler`, }, }; diff --git a/packages/start/src/config/resolve-entries.ts b/packages/start/src/config/resolve-entries.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/start/src/constants.ts b/packages/start/src/constants.ts index 4113721ef..b464bc581 100644 --- a/packages/start/src/constants.ts +++ b/packages/start/src/constants.ts @@ -1,7 +1,5 @@ export const DEFAULT_EXTENSIONS = ["js", "jsx", "ts", "tsx"]; -export const CLIENT_BASE_PATH = "_build"; - export const VIRTUAL_MODULES = { clientViteManifest: "solid-start:client-vite-manifest", getClientManifest: "solid-start:get-client-manifest", @@ -21,4 +19,5 @@ export type ViteEnvironmentNames = export const ENTRY_POINTS = { client: "virtual:solid-start-client-entry", server: "virtual:solid-start-server-entry", + start: "#solid-start-entry", } as const; diff --git a/packages/start/src/server/collect-styles.ts b/packages/start/src/server/collect-styles.ts index 1399281df..dc72be11f 100644 --- a/packages/start/src/server/collect-styles.ts +++ b/packages/start/src/server/collect-styles.ts @@ -1,4 +1,4 @@ -import path from "node:path"; +import path from "pathe"; import { join, resolve } from "pathe"; import type { ModuleNode, ViteDevServer } from "vite"; diff --git a/packages/start/src/server/entry.ts b/packages/start/src/server/entry.ts new file mode 100644 index 000000000..e9700019b --- /dev/null +++ b/packages/start/src/server/entry.ts @@ -0,0 +1,6 @@ +import { createApp, toWebHandler } from "h3"; +import serverEntry from "virtual:solid-start-server-entry"; + +export default { + fetch: toWebHandler(createApp().use(serverEntry)) +} diff --git a/packages/start/src/server/handler.ts b/packages/start/src/server/handler.ts index a8c08ee4e..757efcc49 100644 --- a/packages/start/src/server/handler.ts +++ b/packages/start/src/server/handler.ts @@ -33,7 +33,7 @@ export function createBaseHandler( | HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise) = {}, ) { - const handler = eventHandler({ + const _handler = eventHandler({ ...middleware, handler: async (e: H3Event) => { const event = getRequestEvent()!; @@ -107,8 +107,8 @@ export function createBaseHandler( }); return eventHandler((e: H3Event) => - provideRequestEvent(getFetchEvent(e), () => handler(e)), - ); + provideRequestEvent(getFetchEvent(e), () => _handler(e)), + ) } export function createHandler( diff --git a/packages/start/src/server/manifest/dev-ssr-manifest.ts b/packages/start/src/server/manifest/dev-ssr-manifest.ts index a38d2866e..790b3e8ae 100644 --- a/packages/start/src/server/manifest/dev-ssr-manifest.ts +++ b/packages/start/src/server/manifest/dev-ssr-manifest.ts @@ -1,5 +1,5 @@ -import { join, resolve } from "pathe"; -import { normalizePath, type ViteDevServer } from "vite"; +import { join, normalize, resolve } from "pathe"; +import type { ViteDevServer } from "vite"; import { findStylesInModuleGraph } from "../collect-styles.js"; @@ -7,7 +7,7 @@ export function getSsrDevManifest(target: "client" | "server") { const vite: ViteDevServer = (globalThis as any).VITE_DEV_SERVER; return { - path: (id: string) => normalizePath(join("/@fs", resolve(process.cwd(), id))), + path: (id: string) => normalize(join("/@fs", resolve(process.cwd(), id))), async getAssets(id: string) { const styles = await findStylesInModuleGraph(vite, id, target === "server"); diff --git a/packages/start/src/server/manifest/prod-ssr-manifest.ts b/packages/start/src/server/manifest/prod-ssr-manifest.ts index f07214301..cde5ba129 100644 --- a/packages/start/src/server/manifest/prod-ssr-manifest.ts +++ b/packages/start/src/server/manifest/prod-ssr-manifest.ts @@ -1,6 +1,5 @@ import { clientViteManifest } from "solid-start:client-vite-manifest"; import { join } from "pathe"; -import { CLIENT_BASE_PATH } from "../../constants.js"; import type { Asset } from "../renderAsset.jsx"; // Only reads from client manifest atm, might need server support for islands @@ -13,7 +12,7 @@ export function getSsrProdManifest() { if (!viteManifestEntry) throw new Error("No entry found in vite manifest"); - return `/${CLIENT_BASE_PATH}/${viteManifestEntry.file}`; + return `/${viteManifestEntry.file}`; }, async getAssets(id) { return createHtmlTagsForAssets( @@ -31,7 +30,7 @@ export function getSsrProdManifest() { for (const entryKey of entryKeys) { json[entryKey] = { - output: join("/", CLIENT_BASE_PATH, viteManifest[entryKey]!.file), + output: join("/", viteManifest[entryKey]!.file), assets: await this.getAssets(entryKey), }; } @@ -55,8 +54,8 @@ function createHtmlTagsForAssets(assets: string[]) { .map((asset) => ({ tag: "link", attrs: { - href: join("/", CLIENT_BASE_PATH, asset), - key: join("/", CLIENT_BASE_PATH, asset), + href: join("/", asset), + key: join("/", asset), ...(asset.endsWith(".css") ? { rel: "stylesheet", fetchPriority: "high" } : { rel: "modulepreload" }), diff --git a/packages/start/src/virtual.d.ts b/packages/start/src/virtual.d.ts index 0b5f056bd..7c47515e6 100644 --- a/packages/start/src/virtual.d.ts +++ b/packages/start/src/virtual.d.ts @@ -25,3 +25,7 @@ declare module "solid-start:middleware" { onBeforeResponse?: MaybeArray; }; } + +declare module "virtual:solid-start-server-entry" { + export default serverEntry as import("h3").EventHandler +} From ae2605cc997ba80c6e5b309a9b9c884351dba2a7 Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Sat, 4 Oct 2025 15:43:21 +0800 Subject: [PATCH 3/3] remove unused import --- packages/start/src/config/nitro-v2-plugin.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/start/src/config/nitro-v2-plugin.ts b/packages/start/src/config/nitro-v2-plugin.ts index a75164074..037db5434 100644 --- a/packages/start/src/config/nitro-v2-plugin.ts +++ b/packages/start/src/config/nitro-v2-plugin.ts @@ -127,9 +127,8 @@ export function nitroV2Plugin(nitroConfig?: NitroConfig): PluginOption { }, virtual: { ...nitroConfig?.virtual, - [virtualEntry]: `import { fromWebHandler } from 'h3' - import handler from '${ssrEntryFile}' - export default handler`, + [virtualEntry]: `import handler from '${ssrEntryFile}' + export default handler`, }, };