@rebasepro/cli 0.25.0-canary.ge06257e → 0.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/bin/rebase.js +9 -5
  2. package/dist/{agent-setup-C83DXnlx.js → agent-setup-BYb2Tbdz.js} +2 -2
  3. package/dist/{agent-setup-C83DXnlx.js.map → agent-setup-BYb2Tbdz.js.map} +1 -1
  4. package/dist/{api-keys-Bc4FJKYp.js → api-keys-CSMbsmAn.js} +28 -22
  5. package/dist/api-keys-CSMbsmAn.js.map +1 -0
  6. package/dist/{apps-wG-ZTryA.js → apps-iBXNZhVN.js} +6 -7
  7. package/dist/{apps-wG-ZTryA.js.map → apps-iBXNZhVN.js.map} +1 -1
  8. package/dist/{atlas-dev-database-DeK3Sa4h.js → atlas-dev-database-BusbHP6n.js} +4 -4
  9. package/dist/{atlas-dev-database-DeK3Sa4h.js.map → atlas-dev-database-BusbHP6n.js.map} +1 -1
  10. package/dist/{auth-BL7bNQVu.js → auth-DRsTWPky.js} +77 -11
  11. package/dist/auth-DRsTWPky.js.map +1 -0
  12. package/dist/{branch-pointer-DTQNLFtb.js → branch-pointer-Bn_FjNld.js} +1 -1
  13. package/dist/{build-h_7Re-67.js → build-et7Rccxi.js} +6 -7
  14. package/dist/{build-h_7Re-67.js.map → build-et7Rccxi.js.map} +1 -1
  15. package/dist/{bundle-CqURVN-K.js → bundle-DlqkDYSe.js} +6 -21
  16. package/dist/bundle-DlqkDYSe.js.map +1 -0
  17. package/dist/{cloud-DVV_5GPG.js → cloud-B-ZIjHrA.js} +10 -11
  18. package/dist/{cloud-DVV_5GPG.js.map → cloud-B-ZIjHrA.js.map} +1 -1
  19. package/dist/commands/api-keys.d.ts +4 -1
  20. package/dist/commands/auth.d.ts +3 -2
  21. package/dist/commands/dev.d.ts +12 -0
  22. package/dist/commands/generate_sdk.d.ts +4 -2
  23. package/dist/commands/init.d.ts +20 -0
  24. package/dist/commands/start.d.ts +10 -0
  25. package/dist/commands/upgrade.d.ts +12 -0
  26. package/dist/connection-banner-DbLJzWf4.js +128 -0
  27. package/dist/connection-banner-DbLJzWf4.js.map +1 -0
  28. package/dist/{consent-ClRHmcxf.js → consent-BaB-eQKG.js} +2 -2
  29. package/dist/{consent-ClRHmcxf.js.map → consent-BaB-eQKG.js.map} +1 -1
  30. package/dist/{console-Dw3HLdUs.js → console-BlD9kjFW.js} +4 -4
  31. package/dist/{console-Dw3HLdUs.js.map → console-BlD9kjFW.js.map} +1 -1
  32. package/dist/{context-BM-oOMNX.js → context-DHiiiJ5C.js} +3 -4
  33. package/dist/context-DHiiiJ5C.js.map +1 -0
  34. package/dist/{daemon-CknkDjd6.js → daemon-DDMRbz4T.js} +160 -5
  35. package/dist/daemon-DDMRbz4T.js.map +1 -0
  36. package/dist/{daemon-entry-C6pxdily.js → daemon-entry-zOC1revO.js} +204 -5
  37. package/dist/daemon-entry-zOC1revO.js.map +1 -0
  38. package/dist/{db-Dkn9XhT-.js → db-9P6MnmdC.js} +237 -86
  39. package/dist/db-9P6MnmdC.js.map +1 -0
  40. package/dist/{derive-Dl0z2OWi.js → derive-MTdClnkc.js} +29 -14
  41. package/dist/{derive-Dl0z2OWi.js.map → derive-MTdClnkc.js.map} +1 -1
  42. package/dist/{dev-DAcZR4Pp.js → dev-BDN_OKXA.js} +183 -23
  43. package/dist/dev-BDN_OKXA.js.map +1 -0
  44. package/dist/dev-db/connection-banner.d.ts +47 -0
  45. package/dist/dev-db/daemon.d.ts +41 -0
  46. package/dist/dev-db/notification-proxy.d.ts +82 -1
  47. package/dist/dev-db/pull.d.ts +33 -5
  48. package/dist/dev-db/state.d.ts +9 -0
  49. package/dist/{dev-preflight-CorMg7Ub.js → dev-preflight-FT9GbJVj.js} +73 -4
  50. package/dist/dev-preflight-FT9GbJVj.js.map +1 -0
  51. package/dist/{dev-server-B1UYifZJ.js → dev-server-CIZwAfZa.js} +14 -3
  52. package/dist/dev-server-CIZwAfZa.js.map +1 -0
  53. package/dist/{doctor-Ds_lzc9p.js → doctor-D8YXz7df.js} +6 -6
  54. package/dist/doctor-D8YXz7df.js.map +1 -0
  55. package/dist/{eject-CJHkfnat.js → eject-izG2KjMo.js} +3 -4
  56. package/dist/{eject-CJHkfnat.js.map → eject-izG2KjMo.js.map} +1 -1
  57. package/dist/{fold-static-BC9CYicw.js → fold-static-CybSay_W.js} +3 -3
  58. package/dist/{fold-static-BC9CYicw.js.map → fold-static-CybSay_W.js.map} +1 -1
  59. package/dist/{generate_sdk-kfkZmG-d.js → generate_sdk-B4R65oUV.js} +22 -12
  60. package/dist/generate_sdk-B4R65oUV.js.map +1 -0
  61. package/dist/index.es.js +36 -37
  62. package/dist/index.es.js.map +1 -1
  63. package/dist/{init-CjoJoThg.js → init-DYaeppEN.js} +52 -63
  64. package/dist/init-DYaeppEN.js.map +1 -0
  65. package/dist/invoked-command-CG_rIa_o.js +55 -0
  66. package/dist/invoked-command-CG_rIa_o.js.map +1 -0
  67. package/dist/last-dev-database-B_75fxZC.js +2 -0
  68. package/dist/{manifest-DRp0UVTj.js → manifest-nvPdLlJY.js} +2 -2
  69. package/dist/{manifest-DRp0UVTj.js.map → manifest-nvPdLlJY.js.map} +1 -1
  70. package/dist/{normalize-imports-BHxL2d05.js → normalize-imports-BYw8ad87.js} +3 -3
  71. package/dist/{normalize-imports-BHxL2d05.js.map → normalize-imports-BYw8ad87.js.map} +1 -1
  72. package/dist/precompress.d.ts +0 -7
  73. package/dist/{prepare-C1iaiTC4.js → prepare-1rVNd2PF.js} +7 -6
  74. package/dist/prepare-1rVNd2PF.js.map +1 -0
  75. package/dist/project-g4K6kV1t.js +701 -0
  76. package/dist/project-g4K6kV1t.js.map +1 -0
  77. package/dist/{pull-COpNJFzY.js → pull-DDMpsZ5r.js} +143 -63
  78. package/dist/pull-DDMpsZ5r.js.map +1 -0
  79. package/dist/refusal-ReeeGP8a.js +26 -0
  80. package/dist/refusal-ReeeGP8a.js.map +1 -0
  81. package/dist/resolve-BQUAC3Wi.js +2 -0
  82. package/dist/resources/derive.d.ts +9 -0
  83. package/dist/{resources-CLm6g0br.js → resources-CovP8AZ-.js} +4 -5
  84. package/dist/{resources-CLm6g0br.js.map → resources-CovP8AZ-.js.map} +1 -1
  85. package/dist/{schema-BKdh6UoE.js → schema-nuxvvc50.js} +5 -6
  86. package/dist/{schema-BKdh6UoE.js.map → schema-nuxvvc50.js.map} +1 -1
  87. package/dist/{skills-DEhYiPeO.js → skills-DeUIsZcT.js} +3 -4
  88. package/dist/{skills-DEhYiPeO.js.map → skills-DeUIsZcT.js.map} +1 -1
  89. package/dist/{start-BsPJedPQ.js → start-RzZqDroW.js} +20 -7
  90. package/dist/start-RzZqDroW.js.map +1 -0
  91. package/dist/{state-CCB-FAQ9.js → state-CYdBvnwA.js} +3 -2
  92. package/dist/state-CYdBvnwA.js.map +1 -0
  93. package/dist/{status-D_B3tlDy.js → status-D9Zm88NZ.js} +11 -12
  94. package/dist/{status-D_B3tlDy.js.map → status-D9Zm88NZ.js.map} +1 -1
  95. package/dist/{storage-CtB8polS.js → storage-BB3umRfw.js} +3 -4
  96. package/dist/{storage-CtB8polS.js.map → storage-BB3umRfw.js.map} +1 -1
  97. package/dist/{telemetry-EMFRVRQi.js → telemetry-HfU5uAh1.js} +2 -2
  98. package/dist/{telemetry-EMFRVRQi.js.map → telemetry-HfU5uAh1.js.map} +1 -1
  99. package/dist/{telemetry-BYmPU-Ji.js → telemetry-TseNLk6X.js} +4 -4
  100. package/dist/{telemetry-BYmPU-Ji.js.map → telemetry-TseNLk6X.js.map} +1 -1
  101. package/dist/{upgrade-DbuKX9lv.js → upgrade-apiPKKE_.js} +29 -6
  102. package/dist/{upgrade-DbuKX9lv.js.map → upgrade-apiPKKE_.js.map} +1 -1
  103. package/dist/utils/args.d.ts +45 -3
  104. package/dist/utils/boot-retry.d.ts +41 -0
  105. package/dist/utils/dev-preflight.d.ts +34 -1
  106. package/dist/utils/dev-server.d.ts +11 -0
  107. package/dist/utils/project.d.ts +5 -1
  108. package/dist/utils/redact.d.ts +10 -0
  109. package/dist/utils/refusal.d.ts +18 -0
  110. package/dist/utils/unknown-command.d.ts +4 -0
  111. package/package.json +7 -7
  112. package/templates/overlays/baas/README.md +2 -1
  113. package/templates/resource-graphs/blank.json +25 -0
  114. package/templates/resource-graphs/blog.json +28 -0
  115. package/templates/resource-graphs/ecommerce.json +28 -0
  116. package/templates/resource-graphs/headless.json +22 -0
  117. package/templates/template/.env.example +11 -4
  118. package/templates/template/frontend/src/App.tsx +10 -9
  119. package/templates/template/frontend/vite.config.ts +7 -73
  120. package/dist/api-keys-Bc4FJKYp.js.map +0 -1
  121. package/dist/args-CcBphFdj.js +0 -237
  122. package/dist/args-CcBphFdj.js.map +0 -1
  123. package/dist/auth-BL7bNQVu.js.map +0 -1
  124. package/dist/bundle-CqURVN-K.js.map +0 -1
  125. package/dist/context-BM-oOMNX.js.map +0 -1
  126. package/dist/daemon-CknkDjd6.js.map +0 -1
  127. package/dist/daemon-entry-C6pxdily.js.map +0 -1
  128. package/dist/db-Dkn9XhT-.js.map +0 -1
  129. package/dist/dev-DAcZR4Pp.js.map +0 -1
  130. package/dist/dev-preflight-CorMg7Ub.js.map +0 -1
  131. package/dist/dev-server-B1UYifZJ.js.map +0 -1
  132. package/dist/doctor-Ds_lzc9p.js.map +0 -1
  133. package/dist/generate_sdk-kfkZmG-d.js.map +0 -1
  134. package/dist/init-CjoJoThg.js.map +0 -1
  135. package/dist/last-dev-database-BEBPfAMY.js +0 -2
  136. package/dist/prepare-C1iaiTC4.js.map +0 -1
  137. package/dist/project-Wp2zoyeN.js +0 -349
  138. package/dist/project-Wp2zoyeN.js.map +0 -1
  139. package/dist/pull-COpNJFzY.js.map +0 -1
  140. package/dist/resolve-b_p9bmdH.js +0 -2
  141. package/dist/start-BsPJedPQ.js.map +0 -1
  142. package/dist/state-CCB-FAQ9.js.map +0 -1
package/bin/rebase.js CHANGED
@@ -182,11 +182,15 @@ const { entry } = await import("../dist/index.es.js");
182
182
  * `--debug`/`REBASE_DEBUG`, because when the message is *not* enough that is
183
183
  * the only thing that helps.
184
184
  *
185
- * With one exception: a *usage* error. `rebase status extra` has no stack worth
185
+ * With two exceptions. A *usage* error: `rebase status extra` has no stack worth
186
186
  * reading — it points at `arg` and `utils/args.ts` — and the hint suggests
187
187
  * re-running with another flag, when the flags are precisely what went wrong.
188
- * `utils/args.ts` marks those with `isUsageError` rather than a class, because
189
- * this file imports the bundle and `instanceof` cannot reach across it.
188
+ * And a *refusal* the CLI raised itself, having said why: the compose-port
189
+ * check names the container holding the port and how to move, and its stack
190
+ * points at the line that decided to refuse. `utils/args.ts` and
191
+ * `utils/refusal.ts` mark those with `isUsageError` / `isRefusal` rather than a
192
+ * class, because this file imports the bundle and `instanceof` cannot reach
193
+ * across it.
190
194
  */
191
195
  // After the bundle, which already imports this package, and spelled as the
192
196
  // commands spell it: `wantsRawError` in `commands/cloud/errors.ts`.
@@ -198,12 +202,12 @@ if (wantsStack) process.env.REBASE_DEBUG = "1";
198
202
 
