@rebasepro/cli 0.23.0 → 0.24.1-canary.g56af4a4

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 (158) hide show
  1. package/README.md +19 -3
  2. package/bin/rebase.js +4 -1
  3. package/dist/agent-setup-B31F00DC.js +324 -0
  4. package/dist/agent-setup-B31F00DC.js.map +1 -0
  5. package/dist/api-keys-BPBi5nOF.js +524 -0
  6. package/dist/api-keys-BPBi5nOF.js.map +1 -0
  7. package/dist/apps-CPXNElX4.js +256 -0
  8. package/dist/apps-CPXNElX4.js.map +1 -0
  9. package/dist/args-BnmsEXvu.js +109 -0
  10. package/dist/args-BnmsEXvu.js.map +1 -0
  11. package/dist/atlas-dev-database-DTMuEScS.js +62 -0
  12. package/dist/atlas-dev-database-DTMuEScS.js.map +1 -0
  13. package/dist/auth-DvY94ZuL.js +395 -0
  14. package/dist/auth-DvY94ZuL.js.map +1 -0
  15. package/dist/branch-pointer-DIhKbQLp.js +2 -0
  16. package/dist/build-CFwUx-Ff.js +336 -0
  17. package/dist/build-CFwUx-Ff.js.map +1 -0
  18. package/dist/bundle-BQhP_xiA.js +1617 -0
  19. package/dist/bundle-BQhP_xiA.js.map +1 -0
  20. package/dist/bundle.d.ts +6 -2
  21. package/dist/cli.d.ts +23 -2
  22. package/dist/cloud-CkTr-yt0.js +9640 -0
  23. package/dist/cloud-CkTr-yt0.js.map +1 -0
  24. package/dist/collection-drift-BKj_BoMq.js +106 -0
  25. package/dist/collection-drift-BKj_BoMq.js.map +1 -0
  26. package/dist/commands/__test_support__/parser-specs.d.ts +13 -0
  27. package/dist/commands/agent-setup.d.ts +116 -0
  28. package/dist/commands/api-keys.d.ts +86 -23
  29. package/dist/commands/apps.d.ts +17 -0
  30. package/dist/commands/auth.d.ts +7 -0
  31. package/dist/commands/build.d.ts +5 -1
  32. package/dist/commands/cloud/auth.d.ts +4 -3
  33. package/dist/commands/cloud/bundle-deploy.d.ts +45 -0
  34. package/dist/commands/cloud/context.d.ts +44 -5
  35. package/dist/commands/cloud/cron.d.ts +53 -0
  36. package/dist/commands/cloud/debug.d.ts +134 -0
  37. package/dist/commands/cloud/index.d.ts +89 -12
  38. package/dist/commands/cloud/token-capabilities.d.ts +76 -0
  39. package/dist/commands/cloud/tokens.d.ts +23 -0
  40. package/dist/commands/db.d.ts +52 -25
  41. package/dist/commands/dev.d.ts +181 -7
  42. package/dist/commands/doctor.d.ts +5 -0
  43. package/dist/commands/generate_sdk.d.ts +29 -2
  44. package/dist/commands/init.d.ts +57 -14
  45. package/dist/commands/schema.d.ts +6 -0
  46. package/dist/commands/skills.d.ts +126 -7
  47. package/dist/commands/start.d.ts +29 -0
  48. package/dist/commands/storage.d.ts +46 -0
  49. package/dist/consent-BWHaYx5p.js +76 -0
  50. package/dist/consent-BWHaYx5p.js.map +1 -0
  51. package/dist/context-BqhRydBg.js +1234 -0
  52. package/dist/context-BqhRydBg.js.map +1 -0
  53. package/dist/daemon-DBn-shxX.js +2 -0
  54. package/dist/{daemon-entry-LTFKtpHy.js → daemon-entry-Da-D3rmH.js} +3 -4
  55. package/dist/daemon-entry-Da-D3rmH.js.map +1 -0
  56. package/dist/db-CMpBK3sv.js +1252 -0
  57. package/dist/db-CMpBK3sv.js.map +1 -0
  58. package/dist/derive-RPIsAVO4.js +474 -0
  59. package/dist/derive-RPIsAVO4.js.map +1 -0
  60. package/dist/dev-C9P5Yp9k.js +1593 -0
  61. package/dist/dev-C9P5Yp9k.js.map +1 -0
  62. package/dist/dev-db/atlas-dev-database.d.ts +32 -0
  63. package/dist/dev-db/daemon-entry.d.ts +13 -0
  64. package/dist/dev-db/daemon.d.ts +10 -0
  65. package/dist/dev-db/prepare.d.ts +10 -0
  66. package/dist/dev-preflight-N1evJL3S.js +2 -0
  67. package/dist/doctor-DYs-NqFI.js +771 -0
  68. package/dist/doctor-DYs-NqFI.js.map +1 -0
  69. package/dist/eject-BT6t37D0.js +335 -0
  70. package/dist/eject-BT6t37D0.js.map +1 -0
  71. package/dist/fold-static-C1EtHlfV.js +201 -0
  72. package/dist/fold-static-C1EtHlfV.js.map +1 -0
  73. package/dist/fold-static.d.ts +26 -3
  74. package/dist/function-portability-BIvlvR9q.js +265 -0
  75. package/dist/function-portability-BIvlvR9q.js.map +1 -0
  76. package/dist/generate_sdk-UV635zSe.js +477 -0
  77. package/dist/generate_sdk-UV635zSe.js.map +1 -0
  78. package/dist/index.es.js +189 -22095
  79. package/dist/index.es.js.map +1 -1
  80. package/dist/init-fXeBcxuN.js +1042 -0
  81. package/dist/init-fXeBcxuN.js.map +1 -0
  82. package/dist/manifest-DzlC60WX.js +871 -0
  83. package/dist/manifest-DzlC60WX.js.map +1 -0
  84. package/dist/manifest.d.ts +41 -1
  85. package/dist/normalize-imports-CmVdE9iZ.js +100 -0
  86. package/dist/normalize-imports-CmVdE9iZ.js.map +1 -0
  87. package/dist/package-manager-DSEOwTqM.js +193 -0
  88. package/dist/package-manager-DSEOwTqM.js.map +1 -0
  89. package/dist/path-flags-DUBuI2i1.js +77 -0
  90. package/dist/path-flags-DUBuI2i1.js.map +1 -0
  91. package/dist/precompress.d.ts +17 -0
  92. package/dist/prepare-Btn9Ewbn.js +1052 -0
  93. package/dist/prepare-Btn9Ewbn.js.map +1 -0
  94. package/dist/{project-3WCbrrfW.js → project-Wp2zoyeN.js} +34 -184
  95. package/dist/project-Wp2zoyeN.js.map +1 -0
  96. package/dist/resolve-CJLkfFV0.js +2 -0
  97. package/dist/resources-DT1COn_6.js +161 -0
  98. package/dist/resources-DT1COn_6.js.map +1 -0
  99. package/dist/schema-BDBWvCHu.js +125 -0
  100. package/dist/schema-BDBWvCHu.js.map +1 -0
  101. package/dist/skills-DTFibT1m.js +642 -0
  102. package/dist/skills-DTFibT1m.js.map +1 -0
  103. package/dist/start-rU2e3Kp5.js +228 -0
  104. package/dist/start-rU2e3Kp5.js.map +1 -0
  105. package/dist/{state-C59Elrnt.js → state-Do7ZJYkF.js} +49 -4
  106. package/dist/state-Do7ZJYkF.js.map +1 -0
  107. package/dist/status-BR9oyi-y.js +351 -0
  108. package/dist/status-BR9oyi-y.js.map +1 -0
  109. package/dist/storage-DyvrSTH3.js +303 -0
  110. package/dist/storage-DyvrSTH3.js.map +1 -0
  111. package/dist/telemetry-CAWNCugs.js +338 -0
  112. package/dist/telemetry-CAWNCugs.js.map +1 -0
  113. package/dist/telemetry-DbLqGIBW.js +129 -0
  114. package/dist/telemetry-DbLqGIBW.js.map +1 -0
  115. package/dist/unknown-command-DNwDcX3w.js +98 -0
  116. package/dist/unknown-command-DNwDcX3w.js.map +1 -0
  117. package/dist/upgrade-D-5-Od96.js +1265 -0
  118. package/dist/upgrade-D-5-Od96.js.map +1 -0
  119. package/dist/upgrade.d.ts +14 -2
  120. package/dist/utils/path-flags.d.ts +18 -0
  121. package/dist/utils/project.d.ts +16 -0
  122. package/dist/version-Buyyo1ut.js +58 -0
  123. package/dist/version-Buyyo1ut.js.map +1 -0
  124. package/package.json +7 -7
  125. package/templates/eject/backend/src/env.ts +1 -1
  126. package/templates/eject/backend/src/index.ts +23 -2
  127. package/templates/overlays/baas/ai-instructions.md +1 -1
  128. package/templates/overlays/baas/config/storage.ts +5 -3
  129. package/templates/template/.cursorrules +1 -1
  130. package/templates/template/.env.example +10 -6
  131. package/templates/template/.github/copilot-instructions.md +1 -1
  132. package/templates/template/.mcp.json +2 -2
  133. package/templates/template/.windsurfrules +1 -1
  134. package/templates/template/AGENTS.md +1 -1
  135. package/templates/template/CLAUDE.md +1 -1
  136. package/templates/template/README.md +11 -12
  137. package/templates/template/ai-instructions.md +5 -4
  138. package/templates/template/backend/functions/hello.ts +8 -0
  139. package/templates/template/backend/package.json +1 -1
  140. package/templates/template/config/storage.ts +5 -3
  141. package/templates/template/docker-compose.yml +6 -6
  142. package/templates/template/frontend/vite.config.ts +11 -3
  143. package/templates/template/gitignore +6 -1
  144. package/templates/template/package.json +4 -3
  145. package/templates/template/scripts/example.ts +6 -4
  146. package/dist/branch-pointer-dBiClJ0p.js +0 -111
  147. package/dist/branch-pointer-dBiClJ0p.js.map +0 -1
  148. package/dist/constraints-DKGbNfUW.js +0 -48
  149. package/dist/constraints-DKGbNfUW.js.map +0 -1
  150. package/dist/daemon-DR9Tk0La.js +0 -355
  151. package/dist/daemon-DR9Tk0La.js.map +0 -1
  152. package/dist/daemon-entry-LTFKtpHy.js.map +0 -1
  153. package/dist/dev-preflight-CNLl4rdo.js +0 -367
  154. package/dist/dev-preflight-CNLl4rdo.js.map +0 -1
  155. package/dist/project-3WCbrrfW.js.map +0 -1
  156. package/dist/resolve-BAeRUBhg.js +0 -74
  157. package/dist/resolve-BAeRUBhg.js.map +0 -1
  158. package/dist/state-C59Elrnt.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade-D-5-Od96.js","names":[],"sources":["../src/upgrade.ts","../src/commands/upgrade.ts"],"sourcesContent":["/**\n * Moving a project's `@rebasepro/*` pins to one release.\n *\n * Every `@rebasepro/*` package ships at one version, and a project declares them\n * in several `package.json` files — the root, `backend/`, `frontend/`,\n * `config/`, and whatever else the repository holds. Bumping them by hand means\n * finding every one, keeping each range's `^` or `~`, and noticing the override\n * that quietly wins over all of them. `rebase upgrade` is that job, done the same\n * way every time; the control plane runs it too, when it rebuilds a managed\n * project on a newer release.\n *\n * Everything here is file work — git is asked only which files are the\n * project's — so it can be tested against a temporary directory: which files\n * are read, which specs move, the rewrite itself, and what overrides say. The\n * command in `commands/upgrade.ts` adds the registry lookup, the install and the\n * printing.\n *\n * ## The rewrite is textual\n *\n * A `package.json` is authored. Parsing it and writing `JSON.stringify` back\n * reformats the file, reorders nothing but reindents everything, and drops a\n * trailing newline or a two-space indent somebody chose — a one-line version\n * bump that arrives as a whole-file diff. So the file is scanned for the exact\n * byte range of each value, only those bytes are replaced, and the result is\n * parsed again and compared against what was intended. A file whose rewrite\n * does not parse back to exactly the intended values is not written.\n */\nimport fs from \"fs\";\nimport path from \"path\";\nimport { execFileSync } from \"child_process\";\nimport { isDeepStrictEqual } from \"util\";\nimport { getPMCommands } from \"./utils/package-manager\";\n\n/** The dependency blocks a pin is moved in. `peerDependencies` is not one. */\nexport const PIN_FIELDS = [\"dependencies\", \"devDependencies\", \"optionalDependencies\"] as const;\nexport type PinField = typeof PIN_FIELDS[number];\n\n/** Every framework package lives under this scope. */\nexport const FRAMEWORK_SCOPE = \"@rebasepro/\";\n\n/** The package whose published versions stand for the release as a whole. */\nexport const RELEASE_PACKAGE = \"@rebasepro/cli\";\n\n/** `MAJOR.MINOR.PATCH`, with an optional prerelease and build, and nothing else. */\nconst SEMVER =\n /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$/;\n\n/** Whether `value` is one exact version — `0.21.0`, `0.21.1-canary.g8c5a265`. */\nexport function isExactVersion(value: string): boolean {\n return SEMVER.test(value);\n}\n\n/** An error that carries the `--json` envelope's code and a remedy. */\nexport class UpgradeError extends Error {\n constructor(message: string, readonly code: string, readonly hint?: string) {\n super(message);\n this.name = \"UpgradeError\";\n }\n}\n\n/* ─── which specs move ─────────────────────────────────────────────────────── */\n\nexport type SpecClass =\n /** A plain version, optionally `^` or `~`: moved, keeping the prefix. */\n | { kind: \"movable\"; prefix: \"\" | \"^\" | \"~\"; version: string }\n /** A path on this machine. As a pin it is left alone; as an override it wins over every pin. */\n | { kind: \"local\"; protocol: \"link:\" | \"file:\" | \"portal:\" }\n /** A pnpm `catalog:` reference: the version is in pnpm-workspace.yaml's catalog, and moves there. */\n | { kind: \"catalog\"; catalog: string }\n /** Anything else, with the reason it is left alone. */\n | { kind: \"other\"; reason: string };\n\n/**\n * What a dependency spec is, as far as moving it goes.\n *\n * Only a plain version is moved, because only a plain version has an obvious\n * answer: `^0.19.1` becomes `^0.21.0`. A `>=` floor, a `||` union or a partial\n * `^0.19` could each be rewritten several ways, and a tag or a workspace link\n * already means something other than \"this release\" — so each is reported with\n * its reason and left as written.\n */\nexport function classifySpec(spec: string): SpecClass {\n const movable = /^([\\^~]?)(.+)$/.exec(spec);\n if (movable && isExactVersion(movable[2])) {\n return { kind: \"movable\", prefix: movable[1] as \"\" | \"^\" | \"~\", version: movable[2] };\n }\n for (const protocol of [\"link:\", \"file:\", \"portal:\"] as const) {\n if (spec.startsWith(protocol)) return { kind: \"local\", protocol };\n }\n const catalog = /^catalog:(.*)$/.exec(spec.trim());\n if (catalog) return { kind: \"catalog\", catalog: catalog[1].trim() || \"default\" };\n return { kind: \"other\", reason: otherReason(spec) };\n}\n\n/** Why a spec that does not move is left alone, as the report says it. */\nfunction leftAloneReason(cls: Exclude<SpecClass, { kind: \"movable\" }>): string {\n if (cls.kind === \"local\") {\n return `a local ${cls.protocol} path, which points at a checkout on this machine rather than a release`;\n }\n if (cls.kind === \"catalog\") return \"a catalog: reference inside a catalog, which pnpm does not resolve\";\n return cls.reason;\n}\n\nfunction otherReason(spec: string): string {\n const trimmed = spec.trim();\n if (trimmed.startsWith(\"workspace:\")) return \"a workspace: link, resolved inside this repository rather than from the registry\";\n if (trimmed.startsWith(\"npm:\")) return \"an npm: alias; move the aliased version by hand\";\n if (/^(git\\+|git:|github:|gitlab:|bitbucket:|git@)/.test(trimmed) || /^https?:\\/\\//.test(trimmed)) {\n return \"a git or URL dependency, not a registry version\";\n }\n if (trimmed === \"\" || trimmed === \"*\" || /^[xX]$/.test(trimmed)) return \"a wildcard, which already takes whatever the registry has\";\n if (trimmed.includes(\"||\")) return \"a union of ranges, with no single version to move\";\n if (/^[<>=]/.test(trimmed) || /\\s-\\s/.test(trimmed)) return \"a comparator range, with no single version to move\";\n if (/^[\\^~]?v?\\d/.test(trimmed)) return \"not a plain MAJOR.MINOR.PATCH version\";\n return \"a dist-tag, not a version\";\n}\n\n/**\n * The `@rebasepro/*` package an override key targets, or null.\n *\n * pnpm and npm key an override by name, optionally narrowed: `@rebasepro/x@<1`,\n * `parent>@rebasepro/x`; yarn's `resolutions` by a path, `**\\/@rebasepro/x`. The\n * target is the last segment either way.\n */\nexport function overrideTarget(key: string): string | null {\n const match = /(?:^|[/>])(@rebasepro\\/[^/@>\\s]+)(?:@[^/>]*)?$/.exec(key);\n return match ? match[1] : null;\n}\n\n/* ─── finding the files ────────────────────────────────────────────────────── */\n\nexport interface ProjectFiles {\n /** Absolute paths, in a stable order. */\n packageJsons: string[];\n workspaceYamls: string[];\n}\n\n/**\n * Directories the walk never enters: installed packages, build output (`dist`,\n * `dist-bundle`, `dist-bundle-admin`, …) and anything hidden (`.git`,\n * `.rebase`, an editor's worktrees). None of them hold a manifest anybody\n * authored for this project, and `dist-bundle/package.json` in particular is a\n * generated copy that `rebase build` rewrites anyway. They are skipped whether\n * or not git ignores them.\n */\nfunction skipDirectory(name: string): boolean {\n return name === \"node_modules\" || name.startsWith(\"dist\") || name.startsWith(\".\");\n}\n\n/** `git -C <cwd> …`, returning stdout. Throws when git is missing or refuses. */\nexport type GitRunner = (cwd: string, args: string[]) => string;\n\nconst runGit: GitRunner = (cwd, args) => execFileSync(\"git\", [\"-C\", cwd, ...args], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n // `ls-files` on a large monorepo is megabytes; the default 1 MiB buffer\n // would kill it and silently fall back to the walk.\n maxBuffer: 256 * 1024 * 1024\n});\n\n/**\n * The files git counts as part of the project — tracked, or untracked and not\n * ignored — relative to `projectRoot`, POSIX. Null when git has no say: no git,\n * no repository, or a repository that lists nothing under the project root.\n *\n * Listing nothing means the repository ignores the project as a whole: a copy\n * of it under a gitignored scratch directory, say. Running the upgrade in that\n * copy is asking for the copy to move, and the repository's rules would leave\n * nothing in it to move. Asked with `git ls-files` rather than\n * `git check-ignore`, which answers differently across git versions for a\n * directory and for a negated pattern.\n */\nfunction gitProjectFiles(projectRoot: string, git: GitRunner): Set<string> | null {\n let listed: string;\n try {\n listed = git(projectRoot, [\"ls-files\", \"-z\", \"--cached\", \"--others\", \"--exclude-standard\"]);\n } catch {\n return null;\n }\n const files = new Set(listed.split(\"\\0\").filter(Boolean));\n return files.size > 0 ? files : null;\n}\n\n/**\n * Every `package.json` and `pnpm-workspace.yaml` under the project root that\n * belongs to the project.\n *\n * In a git repository that means what git lists: a gitignored build context,\n * scratch copy or vendored package is not the project's, and rewriting it\n * would change files nobody committed. The walk enters only directories that\n * hold a listed file, so an ignored tree is not read at all. Outside a\n * repository every directory is walked. {@link skipDirectory} applies either\n * way.\n */\nexport function discoverProjectFiles(projectRoot: string, git: GitRunner = runGit): ProjectFiles {\n const found: ProjectFiles = { packageJsons: [], workspaceYamls: [] };\n const listed = gitProjectFiles(projectRoot, git);\n /** Every directory a listed file sits in, at any depth. */\n const listedDirectories = new Set<string>();\n for (const file of listed ?? []) {\n for (let dir = path.posix.dirname(file); dir !== \".\" && !listedDirectories.has(dir); dir = path.posix.dirname(dir)) {\n listedDirectories.add(dir);\n }\n }\n\n const walk = (dir: string, relativeDir: string): void => {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n entries.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n const relative = relativeDir ? `${relativeDir}/${entry.name}` : entry.name;\n // `isDirectory()` is false for a symlink, so a linked workspace\n // package is not walked twice and a cycle cannot form.\n if (entry.isDirectory()) {\n if (!skipDirectory(entry.name) && (!listed || listedDirectories.has(relative))) walk(full, relative);\n } else if (entry.isFile() && (!listed || listed.has(relative))) {\n if (entry.name === \"package.json\") found.packageJsons.push(full);\n else if (entry.name === \"pnpm-workspace.yaml\") found.workspaceYamls.push(full);\n }\n }\n };\n walk(projectRoot, \"\");\n return found;\n}\n\n/* ─── the result ───────────────────────────────────────────────────────────── */\n\n/** Where a catalog pin sits: `catalog`, or `catalogs.<name>` for a named one. */\nexport type CatalogField = \"catalog\" | `catalogs.${string}`;\n\nexport interface ChangedPin {\n /** Relative to the project root, POSIX separators. */\n file: string;\n name: string;\n field: PinField | CatalogField;\n from: string;\n to: string;\n}\n\nexport interface SkippedSpec {\n file: string;\n name: string;\n /** A dependency block, or the override block the entry sits in. */\n field: string;\n spec: string;\n reason: string;\n}\n\nexport type OverrideAction = \"bumped\" | \"kept-local\" | \"removed-local\";\n\nexport interface OverrideFinding {\n file: string;\n /** The override key as written — `@rebasepro/types`, or a narrowed one. */\n name: string;\n spec: string;\n action: OverrideAction;\n /** The new value, for a bumped override. */\n to?: string;\n}\n\nexport interface UnreadableFile {\n file: string;\n reason: string;\n}\n\nexport interface UpgradePlan {\n target: string;\n changed: ChangedPin[];\n skipped: SkippedSpec[];\n overrides: OverrideFinding[];\n unreadable: UnreadableFile[];\n /** The files whose content changes, with the new content. */\n writes: Array<{ file: string; absolute: string; content: string }>;\n /** Pins, overrides and catalog entries that were already on the target. */\n unchanged: number;\n}\n\n/**\n * The `catalog:` references a plan met, and the catalog entries it found.\n *\n * A reference names no version, so it is not a pin to move: the catalog entry\n * it resolves to is. But the catalog may not be anywhere this looked — a\n * project inside a larger workspace keeps it above the project root — and a\n * reference to an entry nobody moved must be reported, not passed over.\n */\ninterface CatalogLedger {\n refs: Array<{ file: string; name: string; field: string; spec: string; catalog: string; pkg: string }>;\n /** `catalogKey(catalog, package)` for every framework entry of every catalog read. */\n defined: Set<string>;\n}\n\nfunction catalogKey(catalog: string, pkg: string): string {\n return `${catalog}\\u0000${pkg}`;\n}\n\nexport interface PlanOptions {\n /** Remove `link:`/`file:` overrides of framework packages instead of reporting them. */\n dropLocalOverrides?: boolean;\n}\n\n/** Project-relative, POSIX. What every file path in the output looks like. */\nfunction relativeTo(projectRoot: string, absolute: string): string {\n return path.relative(projectRoot, absolute).split(path.sep).join(\"/\");\n}\n\n/**\n * Work out every change the upgrade makes, without writing anything.\n *\n * `--dry-run` prints this; a real run writes `writes` and nothing else.\n */\nexport function planUpgrade(projectRoot: string, target: string, options: PlanOptions = {}): UpgradePlan {\n if (!isExactVersion(target)) {\n throw new UpgradeError(`\"${target}\" is not an exact version.`, \"target_invalid\");\n }\n const plan: UpgradePlan = { target, changed: [], skipped: [], overrides: [], unreadable: [], writes: [], unchanged: 0 };\n const ledger: CatalogLedger = { refs: [], defined: new Set() };\n const files = discoverProjectFiles(projectRoot);\n\n for (const absolute of files.packageJsons) {\n const file = relativeTo(projectRoot, absolute);\n const original = fs.readFileSync(absolute, \"utf8\");\n const content = planPackageJson(file, original, target, options, plan, ledger);\n if (content !== null && content !== original) plan.writes.push({ file, absolute, content });\n }\n\n for (const absolute of files.workspaceYamls) {\n const file = relativeTo(projectRoot, absolute);\n const original = fs.readFileSync(absolute, \"utf8\");\n const content = planWorkspaceYaml(file, original, target, options, plan, ledger);\n if (content !== original) plan.writes.push({ file, absolute, content });\n }\n\n for (const ref of ledger.refs) {\n if (ledger.defined.has(catalogKey(ref.catalog, ref.pkg))) continue;\n plan.skipped.push({\n file: ref.file,\n name: ref.name,\n field: ref.field,\n spec: ref.spec,\n reason: `a pnpm catalog: reference, and no catalog under this project defines it — move the version where the \"${ref.catalog}\" catalog is declared`\n });\n }\n\n return plan;\n}\n\n/** Write what the plan changes. Nothing else on disk is touched. */\nexport function applyUpgradePlan(plan: UpgradePlan): void {\n for (const write of plan.writes) fs.writeFileSync(write.absolute, write.content, \"utf8\");\n}\n\n/* ─── package.json ─────────────────────────────────────────────────────────── */\n\n/** Override blocks in a `package.json`, as paths from the root object. */\nconst JSON_OVERRIDE_BLOCKS: ReadonlyArray<readonly string[]> = [[\"pnpm\", \"overrides\"], [\"overrides\"], [\"resolutions\"]];\n\nfunction planPackageJson(\n file: string,\n original: string,\n target: string,\n options: PlanOptions,\n plan: UpgradePlan,\n ledger: CatalogLedger\n): string | null {\n const bom = original.startsWith(\"\") ? \"\" : \"\";\n const text = original.slice(bom.length);\n\n let parsed: unknown;\n let tree: JsonNode;\n try {\n parsed = JSON.parse(text);\n tree = scanJson(text);\n } catch (err) {\n plan.unreadable.push({ file, reason: `not valid JSON: ${err instanceof Error ? err.message : String(err)}` });\n return null;\n }\n if (!isRecord(parsed) || tree.kind !== \"object\") {\n plan.unreadable.push({ file, reason: \"not a JSON object\" });\n return null;\n }\n\n const expected = structuredClone(parsed);\n const edits: TextEdit[] = [];\n /** Override members to remove, as [block path, key]. */\n const removals: Array<[readonly string[], string]> = [];\n\n for (const field of PIN_FIELDS) {\n const block = memberValue(tree, [field]);\n if (block?.kind !== \"object\") continue;\n for (const member of block.members) {\n if (!member.key.startsWith(FRAMEWORK_SCOPE)) continue;\n if (member.value.kind !== \"string\") {\n plan.skipped.push({ file, name: member.key, field, spec: text.slice(member.value.start, member.value.end), reason: \"not a string\" });\n continue;\n }\n const spec = member.value.value;\n const cls = classifySpec(spec);\n if (cls.kind === \"movable\") {\n const to = `${cls.prefix}${target}`;\n if (to === spec) {\n plan.unchanged++;\n continue;\n }\n edits.push({ start: member.value.start, end: member.value.end, replacement: JSON.stringify(to) });\n setPath(expected, [field, member.key], to);\n plan.changed.push({ file, name: member.key, field, from: spec, to });\n } else if (cls.kind === \"catalog\") {\n ledger.refs.push({ file, name: member.key, field, spec, catalog: cls.catalog, pkg: member.key });\n } else {\n plan.skipped.push({ file, name: member.key, field, spec, reason: leftAloneReason(cls) });\n }\n }\n }\n\n for (const blockPath of JSON_OVERRIDE_BLOCKS) {\n const block = memberValue(tree, blockPath);\n if (block?.kind !== \"object\") continue;\n const field = blockPath.join(\".\");\n for (const member of block.members) {\n if (!overrideTarget(member.key)) continue;\n if (member.value.kind !== \"string\") {\n plan.skipped.push({\n file,\n name: member.key,\n field,\n spec: text.slice(member.value.start, member.value.end),\n reason: \"a nested override, which has no single version to move; edit it by hand\"\n });\n continue;\n }\n const spec = member.value.value;\n const cls = classifySpec(spec);\n const pkg = overrideTarget(member.key);\n if (cls.kind === \"movable\") {\n const to = `${cls.prefix}${target}`;\n if (to === spec) {\n plan.unchanged++;\n continue;\n }\n edits.push({ start: member.value.start, end: member.value.end, replacement: JSON.stringify(to) });\n setPath(expected, [...blockPath, member.key], to);\n plan.overrides.push({ file, name: member.key, spec, action: \"bumped\", to });\n } else if (cls.kind === \"catalog\" && pkg) {\n ledger.refs.push({ file, name: member.key, field, spec, catalog: cls.catalog, pkg });\n } else if (cls.kind === \"local\") {\n if (options.dropLocalOverrides) {\n removals.push([blockPath, member.key]);\n deletePath(expected, [...blockPath, member.key]);\n plan.overrides.push({ file, name: member.key, spec, action: \"removed-local\" });\n } else {\n plan.overrides.push({ file, name: member.key, spec, action: \"kept-local\" });\n }\n } else {\n plan.skipped.push({ file, name: member.key, field, spec, reason: leftAloneReason(cls) });\n }\n }\n }\n\n if (edits.length === 0 && removals.length === 0) return original;\n\n let next = applyEdits(text, edits);\n for (const [blockPath, key] of removals) {\n next = removeJsonMember(next, blockPath, key);\n }\n // An override block that only held local links is removed with them, and\n // `pnpm` with it when nothing else was in it — an empty `{}` left behind is\n // a line of diff that says nothing.\n for (const blockPath of JSON_OVERRIDE_BLOCKS) {\n if (!removals.some(([removedFrom]) => removedFrom === blockPath)) continue;\n for (let depth = blockPath.length; depth > 0; depth--) {\n const containerPath = blockPath.slice(0, depth);\n const node = memberValue(scanJson(next), containerPath);\n if (node?.kind !== \"object\" || node.members.length > 0) break;\n next = removeJsonMember(next, containerPath.slice(0, -1), containerPath[containerPath.length - 1]);\n deletePath(expected, containerPath);\n }\n }\n\n // The rewrite is only kept if it says exactly what was meant — every value\n // that was supposed to change, and nothing else.\n let reparsed: unknown;\n try {\n reparsed = JSON.parse(next);\n } catch {\n reparsed = undefined;\n }\n if (!isDeepStrictEqual(reparsed, expected)) {\n throw new UpgradeError(\n `Could not rewrite ${file} without disturbing it; nothing was written.`,\n \"rewrite_failed\",\n \"Move its @rebasepro versions by hand, then run `rebase upgrade` again.\"\n );\n }\n return bom + next;\n}\n\n/* ─── a JSON scanner that keeps byte offsets ───────────────────────────────── */\n\ninterface JsonMember {\n key: string;\n keyStart: number;\n value: JsonNode;\n}\n\ntype JsonNode =\n | { kind: \"object\"; start: number; end: number; members: JsonMember[] }\n | { kind: \"array\"; start: number; end: number }\n | { kind: \"string\"; start: number; end: number; value: string }\n | { kind: \"scalar\"; start: number; end: number };\n\n/**\n * The structure of a JSON document, with where each value starts and ends.\n *\n * `JSON.parse` answers what a file says; this answers where it says it, which is\n * what a rewrite that leaves every other byte alone needs. Throws on anything\n * that is not JSON — callers have already parsed the same text, so that never\n * happens in practice.\n */\nfunction scanJson(text: string): JsonNode {\n let i = 0;\n const WHITESPACE = \" \\t\\n\\r\";\n const skipWhitespace = (): void => {\n while (i < text.length && WHITESPACE.includes(text[i])) i++;\n };\n const unexpected = (): never => {\n throw new Error(`unexpected ${i < text.length ? `\"${text[i]}\"` : \"end of input\"} at offset ${i}`);\n };\n const readString = (): { kind: \"string\"; start: number; end: number; value: string } => {\n const start = i;\n if (text[i] !== \"\\\"\") unexpected();\n i++;\n while (i < text.length && text[i] !== \"\\\"\") i += text[i] === \"\\\\\" ? 2 : 1;\n if (i >= text.length) unexpected();\n i++;\n return { kind: \"string\", start, end: i, value: JSON.parse(text.slice(start, i)) as string };\n };\n const readValue = (): JsonNode => {\n skipWhitespace();\n const start = i;\n if (text[i] === \"{\") {\n i++;\n const members: JsonMember[] = [];\n skipWhitespace();\n if (text[i] === \"}\") {\n i++;\n return { kind: \"object\", start, end: i, members };\n }\n for (;;) {\n skipWhitespace();\n const key = readString();\n skipWhitespace();\n if (text[i] !== \":\") unexpected();\n i++;\n members.push({ key: key.value, keyStart: key.start, value: readValue() });\n skipWhitespace();\n if (text[i] === \",\") {\n i++;\n continue;\n }\n if (text[i] === \"}\") {\n i++;\n return { kind: \"object\", start, end: i, members };\n }\n unexpected();\n }\n }\n if (text[i] === \"[\") {\n i++;\n skipWhitespace();\n if (text[i] === \"]\") {\n i++;\n return { kind: \"array\", start, end: i };\n }\n for (;;) {\n readValue();\n skipWhitespace();\n if (text[i] === \",\") {\n i++;\n continue;\n }\n if (text[i] === \"]\") {\n i++;\n return { kind: \"array\", start, end: i };\n }\n unexpected();\n }\n }\n if (text[i] === \"\\\"\") return readString();\n while (i < text.length && !\",:{}[]\\\"\".includes(text[i]) && !WHITESPACE.includes(text[i])) i++;\n if (i === start) unexpected();\n return { kind: \"scalar\", start, end: i };\n };\n const root = readValue();\n skipWhitespace();\n if (i !== text.length) unexpected();\n return root;\n}\n\n/** The value at a path of object keys, or undefined. The last duplicate wins, as in `JSON.parse`. */\nfunction memberValue(root: JsonNode, keys: readonly string[]): JsonNode | undefined {\n let node: JsonNode | undefined = root;\n for (const key of keys) {\n if (node?.kind !== \"object\") return undefined;\n const members: JsonMember[] = node.members.filter(m => m.key === key);\n node = members[members.length - 1]?.value;\n }\n return node;\n}\n\ninterface TextEdit {\n start: number;\n end: number;\n replacement: string;\n}\n\n/** Apply non-overlapping edits, last first so the earlier offsets stay valid. */\nfunction applyEdits(text: string, edits: TextEdit[]): string {\n let out = text;\n for (const edit of [...edits].sort((a, b) => b.start - a.start)) {\n out = out.slice(0, edit.start) + edit.replacement + out.slice(edit.end);\n }\n return out;\n}\n\n/**\n * Remove one member from the object at `objectPath`, taking its comma with it.\n *\n * Rescans rather than trusting offsets from before an earlier edit. A middle or\n * first member takes everything up to the next key, so the next member inherits\n * its indentation; the last takes the comma and whitespace after the previous\n * value, so the closing brace keeps its line; an only member leaves `{}`.\n */\nfunction removeJsonMember(text: string, objectPath: readonly string[], key: string): string {\n const container = memberValue(scanJson(text), objectPath);\n if (container?.kind !== \"object\") return text;\n const index = container.members.findIndex(m => m.key === key);\n if (index === -1) return text;\n const members = container.members;\n const member = members[index];\n if (members.length === 1) {\n return text.slice(0, container.start + 1) + text.slice(container.end - 1);\n }\n if (index < members.length - 1) {\n return text.slice(0, member.keyStart) + text.slice(members[index + 1].keyStart);\n }\n return text.slice(0, members[index - 1].value.end) + text.slice(member.value.end);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction setPath(root: Record<string, unknown>, keys: string[], value: unknown): void {\n let node: Record<string, unknown> = root;\n for (const key of keys.slice(0, -1)) {\n const next = node[key];\n if (!isRecord(next)) return;\n node = next;\n }\n node[keys[keys.length - 1]] = value;\n}\n\nfunction deletePath(root: Record<string, unknown>, keys: readonly string[]): void {\n let node: Record<string, unknown> = root;\n for (const key of keys.slice(0, -1)) {\n const next = node[key];\n if (!isRecord(next)) return;\n node = next;\n }\n delete node[keys[keys.length - 1]];\n}\n\n/* ─── pnpm-workspace.yaml ──────────────────────────────────────────────────── */\n\ninterface YamlOverride {\n /** Index into the file's lines. */\n line: number;\n key: string;\n value: string;\n /** Where the value's text sits within the line, quotes excluded. */\n valueStart: number;\n valueEnd: number;\n}\n\ninterface YamlOverridesBlock {\n /** The block's key line — `overrides:`, `catalog:`. */\n keyLine: number;\n /** The block's lines, `keyLine` excluded: indented, blank or comment-only. */\n lines: number[];\n entries: YamlOverride[];\n /** Lines in the block that are neither an entry, nor blank, nor a comment. */\n otherContent: number;\n}\n\n/** Lines, each without its `\\r`, and whether the file used them. */\nfunction splitLines(text: string): string[] {\n return text.split(\"\\n\").map(line => (line.endsWith(\"\\r\") ? line.slice(0, -1) : line));\n}\n\n/**\n * A YAML scalar at the start of `rest`: its text, and where that text sits.\n *\n * Double- and single-quoted and plain scalars, which is every shape an override\n * value is written in. A double-quoted one with an escape in it is refused\n * rather than decoded: no version or path needs one, and getting the decoding\n * wrong would rewrite a value this does not understand.\n */\nfunction readYamlScalar(rest: string): { value: string; start: number; end: number } | null {\n if (rest.startsWith(\"\\\"\")) {\n const close = rest.indexOf(\"\\\"\", 1);\n if (close === -1 || rest.slice(1, close).includes(\"\\\\\")) return null;\n if (!/^\\s*(#.*)?$/.test(rest.slice(close + 1))) return null;\n return { value: rest.slice(1, close), start: 1, end: close };\n }\n if (rest.startsWith(\"'\")) {\n const close = rest.indexOf(\"'\", 1);\n if (close === -1 || rest[close + 1] === \"'\") return null;\n if (!/^\\s*(#.*)?$/.test(rest.slice(close + 1))) return null;\n return { value: rest.slice(1, close), start: 1, end: close };\n }\n const comment = rest.search(/\\s#/);\n const plain = (comment === -1 ? rest : rest.slice(0, comment)).trimEnd();\n if (plain === \"\" || /^[[{&*!|>%@`]/.test(plain)) return null;\n return { value: plain, start: 0, end: plain.length };\n}\n\n/**\n * A top-level block mapping of a `pnpm-workspace.yaml` — `overrides:`,\n * `catalog:` — read line by line.\n *\n * Deliberately narrow. The file is YAML, and the CLI carries no YAML parser; the\n * shape pnpm documents and every project writes is a block mapping of one\n * scalar per line, which a line reader handles exactly. Anything else in the\n * block is counted rather than guessed at, and an inline `overrides: { … }` is\n * reported as not handled.\n */\nfunction readYamlBlock(lines: string[], key: \"overrides\" | \"catalog\"): YamlOverridesBlock | null {\n const keyLine = lines.findIndex(line => new RegExp(`^${key}:\\\\s*(#.*)?$`).test(line));\n if (keyLine === -1) return null;\n\n const block: YamlOverridesBlock = { keyLine, lines: [], entries: [], otherContent: 0 };\n for (let index = keyLine + 1; index < lines.length; index++) {\n const line = lines[index];\n if (line.trim() !== \"\" && !/^\\s/.test(line) && !line.startsWith(\"#\")) break;\n block.lines.push(index);\n if (line.trim() === \"\" || /^\\s*#/.test(line)) continue;\n\n const entry = readYamlEntry(line, index);\n if (entry) block.entries.push(entry);\n else block.otherContent++;\n }\n return block;\n}\n\n/** One `key: scalar` line of a block mapping, or null when it is anything else. */\nfunction readYamlEntry(line: string, index: number): YamlOverride | null {\n const entry = /^(\\s+)(\"[^\"]*\"|'[^']*'|[^\\s\"'#][^:#]*?)\\s*:(\\s+|$)/.exec(line);\n const valueOffset = entry ? entry[0].length : -1;\n const scalar = entry ? readYamlScalar(line.slice(valueOffset)) : null;\n if (!entry || !scalar) return null;\n const rawKey = entry[2];\n return {\n line: index,\n key: /^[\"']/.test(rawKey) ? rawKey.slice(1, -1) : rawKey,\n value: scalar.value,\n valueStart: valueOffset + scalar.start,\n valueEnd: valueOffset + scalar.end\n };\n}\n\n/** One pnpm catalog: `catalog:` is the one named \"default\". */\ninterface YamlCatalog {\n name: string;\n field: CatalogField;\n entries: YamlOverride[];\n}\n\n/**\n * Every catalog a `pnpm-workspace.yaml` declares: the top-level `catalog:`\n * block, and each named block under `catalogs:`.\n *\n * `catalogs:` is one level deeper — a header line per catalog, its entries\n * indented under it — and is read with the same one-scalar-per-line rule.\n */\nfunction readYamlCatalogs(lines: string[]): YamlCatalog[] {\n const catalogs: YamlCatalog[] = [];\n const single = readYamlBlock(lines, \"catalog\");\n if (single) catalogs.push({ name: \"default\", field: \"catalog\", entries: single.entries });\n\n const keyLine = lines.findIndex(line => /^catalogs:\\s*(#.*)?$/.test(line));\n if (keyLine === -1) return catalogs;\n\n let current: YamlCatalog | null = null;\n let headerIndent = -1;\n for (let index = keyLine + 1; index < lines.length; index++) {\n const line = lines[index];\n if (line.trim() !== \"\" && !/^\\s/.test(line) && !line.startsWith(\"#\")) break;\n if (line.trim() === \"\" || /^\\s*#/.test(line)) continue;\n\n const indent = line.length - line.trimStart().length;\n const header = /^\\s+(\"[^\"]*\"|'[^']*'|[^\\s\"'#][^:#]*?)\\s*:\\s*(#.*)?$/.exec(line);\n if (header && (headerIndent === -1 || indent === headerIndent)) {\n headerIndent = indent;\n const name = /^[\"']/.test(header[1]) ? header[1].slice(1, -1) : header[1];\n current = { name, field: `catalogs.${name}`, entries: [] };\n catalogs.push(current);\n continue;\n }\n if (!current || indent <= headerIndent) continue;\n const entry = readYamlEntry(line, index);\n if (entry) current.entries.push(entry);\n }\n return catalogs;\n}\n\n/** A `pnpm-workspace.yaml`, with its overrides and then its catalogs moved. */\nfunction planWorkspaceYaml(\n file: string,\n original: string,\n target: string,\n options: PlanOptions,\n plan: UpgradePlan,\n ledger: CatalogLedger\n): string {\n const overridden = planYamlOverrides(file, original, target, options, plan, ledger);\n return planYamlCatalogs(file, overridden, target, plan, ledger);\n}\n\n/**\n * Move the framework entries of every catalog. Entries are rewritten in place\n * — a catalog loses no line — and the result is read back and held to what was\n * meant, like every other rewrite here.\n */\nfunction planYamlCatalogs(\n file: string,\n original: string,\n target: string,\n plan: UpgradePlan,\n ledger: CatalogLedger\n): string {\n const lines = splitLines(original);\n const catalogs = readYamlCatalogs(lines);\n\n for (const key of [\"catalog\", \"catalogs\"]) {\n const inline = lines.find(line => new RegExp(`^${key}:\\\\s*[^\\\\s#]`).test(line));\n if (inline && inline.includes(FRAMEWORK_SCOPE)) {\n plan.skipped.push({\n file,\n name: key,\n field: key,\n spec: inline.slice(key.length + 1).trim(),\n reason: `an inline ${key} map, which this does not rewrite; write it as a block, or edit it by hand`\n });\n }\n }\n if (catalogs.length === 0) return original;\n\n const next = [...lines];\n const expected: Array<[string, string, string]> = [];\n for (const catalog of catalogs) {\n for (const entry of catalog.entries) {\n const meant: [string, string, string] = [catalog.field, entry.key, entry.value];\n expected.push(meant);\n if (!entry.key.startsWith(FRAMEWORK_SCOPE)) continue;\n ledger.defined.add(catalogKey(catalog.name, entry.key));\n\n const cls = classifySpec(entry.value);\n if (cls.kind !== \"movable\") {\n plan.skipped.push({ file, name: entry.key, field: catalog.field, spec: entry.value, reason: leftAloneReason(cls) });\n continue;\n }\n const to = `${cls.prefix}${target}`;\n if (to === entry.value) {\n plan.unchanged++;\n continue;\n }\n meant[2] = to;\n const line = next[entry.line];\n next[entry.line] = line.slice(0, entry.valueStart) + to + line.slice(entry.valueEnd);\n plan.changed.push({ file, name: entry.key, field: catalog.field, from: entry.value, to });\n }\n }\n\n const content = next.join(original.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\");\n const after = readYamlCatalogs(splitLines(content))\n .flatMap(catalog => catalog.entries.map(e => [catalog.field, e.key, e.value]));\n if (!isDeepStrictEqual(after, expected)) {\n throw new UpgradeError(\n `Could not rewrite ${file} without disturbing it; nothing was written.`,\n \"rewrite_failed\",\n \"Move its @rebasepro catalog entries by hand, then run `rebase upgrade` again.\"\n );\n }\n return content;\n}\n\nfunction planYamlOverrides(\n file: string,\n original: string,\n target: string,\n options: PlanOptions,\n plan: UpgradePlan,\n ledger: CatalogLedger\n): string {\n const lines = splitLines(original);\n const crlf = original.includes(\"\\r\\n\");\n const block = readYamlBlock(lines, \"overrides\");\n\n if (!block) {\n const inline = lines.find(line => /^overrides:\\s*[^\\s#]/.test(line));\n if (inline && inline.includes(FRAMEWORK_SCOPE)) {\n plan.skipped.push({\n file,\n name: \"overrides\",\n field: \"overrides\",\n spec: inline.slice(\"overrides:\".length).trim(),\n reason: \"an inline overrides map, which this does not rewrite; write it as a block, or edit it by hand\"\n });\n }\n return original;\n }\n\n const next = [...lines];\n const removed = new Set<number>();\n const expected = new Map<string, string>();\n\n for (const entry of block.entries) {\n if (!overrideTarget(entry.key)) {\n expected.set(entry.key, entry.value);\n continue;\n }\n const cls = classifySpec(entry.value);\n const pkg = overrideTarget(entry.key);\n if (cls.kind === \"movable\") {\n const to = `${cls.prefix}${target}`;\n expected.set(entry.key, to);\n if (to === entry.value) {\n plan.unchanged++;\n continue;\n }\n const line = lines[entry.line];\n next[entry.line] = line.slice(0, entry.valueStart) + to + line.slice(entry.valueEnd);\n plan.overrides.push({ file, name: entry.key, spec: entry.value, action: \"bumped\", to });\n } else if (cls.kind === \"catalog\" && pkg) {\n expected.set(entry.key, entry.value);\n ledger.refs.push({ file, name: entry.key, field: \"overrides\", spec: entry.value, catalog: cls.catalog, pkg });\n } else if (cls.kind === \"local\") {\n if (options.dropLocalOverrides) {\n removed.add(entry.line);\n plan.overrides.push({ file, name: entry.key, spec: entry.value, action: \"removed-local\" });\n } else {\n expected.set(entry.key, entry.value);\n plan.overrides.push({ file, name: entry.key, spec: entry.value, action: \"kept-local\" });\n }\n } else {\n expected.set(entry.key, entry.value);\n plan.skipped.push({ file, name: entry.key, field: \"overrides\", spec: entry.value, reason: leftAloneReason(cls) });\n }\n }\n\n // A block the removals emptied goes too, key line included: `overrides:`\n // with nothing under it is `overrides: null`, which pnpm reads as a value.\n const survivors = block.entries.filter(entry => !removed.has(entry.line)).length + block.otherContent;\n if (removed.size > 0 && survivors === 0) removed.add(block.keyLine);\n\n const kept = next.filter((_, index) => !removed.has(index));\n const content = kept.join(crlf ? \"\\r\\n\" : \"\\n\");\n\n // Read back with the same reader, and hold it to what was meant: the same\n // entries, in the same order, with only the intended values changed, and\n // every line outside the block untouched.\n const after = readYamlBlock(splitLines(content), \"overrides\");\n const afterEntries = after ? after.entries.map(e => [e.key, e.value]) : [];\n if (!isDeepStrictEqual(afterEntries, [...expected.entries()])) {\n throw new UpgradeError(\n `Could not rewrite ${file} without disturbing it; nothing was written.`,\n \"rewrite_failed\",\n \"Move its @rebasepro overrides by hand, then run `rebase upgrade` again.\"\n );\n }\n return content;\n}\n\n/* ─── the install ──────────────────────────────────────────────────────────── */\n\nexport type Installer = \"pnpm\" | \"npm\" | \"yarn\" | \"bun\";\n\n/** Lockfiles, in the order they are looked for in each directory. */\nconst LOCKFILES: ReadonlyArray<[string, Installer]> = [\n [\"pnpm-lock.yaml\", \"pnpm\"],\n [\"package-lock.json\", \"npm\"],\n [\"yarn.lock\", \"yarn\"],\n [\"bun.lockb\", \"bun\"],\n [\"bun.lock\", \"bun\"]\n];\n\n/**\n * The package manager this project installs with, from what is on disk.\n *\n * A lockfile is the project's own statement, so it wins. The search starts at\n * the project root and walks up, because a project inside a workspace has its\n * lockfile at the workspace root; it stops at the repository's root, so a stray\n * lockfile in a home directory is never read as this project's choice. With no\n * lockfile anywhere, a `pnpm-workspace.yaml` still says pnpm; otherwise npm,\n * the one every Node install has.\n */\nexport function detectInstaller(projectRoot: string): Installer {\n let dir = path.resolve(projectRoot);\n let workspaceYaml = false;\n for (;;) {\n for (const [lockfile, installer] of LOCKFILES) {\n if (fs.existsSync(path.join(dir, lockfile))) return installer;\n }\n if (fs.existsSync(path.join(dir, \"pnpm-workspace.yaml\"))) workspaceYaml = true;\n const parent = path.dirname(dir);\n if (parent === dir || fs.existsSync(path.join(dir, \".git\"))) break;\n dir = parent;\n }\n return workspaceYaml ? \"pnpm\" : \"npm\";\n}\n\n/**\n * The install command for each package manager — pnpm's and npm's from the\n * helpers every other command uses, yarn's and bun's spelled the same way.\n */\nexport function installCommand(installer: Installer): [string, string[]] {\n const [bin, ...args] = installer === \"pnpm\" || installer === \"npm\"\n ? getPMCommands(installer).install\n : [installer, \"install\"];\n return [bin, args];\n}\n\n/* ─── the target ───────────────────────────────────────────────────────────── */\n\n/**\n * The exact version `--to` names.\n *\n * An exact version is used as written, with no network call: the control plane\n * passes one when it rebuilds a project, and that rebuild must not depend on a\n * registry lookup succeeding for anything but the install itself. Anything\n * else is a dist-tag, asked of the registry through `npmView` — which runs npm\n * in the project, so its `.npmrc` and the user's registry config apply.\n */\nexport async function resolveTarget(\n requested: string,\n npmView: (spec: string) => Promise<string>\n): Promise<string> {\n const trimmed = requested.trim();\n const bare = trimmed.replace(/^v(?=\\d)/, \"\");\n if (isExactVersion(bare)) return bare;\n\n if (!/^[A-Za-z][\\w.-]*$/.test(trimmed)) {\n throw new UpgradeError(\n `\"${requested}\" is neither an exact version nor a dist-tag.`,\n \"target_invalid\",\n \"Pass an exact version such as 0.21.0, or a dist-tag such as latest or canary.\"\n );\n }\n\n let answer: string;\n try {\n answer = (await npmView(`${RELEASE_PACKAGE}@${trimmed}`)).trim();\n } catch (err) {\n const detail = err instanceof Error ? firstLine(err.message) : String(err);\n throw new UpgradeError(\n `Could not resolve \"${trimmed}\" on the npm registry${detail ? `: ${detail}` : \".\"}`,\n \"target_unresolved\",\n \"Check the tag and your registry access, or pass an exact version with --to.\"\n );\n }\n if (!isExactVersion(answer)) {\n throw new UpgradeError(\n `The registry has no single version for ${RELEASE_PACKAGE}@${trimmed}` +\n `${answer ? ` (it answered \"${firstLine(answer)}\")` : \"\"}.`,\n \"target_unresolved\",\n \"Check the tag, or pass an exact version with --to.\"\n );\n }\n return answer;\n}\n\nfunction firstLine(text: string): string {\n return text.split(\"\\n\").map(line => line.trim()).filter(Boolean)[0] ?? \"\";\n}\n\n/**\n * Whether moving from `from` to `to` goes backwards, for the one-word note the\n * summary prints. Prerelease identifiers compare as SemVer orders them: a\n * release outranks its own prereleases.\n */\nexport function isDowngrade(from: string, to: string): boolean {\n const a = SEMVER.exec(from.replace(/^[\\^~]/, \"\"));\n const b = SEMVER.exec(to.replace(/^[\\^~]/, \"\"));\n if (!a || !b) return false;\n for (let i = 1; i <= 3; i++) {\n const diff = Number(a[i]) - Number(b[i]);\n if (diff !== 0) return diff > 0;\n }\n const preA = a[4];\n const preB = b[4];\n if (preA === preB) return false;\n if (preA === undefined) return true;\n if (preB === undefined) return false;\n const partsA = preA.split(\".\");\n const partsB = preB.split(\".\");\n for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {\n const x = partsA[i];\n const y = partsB[i];\n if (x === undefined) return false;\n if (y === undefined) return true;\n if (x === y) continue;\n const nx = /^\\d+$/.test(x) ? Number(x) : NaN;\n const ny = /^\\d+$/.test(y) ? Number(y) : NaN;\n if (!Number.isNaN(nx) && !Number.isNaN(ny)) return nx > ny;\n if (!Number.isNaN(nx)) return false;\n if (!Number.isNaN(ny)) return true;\n return x > y;\n }\n return false;\n}\n","/**\n * CLI command: rebase upgrade [--to <version|tag>]\n *\n * Moves every `@rebasepro/*` package the project pins to one release, then\n * installs. The file work — which specs move, the rewrite, what overrides say —\n * is `../upgrade.ts`; this adds the registry lookup for a tag, the install, and\n * the two ways of saying what happened.\n */\nimport chalk from \"chalk\";\nimport { execa } from \"execa\";\nimport { parseCommandArgs, wantsHelp } from \"../utils/args\";\nimport { failAsJson, requireProjectRoot, type JsonFailureIssue } from \"../utils/project\";\nimport { loadManifest, ManifestError } from \"../manifest\";\nimport {\n applyUpgradePlan,\n detectInstaller,\n installCommand,\n isDowngrade,\n planUpgrade,\n resolveTarget,\n UpgradeError,\n type ChangedPin,\n type OverrideFinding,\n type SkippedSpec,\n type UnreadableFile,\n type UpgradePlan\n} from \"../upgrade\";\n\n/** Every flag `rebase upgrade` accepts. Its help page and the docs verifier read this. */\nexport const UPGRADE_FLAGS = {\n \"--to\": String,\n \"--drop-local-overrides\": Boolean,\n \"--no-install\": Boolean,\n \"--dry-run\": Boolean,\n \"--json\": Boolean\n} as const;\n\nfunction printHelp(): void {\n console.log(`\n${chalk.bold(\"rebase upgrade\")} — move every @rebasepro package this project pins to one release\n\n${chalk.bold(\"Usage\")}\n rebase upgrade [--to <version|tag>] [options]\n\n${chalk.bold(\"Options\")}\n --to <version|tag> The release: an exact version (0.21.0) or a dist-tag\n (latest, canary). Default: latest\n --drop-local-overrides Remove link: and file: overrides of @rebasepro packages,\n which win over every pin\n --no-install Rewrite the package.json files, but do not install\n --dry-run Print what would change, and write nothing\n --json One JSON document on stdout\n -h, --help Show this help\n\n${chalk.bold(\"What it changes\")}\n Every @rebasepro/* entry in dependencies, devDependencies and optionalDependencies,\n in every package.json under the project that git does not ignore (node_modules,\n dist* and hidden directories excepted, in a repository or not). ^ and ~ are kept.\n peerDependencies are left alone, and so are workspace:, link:, file:, git and tag\n specs, which are listed with the reason.\n Overrides in pnpm-workspace.yaml and package.json are bumped the same way, and so\n are the entries of pnpm-workspace.yaml's catalog: and catalogs: blocks, which is\n where a catalog: pin's version lives.\n\n${chalk.bold(\"Examples\")}\n rebase upgrade Move to the latest release and install\n rebase upgrade --to canary --dry-run See what the canary would change\n rebase upgrade --to 0.21.0 --no-install --json\n`.trim());\n}\n\n/** What the command reports, human or `--json`. */\nexport interface UpgradeResult {\n target: string;\n changed: ChangedPin[];\n skipped: SkippedSpec[];\n overrides: OverrideFinding[];\n unreadable: UnreadableFile[];\n installed: boolean;\n dryRun: boolean;\n}\n\n/**\n * The two things this command does outside the project's files: ask the\n * registry what a tag points at, and install. Injectable, so a test runs the\n * whole command without either.\n */\nexport interface UpgradeIo {\n npmView: (spec: string, cwd: string) => Promise<string>;\n /** `quietStdout`: route the installer's stdout to stderr, so `--json` keeps stdout to itself. */\n install: (command: [string, string[]], cwd: string, quietStdout: boolean) => Promise<void>;\n}\n\nconst defaultIo: UpgradeIo = {\n // Run in the project, so its `.npmrc` — a private registry, a scope\n // mapping — answers the question rather than whatever the CLI was run from.\n npmView: async (spec, cwd) => {\n try {\n return (await execa(\"npm\", [\"view\", spec, \"version\"], { cwd })).stdout;\n } catch (err) {\n throw new Error(npmFailure(err));\n }\n },\n install: async ([bin, args], cwd, quietStdout) => {\n await execa(bin, args, { cwd, stdio: quietStdout ? [\"ignore\", 2, \"inherit\"] : \"inherit\" });\n }\n};\n\n/**\n * The one line of a failed `npm view` worth printing.\n *\n * execa's own message is the command line that failed, which says nothing the\n * reader does not know. npm's stderr says why — `404 No match found for version\n * nosuchtag` — under an `npm error code E404` line that says less.\n */\nexport function npmFailure(err: unknown): string {\n const stderr = typeof err === \"object\" && err !== null && \"stderr\" in err && typeof err.stderr === \"string\"\n ? err.stderr\n : \"\";\n const reason = stderr\n .split(\"\\n\")\n .map(line => line.replace(/^npm (?:error|ERR!)\\s*/, \"\").trim())\n .find(line => line !== \"\" && !/^code\\s/.test(line) && !/^\\d{3}$/.test(line));\n return reason ?? (err instanceof Error ? err.message : String(err));\n}\n\n/**\n * The one release every moved pin came from, or `null` when they disagreed.\n * A range's `^`/`~` is not part of it: `upgrade --to` keeps each pin's operator.\n */\nfunction previousRelease(plan: UpgradePlan): string | null {\n const versions = new Set(plan.changed.map(pin => pin.from.replace(/^[\\^~]/, \"\")));\n if (versions.size !== 1) return null;\n const [version] = versions;\n return /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?$/.test(version) ? version : null;\n}\n\nexport async function upgradeCommand(rawArgs: string[], io: UpgradeIo = defaultIo): Promise<void> {\n if (wantsHelp(rawArgs)) {\n printHelp();\n return;\n }\n\n const { flags } = parseCommandArgs({\n spec: UPGRADE_FLAGS,\n rawArgs,\n commandWords: 1,\n command: \"upgrade\",\n maxPositionals: 0\n });\n const json = flags[\"--json\"] === true;\n const dryRun = flags[\"--dry-run\"] === true;\n\n const projectRoot = requireProjectRoot();\n\n /** Every refusal, in whichever of the two languages was asked for. */\n const refuse = (message: string, code: string, hint?: string, issues?: JsonFailureIssue[]): never => {\n if (json) failAsJson(message, code, hint, issues);\n console.error(chalk.red(`✗ ${message}`));\n for (const issue of issues ?? []) console.error(` ${chalk.gray(issue.path ?? \"\")} ${issue.message}`);\n if (hint) console.error(chalk.gray(` ${hint}`));\n process.exit(1);\n };\n\n // A project whose rebase.json does not load cannot be built on any release,\n // so moving its pins would only move the failure. Said first, and in the\n // same envelope `rebase status` uses.\n try {\n loadManifest(projectRoot);\n } catch (err) {\n if (err instanceof ManifestError) {\n refuse(err.message, \"manifest_invalid\", \"Fix rebase.json, then run this again.\",\n err.issues.map(issue => ({ path: issue.path, message: issue.message })));\n }\n throw err;\n }\n\n let plan: UpgradePlan;\n try {\n const target = await resolveTarget(flags[\"--to\"] ?? \"latest\", spec => io.npmView(spec, projectRoot));\n plan = planUpgrade(projectRoot, target, { dropLocalOverrides: flags[\"--drop-local-overrides\"] === true });\n } catch (err) {\n if (err instanceof UpgradeError) refuse(err.message, err.code, err.hint);\n throw err;\n }\n\n if (!dryRun) applyUpgradePlan(plan);\n const wrote = !dryRun && plan.writes.length > 0;\n const install = wrote && flags[\"--no-install\"] !== true;\n const installer = detectInstaller(projectRoot);\n const [bin, args] = installCommand(installer);\n const installLine = [bin, ...args].join(\" \");\n\n if (!json) printSummary(plan, dryRun);\n\n let installed = false;\n if (install) {\n if (!json) console.log(chalk.gray(` Installing with ${installer}...\\n`));\n try {\n await io.install([bin, args], projectRoot, json);\n installed = true;\n } catch {\n // The undo is a command this one already knows, when every pin it\n // moved came from one release: a mistyped `--to` (0.99.0 for\n // 0.29.0) is the commonest way here, and \"revert with git\" is no\n // answer in a project `rebase init --yes` never made a repository.\n const previous = previousRelease(plan);\n refuse(\n `\\`${installLine}\\` failed.`,\n \"install_failed\",\n `The package.json edits were kept. Fix what the install reported and run \\`${installLine}\\` again, ` +\n (previous\n ? `or put every pin back with \\`rebase upgrade --to ${previous}\\`.`\n : \"or revert the edits with git.\")\n );\n }\n }\n\n const result: UpgradeResult = {\n target: plan.target,\n changed: plan.changed,\n skipped: plan.skipped,\n overrides: plan.overrides,\n unreadable: plan.unreadable,\n installed,\n dryRun\n };\n\n if (json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n printOutcome(plan, { dryRun, wrote, installed, installLine });\n}\n\n/** Changes grouped by file, then what was left alone and why, then overrides. */\nfunction printSummary(plan: UpgradePlan, dryRun: boolean): void {\n console.log(\"\");\n console.log(`${chalk.bold(\"Rebase\")} — ${dryRun ? \"what upgrading\" : \"upgrading\"} @rebasepro packages to ${chalk.cyan(plan.target)}${dryRun ? \" would change\" : \"\"}`);\n\n const byFile = new Map<string, ChangedPin[]>();\n for (const pin of plan.changed) byFile.set(pin.file, [...(byFile.get(pin.file) ?? []), pin]);\n const nameWidth = Math.max(0, ...plan.changed.map(pin => pin.name.length));\n for (const [file, pins] of byFile) {\n console.log(\"\");\n console.log(` ${chalk.bold(file)}`);\n for (const pin of pins) {\n const field = pin.field === \"dependencies\" ? \"\" : chalk.gray(` ${pin.field}`);\n const older = isDowngrade(pin.from, pin.to) ? chalk.yellow(\" (older)\") : \"\";\n console.log(` ${pin.name.padEnd(nameWidth)} ${chalk.gray(pin.from)} → ${chalk.green(pin.to)}${field}${older}`);\n }\n }\n\n if (plan.skipped.length > 0) {\n console.log(\"\");\n console.log(` ${chalk.bold(\"Left alone\")}`);\n for (const skip of plan.skipped) {\n console.log(` ${skip.name} ${chalk.gray(skip.spec)} ${chalk.gray(`(${skip.file}, ${skip.field})`)}`);\n console.log(chalk.gray(` ${skip.reason}`));\n }\n }\n\n if (plan.overrides.length > 0) {\n console.log(\"\");\n console.log(` ${chalk.bold(\"Overrides\")}`);\n for (const override of plan.overrides) {\n const where = chalk.gray(`(${override.file})`);\n if (override.action === \"bumped\") {\n console.log(` ${override.name} ${chalk.gray(override.spec)} → ${chalk.green(override.to ?? \"\")} ${where}`);\n } else if (override.action === \"removed-local\") {\n console.log(` ${override.name} ${chalk.gray(override.spec)} ${where} ${chalk.green(dryRun ? \"would be removed\" : \"removed\")}`);\n } else {\n console.log(` ${chalk.yellow(\"⚠\")} ${override.name} → ${override.spec} ${where}`);\n console.log(chalk.yellow(\" local override — wins over every pin, the upgrade will not reach these packages\"));\n }\n }\n if (plan.overrides.some(o => o.action === \"kept-local\")) {\n console.log(chalk.gray(\" Run again with --drop-local-overrides to remove them.\"));\n }\n }\n\n if (plan.unreadable.length > 0) {\n console.log(\"\");\n console.log(` ${chalk.bold(\"Not read\")}`);\n for (const entry of plan.unreadable) {\n console.log(` ${entry.file} ${chalk.gray(entry.reason)}`);\n }\n }\n console.log(\"\");\n}\n\nfunction printOutcome(\n plan: UpgradePlan,\n outcome: { dryRun: boolean; wrote: boolean; installed: boolean; installLine: string }\n): void {\n const moved = plan.changed.length + plan.overrides.filter(o => o.action !== \"kept-local\").length;\n // What the project is not moved off by this command: every pin it left\n // alone, and every local override that wins over the pins it did move.\n const leftAlone = plan.skipped.length + plan.overrides.filter(o => o.action === \"kept-local\").length;\n const entries = (n: number): string => `${n} entr${n === 1 ? \"y\" : \"ies\"}`;\n\n // Nothing moved is only \"already on\" the target when nothing was left\n // alone either. A project whose every pin was skipped — a dist-tag, a\n // `workspace:` link, a catalog it could not find — is on whatever those\n // resolve to, and saying otherwise is the one sentence it must not print.\n if (moved === 0 && leftAlone > 0) {\n if (plan.unchanged > 0) {\n console.log(chalk.green(\n `✓ Every pin this can move is already on ${plan.target}; ${entries(leftAlone)} ${leftAlone === 1 ? \"was\" : \"were\"} left alone, above.`));\n } else if (outcome.dryRun) {\n console.log(chalk.yellow(\n ` Nothing to move to ${plan.target}: ${entries(leftAlone)} ${leftAlone === 1 ? \"is\" : \"are\"} left alone, above.`));\n } else {\n console.log(chalk.yellow(\n `⚠ Nothing moved to ${plan.target}: ${entries(leftAlone)} ${leftAlone === 1 ? \"was\" : \"were\"} left alone, above.`));\n }\n console.log(\"\");\n return;\n }\n\n if (outcome.dryRun) {\n console.log(chalk.gray(moved === 0\n ? ` Nothing to change: this project is already on ${plan.target}.`\n : \" Dry run — nothing was written. Run it without --dry-run to apply.\"));\n console.log(\"\");\n return;\n }\n\n if (!outcome.wrote) {\n console.log(chalk.green(`✓ This project is already on ${plan.target}.`));\n console.log(\"\");\n return;\n }\n\n const files = plan.writes.length;\n console.log(chalk.green(\n `✓ Moved ${moved} entr${moved === 1 ? \"y\" : \"ies\"} in ${files} file${files === 1 ? \"\" : \"s\"} to ${plan.target}` +\n `${outcome.installed ? \" and installed\" : \"\"}.`\n ));\n if (!outcome.installed) {\n console.log(chalk.gray(` Install with \\`${outcome.installLine}\\`, then run \\`rebase build\\`, then \\`rebase cloud deploy\\`.`));\n } else {\n console.log(chalk.gray(\" Run `rebase build`, then `rebase cloud deploy`.\"));\n }\n console.log(\"\");\n}\n"],"mappings":"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"}
