@rebasepro/cli 0.25.1 → 0.26.0

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.
Files changed (151) hide show
  1. package/README.md +2 -1
  2. package/bin/rebase.js +143 -4
  3. package/dist/{agent-setup-BYb2Tbdz.js → agent-setup-D9mHRZ5R.js} +125 -3
  4. package/dist/agent-setup-D9mHRZ5R.js.map +1 -0
  5. package/dist/{api-keys-CSMbsmAn.js → api-keys-CyJ26KEJ.js} +41 -9
  6. package/dist/api-keys-CyJ26KEJ.js.map +1 -0
  7. package/dist/{apps-iBXNZhVN.js → apps-CnLDV5b6.js} +6 -6
  8. package/dist/{apps-iBXNZhVN.js.map → apps-CnLDV5b6.js.map} +1 -1
  9. package/dist/{atlas-dev-database-BusbHP6n.js → atlas-dev-database-BODqdCWt.js} +2 -2
  10. package/dist/{atlas-dev-database-BusbHP6n.js.map → atlas-dev-database-BODqdCWt.js.map} +1 -1
  11. package/dist/{auth-DRsTWPky.js → auth-dII2jCO1.js} +10 -7
  12. package/dist/auth-dII2jCO1.js.map +1 -0
  13. package/dist/{branch-pointer-Bn_FjNld.js → branch-pointer-BQUF6lYa.js} +1 -1
  14. package/dist/{build-et7Rccxi.js → build-Cza7ZQrp.js} +6 -6
  15. package/dist/{build-et7Rccxi.js.map → build-Cza7ZQrp.js.map} +1 -1
  16. package/dist/{bundle-DlqkDYSe.js → bundle-C6yEtMJ-.js} +53 -5
  17. package/dist/bundle-C6yEtMJ-.js.map +1 -0
  18. package/dist/bundle.d.ts +14 -0
  19. package/dist/{cloud-B-ZIjHrA.js → cloud-BdnmqQaZ.js} +8527 -4340
  20. package/dist/cloud-BdnmqQaZ.js.map +1 -0
  21. package/dist/collections-dir-DlvDhime.js +69 -0
  22. package/dist/collections-dir-DlvDhime.js.map +1 -0
  23. package/dist/commands/agent-setup.d.ts +58 -0
  24. package/dist/commands/api-keys.d.ts +13 -0
  25. package/dist/commands/cloud/activity.d.ts +25 -0
  26. package/dist/commands/cloud/app-key.d.ts +18 -0
  27. package/dist/commands/cloud/auth.d.ts +1 -0
  28. package/dist/commands/cloud/billing-invoices.d.ts +39 -0
  29. package/dist/commands/cloud/claim.d.ts +7 -0
  30. package/dist/commands/cloud/context.d.ts +115 -6
  31. package/dist/commands/cloud/deploy-summary.d.ts +162 -0
  32. package/dist/commands/cloud/deploy.d.ts +64 -0
  33. package/dist/commands/cloud/env.d.ts +24 -0
  34. package/dist/commands/cloud/index.d.ts +13 -1
  35. package/dist/commands/cloud/init.d.ts +143 -0
  36. package/dist/commands/cloud/login-flow.d.ts +51 -0
  37. package/dist/commands/cloud/notifications.d.ts +28 -0
  38. package/dist/commands/cloud/orgs.d.ts +13 -0
  39. package/dist/commands/cloud/previews.d.ts +123 -0
  40. package/dist/commands/cloud/resources.d.ts +68 -14
  41. package/dist/commands/cloud/runtime-logs.d.ts +176 -0
  42. package/dist/commands/cloud/service-key.d.ts +15 -0
  43. package/dist/commands/cloud/token-capabilities.d.ts +61 -8
  44. package/dist/commands/cloud/tokens.d.ts +18 -3
  45. package/dist/commands/cloud/usage.d.ts +63 -0
  46. package/dist/commands/dev.d.ts +10 -0
  47. package/dist/commands/doctor.d.ts +1 -1
  48. package/dist/commands/generate-view.d.ts +94 -0
  49. package/dist/commands/generate_sdk.d.ts +15 -0
  50. package/dist/commands/skills.d.ts +4 -3
  51. package/dist/commands/storage.d.ts +4 -0
  52. package/dist/commands/verify.d.ts +96 -0
  53. package/dist/{consent-BaB-eQKG.js → consent-BD7F29T3.js} +2 -2
  54. package/dist/{consent-BaB-eQKG.js.map → consent-BD7F29T3.js.map} +1 -1
  55. package/dist/{console-BlD9kjFW.js → console-BXB6-8GT.js} +12 -6
  56. package/dist/console-BXB6-8GT.js.map +1 -0
  57. package/dist/{context-DHiiiJ5C.js → context-GUxkZm-S.js} +481 -24
  58. package/dist/context-GUxkZm-S.js.map +1 -0
  59. package/dist/{daemon-DDMRbz4T.js → daemon-Cp7oNXth.js} +2 -2
  60. package/dist/{daemon-DDMRbz4T.js.map → daemon-Cp7oNXth.js.map} +1 -1
  61. package/dist/{db-9P6MnmdC.js → db-KzlqddGD.js} +37 -30
  62. package/dist/db-KzlqddGD.js.map +1 -0
  63. package/dist/{derive-MTdClnkc.js → derive-ae9UOoOB.js} +2 -2
  64. package/dist/{derive-MTdClnkc.js.map → derive-ae9UOoOB.js.map} +1 -1
  65. package/dist/{dev-BDN_OKXA.js → dev-DTqVMgB3.js} +59 -32
  66. package/dist/dev-DTqVMgB3.js.map +1 -0
  67. package/dist/{dev-preflight-FT9GbJVj.js → dev-preflight-Cxv3TiD1.js} +2 -2
  68. package/dist/{dev-preflight-FT9GbJVj.js.map → dev-preflight-Cxv3TiD1.js.map} +1 -1
  69. package/dist/{dev-server-CIZwAfZa.js → dev-server-OJsUGZEB.js} +2 -2
  70. package/dist/{dev-server-CIZwAfZa.js.map → dev-server-OJsUGZEB.js.map} +1 -1
  71. package/dist/{doctor-D8YXz7df.js → doctor-BRWOlqeG.js} +13 -11
  72. package/dist/doctor-BRWOlqeG.js.map +1 -0
  73. package/dist/{eject-izG2KjMo.js → eject-DABcDnPN.js} +3 -3
  74. package/dist/{eject-izG2KjMo.js.map → eject-DABcDnPN.js.map} +1 -1
  75. package/dist/{fold-static-CybSay_W.js → fold-static-BnAK-anQ.js} +3 -3
  76. package/dist/{fold-static-CybSay_W.js.map → fold-static-BnAK-anQ.js.map} +1 -1
  77. package/dist/generate-view-IFwCADvb.js +662 -0
  78. package/dist/generate-view-IFwCADvb.js.map +1 -0
  79. package/dist/{generate_sdk-B4R65oUV.js → generate_sdk-BvcWvoUh.js} +33 -7
  80. package/dist/generate_sdk-BvcWvoUh.js.map +1 -0
  81. package/dist/index.es.js +57 -38
  82. package/dist/index.es.js.map +1 -1
  83. package/dist/{init-DYaeppEN.js → init-CaU6GhwI.js} +8 -8
  84. package/dist/{init-DYaeppEN.js.map → init-CaU6GhwI.js.map} +1 -1
  85. package/dist/last-dev-database-DpW5dfoX.js +2 -0
  86. package/dist/{manifest-nvPdLlJY.js → manifest-BtzDy7KQ.js} +36 -3
  87. package/dist/{manifest-nvPdLlJY.js.map → manifest-BtzDy7KQ.js.map} +1 -1
  88. package/dist/{normalize-imports-BYw8ad87.js → normalize-imports-D0zXlM6g.js} +3 -3
  89. package/dist/{normalize-imports-BYw8ad87.js.map → normalize-imports-D0zXlM6g.js.map} +1 -1
  90. package/dist/{path-flags-BFgG9V6y.js → path-flags-DNvtEi2-.js} +5 -4
  91. package/dist/path-flags-DNvtEi2-.js.map +1 -0
  92. package/dist/{prepare-1rVNd2PF.js → prepare-CTw9NEkh.js} +4 -4
  93. package/dist/{prepare-1rVNd2PF.js.map → prepare-CTw9NEkh.js.map} +1 -1
  94. package/dist/{project-g4K6kV1t.js → project-CasK56vN.js} +2 -2
  95. package/dist/{project-g4K6kV1t.js.map → project-CasK56vN.js.map} +1 -1
  96. package/dist/resolve-D647F1LA.js +2 -0
  97. package/dist/{resources-CovP8AZ-.js → resources-CPSC5Kcu.js} +4 -4
  98. package/dist/{resources-CovP8AZ-.js.map → resources-CPSC5Kcu.js.map} +1 -1
  99. package/dist/{schema-nuxvvc50.js → schema-BSXwZSiI.js} +9 -7
  100. package/dist/schema-BSXwZSiI.js.map +1 -0
  101. package/dist/{skills-DeUIsZcT.js → skills-BU2flMOy.js} +52 -7
  102. package/dist/skills-BU2flMOy.js.map +1 -0
  103. package/dist/{start-RzZqDroW.js → start-mVb6upwY.js} +5 -5
  104. package/dist/{start-RzZqDroW.js.map → start-mVb6upwY.js.map} +1 -1
  105. package/dist/static-syntax-check.d.ts +64 -0
  106. package/dist/{status-D9Zm88NZ.js → status-BREvtzJm.js} +7 -7
  107. package/dist/{status-D9Zm88NZ.js.map → status-BREvtzJm.js.map} +1 -1
  108. package/dist/{storage-BB3umRfw.js → storage-DtOXGflp.js} +159 -15
  109. package/dist/storage-DtOXGflp.js.map +1 -0
  110. package/dist/{telemetry-HfU5uAh1.js → telemetry-CgwJPVMO.js} +2 -2
  111. package/dist/{telemetry-HfU5uAh1.js.map → telemetry-CgwJPVMO.js.map} +1 -1
  112. package/dist/{telemetry-TseNLk6X.js → telemetry-DwK5RQJl.js} +4 -4
  113. package/dist/{telemetry-TseNLk6X.js.map → telemetry-DwK5RQJl.js.map} +1 -1
  114. package/dist/{upgrade-apiPKKE_.js → upgrade-B7sVwL8S.js} +4 -4
  115. package/dist/{upgrade-apiPKKE_.js.map → upgrade-B7sVwL8S.js.map} +1 -1
  116. package/dist/utils/collections-dir.d.ts +14 -0
  117. package/dist/utils/path-flags.d.ts +2 -1
  118. package/dist/utils/tool-stdio.d.ts +1 -1
  119. package/dist/verify-D7UsV_qe.js +730 -0
  120. package/dist/verify-D7UsV_qe.js.map +1 -0
  121. package/package.json +9 -7
  122. package/templates/eject/backend/src/index.ts +9 -1
  123. package/templates/generated-schemas/ecommerce.ts +3 -0
  124. package/templates/overlays/baas/ai-instructions.md +13 -0
  125. package/templates/template/.claude/hooks/post-edit-collection.sh +99 -0
  126. package/templates/template/.claude/settings.json +17 -0
  127. package/templates/template/.env.example +10 -1
  128. package/templates/template/ai-instructions.md +21 -1
  129. package/templates/template/config/collections/presets/ecommerce/index.ts +23 -0
  130. package/templates/template/docker-compose.yml +4 -1
  131. package/templates/template/frontend/package.json +1 -0
  132. package/templates/views/AppView.tsx.tmpl +138 -0
  133. package/templates/views/EntityView.tsx.tmpl +64 -0
  134. package/templates/views/index.ts.tmpl +8 -0
  135. package/dist/agent-setup-BYb2Tbdz.js.map +0 -1
  136. package/dist/api-keys-CSMbsmAn.js.map +0 -1
  137. package/dist/auth-DRsTWPky.js.map +0 -1
  138. package/dist/bundle-DlqkDYSe.js.map +0 -1
  139. package/dist/cloud-B-ZIjHrA.js.map +0 -1
  140. package/dist/console-BlD9kjFW.js.map +0 -1
  141. package/dist/context-DHiiiJ5C.js.map +0 -1
  142. package/dist/db-9P6MnmdC.js.map +0 -1
  143. package/dist/dev-BDN_OKXA.js.map +0 -1
  144. package/dist/doctor-D8YXz7df.js.map +0 -1
  145. package/dist/generate_sdk-B4R65oUV.js.map +0 -1
  146. package/dist/last-dev-database-B_75fxZC.js +0 -2
  147. package/dist/path-flags-BFgG9V6y.js.map +0 -1
  148. package/dist/resolve-BQUAC3Wi.js +0 -2
  149. package/dist/schema-nuxvvc50.js.map +0 -1
  150. package/dist/skills-DeUIsZcT.js.map +0 -1
  151. package/dist/storage-BB3umRfw.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"console-BlD9kjFW.js","names":[],"sources":["../src/commands/console.ts"],"sourcesContent":["/**\n * CLI command: rebase console\n *\n * A Node REPL with the project open — `rebase` (what `openRebase` from\n * `@rebasepro/server-postgres` returns: `dataAsAdmin`, `sql`, `withAuth`) and\n * `collections` in scope — or, with `--eval`, one piece of code run and its\n * result printed as JSON.\n *\n * Resolved like `rebase db push`: the same project and `.env`, the same\n * database (the managed one started if that is what the project uses), the\n * same `--collections` loader — the driver's, spawned in `backend/`. Opening\n * the database changes nothing in it.\n */\nimport chalk from \"chalk\";\nimport path from \"path\";\nimport { parseCommandArgs, wantsHelp } from \"../utils/args\";\nimport { argsFromCommand } from \"../utils/command-words\";\nimport { COLLECTIONS_FLAG_HELP, refuseMissingCollectionsPath } from \"../utils/path-flags\";\nimport { reportSpawnFailure } from \"../utils/spawn-error\";\nimport { DEV_DATABASE_KIND_ENV, managedNotices, prepareDatabaseEnv } from \"../dev-db/prepare\";\nimport { absolutizeLocalPathArgs, ensureDockerDatabase, resolveDriverCli, spawnDriverCli } from \"./db\";\n\nexport const CONSOLE_FLAGS = {\n \"--eval\": String,\n \"-e\": \"--eval\",\n \"--collections\": String,\n \"-c\": \"--collections\",\n \"--database-url\": String,\n \"--docker\": Boolean\n} as const;\n\n/** What each long flag above does, for the Options block. */\nconst CONSOLE_FLAG_HELP: Record<string, string> = {\n \"--eval\": \"Run this code instead of the REPL, print its awaited result as JSON, and exit 1 if it throws\",\n \"--collections\": COLLECTIONS_FLAG_HELP,\n \"--database-url\": \"Open this database instead of the project's\",\n \"--docker\": \"Use the database from docker compose, starting it if needed\"\n};\n\n/** Where the REPL keeps its history: the project's own `.rebase/`, which the scaffold ignores. */\nexport function consoleHistoryPath(projectRoot: string): string {\n return path.join(projectRoot, \".rebase\", \"console_history\");\n}\n\nfunction flagLabel(flag: string): string {\n const aliases = Object.entries(CONSOLE_FLAGS)\n .filter(([, target]) => target === flag)\n .map(([alias]) => alias);\n return [flag, ...aliases].join(\", \");\n}\n\nexport function printConsoleHelp(): void {\n console.log(`\n${chalk.bold(\"rebase console\")} — Explore the project's data from a REPL\n\n${chalk.green.bold(\"Usage\")}\n rebase console [options]\n\n${chalk.green.bold(\"Options\")}\n${Object.keys(CONSOLE_FLAG_HELP)\n .map(flag => ` ${chalk.blue(flagLabel(flag).padEnd(22))} ${CONSOLE_FLAG_HELP[flag]}`)\n .join(\"\\n\")}\n\nIn scope:\n rebase dataAsAdmin, sql(query, { params }), withAuth(user) → { data }, close()\n collections the project's collections\n\nTop-level await works. Opening the database changes nothing in it: no table,\nrole or trigger is created. withAuth runs as the user under row-level security.\n\n${chalk.green.bold(\"Examples\")}\n rebase console\n rebase console -e \"rebase.dataAsAdmin.posts.find({ limit: 5 })\"\n rebase console -e \"(await rebase.withAuth({ uid: 'u1', roles: ['user'] })).data.posts.find()\"\n rebase console -e \"rebase.sql('select count(*) from posts')\"\n`);\n}\n\nexport async function consoleCommand(rawArgs: string[]): Promise<void> {\n if (wantsHelp(rawArgs)) {\n printConsoleHelp();\n return;\n }\n\n // Strictly, before the line is relayed: the driver would otherwise be the\n // first to see a mistyped flag, after a database had been started for it.\n const { flags } = parseCommandArgs({\n spec: CONSOLE_FLAGS,\n rawArgs,\n commandWords: 1,\n command: \"console\",\n maxPositionals: 0\n });\n\n const resolved = await resolveDriverCli();\n const { projectRoot, backendDir } = resolved;\n refuseMissingCollectionsPath(rawArgs, process.cwd(), backendDir, \"console\");\n await ensureDockerDatabase(projectRoot, rawArgs);\n\n // With --eval, stdout is the result and nothing else, so it can be piped\n // into `jq`; piped into the REPL, it is the REPL's answers. Either way what\n // the database resolution has to say goes to stderr.\n const say = flags[\"--eval\"] === undefined && process.stdin.isTTY\n ? (line: string) => console.log(chalk.gray(` ${line}`))\n : (line: string) => console.error(chalk.gray(` ${line}`));\n const prepared = await prepareDatabaseEnv(projectRoot, {\n flagUrl: flags[\"--database-url\"] ?? null,\n flagDocker: flags[\"--docker\"] === true,\n onProgress: say\n });\n Object.assign(resolved.env, prepared.env);\n // The database this run resolved, flags included, so the driver words a\n // failure to open it for that one — a managed database that has no free\n // connection is not \"is your Postgres running?\".\n resolved.env[DEV_DATABASE_KIND_ENV] = prepared.database.kind;\n for (const line of managedNotices(prepared)) say(line);\n\n const childArgs = [\n ...absolutizeLocalPathArgs(argsFromCommand(rawArgs, \"console\"), process.cwd()),\n `--history=${consoleHistoryPath(projectRoot)}`\n ];\n\n try {\n await spawnDriverCli(resolved, childArgs);\n } catch (error) {\n // A child that exited non-zero has already said why, on the terminal it\n // shares — an `--eval` that threw, a database that refused.\n reportSpawnFailure(error);\n process.exit(1);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAsBA,IAAa,gBAAgB;CACzB,UAAU;CACV,MAAM;CACN,iBAAiB;CACjB,MAAM;CACN,kBAAkB;CAClB,YAAY;AAChB;;AAGA,IAAM,oBAA4C;CAC9C,UAAU;CACV,iBAAiB;CACjB,kBAAkB;CAClB,YAAY;AAChB;;AAGA,SAAgB,mBAAmB,aAA6B;CAC5D,OAAO,KAAK,KAAK,aAAa,WAAW,iBAAiB;AAC9D;AAEA,SAAS,UAAU,MAAsB;CAIrC,OAAO,CAAC,MAAM,GAHE,OAAO,QAAQ,aAAa,CAAC,CACxC,QAAQ,GAAG,YAAY,WAAW,IAAI,CAAC,CACvC,KAAK,CAAC,WAAW,KACL,CAAO,CAAC,CAAC,KAAK,IAAI;AACvC;AAEA,SAAgB,mBAAyB;CACrC,QAAQ,IAAI;EACd,MAAM,KAAK,gBAAgB,EAAE;;EAE7B,MAAM,MAAM,KAAK,OAAO,EAAE;;;EAG1B,MAAM,MAAM,KAAK,SAAS,EAAE;EAC5B,OAAO,KAAK,iBAAiB,CAAC,CACvB,KAAI,SAAQ,KAAK,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,kBAAkB,OAAO,CAAC,CACrF,KAAK,IAAI,EAAE;;;;;;;;;EASlB,MAAM,MAAM,KAAK,UAAU,EAAE;;;;;CAK9B;AACD;AAEA,eAAsB,eAAe,SAAkC;CACnE,IAAI,UAAU,OAAO,GAAG;EACpB,iBAAiB;EACjB;CACJ;CAIA,MAAM,EAAE,UAAU,iBAAiB;EAC/B,MAAM;EACN;EACA,cAAc;EACd,SAAS;EACT,gBAAgB;CACpB,CAAC;CAED,MAAM,WAAW,MAAM,iBAAiB;CACxC,MAAM,EAAE,aAAa,eAAe;CACpC,6BAA6B,SAAS,QAAQ,IAAI,GAAG,YAAY,SAAS;CAC1E,MAAM,qBAAqB,aAAa,OAAO;CAK/C,MAAM,MAAM,MAAM,cAAc,KAAA,KAAa,QAAQ,MAAM,SACpD,SAAiB,QAAQ,IAAI,MAAM,KAAK,KAAK,MAAM,CAAC,KACpD,SAAiB,QAAQ,MAAM,MAAM,KAAK,KAAK,MAAM,CAAC;CAC7D,MAAM,WAAW,MAAM,mBAAmB,aAAa;EACnD,SAAS,MAAM,qBAAqB;EACpC,YAAY,MAAM,gBAAgB;EAClC,YAAY;CAChB,CAAC;CACD,OAAO,OAAO,SAAS,KAAK,SAAS,GAAG;CAIxC,SAAS,IAAI,yBAAyB,SAAS,SAAS;CACxD,KAAK,MAAM,QAAQ,eAAe,QAAQ,GAAG,IAAI,IAAI;CAErD,MAAM,YAAY,CACd,GAAG,wBAAwB,gBAAgB,SAAS,SAAS,GAAG,QAAQ,IAAI,CAAC,GAC7E,aAAa,mBAAmB,WAAW,GAC/C;CAEA,IAAI;EACA,MAAM,eAAe,UAAU,SAAS;CAC5C,SAAS,OAAO;EAGZ,mBAAmB,KAAK;EACxB,QAAQ,KAAK,CAAC;CAClB;AACJ"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"context-DHiiiJ5C.js","names":[],"sources":["../src/commands/cloud/errors.ts","../src/commands/cloud/context.ts"],"sourcesContent":["/**\n * Turning a control-plane failure into something the caller can act on.\n *\n * The control plane talks to Kubernetes, and when Kubernetes refuses it, the\n * refusal travels back verbatim: a whole `Status` object, the request headers,\n * an `audit-id`, an `x-kubernetes-pf-flowschema-uid`. That reached the user's\n * terminal unedited. Two things are wrong with it beyond the noise.\n *\n * The first is that the one sentence that matters is buried in the middle of a\n * JSON blob, so the remedy — if there is one — is the hardest part to find.\n *\n * The second is worse, and is the reason this file exists rather than a\n * `slice(0, 200)`. A `403` naming a `system:serviceaccount:` is a statement\n * about the PLATFORM's own credentials: some role the control plane runs as is\n * missing a grant. Nothing in the user's project can change that — not the\n * collections, not `rebase.json`, not the deploy flags — and the error, printed\n * raw in the middle of `rebase cloud deploy`, reads exactly like a project\n * fault. Someone acting on that reading deletes working code looking for the\n * cause. (That is not hypothetical: three cron jobs were removed from a project\n * to test whether they caused a `cronjobs.batch` 403. They did not.)\n *\n * So this classifies before it summarises, and says whose problem it is.\n */\n\nimport { parseEnvBoolean } from \"@rebasepro/types\";\n\nimport { switchOn } from \"../../utils/args\";\n\n/** What a Kubernetes API refusal carries, once it is found. */\nexport interface KubernetesStatus {\n message?: string;\n reason?: string;\n code?: number;\n details?: { group?: string; kind?: string; name?: string };\n}\n\nexport interface ErrorSummary {\n /** One line, safe to print. Never the raw body. */\n message: string;\n /** A remedy, when one exists — or the reason there is none. */\n hint?: string;\n /** A stable code for `--json` callers to branch on. */\n code: string;\n /**\n * Whether the failure is the platform's rather than the project's.\n *\n * The whole point of the summary: a caller that retries or mutates the\n * project on a platform-side refusal makes things worse, and an agent\n * cannot tell from the prose.\n */\n platform: boolean;\n /** The untouched original, printed only under `--debug`. */\n raw: string;\n}\n\n/**\n * The service accounts a Kubernetes 403 can name, and what each means.\n *\n * `system:serviceaccount:` is the platform's own identity — the control plane's\n * pod, or a tenant's operator. A project cannot grant it anything, because the\n * grant lives in a cluster the project does not own. `system:anonymous` is the\n * same fact with the credential missing entirely.\n */\nconst PLATFORM_PRINCIPAL_RE = /system:(?:serviceaccount:|anonymous|node:)/;\n\n/**\n * A Kubernetes `Status` object embedded anywhere in a message.\n *\n * Scanned for rather than parsed off the front: the control plane wraps it\n * (\"Failed to create the tenant namespace: …\"), the client library appends\n * headers after it, and both halves are worth keeping out of the summary.\n * Balanced-brace scanning rather than a regex, because `details.causes` nests\n * and a lazy `\\{.*?\\}` truncates the object at the first inner brace — which\n * parses to nothing and silently falls through to the raw message.\n */\nexport function extractKubernetesStatus(text: string): KubernetesStatus | undefined {\n for (let start = text.indexOf(\"{\"); start !== -1; start = text.indexOf(\"{\", start + 1)) {\n let depth = 0;\n let inString = false;\n let escaped = false;\n for (let i = start; i < text.length; i++) {\n const ch = text[i];\n if (escaped) {\n escaped = false;\n continue;\n }\n if (ch === \"\\\\\") {\n escaped = true;\n continue;\n }\n if (ch === '\"') {\n inString = !inString;\n continue;\n }\n if (inString) continue;\n if (ch === \"{\") depth++;\n else if (ch === \"}\") {\n depth--;\n if (depth !== 0) continue;\n const candidate = text.slice(start, i + 1);\n let parsed: unknown;\n try {\n parsed = JSON.parse(candidate);\n } catch {\n break; // Not JSON; try the next opening brace.\n }\n const obj = parsed as Record<string, unknown> & KubernetesStatus;\n // `kind: \"Status\"` is the marker the API server always sets on a\n // refusal. Requiring it means an ordinary JSON body in an error\n // message — a validation report, say — is left alone.\n if (obj?.kind === \"Status\" || (obj?.status === \"Failure\" && typeof obj.code === \"number\")) {\n return {\n message: typeof obj.message === \"string\" ? obj.message : undefined,\n reason: typeof obj.reason === \"string\" ? obj.reason : undefined,\n code: typeof obj.code === \"number\" ? obj.code : undefined,\n details: (obj.details as KubernetesStatus[\"details\"]) ?? undefined\n };\n }\n break;\n }\n }\n }\n return undefined;\n}\n\n/**\n * Strip the transport noise a Kubernetes client appends to its own message.\n *\n * Only ever applied to the fallback path — when no `Status` was found, the\n * message is all there is, and cutting it at the first header keeps the\n * sentence while dropping the `audit-id` and the flowschema uid nobody outside\n * the cluster can use.\n */\nfunction trimTransportNoise(message: string): string {\n const cut = message.search(\n /\\s*(?:headers:|HTTP request failed|audit-id|x-kubernetes-pf-|\\{\"kind\":\"Status\")/i\n );\n const trimmed = (cut > 0 ? message.slice(0, cut) : message).trim();\n return trimmed.replace(/[\\s:,-]+$/, \"\");\n}\n\n/** The longest a summary may be before it stops being one. */\nconst MAX_SUMMARY = 300;\n\n/**\n * One actionable line (plus a hint) from whatever the control plane returned.\n *\n * `status` is the HTTP status of the control-plane call itself, which is a\n * different number from the `code` inside an embedded Kubernetes `Status` — the\n * control plane routinely answers 500 while the cluster answered 403, and it is\n * the inner one that says what happened.\n */\nexport function summarizeError(error: unknown, context: string): ErrorSummary {\n const err = error as { status?: number; message?: string; code?: string };\n const raw = err?.message ?? String(error);\n const k8s = extractKubernetesStatus(raw);\n\n if (k8s) {\n const inner = k8s.message?.trim() ?? \"\";\n const forbidden = k8s.code === 403 || k8s.reason === \"Forbidden\";\n const platform = forbidden && PLATFORM_PRINCIPAL_RE.test(inner);\n\n if (platform) {\n return {\n // Named as the platform's before the sentence that follows, so\n // the first thing read is whose problem it is.\n message: `${context}: the platform's own cluster credentials were refused by Kubernetes.`,\n hint:\n `${truncate(inner)}\\n`\n + \" This is a platform-side permission, not something your project can grant. \"\n + \"Nothing in your code, collections or deploy flags will change it — \"\n + \"report it with the message above rather than retrying or changing the project.\",\n code: \"platform_permission_denied\",\n platform: true,\n raw\n };\n }\n\n return {\n message: `${context}: ${truncate(inner || k8s.reason || \"the cluster refused the request\")}`,\n hint: k8s.code ? `Kubernetes answered ${k8s.code}${k8s.reason ? ` (${k8s.reason})` : \"\"}.` : undefined,\n code: k8s.reason ? `k8s_${k8s.reason.toLowerCase()}` : \"k8s_error\",\n platform: false,\n raw\n };\n }\n\n // Not a Kubernetes refusal. Still worth trimming: the same transport dumps\n // its headers onto plenty of errors that carry no `Status` at all.\n const trimmed = trimTransportNoise(raw);\n return {\n message: `${context}${err?.status ? ` (${err.status})` : \"\"}: ${truncate(trimmed || raw)}`,\n code: err?.code ?? (err?.status ? `http_${err.status}` : \"request_failed\"),\n platform: false,\n raw\n };\n}\n\nfunction truncate(text: string): string {\n const flat = text.replace(/\\s+/g, \" \").trim();\n return flat.length > MAX_SUMMARY ? `${flat.slice(0, MAX_SUMMARY - 1)}…` : flat;\n}\n\n/**\n * Whether the caller asked for the untouched body.\n *\n * `--debug` is already what `bin/rebase.js` prints after every failure as the\n * thing to add, so the raw payload hangs off the flag people are told to reach\n * for rather than off one invented here.\n *\n * The one reader of `REBASE_DEBUG` in the commands, spelled as the bin spells\n * it. It used to be `=== \"1\"` here while the quote fallbacks in `resources.ts`\n * tested the raw string for truthiness, so `=true` hid the body and `=0`\n * printed the fallback.\n */\nexport function wantsRawError(argv: readonly string[] = process.argv): boolean {\n return switchOn(argv, \"--debug\") || parseEnvBoolean(process.env.REBASE_DEBUG) === true;\n}\n","/**\n * Shared foundation for the `rebase cloud` command family.\n *\n * Everything cloud subcommands need in common lives here:\n * - credential storage (~/.rebase/credentials.json, keyed per control-plane host)\n * - project link file (.rebase/cloud.json in the project dir)\n * - control-plane URL resolution\n * - an authenticated `@rebasepro/client` instance (createCloudClient / requireClient)\n * - small output helpers shared across subcommands\n *\n * The control plane is itself a Rebase app, so we reuse the same SDK the web\n * console uses (`@rebasepro/client`). Auth, token refresh, the data REST client\n * and function invocation all come from the SDK — the CLI only supplies a\n * file-backed AuthStorage so a login persists across invocations.\n */\nimport fs from \"fs\";\nimport os from \"os\";\nimport path from \"path\";\nimport { spawn } from \"child_process\";\nimport chalk from \"chalk\";\nimport arg from \"arg\";\nimport inquirer from \"inquirer\";\nimport { createMemoryStorage, createRebaseClient, type AuthStorage } from \"@rebasepro/client\";\nimport { findProjectRoot } from \"../../utils/project\";\nimport { parseCommandArgs } from \"../../utils/args\";\nimport { cliUserAgent } from \"../../utils/version\";\nimport { summarizeError, wantsRawError } from \"./errors\";\nimport { parseEnvBoolean } from \"@rebasepro/types\";\n\n/* ═══════════════════════════════════════════════════════════════\n Constants & paths\n ═══════════════════════════════════════════════════════════════ */\n\n/** Default hosted control plane (the Rebase Cloud console origin). */\nconst DEFAULT_CLOUD_URL = \"https://app.rebase.pro\";\n\n/** The storage key the SDK's auth module reads/writes the session under. */\nconst SDK_SESSION_KEY = \"rebase_auth\";\n\n/** ~/.rebase/credentials.json — one file, many hosts. */\nfunction credentialsPath(): string {\n return path.join(os.homedir(), \".rebase\", \"credentials.json\");\n}\n\n/** Project-local link file: <project>/.rebase/cloud.json */\n/**\n * The billing account an organization row points at, whichever key it arrived under.\n *\n * REST serves every column under its own property name, so the relation comes\n * back as `billingAccountId`. Both readers in this CLI checked\n * `billing_account_id` and `billingAccount` — neither is what arrives — so\n * `rebase cloud billing` answered \"no billing account\" for every organization,\n * and the deploy pre-check never saw an internal plan. The other two spellings\n * are still accepted: older servers and fixtures send them.\n */\nexport function billingAccountIdOf(org: unknown): string | number | undefined {\n if (typeof org !== \"object\" || org === null) return undefined;\n for (const key of [\"billingAccountId\", \"billing_account_id\", \"billingAccount\"]) {\n const value = (org as Record<string, unknown>)[key];\n if (typeof value === \"string\" || typeof value === \"number\") return value;\n }\n return undefined;\n}\n\nexport function projectLinkPath(cwd: string = process.cwd()): string {\n const root = findProjectRoot(cwd) || cwd;\n return path.join(root, \".rebase\", \"cloud.json\");\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Credentials file model\n ═══════════════════════════════════════════════════════════════\n\n {\n \"current\": \"https://app.rebase.pro\",\n \"contexts\": {\n \"https://app.rebase.pro\": { \"auth\": \"<sdk session json>\", \"org\": \"42\" }\n }\n }\n*/\n\ninterface CloudContextEntry {\n /** Raw JSON blob the SDK auth module persists (the RebaseSession). */\n auth?: string;\n /** Active organization id for this host, if the user selected one. */\n org?: string;\n}\n\ninterface CredentialsFile {\n current?: string;\n contexts: Record<string, CloudContextEntry>;\n}\n\nfunction readCredentials(): CredentialsFile {\n try {\n const raw = fs.readFileSync(credentialsPath(), \"utf-8\");\n const parsed = JSON.parse(raw) as CredentialsFile;\n if (!parsed.contexts) parsed.contexts = {};\n return parsed;\n } catch {\n return { contexts: {} };\n }\n}\n\nfunction writeCredentials(data: CredentialsFile): void {\n const file = credentialsPath();\n fs.mkdirSync(path.dirname(file), { recursive: true });\n // Written with private perms — this file holds refresh tokens.\n fs.writeFileSync(file, JSON.stringify(data, null, 2), { mode: 0o600 });\n try {\n fs.chmodSync(file, 0o600);\n } catch {\n // best effort on platforms without chmod semantics\n }\n}\n\n/** Host that a bare `rebase cloud` command should target, if any. */\nfunction currentContextUrl(): string | undefined {\n return readCredentials().current;\n}\n\n/** Persist the active organization id for a host. */\nexport function setContextOrg(url: string, org: string | undefined): void {\n const creds = readCredentials();\n const entry = creds.contexts[url] || {};\n if (org) entry.org = org;\n else delete entry.org;\n creds.contexts[url] = entry;\n writeCredentials(creds);\n}\n\nexport function getContextOrg(url: string): string | undefined {\n return readCredentials().contexts[url]?.org;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n File-backed AuthStorage (per host)\n ═══════════════════════════════════════════════════════════════ */\n\nfunction createFileAuthStorage(url: string): AuthStorage {\n return {\n getItem(key) {\n if (key !== SDK_SESSION_KEY) return null;\n return readCredentials().contexts[url]?.auth ?? null;\n },\n setItem(key, value) {\n if (key !== SDK_SESSION_KEY) return;\n const creds = readCredentials();\n const entry = creds.contexts[url] || {};\n entry.auth = value;\n creds.contexts[url] = entry;\n if (!creds.current) creds.current = url;\n writeCredentials(creds);\n },\n removeItem(key) {\n if (key !== SDK_SESSION_KEY) return;\n const creds = readCredentials();\n if (creds.contexts[url]) {\n delete creds.contexts[url].auth;\n delete creds.contexts[url].org;\n }\n writeCredentials(creds);\n }\n };\n}\n\n/** Mark a host as the active context (called on login). */\nexport function setCurrentContext(url: string): void {\n const creds = readCredentials();\n creds.current = url;\n if (!creds.contexts[url]) creds.contexts[url] = {};\n writeCredentials(creds);\n}\n\n/* ═══════════════════════════════════════════════════════════════\n URL resolution\n ═══════════════════════════════════════════════════════════════\n\n Priority: --url flag > REBASE_CLOUD_URL env > CLOUD link's url\n > stored current context > default hosted URL.\n\n A **direct** link is deliberately absent from that list; see below.\n*/\n\n/**\n * Where the control-plane URL came from. `link` is the one a repository chose\n * rather than the user — see {@link isKnownControlPlane}.\n */\nexport type CloudUrlSource = \"flag\" | \"env\" | \"link\" | \"context\" | \"default\";\n\nexport function resolveCloudUrl(rawArgs: string[]): string {\n return resolveCloudTarget(rawArgs).url;\n}\n\n/** The control-plane URL, and which rung of the ladder above supplied it. */\nexport function resolveCloudTarget(rawArgs: string[]): { url: string; source: CloudUrlSource } {\n const parsed = arg({ \"--url\": String }, { argv: rawArgs.slice(2),\npermissive: true });\n if (parsed[\"--url\"]) return { url: normalizeUrl(parsed[\"--url\"]),\nsource: \"flag\" };\n if (process.env.REBASE_CLOUD_URL) return { url: normalizeUrl(process.env.REBASE_CLOUD_URL),\nsource: \"env\" };\n\n const link = readLink();\n /*\n * A direct link is a tenant, not a control plane.\n *\n * `rebase cloud link <url>` points this checkout at ONE running Rebase API\n * — \"no control plane, no login\", as its own help page puts it — so its URL\n * is the customer's own backend. Returning it here made it the control\n * plane for the entire `cloud` family: `whoami` reported \"Not logged in to\n * https://api.example.com\", and following that printed remedy POSTed the\n * user's *control-plane* email and password to the tenant host.\n *\n * Commands that genuinely need a control plane refuse instead — see\n * `refuseDirectLink`, which every one of them reaches through\n * `requireClient` (and `login`, which builds its client directly).\n */\n if (link?.url && link.mode !== \"direct\") return { url: normalizeUrl(link.url),\nsource: \"link\" };\n\n const current = currentContextUrl();\n if (current) return { url: normalizeUrl(current),\nsource: \"context\" };\n\n return { url: DEFAULT_CLOUD_URL,\nsource: \"default\" };\n}\n\n/**\n * Whether a control-plane host is one the user chose: the platform's own, or a\n * host already in their credentials file because they signed in to it.\n *\n * A link file is part of the repository, and a cloned repository is not the\n * user's to trust with their password. `login` asks before sending one to a\n * linked host that is neither.\n */\nexport function isKnownControlPlane(url: string): boolean {\n return url === DEFAULT_CLOUD_URL || Object.hasOwn(readCredentials().contexts, url);\n}\n\n/**\n * Refuse to run a control-plane command in a directory linked straight at a\n * backend.\n *\n * The alternative — quietly using the default control plane — would be worse\n * than the bug it replaces: the user asked for `https://api.example.com` and\n * would get an answer about `app.rebase.pro` with nothing saying so. Naming the\n * link, and both ways out of it, is the whole message.\n *\n * `--project` and `--url` are the ways out, so a line carrying either passes\n * through: both say, explicitly, which control-plane subject the caller means.\n */\nexport function refuseDirectLink(rawArgs: string[]): void {\n const link = readLink();\n if (link?.mode !== \"direct\") return;\n\n const parsed = arg(\n { \"--project\": String,\n\"-p\": \"--project\",\n\"--url\": String },\n { argv: rawArgs.slice(2),\npermissive: true }\n );\n if (parsed[\"--project\"] || parsed[\"--url\"]) return;\n\n fail(\n `This directory is linked directly to ${chalk.cyan(link.url)} — `\n + `${chalk.bold(\"rebase cloud unlink\")} first, or pass ${chalk.bold(\"--project\")}.`,\n \"A direct link is one backend, not a control plane: it has no projects, no organizations and no session.\",\n \"direct_link\"\n );\n}\n\nfunction normalizeUrl(url: string): string {\n let u = url.trim().replace(/\\/+$/, \"\");\n if (!/^https?:\\/\\//.test(u)) u = `https://${u}`;\n return u;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Rebase client factory + auth guard\n ═══════════════════════════════════════════════════════════════ */\n\nexport type CloudClient = ReturnType<typeof createRebaseClient>;\n\n/**\n * Build an SDK client bound to a control-plane host, backed by the on-disk\n * credential store. `autoRefresh` is disabled so we never leave a dangling\n * setTimeout that keeps the CLI process alive; token refresh is done on demand\n * by `requireClient`.\n */\nexport function createCloudClient(url: string): CloudClient {\n return createRebaseClient({\n baseUrl: url,\n // No cloud subcommand needs a socket. The one that looks like it might —\n // `logs -f` — polls `deployments.findById` on a timer (see\n // `streamBuildLogs`), so nothing here ever opens a channel or an\n // `observe()`.\n //\n // This used to say `websocketUrl: \"\"` and mean the same thing. It stopped\n // meaning it when the client grew a diagnostic for the case it produces:\n // realtime is on unless you switch it off, so \"on, with no usable URL\"\n // reads as a misconfiguration and warns. The warning is right — and it\n // was firing on every single `rebase cloud` invocation, telling the user\n // to fix the CLI's own client construction, in prose they had no way to\n // act on. `realtime: false` is the escape it names: it is the difference\n // between \"no socket, because I never asked for one\" and \"no socket, and\n // I do not know why\".\n realtime: false,\n // Every control-plane request says which CLI is calling. The control\n // plane's wire format moves ahead of what is published to npm, so it\n // has to be able to answer an old client with `CLI_TOO_OLD` and the\n // minimum version — and it cannot do that for a caller that never\n // identified itself. Until this line, none of them did.\n headers: { \"User-Agent\": cliUserAgent() },\n auth: {\n storage: createFileAuthStorage(url),\n persistSession: true,\n autoRefresh: false\n }\n });\n}\n\n/**\n * The environment variable that authenticates the cloud family with a token\n * instead of a `cloud login` session — for CI and agents, which have no\n * terminal to log in at and should not hold a person's password.\n */\nexport const TOKEN_ENV = \"REBASE_TOKEN\";\n\n/** `REBASE_TOKEN`, trimmed, or undefined when it is unset or blank. */\nexport function envToken(): string | undefined {\n const value = process.env[TOKEN_ENV]?.trim();\n return value ? value : undefined;\n}\n\n/** The token each token-authenticated client was built with — see {@link freshAccessToken}. */\nconst STATIC_TOKENS = new WeakMap<object, string>();\n\n/**\n * A client that sends `token` as its bearer and nothing else.\n *\n * No session: the token is not refreshed, and the credentials file is neither\n * read nor written — a CI job's token must not become, or replace, the login\n * of whoever owns the machine. A 401 is answered by {@link explainRefusedToken}\n * rather than by the SDK's session refresh, because there is no session to\n * refresh and \"log in again\" is the wrong remedy for a token.\n */\nexport function createTokenClient(url: string, token: string): CloudClient {\n const client = createRebaseClient({\n baseUrl: url,\n realtime: false,\n headers: { \"User-Agent\": cliUserAgent() },\n token,\n auth: {\n storage: createMemoryStorage(),\n persistSession: false,\n autoRefresh: false\n }\n });\n client.setOnUnauthorized(() => explainRefusedToken(url, token));\n STATIC_TOKENS.set(client, token);\n return client;\n}\n\n/**\n * Why the control plane answered a token-authenticated request with 401, and\n * what to do about it. Never returns.\n *\n * Two different causes reach the same status. Usually the token itself was\n * refused — it expired, was revoked, or belongs to another control plane — and\n * the remedy is a new token. But a few endpoints take only a person's session\n * (`/auth/me` among them), and those refuse a perfectly good token too. One\n * request to `/api/auth/scopes`, which accepts a token, tells the two apart, so\n * neither is answered with the other's remedy.\n */\nasync function explainRefusedToken(url: string, token: string): Promise<never> {\n let tokenAccepted = false;\n try {\n const probe = await fetch(`${url}/api/auth/scopes`, {\n headers: { Authorization: `Bearer ${token}`, \"User-Agent\": cliUserAgent() }\n });\n tokenAccepted = probe.ok;\n } catch {\n // Unreachable: say what is certain — the request was refused.\n }\n if (tokenAccepted) {\n fail(\n `This command needs a signed-in session, and ${TOKEN_ENV} is an API token.`,\n `Unset ${TOKEN_ENV} and run ${chalk.bold(\"rebase cloud login\")} to run it.`,\n \"session_required\"\n );\n }\n fail(\n `${TOKEN_ENV} was rejected by ${url}: it has expired, been revoked, or was not issued by this control plane.`,\n `Create a new one with ${chalk.bold(\"rebase cloud tokens create\")} and put it in ${TOKEN_ENV}.`,\n \"token_rejected\"\n );\n}\n\n/** Two minutes of head-room before a token is treated as expired. */\nconst EXPIRY_BUFFER_MS = 120_000;\n\n/** The half of a client that holds its session — all {@link freshAccessToken} reads. */\nexport interface SessionHolder {\n auth: {\n getSession(): { accessToken: string; expiresAt: number } | null;\n refreshSession(): Promise<{ accessToken: string }>;\n };\n}\n\n/**\n * An access token with time left on it, refreshed first if it is close to\n * expiry. Rejects when there is no session, or it cannot be refreshed.\n *\n * For the requests the SDK does not make itself. Its own calls refresh and\n * retry on a 401; a raw `fetch` or a tunnel handshake presents whatever token\n * it was handed, and `createCloudClient` never refreshes in the background. A\n * token read once at the start of a command that runs for longer than it\n * lives — a deploy's build, a `db connect` left open — is refused by the time\n * it is used, so it is read here at the moment it is sent.\n *\n * A client built from `REBASE_TOKEN` has no session; its token is returned\n * as it is, since there is nothing to refresh it with.\n */\nexport async function freshAccessToken(client: SessionHolder): Promise<string> {\n const fixed = STATIC_TOKENS.get(client);\n if (fixed) return fixed;\n const session = client.auth.getSession();\n if (session?.accessToken && session.expiresAt > Date.now() + EXPIRY_BUFFER_MS) return session.accessToken;\n return (await client.auth.refreshSession()).accessToken;\n}\n\n/**\n * Return an authenticated client for the resolved host.\n *\n * With `REBASE_TOKEN` set, that token is the credential for every request and\n * the stored login is not consulted at all. Otherwise it is the `cloud login`\n * session — see {@link requireSessionClient}.\n */\nexport async function requireClient(rawArgs: string[]): Promise<{ client: CloudClient; url: string }> {\n const token = envToken();\n if (!token) return requireSessionClient(rawArgs);\n // Before anything else: everything downstream of here is a control-plane\n // call, and a direct-linked directory has no control plane to make it\n // against.\n refuseDirectLink(rawArgs);\n const url = resolveCloudUrl(rawArgs);\n return { client: createTokenClient(url, token), url };\n}\n\n/**\n * Return a client holding the `cloud login` session for the resolved host,\n * refreshing the access token if it is close to expiry, whether or not\n * `REBASE_TOKEN` is set. Exits with a helpful message when there is no usable\n * session (never logged in, or the refresh token was revoked).\n *\n * For the commands a token cannot run — minting and revoking tokens: a key that\n * could mint keys could mint its own successor, so the control plane refuses\n * every key on those routes.\n */\nexport async function requireSessionClient(rawArgs: string[]): Promise<{ client: CloudClient; url: string }> {\n // Before anything else: everything downstream of here is a control-plane\n // call, and a direct-linked directory has no control plane to make it\n // against.\n refuseDirectLink(rawArgs);\n const url = resolveCloudUrl(rawArgs);\n const client = createCloudClient(url);\n const session = client.auth.getSession();\n\n if (!session || !session.accessToken) {\n if (envToken()) {\n fail(\n `This command needs a signed-in session for ${chalk.cyan(url)}, and ${TOKEN_ENV} is an API token.`,\n `A token cannot manage tokens. Run ${chalk.bold(\"rebase cloud login\")} first.`,\n \"session_required\"\n );\n }\n fail(\n `Not logged in to ${chalk.cyan(url)}.`,\n `Run ${chalk.bold(\"rebase cloud login\")} first.`,\n \"not_logged_in\"\n );\n }\n\n if (session.expiresAt <= Date.now() + EXPIRY_BUFFER_MS) {\n try {\n await client.auth.refreshSession();\n } catch {\n fail(\n `Your session for ${chalk.cyan(url)} has expired.`,\n `Run ${chalk.bold(\"rebase cloud login\")} to sign in again.`,\n // Distinct from `not_logged_in`: a caller retrying on a stale\n // session should re-authenticate, not conclude it was never set\n // up. Same remedy, different diagnosis.\n \"session_expired\"\n );\n }\n }\n\n return { client,\nurl };\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Platform configuration\n ═══════════════════════════════════════════════════════════════ */\n\n/** One place a deploy can actually land, as the control plane describes it. */\nexport interface DeployTarget {\n clusterId?: string | null;\n provider: string;\n region?: string;\n label?: string;\n baseDomain?: string;\n}\n\nexport interface PlatformConfig {\n tenantBaseDomain?: string;\n deployTargets?: DeployTarget[];\n}\n\n/**\n * The control plane's public, non-secret self-description (`platform-config`).\n *\n * None of it is knowable from the CLI side: it is per-deployment configuration —\n * production serves tenants at `rebase.website` on GKE, a dev control plane at\n * `localhost` on Docker. Guessing produced two separate lies: a congratulation\n * URL that resolved nowhere near the app, and a `provider` the project does not\n * run on (see `createProject`).\n *\n * Cached per host for the process: it is fixed for a control plane's lifetime,\n * and `projects list` formats one host per row off a single fetch.\n *\n * @returns the config, or `undefined` if the control plane doesn't serve\n * `platform-config` (an older deployment) or the request failed. A failure is\n * cached too — a short-lived CLI should not retry once per row. Note the\n * distinction callers rely on: `undefined` means \"this control plane cannot\n * tell us\", whereas `deployTargets: []` is a control plane stating that it has\n * no infrastructure configured.\n */\nconst platformConfigCache = new Map<string, Promise<PlatformConfig | undefined>>();\n\nexport function fetchPlatformConfig(client: CloudClient, url: string): Promise<PlatformConfig | undefined> {\n let pending = platformConfigCache.get(url);\n if (!pending) {\n pending = client.functions\n .invoke<PlatformConfig>(\"platform-config\", undefined, { method: \"GET\" })\n .then((cfg) => cfg ?? undefined)\n .catch(() => undefined);\n platformConfigCache.set(url, pending);\n }\n return pending;\n}\n\n/**\n * The base domain tenant projects are served at, derived from the same\n * TENANT_BASE_DOMAIN the ingress and the console read (see\n * saas/backend/src/utils/tenant-domain.ts).\n */\nexport function fetchTenantBaseDomain(client: CloudClient, url: string): Promise<string | undefined> {\n return fetchPlatformConfig(client, url).then((cfg) => cfg?.tenantBaseDomain?.trim() || undefined);\n}\n\n/**\n * The infrastructure a deploy for this control plane would ACTUALLY use, in the\n * resolver's own preference order (saas/backend/src/k8s/resolve.ts).\n *\n * @returns the targets, or `undefined` when the control plane cannot say.\n */\nexport function fetchDeployTargets(client: CloudClient, url: string): Promise<DeployTarget[] | undefined> {\n return fetchPlatformConfig(client, url).then((cfg) =>\n Array.isArray(cfg?.deployTargets) ? cfg.deployTargets : undefined\n );\n}\n\n/**\n * Public host for a project — `<subdomain>.<base>`, or the bare subdomain when\n * the base domain is unknown.\n *\n * It deliberately never falls back to a guessed domain. The user copies this\n * string into a browser, so a plausible-but-wrong hostname is worse than an\n * obviously incomplete one: `acme.rebase.pro` looks reachable and isn't, while\n * `acme` reads as \"the subdomain is acme\" and prompts no wasted debugging.\n */\nexport function formatTenantHost(\n subdomain: string | undefined,\n baseDomain: string | undefined\n): string | undefined {\n if (!subdomain) return undefined;\n return baseDomain ? `${subdomain}.${baseDomain}` : subdomain;\n}\n\n/** The fields of a project row this module needs to render a host. */\nexport interface HostableProject {\n subdomain?: string;\n /** Resolved server-side; absent on control planes older than the host hook. */\n host?: string;\n}\n\n/**\n * The host to display for a project.\n *\n * Prefers `host` off the record: the control plane resolves it through the same\n * `tenantHost()` the ingress uses, so it accounts for the project's *cluster*\n * base domain. The CLI cannot compute that itself — `clusters` is admin-only\n * under RLS, so a normal user's token cannot read `baseDomain`, and a project on\n * a second cluster is served somewhere the platform default does not name.\n *\n * `baseDomain` (from `platform-config`) remains the fallback for a control plane\n * that predates the hook — right for the single-cluster case, which is every\n * project today.\n */\nexport function projectHost(\n project: HostableProject,\n baseDomain: string | undefined\n): string | undefined {\n return project.host || formatTenantHost(project.subdomain, baseDomain);\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Project link file (.rebase/cloud.json)\n ═══════════════════════════════════════════════════════════════ */\n\nexport interface ProjectLink {\n url: string;\n projectId: string;\n /** The project's subdomain — the slug users see in console URLs and type into --project. */\n slug?: string;\n projectName?: string;\n orgId?: string;\n /**\n * Base URL of the project's own API.\n *\n * For a cloud project this is a convenience derived from the subdomain. For\n * a **self-hosted** project it is the entire link: there is no control plane\n * to look anything up in, so `projectId` is empty and this is what commands\n * resolve against.\n *\n * Keeping both kinds of link in one file is deliberate. A second link file\n * for self-hosting would fork every command that reads one, and the tooling\n * would drift into being cloud-only by accident.\n */\n apiUrl?: string;\n /**\n * How this checkout is linked. Absent means `cloud` — which is every link\n * written before this field existed.\n */\n mode?: \"cloud\" | \"direct\";\n}\n\nexport function readLink(cwd: string = process.cwd()): ProjectLink | null {\n try {\n return JSON.parse(fs.readFileSync(projectLinkPath(cwd), \"utf-8\")) as ProjectLink;\n } catch {\n return null;\n }\n}\n\nexport function writeLink(link: ProjectLink, cwd: string = process.cwd()): void {\n const file = projectLinkPath(cwd);\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, JSON.stringify(link, null, 2));\n}\n\nexport function removeLink(cwd: string = process.cwd()): boolean {\n const file = projectLinkPath(cwd);\n if (fs.existsSync(file)) {\n fs.rmSync(file);\n return true;\n }\n return false;\n}\n\n/**\n * Flags that may appear anywhere on a `rebase cloud` line, including *before*\n * the resource group.\n *\n * They have to be declared wherever positionals are resolved, because `arg`'s\n * `permissive: true` does not merely tolerate an undeclared flag — it pushes it\n * into `_` alongside the positionals, and for a flag that takes a value it\n * pushes the value in too. So `cloud --project acme storage create` parsed\n * without this spec yields `_` of `[\"--project\", \"acme\", \"storage\", \"create\"]`,\n * and the group reads as `\"acme\"`: a real project name, in the group position,\n * dispatching to nothing. Skipping tokens that start with `-` does not save you\n * there — the damage is the orphaned value, which looks exactly like a\n * positional.\n *\n * Only genuinely global flags belong here. Group-specific ones (`--bucket`,\n * `--region`, …) are declared by the handler that owns them. They can still\n * precede the action — or stand in for it, on a group with a default — so the\n * dispatcher also declares every one that takes a value: `CLOUD_VALUE_FLAGS`\n * in `index.ts`.\n *\n * `-p` is `--project` in eighteen places and `--password` in `login`. That\n * ambiguity does not matter to the one caller that reads this spec: it resolves\n * positionals and never looks at a flag's value, so all it needs to know is\n * that `-p` takes one. Anything that wants the value must keep declaring it\n * itself, with the meaning its own command gives it.\n */\nexport const GLOBAL_CLOUD_FLAGS = {\n \"--json\": Boolean,\n \"--yes\": Boolean,\n \"--help\": Boolean,\n \"--project\": String,\n /* `resolveCloudUrl` reads this off the raw line for EVERY command in the\n family — it is the first entry in the URL priority list — so a strict\n parse that did not declare it would reject a flag the CLI itself honours\n on the command being parsed. */\n \"--url\": String,\n \"-p\": \"--project\",\n \"-y\": \"--yes\",\n \"-h\": \"--help\"\n} as const;\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * The raw project reference to operate on: explicit `--project` flag wins,\n * otherwise the linked project. Exits with guidance when neither is present.\n * The value is a slug (the project's subdomain, as shown in console URLs) or,\n * for old scripts and link files, a raw project UUID.\n */\nexport function requireProjectRef(rawArgs: string[]): string {\n const parsed = arg({ \"--project\": String,\n\"-p\": \"--project\" }, { argv: rawArgs.slice(2),\npermissive: true });\n if (parsed[\"--project\"]) return parsed[\"--project\"];\n const link = readLink();\n if (link?.projectId) return link.projectId;\n fail(\n \"No project specified and this directory is not linked.\",\n `Pass ${chalk.bold(\"--project <slug>\")} or run ${chalk.bold(\"rebase cloud link\")}.`,\n \"no_project\"\n );\n}\n\n/**\n * Resolve a project reference — slug or UUID — to the internal id the API\n * takes, or undefined when no such project is visible. Slugs cost one lookup;\n * UUIDs pass through untouched so linked directories and old scripts skip the\n * round-trip.\n */\nexport async function lookupProjectId(ref: string, client: CloudClient): Promise<string | undefined> {\n if (UUID_RE.test(ref)) return ref;\n const res = await client.data.collection(\"projects\").find({\n where: { subdomain: [\"==\", ref] },\n limit: 1\n });\n const row = res.data[0] as { id?: string | number } | undefined;\n return row?.id === undefined ? undefined : String(row.id);\n}\n\n/** Like `lookupProjectId`, but exits with guidance when the ref matches nothing. */\nexport async function resolveProjectRef(ref: string, client: CloudClient): Promise<string> {\n const id = await lookupProjectId(ref, client);\n if (id === undefined) {\n fail(\n `No project with slug ${chalk.bold(ref)}.`,\n `List yours with ${chalk.bold(\"rebase cloud projects\")}.`,\n \"project_not_found\"\n );\n }\n return id;\n}\n\n/** `requireProjectRef` + `resolveProjectRef` in one step. */\nexport async function requireProject(rawArgs: string[], client: CloudClient): Promise<string> {\n return resolveProjectRef(requireProjectRef(rawArgs), client);\n}\n\n/**\n * The project reference to SHOW: the slug the user typed or the linked slug.\n * Never resolves — for human output only. Old link files predate `slug` and\n * fall back to the stored id.\n */\nexport function displayProjectRef(rawArgs: string[]): string {\n const parsed = arg({ \"--project\": String,\n\"-p\": \"--project\" }, { argv: rawArgs.slice(2),\npermissive: true });\n if (parsed[\"--project\"]) return parsed[\"--project\"];\n const link = readLink();\n return link?.slug || link?.projectId || \"\";\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Machine-readable output mode\n ═══════════════════════════════════════════════════════════════\n\n Rebase is built for agents, and the CLI is their primary interface. An agent\n must never scrape a colorized table, so every cloud command can emit a single\n JSON value instead of human output.\n\n JSON mode is on when ANY of these hold:\n • `--json` was passed,\n • `REBASE_JSON=1` is set, or\n • stdout is not a TTY (piped/redirected — i.e. a program is reading it).\n\n In JSON mode a command prints exactly one JSON value to stdout and nothing\n else; errors print `{\"error\":{...}}` and exit non-zero. The mode is a\n process-global set once, at dispatch, by `initOutputMode` — every helper here\n (fail, reportError, emit) reads it so the whole family is consistent.\n\n ── The stream contract ─────────────────────────────────────────────────────\n\n The mode decides the SHAPE of the result. It does not decide which stream\n anything lands on; that rule is fixed and holds in both modes:\n\n stdout the command's result, and nothing else — one human rendering or\n one JSON value. A caller may redirect it into a parser.\n stderr everything that is not the result: progress, advice, warnings,\n errors, and the interactive prompts.\n\n Nothing is written to both. That is the whole rule, and it is worth stating\n because the family drifted off it in a way that reads as a bug in the report\n itself: a warning from the SDK went to stderr while the report went to\n stdout, so `whoami 2>&1` interleaved two unrelated voices and the header\n looked like it had been printed twice.\n\n The practical consequence for a new command: the ONLY things that may call\n `console.log` are inside an `emit` human closure. Progress and next-step\n advice go through `note`, cautions through `warn`, outcomes through\n `success` — all of which write to stderr. `keyValues` prints result rows and\n so stays on stdout, which is why it belongs inside the `emit` closure too.\n*/\n\nlet JSON_MODE = false;\n\n/**\n * Resolve and latch the output mode for this invocation. Call once at the top of\n * `cloudCommand`, before anything can print or `fail`. Returns the resolved mode\n * (handy for tests, which otherwise leave it at its `false` default).\n */\nexport function initOutputMode(rawArgs: string[]): boolean {\n const parsed = arg({ \"--json\": Boolean }, { argv: rawArgs.slice(2),\npermissive: true });\n // Most explicit wins. `REBASE_JSON=0` is the half that was missing: the\n // \"stdout is not a TTY\" rule is right for a result, and wrong for the reader\n // who ran `rebase cloud env --help | less` and got a JSON object. There was\n // no way to say so — `--json` could only turn the mode ON, and `REBASE_JSON`\n // was tested against \"1\" alone, so any other value including \"0\" fell\n // through to the TTY test and set it anyway. Any spelling of yes or no now\n // decides; only an unset or unrecognised value leaves it to the TTY.\n if (parsed[\"--json\"]) JSON_MODE = true;\n else JSON_MODE = parseEnvBoolean(process.env.REBASE_JSON) ?? process.stdout.isTTY !== true;\n return JSON_MODE;\n}\n\n/** Whether the current invocation is emitting machine-readable JSON. */\nexport function isJsonMode(): boolean {\n return JSON_MODE;\n}\n\n/** Force the mode (tests only — production latches it via `initOutputMode`). */\nexport function setJsonModeForTest(value: boolean): void {\n JSON_MODE = value;\n}\n\n/** Strip ANSI colour codes — JSON output must never carry terminal escapes. */\n// eslint-disable-next-line no-control-regex\nconst ANSI_RE = /\u001b\\[[0-9;]*m/g;\nfunction stripAnsi(s: string): string {\n return s.replace(ANSI_RE, \"\");\n}\n\n/**\n * Write one JSON value to stdout, followed by a newline.\n *\n * Indented, because the overwhelmingly common reader is a person or an agent\n * looking at a terminal — JSON mode is entered automatically whenever stdout is\n * not a TTY, so `rebase cloud deployments list` piped anywhere at all produced\n * a project's entire deployment history as one unwrapped line. `JSON.parse`\n * does not care about the whitespace; everything else does.\n */\nexport function printJson(value: unknown): void {\n process.stdout.write(JSON.stringify(value, null, 2) + \"\\n\");\n}\n\n/**\n * The one output primitive every new command uses: in JSON mode emit `json`\n * (and nothing else); otherwise run `human`. Keeping the two behind a single\n * call is what guarantees a command can never print a table AND a JSON blob.\n */\nexport function emit<T>(human: () => void, json: JsonArg<T>): void {\n if (JSON_MODE) printJson(json);\n else human();\n}\n\n/**\n * The JSON payload, which must be a value and not a producer of one.\n *\n * `json: unknown` accepted a function without complaint, and four call sites in\n * `resources.ts` passed `() => ({ … })` — mirroring the human argument beside\n * it, which *is* a thunk. In JSON mode `printJson` then stringified a function,\n * which is `undefined`. So `rebase cloud compute`, `compute set` and two\n * cluster commands printed the single word `undefined` on every piped or\n * `--json` run — and since this family forces JSON mode off a TTY, that is\n * every scripted use of them.\n *\n * Typed so the mistake cannot be made again: a function resolves the parameter\n * to `never`, and the call site fails to compile.\n */\nexport type JsonArg<T> = T extends (...args: never[]) => unknown ? never : T;\n\n/**\n * Print a help page — the human one, or a machine-readable description of the\n * same command in JSON mode.\n *\n * `--help` is the one place where \"stdout is not a TTY\" is a weak signal: a\n * person runs `rebase cloud db --help | less` and wants the page. But the rule\n * this family promises is that stdout carries one JSON value whenever it is not\n * a terminal, and a help page is the easiest possible thing to describe\n * structurally — so rather than carve out an exception, help answers the same\n * question in the reader's own language. For an agent, `--help` piped is then a\n * discovery call rather than 60 lines of ANSI to scrape.\n *\n * `env` shipped this shape first, alone; this generalises it so every group\n * answers the same way.\n */\nexport function emitHelp(\n command: string,\n actions: Array<string | HelpAction>,\n human: () => void,\n extra: Record<string, unknown> = {}\n): void {\n emit(human, { command,\nactions: actions.map(entry => describeAction(entry, command)),\n...extra });\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Group help pages\n ═══════════════════════════════════════════════════════════════ */\n\n/**\n * One action on a group's help page.\n *\n * The page used to exist twice: a hand-formatted template literal for a\n * terminal, and a bare list of action WORDS for everything else. So the two\n * answers to `--help` were not the same answer — piped, `rebase cloud env\n * --help` said `[\"list\",\"set\",\"unset\",\"reveal\",\"pull\"]` and not one description,\n * not one flag, and not the sentence about build-time variables that is the\n * whole reason the page exists. This family forces JSON mode off a TTY, so that\n * was every scripted and every agent-driven read of it.\n *\n * One description, rendered twice.\n */\nexport interface HelpAction {\n /** The action word: `set`, `backup restore`. */\n action: string;\n /** The usage tail after the word: `KEY=VALUE`, `<domain>`, `[-y]`. */\n args?: string;\n /** One line: what it does. */\n description: string;\n /** Flags this action takes of its own, `[flag, description]`. */\n flags?: Array<[string, string]>;\n /** The heading it sits under, on a page that groups its actions. */\n section?: string;\n}\n\n/** A whole group page — `rebase cloud env --help`. */\nexport interface GroupHelp {\n /** The command words, no leading `rebase`: `cloud env`, or `cloud` itself. */\n command: string;\n /** The title's tail: \"Environment variables\". */\n title: string;\n actions: HelpAction[];\n /** Options that belong to the group rather than to one action. */\n options?: Array<[string, string]>;\n /** Closing paragraphs — the things a reader gets wrong more than once. */\n notes?: string[];\n}\n\n/**\n * Normalise an action for the JSON form. Strings stay legal — the index page\n * lists group names, which are not actions of the command being described.\n *\n * `command` is the page's own command (`cloud env`), so the usage line a caller\n * reads is a line it can run: without it the answer said `rebase cloud set\n * KEY=VALUE`, which is a command that does not exist.\n */\nfunction describeAction(entry: string | HelpAction, command: string): Record<string, unknown> {\n if (typeof entry === \"string\") return { action: entry,\ndescription: \"\",\nflags: [] };\n return {\n action: entry.action,\n usage: `rebase ${command} ${entry.action}${entry.args ? ` ${entry.args}` : \"\"}`,\n description: entry.description,\n flags: (entry.flags ?? []).map(([flag, description]) => ({ flag,\ndescription }))\n };\n}\n\n/**\n * Flags every cloud command accepts, documented once.\n *\n * Lives here rather than in `action-help.ts` because both help renderers print\n * it and `action-help` imports this module, not the other way round.\n */\nexport const GLOBAL_HELP_FLAGS: Array<[string, string]> = [\n [\"--project, -p <slug>\", \"Operate on a project without linking this directory\"],\n [\"--json\", \"Machine-readable output (also when piped, or REBASE_JSON=1)\"],\n [\"--url <origin>\", \"Target a specific control plane (or REBASE_CLOUD_URL)\"],\n [\"--yes, -y\", \"Skip confirmation prompts\"],\n [\"--debug\", \"Print the untouched error body after a failure\"]\n];\n\n/**\n * Flag names `parseCloudArgs` adds to every command in the family.\n *\n * Derived from `GLOBAL_CLOUD_FLAGS` rather than listed again — a second copy is\n * how a global gains a spelling that the collision sweep does not know about.\n * `--debug` is the one addition: `bin/rebase.js` takes it off `process.argv`\n * itself, so no cloud spec declares it and every command still accepts it.\n */\nexport const GLOBAL_SPEC_KEYS = new Set([...Object.keys(GLOBAL_CLOUD_FLAGS), \"--debug\"]);\n\n/** Column width for an action word (+ its args) before its description. */\nconst HELP_COLUMN = 28;\n\n/**\n * The gap after `text` in a `width`-wide column, never less than one space.\n *\n * `padEnd` returns the string unchanged when it is already at the width, which\n * glues the description onto the flag: `--connection-string <url>The external…`.\n */\nfunction pad(text: string, width: number): string {\n return \" \".repeat(Math.max(1, width - text.length));\n}\n\n/**\n * Print a group's page — the human one, and the same content as JSON when piped.\n */\nexport function printGroupHelp(page: GroupHelp): void {\n emitHelp(\n page.command,\n page.actions,\n () => {\n console.log(\"\");\n console.log(`${chalk.bold(`rebase ${page.command}`)} — ${page.title}`);\n console.log(\"\");\n console.log(chalk.green.bold(\"Usage\"));\n console.log(` rebase ${page.command} ${chalk.blue(\"<action>\")} [options]`);\n\n let section: string | undefined;\n for (const entry of page.actions) {\n const heading = entry.section ?? \"Commands\";\n if (heading !== section) {\n section = heading;\n console.log(\"\");\n console.log(chalk.green.bold(heading));\n }\n const word = `${entry.action}${entry.args ? ` ${entry.args}` : \"\"}`;\n console.log(\n ` ${chalk.blue.bold(entry.action)}${entry.args ? ` ${chalk.gray(entry.args)}` : \"\"}`\n + `${pad(word, HELP_COLUMN)}${entry.description}`\n );\n for (const [flag, description] of entry.flags ?? []) {\n console.log(` ${chalk.blue(flag)}${pad(flag, HELP_COLUMN - 4)}${chalk.gray(description)}`);\n }\n }\n\n if (page.options?.length) {\n console.log(\"\");\n console.log(chalk.green.bold(\"Options\"));\n for (const [flag, description] of page.options) {\n console.log(` ${chalk.blue(flag)}${pad(flag, HELP_COLUMN)}${description}`);\n }\n }\n\n console.log(\"\");\n console.log(chalk.green.bold(\"Global options\"));\n for (const [flag, description] of GLOBAL_HELP_FLAGS) {\n console.log(` ${chalk.blue(flag)}${pad(flag, HELP_COLUMN)}${chalk.gray(description)}`);\n }\n\n if (page.notes?.length) {\n console.log(\"\");\n for (const note of page.notes) console.log(chalk.gray(` ${note}`));\n }\n console.log(\"\");\n },\n {\n usage: `rebase ${page.command} <action> [options]`,\n summary: page.title,\n options: (page.options ?? []).map(([flag, description]) => ({ flag,\ndescription })),\n globalFlags: GLOBAL_HELP_FLAGS.map(([flag, description]) => ({ flag,\ndescription })),\n notes: page.notes ?? []\n }\n );\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Output helpers\n ═══════════════════════════════════════════════════════════════ */\n\n/**\n * Print a warning (+ optional hint) — in every output mode, always to stderr.\n *\n * `emit` is for a command's *result*, and JSON mode legitimately replaces the\n * human rendering of one. A warning is not a result: it says the command is\n * about to do something the caller may not have meant, and that is exactly as\n * true when the output is piped. Gating one on `!isJsonMode()` deleted it\n * precisely where nobody was watching the terminal — a `--source` deploy ejected\n * a live project off the managed runtime and said so only to a TTY that wasn't\n * there.\n *\n * stdout carries the JSON value and nothing else, so warnings go to stderr:\n * a machine parser reading stdout cannot be corrupted by one. Only the\n * *formatting* may depend on the mode — colour and indentation for a terminal,\n * plain ASCII otherwise. Whether a warning is emitted at all may not.\n *\n * Anything a caller might branch on belongs in the JSON payload as well; stderr\n * is for whoever reads the transcript afterwards.\n */\nexport function warn(message: string, hint?: string): void {\n if (JSON_MODE) {\n process.stderr.write(`warning: ${stripAnsi(message)}\\n`);\n if (hint) process.stderr.write(` ${stripAnsi(hint)}\\n`);\n return;\n }\n console.error(\"\");\n console.error(chalk.yellow(` ⚠ ${message}`));\n if (hint) console.error(chalk.gray(` ${hint}`));\n}\n\n/**\n * Print an error (+ optional hint) and exit non-zero. Never returns.\n *\n * `code` is the field a caller branches on, and it defaults to `\"error\"` rather\n * than `null`. An envelope whose only machine-readable field is null is not\n * machine-readable — `{\"error\":{\"message\":\"No project specified…\",\"code\":null}}`\n * forced the very substring-matching on `message` that the envelope exists to\n * make unnecessary, and `message` is the field most likely to be reworded.\n *\n * `\"error\"` is deliberately a poor code: it says \"this refusal has not been\n * classified yet\" without ever being absent. Anything a caller might plausibly\n * want to distinguish — `usage`, `not_found`, `unauthenticated` — passes a real\n * one. Codes are part of the CLI's contract once shipped; see\n * `cloud-reporting.test.ts`, which pins the ones commands are documented to\n * return.\n */\nexport function fail(message: string, hint?: string, code?: string): never {\n if (JSON_MODE) {\n printJson({ error: { message: stripAnsi(message),\ncode: code ?? \"error\",\nhint: hint ? stripAnsi(hint) : undefined } });\n process.exit(1);\n }\n console.error(\"\");\n console.error(chalk.red(` ✗ ${message}`));\n if (hint) console.error(chalk.gray(` ${hint}`));\n console.error(\"\");\n process.exit(1);\n}\n\n/**\n * Confirm a destructive/irreversible action, respecting non-interactive use.\n *\n * With `--yes`/`-y` it proceeds silently. In JSON mode or a non-TTY it REFUSES\n * to prompt — a prompt that can hang is a known repo landmine — and fails,\n * telling the caller to pass `--yes`. Only an interactive terminal gets a real\n * confirm prompt; declining there aborts cleanly (exit 0).\n */\nexport async function confirmDestructive(opts: { yes: boolean; prompt: string }): Promise<void> {\n if (opts.yes) return;\n if (JSON_MODE || process.stdin.isTTY !== true) {\n fail(\n \"This action is destructive and needs confirmation.\",\n `Re-run with ${chalk.bold(\"--yes\")} to proceed.`,\n \"confirmation_required\"\n );\n }\n const { confirmed } = (await inquirer.prompt([\n { type: \"confirm\",\nname: \"confirmed\",\ndefault: false,\nmessage: opts.prompt }\n ] as Parameters<typeof inquirer.prompt>[0])) as { confirmed: boolean };\n if (!confirmed) {\n // stderr: declining is not a result. Unreachable in JSON mode — the\n // guard above already refused rather than prompt — so stdout stays\n // empty and the exit code carries the outcome.\n console.error(chalk.gray(\" Aborted.\"));\n process.exit(0);\n }\n}\n\n/**\n * Refuse, rather than prompt, when there is nobody to answer.\n *\n * `confirmDestructive` has always done this for yes/no confirmations. The\n * *value* prompts had no such guard: `cloud login`, `cloud link`, `cloud use`,\n * `cloud orgs create` and `cloud db create` all called `inquirer.prompt`\n * unconditionally, so piping any of them — which is how an agent runs every\n * command in this family — parked the process on a prompt reading from a stdin\n * that was never going to produce a line. A hang is the worst failure mode\n * available here: no output, no exit code, nothing to retry on.\n *\n * @param what what the prompt would have asked for, e.g. \"an email and password\"\n * @param flags the flags that supply it non-interactively\n */\nexport function requireInteractive(what: string, flags: string): void {\n if (JSON_MODE || process.stdin.isTTY !== true) {\n fail(\n `This command needs ${what}, and there is no terminal to ask on.`,\n `Pass ${chalk.bold(flags)}.`,\n \"input_required\"\n );\n }\n}\n\n/**\n * Resolve one cloud command's flags and ARGUMENTS from the full `process.argv`.\n *\n * This replaces `cloudPositionals`, which was `rawArgs.slice(3).filter(a =>\n * !a.startsWith(\"-\"))`. Dropping `-`-prefixed tokens looks like it solves the\n * permissive-parse problem and does not: a flag that takes a VALUE leaves the\n * value behind, an ordinary word in the argument position that no filter can\n * tell from a real one. `--project` is the flag every one of these commands\n * documents, so the failure was reachable from the help page:\n *\n * rebase cloud env unset -p acme → removed the variable \"acme\"\n * rebase cloud env set KEY -p acme → stored the value \"acme\"\n * rebase cloud domains add -p acme → registered the domain \"acme\"\n * rebase cloud webhooks delete -p acme 42 → deleted webhook \"acme\", not 42\n * rebase cloud cancel -p acme → cancelled deployment id \"acme\"\n *\n * The filter's other half is quieter. A flag nobody declared *is* dropped by\n * it — but only from the operands, never from the run: nothing rejects it, so\n * the command proceeds with the argument missing or defaulted. `db backup\n * --dry-run` listed backups, `domains remove --dry-run` detached the domain,\n * and `env set KEY=v --secrett` stored the value as an ordinary variable that\n * `env reveal` will hand back. The one place an undeclared flag became the\n * argument outright is `projects info|delete`, which resolved its id through\n * `positionals()` instead — that skips only LEADING `-` tokens, so `projects\n * delete --force` looked up a project named \"--force\".\n *\n * So: parse the whole line strictly, through the same `parseCommandArgs` the\n * non-cloud commands use — `arg` then consumes each declared flag *with its\n * value* wherever it appears, and rejects the undeclared, leaving `_` holding\n * the command words followed by the real arguments. `commandWords` counts from\n * `cloud` itself (`cloud env set` ⇒ 3), and is applied to the parsed\n * positionals, so a flag written before the group shifts nothing.\n *\n * Two things this adds over calling `parseCommandArgs` directly, and the reason\n * it is worth a wrapper:\n *\n * - `GLOBAL_CLOUD_FLAGS` is merged in. `--json`, `--yes` and `--project` may\n * appear anywhere on a cloud line including before the group, so a strict\n * parse that did not declare them would reject the CLI's own documented\n * usage. (`parseCommandArgs` adds `--debug`/`--help` on top of that.)\n * - A parse error is reported through `fail`, not thrown. A throw reaches\n * `bin/rebase.js`, which prints `✗ …` to stderr — which is right for every\n * other command and wrong here: `rebase cloud` is in JSON mode whenever\n * stdout is not a TTY, i.e. always for the agents this family is built for,\n * and it promises them exactly one JSON value. `fail` keeps that promise,\n * with the same `usage` code the other refusals in this family use.\n */\nexport function parseCloudArgs<S extends arg.Spec>(opts: {\n spec: S;\n rawArgs: string[];\n commandWords: number;\n /** Names the command in errors, e.g. `cloud env set` (no leading `rebase`). */\n command: string;\n maxPositionals?: number;\n}): { flags: arg.Result<S & typeof GLOBAL_CLOUD_FLAGS>; positionals: string[] } {\n const spec = { ...GLOBAL_CLOUD_FLAGS,\n...opts.spec };\n try {\n const parsed = parseCommandArgs({ ...opts,\nspec });\n return { flags: parsed.flags,\npositionals: parsed.positionals };\n } catch (err) {\n fail(err instanceof Error ? err.message : String(err), undefined, \"usage\");\n }\n}\n\n/**\n * Refuse an action word its group does not dispatch. Returns for `undefined`,\n * which is every group's default action.\n *\n * The groups that switch on their action already do this in a `default:` case.\n * The groups written as a chain of `if (action === \"x\") return …` did not: a\n * word that matched nothing fell out of the chain into the *default* action, so\n * `rebase cloud storage creat` listed the buckets and exited 0, and\n * `rebase cloud billing usage` printed the account. Reporting a typo as a\n * successful run of a different command is the failure mode this family exists\n * to not have — an agent branching on the exit code learns nothing, and a person\n * reads the output of a command they did not ask for.\n *\n * One spelling, so the code is `unknown_command` everywhere rather than the\n * default `\"error\"` half of them used, and the hint always names the group's own\n * `--help` rather than the index page.\n */\nexport function requireKnownAction(\n group: string,\n action: string | undefined,\n known: readonly string[]\n): void {\n if (action === undefined || known.includes(action)) return;\n fail(\n `Unknown ${group} command: ${action}`,\n `Run \\`rebase cloud ${group} --help\\`. Actions: ${known.join(\", \")}.`,\n \"unknown_command\"\n );\n}\n\n/**\n * `--timeout <seconds>` as milliseconds, or `fallbackMs` when it was not given.\n *\n * One function rather than one per command, because two commands take this flag\n * and a second copy is where the two would come to disagree about what\n * `--timeout 0` means.\n *\n * A value this cannot read is a refusal, not a fall back to the default. The\n * whole reason a caller passes a timeout is that it has a deadline of its own;\n * quietly substituting a different one is how a fifteen-minute wait turns up\n * inside a five-minute CI step, having been asked for `--timeout 30s`.\n */\nexport function resolveTimeoutMs(\n value: string | undefined,\n opts: { fallbackMs: number; command: string }\n): number {\n if (value === undefined) return opts.fallbackMs;\n const seconds = Number(value);\n if (!Number.isFinite(seconds) || seconds <= 0) {\n fail(\n `--timeout takes a number of seconds (got \"${value}\").`,\n `Run \\`rebase ${opts.command} --help\\`.`,\n \"usage\"\n );\n }\n return seconds * 1000;\n}\n\n/**\n * Announce an outcome — \"Logged in as …\", \"Deleted project …\".\n *\n * On **stderr**, in both modes. It reads like a result and is not one: the\n * result is the JSON value (or the table) on stdout, and every JSON payload in\n * this family already carries `success: true`. Leaving this on stdout meant a\n * successful `rebase cloud link | jq` was handed a green tick followed by an\n * object — one stream, two syntaxes, and only the second parseable.\n *\n * It stays visible in JSON mode, unlike `note`: an agent that got a `success`\n * line on a command it expected to refuse has learned something.\n */\nexport function success(message: string): void {\n if (JSON_MODE) {\n process.stderr.write(`${stripAnsi(message)}\\n`);\n return;\n }\n console.error(\"\");\n console.error(chalk.bold.green(` ✓ ${message}`));\n console.error(\"\");\n}\n\n/**\n * Narrate progress, or point at the next step — \"Signing in to …\", \"Redeploy\n * for the tenant to pick this up\".\n *\n * stderr, and **suppressed entirely in JSON mode**. This is the one helper that\n * a mode may silence, and the distinction from `warn` is worth keeping sharp:\n *\n * - A warning is a *condition*. It is as true when piped as when watched, so\n * silencing it hides something the caller would want to know. `warn` never\n * silences.\n * - A note is *hand-holding*. \"Next: run `rebase generate-sdk`\" tells a person\n * what to type; the agent reading the JSON already has the same information\n * structurally, or does not need it. Printing it anyway is transcript noise.\n *\n * When in doubt it is a warning. The cost of a needless warning is a line; the\n * cost of a swallowed one is the deploy that ejected a project off the managed\n * runtime and said so only to a terminal nobody was looking at.\n */\nexport function note(message: string, indent = \" \"): void {\n if (JSON_MODE) return;\n console.error(`${indent}${message}`);\n}\n\n/** A blank spacer line on the narration stream. No-op in JSON mode. */\nexport function noteBlank(): void {\n if (JSON_MODE) return;\n console.error(\"\");\n}\n\n/** Colorize a deployment / resource status token. */\nexport function colorStatus(status: string | undefined): string {\n switch (status) {\n case \"active\":\n case \"success\":\n case \"connected\":\n return chalk.green(status);\n case \"deploying\":\n case \"provisioning\":\n case \"pending_billing\":\n case \"untested\":\n return chalk.yellow(status ?? \"\");\n case \"failed\":\n return chalk.red(status);\n case \"stopped\":\n return chalk.gray(status);\n default:\n return chalk.gray(status ?? \"unknown\");\n }\n}\n\n/**\n * Render a two-column key/value block with aligned keys. Empty rows are skipped\n * — including `null`, which the API sends for an unset column and which used to\n * print the literal string \"null\" (e.g. `Custom domain: null`).\n */\nexport function keyValues(rows: Array<[string, string | null | undefined]>): void {\n const width = Math.max(...rows.map(([k]) => k.length));\n for (const [k, v] of rows) {\n if (v === undefined || v === null || v === \"\") continue;\n console.log(` ${chalk.gray(`${k}:`.padEnd(width + 1))} ${v}`);\n }\n}\n\n/**\n * Surface an SDK/HTTP error consistently. The SDK throws RebaseApiError with\n * a `.status` and `.message`; anything else falls back to its string form.\n *\n * The message is summarised rather than printed — see `summarizeError`. What\n * arrives here is routinely a whole Kubernetes `Status` object with the request\n * headers appended, and the one sentence worth reading is inside it. The\n * untouched body is still available, behind `--debug`, on stderr where it\n * cannot corrupt the JSON value on stdout.\n */\nexport function reportError(e: unknown, context: string): never {\n const err = e as { status?: number; message?: string; code?: string };\n const summary = summarizeError(e, context);\n\n if (wantsRawError()) {\n process.stderr.write(`\\n${summary.raw}\\n\\n`);\n }\n\n if (JSON_MODE) {\n printJson({\n error: {\n message: stripAnsi(summary.message),\n // The SDK supplies a code for errors the API classified. When it\n // does not, the HTTP status still classifies it well enough to\n // branch on — `http_401` and `http_502` want very different\n // handling, and both used to arrive as `null`. A cluster\n // refusal classifies itself, and `platform` below says whether\n // acting on it is even the caller's business.\n code: summary.code,\n status: err?.status ?? null,\n hint: summary.hint ? stripAnsi(summary.hint) : undefined,\n platform: summary.platform,\n context\n }\n });\n process.exit(1);\n }\n fail(summary.message, summary.hint, summary.code);\n}\n\n/**\n * Open a URL in the user's default browser (best effort). Always announces the\n * URL first so it stays usable over SSH or when no browser is available.\n *\n * The announcement is narration, not the result — it goes to stderr, and in\n * JSON mode it is silent. Every caller `emit`s the same URL in its payload, so\n * a machine reader gets it from the one place it is guaranteed to be parseable\n * rather than from a line that happens to end in a URL.\n */\nexport function openUrl(target: string, label = \"Opening\"): void {\n noteBlank();\n note(`${label} ${chalk.cyan(target)}`);\n noteBlank();\n const opener =\n process.platform === \"darwin\" ? \"open\" : process.platform === \"win32\" ? \"start\" : \"xdg-open\";\n try {\n const child = spawn(opener, [target], {\n stdio: \"ignore\",\n detached: true,\n shell: process.platform === \"win32\"\n });\n child.on(\"error\", () => {\n /* URL already printed for manual copy */\n });\n child.unref();\n } catch {\n /* URL already printed */\n }\n}\n\n/**\n * The one thing every control-plane row is required to have.\n *\n * The subcommands each declare their own row shape — `OrgRow`, `ProjectRow`,\n * `DatabaseRow`, `DeploymentRow` — and every one of them is an `id` plus\n * fields that are all optional, because a control plane older than a given\n * column simply does not send it. The reads are written that way too\n * (`o.name ?? \"(unnamed)\"`, `row.slug ? … : \"\"`).\n */\nexport interface CloudRow {\n id: string | number;\n}\n\n/**\n * Read the control plane's rows as a subcommand's row shape.\n *\n * `client.data.collection(...)` is typed against the *generated* schema of the\n * project the SDK is pointed at, and the control-plane collections this CLI\n * reads are not in one — so every row arrives as an open\n * `Record<string, unknown>`. A declared `interface` gets no implicit index\n * signature, so it does not overlap that, and a direct `as` is refused: which\n * is how ten call sites came to write `as unknown as XRow[]`, an assertion\n * about a wire payload with nothing checking it in either direction.\n *\n * There is exactly one invariant to check and this checks it. Everything else\n * the shapes declare is optional and already read as such, so there is nothing\n * further to verify — but a row with no usable `id` is not a row any of these\n * commands can act on, and passing it through was how a listing came to print\n * `[undefined]` and a lookup came to compare against the string `\"undefined\"`.\n */\nexport function cloudRows<T extends CloudRow>(rows: readonly Record<string, unknown>[] | undefined): T[] {\n return (rows ?? []).filter((row): row is Record<string, unknown> & T =>\n typeof row?.id === \"string\" || typeof row?.id === \"number\");\n}\n\n/** {@link cloudRows} for an endpoint that returns a single row. */\nexport function cloudRow<T extends CloudRow>(row: Record<string, unknown> | undefined): T | undefined {\n return cloudRows<T>(row ? [row] : [])[0];\n}\n\n/**\n * {@link cloudRows} for a write that must have produced a row.\n *\n * `create()` returning something with no usable `id` means the control plane\n * accepted the write and then described it in a way this CLI cannot act on.\n * The callers all go straight on to use that id — `setContextOrg(url,\n * String(created.id))` — so asserting the shape, which is what stood here,\n * turned a control-plane fault into an organization whose active id is the\n * seven-letter string `\"undefined\"`, stored in the user's config file.\n */\nexport function requireCloudRow<T extends CloudRow>(\n row: Record<string, unknown> | undefined,\n what: string\n): T {\n const parsed = cloudRow<T>(row);\n if (!parsed) throw new Error(`The control plane accepted the ${what} but returned no id for it.`);\n return parsed;\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"db-9P6MnmdC.js","names":[],"sources":["../src/utils/command-words.ts","../src/utils/spawn-error.ts","../src/commands/db.ts"],"sourcesContent":["/**\n * The words that name a command, with the flags taken back out.\n *\n * `rawArgs` is the whole of `process.argv`, and reading the command's words at\n * fixed indices off it assumes nothing precedes them. Something routinely does:\n * `--debug` is what `bin/rebase.js` prints after every failure as the thing to\n * re-run with, so it is the single most likely token to appear before a command\n * word, and it shifted every index by one.\n *\n * What that cost is not a bad error message. `rebase db branch switch feature`\n * writes a per-checkout pointer that the CLI owns; the driver, running as a\n * child process, cannot persist it and does not try. The dispatch found\n * `switch` by position, so `rebase --debug db branch switch feature` missed the\n * CLI's branch and handed the line to the driver — which reported success and\n * left the checkout on the main database. Every subsequent `dev`, `push` and\n * `backup` then ran against the wrong database, believing it was the branch,\n * which is the exact failure branching exists to prevent.\n *\n * The words are anchored on the command name rather than taken from position\n * zero, because a flag written in the space form (`--database-url <url>`) leaves\n * its value behind as a bare token and no parser at this level knows which\n * flags take values. Anchoring survives that: the value would have to be the\n * literal command name to fool it.\n *\n * Returns `[]` when the command name is not on the line at all.\n */\nexport function commandWords(rawArgs: readonly string[], command: string): string[] {\n const words = rawArgs.slice(2).filter(token => !token.startsWith(\"-\"));\n const start = words.indexOf(command);\n return start === -1 ? [] : words.slice(start);\n}\n\n/**\n * The line to hand a spawned driver, starting at the command word.\n *\n * The same defect one layer down, and it does not degrade gracefully: the\n * driver reads its domain from `args[0]`, so `rebase --debug db push` spawned\n * it with `[\"--debug\", \"db\", \"push\"]` and it answered \"Unknown domain command:\n * --debug\" — for a flag the CLI itself tells you to add after any failure.\n *\n * Tokens written *before* the command word are moved after it rather than\n * dropped. Dropping them would be the same class of bug in the other direction:\n * `rebase --database-url postgres://… db push` would silently lose the flag that\n * says which database to touch. Appending keeps each flag next to its value, and\n * `arg` reads flags wherever they appear.\n *\n * Falls back to `rawArgs.slice(2)` when the command word is not on the line,\n * which is what an internally synthesised argv looks like.\n */\nexport function argsFromCommand(rawArgs: readonly string[], command: string): string[] {\n const tail = rawArgs.slice(2);\n const start = tail.findIndex(token => token === command);\n if (start <= 0) return [...tail];\n return [...tail.slice(start), ...tail.slice(0, start)];\n}\n","/**\n * What to say when a spawned child process fails.\n *\n * Two failures arrive through the same `catch` and need opposite treatment:\n *\n * - **The child ran and exited non-zero.** It had inherited stdio, so it has\n * already printed its own diagnostics. execa's \"Command failed with exit\n * code 1: …\" is a second, worse copy of the same news with the whole argv\n * appended.\n * - **The child never started.** ENOENT on the tsx binary, EACCES on a script\n * that lost its permissions, ENOMEM on a full machine. Nobody printed\n * anything, because nothing ran. `schema.ts` and `doctor.ts` both swallowed\n * these — `catch { process.exit(1); }`, the error not even bound — so\n * `rebase schema generate` against a broken tsx exited 1 in silence, and so\n * did `rebase doctor`, the command whose entire job is to say what is wrong.\n *\n * The tsx symlink surviving a cleaned pnpm store is the ordinary way to get\n * here: `resolveLocalBin` finds the symlink, so \"dependencies are not\n * installed\" never fires, and the spawn is where it breaks.\n *\n * ## Why the message is not what decides it\n *\n * `db.ts` did make this distinction, by testing the message against\n * `/Command failed|exited with code/i` — and that test is wrong for every case\n * it was written to catch. execa prefixes **all** of them the same way:\n *\n * Command failed with exit code 3: /bin/sh -c 'exit 3'\n * Command failed with ENOENT: /…/tsx x⏎spawn /…/tsx ENOENT\n * Command failed with EACCES: /…/tsx x⏎spawn /…/tsx EACCES\n *\n * So the filter matched the spawn failures too and `db push` was as silent as\n * the other two. The structured fields do distinguish them: a child that ran\n * has a numeric `exitCode` (or a `signal`, if something killed it), and a child\n * that never started has neither — only an errno in `code`.\n */\nimport chalk from \"chalk\";\n\ninterface ChildProcessFailure {\n exitCode?: unknown;\n signal?: unknown;\n /** execa's message without the \"Command failed with …: <argv>\" preamble. */\n originalMessage?: unknown;\n}\n\n/** Did the process start? Only then has anything else already been printed. */\nfunction childRan(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n const failure = error as Error & ChildProcessFailure;\n return typeof failure.exitCode === \"number\" || typeof failure.signal === \"string\";\n}\n\nexport function reportSpawnFailure(error: unknown): void {\n if (childRan(error) || !(error instanceof Error)) return;\n\n // `originalMessage` is \"spawn /…/tsx ENOENT\" — the same fact as `message`\n // without a second copy of the argv the user just typed. Absent on the\n // errors these commands raise themselves, which are already one sentence.\n const failure = error as Error & ChildProcessFailure;\n const message = typeof failure.originalMessage === \"string\"\n ? failure.originalMessage\n : error.message;\n if (message) console.error(chalk.red(`✗ ${message}`));\n}\n","/**\n * CLI command: rebase db <action>\n */\nimport type arg from \"arg\";\nimport chalk from \"chalk\";\nimport fs from \"fs\";\nimport inquirer from \"inquirer\";\nimport os from \"os\";\nimport path from \"path\";\nimport { execa } from \"execa\";\nimport {\n requireProjectRoot,\n requireBackendDir,\n getActiveBackendPlugin,\n resolvePluginCliScript,\n resolveTsx,\n resolveTsxLoader,\n findEnvFile,\n dependenciesNotInstalled\n} from \"../utils/project\";\nimport { reportSpawnFailure } from \"../utils/spawn-error\";\nimport { parseCommandArgs, resolveSwitchValues, switchOn, UsageError } from \"../utils/args\";\nimport { redactConnectionPasswords } from \"../utils/redact\";\nimport { suggestCommand, unknownCommand } from \"../utils/unknown-command\";\nimport { argsFromCommand, commandWords } from \"../utils/command-words\";\nimport { COLLECTIONS_FLAG_HELP, refuseMissingCollectionsPath } from \"../utils/path-flags\";\nimport { recordEvent } from \"../telemetry\";\nimport { DEV_DATABASE_KIND_ENV, devDatabaseKind, type PreparedDatabase } from \"../dev-db/prepare\";\nimport { type DevDatabase } from \"../dev-db/resolve\";\nimport type { AtlasDevDatabase } from \"../dev-db/atlas-dev-database\";\n\n/**\n * The connection string a prepared database actually answers on.\n *\n * One function, because `db url` and `db pull` disagreed about it and the\n * disagreement was a dead command: `prepareDatabaseEnv` returns `env: {}` for a\n * plain external database — the connection string is already somewhere the\n * child looks — so `db pull`'s `prepared.env.DATABASE_URL ?? process.env\n * .DATABASE_URL` was empty for the standard `.env` configuration and answered\n * `✗ No local database to pull into.` on a project whose `rebase db url` had\n * just printed one. Exporting the same URL in the shell made it work, which is\n * the shape of a bug nobody reports as one.\n *\n * `readEnvFile` is passed in rather than imported: this module loads\n * `../utils/project` dynamically everywhere else, and the callers already have\n * it open.\n */\nexport function databaseUrlOf(\n prepared: Pick<PreparedDatabase, \"env\" | \"database\">,\n envFile: Record<string, string>\n): string | undefined {\n // An empty string is \"nothing named a database\", not \"the database is the\n // empty string\" — `docker` resolves to `url: null` when the compose file\n // declares no usable db service.\n const named = (value: string | null | undefined) => (value && value.trim() ? value : undefined);\n\n return named(prepared.env.DATABASE_URL)\n ?? named(prepared.database.kind === \"managed\" ? undefined : prepared.database.url)\n ?? named(envFile.DATABASE_URL)\n ?? named(process.env.DATABASE_URL);\n}\n\n/**\n * A destination that names a remote store rather than a local path.\n *\n * Matched as \"scheme://\" generally, not as a list of the schemes we support:\n * an unknown scheme is still not something to join onto a filesystem path, and\n * a Windows drive letter (\"C:\\backups\") has no \"//\" so it stays a path.\n */\nconst REMOTE_DESTINATION_RE = /^[a-z][a-z0-9+.-]*:\\/\\//i;\n\n/**\n * The flags whose value is a local path, on every line the CLI relays.\n *\n * All three spellings of the destination, because the driver accepts all\n * three: `backup-cli.ts` maps `--output` and `-o` onto `--out`, and `rebase db\n * backup --help` advertises `--output` as an alias. Only `--out` and `-o` were\n * absolutised once, so the one spelling the help page names was the one that\n * landed in `backend/` — and the success line still echoed the path as typed.\n *\n * And `--collections`, which was not absolutised at all: from the project root,\n * `rebase schema generate --collections ./config/collections` was \"not found\",\n * while the same spelling worked for `generate-sdk`. See `utils/path-flags.ts`.\n */\nexport const LOCAL_PATH_FLAGS: readonly string[] = [\"--out\", \"--output\", \"-o\", \"--collections\", \"-c\"];\n\n/**\n * Rewrite local path arguments so they mean what the user typed.\n *\n * The plugin CLI is spawned with `cwd: backendDir` — it has to be, because that\n * is where the plugin and its dependencies resolve from. But the developer runs\n * `rebase db` from the project root, so a relative `--out ./backups` was being\n * resolved against `backend/` and landed in `backend/backups`, while the\n * success line echoed the path as typed. The file was real and the reported\n * location was wrong, which is the worst way for a backup command to behave.\n * `rebase db --help` documents exactly this invocation.\n *\n * Absolutising here rather than inside the plugin keeps the fix where the cwd\n * is actually changed, and leaves the plugin usable on its own terms.\n */\nexport function absolutizeLocalPathArgs(\n args: string[],\n cwd: string,\n pathFlags: readonly string[] = LOCAL_PATH_FLAGS\n): string[] {\n const takesPath = (flag: string) => pathFlags.includes(flag);\n /**\n * Flags whose next token is a value, not a positional.\n *\n * Mirrors the `arg` specs in `@rebasepro/server-postgres`'s backup CLI.\n * Needed only to find the `db restore` dump argument: without it,\n * `restore --target-db app_restored ./x.dump` treats `app_restored` as the\n * positional — it is the first token not starting with `-` — and turns a\n * database name into a path while leaving the real dump path unresolved.\n */\n const VALUE_FLAGS = new Set([\n \"--out\", \"--output\", \"-o\", \"--target-db\", \"--exclude-schema\", \"--row-security-role\"\n ]);\n const out = [...args];\n\n for (let i = 0; i < out.length; i++) {\n const arg = out[i];\n\n // `--out=<value>`\n const eq = arg.indexOf(\"=\");\n if (eq > 0 && takesPath(arg.slice(0, eq))) {\n const value = arg.slice(eq + 1);\n if (value && !REMOTE_DESTINATION_RE.test(value)) {\n out[i] = `${arg.slice(0, eq)}=${path.resolve(cwd, value)}`;\n }\n continue;\n }\n\n // `--out <value>`\n if (takesPath(arg)) {\n const value = out[i + 1];\n if (value && !value.startsWith(\"-\") && !REMOTE_DESTINATION_RE.test(value)) {\n out[i + 1] = path.resolve(cwd, value);\n i++;\n }\n }\n }\n\n // `db restore <file>` — the dump to read is a positional, and a relative one\n // was resolved against `backend/` too, so the path printed by a preceding\n // `db backup` could not be pasted into `db restore`.\n const restoreAt = out.indexOf(\"restore\");\n if (restoreAt !== -1) {\n for (let i = restoreAt + 1; i < out.length; i++) {\n const arg = out[i];\n if (arg.startsWith(\"-\")) {\n // `--flag=value` carries its value inline; `--flag value` eats\n // the next token only when the flag actually takes one.\n if (!arg.includes(\"=\") && VALUE_FLAGS.has(arg)) i++;\n continue;\n }\n // First true positional: the dump to restore.\n if (!REMOTE_DESTINATION_RE.test(arg)) out[i] = path.resolve(cwd, arg);\n break;\n }\n }\n\n return out;\n}\n\n/**\n/**\n * Read `--flag value` or `--flag=value` out of the raw argv.\n *\n * This command forwards its arguments to the driver plugin rather than parsing\n * them, so the two flags the CLI itself acts on are picked out by hand instead\n * of adding a spec that would then have to strip them back out again.\n */\nfunction readFlagValue(rawArgs: readonly string[], flag: string): string | null {\n for (let index = 0; index < rawArgs.length; index += 1) {\n const arg = rawArgs[index];\n if (arg === flag) return rawArgs[index + 1] ?? null;\n if (arg.startsWith(`${flag}=`)) return arg.slice(flag.length + 1);\n }\n\n return null;\n}\n\n/** `rebase db pull`'s flags. */\nconst PULL_FLAGS = {\n \"--from\": String,\n \"--schema\": [String],\n \"--anonymize\": Boolean,\n \"--yes\": Boolean,\n \"-y\": \"--yes\",\n \"--docker\": Boolean,\n // Declared so it is refused with its own reason rather than as a typo:\n // the target of a pull is never selectable. See `pullIntoLocal`.\n \"--database-url\": String\n} satisfies arg.Spec;\n\n/** `rebase db url`'s flags. */\nconst URL_FLAGS = { \"--database-url\": String, \"--docker\": Boolean } satisfies arg.Spec;\n\n/** `rebase db reset`'s flags. */\nconst RESET_FLAGS = { \"--yes\": Boolean, \"-y\": \"--yes\" } satisfies arg.Spec;\n\n/** `rebase db stop` takes none. */\nconst STOP_FLAGS = {} satisfies arg.Spec;\n\n/** `rebase db pull`'s line, parsed strictly. */\nfunction parsePullFlags(rawArgs: readonly string[]): arg.Result<typeof PULL_FLAGS> {\n return parseCommandArgs({ spec: PULL_FLAGS, rawArgs: [...rawArgs], commandWords: 2, command: \"db pull\", maxPositionals: 0 }).flags;\n}\n\n/** `rebase db url`'s line, parsed strictly. */\nfunction parseUrlFlags(rawArgs: readonly string[]): arg.Result<typeof URL_FLAGS> {\n return parseCommandArgs({ spec: URL_FLAGS, rawArgs: [...rawArgs], commandWords: 2, command: \"db url\", maxPositionals: 0 }).flags;\n}\n\n/** `rebase db reset`'s line, parsed strictly. */\nfunction parseResetFlags(rawArgs: readonly string[]): arg.Result<typeof RESET_FLAGS> {\n return parseCommandArgs({ spec: RESET_FLAGS, rawArgs: [...rawArgs], commandWords: 2, command: \"db reset\", maxPositionals: 0 }).flags;\n}\n\n/** `rebase db stop`'s line, parsed strictly. */\nfunction parseStopFlags(rawArgs: readonly string[]): arg.Result<typeof STOP_FLAGS> {\n return parseCommandArgs({ spec: STOP_FLAGS, rawArgs: [...rawArgs], commandWords: 2, command: \"db stop\", maxPositionals: 0 }).flags;\n}\n\n/**\n * The `db` subcommands this CLI answers itself, each with its strict parse.\n *\n * The driver's `db` commands refuse a flag they do not take; these four never\n * reach the driver, and read their flags out of argv by hand, so they accepted\n * anything. On `pull` that cost personal data: `--anonymise` (or `--anonymiz`,\n * or `--anon`) was dropped and the copy arrived as it was. An undeclared flag,\n * or a word where none is taken, is now a `UsageError` naming the flag it was\n * probably meant to be, raised before anything has run.\n */\nconst OWN_SUBCOMMAND_PARSERS: Readonly<Record<string, ((rawArgs: readonly string[]) => unknown) | undefined>> = {\n pull: parsePullFlags,\n url: parseUrlFlags,\n reset: parseResetFlags,\n stop: parseStopFlags\n};\n\n/**\n * Run a database subcommand through the active driver's CLI, throwing on\n * failure instead of exiting.\n *\n * `dbCommand` below turns every failure into `process.exit(1)`, which is right\n * for a command the user invoked directly and wrong for a caller that has more\n * to do afterwards — `rebase dev` runs a schema push during start-up and must\n * survive it failing. Exiting is therefore the wrapper's job, not this\n * function's.\n *\n * The database is resolved *here* rather than in the wrapper, so the schema\n * push `rebase dev` performs during start-up reaches the managed database too.\n */\n/**\n * The `db` subcommands that plan their work with Atlas.\n *\n * Atlas computes a diff by replaying the desired schema into a **second, empty\n * database** and comparing. That is why these three are listed and `backup` and\n * `restore` are not — those shell out to `pg_dump`, which fails loudly on its\n * own. `branch` is refused too, but for its own reason and with its own\n * message: see {@link refuseBranchOnManagedDatabase}.\n */\nconst ATLAS_BACKED_SUBCOMMANDS = new Set([\"push\", \"generate\", \"migrate\"]);\n\n/**\n * A managed-database refusal, raised so the caller decides what it costs.\n *\n * These two guards used to `process.exit(1)` where they stood. That is right\n * for `rebase db push`, typed by a person, and catastrophic for the same code\n * reached from inside `rebase dev`: the dev server's first-boot schema push\n * runs in-process, so an exit there took the whole dev server down — with a\n * `try/catch` around it written expressly to prevent that, which could never\n * run. The first `rebase dev --docker` of every scaffold died this way.\n *\n * So the refusal is a value now. It carries the block it wants printed rather\n * than printing it, because who prints (and whether printing is even right) is\n * the caller's question: `dbCommand` prints it and exits 1, and `rebase dev`\n * keeps serving.\n */\nexport class ManagedDatabaseRefusal extends Error {\n /** The lines to print, in order, already coloured. */\n readonly lines: readonly string[];\n\n constructor(summary: string, lines: readonly string[]) {\n super(summary);\n this.name = \"ManagedDatabaseRefusal\";\n this.lines = lines;\n }\n}\n\n/** Print a refusal exactly as the guards used to print it themselves. */\nexport function printManagedDatabaseRefusal(refusal: ManagedDatabaseRefusal): void {\n for (const line of refusal.lines) console.error(line);\n}\n\n/**\n * The variable the driver reads for Atlas's dev database\n * (`ATLAS_DEV_URL_ENV` in `@rebasepro/server-postgres`, which this CLI does not\n * depend on).\n */\nexport const ATLAS_DEV_URL_ENV = \"REBASE_ATLAS_DEV_URL\";\n\n/**\n * The variable that tells the driver where `rebase` was run\n * (`INVOCATION_CWD_ENV` in `@rebasepro/server-postgres`). The driver runs in\n * `backend/`, so a path it resolves itself, such as `db backup`'s default\n * `./backups`, needs to know the directory the developer meant.\n */\nconst INVOCATION_CWD_ENV = \"REBASE_INVOCATION_CWD\";\n\n/** Loaded only when a command needs one: PGlite is 25 MB of WASM. */\nconst startAtlasDevDatabase = async (): Promise<AtlasDevDatabase> =>\n (await import(\"../dev-db/atlas-dev-database\")).startAtlasDevDatabase();\n\n/**\n * The empty database an Atlas-backed subcommand plans against, on the managed\n * development database.\n *\n * **PGlite serves exactly one database.** Atlas computes a change by replaying\n * the desired schema into a second, empty one; on a real server the driver\n * makes it as `<db>_dev_diff`, but `CREATE DATABASE` against PGlite reports\n * success and creates nothing, so Atlas connected straight back to the\n * database it was comparing and stopped with `connected database is not\n * clean`. These commands were refused outright on the managed database — and\n * with them every way to drop, rename or narrow a column there, since boot\n * only adds.\n *\n * So a throwaway second PGlite is started for the command instead — in\n * memory, in this process, gone when the command ends — and handed to the\n * driver as `REBASE_ATLAS_DEV_URL`. Nothing else about the push changes: the\n * destructive gate is the driver's, and holds as it does everywhere.\n *\n * `undefined` when none is needed: another database kind (the driver makes its\n * own), a subcommand that is not Atlas's, or a `REBASE_ATLAS_DEV_URL` the\n * developer set. When one cannot be started — PGlite is an optional\n * dependency — the old refusal stands, with the reason.\n */\nexport async function atlasDevDatabaseFor(\n rawArgs: string[],\n kind: string,\n env: Readonly<Record<string, string | undefined>>,\n start: () => Promise<AtlasDevDatabase> = startAtlasDevDatabase\n): Promise<AtlasDevDatabase | undefined> {\n if (kind !== \"managed\") return undefined;\n const [domain, subcommand] = commandWords(rawArgs, \"db\");\n if (domain !== \"db\" || !ATLAS_BACKED_SUBCOMMANDS.has(subcommand ?? \"\")) return undefined;\n if (env[ATLAS_DEV_URL_ENV]?.trim()) return undefined;\n\n try {\n return await start();\n } catch (err) {\n const summary = `rebase db ${subcommand} could not start the database Atlas plans against.`;\n throw new ManagedDatabaseRefusal(summary, [\n \"\",\n chalk.red(` ✗ ${summary}`),\n chalk.gray(` ${err instanceof Error ? err.message : String(err)}`),\n \"\",\n chalk.gray(\" Atlas plans every change against a second, empty database. On the managed\"),\n chalk.gray(\" database that is a throwaway PGlite, started for the command.\"),\n \"\",\n chalk.gray(` ${chalk.cyan(\"rebase dev\")} still applies your collections at boot, additively. Otherwise,`),\n chalk.gray(` set ${ATLAS_DEV_URL_ENV} to an empty Postgres database Atlas may fill and clear,`),\n chalk.gray(\" or point the project at a real Postgres (uncomment DATABASE_URL in .env).\"),\n \"\"\n ]);\n }\n}\n\n/**\n * Stop `rebase db branch` before it reports a branch that is not one.\n *\n * **PGlite serves exactly one database**, and this is the second thing that\n * follows from it. `CREATE DATABASE \"rb_feature_x\" TEMPLATE \"postgres\"` there\n * writes a `pg_database` catalog row and nothing else. Nothing errors, so the\n * whole feature reports success end to end:\n *\n * $ rebase db branch create feature_x\n * ✓ Branch \"feature_x\" created successfully.\n * $ rebase db branch list\n * ● feature_x (7.1 MB) — created just now\n *\n * `listBranches` joins `pg_database`, the catalog row is there, and\n * `pg_database_size` answers with the one database's size — so the listing\n * corroborates the lie. Then connecting to `rb_feature_x` reports\n * `current_database()` = `postgres`, and a table created \"in the branch\" is\n * visible in the parent immediately. Measured on a fresh `rebase init` scaffold.\n *\n * **The branch is the parent.** Every write made in the belief that it is\n * sandboxed lands in the developer's real development database — which is the\n * exact failure branching exists to prevent, announced as a success.\n *\n * So this refuses the whole `branch` domain rather than `create` alone: `list`\n * on the managed database ends with \"Create one with: rebase db branch create\",\n * an invitation to do the broken thing, and `info` would confirm a size for a\n * database that was never made.\n *\n * Push, generate and migrate had the same problem — Atlas's scratch database\n * is a second database too — and get a throwaway PGlite of their own instead\n * (`atlasDevDatabaseFor` above). A branch cannot: it is meant to keep the\n * project's data, and a throwaway instance has none.\n */\nexport function refuseBranchOnManagedDatabase(rawArgs: string[], kind: string): void {\n if (kind !== \"managed\") return;\n const [domain, subcommand] = commandWords(rawArgs, \"db\");\n if (domain !== \"db\" || subcommand !== \"branch\") return;\n\n const summary = \"rebase db branch does not work on the managed development database.\";\n\n throw new ManagedDatabaseRefusal(summary, [\n \"\",\n chalk.red(` ✗ ${summary}`),\n \"\",\n chalk.gray(\" Branching copies a database with CREATE DATABASE ... TEMPLATE. The managed\"),\n chalk.gray(\" database is PGlite, which serves exactly one — the copy would be the\"),\n chalk.gray(\" original, and every write you meant to sandbox would land in it.\"),\n \"\",\n chalk.gray(\" Branching needs a real Postgres. Either:\"),\n chalk.gray(` ${chalk.cyan(\"rebase dev --docker\")} starts one, and branches work against it`),\n chalk.gray(\" or uncomment DATABASE_URL in .env to point at your own.\"),\n \"\"\n ]);\n}\n\n/**\n * The variable a driver child reads what named its database from: the\n * resolution's `source` (`flag`, `environment`, `env-file`, `branch`,\n * `docker`, `last-dev` or `managed`). Read as a literal by\n * `@rebasepro/server-postgres`'s `cli-errors.ts`.\n */\nexport const DATABASE_SOURCE_ENV = \"REBASE_DATABASE_SOURCE\";\n\n/**\n * Refuse `rebase db restore` into the managed development database.\n *\n * A backup carries its rows as COPY data, and the managed database's socket\n * server cannot take `COPY … FROM stdin`: `rebase db restore --clean` into it\n * hung the daemon, and every command after it, until the daemon was killed.\n * `pg_restore` has no way to write the rows as INSERTs. `rebase db pull`\n * dumps them that way itself (see `dev-db/pull.ts`), so the route is to\n * restore into a real Postgres and pull the copy across.\n */\nexport function refuseRestoreOnManagedDatabase(rawArgs: string[], kind: string): void {\n if (kind !== \"managed\") return;\n const words = argsFromCommand(rawArgs, \"db\");\n if (words[0] !== \"db\" || words[1] !== \"restore\") return;\n\n let dump = \"<dump>\";\n for (let i = 2; i < words.length; i++) {\n if (words[i] === \"--target-db\") i++;\n else if (!words[i].startsWith(\"-\")) {\n dump = words[i];\n break;\n }\n }\n const summary = \"rebase db restore does not work on the managed development database.\";\n\n throw new ManagedDatabaseRefusal(summary, [\n \"\",\n chalk.red(` ✗ ${summary} Nothing was restored.`),\n \"\",\n chalk.gray(\" A backup carries its rows as COPY data, which the managed database (PGlite)\"),\n chalk.gray(\" cannot receive: the restore would leave it hung until it is stopped.\"),\n \"\",\n chalk.gray(\" Restore into Postgres in Docker instead:\"),\n chalk.gray(` ${chalk.cyan(`rebase db restore ${dump} --docker --clean --yes`)}`),\n chalk.gray(\" and, to have the copy in the managed database too, pull it across:\"),\n chalk.gray(` ${chalk.cyan(\"rebase db pull --from \\\"$(rebase db url --docker)\\\" --yes\")}`),\n \"\"\n ]);\n}\n\n/**\n * Resolve the active driver's CLI and the environment it should run in.\n *\n * Shared by the two runners below. Deliberately does NOT resolve a database:\n * `schema generate` reads collection files and writes one file, and starting a\n * database to run it would be a side effect nobody asked for.\n */\nexport async function resolveDriverCli(): Promise<{\n projectRoot: string;\n backendDir: string;\n pluginCli: string;\n env: Record<string, string>;\n}> {\n const projectRoot = requireProjectRoot();\n const backendDir = requireBackendDir(projectRoot);\n\n const activePlugin = getActiveBackendPlugin(backendDir);\n if (!activePlugin) {\n throw new Error(\n \"Could not detect an active database plugin. Make sure a package like \"\n + \"@rebasepro/server-postgres is installed in backend/package.json.\"\n );\n }\n const pluginCli = resolvePluginCliScript(backendDir, activePlugin);\n if (!pluginCli) {\n throw new Error(dependenciesNotInstalled(projectRoot));\n }\n\n const envFile = findEnvFile(projectRoot);\n const env: Record<string, string> = { ...process.env as Record<string, string> };\n if (envFile) {\n env.DOTENV_CONFIG_PATH = envFile;\n }\n env[DEV_DATABASE_KIND_ENV] = devDatabaseKind(projectRoot) ?? \"\";\n\n return { projectRoot, backendDir, pluginCli, env };\n}\n\n/**\n * The one place this CLI spawns the driver's own CLI.\n *\n * There were three, each with its own copy of \"tsx for a `.ts` entry, `node`\n * otherwise\". That rule was right only while the driver shipped `src/`; once it\n * shipped `dist/cli.js` all three quietly switched to plain `node`, and the\n * driver loads the PROJECT's TypeScript in process:\n *\n * - `schema stale` reads the collections, could not resolve `./authors` onto\n * `authors.ts`, and answered \"⏭ Not checked\" while exiting 0;\n * - `db push` does the same in `ensureAuthTables`, so `rebase.users` was never\n * created and the push died at \"Applying RLS policies\" with\n * `relation \"rebase.users\" does not exist` — on a virgin database, which is\n * the documented bring-your-own-Postgres first run.\n *\n * Two were fixed and the third was missed, because three copies of a decision\n * are three chances to miss one. There is one now, and a gate holds it at one.\n *\n * tsx whenever it is installed — a devDependency of every scaffold, for exactly\n * this reason. Without it a `.ts` entry cannot run at all; a built entry still\n * runs, and the subcommands that never touch the project's TypeScript still work.\n *\n * tsx's loader in one Node (`node --import`) rather than the `tsx` binary,\n * which is a shell shim and a relay Node in front of the same loader: one Node\n * start instead of two, ~50–100 ms on each of the driver runs every `rebase\n * dev` start and every collection save makes. The binary stays the fallback for\n * a tsx whose loader does not resolve as a package — a global install.\n */\nexport async function spawnDriverCli(\n resolved: { projectRoot: string; backendDir: string; pluginCli: string; env: Record<string, string> },\n childArgs: string[],\n options: { quiet?: boolean } = {}\n): Promise<void> {\n const { projectRoot, backendDir, pluginCli, env } = resolved;\n const stdio = options.quiet ? \"pipe\" : \"inherit\";\n\n const tsxBin = resolveTsx(projectRoot);\n const tsxLoader = resolveTsxLoader(projectRoot);\n if (!tsxBin && !tsxLoader && pluginCli.endsWith(\".ts\")) {\n throw new Error(dependenciesNotInstalled(projectRoot));\n }\n\n const [command, ...prefix] = tsxLoader ? [process.execPath, \"--import\", tsxLoader] : [tsxBin ?? \"node\"];\n await execa(command, [...prefix, pluginCli, ...childArgs], { cwd: backendDir, stdio, env });\n}\n\n/** @deprecated Use {@link spawnDriverCli}. Kept as the internal name callers use. */\nconst execDriverCli = spawnDriverCli;\n\n/**\n * Run a `schema` subcommand through the active driver's CLI.\n *\n * Separate from {@link runDriverDbCommand} because it must NOT resolve a\n * database. `rebase dev` calls this before the database exists, which is the\n * whole point: the generated schema has to be right before anything reads it.\n * Throws rather than exiting — the caller has more to do.\n */\nexport async function runDriverSchemaCommand(\n rawArgs: string[],\n options: { quiet?: boolean } = {}\n): Promise<void> {\n const resolved = await resolveDriverCli();\n await execDriverCli(resolved, rawArgs.slice(2), options);\n}\n\nexport async function runDriverDbCommand(\n rawArgs: string[],\n options: { quiet?: boolean } = {}\n): Promise<void> {\n const projectRoot = requireProjectRoot();\n const backendDir = requireBackendDir(projectRoot);\n\n const activePlugin = getActiveBackendPlugin(backendDir);\n if (!activePlugin) {\n throw new Error(\n \"Could not detect an active database plugin. Make sure a package like \"\n + \"@rebasepro/server-postgres is installed in backend/package.json.\"\n );\n }\n\n const pluginCli = resolvePluginCliScript(backendDir, activePlugin);\n if (!pluginCli) {\n throw new Error(dependenciesNotInstalled(projectRoot));\n }\n\n // Set up environment with DOTENV_CONFIG_PATH\n const envFile = findEnvFile(projectRoot);\n const env: Record<string, string> = { ...process.env as Record<string, string> };\n if (envFile) {\n env.DOTENV_CONFIG_PATH = envFile;\n }\n env[DEV_DATABASE_KIND_ENV] = devDatabaseKind(projectRoot) ?? \"\";\n\n // Every `db` subcommand reaches Postgres through the driver plugin, which\n // reads DATABASE_URL from this environment — so resolving the database once\n // here covers push, generate, migrate, backup and restore alike, and any\n // subcommand a driver adds later. When the developer has named their own\n // database this adds nothing at all.\n // Refused before anything is started. `prepareDatabaseEnv` below *boots*\n // the managed database, and booting PGlite in order to say that PGlite\n // cannot branch is latency spent on an answer already known — the resolver\n // is a pure function and settles it. It also keeps the refusal working when\n // the managed database would have failed to start, where the developer\n // would otherwise be told about a daemon rather than about branching.\n const { resolveProjectDatabase } = await import(\"../dev-db/prepare\");\n const resolvedKind = resolveProjectDatabase(projectRoot, {\n flagUrl: readFlagValue(rawArgs, \"--database-url\"),\n flagDocker: switchOn(rawArgs, \"--docker\")\n }).kind;\n refuseBranchOnManagedDatabase(rawArgs, resolvedKind);\n refuseRestoreOnManagedDatabase(rawArgs, resolvedKind);\n\n const { prepareDatabaseEnv, managedNotices } = await import(\"../dev-db/prepare\");\n const prepared = await prepareDatabaseEnv(projectRoot, {\n flagUrl: readFlagValue(rawArgs, \"--database-url\"),\n flagDocker: switchOn(rawArgs, \"--docker\"),\n onProgress: (message) => { if (!options.quiet) console.log(chalk.gray(` ${message}`)); }\n });\n Object.assign(env, prepared.env);\n // What named the database, for the driver's \"Cannot connect\" banner to\n // send the reader to it rather than to a `.env` that played no part.\n env[DATABASE_SOURCE_ENV] = prepared.database.source;\n // And which kind it is, for the managed database's Atlas handling\n // (`--skip-lock`, the revisions table made first): the project default set\n // above is wrong for a command whose --database-url or --docker named\n // another database.\n env[DEV_DATABASE_KIND_ENV] = prepared.database.kind;\n // Suppressed for an internal caller. `rebase dev` runs a schema push during\n // start-up and has already said all of this in its own banner; repeating it\n // mid-boot reads as something having gone wrong.\n if (!options.quiet) {\n for (const line of managedNotices(prepared)) console.log(chalk.gray(` ${line}`));\n }\n\n // Started after the managed database, stopped when the driver exits —\n // whatever it exits with.\n const atlasDev = await atlasDevDatabaseFor(rawArgs, prepared.database.kind, env);\n if (atlasDev) env[ATLAS_DEV_URL_ENV] = atlasDev.url;\n env[INVOCATION_CWD_ENV] = process.cwd();\n\n // Resolved against the directory the developer is standing in, before the\n // child is handed a different one. See absolutizeLocalPathArgs.\n //\n // From the command word, not from index 2: the driver reads its domain out\n // of `args[0]`, so `rebase --debug db push` spawned it with [\"--debug\",\n // \"db\", \"push\"] and it answered \"Unknown domain command: --debug\" — for a\n // flag this CLI prints after every failure as the thing to re-run with.\n const childArgs = absolutizeLocalPathArgs(argsFromCommand(rawArgs, \"db\"), process.cwd());\n\n try {\n await spawnDriverCli({ projectRoot, backendDir, pluginCli, env }, childArgs, options);\n } finally {\n await atlasDev?.stop();\n }\n}\n\nexport async function dbCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void> {\n // `--help` is answered here, before anything else, and never by a\n // subcommand.\n //\n // `cli.ts` rewrites the subcommand to `\"--help\"` only when the user named\n // none, so `rebase db --help` was covered and `rebase db push --help` was\n // not: the flag went through to `runDriverDbCommand`, which resolves (and\n // will START) the development database and then hands the whole line to the\n // driver, whose own dispatch has no `--help` case for `push`. **It ran the\n // push.** A flag whose entire job is to print text applied a schema to a\n // database — the single most dangerous shape a help flag can have, and the\n // same class as `skills install --help` writing files and `auth\n // reset-password --help` running an UPDATE.\n //\n // Answering before `requireProjectRoot` and before the driver spawn makes\n // it structurally impossible rather than conditionally safe: no subcommand\n // can act on `--help`, because no subcommand is reached.\n if (!subcommand || subcommand === \"--help\" || rawArgs.includes(\"--help\") || rawArgs.includes(\"-h\")) {\n printDbHelp(subcommand === \"--help\" ? undefined : subcommand);\n return;\n }\n\n // A typo is answered here, not by the driver, and not after a database has\n // been started for it.\n //\n // `rebase db psh` used to reach `runDriverDbCommand`, which resolves the\n // database first — so it **booted the managed PGlite**, a 180 MB daemon,\n // in order to hand the driver an argv it then rejected with `Unknown db\n // command. Valid: push, generate, migrate, branch, backup, restore,\n // backups`: a list missing `url`, `pull`, `stop` and `reset`, all four of\n // which `rebase db --help` lists and this CLI implements itself. The driver\n // cannot know about them, which is exactly why the answer does not belong\n // to the driver.\n //\n // The set comes from the help table, so the list a typo is measured against\n // and the list `--help` prints cannot drift apart.\n if (!DB_ACTION_HELP[subcommand]) unknownCommand(subcommand, Object.keys(DB_ACTION_HELP), \"db\");\n // `db backups` has one action, and its typo is answered here for the same reason.\n if (subcommand === \"backups\") {\n const action = argsFromCommand(rawArgs, \"backups\")[1];\n if (action !== undefined && action !== \"list\") unknownCommand(action, [\"list\"], \"db backups\");\n }\n\n // The subcommands answered here rather than by the driver are strict about\n // their flags the way the driver's are, and refuse before anything is read,\n // started or copied. See `OWN_SUBCOMMAND_PARSERS`.\n OWN_SUBCOMMAND_PARSERS[subcommand]?.(rawArgs);\n\n const projectRoot = requireProjectRoot();\n\n // Fire-and-forget, and a no-op unless the developer opted in. Never awaited:\n // the command is what the user is waiting for, and a slow collector must not\n // sit in front of it.\n void recordEvent(\"cli.db\", { subcommand: subcommand ?? \"none\" }, { projectRoot });\n\n // Handled here rather than by the driver plugin: these are about the\n // *managed* database's process and data directory, which is a CLI concern.\n // A project pointed at its own Postgres has nothing here to stop or reset,\n // and is told so rather than silently doing nothing.\n if (subcommand === \"stop\" || subcommand === \"reset\") {\n await manageLocalDatabase(subcommand, projectRoot, rawArgs);\n\n return;\n }\n\n // Each starts the remembered compose database itself, once what it was\n // asked for has been checked: a pull refused for a missing --from has no\n // reason to start a container first.\n if (subcommand === \"pull\") {\n await pullIntoLocal(projectRoot, rawArgs);\n\n return;\n }\n\n if (subcommand === \"url\") {\n await printDatabaseUrl(projectRoot, rawArgs);\n\n return;\n }\n\n // Every other subcommand is the driver's, and the driver is spawned only\n // once a database is running for it. Its flags are judged here, by its own\n // check, before the line below starts the remembered container and\n // `runDriverDbCommand` boots the managed one. `branch switch` is this\n // CLI's, and is judged by its own check, before the same start.\n if (subcommand === \"branch\" && commandWords(rawArgs, \"db\")[2] === \"switch\") {\n assertSwitchFlags(rawArgs);\n } else {\n await refuseDriverLineBeforeStarting(projectRoot, rawArgs);\n // And a `--collections` path that does not exist, for the same\n // reason, in the reader's terms. See utils/path-flags.ts.\n refuseMissingCollectionsPath(rawArgs, process.cwd(), requireBackendDir(projectRoot));\n }\n\n // `--docker` on a `db` subcommand meant \"resolve the compose URL\", and\n // nothing started it: `rebase db branch list --docker` on a stock scaffold\n // answered `✗ Failed query: CREATE SCHEMA IF NOT EXISTS rebase` and\n // `connect ECONNREFUSED 127.0.0.1:5436` — two lines, no diagnosis — while\n // the managed-database refusal that sends the reader here says \"`rebase dev\n // --docker` starts one, and branches work against it\".\n //\n // The same ensure step `rebase dev --docker` runs, not a second one.\n await ensureDockerDatabase(projectRoot, rawArgs);\n\n // Handled here rather than by the driver, for the same reason `stop` and\n // `reset` are: it writes per-checkout CLI state. The driver creates and\n // drops the databases; which one this checkout talks to is not its\n // business, and it runs as a child process that could not persist the\n // answer anyway.\n if (subcommand === \"branch\" && commandWords(rawArgs, \"db\")[2] === \"switch\") {\n await switchBranch(projectRoot, rawArgs);\n\n return;\n }\n\n // The other two branch actions that need to know where this checkout is\n // standing, for reasons the driver — a child process with no idea a pointer\n // exists — cannot answer.\n let driverArgs = rawArgs;\n if (subcommand === \"branch\") {\n const action = commandWords(rawArgs, \"db\")[2];\n if (action === \"delete\") await refuseDeletingActiveBranch(projectRoot, rawArgs);\n if (action === \"prune\" || action === \"list\") await tellDriverTheActiveBranch(projectRoot);\n if (action && REGISTRY_ACTIONS.has(action)) driverArgs = await onParentDatabase(projectRoot, rawArgs, action);\n }\n\n try {\n await runDriverDbCommand(driverArgs);\n } catch (error) {\n // The CLI entry point is where a managed-database refusal becomes an\n // exit code. The guards raise it instead of exiting so that `rebase dev`,\n // which runs `db push` in-process, survives one; here, where a person\n // typed the command, it is exactly as fatal as it always was.\n if (error instanceof ManagedDatabaseRefusal) {\n printManagedDatabaseRefusal(error);\n process.exit(1);\n }\n // A child that exited non-zero already printed its diagnostics through\n // inherited stdio; only the errors raised above have a message worth\n // adding here.\n reportSpawnFailure(error);\n process.exit(1);\n }\n}\n\n/**\n * Refuse a driver `db` line the driver would refuse on its flags, before\n * anything is started for it.\n *\n * The driver is spawned with a database already running, because getting one\n * means starting one: the remembered compose container, or the managed PGlite\n * daemon. So `rebase db push --dry-rn` started the database and only then\n * heard that `--dry-rn` does not exist. The check is the driver's own\n * (`assertDbCommandLine`, the same parse each of its commands runs), so this\n * answer and the one the driver gives cannot drift apart.\n *\n * It is this CLI's copy of `@rebasepro/server-postgres`, which ships at the\n * CLI's version, as the project's does. For any other driver the line goes\n * through as it is, and that driver judges it.\n *\n * @throws UsageError with the driver's sentence: nothing ran.\n */\nasync function refuseDriverLineBeforeStarting(projectRoot: string, rawArgs: readonly string[]): Promise<void> {\n if (getActiveBackendPlugin(requireBackendDir(projectRoot)) !== \"@rebasepro/server-postgres\") return;\n const { assertDbCommandLine } = await import(\"@rebasepro/server-postgres\");\n try {\n assertDbCommandLine(argsFromCommand(rawArgs, \"db\"));\n } catch (error) {\n if (error instanceof Error) throw new UsageError(error.message);\n throw error;\n }\n}\n\n/**\n * `rebase db url` — the connection string this project is using, on stdout.\n *\n * The managed database is the one case where nothing on disk names it: `.env`\n * ships `DATABASE_URL` commented out on purpose, the port is derived from the\n * project path, and the data lives under `.rebase/`. A headless project has no\n * admin panel to open either, so before this there was no way to point `psql`,\n * a GUI client or a seeding script at the database `rebase dev` had just\n * created — short of reading the CLI's source.\n *\n * Resolution is the same ordered rule every other command uses, so this prints\n * your own `DATABASE_URL` when you have set one rather than inventing a second\n * answer. Nothing but the URL goes to stdout, so it pipes:\n *\n * psql \"$(rebase db url)\"\n *\n * It starts the managed database if it is not running, because a connection\n * string for a database nobody is serving is not an answer.\n */\nasync function printDatabaseUrl(projectRoot: string, rawArgs: readonly string[]): Promise<void> {\n // Strict about its flags, like every other command.\n //\n // The `db` family's strictness lives in the driver, and `url` is answered\n // here, before the driver is ever spawned — so it accepted anything.\n // `rebase db url --bogus` printed the URL and exited 0, and so did\n // `rebase db url --json`, which is worse: a flag that looks like it asks\n // for a different output format, silently ignored, hands a script a bare\n // string it will try to parse as JSON.\n const flags = parseUrlFlags(rawArgs);\n\n // After the flags, and before the URL is resolved: a remembered container\n // that is stopped is started, with what that says on stderr.\n await ensureDockerDatabase(projectRoot, rawArgs);\n\n const { prepareDatabaseEnv } = await import(\"../dev-db/prepare\");\n const { readEnvFile } = await import(\"../utils/project\");\n\n const prepared = await prepareDatabaseEnv(projectRoot, {\n flagUrl: flags[\"--database-url\"] ?? null,\n flagDocker: flags[\"--docker\"] === true,\n quiet: true,\n // Progress goes to stderr: stdout is the URL and nothing else.\n onProgress: message => console.error(chalk.gray(` ${message}`))\n });\n\n const url = databaseUrlOf(prepared, readEnvFile(projectRoot));\n if (!url) {\n console.error(chalk.red(\" ✗ This project has no database URL to print.\"));\n console.error(chalk.gray(\" Set DATABASE_URL in .env, or run `rebase dev` to start the managed one.\"));\n process.exit(1);\n }\n\n console.log(url);\n}\n\n/**\n * `rebase db stop` and `rebase db reset`, for the managed database only.\n *\n * `reset` deletes the data directory rather than dropping schemas: \"give me an\n * empty database\" is the only thing anyone means by it, and doing it by\n * removing the directory cannot leave a half-dropped schema behind.\n */\nasync function manageLocalDatabase(\n subcommand: \"stop\" | \"reset\",\n projectRoot: string,\n rawArgs: readonly string[]\n): Promise<void> {\n const { resetManagedDatabase, stopManagedDatabase, stoppedManagedDatabaseLines, findRunningDaemon } = await import(\"../dev-db/daemon\");\n const { dataDir } = await import(\"../dev-db/state\");\n\n // What \"nothing here\" means, in the words of the project it is said to.\n //\n // \"No development database was running\" / \"No development database to\n // reset\" is true of the managed one and reads as being about the reader's\n // own Postgres — which these commands do not touch and could not stop.\n // On a project that named its own database, the sentence they need is that\n // it was not what this command was about.\n const nothingHere = (): string => {\n const kind = devDatabaseKind(projectRoot);\n const verb = subcommand === \"stop\" ? \"was not running\" : \"does not exist\";\n if (kind === \"docker\") {\n // The compose `db` service: the project names no DATABASE_URL for it.\n return ` The managed development database (PGlite) ${verb}; `\n + \"this project is on Postgres in Docker, which is untouched.\"\n + (subcommand === \"stop\" ? \" `docker compose stop db` stops it.\" : \"\");\n }\n if (kind === \"external\") {\n return ` The managed development database (PGlite) ${verb}; `\n + \"this project uses its own DATABASE_URL, which is untouched.\";\n }\n\n return subcommand === \"stop\"\n ? \" The managed development database (PGlite) was not running.\"\n : \" There is no managed development database (PGlite) to reset.\";\n };\n\n if (subcommand === \"stop\") {\n if (!(await stopManagedDatabase(projectRoot))) {\n console.log(chalk.gray(nothingHere()));\n\n return;\n }\n // \"`rebase dev` will start it again\" was not true of a dev that is\n // running: see `stoppedManagedDatabaseLines`.\n const [headline, ...detail] = stoppedManagedDatabaseLines(projectRoot);\n console.log(chalk.green(headline));\n for (const line of detail) console.log(chalk.gray(line));\n\n return;\n }\n\n const running = await findRunningDaemon(projectRoot);\n const hasData = fs.existsSync(dataDir(projectRoot));\n if (!running && !hasData) {\n console.log(chalk.gray(nothingHere()));\n\n return;\n }\n\n // Destructive, and the data is not backed up anywhere: it only ever existed\n // on this machine. So it asks, unless the caller has said not to — and\n // without a TTY there is nobody to ask, which is a refusal rather than an\n // assumption.\n if (parseResetFlags(rawArgs)[\"--yes\"] !== true) {\n if (!process.stdin.isTTY) {\n console.error(chalk.red(\"✗ `rebase db reset` deletes the local database and cannot prompt here.\"));\n console.error(chalk.yellow(\" Re-run with --yes if that is what you intend.\"));\n process.exit(1);\n }\n\n const { confirmed } = await inquirer.prompt([{\n type: \"confirm\",\n name: \"confirmed\",\n message: `Delete the development database at ${dataDir(projectRoot)}? This cannot be undone.`,\n default: false\n }]);\n if (!confirmed) {\n console.log(chalk.gray(\" Left alone.\"));\n\n return;\n }\n }\n\n await resetManagedDatabase(projectRoot);\n console.log(chalk.green(\"✓ Development database deleted. `rebase dev` will create a fresh one.\"));\n}\n\n/**\n * `rebase db pull --from <url>` — copy another database's contents into local\n * development.\n *\n * Deliberately one-directional. There is no flag that makes this push, because\n * a tool that can copy in both directions eventually copies in the wrong one,\n * and the wrong one here means overwriting production with a laptop.\n */\nasync function pullIntoLocal(projectRoot: string, rawArgs: readonly string[]): Promise<void> {\n const { describeRestoreFailure, describeTarget, dumpSource, findPgTool, restoreCopy, sourceProblem } =\n await import(\"../dev-db/pull\");\n const { prepareDatabaseEnv } = await import(\"../dev-db/prepare\");\n const { readEnvFile } = await import(\"../utils/project\");\n\n // Parsed strictly, not read by hand. `rawArgs.includes(\"--anonymize\")` made\n // the privacy flag the one a typo turned off: `--anonymise`, `--anonymiz`\n // and `--anon` were dropped on the floor and the copy went ahead with real\n // personal data, and `--schem public` pulled every schema.\n const flags = parsePullFlags(rawArgs);\n const schemas = flags[\"--schema\"] ?? [];\n const anonymize = flags[\"--anonymize\"] === true;\n\n // `--database-url` is refused rather than honoured, and refused rather than\n // ignored — which is what it was.\n //\n // Ignored is the dangerous one. The flag was accepted, dropped on the floor,\n // and the pull went ahead against the `.env` database: someone writing\n // `rebase db pull --from prod --database-url scratch --yes` destroyed their\n // working database while naming a different one. A flag that changes nothing\n // is a bug; a destructive flag that changes nothing is a data-loss bug.\n //\n // Honoured is the other tempting answer, and it breaks the one guarantee\n // this command makes. The target is always the local development database\n // *by construction* — there is no `--to`, and no flag that reverses the\n // direction — because a tool that can copy both ways eventually copies the\n // wrong way, and the wrong way here is a laptop over production.\n // `--database-url prod` is exactly that instruction written as a target.\n //\n // `--docker` is a different question and is passed through: it says how to\n // get a local database, not which database to overwrite.\n const targetFlag = flags[\"--database-url\"];\n if (targetFlag !== undefined) {\n console.error(chalk.red(\"✗ `rebase db pull` does not take --database-url.\"));\n console.error(\"\");\n console.error(chalk.gray(\" The target is always this project's local development database. There is\"));\n console.error(chalk.gray(\" no flag that makes this write somewhere else, deliberately: a command that\"));\n console.error(chalk.gray(\" can copy in both directions eventually copies in the wrong one.\"));\n console.error(\"\");\n // Never the password, and quoted: a connection string's `&` and `?`\n // are shell syntax, so the line as it was printed did not paste.\n const shown = redactConnectionPasswords(targetFlag);\n console.error(chalk.gray(` To read from another database, that is ${chalk.cyan(\"--from\")}:`));\n console.error(chalk.gray(` rebase db pull --from \"${shown}\"`));\n if (shown !== targetFlag) console.error(chalk.gray(\" with the password in place of ***.\"));\n process.exit(1);\n }\n\n const source = flags[\"--from\"];\n if (!source) {\n console.error(chalk.red(\"✗ `rebase db pull` needs a source: --from <connection-string>\"));\n console.error(chalk.gray(\" Example: rebase db pull --from \\\"$PRODUCTION_DATABASE_URL\\\"\"));\n process.exit(1);\n }\n // Known from the string alone, so answered before anything is checked,\n // started or announced. The value is not repeated: see `sourceProblem`.\n const notASource = sourceProblem(source);\n if (notASource !== null) {\n console.error(chalk.red(`✗ The --from value is not a connection string: ${notASource}. Nothing was read or changed.`));\n console.error(chalk.gray(\" Pass a URL, postgresql://user:password@host:5432/database, or libpq's\"));\n console.error(chalk.gray(\" host=… port=… dbname=… user=… pairs, quoted as one argument.\"));\n process.exit(1);\n }\n\n // Both checked before anything destructive: discovering either is missing\n // after dropping the local database would be the worst possible ordering.\n for (const tool of [\"pg_dump\", \"pg_restore\"] as const) {\n if (!await findPgTool(tool)) {\n console.error(chalk.red(`✗ \\`${tool}\\` is not on PATH, and this command cannot run without it.`));\n console.error(chalk.gray(\" Install the PostgreSQL client tools, e.g. `brew install libpq`.\"));\n process.exit(1);\n }\n }\n\n // The local database the copy goes into, started if it is the remembered\n // compose one and stopped — once nothing above has refused.\n await ensureDockerDatabase(projectRoot, rawArgs);\n\n const prepared = await prepareDatabaseEnv(projectRoot, {\n flagDocker: flags[\"--docker\"] === true,\n onProgress: (message) => console.log(chalk.gray(` ${message}`))\n });\n // The database `rebase db url` prints, resolved the one way — see\n // `databaseUrlOf`. Reading only `prepared.env` missed the commonest\n // configuration there is: `DATABASE_URL` in `.env` and nowhere else.\n const target = databaseUrlOf(prepared, readEnvFile(projectRoot)) ?? \"\";\n if (!target) {\n console.error(chalk.red(\"✗ No local database to pull into.\"));\n console.error(chalk.gray(\" Set DATABASE_URL in .env, or run `rebase dev` to start the managed one.\"));\n process.exit(1);\n }\n\n const plan = { source, target, anonymize, schemas };\n\n // Said in full, before anything happens. The target is destroyed, and where\n // the data comes to rest on disk is the part people forget.\n console.log(\"\");\n console.log(chalk.bold(\" This will replace your local database.\"));\n console.log(` ${chalk.gray(\"From\")} ${describeTarget(source)}`);\n console.log(` ${chalk.gray(\"Into\")} ${describeTarget(target)}${prepared.dataDir ? chalk.gray(` (${prepared.dataDir})`) : \"\"}`);\n console.log(` ${chalk.gray(\"Data\")} ${anonymize\n ? \"personal-looking columns will be overwritten after the copy\"\n : chalk.yellow(\"copied as-is, including any personal data\")}`);\n if (schemas.length > 0) console.log(` ${chalk.gray(\"Schemas\")} ${schemas.join(\", \")}`);\n console.log(\"\");\n\n if (flags[\"--yes\"] !== true) {\n if (!process.stdin.isTTY) {\n console.error(chalk.red(\"✗ This replaces the local database and cannot prompt here.\"));\n console.error(chalk.yellow(\" Re-run with --yes if that is what you intend.\"));\n process.exit(1);\n }\n const { confirmed } = await inquirer.prompt([{\n type: \"confirm\", name: \"confirmed\", message: \"Continue?\", default: false\n }]);\n if (!confirmed) {\n console.log(chalk.gray(\" Nothing was changed.\"));\n\n return;\n }\n }\n\n const dumpFile = path.join(os.tmpdir(), `rebase-pull-${process.pid}.dump`);\n console.log(chalk.gray(\" Dumping…\"));\n // In the form the local database can restore: the managed one takes the\n // rows as INSERTs, because PGlite cannot receive COPY data. A source it\n // cannot reach is said here, in the banner, before anything is emptied.\n const dumped = await dumpSource(plan, dumpFile);\n if (!dumped.ok) {\n for (const line of dumped.lines) console.error(line.startsWith(\"✗\") ? chalk.red(line) : line);\n process.exit(1);\n }\n\n /** What failed, the state the local database is left in, and what to do — see `describeRestoreFailure`. */\n let failure: string[] | null = null;\n let anonymizeFailure: string[] | null = null;\n try {\n console.log(chalk.gray(\" Restoring…\"));\n // Empties the local schemas the copy replaces, then restores into\n // them; `pg_restore --clean` alone left anything local the source\n // lacks in the way. A failure is reported only after whatever did\n // arrive has been anonymized.\n const restored = await restoreCopy(dumped.plan, dumpFile);\n failure = restored.failure ? describeRestoreFailure(restored, describeTarget(source)) : null;\n\n // Before the verdict: a partial copy of personal data on a laptop is\n // still personal data on a laptop.\n if (anonymize && restored.started) {\n anonymizeFailure = await anonymizeTarget(target, describeTarget(source), prepared.database.kind);\n }\n\n // Whatever arrived, whole or partial, anonymized or emptied: pg_dump\n // stripped its grants either way, and a pull that failed is pulled\n // again into a database that should still be readable meanwhile.\n if (restored.started) await restoreAppRole(target);\n } finally {\n fs.rmSync(dumpFile, { force: true });\n }\n\n if (anonymizeFailure) {\n for (const line of anonymizeFailure) console.error(line);\n if (failure) console.error(chalk.red(`✗ ${failure[0]}`));\n process.exit(1);\n }\n\n if (failure) {\n const [what, state, ...advice] = failure;\n console.error(chalk.red(`✗ ${what}`));\n console.error(chalk.yellow(` ${state}`));\n for (const line of advice) console.error(chalk.gray(` ${line}`));\n process.exit(1);\n }\n\n console.log(chalk.green(\"✓ Local database now holds a copy of \" + describeTarget(source)));\n}\n\n/**\n * Give the restored copy back the privileges `pg_dump` stripped.\n *\n * A pull without this ends on a green tick and hands over a database the\n * application cannot read: `--no-privileges` removes every GRANT, so the copy\n * has the source's RLS policies and none of the grants behind them, and the\n * first query as `rebase_user` fails with `permission denied`. Measured — 68\n * policies and 60 grants in, 68 policies and 0 grants out.\n *\n * `ensureAppRole` is the routine boot runs and `rebase db push` runs, so the\n * pulled database ends up in the state a booted one is in, and there is no\n * second description of these grants to drift. `detectConnectionPosture` gates\n * it the same way `db push` does: a connection that cannot create roles reports\n * that rather than failing the pull, which has already succeeded by this point.\n *\n * Failure here is a warning, not an error. The data is restored and correct; a\n * missing grant is repaired by the next `rebase dev` or `rebase db push`, and\n * saying so beats unwinding a copy that is fine.\n */\nasync function restoreAppRole(target: string): Promise<void> {\n const { Client } = await import(\"pg\");\n const { provisionableSchemas } = await import(\"../dev-db/pull\");\n\n const client = new Client({ connectionString: target });\n client.on(\"error\", () => undefined);\n try {\n // Inside the `try`: a refused connection is the same warning as a\n // refused grant, not an exception past the pull's own verdict. And\n // before the driver is loaded, which there is no point in doing for a\n // database that cannot be reached.\n await client.connect();\n const { detectConnectionPosture, ensureAppRole, REBASE_USER_ROLE } =\n await import(\"@rebasepro/server-postgres\");\n const runSql = async (text: string) => (await client.query(text)).rows as Record<string, unknown>[];\n const posture = await detectConnectionPosture(runSql);\n if (!posture.privileged) {\n console.log(chalk.yellow(\n ` ⚠ Could not re-grant the \"${REBASE_USER_ROLE}\" role — this connection may not create roles.`\n ));\n console.log(chalk.gray(\" The copy has its RLS policies but no privileges behind them;\"));\n console.log(chalk.gray(\" `rebase dev` or `rebase db push` will provision them.\"));\n\n return;\n }\n\n const { rows } = await client.query<{ schema: string }>(\n \"SELECT nspname AS \\\"schema\\\" FROM pg_namespace\"\n );\n const schemas = provisionableSchemas(rows);\n await ensureAppRole(runSql, schemas);\n console.log(chalk.gray(\n ` ✓ Re-granted \"${REBASE_USER_ROLE}\" on ${schemas.length} schema(s) — pg_dump strips privileges.`\n ));\n } catch (error) {\n console.log(chalk.yellow(\n ` ⚠ Restored, but could not re-grant \"rebase_user\": ${error instanceof Error ? error.message : String(error)}`\n ));\n console.log(chalk.gray(\" Run `rebase db push` (or start `rebase dev`) to provision it.\"));\n } finally {\n await client.end().catch(() => undefined);\n }\n}\n\n/**\n * Anonymize the restored copy, and say what happened if that did not work.\n *\n * Returns null when the copy is anonymized, and otherwise the lines that say —\n * in red, because `--anonymize` was the developer saying this data must not\n * arrive as it is — what state the local database is in now: emptied of what\n * could not be anonymized, or, when even that failed, holding real data that\n * has to be deleted before anything else.\n */\nasync function anonymizeTarget(\n target: string,\n source: string,\n kind: DevDatabase[\"kind\"]\n): Promise<string[] | null> {\n const { Client } = await import(\"pg\");\n const { anonymizeCopy } = await import(\"../dev-db/pull\");\n\n const deleteIt = kind === \"managed\"\n ? `Delete it now: ${chalk.cyan(\"rebase db reset --yes\")}`\n : kind === \"docker\"\n ? `Delete it now: ${chalk.cyan(\"docker compose down -v\")}`\n : \"Delete it now: drop the restored tables, or the database, before anything else reads it.\";\n const holdsRealData = (reason: string): string[] => [\n chalk.red(`✗ The copy could not be anonymized: ${reason}`),\n chalk.red.bold(` The local database holds an UN-ANONYMIZED copy of ${source}, personal data included.`),\n chalk.yellow(` ${deleteIt}`)\n ];\n\n const client = new Client({ connectionString: target });\n client.on(\"error\", () => undefined);\n try {\n await client.connect();\n } catch (error) {\n return holdsRealData(error instanceof Error ? error.message : String(error));\n }\n\n try {\n const outcome = await anonymizeCopy(client);\n if (outcome.ok) {\n console.log(chalk.green(` ✓ Anonymized ${outcome.tables.length} table(s).`));\n console.log(chalk.gray(\" Name-based and best-effort: a free-text column may still hold personal data.\"));\n\n return null;\n }\n if (outcome.emptyError !== null) {\n return [...holdsRealData(outcome.error), chalk.red(` Emptying the affected tables failed too: ${outcome.emptyError}`)];\n }\n\n return [\n chalk.red(`✗ The copy could not be anonymized: ${outcome.error}`),\n chalk.yellow(\" Nothing was anonymized — the pass is one transaction — so the tables it would have\"),\n chalk.yellow(\" rewritten were emptied instead, with every row that references them:\"),\n ...(outcome.emptied.length > 0 ? [chalk.gray(` ${outcome.emptied.join(\", \")}`)] : []),\n chalk.gray(` The rest of the copy of ${source} is in place. Fix that error and pull again.`)\n ];\n } finally {\n await client.end().catch(() => undefined);\n }\n}\n\n/**\n * Start the compose database a `db … --docker` was asked to talk to.\n *\n * `--docker` resolved the compose URL and stopped there, so every `db`\n * subcommand carrying it reached a container nobody had started —\n * `ECONNREFUSED 127.0.0.1:5436`, two lines, no diagnosis — including the\n * commands the managed-database refusals send readers to `--docker` for.\n *\n * `rebase dev --docker`'s preflight, called with the compose URL and nothing\n * to push: this is not a schema step, and `rebase db push --docker` is the\n * push. A failure here is reported and not fatal — the command runs and its\n * own connection error follows, which is the same contract `dev` keeps.\n */\nexport async function ensureDockerDatabase(projectRoot: string, rawArgs: readonly string[]): Promise<void> {\n const { ensureDevDatabase } = await import(\"../utils/dev-preflight\");\n const { resolveProjectDatabase } = await import(\"../dev-db/prepare\");\n\n // `--docker` on this command line, or on the last `rebase dev`: a command\n // that follows the remembered choice reaches the same container, so it has\n // to be up for the same reason. Only when that choice is the one that wins —\n // a DATABASE_URL anywhere outranks it, typed flag or not, and then there is\n // nothing to start: `prepareDatabaseEnv` says the flag was ignored.\n const resolved = resolveProjectDatabase(projectRoot, {\n flagUrl: readFlagValue(rawArgs, \"--database-url\"),\n flagDocker: switchOn(rawArgs, \"--docker\")\n });\n if (resolved.kind !== \"docker\") return;\n\n const composeUrl = resolved.url;\n if (!composeUrl) {\n // `prepareDatabaseEnv` raises the full message a moment later; saying\n // it twice would be worse than saying it once, in its own words.\n return;\n }\n\n await ensureDevDatabase({\n projectRoot,\n databaseUrl: composeUrl,\n disabled: false,\n // Never a push. `rebase db push --docker` is one, and it runs next.\n hasCollections: false,\n pushSchema: async () => undefined,\n // stderr, like every notice about which database a command resolved:\n // stdout belongs to the command. On stdout these lines were the first\n // thing `psql \"$(rebase db url)\"`, `DATABASE_URL=\"$(rebase db url)\"`\n // and `rebase console -e … | jq` read, whenever the container had to\n // be started first.\n log: message => console.error(message)\n });\n}\n\n/**\n * You cannot delete the branch you are standing on.\n *\n * Not a new rule — it was always refused, by a message about a database the\n * developer had never named. After `switch feature_x` the resolved DSN *is*\n * `rb_feature_x`, so `BranchService.deleteBranch` compared it against the\n * connected database, found them equal, and answered `✗ Cannot delete the main\n * database.` The main database is precisely what the developer was not on.\n *\n * Answered here because the pointer is the CLI's: the driver runs as a child\n * process that has never heard of it, and cannot tell \"the branch you are on\"\n * from \"the main database\" — those are the same connection string to it.\n */\nasync function refuseDeletingActiveBranch(projectRoot: string, rawArgs: readonly string[]): Promise<void> {\n const [, , , name] = commandWords(rawArgs, \"db\");\n if (!name) return;\n\n const { readActiveBranch } = await import(\"../dev-db/branch-pointer\");\n const active = readActiveBranch(projectRoot);\n if (active?.name !== name) return;\n\n const off = \"rebase db branch switch --off\";\n const del = `rebase db branch delete ${name}`;\n const column = Math.max(off.length, del.length) + 4;\n\n console.error(\"\");\n console.error(chalk.red(`✗ You are on branch \"${name}\" — leave it before deleting it.`));\n console.error(\"\");\n console.error(chalk.gray(` Every database command in this checkout is pointed at ${active.database},`));\n console.error(chalk.gray(\" including this one, so the delete would be asking that database to drop\"));\n console.error(chalk.gray(\" itself.\"));\n console.error(\"\");\n console.error(` ${chalk.cyan(off)}${\" \".repeat(column - off.length)}back to the main database`);\n console.error(` ${chalk.cyan(del)}${\" \".repeat(column - del.length)}then this works`);\n console.error(\"\");\n process.exit(1);\n}\n\n/**\n * The variable that tells the driver which database this checkout is switched\n * to. Spelled the same in `packages/server-postgres/src/branch-prune.ts`.\n */\nconst ACTIVE_BRANCH_DATABASE_ENV = \"REBASE_ACTIVE_BRANCH_DATABASE\";\n\n/**\n * Tell the driver which branch this checkout is on, for the two actions that\n * answer differently for it.\n *\n * - `prune` keeps it, as `delete` refuses it. `prune --older-than 0d --yes`\n * dropped it, and the checkout then pointed every command at a database\n * that no longer existed, with no word of `switch --off`.\n * - `list` marks it, where every branch had the same bullet.\n *\n * The pointer is the CLI's and the driver is a child process, so it is told\n * the database in its environment.\n */\nasync function tellDriverTheActiveBranch(projectRoot: string): Promise<void> {\n const { readActiveBranch } = await import(\"../dev-db/branch-pointer\");\n const active = readActiveBranch(projectRoot);\n if (active) process.env[ACTIVE_BRANCH_DATABASE_ENV] = active.database;\n else delete process.env[ACTIVE_BRANCH_DATABASE_ENV];\n}\n\n/** The `branch` actions that read or write the registry — every one but `switch`. */\nconst REGISTRY_ACTIONS = new Set([\"list\", \"create\", \"delete\", \"info\", \"prune\"]);\n\n/**\n * Every `branch` action runs against the parent, where the registry lives.\n *\n * `rebase.branches` is written in the database branches are made *from*, and a\n * branch is a `CREATE DATABASE … TEMPLATE` copy — so the copy carries a\n * snapshot of that table taken at branch time, and every branch made since is\n * missing from it. After `switch feature_x`, `branch list` connected to\n * `rb_feature_x` and answered `No branches found. Create one with: rebase db\n * branch create <name>` while `branch switch` with no argument, one command\n * earlier, had said `● On branch feature_x`.\n *\n * The same snapshot answered `create`, `delete`, `info` and `prune`: a branch\n * created from a switched checkout was recorded only in the copy, so `list`\n * never showed it and `delete` from the main checkout said \"not found\" while\n * its database stayed; `info` and `delete` could not find a branch made after\n * the one this checkout is on. The Branches pane in Studio was fixed the same\n * way (`REBASE_BRANCH_PARENT_DATABASE`).\n *\n * `create` still copies what this checkout is on — a branch of the branch, a\n * thing the developer asked for by switching first — so it is given\n * `--from <the branch's database>` unless it names a source itself.\n *\n * Resolved with `branch: null` — the same rule `switch` uses to find what to\n * branch *from* — and relayed as `--database-url`, which the driver honours\n * over anything it would resolve for itself.\n */\nasync function onParentDatabase(projectRoot: string, rawArgs: string[], action: string): Promise<string[]> {\n // An explicit `--database-url` is the developer naming the database; this\n // never overrides one.\n if (readFlagValue(rawArgs, \"--database-url\") !== null) return rawArgs;\n\n const { readActiveBranch } = await import(\"../dev-db/branch-pointer\");\n const active = readActiveBranch(projectRoot);\n if (!active) return rawArgs;\n\n const { readEnvFile } = await import(\"../utils/project\");\n const { resolveDevDatabase } = await import(\"../dev-db/resolve\");\n const { resolveComposeUrl } = await import(\"../dev-db/prepare\");\n\n const { readLastDevDocker } = await import(\"../dev-db/last-dev-database\");\n\n const envFile = readEnvFile(projectRoot);\n const parent = resolveDevDatabase({\n flagDocker: switchOn(rawArgs, \"--docker\"),\n lastDevDocker: readLastDevDocker(projectRoot),\n env: process.env,\n envFile,\n branch: null,\n composeUrl: resolveComposeUrl(projectRoot, envFile)\n });\n const url = (parent.kind === \"managed\" ? null : parent.url)?.trim();\n if (!url) return rawArgs;\n\n // stderr, like every notice about which database a command resolved:\n // stdout belongs to the command. `branch list --json` printed this on\n // stdout, ahead of whatever followed.\n console.error(chalk.gray(` ● On branch ${active.name} — using the main database, where the branch registry lives.`));\n\n const from = action === \"create\" && readFlagValue(rawArgs, \"--from\") === null\n ? [\"--from\", active.database]\n : [];\n\n return [...rawArgs, ...from, \"--database-url\", url];\n}\n\n/**\n * The flags `rebase db branch switch` takes, the relayed database flags and\n * `--debug` included.\n */\nconst SWITCH_FLAGS = {\n \"--off\": Boolean,\n \"--main\": Boolean,\n \"--database-url\": String,\n \"--docker\": Boolean,\n \"--debug\": Boolean\n} satisfies arg.Spec;\n\n/** The long flags in {@link SWITCH_FLAGS}, for the did-you-mean. */\nconst SWITCH_FLAG_NAMES: readonly string[] = Object.keys(SWITCH_FLAGS);\n\n/**\n * Refuse a flag `switch` does not take, naming the one it was probably meant to be.\n *\n * `switch` is answered here, never by the driver, so the driver's strict\n * branch flags do not reach it: `rebase db branch switch --of` reported the\n * current branch, exit 0, instead of leaving it.\n */\nexport function assertSwitchFlags(rawArgs: readonly string[]): void {\n for (const word of rawArgs.slice(2)) {\n if (!word.startsWith(\"-\")) continue;\n // The flag part only: a value given inline, or quoted into the same\n // argument after a space, may be a connection string.\n const flag = word.split(/[=\\s]/)[0];\n if (SWITCH_FLAG_NAMES.includes(flag)) continue;\n const near = suggestCommand(flag.replace(/^-+/, \"\"), SWITCH_FLAG_NAMES.map(known => known.slice(2)));\n throw new UsageError(\n `\\`rebase db branch switch\\` has no option ${flag}` +\n (near ? ` — did you mean --${near}?` : \" — it takes --off (or --main) and a branch name.\") +\n \" Nothing was run. See `rebase db branch --help`.\"\n );\n }\n // Every flag `switch` takes but `--database-url` is a switch: `=true` or\n // `=1` turns one on, `=false` or `=0` leaves it off, and nothing else is\n // read. `--off=false` is not \"leave\".\n resolveSwitchValues(SWITCH_FLAGS, rawArgs.slice(2), \"db branch switch\");\n}\n\n/**\n * What `switch` cannot change: a `rebase dev` started before it connected to\n * the database it was given then, and serves it until it is restarted.\n */\nconst RUNNING_DEV_KEEPS_ITS_DATABASE =\n \"A `rebase dev` that is already running keeps the database it started on until you restart it.\";\n\n/**\n * `rebase db branch switch <name>` — point this checkout at a branch.\n *\n * The step branching was missing. `create` copied the database in about a\n * second and then printed `Database: rb_feature_auth` and stopped: there was no\n * `switch`, no `--branch` on `rebase dev`, and no `REBASE_BRANCH`. The only way\n * to use a branch was to hand-edit `DATABASE_URL`, while the documentation said\n * \"the CLI updates your local development configuration\" — it did not, and the\n * `.env` was byte-identical afterwards.\n *\n * Three things it insists on:\n *\n * - **The branch has to exist.** Writing a pointer to a database that was never\n * created turns a typo into a connection error on the *next* command, which\n * is the one place it cannot be explained. Checked against\n * `rebase.branches` and `pg_database` both, because a branch dropped outside\n * Rebase leaves the metadata row behind.\n *\n * - **It says what changed, and how to undo it.** A command that silently\n * redirects every subsequent database operation owes the reader the database\n * name it moved to and the words that move it back.\n *\n * - **It never edits `.env`.** See `branch-pointer.ts`.\n */\nasync function switchBranch(projectRoot: string, rawArgs: readonly string[]): Promise<void> {\n assertSwitchFlags(rawArgs);\n\n const { branchDatabaseName, clearActiveBranch, databaseNameOf, readActiveBranch, writeActiveBranch } =\n await import(\"../dev-db/branch-pointer\");\n const { readEnvFile } = await import(\"../utils/project\");\n const { resolveDevDatabase } = await import(\"../dev-db/resolve\");\n const { resolveComposeUrl } = await import(\"../dev-db/prepare\");\n const { readLastDevDocker } = await import(\"../dev-db/last-dev-database\");\n\n // Read as a flag rather than as the name in the third position, so\n // `switch --off` and `switch feature --off` mean the same thing. The doc\n // verifier reads a command's flags out of exactly this shape, which is the\n // other reason: a flag it cannot see is one it reports as unrunnable in\n // every page that documents it.\n const goingOff = switchOn(rawArgs, \"--off\") || switchOn(rawArgs, \"--main\");\n\n // [\"db\", \"branch\", \"switch\", <name>], with any flags taken back out —\n // `rebase --debug db branch switch feature` read the name as \"switch\".\n const name = commandWords(rawArgs, \"db\")[3];\n\n // The database to branch from, resolved by the ordered rule every sibling\n // uses. This read `readEnvFile(projectRoot).DATABASE_URL` and nothing else,\n // so `export DATABASE_URL=…; rebase db branch create x` created a branch and\n // `rebase db branch switch x` then answered \"This project has no\n // DATABASE_URL, so there is no database to branch from\" — about a project\n // that had one, in the shell, where `branching.md` documents it as rule (2)\n // and `create` had just read it.\n //\n // `branch: null`, deliberately: this command is what sets the pointer, and\n // the pointer that exists must never become the base of the next switch —\n // that is how a branch of a branch of a branch happens by accident.\n const envFile = readEnvFile(projectRoot);\n const resolved = resolveDevDatabase({\n flagUrl: readFlagValue(rawArgs, \"--database-url\"),\n flagDocker: switchOn(rawArgs, \"--docker\"),\n lastDevDocker: readLastDevDocker(projectRoot),\n env: process.env,\n envFile,\n branch: null,\n composeUrl: resolveComposeUrl(projectRoot, envFile)\n });\n const base = (resolved.kind === \"managed\" ? null : resolved.url)?.trim() || undefined;\n\n // `switch` with no argument reports rather than changes. \"Which branch am I\n // on\" is asked far more often than \"move me\", and answering it should not\n // require guessing a flag.\n if (!name && !goingOff) {\n const active = readActiveBranch(projectRoot);\n console.log(\"\");\n if (active) {\n console.log(` ${chalk.green(\"●\")} On branch ${chalk.bold(active.name)} ${chalk.gray(`(${active.database})`)}`);\n console.log(chalk.gray(` Back to the main database: ${chalk.cyan(\"rebase db branch switch --off\")}`));\n } else {\n const main = base ? databaseNameOf(base) : null;\n console.log(` ${chalk.gray(\"●\")} On the main database${main ? chalk.gray(` (${main})`) : \"\"}`);\n console.log(chalk.gray(` Switch to a branch: ${chalk.cyan(\"rebase db branch switch <name>\")}`));\n }\n console.log(\"\");\n\n return;\n }\n\n if (goingOff) {\n const active = readActiveBranch(projectRoot);\n clearActiveBranch(projectRoot);\n console.log(\"\");\n console.log(active\n ? chalk.green(` ✓ Back on the main database${base ? ` (${databaseNameOf(base)})` : \"\"}.`)\n : chalk.gray(\" Already on the main database.\"));\n if (active) console.log(chalk.gray(` ${RUNNING_DEV_KEEPS_ITS_DATABASE}`));\n console.log(\"\");\n\n return;\n }\n\n if (!base) {\n console.error(chalk.red(\"✗ There is no database to branch from.\"));\n console.error(chalk.gray(resolved.kind === \"managed\"\n ? \" This project is on the managed development database, which serves exactly one —\"\n : \" --docker needs a docker-compose.yml with a db service, and this project has none —\"));\n console.error(chalk.gray(\" and branching copies a database. Set DATABASE_URL in .env or in your\"));\n console.error(chalk.gray(\" shell, or run `rebase dev --docker`.\"));\n process.exit(1);\n }\n\n const database = branchDatabaseName(name);\n\n // First, as every `branch` action the driver runs does: a database a\n // killed `create --force` left closed is opened again, and said.\n const { reopenClosedDatabases, reopenedDatabasesNotice } = await import(\"@rebasepro/server-postgres\");\n const healed = await reopenClosedDatabases(base, [readActiveBranch(projectRoot)?.database]);\n for (const line of reopenedDatabasesNotice(healed)) console.error(chalk.yellow(` ${line}`));\n\n // Verified before the pointer is written, not after.\n const { Client } = await import(\"pg\");\n const client = new Client({ connectionString: base });\n try {\n await client.connect();\n } catch (error) {\n console.error(chalk.red(`✗ Could not reach the database to check that branch \"${name}\" exists.`));\n console.error(chalk.gray(` ${error instanceof Error ? error.message : String(error)}`));\n process.exit(1);\n }\n try {\n const { rows } = await client.query<{ registered: boolean; present: boolean }>(\n `SELECT EXISTS (SELECT 1 FROM rebase.branches WHERE name = $1) AS registered,\n EXISTS (SELECT 1 FROM pg_database WHERE datname = $2) AS present`,\n [name, database]\n ).catch(() => ({ rows: [{ registered: false, present: false }] }));\n\n const { registered, present } = rows[0] ?? { registered: false, present: false };\n if (!present) {\n console.error(chalk.red(`✗ Branch \"${name}\" does not exist.`));\n console.error(registered\n // The metadata row outlives a database dropped with plain SQL.\n ? chalk.gray(` It is registered but its database (${database}) is gone — someone dropped it outside Rebase.`)\n : chalk.gray(` ${chalk.cyan(\"rebase db branch list\")} shows the ones that do.`));\n process.exit(1);\n }\n } finally {\n await client.end();\n }\n\n writeActiveBranch(projectRoot, { name, database });\n\n console.log(\"\");\n console.log(chalk.green(` ✓ Switched to branch \"${name}\".`));\n console.log(chalk.gray(` Database: ${database}`));\n console.log(chalk.gray(\" Every rebase command in this checkout now uses it — dev, db push, migrate.\"));\n console.log(chalk.gray(` ${RUNNING_DEV_KEEPS_ITS_DATABASE}`));\n console.log(chalk.gray(` Back to the main database: ${chalk.cyan(\"rebase db branch switch --off\")}`));\n console.log(\"\");\n}\n\n/**\n * What each `rebase db <action>` does and takes.\n *\n * Kept here rather than delegated to the driver because the driver is reached\n * by *running* it — which is exactly what `--help` must not do. The page is\n * deliberately short: the authority on a flag is the command's own spec, and\n * `check-doc-commands.mjs` holds every command written in this repository's\n * markdown to it. What a reader needs from here is which subcommands exist and\n * what the destructive ones want before they will run.\n */\n/** The database flags every driver command takes; `db url --help` has its own wording. */\nconst DATABASE_FLAGS_HELP =\n \"--database-url <url> names the database; --docker uses the compose one, starting it if needed.\";\n\nconst DB_ACTION_HELP: Record<string, { usage: string; summary: string; notes?: string[] }> = {\n push: {\n usage: \"rebase db push [--collections <dir>] [--dry-run] [--allow-destructive] [--yes]\",\n summary: \"Apply the schema straight to the database. Development only — it does not write a migration.\",\n notes: [\n \"--dry-run prints the SQL and applies nothing. Read it before you approve it.\",\n \"A change that drops data, or re-keys a table (every row gets a new id), needs --allow-destructive.\",\n `--collections <dir>: ${COLLECTIONS_FLAG_HELP}.`,\n DATABASE_FLAGS_HELP\n ]\n },\n generate: {\n usage: \"rebase db generate [--collections <dir>]\",\n summary: \"Generate the Drizzle schema, the Postgres DDL and a SQL migration file from the collections.\",\n notes: [\n \"A migration that drops or narrows data is named when it is written. It is still written.\",\n `--collections <dir>: ${COLLECTIONS_FLAG_HELP}.`,\n DATABASE_FLAGS_HELP\n ]\n },\n migrate: {\n usage: \"rebase db migrate [--baseline <version>] [--refuse-destructive] [amount]\",\n summary: \"Run the pending migration files against the database.\",\n notes: [\n \"--refuse-destructive dry-runs the pending files and applies nothing when one drops or narrows data.\",\n \"--baseline <version> records that version as already applied and starts from the next one.\",\n \"It is what a database Rebase has already booted against needs: boot ensures the schema, so the first migration would try to create tables that are already there.\",\n \"The version is the numeric prefix of a file in drizzle/migrations.\",\n DATABASE_FLAGS_HELP\n ]\n },\n branch: {\n // Every action the dispatch answers and every flag its specs declare.\n // The page is kept here rather than delegated because reaching the\n // driver's own `printBranchHelp` means *running* the driver, which is\n // what `--help` must not do — so `help-coverage.test.ts` holds the two\n // to each other instead. It went two releases without learning `prune`,\n // `--from`, `--force` or `--older-than`, all four of which the dispatch\n // answers and the docs teach.\n usage: \"rebase db branch <create|list|switch|delete|info|prune> [name]\",\n summary: \"Database branching.\",\n notes: [\n \"create <name> [--from <source>] copies an existing database, files and all.\",\n \"switch <name> points this checkout at a branch; every later command uses it.\",\n \"switch with no name reports where you are; switch --off returns to the main database.\",\n \"prune [--older-than <14|14d|2w>] removes branches nothing is using, and the entries that drifted.\",\n \"prune --include-dev-diff also removes the Atlas scratch databases `db push` leaves behind.\",\n \"prune asks before it drops anything; --yes, -y answers for you, which is the form a CI job wants.\",\n \"--force disconnects other sessions first — Postgres refuses to copy or drop a database anything is connected to, usually your own `rebase dev`.\"\n ]\n },\n backup: {\n usage: \"rebase db backup [--out <path|s3://…>]\",\n summary: \"Create a pg_dump backup. --out is resolved against the directory you are standing in.\",\n notes: [\n \"--output is accepted as an alias, as it is on `rebase build`.\",\n \"`rebase db backup list` lists them, the way `rebase cloud db backup list` does.\"\n ]\n },\n backups: {\n usage: \"rebase db backups list [--out <path|s3://…>]\",\n summary: \"List stored backups.\",\n notes: [\"`rebase db backup list` is the same command, spelled the cloud family's way.\"]\n },\n url: {\n usage: \"rebase db url [--database-url <url>] [--docker]\",\n summary: \"Print the connection string this project uses. Nothing else goes to stdout, so it pipes.\",\n notes: [\n \"psql \\\"$(rebase db url)\\\"\",\n \"Starts the managed database if it is not already running.\",\n \"--database-url and --docker answer for the database `rebase dev` would pick with the same flag.\",\n \"After `rebase dev --docker` it prints the Docker database without the flag, as every db command does.\"\n ]\n },\n restore: {\n usage: \"rebase db restore <dump> [--target-db <name>] [--create-db] [--clean] [--yes]\",\n summary: \"Restore a backup with pg_restore.\",\n notes: [\n \"Destructive: on a terminal it asks first, and with no terminal it refuses without --yes.\",\n \"Into a database that already holds what the backup creates, it needs --clean, and changes nothing without it.\"\n ]\n },\n pull: {\n usage: \"rebase db pull --from <url> [--schema <name>] [--anonymize] [--yes]\",\n summary: \"Copy another database into local development. One-directional by design — it can never push.\",\n notes: [\n \"--anonymize overwrites personal-looking columns after the copy. A misspelt flag is refused, never ignored.\",\n \"--schema <name> copies only that schema; repeat it for more.\",\n \"--docker pulls into Postgres in Docker rather than the database `rebase dev` would pick.\",\n \"The target is not selectable: --database-url is refused, so this can never write to a remote database.\"\n ]\n },\n stop: { usage: \"rebase db stop\", summary: \"Stop the managed development database. Data is kept.\" },\n reset: {\n usage: \"rebase db reset [--yes]\",\n summary: \"Delete the managed development database and start over.\",\n notes: [\"Destructive, and the data exists only on this machine.\"]\n }\n};\n\n/** Every subcommand the family dispatches — the help table's keys. */\nexport const DB_SUBCOMMANDS = Object.keys(DB_ACTION_HELP);\n\nfunction printDbHelp(action?: string) {\n const entry = action ? DB_ACTION_HELP[action] : undefined;\n if (entry) {\n console.log(`\n${chalk.bold(`rebase db ${action}`)}\n\n ${entry.summary}\n\n${chalk.green.bold(\"Usage\")}\n ${chalk.blue(entry.usage)}\n${entry.notes?.length ? `\\n${chalk.green.bold(\"Notes\")}\\n${entry.notes.map(n => ` ${chalk.gray(`• ${n}`)}`).join(\"\\n\")}\\n` : \"\"}\n${chalk.gray(\"Run `rebase db --help` for every subcommand.\")}\n`);\n return;\n }\n\n console.log(`\n${chalk.bold(\"rebase db\")} — Database management commands\n\n${chalk.green.bold(\"Usage\")}\n rebase db ${chalk.blue(\"<command>\")} [options]\n\n${chalk.green.bold(\"Commands\")}\n ${chalk.gray(\"(Commands are provided by your active database driver plugin)\")}\n ${chalk.blue.bold(\"url\")} Print the connection string this project uses (pipes into psql)\n ${chalk.blue.bold(\"pull\")} Copy another database into local dev (--from <url>, --anonymize)\n ${chalk.blue.bold(\"stop\")} Stop the managed development database (data is kept)\n ${chalk.blue.bold(\"reset\")} Delete the managed development database and start over\n ${chalk.blue.bold(\"push\")} Apply schema directly to database (development)\n ${chalk.blue.bold(\"generate\")} Generate migration files\n ${chalk.blue.bold(\"migrate\")} Run pending migrations\n ${chalk.blue.bold(\"branch\")} Database branching (create, list, switch, delete, info, prune)\n ${chalk.blue.bold(\"backup\")} Create a backup with pg_dump (--out <path|s3://…>)\n ${chalk.blue.bold(\"restore\")} Restore a backup with pg_restore (destructive; asks, or --yes)\n ${chalk.blue.bold(\"backups\")} List stored backups (db backup list is the same)\n\n${chalk.green.bold(\"Examples\")}\n${dbExamples(devDatabaseKind())}\n ${chalk.gray(\"# Back up to a local directory, then to object storage\")}\n rebase db backup --out ./backups\n rebase db backup --out s3://my-private-bucket/backups\n\n ${chalk.gray(\"# Restore into a fresh database (safe: does not touch the live one)\")}\n rebase db restore ./backups/rebase-app-20260714T030000Z.dump --create-db --target-db app_restored\n`);\n}\n\n/**\n * The examples, which are not the same on the managed development database.\n *\n * Every one of the four the help used to lead with — `db push`, `db generate`,\n * `db migrate`, `db branch` — is refused there, by guards in this same file\n * that explain exactly why. So on the project the CLI had just scaffolded, the\n * first thing `rebase db --help` offered was a command that answers with a\n * refusal, and the reader's most likely conclusion is that their install is\n * broken.\n *\n * Exported for its test.\n */\nexport function dbExamples(kind: DevDatabase[\"kind\"] | null): string {\n if (kind === \"managed\") {\n return ` ${chalk.gray(\"# Quick development workflow (this project is on the managed database)\")}\n rebase schema generate\n rebase dev ${chalk.gray(\"# boot applies your collections to it, additively\")}\n rebase db push ${chalk.gray(\"# also drops, renames and narrows columns\")}\n\n ${chalk.gray(\"# branch needs a Postgres of your own\")}\n rebase dev --docker ${chalk.gray(\"# starts one; or uncomment DATABASE_URL in .env\")}\n\n`;\n }\n\n return ` ${chalk.gray(\"# Quick development workflow\")}\n rebase schema generate && rebase db push\n\n ${chalk.gray(\"# Production migration workflow\")}\n rebase db generate\n rebase db migrate\n\n ${chalk.gray(\"# Create a database branch and work on it\")}\n rebase db branch create feature_auth\n rebase db branch switch feature_auth\n rebase db branch switch --off\n\n`;\n}\n"],"mappings":"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"}