199
203
  entry(process.argv).catch((error) => {
200
204
  const message = error instanceof Error ? error.message : String(error);
201
- const isUsage = Boolean(error && typeof error === "object" && error.isUsageError);
205
+ const saidWhy = Boolean(error && typeof error === "object" && (error.isUsageError || error.isRefusal));
202
206
 
203
207
  process.stderr.write(`${red(`✗ ${message}`)}\n`);
204
208
  if (wantsStack && error instanceof Error && error.stack) {
205
209
  process.stderr.write(`\n${error.stack}\n`);
206
- } else if (!isUsage) {
210
+ } else if (!saidWhy) {
207
211
  process.stderr.write(`${dim(" Re-run with --debug for the stack trace.")}\n`);
208
212
  }
209
213
  process.exit(1);
@@ -1,6 +1,6 @@
1
1
  import { t as detectPackageManager } from "./package-manager-DSEOwTqM.js";
2
2
  import { n as cliVersion } from "./version-Buyyo1ut.js";
3
- import { AGENTS, AGENT_KEYS, detectInstalledAgents, installSkills, loadBundledSkills } from "./skills-DEhYiPeO.js";
3
+ import { AGENTS, AGENT_KEYS, detectInstalledAgents, installSkills, loadBundledSkills } from "./skills-DeUIsZcT.js";
4
4
  import chalk from "chalk";
5
5
  import fs from "fs";
6
6
  import path from "path";
@@ -321,4 +321,4 @@ async function promptForAgents(home) {
321
321
  //#endregion
322
322
  export { MCP_SERVER_NAME, configureAgents, ensureMcpDependency, mcpDependencyNote, mcpServerRegistered, printAgentSetup, promptForAgents, retargetScaffoldMcpConfig, writeMcpConfig };
323
323
 
324
- //# sourceMappingURL=agent-setup-C83DXnlx.js.map
324
+ //# sourceMappingURL=agent-setup-BYb2Tbdz.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-setup-C83DXnlx.js","names":[],"sources":["../src/commands/agent-setup.ts"],"sourcesContent":["/**\n * Setting a project up for the AI coding assistants a developer uses: the\n * Rebase skills, and the Rebase MCP server in each assistant's own config.\n *\n * `rebase init` used to end by *printing* `rebase skills install`, and nothing\n * ran it — so a generated project had pointer files telling every assistant to\n * read skills that were not there, and an MCP server only Claude Code knew\n * about. This asks once, while the project is being made, pre-ticking the\n * assistants installed on the machine.\n */\nimport chalk from \"chalk\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport inquirer from \"inquirer\";\nimport {\n AGENT_KEYS,\n AGENTS,\n type AgentKey,\n detectInstalledAgents,\n installSkills,\n type LoadedSkill,\n loadBundledSkills\n} from \"./skills\";\nimport { detectPackageManager, type PackageManager } from \"../utils/package-manager\";\nimport { cliVersion } from \"../utils/version\";\n\n/** The name the server is registered under, in every config. */\nexport const MCP_SERVER_NAME = \"rebase\";\n\n/** The MCP server's package: a devDependency of the project, pinned with the rest. */\nexport const MCP_PACKAGE = \"@rebasepro/mcp\";\n\n/** The bin {@link MCP_PACKAGE} declares. */\nexport const MCP_BIN = \"rebase-mcp\";\n\n/** The command an assistant spawns, and its arguments. */\nexport interface McpLaunch {\n command: string;\n args: string[];\n}\n\n/**\n * How an assistant starts the Rebase MCP server: the project's own copy, through\n * the project's package manager.\n *\n * Not `npx -y @rebasepro/mcp`, which fetched the newest release on every first\n * start. The server drives the project's own CLI (`pnpm exec rebase …`) and calls\n * the project's own backend (`/api/admin/schema/plan`, …), whose versions the\n * lockfile pins — so a server from the registry ran ahead of both, at every\n * start, and downloaded before it could answer. `@rebasepro/mcp` is a\n * devDependency of the scaffold, pinned to the CLI's version like every other\n * `@rebasepro` package, and this runs that copy.\n *\n * `npx --no`, not `npx`: an assistant spawns the server with no TTY, and npx\n * then assumes \"yes\" and installs a missing package from the registry under the\n * name it was given. `--no` makes a missing install an error instead.\n */\nexport function mcpLaunch(pm: PackageManager): McpLaunch {\n return pm === \"npm\"\n ? { command: \"npx\", args: [\"--no\", MCP_BIN] }\n : { command: \"pnpm\", args: [\"exec\", MCP_BIN] };\n}\n\n/** What writing one MCP config did. */\nexport type McpWriteStatus =\n /** The file was created, or the server was added beside the ones in it. */\n | \"added\"\n /** A `rebase` server was already there. It is left exactly as it was. */\n | \"present\"\n /** The file exists but is not something this can edit without losing data. */\n | \"unreadable\";\n\nexport interface McpWriteResult {\n /** Project-relative path of the config file. */\n file: string;\n status: McpWriteStatus;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Add the server to a JSON config under `key`, keeping everything else in it.\n *\n * A file that does not parse as plain JSON is left alone: VS Code and Gemini\n * both accept comments in these files, and rewriting one through\n * `JSON.stringify` would delete them. Refusing costs one line of hand-editing;\n * the alternative silently costs the developer theirs.\n */\nfunction addJsonServer(filePath: string, key: string, entry: Record<string, unknown>): McpWriteStatus {\n let doc: Record<string, unknown> = {};\n if (fs.existsSync(filePath)) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(fs.readFileSync(filePath, \"utf-8\"));\n } catch {\n return \"unreadable\";\n }\n if (!isRecord(parsed)) return \"unreadable\";\n doc = parsed;\n }\n\n const servers = doc[key] ?? {};\n if (!isRecord(servers)) return \"unreadable\";\n if (MCP_SERVER_NAME in servers) return \"present\";\n\n doc[key] = { ...servers, [MCP_SERVER_NAME]: entry };\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, `${JSON.stringify(doc, null, 2)}\\n`, \"utf-8\");\n return \"added\";\n}\n\n/**\n * The Codex block, as TOML. Appended rather than merged: there is no TOML\n * parser here, and an append keeps every byte already in the file.\n */\nexport function renderCodexServer(projectDir: string, launch: McpLaunch): string {\n // A JSON string literal is a valid TOML basic string for these values.\n const str = (v: string) => JSON.stringify(v);\n return [\n `[mcp_servers.${MCP_SERVER_NAME}]`,\n `command = ${str(launch.command)}`,\n `args = [${launch.args.map(str).join(\", \")}]`,\n \"\",\n `[mcp_servers.${MCP_SERVER_NAME}.env]`,\n `REBASE_PROJECT_DIR = ${str(projectDir)}`,\n \"\"\n ].join(\"\\n\");\n}\n\nfunction addCodexServer(filePath: string, projectDir: string, launch: McpLaunch): McpWriteStatus {\n const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, \"utf-8\") : \"\";\n const table = new RegExp(`^\\\\s*\\\\[mcp_servers\\\\.(?:${MCP_SERVER_NAME}|\"${MCP_SERVER_NAME}\")\\\\]`, \"m\");\n if (table.test(existing)) return \"present\";\n\n const separator = existing === \"\" ? \"\" : existing.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, `${existing}${separator}${renderCodexServer(projectDir, launch)}`, \"utf-8\");\n return \"added\";\n}\n\n/**\n * Register the Rebase MCP server in the agent's project-level config, started\n * through the project's package manager (see {@link mcpLaunch}).\n *\n * Returns null for an agent with no project-level config to write.\n */\nexport function writeMcpConfig(\n agentKey: AgentKey,\n projectDir: string,\n pm: PackageManager = detectPackageManager(projectDir)\n): McpWriteResult | null {\n const mcp = AGENTS[agentKey].mcp;\n if (!mcp) return null;\n\n const filePath = path.join(projectDir, mcp.file);\n const env = { REBASE_PROJECT_DIR: mcp.projectDir };\n const { command, args } = mcpLaunch(pm);\n const write = (): McpWriteStatus => {\n switch (mcp.format) {\n case \"mcpServers\":\n return addJsonServer(filePath, \"mcpServers\", { command, args, env });\n case \"vscode\":\n // VS Code's own shape: `servers`, and an explicit transport.\n return addJsonServer(filePath, \"servers\", { type: \"stdio\", command, args, env });\n case \"codexToml\":\n return addCodexServer(filePath, mcp.projectDir, { command, args });\n }\n };\n return { file: mcp.file, status: write() };\n}\n\n/** What making sure the project depends on the MCP server did. */\nexport type McpDependencyStatus =\n /** Added to `devDependencies`, at this CLI's version: an install is due. */\n | \"added\"\n /** Already a dependency. Left at the version the project chose. */\n | \"present\"\n /** No `package.json`, or one that is not plain JSON: left alone. */\n | \"unreadable\";\n\n/**\n * Make the project depend on {@link MCP_PACKAGE}, which the config written by\n * {@link writeMcpConfig} runs from the project's own install.\n *\n * Pinned to this CLI's version, as `rebase init` pins every `@rebasepro`\n * package; a project that already lists it keeps its own choice.\n */\nexport function ensureMcpDependency(projectDir: string): McpDependencyStatus {\n const manifestPath = path.join(projectDir, \"package.json\");\n if (!fs.existsSync(manifestPath)) return \"unreadable\";\n const text = fs.readFileSync(manifestPath, \"utf-8\");\n let manifest: unknown;\n try {\n manifest = JSON.parse(text);\n } catch {\n return \"unreadable\";\n }\n if (!isRecord(manifest)) return \"unreadable\";\n for (const field of [\"dependencies\", \"devDependencies\"] as const) {\n const deps = manifest[field];\n if (isRecord(deps) && MCP_PACKAGE in deps) return \"present\";\n }\n const devDependencies = isRecord(manifest.devDependencies) ? manifest.devDependencies : {};\n const version = cliVersion();\n manifest.devDependencies = { ...devDependencies, [MCP_PACKAGE]: version === \"unknown\" ? \"latest\" : version };\n // The file's own indentation, so the change is one line in a diff.\n const indent = /\\n([ \\t]+)\"/.exec(text)?.[1] ?? \" \";\n fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, indent)}\\n`, \"utf-8\");\n return \"added\";\n}\n\n/**\n * Point the scaffold's `.mcp.json` at the project's package manager.\n *\n * The template ships the pnpm spelling (`pnpm exec rebase-mcp`); an npm project\n * has no pnpm to run it with. Only the entry the template wrote is rewritten.\n */\nexport function retargetScaffoldMcpConfig(projectDir: string, pm: PackageManager): void {\n const filePath = path.join(projectDir, \".mcp.json\");\n if (!fs.existsSync(filePath)) return;\n let doc: unknown;\n try {\n doc = JSON.parse(fs.readFileSync(filePath, \"utf-8\"));\n } catch {\n return;\n }\n const servers = isRecord(doc) ? doc.mcpServers : undefined;\n const entry = isRecord(servers) ? servers[MCP_SERVER_NAME] : undefined;\n const shipped = mcpLaunch(\"pnpm\");\n if (!isRecord(doc) || !isRecord(servers) || !isRecord(entry)) return;\n if (entry.command !== shipped.command || JSON.stringify(entry.args) !== JSON.stringify(shipped.args)) return;\n const wanted = mcpLaunch(pm);\n if (wanted.command === shipped.command && JSON.stringify(wanted.args) === JSON.stringify(shipped.args)) return;\n servers[MCP_SERVER_NAME] = { ...entry, command: wanted.command, args: wanted.args };\n fs.writeFileSync(filePath, `${JSON.stringify(doc, null, 4)}\\n`, \"utf-8\");\n}\n\n/**\n * Whether the agent's project-level config already registers the Rebase\n * server: `null` for an agent that has no such config, `false` when the file\n * is missing or does not name it. Reads only — for the hint `rebase skills\n * install` prints when it was not asked to write one.\n */\nexport function mcpServerRegistered(agentKey: AgentKey, projectDir: string): boolean | null {\n const mcp = AGENTS[agentKey].mcp;\n if (!mcp) return null;\n const filePath = path.join(projectDir, mcp.file);\n if (!fs.existsSync(filePath)) return false;\n const text = fs.readFileSync(filePath, \"utf-8\");\n if (mcp.format === \"codexToml\") {\n return new RegExp(`^\\\\s*\\\\[mcp_servers\\\\.(?:${MCP_SERVER_NAME}|\"${MCP_SERVER_NAME}\")\\\\]`, \"m\").test(text);\n }\n try {\n const doc: unknown = JSON.parse(text);\n const servers = isRecord(doc) ? doc[mcp.format === \"vscode\" ? \"servers\" : \"mcpServers\"] : undefined;\n return isRecord(servers) && MCP_SERVER_NAME in servers;\n } catch {\n // Not plain JSON (comments): cannot tell, so do not nag.\n return null;\n }\n}\n\n/** What `configureAgents` did for one agent. */\nexport interface AgentSetupResult {\n agent: AgentKey;\n /** Skills written, or null when the bundle could not be loaded. */\n skills: number | null;\n /** An earlier agent in the same run that already wrote the skills directory. */\n sharedWith?: AgentKey;\n mcp: McpWriteResult | null;\n}\n\n/**\n * Install the skills and register the MCP server for each agent.\n *\n * Never throws for a missing skills bundle — the scaffold it runs inside must\n * not fail over its assistants — and reports it as `skills: null` instead.\n */\nexport function configureAgents(\n agents: readonly AgentKey[],\n projectDir: string,\n load: () => LoadedSkill[] = loadBundledSkills,\n pm: PackageManager = detectPackageManager(projectDir)\n): { results: AgentSetupResult[]; skillsError?: string; mcpDependency?: McpDependencyStatus } {\n let skillsError: string | undefined;\n let installed: ReturnType<typeof installSkills> = [];\n try {\n installed = installSkills(agents, load(), projectDir);\n } catch (err) {\n skillsError = err instanceof Error ? err.message : String(err);\n }\n\n const results = agents.map((agent): AgentSetupResult => {\n const skills = installed.find(r => r.agent === agent);\n return {\n agent,\n skills: skills ? skills.skills : null,\n sharedWith: skills?.sharedWith,\n mcp: writeMcpConfig(agent, projectDir, pm)\n };\n });\n // A config that runs the project's copy of the server needs the project to\n // have one.\n const registered = results.some(r => r.mcp?.status === \"added\" || r.mcp?.status === \"present\");\n return { results, skillsError, ...(registered && { mcpDependency: ensureMcpDependency(projectDir) }) };\n}\n\n/** The line to print when {@link ensureMcpDependency} changed or could not change the manifest. */\nexport function mcpDependencyNote(status: McpDependencyStatus | undefined, pm: PackageManager): string | undefined {\n if (status === \"added\") {\n return `Added ${MCP_PACKAGE} to devDependencies — run \\`${pm} install\\` before your assistant starts it.`;\n }\n if (status === \"unreadable\") {\n return `Could not add ${MCP_PACKAGE} to package.json — add it to devDependencies by hand; the MCP config runs the project's own copy.`;\n }\n return undefined;\n}\n\n/** One line per agent, for the scaffold's output. */\nexport function printAgentSetup(\n { results, skillsError, mcpDependency }: ReturnType<typeof configureAgents>,\n pm: PackageManager = \"pnpm\"\n): void {\n for (const result of results) {\n const agent = AGENTS[result.agent];\n const parts: string[] = [];\n\n if (result.sharedWith) {\n parts.push(`skills in ${chalk.gray(agent.targetDir)} ${chalk.gray(`(shared with ${AGENTS[result.sharedWith].label})`)}`);\n } else if (result.skills !== null) {\n parts.push(`${result.skills} skills in ${chalk.gray(agent.targetDir)}`);\n }\n\n if (result.mcp?.status === \"added\") {\n parts.push(`MCP server in ${chalk.gray(result.mcp.file)}`);\n } else if (result.mcp?.status === \"present\") {\n parts.push(`MCP server already in ${chalk.gray(result.mcp.file)}`);\n }\n\n // A tick is a claim that something was written; with nothing, it isn't.\n const mark = parts.length ? chalk.green(\"✓\") : chalk.yellow(\"!\");\n console.log(` ${mark} ${chalk.bold(agent.label)}${parts.length ? ` — ${parts.join(\", \")}` : \"\"}`);\n\n if (result.mcp?.status === \"unreadable\") {\n console.log(chalk.yellow(` ${result.mcp.file} is not plain JSON, so it was left alone — add the \"${MCP_SERVER_NAME}\" server by hand.`));\n } else if (!result.mcp) {\n console.log(chalk.gray(` ${agent.label} has no project-level MCP config — add @rebasepro/mcp in its MCP settings.`));\n }\n }\n\n const dependencyNote = mcpDependencyNote(mcpDependency, pm);\n if (dependencyNote) console.log(chalk.gray(` ${dependencyNote}`));\n\n if (skillsError) {\n console.log(chalk.yellow(` Could not install the Rebase skills: ${skillsError}`));\n console.log(chalk.yellow(\" Run `rebase skills install` in the project once dependencies are installed.\"));\n }\n}\n\n/**\n * Ask whether to set up AI agents, then which, pre-ticking what is installed.\n *\n * Interactive only; the caller has already refused a non-TTY. Returns [] when\n * the developer says no or unticks everything.\n */\nexport async function promptForAgents(home?: string): Promise<AgentKey[]> {\n const { configure } = await inquirer.prompt([{\n type: \"confirm\",\n name: \"configure\",\n message: \"Set up Rebase skills and the Rebase MCP server for your AI coding agent(s)?\",\n default: true\n }]);\n if (!configure) return [];\n\n // Installed first, so the pre-ticked boxes are the ones under the cursor.\n const detected = detectInstalledAgents(home);\n const installed = [...detected.filter(a => a.found), ...detected.filter(a => !a.found)];\n console.log(\"\");\n console.log(\"Detecting installed AI coding agents...\");\n for (const { label, marker, found } of installed) {\n if (found) console.log(` ${chalk.green(\"✓\")} ${label} — ${marker}`);\n else if (marker) console.log(chalk.gray(` ✗ ${label} — ${marker} (not found)`));\n else console.log(chalk.gray(` · ${label} — can't be detected; tick it below if you use it`));\n }\n console.log(\"\");\n\n const { selectedAgents } = await inquirer.prompt([{\n type: \"checkbox\",\n name: \"selectedAgents\",\n message: \"Select agents to configure:\",\n choices: installed.map(({ key, label, found }) => {\n const { targetDir, mcp } = AGENTS[key];\n const writes = mcp ? `${targetDir} + ${mcp.file}` : targetDir;\n return { name: `${label} ${chalk.gray(`— ${writes}`)}`, short: label, value: key, checked: found };\n })\n }]);\n\n return AGENT_KEYS.filter(key => selectedAgents.includes(key));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"agent-setup-BYb2Tbdz.js","names":[],"sources":["../src/commands/agent-setup.ts"],"sourcesContent":["/**\n * Setting a project up for the AI coding assistants a developer uses: the\n * Rebase skills, and the Rebase MCP server in each assistant's own config.\n *\n * `rebase init` used to end by *printing* `rebase skills install`, and nothing\n * ran it — so a generated project had pointer files telling every assistant to\n * read skills that were not there, and an MCP server only Claude Code knew\n * about. This asks once, while the project is being made, pre-ticking the\n * assistants installed on the machine.\n */\nimport chalk from \"chalk\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport inquirer from \"inquirer\";\nimport {\n AGENT_KEYS,\n AGENTS,\n type AgentKey,\n detectInstalledAgents,\n installSkills,\n type LoadedSkill,\n loadBundledSkills\n} from \"./skills\";\nimport { detectPackageManager, type PackageManager } from \"../utils/package-manager\";\nimport { cliVersion } from \"../utils/version\";\n\n/** The name the server is registered under, in every config. */\nexport const MCP_SERVER_NAME = \"rebase\";\n\n/** The MCP server's package: a devDependency of the project, pinned with the rest. */\nexport const MCP_PACKAGE = \"@rebasepro/mcp\";\n\n/** The bin {@link MCP_PACKAGE} declares. */\nexport const MCP_BIN = \"rebase-mcp\";\n\n/** The command an assistant spawns, and its arguments. */\nexport interface McpLaunch {\n command: string;\n args: string[];\n}\n\n/**\n * How an assistant starts the Rebase MCP server: the project's own copy, through\n * the project's package manager.\n *\n * Not `npx -y @rebasepro/mcp`, which fetched the newest release on every first\n * start. The server drives the project's own CLI (`pnpm exec rebase …`) and calls\n * the project's own backend (`/api/admin/schema/plan`, …), whose versions the\n * lockfile pins — so a server from the registry ran ahead of both, at every\n * start, and downloaded before it could answer. `@rebasepro/mcp` is a\n * devDependency of the scaffold, pinned to the CLI's version like every other\n * `@rebasepro` package, and this runs that copy.\n *\n * `npx --no`, not `npx`: an assistant spawns the server with no TTY, and npx\n * then assumes \"yes\" and installs a missing package from the registry under the\n * name it was given. `--no` makes a missing install an error instead.\n */\nexport function mcpLaunch(pm: PackageManager): McpLaunch {\n return pm === \"npm\"\n ? { command: \"npx\", args: [\"--no\", MCP_BIN] }\n : { command: \"pnpm\", args: [\"exec\", MCP_BIN] };\n}\n\n/** What writing one MCP config did. */\nexport type McpWriteStatus =\n /** The file was created, or the server was added beside the ones in it. */\n | \"added\"\n /** A `rebase` server was already there. It is left exactly as it was. */\n | \"present\"\n /** The file exists but is not something this can edit without losing data. */\n | \"unreadable\";\n\nexport interface McpWriteResult {\n /** Project-relative path of the config file. */\n file: string;\n status: McpWriteStatus;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Add the server to a JSON config under `key`, keeping everything else in it.\n *\n * A file that does not parse as plain JSON is left alone: VS Code and Gemini\n * both accept comments in these files, and rewriting one through\n * `JSON.stringify` would delete them. Refusing costs one line of hand-editing;\n * the alternative silently costs the developer theirs.\n */\nfunction addJsonServer(filePath: string, key: string, entry: Record<string, unknown>): McpWriteStatus {\n let doc: Record<string, unknown> = {};\n if (fs.existsSync(filePath)) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(fs.readFileSync(filePath, \"utf-8\"));\n } catch {\n return \"unreadable\";\n }\n if (!isRecord(parsed)) return \"unreadable\";\n doc = parsed;\n }\n\n const servers = doc[key] ?? {};\n if (!isRecord(servers)) return \"unreadable\";\n if (MCP_SERVER_NAME in servers) return \"present\";\n\n doc[key] = { ...servers, [MCP_SERVER_NAME]: entry };\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, `${JSON.stringify(doc, null, 2)}\\n`, \"utf-8\");\n return \"added\";\n}\n\n/**\n * The Codex block, as TOML. Appended rather than merged: there is no TOML\n * parser here, and an append keeps every byte already in the file.\n */\nexport function renderCodexServer(projectDir: string, launch: McpLaunch): string {\n // A JSON string literal is a valid TOML basic string for these values.\n const str = (v: string) => JSON.stringify(v);\n return [\n `[mcp_servers.${MCP_SERVER_NAME}]`,\n `command = ${str(launch.command)}`,\n `args = [${launch.args.map(str).join(\", \")}]`,\n \"\",\n `[mcp_servers.${MCP_SERVER_NAME}.env]`,\n `REBASE_PROJECT_DIR = ${str(projectDir)}`,\n \"\"\n ].join(\"\\n\");\n}\n\nfunction addCodexServer(filePath: string, projectDir: string, launch: McpLaunch): McpWriteStatus {\n const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, \"utf-8\") : \"\";\n const table = new RegExp(`^\\\\s*\\\\[mcp_servers\\\\.(?:${MCP_SERVER_NAME}|\"${MCP_SERVER_NAME}\")\\\\]`, \"m\");\n if (table.test(existing)) return \"present\";\n\n const separator = existing === \"\" ? \"\" : existing.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, `${existing}${separator}${renderCodexServer(projectDir, launch)}`, \"utf-8\");\n return \"added\";\n}\n\n/**\n * Register the Rebase MCP server in the agent's project-level config, started\n * through the project's package manager (see {@link mcpLaunch}).\n *\n * Returns null for an agent with no project-level config to write.\n */\nexport function writeMcpConfig(\n agentKey: AgentKey,\n projectDir: string,\n pm: PackageManager = detectPackageManager(projectDir)\n): McpWriteResult | null {\n const mcp = AGENTS[agentKey].mcp;\n if (!mcp) return null;\n\n const filePath = path.join(projectDir, mcp.file);\n const env = { REBASE_PROJECT_DIR: mcp.projectDir };\n const { command, args } = mcpLaunch(pm);\n const write = (): McpWriteStatus => {\n switch (mcp.format) {\n case \"mcpServers\":\n return addJsonServer(filePath, \"mcpServers\", { command, args, env });\n case \"vscode\":\n // VS Code's own shape: `servers`, and an explicit transport.\n return addJsonServer(filePath, \"servers\", { type: \"stdio\", command, args, env });\n case \"codexToml\":\n return addCodexServer(filePath, mcp.projectDir, { command, args });\n }\n };\n return { file: mcp.file, status: write() };\n}\n\n/** What making sure the project depends on the MCP server did. */\nexport type McpDependencyStatus =\n /** Added to `devDependencies`, at this CLI's version: an install is due. */\n | \"added\"\n /** Already a dependency. Left at the version the project chose. */\n | \"present\"\n /** No `package.json`, or one that is not plain JSON: left alone. */\n | \"unreadable\";\n\n/**\n * Make the project depend on {@link MCP_PACKAGE}, which the config written by\n * {@link writeMcpConfig} runs from the project's own install.\n *\n * Pinned to this CLI's version, as `rebase init` pins every `@rebasepro`\n * package; a project that already lists it keeps its own choice.\n */\nexport function ensureMcpDependency(projectDir: string): McpDependencyStatus {\n const manifestPath = path.join(projectDir, \"package.json\");\n if (!fs.existsSync(manifestPath)) return \"unreadable\";\n const text = fs.readFileSync(manifestPath, \"utf-8\");\n let manifest: unknown;\n try {\n manifest = JSON.parse(text);\n } catch {\n return \"unreadable\";\n }\n if (!isRecord(manifest)) return \"unreadable\";\n for (const field of [\"dependencies\", \"devDependencies\"] as const) {\n const deps = manifest[field];\n if (isRecord(deps) && MCP_PACKAGE in deps) return \"present\";\n }\n const devDependencies = isRecord(manifest.devDependencies) ? manifest.devDependencies : {};\n const version = cliVersion();\n manifest.devDependencies = { ...devDependencies, [MCP_PACKAGE]: version === \"unknown\" ? \"latest\" : version };\n // The file's own indentation, so the change is one line in a diff.\n const indent = /\\n([ \\t]+)\"/.exec(text)?.[1] ?? \" \";\n fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, indent)}\\n`, \"utf-8\");\n return \"added\";\n}\n\n/**\n * Point the scaffold's `.mcp.json` at the project's package manager.\n *\n * The template ships the pnpm spelling (`pnpm exec rebase-mcp`); an npm project\n * has no pnpm to run it with. Only the entry the template wrote is rewritten.\n */\nexport function retargetScaffoldMcpConfig(projectDir: string, pm: PackageManager): void {\n const filePath = path.join(projectDir, \".mcp.json\");\n if (!fs.existsSync(filePath)) return;\n let doc: unknown;\n try {\n doc = JSON.parse(fs.readFileSync(filePath, \"utf-8\"));\n } catch {\n return;\n }\n const servers = isRecord(doc) ? doc.mcpServers : undefined;\n const entry = isRecord(servers) ? servers[MCP_SERVER_NAME] : undefined;\n const shipped = mcpLaunch(\"pnpm\");\n if (!isRecord(doc) || !isRecord(servers) || !isRecord(entry)) return;\n if (entry.command !== shipped.command || JSON.stringify(entry.args) !== JSON.stringify(shipped.args)) return;\n const wanted = mcpLaunch(pm);\n if (wanted.command === shipped.command && JSON.stringify(wanted.args) === JSON.stringify(shipped.args)) return;\n servers[MCP_SERVER_NAME] = { ...entry, command: wanted.command, args: wanted.args };\n fs.writeFileSync(filePath, `${JSON.stringify(doc, null, 4)}\\n`, \"utf-8\");\n}\n\n/**\n * Whether the agent's project-level config already registers the Rebase\n * server: `null` for an agent that has no such config, `false` when the file\n * is missing or does not name it. Reads only — for the hint `rebase skills\n * install` prints when it was not asked to write one.\n */\nexport function mcpServerRegistered(agentKey: AgentKey, projectDir: string): boolean | null {\n const mcp = AGENTS[agentKey].mcp;\n if (!mcp) return null;\n const filePath = path.join(projectDir, mcp.file);\n if (!fs.existsSync(filePath)) return false;\n const text = fs.readFileSync(filePath, \"utf-8\");\n if (mcp.format === \"codexToml\") {\n return new RegExp(`^\\\\s*\\\\[mcp_servers\\\\.(?:${MCP_SERVER_NAME}|\"${MCP_SERVER_NAME}\")\\\\]`, \"m\").test(text);\n }\n try {\n const doc: unknown = JSON.parse(text);\n const servers = isRecord(doc) ? doc[mcp.format === \"vscode\" ? \"servers\" : \"mcpServers\"] : undefined;\n return isRecord(servers) && MCP_SERVER_NAME in servers;\n } catch {\n // Not plain JSON (comments): cannot tell, so do not nag.\n return null;\n }\n}\n\n/** What `configureAgents` did for one agent. */\nexport interface AgentSetupResult {\n agent: AgentKey;\n /** Skills written, or null when the bundle could not be loaded. */\n skills: number | null;\n /** An earlier agent in the same run that already wrote the skills directory. */\n sharedWith?: AgentKey;\n mcp: McpWriteResult | null;\n}\n\n/**\n * Install the skills and register the MCP server for each agent.\n *\n * Never throws for a missing skills bundle — the scaffold it runs inside must\n * not fail over its assistants — and reports it as `skills: null` instead.\n */\nexport function configureAgents(\n agents: readonly AgentKey[],\n projectDir: string,\n load: () => LoadedSkill[] = loadBundledSkills,\n pm: PackageManager = detectPackageManager(projectDir)\n): { results: AgentSetupResult[]; skillsError?: string; mcpDependency?: McpDependencyStatus } {\n let skillsError: string | undefined;\n let installed: ReturnType<typeof installSkills> = [];\n try {\n installed = installSkills(agents, load(), projectDir);\n } catch (err) {\n skillsError = err instanceof Error ? err.message : String(err);\n }\n\n const results = agents.map((agent): AgentSetupResult => {\n const skills = installed.find(r => r.agent === agent);\n return {\n agent,\n skills: skills ? skills.skills : null,\n sharedWith: skills?.sharedWith,\n mcp: writeMcpConfig(agent, projectDir, pm)\n };\n });\n // A config that runs the project's copy of the server needs the project to\n // have one.\n const registered = results.some(r => r.mcp?.status === \"added\" || r.mcp?.status === \"present\");\n return { results, skillsError, ...(registered && { mcpDependency: ensureMcpDependency(projectDir) }) };\n}\n\n/** The line to print when {@link ensureMcpDependency} changed or could not change the manifest. */\nexport function mcpDependencyNote(status: McpDependencyStatus | undefined, pm: PackageManager): string | undefined {\n if (status === \"added\") {\n return `Added ${MCP_PACKAGE} to devDependencies — run \\`${pm} install\\` before your assistant starts it.`;\n }\n if (status === \"unreadable\") {\n return `Could not add ${MCP_PACKAGE} to package.json — add it to devDependencies by hand; the MCP config runs the project's own copy.`;\n }\n return undefined;\n}\n\n/** One line per agent, for the scaffold's output. */\nexport function printAgentSetup(\n { results, skillsError, mcpDependency }: ReturnType<typeof configureAgents>,\n pm: PackageManager = \"pnpm\"\n): void {\n for (const result of results) {\n const agent = AGENTS[result.agent];\n const parts: string[] = [];\n\n if (result.sharedWith) {\n parts.push(`skills in ${chalk.gray(agent.targetDir)} ${chalk.gray(`(shared with ${AGENTS[result.sharedWith].label})`)}`);\n } else if (result.skills !== null) {\n parts.push(`${result.skills} skills in ${chalk.gray(agent.targetDir)}`);\n }\n\n if (result.mcp?.status === \"added\") {\n parts.push(`MCP server in ${chalk.gray(result.mcp.file)}`);\n } else if (result.mcp?.status === \"present\") {\n parts.push(`MCP server already in ${chalk.gray(result.mcp.file)}`);\n }\n\n // A tick is a claim that something was written; with nothing, it isn't.\n const mark = parts.length ? chalk.green(\"✓\") : chalk.yellow(\"!\");\n console.log(` ${mark} ${chalk.bold(agent.label)}${parts.length ? ` — ${parts.join(\", \")}` : \"\"}`);\n\n if (result.mcp?.status === \"unreadable\") {\n console.log(chalk.yellow(` ${result.mcp.file} is not plain JSON, so it was left alone — add the \"${MCP_SERVER_NAME}\" server by hand.`));\n } else if (!result.mcp) {\n console.log(chalk.gray(` ${agent.label} has no project-level MCP config — add @rebasepro/mcp in its MCP settings.`));\n }\n }\n\n const dependencyNote = mcpDependencyNote(mcpDependency, pm);\n if (dependencyNote) console.log(chalk.gray(` ${dependencyNote}`));\n\n if (skillsError) {\n console.log(chalk.yellow(` Could not install the Rebase skills: ${skillsError}`));\n console.log(chalk.yellow(\" Run `rebase skills install` in the project once dependencies are installed.\"));\n }\n}\n\n/**\n * Ask whether to set up AI agents, then which, pre-ticking what is installed.\n *\n * Interactive only; the caller has already refused a non-TTY. Returns [] when\n * the developer says no or unticks everything.\n */\nexport async function promptForAgents(home?: string): Promise<AgentKey[]> {\n const { configure } = await inquirer.prompt([{\n type: \"confirm\",\n name: \"configure\",\n message: \"Set up Rebase skills and the Rebase MCP server for your AI coding agent(s)?\",\n default: true\n }]);\n if (!configure) return [];\n\n // Installed first, so the pre-ticked boxes are the ones under the cursor.\n const detected = detectInstalledAgents(home);\n const installed = [...detected.filter(a => a.found), ...detected.filter(a => !a.found)];\n console.log(\"\");\n console.log(\"Detecting installed AI coding agents...\");\n for (const { label, marker, found } of installed) {\n if (found) console.log(` ${chalk.green(\"✓\")} ${label} — ${marker}`);\n else if (marker) console.log(chalk.gray(` ✗ ${label} — ${marker} (not found)`));\n else console.log(chalk.gray(` · ${label} — can't be detected; tick it below if you use it`));\n }\n console.log(\"\");\n\n const { selectedAgents } = await inquirer.prompt([{\n type: \"checkbox\",\n name: \"selectedAgents\",\n message: \"Select agents to configure:\",\n choices: installed.map(({ key, label, found }) => {\n const { targetDir, mcp } = AGENTS[key];\n const writes = mcp ? `${targetDir} + ${mcp.file}` : targetDir;\n return { name: `${label} ${chalk.gray(`— ${writes}`)}`, short: label, value: key, checked: found };\n })\n }]);\n\n return AGENT_KEYS.filter(key => selectedAgents.includes(key));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA2BA,IAAa,kBAAkB;;AAG/B,IAAa,cAAc;;AAG3B,IAAa,UAAU;;;;;;;;;;;;;;;;;AAwBvB,SAAgB,UAAU,IAA+B;CACrD,OAAO,OAAO,QACR;EAAE,SAAS;EAAO,MAAM,CAAC,QAAQ,OAAO;CAAE,IAC1C;EAAE,SAAS;EAAQ,MAAM,CAAC,QAAQ,OAAO;CAAE;AACrD;AAiBA,SAAS,SAAS,OAAkD;CAChE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC9E;;;;;;;;;AAUA,SAAS,cAAc,UAAkB,KAAa,OAAgD;CAClG,IAAI,MAA+B,CAAC;CACpC,IAAI,GAAG,WAAW,QAAQ,GAAG;EACzB,IAAI;EACJ,IAAI;GACA,SAAS,KAAK,MAAM,GAAG,aAAa,UAAU,OAAO,CAAC;EAC1D,QAAQ;GACJ,OAAO;EACX;EACA,IAAI,CAAC,SAAS,MAAM,GAAG,OAAO;EAC9B,MAAM;CACV;CAEA,MAAM,UAAU,IAAI,QAAQ,CAAC;CAC7B,IAAI,CAAC,SAAS,OAAO,GAAG,OAAO;CAC/B,IAAA,YAAuB,SAAS,OAAO;CAEvC,IAAI,OAAO;EAAE,GAAG;GAAU,kBAAkB;CAAM;CAClD,GAAG,UAAU,KAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;CACxD,GAAG,cAAc,UAAU,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE,KAAK,OAAO;CACvE,OAAO;AACX;;;;;AAMA,SAAgB,kBAAkB,YAAoB,QAA2B;CAE7E,MAAM,OAAO,MAAc,KAAK,UAAU,CAAC;CAC3C,OAAO;EACH,gBAAgB,gBAAgB;EAChC,aAAa,IAAI,OAAO,OAAO;EAC/B,WAAW,OAAO,KAAK,IAAI,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE;EAC3C;EACA,gBAAgB,gBAAgB;EAChC,wBAAwB,IAAI,UAAU;EACtC;CACJ,CAAC,CAAC,KAAK,IAAI;AACf;AAEA,SAAS,eAAe,UAAkB,YAAoB,QAAmC;CAC7F,MAAM,WAAW,GAAG,WAAW,QAAQ,IAAI,GAAG,aAAa,UAAU,OAAO,IAAI;CAEhF,IAAI,IADc,OAAO,gDAAwE,GAC7F,CAAA,CAAM,KAAK,QAAQ,GAAG,OAAO;CAEjC,MAAM,YAAY,aAAa,KAAK,KAAK,SAAS,SAAS,IAAI,IAAI,OAAO;CAC1E,GAAG,UAAU,KAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;CACxD,GAAG,cAAc,UAAU,GAAG,WAAW,YAAY,kBAAkB,YAAY,MAAM,KAAK,OAAO;CACrG,OAAO;AACX;;;;;;;AAQA,SAAgB,eACZ,UACA,YACA,KAAqB,qBAAqB,UAAU,GAC/B;CACrB,MAAM,MAAM,OAAO,SAAS,CAAC;CAC7B,IAAI,CAAC,KAAK,OAAO;CAEjB,MAAM,WAAW,KAAK,KAAK,YAAY,IAAI,IAAI;CAC/C,MAAM,MAAM,EAAE,oBAAoB,IAAI,WAAW;CACjD,MAAM,EAAE,SAAS,SAAS,UAAU,EAAE;CACtC,MAAM,cAA8B;EAChC,QAAQ,IAAI,QAAZ;GACI,KAAK,cACD,OAAO,cAAc,UAAU,cAAc;IAAE;IAAS;IAAM;GAAI,CAAC;GACvE,KAAK,UAED,OAAO,cAAc,UAAU,WAAW;IAAE,MAAM;IAAS;IAAS;IAAM;GAAI,CAAC;GACnF,KAAK,aACD,OAAO,eAAe,UAAU,IAAI,YAAY;IAAE;IAAS;GAAK,CAAC;EACzE;CACJ;CACA,OAAO;EAAE,MAAM,IAAI;EAAM,QAAQ,MAAM;CAAE;AAC7C;;;;;;;;AAkBA,SAAgB,oBAAoB,YAAyC;CACzE,MAAM,eAAe,KAAK,KAAK,YAAY,cAAc;CACzD,IAAI,CAAC,GAAG,WAAW,YAAY,GAAG,OAAO;CACzC,MAAM,OAAO,GAAG,aAAa,cAAc,OAAO;CAClD,IAAI;CACJ,IAAI;EACA,WAAW,KAAK,MAAM,IAAI;CAC9B,QAAQ;EACJ,OAAO;CACX;CACA,IAAI,CAAC,SAAS,QAAQ,GAAG,OAAO;CAChC,KAAK,MAAM,SAAS,CAAC,gBAAgB,iBAAiB,GAAY;EAC9D,MAAM,OAAO,SAAS;EACtB,IAAI,SAAS,IAAI,KAAA,oBAAoB,MAAM,OAAO;CACtD;CACA,MAAM,kBAAkB,SAAS,SAAS,eAAe,IAAI,SAAS,kBAAkB,CAAC;CACzF,MAAM,UAAU,WAAW;CAC3B,SAAS,kBAAkB;EAAE,GAAG;GAAkB,cAAc,YAAY,YAAY,WAAW;CAAQ;CAE3G,MAAM,SAAS,cAAc,KAAK,IAAI,CAAC,GAAG,MAAM;CAChD,GAAG,cAAc,cAAc,GAAG,KAAK,UAAU,UAAU,MAAM,MAAM,EAAE,KAAK,OAAO;CACrF,OAAO;AACX;;;;;;;AAQA,SAAgB,0BAA0B,YAAoB,IAA0B;CACpF,MAAM,WAAW,KAAK,KAAK,YAAY,WAAW;CAClD,IAAI,CAAC,GAAG,WAAW,QAAQ,GAAG;CAC9B,IAAI;CACJ,IAAI;EACA,MAAM,KAAK,MAAM,GAAG,aAAa,UAAU,OAAO,CAAC;CACvD,QAAQ;EACJ;CACJ;CACA,MAAM,UAAU,SAAS,GAAG,IAAI,IAAI,aAAa,KAAA;CACjD,MAAM,QAAQ,SAAS,OAAO,IAAI,QAAQ,mBAAmB,KAAA;CAC7D,MAAM,UAAU,UAAU,MAAM;CAChC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,OAAO,KAAK,CAAC,SAAS,KAAK,GAAG;CAC9D,IAAI,MAAM,YAAY,QAAQ,WAAW,KAAK,UAAU,MAAM,IAAI,MAAM,KAAK,UAAU,QAAQ,IAAI,GAAG;CACtG,MAAM,SAAS,UAAU,EAAE;CAC3B,IAAI,OAAO,YAAY,QAAQ,WAAW,KAAK,UAAU,OAAO,IAAI,MAAM,KAAK,UAAU,QAAQ,IAAI,GAAG;CACxG,QAAQ,mBAAmB;EAAE,GAAG;EAAO,SAAS,OAAO;EAAS,MAAM,OAAO;CAAK;CAClF,GAAG,cAAc,UAAU,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE,KAAK,OAAO;AAC3E;;;;;;;AAQA,SAAgB,oBAAoB,UAAoB,YAAoC;CACxF,MAAM,MAAM,OAAO,SAAS,CAAC;CAC7B,IAAI,CAAC,KAAK,OAAO;CACjB,MAAM,WAAW,KAAK,KAAK,YAAY,IAAI,IAAI;CAC/C,IAAI,CAAC,GAAG,WAAW,QAAQ,GAAG,OAAO;CACrC,MAAM,OAAO,GAAG,aAAa,UAAU,OAAO;CAC9C,IAAI,IAAI,WAAW,aACf,OAAO,IAAI,OAAO,4BAA4B,gBAAgB,IAAI,gBAAgB,QAAQ,GAAG,CAAC,CAAC,KAAK,IAAI;CAE5G,IAAI;EACA,MAAM,MAAe,KAAK,MAAM,IAAI;EACpC,MAAM,UAAU,SAAS,GAAG,IAAI,IAAI,IAAI,WAAW,WAAW,YAAY,gBAAgB,KAAA;EAC1F,OAAO,SAAS,OAAO,KAAA,YAAwB;CACnD,QAAQ;EAEJ,OAAO;CACX;AACJ;;;;;;;AAkBA,SAAgB,gBACZ,QACA,YACA,OAA4B,mBAC5B,KAAqB,qBAAqB,UAAU,GACsC;CAC1F,IAAI;CACJ,IAAI,YAA8C,CAAC;CACnD,IAAI;EACA,YAAY,cAAc,QAAQ,KAAK,GAAG,UAAU;CACxD,SAAS,KAAK;EACV,cAAc,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;CACjE;CAEA,MAAM,UAAU,OAAO,KAAK,UAA4B;EACpD,MAAM,SAAS,UAAU,MAAK,MAAK,EAAE,UAAU,KAAK;EACpD,OAAO;GACH;GACA,QAAQ,SAAS,OAAO,SAAS;GACjC,YAAY,QAAQ;GACpB,KAAK,eAAe,OAAO,YAAY,EAAE;EAC7C;CACJ,CAAC;CAGD,MAAM,aAAa,QAAQ,MAAK,MAAK,EAAE,KAAK,WAAW,WAAW,EAAE,KAAK,WAAW,SAAS;CAC7F,OAAO;EAAE;EAAS;EAAa,GAAI,cAAc,EAAE,eAAe,oBAAoB,UAAU,EAAE;CAAG;AACzG;;AAGA,SAAgB,kBAAkB,QAAyC,IAAwC;CAC/G,IAAI,WAAW,SACX,OAAO,SAAS,YAAY,8BAA8B,GAAG;CAEjE,IAAI,WAAW,cACX,OAAO,iBAAiB,YAAY;AAG5C;;AAGA,SAAgB,gBACZ,EAAE,SAAS,aAAa,iBACxB,KAAqB,QACjB;CACJ,KAAK,MAAM,UAAU,SAAS;EAC1B,MAAM,QAAQ,OAAO,OAAO;EAC5B,MAAM,QAAkB,CAAC;EAEzB,IAAI,OAAO,YACP,MAAM,KAAK,aAAa,MAAM,KAAK,MAAM,SAAS,EAAE,GAAG,MAAM,KAAK,gBAAgB,OAAO,OAAO,WAAW,CAAC,MAAM,EAAE,GAAG;OACpH,IAAI,OAAO,WAAW,MACzB,MAAM,KAAK,GAAG,OAAO,OAAO,aAAa,MAAM,KAAK,MAAM,SAAS,GAAG;EAG1E,IAAI,OAAO,KAAK,WAAW,SACvB,MAAM,KAAK,iBAAiB,MAAM,KAAK,OAAO,IAAI,IAAI,GAAG;OACtD,IAAI,OAAO,KAAK,WAAW,WAC9B,MAAM,KAAK,yBAAyB,MAAM,KAAK,OAAO,IAAI,IAAI,GAAG;EAIrE,MAAM,OAAO,MAAM,SAAS,MAAM,MAAM,GAAG,IAAI,MAAM,OAAO,GAAG;EAC/D,QAAQ,IAAI,KAAK,KAAK,GAAG,MAAM,KAAK,MAAM,KAAK,IAAI,MAAM,SAAS,MAAM,MAAM,KAAK,IAAI,MAAM,IAAI;EAEjG,IAAI,OAAO,KAAK,WAAW,cACvB,QAAQ,IAAI,MAAM,OAAO,OAAO,OAAO,IAAI,KAAK,sDAAsD,gBAAgB,kBAAkB,CAAC;OACtI,IAAI,CAAC,OAAO,KACf,QAAQ,IAAI,MAAM,KAAK,OAAO,MAAM,MAAM,2EAA2E,CAAC;CAE9H;CAEA,MAAM,iBAAiB,kBAAkB,eAAe,EAAE;CAC1D,IAAI,gBAAgB,QAAQ,IAAI,MAAM,KAAK,KAAK,gBAAgB,CAAC;CAEjE,IAAI,aAAa;EACb,QAAQ,IAAI,MAAM,OAAO,0CAA0C,aAAa,CAAC;EACjF,QAAQ,IAAI,MAAM,OAAO,+EAA+E,CAAC;CAC7G;AACJ;;;;;;;AAQA,eAAsB,gBAAgB,MAAoC;CACtE,MAAM,EAAE,cAAc,MAAM,SAAS,OAAO,CAAC;EACzC,MAAM;EACN,MAAM;EACN,SAAS;EACT,SAAS;CACb,CAAC,CAAC;CACF,IAAI,CAAC,WAAW,OAAO,CAAC;CAGxB,MAAM,WAAW,sBAAsB,IAAI;CAC3C,MAAM,YAAY,CAAC,GAAG,SAAS,QAAO,MAAK,EAAE,KAAK,GAAG,GAAG,SAAS,QAAO,MAAK,CAAC,EAAE,KAAK,CAAC;CACtF,QAAQ,IAAI,EAAE;CACd,QAAQ,IAAI,yCAAyC;CACrD,KAAK,MAAM,EAAE,OAAO,QAAQ,WAAW,WACnC,IAAI,OAAO,QAAQ,IAAI,KAAK,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,KAAK,QAAQ;MAC9D,IAAI,QAAQ,QAAQ,IAAI,MAAM,KAAK,OAAO,MAAM,KAAK,OAAO,aAAa,CAAC;MAC1E,QAAQ,IAAI,MAAM,KAAK,OAAO,MAAM,kDAAkD,CAAC;CAEhG,QAAQ,IAAI,EAAE;CAEd,MAAM,EAAE,mBAAmB,MAAM,SAAS,OAAO,CAAC;EAC9C,MAAM;EACN,MAAM;EACN,SAAS;EACT,SAAS,UAAU,KAAK,EAAE,KAAK,OAAO,YAAY;GAC9C,MAAM,EAAE,WAAW,QAAQ,OAAO;GAClC,MAAM,SAAS,MAAM,GAAG,UAAU,KAAK,IAAI,SAAS;GACpD,OAAO;IAAE,MAAM,GAAG,MAAM,GAAG,MAAM,KAAK,KAAK,QAAQ;IAAK,OAAO;IAAO,OAAO;IAAK,SAAS;GAAM;EACrG,CAAC;CACL,CAAC,CAAC;CAEF,OAAO,WAAW,QAAO,QAAO,eAAe,SAAS,GAAG,CAAC;AAChE"}
@@ -1,7 +1,6 @@
1
- import { d as readEnvFile, p as requireProjectRoot } from "./project-Wp2zoyeN.js";
2
- import { a as unknownCommand, n as parseCommandArgs, r as wantsHelp, t as UsageError } from "./args-CcBphFdj.js";
1
+ import { C as wantsHelp, T as unknownCommand, b as parseCommandArgs, d as readEnvFile, p as requireProjectRoot, y as UsageError } from "./project-g4K6kV1t.js";
3
2
  import { t as cliUserAgent } from "./version-Buyyo1ut.js";
4
- import { i as serverUnreachableHint } from "./dev-server-B1UYifZJ.js";
3
+ import { a as serverUnreachableHint } from "./dev-server-CIZwAfZa.js";
5
4
  import chalk from "chalk";
6
5
  import fs from "fs";
7
6
  import path from "path";
@@ -115,9 +114,10 @@ function requireBackendUrl(env, projectRoot) {
115
114
  function connect() {
116
115
  const projectRoot = requireProjectRoot();
117
116
  const env = loadEnv(projectRoot);
118
- const serviceKey = env.SERVICE_KEY || env.REBASE_SERVICE_KEY;
117
+ const keyVariable = env.SERVICE_KEY ? "SERVICE_KEY" : "REBASE_SERVICE_KEY";
118
+ const serviceKey = env[keyVariable];
119
119
  if (!serviceKey) {
120
- console.error(chalk.red("✗ SERVICE_KEY not found in .env — required to manage API keys."));
120
+ console.error(chalk.red("✗ REBASE_SERVICE_KEY not found in .env — required to manage API keys."));
121
121
  process.exit(1);
122
122
  }
123
123
  const baseUrl = requireBackendUrl(env, projectRoot);
@@ -132,7 +132,8 @@ function connect() {
132
132
  autoRefresh: false
133
133
  }
134
134
  }),
135
- baseUrl
135
+ baseUrl,
136
+ keyVariable
136
137
  };
137
138
  }
138
139
  /**
@@ -142,12 +143,12 @@ function connect() {
142
143
  *
143
144
  * Exported so its tests can read the lines without a server.
144
145
  */
145
- function describeFailure(action, error, baseUrl) {
146
+ function describeFailure(action, error, baseUrl, keyVariable = "REBASE_SERVICE_KEY") {
146
147
  if (!(error instanceof RebaseApiError)) return [`✗ ${action}: ${error instanceof Error ? error.message : String(error)}`];
147
148
  if (error.status === 0 || error.code === "NETWORK_ERROR") return [`✗ ${action}: ${error.message}`, ...serverUnreachableHint(baseUrl)];
148
149
  const label = [error.code, error.status ? `(${error.status})` : void 0].filter(Boolean).join(" ");
149
150
  const lines = [`✗ ${action}${label ? ` — ${label}` : ""}: ${error.message}`];
150
- if (error.status === 401) lines.push(` The server at ${baseUrl} did not accept SERVICE_KEY from .env — is it this project's server?`);
151
+ if (error.status === 401) lines.push(` The server at ${baseUrl} did not accept ${keyVariable} from .env — is it this project's server?`);
151
152
  if (error.code === "UNKNOWN_SCOPE_TARGET" && isRecord(error.details)) for (const [kind, title] of [
152
153
  ["collections", "Collections"],
153
154
  ["buckets", "Buckets"],
@@ -161,8 +162,8 @@ function describeFailure(action, error, baseUrl) {
161
162
  function isRecord(value) {
162
163
  return typeof value === "object" && value !== null && !Array.isArray(value);
163
164
  }
164
- function fail(action, error, baseUrl) {
165
- for (const line of describeFailure(action, error, baseUrl)) console.error(line.startsWith("✗") ? chalk.red(line) : chalk.gray(line));
165
+ function fail(action, error, connection) {
166
+ for (const line of describeFailure(action, error, connection.baseUrl, connection.keyVariable)) console.error(line.startsWith("✗") ? chalk.red(line) : chalk.gray(line));
166
167
  process.exit(1);
167
168
  }
168
169
  async function apiKeysCommand(subcommand, rawArgs) {
@@ -230,12 +231,13 @@ async function listKeys(rawArgs) {
230
231
  command: "api-keys list",
231
232
  maxPositionals: 0
232
233
  });
233
- const { client, baseUrl } = connect();
234
+ const connection = connect();
235
+ const { client } = connection;
234
236
  let keys;
235
237
  try {
236
238
  ({keys} = await client.apiKeys.listKeys());
237
239
  } catch (e) {
238
- fail("Failed to list API keys", e, baseUrl);
240
+ fail("Failed to list API keys", e, connection);
239
241
  }
240
242
  console.log("");
241
243
  console.log(chalk.bold(" 🔑 API Keys"));
@@ -271,12 +273,13 @@ function resolveGetKeyArgs(rawArgs) {
271
273
  async function getKey(rawArgs) {
272
274
  const { id } = resolveGetKeyArgs(rawArgs);
273
275
  if (!id) throw new UsageError("Key ID is required: rebase api-keys get <key-id> (`rebase api-keys list` shows them).");
274
- const { client, baseUrl } = connect();
276
+ const connection = connect();
277
+ const { client } = connection;
275
278
  let key;
276
279
  try {
277
280
  ({key} = await client.apiKeys.getKey(id));
278
281
  } catch (e) {
279
- fail("Failed to read API key", e, baseUrl);
282
+ fail("Failed to read API key", e, connection);
280
283
  }
281
284
  console.log("");
282
285
  for (const line of describeKey(key)) console.log(line);
@@ -392,14 +395,15 @@ function grantableScopes(held) {
392
395
  }
393
396
  async function createKey(rawArgs) {
394
397
  const plan = resolveCreateKeyArgs(rawArgs);
395
- const { client, baseUrl } = connect();
398
+ const connection = connect();
399
+ const { client } = connection;
396
400
  let scopes;
397
401
  if (plan.scopes === "held") {
398
402
  let held;
399
403
  try {
400
404
  ({held} = await client.personalKeys.listScopes());
401
405
  } catch (e) {
402
- fail("Failed to read the scopes you hold", e, baseUrl);
406
+ fail("Failed to read the scopes you hold", e, connection);
403
407
  }
404
408
  scopes = grantableScopes(held);
405
409
  if (scopes.length === 0) {
@@ -418,7 +422,7 @@ async function createKey(rawArgs) {
418
422
  try {
419
423
  ({key: created} = await client.apiKeys.createKey(request));
420
424
  } catch (e) {
421
- fail("Failed to create API key", e, baseUrl);
425
+ fail("Failed to create API key", e, connection);
422
426
  }
423
427
  console.log("");
424
428
  console.log(chalk.bold.green(" ✓ API key created"));
@@ -455,11 +459,12 @@ function resolveRevokeKeyArgs(rawArgs) {
455
459
  async function revokeKey(rawArgs) {
456
460
  const { id } = resolveRevokeKeyArgs(rawArgs);
457
461
  if (!id) throw new UsageError("Key ID is required: rebase api-keys revoke <key-id> (`rebase api-keys list` shows them).");
458
- const { client, baseUrl } = connect();
462
+ const connection = connect();
463
+ const { client } = connection;
459
464
  try {
460
465
  await client.apiKeys.revokeKey(id);
461
466
  } catch (e) {
462
- fail("Failed to revoke API key", e, baseUrl);
467
+ fail("Failed to revoke API key", e, connection);
463
468
  }
464
469
  console.log("");
465
470
  console.log(chalk.bold.green(" ✓ API key revoked"));
@@ -517,12 +522,13 @@ async function listScopes(rawArgs) {
517
522
  command: "api-keys scopes",
518
523
  maxPositionals: 0
519
524
  });
520
- const { client, baseUrl } = connect();
525
+ const connection = connect();
526
+ const { client } = connection;
521
527
  let catalogue;
522
528
  try {
523
529
  catalogue = await client.personalKeys.listScopes();
524
530
  } catch (e) {
525
- fail("Failed to read the scopes", e, baseUrl);
531
+ fail("Failed to read the scopes", e, connection);
526
532
  }
527
533
  console.log("");
528
534
  console.log(chalk.bold(" Scopes") + chalk.gray(" (✓ = you hold it; :<target> narrows it to one)"));
@@ -578,4 +584,4 @@ ${chalk.green.bold("Examples")}
578
584
  //#endregion
579
585
  export { API_KEYS_SUBCOMMANDS, apiKeysCommand, describeFailure, requireBackendUrl, resolveBackendAddress };
580
586
 
581
- //# sourceMappingURL=api-keys-Bc4FJKYp.js.map
587
+ //# sourceMappingURL=api-keys-CSMbsmAn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-keys-CSMbsmAn.js","names":[],"sources":["../src/commands/api-keys.ts"],"sourcesContent":["/**\n * CLI command: rebase api-keys <action>\n *\n * The project's service keys, through `/api/admin/api-keys`, authenticated with\n * the service key from `.env`.\n *\n * Subcommands:\n * list — List the service keys (masked): kind, scopes, roles\n * get — Show one key\n * create — Create a service key holding the scopes named on the line\n * revoke — Revoke a key\n * scopes — List the scopes this backend knows, and which the caller holds\n */\nimport chalk from \"chalk\";\nimport type arg from \"arg\";\nimport { createRebaseClient, RebaseApiError } from \"@rebasepro/client\";\nimport {\n ADMIN_SCOPES,\n DATA_PLANE_SCOPES,\n KEY_MANAGEMENT_SCOPES,\n parseScope,\n type ApiKeyMasked,\n type ApiKeyWithSecret,\n type CreateApiKeyRequest,\n type ScopeSummary\n} from \"@rebasepro/types\";\nimport {\n requireProjectRoot,\n readEnvFile\n} from \"../utils/project\";\nimport { parseCommandArgs, UsageError, wantsHelp } from \"../utils/args\";\nimport { unknownCommand } from \"../utils/unknown-command\";\nimport { cliUserAgent } from \"../utils/version\";\nimport { serverUnreachableHint } from \"../utils/dev-server\";\nimport fs from \"fs\";\nimport path from \"path\";\n\n/** Everything the switch below dispatches, for the did-you-mean. */\nexport const API_KEYS_SUBCOMMANDS = [\"list\", \"get\", \"create\", \"revoke\", \"scopes\"] as const;\n\n/* ═══════════════════════════════════════════════════════════════\n Env helper — reads SERVICE_KEY and PORT from .env\n ═══════════════════════════════════════════════════════════════ */\n\n/**\n * Was a hand-rolled `indexOf(\"=\")` loop. It keyed `export KEY=value` as\n * `export KEY` and carried a trailing `# comment` into the value — so a key\n * that was present read as absent, or reached an `Authorization` header with a\n * comment attached and came back 401. See `readEnvFile`.\n */\nconst loadEnv = readEnvFile;\n\n/**\n * Where this project's backend is — or why the CLI will not say.\n *\n * `configured` is an address the developer named; `running` is the one this\n * project's backend recorded when it bound, and is still serving on. There is\n * no third, guessed, answer: the request carries the project's service key —\n * the `admin` role, every scope — and an address the CLI only guessed is one it\n * would hand that key to without knowing whose server answers.\n */\nexport type BackendAddress =\n | { url: string; source: \"configured\" | \"running\" }\n | { url: null; reason: string };\n\n/** Whether a process with this pid is alive and ours to signal. */\nfunction isAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n // ESRCH: gone. EPERM: alive, but another user's — not this project's backend.\n return false;\n }\n}\n\n/**\n * The address the service key may be sent to. Shared with `rebase storage`.\n *\n * In order:\n *\n * 1. `REBASE_BASE_URL`, in the shell or in `.env` — the developer said where.\n * 2. `.rebase/state.json`, which this project's backend writes when it binds\n * and removes when it stops — and only while the pid it names is alive,\n * because a backend that was killed leaves the file behind.\n *\n * Nothing else. `.env`'s `PORT` was the fallback, and every scaffold writes\n * `PORT=3001`: with `rebase dev` stopped, `rebase api-keys list` sent this\n * project's service key to whatever listened on 3001 — on the tester's machine,\n * another project's server. `.rebase-dev-url` is not enough on its own either:\n * a `rebase dev` that was killed leaves it behind, pointing at a port some\n * other server may have taken since.\n */\nexport function resolveBackendAddress(env: Record<string, string>, projectRoot: string): BackendAddress {\n const configured = process.env.REBASE_BASE_URL?.trim() || env.REBASE_BASE_URL?.trim();\n if (configured) return { url: configured, source: \"configured\" };\n\n const state = readBackendState(projectRoot);\n if (state && isAlive(state.pid)) return { url: state.url, source: \"running\" };\n\n const last = state ? ` The last one recorded here, at ${state.url} (pid ${state.pid}), has stopped.` : \"\";\n return {\n url: null,\n reason: `This project's server is not running, so the service key was not sent anywhere.${last} ` +\n \"Start it with `rebase dev`. If it runs some other way — `rebase start`, a container — \" +\n \"set REBASE_BASE_URL in .env to its address.\"\n };\n}\n\n/** What `.rebase/state.json` says about the backend that wrote it, or null. */\nfunction readBackendState(projectRoot: string): { url: string; pid: number } | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(fs.readFileSync(path.join(projectRoot, \".rebase\", \"state.json\"), \"utf-8\"));\n } catch {\n return null;\n }\n if (!isRecord(parsed) || typeof parsed.pid !== \"number\" || !Number.isInteger(parsed.pid) || parsed.pid <= 0) return null;\n const url = typeof parsed.baseUrl === \"string\" && parsed.baseUrl.trim()\n ? parsed.baseUrl.trim()\n : typeof parsed.port === \"number\" ? `http://localhost:${parsed.port}` : null;\n\n return url ? { url, pid: parsed.pid } : null;\n}\n\n/**\n * The address to send the service key to, or the end of the command.\n *\n * Exits before any request is made: the refusal is the point.\n */\nexport function requireBackendUrl(env: Record<string, string>, projectRoot: string): string {\n const address = resolveBackendAddress(env, projectRoot);\n if (address.url !== null) return address.url;\n\n console.error(chalk.red(\"✗ No server to send the request to.\"));\n console.error(chalk.gray(` ${address.reason}`));\n process.exit(1);\n}\n\n/* ═══════════════════════════════════════════════════════════════\n The backend, through the SDK\n ═══════════════════════════════════════════════════════════════ */\n\ntype ProjectClient = ReturnType<typeof createRebaseClient>;\n\ninterface Connection {\n client: ProjectClient;\n baseUrl: string;\n /** The variable the service key was read from, for a hint that names it. */\n keyVariable: ServiceKeyVariable;\n}\n\n/** Where a service key is read from: the name a scaffold writes, or the older one. */\ntype ServiceKeyVariable = \"REBASE_SERVICE_KEY\" | \"SERVICE_KEY\";\n\n/**\n * An SDK client for this project's backend, holding the service key.\n *\n * The service key is the project's own machine identity — the `admin` role,\n * every scope — so it is what may list, mint and revoke service keys. It is a\n * static bearer token: no session to restore or refresh, and no socket.\n */\nfunction connect(): Connection {\n const projectRoot = requireProjectRoot();\n const env = loadEnv(projectRoot);\n const keyVariable: ServiceKeyVariable = env.SERVICE_KEY ? \"SERVICE_KEY\" : \"REBASE_SERVICE_KEY\";\n const serviceKey = env[keyVariable];\n\n if (!serviceKey) {\n console.error(chalk.red(\"✗ REBASE_SERVICE_KEY not found in .env — required to manage API keys.\"));\n process.exit(1);\n }\n const baseUrl = requireBackendUrl(env, projectRoot);\n\n const client = createRebaseClient({\n baseUrl,\n token: serviceKey,\n realtime: false,\n headers: { \"User-Agent\": cliUserAgent() },\n auth: { persistSession: false, autoRefresh: false }\n });\n return { client, baseUrl, keyVariable };\n}\n\n/**\n * What to print when a request fails: the server's error code and message,\n * which is what says why — `SCOPE_EXCEEDS_CREATOR`, `INVALID_SCOPES`,\n * `ROLE_EXCEEDS_CREATOR`, `KEY_MANAGEMENT_SCOPE` — and a hint where one helps.\n *\n * Exported so its tests can read the lines without a server.\n */\nexport function describeFailure(\n action: string,\n error: unknown,\n baseUrl: string,\n keyVariable: ServiceKeyVariable = \"REBASE_SERVICE_KEY\"\n): string[] {\n if (!(error instanceof RebaseApiError)) {\n return [`✗ ${action}: ${error instanceof Error ? error.message : String(error)}`];\n }\n if (error.status === 0 || error.code === \"NETWORK_ERROR\") {\n return [`✗ ${action}: ${error.message}`, ...serverUnreachableHint(baseUrl)];\n }\n\n const label = [error.code, error.status ? `(${error.status})` : undefined].filter(Boolean).join(\" \");\n const lines = [`✗ ${action}${label ? ` — ${label}` : \"\"}: ${error.message}`];\n\n if (error.status === 401) {\n lines.push(` The server at ${baseUrl} did not accept ${keyVariable} from .env — is it this project's server?`);\n }\n // The message names the target that is not there; what *is* there rides\n // in `details`, and is the thing to pick from.\n if (error.code === \"UNKNOWN_SCOPE_TARGET\" && isRecord(error.details)) {\n for (const [kind, title] of [[\"collections\", \"Collections\"], [\"buckets\", \"Buckets\"], [\"functions\", \"Functions\"]] as const) {\n const names = error.details[kind];\n if (Array.isArray(names) && names.length > 0) {\n lines.push(` ${title}: ${names.map(String).join(\", \")}`);\n }\n }\n }\n return lines;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction fail(action: string, error: unknown, connection: Connection): never {\n for (const line of describeFailure(action, error, connection.baseUrl, connection.keyVariable)) {\n console.error(line.startsWith(\"✗\") ? chalk.red(line) : chalk.gray(line));\n }\n process.exit(1);\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Entry\n ═══════════════════════════════════════════════════════════════ */\n\nexport async function apiKeysCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void> {\n // `--help` is answered before dispatch, never by a handler. `cli.ts` only\n // rewrites the subcommand to `\"--help\"` when none was named, so\n // `rebase api-keys list --help` used to *list the keys* and\n // `rebase api-keys revoke --help` sent `DELETE /api/admin/api-keys/--help`.\n if (!subcommand || subcommand === \"--help\" || wantsHelp(rawArgs)) {\n printApiKeysHelp();\n return;\n }\n\n switch (subcommand) {\n case \"list\":\n await listKeys(rawArgs);\n break;\n case \"get\":\n await getKey(rawArgs);\n break;\n case \"create\":\n await createKey(rawArgs);\n break;\n case \"revoke\":\n await revokeKey(rawArgs);\n break;\n case \"scopes\":\n await listScopes(rawArgs);\n break;\n default:\n // The shape every other family uses. This one printed a bare line\n // to stderr *and* the whole help page to stdout, so a typo wrote\n // twenty lines to a stream a `--json` caller reads, with no `✗`, no\n // pointer at `--help`, and no did-you-mean — `craete` is one\n // transposition from `create`.\n unknownCommand(subcommand, API_KEYS_SUBCOMMANDS, \"api-keys\");\n }\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Showing a key\n ═══════════════════════════════════════════════════════════════ */\n\nfunction keyStatus(key: ApiKeyMasked, now: Date): string {\n if (key.revoked_at) return chalk.red(\"revoked\");\n if (key.expires_at && new Date(key.expires_at) < now) return chalk.yellow(\"expired\");\n return chalk.green(\"active\");\n}\n\n/**\n * The lines that describe one key: what it is, what it may do and whom it\n * runs as.\n *\n * A service key runs as the RLS role `service` plus its own `roles`; a\n * personal key runs as its owner's roles as they are when it is used, so it\n * has none of its own to show.\n *\n * Exported so its tests can read the lines without a server.\n */\nexport function describeKey(key: ApiKeyMasked, now: Date = new Date()): string[] {\n const field = (label: string, value: string) => ` ${chalk.gray(`${label}:`.padEnd(12))}${value}`;\n const roles = key.kind === \"personal\"\n ? `its owner's (${key.owner_uid ?? \"unknown\"})`\n : [\"service\", ...key.roles].join(\", \");\n\n const lines = [\n ` ${chalk.bold(key.name)} ${chalk.gray(`[${key.key_prefix}•••]`)} ${keyStatus(key, now)}`,\n field(\"ID\", key.id),\n field(\"Kind\", key.kind),\n field(\"Scopes\", key.scopes.length > 0 ? key.scopes.join(\", \") : chalk.gray(\"none\")),\n field(\"Roles\", roles)\n ];\n if (key.rate_limit !== null) lines.push(field(\"Rate limit\", `${key.rate_limit} requests / 15 min`));\n if (key.expires_at) lines.push(field(\"Expires\", new Date(key.expires_at).toLocaleDateString()));\n lines.push(field(\"Created\", new Date(key.created_at).toLocaleDateString()));\n if (key.last_used_at) lines.push(field(\"Last used\", new Date(key.last_used_at).toLocaleDateString()));\n return lines;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n list\n ═══════════════════════════════════════════════════════════════ */\n\n/** The flags `rebase api-keys list` takes: none of its own. */\nexport const LIST_KEYS_FLAGS = {} as const;\n\nasync function listKeys(rawArgs: string[]): Promise<void> {\n parseCommandArgs({\n spec: LIST_KEYS_FLAGS,\n rawArgs,\n commandWords: 2,\n command: \"api-keys list\",\n maxPositionals: 0\n });\n\n const connection = connect();\n const { client } = connection;\n let keys: ApiKeyMasked[];\n try {\n ({ keys } = await client.apiKeys.listKeys());\n } catch (e: unknown) {\n fail(\"Failed to list API keys\", e, connection);\n }\n\n console.log(\"\");\n console.log(chalk.bold(\" 🔑 API Keys\"));\n console.log(\"\");\n\n if (keys.length === 0) {\n console.log(chalk.gray(\" No API keys found.\"));\n console.log(\"\");\n return;\n }\n\n const now = new Date();\n for (const key of keys) {\n for (const line of describeKey(key, now)) console.log(line);\n console.log(\"\");\n }\n}\n\n/* ═══════════════════════════════════════════════════════════════\n get\n ═══════════════════════════════════════════════════════════════ */\n\n/** The flags `rebase api-keys get` takes. */\nexport const GET_KEY_FLAGS = {\n \"--id\": String\n} as const;\n\n/**\n * Which key this invocation names, as a positional or as `--id`.\n *\n * Exported so its tests can drive the real parser rather than a copy of it.\n */\nexport function resolveGetKeyArgs(rawArgs: string[]): { id?: string } {\n const { flags, positionals } = parseCommandArgs({\n spec: GET_KEY_FLAGS,\n rawArgs,\n commandWords: 2,\n command: \"api-keys get\",\n maxPositionals: 1\n });\n\n return { id: flags[\"--id\"] || positionals[0] };\n}\n\nasync function getKey(rawArgs: string[]): Promise<void> {\n const { id } = resolveGetKeyArgs(rawArgs);\n if (!id) {\n throw new UsageError(\"Key ID is required: rebase api-keys get <key-id> (`rebase api-keys list` shows them).\");\n }\n\n const connection = connect();\n const { client } = connection;\n let key: ApiKeyMasked;\n try {\n ({ key } = await client.apiKeys.getKey(id));\n } catch (e: unknown) {\n fail(\"Failed to read API key\", e, connection);\n }\n\n console.log(\"\");\n for (const line of describeKey(key)) console.log(line);\n console.log(\"\");\n}\n\n/* ═══════════════════════════════════════════════════════════════\n create\n ═══════════════════════════════════════════════════════════════ */\n\n/** The flags `rebase api-keys create` takes. */\nexport const CREATE_KEY_FLAGS = {\n \"--name\": String,\n \"--scopes\": [String],\n \"--full-access\": Boolean,\n \"--roles\": [String],\n \"--rate-limit\": Number,\n \"--expires-in\": String,\n \"--expires-at\": String,\n \"-n\": \"--name\"\n} satisfies arg.Spec;\n\n/**\n * Options `create` refuses by name, each with the flag that does that job.\n *\n * Checked before the line is parsed: the strict parser would answer them\n * \"unknown option\", which does not say what to type instead.\n */\nexport const RETIRED_CREATE_OPTIONS: Readonly<Record<string, string>> = {\n \"--permissions\":\n \"--permissions is gone: name what the key may do with --scopes, e.g. \" +\n \"--scopes data:read:posts,data:write:posts (`rebase api-keys scopes` lists them).\",\n \"--admin\":\n \"--admin is gone: give the key the RLS role with --roles admin, and the admin-plane scopes it needs \" +\n \"with --scopes, e.g. --scopes users:read,schema:read.\",\n \"--expires\":\n \"--expires is gone: use --expires-in <days> (e.g. --expires-in 90) or --expires-at <ISO date>.\"\n};\n\n/** Refuse a retired option, wherever on the line and however it is spelled. */\nfunction refuseRetiredOptions(rawArgs: string[]): void {\n for (const token of rawArgs.slice(2)) {\n // Past `--` everything is a value, never an option.\n if (token === \"--\") return;\n const name = token.split(\"=\", 1)[0];\n const replacement = Object.prototype.hasOwnProperty.call(RETIRED_CREATE_OPTIONS, name)\n ? RETIRED_CREATE_OPTIONS[name]\n : undefined;\n if (replacement) throw new UsageError(replacement);\n }\n}\n\n/**\n * A list flag's values, whether repeated (`--scopes a --scopes b`) or\n * comma-separated (`--scopes a,b`) — or both — trimmed and deduplicated.\n * Whitespace separates too: no scope or role name contains any.\n */\nfunction splitList(values: readonly string[] | undefined): string[] {\n const out = new Set<string>();\n for (const value of values ?? []) {\n for (const entry of value.split(/[\\s,]+/)) {\n if (entry) out.add(entry);\n }\n }\n return [...out];\n}\n\nconst DAY_MS = 86_400_000;\n\nfunction resolveExpiry(expiresIn: string | undefined, expiresAt: string | undefined, now: Date): string | null {\n if (expiresIn !== undefined && expiresAt !== undefined) {\n throw new UsageError(\"Pass --expires-in or --expires-at, not both.\");\n }\n if (expiresIn !== undefined) {\n const days = /^\\d+$/.test(expiresIn.trim()) ? Number(expiresIn.trim()) : NaN;\n if (!Number.isSafeInteger(days) || days < 1) {\n throw new UsageError(`--expires-in takes a whole number of days, e.g. --expires-in 90 (got \"${expiresIn}\").`);\n }\n return new Date(now.getTime() + days * DAY_MS).toISOString();\n }\n if (expiresAt !== undefined) {\n const parsed = new Date(expiresAt);\n if (isNaN(parsed.getTime())) {\n throw new UsageError(`--expires-at takes an ISO date, e.g. --expires-at 2027-01-31 (got \"${expiresAt}\").`);\n }\n if (parsed.getTime() <= now.getTime()) {\n throw new UsageError(`--expires-at must be in the future (got ${parsed.toISOString()}).`);\n }\n return parsed.toISOString();\n }\n return null;\n}\n\n/** What `rebase api-keys create` was asked to mint. */\nexport interface CreateKeyPlan {\n name: string;\n /** The scopes named with `--scopes`, or `\"held\"` for `--full-access`. */\n scopes: string[] | \"held\";\n /** RLS roles beside `service`. */\n roles: string[];\n rate_limit: number | null;\n expires_at: string | null;\n}\n\n/**\n * What this invocation asks to be created.\n *\n * The name may be given either way — `--name \"My Key\"` or as the single\n * positional — and under the old permissive parse an undeclared flag became\n * that positional: `rebase api-keys create --debug --full-access` created a\n * key called `--debug` with access to everything, and `--debug` is what the\n * CLI prints after every failure as the thing to re-run with. Strict parsing\n * makes the flag an error instead of a name.\n *\n * What the key may do has to be asked for by name — `--scopes` or\n * `--full-access` — never defaulted: a forgotten flag must not mint a key that\n * reaches everything.\n *\n * Exported so its tests can drive the real parser rather than a copy of it.\n */\nexport function resolveCreateKeyArgs(rawArgs: string[], now: Date = new Date()): CreateKeyPlan {\n refuseRetiredOptions(rawArgs);\n\n const { flags, positionals } = parseCommandArgs({\n spec: CREATE_KEY_FLAGS,\n rawArgs,\n commandWords: 2,\n command: \"api-keys create\",\n maxPositionals: 1\n });\n\n const name = (flags[\"--name\"] || positionals[0] || \"\").trim();\n if (!name) {\n throw new UsageError('A key needs a name: rebase api-keys create \"CI\" --scopes data:read');\n }\n\n const named = splitList(flags[\"--scopes\"]);\n const fullAccess = flags[\"--full-access\"] === true;\n if (fullAccess && named.length > 0) {\n throw new UsageError(\"Pass --scopes or --full-access, not both: --full-access already means every scope you hold.\");\n }\n if (!fullAccess && named.length === 0) {\n throw new UsageError(\n \"Name what the key may do: --scopes data:read:posts,data:write:posts, or --full-access for every \" +\n \"scope you hold. `rebase api-keys scopes` lists them.\"\n );\n }\n\n const rateLimit = flags[\"--rate-limit\"];\n if (rateLimit !== undefined && (!Number.isSafeInteger(rateLimit) || rateLimit < 1)) {\n throw new UsageError(\"--rate-limit takes a whole number of requests per 15-minute window, e.g. --rate-limit 500.\");\n }\n\n return {\n name,\n scopes: fullAccess ? \"held\" : named,\n roles: splitList(flags[\"--roles\"]),\n rate_limit: rateLimit ?? null,\n expires_at: resolveExpiry(flags[\"--expires-in\"], flags[\"--expires-at\"], now)\n };\n}\n\n/**\n * The scopes `--full-access` puts on a key: every one the caller holds, less\n * key management, which no key may hold.\n *\n * Exported so its tests can check the subtraction without a server.\n */\nexport function grantableScopes(held: readonly string[]): string[] {\n const management: readonly string[] = KEY_MANAGEMENT_SCOPES;\n return held.filter(entry => !management.includes(parseScope(entry)?.scope ?? entry));\n}\n\nasync function createKey(rawArgs: string[]): Promise<void> {\n const plan = resolveCreateKeyArgs(rawArgs);\n const connection = connect();\n const { client } = connection;\n\n let scopes: string[];\n if (plan.scopes === \"held\") {\n let held: string[];\n try {\n ({ held } = await client.personalKeys.listScopes());\n } catch (e: unknown) {\n fail(\"Failed to read the scopes you hold\", e, connection);\n }\n scopes = grantableScopes(held);\n if (scopes.length === 0) {\n console.error(chalk.red(\"✗ You hold no scope a key may carry, so --full-access has nothing to grant.\"));\n process.exit(1);\n }\n } else {\n scopes = plan.scopes;\n }\n\n const request: CreateApiKeyRequest = {\n name: plan.name,\n scopes,\n ...(plan.roles.length > 0 ? { roles: plan.roles } : {}),\n ...(plan.rate_limit !== null ? { rate_limit: plan.rate_limit } : {}),\n ...(plan.expires_at !== null ? { expires_at: plan.expires_at } : {})\n };\n\n let created: ApiKeyWithSecret;\n try {\n ({ key: created } = await client.apiKeys.createKey(request));\n } catch (e: unknown) {\n fail(\"Failed to create API key\", e, connection);\n }\n\n console.log(\"\");\n console.log(chalk.bold.green(\" ✓ API key created\"));\n console.log(\"\");\n for (const line of describeKey(created)) console.log(line);\n console.log(\"\");\n console.log(chalk.bold.yellow(\" ⚠ Copy your key now — it won't be shown again:\"));\n console.log(\"\");\n console.log(` ${chalk.cyan(created.key)}`);\n console.log(\"\");\n}\n\n/* ═══════════════════════════════════════════════════════════════\n revoke\n ═══════════════════════════════════════════════════════════════ */\n\n/** The flags `rebase api-keys revoke` takes. */\nexport const REVOKE_KEY_FLAGS = {\n \"--id\": String\n} as const;\n\n/**\n * Which key this invocation names.\n *\n * The id is a positional, so the permissive parse handed one straight to the\n * DELETE: `rebase api-keys revoke --foo` sent\n * `DELETE /api/admin/api-keys/--foo`, and `rebase --debug api-keys revoke <id>`\n * shifted the words along and revoked the key named `revoke`.\n *\n * Exported so its tests can drive the real parser rather than a copy of it.\n */\nexport function resolveRevokeKeyArgs(rawArgs: string[]): { id?: string } {\n const { flags, positionals } = parseCommandArgs({\n spec: REVOKE_KEY_FLAGS,\n rawArgs,\n commandWords: 2,\n command: \"api-keys revoke\",\n maxPositionals: 1\n });\n\n return { id: flags[\"--id\"] || positionals[0] };\n}\n\nasync function revokeKey(rawArgs: string[]): Promise<void> {\n const { id } = resolveRevokeKeyArgs(rawArgs);\n\n if (!id) {\n throw new UsageError(\"Key ID is required: rebase api-keys revoke <key-id> (`rebase api-keys list` shows them).\");\n }\n\n const connection = connect();\n const { client } = connection;\n try {\n await client.apiKeys.revokeKey(id);\n } catch (e: unknown) {\n fail(\"Failed to revoke API key\", e, connection);\n }\n\n console.log(\"\");\n console.log(chalk.bold.green(\" ✓ API key revoked\"));\n console.log(` ${chalk.gray(\"ID:\")} ${id}`);\n console.log(\"\");\n}\n\n/* ═══════════════════════════════════════════════════════════════\n scopes\n ═══════════════════════════════════════════════════════════════ */\n\n/** The flags `rebase api-keys scopes` takes: none of its own. */\nexport const SCOPES_LIST_FLAGS = {} as const;\n\nconst PLANES: ReadonlyArray<{ plane: ScopeSummary[\"plane\"]; title: string; note: string }> = [\n { plane: \"data\", title: \"Data\", note: \"narrow what a key reaches; row-level security still decides the rows\" },\n { plane: \"admin\", title: \"Admin\", note: \"nobody holds these unless a role grants them; the admin role holds all\" },\n { plane: \"app\", title: \"App\", note: \"declared by this app under auth.scopes on the users collection\" }\n];\n\n/**\n * The scope catalogue as printed lines: one section per plane, each scope with\n * its label and what its target names, marked when the caller holds it.\n *\n * Exported so its tests can read the lines without a server.\n */\nexport function describeScopes(scopes: readonly ScopeSummary[], held: readonly string[]): string[] {\n const management: readonly string[] = KEY_MANAGEMENT_SCOPES;\n const width = Math.max(0, ...scopes.map(s => s.scope.length)) + 2;\n const labelWidth = Math.max(0, ...scopes.map(s => s.label.length)) + 2;\n const lines: string[] = [];\n for (const { plane, title, note } of PLANES) {\n const inPlane = scopes.filter(s => s.plane === plane);\n if (inPlane.length === 0) continue;\n lines.push(` ${chalk.bold(title)} ${chalk.gray(`— ${note}`)}`);\n for (const s of inPlane) {\n const mark = held.includes(s.scope) ? chalk.green(\"✓\") : \" \";\n const extra = management.includes(s.scope)\n ? chalk.gray(\"never on a key\")\n : s.target ? chalk.gray(`:<${s.target}>`) : \"\";\n lines.push(` ${mark} ${s.scope.padEnd(width)}${extra ? s.label.padEnd(labelWidth) : s.label}${extra}`);\n }\n lines.push(\"\");\n }\n return lines;\n}\n\nasync function listScopes(rawArgs: string[]): Promise<void> {\n parseCommandArgs({\n spec: SCOPES_LIST_FLAGS,\n rawArgs,\n commandWords: 2,\n command: \"api-keys scopes\",\n maxPositionals: 0\n });\n\n const connection = connect();\n const { client } = connection;\n let catalogue: { scopes: ScopeSummary[]; held: string[] };\n try {\n catalogue = await client.personalKeys.listScopes();\n } catch (e: unknown) {\n fail(\"Failed to read the scopes\", e, connection);\n }\n\n console.log(\"\");\n console.log(chalk.bold(\" Scopes\") + chalk.gray(\" (✓ = you hold it; :<target> narrows it to one)\"));\n console.log(\"\");\n for (const line of describeScopes(catalogue.scopes, catalogue.held)) console.log(line);\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Help\n ═══════════════════════════════════════════════════════════════ */\n\nfunction printApiKeysHelp() {\n const keyable = ADMIN_SCOPES.filter(scope => !(KEY_MANAGEMENT_SCOPES as readonly string[]).includes(scope));\n console.log(`\n${chalk.bold(\"rebase api-keys\")} — Manage service API keys\n\n${chalk.green.bold(\"Usage\")}\n rebase api-keys ${chalk.blue(\"<command>\")} [options]\n\n${chalk.green.bold(\"Commands\")}\n ${chalk.blue.bold(\"list\")} List the service keys: kind, scopes, roles\n ${chalk.blue.bold(\"get\")} ${chalk.gray(\"<id>\")} Show one key\n ${chalk.blue.bold(\"create\")} Create a service key\n ${chalk.blue.bold(\"revoke\")} ${chalk.gray(\"<id>\")} Revoke a key\n ${chalk.blue.bold(\"scopes\")} List the scopes this backend knows, and which you hold\n\n${chalk.green.bold(\"create Options\")}\n ${chalk.blue(\"--name, -n\")} Key name ${chalk.gray(\"(required; or the first argument)\")}\n ${chalk.blue(\"--scopes\")} What the key may do, comma-separated or repeated\n ${chalk.gray(\"(required unless --full-access)\")}\n ${chalk.blue(\"--full-access\")} Every scope you hold, less keys:read and keys:write\n ${chalk.blue(\"--roles\")} RLS roles the key runs as beside ${chalk.gray(\"service\")}, e.g. admin\n ${chalk.blue(\"--rate-limit\")} Requests per 15-min window ${chalk.gray(\"(default: the server's API-key limit)\")}\n ${chalk.blue(\"--expires-in\")} Days until the key expires\n ${chalk.blue(\"--expires-at\")} Expiry as an ISO date, e.g. 2027-01-31\n\n${chalk.green.bold(\"get / revoke Options\")}\n ${chalk.blue(\"--id\")} API key ID ${chalk.gray(\"(or the first argument)\")}\n\n${chalk.green.bold(\"Scopes\")}\n A scope is ${chalk.blue(\"resource:action\")}, optionally narrowed to one target:\n ${chalk.blue(\"data:read:posts\")} reads the posts collection and nothing else.\n Data ${DATA_PLANE_SCOPES.join(\", \")}\n ${chalk.gray(\"target: a collection slug, a storage source id (default), a function name\")}\n Admin ${keyable.join(\", \")}\n App whatever the app declares under auth.scopes ${chalk.gray(\"(rebase api-keys scopes)\")}\n\n${chalk.green.bold(\"Examples\")}\n rebase api-keys list\n rebase api-keys create \"Analytics\" --scopes data:read:events\n rebase api-keys create -n \"Blog CI\" --scopes data:read:posts,data:write:posts --expires-in 90\n rebase api-keys create -n \"Mailer\" --scopes \"functions:invoke:send-email,storage:read:(default)\"\n rebase api-keys create -n \"Ops\" --full-access --roles admin --expires-at 2027-01-31\n rebase api-keys get abc123-def456\n rebase api-keys revoke abc123-def456\n`);\n}\n"],"mappings":"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"}
@@ -1,9 +1,8 @@
1
- import { i as failAsJson, p as requireProjectRoot } from "./project-Wp2zoyeN.js";
2
- import { a as unknownCommand, n as parseCommandArgs, r as wantsHelp } from "./args-CcBphFdj.js";
3
- import { d as findBackendApp, f as formatAppAddress, m as manifestExists, o as ManifestError, p as loadManifest, s as assessManagedCompatibility, v as staticAppAddress, x as writeManifest, y as synthesizeManifest } from "./manifest-DRp0UVTj.js";
4
- import { r as runningBackendUrl, t as devServerUrl } from "./dev-server-B1UYifZJ.js";
5
- import { M as readLink } from "./context-BM-oOMNX.js";
6
- import { r as foldableApps } from "./fold-static-BC9CYicw.js";
1
+ import { C as wantsHelp, T as unknownCommand, b as parseCommandArgs, i as failAsJson, p as requireProjectRoot } from "./project-g4K6kV1t.js";
2
+ import { d as findBackendApp, f as formatAppAddress, m as manifestExists, o as ManifestError, p as loadManifest, s as assessManagedCompatibility, v as staticAppAddress, x as writeManifest, y as synthesizeManifest } from "./manifest-nvPdLlJY.js";
3
+ import { i as runningBackendUrl, n as devServerUrl } from "./dev-server-CIZwAfZa.js";
4
+ import { M as readLink } from "./context-DHiiiJ5C.js";
5
+ import { r as foldableApps } from "./fold-static-CybSay_W.js";
7
6
  import chalk from "chalk";
8
7
  import path from "path";
9
8
  //#region src/commands/apps.ts
@@ -323,4 +322,4 @@ function loadManifestOrExit(projectRoot, asJson = false) {
323
322
  //#endregion
324
323
  export { APPS_SUBCOMMANDS, appsCommand };
325
324
 
326
- //# sourceMappingURL=apps-wG-ZTryA.js.map
325
+ //# sourceMappingURL=apps-iBXNZhVN.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"apps-wG-ZTryA.js","names":[],"sources":["../src/commands/apps.ts"],"sourcesContent":["/**\n * CLI command: rebase apps\n *\n * Inspect the apps this repository contributes to a project, adopt a\n * `rebase.json` for a project that predates it, and print the client bootstrap\n * an app needs to reach its backend.\n *\n * The distinction that runs through all of this: a *repository* declares apps,\n * a *project* owns them. Two repositories can contribute to the same project and\n * never know about each other, which is what makes a separate frontend repo — or\n * a mobile app with no repo relationship at all — an ordinary thing rather than\n * a special case.\n */\nimport path from \"path\";\nimport chalk from \"chalk\";\nimport type { RebaseAppConfig, RebaseProjectManifest } from \"@rebasepro/types\";\nimport { failAsJson, requireProjectRoot } from \"../utils/project\";\nimport { devServerUrl, runningBackendUrl } from \"../utils/dev-server\";\nimport { parseCommandArgs, wantsHelp } from \"../utils/args\";\nimport {\n assessManagedCompatibility,\n findBackendApp,\n formatAppAddress,\n loadManifest,\n ManifestError,\n manifestExists,\n staticAppAddress,\n synthesizeManifest,\n writeManifest\n} from \"../manifest\";\nimport { readLink } from \"./cloud/context\";\nimport { unknownCommand } from \"../utils/unknown-command\";\nimport { foldableApps } from \"../fold-static\";\n\nfunction printHelp(): void {\n console.log(`\n${chalk.bold(\"rebase apps\")} — the apps this repository contributes\n\n${chalk.bold(\"Usage\")}\n rebase apps list List declared apps and their build outputs\n rebase apps init Write a rebase.json inferred from this project\n rebase apps config <app> Print the client configuration for an app\n\n${chalk.bold(\"Options\")}\n --json Machine-readable output\n --force Replace an existing rebase.json (apps init), keeping\n each app's name, path and cms\n -h, --help Show this help\n`.trim());\n}\n\n/** Everything the switch below dispatches, for the did-you-mean. */\nexport const APPS_SUBCOMMANDS = [\"list\", \"init\", \"config\"] as const;\n\nexport async function appsCommand(subcommand: string | undefined, rawArgs: string[] = []): Promise<void> {\n // Help is answered before parsing, so `rebase apps config --help` prints the\n // page rather than being rejected for naming no app.\n if (!subcommand || subcommand === \"--help\" || wantsHelp(rawArgs)) {\n printHelp();\n return;\n }\n\n // Only `apps` is a command word here: this one parser serves every\n // subcommand, so the subcommand stays in the positionals and the app name\n // `apps config` takes follows it.\n const { flags: args, positionals } = parseCommandArgs({\n spec: {\n \"--json\": Boolean,\n \"--force\": Boolean\n },\n rawArgs,\n commandWords: 1,\n command: \"apps\",\n maxPositionals: 2\n });\n\n switch (subcommand) {\n case \"list\":\n await listApps(Boolean(args[\"--json\"]));\n break;\n case \"init\":\n if (positionals[1] !== undefined) {\n // It never registered one app: the name was ignored and the\n // whole manifest inferred, which is not what the reader asked for.\n console.error(chalk.red(`✗ rebase apps init takes no app name (got \"${positionals[1]}\").`));\n console.error(chalk.dim(\" It infers every app from this project and writes the whole rebase.json.\"));\n console.error(chalk.dim(\" To add one app, declare it under \\\"apps\\\" in rebase.json.\"));\n process.exit(1);\n }\n await initManifest(Boolean(args[\"--force\"]));\n break;\n case \"config\":\n await printAppConfig(positionals[1], Boolean(args[\"--json\"]));\n break;\n default:\n unknownCommand(subcommand, APPS_SUBCOMMANDS, \"apps\");\n }\n}\n\n/**\n * One app's line in `rebase apps list`.\n *\n * A static app shows its full address — the https URL when its `path` gives it\n * a hostname — and the CMS as the address a browser would open. `CMS at /` on\n * an app that lives on `admin.example.com` reads as the project's own root,\n * which is the one place that CMS is not.\n */\nexport function describeApp(name: string, app: RebaseAppConfig): string {\n switch (app.type) {\n case \"backend\":\n return app.runtime === \"custom\"\n // The context is named only when it is not the project, which is\n // the case where it changes what you would type. A workspace app\n // builds from the workspace root, and a listing that showed only\n // the Dockerfile implied a `docker build .` beside it that fails.\n ? `custom runtime — ${app.dockerfile ?? \"Dockerfile\"}`\n + (app.context && app.context !== \".\" ? ` (context: ${app.context})` : \"\")\n : `managed runtime, config: ${app.config ?? \"config\"}`;\n case \"static\": {\n const address = staticAppAddress(name, app);\n return `${app.root} → ${app.output} @ ${formatAppAddress(address)}`\n + (app.cms ? ` ${chalk.magenta(`CMS at ${formatAppAddress({ ...address, path: app.cms })}`)}` : \"\");\n }\n default:\n return \"\";\n }\n}\n\nasync function listApps(asJson: boolean): Promise<void> {\n const projectRoot = requireProjectRoot();\n const loaded = loadManifestOrExit(projectRoot, asJson);\n const compatibility = assessManagedCompatibility(loaded.manifest);\n\n if (asJson) {\n console.log(JSON.stringify(\n {\n source: loaded.source,\n rebase: loaded.manifest.rebase,\n apps: loaded.manifest.apps,\n managed: compatibility\n },\n null,\n 2\n ));\n return;\n }\n\n if (loaded.source === \"synthesized\") {\n console.log(chalk.dim(\"No rebase.json — showing the layout inferred from this project.\"));\n console.log(chalk.dim(`Run ${chalk.cyan(\"rebase apps init\")} to write it down.\\n`));\n }\n\n console.log(chalk.bold(`Rebase ${loaded.manifest.rebase}`));\n console.log(\"\");\n\n const entries = Object.entries(loaded.manifest.apps);\n if (entries.length === 0) {\n console.log(chalk.yellow(\"No apps declared.\"));\n return;\n }\n\n const width = Math.max(...entries.map(([name]) => name.length));\n for (const [name, app] of entries) {\n console.log(\n ` ${chalk.cyan(name.padEnd(width))} ${chalk.dim(app.type.padEnd(8))} ${describeApp(name, app)}`\n );\n }\n\n console.log(\"\");\n if (compatibility.eligible) {\n console.log(chalk.green(\"✓ Eligible for the managed runtime.\"));\n } else {\n console.log(chalk.yellow(\"• Uses the custom runtime:\"));\n for (const reason of compatibility.reasons) {\n console.log(chalk.dim(` ${reason}`));\n }\n }\n}\n\n/** A static app's `root`, compared as a directory: `./frontend/` is `frontend`. */\nfunction sameRoot(a: string, b: string): boolean {\n const normal = (root: string): string => path.posix.normalize(root.replace(/\\\\/g, \"/\")).replace(/\\/+$/, \"\");\n return normal(a) === normal(b);\n}\n\n/**\n * Re-infer over a manifest the project already declares, keeping what only the\n * declaration knows.\n *\n * An inferred app takes the name the file gives the app it matches — the\n * backend, or the static app with the same `root` — and that app's `path` and\n * `cms`. The name is the app's identity on a deployed project, so renaming it\n * would deploy a second app beside the first. `path` can carry the hostname the\n * app is registered on. `cms` is a client-side route that nothing in the project\n * shows. Everything else is inferred again, which is what `--force` asks for.\n *\n * A declared app the inference does not find is returned in `removed`, so the\n * command can say so rather than drop it in silence.\n */\nfunction keepDeclaredIdentity(\n inferred: RebaseProjectManifest,\n declared: RebaseProjectManifest\n): { manifest: RebaseProjectManifest; removed: Array<{ name: string; app: RebaseAppConfig }> } {\n const apps: Record<string, RebaseAppConfig> = {};\n const matched = new Set<string>();\n\n for (const [name, app] of Object.entries(inferred.apps)) {\n if (app.type === \"backend\") {\n const backend = findBackendApp(declared);\n const keptName = backend && !matched.has(backend.name) ? backend.name : name;\n matched.add(keptName);\n apps[keptName] = app;\n continue;\n }\n const match = Object.entries(declared.apps).find(([declaredName, candidate]) =>\n !matched.has(declaredName) && candidate.type === \"static\" && sameRoot(candidate.root, app.root));\n const declaredApp = match?.[1];\n if (!match || declaredApp?.type !== \"static\") {\n apps[name] = app;\n continue;\n }\n const keptName = match[0];\n matched.add(keptName);\n const address = declaredApp.path ?? app.path;\n apps[keptName] = {\n ...app,\n ...(address !== undefined ? { path: address } : {}),\n ...(declaredApp.cms !== undefined ? { cms: declaredApp.cms } : {})\n };\n }\n\n const removed = Object.entries(declared.apps)\n .filter(([name]) => !matched.has(name))\n .map(([name, app]) => ({ name, app }));\n return { manifest: { ...inferred, apps }, removed };\n}\n\nasync function initManifest(force: boolean): Promise<void> {\n const projectRoot = requireProjectRoot();\n\n let declared: RebaseProjectManifest | undefined;\n if (manifestExists(projectRoot)) {\n if (!force) {\n console.error(chalk.red(\"✗ rebase.json already exists.\"));\n console.error(chalk.dim(\" Pass --force to replace it with an inferred one, keeping each app's name, path and cms.\"));\n process.exit(1);\n }\n try {\n declared = loadManifest(projectRoot).manifest;\n } catch (err) {\n if (!(err instanceof ManifestError)) throw err;\n const issues = err.issues.map(issue => `${issue.path ? `${issue.path}: ` : \"\"}${issue.message}`);\n console.log(chalk.yellow(\"• The existing rebase.json is invalid, so no app name, path or cms in it is kept:\"));\n for (const issue of issues.length > 0 ? issues : [err.message]) console.log(chalk.dim(` ${issue}`));\n }\n }\n\n const inferred = synthesizeManifest(projectRoot);\n const { manifest, removed } = declared\n ? keepDeclaredIdentity(inferred, declared)\n : { manifest: inferred, removed: [] };\n const filePath = writeManifest(projectRoot, manifest);\n\n console.log(chalk.green(`✓ Wrote ${path.relative(projectRoot, filePath)}`));\n console.log(\"\");\n for (const [name, app] of Object.entries(manifest.apps)) {\n console.log(` ${chalk.cyan(name)} ${chalk.dim(`(${app.type})`)}`);\n }\n for (const { name, app } of removed) {\n const where = app.type === \"static\" ? `, root ${app.root}` : \"\";\n console.log(` ${chalk.yellow(name)} ${chalk.dim(`(${app.type}${where})`)} ${chalk.yellow(\"— not found in this project, removed\")}`);\n }\n\n const compatibility = assessManagedCompatibility(manifest);\n if (!compatibility.eligible) {\n console.log(\"\");\n console.log(chalk.yellow(\"This project will use the custom runtime:\"));\n for (const reason of compatibility.reasons) {\n console.log(chalk.dim(` ${reason}`));\n }\n }\n}\n\n/**\n * Print what a client needs to reach this project.\n *\n * Never prints a secret. The API URL and an app's publishable identity are meant\n * to ship inside a client bundle; anything that is not safe there does not belong\n * in output that will inevitably be pasted into a `.env` that gets committed.\n */\nasync function printAppConfig(appName: string | undefined, asJson: boolean): Promise<void> {\n const projectRoot = requireProjectRoot();\n const loaded = loadManifestOrExit(projectRoot, asJson);\n\n if (!appName) {\n if (asJson) {\n failAsJson(\"Which app? Usage: rebase apps config <app>\", \"app_not_named\",\n `Declared: ${Object.keys(loaded.manifest.apps).join(\", \") || \"(none)\"}`);\n }\n console.error(chalk.red(\"✗ Which app? Usage: rebase apps config <app>\"));\n process.exit(1);\n }\n\n const app = loaded.manifest.apps[appName];\n if (!app) {\n if (asJson) {\n failAsJson(`No app named \"${appName}\" in rebase.json.`, \"app_not_found\",\n `Declared: ${Object.keys(loaded.manifest.apps).join(\", \") || \"(none)\"}`);\n }\n console.error(chalk.red(`✗ No app named \"${appName}\" in rebase.json.`));\n console.error(chalk.dim(` Declared: ${Object.keys(loaded.manifest.apps).join(\", \") || \"(none)\"}`));\n process.exit(1);\n }\n\n const link = readLink(projectRoot);\n // An app the backend bundle serves calls the API on its own origin, so the\n // right value is empty — wherever the project is linked, and whatever a\n // dev server once wrote down. A URL here is baked into the build and\n // follows the bundle into production.\n const sameOrigin = servedByBackend(loaded.manifest, appName);\n const apiUrl = sameOrigin ? \"\" : resolveApiUrl(projectRoot, link);\n\n const config = {\n app: appName,\n type: app.type,\n apiUrl: apiUrl ?? null,\n sameOrigin,\n project: link?.projectId ?? link?.slug ?? null\n };\n\n if (asJson) {\n console.log(JSON.stringify(config, null, 2));\n return;\n }\n\n if (sameOrigin) {\n console.log(chalk.bold(`# ${appName}`));\n console.log(\"\");\n console.log(\"VITE_API_URL=\");\n console.log(\"\");\n console.log(chalk.dim(`Empty on purpose: \\`rebase build\\` folds ${appName} into the backend bundle, so it`));\n console.log(chalk.dim(\"calls the API on the same origin it is served from, locally and deployed alike.\"));\n console.log(chalk.dim(\"(`rebase dev` points it at the dev backend by itself.)\"));\n return;\n }\n\n // Whether the checkout is linked is a fact about the link, not about\n // whether `rebase dev` happens to be running: a running dev's address\n // used to fill the same slot, and the notice disappeared with it.\n if (!link?.apiUrl) {\n console.log(chalk.yellow(\"This checkout is not linked to a project yet.\"));\n // `rebase cloud link`, not `rebase link`. There has never been a\n // top-level `link` command — `cli.ts` dispatches `cloud`, and the link\n // lives inside that family — so this hint named something that exits 1\n // on the very screen that exists to tell you what to run next.\n console.log(chalk.dim(` Run ${chalk.cyan(\"rebase cloud link\")} (cloud) or ${chalk.cyan(\"rebase cloud link <url>\")} (self-hosted).`));\n console.log(chalk.dim(` Until then, this is the address ${chalk.cyan(\"rebase dev\")} serves this project on.`));\n console.log(\"\");\n }\n\n console.log(chalk.bold(`# ${appName}`));\n console.log(\"\");\n // Unlinked: the dev backend this project runs on, not a fixed 3001 — `rebase dev`\n // derives a port per project.\n console.log(`VITE_API_URL=${apiUrl ?? devServerUrl(projectRoot).url}`);\n console.log(\"\");\n console.log(chalk.dim(\"Then, in the app:\"));\n console.log(chalk.dim(\" const rebase = createRebaseClient({ baseUrl: import.meta.env.VITE_API_URL });\"));\n}\n\n/**\n * Work out the API base URL for this checkout.\n *\n * Prefers an explicit link, then the dev server's own record of where it bound.\n * The dev port is chosen dynamically, so a hardcoded default would be wrong on\n * any machine running more than one project.\n */\nfunction resolveApiUrl(projectRoot: string, link: ReturnType<typeof readLink>): string | undefined {\n if (link?.apiUrl) return link.apiUrl;\n // Only a dev server that is still running: the state file outlives the\n // process, and a port nothing listens on is not an address.\n return runningBackendUrl(projectRoot) ?? undefined;\n}\n\n/**\n * Whether `rebase build` folds this static app into the backend bundle, which\n * then serves it on the API's own origin: a managed backend, and an app with\n * built output to fold. The same predicate the build folds by.\n */\nexport function servedByBackend(manifest: ReturnType<typeof loadManifest>[\"manifest\"], appName: string): boolean {\n const backend = findBackendApp(manifest);\n if (!backend || backend.app.type !== \"backend\" || backend.app.runtime === \"custom\") return false;\n return foldableApps(manifest).apps.some(app => app.name === appName);\n}\n\nfunction loadManifestOrExit(projectRoot: string, asJson = false): ReturnType<typeof loadManifest> {\n try {\n return loadManifest(projectRoot);\n } catch (err) {\n if (err instanceof ManifestError) {\n // A caller that asked for JSON gets one on this exit too. It used\n // to get the human bullet list on stderr and an empty stdout —\n // `apps list --json` against the one manifest a caller most needs\n // to be told about.\n if (asJson) {\n failAsJson(err.message, \"manifest_invalid\", \"Fix rebase.json, then run this again.\",\n err.issues.map(issue => ({ path: issue.path, message: issue.message })));\n }\n console.error(chalk.red(`✗ ${err.message}`));\n for (const issue of err.issues) {\n console.error(chalk.red(` ${issue.path ? `${issue.path}: ` : \"\"}${issue.message}`));\n }\n process.exit(1);\n }\n throw err;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"apps-iBXNZhVN.js","names":[],"sources":["../src/commands/apps.ts"],"sourcesContent":["/**\n * CLI command: rebase apps\n *\n * Inspect the apps this repository contributes to a project, adopt a\n * `rebase.json` for a project that predates it, and print the client bootstrap\n * an app needs to reach its backend.\n *\n * The distinction that runs through all of this: a *repository* declares apps,\n * a *project* owns them. Two repositories can contribute to the same project and\n * never know about each other, which is what makes a separate frontend repo — or\n * a mobile app with no repo relationship at all — an ordinary thing rather than\n * a special case.\n */\nimport path from \"path\";\nimport chalk from \"chalk\";\nimport type { RebaseAppConfig, RebaseProjectManifest } from \"@rebasepro/types\";\nimport { failAsJson, requireProjectRoot } from \"../utils/project\";\nimport { devServerUrl, runningBackendUrl } from \"../utils/dev-server\";\nimport { parseCommandArgs, wantsHelp } from \"../utils/args\";\nimport {\n assessManagedCompatibility,\n findBackendApp,\n formatAppAddress,\n loadManifest,\n ManifestError,\n manifestExists,\n staticAppAddress,\n synthesizeManifest,\n writeManifest\n} from \"../manifest\";\nimport { readLink } from \"./cloud/context\";\nimport { unknownCommand } from \"../utils/unknown-command\";\nimport { foldableApps } from \"../fold-static\";\n\nfunction printHelp(): void {\n console.log(`\n${chalk.bold(\"rebase apps\")} — the apps this repository contributes\n\n${chalk.bold(\"Usage\")}\n rebase apps list List declared apps and their build outputs\n rebase apps init Write a rebase.json inferred from this project\n rebase apps config <app> Print the client configuration for an app\n\n${chalk.bold(\"Options\")}\n --json Machine-readable output\n --force Replace an existing rebase.json (apps init), keeping\n each app's name, path and cms\n -h, --help Show this help\n`.trim());\n}\n\n/** Everything the switch below dispatches, for the did-you-mean. */\nexport const APPS_SUBCOMMANDS = [\"list\", \"init\", \"config\"] as const;\n\nexport async function appsCommand(subcommand: string | undefined, rawArgs: string[] = []): Promise<void> {\n // Help is answered before parsing, so `rebase apps config --help` prints the\n // page rather than being rejected for naming no app.\n if (!subcommand || subcommand === \"--help\" || wantsHelp(rawArgs)) {\n printHelp();\n return;\n }\n\n // Only `apps` is a command word here: this one parser serves every\n // subcommand, so the subcommand stays in the positionals and the app name\n // `apps config` takes follows it.\n const { flags: args, positionals } = parseCommandArgs({\n spec: {\n \"--json\": Boolean,\n \"--force\": Boolean\n },\n rawArgs,\n commandWords: 1,\n command: \"apps\",\n maxPositionals: 2\n });\n\n switch (subcommand) {\n case \"list\":\n await listApps(Boolean(args[\"--json\"]));\n break;\n case \"init\":\n if (positionals[1] !== undefined) {\n // It never registered one app: the name was ignored and the\n // whole manifest inferred, which is not what the reader asked for.\n console.error(chalk.red(`✗ rebase apps init takes no app name (got \"${positionals[1]}\").`));\n console.error(chalk.dim(\" It infers every app from this project and writes the whole rebase.json.\"));\n console.error(chalk.dim(\" To add one app, declare it under \\\"apps\\\" in rebase.json.\"));\n process.exit(1);\n }\n await initManifest(Boolean(args[\"--force\"]));\n break;\n case \"config\":\n await printAppConfig(positionals[1], Boolean(args[\"--json\"]));\n break;\n default:\n unknownCommand(subcommand, APPS_SUBCOMMANDS, \"apps\");\n }\n}\n\n/**\n * One app's line in `rebase apps list`.\n *\n * A static app shows its full address — the https URL when its `path` gives it\n * a hostname — and the CMS as the address a browser would open. `CMS at /` on\n * an app that lives on `admin.example.com` reads as the project's own root,\n * which is the one place that CMS is not.\n */\nexport function describeApp(name: string, app: RebaseAppConfig): string {\n switch (app.type) {\n case \"backend\":\n return app.runtime === \"custom\"\n // The context is named only when it is not the project, which is\n // the case where it changes what you would type. A workspace app\n // builds from the workspace root, and a listing that showed only\n // the Dockerfile implied a `docker build .` beside it that fails.\n ? `custom runtime — ${app.dockerfile ?? \"Dockerfile\"}`\n + (app.context && app.context !== \".\" ? ` (context: ${app.context})` : \"\")\n : `managed runtime, config: ${app.config ?? \"config\"}`;\n case \"static\": {\n const address = staticAppAddress(name, app);\n return `${app.root} → ${app.output} @ ${formatAppAddress(address)}`\n + (app.cms ? ` ${chalk.magenta(`CMS at ${formatAppAddress({ ...address, path: app.cms })}`)}` : \"\");\n }\n default:\n return \"\";\n }\n}\n\nasync function listApps(asJson: boolean): Promise<void> {\n const projectRoot = requireProjectRoot();\n const loaded = loadManifestOrExit(projectRoot, asJson);\n const compatibility = assessManagedCompatibility(loaded.manifest);\n\n if (asJson) {\n console.log(JSON.stringify(\n {\n source: loaded.source,\n rebase: loaded.manifest.rebase,\n apps: loaded.manifest.apps,\n managed: compatibility\n },\n null,\n 2\n ));\n return;\n }\n\n if (loaded.source === \"synthesized\") {\n console.log(chalk.dim(\"No rebase.json — showing the layout inferred from this project.\"));\n console.log(chalk.dim(`Run ${chalk.cyan(\"rebase apps init\")} to write it down.\\n`));\n }\n\n console.log(chalk.bold(`Rebase ${loaded.manifest.rebase}`));\n console.log(\"\");\n\n const entries = Object.entries(loaded.manifest.apps);\n if (entries.length === 0) {\n console.log(chalk.yellow(\"No apps declared.\"));\n return;\n }\n\n const width = Math.max(...entries.map(([name]) => name.length));\n for (const [name, app] of entries) {\n console.log(\n ` ${chalk.cyan(name.padEnd(width))} ${chalk.dim(app.type.padEnd(8))} ${describeApp(name, app)}`\n );\n }\n\n console.log(\"\");\n if (compatibility.eligible) {\n console.log(chalk.green(\"✓ Eligible for the managed runtime.\"));\n } else {\n console.log(chalk.yellow(\"• Uses the custom runtime:\"));\n for (const reason of compatibility.reasons) {\n console.log(chalk.dim(` ${reason}`));\n }\n }\n}\n\n/** A static app's `root`, compared as a directory: `./frontend/` is `frontend`. */\nfunction sameRoot(a: string, b: string): boolean {\n const normal = (root: string): string => path.posix.normalize(root.replace(/\\\\/g, \"/\")).replace(/\\/+$/, \"\");\n return normal(a) === normal(b);\n}\n\n/**\n * Re-infer over a manifest the project already declares, keeping what only the\n * declaration knows.\n *\n * An inferred app takes the name the file gives the app it matches — the\n * backend, or the static app with the same `root` — and that app's `path` and\n * `cms`. The name is the app's identity on a deployed project, so renaming it\n * would deploy a second app beside the first. `path` can carry the hostname the\n * app is registered on. `cms` is a client-side route that nothing in the project\n * shows. Everything else is inferred again, which is what `--force` asks for.\n *\n * A declared app the inference does not find is returned in `removed`, so the\n * command can say so rather than drop it in silence.\n */\nfunction keepDeclaredIdentity(\n inferred: RebaseProjectManifest,\n declared: RebaseProjectManifest\n): { manifest: RebaseProjectManifest; removed: Array<{ name: string; app: RebaseAppConfig }> } {\n const apps: Record<string, RebaseAppConfig> = {};\n const matched = new Set<string>();\n\n for (const [name, app] of Object.entries(inferred.apps)) {\n if (app.type === \"backend\") {\n const backend = findBackendApp(declared);\n const keptName = backend && !matched.has(backend.name) ? backend.name : name;\n matched.add(keptName);\n apps[keptName] = app;\n continue;\n }\n const match = Object.entries(declared.apps).find(([declaredName, candidate]) =>\n !matched.has(declaredName) && candidate.type === \"static\" && sameRoot(candidate.root, app.root));\n const declaredApp = match?.[1];\n if (!match || declaredApp?.type !== \"static\") {\n apps[name] = app;\n continue;\n }\n const keptName = match[0];\n matched.add(keptName);\n const address = declaredApp.path ?? app.path;\n apps[keptName] = {\n ...app,\n ...(address !== undefined ? { path: address } : {}),\n ...(declaredApp.cms !== undefined ? { cms: declaredApp.cms } : {})\n };\n }\n\n const removed = Object.entries(declared.apps)\n .filter(([name]) => !matched.has(name))\n .map(([name, app]) => ({ name, app }));\n return { manifest: { ...inferred, apps }, removed };\n}\n\nasync function initManifest(force: boolean): Promise<void> {\n const projectRoot = requireProjectRoot();\n\n let declared: RebaseProjectManifest | undefined;\n if (manifestExists(projectRoot)) {\n if (!force) {\n console.error(chalk.red(\"✗ rebase.json already exists.\"));\n console.error(chalk.dim(\" Pass --force to replace it with an inferred one, keeping each app's name, path and cms.\"));\n process.exit(1);\n }\n try {\n declared = loadManifest(projectRoot).manifest;\n } catch (err) {\n if (!(err instanceof ManifestError)) throw err;\n const issues = err.issues.map(issue => `${issue.path ? `${issue.path}: ` : \"\"}${issue.message}`);\n console.log(chalk.yellow(\"• The existing rebase.json is invalid, so no app name, path or cms in it is kept:\"));\n for (const issue of issues.length > 0 ? issues : [err.message]) console.log(chalk.dim(` ${issue}`));\n }\n }\n\n const inferred = synthesizeManifest(projectRoot);\n const { manifest, removed } = declared\n ? keepDeclaredIdentity(inferred, declared)\n : { manifest: inferred, removed: [] };\n const filePath = writeManifest(projectRoot, manifest);\n\n console.log(chalk.green(`✓ Wrote ${path.relative(projectRoot, filePath)}`));\n console.log(\"\");\n for (const [name, app] of Object.entries(manifest.apps)) {\n console.log(` ${chalk.cyan(name)} ${chalk.dim(`(${app.type})`)}`);\n }\n for (const { name, app } of removed) {\n const where = app.type === \"static\" ? `, root ${app.root}` : \"\";\n console.log(` ${chalk.yellow(name)} ${chalk.dim(`(${app.type}${where})`)} ${chalk.yellow(\"— not found in this project, removed\")}`);\n }\n\n const compatibility = assessManagedCompatibility(manifest);\n if (!compatibility.eligible) {\n console.log(\"\");\n console.log(chalk.yellow(\"This project will use the custom runtime:\"));\n for (const reason of compatibility.reasons) {\n console.log(chalk.dim(` ${reason}`));\n }\n }\n}\n\n/**\n * Print what a client needs to reach this project.\n *\n * Never prints a secret. The API URL and an app's publishable identity are meant\n * to ship inside a client bundle; anything that is not safe there does not belong\n * in output that will inevitably be pasted into a `.env` that gets committed.\n */\nasync function printAppConfig(appName: string | undefined, asJson: boolean): Promise<void> {\n const projectRoot = requireProjectRoot();\n const loaded = loadManifestOrExit(projectRoot, asJson);\n\n if (!appName) {\n if (asJson) {\n failAsJson(\"Which app? Usage: rebase apps config <app>\", \"app_not_named\",\n `Declared: ${Object.keys(loaded.manifest.apps).join(\", \") || \"(none)\"}`);\n }\n console.error(chalk.red(\"✗ Which app? Usage: rebase apps config <app>\"));\n process.exit(1);\n }\n\n const app = loaded.manifest.apps[appName];\n if (!app) {\n if (asJson) {\n failAsJson(`No app named \"${appName}\" in rebase.json.`, \"app_not_found\",\n `Declared: ${Object.keys(loaded.manifest.apps).join(\", \") || \"(none)\"}`);\n }\n console.error(chalk.red(`✗ No app named \"${appName}\" in rebase.json.`));\n console.error(chalk.dim(` Declared: ${Object.keys(loaded.manifest.apps).join(\", \") || \"(none)\"}`));\n process.exit(1);\n }\n\n const link = readLink(projectRoot);\n // An app the backend bundle serves calls the API on its own origin, so the\n // right value is empty — wherever the project is linked, and whatever a\n // dev server once wrote down. A URL here is baked into the build and\n // follows the bundle into production.\n const sameOrigin = servedByBackend(loaded.manifest, appName);\n const apiUrl = sameOrigin ? \"\" : resolveApiUrl(projectRoot, link);\n\n const config = {\n app: appName,\n type: app.type,\n apiUrl: apiUrl ?? null,\n sameOrigin,\n project: link?.projectId ?? link?.slug ?? null\n };\n\n if (asJson) {\n console.log(JSON.stringify(config, null, 2));\n return;\n }\n\n if (sameOrigin) {\n console.log(chalk.bold(`# ${appName}`));\n console.log(\"\");\n console.log(\"VITE_API_URL=\");\n console.log(\"\");\n console.log(chalk.dim(`Empty on purpose: \\`rebase build\\` folds ${appName} into the backend bundle, so it`));\n console.log(chalk.dim(\"calls the API on the same origin it is served from, locally and deployed alike.\"));\n console.log(chalk.dim(\"(`rebase dev` points it at the dev backend by itself.)\"));\n return;\n }\n\n // Whether the checkout is linked is a fact about the link, not about\n // whether `rebase dev` happens to be running: a running dev's address\n // used to fill the same slot, and the notice disappeared with it.\n if (!link?.apiUrl) {\n console.log(chalk.yellow(\"This checkout is not linked to a project yet.\"));\n // `rebase cloud link`, not `rebase link`. There has never been a\n // top-level `link` command — `cli.ts` dispatches `cloud`, and the link\n // lives inside that family — so this hint named something that exits 1\n // on the very screen that exists to tell you what to run next.\n console.log(chalk.dim(` Run ${chalk.cyan(\"rebase cloud link\")} (cloud) or ${chalk.cyan(\"rebase cloud link <url>\")} (self-hosted).`));\n console.log(chalk.dim(` Until then, this is the address ${chalk.cyan(\"rebase dev\")} serves this project on.`));\n console.log(\"\");\n }\n\n console.log(chalk.bold(`# ${appName}`));\n console.log(\"\");\n // Unlinked: the dev backend this project runs on, not a fixed 3001 — `rebase dev`\n // derives a port per project.\n console.log(`VITE_API_URL=${apiUrl ?? devServerUrl(projectRoot).url}`);\n console.log(\"\");\n console.log(chalk.dim(\"Then, in the app:\"));\n console.log(chalk.dim(\" const rebase = createRebaseClient({ baseUrl: import.meta.env.VITE_API_URL });\"));\n}\n\n/**\n * Work out the API base URL for this checkout.\n *\n * Prefers an explicit link, then the dev server's own record of where it bound.\n * The dev port is chosen dynamically, so a hardcoded default would be wrong on\n * any machine running more than one project.\n */\nfunction resolveApiUrl(projectRoot: string, link: ReturnType<typeof readLink>): string | undefined {\n if (link?.apiUrl) return link.apiUrl;\n // Only a dev server that is still running: the state file outlives the\n // process, and a port nothing listens on is not an address.\n return runningBackendUrl(projectRoot) ?? undefined;\n}\n\n/**\n * Whether `rebase build` folds this static app into the backend bundle, which\n * then serves it on the API's own origin: a managed backend, and an app with\n * built output to fold. The same predicate the build folds by.\n */\nexport function servedByBackend(manifest: ReturnType<typeof loadManifest>[\"manifest\"], appName: string): boolean {\n const backend = findBackendApp(manifest);\n if (!backend || backend.app.type !== \"backend\" || backend.app.runtime === \"custom\") return false;\n return foldableApps(manifest).apps.some(app => app.name === appName);\n}\n\nfunction loadManifestOrExit(projectRoot: string, asJson = false): ReturnType<typeof loadManifest> {\n try {\n return loadManifest(projectRoot);\n } catch (err) {\n if (err instanceof ManifestError) {\n // A caller that asked for JSON gets one on this exit too. It used\n // to get the human bullet list on stderr and an empty stdout —\n // `apps list --json` against the one manifest a caller most needs\n // to be told about.\n if (asJson) {\n failAsJson(err.message, \"manifest_invalid\", \"Fix rebase.json, then run this again.\",\n err.issues.map(issue => ({ path: issue.path, message: issue.message })));\n }\n console.error(chalk.red(`✗ ${err.message}`));\n for (const issue of err.issues) {\n console.error(chalk.red(` ${issue.path ? `${issue.path}: ` : \"\"}${issue.message}`));\n }\n process.exit(1);\n }\n throw err;\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { s as findFreePort } from "./state-CCB-FAQ9.js";
2
- import { i as managedUrl } from "./daemon-CknkDjd6.js";
3
- import { loadExtensions } from "./daemon-entry-C6pxdily.js";
1
+ import { s as findFreePort } from "./state-CYdBvnwA.js";
2
+ import { i as managedUrl } from "./daemon-DDMRbz4T.js";
3
+ import { loadExtensions } from "./daemon-entry-zOC1revO.js";
4
4
  //#region src/dev-db/atlas-dev-database.ts
5
5
  /**
6
6
  * A second, throwaway PGlite for Atlas to plan against.
@@ -59,4 +59,4 @@ async function startAtlasDevDatabase() {
59
59
  //#endregion
60
60
  export { startAtlasDevDatabase };
61
61
 
62
- //# sourceMappingURL=atlas-dev-database-DeK3Sa4h.js.map
62
+ //# sourceMappingURL=atlas-dev-database-BusbHP6n.js.map