{"version":3,"file":"index.mjs","names":["nodeMkdir","nodeWriteFile","nodeRename","nodeUnlink"],"sources":["../../src/astro/storage/adapters.ts","../../src/astro/object-cache/adapters.ts","../../src/migrations/manifest-writer.ts","../../src/astro/integration/font-provider.ts","../../src/astro/integration/route-naming.ts","../../src/astro/integration/routes.ts","../../src/astro/integration/virtual-modules.ts","../../src/astro/integration/vite-config.ts","../../src/astro/integration/runtime.ts","../../src/astro/integration/index.ts"],"sourcesContent":["/**\n * Storage Adapter Functions\n *\n * These run at config time (astro.config.mjs) and return serializable descriptors.\n * The actual storage is created at runtime by loading the entrypoint.\n *\n * @example\n * ```ts\n * // astro.config.mjs\n * import emdash, { s3, local } from \"@premium-cms/emdash/astro\";\n *\n * export default defineConfig({\n *   integrations: [\n *     emdash({\n *       storage: s3({\n *         endpoint: \"https://xxx.r2.cloudflarestorage.com\",\n *         bucket: \"media\",\n *         accessKeyId: process.env.R2_ACCESS_KEY_ID!,\n *         secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,\n *       }),\n *       // or: storage: local({ directory: \"./uploads\", baseUrl: \"/_emdash/api/media/file\" }),\n *     }),\n *   ],\n * });\n * ```\n *\n * For Cloudflare R2 bindings, use `r2()` from `@premium-cms/cloudflare`.\n */\n\nimport type { StorageDescriptor, S3StorageConfig, LocalStorageConfig } from \"./types.js\";\n\n/**\n * S3-compatible storage adapter\n *\n * Works with AWS S3, Cloudflare R2 (via S3 API), MinIO, etc.\n *\n * Any field omitted here is resolved from the matching `S3_*` environment\n * variable when the container starts (`S3_ENDPOINT`, `S3_BUCKET`,\n * `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`, `S3_REGION`, `S3_PUBLIC_URL`).\n * Explicit values always take precedence over env vars.\n *\n * Note: env var resolution reads `process.env` on Node at runtime.\n * Workers users should continue passing explicit values to `s3({...})`.\n *\n * @example\n * ```ts\n * // All fields from env (container deployments)\n * storage: s3()\n *\n * // Mix: CDN from config, credentials from env\n * storage: s3({ publicUrl: \"https://cdn.example.com\" })\n *\n * // All explicit (unchanged from before)\n * storage: s3({\n *   endpoint: \"https://xxx.r2.cloudflarestorage.com\",\n *   bucket: \"media\",\n *   accessKeyId: process.env.R2_ACCESS_KEY_ID,\n *   secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,\n * })\n * ```\n */\nexport function s3(config: Partial<S3StorageConfig> = {}): StorageDescriptor {\n\treturn {\n\t\tentrypoint: \"@premium-cms/emdash/storage/s3\",\n\t\tconfig,\n\t};\n}\n\n/**\n * Local filesystem storage adapter\n *\n * For development and testing. Stores files in a local directory.\n * Does NOT support signed upload URLs.\n *\n * @example\n * ```ts\n * storage: local({\n *   directory: \"./uploads\",\n *   baseUrl: \"/_emdash/api/media/file\",\n * })\n * ```\n */\nexport function local(config: LocalStorageConfig): StorageDescriptor {\n\treturn {\n\t\tentrypoint: \"@premium-cms/emdash/storage/local\",\n\t\tconfig,\n\t};\n}\n","/**\n * Object-cache adapter functions (config time).\n *\n * These run in `astro.config.mjs` and return serializable\n * {@link ObjectCacheDescriptor}s. The backend is instantiated at runtime by\n * loading the descriptor's `entrypoint`.\n *\n * For Cloudflare KV, use `kvCache()` from `@premium-cms/cloudflare`.\n *\n * @example\n * ```ts\n * // astro.config.mjs (Node / local)\n * import emdash, { memoryCache } from \"@premium-cms/emdash/astro\";\n *\n * export default defineConfig({\n *   integrations: [emdash({ objectCache: memoryCache() })],\n * });\n * ```\n */\n\nimport type { ObjectCacheDescriptor, ObjectCacheRuntimeConfig } from \"../../object-cache/types.js\";\n\n/** Options for {@link memoryCache}. */\nexport interface MemoryCacheOptions extends ObjectCacheRuntimeConfig {\n\t/**\n\t * Soft cap on the number of cached keys per isolate before FIFO eviction.\n\t * @default 1000\n\t */\n\tmaxEntries?: number;\n}\n\n/**\n * In-isolate memory object cache.\n *\n * Caches query results across requests within a single isolate/process. On\n * Node (one long-lived process) this is a genuine cross-request cache; on\n * multi-isolate platforms (Cloudflare) prefer `kvCache()` so the cache is\n * shared. Useful for local development regardless of target.\n *\n * @example\n * ```ts\n * emdash({ objectCache: memoryCache({ defaultTtl: 600 }) })\n * ```\n */\nexport function memoryCache(options: MemoryCacheOptions = {}): ObjectCacheDescriptor {\n\treturn {\n\t\tentrypoint: \"@premium-cms/emdash/object-cache/memory\",\n\t\tconfig: { ...options },\n\t};\n}\n","import { randomUUID } from \"node:crypto\";\nimport {\n\tmkdir as nodeMkdir,\n\trename as nodeRename,\n\tunlink as nodeUnlink,\n\twriteFile as nodeWriteFile,\n} from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport type { MigrationManifestV1 } from \"./manifest.js\";\nimport { serializeMigrationManifest, validateMigrationManifest } from \"./manifest.js\";\n\nexport const MIGRATION_MANIFEST_PATH = \".emdash/migrations.json\";\n\nexport interface ManifestWriterFileSystem {\n\tmkdir(path: string, options: { recursive: true }): Promise<unknown>;\n\twriteFile(\n\t\tpath: string,\n\t\tdata: string,\n\t\toptions: { encoding: \"utf8\"; flag: \"wx\" },\n\t): Promise<unknown>;\n\trename(from: string, to: string): Promise<unknown>;\n\tunlink(path: string): Promise<unknown>;\n}\n\nconst nodeFileSystem: ManifestWriterFileSystem = {\n\tmkdir: (path, options) => nodeMkdir(path, options),\n\twriteFile: (path, data, options) => nodeWriteFile(path, data, options),\n\trename: (from, to) => nodeRename(from, to),\n\tunlink: (path) => nodeUnlink(path),\n};\n\nexport async function writeMigrationManifest(\n\tprojectRoot: string,\n\tmanifest: MigrationManifestV1,\n\tfileSystem: ManifestWriterFileSystem = nodeFileSystem,\n): Promise<string> {\n\tconst validated = await validateMigrationManifest(manifest);\n\tconst outputPath = join(projectRoot, MIGRATION_MANIFEST_PATH);\n\tconst outputDirectory = dirname(outputPath);\n\tawait fileSystem.mkdir(outputDirectory, { recursive: true });\n\n\tconst temporaryPath = join(\n\t\toutputDirectory,\n\t\t`.migrations.json.${process.pid}.${randomUUID()}.tmp`,\n\t);\n\tlet temporaryFileMayExist = false;\n\ttry {\n\t\ttemporaryFileMayExist = true;\n\t\tawait fileSystem.writeFile(temporaryPath, serializeMigrationManifest(validated), {\n\t\t\tencoding: \"utf8\",\n\t\t\tflag: \"wx\",\n\t\t});\n\t\tawait fileSystem.rename(temporaryPath, outputPath);\n\t\ttemporaryFileMayExist = false;\n\t\treturn outputPath;\n\t} catch (error) {\n\t\tif (temporaryFileMayExist) {\n\t\t\tawait fileSystem.unlink(temporaryPath).catch(() => undefined);\n\t\t}\n\t\tthrow error;\n\t}\n}\n","/**\n * EmDash Noto Sans font provider\n *\n * A custom Astro font provider that wraps Google Fonts to resolve\n * multiple Noto Sans families (Latin, Arabic, JP, etc.) under a\n * single logical font entry. This lets all @font-face blocks share\n * the same font-family name, so the browser picks the right file\n * per character via unicode-range.\n *\n * Without this, registering \"Noto Sans\" and \"Noto Sans Arabic\" as\n * separate font entries on the same cssVariable triggers an Astro\n * warning and the last entry overwrites the first.\n */\n\nimport { fontProviders } from \"astro/config\";\n\n/**\n * All subset names used by Google Fonts CSS responses.\n * Passed when resolving extra script families so the unifont\n * provider doesn't filter out any faces.\n */\nconst ALL_GOOGLE_SUBSETS = [\n\t\"arabic\",\n\t\"armenian\",\n\t\"bengali\",\n\t\"chinese-simplified\",\n\t\"chinese-traditional\",\n\t\"chinese-hongkong\",\n\t\"cyrillic\",\n\t\"cyrillic-ext\",\n\t\"devanagari\",\n\t\"ethiopic\",\n\t\"farsi\",\n\t\"georgian\",\n\t\"greek\",\n\t\"greek-ext\",\n\t\"gujarati\",\n\t\"gurmukhi\",\n\t\"hebrew\",\n\t\"japanese\",\n\t\"kannada\",\n\t\"khmer\",\n\t\"korean\",\n\t\"lao\",\n\t\"latin\",\n\t\"latin-ext\",\n\t\"malayalam\",\n\t\"math\",\n\t\"myanmar\",\n\t\"oriya\",\n\t\"sinhala\",\n\t\"symbols\",\n\t\"tamil\",\n\t\"telugu\",\n\t\"thai\",\n\t\"tibetan\",\n\t\"vietnamese\",\n];\n\n/**\n * Known Noto Sans and Sans script families on Google Fonts.\n * Maps user-friendly script names to Google Fonts family names.\n */\nconst NOTO_SCRIPT_FAMILIES: Record<string, string> = {\n\tarabic: \"Noto Sans Arabic\",\n\tarmenian: \"Noto Sans Armenian\",\n\tbengali: \"Noto Sans Bengali\",\n\t\"chinese-simplified\": \"Noto Sans SC\",\n\t\"chinese-traditional\": \"Noto Sans TC\",\n\t\"chinese-hongkong\": \"Noto Sans HK\",\n\tdevanagari: \"Noto Sans Devanagari\",\n\tethiopic: \"Noto Sans Ethiopic\",\n\tfarsi: \"Vazirmatn\",\n\tgeorgian: \"Noto Sans Georgian\",\n\tgujarati: \"Noto Sans Gujarati\",\n\tgurmukhi: \"Noto Sans Gurmukhi\",\n\thebrew: \"Noto Sans Hebrew\",\n\tjapanese: \"Noto Sans JP\",\n\tkannada: \"Noto Sans Kannada\",\n\tkhmer: \"Noto Sans Khmer\",\n\tkorean: \"Noto Sans KR\",\n\tlao: \"Noto Sans Lao\",\n\tmalayalam: \"Noto Sans Malayalam\",\n\tmyanmar: \"Noto Sans Myanmar\",\n\toriya: \"Noto Sans Oriya\",\n\tsinhala: \"Noto Sans Sinhala\",\n\ttamil: \"Noto Sans Tamil\",\n\ttelugu: \"Noto Sans Telugu\",\n\tthai: \"Noto Sans Thai\",\n\ttibetan: \"Noto Sans Tibetan\",\n};\n\nexport interface NotoSansProviderOptions {\n\t/**\n\t * Additional Noto Sans script families to include.\n\t * Use script names like \"arabic\", \"japanese\", \"chinese-simplified\".\n\t *\n\t * @see {@link NOTO_SCRIPT_FAMILIES} for the full list of supported scripts.\n\t */\n\tscripts?: string[];\n}\n\n// Use ReturnType to get the provider type without importing it directly.\n// The Astro FontProvider type is not part of the public API surface.\ntype GoogleProvider = ReturnType<typeof fontProviders.google>;\n\n/**\n * Create a font provider that resolves Noto Sans plus additional\n * script-specific Noto families from Google Fonts, all under one\n * font-family name.\n */\nexport function notoSans(options?: NotoSansProviderOptions): GoogleProvider {\n\t// Create a single Google provider instance to share initialization\n\tconst googleProvider = fontProviders.google();\n\n\treturn {\n\t\tname: \"emdash-noto\",\n\t\tasync init(context) {\n\t\t\tawait googleProvider.init?.(context);\n\t\t},\n\t\tasync resolveFont(resolveFontOptions) {\n\t\t\t// Resolve the base Noto Sans (Latin, Cyrillic, Greek, etc.)\n\t\t\tconst base = await googleProvider.resolveFont(resolveFontOptions);\n\t\t\tconst baseFonts = base?.fonts ?? [];\n\n\t\t\tif (!options?.scripts?.length) {\n\t\t\t\treturn base;\n\t\t\t}\n\n\t\t\t// Collect subset names already covered by the base font so we\n\t\t\t// can filter out duplicate faces from extra script families.\n\t\t\t// e.g. Noto Sans Arabic includes latin/latin-ext faces that\n\t\t\t// would otherwise override the base Noto Sans latin faces.\n\t\t\tconst baseSubsets = new Set(baseFonts.map((f) => f.meta?.subset).filter(Boolean));\n\n\t\t\t// Resolve additional script families\n\t\t\tconst extraFonts = await Promise.all(\n\t\t\t\toptions.scripts.map(async (script) => {\n\t\t\t\t\tconst family = NOTO_SCRIPT_FAMILIES[script];\n\t\t\t\t\tif (!family) {\n\t\t\t\t\t\t// Silently skip subset names that are already covered\n\t\t\t\t\t\t// by the base Noto Sans font (latin, cyrillic, etc.)\n\t\t\t\t\t\tif (ALL_GOOGLE_SUBSETS.includes(script)) {\n\t\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`[emdash] Unknown Noto Sans script \"${script}\". ` +\n\t\t\t\t\t\t\t\t`Available: ${Object.keys(NOTO_SCRIPT_FAMILIES).join(\", \")}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\t\t\t\t\treturn googleProvider.resolveFont({\n\t\t\t\t\t\t...resolveFontOptions,\n\t\t\t\t\t\tfamilyName: family,\n\t\t\t\t\t\t// Pass all known subset names so the unifont provider\n\t\t\t\t\t\t// doesn't filter out any faces. Each script family\n\t\t\t\t\t\t// only returns faces for its own subsets anyway.\n\t\t\t\t\t\tsubsets: ALL_GOOGLE_SUBSETS,\n\t\t\t\t\t});\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\t// Merge, dropping faces from extra fonts that duplicate base subsets\n\t\t\tconst extraFaces = extraFonts.flatMap((r) =>\n\t\t\t\t(r?.fonts ?? []).filter((f) => !f.meta?.subset || !baseSubsets.has(f.meta.subset)),\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tfonts: [...baseFonts, ...extraFaces],\n\t\t\t};\n\t\t},\n\t};\n}\n\n/** Get the list of available Noto Sans script names */\nexport function getAvailableNotoScripts(): string[] {\n\treturn Object.keys(NOTO_SCRIPT_FAMILIES);\n}\n","/**\n * Compiled route artifact naming -- single source of truth.\n *\n * rolldown reserves `[name]`, `[hash]`, `[ext]` (and more) as output-filename\n * placeholders, so compiled route files cannot keep Astro's literal\n * `[param]` dynamic-segment filenames -- a path containing `[name]` would be\n * substituted by the bundler. This function defines the safe artifact form.\n *\n * It is imported by BOTH the build (`tsdown.config.ts` `entryFileNames`) and\n * the route injector (`resolveRoute`, which resolves `emdash/routes/*`).\n * They must stay in lockstep: change the scheme here and both follow.\n *\n * `[` and `]` -> `_` (e.g. `[collection]` -> `_collection_`,\n * `[...path]` -> `_...path_`). The Astro route URL pattern is set explicitly\n * at injection time, so the artifact filename never affects routing.\n */\nexport function routeArtifactName(srcRelativePathNoExt: string): string {\n\treturn srcRelativePathNoExt.replaceAll(\"[\", \"_\").replaceAll(\"]\", \"_\");\n}\n","/**\n * Route Injection\n *\n * Defines and injects all EmDash routes into the Astro application.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { routeArtifactName } from \"./route-naming.js\";\n\nconst TS_EXT = /\\.tsx?$/;\n\n/**\n * Resolve path to a route file in the package\n * Uses Node.js APIs - only call at build time\n */\nfunction resolveRoute(route: string): string {\n\t// Lazy initialization to avoid running Node.js code at import time\n\t// This prevents issues when the module is bundled for Cloudflare Workers\n\tconst require = createRequire(import.meta.url);\n\tconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n\t// .astro routes ship as source (the consumer's Astro build processes them);\n\t// .ts/.tsx routes are compiled, exported extensionless via emdash/routes/*.\n\tconst isAstro = route.endsWith(\".astro\");\n\tconst specifier = isAstro ? route : routeArtifactName(route.replace(TS_EXT, \"\"));\n\n\ttry {\n\t\t// Try to resolve as package export\n\t\treturn require.resolve(`@premium-cms/emdash/routes/${specifier}`);\n\t} catch {\n\t\t// Fallback for development (e.g. dist not yet built).\n\t\treturn isAstro\n\t\t\t? resolve(__dirname, \"../routes\", route)\n\t\t\t: resolve(__dirname, \"../routes\", `${specifier}.mjs`);\n\t}\n}\n\n/** Route injection function type */\ntype InjectRoute = (route: { pattern: string; entrypoint: string }) => void;\n\ninterface InjectCoreRoutesOptions {\n\tsrcDir?: URL;\n}\n\nconst ROUTE_OVERRIDE_EXTENSIONS = [\n\t\".astro\",\n\t\".js\",\n\t\".ts\",\n\t\".jsx\",\n\t\".tsx\",\n\t\".mjs\",\n\t\".mts\",\n\t\".md\",\n\t\".mdx\",\n\t\".html\",\n];\n\n/**\n * Detect whether the host site defines its own root-level public route file.\n */\nexport function hasUserDefinedPublicRoute(srcDir: URL, basename: string): boolean {\n\tconst srcDirPath = fileURLToPath(srcDir);\n\treturn ROUTE_OVERRIDE_EXTENSIONS.some(\n\t\t(extension) =>\n\t\t\texistsSync(resolve(srcDirPath, \"pages\", `${basename}${extension}`)) ||\n\t\t\texistsSync(resolve(srcDirPath, \"pages\", basename, `index${extension}`)),\n\t);\n}\n\n/**\n * Injects all core EmDash routes.\n */\nexport function injectCoreRoutes(\n\tinjectRoute: InjectRoute,\n\toptions: InjectCoreRoutesOptions = {},\n): void {\n\t// Inject admin shell route\n\tinjectRoute({\n\t\tpattern: \"/_emdash/admin/[...path]\",\n\t\tentrypoint: resolveRoute(\"admin.astro\"),\n\t});\n\n\t// Inject API routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/manifest\",\n\t\tentrypoint: resolveRoute(\"api/manifest.ts\"),\n\t});\n\n\t// Auth mode endpoint (public — used by the login page to pick the right UI)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/mode\",\n\t\tentrypoint: resolveRoute(\"api/auth/mode.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/dashboard\",\n\t\tentrypoint: resolveRoute(\"api/dashboard.ts\"),\n\t});\n\n\t// Billing + immutable log (recursive-hosting cost-plus credits)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/billing\",\n\t\tentrypoint: resolveRoute(\"api/billing.ts\"),\n\t});\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/billing/topup\",\n\t\tentrypoint: resolveRoute(\"api/billing/topup.ts\"),\n\t});\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/immutable-log\",\n\t\tentrypoint: resolveRoute(\"api/immutable-log.ts\"),\n\t});\n\n\t// Color schemes (tweakcn-adapted palettes)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/color-schemes/marketplace\",\n\t\tentrypoint: resolveRoute(\"api/color-schemes/marketplace.ts\"),\n\t});\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/color-schemes/marketplace/[id]\",\n\t\tentrypoint: resolveRoute(\"api/color-schemes/marketplace/[id].ts\"),\n\t});\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/color-schemes/apply\",\n\t\tentrypoint: resolveRoute(\"api/color-schemes/apply.ts\"),\n\t});\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/color-schemes/current\",\n\t\tentrypoint: resolveRoute(\"api/color-schemes/current.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]/[id]\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/[id].ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]/[id]/revisions\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/[id]/revisions.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]/[id]/preview-url\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/[id]/preview-url.ts\"),\n\t});\n\n\t// Content authors (for the admin author filter)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]/authors\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/authors.ts\"),\n\t});\n\n\t// Trash/restore routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]/trash\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/trash.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]/[id]/restore\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/[id]/restore.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]/[id]/permanent\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/[id]/permanent.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]/[id]/duplicate\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/[id]/duplicate.ts\"),\n\t});\n\n\t// Publishing routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]/[id]/publish\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/[id]/publish.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]/[id]/unpublish\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/[id]/unpublish.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]/[id]/discard-draft\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/[id]/discard-draft.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]/[id]/compare\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/[id]/compare.ts\"),\n\t});\n\n\t// i18n translation routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]/[id]/translations\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/[id]/translations.ts\"),\n\t});\n\n\t// Scheduled publishing routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]/[id]/schedule\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/[id]/schedule.ts\"),\n\t});\n\n\t// Revision management routes (for restore, etc.)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/revisions/[revisionId]\",\n\t\tentrypoint: resolveRoute(\"api/revisions/[revisionId]/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/revisions/[revisionId]/restore\",\n\t\tentrypoint: resolveRoute(\"api/revisions/[revisionId]/restore.ts\"),\n\t});\n\n\t// Media API routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/media\",\n\t\tentrypoint: resolveRoute(\"api/media.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/media/upload-url\",\n\t\tentrypoint: resolveRoute(\"api/media/upload-url.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/media/file/[...key]\",\n\t\tentrypoint: resolveRoute(\"api/media/file/[...key].ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/media/[id]\",\n\t\tentrypoint: resolveRoute(\"api/media/[id].ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/media/[id]/usage\",\n\t\tentrypoint: resolveRoute(\"api/media/[id]/usage.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/media/[id]/confirm\",\n\t\tentrypoint: resolveRoute(\"api/media/[id]/confirm.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/media/[id]/upload\",\n\t\tentrypoint: resolveRoute(\"api/media/[id]/upload.ts\"),\n\t});\n\n\t// Media provider routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/media/providers\",\n\t\tentrypoint: resolveRoute(\"api/media/providers/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/media/providers/[providerId]\",\n\t\tentrypoint: resolveRoute(\"api/media/providers/[providerId]/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/media/providers/[providerId]/[itemId]\",\n\t\tentrypoint: resolveRoute(\"api/media/providers/[providerId]/[itemId].ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/media-usage/repair\",\n\t\tentrypoint: resolveRoute(\"api/admin/media-usage/repair.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/media-usage/work\",\n\t\tentrypoint: resolveRoute(\"api/admin/media-usage/work/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/media-usage/work/retry\",\n\t\tentrypoint: resolveRoute(\"api/admin/media-usage/work/retry.ts\"),\n\t});\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/media-usage/collection-deletions\",\n\t\tentrypoint: resolveRoute(\"api/admin/media-usage/collection-deletions/index.ts\"),\n\t});\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/media-usage/collection-deletions/retry\",\n\t\tentrypoint: resolveRoute(\"api/admin/media-usage/collection-deletions/retry.ts\"),\n\t});\n\n\t// Import API routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/import/probe\",\n\t\tentrypoint: resolveRoute(\"api/import/probe.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/import/wordpress/analyze\",\n\t\tentrypoint: resolveRoute(\"api/import/wordpress/analyze.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/import/wordpress/prepare\",\n\t\tentrypoint: resolveRoute(\"api/import/wordpress/prepare.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/import/wordpress/execute\",\n\t\tentrypoint: resolveRoute(\"api/import/wordpress/execute.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/import/wordpress/media\",\n\t\tentrypoint: resolveRoute(\"api/import/wordpress/media.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/import/wordpress/rewrite-urls\",\n\t\tentrypoint: resolveRoute(\"api/import/wordpress/rewrite-urls.ts\"),\n\t});\n\n\t// WordPress Plugin (EmDash Exporter) direct import routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/import/wordpress-plugin/analyze\",\n\t\tentrypoint: resolveRoute(\"api/import/wordpress-plugin/analyze.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/import/wordpress-plugin/execute\",\n\t\tentrypoint: resolveRoute(\"api/import/wordpress-plugin/execute.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/import/wordpress-plugin/callback\",\n\t\tentrypoint: resolveRoute(\"api/import/wordpress-plugin/callback.ts\"),\n\t});\n\n\t// Schema API routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/schema\",\n\t\tentrypoint: resolveRoute(\"api/schema/index.ts\"),\n\t});\n\n\t// Typegen endpoint (dev-only)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/typegen\",\n\t\tentrypoint: resolveRoute(\"api/typegen.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/schema/collections\",\n\t\tentrypoint: resolveRoute(\"api/schema/collections/index.ts\"),\n\t});\n\n\t// Order matters: the static `reorder` route must precede the dynamic\n\t// `[slug]` route so Astro's resolver dispatches POST\n\t// /schema/collections/reorder to the reorder handler instead of treating\n\t// \"reorder\" as a collection slug.\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/schema/collections/reorder\",\n\t\tentrypoint: resolveRoute(\"api/schema/collections/reorder.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/schema/collections/[slug]\",\n\t\tentrypoint: resolveRoute(\"api/schema/collections/[slug]/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/schema/collections/[slug]/fields\",\n\t\tentrypoint: resolveRoute(\"api/schema/collections/[slug]/fields/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/schema/collections/[slug]/fields/reorder\",\n\t\tentrypoint: resolveRoute(\"api/schema/collections/[slug]/fields/reorder.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/schema/collections/[slug]/fields/[fieldSlug]\",\n\t\tentrypoint: resolveRoute(\"api/schema/collections/[slug]/fields/[fieldSlug].ts\"),\n\t});\n\n\t// Orphaned tables discovery\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/schema/orphans\",\n\t\tentrypoint: resolveRoute(\"api/schema/orphans/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/schema/orphans/[slug]\",\n\t\tentrypoint: resolveRoute(\"api/schema/orphans/[slug].ts\"),\n\t});\n\n\t// Site settings route\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/settings\",\n\t\tentrypoint: resolveRoute(\"api/settings.ts\"),\n\t});\n\n\t// Email settings route\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/settings/email\",\n\t\tentrypoint: resolveRoute(\"api/settings/email.ts\"),\n\t});\n\n\t// Custom-domain route (managed instances)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/settings/custom-domain\",\n\t\tentrypoint: resolveRoute(\"api/settings/custom-domain.ts\"),\n\t});\n\n\t// The frontend service account's token + backend URL (admins only), and its rotation\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/settings/frontend-token\",\n\t\tentrypoint: resolveRoute(\"api/settings/frontend-token.ts\"),\n\t});\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/settings/frontend-token/rotate\",\n\t\tentrypoint: resolveRoute(\"api/settings/frontend-token/rotate.ts\"),\n\t});\n\n\t// Create the custom-domain DNS records at the owner's provider\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/settings/custom-domain/dns\",\n\t\tentrypoint: resolveRoute(\"api/settings/custom-domain/dns.ts\"),\n\t});\n\n\t// Re-apply the bundled theme seed (managed instances)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/settings/reseed\",\n\t\tentrypoint: resolveRoute(\"api/settings/reseed.ts\"),\n\t});\n\n\t// Seed export / apply (theme publishing + copying, managed instances)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/settings/seed/export\",\n\t\tentrypoint: resolveRoute(\"api/settings/seed/export.ts\"),\n\t});\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/settings/seed/apply\",\n\t\tentrypoint: resolveRoute(\"api/settings/seed/apply.ts\"),\n\t});\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/settings/seed/apply-repo\",\n\t\tentrypoint: resolveRoute(\"api/settings/seed/apply-repo.ts\"),\n\t});\n\n\t// Create + fork a plugin repo through the hosting platform\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins/marketplace/fork\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/marketplace/fork.ts\"),\n\t});\n\n\t// Backup routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/settings/backups\",\n\t\tentrypoint: resolveRoute(\"api/settings/backups/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/settings/backups/export\",\n\t\tentrypoint: resolveRoute(\"api/settings/backups/export.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/settings/backups/archives\",\n\t\tentrypoint: resolveRoute(\"api/settings/backups/archives/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/settings/backups/archives/[name]\",\n\t\tentrypoint: resolveRoute(\"api/settings/backups/archives/[name].ts\"),\n\t});\n\n\t// Snapshot route (for DO preview database population)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/snapshot\",\n\t\tentrypoint: resolveRoute(\"api/snapshot.ts\"),\n\t});\n\n\t// Taxonomy API routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/taxonomies\",\n\t\tentrypoint: resolveRoute(\"api/taxonomies/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/taxonomies/[name]\",\n\t\tentrypoint: resolveRoute(\"api/taxonomies/[name].ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/taxonomies/[name]/translations\",\n\t\tentrypoint: resolveRoute(\"api/taxonomies/[name]/translations.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/taxonomies/[name]/reorder\",\n\t\tentrypoint: resolveRoute(\"api/taxonomies/[name]/reorder.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/taxonomies/[name]/terms\",\n\t\tentrypoint: resolveRoute(\"api/taxonomies/[name]/terms/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/taxonomies/[name]/terms/[slug]\",\n\t\tentrypoint: resolveRoute(\"api/taxonomies/[name]/terms/[slug].ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/taxonomies/[name]/terms/[slug]/translations\",\n\t\tentrypoint: resolveRoute(\"api/taxonomies/[name]/terms/[slug]/translations.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/content/[collection]/[id]/terms/[taxonomy]\",\n\t\tentrypoint: resolveRoute(\"api/content/[collection]/[id]/terms/[taxonomy].ts\"),\n\t});\n\n\t// Plugin management routes (under /admin to avoid conflict with plugin API routes)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins/[id]\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/[id]/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins/[id]/enable\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/[id]/enable.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins/[id]/disable\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/[id]/disable.ts\"),\n\t});\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins/[id]/mcp\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/[id]/mcp.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins/[id]/settings\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/[id]/settings.ts\"),\n\t});\n\n\t// Marketplace plugin routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins/marketplace\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/marketplace/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins/marketplace/[id]\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/marketplace/[id]/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins/marketplace/[id]/icon\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/marketplace/[id]/icon.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins/marketplace/[id]/install\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/marketplace/[id]/install.ts\"),\n\t});\n\n\t// Experimental registry routes (see RFC 0001)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins/registry/install\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/registry/install.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins/registry/artifact\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/registry/artifact.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins/[id]/update\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/[id]/update.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins/[id]/uninstall\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/[id]/uninstall.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/plugins/updates\",\n\t\tentrypoint: resolveRoute(\"api/admin/plugins/updates.ts\"),\n\t});\n\n\t// Exclusive hooks admin routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/hooks/exclusive\",\n\t\tentrypoint: resolveRoute(\"api/admin/hooks/exclusive/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/hooks/exclusive/[hookName]\",\n\t\tentrypoint: resolveRoute(\"api/admin/hooks/exclusive/[hookName].ts\"),\n\t});\n\n\t// Theme marketplace routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/themes/marketplace\",\n\t\tentrypoint: resolveRoute(\"api/admin/themes/marketplace/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/themes/marketplace/[id]\",\n\t\tentrypoint: resolveRoute(\"api/admin/themes/marketplace/[id]/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/themes/marketplace/[id]/thumbnail\",\n\t\tentrypoint: resolveRoute(\"api/admin/themes/marketplace/[id]/thumbnail.ts\"),\n\t});\n\n\t// Theme preview signing (local, not proxied)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/themes/preview\",\n\t\tentrypoint: resolveRoute(\"api/themes/preview.ts\"),\n\t});\n\n\t// User management routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/users\",\n\t\tentrypoint: resolveRoute(\"api/admin/users/index.ts\"),\n\t});\n\n\t// Bylines routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/bylines\",\n\t\tentrypoint: resolveRoute(\"api/admin/bylines/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/bylines/[id]\",\n\t\tentrypoint: resolveRoute(\"api/admin/bylines/[id]/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/bylines/[id]/translations\",\n\t\tentrypoint: resolveRoute(\"api/admin/bylines/[id]/translations.ts\"),\n\t});\n\n\t// Byline custom-field schema routes (Discussion #1174, Phase 4).\n\t// Order matters: the static `reorder` route must precede the dynamic\n\t// `[slug]` route so Astro's resolver dispatches POST /byline-fields/reorder\n\t// to the reorder handler instead of treating \"reorder\" as a slug. The\n\t// `reorder` slug is also reserved at the data layer\n\t// (RESERVED_BYLINE_FIELD_SLUGS) so the registry rejects field creation\n\t// with that name — defence in depth.\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/byline-fields\",\n\t\tentrypoint: resolveRoute(\"api/admin/byline-fields/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/byline-fields/reorder\",\n\t\tentrypoint: resolveRoute(\"api/admin/byline-fields/reorder.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/byline-fields/[slug]\",\n\t\tentrypoint: resolveRoute(\"api/admin/byline-fields/[slug].ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/byline-fields/[slug]/usage\",\n\t\tentrypoint: resolveRoute(\"api/admin/byline-fields/[slug]/usage.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/users/[id]\",\n\t\tentrypoint: resolveRoute(\"api/admin/users/[id]/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/users/[id]/disable\",\n\t\tentrypoint: resolveRoute(\"api/admin/users/[id]/disable.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/users/[id]/enable\",\n\t\tentrypoint: resolveRoute(\"api/admin/users/[id]/enable.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/users/[id]/send-recovery\",\n\t\tentrypoint: resolveRoute(\"api/admin/users/[id]/send-recovery.ts\"),\n\t});\n\n\t// API token admin routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/api-tokens\",\n\t\tentrypoint: resolveRoute(\"api/admin/api-tokens/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/api-tokens/[id]\",\n\t\tentrypoint: resolveRoute(\"api/admin/api-tokens/[id].ts\"),\n\t});\n\n\t// Authorization model: roles → policies → routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/roles\",\n\t\tentrypoint: resolveRoute(\"api/admin/roles/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/roles/[id]\",\n\t\tentrypoint: resolveRoute(\"api/admin/roles/[id].ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/policies\",\n\t\tentrypoint: resolveRoute(\"api/admin/policies/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/policies/[id]\",\n\t\tentrypoint: resolveRoute(\"api/admin/policies/[id].ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/authz/catalog\",\n\t\tentrypoint: resolveRoute(\"api/admin/authz/catalog.ts\"),\n\t});\n\n\t// OAuth client admin routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/oauth-clients\",\n\t\tentrypoint: resolveRoute(\"api/admin/oauth-clients/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/oauth-clients/[id]\",\n\t\tentrypoint: resolveRoute(\"api/admin/oauth-clients/[id].ts\"),\n\t});\n\n\t// OAuth Device Flow routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/oauth/device/code\",\n\t\tentrypoint: resolveRoute(\"api/oauth/device/code.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/oauth/device/token\",\n\t\tentrypoint: resolveRoute(\"api/oauth/device/token.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/oauth/device/authorize\",\n\t\tentrypoint: resolveRoute(\"api/oauth/device/authorize.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/oauth/token/refresh\",\n\t\tentrypoint: resolveRoute(\"api/oauth/token/refresh.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/oauth/token/revoke\",\n\t\tentrypoint: resolveRoute(\"api/oauth/token/revoke.ts\"),\n\t});\n\n\t// Auth discovery endpoint\n\tinjectRoute({\n\t\tpattern: \"/_emdash/.well-known/auth\",\n\t\tentrypoint: resolveRoute(\"api/well-known/auth.ts\"),\n\t});\n\n\t// OAuth 2.1 Authorization Code flow routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/oauth/token\",\n\t\tentrypoint: resolveRoute(\"api/oauth/token.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/oauth/authorize\",\n\t\tentrypoint: resolveRoute(\"api/oauth/authorize.ts\"),\n\t});\n\n\t// OAuth discovery endpoints (RFC 9728, RFC 8414)\n\tinjectRoute({\n\t\tpattern: \"/.well-known/oauth-protected-resource\",\n\t\tentrypoint: resolveRoute(\"api/well-known/oauth-protected-resource.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/.well-known/oauth-authorization-server/_emdash\",\n\t\tentrypoint: resolveRoute(\"api/well-known/oauth-authorization-server.ts\"),\n\t});\n\n\t// RFC 7591 Dynamic Client Registration\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/oauth/register\",\n\t\tentrypoint: resolveRoute(\"api/oauth/register.ts\"),\n\t});\n\n\t// Plugin-defined API routes\n\t// All plugin routes are handled by a single catch-all handler\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/plugins/[pluginId]/[...path]\",\n\t\tentrypoint: resolveRoute(\"api/plugins/[pluginId]/[...path].ts\"),\n\t});\n\n\t// Menu API routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/menus\",\n\t\tentrypoint: resolveRoute(\"api/menus/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/menus/[name]\",\n\t\tentrypoint: resolveRoute(\"api/menus/[name].ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/menus/[name]/items\",\n\t\tentrypoint: resolveRoute(\"api/menus/[name]/items.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/menus/[name]/items/[id]\",\n\t\tentrypoint: resolveRoute(\"api/menus/[name]/items/[id].ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/menus/[name]/reorder\",\n\t\tentrypoint: resolveRoute(\"api/menus/[name]/reorder.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/menus/[name]/translations\",\n\t\tentrypoint: resolveRoute(\"api/menus/[name]/translations.ts\"),\n\t});\n\n\t// Widget area routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/widget-areas\",\n\t\tentrypoint: resolveRoute(\"api/widget-areas/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/widget-components\",\n\t\tentrypoint: resolveRoute(\"api/widget-components.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/widget-areas/[name]\",\n\t\tentrypoint: resolveRoute(\"api/widget-areas/[name].ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/widget-areas/[name]/widgets\",\n\t\tentrypoint: resolveRoute(\"api/widget-areas/[name]/widgets.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/widget-areas/[name]/widgets/[id]\",\n\t\tentrypoint: resolveRoute(\"api/widget-areas/[name]/widgets/[id].ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/widget-areas/[name]/reorder\",\n\t\tentrypoint: resolveRoute(\"api/widget-areas/[name]/reorder.ts\"),\n\t});\n\n\t// Section routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/sections\",\n\t\tentrypoint: resolveRoute(\"api/sections/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/sections/[slug]\",\n\t\tentrypoint: resolveRoute(\"api/sections/[slug].ts\"),\n\t});\n\n\t// Redirect routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/redirects\",\n\t\tentrypoint: resolveRoute(\"api/redirects/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/redirects/404s/summary\",\n\t\tentrypoint: resolveRoute(\"api/redirects/404s/summary.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/redirects/404s\",\n\t\tentrypoint: resolveRoute(\"api/redirects/404s/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/redirects/[id]\",\n\t\tentrypoint: resolveRoute(\"api/redirects/[id].ts\"),\n\t});\n\n\t// Search routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/search\",\n\t\tentrypoint: resolveRoute(\"api/search/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/search/suggest\",\n\t\tentrypoint: resolveRoute(\"api/search/suggest.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/search/stats\",\n\t\tentrypoint: resolveRoute(\"api/search/stats.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/search/rebuild\",\n\t\tentrypoint: resolveRoute(\"api/search/rebuild.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/search/enable\",\n\t\tentrypoint: resolveRoute(\"api/search/enable.ts\"),\n\t});\n\n\t// Comment routes (public)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/comments/[collection]/[contentId]\",\n\t\tentrypoint: resolveRoute(\"api/comments/[collection]/[contentId]/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/comments/[collection]/[contentId]/reactions\",\n\t\tentrypoint: resolveRoute(\"api/comments/[collection]/[contentId]/reactions.ts\"),\n\t});\n\n\t// Comment routes (admin)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/comments\",\n\t\tentrypoint: resolveRoute(\"api/admin/comments/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/comments/counts\",\n\t\tentrypoint: resolveRoute(\"api/admin/comments/counts.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/comments/bulk\",\n\t\tentrypoint: resolveRoute(\"api/admin/comments/bulk.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/comments/[id]/status\",\n\t\tentrypoint: resolveRoute(\"api/admin/comments/[id]/status.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/comments/[id]\",\n\t\tentrypoint: resolveRoute(\"api/admin/comments/[id].ts\"),\n\t});\n\n\t// SEO routes (public, at site root)\n\tif (!options.srcDir || !hasUserDefinedPublicRoute(options.srcDir, \"sitemap.xml\")) {\n\t\tinjectRoute({\n\t\t\tpattern: \"/sitemap.xml\",\n\t\t\tentrypoint: resolveRoute(\"sitemap.xml.ts\"),\n\t\t});\n\t}\n\n\tif (!options.srcDir || !hasUserDefinedPublicRoute(options.srcDir, \"sitemap-[collection].xml\")) {\n\t\tinjectRoute({\n\t\t\tpattern: \"/sitemap-[collection].xml\",\n\t\t\tentrypoint: resolveRoute(\"sitemap-[collection].xml.ts\"),\n\t\t});\n\t}\n\n\tif (!options.srcDir || !hasUserDefinedPublicRoute(options.srcDir, \"robots.txt\")) {\n\t\tinjectRoute({\n\t\t\tpattern: \"/robots.txt\",\n\t\t\tentrypoint: resolveRoute(\"robots.txt.ts\"),\n\t\t});\n\t}\n\n\t// Setup wizard API routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/setup/status\",\n\t\tentrypoint: resolveRoute(\"api/setup/status.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/setup\",\n\t\tentrypoint: resolveRoute(\"api/setup/index.ts\"),\n\t});\n\n\t// Auth API routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/setup/admin\",\n\t\tentrypoint: resolveRoute(\"api/setup/admin.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/setup/admin/verify\",\n\t\tentrypoint: resolveRoute(\"api/setup/admin-verify.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/setup/dev-bypass\",\n\t\tentrypoint: resolveRoute(\"api/setup/dev-bypass.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/setup/dev-reset\",\n\t\tentrypoint: resolveRoute(\"api/setup/dev-reset.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/dev/emails\",\n\t\tentrypoint: resolveRoute(\"api/dev/emails.ts\"),\n\t});\n\n\t// Current user endpoint (always available)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/me\",\n\t\tentrypoint: resolveRoute(\"api/auth/me.ts\"),\n\t});\n\n\t// Short-lived personal tokens for browser-side helpers (session-only)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/session-tokens\",\n\t\tentrypoint: resolveRoute(\"api/auth/session-tokens/index.ts\"),\n\t});\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/session-tokens/[id]\",\n\t\tentrypoint: resolveRoute(\"api/auth/session-tokens/[id].ts\"),\n\t});\n\n\t// Buttons plugins add to the visual-editing toolbar (session-only)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/toolbar/extensions\",\n\t\tentrypoint: resolveRoute(\"api/toolbar/extensions.ts\"),\n\t});\n\n\t// Logout is always available (though behavior differs by auth mode)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/logout\",\n\t\tentrypoint: resolveRoute(\"api/auth/logout.ts\"),\n\t});\n}\n\n/**\n * Injects the MCP (Model Context Protocol) server route.\n * Only injected when `mcp: true` is set in the EmDash config.\n */\nexport function injectMcpRoute(injectRoute: InjectRoute): void {\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/mcp\",\n\t\tentrypoint: resolveRoute(\"api/mcp.ts\"),\n\t});\n}\n\n/**\n * Injects routes from pluggable auth providers.\n *\n * Each provider declares the routes it needs in its `AuthProviderDescriptor.routes` array.\n * Routes are injected at build time so Vite can bundle them.\n */\nexport function injectAuthProviderRoutes(\n\tinjectRoute: InjectRoute,\n\tproviders: Array<{ routes?: Array<{ pattern: string; entrypoint: string }> }>,\n): void {\n\tfor (const provider of providers) {\n\t\tif (provider.routes) {\n\t\t\tfor (const route of provider.routes) {\n\t\t\t\tinjectRoute({\n\t\t\t\t\tpattern: route.pattern,\n\t\t\t\t\tentrypoint: route.entrypoint,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Injects passkey/oauth/magic-link auth routes.\n * Only used when NOT using external auth.\n */\nexport function injectBuiltinAuthRoutes(injectRoute: InjectRoute): void {\n\t// Passkey authentication routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/passkey/options\",\n\t\tentrypoint: resolveRoute(\"api/auth/passkey/options.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/passkey/verify\",\n\t\tentrypoint: resolveRoute(\"api/auth/passkey/verify.ts\"),\n\t});\n\n\t// Passkey management routes (authenticated users)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/passkey\",\n\t\tentrypoint: resolveRoute(\"api/auth/passkey/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/passkey/register/options\",\n\t\tentrypoint: resolveRoute(\"api/auth/passkey/register/options.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/passkey/register/verify\",\n\t\tentrypoint: resolveRoute(\"api/auth/passkey/register/verify.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/passkey/[id]\",\n\t\tentrypoint: resolveRoute(\"api/auth/passkey/[id].ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/dev-bypass\",\n\t\tentrypoint: resolveRoute(\"api/auth/dev-bypass.ts\"),\n\t});\n\n\t// Invite routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/invite\",\n\t\tentrypoint: resolveRoute(\"api/auth/invite/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/invite/accept\",\n\t\tentrypoint: resolveRoute(\"api/auth/invite/accept.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/invite/complete\",\n\t\tentrypoint: resolveRoute(\"api/auth/invite/complete.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/invite/register-options\",\n\t\tentrypoint: resolveRoute(\"api/auth/invite/register-options.ts\"),\n\t});\n\n\t// Magic link routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/magic-link/send\",\n\t\tentrypoint: resolveRoute(\"api/auth/magic-link/send.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/magic-link/verify\",\n\t\tentrypoint: resolveRoute(\"api/auth/magic-link/verify.ts\"),\n\t});\n\n\t// OAuth routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/oauth/[provider]\",\n\t\tentrypoint: resolveRoute(\"api/auth/oauth/[provider].ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/oauth/[provider]/callback\",\n\t\tentrypoint: resolveRoute(\"api/auth/oauth/[provider]/callback.ts\"),\n\t});\n\n\t// Self-signup routes\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/signup/request\",\n\t\tentrypoint: resolveRoute(\"api/auth/signup/request.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/signup/verify\",\n\t\tentrypoint: resolveRoute(\"api/auth/signup/verify.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/auth/signup/complete\",\n\t\tentrypoint: resolveRoute(\"api/auth/signup/complete.ts\"),\n\t});\n\n\t// Allowed domains admin routes (only relevant for passkey mode)\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/allowed-domains\",\n\t\tentrypoint: resolveRoute(\"api/admin/allowed-domains/index.ts\"),\n\t});\n\n\tinjectRoute({\n\t\tpattern: \"/_emdash/api/admin/allowed-domains/[domain]\",\n\t\tentrypoint: resolveRoute(\"api/admin/allowed-domains/[domain].ts\"),\n\t});\n}\n","/**\n * Virtual Module Generators\n *\n * Functions that generate virtual module content for Vite.\n * These modules statically import configured dependencies\n * so Vite can properly resolve and bundle them.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { resolve } from \"node:path\";\n\nimport type { AuthProviderDescriptor } from \"../../auth/types.js\";\nimport type { MediaProviderDescriptor } from \"../../media/types.js\";\nimport { defaultSeed } from \"../../seed/default.js\";\nimport type { PluginDescriptor } from \"./runtime.js\";\n\nconst TS_SOURCE_EXT_RE = /^\\.(ts|tsx|mts|cts|jsx)$/;\n\n/** Pattern to remove scoped package prefix from plugin ID */\nconst SCOPED_PREFIX_PATTERN = /^@[^/]+\\/plugin-/;\n\n/** Pattern to remove emdash-plugin- prefix from plugin ID */\nconst EMDASH_PREFIX_PATTERN = /^emdash-plugin-/;\n\n// Virtual module IDs\nexport const VIRTUAL_CONFIG_ID = \"virtual:emdash/config\";\nexport const RESOLVED_VIRTUAL_CONFIG_ID = \"\\0\" + VIRTUAL_CONFIG_ID;\n\nexport const VIRTUAL_DIALECT_ID = \"virtual:emdash/dialect\";\nexport const RESOLVED_VIRTUAL_DIALECT_ID = \"\\0\" + VIRTUAL_DIALECT_ID;\n\nexport const VIRTUAL_STORAGE_ID = \"virtual:emdash/storage\";\nexport const RESOLVED_VIRTUAL_STORAGE_ID = \"\\0\" + VIRTUAL_STORAGE_ID;\n\nexport const VIRTUAL_OBJECT_CACHE_ID = \"virtual:emdash/object-cache\";\nexport const RESOLVED_VIRTUAL_OBJECT_CACHE_ID = \"\\0\" + VIRTUAL_OBJECT_CACHE_ID;\n\nexport const VIRTUAL_ADMIN_REGISTRY_ID = \"virtual:emdash/admin-registry\";\nexport const RESOLVED_VIRTUAL_ADMIN_REGISTRY_ID = \"\\0\" + VIRTUAL_ADMIN_REGISTRY_ID;\n\nexport const VIRTUAL_PLUGINS_ID = \"virtual:emdash/plugins\";\nexport const RESOLVED_VIRTUAL_PLUGINS_ID = \"\\0\" + VIRTUAL_PLUGINS_ID;\n\nexport const VIRTUAL_SANDBOX_RUNNER_ID = \"virtual:emdash/sandbox-runner\";\nexport const RESOLVED_VIRTUAL_SANDBOX_RUNNER_ID = \"\\0\" + VIRTUAL_SANDBOX_RUNNER_ID;\n\nexport const VIRTUAL_SANDBOXED_PLUGINS_ID = \"virtual:emdash/sandboxed-plugins\";\nexport const RESOLVED_VIRTUAL_SANDBOXED_PLUGINS_ID = \"\\0\" + VIRTUAL_SANDBOXED_PLUGINS_ID;\n\nexport const VIRTUAL_AUTH_ID = \"virtual:emdash/auth\";\nexport const RESOLVED_VIRTUAL_AUTH_ID = \"\\0\" + VIRTUAL_AUTH_ID;\n\nexport const VIRTUAL_AUTH_PROVIDERS_ID = \"virtual:emdash/auth-providers\";\nexport const RESOLVED_VIRTUAL_AUTH_PROVIDERS_ID = \"\\0\" + VIRTUAL_AUTH_PROVIDERS_ID;\n\nexport const VIRTUAL_MEDIA_PROVIDERS_ID = \"virtual:emdash/media-providers\";\nexport const RESOLVED_VIRTUAL_MEDIA_PROVIDERS_ID = \"\\0\" + VIRTUAL_MEDIA_PROVIDERS_ID;\n\nexport const VIRTUAL_BLOCK_COMPONENTS_ID = \"virtual:emdash/block-components\";\nexport const RESOLVED_VIRTUAL_BLOCK_COMPONENTS_ID = \"\\0\" + VIRTUAL_BLOCK_COMPONENTS_ID;\n\nexport const VIRTUAL_SEED_ID = \"virtual:emdash/seed\";\nexport const RESOLVED_VIRTUAL_SEED_ID = \"\\0\" + VIRTUAL_SEED_ID;\n\nexport const VIRTUAL_WAIT_UNTIL_ID = \"virtual:emdash/wait-until\";\nexport const RESOLVED_VIRTUAL_WAIT_UNTIL_ID = \"\\0\" + VIRTUAL_WAIT_UNTIL_ID;\n\nexport const VIRTUAL_SCHEDULER_ID = \"virtual:emdash/scheduler\";\nexport const RESOLVED_VIRTUAL_SCHEDULER_ID = \"\\0\" + VIRTUAL_SCHEDULER_ID;\n\nexport const VIRTUAL_ENV_ID = \"virtual:emdash/env\";\nexport const RESOLVED_VIRTUAL_ENV_ID = \"\\0\" + VIRTUAL_ENV_ID;\n\nexport const VIRTUAL_BUILD_ID = \"virtual:emdash/build\";\nexport const RESOLVED_VIRTUAL_BUILD_ID = \"\\0\" + VIRTUAL_BUILD_ID;\n\n/**\n * Generates the config virtual module.\n */\nexport function generateConfigModule(serializableConfig: Record<string, unknown>): string {\n\treturn `export default ${JSON.stringify(serializableConfig)};`;\n}\n\n/**\n * Generates the dialect virtual module.\n *\n * Adapters that set `supportsRequestScope: true` on their descriptor are\n * expected to export `createRequestScopedDb` from their runtime entrypoint;\n * the generator re-exports it so middleware can ask for a per-request Kysely\n * (used for D1 Sessions API, bookmark cookies, read-replica routing). Other\n * adapters get a stub that returns null.\n *\n * Adapters independently opt into the cold-start coalescing dialect. Keeping\n * this capability explicit prevents bundlers from probing exports that do not\n * exist on SQLite, libSQL, PostgreSQL, or other adapters.\n */\nexport function generateDialectModule(opts: {\n\tentrypoint?: string;\n\ttype?: string;\n\tsupportsRequestScope: boolean;\n\tsupportsCoalescing: boolean;\n\tsupportsCollectionDeletionGuard: boolean;\n}): string {\n\tconst { entrypoint, supportsRequestScope, supportsCoalescing, supportsCollectionDeletionGuard } =\n\t\topts;\n\tif (!entrypoint) {\n\t\treturn [\n\t\t\t`export const createDialect = undefined;`,\n\t\t\t`export const dialectType = \"sqlite\";`,\n\t\t\t`export const createRequestScopedDb = (_opts) => null;`,\n\t\t\t`export const createCoalescingDialect = undefined;`,\n\t\t\t`export const executeCollectionDeletionGuard = undefined;`,\n\t\t].join(\"\\n\");\n\t}\n\tconst type = opts.type ?? \"sqlite\";\n\n\tconst coalescingExport = supportsCoalescing\n\t\t? `import { createCoalescingDialect as _createCoalescingDialect } from \"${entrypoint}\";\nexport const createCoalescingDialect = _createCoalescingDialect;`\n\t\t: `export const createCoalescingDialect = undefined;`;\n\tconst collectionDeletionExport = supportsCollectionDeletionGuard\n\t\t? `export { executeCollectionDeletionGuard } from \"${entrypoint}\";`\n\t\t: `export const executeCollectionDeletionGuard = undefined;`;\n\n\tif (supportsRequestScope) {\n\t\treturn `\nimport { createDialect as _createDialect } from \"${entrypoint}\";\nexport { createRequestScopedDb } from \"${entrypoint}\";\n${coalescingExport}\n${collectionDeletionExport}\nexport const createDialect = _createDialect;\nexport const dialectType = ${JSON.stringify(type)};\n`;\n\t}\n\n\treturn `\nimport { createDialect as _createDialect } from \"${entrypoint}\";\n${coalescingExport}\n${collectionDeletionExport}\nexport const createDialect = _createDialect;\nexport const dialectType = ${JSON.stringify(type)};\nexport const createRequestScopedDb = (_opts) => null;\n`;\n}\n\n/**\n * Generates the storage virtual module.\n * Statically imports the configured storage adapter.\n */\nexport function generateStorageModule(storageEntrypoint?: string): string {\n\tif (!storageEntrypoint) {\n\t\treturn `export const createStorage = undefined;`;\n\t}\n\treturn `\nimport { createStorage as _createStorage } from \"${storageEntrypoint}\";\nexport const createStorage = _createStorage;\n`;\n}\n\n/**\n * Generates the object-cache virtual module.\n *\n * Statically imports the configured object-cache backend's `createObjectCache`\n * factory and embeds its serializable config. When no object cache is\n * configured, exports `undefined` so the runtime read-through layer becomes a\n * transparent passthrough (cache off by default).\n */\nexport function generateObjectCacheModule(\n\tentrypoint?: string,\n\tconfig?: Record<string, unknown>,\n): string {\n\tif (!entrypoint) {\n\t\treturn [\n\t\t\t`export const createObjectCache = undefined;`,\n\t\t\t`export const objectCacheConfig = undefined;`,\n\t\t].join(\"\\n\");\n\t}\n\treturn `\nimport { createObjectCache as _createObjectCache } from \"${entrypoint}\";\nexport const createObjectCache = _createObjectCache;\nexport const objectCacheConfig = ${JSON.stringify(config ?? {})};\n`;\n}\n\n/**\n * Generates the auth virtual module.\n * Statically imports the configured auth provider.\n */\nexport function generateAuthModule(authEntrypoint?: string): string {\n\tif (!authEntrypoint) {\n\t\treturn `export const authenticate = undefined;`;\n\t}\n\treturn `\nimport { authenticate as _authenticate } from \"${authEntrypoint}\";\nexport const authenticate = _authenticate;\n`;\n}\n\n/**\n * Generates the auth providers module.\n *\n * Statically imports each auth provider's `adminEntry` module and exports\n * a registry keyed by provider ID. The admin UI uses this to render\n * provider-specific login buttons/forms and setup steps.\n *\n * Follows the same pattern as `generateAdminRegistryModule()` for plugins.\n */\nexport function generateAuthProvidersModule(descriptors: AuthProviderDescriptor[]): string {\n\tconst withAdmin = descriptors.filter((d) => d.adminEntry);\n\n\tif (withAdmin.length === 0) {\n\t\treturn `export const authProviders = {};`;\n\t}\n\n\tconst imports: string[] = [];\n\tconst entries: string[] = [];\n\n\twithAdmin.forEach((descriptor, index) => {\n\t\tconst varName = `authProvider${index}`;\n\t\timports.push(`import * as ${varName} from ${JSON.stringify(descriptor.adminEntry)};`);\n\t\tentries.push(\n\t\t\t`  ${JSON.stringify(descriptor.id)}: { ...${varName}, id: ${JSON.stringify(descriptor.id)}, label: ${JSON.stringify(descriptor.label)} },`,\n\t\t);\n\t});\n\n\treturn `\n// Auto-generated auth provider registry\n${imports.join(\"\\n\")}\n\nexport const authProviders = {\n${entries.join(\"\\n\")}\n};\n`;\n}\n\n/**\n * Generates the plugins module.\n * Imports and instantiates all plugins at runtime.\n *\n * Handles two plugin formats:\n * - **Native**: imports `createPlugin` and calls it with options\n * - **Standard**: imports the default export and wraps it with `adaptSandboxEntry`\n *\n * The format is determined by `descriptor.format`:\n * - `\"standard\"` -- uses adaptSandboxEntry\n * - `\"native\"` or undefined -- uses createPlugin\n *\n * This is critical for Cloudflare Workers where globals don't persist\n * between build time and runtime.\n */\nexport function generatePluginsModule(descriptors: PluginDescriptor[]): string {\n\tif (descriptors.length === 0) {\n\t\treturn `export const plugins = [];`;\n\t}\n\n\tconst imports: string[] = [];\n\tconst instantiations: string[] = [];\n\n\t// Track whether we need the adapter import\n\tlet needsAdapter = false;\n\n\tdescriptors.forEach((descriptor, index) => {\n\t\t// Every `plugins: []` entry must resolve to a file/package entrypoint that\n\t\t// can be statically imported and bundled at build time. An in-process\n\t\t// `definePlugin({...})` result passed directly has no entrypoint; without\n\t\t// this guard the generator emitted `import pluginDefN from \"undefined\";`,\n\t\t// which failed deep in Rollup with `failed to resolve import \"undefined\"`\n\t\t// (#1416). Fail fast with an actionable message instead.\n\t\tif (!descriptor.entrypoint) {\n\t\t\tthrow new Error(\n\t\t\t\t`[emdash] Plugin \"${descriptor.id}\" has no \\`entrypoint\\`. The astro integration's ` +\n\t\t\t\t\t`\\`plugins: []\\` requires plugins that resolve to a file/package entrypoint so they can be ` +\n\t\t\t\t\t`bundled at build time; an in-process \\`definePlugin({...})\\` result passed directly is not ` +\n\t\t\t\t\t`supported. Move the plugin into its own module and reference it via a factory that returns ` +\n\t\t\t\t\t`a descriptor with an \\`entrypoint\\` (e.g. \\`plugins: [myPlugin()]\\`).`,\n\t\t\t);\n\t\t}\n\t\tif (descriptor.format === \"standard\") {\n\t\t\t// Standard format: import default export, wrap with adaptSandboxEntry\n\t\t\tneedsAdapter = true;\n\t\t\tconst varName = `pluginDef${index}`;\n\t\t\timports.push(`import ${varName} from \"${descriptor.entrypoint}\";`);\n\t\t\tinstantiations.push(\n\t\t\t\t`adaptSandboxEntry(${varName}, ${JSON.stringify({\n\t\t\t\t\tid: descriptor.id,\n\t\t\t\t\tversion: descriptor.version,\n\t\t\t\t\tcapabilities: descriptor.capabilities,\n\t\t\t\t\tallowedHosts: descriptor.allowedHosts,\n\t\t\t\t\tstorage: descriptor.storage,\n\t\t\t\t\tadminPages: descriptor.adminPages,\n\t\t\t\t\tadminWidgets: descriptor.adminWidgets,\n\t\t\t\t\tsettingsSchema: descriptor.settingsSchema,\n\t\t\t\t\tportableTextBlocks: descriptor.portableTextBlocks,\n\t\t\t\t\tfieldWidgets: descriptor.fieldWidgets,\n\t\t\t\t})})`,\n\t\t\t);\n\t\t} else {\n\t\t\t// Native format: import createPlugin and call with options\n\t\t\tconst varName = `createPlugin${index}`;\n\t\t\timports.push(`import { createPlugin as ${varName} } from \"${descriptor.entrypoint}\";`);\n\t\t\tinstantiations.push(`${varName}(${JSON.stringify(descriptor.options ?? {})})`);\n\t\t}\n\t});\n\n\tconst adapterImport = needsAdapter\n\t\t? `import { adaptSandboxEntry } from \"@premium-cms/emdash/plugins/adapt-sandbox-entry\";\\n`\n\t\t: \"\";\n\n\treturn `\n// Auto-generated plugins module\n// Imports and instantiates all configured plugins at runtime\n\n${adapterImport}${imports.join(\"\\n\")}\n\n/** Resolved plugins array */\nexport const plugins = [\n  ${instantiations.join(\",\\n  \")}\n];\n`;\n}\n\n/**\n * Generates the admin registry module.\n * Uses adminEntry from plugin descriptors to statically import admin modules.\n */\nexport function generateAdminRegistryModule(descriptors: PluginDescriptor[]): string {\n\t// Filter to descriptors with admin entries\n\tconst adminDescriptors = descriptors.filter((d) => d.adminEntry);\n\n\tif (adminDescriptors.length === 0) {\n\t\treturn `export const pluginAdmins = {};`;\n\t}\n\n\tconst imports: string[] = [];\n\tconst entries: string[] = [];\n\n\tadminDescriptors.forEach((descriptor, index) => {\n\t\tconst varName = `admin${index}`;\n\t\t// Use explicit ID from descriptor if available, otherwise derive from entrypoint\n\t\tconst pluginId =\n\t\t\tdescriptor.id ??\n\t\t\tdescriptor.entrypoint.replace(SCOPED_PREFIX_PATTERN, \"\").replace(EMDASH_PREFIX_PATTERN, \"\");\n\n\t\timports.push(`import * as ${varName} from \"${descriptor.adminEntry}\";`);\n\t\tentries.push(`  \"${pluginId}\": ${varName},`);\n\t});\n\n\treturn `\n// Auto-generated plugin admin registry\n${imports.join(\"\\n\")}\n\nexport const pluginAdmins = {\n${entries.join(\"\\n\")}\n};\n`;\n}\n\n/**\n * Generates the sandbox runner module.\n * Imports the configured sandbox runner factory or provides a noop default.\n *\n * When sandbox is explicitly false (debugging escape hatch), we still mark\n * sandboxEnabled = true so sandboxed plugin entries are loaded, but we use\n * the noop runner which falls through to in-process loading via adaptSandboxEntry.\n */\nexport function generateSandboxRunnerModule(sandboxRunner?: string, sandbox?: boolean): string {\n\tif (!sandboxRunner) {\n\t\t// No sandbox runner configured - sandboxed plugins disabled\n\t\treturn `\n// No sandbox runner configured - sandboxed plugins disabled\nimport { createNoopSandboxRunner } from \"@premium-cms/emdash\";\n\nexport const createSandboxRunner = createNoopSandboxRunner;\nexport const sandboxEnabled = false;\n`;\n\t}\n\n\tif (sandbox === false) {\n\t\t// sandbox: false escape hatch - plugins are loaded but run in-process\n\t\t// (no isolation, for debugging)\n\t\treturn `\n// Sandbox explicitly disabled (sandbox: false) - plugins run in-process\nimport { createNoopSandboxRunner } from \"@premium-cms/emdash\";\n\nexport const createSandboxRunner = createNoopSandboxRunner;\nexport const sandboxEnabled = true;\nexport const sandboxBypassed = true;\n`;\n\t}\n\n\treturn `\n// Auto-generated sandbox runner module\nimport { createSandboxRunner as _createSandboxRunner } from \"${sandboxRunner}\";\n\nexport const createSandboxRunner = _createSandboxRunner;\nexport const sandboxEnabled = true;\n`;\n}\n\n/**\n * Generates the media providers module.\n * Imports and instantiates configured media providers at runtime.\n */\nexport function generateMediaProvidersModule(descriptors: MediaProviderDescriptor[]): string {\n\t// Always include local provider by default unless explicitly disabled\n\tconst localDisabled = descriptors.some((d) => d.id === \"local\" && d.config.enabled === false);\n\n\tconst imports: string[] = [];\n\tconst entries: string[] = [];\n\n\t// Add local provider first if not disabled\n\tif (!localDisabled) {\n\t\timports.push(\n\t\t\t`import { createMediaProvider as createLocalProvider } from \"@premium-cms/emdash/media/local-runtime\";`,\n\t\t);\n\t\tentries.push(`{\n\tid: \"local\",\n\tname: \"Library\",\n\ticon: \"folder\",\n\tcapabilities: { browse: true, search: false, upload: true, delete: true },\n\tcreateProvider: (ctx) => createLocalProvider({ ...ctx, enabled: true }),\n}`);\n\t}\n\n\t// Add custom providers\n\tdescriptors\n\t\t.filter((d) => d.id !== \"local\" || d.config.enabled !== false)\n\t\t.filter((d) => d.id !== \"local\") // Skip local if we already added it\n\t\t.forEach((descriptor, index) => {\n\t\t\tconst varName = `createProvider${index}`;\n\t\t\timports.push(`import { createMediaProvider as ${varName} } from \"${descriptor.entrypoint}\";`);\n\t\t\tentries.push(`{\n\tid: ${JSON.stringify(descriptor.id)},\n\tname: ${JSON.stringify(descriptor.name)},\n\ticon: ${JSON.stringify(descriptor.icon)},\n\tcapabilities: ${JSON.stringify(descriptor.capabilities)},\n\tcreateProvider: (ctx) => ${varName}({ ...${JSON.stringify(descriptor.config)}, ...ctx }),\n}`);\n\t\t});\n\n\treturn `\n// Auto-generated media providers module\n${imports.join(\"\\n\")}\n\n/** Media provider descriptors with factory functions */\nexport const mediaProviders = [\n  ${entries.join(\",\\n  \")}\n];\n`;\n}\n\n/**\n * Generates the block components module.\n * Collects and merges `blockComponents` exports from plugin component entries.\n */\nexport function generateBlockComponentsModule(descriptors: PluginDescriptor[]): string {\n\tconst withComponents = descriptors.filter((d) => d.componentsEntry);\n\tif (withComponents.length === 0) {\n\t\treturn `export const pluginBlockComponents = {};`;\n\t}\n\n\tconst imports: string[] = [];\n\tconst spreads: string[] = [];\n\twithComponents.forEach((d, i) => {\n\t\timports.push(`import { blockComponents as bc${i} } from \"${d.componentsEntry}\";`);\n\t\tspreads.push(`...bc${i}`);\n\t});\n\n\treturn `${imports.join(\"\\n\")}\\nexport const pluginBlockComponents = { ${spreads.join(\", \")} };`;\n}\n\n/**\n * Generates the wait-until virtual module.\n *\n * Under @astrojs/cloudflare, re-exports `waitUntil` from `cloudflare:workers`\n * so `after(fn)` in core can extend the worker's lifetime past the response\n * for deferred bookkeeping. For any other adapter, exports `undefined` —\n * Node's long-lived event loop keeps deferred promises running without a\n * lifetime extender.\n *\n * Keeping the adapter check here — rather than in core — means core itself\n * has no Cloudflare-specific imports or code paths.\n */\nexport function generateWaitUntilModule(adapterName: string | undefined): string {\n\tif (adapterName === \"@astrojs/cloudflare\") {\n\t\treturn `export { waitUntil } from \"cloudflare:workers\";`;\n\t}\n\treturn `export const waitUntil = undefined;`;\n}\n\n/**\n * Generates the env virtual module.\n *\n * Under @astrojs/cloudflare, re-exports `env` from `cloudflare:workers` so\n * routes can read Worker bindings/secrets without touching\n * `Astro.locals.runtime.env`, which Astro 6+ removed (accessing it throws\n * rather than returning undefined, so `locals.runtime?.env` optional-chaining\n * doesn't help -- see #1736). For any other adapter, exports `undefined` so\n * callers fall back to `import.meta.env`. Mirrors generateWaitUntilModule:\n * core stays adapter-agnostic, with no direct `cloudflare:workers` import\n * that would fail to resolve under a Node build.\n */\nexport function generateEnvModule(adapterName: string | undefined): string {\n\tif (adapterName === \"@astrojs/cloudflare\") {\n\t\treturn `export { env } from \"cloudflare:workers\";`;\n\t}\n\treturn `export const env = undefined;`;\n}\n\n/**\n * Generates the build virtual module.\n *\n * Content-hashed `/_astro/*` names make the response depend on the build, not\n * only on the content. Exposing the build timestamp lets the middleware fold\n * that dimension into the cache validator, so a code-only deploy stops\n * answering conditional requests with 304 while the assets the cached HTML\n * references are already gone.\n */\nexport function generateBuildModule(buildTime: number): string {\n\treturn `export const buildTime = ${buildTime};`;\n}\n\n/**\n * Generates the scheduler virtual module.\n *\n * Decides — at build time, from the Astro adapter — whether the runtime gets a\n * long-lived timer heartbeat. A *production* Cloudflare build has no persistent\n * timers, so the Worker's `scheduled()` handler (a Cron Trigger) drives\n * `runScheduledTasks()` instead and this exports `null`. Every other case — any\n * other adapter (Node, Bun), and crucially local `astro dev` even under the\n * Cloudflare adapter (no Cron Trigger fires in dev) — gets a `NodeCronScheduler`\n * factory so plugin cron, scheduled publishing, and cleanup still run.\n *\n * Keeping the adapter check here — rather than in core's runtime — means the\n * runtime has no Cloudflare-specific code path; it just calls `createScheduler`\n * if one was injected. Mirrors the wait-until module's approach.\n */\nexport function generateSchedulerModule(\n\tadapterName: string | undefined,\n\tcommand: \"build\" | \"serve\" | undefined,\n): string {\n\t// Only suppress the timer for an actual Cloudflare *build* — that artifact\n\t// runs in workerd where a Cron Trigger drives scheduled work. In `serve`\n\t// (local dev) nothing fires the Cron Trigger, so fall through to the timer.\n\tif (adapterName === \"@astrojs/cloudflare\" && command !== \"serve\") {\n\t\treturn `// Serverless build: an external Cron Trigger drives scheduled work.\nexport const createScheduler = null;\n`;\n\t}\n\treturn `// Long-lived runtime (or local dev): drive scheduled work from an in-process timer.\nimport { NodeCronScheduler } from \"@premium-cms/emdash\";\n\nexport function createScheduler(executor) {\n\treturn new NodeCronScheduler(executor);\n}\n`;\n}\n\n/**\n * Generates the seed virtual module.\n * Reads the user's seed file at build time (in Node context) and embeds it,\n * so the runtime doesn't need filesystem access (required for workerd).\n *\n * Search order:\n *   1. `.emdash/seed.json`\n *   2. `package.json` → `emdash.seed` reference\n *   3. `seed/seed.json` (conventional template path)\n *\n * Exports `userSeed` (user's seed or null) and `seed` (user's seed or default).\n *\n * When no user seed is found, falls back to the built-in default seed and\n * (if `warnOnFallback` is true) logs a warning so misconfiguration is visible\n * during `astro dev`. Build/preview/sync stay silent so sites that\n * intentionally use the default seed (e.g. the blank template) don't\n * generate noisy logs.\n */\nexport function generateSeedModule(projectRoot: string, warnOnFallback = false): string {\n\tlet userSeedJson: string | null = null;\n\n\t// Try .emdash/seed.json\n\ttry {\n\t\tconst seedPath = resolve(projectRoot, \".emdash\", \"seed.json\");\n\t\tconst content = readFileSync(seedPath, \"utf-8\");\n\t\tJSON.parse(content); // validate\n\t\tuserSeedJson = content;\n\t} catch {\n\t\t// Not found, try next\n\t}\n\n\t// Try package.json → emdash.seed reference\n\tif (!userSeedJson) {\n\t\ttry {\n\t\t\tconst pkgPath = resolve(projectRoot, \"package.json\");\n\t\t\tconst pkgContent = readFileSync(pkgPath, \"utf-8\");\n\t\t\tconst pkg: { emdash?: { seed?: string } } = JSON.parse(pkgContent);\n\n\t\t\tif (pkg.emdash?.seed) {\n\t\t\t\tconst seedPath = resolve(projectRoot, pkg.emdash.seed);\n\t\t\t\tconst content = readFileSync(seedPath, \"utf-8\");\n\t\t\t\tJSON.parse(content); // validate\n\t\t\t\tuserSeedJson = content;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Not found\n\t\t}\n\t}\n\n\t// Try conventional seed/seed.json fallback\n\tif (!userSeedJson) {\n\t\ttry {\n\t\t\tconst seedPath = resolve(projectRoot, \"seed\", \"seed.json\");\n\t\t\tconst content = readFileSync(seedPath, \"utf-8\");\n\t\t\tJSON.parse(content); // validate\n\t\t\tuserSeedJson = content;\n\t\t} catch {\n\t\t\t// Not found\n\t\t}\n\t}\n\n\tif (userSeedJson) {\n\t\treturn [`export const userSeed = ${userSeedJson};`, `export const seed = userSeed;`].join(\"\\n\");\n\t}\n\n\t// No user seed — inline the default. Caller (the Vite plugin) gates this\n\t// to dev-only so production builds stay quiet for sites that intentionally\n\t// rely on the default seed.\n\tif (warnOnFallback) {\n\t\tconsole.warn(\n\t\t\t\"[emdash] No user seed found at .emdash/seed.json, package.json#emdash.seed, or seed/seed.json. Falling back to the built-in default seed; the setup wizard will not offer demo content for this site.\",\n\t\t);\n\t}\n\treturn [\n\t\t`export const userSeed = null;`,\n\t\t`export const seed = ${JSON.stringify(defaultSeed)};`,\n\t].join(\"\\n\");\n}\n\n/**\n * Resolve a module specifier from the project's context.\n * Uses Node.js require.resolve with the project root as base.\n */\nfunction resolveModulePathFromProject(specifier: string, projectRoot: string): string {\n\t// Create require from the project's package.json location\n\tconst projectPackageJson = resolve(projectRoot, \"package.json\");\n\tconst require = createRequire(projectPackageJson);\n\treturn require.resolve(specifier);\n}\n\n/**\n * Generates the sandboxed plugins module.\n * Resolves plugin entrypoints to files, reads them, and embeds the code.\n * Notifies the caller about each resolved entry so build tools can watch it.\n *\n * At runtime, middleware uses SandboxRunner to load these into isolates.\n */\nexport function generateSandboxedPluginsModule(\n\tsandboxed: PluginDescriptor[],\n\tprojectRoot: string,\n\tonEntryResolved?: (filePath: string) => void,\n): string {\n\tif (sandboxed.length === 0) {\n\t\treturn `\n// No sandboxed plugins configured\nexport const sandboxedPlugins = [];\n`;\n\t}\n\n\tconst pluginEntries: string[] = [];\n\n\tfor (const descriptor of sandboxed) {\n\t\tconst bundleSpecifier = descriptor.entrypoint;\n\n\t\t// Resolve the bundle to a file path using project's require context\n\t\tconst filePath = resolveModulePathFromProject(bundleSpecifier, projectRoot);\n\n\t\tconst ext = filePath.slice(filePath.lastIndexOf(\".\"));\n\t\tif (TS_SOURCE_EXT_RE.test(ext)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Sandboxed plugin \"${descriptor.id}\" entrypoint \"${bundleSpecifier}\" resolves to ` +\n\t\t\t\t\t`unbuilt source (${filePath}). Sandbox entries must be pre-built JavaScript. ` +\n\t\t\t\t\t`Ensure the plugin's package.json exports point to built files (e.g. dist/*.mjs) ` +\n\t\t\t\t\t`and run the plugin's build step before building the site.`,\n\t\t\t);\n\t\t}\n\n\t\tonEntryResolved?.(filePath);\n\n\t\tconst code = readFileSync(filePath, \"utf-8\");\n\n\t\t// Create the plugin entry with embedded code and sandbox config\n\t\tpluginEntries.push(`{\n    id: ${JSON.stringify(descriptor.id)},\n    version: ${JSON.stringify(descriptor.version)},\n    options: ${JSON.stringify(descriptor.options ?? {})},\n    capabilities: ${JSON.stringify(descriptor.capabilities ?? [])},\n    allowedHosts: ${JSON.stringify(descriptor.allowedHosts ?? [])},\n    storage: ${JSON.stringify(descriptor.storage ?? {})},\n    mcp: ${JSON.stringify(descriptor.mcp)},\n    routes: ${JSON.stringify(descriptor.routes ?? [])},\n    hooks: ${JSON.stringify(descriptor.hooks ?? [])},\n    adminPages: ${JSON.stringify(descriptor.adminPages ?? [])},\n    adminWidgets: ${JSON.stringify(descriptor.adminWidgets ?? [])},\n    settingsSchema: ${JSON.stringify(descriptor.settingsSchema)},\n    portableTextBlocks: ${JSON.stringify(descriptor.portableTextBlocks ?? [])},\n    fieldWidgets: ${JSON.stringify(descriptor.fieldWidgets ?? [])},\n    adminEntry: ${JSON.stringify(descriptor.adminEntry)},\n    // Code read from: ${filePath}\n    code: ${JSON.stringify(code)},\n  }`);\n\t}\n\n\treturn `\n// Auto-generated sandboxed plugins module\n// Plugin code is embedded at build time\n\n/**\n * Sandboxed plugin entries with embedded code.\n * Loaded at runtime via SandboxRunner.\n */\nexport const sandboxedPlugins = [\n  ${pluginEntries.join(\",\\n  \")}\n];\n`;\n}\n","/**\n * Vite Plugin Configuration\n *\n * Defines the Vite plugin that handles virtual modules and other\n * Vite-specific configuration for EmDash.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, isAbsolute, relative, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport type { AstroConfig } from \"astro\";\nimport type { Plugin } from \"vite\";\n\nimport { COMMIT, VERSION } from \"../../version.js\";\nimport type { EmDashConfig, PluginDescriptor } from \"./runtime.js\";\nimport {\n\tVIRTUAL_CONFIG_ID,\n\tRESOLVED_VIRTUAL_CONFIG_ID,\n\tVIRTUAL_DIALECT_ID,\n\tRESOLVED_VIRTUAL_DIALECT_ID,\n\tVIRTUAL_STORAGE_ID,\n\tRESOLVED_VIRTUAL_STORAGE_ID,\n\tVIRTUAL_OBJECT_CACHE_ID,\n\tRESOLVED_VIRTUAL_OBJECT_CACHE_ID,\n\tVIRTUAL_ADMIN_REGISTRY_ID,\n\tRESOLVED_VIRTUAL_ADMIN_REGISTRY_ID,\n\tVIRTUAL_PLUGINS_ID,\n\tRESOLVED_VIRTUAL_PLUGINS_ID,\n\tVIRTUAL_SANDBOX_RUNNER_ID,\n\tRESOLVED_VIRTUAL_SANDBOX_RUNNER_ID,\n\tVIRTUAL_SANDBOXED_PLUGINS_ID,\n\tRESOLVED_VIRTUAL_SANDBOXED_PLUGINS_ID,\n\tVIRTUAL_AUTH_ID,\n\tRESOLVED_VIRTUAL_AUTH_ID,\n\tVIRTUAL_AUTH_PROVIDERS_ID,\n\tRESOLVED_VIRTUAL_AUTH_PROVIDERS_ID,\n\tVIRTUAL_MEDIA_PROVIDERS_ID,\n\tRESOLVED_VIRTUAL_MEDIA_PROVIDERS_ID,\n\tVIRTUAL_BLOCK_COMPONENTS_ID,\n\tRESOLVED_VIRTUAL_BLOCK_COMPONENTS_ID,\n\tVIRTUAL_SEED_ID,\n\tRESOLVED_VIRTUAL_SEED_ID,\n\tVIRTUAL_WAIT_UNTIL_ID,\n\tRESOLVED_VIRTUAL_WAIT_UNTIL_ID,\n\tVIRTUAL_SCHEDULER_ID,\n\tRESOLVED_VIRTUAL_SCHEDULER_ID,\n\tVIRTUAL_ENV_ID,\n\tRESOLVED_VIRTUAL_ENV_ID,\n\tVIRTUAL_BUILD_ID,\n\tRESOLVED_VIRTUAL_BUILD_ID,\n\tgenerateSeedModule,\n\tgenerateWaitUntilModule,\n\tgenerateSchedulerModule,\n\tgenerateEnvModule,\n\tgenerateBuildModule,\n\tgenerateConfigModule,\n\tgenerateDialectModule,\n\tgenerateStorageModule,\n\tgenerateObjectCacheModule,\n\tgenerateAuthModule,\n\tgenerateAuthProvidersModule,\n\tgeneratePluginsModule,\n\tgenerateAdminRegistryModule,\n\tgenerateSandboxRunnerModule,\n\tgenerateSandboxedPluginsModule,\n\tgenerateMediaProvidersModule,\n\tgenerateBlockComponentsModule,\n} from \"./virtual-modules.js\";\n\nconst LOCALE_MESSAGES_RE = /[/\\\\]([a-z]{2}(?:-[A-Z]{2})?)[/\\\\]messages\\.mjs$/;\n/**\n * Vite plugin that compiles Lingui macros in admin source files.\n * Only active in dev mode when the admin package is aliased to source for HMR.\n * @babel/core is dynamically imported from admin's devDependencies —\n * not declared by core, never ships to end users.\n */\nfunction linguiMacroPlugin(adminSourcePath: string, adminDistPath: string): Plugin {\n\t// Resolve @babel/core from admin's devDependencies, not core's.\n\tconst adminRequire = createRequire(resolve(adminDistPath, \"index.js\"));\n\tconst babelCorePath = adminRequire.resolve(\"@babel/core\");\n\n\treturn {\n\t\tname: \"emdash-lingui-macro\",\n\t\tenforce: \"pre\",\n\t\tresolveId(id, importer) {\n\t\t\t// Redirect relative locale catalog imports (e.g. ./de/messages.mjs) from\n\t\t\t// within admin source to the compiled dist/locales/ directory, since\n\t\t\t// lingui compile only runs during build — not in dev watch mode.\n\t\t\tif (!importer?.startsWith(adminSourcePath)) return;\n\t\t\tconst match = id.match(LOCALE_MESSAGES_RE);\n\t\t\tif (match?.[1]) {\n\t\t\t\treturn resolve(adminDistPath, \"locales\", match[1], \"messages.mjs\");\n\t\t\t}\n\t\t},\n\t\tasync transform(code, id) {\n\t\t\tif (!id.startsWith(adminSourcePath) || !code.includes(\"@lingui\")) return;\n\t\t\tconst { transformAsync } = (await import(babelCorePath)) as typeof import(\"@babel/core\");\n\t\t\tconst result = await transformAsync(code, {\n\t\t\t\tfilename: id,\n\t\t\t\tplugins: [\"@lingui/babel-plugin-lingui-macro\"],\n\t\t\t\tparserOpts: { plugins: [\"jsx\", \"typescript\"] },\n\t\t\t});\n\t\t\tif (!result?.code) return;\n\t\t\treturn { code: result.code, map: result.map ?? undefined };\n\t\t},\n\t};\n}\n\n/**\n * Resolve path to the admin package dist directory.\n * Used for Vite alias to ensure the package is found in pnpm's isolated node_modules.\n */\nfunction resolveAdminDist(): string {\n\tconst require = createRequire(import.meta.url);\n\tconst adminPath = require.resolve(\"@premium-cms/admin\");\n\t// Return the directory containing the built package (dist/)\n\treturn dirname(adminPath);\n}\n\n/**\n * Check whether child is inside parent without relying on simple prefix checks.\n */\nfunction isInside(parent: string, child: string): boolean {\n\tconst relativePath = relative(parent, child);\n\treturn relativePath === \"\" || (!relativePath.startsWith(\"..\") && !isAbsolute(relativePath));\n}\n\n/**\n * Resolve path to the admin package source directory.\n * In dev mode inside this repo, we alias @premium-cms/admin to the source so\n * Vite processes it directly — giving instant HMR instead of requiring a\n * rebuild + restart. External apps should use the built package surface.\n */\nfunction resolveAdminSource(projectRoot: string): string | undefined {\n\tconst require = createRequire(import.meta.url);\n\tconst adminPath = require.resolve(\"@premium-cms/admin\");\n\t// dist/index.js -> go up to package root, then into src/\n\tconst packageRoot = resolve(dirname(adminPath), \"..\");\n\tconst repoRoot = resolve(packageRoot, \"..\", \"..\");\n\tconst srcEntry = resolve(packageRoot, \"src\", \"index.ts\");\n\n\ttry {\n\t\tif (existsSync(srcEntry) && isInside(repoRoot, projectRoot)) {\n\t\t\treturn resolve(packageRoot, \"src\");\n\t\t}\n\t} catch {\n\t\t// Not in local repo — fall back to dist\n\t}\n\treturn undefined;\n}\n\nfunction resolveIntegrationShim(fileName: string): string {\n\tconst currentDir = dirname(fileURLToPath(import.meta.url));\n\tconst sourceShimPath = resolve(currentDir, \"shims\", fileName);\n\tif (existsSync(sourceShimPath)) {\n\t\treturn sourceShimPath;\n\t}\n\treturn resolve(currentDir, \"..\", \"..\", \"src\", \"astro\", \"integration\", \"shims\", fileName);\n}\n\nexport interface VitePluginOptions {\n\t/** Serializable config (database, storage, auth descriptors) */\n\tserializableConfig: Record<string, unknown>;\n\t/** Resolved EmDash config */\n\tresolvedConfig: EmDashConfig;\n\t/** Plugin descriptors */\n\tpluginDescriptors: PluginDescriptor[];\n\t/** Astro config */\n\tastroConfig: AstroConfig;\n}\n\n/**\n * Creates the EmDash virtual modules Vite plugin.\n */\nexport function createVirtualModulesPlugin(\n\toptions: VitePluginOptions,\n\tastroCommand: \"dev\" | \"build\" | \"preview\" | \"sync\",\n): Plugin {\n\tconst { serializableConfig, resolvedConfig, pluginDescriptors, astroConfig } = options;\n\n\tlet viteCommand: \"build\" | \"serve\" | undefined;\n\n\t// Captured once per plugin instance rather than inside load(): Vite may load\n\t// the module more than once (client and server passes, dev reloads), and a\n\t// validator that moved between those loads would invalidate at random.\n\tconst buildTime = Date.now();\n\n\treturn {\n\t\tname: \"emdash-virtual-modules\",\n\t\tconfigResolved(config) {\n\t\t\tviteCommand = config.command;\n\t\t},\n\t\tresolveId(id: string) {\n\t\t\tif (id === VIRTUAL_CONFIG_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_CONFIG_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_DIALECT_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_DIALECT_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_STORAGE_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_STORAGE_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_OBJECT_CACHE_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_OBJECT_CACHE_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_ADMIN_REGISTRY_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_ADMIN_REGISTRY_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_PLUGINS_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_PLUGINS_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_SANDBOX_RUNNER_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_SANDBOX_RUNNER_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_SANDBOXED_PLUGINS_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_SANDBOXED_PLUGINS_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_AUTH_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_AUTH_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_AUTH_PROVIDERS_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_AUTH_PROVIDERS_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_MEDIA_PROVIDERS_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_MEDIA_PROVIDERS_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_BLOCK_COMPONENTS_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_BLOCK_COMPONENTS_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_SEED_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_SEED_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_WAIT_UNTIL_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_WAIT_UNTIL_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_SCHEDULER_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_SCHEDULER_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_ENV_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_ENV_ID;\n\t\t\t}\n\t\t\tif (id === VIRTUAL_BUILD_ID) {\n\t\t\t\treturn RESOLVED_VIRTUAL_BUILD_ID;\n\t\t\t}\n\t\t},\n\t\tload(id: string) {\n\t\t\tif (id === RESOLVED_VIRTUAL_CONFIG_ID) {\n\t\t\t\treturn generateConfigModule(serializableConfig);\n\t\t\t}\n\t\t\t// Generate a module that statically imports the configured dialect\n\t\t\t// This allows Vite to properly resolve and bundle it\n\t\t\tif (id === RESOLVED_VIRTUAL_DIALECT_ID) {\n\t\t\t\treturn generateDialectModule({\n\t\t\t\t\tentrypoint: resolvedConfig.database?.entrypoint,\n\t\t\t\t\ttype: resolvedConfig.database?.type,\n\t\t\t\t\tsupportsRequestScope: resolvedConfig.database?.supportsRequestScope ?? false,\n\t\t\t\t\tsupportsCoalescing: resolvedConfig.database?.supportsCoalescing ?? false,\n\t\t\t\t\tsupportsCollectionDeletionGuard:\n\t\t\t\t\t\tresolvedConfig.database?.supportsCollectionDeletionGuard ?? false,\n\t\t\t\t});\n\t\t\t}\n\t\t\t// Generate a module that statically imports the configured storage\n\t\t\tif (id === RESOLVED_VIRTUAL_STORAGE_ID) {\n\t\t\t\treturn generateStorageModule(resolvedConfig.storage?.entrypoint);\n\t\t\t}\n\t\t\t// Generate the object-cache module — statically imports the\n\t\t\t// configured backend factory, or exports undefined (cache off).\n\t\t\tif (id === RESOLVED_VIRTUAL_OBJECT_CACHE_ID) {\n\t\t\t\treturn generateObjectCacheModule(\n\t\t\t\t\tresolvedConfig.objectCache?.entrypoint,\n\t\t\t\t\tresolvedConfig.objectCache?.config,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Generate plugins module that imports and instantiates all plugins\n\t\t\tif (id === RESOLVED_VIRTUAL_PLUGINS_ID) {\n\t\t\t\treturn generatePluginsModule(pluginDescriptors);\n\t\t\t}\n\t\t\t// Generate admin registry module with plugin components\n\t\t\tif (id === RESOLVED_VIRTUAL_ADMIN_REGISTRY_ID) {\n\t\t\t\t// Include both trusted and sandboxed plugins\n\t\t\t\tconst allDescriptors = [...pluginDescriptors, ...(resolvedConfig.sandboxed ?? [])];\n\t\t\t\treturn generateAdminRegistryModule(allDescriptors);\n\t\t\t}\n\t\t\t// Generate sandbox runner module\n\t\t\tif (id === RESOLVED_VIRTUAL_SANDBOX_RUNNER_ID) {\n\t\t\t\treturn generateSandboxRunnerModule(resolvedConfig.sandboxRunner, resolvedConfig.sandbox);\n\t\t\t}\n\t\t\t// Generate sandboxed plugins config module\n\t\t\tif (id === RESOLVED_VIRTUAL_SANDBOXED_PLUGINS_ID) {\n\t\t\t\t// Pass project root for proper module resolution\n\t\t\t\tconst projectRoot = fileURLToPath(astroConfig.root);\n\t\t\t\treturn generateSandboxedPluginsModule(\n\t\t\t\t\tresolvedConfig.sandboxed ?? [],\n\t\t\t\t\tprojectRoot,\n\t\t\t\t\t(filePath) => this.addWatchFile(filePath),\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Generate auth module that statically imports the configured auth provider\n\t\t\tif (id === RESOLVED_VIRTUAL_AUTH_ID) {\n\t\t\t\tconst authDescriptor = resolvedConfig.auth;\n\t\t\t\tif (!authDescriptor || !(\"entrypoint\" in authDescriptor)) {\n\t\t\t\t\treturn generateAuthModule(undefined);\n\t\t\t\t}\n\t\t\t\treturn generateAuthModule(authDescriptor.entrypoint);\n\t\t\t}\n\t\t\t// Generate auth providers module (pluggable login methods)\n\t\t\tif (id === RESOLVED_VIRTUAL_AUTH_PROVIDERS_ID) {\n\t\t\t\treturn generateAuthProvidersModule(resolvedConfig.authProviders ?? []);\n\t\t\t}\n\t\t\t// Generate media providers module\n\t\t\tif (id === RESOLVED_VIRTUAL_MEDIA_PROVIDERS_ID) {\n\t\t\t\treturn generateMediaProvidersModule(resolvedConfig.mediaProviders ?? []);\n\t\t\t}\n\t\t\t// Generate block components module (plugin rendering components for PortableText)\n\t\t\tif (id === RESOLVED_VIRTUAL_BLOCK_COMPONENTS_ID) {\n\t\t\t\treturn generateBlockComponentsModule(pluginDescriptors);\n\t\t\t}\n\t\t\t// Generate seed module — embeds user seed or default at build time\n\t\t\tif (id === RESOLVED_VIRTUAL_SEED_ID) {\n\t\t\t\tconst projectRoot = fileURLToPath(astroConfig.root);\n\t\t\t\treturn generateSeedModule(projectRoot, viteCommand === \"serve\");\n\t\t\t}\n\t\t\t// Generate wait-until module — re-exports cloudflare:workers'\n\t\t\t// waitUntil under the Cloudflare adapter, undefined otherwise.\n\t\t\tif (id === RESOLVED_VIRTUAL_WAIT_UNTIL_ID) {\n\t\t\t\treturn generateWaitUntilModule(astroConfig.adapter?.name);\n\t\t\t}\n\t\t\t// Generate scheduler module — a NodeCronScheduler factory on\n\t\t\t// long-lived runtimes, or null under the Cloudflare adapter where\n\t\t\t// a Cron Trigger drives scheduled work instead.\n\t\t\t//\n\t\t\t// Decide from Astro's command, not Vite's config.command: the\n\t\t\t// Cloudflare adapter builds the worker bundle via a nested Vite\n\t\t\t// *build* pass even during `astro dev`, so viteCommand reports\n\t\t\t// \"build\" and would wrongly suppress the in-process timer (#1635).\n\t\t\t// Astro's command stays \"dev\", which is the only case that should\n\t\t\t// fall through to a NodeCronScheduler.\n\t\t\tif (id === RESOLVED_VIRTUAL_SCHEDULER_ID) {\n\t\t\t\tconst schedulerCommand = astroCommand === \"dev\" ? \"serve\" : \"build\";\n\t\t\t\treturn generateSchedulerModule(astroConfig.adapter?.name, schedulerCommand);\n\t\t\t}\n\t\t\t// Generate env module — re-exports cloudflare:workers' env under\n\t\t\t// the Cloudflare adapter, undefined otherwise (#1736).\n\t\t\tif (id === RESOLVED_VIRTUAL_ENV_ID) {\n\t\t\t\treturn generateEnvModule(astroConfig.adapter?.name);\n\t\t\t}\n\t\t\tif (id === RESOLVED_VIRTUAL_BUILD_ID) {\n\t\t\t\treturn generateBuildModule(buildTime);\n\t\t\t}\n\t\t},\n\t};\n}\n\n/**\n * Modules that contain native Node.js addons or Node-only code.\n * These must be external in SSR to avoid bundling failures on Node.\n * On Cloudflare, the adapter handles its own externalization — setting\n * ssr.external there conflicts with @cloudflare/vite-plugin's validation.\n */\n// Matches the admin stylesheet import with or without a trailing query (e.g.\n// `?url`), so both forms resolve to dist rather than the source alias.\nconst ADMIN_STYLES_ALIAS = /^@emdash-cms\\/admin\\/styles\\.css/;\n\nconst NODE_NATIVE_EXTERNALS = [\n\t\"better-sqlite3\",\n\t\"bindings\",\n\t\"file-uri-to-path\",\n\t\"@libsql/kysely-libsql\",\n\t\"pg\",\n];\n\n/**\n * Detect whether the Cloudflare adapter is being used.\n */\nfunction isCloudflareAdapter(astroConfig: AstroConfig): boolean {\n\treturn astroConfig.adapter?.name === \"@astrojs/cloudflare\";\n}\n\n/**\n * Creates the Vite config update for EmDash.\n */\nexport function createViteConfig(\n\toptions: VitePluginOptions,\n\tcommand: \"dev\" | \"build\" | \"preview\" | \"sync\",\n): NonNullable<AstroConfig[\"vite\"]> {\n\tconst adminDistPath = resolveAdminDist();\n\tconst cloudflare = isCloudflareAdapter(options.astroConfig);\n\tconst isDev = command === \"dev\";\n\tconst projectRoot = fileURLToPath(options.astroConfig.root);\n\n\tconst adminSourcePath = isDev ? resolveAdminSource(projectRoot) : undefined;\n\tconst useSource = adminSourcePath !== undefined;\n\tconst useSyncExternalStoreShimPath = resolveIntegrationShim(\"use-sync-external-store.js\");\n\tconst useSyncExternalStoreWithSelectorShimPath = resolveIntegrationShim(\n\t\t\"use-sync-external-store-with-selector.js\",\n\t);\n\n\treturn {\n\t\t// Astro SSR routes resolve version.ts from source (not tsdown dist),\n\t\t// so Vite needs its own define pass for the __EMDASH_*__ placeholders.\n\t\tdefine: {\n\t\t\t__EMDASH_VERSION__: JSON.stringify(VERSION),\n\t\t\t__EMDASH_COMMIT__: JSON.stringify(COMMIT),\n\t\t\t__EMDASH_PSEUDO_LOCALE__: JSON.stringify(\n\t\t\t\tisDev && process.env[\"EMDASH_PSEUDO_LOCALE\"] === \"1\",\n\t\t\t),\n\t\t},\n\t\tresolve: {\n\t\t\tdedupe: [\"@premium-cms/admin\", \"react\", \"react-dom\"],\n\t\t\t// Array form so more-specific entries are checked first.\n\t\t\t// The styles.css alias must come before the package alias, otherwise\n\t\t\t// Vite's prefix matching on \"@premium-cms/admin\" would resolve\n\t\t\t// \"@premium-cms/admin/styles.css\" through the source directory.\n\t\t\t// Regex (not string) so the `?url` variant — admin.astro imports the\n\t\t\t// stylesheet as `?url` to keep it out of the page CSS graph — also\n\t\t\t// resolves to dist; a string `find` only matches on a `/` or end\n\t\t\t// boundary, so `styles.css?url` would slip through to the source alias.\n\t\t\talias: [\n\t\t\t\t{ find: ADMIN_STYLES_ALIAS, replacement: resolve(adminDistPath, \"styles.css\") },\n\t\t\t\t{ find: \"@premium-cms/admin\", replacement: useSource ? adminSourcePath : adminDistPath },\n\t\t\t\t// `use-sync-external-store/shim` is a React <18 polyfill that ships\n\t\t\t\t// only as CJS. It's pulled in transitively by `@tiptap/react`. With\n\t\t\t\t// pnpm's virtual store the file lives under .pnpm/, where Vite's\n\t\t\t\t// dep scanner can't reach it for pre-bundling — so the browser is\n\t\t\t\t// served raw `module.exports` and hydration fails with\n\t\t\t\t// `SyntaxError: ... does not provide an export named\n\t\t\t\t// 'useSyncExternalStore'`. Redirect both shim entry points to a\n\t\t\t\t// tiny ESM shim file that re-exports React's built-in hook, and\n\t\t\t\t// redirect the selector entry points to an ESM wrapper around that\n\t\t\t\t// hook. The absolute file paths are required because Vite/Rolldown\n\t\t\t\t// dependency optimization applies aliases without EmDash's virtual\n\t\t\t\t// module plugin. This also avoids the package main entry's React\n\t\t\t\t// 18+ dev warning.\n\t\t\t\t{\n\t\t\t\t\tfind: \"use-sync-external-store/shim/with-selector.js\",\n\t\t\t\t\treplacement: useSyncExternalStoreWithSelectorShimPath,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tfind: \"use-sync-external-store/shim/with-selector\",\n\t\t\t\t\treplacement: useSyncExternalStoreWithSelectorShimPath,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tfind: \"use-sync-external-store/shim/index.js\",\n\t\t\t\t\treplacement: useSyncExternalStoreShimPath,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tfind: \"use-sync-external-store/shim\",\n\t\t\t\t\treplacement: useSyncExternalStoreShimPath,\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- Monorepo has both vite 6 (docs) and vite 7 (core). tsgo resolves correctly.\n\t\tplugins: [\n\t\t\tcreateVirtualModulesPlugin(options, command),\n\t\t\t// In dev mode with source alias, compile Lingui macros on the fly\n\t\t\t// and redirect locale .mjs imports to dist/.\n\t\t\t// In production, macros are pre-compiled by tsdown in the admin package.\n\t\t\t...(useSource ? [linguiMacroPlugin(adminSourcePath, adminDistPath)] : []),\n\t\t] as NonNullable<AstroConfig[\"vite\"]>[\"plugins\"],\n\t\t// Handle native modules for SSR.\n\t\t// On Node: external keeps native addons out of the SSR bundle.\n\t\t// On Cloudflare: skip — the adapter handles externalization, and setting\n\t\t// ssr.external conflicts with @cloudflare/vite-plugin's resolve.external validation.\n\t\tssr: cloudflare\n\t\t\t? {\n\t\t\t\t\tnoExternal: [\"@premium-cms/emdash\", \"@premium-cms/admin\"],\n\t\t\t\t\t// Pre-bundle EmDash's runtime deps for workerd. Without this,\n\t\t\t\t\t// Vite discovers them one-by-one on first request, causing workerd\n\t\t\t\t\t// to enter \"worker cancelled\" state on cold cache.\n\t\t\t\t\toptimizeDeps: {\n\t\t\t\t\t\t// Exclude EmDash virtual modules from esbuild's dependency\n\t\t\t\t\t\t// scan. These are resolved by the Vite plugin at transform time,\n\t\t\t\t\t\t// but esbuild encounters them when crawling emdash's dist files\n\t\t\t\t\t\t// during pre-bundling and can't resolve them. Vite's exclude\n\t\t\t\t\t\t// uses prefix matching (id.startsWith(m + \"/\")), so\n\t\t\t\t\t\t// \"virtual:emdash\" matches all \"virtual:emdash/*\" imports.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// First-party packages must also stay excluded. In a\n\t\t\t\t\t\t// real install (unlike the workspace symlink, which Vite never\n\t\t\t\t\t\t// optimizes), the optimizer bundles their dist and code-splits\n\t\t\t\t\t\t// lazily-executed dynamic imports (MCP tools, content\n\t\t\t\t\t\t// validation) into hashed chunks. A mid-session re-optimization\n\t\t\t\t\t\t// deletes those chunks while loaded modules still reference\n\t\t\t\t\t\t// them, so every content write fails with \"The file does not\n\t\t\t\t\t\t// exist at .../deps_ssr/...\" until the dev server restarts.\n\t\t\t\t\t\t// Their CJS deps are still pre-bundled via the \"parent > dep\"\n\t\t\t\t\t\t// include entries below, which resolve through excluded parents.\n\t\t\t\t\t\texclude: [\"virtual:emdash\", \"@premium-cms/emdash\", \"@premium-cms/admin\", \"@premium-cms/cloudflare\"],\n\t\t\t\t\t\tinclude: [\n\t\t\t\t\t\t\t// EmDash direct deps\n\t\t\t\t\t\t\t\"emdash > @portabletext/toolkit\",\n\t\t\t\t\t\t\t\"emdash > @unpic/placeholder\",\n\t\t\t\t\t\t\t\"emdash > blurhash\",\n\t\t\t\t\t\t\t\"emdash > croner\",\n\t\t\t\t\t\t\t\"emdash > jose\",\n\t\t\t\t\t\t\t\"emdash > jpeg-js\",\n\t\t\t\t\t\t\t\"emdash > kysely\",\n\t\t\t\t\t\t\t// Only imported by the migration runner, so the first\n\t\t\t\t\t\t\t// dev-bypass/setup request would otherwise discover it.\n\t\t\t\t\t\t\t\"emdash > kysely/migration\",\n\t\t\t\t\t\t\t\"emdash > mime/lite\",\n\t\t\t\t\t\t\t\"emdash > modern-tar\",\n\t\t\t\t\t\t\t\"emdash > sanitize-html\",\n\t\t\t\t\t\t\t\"emdash > ulidx\",\n\t\t\t\t\t\t\t\"emdash > upng-js\",\n\t\t\t\t\t\t\t\"emdash > astro-portabletext\",\n\t\t\t\t\t\t\t\"emdash > sax\",\n\t\t\t\t\t\t\t// Deeper transitive deps\n\t\t\t\t\t\t\t\"emdash > sanitize-html > parse5\",\n\t\t\t\t\t\t\t\"emdash > @premium-cms/gutenberg-to-portable-text > @wordpress/block-serialization-default-parser\",\n\t\t\t\t\t\t\t\"emdash > @premium-cms/auth > @oslojs/crypto/ecdsa\",\n\t\t\t\t\t\t\t\"emdash > @premium-cms/auth > @oslojs/crypto/sha2\",\n\t\t\t\t\t\t\t\"emdash > @premium-cms/auth > @oslojs/webauthn\",\n\t\t\t\t\t\t\t// Auth deps imported only on auth/login/callback routes, so\n\t\t\t\t\t\t\t// the initial page scan misses them. Pre-bundle to avoid a\n\t\t\t\t\t\t\t// re-optimize + reload cascade on first authenticated request.\n\t\t\t\t\t\t\t\"emdash > @oslojs/crypto/hmac\",\n\t\t\t\t\t\t\t\"emdash > @oslojs/crypto/subtle\",\n\t\t\t\t\t\t\t\"emdash > @oslojs/crypto/rsa\",\n\t\t\t\t\t\t\t\"emdash > arctic\",\n\t\t\t\t\t\t\t// MCP server entrypoints — only imported on the MCP route, so\n\t\t\t\t\t\t\t// missed by the initial scan.\n\t\t\t\t\t\t\t\"emdash > @modelcontextprotocol/server\",\n\t\t\t\t\t\t\t\"emdash > @modelcontextprotocol/server/validators/cf-worker\",\n\t\t\t\t\t\t\t// Admin shell SSR deps, reached only when the admin route is\n\t\t\t\t\t\t\t// first rendered.\n\t\t\t\t\t\t\t\"emdash > @premium-cms/admin > @lingui/react\",\n\t\t\t\t\t\t\t\"emdash > @premium-cms/admin > @cloudflare/kumo/primitives\",\n\t\t\t\t\t\t\t// React (commonly used, may be hoisted)\n\t\t\t\t\t\t\t\"react\",\n\t\t\t\t\t\t\t\"react/jsx-dev-runtime\",\n\t\t\t\t\t\t\t\"react/jsx-runtime\",\n\t\t\t\t\t\t\t\"react-dom\",\n\t\t\t\t\t\t\t\"react-dom/server\",\n\t\t\t\t\t\t\t// Top-level deps (use astro > path for pnpm compat)\n\t\t\t\t\t\t\t\"astro > zod/v4\",\n\t\t\t\t\t\t\t\"astro > zod/v4/core\",\n\t\t\t\t\t\t\t\"astro/zod\",\n\t\t\t\t\t\t\t// zod-generator imports the bare `zod` entry, not `zod/v4`\n\t\t\t\t\t\t\t\"emdash > zod\",\n\t\t\t\t\t\t\t\"@premium-cms/cloudflare > kysely-d1\",\n\t\t\t\t\t\t\t// Astro internal deps not covered by @astrojs/cloudflare adapter\n\t\t\t\t\t\t\t\"astro/virtual-modules/middleware.js\",\n\t\t\t\t\t\t\t\"astro/virtual-modules/live-config\",\n\t\t\t\t\t\t\t\"astro/content/runtime\",\n\t\t\t\t\t\t\t\"astro/assets/utils/inferRemoteSize.js\",\n\t\t\t\t\t\t\t\"astro/assets/fonts/runtime.js\",\n\t\t\t\t\t\t\t\"astro/assets/services/noop\",\n\t\t\t\t\t\t\t\"@astrojs/cloudflare/image-service\",\n\t\t\t\t\t\t\t// Only imported by the /_image route, so the first image\n\t\t\t\t\t\t\t// request would otherwise discover it.\n\t\t\t\t\t\t\t\"@astrojs/cloudflare/image-transform-endpoint\",\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\texternal: NODE_NATIVE_EXTERNALS,\n\t\t\t\t\tnoExternal: [\"@premium-cms/emdash\", \"@premium-cms/admin\"],\n\t\t\t\t},\n\t\toptimizeDeps: {\n\t\t\t// When using source, don't pre-bundle JS — let Vite transform on the fly for HMR.\n\t\t\t// When using dist, pre-bundle to avoid re-optimization on first hydration.\n\t\t\tinclude: useSource\n\t\t\t\t? [\"@astrojs/react/client.js\"]\n\t\t\t\t: [\"@premium-cms/admin\", \"@astrojs/react/client.js\"],\n\t\t\texclude: cloudflare ? [\"virtual:emdash\"] : [...NODE_NATIVE_EXTERNALS, \"virtual:emdash\"],\n\t\t},\n\t};\n}\n","/**\n * Runtime utilities for EmDash\n *\n * This file contains functions that are used at runtime (in middleware, routes, etc.)\n * and must work in all environments including Cloudflare Workers.\n *\n * DO NOT import Node.js-only modules here (fs, path, module, etc.)\n */\n\nimport type { ManifestHookEntry, ManifestRouteEntry } from \"@premium-cms/plugin-types\";\n\nimport type { AuthDescriptor, AuthProviderDescriptor } from \"../../auth/types.js\";\nimport type { RuntimeMigrationConfig } from \"../../database/migrations/policy.js\";\nimport type { DatabaseDescriptor } from \"../../db/adapters.js\";\nimport type { MediaProviderDescriptor } from \"../../media/types.js\";\nimport type { ObjectCacheDescriptor } from \"../../object-cache/types.js\";\nimport type {\n\tFieldWidgetConfig,\n\tPluginMcpManifestConfig,\n\tPortableTextBlockConfig,\n\tResolvedPlugin,\n\tSettingField,\n} from \"../../plugins/types.js\";\nimport type { ExperimentalConfig } from \"../../registry/types.js\";\nimport type { StorageDescriptor } from \"../storage/types.js\";\n\nexport type { ExperimentalConfig, RegistryConfig } from \"../../registry/types.js\";\n\nexport type { ResolvedPlugin };\nexport type { MediaProviderDescriptor };\n\n/**\n * Admin page definition (copied from plugins/types to avoid circular deps)\n */\nexport interface PluginAdminPage {\n\tpath: string;\n\tlabel: string;\n\ticon?: string;\n}\n\n/**\n * Dashboard widget definition (copied from plugins/types to avoid circular deps)\n */\nexport interface PluginDashboardWidget {\n\tid: string;\n\tsize?: \"full\" | \"half\" | \"third\";\n\ttitle?: string;\n}\n\n/**\n * Plugin descriptor - returned by plugin factory functions\n *\n * Contains all static metadata needed for manifest and admin UI,\n * plus the entrypoint for runtime instantiation.\n *\n * @example\n * ```ts\n * export function myPlugin(options?: MyPluginOptions): PluginDescriptor {\n *   return {\n *     id: \"my-plugin\",\n *     version: \"1.0.0\",\n *     entrypoint: \"@my-org/emdash-plugin-foo\",\n *     options: options ?? {},\n *     adminEntry: \"@my-org/emdash-plugin-foo/admin\",\n *     adminPages: [{ path: \"/settings\", label: \"Settings\" }],\n *   };\n * }\n * ```\n */\n/**\n * Storage collection declaration for sandboxed plugins\n */\nexport interface StorageCollectionDeclaration {\n\tindexes?: string[];\n\tuniqueIndexes?: string[];\n}\n\nexport interface PluginDescriptor<TOptions = Record<string, unknown>> {\n\t/** Unique plugin identifier */\n\tid: string;\n\t/** Plugin version (semver) */\n\tversion: string;\n\t/** Module specifier to import (e.g., \"@premium-cms/plugin-api-test\") */\n\tentrypoint: string;\n\t/**\n\t * Options to pass to createPlugin(). Native format only.\n\t * Standard-format plugins configure themselves via KV settings\n\t * and Block Kit admin pages -- not constructor options.\n\t */\n\toptions?: TOptions;\n\t/**\n\t * Plugin format. Determines how the entrypoint is loaded:\n\t * - `\"standard\"` -- exports `definePlugin({ hooks, routes })` as default.\n\t *   Wrapped with `adaptSandboxEntry` for in-process execution. Can run in both\n\t *   `plugins: []` (in-process) and `sandboxed: []` (isolate).\n\t * - `\"native\"` -- exports `createPlugin(options)` returning a `ResolvedPlugin`.\n\t *   Can only run in `plugins: []`. Cannot be sandboxed or published to marketplace.\n\t *\n\t * Defaults to `\"native\"` when unset.\n\t *\n\t */\n\tformat?: \"standard\" | \"native\";\n\t/** Admin UI module specifier (e.g., \"@premium-cms/plugin-audit-log/admin\") */\n\tadminEntry?: string;\n\t/** Module specifier for site-side Astro rendering components (must export `blockComponents`) */\n\tcomponentsEntry?: string;\n\t/** Admin pages for navigation */\n\tadminPages?: PluginAdminPage[];\n\t/** Dashboard widgets */\n\tadminWidgets?: PluginDashboardWidget[];\n\t/** Settings schema for the auto-generated admin settings form */\n\tsettingsSchema?: Record<string, SettingField>;\n\t/**\n\t * Portable Text block types this plugin contributes to the editor.\n\t * Declarative (Block Kit) — surfaced in the admin slash menu and consumed\n\t * from the manifest, so standard/sandboxed plugins can contribute blocks\n\t * without a native render component.\n\t */\n\tportableTextBlocks?: PortableTextBlockConfig[];\n\t/** Field widget types this plugin contributes for schema-field editing UIs. */\n\tfieldWidgets?: FieldWidgetConfig[];\n\n\t// === Sandbox-specific fields (for sandboxed plugins) ===\n\n\t/**\n\t * Capabilities the plugin requests.\n\t * For standard-format plugins, capabilities are enforced in both trusted and\n\t * sandboxed modes via the PluginContextFactory.\n\t */\n\tcapabilities?: string[];\n\t/**\n\t * Allowed hosts for network:fetch capability\n\t * Supports wildcards like \"*.example.com\"\n\t */\n\tallowedHosts?: string[];\n\t/**\n\t * Storage collections the plugin declares\n\t * Sandboxed plugins can only access declared collections.\n\t */\n\tstorage?: Record<string, StorageCollectionDeclaration>;\n\t/** Serialized MCP declarations emitted by the plugin build. */\n\tmcp?: PluginMcpManifestConfig;\n\t/**\n\t * Route declarations for sandboxed config-declared plugins. Mirrors\n\t * definePlugin({ routes }) and drives route auth decisions; omitted routes\n\t * default to non-public.\n\t */\n\troutes?: Array<ManifestRouteEntry | string>;\n\t/**\n\t * Hook declarations for sandboxed config-declared plugins. Mirrors\n\t * definePlugin({ hooks }).\n\t */\n\thooks?: Array<ManifestHookEntry | string>;\n}\n\n/**\n * Sandboxed plugin descriptor - same format as PluginDescriptor\n *\n * These run in isolated V8 isolates via Worker Loader on Cloudflare.\n * The `entrypoint` is resolved to a file and bundled at build time.\n */\nexport type SandboxedPluginDescriptor<TOptions = Record<string, unknown>> =\n\tPluginDescriptor<TOptions>;\n\nexport interface EmDashConfig {\n\t/**\n\t * Database configuration\n\t *\n\t * Use one of the adapter functions:\n\t * - `sqlite({ url: \"file:./data.db\" })` - Local SQLite\n\t * - `libsql({ url: \"...\", authToken: \"...\" })` - Turso/libSQL\n\t * - `d1({ binding: \"DB\" })` - Cloudflare D1\n\t *\n\t * @example\n\t * ```ts\n\t * import { sqlite } from \"@premium-cms/emdash/db\";\n\t *\n\t * emdash({\n\t *   database: sqlite({ url: \"file:./data.db\" }),\n\t * })\n\t * ```\n\t */\n\tdatabase?: DatabaseDescriptor;\n\t/** Core database migration behavior at runtime. Defaults to `auto`. */\n\tmigrations?: RuntimeMigrationConfig;\n\t/**\n\t * Storage configuration (for media)\n\t */\n\tstorage?: StorageDescriptor;\n\n\t/**\n\t * Optional distributed object cache for query results.\n\t *\n\t * Off by default. When configured, content and chrome (settings, menus,\n\t * taxonomies) reads are cached in a fast key/value store and served without\n\t * touching the database on repeat requests across isolates. This offloads\n\t * read pressure from D1/SQLite, which is especially valuable on Cloudflare\n\t * where D1 has far lower request capacity than KV.\n\t *\n\t * Use a backend adapter:\n\t * - `memoryCache()` from `emdash/astro` — in-isolate (Node / local dev)\n\t * - `kvCache({ binding: \"CACHE\" })` from `@premium-cms/cloudflare` — KV\n\t *\n\t * Preview and visual-edit requests bypass the cache, so editors previewing\n\t * see live content. All other reads — including authenticated browsing outside\n\t * edit mode — are served from the cache, which only ever stores published\n\t * content. After an edit, anonymous visitors may see stale content until other\n\t * isolates pick up the bumped epoch: immediate with the memory backend, and on\n\t * KV bounded by KV's edge-cache propagation (eventual consistency, up to ~60s)\n\t * plus the isolate-local `revalidate` window (default 1s).\n\t *\n\t * Scheduled content becomes visible at query time (no write event fires when\n\t * its publish time passes), so a cached list/entry won't surface a newly-due\n\t * scheduled item until the next write to that collection or until the\n\t * entry's TTL lapses (`defaultTtl`, default 1h). Sites that rely on precise\n\t * scheduled publishing should lower `defaultTtl` accordingly.\n\t *\n\t * @example\n\t * ```ts\n\t * import { kvCache } from \"@premium-cms/cloudflare\";\n\t *\n\t * emdash({\n\t *   database: d1({ binding: \"DB\" }),\n\t *   objectCache: kvCache({ binding: \"CACHE\" }),\n\t * })\n\t * ```\n\t */\n\tobjectCache?: ObjectCacheDescriptor;\n\t/**\n\t * Image optimization.\n\t *\n\t * By default EmDash wraps Astro's image endpoint so media served from\n\t * storage is optimized through the normal `<Image>` / `getImage` pipeline,\n\t * loading source bytes directly from the storage adapter (works behind\n\t * Cloudflare Access). Set to `false` to leave Astro's image endpoint\n\t * untouched -- media then renders as a plain `<img>` unless your image\n\t * service can fetch it over HTTP.\n\t */\n\timages?: boolean;\n\t/**\n\t * Trusted plugins to load (run in main isolate)\n\t *\n\t * @example\n\t * ```ts\n\t * import auditLog from \"@premium-cms/plugin-audit-log\";\n\t * import webhookNotifier from \"@premium-cms/plugin-webhook-notifier\";\n\t *\n\t * emdash({\n\t *   plugins: [auditLog, webhookNotifier],\n\t * })\n\t * ```\n\t */\n\tplugins?: PluginDescriptor[];\n\t/**\n\t * Sandboxed plugins to load (run in isolated V8 isolates)\n\t *\n\t * Only works on Cloudflare with Worker Loader enabled.\n\t * Uses the same format as `plugins` - the difference is where they run.\n\t *\n\t * @example\n\t * ```ts\n\t * import { untrustedPlugin } from \"some-third-party-plugin\";\n\t *\n\t * emdash({\n\t *   plugins: [trustedPlugin()],     // runs in host\n\t *   sandboxed: [untrustedPlugin()], // runs in isolate\n\t *   sandboxRunner: \"@premium-cms/sandbox-cloudflare\",\n\t * })\n\t * ```\n\t */\n\tsandboxed?: SandboxedPluginDescriptor[];\n\t/**\n\t * Module that exports the sandbox runner factory.\n\t * Required if using sandboxed plugins.\n\t *\n\t * @example\n\t * ```ts\n\t * emdash({\n\t *   sandboxRunner: \"@premium-cms/sandbox-cloudflare\",\n\t * })\n\t * ```\n\t */\n\tsandboxRunner?: string;\n\n\t/**\n\t * Explicitly disable plugin sandboxing, even if a sandbox runner is configured.\n\t * Use this as a debugging escape hatch to determine whether a bug is in your\n\t * plugin code or in the sandbox runtime.\n\t *\n\t * When set to `false`, all plugins run in-process without isolation.\n\t *\n\t * @default true (sandboxing enabled if sandboxRunner is configured)\n\t */\n\tsandbox?: boolean;\n\n\t/**\n\t * Authentication configuration\n\t *\n\t * Use an auth adapter function from a platform package:\n\t * - `access({ teamDomain: \"...\" })` from `@premium-cms/cloudflare`\n\t *\n\t * When an external auth provider is configured, passkey auth is disabled.\n\t *\n\t * @example\n\t * ```ts\n\t * import { access } from \"@premium-cms/cloudflare\";\n\t *\n\t * emdash({\n\t *   auth: access({\n\t *     teamDomain: \"myteam.cloudflareaccess.com\",\n\t *     audience: \"abc123...\",\n\t *     roleMapping: {\n\t *       \"Admins\": 50,\n\t *       \"Editors\": 30,\n\t *     },\n\t *   }),\n\t * })\n\t * ```\n\t */\n\tauth?: AuthDescriptor;\n\n\t/**\n\t * Pluggable auth providers (login methods on the login page).\n\t *\n\t * Auth providers appear as options alongside passkey on the login page\n\t * and setup wizard. Any provider can be used to create the initial\n\t * admin account. Passkey is built-in; providers listed here are additive.\n\t *\n\t * @example\n\t * ```ts\n\t * import { atproto } from \"@premium-cms/auth-atproto\";\n\t *\n\t * emdash({\n\t *   authProviders: [atproto()],\n\t * })\n\t * ```\n\t */\n\tauthProviders?: AuthProviderDescriptor[];\n\n\t/**\n\t * MCP (Model Context Protocol) server endpoint.\n\t *\n\t * Exposes an MCP Streamable HTTP server at `/_emdash/api/mcp`\n\t * that allows AI agents and tools to interact with the CMS using\n\t * the standardized MCP protocol.\n\t *\n\t * Enabled by default. The endpoint requires bearer token auth, so\n\t * it has no effect unless the user creates an API token and\n\t * configures a client. Set to `false` to disable.\n\t *\n\t * @default true\n\t */\n\tmcp?: boolean;\n\n\t/**\n\t * Plugin marketplace URL\n\t *\n\t * When set, enables the marketplace features: browse, install, update,\n\t * and uninstall plugins from a remote marketplace.\n\t *\n\t * Must be an HTTPS URL in production, or localhost/127.0.0.1 in dev.\n\t * Requires `sandboxRunner` to be configured (marketplace plugins run sandboxed).\n\t *\n\t * When `registry` is also configured, the registry replaces the marketplace\n\t * for the admin UI's browse and install flows. Existing marketplace-installed\n\t * plugins continue to work; new installs and updates come from the registry.\n\t *\n\t * @example\n\t * ```ts\n\t * emdash({\n\t *   marketplace: \"https://marketplace.emdashcms.com\",\n\t *   sandboxRunner: \"@premium-cms/sandbox-cloudflare\",\n\t * })\n\t * ```\n\t */\n\tmarketplace?: string;\n\n\t/**\n\t * Experimental features.\n\t *\n\t * These options are not yet stable. Shape, defaults, and behavior may\n\t * change between minor versions. Use only if you're comfortable\n\t * tracking the release notes and updating your config when an\n\t * experimental feature graduates or changes.\n\t *\n\t * @example\n\t * ```ts\n\t * emdash({\n\t *   experimental: {\n\t *     registry: {\n\t *       aggregatorUrl: \"https://registry.emdashcms.com\",\n\t *     },\n\t *   },\n\t *   sandboxRunner: \"@premium-cms/sandbox-cloudflare\",\n\t * })\n\t * ```\n\t */\n\texperimental?: ExperimentalConfig;\n\n\t/**\n\t * Maximum allowed media file upload size in bytes.\n\t *\n\t * Applies to both direct multipart uploads and signed-URL uploads.\n\t * When unset, defaults to 52_428_800 (50 MB).\n\t *\n\t * @example\n\t * ```ts\n\t * emdash({ maxUploadSize: 100 * 1024 * 1024 }) // 100 MB\n\t * ```\n\t */\n\tmaxUploadSize?: number;\n\n\t/**\n\t * Public browser-facing origin for the site.\n\t *\n\t * Use when `Astro.url` / `request.url` do not match what users open — common with a\n\t * **TLS-terminating reverse proxy**: the app often sees `http://` on the internal hop\n\t * while the browser uses `https://`, which breaks WebAuthn, CSRF, OAuth, and redirect URLs.\n\t *\n\t * Set to the full origin users type in the address bar (no path), e.g.\n\t * `https://mysite.example.com`. When not set, falls back to environment variables\n\t * `EMDASH_SITE_URL` > `SITE_URL`, then to the request URL's origin.\n\t *\n\t * Replaces `passkeyPublicOrigin` (which only fixed passkeys).\n\t */\n\tsiteUrl?: string;\n\n\t/**\n\t * Additional origins accepted by passkey verification.\n\t *\n\t * When the same EmDash deployment is reachable under several hostnames sharing\n\t * a registrable parent (e.g. `https://example.com` plus\n\t * `https://preview.example.com`), the canonical `siteUrl` defines the `rpId`\n\t * and the entries here are the *additional* origins from which assertions\n\t * are accepted. Each entry must be the same hostname as `siteUrl` or a\n\t * subdomain of it — WebAuthn requires `rpId` to be a registrable suffix of\n\t * every origin.\n\t *\n\t * Merged at runtime with the `EMDASH_ALLOWED_ORIGINS` env var (comma-separated).\n\t * Validation:\n\t *   - Config-declared entries are shape-checked at Astro startup.\n\t *   - Subdomain relationship to `siteUrl` is checked at startup when\n\t *     `siteUrl` is also config-declared, otherwise at first passkey\n\t *     verification (since `siteUrl` may come from `EMDASH_SITE_URL`).\n\t *\n\t * Mismatches throw with a source-attributed message naming\n\t * `config.allowedOrigins` or `EMDASH_ALLOWED_ORIGINS`.\n\t *\n\t * @example\n\t * ```ts\n\t * emdash({\n\t *   siteUrl: \"https://example.com\",\n\t *   allowedOrigins: [\"https://preview.example.com\"],\n\t * })\n\t * ```\n\t */\n\tallowedOrigins?: string[];\n\t/*\n\t * Headers to trust for client IP resolution when running behind a reverse\n\t * proxy. The first header in this list that is present on the request\n\t * wins. Applies to rate limiting for auth endpoints and comment\n\t * submission.\n\t *\n\t * Common values:\n\t * - `x-real-ip` — nginx, Caddy, Traefik\n\t * - `fly-client-ip` — Fly.io\n\t * - `x-forwarded-for` — generic (first entry is used)\n\t *\n\t * Only set this when you **control the reverse proxy**. Untrusted\n\t * clients can set any header they like; trusting headers from an open\n\t * network is an IP-spoofing vulnerability that defeats rate limiting.\n\t *\n\t * On Cloudflare the `cf` object on the request is used automatically —\n\t * you normally don't need to set this. Leave unset (or empty) to\n\t * preserve the default: IP is resolved only when the request came\n\t * through Cloudflare's edge.\n\t *\n\t * Falls back to `EMDASH_TRUSTED_PROXY_HEADERS` env var (comma-separated)\n\t * when this option is not set, so operators can configure at deploy\n\t * time without touching the Astro config.\n\t */\n\ttrustedProxyHeaders?: string[];\n\n\t/**\n\t * User middleware that wraps the complete EmDash request pipeline.\n\t *\n\t * Before `next()` it runs before EmDash initializes its runtime or database,\n\t * so `locals.emdash`, the authenticated user, and request-scoped EmDash state\n\t * are unavailable. This allows cached responses and request gates to return\n\t * without paying initialization cost. When it calls `next()`, the resolved\n\t * response includes EmDash HTML injection and all other response mutations,\n\t * allowing the middleware to finalize caching and response headers safely.\n\t */\n\tmiddleware?: {\n\t\t/** Astro middleware module entrypoint. */\n\t\touter: string | URL;\n\t};\n\n\t/**\n\t * Enable playground mode for ephemeral \"try EmDash\" sites.\n\t *\n\t * When set, the integration injects a playground middleware (order: \"pre\")\n\t * that runs BEFORE the normal EmDash middleware chain. It creates an\n\t * isolated Durable Object database per session, runs migrations, applies\n\t * the seed, creates an anonymous admin user, and sets the DB in ALS.\n\t * By the time the runtime middleware runs, the database is fully ready.\n\t *\n\t * Setup and auth middleware are skipped (the playground handles both).\n\t *\n\t * Requires `@premium-cms/cloudflare` as a dependency and a DO binding\n\t * in wrangler.jsonc.\n\t *\n\t * @example\n\t * ```ts\n\t * emdash({\n\t *   database: playgroundDatabase({ binding: \"PLAYGROUND_DB\" }),\n\t *   playground: {\n\t *     middlewareEntrypoint: \"@premium-cms/cloudflare/db/playground-middleware\",\n\t *   },\n\t * })\n\t * ```\n\t */\n\tplayground?: {\n\t\t/** Module path for the playground middleware. */\n\t\tmiddlewareEntrypoint: string;\n\t};\n\n\t/**\n\t * Media providers for browsing and uploading media\n\t *\n\t * The local media provider (using storage adapter) is available by default.\n\t * Additional providers can be added for external services like Unsplash,\n\t * Cloudinary, Mux, Cloudflare Images, etc.\n\t *\n\t * @example\n\t * ```ts\n\t * import { cloudflareImages, cloudflareStream } from \"@premium-cms/cloudflare\";\n\t * import { unsplash } from \"@premium-cms/provider-unsplash\";\n\t *\n\t * emdash({\n\t *   mediaProviders: [\n\t *     cloudflareImages({ accountId: \"...\" }),\n\t *     cloudflareStream({ accountId: \"...\" }),\n\t *     unsplash({ accessKey: \"...\" }),\n\t *   ],\n\t * })\n\t * ```\n\t */\n\tmediaProviders?: MediaProviderDescriptor[];\n\n\t/**\n\t * Admin UI font configuration.\n\t *\n\t * By default, EmDash loads Noto Sans via the Astro Font API, covering\n\t * Latin, Latin Extended, Cyrillic, Cyrillic Extended, Greek, Greek\n\t * Extended, Devanagari, and Vietnamese. Fonts are downloaded from\n\t * Google at build time and self-hosted, so there are no runtime CDN\n\t * requests.\n\t *\n\t * To add support for additional writing systems (Arabic, CJK, etc.),\n\t * pass script names. EmDash resolves the matching Noto Sans variant\n\t * from Google Fonts and merges all script faces under a single\n\t * font-family, so the browser downloads only the glyphs it needs\n\t * via unicode-range.\n\t *\n\t * Set to `false` to disable font injection entirely and use system fonts.\n\t *\n\t * @example\n\t * ```ts\n\t * // Add Arabic and Japanese support\n\t * emdash({\n\t *   fonts: {\n\t *     scripts: [\"arabic\", \"japanese\"],\n\t *   },\n\t * })\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * // Disable web fonts entirely (use system fonts)\n\t * emdash({\n\t *   fonts: false,\n\t * })\n\t * ```\n\t */\n\tfonts?:\n\t\t| false\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * Additional Noto Sans script families to include.\n\t\t\t\t *\n\t\t\t\t * Available scripts: arabic, armenian, bengali, chinese-simplified,\n\t\t\t\t * chinese-traditional, chinese-hongkong, devanagari, ethiopic, farsi,\n\t\t\t\t * georgian, gujarati, gurmukhi, hebrew, japanese, kannada, khmer,\n\t\t\t\t * korean, lao, malayalam, myanmar, oriya, sinhala, tamil, telugu,\n\t\t\t\t * thai, tibetan.\n\t\t\t\t */\n\t\t\t\tscripts?: string[];\n\t\t  };\n\n\t/**\n\t * Admin UI branding (white-labeling).\n\t *\n\t * Overrides the default EmDash logo and name in the admin panel.\n\t * Use this to white-label the CMS for agency or enterprise deployments.\n\t * These settings are separate from the public site settings (title, logo,\n\t * favicon) which remain available for SEO and front-end use.\n\t *\n\t * @example\n\t * ```ts\n\t * emdash({\n\t *   admin: {\n\t *     logo: \"/images/agency-logo.webp\",\n\t *     siteName: \"AgencyX CMS\",\n\t *     favicon: \"/favicon.ico\",\n\t *   },\n\t * })\n\t * ```\n\t */\n\tadmin?: {\n\t\t/** URL or path to a custom logo image for the admin UI (login page, sidebar). */\n\t\tlogo?: string;\n\t\t/** Custom name displayed in the admin sidebar and browser tab. */\n\t\tsiteName?: string;\n\t\t/** URL or path to a custom favicon for the admin panel. */\n\t\tfavicon?: string;\n\t};\n\n\t/**\n\t * Editor toolbar delivery on public pages.\n\t *\n\t * - `\"server\"` (default): the toolbar is injected server-side into every\n\t *   HTML response rendered for an authenticated editor. Simple and\n\t *   zero-config, but behind a shared cache (Cloudflare Cache Everything /\n\t *   Workers Cache, Fastly, Varnish, …) editors often receive the cached\n\t *   anonymous variant — without the toolbar — whenever an anonymous visitor\n\t *   primed the cache first, so the toolbar appears and disappears with\n\t *   cache state.\n\t * - `\"client\"`: public HTML is identical for everyone (nothing\n\t *   session-specific is injected server-side, so shared caches stay fully\n\t *   effective). A tiny bootstrap script shows an \"Edit\" pill for browsers\n\t *   that have logged into the admin (non-secret localStorage flag). Clicking\n\t *   it verifies the session and reloads the page with an `_edit` query\n\t *   param, which is always rendered fresh (never cached) with the full\n\t *   toolbar. Logged-out visitors opening an `_edit` URL are redirected to\n\t *   the canonical URL.\n\t * - `false`: never render the toolbar or bootstrap script.\n\t *\n\t * See the visual-editing docs for the cache-behavior details.\n\t */\n\ttoolbar?: \"server\" | \"client\" | false;\n\n\t/**\n\t * Version of Astro the host project is building with. Populated by the\n\t * integration's `astro:config:setup` hook (not authored by the user) and\n\t * surfaced to the admin and the registry install gate so a plugin's\n\t * `env:astro` requirement can be evaluated against the real host version.\n\t */\n\tastroVersion?: string;\n}\n\nconst STORED_CONFIG_KEY = Symbol.for(\"emdash:stored-config\");\nconst configHolder = globalThis as Record<symbol, unknown>;\n\n/**\n * Get stored config from global\n * This is set by the virtual module at build time\n */\nexport function getStoredConfig(): EmDashConfig | null {\n\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- globalThis singleton pattern (see request-context.ts)\n\treturn (configHolder[STORED_CONFIG_KEY] as EmDashConfig | undefined) ?? null;\n}\n\n/**\n * Set stored config in global\n * Called by the integration at config time\n */\nexport function setStoredConfig(config: EmDashConfig): void {\n\tconfigHolder[STORED_CONFIG_KEY] = config;\n}\n","/**\n * EmDash Astro Integration\n *\n * This integration:\n * - Injects the admin shell route at /_emdash/admin/[...path].astro\n * - Sets up REST API endpoints under /_emdash/api/*\n * - Configures middleware to provide database and manifest\n *\n * NOTE: This file is for build-time only. Runtime utilities are in runtime.ts\n * to avoid bundling Node.js-only code into the production build.\n */\n\nimport { createRequire } from \"node:module\";\nimport { fileURLToPath } from \"node:url\";\n\nimport type { AstroIntegration, AstroIntegrationLogger, AstroIntegrationMiddleware } from \"astro\";\n\nimport { validateAllowedOrigins, validateOriginShape } from \"../../auth/allowed-origins.js\";\nimport { normalizeMigrationConfig } from \"../../database/migrations/policy.js\";\nimport { normalizeAstroI18n } from \"../../i18n/normalize.js\";\nimport { INTERNAL_MEDIA_PREFIX } from \"../../media/normalize.js\";\nimport { getCoreMigrationIdentity } from \"../../migrations/identity.js\";\nimport {\n\tcreateMigrationIntegrationMetadata,\n\tMIGRATION_CONFIG_SYMBOL,\n} from \"../../migrations/integration-metadata.js\";\nimport { buildMigrationManifest } from \"../../migrations/manifest-builder.js\";\nimport { writeMigrationManifest } from \"../../migrations/manifest-writer.js\";\nimport type { ResolvedPlugin } from \"../../plugins/types.js\";\nimport { VERSION } from \"../../version.js\";\nimport { local } from \"../storage/adapters.js\";\nimport { notoSans } from \"./font-provider.js\";\nimport {\n\tinjectCoreRoutes,\n\tinjectBuiltinAuthRoutes,\n\tinjectAuthProviderRoutes,\n\tinjectMcpRoute,\n} from \"./routes.js\";\nimport type { EmDashConfig } from \"./runtime.js\";\nimport { createViteConfig } from \"./vite-config.js\";\n\n// Re-export runtime types and functions\nexport type {\n\tEmDashConfig,\n\tPluginDescriptor,\n\tSandboxedPluginDescriptor,\n\tResolvedPlugin,\n} from \"./runtime.js\";\nexport { getStoredConfig } from \"./runtime.js\";\n\n/**\n * Resolve the version of Astro the host project is building with, by reading\n * `astro/package.json` from the project's own dependency tree. Surfaced to the\n * admin and the registry install gate so a plugin's `env:astro` constraint can\n * be evaluated against the real host version. Returns `undefined` if Astro\n * can't be resolved (shouldn't happen in a real build, but never throw here).\n */\nfunction resolveAstroVersion(): string | undefined {\n\ttry {\n\t\tconst require = createRequire(import.meta.url);\n\t\tconst pkg = require(\"astro/package.json\") as { version?: unknown };\n\t\treturn typeof pkg.version === \"string\" ? pkg.version : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** Default storage: Local filesystem in .emdash directory */\nconst DEFAULT_STORAGE = local({\n\tdirectory: \"./.emdash/uploads\",\n\tbaseUrl: \"/_emdash/api/media/file\",\n});\n\ninterface ImageRemotePattern {\n\tprotocol?: \"http\" | \"https\";\n\thostname?: string;\n\tpathname?: string;\n}\n\n/**\n * Build `image.remotePatterns` entries so Astro will optimize EmDash media.\n *\n * Astro's image services only build a transform URL for sources allowed via\n * `image.domains` / `image.remotePatterns` (relative URLs are never optimized —\n * see `isRemoteAllowed`). We authorize the media sources automatically:\n *\n *  1. The storage adapter's public URL host (R2 custom domain, S3/CDN).\n *  2. The site's own origin, scoped to the media proxy route\n *     (`/_emdash/api/media/file/**`), so same-origin proxied media is optimized.\n *     The components absolutize the media URL against this origin; EmDash's\n *     wrapped image endpoint then serves the bytes from storage (so the absolute\n *     URL is never fetched). Only registered when `siteUrl` is known at build.\n *  3. In `astro dev` the dev-server origin isn't known at build time, so we\n *     register a host-agnostic pattern scoped to the media route. Dev-only.\n *\n * Returns an empty array when no source is statically known (production build,\n * local storage, no `siteUrl`), in which case media renders as a plain `<img>`.\n *\n * @internal Exported for unit testing.\n */\nexport function buildImageRemotePatterns(\n\tstorage: { config?: unknown } | undefined,\n\tsiteUrl: string | undefined,\n\tcommand: \"dev\" | \"build\" | \"preview\" | \"sync\",\n): ImageRemotePattern[] {\n\tconst patterns: ImageRemotePattern[] = [];\n\n\tconst config = storage?.config;\n\tconst publicUrl =\n\t\tconfig && typeof config === \"object\"\n\t\t\t? (config as { publicUrl?: unknown }).publicUrl\n\t\t\t: undefined;\n\tif (typeof publicUrl === \"string\" && publicUrl) {\n\t\ttry {\n\t\t\tconst url = new URL(publicUrl);\n\t\t\t// Only authorize http(s) hosts — a `file:`/`ftp:` URL is not a media\n\t\t\t// origin Astro can fetch.\n\t\t\tif (url.protocol === \"http:\" || url.protocol === \"https:\") {\n\t\t\t\tconst pattern: ImageRemotePattern = {\n\t\t\t\t\tprotocol: url.protocol === \"http:\" ? \"http\" : \"https\",\n\t\t\t\t\thostname: url.hostname,\n\t\t\t\t};\n\t\t\t\t// When the public URL has a path prefix (CDN sub-path), scope the\n\t\t\t\t// pattern to it so we don't authorize the entire host. Media keys\n\t\t\t\t// are appended as `${publicUrl}/${key}`, so the prefix is exact.\n\t\t\t\tconst prefix = url.pathname.endsWith(\"/\") ? url.pathname.slice(0, -1) : url.pathname;\n\t\t\t\tif (prefix && prefix !== \"/\") {\n\t\t\t\t\tpattern.pathname = `${prefix}/**`;\n\t\t\t\t}\n\t\t\t\tpatterns.push(pattern);\n\t\t\t}\n\t\t} catch {\n\t\t\t// ignore an unparseable public URL\n\t\t}\n\t}\n\n\tif (siteUrl) {\n\t\ttry {\n\t\t\tpatterns.push({\n\t\t\t\thostname: new URL(siteUrl).hostname,\n\t\t\t\tpathname: `${INTERNAL_MEDIA_PREFIX}**`,\n\t\t\t});\n\t\t} catch {\n\t\t\t// ignore an unparseable site URL\n\t\t}\n\t}\n\n\tif (command === \"dev\") {\n\t\tpatterns.push({ pathname: `${INTERNAL_MEDIA_PREFIX}**` });\n\t}\n\n\treturn patterns;\n}\n\n/**\n * Stock image endpoints EmDash may safely replace with its storage-backed\n * wrapper. Our wrapper delegates non-EmDash images to the platform's transform\n * endpoint, so we only override endpoints whose transform we can delegate to.\n */\nconst OVERRIDABLE_IMAGE_ENDPOINTS = new Set([\n\t\"astro/assets/endpoint/generic\",\n\t\"astro/assets/endpoint/node\",\n\t\"astro/assets/endpoint/dev\",\n\t\"@astrojs/cloudflare/image-transform-endpoint\",\n]);\n\n/**\n * Stock endpoints that deliberately don't transform (the user opted into\n * passthrough). We leave these untouched -- and without a warning, since it's a\n * supported choice, not a custom endpoint. Overriding would route non-EmDash\n * images through a transformer the passthrough setup doesn't provide.\n */\nconst PASSTHROUGH_IMAGE_ENDPOINTS = new Set([\"@astrojs/cloudflare/image-passthrough-endpoint\"]);\n\n/**\n * Decide which image endpoint to install (if any). EmDash wraps Astro's image\n * endpoint so EmDash media bytes load from storage; the wrapper delegates other\n * images back to the platform's stock endpoint.\n *\n * Returns `{ entrypoint }` to install, `{ warn }` to skip with a warning (a\n * custom endpoint we can't delegate to), or `{}` to skip silently (opted out).\n *\n * @internal Exported for unit testing.\n */\nexport function resolveImageEndpoint(opts: {\n\timagesDisabled: boolean;\n\tcurrentEntrypoint: string | undefined;\n\tisCloudflare: boolean;\n}): { entrypoint?: string; warn?: string } {\n\tif (opts.imagesDisabled) return {};\n\tconst current = opts.currentEntrypoint;\n\tif (current === undefined || OVERRIDABLE_IMAGE_ENDPOINTS.has(current)) {\n\t\treturn {\n\t\t\tentrypoint: opts.isCloudflare\n\t\t\t\t? \"@premium-cms/cloudflare/image-endpoint\"\n\t\t\t\t: \"@premium-cms/emdash/image-endpoint\",\n\t\t};\n\t}\n\t// A deliberate passthrough setup: leave it alone, no warning.\n\tif (PASSTHROUGH_IMAGE_ENDPOINTS.has(current)) return {};\n\treturn {\n\t\twarn:\n\t\t\t`A custom image.endpoint (${current}) is configured; EmDash will not wrap ` +\n\t\t\t`it, so storage-backed media may render unoptimized.`,\n\t};\n}\n\n/**\n * Warn when `@astrojs/react` is not registered in the host's `integrations`.\n *\n * The admin SPA is a React app hydrated via `client:only=\"react\"`. Without the\n * React integration the build succeeds and the admin route returns 200, but the\n * bundle never hydrates -- the page sits on \"Loading EmDash...\" forever with no\n * error anywhere (#962). Checked in `astro:config:done` so integrations added\n * by other integrations are visible too.\n *\n * @internal Exported for unit testing.\n */\nexport function missingReactIntegrationWarning(\n\tintegrations: readonly { name: string }[],\n): string | undefined {\n\tif (integrations.some((integration) => integration.name === \"@astrojs/react\")) {\n\t\treturn undefined;\n\t}\n\treturn (\n\t\t`@astrojs/react is not registered in your Astro config. The EmDash admin UI ` +\n\t\t`will not hydrate without it (the page stays on \"Loading EmDash...\"). ` +\n\t\t`Add it to your integrations:\\n\\n` +\n\t\t`  import react from \"@astrojs/react\";\\n` +\n\t\t`  export default defineConfig({\\n` +\n\t\t`    integrations: [react(), emdash({ ... })],\\n` +\n\t\t`  });`\n\t);\n}\n\n// Terminal formatting\nconst dim = (s: string) => `\\x1b[2m${s}\\x1b[22m`;\nconst bold = (s: string) => `\\x1b[1m${s}\\x1b[22m`;\nconst cyan = (s: string) => `\\x1b[36m${s}\\x1b[39m`;\n\n/** Print the EmDash startup banner */\nfunction printBanner(_logger: AstroIntegrationLogger): void {\n\tconst banner = `\n\n  ${bold(cyan(\"— E M D A S H —\"))}  ${dim(`v${VERSION}`)}\n   `;\n\tconsole.log(banner);\n}\n\n/**\n * Print dev-server route info with absolute (clickable) URLs, including the\n * dev-bypass shortcut that skips passkey auth. Dev only -- the dev-bypass\n * endpoint returns 403 in production.\n */\nfunction printDevServerInfo(baseUrl: string, mcpEnabled: boolean): void {\n\tconst devBypassUrl = `${baseUrl}/_emdash/api/setup/dev-bypass?redirect=/_emdash/admin`;\n\tconsole.log(`\\n  ${dim(\"›\")} Admin UI    ${cyan(`${baseUrl}/_emdash/admin`)}`);\n\tif (mcpEnabled) {\n\t\tconsole.log(`  ${dim(\"›\")} MCP server  ${cyan(`${baseUrl}/_emdash/api/mcp`)}`);\n\t}\n\tconsole.log(`  ${dim(\"›\")} Dev bypass  ${cyan(devBypassUrl)}`);\n\tconsole.log(`    ${dim(\"Skips passkey setup/auth and signs you in as a dev admin\")}`);\n\tconsole.log(\"\");\n}\n\n/**\n * Static-frontend dev banner. The admin, REST API, auth and MCP routes are\n * NOT injected locally (they are the backend's job) — under `bun dev` every\n * `/_emdash/*` request is proxied to the live backend by the site's vite\n * proxy, so print the real origins instead of advertising local routes.\n */\nfunction printStaticFrontendInfo(\n\tbaseUrl: string,\n\tdatabase?: { entrypoint?: string; config?: unknown },\n): void {\n\tconst cfg = (database?.config ?? {}) as { url?: string };\n\tconst live = !!database?.entrypoint?.endsWith(\"/snapshot-live\");\n\tif (live && cfg.url) {\n\t\tconsole.log(`\\n  ${dim(\"›\")} Static frontend ${dim(\"— live-connected, no local backend\")}`);\n\t\tconsole.log(\n\t\t\t`  ${dim(\"›\")} Content   ${cyan(`${cfg.url}/_emdash/api/snapshot`)} ${dim(\"(in-memory, auto-refresh)\")}`,\n\t\t);\n\t\tconsole.log(\n\t\t\t`  ${dim(\"›\")} Backend   ${cyan(`${baseUrl}/_emdash/*`)} ${dim(\"→\")} ${cyan(`${cfg.url}/_emdash/*`)} ${dim(\"(dev proxy)\")}`,\n\t\t);\n\t} else {\n\t\tconsole.log(\n\t\t\t`\\n  ${dim(\"›\")} Static frontend ${dim(\"— rendering from a local snapshot, no local backend\")}`,\n\t\t);\n\t\tif (cfg.url) console.log(`  ${dim(\"›\")} Content   ${cyan(cfg.url)}`);\n\t}\n\tconsole.log(\"\");\n}\n\nexport function buildMiddlewareEntries(\n\tconfig: Pick<EmDashConfig, \"middleware\" | \"playground\">,\n\troot: URL,\n): AstroIntegrationMiddleware[] {\n\tconst entries: AstroIntegrationMiddleware[] = [];\n\n\tif (config.middleware !== undefined) {\n\t\tconst configuredEntrypoint = config.middleware?.outer;\n\t\tif (\n\t\t\t(typeof configuredEntrypoint !== \"string\" && !(configuredEntrypoint instanceof URL)) ||\n\t\t\t(typeof configuredEntrypoint === \"string\" && configuredEntrypoint.trim() === \"\")\n\t\t) {\n\t\t\tthrow new Error(\"middleware.outer must be a non-empty module specifier string or URL.\");\n\t\t}\n\t\tconst entrypoint =\n\t\t\ttypeof configuredEntrypoint === \"string\" &&\n\t\t\t(configuredEntrypoint.startsWith(\"./\") || configuredEntrypoint.startsWith(\"../\"))\n\t\t\t\t? new URL(configuredEntrypoint, root)\n\t\t\t\t: configuredEntrypoint;\n\t\tentries.push({\n\t\t\tentrypoint,\n\t\t\torder: \"pre\",\n\t\t});\n\t}\n\n\tif (config.playground) {\n\t\tentries.push({\n\t\t\tentrypoint: config.playground.middlewareEntrypoint,\n\t\t\torder: \"pre\",\n\t\t});\n\t}\n\n\tentries.push(\n\t\t{ entrypoint: \"@premium-cms/emdash/middleware/cors\", order: \"pre\" },\n\t\t{ entrypoint: \"@premium-cms/emdash/middleware\", order: \"pre\" },\n\t\t{ entrypoint: \"@premium-cms/emdash/middleware/redirect\", order: \"pre\" },\n\t);\n\n\tif (!config.playground) {\n\t\tentries.push(\n\t\t\t{ entrypoint: \"@premium-cms/emdash/middleware/setup\", order: \"pre\" },\n\t\t\t{ entrypoint: \"@premium-cms/emdash/middleware/auth\", order: \"pre\" },\n\t\t\t{ entrypoint: \"@premium-cms/emdash/middleware/credits\", order: \"pre\" },\n\t\t);\n\t}\n\n\tentries.push(\n\t\t{ entrypoint: \"@premium-cms/emdash/middleware/media-usage-write-fence\", order: \"pre\" },\n\t\t{ entrypoint: \"@premium-cms/emdash/middleware/request-context\", order: \"pre\" },\n\t);\n\n\treturn entries;\n}\n\n/**\n * Create the EmDash Astro integration\n */\nexport function emdash(config: EmDashConfig = {}): AstroIntegration {\n\t// Apply defaults\n\tconst resolvedConfig: EmDashConfig = {\n\t\t...config,\n\t\tstorage: config.storage ?? DEFAULT_STORAGE,\n\t\tmigrations: normalizeMigrationConfig(config.migrations),\n\t};\n\n\t// Validate marketplace URL\n\tif (resolvedConfig.marketplace) {\n\t\tconst url = resolvedConfig.marketplace;\n\t\ttry {\n\t\t\tconst parsed = new URL(url);\n\t\t\tconst isLocalhost = parsed.hostname === \"localhost\" || parsed.hostname === \"127.0.0.1\";\n\t\t\tif (parsed.protocol !== \"https:\" && !isLocalhost) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Marketplace URL must use HTTPS (got ${parsed.protocol}). ` +\n\t\t\t\t\t\t`Only localhost URLs are allowed over HTTP.`,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tif (e instanceof TypeError) {\n\t\t\t\tthrow new Error(`Invalid marketplace URL: \"${url}\"`, { cause: e });\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t\tif (!resolvedConfig.sandboxRunner) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Marketplace requires `sandboxRunner` to be configured. \" +\n\t\t\t\t\t\"Marketplace plugins run in sandboxed V8 isolates.\",\n\t\t\t);\n\t\t}\n\t}\n\n\t// Validate siteUrl if provided in astro.config.mjs.\n\t// Env-var fallback (EMDASH_SITE_URL / SITE_URL) is handled at runtime by\n\t// getPublicOrigin() in api/public-url.ts — NOT here — so Docker images built\n\t// without a domain can pick it up at container start via process.env.\n\tif (resolvedConfig.siteUrl) {\n\t\tconst raw = resolvedConfig.siteUrl;\n\t\ttry {\n\t\t\tconst parsed = new URL(raw);\n\t\t\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n\t\t\t\tthrow new Error(`siteUrl must be http or https (got ${parsed.protocol})`);\n\t\t\t}\n\t\t\t// Always store origin-normalized value (no path) — security invariant L-1\n\t\t\tresolvedConfig.siteUrl = parsed.origin;\n\t\t} catch (e) {\n\t\t\tif (e instanceof TypeError) {\n\t\t\t\tthrow new Error(`Invalid siteUrl: \"${raw}\"`, { cause: e });\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\t// Validate config.allowedOrigins shape at startup (per-entry rules: parseable,\n\t// http(s), no trailing dots, no empty labels). The siteUrl-dependent rules\n\t// (Rule A: requires siteUrl; Rule B: must be a subdomain of siteUrl) are\n\t// deferred to runtime when config.siteUrl is absent — EMDASH_SITE_URL may\n\t// supply it post-build, just like the env-var fallback for siteUrl above.\n\t// When config.siteUrl IS present, run the full validator here for fail-fast.\n\tif (resolvedConfig.allowedOrigins?.length) {\n\t\tconst tagged = resolvedConfig.allowedOrigins.map((origin) => ({\n\t\t\torigin,\n\t\t\tsource: \"config.allowedOrigins\" as const,\n\t\t}));\n\t\tresolvedConfig.allowedOrigins = resolvedConfig.siteUrl\n\t\t\t? validateAllowedOrigins(resolvedConfig.siteUrl, tagged)\n\t\t\t: validateOriginShape(tagged);\n\t}\n\n\t// Plugin descriptors from config\n\tconst pluginDescriptors = resolvedConfig.plugins ?? [];\n\tconst sandboxedDescriptors = resolvedConfig.sandboxed ?? [];\n\n\t// Validate all plugin descriptors\n\tfor (const descriptor of [...pluginDescriptors, ...sandboxedDescriptors]) {\n\t\t// Standard-format plugins can't use features that require trusted mode\n\t\tif (descriptor.format === \"standard\") {\n\t\t\tif (descriptor.adminEntry) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Plugin \"${descriptor.id}\" is standard format but declares adminEntry. ` +\n\t\t\t\t\t\t`Standard plugins use Block Kit for admin UI, not React components. ` +\n\t\t\t\t\t\t`Remove adminEntry or change format to \"native\".`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (descriptor.componentsEntry) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Plugin \"${descriptor.id}\" is standard format but declares componentsEntry. ` +\n\t\t\t\t\t\t`Portable Text block components require native format. ` +\n\t\t\t\t\t\t`Remove componentsEntry or change format to \"native\".`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate: non-standard plugins cannot be placed in sandboxed: []\n\tfor (const descriptor of sandboxedDescriptors) {\n\t\tif (descriptor.format !== \"standard\") {\n\t\t\tthrow new Error(\n\t\t\t\t`Plugin \"${descriptor.id}\" uses the native format and cannot be placed in ` +\n\t\t\t\t\t`\\`sandboxed: []\\`. Native plugins can only run in \\`plugins: []\\`. ` +\n\t\t\t\t\t`To sandbox this plugin, convert it to the standard format.`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// Resolved plugins (populated at build time by importing entrypoints)\n\tlet _resolvedPlugins: ResolvedPlugin[] = [];\n\n\t// Serialize config for virtual module (database/storage/auth - plugins handled separately)\n\t// i18n is populated in astro:config:setup from astroConfig.i18n\n\tconst serializableConfig: Record<string, unknown> = {\n\t\tdatabase: resolvedConfig.database,\n\t\tmigrations: resolvedConfig.migrations,\n\t\tstorage: resolvedConfig.storage,\n\t\tauth: resolvedConfig.auth,\n\t\tauthProviders: resolvedConfig.authProviders,\n\t\tmarketplace: resolvedConfig.marketplace,\n\t\texperimental: resolvedConfig.experimental,\n\t\tsiteUrl: resolvedConfig.siteUrl,\n\t\ttrustedProxyHeaders: resolvedConfig.trustedProxyHeaders,\n\t\tmaxUploadSize: resolvedConfig.maxUploadSize,\n\t\tadmin: resolvedConfig.admin,\n\t\ttoolbar: resolvedConfig.toolbar,\n\t};\n\n\t// Determine auth mode for route injection\n\t// Check if auth is an AuthDescriptor (has entrypoint) indicating external auth\n\tconst useExternalAuth = !!(resolvedConfig.auth && \"entrypoint\" in resolvedConfig.auth);\n\n\t// Captured in astro:config:setup so the astro:server:setup hook can tell\n\t// whether we're running `astro dev` (where the dev-bypass shortcut applies).\n\tlet astroCommand: \"dev\" | \"build\" | \"preview\" | \"sync\" | undefined;\n\tlet normalizedI18n: ReturnType<typeof normalizeAstroI18n> = null;\n\tconst migrationMetadata = createMigrationIntegrationMetadata(resolvedConfig.database);\n\n\tconst integration: AstroIntegration = {\n\t\tname: \"@premium-cms/emdash\",\n\t\thooks: {\n\t\t\t// A live-connected static frontend prerenders every route, and Astro\n\t\t\t// strips request context (headers AND cookies) from prerendered\n\t\t\t// routes — so the dev editor middleware can never see the session\n\t\t\t// cookie. Render on demand in `astro dev` only, restoring that\n\t\t\t// context; the production build stays fully prerendered.\n\t\t\t\"astro:route:setup\": ({ route }) => {\n\t\t\t\tif (resolvedConfig.staticFrontend && astroCommand === \"dev\") {\n\t\t\t\t\troute.prerender = false;\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"astro:config:setup\": ({\n\t\t\t\tinjectRoute,\n\t\t\t\taddMiddleware,\n\t\t\t\tlogger,\n\t\t\t\tupdateConfig,\n\t\t\t\tconfig: astroConfig,\n\t\t\t\tcommand,\n\t\t\t}) => {\n\t\t\t\tastroCommand = command;\n\t\t\t\tprintBanner(logger);\n\t\t\t\t// Capture the host's Astro version so the runtime can expose it\n\t\t\t\t// to the admin and the registry install gate for `env:astro`\n\t\t\t\t// constraint checks.\n\t\t\t\tconst astroVersion = resolveAstroVersion();\n\t\t\t\tif (astroVersion !== undefined) {\n\t\t\t\t\tserializableConfig.astroVersion = astroVersion;\n\t\t\t\t}\n\t\t\t\t// EmDashHead must not access Astro.csp when the host has disabled\n\t\t\t\t// Astro's built-in CSP runtime; Astro logs a warning for that access.\n\t\t\t\tserializableConfig.astroCspEnabled = Boolean(astroConfig.security.csp);\n\t\t\t\t// Expose Astro's trailingSlash routing policy so plugins can build\n\t\t\t\t// URLs (sitemap/canonical/hreflang) that match what the site serves.\n\t\t\t\tserializableConfig.trailingSlash = astroConfig.trailingSlash;\n\t\t\t\tnormalizedI18n = normalizeAstroI18n(astroConfig.i18n);\n\t\t\t\tif (normalizedI18n) serializableConfig.i18n = normalizedI18n;\n\n\t\t\t\t// Disable Astro's built-in checkOrigin -- EmDash's own CSRF\n\t\t\t\t// layer (checkPublicCsrf in api/csrf.ts) handles origin\n\t\t\t\t// validation with dual-origin support: it accepts both the\n\t\t\t\t// internal origin AND the public origin from getPublicOrigin(),\n\t\t\t\t// which resolves siteUrl from config or env vars at runtime.\n\t\t\t\t// Astro's check can't do this because allowedDomains is baked\n\t\t\t\t// at build time, which breaks Docker deployments where the\n\t\t\t\t// domain is only known at container start via EMDASH_SITE_URL.\n\t\t\t\t//\n\t\t\t\t// When siteUrl is known at build time, also set allowedDomains\n\t\t\t\t// so Astro.url reflects the public origin (helps user template\n\t\t\t\t// code that reads Astro.url directly).\n\t\t\t\tconst securityConfig: Record<string, unknown> = {\n\t\t\t\t\tcheckOrigin: false,\n\t\t\t\t\t...(resolvedConfig.siteUrl\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tallowedDomains: [{ hostname: new URL(resolvedConfig.siteUrl).hostname }],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t};\n\n\t\t\t\t// Inject default Noto Sans font for the admin UI.\n\t\t\t\t// Uses the Astro Font API so fonts are downloaded at build time\n\t\t\t\t// and self-hosted (no runtime CDN requests).\n\t\t\t\t//\n\t\t\t\t// The admin CSS references var(--font-emdash) with a system font\n\t\t\t\t// fallback. Users can add extra script coverage (Arabic, CJK, etc.)\n\t\t\t\t// by passing fonts.scripts in the emdash() config. The custom\n\t\t\t\t// notoSans provider resolves all script families from Google Fonts\n\t\t\t\t// under a single font-family name, so they stack via unicode-range.\n\t\t\t\tconst fontsConfig = resolvedConfig.fonts;\n\t\t\t\tconst emdashFonts =\n\t\t\t\t\tfontsConfig === false\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tprovider: notoSans({\n\t\t\t\t\t\t\t\t\t\tscripts: fontsConfig?.scripts,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\tname: \"Noto Sans\",\n\t\t\t\t\t\t\t\t\tcssVariable: \"--font-emdash\",\n\t\t\t\t\t\t\t\t\tweights: [\"100 900\" as const],\n\t\t\t\t\t\t\t\t\tstyles: [\"normal\" as const, \"italic\" as const],\n\t\t\t\t\t\t\t\t\tsubsets: [\n\t\t\t\t\t\t\t\t\t\t\"latin\" as const,\n\t\t\t\t\t\t\t\t\t\t\"latin-ext\" as const,\n\t\t\t\t\t\t\t\t\t\t\"cyrillic\" as const,\n\t\t\t\t\t\t\t\t\t\t\"cyrillic-ext\" as const,\n\t\t\t\t\t\t\t\t\t\t\"devanagari\" as const,\n\t\t\t\t\t\t\t\t\t\t\"greek\" as const,\n\t\t\t\t\t\t\t\t\t\t\"greek-ext\" as const,\n\t\t\t\t\t\t\t\t\t\t\"vietnamese\" as const,\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\tfallbacks: [\"ui-sans-serif\", \"system-ui\", \"sans-serif\"],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t];\n\n\t\t\t\t// Authorize media sources so Astro's image service builds transform\n\t\t\t\t// URLs for them (it won't optimize an un-allowed source). `updateConfig`\n\t\t\t\t// merges arrays, so user-configured remotePatterns are preserved.\n\t\t\t\tconst imageRemotePatterns = buildImageRemotePatterns(\n\t\t\t\t\tresolvedConfig.storage,\n\t\t\t\t\tresolvedConfig.siteUrl,\n\t\t\t\t\tcommand,\n\t\t\t\t);\n\n\t\t\t\t// Wrap Astro's image endpoint so EmDash media bytes load straight from\n\t\t\t\t// storage (Access-safe) instead of over HTTP. Skip when the user opts\n\t\t\t\t// out or has a custom endpoint we can't delegate back to.\n\t\t\t\tconst { entrypoint: imageEndpoint, warn: imageEndpointWarning } = resolveImageEndpoint({\n\t\t\t\t\timagesDisabled: resolvedConfig.images === false,\n\t\t\t\t\tcurrentEntrypoint: astroConfig.image?.endpoint?.entrypoint,\n\t\t\t\t\tisCloudflare: astroConfig.adapter?.name === \"@astrojs/cloudflare\",\n\t\t\t\t});\n\t\t\t\tif (imageEndpointWarning) logger.warn(imageEndpointWarning);\n\n\t\t\t\tconst imageConfig: Record<string, unknown> = {};\n\t\t\t\tif (imageRemotePatterns.length) imageConfig.remotePatterns = imageRemotePatterns;\n\t\t\t\tif (imageEndpoint) imageConfig.endpoint = { entrypoint: imageEndpoint };\n\n\t\t\t\tupdateConfig({\n\t\t\t\t\tsecurity: securityConfig,\n\t\t\t\t\t...(Object.keys(imageConfig).length ? { image: imageConfig } : {}),\n\t\t\t\t\t// fonts is a valid AstroConfig key but may not be in the\n\t\t\t\t\t// type definition for the minimum supported Astro version\n\t\t\t\t\t...({ fonts: emdashFonts } as Record<string, unknown>),\n\t\t\t\t\tvite: createViteConfig(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tserializableConfig,\n\t\t\t\t\t\t\tresolvedConfig,\n\t\t\t\t\t\t\tpluginDescriptors,\n\t\t\t\t\t\t\tastroConfig,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t),\n\t\t\t\t});\n\n\t\t\t\t// Static-frontend build: the admin + REST API + auth + MCP routes\n\t\t\t\t// are the BACKEND's job (a Cloudflare Worker). A static site\n\t\t\t\t// (GitHub Pages) ships only the theme's public pages, prerendered\n\t\t\t\t// from a snapshot DB — so skip injecting all of the SSR routes,\n\t\t\t\t// which would otherwise force a server adapter under output:'static'.\n\t\t\t\tif (!resolvedConfig.staticFrontend) {\n\t\t\t\t\t// Inject all core routes\n\t\t\t\t\tinjectCoreRoutes(injectRoute, { srcDir: astroConfig.srcDir });\n\n\t\t\t\t\t// Inject routes from pluggable auth providers (authProviders config)\n\t\t\t\t\tif (resolvedConfig.authProviders?.length) {\n\t\t\t\t\t\tinjectAuthProviderRoutes(injectRoute, resolvedConfig.authProviders);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Inject passkey/oauth/magic-link routes unless transparent external auth is active\n\t\t\t\t\tif (!useExternalAuth) {\n\t\t\t\t\t\tinjectBuiltinAuthRoutes(injectRoute);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Inject MCP endpoint (always on — bearer-token-only, no cost if unused)\n\t\t\t\t\tif (resolvedConfig.mcp !== false) {\n\t\t\t\t\t\tinjectMcpRoute(injectRoute);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (const middleware of buildMiddlewareEntries(resolvedConfig, astroConfig.root)) {\n\t\t\t\t\taddMiddleware(middleware);\n\t\t\t\t}\n\n\t\t\t\t// Live-connected static-frontend dev: editor session transfer + toolbar.\n\t\t\t\tif (resolvedConfig.staticFrontend && astroCommand === \"dev\") {\n\t\t\t\t\taddMiddleware({\n\t\t\t\t\t\tentrypoint: \"@premium-cms/emdash/middleware/static-dev\",\n\t\t\t\t\t\torder: \"pre\",\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Route info is printed with absolute, clickable URLs once the\n\t\t\t\t// dev server is listening (see astro:server:setup), since the\n\t\t\t\t// port isn't known yet here. Nothing useful to print for build.\n\t\t\t},\n\t\t\t\"astro:config:done\": async ({ config: finalConfig, logger }) => {\n\t\t\t\tconst warning = missingReactIntegrationWarning(finalConfig.integrations);\n\t\t\t\tif (warning) logger.warn(warning);\n\n\t\t\t\tif (astroCommand !== \"build\" && astroCommand !== \"sync\") return;\n\t\t\t\tif (!migrationMetadata.database) {\n\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t\"EmDash migration manifest was not written because no database adapter is configured.\",\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!migrationMetadata.database.migrations) {\n\t\t\t\t\t// Static frontends render from a snapshot; they deploy no\n\t\t\t\t\t// migrations, so the missing manifest is not worth a warning.\n\t\t\t\t\tif (!resolvedConfig.staticFrontend) {\n\t\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t\t\"EmDash migration manifest was not written because the configured database adapter does not support deployment migrations.\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst identity = await getCoreMigrationIdentity();\n\t\t\t\tconst manifest = await buildMigrationManifest({\n\t\t\t\t\tidentity,\n\t\t\t\t\ti18n: normalizedI18n,\n\t\t\t\t\tdatabase: migrationMetadata.database,\n\t\t\t\t});\n\t\t\t\tawait writeMigrationManifest(fileURLToPath(finalConfig.root), manifest);\n\t\t\t},\n\t\t\t\"astro:server:setup\": ({ server, logger }) => {\n\t\t\t\t// Print route info with absolute, clickable URLs once the server\n\t\t\t\t// is listening. Only in `astro dev` -- the dev-bypass shortcut is\n\t\t\t\t// dev-only and the port is unknown until now.\n\t\t\t\tif (astroCommand === \"dev\") {\n\t\t\t\t\tserver.httpServer?.once(\"listening\", () => {\n\t\t\t\t\t\tconst address = server.httpServer?.address();\n\t\t\t\t\t\tif (!address || typeof address === \"string\") return;\n\t\t\t\t\t\tlet host = address.address;\n\t\t\t\t\t\tif (host === \"::1\" || host === \"::\" || host === \"0.0.0.0\") {\n\t\t\t\t\t\t\thost = \"localhost\";\n\t\t\t\t\t\t} else if (address.family === \"IPv6\") {\n\t\t\t\t\t\t\thost = `[${host}]`;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (resolvedConfig.staticFrontend) {\n\t\t\t\t\t\t\tprintStaticFrontendInfo(`http://${host}:${address.port}`, resolvedConfig.database);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tprintDevServerInfo(`http://${host}:${address.port}`, resolvedConfig.mcp !== false);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Generate types once the server is listening.\n\t\t\t\t// The endpoint returns the types content; we write the file here\n\t\t\t\t// (in Node) because workerd has no real filesystem access.\n\t\t\t\tserver.httpServer?.once(\"listening\", async () => {\n\t\t\t\t\t// Static frontends have no local typegen route (and the dev proxy\n\t\t\t\t\t// would forward the call to the live backend) — skip the fetch.\n\t\t\t\t\tif (resolvedConfig.staticFrontend) return;\n\t\t\t\t\tconst { writeFile, readFile } = await import(\"node:fs/promises\");\n\t\t\t\t\tconst { resolve } = await import(\"node:path\");\n\n\t\t\t\t\tconst address = server.httpServer?.address();\n\t\t\t\t\tif (!address || typeof address === \"string\") return;\n\n\t\t\t\t\tconst port = address.port;\n\t\t\t\t\tconst typegenUrl = `http://localhost:${port}/_emdash/api/typegen`;\n\t\t\t\t\tconst outputPath = resolve(process.cwd(), \"emdash-env.d.ts\");\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst response = await fetch(typegenUrl, {\n\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (!response.ok) {\n\t\t\t\t\t\t\tconst body = await response.text().catch(() => \"\");\n\t\t\t\t\t\t\tlogger.warn(`Typegen failed: ${response.status} ${body.slice(0, 200)}`);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst { data: result } = (await response.json()) as {\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\ttypes: string;\n\t\t\t\t\t\t\t\thash: string;\n\t\t\t\t\t\t\t\tcollections: number;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t// Only write if content changed\n\t\t\t\t\t\tlet needsWrite = true;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst existing = await readFile(outputPath, \"utf-8\");\n\t\t\t\t\t\t\tif (existing === result.types) needsWrite = false;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// File doesn't exist yet\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (needsWrite) {\n\t\t\t\t\t\t\tawait writeFile(outputPath, result.types, \"utf-8\");\n\t\t\t\t\t\t\tlogger.info(`Generated emdash-env.d.ts (${result.collections} collections)`);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst msg = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\tlogger.warn(`Typegen failed: ${msg}`);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t\t\"astro:build:done\": ({ logger }) => {\n\t\t\t\tlogger.info(\"Build complete\");\n\t\t\t},\n\t\t},\n\t};\n\n\tObject.defineProperty(integration, MIGRATION_CONFIG_SYMBOL, {\n\t\tvalue: migrationMetadata,\n\t\tenumerable: false,\n\t});\n\treturn integration;\n}\n\nexport default emdash;\n"],"mappings":"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"}