@rebasepro/cli 0.0.1-canary.dbf160a → 0.0.1-canary.e17585f

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.
@@ -0,0 +1 @@
1
+ export declare function buildCommand(): Promise<void>;
@@ -1,3 +1,4 @@
1
+ import type { PackageManager, PMCommands } from "../utils/package-manager";
1
2
  export interface InitOptions {
2
3
  projectName: string;
3
4
  git: boolean;
@@ -6,5 +7,10 @@ export interface InitOptions {
6
7
  templateDirectory: string;
7
8
  databaseUrl?: string;
8
9
  introspect?: boolean;
10
+ /** Detected package manager (pnpm or npm). */
11
+ pm: PackageManager;
12
+ /** Command helpers for the detected PM. */
13
+ pmCommands: PMCommands;
9
14
  }
10
15
  export declare function createRebaseApp(rawArgs: string[]): Promise<void>;
16
+ export declare function configureEnvFile(targetDirectory: string, databaseUrl?: string): void;
@@ -0,0 +1 @@
1
+ export declare function startCommand(): Promise<void>;
package/dist/index.cjs CHANGED
@@ -20,6 +20,45 @@
20
20
  return Object.freeze(n);
21
21
  }
22
22
  const os__namespace = /* @__PURE__ */ _interopNamespaceDefault(os);
