@rebasepro/cli 0.3.0 → 0.5.0

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/README.md CHANGED
@@ -1,16 +1,16 @@
1
- ## Rebase CLI
1
+ # @rebasepro/cli
2
2
 
3
- Developer tools for scaffolding, running, and managing Rebase projects.
3
+ Developer CLI for scaffolding, running, and managing Rebase projects.
4
4
 
5
- ### Installation
6
-
7
- The CLI is bundled with every Rebase project. You can also install it globally:
5
+ ## Installation
8
6
 
9
7
  ```bash
10
8
  pnpm add -g @rebasepro/cli
11
9
  ```
12
10
 
13
- ### Commands
11
+ The CLI is also bundled with every Rebase project as a local dependency.
12
+
13
+ ## Commands
14
14
 
15
15
  | Command | Description |
16
16
  |---------|-------------|
@@ -19,16 +19,18 @@ pnpm add -g @rebasepro/cli
19
19
  | `rebase build` | Build all workspace packages |
20
20
  | `rebase start` | Start the backend server (production) |
21
21
  | `rebase schema generate` | Generate Drizzle schema from collection definitions |
22
- | `rebase schema introspect` | Introspect an existing database to generate collections |
23
- | `rebase db push` | Apply schema directly to database (development) |
22
+ | `rebase schema introspect` | Introspect an existing database Rebase collections |
23
+ | `rebase db push` | Apply schema directly to database (dev) |
24
24
  | `rebase db generate` | Generate SQL migration files |
25
25
  | `rebase db migrate` | Run pending migrations |
26
26
  | `rebase db studio` | Open Drizzle Studio |
27
- | `rebase generate-sdk` | Generate a typed JS SDK from collections |
27
+ | `rebase generate-sdk` | Generate a typed TypeScript SDK from collections |
28
28
  | `rebase auth reset-password` | Reset a user's password |
29
- | `rebase doctor` | Detect schema drift between collections, schema, and DB |
29
+ | `rebase doctor` | Detect schema drift between collections, Drizzle schema, and database |
30
+
31
+ Run `rebase --help` or `rebase <command> --help` for detailed usage.
30
32
 
31
- ### Quick Start
33
+ ## Quick Start
32
34
 
33
35
  ```bash
34
36
  rebase init my-app
@@ -38,21 +40,11 @@ pnpm run db:push
38
40
  pnpm run dev
39
41
  ```
40
42
 
41
- ### Help
42
-
43
- Run `rebase --help` or `rebase <command> --help` for detailed usage information.
44
-
45
- ### Development
46
-
47
- For local development of the CLI itself, link the package:
48
-
49
- ```bash
50
- pnpm link --global
51
- ```
52
-
53
- You can change the environment when deploying to Rebase Cloud by defining the `--env` variable.
54
- Possible values are `prod` (default) and `dev`.
43
+ ## Related Packages
55
44
 
56
- ```bash
57
- rebase deploy --env dev
58
- ```
45
+ | Package | Role |
46
+ |---------|------|
47
+ | `@rebasepro/server-core` | Backend framework used by `dev` and `start` |
48
+ | `@rebasepro/server-postgresql` | PostgreSQL driver used by schema/db commands |
49
+ | `@rebasepro/sdk-generator` | Powers `generate-sdk` |
50
+ | `@rebasepro/types` | Shared type definitions |
@@ -1,4 +1,5 @@
1
1
  import type { PackageManager, PMCommands } from "../utils/package-manager";
