@rebasepro/cli 0.12.1-canary.g8b4f68e → 0.12.1-canary.gcc9d592

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.
package/bin/rebase.js CHANGED
@@ -88,4 +88,30 @@ if (!existsSync(distEntry)) {
88
88
 
89
89
  const { entry } = await import("../dist/index.es.js");
90
90
 
91
- entry(process.argv);
91
+ /**
92
+ * The CLI's last line of defence.
93
+ *
94
+ * `entry()` returns a promise and nothing was awaiting it, so anything a
95
+ * command threw surfaced as an unhandled rejection: Node's own stack trace,
96
+ * rooted in `dist/index.es.js`, with the CLI's bundled line numbers and no
97
+ * exit code of its own. "Collections directory not found" is a sentence a
98
+ * developer can act on; the same sentence under ten frames of bundle internals
99
+ * reads as a crash in Rebase.
100
+ *
101
+ * The message is the error's own — commands that already print something
102
+ * friendly and exit never reach here. The stack is available behind
103
+ * `--debug`/`REBASE_DEBUG`, because when the message is *not* enough that is
104
+ * the only thing that helps.
105
+ */
106
+ const wantsStack = process.argv.includes("--debug") || process.env.REBASE_DEBUG === "1";
107
+
108
+ entry(process.argv).catch((error) => {
109
+ const message = error instanceof Error ? error.message : String(error);
110
+ process.stderr.write(`\x1b[31m✗ ${message}\x1b[0m\n`);
111
+ if (wantsStack && error instanceof Error && error.stack) {
112
+ process.stderr.write(`\n${error.stack}\n`);
113
+ } else {
114
+ process.stderr.write("\x1b[90m Re-run with --debug for the stack trace.\x1b[0m\n");
115
+ }
116
+ process.exit(1);
117
+ });
package/dist/bundle.d.ts CHANGED
@@ -68,6 +68,41 @@ export declare function detectNativeDependencies(projectRoot: string, declared:
68
68
  * own config package already travels inside the bundle.
69
69
  */
70
70
  export declare function collectDeclaredDependencies(projectRoot: string): Record<string, string>;
71
+ /** One `@rebasepro/*` dependency as some package.json in the project declares it. */
72
+ export interface DeclaredFrameworkDep {
73
+ name: string;
74
+ range: string;
75
+ /** Project-relative package.json it was declared in. */
76
+ file: string;
77
+ }
78
+ export interface FrameworkDepDrift {
79
+ /** Declared at a version that can never reach the CLI's own. */
80
+ behind: DeclaredFrameworkDep[];
81
+ /**
82
+ * The distinct lower bounds found across all declared `@rebasepro/*`, when
83
+ * there is more than one — the project is pinning mixed-era framework
84
+ * packages against each other.
85
+ */
86
+ disagreeing: string[];
87
+ }
88
+ /**
89
+ * Find `@rebasepro/*` dependencies pinned to a version older than this CLI.
90
+ *
91
+ * This is the only place a developer can be told. In development, every
92
+ * `@rebasepro/*` resolves through pnpm's `link:`/`workspace:` overrides to the
93
+ * checkout, so the version STRINGS in package.json are never exercised — the
94
+ * project runs fine locally on whatever is on disk, and the declared numbers are
95
+ * first honoured when the runtime npm-installs them from a bundle in the cloud.
96
+ * A project scaffolded at 0.10.0 therefore keeps working on a developer's
97
+ * machine indefinitely while being, in the cloud, a 0.10.0 driver.
98
+ *
99
+ * That matters because the image supplies only `@rebasepro/server`; the database
100
+ * driver comes from these declarations and a newer runtime never updates it.
101
+ * Every package.json is scanned, `dependencies` and `devDependencies` both,
102
+ * because they have to be bumped together and the one that gets forgotten is the
103
+ * one nobody looks at.
104
+ */
105
+ export declare function detectFrameworkDepDrift(projectRoot: string, cliVersion: string): FrameworkDepDrift;
71
106
  /**
72
107
  * Rewrite relative import specifiers in emitted JavaScript so Node can resolve them.
73
108
  *
@@ -182,3 +217,4 @@ export declare function buildStaticBundle(options: {
182
217
  manifest: RebaseBundleManifest;
183
218
  fileCount: number;
184
219
  };
220
+ export declare function resolveCliVersion(): string;
package/dist/index.es.js CHANGED
@@ -3515,6 +3515,139 @@ function collectDeclaredDependencies(projectRoot) {
3515
3515
  return declared;
3516
3516
  }
3517
3517
  /**
3518
+ * Lowest version a range could resolve to, or null if it is not a range.
3519
+ *
3520
+ * Kept deliberately tiny and local. The published range grammar here is a caret,
3521
+ * a tilde, an exact version or a `>=` floor, and the alternative — a semver
3522
+ * dependency in the CLI — buys breadth this does not need.
3523
+ */
3524
+ function lowerBoundOf(range) {
3525
+ const raw = range.trim().replace(/^[\^~]/, "").replace(/^>=\s*/, "").replace(/^v/, "");
3526
+ if (!/^\d+(\.\d+){0,2}$/.test(raw)) return null;
3527
+ const [major, minor = 0, patch = 0] = raw.split(".").map(Number);
3528
+ return [
3529
+ major,
3530
+ minor,
3531
+ patch
3532
+ ];
3533
+ }
3534
+ /** Highest version a range could resolve to (exclusive), or null. */
3535
+ function upperBoundOf(range) {
3536
+ const trimmed = range.trim();
3537
+ const min = lowerBoundOf(trimmed);
3538
+ if (!min) return null;
3539
+ if (trimmed.startsWith(">=")) return null;
3540
+ const [major, minor, patch] = min;
3541
+ if (trimmed.startsWith("^")) {
3542
+ if (major > 0) return [
3543
+ major + 1,
3544
+ 0,
3545
+ 0
3546
+ ];
3547
+ if (minor > 0) return [
3548
+ 0,
3549
+ minor + 1,
3550
+ 0
3551
+ ];
3552
+ return [
3553
+ 0,
3554
+ 0,
3555
+ patch + 1
3556
+ ];
3557
+ }
3558
+ if (trimmed.startsWith("~")) return trimmed.replace(/^~v?/, "").split(".").length >= 2 ? [
3559
+ major,
3560
+ minor + 1,
3561
+ 0
3562
+ ] : [
3563
+ major + 1,
3564
+ 0,
3565
+ 0
3566
+ ];
3567
+ const parts = trimmed.replace(/^v/, "").split(".").length;
3568
+ if (parts === 1) return [
3569
+ major + 1,
3570
+ 0,
3571
+ 0
3572
+ ];
3573
+ if (parts === 2) return [
3574
+ major,
3575
+ minor + 1,
3576
+ 0
3577
+ ];
3578
+ return [
3579
+ major,
3580
+ minor,
3581
+ patch + 1
3582
+ ];
3583
+ }
3584
+ function compareTriples(a, b) {
3585
+ for (let i = 0; i < 3; i++) if (a[i] !== b[i]) return a[i] < b[i] ? -1 : 1;
3586
+ return 0;
3587
+ }
3588
+ /**
3589
+ * Whether a declared range could EVER resolve at or above `target`.
3590
+ *
3591
+ * The same question the control plane asks at intake, asked here first. Only a
3592
+ * range whose entire span sits below the target is reported — `^0.10.0` can
3593
+ * never cross to 0.12 whatever npm publishes — because a false alarm on a build
3594
+ * that would have worked trains people to ignore the warning that matters.
3595
+ */
3596
+ function canReach(range, target) {
3597
+ const ceiling = upperBoundOf(range);
3598
+ const floor = lowerBoundOf(target);
3599
+ if (!floor || !lowerBoundOf(range)) return null;
3600
+ if (!ceiling) return true;
3601
+ return compareTriples(ceiling, floor) > 0;
3602
+ }
3603
+ /**
3604
+ * Find `@rebasepro/*` dependencies pinned to a version older than this CLI.
3605
+ *
3606
+ * This is the only place a developer can be told. In development, every
3607
+ * `@rebasepro/*` resolves through pnpm's `link:`/`workspace:` overrides to the
3608
+ * checkout, so the version STRINGS in package.json are never exercised — the
3609
+ * project runs fine locally on whatever is on disk, and the declared numbers are
3610
+ * first honoured when the runtime npm-installs them from a bundle in the cloud.
3611
+ * A project scaffolded at 0.10.0 therefore keeps working on a developer's
3612
+ * machine indefinitely while being, in the cloud, a 0.10.0 driver.
3613
+ *
3614
+ * That matters because the image supplies only `@rebasepro/server`; the database
3615
+ * driver comes from these declarations and a newer runtime never updates it.
3616
+ * Every package.json is scanned, `dependencies` and `devDependencies` both,
3617
+ * because they have to be bumped together and the one that gets forgotten is the
3618
+ * one nobody looks at.
3619
+ */
3620
+ function detectFrameworkDepDrift(projectRoot, cliVersion) {
3621
+ const found = [];
3622
+ for (const relative of [
3623
+ "package.json",
3624
+ "backend/package.json",
3625
+ "config/package.json",
3626
+ "frontend/package.json"
3627
+ ]) {
3628
+ const file = path.join(projectRoot, relative);
3629
+ if (!fs.existsSync(file)) continue;
3630
+ try {
3631
+ const pkg = JSON.parse(fs.readFileSync(file, "utf8"));
3632
+ for (const block of [pkg.dependencies, pkg.devDependencies]) for (const [name, range] of Object.entries(block ?? {})) {
3633
+ if (!name.startsWith("@rebasepro/")) continue;
3634
+ if (typeof range !== "string") continue;
3635
+ found.push({
3636
+ name,
3637
+ range,
3638
+ file: relative
3639
+ });
3640
+ }
3641
+ } catch {}
3642
+ }
3643
+ const behind = found.filter((d) => canReach(d.range, cliVersion) === false);
3644
+ const bounds = new Set(found.map((d) => lowerBoundOf(d.range)).filter((b) => b != null).map((b) => b.join(".")));
3645
+ return {
3646
+ behind,
3647
+ disagreeing: bounds.size > 1 ? [...bounds].sort() : []
3648
+ };
3649
+ }
3650
+ /**
3518
3651
  * Rewrite relative import specifiers in emitted JavaScript so Node can resolve them.
3519
3652
  *
3520
3653
  * TypeScript deliberately does not touch specifiers: `moduleResolution: "bundler"`
@@ -4212,6 +4345,16 @@ async function buildCommand(rawArgs = []) {
4212
4345
  console.log(chalk.yellow(` ⚠ native dependencies detected: ${names}`));
4213
4346
  console.log(chalk.dim(" These cannot run on the managed runtime. See `rebase doctor`."));
4214
4347
  }
4348
+ const drift = detectFrameworkDepDrift(projectRoot, resolveCliVersion());
4349
+ if (drift.behind.length > 0) {
4350
+ console.log(chalk.yellow(` ⚠ framework dependencies older than this CLI (${resolveCliVersion()}):`));
4351
+ for (const dep of drift.behind) console.log(chalk.dim(` ${dep.name}@${dep.range} (${dep.file})`));
4352
+ console.log(chalk.dim(" The image supplies the server, but your bundle supplies the database"));
4353
+ console.log(chalk.dim(" driver — a newer runtime does not update it. Bump these and rebuild."));
4354
+ } else if (drift.disagreeing.length > 0) {
4355
+ console.log(chalk.yellow(` ⚠ mixed @rebasepro versions declared: ${drift.disagreeing.join(", ")}`));
4356
+ console.log(chalk.dim(" These are published together and expect to run together; pin them alike."));
4357
+ }
4215
4358
  if (!args["--no-static"]) {
4216
4359
  const folded = await foldFrontendIntoBundle({
4217
4360
  projectRoot,
@@ -5070,7 +5213,7 @@ function parseAgentFlags(rawArgs) {
5070
5213
  return requested;
5071
5214
  }
5072
5215
  async function skillsInstall(rawArgs = []) {
5073
- const projectDir = process.cwd();
5216
+ const projectDir = findProjectRoot() ?? process.cwd();
5074
5217
  let skillsDir;
5075
5218
  try {
5076
5219
  skillsDir = getSkillsSourceDir();
@@ -5114,7 +5257,8 @@ async function skillsInstall(rawArgs = []) {
5114
5257
  for (const agentKey of agents) {
5115
5258
  const agent = AGENTS[agentKey];
5116
5259
  const count = installForAgent(agentKey, skills, projectDir);
5117
- console.log(` ${chalk.green("✓")} ${chalk.bold(agent.label)} — ${count} skills installed to ${chalk.gray(agent.targetDir)}`);
5260
+ const shown = path.relative(process.cwd(), path.join(projectDir, agent.targetDir)) || agent.targetDir;
5261
+ console.log(` ${chalk.green("✓")} ${chalk.bold(agent.label)} — ${count} skills installed to ${chalk.gray(shown)}`);
5118
5262
  }
5119
5263
  console.log("");
5120
5264
  console.log(chalk.gray(" Skills are project-local. Commit them to share with your team."));
@@ -9885,9 +10029,10 @@ async function entry(args) {
9885
10029
  argv: args.slice(3),
9886
10030
  permissive: true
9887
10031
  });
10032
+ const sdkRoot = sdkArgs["--help"] ? process.cwd() : requireProjectRoot();
9888
10033
  await generateSdkCommand({
9889
- collectionsDir: sdkArgs["--collections-dir"] || "./config/collections",
9890
- output: sdkArgs["--output"] || "./generated/sdk",
10034
+ collectionsDir: sdkArgs["--collections-dir"] || path.join(sdkRoot, "config/collections"),
10035
+ output: sdkArgs["--output"] || path.join(sdkRoot, "generated/sdk"),
9891
10036
  from: sdkArgs["--from"],
9892
10037
  token: sdkArgs["--token"],
9893
10038
  help: sdkArgs["--help"],
@@ -9997,6 +10142,6 @@ ${chalk.gray("Documentation: https://rebase.pro/docs")}
9997
10142
  `);
9998
10143
  }
9999
10144
  //#endregion
10000
- export { CURRENT_RUNTIME_RANGE, DEFAULT_BUNDLE_DIR, DEFAULT_CONFIG_DIR, DEFAULT_CRONS_DIR, DEFAULT_FUNCTIONS_DIR, DEFAULT_SCHEMA_FILE, MANIFEST_FILENAME, ManifestError, TEMPLATE_PLACEHOLDER_FILES, appsCommand, assessManagedCompatibility, authCommand, buildBundle, buildCommand, buildInitQuestions, buildStaticBundle, buildableApps, cloudCommand, collectDeclaredDependencies, configureEnvFile, createRebaseApp, dbCommand, detectNativeDependencies, detectPackageManager, detectStorageAuthorize, devCommand, doctorCommand, ejectCommand, entry, findBackendApp, findBackendDir, findEnvFile, findFrontendDir, findProjectRoot, findUnusedServerEntry, foldStaticIntoBundle, formatCdTarget, generateSdkCommand, getActiveBackendPlugin, getPMCommands, isIdentifierLike, isPnpmAvailable, loadManifest, manifestExists, manifestPath, normalizeEsmSpecifiers, pnpmAvailabilityFromProbe, printInitHelp, requireBackendDir, requireProjectRoot, resetPnpmAvailabilityCache, resolveBackendPaths, resolveExampleBaseUrl, resolveLocalBin, resolvePluginCliScript, resolveTsx, schemaCommand, startCommand, synthesizeManifest, validateManifest, validateProjectName, validateTsxInstallation, writeManifest };
10145
+ export { CURRENT_RUNTIME_RANGE, DEFAULT_BUNDLE_DIR, DEFAULT_CONFIG_DIR, DEFAULT_CRONS_DIR, DEFAULT_FUNCTIONS_DIR, DEFAULT_SCHEMA_FILE, MANIFEST_FILENAME, ManifestError, TEMPLATE_PLACEHOLDER_FILES, appsCommand, assessManagedCompatibility, authCommand, buildBundle, buildCommand, buildInitQuestions, buildStaticBundle, buildableApps, cloudCommand, collectDeclaredDependencies, configureEnvFile, createRebaseApp, dbCommand, detectFrameworkDepDrift, detectNativeDependencies, detectPackageManager, detectStorageAuthorize, devCommand, doctorCommand, ejectCommand, entry, findBackendApp, findBackendDir, findEnvFile, findFrontendDir, findProjectRoot, findUnusedServerEntry, foldStaticIntoBundle, formatCdTarget, generateSdkCommand, getActiveBackendPlugin, getPMCommands, isIdentifierLike, isPnpmAvailable, loadManifest, manifestExists, manifestPath, normalizeEsmSpecifiers, pnpmAvailabilityFromProbe, printInitHelp, requireBackendDir, requireProjectRoot, resetPnpmAvailabilityCache, resolveBackendPaths, resolveCliVersion, resolveExampleBaseUrl, resolveLocalBin, resolvePluginCliScript, resolveTsx, schemaCommand, startCommand, synthesizeManifest, validateManifest, validateProjectName, validateTsxInstallation, writeManifest };
10001
10146
 
10002
10147
  //# sourceMappingURL=index.es.js.map