{"version":3,"file":"index.cjs","names":[],"sources":["../../../src/manifest/index.ts"],"sourcesContent":["import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, relative } from \"node:path\";\nimport { scanActions, type ActionRegistry } from \"../action/scan.js\";\nimport type { ResolvedNixConfig } from \"../config/index.js\";\nimport { runIntegrationHook } from \"../integrations/index.js\";\nimport { scanIslands, type IslandModule } from \"../island/scan.js\";\nimport { scanRoutes, type ScannedRoutes } from \"../router/route-scanner.js\";\n\nexport interface AppManifest {\n  version: 1;\n  root: string;\n  routes: ScannedRoutes;\n  actions: ActionRegistry;\n  islands: IslandModule[];\n  base: string;\n  output: ResolvedNixConfig[\"output\"];\n}\n\nexport async function createAppManifest(config: ResolvedNixConfig): Promise<AppManifest> {\n  const [routes, actions, islands] = await Promise.all([\n    scanRoutes(config.appDir),\n    scanActions(config.appDir),\n    scanIslands(config.islandsDir),\n  ]);\n  validateManifestRoutes(routes);\n  validateIslands(islands);\n  const manifest: AppManifest = {\n    version: 1,\n    root: config.root,\n    routes,\n    actions,\n    islands,\n    base: config.base,\n    output: config.output,\n  };\n  await runIntegrationHook(config.integrations, \"routes\", [\n    manifest,\n    { root: config.root, command: \"build\" },\n  ]);\n  return manifest;\n}\n\nexport async function writeAppManifest(manifest: AppManifest, path: string): Promise<void> {\n  await mkdir(dirname(path), { recursive: true });\n  await writeFile(path, JSON.stringify(toPortableManifest(manifest), null, 2), \"utf8\");\n}\n\nexport async function writeRouteTypes(manifest: AppManifest, path: string): Promise<void> {\n  const routePaths = manifest.routes.pages.map((route) => JSON.stringify(route.path));\n  const actionNames = Object.values(manifest.actions)\n    .flatMap((actions) => Object.keys(actions))\n    .filter((name, index, names) => names.indexOf(name) === index)\n    .map((name) => JSON.stringify(name));\n  const source = [\n    `export type NixRoutePath = ${routePaths.length ? routePaths.join(\" | \") : \"never\"};`,\n    `export type NixActionName = ${actionNames.length ? actionNames.join(\" | \") : \"never\"};`,\n    \"export interface NixRouteParams { [name: string]: string | string[] | undefined }\",\n    \"\",\n  ].join(\"\\n\");\n  await mkdir(dirname(path), { recursive: true });\n  await writeFile(path, source, \"utf8\");\n}\n\nexport function validateManifestRoutes(routes: ScannedRoutes): void {\n  const seen = new Map<string, string>();\n  for (const route of routes.pages) {\n    registerRoute(seen, route.path, route.pagePath, \"page\");\n    assertNotReserved(route.path, route.pagePath);\n  }\n  for (const route of routes.api) {\n    registerRoute(seen, route.path, route.routePath, \"API\");\n    assertNotReserved(route.path, route.routePath);\n  }\n}\n\nexport function assertClientImportAllowed(id: string, importer?: string): void {\n  if (/\\.server\\.[cm]?[jt]sx?$/.test(id)) {\n    throw new Error(`[nix-js-kit] Server-only module imported by client${importer ? ` from ${importer}` : \"\"}: ${id}`);\n  }\n}\n\nfunction registerRoute(seen: Map<string, string>, path: string, file: string, kind: string): void {\n  const existing = seen.get(path);\n  if (existing) {\n    throw new Error(`[nix-js-kit] Duplicate ${kind} route \"${path}\": ${existing} and ${file}`);\n  }\n  seen.set(path, file);\n}\n\nfunction assertNotReserved(path: string, file: string): void {\n  if (path === \"/__nix-js\" || path.startsWith(\"/__nix-js/\") || path === \"/_nix-js\" || path.startsWith(\"/_nix-js/\")) {\n    throw new Error(`[nix-js-kit] Reserved route \"${path}\" declared by ${file}`);\n  }\n}\n\nfunction validateIslands(islands: readonly IslandModule[]): void {\n  const names = new Set<string>();\n  for (const island of islands) {\n    if (names.has(island.name)) throw new Error(`[nix-js-kit] Duplicate island name: ${island.name}`);\n    names.add(island.name);\n  }\n}\n\nfunction toPortableManifest(manifest: AppManifest): AppManifest {\n  const relativePath = (path: string | undefined) => path ? relative(manifest.root, path).split(\"\\\\\").join(\"/\") : undefined;\n  const routes: ScannedRoutes = {\n    pages: manifest.routes.pages.map((route) => ({\n      ...route,\n      pagePath: relativePath(route.pagePath)!,\n      dataPath: relativePath(route.dataPath),\n      actionPath: relativePath(route.actionPath),\n      loadingPath: relativePath(route.loadingPath),\n      layouts: route.layouts.map((layout) => relativePath(layout)!),\n    })),\n    api: manifest.routes.api.map((route) => ({ ...route, routePath: relativePath(route.routePath)! })),\n    error404: manifest.routes.error404 ? {\n      ...manifest.routes.error404,\n      pagePath: relativePath(manifest.routes.error404.pagePath)!,\n      dataPath: relativePath(manifest.routes.error404.dataPath),\n      actionPath: relativePath(manifest.routes.error404.actionPath),\n      loadingPath: relativePath(manifest.routes.error404.loadingPath),\n      layouts: manifest.routes.error404.layouts.map((layout) => relativePath(layout)!),\n    } : undefined,\n    error500: manifest.routes.error500 ? {\n      ...manifest.routes.error500,\n      pagePath: relativePath(manifest.routes.error500.pagePath)!,\n      dataPath: relativePath(manifest.routes.error500.dataPath),\n      actionPath: relativePath(manifest.routes.error500.actionPath),\n      loadingPath: relativePath(manifest.routes.error500.loadingPath),\n      layouts: manifest.routes.error500.layouts.map((layout) => relativePath(layout)!),\n    } : undefined,\n  };\n  const actions: ActionRegistry = {};\n  for (const [page, pageActions] of Object.entries(manifest.actions)) {\n    actions[page] = Object.fromEntries(\n      Object.entries(pageActions).map(([name, path]) => [name, relativePath(path)!]),\n    );\n  }\n  return {\n    ...manifest,\n    root: \".\",\n    routes,\n    actions,\n    islands: manifest.islands.map((island) => ({ ...island, filePath: relativePath(island.filePath)! })),\n  };\n}\n"],"mappings":"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"}