2
+ export type TemplatePreset = "blog" | "ecommerce" | "blank";
2
3
  export interface InitOptions {
3
4
  projectName: string;
4
5
  git: boolean;
@@ -7,6 +8,8 @@ export interface InitOptions {
7
8
  templateDirectory: string;
8
9
  databaseUrl?: string;
9
10
  introspect?: boolean;
11
+ /** Starter template preset. */
12
+ preset: TemplatePreset;
10
13
  /** Detected package manager (pnpm or npm). */
11
14
  pm: PackageManager;
12
15
  /** Command helpers for the detected PM. */
package/dist/index.cjs CHANGED
@@ -56,6 +56,11 @@
56
56
  return null;
57
57
  }
58
58
  const cliRoot = findParentDir(__dirname$2, "cli");
59
+ const PRESET_CHOICES = [
60
+ { name: "Blog — Posts, Authors, Tags (with markdown editor)", value: "blog", short: "Blog" },
61
+ { name: "E-commerce — Products, Categories, Orders", value: "ecommerce", short: "E-commerce" },
62
+ { name: "Blank — Empty project, just authentication", value: "blank", short: "Blank" }
63
+ ];
59
64
  async function createRebaseApp(rawArgs) {
60
65
  console.log(`
61
66
  ${chalk.bold("Rebase")} — Create a new project 🚀
@@ -71,9 +76,11 @@ ${chalk.bold("Rebase")} — Create a new project 🚀
71
76
  "--install": Boolean,
72
77
  "--database-url": String,
73
78
  "--introspect": Boolean,
79
+ "--template": String,
74
80
  "--yes": Boolean,
75
81
  "-g": "--git",
76
82
  "-i": "--install",
83
+ "-t": "--template",
77
84
  "-y": "--yes"
78
85
  },
79
86
  {
@@ -84,6 +91,11 @@ ${chalk.bold("Rebase")} — Create a new project 🚀
84
91
  );
85
92
  const nameArg = args._[0];
86
93
  const isNonInteractive = args["--yes"] || false;
94
+ const templateArg = args["--template"];
95
+ if (templateArg && !PRESET_CHOICES.some((p) => p.value === templateArg)) {
96
+ console.error(chalk.red(`Unknown template "${templateArg}". Available: ${PRESET_CHOICES.map((p) => p.value).join(", ")}`));
97
+ process.exit(1);
98
+ }
87
99
  if (isNonInteractive) {
88
100
  const projectName2 = nameArg || "my-rebase-app";
89
101
  const targetDirectory2 = path.resolve(process.cwd(), projectName2);
@@ -97,6 +109,7 @@ ${chalk.bold("Rebase")} — Create a new project 🚀
97
109
  templateDirectory: templateDirectory2,
98
110
  databaseUrl: args["--database-url"] || void 0,
99
111
  introspect: args["--introspect"] || false,
112
+ preset: templateArg || "blog",
100
113
  pm,
101
114
  pmCommands: pmCommands2
102
115
  };
@@ -117,6 +130,15 @@ ${chalk.bold("Rebase")} — Create a new project 🚀
117
130
  }
118
131
  });
119
132
  }
133
+ if (!templateArg) {
134
+ questions.push({
135
+ type: "list",
136
+ name: "preset",
137
+ message: "Choose a starter template:",
138
+ choices: PRESET_CHOICES,
139
+ default: "blog"
140
+ });
141
+ }
120
142
  if (!args["--git"]) {
121
143
  questions.push({
122
144
  type: "confirm",
@@ -165,6 +187,7 @@ ${chalk.bold("Rebase")} — Create a new project 🚀
165
187
  templateDirectory,
166
188
  databaseUrl: answers.databaseUrl?.trim() || void 0,
167
189
  introspect: answers.introspect || false,
190
+ preset: templateArg || answers.preset || "blog",
168
191
  pm,
169
192
  pmCommands
170
193
  };
@@ -197,6 +220,7 @@ ${chalk.bold("Rebase")} — Create a new project 🚀
197
220
  console.error(`${chalk.red.bold("ERROR")} Failed to copy template files: ${err instanceof Error ? err.message : String(err)}`);
198
221
  process.exit(1);
199
222
  }
223
+ await applyPreset(options.targetDirectory, options.preset);
200
224
  await replacePlaceholders(options);
201
225
  await configureEnvFile(options.targetDirectory, options.databaseUrl);
202
226
  if (options.git) {
@@ -286,6 +310,38 @@ ${chalk.bold("Rebase")} — Create a new project 🚀
286
310
  console.log(chalk.gray("GitHub: https://github.com/rebasepro/rebase"));
287
311
  console.log("");
288
312
  }
313
+ async function applyPreset(targetDirectory, preset) {
314
+ const collectionsDir = path.join(targetDirectory, "config", "collections");
315
+ const presetsDir = path.join(collectionsDir, "presets");
316
+ if (preset !== "blog") {
317
+ const presetDir = path.join(presetsDir, preset);
318
+ if (!fs.existsSync(presetDir)) {
319
+ console.warn(chalk.yellow(` Warning: Preset "${preset}" not found, falling back to blog template.`));
320
+ cleanupPresets(presetsDir);
321
+ return;
322
+ }
323
+ const blogFiles = ["posts.ts", "authors.ts", "tags.ts", "index.ts"];
324
+ for (const file of blogFiles) {
325
+ const filePath = path.join(collectionsDir, file);
326
+ if (fs.existsSync(filePath)) {
327
+ fs.unlinkSync(filePath);
328
+ }
329
+ }
330
+ const presetFiles = fs.readdirSync(presetDir).filter((f) => f.endsWith(".ts"));
331
+ for (const file of presetFiles) {
332
+ fs.copyFileSync(
333
+ path.join(presetDir, file),
334
+ path.join(collectionsDir, file)
335
+ );
336
+ }
337
+ }
338
+ cleanupPresets(presetsDir);
339
+ }
340
+ function cleanupPresets(presetsDir) {
341
+ if (fs.existsSync(presetsDir)) {
342
+ fs.rmSync(presetsDir, { recursive: true, force: true });
343
+ }
344
+ }
289
345
  async function replacePlaceholders(options) {
290
346
  const filesToProcess = [
291
347
  "package.json",