@rebasepro/cli 0.2.3 → 0.3.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 +34 -30
- package/dist/index.cjs +45 -80
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.es.js +43 -62
- package/dist/index.es.js.map +1 -1
- package/package.json +5 -9
- package/templates/template/config/collections/roles.ts +0 -10
- package/templates/template/docker-compose.yml +1 -1
- package/templates/template/frontend/src/App.tsx +15 -12
- package/templates/template/frontend/src/main.tsx +4 -0
- package/dist/auth.d.ts +0 -5
package/README.md
CHANGED
|
@@ -1,52 +1,56 @@
|
|
|
1
1
|
## Rebase CLI
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
**IMPORTANT**: You should not be using this tool directly, but `rebase` instead.
|
|
3
|
+
Developer tools for scaffolding, running, and managing Rebase projects.
|
|
5
4
|
|
|
6
|
-
###
|
|
5
|
+
### Installation
|
|
7
6
|
|
|
8
|
-
You can
|
|
7
|
+
The CLI is bundled with every Rebase project. You can also install it globally:
|
|
9
8
|
|
|
10
9
|
```bash
|
|
11
|
-
|
|
10
|
+
pnpm add -g @rebasepro/cli
|
|
12
11
|
```
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
### Commands
|
|
14
|
+
|
|
15
|
+
| Command | Description |
|
|
16
|
+
|---------|-------------|
|
|
17
|
+
| `rebase init` | Scaffold a new Rebase project |
|
|
18
|
+
| `rebase dev` | Start the development server (backend + frontend) |
|
|
19
|
+
| `rebase build` | Build all workspace packages |
|
|
20
|
+
| `rebase start` | Start the backend server (production) |
|
|
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) |
|
|
24
|
+
| `rebase db generate` | Generate SQL migration files |
|
|
25
|
+
| `rebase db migrate` | Run pending migrations |
|
|
26
|
+
| `rebase db studio` | Open Drizzle Studio |
|
|
27
|
+
| `rebase generate-sdk` | Generate a typed JS SDK from collections |
|
|
28
|
+
| `rebase auth reset-password` | Reset a user's password |
|
|
29
|
+
| `rebase doctor` | Detect schema drift between collections, schema, and DB |
|
|
30
|
+
|
|
31
|
+
### Quick Start
|
|
17
32
|
|
|
18
33
|
```bash
|
|
19
|
-
rebase
|
|
34
|
+
rebase init my-app
|
|
35
|
+
cd my-app
|
|
36
|
+
docker compose up -d db
|
|
37
|
+
pnpm run db:push
|
|
38
|
+
pnpm run dev
|
|
20
39
|
```
|
|
21
40
|
|
|
22
|
-
###
|
|
23
|
-
|
|
24
|
-
You can initialize a new project using different templates. Please not that these templates can't
|
|
25
|
-
be deployed to Rebase Cloud. For example:
|
|
41
|
+
### Help
|
|
26
42
|
|
|
27
|
-
|
|
43
|
+
Run `rebase --help` or `rebase <command> --help` for detailed usage information.
|
|
28
44
|
|
|
29
|
-
|
|
30
|
-
rebase init
|
|
31
|
-
```
|
|
45
|
+
### Development
|
|
32
46
|
|
|
33
|
-
For
|
|
47
|
+
For local development of the CLI itself, link the package:
|
|
34
48
|
|
|
35
49
|
```bash
|
|
36
|
-
|
|
50
|
+
pnpm link --global
|
|
37
51
|
```
|
|
38
52
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
For development purposes, you can link the package locally.
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
npm link rebase
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### Development only
|
|
48
|
-
|
|
49
|
-
You can change the environment when deploying to Rebase Cloud by defining the --env variable.
|
|
53
|
+
You can change the environment when deploying to Rebase Cloud by defining the `--env` variable.
|
|
50
54
|
Possible values are `prod` (default) and `dev`.
|
|
51
55
|
|
|
52
56
|
```bash
|
package/dist/index.cjs
CHANGED
|
@@ -1,25 +1,8 @@
|
|
|
1
1
|
(function(global, factory) {
|
|
2
|
-
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("chalk"), require("arg"), require("inquirer"), require("path"), require("fs"), require("net"), require("util"), require("execa"), require("fs/promises"), require("url"), require("crypto"), require("@rebasepro/sdk-generator"), require("child_process")
|
|
3
|
-
})(this, (function(exports2, chalk, arg, inquirer, path, fs, net, util, execa, promises, url, crypto, sdkGenerator, child_process
|
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("chalk"), require("arg"), require("inquirer"), require("path"), require("fs"), require("net"), require("util"), require("execa"), require("fs/promises"), require("url"), require("crypto"), require("@rebasepro/sdk-generator"), require("child_process")) : typeof define === "function" && define.amd ? define(["exports", "chalk", "arg", "inquirer", "path", "fs", "net", "util", "execa", "fs/promises", "url", "crypto", "@rebasepro/sdk-generator", "child_process"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global["Rebase CLI"] = {}, global.chalk, global.arg, global.inquirer, global.path, global.fs, global.net, global.util, global.execa, global.promises, global.url, global.crypto, global.sdkGenerator, global.child_process));
|
|
3
|
+
})(this, (function(exports2, chalk, arg, inquirer, path, fs, net, util, execa, promises, url, crypto, sdkGenerator, child_process) {
|
|
4
4
|
"use strict";
|
|
5
5
|
var _documentCurrentScript = typeof document !== "undefined" ? document.currentScript : null;
|
|
6
|
-
function _interopNamespaceDefault(e) {
|
|
7
|
-
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
8
|
-
if (e) {
|
|
9
|
-
for (const k in e) {
|
|
10
|
-
if (k !== "default") {
|
|
11
|
-
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
12
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
13
|
-
enumerable: true,
|
|
14
|
-
get: () => e[k]
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
n.default = e;
|
|
20
|
-
return Object.freeze(n);
|
|
21
|
-
}
|
|
22
|
-
const os__namespace = /* @__PURE__ */ _interopNamespaceDefault(os);
|
|
23
6
|
function detectPackageManager(targetDir) {
|
|
24
7
|
const userAgent = process.env.npm_config_user_agent ?? "";
|
|
25
8
|
if (userAgent.startsWith("npm/")) return "npm";
|
|
@@ -154,7 +137,13 @@ ${chalk.bold("Rebase")} — Create a new project 🚀
|
|
|
154
137
|
type: "input",
|
|
155
138
|
name: "databaseUrl",
|
|
156
139
|
message: "Enter your PostgreSQL database connection string (leave blank to use a local default):",
|
|
157
|
-
default: ""
|
|
140
|
+
default: "",
|
|
141
|
+
validate: (input) => {
|
|
142
|
+
if (input.trim() && /[\r\n]/.test(input)) {
|
|
143
|
+
return "Database URL cannot contain newline characters.";
|
|
144
|
+
}
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
158
147
|
});
|
|
159
148
|
questions.push({
|
|
160
149
|
type: "confirm",
|
|
@@ -260,23 +249,37 @@ ${chalk.bold("Rebase")} — Create a new project 🚀
|
|
|
260
249
|
console.log(chalk.bold("Next steps:"));
|
|
261
250
|
console.log("");
|
|
262
251
|
const runDev = pmCommands.run("dev");
|
|
252
|
+
const runDbPush = pmCommands.run("db:push");
|
|
263
253
|
console.log(` ${chalk.cyan("cd")} ${options.projectName}`);
|
|
264
254
|
if (!options.installDeps) {
|
|
265
255
|
console.log(` ${chalk.cyan(installCmd.join(" "))}`);
|
|
266
256
|
}
|
|
267
257
|
console.log("");
|
|
268
258
|
if (options.databaseUrl) {
|
|
269
|
-
|
|
259
|
+
if (options.introspect) {
|
|
260
|
+
console.log(chalk.gray(" # Database has been introspected & collections generated!"));
|
|
261
|
+
console.log(chalk.gray(" # Start the development server (frontend + backend):"));
|
|
262
|
+
console.log(` ${chalk.cyan(runDev.join(" "))}`);
|
|
263
|
+
} else {
|
|
264
|
+
console.log(chalk.gray(" # Your custom database is configured in .env."));
|
|
265
|
+
console.log(chalk.gray(" # If the database is empty, push the Rebase schema to initialize it:"));
|
|
266
|
+
console.log(` ${chalk.cyan(runDbPush.join(" "))}`);
|
|
267
|
+
console.log("");
|
|
268
|
+
console.log(chalk.gray(" # Then start the development server:"));
|
|
269
|
+
console.log(` ${chalk.cyan(runDev.join(" "))}`);
|
|
270
|
+
}
|
|
270
271
|
} else {
|
|
271
272
|
console.log(chalk.gray(" # A local database configuration has been generated in .env."));
|
|
272
|
-
console.log(chalk.gray(" #
|
|
273
|
+
console.log(chalk.gray(" # 1. Start the PostgreSQL database container:"));
|
|
273
274
|
console.log(` ${chalk.cyan("docker compose up -d db")}`);
|
|
274
275
|
console.log("");
|
|
275
|
-
console.log(chalk.gray(" #
|
|
276
|
+
console.log(chalk.gray(" # 2. Push the Rebase schema to initialize database tables:"));
|
|
277
|
+
console.log(` ${chalk.cyan(runDbPush.join(" "))}`);
|
|
278
|
+
console.log("");
|
|
279
|
+
console.log(chalk.gray(" # 3. Start the development server (frontend + backend):"));
|
|
280
|
+
console.log(` ${chalk.cyan(runDev.join(" "))}`);
|
|
276
281
|
}
|
|
277
282
|
console.log("");
|
|
278
|
-
console.log(` ${chalk.cyan(runDev.join(" "))}`);
|
|
279
|
-
console.log("");
|
|
280
283
|
console.log(chalk.gray("This starts both the backend (Hono + PostgreSQL)") + chalk.gray(" and the frontend (Vite + React) concurrently."));
|
|
281
284
|
console.log("");
|
|
282
285
|
console.log(chalk.gray("Docs: https://rebase.pro/docs"));
|
|
@@ -387,6 +390,9 @@ ${chalk.bold("Rebase")} — Create a new project 🚀
|
|
|
387
390
|
`JWT_SECRET=${jwtSecret}`
|
|
388
391
|
);
|
|
389
392
|
if (databaseUrl) {
|
|
393
|
+
if (/[\r\n]/.test(databaseUrl)) {
|
|
394
|
+
throw new Error("Invalid DATABASE_URL: multiline values are not allowed.");
|
|
395
|
+
}
|
|
390
396
|
envContent = envContent.replace(
|
|
391
397
|
/^DATABASE_URL=.*$/m,
|
|
392
398
|
`DATABASE_URL=${databaseUrl}`
|
|
@@ -696,7 +702,7 @@ Expected a default export of EntityCollection[] or an object with named collecti
|
|
|
696
702
|
env
|
|
697
703
|
});
|
|
698
704
|
}
|
|
699
|
-
} catch
|
|
705
|
+
} catch {
|
|
700
706
|
process.exit(1);
|
|
701
707
|
}
|
|
702
708
|
}
|
|
@@ -764,7 +770,7 @@ ${chalk.green.bold("introspect Options")}
|
|
|
764
770
|
env
|
|
765
771
|
});
|
|
766
772
|
}
|
|
767
|
-
} catch
|
|
773
|
+
} catch {
|
|
768
774
|
process.exit(1);
|
|
769
775
|
}
|
|
770
776
|
}
|
|
@@ -984,7 +990,7 @@ ${chalk.green.bold("Examples")}
|
|
|
984
990
|
});
|
|
985
991
|
console.log(chalk.green(" ✓ Initial schema and SDK generated successfully.\n"));
|
|
986
992
|
} catch (err) {
|
|
987
|
-
console.error(chalk.red(` ✗ Initial schema/SDK generation failed: ${err.message
|
|
993
|
+
console.error(chalk.red(` ✗ Initial schema/SDK generation failed: ${err instanceof Error ? err.message : err}
|
|
988
994
|
`));
|
|
989
995
|
}
|
|
990
996
|
const collectionsDir = path.join(projectRoot, "config", "collections");
|
|
@@ -1013,7 +1019,7 @@ ${chalk.green.bold("Examples")}
|
|
|
1013
1019
|
});
|
|
1014
1020
|
console.log(chalk.green(" ✓ Schema & SDK regenerated successfully. Hono will reload."));
|
|
1015
1021
|
} catch (err) {
|
|
1016
|
-
console.error(chalk.red(` ✗ Failed to regenerate schema/SDK: ${err.message
|
|
1022
|
+
console.error(chalk.red(` ✗ Failed to regenerate schema/SDK: ${err instanceof Error ? err.message : err}`));
|
|
1017
1023
|
}
|
|
1018
1024
|
}, 300);
|
|
1019
1025
|
});
|
|
@@ -1208,6 +1214,9 @@ ${chalk.green.bold("Description")}
|
|
|
1208
1214
|
if (envFile) {
|
|
1209
1215
|
env.DOTENV_CONFIG_PATH = envFile;
|
|
1210
1216
|
}
|
|
1217
|
+
env.REBASE_RESET_EMAIL = email;
|
|
1218
|
+
env.REBASE_RESET_PASSWORD = newPassword || "NewPassword123!";
|
|
1219
|
+
env.REBASE_ENV_FILE_PATH = envFile || path.join(projectRoot, ".env");
|
|
1211
1220
|
const scriptContent = `
|
|
1212
1221
|
import { createPostgresDatabaseConnection } from "@rebasepro/server-postgresql";
|
|
1213
1222
|
import { hashPassword } from "@rebasepro/server-core";
|
|
@@ -1216,10 +1225,10 @@ import * as dotenv from "dotenv";
|
|
|
1216
1225
|
import path from "path";
|
|
1217
1226
|
import fs from "fs";
|
|
1218
1227
|
|
|
1219
|
-
dotenv.config({ path:
|
|
1228
|
+
dotenv.config({ path: process.env.REBASE_ENV_FILE_PATH });
|
|
1220
1229
|
|
|
1221
|
-
const email =
|
|
1222
|
-
const newPassword =
|
|
1230
|
+
const email = process.env.REBASE_RESET_EMAIL!;
|
|
1231
|
+
const newPassword = process.env.REBASE_RESET_PASSWORD!;
|
|
1223
1232
|
|
|
1224
1233
|
async function resetPassword() {
|
|
1225
1234
|
const { db } = createPostgresDatabaseConnection(process.env.DATABASE_URL!);
|
|
@@ -1482,66 +1491,22 @@ ${chalk.green.bold("Options")}
|
|
|
1482
1491
|
${chalk.gray("Documentation: https://rebase.pro/docs")}
|
|
1483
1492
|
`);
|
|
1484
1493
|
}
|
|
1485
|
-
const TOKEN_DIR = path.join(os__namespace.homedir(), ".rebase");
|
|
1486
|
-
function tokenPath(env) {
|
|
1487
|
-
return path.join(TOKEN_DIR, (env === "dev" ? "staging." : "") + "tokens.json");
|
|
1488
|
-
}
|
|
1489
|
-
async function getTokens(env, _debug) {
|
|
1490
|
-
const fp = tokenPath(env);
|
|
1491
|
-
if (!fs.existsSync(fp)) return null;
|
|
1492
|
-
try {
|
|
1493
|
-
const data = fs.readFileSync(fp, "utf-8");
|
|
1494
|
-
return JSON.parse(data);
|
|
1495
|
-
} catch {
|
|
1496
|
-
return null;
|
|
1497
|
-
}
|
|
1498
|
-
}
|
|
1499
|
-
function parseJwt(token) {
|
|
1500
|
-
if (!token) throw new Error("No JWT token");
|
|
1501
|
-
const base64Url = token.split(".")[1];
|
|
1502
|
-
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
|
|
1503
|
-
const buffer = Buffer.from(base64, "base64");
|
|
1504
|
-
return JSON.parse(buffer.toString());
|
|
1505
|
-
}
|
|
1506
|
-
async function refreshCredentials(env, credentials, _onErr) {
|
|
1507
|
-
if (!credentials) return null;
|
|
1508
|
-
const expiryDate = new Date(credentials["expiry_date"]);
|
|
1509
|
-
if (expiryDate.getTime() > Date.now()) {
|
|
1510
|
-
return credentials;
|
|
1511
|
-
}
|
|
1512
|
-
return null;
|
|
1513
|
-
}
|
|
1514
|
-
async function login(env, _debug) {
|
|
1515
|
-
console.log(
|
|
1516
|
-
"Interactive login is not yet implemented in @rebasepro/cli.\nPlease authenticate via the Rebase dashboard and copy your tokens to " + tokenPath(env)
|
|
1517
|
-
);
|
|
1518
|
-
}
|
|
1519
|
-
async function logout(env, _debug) {
|
|
1520
|
-
const fp = tokenPath(env);
|
|
1521
|
-
if (fs.existsSync(fp)) {
|
|
1522
|
-
fs.unlinkSync(fp);
|
|
1523
|
-
console.log("You have been logged out.");
|
|
1524
|
-
} else {
|
|
1525
|
-
console.log("You are not logged in.");
|
|
1526
|
-
}
|
|
1527
|
-
}
|
|
1528
1494
|
exports2.authCommand = authCommand;
|
|
1529
1495
|
exports2.buildCommand = buildCommand;
|
|
1530
1496
|
exports2.configureEnvFile = configureEnvFile;
|
|
1531
1497
|
exports2.createRebaseApp = createRebaseApp;
|
|
1532
1498
|
exports2.dbCommand = dbCommand;
|
|
1499
|
+
exports2.detectPackageManager = detectPackageManager;
|
|
1533
1500
|
exports2.devCommand = devCommand;
|
|
1501
|
+
exports2.doctorCommand = doctorCommand;
|
|
1534
1502
|
exports2.entry = entry;
|
|
1535
1503
|
exports2.findBackendDir = findBackendDir;
|
|
1536
1504
|
exports2.findEnvFile = findEnvFile;
|
|
1537
1505
|
exports2.findFrontendDir = findFrontendDir;
|
|
1538
1506
|
exports2.findProjectRoot = findProjectRoot;
|
|
1507
|
+
exports2.generateSdkCommand = generateSdkCommand;
|
|
1539
1508
|
exports2.getActiveBackendPlugin = getActiveBackendPlugin;
|
|
1540
|
-
exports2.
|
|
1541
|
-
exports2.login = login;
|
|
1542
|
-
exports2.logout = logout;
|
|
1543
|
-
exports2.parseJwt = parseJwt;
|
|
1544
|
-
exports2.refreshCredentials = refreshCredentials;
|
|
1509
|
+
exports2.getPMCommands = getPMCommands;
|
|
1545
1510
|
exports2.requireBackendDir = requireBackendDir;
|
|
1546
1511
|
exports2.requireProjectRoot = requireProjectRoot;
|
|
1547
1512
|
exports2.resolveLocalBin = resolveLocalBin;
|