@the-meridian/cli 0.1.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/db.ts","../src/version.ts","../src/lib/api.ts","../src/lib/api-types.ts","../src/lib/errors.ts","../src/lib/config.ts","../src/lib/paths.ts","../src/lib/context.ts","../src/lib/client.ts","../src/lib/db/connection.ts","../src/lib/output.ts","../src/lib/options.ts","../src/lib/prompts.ts","../src/lib/project.ts","../src/lib/run.ts","../src/lib/env-file.ts","../src/lib/port.ts","../src/lib/prisma.ts","../src/lib/proxy/binary.ts","../src/lib/proxy/proxy.ts","../src/lib/signals.ts","../src/lib/session.ts","../src/commands/db-shell-repl.ts","../src/commands/dev.ts","../src/commands/link.ts","../src/commands/login.ts","../src/auth/device-flow.ts","../src/commands/logout.ts","../src/lib/db/snapshot.ts","../src/commands/migrate.ts","../src/commands/unlink.ts","../src/commands/whoami.ts","../src/lib/global-flags.ts"],"sourcesContent":["import { realpathSync } from \"node:fs\"\nimport { fileURLToPath } from \"node:url\"\n\nimport { Command } from \"commander\"\n\nimport { registerDbCommand } from \"./commands/db.js\"\nimport { registerDevCommand } from \"./commands/dev.js\"\nimport { registerLinkCommand } from \"./commands/link.js\"\nimport { registerLoginCommand } from \"./commands/login.js\"\nimport { registerLogoutCommand } from \"./commands/logout.js\"\nimport { registerMigrateCommand } from \"./commands/migrate.js\"\nimport { registerUnlinkCommand } from \"./commands/unlink.js\"\nimport { registerWhoamiCommand } from \"./commands/whoami.js\"\nimport { setGlobalOptions } from \"./lib/context.js\"\nimport { addGlobalFlags, addGlobalFlagsToSubcommands, resolveGlobalFlags } from \"./lib/global-flags.js\"\nimport { configureOutput, reportError } from \"./lib/output.js\"\nimport { configurePrompts } from \"./lib/prompts.js\"\nimport { VERSION } from \"./version.js\"\n\nexport function buildProgram(): Command {\n const program = new Command()\n\n program\n .name(\"meridian\")\n .description(\n \"Managed remote development databases for Meridian apps.\\n\\n\" +\n \"Run `meridian login` once, `meridian link` per project, then `meridian dev`.\",\n )\n .version(VERSION, \"-V, --version\")\n // `meridian dev -- npm run something` must reach the subcommand untouched.\n .enablePositionalOptions()\n .showHelpAfterError(\"(run `meridian --help` for usage)\")\n\n addGlobalFlags(program)\n\n program.hook(\"preAction\", (_thisCommand, actionCommand) => {\n const flags = resolveGlobalFlags(actionCommand)\n\n setGlobalOptions(flags)\n\n configureOutput({\n json: flags.json === true,\n quiet: flags.quiet === true,\n verbose: flags.verbose === true,\n ...(flags.color !== undefined ? { color: flags.color } : {}),\n })\n\n configurePrompts({\n // Only set when the flag is actually present: `--yes` has no negated\n // form, so passing `false` here would just be \"flag absent\" — and it\n // would override the MERIDIAN_YES fallback isAssumeYes() falls back to.\n ...(flags.yes === true ? { assumeYes: true } : {}),\n ...(flags.interactive !== undefined ? { interactive: flags.interactive } : {}),\n })\n })\n\n registerLoginCommand(program)\n registerLogoutCommand(program)\n registerWhoamiCommand(program)\n registerLinkCommand(program)\n registerUnlinkCommand(program)\n registerDevCommand(program)\n registerMigrateCommand(program)\n registerDbCommand(program)\n\n addGlobalFlagsToSubcommands(program)\n\n return program\n}\n\nexport async function run(argv: string[] = process.argv): Promise<number> {\n try {\n await buildProgram().parseAsync(argv)\n return process.exitCode === undefined ? 0 : Number(process.exitCode)\n } catch (error) {\n return reportError(error)\n }\n}\n\n/** True when this file was executed as the `meridian` bin rather than imported. */\nfunction isMainModule(): boolean {\n const entry = process.argv[1]\n if (entry === undefined) return false\n try {\n // npm installs the bin as a symlink into its bin directory, so the entry\n // path only matches this module once both sides are fully resolved.\n return realpathSync(entry) === realpathSync(fileURLToPath(import.meta.url))\n } catch {\n return false\n }\n}\n\nif (isMainModule()) {\n const code = await run(process.argv)\n if (code !== 0) process.exitCode = code\n}\n","/**\n * `meridian db reset|seed|shell` — the three commands for working directly\n * against the Meridian-managed MySQL development database once it's linked\n * and running: destroy-and-rebuild the schema, run Prisma's seed script, or\n * open a SQL client (the real `mysql` binary when available, otherwise a\n * minimal built-in REPL — see `db-shell-repl.ts`).\n */\n\nimport { readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport type { Command } from \"commander\"\nimport type { Id } from \"../lib/api-types.js\"\nimport { createApiClient } from \"../lib/client.js\"\nimport { isJsonOutput, workingDirectory } from \"../lib/context.js\"\nimport type { ConnectionFactory } from \"../lib/db/connection.js\"\nimport { createSqlConnection, withConnection } from \"../lib/db/connection.js\"\nimport { error, hint, log, printJson, step, style, success, withSpinner } from \"../lib/output.js\"\nimport { parsePortOption } from \"../lib/options.js\"\nimport { confirmAction, confirmDestructive, isAssumeYes, isInteractive } from \"../lib/prompts.js\"\nimport { requireProject } from \"../lib/project.js\"\nimport { runNpx, runProcess } from \"../lib/run.js\"\nimport type { RunResult } from \"../lib/run.js\"\nimport type { DevSessionInfo } from \"../lib/session.js\"\nimport { ensureDevDatabaseReady, startDevSession } from \"../lib/session.js\"\nimport { executeStatement, findExecutable, runRepl } from \"./db-shell-repl.js\"\n\n/** Every side-effecting collaborator `db reset`/`db seed`/`db shell` use, injectable so they're testable offline. */\nexport interface DbDeps {\n startDevSession: typeof startDevSession\n ensureDevDatabaseReady: typeof ensureDevDatabaseReady\n createApiClient: typeof createApiClient\n runNpx: typeof runNpx\n runProcess: typeof runProcess\n createConnection: ConnectionFactory\n findExecutable: (name: string) => string | null\n requireProject: typeof requireProject\n /** Injectable for tests; used for the `db reset` migrate/seed follow-up prompts. Never invokes real inquirer. */\n confirmImpl?: typeof import(\"@inquirer/prompts\").confirm\n /** Injectable for tests; used for `confirmDestructive`'s typed-phrase prompt. Never invokes real inquirer. */\n destructiveImpl?: typeof import(\"@inquirer/prompts\").input\n}\n\nfunction defaultDbDeps(): DbDeps {\n return {\n startDevSession,\n ensureDevDatabaseReady,\n createApiClient,\n runNpx,\n runProcess,\n createConnection: createSqlConnection,\n findExecutable,\n requireProject,\n }\n}\n\ninterface PackageJsonShape {\n scripts?: Record<string, unknown>\n prisma?: { seed?: unknown }\n}\n\n/**\n * Whether seeding is configured at all — used to decide whether `db reset`\n * even offers the \"seed now?\" follow-up. Covers the classic `prisma.seed`\n * field (Prisma <6) and a plain `scripts.seed` entry; Prisma 6's\n * `prisma.config.ts` seed export can't be detected without executing it, so\n * a project relying solely on that will need to run `meridian db seed`\n * manually (it still works — it's just not auto-offered here).\n */\nfunction hasSeedConfigured(root: string): boolean {\n let parsed: PackageJsonShape\n try {\n parsed = JSON.parse(readFileSync(join(root, \"package.json\"), \"utf8\")) as PackageJsonShape\n } catch {\n return false\n }\n const prismaSeed = parsed.prisma?.seed\n if (typeof prismaSeed === \"string\" && prismaSeed !== \"\") return true\n const seedScript = parsed.scripts?.seed\n return typeof seedScript === \"string\" && seedScript !== \"\"\n}\n\nexport interface DbResetOptions {\n /** Run `npx prisma migrate deploy` afterwards, without asking. */\n migrate?: boolean\n /** Run `npx prisma db seed` afterwards, without asking. */\n seed?: boolean\n port?: number\n envFile?: string\n deps?: Partial<DbDeps>\n}\n\ninterface DbResetJson {\n reset: boolean\n database: string\n app_id: Id\n migrated: boolean\n seeded: boolean\n aborted: boolean\n}\n\n/** Runs `db reset`'s logic; `options.deps` lets tests inject every collaborator. Returns the process exit code. */\nexport async function runDbReset(options: DbResetOptions = {}): Promise<number> {\n const deps = { ...defaultDbDeps(), ...options.deps }\n const json = isJsonOutput()\n\n const project = deps.requireProject(workingDirectory())\n const client = deps.createApiClient({})\n const appId = project.config.app_id\n\n const devDatabase = await deps.ensureDevDatabaseReady(client, appId)\n const database = devDatabase.database\n\n const confirmed = await confirmDestructive({\n message: `This will drop every table in ${database}. Type the database name to confirm.`,\n phrase: database,\n assumeYes: isAssumeYes(),\n ...(deps.destructiveImpl !== undefined ? { promptImpl: deps.destructiveImpl } : {}),\n })\n\n if (!confirmed) {\n log(\"Aborted.\")\n if (json) {\n printJson({\n reset: false,\n database,\n app_id: appId,\n migrated: false,\n seeded: false,\n aborted: true,\n } satisfies DbResetJson)\n }\n return 0\n }\n\n await withSpinner(`Resetting ${database}...`, () => client.resetDevDatabase(appId), {\n success: `Reset ${database}.`,\n })\n\n let wantMigrate = options.migrate === true\n let wantSeed = options.seed === true\n\n if (!wantMigrate && !wantSeed) {\n if (isInteractive()) {\n wantMigrate = await confirmAction({\n message: \"Run `npx prisma migrate deploy` now?\",\n default: false,\n ...(deps.confirmImpl !== undefined ? { promptImpl: deps.confirmImpl } : {}),\n })\n if (hasSeedConfigured(project.root)) {\n wantSeed = await confirmAction({\n message: \"Seed the database now?\",\n default: false,\n ...(deps.confirmImpl !== undefined ? { promptImpl: deps.confirmImpl } : {}),\n })\n }\n } else {\n hint(\"Run `npx prisma migrate deploy` and `npx prisma db seed` to finish setting up the database.\")\n }\n }\n\n let migrated = false\n let seeded = false\n let followUpExitCode = 0\n\n if (wantMigrate || wantSeed) {\n let session: DevSessionInfo | undefined\n try {\n session = await deps.startDevSession({\n ...(options.port !== undefined ? { port: options.port } : {}),\n ...(options.envFile !== undefined ? { envFile: options.envFile } : {}),\n })\n\n if (wantMigrate) {\n const result = await deps.runNpx([\"prisma\", \"migrate\", \"deploy\"], {\n cwd: session.project.root,\n env: session.env,\n inherit: true,\n })\n migrated = result.code === 0\n if (result.code !== 0) {\n error(`\\`npx prisma migrate deploy\\` exited with code ${result.code}.`)\n followUpExitCode = result.code\n }\n }\n\n if (followUpExitCode === 0 && wantSeed) {\n const result = await deps.runNpx([\"prisma\", \"db\", \"seed\"], {\n cwd: session.project.root,\n env: session.env,\n inherit: true,\n })\n seeded = result.code === 0\n if (result.code !== 0) {\n error(`\\`npx prisma db seed\\` exited with code ${result.code}.`)\n hint(\"Make sure `prisma.seed` (or your Prisma 6 seed config) is set in package.json.\")\n followUpExitCode = result.code\n }\n }\n } finally {\n if (session !== undefined) await session.stop()\n }\n }\n\n if (json) {\n printJson({ reset: true, database, app_id: appId, migrated, seeded, aborted: false } satisfies DbResetJson)\n }\n\n return followUpExitCode\n}\n\nexport interface DbSeedOptions {\n port?: number\n envFile?: string\n /** Extra args forwarded after `npx prisma db seed` (from `-- <args>`). */\n extraArgs?: string[]\n deps?: Partial<DbDeps>\n}\n\ninterface DbSeedJson {\n seeded: boolean\n exit_code: number\n}\n\n/** Runs `db seed`'s logic; `options.deps` lets tests inject every collaborator. Returns the process exit code. */\nexport async function runDbSeed(options: DbSeedOptions = {}): Promise<number> {\n const deps = { ...defaultDbDeps(), ...options.deps }\n const json = isJsonOutput()\n\n let session: DevSessionInfo | undefined\n try {\n session = await deps.startDevSession({\n ...(options.port !== undefined ? { port: options.port } : {}),\n ...(options.envFile !== undefined ? { envFile: options.envFile } : {}),\n })\n\n const args = [\"prisma\", \"db\", \"seed\", ...(options.extraArgs ?? [])]\n const result: RunResult = await deps.runNpx(args, {\n cwd: session.project.root,\n env: session.env,\n inherit: true,\n })\n\n if (result.code === 0) {\n success(\"Seeded the development database.\")\n } else {\n error(`\\`npx prisma db seed\\` exited with code ${result.code}.`)\n hint(\"Make sure `prisma.seed` (or your Prisma 6 seed config) is set in package.json.\")\n }\n\n if (json) printJson({ seeded: result.code === 0, exit_code: result.code } satisfies DbSeedJson)\n\n return result.code\n } finally {\n if (session !== undefined) await session.stop()\n }\n}\n\nexport interface DbShellOptions {\n port?: number\n envFile?: string\n /** Force the built-in REPL even when `mysql` is on PATH. */\n repl?: boolean\n /** Run one statement and exit. */\n execute?: string\n /** `--no-env`: skip patching DATABASE_URL into the project's .env file. */\n env?: boolean\n deps?: Partial<DbDeps>\n}\n\n/** Runs `db shell`'s logic; `options.deps` lets tests inject every collaborator. Returns the process exit code. */\nexport async function runDbShell(options: DbShellOptions = {}): Promise<number> {\n const deps = { ...defaultDbDeps(), ...options.deps }\n const json = isJsonOutput()\n\n let session: DevSessionInfo | undefined\n try {\n session = await deps.startDevSession({\n waitForDb: true,\n ...(options.port !== undefined ? { port: options.port } : {}),\n ...(options.envFile !== undefined ? { envFile: options.envFile } : {}),\n ...(options.env === false ? { patchEnv: false } : {}),\n })\n\n const info = session.connection\n const wantRepl = options.repl === true\n const mysqlPath = wantRepl ? null : deps.findExecutable(process.platform === \"win32\" ? \"mysql.exe\" : \"mysql\")\n\n if (mysqlPath !== null) {\n step(`Connecting to ${style.bold(info.database)} on ${info.host}:${info.port} with the mysql client...`)\n const args = [\"--host\", info.host, \"--port\", String(info.port), \"--user\", info.user, \"--database\", info.database]\n if (options.execute !== undefined) args.push(`--execute=${options.execute}`)\n\n // The password never touches argv (visible in `ps`) — only the env, which child processes don't leak to other users.\n const env: NodeJS.ProcessEnv = { ...session.env, MYSQL_PWD: info.password }\n const result = await deps.runProcess(mysqlPath, args, { cwd: session.project.root, env, inherit: true })\n return result.code\n }\n\n step(`Connecting to ${style.bold(info.database)} on ${info.host}:${info.port}...`)\n\n return await withConnection(\n info,\n async (connection) => {\n if (options.execute !== undefined) {\n return executeStatement(connection, info, options.execute, { json })\n }\n return runRepl({ connection, connectionInfo: info, input: process.stdin, output: process.stdout })\n },\n { factory: deps.createConnection },\n )\n } finally {\n if (session !== undefined) await session.stop()\n }\n}\n\nasync function runAndSetExitCode(fn: () => Promise<number>): Promise<void> {\n const code = await fn()\n if (code !== 0) process.exitCode = code\n}\n\n/** Wires up `meridian db reset|seed|shell`. `meridian db` alone prints help. */\nexport function registerDbCommand(program: Command): void {\n const db = program\n .command(\"db\")\n .description(\"Manage the Meridian-managed MySQL development database: reset, seed, or open a SQL shell.\")\n\n db.action(() => {\n db.outputHelp()\n })\n\n db.command(\"reset\")\n .description(\"Drop and recreate every table in the development database (keeps the MySQL user).\")\n .option(\"--migrate\", \"run `npx prisma migrate deploy` afterwards, without asking\")\n .option(\"--seed\", \"run `npx prisma db seed` afterwards, without asking\")\n .option(\"--port <port>\", \"local port for the Cloud SQL Auth Proxy\", (value: string) => parsePortOption(value))\n .option(\"--env-file <file>\", \"project .env file to update (defaults to .env)\")\n .action(async (opts: { migrate?: boolean; seed?: boolean; port?: number; envFile?: string }) => {\n await runAndSetExitCode(() =>\n runDbReset({\n ...(opts.migrate === true ? { migrate: true } : {}),\n ...(opts.seed === true ? { seed: true } : {}),\n ...(opts.port !== undefined ? { port: opts.port } : {}),\n ...(opts.envFile !== undefined ? { envFile: opts.envFile } : {}),\n }),\n )\n })\n\n db.command(\"seed\")\n .description(\"Run `npx prisma db seed` with the Cloud SQL Auth Proxy up and DATABASE_URL set.\")\n .option(\"--port <port>\", \"local port for the Cloud SQL Auth Proxy\", (value: string) => parsePortOption(value))\n .option(\"--env-file <file>\", \"project .env file to update (defaults to .env)\")\n .passThroughOptions()\n .argument(\"[args...]\", \"extra arguments forwarded to `npx prisma db seed` (put them after `--`)\")\n .action(async (args: string[], opts: { port?: number; envFile?: string }) => {\n await runAndSetExitCode(() =>\n runDbSeed({\n ...(opts.port !== undefined ? { port: opts.port } : {}),\n ...(opts.envFile !== undefined ? { envFile: opts.envFile } : {}),\n ...(args.length > 0 ? { extraArgs: args } : {}),\n }),\n )\n })\n\n db.command(\"shell\")\n .description(\"Open a SQL shell against the development database (the `mysql` client if available, otherwise a built-in REPL).\")\n .option(\"--port <port>\", \"local port for the Cloud SQL Auth Proxy\", (value: string) => parsePortOption(value))\n .option(\"--env-file <file>\", \"project .env file to read/patch (defaults to .env)\")\n .option(\"--repl\", \"force the built-in SQL REPL even when `mysql` is on PATH\")\n .option(\"-e, --execute <sql>\", \"run one SQL statement and exit\")\n .option(\"--no-env\", \"do not patch DATABASE_URL into the project's .env file\")\n .action(async (opts: { port?: number; envFile?: string; repl?: boolean; execute?: string; env?: boolean }) => {\n await runAndSetExitCode(() =>\n runDbShell({\n ...(opts.port !== undefined ? { port: opts.port } : {}),\n ...(opts.envFile !== undefined ? { envFile: opts.envFile } : {}),\n ...(opts.repl === true ? { repl: true } : {}),\n ...(opts.execute !== undefined ? { execute: opts.execute } : {}),\n ...(opts.env === false ? { env: false } : {}),\n }),\n )\n })\n}\n","import { createRequire } from \"node:module\"\n\n/**\n * The package version, read from package.json at runtime. `../package.json`\n * resolves from both `dist/index.js` (the published bin) and `src/` (vitest),\n * so there is nothing to keep in sync.\n */\nexport const VERSION: string = (() => {\n try {\n const require = createRequire(import.meta.url)\n const pkg = require(\"../package.json\") as { version?: unknown }\n return typeof pkg.version === \"string\" ? pkg.version : \"0.0.0\"\n } catch {\n return \"0.0.0\"\n }\n})()\n\n/** Sent as the User-Agent on every API call, e.g. `meridian-cli/0.1.0 (darwin arm64)`. */\nexport const USER_AGENT = `meridian-cli/${VERSION} (${process.platform} ${process.arch})`\n","/**\n * Typed HTTP client for meridian-api's `/app/cli/*` surface. Every response is\n * validated against the zod schemas in `./api-types.js` so a malformed or\n * unexpectedly-shaped payload becomes a clear `CliError` instead of a runtime\n * crash somewhere downstream. Every failure mode (HTTP error, network error,\n * timeout, bad payload) is normalized to `CliError`/`ApiError` so command code\n * never has to deal with raw `fetch` exceptions or `ZodError`s.\n */\n\nimport { hostname as osHostname } from \"node:os\"\nimport { z, type ZodType } from \"zod\"\nimport {\n type AppSummary,\n appSummarySchema,\n type DeviceCodeResponse,\n deviceCodeResponseSchema,\n type DeviceInfoResponse,\n deviceInfoResponseSchema,\n type DeviceTokenResponse,\n deviceTokenResponseSchema,\n type DevCredentials,\n devCredentialsSchema,\n type DevDatabase,\n devDatabaseSchema,\n type Id,\n type MeResponse,\n meResponseSchema,\n type MigrationRun,\n migrationRunSchema,\n type MigrationRunInput,\n type ProxyToken,\n proxyTokenSchema,\n} from \"./api-types.js\"\nimport { ApiError, CliError, notLoggedInError, sessionExpiredError } from \"./errors.js\"\n\nconst DEFAULT_TIMEOUT_MS = 30_000\nconst DEFAULT_CLIENT_NAME = \"meridian-cli\"\n/** `command` is `max:500` server-side; `truncate` adds one ellipsis character. */\nconst MAX_MIGRATION_COMMAND_LENGTH = 499\n\nexport interface ApiClientOptions {\n /** meridian-api root, e.g. https://api.the-meridian.ai (no trailing slash, no /app suffix). */\n baseUrl: string\n token?: string\n fetchImpl?: typeof fetch\n /** Per-request timeout in ms. Default 30_000. */\n timeoutMs?: number\n /** Sent as User-Agent, e.g. \"meridian-cli/0.1.0 (darwin arm64)\". */\n userAgent?: string\n}\n\nexport interface RequestOptions {\n body?: unknown\n query?: Record<string, string | number | undefined>\n /** Attach the bearer token. Default true. */\n auth?: boolean\n headers?: Record<string, string>\n /** Return null instead of throwing on 404. */\n allow404?: boolean\n signal?: AbortSignal\n}\n\n/**\n * Thin wrapper over `fetch`. Deliberately has no interceptor/plugin system —\n * every request goes through the same `request()` method so error handling\n * stays in one place.\n */\nexport class ApiClient {\n readonly baseUrl: string\n readonly #token: string | undefined\n readonly #fetchImpl: typeof fetch\n readonly #timeoutMs: number\n readonly #userAgent: string | undefined\n\n constructor(options: ApiClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\")\n this.#token = options.token\n this.#fetchImpl = options.fetchImpl ?? fetch\n this.#timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS\n this.#userAgent = options.userAgent\n }\n\n get hasToken(): boolean {\n return this.#token !== undefined\n }\n\n /** Returns a new client carrying the given token; used right after login. */\n withToken(token: string): ApiClient {\n return new ApiClient({\n baseUrl: this.baseUrl,\n token,\n fetchImpl: this.#fetchImpl,\n timeoutMs: this.#timeoutMs,\n ...(this.#userAgent !== undefined ? { userAgent: this.#userAgent } : {}),\n })\n }\n\n /**\n * Performs one request and validates the response against `schema`. Pass\n * `null` for endpoints whose body is irrelevant (e.g. logging a migration\n * run) — the resolved value is then `undefined`.\n */\n async request<T>(\n schema: ZodType<T> | null,\n method: string,\n path: string,\n options: RequestOptions = {},\n ): Promise<T> {\n const auth = options.auth ?? true\n if (auth && this.#token === undefined) throw notLoggedInError()\n\n const url = this.#buildUrl(path, options.query)\n const headers = this.#buildHeaders(options.headers, options.body !== undefined, auth)\n const response = await this.#fetchWithTimeout(url, method, headers, options.body, options.signal)\n\n if (response.status === 404 && options.allow404 === true) {\n await response.text().catch(() => \"\")\n return null as T\n }\n\n if (!response.ok) {\n throw await toApiError(response, method, path)\n }\n\n if (schema === null) {\n await response.text().catch(() => \"\")\n return undefined as T\n }\n\n const text = await response.text().catch(() => \"\")\n const data: unknown = text.trim().length === 0 ? undefined : parseJson(text, method, path)\n return parseWithSchema(schema, data, method, path)\n }\n\n /** `POST /app/cli/device/code` — unauthenticated. */\n async requestDeviceCode(input: { clientName?: string; hostname?: string } = {}): Promise<DeviceCodeResponse> {\n return this.request(deviceCodeResponseSchema, \"POST\", \"/app/cli/device/code\", {\n auth: false,\n body: {\n client_name: input.clientName ?? DEFAULT_CLIENT_NAME,\n hostname: input.hostname ?? osHostname(),\n },\n })\n }\n\n /**\n * `POST /app/cli/device/token` — a single poll attempt. On 428/429/410/403\n * this resolves an `ApiError` whose `errorCode` is the RFC 8628-ish string\n * from the body (`authorization_pending`, `slow_down`, ...); callers branch\n * on that, not on `status`.\n */\n async pollDeviceTokenOnce(deviceCode: string): Promise<DeviceTokenResponse> {\n return this.request(deviceTokenResponseSchema, \"POST\", \"/app/cli/device/token\", {\n auth: false,\n body: { device_code: deviceCode },\n })\n }\n\n /**\n * `GET /app/cli/device/info` — the approval UI's endpoint, exposed here for\n * completeness/tests. It sits behind `auth:api` (and rejects CLI tokens), so\n * the token is attached when one is available rather than required.\n */\n async getDeviceInfo(userCode: string): Promise<DeviceInfoResponse> {\n return this.request(deviceInfoResponseSchema, \"GET\", \"/app/cli/device/info\", {\n auth: this.hasToken,\n query: { user_code: userCode },\n })\n }\n\n async getMe(): Promise<MeResponse> {\n return this.request(meResponseSchema, \"GET\", \"/app/cli/me\")\n }\n\n async listApps(orgId: Id): Promise<AppSummary[]> {\n return this.request(z.array(appSummarySchema), \"GET\", `/app/cli/orgs/${encodePathSegment(orgId)}/apps`)\n }\n\n /** Idempotent ensure/provision; may resolve with `status: \"provisioning\"` — poll `getDevDatabase` until `\"ready\"`. */\n async ensureDevDatabase(appId: Id): Promise<DevDatabase> {\n return this.request(devDatabaseSchema, \"POST\", `/app/cli/apps/${encodePathSegment(appId)}/dev-database`)\n }\n\n /** `null` when the app has no dev database provisioned yet (404). */\n async getDevDatabase(appId: Id): Promise<DevDatabase | null> {\n return this.request<DevDatabase | null>(\n devDatabaseSchema,\n \"GET\",\n `/app/cli/apps/${encodePathSegment(appId)}/dev-database`,\n { allow404: true },\n )\n }\n\n async issueCredentials(appId: Id): Promise<DevCredentials> {\n return this.request(\n devCredentialsSchema,\n \"POST\",\n `/app/cli/apps/${encodePathSegment(appId)}/dev-database/credentials`,\n )\n }\n\n async issueProxyToken(appId: Id): Promise<ProxyToken> {\n return this.request(\n proxyTokenSchema,\n \"POST\",\n `/app/cli/apps/${encodePathSegment(appId)}/dev-database/proxy-token`,\n )\n }\n\n async resetDevDatabase(appId: Id): Promise<DevDatabase> {\n return this.request(devDatabaseSchema, \"POST\", `/app/cli/apps/${encodePathSegment(appId)}/dev-database/reset`)\n }\n\n /** `command` is capped server-side at 500 characters, so a long `--` passthrough is trimmed here rather than rejected as a 422. */\n async reportMigration(appId: Id, run: MigrationRunInput): Promise<void> {\n await this.request(null, \"POST\", `/app/cli/apps/${encodePathSegment(appId)}/dev-database/migrations`, {\n body: { ...run, command: truncate(run.command, MAX_MIGRATION_COMMAND_LENGTH) },\n })\n }\n\n async listMigrations(appId: Id): Promise<MigrationRun[]> {\n return this.request(\n z.array(migrationRunSchema),\n \"GET\",\n `/app/cli/apps/${encodePathSegment(appId)}/dev-database/migrations`,\n )\n }\n\n #buildUrl(path: string, query?: Record<string, string | number | undefined>): string {\n const url = new URL(`${this.baseUrl}${path}`)\n if (query !== undefined) {\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined) url.searchParams.set(key, String(value))\n }\n }\n return url.toString()\n }\n\n #buildHeaders(extra: Record<string, string> | undefined, hasBody: boolean, auth: boolean): Record<string, string> {\n const headers: Record<string, string> = { Accept: \"application/json\" }\n if (hasBody) headers[\"Content-Type\"] = \"application/json\"\n if (auth && this.#token !== undefined) headers.Authorization = `Bearer ${this.#token}`\n if (this.#userAgent !== undefined) headers[\"User-Agent\"] = this.#userAgent\n if (extra !== undefined) Object.assign(headers, extra)\n return headers\n }\n\n async #fetchWithTimeout(\n url: string,\n method: string,\n headers: Record<string, string>,\n body: unknown,\n externalSignal: AbortSignal | undefined,\n ): Promise<Response> {\n const controller = new AbortController()\n let timedOut = false\n const onExternalAbort = (): void => controller.abort()\n\n if (externalSignal !== undefined) {\n if (externalSignal.aborted) controller.abort()\n else externalSignal.addEventListener(\"abort\", onExternalAbort, { once: true })\n }\n\n const timeoutId = setTimeout(() => {\n timedOut = true\n controller.abort()\n }, this.#timeoutMs)\n\n try {\n return await this.#fetchImpl(url, {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n signal: controller.signal,\n })\n } catch (error) {\n if (timedOut) {\n throw new CliError(`Request to the Meridian API timed out after ${this.#timeoutMs}ms.`, {\n hint: \"The API may be slow or unreachable right now; try again in a moment.\",\n cause: error,\n })\n }\n if (externalSignal?.aborted === true) throw error\n throw new CliError(`Cannot reach the Meridian API at ${this.baseUrl}.`, {\n hint: \"Check your network connection, or set MERIDIAN_API_URL if you're targeting a different environment.\",\n cause: error,\n })\n } finally {\n clearTimeout(timeoutId)\n externalSignal?.removeEventListener(\"abort\", onExternalAbort)\n }\n }\n}\n\nfunction encodePathSegment(id: Id): string {\n return encodeURIComponent(String(id))\n}\n\nfunction parseJson(text: string, method: string, path: string): unknown {\n try {\n return JSON.parse(text)\n } catch (error) {\n throw new CliError(`The Meridian API returned a non-JSON response for ${method} ${path}.`, {\n hint: \"This usually means the CLI is out of date; try upgrading @the-meridian/cli.\",\n cause: error,\n })\n }\n}\n\nfunction parseWithSchema<T>(schema: ZodType<T>, data: unknown, method: string, path: string): T {\n const result = schema.safeParse(data)\n if (result.success) return result.data\n\n const issues = result.error.issues\n .slice(0, 3)\n .map((issue) => `${issue.path.length > 0 ? issue.path.join(\".\") : \"<root>\"}: ${issue.message}`)\n .join(\"; \")\n throw new CliError(\n `The Meridian API returned an unexpected payload for ${method} ${path}: ${truncate(issues, 300)}`,\n {\n hint: \"This usually means the CLI is out of date; try upgrading @the-meridian/cli.\",\n cause: result.error,\n },\n )\n}\n\nasync function toApiError(response: Response, method: string, path: string): Promise<ApiError> {\n const text = await response.text().catch(() => \"\")\n let body: unknown\n if (text.trim().length === 0) body = undefined\n else {\n try {\n body = JSON.parse(text)\n } catch {\n body = text\n }\n }\n\n const errorCode = extractErrorCode(body)\n const message =\n extractMessage(body) ?? `${method} ${path} failed with ${response.status} ${response.statusText}`.trim()\n const hint = hintForError(response.status, errorCode)\n\n return new ApiError(message, {\n status: response.status,\n body,\n ...(errorCode !== undefined ? { errorCode } : {}),\n ...(hint !== undefined ? { hint } : {}),\n })\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined\n}\n\n/**\n * meridian-api speaks two error dialects on the CLI surface. The device-auth\n * endpoints return the raw RFC 8628 shape (`{\"error\":\"authorization_pending\"}`),\n * while everything routed through the platform's `ApiResponse` helper — 409\n * \"database isn't ready\", 403 from the `cli.token` middleware, 404 from\n * `firstOrFail()` — returns the envelope\n * `{\"success\":false,\"data\":null,\"error\":{\"code\":…,\"message\":…,\"details\":…}}`.\n * Both must yield the same `errorCode`/`message` so callers can branch on one\n * thing.\n */\nfunction envelopeError(body: unknown): Record<string, unknown> | undefined {\n const record = asRecord(body)\n return record === undefined ? undefined : asRecord(record.error)\n}\n\n/** First field error out of a Laravel validation bag, in either dialect. */\nfunction firstFieldError(bag: unknown): string | undefined {\n const fields = asRecord(bag)\n if (fields === undefined) return undefined\n for (const value of Object.values(fields)) {\n if (Array.isArray(value) && typeof value[0] === \"string\") return value[0]\n if (typeof value === \"string\") return value\n }\n return undefined\n}\n\n/**\n * A specific validation failure is more actionable than the generic message\n * wrapping it, so it wins when both are present.\n */\nfunction extractMessage(body: unknown): string | undefined {\n const record = asRecord(body)\n if (record === undefined) return undefined\n\n const envelope = envelopeError(body)\n if (envelope !== undefined) {\n const fieldError = firstFieldError(asRecord(envelope.details)?.fields)\n if (fieldError !== undefined) return fieldError\n if (typeof envelope.message === \"string\" && envelope.message.length > 0) return envelope.message\n if (typeof envelope.code === \"string\" && envelope.code.length > 0) return envelope.code\n }\n\n const fieldError = firstFieldError(record.errors)\n if (fieldError !== undefined) return fieldError\n\n if (typeof record.message === \"string\" && record.message.length > 0) return record.message\n if (typeof record.error === \"string\" && record.error.length > 0) return record.error\n return undefined\n}\n\nfunction extractErrorCode(body: unknown): string | undefined {\n const envelope = envelopeError(body)\n if (envelope !== undefined && typeof envelope.code === \"string\") return envelope.code\n\n const record = asRecord(body)\n return record !== undefined && typeof record.error === \"string\" ? record.error : undefined\n}\n\n/**\n * Hints keyed by the envelope's `error.code`, for failures whose status alone\n * is too coarse to act on. The API's own `message` is always shown (see\n * `extractMessage`) and explains what happened; these add the next step.\n *\n * Without them, a plan or quota rejection inherits the generic hint for its\n * status — telling a developer over the storage cap to \"wait for provisioning\n * to finish\", which never helps and hides the one command that does.\n */\nconst HINTS_BY_ERROR_CODE: Record<string, string> = {\n dev_database_limit_reached:\n \"This app has reached its allowance of development databases. Whoever owns the existing one can delete it, or an organization owner/admin can remove it from the Meridian dashboard.\",\n dev_database_over_storage_limit:\n \"Run `meridian db reset` to drop and recreate the schema — reset and delete stay available while you're over the limit.\",\n FEATURE_NOT_ENTITLED:\n \"Your organization's plan does not include managed development databases; upgrade it in the Meridian dashboard.\",\n}\n\nfunction hintForError(status: number, errorCode: string | undefined): string | undefined {\n if (errorCode !== undefined) {\n const byCode = HINTS_BY_ERROR_CODE[errorCode]\n if (byCode !== undefined) return byCode\n }\n\n if (status === 401) return sessionExpiredError().hint\n if (status === 403) return \"You may not have access to this organization or app; check your Meridian membership.\"\n if (status === 404) return \"Run `meridian link` to select a valid organization and app.\"\n if (status === 409) {\n return \"The development database is not ready yet. Wait for provisioning to finish, then try again — `meridian dev` polls for you.\"\n }\n if (status === 422) return \"Check the request for validation errors and try again.\"\n if (status === 429) return \"You're being rate limited by the Meridian API; wait a moment and try again.\"\n if (status >= 500) return \"This looks like a server-side failure on the Meridian API; try again shortly.\"\n return undefined\n}\n\nfunction truncate(text: string, max: number): string {\n return text.length > max ? `${text.slice(0, max)}…` : text\n}\n","/**\n * Zod schemas (and their inferred types) for every payload meridian-api's\n * `/app/cli/*` endpoints send or accept. Every object schema is `.loose()` so\n * new fields added on the Laravel side never break an older CLI, while the\n * fields the CLI actually reads are still validated.\n */\n\nimport { z } from \"zod\"\n\n/** Laravel ids are sometimes numeric, sometimes string-ish (ULIDs, etc). */\nexport const idSchema = z.union([z.number(), z.string()])\nexport type Id = z.infer<typeof idSchema>\n\nexport const cliUserSchema = z\n .object({\n id: idSchema,\n name: z.string(),\n email: z.string(),\n })\n .loose()\nexport type CliUser = z.infer<typeof cliUserSchema>\n\nexport const orgSchema = z\n .object({\n id: idSchema,\n name: z.string(),\n slug: z.string(),\n })\n .loose()\nexport type Org = z.infer<typeof orgSchema>\n\nexport const appSummarySchema = z\n .object({\n id: idSchema,\n name: z.string(),\n slug: z.string(),\n })\n .loose()\nexport type AppSummary = z.infer<typeof appSummarySchema>\n\nexport const meResponseSchema = z\n .object({\n user: cliUserSchema,\n orgs: z.array(orgSchema),\n })\n .loose()\nexport type MeResponse = z.infer<typeof meResponseSchema>\n\nexport const deviceCodeResponseSchema = z\n .object({\n device_code: z.string(),\n user_code: z.string(),\n verification_uri: z.string(),\n verification_uri_complete: z.string().optional(),\n interval: z.number().optional(),\n expires_in: z.number().optional(),\n })\n .loose()\nexport type DeviceCodeResponse = z.infer<typeof deviceCodeResponseSchema>\n\nexport const deviceTokenResponseSchema = z\n .object({\n token: z.string(),\n expires_at: z.string().optional(),\n user: cliUserSchema,\n })\n .loose()\nexport type DeviceTokenResponse = z.infer<typeof deviceTokenResponseSchema>\n\nexport const deviceInfoResponseSchema = z\n .object({\n hostname: z.string(),\n client_name: z.string(),\n created_at: z.string().optional(),\n })\n .loose()\nexport type DeviceInfoResponse = z.infer<typeof deviceInfoResponseSchema>\n\n/**\n * Known statuses are validated as a literal union, but any other string\n * is still accepted (falls back to `z.string()`) so an unexpected status\n * added server-side surfaces as data instead of crashing the CLI.\n */\nexport const devDatabaseStatusSchema = z.union([z.enum([\"provisioning\", \"ready\", \"error\"]), z.string()])\nexport type DevDatabaseStatus = z.infer<typeof devDatabaseStatusSchema>\n\n/**\n * Mirrors `DevDatabaseResource`. Everything the API declares nullable is\n * `.nullish()` rather than `.optional()`: an explicit `null` (which the\n * resource does send — `instance_connection_name` and `region` are nullable\n * columns, and `error_message` is null unless `status` is `error`) fails an\n * `.optional()` check and would surface as a bogus \"unexpected payload\" error.\n */\nexport const devDatabaseSchema = z\n .object({\n id: idSchema,\n status: devDatabaseStatusSchema,\n database: z.string(),\n /** Nullish for an API older than per-developer Prisma shadow databases. */\n shadow_database: z.string().nullish(),\n mysql_user: z.string(),\n instance_connection_name: z.string().nullish(),\n region: z.string().nullish(),\n created_at: z.string().nullish(),\n /** Set by the API only while `status` is `error`; surfaced verbatim to the developer. */\n error_message: z.string().nullish(),\n })\n .loose()\nexport type DevDatabase = z.infer<typeof devDatabaseSchema>\n\nexport const devCredentialsSchema = z\n .object({\n host: z.string(),\n port: z.coerce.number(),\n database: z.string(),\n /**\n * The developer's Prisma shadow database, reachable with these same\n * credentials. Nullish for an API older than shadow databases, in which\n * case no SHADOW_DATABASE_URL is written.\n */\n shadow_database: z.string().nullish(),\n username: z.string(),\n password: z.string(),\n expires_at: z.string().nullish(),\n /** Echoed from the (nullable) dev-database column, so it can be null. */\n instance_connection_name: z.string().nullish(),\n })\n .loose()\nexport type DevCredentials = z.infer<typeof devCredentialsSchema>\n\nexport const proxyTokenSchema = z\n .object({\n access_token: z.string(),\n expires_at: z.string().nullish(),\n instance_connection_name: z.string().nullish(),\n })\n .loose()\nexport type ProxyToken = z.infer<typeof proxyTokenSchema>\n\nexport const migrationRunInputSchema = z.object({\n command: z.string(),\n status: z.enum([\"success\", \"failed\", \"rolled_back\"]),\n started_at: z.string(),\n finished_at: z.string(),\n output_excerpt: z.string().optional(),\n})\nexport type MigrationRunInput = z.infer<typeof migrationRunInputSchema>\n\n/** Mirrors `DevDatabaseMigrationResource`, whose timestamps and excerpt are all nullable columns. */\nexport const migrationRunSchema = z\n .object({\n id: idSchema.nullish(),\n command: z.string(),\n status: z.string(),\n started_at: z.string().nullish(),\n finished_at: z.string().nullish(),\n output_excerpt: z.string().nullish(),\n created_at: z.string().nullish(),\n })\n .loose()\nexport type MigrationRun = z.infer<typeof migrationRunSchema>\n\n/**\n * The `error` codes `POST /app/cli/device/token` returns. The first four are\n * the contract's polling codes (428/429/410/403); `invalid_grant` (404) is the\n * API's answer for a device code that is unknown or already exchanged.\n */\nexport type DeviceErrorCode =\n | \"authorization_pending\"\n | \"slow_down\"\n | \"expired_token\"\n | \"access_denied\"\n | \"invalid_grant\"\n","/**\n * Error types shared by every command.\n *\n * A `CliError` is an *expected* failure: the top-level handler prints\n * `message` (plus `hint` when present) and exits with `exitCode` instead of\n * dumping a stack trace. Anything else that escapes a command is a bug and is\n * reported with its stack.\n */\n\nexport interface CliErrorOptions {\n /** Actionable next step, e.g. \"Run `meridian login` to authenticate.\" */\n hint?: string\n /** Process exit code. Defaults to 1. */\n exitCode?: number\n cause?: unknown\n}\n\nexport class CliError extends Error {\n readonly hint: string | undefined\n readonly exitCode: number\n\n constructor(message: string, options: CliErrorOptions = {}) {\n super(message, options.cause !== undefined ? { cause: options.cause } : undefined)\n this.name = \"CliError\"\n this.hint = options.hint\n this.exitCode = options.exitCode ?? 1\n }\n}\n\n/** An error envelope returned by meridian-api. */\nexport class ApiError extends CliError {\n readonly status: number\n readonly body: unknown\n /** `error` field from the response body, e.g. \"authorization_pending\". */\n readonly errorCode: string | undefined\n\n constructor(\n message: string,\n init: { status: number; body?: unknown; errorCode?: string } & CliErrorOptions,\n ) {\n super(message, init)\n this.name = \"ApiError\"\n this.status = init.status\n this.body = init.body\n this.errorCode = init.errorCode\n }\n}\n\nexport function isCliError(error: unknown): error is CliError {\n return error instanceof CliError\n}\n\nexport function isApiError(error: unknown): error is ApiError {\n return error instanceof ApiError\n}\n\n/** No CLI token in ~/.meridian/config.json. */\nexport function notLoggedInError(): CliError {\n return new CliError(\"You are not logged in to Meridian.\", {\n hint: \"Run `meridian login` to authenticate this machine.\",\n })\n}\n\n/** No .meridian/project.json in the current directory tree. */\nexport function notLinkedError(): CliError {\n return new CliError(\"This project is not linked to a Meridian app.\", {\n hint: \"Run `meridian link` in your project root to pick an organization and app.\",\n })\n}\n\n/** A 401 from the API means the stored CLI token is expired or revoked. */\nexport function sessionExpiredError(cause?: unknown): CliError {\n return new CliError(\"Your Meridian CLI token is no longer valid (401).\", {\n hint: \"Run `meridian login` again to issue a fresh token.\",\n ...(cause !== undefined ? { cause } : {}),\n })\n}\n\n/**\n * A prompt was needed but stdin is not a TTY (CI, piped input). Names the\n * escape hatch so scripts can supply the answer up front.\n */\nexport function nonInteractiveError(what: string, override: string): CliError {\n return new CliError(`Cannot prompt for ${what} in a non-interactive shell.`, {\n hint: `Set ${override} to answer it up front.`,\n })\n}\n\n/** Human-readable one-liner for any thrown value. */\nexport function describeError(error: unknown): string {\n if (error instanceof Error) return error.message\n if (typeof error === \"string\") return error\n return String(error)\n}\n","/**\n * User-level state at `~/.meridian/config.json` (relocatable via\n * `MERIDIAN_HOME` for tests). Holds the long-lived scoped CLI token issued by\n * `meridian login`, so the file is created/rewritten with 0o600 permissions.\n */\n\nimport { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\"\nimport { dirname } from \"node:path\"\nimport { z } from \"zod\"\nimport { CliError, notLoggedInError } from \"./errors.js\"\nimport { globalConfigPath } from \"./paths.js\"\n\n/** meridian-api root. CLI endpoints resolve to `${base}/app/cli/...`. */\nexport const DEFAULT_API_BASE_URL = \"https://api.the-meridian.ai\"\n\nexport interface ConfigUser {\n id: number | string\n name: string\n email: string\n}\n\nexport interface GlobalConfig {\n api_base_url?: string\n token?: string\n token_expires_at?: string\n user?: ConfigUser\n}\n\nconst configUserSchema = z.object({\n id: z.union([z.number(), z.string()]),\n name: z.string(),\n email: z.string(),\n})\n\n/** Zod schema for the file; unknown keys are preserved. */\nexport const globalConfigSchema = z\n .object({\n api_base_url: z.string().exactOptional(),\n token: z.string().exactOptional(),\n token_expires_at: z.string().exactOptional(),\n user: configUserSchema.exactOptional(),\n })\n .loose() satisfies z.ZodType<GlobalConfig>\n\n/** `{}` when the file does not exist. Throws a CliError when it is unreadable/corrupt. */\nexport function readConfig(): GlobalConfig {\n const path = globalConfigPath()\n let raw: string\n try {\n raw = readFileSync(path, \"utf8\")\n } catch (error) {\n if (isEnoent(error)) return {}\n throw new CliError(`Could not read ${path}.`, {\n hint: \"Check the file's permissions, then run `meridian login` again.\",\n cause: error,\n })\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (error) {\n throw new CliError(`${path} is not valid JSON.`, {\n hint: \"Fix or delete the file, then run `meridian login` again.\",\n cause: error,\n })\n }\n\n const result = globalConfigSchema.safeParse(parsed)\n if (!result.success) {\n throw new CliError(`${path} does not look like a Meridian config file.`, {\n hint: \"Fix or delete the file, then run `meridian login` again.\",\n cause: result.error,\n })\n }\n return result.data\n}\n\n/** Atomic write: mkdir 0o700, write temp file 0o600, rename, chmod 600. */\nexport function writeConfig(config: GlobalConfig): void {\n const path = globalConfigPath()\n const dir = dirname(path)\n mkdirSync(dir, { recursive: true, mode: 0o700 })\n\n const tmpPath = `${path}.tmp`\n writeFileSync(tmpPath, `${JSON.stringify(config, null, 2)}\\n`, { mode: 0o600 })\n renameSync(tmpPath, path)\n chmodSync(path, 0o600)\n}\n\n/** Shallow merge onto the current file contents; returns the merged result. */\nexport function updateConfig(patch: Partial<GlobalConfig>): GlobalConfig {\n const merged = { ...readConfig(), ...patch }\n writeConfig(merged)\n return merged\n}\n\n/** Drops token/token_expires_at/user, keeps api_base_url. Returns true if a token was present. */\nexport function clearAuth(): boolean {\n const current = readConfig()\n const hadToken = current.token !== undefined\n const next: GlobalConfig = {\n ...(current.api_base_url !== undefined ? { api_base_url: current.api_base_url } : {}),\n }\n writeConfig(next)\n return hadToken\n}\n\n/**\n * Strips a trailing slash and a trailing `/app` segment. The API client builds\n * paths that already start with `/app/cli/...`, and the dashboard's\n * `NEXT_PUBLIC_API_BASE_URL` includes `/app` — so a copy-pasted dashboard base\n * URL keeps working instead of producing `/app/app/cli`. Any other prefix (e.g.\n * `/api`) is preserved, since it may be a real mount point.\n */\nexport function normalizeApiBaseUrl(url: string): string {\n return url.trim().replace(/\\/+$/, \"\").replace(/\\/app$/, \"\")\n}\n\n/**\n * Precedence: explicit override (a --api-url flag) > MERIDIAN_API_URL env >\n * config file api_base_url > DEFAULT_API_BASE_URL. Normalized (see below).\n */\nexport function resolveApiBaseUrl(override?: string): string {\n if (override !== undefined && override !== \"\") return normalizeApiBaseUrl(override)\n\n const envValue = process.env.MERIDIAN_API_URL\n if (envValue !== undefined && envValue !== \"\") return normalizeApiBaseUrl(envValue)\n\n const config = readConfig()\n if (config.api_base_url !== undefined && config.api_base_url !== \"\") {\n return normalizeApiBaseUrl(config.api_base_url)\n }\n\n return normalizeApiBaseUrl(DEFAULT_API_BASE_URL)\n}\n\nexport interface AuthState {\n token: string\n tokenExpiresAt?: string\n user?: ConfigUser\n}\n\n/** null when there is no stored token. */\nexport function getAuth(): AuthState | null {\n const config = readConfig()\n if (config.token === undefined) return null\n return {\n token: config.token,\n ...(config.token_expires_at !== undefined ? { tokenExpiresAt: config.token_expires_at } : {}),\n ...(config.user !== undefined ? { user: config.user } : {}),\n }\n}\n\n/** Throws notLoggedInError() when absent; throws a CliError hinting re-login when token_expires_at is in the past. */\nexport function requireToken(): string {\n const auth = getAuth()\n if (auth === null) throw notLoggedInError()\n\n if (auth.tokenExpiresAt !== undefined) {\n const expiry = new Date(auth.tokenExpiresAt).getTime()\n if (!Number.isNaN(expiry) && expiry < Date.now()) {\n throw new CliError(\"Your Meridian CLI token has expired.\", {\n hint: \"Run `meridian login` again to issue a fresh token.\",\n })\n }\n }\n\n return auth.token\n}\n\nfunction isEnoent(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\"\n}\n","/**\n * Every path the CLI touches, in one place.\n *\n * `MERIDIAN_HOME` relocates the whole user-level state directory — the tests\n * set it to a temp dir so nothing ever writes to the developer's real\n * ~/.meridian.\n */\n\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\n\n/** User-level state directory. Defaults to ~/.meridian. */\nexport function meridianHome(): string {\n const override = process.env.MERIDIAN_HOME\n if (override !== undefined && override !== \"\") return override\n return join(homedir(), \".meridian\")\n}\n\n/** Global config: token, api_base_url, cached user. chmod 600. */\nexport function globalConfigPath(): string {\n return join(meridianHome(), \"config.json\")\n}\n\n/** Cache directory for the downloaded cloud-sql-proxy binary. */\nexport function proxyBinDir(): string {\n return join(meridianHome(), \"bin\")\n}\n\n/** Per-project state directory: <root>/.meridian. */\nexport function projectStateDir(root: string): string {\n return join(root, \".meridian\")\n}\n\n/** Committed-safe project link file: <root>/.meridian/project.json. */\nexport function projectConfigPath(root: string): string {\n return join(projectStateDir(root), \"project.json\")\n}\n\n/** Database snapshots taken by `meridian migrate`: <root>/.meridian/snapshots. */\nexport function snapshotsDir(root: string): string {\n return join(projectStateDir(root), \"snapshots\")\n}\n\n/** The project's dotenv file that DATABASE_URL is written into. */\nexport function envFilePath(root: string, fileName = \".env\"): string {\n return join(root, fileName)\n}\n","/**\n * Global flags parsed by the root command, made available to every subcommand\n * without threading them through each action signature. The root command calls\n * `setGlobalOptions` once in its `preAction` hook.\n */\n\nexport interface GlobalOptions {\n /** `--api-url`: overrides MERIDIAN_API_URL and the stored config. */\n apiUrl?: string\n /** `--json`: machine-readable result on stdout, no human logs. */\n json: boolean\n quiet: boolean\n verbose: boolean\n /** `--no-color`; undefined means \"decide from the terminal\". */\n color?: boolean\n /** `--yes`: pre-approve confirmation prompts. */\n yes: boolean\n /** `--no-input`: never prompt, fail instead. */\n interactive?: boolean\n /** `--cwd`: run as if the CLI had been started in this directory. */\n cwd?: string\n}\n\nconst defaults: GlobalOptions = {\n json: false,\n quiet: false,\n verbose: false,\n yes: false,\n}\n\nlet current: GlobalOptions = { ...defaults }\n\nexport function setGlobalOptions(options: Partial<GlobalOptions>): void {\n current = { ...current, ...options }\n}\n\nexport function getGlobalOptions(): Readonly<GlobalOptions> {\n return current\n}\n\nexport function resetGlobalOptions(): void {\n current = { ...defaults }\n}\n\nexport function isJsonOutput(): boolean {\n return current.json\n}\n\n/** Directory commands should treat as the project location. */\nexport function workingDirectory(): string {\n return current.cwd ?? process.cwd()\n}\n","import { USER_AGENT } from \"../version.js\"\nimport { ApiClient } from \"./api.js\"\nimport { getAuth, resolveApiBaseUrl } from \"./config.js\"\nimport { getGlobalOptions } from \"./context.js\"\nimport { notLoggedInError } from \"./errors.js\"\n\nexport interface CreateApiClientOptions {\n /** Fail fast when there is no stored token. Default true. */\n requireAuth?: boolean\n /** Overrides --api-url / MERIDIAN_API_URL / the stored config. */\n apiUrl?: string\n /** Use this token instead of the stored one (used right after login). */\n token?: string\n fetchImpl?: typeof fetch\n}\n\n/**\n * The single place commands get an API client from: resolves the base URL and\n * the stored CLI token, and turns \"no token\" into the actionable\n * `meridian login` error before any request is attempted.\n */\nexport function createApiClient(options: CreateApiClientOptions = {}): ApiClient {\n const requireAuth = options.requireAuth ?? true\n const baseUrl = resolveApiBaseUrl(options.apiUrl ?? getGlobalOptions().apiUrl)\n const token = options.token ?? getAuth()?.token\n\n if (requireAuth && token === undefined) throw notLoggedInError()\n\n return new ApiClient({\n baseUrl,\n userAgent: USER_AGENT,\n ...(token !== undefined ? { token } : {}),\n ...(options.fetchImpl !== undefined ? { fetchImpl: options.fetchImpl } : {}),\n })\n}\n","/**\n * Reaching the dev database through the local Cloud SQL Auth Proxy: building\n * connection info from API credentials, opening/closing connections, polling\n * until the backend answers queries, and turning mysql2 errors into\n * actionable `CliError`s that never leak the password.\n */\n\nimport { CliError, describeError } from \"../errors.js\"\n\n/** Everything needed to reach the dev DB through the local proxy. */\nexport interface DbConnectionInfo {\n host: string\n port: number\n user: string\n password: string\n database: string\n}\n\n/**\n * Minimal surface of a mysql2 promise connection that this CLI uses, so tests\n * can inject a fake without pulling in mysql2's types.\n */\nexport interface SqlConnection {\n query(sql: string): Promise<unknown>\n end(): Promise<void>\n destroy?(): void\n}\n\nexport type ConnectionFactory = (\n info: DbConnectionInfo,\n options?: { multipleStatements?: boolean },\n) => Promise<SqlConnection>\n\n/**\n * The API returns `host`/`port` placeholders for the real Cloud SQL instance;\n * every connection actually goes through the proxy this CLI spawns locally.\n */\nexport function connectionInfoFromCredentials(\n credentials: { username: string; password: string; database: string },\n proxy: { host?: string; port: number },\n): DbConnectionInfo {\n return {\n host: proxy.host ?? \"127.0.0.1\",\n port: proxy.port,\n user: credentials.username,\n password: credentials.password,\n database: credentials.database,\n }\n}\n\n/** Real factory over mysql2/promise, imported lazily so it isn't paid for on every command. */\nexport const createSqlConnection: ConnectionFactory = async (info, options) => {\n const { createConnection } = await import(\"mysql2/promise\")\n const connection = await createConnection({\n host: info.host,\n port: info.port,\n user: info.user,\n password: info.password,\n database: info.database,\n ...(options?.multipleStatements !== undefined ? { multipleStatements: options.multipleStatements } : {}),\n })\n return connection as unknown as SqlConnection\n}\n\n/** Closes a connection, falling back to a forceful destroy so a close failure never masks the real error. */\nasync function closeQuietly(connection: SqlConnection): Promise<void> {\n try {\n await connection.end()\n } catch {\n connection.destroy?.()\n }\n}\n\n/** Runs `fn` with a connection and always closes it, even on throw. */\nexport async function withConnection<T>(\n info: DbConnectionInfo,\n fn: (connection: SqlConnection) => Promise<T>,\n options: { multipleStatements?: boolean; factory?: ConnectionFactory } = {},\n): Promise<T> {\n const factory = options.factory ?? createSqlConnection\n const factoryOptions = options.multipleStatements !== undefined ? { multipleStatements: options.multipleStatements } : {}\n const connection = await factory(info, factoryOptions)\n try {\n return await fn(connection)\n } finally {\n await closeQuietly(connection)\n }\n}\n\n/**\n * Polls `SELECT 1` until the database answers. The proxy accepts TCP before\n * the backend is reachable, so a successful port probe is not enough.\n */\nexport async function waitForDatabase(\n info: DbConnectionInfo,\n options: {\n timeoutMs?: number\n intervalMs?: number\n factory?: ConnectionFactory\n sleep?: (ms: number) => Promise<void>\n now?: () => number\n } = {},\n): Promise<void> {\n const timeoutMs = options.timeoutMs ?? 30_000\n const intervalMs = options.intervalMs ?? 500\n const factory = options.factory ?? createSqlConnection\n const sleep = options.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)))\n const now = options.now ?? Date.now\n\n const deadline = now() + timeoutMs\n let lastError: unknown\n\n for (;;) {\n try {\n const connection = await factory(info)\n try {\n await connection.query(\"SELECT 1\")\n } finally {\n await closeQuietly(connection)\n }\n return\n } catch (error) {\n lastError = error\n }\n\n if (now() >= deadline) throw toDatabaseError(lastError, info)\n await sleep(intervalMs)\n }\n}\n\nfunction extractErrorCode(error: unknown): string | undefined {\n if (typeof error === \"object\" && error !== null && \"code\" in error) {\n const code = (error as { code?: unknown }).code\n if (typeof code === \"string\") return code\n }\n return undefined\n}\n\n/** Removes every occurrence of the password from a message so it can never be echoed back. */\nfunction redactPassword(text: string, password: string): string {\n if (password === \"\") return text\n return text.split(password).join(\"***\")\n}\n\n/** Turns a mysql2 error into an actionable CliError (never leaks the password). */\nexport function toDatabaseError(error: unknown, info: DbConnectionInfo): CliError {\n const target = `${info.host}:${info.port}/${info.database}`\n const code = extractErrorCode(error)\n\n const build = (message: string, hint?: string): CliError =>\n new CliError(redactPassword(message, info.password), {\n ...(hint !== undefined ? { hint: redactPassword(hint, info.password) } : {}),\n cause: error,\n })\n\n if (code === \"ER_ACCESS_DENIED_ERROR\") {\n return build(\n `Access denied connecting to ${target} as \"${info.user}\".`,\n \"Database credentials are short-lived and rotate automatically — run `meridian dev` again to fetch fresh ones.\",\n )\n }\n\n if (code === \"ER_BAD_DB_ERROR\") {\n return build(\n `Database \"${info.database}\" does not exist on ${target}.`,\n \"Run `meridian db reset` to recreate it.\",\n )\n }\n\n if (code === \"ECONNREFUSED\") {\n return build(\n `Could not reach ${target} (${code}).`,\n \"Nothing is listening on that port. `meridian dev` and `meridian migrate` start the Cloud SQL Auth Proxy for you; start it first if you are connecting by hand.\",\n )\n }\n\n // The port answered but MySQL never completed a handshake, so the proxy is up\n // and the problem is between it and Cloud SQL.\n if (code === \"ETIMEDOUT\" || code === \"PROTOCOL_SEQUENCE_TIMEOUT\") {\n return build(\n `Timed out waiting for MySQL at ${target} (${code}).`,\n \"The proxy is listening but the database never answered. Check that your network allows outbound connections to Cloud SQL (VPN, firewall, proxy), then retry with --verbose to see the proxy's own log output.\",\n )\n }\n\n const detail = code ?? describeError(error)\n return build(`Database error connecting to ${target} as \"${info.user}\": ${detail}`)\n}\n","/**\n * The CLI's only channel for talking to a human or to a machine consumer.\n *\n * Design rule every command follows: human-readable output goes to stderr;\n * stdout is reserved for machine-readable payloads (`--json`, `db shell`\n * query rows). That way `meridian whoami --json | jq` always works, and\n * piping/redirecting stdout never captures a progress spinner by accident.\n */\n\nimport pc from \"picocolors\"\nimport { describeError, isApiError, isCliError } from \"./errors.js\"\nimport type { CliError } from \"./errors.js\"\n\nexport interface OutputStreams {\n out: NodeJS.WritableStream\n err: NodeJS.WritableStream\n}\n\nexport interface OutputMode {\n /** --json: suppress human logs and spinners entirely. */\n json: boolean\n /** --quiet: only warnings and errors. */\n quiet: boolean\n /** --verbose: include debug lines. */\n verbose: boolean\n /** Colors enabled (respects NO_COLOR / FORCE_COLOR / non-TTY). */\n color: boolean\n}\n\ninterface OutputState {\n mode: OutputMode\n streams: OutputStreams\n}\n\nlet state: OutputState | undefined\n\nfunction defaultStreams(): OutputStreams {\n return { out: process.stdout, err: process.stderr }\n}\n\nfunction computeDefaultColor(streams: OutputStreams): boolean {\n return Boolean(\n !process.env.NO_COLOR &&\n (process.env.FORCE_COLOR ? true : Boolean((streams.err as NodeJS.WriteStream).isTTY)),\n )\n}\n\nfunction getState(): OutputState {\n if (state === undefined) {\n const streams = defaultStreams()\n state = {\n streams,\n mode: { json: false, quiet: false, verbose: false, color: computeDefaultColor(streams) },\n }\n }\n return state\n}\n\n/** Process-wide mode, configured once by the root command from its global flags. */\nexport function configureOutput(options: Partial<OutputMode> & { streams?: OutputStreams }): void {\n const current = getState()\n const streamsChanged = options.streams !== undefined\n const streams = options.streams ?? current.streams\n const color = options.color ?? (streamsChanged ? computeDefaultColor(streams) : current.mode.color)\n\n state = {\n streams,\n mode: {\n json: options.json ?? current.mode.json,\n quiet: options.quiet ?? current.mode.quiet,\n verbose: options.verbose ?? current.mode.verbose,\n color,\n },\n }\n}\n\nexport function getOutputMode(): Readonly<OutputMode> {\n return { ...getState().mode }\n}\n\n/** Test helper: resets mode and streams to the defaults. */\nexport function resetOutput(): void {\n state = undefined\n}\n\nfunction colors(): ReturnType<typeof pc.createColors> {\n return pc.createColors(getOutputMode().color)\n}\n\n/** Style helpers so commands never import picocolors directly. */\nexport const style = {\n bold(s: string): string {\n return colors().bold(s)\n },\n dim(s: string): string {\n return colors().dim(s)\n },\n cyan(s: string): string {\n return colors().cyan(s)\n },\n green(s: string): string {\n return colors().green(s)\n },\n yellow(s: string): string {\n return colors().yellow(s)\n },\n red(s: string): string {\n return colors().red(s)\n },\n /** Highlights a command the user should run, e.g. `meridian login`. */\n command(s: string): string {\n return colors().cyan(colors().bold(s))\n },\n /** Highlights a path or URL. */\n path(s: string): string {\n return colors().underline(s)\n },\n}\n\n/** Wraps `` `backticked` `` spans in `style.command` so hints read like docs. */\nfunction highlightBackticks(message: string): string {\n return message.replace(/`([^`]+)`/g, (_match, code: string) => style.command(code))\n}\n\nfunction indentLines(message: string, prefix: string): string {\n return message\n .split(\"\\n\")\n .map((line) => `${prefix}${line}`)\n .join(\"\\n\")\n}\n\nfunction suppressed(): boolean {\n const mode = getOutputMode()\n return mode.json || mode.quiet\n}\n\nfunction writeErr(text: string): void {\n getState().streams.err.write(text)\n}\n\nfunction writeErrLine(text: string): void {\n writeErr(`${text}\\n`)\n}\n\n// Log helpers — all write to stderr, all no-ops in json mode (except error/warn, which still print).\n\nexport function log(message = \"\"): void {\n if (suppressed()) return\n writeErrLine(message)\n}\n\nexport function step(message: string): void {\n if (suppressed()) return\n writeErrLine(`${colors().cyan(\"→\")} ${message}`)\n}\n\nexport function success(message: string): void {\n if (suppressed()) return\n writeErrLine(`${colors().green(\"✔\")} ${message}`)\n}\n\nexport function warn(message: string): void {\n writeErrLine(`${colors().yellow(\"⚠\")} ${message}`)\n}\n\nexport function error(message: string): void {\n writeErrLine(`${colors().red(\"✖\")} ${message}`)\n}\n\nexport function debug(message: string): void {\n const mode = getOutputMode()\n if (suppressed() || !mode.verbose) return\n writeErrLine(colors().dim(`· ${message}`))\n}\n\n/** Indented continuation lines, e.g. key/value details under a step. */\nexport function detail(message: string): void {\n if (suppressed()) return\n writeErrLine(indentLines(message, \" \"))\n}\n\n/** Like `detail`, but always prints — used by `reportError`, whose human line must survive --json/--quiet. */\nfunction detailAlways(message: string): void {\n writeErrLine(indentLines(message, \" \"))\n}\n\n/** Aligned \" key value\" block for whoami/link summaries. */\nexport function keyValues(entries: Array<[string, string]>): void {\n if (suppressed()) return\n if (entries.length === 0) return\n const maxKeyLength = Math.max(...entries.map(([key]) => key.length))\n for (const [key, value] of entries) {\n writeErrLine(` ${colors().dim(key.padEnd(maxKeyLength))} ${value}`)\n }\n}\n\n/** A boxed/indented actionable hint, e.g. \"Run `meridian login`\". Backticked spans are highlighted. */\nexport function hint(message: string): void {\n writeErrLine(indentLines(highlightBackticks(message), ` ${colors().dim(\"›\")} `))\n}\n\n/** stdout, `JSON.stringify(value, null, 2)` + newline. The only stdout writer for commands. */\nexport function printJson(value: unknown): void {\n getState().streams.out.write(`${JSON.stringify(value, null, 2)}\\n`)\n}\n\n/** stdout, raw (for `db shell` output). */\nexport function printLine(message: string): void {\n getState().streams.out.write(`${message}\\n`)\n}\n\nexport interface Spinner {\n start(text?: string): Spinner\n /** Replace the text while running. */\n update(text: string): Spinner\n succeed(text?: string): void\n fail(text?: string): void\n /** Stop without a mark (e.g. before handing the terminal to a child process). */\n stop(): void\n readonly text: string\n}\n\nconst SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"]\nconst SPINNER_INTERVAL_MS = 80\nconst HIDE_CURSOR = \"\\u001B[?25l\"\nconst SHOW_CURSOR = \"\\u001B[?25h\"\nconst CLEAR_LINE = \"\\r\\u001B[K\"\n\nclass SpinnerImpl implements Spinner {\n #text: string\n #timer: NodeJS.Timeout | undefined\n #frame = 0\n #running = false\n\n constructor(text: string) {\n this.#text = text\n }\n\n get text(): string {\n return this.#text\n }\n\n start(text?: string): Spinner {\n if (text !== undefined) this.#text = text\n if (getOutputMode().json || this.#running) return this\n this.#running = true\n\n if (!this.#animated()) {\n this.#writeLine(`${colors().cyan(\"→\")} ${this.#text}`)\n return this\n }\n\n this.#writeRaw(HIDE_CURSOR)\n this.#render()\n this.#timer = setInterval(() => {\n this.#frame = (this.#frame + 1) % SPINNER_FRAMES.length\n this.#render()\n }, SPINNER_INTERVAL_MS)\n this.#timer.unref()\n return this\n }\n\n update(text: string): Spinner {\n this.#text = text\n if (getOutputMode().json || !this.#running || !this.#animated()) return this\n this.#render()\n return this\n }\n\n succeed(text?: string): void {\n this.#finish(colors().green(\"✔\"), text)\n }\n\n fail(text?: string): void {\n this.#finish(colors().red(\"✖\"), text)\n }\n\n stop(): void {\n if (!this.#running) return\n this.#clearTimer()\n if (this.#animated()) {\n this.#writeRaw(CLEAR_LINE)\n this.#writeRaw(SHOW_CURSOR)\n }\n this.#running = false\n }\n\n #finish(mark: string, text?: string): void {\n if (text !== undefined) this.#text = text\n if (getOutputMode().json) {\n this.#running = false\n return\n }\n const wasAnimated = this.#running && this.#animated()\n this.#clearTimer()\n if (wasAnimated) {\n this.#writeRaw(CLEAR_LINE)\n this.#writeRaw(SHOW_CURSOR)\n }\n this.#writeLine(`${mark} ${this.#text}`)\n this.#running = false\n }\n\n #clearTimer(): void {\n if (this.#timer !== undefined) {\n clearInterval(this.#timer)\n this.#timer = undefined\n }\n }\n\n #render(): void {\n const frame = SPINNER_FRAMES[this.#frame] ?? SPINNER_FRAMES[0]\n const line = this.#truncate(`${colors().cyan(frame ?? \"\")} ${this.#text}`)\n this.#writeRaw(`${CLEAR_LINE}${line}`)\n }\n\n #truncate(line: string): string {\n const columns = this.#columns()\n if (columns === undefined || line.length <= columns) return line\n return line.slice(0, Math.max(0, columns - 1))\n }\n\n #columns(): number | undefined {\n const stream = getState().streams.err as NodeJS.WriteStream\n return typeof stream.columns === \"number\" ? stream.columns : undefined\n }\n\n /** Full braille animation only makes sense on a TTY, outside quiet mode. */\n #animated(): boolean {\n const stream = getState().streams.err as NodeJS.WriteStream\n return stream.isTTY === true && !getOutputMode().quiet\n }\n\n #writeLine(text: string): void {\n this.#writeRaw(`${text}\\n`)\n }\n\n #writeRaw(text: string): void {\n getState().streams.err.write(text)\n }\n}\n\n/**\n * Braille spinner on a TTY; a single \"→ text\" line (and a final mark) when the\n * stream is not a TTY, in quiet mode, or in json mode, so CI logs stay readable.\n */\nexport function spinner(text: string): Spinner {\n return new SpinnerImpl(text)\n}\n\n/** Runs `fn` with a spinner, succeeding/failing automatically. Returns fn's value. */\nexport async function withSpinner<T>(\n text: string,\n fn: (spinner: Spinner) => Promise<T>,\n options: { success?: string | ((value: T) => string); fail?: string } = {},\n): Promise<T> {\n const active = spinner(text).start()\n try {\n const value = await fn(active)\n const successText = typeof options.success === \"function\" ? options.success(value) : options.success\n active.succeed(successText)\n return value\n } catch (err) {\n active.fail(options.fail)\n throw err\n }\n}\n\ninterface JsonError {\n message: string\n hint?: string\n status?: number\n}\n\nfunction buildJsonError(err: CliError): JsonError {\n const payload: JsonError = { message: err.message }\n if (err.hint !== undefined) payload.hint = err.hint\n if (isApiError(err)) payload.status = err.status\n return payload\n}\n\nfunction truncate(text: string, max: number): string {\n return text.length > max ? `${text.slice(0, max)}…` : text\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value)\n } catch {\n return String(value)\n }\n}\n\n/**\n * Prints a CliError the way the top-level handler should: \"✖ message\", then the\n * hint, then (verbose only) the cause/stack. Returns the exit code to use.\n */\nexport function reportError(err: unknown): number {\n const mode = getOutputMode()\n\n if (isApiError(err)) {\n error(err.message)\n if (err.hint !== undefined) hint(err.hint)\n detailAlways(`status: ${err.status}`)\n if (mode.verbose && err.body !== undefined) detailAlways(truncate(safeStringify(err.body), 500))\n if (mode.json) printJson({ error: buildJsonError(err) })\n return err.exitCode\n }\n\n if (isCliError(err)) {\n error(err.message)\n if (err.hint !== undefined) hint(err.hint)\n if (mode.verbose && err.stack !== undefined) detailAlways(err.stack)\n if (mode.json) printJson({ error: buildJsonError(err) })\n return err.exitCode\n }\n\n const message = describeError(err)\n error(message)\n if (err instanceof Error && err.stack !== undefined) detailAlways(err.stack)\n if (mode.json) printJson({ error: { message } })\n return 1\n}\n","/**\n * Validation for numeric command flags. `Number(value)` quietly yields `NaN`\n * for a typo like `--port 300O`, which would otherwise surface much later as a\n * confusing proxy or port-scan failure.\n */\n\nimport { CliError } from \"./errors.js\"\n\nexport interface IntegerOptionRange {\n min?: number\n max?: number\n}\n\n/** Parses an integer flag, or returns undefined when the flag was not given. */\nexport function parseIntegerOption(\n raw: string | undefined,\n flag: string,\n range: IntegerOptionRange = {},\n): number | undefined {\n if (raw === undefined) return undefined\n\n const value = Number(raw)\n const { min, max } = range\n const isValid =\n Number.isInteger(value) && (min === undefined || value >= min) && (max === undefined || value <= max)\n\n if (!isValid) {\n const bounds =\n min !== undefined && max !== undefined\n ? ` between ${min} and ${max}`\n : min !== undefined\n ? ` of at least ${min}`\n : \"\"\n throw new CliError(`${flag} expects a whole number${bounds}, but got \"${raw}\".`, {\n hint: `Pass a valid value, e.g. \\`${flag} ${min ?? 1}\\`.`,\n })\n }\n\n return value\n}\n\n/** Parses a TCP port flag. */\nexport function parsePortOption(raw: string | undefined, flag = \"--port\"): number | undefined {\n return parseIntegerOption(raw, flag, { min: 1, max: 65535 })\n}\n","/**\n * Thin wrapper over `@inquirer/prompts` that gives every prompt a\n * non-interactive escape hatch: a command flag or an env var. `meridian` runs\n * unattended in CI and in agent/scripted environments, so a prompt that would\n * otherwise hang forever must instead fail fast with a `CliError` that names\n * the flag/env var to set.\n *\n * Renders on **stderr** (via the `output: process.stderr` context inquirer\n * accepts), keeping stdout free for machine-readable output.\n */\n\nimport { confirm, input, select } from \"@inquirer/prompts\"\nimport { CliError, nonInteractiveError } from \"./errors.js\"\n\n/**\n * False when stdin/stderr are not TTYs, when CI is set, or when\n * MERIDIAN_NON_INTERACTIVE is set. Commands use this to decide between\n * prompting and requiring flags/env vars.\n */\nexport function isInteractive(): boolean {\n if (interactiveOverride !== undefined) return interactiveOverride\n return (\n process.stdin.isTTY === true &&\n process.stderr.isTTY === true &&\n !process.env.CI &&\n !process.env.MERIDIAN_NON_INTERACTIVE\n )\n}\n\n/** True when `--yes`/MERIDIAN_YES pre-approves confirmations. */\nexport function isAssumeYes(): boolean {\n if (assumeYesOverride !== undefined) return assumeYesOverride\n return Boolean(process.env.MERIDIAN_YES)\n}\n\nlet interactiveOverride: boolean | undefined\nlet assumeYesOverride: boolean | undefined\n\n/** Set from the root command's `--yes`/`--no-input` flags. */\nexport function configurePrompts(options: { assumeYes?: boolean; interactive?: boolean }): void {\n if (options.assumeYes !== undefined) assumeYesOverride = options.assumeYes\n if (options.interactive !== undefined) interactiveOverride = options.interactive\n}\n\n/** Test helper: clears the overrides set by `configurePrompts`. */\nexport function resetPrompts(): void {\n interactiveOverride = undefined\n assumeYesOverride = undefined\n}\n\nexport interface Choice<T> {\n value: T\n name: string\n description?: string\n}\n\nexport interface SelectOptions<T> {\n message: string\n choices: Array<Choice<T>>\n /** Pre-selected value. */\n default?: T\n /**\n * Env var consulted before prompting (e.g. MERIDIAN_ORG). Matched against the\n * choice value, name, or a `slug`-like id, case-insensitively.\n */\n envVar?: string\n /** Explicit answer from a command flag; wins over everything. */\n answer?: string\n /** Names the flag to mention in the non-interactive error, e.g. \"--org\". */\n flag?: string\n promptImpl?: typeof import(\"@inquirer/prompts\").select\n}\n\nfunction matchChoice<T>(choices: Array<Choice<T>>, raw: string): Choice<T> | undefined {\n const target = raw.trim().toLowerCase()\n return choices.find((choice) => {\n const value = String(choice.value).trim().toLowerCase()\n const name = choice.name.trim().toLowerCase()\n return value === target || name === target\n })\n}\n\nfunction listChoiceNames<T>(choices: Array<Choice<T>>): string {\n return choices.map((choice) => choice.name).join(\", \")\n}\n\n/** Combines a flag and/or env var into the text `nonInteractiveError`'s hint mentions. */\nfunction describeOverride(flag: string | undefined, envVar: string | undefined): string {\n const parts = [flag, envVar].filter((part): part is string => part !== undefined)\n return parts.length > 0 ? parts.join(\" or \") : \"the appropriate flag\"\n}\n\n/**\n * Resolves a choice: explicit answer → env var → single choice auto-selected →\n * interactive select → nonInteractiveError naming the flag/env var.\n */\nexport async function selectOne<T>(options: SelectOptions<T>): Promise<T> {\n const { message, choices, envVar, answer, flag } = options\n\n if (choices.length === 0) {\n throw new CliError(\"Nothing to choose from.\")\n }\n\n if (answer !== undefined) {\n const match = matchChoice(choices, answer)\n if (match === undefined) {\n throw new CliError(`\"${answer}\" is not a valid choice for ${message}.`, {\n hint: `Valid options: ${listChoiceNames(choices)}.`,\n })\n }\n return match.value\n }\n\n if (envVar !== undefined) {\n const envValue = process.env[envVar]\n if (envValue !== undefined && envValue !== \"\") {\n const match = matchChoice(choices, envValue)\n if (match === undefined) {\n throw new CliError(`${envVar}=\"${envValue}\" is not a valid choice for ${message}.`, {\n hint: `Valid options: ${listChoiceNames(choices)}.`,\n })\n }\n return match.value\n }\n }\n\n if (choices.length === 1) {\n const only = choices[0]\n if (only !== undefined) return only.value\n }\n\n if (!isInteractive()) {\n throw nonInteractiveError(message, describeOverride(flag, envVar))\n }\n\n const promptImpl = options.promptImpl ?? select\n try {\n return await promptImpl(\n {\n message,\n choices: choices.map((choice) => ({\n value: choice.value,\n name: choice.name,\n ...(choice.description !== undefined ? { description: choice.description } : {}),\n })),\n ...(options.default !== undefined ? { default: options.default } : {}),\n },\n { output: process.stderr },\n )\n } catch (err) {\n throw toPromptError(err)\n }\n}\n\nexport interface ConfirmOptions {\n message: string\n default?: boolean\n /** Skip the prompt when --yes/MERIDIAN_YES is set. */\n assumeYes?: boolean\n flag?: string\n promptImpl?: typeof import(\"@inquirer/prompts\").confirm\n}\n\n/** Text mentioned in the non-interactive error: the call's own flag (if any), plus the global bypasses. */\nfunction confirmOverrideText(flag: string | undefined): string {\n return `${flag ?? \"--yes\"} (or MERIDIAN_YES)`\n}\n\n/** Non-interactive without --yes → nonInteractiveError (do NOT silently assume yes). */\nexport async function confirmAction(options: ConfirmOptions): Promise<boolean> {\n const assumeYes = options.assumeYes ?? isAssumeYes()\n if (assumeYes) return true\n\n if (!isInteractive()) {\n throw nonInteractiveError(options.message, confirmOverrideText(options.flag))\n }\n\n const promptImpl = options.promptImpl ?? confirm\n try {\n return await promptImpl(\n {\n message: options.message,\n ...(options.default !== undefined ? { default: options.default } : {}),\n },\n { output: process.stderr },\n )\n } catch (err) {\n throw toPromptError(err)\n }\n}\n\nexport interface TextOptions {\n message: string\n default?: string\n envVar?: string\n answer?: string\n flag?: string\n validate?: (value: string) => true | string\n promptImpl?: typeof import(\"@inquirer/prompts\").input\n}\n\nexport async function promptText(options: TextOptions): Promise<string> {\n if (options.answer !== undefined) return options.answer\n\n if (options.envVar !== undefined) {\n const envValue = process.env[options.envVar]\n if (envValue !== undefined && envValue !== \"\") return envValue\n }\n\n if (!isInteractive()) {\n throw nonInteractiveError(options.message, describeOverride(options.flag, options.envVar))\n }\n\n const promptImpl = options.promptImpl ?? input\n try {\n return await promptImpl(\n {\n message: options.message,\n ...(options.default !== undefined ? { default: options.default } : {}),\n ...(options.validate !== undefined ? { validate: options.validate } : {}),\n },\n { output: process.stderr },\n )\n } catch (err) {\n throw toPromptError(err)\n }\n}\n\n/**\n * A destructive-action confirmation that requires typing an exact phrase (the\n * database name) when interactive, and `--yes` when not. Used by `meridian db reset`.\n */\nexport async function confirmDestructive(options: {\n message: string\n phrase: string\n assumeYes?: boolean\n flag?: string\n promptImpl?: typeof import(\"@inquirer/prompts\").input\n}): Promise<boolean> {\n const assumeYes = options.assumeYes ?? isAssumeYes()\n if (assumeYes) return true\n\n if (!isInteractive()) {\n throw nonInteractiveError(options.message, confirmOverrideText(options.flag))\n }\n\n const promptImpl = options.promptImpl ?? input\n let typed: string\n try {\n typed = await promptImpl(\n { message: `${options.message} Type \"${options.phrase}\" to confirm:` },\n { output: process.stderr },\n )\n } catch (err) {\n throw toPromptError(err)\n }\n return typed.trim() === options.phrase\n}\n\n/** Maps @inquirer's ExitPromptError (Ctrl-C) to a CliError with exit code 130. */\nexport function toPromptError(error: unknown): unknown {\n if (error instanceof Error && error.name === \"ExitPromptError\") {\n return new CliError(\"Aborted.\", { exitCode: 130, cause: error })\n }\n return error\n}\n","/**\n * Per-project link file at `<root>/.meridian/project.json`. Committed-safe:\n * it names the org/app the project is linked to but never holds a secret.\n */\n\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\"\nimport { dirname, parse, resolve } from \"node:path\"\nimport { z } from \"zod\"\nimport { CliError, notLinkedError } from \"./errors.js\"\nimport { projectConfigPath, projectStateDir } from \"./paths.js\"\n\nexport interface ProjectConfig {\n org_id: number | string\n app_id: number | string\n app_name?: string\n /** Overrides the default `npm run dev` used by `meridian dev`. */\n dev_command?: string\n /** Opts out of the check that the Prisma datasource reads Meridian's DATABASE_URL. */\n skip_datasource_check?: boolean\n}\n\nexport const projectConfigSchema = z.object({\n org_id: z.union([z.number(), z.string()]),\n app_id: z.union([z.number(), z.string()]),\n app_name: z.string().exactOptional(),\n dev_command: z.string().exactOptional(),\n skip_datasource_check: z.boolean().exactOptional(),\n}) satisfies z.ZodType<ProjectConfig>\n\nexport interface LinkedProject {\n root: string\n config: ProjectConfig\n}\n\nconst GITIGNORE_ENTRIES = [\"snapshots/\", \"*.log\", \"tmp/\"]\n\n/** Walks up from `startDir` (default process.cwd()) to the filesystem root looking for `.meridian/project.json`. */\nexport function findProjectRoot(startDir?: string): string | null {\n let dir = resolve(startDir ?? process.cwd())\n const { root } = parse(dir)\n\n while (true) {\n if (existsSync(projectConfigPath(dir))) return dir\n if (dir === root) return null\n dir = dirname(dir)\n }\n}\n\n/** null when unlinked. Throws CliError on a corrupt/invalid project.json (mention the path, hint `meridian link`). */\nexport function readProject(startDir?: string): LinkedProject | null {\n const root = findProjectRoot(startDir)\n if (root === null) return null\n\n const path = projectConfigPath(root)\n let raw: string\n try {\n raw = readFileSync(path, \"utf8\")\n } catch (error) {\n if (isEnoent(error)) return null\n throw new CliError(`Could not read ${path}.`, {\n hint: \"Run `meridian link` to relink this project.\",\n cause: error,\n })\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (error) {\n throw new CliError(`${path} is not valid JSON.`, {\n hint: \"Run `meridian link` to relink this project.\",\n cause: error,\n })\n }\n\n const result = projectConfigSchema.safeParse(parsed)\n if (!result.success) {\n throw new CliError(`${path} is not a valid Meridian project file.`, {\n hint: \"Run `meridian link` to relink this project.\",\n cause: result.error,\n })\n }\n\n return { root, config: result.data }\n}\n\n/** Throws notLinkedError() when unlinked. */\nexport function requireProject(startDir?: string): LinkedProject {\n const project = readProject(startDir)\n if (project === null) throw notLinkedError()\n return project\n}\n\n/** Creates `<root>/.meridian/`, writes project.json (2-space JSON + trailing newline) and calls ensureProjectStateIgnore. */\nexport function writeProject(root: string, config: ProjectConfig): void {\n const resolvedRoot = resolve(root)\n mkdirSync(projectStateDir(resolvedRoot), { recursive: true })\n writeFileSync(projectConfigPath(resolvedRoot), `${JSON.stringify(config, null, 2)}\\n`)\n ensureProjectStateIgnore(resolvedRoot)\n}\n\n/** Deletes project.json; returns false when there was nothing to delete. Leaves other .meridian contents alone. */\nexport function removeProject(root: string): boolean {\n const path = projectConfigPath(resolve(root))\n if (!existsSync(path)) return false\n rmSync(path)\n return true\n}\n\n/**\n * Writes `<root>/.meridian/.gitignore` ignoring the runtime bits (snapshots/,\n * *.log, tmp/) while keeping project.json committable. Never overwrites an\n * existing file that already contains the entries.\n */\nexport function ensureProjectStateIgnore(root: string): void {\n const resolvedRoot = resolve(root)\n const stateDir = projectStateDir(resolvedRoot)\n mkdirSync(stateDir, { recursive: true })\n\n const gitignorePath = `${stateDir}/.gitignore`\n let existingLines: string[] = []\n if (existsSync(gitignorePath)) {\n existingLines = readFileSync(gitignorePath, \"utf8\").split(\"\\n\")\n }\n\n const missing = GITIGNORE_ENTRIES.filter((entry) => !existingLines.includes(entry))\n if (existingLines.length > 0 && missing.length === 0) return\n\n const lines = [...existingLines.filter((line) => line.trim() !== \"\"), ...missing]\n writeFileSync(gitignorePath, `${lines.join(\"\\n\")}\\n`)\n}\n\n/** Resolves the project root for a command: an explicit --cwd wins, else search upwards, else null. */\nexport function resolveProjectRoot(cwd?: string): string | null {\n if (cwd !== undefined) return findProjectRoot(cwd)\n return findProjectRoot()\n}\n\nfunction isEnoent(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\"\n}\n","/**\n * Child-process plumbing shared by `meridian dev` (the app's long-running dev\n * server) and `meridian migrate` / `meridian db seed` (short-lived `npx\n * prisma ...` invocations).\n */\n\nimport type { ChildProcess, SpawnOptions as NodeSpawnOptions } from \"node:child_process\"\nimport { readFileSync } from \"node:fs\"\nimport { delimiter, join } from \"node:path\"\nimport crossSpawn from \"cross-spawn\"\nimport { CliError } from \"./errors.js\"\n\n/**\n * We spawn through `cross-spawn` rather than `node:child_process.spawn` so\n * that `npm`/`npx` work on Windows, where they are `.cmd` shims that Node\n * refuses to execute without a shell. Doing that ourselves would mean passing\n * `shell: true`, and Node then flattens argv into one command line with no\n * escaping at all — so a `--name \"add users\"` would split, and a `&` in an\n * argument would run as a second command. cross-spawn instead builds the\n * `cmd.exe /d /s /c` invocation itself with per-argument quoting, so nothing\n * we pass is ever interpreted as shell syntax.\n */\nexport type SpawnFn = (command: string, args: readonly string[], options: NodeSpawnOptions) => ChildProcess\n\nexport interface SpawnOptions {\n cwd: string\n env?: NodeJS.ProcessEnv\n /** Inherit stdio (interactive commands like `prisma migrate dev` need a TTY). Default true. */\n inherit?: boolean\n /** Injectable for tests. */\n spawnImpl?: SpawnFn\n}\n\nexport interface RunResult {\n code: number\n signal: NodeJS.Signals | null\n /** Combined stdout+stderr, only captured when `inherit` is false. Trimmed to the last 8 KB. */\n output: string\n}\n\nconst MAX_OUTPUT_LENGTH = 8 * 1024\n\nfunction toEnoentError(command: string, cause: unknown): CliError {\n return new CliError(`Could not run \\`${command}\\`: command not found.`, {\n hint: `Make sure \\`${command}\\` is installed and on your PATH.`,\n cause,\n })\n}\n\nfunction isEnoent(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\"\n}\n\n/** Splits a shell-ish command string into argv without invoking a shell: handles single/double quotes and escaped spaces. */\nexport function parseCommandString(command: string): { command: string; args: string[] } {\n const tokens: string[] = []\n let current = \"\"\n let hasCurrent = false\n let quote: '\"' | \"'\" | null = null\n let i = 0\n\n while (i < command.length) {\n const ch = command.charAt(i)\n\n if (quote !== null) {\n if (ch === quote) {\n quote = null\n } else {\n current += ch\n hasCurrent = true\n }\n i++\n continue\n }\n\n if (ch === '\"' || ch === \"'\") {\n quote = ch\n hasCurrent = true\n i++\n continue\n }\n\n if (ch === \"\\\\\" && i + 1 < command.length) {\n current += command.charAt(i + 1)\n hasCurrent = true\n i += 2\n continue\n }\n\n if (ch === \" \" || ch === \"\\t\") {\n if (hasCurrent) {\n tokens.push(current)\n current = \"\"\n hasCurrent = false\n }\n i++\n continue\n }\n\n current += ch\n hasCurrent = true\n i++\n }\n\n if (quote !== null) {\n throw new CliError(`Unbalanced ${quote} quote in command: ${command}`)\n }\n if (hasCurrent) tokens.push(current)\n\n const [first, ...rest] = tokens\n if (first === undefined) {\n throw new CliError(\"Cannot parse an empty command string.\")\n }\n return { command: first, args: rest }\n}\n\nfunction attachOutputCapture(\n child: { stdout: NodeJS.ReadableStream | null; stderr: NodeJS.ReadableStream | null },\n onData: (chunk: Buffer | string) => void,\n): void {\n child.stdout?.on(\"data\", onData)\n child.stderr?.on(\"data\", onData)\n}\n\nfunction makeOutputCollector(): { append: (chunk: Buffer | string) => void; get: () => string } {\n let output = \"\"\n return {\n append(chunk) {\n output += chunk.toString()\n if (output.length > MAX_OUTPUT_LENGTH) output = output.slice(output.length - MAX_OUTPUT_LENGTH)\n },\n get: () => output,\n }\n}\n\n/** Spawns and resolves when the process exits. Never rejects on a non-zero exit — inspect `code`. Rejects only when the binary cannot be spawned (ENOENT → CliError naming the command). */\nexport function runProcess(command: string, args: string[], options: SpawnOptions): Promise<RunResult> {\n const spawnFn = options.spawnImpl ?? crossSpawn\n const inherit = options.inherit ?? true\n\n return new Promise((resolve, reject) => {\n const child = spawnFn(command, args, {\n cwd: options.cwd,\n env: options.env ?? process.env,\n stdio: inherit ? \"inherit\" : [\"ignore\", \"pipe\", \"pipe\"],\n })\n\n const collector = makeOutputCollector()\n if (!inherit) attachOutputCapture(child, collector.append)\n\n let settled = false\n\n child.once(\"error\", (error: NodeJS.ErrnoException) => {\n if (settled) return\n settled = true\n reject(isEnoent(error) ? toEnoentError(command, error) : error)\n })\n\n child.once(\"close\", (code, signal) => {\n if (settled) return\n settled = true\n resolve({ code: code ?? 0, signal, output: collector.get() })\n })\n })\n}\n\n/** Convenience for `runProcess(parseCommandString(cmd))`. */\nexport function runCommandString(command: string, options: SpawnOptions): Promise<RunResult> {\n const parsed = parseCommandString(command)\n return runProcess(parsed.command, parsed.args, options)\n}\n\n/** `npx <bin> <args>` with the local node_modules/.bin on PATH; used for prisma. */\nexport function runNpx(args: string[], options: SpawnOptions): Promise<RunResult> {\n const baseEnv = options.env ?? process.env\n const binDir = join(options.cwd, \"node_modules\", \".bin\")\n const path = baseEnv.PATH\n const env: NodeJS.ProcessEnv = {\n ...baseEnv,\n PATH: path !== undefined && path !== \"\" ? `${binDir}${delimiter}${path}` : binDir,\n }\n return runProcess(\"npx\", args, { ...options, env })\n}\n\nexport interface ManagedChild {\n readonly pid: number | undefined\n /** Resolves with the exit result. */\n readonly exited: Promise<RunResult>\n /** SIGTERM, then SIGKILL after `graceMs` (default 5000). Idempotent. */\n stop(signal?: NodeJS.Signals, graceMs?: number): Promise<void>\n}\n\nfunction trySignal(child: { kill(signal?: NodeJS.Signals): boolean }, signal: NodeJS.Signals): void {\n try {\n child.kill(signal)\n } catch (error) {\n if (!isEsrch(error)) throw error\n }\n}\n\nfunction isEsrch(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ESRCH\"\n}\n\n/**\n * Long-running child (the app dev server) that the caller supervises. Always\n * carries the {@link DEV_GUARD_ENV} marker so a nested `meridian dev` fails\n * loudly instead of forking forever — callers of `runProcess`/`runNpx`\n * (one-shot `prisma` commands) do not get this marker.\n */\nexport function startProcess(command: string, args: string[], options: SpawnOptions): ManagedChild {\n const spawnFn = options.spawnImpl ?? crossSpawn\n const inherit = options.inherit ?? true\n const env: NodeJS.ProcessEnv = { ...(options.env ?? process.env), [DEV_GUARD_ENV]: \"1\" }\n\n const child = spawnFn(command, args, {\n cwd: options.cwd,\n env,\n stdio: inherit ? \"inherit\" : [\"ignore\", \"pipe\", \"pipe\"],\n })\n\n const collector = makeOutputCollector()\n if (!inherit) attachOutputCapture(child, collector.append)\n\n const exited = new Promise<RunResult>((resolve, reject) => {\n child.once(\"error\", (error: NodeJS.ErrnoException) => {\n reject(isEnoent(error) ? toEnoentError(command, error) : error)\n })\n child.once(\"close\", (code, signal) => {\n resolve({ code: code ?? 0, signal, output: collector.get() })\n })\n })\n\n let stopped = false\n\n const stop = async (signal: NodeJS.Signals = \"SIGTERM\", graceMs = 5000): Promise<void> => {\n if (stopped) {\n await exited.catch(() => undefined)\n return\n }\n stopped = true\n\n trySignal(child, signal)\n\n const killTimer = setTimeout(() => {\n trySignal(child, \"SIGKILL\")\n }, graceMs)\n killTimer.unref?.()\n\n try {\n await exited\n } catch {\n // A spawn error surfaces via `exited`; `stop()` only guarantees termination.\n } finally {\n clearTimeout(killTimer)\n }\n }\n\n return {\n get pid() {\n return child.pid\n },\n exited,\n stop,\n }\n}\n\n/**\n * Environment marker set on children spawned by `meridian dev` so a nested\n * `meridian dev` (e.g. when the app's own `npm run dev` script calls it) can\n * fail loudly instead of forking forever.\n */\nexport const DEV_GUARD_ENV = \"MERIDIAN_DEV_ACTIVE\"\n\n/** True when we are already inside a `meridian dev` child process tree. */\nexport function isInsideDevSession(env: NodeJS.ProcessEnv = process.env): boolean {\n return env[DEV_GUARD_ENV] === \"1\"\n}\n\nconst RUNNER_PREFIXES: string[][] = [[\"npx\"], [\"npm\", \"exec\"], [\"pnpm\", \"dlx\"], [\"yarn\", \"dlx\"]]\n\nfunction stripRunnerPrefix(tokens: string[]): string[] {\n for (const prefix of RUNNER_PREFIXES) {\n if (prefix.length <= tokens.length && prefix.every((part, i) => tokens[i] === part)) {\n return tokens.slice(prefix.length)\n }\n }\n return tokens\n}\n\nfunction isMeridianBinary(token: string | undefined): boolean {\n if (token === undefined) return false\n return token === \"meridian\" || token.endsWith(\"/meridian\") || token.endsWith(\"\\\\meridian\")\n}\n\n/**\n * Throws a CliError when `command` would re-enter the CLI (matches\n * `meridian dev`, `npx meridian dev`, `pnpm|yarn|npm run` scripts resolved to\n * `meridian dev`, etc.). Used by `meridian dev` before running the app command.\n *\n * This is a syntactic check only (no filesystem access) so it never flags\n * `npm run dev` itself — the default app dev command — even though that\n * script could theoretically resolve to something self-invoking.\n */\nexport function assertNotSelfInvoking(command: string): void {\n let tokens: string[]\n try {\n const parsed = parseCommandString(command)\n tokens = [parsed.command, ...parsed.args]\n } catch {\n return\n }\n\n const rest = stripRunnerPrefix(tokens)\n if (isMeridianBinary(rest[0]) && rest[1] === \"dev\") {\n throw new CliError(\"`meridian dev` cannot run itself as the app's dev command.\", {\n hint:\n \"Set `dev_command` in .meridian/project.json to the underlying command (e.g. `next dev`), \" +\n \"because `meridian dev` runs `npm run dev` by default.\",\n })\n }\n}\n\n/** Reads `scripts.<name>` from `<root>/package.json`; null when absent/unreadable. */\nexport function readPackageScript(root: string, name: string): string | null {\n try {\n const raw = readFileSync(join(root, \"package.json\"), \"utf8\")\n const parsed: unknown = JSON.parse(raw)\n if (typeof parsed !== \"object\" || parsed === null) return null\n const scripts = (parsed as { scripts?: unknown }).scripts\n if (typeof scripts !== \"object\" || scripts === null) return null\n const value = (scripts as Record<string, unknown>)[name]\n return typeof value === \"string\" ? value : null\n } catch {\n return null\n }\n}\n","/**\n * Surgical `.env` patching for `meridian dev`.\n *\n * The developer's `.env` is user-owned content: comments, blank lines,\n * ordering, line endings and unrelated keys must survive untouched. We only\n * ever rewrite the specific keys we're told to (in place, if present) or\n * append them, and we keep a one-time `.backup` so the original is always\n * recoverable.\n */\n\nimport {\n chmodSync,\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n statSync,\n writeFileSync,\n} from \"node:fs\"\nimport { dirname } from \"node:path\"\nimport { CliError } from \"./errors.js\"\n\n/**\n * Mode for a `.env` this CLI creates itself. The file holds a live database\n * password, so it is owner-only from the start; a file the developer already\n * had keeps whatever mode they chose.\n */\nconst CREATED_ENV_MODE = 0o600\n\nexport interface EnvPatch {\n [key: string]: string\n}\n\nexport interface PatchEnvResult {\n path: string\n /** The .env file did not exist and was created. */\n created: boolean\n /** A `.env.backup` was written by this call (only ever written once — never overwritten). */\n backedUp: boolean\n /** Whether the file contents actually changed. */\n changed: boolean\n /** Per-key detail for reporting: previous value (undefined when the key was absent). */\n keys: Array<{ key: string; previous?: string; next: string; action: \"created\" | \"updated\" | \"unchanged\" }>\n}\n\nconst MANAGED_HEADER = \"# Managed by the Meridian CLI — DATABASE_URL is rewritten by `meridian dev`.\"\n\nconst LINE_RE = /^([ \\t]*)(export[ \\t]+)?([A-Za-z_][A-Za-z0-9_]*)([ \\t]*=[ \\t]*)(.*)$/\n\ninterface Line {\n text: string\n eol: string\n}\n\ninterface LineMatch {\n indent: string\n prefix: string\n key: string\n eq: string\n rest: string\n}\n\nfunction splitLines(content: string): Line[] {\n const lines: Line[] = []\n let start = 0\n for (let i = 0; i < content.length; i++) {\n if (content.charAt(i) !== \"\\n\") continue\n const hasCr = i > start && content.charAt(i - 1) === \"\\r\"\n const end = hasCr ? i - 1 : i\n lines.push({ text: content.slice(start, end), eol: hasCr ? \"\\r\\n\" : \"\\n\" })\n start = i + 1\n }\n if (start < content.length) lines.push({ text: content.slice(start), eol: \"\" })\n return lines\n}\n\nfunction detectDominantEol(lines: Line[]): string {\n let crlf = 0\n let lf = 0\n for (const line of lines) {\n if (line.eol === \"\\r\\n\") crlf++\n else if (line.eol === \"\\n\") lf++\n }\n return crlf > lf ? \"\\r\\n\" : \"\\n\"\n}\n\nfunction matchLine(text: string): LineMatch | null {\n const match = LINE_RE.exec(text)\n if (match === null) return null\n return {\n indent: match[1] ?? \"\",\n prefix: match[2] ?? \"\",\n key: match[3] ?? \"\",\n eq: match[4] ?? \"\",\n rest: match[5] ?? \"\",\n }\n}\n\nfunction unescapeDoubleQuoted(inner: string): string {\n return inner.replace(/\\\\(.)/g, (_full, ch: string) => (ch === \"n\" ? \"\\n\" : ch))\n}\n\nfunction decodeEnvValue(raw: string): string {\n const trimmed = raw.trim()\n if (trimmed.length >= 2 && trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n return unescapeDoubleQuoted(trimmed.slice(1, -1))\n }\n if (trimmed.length >= 2 && trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\")) {\n return trimmed.slice(1, -1)\n }\n return trimmed\n}\n\n/** Quotes/escapes a value for dotenv when needed (whitespace, #, quotes, newlines, empty). */\nexport function formatEnvValue(value: string): string {\n const needsQuoting = value === \"\" || /[\\s#\"'$]/.test(value)\n if (!needsQuoting) return value\n const escaped = value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"').replace(/\\n/g, \"\\\\n\")\n return `\"${escaped}\"`\n}\n\n/** Parses dotenv content into a record (last occurrence wins), for reading DATABASE_URL etc. */\nexport function parseEnvContent(content: string): Record<string, string> {\n const result: Record<string, string> = {}\n for (const line of splitLines(content)) {\n const match = matchLine(line.text)\n if (match === null) continue\n result[match.key] = decodeEnvValue(match.rest)\n }\n return result\n}\n\n/** Reads a single key's *unquoted* value out of dotenv content. */\nexport function readEnvValue(content: string, key: string): string | undefined {\n return parseEnvContent(content)[key]\n}\n\n/** Pure string transform, unit-testable without the filesystem. */\nexport function upsertEnvContent(\n content: string,\n patch: EnvPatch,\n): { content: string; changed: boolean; keys: PatchEnvResult[\"keys\"] } {\n const lines = splitLines(content)\n const keys: PatchEnvResult[\"keys\"] = []\n const toAppend: Array<{ key: string; value: string }> = []\n let changed = false\n\n for (const [key, value] of Object.entries(patch)) {\n let foundIndex = -1\n for (let i = lines.length - 1; i >= 0; i--) {\n const line = lines[i]\n if (line === undefined) continue\n const match = matchLine(line.text)\n if (match !== null && match.key === key) {\n foundIndex = i\n break\n }\n }\n\n if (foundIndex === -1) {\n toAppend.push({ key, value })\n keys.push({ key, next: value, action: \"created\" })\n changed = true\n continue\n }\n\n const line = lines[foundIndex]\n const match = line === undefined ? null : matchLine(line.text)\n if (line === undefined || match === null) continue\n\n const previous = decodeEnvValue(match.rest)\n if (previous === value) {\n keys.push({ key, previous, next: value, action: \"unchanged\" })\n continue\n }\n\n lines[foundIndex] = {\n text: `${match.indent}${match.prefix}${key}${match.eq}${formatEnvValue(value)}`,\n eol: line.eol,\n }\n keys.push({ key, previous, next: value, action: \"updated\" })\n changed = true\n }\n\n if (toAppend.length > 0) {\n const dominantEol = detectDominantEol(lines)\n const lastIndex = lines.length - 1\n const lastLine = lines[lastIndex]\n if (lastLine !== undefined && lastLine.eol === \"\") {\n lines[lastIndex] = { text: lastLine.text, eol: dominantEol }\n }\n for (const { key, value } of toAppend) {\n lines.push({ text: `${key}=${formatEnvValue(value)}`, eol: dominantEol })\n }\n }\n\n const nextContent = lines.map((line) => line.text + line.eol).join(\"\")\n return { content: nextContent, changed, keys }\n}\n\nfunction isEnoent(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\"\n}\n\n/**\n * Writes `content` and forces `mode`. `writeFileSync`'s own `mode` option only\n * applies when it creates the file, so a leftover temp/backup file from an\n * interrupted run would otherwise keep its old (possibly wider) permissions.\n */\nfunction writeExact(path: string, content: string, mode: number): void {\n writeFileSync(path, content, { mode })\n try {\n chmodSync(path, mode)\n } catch {\n // Best effort: some filesystems (Windows, mounted volumes) don't support chmod.\n }\n}\n\n/**\n * Patch (or create) the file at `envPath`. Writes `<envPath>.backup` before the\n * first modification of an existing file and never overwrites an existing backup,\n * so the developer's original is always recoverable.\n */\nexport function patchEnvFile(envPath: string, patch: EnvPatch, options: { backup?: boolean } = {}): PatchEnvResult {\n const backupEnabled = options.backup ?? true\n\n let existing: string | null = null\n let mode: number | undefined\n try {\n existing = readFileSync(envPath, \"utf8\")\n mode = statSync(envPath).mode & 0o777\n } catch (error) {\n if (!isEnoent(error)) {\n throw new CliError(`Could not read ${envPath}.`, {\n hint: \"Check the file's permissions and try again.\",\n cause: error,\n })\n }\n }\n\n const created = existing === null\n const baseContent = existing !== null ? existing : `${MANAGED_HEADER}\\n`\n const targetMode = mode ?? CREATED_ENV_MODE\n\n const { content: nextContent, changed, keys } = upsertEnvContent(baseContent, patch)\n\n let backedUp = false\n if (existing !== null && changed && backupEnabled) {\n const backupPath = `${envPath}.backup`\n if (!existsSync(backupPath)) {\n // The backup is a verbatim copy of a file that may hold secrets, so it\n // must not end up more readable than the original.\n writeExact(backupPath, existing, targetMode)\n backedUp = true\n }\n }\n\n if (created || changed) {\n mkdirSync(dirname(envPath), { recursive: true })\n // The pid keeps two concurrent commands (`meridian dev` in one terminal,\n // `meridian migrate` in another) from writing the same temp file and\n // renaming each other's half-written content over the real .env.\n const tmpPath = `${envPath}.${process.pid}.tmp`\n writeExact(tmpPath, nextContent, targetMode)\n renameSync(tmpPath, envPath)\n }\n\n return { path: envPath, created, backedUp, changed: created || changed, keys }\n}\n\n/** mysql://user:pass@host:port/db with user/password percent-encoded. */\nexport function buildDatabaseUrl(input: {\n username: string\n password: string\n host?: string\n port: number\n database: string\n params?: Record<string, string>\n}): string {\n const host = input.host ?? \"127.0.0.1\"\n const user = encodeURIComponent(input.username)\n const pass = encodeURIComponent(input.password)\n const hasParams = input.params !== undefined && Object.keys(input.params).length > 0\n const query = hasParams ? `?${new URLSearchParams(input.params).toString()}` : \"\"\n return `mysql://${user}:${pass}@${host}:${input.port}/${input.database}${query}`\n}\n\n/** Redacts the password in a mysql:// URL for log output. */\nexport function redactDatabaseUrl(url: string): string {\n return url.replace(/^(mysql:\\/\\/[^:@/]+):([^@]*)@/, \"$1:****@\")\n}\n","/**\n * Free-port selection for the Cloud SQL Auth Proxy. We bind-test rather than\n * connect-test so a stray refused connection doesn't get mistaken for a free\n * port.\n */\n\nimport { createServer } from \"node:net\"\nimport { CliError } from \"./errors.js\"\n\n/** One above MySQL's default (3306), so a proxy on this port is recognisable in logs. */\nconst DEFAULT_START_PORT = 3307\nconst DEFAULT_ATTEMPTS = 20\nconst MAX_PORT = 65535\n\n/** True when nothing is listening on host:port (bind test, not connect test). */\nexport function isPortFree(port: number, host = \"127.0.0.1\"): Promise<boolean> {\n return new Promise((resolve) => {\n const server = createServer()\n server.once(\"error\", () => {\n resolve(false)\n })\n server.once(\"listening\", () => {\n server.close(() => resolve(true))\n })\n server.listen({ port, host, exclusive: true })\n })\n}\n\nfunction bindEphemeralPort(host: string): Promise<number | null> {\n return new Promise((resolve) => {\n const server = createServer()\n server.once(\"error\", () => resolve(null))\n server.listen({ port: 0, host, exclusive: true }, () => {\n const address = server.address()\n const port = typeof address === \"object\" && address !== null ? address.port : null\n server.close(() => resolve(port))\n })\n })\n}\n\nexport interface FindFreePortOptions {\n preferred?: number\n start?: number\n attempts?: number\n host?: string\n}\n\n/**\n * Finds a free TCP port on 127.0.0.1. Tries `preferred` first when given, then\n * scans upward from `start` (default 3307 — one above MySQL's default so the\n * proxy port is recognisable), then falls back to an ephemeral port from the OS.\n */\nexport async function findFreePort(options: FindFreePortOptions = {}): Promise<number> {\n const host = options.host ?? \"127.0.0.1\"\n const start = options.start ?? DEFAULT_START_PORT\n const attempts = options.attempts ?? DEFAULT_ATTEMPTS\n\n if (options.preferred !== undefined && (await isPortFree(options.preferred, host))) {\n return options.preferred\n }\n\n for (let offset = 0; offset < attempts; offset++) {\n const candidate = start + offset\n if (candidate > MAX_PORT) break\n if (await isPortFree(candidate, host)) return candidate\n }\n\n const ephemeral = await bindEphemeralPort(host)\n if (ephemeral === null) {\n throw new CliError(\"Could not find a free local port for the Cloud SQL Auth Proxy.\", {\n hint: \"Close other applications using local ports and try again.\",\n })\n }\n return ephemeral\n}\n","/**\n * Reading and vetting a project's Prisma configuration, plus explaining the\n * Prisma failures whose messages point away from their real cause.\n *\n * The main guard here covers the one silent failure this product exists to\n * prevent: a Prisma datasource that does not read `DATABASE_URL`.\n *\n * Every session provisions the managed MySQL database, rotates its password,\n * starts the proxy and patches `DATABASE_URL` into `.env` — and a datasource\n * like `url = \"file:dev.sqlite\"` then ignores all of it, migrates a local\n * SQLite file, and reports success. The developer is left with a green\n * `meridian migrate` and an empty managed database, which is exactly the\n * SQLite/MySQL split the managed database is meant to remove.\n *\n * Checked before the session starts, so nothing is provisioned or rotated for\n * a run that cannot reach the managed database.\n */\n\nimport { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from \"node:fs\"\nimport { dirname, join, relative } from \"node:path\"\nimport { CliError } from \"./errors.js\"\n\nconst REQUIRED_URL_ENV = \"DATABASE_URL\"\nconst REQUIRED_SHADOW_URL_ENV = \"SHADOW_DATABASE_URL\"\nconst REQUIRED_PROVIDER = \"mysql\"\n\nconst BYPASS_HINT = `Set \\`\"skip_datasource_check\": true\\` in .meridian/project.json to run anyway.`\n\nexport type DatasourceUrl = { kind: \"env\"; name: string } | { kind: \"literal\"; value: string }\n\nexport interface PrismaDatasource {\n /** Relative to the project root, so error messages stay short. */\n schemaPath: string\n name: string\n /** null when the block declares no literal provider. */\n provider: string | null\n /** null when the block declares no url, or one this parser does not model. */\n url: DatasourceUrl | null\n /** null when the block declares no shadowDatabaseUrl. */\n shadowUrl: DatasourceUrl | null\n}\n\n/**\n * Drops `//` comments while respecting string literals, because a perfectly\n * ordinary `url = \"mysql://host/db\"` contains what looks like a comment.\n */\nfunction stripComments(source: string): string {\n let out = \"\"\n let inString = false\n let i = 0\n\n while (i < source.length) {\n const ch = source.charAt(i)\n\n if (inString) {\n if (ch === \"\\\\\" && i + 1 < source.length) {\n out += ch + source.charAt(i + 1)\n i += 2\n continue\n }\n if (ch === '\"') inString = false\n out += ch\n i++\n continue\n }\n\n if (ch === '\"') {\n inString = true\n out += ch\n i++\n continue\n }\n\n if (ch === \"/\" && source.charAt(i + 1) === \"/\") {\n while (i < source.length && source.charAt(i) !== \"\\n\") i++\n continue\n }\n\n out += ch\n i++\n }\n\n return out\n}\n\nfunction isDirectory(path: string): boolean {\n try {\n return statSync(path).isDirectory()\n } catch {\n return false\n }\n}\n\n/**\n * The default locations, in the order Prisma itself resolves them: a single\n * `prisma/schema.prisma`, then a multi-file `prisma/schema/` directory, then a\n * bare `schema.prisma`. A schema pointed at by `--schema` or prisma.config.ts\n * is not found here, which leaves the check disabled rather than wrong.\n */\nexport function findPrismaSchemas(root: string): string[] {\n const paths: string[] = []\n\n const single = join(root, \"prisma\", \"schema.prisma\")\n if (existsSync(single)) paths.push(single)\n\n const folder = join(root, \"prisma\", \"schema\")\n if (isDirectory(folder)) {\n for (const entry of readdirSync(folder).sort()) {\n if (entry.endsWith(\".prisma\")) paths.push(join(folder, entry))\n }\n }\n\n const bare = join(root, \"schema.prisma\")\n if (existsSync(bare)) paths.push(bare)\n\n return paths\n}\n\nfunction parseUrl(body: string, key: \"url\" | \"shadowDatabaseUrl\"): DatasourceUrl | null {\n const fromEnv = new RegExp(`\\\\b${key}\\\\s*=\\\\s*env\\\\(\\\\s*\"([^\"]*)\"\\\\s*\\\\)`).exec(body)\n if (fromEnv?.[1] !== undefined) return { kind: \"env\", name: fromEnv[1] }\n\n const literal = new RegExp(`\\\\b${key}\\\\s*=\\\\s*\"([^\"]*)\"`).exec(body)\n if (literal?.[1] !== undefined) return { kind: \"literal\", value: literal[1] }\n\n return null\n}\n\n/** Parses the first `datasource` block in a schema. Datasource blocks cannot nest, so brace matching is unnecessary. */\nexport function parseDatasource(source: string): Omit<PrismaDatasource, \"schemaPath\"> | null {\n const block = /datasource\\s+(\\w+)\\s*\\{([^}]*)\\}/.exec(stripComments(source))\n if (block === null) return null\n\n const name = block[1] ?? \"db\"\n const body = block[2] ?? \"\"\n const provider = /\\bprovider\\s*=\\s*\"([^\"]*)\"/.exec(body)\n\n return {\n name,\n provider: provider?.[1] ?? null,\n url: parseUrl(body, \"url\"),\n shadowUrl: parseUrl(body, \"shadowDatabaseUrl\"),\n }\n}\n\n/** The project's first Prisma datasource, or null when the project has no schema this can find. */\nexport function readPrismaDatasource(root: string): PrismaDatasource | null {\n for (const path of findPrismaSchemas(root)) {\n let source: string\n try {\n source = readFileSync(path, \"utf8\")\n } catch {\n continue\n }\n\n const parsed = parseDatasource(source)\n if (parsed !== null) return { ...parsed, schemaPath: relative(root, path) }\n }\n\n return null\n}\n\n/**\n * The schema path when a datasource exists but declares no\n * `shadowDatabaseUrl` at all — the one case {@link addShadowDatabaseUrl} can\n * fix — and null otherwise. A block that names some other variable, or\n * hardcodes a URL, is a deliberate choice this must not quietly overwrite.\n */\nexport function missingShadowDatabaseUrl(root: string): string | null {\n const datasource = readPrismaDatasource(root)\n if (datasource === null || datasource.shadowUrl !== null) return null\n return datasource.schemaPath\n}\n\n/** Re-pads `key = value` assignments to one column, the way `prisma format` lays a block out. */\nfunction alignAssignments(lines: string[]): string[] {\n const parsed = lines.map((line) => /^(\\s*)([A-Za-z_]\\w*)\\s*=\\s*(.*)$/.exec(line))\n const widest = parsed.reduce((max, match) => Math.max(max, match?.[2]?.length ?? 0), 0)\n\n return lines.map((line, index) => {\n const match = parsed[index]\n if (match === undefined || match === null) return line\n return `${match[1]}${(match[2] ?? \"\").padEnd(widest)} = ${match[3] ?? \"\"}`\n })\n}\n\n/**\n * Adds `shadowDatabaseUrl = env(\"SHADOW_DATABASE_URL\")` to the project's\n * datasource, immediately after `url` so the two read together, and returns\n * the schema path relative to the root.\n *\n * Only ever called once {@link shadowDatabaseUrlIsMissing} is true, and never\n * without asking first: unlike `.env`, a schema is source the developer wrote\n * and keeps in git.\n */\nexport function addShadowDatabaseUrl(root: string): string {\n const datasource = readPrismaDatasource(root)\n if (datasource === null) throw new CliError(\"No Prisma datasource found to add `shadowDatabaseUrl` to.\")\n\n const absolute = join(root, datasource.schemaPath)\n const source = readFileSync(absolute, \"utf8\")\n const lines = source.split(\"\\n\")\n\n // Located on the raw source rather than the comment-stripped copy the\n // parser uses, since the offsets have to line up with what gets written.\n const open = lines.findIndex((line) => new RegExp(`^\\\\s*datasource\\\\s+${datasource.name}\\\\s*\\\\{`).test(line))\n if (open === -1) throw new CliError(`Could not locate the \\`${datasource.name}\\` datasource in ${datasource.schemaPath}.`)\n\n const close = lines.findIndex((line, index) => index > open && /^\\s*\\}/.test(line))\n if (close === -1) throw new CliError(`\\`${datasource.schemaPath}\\` has an unterminated datasource block.`)\n\n const urlLine = lines.findIndex((line, index) => index > open && index < close && /^\\s*url\\s*=/.test(line))\n const insertAfter = urlLine === -1 ? open : urlLine\n const indent = /^(\\s*)/.exec(lines[insertAfter] ?? \"\")?.[1]\n const body = [\n ...lines.slice(open + 1, insertAfter + 1),\n `${urlLine === -1 ? \" \" : indent}shadowDatabaseUrl = env(\"${REQUIRED_SHADOW_URL_ENV}\")`,\n ...lines.slice(insertAfter + 1, close),\n ]\n\n const patched = [...lines.slice(0, open + 1), ...alignAssignments(body), ...lines.slice(close)]\n writeFileSync(absolute, patched.join(\"\\n\"))\n\n return datasource.schemaPath\n}\n\nfunction wrongUrlError(datasource: PrismaDatasource, url: DatasourceUrl): CliError {\n const problem =\n url.kind === \"literal\"\n ? `hardcodes \\`url = \"${url.value}\"\\``\n : `reads \\`env(\"${url.name}\")\\`, but Meridian sets \\`${REQUIRED_URL_ENV}\\``\n\n return new CliError(\n `\\`${datasource.schemaPath}\\` ${problem}, so this command would not touch the managed development database.`,\n {\n hint:\n `Change the \\`${datasource.name}\\` datasource to \\`url = env(\"${REQUIRED_URL_ENV}\")\\` ` +\n `with \\`provider = \"${REQUIRED_PROVIDER}\"\\`. Migrations generated against another ` +\n `database use dialect-specific SQL and have to be regenerated. ${BYPASS_HINT}`,\n },\n )\n}\n\nfunction wrongProviderError(datasource: PrismaDatasource, provider: string): CliError {\n return new CliError(\n `\\`${datasource.schemaPath}\\` sets \\`provider = \"${provider}\"\\`, but the managed development database is MySQL.`,\n {\n hint:\n `Change the \\`${datasource.name}\\` datasource to \\`provider = \"${REQUIRED_PROVIDER}\"\\` and regenerate any ` +\n `migrations generated for ${provider}, which use dialect-specific SQL. ${BYPASS_HINT}`,\n },\n )\n}\n\n/**\n * Throws when the project's Prisma datasource would ignore the managed\n * database. Stays silent for projects this cannot speak for: no schema, no\n * datasource block, or a `url` shape it does not model.\n */\nexport function assertManagedDatasource(root: string): void {\n const datasource = readPrismaDatasource(root)\n if (datasource === null || datasource.url === null) return\n\n if (datasource.url.kind !== \"env\" || datasource.url.name !== REQUIRED_URL_ENV) {\n throw wrongUrlError(datasource, datasource.url)\n }\n\n if (datasource.provider !== null && datasource.provider !== REQUIRED_PROVIDER) {\n throw wrongProviderError(datasource, datasource.provider)\n }\n}\n\n/**\n * Throws when the datasource has no usable `shadowDatabaseUrl`. Only\n * `prisma migrate dev` needs one, so this is deliberately separate from\n * {@link assertManagedDatasource}: `dev`, `db seed` and `db shell` work fine\n * without it and must not be blocked.\n */\nexport function assertShadowDatasource(root: string): void {\n const datasource = readPrismaDatasource(root)\n if (datasource === null) return\n\n const shadow = datasource.shadowUrl\n if (shadow !== null && shadow.kind === \"env\" && shadow.name === REQUIRED_SHADOW_URL_ENV) return\n\n const problem =\n shadow === null\n ? 'declares no `shadowDatabaseUrl`'\n : shadow.kind === \"literal\"\n ? `hardcodes \\`shadowDatabaseUrl = \"${shadow.value}\"\\``\n : `reads \\`env(\"${shadow.name}\")\\` for its shadow database, but Meridian sets \\`${REQUIRED_SHADOW_URL_ENV}\\``\n\n throw new CliError(`\\`${datasource.schemaPath}\\` ${problem}.`, {\n hint:\n `\\`prisma migrate dev\\` diffs your migrations in a throwaway shadow database, and your dev user cannot ` +\n `create one — so Meridian provisions it for you and exports \\`${REQUIRED_SHADOW_URL_ENV}\\`. Add ` +\n `\\`shadowDatabaseUrl = env(\"${REQUIRED_SHADOW_URL_ENV}\")\\` to the \\`${datasource.name}\\` datasource. ${BYPASS_HINT}`,\n })\n}\n\n/**\n * SQLite and Postgres quote identifiers with double quotes; MySQL uses\n * backticks and, without ANSI_QUOTES, reads `\"Session\"` as a string literal\n * rather than a table name. Anchoring to a DDL keyword keeps this from\n * matching a double quote inside a string literal, which is legal in any\n * dialect.\n */\nconst FOREIGN_DIALECT_DDL = /\\b(?:CREATE\\s+(?:UNIQUE\\s+)?(?:TABLE|INDEX)|ALTER\\s+TABLE|REFERENCES)\\s+\"/i\n\n/** Migration directories hold one `migration.sql` each, next to the schema. */\nfunction migrationSqlPaths(root: string): string[] {\n const schemas = findPrismaSchemas(root)\n const roots = new Set(schemas.map((schema) => join(dirname(schema), \"migrations\")))\n // A multi-file schema lives in prisma/schema/, but its migrations stay in prisma/.\n roots.add(join(root, \"prisma\", \"migrations\"))\n\n const paths: string[] = []\n for (const dir of roots) {\n if (!isDirectory(dir)) continue\n for (const entry of readdirSync(dir).sort()) {\n const sql = join(dir, entry, \"migration.sql\")\n if (existsSync(sql)) paths.push(sql)\n }\n }\n return paths\n}\n\n/**\n * The first migration in the history written for another engine, relative to\n * the project root, or null when the history looks fine.\n *\n * Reads the migration files rather than Prisma's output, which is streamed\n * straight to the terminal and never captured on the interactive path.\n */\nexport function findForeignDialectMigration(root: string): string | null {\n const offender = migrationSqlPaths(root).find((path) => {\n try {\n return FOREIGN_DIALECT_DDL.test(readFileSync(path, \"utf8\"))\n } catch {\n return false\n }\n })\n\n return offender === undefined ? null : relative(root, offender)\n}\n\n/**\n * Why the history cannot be replayed, and how to get out of it.\n *\n * The reset half matters as much as the delete half: a failed attempt leaves\n * a row in `_prisma_migrations` naming a directory that no longer exists once\n * the history is deleted, and Prisma refuses to generate anything until that\n * is cleared. Anyone told only to delete the folder hits a drift error next.\n */\nfunction foreignDialectExplanation(offender: string): string {\n return (\n `\\`${offender}\\` was generated for SQLite or Postgres — it quotes identifiers with double quotes, which ` +\n `MySQL reads as string literals. Migration SQL is dialect-specific and cannot be replayed against MySQL. ` +\n `If this history has only ever run locally, delete \\`prisma/migrations\\` and re-run to regenerate it for ` +\n `MySQL; run \\`meridian db reset\\` first if an earlier attempt already failed, since Prisma records that ` +\n `failure in \\`_prisma_migrations\\` and will not continue while it is there.`\n )\n}\n\n/**\n * Refuses to start a migration whose history cannot possibly apply.\n *\n * Every Shopify app template ships SQLite migrations, so this is the first\n * wall a project hits after pointing its datasource at the managed MySQL\n * database. Caught here rather than only after the fact, the developer skips\n * a doomed run that provisions a session, snapshots the database, fails on a\n * raw MySQL syntax error against a file nobody wrote by hand, and rolls back.\n */\nexport function assertMigrationDialect(root: string): void {\n const offender = findForeignDialectMigration(root)\n if (offender === null) return\n\n throw new CliError(`\\`${offender}\\` was written for a different database engine and cannot apply to MySQL.`, {\n hint: `${foreignDialectExplanation(offender)} Pass \\`--allow-foreign-migrations\\` to try anyway.`,\n })\n}\n\n/**\n * Explains a failure caused by a foreign-dialect history, or null when the\n * history looks fine and the failure was something else.\n *\n * Still worth running after the fact even though {@link assertMigrationDialect}\n * screens for this up front, since that check can be waived with\n * `--allow-foreign-migrations`.\n */\nexport function diagnoseMigrationFailure(root: string): string | null {\n const offender = findForeignDialectMigration(root)\n return offender === null ? null : foreignDialectExplanation(offender)\n}\n","/**\n * Downloads, caches and verifies the Cloud SQL Auth Proxy v2 binary.\n *\n * The proxy ships as a single static executable per platform/arch with no\n * installer, so we cache it once under `<meridianHome>/bin` and re-verify its\n * checksum on every run rather than trusting whatever happens to be on disk.\n */\n\nimport { createHash } from \"node:crypto\"\nimport { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport { CliError } from \"../errors.js\"\nimport { proxyBinDir } from \"../paths.js\"\n\n/** Pinned proxy version; override with MERIDIAN_PROXY_VERSION for a hotfix. */\nexport const PROXY_VERSION = \"2.24.1\"\n\n/** sha256 of every asset of PROXY_VERSION, from Google's published release notes. */\nexport const PROXY_CHECKSUMS: Readonly<Record<string, string>> = Object.freeze({\n \"cloud-sql-proxy.darwin.amd64\": \"67a38444d03fe77a8b11036f96fe5d2379640088bb6e338737fb48d97c58cf48\",\n \"cloud-sql-proxy.darwin.arm64\": \"fd374545705f2aa687d8e525a2efcbb9d356cc8af60d4dfa1a330cb59a7f9450\",\n \"cloud-sql-proxy.linux.386\": \"cf731f4becfb5a2de61f2998b2d660c5fb8f3067cbd3b86f5783ae9049c06f24\",\n \"cloud-sql-proxy.linux.amd64\": \"fae2766aac9d614a2bdef2f2a7778f3d054f3acd5ff07a81a9e300bd471512eb\",\n \"cloud-sql-proxy.linux.arm64\": \"da49fd73b0d33c0ab8e5dfc19dfb104cdd969ebd355eef8fd3b079c20a723c82\",\n \"cloud-sql-proxy.x64.exe\": \"01ec54c69dbb8118c0b181c33ff1469a5cdb2dddb49eb86b0b173f6c55dea0bc\",\n \"cloud-sql-proxy.x86.exe\": \"98c3b1897c80f2bc0b241b4452c18557a00cd86f89e4d7449c4ff1316e243c44\",\n})\n\nexport interface ProxyAsset {\n version: string\n /** e.g. \"cloud-sql-proxy.darwin.arm64\" */\n assetName: string\n downloadUrl: string\n /** Known sha256, or undefined when the version was overridden and we must fetch the release notes. */\n sha256?: string\n /** Cached file name, e.g. \"cloud-sql-proxy-2.24.1-darwin-arm64\" (+ \".exe\" on Windows). */\n fileName: string\n}\n\nconst ASSET_NAME_BY_PLATFORM_ARCH: Readonly<Record<string, string>> = Object.freeze({\n \"darwin:arm64\": \"cloud-sql-proxy.darwin.arm64\",\n \"darwin:x64\": \"cloud-sql-proxy.darwin.amd64\",\n \"linux:x64\": \"cloud-sql-proxy.linux.amd64\",\n \"linux:arm64\": \"cloud-sql-proxy.linux.arm64\",\n \"linux:ia32\": \"cloud-sql-proxy.linux.386\",\n \"win32:x64\": \"cloud-sql-proxy.x64.exe\",\n \"win32:ia32\": \"cloud-sql-proxy.x86.exe\",\n})\n\nfunction defaultVersion(): string {\n const override = process.env.MERIDIAN_PROXY_VERSION\n if (override !== undefined && override !== \"\") return override\n return PROXY_VERSION\n}\n\n/** Maps process.platform/process.arch to a published asset. Throws a CliError naming the platform when unsupported. */\nexport function resolveProxyAsset(options?: {\n platform?: NodeJS.Platform\n arch?: string\n version?: string\n}): ProxyAsset {\n const platform = options?.platform ?? process.platform\n const arch = options?.arch ?? process.arch\n const version = options?.version ?? defaultVersion()\n\n const assetName = ASSET_NAME_BY_PLATFORM_ARCH[`${platform}:${arch}`]\n if (assetName === undefined) {\n throw new CliError(`The Cloud SQL Auth Proxy has no published build for ${platform}/${arch}.`, {\n hint: \"Set MERIDIAN_PROXY_PATH to the path of a proxy binary you install yourself.\",\n })\n }\n\n const downloadUrl = `https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v${version}/${assetName}`\n const sha256Value = version === PROXY_VERSION ? PROXY_CHECKSUMS[assetName] : undefined\n const fileName = `cloud-sql-proxy-${version}-${platform}-${arch}${platform === \"win32\" ? \".exe\" : \"\"}`\n\n return {\n version,\n assetName,\n downloadUrl,\n ...(sha256Value !== undefined ? { sha256: sha256Value } : {}),\n fileName,\n }\n}\n\n/** sha256 hex of a buffer. */\nexport function sha256(data: Uint8Array): string {\n return createHash(\"sha256\").update(data).digest(\"hex\")\n}\n\nconst CHECKSUM_ROW_PATTERN = /\\[([^\\]]+)]\\([^)]*\\)\\s*\\|\\s*([0-9a-fA-F]{64})/g\n\n/** Pulls the `| [asset](url) | hash |` table out of a GitHub release body. */\nexport function parseChecksumTable(releaseBody: string): Record<string, string> {\n const table: Record<string, string> = {}\n for (const match of releaseBody.matchAll(CHECKSUM_ROW_PATTERN)) {\n const name = match[1]\n const hash = match[2]\n if (name !== undefined && hash !== undefined) table[name] = hash.toLowerCase()\n }\n return table\n}\n\nexport interface EnsureProxyOptions {\n version?: string\n /** Cache directory. Default proxyBinDir(). */\n dir?: string\n fetchImpl?: typeof fetch\n /** Progress in bytes; used for a spinner by the caller. */\n onProgress?: (received: number, total: number | undefined) => void\n /** Re-download even when cached. */\n force?: boolean\n}\n\nconst RELEASE_API_URL = \"https://api.github.com/repos/GoogleCloudPlatform/cloud-sql-proxy/releases/tags\"\n\n/**\n * Memoizes a looked-up (non-pinned-version) checksum for the life of the\n * process, so a cache-hit in ensureProxyBinary never re-hits the GitHub API\n * just to confirm a file it already verified moments (or a run) ago.\n */\nconst checksumCache = new Map<string, string>()\n\n/**\n * The known checksum for a pinned-version asset, or the one published for an\n * overridden version's GitHub release. Returns undefined (skip verification)\n * only when MERIDIAN_PROXY_SKIP_CHECKSUM=1 and no checksum could be found —\n * otherwise throws, because we must never install unverified bytes silently.\n */\nasync function resolveExpectedChecksum(asset: ProxyAsset, fetchImpl: typeof fetch): Promise<string | undefined> {\n if (asset.sha256 !== undefined) return asset.sha256\n\n const cacheKey = `${asset.version}:${asset.assetName}`\n const cached = checksumCache.get(cacheKey)\n if (cached !== undefined) return cached\n\n const skipAllowed = process.env.MERIDIAN_PROXY_SKIP_CHECKSUM === \"1\"\n const url = `${RELEASE_API_URL}/v${asset.version}`\n\n let response: Response\n try {\n response = await fetchImpl(url, { headers: { Accept: \"application/vnd.github+json\" } })\n } catch (error) {\n if (skipAllowed) return undefined\n throw new CliError(`Could not reach ${url} to look up the checksum for cloud-sql-proxy v${asset.version}.`, {\n hint: \"Check your network connection, or set MERIDIAN_PROXY_SKIP_CHECKSUM=1 to install without verifying the checksum, at your own risk.\",\n cause: error,\n })\n }\n\n if (!response.ok) {\n if (skipAllowed) return undefined\n throw new CliError(\n `Could not determine the sha256 checksum for cloud-sql-proxy v${asset.version} (GitHub release lookup for ${url} returned HTTP ${response.status}).`,\n {\n hint: \"Set MERIDIAN_PROXY_SKIP_CHECKSUM=1 to install without verifying the checksum, at your own risk.\",\n },\n )\n }\n\n const rawBody = await response.text()\n let releaseNotes = rawBody\n try {\n const parsed: unknown = JSON.parse(rawBody)\n if (typeof parsed === \"object\" && parsed !== null && \"body\" in parsed && typeof parsed.body === \"string\") {\n releaseNotes = parsed.body\n }\n } catch {\n // Not JSON — treat the raw text as the release body (tests may inject the table directly).\n }\n\n const checksum = parseChecksumTable(releaseNotes)[asset.assetName]\n if (checksum !== undefined) {\n checksumCache.set(cacheKey, checksum)\n return checksum\n }\n\n if (skipAllowed) return undefined\n throw new CliError(\n `Could not find a published sha256 checksum for ${asset.assetName} in the cloud-sql-proxy v${asset.version} release notes.`,\n { hint: \"Set MERIDIAN_PROXY_SKIP_CHECKSUM=1 to install without verifying the checksum, at your own risk.\" },\n )\n}\n\nfunction parseContentLength(header: string | null): number | undefined {\n if (header === null) return undefined\n const value = Number(header)\n return Number.isFinite(value) ? value : undefined\n}\n\nasync function readResponseBody(\n response: Response,\n onProgress: ((received: number, total: number | undefined) => void) | undefined,\n): Promise<Buffer> {\n const total = parseContentLength(response.headers.get(\"content-length\"))\n\n if (response.body === null) {\n const buffer = Buffer.from(await response.arrayBuffer())\n onProgress?.(buffer.byteLength, total)\n return buffer\n }\n\n const reader = response.body.getReader()\n const chunks: Uint8Array[] = []\n let received = 0\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n if (value !== undefined) {\n chunks.push(value)\n received += value.byteLength\n onProgress?.(received, total)\n }\n }\n return Buffer.concat(chunks)\n}\n\n/**\n * Absolute path to a verified, executable proxy binary, downloading it into the\n * cache on first use. `MERIDIAN_PROXY_PATH` short-circuits everything (bring\n * your own binary; used in CI and by `apt`-installed proxies).\n */\nexport async function ensureProxyBinary(options: EnsureProxyOptions = {}): Promise<string> {\n const overridePath = process.env.MERIDIAN_PROXY_PATH\n if (overridePath !== undefined && overridePath !== \"\") {\n if (!existsSync(overridePath)) {\n throw new CliError(`MERIDIAN_PROXY_PATH is set to ${overridePath}, but that file does not exist.`, {\n hint: \"Fix or unset MERIDIAN_PROXY_PATH.\",\n })\n }\n return overridePath\n }\n\n const asset = resolveProxyAsset(options.version !== undefined ? { version: options.version } : {})\n const dir = options.dir ?? proxyBinDir()\n const fetchImpl = options.fetchImpl ?? fetch\n const targetPath = join(dir, asset.fileName)\n\n mkdirSync(dir, { recursive: true })\n\n if (!options.force && existsSync(targetPath)) {\n const cached = readFileSync(targetPath)\n const expected = await resolveExpectedChecksum(asset, fetchImpl)\n if (expected === undefined || sha256(cached) === expected) return targetPath\n rmSync(targetPath, { force: true })\n }\n\n const response = await fetchImpl(asset.downloadUrl)\n if (!response.ok) {\n throw new CliError(\n `Failed to download the Cloud SQL Auth Proxy v${asset.version} from ${asset.downloadUrl} (HTTP ${response.status}).`,\n {\n hint: \"Check your network connection (and any corporate proxy settings), or set MERIDIAN_PROXY_PATH to a proxy binary you install yourself.\",\n },\n )\n }\n\n const buffer = await readResponseBody(response, options.onProgress)\n\n const expected = await resolveExpectedChecksum(asset, fetchImpl)\n const actual = sha256(buffer)\n if (expected !== undefined && actual !== expected) {\n throw new CliError(\n `Checksum mismatch for ${asset.assetName}: expected ${expected.slice(0, 12)}..., got ${actual.slice(0, 12)}....`,\n {\n hint: \"This can happen after a corrupted download or an untrusted network. Try again; if it persists, report this.\",\n },\n )\n }\n\n const tmpPath = join(dir, `.${asset.fileName}.${process.pid}.tmp`)\n writeFileSync(tmpPath, buffer)\n chmodSync(tmpPath, 0o755)\n renameSync(tmpPath, targetPath)\n\n return targetPath\n}\n","/**\n * Runs the Cloud SQL Auth Proxy v2 as a supervised child process.\n *\n * The proxy reads its access token once at startup, so it cannot pick up a\n * refreshed token on its own — the only way to hand it a new token is to\n * restart the process on the same port. That drops any in-flight MySQL\n * connections, which is an acceptable trade-off for a local dev database.\n * Every failure mode (a slow/failed readiness probe, a refresh that fails, a\n * crash) is reported through `onEvent` instead of throwing asynchronously, so\n * a long-running `meridian dev` session never dies from an unhandled\n * rejection — only the initial `startProxy()` call can reject.\n */\n\nimport type { ChildProcess } from \"node:child_process\"\nimport { spawn } from \"node:child_process\"\nimport { createConnection } from \"node:net\"\nimport { CliError, describeError } from \"../errors.js\"\n\nexport interface ProxyToken {\n access_token: string\n expires_at?: string\n}\n\nexport type ProxyEvent =\n | { type: \"starting\"; attempt: number }\n | { type: \"ready\"; port: number }\n | { type: \"log\"; line: string }\n | { type: \"token-refreshed\"; expiresAt?: string }\n | { type: \"restarting\"; reason: \"token-refresh\" | \"crash\" }\n | { type: \"exit\"; code: number | null; signal: NodeJS.Signals | null }\n | { type: \"error\"; message: string }\n\nexport interface StartProxyOptions {\n binaryPath: string\n instanceConnectionName: string\n token: ProxyToken\n port: number\n /** Default \"127.0.0.1\" */\n host?: string\n /** Called when the current token is close to expiry; must return a fresh token. */\n refreshToken?: () => Promise<ProxyToken>\n /** Refresh this long before expiry. Default 5 minutes. */\n refreshSkewMs?: number\n /** Fallback lifetime when the API omits expires_at. Default 55 minutes. */\n assumedLifetimeMs?: number\n /** Structured events for the caller's logger/spinner. */\n onEvent?: (event: ProxyEvent) => void\n /** How long to wait for readiness. Default 30s. */\n readyTimeoutMs?: number\n /** Base environment for the proxy child. Default `process.env`. */\n env?: NodeJS.ProcessEnv\n spawnImpl?: typeof spawn\n /** Injectable readiness probe; default is a TCP connect to host:port. */\n probeImpl?: (host: string, port: number) => Promise<boolean>\n /** Keep timers injectable for tests. */\n setTimeoutImpl?: typeof setTimeout\n}\n\nexport interface ManagedProxy {\n readonly host: string\n readonly port: number\n readonly instanceConnectionName: string\n /** True between a successful start and stop(). */\n readonly running: boolean\n /** Force a token refresh + restart now (used by tests and by `migrate`). */\n refresh(): Promise<void>\n /** Stops the token timer and terminates the child (SIGTERM → SIGKILL). Idempotent. */\n stop(): Promise<void>\n}\n\nconst PROBE_INTERVAL_MS = 150\nconst KILL_GRACE_MS = 2_000\nconst CRASH_BACKOFFS_MS = [200, 1_000, 3_000]\nconst MAX_CRASH_RESTARTS = CRASH_BACKOFFS_MS.length\nconst REFRESH_RETRY_BACKOFFS_MS = [30_000, 60_000, 120_000]\nconst MIN_REFRESH_DELAY_MS = 60_000\nconst LOG_RING_SIZE = 20\nconst STDERR_TAIL_LINES = 10\n\n/**\n * The exact argv the proxy is spawned with — exported so it can be asserted in\n * tests and printed in verbose mode. The access token is deliberately absent:\n * see {@link buildProxyEnv}.\n */\nexport function buildProxyArgs(input: { instanceConnectionName: string; host: string; port: number }): string[] {\n return [\"--address\", input.host, \"--port\", String(input.port), input.instanceConnectionName]\n}\n\n/**\n * The proxy accepts every flag as a `CSQL_PROXY_`-prefixed environment\n * variable, so the short-lived GCP access token goes in the environment rather\n * than in argv, where `ps` would show it to every other user on the machine.\n * Explicit flags still win over the environment, so `--address`/`--port` are\n * unaffected by anything the developer happens to have exported.\n */\nexport function buildProxyEnv(accessToken: string, base: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {\n return { ...base, CSQL_PROXY_TOKEN: accessToken }\n}\n\nfunction defaultProbe(host: string, port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = createConnection({ host, port })\n const finish = (ok: boolean) => {\n socket.removeAllListeners()\n socket.destroy()\n resolve(ok)\n }\n socket.once(\"connect\", () => finish(true))\n socket.once(\"error\", () => finish(false))\n socket.setTimeout(1_000, () => finish(false))\n })\n}\n\nfunction computeRefreshDelayMs(token: ProxyToken, refreshSkewMs: number, assumedLifetimeMs: number): number {\n let expiresAtMs: number | undefined\n if (token.expires_at !== undefined) {\n const parsed = new Date(token.expires_at).getTime()\n if (!Number.isNaN(parsed)) expiresAtMs = parsed\n }\n const effectiveExpiryMs = expiresAtMs ?? Date.now() + assumedLifetimeMs\n return Math.max(effectiveExpiryMs - Date.now() - refreshSkewMs, MIN_REFRESH_DELAY_MS)\n}\n\nfunction buildStartupFailureError(\n code: number | null,\n signal: NodeJS.Signals | null,\n lastLines: string[],\n): CliError {\n const tail = lastLines.slice(-STDERR_TAIL_LINES).join(\"\\n\")\n const lower = tail.toLowerCase()\n\n let hint = \"Run `meridian dev` again; if this keeps happening, check the instance connection name and your network.\"\n if (lower.includes(\"iam\") || lower.includes(\"permission\") || lower.includes(\"forbidden\")) {\n hint =\n \"The Meridian API's service account may be missing roles/cloudsql.client on the dev Cloud SQL instance. Contact Meridian support.\"\n } else if (lower.includes(\"invalid token\") || lower.includes(\"401\") || lower.includes(\"unauthorized\")) {\n hint = \"The access token appears to have expired. Retry `meridian dev` to mint a fresh one.\"\n } else if (lower.includes(\"address already in use\")) {\n hint = \"Another process is already listening on that port. Free it up, or retry with a different port.\"\n }\n\n const summary = `The Cloud SQL Auth Proxy exited before it was ready (code ${code ?? \"null\"}, signal ${signal ?? \"null\"}).`\n return new CliError(tail === \"\" ? summary : `${summary}\\n${tail}`, { hint })\n}\n\nfunction waitForReady(\n child: ChildProcess,\n probeImpl: (host: string, port: number) => Promise<boolean>,\n host: string,\n port: number,\n timeoutMs: number,\n setTimeoutImpl: typeof setTimeout,\n getLastLines: () => string[],\n): Promise<void> {\n return new Promise((resolve, reject) => {\n let settled = false\n let pollTimer: ReturnType<typeof setTimeoutImpl> | undefined\n let timeoutTimer: ReturnType<typeof setTimeoutImpl> | undefined\n\n const cleanup = () => {\n if (pollTimer !== undefined) clearTimeout(pollTimer)\n if (timeoutTimer !== undefined) clearTimeout(timeoutTimer)\n child.off(\"exit\", onExit)\n }\n\n function onExit(code: number | null, signal: NodeJS.Signals | null) {\n if (settled) return\n settled = true\n cleanup()\n reject(buildStartupFailureError(code, signal, getLastLines()))\n }\n\n function poll() {\n if (settled) return\n probeImpl(host, port)\n .then((ok) => {\n if (settled) return\n if (ok) {\n settled = true\n cleanup()\n resolve()\n } else {\n pollTimer = setTimeoutImpl(poll, PROBE_INTERVAL_MS)\n }\n })\n .catch(() => {\n if (!settled) pollTimer = setTimeoutImpl(poll, PROBE_INTERVAL_MS)\n })\n }\n\n child.on(\"exit\", onExit)\n timeoutTimer = setTimeoutImpl(() => {\n if (settled) return\n settled = true\n cleanup()\n reject(\n new CliError(`Timed out after ${timeoutMs}ms waiting for the Cloud SQL Auth Proxy to accept connections.`, {\n hint: \"The instance may be slow to reach, or readyTimeoutMs may need to be raised.\",\n }),\n )\n }, timeoutMs)\n poll()\n })\n}\n\n/** Spawns the proxy and resolves once it accepts TCP connections on host:port. */\nexport async function startProxy(options: StartProxyOptions): Promise<ManagedProxy> {\n const host = options.host ?? \"127.0.0.1\"\n const spawnImpl = options.spawnImpl ?? spawn\n const probeImpl = options.probeImpl ?? defaultProbe\n const setTimeoutImpl = options.setTimeoutImpl ?? setTimeout\n const refreshSkewMs = options.refreshSkewMs ?? 5 * 60_000\n const assumedLifetimeMs = options.assumedLifetimeMs ?? 55 * 60_000\n const readyTimeoutMs = options.readyTimeoutMs ?? 30_000\n const emit = (event: ProxyEvent) => options.onEvent?.(event)\n\n let stopped = false\n let running = false\n let expectingExit = false\n let currentToken = options.token\n let child: ChildProcess | undefined\n let refreshTimer: ReturnType<typeof setTimeoutImpl> | undefined\n let crashTimer: ReturnType<typeof setTimeoutImpl> | undefined\n let refreshBackoffIndex = 0\n // A lifetime budget, not a per-crash-episode one: once a ManagedProxy has\n // auto-restarted 3 times after a crash, any further crash goes straight to\n // a terminal error rather than resetting the count, so a truly flaky\n // binary/instance fails loudly instead of looping forever.\n let crashRestartsRemaining = MAX_CRASH_RESTARTS\n let attemptCounter = 0\n let cleanupFns: Array<() => void> = []\n const knownTokens = new Set<string>()\n const logRing: string[] = []\n\n function trackToken(token: ProxyToken) {\n if (token.access_token !== \"\") knownTokens.add(token.access_token)\n }\n\n function redact(text: string): string {\n let result = text\n for (const token of knownTokens) result = result.split(token).join(\"<redacted>\")\n return result\n }\n\n function pushLog(line: string) {\n const safeLine = redact(line)\n logRing.push(safeLine)\n if (logRing.length > LOG_RING_SIZE) logRing.shift()\n emit({ type: \"log\", line: safeLine })\n }\n\n function wireOutput(c: ChildProcess) {\n for (const stream of [c.stdout, c.stderr]) {\n if (stream === null) continue\n let buffer = \"\"\n const onData = (chunk: Buffer | string) => {\n buffer += chunk.toString()\n const lines = buffer.split(\"\\n\")\n buffer = lines.pop() ?? \"\"\n for (const line of lines) pushLog(line)\n }\n stream.on(\"data\", onData)\n cleanupFns.push(() => stream.off(\"data\", onData))\n }\n }\n\n function wireExit(c: ChildProcess) {\n c.once(\"exit\", (code, signal) => {\n if (child !== c) return\n const wasRunning = running\n const wasExpected = expectingExit\n running = false\n expectingExit = false\n emit({ type: \"exit\", code, signal })\n if (stopped || wasExpected || !wasRunning) return\n void handleCrash()\n })\n }\n\n async function spawnChild(): Promise<void> {\n attemptCounter += 1\n emit({ type: \"starting\", attempt: attemptCounter })\n const args = buildProxyArgs({\n instanceConnectionName: options.instanceConnectionName,\n host,\n port: options.port,\n })\n const c = spawnImpl(options.binaryPath, args, {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: buildProxyEnv(currentToken.access_token, options.env),\n })\n child = c\n wireOutput(c)\n wireExit(c)\n try {\n await waitForReady(c, probeImpl, host, options.port, readyTimeoutMs, setTimeoutImpl, () => logRing.slice())\n } catch (error) {\n // A child that never became ready is still running (readiness timeout) —\n // leaving it behind would orphan a proxy holding the port.\n expectingExit = true\n await killChild(c)\n if (child === c) child = undefined\n throw error\n }\n emit({ type: \"ready\", port: options.port })\n }\n\n function killChild(c: ChildProcess): Promise<void> {\n if (c.exitCode !== null || c.signalCode !== null) return Promise.resolve()\n return new Promise((resolve) => {\n let settled = false\n let killTimer: ReturnType<typeof setTimeoutImpl> | undefined\n const onExit = () => {\n if (settled) return\n settled = true\n if (killTimer !== undefined) clearTimeout(killTimer)\n resolve()\n }\n c.once(\"exit\", onExit)\n c.kill(\"SIGTERM\")\n killTimer = setTimeoutImpl(() => {\n if (!settled) c.kill(\"SIGKILL\")\n }, KILL_GRACE_MS)\n })\n }\n\n function scheduleRefresh(token: ProxyToken) {\n if (stopped || options.refreshToken === undefined) return\n if (refreshTimer !== undefined) clearTimeout(refreshTimer)\n const delayMs = computeRefreshDelayMs(token, refreshSkewMs, assumedLifetimeMs)\n refreshTimer = setTimeoutImpl(() => {\n refreshTimer = undefined\n void handleRefreshFire()\n }, delayMs)\n }\n\n function scheduleRefreshRetry() {\n if (stopped) return\n const delayMs = REFRESH_RETRY_BACKOFFS_MS[Math.min(refreshBackoffIndex, REFRESH_RETRY_BACKOFFS_MS.length - 1)] ?? 120_000\n refreshBackoffIndex += 1\n if (refreshTimer !== undefined) clearTimeout(refreshTimer)\n refreshTimer = setTimeoutImpl(() => {\n refreshTimer = undefined\n void handleRefreshFire()\n }, delayMs)\n }\n\n async function handleRefreshFire(): Promise<void> {\n if (stopped || options.refreshToken === undefined) return\n\n let newToken: ProxyToken\n try {\n newToken = await options.refreshToken()\n } catch (error) {\n emit({ type: \"error\", message: redact(`Token refresh failed: ${describeError(error)}`) })\n scheduleRefreshRetry()\n return\n }\n if (stopped) return\n\n trackToken(newToken)\n currentToken = newToken\n expectingExit = true\n emit({ type: \"restarting\", reason: \"token-refresh\" })\n\n try {\n const previous = child\n if (previous !== undefined) await killChild(previous)\n await spawnChild()\n } catch (error) {\n emit({ type: \"error\", message: redact(`Restart after token refresh failed: ${describeError(error)}`) })\n scheduleRefreshRetry()\n return\n }\n\n running = true\n refreshBackoffIndex = 0\n emit({ type: \"token-refreshed\", ...(newToken.expires_at !== undefined ? { expiresAt: newToken.expires_at } : {}) })\n scheduleRefresh(newToken)\n }\n\n async function handleCrash(): Promise<void> {\n if (stopped) return\n if (crashRestartsRemaining <= 0) {\n const tail = logRing.slice(-STDERR_TAIL_LINES).join(\"\\n\")\n emit({\n type: \"error\",\n message: `The Cloud SQL Auth Proxy crashed repeatedly and could not be restarted.${tail === \"\" ? \"\" : `\\n${tail}`}`,\n })\n return\n }\n\n const attemptIndex = MAX_CRASH_RESTARTS - crashRestartsRemaining\n const delayMs = CRASH_BACKOFFS_MS[attemptIndex] ?? (CRASH_BACKOFFS_MS[CRASH_BACKOFFS_MS.length - 1] ?? 3_000)\n crashRestartsRemaining -= 1\n emit({ type: \"restarting\", reason: \"crash\" })\n\n crashTimer = setTimeoutImpl(() => {\n crashTimer = undefined\n if (stopped) return\n spawnChild()\n .then(() => {\n running = true\n })\n .catch((error: unknown) => {\n emit({ type: \"error\", message: redact(describeError(error)) })\n void handleCrash()\n })\n }, delayMs)\n }\n\n async function refresh(): Promise<void> {\n if (stopped) return\n if (options.refreshToken === undefined) {\n throw new CliError(\"Cannot refresh the Cloud SQL Auth Proxy token: no refreshToken() was configured.\")\n }\n if (refreshTimer !== undefined) {\n clearTimeout(refreshTimer)\n refreshTimer = undefined\n }\n refreshBackoffIndex = 0\n await handleRefreshFire()\n }\n\n async function stop(): Promise<void> {\n if (stopped) return\n stopped = true\n\n if (refreshTimer !== undefined) clearTimeout(refreshTimer)\n refreshTimer = undefined\n if (crashTimer !== undefined) clearTimeout(crashTimer)\n crashTimer = undefined\n\n for (const cleanup of cleanupFns) cleanup()\n cleanupFns = []\n\n const current = child\n if (current !== undefined) {\n expectingExit = true\n await killChild(current)\n }\n running = false\n child = undefined\n }\n\n trackToken(currentToken)\n await spawnChild()\n running = true\n scheduleRefresh(currentToken)\n\n return {\n host,\n port: options.port,\n instanceConnectionName: options.instanceConnectionName,\n get running() {\n return running\n },\n refresh,\n stop,\n }\n}\n","/**\n * One shutdown path for every command that owns a background process (the\n * Cloud SQL Auth Proxy, the app's dev server, ...). `meridian dev` in\n * particular needs Ctrl-C to tear everything down cleanly, but also needs a\n * *second* Ctrl-C — the developer mashing the key because nothing seems to be\n * happening — to force an immediate exit rather than hang forever.\n */\n\nconst SIGNALS: readonly NodeJS.Signals[] = [\"SIGINT\", \"SIGTERM\", \"SIGHUP\"]\n\n/** 128 + signal number, the POSIX convention `$?` reports for a signal-terminated process. */\nconst SIGNAL_EXIT_CODES: Readonly<Partial<Record<NodeJS.Signals, number>>> = {\n SIGHUP: 129,\n SIGINT: 130,\n SIGTERM: 143,\n}\n\n/** Forced-exit code for a second signal received while handlers are still running. */\nconst FORCE_EXIT_CODE = 130\n\n/** Default ceiling on how long a single handler may take before it is abandoned. */\nconst DEFAULT_HANDLER_TIMEOUT_MS = 8_000\n\nexport type ShutdownHandler = (reason: ShutdownReason) => void | Promise<void>\n\nexport interface ShutdownReason {\n signal?: NodeJS.Signals\n error?: unknown\n}\n\nlet handlers: ShutdownHandler[] = []\nlet signalListeners: Map<NodeJS.Signals, () => void> | undefined\nlet isShuttingDown = false\nlet hasRun = false\nlet exitImpl: (code: number) => void = (code) => process.exit(code)\n\nfunction attachListeners(): void {\n if (signalListeners !== undefined) return\n const listeners = new Map<NodeJS.Signals, () => void>()\n for (const signal of SIGNALS) {\n const listener = (): void => {\n void handleSignal(signal)\n }\n process.on(signal, listener)\n listeners.set(signal, listener)\n }\n signalListeners = listeners\n}\n\nfunction detachListeners(): void {\n if (signalListeners === undefined) return\n for (const [signal, listener] of signalListeners) {\n process.off(signal, listener)\n }\n signalListeners = undefined\n}\n\nasync function handleSignal(signal: NodeJS.Signals): Promise<void> {\n if (isShuttingDown) {\n exitImpl(FORCE_EXIT_CODE)\n return\n }\n isShuttingDown = true\n await runShutdownHandlers({ signal })\n process.exitCode = exitCodeForSignal(signal)\n}\n\n/**\n * Runs `handler(reason)` with a hard timeout so one stuck handler (a hung\n * child process, a network call that never settles) can never keep the\n * terminal open forever — after the timeout we simply move on.\n */\nfunction runHandlerWithTimeout(\n handler: ShutdownHandler,\n reason: ShutdownReason,\n timeoutMs: number,\n): Promise<void> {\n return new Promise((resolve) => {\n let settled = false\n const timer = setTimeout(() => {\n if (settled) return\n settled = true\n resolve()\n }, timeoutMs)\n timer.unref?.()\n\n Promise.resolve()\n .then(() => handler(reason))\n .catch(() => {\n // A failing handler must never block the rest of shutdown.\n })\n .then(() => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n resolve()\n })\n })\n}\n\n/**\n * Registers a cleanup handler for SIGINT/SIGTERM/SIGHUP. Handlers run once,\n * in reverse registration order (LIFO — the most recently acquired resource\n * is released first), each guarded so one failure does not block the rest.\n * Returns an unregister function.\n */\nexport function onShutdown(handler: ShutdownHandler): () => void {\n handlers.push(handler)\n attachListeners()\n\n let unregistered = false\n return () => {\n if (unregistered) return\n unregistered = true\n const index = handlers.indexOf(handler)\n if (index !== -1) handlers.splice(index, 1)\n if (handlers.length === 0) detachListeners()\n }\n}\n\n/** Runs every handler now (used by commands that finish normally). Idempotent. */\nexport async function runShutdownHandlers(\n reason: ShutdownReason = {},\n timeoutMs: number = DEFAULT_HANDLER_TIMEOUT_MS,\n): Promise<void> {\n if (hasRun) return\n hasRun = true\n\n const toRun = [...handlers].reverse()\n for (const handler of toRun) {\n await runHandlerWithTimeout(handler, reason, timeoutMs)\n }\n}\n\n/** Test helper: clears handlers and removes the process listeners. */\nexport function resetShutdown(): void {\n detachListeners()\n handlers = []\n isShuttingDown = false\n hasRun = false\n exitImpl = (code) => process.exit(code)\n}\n\n/** Exit code convention for a signal-triggered exit (128 + signal number). */\nexport function exitCodeForSignal(signal: NodeJS.Signals): number {\n return SIGNAL_EXIT_CODES[signal] ?? 128\n}\n\n/** Test seam: replaces the forced-exit implementation so tests never kill the test runner. */\nexport function __setExitImpl(fn: (code: number) => void): void {\n exitImpl = fn\n}\n","/**\n * The shared \"make the dev database reachable\" flow behind `meridian dev`,\n * `meridian migrate`, `meridian db seed` and `meridian db shell`: ensure the\n * database is provisioned, fetch fresh credentials and a proxy token, spawn\n * the Cloud SQL Auth Proxy, wait for MySQL to answer, and patch\n * `DATABASE_URL` into the project's `.env`. Every collaborator is injectable\n * (see {@link SessionDeps}) so the whole flow can be exercised offline.\n */\n\nimport type { ApiClient } from \"./api.js\"\nimport type { DevCredentials, DevDatabase, Id, ProxyToken as ApiProxyToken } from \"./api-types.js\"\nimport { createApiClient } from \"./client.js\"\nimport { workingDirectory } from \"./context.js\"\nimport type { DbConnectionInfo } from \"./db/connection.js\"\nimport { connectionInfoFromCredentials, waitForDatabase } from \"./db/connection.js\"\nimport type { EnvPatch, PatchEnvResult } from \"./env-file.js\"\nimport { buildDatabaseUrl, patchEnvFile, redactDatabaseUrl } from \"./env-file.js\"\nimport { CliError, describeError, isCliError } from \"./errors.js\"\nimport { debug, detail, step, success, warn, withSpinner } from \"./output.js\"\nimport type { Spinner } from \"./output.js\"\nimport { envFilePath } from \"./paths.js\"\nimport { findFreePort } from \"./port.js\"\nimport { assertManagedDatasource } from \"./prisma.js\"\nimport type { FindFreePortOptions } from \"./port.js\"\nimport { ensureProxyBinary } from \"./proxy/binary.js\"\nimport type { EnsureProxyOptions } from \"./proxy/binary.js\"\nimport { startProxy } from \"./proxy/proxy.js\"\nimport type { ManagedProxy, ProxyEvent, ProxyToken as ProxyProxyToken } from \"./proxy/proxy.js\"\nimport type { LinkedProject } from \"./project.js\"\nimport { requireProject } from \"./project.js\"\nimport { onShutdown } from \"./signals.js\"\n\n/** Everything a `startDevSession()` caller gets back to run its own command logic. */\nexport interface DevSessionInfo {\n project: LinkedProject\n devDatabase: DevDatabase\n credentials: DevCredentials\n connection: DbConnectionInfo\n databaseUrl: string\n /** Undefined when the API did not report a shadow database for this dev database. */\n shadowDatabaseUrl?: string\n proxy: ManagedProxy\n /**\n * process.env plus DATABASE_URL (and SHADOW_DATABASE_URL, and\n * {@link DEV_DATABASE_ID_ENV}), for handing to child processes.\n */\n env: NodeJS.ProcessEnv\n /** Result of patching .env, or undefined when patching was skipped. */\n envPatch?: PatchEnvResult\n /** Tears down the proxy and unregisters the shutdown handler. Idempotent. */\n stop(): Promise<void>\n}\n\nexport interface StartSessionOptions {\n /** Defaults to createApiClient(). */\n client?: ApiClient\n /** Defaults to requireProject(workingDirectory()). */\n project?: LinkedProject\n /** Patch DATABASE_URL into <root>/.env. Default true. */\n patchEnv?: boolean\n /** .env file name (relative to the project root). Default \".env\". */\n envFile?: string\n /** Preferred local port for the proxy. */\n port?: number\n /** Keep refreshing the proxy token in the background. Default true. */\n refreshToken?: boolean\n /** Register a SIGINT/SIGTERM handler that stops the proxy. Default true. */\n handleSignals?: boolean\n /** Wait for MySQL to answer before returning. Default true. */\n waitForDb?: boolean\n /** Overrides for tests. */\n deps?: Partial<SessionDeps>\n}\n\n/** Every side-effecting collaborator, injectable so the whole flow is testable offline. */\nexport interface SessionDeps {\n ensureProxyBinary: typeof import(\"./proxy/binary.js\").ensureProxyBinary\n startProxy: typeof import(\"./proxy/proxy.js\").startProxy\n findFreePort: typeof import(\"./port.js\").findFreePort\n patchEnvFile: typeof import(\"./env-file.js\").patchEnvFile\n waitForDatabase: typeof import(\"./db/connection.js\").waitForDatabase\n sleep: (ms: number) => Promise<void>\n now: () => number\n}\n\nfunction defaultSleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction resolveDeps(overrides?: Partial<SessionDeps>): SessionDeps {\n return {\n ensureProxyBinary,\n startProxy,\n findFreePort,\n patchEnvFile,\n waitForDatabase,\n sleep: defaultSleep,\n now: () => Date.now(),\n ...overrides,\n }\n}\n\nconst DEFAULT_POLL_TIMEOUT_MS = 5 * 60_000\nconst DEFAULT_POLL_INTERVAL_MS = 2_000\nconst NOT_FOUND_GRACE_MS = 30_000\nconst DEFAULT_PORT_START = 3307\n\n/**\n * The provisioned dev database's id, exported to every child of a managed\n * session (see {@link DevSessionInfo.env}) so the Meridian SDK can send it as\n * `devDatabaseId` on the app's identify call — that is what lets the API bill a\n * shop install against this developer's dev database while the app runs\n * locally. Only ever set alongside a live session, so a plain `npm run dev`\n * (no proxy, no credentials) never claims a dev database.\n *\n * Sibling of `DEV_GUARD_ENV` in `./run.js`, which every child of `meridian\n * dev` also carries.\n */\nexport const DEV_DATABASE_ID_ENV = \"MERIDIAN_DEV_DATABASE_ID\"\n\nexport interface EnsureDevDatabaseReadyOptions {\n timeoutMs?: number\n intervalMs?: number\n sleep?: (ms: number) => Promise<void>\n now?: () => number\n onStatus?: (status: string, elapsedMs: number) => void\n}\n\n/**\n * The API reports why provisioning failed in the dev database's\n * `error_message` (populated only while `status` is `error`), so it is quoted\n * verbatim rather than making the developer go and look it up.\n */\nfunction provisioningFailedError(devDatabase: DevDatabase): CliError {\n const reason = devDatabase.error_message\n const detail = typeof reason === \"string\" && reason.trim() !== \"\" ? ` ${reason.trim()}` : \"\"\n return new CliError(`Provisioning the development database failed.${detail}`, {\n hint: \"Check the Meridian dashboard for details, or contact support if this keeps happening.\",\n })\n}\n\nfunction provisioningTimeoutError(): CliError {\n return new CliError(\"Timed out waiting for the development database to be provisioned.\", {\n hint: \"Try `meridian dev` again in a few minutes, and check the Meridian dashboard for its status.\",\n })\n}\n\nfunction provisioningNotFoundError(): CliError {\n return new CliError(\"The Meridian API never finished creating the development database.\", {\n hint: \"Try `meridian dev` again; if this keeps happening, contact Meridian support.\",\n })\n}\n\nasync function pollDevDatabase(\n client: ApiClient,\n appId: Id,\n options: EnsureDevDatabaseReadyOptions,\n spinner: Spinner,\n): Promise<DevDatabase> {\n const timeoutMs = options.timeoutMs ?? DEFAULT_POLL_TIMEOUT_MS\n const intervalMs = options.intervalMs ?? DEFAULT_POLL_INTERVAL_MS\n const sleep = options.sleep ?? defaultSleep\n const now = options.now ?? Date.now\n\n const start = now()\n const report = (status: string): void => {\n const elapsedMs = now() - start\n spinner.update(`Provisioning the development database... (${status}, ${Math.round(elapsedMs / 1000)}s)`)\n options.onStatus?.(status, elapsedMs)\n }\n\n let current = await client.ensureDevDatabase(appId)\n report(current.status)\n if (current.status === \"ready\") return current\n if (current.status === \"error\") throw provisioningFailedError(current)\n\n let notFoundSince: number | undefined\n\n for (;;) {\n if (now() - start >= timeoutMs) throw provisioningTimeoutError()\n await sleep(intervalMs)\n\n const fetched = await client.getDevDatabase(appId)\n if (fetched === null) {\n if (notFoundSince === undefined) notFoundSince = now()\n if (now() - notFoundSince >= NOT_FOUND_GRACE_MS) throw provisioningNotFoundError()\n report(\"provisioning\")\n continue\n }\n\n notFoundSince = undefined\n current = fetched\n report(current.status)\n if (current.status === \"ready\") return current\n if (current.status === \"error\") throw provisioningFailedError(current)\n }\n}\n\n/**\n * POSTs the ensure endpoint and polls GET until `ready`, with a spinner.\n * Exported separately because `db reset` wants it without the proxy.\n */\nexport async function ensureDevDatabaseReady(\n client: ApiClient,\n appId: Id,\n options: EnsureDevDatabaseReadyOptions = {},\n): Promise<DevDatabase> {\n return withSpinner(\n \"Provisioning the development database...\",\n (spinner) => pollDevDatabase(client, appId, options, spinner),\n { success: (db) => `Development database \"${db.database}\" is ready.` },\n )\n}\n\n/**\n * `ApiProxyToken`'s zod-inferred `expires_at?: string | null` is not\n * assignable to the proxy module's stricter `expires_at?: string` under\n * `exactOptionalPropertyTypes` — this drops the key instead of ever setting\n * it to `null`/`undefined`, which is also how the proxy asks to fall back to\n * its assumed token lifetime.\n */\nfunction toProxyToken(token: ApiProxyToken): ProxyProxyToken {\n return {\n access_token: token.access_token,\n ...(typeof token.expires_at === \"string\" ? { expires_at: token.expires_at } : {}),\n }\n}\n\nfunction formatMb(bytes: number): string {\n return (bytes / (1024 * 1024)).toFixed(1)\n}\n\n/** First value that is a non-blank string, treating null/undefined/\"\" alike. */\nfunction firstNonEmpty(...values: Array<string | null | undefined>): string | undefined {\n for (const value of values) {\n if (typeof value === \"string\" && value.trim() !== \"\") return value\n }\n return undefined\n}\n\n/**\n * {@link DEV_DATABASE_ID_ENV}'s value. `idSchema` allows a number or a string,\n * so the id is stringified; a blank one is treated as absent rather than\n * exported as an empty variable the SDK would then send as `devDatabaseId`.\n */\nfunction devDatabaseIdValue(devDatabase: DevDatabase): string | undefined {\n return firstNonEmpty(String(devDatabase.id))\n}\n\nfunction logEnvPatch(result: PatchEnvResult, databaseUrl: string, wroteShadow: boolean): void {\n const redacted = redactDatabaseUrl(databaseUrl)\n const names = wroteShadow ? \"DATABASE_URL and SHADOW_DATABASE_URL\" : \"DATABASE_URL\"\n if (result.created) {\n success(`Created ${result.path} with DATABASE_URL=${redacted}`)\n } else if (result.changed) {\n success(`Updated ${names} in ${result.path} (${redacted})`)\n } else {\n debug(`${result.path} already has the correct ${names}.`)\n }\n if (result.backedUp) detail(`Backed up the previous file to ${result.path}.backup`)\n}\n\n/**\n * Maps proxy lifecycle events onto `output.ts`. Never prints a token or\n * anything derived from one — the proxy module itself pre-redacts `log`\n * lines and error messages, but the mapping here is deliberately narrow too.\n */\nfunction handleProxyEvent(event: ProxyEvent): void {\n switch (event.type) {\n case \"starting\":\n debug(`Starting the Cloud SQL Auth Proxy (attempt ${event.attempt}).`)\n return\n case \"ready\":\n debug(`Cloud SQL Auth Proxy listening on port ${event.port}.`)\n return\n case \"log\":\n debug(event.line)\n return\n case \"token-refreshed\":\n step(\"Refreshed the Cloud SQL Auth Proxy token.\")\n return\n case \"restarting\":\n if (event.reason === \"crash\") warn(\"The Cloud SQL Auth Proxy crashed; restarting it.\")\n else debug(\"Restarting the Cloud SQL Auth Proxy with a refreshed token...\")\n return\n case \"exit\":\n debug(`Cloud SQL Auth Proxy exited (code ${event.code ?? \"null\"}, signal ${event.signal ?? \"null\"}).`)\n return\n case \"error\":\n warn(`Cloud SQL Auth Proxy error: ${event.message} Restart \\`meridian dev\\` if the database becomes unreachable.`)\n return\n }\n}\n\n/** Runs the whole \"make the dev database reachable\" flow, logging each step. */\nexport async function startDevSession(options: StartSessionOptions = {}): Promise<DevSessionInfo> {\n const deps = resolveDeps(options.deps)\n let proxy: ManagedProxy | undefined\n\n try {\n const project = options.project ?? requireProject(workingDirectory())\n // Before anything is provisioned, rotated or downloaded: a schema that\n // ignores DATABASE_URL makes every step below pointless.\n if (project.config.skip_datasource_check !== true) assertManagedDatasource(project.root)\n\n const client = options.client ?? createApiClient()\n const appId = project.config.app_id\n\n const devDatabase = await ensureDevDatabaseReady(client, appId, { sleep: deps.sleep, now: deps.now })\n\n const credentials = await withSpinner(\n \"Fetching database credentials...\",\n () => client.issueCredentials(appId),\n {\n success: (creds) =>\n `Fetched credentials for database \"${creds.database}\"${\n typeof creds.expires_at === \"string\" ? ` (expire ${creds.expires_at})` : \"\"\n }.`,\n },\n )\n\n const proxyToken = await withSpinner(\n \"Requesting a Cloud SQL Auth Proxy token...\",\n () => client.issueProxyToken(appId),\n { success: \"Issued a Cloud SQL Auth Proxy token.\" },\n )\n\n const binaryPath = await withSpinner(\n \"Preparing the Cloud SQL Auth Proxy...\",\n (spinner) => {\n const ensureOptions: EnsureProxyOptions = {\n onProgress: (received, total) => {\n spinner.update(\n total !== undefined\n ? `Downloading the Cloud SQL Auth Proxy... (${formatMb(received)}/${formatMb(total)} MB)`\n : `Downloading the Cloud SQL Auth Proxy... (${formatMb(received)} MB)`,\n )\n },\n }\n return deps.ensureProxyBinary(ensureOptions)\n },\n { success: \"Cloud SQL Auth Proxy is ready.\" },\n )\n\n const findPortOptions: FindFreePortOptions = { start: DEFAULT_PORT_START }\n if (options.port !== undefined) findPortOptions.preferred = options.port\n const port = await deps.findFreePort(findPortOptions)\n if (options.port !== undefined && port !== options.port) {\n throw new CliError(`Port ${options.port} is already in use.`, {\n hint: \"Pick a different port with --port, or free up that port and try again.\",\n })\n }\n\n // Both sources are nullable columns on the API side, so an empty string or\n // an explicit null has to be treated the same as a missing field.\n const instanceConnectionName = firstNonEmpty(\n credentials.instance_connection_name,\n proxyToken.instance_connection_name,\n devDatabase.instance_connection_name,\n )\n if (instanceConnectionName === undefined) {\n throw new CliError(\"The Meridian API did not return a Cloud SQL instance connection name.\", {\n hint: \"Try again, or contact Meridian support if this persists.\",\n })\n }\n\n proxy = await withSpinner(\n `Starting the Cloud SQL Auth Proxy on 127.0.0.1:${port}...`,\n () =>\n deps.startProxy({\n binaryPath,\n instanceConnectionName,\n token: toProxyToken(proxyToken),\n port,\n ...(options.refreshToken !== false\n ? { refreshToken: async () => toProxyToken(await client.issueProxyToken(appId)) }\n : {}),\n onEvent: handleProxyEvent,\n }),\n { success: `Cloud SQL Auth Proxy listening on 127.0.0.1:${port}.` },\n )\n\n const connection = connectionInfoFromCredentials(credentials, { host: proxy.host, port: proxy.port })\n\n if (options.waitForDb !== false) {\n await withSpinner(\n \"Waiting for MySQL to accept connections...\",\n () => deps.waitForDatabase(connection),\n { success: \"MySQL is accepting connections.\" },\n )\n }\n\n const databaseUrl = buildDatabaseUrl({\n username: credentials.username,\n password: credentials.password,\n port: proxy.port,\n database: credentials.database,\n })\n\n // `prisma migrate dev` replays the migration history into a shadow\n // database and diffs it against the schema. It creates one itself unless\n // handed a URL, and a dev user scoped to a single schema cannot — hence\n // the second database the API provisions per developer.\n const shadowDatabase = firstNonEmpty(credentials.shadow_database, devDatabase.shadow_database)\n const shadowDatabaseUrl =\n shadowDatabase === undefined\n ? undefined\n : buildDatabaseUrl({\n username: credentials.username,\n password: credentials.password,\n port: proxy.port,\n database: shadowDatabase,\n })\n\n // Exported into the child environment only (below), never written to\n // `.env`: it belongs to this session, and a stale one left behind in a\n // committed-adjacent file would tag installs long after the session ended.\n const devDatabaseId = devDatabaseIdValue(devDatabase)\n\n let envPatch: PatchEnvResult | undefined\n if (options.patchEnv !== false) {\n const envPath = envFilePath(project.root, options.envFile)\n const patch: EnvPatch = {\n DATABASE_URL: databaseUrl,\n ...(shadowDatabaseUrl !== undefined ? { SHADOW_DATABASE_URL: shadowDatabaseUrl } : {}),\n }\n envPatch = deps.patchEnvFile(envPath, patch, { backup: true })\n logEnvPatch(envPatch, databaseUrl, shadowDatabaseUrl !== undefined)\n }\n\n let unregisterShutdown: (() => void) | undefined\n const stop = async (): Promise<void> => {\n if (unregisterShutdown !== undefined) {\n const unregister = unregisterShutdown\n unregisterShutdown = undefined\n unregister()\n }\n if (proxy !== undefined) await proxy.stop()\n }\n\n if (options.handleSignals !== false) {\n unregisterShutdown = onShutdown(() => stop())\n }\n\n return {\n project,\n devDatabase,\n credentials,\n connection,\n databaseUrl,\n ...(shadowDatabaseUrl !== undefined ? { shadowDatabaseUrl } : {}),\n proxy,\n env: {\n ...process.env,\n DATABASE_URL: databaseUrl,\n ...(shadowDatabaseUrl !== undefined ? { SHADOW_DATABASE_URL: shadowDatabaseUrl } : {}),\n ...(devDatabaseId !== undefined ? { [DEV_DATABASE_ID_ENV]: devDatabaseId } : {}),\n },\n ...(envPatch !== undefined ? { envPatch } : {}),\n stop,\n }\n } catch (error) {\n if (proxy !== undefined) {\n await proxy.stop().catch(() => {})\n }\n if (isCliError(error)) throw error\n throw new CliError(`Failed to start the Meridian development session: ${describeError(error)}`, { cause: error })\n }\n}\n","/**\n * The built-in fallback SQL client for `meridian db shell`, used whenever the\n * `mysql` binary isn't on PATH (or `--repl` forces it): a minimal line-buffered\n * REPL over mysql2, plus the single-statement runner `-e/--execute` shares\n * with it, and the `findExecutable` PATH probe that decides which path to take.\n *\n * mysql2's `connection.query()` resolves `[rows, fields]` for a `SELECT` and\n * `[ResultSetHeader, undefined]` for a write; `createSqlConnection` (in\n * `lib/db/connection.ts`) passes that straight through, so both\n * `interpretQueryResult` and the fakes tests inject speak that same tuple\n * shape.\n */\n\nimport { accessSync, constants as fsConstants } from \"node:fs\"\nimport { delimiter, join } from \"node:path\"\nimport { createInterface } from \"node:readline\"\nimport type { DbConnectionInfo, SqlConnection } from \"../lib/db/connection.js\"\nimport { toDatabaseError } from \"../lib/db/connection.js\"\nimport { error, hint, printJson, printLine } from \"../lib/output.js\"\n\nfunction candidateNames(name: string): string[] {\n if (process.platform !== \"win32\") return [name]\n if (/\\.[^./\\\\]+$/.test(name)) return [name]\n const pathExt = process.env.PATHEXT ?? \".EXE;.CMD;.BAT;.COM\"\n const extensions = pathExt.split(\";\").filter((ext) => ext !== \"\")\n return [name, ...extensions.map((ext) => `${name}${ext.toLowerCase()}`)]\n}\n\n/**\n * Default `DbDeps.findExecutable`: scans `PATH` the way a shell would,\n * without invoking one (so it never risks running an arbitrary shell\n * builtin). On Windows, also tries each `PATHEXT` extension when `name` has\n * none of its own.\n */\nexport function findExecutable(name: string): string | null {\n const pathValue = process.env.PATH ?? \"\"\n const dirs = pathValue.split(delimiter).filter((dir) => dir !== \"\")\n const candidates = candidateNames(name)\n\n for (const dir of dirs) {\n for (const candidate of candidates) {\n const fullPath = join(dir, candidate)\n try {\n accessSync(fullPath, fsConstants.X_OK)\n return fullPath\n } catch {\n continue\n }\n }\n }\n return null\n}\n\nexport interface QueryRowsOutcome {\n kind: \"rows\"\n rows: Array<Record<string, unknown>>\n}\n\nexport interface QueryWriteOutcome {\n kind: \"write\"\n affectedRows: number\n}\n\nexport type QueryOutcome = QueryRowsOutcome | QueryWriteOutcome\n\nfunction isResultSetHeaderLike(value: unknown): value is { affectedRows: number } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"affectedRows\" in value &&\n typeof (value as { affectedRows: unknown }).affectedRows === \"number\"\n )\n}\n\n/** Interprets a raw `connection.query()` result as either row data or a write's affected-row count. */\nexport function interpretQueryResult(raw: unknown): QueryOutcome {\n const first = Array.isArray(raw) ? raw[0] : raw\n if (Array.isArray(first)) {\n return { kind: \"rows\", rows: first as Array<Record<string, unknown>> }\n }\n if (isResultSetHeaderLike(first)) {\n return { kind: \"write\", affectedRows: first.affectedRows }\n }\n return { kind: \"write\", affectedRows: 0 }\n}\n\nconst MAX_CELL_WIDTH = 60\n\nfunction cellText(value: unknown): string {\n if (value === null || value === undefined) return \"NULL\"\n if (value instanceof Date) return value.toISOString()\n if (Buffer.isBuffer(value)) return value.toString(\"hex\")\n return String(value)\n}\n\nfunction truncateCell(text: string): string {\n return text.length > MAX_CELL_WIDTH ? `${text.slice(0, MAX_CELL_WIDTH - 1)}…` : text\n}\n\n/** Renders rows as a simple aligned text table: header, separator, rows, then a \"(N rows)\" footer. */\nexport function formatTable(rows: Array<Record<string, unknown>>): string {\n if (rows.length === 0) return \"(0 rows)\"\n\n const columns = Object.keys(rows[0] ?? {})\n const cells = rows.map((row) => columns.map((column) => truncateCell(cellText(row[column]))))\n const widths = columns.map((column, i) => Math.max(column.length, ...cells.map((row) => row[i]?.length ?? 0)))\n\n const renderRow = (values: string[]): string => values.map((value, i) => value.padEnd(widths[i] ?? 0)).join(\" \")\n\n const lines = [\n renderRow(columns),\n renderRow(widths.map((width) => \"-\".repeat(width))),\n ...cells.map((row) => renderRow(row)),\n `(${rows.length} row${rows.length === 1 ? \"\" : \"s\"})`,\n ]\n return lines.join(\"\\n\")\n}\n\nasync function printQueryOutcome(raw: unknown, json: boolean): Promise<void> {\n const outcome = interpretQueryResult(raw)\n if (outcome.kind === \"rows\") {\n if (json) printJson(outcome.rows)\n else printLine(formatTable(outcome.rows))\n return\n }\n if (json) printJson({ affected_rows: outcome.affectedRows })\n else printLine(`Query OK, ${outcome.affectedRows} row${outcome.affectedRows === 1 ? \"\" : \"s\"} affected.`)\n}\n\n/** Runs one statement, printing its result or a redacted, actionable error. Never throws. */\nasync function runStatement(\n connection: SqlConnection,\n connectionInfo: DbConnectionInfo,\n sql: string,\n json = false,\n): Promise<boolean> {\n try {\n const raw = await connection.query(sql)\n await printQueryOutcome(raw, json)\n return true\n } catch (err) {\n const dbError = toDatabaseError(err, connectionInfo)\n error(dbError.message)\n if (dbError.hint !== undefined) hint(dbError.hint)\n return false\n }\n}\n\n/** Runs a single statement for `db shell -e/--execute` and returns the process exit code (0, or 1 on a query error). */\nexport async function executeStatement(\n connection: SqlConnection,\n connectionInfo: DbConnectionInfo,\n sql: string,\n options: { json?: boolean } = {},\n): Promise<number> {\n const ok = await runStatement(connection, connectionInfo, sql, options.json === true)\n return ok ? 0 : 1\n}\n\nexport interface RunReplOptions {\n connection: SqlConnection\n connectionInfo: DbConnectionInfo\n input: NodeJS.ReadableStream\n output: NodeJS.WritableStream\n}\n\nconst EXIT_COMMANDS = new Set([\"exit\", \"quit\", \"\\\\q\"])\n\n/**\n * Minimal line-buffered SQL REPL: accumulates input until a line ends with\n * `;` (so multi-line statements work), then runs it through `connection`.\n * `exit`/`quit`/`\\q` and EOF end the session; Ctrl-C clears the current\n * buffer instead of killing the process, unless the buffer is already empty.\n * Kept as a plain function over injected `input`/`output` streams so tests\n * can drive it without a real TTY.\n */\nexport function runRepl(options: RunReplOptions): Promise<number> {\n const { connection, connectionInfo, input, output } = options\n const rl = createInterface({ input, output, prompt: `meridian(${connectionInfo.database})> ` })\n\n let buffer = \"\"\n let settled = false\n\n return new Promise<number>((resolve) => {\n const finish = (code: number): void => {\n if (settled) return\n settled = true\n rl.close()\n resolve(code)\n }\n\n rl.on(\"line\", (line) => {\n const trimmed = line.trim()\n if (buffer === \"\" && EXIT_COMMANDS.has(trimmed.toLowerCase())) {\n finish(0)\n return\n }\n\n buffer = buffer === \"\" ? line : `${buffer}\\n${line}`\n if (!trimmed.endsWith(\";\")) {\n if (!settled) rl.prompt()\n return\n }\n\n const statement = buffer\n buffer = \"\"\n void runStatement(connection, connectionInfo, statement).then(() => {\n if (!settled) rl.prompt()\n })\n })\n\n rl.on(\"SIGINT\", () => {\n if (buffer !== \"\") {\n buffer = \"\"\n output.write(\"\\n\")\n if (!settled) rl.prompt()\n } else {\n finish(0)\n }\n })\n\n rl.once(\"close\", () => finish(0))\n\n rl.prompt()\n })\n}\n","/**\n * `meridian dev` — the flagship command. `startDevSession()` (in\n * `../lib/session.js`) already does the heavy lifting (provision, credentials,\n * proxy token, proxy binary, spawn the Cloud SQL Auth Proxy, patch `.env`);\n * this command's job is narrower: work out what the app's own dev command is,\n * run it with `DATABASE_URL` pointed at the local proxy, and make sure the\n * proxy and the app are always torn down together, in the right order.\n */\n\nimport type { Command } from \"commander\"\nimport { isJsonOutput, workingDirectory } from \"../lib/context.js\"\nimport { CliError } from \"../lib/errors.js\"\nimport { redactDatabaseUrl } from \"../lib/env-file.js\"\nimport { parsePortOption } from \"../lib/options.js\"\nimport { keyValues, log, printJson, step, style } from \"../lib/output.js\"\nimport type { LinkedProject } from \"../lib/project.js\"\nimport { requireProject } from \"../lib/project.js\"\nimport { assertNotSelfInvoking, isInsideDevSession, parseCommandString, readPackageScript, startProcess } from \"../lib/run.js\"\nimport type { DevSessionInfo, StartSessionOptions } from \"../lib/session.js\"\nimport { startDevSession } from \"../lib/session.js\"\nimport { exitCodeForSignal, onShutdown } from \"../lib/signals.js\"\n\n/** Every side-effecting collaborator `runDev` calls, injectable so tests never touch the network, a real proxy, or a real child process. */\nexport interface DevDeps {\n startDevSession: typeof startDevSession\n startProcess: typeof startProcess\n readPackageScript: typeof readPackageScript\n requireProject: typeof requireProject\n}\n\nexport interface DevOptions {\n /** Preferred local port for the Cloud SQL Auth Proxy. */\n port?: number\n /** .env file to patch, relative to the project root. Default \".env\". */\n envFile?: string\n /** `--`-passthrough argv, verbatim: command[0] plus the rest as args. Wins over `dev_command` and the default. */\n command?: string[]\n /** `--no-env`: don't touch any .env file; the summary/JSON still prints DATABASE_URL for manual use. */\n noEnv?: boolean\n deps?: Partial<DevDeps>\n}\n\nfunction defaultDeps(): DevDeps {\n return { startDevSession, startProcess, readPackageScript, requireProject }\n}\n\nconst RECURSION_HINT =\n \"Set `dev_command` in `.meridian/project.json` to the underlying command (e.g. `next dev`), \" +\n \"or run `meridian dev -- next dev` to bypass the script entirely.\"\n\n/** The `dev` script would call back into this command, so nothing has started yet. */\nfunction selfInvokingScriptError(): CliError {\n return new CliError('This project\\'s \"dev\" script runs `meridian dev`, which would start it again in a loop.', {\n hint: RECURSION_HINT,\n })\n}\n\n/** We are already a child of a `meridian dev` session, so a second proxy would be pointless. */\nfunction nestedSessionError(): CliError {\n return new CliError(\"`meridian dev` is already running in this process tree.\", {\n hint: `Use the dev server that session started, or stop it first. ${RECURSION_HINT}`,\n })\n}\n\n/** Reuses `assertNotSelfInvoking`'s tokenizing logic to detect a `dev` script that calls back into `meridian dev`. */\nfunction scriptReentersMeridianDev(script: string): boolean {\n try {\n assertNotSelfInvoking(script)\n return false\n } catch {\n return true\n }\n}\n\ninterface ResolvedDevCommand {\n command: string\n args: string[]\n /** Human-readable form, used in log lines only. */\n display: string\n}\n\nfunction resolvePassthroughCommand(argv: string[]): ResolvedDevCommand {\n const [command, ...args] = argv\n // Guarded by the `argv.length > 0` check at the call site.\n return { command: command as string, args, display: argv.join(\" \") }\n}\n\nfunction resolveConfiguredCommand(devCommand: string): ResolvedDevCommand {\n assertNotSelfInvoking(devCommand)\n const { command, args } = parseCommandString(devCommand)\n return { command, args, display: devCommand }\n}\n\nfunction noDevScriptError(): CliError {\n return new CliError('This project has no \"dev\" script.', {\n hint: \"Run `meridian dev -- <your command>`, or set `dev_command` in `.meridian/project.json`.\",\n })\n}\n\nfunction resolveDefaultCommand(deps: DevDeps, root: string): ResolvedDevCommand {\n const script = deps.readPackageScript(root, \"dev\")\n if (script === null) throw noDevScriptError()\n if (scriptReentersMeridianDev(script)) throw selfInvokingScriptError()\n\n const display = \"npm run dev\"\n assertNotSelfInvoking(display)\n return { command: \"npm\", args: [\"run\", \"dev\"], display }\n}\n\n/** Precedence: `--`-passthrough > `dev_command` > `npm run dev`. */\nfunction resolveDevCommand(deps: DevDeps, project: LinkedProject, passthrough: string[] | undefined): ResolvedDevCommand {\n if (passthrough !== undefined && passthrough.length > 0) return resolvePassthroughCommand(passthrough)\n if (project.config.dev_command !== undefined) return resolveConfiguredCommand(project.config.dev_command)\n return resolveDefaultCommand(deps, project.root)\n}\n\nfunction appLabel(project: LinkedProject): string {\n return project.config.app_name ?? String(project.config.app_id)\n}\n\nfunction printDevSummary(session: DevSessionInfo, noEnv: boolean): void {\n const envEntry = noEnv\n ? \"not touched (--no-env)\"\n : session.envPatch !== undefined\n ? session.envPatch.path\n : \"unchanged\"\n\n const entries: Array<[string, string]> = [\n [\"App\", appLabel(session.project)],\n [\"Database\", session.devDatabase.database],\n [\"Proxy\", `127.0.0.1:${session.proxy.port}`],\n [\"Env file\", envEntry],\n [\"DATABASE_URL\", redactDatabaseUrl(session.databaseUrl)],\n ]\n if (typeof session.credentials.expires_at === \"string\") {\n entries.push([\"Credentials expire\", session.credentials.expires_at])\n }\n\n log()\n keyValues(entries)\n log()\n}\n\n/** `--json` payload for a long-running command: printed once, before the child starts. Never carries a real password or proxy token. */\nfunction buildDevJsonPayload(session: DevSessionInfo): Record<string, unknown> {\n return {\n app: appLabel(session.project),\n database: session.devDatabase.database,\n proxy: { host: session.proxy.host, port: session.proxy.port },\n database_url: redactDatabaseUrl(session.databaseUrl),\n env_file: session.envPatch?.path ?? null,\n credentials_expire_at: session.credentials.expires_at ?? null,\n }\n}\n\n/**\n * Resolves the app's dev command, brings up the managed database session, and\n * runs the command until it exits (or the process is signalled). Resolves\n * with the exit code to use for the whole `meridian dev` invocation.\n */\nexport async function runDev(options: DevOptions = {}): Promise<number> {\n const deps: DevDeps = { ...defaultDeps(), ...options.deps }\n\n if (isInsideDevSession()) throw nestedSessionError()\n\n const project = deps.requireProject(workingDirectory())\n const resolved = resolveDevCommand(deps, project, options.command)\n const json = isJsonOutput()\n\n const sessionOptions: StartSessionOptions = {\n project,\n patchEnv: options.noEnv !== true,\n ...(options.port !== undefined ? { port: options.port } : {}),\n ...(options.envFile !== undefined ? { envFile: options.envFile } : {}),\n }\n const session = await deps.startDevSession(sessionOptions)\n\n let unregisterShutdown: (() => void) | undefined\n try {\n if (json) {\n printJson(buildDevJsonPayload(session))\n } else {\n printDevSummary(session, options.noEnv === true)\n step(`Starting ${resolved.display}...`)\n }\n\n const child = deps.startProcess(resolved.command, resolved.args, {\n cwd: project.root,\n env: session.env,\n inherit: true,\n })\n\n // Registered after the session's own shutdown handler, so on a signal it\n // runs first (handlers run LIFO): the app gets a chance to close its DB\n // connections before the proxy underneath it disappears.\n unregisterShutdown = onShutdown(async () => {\n await child.stop()\n await session.stop()\n })\n\n const result = await child.exited\n unregisterShutdown()\n unregisterShutdown = undefined\n await session.stop()\n\n if (result.signal !== null) return exitCodeForSignal(result.signal)\n if (result.code !== 0) log(style.dim(`${resolved.display} exited with code ${result.code}.`))\n return result.code\n } catch (error) {\n unregisterShutdown?.()\n await session.stop().catch(() => {})\n throw error\n }\n}\n\nexport function registerDevCommand(program: Command): void {\n program\n .command(\"dev\")\n .description(\"Run the managed dev database proxy and your app's dev server together.\")\n .option(\"--port <port>\", \"preferred local port for the Cloud SQL Auth Proxy\")\n .option(\"--env-file <file>\", \"the .env file to patch, relative to the project root (default .env)\")\n .option(\"--no-env\", \"don't touch any .env file; just print the DATABASE_URL for manual use\")\n .argument(\"[command...]\", \"run this instead of the app's dev script, e.g. `meridian dev -- next dev`\")\n .passThroughOptions()\n .action(async (command: string[], opts: { port?: string; envFile?: string; env?: boolean }) => {\n const port = parsePortOption(opts.port)\n const code = await runDev({\n ...(command.length > 0 ? { command } : {}),\n ...(port !== undefined ? { port } : {}),\n ...(opts.envFile !== undefined ? { envFile: opts.envFile } : {}),\n ...(opts.env === false ? { noEnv: true } : {}),\n })\n process.exitCode = code\n })\n}\n","/**\n * `meridian link` — picks an organization and app and writes\n * `<project>/.meridian/project.json` so `meridian dev` knows which managed\n * database to provision/reach.\n */\n\nimport { existsSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport type { Command } from \"commander\"\nimport type { AppSummary, Org } from \"../lib/api-types.js\"\nimport { createApiClient } from \"../lib/client.js\"\nimport { isJsonOutput, workingDirectory } from \"../lib/context.js\"\nimport { CliError } from \"../lib/errors.js\"\nimport { hint, keyValues, log, printJson, style, success } from \"../lib/output.js\"\nimport type { Choice } from \"../lib/prompts.js\"\nimport { confirmAction, selectOne } from \"../lib/prompts.js\"\nimport type { ProjectConfig } from \"../lib/project.js\"\nimport { readProject, resolveProjectRoot, writeProject } from \"../lib/project.js\"\n\nexport interface LinkDeps {\n createClient: typeof createApiClient\n /** Injectable for tests; never invokes real inquirer. */\n confirmImpl?: typeof import(\"@inquirer/prompts\").confirm\n /** Injectable for tests; never invokes real inquirer. */\n selectImpl?: typeof import(\"@inquirer/prompts\").select\n}\n\nexport interface LinkOptions {\n /** Organization id, name, or slug. */\n org?: string\n /** App id, name, or slug. */\n app?: string\n /** Stored as `dev_command`; overrides the default `npm run dev` in `meridian dev`. */\n devCommand?: string\n /** Skip both the \"no package.json\" and \"already linked\" confirmations. */\n force?: boolean\n deps?: Partial<LinkDeps>\n}\n\nfunction defaultDeps(): LinkDeps {\n return { createClient: createApiClient }\n}\n\nfunction formatOrg(org: Org): string {\n return `${org.name} (${org.slug})`\n}\n\nfunction formatApp(app: AppSummary): string {\n return `${app.name} (${app.slug})`\n}\n\n/**\n * Resolves a raw `--org`/`--app`/env-var answer against id, name, or slug so\n * `selectOne` (which otherwise only matches its `value`/`name`) can find the\n * right choice. Falls through to the raw string, unmatched, so `selectOne`\n * still produces its normal \"not a valid choice\" error listing the options.\n */\nfunction resolveChoiceAnswer<T>(choices: Array<Choice<T>>, raw: string, keysOf: (value: T) => string[]): string {\n const target = raw.trim().toLowerCase()\n const match = choices.find((choice) => keysOf(choice.value).some((key) => key.toLowerCase() === target))\n return match !== undefined ? match.name : raw\n}\n\n/** Runs the link logic; `options.deps` lets tests inject a fake API client. */\nexport async function runLink(options: LinkOptions = {}): Promise<void> {\n const deps = { ...defaultDeps(), ...options.deps }\n const json = isJsonOutput()\n\n const root = resolveProjectRoot(workingDirectory()) ?? workingDirectory()\n\n if (!existsSync(join(root, \"package.json\"))) {\n log(`No package.json found in ${style.path(root)}.`)\n const proceed = await confirmAction({\n message: \"Link this directory to a Meridian app anyway?\",\n flag: \"--force\",\n ...(options.force === true ? { assumeYes: true } : {}),\n ...(deps.confirmImpl !== undefined ? { promptImpl: deps.confirmImpl } : {}),\n })\n if (!proceed) throw new CliError(\"Aborted.\")\n }\n\n const existing = readProject(root)\n if (existing !== null) {\n log(\"This directory is already linked:\")\n keyValues([\n [\"App\", existing.config.app_name ?? String(existing.config.app_id)],\n [\"Org\", String(existing.config.org_id)],\n ])\n const relink = await confirmAction({\n message: \"Re-link this project?\",\n flag: \"--force\",\n ...(options.force === true ? { assumeYes: true } : {}),\n ...(deps.confirmImpl !== undefined ? { promptImpl: deps.confirmImpl } : {}),\n })\n if (!relink) throw new CliError(\"Aborted.\")\n }\n\n const client = deps.createClient({})\n const me = await client.getMe()\n const orgs = me.orgs\n\n if (orgs.length === 0) {\n throw new CliError(\"Your Meridian account has no organizations yet.\", {\n hint: \"Create one in the Meridian dashboard, then run `meridian link` again.\",\n })\n }\n\n const orgChoices: Array<Choice<Org>> = orgs.map((org) => ({ value: org, name: formatOrg(org) }))\n const orgCandidate = options.org ?? process.env.MERIDIAN_ORG\n const orgAnswer =\n orgCandidate !== undefined\n ? resolveChoiceAnswer(orgChoices, orgCandidate, (org) => [String(org.id), org.name, org.slug])\n : undefined\n\n const org = await selectOne({\n message: \"Select an organization\",\n choices: orgChoices,\n envVar: \"MERIDIAN_ORG\",\n flag: \"--org\",\n ...(orgAnswer !== undefined ? { answer: orgAnswer } : {}),\n ...(deps.selectImpl !== undefined ? { promptImpl: deps.selectImpl } : {}),\n })\n log(`Organization: ${style.bold(formatOrg(org))}`)\n\n const apps = await client.listApps(org.id)\n if (apps.length === 0) {\n throw new CliError(`Organization \"${org.name}\" has no apps yet.`, {\n hint: \"Create an app in the Meridian dashboard, then run `meridian link` again.\",\n })\n }\n\n const appChoices: Array<Choice<AppSummary>> = apps.map((app) => ({ value: app, name: formatApp(app) }))\n const appCandidate = options.app ?? process.env.MERIDIAN_APP\n const appAnswer =\n appCandidate !== undefined\n ? resolveChoiceAnswer(appChoices, appCandidate, (app) => [String(app.id), app.name, app.slug])\n : undefined\n\n const app = await selectOne({\n message: \"Select an app\",\n choices: appChoices,\n envVar: \"MERIDIAN_APP\",\n flag: \"--app\",\n ...(appAnswer !== undefined ? { answer: appAnswer } : {}),\n ...(deps.selectImpl !== undefined ? { promptImpl: deps.selectImpl } : {}),\n })\n log(`App: ${style.bold(formatApp(app))}`)\n\n const config: ProjectConfig = {\n org_id: org.id,\n app_id: app.id,\n app_name: app.name,\n ...(options.devCommand !== undefined ? { dev_command: options.devCommand } : {}),\n }\n writeProject(root, config)\n\n if (json) {\n printJson({ ...config, root })\n return\n }\n\n success(`Linked ${style.path(root)} to ${app.name}.`)\n keyValues([\n [\"Org\", formatOrg(org)],\n [\"App\", formatApp(app)],\n [\"Root\", root],\n ])\n log()\n hint(\"Run `meridian dev` to start your local dev server against the managed database.\")\n}\n\nexport function registerLinkCommand(program: Command): void {\n program\n .command(\"link\")\n .description(\"Link this project to a Meridian organization and app.\")\n .option(\"--org <idOrName>\", \"organization to link (id, name, or slug)\")\n .option(\"--app <idOrName>\", \"app to link (id, name, or slug)\")\n .option(\"--dev-command <cmd>\", \"override the command `meridian dev` runs (defaults to `npm run dev`)\")\n .option(\"--force\", \"overwrite an existing link, and skip the missing-package.json warning, without prompting\")\n .action(async (opts: { org?: string; app?: string; devCommand?: string; force?: boolean }) => {\n await runLink({\n ...(opts.org !== undefined ? { org: opts.org } : {}),\n ...(opts.app !== undefined ? { app: opts.app } : {}),\n ...(opts.devCommand !== undefined ? { devCommand: opts.devCommand } : {}),\n ...(opts.force === true ? { force: true } : {}),\n })\n })\n}\n","/**\n * `meridian login` — device-code OAuth against meridian-api. Verifies (and\n * reuses) an existing token when possible; otherwise runs the device flow and\n * stores the issued token in `~/.meridian/config.json`.\n */\n\nimport { hostname as osHostname } from \"node:os\"\nimport type { Command } from \"commander\"\nimport { formatUserCode, runDeviceFlow } from \"../auth/device-flow.js\"\nimport { createApiClient } from \"../lib/client.js\"\nimport type { ConfigUser } from \"../lib/config.js\"\nimport { DEFAULT_API_BASE_URL, getAuth, updateConfig } from \"../lib/config.js\"\nimport { isJsonOutput, workingDirectory } from \"../lib/context.js\"\nimport { isApiError } from \"../lib/errors.js\"\nimport { hint, log, printJson, spinner, style, success, warn } from \"../lib/output.js\"\nimport { isInteractive } from \"../lib/prompts.js\"\nimport { readProject } from \"../lib/project.js\"\n\nexport interface LoginDeps {\n createClient: typeof createApiClient\n runDeviceFlow: typeof runDeviceFlow\n /** Opens `url` in the system browser. Default: dynamic `import(\"open\")`. */\n openUrl: (url: string) => Promise<void>\n}\n\nexport interface LoginOptions {\n /** Re-authenticate even when a valid token is already stored. */\n force?: boolean\n /** Print the verification URL instead of opening a browser. */\n noBrowser?: boolean\n /** Overrides `os.hostname()` in the device-code request. */\n hostname?: string\n deps?: Partial<LoginDeps>\n}\n\nasync function defaultOpenUrl(url: string): Promise<void> {\n const { default: open } = await import(\"open\")\n await open(url)\n}\n\nfunction defaultDeps(): LoginDeps {\n return { createClient: createApiClient, runDeviceFlow, openUrl: defaultOpenUrl }\n}\n\n/**\n * The browser is only worth trying when a human is plausibly watching:\n * skipped for `--no-browser`, `MERIDIAN_NO_BROWSER`, CI, and any\n * non-interactive shell (piped input, `--no-input`, ...).\n */\nfunction shouldOpenBrowser(noBrowser: boolean | undefined): boolean {\n if (noBrowser === true) return false\n if (process.env.MERIDIAN_NO_BROWSER) return false\n if (process.env.CI) return false\n return isInteractive()\n}\n\nfunction toConfigUser(user: { id: number | string; name: string; email: string }): ConfigUser {\n return { id: user.id, name: user.name, email: user.email }\n}\n\nfunction printLoginJson(user: ConfigUser, tokenExpiresAt: string | undefined, apiBaseUrl: string): void {\n printJson({ user, token_expires_at: tokenExpiresAt, api_base_url: apiBaseUrl })\n}\n\nfunction hintUnlessLinked(json: boolean): void {\n if (json) return\n if (readProject(workingDirectory()) !== null) return\n hint(\"Run `meridian link` to connect this project to a Meridian app.\")\n}\n\n/** Runs the login logic; `options.deps` lets tests inject fakes for the API client, device flow, and browser opener. */\nexport async function runLogin(options: LoginOptions = {}): Promise<void> {\n const deps = { ...defaultDeps(), ...options.deps }\n const json = isJsonOutput()\n\n if (options.force !== true) {\n const auth = getAuth()\n if (auth !== null) {\n const client = deps.createClient({ requireAuth: false, token: auth.token })\n try {\n const me = await client.getMe()\n const user = toConfigUser(me.user)\n updateConfig({ user })\n if (json) {\n printLoginJson(user, auth.tokenExpiresAt, client.baseUrl)\n } else {\n log(`Already logged in as ${user.name} <${user.email}>`)\n hint(\"Run `meridian login --force` to re-authenticate.\")\n }\n return\n } catch (error) {\n if (!(isApiError(error) && error.status === 401)) throw error\n // Stored token was revoked/expired server-side; fall through to a fresh login.\n }\n }\n }\n\n const client = deps.createClient({ requireAuth: false })\n const hostname = options.hostname ?? osHostname()\n const wait = spinner(\"Waiting for approval in the browser…\")\n const startedAt = Date.now()\n\n const tokenResponse = await deps.runDeviceFlow({\n client,\n hostname,\n onCode: async (code) => {\n const target = code.verification_uri_complete ?? code.verification_uri\n\n if (!json) {\n log()\n log(` ${style.bold(formatUserCode(code.user_code))}`)\n log()\n log(`Visit: ${style.path(code.verification_uri)}`)\n log(\"Waiting for you to approve this login in the browser…\")\n }\n\n let opened = false\n if (shouldOpenBrowser(options.noBrowser)) {\n try {\n await deps.openUrl(target)\n opened = true\n } catch {\n warn(\"Could not open the browser automatically.\")\n }\n }\n if (!opened && !json) log(`Open this URL to continue: ${style.path(target)}`)\n\n if (!json) wait.start()\n },\n onPoll: () => {\n const elapsedSeconds = Math.round((Date.now() - startedAt) / 1000)\n wait.update(`Waiting for approval in the browser… (${elapsedSeconds}s)`)\n },\n })\n\n wait.stop()\n\n const user = toConfigUser(tokenResponse.user)\n const storeApiBaseUrl = client.baseUrl !== DEFAULT_API_BASE_URL\n\n updateConfig({\n token: tokenResponse.token,\n ...(tokenResponse.expires_at !== undefined ? { token_expires_at: tokenResponse.expires_at } : {}),\n user,\n ...(storeApiBaseUrl ? { api_base_url: client.baseUrl } : {}),\n })\n\n if (json) {\n printLoginJson(user, tokenResponse.expires_at, client.baseUrl)\n } else {\n success(`Logged in as ${user.name} <${user.email}>`)\n hintUnlessLinked(json)\n }\n}\n\nexport function registerLoginCommand(program: Command): void {\n program\n .command(\"login\")\n .description(\"Authenticate this machine with Meridian via a device-code login in your browser.\")\n .option(\"--force\", \"re-authenticate even when a valid token is already stored\")\n .option(\"--no-browser\", \"print the verification URL instead of opening it\")\n .option(\"--hostname <name>\", \"hostname reported to Meridian for this device (defaults to the machine hostname)\")\n .action(async (opts: { force?: boolean; browser?: boolean; hostname?: string }) => {\n await runLogin({\n ...(opts.force === true ? { force: true } : {}),\n ...(opts.browser === false ? { noBrowser: true } : {}),\n ...(typeof opts.hostname === \"string\" ? { hostname: opts.hostname } : {}),\n })\n })\n}\n","/**\n * Device-code login orchestration (RFC 8628-ish, per meridian-api's\n * `/app/cli/device/*` contract), stripped of all I/O: no console output, no\n * browser opening, no config writing. The `login` command wires those in via\n * `DeviceFlowCallbacks` so this module stays trivially unit-testable and\n * reusable (e.g. by a future `--json` login mode).\n */\n\nimport { hostname as osHostname } from \"node:os\"\nimport type { ApiClient } from \"../lib/api.js\"\nimport type { DeviceCodeResponse, DeviceTokenResponse } from \"../lib/api-types.js\"\nimport { CliError, isApiError, isCliError } from \"../lib/errors.js\"\n\nconst DEFAULT_CLIENT_NAME = \"meridian-cli\"\nconst DEFAULT_INTERVAL_SECONDS = 5\nconst DEFAULT_EXPIRES_IN_SECONDS = 900\nconst SLOW_DOWN_INCREMENT_MS = 5_000\nconst MAX_CONSECUTIVE_TRANSIENT_FAILURES = 3\nconst DEFAULT_MAX_WAIT_MS = 15 * 60 * 1000\n\nexport interface DeviceFlowCallbacks {\n /** Called once with the code payload so the command can print the user code and open the browser. */\n onCode?: (code: DeviceCodeResponse) => void | Promise<void>\n /** Called each time the server asks us to slow down, with the new interval in ms. */\n onSlowDown?: (intervalMs: number) => void\n /** Called before each poll attempt (attempt starts at 1) so the caller can update a spinner. */\n onPoll?: (attempt: number) => void\n}\n\nexport interface DeviceFlowOptions extends DeviceFlowCallbacks {\n client: ApiClient\n clientName?: string\n hostname?: string\n /** Injectable for tests. Default: (ms) => new Promise(r => setTimeout(r, ms)). */\n sleep?: (ms: number) => Promise<void>\n /** Injectable clock for expiry maths. Default Date.now. */\n now?: () => number\n /** Hard cap regardless of the server's expires_in. Default 15 minutes. */\n maxWaitMs?: number\n}\n\nfunction defaultSleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction deniedError(): CliError {\n return new CliError(\"Authorization was denied in the browser.\", {\n hint: \"Run `meridian login` again if you want to retry.\",\n })\n}\n\nfunction expiredError(expiresInSeconds: number): CliError {\n const minutes = Math.max(1, Math.round(expiresInSeconds / 60))\n return new CliError(\"The login request expired before it was approved.\", {\n hint: `Run \\`meridian login\\` again and approve it in the browser within ${minutes} minute${minutes === 1 ? \"\" : \"s\"}.`,\n })\n}\n\nfunction timedOutError(): CliError {\n return new CliError(\"Timed out waiting for the login to be approved.\", {\n hint: \"Run `meridian login` again and approve the request promptly in the browser.\",\n })\n}\n\n/**\n * `invalid_grant` is outside the four polling codes the contract lists: the\n * API returns it (as a 404) when the device code is unknown or has already\n * been exchanged for a token. Retrying can never help, and the generic 404\n * handling would tell the user to run `meridian link`, so it is terminal here.\n */\nfunction invalidGrantError(): CliError {\n return new CliError(\"This login request is no longer valid.\", {\n hint: \"Run `meridian login` again to start a new one.\",\n })\n}\n\n/** True for failures worth a bounded retry: a 5xx from the API, or a network/timeout CliError raised by ApiClient. */\nfunction isTransientFailure(error: unknown): boolean {\n if (isApiError(error)) return error.status >= 500\n return isCliError(error)\n}\n\n/** Runs the full device flow and resolves with the issued token. */\nexport async function runDeviceFlow(options: DeviceFlowOptions): Promise<DeviceTokenResponse> {\n const { client } = options\n const sleep = options.sleep ?? defaultSleep\n const now = options.now ?? Date.now\n const maxWaitMs = options.maxWaitMs ?? DEFAULT_MAX_WAIT_MS\n\n const code = await client.requestDeviceCode({\n clientName: options.clientName ?? DEFAULT_CLIENT_NAME,\n hostname: options.hostname ?? osHostname(),\n })\n await options.onCode?.(code)\n\n const expiresInSeconds = code.expires_in ?? DEFAULT_EXPIRES_IN_SECONDS\n let intervalMs = Math.max(1, code.interval ?? DEFAULT_INTERVAL_SECONDS) * 1000\n\n const start = now()\n const deadline = Math.min(start + expiresInSeconds * 1000, start + maxWaitMs)\n\n let attempt = 1\n let consecutiveFailures = 0\n\n while (true) {\n if (now() >= deadline) throw timedOutError()\n\n options.onPoll?.(attempt)\n\n try {\n return await client.pollDeviceTokenOnce(code.device_code)\n } catch (error) {\n if (isApiError(error)) {\n if (error.errorCode === \"authorization_pending\") {\n consecutiveFailures = 0\n await sleep(intervalMs)\n attempt += 1\n continue\n }\n // The device endpoints are IP-throttled on top of the per-code\n // `slow_down` guard, and a throttled response carries the platform's\n // own error code — any 429 means the same thing: poll less often.\n if (error.errorCode === \"slow_down\" || error.status === 429) {\n intervalMs += SLOW_DOWN_INCREMENT_MS\n options.onSlowDown?.(intervalMs)\n consecutiveFailures = 0\n await sleep(intervalMs)\n attempt += 1\n continue\n }\n if (error.errorCode === \"access_denied\") throw deniedError()\n if (error.errorCode === \"expired_token\") throw expiredError(expiresInSeconds)\n if (error.errorCode === \"invalid_grant\") throw invalidGrantError()\n }\n\n if (!isTransientFailure(error)) throw error\n\n consecutiveFailures += 1\n if (consecutiveFailures > MAX_CONSECUTIVE_TRANSIENT_FAILURES) throw error\n\n await sleep(intervalMs)\n attempt += 1\n }\n }\n}\n\n/**\n * Normalizes a user-typed device code: uppercases, strips whitespace/dashes,\n * then re-inserts the dash for the standard 8-character `XXXX-XXXX` shape so\n * `\"abcd 1234\"` and `\"abcd-1234\"` both become `\"ABCD-1234\"`.\n */\nexport function formatUserCode(code: string): string {\n const cleaned = code.trim().toUpperCase().replace(/[^A-Z0-9]/g, \"\")\n if (cleaned.length === 8) return `${cleaned.slice(0, 4)}-${cleaned.slice(4)}`\n return cleaned\n}\n","/**\n * `meridian logout` — clears the stored CLI token. Leaves any linked project\n * (`.meridian/project.json`) untouched; that's `meridian unlink`'s job.\n */\n\nimport type { Command } from \"commander\"\nimport { clearAuth } from \"../lib/config.js\"\nimport { isJsonOutput } from \"../lib/context.js\"\nimport { hint, log, printJson, success } from \"../lib/output.js\"\n\n/** Clears the stored token. Returns void; the exit code is always 0. */\nexport async function runLogout(): Promise<void> {\n const hadToken = clearAuth()\n\n if (isJsonOutput()) {\n printJson({ logged_out: hadToken })\n return\n }\n\n if (hadToken) success(\"Logged out.\")\n else log(\"You were not logged in.\")\n\n hint(\"`.meridian/project.json` is untouched; run `meridian unlink` to remove a linked project.\")\n}\n\nexport function registerLogoutCommand(program: Command): void {\n program\n .command(\"logout\")\n .description(\"Clear the Meridian CLI token stored on this machine.\")\n .action(async () => {\n await runLogout()\n })\n}\n","/**\n * Logical dump/replay of the dev database around a `meridian migrate` run.\n * `createSnapshot` is taken before `npx prisma migrate dev`; if that fails,\n * the API resets the schema to empty and `restoreSnapshot` replays the dump\n * so the developer never loses data to a bad migration.\n */\n\nimport { mkdir, readFile, readdir, rm, stat } from \"node:fs/promises\"\nimport { join } from \"node:path\"\nimport { CliError, describeError } from \"../errors.js\"\nimport { createSqlConnection } from \"./connection.js\"\nimport type { ConnectionFactory, DbConnectionInfo, SqlConnection } from \"./connection.js\"\n\nexport interface SnapshotResult {\n /** Dump file, or null when the database held no tables and nothing was written. */\n path: string | null\n bytes: number\n createdAt: Date\n /** Tables captured. Zero means the database was empty. */\n tables: number\n}\n\n/** `2026-07-31T11-22-33-123Z.sql` — filesystem-safe ISO, sorts chronologically. */\nexport function snapshotFileName(date: Date = new Date()): string {\n return `${date.toISOString().replace(/[:.]/g, \"-\")}.sql`\n}\n\nexport type DumpFn = (options: {\n connection: { host: string; port: number; user: string; password: string; database: string }\n dumpToFile?: string\n dump?: unknown\n}) => Promise<unknown>\n\nexport interface CreateSnapshotOptions {\n /** Directory to write into; created recursively. Usually snapshotsDir(projectRoot). */\n dir: string\n now?: () => Date\n /** Injectable `mysqldump` for tests. */\n dumpImpl?: DumpFn\n /** Injectable connection factory, used for the table count. */\n factory?: ConnectionFactory\n}\n\nconst SKIP_SNAPSHOT_HINT = \"Re-run with --skip-snapshot to bypass snapshotting (not recommended before a schema-changing migration).\"\n\n/**\n * mysqldump v3 is CJS; its `module.exports` (not a named export) is the dump\n * function, and it's also mirrored onto `.default` — handle both interop\n * shapes and import lazily so non-migrate commands don't pay its startup cost.\n */\nasync function loadMysqldump(): Promise<DumpFn> {\n const mod = await import(\"mysqldump\")\n const dump = (mod.default as unknown as { default?: DumpFn }).default ?? (mod.default as unknown as DumpFn)\n return dump\n}\n\n/**\n * Logical dump (schema + data + triggers/routines/views) of the dev database.\n *\n * The dump options drop-and-recreate every table (`dropIfExist: true`,\n * `ifNotExist: false`) rather than assuming an empty target, so the file\n * replays cleanly whether it lands on an empty schema (the migrate rollback\n * path, after the API resets the schema) or is re-run by hand.\n */\nexport async function createSnapshot(info: DbConnectionInfo, options: CreateSnapshotOptions): Promise<SnapshotResult> {\n const now = options.now ?? (() => new Date())\n const createdAt = now()\n\n // A dev database has no tables until the first `prisma migrate dev` — the\n // normal state on the very run that creates them. mysqldump builds one\n // multi-statement query out of the table list and sends it unconditionally,\n // so with no tables it issues an empty string and MySQL rejects it\n // (ER_EMPTY_QUERY). There is nothing to dump, so don't ask it to.\n const tables = await countTables(info, options.factory)\n if (tables === 0) {\n return { path: null, bytes: 0, createdAt, tables: 0 }\n }\n\n const dump = options.dumpImpl ?? (await loadMysqldump())\n\n await mkdir(options.dir, { recursive: true })\n\n const path = join(options.dir, snapshotFileName(createdAt))\n\n try {\n await dump({\n connection: {\n host: info.host,\n port: info.port,\n user: info.user,\n password: info.password,\n database: info.database,\n },\n dumpToFile: path,\n dump: {\n schema: { table: { ifNotExist: false, dropIfExist: true }, engine: false },\n data: { format: false, verbose: false },\n trigger: {},\n },\n })\n } catch (error) {\n // Name the underlying failure: without it every cause — unreachable proxy,\n // missing privilege, disk full — reads as the same opaque one-liner.\n throw new CliError(`Could not snapshot the development database: ${describeError(error)}`, {\n hint: SKIP_SNAPSHOT_HINT,\n cause: error,\n })\n }\n\n let bytes: number\n try {\n bytes = (await stat(path)).size\n } catch (error) {\n throw new CliError(\"Could not snapshot the development database: the dump did not produce a file.\", {\n hint: SKIP_SNAPSHOT_HINT,\n cause: error,\n })\n }\n\n if (bytes === 0) {\n throw new CliError(\"Could not snapshot the development database: the dump produced an empty file.\", {\n hint: SKIP_SNAPSHOT_HINT,\n })\n }\n\n return { path, bytes, createdAt, tables }\n}\n\n/** Single-quoted SQL literal; the database name is interpolated, not bound. */\nfunction quoteSqlString(value: string): string {\n return `'${value.replace(/\\\\/g, \"\\\\\\\\\").replace(/'/g, \"''\")}'`\n}\n\n/**\n * Reads `COUNT(*)` out of a result. mysql2 answers `[rows, fields]`; a test\n * fake may answer the rows directly, so accept either shape.\n */\nfunction readCount(result: unknown): number | undefined {\n const groups = Array.isArray(result) ? result : [result]\n for (const group of groups) {\n const rows = Array.isArray(group) ? group : [group]\n for (const row of rows) {\n if (typeof row === \"object\" && row !== null && \"count\" in row) {\n const parsed = Number((row as { count: unknown }).count)\n if (Number.isFinite(parsed)) return parsed\n }\n }\n }\n return undefined\n}\n\n/**\n * How many tables the dev database holds. Returns 1 (\"assume non-empty\")\n * whenever the count cannot be established — an unreachable database or an\n * unexpected result shape falls through to attempting the dump, whose own\n * failure is the more informative one to report.\n */\nasync function countTables(info: DbConnectionInfo, factory: ConnectionFactory = createSqlConnection): Promise<number> {\n let connection: SqlConnection\n try {\n connection = await factory(info)\n } catch {\n return 1\n }\n\n try {\n const result = await connection.query(\n `SELECT COUNT(*) AS \\`count\\` FROM information_schema.tables WHERE table_schema = ${quoteSqlString(info.database)}`,\n )\n return readCount(result) ?? 1\n } catch {\n return 1\n } finally {\n try {\n await connection.end()\n } catch {\n connection.destroy?.()\n }\n }\n}\n\nexport interface RestoreSnapshotOptions {\n factory?: ConnectionFactory\n /** Called with progress info for a spinner: statements executed so far. */\n onProgress?: (executed: number, total: number) => void\n}\n\n/**\n * Replays a snapshot into an (empty) database. Used as the rollback half of\n * `meridian migrate` after the API has dropped and recreated the schema.\n */\nexport async function restoreSnapshot(\n info: DbConnectionInfo,\n snapshotPath: string,\n options: RestoreSnapshotOptions = {},\n): Promise<{ statements: number }> {\n const factory = options.factory ?? createSqlConnection\n const sql = await readFile(snapshotPath, \"utf8\")\n const statements = splitSqlStatements(sql)\n\n const connection = await factory(info, { multipleStatements: true })\n try {\n await connection.query(\"SET FOREIGN_KEY_CHECKS=0\")\n await connection.query(\"SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO'\")\n\n for (const [index, statement] of statements.entries()) {\n try {\n await connection.query(statement)\n } catch (error) {\n throw new CliError(\n `Snapshot replay failed at statement ${index + 1} of ${statements.length}: ${statement.slice(0, 200)}`,\n {\n hint: `Inspect the failure, then replay the snapshot by hand with \\`mysql < ${snapshotPath}\\`.`,\n cause: error,\n },\n )\n }\n options.onProgress?.(index + 1, statements.length)\n }\n\n await connection.query(\"SET FOREIGN_KEY_CHECKS=1\")\n } finally {\n await connection.end()\n }\n\n return { statements: statements.length }\n}\n\n/**\n * Splits a dump into executable statements. Handles `--` and `#` line\n * comments, `/* *\\/` block comments (including MySQL's executable `/*! ... *\\/`\n * hints, which must be kept), single/double-quoted strings, backtick\n * identifiers, escaped quotes, and `DELIMITER` blocks used for\n * triggers/routines.\n */\nexport function splitSqlStatements(sql: string): string[] {\n const statements: string[] = []\n let delimiter = \";\"\n let buffer = \"\"\n let i = 0\n const n = sql.length\n\n const flush = (): void => {\n const trimmed = buffer.trim()\n buffer = \"\"\n if (trimmed !== \"\") statements.push(trimmed)\n }\n\n while (i < n) {\n if (buffer.trim() === \"\" && sql.slice(i, i + 10).toUpperCase() === \"DELIMITER \") {\n const lineEnd = sql.indexOf(\"\\n\", i)\n const line = lineEnd === -1 ? sql.slice(i) : sql.slice(i, lineEnd)\n const newDelimiter = line.slice(\"DELIMITER\".length).trim()\n if (newDelimiter !== \"\") {\n delimiter = newDelimiter\n buffer = \"\"\n i = lineEnd === -1 ? n : lineEnd + 1\n continue\n }\n }\n\n const ch = sql[i]\n\n if (ch === \"-\" && sql[i + 1] === \"-\" && (sql[i + 2] === undefined || /\\s/.test(sql[i + 2] ?? \"\"))) {\n const lineEnd = sql.indexOf(\"\\n\", i)\n i = lineEnd === -1 ? n : lineEnd + 1\n buffer += \"\\n\"\n continue\n }\n\n if (ch === \"#\") {\n const lineEnd = sql.indexOf(\"\\n\", i)\n i = lineEnd === -1 ? n : lineEnd + 1\n buffer += \"\\n\"\n continue\n }\n\n if (ch === \"/\" && sql[i + 1] === \"*\") {\n const isExecutableHint = sql[i + 2] === \"!\"\n const end = sql.indexOf(\"*/\", i + 2)\n const commentEnd = end === -1 ? n : end + 2\n buffer += isExecutableHint ? sql.slice(i, commentEnd) : \" \"\n i = commentEnd\n continue\n }\n\n if (ch === \"'\" || ch === '\"' || ch === \"`\") {\n const quote = ch\n let j = i + 1\n let text = ch\n while (j < n) {\n const c = sql[j]\n if (c === \"\\\\\" && quote !== \"`\") {\n text += sql.slice(j, j + 2)\n j += 2\n continue\n }\n if (c === quote) {\n if (sql[j + 1] === quote) {\n text += quote + quote\n j += 2\n continue\n }\n text += quote\n j += 1\n break\n }\n text += c\n j += 1\n }\n buffer += text\n i = j\n continue\n }\n\n if (sql.startsWith(delimiter, i)) {\n flush()\n i += delimiter.length\n continue\n }\n\n buffer += ch\n i += 1\n }\n\n flush()\n return statements\n}\n\nfunction isEnoent(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\"\n}\n\n/** Recovers the timestamp encoded in a name produced by `snapshotFileName`. */\nfunction parseSnapshotDate(name: string): Date {\n const iso = name.replace(/\\.sql$/, \"\").replace(/T(\\d\\d)-(\\d\\d)-(\\d\\d)-(\\d\\d\\d)Z$/, \"T$1:$2:$3.$4Z\")\n return new Date(iso)\n}\n\n/** Lists snapshots in a directory, newest first (name-sorted). */\nexport async function listSnapshots(dir: string): Promise<Array<{ path: string; name: string; bytes: number; createdAt: Date }>> {\n let entries: string[]\n try {\n entries = await readdir(dir)\n } catch (error) {\n if (isEnoent(error)) return []\n throw error\n }\n\n const names = entries.filter((name) => name.endsWith(\".sql\")).sort().reverse()\n\n const results: Array<{ path: string; name: string; bytes: number; createdAt: Date }> = []\n for (const name of names) {\n const path = join(dir, name)\n const { size } = await stat(path)\n results.push({ path, name, bytes: size, createdAt: parseSnapshotDate(name) })\n }\n return results\n}\n\n/** Keeps the newest `keep` snapshots and deletes the rest; returns the deleted paths. */\nexport async function pruneSnapshots(dir: string, keep: number): Promise<string[]> {\n const snapshots = await listSnapshots(dir)\n const toDelete = snapshots.slice(Math.max(keep, 0))\n for (const snapshot of toDelete) {\n await rm(snapshot.path, { force: true })\n }\n return toDelete.map((snapshot) => snapshot.path)\n}\n","/**\n * `meridian migrate` — the only command that runs `prisma migrate dev`\n * against the shared remote dev database. Because a bad migration can wreck\n * that database for the whole team, this always takes a logical snapshot\n * first (unless told not to) and can drop+recreate the schema and replay the\n * snapshot automatically when the migration fails.\n */\n\nimport type { Command } from \"commander\"\nimport type { ApiClient } from \"../lib/api.js\"\nimport type { Id, MigrationRunInput } from \"../lib/api-types.js\"\nimport { createApiClient } from \"../lib/client.js\"\nimport { isJsonOutput, workingDirectory } from \"../lib/context.js\"\nimport type { SnapshotResult } from \"../lib/db/snapshot.js\"\nimport { createSnapshot, pruneSnapshots, restoreSnapshot } from \"../lib/db/snapshot.js\"\nimport { parseIntegerOption, parsePortOption } from \"../lib/options.js\"\nimport { detail, error, hint, printJson, style, success, warn, withSpinner } from \"../lib/output.js\"\nimport { snapshotsDir } from \"../lib/paths.js\"\nimport {\n addShadowDatabaseUrl,\n assertMigrationDialect,\n assertShadowDatasource,\n diagnoseMigrationFailure,\n missingShadowDatabaseUrl,\n} from \"../lib/prisma.js\"\nimport type { LinkedProject } from \"../lib/project.js\"\nimport { requireProject } from \"../lib/project.js\"\nimport { confirmAction, isAssumeYes, isInteractive } from \"../lib/prompts.js\"\nimport type { RunResult } from \"../lib/run.js\"\nimport { runNpx } from \"../lib/run.js\"\nimport type { DevSessionInfo, StartSessionOptions } from \"../lib/session.js\"\nimport { startDevSession } from \"../lib/session.js\"\n\nconst DEFAULT_KEEP_SNAPSHOTS = 5\n/** Bounds the payload sent to `POST .../migrations`; the raw capture from run.ts is already capped at 8 KB. */\nconst MAX_OUTPUT_EXCERPT = 4000\n\nexport type MigrationStatus = \"success\" | \"failed\" | \"rolled_back\"\n\n/** Every side-effecting collaborator, injectable so the whole flow is testable offline. */\nexport interface MigrateDeps {\n startDevSession: typeof startDevSession\n createSnapshot: typeof createSnapshot\n restoreSnapshot: typeof restoreSnapshot\n pruneSnapshots: typeof pruneSnapshots\n runNpx: typeof runNpx\n createApiClient: typeof createApiClient\n requireProject: () => LinkedProject\n assertShadowDatasource: typeof assertShadowDatasource\n assertMigrationDialect: typeof assertMigrationDialect\n missingShadowDatabaseUrl: typeof missingShadowDatabaseUrl\n addShadowDatabaseUrl: typeof addShadowDatabaseUrl\n diagnoseMigrationFailure: typeof diagnoseMigrationFailure\n now: () => Date\n}\n\nexport interface MigrateOptions {\n /** Extra argv forwarded to `prisma migrate dev` verbatim, e.g. [\"--name\", \"add_orders\"]. */\n prismaArgs?: string[]\n /** Skip the pre-migration snapshot entirely. There is nothing to roll back to when this is set. */\n skipSnapshot?: boolean\n /** Still snapshot, but never auto-restore on failure; just report where the snapshot is. */\n noRollback?: boolean\n /** Run even when the history was written for another engine, which `prisma migrate dev` will reject. */\n allowForeignMigrations?: boolean\n /** Snapshots to keep (newest first) after a *successful* migration. Default 5. */\n keepSnapshots?: number\n /** Preferred local port for the Cloud SQL Auth Proxy. */\n port?: number\n /** .env file (relative to the project root) to patch with DATABASE_URL. */\n envFile?: string\n deps?: Partial<MigrateDeps>\n}\n\nfunction defaultDeps(): MigrateDeps {\n return {\n startDevSession,\n createSnapshot,\n restoreSnapshot,\n pruneSnapshots,\n runNpx,\n createApiClient,\n requireProject: () => requireProject(workingDirectory()),\n assertShadowDatasource,\n assertMigrationDialect,\n missingShadowDatabaseUrl,\n addShadowDatabaseUrl,\n diagnoseMigrationFailure,\n now: () => new Date(),\n }\n}\n\nfunction resolveDeps(overrides?: Partial<MigrateDeps>): MigrateDeps {\n return { ...defaultDeps(), ...overrides }\n}\n\n/** `12.3 KB` under 1 MiB, `4.1 MB` above — the units a developer expects for a SQL dump. */\nfunction formatSize(bytes: number): string {\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction excerptOf(output: string): string {\n return output.length > MAX_OUTPUT_EXCERPT ? output.slice(-MAX_OUTPUT_EXCERPT) : output\n}\n\n/**\n * `prisma migrate dev` needs a TTY to interactively prompt for a migration\n * name, so stdio is inherited by default. That prompt is meaningless under\n * `--json` (nothing would render it) and in non-interactive shells (CI,\n * `--no-input`, piped stdin) — those cases capture output instead so the API\n * gets a real `output_excerpt` and `--json` gets something to report.\n */\nfunction shouldInheritStdio(json: boolean): boolean {\n return !json && isInteractive()\n}\n\ninterface JsonPayload {\n status: MigrationStatus\n command: string\n started_at: string\n finished_at: string\n exit_code: number\n /** `path` is null when the database was empty and no dump file was written. */\n snapshot: { path: string | null; bytes: number } | null\n rolled_back: boolean\n database: string\n app_id: Id\n}\n\n/**\n * Reports the run to Meridian without ever masking the migration's own\n * result: a reporting failure becomes a warning, never a thrown error.\n */\nasync function reportMigrationSafely(client: ApiClient, appId: Id, input: MigrationRunInput): Promise<void> {\n try {\n await client.reportMigration(appId, input)\n } catch {\n warn(\"Could not report this migration run to Meridian.\")\n }\n}\n\ninterface RunMigrationContext {\n json: boolean\n keepSnapshots: number\n commandArgs: string[]\n commandString: string\n options: MigrateOptions\n}\n\nasync function runMigration(session: DevSessionInfo, deps: MigrateDeps, ctx: RunMigrationContext): Promise<number> {\n const { json, keepSnapshots, commandArgs, commandString, options } = ctx\n const client = deps.createApiClient()\n const appId = session.project.config.app_id\n const dir = snapshotsDir(session.project.root)\n\n let snapshot: SnapshotResult | undefined\n if (options.skipSnapshot !== true) {\n snapshot = await withSpinner(\n \"Snapshotting the development database...\",\n () => deps.createSnapshot(session.connection, { dir, now: deps.now }),\n {\n success: (result) =>\n result.path === null\n ? \"Development database is empty — nothing to snapshot.\"\n : `Snapshot saved to ${style.path(result.path)} (${formatSize(result.bytes)}).`,\n },\n )\n }\n\n const inherit = shouldInheritStdio(json)\n const startedAt = deps.now().toISOString()\n const runResult: RunResult = await deps.runNpx(commandArgs, { cwd: session.project.root, env: session.env, inherit })\n const finishedAt = deps.now().toISOString()\n\n let status: MigrationStatus\n let rolledBack = false\n let exitCode: number\n\n if (runResult.code === 0) {\n success(\"Migration applied.\")\n status = \"success\"\n exitCode = 0\n if (snapshot !== undefined) await deps.pruneSnapshots(dir, keepSnapshots)\n } else {\n // A killed-but-reported-as-0 process still counts as a failure here; never report success with a 0 exit code.\n exitCode = runResult.code !== 0 ? runResult.code : 1\n status = \"failed\"\n\n if (snapshot === undefined) {\n warn(`\\`${commandString}\\` failed (exit code ${runResult.code}).`)\n hint(\"No snapshot was taken (--skip-snapshot), so there is nothing to roll back.\")\n } else if (options.noRollback === true) {\n warn(`\\`${commandString}\\` failed (exit code ${runResult.code}); the database was left as-is (--no-rollback).`)\n if (snapshot.path === null) {\n hint(\"The database was empty before the migration; `meridian db reset` returns it to that state.\")\n } else {\n detail(`Pre-migration snapshot: ${snapshot.path}`)\n hint(`Replay it by hand once the proxy is up (\\`meridian dev\\`): \\`mysql < ${snapshot.path}\\`.`)\n }\n } else {\n const snapshotPath = snapshot.path\n warn(\n `\\`${commandString}\\` failed (exit code ${runResult.code}); ` +\n (snapshotPath === null\n ? \"rolling the development database back to its pre-migration (empty) state...\"\n : \"rolling back the development database to the pre-migration snapshot...\"),\n )\n try {\n await client.resetDevDatabase(appId)\n if (snapshotPath === null) {\n // The database was empty going in, so the reset above is the entire\n // rollback — there is no dump to replay.\n success(\"Development database rolled back to its pre-migration (empty) state.\")\n } else {\n await withSpinner(\n \"Restoring the pre-migration snapshot...\",\n (spinner) =>\n deps.restoreSnapshot(session.connection, snapshotPath, {\n onProgress: (executed, total) =>\n spinner.update(`Restoring the pre-migration snapshot... (${executed}/${total} statements)`),\n }),\n { success: (result) => `Restored the pre-migration snapshot (${result.statements} statements).` },\n )\n }\n status = \"rolled_back\"\n rolledBack = true\n } catch {\n error(\"Automatic rollback failed. The development database may be in a partial state — treat it as unsafe.\")\n if (snapshotPath === null) {\n hint(\"Recover by hand with `meridian db reset` — the database was empty before this migration.\")\n } else {\n detail(`Pre-migration snapshot: ${snapshotPath}`)\n hint(\n `Recover by hand: start the proxy with \\`meridian dev\\`, then run \\`mysql < ${snapshotPath}\\` to replay the ` +\n \"snapshot, or `meridian db reset` to start over from an empty schema.\",\n )\n }\n // status stays \"failed\" — a broken rollback is reported as a failed run, not a rolled-back one.\n }\n }\n\n // Last, so it is what the developer is left looking at: the rollback\n // messaging above says what happened to the database, this says why the\n // migration failed in the first place.\n const diagnosis = deps.diagnoseMigrationFailure(session.project.root)\n if (diagnosis !== null) hint(diagnosis)\n }\n\n const excerpt = excerptOf(runResult.output)\n await reportMigrationSafely(client, appId, {\n command: commandString,\n status,\n started_at: startedAt,\n finished_at: finishedAt,\n ...(excerpt !== \"\" ? { output_excerpt: excerpt } : {}),\n })\n\n if (json) {\n const payload: JsonPayload = {\n status,\n command: commandString,\n started_at: startedAt,\n finished_at: finishedAt,\n exit_code: exitCode,\n snapshot: snapshot !== undefined ? { path: snapshot.path, bytes: snapshot.bytes } : null,\n rolled_back: rolledBack,\n database: session.connection.database,\n app_id: appId,\n }\n printJson(payload)\n }\n\n return exitCode\n}\n\n/**\n * Offers to add the missing `shadowDatabaseUrl` line, then insists on it.\n *\n * Adding it is a one-line, mechanical edit that every project needs, so\n * offering beats making the developer break off and do it by hand. It is\n * offered rather than just applied because a schema is source they wrote and\n * keep in git, unlike the generated `.env` the CLI rewrites freely.\n *\n * Declining, or a datasource pointing somewhere deliberate, still falls\n * through to the assertion and its specific error.\n */\nasync function ensureShadowDatasource(root: string, deps: MigrateDeps): Promise<void> {\n const schemaPath = deps.missingShadowDatabaseUrl(root)\n\n // A run with nowhere to prompt falls straight through to the assertion:\n // its message names the exact line to add, which is more use than\n // \"cannot prompt in a non-interactive shell\".\n if (schemaPath !== null && (isAssumeYes() || isInteractive())) {\n const approved = await confirmAction({\n message: `\\`prisma migrate dev\\` needs a shadow database. Add \\`shadowDatabaseUrl\\` to ${schemaPath}?`,\n default: true,\n })\n if (approved) {\n deps.addShadowDatabaseUrl(root)\n success(`Added \\`shadowDatabaseUrl = env(\"SHADOW_DATABASE_URL\")\\` to ${style.path(schemaPath)}.`)\n }\n }\n\n deps.assertShadowDatasource(root)\n}\n\n/**\n * Runs the snapshot → `prisma migrate dev` → (rollback) → report flow.\n * `options.deps` lets tests inject fakes for every side-effecting\n * collaborator so this is exercised fully offline. The dev session is always\n * stopped, even when a step above throws.\n */\nexport async function runMigrate(options: MigrateOptions = {}): Promise<number> {\n const deps = resolveDeps(options.deps)\n const json = isJsonOutput()\n const keepSnapshots = options.keepSnapshots ?? DEFAULT_KEEP_SNAPSHOTS\n const commandArgs = [\"prisma\", \"migrate\", \"dev\", ...(options.prismaArgs ?? [])]\n const commandString = [\"npx\", ...commandArgs].join(\" \")\n\n // Both screens are specific to `migrate` — a shadow database and a\n // replayable history matter to nothing else — so they live here rather than\n // in the session flow `dev`, `db seed` and `db shell` share. Ahead of\n // startDevSession() so a run `prisma migrate dev` is certain to reject\n // never provisions a session, snapshots the database, or rolls it back.\n const project = deps.requireProject()\n if (project.config.skip_datasource_check !== true) await ensureShadowDatasource(project.root, deps)\n if (options.allowForeignMigrations !== true) deps.assertMigrationDialect(project.root)\n\n const sessionOptions: StartSessionOptions = {\n ...(options.port !== undefined ? { port: options.port } : {}),\n ...(options.envFile !== undefined ? { envFile: options.envFile } : {}),\n project,\n }\n const session = await deps.startDevSession(sessionOptions)\n\n try {\n return await runMigration(session, deps, { json, keepSnapshots, commandArgs, commandString, options })\n } finally {\n await session.stop()\n }\n}\n\ninterface MigrateCommandOptions {\n skipSnapshot?: boolean\n allowForeignMigrations?: boolean\n /** `--no-rollback` — commander negates this to `rollback`, default `true`. */\n rollback?: boolean\n keepSnapshots?: string\n port?: string\n envFile?: string\n}\n\n/** Registers `meridian migrate` on the root program; wiring only, logic lives in {@link runMigrate}. */\nexport function registerMigrateCommand(program: Command): void {\n program\n .command(\"migrate\")\n .description(\n \"Snapshot the development database, run `prisma migrate dev`, and roll back to the snapshot automatically if the migration fails.\",\n )\n .option(\"--skip-snapshot\", \"run without a pre-migration snapshot (no rollback is possible)\")\n .option(\n \"--allow-foreign-migrations\",\n \"run even when prisma/migrations was generated for SQLite or Postgres and cannot apply to MySQL\",\n )\n .option(\"--no-rollback\", \"keep a snapshot but do not automatically restore it after a failed migration\")\n .option(\"--keep-snapshots <n>\", \"number of recent snapshots to keep after a successful migration\", \"5\")\n .option(\"--port <port>\", \"preferred local port for the Cloud SQL Auth Proxy\")\n .option(\"--env-file <file>\", \"path (relative to the project root) of the .env file to patch with DATABASE_URL\")\n .argument(\"[prismaArgs...]\", \"extra arguments forwarded to `prisma migrate dev` verbatim, after --\")\n .passThroughOptions()\n .action(async (prismaArgs: string[], opts: MigrateCommandOptions) => {\n const keepSnapshots = parseIntegerOption(opts.keepSnapshots, \"--keep-snapshots\", { min: 0 })\n const port = parsePortOption(opts.port)\n const exitCode = await runMigrate({\n prismaArgs,\n ...(opts.skipSnapshot === true ? { skipSnapshot: true } : {}),\n ...(opts.allowForeignMigrations === true ? { allowForeignMigrations: true } : {}),\n ...(opts.rollback === false ? { noRollback: true } : {}),\n ...(keepSnapshots !== undefined ? { keepSnapshots } : {}),\n ...(port !== undefined ? { port } : {}),\n ...(opts.envFile !== undefined ? { envFile: opts.envFile } : {}),\n })\n process.exitCode = exitCode\n })\n}\n","/**\n * `meridian unlink` — removes `<root>/.meridian/project.json`. Leaves\n * `.meridian/snapshots/` (and anything else under `.meridian/`) alone.\n */\n\nimport type { Command } from \"commander\"\nimport { isJsonOutput, workingDirectory } from \"../lib/context.js\"\nimport { CliError } from \"../lib/errors.js\"\nimport { hint, log, printJson, success } from \"../lib/output.js\"\nimport { readProject, removeProject } from \"../lib/project.js\"\nimport { confirmAction } from \"../lib/prompts.js\"\n\nexport interface UnlinkDeps {\n /** Injectable for tests; never invokes real inquirer. */\n confirmImpl?: typeof import(\"@inquirer/prompts\").confirm\n}\n\nexport interface UnlinkOptions {\n deps?: Partial<UnlinkDeps>\n}\n\n/** Runs the unlink logic; `options.deps` lets tests inject a fake confirm prompt. */\nexport async function runUnlink(options: UnlinkOptions = {}): Promise<void> {\n const deps = { ...options.deps }\n const json = isJsonOutput()\n const root = workingDirectory()\n\n const project = readProject(root)\n if (project === null) {\n if (json) printJson({ unlinked: false, root })\n else log(\"This directory is not linked to a Meridian app.\")\n return\n }\n\n const appLabel = project.config.app_name ?? String(project.config.app_id)\n const proceed = await confirmAction({\n message: `Unlink ${project.root} from ${appLabel}?`,\n ...(deps.confirmImpl !== undefined ? { promptImpl: deps.confirmImpl } : {}),\n })\n if (!proceed) throw new CliError(\"Aborted.\")\n\n removeProject(project.root)\n\n if (json) {\n printJson({ unlinked: true, root: project.root })\n return\n }\n\n success(`Unlinked ${project.root} from ${appLabel}.`)\n hint(\"Snapshots in `.meridian/snapshots/` were left alone.\")\n}\n\nexport function registerUnlinkCommand(program: Command): void {\n program\n .command(\"unlink\")\n .description(\"Remove this project's link to a Meridian organization and app.\")\n .action(async () => {\n await runUnlink()\n })\n}\n","/**\n * `meridian whoami` — shows the logged-in user, org memberships, and any\n * linked project. `--offline` skips the network round trip and reports only\n * what is cached in `~/.meridian/config.json`, for use when the API is down.\n */\n\nimport type { Command } from \"commander\"\nimport type { Org } from \"../lib/api-types.js\"\nimport { createApiClient } from \"../lib/client.js\"\nimport type { ConfigUser } from \"../lib/config.js\"\nimport { getAuth, resolveApiBaseUrl } from \"../lib/config.js\"\nimport { getGlobalOptions, isJsonOutput, workingDirectory } from \"../lib/context.js\"\nimport { isApiError, notLoggedInError, sessionExpiredError } from \"../lib/errors.js\"\nimport { hint, keyValues, log, printJson, step, success, warn } from \"../lib/output.js\"\nimport type { LinkedProject } from \"../lib/project.js\"\nimport { readProject } from \"../lib/project.js\"\n\nexport interface WhoamiDeps {\n createClient: typeof createApiClient\n}\n\nexport interface WhoamiOptions {\n /** Skip the `getMe()` call; report only what is stored locally. */\n offline?: boolean\n deps?: Partial<WhoamiDeps>\n}\n\ninterface WhoamiResult {\n user: ConfigUser | null\n apiBaseUrl: string\n tokenExpiresAt: string | undefined\n orgs: Org[]\n offline: boolean\n}\n\nconst SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000\n\nfunction defaultDeps(): WhoamiDeps {\n return { createClient: createApiClient }\n}\n\nfunction toConfigUser(user: { id: number | string; name: string; email: string }): ConfigUser {\n return { id: user.id, name: user.name, email: user.email }\n}\n\n/** Warns when the token has already expired or expires within 7 days; undefined otherwise. */\nfunction describeExpiry(tokenExpiresAt: string | undefined): string | undefined {\n if (tokenExpiresAt === undefined) return undefined\n const expiry = new Date(tokenExpiresAt).getTime()\n if (Number.isNaN(expiry)) return undefined\n const remainingMs = expiry - Date.now()\n if (remainingMs < 0) return \"Your Meridian CLI token has expired.\"\n if (remainingMs < SEVEN_DAYS_MS) return \"Your Meridian CLI token expires soon.\"\n return undefined\n}\n\nfunction printHuman(result: WhoamiResult, project: LinkedProject | null): void {\n if (result.user !== null) {\n success(`Logged in as ${result.user.name} <${result.user.email}>`)\n } else {\n log(\"Logged in (cached user details unavailable offline).\")\n }\n\n keyValues([\n [\"User ID\", result.user !== null ? String(result.user.id) : \"unknown\"],\n [\"API URL\", result.apiBaseUrl],\n [\"Token expires\", result.tokenExpiresAt ?? \"never\"],\n ])\n\n const expiryWarning = describeExpiry(result.tokenExpiresAt)\n if (expiryWarning !== undefined) warn(expiryWarning)\n\n log()\n if (result.offline) {\n hint(\"Organization list requires network access; omitted in --offline mode.\")\n } else if (result.orgs.length > 0) {\n step(\"Organizations\")\n keyValues(result.orgs.map((org): [string, string] => [org.name, org.slug]))\n } else {\n log(\"No organizations.\")\n }\n\n log()\n if (project !== null) {\n step(\"Linked project\")\n keyValues([\n [\"App\", project.config.app_name ?? String(project.config.app_id)],\n [\"Org\", String(project.config.org_id)],\n [\"Root\", project.root],\n ])\n } else {\n hint(\"Run `meridian link` to connect this directory to a Meridian app.\")\n }\n}\n\nfunction printJsonResult(result: WhoamiResult, project: LinkedProject | null): void {\n printJson({\n user: result.user,\n api_base_url: result.apiBaseUrl,\n token_expires_at: result.tokenExpiresAt,\n orgs: result.orgs,\n project:\n project === null\n ? null\n : {\n root: project.root,\n org_id: project.config.org_id,\n app_id: project.config.app_id,\n ...(project.config.app_name !== undefined ? { app_name: project.config.app_name } : {}),\n },\n })\n}\n\n/** Runs the whoami logic; `options.deps` lets tests inject a fake API client. */\nexport async function runWhoami(options: WhoamiOptions = {}): Promise<void> {\n const deps = { ...defaultDeps(), ...options.deps }\n const json = isJsonOutput()\n\n const auth = getAuth()\n if (auth === null) throw notLoggedInError()\n\n let result: WhoamiResult\n if (options.offline === true) {\n result = {\n user: auth.user ?? null,\n apiBaseUrl: resolveApiBaseUrl(getGlobalOptions().apiUrl),\n tokenExpiresAt: auth.tokenExpiresAt,\n orgs: [],\n offline: true,\n }\n } else {\n const client = deps.createClient({ token: auth.token, requireAuth: false })\n try {\n const me = await client.getMe()\n result = {\n user: toConfigUser(me.user),\n apiBaseUrl: client.baseUrl,\n tokenExpiresAt: auth.tokenExpiresAt,\n orgs: me.orgs,\n offline: false,\n }\n } catch (error) {\n if (isApiError(error) && error.status === 401) throw sessionExpiredError(error)\n throw error\n }\n }\n\n const project = readProject(workingDirectory())\n\n if (json) printJsonResult(result, project)\n else printHuman(result, project)\n}\n\nexport function registerWhoamiCommand(program: Command): void {\n program\n .command(\"whoami\")\n .description(\n \"Show the logged-in Meridian user, org memberships, and any linked project.\\n\" +\n \"Use --offline to skip the API call and report only what is cached locally.\",\n )\n .option(\"--offline\", \"skip the API call; report only what is stored locally\")\n .action(async (opts: { offline?: boolean }) => {\n await runWhoami({ ...(opts.offline === true ? { offline: true } : {}) })\n })\n}\n","/**\n * The flags every command understands (`--json`, `--verbose`, `--yes`, …).\n *\n * The root command enables positional options so that `meridian dev -- npm run x`\n * reaches the subcommand untouched, which also means flags written after the\n * subcommand name are parsed by the subcommand. To let people type both\n * `meridian --json whoami` and `meridian whoami --json`, the same options are\n * declared on the root and on every leaf command, then merged deepest-first.\n */\n\nimport { type Command, Option } from \"commander\"\n\nimport type { GlobalOptions } from \"./context.js\"\n\nconst HELP_GROUP = \"Global Options:\"\n\nfunction globalOptions(): Option[] {\n return [\n new Option(\"--api-url <url>\", \"Meridian API base URL (overrides MERIDIAN_API_URL and the stored config)\"),\n new Option(\"--json\", \"print machine-readable JSON on stdout\").default(false),\n new Option(\"-q, --quiet\", \"only print warnings and errors\").default(false),\n new Option(\"--verbose\", \"print debug output, including stack traces\").default(false),\n new Option(\"--no-color\", \"disable ANSI colors\"),\n new Option(\"-y, --yes\", \"assume yes for every confirmation prompt\").default(false),\n new Option(\"--no-input\", \"never prompt; fail instead (for CI)\"),\n new Option(\"--cwd <dir>\", \"run as if started in this directory\"),\n ]\n}\n\n/** Declares the global flags on `command`, grouped at the bottom of its help. */\nexport function addGlobalFlags(command: Command): Command {\n for (const option of globalOptions()) {\n command.addOption(option.helpGroup(HELP_GROUP))\n }\n return command\n}\n\n/**\n * Declares the global flags on every leaf subcommand of `parent`, so new\n * commands pick them up without extra wiring. Groups such as `db` only route to\n * their children, so they are traversed rather than annotated.\n */\nexport function addGlobalFlagsToSubcommands(parent: Command): void {\n for (const child of parent.commands) {\n if (child.commands.length > 0) addGlobalFlagsToSubcommands(child)\n else addGlobalFlags(child)\n }\n}\n\n/** The command chain from `command` up to the root, deepest first. */\nfunction commandChain(command: Command): Command[] {\n const chain: Command[] = []\n let node: Command | null = command\n while (node !== null) {\n chain.push(node)\n node = node.parent\n }\n return chain\n}\n\n/**\n * Reads a global flag from the innermost command that actually saw it on the\n * command line, so `meridian --json whoami` and `meridian whoami --json` agree.\n */\nfunction explicit<T>(chain: Command[], key: string): T | undefined {\n for (const command of chain) {\n if (command.getOptionValueSource(key) === \"cli\") return command.getOptionValue(key) as T\n }\n return undefined\n}\n\n/** Merges the global flags seen anywhere along `actionCommand`'s chain. */\nexport function resolveGlobalFlags(actionCommand: Command): Partial<GlobalOptions> {\n const chain = commandChain(actionCommand)\n\n const apiUrl = explicit<string>(chain, \"apiUrl\")\n const color = explicit<boolean>(chain, \"color\")\n const input = explicit<boolean>(chain, \"input\")\n const cwd = explicit<string>(chain, \"cwd\")\n\n return {\n ...(apiUrl !== undefined ? { apiUrl } : {}),\n json: explicit<boolean>(chain, \"json\") === true,\n quiet: explicit<boolean>(chain, \"quiet\") === true,\n verbose: explicit<boolean>(chain, \"verbose\") === true,\n // `--no-color`/`--no-input` are only meaningful when asked for explicitly;\n // otherwise output and prompts auto-detect the terminal.\n ...(color !== undefined ? { color } : {}),\n yes: explicit<boolean>(chain, \"yes\") === true,\n ...(input !== undefined ? { interactive: input } : {}),\n ...(cwd !== undefined ? { cwd } : {}),\n }\n}\n"],"mappings":"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","names":["readFileSync","join","require","z","error","input","z","run","error","hint","fieldError","z","z","error","current","error","createConnection","resolve","error","extractErrorCode","hint","detail","current","truncate","error","mkdirSync","readFileSync","writeFileSync","dirname","z","z","dirname","readFileSync","error","isEnoent","mkdirSync","writeFileSync","readFileSync","join","isEnoent","error","current","resolve","join","error","resolve","isEnoent","readFileSync","chmodSync","existsSync","mkdirSync","readFileSync","renameSync","writeFileSync","dirname","line","match","isEnoent","error","writeFileSync","chmodSync","readFileSync","existsSync","mkdirSync","dirname","renameSync","input","resolve","existsSync","readFileSync","statSync","writeFileSync","dirname","join","statSync","join","existsSync","readFileSync","writeFileSync","dirname","chmodSync","existsSync","mkdirSync","readFileSync","renameSync","rmSync","writeFileSync","join","error","existsSync","join","mkdirSync","readFileSync","expected","rmSync","writeFileSync","chmodSync","renameSync","input","resolve","hint","error","current","resolve","resolve","detail","spinner","current","error","delimiter","join","delimiter","join","input","resolve","readFileSync","join","error","existsSync","join","defaultDeps","existsSync","join","org","app","osHostname","osHostname","DEFAULT_CLIENT_NAME","defaultSleep","resolve","error","osHostname","defaultDeps","client","user","error","osHostname","join","join","error","delimiter","isEnoent","defaultDeps","resolveDeps","input","spinner","appLabel","defaultDeps","toConfigUser","error","input","error"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/db.ts","../src/version.ts","../src/lib/api.ts","../src/lib/api-types.ts","../src/lib/errors.ts","../src/lib/config.ts","../src/lib/paths.ts","../src/lib/context.ts","../src/lib/client.ts","../src/lib/db/connection.ts","../src/lib/output.ts","../src/lib/options.ts","../src/lib/prompts.ts","../src/lib/project.ts","../src/lib/run.ts","../src/lib/env-file.ts","../src/lib/port.ts","../src/lib/prisma.ts","../src/lib/proxy/binary.ts","../src/lib/proxy/proxy.ts","../src/lib/signals.ts","../src/lib/session.ts","../src/commands/db-shell-repl.ts","../src/commands/dev.ts","../src/commands/link.ts","../src/commands/login.ts","../src/auth/device-flow.ts","../src/commands/logout.ts","../src/lib/db/snapshot.ts","../src/commands/migrate.ts","../src/commands/unlink.ts","../src/commands/whoami.ts","../src/lib/global-flags.ts"],"sourcesContent":["import { realpathSync } from \"node:fs\"\nimport { fileURLToPath } from \"node:url\"\n\nimport { Command } from \"commander\"\n\nimport { registerDbCommand } from \"./commands/db.js\"\nimport { registerDevCommand } from \"./commands/dev.js\"\nimport { registerLinkCommand } from \"./commands/link.js\"\nimport { registerLoginCommand } from \"./commands/login.js\"\nimport { registerLogoutCommand } from \"./commands/logout.js\"\nimport { registerMigrateCommand } from \"./commands/migrate.js\"\nimport { registerUnlinkCommand } from \"./commands/unlink.js\"\nimport { registerWhoamiCommand } from \"./commands/whoami.js\"\nimport { setGlobalOptions } from \"./lib/context.js\"\nimport { addGlobalFlags, addGlobalFlagsToSubcommands, resolveGlobalFlags } from \"./lib/global-flags.js\"\nimport { configureOutput, reportError } from \"./lib/output.js\"\nimport { configurePrompts } from \"./lib/prompts.js\"\nimport { VERSION } from \"./version.js\"\n\nexport function buildProgram(): Command {\n const program = new Command()\n\n program\n .name(\"meridian\")\n .description(\n \"Managed remote development databases for Meridian apps.\\n\\n\" +\n \"Run `meridian login` once, `meridian link` per project, then `meridian dev`.\",\n )\n .version(VERSION, \"-V, --version\")\n // `meridian dev -- npm run something` must reach the subcommand untouched.\n .enablePositionalOptions()\n .showHelpAfterError(\"(run `meridian --help` for usage)\")\n\n addGlobalFlags(program)\n\n program.hook(\"preAction\", (_thisCommand, actionCommand) => {\n const flags = resolveGlobalFlags(actionCommand)\n\n setGlobalOptions(flags)\n\n configureOutput({\n json: flags.json === true,\n quiet: flags.quiet === true,\n verbose: flags.verbose === true,\n ...(flags.color !== undefined ? { color: flags.color } : {}),\n })\n\n configurePrompts({\n // Only set when the flag is actually present: `--yes` has no negated\n // form, so passing `false` here would just be \"flag absent\" — and it\n // would override the MERIDIAN_YES fallback isAssumeYes() falls back to.\n ...(flags.yes === true ? { assumeYes: true } : {}),\n ...(flags.interactive !== undefined ? { interactive: flags.interactive } : {}),\n })\n })\n\n registerLoginCommand(program)\n registerLogoutCommand(program)\n registerWhoamiCommand(program)\n registerLinkCommand(program)\n registerUnlinkCommand(program)\n registerDevCommand(program)\n registerMigrateCommand(program)\n registerDbCommand(program)\n\n addGlobalFlagsToSubcommands(program)\n\n return program\n}\n\nexport async function run(argv: string[] = process.argv): Promise<number> {\n try {\n await buildProgram().parseAsync(argv)\n return process.exitCode === undefined ? 0 : Number(process.exitCode)\n } catch (error) {\n return reportError(error)\n }\n}\n\n/** True when this file was executed as the `meridian` bin rather than imported. */\nfunction isMainModule(): boolean {\n const entry = process.argv[1]\n if (entry === undefined) return false\n try {\n // npm installs the bin as a symlink into its bin directory, so the entry\n // path only matches this module once both sides are fully resolved.\n return realpathSync(entry) === realpathSync(fileURLToPath(import.meta.url))\n } catch {\n return false\n }\n}\n\nif (isMainModule()) {\n const code = await run(process.argv)\n if (code !== 0) process.exitCode = code\n}\n","/**\n * `meridian db reset|seed|shell` — the three commands for working directly\n * against the Meridian-managed MySQL development database once it's linked\n * and running: destroy-and-rebuild the schema, run Prisma's seed script, or\n * open a SQL client (the real `mysql` binary when available, otherwise a\n * minimal built-in REPL — see `db-shell-repl.ts`).\n */\n\nimport { readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport type { Command } from \"commander\"\nimport type { Id } from \"../lib/api-types.js\"\nimport { createApiClient } from \"../lib/client.js\"\nimport { isJsonOutput, workingDirectory } from \"../lib/context.js\"\nimport type { ConnectionFactory } from \"../lib/db/connection.js\"\nimport { createSqlConnection, withConnection } from \"../lib/db/connection.js\"\nimport { error, hint, log, printJson, step, style, success, withSpinner } from \"../lib/output.js\"\nimport { parsePortOption } from \"../lib/options.js\"\nimport { confirmAction, confirmDestructive, isAssumeYes, isInteractive } from \"../lib/prompts.js\"\nimport { requireProject } from \"../lib/project.js\"\nimport { runNpx, runProcess } from \"../lib/run.js\"\nimport type { RunResult } from \"../lib/run.js\"\nimport type { DevSessionInfo } from \"../lib/session.js\"\nimport { ensureDevDatabaseReady, startDevSession } from \"../lib/session.js\"\nimport { executeStatement, findExecutable, runRepl } from \"./db-shell-repl.js\"\n\n/** Every side-effecting collaborator `db reset`/`db seed`/`db shell` use, injectable so they're testable offline. */\nexport interface DbDeps {\n startDevSession: typeof startDevSession\n ensureDevDatabaseReady: typeof ensureDevDatabaseReady\n createApiClient: typeof createApiClient\n runNpx: typeof runNpx\n runProcess: typeof runProcess\n createConnection: ConnectionFactory\n findExecutable: (name: string) => string | null\n requireProject: typeof requireProject\n /** Injectable for tests; used for the `db reset` migrate/seed follow-up prompts. Never invokes real inquirer. */\n confirmImpl?: typeof import(\"@inquirer/prompts\").confirm\n /** Injectable for tests; used for `confirmDestructive`'s typed-phrase prompt. Never invokes real inquirer. */\n destructiveImpl?: typeof import(\"@inquirer/prompts\").input\n}\n\nfunction defaultDbDeps(): DbDeps {\n return {\n startDevSession,\n ensureDevDatabaseReady,\n createApiClient,\n runNpx,\n runProcess,\n createConnection: createSqlConnection,\n findExecutable,\n requireProject,\n }\n}\n\ninterface PackageJsonShape {\n scripts?: Record<string, unknown>\n prisma?: { seed?: unknown }\n}\n\n/**\n * Whether seeding is configured at all — used to decide whether `db reset`\n * even offers the \"seed now?\" follow-up. Covers the classic `prisma.seed`\n * field (Prisma <6) and a plain `scripts.seed` entry; Prisma 6's\n * `prisma.config.ts` seed export can't be detected without executing it, so\n * a project relying solely on that will need to run `meridian db seed`\n * manually (it still works — it's just not auto-offered here).\n */\nfunction hasSeedConfigured(root: string): boolean {\n let parsed: PackageJsonShape\n try {\n parsed = JSON.parse(readFileSync(join(root, \"package.json\"), \"utf8\")) as PackageJsonShape\n } catch {\n return false\n }\n const prismaSeed = parsed.prisma?.seed\n if (typeof prismaSeed === \"string\" && prismaSeed !== \"\") return true\n const seedScript = parsed.scripts?.seed\n return typeof seedScript === \"string\" && seedScript !== \"\"\n}\n\nexport interface DbResetOptions {\n /** Run `npx prisma migrate deploy` afterwards, without asking. */\n migrate?: boolean\n /** Run `npx prisma db seed` afterwards, without asking. */\n seed?: boolean\n port?: number\n envFile?: string\n deps?: Partial<DbDeps>\n}\n\ninterface DbResetJson {\n reset: boolean\n database: string\n app_id: Id\n migrated: boolean\n seeded: boolean\n aborted: boolean\n}\n\n/** Runs `db reset`'s logic; `options.deps` lets tests inject every collaborator. Returns the process exit code. */\nexport async function runDbReset(options: DbResetOptions = {}): Promise<number> {\n const deps = { ...defaultDbDeps(), ...options.deps }\n const json = isJsonOutput()\n\n const project = deps.requireProject(workingDirectory())\n const client = deps.createApiClient({})\n const appId = project.config.app_id\n\n const devDatabase = await deps.ensureDevDatabaseReady(client, appId)\n const database = devDatabase.database\n\n const confirmed = await confirmDestructive({\n message: `This will drop every table in ${database}. Type the database name to confirm.`,\n phrase: database,\n assumeYes: isAssumeYes(),\n ...(deps.destructiveImpl !== undefined ? { promptImpl: deps.destructiveImpl } : {}),\n })\n\n if (!confirmed) {\n log(\"Aborted.\")\n if (json) {\n printJson({\n reset: false,\n database,\n app_id: appId,\n migrated: false,\n seeded: false,\n aborted: true,\n } satisfies DbResetJson)\n }\n return 0\n }\n\n await withSpinner(`Resetting ${database}...`, () => client.resetDevDatabase(appId), {\n success: `Reset ${database}.`,\n })\n\n let wantMigrate = options.migrate === true\n let wantSeed = options.seed === true\n\n if (!wantMigrate && !wantSeed) {\n if (isInteractive()) {\n wantMigrate = await confirmAction({\n message: \"Run `npx prisma migrate deploy` now?\",\n default: false,\n ...(deps.confirmImpl !== undefined ? { promptImpl: deps.confirmImpl } : {}),\n })\n if (hasSeedConfigured(project.root)) {\n wantSeed = await confirmAction({\n message: \"Seed the database now?\",\n default: false,\n ...(deps.confirmImpl !== undefined ? { promptImpl: deps.confirmImpl } : {}),\n })\n }\n } else {\n hint(\"Run `npx prisma migrate deploy` and `npx prisma db seed` to finish setting up the database.\")\n }\n }\n\n let migrated = false\n let seeded = false\n let followUpExitCode = 0\n\n if (wantMigrate || wantSeed) {\n let session: DevSessionInfo | undefined\n try {\n session = await deps.startDevSession({\n ...(options.port !== undefined ? { port: options.port } : {}),\n ...(options.envFile !== undefined ? { envFile: options.envFile } : {}),\n })\n\n if (wantMigrate) {\n const result = await deps.runNpx([\"prisma\", \"migrate\", \"deploy\"], {\n cwd: session.project.root,\n env: session.env,\n inherit: true,\n })\n migrated = result.code === 0\n if (result.code !== 0) {\n error(`\\`npx prisma migrate deploy\\` exited with code ${result.code}.`)\n followUpExitCode = result.code\n }\n }\n\n if (followUpExitCode === 0 && wantSeed) {\n const result = await deps.runNpx([\"prisma\", \"db\", \"seed\"], {\n cwd: session.project.root,\n env: session.env,\n inherit: true,\n })\n seeded = result.code === 0\n if (result.code !== 0) {\n error(`\\`npx prisma db seed\\` exited with code ${result.code}.`)\n hint(\"Make sure `prisma.seed` (or your Prisma 6 seed config) is set in package.json.\")\n followUpExitCode = result.code\n }\n }\n } finally {\n if (session !== undefined) await session.stop()\n }\n }\n\n if (json) {\n printJson({ reset: true, database, app_id: appId, migrated, seeded, aborted: false } satisfies DbResetJson)\n }\n\n return followUpExitCode\n}\n\nexport interface DbSeedOptions {\n port?: number\n envFile?: string\n /** Extra args forwarded after `npx prisma db seed` (from `-- <args>`). */\n extraArgs?: string[]\n deps?: Partial<DbDeps>\n}\n\ninterface DbSeedJson {\n seeded: boolean\n exit_code: number\n}\n\n/** Runs `db seed`'s logic; `options.deps` lets tests inject every collaborator. Returns the process exit code. */\nexport async function runDbSeed(options: DbSeedOptions = {}): Promise<number> {\n const deps = { ...defaultDbDeps(), ...options.deps }\n const json = isJsonOutput()\n\n let session: DevSessionInfo | undefined\n try {\n session = await deps.startDevSession({\n ...(options.port !== undefined ? { port: options.port } : {}),\n ...(options.envFile !== undefined ? { envFile: options.envFile } : {}),\n })\n\n const args = [\"prisma\", \"db\", \"seed\", ...(options.extraArgs ?? [])]\n const result: RunResult = await deps.runNpx(args, {\n cwd: session.project.root,\n env: session.env,\n inherit: true,\n })\n\n if (result.code === 0) {\n success(\"Seeded the development database.\")\n } else {\n error(`\\`npx prisma db seed\\` exited with code ${result.code}.`)\n hint(\"Make sure `prisma.seed` (or your Prisma 6 seed config) is set in package.json.\")\n }\n\n if (json) printJson({ seeded: result.code === 0, exit_code: result.code } satisfies DbSeedJson)\n\n return result.code\n } finally {\n if (session !== undefined) await session.stop()\n }\n}\n\nexport interface DbShellOptions {\n port?: number\n envFile?: string\n /** Force the built-in REPL even when `mysql` is on PATH. */\n repl?: boolean\n /** Run one statement and exit. */\n execute?: string\n /** `--no-env`: skip patching DATABASE_URL into the project's .env file. */\n env?: boolean\n deps?: Partial<DbDeps>\n}\n\n/** Runs `db shell`'s logic; `options.deps` lets tests inject every collaborator. Returns the process exit code. */\nexport async function runDbShell(options: DbShellOptions = {}): Promise<number> {\n const deps = { ...defaultDbDeps(), ...options.deps }\n const json = isJsonOutput()\n\n let session: DevSessionInfo | undefined\n try {\n session = await deps.startDevSession({\n waitForDb: true,\n ...(options.port !== undefined ? { port: options.port } : {}),\n ...(options.envFile !== undefined ? { envFile: options.envFile } : {}),\n ...(options.env === false ? { patchEnv: false } : {}),\n })\n\n const info = session.connection\n const wantRepl = options.repl === true\n const mysqlPath = wantRepl ? null : deps.findExecutable(process.platform === \"win32\" ? \"mysql.exe\" : \"mysql\")\n\n if (mysqlPath !== null) {\n step(`Connecting to ${style.bold(info.database)} on ${info.host}:${info.port} with the mysql client...`)\n const args = [\"--host\", info.host, \"--port\", String(info.port), \"--user\", info.user, \"--database\", info.database]\n if (options.execute !== undefined) args.push(`--execute=${options.execute}`)\n\n // The password never touches argv (visible in `ps`) — only the env, which child processes don't leak to other users.\n const env: NodeJS.ProcessEnv = { ...session.env, MYSQL_PWD: info.password }\n const result = await deps.runProcess(mysqlPath, args, { cwd: session.project.root, env, inherit: true })\n return result.code\n }\n\n step(`Connecting to ${style.bold(info.database)} on ${info.host}:${info.port}...`)\n\n return await withConnection(\n info,\n async (connection) => {\n if (options.execute !== undefined) {\n return executeStatement(connection, info, options.execute, { json })\n }\n return runRepl({ connection, connectionInfo: info, input: process.stdin, output: process.stdout })\n },\n { factory: deps.createConnection },\n )\n } finally {\n if (session !== undefined) await session.stop()\n }\n}\n\nasync function runAndSetExitCode(fn: () => Promise<number>): Promise<void> {\n const code = await fn()\n if (code !== 0) process.exitCode = code\n}\n\n/** Wires up `meridian db reset|seed|shell`. `meridian db` alone prints help. */\nexport function registerDbCommand(program: Command): void {\n const db = program\n .command(\"db\")\n .description(\"Manage the Meridian-managed MySQL development database: reset, seed, or open a SQL shell.\")\n\n db.action(() => {\n db.outputHelp()\n })\n\n db.command(\"reset\")\n .description(\"Drop and recreate every table in the development database (keeps the MySQL user).\")\n .option(\"--migrate\", \"run `npx prisma migrate deploy` afterwards, without asking\")\n .option(\"--seed\", \"run `npx prisma db seed` afterwards, without asking\")\n .option(\"--port <port>\", \"local port for the Cloud SQL Auth Proxy\", (value: string) => parsePortOption(value))\n .option(\"--env-file <file>\", \"project .env file to update (defaults to .env)\")\n .action(async (opts: { migrate?: boolean; seed?: boolean; port?: number; envFile?: string }) => {\n await runAndSetExitCode(() =>\n runDbReset({\n ...(opts.migrate === true ? { migrate: true } : {}),\n ...(opts.seed === true ? { seed: true } : {}),\n ...(opts.port !== undefined ? { port: opts.port } : {}),\n ...(opts.envFile !== undefined ? { envFile: opts.envFile } : {}),\n }),\n )\n })\n\n db.command(\"seed\")\n .description(\"Run `npx prisma db seed` with the Cloud SQL Auth Proxy up and DATABASE_URL set.\")\n .option(\"--port <port>\", \"local port for the Cloud SQL Auth Proxy\", (value: string) => parsePortOption(value))\n .option(\"--env-file <file>\", \"project .env file to update (defaults to .env)\")\n .passThroughOptions()\n .argument(\"[args...]\", \"extra arguments forwarded to `npx prisma db seed` (put them after `--`)\")\n .action(async (args: string[], opts: { port?: number; envFile?: string }) => {\n await runAndSetExitCode(() =>\n runDbSeed({\n ...(opts.port !== undefined ? { port: opts.port } : {}),\n ...(opts.envFile !== undefined ? { envFile: opts.envFile } : {}),\n ...(args.length > 0 ? { extraArgs: args } : {}),\n }),\n )\n })\n\n db.command(\"shell\")\n .description(\"Open a SQL shell against the development database (the `mysql` client if available, otherwise a built-in REPL).\")\n .option(\"--port <port>\", \"local port for the Cloud SQL Auth Proxy\", (value: string) => parsePortOption(value))\n .option(\"--env-file <file>\", \"project .env file to read/patch (defaults to .env)\")\n .option(\"--repl\", \"force the built-in SQL REPL even when `mysql` is on PATH\")\n .option(\"-e, --execute <sql>\", \"run one SQL statement and exit\")\n .option(\"--no-env\", \"do not patch DATABASE_URL into the project's .env file\")\n .action(async (opts: { port?: number; envFile?: string; repl?: boolean; execute?: string; env?: boolean }) => {\n await runAndSetExitCode(() =>\n runDbShell({\n ...(opts.port !== undefined ? { port: opts.port } : {}),\n ...(opts.envFile !== undefined ? { envFile: opts.envFile } : {}),\n ...(opts.repl === true ? { repl: true } : {}),\n ...(opts.execute !== undefined ? { execute: opts.execute } : {}),\n ...(opts.env === false ? { env: false } : {}),\n }),\n )\n })\n}\n","import { createRequire } from \"node:module\"\n\n/**\n * The package version, read from package.json at runtime. `../package.json`\n * resolves from both `dist/index.js` (the published bin) and `src/` (vitest),\n * so there is nothing to keep in sync.\n */\nexport const VERSION: string = (() => {\n try {\n const require = createRequire(import.meta.url)\n const pkg = require(\"../package.json\") as { version?: unknown }\n return typeof pkg.version === \"string\" ? pkg.version : \"0.0.0\"\n } catch {\n return \"0.0.0\"\n }\n})()\n\n/** Sent as the User-Agent on every API call, e.g. `meridian-cli/0.1.0 (darwin arm64)`. */\nexport const USER_AGENT = `meridian-cli/${VERSION} (${process.platform} ${process.arch})`\n","/**\n * Typed HTTP client for meridian-api's `/app/cli/*` surface. Every response is\n * validated against the zod schemas in `./api-types.js` so a malformed or\n * unexpectedly-shaped payload becomes a clear `CliError` instead of a runtime\n * crash somewhere downstream. Every failure mode (HTTP error, network error,\n * timeout, bad payload) is normalized to `CliError`/`ApiError` so command code\n * never has to deal with raw `fetch` exceptions or `ZodError`s.\n */\n\nimport { hostname as osHostname } from \"node:os\"\nimport { z, type ZodType } from \"zod\"\nimport {\n type AppSummary,\n appSummarySchema,\n type DeviceCodeResponse,\n deviceCodeResponseSchema,\n type DeviceInfoResponse,\n deviceInfoResponseSchema,\n type DeviceTokenResponse,\n deviceTokenResponseSchema,\n type DevCredentials,\n devCredentialsSchema,\n type DevDatabase,\n devDatabaseSchema,\n type Id,\n type MeResponse,\n meResponseSchema,\n type MigrationRun,\n migrationRunSchema,\n type MigrationRunInput,\n type ProxyToken,\n proxyTokenSchema,\n} from \"./api-types.js\"\nimport { ApiError, CliError, notLoggedInError, sessionExpiredError } from \"./errors.js\"\n\nconst DEFAULT_TIMEOUT_MS = 30_000\nconst DEFAULT_CLIENT_NAME = \"meridian-cli\"\n/** `command` is `max:500` server-side; `truncate` adds one ellipsis character. */\nconst MAX_MIGRATION_COMMAND_LENGTH = 499\n\nexport interface ApiClientOptions {\n /** meridian-api root, e.g. https://api.the-meridian.ai (no trailing slash, no /app suffix). */\n baseUrl: string\n token?: string\n fetchImpl?: typeof fetch\n /** Per-request timeout in ms. Default 30_000. */\n timeoutMs?: number\n /** Sent as User-Agent, e.g. \"meridian-cli/0.1.0 (darwin arm64)\". */\n userAgent?: string\n}\n\nexport interface RequestOptions {\n body?: unknown\n query?: Record<string, string | number | undefined>\n /** Attach the bearer token. Default true. */\n auth?: boolean\n headers?: Record<string, string>\n /** Return null instead of throwing on 404. */\n allow404?: boolean\n signal?: AbortSignal\n}\n\n/**\n * Thin wrapper over `fetch`. Deliberately has no interceptor/plugin system —\n * every request goes through the same `request()` method so error handling\n * stays in one place.\n */\nexport class ApiClient {\n readonly baseUrl: string\n readonly #token: string | undefined\n readonly #fetchImpl: typeof fetch\n readonly #timeoutMs: number\n readonly #userAgent: string | undefined\n\n constructor(options: ApiClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\")\n this.#token = options.token\n this.#fetchImpl = options.fetchImpl ?? fetch\n this.#timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS\n this.#userAgent = options.userAgent\n }\n\n get hasToken(): boolean {\n return this.#token !== undefined\n }\n\n /** Returns a new client carrying the given token; used right after login. */\n withToken(token: string): ApiClient {\n return new ApiClient({\n baseUrl: this.baseUrl,\n token,\n fetchImpl: this.#fetchImpl,\n timeoutMs: this.#timeoutMs,\n ...(this.#userAgent !== undefined ? { userAgent: this.#userAgent } : {}),\n })\n }\n\n /**\n * Performs one request and validates the response against `schema`. Pass\n * `null` for endpoints whose body is irrelevant (e.g. logging a migration\n * run) — the resolved value is then `undefined`.\n */\n async request<T>(\n schema: ZodType<T> | null,\n method: string,\n path: string,\n options: RequestOptions = {},\n ): Promise<T> {\n const auth = options.auth ?? true\n if (auth && this.#token === undefined) throw notLoggedInError()\n\n const url = this.#buildUrl(path, options.query)\n const headers = this.#buildHeaders(options.headers, options.body !== undefined, auth)\n const response = await this.#fetchWithTimeout(url, method, headers, options.body, options.signal)\n\n if (response.status === 404 && options.allow404 === true) {\n await response.text().catch(() => \"\")\n return null as T\n }\n\n if (!response.ok) {\n throw await toApiError(response, method, path)\n }\n\n if (schema === null) {\n await response.text().catch(() => \"\")\n return undefined as T\n }\n\n const text = await response.text().catch(() => \"\")\n const data: unknown = text.trim().length === 0 ? undefined : parseJson(text, method, path)\n return parseWithSchema(schema, data, method, path)\n }\n\n /** `POST /app/cli/device/code` — unauthenticated. */\n async requestDeviceCode(input: { clientName?: string; hostname?: string } = {}): Promise<DeviceCodeResponse> {\n return this.request(deviceCodeResponseSchema, \"POST\", \"/app/cli/device/code\", {\n auth: false,\n body: {\n client_name: input.clientName ?? DEFAULT_CLIENT_NAME,\n hostname: input.hostname ?? osHostname(),\n },\n })\n }\n\n /**\n * `POST /app/cli/device/token` — a single poll attempt. On 428/429/410/403\n * this resolves an `ApiError` whose `errorCode` is the RFC 8628-ish string\n * from the body (`authorization_pending`, `slow_down`, ...); callers branch\n * on that, not on `status`.\n */\n async pollDeviceTokenOnce(deviceCode: string): Promise<DeviceTokenResponse> {\n return this.request(deviceTokenResponseSchema, \"POST\", \"/app/cli/device/token\", {\n auth: false,\n body: { device_code: deviceCode },\n })\n }\n\n /**\n * `GET /app/cli/device/info` — the approval UI's endpoint, exposed here for\n * completeness/tests. It sits behind `auth:api` (and rejects CLI tokens), so\n * the token is attached when one is available rather than required.\n */\n async getDeviceInfo(userCode: string): Promise<DeviceInfoResponse> {\n return this.request(deviceInfoResponseSchema, \"GET\", \"/app/cli/device/info\", {\n auth: this.hasToken,\n query: { user_code: userCode },\n })\n }\n\n async getMe(): Promise<MeResponse> {\n return this.request(meResponseSchema, \"GET\", \"/app/cli/me\")\n }\n\n async listApps(orgId: Id): Promise<AppSummary[]> {\n return this.request(z.array(appSummarySchema), \"GET\", `/app/cli/orgs/${encodePathSegment(orgId)}/apps`)\n }\n\n /** Idempotent ensure/provision; may resolve with `status: \"provisioning\"` — poll `getDevDatabase` until `\"ready\"`. */\n async ensureDevDatabase(appId: Id): Promise<DevDatabase> {\n return this.request(devDatabaseSchema, \"POST\", `/app/cli/apps/${encodePathSegment(appId)}/dev-database`)\n }\n\n /** `null` when the app has no dev database provisioned yet (404). */\n async getDevDatabase(appId: Id): Promise<DevDatabase | null> {\n return this.request<DevDatabase | null>(\n devDatabaseSchema,\n \"GET\",\n `/app/cli/apps/${encodePathSegment(appId)}/dev-database`,\n { allow404: true },\n )\n }\n\n async issueCredentials(appId: Id): Promise<DevCredentials> {\n return this.request(\n devCredentialsSchema,\n \"POST\",\n `/app/cli/apps/${encodePathSegment(appId)}/dev-database/credentials`,\n )\n }\n\n async issueProxyToken(appId: Id): Promise<ProxyToken> {\n return this.request(\n proxyTokenSchema,\n \"POST\",\n `/app/cli/apps/${encodePathSegment(appId)}/dev-database/proxy-token`,\n )\n }\n\n async resetDevDatabase(appId: Id): Promise<DevDatabase> {\n return this.request(devDatabaseSchema, \"POST\", `/app/cli/apps/${encodePathSegment(appId)}/dev-database/reset`)\n }\n\n /** `command` is capped server-side at 500 characters, so a long `--` passthrough is trimmed here rather than rejected as a 422. */\n async reportMigration(appId: Id, run: MigrationRunInput): Promise<void> {\n await this.request(null, \"POST\", `/app/cli/apps/${encodePathSegment(appId)}/dev-database/migrations`, {\n body: { ...run, command: truncate(run.command, MAX_MIGRATION_COMMAND_LENGTH) },\n })\n }\n\n async listMigrations(appId: Id): Promise<MigrationRun[]> {\n return this.request(\n z.array(migrationRunSchema),\n \"GET\",\n `/app/cli/apps/${encodePathSegment(appId)}/dev-database/migrations`,\n )\n }\n\n #buildUrl(path: string, query?: Record<string, string | number | undefined>): string {\n const url = new URL(`${this.baseUrl}${path}`)\n if (query !== undefined) {\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined) url.searchParams.set(key, String(value))\n }\n }\n return url.toString()\n }\n\n #buildHeaders(extra: Record<string, string> | undefined, hasBody: boolean, auth: boolean): Record<string, string> {\n const headers: Record<string, string> = { Accept: \"application/json\" }\n if (hasBody) headers[\"Content-Type\"] = \"application/json\"\n if (auth && this.#token !== undefined) headers.Authorization = `Bearer ${this.#token}`\n if (this.#userAgent !== undefined) headers[\"User-Agent\"] = this.#userAgent\n if (extra !== undefined) Object.assign(headers, extra)\n return headers\n }\n\n async #fetchWithTimeout(\n url: string,\n method: string,\n headers: Record<string, string>,\n body: unknown,\n externalSignal: AbortSignal | undefined,\n ): Promise<Response> {\n const controller = new AbortController()\n let timedOut = false\n const onExternalAbort = (): void => controller.abort()\n\n if (externalSignal !== undefined) {\n if (externalSignal.aborted) controller.abort()\n else externalSignal.addEventListener(\"abort\", onExternalAbort, { once: true })\n }\n\n const timeoutId = setTimeout(() => {\n timedOut = true\n controller.abort()\n }, this.#timeoutMs)\n\n try {\n return await this.#fetchImpl(url, {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n signal: controller.signal,\n })\n } catch (error) {\n if (timedOut) {\n throw new CliError(`Request to the Meridian API timed out after ${this.#timeoutMs}ms.`, {\n hint: \"The API may be slow or unreachable right now; try again in a moment.\",\n cause: error,\n })\n }\n if (externalSignal?.aborted === true) throw error\n throw new CliError(`Cannot reach the Meridian API at ${this.baseUrl}.`, {\n hint: \"Check your network connection, or set MERIDIAN_API_URL if you're targeting a different environment.\",\n cause: error,\n })\n } finally {\n clearTimeout(timeoutId)\n externalSignal?.removeEventListener(\"abort\", onExternalAbort)\n }\n }\n}\n\nfunction encodePathSegment(id: Id): string {\n return encodeURIComponent(String(id))\n}\n\nfunction parseJson(text: string, method: string, path: string): unknown {\n try {\n return JSON.parse(text)\n } catch (error) {\n throw new CliError(`The Meridian API returned a non-JSON response for ${method} ${path}.`, {\n hint: \"This usually means the CLI is out of date; try upgrading @the-meridian/cli.\",\n cause: error,\n })\n }\n}\n\nfunction parseWithSchema<T>(schema: ZodType<T>, data: unknown, method: string, path: string): T {\n const result = schema.safeParse(data)\n if (result.success) return result.data\n\n const issues = result.error.issues\n .slice(0, 3)\n .map((issue) => `${issue.path.length > 0 ? issue.path.join(\".\") : \"<root>\"}: ${issue.message}`)\n .join(\"; \")\n throw new CliError(\n `The Meridian API returned an unexpected payload for ${method} ${path}: ${truncate(issues, 300)}`,\n {\n hint: \"This usually means the CLI is out of date; try upgrading @the-meridian/cli.\",\n cause: result.error,\n },\n )\n}\n\nasync function toApiError(response: Response, method: string, path: string): Promise<ApiError> {\n const text = await response.text().catch(() => \"\")\n let body: unknown\n if (text.trim().length === 0) body = undefined\n else {\n try {\n body = JSON.parse(text)\n } catch {\n body = text\n }\n }\n\n const errorCode = extractErrorCode(body)\n const message =\n extractMessage(body) ?? `${method} ${path} failed with ${response.status} ${response.statusText}`.trim()\n const hint = hintForError(response.status, errorCode)\n\n return new ApiError(message, {\n status: response.status,\n body,\n ...(errorCode !== undefined ? { errorCode } : {}),\n ...(hint !== undefined ? { hint } : {}),\n })\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined\n}\n\n/**\n * meridian-api speaks two error dialects on the CLI surface. The device-auth\n * endpoints return the raw RFC 8628 shape (`{\"error\":\"authorization_pending\"}`),\n * while everything routed through the platform's `ApiResponse` helper — 409\n * \"database isn't ready\", 403 from the `cli.token` middleware, 404 from\n * `firstOrFail()` — returns the envelope\n * `{\"success\":false,\"data\":null,\"error\":{\"code\":…,\"message\":…,\"details\":…}}`.\n * Both must yield the same `errorCode`/`message` so callers can branch on one\n * thing.\n */\nfunction envelopeError(body: unknown): Record<string, unknown> | undefined {\n const record = asRecord(body)\n return record === undefined ? undefined : asRecord(record.error)\n}\n\n/** First field error out of a Laravel validation bag, in either dialect. */\nfunction firstFieldError(bag: unknown): string | undefined {\n const fields = asRecord(bag)\n if (fields === undefined) return undefined\n for (const value of Object.values(fields)) {\n if (Array.isArray(value) && typeof value[0] === \"string\") return value[0]\n if (typeof value === \"string\") return value\n }\n return undefined\n}\n\n/**\n * A specific validation failure is more actionable than the generic message\n * wrapping it, so it wins when both are present.\n */\nfunction extractMessage(body: unknown): string | undefined {\n const record = asRecord(body)\n if (record === undefined) return undefined\n\n const envelope = envelopeError(body)\n if (envelope !== undefined) {\n const fieldError = firstFieldError(asRecord(envelope.details)?.fields)\n if (fieldError !== undefined) return fieldError\n if (typeof envelope.message === \"string\" && envelope.message.length > 0) return envelope.message\n if (typeof envelope.code === \"string\" && envelope.code.length > 0) return envelope.code\n }\n\n const fieldError = firstFieldError(record.errors)\n if (fieldError !== undefined) return fieldError\n\n if (typeof record.message === \"string\" && record.message.length > 0) return record.message\n if (typeof record.error === \"string\" && record.error.length > 0) return record.error\n return undefined\n}\n\nfunction extractErrorCode(body: unknown): string | undefined {\n const envelope = envelopeError(body)\n if (envelope !== undefined && typeof envelope.code === \"string\") return envelope.code\n\n const record = asRecord(body)\n return record !== undefined && typeof record.error === \"string\" ? record.error : undefined\n}\n\n/**\n * Hints keyed by the envelope's `error.code`, for failures whose status alone\n * is too coarse to act on. The API's own `message` is always shown (see\n * `extractMessage`) and explains what happened; these add the next step.\n *\n * Without them, a plan or quota rejection inherits the generic hint for its\n * status — telling a developer over the storage cap to \"wait for provisioning\n * to finish\", which never helps and hides the one command that does.\n */\nconst HINTS_BY_ERROR_CODE: Record<string, string> = {\n dev_database_limit_reached:\n \"Your plan does not include a development database for you on this app. Every collaborator gets their own out of the plan's allowance, so upgrading the organization's plan in the Meridian dashboard is what unlocks it.\",\n dev_database_over_storage_limit:\n \"Run `meridian db reset` to drop and recreate the schema — reset and delete stay available while you're over the limit.\",\n FEATURE_NOT_ENTITLED:\n \"Your organization's plan does not include managed development databases; upgrade it in the Meridian dashboard.\",\n}\n\nfunction hintForError(status: number, errorCode: string | undefined): string | undefined {\n if (errorCode !== undefined) {\n const byCode = HINTS_BY_ERROR_CODE[errorCode]\n if (byCode !== undefined) return byCode\n }\n\n if (status === 401) return sessionExpiredError().hint\n if (status === 403) return \"You may not have access to this organization or app; check your Meridian membership.\"\n if (status === 404) return \"Run `meridian link` to select a valid organization and app.\"\n if (status === 409) {\n return \"The development database is not ready yet. Wait for provisioning to finish, then try again — `meridian dev` polls for you.\"\n }\n if (status === 422) return \"Check the request for validation errors and try again.\"\n if (status === 429) return \"You're being rate limited by the Meridian API; wait a moment and try again.\"\n if (status >= 500) return \"This looks like a server-side failure on the Meridian API; try again shortly.\"\n return undefined\n}\n\nfunction truncate(text: string, max: number): string {\n return text.length > max ? `${text.slice(0, max)}…` : text\n}\n","/**\n * Zod schemas (and their inferred types) for every payload meridian-api's\n * `/app/cli/*` endpoints send or accept. Every object schema is `.loose()` so\n * new fields added on the Laravel side never break an older CLI, while the\n * fields the CLI actually reads are still validated.\n */\n\nimport { z } from \"zod\"\n\n/** Laravel ids are sometimes numeric, sometimes string-ish (ULIDs, etc). */\nexport const idSchema = z.union([z.number(), z.string()])\nexport type Id = z.infer<typeof idSchema>\n\nexport const cliUserSchema = z\n .object({\n id: idSchema,\n name: z.string(),\n email: z.string(),\n })\n .loose()\nexport type CliUser = z.infer<typeof cliUserSchema>\n\nexport const orgSchema = z\n .object({\n id: idSchema,\n name: z.string(),\n slug: z.string(),\n })\n .loose()\nexport type Org = z.infer<typeof orgSchema>\n\nexport const appSummarySchema = z\n .object({\n id: idSchema,\n name: z.string(),\n slug: z.string(),\n })\n .loose()\nexport type AppSummary = z.infer<typeof appSummarySchema>\n\nexport const meResponseSchema = z\n .object({\n user: cliUserSchema,\n orgs: z.array(orgSchema),\n })\n .loose()\nexport type MeResponse = z.infer<typeof meResponseSchema>\n\nexport const deviceCodeResponseSchema = z\n .object({\n device_code: z.string(),\n user_code: z.string(),\n verification_uri: z.string(),\n verification_uri_complete: z.string().optional(),\n interval: z.number().optional(),\n expires_in: z.number().optional(),\n })\n .loose()\nexport type DeviceCodeResponse = z.infer<typeof deviceCodeResponseSchema>\n\nexport const deviceTokenResponseSchema = z\n .object({\n token: z.string(),\n expires_at: z.string().optional(),\n user: cliUserSchema,\n })\n .loose()\nexport type DeviceTokenResponse = z.infer<typeof deviceTokenResponseSchema>\n\nexport const deviceInfoResponseSchema = z\n .object({\n hostname: z.string(),\n client_name: z.string(),\n created_at: z.string().optional(),\n })\n .loose()\nexport type DeviceInfoResponse = z.infer<typeof deviceInfoResponseSchema>\n\n/**\n * Known statuses are validated as a literal union, but any other string\n * is still accepted (falls back to `z.string()`) so an unexpected status\n * added server-side surfaces as data instead of crashing the CLI.\n */\nexport const devDatabaseStatusSchema = z.union([z.enum([\"provisioning\", \"ready\", \"error\"]), z.string()])\nexport type DevDatabaseStatus = z.infer<typeof devDatabaseStatusSchema>\n\n/**\n * Mirrors `DevDatabaseResource`. Everything the API declares nullable is\n * `.nullish()` rather than `.optional()`: an explicit `null` (which the\n * resource does send — `instance_connection_name` and `region` are nullable\n * columns, and `error_message` is null unless `status` is `error`) fails an\n * `.optional()` check and would surface as a bogus \"unexpected payload\" error.\n */\nexport const devDatabaseSchema = z\n .object({\n id: idSchema,\n status: devDatabaseStatusSchema,\n database: z.string(),\n /** Nullish for an API older than per-developer Prisma shadow databases. */\n shadow_database: z.string().nullish(),\n mysql_user: z.string(),\n instance_connection_name: z.string().nullish(),\n region: z.string().nullish(),\n created_at: z.string().nullish(),\n /** Set by the API only while `status` is `error`; surfaced verbatim to the developer. */\n error_message: z.string().nullish(),\n })\n .loose()\nexport type DevDatabase = z.infer<typeof devDatabaseSchema>\n\nexport const devCredentialsSchema = z\n .object({\n host: z.string(),\n port: z.coerce.number(),\n database: z.string(),\n /**\n * The developer's Prisma shadow database, reachable with these same\n * credentials. Nullish for an API older than shadow databases, in which\n * case no SHADOW_DATABASE_URL is written.\n */\n shadow_database: z.string().nullish(),\n username: z.string(),\n password: z.string(),\n expires_at: z.string().nullish(),\n /** Echoed from the (nullable) dev-database column, so it can be null. */\n instance_connection_name: z.string().nullish(),\n })\n .loose()\nexport type DevCredentials = z.infer<typeof devCredentialsSchema>\n\nexport const proxyTokenSchema = z\n .object({\n access_token: z.string(),\n expires_at: z.string().nullish(),\n instance_connection_name: z.string().nullish(),\n })\n .loose()\nexport type ProxyToken = z.infer<typeof proxyTokenSchema>\n\nexport const migrationRunInputSchema = z.object({\n command: z.string(),\n status: z.enum([\"success\", \"failed\", \"rolled_back\"]),\n started_at: z.string(),\n finished_at: z.string(),\n output_excerpt: z.string().optional(),\n})\nexport type MigrationRunInput = z.infer<typeof migrationRunInputSchema>\n\n/** Mirrors `DevDatabaseMigrationResource`, whose timestamps and excerpt are all nullable columns. */\nexport const migrationRunSchema = z\n .object({\n id: idSchema.nullish(),\n command: z.string(),\n status: z.string(),\n started_at: z.string().nullish(),\n finished_at: z.string().nullish(),\n output_excerpt: z.string().nullish(),\n created_at: z.string().nullish(),\n })\n .loose()\nexport type MigrationRun = z.infer<typeof migrationRunSchema>\n\n/**\n * The `error` codes `POST /app/cli/device/token` returns. The first four are\n * the contract's polling codes (428/429/410/403); `invalid_grant` (404) is the\n * API's answer for a device code that is unknown or already exchanged.\n */\nexport type DeviceErrorCode =\n | \"authorization_pending\"\n | \"slow_down\"\n | \"expired_token\"\n | \"access_denied\"\n | \"invalid_grant\"\n","/**\n * Error types shared by every command.\n *\n * A `CliError` is an *expected* failure: the top-level handler prints\n * `message` (plus `hint` when present) and exits with `exitCode` instead of\n * dumping a stack trace. Anything else that escapes a command is a bug and is\n * reported with its stack.\n */\n\nexport interface CliErrorOptions {\n /** Actionable next step, e.g. \"Run `meridian login` to authenticate.\" */\n hint?: string\n /** Process exit code. Defaults to 1. */\n exitCode?: number\n cause?: unknown\n}\n\nexport class CliError extends Error {\n readonly hint: string | undefined\n readonly exitCode: number\n\n constructor(message: string, options: CliErrorOptions = {}) {\n super(message, options.cause !== undefined ? { cause: options.cause } : undefined)\n this.name = \"CliError\"\n this.hint = options.hint\n this.exitCode = options.exitCode ?? 1\n }\n}\n\n/** An error envelope returned by meridian-api. */\nexport class ApiError extends CliError {\n readonly status: number\n readonly body: unknown\n /** `error` field from the response body, e.g. \"authorization_pending\". */\n readonly errorCode: string | undefined\n\n constructor(\n message: string,\n init: { status: number; body?: unknown; errorCode?: string } & CliErrorOptions,\n ) {\n super(message, init)\n this.name = \"ApiError\"\n this.status = init.status\n this.body = init.body\n this.errorCode = init.errorCode\n }\n}\n\nexport function isCliError(error: unknown): error is CliError {\n return error instanceof CliError\n}\n\nexport function isApiError(error: unknown): error is ApiError {\n return error instanceof ApiError\n}\n\n/** No CLI token in ~/.meridian/config.json. */\nexport function notLoggedInError(): CliError {\n return new CliError(\"You are not logged in to Meridian.\", {\n hint: \"Run `meridian login` to authenticate this machine.\",\n })\n}\n\n/** No .meridian/project.json in the current directory tree. */\nexport function notLinkedError(): CliError {\n return new CliError(\"This project is not linked to a Meridian app.\", {\n hint: \"Run `meridian link` in your project root to pick an organization and app.\",\n })\n}\n\n/** A 401 from the API means the stored CLI token is expired or revoked. */\nexport function sessionExpiredError(cause?: unknown): CliError {\n return new CliError(\"Your Meridian CLI token is no longer valid (401).\", {\n hint: \"Run `meridian login` again to issue a fresh token.\",\n ...(cause !== undefined ? { cause } : {}),\n })\n}\n\n/**\n * A prompt was needed but stdin is not a TTY (CI, piped input). Names the\n * escape hatch so scripts can supply the answer up front.\n */\nexport function nonInteractiveError(what: string, override: string): CliError {\n return new CliError(`Cannot prompt for ${what} in a non-interactive shell.`, {\n hint: `Set ${override} to answer it up front.`,\n })\n}\n\n/** Human-readable one-liner for any thrown value. */\nexport function describeError(error: unknown): string {\n if (error instanceof Error) return error.message\n if (typeof error === \"string\") return error\n return String(error)\n}\n","/**\n * User-level state at `~/.meridian/config.json` (relocatable via\n * `MERIDIAN_HOME` for tests). Holds the long-lived scoped CLI token issued by\n * `meridian login`, so the file is created/rewritten with 0o600 permissions.\n */\n\nimport { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\"\nimport { dirname } from \"node:path\"\nimport { z } from \"zod\"\nimport { CliError, notLoggedInError } from \"./errors.js\"\nimport { globalConfigPath } from \"./paths.js\"\n\n/** meridian-api root. CLI endpoints resolve to `${base}/app/cli/...`. */\nexport const DEFAULT_API_BASE_URL = \"https://api.the-meridian.ai\"\n\nexport interface ConfigUser {\n id: number | string\n name: string\n email: string\n}\n\nexport interface GlobalConfig {\n api_base_url?: string\n token?: string\n token_expires_at?: string\n user?: ConfigUser\n}\n\nconst configUserSchema = z.object({\n id: z.union([z.number(), z.string()]),\n name: z.string(),\n email: z.string(),\n})\n\n/** Zod schema for the file; unknown keys are preserved. */\nexport const globalConfigSchema = z\n .object({\n api_base_url: z.string().exactOptional(),\n token: z.string().exactOptional(),\n token_expires_at: z.string().exactOptional(),\n user: configUserSchema.exactOptional(),\n })\n .loose() satisfies z.ZodType<GlobalConfig>\n\n/** `{}` when the file does not exist. Throws a CliError when it is unreadable/corrupt. */\nexport function readConfig(): GlobalConfig {\n const path = globalConfigPath()\n let raw: string\n try {\n raw = readFileSync(path, \"utf8\")\n } catch (error) {\n if (isEnoent(error)) return {}\n throw new CliError(`Could not read ${path}.`, {\n hint: \"Check the file's permissions, then run `meridian login` again.\",\n cause: error,\n })\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (error) {\n throw new CliError(`${path} is not valid JSON.`, {\n hint: \"Fix or delete the file, then run `meridian login` again.\",\n cause: error,\n })\n }\n\n const result = globalConfigSchema.safeParse(parsed)\n if (!result.success) {\n throw new CliError(`${path} does not look like a Meridian config file.`, {\n hint: \"Fix or delete the file, then run `meridian login` again.\",\n cause: result.error,\n })\n }\n return result.data\n}\n\n/** Atomic write: mkdir 0o700, write temp file 0o600, rename, chmod 600. */\nexport function writeConfig(config: GlobalConfig): void {\n const path = globalConfigPath()\n const dir = dirname(path)\n mkdirSync(dir, { recursive: true, mode: 0o700 })\n\n const tmpPath = `${path}.tmp`\n writeFileSync(tmpPath, `${JSON.stringify(config, null, 2)}\\n`, { mode: 0o600 })\n renameSync(tmpPath, path)\n chmodSync(path, 0o600)\n}\n\n/** Shallow merge onto the current file contents; returns the merged result. */\nexport function updateConfig(patch: Partial<GlobalConfig>): GlobalConfig {\n const merged = { ...readConfig(), ...patch }\n writeConfig(merged)\n return merged\n}\n\n/** Drops token/token_expires_at/user, keeps api_base_url. Returns true if a token was present. */\nexport function clearAuth(): boolean {\n const current = readConfig()\n const hadToken = current.token !== undefined\n const next: GlobalConfig = {\n ...(current.api_base_url !== undefined ? { api_base_url: current.api_base_url } : {}),\n }\n writeConfig(next)\n return hadToken\n}\n\n/**\n * Strips a trailing slash and a trailing `/app` segment. The API client builds\n * paths that already start with `/app/cli/...`, and the dashboard's\n * `NEXT_PUBLIC_API_BASE_URL` includes `/app` — so a copy-pasted dashboard base\n * URL keeps working instead of producing `/app/app/cli`. Any other prefix (e.g.\n * `/api`) is preserved, since it may be a real mount point.\n */\nexport function normalizeApiBaseUrl(url: string): string {\n return url.trim().replace(/\\/+$/, \"\").replace(/\\/app$/, \"\")\n}\n\n/**\n * Precedence: explicit override (a --api-url flag) > MERIDIAN_API_URL env >\n * config file api_base_url > DEFAULT_API_BASE_URL. Normalized (see below).\n */\nexport function resolveApiBaseUrl(override?: string): string {\n if (override !== undefined && override !== \"\") return normalizeApiBaseUrl(override)\n\n const envValue = process.env.MERIDIAN_API_URL\n if (envValue !== undefined && envValue !== \"\") return normalizeApiBaseUrl(envValue)\n\n const config = readConfig()\n if (config.api_base_url !== undefined && config.api_base_url !== \"\") {\n return normalizeApiBaseUrl(config.api_base_url)\n }\n\n return normalizeApiBaseUrl(DEFAULT_API_BASE_URL)\n}\n\nexport interface AuthState {\n token: string\n tokenExpiresAt?: string\n user?: ConfigUser\n}\n\n/** null when there is no stored token. */\nexport function getAuth(): AuthState | null {\n const config = readConfig()\n if (config.token === undefined) return null\n return {\n token: config.token,\n ...(config.token_expires_at !== undefined ? { tokenExpiresAt: config.token_expires_at } : {}),\n ...(config.user !== undefined ? { user: config.user } : {}),\n }\n}\n\n/** Throws notLoggedInError() when absent; throws a CliError hinting re-login when token_expires_at is in the past. */\nexport function requireToken(): string {\n const auth = getAuth()\n if (auth === null) throw notLoggedInError()\n\n if (auth.tokenExpiresAt !== undefined) {\n const expiry = new Date(auth.tokenExpiresAt).getTime()\n if (!Number.isNaN(expiry) && expiry < Date.now()) {\n throw new CliError(\"Your Meridian CLI token has expired.\", {\n hint: \"Run `meridian login` again to issue a fresh token.\",\n })\n }\n }\n\n return auth.token\n}\n\nfunction isEnoent(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\"\n}\n","/**\n * Every path the CLI touches, in one place.\n *\n * `MERIDIAN_HOME` relocates the whole user-level state directory — the tests\n * set it to a temp dir so nothing ever writes to the developer's real\n * ~/.meridian.\n */\n\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\n\n/** User-level state directory. Defaults to ~/.meridian. */\nexport function meridianHome(): string {\n const override = process.env.MERIDIAN_HOME\n if (override !== undefined && override !== \"\") return override\n return join(homedir(), \".meridian\")\n}\n\n/** Global config: token, api_base_url, cached user. chmod 600. */\nexport function globalConfigPath(): string {\n return join(meridianHome(), \"config.json\")\n}\n\n/** Cache directory for the downloaded cloud-sql-proxy binary. */\nexport function proxyBinDir(): string {\n return join(meridianHome(), \"bin\")\n}\n\n/** Per-project state directory: <root>/.meridian. */\nexport function projectStateDir(root: string): string {\n return join(root, \".meridian\")\n}\n\n/** Committed-safe project link file: <root>/.meridian/project.json. */\nexport function projectConfigPath(root: string): string {\n return join(projectStateDir(root), \"project.json\")\n}\n\n/** Database snapshots taken by `meridian migrate`: <root>/.meridian/snapshots. */\nexport function snapshotsDir(root: string): string {\n return join(projectStateDir(root), \"snapshots\")\n}\n\n/** The project's dotenv file that DATABASE_URL is written into. */\nexport function envFilePath(root: string, fileName = \".env\"): string {\n return join(root, fileName)\n}\n","/**\n * Global flags parsed by the root command, made available to every subcommand\n * without threading them through each action signature. The root command calls\n * `setGlobalOptions` once in its `preAction` hook.\n */\n\nexport interface GlobalOptions {\n /** `--api-url`: overrides MERIDIAN_API_URL and the stored config. */\n apiUrl?: string\n /** `--json`: machine-readable result on stdout, no human logs. */\n json: boolean\n quiet: boolean\n verbose: boolean\n /** `--no-color`; undefined means \"decide from the terminal\". */\n color?: boolean\n /** `--yes`: pre-approve confirmation prompts. */\n yes: boolean\n /** `--no-input`: never prompt, fail instead. */\n interactive?: boolean\n /** `--cwd`: run as if the CLI had been started in this directory. */\n cwd?: string\n}\n\nconst defaults: GlobalOptions = {\n json: false,\n quiet: false,\n verbose: false,\n yes: false,\n}\n\nlet current: GlobalOptions = { ...defaults }\n\nexport function setGlobalOptions(options: Partial<GlobalOptions>): void {\n current = { ...current, ...options }\n}\n\nexport function getGlobalOptions(): Readonly<GlobalOptions> {\n return current\n}\n\nexport function resetGlobalOptions(): void {\n current = { ...defaults }\n}\n\nexport function isJsonOutput(): boolean {\n return current.json\n}\n\n/** Directory commands should treat as the project location. */\nexport function workingDirectory(): string {\n return current.cwd ?? process.cwd()\n}\n","import { USER_AGENT } from \"../version.js\"\nimport { ApiClient } from \"./api.js\"\nimport { getAuth, resolveApiBaseUrl } from \"./config.js\"\nimport { getGlobalOptions } from \"./context.js\"\nimport { notLoggedInError } from \"./errors.js\"\n\nexport interface CreateApiClientOptions {\n /** Fail fast when there is no stored token. Default true. */\n requireAuth?: boolean\n /** Overrides --api-url / MERIDIAN_API_URL / the stored config. */\n apiUrl?: string\n /** Use this token instead of the stored one (used right after login). */\n token?: string\n fetchImpl?: typeof fetch\n}\n\n/**\n * The single place commands get an API client from: resolves the base URL and\n * the stored CLI token, and turns \"no token\" into the actionable\n * `meridian login` error before any request is attempted.\n */\nexport function createApiClient(options: CreateApiClientOptions = {}): ApiClient {\n const requireAuth = options.requireAuth ?? true\n const baseUrl = resolveApiBaseUrl(options.apiUrl ?? getGlobalOptions().apiUrl)\n const token = options.token ?? getAuth()?.token\n\n if (requireAuth && token === undefined) throw notLoggedInError()\n\n return new ApiClient({\n baseUrl,\n userAgent: USER_AGENT,\n ...(token !== undefined ? { token } : {}),\n ...(options.fetchImpl !== undefined ? { fetchImpl: options.fetchImpl } : {}),\n })\n}\n","/**\n * Reaching the dev database through the local Cloud SQL Auth Proxy: building\n * connection info from API credentials, opening/closing connections, polling\n * until the backend answers queries, and turning mysql2 errors into\n * actionable `CliError`s that never leak the password.\n */\n\nimport { CliError, describeError } from \"../errors.js\"\n\n/** Everything needed to reach the dev DB through the local proxy. */\nexport interface DbConnectionInfo {\n host: string\n port: number\n user: string\n password: string\n database: string\n}\n\n/**\n * Minimal surface of a mysql2 promise connection that this CLI uses, so tests\n * can inject a fake without pulling in mysql2's types.\n */\nexport interface SqlConnection {\n query(sql: string): Promise<unknown>\n end(): Promise<void>\n destroy?(): void\n}\n\nexport type ConnectionFactory = (\n info: DbConnectionInfo,\n options?: { multipleStatements?: boolean },\n) => Promise<SqlConnection>\n\n/**\n * The API returns `host`/`port` placeholders for the real Cloud SQL instance;\n * every connection actually goes through the proxy this CLI spawns locally.\n */\nexport function connectionInfoFromCredentials(\n credentials: { username: string; password: string; database: string },\n proxy: { host?: string; port: number },\n): DbConnectionInfo {\n return {\n host: proxy.host ?? \"127.0.0.1\",\n port: proxy.port,\n user: credentials.username,\n password: credentials.password,\n database: credentials.database,\n }\n}\n\n/** Real factory over mysql2/promise, imported lazily so it isn't paid for on every command. */\nexport const createSqlConnection: ConnectionFactory = async (info, options) => {\n const { createConnection } = await import(\"mysql2/promise\")\n const connection = await createConnection({\n host: info.host,\n port: info.port,\n user: info.user,\n password: info.password,\n database: info.database,\n ...(options?.multipleStatements !== undefined ? { multipleStatements: options.multipleStatements } : {}),\n })\n return connection as unknown as SqlConnection\n}\n\n/** Closes a connection, falling back to a forceful destroy so a close failure never masks the real error. */\nasync function closeQuietly(connection: SqlConnection): Promise<void> {\n try {\n await connection.end()\n } catch {\n connection.destroy?.()\n }\n}\n\n/** Runs `fn` with a connection and always closes it, even on throw. */\nexport async function withConnection<T>(\n info: DbConnectionInfo,\n fn: (connection: SqlConnection) => Promise<T>,\n options: { multipleStatements?: boolean; factory?: ConnectionFactory } = {},\n): Promise<T> {\n const factory = options.factory ?? createSqlConnection\n const factoryOptions = options.multipleStatements !== undefined ? { multipleStatements: options.multipleStatements } : {}\n const connection = await factory(info, factoryOptions)\n try {\n return await fn(connection)\n } finally {\n await closeQuietly(connection)\n }\n}\n\n/**\n * Polls `SELECT 1` until the database answers. The proxy accepts TCP before\n * the backend is reachable, so a successful port probe is not enough.\n */\nexport async function waitForDatabase(\n info: DbConnectionInfo,\n options: {\n timeoutMs?: number\n intervalMs?: number\n factory?: ConnectionFactory\n sleep?: (ms: number) => Promise<void>\n now?: () => number\n } = {},\n): Promise<void> {\n const timeoutMs = options.timeoutMs ?? 30_000\n const intervalMs = options.intervalMs ?? 500\n const factory = options.factory ?? createSqlConnection\n const sleep = options.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)))\n const now = options.now ?? Date.now\n\n const deadline = now() + timeoutMs\n let lastError: unknown\n\n for (;;) {\n try {\n const connection = await factory(info)\n try {\n await connection.query(\"SELECT 1\")\n } finally {\n await closeQuietly(connection)\n }\n return\n } catch (error) {\n lastError = error\n }\n\n if (now() >= deadline) throw toDatabaseError(lastError, info)\n await sleep(intervalMs)\n }\n}\n\nfunction extractErrorCode(error: unknown): string | undefined {\n if (typeof error === \"object\" && error !== null && \"code\" in error) {\n const code = (error as { code?: unknown }).code\n if (typeof code === \"string\") return code\n }\n return undefined\n}\n\n/** Removes every occurrence of the password from a message so it can never be echoed back. */\nfunction redactPassword(text: string, password: string): string {\n if (password === \"\") return text\n return text.split(password).join(\"***\")\n}\n\n/** Turns a mysql2 error into an actionable CliError (never leaks the password). */\nexport function toDatabaseError(error: unknown, info: DbConnectionInfo): CliError {\n const target = `${info.host}:${info.port}/${info.database}`\n const code = extractErrorCode(error)\n\n const build = (message: string, hint?: string): CliError =>\n new CliError(redactPassword(message, info.password), {\n ...(hint !== undefined ? { hint: redactPassword(hint, info.password) } : {}),\n cause: error,\n })\n\n if (code === \"ER_ACCESS_DENIED_ERROR\") {\n return build(\n `Access denied connecting to ${target} as \"${info.user}\".`,\n \"Database credentials are short-lived and rotate automatically — run `meridian dev` again to fetch fresh ones.\",\n )\n }\n\n if (code === \"ER_BAD_DB_ERROR\") {\n return build(\n `Database \"${info.database}\" does not exist on ${target}.`,\n \"Run `meridian db reset` to recreate it.\",\n )\n }\n\n if (code === \"ECONNREFUSED\") {\n return build(\n `Could not reach ${target} (${code}).`,\n \"Nothing is listening on that port. `meridian dev` and `meridian migrate` start the Cloud SQL Auth Proxy for you; start it first if you are connecting by hand.\",\n )\n }\n\n // The port answered but MySQL never completed a handshake, so the proxy is up\n // and the problem is between it and Cloud SQL.\n if (code === \"ETIMEDOUT\" || code === \"PROTOCOL_SEQUENCE_TIMEOUT\") {\n return build(\n `Timed out waiting for MySQL at ${target} (${code}).`,\n \"The proxy is listening but the database never answered. Check that your network allows outbound connections to Cloud SQL (VPN, firewall, proxy), then retry with --verbose to see the proxy's own log output.\",\n )\n }\n\n const detail = code ?? describeError(error)\n return build(`Database error connecting to ${target} as \"${info.user}\": ${detail}`)\n}\n","/**\n * The CLI's only channel for talking to a human or to a machine consumer.\n *\n * Design rule every command follows: human-readable output goes to stderr;\n * stdout is reserved for machine-readable payloads (`--json`, `db shell`\n * query rows). That way `meridian whoami --json | jq` always works, and\n * piping/redirecting stdout never captures a progress spinner by accident.\n */\n\nimport pc from \"picocolors\"\nimport { describeError, isApiError, isCliError } from \"./errors.js\"\nimport type { CliError } from \"./errors.js\"\n\nexport interface OutputStreams {\n out: NodeJS.WritableStream\n err: NodeJS.WritableStream\n}\n\nexport interface OutputMode {\n /** --json: suppress human logs and spinners entirely. */\n json: boolean\n /** --quiet: only warnings and errors. */\n quiet: boolean\n /** --verbose: include debug lines. */\n verbose: boolean\n /** Colors enabled (respects NO_COLOR / FORCE_COLOR / non-TTY). */\n color: boolean\n}\n\ninterface OutputState {\n mode: OutputMode\n streams: OutputStreams\n}\n\nlet state: OutputState | undefined\n\nfunction defaultStreams(): OutputStreams {\n return { out: process.stdout, err: process.stderr }\n}\n\nfunction computeDefaultColor(streams: OutputStreams): boolean {\n return Boolean(\n !process.env.NO_COLOR &&\n (process.env.FORCE_COLOR ? true : Boolean((streams.err as NodeJS.WriteStream).isTTY)),\n )\n}\n\nfunction getState(): OutputState {\n if (state === undefined) {\n const streams = defaultStreams()\n state = {\n streams,\n mode: { json: false, quiet: false, verbose: false, color: computeDefaultColor(streams) },\n }\n }\n return state\n}\n\n/** Process-wide mode, configured once by the root command from its global flags. */\nexport function configureOutput(options: Partial<OutputMode> & { streams?: OutputStreams }): void {\n const current = getState()\n const streamsChanged = options.streams !== undefined\n const streams = options.streams ?? current.streams\n const color = options.color ?? (streamsChanged ? computeDefaultColor(streams) : current.mode.color)\n\n state = {\n streams,\n mode: {\n json: options.json ?? current.mode.json,\n quiet: options.quiet ?? current.mode.quiet,\n verbose: options.verbose ?? current.mode.verbose,\n color,\n },\n }\n}\n\nexport function getOutputMode(): Readonly<OutputMode> {\n return { ...getState().mode }\n}\n\n/** Test helper: resets mode and streams to the defaults. */\nexport function resetOutput(): void {\n state = undefined\n}\n\nfunction colors(): ReturnType<typeof pc.createColors> {\n return pc.createColors(getOutputMode().color)\n}\n\n/** Style helpers so commands never import picocolors directly. */\nexport const style = {\n bold(s: string): string {\n return colors().bold(s)\n },\n dim(s: string): string {\n return colors().dim(s)\n },\n cyan(s: string): string {\n return colors().cyan(s)\n },\n green(s: string): string {\n return colors().green(s)\n },\n yellow(s: string): string {\n return colors().yellow(s)\n },\n red(s: string): string {\n return colors().red(s)\n },\n /** Highlights a command the user should run, e.g. `meridian login`. */\n command(s: string): string {\n return colors().cyan(colors().bold(s))\n },\n /** Highlights a path or URL. */\n path(s: string): string {\n return colors().underline(s)\n },\n}\n\n/** Wraps `` `backticked` `` spans in `style.command` so hints read like docs. */\nfunction highlightBackticks(message: string): string {\n return message.replace(/`([^`]+)`/g, (_match, code: string) => style.command(code))\n}\n\nfunction indentLines(message: string, prefix: string): string {\n return message\n .split(\"\\n\")\n .map((line) => `${prefix}${line}`)\n .join(\"\\n\")\n}\n\nfunction suppressed(): boolean {\n const mode = getOutputMode()\n return mode.json || mode.quiet\n}\n\nfunction writeErr(text: string): void {\n getState().streams.err.write(text)\n}\n\nfunction writeErrLine(text: string): void {\n writeErr(`${text}\\n`)\n}\n\n// Log helpers — all write to stderr, all no-ops in json mode (except error/warn, which still print).\n\nexport function log(message = \"\"): void {\n if (suppressed()) return\n writeErrLine(message)\n}\n\nexport function step(message: string): void {\n if (suppressed()) return\n writeErrLine(`${colors().cyan(\"→\")} ${message}`)\n}\n\nexport function success(message: string): void {\n if (suppressed()) return\n writeErrLine(`${colors().green(\"✔\")} ${message}`)\n}\n\nexport function warn(message: string): void {\n writeErrLine(`${colors().yellow(\"⚠\")} ${message}`)\n}\n\nexport function error(message: string): void {\n writeErrLine(`${colors().red(\"✖\")} ${message}`)\n}\n\nexport function debug(message: string): void {\n const mode = getOutputMode()\n if (suppressed() || !mode.verbose) return\n writeErrLine(colors().dim(`· ${message}`))\n}\n\n/** Indented continuation lines, e.g. key/value details under a step. */\nexport function detail(message: string): void {\n if (suppressed()) return\n writeErrLine(indentLines(message, \" \"))\n}\n\n/** Like `detail`, but always prints — used by `reportError`, whose human line must survive --json/--quiet. */\nfunction detailAlways(message: string): void {\n writeErrLine(indentLines(message, \" \"))\n}\n\n/** Aligned \" key value\" block for whoami/link summaries. */\nexport function keyValues(entries: Array<[string, string]>): void {\n if (suppressed()) return\n if (entries.length === 0) return\n const maxKeyLength = Math.max(...entries.map(([key]) => key.length))\n for (const [key, value] of entries) {\n writeErrLine(` ${colors().dim(key.padEnd(maxKeyLength))} ${value}`)\n }\n}\n\n/** A boxed/indented actionable hint, e.g. \"Run `meridian login`\". Backticked spans are highlighted. */\nexport function hint(message: string): void {\n writeErrLine(indentLines(highlightBackticks(message), ` ${colors().dim(\"›\")} `))\n}\n\n/** stdout, `JSON.stringify(value, null, 2)` + newline. The only stdout writer for commands. */\nexport function printJson(value: unknown): void {\n getState().streams.out.write(`${JSON.stringify(value, null, 2)}\\n`)\n}\n\n/** stdout, raw (for `db shell` output). */\nexport function printLine(message: string): void {\n getState().streams.out.write(`${message}\\n`)\n}\n\nexport interface Spinner {\n start(text?: string): Spinner\n /** Replace the text while running. */\n update(text: string): Spinner\n succeed(text?: string): void\n fail(text?: string): void\n /** Stop without a mark (e.g. before handing the terminal to a child process). */\n stop(): void\n readonly text: string\n}\n\nconst SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"]\nconst SPINNER_INTERVAL_MS = 80\nconst HIDE_CURSOR = \"\\u001B[?25l\"\nconst SHOW_CURSOR = \"\\u001B[?25h\"\nconst CLEAR_LINE = \"\\r\\u001B[K\"\n\nclass SpinnerImpl implements Spinner {\n #text: string\n #timer: NodeJS.Timeout | undefined\n #frame = 0\n #running = false\n\n constructor(text: string) {\n this.#text = text\n }\n\n get text(): string {\n return this.#text\n }\n\n start(text?: string): Spinner {\n if (text !== undefined) this.#text = text\n if (getOutputMode().json || this.#running) return this\n this.#running = true\n\n if (!this.#animated()) {\n this.#writeLine(`${colors().cyan(\"→\")} ${this.#text}`)\n return this\n }\n\n this.#writeRaw(HIDE_CURSOR)\n this.#render()\n this.#timer = setInterval(() => {\n this.#frame = (this.#frame + 1) % SPINNER_FRAMES.length\n this.#render()\n }, SPINNER_INTERVAL_MS)\n this.#timer.unref()\n return this\n }\n\n update(text: string): Spinner {\n this.#text = text\n if (getOutputMode().json || !this.#running || !this.#animated()) return this\n this.#render()\n return this\n }\n\n succeed(text?: string): void {\n this.#finish(colors().green(\"✔\"), text)\n }\n\n fail(text?: string): void {\n this.#finish(colors().red(\"✖\"), text)\n }\n\n stop(): void {\n if (!this.#running) return\n this.#clearTimer()\n if (this.#animated()) {\n this.#writeRaw(CLEAR_LINE)\n this.#writeRaw(SHOW_CURSOR)\n }\n this.#running = false\n }\n\n #finish(mark: string, text?: string): void {\n if (text !== undefined) this.#text = text\n if (getOutputMode().json) {\n this.#running = false\n return\n }\n const wasAnimated = this.#running && this.#animated()\n this.#clearTimer()\n if (wasAnimated) {\n this.#writeRaw(CLEAR_LINE)\n this.#writeRaw(SHOW_CURSOR)\n }\n this.#writeLine(`${mark} ${this.#text}`)\n this.#running = false\n }\n\n #clearTimer(): void {\n if (this.#timer !== undefined) {\n clearInterval(this.#timer)\n this.#timer = undefined\n }\n }\n\n #render(): void {\n const frame = SPINNER_FRAMES[this.#frame] ?? SPINNER_FRAMES[0]\n const line = this.#truncate(`${colors().cyan(frame ?? \"\")} ${this.#text}`)\n this.#writeRaw(`${CLEAR_LINE}${line}`)\n }\n\n #truncate(line: string): string {\n const columns = this.#columns()\n if (columns === undefined || line.length <= columns) return line\n return line.slice(0, Math.max(0, columns - 1))\n }\n\n #columns(): number | undefined {\n const stream = getState().streams.err as NodeJS.WriteStream\n return typeof stream.columns === \"number\" ? stream.columns : undefined\n }\n\n /** Full braille animation only makes sense on a TTY, outside quiet mode. */\n #animated(): boolean {\n const stream = getState().streams.err as NodeJS.WriteStream\n return stream.isTTY === true && !getOutputMode().quiet\n }\n\n #writeLine(text: string): void {\n this.#writeRaw(`${text}\\n`)\n }\n\n #writeRaw(text: string): void {\n getState().streams.err.write(text)\n }\n}\n\n/**\n * Braille spinner on a TTY; a single \"→ text\" line (and a final mark) when the\n * stream is not a TTY, in quiet mode, or in json mode, so CI logs stay readable.\n */\nexport function spinner(text: string): Spinner {\n return new SpinnerImpl(text)\n}\n\n/** Runs `fn` with a spinner, succeeding/failing automatically. Returns fn's value. */\nexport async function withSpinner<T>(\n text: string,\n fn: (spinner: Spinner) => Promise<T>,\n options: { success?: string | ((value: T) => string); fail?: string } = {},\n): Promise<T> {\n const active = spinner(text).start()\n try {\n const value = await fn(active)\n const successText = typeof options.success === \"function\" ? options.success(value) : options.success\n active.succeed(successText)\n return value\n } catch (err) {\n active.fail(options.fail)\n throw err\n }\n}\n\ninterface JsonError {\n message: string\n hint?: string\n status?: number\n}\n\nfunction buildJsonError(err: CliError): JsonError {\n const payload: JsonError = { message: err.message }\n if (err.hint !== undefined) payload.hint = err.hint\n if (isApiError(err)) payload.status = err.status\n return payload\n}\n\nfunction truncate(text: string, max: number): string {\n return text.length > max ? `${text.slice(0, max)}…` : text\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value)\n } catch {\n return String(value)\n }\n}\n\n/**\n * Prints a CliError the way the top-level handler should: \"✖ message\", then the\n * hint, then (verbose only) the cause/stack. Returns the exit code to use.\n */\nexport function reportError(err: unknown): number {\n const mode = getOutputMode()\n\n if (isApiError(err)) {\n error(err.message)\n if (err.hint !== undefined) hint(err.hint)\n detailAlways(`status: ${err.status}`)\n if (mode.verbose && err.body !== undefined) detailAlways(truncate(safeStringify(err.body), 500))\n if (mode.json) printJson({ error: buildJsonError(err) })\n return err.exitCode\n }\n\n if (isCliError(err)) {\n error(err.message)\n if (err.hint !== undefined) hint(err.hint)\n if (mode.verbose && err.stack !== undefined) detailAlways(err.stack)\n if (mode.json) printJson({ error: buildJsonError(err) })\n return err.exitCode\n }\n\n const message = describeError(err)\n error(message)\n if (err instanceof Error && err.stack !== undefined) detailAlways(err.stack)\n if (mode.json) printJson({ error: { message } })\n return 1\n}\n","/**\n * Validation for numeric command flags. `Number(value)` quietly yields `NaN`\n * for a typo like `--port 300O`, which would otherwise surface much later as a\n * confusing proxy or port-scan failure.\n */\n\nimport { CliError } from \"./errors.js\"\n\nexport interface IntegerOptionRange {\n min?: number\n max?: number\n}\n\n/** Parses an integer flag, or returns undefined when the flag was not given. */\nexport function parseIntegerOption(\n raw: string | undefined,\n flag: string,\n range: IntegerOptionRange = {},\n): number | undefined {\n if (raw === undefined) return undefined\n\n const value = Number(raw)\n const { min, max } = range\n const isValid =\n Number.isInteger(value) && (min === undefined || value >= min) && (max === undefined || value <= max)\n\n if (!isValid) {\n const bounds =\n min !== undefined && max !== undefined\n ? ` between ${min} and ${max}`\n : min !== undefined\n ? ` of at least ${min}`\n : \"\"\n throw new CliError(`${flag} expects a whole number${bounds}, but got \"${raw}\".`, {\n hint: `Pass a valid value, e.g. \\`${flag} ${min ?? 1}\\`.`,\n })\n }\n\n return value\n}\n\n/** Parses a TCP port flag. */\nexport function parsePortOption(raw: string | undefined, flag = \"--port\"): number | undefined {\n return parseIntegerOption(raw, flag, { min: 1, max: 65535 })\n}\n","/**\n * Thin wrapper over `@inquirer/prompts` that gives every prompt a\n * non-interactive escape hatch: a command flag or an env var. `meridian` runs\n * unattended in CI and in agent/scripted environments, so a prompt that would\n * otherwise hang forever must instead fail fast with a `CliError` that names\n * the flag/env var to set.\n *\n * Renders on **stderr** (via the `output: process.stderr` context inquirer\n * accepts), keeping stdout free for machine-readable output.\n */\n\nimport { confirm, input, select } from \"@inquirer/prompts\"\nimport { CliError, nonInteractiveError } from \"./errors.js\"\n\n/**\n * False when stdin/stderr are not TTYs, when CI is set, or when\n * MERIDIAN_NON_INTERACTIVE is set. Commands use this to decide between\n * prompting and requiring flags/env vars.\n */\nexport function isInteractive(): boolean {\n if (interactiveOverride !== undefined) return interactiveOverride\n return (\n process.stdin.isTTY === true &&\n process.stderr.isTTY === true &&\n !process.env.CI &&\n !process.env.MERIDIAN_NON_INTERACTIVE\n )\n}\n\n/** True when `--yes`/MERIDIAN_YES pre-approves confirmations. */\nexport function isAssumeYes(): boolean {\n if (assumeYesOverride !== undefined) return assumeYesOverride\n return Boolean(process.env.MERIDIAN_YES)\n}\n\nlet interactiveOverride: boolean | undefined\nlet assumeYesOverride: boolean | undefined\n\n/** Set from the root command's `--yes`/`--no-input` flags. */\nexport function configurePrompts(options: { assumeYes?: boolean; interactive?: boolean }): void {\n if (options.assumeYes !== undefined) assumeYesOverride = options.assumeYes\n if (options.interactive !== undefined) interactiveOverride = options.interactive\n}\n\n/** Test helper: clears the overrides set by `configurePrompts`. */\nexport function resetPrompts(): void {\n interactiveOverride = undefined\n assumeYesOverride = undefined\n}\n\nexport interface Choice<T> {\n value: T\n name: string\n description?: string\n}\n\nexport interface SelectOptions<T> {\n message: string\n choices: Array<Choice<T>>\n /** Pre-selected value. */\n default?: T\n /**\n * Env var consulted before prompting (e.g. MERIDIAN_ORG). Matched against the\n * choice value, name, or a `slug`-like id, case-insensitively.\n */\n envVar?: string\n /** Explicit answer from a command flag; wins over everything. */\n answer?: string\n /** Names the flag to mention in the non-interactive error, e.g. \"--org\". */\n flag?: string\n promptImpl?: typeof import(\"@inquirer/prompts\").select\n}\n\nfunction matchChoice<T>(choices: Array<Choice<T>>, raw: string): Choice<T> | undefined {\n const target = raw.trim().toLowerCase()\n return choices.find((choice) => {\n const value = String(choice.value).trim().toLowerCase()\n const name = choice.name.trim().toLowerCase()\n return value === target || name === target\n })\n}\n\nfunction listChoiceNames<T>(choices: Array<Choice<T>>): string {\n return choices.map((choice) => choice.name).join(\", \")\n}\n\n/** Combines a flag and/or env var into the text `nonInteractiveError`'s hint mentions. */\nfunction describeOverride(flag: string | undefined, envVar: string | undefined): string {\n const parts = [flag, envVar].filter((part): part is string => part !== undefined)\n return parts.length > 0 ? parts.join(\" or \") : \"the appropriate flag\"\n}\n\n/**\n * Resolves a choice: explicit answer → env var → single choice auto-selected →\n * interactive select → nonInteractiveError naming the flag/env var.\n */\nexport async function selectOne<T>(options: SelectOptions<T>): Promise<T> {\n const { message, choices, envVar, answer, flag } = options\n\n if (choices.length === 0) {\n throw new CliError(\"Nothing to choose from.\")\n }\n\n if (answer !== undefined) {\n const match = matchChoice(choices, answer)\n if (match === undefined) {\n throw new CliError(`\"${answer}\" is not a valid choice for ${message}.`, {\n hint: `Valid options: ${listChoiceNames(choices)}.`,\n })\n }\n return match.value\n }\n\n if (envVar !== undefined) {\n const envValue = process.env[envVar]\n if (envValue !== undefined && envValue !== \"\") {\n const match = matchChoice(choices, envValue)\n if (match === undefined) {\n throw new CliError(`${envVar}=\"${envValue}\" is not a valid choice for ${message}.`, {\n hint: `Valid options: ${listChoiceNames(choices)}.`,\n })\n }\n return match.value\n }\n }\n\n if (choices.length === 1) {\n const only = choices[0]\n if (only !== undefined) return only.value\n }\n\n if (!isInteractive()) {\n throw nonInteractiveError(message, describeOverride(flag, envVar))\n }\n\n const promptImpl = options.promptImpl ?? select\n try {\n return await promptImpl(\n {\n message,\n choices: choices.map((choice) => ({\n value: choice.value,\n name: choice.name,\n ...(choice.description !== undefined ? { description: choice.description } : {}),\n })),\n ...(options.default !== undefined ? { default: options.default } : {}),\n },\n { output: process.stderr },\n )\n } catch (err) {\n throw toPromptError(err)\n }\n}\n\nexport interface ConfirmOptions {\n message: string\n default?: boolean\n /** Skip the prompt when --yes/MERIDIAN_YES is set. */\n assumeYes?: boolean\n flag?: string\n promptImpl?: typeof import(\"@inquirer/prompts\").confirm\n}\n\n/** Text mentioned in the non-interactive error: the call's own flag (if any), plus the global bypasses. */\nfunction confirmOverrideText(flag: string | undefined): string {\n return `${flag ?? \"--yes\"} (or MERIDIAN_YES)`\n}\n\n/** Non-interactive without --yes → nonInteractiveError (do NOT silently assume yes). */\nexport async function confirmAction(options: ConfirmOptions): Promise<boolean> {\n const assumeYes = options.assumeYes ?? isAssumeYes()\n if (assumeYes) return true\n\n if (!isInteractive()) {\n throw nonInteractiveError(options.message, confirmOverrideText(options.flag))\n }\n\n const promptImpl = options.promptImpl ?? confirm\n try {\n return await promptImpl(\n {\n message: options.message,\n ...(options.default !== undefined ? { default: options.default } : {}),\n },\n { output: process.stderr },\n )\n } catch (err) {\n throw toPromptError(err)\n }\n}\n\nexport interface TextOptions {\n message: string\n default?: string\n envVar?: string\n answer?: string\n flag?: string\n validate?: (value: string) => true | string\n promptImpl?: typeof import(\"@inquirer/prompts\").input\n}\n\nexport async function promptText(options: TextOptions): Promise<string> {\n if (options.answer !== undefined) return options.answer\n\n if (options.envVar !== undefined) {\n const envValue = process.env[options.envVar]\n if (envValue !== undefined && envValue !== \"\") return envValue\n }\n\n if (!isInteractive()) {\n throw nonInteractiveError(options.message, describeOverride(options.flag, options.envVar))\n }\n\n const promptImpl = options.promptImpl ?? input\n try {\n return await promptImpl(\n {\n message: options.message,\n ...(options.default !== undefined ? { default: options.default } : {}),\n ...(options.validate !== undefined ? { validate: options.validate } : {}),\n },\n { output: process.stderr },\n )\n } catch (err) {\n throw toPromptError(err)\n }\n}\n\n/**\n * A destructive-action confirmation that requires typing an exact phrase (the\n * database name) when interactive, and `--yes` when not. Used by `meridian db reset`.\n */\nexport async function confirmDestructive(options: {\n message: string\n phrase: string\n assumeYes?: boolean\n flag?: string\n promptImpl?: typeof import(\"@inquirer/prompts\").input\n}): Promise<boolean> {\n const assumeYes = options.assumeYes ?? isAssumeYes()\n if (assumeYes) return true\n\n if (!isInteractive()) {\n throw nonInteractiveError(options.message, confirmOverrideText(options.flag))\n }\n\n const promptImpl = options.promptImpl ?? input\n let typed: string\n try {\n typed = await promptImpl(\n { message: `${options.message} Type \"${options.phrase}\" to confirm:` },\n { output: process.stderr },\n )\n } catch (err) {\n throw toPromptError(err)\n }\n return typed.trim() === options.phrase\n}\n\n/** Maps @inquirer's ExitPromptError (Ctrl-C) to a CliError with exit code 130. */\nexport function toPromptError(error: unknown): unknown {\n if (error instanceof Error && error.name === \"ExitPromptError\") {\n return new CliError(\"Aborted.\", { exitCode: 130, cause: error })\n }\n return error\n}\n","/**\n * Per-project link file at `<root>/.meridian/project.json`. Committed-safe:\n * it names the org/app the project is linked to but never holds a secret.\n */\n\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\"\nimport { dirname, parse, resolve } from \"node:path\"\nimport { z } from \"zod\"\nimport { CliError, notLinkedError } from \"./errors.js\"\nimport { projectConfigPath, projectStateDir } from \"./paths.js\"\n\nexport interface ProjectConfig {\n org_id: number | string\n app_id: number | string\n app_name?: string\n /** Overrides the default `npm run dev` used by `meridian dev`. */\n dev_command?: string\n /** Opts out of the check that the Prisma datasource reads Meridian's DATABASE_URL. */\n skip_datasource_check?: boolean\n}\n\nexport const projectConfigSchema = z.object({\n org_id: z.union([z.number(), z.string()]),\n app_id: z.union([z.number(), z.string()]),\n app_name: z.string().exactOptional(),\n dev_command: z.string().exactOptional(),\n skip_datasource_check: z.boolean().exactOptional(),\n}) satisfies z.ZodType<ProjectConfig>\n\nexport interface LinkedProject {\n root: string\n config: ProjectConfig\n}\n\nconst GITIGNORE_ENTRIES = [\"snapshots/\", \"*.log\", \"tmp/\"]\n\n/** Walks up from `startDir` (default process.cwd()) to the filesystem root looking for `.meridian/project.json`. */\nexport function findProjectRoot(startDir?: string): string | null {\n let dir = resolve(startDir ?? process.cwd())\n const { root } = parse(dir)\n\n while (true) {\n if (existsSync(projectConfigPath(dir))) return dir\n if (dir === root) return null\n dir = dirname(dir)\n }\n}\n\n/** null when unlinked. Throws CliError on a corrupt/invalid project.json (mention the path, hint `meridian link`). */\nexport function readProject(startDir?: string): LinkedProject | null {\n const root = findProjectRoot(startDir)\n if (root === null) return null\n\n const path = projectConfigPath(root)\n let raw: string\n try {\n raw = readFileSync(path, \"utf8\")\n } catch (error) {\n if (isEnoent(error)) return null\n throw new CliError(`Could not read ${path}.`, {\n hint: \"Run `meridian link` to relink this project.\",\n cause: error,\n })\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (error) {\n throw new CliError(`${path} is not valid JSON.`, {\n hint: \"Run `meridian link` to relink this project.\",\n cause: error,\n })\n }\n\n const result = projectConfigSchema.safeParse(parsed)\n if (!result.success) {\n throw new CliError(`${path} is not a valid Meridian project file.`, {\n hint: \"Run `meridian link` to relink this project.\",\n cause: result.error,\n })\n }\n\n return { root, config: result.data }\n}\n\n/** Throws notLinkedError() when unlinked. */\nexport function requireProject(startDir?: string): LinkedProject {\n const project = readProject(startDir)\n if (project === null) throw notLinkedError()\n return project\n}\n\n/** Creates `<root>/.meridian/`, writes project.json (2-space JSON + trailing newline) and calls ensureProjectStateIgnore. */\nexport function writeProject(root: string, config: ProjectConfig): void {\n const resolvedRoot = resolve(root)\n mkdirSync(projectStateDir(resolvedRoot), { recursive: true })\n writeFileSync(projectConfigPath(resolvedRoot), `${JSON.stringify(config, null, 2)}\\n`)\n ensureProjectStateIgnore(resolvedRoot)\n}\n\n/** Deletes project.json; returns false when there was nothing to delete. Leaves other .meridian contents alone. */\nexport function removeProject(root: string): boolean {\n const path = projectConfigPath(resolve(root))\n if (!existsSync(path)) return false\n rmSync(path)\n return true\n}\n\n/**\n * Writes `<root>/.meridian/.gitignore` ignoring the runtime bits (snapshots/,\n * *.log, tmp/) while keeping project.json committable. Never overwrites an\n * existing file that already contains the entries.\n */\nexport function ensureProjectStateIgnore(root: string): void {\n const resolvedRoot = resolve(root)\n const stateDir = projectStateDir(resolvedRoot)\n mkdirSync(stateDir, { recursive: true })\n\n const gitignorePath = `${stateDir}/.gitignore`\n let existingLines: string[] = []\n if (existsSync(gitignorePath)) {\n existingLines = readFileSync(gitignorePath, \"utf8\").split(\"\\n\")\n }\n\n const missing = GITIGNORE_ENTRIES.filter((entry) => !existingLines.includes(entry))\n if (existingLines.length > 0 && missing.length === 0) return\n\n const lines = [...existingLines.filter((line) => line.trim() !== \"\"), ...missing]\n writeFileSync(gitignorePath, `${lines.join(\"\\n\")}\\n`)\n}\n\n/** Resolves the project root for a command: an explicit --cwd wins, else search upwards, else null. */\nexport function resolveProjectRoot(cwd?: string): string | null {\n if (cwd !== undefined) return findProjectRoot(cwd)\n return findProjectRoot()\n}\n\nfunction isEnoent(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\"\n}\n","/**\n * Child-process plumbing shared by `meridian dev` (the app's long-running dev\n * server) and `meridian migrate` / `meridian db seed` (short-lived `npx\n * prisma ...` invocations).\n */\n\nimport type { ChildProcess, SpawnOptions as NodeSpawnOptions } from \"node:child_process\"\nimport { readFileSync } from \"node:fs\"\nimport { delimiter, join } from \"node:path\"\nimport crossSpawn from \"cross-spawn\"\nimport { CliError } from \"./errors.js\"\n\n/**\n * We spawn through `cross-spawn` rather than `node:child_process.spawn` so\n * that `npm`/`npx` work on Windows, where they are `.cmd` shims that Node\n * refuses to execute without a shell. Doing that ourselves would mean passing\n * `shell: true`, and Node then flattens argv into one command line with no\n * escaping at all — so a `--name \"add users\"` would split, and a `&` in an\n * argument would run as a second command. cross-spawn instead builds the\n * `cmd.exe /d /s /c` invocation itself with per-argument quoting, so nothing\n * we pass is ever interpreted as shell syntax.\n */\nexport type SpawnFn = (command: string, args: readonly string[], options: NodeSpawnOptions) => ChildProcess\n\nexport interface SpawnOptions {\n cwd: string\n env?: NodeJS.ProcessEnv\n /** Inherit stdio (interactive commands like `prisma migrate dev` need a TTY). Default true. */\n inherit?: boolean\n /** Injectable for tests. */\n spawnImpl?: SpawnFn\n}\n\nexport interface RunResult {\n code: number\n signal: NodeJS.Signals | null\n /** Combined stdout+stderr, only captured when `inherit` is false. Trimmed to the last 8 KB. */\n output: string\n}\n\nconst MAX_OUTPUT_LENGTH = 8 * 1024\n\nfunction toEnoentError(command: string, cause: unknown): CliError {\n return new CliError(`Could not run \\`${command}\\`: command not found.`, {\n hint: `Make sure \\`${command}\\` is installed and on your PATH.`,\n cause,\n })\n}\n\nfunction isEnoent(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\"\n}\n\n/** Splits a shell-ish command string into argv without invoking a shell: handles single/double quotes and escaped spaces. */\nexport function parseCommandString(command: string): { command: string; args: string[] } {\n const tokens: string[] = []\n let current = \"\"\n let hasCurrent = false\n let quote: '\"' | \"'\" | null = null\n let i = 0\n\n while (i < command.length) {\n const ch = command.charAt(i)\n\n if (quote !== null) {\n if (ch === quote) {\n quote = null\n } else {\n current += ch\n hasCurrent = true\n }\n i++\n continue\n }\n\n if (ch === '\"' || ch === \"'\") {\n quote = ch\n hasCurrent = true\n i++\n continue\n }\n\n if (ch === \"\\\\\" && i + 1 < command.length) {\n current += command.charAt(i + 1)\n hasCurrent = true\n i += 2\n continue\n }\n\n if (ch === \" \" || ch === \"\\t\") {\n if (hasCurrent) {\n tokens.push(current)\n current = \"\"\n hasCurrent = false\n }\n i++\n continue\n }\n\n current += ch\n hasCurrent = true\n i++\n }\n\n if (quote !== null) {\n throw new CliError(`Unbalanced ${quote} quote in command: ${command}`)\n }\n if (hasCurrent) tokens.push(current)\n\n const [first, ...rest] = tokens\n if (first === undefined) {\n throw new CliError(\"Cannot parse an empty command string.\")\n }\n return { command: first, args: rest }\n}\n\nfunction attachOutputCapture(\n child: { stdout: NodeJS.ReadableStream | null; stderr: NodeJS.ReadableStream | null },\n onData: (chunk: Buffer | string) => void,\n): void {\n child.stdout?.on(\"data\", onData)\n child.stderr?.on(\"data\", onData)\n}\n\nfunction makeOutputCollector(): { append: (chunk: Buffer | string) => void; get: () => string } {\n let output = \"\"\n return {\n append(chunk) {\n output += chunk.toString()\n if (output.length > MAX_OUTPUT_LENGTH) output = output.slice(output.length - MAX_OUTPUT_LENGTH)\n },\n get: () => output,\n }\n}\n\n/** Spawns and resolves when the process exits. Never rejects on a non-zero exit — inspect `code`. Rejects only when the binary cannot be spawned (ENOENT → CliError naming the command). */\nexport function runProcess(command: string, args: string[], options: SpawnOptions): Promise<RunResult> {\n const spawnFn = options.spawnImpl ?? crossSpawn\n const inherit = options.inherit ?? true\n\n return new Promise((resolve, reject) => {\n const child = spawnFn(command, args, {\n cwd: options.cwd,\n env: options.env ?? process.env,\n stdio: inherit ? \"inherit\" : [\"ignore\", \"pipe\", \"pipe\"],\n })\n\n const collector = makeOutputCollector()\n if (!inherit) attachOutputCapture(child, collector.append)\n\n let settled = false\n\n child.once(\"error\", (error: NodeJS.ErrnoException) => {\n if (settled) return\n settled = true\n reject(isEnoent(error) ? toEnoentError(command, error) : error)\n })\n\n child.once(\"close\", (code, signal) => {\n if (settled) return\n settled = true\n resolve({ code: code ?? 0, signal, output: collector.get() })\n })\n })\n}\n\n/** Convenience for `runProcess(parseCommandString(cmd))`. */\nexport function runCommandString(command: string, options: SpawnOptions): Promise<RunResult> {\n const parsed = parseCommandString(command)\n return runProcess(parsed.command, parsed.args, options)\n}\n\n/** `npx <bin> <args>` with the local node_modules/.bin on PATH; used for prisma. */\nexport function runNpx(args: string[], options: SpawnOptions): Promise<RunResult> {\n const baseEnv = options.env ?? process.env\n const binDir = join(options.cwd, \"node_modules\", \".bin\")\n const path = baseEnv.PATH\n const env: NodeJS.ProcessEnv = {\n ...baseEnv,\n PATH: path !== undefined && path !== \"\" ? `${binDir}${delimiter}${path}` : binDir,\n }\n return runProcess(\"npx\", args, { ...options, env })\n}\n\nexport interface ManagedChild {\n readonly pid: number | undefined\n /** Resolves with the exit result. */\n readonly exited: Promise<RunResult>\n /** SIGTERM, then SIGKILL after `graceMs` (default 5000). Idempotent. */\n stop(signal?: NodeJS.Signals, graceMs?: number): Promise<void>\n}\n\nfunction trySignal(child: { kill(signal?: NodeJS.Signals): boolean }, signal: NodeJS.Signals): void {\n try {\n child.kill(signal)\n } catch (error) {\n if (!isEsrch(error)) throw error\n }\n}\n\nfunction isEsrch(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ESRCH\"\n}\n\n/**\n * Long-running child (the app dev server) that the caller supervises. Always\n * carries the {@link DEV_GUARD_ENV} marker so a nested `meridian dev` fails\n * loudly instead of forking forever — callers of `runProcess`/`runNpx`\n * (one-shot `prisma` commands) do not get this marker.\n */\nexport function startProcess(command: string, args: string[], options: SpawnOptions): ManagedChild {\n const spawnFn = options.spawnImpl ?? crossSpawn\n const inherit = options.inherit ?? true\n const env: NodeJS.ProcessEnv = { ...(options.env ?? process.env), [DEV_GUARD_ENV]: \"1\" }\n\n const child = spawnFn(command, args, {\n cwd: options.cwd,\n env,\n stdio: inherit ? \"inherit\" : [\"ignore\", \"pipe\", \"pipe\"],\n })\n\n const collector = makeOutputCollector()\n if (!inherit) attachOutputCapture(child, collector.append)\n\n const exited = new Promise<RunResult>((resolve, reject) => {\n child.once(\"error\", (error: NodeJS.ErrnoException) => {\n reject(isEnoent(error) ? toEnoentError(command, error) : error)\n })\n child.once(\"close\", (code, signal) => {\n resolve({ code: code ?? 0, signal, output: collector.get() })\n })\n })\n\n let stopped = false\n\n const stop = async (signal: NodeJS.Signals = \"SIGTERM\", graceMs = 5000): Promise<void> => {\n if (stopped) {\n await exited.catch(() => undefined)\n return\n }\n stopped = true\n\n trySignal(child, signal)\n\n const killTimer = setTimeout(() => {\n trySignal(child, \"SIGKILL\")\n }, graceMs)\n killTimer.unref?.()\n\n try {\n await exited\n } catch {\n // A spawn error surfaces via `exited`; `stop()` only guarantees termination.\n } finally {\n clearTimeout(killTimer)\n }\n }\n\n return {\n get pid() {\n return child.pid\n },\n exited,\n stop,\n }\n}\n\n/**\n * Environment marker set on children spawned by `meridian dev` so a nested\n * `meridian dev` (e.g. when the app's own `npm run dev` script calls it) can\n * fail loudly instead of forking forever.\n */\nexport const DEV_GUARD_ENV = \"MERIDIAN_DEV_ACTIVE\"\n\n/** True when we are already inside a `meridian dev` child process tree. */\nexport function isInsideDevSession(env: NodeJS.ProcessEnv = process.env): boolean {\n return env[DEV_GUARD_ENV] === \"1\"\n}\n\nconst RUNNER_PREFIXES: string[][] = [[\"npx\"], [\"npm\", \"exec\"], [\"pnpm\", \"dlx\"], [\"yarn\", \"dlx\"]]\n\nfunction stripRunnerPrefix(tokens: string[]): string[] {\n for (const prefix of RUNNER_PREFIXES) {\n if (prefix.length <= tokens.length && prefix.every((part, i) => tokens[i] === part)) {\n return tokens.slice(prefix.length)\n }\n }\n return tokens\n}\n\nfunction isMeridianBinary(token: string | undefined): boolean {\n if (token === undefined) return false\n return token === \"meridian\" || token.endsWith(\"/meridian\") || token.endsWith(\"\\\\meridian\")\n}\n\n/**\n * Throws a CliError when `command` would re-enter the CLI (matches\n * `meridian dev`, `npx meridian dev`, `pnpm|yarn|npm run` scripts resolved to\n * `meridian dev`, etc.). Used by `meridian dev` before running the app command.\n *\n * This is a syntactic check only (no filesystem access) so it never flags\n * `npm run dev` itself — the default app dev command — even though that\n * script could theoretically resolve to something self-invoking.\n */\nexport function assertNotSelfInvoking(command: string): void {\n let tokens: string[]\n try {\n const parsed = parseCommandString(command)\n tokens = [parsed.command, ...parsed.args]\n } catch {\n return\n }\n\n const rest = stripRunnerPrefix(tokens)\n if (isMeridianBinary(rest[0]) && rest[1] === \"dev\") {\n throw new CliError(\"`meridian dev` cannot run itself as the app's dev command.\", {\n hint:\n \"Set `dev_command` in .meridian/project.json to the underlying command (e.g. `next dev`), \" +\n \"because `meridian dev` runs `npm run dev` by default.\",\n })\n }\n}\n\n/** Reads `scripts.<name>` from `<root>/package.json`; null when absent/unreadable. */\nexport function readPackageScript(root: string, name: string): string | null {\n try {\n const raw = readFileSync(join(root, \"package.json\"), \"utf8\")\n const parsed: unknown = JSON.parse(raw)\n if (typeof parsed !== \"object\" || parsed === null) return null\n const scripts = (parsed as { scripts?: unknown }).scripts\n if (typeof scripts !== \"object\" || scripts === null) return null\n const value = (scripts as Record<string, unknown>)[name]\n return typeof value === \"string\" ? value : null\n } catch {\n return null\n }\n}\n","/**\n * Surgical `.env` patching for `meridian dev`.\n *\n * The developer's `.env` is user-owned content: comments, blank lines,\n * ordering, line endings and unrelated keys must survive untouched. We only\n * ever rewrite the specific keys we're told to (in place, if present) or\n * append them, and we keep a one-time `.backup` so the original is always\n * recoverable.\n */\n\nimport {\n chmodSync,\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n statSync,\n writeFileSync,\n} from \"node:fs\"\nimport { dirname } from \"node:path\"\nimport { CliError } from \"./errors.js\"\n\n/**\n * Mode for a `.env` this CLI creates itself. The file holds a live database\n * password, so it is owner-only from the start; a file the developer already\n * had keeps whatever mode they chose.\n */\nconst CREATED_ENV_MODE = 0o600\n\nexport interface EnvPatch {\n [key: string]: string\n}\n\nexport interface PatchEnvResult {\n path: string\n /** The .env file did not exist and was created. */\n created: boolean\n /** A `.env.backup` was written by this call (only ever written once — never overwritten). */\n backedUp: boolean\n /** Whether the file contents actually changed. */\n changed: boolean\n /** Per-key detail for reporting: previous value (undefined when the key was absent). */\n keys: Array<{ key: string; previous?: string; next: string; action: \"created\" | \"updated\" | \"unchanged\" }>\n}\n\nconst MANAGED_HEADER = \"# Managed by the Meridian CLI — DATABASE_URL is rewritten by `meridian dev`.\"\n\nconst LINE_RE = /^([ \\t]*)(export[ \\t]+)?([A-Za-z_][A-Za-z0-9_]*)([ \\t]*=[ \\t]*)(.*)$/\n\ninterface Line {\n text: string\n eol: string\n}\n\ninterface LineMatch {\n indent: string\n prefix: string\n key: string\n eq: string\n rest: string\n}\n\nfunction splitLines(content: string): Line[] {\n const lines: Line[] = []\n let start = 0\n for (let i = 0; i < content.length; i++) {\n if (content.charAt(i) !== \"\\n\") continue\n const hasCr = i > start && content.charAt(i - 1) === \"\\r\"\n const end = hasCr ? i - 1 : i\n lines.push({ text: content.slice(start, end), eol: hasCr ? \"\\r\\n\" : \"\\n\" })\n start = i + 1\n }\n if (start < content.length) lines.push({ text: content.slice(start), eol: \"\" })\n return lines\n}\n\nfunction detectDominantEol(lines: Line[]): string {\n let crlf = 0\n let lf = 0\n for (const line of lines) {\n if (line.eol === \"\\r\\n\") crlf++\n else if (line.eol === \"\\n\") lf++\n }\n return crlf > lf ? \"\\r\\n\" : \"\\n\"\n}\n\nfunction matchLine(text: string): LineMatch | null {\n const match = LINE_RE.exec(text)\n if (match === null) return null\n return {\n indent: match[1] ?? \"\",\n prefix: match[2] ?? \"\",\n key: match[3] ?? \"\",\n eq: match[4] ?? \"\",\n rest: match[5] ?? \"\",\n }\n}\n\nfunction unescapeDoubleQuoted(inner: string): string {\n return inner.replace(/\\\\(.)/g, (_full, ch: string) => (ch === \"n\" ? \"\\n\" : ch))\n}\n\nfunction decodeEnvValue(raw: string): string {\n const trimmed = raw.trim()\n if (trimmed.length >= 2 && trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n return unescapeDoubleQuoted(trimmed.slice(1, -1))\n }\n if (trimmed.length >= 2 && trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\")) {\n return trimmed.slice(1, -1)\n }\n return trimmed\n}\n\n/** Quotes/escapes a value for dotenv when needed (whitespace, #, quotes, newlines, empty). */\nexport function formatEnvValue(value: string): string {\n const needsQuoting = value === \"\" || /[\\s#\"'$]/.test(value)\n if (!needsQuoting) return value\n const escaped = value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"').replace(/\\n/g, \"\\\\n\")\n return `\"${escaped}\"`\n}\n\n/** Parses dotenv content into a record (last occurrence wins), for reading DATABASE_URL etc. */\nexport function parseEnvContent(content: string): Record<string, string> {\n const result: Record<string, string> = {}\n for (const line of splitLines(content)) {\n const match = matchLine(line.text)\n if (match === null) continue\n result[match.key] = decodeEnvValue(match.rest)\n }\n return result\n}\n\n/** Reads a single key's *unquoted* value out of dotenv content. */\nexport function readEnvValue(content: string, key: string): string | undefined {\n return parseEnvContent(content)[key]\n}\n\n/** Pure string transform, unit-testable without the filesystem. */\nexport function upsertEnvContent(\n content: string,\n patch: EnvPatch,\n): { content: string; changed: boolean; keys: PatchEnvResult[\"keys\"] } {\n const lines = splitLines(content)\n const keys: PatchEnvResult[\"keys\"] = []\n const toAppend: Array<{ key: string; value: string }> = []\n let changed = false\n\n for (const [key, value] of Object.entries(patch)) {\n let foundIndex = -1\n for (let i = lines.length - 1; i >= 0; i--) {\n const line = lines[i]\n if (line === undefined) continue\n const match = matchLine(line.text)\n if (match !== null && match.key === key) {\n foundIndex = i\n break\n }\n }\n\n if (foundIndex === -1) {\n toAppend.push({ key, value })\n keys.push({ key, next: value, action: \"created\" })\n changed = true\n continue\n }\n\n const line = lines[foundIndex]\n const match = line === undefined ? null : matchLine(line.text)\n if (line === undefined || match === null) continue\n\n const previous = decodeEnvValue(match.rest)\n if (previous === value) {\n keys.push({ key, previous, next: value, action: \"unchanged\" })\n continue\n }\n\n lines[foundIndex] = {\n text: `${match.indent}${match.prefix}${key}${match.eq}${formatEnvValue(value)}`,\n eol: line.eol,\n }\n keys.push({ key, previous, next: value, action: \"updated\" })\n changed = true\n }\n\n if (toAppend.length > 0) {\n const dominantEol = detectDominantEol(lines)\n const lastIndex = lines.length - 1\n const lastLine = lines[lastIndex]\n if (lastLine !== undefined && lastLine.eol === \"\") {\n lines[lastIndex] = { text: lastLine.text, eol: dominantEol }\n }\n for (const { key, value } of toAppend) {\n lines.push({ text: `${key}=${formatEnvValue(value)}`, eol: dominantEol })\n }\n }\n\n const nextContent = lines.map((line) => line.text + line.eol).join(\"\")\n return { content: nextContent, changed, keys }\n}\n\nfunction isEnoent(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\"\n}\n\n/**\n * Writes `content` and forces `mode`. `writeFileSync`'s own `mode` option only\n * applies when it creates the file, so a leftover temp/backup file from an\n * interrupted run would otherwise keep its old (possibly wider) permissions.\n */\nfunction writeExact(path: string, content: string, mode: number): void {\n writeFileSync(path, content, { mode })\n try {\n chmodSync(path, mode)\n } catch {\n // Best effort: some filesystems (Windows, mounted volumes) don't support chmod.\n }\n}\n\n/**\n * Patch (or create) the file at `envPath`. Writes `<envPath>.backup` before the\n * first modification of an existing file and never overwrites an existing backup,\n * so the developer's original is always recoverable.\n */\nexport function patchEnvFile(envPath: string, patch: EnvPatch, options: { backup?: boolean } = {}): PatchEnvResult {\n const backupEnabled = options.backup ?? true\n\n let existing: string | null = null\n let mode: number | undefined\n try {\n existing = readFileSync(envPath, \"utf8\")\n mode = statSync(envPath).mode & 0o777\n } catch (error) {\n if (!isEnoent(error)) {\n throw new CliError(`Could not read ${envPath}.`, {\n hint: \"Check the file's permissions and try again.\",\n cause: error,\n })\n }\n }\n\n const created = existing === null\n const baseContent = existing !== null ? existing : `${MANAGED_HEADER}\\n`\n const targetMode = mode ?? CREATED_ENV_MODE\n\n const { content: nextContent, changed, keys } = upsertEnvContent(baseContent, patch)\n\n let backedUp = false\n if (existing !== null && changed && backupEnabled) {\n const backupPath = `${envPath}.backup`\n if (!existsSync(backupPath)) {\n // The backup is a verbatim copy of a file that may hold secrets, so it\n // must not end up more readable than the original.\n writeExact(backupPath, existing, targetMode)\n backedUp = true\n }\n }\n\n if (created || changed) {\n mkdirSync(dirname(envPath), { recursive: true })\n // The pid keeps two concurrent commands (`meridian dev` in one terminal,\n // `meridian migrate` in another) from writing the same temp file and\n // renaming each other's half-written content over the real .env.\n const tmpPath = `${envPath}.${process.pid}.tmp`\n writeExact(tmpPath, nextContent, targetMode)\n renameSync(tmpPath, envPath)\n }\n\n return { path: envPath, created, backedUp, changed: created || changed, keys }\n}\n\n/** mysql://user:pass@host:port/db with user/password percent-encoded. */\nexport function buildDatabaseUrl(input: {\n username: string\n password: string\n host?: string\n port: number\n database: string\n params?: Record<string, string>\n}): string {\n const host = input.host ?? \"127.0.0.1\"\n const user = encodeURIComponent(input.username)\n const pass = encodeURIComponent(input.password)\n const hasParams = input.params !== undefined && Object.keys(input.params).length > 0\n const query = hasParams ? `?${new URLSearchParams(input.params).toString()}` : \"\"\n return `mysql://${user}:${pass}@${host}:${input.port}/${input.database}${query}`\n}\n\n/** Redacts the password in a mysql:// URL for log output. */\nexport function redactDatabaseUrl(url: string): string {\n return url.replace(/^(mysql:\\/\\/[^:@/]+):([^@]*)@/, \"$1:****@\")\n}\n","/**\n * Free-port selection for the Cloud SQL Auth Proxy. We bind-test rather than\n * connect-test so a stray refused connection doesn't get mistaken for a free\n * port.\n */\n\nimport { createServer } from \"node:net\"\nimport { CliError } from \"./errors.js\"\n\n/** One above MySQL's default (3306), so a proxy on this port is recognisable in logs. */\nconst DEFAULT_START_PORT = 3307\nconst DEFAULT_ATTEMPTS = 20\nconst MAX_PORT = 65535\n\n/** True when nothing is listening on host:port (bind test, not connect test). */\nexport function isPortFree(port: number, host = \"127.0.0.1\"): Promise<boolean> {\n return new Promise((resolve) => {\n const server = createServer()\n server.once(\"error\", () => {\n resolve(false)\n })\n server.once(\"listening\", () => {\n server.close(() => resolve(true))\n })\n server.listen({ port, host, exclusive: true })\n })\n}\n\nfunction bindEphemeralPort(host: string): Promise<number | null> {\n return new Promise((resolve) => {\n const server = createServer()\n server.once(\"error\", () => resolve(null))\n server.listen({ port: 0, host, exclusive: true }, () => {\n const address = server.address()\n const port = typeof address === \"object\" && address !== null ? address.port : null\n server.close(() => resolve(port))\n })\n })\n}\n\nexport interface FindFreePortOptions {\n preferred?: number\n start?: number\n attempts?: number\n host?: string\n}\n\n/**\n * Finds a free TCP port on 127.0.0.1. Tries `preferred` first when given, then\n * scans upward from `start` (default 3307 — one above MySQL's default so the\n * proxy port is recognisable), then falls back to an ephemeral port from the OS.\n */\nexport async function findFreePort(options: FindFreePortOptions = {}): Promise<number> {\n const host = options.host ?? \"127.0.0.1\"\n const start = options.start ?? DEFAULT_START_PORT\n const attempts = options.attempts ?? DEFAULT_ATTEMPTS\n\n if (options.preferred !== undefined && (await isPortFree(options.preferred, host))) {\n return options.preferred\n }\n\n for (let offset = 0; offset < attempts; offset++) {\n const candidate = start + offset\n if (candidate > MAX_PORT) break\n if (await isPortFree(candidate, host)) return candidate\n }\n\n const ephemeral = await bindEphemeralPort(host)\n if (ephemeral === null) {\n throw new CliError(\"Could not find a free local port for the Cloud SQL Auth Proxy.\", {\n hint: \"Close other applications using local ports and try again.\",\n })\n }\n return ephemeral\n}\n","/**\n * Reading and vetting a project's Prisma configuration, plus explaining the\n * Prisma failures whose messages point away from their real cause.\n *\n * The main guard here covers the one silent failure this product exists to\n * prevent: a Prisma datasource that does not read `DATABASE_URL`.\n *\n * Every session provisions the managed MySQL database, rotates its password,\n * starts the proxy and patches `DATABASE_URL` into `.env` — and a datasource\n * like `url = \"file:dev.sqlite\"` then ignores all of it, migrates a local\n * SQLite file, and reports success. The developer is left with a green\n * `meridian migrate` and an empty managed database, which is exactly the\n * SQLite/MySQL split the managed database is meant to remove.\n *\n * Checked before the session starts, so nothing is provisioned or rotated for\n * a run that cannot reach the managed database.\n */\n\nimport { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from \"node:fs\"\nimport { dirname, join, relative } from \"node:path\"\nimport { CliError } from \"./errors.js\"\n\nconst REQUIRED_URL_ENV = \"DATABASE_URL\"\nconst REQUIRED_SHADOW_URL_ENV = \"SHADOW_DATABASE_URL\"\nconst REQUIRED_PROVIDER = \"mysql\"\n\nconst BYPASS_HINT = `Set \\`\"skip_datasource_check\": true\\` in .meridian/project.json to run anyway.`\n\nexport type DatasourceUrl = { kind: \"env\"; name: string } | { kind: \"literal\"; value: string }\n\nexport interface PrismaDatasource {\n /** Relative to the project root, so error messages stay short. */\n schemaPath: string\n name: string\n /** null when the block declares no literal provider. */\n provider: string | null\n /** null when the block declares no url, or one this parser does not model. */\n url: DatasourceUrl | null\n /** null when the block declares no shadowDatabaseUrl. */\n shadowUrl: DatasourceUrl | null\n}\n\n/**\n * Drops `//` comments while respecting string literals, because a perfectly\n * ordinary `url = \"mysql://host/db\"` contains what looks like a comment.\n */\nfunction stripComments(source: string): string {\n let out = \"\"\n let inString = false\n let i = 0\n\n while (i < source.length) {\n const ch = source.charAt(i)\n\n if (inString) {\n if (ch === \"\\\\\" && i + 1 < source.length) {\n out += ch + source.charAt(i + 1)\n i += 2\n continue\n }\n if (ch === '\"') inString = false\n out += ch\n i++\n continue\n }\n\n if (ch === '\"') {\n inString = true\n out += ch\n i++\n continue\n }\n\n if (ch === \"/\" && source.charAt(i + 1) === \"/\") {\n while (i < source.length && source.charAt(i) !== \"\\n\") i++\n continue\n }\n\n out += ch\n i++\n }\n\n return out\n}\n\nfunction isDirectory(path: string): boolean {\n try {\n return statSync(path).isDirectory()\n } catch {\n return false\n }\n}\n\n/**\n * The default locations, in the order Prisma itself resolves them: a single\n * `prisma/schema.prisma`, then a multi-file `prisma/schema/` directory, then a\n * bare `schema.prisma`. A schema pointed at by `--schema` or prisma.config.ts\n * is not found here, which leaves the check disabled rather than wrong.\n */\nexport function findPrismaSchemas(root: string): string[] {\n const paths: string[] = []\n\n const single = join(root, \"prisma\", \"schema.prisma\")\n if (existsSync(single)) paths.push(single)\n\n const folder = join(root, \"prisma\", \"schema\")\n if (isDirectory(folder)) {\n for (const entry of readdirSync(folder).sort()) {\n if (entry.endsWith(\".prisma\")) paths.push(join(folder, entry))\n }\n }\n\n const bare = join(root, \"schema.prisma\")\n if (existsSync(bare)) paths.push(bare)\n\n return paths\n}\n\nfunction parseUrl(body: string, key: \"url\" | \"shadowDatabaseUrl\"): DatasourceUrl | null {\n const fromEnv = new RegExp(`\\\\b${key}\\\\s*=\\\\s*env\\\\(\\\\s*\"([^\"]*)\"\\\\s*\\\\)`).exec(body)\n if (fromEnv?.[1] !== undefined) return { kind: \"env\", name: fromEnv[1] }\n\n const literal = new RegExp(`\\\\b${key}\\\\s*=\\\\s*\"([^\"]*)\"`).exec(body)\n if (literal?.[1] !== undefined) return { kind: \"literal\", value: literal[1] }\n\n return null\n}\n\n/** Parses the first `datasource` block in a schema. Datasource blocks cannot nest, so brace matching is unnecessary. */\nexport function parseDatasource(source: string): Omit<PrismaDatasource, \"schemaPath\"> | null {\n const block = /datasource\\s+(\\w+)\\s*\\{([^}]*)\\}/.exec(stripComments(source))\n if (block === null) return null\n\n const name = block[1] ?? \"db\"\n const body = block[2] ?? \"\"\n const provider = /\\bprovider\\s*=\\s*\"([^\"]*)\"/.exec(body)\n\n return {\n name,\n provider: provider?.[1] ?? null,\n url: parseUrl(body, \"url\"),\n shadowUrl: parseUrl(body, \"shadowDatabaseUrl\"),\n }\n}\n\n/** The project's first Prisma datasource, or null when the project has no schema this can find. */\nexport function readPrismaDatasource(root: string): PrismaDatasource | null {\n for (const path of findPrismaSchemas(root)) {\n let source: string\n try {\n source = readFileSync(path, \"utf8\")\n } catch {\n continue\n }\n\n const parsed = parseDatasource(source)\n if (parsed !== null) return { ...parsed, schemaPath: relative(root, path) }\n }\n\n return null\n}\n\n/**\n * The schema path when a datasource exists but declares no\n * `shadowDatabaseUrl` at all — the one case {@link addShadowDatabaseUrl} can\n * fix — and null otherwise. A block that names some other variable, or\n * hardcodes a URL, is a deliberate choice this must not quietly overwrite.\n */\nexport function missingShadowDatabaseUrl(root: string): string | null {\n const datasource = readPrismaDatasource(root)\n if (datasource === null || datasource.shadowUrl !== null) return null\n return datasource.schemaPath\n}\n\n/** Re-pads `key = value` assignments to one column, the way `prisma format` lays a block out. */\nfunction alignAssignments(lines: string[]): string[] {\n const parsed = lines.map((line) => /^(\\s*)([A-Za-z_]\\w*)\\s*=\\s*(.*)$/.exec(line))\n const widest = parsed.reduce((max, match) => Math.max(max, match?.[2]?.length ?? 0), 0)\n\n return lines.map((line, index) => {\n const match = parsed[index]\n if (match === undefined || match === null) return line\n return `${match[1]}${(match[2] ?? \"\").padEnd(widest)} = ${match[3] ?? \"\"}`\n })\n}\n\n/**\n * Adds `shadowDatabaseUrl = env(\"SHADOW_DATABASE_URL\")` to the project's\n * datasource, immediately after `url` so the two read together, and returns\n * the schema path relative to the root.\n *\n * Only ever called once {@link shadowDatabaseUrlIsMissing} is true, and never\n * without asking first: unlike `.env`, a schema is source the developer wrote\n * and keeps in git.\n */\nexport function addShadowDatabaseUrl(root: string): string {\n const datasource = readPrismaDatasource(root)\n if (datasource === null) throw new CliError(\"No Prisma datasource found to add `shadowDatabaseUrl` to.\")\n\n const absolute = join(root, datasource.schemaPath)\n const source = readFileSync(absolute, \"utf8\")\n const lines = source.split(\"\\n\")\n\n // Located on the raw source rather than the comment-stripped copy the\n // parser uses, since the offsets have to line up with what gets written.\n const open = lines.findIndex((line) => new RegExp(`^\\\\s*datasource\\\\s+${datasource.name}\\\\s*\\\\{`).test(line))\n if (open === -1) throw new CliError(`Could not locate the \\`${datasource.name}\\` datasource in ${datasource.schemaPath}.`)\n\n const close = lines.findIndex((line, index) => index > open && /^\\s*\\}/.test(line))\n if (close === -1) throw new CliError(`\\`${datasource.schemaPath}\\` has an unterminated datasource block.`)\n\n const urlLine = lines.findIndex((line, index) => index > open && index < close && /^\\s*url\\s*=/.test(line))\n const insertAfter = urlLine === -1 ? open : urlLine\n const indent = /^(\\s*)/.exec(lines[insertAfter] ?? \"\")?.[1]\n const body = [\n ...lines.slice(open + 1, insertAfter + 1),\n `${urlLine === -1 ? \" \" : indent}shadowDatabaseUrl = env(\"${REQUIRED_SHADOW_URL_ENV}\")`,\n ...lines.slice(insertAfter + 1, close),\n ]\n\n const patched = [...lines.slice(0, open + 1), ...alignAssignments(body), ...lines.slice(close)]\n writeFileSync(absolute, patched.join(\"\\n\"))\n\n return datasource.schemaPath\n}\n\nfunction wrongUrlError(datasource: PrismaDatasource, url: DatasourceUrl): CliError {\n const problem =\n url.kind === \"literal\"\n ? `hardcodes \\`url = \"${url.value}\"\\``\n : `reads \\`env(\"${url.name}\")\\`, but Meridian sets \\`${REQUIRED_URL_ENV}\\``\n\n return new CliError(\n `\\`${datasource.schemaPath}\\` ${problem}, so this command would not touch the managed development database.`,\n {\n hint:\n `Change the \\`${datasource.name}\\` datasource to \\`url = env(\"${REQUIRED_URL_ENV}\")\\` ` +\n `with \\`provider = \"${REQUIRED_PROVIDER}\"\\`. Migrations generated against another ` +\n `database use dialect-specific SQL and have to be regenerated. ${BYPASS_HINT}`,\n },\n )\n}\n\nfunction wrongProviderError(datasource: PrismaDatasource, provider: string): CliError {\n return new CliError(\n `\\`${datasource.schemaPath}\\` sets \\`provider = \"${provider}\"\\`, but the managed development database is MySQL.`,\n {\n hint:\n `Change the \\`${datasource.name}\\` datasource to \\`provider = \"${REQUIRED_PROVIDER}\"\\` and regenerate any ` +\n `migrations generated for ${provider}, which use dialect-specific SQL. ${BYPASS_HINT}`,\n },\n )\n}\n\n/**\n * Throws when the project's Prisma datasource would ignore the managed\n * database. Stays silent for projects this cannot speak for: no schema, no\n * datasource block, or a `url` shape it does not model.\n */\nexport function assertManagedDatasource(root: string): void {\n const datasource = readPrismaDatasource(root)\n if (datasource === null || datasource.url === null) return\n\n if (datasource.url.kind !== \"env\" || datasource.url.name !== REQUIRED_URL_ENV) {\n throw wrongUrlError(datasource, datasource.url)\n }\n\n if (datasource.provider !== null && datasource.provider !== REQUIRED_PROVIDER) {\n throw wrongProviderError(datasource, datasource.provider)\n }\n}\n\n/**\n * Throws when the datasource has no usable `shadowDatabaseUrl`. Only\n * `prisma migrate dev` needs one, so this is deliberately separate from\n * {@link assertManagedDatasource}: `dev`, `db seed` and `db shell` work fine\n * without it and must not be blocked.\n */\nexport function assertShadowDatasource(root: string): void {\n const datasource = readPrismaDatasource(root)\n if (datasource === null) return\n\n const shadow = datasource.shadowUrl\n if (shadow !== null && shadow.kind === \"env\" && shadow.name === REQUIRED_SHADOW_URL_ENV) return\n\n const problem =\n shadow === null\n ? 'declares no `shadowDatabaseUrl`'\n : shadow.kind === \"literal\"\n ? `hardcodes \\`shadowDatabaseUrl = \"${shadow.value}\"\\``\n : `reads \\`env(\"${shadow.name}\")\\` for its shadow database, but Meridian sets \\`${REQUIRED_SHADOW_URL_ENV}\\``\n\n throw new CliError(`\\`${datasource.schemaPath}\\` ${problem}.`, {\n hint:\n `\\`prisma migrate dev\\` diffs your migrations in a throwaway shadow database, and your dev user cannot ` +\n `create one — so Meridian provisions it for you and exports \\`${REQUIRED_SHADOW_URL_ENV}\\`. Add ` +\n `\\`shadowDatabaseUrl = env(\"${REQUIRED_SHADOW_URL_ENV}\")\\` to the \\`${datasource.name}\\` datasource. ${BYPASS_HINT}`,\n })\n}\n\n/**\n * SQLite and Postgres quote identifiers with double quotes; MySQL uses\n * backticks and, without ANSI_QUOTES, reads `\"Session\"` as a string literal\n * rather than a table name. Anchoring to a DDL keyword keeps this from\n * matching a double quote inside a string literal, which is legal in any\n * dialect.\n */\nconst FOREIGN_DIALECT_DDL = /\\b(?:CREATE\\s+(?:UNIQUE\\s+)?(?:TABLE|INDEX)|ALTER\\s+TABLE|REFERENCES)\\s+\"/i\n\n/** Migration directories hold one `migration.sql` each, next to the schema. */\nfunction migrationSqlPaths(root: string): string[] {\n const schemas = findPrismaSchemas(root)\n const roots = new Set(schemas.map((schema) => join(dirname(schema), \"migrations\")))\n // A multi-file schema lives in prisma/schema/, but its migrations stay in prisma/.\n roots.add(join(root, \"prisma\", \"migrations\"))\n\n const paths: string[] = []\n for (const dir of roots) {\n if (!isDirectory(dir)) continue\n for (const entry of readdirSync(dir).sort()) {\n const sql = join(dir, entry, \"migration.sql\")\n if (existsSync(sql)) paths.push(sql)\n }\n }\n return paths\n}\n\n/**\n * The first migration in the history written for another engine, relative to\n * the project root, or null when the history looks fine.\n *\n * Reads the migration files rather than Prisma's output, which is streamed\n * straight to the terminal and never captured on the interactive path.\n */\nexport function findForeignDialectMigration(root: string): string | null {\n const offender = migrationSqlPaths(root).find((path) => {\n try {\n return FOREIGN_DIALECT_DDL.test(readFileSync(path, \"utf8\"))\n } catch {\n return false\n }\n })\n\n return offender === undefined ? null : relative(root, offender)\n}\n\n/**\n * Why the history cannot be replayed, and how to get out of it.\n *\n * The reset half matters as much as the delete half: a failed attempt leaves\n * a row in `_prisma_migrations` naming a directory that no longer exists once\n * the history is deleted, and Prisma refuses to generate anything until that\n * is cleared. Anyone told only to delete the folder hits a drift error next.\n */\nfunction foreignDialectExplanation(offender: string): string {\n return (\n `\\`${offender}\\` was generated for SQLite or Postgres — it quotes identifiers with double quotes, which ` +\n `MySQL reads as string literals. Migration SQL is dialect-specific and cannot be replayed against MySQL. ` +\n `If this history has only ever run locally, delete \\`prisma/migrations\\` and re-run to regenerate it for ` +\n `MySQL; run \\`meridian db reset\\` first if an earlier attempt already failed, since Prisma records that ` +\n `failure in \\`_prisma_migrations\\` and will not continue while it is there.`\n )\n}\n\n/**\n * Refuses to start a migration whose history cannot possibly apply.\n *\n * Every Shopify app template ships SQLite migrations, so this is the first\n * wall a project hits after pointing its datasource at the managed MySQL\n * database. Caught here rather than only after the fact, the developer skips\n * a doomed run that provisions a session, snapshots the database, fails on a\n * raw MySQL syntax error against a file nobody wrote by hand, and rolls back.\n */\nexport function assertMigrationDialect(root: string): void {\n const offender = findForeignDialectMigration(root)\n if (offender === null) return\n\n throw new CliError(`\\`${offender}\\` was written for a different database engine and cannot apply to MySQL.`, {\n hint: `${foreignDialectExplanation(offender)} Pass \\`--allow-foreign-migrations\\` to try anyway.`,\n })\n}\n\n/**\n * Explains a failure caused by a foreign-dialect history, or null when the\n * history looks fine and the failure was something else.\n *\n * Still worth running after the fact even though {@link assertMigrationDialect}\n * screens for this up front, since that check can be waived with\n * `--allow-foreign-migrations`.\n */\nexport function diagnoseMigrationFailure(root: string): string | null {\n const offender = findForeignDialectMigration(root)\n return offender === null ? null : foreignDialectExplanation(offender)\n}\n","/**\n * Downloads, caches and verifies the Cloud SQL Auth Proxy v2 binary.\n *\n * The proxy ships as a single static executable per platform/arch with no\n * installer, so we cache it once under `<meridianHome>/bin` and re-verify its\n * checksum on every run rather than trusting whatever happens to be on disk.\n */\n\nimport { createHash } from \"node:crypto\"\nimport { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport { CliError } from \"../errors.js\"\nimport { proxyBinDir } from \"../paths.js\"\n\n/** Pinned proxy version; override with MERIDIAN_PROXY_VERSION for a hotfix. */\nexport const PROXY_VERSION = \"2.24.1\"\n\n/** sha256 of every asset of PROXY_VERSION, from Google's published release notes. */\nexport const PROXY_CHECKSUMS: Readonly<Record<string, string>> = Object.freeze({\n \"cloud-sql-proxy.darwin.amd64\": \"67a38444d03fe77a8b11036f96fe5d2379640088bb6e338737fb48d97c58cf48\",\n \"cloud-sql-proxy.darwin.arm64\": \"fd374545705f2aa687d8e525a2efcbb9d356cc8af60d4dfa1a330cb59a7f9450\",\n \"cloud-sql-proxy.linux.386\": \"cf731f4becfb5a2de61f2998b2d660c5fb8f3067cbd3b86f5783ae9049c06f24\",\n \"cloud-sql-proxy.linux.amd64\": \"fae2766aac9d614a2bdef2f2a7778f3d054f3acd5ff07a81a9e300bd471512eb\",\n \"cloud-sql-proxy.linux.arm64\": \"da49fd73b0d33c0ab8e5dfc19dfb104cdd969ebd355eef8fd3b079c20a723c82\",\n \"cloud-sql-proxy.x64.exe\": \"01ec54c69dbb8118c0b181c33ff1469a5cdb2dddb49eb86b0b173f6c55dea0bc\",\n \"cloud-sql-proxy.x86.exe\": \"98c3b1897c80f2bc0b241b4452c18557a00cd86f89e4d7449c4ff1316e243c44\",\n})\n\nexport interface ProxyAsset {\n version: string\n /** e.g. \"cloud-sql-proxy.darwin.arm64\" */\n assetName: string\n downloadUrl: string\n /** Known sha256, or undefined when the version was overridden and we must fetch the release notes. */\n sha256?: string\n /** Cached file name, e.g. \"cloud-sql-proxy-2.24.1-darwin-arm64\" (+ \".exe\" on Windows). */\n fileName: string\n}\n\nconst ASSET_NAME_BY_PLATFORM_ARCH: Readonly<Record<string, string>> = Object.freeze({\n \"darwin:arm64\": \"cloud-sql-proxy.darwin.arm64\",\n \"darwin:x64\": \"cloud-sql-proxy.darwin.amd64\",\n \"linux:x64\": \"cloud-sql-proxy.linux.amd64\",\n \"linux:arm64\": \"cloud-sql-proxy.linux.arm64\",\n \"linux:ia32\": \"cloud-sql-proxy.linux.386\",\n \"win32:x64\": \"cloud-sql-proxy.x64.exe\",\n \"win32:ia32\": \"cloud-sql-proxy.x86.exe\",\n})\n\nfunction defaultVersion(): string {\n const override = process.env.MERIDIAN_PROXY_VERSION\n if (override !== undefined && override !== \"\") return override\n return PROXY_VERSION\n}\n\n/** Maps process.platform/process.arch to a published asset. Throws a CliError naming the platform when unsupported. */\nexport function resolveProxyAsset(options?: {\n platform?: NodeJS.Platform\n arch?: string\n version?: string\n}): ProxyAsset {\n const platform = options?.platform ?? process.platform\n const arch = options?.arch ?? process.arch\n const version = options?.version ?? defaultVersion()\n\n const assetName = ASSET_NAME_BY_PLATFORM_ARCH[`${platform}:${arch}`]\n if (assetName === undefined) {\n throw new CliError(`The Cloud SQL Auth Proxy has no published build for ${platform}/${arch}.`, {\n hint: \"Set MERIDIAN_PROXY_PATH to the path of a proxy binary you install yourself.\",\n })\n }\n\n const downloadUrl = `https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v${version}/${assetName}`\n const sha256Value = version === PROXY_VERSION ? PROXY_CHECKSUMS[assetName] : undefined\n const fileName = `cloud-sql-proxy-${version}-${platform}-${arch}${platform === \"win32\" ? \".exe\" : \"\"}`\n\n return {\n version,\n assetName,\n downloadUrl,\n ...(sha256Value !== undefined ? { sha256: sha256Value } : {}),\n fileName,\n }\n}\n\n/** sha256 hex of a buffer. */\nexport function sha256(data: Uint8Array): string {\n return createHash(\"sha256\").update(data).digest(\"hex\")\n}\n\nconst CHECKSUM_ROW_PATTERN = /\\[([^\\]]+)]\\([^)]*\\)\\s*\\|\\s*([0-9a-fA-F]{64})/g\n\n/** Pulls the `| [asset](url) | hash |` table out of a GitHub release body. */\nexport function parseChecksumTable(releaseBody: string): Record<string, string> {\n const table: Record<string, string> = {}\n for (const match of releaseBody.matchAll(CHECKSUM_ROW_PATTERN)) {\n const name = match[1]\n const hash = match[2]\n if (name !== undefined && hash !== undefined) table[name] = hash.toLowerCase()\n }\n return table\n}\n\nexport interface EnsureProxyOptions {\n version?: string\n /** Cache directory. Default proxyBinDir(). */\n dir?: string\n fetchImpl?: typeof fetch\n /** Progress in bytes; used for a spinner by the caller. */\n onProgress?: (received: number, total: number | undefined) => void\n /** Re-download even when cached. */\n force?: boolean\n}\n\nconst RELEASE_API_URL = \"https://api.github.com/repos/GoogleCloudPlatform/cloud-sql-proxy/releases/tags\"\n\n/**\n * Memoizes a looked-up (non-pinned-version) checksum for the life of the\n * process, so a cache-hit in ensureProxyBinary never re-hits the GitHub API\n * just to confirm a file it already verified moments (or a run) ago.\n */\nconst checksumCache = new Map<string, string>()\n\n/**\n * The known checksum for a pinned-version asset, or the one published for an\n * overridden version's GitHub release. Returns undefined (skip verification)\n * only when MERIDIAN_PROXY_SKIP_CHECKSUM=1 and no checksum could be found —\n * otherwise throws, because we must never install unverified bytes silently.\n */\nasync function resolveExpectedChecksum(asset: ProxyAsset, fetchImpl: typeof fetch): Promise<string | undefined> {\n if (asset.sha256 !== undefined) return asset.sha256\n\n const cacheKey = `${asset.version}:${asset.assetName}`\n const cached = checksumCache.get(cacheKey)\n if (cached !== undefined) return cached\n\n const skipAllowed = process.env.MERIDIAN_PROXY_SKIP_CHECKSUM === \"1\"\n const url = `${RELEASE_API_URL}/v${asset.version}`\n\n let response: Response\n try {\n response = await fetchImpl(url, { headers: { Accept: \"application/vnd.github+json\" } })\n } catch (error) {\n if (skipAllowed) return undefined\n throw new CliError(`Could not reach ${url} to look up the checksum for cloud-sql-proxy v${asset.version}.`, {\n hint: \"Check your network connection, or set MERIDIAN_PROXY_SKIP_CHECKSUM=1 to install without verifying the checksum, at your own risk.\",\n cause: error,\n })\n }\n\n if (!response.ok) {\n if (skipAllowed) return undefined\n throw new CliError(\n `Could not determine the sha256 checksum for cloud-sql-proxy v${asset.version} (GitHub release lookup for ${url} returned HTTP ${response.status}).`,\n {\n hint: \"Set MERIDIAN_PROXY_SKIP_CHECKSUM=1 to install without verifying the checksum, at your own risk.\",\n },\n )\n }\n\n const rawBody = await response.text()\n let releaseNotes = rawBody\n try {\n const parsed: unknown = JSON.parse(rawBody)\n if (typeof parsed === \"object\" && parsed !== null && \"body\" in parsed && typeof parsed.body === \"string\") {\n releaseNotes = parsed.body\n }\n } catch {\n // Not JSON — treat the raw text as the release body (tests may inject the table directly).\n }\n\n const checksum = parseChecksumTable(releaseNotes)[asset.assetName]\n if (checksum !== undefined) {\n checksumCache.set(cacheKey, checksum)\n return checksum\n }\n\n if (skipAllowed) return undefined\n throw new CliError(\n `Could not find a published sha256 checksum for ${asset.assetName} in the cloud-sql-proxy v${asset.version} release notes.`,\n { hint: \"Set MERIDIAN_PROXY_SKIP_CHECKSUM=1 to install without verifying the checksum, at your own risk.\" },\n )\n}\n\nfunction parseContentLength(header: string | null): number | undefined {\n if (header === null) return undefined\n const value = Number(header)\n return Number.isFinite(value) ? value : undefined\n}\n\nasync function readResponseBody(\n response: Response,\n onProgress: ((received: number, total: number | undefined) => void) | undefined,\n): Promise<Buffer> {\n const total = parseContentLength(response.headers.get(\"content-length\"))\n\n if (response.body === null) {\n const buffer = Buffer.from(await response.arrayBuffer())\n onProgress?.(buffer.byteLength, total)\n return buffer\n }\n\n const reader = response.body.getReader()\n const chunks: Uint8Array[] = []\n let received = 0\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n if (value !== undefined) {\n chunks.push(value)\n received += value.byteLength\n onProgress?.(received, total)\n }\n }\n return Buffer.concat(chunks)\n}\n\n/**\n * Absolute path to a verified, executable proxy binary, downloading it into the\n * cache on first use. `MERIDIAN_PROXY_PATH` short-circuits everything (bring\n * your own binary; used in CI and by `apt`-installed proxies).\n */\nexport async function ensureProxyBinary(options: EnsureProxyOptions = {}): Promise<string> {\n const overridePath = process.env.MERIDIAN_PROXY_PATH\n if (overridePath !== undefined && overridePath !== \"\") {\n if (!existsSync(overridePath)) {\n throw new CliError(`MERIDIAN_PROXY_PATH is set to ${overridePath}, but that file does not exist.`, {\n hint: \"Fix or unset MERIDIAN_PROXY_PATH.\",\n })\n }\n return overridePath\n }\n\n const asset = resolveProxyAsset(options.version !== undefined ? { version: options.version } : {})\n const dir = options.dir ?? proxyBinDir()\n const fetchImpl = options.fetchImpl ?? fetch\n const targetPath = join(dir, asset.fileName)\n\n mkdirSync(dir, { recursive: true })\n\n if (!options.force && existsSync(targetPath)) {\n const cached = readFileSync(targetPath)\n const expected = await resolveExpectedChecksum(asset, fetchImpl)\n if (expected === undefined || sha256(cached) === expected) return targetPath\n rmSync(targetPath, { force: true })\n }\n\n const response = await fetchImpl(asset.downloadUrl)\n if (!response.ok) {\n throw new CliError(\n `Failed to download the Cloud SQL Auth Proxy v${asset.version} from ${asset.downloadUrl} (HTTP ${response.status}).`,\n {\n hint: \"Check your network connection (and any corporate proxy settings), or set MERIDIAN_PROXY_PATH to a proxy binary you install yourself.\",\n },\n )\n }\n\n const buffer = await readResponseBody(response, options.onProgress)\n\n const expected = await resolveExpectedChecksum(asset, fetchImpl)\n const actual = sha256(buffer)\n if (expected !== undefined && actual !== expected) {\n throw new CliError(\n `Checksum mismatch for ${asset.assetName}: expected ${expected.slice(0, 12)}..., got ${actual.slice(0, 12)}....`,\n {\n hint: \"This can happen after a corrupted download or an untrusted network. Try again; if it persists, report this.\",\n },\n )\n }\n\n const tmpPath = join(dir, `.${asset.fileName}.${process.pid}.tmp`)\n writeFileSync(tmpPath, buffer)\n chmodSync(tmpPath, 0o755)\n renameSync(tmpPath, targetPath)\n\n return targetPath\n}\n","/**\n * Runs the Cloud SQL Auth Proxy v2 as a supervised child process.\n *\n * The proxy reads its access token once at startup, so it cannot pick up a\n * refreshed token on its own — the only way to hand it a new token is to\n * restart the process on the same port. That drops any in-flight MySQL\n * connections, which is an acceptable trade-off for a local dev database.\n * Every failure mode (a slow/failed readiness probe, a refresh that fails, a\n * crash) is reported through `onEvent` instead of throwing asynchronously, so\n * a long-running `meridian dev` session never dies from an unhandled\n * rejection — only the initial `startProxy()` call can reject.\n */\n\nimport type { ChildProcess } from \"node:child_process\"\nimport { spawn } from \"node:child_process\"\nimport { createConnection } from \"node:net\"\nimport { CliError, describeError } from \"../errors.js\"\n\nexport interface ProxyToken {\n access_token: string\n expires_at?: string\n}\n\nexport type ProxyEvent =\n | { type: \"starting\"; attempt: number }\n | { type: \"ready\"; port: number }\n | { type: \"log\"; line: string }\n | { type: \"token-refreshed\"; expiresAt?: string }\n | { type: \"restarting\"; reason: \"token-refresh\" | \"crash\" }\n | { type: \"exit\"; code: number | null; signal: NodeJS.Signals | null }\n | { type: \"error\"; message: string }\n\nexport interface StartProxyOptions {\n binaryPath: string\n instanceConnectionName: string\n token: ProxyToken\n port: number\n /** Default \"127.0.0.1\" */\n host?: string\n /** Called when the current token is close to expiry; must return a fresh token. */\n refreshToken?: () => Promise<ProxyToken>\n /** Refresh this long before expiry. Default 5 minutes. */\n refreshSkewMs?: number\n /** Fallback lifetime when the API omits expires_at. Default 55 minutes. */\n assumedLifetimeMs?: number\n /** Structured events for the caller's logger/spinner. */\n onEvent?: (event: ProxyEvent) => void\n /** How long to wait for readiness. Default 30s. */\n readyTimeoutMs?: number\n /** Base environment for the proxy child. Default `process.env`. */\n env?: NodeJS.ProcessEnv\n spawnImpl?: typeof spawn\n /** Injectable readiness probe; default is a TCP connect to host:port. */\n probeImpl?: (host: string, port: number) => Promise<boolean>\n /** Keep timers injectable for tests. */\n setTimeoutImpl?: typeof setTimeout\n}\n\nexport interface ManagedProxy {\n readonly host: string\n readonly port: number\n readonly instanceConnectionName: string\n /** True between a successful start and stop(). */\n readonly running: boolean\n /** Force a token refresh + restart now (used by tests and by `migrate`). */\n refresh(): Promise<void>\n /** Stops the token timer and terminates the child (SIGTERM → SIGKILL). Idempotent. */\n stop(): Promise<void>\n}\n\nconst PROBE_INTERVAL_MS = 150\nconst KILL_GRACE_MS = 2_000\nconst CRASH_BACKOFFS_MS = [200, 1_000, 3_000]\nconst MAX_CRASH_RESTARTS = CRASH_BACKOFFS_MS.length\nconst REFRESH_RETRY_BACKOFFS_MS = [30_000, 60_000, 120_000]\nconst MIN_REFRESH_DELAY_MS = 60_000\nconst LOG_RING_SIZE = 20\nconst STDERR_TAIL_LINES = 10\n\n/**\n * The exact argv the proxy is spawned with — exported so it can be asserted in\n * tests and printed in verbose mode. The access token is deliberately absent:\n * see {@link buildProxyEnv}.\n */\nexport function buildProxyArgs(input: { instanceConnectionName: string; host: string; port: number }): string[] {\n return [\"--address\", input.host, \"--port\", String(input.port), input.instanceConnectionName]\n}\n\n/**\n * The proxy accepts every flag as a `CSQL_PROXY_`-prefixed environment\n * variable, so the short-lived GCP access token goes in the environment rather\n * than in argv, where `ps` would show it to every other user on the machine.\n * Explicit flags still win over the environment, so `--address`/`--port` are\n * unaffected by anything the developer happens to have exported.\n */\nexport function buildProxyEnv(accessToken: string, base: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {\n return { ...base, CSQL_PROXY_TOKEN: accessToken }\n}\n\nfunction defaultProbe(host: string, port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = createConnection({ host, port })\n const finish = (ok: boolean) => {\n socket.removeAllListeners()\n socket.destroy()\n resolve(ok)\n }\n socket.once(\"connect\", () => finish(true))\n socket.once(\"error\", () => finish(false))\n socket.setTimeout(1_000, () => finish(false))\n })\n}\n\nfunction computeRefreshDelayMs(token: ProxyToken, refreshSkewMs: number, assumedLifetimeMs: number): number {\n let expiresAtMs: number | undefined\n if (token.expires_at !== undefined) {\n const parsed = new Date(token.expires_at).getTime()\n if (!Number.isNaN(parsed)) expiresAtMs = parsed\n }\n const effectiveExpiryMs = expiresAtMs ?? Date.now() + assumedLifetimeMs\n return Math.max(effectiveExpiryMs - Date.now() - refreshSkewMs, MIN_REFRESH_DELAY_MS)\n}\n\nfunction buildStartupFailureError(\n code: number | null,\n signal: NodeJS.Signals | null,\n lastLines: string[],\n): CliError {\n const tail = lastLines.slice(-STDERR_TAIL_LINES).join(\"\\n\")\n const lower = tail.toLowerCase()\n\n let hint = \"Run `meridian dev` again; if this keeps happening, check the instance connection name and your network.\"\n if (lower.includes(\"iam\") || lower.includes(\"permission\") || lower.includes(\"forbidden\")) {\n hint =\n \"The Meridian API's service account may be missing roles/cloudsql.client on the dev Cloud SQL instance. Contact Meridian support.\"\n } else if (lower.includes(\"invalid token\") || lower.includes(\"401\") || lower.includes(\"unauthorized\")) {\n hint = \"The access token appears to have expired. Retry `meridian dev` to mint a fresh one.\"\n } else if (lower.includes(\"address already in use\")) {\n hint = \"Another process is already listening on that port. Free it up, or retry with a different port.\"\n }\n\n const summary = `The Cloud SQL Auth Proxy exited before it was ready (code ${code ?? \"null\"}, signal ${signal ?? \"null\"}).`\n return new CliError(tail === \"\" ? summary : `${summary}\\n${tail}`, { hint })\n}\n\nfunction waitForReady(\n child: ChildProcess,\n probeImpl: (host: string, port: number) => Promise<boolean>,\n host: string,\n port: number,\n timeoutMs: number,\n setTimeoutImpl: typeof setTimeout,\n getLastLines: () => string[],\n): Promise<void> {\n return new Promise((resolve, reject) => {\n let settled = false\n let pollTimer: ReturnType<typeof setTimeoutImpl> | undefined\n let timeoutTimer: ReturnType<typeof setTimeoutImpl> | undefined\n\n const cleanup = () => {\n if (pollTimer !== undefined) clearTimeout(pollTimer)\n if (timeoutTimer !== undefined) clearTimeout(timeoutTimer)\n child.off(\"exit\", onExit)\n }\n\n function onExit(code: number | null, signal: NodeJS.Signals | null) {\n if (settled) return\n settled = true\n cleanup()\n reject(buildStartupFailureError(code, signal, getLastLines()))\n }\n\n function poll() {\n if (settled) return\n probeImpl(host, port)\n .then((ok) => {\n if (settled) return\n if (ok) {\n settled = true\n cleanup()\n resolve()\n } else {\n pollTimer = setTimeoutImpl(poll, PROBE_INTERVAL_MS)\n }\n })\n .catch(() => {\n if (!settled) pollTimer = setTimeoutImpl(poll, PROBE_INTERVAL_MS)\n })\n }\n\n child.on(\"exit\", onExit)\n timeoutTimer = setTimeoutImpl(() => {\n if (settled) return\n settled = true\n cleanup()\n reject(\n new CliError(`Timed out after ${timeoutMs}ms waiting for the Cloud SQL Auth Proxy to accept connections.`, {\n hint: \"The instance may be slow to reach, or readyTimeoutMs may need to be raised.\",\n }),\n )\n }, timeoutMs)\n poll()\n })\n}\n\n/** Spawns the proxy and resolves once it accepts TCP connections on host:port. */\nexport async function startProxy(options: StartProxyOptions): Promise<ManagedProxy> {\n const host = options.host ?? \"127.0.0.1\"\n const spawnImpl = options.spawnImpl ?? spawn\n const probeImpl = options.probeImpl ?? defaultProbe\n const setTimeoutImpl = options.setTimeoutImpl ?? setTimeout\n const refreshSkewMs = options.refreshSkewMs ?? 5 * 60_000\n const assumedLifetimeMs = options.assumedLifetimeMs ?? 55 * 60_000\n const readyTimeoutMs = options.readyTimeoutMs ?? 30_000\n const emit = (event: ProxyEvent) => options.onEvent?.(event)\n\n let stopped = false\n let running = false\n let expectingExit = false\n let currentToken = options.token\n let child: ChildProcess | undefined\n let refreshTimer: ReturnType<typeof setTimeoutImpl> | undefined\n let crashTimer: ReturnType<typeof setTimeoutImpl> | undefined\n let refreshBackoffIndex = 0\n // A lifetime budget, not a per-crash-episode one: once a ManagedProxy has\n // auto-restarted 3 times after a crash, any further crash goes straight to\n // a terminal error rather than resetting the count, so a truly flaky\n // binary/instance fails loudly instead of looping forever.\n let crashRestartsRemaining = MAX_CRASH_RESTARTS\n let attemptCounter = 0\n let cleanupFns: Array<() => void> = []\n const knownTokens = new Set<string>()\n const logRing: string[] = []\n\n function trackToken(token: ProxyToken) {\n if (token.access_token !== \"\") knownTokens.add(token.access_token)\n }\n\n function redact(text: string): string {\n let result = text\n for (const token of knownTokens) result = result.split(token).join(\"<redacted>\")\n return result\n }\n\n function pushLog(line: string) {\n const safeLine = redact(line)\n logRing.push(safeLine)\n if (logRing.length > LOG_RING_SIZE) logRing.shift()\n emit({ type: \"log\", line: safeLine })\n }\n\n function wireOutput(c: ChildProcess) {\n for (const stream of [c.stdout, c.stderr]) {\n if (stream === null) continue\n let buffer = \"\"\n const onData = (chunk: Buffer | string) => {\n buffer += chunk.toString()\n const lines = buffer.split(\"\\n\")\n buffer = lines.pop() ?? \"\"\n for (const line of lines) pushLog(line)\n }\n stream.on(\"data\", onData)\n cleanupFns.push(() => stream.off(\"data\", onData))\n }\n }\n\n function wireExit(c: ChildProcess) {\n c.once(\"exit\", (code, signal) => {\n if (child !== c) return\n const wasRunning = running\n const wasExpected = expectingExit\n running = false\n expectingExit = false\n emit({ type: \"exit\", code, signal })\n if (stopped || wasExpected || !wasRunning) return\n void handleCrash()\n })\n }\n\n async function spawnChild(): Promise<void> {\n attemptCounter += 1\n emit({ type: \"starting\", attempt: attemptCounter })\n const args = buildProxyArgs({\n instanceConnectionName: options.instanceConnectionName,\n host,\n port: options.port,\n })\n const c = spawnImpl(options.binaryPath, args, {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: buildProxyEnv(currentToken.access_token, options.env),\n })\n child = c\n wireOutput(c)\n wireExit(c)\n try {\n await waitForReady(c, probeImpl, host, options.port, readyTimeoutMs, setTimeoutImpl, () => logRing.slice())\n } catch (error) {\n // A child that never became ready is still running (readiness timeout) —\n // leaving it behind would orphan a proxy holding the port.\n expectingExit = true\n await killChild(c)\n if (child === c) child = undefined\n throw error\n }\n emit({ type: \"ready\", port: options.port })\n }\n\n function killChild(c: ChildProcess): Promise<void> {\n if (c.exitCode !== null || c.signalCode !== null) return Promise.resolve()\n return new Promise((resolve) => {\n let settled = false\n let killTimer: ReturnType<typeof setTimeoutImpl> | undefined\n const onExit = () => {\n if (settled) return\n settled = true\n if (killTimer !== undefined) clearTimeout(killTimer)\n resolve()\n }\n c.once(\"exit\", onExit)\n c.kill(\"SIGTERM\")\n killTimer = setTimeoutImpl(() => {\n if (!settled) c.kill(\"SIGKILL\")\n }, KILL_GRACE_MS)\n })\n }\n\n function scheduleRefresh(token: ProxyToken) {\n if (stopped || options.refreshToken === undefined) return\n if (refreshTimer !== undefined) clearTimeout(refreshTimer)\n const delayMs = computeRefreshDelayMs(token, refreshSkewMs, assumedLifetimeMs)\n refreshTimer = setTimeoutImpl(() => {\n refreshTimer = undefined\n void handleRefreshFire()\n }, delayMs)\n }\n\n function scheduleRefreshRetry() {\n if (stopped) return\n const delayMs = REFRESH_RETRY_BACKOFFS_MS[Math.min(refreshBackoffIndex, REFRESH_RETRY_BACKOFFS_MS.length - 1)] ?? 120_000\n refreshBackoffIndex += 1\n if (refreshTimer !== undefined) clearTimeout(refreshTimer)\n refreshTimer = setTimeoutImpl(() => {\n refreshTimer = undefined\n void handleRefreshFire()\n }, delayMs)\n }\n\n async function handleRefreshFire(): Promise<void> {\n if (stopped || options.refreshToken === undefined) return\n\n let newToken: ProxyToken\n try {\n newToken = await options.refreshToken()\n } catch (error) {\n emit({ type: \"error\", message: redact(`Token refresh failed: ${describeError(error)}`) })\n scheduleRefreshRetry()\n return\n }\n if (stopped) return\n\n trackToken(newToken)\n currentToken = newToken\n expectingExit = true\n emit({ type: \"restarting\", reason: \"token-refresh\" })\n\n try {\n const previous = child\n if (previous !== undefined) await killChild(previous)\n await spawnChild()\n } catch (error) {\n emit({ type: \"error\", message: redact(`Restart after token refresh failed: ${describeError(error)}`) })\n scheduleRefreshRetry()\n return\n }\n\n running = true\n refreshBackoffIndex = 0\n emit({ type: \"token-refreshed\", ...(newToken.expires_at !== undefined ? { expiresAt: newToken.expires_at } : {}) })\n scheduleRefresh(newToken)\n }\n\n async function handleCrash(): Promise<void> {\n if (stopped) return\n if (crashRestartsRemaining <= 0) {\n const tail = logRing.slice(-STDERR_TAIL_LINES).join(\"\\n\")\n emit({\n type: \"error\",\n message: `The Cloud SQL Auth Proxy crashed repeatedly and could not be restarted.${tail === \"\" ? \"\" : `\\n${tail}`}`,\n })\n return\n }\n\n const attemptIndex = MAX_CRASH_RESTARTS - crashRestartsRemaining\n const delayMs = CRASH_BACKOFFS_MS[attemptIndex] ?? (CRASH_BACKOFFS_MS[CRASH_BACKOFFS_MS.length - 1] ?? 3_000)\n crashRestartsRemaining -= 1\n emit({ type: \"restarting\", reason: \"crash\" })\n\n crashTimer = setTimeoutImpl(() => {\n crashTimer = undefined\n if (stopped) return\n spawnChild()\n .then(() => {\n running = true\n })\n .catch((error: unknown) => {\n emit({ type: \"error\", message: redact(describeError(error)) })\n void handleCrash()\n })\n }, delayMs)\n }\n\n async function refresh(): Promise<void> {\n if (stopped) return\n if (options.refreshToken === undefined) {\n throw new CliError(\"Cannot refresh the Cloud SQL Auth Proxy token: no refreshToken() was configured.\")\n }\n if (refreshTimer !== undefined) {\n clearTimeout(refreshTimer)\n refreshTimer = undefined\n }\n refreshBackoffIndex = 0\n await handleRefreshFire()\n }\n\n async function stop(): Promise<void> {\n if (stopped) return\n stopped = true\n\n if (refreshTimer !== undefined) clearTimeout(refreshTimer)\n refreshTimer = undefined\n if (crashTimer !== undefined) clearTimeout(crashTimer)\n crashTimer = undefined\n\n for (const cleanup of cleanupFns) cleanup()\n cleanupFns = []\n\n const current = child\n if (current !== undefined) {\n expectingExit = true\n await killChild(current)\n }\n running = false\n child = undefined\n }\n\n trackToken(currentToken)\n await spawnChild()\n running = true\n scheduleRefresh(currentToken)\n\n return {\n host,\n port: options.port,\n instanceConnectionName: options.instanceConnectionName,\n get running() {\n return running\n },\n refresh,\n stop,\n }\n}\n","/**\n * One shutdown path for every command that owns a background process (the\n * Cloud SQL Auth Proxy, the app's dev server, ...). `meridian dev` in\n * particular needs Ctrl-C to tear everything down cleanly, but also needs a\n * *second* Ctrl-C — the developer mashing the key because nothing seems to be\n * happening — to force an immediate exit rather than hang forever.\n */\n\nconst SIGNALS: readonly NodeJS.Signals[] = [\"SIGINT\", \"SIGTERM\", \"SIGHUP\"]\n\n/** 128 + signal number, the POSIX convention `$?` reports for a signal-terminated process. */\nconst SIGNAL_EXIT_CODES: Readonly<Partial<Record<NodeJS.Signals, number>>> = {\n SIGHUP: 129,\n SIGINT: 130,\n SIGTERM: 143,\n}\n\n/** Forced-exit code for a second signal received while handlers are still running. */\nconst FORCE_EXIT_CODE = 130\n\n/** Default ceiling on how long a single handler may take before it is abandoned. */\nconst DEFAULT_HANDLER_TIMEOUT_MS = 8_000\n\nexport type ShutdownHandler = (reason: ShutdownReason) => void | Promise<void>\n\nexport interface ShutdownReason {\n signal?: NodeJS.Signals\n error?: unknown\n}\n\nlet handlers: ShutdownHandler[] = []\nlet signalListeners: Map<NodeJS.Signals, () => void> | undefined\nlet isShuttingDown = false\nlet hasRun = false\nlet exitImpl: (code: number) => void = (code) => process.exit(code)\n\nfunction attachListeners(): void {\n if (signalListeners !== undefined) return\n const listeners = new Map<NodeJS.Signals, () => void>()\n for (const signal of SIGNALS) {\n const listener = (): void => {\n void handleSignal(signal)\n }\n process.on(signal, listener)\n listeners.set(signal, listener)\n }\n signalListeners = listeners\n}\n\nfunction detachListeners(): void {\n if (signalListeners === undefined) return\n for (const [signal, listener] of signalListeners) {\n process.off(signal, listener)\n }\n signalListeners = undefined\n}\n\nasync function handleSignal(signal: NodeJS.Signals): Promise<void> {\n if (isShuttingDown) {\n exitImpl(FORCE_EXIT_CODE)\n return\n }\n isShuttingDown = true\n await runShutdownHandlers({ signal })\n process.exitCode = exitCodeForSignal(signal)\n}\n\n/**\n * Runs `handler(reason)` with a hard timeout so one stuck handler (a hung\n * child process, a network call that never settles) can never keep the\n * terminal open forever — after the timeout we simply move on.\n */\nfunction runHandlerWithTimeout(\n handler: ShutdownHandler,\n reason: ShutdownReason,\n timeoutMs: number,\n): Promise<void> {\n return new Promise((resolve) => {\n let settled = false\n const timer = setTimeout(() => {\n if (settled) return\n settled = true\n resolve()\n }, timeoutMs)\n timer.unref?.()\n\n Promise.resolve()\n .then(() => handler(reason))\n .catch(() => {\n // A failing handler must never block the rest of shutdown.\n })\n .then(() => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n resolve()\n })\n })\n}\n\n/**\n * Registers a cleanup handler for SIGINT/SIGTERM/SIGHUP. Handlers run once,\n * in reverse registration order (LIFO — the most recently acquired resource\n * is released first), each guarded so one failure does not block the rest.\n * Returns an unregister function.\n */\nexport function onShutdown(handler: ShutdownHandler): () => void {\n handlers.push(handler)\n attachListeners()\n\n let unregistered = false\n return () => {\n if (unregistered) return\n unregistered = true\n const index = handlers.indexOf(handler)\n if (index !== -1) handlers.splice(index, 1)\n if (handlers.length === 0) detachListeners()\n }\n}\n\n/** Runs every handler now (used by commands that finish normally). Idempotent. */\nexport async function runShutdownHandlers(\n reason: ShutdownReason = {},\n timeoutMs: number = DEFAULT_HANDLER_TIMEOUT_MS,\n): Promise<void> {\n if (hasRun) return\n hasRun = true\n\n const toRun = [...handlers].reverse()\n for (const handler of toRun) {\n await runHandlerWithTimeout(handler, reason, timeoutMs)\n }\n}\n\n/** Test helper: clears handlers and removes the process listeners. */\nexport function resetShutdown(): void {\n detachListeners()\n handlers = []\n isShuttingDown = false\n hasRun = false\n exitImpl = (code) => process.exit(code)\n}\n\n/** Exit code convention for a signal-triggered exit (128 + signal number). */\nexport function exitCodeForSignal(signal: NodeJS.Signals): number {\n return SIGNAL_EXIT_CODES[signal] ?? 128\n}\n\n/** Test seam: replaces the forced-exit implementation so tests never kill the test runner. */\nexport function __setExitImpl(fn: (code: number) => void): void {\n exitImpl = fn\n}\n","/**\n * The shared \"make the dev database reachable\" flow behind `meridian dev`,\n * `meridian migrate`, `meridian db seed` and `meridian db shell`: ensure the\n * database is provisioned, fetch fresh credentials and a proxy token, spawn\n * the Cloud SQL Auth Proxy, wait for MySQL to answer, and patch\n * `DATABASE_URL` into the project's `.env`. Every collaborator is injectable\n * (see {@link SessionDeps}) so the whole flow can be exercised offline.\n */\n\nimport type { ApiClient } from \"./api.js\"\nimport type { DevCredentials, DevDatabase, Id, ProxyToken as ApiProxyToken } from \"./api-types.js\"\nimport { createApiClient } from \"./client.js\"\nimport { workingDirectory } from \"./context.js\"\nimport type { DbConnectionInfo } from \"./db/connection.js\"\nimport { connectionInfoFromCredentials, waitForDatabase } from \"./db/connection.js\"\nimport type { EnvPatch, PatchEnvResult } from \"./env-file.js\"\nimport { buildDatabaseUrl, patchEnvFile, redactDatabaseUrl } from \"./env-file.js\"\nimport { CliError, describeError, isCliError } from \"./errors.js\"\nimport { debug, detail, step, success, warn, withSpinner } from \"./output.js\"\nimport type { Spinner } from \"./output.js\"\nimport { envFilePath } from \"./paths.js\"\nimport { findFreePort } from \"./port.js\"\nimport { assertManagedDatasource } from \"./prisma.js\"\nimport type { FindFreePortOptions } from \"./port.js\"\nimport { ensureProxyBinary } from \"./proxy/binary.js\"\nimport type { EnsureProxyOptions } from \"./proxy/binary.js\"\nimport { startProxy } from \"./proxy/proxy.js\"\nimport type { ManagedProxy, ProxyEvent, ProxyToken as ProxyProxyToken } from \"./proxy/proxy.js\"\nimport type { LinkedProject } from \"./project.js\"\nimport { requireProject } from \"./project.js\"\nimport { onShutdown } from \"./signals.js\"\n\n/** Everything a `startDevSession()` caller gets back to run its own command logic. */\nexport interface DevSessionInfo {\n project: LinkedProject\n devDatabase: DevDatabase\n credentials: DevCredentials\n connection: DbConnectionInfo\n databaseUrl: string\n /** Undefined when the API did not report a shadow database for this dev database. */\n shadowDatabaseUrl?: string\n proxy: ManagedProxy\n /**\n * process.env plus DATABASE_URL (and SHADOW_DATABASE_URL, and\n * {@link DEV_DATABASE_ID_ENV}), for handing to child processes.\n */\n env: NodeJS.ProcessEnv\n /** Result of patching .env, or undefined when patching was skipped. */\n envPatch?: PatchEnvResult\n /** Tears down the proxy and unregisters the shutdown handler. Idempotent. */\n stop(): Promise<void>\n}\n\nexport interface StartSessionOptions {\n /** Defaults to createApiClient(). */\n client?: ApiClient\n /** Defaults to requireProject(workingDirectory()). */\n project?: LinkedProject\n /** Patch DATABASE_URL into <root>/.env. Default true. */\n patchEnv?: boolean\n /** .env file name (relative to the project root). Default \".env\". */\n envFile?: string\n /** Preferred local port for the proxy. */\n port?: number\n /** Keep refreshing the proxy token in the background. Default true. */\n refreshToken?: boolean\n /** Register a SIGINT/SIGTERM handler that stops the proxy. Default true. */\n handleSignals?: boolean\n /** Wait for MySQL to answer before returning. Default true. */\n waitForDb?: boolean\n /** Overrides for tests. */\n deps?: Partial<SessionDeps>\n}\n\n/** Every side-effecting collaborator, injectable so the whole flow is testable offline. */\nexport interface SessionDeps {\n ensureProxyBinary: typeof import(\"./proxy/binary.js\").ensureProxyBinary\n startProxy: typeof import(\"./proxy/proxy.js\").startProxy\n findFreePort: typeof import(\"./port.js\").findFreePort\n patchEnvFile: typeof import(\"./env-file.js\").patchEnvFile\n waitForDatabase: typeof import(\"./db/connection.js\").waitForDatabase\n sleep: (ms: number) => Promise<void>\n now: () => number\n}\n\nfunction defaultSleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction resolveDeps(overrides?: Partial<SessionDeps>): SessionDeps {\n return {\n ensureProxyBinary,\n startProxy,\n findFreePort,\n patchEnvFile,\n waitForDatabase,\n sleep: defaultSleep,\n now: () => Date.now(),\n ...overrides,\n }\n}\n\nconst DEFAULT_POLL_TIMEOUT_MS = 5 * 60_000\nconst DEFAULT_POLL_INTERVAL_MS = 2_000\nconst NOT_FOUND_GRACE_MS = 30_000\nconst DEFAULT_PORT_START = 3307\n\n/**\n * The provisioned dev database's id, exported to every child of a managed\n * session (see {@link DevSessionInfo.env}) so the Meridian SDK can send it as\n * `devDatabaseId` on the app's identify call — that is what lets the API bill a\n * shop install against this developer's dev database while the app runs\n * locally. Only ever set alongside a live session, so a plain `npm run dev`\n * (no proxy, no credentials) never claims a dev database.\n *\n * Sibling of `DEV_GUARD_ENV` in `./run.js`, which every child of `meridian\n * dev` also carries.\n */\nexport const DEV_DATABASE_ID_ENV = \"MERIDIAN_DEV_DATABASE_ID\"\n\nexport interface EnsureDevDatabaseReadyOptions {\n timeoutMs?: number\n intervalMs?: number\n sleep?: (ms: number) => Promise<void>\n now?: () => number\n onStatus?: (status: string, elapsedMs: number) => void\n}\n\n/**\n * The API reports why provisioning failed in the dev database's\n * `error_message` (populated only while `status` is `error`), so it is quoted\n * verbatim rather than making the developer go and look it up.\n */\nfunction provisioningFailedError(devDatabase: DevDatabase): CliError {\n const reason = devDatabase.error_message\n const detail = typeof reason === \"string\" && reason.trim() !== \"\" ? ` ${reason.trim()}` : \"\"\n return new CliError(`Provisioning the development database failed.${detail}`, {\n hint: \"Check the Meridian dashboard for details, or contact support if this keeps happening.\",\n })\n}\n\nfunction provisioningTimeoutError(): CliError {\n return new CliError(\"Timed out waiting for the development database to be provisioned.\", {\n hint: \"Try `meridian dev` again in a few minutes, and check the Meridian dashboard for its status.\",\n })\n}\n\nfunction provisioningNotFoundError(): CliError {\n return new CliError(\"The Meridian API never finished creating the development database.\", {\n hint: \"Try `meridian dev` again; if this keeps happening, contact Meridian support.\",\n })\n}\n\nasync function pollDevDatabase(\n client: ApiClient,\n appId: Id,\n options: EnsureDevDatabaseReadyOptions,\n spinner: Spinner,\n): Promise<DevDatabase> {\n const timeoutMs = options.timeoutMs ?? DEFAULT_POLL_TIMEOUT_MS\n const intervalMs = options.intervalMs ?? DEFAULT_POLL_INTERVAL_MS\n const sleep = options.sleep ?? defaultSleep\n const now = options.now ?? Date.now\n\n const start = now()\n const report = (status: string): void => {\n const elapsedMs = now() - start\n spinner.update(`Provisioning the development database... (${status}, ${Math.round(elapsedMs / 1000)}s)`)\n options.onStatus?.(status, elapsedMs)\n }\n\n let current = await client.ensureDevDatabase(appId)\n report(current.status)\n if (current.status === \"ready\") return current\n if (current.status === \"error\") throw provisioningFailedError(current)\n\n let notFoundSince: number | undefined\n\n for (;;) {\n if (now() - start >= timeoutMs) throw provisioningTimeoutError()\n await sleep(intervalMs)\n\n const fetched = await client.getDevDatabase(appId)\n if (fetched === null) {\n if (notFoundSince === undefined) notFoundSince = now()\n if (now() - notFoundSince >= NOT_FOUND_GRACE_MS) throw provisioningNotFoundError()\n report(\"provisioning\")\n continue\n }\n\n notFoundSince = undefined\n current = fetched\n report(current.status)\n if (current.status === \"ready\") return current\n if (current.status === \"error\") throw provisioningFailedError(current)\n }\n}\n\n/**\n * POSTs the ensure endpoint and polls GET until `ready`, with a spinner.\n * Exported separately because `db reset` wants it without the proxy.\n */\nexport async function ensureDevDatabaseReady(\n client: ApiClient,\n appId: Id,\n options: EnsureDevDatabaseReadyOptions = {},\n): Promise<DevDatabase> {\n return withSpinner(\n \"Provisioning the development database...\",\n (spinner) => pollDevDatabase(client, appId, options, spinner),\n { success: (db) => `Development database \"${db.database}\" is ready.` },\n )\n}\n\n/**\n * `ApiProxyToken`'s zod-inferred `expires_at?: string | null` is not\n * assignable to the proxy module's stricter `expires_at?: string` under\n * `exactOptionalPropertyTypes` — this drops the key instead of ever setting\n * it to `null`/`undefined`, which is also how the proxy asks to fall back to\n * its assumed token lifetime.\n */\nfunction toProxyToken(token: ApiProxyToken): ProxyProxyToken {\n return {\n access_token: token.access_token,\n ...(typeof token.expires_at === \"string\" ? { expires_at: token.expires_at } : {}),\n }\n}\n\nfunction formatMb(bytes: number): string {\n return (bytes / (1024 * 1024)).toFixed(1)\n}\n\n/** First value that is a non-blank string, treating null/undefined/\"\" alike. */\nfunction firstNonEmpty(...values: Array<string | null | undefined>): string | undefined {\n for (const value of values) {\n if (typeof value === \"string\" && value.trim() !== \"\") return value\n }\n return undefined\n}\n\n/**\n * {@link DEV_DATABASE_ID_ENV}'s value. `idSchema` allows a number or a string,\n * so the id is stringified; a blank one is treated as absent rather than\n * exported as an empty variable the SDK would then send as `devDatabaseId`.\n */\nfunction devDatabaseIdValue(devDatabase: DevDatabase): string | undefined {\n return firstNonEmpty(String(devDatabase.id))\n}\n\nfunction logEnvPatch(result: PatchEnvResult, databaseUrl: string, wroteShadow: boolean): void {\n const redacted = redactDatabaseUrl(databaseUrl)\n const names = wroteShadow ? \"DATABASE_URL and SHADOW_DATABASE_URL\" : \"DATABASE_URL\"\n if (result.created) {\n success(`Created ${result.path} with DATABASE_URL=${redacted}`)\n } else if (result.changed) {\n success(`Updated ${names} in ${result.path} (${redacted})`)\n } else {\n debug(`${result.path} already has the correct ${names}.`)\n }\n if (result.backedUp) detail(`Backed up the previous file to ${result.path}.backup`)\n}\n\n/**\n * Maps proxy lifecycle events onto `output.ts`. Never prints a token or\n * anything derived from one — the proxy module itself pre-redacts `log`\n * lines and error messages, but the mapping here is deliberately narrow too.\n */\nfunction handleProxyEvent(event: ProxyEvent): void {\n switch (event.type) {\n case \"starting\":\n debug(`Starting the Cloud SQL Auth Proxy (attempt ${event.attempt}).`)\n return\n case \"ready\":\n debug(`Cloud SQL Auth Proxy listening on port ${event.port}.`)\n return\n case \"log\":\n debug(event.line)\n return\n case \"token-refreshed\":\n step(\"Refreshed the Cloud SQL Auth Proxy token.\")\n return\n case \"restarting\":\n if (event.reason === \"crash\") warn(\"The Cloud SQL Auth Proxy crashed; restarting it.\")\n else debug(\"Restarting the Cloud SQL Auth Proxy with a refreshed token...\")\n return\n case \"exit\":\n debug(`Cloud SQL Auth Proxy exited (code ${event.code ?? \"null\"}, signal ${event.signal ?? \"null\"}).`)\n return\n case \"error\":\n warn(`Cloud SQL Auth Proxy error: ${event.message} Restart \\`meridian dev\\` if the database becomes unreachable.`)\n return\n }\n}\n\n/** Runs the whole \"make the dev database reachable\" flow, logging each step. */\nexport async function startDevSession(options: StartSessionOptions = {}): Promise<DevSessionInfo> {\n const deps = resolveDeps(options.deps)\n let proxy: ManagedProxy | undefined\n\n try {\n const project = options.project ?? requireProject(workingDirectory())\n // Before anything is provisioned, rotated or downloaded: a schema that\n // ignores DATABASE_URL makes every step below pointless.\n if (project.config.skip_datasource_check !== true) assertManagedDatasource(project.root)\n\n const client = options.client ?? createApiClient()\n const appId = project.config.app_id\n\n const devDatabase = await ensureDevDatabaseReady(client, appId, { sleep: deps.sleep, now: deps.now })\n\n const credentials = await withSpinner(\n \"Fetching database credentials...\",\n () => client.issueCredentials(appId),\n {\n success: (creds) =>\n `Fetched credentials for database \"${creds.database}\"${\n typeof creds.expires_at === \"string\" ? ` (expire ${creds.expires_at})` : \"\"\n }.`,\n },\n )\n\n const proxyToken = await withSpinner(\n \"Requesting a Cloud SQL Auth Proxy token...\",\n () => client.issueProxyToken(appId),\n { success: \"Issued a Cloud SQL Auth Proxy token.\" },\n )\n\n const binaryPath = await withSpinner(\n \"Preparing the Cloud SQL Auth Proxy...\",\n (spinner) => {\n const ensureOptions: EnsureProxyOptions = {\n onProgress: (received, total) => {\n spinner.update(\n total !== undefined\n ? `Downloading the Cloud SQL Auth Proxy... (${formatMb(received)}/${formatMb(total)} MB)`\n : `Downloading the Cloud SQL Auth Proxy... (${formatMb(received)} MB)`,\n )\n },\n }\n return deps.ensureProxyBinary(ensureOptions)\n },\n { success: \"Cloud SQL Auth Proxy is ready.\" },\n )\n\n const findPortOptions: FindFreePortOptions = { start: DEFAULT_PORT_START }\n if (options.port !== undefined) findPortOptions.preferred = options.port\n const port = await deps.findFreePort(findPortOptions)\n if (options.port !== undefined && port !== options.port) {\n throw new CliError(`Port ${options.port} is already in use.`, {\n hint: \"Pick a different port with --port, or free up that port and try again.\",\n })\n }\n\n // Both sources are nullable columns on the API side, so an empty string or\n // an explicit null has to be treated the same as a missing field.\n const instanceConnectionName = firstNonEmpty(\n credentials.instance_connection_name,\n proxyToken.instance_connection_name,\n devDatabase.instance_connection_name,\n )\n if (instanceConnectionName === undefined) {\n throw new CliError(\"The Meridian API did not return a Cloud SQL instance connection name.\", {\n hint: \"Try again, or contact Meridian support if this persists.\",\n })\n }\n\n proxy = await withSpinner(\n `Starting the Cloud SQL Auth Proxy on 127.0.0.1:${port}...`,\n () =>\n deps.startProxy({\n binaryPath,\n instanceConnectionName,\n token: toProxyToken(proxyToken),\n port,\n ...(options.refreshToken !== false\n ? { refreshToken: async () => toProxyToken(await client.issueProxyToken(appId)) }\n : {}),\n onEvent: handleProxyEvent,\n }),\n { success: `Cloud SQL Auth Proxy listening on 127.0.0.1:${port}.` },\n )\n\n const connection = connectionInfoFromCredentials(credentials, { host: proxy.host, port: proxy.port })\n\n if (options.waitForDb !== false) {\n await withSpinner(\n \"Waiting for MySQL to accept connections...\",\n () => deps.waitForDatabase(connection),\n { success: \"MySQL is accepting connections.\" },\n )\n }\n\n const databaseUrl = buildDatabaseUrl({\n username: credentials.username,\n password: credentials.password,\n port: proxy.port,\n database: credentials.database,\n })\n\n // `prisma migrate dev` replays the migration history into a shadow\n // database and diffs it against the schema. It creates one itself unless\n // handed a URL, and a dev user scoped to a single schema cannot — hence\n // the second database the API provisions per developer.\n const shadowDatabase = firstNonEmpty(credentials.shadow_database, devDatabase.shadow_database)\n const shadowDatabaseUrl =\n shadowDatabase === undefined\n ? undefined\n : buildDatabaseUrl({\n username: credentials.username,\n password: credentials.password,\n port: proxy.port,\n database: shadowDatabase,\n })\n\n // Exported into the child environment only (below), never written to\n // `.env`: it belongs to this session, and a stale one left behind in a\n // committed-adjacent file would tag installs long after the session ended.\n const devDatabaseId = devDatabaseIdValue(devDatabase)\n\n let envPatch: PatchEnvResult | undefined\n if (options.patchEnv !== false) {\n const envPath = envFilePath(project.root, options.envFile)\n const patch: EnvPatch = {\n DATABASE_URL: databaseUrl,\n ...(shadowDatabaseUrl !== undefined ? { SHADOW_DATABASE_URL: shadowDatabaseUrl } : {}),\n }\n envPatch = deps.patchEnvFile(envPath, patch, { backup: true })\n logEnvPatch(envPatch, databaseUrl, shadowDatabaseUrl !== undefined)\n }\n\n let unregisterShutdown: (() => void) | undefined\n const stop = async (): Promise<void> => {\n if (unregisterShutdown !== undefined) {\n const unregister = unregisterShutdown\n unregisterShutdown = undefined\n unregister()\n }\n if (proxy !== undefined) await proxy.stop()\n }\n\n if (options.handleSignals !== false) {\n unregisterShutdown = onShutdown(() => stop())\n }\n\n return {\n project,\n devDatabase,\n credentials,\n connection,\n databaseUrl,\n ...(shadowDatabaseUrl !== undefined ? { shadowDatabaseUrl } : {}),\n proxy,\n env: {\n ...process.env,\n DATABASE_URL: databaseUrl,\n ...(shadowDatabaseUrl !== undefined ? { SHADOW_DATABASE_URL: shadowDatabaseUrl } : {}),\n ...(devDatabaseId !== undefined ? { [DEV_DATABASE_ID_ENV]: devDatabaseId } : {}),\n },\n ...(envPatch !== undefined ? { envPatch } : {}),\n stop,\n }\n } catch (error) {\n if (proxy !== undefined) {\n await proxy.stop().catch(() => {})\n }\n if (isCliError(error)) throw error\n throw new CliError(`Failed to start the Meridian development session: ${describeError(error)}`, { cause: error })\n }\n}\n","/**\n * The built-in fallback SQL client for `meridian db shell`, used whenever the\n * `mysql` binary isn't on PATH (or `--repl` forces it): a minimal line-buffered\n * REPL over mysql2, plus the single-statement runner `-e/--execute` shares\n * with it, and the `findExecutable` PATH probe that decides which path to take.\n *\n * mysql2's `connection.query()` resolves `[rows, fields]` for a `SELECT` and\n * `[ResultSetHeader, undefined]` for a write; `createSqlConnection` (in\n * `lib/db/connection.ts`) passes that straight through, so both\n * `interpretQueryResult` and the fakes tests inject speak that same tuple\n * shape.\n */\n\nimport { accessSync, constants as fsConstants } from \"node:fs\"\nimport { delimiter, join } from \"node:path\"\nimport { createInterface } from \"node:readline\"\nimport type { DbConnectionInfo, SqlConnection } from \"../lib/db/connection.js\"\nimport { toDatabaseError } from \"../lib/db/connection.js\"\nimport { error, hint, printJson, printLine } from \"../lib/output.js\"\n\nfunction candidateNames(name: string): string[] {\n if (process.platform !== \"win32\") return [name]\n if (/\\.[^./\\\\]+$/.test(name)) return [name]\n const pathExt = process.env.PATHEXT ?? \".EXE;.CMD;.BAT;.COM\"\n const extensions = pathExt.split(\";\").filter((ext) => ext !== \"\")\n return [name, ...extensions.map((ext) => `${name}${ext.toLowerCase()}`)]\n}\n\n/**\n * Default `DbDeps.findExecutable`: scans `PATH` the way a shell would,\n * without invoking one (so it never risks running an arbitrary shell\n * builtin). On Windows, also tries each `PATHEXT` extension when `name` has\n * none of its own.\n */\nexport function findExecutable(name: string): string | null {\n const pathValue = process.env.PATH ?? \"\"\n const dirs = pathValue.split(delimiter).filter((dir) => dir !== \"\")\n const candidates = candidateNames(name)\n\n for (const dir of dirs) {\n for (const candidate of candidates) {\n const fullPath = join(dir, candidate)\n try {\n accessSync(fullPath, fsConstants.X_OK)\n return fullPath\n } catch {\n continue\n }\n }\n }\n return null\n}\n\nexport interface QueryRowsOutcome {\n kind: \"rows\"\n rows: Array<Record<string, unknown>>\n}\n\nexport interface QueryWriteOutcome {\n kind: \"write\"\n affectedRows: number\n}\n\nexport type QueryOutcome = QueryRowsOutcome | QueryWriteOutcome\n\nfunction isResultSetHeaderLike(value: unknown): value is { affectedRows: number } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"affectedRows\" in value &&\n typeof (value as { affectedRows: unknown }).affectedRows === \"number\"\n )\n}\n\n/** Interprets a raw `connection.query()` result as either row data or a write's affected-row count. */\nexport function interpretQueryResult(raw: unknown): QueryOutcome {\n const first = Array.isArray(raw) ? raw[0] : raw\n if (Array.isArray(first)) {\n return { kind: \"rows\", rows: first as Array<Record<string, unknown>> }\n }\n if (isResultSetHeaderLike(first)) {\n return { kind: \"write\", affectedRows: first.affectedRows }\n }\n return { kind: \"write\", affectedRows: 0 }\n}\n\nconst MAX_CELL_WIDTH = 60\n\nfunction cellText(value: unknown): string {\n if (value === null || value === undefined) return \"NULL\"\n if (value instanceof Date) return value.toISOString()\n if (Buffer.isBuffer(value)) return value.toString(\"hex\")\n return String(value)\n}\n\nfunction truncateCell(text: string): string {\n return text.length > MAX_CELL_WIDTH ? `${text.slice(0, MAX_CELL_WIDTH - 1)}…` : text\n}\n\n/** Renders rows as a simple aligned text table: header, separator, rows, then a \"(N rows)\" footer. */\nexport function formatTable(rows: Array<Record<string, unknown>>): string {\n if (rows.length === 0) return \"(0 rows)\"\n\n const columns = Object.keys(rows[0] ?? {})\n const cells = rows.map((row) => columns.map((column) => truncateCell(cellText(row[column]))))\n const widths = columns.map((column, i) => Math.max(column.length, ...cells.map((row) => row[i]?.length ?? 0)))\n\n const renderRow = (values: string[]): string => values.map((value, i) => value.padEnd(widths[i] ?? 0)).join(\" \")\n\n const lines = [\n renderRow(columns),\n renderRow(widths.map((width) => \"-\".repeat(width))),\n ...cells.map((row) => renderRow(row)),\n `(${rows.length} row${rows.length === 1 ? \"\" : \"s\"})`,\n ]\n return lines.join(\"\\n\")\n}\n\nasync function printQueryOutcome(raw: unknown, json: boolean): Promise<void> {\n const outcome = interpretQueryResult(raw)\n if (outcome.kind === \"rows\") {\n if (json) printJson(outcome.rows)\n else printLine(formatTable(outcome.rows))\n return\n }\n if (json) printJson({ affected_rows: outcome.affectedRows })\n else printLine(`Query OK, ${outcome.affectedRows} row${outcome.affectedRows === 1 ? \"\" : \"s\"} affected.`)\n}\n\n/** Runs one statement, printing its result or a redacted, actionable error. Never throws. */\nasync function runStatement(\n connection: SqlConnection,\n connectionInfo: DbConnectionInfo,\n sql: string,\n json = false,\n): Promise<boolean> {\n try {\n const raw = await connection.query(sql)\n await printQueryOutcome(raw, json)\n return true\n } catch (err) {\n const dbError = toDatabaseError(err, connectionInfo)\n error(dbError.message)\n if (dbError.hint !== undefined) hint(dbError.hint)\n return false\n }\n}\n\n/** Runs a single statement for `db shell -e/--execute` and returns the process exit code (0, or 1 on a query error). */\nexport async function executeStatement(\n connection: SqlConnection,\n connectionInfo: DbConnectionInfo,\n sql: string,\n options: { json?: boolean } = {},\n): Promise<number> {\n const ok = await runStatement(connection, connectionInfo, sql, options.json === true)\n return ok ? 0 : 1\n}\n\nexport interface RunReplOptions {\n connection: SqlConnection\n connectionInfo: DbConnectionInfo\n input: NodeJS.ReadableStream\n output: NodeJS.WritableStream\n}\n\nconst EXIT_COMMANDS = new Set([\"exit\", \"quit\", \"\\\\q\"])\n\n/**\n * Minimal line-buffered SQL REPL: accumulates input until a line ends with\n * `;` (so multi-line statements work), then runs it through `connection`.\n * `exit`/`quit`/`\\q` and EOF end the session; Ctrl-C clears the current\n * buffer instead of killing the process, unless the buffer is already empty.\n * Kept as a plain function over injected `input`/`output` streams so tests\n * can drive it without a real TTY.\n */\nexport function runRepl(options: RunReplOptions): Promise<number> {\n const { connection, connectionInfo, input, output } = options\n const rl = createInterface({ input, output, prompt: `meridian(${connectionInfo.database})> ` })\n\n let buffer = \"\"\n let settled = false\n\n return new Promise<number>((resolve) => {\n const finish = (code: number): void => {\n if (settled) return\n settled = true\n rl.close()\n resolve(code)\n }\n\n rl.on(\"line\", (line) => {\n const trimmed = line.trim()\n if (buffer === \"\" && EXIT_COMMANDS.has(trimmed.toLowerCase())) {\n finish(0)\n return\n }\n\n buffer = buffer === \"\" ? line : `${buffer}\\n${line}`\n if (!trimmed.endsWith(\";\")) {\n if (!settled) rl.prompt()\n return\n }\n\n const statement = buffer\n buffer = \"\"\n void runStatement(connection, connectionInfo, statement).then(() => {\n if (!settled) rl.prompt()\n })\n })\n\n rl.on(\"SIGINT\", () => {\n if (buffer !== \"\") {\n buffer = \"\"\n output.write(\"\\n\")\n if (!settled) rl.prompt()\n } else {\n finish(0)\n }\n })\n\n rl.once(\"close\", () => finish(0))\n\n rl.prompt()\n })\n}\n","/**\n * `meridian dev` — the flagship command. `startDevSession()` (in\n * `../lib/session.js`) already does the heavy lifting (provision, credentials,\n * proxy token, proxy binary, spawn the Cloud SQL Auth Proxy, patch `.env`);\n * this command's job is narrower: work out what the app's own dev command is,\n * run it with `DATABASE_URL` pointed at the local proxy, and make sure the\n * proxy and the app are always torn down together, in the right order.\n */\n\nimport type { Command } from \"commander\"\nimport { isJsonOutput, workingDirectory } from \"../lib/context.js\"\nimport { CliError } from \"../lib/errors.js\"\nimport { redactDatabaseUrl } from \"../lib/env-file.js\"\nimport { parsePortOption } from \"../lib/options.js\"\nimport { keyValues, log, printJson, step, style } from \"../lib/output.js\"\nimport type { LinkedProject } from \"../lib/project.js\"\nimport { requireProject } from \"../lib/project.js\"\nimport { assertNotSelfInvoking, isInsideDevSession, parseCommandString, readPackageScript, startProcess } from \"../lib/run.js\"\nimport type { DevSessionInfo, StartSessionOptions } from \"../lib/session.js\"\nimport { startDevSession } from \"../lib/session.js\"\nimport { exitCodeForSignal, onShutdown } from \"../lib/signals.js\"\n\n/** Every side-effecting collaborator `runDev` calls, injectable so tests never touch the network, a real proxy, or a real child process. */\nexport interface DevDeps {\n startDevSession: typeof startDevSession\n startProcess: typeof startProcess\n readPackageScript: typeof readPackageScript\n requireProject: typeof requireProject\n}\n\nexport interface DevOptions {\n /** Preferred local port for the Cloud SQL Auth Proxy. */\n port?: number\n /** .env file to patch, relative to the project root. Default \".env\". */\n envFile?: string\n /** `--`-passthrough argv, verbatim: command[0] plus the rest as args. Wins over `dev_command` and the default. */\n command?: string[]\n /** `--no-env`: don't touch any .env file; the summary/JSON still prints DATABASE_URL for manual use. */\n noEnv?: boolean\n deps?: Partial<DevDeps>\n}\n\nfunction defaultDeps(): DevDeps {\n return { startDevSession, startProcess, readPackageScript, requireProject }\n}\n\nconst RECURSION_HINT =\n \"Set `dev_command` in `.meridian/project.json` to the underlying command (e.g. `next dev`), \" +\n \"or run `meridian dev -- next dev` to bypass the script entirely.\"\n\n/** The `dev` script would call back into this command, so nothing has started yet. */\nfunction selfInvokingScriptError(): CliError {\n return new CliError('This project\\'s \"dev\" script runs `meridian dev`, which would start it again in a loop.', {\n hint: RECURSION_HINT,\n })\n}\n\n/** We are already a child of a `meridian dev` session, so a second proxy would be pointless. */\nfunction nestedSessionError(): CliError {\n return new CliError(\"`meridian dev` is already running in this process tree.\", {\n hint: `Use the dev server that session started, or stop it first. ${RECURSION_HINT}`,\n })\n}\n\n/** Reuses `assertNotSelfInvoking`'s tokenizing logic to detect a `dev` script that calls back into `meridian dev`. */\nfunction scriptReentersMeridianDev(script: string): boolean {\n try {\n assertNotSelfInvoking(script)\n return false\n } catch {\n return true\n }\n}\n\ninterface ResolvedDevCommand {\n command: string\n args: string[]\n /** Human-readable form, used in log lines only. */\n display: string\n}\n\nfunction resolvePassthroughCommand(argv: string[]): ResolvedDevCommand {\n const [command, ...args] = argv\n // Guarded by the `argv.length > 0` check at the call site.\n return { command: command as string, args, display: argv.join(\" \") }\n}\n\nfunction resolveConfiguredCommand(devCommand: string): ResolvedDevCommand {\n assertNotSelfInvoking(devCommand)\n const { command, args } = parseCommandString(devCommand)\n return { command, args, display: devCommand }\n}\n\nfunction noDevScriptError(): CliError {\n return new CliError('This project has no \"dev\" script.', {\n hint: \"Run `meridian dev -- <your command>`, or set `dev_command` in `.meridian/project.json`.\",\n })\n}\n\nfunction resolveDefaultCommand(deps: DevDeps, root: string): ResolvedDevCommand {\n const script = deps.readPackageScript(root, \"dev\")\n if (script === null) throw noDevScriptError()\n if (scriptReentersMeridianDev(script)) throw selfInvokingScriptError()\n\n const display = \"npm run dev\"\n assertNotSelfInvoking(display)\n return { command: \"npm\", args: [\"run\", \"dev\"], display }\n}\n\n/** Precedence: `--`-passthrough > `dev_command` > `npm run dev`. */\nfunction resolveDevCommand(deps: DevDeps, project: LinkedProject, passthrough: string[] | undefined): ResolvedDevCommand {\n if (passthrough !== undefined && passthrough.length > 0) return resolvePassthroughCommand(passthrough)\n if (project.config.dev_command !== undefined) return resolveConfiguredCommand(project.config.dev_command)\n return resolveDefaultCommand(deps, project.root)\n}\n\nfunction appLabel(project: LinkedProject): string {\n return project.config.app_name ?? String(project.config.app_id)\n}\n\nfunction printDevSummary(session: DevSessionInfo, noEnv: boolean): void {\n const envEntry = noEnv\n ? \"not touched (--no-env)\"\n : session.envPatch !== undefined\n ? session.envPatch.path\n : \"unchanged\"\n\n const entries: Array<[string, string]> = [\n [\"App\", appLabel(session.project)],\n [\"Database\", session.devDatabase.database],\n [\"Proxy\", `127.0.0.1:${session.proxy.port}`],\n [\"Env file\", envEntry],\n [\"DATABASE_URL\", redactDatabaseUrl(session.databaseUrl)],\n ]\n if (typeof session.credentials.expires_at === \"string\") {\n entries.push([\"Credentials expire\", session.credentials.expires_at])\n }\n\n log()\n keyValues(entries)\n log()\n}\n\n/** `--json` payload for a long-running command: printed once, before the child starts. Never carries a real password or proxy token. */\nfunction buildDevJsonPayload(session: DevSessionInfo): Record<string, unknown> {\n return {\n app: appLabel(session.project),\n database: session.devDatabase.database,\n proxy: { host: session.proxy.host, port: session.proxy.port },\n database_url: redactDatabaseUrl(session.databaseUrl),\n env_file: session.envPatch?.path ?? null,\n credentials_expire_at: session.credentials.expires_at ?? null,\n }\n}\n\n/**\n * Resolves the app's dev command, brings up the managed database session, and\n * runs the command until it exits (or the process is signalled). Resolves\n * with the exit code to use for the whole `meridian dev` invocation.\n */\nexport async function runDev(options: DevOptions = {}): Promise<number> {\n const deps: DevDeps = { ...defaultDeps(), ...options.deps }\n\n if (isInsideDevSession()) throw nestedSessionError()\n\n const project = deps.requireProject(workingDirectory())\n const resolved = resolveDevCommand(deps, project, options.command)\n const json = isJsonOutput()\n\n const sessionOptions: StartSessionOptions = {\n project,\n patchEnv: options.noEnv !== true,\n ...(options.port !== undefined ? { port: options.port } : {}),\n ...(options.envFile !== undefined ? { envFile: options.envFile } : {}),\n }\n const session = await deps.startDevSession(sessionOptions)\n\n let unregisterShutdown: (() => void) | undefined\n try {\n if (json) {\n printJson(buildDevJsonPayload(session))\n } else {\n printDevSummary(session, options.noEnv === true)\n step(`Starting ${resolved.display}...`)\n }\n\n const child = deps.startProcess(resolved.command, resolved.args, {\n cwd: project.root,\n env: session.env,\n inherit: true,\n })\n\n // Registered after the session's own shutdown handler, so on a signal it\n // runs first (handlers run LIFO): the app gets a chance to close its DB\n // connections before the proxy underneath it disappears.\n unregisterShutdown = onShutdown(async () => {\n await child.stop()\n await session.stop()\n })\n\n const result = await child.exited\n unregisterShutdown()\n unregisterShutdown = undefined\n await session.stop()\n\n if (result.signal !== null) return exitCodeForSignal(result.signal)\n if (result.code !== 0) log(style.dim(`${resolved.display} exited with code ${result.code}.`))\n return result.code\n } catch (error) {\n unregisterShutdown?.()\n await session.stop().catch(() => {})\n throw error\n }\n}\n\nexport function registerDevCommand(program: Command): void {\n program\n .command(\"dev\")\n .description(\"Run the managed dev database proxy and your app's dev server together.\")\n .option(\"--port <port>\", \"preferred local port for the Cloud SQL Auth Proxy\")\n .option(\"--env-file <file>\", \"the .env file to patch, relative to the project root (default .env)\")\n .option(\"--no-env\", \"don't touch any .env file; just print the DATABASE_URL for manual use\")\n .argument(\"[command...]\", \"run this instead of the app's dev script, e.g. `meridian dev -- next dev`\")\n .passThroughOptions()\n .action(async (command: string[], opts: { port?: string; envFile?: string; env?: boolean }) => {\n const port = parsePortOption(opts.port)\n const code = await runDev({\n ...(command.length > 0 ? { command } : {}),\n ...(port !== undefined ? { port } : {}),\n ...(opts.envFile !== undefined ? { envFile: opts.envFile } : {}),\n ...(opts.env === false ? { noEnv: true } : {}),\n })\n process.exitCode = code\n })\n}\n","/**\n * `meridian link` — picks an organization and app and writes\n * `<project>/.meridian/project.json` so `meridian dev` knows which managed\n * database to provision/reach.\n */\n\nimport { existsSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport type { Command } from \"commander\"\nimport type { AppSummary, Org } from \"../lib/api-types.js\"\nimport { createApiClient } from \"../lib/client.js\"\nimport { isJsonOutput, workingDirectory } from \"../lib/context.js\"\nimport { CliError } from \"../lib/errors.js\"\nimport { hint, keyValues, log, printJson, style, success } from \"../lib/output.js\"\nimport type { Choice } from \"../lib/prompts.js\"\nimport { confirmAction, selectOne } from \"../lib/prompts.js\"\nimport type { ProjectConfig } from \"../lib/project.js\"\nimport { readProject, resolveProjectRoot, writeProject } from \"../lib/project.js\"\n\nexport interface LinkDeps {\n createClient: typeof createApiClient\n /** Injectable for tests; never invokes real inquirer. */\n confirmImpl?: typeof import(\"@inquirer/prompts\").confirm\n /** Injectable for tests; never invokes real inquirer. */\n selectImpl?: typeof import(\"@inquirer/prompts\").select\n}\n\nexport interface LinkOptions {\n /** Organization id, name, or slug. */\n org?: string\n /** App id, name, or slug. */\n app?: string\n /** Stored as `dev_command`; overrides the default `npm run dev` in `meridian dev`. */\n devCommand?: string\n /** Skip both the \"no package.json\" and \"already linked\" confirmations. */\n force?: boolean\n deps?: Partial<LinkDeps>\n}\n\nfunction defaultDeps(): LinkDeps {\n return { createClient: createApiClient }\n}\n\nfunction formatOrg(org: Org): string {\n return `${org.name} (${org.slug})`\n}\n\nfunction formatApp(app: AppSummary): string {\n return `${app.name} (${app.slug})`\n}\n\n/**\n * Resolves a raw `--org`/`--app`/env-var answer against id, name, or slug so\n * `selectOne` (which otherwise only matches its `value`/`name`) can find the\n * right choice. Falls through to the raw string, unmatched, so `selectOne`\n * still produces its normal \"not a valid choice\" error listing the options.\n */\nfunction resolveChoiceAnswer<T>(choices: Array<Choice<T>>, raw: string, keysOf: (value: T) => string[]): string {\n const target = raw.trim().toLowerCase()\n const match = choices.find((choice) => keysOf(choice.value).some((key) => key.toLowerCase() === target))\n return match !== undefined ? match.name : raw\n}\n\n/** Runs the link logic; `options.deps` lets tests inject a fake API client. */\nexport async function runLink(options: LinkOptions = {}): Promise<void> {\n const deps = { ...defaultDeps(), ...options.deps }\n const json = isJsonOutput()\n\n const root = resolveProjectRoot(workingDirectory()) ?? workingDirectory()\n\n if (!existsSync(join(root, \"package.json\"))) {\n log(`No package.json found in ${style.path(root)}.`)\n const proceed = await confirmAction({\n message: \"Link this directory to a Meridian app anyway?\",\n flag: \"--force\",\n ...(options.force === true ? { assumeYes: true } : {}),\n ...(deps.confirmImpl !== undefined ? { promptImpl: deps.confirmImpl } : {}),\n })\n if (!proceed) throw new CliError(\"Aborted.\")\n }\n\n const existing = readProject(root)\n if (existing !== null) {\n log(\"This directory is already linked:\")\n keyValues([\n [\"App\", existing.config.app_name ?? String(existing.config.app_id)],\n [\"Org\", String(existing.config.org_id)],\n ])\n const relink = await confirmAction({\n message: \"Re-link this project?\",\n flag: \"--force\",\n ...(options.force === true ? { assumeYes: true } : {}),\n ...(deps.confirmImpl !== undefined ? { promptImpl: deps.confirmImpl } : {}),\n })\n if (!relink) throw new CliError(\"Aborted.\")\n }\n\n const client = deps.createClient({})\n const me = await client.getMe()\n const orgs = me.orgs\n\n if (orgs.length === 0) {\n throw new CliError(\"Your Meridian account has no organizations yet.\", {\n hint: \"Create one in the Meridian dashboard, then run `meridian link` again.\",\n })\n }\n\n const orgChoices: Array<Choice<Org>> = orgs.map((org) => ({ value: org, name: formatOrg(org) }))\n const orgCandidate = options.org ?? process.env.MERIDIAN_ORG\n const orgAnswer =\n orgCandidate !== undefined\n ? resolveChoiceAnswer(orgChoices, orgCandidate, (org) => [String(org.id), org.name, org.slug])\n : undefined\n\n const org = await selectOne({\n message: \"Select an organization\",\n choices: orgChoices,\n envVar: \"MERIDIAN_ORG\",\n flag: \"--org\",\n ...(orgAnswer !== undefined ? { answer: orgAnswer } : {}),\n ...(deps.selectImpl !== undefined ? { promptImpl: deps.selectImpl } : {}),\n })\n log(`Organization: ${style.bold(formatOrg(org))}`)\n\n const apps = await client.listApps(org.id)\n if (apps.length === 0) {\n throw new CliError(`Organization \"${org.name}\" has no apps yet.`, {\n hint: \"Create an app in the Meridian dashboard, then run `meridian link` again.\",\n })\n }\n\n const appChoices: Array<Choice<AppSummary>> = apps.map((app) => ({ value: app, name: formatApp(app) }))\n const appCandidate = options.app ?? process.env.MERIDIAN_APP\n const appAnswer =\n appCandidate !== undefined\n ? resolveChoiceAnswer(appChoices, appCandidate, (app) => [String(app.id), app.name, app.slug])\n : undefined\n\n const app = await selectOne({\n message: \"Select an app\",\n choices: appChoices,\n envVar: \"MERIDIAN_APP\",\n flag: \"--app\",\n ...(appAnswer !== undefined ? { answer: appAnswer } : {}),\n ...(deps.selectImpl !== undefined ? { promptImpl: deps.selectImpl } : {}),\n })\n log(`App: ${style.bold(formatApp(app))}`)\n\n const config: ProjectConfig = {\n org_id: org.id,\n app_id: app.id,\n app_name: app.name,\n ...(options.devCommand !== undefined ? { dev_command: options.devCommand } : {}),\n }\n writeProject(root, config)\n\n if (json) {\n printJson({ ...config, root })\n return\n }\n\n success(`Linked ${style.path(root)} to ${app.name}.`)\n keyValues([\n [\"Org\", formatOrg(org)],\n [\"App\", formatApp(app)],\n [\"Root\", root],\n ])\n log()\n hint(\"Run `meridian dev` to start your local dev server against the managed database.\")\n}\n\nexport function registerLinkCommand(program: Command): void {\n program\n .command(\"link\")\n .description(\"Link this project to a Meridian organization and app.\")\n .option(\"--org <idOrName>\", \"organization to link (id, name, or slug)\")\n .option(\"--app <idOrName>\", \"app to link (id, name, or slug)\")\n .option(\"--dev-command <cmd>\", \"override the command `meridian dev` runs (defaults to `npm run dev`)\")\n .option(\"--force\", \"overwrite an existing link, and skip the missing-package.json warning, without prompting\")\n .action(async (opts: { org?: string; app?: string; devCommand?: string; force?: boolean }) => {\n await runLink({\n ...(opts.org !== undefined ? { org: opts.org } : {}),\n ...(opts.app !== undefined ? { app: opts.app } : {}),\n ...(opts.devCommand !== undefined ? { devCommand: opts.devCommand } : {}),\n ...(opts.force === true ? { force: true } : {}),\n })\n })\n}\n","/**\n * `meridian login` — device-code OAuth against meridian-api. Verifies (and\n * reuses) an existing token when possible; otherwise runs the device flow and\n * stores the issued token in `~/.meridian/config.json`.\n */\n\nimport { hostname as osHostname } from \"node:os\"\nimport type { Command } from \"commander\"\nimport { formatUserCode, runDeviceFlow } from \"../auth/device-flow.js\"\nimport { createApiClient } from \"../lib/client.js\"\nimport type { ConfigUser } from \"../lib/config.js\"\nimport { DEFAULT_API_BASE_URL, getAuth, updateConfig } from \"../lib/config.js\"\nimport { isJsonOutput, workingDirectory } from \"../lib/context.js\"\nimport { isApiError } from \"../lib/errors.js\"\nimport { hint, log, printJson, spinner, style, success, warn } from \"../lib/output.js\"\nimport { isInteractive } from \"../lib/prompts.js\"\nimport { readProject } from \"../lib/project.js\"\n\nexport interface LoginDeps {\n createClient: typeof createApiClient\n runDeviceFlow: typeof runDeviceFlow\n /** Opens `url` in the system browser. Default: dynamic `import(\"open\")`. */\n openUrl: (url: string) => Promise<void>\n}\n\nexport interface LoginOptions {\n /** Re-authenticate even when a valid token is already stored. */\n force?: boolean\n /** Print the verification URL instead of opening a browser. */\n noBrowser?: boolean\n /** Overrides `os.hostname()` in the device-code request. */\n hostname?: string\n deps?: Partial<LoginDeps>\n}\n\nasync function defaultOpenUrl(url: string): Promise<void> {\n const { default: open } = await import(\"open\")\n await open(url)\n}\n\nfunction defaultDeps(): LoginDeps {\n return { createClient: createApiClient, runDeviceFlow, openUrl: defaultOpenUrl }\n}\n\n/**\n * The browser is only worth trying when a human is plausibly watching:\n * skipped for `--no-browser`, `MERIDIAN_NO_BROWSER`, CI, and any\n * non-interactive shell (piped input, `--no-input`, ...).\n */\nfunction shouldOpenBrowser(noBrowser: boolean | undefined): boolean {\n if (noBrowser === true) return false\n if (process.env.MERIDIAN_NO_BROWSER) return false\n if (process.env.CI) return false\n return isInteractive()\n}\n\nfunction toConfigUser(user: { id: number | string; name: string; email: string }): ConfigUser {\n return { id: user.id, name: user.name, email: user.email }\n}\n\nfunction printLoginJson(user: ConfigUser, tokenExpiresAt: string | undefined, apiBaseUrl: string): void {\n printJson({ user, token_expires_at: tokenExpiresAt, api_base_url: apiBaseUrl })\n}\n\nfunction hintUnlessLinked(json: boolean): void {\n if (json) return\n if (readProject(workingDirectory()) !== null) return\n hint(\"Run `meridian link` to connect this project to a Meridian app.\")\n}\n\n/** Runs the login logic; `options.deps` lets tests inject fakes for the API client, device flow, and browser opener. */\nexport async function runLogin(options: LoginOptions = {}): Promise<void> {\n const deps = { ...defaultDeps(), ...options.deps }\n const json = isJsonOutput()\n\n if (options.force !== true) {\n const auth = getAuth()\n if (auth !== null) {\n const client = deps.createClient({ requireAuth: false, token: auth.token })\n try {\n const me = await client.getMe()\n const user = toConfigUser(me.user)\n updateConfig({ user })\n if (json) {\n printLoginJson(user, auth.tokenExpiresAt, client.baseUrl)\n } else {\n log(`Already logged in as ${user.name} <${user.email}>`)\n hint(\"Run `meridian login --force` to re-authenticate.\")\n }\n return\n } catch (error) {\n if (!(isApiError(error) && error.status === 401)) throw error\n // Stored token was revoked/expired server-side; fall through to a fresh login.\n }\n }\n }\n\n const client = deps.createClient({ requireAuth: false })\n const hostname = options.hostname ?? osHostname()\n const wait = spinner(\"Waiting for approval in the browser…\")\n const startedAt = Date.now()\n\n const tokenResponse = await deps.runDeviceFlow({\n client,\n hostname,\n onCode: async (code) => {\n const target = code.verification_uri_complete ?? code.verification_uri\n\n if (!json) {\n log()\n log(` ${style.bold(formatUserCode(code.user_code))}`)\n log()\n log(`Visit: ${style.path(code.verification_uri)}`)\n log(\"Waiting for you to approve this login in the browser…\")\n }\n\n let opened = false\n if (shouldOpenBrowser(options.noBrowser)) {\n try {\n await deps.openUrl(target)\n opened = true\n } catch {\n warn(\"Could not open the browser automatically.\")\n }\n }\n if (!opened && !json) log(`Open this URL to continue: ${style.path(target)}`)\n\n if (!json) wait.start()\n },\n onPoll: () => {\n const elapsedSeconds = Math.round((Date.now() - startedAt) / 1000)\n wait.update(`Waiting for approval in the browser… (${elapsedSeconds}s)`)\n },\n })\n\n wait.stop()\n\n const user = toConfigUser(tokenResponse.user)\n const storeApiBaseUrl = client.baseUrl !== DEFAULT_API_BASE_URL\n\n updateConfig({\n token: tokenResponse.token,\n ...(tokenResponse.expires_at !== undefined ? { token_expires_at: tokenResponse.expires_at } : {}),\n user,\n ...(storeApiBaseUrl ? { api_base_url: client.baseUrl } : {}),\n })\n\n if (json) {\n printLoginJson(user, tokenResponse.expires_at, client.baseUrl)\n } else {\n success(`Logged in as ${user.name} <${user.email}>`)\n hintUnlessLinked(json)\n }\n}\n\nexport function registerLoginCommand(program: Command): void {\n program\n .command(\"login\")\n .description(\"Authenticate this machine with Meridian via a device-code login in your browser.\")\n .option(\"--force\", \"re-authenticate even when a valid token is already stored\")\n .option(\"--no-browser\", \"print the verification URL instead of opening it\")\n .option(\"--hostname <name>\", \"hostname reported to Meridian for this device (defaults to the machine hostname)\")\n .action(async (opts: { force?: boolean; browser?: boolean; hostname?: string }) => {\n await runLogin({\n ...(opts.force === true ? { force: true } : {}),\n ...(opts.browser === false ? { noBrowser: true } : {}),\n ...(typeof opts.hostname === \"string\" ? { hostname: opts.hostname } : {}),\n })\n })\n}\n","/**\n * Device-code login orchestration (RFC 8628-ish, per meridian-api's\n * `/app/cli/device/*` contract), stripped of all I/O: no console output, no\n * browser opening, no config writing. The `login` command wires those in via\n * `DeviceFlowCallbacks` so this module stays trivially unit-testable and\n * reusable (e.g. by a future `--json` login mode).\n */\n\nimport { hostname as osHostname } from \"node:os\"\nimport type { ApiClient } from \"../lib/api.js\"\nimport type { DeviceCodeResponse, DeviceTokenResponse } from \"../lib/api-types.js\"\nimport { CliError, isApiError, isCliError } from \"../lib/errors.js\"\n\nconst DEFAULT_CLIENT_NAME = \"meridian-cli\"\nconst DEFAULT_INTERVAL_SECONDS = 5\nconst DEFAULT_EXPIRES_IN_SECONDS = 900\nconst SLOW_DOWN_INCREMENT_MS = 5_000\nconst MAX_CONSECUTIVE_TRANSIENT_FAILURES = 3\nconst DEFAULT_MAX_WAIT_MS = 15 * 60 * 1000\n\nexport interface DeviceFlowCallbacks {\n /** Called once with the code payload so the command can print the user code and open the browser. */\n onCode?: (code: DeviceCodeResponse) => void | Promise<void>\n /** Called each time the server asks us to slow down, with the new interval in ms. */\n onSlowDown?: (intervalMs: number) => void\n /** Called before each poll attempt (attempt starts at 1) so the caller can update a spinner. */\n onPoll?: (attempt: number) => void\n}\n\nexport interface DeviceFlowOptions extends DeviceFlowCallbacks {\n client: ApiClient\n clientName?: string\n hostname?: string\n /** Injectable for tests. Default: (ms) => new Promise(r => setTimeout(r, ms)). */\n sleep?: (ms: number) => Promise<void>\n /** Injectable clock for expiry maths. Default Date.now. */\n now?: () => number\n /** Hard cap regardless of the server's expires_in. Default 15 minutes. */\n maxWaitMs?: number\n}\n\nfunction defaultSleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction deniedError(): CliError {\n return new CliError(\"Authorization was denied in the browser.\", {\n hint: \"Run `meridian login` again if you want to retry.\",\n })\n}\n\nfunction expiredError(expiresInSeconds: number): CliError {\n const minutes = Math.max(1, Math.round(expiresInSeconds / 60))\n return new CliError(\"The login request expired before it was approved.\", {\n hint: `Run \\`meridian login\\` again and approve it in the browser within ${minutes} minute${minutes === 1 ? \"\" : \"s\"}.`,\n })\n}\n\nfunction timedOutError(): CliError {\n return new CliError(\"Timed out waiting for the login to be approved.\", {\n hint: \"Run `meridian login` again and approve the request promptly in the browser.\",\n })\n}\n\n/**\n * `invalid_grant` is outside the four polling codes the contract lists: the\n * API returns it (as a 404) when the device code is unknown or has already\n * been exchanged for a token. Retrying can never help, and the generic 404\n * handling would tell the user to run `meridian link`, so it is terminal here.\n */\nfunction invalidGrantError(): CliError {\n return new CliError(\"This login request is no longer valid.\", {\n hint: \"Run `meridian login` again to start a new one.\",\n })\n}\n\n/** True for failures worth a bounded retry: a 5xx from the API, or a network/timeout CliError raised by ApiClient. */\nfunction isTransientFailure(error: unknown): boolean {\n if (isApiError(error)) return error.status >= 500\n return isCliError(error)\n}\n\n/** Runs the full device flow and resolves with the issued token. */\nexport async function runDeviceFlow(options: DeviceFlowOptions): Promise<DeviceTokenResponse> {\n const { client } = options\n const sleep = options.sleep ?? defaultSleep\n const now = options.now ?? Date.now\n const maxWaitMs = options.maxWaitMs ?? DEFAULT_MAX_WAIT_MS\n\n const code = await client.requestDeviceCode({\n clientName: options.clientName ?? DEFAULT_CLIENT_NAME,\n hostname: options.hostname ?? osHostname(),\n })\n await options.onCode?.(code)\n\n const expiresInSeconds = code.expires_in ?? DEFAULT_EXPIRES_IN_SECONDS\n let intervalMs = Math.max(1, code.interval ?? DEFAULT_INTERVAL_SECONDS) * 1000\n\n const start = now()\n const deadline = Math.min(start + expiresInSeconds * 1000, start + maxWaitMs)\n\n let attempt = 1\n let consecutiveFailures = 0\n\n while (true) {\n if (now() >= deadline) throw timedOutError()\n\n options.onPoll?.(attempt)\n\n try {\n return await client.pollDeviceTokenOnce(code.device_code)\n } catch (error) {\n if (isApiError(error)) {\n if (error.errorCode === \"authorization_pending\") {\n consecutiveFailures = 0\n await sleep(intervalMs)\n attempt += 1\n continue\n }\n // The device endpoints are IP-throttled on top of the per-code\n // `slow_down` guard, and a throttled response carries the platform's\n // own error code — any 429 means the same thing: poll less often.\n if (error.errorCode === \"slow_down\" || error.status === 429) {\n intervalMs += SLOW_DOWN_INCREMENT_MS\n options.onSlowDown?.(intervalMs)\n consecutiveFailures = 0\n await sleep(intervalMs)\n attempt += 1\n continue\n }\n if (error.errorCode === \"access_denied\") throw deniedError()\n if (error.errorCode === \"expired_token\") throw expiredError(expiresInSeconds)\n if (error.errorCode === \"invalid_grant\") throw invalidGrantError()\n }\n\n if (!isTransientFailure(error)) throw error\n\n consecutiveFailures += 1\n if (consecutiveFailures > MAX_CONSECUTIVE_TRANSIENT_FAILURES) throw error\n\n await sleep(intervalMs)\n attempt += 1\n }\n }\n}\n\n/**\n * Normalizes a user-typed device code: uppercases, strips whitespace/dashes,\n * then re-inserts the dash for the standard 8-character `XXXX-XXXX` shape so\n * `\"abcd 1234\"` and `\"abcd-1234\"` both become `\"ABCD-1234\"`.\n */\nexport function formatUserCode(code: string): string {\n const cleaned = code.trim().toUpperCase().replace(/[^A-Z0-9]/g, \"\")\n if (cleaned.length === 8) return `${cleaned.slice(0, 4)}-${cleaned.slice(4)}`\n return cleaned\n}\n","/**\n * `meridian logout` — clears the stored CLI token. Leaves any linked project\n * (`.meridian/project.json`) untouched; that's `meridian unlink`'s job.\n */\n\nimport type { Command } from \"commander\"\nimport { clearAuth } from \"../lib/config.js\"\nimport { isJsonOutput } from \"../lib/context.js\"\nimport { hint, log, printJson, success } from \"../lib/output.js\"\n\n/** Clears the stored token. Returns void; the exit code is always 0. */\nexport async function runLogout(): Promise<void> {\n const hadToken = clearAuth()\n\n if (isJsonOutput()) {\n printJson({ logged_out: hadToken })\n return\n }\n\n if (hadToken) success(\"Logged out.\")\n else log(\"You were not logged in.\")\n\n hint(\"`.meridian/project.json` is untouched; run `meridian unlink` to remove a linked project.\")\n}\n\nexport function registerLogoutCommand(program: Command): void {\n program\n .command(\"logout\")\n .description(\"Clear the Meridian CLI token stored on this machine.\")\n .action(async () => {\n await runLogout()\n })\n}\n","/**\n * Logical dump/replay of the dev database around a `meridian migrate` run.\n * `createSnapshot` is taken before `npx prisma migrate dev`; if that fails,\n * the API resets the schema to empty and `restoreSnapshot` replays the dump\n * so the developer never loses data to a bad migration.\n */\n\nimport { mkdir, readFile, readdir, rm, stat } from \"node:fs/promises\"\nimport { join } from \"node:path\"\nimport { CliError, describeError } from \"../errors.js\"\nimport { createSqlConnection } from \"./connection.js\"\nimport type { ConnectionFactory, DbConnectionInfo, SqlConnection } from \"./connection.js\"\n\nexport interface SnapshotResult {\n /** Dump file, or null when the database held no tables and nothing was written. */\n path: string | null\n bytes: number\n createdAt: Date\n /** Tables captured. Zero means the database was empty. */\n tables: number\n}\n\n/** `2026-07-31T11-22-33-123Z.sql` — filesystem-safe ISO, sorts chronologically. */\nexport function snapshotFileName(date: Date = new Date()): string {\n return `${date.toISOString().replace(/[:.]/g, \"-\")}.sql`\n}\n\nexport type DumpFn = (options: {\n connection: { host: string; port: number; user: string; password: string; database: string }\n dumpToFile?: string\n dump?: unknown\n}) => Promise<unknown>\n\nexport interface CreateSnapshotOptions {\n /** Directory to write into; created recursively. Usually snapshotsDir(projectRoot). */\n dir: string\n now?: () => Date\n /** Injectable `mysqldump` for tests. */\n dumpImpl?: DumpFn\n /** Injectable connection factory, used for the table count. */\n factory?: ConnectionFactory\n}\n\nconst SKIP_SNAPSHOT_HINT = \"Re-run with --skip-snapshot to bypass snapshotting (not recommended before a schema-changing migration).\"\n\n/**\n * mysqldump v3 is CJS; its `module.exports` (not a named export) is the dump\n * function, and it's also mirrored onto `.default` — handle both interop\n * shapes and import lazily so non-migrate commands don't pay its startup cost.\n */\nasync function loadMysqldump(): Promise<DumpFn> {\n const mod = await import(\"mysqldump\")\n const dump = (mod.default as unknown as { default?: DumpFn }).default ?? (mod.default as unknown as DumpFn)\n return dump\n}\n\n/**\n * Logical dump (schema + data + triggers/routines/views) of the dev database.\n *\n * The dump options drop-and-recreate every table (`dropIfExist: true`,\n * `ifNotExist: false`) rather than assuming an empty target, so the file\n * replays cleanly whether it lands on an empty schema (the migrate rollback\n * path, after the API resets the schema) or is re-run by hand.\n */\nexport async function createSnapshot(info: DbConnectionInfo, options: CreateSnapshotOptions): Promise<SnapshotResult> {\n const now = options.now ?? (() => new Date())\n const createdAt = now()\n\n // A dev database has no tables until the first `prisma migrate dev` — the\n // normal state on the very run that creates them. mysqldump builds one\n // multi-statement query out of the table list and sends it unconditionally,\n // so with no tables it issues an empty string and MySQL rejects it\n // (ER_EMPTY_QUERY). There is nothing to dump, so don't ask it to.\n const tables = await countTables(info, options.factory)\n if (tables === 0) {\n return { path: null, bytes: 0, createdAt, tables: 0 }\n }\n\n const dump = options.dumpImpl ?? (await loadMysqldump())\n\n await mkdir(options.dir, { recursive: true })\n\n const path = join(options.dir, snapshotFileName(createdAt))\n\n try {\n await dump({\n connection: {\n host: info.host,\n port: info.port,\n user: info.user,\n password: info.password,\n database: info.database,\n },\n dumpToFile: path,\n dump: {\n schema: { table: { ifNotExist: false, dropIfExist: true }, engine: false },\n data: { format: false, verbose: false },\n trigger: {},\n },\n })\n } catch (error) {\n // Name the underlying failure: without it every cause — unreachable proxy,\n // missing privilege, disk full — reads as the same opaque one-liner.\n throw new CliError(`Could not snapshot the development database: ${describeError(error)}`, {\n hint: SKIP_SNAPSHOT_HINT,\n cause: error,\n })\n }\n\n let bytes: number\n try {\n bytes = (await stat(path)).size\n } catch (error) {\n throw new CliError(\"Could not snapshot the development database: the dump did not produce a file.\", {\n hint: SKIP_SNAPSHOT_HINT,\n cause: error,\n })\n }\n\n if (bytes === 0) {\n throw new CliError(\"Could not snapshot the development database: the dump produced an empty file.\", {\n hint: SKIP_SNAPSHOT_HINT,\n })\n }\n\n return { path, bytes, createdAt, tables }\n}\n\n/** Single-quoted SQL literal; the database name is interpolated, not bound. */\nfunction quoteSqlString(value: string): string {\n return `'${value.replace(/\\\\/g, \"\\\\\\\\\").replace(/'/g, \"''\")}'`\n}\n\n/**\n * Reads `COUNT(*)` out of a result. mysql2 answers `[rows, fields]`; a test\n * fake may answer the rows directly, so accept either shape.\n */\nfunction readCount(result: unknown): number | undefined {\n const groups = Array.isArray(result) ? result : [result]\n for (const group of groups) {\n const rows = Array.isArray(group) ? group : [group]\n for (const row of rows) {\n if (typeof row === \"object\" && row !== null && \"count\" in row) {\n const parsed = Number((row as { count: unknown }).count)\n if (Number.isFinite(parsed)) return parsed\n }\n }\n }\n return undefined\n}\n\n/**\n * How many tables the dev database holds. Returns 1 (\"assume non-empty\")\n * whenever the count cannot be established — an unreachable database or an\n * unexpected result shape falls through to attempting the dump, whose own\n * failure is the more informative one to report.\n */\nasync function countTables(info: DbConnectionInfo, factory: ConnectionFactory = createSqlConnection): Promise<number> {\n let connection: SqlConnection\n try {\n connection = await factory(info)\n } catch {\n return 1\n }\n\n try {\n const result = await connection.query(\n `SELECT COUNT(*) AS \\`count\\` FROM information_schema.tables WHERE table_schema = ${quoteSqlString(info.database)}`,\n )\n return readCount(result) ?? 1\n } catch {\n return 1\n } finally {\n try {\n await connection.end()\n } catch {\n connection.destroy?.()\n }\n }\n}\n\nexport interface RestoreSnapshotOptions {\n factory?: ConnectionFactory\n /** Called with progress info for a spinner: statements executed so far. */\n onProgress?: (executed: number, total: number) => void\n}\n\n/**\n * Replays a snapshot into an (empty) database. Used as the rollback half of\n * `meridian migrate` after the API has dropped and recreated the schema.\n */\nexport async function restoreSnapshot(\n info: DbConnectionInfo,\n snapshotPath: string,\n options: RestoreSnapshotOptions = {},\n): Promise<{ statements: number }> {\n const factory = options.factory ?? createSqlConnection\n const sql = await readFile(snapshotPath, \"utf8\")\n const statements = splitSqlStatements(sql)\n\n const connection = await factory(info, { multipleStatements: true })\n try {\n await connection.query(\"SET FOREIGN_KEY_CHECKS=0\")\n await connection.query(\"SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO'\")\n\n for (const [index, statement] of statements.entries()) {\n try {\n await connection.query(statement)\n } catch (error) {\n throw new CliError(\n `Snapshot replay failed at statement ${index + 1} of ${statements.length}: ${statement.slice(0, 200)}`,\n {\n hint: `Inspect the failure, then replay the snapshot by hand with \\`mysql < ${snapshotPath}\\`.`,\n cause: error,\n },\n )\n }\n options.onProgress?.(index + 1, statements.length)\n }\n\n await connection.query(\"SET FOREIGN_KEY_CHECKS=1\")\n } finally {\n await connection.end()\n }\n\n return { statements: statements.length }\n}\n\n/**\n * Splits a dump into executable statements. Handles `--` and `#` line\n * comments, `/* *\\/` block comments (including MySQL's executable `/*! ... *\\/`\n * hints, which must be kept), single/double-quoted strings, backtick\n * identifiers, escaped quotes, and `DELIMITER` blocks used for\n * triggers/routines.\n */\nexport function splitSqlStatements(sql: string): string[] {\n const statements: string[] = []\n let delimiter = \";\"\n let buffer = \"\"\n let i = 0\n const n = sql.length\n\n const flush = (): void => {\n const trimmed = buffer.trim()\n buffer = \"\"\n if (trimmed !== \"\") statements.push(trimmed)\n }\n\n while (i < n) {\n if (buffer.trim() === \"\" && sql.slice(i, i + 10).toUpperCase() === \"DELIMITER \") {\n const lineEnd = sql.indexOf(\"\\n\", i)\n const line = lineEnd === -1 ? sql.slice(i) : sql.slice(i, lineEnd)\n const newDelimiter = line.slice(\"DELIMITER\".length).trim()\n if (newDelimiter !== \"\") {\n delimiter = newDelimiter\n buffer = \"\"\n i = lineEnd === -1 ? n : lineEnd + 1\n continue\n }\n }\n\n const ch = sql[i]\n\n if (ch === \"-\" && sql[i + 1] === \"-\" && (sql[i + 2] === undefined || /\\s/.test(sql[i + 2] ?? \"\"))) {\n const lineEnd = sql.indexOf(\"\\n\", i)\n i = lineEnd === -1 ? n : lineEnd + 1\n buffer += \"\\n\"\n continue\n }\n\n if (ch === \"#\") {\n const lineEnd = sql.indexOf(\"\\n\", i)\n i = lineEnd === -1 ? n : lineEnd + 1\n buffer += \"\\n\"\n continue\n }\n\n if (ch === \"/\" && sql[i + 1] === \"*\") {\n const isExecutableHint = sql[i + 2] === \"!\"\n const end = sql.indexOf(\"*/\", i + 2)\n const commentEnd = end === -1 ? n : end + 2\n buffer += isExecutableHint ? sql.slice(i, commentEnd) : \" \"\n i = commentEnd\n continue\n }\n\n if (ch === \"'\" || ch === '\"' || ch === \"`\") {\n const quote = ch\n let j = i + 1\n let text = ch\n while (j < n) {\n const c = sql[j]\n if (c === \"\\\\\" && quote !== \"`\") {\n text += sql.slice(j, j + 2)\n j += 2\n continue\n }\n if (c === quote) {\n if (sql[j + 1] === quote) {\n text += quote + quote\n j += 2\n continue\n }\n text += quote\n j += 1\n break\n }\n text += c\n j += 1\n }\n buffer += text\n i = j\n continue\n }\n\n if (sql.startsWith(delimiter, i)) {\n flush()\n i += delimiter.length\n continue\n }\n\n buffer += ch\n i += 1\n }\n\n flush()\n return statements\n}\n\nfunction isEnoent(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\"\n}\n\n/** Recovers the timestamp encoded in a name produced by `snapshotFileName`. */\nfunction parseSnapshotDate(name: string): Date {\n const iso = name.replace(/\\.sql$/, \"\").replace(/T(\\d\\d)-(\\d\\d)-(\\d\\d)-(\\d\\d\\d)Z$/, \"T$1:$2:$3.$4Z\")\n return new Date(iso)\n}\n\n/** Lists snapshots in a directory, newest first (name-sorted). */\nexport async function listSnapshots(dir: string): Promise<Array<{ path: string; name: string; bytes: number; createdAt: Date }>> {\n let entries: string[]\n try {\n entries = await readdir(dir)\n } catch (error) {\n if (isEnoent(error)) return []\n throw error\n }\n\n const names = entries.filter((name) => name.endsWith(\".sql\")).sort().reverse()\n\n const results: Array<{ path: string; name: string; bytes: number; createdAt: Date }> = []\n for (const name of names) {\n const path = join(dir, name)\n const { size } = await stat(path)\n results.push({ path, name, bytes: size, createdAt: parseSnapshotDate(name) })\n }\n return results\n}\n\n/** Keeps the newest `keep` snapshots and deletes the rest; returns the deleted paths. */\nexport async function pruneSnapshots(dir: string, keep: number): Promise<string[]> {\n const snapshots = await listSnapshots(dir)\n const toDelete = snapshots.slice(Math.max(keep, 0))\n for (const snapshot of toDelete) {\n await rm(snapshot.path, { force: true })\n }\n return toDelete.map((snapshot) => snapshot.path)\n}\n","/**\n * `meridian migrate` — the only command that runs `prisma migrate dev`\n * against the shared remote dev database. Because a bad migration can wreck\n * that database for the whole team, this always takes a logical snapshot\n * first (unless told not to) and can drop+recreate the schema and replay the\n * snapshot automatically when the migration fails.\n */\n\nimport type { Command } from \"commander\"\nimport type { ApiClient } from \"../lib/api.js\"\nimport type { Id, MigrationRunInput } from \"../lib/api-types.js\"\nimport { createApiClient } from \"../lib/client.js\"\nimport { isJsonOutput, workingDirectory } from \"../lib/context.js\"\nimport type { SnapshotResult } from \"../lib/db/snapshot.js\"\nimport { createSnapshot, pruneSnapshots, restoreSnapshot } from \"../lib/db/snapshot.js\"\nimport { parseIntegerOption, parsePortOption } from \"../lib/options.js\"\nimport { detail, error, hint, printJson, style, success, warn, withSpinner } from \"../lib/output.js\"\nimport { snapshotsDir } from \"../lib/paths.js\"\nimport {\n addShadowDatabaseUrl,\n assertMigrationDialect,\n assertShadowDatasource,\n diagnoseMigrationFailure,\n missingShadowDatabaseUrl,\n} from \"../lib/prisma.js\"\nimport type { LinkedProject } from \"../lib/project.js\"\nimport { requireProject } from \"../lib/project.js\"\nimport { confirmAction, isAssumeYes, isInteractive } from \"../lib/prompts.js\"\nimport type { RunResult } from \"../lib/run.js\"\nimport { runNpx } from \"../lib/run.js\"\nimport type { DevSessionInfo, StartSessionOptions } from \"../lib/session.js\"\nimport { startDevSession } from \"../lib/session.js\"\n\nconst DEFAULT_KEEP_SNAPSHOTS = 5\n/** Bounds the payload sent to `POST .../migrations`; the raw capture from run.ts is already capped at 8 KB. */\nconst MAX_OUTPUT_EXCERPT = 4000\n\nexport type MigrationStatus = \"success\" | \"failed\" | \"rolled_back\"\n\n/** Every side-effecting collaborator, injectable so the whole flow is testable offline. */\nexport interface MigrateDeps {\n startDevSession: typeof startDevSession\n createSnapshot: typeof createSnapshot\n restoreSnapshot: typeof restoreSnapshot\n pruneSnapshots: typeof pruneSnapshots\n runNpx: typeof runNpx\n createApiClient: typeof createApiClient\n requireProject: () => LinkedProject\n assertShadowDatasource: typeof assertShadowDatasource\n assertMigrationDialect: typeof assertMigrationDialect\n missingShadowDatabaseUrl: typeof missingShadowDatabaseUrl\n addShadowDatabaseUrl: typeof addShadowDatabaseUrl\n diagnoseMigrationFailure: typeof diagnoseMigrationFailure\n now: () => Date\n}\n\nexport interface MigrateOptions {\n /** Extra argv forwarded to `prisma migrate dev` verbatim, e.g. [\"--name\", \"add_orders\"]. */\n prismaArgs?: string[]\n /** Skip the pre-migration snapshot entirely. There is nothing to roll back to when this is set. */\n skipSnapshot?: boolean\n /** Still snapshot, but never auto-restore on failure; just report where the snapshot is. */\n noRollback?: boolean\n /** Run even when the history was written for another engine, which `prisma migrate dev` will reject. */\n allowForeignMigrations?: boolean\n /** Snapshots to keep (newest first) after a *successful* migration. Default 5. */\n keepSnapshots?: number\n /** Preferred local port for the Cloud SQL Auth Proxy. */\n port?: number\n /** .env file (relative to the project root) to patch with DATABASE_URL. */\n envFile?: string\n deps?: Partial<MigrateDeps>\n}\n\nfunction defaultDeps(): MigrateDeps {\n return {\n startDevSession,\n createSnapshot,\n restoreSnapshot,\n pruneSnapshots,\n runNpx,\n createApiClient,\n requireProject: () => requireProject(workingDirectory()),\n assertShadowDatasource,\n assertMigrationDialect,\n missingShadowDatabaseUrl,\n addShadowDatabaseUrl,\n diagnoseMigrationFailure,\n now: () => new Date(),\n }\n}\n\nfunction resolveDeps(overrides?: Partial<MigrateDeps>): MigrateDeps {\n return { ...defaultDeps(), ...overrides }\n}\n\n/** `12.3 KB` under 1 MiB, `4.1 MB` above — the units a developer expects for a SQL dump. */\nfunction formatSize(bytes: number): string {\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction excerptOf(output: string): string {\n return output.length > MAX_OUTPUT_EXCERPT ? output.slice(-MAX_OUTPUT_EXCERPT) : output\n}\n\n/**\n * `prisma migrate dev` needs a TTY to interactively prompt for a migration\n * name, so stdio is inherited by default. That prompt is meaningless under\n * `--json` (nothing would render it) and in non-interactive shells (CI,\n * `--no-input`, piped stdin) — those cases capture output instead so the API\n * gets a real `output_excerpt` and `--json` gets something to report.\n */\nfunction shouldInheritStdio(json: boolean): boolean {\n return !json && isInteractive()\n}\n\ninterface JsonPayload {\n status: MigrationStatus\n command: string\n started_at: string\n finished_at: string\n exit_code: number\n /** `path` is null when the database was empty and no dump file was written. */\n snapshot: { path: string | null; bytes: number } | null\n rolled_back: boolean\n database: string\n app_id: Id\n}\n\n/**\n * Reports the run to Meridian without ever masking the migration's own\n * result: a reporting failure becomes a warning, never a thrown error.\n */\nasync function reportMigrationSafely(client: ApiClient, appId: Id, input: MigrationRunInput): Promise<void> {\n try {\n await client.reportMigration(appId, input)\n } catch {\n warn(\"Could not report this migration run to Meridian.\")\n }\n}\n\ninterface RunMigrationContext {\n json: boolean\n keepSnapshots: number\n commandArgs: string[]\n commandString: string\n options: MigrateOptions\n}\n\nasync function runMigration(session: DevSessionInfo, deps: MigrateDeps, ctx: RunMigrationContext): Promise<number> {\n const { json, keepSnapshots, commandArgs, commandString, options } = ctx\n const client = deps.createApiClient()\n const appId = session.project.config.app_id\n const dir = snapshotsDir(session.project.root)\n\n let snapshot: SnapshotResult | undefined\n if (options.skipSnapshot !== true) {\n snapshot = await withSpinner(\n \"Snapshotting the development database...\",\n () => deps.createSnapshot(session.connection, { dir, now: deps.now }),\n {\n success: (result) =>\n result.path === null\n ? \"Development database is empty — nothing to snapshot.\"\n : `Snapshot saved to ${style.path(result.path)} (${formatSize(result.bytes)}).`,\n },\n )\n }\n\n const inherit = shouldInheritStdio(json)\n const startedAt = deps.now().toISOString()\n const runResult: RunResult = await deps.runNpx(commandArgs, { cwd: session.project.root, env: session.env, inherit })\n const finishedAt = deps.now().toISOString()\n\n let status: MigrationStatus\n let rolledBack = false\n let exitCode: number\n\n if (runResult.code === 0) {\n success(\"Migration applied.\")\n status = \"success\"\n exitCode = 0\n if (snapshot !== undefined) await deps.pruneSnapshots(dir, keepSnapshots)\n } else {\n // A killed-but-reported-as-0 process still counts as a failure here; never report success with a 0 exit code.\n exitCode = runResult.code !== 0 ? runResult.code : 1\n status = \"failed\"\n\n if (snapshot === undefined) {\n warn(`\\`${commandString}\\` failed (exit code ${runResult.code}).`)\n hint(\"No snapshot was taken (--skip-snapshot), so there is nothing to roll back.\")\n } else if (options.noRollback === true) {\n warn(`\\`${commandString}\\` failed (exit code ${runResult.code}); the database was left as-is (--no-rollback).`)\n if (snapshot.path === null) {\n hint(\"The database was empty before the migration; `meridian db reset` returns it to that state.\")\n } else {\n detail(`Pre-migration snapshot: ${snapshot.path}`)\n hint(`Replay it by hand once the proxy is up (\\`meridian dev\\`): \\`mysql < ${snapshot.path}\\`.`)\n }\n } else {\n const snapshotPath = snapshot.path\n warn(\n `\\`${commandString}\\` failed (exit code ${runResult.code}); ` +\n (snapshotPath === null\n ? \"rolling the development database back to its pre-migration (empty) state...\"\n : \"rolling back the development database to the pre-migration snapshot...\"),\n )\n try {\n await client.resetDevDatabase(appId)\n if (snapshotPath === null) {\n // The database was empty going in, so the reset above is the entire\n // rollback — there is no dump to replay.\n success(\"Development database rolled back to its pre-migration (empty) state.\")\n } else {\n await withSpinner(\n \"Restoring the pre-migration snapshot...\",\n (spinner) =>\n deps.restoreSnapshot(session.connection, snapshotPath, {\n onProgress: (executed, total) =>\n spinner.update(`Restoring the pre-migration snapshot... (${executed}/${total} statements)`),\n }),\n { success: (result) => `Restored the pre-migration snapshot (${result.statements} statements).` },\n )\n }\n status = \"rolled_back\"\n rolledBack = true\n } catch {\n error(\"Automatic rollback failed. The development database may be in a partial state — treat it as unsafe.\")\n if (snapshotPath === null) {\n hint(\"Recover by hand with `meridian db reset` — the database was empty before this migration.\")\n } else {\n detail(`Pre-migration snapshot: ${snapshotPath}`)\n hint(\n `Recover by hand: start the proxy with \\`meridian dev\\`, then run \\`mysql < ${snapshotPath}\\` to replay the ` +\n \"snapshot, or `meridian db reset` to start over from an empty schema.\",\n )\n }\n // status stays \"failed\" — a broken rollback is reported as a failed run, not a rolled-back one.\n }\n }\n\n // Last, so it is what the developer is left looking at: the rollback\n // messaging above says what happened to the database, this says why the\n // migration failed in the first place.\n const diagnosis = deps.diagnoseMigrationFailure(session.project.root)\n if (diagnosis !== null) hint(diagnosis)\n }\n\n const excerpt = excerptOf(runResult.output)\n await reportMigrationSafely(client, appId, {\n command: commandString,\n status,\n started_at: startedAt,\n finished_at: finishedAt,\n ...(excerpt !== \"\" ? { output_excerpt: excerpt } : {}),\n })\n\n if (json) {\n const payload: JsonPayload = {\n status,\n command: commandString,\n started_at: startedAt,\n finished_at: finishedAt,\n exit_code: exitCode,\n snapshot: snapshot !== undefined ? { path: snapshot.path, bytes: snapshot.bytes } : null,\n rolled_back: rolledBack,\n database: session.connection.database,\n app_id: appId,\n }\n printJson(payload)\n }\n\n return exitCode\n}\n\n/**\n * Offers to add the missing `shadowDatabaseUrl` line, then insists on it.\n *\n * Adding it is a one-line, mechanical edit that every project needs, so\n * offering beats making the developer break off and do it by hand. It is\n * offered rather than just applied because a schema is source they wrote and\n * keep in git, unlike the generated `.env` the CLI rewrites freely.\n *\n * Declining, or a datasource pointing somewhere deliberate, still falls\n * through to the assertion and its specific error.\n */\nasync function ensureShadowDatasource(root: string, deps: MigrateDeps): Promise<void> {\n const schemaPath = deps.missingShadowDatabaseUrl(root)\n\n // A run with nowhere to prompt falls straight through to the assertion:\n // its message names the exact line to add, which is more use than\n // \"cannot prompt in a non-interactive shell\".\n if (schemaPath !== null && (isAssumeYes() || isInteractive())) {\n const approved = await confirmAction({\n message: `\\`prisma migrate dev\\` needs a shadow database. Add \\`shadowDatabaseUrl\\` to ${schemaPath}?`,\n default: true,\n })\n if (approved) {\n deps.addShadowDatabaseUrl(root)\n success(`Added \\`shadowDatabaseUrl = env(\"SHADOW_DATABASE_URL\")\\` to ${style.path(schemaPath)}.`)\n }\n }\n\n deps.assertShadowDatasource(root)\n}\n\n/**\n * Runs the snapshot → `prisma migrate dev` → (rollback) → report flow.\n * `options.deps` lets tests inject fakes for every side-effecting\n * collaborator so this is exercised fully offline. The dev session is always\n * stopped, even when a step above throws.\n */\nexport async function runMigrate(options: MigrateOptions = {}): Promise<number> {\n const deps = resolveDeps(options.deps)\n const json = isJsonOutput()\n const keepSnapshots = options.keepSnapshots ?? DEFAULT_KEEP_SNAPSHOTS\n const commandArgs = [\"prisma\", \"migrate\", \"dev\", ...(options.prismaArgs ?? [])]\n const commandString = [\"npx\", ...commandArgs].join(\" \")\n\n // Both screens are specific to `migrate` — a shadow database and a\n // replayable history matter to nothing else — so they live here rather than\n // in the session flow `dev`, `db seed` and `db shell` share. Ahead of\n // startDevSession() so a run `prisma migrate dev` is certain to reject\n // never provisions a session, snapshots the database, or rolls it back.\n const project = deps.requireProject()\n if (project.config.skip_datasource_check !== true) await ensureShadowDatasource(project.root, deps)\n if (options.allowForeignMigrations !== true) deps.assertMigrationDialect(project.root)\n\n const sessionOptions: StartSessionOptions = {\n ...(options.port !== undefined ? { port: options.port } : {}),\n ...(options.envFile !== undefined ? { envFile: options.envFile } : {}),\n project,\n }\n const session = await deps.startDevSession(sessionOptions)\n\n try {\n return await runMigration(session, deps, { json, keepSnapshots, commandArgs, commandString, options })\n } finally {\n await session.stop()\n }\n}\n\ninterface MigrateCommandOptions {\n skipSnapshot?: boolean\n allowForeignMigrations?: boolean\n /** `--no-rollback` — commander negates this to `rollback`, default `true`. */\n rollback?: boolean\n keepSnapshots?: string\n port?: string\n envFile?: string\n}\n\n/** Registers `meridian migrate` on the root program; wiring only, logic lives in {@link runMigrate}. */\nexport function registerMigrateCommand(program: Command): void {\n program\n .command(\"migrate\")\n .description(\n \"Snapshot the development database, run `prisma migrate dev`, and roll back to the snapshot automatically if the migration fails.\",\n )\n .option(\"--skip-snapshot\", \"run without a pre-migration snapshot (no rollback is possible)\")\n .option(\n \"--allow-foreign-migrations\",\n \"run even when prisma/migrations was generated for SQLite or Postgres and cannot apply to MySQL\",\n )\n .option(\"--no-rollback\", \"keep a snapshot but do not automatically restore it after a failed migration\")\n .option(\"--keep-snapshots <n>\", \"number of recent snapshots to keep after a successful migration\", \"5\")\n .option(\"--port <port>\", \"preferred local port for the Cloud SQL Auth Proxy\")\n .option(\"--env-file <file>\", \"path (relative to the project root) of the .env file to patch with DATABASE_URL\")\n .argument(\"[prismaArgs...]\", \"extra arguments forwarded to `prisma migrate dev` verbatim, after --\")\n .passThroughOptions()\n .action(async (prismaArgs: string[], opts: MigrateCommandOptions) => {\n const keepSnapshots = parseIntegerOption(opts.keepSnapshots, \"--keep-snapshots\", { min: 0 })\n const port = parsePortOption(opts.port)\n const exitCode = await runMigrate({\n prismaArgs,\n ...(opts.skipSnapshot === true ? { skipSnapshot: true } : {}),\n ...(opts.allowForeignMigrations === true ? { allowForeignMigrations: true } : {}),\n ...(opts.rollback === false ? { noRollback: true } : {}),\n ...(keepSnapshots !== undefined ? { keepSnapshots } : {}),\n ...(port !== undefined ? { port } : {}),\n ...(opts.envFile !== undefined ? { envFile: opts.envFile } : {}),\n })\n process.exitCode = exitCode\n })\n}\n","/**\n * `meridian unlink` — removes `<root>/.meridian/project.json`. Leaves\n * `.meridian/snapshots/` (and anything else under `.meridian/`) alone.\n */\n\nimport type { Command } from \"commander\"\nimport { isJsonOutput, workingDirectory } from \"../lib/context.js\"\nimport { CliError } from \"../lib/errors.js\"\nimport { hint, log, printJson, success } from \"../lib/output.js\"\nimport { readProject, removeProject } from \"../lib/project.js\"\nimport { confirmAction } from \"../lib/prompts.js\"\n\nexport interface UnlinkDeps {\n /** Injectable for tests; never invokes real inquirer. */\n confirmImpl?: typeof import(\"@inquirer/prompts\").confirm\n}\n\nexport interface UnlinkOptions {\n deps?: Partial<UnlinkDeps>\n}\n\n/** Runs the unlink logic; `options.deps` lets tests inject a fake confirm prompt. */\nexport async function runUnlink(options: UnlinkOptions = {}): Promise<void> {\n const deps = { ...options.deps }\n const json = isJsonOutput()\n const root = workingDirectory()\n\n const project = readProject(root)\n if (project === null) {\n if (json) printJson({ unlinked: false, root })\n else log(\"This directory is not linked to a Meridian app.\")\n return\n }\n\n const appLabel = project.config.app_name ?? String(project.config.app_id)\n const proceed = await confirmAction({\n message: `Unlink ${project.root} from ${appLabel}?`,\n ...(deps.confirmImpl !== undefined ? { promptImpl: deps.confirmImpl } : {}),\n })\n if (!proceed) throw new CliError(\"Aborted.\")\n\n removeProject(project.root)\n\n if (json) {\n printJson({ unlinked: true, root: project.root })\n return\n }\n\n success(`Unlinked ${project.root} from ${appLabel}.`)\n hint(\"Snapshots in `.meridian/snapshots/` were left alone.\")\n}\n\nexport function registerUnlinkCommand(program: Command): void {\n program\n .command(\"unlink\")\n .description(\"Remove this project's link to a Meridian organization and app.\")\n .action(async () => {\n await runUnlink()\n })\n}\n","/**\n * `meridian whoami` — shows the logged-in user, org memberships, and any\n * linked project. `--offline` skips the network round trip and reports only\n * what is cached in `~/.meridian/config.json`, for use when the API is down.\n */\n\nimport type { Command } from \"commander\"\nimport type { Org } from \"../lib/api-types.js\"\nimport { createApiClient } from \"../lib/client.js\"\nimport type { ConfigUser } from \"../lib/config.js\"\nimport { getAuth, resolveApiBaseUrl } from \"../lib/config.js\"\nimport { getGlobalOptions, isJsonOutput, workingDirectory } from \"../lib/context.js\"\nimport { isApiError, notLoggedInError, sessionExpiredError } from \"../lib/errors.js\"\nimport { hint, keyValues, log, printJson, step, success, warn } from \"../lib/output.js\"\nimport type { LinkedProject } from \"../lib/project.js\"\nimport { readProject } from \"../lib/project.js\"\n\nexport interface WhoamiDeps {\n createClient: typeof createApiClient\n}\n\nexport interface WhoamiOptions {\n /** Skip the `getMe()` call; report only what is stored locally. */\n offline?: boolean\n deps?: Partial<WhoamiDeps>\n}\n\ninterface WhoamiResult {\n user: ConfigUser | null\n apiBaseUrl: string\n tokenExpiresAt: string | undefined\n orgs: Org[]\n offline: boolean\n}\n\nconst SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000\n\nfunction defaultDeps(): WhoamiDeps {\n return { createClient: createApiClient }\n}\n\nfunction toConfigUser(user: { id: number | string; name: string; email: string }): ConfigUser {\n return { id: user.id, name: user.name, email: user.email }\n}\n\n/** Warns when the token has already expired or expires within 7 days; undefined otherwise. */\nfunction describeExpiry(tokenExpiresAt: string | undefined): string | undefined {\n if (tokenExpiresAt === undefined) return undefined\n const expiry = new Date(tokenExpiresAt).getTime()\n if (Number.isNaN(expiry)) return undefined\n const remainingMs = expiry - Date.now()\n if (remainingMs < 0) return \"Your Meridian CLI token has expired.\"\n if (remainingMs < SEVEN_DAYS_MS) return \"Your Meridian CLI token expires soon.\"\n return undefined\n}\n\nfunction printHuman(result: WhoamiResult, project: LinkedProject | null): void {\n if (result.user !== null) {\n success(`Logged in as ${result.user.name} <${result.user.email}>`)\n } else {\n log(\"Logged in (cached user details unavailable offline).\")\n }\n\n keyValues([\n [\"User ID\", result.user !== null ? String(result.user.id) : \"unknown\"],\n [\"API URL\", result.apiBaseUrl],\n [\"Token expires\", result.tokenExpiresAt ?? \"never\"],\n ])\n\n const expiryWarning = describeExpiry(result.tokenExpiresAt)\n if (expiryWarning !== undefined) warn(expiryWarning)\n\n log()\n if (result.offline) {\n hint(\"Organization list requires network access; omitted in --offline mode.\")\n } else if (result.orgs.length > 0) {\n step(\"Organizations\")\n keyValues(result.orgs.map((org): [string, string] => [org.name, org.slug]))\n } else {\n log(\"No organizations.\")\n }\n\n log()\n if (project !== null) {\n step(\"Linked project\")\n keyValues([\n [\"App\", project.config.app_name ?? String(project.config.app_id)],\n [\"Org\", String(project.config.org_id)],\n [\"Root\", project.root],\n ])\n } else {\n hint(\"Run `meridian link` to connect this directory to a Meridian app.\")\n }\n}\n\nfunction printJsonResult(result: WhoamiResult, project: LinkedProject | null): void {\n printJson({\n user: result.user,\n api_base_url: result.apiBaseUrl,\n token_expires_at: result.tokenExpiresAt,\n orgs: result.orgs,\n project:\n project === null\n ? null\n : {\n root: project.root,\n org_id: project.config.org_id,\n app_id: project.config.app_id,\n ...(project.config.app_name !== undefined ? { app_name: project.config.app_name } : {}),\n },\n })\n}\n\n/** Runs the whoami logic; `options.deps` lets tests inject a fake API client. */\nexport async function runWhoami(options: WhoamiOptions = {}): Promise<void> {\n const deps = { ...defaultDeps(), ...options.deps }\n const json = isJsonOutput()\n\n const auth = getAuth()\n if (auth === null) throw notLoggedInError()\n\n let result: WhoamiResult\n if (options.offline === true) {\n result = {\n user: auth.user ?? null,\n apiBaseUrl: resolveApiBaseUrl(getGlobalOptions().apiUrl),\n tokenExpiresAt: auth.tokenExpiresAt,\n orgs: [],\n offline: true,\n }\n } else {\n const client = deps.createClient({ token: auth.token, requireAuth: false })\n try {\n const me = await client.getMe()\n result = {\n user: toConfigUser(me.user),\n apiBaseUrl: client.baseUrl,\n tokenExpiresAt: auth.tokenExpiresAt,\n orgs: me.orgs,\n offline: false,\n }\n } catch (error) {\n if (isApiError(error) && error.status === 401) throw sessionExpiredError(error)\n throw error\n }\n }\n\n const project = readProject(workingDirectory())\n\n if (json) printJsonResult(result, project)\n else printHuman(result, project)\n}\n\nexport function registerWhoamiCommand(program: Command): void {\n program\n .command(\"whoami\")\n .description(\n \"Show the logged-in Meridian user, org memberships, and any linked project.\\n\" +\n \"Use --offline to skip the API call and report only what is cached locally.\",\n )\n .option(\"--offline\", \"skip the API call; report only what is stored locally\")\n .action(async (opts: { offline?: boolean }) => {\n await runWhoami({ ...(opts.offline === true ? { offline: true } : {}) })\n })\n}\n","/**\n * The flags every command understands (`--json`, `--verbose`, `--yes`, …).\n *\n * The root command enables positional options so that `meridian dev -- npm run x`\n * reaches the subcommand untouched, which also means flags written after the\n * subcommand name are parsed by the subcommand. To let people type both\n * `meridian --json whoami` and `meridian whoami --json`, the same options are\n * declared on the root and on every leaf command, then merged deepest-first.\n */\n\nimport { type Command, Option } from \"commander\"\n\nimport type { GlobalOptions } from \"./context.js\"\n\nconst HELP_GROUP = \"Global Options:\"\n\nfunction globalOptions(): Option[] {\n return [\n new Option(\"--api-url <url>\", \"Meridian API base URL (overrides MERIDIAN_API_URL and the stored config)\"),\n new Option(\"--json\", \"print machine-readable JSON on stdout\").default(false),\n new Option(\"-q, --quiet\", \"only print warnings and errors\").default(false),\n new Option(\"--verbose\", \"print debug output, including stack traces\").default(false),\n new Option(\"--no-color\", \"disable ANSI colors\"),\n new Option(\"-y, --yes\", \"assume yes for every confirmation prompt\").default(false),\n new Option(\"--no-input\", \"never prompt; fail instead (for CI)\"),\n new Option(\"--cwd <dir>\", \"run as if started in this directory\"),\n ]\n}\n\n/** Declares the global flags on `command`, grouped at the bottom of its help. */\nexport function addGlobalFlags(command: Command): Command {\n for (const option of globalOptions()) {\n command.addOption(option.helpGroup(HELP_GROUP))\n }\n return command\n}\n\n/**\n * Declares the global flags on every leaf subcommand of `parent`, so new\n * commands pick them up without extra wiring. Groups such as `db` only route to\n * their children, so they are traversed rather than annotated.\n */\nexport function addGlobalFlagsToSubcommands(parent: Command): void {\n for (const child of parent.commands) {\n if (child.commands.length > 0) addGlobalFlagsToSubcommands(child)\n else addGlobalFlags(child)\n }\n}\n\n/** The command chain from `command` up to the root, deepest first. */\nfunction commandChain(command: Command): Command[] {\n const chain: Command[] = []\n let node: Command | null = command\n while (node !== null) {\n chain.push(node)\n node = node.parent\n }\n return chain\n}\n\n/**\n * Reads a global flag from the innermost command that actually saw it on the\n * command line, so `meridian --json whoami` and `meridian whoami --json` agree.\n */\nfunction explicit<T>(chain: Command[], key: string): T | undefined {\n for (const command of chain) {\n if (command.getOptionValueSource(key) === \"cli\") return command.getOptionValue(key) as T\n }\n return undefined\n}\n\n/** Merges the global flags seen anywhere along `actionCommand`'s chain. */\nexport function resolveGlobalFlags(actionCommand: Command): Partial<GlobalOptions> {\n const chain = commandChain(actionCommand)\n\n const apiUrl = explicit<string>(chain, \"apiUrl\")\n const color = explicit<boolean>(chain, \"color\")\n const input = explicit<boolean>(chain, \"input\")\n const cwd = explicit<string>(chain, \"cwd\")\n\n return {\n ...(apiUrl !== undefined ? { apiUrl } : {}),\n json: explicit<boolean>(chain, \"json\") === true,\n quiet: explicit<boolean>(chain, \"quiet\") === true,\n verbose: explicit<boolean>(chain, \"verbose\") === true,\n // `--no-color`/`--no-input` are only meaningful when asked for explicitly;\n // otherwise output and prompts auto-detect the terminal.\n ...(color !== undefined ? { color } : {}),\n yes: explicit<boolean>(chain, \"yes\") === true,\n ...(input !== undefined ? { interactive: input } : {}),\n ...(cwd !== undefined ? { cwd } : {}),\n }\n}\n"],"mappings":"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","names":["readFileSync","join","require","z","error","input","z","run","error","hint","fieldError","z","z","error","current","error","createConnection","resolve","error","extractErrorCode","hint","detail","current","truncate","error","mkdirSync","readFileSync","writeFileSync","dirname","z","z","dirname","readFileSync","error","isEnoent","mkdirSync","writeFileSync","readFileSync","join","isEnoent","error","current","resolve","join","error","resolve","isEnoent","readFileSync","chmodSync","existsSync","mkdirSync","readFileSync","renameSync","writeFileSync","dirname","line","match","isEnoent","error","writeFileSync","chmodSync","readFileSync","existsSync","mkdirSync","dirname","renameSync","input","resolve","existsSync","readFileSync","statSync","writeFileSync","dirname","join","statSync","join","existsSync","readFileSync","writeFileSync","dirname","chmodSync","existsSync","mkdirSync","readFileSync","renameSync","rmSync","writeFileSync","join","error","existsSync","join","mkdirSync","readFileSync","expected","rmSync","writeFileSync","chmodSync","renameSync","input","resolve","hint","error","current","resolve","resolve","detail","spinner","current","error","delimiter","join","delimiter","join","input","resolve","readFileSync","join","error","existsSync","join","defaultDeps","existsSync","join","org","app","osHostname","osHostname","DEFAULT_CLIENT_NAME","defaultSleep","resolve","error","osHostname","defaultDeps","client","user","error","osHostname","join","join","error","delimiter","isEnoent","defaultDeps","resolveDeps","input","spinner","appLabel","defaultDeps","toConfigUser","error","input","error"]}
|