@rebasepro/cli 0.0.1-canary.892f711 → 0.0.1-canary.a6becfb

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/dist/index.es.js CHANGED
@@ -11,6 +11,45 @@ import crypto from "crypto";
11
11
  import { generateSDK } from "@rebasepro/sdk-generator";
12
12
  import { execSync, spawn } from "child_process";
13
13
  import * as os from "os";
14
+ function detectPackageManager(targetDir) {
15
+ const userAgent = process.env.npm_config_user_agent ?? "";
16
+ if (userAgent.startsWith("npm/")) return "npm";
17
+ if (userAgent.startsWith("pnpm/")) return "pnpm";
18
+ if (targetDir) {
19
+ if (fs.existsSync(path.join(targetDir, "package-lock.json"))) return "npm";
20
+ if (fs.existsSync(path.join(targetDir, "pnpm-lock.yaml"))) return "pnpm";
21
+ }
22
+ const cwd = process.cwd();
23
+ if (cwd !== targetDir) {
24
+ if (fs.existsSync(path.join(cwd, "package-lock.json"))) return "npm";
25
+ if (fs.existsSync(path.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
26
+ }
27
+ return "pnpm";
28
+ }
29
+ function getPMCommands(pm) {
30
+ if (pm === "npm") {
31
+ return {
32
+ name: "npm",
33
+ install: ["npm", "install"],
34
+ run: (script) => ["npm", "run", script],
35
+ exec: (bin, args) => ["npx", bin, ...args],
36
+ view: (pkg, field) => ["npm", "view", pkg, field],
37
+ runAll: (script) => ["npm", "run", script, "--workspaces", "--if-present"],
38
+ runWorkspace: (workspace, script) => ["npm", "run", script, "-w", workspace],
39
+ workspaceProtocol: "*"
40
+ };
41
+ }
42
+ return {
43
+ name: "pnpm",
44
+ install: ["pnpm", "install"],
45
+ run: (script) => ["pnpm", "run", script],
46
+ exec: (bin, args) => ["pnpm", "exec", bin, ...args],
47
+ view: (pkg, field) => ["pnpm", "view", pkg, field],
48
+ runAll: (script) => ["pnpm", "-r", "run", script],
49
+ runWorkspace: (workspace, script) => ["pnpm", "--filter", workspace, script],
50
+ workspaceProtocol: "workspace:*"
51
+ };
52
+ }
14
53
  const access = promisify(fs.access);
15
54
  const copy = promisify(ncp);
16
55
  const __filename$2 = fileURLToPath(import.meta.url);
@@ -30,10 +69,11 @@ async function createRebaseApp(rawArgs) {
30
69
  console.log(`
31
70
  ${chalk.bold("Rebase")} — Create a new project šŸš€
32
71
  `);
33
- const options = await promptForOptions(rawArgs);
72
+ const pm = detectPackageManager();
73
+ const options = await promptForOptions(rawArgs, pm);
34
74
  await createProject(options);
35
75
  }
36
- async function promptForOptions(rawArgs) {
76
+ async function promptForOptions(rawArgs, pm) {
37
77
  const args = arg(
38
78
  {
39
79
  "--git": Boolean,
@@ -76,7 +116,7 @@ async function promptForOptions(rawArgs) {
76
116
  questions.push({
77
117
  type: "confirm",
78
118
  name: "installDeps",
79
- message: "Install dependencies with pnpm?",
119
+ message: `Install dependencies with ${pm}?`,
80
120
  default: true
81
121
  });
82
122
  }
@@ -97,6 +137,7 @@ async function promptForOptions(rawArgs) {
97
137
  const targetDirectory = path.resolve(process.cwd(), nameArg || answers.projectName);
98
138
  const projectName = path.basename(targetDirectory);
99
139
  const templateDirectory = path.resolve(cliRoot, "templates", "template");
140
+ const pmCommands = getPMCommands(pm);
100
141
  return {
101
142
  projectName,
102
143
  git: args["--git"] || answers.git || false,
@@ -104,7 +145,9 @@ async function promptForOptions(rawArgs) {
104
145
  targetDirectory,
105
146
  templateDirectory,
106
147
  databaseUrl: answers.databaseUrl?.trim() || void 0,
107
- introspect: answers.introspect || false
148
+ introspect: answers.introspect || false,
149
+ pm,
150
+ pmCommands
108
151
  };
109
152
  }
110
153
  async function createProject(options) {
@@ -146,17 +189,20 @@ async function createProject(options) {
146
189
  console.warn(chalk.yellow(" Warning: Failed to initialize git repository"));
147
190
  }
148
191
  }
192
+ const { pm, pmCommands } = options;
193
+ const installCmd = pmCommands.install;
194
+ const execCmd = pmCommands.exec("rebase", ["schema", "introspect", "--force"]);
149
195
  if (options.installDeps) {
150
196
  console.log("");
151
- console.log(chalk.gray(" Installing dependencies with pnpm..."));
197
+ console.log(chalk.gray(` Installing dependencies with ${pm}...`));
152
198
  console.log("");
153
199
  try {
154
- await execa("pnpm", ["install"], {
200
+ await execa(installCmd[0], installCmd.slice(1), {
155
201
  cwd: options.targetDirectory,
156
202
  stdio: "inherit"
157
203
  });
158
204
  } catch {
159
- console.warn(chalk.yellow(" Warning: Failed to install dependencies. You may need to run `pnpm install` manually."));
205
+ console.warn(chalk.yellow(` Warning: Failed to install dependencies. You may need to run \`${installCmd.join(" ")}\` manually.`));
160
206
  }
161
207
  }
162
208
  if (options.introspect) {
@@ -165,18 +211,18 @@ async function createProject(options) {
165
211
  console.log(chalk.gray(" Introspecting database and generating collections..."));
166
212
  console.log("");
167
213
  try {
168
- await execa("pnpm", ["exec", "rebase", "schema", "introspect", "--force"], {
214
+ await execa(execCmd[0], execCmd.slice(1), {
169
215
  cwd: options.targetDirectory,
170
216
  stdio: "inherit"
171
217
  });
172
218
  console.log(chalk.green(" Database successfully introspected!"));
173
219
  } catch {
174
220
  console.warn(chalk.yellow(" Warning: Failed to introspect database automatically."));
175
- console.warn(chalk.yellow(" You can run `pnpm exec rebase schema introspect` manually after setup."));
221
+ console.warn(chalk.yellow(` You can run \`${execCmd.join(" ")}\` manually after setup.`));
176
222
  }
177
223
  } else {
178
224
  console.warn(chalk.yellow(" Skipping introspection because dependencies were not installed."));
179
- console.warn(chalk.yellow(" Run `pnpm install` then `pnpm exec rebase schema introspect` manually."));
225
+ console.warn(chalk.yellow(` Run \`${installCmd.join(" ")}\` then \`${execCmd.join(" ")}\` manually.`));
180
226
  }
181
227
  }
182
228
  console.log("");
@@ -184,9 +230,10 @@ async function createProject(options) {
184
230
  console.log("");
185
231
  console.log(chalk.bold("Next steps:"));
186
232
  console.log("");
233
+ const runDev = pmCommands.run("dev");
187
234
  console.log(` ${chalk.cyan("cd")} ${options.projectName}`);
188
235
  if (!options.installDeps) {
189
- console.log(` ${chalk.cyan("pnpm install")}`);
236
+ console.log(` ${chalk.cyan(installCmd.join(" "))}`);
190
237
  }
191
238
  console.log("");
192
239
  if (options.databaseUrl) {
@@ -199,7 +246,7 @@ async function createProject(options) {
199
246
  console.log(chalk.gray(" # Then start the dev server:"));
200
247
  }
201
248
  console.log("");
202
- console.log(` ${chalk.cyan("pnpm dev")}`);
249
+ console.log(` ${chalk.cyan(runDev.join(" "))}`);
203
250
  console.log("");
204
251
  console.log(chalk.gray("This starts both the backend (Hono + PostgreSQL)") + chalk.gray(" and the frontend (Vite + React) concurrently."));
205
252
  console.log("");
@@ -213,7 +260,8 @@ async function replacePlaceholders(options) {
213
260
  "frontend/package.json",
214
261
  "backend/package.json",
215
262
  "config/package.json",
216
- "frontend/index.html"
263
+ "frontend/index.html",
264
+ "README.md"
217
265
  ];
218
266
  const packageJsonPath = path.resolve(cliRoot, "package.json");
219
267
  let cliVersion = "latest";
@@ -222,22 +270,23 @@ async function replacePlaceholders(options) {
222
270
  cliVersion = pkg.version || "latest";
223
271
  }
224
272
  const versionCache = /* @__PURE__ */ new Map();
273
+ const viewBin = "npm";
225
274
  const getPackageVersion = async (pkgName) => {
226
275
  if (versionCache.has(pkgName)) return versionCache.get(pkgName);
227
276
  let versionToUse = cliVersion;
228
277
  try {
229
- const { stdout } = await execa("pnpm", ["view", `${pkgName}@${cliVersion}`, "version"]);
278
+ const { stdout } = await execa(viewBin, ["view", `${pkgName}@${cliVersion}`, "version"]);
230
279
  if (!stdout.trim()) throw new Error("Not found");
231
280
  versionToUse = stdout.trim();
232
281
  } catch {
233
282
  try {
234
283
  const tag = cliVersion.includes("canary") ? "canary" : "latest";
235
- const { stdout } = await execa("pnpm", ["view", `${pkgName}@${tag}`, "version"]);
284
+ const { stdout } = await execa(viewBin, ["view", `${pkgName}@${tag}`, "version"]);
236
285
  if (!stdout.trim()) throw new Error("Not found");
237
286
  versionToUse = stdout.trim();
238
287
  } catch {
239
288
  try {
240
- const { stdout } = await execa("pnpm", ["view", pkgName, "version"]);
289
+ const { stdout } = await execa(viewBin, ["view", pkgName, "version"]);
241
290
  versionToUse = stdout.trim() || "latest";
242
291
  } catch {
243
292
  versionToUse = "latest";
@@ -450,15 +499,20 @@ function getActiveBackendPlugin(backendDir) {
450
499
  if (!fs.existsSync(pkgPath)) return null;
451
500
  try {
452
501
  const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
453
- const deps = {
454
- ...pkg.dependencies,
455
- ...pkg.devDependencies
456
- };
457
- for (const dep of Object.keys(deps)) {
458
- if (dep.startsWith("@rebasepro/server-") && dep !== "@rebasepro/server-core") {
459
- return dep;
502
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
503
+ const candidates = Object.keys(deps).filter(
504
+ (dep) => dep.startsWith("@rebasepro/server-") && dep !== "@rebasepro/server-core"
505
+ );
506
+ if (candidates.length === 0) return null;
507
+ if (candidates.includes("@rebasepro/server-postgresql")) {
508
+ return "@rebasepro/server-postgresql";
509
+ }
510
+ for (const candidate of candidates) {
511
+ if (resolvePluginCliScript(backendDir, candidate)) {
512
+ return candidate;
460
513
  }
461
514
  }
515
+ return candidates[0];
462
516
  } catch {
463
517
  }
464
518
  return null;
@@ -789,9 +843,12 @@ async function devCommand(rawArgs) {
789
843
  frontendEnv.VITE_API_URL = `http://localhost:${backendPort}`;
790
844
  console.log(` ${chalk.gray("↳ VITE_API_URL")} = ${chalk.white(`http://localhost:${backendPort}`)}`);
791
845
  }
846
+ const pm = detectPackageManager(projectRoot);
847
+ const pmCmds = getPMCommands(pm);
848
+ const runDevCmd = pmCmds.run("dev");
792
849
  const frontendChild = execa(
793
- "pnpm",
794
- ["run", "dev"],
850
+ runDevCmd[0],
851
+ runDevCmd.slice(1),
795
852
  {
796
853
  cwd: frontendDir,
797
854
  stdio: ["inherit", "pipe", "pipe"],
@@ -825,8 +882,10 @@ async function devCommand(rawArgs) {
825
882
  if (!frontendOnly && backendDir) {
826
883
  const tsxBin = resolveTsx(projectRoot);
827
884
  if (!tsxBin) {
885
+ const pmName = detectPackageManager(projectRoot);
886
+ const addCmd = pmName === "npm" ? "npm install -D tsx" : "pnpm add -D tsx";
828
887
  console.error(chalk.red(" āœ— Could not find tsx binary for backend."));
829
- console.error(chalk.gray(" Install it with: pnpm add -D tsx"));
888
+ console.error(chalk.gray(` Install it with: ${addCmd}`));
830
889
  process.exit(1);
831
890
  }
832
891
  const envFile = findEnvFile(projectRoot);
@@ -927,6 +986,46 @@ ${chalk.green.bold("Description")}
927
986
  backend is ready, and VITE_API_URL is injected automatically.
928
987
  `);
929
988
  }
989
+ async function buildCommand() {
990
+ const projectRoot = requireProjectRoot();
991
+ const pm = detectPackageManager(projectRoot);
992
+ const cmds = getPMCommands(pm);
993
+ const buildCmd = cmds.runAll("build");
994
+ console.log(`${chalk.bold("Rebase")} — Building all workspaces with ${chalk.cyan(pm)}...
995
+ `);
996
+ try {
997
+ await execa(buildCmd[0], buildCmd.slice(1), {
998
+ cwd: projectRoot,
999
+ stdio: "inherit"
1000
+ });
1001
+ } catch {
1002
+ console.error(chalk.red("\nāœ— Build failed."));
1003
+ process.exit(1);
1004
+ }
1005
+ }
1006
+ async function startCommand() {
1007
+ const projectRoot = requireProjectRoot();
1008
+ const pm = detectPackageManager(projectRoot);
1009
+ const cmds = getPMCommands(pm);
1010
+ const startCmd = cmds.runWorkspace("backend", "start");
1011
+ const envFile = findEnvFile(projectRoot);
1012
+ const env = { ...process.env };
1013
+ if (envFile) {
1014
+ env.DOTENV_CONFIG_PATH = envFile;
1015
+ }
1016
+ console.log(`${chalk.bold("Rebase")} — Starting backend server...
1017
+ `);
1018
+ try {
1019
+ await execa(startCmd[0], startCmd.slice(1), {
1020
+ cwd: projectRoot,
1021
+ stdio: "inherit",
1022
+ env
1023
+ });
1024
+ } catch {
1025
+ console.error(chalk.red("\nāœ— Failed to start server."));
1026
+ process.exit(1);
1027
+ }
1028
+ }
930
1029
  async function authCommand(subcommand, rawArgs) {
931
1030
  if (!subcommand || subcommand === "--help") {
932
1031
  printAuthHelp();
@@ -1135,7 +1234,7 @@ async function entry(args) {
1135
1234
  }
1136
1235
  const command = parsedArgs._[0];
1137
1236
  const subcommand = parsedArgs._[1];
1138
- const namespacedCommands = ["schema", "db", "dev", "auth", "doctor"];
1237
+ const namespacedCommands = ["schema", "db", "dev", "build", "start", "auth", "doctor"];
1139
1238
  if (!command || parsedArgs["--help"] && !namespacedCommands.includes(command)) {
1140
1239
  printHelp();
1141
1240
  return;
@@ -1174,6 +1273,12 @@ async function entry(args) {
1174
1273
  case "dev":
1175
1274
  await devCommand(args);
1176
1275
  break;
1276
+ case "build":
1277
+ await buildCommand();
1278
+ break;
1279
+ case "start":
1280
+ await startCommand();
1281
+ break;
1177
1282
  case "auth":
1178
1283
  await authCommand(effectiveSubcommand, args);
1179
1284
  break;
@@ -1196,14 +1301,16 @@ ${chalk.green.bold("Usage")}
1196
1301
  ${chalk.green.bold("Commands")}
1197
1302
  ${chalk.blue.bold("init")} Create a new Rebase project
1198
1303
  ${chalk.blue.bold("dev")} Start the development server
1304
+ ${chalk.blue.bold("build")} Build all workspace packages
1305
+ ${chalk.blue.bold("start")} Start the backend server ${chalk.gray("(production)")}
1199
1306
 
1200
1307
  ${chalk.green.bold("Schema")}
1201
1308
  ${chalk.blue.bold("schema generate")} Generate Drizzle schema from collections
1309
+ ${chalk.blue.bold("schema introspect")} Introspect database → Rebase collections
1202
1310
  ${chalk.blue.bold("schema")} ${chalk.gray("--help")} Show schema command help
1203
1311
 
1204
1312
  ${chalk.green.bold("Database")}
1205
1313
  ${chalk.blue.bold("db push")} Apply schema directly to database ${chalk.gray("(dev)")}
1206
- ${chalk.blue.bold("db pull")} Introspect database → Drizzle schema
1207
1314
  ${chalk.blue.bold("db generate")} Generate SQL migration files
1208
1315
  ${chalk.blue.bold("db migrate")} Run pending migrations
1209
1316
  ${chalk.blue.bold("db studio")} Open Drizzle Studio
@@ -1271,6 +1378,7 @@ async function logout(env, _debug) {
1271
1378
  }
1272
1379
  export {
1273
1380
  authCommand,
1381
+ buildCommand,
1274
1382
  configureEnvFile,
1275
1383
  createRebaseApp,
1276
1384
  dbCommand,
@@ -1291,6 +1399,7 @@ export {
1291
1399
  resolveLocalBin,
1292
1400
  resolvePluginCliScript,
1293
1401
  resolveTsx,
1294
- schemaCommand
1402
+ schemaCommand,
1403
+ startCommand
1295
1404
  };
1296
1405
  //# sourceMappingURL=index.es.js.map