@analogjs/vite-plugin-nitro 3.0.0-alpha.17 → 3.0.0-alpha.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/index.js.map +1 -1
- package/src/lib/build-server.js.map +1 -1
- package/src/lib/build-sitemap.js.map +1 -1
- package/src/lib/build-ssr.js.map +1 -1
- package/src/lib/hooks/post-rendering-hook.js.map +1 -1
- package/src/lib/plugins/dev-server-plugin.js.map +1 -1
- package/src/lib/plugins/page-endpoints.js.map +1 -1
- package/src/lib/utils/get-content-files.js.map +1 -1
- package/src/lib/utils/get-page-handlers.js.map +1 -1
- package/src/lib/utils/node-web-bridge.js.map +1 -1
- package/src/lib/utils/register-dev-middleware.js.map +1 -1
- package/src/lib/utils/renderers.js.map +1 -1
- package/src/lib/utils/rolldown.js.map +1 -1
- package/src/lib/vite-plugin-nitro.js.map +1 -1
package/package.json
CHANGED
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/index.ts"],"sourcesContent":["import { nitro } from './lib/vite-plugin-nitro.js';\nexport type {\n Options,\n SitemapConfig,\n SitemapEntry,\n SitemapExcludeRule,\n SitemapPriority,\n SitemapRouteDefinition,\n SitemapRouteInput,\n SitemapRouteSource,\n SitemapTransform,\n PrerenderSitemapConfig,\n PrerenderRouteConfig,\n PrerenderContentDir,\n PrerenderContentFile,\n} from './lib/options.js';\n\ndeclare module 'nitro/types' {\n interface NitroRouteConfig {\n ssr?: boolean;\n }\n\n interface NitroRouteRules {\n ssr?: boolean;\n }\n}\n\nexport default nitro;\n"],"mappings":";;AA2BA,IAAA,cAAe"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-server.js","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"build-server.js","names":[],"sources":["../../../src/lib/build-server.ts"],"sourcesContent":["import type { NitroConfig } from 'nitro/types';\nimport {\n build,\n copyPublicAssets,\n createNitro,\n prepare,\n prerender,\n} from 'nitro/builder';\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nimport { Options } from './options.js';\nimport { addPostRenderingHooks } from './hooks/post-rendering-hook.js';\n\n/**\n * Ensures a minimal `tsconfig.json` exists in the SSR output directory.\n *\n * Nitro v3's `nitro:oxc` Rollup plugin uses OXC's resolver for every\n * file it transforms. OXC walks up the directory tree looking for a\n * `tsconfig.json` to load path aliases. The SSR output directory\n * (`dist/<app>/ssr/`) is outside the source tree, so no tsconfig\n * exists there. On Windows, OXC's upward directory walk also fails to\n * reach the project root's tsconfig due to path normalisation issues,\n * causing:\n *\n * [TSCONFIG_ERROR] Failed to load tsconfig for\n * '../../dist/apps/blog-app/ssr/main.server.js': Tsconfig not found\n *\n * Writing a minimal tsconfig satisfies the resolver without adding any\n * path aliases that would interfere with Nitro's own module resolution.\n */\nfunction ensureSsrTsconfig(nitroConfig: NitroConfig | undefined) {\n const ssrEntry = nitroConfig?.alias?.['#analog/ssr'];\n if (!ssrEntry) {\n return;\n }\n\n // The alias value is a normalized absolute path (forward slashes on\n // all platforms). Convert to a native path for dirname().\n const ssrDir = dirname(ssrEntry.replace(/\\//g, join('a', 'b')[1]));\n const tsconfigPath = join(ssrDir, 'tsconfig.json');\n\n if (existsSync(tsconfigPath)) {\n return;\n }\n\n writeFileSync(\n tsconfigPath,\n JSON.stringify(\n { compilerOptions: { module: 'ESNext', moduleResolution: 'bundler' } },\n null,\n 2,\n ),\n 'utf8',\n );\n}\n\nexport function isVercelPreset(preset: string | undefined): boolean {\n return !!preset?.toLowerCase().includes('vercel');\n}\n\nfunction getVercelBuildConfigPath(\n nitro: Awaited<ReturnType<typeof createNitro>>,\n) {\n return join(nitro.options.output.dir, 'config.json');\n}\n\nfunction assertValidVercelBuildConfig(\n nitro: Awaited<ReturnType<typeof createNitro>>,\n) {\n if (!isVercelPreset(nitro.options.preset)) {\n return;\n }\n\n const buildConfigPath = getVercelBuildConfigPath(nitro);\n if (!existsSync(buildConfigPath)) {\n throw new Error(\n `Nitro did not generate the expected Vercel build output config at \"${buildConfigPath}\".`,\n );\n }\n\n const buildConfig = readFileSync(buildConfigPath, 'utf8').trim();\n if (!buildConfig) {\n throw new Error(\n `Nitro generated an empty Vercel build output config at \"${buildConfigPath}\".`,\n );\n }\n\n try {\n JSON.parse(buildConfig);\n } catch (error) {\n const symptomError = new Error(\n `Nitro generated an invalid Vercel build output config at \"${buildConfigPath}\": ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n\n (symptomError as Error & { cause?: unknown }).cause = error;\n throw symptomError;\n }\n}\n\nfunction ensureVercelFunctionConfig(\n nitro: Awaited<ReturnType<typeof createNitro>>,\n) {\n if (!isVercelPreset(nitro.options.preset)) {\n return;\n }\n\n const serverDir = nitro.options.output.serverDir;\n const functionConfigPath = join(serverDir, '.vc-config.json');\n\n if (existsSync(functionConfigPath)) {\n return;\n }\n\n mkdirSync(serverDir, { recursive: true });\n\n writeFileSync(\n functionConfigPath,\n JSON.stringify(\n {\n handler: 'index.mjs',\n launcherType: 'Nodejs',\n shouldAddHelpers: false,\n supportsResponseStreaming: true,\n ...nitro.options.vercel?.functions,\n },\n null,\n 2,\n ),\n 'utf8',\n );\n}\n\nexport async function buildServer(\n options?: Options,\n nitroConfig?: NitroConfig,\n routeSourceFiles?: Record<string, string>,\n): Promise<void> {\n // ── Ensure the SSR output has a tsconfig for OXC ─────────────────\n //\n // Must run before createNitro() so the tsconfig is on disk when the\n // nitro:oxc plugin initialises its resolver.\n ensureSsrTsconfig(nitroConfig);\n\n // ── Force Rollup as the server bundler ────────────────────────────\n //\n // Nitro v3 defaults to Rolldown when available. Rolldown is faster,\n // but its module resolver cannot resolve relative chunk imports\n // (e.g. `./assets/core-DTazUigR.js`) from a rebundled SSR entry on\n // Windows. The prerender build fails with:\n //\n // [RESOLVE_ERROR] Could not resolve './assets/core-DTazUigR.js'\n // in ../../dist/apps/blog-app/ssr/main.server.js\n //\n // This is a known Rolldown limitation with cross-directory relative\n // paths on Windows (backslash vs forward-slash normalisation).\n // Rollup handles these paths correctly on all platforms.\n //\n // The dev server already uses `builder: 'rollup'` for the same\n // reason. Default to Rollup here too until Rolldown's resolver\n // matures. The caller can still opt in to Rolldown explicitly via\n // nitroConfig.builder if their platform supports it.\n const nitro = await createNitro({\n dev: false,\n preset: process.env['BUILD_PRESET'],\n ...nitroConfig,\n builder: nitroConfig?.builder ?? 'rollup',\n });\n\n if (options?.prerender?.postRenderingHooks) {\n addPostRenderingHooks(nitro, options.prerender.postRenderingHooks);\n }\n\n await prepare(nitro);\n await copyPublicAssets(nitro);\n\n if (\n options?.ssr &&\n nitroConfig?.prerender?.routes &&\n (nitroConfig?.prerender?.routes.find((route) => route === '/') ||\n nitroConfig?.prerender?.routes?.length === 0)\n ) {\n const indexFileExts = ['', '.br', '.gz'];\n\n indexFileExts.forEach((fileExt) => {\n // Remove the root index.html(.br|.gz) files\n const indexFilePath = join(\n nitroConfig?.output?.publicDir ?? '',\n `index.html${fileExt}`,\n );\n\n rmSync(indexFilePath, { force: true });\n });\n }\n\n if (\n nitroConfig?.prerender?.routes &&\n nitroConfig?.prerender?.routes?.length > 0\n ) {\n console.log(`Prerendering static pages...`);\n await prerender(nitro);\n }\n\n if (routeSourceFiles && Object.keys(routeSourceFiles).length > 0) {\n const publicDir = nitroConfig?.output?.publicDir;\n if (!publicDir) {\n throw new Error(\n 'Nitro public output directory is required to write route source files.',\n );\n }\n\n for (const [route, content] of Object.entries(routeSourceFiles)) {\n const outputPath = join(publicDir, `${route}.md`);\n const outputDir = dirname(outputPath);\n mkdirSync(outputDir, { recursive: true });\n\n writeFileSync(outputPath, content, 'utf8');\n }\n }\n\n if (!options?.static) {\n console.log('Building Server...');\n await build(nitro);\n ensureVercelFunctionConfig(nitro);\n }\n\n await nitro.close();\n assertValidVercelBuildConfig(nitro);\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-sitemap.js","names":[],"sources":["../../../../../packages/vite-plugin-nitro/src/lib/build-sitemap.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { create } from 'xmlbuilder2';\nimport { XMLBuilder } from 'xmlbuilder2/lib/interfaces';\nimport { UserConfig } from 'vite';\nimport {\n PrerenderSitemapConfig,\n SitemapConfig,\n SitemapEntry,\n SitemapExcludeRule,\n SitemapRouteDefinition,\n SitemapRouteInput,\n SitemapRouteSource,\n} from './options';\n\ntype RouteSitemapConfig =\n | PrerenderSitemapConfig\n | (() => PrerenderSitemapConfig)\n | undefined;\n\nexport type PagesJson = SitemapEntry;\n\nexport interface BuildSitemapOptions {\n apiPrefix?: string;\n}\n\nexport async function buildSitemap(\n _config: UserConfig,\n sitemapConfig: SitemapConfig,\n routes: (string | undefined)[] | (() => Promise<(string | undefined)[]>),\n outputDir: string,\n routeSitemaps: Record<string, RouteSitemapConfig>,\n buildOptions: BuildSitemapOptions = {},\n): Promise<void> {\n const host = normalizeSitemapHost(sitemapConfig.host);\n const routeList = await collectSitemapRoutes(routes, sitemapConfig.include);\n const sitemapData = await resolveSitemapEntries(\n routeList,\n host,\n routeSitemaps,\n sitemapConfig,\n buildOptions,\n );\n\n if (!sitemapData.length) {\n return;\n }\n\n const sitemap = createXml('urlset');\n\n for (const item of sitemapData) {\n const page = sitemap.ele('url');\n page.ele('loc').txt(item.loc);\n\n if (item.lastmod) {\n page.ele('lastmod').txt(item.lastmod);\n }\n\n if (item.changefreq) {\n page.ele('changefreq').txt(item.changefreq);\n }\n\n if (item.priority !== undefined) {\n page.ele('priority').txt(String(item.priority));\n }\n }\n\n const resolvedOutputDir = resolve(outputDir);\n const mapPath = resolve(resolvedOutputDir, 'sitemap.xml');\n try {\n if (!resolvedOutputDir || resolvedOutputDir === resolve()) {\n throw new Error(\n 'Refusing to write the sitemap to the current working directory. Expected the Nitro public output directory instead.',\n );\n }\n\n if (!existsSync(resolvedOutputDir)) {\n mkdirSync(resolvedOutputDir, { recursive: true });\n }\n console.log(`Writing sitemap at ${mapPath}`);\n writeFileSync(mapPath, sitemap.end({ prettyPrint: true }));\n } catch (e) {\n console.error(`Unable to write file at ${mapPath}`, e);\n }\n}\n\nasync function resolveSitemapEntries(\n routes: SitemapRouteInput[],\n host: string,\n routeSitemaps: Record<string, RouteSitemapConfig>,\n sitemapConfig: SitemapConfig,\n buildOptions: BuildSitemapOptions,\n): Promise<SitemapEntry[]> {\n const defaults = sitemapConfig.defaults ?? {};\n const seen = new Set<string>();\n const entries: SitemapEntry[] = [];\n\n for (const route of routes) {\n const entry = await toSitemapEntry(\n route,\n host,\n routeSitemaps,\n defaults,\n sitemapConfig.transform,\n );\n\n if (!entry) {\n continue;\n }\n\n if (\n isInternalSitemapRoute(entry.route, buildOptions.apiPrefix) ||\n (await isExcludedSitemapRoute(entry, sitemapConfig.exclude))\n ) {\n continue;\n }\n\n if (seen.has(entry.loc)) {\n continue;\n }\n\n seen.add(entry.loc);\n entries.push(entry);\n }\n\n return entries;\n}\n\nasync function toSitemapEntry(\n route: SitemapRouteInput,\n host: string,\n routeSitemaps: Record<string, RouteSitemapConfig>,\n defaults: PrerenderSitemapConfig,\n transform: SitemapConfig['transform'],\n): Promise<SitemapEntry | undefined> {\n const normalizedRoute = normalizeSitemapRoute(\n typeof route === 'string' ? route : route?.route,\n );\n if (!normalizedRoute) {\n return undefined;\n }\n\n const baseEntry = createSitemapEntry(\n {\n ...defaults,\n ...resolveRouteSitemapConfig(routeSitemaps[normalizedRoute]),\n ...(typeof route === 'object' ? route : {}),\n route: normalizedRoute,\n },\n host,\n );\n\n if (!transform) {\n return baseEntry;\n }\n\n const transformed = await transform(baseEntry);\n if (!transformed) {\n return undefined;\n }\n\n return createSitemapEntry(\n {\n ...baseEntry,\n ...transformed,\n },\n host,\n );\n}\n\nfunction createSitemapEntry(\n routeDefinition: SitemapRouteDefinition,\n host: string,\n): SitemapEntry {\n const route = normalizeSitemapRoute(routeDefinition.route) ?? '/';\n\n return {\n route,\n loc: new URL(route, ensureTrailingSlash(host)).toString(),\n lastmod: routeDefinition.lastmod,\n changefreq: routeDefinition.changefreq,\n priority: routeDefinition.priority,\n };\n}\n\nfunction resolveRouteSitemapConfig(\n config: RouteSitemapConfig,\n): PrerenderSitemapConfig {\n if (!config) {\n return {};\n }\n\n return typeof config === 'function' ? config() : config;\n}\n\nfunction normalizeSitemapHost(host: string): string {\n const resolvedHost = new URL(host);\n resolvedHost.hash = '';\n return resolvedHost.toString();\n}\n\nfunction ensureTrailingSlash(host: string): string {\n return host.endsWith('/') ? host : `${host}/`;\n}\n\nfunction normalizeSitemapRoute(route: string | undefined): string | undefined {\n if (!route) {\n return undefined;\n }\n\n const trimmedRoute = route.trim();\n if (!trimmedRoute) {\n return undefined;\n }\n\n const pathWithQuery = trimmedRoute.split('#', 1)[0] ?? '';\n const [pathname, search] = pathWithQuery.split('?', 2);\n const normalizedPathname = pathname\n ? `/${pathname.replace(/^\\/+/, '').replace(/\\/{2,}/g, '/')}`\n : '/';\n\n return search ? `${normalizedPathname}?${search}` : normalizedPathname;\n}\n\nfunction isInternalSitemapRoute(route: string, apiPrefix = 'api'): boolean {\n const normalizedApiPrefix = normalizeSitemapRoute(`/${apiPrefix}`) ?? '/api';\n return (\n route === `${normalizedApiPrefix}/_analog/pages` ||\n route.startsWith(`${normalizedApiPrefix}/_analog/pages/`)\n );\n}\n\nasync function isExcludedSitemapRoute(\n entry: SitemapEntry,\n excludeRules: SitemapExcludeRule[] | undefined,\n): Promise<boolean> {\n if (!excludeRules?.length) {\n return false;\n }\n\n for (const rule of excludeRules) {\n if (typeof rule === 'function') {\n if (await rule(entry)) {\n return true;\n }\n continue;\n }\n\n if (rule instanceof RegExp) {\n if (rule.test(entry.route)) {\n return true;\n }\n continue;\n }\n\n if (toGlobRegExp(rule).test(entry.route)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction toGlobRegExp(pattern: string): RegExp {\n const doubleStarToken = '__ANALOG_DOUBLE_STAR__';\n const singleStarToken = '__ANALOG_SINGLE_STAR__';\n const escapedPattern = pattern\n .replace(/\\*\\*/g, doubleStarToken)\n .replace(/\\*/g, singleStarToken)\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&');\n const regexPattern = escapedPattern\n .replace(new RegExp(doubleStarToken, 'g'), '.*')\n .replace(new RegExp(singleStarToken, 'g'), '[^/]*');\n return new RegExp(`^${regexPattern}$`);\n}\n\nasync function collectSitemapRoutes(\n routes: (string | undefined)[] | (() => Promise<(string | undefined)[]>),\n include?: SitemapRouteSource,\n): Promise<SitemapRouteInput[]> {\n const routeList = await resolveRouteInputs(routes);\n const includedRoutes = include ? await resolveRouteInputs(include) : [];\n return [...routeList, ...includedRoutes];\n}\n\nasync function resolveRouteInputs(\n routes:\n | SitemapRouteSource\n | (string | undefined)[]\n | (() => Promise<(string | undefined)[]>),\n): Promise<SitemapRouteInput[]> {\n let routeList: SitemapRouteInput[];\n\n if (typeof routes === 'function') {\n routeList = await routes();\n } else if (Array.isArray(routes)) {\n routeList = routes;\n } else {\n routeList = [];\n }\n\n return routeList.filter(Boolean);\n}\n\nfunction createXml(elementName: 'urlset' | 'sitemapindex'): XMLBuilder {\n return create({ version: '1.0', encoding: 'UTF-8' })\n .ele(elementName, {\n xmlns: 'https://www.sitemaps.org/schemas/sitemap/0.9',\n })\n .com(`This file was automatically generated by Analog.`);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"build-sitemap.js","names":[],"sources":["../../../src/lib/build-sitemap.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { create } from 'xmlbuilder2';\nimport { XMLBuilder } from 'xmlbuilder2/lib/interfaces';\nimport { UserConfig } from 'vite';\nimport {\n PrerenderSitemapConfig,\n SitemapConfig,\n SitemapEntry,\n SitemapExcludeRule,\n SitemapRouteDefinition,\n SitemapRouteInput,\n SitemapRouteSource,\n} from './options';\n\ntype RouteSitemapConfig =\n | PrerenderSitemapConfig\n | (() => PrerenderSitemapConfig)\n | undefined;\n\nexport type PagesJson = SitemapEntry;\n\nexport interface BuildSitemapOptions {\n apiPrefix?: string;\n}\n\nexport async function buildSitemap(\n _config: UserConfig,\n sitemapConfig: SitemapConfig,\n routes: (string | undefined)[] | (() => Promise<(string | undefined)[]>),\n outputDir: string,\n routeSitemaps: Record<string, RouteSitemapConfig>,\n buildOptions: BuildSitemapOptions = {},\n): Promise<void> {\n const host = normalizeSitemapHost(sitemapConfig.host);\n const routeList = await collectSitemapRoutes(routes, sitemapConfig.include);\n const sitemapData = await resolveSitemapEntries(\n routeList,\n host,\n routeSitemaps,\n sitemapConfig,\n buildOptions,\n );\n\n if (!sitemapData.length) {\n return;\n }\n\n const sitemap = createXml('urlset');\n\n for (const item of sitemapData) {\n const page = sitemap.ele('url');\n page.ele('loc').txt(item.loc);\n\n if (item.lastmod) {\n page.ele('lastmod').txt(item.lastmod);\n }\n\n if (item.changefreq) {\n page.ele('changefreq').txt(item.changefreq);\n }\n\n if (item.priority !== undefined) {\n page.ele('priority').txt(String(item.priority));\n }\n }\n\n const resolvedOutputDir = resolve(outputDir);\n const mapPath = resolve(resolvedOutputDir, 'sitemap.xml');\n try {\n if (!resolvedOutputDir || resolvedOutputDir === resolve()) {\n throw new Error(\n 'Refusing to write the sitemap to the current working directory. Expected the Nitro public output directory instead.',\n );\n }\n\n if (!existsSync(resolvedOutputDir)) {\n mkdirSync(resolvedOutputDir, { recursive: true });\n }\n console.log(`Writing sitemap at ${mapPath}`);\n writeFileSync(mapPath, sitemap.end({ prettyPrint: true }));\n } catch (e) {\n console.error(`Unable to write file at ${mapPath}`, e);\n }\n}\n\nasync function resolveSitemapEntries(\n routes: SitemapRouteInput[],\n host: string,\n routeSitemaps: Record<string, RouteSitemapConfig>,\n sitemapConfig: SitemapConfig,\n buildOptions: BuildSitemapOptions,\n): Promise<SitemapEntry[]> {\n const defaults = sitemapConfig.defaults ?? {};\n const seen = new Set<string>();\n const entries: SitemapEntry[] = [];\n\n for (const route of routes) {\n const entry = await toSitemapEntry(\n route,\n host,\n routeSitemaps,\n defaults,\n sitemapConfig.transform,\n );\n\n if (!entry) {\n continue;\n }\n\n if (\n isInternalSitemapRoute(entry.route, buildOptions.apiPrefix) ||\n (await isExcludedSitemapRoute(entry, sitemapConfig.exclude))\n ) {\n continue;\n }\n\n if (seen.has(entry.loc)) {\n continue;\n }\n\n seen.add(entry.loc);\n entries.push(entry);\n }\n\n return entries;\n}\n\nasync function toSitemapEntry(\n route: SitemapRouteInput,\n host: string,\n routeSitemaps: Record<string, RouteSitemapConfig>,\n defaults: PrerenderSitemapConfig,\n transform: SitemapConfig['transform'],\n): Promise<SitemapEntry | undefined> {\n const normalizedRoute = normalizeSitemapRoute(\n typeof route === 'string' ? route : route?.route,\n );\n if (!normalizedRoute) {\n return undefined;\n }\n\n const baseEntry = createSitemapEntry(\n {\n ...defaults,\n ...resolveRouteSitemapConfig(routeSitemaps[normalizedRoute]),\n ...(typeof route === 'object' ? route : {}),\n route: normalizedRoute,\n },\n host,\n );\n\n if (!transform) {\n return baseEntry;\n }\n\n const transformed = await transform(baseEntry);\n if (!transformed) {\n return undefined;\n }\n\n return createSitemapEntry(\n {\n ...baseEntry,\n ...transformed,\n },\n host,\n );\n}\n\nfunction createSitemapEntry(\n routeDefinition: SitemapRouteDefinition,\n host: string,\n): SitemapEntry {\n const route = normalizeSitemapRoute(routeDefinition.route) ?? '/';\n\n return {\n route,\n loc: new URL(route, ensureTrailingSlash(host)).toString(),\n lastmod: routeDefinition.lastmod,\n changefreq: routeDefinition.changefreq,\n priority: routeDefinition.priority,\n };\n}\n\nfunction resolveRouteSitemapConfig(\n config: RouteSitemapConfig,\n): PrerenderSitemapConfig {\n if (!config) {\n return {};\n }\n\n return typeof config === 'function' ? config() : config;\n}\n\nfunction normalizeSitemapHost(host: string): string {\n const resolvedHost = new URL(host);\n resolvedHost.hash = '';\n return resolvedHost.toString();\n}\n\nfunction ensureTrailingSlash(host: string): string {\n return host.endsWith('/') ? host : `${host}/`;\n}\n\nfunction normalizeSitemapRoute(route: string | undefined): string | undefined {\n if (!route) {\n return undefined;\n }\n\n const trimmedRoute = route.trim();\n if (!trimmedRoute) {\n return undefined;\n }\n\n const pathWithQuery = trimmedRoute.split('#', 1)[0] ?? '';\n const [pathname, search] = pathWithQuery.split('?', 2);\n const normalizedPathname = pathname\n ? `/${pathname.replace(/^\\/+/, '').replace(/\\/{2,}/g, '/')}`\n : '/';\n\n return search ? `${normalizedPathname}?${search}` : normalizedPathname;\n}\n\nfunction isInternalSitemapRoute(route: string, apiPrefix = 'api'): boolean {\n const normalizedApiPrefix = normalizeSitemapRoute(`/${apiPrefix}`) ?? '/api';\n return (\n route === `${normalizedApiPrefix}/_analog/pages` ||\n route.startsWith(`${normalizedApiPrefix}/_analog/pages/`)\n );\n}\n\nasync function isExcludedSitemapRoute(\n entry: SitemapEntry,\n excludeRules: SitemapExcludeRule[] | undefined,\n): Promise<boolean> {\n if (!excludeRules?.length) {\n return false;\n }\n\n for (const rule of excludeRules) {\n if (typeof rule === 'function') {\n if (await rule(entry)) {\n return true;\n }\n continue;\n }\n\n if (rule instanceof RegExp) {\n if (rule.test(entry.route)) {\n return true;\n }\n continue;\n }\n\n if (toGlobRegExp(rule).test(entry.route)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction toGlobRegExp(pattern: string): RegExp {\n const doubleStarToken = '__ANALOG_DOUBLE_STAR__';\n const singleStarToken = '__ANALOG_SINGLE_STAR__';\n const escapedPattern = pattern\n .replace(/\\*\\*/g, doubleStarToken)\n .replace(/\\*/g, singleStarToken)\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&');\n const regexPattern = escapedPattern\n .replace(new RegExp(doubleStarToken, 'g'), '.*')\n .replace(new RegExp(singleStarToken, 'g'), '[^/]*');\n return new RegExp(`^${regexPattern}$`);\n}\n\nasync function collectSitemapRoutes(\n routes: (string | undefined)[] | (() => Promise<(string | undefined)[]>),\n include?: SitemapRouteSource,\n): Promise<SitemapRouteInput[]> {\n const routeList = await resolveRouteInputs(routes);\n const includedRoutes = include ? await resolveRouteInputs(include) : [];\n return [...routeList, ...includedRoutes];\n}\n\nasync function resolveRouteInputs(\n routes:\n | SitemapRouteSource\n | (string | undefined)[]\n | (() => Promise<(string | undefined)[]>),\n): Promise<SitemapRouteInput[]> {\n let routeList: SitemapRouteInput[];\n\n if (typeof routes === 'function') {\n routeList = await routes();\n } else if (Array.isArray(routes)) {\n routeList = routes;\n } else {\n routeList = [];\n }\n\n return routeList.filter(Boolean);\n}\n\nfunction createXml(elementName: 'urlset' | 'sitemapindex'): XMLBuilder {\n return create({ version: '1.0', encoding: 'UTF-8' })\n .ele(elementName, {\n xmlns: 'https://www.sitemaps.org/schemas/sitemap/0.9',\n })\n .com(`This file was automatically generated by Analog.`);\n}\n"],"mappings":"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"}
|
package/src/lib/build-ssr.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-ssr.js","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"build-ssr.js","names":[],"sources":["../../../src/lib/build-ssr.ts"],"sourcesContent":["import { build, mergeConfig, UserConfig } from 'vite';\nimport { relative, resolve } from 'node:path';\n\nimport { Options } from './options.js';\nimport { getBundleOptionsKey } from './utils/rolldown.js';\n\nexport async function buildClientApp(\n config: UserConfig,\n options?: Options,\n): Promise<void> {\n const workspaceRoot = options?.workspaceRoot ?? process.cwd();\n const rootDir = relative(workspaceRoot, config.root || '.') || '.';\n const clientBuildConfig = mergeConfig(config, <UserConfig>{\n build: {\n ssr: false,\n outDir:\n config.build?.outDir ||\n resolve(workspaceRoot, 'dist', rootDir, 'client'),\n emptyOutDir: true,\n },\n });\n\n await build(clientBuildConfig);\n}\n\nexport async function buildSSRApp(\n config: UserConfig,\n options?: Options,\n): Promise<void> {\n const workspaceRoot = options?.workspaceRoot ?? process.cwd();\n const sourceRoot = options?.sourceRoot ?? 'src';\n const rootDir = relative(workspaceRoot, config.root || '.') || '.';\n const bundleOptionsKey = getBundleOptionsKey();\n const ssrBuildConfig = mergeConfig(config, <UserConfig>{\n build: {\n ssr: true,\n [bundleOptionsKey]: {\n input:\n options?.entryServer ||\n resolve(workspaceRoot, rootDir, `${sourceRoot}/main.server.ts`),\n },\n outDir:\n options?.ssrBuildDir || resolve(workspaceRoot, 'dist', rootDir, 'ssr'),\n // Preserve the client build output. The client pass already handled its\n // own cleanup, and on Windows this nested SSR build can otherwise remove\n // sibling artifacts that Nitro needs to read immediately afterward.\n emptyOutDir: false,\n },\n });\n\n await build(ssrBuildConfig);\n}\n"],"mappings":";;;;AAMA,eAAsB,eACpB,QACA,SACe;CACf,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ,KAAK;CAC7D,MAAM,UAAU,SAAS,eAAe,OAAO,QAAQ,IAAI,IAAI;AAW/D,OAAM,MAVoB,YAAY,QAAoB,EACxD,OAAO;EACL,KAAK;EACL,QACE,OAAO,OAAO,UACd,QAAQ,eAAe,QAAQ,SAAS,SAAS;EACnD,aAAa;EACd,EACF,CAAC,CAE4B;;AAGhC,eAAsB,YACpB,QACA,SACe;CACf,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ,KAAK;CAC7D,MAAM,aAAa,SAAS,cAAc;CAC1C,MAAM,UAAU,SAAS,eAAe,OAAO,QAAQ,IAAI,IAAI;AAmB/D,OAAM,MAjBiB,YAAY,QAAoB,EACrD,OAAO;EACL,KAAK;GAHgB,qBAAqB,GAItB,EAClB,OACE,SAAS,eACT,QAAQ,eAAe,SAAS,GAAG,WAAW,iBAAiB,EAClE;EACD,QACE,SAAS,eAAe,QAAQ,eAAe,QAAQ,SAAS,MAAM;EAIxE,aAAa;EACd,EACF,CAAC,CAEyB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-rendering-hook.js","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"post-rendering-hook.js","names":[],"sources":["../../../../src/lib/hooks/post-rendering-hook.ts"],"sourcesContent":["import type { Nitro, PrerenderRoute } from 'nitro/types';\n\nexport function addPostRenderingHooks(\n nitro: Nitro,\n hooks: ((pr: PrerenderRoute) => Promise<void>)[],\n): void {\n hooks.forEach((hook: (preRoute: PrerenderRoute) => void) => {\n nitro.hooks.hook('prerender:generate', (route: PrerenderRoute) => {\n hook(route);\n });\n });\n}\n"],"mappings":";AAEA,SAAgB,sBACd,OACA,OACM;AACN,OAAM,SAAS,SAA6C;AAC1D,QAAM,MAAM,KAAK,uBAAuB,UAA0B;AAChE,QAAK,MAAM;IACX;GACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-server-plugin.js","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"dev-server-plugin.js","names":[],"sources":["../../../../src/lib/plugins/dev-server-plugin.ts"],"sourcesContent":["// SSR dev server, middleware and error page source modified from\n// https://github.com/solidjs/solid-start/blob/main/packages/start/dev/server.js\n\nimport {\n Connect,\n Plugin,\n UserConfig,\n ViteDevServer,\n normalizePath,\n} from 'vite';\nimport { resolve } from 'node:path';\nimport { readFileSync } from 'node:fs';\nimport { createRouter as createRadixRouter, toRouteMatcher } from 'radix3';\nimport { defu } from 'defu';\nimport type { NitroRouteRules } from 'nitro/types';\n\nimport { registerDevServerMiddleware } from '../utils/register-dev-middleware.js';\nimport { writeWebResponseToNode } from '../utils/node-web-bridge.js';\nimport { Options } from '../options.js';\n\ntype ServerOptions = Options & { routeRules?: Record<string, any> | undefined };\n\nexport function devServerPlugin(options: ServerOptions): Plugin {\n const workspaceRoot = options?.workspaceRoot || process.cwd();\n const sourceRoot = options?.sourceRoot ?? 'src';\n const index = options.index || 'index.html';\n let config: UserConfig;\n let root: string;\n let isTest = false;\n\n return {\n name: 'analogjs-dev-ssr-plugin',\n config(userConfig, { mode }) {\n config = userConfig;\n root = normalizePath(resolve(workspaceRoot, config.root || '.') || '.');\n isTest = isTest ? isTest : mode === 'test';\n return {\n appType: 'custom',\n resolve: {\n alias: {\n '~analog/entry-server':\n options.entryServer || `${root}/${sourceRoot}/main.server.ts`,\n },\n },\n };\n },\n configureServer(viteServer) {\n if (isTest) {\n return;\n }\n\n return async () => {\n remove_html_middlewares(viteServer.middlewares);\n registerDevServerMiddleware(root, sourceRoot, viteServer);\n\n viteServer.middlewares.use(async (req, res) => {\n let template = readFileSync(\n resolve(viteServer.config.root, index),\n 'utf-8',\n );\n\n template = await viteServer.transformIndexHtml(\n req.originalUrl as string,\n template,\n );\n\n const _routeRulesMatcher = toRouteMatcher(\n createRadixRouter({ routes: options.routeRules }),\n );\n const _getRouteRules = (path: string) =>\n defu(\n {},\n ..._routeRulesMatcher.matchAll(path).reverse(),\n ) as NitroRouteRules;\n\n try {\n let result: string | Response;\n // Check for route rules explicitly disabling SSR\n if (_getRouteRules(req.originalUrl as string).ssr === false) {\n result = template;\n } else {\n const entryServer = (\n await viteServer.ssrLoadModule('~analog/entry-server')\n )['default'];\n result = await entryServer(req.originalUrl, template, {\n req,\n res,\n });\n }\n\n if (result instanceof Response) {\n await writeWebResponseToNode(res, result);\n return;\n }\n res.setHeader('Content-Type', 'text/html');\n res.end(result);\n } catch (e) {\n viteServer.ssrFixStacktrace(e as Error);\n res.statusCode = 500;\n res.end(`\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <title>Error</title>\n <script type=\"module\">\n import { ErrorOverlay } from '/@vite/client'\n document.body.appendChild(new ErrorOverlay(${JSON.stringify(\n prepareError(req, e),\n ).replace(/</g, '\\\\u003c')}))\n </script>\n </head>\n <body>\n </body>\n </html>\n `);\n }\n });\n };\n },\n };\n}\n\n/**\n * Removes Vite internal middleware\n *\n * @param server\n */\nfunction remove_html_middlewares(server: ViteDevServer['middlewares']) {\n const html_middlewares = [\n 'viteIndexHtmlMiddleware',\n 'vite404Middleware',\n 'viteSpaFallbackMiddleware',\n 'viteHtmlFallbackMiddleware',\n ];\n for (let i = server.stack.length - 1; i > 0; i--) {\n const handler = server.stack[i]?.handle;\n const handlerName =\n typeof handler === 'function' ? handler.name : undefined;\n if (handlerName && html_middlewares.includes(handlerName)) {\n server.stack.splice(i, 1);\n }\n }\n}\n\n/**\n * Formats error for SSR message in error overlay\n * @param req\n * @param error\n * @returns\n */\nfunction prepareError(req: Connect.IncomingMessage, error: unknown) {\n const e = error as Error;\n return {\n message: `An error occured while server rendering ${req.url}:\\n\\n\\t${\n typeof e === 'string' ? e : e.message\n } `,\n stack: typeof e === 'string' ? '' : e.stack,\n };\n}\n"],"mappings":";;;;;;;;AAsBA,SAAgB,gBAAgB,SAAgC;CAC9D,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ,KAAK;CAC7D,MAAM,aAAa,SAAS,cAAc;CAC1C,MAAM,QAAQ,QAAQ,SAAS;CAC/B,IAAI;CACJ,IAAI;CACJ,IAAI,SAAS;AAEb,QAAO;EACL,MAAM;EACN,OAAO,YAAY,EAAE,QAAQ;AAC3B,YAAS;AACT,UAAO,cAAc,QAAQ,eAAe,OAAO,QAAQ,IAAI,IAAI,IAAI;AACvE,YAAS,SAAS,SAAS,SAAS;AACpC,UAAO;IACL,SAAS;IACT,SAAS,EACP,OAAO,EACL,wBACE,QAAQ,eAAe,GAAG,KAAK,GAAG,WAAW,kBAChD,EACF;IACF;;EAEH,gBAAgB,YAAY;AAC1B,OAAI,OACF;AAGF,UAAO,YAAY;AACjB,4BAAwB,WAAW,YAAY;AAC/C,gCAA4B,MAAM,YAAY,WAAW;AAEzD,eAAW,YAAY,IAAI,OAAO,KAAK,QAAQ;KAC7C,IAAI,WAAW,aACb,QAAQ,WAAW,OAAO,MAAM,MAAM,EACtC,QACD;AAED,gBAAW,MAAM,WAAW,mBAC1B,IAAI,aACJ,SACD;KAED,MAAM,qBAAqB,eACzB,aAAkB,EAAE,QAAQ,QAAQ,YAAY,CAAC,CAClD;KACD,MAAM,kBAAkB,SACtB,KACE,EAAE,EACF,GAAG,mBAAmB,SAAS,KAAK,CAAC,SAAS,CAC/C;AAEH,SAAI;MACF,IAAI;AAEJ,UAAI,eAAe,IAAI,YAAsB,CAAC,QAAQ,MACpD,UAAS;WACJ;OACL,MAAM,eACJ,MAAM,WAAW,cAAc,uBAAuB,EACtD;AACF,gBAAS,MAAM,YAAY,IAAI,aAAa,UAAU;QACpD;QACA;QACD,CAAC;;AAGJ,UAAI,kBAAkB,UAAU;AAC9B,aAAM,uBAAuB,KAAK,OAAO;AACzC;;AAEF,UAAI,UAAU,gBAAgB,YAAY;AAC1C,UAAI,IAAI,OAAO;cACR,GAAG;AACV,iBAAW,iBAAiB,EAAW;AACvC,UAAI,aAAa;AACjB,UAAI,IAAI;;;;;;;;iEAQ6C,KAAK,UAChD,aAAa,KAAK,EAAE,CACrB,CAAC,QAAQ,MAAM,UAAU,CAAC;;;;;;cAMjC;;MAEJ;;;EAGP;;;;;;;AAQH,SAAS,wBAAwB,QAAsC;CACrE,MAAM,mBAAmB;EACvB;EACA;EACA;EACA;EACD;AACD,MAAK,IAAI,IAAI,OAAO,MAAM,SAAS,GAAG,IAAI,GAAG,KAAK;EAChD,MAAM,UAAU,OAAO,MAAM,IAAI;EACjC,MAAM,cACJ,OAAO,YAAY,aAAa,QAAQ,OAAO,KAAA;AACjD,MAAI,eAAe,iBAAiB,SAAS,YAAY,CACvD,QAAO,MAAM,OAAO,GAAG,EAAE;;;;;;;;;AAW/B,SAAS,aAAa,KAA8B,OAAgB;CAClE,MAAM,IAAI;AACV,QAAO;EACL,SAAS,2CAA2C,IAAI,IAAI,SAC1D,OAAO,MAAM,WAAW,IAAI,EAAE,QAC/B;EACD,OAAO,OAAO,MAAM,WAAW,KAAK,EAAE;EACvC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-endpoints.js","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"page-endpoints.js","names":[],"sources":["../../../../src/lib/plugins/page-endpoints.ts"],"sourcesContent":["import { parseSync } from 'oxc-parser';\nimport { normalizePath } from 'vite';\nimport { SERVER_FETCH_FACTORY_SNIPPET } from '../utils/renderers.js';\n\nexport function pageEndpointsPlugin() {\n return {\n name: 'analogjs-vite-plugin-nitro-rollup-page-endpoint',\n async transform(\n _code: string,\n id: string,\n ): Promise<{ code: string; map: null } | undefined> {\n if (normalizePath(id).includes('/pages/') && id.endsWith('.server.ts')) {\n const result = parseSync(id, _code, {\n sourceType: 'module',\n lang: 'ts',\n });\n\n const fileExports: string[] = result.module.staticExports.flatMap((e) =>\n e.entries\n .filter((entry) => entry.exportName.name !== null)\n .map((entry) => entry.exportName.name as string),\n );\n\n // In h3 v2 / Nitro v3, event.node is undefined during prerendering\n // (which uses the fetch-based pipeline, not Node.js http). We use\n // optional chaining so that page endpoints work in both Node.js\n // server and fetch-based prerender contexts.\n // Nitro v3 no longer guarantees the private `nitro/deps/ofetch`\n // subpath that older codegen relied on.\n //\n // Page loaders expect Nitro-style `$fetch` semantics (parsed data plus\n // internal relative-route support), so construct a request-local fetch\n // using public APIs:\n // - `createFetch` from `ofetch` for `$fetch` behavior\n // - `fetchWithEvent` from `h3` for internal Nitro request routing\n //\n // This avoids both unstable private Nitro imports and assumptions about\n // a global runtime `$fetch` being available during prerender.\n const code = `\n import { defineHandler, fetchWithEvent } from 'nitro/h3';\n import { createFetch } from 'ofetch';\n\n ${\n fileExports.includes('load')\n ? _code\n : `\n ${_code}\n export const load = () => {\n return {};\n }`\n }\n\n ${\n fileExports.includes('action')\n ? ''\n : `\n export const action = () => {\n return {};\n }\n `\n }\n\n export default defineHandler(async(event) => {\n ${SERVER_FETCH_FACTORY_SNIPPET}\n\n if (event.method === 'GET') {\n try {\n return await load({\n params: event.context.params,\n req: event.node?.req,\n res: event.node?.res,\n fetch: serverFetch,\n event\n });\n } catch(e) {\n console.error(\\` An error occurred: \\${e}\\`)\n throw e;\n }\n } else {\n try {\n return await action({\n params: event.context.params,\n req: event.node?.req,\n res: event.node?.res,\n fetch: serverFetch,\n event\n });\n } catch(e) {\n console.error(\\` An error occurred: \\${e}\\`)\n throw e;\n }\n }\n });\n `;\n\n return {\n code,\n map: null,\n };\n }\n\n return;\n },\n };\n}\n"],"mappings":";;;;AAIA,SAAgB,sBAAsB;AACpC,QAAO;EACL,MAAM;EACN,MAAM,UACJ,OACA,IACkD;AAClD,OAAI,cAAc,GAAG,CAAC,SAAS,UAAU,IAAI,GAAG,SAAS,aAAa,EAAE;IAMtE,MAAM,cALS,UAAU,IAAI,OAAO;KAClC,YAAY;KACZ,MAAM;KACP,CAAC,CAEmC,OAAO,cAAc,SAAS,MACjE,EAAE,QACC,QAAQ,UAAU,MAAM,WAAW,SAAS,KAAK,CACjD,KAAK,UAAU,MAAM,WAAW,KAAe,CACnD;AA0ED,WAAO;KACL,MA1DW;;;;cAKP,YAAY,SAAS,OAAO,GACxB,QACA;kBACA,MAAM;;;mBAIX;;cAGC,YAAY,SAAS,SAAS,GAC1B,KACA;;;;gBAKL;;;gBAGG,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAkCnC,KAAK;KACN;;;EAKN"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-content-files.js","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"get-content-files.js","names":[],"sources":["../../../../src/lib/utils/get-content-files.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { join, relative, resolve } from 'node:path';\nimport { normalizePath } from 'vite';\nimport { createRequire } from 'node:module';\nimport { globSync } from 'tinyglobby';\n\nimport { PrerenderContentFile } from '../options';\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Discovers content files with front matter and extracts metadata for prerendering.\n *\n * This function:\n * 1. Discovers all content files matching the specified glob pattern\n * 2. Reads each file and parses front matter metadata\n * 3. Extracts file name, extension, and path information\n * 4. Returns structured data for prerendering content pages\n *\n * @param workspaceRoot The workspace root directory path\n * @param rootDir The project root directory relative to workspace\n * @param glob The glob pattern to match content files (e.g., 'content/blog')\n * @returns Array of PrerenderContentFile objects with metadata and front matter\n *\n * Example usage:\n * const contentFiles = getMatchingContentFilesWithFrontMatter(\n * '/workspace',\n * 'apps/my-app',\n * 'content/blog'\n * );\n *\n * Sample discovered file paths:\n * - /workspace/apps/my-app/content/blog/first-post.md\n * - /workspace/apps/my-app/content/blog/2024/01/hello-world.md\n * - /workspace/apps/my-app/content/blog/tech/angular-v17.mdx\n * - /workspace/apps/my-app/content/blog/about/index.md\n *\n * Sample output structure:\n * {\n * name: 'first-post',\n * extension: 'md',\n * path: 'content/blog',\n * attributes: { title: 'My First Post', date: '2024-01-01', tags: ['intro'] }\n * }\n *\n * tinyglobby vs fast-glob comparison:\n * - Both support the same glob patterns for file discovery\n * - Both are efficient for finding content files\n * - tinyglobby is now used instead of fast-glob\n * - tinyglobby provides similar functionality with smaller bundle size\n * - tinyglobby's globSync returns absolute paths when absolute: true is set\n *\n * Front matter parsing:\n * - Uses front-matter library to parse YAML/TOML front matter\n * - Extracts metadata like title, date, tags, author, etc.\n * - Supports both YAML (---) and TOML (+++) delimiters\n * - Returns structured attributes for prerendering\n *\n * File path processing:\n * - Normalizes paths for cross-platform compatibility\n * - Extracts file name without extension\n * - Determines file extension for content type handling\n * - Maintains relative path structure for routing\n */\nexport function getMatchingContentFilesWithFrontMatter(\n workspaceRoot: string,\n rootDir: string,\n glob: string,\n): PrerenderContentFile[] {\n // Dynamically require front-matter library\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const fm = require('front-matter');\n\n // Normalize the project root path for consistent path handling\n const root = normalizePath(resolve(workspaceRoot, rootDir));\n\n // Resolve the content directory path relative to the project root\n const resolvedDir = normalizePath(relative(root, join(root, glob)));\n\n // Discover all content files in the specified directory\n // Pattern: looks for any files in the resolved directory\n const contentFiles: string[] = globSync([`${root}/${resolvedDir}/*`], {\n dot: true,\n absolute: true,\n });\n\n // Process each discovered content file to extract metadata and front matter\n const mappedFilesWithFm: PrerenderContentFile[] = contentFiles.map((f) => {\n // Read the file contents as UTF-8 text\n const fileContents = readFileSync(f, 'utf8');\n\n // Parse front matter from the file content\n const raw = fm(fileContents);\n\n const filepath = normalizePath(f).replace(root, '');\n\n const match = filepath.match(/\\/([^/.]+)(\\.([^/.]+))?$/);\n let name = '';\n let extension = '';\n if (match) {\n name = match[1]; // File name without extension\n extension = match[3] || ''; // File extension or empty string if no extension\n }\n\n // Return structured content file data for prerendering\n return {\n name,\n extension,\n path: resolvedDir,\n attributes: raw.attributes as { attributes: Record<string, any> },\n content: fileContents,\n };\n });\n\n return mappedFilesWithFm;\n}\n"],"mappings":";;;;;;AAQA,IAAM,UAAU,cAAc,OAAO,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwD9C,SAAgB,uCACd,eACA,SACA,MACwB;CAGxB,MAAM,KAAK,QAAQ,eAAe;CAGlC,MAAM,OAAO,cAAc,QAAQ,eAAe,QAAQ,CAAC;CAG3D,MAAM,cAAc,cAAc,SAAS,MAAM,KAAK,MAAM,KAAK,CAAC,CAAC;AAqCnE,QAjC+B,SAAS,CAAC,GAAG,KAAK,GAAG,YAAY,IAAI,EAAE;EACpE,KAAK;EACL,UAAU;EACX,CAAC,CAG6D,KAAK,MAAM;EAExE,MAAM,eAAe,aAAa,GAAG,OAAO;EAG5C,MAAM,MAAM,GAAG,aAAa;EAI5B,MAAM,QAFW,cAAc,EAAE,CAAC,QAAQ,MAAM,GAAG,CAE5B,MAAM,2BAA2B;EACxD,IAAI,OAAO;EACX,IAAI,YAAY;AAChB,MAAI,OAAO;AACT,UAAO,MAAM;AACb,eAAY,MAAM,MAAM;;AAI1B,SAAO;GACL;GACA;GACA,MAAM;GACN,YAAY,IAAI;GAChB,SAAS;GACV;GACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-page-handlers.js","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"get-page-handlers.js","names":[],"sources":["../../../../src/lib/utils/get-page-handlers.ts"],"sourcesContent":["import { resolve, relative } from 'node:path';\nimport { globSync } from 'tinyglobby';\n\nimport type { NitroEventHandler } from 'nitro/types';\nimport { normalizePath } from 'vite';\n\ntype GetHandlersArgs = {\n workspaceRoot: string;\n sourceRoot: string;\n rootDir: string;\n additionalPagesDirs?: string[];\n hasAPIDir?: boolean;\n};\n\n/**\n * Discovers and generates Nitro event handlers for server-side page routes.\n *\n * This function:\n * 1. Discovers all .server.ts files in the app/pages directory and additional pages directories\n * 2. Converts file paths to route patterns using Angular-style route syntax\n * 3. Generates Nitro event handlers with proper route mapping and lazy loading\n * 4. Handles dynamic route parameters and catch-all routes\n *\n * @param workspaceRoot The workspace root directory path\n * @param sourceRoot The source directory path (e.g., 'src')\n * @param rootDir The project root directory relative to workspace\n * @param additionalPagesDirs Optional array of additional pages directories to scan\n * @param hasAPIDir Whether the project has an API directory (affects route prefixing)\n * @returns Array of NitroEventHandler objects with handler paths and route patterns\n *\n * Example usage:\n * const handlers = getPageHandlers({\n * workspaceRoot: '/workspace',\n * sourceRoot: 'src',\n * rootDir: 'apps/my-app',\n * additionalPagesDirs: ['/libs/shared/pages'],\n * hasAPIDir: true\n * });\n *\n * Sample discovered file paths:\n * - /workspace/apps/my-app/src/app/pages/index.server.ts\n * - /workspace/apps/my-app/src/app/pages/users/[id].server.ts\n * - /workspace/apps/my-app/src/app/pages/products/[...slug].server.ts\n * - /workspace/apps/my-app/src/app/pages/(auth)/login.server.ts\n *\n * Route transformation examples:\n * - index.server.ts → /_analog/pages/index\n * - users/[id].server.ts → /_analog/pages/users/:id\n * - products/[...slug].server.ts → /_analog/pages/products/**:slug\n * - (auth)/login.server.ts → /_analog/pages/-auth-/login\n *\n * tinyglobby vs fast-glob comparison:\n * - Both support the same glob patterns for file discovery\n * - Both are efficient for finding server-side page files\n * - tinyglobby is now used instead of fast-glob\n * - tinyglobby provides similar functionality with smaller bundle size\n * - tinyglobby's globSync returns absolute paths when absolute: true is set\n *\n * Route transformation rules:\n * 1. Removes .server.ts extension\n * 2. Converts [param] to :param for dynamic routes\n * 3. Converts [...param] to **:param for catch-all routes\n * 4. Converts (group) to -group- for route groups\n * 5. Converts dots to forward slashes\n * 6. Prefixes with /_analog/pages and optionally /api\n */\nexport function getPageHandlers({\n workspaceRoot,\n sourceRoot,\n rootDir,\n additionalPagesDirs,\n hasAPIDir,\n}: GetHandlersArgs): NitroEventHandler[] {\n // Normalize the project root path for consistent path handling\n const root = normalizePath(resolve(workspaceRoot, rootDir));\n\n // Discover all .server.ts files in the app/pages directory and additional pages directories\n // Pattern: looks for any .server.ts files in app/pages/**/*.server.ts and additional directories\n const endpointFiles: string[] = globSync(\n [\n `${root}/${sourceRoot}/app/pages/**/*.server.ts`,\n ...(additionalPagesDirs || []).map(\n (dir) => `${workspaceRoot}${dir}/**/*.server.ts`,\n ),\n ],\n { dot: true, absolute: true },\n );\n\n // Transform each discovered file into a Nitro event handler\n const handlers: NitroEventHandler[] = endpointFiles.map((endpointFile) => {\n // Normalize the endpoint file path for consistent path handling\n const normalized = normalizePath(endpointFile);\n // Transform the normalized path into a route pattern\n const route = normalized\n .replace(/^(.*?)\\/pages/, '/pages')\n .replace(/\\.server\\.ts$/, '') // Remove .server.ts extension\n .replace(/\\[\\.{3}(.+)\\]/g, '**:$1') // Convert [...param] to **:param (catch-all routes)\n .replace(/\\[\\.{3}(\\w+)\\]/g, '**:$1') // Alternative catch-all pattern\n .replace(/\\/\\((.*?)\\)$/, '/-$1-') // Convert (group) to -group- (route groups)\n .replace(/\\[(\\w+)\\]/g, ':$1') // Convert [param] to :param (dynamic routes)\n .replace(/\\./g, '/'); // Convert dots to forward slashes\n\n // Return Nitro event handler with absolute handler path and transformed route\n return {\n handler: endpointFile,\n route: `${hasAPIDir ? '/api' : ''}/_analog${route}`,\n lazy: true,\n };\n });\n\n return handlers;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA,SAAgB,gBAAgB,EAC9B,eACA,YACA,SACA,qBACA,aACuC;AAsCvC,QAhCgC,SAC9B,CACE,GANS,cAAc,QAAQ,eAAe,QAAQ,CAAC,CAM/C,GAAG,WAAW,4BACtB,IAAI,uBAAuB,EAAE,EAAE,KAC5B,QAAQ,GAAG,gBAAgB,IAAI,iBACjC,CACF,EACD;EAAE,KAAK;EAAM,UAAU;EAAM,CAC9B,CAGmD,KAAK,iBAAiB;EAIxE,MAAM,QAFa,cAAc,aAAa,CAG3C,QAAQ,iBAAiB,SAAS,CAClC,QAAQ,iBAAiB,GAAG,CAC5B,QAAQ,kBAAkB,QAAQ,CAClC,QAAQ,mBAAmB,QAAQ,CACnC,QAAQ,gBAAgB,QAAQ,CAChC,QAAQ,cAAc,MAAM,CAC5B,QAAQ,OAAO,IAAI;AAGtB,SAAO;GACL,SAAS;GACT,OAAO,GAAG,YAAY,SAAS,GAAG,UAAU;GAC5C,MAAM;GACP;GACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-web-bridge.js","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"node-web-bridge.js","names":[],"sources":["../../../../src/lib/utils/node-web-bridge.ts"],"sourcesContent":["import type {\n IncomingHttpHeaders,\n IncomingMessage,\n ServerResponse,\n} from 'node:http';\nimport { Readable } from 'node:stream';\nimport { pipeline } from 'node:stream/promises';\n\nfunction toWebHeaders(headers: IncomingHttpHeaders) {\n return Object.entries(headers).reduce((acc, [key, value]) => {\n if (value && !key.startsWith(':')) {\n acc.set(key, Array.isArray(value) ? value.join(', ') : value);\n }\n\n return acc;\n }, new Headers());\n}\n\nexport function toWebRequest(req: IncomingMessage): Request {\n const protocol = 'http';\n const host = req.headers.host || 'localhost';\n const url = new URL(req.url || '/', `${protocol}://${host}`);\n const body =\n req.method && !['GET', 'HEAD'].includes(req.method)\n ? (Readable.toWeb(req) as ReadableStream<Uint8Array>)\n : undefined;\n\n return new Request(url, {\n method: req.method,\n headers: toWebHeaders(req.headers),\n body,\n // @ts-expect-error duplex is required for streaming request bodies in Node.js\n duplex: body ? 'half' : undefined,\n });\n}\n\nfunction isClientDisconnectError(error: unknown, res: ServerResponse): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n\n const hasDisconnectCode =\n 'code' in error &&\n typeof error.code === 'string' &&\n [\n 'ERR_STREAM_PREMATURE_CLOSE',\n 'ERR_INVALID_STATE',\n 'ECONNRESET',\n 'EPIPE',\n ].includes(error.code);\n\n const hasDisconnectMessage = /closed or destroyed stream/i.test(\n error.message,\n );\n\n return (\n (res.destroyed || res.writableEnded) &&\n (hasDisconnectCode || hasDisconnectMessage)\n );\n}\n\nexport async function writeWebResponseToNode(\n res: ServerResponse,\n response: Response,\n): Promise<void> {\n res.statusCode = response.status;\n res.statusMessage = response.statusText;\n\n const setCookies =\n 'getSetCookie' in response.headers &&\n typeof response.headers.getSetCookie === 'function'\n ? response.headers.getSetCookie()\n : [];\n\n if (setCookies.length > 0) {\n res.setHeader('set-cookie', setCookies);\n }\n\n response.headers.forEach((value, key) => {\n if (key !== 'set-cookie') {\n res.setHeader(key, value);\n }\n });\n\n if (!response.body) {\n res.end();\n return;\n }\n\n // The Web ReadableStream and Node.js stream/web ReadableStream types\n // are structurally identical at runtime but TypeScript treats them as\n // distinct nominal types. The double-cast bridges this gap safely.\n try {\n await pipeline(\n Readable.fromWeb(\n response.body as unknown as import('node:stream/web').ReadableStream,\n ),\n res,\n );\n } catch (error) {\n // Long-lived dev responses such as SSE can be interrupted by a browser\n // refresh or HMR-triggered reconnect. Those closed-stream cases are\n // expected and should not surface as noisy server errors.\n if (isClientDisconnectError(error, res)) {\n return;\n }\n\n throw error;\n }\n}\n"],"mappings":";;;AAQA,SAAS,aAAa,SAA8B;AAClD,QAAO,OAAO,QAAQ,QAAQ,CAAC,QAAQ,KAAK,CAAC,KAAK,WAAW;AAC3D,MAAI,SAAS,CAAC,IAAI,WAAW,IAAI,CAC/B,KAAI,IAAI,KAAK,MAAM,QAAQ,MAAM,GAAG,MAAM,KAAK,KAAK,GAAG,MAAM;AAG/D,SAAO;IACN,IAAI,SAAS,CAAC;;AAGnB,SAAgB,aAAa,KAA+B;CAC1D,MAAM,WAAW;CACjB,MAAM,OAAO,IAAI,QAAQ,QAAQ;CACjC,MAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,GAAG,SAAS,KAAK,OAAO;CAC5D,MAAM,OACJ,IAAI,UAAU,CAAC,CAAC,OAAO,OAAO,CAAC,SAAS,IAAI,OAAO,GAC9C,SAAS,MAAM,IAAI,GACpB,KAAA;AAEN,QAAO,IAAI,QAAQ,KAAK;EACtB,QAAQ,IAAI;EACZ,SAAS,aAAa,IAAI,QAAQ;EAClC;EAEA,QAAQ,OAAO,SAAS,KAAA;EACzB,CAAC;;AAGJ,SAAS,wBAAwB,OAAgB,KAA8B;AAC7E,KAAI,EAAE,iBAAiB,OACrB,QAAO;CAGT,MAAM,oBACJ,UAAU,SACV,OAAO,MAAM,SAAS,YACtB;EACE;EACA;EACA;EACA;EACD,CAAC,SAAS,MAAM,KAAK;CAExB,MAAM,uBAAuB,8BAA8B,KACzD,MAAM,QACP;AAED,SACG,IAAI,aAAa,IAAI,mBACrB,qBAAqB;;AAI1B,eAAsB,uBACpB,KACA,UACe;AACf,KAAI,aAAa,SAAS;AAC1B,KAAI,gBAAgB,SAAS;CAE7B,MAAM,aACJ,kBAAkB,SAAS,WAC3B,OAAO,SAAS,QAAQ,iBAAiB,aACrC,SAAS,QAAQ,cAAc,GAC/B,EAAE;AAER,KAAI,WAAW,SAAS,EACtB,KAAI,UAAU,cAAc,WAAW;AAGzC,UAAS,QAAQ,SAAS,OAAO,QAAQ;AACvC,MAAI,QAAQ,aACV,KAAI,UAAU,KAAK,MAAM;GAE3B;AAEF,KAAI,CAAC,SAAS,MAAM;AAClB,MAAI,KAAK;AACT;;AAMF,KAAI;AACF,QAAM,SACJ,SAAS,QACP,SAAS,KACV,EACD,IACD;UACM,OAAO;AAId,MAAI,wBAAwB,OAAO,IAAI,CACrC;AAGF,QAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register-dev-middleware.js","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"register-dev-middleware.js","names":[],"sources":["../../../../src/lib/utils/register-dev-middleware.ts"],"sourcesContent":["import { ViteDevServer } from 'vite';\nimport { EventHandler, H3 } from 'nitro/h3';\nimport { globSync } from 'tinyglobby';\n\nimport { toWebRequest, writeWebResponseToNode } from './node-web-bridge.js';\n\nconst PASSTHROUGH_HEADER = 'x-analog-passthrough';\n\n/**\n * Registers development server middleware by discovering and loading middleware files.\n *\n * Each discovered h3 middleware module is loaded through Vite's SSR loader,\n * wrapped in a temporary H3 app, then bridged back into Vite's Connect stack.\n * If the middleware does not write a response, control falls through to the\n * next Vite middleware.\n *\n * @param root The project root directory path\n * @param sourceRoot The source directory path (e.g., 'src')\n * @param viteServer The Vite development server instance\n */\nexport async function registerDevServerMiddleware(\n root: string,\n sourceRoot: string,\n viteServer: ViteDevServer,\n): Promise<void> {\n const middlewareFiles = globSync(\n [`${root}/${sourceRoot}/server/middleware/**/*.ts`],\n {\n dot: true,\n absolute: true,\n },\n );\n\n middlewareFiles.forEach((file) => {\n // Create the H3 app once per middleware file (not per request).\n // The dynamic handler inside still loads the module fresh each request\n // via ssrLoadModule, preserving HMR.\n const app = new H3();\n app.use(async (event) => {\n const handler: EventHandler = await viteServer\n .ssrLoadModule(file)\n .then((m: unknown) => (m as { default: EventHandler }).default);\n return handler(event);\n });\n // Sentinel catch-all: when the middleware returns undefined (does not\n // handle the request), h3 does not emit its default 404 — instead we\n // detect the passthrough header and let the Connect stack continue.\n app.use(\n () =>\n new Response(null, {\n status: 204,\n headers: { [PASSTHROUGH_HEADER]: '1' },\n }),\n );\n\n viteServer.middlewares.use(async (req, res, next) => {\n const response = await app.fetch(toWebRequest(req));\n\n if (response.headers.get(PASSTHROUGH_HEADER) === '1') {\n next();\n return;\n }\n\n await writeWebResponseToNode(res, response);\n });\n });\n}\n"],"mappings":";;;;AAMA,IAAM,qBAAqB;;;;;;;;;;;;;AAc3B,eAAsB,4BACpB,MACA,YACA,YACe;AACS,UACtB,CAAC,GAAG,KAAK,GAAG,WAAW,4BAA4B,EACnD;EACE,KAAK;EACL,UAAU;EACX,CACF,CAEe,SAAS,SAAS;EAIhC,MAAM,MAAM,IAAI,IAAI;AACpB,MAAI,IAAI,OAAO,UAAU;AAIvB,WAH8B,MAAM,WACjC,cAAc,KAAK,CACnB,MAAM,MAAgB,EAAgC,QAAQ,EAClD,MAAM;IACrB;AAIF,MAAI,UAEA,IAAI,SAAS,MAAM;GACjB,QAAQ;GACR,SAAS,GAAG,qBAAqB,KAAK;GACvC,CAAC,CACL;AAED,aAAW,YAAY,IAAI,OAAO,KAAK,KAAK,SAAS;GACnD,MAAM,WAAW,MAAM,IAAI,MAAM,aAAa,IAAI,CAAC;AAEnD,OAAI,SAAS,QAAQ,IAAI,mBAAmB,KAAK,KAAK;AACpD,UAAM;AACN;;AAGF,SAAM,uBAAuB,KAAK,SAAS;IAC3C;GACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderers.js","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"renderers.js","names":[],"sources":["../../../../src/lib/utils/renderers.ts"],"sourcesContent":["/**\n * Code snippet emitted into virtual modules to create a request-scoped\n * fetch using ofetch's `createFetch` + h3's `fetchWithEvent`.\n *\n * Shared between the SSR renderer and page-endpoint virtual modules so\n * the fetch-wiring logic stays in sync.\n *\n * The emitted variable is named `serverFetch` — callers should reference it\n * by that name.\n */\nexport const SERVER_FETCH_FACTORY_SNIPPET = `\n const serverFetch = createFetch({\n fetch: (resource, init) => {\n const url = resource instanceof Request ? resource.url : resource.toString();\n return fetchWithEvent(event, url, init);\n }\n });`;\n\n/**\n * SSR renderer virtual module content.\n *\n * This code runs inside Nitro's server runtime (Node.js context) where\n * event.node is always populated. In h3 v2, event.node is typed as optional,\n * so we use h3's first-class event properties (event.path, event.method) where\n * possible and apply optional chaining when accessing the Node.js context for\n * the Angular renderer which requires raw req/res objects.\n *\n * h3 v2 idiomatic APIs used:\n * - defineHandler (replaces defineEventHandler / eventHandler)\n * - event.path (replaces event.node.req.url)\n * - getResponseHeader compat shim (still available in h3 v2)\n */\nexport function ssrRenderer() {\n return `\nimport { createFetch } from 'ofetch';\nimport { defineHandler, fetchWithEvent } from 'nitro/h3';\n// @ts-ignore\nimport renderer from '#analog/ssr';\nimport template from '#analog/index';\n\nconst normalizeHtmlRequestUrl = (url) =>\n url.replace(/\\\\/index\\\\.html(?=$|[?#])/, '/');\n\nexport default defineHandler(async (event) => {\n event.res.headers.set('content-type', 'text/html; charset=utf-8');\n const noSSR = event.res.headers.get('x-analog-no-ssr');\n const requestPath = normalizeHtmlRequestUrl(event.path);\n\n if (noSSR === 'true') {\n return template;\n }\n\n // event.path is the canonical h3 v2 way to access the request URL.\n // event.node?.req and event.node?.res are needed by the Angular SSR renderer\n // which operates on raw Node.js request/response objects.\n // During prerendering (Nitro v3 fetch-based pipeline), event.node is undefined.\n // The Angular renderer requires a req object with at least { headers, url },\n // so we provide a minimal stub to avoid runtime errors in prerender context.\n const req = event.node?.req\n ? {\n ...event.node.req,\n url: requestPath,\n originalUrl: requestPath,\n }\n : {\n headers: { host: 'localhost' },\n url: requestPath,\n originalUrl: requestPath,\n connection: {},\n };\n const res = event.node?.res;\n${SERVER_FETCH_FACTORY_SNIPPET}\n\n const html = await renderer(requestPath, template, { req, res, fetch: serverFetch });\n\n return html;\n});`;\n}\n\n/**\n * Client-only renderer virtual module content.\n *\n * Used when SSR is disabled — simply serves the static index.html template\n * for every route, letting the client-side Angular router handle navigation.\n */\nexport function clientRenderer() {\n return `\nimport { defineHandler } from 'nitro/h3';\nimport template from '#analog/index';\n\nexport default defineHandler(async (event) => {\n event.res.headers.set('content-type', 'text/html; charset=utf-8');\n return template;\n});\n`;\n}\n\n/**\n * API middleware virtual module content.\n *\n * Intercepts requests matching the configured API prefix and either:\n * - Uses event-bound internal forwarding for GET requests (except .xml routes)\n * - Uses request proxying for all other methods to forward the full request\n *\n * h3 v2 idiomatic APIs used:\n * - defineHandler (replaces defineEventHandler / eventHandler)\n * - event.path (replaces event.node.req.url)\n * - event.method (replaces event.node.req.method)\n * - proxyRequest is retained internally because it preserves Nitro route\n * matching for event-bound server requests during SSR/prerender\n * - Object.fromEntries(event.req.headers.entries()) replaces direct event.node.req.headers access\n *\n * `fetchWithEvent` keeps the active event context while forwarding to a\n * rewritten path, which avoids falling through to the HTML renderer when\n * SSR code makes relative API requests.\n */\nexport const apiMiddleware = `\nimport { defineHandler, fetchWithEvent, proxyRequest } from 'nitro/h3';\nimport { useRuntimeConfig } from 'nitro/runtime-config';\n\nexport default defineHandler(async (event) => {\n const prefix = useRuntimeConfig().prefix;\n const apiPrefix = \\`\\${prefix}/\\${useRuntimeConfig().apiPrefix}\\`;\n\n if (event.path?.startsWith(apiPrefix)) {\n const reqUrl = event.path?.replace(apiPrefix, '');\n\n if (\n event.method === 'GET' &&\n // in the case of XML routes, we want to proxy the request so that nitro gets the correct headers\n // and can render the XML correctly as a static asset\n !event.path?.endsWith('.xml')\n ) {\n return fetchWithEvent(event, reqUrl, {\n headers: Object.fromEntries(event.req.headers.entries()),\n });\n }\n\n return proxyRequest(event, reqUrl);\n }\n});`;\n"],"mappings":";;;;;;;;;;;AAUA,IAAa,+BAA+B;;;;;;;;;;;;;;;;;;;;;AAsB5C,SAAgB,cAAc;AAC5B,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsCP,6BAA6B;;;;;;;;;;;;;AAc/B,SAAgB,iBAAiB;AAC/B,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BT,IAAa,gBAAgB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rolldown.js","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"rolldown.js","names":[],"sources":["../../../../src/lib/utils/rolldown.ts"],"sourcesContent":["import * as vite from 'vite';\n\nexport function isRolldown(): boolean {\n return !!vite.rolldownVersion;\n}\n\nexport function getBundleOptionsKey(): 'rolldownOptions' | 'rollupOptions' {\n return isRolldown() ? 'rolldownOptions' : 'rollupOptions';\n}\n"],"mappings":";;AAEA,SAAgB,aAAsB;AACpC,QAAO,CAAC,CAAC,KAAK;;AAGhB,SAAgB,sBAA2D;AACzE,QAAO,YAAY,GAAG,oBAAoB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-plugin-nitro.js","names":[],"sources":["../../../../../packages/vite-plugin-nitro/src/lib/vite-plugin-nitro.ts"],"sourcesContent":["import type { NitroConfig, NitroEventHandler, RollupConfig } from 'nitro/types';\nimport { build, createDevServer, createNitro } from 'nitro/builder';\nimport * as vite from 'vite';\nimport type { Plugin, UserConfig, ViteDevServer } from 'vite';\nimport { mergeConfig, normalizePath } from 'vite';\nimport { relative, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { existsSync, readFileSync, readdirSync } from 'node:fs';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\nimport { buildServer, isVercelPreset } from './build-server.js';\nimport { buildClientApp, buildSSRApp } from './build-ssr.js';\nimport {\n Options,\n PrerenderContentDir,\n PrerenderContentFile,\n PrerenderRouteConfig,\n PrerenderSitemapConfig,\n} from './options.js';\nimport { pageEndpointsPlugin } from './plugins/page-endpoints.js';\nimport { getPageHandlers } from './utils/get-page-handlers.js';\nimport { buildSitemap } from './build-sitemap.js';\nimport { devServerPlugin } from './plugins/dev-server-plugin.js';\nimport {\n toWebRequest,\n writeWebResponseToNode,\n} from './utils/node-web-bridge.js';\nimport { getMatchingContentFilesWithFrontMatter } from './utils/get-content-files.js';\nimport {\n ssrRenderer,\n clientRenderer,\n apiMiddleware,\n} from './utils/renderers.js';\nimport { getBundleOptionsKey, isRolldown } from './utils/rolldown.js';\n\nfunction createNitroMiddlewareHandler(handler: string): NitroEventHandler {\n return {\n route: '/**',\n handler,\n middleware: true,\n };\n}\n\n/**\n * Creates a `rollup:before` hook that marks specified packages as external\n * in Nitro's bundler config (applied to both the server build and the\n * prerender build).\n *\n * ## Subpath matching (Rolldown compatibility)\n *\n * When `bundlerConfig.external` is an **array**, Rollup automatically\n * prefix-matches entries — `'rxjs'` in the array will also externalise\n * `'rxjs/operators'`, `'rxjs/internal/Observable'`, etc.\n *\n * Rolldown (the default bundler in Nitro v3) does **not** do this. It\n * treats array entries as exact strings. To keep behaviour consistent\n * across both bundlers, the **function** branch already needed explicit\n * subpath matching. We now use the same `isExternal` helper for all\n * branches so that `'rxjs'` reliably matches `'rxjs/operators'`\n * regardless of whether the existing `external` value is a function,\n * array, or absent.\n *\n * Without this, the Nitro prerender build fails on Windows CI with:\n *\n * [RESOLVE_ERROR] Could not resolve 'rxjs/operators'\n */\nfunction createRollupBeforeHook(externalEntries: string[]) {\n const isExternal = (source: string) =>\n externalEntries.some(\n (entry) => source === entry || source.startsWith(entry + '/'),\n );\n\n return (_nitro: unknown, bundlerConfig: RollupConfig) => {\n sanitizeNitroBundlerConfig(_nitro, bundlerConfig);\n\n if (externalEntries.length === 0) {\n return;\n }\n\n const existing = bundlerConfig.external;\n if (!existing) {\n bundlerConfig.external = externalEntries;\n } else if (typeof existing === 'function') {\n bundlerConfig.external = (\n source: string,\n importer: string | undefined,\n isResolved: boolean,\n ) => existing(source, importer, isResolved) || isExternal(source);\n } else if (Array.isArray(existing)) {\n bundlerConfig.external = [...existing, ...externalEntries];\n } else {\n bundlerConfig.external = [existing as string, ...externalEntries];\n }\n };\n}\n\nfunction appendNoExternals(\n noExternals: NitroConfig['noExternals'],\n ...entries: string[]\n): NitroConfig['noExternals'] {\n if (!noExternals) {\n return entries;\n }\n\n return Array.isArray(noExternals)\n ? [...noExternals, ...entries]\n : noExternals;\n}\n\n/**\n * Patches Nitro's internal Rollup/Rolldown bundler config to work around\n * incompatibilities in the Nitro v3 alpha series.\n *\n * Called from the `rollup:before` hook, this function runs against the *final*\n * bundler config that Nitro assembles for its server/prerender builds — it\n * does NOT touch the normal Vite client or SSR environment configs.\n *\n * Each workaround is narrowly scoped and safe to remove once the corresponding\n * upstream Nitro issue is resolved.\n */\nfunction sanitizeNitroBundlerConfig(\n _nitro: unknown,\n bundlerConfig: RollupConfig,\n) {\n const output = bundlerConfig['output'];\n if (!output || Array.isArray(output) || typeof output !== 'object') {\n return;\n }\n\n // ── 1. Remove invalid `output.codeSplitting` ────────────────────────\n //\n // Nitro 3.0.1-alpha.2 adds `output.codeSplitting` to its internal bundler\n // config, but Rolldown rejects it as an unknown key:\n //\n // Warning: Invalid output options (1 issue found)\n // - For the \"codeSplitting\". Invalid key: Expected never but received \"codeSplitting\".\n //\n // Analog never sets this option. Removing it restores default bundler\n // behavior without changing any Analog semantics.\n if ('codeSplitting' in output) {\n delete (output as Record<string, unknown>)['codeSplitting'];\n }\n\n // ── 2. Remove invalid `output.manualChunks` ─────────────────────────\n //\n // Nitro's default config enables manual chunking for node_modules. Under\n // Nitro v3 alpha + Rollup 4.59 this crashes during the prerender rebundle:\n //\n // Cannot read properties of undefined (reading 'included')\n //\n // A single server bundle is acceptable for Analog's use case, so we strip\n // `manualChunks` until the upstream bug is fixed.\n if ('manualChunks' in output) {\n delete (output as Record<string, unknown>)['manualChunks'];\n }\n\n // ── 3. Escape route params in `output.chunkFileNames` ───────────────\n //\n // Nitro's `getChunkName()` derives chunk filenames from route patterns,\n // using its internal `routeToFsPath()` helper to convert route params\n // (`:productId` → `[productId]`) and catch-alls (`**` → `[...]`).\n //\n // Rollup/Rolldown interprets *any* `[token]` in the string returned by a\n // `chunkFileNames` function as a placeholder. Only a handful are valid —\n // `[name]`, `[hash]`, `[format]`, `[ext]` — so route-derived tokens like\n // `[productId]` or `[...]` trigger a build error:\n //\n // \"[productId]\" is not a valid placeholder in the \"output.chunkFileNames\" pattern.\n //\n // We wrap the original function to replace non-standard `[token]` patterns\n // with `_token_`, preserving the intended filename while avoiding the\n // placeholder validation error.\n //\n // Example: `_routes/products/[productId].mjs` → `_routes/products/_productId_.mjs`\n const VALID_ROLLUP_PLACEHOLDER = /^\\[(?:name|hash|format|ext)\\]$/;\n const chunkFileNames = (output as Record<string, unknown>)['chunkFileNames'];\n if (typeof chunkFileNames === 'function') {\n const originalFn = chunkFileNames as (...args: unknown[]) => unknown;\n (output as Record<string, unknown>)['chunkFileNames'] = (\n ...args: unknown[]\n ) => {\n const result = originalFn(...args);\n if (typeof result !== 'string') return result;\n return result.replace(/\\[[^\\]]+\\]/g, (match: string) =>\n VALID_ROLLUP_PLACEHOLDER.test(match)\n ? match\n : `_${match.slice(1, -1)}_`,\n );\n };\n }\n}\n\nfunction resolveClientOutputPath(\n cachedPath: string,\n workspaceRoot: string,\n rootDir: string,\n configuredOutDir: string | undefined,\n) {\n if (cachedPath) {\n debugLog('resolveClientOutputPath using cached path', () => ({\n cachedPath,\n workspaceRoot,\n rootDir,\n configuredOutDir,\n }));\n return cachedPath;\n }\n\n if (configuredOutDir) {\n const resolvedPath = normalizePath(\n resolve(workspaceRoot, rootDir, configuredOutDir),\n );\n debugLog('resolveClientOutputPath using configured build.outDir', () => ({\n workspaceRoot,\n rootDir,\n configuredOutDir,\n resolvedPath,\n }));\n return resolvedPath;\n }\n\n // When no explicit build.outDir is set, the environment build config defaults\n // to `<workspace>/dist/<root>/client` for the client build. The non-SSR\n // (client) and SSR paths must agree on this so that registerIndexHtmlVirtual()\n // and publicAssets read from the directory the client build actually wrote to.\n const resolvedPath = normalizePath(\n resolve(workspaceRoot, 'dist', rootDir, 'client'),\n );\n debugLog('resolveClientOutputPath using default dist client path', () => ({\n workspaceRoot,\n rootDir,\n configuredOutDir,\n resolvedPath,\n }));\n return resolvedPath;\n}\n\nfunction getEnvironmentBuildOutDir(environment: unknown): string | undefined {\n if (!environment || typeof environment !== 'object') {\n return undefined;\n }\n\n const environmentConfig = environment as {\n config?: {\n build?: {\n outDir?: string;\n };\n };\n build?: {\n outDir?: string;\n };\n };\n\n return (\n environmentConfig.config?.build?.outDir ?? environmentConfig.build?.outDir\n );\n}\n\nfunction resolveBuiltClientOutputPath(\n cachedPath: string,\n workspaceRoot: string,\n rootDir: string,\n configuredOutDir: string | undefined,\n environment?: unknown,\n) {\n const environmentOutDir = getEnvironmentBuildOutDir(environment);\n if (environmentOutDir) {\n const resolvedPath = normalizePath(\n resolve(workspaceRoot, rootDir, environmentOutDir),\n );\n debugLog('resolveBuiltClientOutputPath using environment outDir', () => ({\n cachedPath,\n workspaceRoot,\n rootDir,\n configuredOutDir,\n environmentOutDir,\n resolvedPath,\n }));\n return resolvedPath;\n }\n\n debugLog(\n 'resolveBuiltClientOutputPath falling back to shared resolver',\n () => ({\n cachedPath,\n workspaceRoot,\n rootDir,\n configuredOutDir,\n environmentOutDir,\n }),\n );\n return resolveClientOutputPath(\n cachedPath,\n workspaceRoot,\n rootDir,\n configuredOutDir,\n );\n}\n\nfunction getNitroPublicOutputDir(nitroConfig: NitroConfig): string {\n const publicDir = nitroConfig.output?.publicDir;\n if (!publicDir) {\n throw new Error(\n 'Nitro public output directory is required to build the sitemap.',\n );\n }\n\n return publicDir;\n}\n\nconst DEBUG_NAMESPACE = 'analog:vite-plugin-nitro';\n\nfunction escapeRegExp(value: string) {\n return value.replace(/[|\\\\{}()[\\]^$+?.*]/g, '\\\\$&');\n}\n\n// Keep DEBUG matching local to this package so CI can opt into verbose traces\n// with familiar patterns like `analog:*` without adding a runtime dependency.\nfunction isDebugEnabled(namespace: string) {\n const debugValue = process.env['DEBUG'];\n if (!debugValue) {\n return false;\n }\n\n return debugValue\n .split(/[\\s,]+/)\n .filter(Boolean)\n .some((pattern) => {\n const matcher = new RegExp(\n `^${escapeRegExp(pattern).replace(/\\\\\\*/g, '.*')}$`,\n );\n return matcher.test(namespace);\n });\n}\n\nfunction debugLog(\n label: string,\n details?: Record<string, unknown> | (() => Record<string, unknown>),\n) {\n if (!isDebugEnabled(DEBUG_NAMESPACE)) {\n return;\n }\n\n const resolvedDetails = typeof details === 'function' ? details() : details;\n if (resolvedDetails && Object.keys(resolvedDetails).length > 0) {\n console.log(`DEBUG: ${label}`, resolvedDetails);\n return;\n }\n\n console.log(`DEBUG: ${label}`);\n}\n\nfunction readDirectoryEntries(path: string): string[] {\n try {\n return readdirSync(path).sort();\n } catch (error) {\n return [\n `<<unable to read directory: ${error instanceof Error ? error.message : String(error)}>>`,\n ];\n }\n}\n\nfunction getPathDebugInfo(path: string) {\n return {\n rawPath: path,\n normalizedPath: normalizePath(path),\n exists: existsSync(path),\n entries: existsSync(path) ? readDirectoryEntries(path) : [],\n };\n}\n\nfunction assetSourceToString(source: string | Uint8Array) {\n return typeof source === 'string'\n ? source\n : Buffer.from(source).toString('utf8');\n}\n\nfunction captureClientIndexHtmlFromBundle(\n bundle: Record<\n string,\n {\n type?: string;\n fileName?: string;\n source?: string | Uint8Array;\n }\n >,\n hook: 'generateBundle' | 'writeBundle',\n) {\n const indexHtmlAsset = Object.values(bundle).find(\n (chunk) =>\n chunk.type === 'asset' &&\n chunk.fileName === 'index.html' &&\n typeof chunk.source !== 'undefined',\n );\n\n if (!indexHtmlAsset?.source) {\n debugLog(`client bundle did not expose index.html during ${hook}`, () => ({\n hook,\n bundleKeys: Object.keys(bundle).sort(),\n assetFileNames: Object.values(bundle)\n .filter((chunk) => chunk.type === 'asset')\n .map((chunk) => chunk.fileName)\n .filter(Boolean),\n }));\n return undefined;\n }\n\n const indexHtml = assetSourceToString(indexHtmlAsset.source);\n debugLog(`captured client bundle index.html asset during ${hook}`, () => ({\n hook,\n fileName: indexHtmlAsset.fileName,\n htmlLength: indexHtml.length,\n }));\n return indexHtml;\n}\n\n// Nitro only needs the HTML template string. Prefer the on-disk file when it\n// exists, but allow the captured client asset to cover build flows where the\n// client output directory disappears before Nitro assembles its virtual modules.\nfunction registerIndexHtmlVirtual(\n nitroConfig: NitroConfig,\n clientOutputPath: string,\n inlineIndexHtml?: string,\n) {\n const indexHtmlPath = resolve(clientOutputPath, 'index.html');\n debugLog('registerIndexHtmlVirtual inspecting client output', () => ({\n platform: process.platform,\n cwd: process.cwd(),\n clientOutputPath,\n clientOutputPathInfo: getPathDebugInfo(clientOutputPath),\n indexHtmlPath,\n indexHtmlExists: existsSync(indexHtmlPath),\n hasInlineIndexHtml: typeof inlineIndexHtml === 'string',\n }));\n if (!existsSync(indexHtmlPath) && typeof inlineIndexHtml !== 'string') {\n debugLog('registerIndexHtmlVirtual missing index.html', () => ({\n platform: process.platform,\n cwd: process.cwd(),\n clientOutputPath,\n clientOutputPathInfo: getPathDebugInfo(clientOutputPath),\n indexHtmlPath,\n hasInlineIndexHtml: typeof inlineIndexHtml === 'string',\n nitroOutput: nitroConfig.output,\n nitroPublicAssets: nitroConfig.publicAssets,\n }));\n throw new Error(\n `[analog] Client build output not found at ${indexHtmlPath}.\\n` +\n `Ensure the client environment build completed successfully before the server build.`,\n );\n }\n const indexHtml =\n typeof inlineIndexHtml === 'string'\n ? inlineIndexHtml\n : readFileSync(indexHtmlPath, 'utf8');\n debugLog('registerIndexHtmlVirtual using HTML template source', () => ({\n source:\n typeof inlineIndexHtml === 'string'\n ? 'captured client bundle asset'\n : 'client output index.html file',\n indexHtmlPath,\n }));\n nitroConfig.virtual = {\n ...nitroConfig.virtual,\n '#analog/index': `export default ${JSON.stringify(indexHtml)};`,\n };\n}\n\n/**\n * Converts the built SSR entry path into a specifier that Nitro's bundler\n * can resolve, including all relative `./assets/*` chunk imports inside\n * the entry.\n *\n * The returned path **must** be an absolute filesystem path with forward\n * slashes (e.g. `D:/a/analog/dist/apps/blog-app/ssr/main.server.js`).\n * This lets Rollup/Rolldown determine the entry's directory and resolve\n * sibling chunk imports like `./assets/core-DTazUigR.js` correctly.\n *\n * ## Why not pathToFileURL() on Windows?\n *\n * Earlier versions converted the path to a `file:///D:/a/...` URL on\n * Windows, which worked with Nitro v2 + Rollup. Nitro v3 switched its\n * default bundler to Rolldown, and Rolldown does **not** extract the\n * importer directory from `file://` URLs. This caused every relative\n * import inside the SSR entry to fail during the prerender build:\n *\n * [RESOLVE_ERROR] Could not resolve './assets/core-DTazUigR.js'\n * in ../../dist/apps/blog-app/ssr/main.server.js\n *\n * `normalizePath()` (from Vite) simply converts backslashes to forward\n * slashes, which both Rollup and Rolldown handle correctly on all\n * platforms.\n */\nfunction toNitroSsrEntrypointSpecifier(ssrEntryPath: string) {\n return normalizePath(ssrEntryPath);\n}\n\nfunction applySsrEntryAlias(\n nitroConfig: NitroConfig,\n options: Options | undefined,\n workspaceRoot: string,\n rootDir: string,\n): void {\n const ssrOutDir =\n options?.ssrBuildDir || resolve(workspaceRoot, 'dist', rootDir, 'ssr');\n if (options?.ssr || nitroConfig.prerender?.routes?.length) {\n const ssrEntryPath = resolveBuiltSsrEntryPath(ssrOutDir);\n const ssrEntry = toNitroSsrEntrypointSpecifier(ssrEntryPath);\n nitroConfig.alias = {\n ...nitroConfig.alias,\n '#analog/ssr': ssrEntry,\n };\n }\n}\n\nfunction resolveBuiltSsrEntryPath(ssrOutDir: string) {\n const candidatePaths = [\n resolve(ssrOutDir, 'main.server.mjs'),\n resolve(ssrOutDir, 'main.server.js'),\n resolve(ssrOutDir, 'main.server'),\n ];\n\n const ssrEntryPath = candidatePaths.find((candidatePath) =>\n existsSync(candidatePath),\n );\n\n if (!ssrEntryPath) {\n throw new Error(\n `Unable to locate the built SSR entry in \"${ssrOutDir}\". Expected one of: ${candidatePaths.join(\n ', ',\n )}`,\n );\n }\n\n return ssrEntryPath;\n}\n\nexport function nitro(options?: Options, nitroOptions?: NitroConfig): Plugin[] {\n const workspaceRoot = options?.workspaceRoot ?? process.cwd();\n const sourceRoot = options?.sourceRoot ?? 'src';\n let isTest = process.env['NODE_ENV'] === 'test' || !!process.env['VITEST'];\n const baseURL = process.env['NITRO_APP_BASE_URL'] || '';\n const prefix = baseURL ? baseURL.substring(0, baseURL.length - 1) : '';\n const apiPrefix = `/${options?.apiPrefix || 'api'}`;\n const useAPIMiddleware =\n typeof options?.useAPIMiddleware !== 'undefined'\n ? options?.useAPIMiddleware\n : true;\n const viteRolldownOutput = options?.vite?.build?.rolldownOptions?.output;\n // Vite's native build typing allows `output` to be either a single object or\n // an array. Analog only forwards `codeSplitting` into the client environment\n // when there is a single output object to merge into.\n const viteRolldownOutputConfig =\n viteRolldownOutput && !Array.isArray(viteRolldownOutput)\n ? viteRolldownOutput\n : undefined;\n const codeSplitting = viteRolldownOutputConfig?.codeSplitting;\n\n let isBuild = false;\n let isServe = false;\n let ssrBuild = false;\n let config: UserConfig;\n let nitroConfig: NitroConfig;\n let environmentBuild = false;\n let hasAPIDir = false;\n let clientOutputPath = '';\n let clientIndexHtml: string | undefined;\n let legacyClientSubBuild = false;\n const rollupExternalEntries: string[] = [];\n const sitemapRoutes: string[] = [];\n const routeSitemaps: Record<\n string,\n PrerenderSitemapConfig | (() => PrerenderSitemapConfig)\n > = {};\n const routeSourceFiles: Record<string, string> = {};\n let rootDir = workspaceRoot;\n\n return [\n (options?.ssr\n ? devServerPlugin({\n entryServer: options?.entryServer,\n index: options?.index,\n routeRules: nitroOptions?.routeRules,\n })\n : false) as Plugin,\n {\n name: '@analogjs/vite-plugin-nitro',\n async config(userConfig, { mode, command }) {\n isServe = command === 'serve';\n isBuild = command === 'build';\n ssrBuild = userConfig.build?.ssr === true;\n config = userConfig;\n isTest = isTest ? isTest : mode === 'test';\n rollupExternalEntries.length = 0;\n clientIndexHtml = undefined;\n sitemapRoutes.length = 0;\n for (const key of Object.keys(routeSitemaps)) {\n delete routeSitemaps[key];\n }\n for (const key of Object.keys(routeSourceFiles)) {\n delete routeSourceFiles[key];\n }\n\n const resolvedConfigRoot = config.root\n ? resolve(workspaceRoot, config.root)\n : workspaceRoot;\n rootDir = relative(workspaceRoot, resolvedConfigRoot) || '.';\n hasAPIDir = existsSync(\n resolve(\n workspaceRoot,\n rootDir,\n `${sourceRoot}/server/routes/${options?.apiPrefix || 'api'}`,\n ),\n );\n const buildPreset =\n process.env['BUILD_PRESET'] ??\n (nitroOptions?.preset as string | undefined) ??\n (process.env['VERCEL'] ? 'vercel' : undefined);\n\n const pageHandlers = getPageHandlers({\n workspaceRoot,\n sourceRoot,\n rootDir,\n additionalPagesDirs: options?.additionalPagesDirs,\n hasAPIDir,\n });\n const resolvedClientOutputPath = resolveClientOutputPath(\n clientOutputPath,\n workspaceRoot,\n rootDir,\n config.build?.outDir,\n );\n debugLog('nitro config resolved client output path', () => ({\n platform: process.platform,\n workspaceRoot,\n configRoot: config.root,\n resolvedConfigRoot,\n rootDir,\n buildOutDir: config.build?.outDir,\n clientOutputPath,\n resolvedClientOutputPath,\n hasEnvironmentConfig: !!config.environments,\n clientEnvironmentOutDir:\n config.environments?.['client'] &&\n typeof config.environments['client'] === 'object' &&\n 'build' in config.environments['client']\n ? (\n config.environments['client'] as {\n build?: { outDir?: string };\n }\n ).build?.outDir\n : undefined,\n }));\n\n nitroConfig = {\n rootDir: normalizePath(rootDir),\n preset: buildPreset,\n compatibilityDate: '2025-11-19',\n logLevel: nitroOptions?.logLevel || 0,\n serverDir: normalizePath(`${sourceRoot}/server`),\n scanDirs: [\n normalizePath(`${rootDir}/${sourceRoot}/server`),\n ...(options?.additionalAPIDirs || []).map((dir) =>\n normalizePath(`${workspaceRoot}${dir}`),\n ),\n ],\n output: {\n dir: normalizePath(\n resolve(workspaceRoot, 'dist', rootDir, 'analog'),\n ),\n publicDir: normalizePath(\n resolve(workspaceRoot, 'dist', rootDir, 'analog/public'),\n ),\n },\n buildDir: normalizePath(\n resolve(workspaceRoot, 'dist', rootDir, '.nitro'),\n ),\n typescript: {\n generateTsConfig: false,\n },\n runtimeConfig: {\n apiPrefix: apiPrefix.substring(1),\n prefix,\n },\n // Analog provides its own renderer handler; prevent Nitro v3 from\n // auto-detecting index.html in rootDir and adding a conflicting one.\n renderer: false,\n imports: {\n autoImport: false,\n },\n hooks: {\n 'rollup:before': createRollupBeforeHook(rollupExternalEntries),\n },\n rollupConfig: {\n onwarn(warning) {\n if (\n warning.message.includes('empty chunk') &&\n warning.message.endsWith('.server')\n ) {\n return;\n }\n },\n plugins: [pageEndpointsPlugin()],\n },\n handlers: [\n ...(hasAPIDir\n ? []\n : useAPIMiddleware\n ? [createNitroMiddlewareHandler('#ANALOG_API_MIDDLEWARE')]\n : []),\n ...pageHandlers,\n ],\n routeRules: hasAPIDir\n ? undefined\n : useAPIMiddleware\n ? undefined\n : {\n [`${prefix}${apiPrefix}/**`]: {\n proxy: { to: '/**' },\n },\n },\n virtual: {\n '#ANALOG_SSR_RENDERER': ssrRenderer(),\n '#ANALOG_CLIENT_RENDERER': clientRenderer(),\n ...(hasAPIDir ? {} : { '#ANALOG_API_MIDDLEWARE': apiMiddleware }),\n },\n };\n\n if (isVercelPreset(buildPreset)) {\n nitroConfig = withVercelOutputAPI(nitroConfig, workspaceRoot);\n }\n\n if (isCloudflarePreset(buildPreset)) {\n nitroConfig = withCloudflareOutput(nitroConfig);\n }\n\n if (\n isNetlifyPreset(buildPreset) &&\n rootDir === '.' &&\n !existsSync(resolve(workspaceRoot, 'netlify.toml'))\n ) {\n nitroConfig = withNetlifyOutputAPI(nitroConfig, workspaceRoot);\n }\n\n if (isFirebaseAppHosting()) {\n nitroConfig = withAppHostingOutput(nitroConfig);\n }\n\n if (!ssrBuild && !isTest) {\n // store the client output path for the SSR build config\n clientOutputPath = resolvedClientOutputPath;\n debugLog(\n 'nitro config cached client output path for later SSR/Nitro build',\n () => ({\n ssrBuild,\n isTest,\n clientOutputPath,\n }),\n );\n }\n\n // Start with a clean alias map. #analog/index is registered as a Nitro\n // virtual module after the client build, inlining the HTML template so\n // the server bundle imports it instead of using readFileSync with an\n // absolute path.\n nitroConfig.alias = {};\n\n if (isBuild) {\n nitroConfig.publicAssets = [\n { dir: normalizePath(resolvedClientOutputPath), maxAge: 0 },\n ];\n\n // In Nitro v3, renderer.entry is resolved via resolveModulePath()\n // during options normalization, which requires a real filesystem path.\n // Virtual modules (prefixed with #) can't survive this resolution.\n // Instead, we add the renderer as a catch-all handler directly —\n // this is functionally equivalent to what Nitro does internally\n // (it converts renderer.entry into a { route: '/**', lazy: true }\n // handler), but avoids the filesystem resolution step.\n const rendererHandler = options?.ssr\n ? '#ANALOG_SSR_RENDERER'\n : '#ANALOG_CLIENT_RENDERER';\n nitroConfig.handlers = [\n ...(nitroConfig.handlers || []),\n {\n handler: rendererHandler,\n route: '/**',\n lazy: true,\n },\n ];\n\n if (isEmptyPrerenderRoutes(options)) {\n nitroConfig.prerender = {};\n nitroConfig.prerender.routes = ['/'];\n }\n\n if (options?.prerender) {\n nitroConfig.prerender = nitroConfig.prerender ?? {};\n nitroConfig.prerender.crawlLinks = options?.prerender?.discover;\n\n let routes: (\n | string\n | PrerenderContentDir\n | PrerenderRouteConfig\n | undefined\n )[] = [];\n\n const prerenderRoutes = options?.prerender?.routes;\n const hasExplicitPrerenderRoutes =\n typeof prerenderRoutes === 'function' ||\n Array.isArray(prerenderRoutes);\n if (\n isArrayWithElements<string | PrerenderContentDir>(prerenderRoutes)\n ) {\n routes = prerenderRoutes;\n } else if (typeof prerenderRoutes === 'function') {\n routes = await prerenderRoutes();\n }\n\n const resolvedPrerenderRoutes = routes.reduce<string[]>(\n (prev, current) => {\n if (!current) {\n return prev;\n }\n if (typeof current === 'string') {\n prev.push(current);\n sitemapRoutes.push(current);\n return prev;\n }\n\n if ('route' in current) {\n if (current.sitemap) {\n routeSitemaps[current.route] = current.sitemap;\n }\n\n if (current.outputSourceFile) {\n const sourcePath = resolve(\n workspaceRoot,\n rootDir,\n current.outputSourceFile,\n );\n routeSourceFiles[current.route] = readFileSync(\n sourcePath,\n 'utf8',\n );\n }\n\n prev.push(current.route);\n sitemapRoutes.push(current.route);\n\n // Add the server-side data fetching endpoint URL\n if ('staticData' in current) {\n prev.push(`${apiPrefix}/_analog/pages/${current.route}`);\n }\n\n return prev;\n }\n\n const affectedFiles: PrerenderContentFile[] =\n getMatchingContentFilesWithFrontMatter(\n workspaceRoot,\n rootDir,\n current.contentDir,\n );\n\n affectedFiles.forEach((f) => {\n const result = current.transform(f);\n\n if (result) {\n if (current.sitemap) {\n routeSitemaps[result] =\n current.sitemap && typeof current.sitemap === 'function'\n ? current.sitemap?.(f)\n : current.sitemap;\n }\n\n if (current.outputSourceFile) {\n const sourceContent = current.outputSourceFile(f);\n if (sourceContent) {\n routeSourceFiles[result] = sourceContent;\n }\n }\n\n prev.push(result);\n sitemapRoutes.push(result);\n\n // Add the server-side data fetching endpoint URL\n if ('staticData' in current) {\n prev.push(`${apiPrefix}/_analog/pages/${result}`);\n }\n }\n });\n\n return prev;\n },\n [],\n );\n\n nitroConfig.prerender.routes =\n hasExplicitPrerenderRoutes || resolvedPrerenderRoutes.length\n ? resolvedPrerenderRoutes\n : (nitroConfig.prerender.routes ?? []);\n }\n\n // ── SSR / prerender Nitro config ─────────────────────────────\n //\n // This block configures Nitro for builds that rebundle the SSR\n // entry (main.server.{js,mjs}). That happens in two cases:\n //\n // 1. Full SSR apps — `options.ssr === true`\n // 2. Prerender-only — no runtime SSR, but the prerender build\n // still imports the SSR entry to render static pages.\n //\n // The original gate was `if (ssrBuild)`, which checks the Vite\n // top-level `build.ssr` flag. That works for SSR-only builds but\n // misses two Vite 6+ paths:\n //\n // a. **Vite Environment API (Vite 6+)** — SSR config lives in\n // `environments.ssr.build.ssr`, not `build.ssr`, so\n // `ssrBuild` is always `false`.\n // b. **Prerender-only apps** (e.g. blog-app) — `options.ssr`\n // is `false`, but prerender routes exist and the prerender\n // build still processes the SSR entry.\n //\n // Without this block:\n // - `rxjs` is never externalised → RESOLVE_ERROR in the\n // Nitro prerender build (especially on Windows CI).\n // - `moduleSideEffects` for zone.js is never set → zone.js\n // side-effects may be tree-shaken.\n // - The handlers list is not reassembled with page endpoints\n // + the renderer catch-all.\n //\n // The widened condition covers all supported build paths:\n // - `ssrBuild` → SSR-only build\n // - `options?.ssr` → Environment API SSR\n // - `nitroConfig.prerender?.routes?.length` → prerender-only\n if (\n ssrBuild ||\n options?.ssr ||\n nitroConfig.prerender?.routes?.length\n ) {\n if (process.platform === 'win32') {\n nitroConfig.noExternals = appendNoExternals(\n nitroConfig.noExternals,\n 'std-env',\n );\n }\n\n rollupExternalEntries.push(\n 'rxjs',\n 'node-fetch-native/dist/polyfill',\n );\n\n nitroConfig = {\n ...nitroConfig,\n moduleSideEffects: ['zone.js/node', 'zone.js/fesm2015/zone-node'],\n handlers: [\n ...(hasAPIDir\n ? []\n : useAPIMiddleware\n ? [createNitroMiddlewareHandler('#ANALOG_API_MIDDLEWARE')]\n : []),\n ...pageHandlers,\n // Preserve the renderer catch-all handler added above\n {\n handler: rendererHandler,\n route: '/**',\n lazy: true,\n },\n ],\n };\n }\n }\n\n nitroConfig = mergeConfig(\n nitroConfig,\n nitroOptions as Record<string, any>,\n );\n\n return {\n environments: {\n client: {\n build: {\n outDir:\n config?.build?.outDir ||\n resolve(workspaceRoot, 'dist', rootDir, 'client'),\n emptyOutDir: true,\n // Forward code-splitting config to Rolldown when running\n // under Vite 8+. `false` disables splitting (inlines all\n // dynamic imports); an object configures chunk groups.\n // The `!== undefined` check ensures `codeSplitting: false`\n // is forwarded correctly (a truthy check would swallow it).\n ...(isRolldown() && codeSplitting !== undefined\n ? {\n rolldownOptions: {\n output: {\n // Preserve any sibling Rolldown output options while\n // overriding just `codeSplitting` for the client build.\n ...viteRolldownOutputConfig,\n codeSplitting,\n },\n },\n }\n : {}),\n },\n },\n ssr: {\n build: {\n ssr: true,\n [getBundleOptionsKey()]: {\n input:\n options?.entryServer ||\n resolve(\n workspaceRoot,\n rootDir,\n `${sourceRoot}/main.server.ts`,\n ),\n },\n outDir:\n options?.ssrBuildDir ||\n resolve(workspaceRoot, 'dist', rootDir, 'ssr'),\n // Preserve the client build output. The client environment is\n // built first and Nitro reads its index.html after SSR finishes.\n emptyOutDir: false,\n },\n },\n },\n builder: {\n sharedPlugins: true,\n buildApp: async (builder) => {\n environmentBuild = true;\n debugLog('builder.buildApp starting', () => ({\n platform: process.platform,\n workspaceRoot,\n rootDir,\n cachedClientOutputPath: clientOutputPath,\n configuredBuildOutDir: config.build?.outDir,\n clientEnvironmentOutDir: getEnvironmentBuildOutDir(\n builder.environments['client'],\n ),\n ssrEnvironmentOutDir: getEnvironmentBuildOutDir(\n builder.environments['ssr'],\n ),\n }));\n\n // Client must complete before SSR — the server build reads the\n // client's index.html via registerIndexHtmlVirtual(). Running\n // them in parallel caused a race on Windows where emptyOutDir\n // could delete client output before the server read it.\n await builder.build(builder.environments['client']);\n const postClientBuildOutputPath = resolveBuiltClientOutputPath(\n clientOutputPath,\n workspaceRoot,\n rootDir,\n config.build?.outDir,\n builder.environments['client'],\n );\n // Capture the client template before any SSR/prerender work runs.\n // On Windows, later phases can leave the client output directory\n // unavailable even though the client build itself succeeded.\n registerIndexHtmlVirtual(\n nitroConfig,\n postClientBuildOutputPath,\n clientIndexHtml,\n );\n debugLog('builder.buildApp completed client build', () => ({\n postClientBuildOutputPath,\n postClientBuildOutputInfo: getPathDebugInfo(\n postClientBuildOutputPath,\n ),\n postClientBuildIndexHtmlPath: resolve(\n postClientBuildOutputPath,\n 'index.html',\n ),\n postClientBuildIndexHtmlExists: existsSync(\n resolve(postClientBuildOutputPath, 'index.html'),\n ),\n }));\n\n if (options?.ssr || nitroConfig.prerender?.routes?.length) {\n debugLog('builder.buildApp starting SSR build', () => ({\n ssrEnabled: options?.ssr,\n prerenderRoutes: nitroConfig.prerender?.routes,\n }));\n await builder.build(builder.environments['ssr']);\n debugLog('builder.buildApp completed SSR build', () => ({\n ssrOutputPath:\n options?.ssrBuildDir ||\n resolve(workspaceRoot, 'dist', rootDir, 'ssr'),\n }));\n }\n\n applySsrEntryAlias(nitroConfig, options, workspaceRoot, rootDir);\n\n const resolvedClientOutputPath = resolveBuiltClientOutputPath(\n clientOutputPath,\n workspaceRoot,\n rootDir,\n config.build?.outDir,\n builder.environments['client'],\n );\n\n nitroConfig.publicAssets = [\n { dir: normalizePath(resolvedClientOutputPath), maxAge: 0 },\n ];\n debugLog(\n 'builder.buildApp resolved final client output path before Nitro build',\n () => ({\n resolvedClientOutputPath,\n resolvedClientOutputInfo: getPathDebugInfo(\n resolvedClientOutputPath,\n ),\n nitroPublicAssets: nitroConfig.publicAssets,\n }),\n );\n\n await buildServer(options, nitroConfig, routeSourceFiles);\n\n if (\n nitroConfig.prerender?.routes?.length &&\n options?.prerender?.sitemap\n ) {\n console.log('Building Sitemap...');\n // sitemap needs to be built after all directories are built\n await buildSitemap(\n config,\n options.prerender.sitemap,\n sitemapRoutes.length\n ? sitemapRoutes\n : nitroConfig.prerender.routes,\n getNitroPublicOutputDir(nitroConfig),\n routeSitemaps,\n { apiPrefix: options?.apiPrefix || 'api' },\n );\n }\n\n console.log(\n `\\n\\nThe '@analogjs/platform' server has been successfully built.`,\n );\n },\n },\n };\n },\n generateBundle(\n _options,\n bundle: Record<\n string,\n {\n type?: string;\n fileName?: string;\n source?: string | Uint8Array;\n }\n >,\n ) {\n if (!isBuild || ssrBuild) {\n return;\n }\n\n clientIndexHtml =\n captureClientIndexHtmlFromBundle(bundle, 'generateBundle') ??\n clientIndexHtml;\n },\n writeBundle(\n _options,\n bundle: Record<\n string,\n {\n type?: string;\n fileName?: string;\n source?: string | Uint8Array;\n }\n >,\n ) {\n if (!isBuild || ssrBuild) {\n return;\n }\n\n clientIndexHtml =\n captureClientIndexHtmlFromBundle(bundle, 'writeBundle') ??\n clientIndexHtml;\n },\n async configureServer(viteServer: ViteDevServer) {\n if (isServe && !isTest) {\n const nitro = await createNitro({\n dev: true,\n // Nitro's Vite builder now rejects `build()` in dev mode, but Analog's\n // dev integration still relies on the builder-driven reload hooks.\n // Force the server worker onto Rollup for this dev-only path.\n builder: 'rollup',\n ...nitroConfig,\n });\n const server = createDevServer(nitro);\n await build(nitro);\n const nitroSourceRoots = [\n normalizePath(\n resolve(workspaceRoot, rootDir, `${sourceRoot}/server`),\n ),\n ...(options?.additionalAPIDirs || []).map((dir) =>\n normalizePath(`${workspaceRoot}${dir}`),\n ),\n ];\n const isNitroSourceFile = (path: string) => {\n const normalizedPath = normalizePath(path);\n return nitroSourceRoots.some(\n (root) =>\n normalizedPath === root ||\n normalizedPath.startsWith(`${root}/`),\n );\n };\n let nitroRebuildPromise: Promise<void> | undefined;\n let nitroRebuildPending = false;\n const rebuildNitroServer = () => {\n if (nitroRebuildPromise) {\n // Coalesce rapid file events so a save that touches multiple server\n // route files results in one follow-up rebuild instead of many.\n nitroRebuildPending = true;\n return nitroRebuildPromise;\n }\n\n nitroRebuildPromise = (async () => {\n do {\n nitroRebuildPending = false;\n // Nitro API routes are not part of Vite's normal client HMR graph,\n // so rebuild the Nitro dev server to pick up handler edits.\n await build(nitro);\n } while (nitroRebuildPending);\n\n // Reload the page after the server rebuild completes so the next\n // request observes the updated API route implementation.\n viteServer.ws.send({ type: 'full-reload' });\n })()\n .catch((error: unknown) => {\n viteServer.config.logger.error(\n `[analog] Failed to rebuild Nitro dev server.\\n${error instanceof Error ? error.stack || error.message : String(error)}`,\n );\n })\n .finally(() => {\n nitroRebuildPromise = undefined;\n });\n\n return nitroRebuildPromise;\n };\n const onNitroSourceChange = (path: string) => {\n if (!isNitroSourceFile(path)) {\n return;\n }\n\n void rebuildNitroServer();\n };\n\n // Watch the full Nitro source roots instead of only the API route\n // directory. API handlers often read helper modules, shared data, or\n // middleware from elsewhere under `src/server`, and those edits should\n // still rebuild the Nitro dev server and refresh connected browsers.\n viteServer.watcher.on('add', onNitroSourceChange);\n viteServer.watcher.on('change', onNitroSourceChange);\n viteServer.watcher.on('unlink', onNitroSourceChange);\n\n const apiHandler = async (\n req: IncomingMessage,\n res: ServerResponse,\n ) => {\n // Nitro v3's dev server is fetch-first, so adapt Vite's Node\n // request once and let Nitro respond with a standard Web Response.\n const response = await server.fetch(toWebRequest(req));\n await writeWebResponseToNode(res, response);\n };\n\n if (hasAPIDir) {\n viteServer.middlewares.use(\n (\n req: IncomingMessage,\n res: ServerResponse,\n next: (error?: unknown) => void,\n ) => {\n if (req.url?.startsWith(`${prefix}${apiPrefix}`)) {\n void apiHandler(req, res).catch((error) => next(error));\n return;\n }\n\n next();\n },\n );\n } else {\n viteServer.middlewares.use(\n apiPrefix,\n (\n req: IncomingMessage,\n res: ServerResponse,\n next: (error?: unknown) => void,\n ) => {\n void apiHandler(req, res).catch((error) => next(error));\n },\n );\n }\n\n viteServer.httpServer?.once('listening', () => {\n process.env['ANALOG_HOST'] = !viteServer.config.server.host\n ? 'localhost'\n : (viteServer.config.server.host as string);\n process.env['ANALOG_PORT'] = `${viteServer.config.server.port}`;\n });\n\n // handle upgrades if websockets are enabled\n if (nitroOptions?.experimental?.websocket) {\n viteServer.httpServer?.on('upgrade', server.upgrade);\n }\n\n console.log(\n `\\n\\nThe server endpoints are accessible under the \"${prefix}${apiPrefix}\" path.`,\n );\n }\n },\n\n async closeBundle() {\n if (legacyClientSubBuild) {\n return;\n }\n\n // When builder.buildApp ran, it already handled the full\n // client → SSR → Nitro pipeline. Skip to avoid double work.\n if (environmentBuild) {\n return;\n }\n\n // SSR sub-build — Vite re-enters the plugin with build.ssr;\n // Nitro server assembly happens only after the client pass.\n if (ssrBuild) {\n return;\n }\n\n // Nx executors (and any caller that runs `vite build` without\n // the Environment API) never trigger builder.buildApp, so\n // closeBundle is the only place to drive the SSR + Nitro build.\n if (isBuild) {\n const resolvedClientOutputPath = resolveClientOutputPath(\n clientOutputPath,\n workspaceRoot,\n rootDir,\n config.build?.outDir,\n );\n debugLog(\n 'closeBundle resolved client output path before legacy SSR build',\n () => ({\n platform: process.platform,\n workspaceRoot,\n rootDir,\n cachedClientOutputPath: clientOutputPath,\n configuredBuildOutDir: config.build?.outDir,\n resolvedClientOutputPath,\n resolvedClientOutputInfo: getPathDebugInfo(\n resolvedClientOutputPath,\n ),\n }),\n );\n const indexHtmlPath = resolve(resolvedClientOutputPath, 'index.html');\n if (\n !existsSync(indexHtmlPath) &&\n typeof clientIndexHtml !== 'string'\n ) {\n debugLog(\n 'closeBundle rebuilding missing client output before SSR/Nitro',\n () => ({\n platform: process.platform,\n workspaceRoot,\n rootDir,\n configuredBuildOutDir: config.build?.outDir,\n resolvedClientOutputPath,\n indexHtmlPath,\n }),\n );\n legacyClientSubBuild = true;\n try {\n await buildClientApp(config, options);\n } finally {\n legacyClientSubBuild = false;\n }\n }\n // Capture the client HTML before kicking off the standalone SSR build.\n // This mirrors the successful sequencing from before the closeBundle\n // refactor and avoids depending on the client directory surviving the\n // nested SSR build on Windows.\n registerIndexHtmlVirtual(\n nitroConfig,\n resolvedClientOutputPath,\n clientIndexHtml,\n );\n\n if (options?.ssr) {\n console.log('Building SSR application...');\n await buildSSRApp(config, options);\n debugLog('closeBundle completed standalone SSR build', () => ({\n ssrBuildDir:\n options?.ssrBuildDir ||\n resolve(workspaceRoot, 'dist', rootDir, 'ssr'),\n clientOutputPathInfo: clientOutputPath\n ? getPathDebugInfo(clientOutputPath)\n : null,\n }));\n }\n\n applySsrEntryAlias(nitroConfig, options, workspaceRoot, rootDir);\n debugLog(\n 'closeBundle resolved client output path before Nitro build',\n () => ({\n platform: process.platform,\n workspaceRoot,\n rootDir,\n cachedClientOutputPath: clientOutputPath,\n configuredBuildOutDir: config.build?.outDir,\n resolvedClientOutputPath,\n resolvedClientOutputInfo: getPathDebugInfo(\n resolvedClientOutputPath,\n ),\n }),\n );\n registerIndexHtmlVirtual(\n nitroConfig,\n resolvedClientOutputPath,\n clientIndexHtml,\n );\n\n await buildServer(options, nitroConfig, routeSourceFiles);\n\n if (\n nitroConfig.prerender?.routes?.length &&\n options?.prerender?.sitemap\n ) {\n console.log('Building Sitemap...');\n await buildSitemap(\n config,\n options.prerender.sitemap,\n sitemapRoutes.length\n ? sitemapRoutes\n : nitroConfig.prerender.routes,\n getNitroPublicOutputDir(nitroConfig),\n routeSitemaps,\n { apiPrefix: options?.apiPrefix || 'api' },\n );\n }\n\n console.log(\n `\\n\\nThe '@analogjs/platform' server has been successfully built.`,\n );\n }\n },\n },\n {\n name: '@analogjs/vite-plugin-nitro-api-prefix',\n config() {\n return {\n define: {\n ANALOG_API_PREFIX: `\"${baseURL.substring(1)}${apiPrefix.substring(1)}\"`,\n },\n };\n },\n },\n ];\n}\n\nfunction isEmptyPrerenderRoutes(options?: Options): boolean {\n if (!options || isArrayWithElements(options?.prerender?.routes)) {\n return false;\n }\n return !options.prerender?.routes;\n}\n\nfunction isArrayWithElements<T>(arr: unknown): arr is [T, ...T[]] {\n return !!(Array.isArray(arr) && arr.length);\n}\n\nconst VERCEL_PRESET = 'vercel';\n// Nitro v3 consolidates the old `vercel-edge` preset into `vercel` with\n// fluid compute enabled by default, so a single preset covers both\n// serverless and edge deployments.\nconst withVercelOutputAPI = (\n nitroConfig: NitroConfig | undefined,\n workspaceRoot: string,\n) => ({\n ...nitroConfig,\n preset: nitroConfig?.preset ?? 'vercel',\n vercel: {\n ...nitroConfig?.vercel,\n entryFormat: nitroConfig?.vercel?.entryFormat ?? 'node',\n functions: {\n runtime: nitroConfig?.vercel?.functions?.runtime ?? 'nodejs24.x',\n ...nitroConfig?.vercel?.functions,\n },\n },\n output: {\n ...nitroConfig?.output,\n dir: normalizePath(resolve(workspaceRoot, '.vercel', 'output')),\n publicDir: normalizePath(\n resolve(workspaceRoot, '.vercel', 'output/static'),\n ),\n },\n});\n\n// Nitro v3 uses underscore-separated preset names (e.g. `cloudflare_pages`),\n// but we accept both hyphen and underscore forms for backwards compatibility.\nconst isCloudflarePreset = (buildPreset: string | undefined) =>\n process.env['CF_PAGES'] ||\n (buildPreset &&\n (buildPreset.toLowerCase().includes('cloudflare-pages') ||\n buildPreset.toLowerCase().includes('cloudflare_pages')));\n\nconst withCloudflareOutput = (nitroConfig: NitroConfig | undefined) => ({\n ...nitroConfig,\n output: {\n ...nitroConfig?.output,\n serverDir: '{{ output.publicDir }}/_worker.js',\n },\n});\n\nconst isFirebaseAppHosting = () => !!process.env['NG_BUILD_LOGS_JSON'];\nconst withAppHostingOutput = (nitroConfig: NitroConfig) => {\n let hasOutput = false;\n\n return <NitroConfig>{\n ...nitroConfig,\n serveStatic: true,\n rollupConfig: {\n ...nitroConfig.rollupConfig,\n output: {\n ...nitroConfig.rollupConfig?.output,\n entryFileNames: 'server.mjs',\n },\n },\n hooks: {\n ...nitroConfig.hooks,\n compiled: () => {\n if (!hasOutput) {\n const buildOutput = {\n errors: [],\n warnings: [],\n outputPaths: {\n root: pathToFileURL(`${nitroConfig.output?.dir}`),\n browser: pathToFileURL(`${nitroConfig.output?.publicDir}`),\n server: pathToFileURL(`${nitroConfig.output?.dir}/server`),\n },\n };\n\n // Log the build output for Firebase App Hosting to pick up\n console.log(JSON.stringify(buildOutput, null, 2));\n hasOutput = true;\n }\n },\n },\n };\n};\n\nconst isNetlifyPreset = (buildPreset: string | undefined) =>\n process.env['NETLIFY'] ||\n (buildPreset && buildPreset.toLowerCase().includes('netlify'));\n\nconst withNetlifyOutputAPI = (\n nitroConfig: NitroConfig | undefined,\n workspaceRoot: string,\n) => ({\n ...nitroConfig,\n output: {\n ...nitroConfig?.output,\n dir: normalizePath(resolve(workspaceRoot, 'netlify/functions')),\n },\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vite-plugin-nitro.js","names":[],"sources":["../../../src/lib/vite-plugin-nitro.ts"],"sourcesContent":["import type { NitroConfig, NitroEventHandler, RollupConfig } from 'nitro/types';\nimport { build, createDevServer, createNitro } from 'nitro/builder';\nimport * as vite from 'vite';\nimport type { Plugin, UserConfig, ViteDevServer } from 'vite';\nimport { mergeConfig, normalizePath } from 'vite';\nimport { relative, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { existsSync, readFileSync, readdirSync } from 'node:fs';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\nimport { buildServer, isVercelPreset } from './build-server.js';\nimport { buildClientApp, buildSSRApp } from './build-ssr.js';\nimport {\n Options,\n PrerenderContentDir,\n PrerenderContentFile,\n PrerenderRouteConfig,\n PrerenderSitemapConfig,\n} from './options.js';\nimport { pageEndpointsPlugin } from './plugins/page-endpoints.js';\nimport { getPageHandlers } from './utils/get-page-handlers.js';\nimport { buildSitemap } from './build-sitemap.js';\nimport { devServerPlugin } from './plugins/dev-server-plugin.js';\nimport {\n toWebRequest,\n writeWebResponseToNode,\n} from './utils/node-web-bridge.js';\nimport { getMatchingContentFilesWithFrontMatter } from './utils/get-content-files.js';\nimport {\n ssrRenderer,\n clientRenderer,\n apiMiddleware,\n} from './utils/renderers.js';\nimport { getBundleOptionsKey, isRolldown } from './utils/rolldown.js';\n\nfunction createNitroMiddlewareHandler(handler: string): NitroEventHandler {\n return {\n route: '/**',\n handler,\n middleware: true,\n };\n}\n\n/**\n * Creates a `rollup:before` hook that marks specified packages as external\n * in Nitro's bundler config (applied to both the server build and the\n * prerender build).\n *\n * ## Subpath matching (Rolldown compatibility)\n *\n * When `bundlerConfig.external` is an **array**, Rollup automatically\n * prefix-matches entries — `'rxjs'` in the array will also externalise\n * `'rxjs/operators'`, `'rxjs/internal/Observable'`, etc.\n *\n * Rolldown (the default bundler in Nitro v3) does **not** do this. It\n * treats array entries as exact strings. To keep behaviour consistent\n * across both bundlers, the **function** branch already needed explicit\n * subpath matching. We now use the same `isExternal` helper for all\n * branches so that `'rxjs'` reliably matches `'rxjs/operators'`\n * regardless of whether the existing `external` value is a function,\n * array, or absent.\n *\n * Without this, the Nitro prerender build fails on Windows CI with:\n *\n * [RESOLVE_ERROR] Could not resolve 'rxjs/operators'\n */\nfunction createRollupBeforeHook(externalEntries: string[]) {\n const isExternal = (source: string) =>\n externalEntries.some(\n (entry) => source === entry || source.startsWith(entry + '/'),\n );\n\n return (_nitro: unknown, bundlerConfig: RollupConfig) => {\n sanitizeNitroBundlerConfig(_nitro, bundlerConfig);\n\n if (externalEntries.length === 0) {\n return;\n }\n\n const existing = bundlerConfig.external;\n if (!existing) {\n bundlerConfig.external = externalEntries;\n } else if (typeof existing === 'function') {\n bundlerConfig.external = (\n source: string,\n importer: string | undefined,\n isResolved: boolean,\n ) => existing(source, importer, isResolved) || isExternal(source);\n } else if (Array.isArray(existing)) {\n bundlerConfig.external = [...existing, ...externalEntries];\n } else {\n bundlerConfig.external = [existing as string, ...externalEntries];\n }\n };\n}\n\nfunction appendNoExternals(\n noExternals: NitroConfig['noExternals'],\n ...entries: string[]\n): NitroConfig['noExternals'] {\n if (!noExternals) {\n return entries;\n }\n\n return Array.isArray(noExternals)\n ? [...noExternals, ...entries]\n : noExternals;\n}\n\n/**\n * Patches Nitro's internal Rollup/Rolldown bundler config to work around\n * incompatibilities in the Nitro v3 alpha series.\n *\n * Called from the `rollup:before` hook, this function runs against the *final*\n * bundler config that Nitro assembles for its server/prerender builds — it\n * does NOT touch the normal Vite client or SSR environment configs.\n *\n * Each workaround is narrowly scoped and safe to remove once the corresponding\n * upstream Nitro issue is resolved.\n */\nfunction sanitizeNitroBundlerConfig(\n _nitro: unknown,\n bundlerConfig: RollupConfig,\n) {\n const output = bundlerConfig['output'];\n if (!output || Array.isArray(output) || typeof output !== 'object') {\n return;\n }\n\n // ── 1. Remove invalid `output.codeSplitting` ────────────────────────\n //\n // Nitro 3.0.1-alpha.2 adds `output.codeSplitting` to its internal bundler\n // config, but Rolldown rejects it as an unknown key:\n //\n // Warning: Invalid output options (1 issue found)\n // - For the \"codeSplitting\". Invalid key: Expected never but received \"codeSplitting\".\n //\n // Analog never sets this option. Removing it restores default bundler\n // behavior without changing any Analog semantics.\n if ('codeSplitting' in output) {\n delete (output as Record<string, unknown>)['codeSplitting'];\n }\n\n // ── 2. Remove invalid `output.manualChunks` ─────────────────────────\n //\n // Nitro's default config enables manual chunking for node_modules. Under\n // Nitro v3 alpha + Rollup 4.59 this crashes during the prerender rebundle:\n //\n // Cannot read properties of undefined (reading 'included')\n //\n // A single server bundle is acceptable for Analog's use case, so we strip\n // `manualChunks` until the upstream bug is fixed.\n if ('manualChunks' in output) {\n delete (output as Record<string, unknown>)['manualChunks'];\n }\n\n // ── 3. Escape route params in `output.chunkFileNames` ───────────────\n //\n // Nitro's `getChunkName()` derives chunk filenames from route patterns,\n // using its internal `routeToFsPath()` helper to convert route params\n // (`:productId` → `[productId]`) and catch-alls (`**` → `[...]`).\n //\n // Rollup/Rolldown interprets *any* `[token]` in the string returned by a\n // `chunkFileNames` function as a placeholder. Only a handful are valid —\n // `[name]`, `[hash]`, `[format]`, `[ext]` — so route-derived tokens like\n // `[productId]` or `[...]` trigger a build error:\n //\n // \"[productId]\" is not a valid placeholder in the \"output.chunkFileNames\" pattern.\n //\n // We wrap the original function to replace non-standard `[token]` patterns\n // with `_token_`, preserving the intended filename while avoiding the\n // placeholder validation error.\n //\n // Example: `_routes/products/[productId].mjs` → `_routes/products/_productId_.mjs`\n const VALID_ROLLUP_PLACEHOLDER = /^\\[(?:name|hash|format|ext)\\]$/;\n const chunkFileNames = (output as Record<string, unknown>)['chunkFileNames'];\n if (typeof chunkFileNames === 'function') {\n const originalFn = chunkFileNames as (...args: unknown[]) => unknown;\n (output as Record<string, unknown>)['chunkFileNames'] = (\n ...args: unknown[]\n ) => {\n const result = originalFn(...args);\n if (typeof result !== 'string') return result;\n return result.replace(/\\[[^\\]]+\\]/g, (match: string) =>\n VALID_ROLLUP_PLACEHOLDER.test(match)\n ? match\n : `_${match.slice(1, -1)}_`,\n );\n };\n }\n}\n\nfunction resolveClientOutputPath(\n cachedPath: string,\n workspaceRoot: string,\n rootDir: string,\n configuredOutDir: string | undefined,\n) {\n if (cachedPath) {\n debugLog('resolveClientOutputPath using cached path', () => ({\n cachedPath,\n workspaceRoot,\n rootDir,\n configuredOutDir,\n }));\n return cachedPath;\n }\n\n if (configuredOutDir) {\n const resolvedPath = normalizePath(\n resolve(workspaceRoot, rootDir, configuredOutDir),\n );\n debugLog('resolveClientOutputPath using configured build.outDir', () => ({\n workspaceRoot,\n rootDir,\n configuredOutDir,\n resolvedPath,\n }));\n return resolvedPath;\n }\n\n // When no explicit build.outDir is set, the environment build config defaults\n // to `<workspace>/dist/<root>/client` for the client build. The non-SSR\n // (client) and SSR paths must agree on this so that registerIndexHtmlVirtual()\n // and publicAssets read from the directory the client build actually wrote to.\n const resolvedPath = normalizePath(\n resolve(workspaceRoot, 'dist', rootDir, 'client'),\n );\n debugLog('resolveClientOutputPath using default dist client path', () => ({\n workspaceRoot,\n rootDir,\n configuredOutDir,\n resolvedPath,\n }));\n return resolvedPath;\n}\n\nfunction getEnvironmentBuildOutDir(environment: unknown): string | undefined {\n if (!environment || typeof environment !== 'object') {\n return undefined;\n }\n\n const environmentConfig = environment as {\n config?: {\n build?: {\n outDir?: string;\n };\n };\n build?: {\n outDir?: string;\n };\n };\n\n return (\n environmentConfig.config?.build?.outDir ?? environmentConfig.build?.outDir\n );\n}\n\nfunction resolveBuiltClientOutputPath(\n cachedPath: string,\n workspaceRoot: string,\n rootDir: string,\n configuredOutDir: string | undefined,\n environment?: unknown,\n) {\n const environmentOutDir = getEnvironmentBuildOutDir(environment);\n if (environmentOutDir) {\n const resolvedPath = normalizePath(\n resolve(workspaceRoot, rootDir, environmentOutDir),\n );\n debugLog('resolveBuiltClientOutputPath using environment outDir', () => ({\n cachedPath,\n workspaceRoot,\n rootDir,\n configuredOutDir,\n environmentOutDir,\n resolvedPath,\n }));\n return resolvedPath;\n }\n\n debugLog(\n 'resolveBuiltClientOutputPath falling back to shared resolver',\n () => ({\n cachedPath,\n workspaceRoot,\n rootDir,\n configuredOutDir,\n environmentOutDir,\n }),\n );\n return resolveClientOutputPath(\n cachedPath,\n workspaceRoot,\n rootDir,\n configuredOutDir,\n );\n}\n\nfunction getNitroPublicOutputDir(nitroConfig: NitroConfig): string {\n const publicDir = nitroConfig.output?.publicDir;\n if (!publicDir) {\n throw new Error(\n 'Nitro public output directory is required to build the sitemap.',\n );\n }\n\n return publicDir;\n}\n\nconst DEBUG_NAMESPACE = 'analog:vite-plugin-nitro';\n\nfunction escapeRegExp(value: string) {\n return value.replace(/[|\\\\{}()[\\]^$+?.*]/g, '\\\\$&');\n}\n\n// Keep DEBUG matching local to this package so CI can opt into verbose traces\n// with familiar patterns like `analog:*` without adding a runtime dependency.\nfunction isDebugEnabled(namespace: string) {\n const debugValue = process.env['DEBUG'];\n if (!debugValue) {\n return false;\n }\n\n return debugValue\n .split(/[\\s,]+/)\n .filter(Boolean)\n .some((pattern) => {\n const matcher = new RegExp(\n `^${escapeRegExp(pattern).replace(/\\\\\\*/g, '.*')}$`,\n );\n return matcher.test(namespace);\n });\n}\n\nfunction debugLog(\n label: string,\n details?: Record<string, unknown> | (() => Record<string, unknown>),\n) {\n if (!isDebugEnabled(DEBUG_NAMESPACE)) {\n return;\n }\n\n const resolvedDetails = typeof details === 'function' ? details() : details;\n if (resolvedDetails && Object.keys(resolvedDetails).length > 0) {\n console.log(`DEBUG: ${label}`, resolvedDetails);\n return;\n }\n\n console.log(`DEBUG: ${label}`);\n}\n\nfunction readDirectoryEntries(path: string): string[] {\n try {\n return readdirSync(path).sort();\n } catch (error) {\n return [\n `<<unable to read directory: ${error instanceof Error ? error.message : String(error)}>>`,\n ];\n }\n}\n\nfunction getPathDebugInfo(path: string) {\n return {\n rawPath: path,\n normalizedPath: normalizePath(path),\n exists: existsSync(path),\n entries: existsSync(path) ? readDirectoryEntries(path) : [],\n };\n}\n\nfunction assetSourceToString(source: string | Uint8Array) {\n return typeof source === 'string'\n ? source\n : Buffer.from(source).toString('utf8');\n}\n\nfunction captureClientIndexHtmlFromBundle(\n bundle: Record<\n string,\n {\n type?: string;\n fileName?: string;\n source?: string | Uint8Array;\n }\n >,\n hook: 'generateBundle' | 'writeBundle',\n) {\n const indexHtmlAsset = Object.values(bundle).find(\n (chunk) =>\n chunk.type === 'asset' &&\n chunk.fileName === 'index.html' &&\n typeof chunk.source !== 'undefined',\n );\n\n if (!indexHtmlAsset?.source) {\n debugLog(`client bundle did not expose index.html during ${hook}`, () => ({\n hook,\n bundleKeys: Object.keys(bundle).sort(),\n assetFileNames: Object.values(bundle)\n .filter((chunk) => chunk.type === 'asset')\n .map((chunk) => chunk.fileName)\n .filter(Boolean),\n }));\n return undefined;\n }\n\n const indexHtml = assetSourceToString(indexHtmlAsset.source);\n debugLog(`captured client bundle index.html asset during ${hook}`, () => ({\n hook,\n fileName: indexHtmlAsset.fileName,\n htmlLength: indexHtml.length,\n }));\n return indexHtml;\n}\n\n// Nitro only needs the HTML template string. Prefer the on-disk file when it\n// exists, but allow the captured client asset to cover build flows where the\n// client output directory disappears before Nitro assembles its virtual modules.\nfunction registerIndexHtmlVirtual(\n nitroConfig: NitroConfig,\n clientOutputPath: string,\n inlineIndexHtml?: string,\n) {\n const indexHtmlPath = resolve(clientOutputPath, 'index.html');\n debugLog('registerIndexHtmlVirtual inspecting client output', () => ({\n platform: process.platform,\n cwd: process.cwd(),\n clientOutputPath,\n clientOutputPathInfo: getPathDebugInfo(clientOutputPath),\n indexHtmlPath,\n indexHtmlExists: existsSync(indexHtmlPath),\n hasInlineIndexHtml: typeof inlineIndexHtml === 'string',\n }));\n if (!existsSync(indexHtmlPath) && typeof inlineIndexHtml !== 'string') {\n debugLog('registerIndexHtmlVirtual missing index.html', () => ({\n platform: process.platform,\n cwd: process.cwd(),\n clientOutputPath,\n clientOutputPathInfo: getPathDebugInfo(clientOutputPath),\n indexHtmlPath,\n hasInlineIndexHtml: typeof inlineIndexHtml === 'string',\n nitroOutput: nitroConfig.output,\n nitroPublicAssets: nitroConfig.publicAssets,\n }));\n throw new Error(\n `[analog] Client build output not found at ${indexHtmlPath}.\\n` +\n `Ensure the client environment build completed successfully before the server build.`,\n );\n }\n const indexHtml =\n typeof inlineIndexHtml === 'string'\n ? inlineIndexHtml\n : readFileSync(indexHtmlPath, 'utf8');\n debugLog('registerIndexHtmlVirtual using HTML template source', () => ({\n source:\n typeof inlineIndexHtml === 'string'\n ? 'captured client bundle asset'\n : 'client output index.html file',\n indexHtmlPath,\n }));\n nitroConfig.virtual = {\n ...nitroConfig.virtual,\n '#analog/index': `export default ${JSON.stringify(indexHtml)};`,\n };\n}\n\n/**\n * Converts the built SSR entry path into a specifier that Nitro's bundler\n * can resolve, including all relative `./assets/*` chunk imports inside\n * the entry.\n *\n * The returned path **must** be an absolute filesystem path with forward\n * slashes (e.g. `D:/a/analog/dist/apps/blog-app/ssr/main.server.js`).\n * This lets Rollup/Rolldown determine the entry's directory and resolve\n * sibling chunk imports like `./assets/core-DTazUigR.js` correctly.\n *\n * ## Why not pathToFileURL() on Windows?\n *\n * Earlier versions converted the path to a `file:///D:/a/...` URL on\n * Windows, which worked with Nitro v2 + Rollup. Nitro v3 switched its\n * default bundler to Rolldown, and Rolldown does **not** extract the\n * importer directory from `file://` URLs. This caused every relative\n * import inside the SSR entry to fail during the prerender build:\n *\n * [RESOLVE_ERROR] Could not resolve './assets/core-DTazUigR.js'\n * in ../../dist/apps/blog-app/ssr/main.server.js\n *\n * `normalizePath()` (from Vite) simply converts backslashes to forward\n * slashes, which both Rollup and Rolldown handle correctly on all\n * platforms.\n */\nfunction toNitroSsrEntrypointSpecifier(ssrEntryPath: string) {\n return normalizePath(ssrEntryPath);\n}\n\nfunction applySsrEntryAlias(\n nitroConfig: NitroConfig,\n options: Options | undefined,\n workspaceRoot: string,\n rootDir: string,\n): void {\n const ssrOutDir =\n options?.ssrBuildDir || resolve(workspaceRoot, 'dist', rootDir, 'ssr');\n if (options?.ssr || nitroConfig.prerender?.routes?.length) {\n const ssrEntryPath = resolveBuiltSsrEntryPath(ssrOutDir);\n const ssrEntry = toNitroSsrEntrypointSpecifier(ssrEntryPath);\n nitroConfig.alias = {\n ...nitroConfig.alias,\n '#analog/ssr': ssrEntry,\n };\n }\n}\n\nfunction resolveBuiltSsrEntryPath(ssrOutDir: string) {\n const candidatePaths = [\n resolve(ssrOutDir, 'main.server.mjs'),\n resolve(ssrOutDir, 'main.server.js'),\n resolve(ssrOutDir, 'main.server'),\n ];\n\n const ssrEntryPath = candidatePaths.find((candidatePath) =>\n existsSync(candidatePath),\n );\n\n if (!ssrEntryPath) {\n throw new Error(\n `Unable to locate the built SSR entry in \"${ssrOutDir}\". Expected one of: ${candidatePaths.join(\n ', ',\n )}`,\n );\n }\n\n return ssrEntryPath;\n}\n\nexport function nitro(options?: Options, nitroOptions?: NitroConfig): Plugin[] {\n const workspaceRoot = options?.workspaceRoot ?? process.cwd();\n const sourceRoot = options?.sourceRoot ?? 'src';\n let isTest = process.env['NODE_ENV'] === 'test' || !!process.env['VITEST'];\n const baseURL = process.env['NITRO_APP_BASE_URL'] || '';\n const prefix = baseURL ? baseURL.substring(0, baseURL.length - 1) : '';\n const apiPrefix = `/${options?.apiPrefix || 'api'}`;\n const useAPIMiddleware =\n typeof options?.useAPIMiddleware !== 'undefined'\n ? options?.useAPIMiddleware\n : true;\n const viteRolldownOutput = options?.vite?.build?.rolldownOptions?.output;\n // Vite's native build typing allows `output` to be either a single object or\n // an array. Analog only forwards `codeSplitting` into the client environment\n // when there is a single output object to merge into.\n const viteRolldownOutputConfig =\n viteRolldownOutput && !Array.isArray(viteRolldownOutput)\n ? viteRolldownOutput\n : undefined;\n const codeSplitting = viteRolldownOutputConfig?.codeSplitting;\n\n let isBuild = false;\n let isServe = false;\n let ssrBuild = false;\n let config: UserConfig;\n let nitroConfig: NitroConfig;\n let environmentBuild = false;\n let hasAPIDir = false;\n let clientOutputPath = '';\n let clientIndexHtml: string | undefined;\n let legacyClientSubBuild = false;\n const rollupExternalEntries: string[] = [];\n const sitemapRoutes: string[] = [];\n const routeSitemaps: Record<\n string,\n PrerenderSitemapConfig | (() => PrerenderSitemapConfig)\n > = {};\n const routeSourceFiles: Record<string, string> = {};\n let rootDir = workspaceRoot;\n\n return [\n (options?.ssr\n ? devServerPlugin({\n entryServer: options?.entryServer,\n index: options?.index,\n routeRules: nitroOptions?.routeRules,\n })\n : false) as Plugin,\n {\n name: '@analogjs/vite-plugin-nitro',\n async config(userConfig, { mode, command }) {\n isServe = command === 'serve';\n isBuild = command === 'build';\n ssrBuild = userConfig.build?.ssr === true;\n config = userConfig;\n isTest = isTest ? isTest : mode === 'test';\n rollupExternalEntries.length = 0;\n clientIndexHtml = undefined;\n sitemapRoutes.length = 0;\n for (const key of Object.keys(routeSitemaps)) {\n delete routeSitemaps[key];\n }\n for (const key of Object.keys(routeSourceFiles)) {\n delete routeSourceFiles[key];\n }\n\n const resolvedConfigRoot = config.root\n ? resolve(workspaceRoot, config.root)\n : workspaceRoot;\n rootDir = relative(workspaceRoot, resolvedConfigRoot) || '.';\n hasAPIDir = existsSync(\n resolve(\n workspaceRoot,\n rootDir,\n `${sourceRoot}/server/routes/${options?.apiPrefix || 'api'}`,\n ),\n );\n const buildPreset =\n process.env['BUILD_PRESET'] ??\n (nitroOptions?.preset as string | undefined) ??\n (process.env['VERCEL'] ? 'vercel' : undefined);\n\n const pageHandlers = getPageHandlers({\n workspaceRoot,\n sourceRoot,\n rootDir,\n additionalPagesDirs: options?.additionalPagesDirs,\n hasAPIDir,\n });\n const resolvedClientOutputPath = resolveClientOutputPath(\n clientOutputPath,\n workspaceRoot,\n rootDir,\n config.build?.outDir,\n );\n debugLog('nitro config resolved client output path', () => ({\n platform: process.platform,\n workspaceRoot,\n configRoot: config.root,\n resolvedConfigRoot,\n rootDir,\n buildOutDir: config.build?.outDir,\n clientOutputPath,\n resolvedClientOutputPath,\n hasEnvironmentConfig: !!config.environments,\n clientEnvironmentOutDir:\n config.environments?.['client'] &&\n typeof config.environments['client'] === 'object' &&\n 'build' in config.environments['client']\n ? (\n config.environments['client'] as {\n build?: { outDir?: string };\n }\n ).build?.outDir\n : undefined,\n }));\n\n nitroConfig = {\n rootDir: normalizePath(rootDir),\n preset: buildPreset,\n compatibilityDate: '2025-11-19',\n logLevel: nitroOptions?.logLevel || 0,\n serverDir: normalizePath(`${sourceRoot}/server`),\n scanDirs: [\n normalizePath(`${rootDir}/${sourceRoot}/server`),\n ...(options?.additionalAPIDirs || []).map((dir) =>\n normalizePath(`${workspaceRoot}${dir}`),\n ),\n ],\n output: {\n dir: normalizePath(\n resolve(workspaceRoot, 'dist', rootDir, 'analog'),\n ),\n publicDir: normalizePath(\n resolve(workspaceRoot, 'dist', rootDir, 'analog/public'),\n ),\n },\n buildDir: normalizePath(\n resolve(workspaceRoot, 'dist', rootDir, '.nitro'),\n ),\n typescript: {\n generateTsConfig: false,\n },\n runtimeConfig: {\n apiPrefix: apiPrefix.substring(1),\n prefix,\n },\n // Analog provides its own renderer handler; prevent Nitro v3 from\n // auto-detecting index.html in rootDir and adding a conflicting one.\n renderer: false,\n imports: {\n autoImport: false,\n },\n hooks: {\n 'rollup:before': createRollupBeforeHook(rollupExternalEntries),\n },\n rollupConfig: {\n onwarn(warning) {\n if (\n warning.message.includes('empty chunk') &&\n warning.message.endsWith('.server')\n ) {\n return;\n }\n },\n plugins: [pageEndpointsPlugin()],\n },\n handlers: [\n ...(hasAPIDir\n ? []\n : useAPIMiddleware\n ? [createNitroMiddlewareHandler('#ANALOG_API_MIDDLEWARE')]\n : []),\n ...pageHandlers,\n ],\n routeRules: hasAPIDir\n ? undefined\n : useAPIMiddleware\n ? undefined\n : {\n [`${prefix}${apiPrefix}/**`]: {\n proxy: { to: '/**' },\n },\n },\n virtual: {\n '#ANALOG_SSR_RENDERER': ssrRenderer(),\n '#ANALOG_CLIENT_RENDERER': clientRenderer(),\n ...(hasAPIDir ? {} : { '#ANALOG_API_MIDDLEWARE': apiMiddleware }),\n },\n };\n\n if (isVercelPreset(buildPreset)) {\n nitroConfig = withVercelOutputAPI(nitroConfig, workspaceRoot);\n }\n\n if (isCloudflarePreset(buildPreset)) {\n nitroConfig = withCloudflareOutput(nitroConfig);\n }\n\n if (\n isNetlifyPreset(buildPreset) &&\n rootDir === '.' &&\n !existsSync(resolve(workspaceRoot, 'netlify.toml'))\n ) {\n nitroConfig = withNetlifyOutputAPI(nitroConfig, workspaceRoot);\n }\n\n if (isFirebaseAppHosting()) {\n nitroConfig = withAppHostingOutput(nitroConfig);\n }\n\n if (!ssrBuild && !isTest) {\n // store the client output path for the SSR build config\n clientOutputPath = resolvedClientOutputPath;\n debugLog(\n 'nitro config cached client output path for later SSR/Nitro build',\n () => ({\n ssrBuild,\n isTest,\n clientOutputPath,\n }),\n );\n }\n\n // Start with a clean alias map. #analog/index is registered as a Nitro\n // virtual module after the client build, inlining the HTML template so\n // the server bundle imports it instead of using readFileSync with an\n // absolute path.\n nitroConfig.alias = {};\n\n if (isBuild) {\n nitroConfig.publicAssets = [\n { dir: normalizePath(resolvedClientOutputPath), maxAge: 0 },\n ];\n\n // In Nitro v3, renderer.entry is resolved via resolveModulePath()\n // during options normalization, which requires a real filesystem path.\n // Virtual modules (prefixed with #) can't survive this resolution.\n // Instead, we add the renderer as a catch-all handler directly —\n // this is functionally equivalent to what Nitro does internally\n // (it converts renderer.entry into a { route: '/**', lazy: true }\n // handler), but avoids the filesystem resolution step.\n const rendererHandler = options?.ssr\n ? '#ANALOG_SSR_RENDERER'\n : '#ANALOG_CLIENT_RENDERER';\n nitroConfig.handlers = [\n ...(nitroConfig.handlers || []),\n {\n handler: rendererHandler,\n route: '/**',\n lazy: true,\n },\n ];\n\n if (isEmptyPrerenderRoutes(options)) {\n nitroConfig.prerender = {};\n nitroConfig.prerender.routes = ['/'];\n }\n\n if (options?.prerender) {\n nitroConfig.prerender = nitroConfig.prerender ?? {};\n nitroConfig.prerender.crawlLinks = options?.prerender?.discover;\n\n let routes: (\n | string\n | PrerenderContentDir\n | PrerenderRouteConfig\n | undefined\n )[] = [];\n\n const prerenderRoutes = options?.prerender?.routes;\n const hasExplicitPrerenderRoutes =\n typeof prerenderRoutes === 'function' ||\n Array.isArray(prerenderRoutes);\n if (\n isArrayWithElements<string | PrerenderContentDir>(prerenderRoutes)\n ) {\n routes = prerenderRoutes;\n } else if (typeof prerenderRoutes === 'function') {\n routes = await prerenderRoutes();\n }\n\n const resolvedPrerenderRoutes = routes.reduce<string[]>(\n (prev, current) => {\n if (!current) {\n return prev;\n }\n if (typeof current === 'string') {\n prev.push(current);\n sitemapRoutes.push(current);\n return prev;\n }\n\n if ('route' in current) {\n if (current.sitemap) {\n routeSitemaps[current.route] = current.sitemap;\n }\n\n if (current.outputSourceFile) {\n const sourcePath = resolve(\n workspaceRoot,\n rootDir,\n current.outputSourceFile,\n );\n routeSourceFiles[current.route] = readFileSync(\n sourcePath,\n 'utf8',\n );\n }\n\n prev.push(current.route);\n sitemapRoutes.push(current.route);\n\n // Add the server-side data fetching endpoint URL\n if ('staticData' in current) {\n prev.push(`${apiPrefix}/_analog/pages/${current.route}`);\n }\n\n return prev;\n }\n\n const affectedFiles: PrerenderContentFile[] =\n getMatchingContentFilesWithFrontMatter(\n workspaceRoot,\n rootDir,\n current.contentDir,\n );\n\n affectedFiles.forEach((f) => {\n const result = current.transform(f);\n\n if (result) {\n if (current.sitemap) {\n routeSitemaps[result] =\n current.sitemap && typeof current.sitemap === 'function'\n ? current.sitemap?.(f)\n : current.sitemap;\n }\n\n if (current.outputSourceFile) {\n const sourceContent = current.outputSourceFile(f);\n if (sourceContent) {\n routeSourceFiles[result] = sourceContent;\n }\n }\n\n prev.push(result);\n sitemapRoutes.push(result);\n\n // Add the server-side data fetching endpoint URL\n if ('staticData' in current) {\n prev.push(`${apiPrefix}/_analog/pages/${result}`);\n }\n }\n });\n\n return prev;\n },\n [],\n );\n\n nitroConfig.prerender.routes =\n hasExplicitPrerenderRoutes || resolvedPrerenderRoutes.length\n ? resolvedPrerenderRoutes\n : (nitroConfig.prerender.routes ?? []);\n }\n\n // ── SSR / prerender Nitro config ─────────────────────────────\n //\n // This block configures Nitro for builds that rebundle the SSR\n // entry (main.server.{js,mjs}). That happens in two cases:\n //\n // 1. Full SSR apps — `options.ssr === true`\n // 2. Prerender-only — no runtime SSR, but the prerender build\n // still imports the SSR entry to render static pages.\n //\n // The original gate was `if (ssrBuild)`, which checks the Vite\n // top-level `build.ssr` flag. That works for SSR-only builds but\n // misses two Vite 6+ paths:\n //\n // a. **Vite Environment API (Vite 6+)** — SSR config lives in\n // `environments.ssr.build.ssr`, not `build.ssr`, so\n // `ssrBuild` is always `false`.\n // b. **Prerender-only apps** (e.g. blog-app) — `options.ssr`\n // is `false`, but prerender routes exist and the prerender\n // build still processes the SSR entry.\n //\n // Without this block:\n // - `rxjs` is never externalised → RESOLVE_ERROR in the\n // Nitro prerender build (especially on Windows CI).\n // - `moduleSideEffects` for zone.js is never set → zone.js\n // side-effects may be tree-shaken.\n // - The handlers list is not reassembled with page endpoints\n // + the renderer catch-all.\n //\n // The widened condition covers all supported build paths:\n // - `ssrBuild` → SSR-only build\n // - `options?.ssr` → Environment API SSR\n // - `nitroConfig.prerender?.routes?.length` → prerender-only\n if (\n ssrBuild ||\n options?.ssr ||\n nitroConfig.prerender?.routes?.length\n ) {\n if (process.platform === 'win32') {\n nitroConfig.noExternals = appendNoExternals(\n nitroConfig.noExternals,\n 'std-env',\n );\n }\n\n rollupExternalEntries.push(\n 'rxjs',\n 'node-fetch-native/dist/polyfill',\n );\n\n nitroConfig = {\n ...nitroConfig,\n moduleSideEffects: ['zone.js/node', 'zone.js/fesm2015/zone-node'],\n handlers: [\n ...(hasAPIDir\n ? []\n : useAPIMiddleware\n ? [createNitroMiddlewareHandler('#ANALOG_API_MIDDLEWARE')]\n : []),\n ...pageHandlers,\n // Preserve the renderer catch-all handler added above\n {\n handler: rendererHandler,\n route: '/**',\n lazy: true,\n },\n ],\n };\n }\n }\n\n nitroConfig = mergeConfig(\n nitroConfig,\n nitroOptions as Record<string, any>,\n );\n\n return {\n environments: {\n client: {\n build: {\n outDir:\n config?.build?.outDir ||\n resolve(workspaceRoot, 'dist', rootDir, 'client'),\n emptyOutDir: true,\n // Forward code-splitting config to Rolldown when running\n // under Vite 8+. `false` disables splitting (inlines all\n // dynamic imports); an object configures chunk groups.\n // The `!== undefined` check ensures `codeSplitting: false`\n // is forwarded correctly (a truthy check would swallow it).\n ...(isRolldown() && codeSplitting !== undefined\n ? {\n rolldownOptions: {\n output: {\n // Preserve any sibling Rolldown output options while\n // overriding just `codeSplitting` for the client build.\n ...viteRolldownOutputConfig,\n codeSplitting,\n },\n },\n }\n : {}),\n },\n },\n ssr: {\n build: {\n ssr: true,\n [getBundleOptionsKey()]: {\n input:\n options?.entryServer ||\n resolve(\n workspaceRoot,\n rootDir,\n `${sourceRoot}/main.server.ts`,\n ),\n },\n outDir:\n options?.ssrBuildDir ||\n resolve(workspaceRoot, 'dist', rootDir, 'ssr'),\n // Preserve the client build output. The client environment is\n // built first and Nitro reads its index.html after SSR finishes.\n emptyOutDir: false,\n },\n },\n },\n builder: {\n sharedPlugins: true,\n buildApp: async (builder) => {\n environmentBuild = true;\n debugLog('builder.buildApp starting', () => ({\n platform: process.platform,\n workspaceRoot,\n rootDir,\n cachedClientOutputPath: clientOutputPath,\n configuredBuildOutDir: config.build?.outDir,\n clientEnvironmentOutDir: getEnvironmentBuildOutDir(\n builder.environments['client'],\n ),\n ssrEnvironmentOutDir: getEnvironmentBuildOutDir(\n builder.environments['ssr'],\n ),\n }));\n\n // Client must complete before SSR — the server build reads the\n // client's index.html via registerIndexHtmlVirtual(). Running\n // them in parallel caused a race on Windows where emptyOutDir\n // could delete client output before the server read it.\n await builder.build(builder.environments['client']);\n const postClientBuildOutputPath = resolveBuiltClientOutputPath(\n clientOutputPath,\n workspaceRoot,\n rootDir,\n config.build?.outDir,\n builder.environments['client'],\n );\n // Capture the client template before any SSR/prerender work runs.\n // On Windows, later phases can leave the client output directory\n // unavailable even though the client build itself succeeded.\n registerIndexHtmlVirtual(\n nitroConfig,\n postClientBuildOutputPath,\n clientIndexHtml,\n );\n debugLog('builder.buildApp completed client build', () => ({\n postClientBuildOutputPath,\n postClientBuildOutputInfo: getPathDebugInfo(\n postClientBuildOutputPath,\n ),\n postClientBuildIndexHtmlPath: resolve(\n postClientBuildOutputPath,\n 'index.html',\n ),\n postClientBuildIndexHtmlExists: existsSync(\n resolve(postClientBuildOutputPath, 'index.html'),\n ),\n }));\n\n if (options?.ssr || nitroConfig.prerender?.routes?.length) {\n debugLog('builder.buildApp starting SSR build', () => ({\n ssrEnabled: options?.ssr,\n prerenderRoutes: nitroConfig.prerender?.routes,\n }));\n await builder.build(builder.environments['ssr']);\n debugLog('builder.buildApp completed SSR build', () => ({\n ssrOutputPath:\n options?.ssrBuildDir ||\n resolve(workspaceRoot, 'dist', rootDir, 'ssr'),\n }));\n }\n\n applySsrEntryAlias(nitroConfig, options, workspaceRoot, rootDir);\n\n const resolvedClientOutputPath = resolveBuiltClientOutputPath(\n clientOutputPath,\n workspaceRoot,\n rootDir,\n config.build?.outDir,\n builder.environments['client'],\n );\n\n nitroConfig.publicAssets = [\n { dir: normalizePath(resolvedClientOutputPath), maxAge: 0 },\n ];\n debugLog(\n 'builder.buildApp resolved final client output path before Nitro build',\n () => ({\n resolvedClientOutputPath,\n resolvedClientOutputInfo: getPathDebugInfo(\n resolvedClientOutputPath,\n ),\n nitroPublicAssets: nitroConfig.publicAssets,\n }),\n );\n\n await buildServer(options, nitroConfig, routeSourceFiles);\n\n if (\n nitroConfig.prerender?.routes?.length &&\n options?.prerender?.sitemap\n ) {\n console.log('Building Sitemap...');\n // sitemap needs to be built after all directories are built\n await buildSitemap(\n config,\n options.prerender.sitemap,\n sitemapRoutes.length\n ? sitemapRoutes\n : nitroConfig.prerender.routes,\n getNitroPublicOutputDir(nitroConfig),\n routeSitemaps,\n { apiPrefix: options?.apiPrefix || 'api' },\n );\n }\n\n console.log(\n `\\n\\nThe '@analogjs/platform' server has been successfully built.`,\n );\n },\n },\n };\n },\n generateBundle(\n _options,\n bundle: Record<\n string,\n {\n type?: string;\n fileName?: string;\n source?: string | Uint8Array;\n }\n >,\n ) {\n if (!isBuild || ssrBuild) {\n return;\n }\n\n clientIndexHtml =\n captureClientIndexHtmlFromBundle(bundle, 'generateBundle') ??\n clientIndexHtml;\n },\n writeBundle(\n _options,\n bundle: Record<\n string,\n {\n type?: string;\n fileName?: string;\n source?: string | Uint8Array;\n }\n >,\n ) {\n if (!isBuild || ssrBuild) {\n return;\n }\n\n clientIndexHtml =\n captureClientIndexHtmlFromBundle(bundle, 'writeBundle') ??\n clientIndexHtml;\n },\n async configureServer(viteServer: ViteDevServer) {\n if (isServe && !isTest) {\n const nitro = await createNitro({\n dev: true,\n // Nitro's Vite builder now rejects `build()` in dev mode, but Analog's\n // dev integration still relies on the builder-driven reload hooks.\n // Force the server worker onto Rollup for this dev-only path.\n builder: 'rollup',\n ...nitroConfig,\n });\n const server = createDevServer(nitro);\n await build(nitro);\n const nitroSourceRoots = [\n normalizePath(\n resolve(workspaceRoot, rootDir, `${sourceRoot}/server`),\n ),\n ...(options?.additionalAPIDirs || []).map((dir) =>\n normalizePath(`${workspaceRoot}${dir}`),\n ),\n ];\n const isNitroSourceFile = (path: string) => {\n const normalizedPath = normalizePath(path);\n return nitroSourceRoots.some(\n (root) =>\n normalizedPath === root ||\n normalizedPath.startsWith(`${root}/`),\n );\n };\n let nitroRebuildPromise: Promise<void> | undefined;\n let nitroRebuildPending = false;\n const rebuildNitroServer = () => {\n if (nitroRebuildPromise) {\n // Coalesce rapid file events so a save that touches multiple server\n // route files results in one follow-up rebuild instead of many.\n nitroRebuildPending = true;\n return nitroRebuildPromise;\n }\n\n nitroRebuildPromise = (async () => {\n do {\n nitroRebuildPending = false;\n // Nitro API routes are not part of Vite's normal client HMR graph,\n // so rebuild the Nitro dev server to pick up handler edits.\n await build(nitro);\n } while (nitroRebuildPending);\n\n // Reload the page after the server rebuild completes so the next\n // request observes the updated API route implementation.\n viteServer.ws.send({ type: 'full-reload' });\n })()\n .catch((error: unknown) => {\n viteServer.config.logger.error(\n `[analog] Failed to rebuild Nitro dev server.\\n${error instanceof Error ? error.stack || error.message : String(error)}`,\n );\n })\n .finally(() => {\n nitroRebuildPromise = undefined;\n });\n\n return nitroRebuildPromise;\n };\n const onNitroSourceChange = (path: string) => {\n if (!isNitroSourceFile(path)) {\n return;\n }\n\n void rebuildNitroServer();\n };\n\n // Watch the full Nitro source roots instead of only the API route\n // directory. API handlers often read helper modules, shared data, or\n // middleware from elsewhere under `src/server`, and those edits should\n // still rebuild the Nitro dev server and refresh connected browsers.\n viteServer.watcher.on('add', onNitroSourceChange);\n viteServer.watcher.on('change', onNitroSourceChange);\n viteServer.watcher.on('unlink', onNitroSourceChange);\n\n const apiHandler = async (\n req: IncomingMessage,\n res: ServerResponse,\n ) => {\n // Nitro v3's dev server is fetch-first, so adapt Vite's Node\n // request once and let Nitro respond with a standard Web Response.\n const response = await server.fetch(toWebRequest(req));\n await writeWebResponseToNode(res, response);\n };\n\n if (hasAPIDir) {\n viteServer.middlewares.use(\n (\n req: IncomingMessage,\n res: ServerResponse,\n next: (error?: unknown) => void,\n ) => {\n if (req.url?.startsWith(`${prefix}${apiPrefix}`)) {\n void apiHandler(req, res).catch((error) => next(error));\n return;\n }\n\n next();\n },\n );\n } else {\n viteServer.middlewares.use(\n apiPrefix,\n (\n req: IncomingMessage,\n res: ServerResponse,\n next: (error?: unknown) => void,\n ) => {\n void apiHandler(req, res).catch((error) => next(error));\n },\n );\n }\n\n viteServer.httpServer?.once('listening', () => {\n process.env['ANALOG_HOST'] = !viteServer.config.server.host\n ? 'localhost'\n : (viteServer.config.server.host as string);\n process.env['ANALOG_PORT'] = `${viteServer.config.server.port}`;\n });\n\n // handle upgrades if websockets are enabled\n if (nitroOptions?.experimental?.websocket) {\n viteServer.httpServer?.on('upgrade', server.upgrade);\n }\n\n console.log(\n `\\n\\nThe server endpoints are accessible under the \"${prefix}${apiPrefix}\" path.`,\n );\n }\n },\n\n async closeBundle() {\n if (legacyClientSubBuild) {\n return;\n }\n\n // When builder.buildApp ran, it already handled the full\n // client → SSR → Nitro pipeline. Skip to avoid double work.\n if (environmentBuild) {\n return;\n }\n\n // SSR sub-build — Vite re-enters the plugin with build.ssr;\n // Nitro server assembly happens only after the client pass.\n if (ssrBuild) {\n return;\n }\n\n // Nx executors (and any caller that runs `vite build` without\n // the Environment API) never trigger builder.buildApp, so\n // closeBundle is the only place to drive the SSR + Nitro build.\n if (isBuild) {\n const resolvedClientOutputPath = resolveClientOutputPath(\n clientOutputPath,\n workspaceRoot,\n rootDir,\n config.build?.outDir,\n );\n debugLog(\n 'closeBundle resolved client output path before legacy SSR build',\n () => ({\n platform: process.platform,\n workspaceRoot,\n rootDir,\n cachedClientOutputPath: clientOutputPath,\n configuredBuildOutDir: config.build?.outDir,\n resolvedClientOutputPath,\n resolvedClientOutputInfo: getPathDebugInfo(\n resolvedClientOutputPath,\n ),\n }),\n );\n const indexHtmlPath = resolve(resolvedClientOutputPath, 'index.html');\n if (\n !existsSync(indexHtmlPath) &&\n typeof clientIndexHtml !== 'string'\n ) {\n debugLog(\n 'closeBundle rebuilding missing client output before SSR/Nitro',\n () => ({\n platform: process.platform,\n workspaceRoot,\n rootDir,\n configuredBuildOutDir: config.build?.outDir,\n resolvedClientOutputPath,\n indexHtmlPath,\n }),\n );\n legacyClientSubBuild = true;\n try {\n await buildClientApp(config, options);\n } finally {\n legacyClientSubBuild = false;\n }\n }\n // Capture the client HTML before kicking off the standalone SSR build.\n // This mirrors the successful sequencing from before the closeBundle\n // refactor and avoids depending on the client directory surviving the\n // nested SSR build on Windows.\n registerIndexHtmlVirtual(\n nitroConfig,\n resolvedClientOutputPath,\n clientIndexHtml,\n );\n\n if (options?.ssr) {\n console.log('Building SSR application...');\n await buildSSRApp(config, options);\n debugLog('closeBundle completed standalone SSR build', () => ({\n ssrBuildDir:\n options?.ssrBuildDir ||\n resolve(workspaceRoot, 'dist', rootDir, 'ssr'),\n clientOutputPathInfo: clientOutputPath\n ? getPathDebugInfo(clientOutputPath)\n : null,\n }));\n }\n\n applySsrEntryAlias(nitroConfig, options, workspaceRoot, rootDir);\n debugLog(\n 'closeBundle resolved client output path before Nitro build',\n () => ({\n platform: process.platform,\n workspaceRoot,\n rootDir,\n cachedClientOutputPath: clientOutputPath,\n configuredBuildOutDir: config.build?.outDir,\n resolvedClientOutputPath,\n resolvedClientOutputInfo: getPathDebugInfo(\n resolvedClientOutputPath,\n ),\n }),\n );\n registerIndexHtmlVirtual(\n nitroConfig,\n resolvedClientOutputPath,\n clientIndexHtml,\n );\n\n await buildServer(options, nitroConfig, routeSourceFiles);\n\n if (\n nitroConfig.prerender?.routes?.length &&\n options?.prerender?.sitemap\n ) {\n console.log('Building Sitemap...');\n await buildSitemap(\n config,\n options.prerender.sitemap,\n sitemapRoutes.length\n ? sitemapRoutes\n : nitroConfig.prerender.routes,\n getNitroPublicOutputDir(nitroConfig),\n routeSitemaps,\n { apiPrefix: options?.apiPrefix || 'api' },\n );\n }\n\n console.log(\n `\\n\\nThe '@analogjs/platform' server has been successfully built.`,\n );\n }\n },\n },\n {\n name: '@analogjs/vite-plugin-nitro-api-prefix',\n config() {\n return {\n define: {\n ANALOG_API_PREFIX: `\"${baseURL.substring(1)}${apiPrefix.substring(1)}\"`,\n },\n };\n },\n },\n ];\n}\n\nfunction isEmptyPrerenderRoutes(options?: Options): boolean {\n if (!options || isArrayWithElements(options?.prerender?.routes)) {\n return false;\n }\n return !options.prerender?.routes;\n}\n\nfunction isArrayWithElements<T>(arr: unknown): arr is [T, ...T[]] {\n return !!(Array.isArray(arr) && arr.length);\n}\n\nconst VERCEL_PRESET = 'vercel';\n// Nitro v3 consolidates the old `vercel-edge` preset into `vercel` with\n// fluid compute enabled by default, so a single preset covers both\n// serverless and edge deployments.\nconst withVercelOutputAPI = (\n nitroConfig: NitroConfig | undefined,\n workspaceRoot: string,\n) => ({\n ...nitroConfig,\n preset: nitroConfig?.preset ?? 'vercel',\n vercel: {\n ...nitroConfig?.vercel,\n entryFormat: nitroConfig?.vercel?.entryFormat ?? 'node',\n functions: {\n runtime: nitroConfig?.vercel?.functions?.runtime ?? 'nodejs24.x',\n ...nitroConfig?.vercel?.functions,\n },\n },\n output: {\n ...nitroConfig?.output,\n dir: normalizePath(resolve(workspaceRoot, '.vercel', 'output')),\n publicDir: normalizePath(\n resolve(workspaceRoot, '.vercel', 'output/static'),\n ),\n },\n});\n\n// Nitro v3 uses underscore-separated preset names (e.g. `cloudflare_pages`),\n// but we accept both hyphen and underscore forms for backwards compatibility.\nconst isCloudflarePreset = (buildPreset: string | undefined) =>\n process.env['CF_PAGES'] ||\n (buildPreset &&\n (buildPreset.toLowerCase().includes('cloudflare-pages') ||\n buildPreset.toLowerCase().includes('cloudflare_pages')));\n\nconst withCloudflareOutput = (nitroConfig: NitroConfig | undefined) => ({\n ...nitroConfig,\n output: {\n ...nitroConfig?.output,\n serverDir: '{{ output.publicDir }}/_worker.js',\n },\n});\n\nconst isFirebaseAppHosting = () => !!process.env['NG_BUILD_LOGS_JSON'];\nconst withAppHostingOutput = (nitroConfig: NitroConfig) => {\n let hasOutput = false;\n\n return <NitroConfig>{\n ...nitroConfig,\n serveStatic: true,\n rollupConfig: {\n ...nitroConfig.rollupConfig,\n output: {\n ...nitroConfig.rollupConfig?.output,\n entryFileNames: 'server.mjs',\n },\n },\n hooks: {\n ...nitroConfig.hooks,\n compiled: () => {\n if (!hasOutput) {\n const buildOutput = {\n errors: [],\n warnings: [],\n outputPaths: {\n root: pathToFileURL(`${nitroConfig.output?.dir}`),\n browser: pathToFileURL(`${nitroConfig.output?.publicDir}`),\n server: pathToFileURL(`${nitroConfig.output?.dir}/server`),\n },\n };\n\n // Log the build output for Firebase App Hosting to pick up\n console.log(JSON.stringify(buildOutput, null, 2));\n hasOutput = true;\n }\n },\n },\n };\n};\n\nconst isNetlifyPreset = (buildPreset: string | undefined) =>\n process.env['NETLIFY'] ||\n (buildPreset && buildPreset.toLowerCase().includes('netlify'));\n\nconst withNetlifyOutputAPI = (\n nitroConfig: NitroConfig | undefined,\n workspaceRoot: string,\n) => ({\n ...nitroConfig,\n output: {\n ...nitroConfig?.output,\n dir: normalizePath(resolve(workspaceRoot, 'netlify/functions')),\n },\n});\n"],"mappings":"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"}
|