@rebasepro/cli 0.25.0 → 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 (125) hide show
  1. package/dist/{agent-setup-B5AKHOgt.js → agent-setup-BYb2Tbdz.js} +2 -2
  2. package/dist/{agent-setup-B5AKHOgt.js.map → agent-setup-BYb2Tbdz.js.map} +1 -1
  3. package/dist/{api-keys-Tm7zvAPe.js → api-keys-CSMbsmAn.js} +3 -4
  4. package/dist/{api-keys-Tm7zvAPe.js.map → api-keys-CSMbsmAn.js.map} +1 -1
  5. package/dist/{apps-BsU_ILbP.js → apps-iBXNZhVN.js} +6 -7
  6. package/dist/{apps-BsU_ILbP.js.map → apps-iBXNZhVN.js.map} +1 -1
  7. package/dist/{atlas-dev-database-OWtqnG7W.js → atlas-dev-database-BusbHP6n.js} +4 -4
  8. package/dist/{atlas-dev-database-OWtqnG7W.js.map → atlas-dev-database-BusbHP6n.js.map} +1 -1
  9. package/dist/{auth-Vl2hFKXP.js → auth-DRsTWPky.js} +6 -7
  10. package/dist/{auth-Vl2hFKXP.js.map → auth-DRsTWPky.js.map} +1 -1
  11. package/dist/{branch-pointer-9DnwkFJJ.js → branch-pointer-Bn_FjNld.js} +1 -1
  12. package/dist/{build-BBgT8EJZ.js → build-et7Rccxi.js} +6 -7
  13. package/dist/{build-BBgT8EJZ.js.map → build-et7Rccxi.js.map} +1 -1
  14. package/dist/{bundle-DtCCCr4w.js → bundle-DlqkDYSe.js} +3 -3
  15. package/dist/{bundle-DtCCCr4w.js.map → bundle-DlqkDYSe.js.map} +1 -1
  16. package/dist/{cloud-BpH0_bmV.js → cloud-B-ZIjHrA.js} +10 -11
  17. package/dist/{cloud-BpH0_bmV.js.map → cloud-B-ZIjHrA.js.map} +1 -1
  18. package/dist/commands/dev.d.ts +12 -0
  19. package/dist/commands/generate_sdk.d.ts +4 -2
  20. package/dist/commands/init.d.ts +20 -0
  21. package/dist/commands/start.d.ts +10 -0
  22. package/dist/commands/upgrade.d.ts +12 -0
  23. package/dist/{consent-ClRHmcxf.js → consent-BaB-eQKG.js} +2 -2
  24. package/dist/{consent-ClRHmcxf.js.map → consent-BaB-eQKG.js.map} +1 -1
  25. package/dist/{console-CEGm0XNc.js → console-BlD9kjFW.js} +4 -4
  26. package/dist/{console-CEGm0XNc.js.map → console-BlD9kjFW.js.map} +1 -1
  27. package/dist/{context-CyflUrKg.js → context-DHiiiJ5C.js} +3 -4
  28. package/dist/context-DHiiiJ5C.js.map +1 -0
  29. package/dist/{daemon-CknkDjd6.js → daemon-DDMRbz4T.js} +160 -5
  30. package/dist/daemon-DDMRbz4T.js.map +1 -0
  31. package/dist/{daemon-entry-CbLRrgzy.js → daemon-entry-zOC1revO.js} +6 -3
  32. package/dist/daemon-entry-zOC1revO.js.map +1 -0
  33. package/dist/{db-CRNpA5mH.js → db-9P6MnmdC.js} +90 -50
  34. package/dist/db-9P6MnmdC.js.map +1 -0
  35. package/dist/{derive-CsoFGAnK.js → derive-MTdClnkc.js} +2 -2
  36. package/dist/{derive-CsoFGAnK.js.map → derive-MTdClnkc.js.map} +1 -1
  37. package/dist/{dev-C0pbMmhS.js → dev-BDN_OKXA.js} +183 -23
  38. package/dist/dev-BDN_OKXA.js.map +1 -0
  39. package/dist/dev-db/daemon.d.ts +41 -0
  40. package/dist/dev-db/pull.d.ts +33 -5
  41. package/dist/dev-db/state.d.ts +9 -0
  42. package/dist/{dev-preflight-unHpiYO1.js → dev-preflight-FT9GbJVj.js} +73 -27
  43. package/dist/dev-preflight-FT9GbJVj.js.map +1 -0
  44. package/dist/{dev-server-B1UYifZJ.js → dev-server-CIZwAfZa.js} +14 -3
  45. package/dist/dev-server-CIZwAfZa.js.map +1 -0
  46. package/dist/{doctor-CATRdWm6.js → doctor-D8YXz7df.js} +6 -6
  47. package/dist/doctor-D8YXz7df.js.map +1 -0
  48. package/dist/{eject-DuasTr-F.js → eject-izG2KjMo.js} +3 -4
  49. package/dist/{eject-DuasTr-F.js.map → eject-izG2KjMo.js.map} +1 -1
  50. package/dist/{fold-static-hDHtDfTq.js → fold-static-CybSay_W.js} +3 -3
  51. package/dist/{fold-static-hDHtDfTq.js.map → fold-static-CybSay_W.js.map} +1 -1
  52. package/dist/{generate_sdk-Cvg5jjJF.js → generate_sdk-B4R65oUV.js} +21 -11
  53. package/dist/generate_sdk-B4R65oUV.js.map +1 -0
  54. package/dist/index.es.js +36 -37
  55. package/dist/index.es.js.map +1 -1
  56. package/dist/{init-BWAwHPtz.js → init-DYaeppEN.js} +50 -62
  57. package/dist/init-DYaeppEN.js.map +1 -0
  58. package/dist/invoked-command-CG_rIa_o.js +55 -0
  59. package/dist/invoked-command-CG_rIa_o.js.map +1 -0
  60. package/dist/last-dev-database-B_75fxZC.js +2 -0
  61. package/dist/{manifest-DRp0UVTj.js → manifest-nvPdLlJY.js} +2 -2
  62. package/dist/{manifest-DRp0UVTj.js.map → manifest-nvPdLlJY.js.map} +1 -1
  63. package/dist/{normalize-imports-BoBVh5tU.js → normalize-imports-BYw8ad87.js} +3 -3
  64. package/dist/{normalize-imports-BoBVh5tU.js.map → normalize-imports-BYw8ad87.js.map} +1 -1
  65. package/dist/{prepare-DdnU70z8.js → prepare-1rVNd2PF.js} +5 -4
  66. package/dist/{prepare-DdnU70z8.js.map → prepare-1rVNd2PF.js.map} +1 -1
  67. package/dist/project-g4K6kV1t.js +701 -0
  68. package/dist/project-g4K6kV1t.js.map +1 -0
  69. package/dist/{pull-C3PXduzl.js → pull-DDMpsZ5r.js} +131 -24
  70. package/dist/pull-DDMpsZ5r.js.map +1 -0
  71. package/dist/refusal-ReeeGP8a.js +26 -0
  72. package/dist/refusal-ReeeGP8a.js.map +1 -0
  73. package/dist/resolve-BQUAC3Wi.js +2 -0
  74. package/dist/{resources-BdNRDEAy.js → resources-CovP8AZ-.js} +4 -5
  75. package/dist/{resources-BdNRDEAy.js.map → resources-CovP8AZ-.js.map} +1 -1
  76. package/dist/{schema-B0-p6T1O.js → schema-nuxvvc50.js} +5 -6
  77. package/dist/{schema-B0-p6T1O.js.map → schema-nuxvvc50.js.map} +1 -1
  78. package/dist/{skills-DfnTeyRz.js → skills-DeUIsZcT.js} +3 -4
  79. package/dist/{skills-DfnTeyRz.js.map → skills-DeUIsZcT.js.map} +1 -1
  80. package/dist/{start-BmEZkS0n.js → start-RzZqDroW.js} +20 -7
  81. package/dist/start-RzZqDroW.js.map +1 -0
  82. package/dist/{state-CCB-FAQ9.js → state-CYdBvnwA.js} +3 -2
  83. package/dist/state-CYdBvnwA.js.map +1 -0
  84. package/dist/{status-BJ26yZOo.js → status-D9Zm88NZ.js} +8 -9
  85. package/dist/{status-BJ26yZOo.js.map → status-D9Zm88NZ.js.map} +1 -1
  86. package/dist/{storage-DKPUBTWG.js → storage-BB3umRfw.js} +3 -4
  87. package/dist/{storage-DKPUBTWG.js.map → storage-BB3umRfw.js.map} +1 -1
  88. package/dist/{telemetry-EMFRVRQi.js → telemetry-HfU5uAh1.js} +2 -2
  89. package/dist/{telemetry-EMFRVRQi.js.map → telemetry-HfU5uAh1.js.map} +1 -1
  90. package/dist/{telemetry-m9czTNGR.js → telemetry-TseNLk6X.js} +4 -4
  91. package/dist/{telemetry-m9czTNGR.js.map → telemetry-TseNLk6X.js.map} +1 -1
  92. package/dist/{upgrade-DjihWuZL.js → upgrade-apiPKKE_.js} +26 -4
  93. package/dist/{upgrade-DjihWuZL.js.map → upgrade-apiPKKE_.js.map} +1 -1
  94. package/dist/utils/args.d.ts +32 -3
  95. package/dist/utils/boot-retry.d.ts +41 -0
  96. package/dist/utils/dev-preflight.d.ts +34 -1
  97. package/dist/utils/dev-server.d.ts +11 -0
  98. package/dist/utils/project.d.ts +5 -1
  99. package/dist/utils/unknown-command.d.ts +4 -0
  100. package/package.json +7 -7
  101. package/templates/resource-graphs/blank.json +25 -0
  102. package/templates/resource-graphs/blog.json +28 -0
  103. package/templates/resource-graphs/ecommerce.json +28 -0
  104. package/templates/resource-graphs/headless.json +22 -0
  105. package/templates/template/.env.example +5 -4
  106. package/templates/template/frontend/src/App.tsx +10 -9
  107. package/dist/args-BX0YD14a.js +0 -266
  108. package/dist/args-BX0YD14a.js.map +0 -1
  109. package/dist/context-CyflUrKg.js.map +0 -1
  110. package/dist/daemon-CknkDjd6.js.map +0 -1
  111. package/dist/daemon-entry-CbLRrgzy.js.map +0 -1
  112. package/dist/db-CRNpA5mH.js.map +0 -1
  113. package/dist/dev-C0pbMmhS.js.map +0 -1
  114. package/dist/dev-preflight-unHpiYO1.js.map +0 -1
  115. package/dist/dev-server-B1UYifZJ.js.map +0 -1
  116. package/dist/doctor-CATRdWm6.js.map +0 -1
  117. package/dist/generate_sdk-Cvg5jjJF.js.map +0 -1
  118. package/dist/init-BWAwHPtz.js.map +0 -1
  119. package/dist/last-dev-database-c_dKz1S3.js +0 -2
  120. package/dist/project-Wp2zoyeN.js +0 -349
  121. package/dist/project-Wp2zoyeN.js.map +0 -1
  122. package/dist/pull-C3PXduzl.js.map +0 -1
  123. package/dist/resolve-CNQjsatH.js +0 -2
  124. package/dist/start-BmEZkS0n.js.map +0 -1
  125. package/dist/state-CCB-FAQ9.js.map +0 -1
@@ -1,6 +1,5 @@
1
- import { d as readEnvFile, f as requireBackendDir, g as resolveTsx, o as findEnvFile, p as requireProjectRoot, r as exitDependenciesNotInstalled } from "./project-Wp2zoyeN.js";
2
- import { a as unknownCommand, n as parseCommandArgs, r as wantsHelp, s as redactConnectionPasswords } from "./args-BX0YD14a.js";
3
- import { resolveBackendAddress } from "./api-keys-Tm7zvAPe.js";
1
+ import { C as wantsHelp, D as redactConnectionPasswords, T as unknownCommand, b as parseCommandArgs, d as readEnvFile, f as requireBackendDir, g as resolveTsx, o as findEnvFile, p as requireProjectRoot, r as exitDependenciesNotInstalled } from "./project-g4K6kV1t.js";
2
+ import { resolveBackendAddress } from "./api-keys-CSMbsmAn.js";
4
3
  import chalk from "chalk";
5
4
  import fs from "fs";
6
5
  import path from "path";