package/dist/upgrade.d.ts CHANGED
@@ -58,8 +58,20 @@ export interface ProjectFiles {
58
58
  packageJsons: string[];
59
59
  workspaceYamls: string[];
60
60
  }
61
- /** Every `package.json` and `pnpm-workspace.yaml` under the project root. */
62
- export declare function discoverProjectFiles(projectRoot: string): ProjectFiles;
61
+ /** `git -C <cwd> …`, returning stdout. Throws when git is missing or refuses. */
62
+ export type GitRunner = (cwd: string, args: string[]) => string;
63
+ /**
64
+ * Every `package.json` and `pnpm-workspace.yaml` under the project root that
65
+ * belongs to the project.
66
+ *
67
+ * In a git repository that means what git lists: a gitignored build context,
68
+ * scratch copy or vendored package is not the project's, and rewriting it
69
+ * would change files nobody committed. The walk enters only directories that
70
+ * hold a listed file, so an ignored tree is not read at all. Outside a
71
+ * repository every directory is walked. {@link skipDirectory} applies either
72
+ * way.
73
+ */
74
+ export declare function discoverProjectFiles(projectRoot: string, git?: GitRunner): ProjectFiles;
63
75
  /** Where a catalog pin sits: `catalog`, or `catalogs.<name>` for a named one. */
