@rebasepro/cli 0.0.1-canary.f81da60 ā 0.1.2
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/dist/commands/build.d.ts +1 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/start.d.ts +1 -0
- package/dist/index.cjs +125 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.es.js +126 -23
- package/dist/index.es.js.map +1 -1
- package/dist/utils/package-manager.d.ts +31 -0
- package/dist/utils/package-manager.test.d.ts +1 -0
- package/package.json +4 -4
- package/templates/template/README.md +3 -3
- package/templates/template/backend/package.json +1 -1
- package/templates/template/docker-compose.yml +1 -1
- package/templates/template/frontend/package.json +1 -1
- package/templates/template/package.json +9 -4
package/dist/index.es.js
CHANGED
|
@@ -11,6 +11,45 @@ import crypto from "crypto";
|
|
|
11
11
|
import { generateSDK } from "@rebasepro/sdk-generator";
|
|
12
12
|
import { execSync, spawn } from "child_process";
|
|
13
13
|
import * as os from "os";
|
|
14
|
+
function detectPackageManager(targetDir) {
|
|
15
|
+
const userAgent = process.env.npm_config_user_agent ?? "";
|
|
16
|
+
if (userAgent.startsWith("npm/")) return "npm";
|
|
17
|
+
if (userAgent.startsWith("pnpm/")) return "pnpm";
|
|
18
|
+
if (targetDir) {
|
|
19
|
+
if (fs.existsSync(path.join(targetDir, "package-lock.json"))) return "npm";
|
|
20
|
+
if (fs.existsSync(path.join(targetDir, "pnpm-lock.yaml"))) return "pnpm";
|
|
21
|
+
}
|
|
22
|
+
const cwd = process.cwd();
|
|
23
|
+
if (cwd !== targetDir) {
|
|
24
|
+
if (fs.existsSync(path.join(cwd, "package-lock.json"))) return "npm";
|
|
25
|
+
if (fs.existsSync(path.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
26
|
+
}
|
|
27
|
+
return "pnpm";
|
|
28
|
+
}
|
|
29
|
+
function getPMCommands(pm) {
|
|
30
|
+
if (pm === "npm") {
|
|
31
|
+
return {
|
|
32
|
+
name: "npm",
|
|
33
|
+
install: ["npm", "install"],
|
|
34
|
+
run: (script) => ["npm", "run", script],
|
|
35
|
+
exec: (bin, args) => ["npx", bin, ...args],
|
|
36
|
+
view: (pkg, field) => ["npm", "view", pkg, field],
|
|
37
|
+
runAll: (script) => ["npm", "run", script, "--workspaces", "--if-present"],
|
|
38
|
+
runWorkspace: (workspace, script) => ["npm", "run", script, "-w", workspace],
|
|
39
|
+
workspaceProtocol: "*"
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
name: "pnpm",
|
|
44
|
+
install: ["pnpm", "install"],
|
|
45
|
+
run: (script) => ["pnpm", "run", script],
|
|
46
|
+
exec: (bin, args) => ["pnpm", "exec", bin, ...args],
|
|
47
|
+
view: (pkg, field) => ["pnpm", "view", pkg, field],
|
|
48
|
+
runAll: (script) => ["pnpm", "-r", "run", script],
|
|
49
|
+
runWorkspace: (workspace, script) => ["pnpm", "--filter", workspace, script],
|
|
50
|
+
workspaceProtocol: "workspace:*"
|
|
51
|
+
};
|
|
52
|
+
}
|
|
14
53
|
const access = promisify(fs.access);
|
|
15
54
|
const copy = promisify(ncp);
|
|
16
55
|
const __filename$2 = fileURLToPath(import.meta.url);
|
|
@@ -30,10 +69,11 @@ async function createRebaseApp(rawArgs) {
|
|
|
30
69
|
console.log(`
|
|
31
70
|
${chalk.bold("Rebase")} ā Create a new project š
|
|
32
71
|
`);
|
|
33
|
-
const
|
|
72
|
+
const pm = detectPackageManager();
|
|
73
|
+
const options = await promptForOptions(rawArgs, pm);
|
|
34
74
|
await createProject(options);
|
|
35
75
|
}
|
|
36
|
-
async function promptForOptions(rawArgs) {
|
|
76
|
+
async function promptForOptions(rawArgs, pm) {
|
|
37
77
|
const args = arg(
|
|
38
78
|
{
|
|
39
79
|
"--git": Boolean,
|
|
@@ -76,7 +116,7 @@ async function promptForOptions(rawArgs) {
|
|
|
76
116
|
questions.push({
|
|
77
117
|
type: "confirm",
|
|
78
118
|
name: "installDeps",
|
|
79
|
-
message:
|
|
119
|
+
message: `Install dependencies with ${pm}?`,
|
|
80
120
|
default: true
|
|
81
121
|
});
|
|
82
122
|
}
|
|
@@ -97,6 +137,7 @@ async function promptForOptions(rawArgs) {
|
|
|
97
137
|
const targetDirectory = path.resolve(process.cwd(), nameArg || answers.projectName);
|
|
98
138
|
const projectName = path.basename(targetDirectory);
|
|
99
139
|
const templateDirectory = path.resolve(cliRoot, "templates", "template");
|
|
140
|
+
const pmCommands = getPMCommands(pm);
|
|
100
141
|
return {
|
|
101
142
|
projectName,
|
|
102
143
|
git: args["--git"] || answers.git || false,
|
|
@@ -104,7 +145,9 @@ async function promptForOptions(rawArgs) {
|
|
|
104
145
|
targetDirectory,
|
|
105
146
|
templateDirectory,
|
|
106
147
|
databaseUrl: answers.databaseUrl?.trim() || void 0,
|
|
107
|
-
introspect: answers.introspect || false
|
|
148
|
+
introspect: answers.introspect || false,
|
|
149
|
+
pm,
|
|
150
|
+
pmCommands
|
|
108
151
|
};
|
|
109
152
|
}
|
|
110
153
|
async function createProject(options) {
|
|
@@ -146,17 +189,20 @@ async function createProject(options) {
|
|
|
146
189
|
console.warn(chalk.yellow(" Warning: Failed to initialize git repository"));
|
|
147
190
|
}
|
|
148
191
|
}
|
|
192
|
+
const { pm, pmCommands } = options;
|
|
193
|
+
const installCmd = pmCommands.install;
|
|
194
|
+
const execCmd = pmCommands.exec("rebase", ["schema", "introspect", "--force"]);
|
|
149
195
|
if (options.installDeps) {
|
|
150
196
|
console.log("");
|
|
151
|
-
console.log(chalk.gray(
|
|
197
|
+
console.log(chalk.gray(` Installing dependencies with ${pm}...`));
|
|
152
198
|
console.log("");
|
|
153
199
|
try {
|
|
154
|
-
await execa(
|
|
200
|
+
await execa(installCmd[0], installCmd.slice(1), {
|
|
155
201
|
cwd: options.targetDirectory,
|
|
156
202
|
stdio: "inherit"
|
|
157
203
|
});
|
|
158
204
|
} catch {
|
|
159
|
-
console.warn(chalk.yellow(
|
|
205
|
+
console.warn(chalk.yellow(` Warning: Failed to install dependencies. You may need to run \`${installCmd.join(" ")}\` manually.`));
|
|
160
206
|
}
|
|
161
207
|
}
|
|
162
208
|
if (options.introspect) {
|
|
@@ -165,18 +211,18 @@ async function createProject(options) {
|
|
|
165
211
|
console.log(chalk.gray(" Introspecting database and generating collections..."));
|
|
166
212
|
console.log("");
|
|
167
213
|
try {
|
|
168
|
-
await execa(
|
|
214
|
+
await execa(execCmd[0], execCmd.slice(1), {
|
|
169
215
|
cwd: options.targetDirectory,
|
|
170
216
|
stdio: "inherit"
|
|
171
217
|
});
|
|
172
218
|
console.log(chalk.green(" Database successfully introspected!"));
|
|
173
219
|
} catch {
|
|
174
220
|
console.warn(chalk.yellow(" Warning: Failed to introspect database automatically."));
|
|
175
|
-
console.warn(chalk.yellow(
|
|
221
|
+
console.warn(chalk.yellow(` You can run \`${execCmd.join(" ")}\` manually after setup.`));
|
|
176
222
|
}
|
|
177
223
|
} else {
|
|
178
224
|
console.warn(chalk.yellow(" Skipping introspection because dependencies were not installed."));
|
|
179
|
-
console.warn(chalk.yellow(
|
|
225
|
+
console.warn(chalk.yellow(` Run \`${installCmd.join(" ")}\` then \`${execCmd.join(" ")}\` manually.`));
|
|
180
226
|
}
|
|
181
227
|
}
|
|
182
228
|
console.log("");
|
|
@@ -184,9 +230,10 @@ async function createProject(options) {
|
|
|
184
230
|
console.log("");
|
|
185
231
|
console.log(chalk.bold("Next steps:"));
|
|
186
232
|
console.log("");
|
|
233
|
+
const runDev = pmCommands.run("dev");
|
|
187
234
|
console.log(` ${chalk.cyan("cd")} ${options.projectName}`);
|
|
188
235
|
if (!options.installDeps) {
|
|
189
|
-
console.log(` ${chalk.cyan("
|
|
236
|
+
console.log(` ${chalk.cyan(installCmd.join(" "))}`);
|
|
190
237
|
}
|
|
191
238
|
console.log("");
|
|
192
239
|
if (options.databaseUrl) {
|
|
@@ -199,7 +246,7 @@ async function createProject(options) {
|
|
|
199
246
|
console.log(chalk.gray(" # Then start the dev server:"));
|
|
200
247
|
}
|
|
201
248
|
console.log("");
|
|
202
|
-
console.log(` ${chalk.cyan("
|
|
249
|
+
console.log(` ${chalk.cyan(runDev.join(" "))}`);
|
|
203
250
|
console.log("");
|
|
204
251
|
console.log(chalk.gray("This starts both the backend (Hono + PostgreSQL)") + chalk.gray(" and the frontend (Vite + React) concurrently."));
|
|
205
252
|
console.log("");
|
|
@@ -213,7 +260,8 @@ async function replacePlaceholders(options) {
|
|
|
213
260
|
"frontend/package.json",
|
|
214
261
|
"backend/package.json",
|
|
215
262
|
"config/package.json",
|
|
216
|
-
"frontend/index.html"
|
|
263
|
+
"frontend/index.html",
|
|
264
|
+
"README.md"
|
|
217
265
|
];
|
|
218
266
|
const packageJsonPath = path.resolve(cliRoot, "package.json");
|
|
219
267
|
let cliVersion = "latest";
|
|
@@ -222,22 +270,23 @@ async function replacePlaceholders(options) {
|
|
|
222
270
|
cliVersion = pkg.version || "latest";
|
|
223
271
|
}
|
|
224
272
|
const versionCache = /* @__PURE__ */ new Map();
|
|
273
|
+
const viewBin = "npm";
|
|
225
274
|
const getPackageVersion = async (pkgName) => {
|
|
226
275
|
if (versionCache.has(pkgName)) return versionCache.get(pkgName);
|
|
227
276
|
let versionToUse = cliVersion;
|
|
228
277
|
try {
|
|
229
|
-
const { stdout } = await execa(
|
|
278
|
+
const { stdout } = await execa(viewBin, ["view", `${pkgName}@${cliVersion}`, "version"]);
|
|
230
279
|
if (!stdout.trim()) throw new Error("Not found");
|
|
231
280
|
versionToUse = stdout.trim();
|
|
232
281
|
} catch {
|
|
233
282
|
try {
|
|
234
283
|
const tag = cliVersion.includes("canary") ? "canary" : "latest";
|
|
235
|
-
const { stdout } = await execa(
|
|
284
|
+
const { stdout } = await execa(viewBin, ["view", `${pkgName}@${tag}`, "version"]);
|
|
236
285
|
if (!stdout.trim()) throw new Error("Not found");
|
|
237
286
|
versionToUse = stdout.trim();
|
|
238
287
|
} catch {
|
|
239
288
|
try {
|
|
240
|
-
const { stdout } = await execa(
|
|
289
|
+
const { stdout } = await execa(viewBin, ["view", pkgName, "version"]);
|
|
241
290
|
versionToUse = stdout.trim() || "latest";
|
|
242
291
|
} catch {
|
|
243
292
|
versionToUse = "latest";
|
|
@@ -659,7 +708,6 @@ ${chalk.green.bold("Usage")}
|
|
|
659
708
|
${chalk.green.bold("Commands")}
|
|
660
709
|
${chalk.gray("(Commands are provided by your active database driver plugin)")}
|
|
661
710
|
${chalk.blue.bold("push")} Apply schema directly to database (development)
|
|
662
|
-
${chalk.blue.bold("pull")} Introspect database ā Schema
|
|
663
711
|
${chalk.blue.bold("generate")} Generate migration files
|
|
664
712
|
${chalk.blue.bold("migrate")} Run pending migrations
|
|
665
713
|
${chalk.blue.bold("studio")} Open Studio viewer
|
|
@@ -790,9 +838,12 @@ async function devCommand(rawArgs) {
|
|
|
790
838
|
frontendEnv.VITE_API_URL = `http://localhost:${backendPort}`;
|
|
791
839
|
console.log(` ${chalk.gray("ā³ VITE_API_URL")} = ${chalk.white(`http://localhost:${backendPort}`)}`);
|
|
792
840
|
}
|
|
841
|
+
const pm = detectPackageManager(projectRoot);
|
|
842
|
+
const pmCmds = getPMCommands(pm);
|
|
843
|
+
const runDevCmd = pmCmds.run("dev");
|
|
793
844
|
const frontendChild = execa(
|
|
794
|
-
|
|
795
|
-
|
|
845
|
+
runDevCmd[0],
|
|
846
|
+
runDevCmd.slice(1),
|
|
796
847
|
{
|
|
797
848
|
cwd: frontendDir,
|
|
798
849
|
stdio: ["inherit", "pipe", "pipe"],
|
|
@@ -826,8 +877,10 @@ async function devCommand(rawArgs) {
|
|
|
826
877
|
if (!frontendOnly && backendDir) {
|
|
827
878
|
const tsxBin = resolveTsx(projectRoot);
|
|
828
879
|
if (!tsxBin) {
|
|
880
|
+
const pmName = detectPackageManager(projectRoot);
|
|
881
|
+
const addCmd = pmName === "npm" ? "npm install -D tsx" : "pnpm add -D tsx";
|
|
829
882
|
console.error(chalk.red(" ā Could not find tsx binary for backend."));
|
|
830
|
-
console.error(chalk.gray(
|
|
883
|
+
console.error(chalk.gray(` Install it with: ${addCmd}`));
|
|
831
884
|
process.exit(1);
|
|
832
885
|
}
|
|
833
886
|
const envFile = findEnvFile(projectRoot);
|
|
@@ -928,6 +981,46 @@ ${chalk.green.bold("Description")}
|
|
|
928
981
|
backend is ready, and VITE_API_URL is injected automatically.
|
|
929
982
|
`);
|
|
930
983
|
}
|
|
984
|
+
async function buildCommand() {
|
|
985
|
+
const projectRoot = requireProjectRoot();
|
|
986
|
+
const pm = detectPackageManager(projectRoot);
|
|
987
|
+
const cmds = getPMCommands(pm);
|
|
988
|
+
const buildCmd = cmds.runAll("build");
|
|
989
|
+
console.log(`${chalk.bold("Rebase")} ā Building all workspaces with ${chalk.cyan(pm)}...
|
|
990
|
+
`);
|
|
991
|
+
try {
|
|
992
|
+
await execa(buildCmd[0], buildCmd.slice(1), {
|
|
993
|
+
cwd: projectRoot,
|
|
994
|
+
stdio: "inherit"
|
|
995
|
+
});
|
|
996
|
+
} catch {
|
|
997
|
+
console.error(chalk.red("\nā Build failed."));
|
|
998
|
+
process.exit(1);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
async function startCommand() {
|
|
1002
|
+
const projectRoot = requireProjectRoot();
|
|
1003
|
+
const pm = detectPackageManager(projectRoot);
|
|
1004
|
+
const cmds = getPMCommands(pm);
|
|
1005
|
+
const startCmd = cmds.runWorkspace("backend", "start");
|
|
1006
|
+
const envFile = findEnvFile(projectRoot);
|
|
1007
|
+
const env = { ...process.env };
|
|
1008
|
+
if (envFile) {
|
|
1009
|
+
env.DOTENV_CONFIG_PATH = envFile;
|
|
1010
|
+
}
|
|
1011
|
+
console.log(`${chalk.bold("Rebase")} ā Starting backend server...
|
|
1012
|
+
`);
|
|
1013
|
+
try {
|
|
1014
|
+
await execa(startCmd[0], startCmd.slice(1), {
|
|
1015
|
+
cwd: projectRoot,
|
|
1016
|
+
stdio: "inherit",
|
|
1017
|
+
env
|
|
1018
|
+
});
|
|
1019
|
+
} catch {
|
|
1020
|
+
console.error(chalk.red("\nā Failed to start server."));
|
|
1021
|
+
process.exit(1);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
931
1024
|
async function authCommand(subcommand, rawArgs) {
|
|
932
1025
|
if (!subcommand || subcommand === "--help") {
|
|
933
1026
|
printAuthHelp();
|
|
@@ -1136,7 +1229,7 @@ async function entry(args) {
|
|
|
1136
1229
|
}
|
|
1137
1230
|
const command = parsedArgs._[0];
|
|
1138
1231
|
const subcommand = parsedArgs._[1];
|
|
1139
|
-
const namespacedCommands = ["schema", "db", "dev", "auth", "doctor"];
|
|
1232
|
+
const namespacedCommands = ["schema", "db", "dev", "build", "start", "auth", "doctor"];
|
|
1140
1233
|
if (!command || parsedArgs["--help"] && !namespacedCommands.includes(command)) {
|
|
1141
1234
|
printHelp();
|
|
1142
1235
|
return;
|
|
@@ -1175,6 +1268,12 @@ async function entry(args) {
|
|
|
1175
1268
|
case "dev":
|
|
1176
1269
|
await devCommand(args);
|
|
1177
1270
|
break;
|
|
1271
|
+
case "build":
|
|
1272
|
+
await buildCommand();
|
|
1273
|
+
break;
|
|
1274
|
+
case "start":
|
|
1275
|
+
await startCommand();
|
|
1276
|
+
break;
|
|
1178
1277
|
case "auth":
|
|
1179
1278
|
await authCommand(effectiveSubcommand, args);
|
|
1180
1279
|
break;
|
|
@@ -1197,14 +1296,16 @@ ${chalk.green.bold("Usage")}
|
|
|
1197
1296
|
${chalk.green.bold("Commands")}
|
|
1198
1297
|
${chalk.blue.bold("init")} Create a new Rebase project
|
|
1199
1298
|
${chalk.blue.bold("dev")} Start the development server
|
|
1299
|
+
${chalk.blue.bold("build")} Build all workspace packages
|
|
1300
|
+
${chalk.blue.bold("start")} Start the backend server ${chalk.gray("(production)")}
|
|
1200
1301
|
|
|
1201
1302
|
${chalk.green.bold("Schema")}
|
|
1202
1303
|
${chalk.blue.bold("schema generate")} Generate Drizzle schema from collections
|
|
1304
|
+
${chalk.blue.bold("schema introspect")} Introspect database ā Rebase collections
|
|
1203
1305
|
${chalk.blue.bold("schema")} ${chalk.gray("--help")} Show schema command help
|
|
1204
1306
|
|
|
1205
1307
|
${chalk.green.bold("Database")}
|
|
1206
1308
|
${chalk.blue.bold("db push")} Apply schema directly to database ${chalk.gray("(dev)")}
|
|
1207
|
-
${chalk.blue.bold("db pull")} Introspect database ā Drizzle schema
|
|
1208
1309
|
${chalk.blue.bold("db generate")} Generate SQL migration files
|
|
1209
1310
|
${chalk.blue.bold("db migrate")} Run pending migrations
|
|
1210
1311
|
${chalk.blue.bold("db studio")} Open Drizzle Studio
|
|
@@ -1272,6 +1373,7 @@ async function logout(env, _debug) {
|
|
|
1272
1373
|
}
|
|
1273
1374
|
export {
|
|
1274
1375
|
authCommand,
|
|
1376
|
+
buildCommand,
|
|
1275
1377
|
configureEnvFile,
|
|
1276
1378
|
createRebaseApp,
|
|
1277
1379
|
dbCommand,
|
|
@@ -1292,6 +1394,7 @@ export {
|
|
|
1292
1394
|
resolveLocalBin,
|
|
1293
1395
|
resolvePluginCliScript,
|
|
1294
1396
|
resolveTsx,
|
|
1295
|
-
schemaCommand
|
|
1397
|
+
schemaCommand,
|
|
1398
|
+
startCommand
|
|
1296
1399
|
};
|
|
1297
1400
|
//# sourceMappingURL=index.es.js.map
|