@rebasepro/cli 0.2.3 → 0.2.4
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/dist/index.es.js
CHANGED
|
@@ -11,7 +11,6 @@ import { fileURLToPath } from "url";
|
|
|
11
11
|
import crypto from "crypto";
|
|
12
12
|
import { generateSDK } from "@rebasepro/sdk-generator";
|
|
13
13
|
import { execSync, spawn } from "child_process";
|
|
14
|
-
import * as os from "os";
|
|
15
14
|
function detectPackageManager(targetDir) {
|
|
16
15
|
const userAgent = process.env.npm_config_user_agent ?? "";
|
|
17
16
|
if (userAgent.startsWith("npm/")) return "npm";
|
|
@@ -146,7 +145,13 @@ async function promptForOptions(rawArgs, pm) {
|
|
|
146
145
|
type: "input",
|
|
147
146
|
name: "databaseUrl",
|
|
148
147
|
message: "Enter your PostgreSQL database connection string (leave blank to use a local default):",
|
|
149
|
-
default: ""
|
|
148
|
+
default: "",
|
|
149
|
+
validate: (input) => {
|
|
150
|
+
if (input.trim() && /[\r\n]/.test(input)) {
|
|
151
|
+
return "Database URL cannot contain newline characters.";
|
|
152
|
+
}
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
150
155
|
});
|
|
151
156
|
questions.push({
|
|
152
157
|
type: "confirm",
|
|
@@ -252,23 +257,37 @@ async function createProject(options) {
|
|
|
252
257
|
console.log(chalk.bold("Next steps:"));
|
|
253
258
|
console.log("");
|
|
254
259
|
const runDev = pmCommands.run("dev");
|
|
260
|
+
const runDbPush = pmCommands.run("db:push");
|
|
255
261
|
console.log(` ${chalk.cyan("cd")} ${options.projectName}`);
|
|
256
262
|
if (!options.installDeps) {
|
|
257
263
|
console.log(` ${chalk.cyan(installCmd.join(" "))}`);
|
|
258
264
|
}
|
|
259
265
|
console.log("");
|
|
260
266
|
if (options.databaseUrl) {
|
|
261
|
-
|
|
267
|
+
if (options.introspect) {
|
|
268
|
+
console.log(chalk.gray(" # Database has been introspected & collections generated!"));
|
|
269
|
+
console.log(chalk.gray(" # Start the development server (frontend + backend):"));
|
|
270
|
+
console.log(` ${chalk.cyan(runDev.join(" "))}`);
|
|
271
|
+
} else {
|
|
272
|
+
console.log(chalk.gray(" # Your custom database is configured in .env."));
|
|
273
|
+
console.log(chalk.gray(" # If the database is empty, push the Rebase schema to initialize it:"));
|
|
274
|
+
console.log(` ${chalk.cyan(runDbPush.join(" "))}`);
|
|
275
|
+
console.log("");
|
|
276
|
+
console.log(chalk.gray(" # Then start the development server:"));
|
|
277
|
+
console.log(` ${chalk.cyan(runDev.join(" "))}`);
|
|
278
|
+
}
|
|
262
279
|
} else {
|
|
263
280
|
console.log(chalk.gray(" # A local database configuration has been generated in .env."));
|
|
264
|
-
console.log(chalk.gray(" #
|
|
281
|
+
console.log(chalk.gray(" # 1. Start the PostgreSQL database container:"));
|
|
265
282
|
console.log(` ${chalk.cyan("docker compose up -d db")}`);
|
|
266
283
|
console.log("");
|
|
267
|
-
console.log(chalk.gray(" #
|
|
284
|
+
console.log(chalk.gray(" # 2. Push the Rebase schema to initialize database tables:"));
|
|
285
|
+
console.log(` ${chalk.cyan(runDbPush.join(" "))}`);
|
|
286
|
+
console.log("");
|
|
287
|
+
console.log(chalk.gray(" # 3. Start the development server (frontend + backend):"));
|
|
288
|
+
console.log(` ${chalk.cyan(runDev.join(" "))}`);
|
|
268
289
|
}
|
|
269
290
|
console.log("");
|
|
270
|
-
console.log(` ${chalk.cyan(runDev.join(" "))}`);
|
|
271
|
-
console.log("");
|
|
272
291
|
console.log(chalk.gray("This starts both the backend (Hono + PostgreSQL)") + chalk.gray(" and the frontend (Vite + React) concurrently."));
|
|
273
292
|
console.log("");
|
|
274
293
|
console.log(chalk.gray("Docs: https://rebase.pro/docs"));
|
|
@@ -379,6 +398,9 @@ async function configureEnvFile(targetDirectory, databaseUrl) {
|
|
|
379
398
|
`JWT_SECRET=${jwtSecret}`
|
|
380
399
|
);
|
|
381
400
|
if (databaseUrl) {
|
|
401
|
+
if (/[\r\n]/.test(databaseUrl)) {
|
|
402
|
+
throw new Error("Invalid DATABASE_URL: multiline values are not allowed.");
|
|
403
|
+
}
|
|
382
404
|
envContent = envContent.replace(
|
|
383
405
|
/^DATABASE_URL=.*$/m,
|
|
384
406
|
`DATABASE_URL=${databaseUrl}`
|
|
@@ -688,7 +710,7 @@ async function schemaCommand(subcommand, rawArgs) {
|
|
|
688
710
|
env
|
|
689
711
|
});
|
|
690
712
|
}
|
|
691
|
-
} catch
|
|
713
|
+
} catch {
|
|
692
714
|
process.exit(1);
|
|
693
715
|
}
|
|
694
716
|
}
|
|
@@ -756,7 +778,7 @@ async function dbCommand(subcommand, rawArgs) {
|
|
|
756
778
|
env
|
|
757
779
|
});
|
|
758
780
|
}
|
|
759
|
-
} catch
|
|
781
|
+
} catch {
|
|
760
782
|
process.exit(1);
|
|
761
783
|
}
|
|
762
784
|
}
|
|
@@ -976,7 +998,7 @@ async function devCommand(rawArgs) {
|
|
|
976
998
|
});
|
|
977
999
|
console.log(chalk.green(" ✓ Initial schema and SDK generated successfully.\n"));
|
|
978
1000
|
} catch (err) {
|
|
979
|
-
console.error(chalk.red(` ✗ Initial schema/SDK generation failed: ${err.message
|
|
1001
|
+
console.error(chalk.red(` ✗ Initial schema/SDK generation failed: ${err instanceof Error ? err.message : err}
|
|
980
1002
|
`));
|
|
981
1003
|
}
|
|
982
1004
|
const collectionsDir = path.join(projectRoot, "config", "collections");
|
|
@@ -1005,7 +1027,7 @@ async function devCommand(rawArgs) {
|
|
|
1005
1027
|
});
|
|
1006
1028
|
console.log(chalk.green(" ✓ Schema & SDK regenerated successfully. Hono will reload."));
|
|
1007
1029
|
} catch (err) {
|
|
1008
|
-
console.error(chalk.red(` ✗ Failed to regenerate schema/SDK: ${err.message
|
|
1030
|
+
console.error(chalk.red(` ✗ Failed to regenerate schema/SDK: ${err instanceof Error ? err.message : err}`));
|
|
1009
1031
|
}
|
|
1010
1032
|
}, 300);
|
|
1011
1033
|
});
|
|
@@ -1200,6 +1222,9 @@ async function resetPassword(rawArgs) {
|
|
|
1200
1222
|
if (envFile) {
|
|
1201
1223
|
env.DOTENV_CONFIG_PATH = envFile;
|
|
1202
1224
|
}
|
|
1225
|
+
env.REBASE_RESET_EMAIL = email;
|
|
1226
|
+
env.REBASE_RESET_PASSWORD = newPassword || "NewPassword123!";
|
|
1227
|
+
env.REBASE_ENV_FILE_PATH = envFile || path.join(projectRoot, ".env");
|
|
1203
1228
|
const scriptContent = `
|
|
1204
1229
|
import { createPostgresDatabaseConnection } from "@rebasepro/server-postgresql";
|
|
1205
1230
|
import { hashPassword } from "@rebasepro/server-core";
|
|
@@ -1208,10 +1233,10 @@ import * as dotenv from "dotenv";
|
|
|
1208
1233
|
import path from "path";
|
|
1209
1234
|
import fs from "fs";
|
|
1210
1235
|
|
|
1211
|
-
dotenv.config({ path:
|
|
1236
|
+
dotenv.config({ path: process.env.REBASE_ENV_FILE_PATH });
|
|
1212
1237
|
|
|
1213
|
-
const email =
|
|
1214
|
-
const newPassword =
|
|
1238
|
+
const email = process.env.REBASE_RESET_EMAIL!;
|
|
1239
|
+
const newPassword = process.env.REBASE_RESET_PASSWORD!;
|
|
1215
1240
|
|
|
1216
1241
|
async function resetPassword() {
|
|
1217
1242
|
const { db } = createPostgresDatabaseConnection(process.env.DATABASE_URL!);
|
|
@@ -1474,67 +1499,23 @@ ${chalk.green.bold("Options")}
|
|
|
1474
1499
|
${chalk.gray("Documentation: https://rebase.pro/docs")}
|
|
1475
1500
|
`);
|
|
1476
1501
|
}
|
|
1477
|
-
const TOKEN_DIR = path.join(os.homedir(), ".rebase");
|
|
1478
|
-
function tokenPath(env) {
|
|
1479
|
-
return path.join(TOKEN_DIR, (env === "dev" ? "staging." : "") + "tokens.json");
|
|
1480
|
-
}
|
|
1481
|
-
async function getTokens(env, _debug) {
|
|
1482
|
-
const fp = tokenPath(env);
|
|
1483
|
-
if (!fs.existsSync(fp)) return null;
|
|
1484
|
-
try {
|
|
1485
|
-
const data = fs.readFileSync(fp, "utf-8");
|
|
1486
|
-
return JSON.parse(data);
|
|
1487
|
-
} catch {
|
|
1488
|
-
return null;
|
|
1489
|
-
}
|
|
1490
|
-
}
|
|
1491
|
-
function parseJwt(token) {
|
|
1492
|
-
if (!token) throw new Error("No JWT token");
|
|
1493
|
-
const base64Url = token.split(".")[1];
|
|
1494
|
-
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
|
|
1495
|
-
const buffer = Buffer.from(base64, "base64");
|
|
1496
|
-
return JSON.parse(buffer.toString());
|
|
1497
|
-
}
|
|
1498
|
-
async function refreshCredentials(env, credentials, _onErr) {
|
|
1499
|
-
if (!credentials) return null;
|
|
1500
|
-
const expiryDate = new Date(credentials["expiry_date"]);
|
|
1501
|
-
if (expiryDate.getTime() > Date.now()) {
|
|
1502
|
-
return credentials;
|
|
1503
|
-
}
|
|
1504
|
-
return null;
|
|
1505
|
-
}
|
|
1506
|
-
async function login(env, _debug) {
|
|
1507
|
-
console.log(
|
|
1508
|
-
"Interactive login is not yet implemented in @rebasepro/cli.\nPlease authenticate via the Rebase dashboard and copy your tokens to " + tokenPath(env)
|
|
1509
|
-
);
|
|
1510
|
-
}
|
|
1511
|
-
async function logout(env, _debug) {
|
|
1512
|
-
const fp = tokenPath(env);
|
|
1513
|
-
if (fs.existsSync(fp)) {
|
|
1514
|
-
fs.unlinkSync(fp);
|
|
1515
|
-
console.log("You have been logged out.");
|
|
1516
|
-
} else {
|
|
1517
|
-
console.log("You are not logged in.");
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
1502
|
export {
|
|
1521
1503
|
authCommand,
|
|
1522
1504
|
buildCommand,
|
|
1523
1505
|
configureEnvFile,
|
|
1524
1506
|
createRebaseApp,
|
|
1525
1507
|
dbCommand,
|
|
1508
|
+
detectPackageManager,
|
|
1526
1509
|
devCommand,
|
|
1510
|
+
doctorCommand,
|
|
1527
1511
|
entry,
|
|
1528
1512
|
findBackendDir,
|
|
1529
1513
|
findEnvFile,
|
|
1530
1514
|
findFrontendDir,
|
|
1531
1515
|
findProjectRoot,
|
|
1516
|
+
generateSdkCommand,
|
|
1532
1517
|
getActiveBackendPlugin,
|
|
1533
|
-
|
|
1534
|
-
login,
|
|
1535
|
-
logout,
|
|
1536
|
-
parseJwt,
|
|
1537
|
-
refreshCredentials,
|
|
1518
|
+
getPMCommands,
|
|
1538
1519
|
requireBackendDir,
|
|
1539
1520
|
requireProjectRoot,
|
|
1540
1521
|
resolveLocalBin,
|