23
+ function detectPackageManager(targetDir) {
24
+ const userAgent = process.env.npm_config_user_agent ?? "";
25
+ if (userAgent.startsWith("npm/")) return "npm";
26
+ if (userAgent.startsWith("pnpm/")) return "pnpm";
27
+ if (targetDir) {
28
+ if (fs.existsSync(path.join(targetDir, "package-lock.json"))) return "npm";
29
+ if (fs.existsSync(path.join(targetDir, "pnpm-lock.yaml"))) return "pnpm";
30
+ }
31
+ const cwd = process.cwd();
32
+ if (cwd !== targetDir) {
33
+ if (fs.existsSync(path.join(cwd, "package-lock.json"))) return "npm";
34
+ if (fs.existsSync(path.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
35
+ }
36
+ return "pnpm";
37
+ }
38
+ function getPMCommands(pm) {
39
+ if (pm === "npm") {
40
+ return {
41
+ name: "npm",
42
+ install: ["npm", "install"],
43
+ run: (script) => ["npm", "run", script],
44
+ exec: (bin, args) => ["npx", bin, ...args],
45
+ view: (pkg, field) => ["npm", "view", pkg, field],
46
+ runAll: (script) => ["npm", "run", script, "--workspaces", "--if-present"],
47
+ runWorkspace: (workspace, script) => ["npm", "run", script, "-w", workspace],
48
+ workspaceProtocol: "*"
49
+ };
50
+ }
51
+ return {
52
+ name: "pnpm",
53
+ install: ["pnpm", "install"],
54
+ run: (script) => ["pnpm", "run", script],
55
+ exec: (bin, args) => ["pnpm", "exec", bin, ...args],
56
+ view: (pkg, field) => ["pnpm", "view", pkg, field],
57
+ runAll: (script) => ["pnpm", "-r", "run", script],
58
+ runWorkspace: (workspace, script) => ["pnpm", "--filter", workspace, script],
59
+ workspaceProtocol: "workspace:*"
60
+ };
61
+ }
23
62
  const access = util.promisify(fs.access);
24
63
  const copy = util.promisify(ncp);
25
64
  const __filename$2 = url.fileURLToPath(typeof document === "undefined" && typeof location === "undefined" ? require("url").pathToFileURL(__filename).href : typeof document === "undefined" ? location.href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.cjs", document.baseURI).href);
@@ -39,10 +78,11 @@
39
78
  console.log(`
40
79
  ${chalk.bold("Rebase")} — Create a new project šŸš€
41
80
  `);
42
- const options = await promptForOptions(rawArgs);
81
+ const pm = detectPackageManager();
82
+ const options = await promptForOptions(rawArgs, pm);
43
83
  await createProject(options);
44
84
  }
45
- async function promptForOptions(rawArgs) {
85
+ async function promptForOptions(rawArgs, pm) {
46
86
  const args = arg(
47
87
  {
48
88
  "--git": Boolean,
@@ -85,7 +125,7 @@ ${chalk.bold("Rebase")} — Create a new project šŸš€
85
125
  questions.push({
86
126
  type: "confirm",
87
127
  name: "installDeps",
88
- message: "Install dependencies with pnpm?",
128
+ message: `Install dependencies with ${pm}?`,
89
129
  default: true
90
130
  });
91
131
  }
@@ -106,6 +146,7 @@ ${chalk.bold("Rebase")} — Create a new project šŸš€
106
146
  const targetDirectory = path.resolve(process.cwd(), nameArg || answers.projectName);
107
147
  const projectName = path.basename(targetDirectory);
108
148
  const templateDirectory = path.resolve(cliRoot, "templates", "template");
149
+ const pmCommands = getPMCommands(pm);
109
150
  return {
110
151
  projectName,
111
152
  git: args["--git"] || answers.git || false,
@@ -113,7 +154,9 @@ ${chalk.bold("Rebase")} — Create a new project šŸš€
113
154
  targetDirectory,
114
155
  templateDirectory,
115
156
  databaseUrl: answers.databaseUrl?.trim() || void 0,
116
- introspect: answers.introspect || false
157
+ introspect: answers.introspect || false,
158
+ pm,
159
+ pmCommands
117
160
  };
118
161
  }
119
162
  async function createProject(options) {
@@ -146,34 +189,7 @@ ${chalk.bold("Rebase")} — Create a new project šŸš€
146
189
  process.exit(1);
147
190
  }
148
191
  await replacePlaceholders(options);
149
- const envTemplatePath = path.join(options.targetDirectory, ".env.template");
150
- const envPath = path.join(options.targetDirectory, ".env");
151
- if (fs.existsSync(envTemplatePath) && !fs.existsSync(envPath)) {
152
- fs.renameSync(envTemplatePath, envPath);
153
- const jwtSecret = crypto.randomBytes(32).toString("hex");
154
- let envContent = fs.readFileSync(envPath, "utf-8");
155
- envContent = envContent.replace(
156
- "change-this-to-a-secure-random-string",
157
- jwtSecret
158
- );
159
- if (options.databaseUrl) {
160
- envContent = envContent.replace(
161
- "postgresql://rebase:password@localhost:5432/rebase",
162
- options.databaseUrl
163
- );
164
- } else {
165
- const dbPassword = crypto.randomBytes(16).toString("hex");
166
- envContent = envContent.replace(
167
- "postgresql://rebase:password@localhost:5432/rebase",
168
- `postgresql://rebase:${dbPassword}@localhost:5432/rebase`
169
- );
170
- envContent += `
171
- # Docker Compose Database Password
172
- POSTGRES_PASSWORD=${dbPassword}
173
- `;
174
- }
175
- fs.writeFileSync(envPath, envContent, "utf-8");
176
- }
192
+ configureEnvFile(options.targetDirectory, options.databaseUrl);
177
193
  if (options.git) {
178
194
  console.log(chalk.gray(" Initializing git repository..."));
179
195
  try {
@@ -182,17 +198,20 @@ POSTGRES_PASSWORD=${dbPassword}
182
198
  console.warn(chalk.yellow(" Warning: Failed to initialize git repository"));
183
199
  }
184
200
  }
201
+ const { pm, pmCommands } = options;
202
+ const installCmd = pmCommands.install;
203
+ const execCmd = pmCommands.exec("rebase", ["schema", "introspect", "--force"]);
185
204
  if (options.installDeps) {
186
205
  console.log("");
187
- console.log(chalk.gray(" Installing dependencies with pnpm..."));
206
+ console.log(chalk.gray(` Installing dependencies with ${pm}...`));
188
207
  console.log("");
189
208
  try {
190
- await execa("pnpm", ["install"], {
209
+ await execa(installCmd[0], installCmd.slice(1), {
191
210
  cwd: options.targetDirectory,
192
211
  stdio: "inherit"
193
212
  });
194
213
  } catch {
195
- console.warn(chalk.yellow(" Warning: Failed to install dependencies. You may need to run `pnpm install` manually."));
214
+ console.warn(chalk.yellow(` Warning: Failed to install dependencies. You may need to run \`${installCmd.join(" ")}\` manually.`));
196
215
  }
197
216
  }
198
217
  if (options.introspect) {
@@ -201,18 +220,18 @@ POSTGRES_PASSWORD=${dbPassword}
201
220
  console.log(chalk.gray(" Introspecting database and generating collections..."));
202
221
  console.log("");
203
222
  try {
204
- await execa("pnpm", ["exec", "rebase", "schema", "introspect"], {
223
+ await execa(execCmd[0], execCmd.slice(1), {
205
224
  cwd: options.targetDirectory,
206
225
  stdio: "inherit"
207
226
  });
208
227
  console.log(chalk.green(" Database successfully introspected!"));
209
228
  } catch {
210
229
  console.warn(chalk.yellow(" Warning: Failed to introspect database automatically."));
211
- console.warn(chalk.yellow(" You can run `pnpm exec rebase schema introspect` manually after setup."));
230
+ console.warn(chalk.yellow(` You can run \`${execCmd.join(" ")}\` manually after setup.`));
212
231
  }
213
232
  } else {
214
233
  console.warn(chalk.yellow(" Skipping introspection because dependencies were not installed."));
215
- console.warn(chalk.yellow(" Run `pnpm install` then `pnpm exec rebase schema introspect` manually."));
234
+ console.warn(chalk.yellow(` Run \`${installCmd.join(" ")}\` then \`${execCmd.join(" ")}\` manually.`));
216
235
  }
217
236
  }
218
237
  console.log("");
@@ -220,22 +239,23 @@ POSTGRES_PASSWORD=${dbPassword}
220
239
  console.log("");
221
240
  console.log(chalk.bold("Next steps:"));
222
241
  console.log("");
242
+ const runDev = pmCommands.run("dev");
223
243
  console.log(` ${chalk.cyan("cd")} ${options.projectName}`);
224
244
  if (!options.installDeps) {
225
- console.log(` ${chalk.cyan("pnpm install")}`);
245
+ console.log(` ${chalk.cyan(installCmd.join(" "))}`);
226
246
  }
227
247
  console.log("");
228
248
  if (options.databaseUrl) {
229
249
  console.log(chalk.gray(" # Your database is configured! Start the dev server:"));
230
250
  } else {
231
- console.log(chalk.gray(" # A local database configuration has been generated in .env"));
251
+ console.log(chalk.gray(" # A local database configuration has been generated in .env."));
232
252
  console.log(chalk.gray(" # If using the included docker-compose.yml, start it with:"));
233
253
  console.log(` ${chalk.cyan("docker compose up -d")}`);
234
254
  console.log("");
235
255
  console.log(chalk.gray(" # Then start the dev server:"));
236
256
  }
237
257
  console.log("");
238
- console.log(` ${chalk.cyan("pnpm dev")}`);
258
+ console.log(` ${chalk.cyan(runDev.join(" "))}`);
239
259
  console.log("");
240
260
  console.log(chalk.gray("This starts both the backend (Hono + PostgreSQL)") + chalk.gray(" and the frontend (Vite + React) concurrently."));
241
261
  console.log("");
@@ -249,7 +269,8 @@ POSTGRES_PASSWORD=${dbPassword}
249
269
  "frontend/package.json",
250
270
  "backend/package.json",
251
271
  "config/package.json",
252
- "frontend/index.html"
272
+ "frontend/index.html",
273
+ "README.md"
253
274
  ];
254
275
  const packageJsonPath = path.resolve(cliRoot, "package.json");
255
276
  let cliVersion = "latest";
@@ -258,22 +279,23 @@ POSTGRES_PASSWORD=${dbPassword}
258
279
  cliVersion = pkg.version || "latest";
259
280
  }
260
281
  const versionCache = /* @__PURE__ */ new Map();
282
+ const viewBin = "npm";
261
283
  const getPackageVersion = async (pkgName) => {
262
284
  if (versionCache.has(pkgName)) return versionCache.get(pkgName);
263
285
  let versionToUse = cliVersion;
264
286
  try {
265
- const { stdout } = await execa("npm", ["--loglevel", "error", "info", `${pkgName}@${cliVersion}`, "version"]);
287
+ const { stdout } = await execa(viewBin, ["view", `${pkgName}@${cliVersion}`, "version"]);
266
288
  if (!stdout.trim()) throw new Error("Not found");
267
289
  versionToUse = stdout.trim();
268
290
  } catch {
269
291
  try {
270
292
  const tag = cliVersion.includes("canary") ? "canary" : "latest";
271
- const { stdout } = await execa("npm", ["--loglevel", "error", "info", `${pkgName}@${tag}`, "version"]);
293
+ const { stdout } = await execa(viewBin, ["view", `${pkgName}@${tag}`, "version"]);
272
294
  if (!stdout.trim()) throw new Error("Not found");
273
295
  versionToUse = stdout.trim();
274
296
  } catch {
275
297
  try {
276
- const { stdout } = await execa("npm", ["--loglevel", "error", "info", pkgName, "version"]);
298
+ const { stdout } = await execa(viewBin, ["view", pkgName, "version"]);
277
299
  versionToUse = stdout.trim() || "latest";
278
300
  } catch {
279
301
  versionToUse = "latest";
@@ -308,6 +330,32 @@ POSTGRES_PASSWORD=${dbPassword}
308
330
  fs.writeFileSync(fullPath, content, "utf-8");
309
331
  }
310
332
  }
333
+ function configureEnvFile(targetDirectory, databaseUrl) {
334
+ const envExamplePath = path.join(targetDirectory, ".env.example");
335
+ const envPath = path.join(targetDirectory, ".env");
336
+ if (fs.existsSync(envExamplePath) && !fs.existsSync(envPath)) {
337
+ fs.copyFileSync(envExamplePath, envPath);
338
+ const jwtSecret = crypto.randomBytes(32).toString("hex");
339
+ const dbPassword = crypto.randomBytes(16).toString("hex");
340
+ let envContent = fs.readFileSync(envPath, "utf-8");
341
+ envContent = envContent.replace(
342
+ /^JWT_SECRET=.*$/m,
343
+ `JWT_SECRET=${jwtSecret}`
344
+ );
345
+ if (databaseUrl) {
346
+ envContent = envContent.replace(
347
+ /^DATABASE_URL=.*$/m,
348
+ `DATABASE_URL=${databaseUrl}`
349
+ );
350
+ } else {
351
+ envContent = envContent.replace(
352
+ /^DATABASE_URL=.*$/m,
353
+ `DATABASE_URL=postgresql://rebase:${dbPassword}@localhost:5432/rebase`
354
+ );
355
+ }
356
+ fs.writeFileSync(envPath, envContent, "utf-8");
357
+ }
358
+ }
311
359
  async function loadCollections(collectionsDir) {
312
360
  const absDir = path.resolve(collectionsDir);
313
361
  if (!fs.existsSync(absDir)) {
@@ -460,15 +508,20 @@ Expected a default export of EntityCollection[] or an object with named collecti
460
508
  if (!fs.existsSync(pkgPath)) return null;
461
509
  try {
462
510
  const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
463
- const deps = {
464
- ...pkg.dependencies,
465
- ...pkg.devDependencies
466
- };
467
- for (const dep of Object.keys(deps)) {
468
- if (dep.startsWith("@rebasepro/server-") && dep !== "@rebasepro/server-core") {
469
- return dep;
511
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
512
+ const candidates = Object.keys(deps).filter(
513
+ (dep) => dep.startsWith("@rebasepro/server-") && dep !== "@rebasepro/server-core"
514
+ );
515
+ if (candidates.length === 0) return null;
516
+ if (candidates.includes("@rebasepro/server-postgresql")) {
517
+ return "@rebasepro/server-postgresql";
518
+ }
519
+ for (const candidate of candidates) {
520
+ if (resolvePluginCliScript(backendDir, candidate)) {
521
+ return candidate;
470
522
  }
471
523
  }
524
+ return candidates[0];
472
525
  } catch {
473
526
  }
474
527
  return null;
@@ -669,7 +722,6 @@ ${chalk.green.bold("Usage")}
669
722
  ${chalk.green.bold("Commands")}
670
723
  ${chalk.gray("(Commands are provided by your active database driver plugin)")}
671
724
  ${chalk.blue.bold("push")} Apply schema directly to database (development)
672
- ${chalk.blue.bold("pull")} Introspect database → Schema
673
725
  ${chalk.blue.bold("generate")} Generate migration files
674
726
  ${chalk.blue.bold("migrate")} Run pending migrations
675
727
  ${chalk.blue.bold("studio")} Open Studio viewer
@@ -800,9 +852,12 @@ ${chalk.green.bold("Examples")}
800
852
  frontendEnv.VITE_API_URL = `http://localhost:${backendPort}`;
801
853
  console.log(` ${chalk.gray("↳ VITE_API_URL")} = ${chalk.white(`http://localhost:${backendPort}`)}`);
802
854
  }
855
+ const pm = detectPackageManager(projectRoot);
856
+ const pmCmds = getPMCommands(pm);
857
+ const runDevCmd = pmCmds.run("dev");
803
858
  const frontendChild = execa(
804
- "pnpm",
805
- ["run", "dev"],
859
+ runDevCmd[0],
860
+ runDevCmd.slice(1),
806
861
  {
807
862
  cwd: frontendDir,
808
863
  stdio: ["inherit", "pipe", "pipe"],
@@ -836,8 +891,10 @@ ${chalk.green.bold("Examples")}
836
891
  if (!frontendOnly && backendDir) {
837
892
  const tsxBin = resolveTsx(projectRoot);
838
893
  if (!tsxBin) {
894
+ const pmName = detectPackageManager(projectRoot);
895
+ const addCmd = pmName === "npm" ? "npm install -D tsx" : "pnpm add -D tsx";
839
896
  console.error(chalk.red(" āœ— Could not find tsx binary for backend."));
840
- console.error(chalk.gray(" Install it with: pnpm add -D tsx"));
897
+ console.error(chalk.gray(` Install it with: ${addCmd}`));
841
898
  process.exit(1);
842
899
  }
843
900
  const envFile = findEnvFile(projectRoot);
@@ -938,6 +995,46 @@ ${chalk.green.bold("Description")}
938
995
  backend is ready, and VITE_API_URL is injected automatically.
939
996
  `);
940
997
  }
998
+ async function buildCommand() {
999
+ const projectRoot = requireProjectRoot();
1000
+ const pm = detectPackageManager(projectRoot);
1001
+ const cmds = getPMCommands(pm);
1002
+ const buildCmd = cmds.runAll("build");
1003
+ console.log(`${chalk.bold("Rebase")} — Building all workspaces with ${chalk.cyan(pm)}...
1004
+ `);
1005
+ try {
1006
+ await execa(buildCmd[0], buildCmd.slice(1), {
1007
+ cwd: projectRoot,
1008
+ stdio: "inherit"
1009
+ });
1010
+ } catch {
1011
+ console.error(chalk.red("\nāœ— Build failed."));
1012
+ process.exit(1);
1013
+ }
1014
+ }
1015
+ async function startCommand() {
1016
+ const projectRoot = requireProjectRoot();
1017
+ const pm = detectPackageManager(projectRoot);
1018
+ const cmds = getPMCommands(pm);
1019
+ const startCmd = cmds.runWorkspace("backend", "start");
1020
+ const envFile = findEnvFile(projectRoot);
1021
+ const env = { ...process.env };
1022
+ if (envFile) {
1023
+ env.DOTENV_CONFIG_PATH = envFile;
1024
+ }
1025
+ console.log(`${chalk.bold("Rebase")} — Starting backend server...
1026
+ `);
1027
+ try {
1028
+ await execa(startCmd[0], startCmd.slice(1), {
1029
+ cwd: projectRoot,
1030
+ stdio: "inherit",
1031
+ env
1032
+ });
1033
+ } catch {
1034
+ console.error(chalk.red("\nāœ— Failed to start server."));
1035
+ process.exit(1);
1036
+ }
1037
+ }
941
1038
  async function authCommand(subcommand, rawArgs) {
942
1039
  if (!subcommand || subcommand === "--help") {
943
1040
  printAuthHelp();
@@ -1146,7 +1243,7 @@ ${chalk.green.bold("Examples")}
1146
1243
  }
1147
1244
  const command = parsedArgs._[0];
1148
1245
  const subcommand = parsedArgs._[1];
1149
- const namespacedCommands = ["schema", "db", "dev", "auth", "doctor"];
1246
+ const namespacedCommands = ["schema", "db", "dev", "build", "start", "auth", "doctor"];
1150
1247
  if (!command || parsedArgs["--help"] && !namespacedCommands.includes(command)) {
1151
1248
  printHelp();
1152
1249
  return;
@@ -1185,6 +1282,12 @@ ${chalk.green.bold("Examples")}
1185
1282
  case "dev":
1186
1283
  await devCommand(args);
1187
1284
  break;
1285
+ case "build":
1286
+ await buildCommand();
1287
+ break;
1288
+ case "start":
1289
+ await startCommand();
1290
+ break;
1188
1291
  case "auth":
1189
1292
  await authCommand(effectiveSubcommand, args);
1190
1293
  break;
@@ -1207,14 +1310,16 @@ ${chalk.green.bold("Usage")}
1207
1310
  ${chalk.green.bold("Commands")}
1208
1311
  ${chalk.blue.bold("init")} Create a new Rebase project
1209
1312
  ${chalk.blue.bold("dev")} Start the development server
1313
+ ${chalk.blue.bold("build")} Build all workspace packages
1314
+ ${chalk.blue.bold("start")} Start the backend server ${chalk.gray("(production)")}
1210
1315
 
1211
1316
  ${chalk.green.bold("Schema")}
1212
1317
  ${chalk.blue.bold("schema generate")} Generate Drizzle schema from collections
1318
+ ${chalk.blue.bold("schema introspect")} Introspect database → Rebase collections
1213
1319
  ${chalk.blue.bold("schema")} ${chalk.gray("--help")} Show schema command help
1214
1320
 
1215
1321
  ${chalk.green.bold("Database")}
1216
1322
  ${chalk.blue.bold("db push")} Apply schema directly to database ${chalk.gray("(dev)")}
1217
- ${chalk.blue.bold("db pull")} Introspect database → Drizzle schema
1218
1323
  ${chalk.blue.bold("db generate")} Generate SQL migration files
1219
1324
  ${chalk.blue.bold("db migrate")} Run pending migrations
1220
1325
  ${chalk.blue.bold("db studio")} Open Drizzle Studio
@@ -1281,6 +1386,8 @@ ${chalk.gray("Documentation: https://rebase.pro/docs")}
1281
1386
  }
1282
1387
  }
1283
1388
  exports2.authCommand = authCommand;
1389
+ exports2.buildCommand = buildCommand;
1390
+ exports2.configureEnvFile = configureEnvFile;
1284
1391
  exports2.createRebaseApp = createRebaseApp;
1285
1392
  exports2.dbCommand = dbCommand;
1286
1393
  exports2.devCommand = devCommand;
@@ -1301,6 +1408,7 @@ ${chalk.gray("Documentation: https://rebase.pro/docs")}
1301
1408
  exports2.resolvePluginCliScript = resolvePluginCliScript;
1302
1409
  exports2.resolveTsx = resolveTsx;
1303
1410
  exports2.schemaCommand = schemaCommand;
1411
+ exports2.startCommand = startCommand;
1304
1412
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
1305
1413
  }));
1306
1414
  //# sourceMappingURL=index.cjs.map