import { JsonConsoleLogger, LocalSecretService, LocalVariablesService, } from '@pikku/core/services' import { pikkuServices } from '../.pikku/pikku-types.gen.js' import { CFWorkerSchemaService } from '@pikku/schema-cfworker' import { LibsqlWebDialect } from '@pikku/kysely-sqlite' import { Kysely, CamelCasePlugin } from 'kysely' import { LocalBrowserService } from '@pikku/browser' import type { DB } from './types/db.types.js' import './wire-services.js' export const createSingletonServices = pikkuServices(async ( config, existingServices, ) => { const variables = existingServices?.variables ?? new LocalVariablesService() const secrets = existingServices?.secrets ?? new LocalSecretService(variables) const logger = existingServices?.logger ?? new JsonConsoleLogger() const schema = existingServices?.schema ?? new CFWorkerSchemaService(logger) let kysely = existingServices?.kysely as Kysely | undefined if (!kysely) { const databaseUrl = await variables.get('DATABASE_URL') if (!databaseUrl) { throw new Error( 'DATABASE_URL not set — in dev, enable `dev.db` in your pikku config; in prod, Fabric injects DATABASE_URL', ) } kysely = new Kysely({ dialect: new LibsqlWebDialect({ url: databaseUrl }), plugins: [new CamelCasePlugin()], }) } const content = existingServices?.content // On CF the browserContributor injects a Cloudflare Browser Rendering-backed // service; locally/sandbox/server we fall back to the node-puppeteer pool. const browser = existingServices?.browser ?? new LocalBrowserService({ logger }) return { ...(existingServices ?? {}), config, variables, secrets, logger, schema, kysely, content, browser, } })