64
76
  export type CatalogField = "catalog" | `catalogs.${string}`;
65
77
  export interface ChangedPin {
@@ -0,0 +1,18 @@
1
+ /** The rule, as every help page and error states it. */
2
+ export declare const COLLECTIONS_PATH_RULE = "relative paths are resolved from where you run the command";
3
+ /** The `--collections` line of a help page. */
4
+ export declare const COLLECTIONS_FLAG_HELP = "Collections directory (default: config/collections); relative paths are resolved from where you run the command";
5
+ /**
6
+ * The refusal for a `--collections` path that does not exist, or `null`.
7
+ *
8
+ * Checked by the CLI, in the reader's terms, before the driver is spawned: the
9
+ * driver's own check runs in `backend/` and can only describe the path it was
10
+ * handed. A generator pointed at a directory that is not there writes an empty
11
+ * schema, and a push of an empty schema drops every table — so nothing runs.
12
+ *
13
+ * Scripts written for the old rule (`--collections ../config/collections`,
14
+ * run from the root) land here, and the message says exactly what to change.
15
+ */
16
+ export declare function missingCollectionsPath(args: readonly string[], cwd: string, backendDir: string): string[] | null;
17
+ /** Print {@link missingCollectionsPath}'s refusal and exit 1, or return. */
18
+ export declare function refuseMissingCollectionsPath(args: readonly string[], cwd: string, backendDir: string): void;
@@ -63,6 +63,22 @@ export declare function resolveLocalBin(projectRoot: string, binName: string): s
63
63
  * Resolve the tsx binary. Checks backend node_modules first, then root.
64
64
  */
65
65
  export declare function resolveTsx(projectRoot: string): string | null;
66
+ /**
67
+ * tsx's loader, as the URL `node --import` takes, or null when none resolves.
68
+ *
69
+ * For running a TypeScript entry in one Node process. The `tsx` binary is a
70
+ * relay — pnpm's `.bin/tsx` shell shim, then tsx's CLI in one Node, which
71
+ * spawns a second Node with this same loader to run the script — so spawning
72
+ * through it costs a shell and a Node start (~50–100 ms) on every hop, and
73
+ * `rebase dev` pays a hop on every start and every collection save.
74
+ *
75
+ * Resolved the way Node resolves the package, from the project first — the
76
+ * backend, where a scaffold declares tsx, then the root and everything above it
77
+ * — so the tsx used is the one {@link resolveTsx} would have found; then from
78
+ * this package, as the repository's own tests resolve `tsx/cli`. A URL rather
79
+ * than a path: a Windows path is not a valid `--import` specifier.
80
+ */
81
+ export declare function resolveTsxLoader(projectRoot: string): string | null;
66
82
  /**
67
83
  * Validate that a resolved tsx binary actually has an intact installation.
68
84
  *
@@ -0,0 +1,58 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { fileURLToPath } from "url";
4
+ //#region src/utils/version.ts
5
+ /**
6
+ * This CLI's own version, and the User-Agent built from it.
7
+ *
8
+ * Four call sites used to answer "what version am I?" and each answered it
9
+ * differently. `cli.ts` walked one directory up from `__dirname`. `init.ts`
10
+ * walked up looking for a folder literally named `cli`. `bundle.ts` had
11
+ * `resolveCliVersion`, which walked up at most five levels for a manifest whose
12
+ * `name` matched — the only one of the three that was actually correct, and the
13
+ * one the other two did not know existed. Every HTTP request to the control
14
+ * plane answered it not at all, which is the expensive gap: a control plane
15
+ * cannot refuse a CLI that is too old for its wire format if no request ever
16
+ * says which CLI is calling.
17
+ *
18
+ * One answer now, and it is `bundle.ts`'s: walk up for the manifest that names
19
+ * this package, rather than counting directories or matching a folder name.
20
+ * `dist/` is one level down in a published install and two in a source
21
+ * checkout, and a folder called `cli` is not guaranteed to be ours. Two
22
+ * differences from that original — `fileURLToPath` instead of `new
23
+ * URL().pathname`, which is what makes it survive a path containing a space,
24
+ * and no five-level ceiling.
25
+ */
26
+ function readVersion() {
27
+ let dir = path.dirname(fileURLToPath(import.meta.url));
28
+ const root = path.parse(dir).root;
29
+ while (dir && dir !== root) {
30
+ const manifest = path.join(dir, "package.json");
31
+ if (fs.existsSync(manifest)) try {
32
+ const pkg = JSON.parse(fs.readFileSync(manifest, "utf-8"));
33
+ if (pkg.name === "@rebasepro/cli" && typeof pkg.version === "string") return pkg.version;
34
+ } catch {}
35
+ dir = path.dirname(dir);
36
+ }
37
+ return "unknown";
38
+ }
39
+ var cached;
40
+ /** The CLI's version, or `"unknown"` when it cannot be read. Memoized. */
41
+ function cliVersion() {
42
+ if (cached === void 0) cached = readVersion();
43
+ return cached;
44
+ }
45
+ /**
46
+ * `rebase-cli/0.17.3` — sent on every control-plane request.
47
+ *
48
+ * The control plane needs it to answer `CLI_TOO_OLD` with a minimum version
49
+ * instead of failing somewhere further in with a shape error. A client that
50
+ * does not identify itself can only ever be refused generically.
51
+ */
52
+ function cliUserAgent() {
53
+ return `rebase-cli/${cliVersion()}`;
54
+ }
55
+ //#endregion
56
+ export { cliVersion as n, cliUserAgent as t };
57
+
58
+ //# sourceMappingURL=version-Buyyo1ut.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-Buyyo1ut.js","names":[],"sources":["../src/utils/version.ts"],"sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\n\n/**\n * This CLI's own version, and the User-Agent built from it.\n *\n * Four call sites used to answer \"what version am I?\" and each answered it\n * differently. `cli.ts` walked one directory up from `__dirname`. `init.ts`\n * walked up looking for a folder literally named `cli`. `bundle.ts` had\n * `resolveCliVersion`, which walked up at most five levels for a manifest whose\n * `name` matched — the only one of the three that was actually correct, and the\n * one the other two did not know existed. Every HTTP request to the control\n * plane answered it not at all, which is the expensive gap: a control plane\n * cannot refuse a CLI that is too old for its wire format if no request ever\n * says which CLI is calling.\n *\n * One answer now, and it is `bundle.ts`'s: walk up for the manifest that names\n * this package, rather than counting directories or matching a folder name.\n * `dist/` is one level down in a published install and two in a source\n * checkout, and a folder called `cli` is not guaranteed to be ours. Two\n * differences from that original — `fileURLToPath` instead of `new\n * URL().pathname`, which is what makes it survive a path containing a space,\n * and no five-level ceiling.\n */\nfunction readVersion(): string {\n let dir = path.dirname(fileURLToPath(import.meta.url));\n const root = path.parse(dir).root;\n while (dir && dir !== root) {\n const manifest = path.join(dir, \"package.json\");\n if (fs.existsSync(manifest)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(manifest, \"utf-8\"));\n if (pkg.name === \"@rebasepro/cli\" && typeof pkg.version === \"string\") return pkg.version;\n } catch {\n // A malformed manifest on the way up is not ours to complain\n // about; keep walking.\n }\n }\n dir = path.dirname(dir);\n }\n return \"unknown\";\n}\n\nlet cached: string | undefined;\n\n/** The CLI's version, or `\"unknown\"` when it cannot be read. Memoized. */\nexport function cliVersion(): string {\n if (cached === undefined) cached = readVersion();\n return cached;\n}\n\n/**\n * `rebase-cli/0.17.3` — sent on every control-plane request.\n *\n * The control plane needs it to answer `CLI_TOO_OLD` with a minimum version\n * instead of failing somewhere further in with a shape error. A client that\n * does not identify itself can only ever be refused generically.\n */\nexport function cliUserAgent(): string {\n return `rebase-cli/${cliVersion()}`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAS,cAAsB;CAC3B,IAAI,MAAM,KAAK,QAAQ,cAAc,OAAO,KAAK,GAAG,CAAC;CACrD,MAAM,OAAO,KAAK,MAAM,GAAG,CAAC,CAAC;CAC7B,OAAO,OAAO,QAAQ,MAAM;EACxB,MAAM,WAAW,KAAK,KAAK,KAAK,cAAc;EAC9C,IAAI,GAAG,WAAW,QAAQ,GACtB,IAAI;GACA,MAAM,MAAM,KAAK,MAAM,GAAG,aAAa,UAAU,OAAO,CAAC;GACzD,IAAI,IAAI,SAAS,oBAAoB,OAAO,IAAI,YAAY,UAAU,OAAO,IAAI;EACrF,QAAQ,CAGR;EAEJ,MAAM,KAAK,QAAQ,GAAG;CAC1B;CACA,OAAO;AACX;AAEA,IAAI;;AAGJ,SAAgB,aAAqB;CACjC,IAAI,WAAW,KAAA,GAAW,SAAS,YAAY;CAC/C,OAAO;AACX;;;;;;;;AASA,SAAgB,eAAuB;CACnC,OAAO,cAAc,WAAW;AACpC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rebasepro/cli",
3
- "version": "0.23.0",
3
+ "version": "0.24.1-canary.g56af4a4",
4
4
  "description": "Developer tools for Rebase projects",
5
5
  "keywords": [
6
6
  "cli",
@@ -43,12 +43,12 @@
43
43
  "inquirer": "14.0.2",
44
44
  "jiti": "^2.7.0",
45
45
  "pg": "^8.22.0",
46
- "@rebasepro/agent-skills": "0.23.0",
47
- "@rebasepro/client": "0.23.0",
48
- "@rebasepro/codegen": "0.23.0",
49
- "@rebasepro/server": "0.23.0",
50
- "@rebasepro/types": "0.23.0",
51
- "@rebasepro/server-postgres": "0.23.0"
46
+ "@rebasepro/agent-skills": "0.24.1-canary.g56af4a4",
47
+ "@rebasepro/client": "0.24.1-canary.g56af4a4",
48
+ "@rebasepro/codegen": "0.24.1-canary.g56af4a4",
49
+ "@rebasepro/server": "0.24.1-canary.g56af4a4",
50
+ "@rebasepro/server-postgres": "0.24.1-canary.g56af4a4",
51
+ "@rebasepro/types": "0.24.1-canary.g56af4a4"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/node": "^26.1.2",
@@ -45,7 +45,7 @@ function findEnvFile(startDir: string): string | undefined {
45
45
  // the real process environment flow through.
46
46
  const envPath = process.env.DOTENV_CONFIG_PATH || findEnvFile(__dirname);
47
47
  if (envPath && fs.existsSync(envPath)) {
48
- dotenv.config({ path: envPath });
48
+ dotenv.config({ path: envPath, quiet: true });
49
49
  }
50
50
 
51
51
  export const env = loadEnv({
@@ -81,7 +81,24 @@ app.use("/*", cors({
81
81
  if (!origin) return "*";
82
82
  return isLocalhostOrigin(origin) ? origin : null;
83
83
  },
84
- credentials: true
84
+ credentials: true,
85
+ // A frontend on another origin reads only the response headers named here.
86
+ // Without `ETag` the SDK's `etagOf(row)` is always undefined there, and an
87
+ // `ifMatch` write silently goes out unconditional; without `Retry-After`
88
+ // and `X-Request-ID` a 429 or an error loses what it reports.
89
+ exposeHeaders: [
90
+ "ETag",
91
+ "Retry-After",
92
+ "X-Request-ID",
93
+ "X-RateLimit-Limit",
94
+ "X-RateLimit-Remaining",
95
+ "X-RateLimit-Reset",
96
+ "Preference-Applied",
97
+ // A resumable upload: where it lives, how far it got, what was stored.
98
+ "Location",
99
+ "Upload-Offset",
100
+ "Rebase-Upload-Result"
101
+ ]
85
102
  }));
86
103
 
87
104
  app.use("/*", secureHeaders());
@@ -106,7 +123,11 @@ const resolvedDataSources = resolveDataSources(process.env, dataSources);
106
123
  async function startServer() {
107
124
  const jwtSecret = env.JWT_SECRET;
108
125
  const PORT = env.PORT;
109
- const server = createServer(getRequestListener(app.fetch));
126
+ // 64 KB of request line plus headers, as the Rebase runtime takes, not
127
+ // Node's 16 KB: a vector search's embedding travels in `?vector=`, and
128
+ // 768 dimensions of it are already 17 KB of URL. (The SDK sends a vector
129
+ // search in a POST body; this is for a URL built by hand.)
130
+ const server = createServer({ maxHeaderSize: 64 * 1024 }, getRequestListener(app.fetch));
110
131
 
111
132
  // `backend/crons` holds the scheduled jobs — nightly backups among them.
112
133
  // Passed only when the directory exists, because a configured `cronsDir`
@@ -12,7 +12,7 @@ This is a **headless** Rebase project: a REST API, auth, storage and realtime ov
12
12
  | `rebase db url` | Print the connection string in use — it pipes straight into `psql` |
13
13
  | `pnpm db:migrate` | Apply the migration files in `backend/drizzle/migrations`. Needs your own PostgreSQL, not the managed development database |
14
14
  | `pnpm schema:introspect` | Existing tables → collection definitions in `config/collections/`. That directory ends headless mode; see rule 1 |
15
- | `pnpm generate:sdk` | Regenerate the typed client from `config/collections/` — so in a headless project it has nothing to read until you introspect |
15
+ | `pnpm generate:sdk` | Regenerate the typed client from `config/collections/` — so in a headless project it has nothing to read until you introspect. Once there are collections, `pnpm dev` does this on start and on every save; the script is for CI and for when `pnpm dev` is not running |
16
16
  | `pnpm build` then `pnpm start` | Build the deployable bundle, then run it |
17
17
  | `pnpm skills:install` | Install the Rebase skills for your assistant |
18
18
  | `pnpm example` | Run `scripts/example.ts` against the running backend — the SDK, end to end |
@@ -1,4 +1,4 @@
1
- import { isPublicStoragePath, type StorageAuthorize } from "@rebasepro/types";
1
+ import type { StorageAuthorize } from "@rebasepro/types";
2
2
 
3
3
  /**
4
4
  * Who may do what to files in storage.
@@ -39,7 +39,7 @@ import { isPublicStoragePath, type StorageAuthorize } from "@rebasepro/types";
39
39
  *
40
40
  * ```ts
41
41
  * export const storageAuthorize: StorageAuthorize = async ({ key, user, operation, data }) => {
42
- * if (operation === "read" && isPublicStoragePath(key)) return true;
42
+ * if (operation === "read" && key.startsWith("public/")) return true;
43
43
  * if (!user) return false;
44
44
  * const row = (await data?.collection("attachments").find({
45
45
  * where: { storage_key: ["==", key] }, limit: 1
@@ -55,7 +55,9 @@ import { isPublicStoragePath, type StorageAuthorize } from "@rebasepro/types";
55
55
  */
56
56
  export const storageAuthorize: StorageAuthorize = ({ key, user, operation }) => {
57
57
  // The `public/` prefix is the framework's convention for world-readable objects.
58
- if (operation === "read" && isPublicStoragePath(key)) {
58
+ // `key` is the canonical key the server serves, so a prefix test is exact:
59
+ // `default/public/x` is a private object in a folder named `default`.
60
+ if (operation === "read" && key.startsWith("public/")) {
59
61
  return true;
60
62
  }
61
63
 
@@ -1,3 +1,3 @@
1
1
  # Rebase AI Rules
2
2
  Please refer to and follow the instructions defined in [ai-instructions.md](./ai-instructions.md).
3
- Install the Rebase skills for this assistant: `rebase skills install --agent cursor`.
3
+ The Rebase skills for this assistant live in `.cursor/rules/`. If they are not there yet, install them, with the Rebase MCP server: `rebase skills install --agent cursor --mcp`.
@@ -51,10 +51,12 @@ DATABASE_URL=postgresql://rebase_app:changeme@localhost:5432/rebase?options=-c%2
51
51
  # DB_POOL_CONNECT_TIMEOUT=10000
52
52
 
53
53
  # ── Server ────────────────────────────────────────────────────────────────────
54
- # Used by `rebase start` (production). `rebase dev` IGNORES this and binds a
54
+ # Used by `rebase start`. `rebase dev` IGNORES this and binds a
55
55
  # port derived from the project path, so several projects can run at once —
56
56
  # trust the URL `rebase dev` prints, or pin one with `rebase dev --port 3001`.
57
57
  PORT=3001
58
+ # `rebase start` runs in this mode too, and warns that it is not a production
59
+ # server: set NODE_ENV=production (here or in the shell) for one.
58
60
  NODE_ENV=development
59
61
  # Allow connecting to localhost / 127.0.0.1 in production mode (for local testing of prod builds)
60
62
  # ALLOW_LOCALHOST_IN_PRODUCTION=false
@@ -222,7 +224,7 @@ VITE_API_URL=
222
224
  # BACKUP_DESTINATION=./backups # local path, or s3://bucket/prefix / gs://bucket/prefix
223
225
  # BACKUP_RETENTION_DAYS=14 # delete backups older than N days (unset/0 ⇒ keep all)
224
226
  # BACKUP_KEEP_MINIMUM=3 # always retain at least N most-recent backups
225
- # PG_DUMP_PATH= # override pg_dump binary (must match server major version)
227
+ # PG_DUMP_PATH= # override pg_dump binary (server's major version or newer)
226
228
  # PG_RESTORE_PATH= # override pg_restore binary
227
229
 
228
230
  # ── Admin Service Key (optional) ──────────────────────────────────────────────
@@ -250,9 +252,11 @@ VITE_API_URL=
250
252
  # unset. To upgrade, change this and restart — your bundle is untouched.
251
253
  REBASE_VERSION=latest
252
254
 
253
- # What boot does about versioned migrations in `backend/migrations`.
254
- # ensure create missing tables and columns from your collections (the default)
255
- # migrate run the migration files, then ensure
256
- # off neither
255
+ # Whether boot provisions the schema your collections describe.
256
+ # ensure create missing tables, columns and enum types, additively (the default)
257
+ # none leave the schema alone
258
+ # Any other value refuses to boot. Boot never runs migration files: the ones
259
+ # `rebase db generate` writes to `backend/drizzle/migrations` are applied with
260
+ # `rebase db migrate`.
257
261
  # REBASE_MIGRATE_ON_BOOT=ensure
258
262
 
@@ -1,3 +1,3 @@
1
1
  # Rebase AI Rules
2
2
  Please refer to and follow the instructions defined in [ai-instructions.md](../ai-instructions.md).
3
- Install the Rebase skills for this assistant: `rebase skills install --agent copilot`.
3
+ The Rebase skills for this assistant live in `.github/instructions/`. If they are not there yet, install them, with the Rebase MCP server: `rebase skills install --agent copilot --mcp`.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "mcpServers": {
3
3
  "rebase": {
4
- "command": "npx",
5
- "args": ["-y", "@rebasepro/mcp"],
4
+ "command": "pnpm",
5
+ "args": ["exec", "rebase-mcp"],
6
6
  "env": {
7
7
  "REBASE_PROJECT_DIR": "."
8
8
  }
@@ -1,3 +1,3 @@
1
1
  # Rebase AI Rules
2
2
  Please refer to and follow the instructions defined in [ai-instructions.md](./ai-instructions.md).
3
- Install the Rebase skills for this assistant: `rebase skills install --agent windsurf`.
3
+ The Rebase skills for this assistant live in `.windsurf/rules/`. If they are not there yet, install them, with the Rebase MCP server: `rebase skills install --agent windsurf --mcp`.
@@ -1,3 +1,3 @@
1
1
  # Rebase AI Rules
2
2
  Please refer to and follow the instructions defined in [ai-instructions.md](ai-instructions.md).
3
- Install the Rebase skills for this assistant: `rebase skills install --agent codex`.
3
+ The Rebase skills for this assistant live in `.agents/skills/`. If they are not there yet, install them, with the Rebase MCP server: `rebase skills install --agent codex --mcp`.
@@ -1,3 +1,3 @@
1
1
  # Rebase AI Rules
2
2
  Please refer to and follow the instructions defined in [ai-instructions.md](./ai-instructions.md).
3
- Install the Rebase skills for this assistant: `rebase skills install --agent claude`.
3
+ The Rebase skills for this assistant live in `.claude/skills/`. If they are not there yet, install them, with the Rebase MCP server: `rebase skills install --agent claude --mcp`.
@@ -33,20 +33,20 @@ pnpm install # or: npm install
33
33
  pnpm dev # or: npm run dev
34
34
  ```
35
35
 
36
- That is the whole first run. `rebase dev` generates the Drizzle schema from
37
- `config/collections`, starts the database, creates a table for every collection
38
- declared there, and serves the API and the admin panel.
36
+ That is the whole first run. `rebase dev` generates the Drizzle schema and the
37
+ SDK types from `config/collections`, starts the database, creates a table for
38
+ every collection declared there, and serves the API and the admin panel.
39
39
 
40
40
  `rebase dev` prints the two URLs it actually bound. The first account you
41
41
  register becomes the admin. `REBASE_ADMIN_EMAIL` and `REBASE_ADMIN_PASSWORD` in
42
42
  `.env` are ignored here and read by the production boot below, where that window
43
- is shut — see [Self-hosting](#self-hosting-with-docker).
43
+ is shut — see [Self-hosting](#self-hosting).
44
44
 
45
45
  Ports are **derived from this project's path**, not fixed at 3001/5173, so
46
46
  several Rebase projects can run at once without colliding. That is why the URL
47
47
  in your terminal is the one to trust — and why the `PORT` and `VITE_API_URL` in
48
- `.env` are ignored by `rebase dev` (they apply to `rebase start`, the production
49
- server). Pin a port with `rebase dev --port 3001` if you need a stable one.
48
+ `.env` are ignored by `rebase dev` (they apply to `rebase start`, which runs the
49
+ built bundle). Pin a port with `rebase dev --port 3001` if you need a stable one.
50
50
 
51
51
  ### Variant: your own PostgreSQL
52
52
 
@@ -61,10 +61,9 @@ database to compare against, and PGlite serves exactly one:
61
61
  pnpm run db:push
62
62
  ```
63
63
 
64
- Boot already creates missing tables and columns additively, so `db push` is for
65
- what it deliberately leaves alone: junction-table RLS on many-to-many relations,
66
- and any change that is not purely additive — a renamed column, a narrowed type,
67
- a removed field.
64
+ Boot already creates missing tables and columns, and their row-level security,
65
+ additively, so `db push` is for what it deliberately leaves alone: any change
66
+ that is not purely additive — a renamed column, a narrowed type, a removed field.
68
67
 
69
68
  The `docker-compose.yml` in this project runs PostgreSQL in a container if you
70
69
  would rather not install one:
@@ -163,8 +162,8 @@ compose database is a database of your own, so step 0 is the same one line.
163
162
  pnpm run build # or: npm run build
164
163
 
165
164
  # 2. Start the database. Boot creates the tables from your collections;
166
- # `db:push` is for what it leaves alone — junction-table RLS, and any
167
- # change that is not purely additive.
165
+ # `db:push` is for what it leaves alone — any change that is not purely
166
+ # additive.
168
167
  docker compose up -d db
169
168
  pnpm run db:push # or: npm run db:push
170
169