UNPKG

everything-dev

Version:

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

1 lines 7.48 kB
{"version":3,"file":"db-studio.mjs","names":[],"sources":["../../src/cli/db-studio.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport type { RuntimeConfig } from \"../types\";\n\nexport interface PluginDbInfo {\n key: string;\n source: \"local\" | \"remote\";\n section: \"app.api\" | \"app.auth\" | \"plugins\";\n databaseSecret: string;\n databaseUrl: string;\n workspaceDir?: string;\n projectDir: string;\n}\n\nexport function resolvePluginDbInfo(\n pluginKey: string,\n runtimeConfig: RuntimeConfig,\n projectDir: string,\n): PluginDbInfo {\n let source: \"local\" | \"remote\" | undefined;\n let section: PluginDbInfo[\"section\"];\n let secrets: string[] | undefined;\n let localPath: string | undefined;\n let key: string;\n\n if (pluginKey === \"api\" && runtimeConfig.api) {\n source = runtimeConfig.api.source;\n section = \"app.api\";\n secrets = runtimeConfig.api.secrets;\n localPath = runtimeConfig.api.localPath;\n key = \"api\";\n } else if (pluginKey === \"auth\" && runtimeConfig.auth) {\n source = runtimeConfig.auth.source;\n section = \"app.auth\";\n secrets = runtimeConfig.auth.secrets;\n localPath = runtimeConfig.auth.localPath;\n key = \"auth\";\n } else if (runtimeConfig.plugins?.[pluginKey]) {\n const plugin = runtimeConfig.plugins[pluginKey];\n source = plugin.source;\n section = \"plugins\";\n secrets = plugin.secrets;\n localPath = plugin.localPath;\n key = pluginKey;\n } else {\n throw new Error(\n `Plugin \"${pluginKey}\" not found in app.api, app.auth, or plugins. ` +\n `Available: ${[\n \"api\",\n ...(runtimeConfig.auth ? [\"auth\"] : []),\n ...Object.keys(runtimeConfig.plugins ?? {}),\n ].join(\", \")}`,\n );\n }\n\n const dbSecret = secrets?.find((s) => s.endsWith(\"_DATABASE_URL\"));\n if (!dbSecret) {\n throw new Error(\n `Plugin \"${pluginKey}\" has no database secret (no secret ending in _DATABASE_URL). ` +\n `Secrets: ${(secrets ?? []).join(\", \") || \"none\"}`,\n );\n }\n\n const dbUrl = process.env[dbSecret];\n if (!dbUrl) {\n throw new Error(\n `.env missing ${dbSecret} for plugin \"${pluginKey}\". ` +\n `Add it to your .env file (see .env.example).`,\n );\n }\n\n return {\n key,\n source: source ?? \"remote\",\n section,\n databaseSecret: dbSecret,\n databaseUrl: dbUrl,\n workspaceDir: localPath,\n projectDir,\n };\n}\n\nexport async function runStudioLocal(info: PluginDbInfo): Promise<void> {\n const workspaceRoot = info.workspaceDir\n ? resolve(info.projectDir, info.workspaceDir)\n : resolve(info.projectDir, info.key);\n const configPath = join(workspaceRoot, \"drizzle.config.ts\");\n\n if (!existsSync(configPath)) {\n throw new Error(\n `No drizzle.config.ts found in ${workspaceRoot}. ` +\n `Run 'drizzle-kit init' first in the plugin workspace.`,\n );\n }\n\n p.log.info(`Starting Drizzle Studio for ${info.key} (local)...`);\n\n await spawnAsync(\"npx\", [\"drizzle-kit\", \"studio\", \"--config\", configPath], {\n cwd: workspaceRoot,\n });\n}\n\nexport async function runStudioRemote(info: PluginDbInfo): Promise<void> {\n const dbDir = resolve(info.projectDir, \".bos\", \"db\", info.key);\n\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: \"${info.databaseUrl}\",\n },\n verbose: true,\n strict: true,\n});\n`;\n\n writeFileSync(configPath, configContent);\n\n p.log.info(`Introspecting database schema for ${info.key}...`);\n try {\n await spawnAsync(\"npx\", [\"drizzle-kit\", \"pull\", \"--config\", configPath], {\n cwd: dbDir,\n });\n } catch {\n throw new Error(\n `Failed to introspect database for \"${info.key}\". ` +\n `Check that ${info.databaseSecret} is correct and the database is reachable.`,\n );\n }\n\n p.log.info(`Starting Drizzle Studio for ${info.key}...`);\n await spawnAsync(\"npx\", [\"drizzle-kit\", \"studio\", \"--config\", configPath], {\n cwd: dbDir,\n });\n}\n\nfunction spawnAsync(cmd: string, args: string[], options: { cwd: string }): Promise<void> {\n return new Promise((resolvePromise, reject) => {\n const child = spawn(cmd, args, {\n cwd: options.cwd,\n stdio: \"inherit\",\n shell: true,\n });\n\n child.on(\"error\", (err) => {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n reject(\n new Error(\n `\"${cmd}\" not found. Ensure it is installed (e.g. 'npm install -g drizzle-kit').`,\n ),\n );\n } else {\n reject(new Error(`Failed to start ${cmd}: ${err.message}`));\n }\n });\n\n child.on(\"exit\", (code) => {\n if (code === 0 || code === null) {\n resolvePromise();\n } else {\n reject(new Error(`\"${cmd}\" exited with code ${code}`));\n }\n });\n });\n}\n"],"mappings":"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"}