UNPKG

everything-dev

Version:

A consolidated product package for building Module Federation apps with oRPC APIs.

1 lines • 10.4 kB
{"version":3,"file":"drizzle-kit.cjs","names":["Data","Context","Effect","effect","spawn","bindingEnv","join","existsSync","resolve","Layer"],"sources":["../../src/db/drizzle-kit.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { Context, Data, Effect, Layer } from \"effect\";\nimport { bindingEnv } from \"./binding\";\nimport type { DatabaseBinding } from \"./bindings\";\n\nexport class DrizzleKitError extends Data.TaggedError(\"DrizzleKitError\")<{\n readonly command: string;\n readonly message: string;\n readonly exitCode: number | undefined;\n}> {}\n\nexport interface DrizzleKitService {\n readonly studio: (binding: DatabaseBinding) => Effect.Effect<void, DrizzleKitError>;\n readonly migrate: (binding: DatabaseBinding) => Effect.Effect<void, DrizzleKitError>;\n}\n\nexport class DrizzleKit extends Context.Service<DrizzleKit, DrizzleKitService>()(\n \"everything-dev/DrizzleKit\",\n) {}\n\ninterface SpawnSpec {\n readonly args: readonly string[];\n readonly cwd: string;\n readonly env: Record<string, string | undefined>;\n readonly command: string;\n readonly stdio: \"inherit\" | \"pipe\";\n}\n\n/**\n * The single choke point for invoking drizzle-kit. Every child receives the\n * composition root's materialized environment (`bindingEnv`) so the config it\n * evaluates never has to re-derive credentials from ambient state.\n */\nfunction spawnDrizzleKit(spec: SpawnSpec): Effect.Effect<void, DrizzleKitError> {\n return Effect.callback((resume) => {\n let stderr = \"\";\n let settled = false;\n const settle = (effect: Effect.Effect<void, DrizzleKitError>) => {\n if (settled) return;\n settled = true;\n resume(effect);\n };\n\n const child = spawn(process.platform === \"win32\" ? \"npx.cmd\" : \"npx\", [...spec.args], {\n cwd: spec.cwd,\n env: spec.env,\n stdio: spec.stdio,\n });\n\n if (spec.stdio === \"pipe\") {\n child.stderr?.on(\"data\", (data: Buffer) => {\n stderr += data.toString();\n });\n }\n\n child.on(\"error\", (err) => {\n const hint =\n (err as NodeJS.ErrnoException).code === \"ENOENT\"\n ? '\"npx\" not found. Ensure Node.js is installed.'\n : err.message;\n settle(\n Effect.fail(\n new DrizzleKitError({ command: spec.command, message: hint, exitCode: undefined }),\n ),\n );\n });\n\n child.on(\"exit\", (code) => {\n if (code === 0 || code === null) {\n settle(Effect.void);\n return;\n }\n settle(\n Effect.fail(\n new DrizzleKitError({\n command: spec.command,\n message: `drizzle-kit ${spec.command} exited with code ${code}${\n stderr.trim() ? `: ${stderr.trim()}` : \"\"\n }`,\n exitCode: code,\n }),\n ),\n );\n });\n\n return Effect.sync(() => {\n if (child.exitCode === null && !child.killed) child.kill();\n });\n });\n}\n\nfunction childEnv(binding: DatabaseBinding): Record<string, string | undefined> {\n return {\n ...process.env,\n ...bindingEnv({ secretName: binding.identity.secretName, url: binding.url }),\n };\n}\n\nfunction workspaceConfigPath(binding: DatabaseBinding): string | undefined {\n const workspaceDir = binding.identity.workspaceDir;\n if (!workspaceDir) return undefined;\n const configPath = join(workspaceDir, \"drizzle.config.ts\");\n return existsSync(configPath) ? configPath : undefined;\n}\n\nfunction writeGeneratedConfig(binding: DatabaseBinding, projectDir: string): string {\n const dbDir = resolve(projectDir, \".bos\", \"db\", binding.key);\n mkdirSync(dbDir, { recursive: true });\n\n const configPath = join(dbDir, \"drizzle.config.ts\");\n const configContent = `import { defineConfig } from \"drizzle-kit\";\n\nexport default defineConfig({\n schema: \"./drizzle/schema.ts\",\n out: \"./drizzle\",\n dialect: \"postgresql\",\n dbCredentials: {\n url: \"${binding.url}\",\n },\n migrations: {\n schema: \"${binding.identity.journal.schema}\",\n table: \"${binding.identity.journal.table}\",\n },\n verbose: true,\n strict: true,\n});\n`;\n\n writeFileSync(configPath, configContent);\n return dbDir;\n}\n\nexport interface DrizzleKitOptions {\n readonly projectDir: string;\n readonly onLog?: (message: string) => void;\n}\n\nexport const makeDrizzleKitLive = (options: DrizzleKitOptions): Layer.Layer<DrizzleKit> =>\n Layer.succeed(DrizzleKit, {\n studio: (binding) =>\n Effect.gen(function* () {\n const localConfig = workspaceConfigPath(binding);\n\n if (localConfig && binding.identity.workspaceDir) {\n options.onLog?.(`Starting Drizzle Studio for ${binding.key} (local)...`);\n yield* spawnDrizzleKit({\n args: [\"drizzle-kit\", \"studio\", \"--config\", localConfig],\n cwd: binding.identity.workspaceDir,\n env: childEnv(binding),\n command: \"studio\",\n stdio: \"inherit\",\n });\n return;\n }\n\n if (binding.source === \"local\") {\n return yield* new DrizzleKitError({\n command: \"studio\",\n message:\n `No drizzle.config.ts found in ${binding.identity.workspaceDir ?? binding.key}. ` +\n `Run 'drizzle-kit init' first in the plugin workspace.`,\n exitCode: undefined,\n });\n }\n\n options.onLog?.(`Introspecting database schema for ${binding.key}...`);\n const dbDir = writeGeneratedConfig(binding, options.projectDir);\n yield* spawnDrizzleKit({\n args: [\"drizzle-kit\", \"pull\", \"--config\", join(dbDir, \"drizzle.config.ts\")],\n cwd: dbDir,\n env: childEnv(binding),\n command: \"pull\",\n stdio: \"inherit\",\n }).pipe(\n Effect.mapError(\n (error) =>\n new DrizzleKitError({\n command: \"pull\",\n exitCode: error.exitCode,\n message:\n `Failed to introspect database for \"${binding.key}\". ` +\n `Check that ${binding.identity.secretName} is correct and the database is reachable. ` +\n error.message,\n }),\n ),\n );\n\n options.onLog?.(`Starting Drizzle Studio for ${binding.key}...`);\n yield* spawnDrizzleKit({\n args: [\"drizzle-kit\", \"studio\", \"--config\", join(dbDir, \"drizzle.config.ts\")],\n cwd: dbDir,\n env: childEnv(binding),\n command: \"studio\",\n stdio: \"inherit\",\n });\n }),\n\n migrate: (binding) => {\n const configPath = workspaceConfigPath(binding);\n if (!configPath || !binding.identity.workspaceDir) {\n return Effect.fail(\n new DrizzleKitError({\n command: \"migrate\",\n message: `No drizzle.config.ts found in ${binding.identity.workspaceDir ?? binding.key}.`,\n exitCode: undefined,\n }),\n );\n }\n return spawnDrizzleKit({\n args: [\"drizzle-kit\", \"migrate\", \"--config\", configPath],\n cwd: binding.identity.workspaceDir,\n env: childEnv(binding),\n command: \"migrate\",\n stdio: \"pipe\",\n });\n },\n });\n"],"mappings":"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"}