/** * Durable Object preview database — RUNTIME ENTRY * * Creates a Kysely dialect backed by a preview Durable Object. * Loaded at runtime via virtual module when preview database queries are needed. * * This module imports directly from cloudflare:workers to access the DO binding. * Do NOT import this at config time. */ import { env } from "cloudflare:workers"; import type { Dialect } from "kysely"; import type { EmDashPreviewDB } from "./do-class.js"; import { PreviewDODialect } from "./do-dialect.js"; import type { PreviewDBStub } from "./do-dialect.js"; import type { PreviewDOConfig } from "./do-types.js"; /** * Create a preview DO dialect from config. * * The caller is responsible for resolving the DO name (session token). * This is passed as `config.name` by the preview middleware. */ export function createDialect(config: PreviewDOConfig & { name: string }): Dialect { // eslint-disable-next-line typescript/no-unsafe-type-assertion -- Worker binding accessed from untyped env object const ns = (env as Record)[config.binding]; if (!ns) { throw new Error( `Durable Object binding "${config.binding}" not found in environment. ` + `Check your wrangler.jsonc configuration:\n\n` + `[durable_objects]\n` + `bindings = [\n` + ` { name = "${config.binding}", class_name = "EmDashPreviewDB" }\n` + `]\n\n` + `[[migrations]]\n` + `tag = "v1"\n` + `new_sqlite_classes = ["EmDashPreviewDB"]`, ); } // eslint-disable-next-line typescript/no-unsafe-type-assertion -- DO namespace binding from untyped env object const namespace = ns as DurableObjectNamespace; const id = namespace.idFromName(config.name); // Return a factory that creates a fresh stub per connection. const getStub = (): PreviewDBStub => { const stub = namespace.get(id); // eslint-disable-next-line typescript/no-unsafe-type-assertion -- Rpc type limitation with unknown in return types return stub as unknown as PreviewDBStub; }; return new PreviewDODialect({ getStub }); } // Re-export the DO class and preview middleware for user convenience export { EmDashPreviewDB } from "./do-class.js"; export { createPreviewMiddleware } from "./do-preview.js"; export type { PreviewMiddlewareConfig } from "./do-preview.js"; export { isBlockedInPreview } from "./do-preview-routes.js"; export { signPreviewUrl, verifyPreviewSignature } from "./do-preview-sign.js";