@rebasepro/cli 0.24.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 (118) hide show
  1. package/bin/rebase.js +3 -0
  2. package/dist/agent-setup-B31F00DC.js +324 -0
  3. package/dist/agent-setup-B31F00DC.js.map +1 -0
  4. package/dist/api-keys-BPBi5nOF.js +524 -0
  5. package/dist/api-keys-BPBi5nOF.js.map +1 -0
  6. package/dist/apps-CPXNElX4.js +256 -0
  7. package/dist/apps-CPXNElX4.js.map +1 -0
  8. package/dist/args-BnmsEXvu.js +109 -0
  9. package/dist/args-BnmsEXvu.js.map +1 -0
  10. package/dist/atlas-dev-database-DTMuEScS.js +62 -0
  11. package/dist/atlas-dev-database-DTMuEScS.js.map +1 -0
  12. package/dist/auth-DvY94ZuL.js +395 -0
  13. package/dist/auth-DvY94ZuL.js.map +1 -0
  14. package/dist/branch-pointer-DIhKbQLp.js +2 -0
  15. package/dist/build-CFwUx-Ff.js +336 -0
  16. package/dist/build-CFwUx-Ff.js.map +1 -0
  17. package/dist/bundle-BQhP_xiA.js +1617 -0
  18. package/dist/bundle-BQhP_xiA.js.map +1 -0
  19. package/dist/cli.d.ts +2 -2
  20. package/dist/cloud-CkTr-yt0.js +9640 -0
  21. package/dist/cloud-CkTr-yt0.js.map +1 -0
  22. package/dist/collection-drift-BKj_BoMq.js +106 -0
  23. package/dist/collection-drift-BKj_BoMq.js.map +1 -0
  24. package/dist/commands/api-keys.d.ts +2 -0
  25. package/dist/commands/db.d.ts +37 -24
  26. package/dist/commands/dev.d.ts +103 -0
  27. package/dist/commands/generate_sdk.d.ts +26 -0
  28. package/dist/commands/skills.d.ts +22 -7
  29. package/dist/commands/storage.d.ts +46 -0
  30. package/dist/consent-BWHaYx5p.js +76 -0
  31. package/dist/consent-BWHaYx5p.js.map +1 -0
  32. package/dist/context-BqhRydBg.js +1234 -0
  33. package/dist/context-BqhRydBg.js.map +1 -0
  34. package/dist/daemon-DBn-shxX.js +2 -0
  35. package/dist/{daemon-entry-LTFKtpHy.js → daemon-entry-Da-D3rmH.js} +3 -4
  36. package/dist/daemon-entry-Da-D3rmH.js.map +1 -0
  37. package/dist/db-CMpBK3sv.js +1252 -0
  38. package/dist/db-CMpBK3sv.js.map +1 -0
  39. package/dist/derive-RPIsAVO4.js +474 -0
  40. package/dist/derive-RPIsAVO4.js.map +1 -0
  41. package/dist/dev-C9P5Yp9k.js +1593 -0
  42. package/dist/dev-C9P5Yp9k.js.map +1 -0
  43. package/dist/dev-db/atlas-dev-database.d.ts +32 -0
  44. package/dist/dev-db/daemon-entry.d.ts +13 -0
  45. package/dist/dev-preflight-N1evJL3S.js +2 -0
  46. package/dist/doctor-DYs-NqFI.js +771 -0
  47. package/dist/doctor-DYs-NqFI.js.map +1 -0
  48. package/dist/eject-BT6t37D0.js +335 -0
  49. package/dist/eject-BT6t37D0.js.map +1 -0
  50. package/dist/fold-static-C1EtHlfV.js +201 -0
  51. package/dist/fold-static-C1EtHlfV.js.map +1 -0
  52. package/dist/function-portability-BIvlvR9q.js +265 -0
  53. package/dist/function-portability-BIvlvR9q.js.map +1 -0
  54. package/dist/generate_sdk-UV635zSe.js +477 -0
  55. package/dist/generate_sdk-UV635zSe.js.map +1 -0
  56. package/dist/index.es.js +141 -24674
  57. package/dist/index.es.js.map +1 -1
  58. package/dist/init-fXeBcxuN.js +1042 -0
  59. package/dist/init-fXeBcxuN.js.map +1 -0
  60. package/dist/manifest-DzlC60WX.js +871 -0
  61. package/dist/manifest-DzlC60WX.js.map +1 -0
  62. package/dist/normalize-imports-CmVdE9iZ.js +100 -0
  63. package/dist/normalize-imports-CmVdE9iZ.js.map +1 -0
  64. package/dist/{package-manager-CXQevsE1.js → package-manager-DSEOwTqM.js} +2 -2
  65. package/dist/{package-manager-CXQevsE1.js.map → package-manager-DSEOwTqM.js.map} +1 -1
  66. package/dist/path-flags-DUBuI2i1.js +77 -0
  67. package/dist/path-flags-DUBuI2i1.js.map +1 -0
  68. package/dist/precompress.d.ts +17 -0
  69. package/dist/prepare-Btn9Ewbn.js +1052 -0
  70. package/dist/prepare-Btn9Ewbn.js.map +1 -0
  71. package/dist/{project-DmaGLmH2.js → project-Wp2zoyeN.js} +33 -4
  72. package/dist/project-Wp2zoyeN.js.map +1 -0
  73. package/dist/resolve-CJLkfFV0.js +2 -0
  74. package/dist/resources-DT1COn_6.js +161 -0
  75. package/dist/resources-DT1COn_6.js.map +1 -0
  76. package/dist/schema-BDBWvCHu.js +125 -0
  77. package/dist/schema-BDBWvCHu.js.map +1 -0
  78. package/dist/skills-DTFibT1m.js +642 -0
  79. package/dist/skills-DTFibT1m.js.map +1 -0
  80. package/dist/start-rU2e3Kp5.js +228 -0
  81. package/dist/start-rU2e3Kp5.js.map +1 -0
  82. package/dist/{state-C59Elrnt.js → state-Do7ZJYkF.js} +49 -4
  83. package/dist/state-Do7ZJYkF.js.map +1 -0
  84. package/dist/status-BR9oyi-y.js +351 -0
  85. package/dist/status-BR9oyi-y.js.map +1 -0
  86. package/dist/storage-DyvrSTH3.js +303 -0
  87. package/dist/storage-DyvrSTH3.js.map +1 -0
  88. package/dist/telemetry-CAWNCugs.js +338 -0
  89. package/dist/telemetry-CAWNCugs.js.map +1 -0
  90. package/dist/telemetry-DbLqGIBW.js +129 -0
  91. package/dist/telemetry-DbLqGIBW.js.map +1 -0
  92. package/dist/unknown-command-DNwDcX3w.js +98 -0
  93. package/dist/unknown-command-DNwDcX3w.js.map +1 -0
  94. package/dist/upgrade-D-5-Od96.js +1265 -0
  95. package/dist/upgrade-D-5-Od96.js.map +1 -0
  96. package/dist/utils/project.d.ts +16 -0
  97. package/dist/{version-DsgBmP22.js → version-Buyyo1ut.js} +2 -2
  98. package/dist/{version-DsgBmP22.js.map → version-Buyyo1ut.js.map} +1 -1
  99. package/package.json +7 -7
  100. package/templates/eject/backend/src/env.ts +1 -1
  101. package/templates/eject/backend/src/index.ts +10 -2
  102. package/templates/template/README.md +1 -1
  103. package/templates/template/ai-instructions.md +2 -1
  104. package/templates/template/frontend/vite.config.ts +11 -3
  105. package/templates/template/scripts/example.ts +2 -1
  106. package/dist/branch-pointer-kk9F5FBO.js +0 -111
  107. package/dist/branch-pointer-kk9F5FBO.js.map +0 -1
  108. package/dist/constraints-DKGbNfUW.js +0 -48
  109. package/dist/constraints-DKGbNfUW.js.map +0 -1
  110. package/dist/daemon-C8p32i-n.js +0 -357
  111. package/dist/daemon-C8p32i-n.js.map +0 -1
  112. package/dist/daemon-entry-LTFKtpHy.js.map +0 -1
  113. package/dist/dev-preflight-CNLl4rdo.js +0 -367
  114. package/dist/dev-preflight-CNLl4rdo.js.map +0 -1
  115. package/dist/project-DmaGLmH2.js.map +0 -1
  116. package/dist/resolve-BAeRUBhg.js +0 -74
  117. package/dist/resolve-BAeRUBhg.js.map +0 -1
  118. 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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"}
