@rebasepro/cli 0.0.1-canary.94dff14 → 0.0.1-canary.b6f40f8

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)) {
@@ -669,7 +717,6 @@ ${chalk.green.bold("Usage")}
669
717
  ${chalk.green.bold("Commands")}
670
718
  ${chalk.gray("(Commands are provided by your active database driver plugin)")}
671
719
  ${chalk.blue.bold("push")} Apply schema directly to database (development)
672
- ${chalk.blue.bold("pull")} Introspect database → Schema
673
720
  ${chalk.blue.bold("generate")} Generate migration files
674
721
  ${chalk.blue.bold("migrate")} Run pending migrations
675
722
  ${chalk.blue.bold("studio")} Open Studio viewer
@@ -800,9 +847,12 @@ ${chalk.green.bold("Examples")}
800
847
  frontendEnv.VITE_API_URL = `http://localhost:${backendPort}`;
801
848
  console.log(` ${chalk.gray("↳ VITE_API_URL")} = ${chalk.white(`http://localhost:${backendPort}`)}`);
802
849
  }
850
+ const pm = detectPackageManager(projectRoot);
851
+ const pmCmds = getPMCommands(pm);
852
+ const runDevCmd = pmCmds.run("dev");
803
853
  const frontendChild = execa(
804
- "pnpm",
805
- ["run", "dev"],
854
+ runDevCmd[0],
855
+ runDevCmd.slice(1),
806
856
  {
807
857
  cwd: frontendDir,
808
858
  stdio: ["inherit", "pipe", "pipe"],
@@ -836,8 +886,10 @@ ${chalk.green.bold("Examples")}
836
886
  if (!frontendOnly && backendDir) {
837
887
  const tsxBin = resolveTsx(projectRoot);
838
888
  if (!tsxBin) {
889
+ const pmName = detectPackageManager(projectRoot);
890
+ const addCmd = pmName === "npm" ? "npm install -D tsx" : "pnpm add -D tsx";
839
891
  console.error(chalk.red(" āœ— Could not find tsx binary for backend."));
840
- console.error(chalk.gray(" Install it with: pnpm add -D tsx"));
892
+ console.error(chalk.gray(` Install it with: ${addCmd}`));
841
893
  process.exit(1);
842
894
  }
843
895
  const envFile = findEnvFile(projectRoot);
@@ -938,6 +990,46 @@ ${chalk.green.bold("Description")}
938
990
  backend is ready, and VITE_API_URL is injected automatically.
939
991
  `);
940
992
  }
993
+ async function buildCommand() {
994
+ const projectRoot = requireProjectRoot();
995
+ const pm = detectPackageManager(projectRoot);
996
+ const cmds = getPMCommands(pm);
997
+ const buildCmd = cmds.runAll("build");
998
+ console.log(`${chalk.bold("Rebase")} — Building all workspaces with ${chalk.cyan(pm)}...
999
+ `);
1000
+ try {
1001
+ await execa(buildCmd[0], buildCmd.slice(1), {
1002
+ cwd: projectRoot,
1003
+ stdio: "inherit"
1004
+ });
1005
+ } catch {
1006
+ console.error(chalk.red("\nāœ— Build failed."));
1007
+ process.exit(1);
1008
+ }
1009
+ }
1010
+ async function startCommand() {
1011
+ const projectRoot = requireProjectRoot();
1012
+ const pm = detectPackageManager(projectRoot);
1013
+ const cmds = getPMCommands(pm);
1014
+ const startCmd = cmds.runWorkspace("backend", "start");
1015
+ const envFile = findEnvFile(projectRoot);
1016
+ const env = { ...process.env };
1017
+ if (envFile) {
1018
+ env.DOTENV_CONFIG_PATH = envFile;
1019
+ }
1020
+ console.log(`${chalk.bold("Rebase")} — Starting backend server...
1021
+ `);
1022
+ try {
1023
+ await execa(startCmd[0], startCmd.slice(1), {
1024
+ cwd: projectRoot,
1025
+ stdio: "inherit",
1026
+ env
1027
+ });
1028
+ } catch {
1029
+ console.error(chalk.red("\nāœ— Failed to start server."));
1030
+ process.exit(1);
1031
+ }
1032
+ }
941
1033
  async function authCommand(subcommand, rawArgs) {
942
1034
  if (!subcommand || subcommand === "--help") {
943
1035
  printAuthHelp();
@@ -1146,7 +1238,7 @@ ${chalk.green.bold("Examples")}
1146
1238
  }
1147
1239
  const command = parsedArgs._[0];
1148
1240
  const subcommand = parsedArgs._[1];
1149
- const namespacedCommands = ["schema", "db", "dev", "auth", "doctor"];
1241
+ const namespacedCommands = ["schema", "db", "dev", "build", "start", "auth", "doctor"];
1150
1242
  if (!command || parsedArgs["--help"] && !namespacedCommands.includes(command)) {
1151
1243
  printHelp();
1152
1244
  return;
@@ -1185,6 +1277,12 @@ ${chalk.green.bold("Examples")}
1185
1277
  case "dev":
1186
1278
  await devCommand(args);
1187
1279
  break;
1280
+ case "build":
1281
+ await buildCommand();
1282
+ break;
1283
+ case "start":
1284
+ await startCommand();
1285
+ break;
1188
1286
  case "auth":
1189
1287
  await authCommand(effectiveSubcommand, args);
1190
1288
  break;
@@ -1207,14 +1305,16 @@ ${chalk.green.bold("Usage")}
1207
1305
  ${chalk.green.bold("Commands")}
1208
1306
  ${chalk.blue.bold("init")} Create a new Rebase project
1209
1307
  ${chalk.blue.bold("dev")} Start the development server
1308
+ ${chalk.blue.bold("build")} Build all workspace packages
1309
+ ${chalk.blue.bold("start")} Start the backend server ${chalk.gray("(production)")}
1210
1310
 
1211
1311
  ${chalk.green.bold("Schema")}
1212
1312
  ${chalk.blue.bold("schema generate")} Generate Drizzle schema from collections
1313
+ ${chalk.blue.bold("schema introspect")} Introspect database → Rebase collections
1213
1314
  ${chalk.blue.bold("schema")} ${chalk.gray("--help")} Show schema command help
1214
1315
 
1215
1316
  ${chalk.green.bold("Database")}
1216
1317
  ${chalk.blue.bold("db push")} Apply schema directly to database ${chalk.gray("(dev)")}
1217
- ${chalk.blue.bold("db pull")} Introspect database → Drizzle schema
1218
1318
  ${chalk.blue.bold("db generate")} Generate SQL migration files
1219
1319
  ${chalk.blue.bold("db migrate")} Run pending migrations
1220
1320
  ${chalk.blue.bold("db studio")} Open Drizzle Studio
@@ -1281,6 +1381,8 @@ ${chalk.gray("Documentation: https://rebase.pro/docs")}
1281
1381
  }
1282
1382
  }
1283
1383
  exports2.authCommand = authCommand;
1384
+ exports2.buildCommand = buildCommand;
1385
+ exports2.configureEnvFile = configureEnvFile;
1284
1386
  exports2.createRebaseApp = createRebaseApp;
1285
1387
  exports2.dbCommand = dbCommand;
1286
1388
  exports2.devCommand = devCommand;
@@ -1301,6 +1403,7 @@ ${chalk.gray("Documentation: https://rebase.pro/docs")}
1301
1403
  exports2.resolvePluginCliScript = resolvePluginCliScript;
1302
1404
  exports2.resolveTsx = resolveTsx;
1303
1405
  exports2.schemaCommand = schemaCommand;
1406
+ exports2.startCommand = startCommand;
1304
1407
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
1305
1408
  }));
1306
1409
  //# sourceMappingURL=index.cjs.map