@@ -216,16 +215,16 @@ async function resetPassword(rawArgs) {
216
215
  if (!tsxBin) exitDependenciesNotInstalled(projectRoot);
217
216
  let prepared;
218
217
  try {
219
- const { ensureDockerDatabase } = await import("./db-CRNpA5mH.js");
218
+ const { ensureDockerDatabase } = await import("./db-9P6MnmdC.js");
220
219
  await ensureDockerDatabase(projectRoot, rawArgs);
221
- const { prepareDatabaseEnv } = await import("./prepare-DdnU70z8.js");
220
+ const { prepareDatabaseEnv } = await import("./prepare-1rVNd2PF.js");
222
221
  prepared = await prepareDatabaseEnv(projectRoot, { onProgress: (message) => console.log(chalk.gray(` ${message}`)) });
223
222
  } catch (err) {
224
223
  console.error(chalk.red("✗ Direct database update failed."));
225
224
  console.error(err instanceof Error ? err.message : String(err));
226
225
  process.exit(1);
227
226
  }
228
- const { databaseUrlOf } = await import("./db-CRNpA5mH.js");
227
+ const { databaseUrlOf } = await import("./db-9P6MnmdC.js");
229
228
  const url = databaseUrlOf(prepared, readEnvFile(projectRoot));
230
229
  if (url) {
231
230
  const failure = await databaseOpenFailure(url, prepared.database.source);
@@ -471,4 +470,4 @@ ${chalk.green.bold("Examples")}
471
470
  //#endregion
472
471
  export { AUTH_SUBCOMMANDS, authCommand };
473
472
 
474
- //# sourceMappingURL=auth-Vl2hFKXP.js.map
473
+ //# sourceMappingURL=auth-DRsTWPky.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-Vl2hFKXP.js","names":[],"sources":["../src/commands/auth.ts"],"sourcesContent":["/**\n * CLI command: rebase auth <action>\n *\n * Subcommands:\n * reset-password — Reset a user's password\n */\nimport chalk from \"chalk\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport { spawn } from \"child_process\";\nimport { randomBytes } from \"node:crypto\";\nimport {\n requireProjectRoot,\n requireBackendDir,\n findEnvFile,\n readEnvFile,\n resolveTsx,\n exitDependenciesNotInstalled\n} from \"../utils/project\";\nimport { parseEnvBoolean } from \"@rebasepro/types\";\nimport { unknownCommand } from \"../utils/unknown-command\";\nimport { redactConnectionPasswords } from \"../utils/redact\";\nimport type { PreparedDatabase } from \"../dev-db/prepare\";\nimport type { DevDatabaseSource } from \"../dev-db/resolve\";\n\n/** The backend was reached and refused: not a reason to fall back to the database. */\nclass ApiAnswered extends Error {}\n\n/** Everything the switch below dispatches, for the did-you-mean. */\nexport const AUTH_SUBCOMMANDS = [\"reset-password\"] as const;\nimport { parseCommandArgs, wantsHelp } from \"../utils/args\";\nimport { resolveBackendAddress } from \"./api-keys\";\n\n/** A user as the admin API returns it, reduced to what this command needs. */\nexport interface ResolvedUser {\n id: string;\n email: string;\n}\n\n/**\n * Pick the user with exactly this email out of a search response.\n *\n * `/api/admin/users?search=` is an `ILIKE '%…%'` over email **or display\n * name**, ordered by role count descending. This used to take row `[0]` and\n * reset it, then print the email it had been *given* as confirmation — so two\n * ordinary situations ended in a successful-looking reset of somebody else's\n * account:\n *\n * - a substring collision: `bob@example.com` also matches\n * `robert.bob@example.com`;\n * - a display name, which is user-controlled and accepted up to 255\n * characters with no constraint on its content, containing an address\n * belonging to someone else.\n *\n * The ordering makes it worse rather than better — `array_length(roles) DESC\n * NULLS LAST` puts the most privileged match first, so the account most likely\n * to be reset by mistake is an admin's.\n *\n * Returns `undefined` when nothing matched exactly, which the caller reports\n * rather than falling through to a guess. The direct-database fallback below\n * has always matched with `eq(usersTable.email, email)`; this is the same\n * definition, so the command no longer resets different accounts depending on\n * whether the backend happened to be running.\n */\nexport function selectUserForEmail(payload: unknown, email: string): ResolvedUser | undefined {\n const wanted = email.trim().toLowerCase();\n if (!wanted) return undefined;\n\n const rows: unknown[] = Array.isArray(payload)\n ? payload\n : (payload && typeof payload === \"object\" && Array.isArray((payload as { users?: unknown }).users)\n ? (payload as { users: unknown[] }).users\n : []);\n\n for (const row of rows) {\n if (!row || typeof row !== \"object\") continue;\n const record = row as Record<string, unknown>;\n const rowEmail = typeof record.email === \"string\" ? record.email.trim().toLowerCase() : undefined;\n if (!rowEmail || rowEmail !== wanted) continue;\n\n const id = typeof record.id === \"string\"\n ? record.id\n : (typeof record.uid === \"string\" ? record.uid : undefined);\n if (!id) continue;\n\n return { id, email: record.email as string };\n }\n\n return undefined;\n}\n\nexport async function authCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void> {\n // `--help` is answered here and never reaches a handler. `cli.ts` only\n // rewrites the subcommand to `\"--help\"` when no subcommand was named, so\n // `rebase auth reset-password --help` used to *run the reset*: `--help`\n // became the email, the backend was contacted, `.tmp-reset-password.ts` was\n // written into the user's `backend/`, and a database UPDATE ran for a user\n // named `--help`. A flag whose whole job is to print text cannot be allowed\n // to reach code that writes.\n if (!subcommand || subcommand === \"--help\" || wantsHelp(rawArgs)) {\n printAuthHelp();\n return;\n }\n\n switch (subcommand) {\n case \"reset-password\":\n await resetPassword(rawArgs);\n break;\n default:\n unknownCommand(subcommand, AUTH_SUBCOMMANDS, \"auth\");\n }\n}\n\n/**\n * The flags `rebase auth reset-password` takes.\n *\n * `-p` was advertised in this command's own help and never declared here, so\n * `arg` — running permissively — pushed it into the positionals and the value\n * *after* it shifted out of reach: anyone following the help set the account's\n * password to the two-character string `-p`. Declared now, and `auth.test.ts`\n * asserts that the help and this spec list the same aliases.\n */\nexport const RESET_PASSWORD_FLAGS = {\n \"--email\": String,\n \"--password\": String,\n \"-e\": \"--email\",\n \"-p\": \"--password\"\n} as const;\n\n/**\n * Which account, and which password, this invocation names.\n *\n * Both may still be absent — the caller reports a missing email — but neither\n * can be a flag. `parseCommandArgs` parses the whole line strictly, so an\n * undeclared flag is an error rather than a positional. That is what stops\n * `rebase auth reset-password bob@example.com --debug` from setting Bob's\n * password to `--debug`, which is the flag the CLI itself prints after every\n * failure as the thing to re-run with.\n *\n * Exported so its tests can drive the real parser rather than a copy of it.\n */\nexport function resolveResetPasswordArgs(rawArgs: string[]): {\n email?: string;\n password?: string;\n} {\n const { flags, positionals } = parseCommandArgs({\n spec: RESET_PASSWORD_FLAGS,\n rawArgs,\n commandWords: 2,\n command: \"auth reset-password\",\n maxPositionals: 2\n });\n\n // Both spellings are supported: `<email> [password]` and `--email/--password`.\n return {\n email: flags[\"--email\"] || positionals[0],\n password: flags[\"--password\"] || positionals[1]\n };\n}\n\n/**\n * A password for a reset that was not given one.\n *\n * This used to be a constant, and `--help` printed it as the default. Reset is\n * the documented way back into an account nobody can sign in to — an admin,\n * usually — so the recovery path set every such account to a fixed string that\n * ships inside a public repository and a published npm package, and left it\n * there until somebody remembered to change it.\n *\n * base64url of 18 random bytes: 24 characters, ~144 bits, no shell-quoting\n * hazard, and nothing that reads like a placeholder somebody might keep.\n */\nexport function generatePassword(): string {\n return randomBytes(18).toString(\"base64url\");\n}\n\n/**\n * What a refusing backend said, from its `{ error: { message, code } }` body.\n *\n * The body used to be printed as it came, so a weak password read\n * `{\"error\":{\"message\":\"…\",\"code\":\"…\"}}`. A body that is not the envelope is\n * still shown, since it is the only account of the refusal there is.\n */\nasync function refusalReason(response: Response): Promise<string> {\n const text = await response.text().catch(() => \"\");\n try {\n const parsed: unknown = JSON.parse(text);\n const error = parsed && typeof parsed === \"object\" && \"error\" in parsed ? parsed.error : undefined;\n if (error && typeof error === \"object\" && \"message\" in error && typeof error.message === \"string\") {\n const code = \"code\" in error && typeof error.code === \"string\" ? ` (${error.code})` : \"\";\n return `${error.message}${code}`;\n }\n } catch {\n // Not JSON: the text is the answer.\n }\n return text.trim() || `${response.status} ${response.statusText}`.trim();\n}\n\nasync function resetPassword(rawArgs: string[]): Promise<void> {\n const { email, password: providedPassword } = resolveResetPasswordArgs(rawArgs);\n // Generated once, so both reset paths set and report the same thing.\n const wasGenerated = !providedPassword;\n const newPassword = providedPassword || generatePassword();\n\n if (!email) {\n console.error(chalk.red(\"✗ Email is required.\"));\n console.log(\"\");\n console.log(chalk.gray(\" Usage: rebase auth reset-password <email> [new-password]\"));\n console.log(chalk.gray(\" rebase auth reset-password --email user@example.com --password NewPass123!\"));\n process.exit(1);\n }\n\n const projectRoot = requireProjectRoot();\n\n // 1. Try API-first reset\n // Was a single-key regex, which did not match `export REBASE_SERVICE_KEY=…`\n // and kept a trailing `# comment` in the value. The command then fell\n // through to the direct-database path as though no key were configured.\n const envFile = findEnvFile(projectRoot);\n const envServiceKey: string | undefined = readEnvFile(projectRoot).REBASE_SERVICE_KEY;\n\n let serviceKey = process.env.REBASE_SERVICE_KEY || envServiceKey;\n\n const statePath = path.join(projectRoot, \".rebase\", \"state.json\");\n if (fs.existsSync(statePath)) {\n try {\n const state = JSON.parse(fs.readFileSync(statePath, \"utf8\")) as Record<string, unknown>;\n if (state && typeof state === \"object\" && typeof state.serviceKey === \"string\" && !serviceKey) {\n serviceKey = state.serviceKey;\n }\n } catch {\n // Ignore\n }\n }\n\n // Where the service key may go: a REBASE_BASE_URL the developer named, or\n // this project's backend while the pid that recorded it is alive — see\n // `resolveBackendAddress`. `.rebase/state.json`'s address on its own, and\n // `.rebase-dev-url`, outlive a killed `rebase dev`, and the port they name\n // may be another server's by now. With neither, the reset goes to the\n // database directly.\n const baseUrl = resolveBackendAddress(readEnvFile(projectRoot), projectRoot).url;\n\n if (baseUrl && serviceKey) {\n console.log(\"Trying API-first reset via running backend...\");\n try {\n const finalPass = newPassword;\n const cleanBaseUrl = baseUrl.replace(/\\/+$/, \"\");\n // Not `limit=1`: the search is fuzzy and ordered by role count, so\n // the exact match is not necessarily first — asking for one row can\n // make it unreachable. Ask for a page, then match exactly.\n const searchUrl = `${cleanBaseUrl}/api/admin/users?search=${encodeURIComponent(email)}&limit=50`;\n const searchRes = await fetch(searchUrl, {\n headers: {\n \"Authorization\": `Bearer ${serviceKey}`,\n \"Accept\": \"application/json\"\n }\n });\n if (!searchRes.ok) {\n throw new ApiAnswered(`Failed to list users: ${searchRes.status} ${searchRes.statusText}`);\n }\n const searchData = await searchRes.json() as unknown;\n if (!searchData || typeof searchData !== \"object\") {\n throw new Error(\"Invalid response format from user search API.\");\n }\n\n const matched = selectUserForEmail(searchData, email);\n if (!matched) {\n throw new ApiAnswered(`No user has the email ${email}.`);\n }\n\n const resetUrl = `${cleanBaseUrl}/api/admin/users/${matched.id}/reset-password`;\n const resetRes = await fetch(resetUrl, {\n method: \"POST\",\n headers: {\n \"Authorization\": `Bearer ${serviceKey}`,\n \"Content-Type\": \"application/json\",\n \"Accept\": \"application/json\"\n },\n body: JSON.stringify({ password: finalPass })\n });\n\n if (!resetRes.ok) {\n throw new ApiAnswered(`Password reset refused: ${await refusalReason(resetRes)}`);\n }\n\n console.log(\"API reset successful.\");\n console.log(chalk.bold(\" 🔑 Rebase Auth — Reset Password (via API)\"));\n console.log(\"\");\n // The address as stored, not as typed — they differ in case often\n // enough that echoing the input hides which account was touched.\n console.log(` ${chalk.gray(\"Email:\")} ${matched.email}`);\n // Echoed only when we invented it. A password the operator typed\n // is already theirs; printing it again only adds scrollback.\n console.log(` ${chalk.gray(\"Password:\")} ${wasGenerated ? finalPass : \"*\".repeat(finalPass.length)}`);\n console.log(\"\");\n return;\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err);\n // The backend answered and said no — a password too weak, a user\n // it does not have. That answer stands: writing the hash straight\n // into the database instead skipped the strength rule it had just\n // applied, and ended no sessions. Only a backend that could not be\n // reached is a reason to go round it.\n if (err instanceof ApiAnswered) {\n console.error(chalk.red(`✗ ${errMsg}`));\n process.exitCode = 1;\n return;\n }\n console.warn(chalk.yellow(\"API reset failed, falling back to direct database update...\"));\n console.warn(chalk.gray(` Details: ${errMsg}`));\n }\n }\n\n // 2. Direct-DB Fallback\n const backendDir = requireBackendDir(projectRoot);\n const tsxBin = resolveTsx(projectRoot);\n\n if (!tsxBin) {\n exitDependenciesNotInstalled(projectRoot);\n }\n\n // The database the `db` family would use, resolved — and, for a remembered\n // compose container that is stopped, started — the same way. A stock\n // scaffold leaves DATABASE_URL commented out and runs on the managed\n // database, which only exists in a child's environment when something puts\n // it there — without this the script connected with libpq's defaults,\n // localhost:5432 as the OS user. An external DATABASE_URL adds nothing\n // here: the child already reads it.\n let prepared: PreparedDatabase;\n try {\n const { ensureDockerDatabase } = await import(\"./db\");\n await ensureDockerDatabase(projectRoot, rawArgs);\n const { prepareDatabaseEnv } = await import(\"../dev-db/prepare\");\n prepared = await prepareDatabaseEnv(projectRoot, {\n onProgress: (message) => console.log(chalk.gray(` ${message}`))\n });\n } catch (err) {\n console.error(chalk.red(\"✗ Direct database update failed.\"));\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n\n // Opened here first, so a database that does not answer gets the banner\n // every other command prints — not the script's raw error and stack — and\n // no script is written for it.\n const { databaseUrlOf } = await import(\"./db\");\n const url = databaseUrlOf(prepared, readEnvFile(projectRoot));\n if (url) {\n const failure = await databaseOpenFailure(url, prepared.database.source);\n if (failure) {\n for (const line of failure) console.error(line);\n process.exit(1);\n }\n }\n\n try {\n const env: Record<string, string> = { ...process.env as Record<string, string> };\n if (envFile) {\n env.DOTENV_CONFIG_PATH = envFile;\n }\n env.REBASE_RESET_EMAIL = email;\n env.REBASE_RESET_PASSWORD = newPassword;\n env.REBASE_ENV_FILE_PATH = envFile || path.join(projectRoot, \".env\");\n Object.assign(env, prepared.env);\n\n const scriptContent = resetPasswordScript(wasGenerated, parseEnvBoolean(process.env.REBASE_DEBUG) === true);\n\n const tmpScriptPath = path.join(backendDir, \".tmp-reset-password.ts\");\n fs.writeFileSync(tmpScriptPath, scriptContent, \"utf-8\");\n\n console.log(\"\");\n console.log(chalk.bold(\" 🔑 Rebase Auth — Reset Password (Direct DB Fallback)\"));\n console.log(\"\");\n console.log(` ${chalk.gray(\"Email:\")} ${email}`);\n console.log(` ${chalk.gray(\"Database:\")} ${prepared.description}`);\n if (!wasGenerated) {\n console.log(` ${chalk.gray(\"Password:\")} ${\"*\".repeat(newPassword.length)}`);\n }\n console.log(\"\");\n\n const child = spawn(tsxBin, [tmpScriptPath], {\n cwd: backendDir,\n stdio: \"inherit\",\n env\n });\n\n // The script is written into the user's backend directory, so every\n // exit has to remove it. Without an `error` handler a failed spawn\n // raises an unhandled event, the process dies before `close`, and\n // `.tmp-reset-password.ts` is left behind to be committed.\n const cleanup = () => {\n try { fs.unlinkSync(tmpScriptPath); } catch { /* already gone */ }\n };\n\n return new Promise((resolve) => {\n child.on(\"error\", (err) => {\n cleanup();\n console.error(chalk.red(\"✗ Could not run the reset script.\"));\n console.error(chalk.gray(` ${err.message}`));\n process.exit(1);\n });\n child.on(\"close\", (code) => {\n cleanup();\n if (code !== 0) {\n process.exit(code ?? 1);\n }\n resolve();\n });\n });\n } catch (err) {\n console.error(chalk.red(\"✗ Direct database update failed.\"));\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n}\n\n/**\n * Why the database the fallback would reset in cannot be opened, as the lines\n * to print — or null when it opens.\n *\n * A stopped database, refused credentials and a database name the server does\n * not have get the boxed banner the other commands print; anything else is one\n * sentence. Either way the password was not reset and no script was written.\n */\nasync function databaseOpenFailure(url: string, source: DevDatabaseSource): Promise<string[] | null> {\n const { Client } = await import(\"pg\");\n const client = new Client({ connectionString: url, connectionTimeoutMillis: 10_000 });\n client.on(\"error\", () => undefined);\n try {\n await client.connect();\n await client.query(\"SELECT 1\");\n return null;\n } catch (error) {\n const { connectionErrorText, connectionFailureBanner, connectionRefusedFixes } =\n await import(\"../dev-db/connection-banner\");\n const consequence = \"The password was not reset.\";\n return connectionFailureBanner(url, error, { consequence, fixes: connectionRefusedFixes(source) }) ?? [\n chalk.red(`✗ Could not open the database: ${redactConnectionPasswords(connectionErrorText(error))}`),\n chalk.gray(` ${consequence}`)\n ];\n } finally {\n await client.end().catch(() => undefined);\n }\n}\n\n/**\n * The script the direct-database fallback runs under the project's own tsx, so\n * it resolves the project's `@rebasepro/server-postgres` and schema.\n *\n * It ends the account's sessions in the transaction that sets the password,\n * as every door through the API does (`replaceUserPassword`): the refresh\n * tokens and outstanding reset links go, and `tokens_valid_after` voids the\n * access tokens already handed out. An operator resetting a phished account\n * with the backend down is the case this exists for, and a reset that left the\n * attacker's refresh token minting access tokens did not recover anything.\n *\n * It exits 0 only when a row was updated: a missing user and a thrown error are\n * both exit 1. `echoPassword` prints the new password, for a generated one;\n * `showStack` prints a failure's stack rather than its sentence (`--debug`).\n *\n * Exported so its tests can run it.\n */\nexport function resetPasswordScript(echoPassword: boolean, showStack = false): string {\n return `\nimport { createPostgresDatabaseConnection } from \"@rebasepro/server-postgres\";\nimport { hashPassword } from \"@rebasepro/server\";\nimport { getTableConfig } from \"drizzle-orm/pg-core\";\nimport * as dotenv from \"dotenv\";\nimport path from \"path\";\nimport fs from \"fs\";\n\ndotenv.config({ path: process.env.REBASE_ENV_FILE_PATH, quiet: true });\n\n// Lowercased, as every address is stored (\\`normalizeEmail\\`): matched as\n// typed, \"Ops@Acme.test\" found no row.\nconst email = process.env.REBASE_RESET_EMAIL!.trim().toLowerCase();\nconst newPassword = process.env.REBASE_RESET_PASSWORD!;\n\nconst quote = (identifier: string) => '\"' + identifier.replace(/\"/g, '\"\"') + '\"';\n\nasync function resetPassword() {\n const { pool } = createPostgresDatabaseConnection(process.env.DATABASE_URL!);\n const hash = await hashPassword(newPassword);\n\n let usersTable;\n try {\n const schemaPath = path.resolve(\"./src/schema.generated.ts\");\n if (fs.existsSync(schemaPath)) {\n const schema = await import(\"file://\" + schemaPath);\n usersTable = schema.users || schema.tables?.users;\n }\n } catch (e) {\n // ignore and fallback\n }\n\n if (!usersTable) {\n const pgServer = await import(\"@rebasepro/server-postgres\");\n usersTable = pgServer.users;\n }\n\n // The physical names, from the table object: the collection may map its\n // properties to other columns, and the statements below are plain SQL.\n const { name: tableName, schema: tableSchema } = getTableConfig(usersTable);\n const usersSchema = tableSchema || \"public\";\n const users = quote(usersSchema) + \".\" + quote(tableName);\n const idColumn = quote(usersTable.id.name);\n const emailColumn = quote(usersTable.email.name);\n const passwordColumn = quote((usersTable.passwordHash ?? usersTable.password_hash).name);\n // Where \\`ensureAuthTablesExist\\` puts the tables that hang off the users\n // table: beside it, or in \\`rebase\\` when it lives in \\`public\\`.\n const authSchema = usersSchema === \"public\" ? \"rebase\" : usersSchema;\n\n const client = await pool.connect();\n try {\n // A database nothing has booted against — or a managed one \\`db reset\\`\n // emptied — has no users table, and so no account to reset. Said as\n // that, not as pg's \\`relation … does not exist\\`.\n const usersTable = await client.query(\"SELECT to_regclass($1) IS NOT NULL AS present\", [users]);\n if (!usersTable.rows[0]?.present) {\n console.error(\"✗ \" + users + \" does not exist in this database, so it holds no account to reset.\");\n console.error(\" Nothing was changed. \\`rebase dev\\` creates it the first time it boots against this database.\");\n process.exit(1);\n }\n\n await client.query(\"BEGIN\");\n const updated = await client.query(\n \"UPDATE \" + users + \" SET \" + passwordColumn + \" = $1 WHERE \" + emailColumn + \" = $2 \" +\n \"RETURNING \" + idColumn + \" AS id, \" + emailColumn + \" AS email\",\n [hash, email]\n );\n if (updated.rows.length === 0) {\n await client.query(\"ROLLBACK\");\n // Nothing was updated, so nothing was reset. Exiting 0 here reported\n // success for a no-op, which is what a script would have believed.\n console.error(\"✗ User not found: \" + email);\n process.exit(1);\n }\n const uid = updated.rows[0].id;\n\n // A table or column the server has not created yet (it never booted\n // against this database) holds no session to end.\n const watermark = await client.query(\n \"SELECT 1 FROM information_schema.columns WHERE table_schema = $1 AND table_name = $2 AND column_name = 'tokens_valid_after'\",\n [usersSchema, tableName]\n );\n if (watermark.rows.length > 0) {\n await client.query(\"UPDATE \" + users + \" SET tokens_valid_after = NOW() WHERE \" + idColumn + \" = $1\", [uid]);\n }\n for (const table of [\"refresh_tokens\", \"password_reset_tokens\"]) {\n const qualified = quote(authSchema) + \".\" + quote(table);\n const present = await client.query(\"SELECT to_regclass($1) IS NOT NULL AS present\", [qualified]);\n if (present.rows[0]?.present) {\n await client.query(\"DELETE FROM \" + qualified + \" WHERE uid = $1\", [uid]);\n }\n }\n await client.query(\"COMMIT\");\n\n console.log(\"✅ Password reset for: \" + updated.rows[0].email);\n console.log(\" Every session of this account has ended.\");\n ${echoPassword ? 'console.log(\" Password: \" + newPassword);' : \"\"}\n process.exit(0);\n } catch (error) {\n await client.query(\"ROLLBACK\").catch(() => undefined);\n throw error;\n } finally {\n client.release();\n }\n}\n\n// A thrown error is a failed reset, and exits like one — a refused connection\n// that exits 0 reads as a reset to anything checking the exit code. Said as a\n// sentence: the stack is the script's own, and only --debug asks for it.\nconst describe = (error: unknown): string => {\n if (error instanceof AggregateError && !error.message && error.errors.length > 0) return describe(error.errors[0]);\n const message = error instanceof Error ? error.message : String(error);\n const code = error && typeof error === \"object\" && \"code\" in error && typeof error.code === \"string\" ? error.code : \"\";\n return code && !message.includes(code) ? message + \" (\" + code + \")\" : message;\n};\nresetPassword().catch((error) => {\n ${showStack ? \"console.error(error);\" : \"console.error(\\\"✗ The password was not reset: \\\" + describe(error));\"}\n process.exit(1);\n});\n`;\n}\n\nfunction printAuthHelp() {\n console.log(`\n${chalk.bold(\"rebase auth\")} — Authentication management commands\n\n${chalk.green.bold(\"Usage\")}\n rebase auth ${chalk.blue(\"<command>\")} [options]\n\n${chalk.green.bold(\"Commands\")}\n ${chalk.blue.bold(\"reset-password\")} Reset a user's password\n\n${chalk.green.bold(\"reset-password Options\")}\n ${chalk.blue(\"--email, -e\")} User's email address\n ${chalk.blue(\"--password, -p\")} New password (default: one is generated and printed)\n\n${chalk.green.bold(\"Examples\")}\n rebase auth reset-password user@example.com\n rebase auth reset-password --email user@example.com --password MyNewPass!\n`);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"auth-DRsTWPky.js","names":[],"sources":["../src/commands/auth.ts"],"sourcesContent":["/**\n * CLI command: rebase auth <action>\n *\n * Subcommands:\n * reset-password — Reset a user's password\n */\nimport chalk from \"chalk\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport { spawn } from \"child_process\";\nimport { randomBytes } from \"node:crypto\";\nimport {\n requireProjectRoot,\n requireBackendDir,\n findEnvFile,\n readEnvFile,\n resolveTsx,\n exitDependenciesNotInstalled\n} from \"../utils/project\";\nimport { parseEnvBoolean } from \"@rebasepro/types\";\nimport { unknownCommand } from \"../utils/unknown-command\";\nimport { redactConnectionPasswords } from \"../utils/redact\";\nimport type { PreparedDatabase } from \"../dev-db/prepare\";\nimport type { DevDatabaseSource } from \"../dev-db/resolve\";\n\n/** The backend was reached and refused: not a reason to fall back to the database. */\nclass ApiAnswered extends Error {}\n\n/** Everything the switch below dispatches, for the did-you-mean. */\nexport const AUTH_SUBCOMMANDS = [\"reset-password\"] as const;\nimport { parseCommandArgs, wantsHelp } from \"../utils/args\";\nimport { resolveBackendAddress } from \"./api-keys\";\n\n/** A user as the admin API returns it, reduced to what this command needs. */\nexport interface ResolvedUser {\n id: string;\n email: string;\n}\n\n/**\n * Pick the user with exactly this email out of a search response.\n *\n * `/api/admin/users?search=` is an `ILIKE '%…%'` over email **or display\n * name**, ordered by role count descending. This used to take row `[0]` and\n * reset it, then print the email it had been *given* as confirmation — so two\n * ordinary situations ended in a successful-looking reset of somebody else's\n * account:\n *\n * - a substring collision: `bob@example.com` also matches\n * `robert.bob@example.com`;\n * - a display name, which is user-controlled and accepted up to 255\n * characters with no constraint on its content, containing an address\n * belonging to someone else.\n *\n * The ordering makes it worse rather than better — `array_length(roles) DESC\n * NULLS LAST` puts the most privileged match first, so the account most likely\n * to be reset by mistake is an admin's.\n *\n * Returns `undefined` when nothing matched exactly, which the caller reports\n * rather than falling through to a guess. The direct-database fallback below\n * has always matched with `eq(usersTable.email, email)`; this is the same\n * definition, so the command no longer resets different accounts depending on\n * whether the backend happened to be running.\n */\nexport function selectUserForEmail(payload: unknown, email: string): ResolvedUser | undefined {\n const wanted = email.trim().toLowerCase();\n if (!wanted) return undefined;\n\n const rows: unknown[] = Array.isArray(payload)\n ? payload\n : (payload && typeof payload === \"object\" && Array.isArray((payload as { users?: unknown }).users)\n ? (payload as { users: unknown[] }).users\n : []);\n\n for (const row of rows) {\n if (!row || typeof row !== \"object\") continue;\n const record = row as Record<string, unknown>;\n const rowEmail = typeof record.email === \"string\" ? record.email.trim().toLowerCase() : undefined;\n if (!rowEmail || rowEmail !== wanted) continue;\n\n const id = typeof record.id === \"string\"\n ? record.id\n : (typeof record.uid === \"string\" ? record.uid : undefined);\n if (!id) continue;\n\n return { id, email: record.email as string };\n }\n\n return undefined;\n}\n\nexport async function authCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void> {\n // `--help` is answered here and never reaches a handler. `cli.ts` only\n // rewrites the subcommand to `\"--help\"` when no subcommand was named, so\n // `rebase auth reset-password --help` used to *run the reset*: `--help`\n // became the email, the backend was contacted, `.tmp-reset-password.ts` was\n // written into the user's `backend/`, and a database UPDATE ran for a user\n // named `--help`. A flag whose whole job is to print text cannot be allowed\n // to reach code that writes.\n if (!subcommand || subcommand === \"--help\" || wantsHelp(rawArgs)) {\n printAuthHelp();\n return;\n }\n\n switch (subcommand) {\n case \"reset-password\":\n await resetPassword(rawArgs);\n break;\n default:\n unknownCommand(subcommand, AUTH_SUBCOMMANDS, \"auth\");\n }\n}\n\n/**\n * The flags `rebase auth reset-password` takes.\n *\n * `-p` was advertised in this command's own help and never declared here, so\n * `arg` — running permissively — pushed it into the positionals and the value\n * *after* it shifted out of reach: anyone following the help set the account's\n * password to the two-character string `-p`. Declared now, and `auth.test.ts`\n * asserts that the help and this spec list the same aliases.\n */\nexport const RESET_PASSWORD_FLAGS = {\n \"--email\": String,\n \"--password\": String,\n \"-e\": \"--email\",\n \"-p\": \"--password\"\n} as const;\n\n/**\n * Which account, and which password, this invocation names.\n *\n * Both may still be absent — the caller reports a missing email — but neither\n * can be a flag. `parseCommandArgs` parses the whole line strictly, so an\n * undeclared flag is an error rather than a positional. That is what stops\n * `rebase auth reset-password bob@example.com --debug` from setting Bob's\n * password to `--debug`, which is the flag the CLI itself prints after every\n * failure as the thing to re-run with.\n *\n * Exported so its tests can drive the real parser rather than a copy of it.\n */\nexport function resolveResetPasswordArgs(rawArgs: string[]): {\n email?: string;\n password?: string;\n} {\n const { flags, positionals } = parseCommandArgs({\n spec: RESET_PASSWORD_FLAGS,\n rawArgs,\n commandWords: 2,\n command: \"auth reset-password\",\n maxPositionals: 2\n });\n\n // Both spellings are supported: `<email> [password]` and `--email/--password`.\n return {\n email: flags[\"--email\"] || positionals[0],\n password: flags[\"--password\"] || positionals[1]\n };\n}\n\n/**\n * A password for a reset that was not given one.\n *\n * This used to be a constant, and `--help` printed it as the default. Reset is\n * the documented way back into an account nobody can sign in to — an admin,\n * usually — so the recovery path set every such account to a fixed string that\n * ships inside a public repository and a published npm package, and left it\n * there until somebody remembered to change it.\n *\n * base64url of 18 random bytes: 24 characters, ~144 bits, no shell-quoting\n * hazard, and nothing that reads like a placeholder somebody might keep.\n */\nexport function generatePassword(): string {\n return randomBytes(18).toString(\"base64url\");\n}\n\n/**\n * What a refusing backend said, from its `{ error: { message, code } }` body.\n *\n * The body used to be printed as it came, so a weak password read\n * `{\"error\":{\"message\":\"…\",\"code\":\"…\"}}`. A body that is not the envelope is\n * still shown, since it is the only account of the refusal there is.\n */\nasync function refusalReason(response: Response): Promise<string> {\n const text = await response.text().catch(() => \"\");\n try {\n const parsed: unknown = JSON.parse(text);\n const error = parsed && typeof parsed === \"object\" && \"error\" in parsed ? parsed.error : undefined;\n if (error && typeof error === \"object\" && \"message\" in error && typeof error.message === \"string\") {\n const code = \"code\" in error && typeof error.code === \"string\" ? ` (${error.code})` : \"\";\n return `${error.message}${code}`;\n }\n } catch {\n // Not JSON: the text is the answer.\n }\n return text.trim() || `${response.status} ${response.statusText}`.trim();\n}\n\nasync function resetPassword(rawArgs: string[]): Promise<void> {\n const { email, password: providedPassword } = resolveResetPasswordArgs(rawArgs);\n // Generated once, so both reset paths set and report the same thing.\n const wasGenerated = !providedPassword;\n const newPassword = providedPassword || generatePassword();\n\n if (!email) {\n console.error(chalk.red(\"✗ Email is required.\"));\n console.log(\"\");\n console.log(chalk.gray(\" Usage: rebase auth reset-password <email> [new-password]\"));\n console.log(chalk.gray(\" rebase auth reset-password --email user@example.com --password NewPass123!\"));\n process.exit(1);\n }\n\n const projectRoot = requireProjectRoot();\n\n // 1. Try API-first reset\n // Was a single-key regex, which did not match `export REBASE_SERVICE_KEY=…`\n // and kept a trailing `# comment` in the value. The command then fell\n // through to the direct-database path as though no key were configured.\n const envFile = findEnvFile(projectRoot);\n const envServiceKey: string | undefined = readEnvFile(projectRoot).REBASE_SERVICE_KEY;\n\n let serviceKey = process.env.REBASE_SERVICE_KEY || envServiceKey;\n\n const statePath = path.join(projectRoot, \".rebase\", \"state.json\");\n if (fs.existsSync(statePath)) {\n try {\n const state = JSON.parse(fs.readFileSync(statePath, \"utf8\")) as Record<string, unknown>;\n if (state && typeof state === \"object\" && typeof state.serviceKey === \"string\" && !serviceKey) {\n serviceKey = state.serviceKey;\n }\n } catch {\n // Ignore\n }\n }\n\n // Where the service key may go: a REBASE_BASE_URL the developer named, or\n // this project's backend while the pid that recorded it is alive — see\n // `resolveBackendAddress`. `.rebase/state.json`'s address on its own, and\n // `.rebase-dev-url`, outlive a killed `rebase dev`, and the port they name\n // may be another server's by now. With neither, the reset goes to the\n // database directly.\n const baseUrl = resolveBackendAddress(readEnvFile(projectRoot), projectRoot).url;\n\n if (baseUrl && serviceKey) {\n console.log(\"Trying API-first reset via running backend...\");\n try {\n const finalPass = newPassword;\n const cleanBaseUrl = baseUrl.replace(/\\/+$/, \"\");\n // Not `limit=1`: the search is fuzzy and ordered by role count, so\n // the exact match is not necessarily first — asking for one row can\n // make it unreachable. Ask for a page, then match exactly.\n const searchUrl = `${cleanBaseUrl}/api/admin/users?search=${encodeURIComponent(email)}&limit=50`;\n const searchRes = await fetch(searchUrl, {\n headers: {\n \"Authorization\": `Bearer ${serviceKey}`,\n \"Accept\": \"application/json\"\n }\n });\n if (!searchRes.ok) {\n throw new ApiAnswered(`Failed to list users: ${searchRes.status} ${searchRes.statusText}`);\n }\n const searchData = await searchRes.json() as unknown;\n if (!searchData || typeof searchData !== \"object\") {\n throw new Error(\"Invalid response format from user search API.\");\n }\n\n const matched = selectUserForEmail(searchData, email);\n if (!matched) {\n throw new ApiAnswered(`No user has the email ${email}.`);\n }\n\n const resetUrl = `${cleanBaseUrl}/api/admin/users/${matched.id}/reset-password`;\n const resetRes = await fetch(resetUrl, {\n method: \"POST\",\n headers: {\n \"Authorization\": `Bearer ${serviceKey}`,\n \"Content-Type\": \"application/json\",\n \"Accept\": \"application/json\"\n },\n body: JSON.stringify({ password: finalPass })\n });\n\n if (!resetRes.ok) {\n throw new ApiAnswered(`Password reset refused: ${await refusalReason(resetRes)}`);\n }\n\n console.log(\"API reset successful.\");\n console.log(chalk.bold(\" 🔑 Rebase Auth — Reset Password (via API)\"));\n console.log(\"\");\n // The address as stored, not as typed — they differ in case often\n // enough that echoing the input hides which account was touched.\n console.log(` ${chalk.gray(\"Email:\")} ${matched.email}`);\n // Echoed only when we invented it. A password the operator typed\n // is already theirs; printing it again only adds scrollback.\n console.log(` ${chalk.gray(\"Password:\")} ${wasGenerated ? finalPass : \"*\".repeat(finalPass.length)}`);\n console.log(\"\");\n return;\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err);\n // The backend answered and said no — a password too weak, a user\n // it does not have. That answer stands: writing the hash straight\n // into the database instead skipped the strength rule it had just\n // applied, and ended no sessions. Only a backend that could not be\n // reached is a reason to go round it.\n if (err instanceof ApiAnswered) {\n console.error(chalk.red(`✗ ${errMsg}`));\n process.exitCode = 1;\n return;\n }\n console.warn(chalk.yellow(\"API reset failed, falling back to direct database update...\"));\n console.warn(chalk.gray(` Details: ${errMsg}`));\n }\n }\n\n // 2. Direct-DB Fallback\n const backendDir = requireBackendDir(projectRoot);\n const tsxBin = resolveTsx(projectRoot);\n\n if (!tsxBin) {\n exitDependenciesNotInstalled(projectRoot);\n }\n\n // The database the `db` family would use, resolved — and, for a remembered\n // compose container that is stopped, started — the same way. A stock\n // scaffold leaves DATABASE_URL commented out and runs on the managed\n // database, which only exists in a child's environment when something puts\n // it there — without this the script connected with libpq's defaults,\n // localhost:5432 as the OS user. An external DATABASE_URL adds nothing\n // here: the child already reads it.\n let prepared: PreparedDatabase;\n try {\n const { ensureDockerDatabase } = await import(\"./db\");\n await ensureDockerDatabase(projectRoot, rawArgs);\n const { prepareDatabaseEnv } = await import(\"../dev-db/prepare\");\n prepared = await prepareDatabaseEnv(projectRoot, {\n onProgress: (message) => console.log(chalk.gray(` ${message}`))\n });\n } catch (err) {\n console.error(chalk.red(\"✗ Direct database update failed.\"));\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n\n // Opened here first, so a database that does not answer gets the banner\n // every other command prints — not the script's raw error and stack — and\n // no script is written for it.\n const { databaseUrlOf } = await import(\"./db\");\n const url = databaseUrlOf(prepared, readEnvFile(projectRoot));\n if (url) {\n const failure = await databaseOpenFailure(url, prepared.database.source);\n if (failure) {\n for (const line of failure) console.error(line);\n process.exit(1);\n }\n }\n\n try {\n const env: Record<string, string> = { ...process.env as Record<string, string> };\n if (envFile) {\n env.DOTENV_CONFIG_PATH = envFile;\n }\n env.REBASE_RESET_EMAIL = email;\n env.REBASE_RESET_PASSWORD = newPassword;\n env.REBASE_ENV_FILE_PATH = envFile || path.join(projectRoot, \".env\");\n Object.assign(env, prepared.env);\n\n const scriptContent = resetPasswordScript(wasGenerated, parseEnvBoolean(process.env.REBASE_DEBUG) === true);\n\n const tmpScriptPath = path.join(backendDir, \".tmp-reset-password.ts\");\n fs.writeFileSync(tmpScriptPath, scriptContent, \"utf-8\");\n\n console.log(\"\");\n console.log(chalk.bold(\" 🔑 Rebase Auth — Reset Password (Direct DB Fallback)\"));\n console.log(\"\");\n console.log(` ${chalk.gray(\"Email:\")} ${email}`);\n console.log(` ${chalk.gray(\"Database:\")} ${prepared.description}`);\n if (!wasGenerated) {\n console.log(` ${chalk.gray(\"Password:\")} ${\"*\".repeat(newPassword.length)}`);\n }\n console.log(\"\");\n\n const child = spawn(tsxBin, [tmpScriptPath], {\n cwd: backendDir,\n stdio: \"inherit\",\n env\n });\n\n // The script is written into the user's backend directory, so every\n // exit has to remove it. Without an `error` handler a failed spawn\n // raises an unhandled event, the process dies before `close`, and\n // `.tmp-reset-password.ts` is left behind to be committed.\n const cleanup = () => {\n try { fs.unlinkSync(tmpScriptPath); } catch { /* already gone */ }\n };\n\n return new Promise((resolve) => {\n child.on(\"error\", (err) => {\n cleanup();\n console.error(chalk.red(\"✗ Could not run the reset script.\"));\n console.error(chalk.gray(` ${err.message}`));\n process.exit(1);\n });\n child.on(\"close\", (code) => {\n cleanup();\n if (code !== 0) {\n process.exit(code ?? 1);\n }\n resolve();\n });\n });\n } catch (err) {\n console.error(chalk.red(\"✗ Direct database update failed.\"));\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n}\n\n/**\n * Why the database the fallback would reset in cannot be opened, as the lines\n * to print — or null when it opens.\n *\n * A stopped database, refused credentials and a database name the server does\n * not have get the boxed banner the other commands print; anything else is one\n * sentence. Either way the password was not reset and no script was written.\n */\nasync function databaseOpenFailure(url: string, source: DevDatabaseSource): Promise<string[] | null> {\n const { Client } = await import(\"pg\");\n const client = new Client({ connectionString: url, connectionTimeoutMillis: 10_000 });\n client.on(\"error\", () => undefined);\n try {\n await client.connect();\n await client.query(\"SELECT 1\");\n return null;\n } catch (error) {\n const { connectionErrorText, connectionFailureBanner, connectionRefusedFixes } =\n await import(\"../dev-db/connection-banner\");\n const consequence = \"The password was not reset.\";\n return connectionFailureBanner(url, error, { consequence, fixes: connectionRefusedFixes(source) }) ?? [\n chalk.red(`✗ Could not open the database: ${redactConnectionPasswords(connectionErrorText(error))}`),\n chalk.gray(` ${consequence}`)\n ];\n } finally {\n await client.end().catch(() => undefined);\n }\n}\n\n/**\n * The script the direct-database fallback runs under the project's own tsx, so\n * it resolves the project's `@rebasepro/server-postgres` and schema.\n *\n * It ends the account's sessions in the transaction that sets the password,\n * as every door through the API does (`replaceUserPassword`): the refresh\n * tokens and outstanding reset links go, and `tokens_valid_after` voids the\n * access tokens already handed out. An operator resetting a phished account\n * with the backend down is the case this exists for, and a reset that left the\n * attacker's refresh token minting access tokens did not recover anything.\n *\n * It exits 0 only when a row was updated: a missing user and a thrown error are\n * both exit 1. `echoPassword` prints the new password, for a generated one;\n * `showStack` prints a failure's stack rather than its sentence (`--debug`).\n *\n * Exported so its tests can run it.\n */\nexport function resetPasswordScript(echoPassword: boolean, showStack = false): string {\n return `\nimport { createPostgresDatabaseConnection } from \"@rebasepro/server-postgres\";\nimport { hashPassword } from \"@rebasepro/server\";\nimport { getTableConfig } from \"drizzle-orm/pg-core\";\nimport * as dotenv from \"dotenv\";\nimport path from \"path\";\nimport fs from \"fs\";\n\ndotenv.config({ path: process.env.REBASE_ENV_FILE_PATH, quiet: true });\n\n// Lowercased, as every address is stored (\\`normalizeEmail\\`): matched as\n// typed, \"Ops@Acme.test\" found no row.\nconst email = process.env.REBASE_RESET_EMAIL!.trim().toLowerCase();\nconst newPassword = process.env.REBASE_RESET_PASSWORD!;\n\nconst quote = (identifier: string) => '\"' + identifier.replace(/\"/g, '\"\"') + '\"';\n\nasync function resetPassword() {\n const { pool } = createPostgresDatabaseConnection(process.env.DATABASE_URL!);\n const hash = await hashPassword(newPassword);\n\n let usersTable;\n try {\n const schemaPath = path.resolve(\"./src/schema.generated.ts\");\n if (fs.existsSync(schemaPath)) {\n const schema = await import(\"file://\" + schemaPath);\n usersTable = schema.users || schema.tables?.users;\n }\n } catch (e) {\n // ignore and fallback\n }\n\n if (!usersTable) {\n const pgServer = await import(\"@rebasepro/server-postgres\");\n usersTable = pgServer.users;\n }\n\n // The physical names, from the table object: the collection may map its\n // properties to other columns, and the statements below are plain SQL.\n const { name: tableName, schema: tableSchema } = getTableConfig(usersTable);\n const usersSchema = tableSchema || \"public\";\n const users = quote(usersSchema) + \".\" + quote(tableName);\n const idColumn = quote(usersTable.id.name);\n const emailColumn = quote(usersTable.email.name);\n const passwordColumn = quote((usersTable.passwordHash ?? usersTable.password_hash).name);\n // Where \\`ensureAuthTablesExist\\` puts the tables that hang off the users\n // table: beside it, or in \\`rebase\\` when it lives in \\`public\\`.\n const authSchema = usersSchema === \"public\" ? \"rebase\" : usersSchema;\n\n const client = await pool.connect();\n try {\n // A database nothing has booted against — or a managed one \\`db reset\\`\n // emptied — has no users table, and so no account to reset. Said as\n // that, not as pg's \\`relation … does not exist\\`.\n const usersTable = await client.query(\"SELECT to_regclass($1) IS NOT NULL AS present\", [users]);\n if (!usersTable.rows[0]?.present) {\n console.error(\"✗ \" + users + \" does not exist in this database, so it holds no account to reset.\");\n console.error(\" Nothing was changed. \\`rebase dev\\` creates it the first time it boots against this database.\");\n process.exit(1);\n }\n\n await client.query(\"BEGIN\");\n const updated = await client.query(\n \"UPDATE \" + users + \" SET \" + passwordColumn + \" = $1 WHERE \" + emailColumn + \" = $2 \" +\n \"RETURNING \" + idColumn + \" AS id, \" + emailColumn + \" AS email\",\n [hash, email]\n );\n if (updated.rows.length === 0) {\n await client.query(\"ROLLBACK\");\n // Nothing was updated, so nothing was reset. Exiting 0 here reported\n // success for a no-op, which is what a script would have believed.\n console.error(\"✗ User not found: \" + email);\n process.exit(1);\n }\n const uid = updated.rows[0].id;\n\n // A table or column the server has not created yet (it never booted\n // against this database) holds no session to end.\n const watermark = await client.query(\n \"SELECT 1 FROM information_schema.columns WHERE table_schema = $1 AND table_name = $2 AND column_name = 'tokens_valid_after'\",\n [usersSchema, tableName]\n );\n if (watermark.rows.length > 0) {\n await client.query(\"UPDATE \" + users + \" SET tokens_valid_after = NOW() WHERE \" + idColumn + \" = $1\", [uid]);\n }\n for (const table of [\"refresh_tokens\", \"password_reset_tokens\"]) {\n const qualified = quote(authSchema) + \".\" + quote(table);\n const present = await client.query(\"SELECT to_regclass($1) IS NOT NULL AS present\", [qualified]);\n if (present.rows[0]?.present) {\n await client.query(\"DELETE FROM \" + qualified + \" WHERE uid = $1\", [uid]);\n }\n }\n await client.query(\"COMMIT\");\n\n console.log(\"✅ Password reset for: \" + updated.rows[0].email);\n console.log(\" Every session of this account has ended.\");\n ${echoPassword ? 'console.log(\" Password: \" + newPassword);' : \"\"}\n process.exit(0);\n } catch (error) {\n await client.query(\"ROLLBACK\").catch(() => undefined);\n throw error;\n } finally {\n client.release();\n }\n}\n\n// A thrown error is a failed reset, and exits like one — a refused connection\n// that exits 0 reads as a reset to anything checking the exit code. Said as a\n// sentence: the stack is the script's own, and only --debug asks for it.\nconst describe = (error: unknown): string => {\n if (error instanceof AggregateError && !error.message && error.errors.length > 0) return describe(error.errors[0]);\n const message = error instanceof Error ? error.message : String(error);\n const code = error && typeof error === \"object\" && \"code\" in error && typeof error.code === \"string\" ? error.code : \"\";\n return code && !message.includes(code) ? message + \" (\" + code + \")\" : message;\n};\nresetPassword().catch((error) => {\n ${showStack ? \"console.error(error);\" : \"console.error(\\\"✗ The password was not reset: \\\" + describe(error));\"}\n process.exit(1);\n});\n`;\n}\n\nfunction printAuthHelp() {\n console.log(`\n${chalk.bold(\"rebase auth\")} — Authentication management commands\n\n${chalk.green.bold(\"Usage\")}\n rebase auth ${chalk.blue(\"<command>\")} [options]\n\n${chalk.green.bold(\"Commands\")}\n ${chalk.blue.bold(\"reset-password\")} Reset a user's password\n\n${chalk.green.bold(\"reset-password Options\")}\n ${chalk.blue(\"--email, -e\")} User's email address\n ${chalk.blue(\"--password, -p\")} New password (default: one is generated and printed)\n\n${chalk.green.bold(\"Examples\")}\n rebase auth reset-password user@example.com\n rebase auth reset-password --email user@example.com --password MyNewPass!\n`);\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { c as branchDatabaseName, d as clearActiveBranch, f as databaseNameOf, m as writeActiveBranch, p as readActiveBranch } from "./prepare-DdnU70z8.js";
1
+ import { c as branchDatabaseName, d as clearActiveBranch, f as databaseNameOf, m as writeActiveBranch, p as readActiveBranch } from "./prepare-1rVNd2PF.js";
2
2
  export { branchDatabaseName, clearActiveBranch, databaseNameOf, readActiveBranch, writeActiveBranch };
@@ -1,12 +1,11 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { n as getPMCommands, t as detectPackageManager } from "./package-manager-DSEOwTqM.js";
3
- import { p as requireProjectRoot } from "./project-Wp2zoyeN.js";
4
- import { n as parseCommandArgs, r as wantsHelp, t as UsageError } from "./args-BX0YD14a.js";
3
+ import { C as wantsHelp, b as parseCommandArgs, p as requireProjectRoot, y as UsageError } from "./project-g4K6kV1t.js";
5
4
  import { n as cliVersion } from "./version-Buyyo1ut.js";
6
- import { c as buildableApps, d as findBackendApp, f as formatAppAddress, o as ManifestError, p as loadManifest, v as staticAppAddress } from "./manifest-DRp0UVTj.js";
7
- import { b as toolStdio, o as buildBundle, p as detectFrameworkDepDrift, s as buildStaticBundle, t as DEFAULT_BUNDLE_DIR } from "./bundle-DtCCCr4w.js";
8
- import { i as staticBuildEnv, n as foldFrontendIntoBundle, t as assertBuiltForPath } from "./fold-static-hDHtDfTq.js";
9
- import { l as writeResourceGraphFile, n as deriveOptionsFor, r as deriveResourceGraph, t as RESOURCE_GRAPH_FILENAME } from "./derive-CsoFGAnK.js";
5
+ import { c as buildableApps, d as findBackendApp, f as formatAppAddress, o as ManifestError, p as loadManifest, v as staticAppAddress } from "./manifest-nvPdLlJY.js";
6
+ import { b as toolStdio, o as buildBundle, p as detectFrameworkDepDrift, s as buildStaticBundle, t as DEFAULT_BUNDLE_DIR } from "./bundle-DlqkDYSe.js";
7
+ import { i as staticBuildEnv, n as foldFrontendIntoBundle, t as assertBuiltForPath } from "./fold-static-CybSay_W.js";
8
+ import { l as writeResourceGraphFile, n as deriveOptionsFor, r as deriveResourceGraph, t as RESOURCE_GRAPH_FILENAME } from "./derive-MTdClnkc.js";
10
9
  import chalk from "chalk";
11
10
  import fs from "fs";
12
11
  import path from "path";
@@ -333,4 +332,4 @@ async function runWorkspaceBuilds(projectRoot) {
333
332
  //#endregion
334
333
  export { build_exports as n, buildAssetApp as t };
335
334
 
336
- //# sourceMappingURL=build-BBgT8EJZ.js.map
335
+ //# sourceMappingURL=build-et7Rccxi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-BBgT8EJZ.js","names":[],"sources":["../src/commands/build.ts"],"sourcesContent":["/**\n * CLI command: rebase build [app...]\n *\n * Builds the apps a repository declares in `rebase.json`.\n *\n * For a `backend` app this produces a **bundle** — compiled collections,\n * functions and schema plus a manifest — which is the artifact the runtime\n * loads. For `static` and bundled `admin` apps it runs the declared build\n * command and reports where the output landed.\n *\n * A project with no manifest, or one whose backend has been ejected to its own\n * entrypoint, falls back to the previous behaviour: run every workspace's own\n * `build` script. Nothing that built before stops building.\n */\nimport fs from \"fs\";\nimport path from \"path\";\nimport chalk from \"chalk\";\nimport { execa } from \"execa\";\nimport type { RebaseAppConfig, RebaseStaticAppConfig } from \"@rebasepro/types\";\nimport { requireProjectRoot } from \"../utils/project\";\nimport { parseCommandArgs, UsageError, wantsHelp } from \"../utils/args\";\nimport { detectPackageManager, getPMCommands } from \"../utils/package-manager\";\nimport { cliVersion } from \"../utils/version\";\nimport { toolStdio } from \"../utils/tool-stdio\";\nimport {\n buildableApps,\n findBackendApp,\n formatAppAddress,\n loadManifest,\n ManifestError,\n resolveBackendPaths,\n staticAppAddress\n} from \"../manifest\";\nimport {\n buildBundle,\n buildStaticBundle,\n detectFrameworkDepDrift,\n DEFAULT_BUNDLE_DIR,\n VENDOR_SIZE_WARN_BYTES\n} from \"../bundle\";\nimport { assertBuiltForPath, foldFrontendIntoBundle, staticBuildEnv } from \"../fold-static\";\nimport { deriveOptionsFor, deriveResourceGraph, RESOURCE_GRAPH_FILENAME, writeResourceGraphFile } from \"../resources/derive\";\n\nfunction printHelp(): void {\n console.log(`\n${chalk.bold(\"rebase build\")} — build the apps declared in rebase.json\n\n${chalk.bold(\"Usage\")}\n rebase build [app...] Build the named apps (default: all)\n\n${chalk.bold(\"Options\")}\n --output, --out <dir> Bundle output directory (default: ${DEFAULT_BUNDLE_DIR});\n one app at a time\n --skip-type-check Compile without type checking (faster; use for iteration only)\n --skip-schema Do not regenerate the database schema from collections\n --no-static Do not fold the frontend into the backend bundle (each\n static app still gets its own bundle)\n --skip-static-build Fold the frontend as already built, without running its\n build command — for CI that built it in an earlier step\n --no-vendor Do not install dependencies into the bundle (they\n install on every pod start instead, ~40-60s slower)\n --vendor Install them whatever the tree's size — for a\n deploy that builds from source and never uploads it\n --workspace Run every workspace's own build script instead\n -h, --help Show this help\n\n${chalk.bold(\"Examples\")}\n rebase build Build every app in this repository\n rebase build backend Build only the backend bundle\n rebase build web Build only the \"web\" static app\n`.trim());\n}\n\n/**\n * The two commands that turn a custom-runtime app into an image.\n *\n * Exported for the test, because the failure this replaced was in the printed\n * text and nowhere else. It said:\n *\n * docker build -f backend/Dockerfile .\n *\n * for every custom backend, and the `.` was a guess — `context` was validated,\n * stored on the config, and read by nothing. For the reference project that\n * guess is wrong: `app/backend/Dockerfile` opens by copying `pnpm-lock.yaml`\n * and `pnpm-workspace.yaml`, which live at the monorepo root, so the command\n * `rebase build` handed you died on its first instruction. The deploy that\n * actually works, `infra/cloudbuild.yaml`, has always said\n * `-f app/backend/Dockerfile .` from the root.\n *\n * `dockerfile` is relative to `rebase.json`; `context` is too, and may point\n * above it. Docker resolves `-f` against the working directory, not the\n * context, so the path has to be re-expressed against wherever the command\n * runs — which is what the old line never did and is the whole reason it\n * could not be right for both.\n */\nexport function dockerBuildHint(\n projectRoot: string,\n name: string,\n app: { dockerfile?: string; context?: string }\n): string[] {\n const dockerfile = app.dockerfile ?? \"Dockerfile\";\n const context = app.context ?? \".\";\n const contextDir = path.resolve(projectRoot, context);\n const fromContext = path.relative(contextDir, path.resolve(projectRoot, dockerfile));\n\n const build = `${chalk.cyan(`npm run build --workspace ${name}`)}`;\n\n // A Dockerfile outside its own context is legal to `docker build` but means\n // nothing it copies is reachable, so there is no command to offer. Say what\n // is wrong instead of printing one that cannot work.\n if (fromContext.startsWith(\"..\")) {\n return [\n chalk.dim(` ${build}`),\n chalk.yellow(` ⚠ ${dockerfile} is outside the build context (${context}) — nothing it COPYs is reachable.`),\n chalk.dim(` Widen \"context\" in rebase.json, or move the Dockerfile inside it.`)\n ];\n }\n\n const docker = chalk.cyan(`docker build -f ${fromContext} .`);\n return context === \".\"\n ? [chalk.dim(` ${build} then ${docker}`)]\n : [chalk.dim(` ${build}`), chalk.dim(` ${chalk.cyan(`cd ${context}`)} && ${docker}`)];\n}\n\nexport async function buildCommand(rawArgs: string[] = []): Promise<void> {\n if (wantsHelp(rawArgs)) {\n printHelp();\n return;\n }\n\n const { flags: args, positionals: requested } = parseCommandArgs({\n spec: {\n \"--output\": String,\n // `--out` kept as an accepted alias. `generate-sdk` has always\n // spelled this `--output`, and two names for one concept across one\n // CLI is a thing you have to remember rather than know. `--output`\n // is canonical now; `--out` still works so no script breaks.\n \"--out\": \"--output\",\n \"--skip-type-check\": Boolean,\n /* Do not install the declared dependencies into the bundle. The\n bundle still works — it installs them at boot, as every bundle did\n before vendoring existed — so this is for a build that must not\n shell out to npm, not for a smaller artifact. */\n \"--no-vendor\": Boolean,\n /* Keep the installed tree whatever its size. The size ceiling\n protects an upload that a source-built deploy never performs, so\n that path needs a way to say so. */\n \"--vendor\": Boolean,\n \"--skip-schema\": Boolean,\n /* Do not fold the frontend into the backend bundle. For a project\n that publishes its frontend elsewhere and does not want the assets\n travelling with its API. */\n \"--no-static\": Boolean,\n /* Fold assets that are already built, without re-running the app's\n build command — for a CI job that built the frontend in an earlier\n step. */\n \"--skip-static-build\": Boolean,\n \"--workspace\": Boolean\n },\n rawArgs,\n commandWords: 1,\n command: \"build\"\n });\n\n const projectRoot = requireProjectRoot();\n\n if (args[\"--workspace\"]) {\n await runWorkspaceBuilds(projectRoot);\n return;\n }\n\n let loaded;\n try {\n loaded = loadManifest(projectRoot);\n } catch (err) {\n if (err instanceof ManifestError) {\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 const { manifest, source } = loaded;\n\n let targets = buildableApps(manifest);\n if (requested.length > 0) {\n const known = new Set(targets.map(t => t.name));\n const unknown = requested.filter(name => !known.has(name));\n if (unknown.length > 0) {\n console.error(chalk.red(`✗ Unknown app(s): ${unknown.join(\", \")}`));\n console.error(chalk.dim(` This repository declares: ${targets.map(t => t.name).join(\", \") || \"(none)\"}`));\n process.exit(1);\n }\n targets = targets.filter(t => requested.includes(t.name));\n }\n\n if (targets.length === 0) {\n console.log(chalk.yellow(\"No buildable apps declared. Nothing to do.\"));\n return;\n }\n\n // An ejected backend owns its own build; the workspace scripts are the only\n // thing that knows how to run it.\n const backend = findBackendApp(manifest);\n if (!backend && source === \"synthesized\") {\n console.log(chalk.dim(\"No rebase.json found — building workspace packages.\\n\"));\n await runWorkspaceBuilds(projectRoot);\n return;\n }\n\n // `--output` names one bundle directory, resolved from where it was typed.\n // It is refused for a build that produces several bundles rather than\n // handed to each: every bundle build empties its directory first, so the\n // last app built deleted the others' and the build still reported success.\n const output = args[\"--output\"] ? path.resolve(process.cwd(), args[\"--output\"]) : undefined;\n const bundled = targets.filter(({ app }) =>\n (app.type === \"backend\" && app.runtime !== \"custom\") ||\n (app.type === \"static\" && Boolean(app.build) && Boolean(app.output)));\n if (output && bundled.length > 1) {\n throw new UsageError(\n `--output names one bundle directory, and this build produces ${bundled.length}: ` +\n `${bundled.map(t => t.name).join(\", \")}. Build one app into it: ` +\n `rebase build ${bundled[0].name} --output ${args[\"--output\"]}`\n );\n }\n\n console.log(`${chalk.bold(\"Rebase\")} — building ${targets.length} app(s)\\n`);\n\n // Each static app is built once per run, whichever consumer gets to it\n // first: folding into the backend bundle, or its own static bundle.\n const builtApps = new Set<string>();\n\n for (const { name, app } of targets) {\n console.log(chalk.cyan(`▸ ${name}`) + chalk.dim(` (${app.type})`));\n\n if (app.type === \"backend\" && app.runtime === \"custom\") {\n // An ejected backend's artifact is an IMAGE, not a bundle. Building\n // one anyway produced a `dist-bundle/` the project never deploys,\n // which is worse than doing nothing: it looks like the thing that\n // ships. The workspace's own `build` script compiles this app, and\n // the Dockerfile turns it into the image.\n console.log(chalk.dim(\" custom runtime — this project builds its own image, not a bundle\"));\n for (const line of dockerBuildHint(projectRoot, name, app)) console.log(line);\n console.log(\"\");\n continue;\n }\n\n if (app.type === \"backend\") {\n // Derived per backend app, because each has its own config\n // directory. Issues are fatal here rather than reported: a bundle\n // whose manifest is missing a bucket the code declares would deploy\n // into a tenant with nothing provisioned for it, and the first sign\n // would be uploads failing in production.\n const { graph: resourceGraph, issues } = await deriveResourceGraph(deriveOptionsFor(projectRoot, app));\n if (issues.length > 0) {\n console.error(chalk.red(`\\n ✗ ${issues.length} problem(s) in the declared resources:\\n`));\n for (const issue of issues) console.error(` ${chalk.bold(issue.path)} ${issue.message}`);\n console.error(\"\");\n process.exitCode = 1;\n return;\n }\n // Written alongside the bundle so the repository records what this\n // project needs. `rebase resources --check` is what keeps it honest.\n // Committed, so a change to it is said: the first build of a\n // scaffold otherwise left it untracked with no word on what it is.\n if (writeResourceGraphFile(projectRoot, resourceGraph).changed) {\n console.log(chalk.dim(` ${RESOURCE_GRAPH_FILENAME} updated — commit it: it records what this project needs from a host`));\n }\n\n /* The framework pins, read before the build and reported after it.\n Ranges no single version satisfies are refused by `buildBundle`\n itself, before it builds anything, for every command that builds\n a bundle. */\n const drift = detectFrameworkDepDrift(projectRoot, cliVersion());\n\n const result = await buildBundle({\n projectRoot,\n appName: name,\n app,\n outDir: output,\n runtimeRange: manifest.rebase,\n resources: resourceGraph,\n skipTypeCheck: args[\"--skip-type-check\"],\n skipSchema: args[\"--skip-schema\"],\n vendor: args[\"--no-vendor\"] ? false : (args[\"--vendor\"] ? true : undefined)\n });\n const rel = path.relative(projectRoot, result.outDir);\n console.log(chalk.green(` ✓ bundle → ${rel}/`));\n // A headless build has no schema version — the API is introspected\n // from the live database at boot — and interpolating it anyway left\n // the summary ending in a dangling `schema `, which reads as a value\n // that failed to render rather than one that does not exist.\n const schemaVersion = result.manifest.schemaVersion;\n console.log(chalk.dim(\n ` ${result.collectionCount} collection(s)${schemaVersion ? `, schema ${schemaVersion}` : \"\"}`\n ));\n /* Say what the bundle's cold start will be, at the one moment\n anyone is listening.\n\n A vendored bundle starts in about five seconds; one that installs\n at boot takes forty to sixty, on EVERY pod start — an eviction, a\n node failure, an OOM, a runtime rollout. That is not a build\n detail, it is what each of those events costs in downtime, and it\n is invisible until an incident unless it is said here. */\n if (result.vendor.vendored) {\n console.log(chalk.dim(` dependencies installed into the bundle (${result.vendor.target?.os}/${result.vendor.target?.cpu})`));\n if ((result.vendor.bytes ?? 0) > VENDOR_SIZE_WARN_BYTES) {\n const mb = Math.round((result.vendor.bytes ?? 0) / (1024 * 1024));\n /* The limit is on the *compressed* upload and this is the\n tree on disk, so a number above 100 does not mean the\n upload fails — but \"201 MB, close to the 100 MB limit\"\n reads as nonsense and got ignored for exactly that\n reason. Say which quantity is which. */\n console.log(chalk.yellow(\n ` ⚠ the installed tree is ${mb} MB on disk — enough to risk the control plane's 100 MB ` +\n \"limit on the compressed upload\"));\n console.log(chalk.dim(\" Shrink the declared dependencies, or rebuild with --no-vendor.\"));\n }\n } else if (Object.keys(result.manifest.deps.declared).length === 0) {\n // Nothing to install is not a degraded state — this bundle\n // already starts as fast as a vendored one. Warning here would\n // train people to ignore the warning that matters.\n console.log(chalk.dim(\" no dependencies to install — nothing to bundle\"));\n } else {\n console.log(chalk.yellow(` ⚠ dependencies not bundled: ${result.vendor.skipped}`));\n console.log(chalk.dim(\" They install on every pod start instead, which is ~40-60s of cold start.\"));\n }\n\n if (result.manifest.hooks.native) {\n const names = (result.manifest.hooks.nativeModules ?? []).map(m => m.name).join(\", \");\n console.log(chalk.yellow(` ⚠ native dependencies detected: ${names}`));\n console.log(chalk.dim(\" These cannot run on the managed runtime. See `rebase doctor`.\"));\n }\n\n /* Framework pins older than this CLI.\n\n Warned here because this is the only moment anyone can be told.\n Locally every `@rebasepro/*` resolves through pnpm's workspace and\n `link:` overrides to the checkout, so the version strings in\n package.json are never exercised — the project runs fine on a\n developer's machine while declaring something years old. Those\n strings are first honoured when the runtime npm-installs them in\n the cloud, and by then the symptom is a tenant that boots and then\n misbehaves against its database.\n\n A warning rather than a hard failure: the CLI cannot know that a\n newer package has actually been published, and refusing to build\n over a guess would be worse than saying it out loud. (`drift` was\n read before the build, above.) */\n if (drift.behind.length > 0) {\n console.log(chalk.yellow(` ⚠ framework dependencies older than this CLI (${cliVersion()}):`));\n for (const dep of drift.behind) {\n console.log(chalk.dim(` ${dep.name}@${dep.range} (${dep.file})`));\n }\n console.log(chalk.dim(\" The image supplies the server, but your bundle supplies the database\"));\n console.log(chalk.dim(\" driver — a newer runtime does not update it.\"));\n console.log(chalk.dim(` Run \\`${upgradeToThisCli()}\\`, then rebuild.`));\n } else if (drift.disagreeing.length > 0) {\n console.log(chalk.yellow(` ⚠ mixed @rebasepro versions declared: ${drift.disagreeing.join(\", \")}`));\n console.log(chalk.dim(\" These are published together and expect to run together.\"));\n console.log(chalk.dim(` Run \\`${upgradeToThisCli()}\\` to pin them alike, then rebuild.`));\n }\n\n /* Fold the project's static apps into the backend bundle, so ONE\n runtime serves the site at `/`, the admin at `/admin` and the API\n at `/api` — the shape the scaffolded template produces and the\n shape a custom container already had.\n\n Without this, moving a project to the managed runtime silently\n removed its website: the API answered perfectly and every page\n 404'd, because the managed pod runs the backend bundle and nothing\n else. Parity with the container being replaced is the only honest\n baseline for calling managed a drop-in.\n\n `--no-static` opts out, for a project that publishes its frontend\n somewhere else and does not want the assets in its bundle. */\n if (!args[\"--no-static\"]) {\n const folded = await foldFrontendIntoBundle({\n projectRoot,\n manifest,\n bundleDir: result.outDir,\n skipBuild: args[\"--skip-static-build\"] === true,\n builtApps,\n log: (m) => console.log(m)\n }).catch((err: unknown) => {\n console.error(chalk.red(` ✗ ${err instanceof Error ? err.message : String(err)}`));\n process.exit(1);\n });\n for (const outcome of folded ?? []) {\n console.log(\n chalk.green(` ✓ ${outcome.appName} folded in`) +\n chalk.dim(` (${outcome.fileCount} file(s) → served at ${formatAppAddress(outcome)})`)\n );\n }\n }\n } else if (app.type === \"static\") {\n await buildAssetApp(projectRoot, name, app, manifest.rebase, output, { builtApps }).catch((err: unknown) => {\n console.error(chalk.red(` ✗ ${err instanceof Error ? err.message : String(err)}`));\n process.exit(1);\n });\n }\n\n console.log(\"\");\n }\n\n console.log(chalk.green(\"✓ Build complete.\"));\n}\n\n/**\n * Build a static app and package it into a static bundle.\n *\n * Runs the app's own build command, checks it produced the declared output, then\n * packages that output into a `static`-kind bundle — the same deployable shape as\n * a backend bundle, so a frontend or admin app deploys through the identical\n * path and runs on the identical image, just serving files instead of an API.\n *\n * Throws when the build fails or produces nothing usable, so the caller answers\n * in its own way: `rebase build` with a red line, `rebase cloud deploy --json`\n * with its JSON error.\n */\nexport async function buildAssetApp(\n projectRoot: string,\n name: string,\n app: RebaseAppConfig,\n runtimeRange: string,\n outOverride?: string,\n /**\n * `quietStdout`: every line, the build command's included, goes to stderr. See `toolStdio`.\n * `builtApps`: the static apps already built in this run (see `FoldOptions.builtApps`).\n */\n options: { quietStdout?: boolean; builtApps?: Set<string> } = {}\n): Promise<string | undefined> {\n const asset = app as RebaseStaticAppConfig;\n // The path part is what the app is built for and mounted at; the hostname,\n // when `path` names one, only travels in the bundle.\n const address = staticAppAddress(name, asset);\n const basePath = address.path;\n const say = (line: string): void => {\n if (options.quietStdout) console.error(line);\n else console.log(line);\n };\n\n if (!asset.build) {\n say(chalk.dim(\" no build command declared — skipping\"));\n return undefined;\n }\n\n if (options.builtApps?.has(name)) {\n say(chalk.dim(\" built once already in this run — packaging that output\"));\n } else {\n try {\n await execa(asset.build, {\n cwd: projectRoot,\n stdio: toolStdio(options.quietStdout),\n shell: true,\n env: staticBuildEnv(basePath, name)\n });\n } catch {\n throw new Error(`build command failed for \"${name}\"`);\n }\n options.builtApps?.add(name);\n }\n\n if (!asset.output) {\n say(chalk.yellow(\" no output directory declared — built, but nothing to bundle\"));\n return undefined;\n }\n\n const outputPath = path.join(projectRoot, asset.output);\n if (!fs.existsSync(outputPath)) {\n // The command exited 0 but produced nothing where the manifest says it\n // should. Bundling that would ship an empty site.\n throw new Error(`declared output \"${asset.output}\" does not exist after building`);\n }\n\n // The assets were built for `basePath`; refusing here is the difference\n // between a build error and a blank page nobody can diagnose.\n const indexHtml = path.join(outputPath, \"index.html\");\n if (fs.existsSync(indexHtml)) {\n assertBuiltForPath(fs.readFileSync(indexHtml, \"utf8\"), basePath, name);\n }\n\n // Per-app bundle directory, so a project's several static apps do not clobber\n // one another or the backend's `dist-bundle`.\n const outDir = outOverride\n ? path.resolve(process.cwd(), outOverride)\n : path.join(projectRoot, `dist-bundle-${name}`);\n const result = buildStaticBundle({\n projectRoot,\n appName: name,\n assetsDir: outputPath,\n outDir,\n runtimeRange,\n path: basePath,\n host: address.host,\n spa: asset.spa ?? true,\n cms: asset.cms\n });\n const rel = path.relative(projectRoot, result.outDir);\n say(\n chalk.green(` ✓ static bundle → ${rel}/`) +\n chalk.dim(` (${result.fileCount} file(s) → served at ${formatAppAddress(address)})`)\n );\n return result.outDir;\n}\n\n/**\n * The `rebase upgrade` line the drift warnings print.\n *\n * Aimed at this CLI's own version, because that is what the warning measured\n * against: \"older than this CLI\" is answered by moving to exactly this CLI, not\n * to whatever `latest` happens to be — which, on a canary, is older still.\n */\nfunction upgradeToThisCli(): string {\n const version = cliVersion();\n return version === \"unknown\" ? \"rebase upgrade\" : `rebase upgrade --to ${version}`;\n}\n\n/** The pre-manifest behaviour: build every workspace package. */\nasync function runWorkspaceBuilds(projectRoot: string): Promise<void> {\n const pm = detectPackageManager(projectRoot);\n const cmds = getPMCommands(pm);\n const buildCmd = cmds.runAll(\"build\");\n\n console.log(`${chalk.bold(\"Rebase\")} — Building all workspaces with ${chalk.cyan(pm)}...\\n`);\n\n try {\n await execa(buildCmd[0], buildCmd.slice(1), {\n cwd: projectRoot,\n stdio: \"inherit\"\n });\n } catch {\n console.error(chalk.red(\"\\n✗ Build failed.\"));\n process.exit(1);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"build-et7Rccxi.js","names":[],"sources":["../src/commands/build.ts"],"sourcesContent":["/**\n * CLI command: rebase build [app...]\n *\n * Builds the apps a repository declares in `rebase.json`.\n *\n * For a `backend` app this produces a **bundle** — compiled collections,\n * functions and schema plus a manifest — which is the artifact the runtime\n * loads. For `static` and bundled `admin` apps it runs the declared build\n * command and reports where the output landed.\n *\n * A project with no manifest, or one whose backend has been ejected to its own\n * entrypoint, falls back to the previous behaviour: run every workspace's own\n * `build` script. Nothing that built before stops building.\n */\nimport fs from \"fs\";\nimport path from \"path\";\nimport chalk from \"chalk\";\nimport { execa } from \"execa\";\nimport type { RebaseAppConfig, RebaseStaticAppConfig } from \"@rebasepro/types\";\nimport { requireProjectRoot } from \"../utils/project\";\nimport { parseCommandArgs, UsageError, wantsHelp } from \"../utils/args\";\nimport { detectPackageManager, getPMCommands } from \"../utils/package-manager\";\nimport { cliVersion } from \"../utils/version\";\nimport { toolStdio } from \"../utils/tool-stdio\";\nimport {\n buildableApps,\n findBackendApp,\n formatAppAddress,\n loadManifest,\n ManifestError,\n resolveBackendPaths,\n staticAppAddress\n} from \"../manifest\";\nimport {\n buildBundle,\n buildStaticBundle,\n detectFrameworkDepDrift,\n DEFAULT_BUNDLE_DIR,\n VENDOR_SIZE_WARN_BYTES\n} from \"../bundle\";\nimport { assertBuiltForPath, foldFrontendIntoBundle, staticBuildEnv } from \"../fold-static\";\nimport { deriveOptionsFor, deriveResourceGraph, RESOURCE_GRAPH_FILENAME, writeResourceGraphFile } from \"../resources/derive\";\n\nfunction printHelp(): void {\n console.log(`\n${chalk.bold(\"rebase build\")} — build the apps declared in rebase.json\n\n${chalk.bold(\"Usage\")}\n rebase build [app...] Build the named apps (default: all)\n\n${chalk.bold(\"Options\")}\n --output, --out <dir> Bundle output directory (default: ${DEFAULT_BUNDLE_DIR});\n one app at a time\n --skip-type-check Compile without type checking (faster; use for iteration only)\n --skip-schema Do not regenerate the database schema from collections\n --no-static Do not fold the frontend into the backend bundle (each\n static app still gets its own bundle)\n --skip-static-build Fold the frontend as already built, without running its\n build command — for CI that built it in an earlier step\n --no-vendor Do not install dependencies into the bundle (they\n install on every pod start instead, ~40-60s slower)\n --vendor Install them whatever the tree's size — for a\n deploy that builds from source and never uploads it\n --workspace Run every workspace's own build script instead\n -h, --help Show this help\n\n${chalk.bold(\"Examples\")}\n rebase build Build every app in this repository\n rebase build backend Build only the backend bundle\n rebase build web Build only the \"web\" static app\n`.trim());\n}\n\n/**\n * The two commands that turn a custom-runtime app into an image.\n *\n * Exported for the test, because the failure this replaced was in the printed\n * text and nowhere else. It said:\n *\n * docker build -f backend/Dockerfile .\n *\n * for every custom backend, and the `.` was a guess — `context` was validated,\n * stored on the config, and read by nothing. For the reference project that\n * guess is wrong: `app/backend/Dockerfile` opens by copying `pnpm-lock.yaml`\n * and `pnpm-workspace.yaml`, which live at the monorepo root, so the command\n * `rebase build` handed you died on its first instruction. The deploy that\n * actually works, `infra/cloudbuild.yaml`, has always said\n * `-f app/backend/Dockerfile .` from the root.\n *\n * `dockerfile` is relative to `rebase.json`; `context` is too, and may point\n * above it. Docker resolves `-f` against the working directory, not the\n * context, so the path has to be re-expressed against wherever the command\n * runs — which is what the old line never did and is the whole reason it\n * could not be right for both.\n */\nexport function dockerBuildHint(\n projectRoot: string,\n name: string,\n app: { dockerfile?: string; context?: string }\n): string[] {\n const dockerfile = app.dockerfile ?? \"Dockerfile\";\n const context = app.context ?? \".\";\n const contextDir = path.resolve(projectRoot, context);\n const fromContext = path.relative(contextDir, path.resolve(projectRoot, dockerfile));\n\n const build = `${chalk.cyan(`npm run build --workspace ${name}`)}`;\n\n // A Dockerfile outside its own context is legal to `docker build` but means\n // nothing it copies is reachable, so there is no command to offer. Say what\n // is wrong instead of printing one that cannot work.\n if (fromContext.startsWith(\"..\")) {\n return [\n chalk.dim(` ${build}`),\n chalk.yellow(` ⚠ ${dockerfile} is outside the build context (${context}) — nothing it COPYs is reachable.`),\n chalk.dim(` Widen \"context\" in rebase.json, or move the Dockerfile inside it.`)\n ];\n }\n\n const docker = chalk.cyan(`docker build -f ${fromContext} .`);\n return context === \".\"\n ? [chalk.dim(` ${build} then ${docker}`)]\n : [chalk.dim(` ${build}`), chalk.dim(` ${chalk.cyan(`cd ${context}`)} && ${docker}`)];\n}\n\nexport async function buildCommand(rawArgs: string[] = []): Promise<void> {\n if (wantsHelp(rawArgs)) {\n printHelp();\n return;\n }\n\n const { flags: args, positionals: requested } = parseCommandArgs({\n spec: {\n \"--output\": String,\n // `--out` kept as an accepted alias. `generate-sdk` has always\n // spelled this `--output`, and two names for one concept across one\n // CLI is a thing you have to remember rather than know. `--output`\n // is canonical now; `--out` still works so no script breaks.\n \"--out\": \"--output\",\n \"--skip-type-check\": Boolean,\n /* Do not install the declared dependencies into the bundle. The\n bundle still works — it installs them at boot, as every bundle did\n before vendoring existed — so this is for a build that must not\n shell out to npm, not for a smaller artifact. */\n \"--no-vendor\": Boolean,\n /* Keep the installed tree whatever its size. The size ceiling\n protects an upload that a source-built deploy never performs, so\n that path needs a way to say so. */\n \"--vendor\": Boolean,\n \"--skip-schema\": Boolean,\n /* Do not fold the frontend into the backend bundle. For a project\n that publishes its frontend elsewhere and does not want the assets\n travelling with its API. */\n \"--no-static\": Boolean,\n /* Fold assets that are already built, without re-running the app's\n build command — for a CI job that built the frontend in an earlier\n step. */\n \"--skip-static-build\": Boolean,\n \"--workspace\": Boolean\n },\n rawArgs,\n commandWords: 1,\n command: \"build\"\n });\n\n const projectRoot = requireProjectRoot();\n\n if (args[\"--workspace\"]) {\n await runWorkspaceBuilds(projectRoot);\n return;\n }\n\n let loaded;\n try {\n loaded = loadManifest(projectRoot);\n } catch (err) {\n if (err instanceof ManifestError) {\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 const { manifest, source } = loaded;\n\n let targets = buildableApps(manifest);\n if (requested.length > 0) {\n const known = new Set(targets.map(t => t.name));\n const unknown = requested.filter(name => !known.has(name));\n if (unknown.length > 0) {\n console.error(chalk.red(`✗ Unknown app(s): ${unknown.join(\", \")}`));\n console.error(chalk.dim(` This repository declares: ${targets.map(t => t.name).join(\", \") || \"(none)\"}`));\n process.exit(1);\n }\n targets = targets.filter(t => requested.includes(t.name));\n }\n\n if (targets.length === 0) {\n console.log(chalk.yellow(\"No buildable apps declared. Nothing to do.\"));\n return;\n }\n\n // An ejected backend owns its own build; the workspace scripts are the only\n // thing that knows how to run it.\n const backend = findBackendApp(manifest);\n if (!backend && source === \"synthesized\") {\n console.log(chalk.dim(\"No rebase.json found — building workspace packages.\\n\"));\n await runWorkspaceBuilds(projectRoot);\n return;\n }\n\n // `--output` names one bundle directory, resolved from where it was typed.\n // It is refused for a build that produces several bundles rather than\n // handed to each: every bundle build empties its directory first, so the\n // last app built deleted the others' and the build still reported success.\n const output = args[\"--output\"] ? path.resolve(process.cwd(), args[\"--output\"]) : undefined;\n const bundled = targets.filter(({ app }) =>\n (app.type === \"backend\" && app.runtime !== \"custom\") ||\n (app.type === \"static\" && Boolean(app.build) && Boolean(app.output)));\n if (output && bundled.length > 1) {\n throw new UsageError(\n `--output names one bundle directory, and this build produces ${bundled.length}: ` +\n `${bundled.map(t => t.name).join(\", \")}. Build one app into it: ` +\n `rebase build ${bundled[0].name} --output ${args[\"--output\"]}`\n );\n }\n\n console.log(`${chalk.bold(\"Rebase\")} — building ${targets.length} app(s)\\n`);\n\n // Each static app is built once per run, whichever consumer gets to it\n // first: folding into the backend bundle, or its own static bundle.\n const builtApps = new Set<string>();\n\n for (const { name, app } of targets) {\n console.log(chalk.cyan(`▸ ${name}`) + chalk.dim(` (${app.type})`));\n\n if (app.type === \"backend\" && app.runtime === \"custom\") {\n // An ejected backend's artifact is an IMAGE, not a bundle. Building\n // one anyway produced a `dist-bundle/` the project never deploys,\n // which is worse than doing nothing: it looks like the thing that\n // ships. The workspace's own `build` script compiles this app, and\n // the Dockerfile turns it into the image.\n console.log(chalk.dim(\" custom runtime — this project builds its own image, not a bundle\"));\n for (const line of dockerBuildHint(projectRoot, name, app)) console.log(line);\n console.log(\"\");\n continue;\n }\n\n if (app.type === \"backend\") {\n // Derived per backend app, because each has its own config\n // directory. Issues are fatal here rather than reported: a bundle\n // whose manifest is missing a bucket the code declares would deploy\n // into a tenant with nothing provisioned for it, and the first sign\n // would be uploads failing in production.\n const { graph: resourceGraph, issues } = await deriveResourceGraph(deriveOptionsFor(projectRoot, app));\n if (issues.length > 0) {\n console.error(chalk.red(`\\n ✗ ${issues.length} problem(s) in the declared resources:\\n`));\n for (const issue of issues) console.error(` ${chalk.bold(issue.path)} ${issue.message}`);\n console.error(\"\");\n process.exitCode = 1;\n return;\n }\n // Written alongside the bundle so the repository records what this\n // project needs. `rebase resources --check` is what keeps it honest.\n // Committed, so a change to it is said: the first build of a\n // scaffold otherwise left it untracked with no word on what it is.\n if (writeResourceGraphFile(projectRoot, resourceGraph).changed) {\n console.log(chalk.dim(` ${RESOURCE_GRAPH_FILENAME} updated — commit it: it records what this project needs from a host`));\n }\n\n /* The framework pins, read before the build and reported after it.\n Ranges no single version satisfies are refused by `buildBundle`\n itself, before it builds anything, for every command that builds\n a bundle. */\n const drift = detectFrameworkDepDrift(projectRoot, cliVersion());\n\n const result = await buildBundle({\n projectRoot,\n appName: name,\n app,\n outDir: output,\n runtimeRange: manifest.rebase,\n resources: resourceGraph,\n skipTypeCheck: args[\"--skip-type-check\"],\n skipSchema: args[\"--skip-schema\"],\n vendor: args[\"--no-vendor\"] ? false : (args[\"--vendor\"] ? true : undefined)\n });\n const rel = path.relative(projectRoot, result.outDir);\n console.log(chalk.green(` ✓ bundle → ${rel}/`));\n // A headless build has no schema version — the API is introspected\n // from the live database at boot — and interpolating it anyway left\n // the summary ending in a dangling `schema `, which reads as a value\n // that failed to render rather than one that does not exist.\n const schemaVersion = result.manifest.schemaVersion;\n console.log(chalk.dim(\n ` ${result.collectionCount} collection(s)${schemaVersion ? `, schema ${schemaVersion}` : \"\"}`\n ));\n /* Say what the bundle's cold start will be, at the one moment\n anyone is listening.\n\n A vendored bundle starts in about five seconds; one that installs\n at boot takes forty to sixty, on EVERY pod start — an eviction, a\n node failure, an OOM, a runtime rollout. That is not a build\n detail, it is what each of those events costs in downtime, and it\n is invisible until an incident unless it is said here. */\n if (result.vendor.vendored) {\n console.log(chalk.dim(` dependencies installed into the bundle (${result.vendor.target?.os}/${result.vendor.target?.cpu})`));\n if ((result.vendor.bytes ?? 0) > VENDOR_SIZE_WARN_BYTES) {\n const mb = Math.round((result.vendor.bytes ?? 0) / (1024 * 1024));\n /* The limit is on the *compressed* upload and this is the\n tree on disk, so a number above 100 does not mean the\n upload fails — but \"201 MB, close to the 100 MB limit\"\n reads as nonsense and got ignored for exactly that\n reason. Say which quantity is which. */\n console.log(chalk.yellow(\n ` ⚠ the installed tree is ${mb} MB on disk — enough to risk the control plane's 100 MB ` +\n \"limit on the compressed upload\"));\n console.log(chalk.dim(\" Shrink the declared dependencies, or rebuild with --no-vendor.\"));\n }\n } else if (Object.keys(result.manifest.deps.declared).length === 0) {\n // Nothing to install is not a degraded state — this bundle\n // already starts as fast as a vendored one. Warning here would\n // train people to ignore the warning that matters.\n console.log(chalk.dim(\" no dependencies to install — nothing to bundle\"));\n } else {\n console.log(chalk.yellow(` ⚠ dependencies not bundled: ${result.vendor.skipped}`));\n console.log(chalk.dim(\" They install on every pod start instead, which is ~40-60s of cold start.\"));\n }\n\n if (result.manifest.hooks.native) {\n const names = (result.manifest.hooks.nativeModules ?? []).map(m => m.name).join(\", \");\n console.log(chalk.yellow(` ⚠ native dependencies detected: ${names}`));\n console.log(chalk.dim(\" These cannot run on the managed runtime. See `rebase doctor`.\"));\n }\n\n /* Framework pins older than this CLI.\n\n Warned here because this is the only moment anyone can be told.\n Locally every `@rebasepro/*` resolves through pnpm's workspace and\n `link:` overrides to the checkout, so the version strings in\n package.json are never exercised — the project runs fine on a\n developer's machine while declaring something years old. Those\n strings are first honoured when the runtime npm-installs them in\n the cloud, and by then the symptom is a tenant that boots and then\n misbehaves against its database.\n\n A warning rather than a hard failure: the CLI cannot know that a\n newer package has actually been published, and refusing to build\n over a guess would be worse than saying it out loud. (`drift` was\n read before the build, above.) */\n if (drift.behind.length > 0) {\n console.log(chalk.yellow(` ⚠ framework dependencies older than this CLI (${cliVersion()}):`));\n for (const dep of drift.behind) {\n console.log(chalk.dim(` ${dep.name}@${dep.range} (${dep.file})`));\n }\n console.log(chalk.dim(\" The image supplies the server, but your bundle supplies the database\"));\n console.log(chalk.dim(\" driver — a newer runtime does not update it.\"));\n console.log(chalk.dim(` Run \\`${upgradeToThisCli()}\\`, then rebuild.`));\n } else if (drift.disagreeing.length > 0) {\n console.log(chalk.yellow(` ⚠ mixed @rebasepro versions declared: ${drift.disagreeing.join(\", \")}`));\n console.log(chalk.dim(\" These are published together and expect to run together.\"));\n console.log(chalk.dim(` Run \\`${upgradeToThisCli()}\\` to pin them alike, then rebuild.`));\n }\n\n /* Fold the project's static apps into the backend bundle, so ONE\n runtime serves the site at `/`, the admin at `/admin` and the API\n at `/api` — the shape the scaffolded template produces and the\n shape a custom container already had.\n\n Without this, moving a project to the managed runtime silently\n removed its website: the API answered perfectly and every page\n 404'd, because the managed pod runs the backend bundle and nothing\n else. Parity with the container being replaced is the only honest\n baseline for calling managed a drop-in.\n\n `--no-static` opts out, for a project that publishes its frontend\n somewhere else and does not want the assets in its bundle. */\n if (!args[\"--no-static\"]) {\n const folded = await foldFrontendIntoBundle({\n projectRoot,\n manifest,\n bundleDir: result.outDir,\n skipBuild: args[\"--skip-static-build\"] === true,\n builtApps,\n log: (m) => console.log(m)\n }).catch((err: unknown) => {\n console.error(chalk.red(` ✗ ${err instanceof Error ? err.message : String(err)}`));\n process.exit(1);\n });\n for (const outcome of folded ?? []) {\n console.log(\n chalk.green(` ✓ ${outcome.appName} folded in`) +\n chalk.dim(` (${outcome.fileCount} file(s) → served at ${formatAppAddress(outcome)})`)\n );\n }\n }\n } else if (app.type === \"static\") {\n await buildAssetApp(projectRoot, name, app, manifest.rebase, output, { builtApps }).catch((err: unknown) => {\n console.error(chalk.red(` ✗ ${err instanceof Error ? err.message : String(err)}`));\n process.exit(1);\n });\n }\n\n console.log(\"\");\n }\n\n console.log(chalk.green(\"✓ Build complete.\"));\n}\n\n/**\n * Build a static app and package it into a static bundle.\n *\n * Runs the app's own build command, checks it produced the declared output, then\n * packages that output into a `static`-kind bundle — the same deployable shape as\n * a backend bundle, so a frontend or admin app deploys through the identical\n * path and runs on the identical image, just serving files instead of an API.\n *\n * Throws when the build fails or produces nothing usable, so the caller answers\n * in its own way: `rebase build` with a red line, `rebase cloud deploy --json`\n * with its JSON error.\n */\nexport async function buildAssetApp(\n projectRoot: string,\n name: string,\n app: RebaseAppConfig,\n runtimeRange: string,\n outOverride?: string,\n /**\n * `quietStdout`: every line, the build command's included, goes to stderr. See `toolStdio`.\n * `builtApps`: the static apps already built in this run (see `FoldOptions.builtApps`).\n */\n options: { quietStdout?: boolean; builtApps?: Set<string> } = {}\n): Promise<string | undefined> {\n const asset = app as RebaseStaticAppConfig;\n // The path part is what the app is built for and mounted at; the hostname,\n // when `path` names one, only travels in the bundle.\n const address = staticAppAddress(name, asset);\n const basePath = address.path;\n const say = (line: string): void => {\n if (options.quietStdout) console.error(line);\n else console.log(line);\n };\n\n if (!asset.build) {\n say(chalk.dim(\" no build command declared — skipping\"));\n return undefined;\n }\n\n if (options.builtApps?.has(name)) {\n say(chalk.dim(\" built once already in this run — packaging that output\"));\n } else {\n try {\n await execa(asset.build, {\n cwd: projectRoot,\n stdio: toolStdio(options.quietStdout),\n shell: true,\n env: staticBuildEnv(basePath, name)\n });\n } catch {\n throw new Error(`build command failed for \"${name}\"`);\n }\n options.builtApps?.add(name);\n }\n\n if (!asset.output) {\n say(chalk.yellow(\" no output directory declared — built, but nothing to bundle\"));\n return undefined;\n }\n\n const outputPath = path.join(projectRoot, asset.output);\n if (!fs.existsSync(outputPath)) {\n // The command exited 0 but produced nothing where the manifest says it\n // should. Bundling that would ship an empty site.\n throw new Error(`declared output \"${asset.output}\" does not exist after building`);\n }\n\n // The assets were built for `basePath`; refusing here is the difference\n // between a build error and a blank page nobody can diagnose.\n const indexHtml = path.join(outputPath, \"index.html\");\n if (fs.existsSync(indexHtml)) {\n assertBuiltForPath(fs.readFileSync(indexHtml, \"utf8\"), basePath, name);\n }\n\n // Per-app bundle directory, so a project's several static apps do not clobber\n // one another or the backend's `dist-bundle`.\n const outDir = outOverride\n ? path.resolve(process.cwd(), outOverride)\n : path.join(projectRoot, `dist-bundle-${name}`);\n const result = buildStaticBundle({\n projectRoot,\n appName: name,\n assetsDir: outputPath,\n outDir,\n runtimeRange,\n path: basePath,\n host: address.host,\n spa: asset.spa ?? true,\n cms: asset.cms\n });\n const rel = path.relative(projectRoot, result.outDir);\n say(\n chalk.green(` ✓ static bundle → ${rel}/`) +\n chalk.dim(` (${result.fileCount} file(s) → served at ${formatAppAddress(address)})`)\n );\n return result.outDir;\n}\n\n/**\n * The `rebase upgrade` line the drift warnings print.\n *\n * Aimed at this CLI's own version, because that is what the warning measured\n * against: \"older than this CLI\" is answered by moving to exactly this CLI, not\n * to whatever `latest` happens to be — which, on a canary, is older still.\n */\nfunction upgradeToThisCli(): string {\n const version = cliVersion();\n return version === \"unknown\" ? \"rebase upgrade\" : `rebase upgrade --to ${version}`;\n}\n\n/** The pre-manifest behaviour: build every workspace package. */\nasync function runWorkspaceBuilds(projectRoot: string): Promise<void> {\n const pm = detectPackageManager(projectRoot);\n const cmds = getPMCommands(pm);\n const buildCmd = cmds.runAll(\"build\");\n\n console.log(`${chalk.bold(\"Rebase\")} — Building all workspaces with ${chalk.cyan(pm)}...\\n`);\n\n try {\n await execa(buildCmd[0], buildCmd.slice(1), {\n cwd: projectRoot,\n stdio: \"inherit\"\n });\n } catch {\n console.error(chalk.red(\"\\n✗ Build failed.\"));\n process.exit(1);\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { g as resolveTsx, h as resolvePluginCliScript, l as getActiveBackendPlugin, m as resolveLocalBin } from "./project-Wp2zoyeN.js";
1
+ import { g as resolveTsx, h as resolvePluginCliScript, l as getActiveBackendPlugin, m as resolveLocalBin } from "./project-g4K6kV1t.js";
2
2
  import { n as cliVersion } from "./version-Buyyo1ut.js";
3
- import { g as resolveBackendPaths, u as compareMountOrder } from "./manifest-DRp0UVTj.js";
3
+ import { g as resolveBackendPaths, u as compareMountOrder } from "./manifest-nvPdLlJY.js";
4
4
  import { n as summarisePortability, t as analyseFunctionsDirectory } from "./function-portability-BIvlvR9q.js";
5
5
  import chalk from "chalk";
6
6
  import fs from "fs";
@@ -1603,4 +1603,4 @@ function resolveServerVersion(projectRoot) {
1603
1603
  //#endregion
1604
1604
  export { foldStaticIntoBundle as _, VENDOR_TARGET_OS as a, toolStdio as b, collectDeclaredDependencies as c, describeDepConflicts as d, detectDeclaredDepConflicts as f, findUnusedServerEntry as g, detectStorageAuthorize as h, VENDOR_TARGET_CPU as i, commentSpans as l, detectNativeDependencies as m, VENDOR_SIZE_MAX_BYTES as n, buildBundle as o, detectFrameworkDepDrift as p, VENDOR_SIZE_WARN_BYTES as r, buildStaticBundle as s, DEFAULT_BUNDLE_DIR as t, composeBundleManifest as u, normalizeEsmSpecifiers as v, vendorDependencies as y };
1605
1605
 
1606
- //# sourceMappingURL=bundle-DtCCCr4w.js.map
1606
+ //# sourceMappingURL=bundle-DlqkDYSe.js.map