@@ -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
  *
@@ -1,5 +1,5 @@
1
- import path from "path";
2
1
  import fs from "fs";
2
+ import path from "path";
3
3
  import { fileURLToPath } from "url";
4
4
  //#region src/utils/version.ts
5
5
  /**
@@ -55,4 +55,4 @@ function cliUserAgent() {
55
55
  //#endregion
56
56
  export { cliVersion as n, cliUserAgent as t };
57
57
 
58
- //# sourceMappingURL=version-DsgBmP22.js.map
58
+ //# sourceMappingURL=version-Buyyo1ut.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version-DsgBmP22.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"}
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.24.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.24.0",
47
- "@rebasepro/codegen": "0.24.0",
48
- "@rebasepro/server": "0.24.0",
49
- "@rebasepro/types": "0.24.0",
50
- "@rebasepro/server-postgres": "0.24.0",
51
- "@rebasepro/client": "0.24.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({
@@ -93,7 +93,11 @@ app.use("/*", cors({
93
93
  "X-RateLimit-Limit",
94
94
  "X-RateLimit-Remaining",
95
95
  "X-RateLimit-Reset",
96
- "Preference-Applied"
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"
97
101
  ]
98
102
  }));
99
103
 
@@ -119,7 +123,11 @@ const resolvedDataSources = resolveDataSources(process.env, dataSources);
119
123
  async function startServer() {
120
124
  const jwtSecret = env.JWT_SECRET;
121
125
  const PORT = env.PORT;
122
- 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));
123
131
 
124
132
  // `backend/crons` holds the scheduled jobs — nightly backups among them.
125
133
  // Passed only when the directory exists, because a configured `cronsDir`
@@ -40,7 +40,7 @@ every collection declared there, and serves the API and the admin panel.
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
@@ -7,7 +7,8 @@
7
7
  | Command | What it does |
8
8
  |---|---|
9
9
  | `pnpm dev` | Backend, frontend and the managed development database, together |
10
- | `pnpm schema:generate` then `pnpm db:push` | The same loop with `pnpm dev` not running, plus the changes boot leaves alone: collections → Drizzle schema → development database |
10
+ | `pnpm schema:generate` then `pnpm generate:sdk` | The same loop with `pnpm dev` not running: collections → Drizzle schema and SDK types. The next boot creates what is missing |
11
+ | `pnpm db:push` | The changes boot leaves alone (a rename, a narrowed type, a removed field). Needs your own PostgreSQL in `DATABASE_URL`; it refuses the managed development database |
11
12
  | `pnpm db:generate` then `pnpm db:migrate` | The production path — write the migration file, then apply it |
12
13
  | `pnpm schema:introspect` | The other direction: existing tables → collection definitions |
13
14
  | `pnpm generate:sdk` | Regenerate the typed client in `generated/sdk/` from the collections. `pnpm dev` already does this on start and on every save; the script is for CI and for when `pnpm dev` is not running |
@@ -30,9 +30,9 @@ export default defineConfig({
30
30
  "@remix-run/router"
31
31
  ]
32
32
  },
33
- esbuild: {
34
- logOverride: { "this-is-undefined-in-esm": "silent" }
35
- },
33
+ // No `esbuild` block: Vite 8 transforms with oxc and ignores it, and
34
+ // having one made every `rebase dev` and build print "Both esbuild and oxc
35
+ // options were set".
36
36
  build: {
37
37
  minify: true,
38
38
  outDir: "./dist",
@@ -75,6 +75,14 @@ export default defineConfig({
75
75
  // anchor a heavy one to the critical path.
76
76
  if (id.includes("commonjsHelpers") || id.includes("commonjs-dynamic-modules")) return "vendor-commonjs-helpers";
77
77
 
78
+ // Small libraries the entry needs, named before the heavy groups. A name
79
+ // takes the unassigned dependencies of its modules with it, so
80
+ // `prism-react-renderer` took `clsx` — which the kit imports statically — and
81
+ // the entry imported 85 kB of syntax highlighter for a 633-byte helper;
82
+ // React core landed in `vendor-dnd` the same way.
83
+ if (/[\\/]node_modules[\\/](react|scheduler|use-sync-external-store)[\\/]/.test(id)) return "vendor-react";
84
+ if (/[\\/]node_modules[\\/]clsx[\\/]/.test(id)) return "vendor-clsx";
85
+
78
86
  if (id.includes("exceljs")) return "vendor-exceljs";
79
87
  if (id.includes("prosemirror")) return "vendor-prosemirror";
80
88
  if (id.includes("monaco-editor") || id.includes("@monaco-editor")) return "vendor-monaco";
@@ -30,7 +30,8 @@ import { createRebaseClient } from "@rebasepro/client";
30
30
  // import { collectionsDictionary, type Database } from "../generated/sdk/database.types";
31
31
 
32
32
  // Load .env from project root (same file the backend uses)
33
- dotenv.config({ path: path.resolve(process.cwd(), ".env") });
33
+ // `quiet`: dotenv 17 otherwise prints its own advertisement banner.
34
+ dotenv.config({ path: path.resolve(process.cwd(), ".env"), quiet: true });
34
35
 
35
36
  // ─── Resolve Backend URL ─────────────────────────────────────────────
36
37
  let baseUrl = process.env.REBASE_URL;
@@ -1,111 +0,0 @@
1
- import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import path from "path";
3
- import fs from "fs";
4
- //#region src/dev-db/branch-pointer.ts
5
- /**
6
- * Which database branch this checkout is working on.
7
- *
8
- * `rebase db branch create` made a full copy of the database in about a second
9
- * and then stopped one step short of being a feature: there was no `switch`, no
10
- * `--branch` on `rebase dev`, and nothing wrote the branch anywhere a command
11
- * would read it. The only way to *use* a branch was to hand-edit
12
- * `DATABASE_URL`, and the documentation claimed otherwise — "the CLI updates
13
- * your local development configuration" — which it did not; the `.env` was
14
- * byte-identical afterwards.
15
- *
16
- * This is that missing step, and the shape of it is chosen to avoid three
17
- * things:
18
- *
19
- * 1. **It does not touch `.env`.** That file holds secrets, comments and the
20
- * developer's own ordering, and a command that rewrites it in place will
21
- * eventually lose something that was not its business. The branch is
22
- * recorded beside the other per-checkout state in `.rebase/`, which is
23
- * already gitignored — a branch is a fact about one machine, never about
24
- * the project.
25
- *
26
- * 2. **It stores a name, not a connection string.** The credentials stay in
27
- * exactly one place; the URL is derived by swapping the database name on
28
- * the base one at resolution time. A stored URL would be a second copy of
29
- * the password, and would go stale the moment `.env` changed.
30
- *
31
- * 3. **It does not outrank an explicit instruction.** `--database-url` and a
32
- * `DATABASE_URL` in the shell are more immediate and more specific than a
33
- * switch made yesterday, so they still win. The pointer sits directly above
34
- * the project's `.env`: it is a deliberate, persistent choice, and `.env` is
35
- * the project default it is meant to override. Anything less and `switch`
36
- * would silently do nothing on every project that sets `DATABASE_URL` —
37
- * which is every project not using the managed database.
38
- */
39
- var branch_pointer_exports = /* @__PURE__ */ __exportAll({
40
- BRANCH_DB_PREFIX: () => "rb_",
41
- branchDatabaseName: () => branchDatabaseName,
42
- branchPointerPath: () => branchPointerPath,
43
- branchUrl: () => branchUrl,
44
- clearActiveBranch: () => clearActiveBranch,
45
- databaseNameOf: () => databaseNameOf,
46
- readActiveBranch: () => readActiveBranch,
47
- writeActiveBranch: () => writeActiveBranch
48
- });
49
- /** Where the pointer lives, next to the rest of the per-checkout state. */
50
- function branchPointerPath(projectRoot) {
51
- return path.join(projectRoot, ".rebase", "branch.json");
52
- }
53
- function branchDatabaseName(name) {
54
- return `rb_${name}`;
55
- }
56
- /** Read the active branch, or null when the checkout is on the main database. */
57
- function readActiveBranch(projectRoot) {
58
- try {
59
- const raw = fs.readFileSync(branchPointerPath(projectRoot), "utf-8");
60
- const parsed = JSON.parse(raw);
61
- if (typeof parsed.name !== "string" || typeof parsed.database !== "string") return null;
62
- if (!parsed.name || !parsed.database) return null;
63
- return {
64
- name: parsed.name,
65
- database: parsed.database
66
- };
67
- } catch {
68
- return null;
69
- }
70
- }
71
- function writeActiveBranch(projectRoot, branch) {
72
- const file = branchPointerPath(projectRoot);
73
- fs.mkdirSync(path.dirname(file), { recursive: true });
74
- fs.writeFileSync(file, `${JSON.stringify(branch, null, 2)}\n`, "utf-8");
75
- }
76
- /** Return to the main database. Absent is success — this is idempotent. */
77
- function clearActiveBranch(projectRoot) {
78
- fs.rmSync(branchPointerPath(projectRoot), { force: true });
79
- }
80
- /**
81
- * The base connection string with its database swapped for the branch's.
82
- *
83
- * Everything else is carried across untouched — credentials, host, port, and
84
- * the query string, which is load-bearing here: `?sslmode=disable` is what a
85
- * local Docker Postgres needs, and dropping it turns a switch into a TLS error
86
- * that says nothing about branches.
87
- *
88
- * Returns null for a connection string that cannot be parsed, so the caller can
89
- * say so plainly rather than emitting a mangled URL that fails later.
90
- */
91
- function branchUrl(baseUrl, database) {
92
- try {
93
- const url = new URL(baseUrl);
94
- url.pathname = `/${database}`;
95
- return url.toString();
96
- } catch {
97
- return null;
98
- }
99
- }
100
- /** The database name in a connection string, for reporting what you are on. */
101
- function databaseNameOf(connectionString) {
102
- try {
103
- return new URL(connectionString).pathname.replace(/^\//, "") || null;
104
- } catch {
105
- return null;
106
- }
107
- }
108
- //#endregion
109
- export { readActiveBranch as i, branch_pointer_exports as n, databaseNameOf as r, branchUrl as t };
110
-
111
- //# sourceMappingURL=branch-pointer-kk9F5FBO.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"branch-pointer-kk9F5FBO.js","names":[],"sources":["../src/dev-db/branch-pointer.ts"],"sourcesContent":["/**\n * Which database branch this checkout is working on.\n *\n * `rebase db branch create` made a full copy of the database in about a second\n * and then stopped one step short of being a feature: there was no `switch`, no\n * `--branch` on `rebase dev`, and nothing wrote the branch anywhere a command\n * would read it. The only way to *use* a branch was to hand-edit\n * `DATABASE_URL`, and the documentation claimed otherwise — \"the CLI updates\n * your local development configuration\" — which it did not; the `.env` was\n * byte-identical afterwards.\n *\n * This is that missing step, and the shape of it is chosen to avoid three\n * things:\n *\n * 1. **It does not touch `.env`.** That file holds secrets, comments and the\n * developer's own ordering, and a command that rewrites it in place will\n * eventually lose something that was not its business. The branch is\n * recorded beside the other per-checkout state in `.rebase/`, which is\n * already gitignored — a branch is a fact about one machine, never about\n * the project.\n *\n * 2. **It stores a name, not a connection string.** The credentials stay in\n * exactly one place; the URL is derived by swapping the database name on\n * the base one at resolution time. A stored URL would be a second copy of\n * the password, and would go stale the moment `.env` changed.\n *\n * 3. **It does not outrank an explicit instruction.** `--database-url` and a\n * `DATABASE_URL` in the shell are more immediate and more specific than a\n * switch made yesterday, so they still win. The pointer sits directly above\n * the project's `.env`: it is a deliberate, persistent choice, and `.env` is\n * the project default it is meant to override. Anything less and `switch`\n * would silently do nothing on every project that sets `DATABASE_URL` —\n * which is every project not using the managed database.\n */\n\nimport fs from \"fs\";\nimport path from \"path\";\n\n/** Where the pointer lives, next to the rest of the per-checkout state. */\nexport function branchPointerPath(projectRoot: string): string {\n return path.join(projectRoot, \".rebase\", \"branch.json\");\n}\n\nexport interface ActiveBranch {\n /** The name the developer typed. */\n name: string;\n /** The PostgreSQL database that name refers to. */\n database: string;\n}\n\n/**\n * The prefix `BranchService` puts on every branch database.\n *\n * Duplicated from the driver rather than imported because the CLI must answer\n * \"which database\" without loading a database driver — `rebase dev` reads this\n * before it knows which plugin the project uses. It is covered by a test that\n * fails if the driver's prefix moves.\n */\nexport const BRANCH_DB_PREFIX = \"rb_\";\n\nexport function branchDatabaseName(name: string): string {\n return `${BRANCH_DB_PREFIX}${name}`;\n}\n\n/** Read the active branch, or null when the checkout is on the main database. */\nexport function readActiveBranch(projectRoot: string): ActiveBranch | null {\n try {\n const raw = fs.readFileSync(branchPointerPath(projectRoot), \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<ActiveBranch>;\n if (typeof parsed.name !== \"string\" || typeof parsed.database !== \"string\") return null;\n if (!parsed.name || !parsed.database) return null;\n\n return { name: parsed.name, database: parsed.database };\n } catch {\n // Absent is the common case and is not an error. A corrupt file is\n // treated the same way: the answer is \"no branch\", which is the state\n // the developer can always get back to with `branch switch --off`.\n return null;\n }\n}\n\nexport function writeActiveBranch(projectRoot: string, branch: ActiveBranch): void {\n const file = branchPointerPath(projectRoot);\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, `${JSON.stringify(branch, null, 2)}\\n`, \"utf-8\");\n}\n\n/** Return to the main database. Absent is success — this is idempotent. */\nexport function clearActiveBranch(projectRoot: string): void {\n fs.rmSync(branchPointerPath(projectRoot), { force: true });\n}\n\n/**\n * The base connection string with its database swapped for the branch's.\n *\n * Everything else is carried across untouched — credentials, host, port, and\n * the query string, which is load-bearing here: `?sslmode=disable` is what a\n * local Docker Postgres needs, and dropping it turns a switch into a TLS error\n * that says nothing about branches.\n *\n * Returns null for a connection string that cannot be parsed, so the caller can\n * say so plainly rather than emitting a mangled URL that fails later.\n */\nexport function branchUrl(baseUrl: string, database: string): string | null {\n try {\n const url = new URL(baseUrl);\n // `pathname` keeps its leading slash; a URL with no database at all\n // still gets one, which is what connecting to a named branch means.\n url.pathname = `/${database}`;\n\n return url.toString();\n } catch {\n return null;\n }\n}\n\n/** The database name in a connection string, for reporting what you are on. */\nexport function databaseNameOf(connectionString: string): string | null {\n try {\n const name = new URL(connectionString).pathname.replace(/^\\//, \"\");\n\n return name || null;\n } catch {\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,SAAgB,kBAAkB,aAA6B;CAC3D,OAAO,KAAK,KAAK,aAAa,WAAW,aAAa;AAC1D;AAmBA,SAAgB,mBAAmB,MAAsB;CACrD,OAAO,MAAsB;AACjC;;AAGA,SAAgB,iBAAiB,aAA0C;CACvE,IAAI;EACA,MAAM,MAAM,GAAG,aAAa,kBAAkB,WAAW,GAAG,OAAO;EACnE,MAAM,SAAS,KAAK,MAAM,GAAG;EAC7B,IAAI,OAAO,OAAO,SAAS,YAAY,OAAO,OAAO,aAAa,UAAU,OAAO;EACnF,IAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,UAAU,OAAO;EAE7C,OAAO;GAAE,MAAM,OAAO;GAAM,UAAU,OAAO;EAAS;CAC1D,QAAQ;EAIJ,OAAO;CACX;AACJ;AAEA,SAAgB,kBAAkB,aAAqB,QAA4B;CAC/E,MAAM,OAAO,kBAAkB,WAAW;CAC1C,GAAG,UAAU,KAAK,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;CACpD,GAAG,cAAc,MAAM,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,KAAK,OAAO;AAC1E;;AAGA,SAAgB,kBAAkB,aAA2B;CACzD,GAAG,OAAO,kBAAkB,WAAW,GAAG,EAAE,OAAO,KAAK,CAAC;AAC7D;;;;;;;;;;;;AAaA,SAAgB,UAAU,SAAiB,UAAiC;CACxE,IAAI;EACA,MAAM,MAAM,IAAI,IAAI,OAAO;EAG3B,IAAI,WAAW,IAAI;EAEnB,OAAO,IAAI,SAAS;CACxB,QAAQ;EACJ,OAAO;CACX;AACJ;;AAGA,SAAgB,eAAe,kBAAyC;CACpE,IAAI;EAGA,OAFa,IAAI,IAAI,gBAAgB,CAAC,CAAC,SAAS,QAAQ,OAAO,EAExD,KAAQ;CACnB,QAAQ;EACJ,OAAO;CACX;AACJ"}
@@ -1,48 +0,0 @@
1
- //#region src/dev-db/constraints.ts
2
- /**
3
- * Extensions to hand PGlite's constructor.
4
- *
5
- * `CREATE EXTENSION` alone cannot install these — PGlite resolves them from
6
- * bundles supplied at construction time, so anything missing here is missing
7
- * from the database no matter what the migration says.
8
- *
9
- * The module is spelled out per extension rather than derived from the name,
10
- * because they do not all live in the same place: the two contrib ones are
11
- * subpaths of PGlite itself, and pgvector is a package of its own. Deriving the
12
- * path is what left `vector` off this list — `@electric-sql/pglite/contrib/vector`
13
- * does not exist, so a project declaring a `{ type: "vector" }` property could
14
- * not use the managed dev database at all.
15
- */
16
- var PGLITE_EXTENSIONS = [
17
- {
18
- name: "pg_trgm",
19
- module: "@electric-sql/pglite/contrib/pg_trgm",
20
- export: "pg_trgm"
21
- },
22
- {
23
- name: "unaccent",
24
- module: "@electric-sql/pglite/contrib/unaccent",
25
- export: "unaccent"
26
- },
27
- {
28
- name: "vector",
29
- module: "@electric-sql/pglite-pgvector",
30
- export: "vector"
31
- }
32
- ];
33
- /**
34
- * Announced at startup, every time, rather than discovered.
35
- *
36
- * A developer who does not know realtime is off will read the silence as a bug
37
- * in their own code, which is a worse outcome than not offering the managed
38
- * database at all.
39
- */
40
- var MANAGED_LIMITATIONS = [{
41
- id: "concurrency",
42
- summary: "Requests are served one at a time. Behaviour is correct but serialized, so lock contention and job-queue concurrency cannot be reproduced here.",
43
- remedy: "Reproduce concurrency against a real Postgres: rebase dev --docker"
44
- }];
45
- //#endregion
46
- export { PGLITE_EXTENSIONS as n, MANAGED_LIMITATIONS as t };
47
-
48
- //# sourceMappingURL=constraints-DKGbNfUW.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"constraints-DKGbNfUW.js","names":[],"sources":["../src/dev-db/constraints.ts"],"sourcesContent":["/**\n * What PGlite can and cannot do as a development database, measured rather\n * than assumed.\n *\n * Everything in this directory is shaped by four facts, each established by\n * running it against `@electric-sql/pglite` 0.5.6 and\n * `@electric-sql/pglite-socket` 0.2.9 rather than by reading their docs. They\n * are recorded here because two of them are silent failures — the kind that\n * make a developer lose an evening to a feature that reports success and does\n * nothing.\n *\n * 1. **It is really PostgreSQL 18.3.** `select version()` over the socket\n * returns `PostgreSQL 18.3 (PGlite 0.5.6) on wasm32`, which is the same\n * major as the `postgres:18-alpine` the eject template ships. So a dev\n * database here and a compose database there are the same Postgres, and\n * schema behaviour does not diverge between them.\n *\n * 2. **`pg_trgm` and `unaccent` are available**, which is what search\n * collections need. They are not installed by a bare `CREATE EXTENSION`,\n * though — PGlite ships them as separate bundles that must be passed to the\n * constructor, and without that `CREATE EXTENSION pg_trgm` fails with\n * `extension \"pg_trgm\" is not available`. {@link PGLITE_EXTENSIONS} is that\n * list, and it has to stay in step with what the schema generator emits.\n *\n * 3. **RLS is enforced exactly as it is on a real server.** With\n * `SET LOCAL ROLE \"rebase_user\"` inside a transaction — which is how\n * `PostgresBackendDriver` isolates every request — `current_user` becomes\n * the restricted role, `session_user` stays the owner, and a policy using\n * `current_setting('app.tenant')` filters rows correctly, including under\n * `FORCE ROW LEVEL SECURITY`. Measured: an owner saw 3 rows and the\n * role-switched transaction saw 2, with the cross-tenant probe returning 0.\n * This is the one that mattered most: a dev database that quietly failed to\n * apply RLS would give false confidence about the product's central claim.\n *\n * 4. **Concurrency is the real limit, and it fails badly.** PGlite is a single\n * session, and `PGLiteSocketServer` multiplexes connections onto it. Two\n * pooled clients that hold *overlapping transactions* deadlock — not error,\n * hang — which is precisely what a request-per-transaction server does under\n * any concurrent load. {@link MANAGED_POOL_MAX} is the answer: one client\n * connection, so requests queue in the pool instead of deadlocking in the\n * multiplexer. Measured: with a pool of 1, four concurrent queries and a\n * role-switched RLS transaction all pass; with a pool of 5 the same script\n * hangs indefinitely.\n *\n * 5. **LISTEN/NOTIFY needed repairing, and now works.** A notification is an\n * asynchronous message with no request to answer, and the multiplexer hands\n * it to whichever socket is reading rather than to the one that issued\n * `LISTEN` — so a dedicated listener connection, which is exactly how the\n * realtime engine works, received nothing while the *writer* received\n * notifications it never asked for. `notification-proxy.ts` corrects that by\n * copying every `NotificationResponse` frame to every client, which for a\n * single-session database is simply the truth. Realtime therefore works\n * against the managed database, with no change to the server: it does\n * ordinary `LISTEN` over ordinary libpq.\n */\n\n/** One extension bundle, and where to import it from. */\nexport interface PgliteExtension {\n /** The name `CREATE EXTENSION` uses, and the key PGlite is handed. */\n name: string;\n /** Module the bundle is imported from. */\n module: string;\n /** The named export carrying the bundle. */\n export: string;\n}\n\n/**\n * Extensions to hand PGlite's constructor.\n *\n * `CREATE EXTENSION` alone cannot install these — PGlite resolves them from\n * bundles supplied at construction time, so anything missing here is missing\n * from the database no matter what the migration says.\n *\n * The module is spelled out per extension rather than derived from the name,\n * because they do not all live in the same place: the two contrib ones are\n * subpaths of PGlite itself, and pgvector is a package of its own. Deriving the\n * path is what left `vector` off this list — `@electric-sql/pglite/contrib/vector`\n * does not exist, so a project declaring a `{ type: \"vector\" }` property could\n * not use the managed dev database at all.\n */\nexport const PGLITE_EXTENSIONS: readonly PgliteExtension[] = [\n { name: \"pg_trgm\", module: \"@electric-sql/pglite/contrib/pg_trgm\", export: \"pg_trgm\" },\n { name: \"unaccent\", module: \"@electric-sql/pglite/contrib/unaccent\", export: \"unaccent\" },\n { name: \"vector\", module: \"@electric-sql/pglite-pgvector\", export: \"vector\" }\n];\n\n/**\n * Client connections the managed database tolerates: exactly one.\n *\n * Not a tuning choice. Two concurrent transactions over the socket\n * multiplexer deadlock, and a request-per-transaction server produces those\n * the moment two requests overlap. One connection converts that deadlock into\n * ordinary queueing, which is slower and correct.\n */\nexport const MANAGED_POOL_MAX = 1;\n\n/**\n * Connections the socket server will accept.\n *\n * Above {@link MANAGED_POOL_MAX} so that a second *non-transactional* client —\n * `rebase db push` in another terminal while `rebase dev` runs — is refused\n * with a connection error rather than corrupting the multiplexer. The pool\n * limit is what prevents overlapping transactions; this only stops a stampede.\n */\nexport const MANAGED_SERVER_MAX_CONNECTIONS = 4;\n\n/** What a managed PGlite database cannot do, in the words the user needs. */\nexport interface ManagedLimitation {\n /** Stable id, so a warning can be suppressed or tested for. */\n id: string;\n /** One line, naming the feature rather than the mechanism. */\n summary: string;\n /** What to do instead. Always a concrete command. */\n remedy: string;\n}\n\n/**\n * Announced at startup, every time, rather than discovered.\n *\n * A developer who does not know realtime is off will read the silence as a bug\n * in their own code, which is a worse outcome than not offering the managed\n * database at all.\n */\nexport const MANAGED_LIMITATIONS: readonly ManagedLimitation[] = [\n {\n id: \"concurrency\",\n summary:\n \"Requests are served one at a time. Behaviour is correct but serialized, so \" +\n \"lock contention and job-queue concurrency cannot be reproduced here.\",\n remedy: \"Reproduce concurrency against a real Postgres: rebase dev --docker\"\n }\n] as const;\n"],"mappings":";;;;;;;;;;;;;;;AAgFA,IAAa,oBAAgD;CACzD;EAAE,MAAM;EAAW,QAAQ;EAAwC,QAAQ;CAAU;CACrF;EAAE,MAAM;EAAY,QAAQ;EAAyC,QAAQ;CAAW;CACxF;EAAE,MAAM;EAAU,QAAQ;EAAiC,QAAQ;CAAS;AAChF;;;;;;;;AAuCA,IAAa,sBAAoD,CAC7D;CACI,IAAI;CACJ,SACI;CAEJ,QAAQ;AACZ,CACJ"}