@rebasepro/cli 0.0.1-canary.ca2cb6e → 0.0.1-canary.dbf160a
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/init.d.ts +2 -0
- package/dist/index.cjs +108 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +108 -12
- package/dist/index.es.js.map +1 -1
- package/package.json +4 -4
- package/templates/template/backend/drizzle.config.ts +15 -3
- package/templates/template/backend/package.json +2 -2
- package/templates/template/config/collections/posts.ts +3 -3
- package/templates/template/frontend/src/App.tsx +19 -98
- package/templates/template/frontend/vite.config.ts +31 -2
- package/templates/template/package.json +5 -4
package/dist/index.es.js
CHANGED
|
@@ -80,6 +80,19 @@ async function promptForOptions(rawArgs) {
|
|
|
80
80
|
default: true
|
|
81
81
|
});
|
|
82
82
|
}
|
|
83
|
+
questions.push({
|
|
84
|
+
type: "input",
|
|
85
|
+
name: "databaseUrl",
|
|
86
|
+
message: "Enter your PostgreSQL database connection string (leave blank to use a local default):",
|
|
87
|
+
default: ""
|
|
88
|
+
});
|
|
89
|
+
questions.push({
|
|
90
|
+
type: "confirm",
|
|
91
|
+
name: "introspect",
|
|
92
|
+
message: "Would you like to introspect this database to automatically generate collections?",
|
|
93
|
+
default: true,
|
|
94
|
+
when: (answers2) => !!answers2.databaseUrl?.trim()
|
|
95
|
+
});
|
|
83
96
|
const answers = await inquirer.prompt(questions);
|
|
84
97
|
const targetDirectory = path.resolve(process.cwd(), nameArg || answers.projectName);
|
|
85
98
|
const projectName = path.basename(targetDirectory);
|
|
@@ -89,7 +102,9 @@ async function promptForOptions(rawArgs) {
|
|
|
89
102
|
git: args["--git"] || answers.git || false,
|
|
90
103
|
installDeps: args["--install"] || answers.installDeps || false,
|
|
91
104
|
targetDirectory,
|
|
92
|
-
templateDirectory
|
|
105
|
+
templateDirectory,
|
|
106
|
+
databaseUrl: answers.databaseUrl?.trim() || void 0,
|
|
107
|
+
introspect: answers.introspect || false
|
|
93
108
|
};
|
|
94
109
|
}
|
|
95
110
|
async function createProject(options) {
|
|
@@ -127,20 +142,27 @@ async function createProject(options) {
|
|
|
127
142
|
if (fs.existsSync(envTemplatePath) && !fs.existsSync(envPath)) {
|
|
128
143
|
fs.renameSync(envTemplatePath, envPath);
|
|
129
144
|
const jwtSecret = crypto.randomBytes(32).toString("hex");
|
|
130
|
-
const dbPassword = crypto.randomBytes(16).toString("hex");
|
|
131
145
|
let envContent = fs.readFileSync(envPath, "utf-8");
|
|
132
|
-
envContent = envContent.replace(
|
|
133
|
-
"postgresql://rebase:password@localhost:5432/rebase",
|
|
134
|
-
`postgresql://rebase:${dbPassword}@localhost:5432/rebase`
|
|
135
|
-
);
|
|
136
146
|
envContent = envContent.replace(
|
|
137
147
|
"change-this-to-a-secure-random-string",
|
|
138
148
|
jwtSecret
|
|
139
149
|
);
|
|
140
|
-
|
|
150
|
+
if (options.databaseUrl) {
|
|
151
|
+
envContent = envContent.replace(
|
|
152
|
+
"postgresql://rebase:password@localhost:5432/rebase",
|
|
153
|
+
options.databaseUrl
|
|
154
|
+
);
|
|
155
|
+
} else {
|
|
156
|
+
const dbPassword = crypto.randomBytes(16).toString("hex");
|
|
157
|
+
envContent = envContent.replace(
|
|
158
|
+
"postgresql://rebase:password@localhost:5432/rebase",
|
|
159
|
+
`postgresql://rebase:${dbPassword}@localhost:5432/rebase`
|
|
160
|
+
);
|
|
161
|
+
envContent += `
|
|
141
162
|
# Docker Compose Database Password
|
|
142
163
|
POSTGRES_PASSWORD=${dbPassword}
|
|
143
164
|
`;
|
|
165
|
+
}
|
|
144
166
|
fs.writeFileSync(envPath, envContent, "utf-8");
|
|
145
167
|
}
|
|
146
168
|
if (options.git) {
|
|
@@ -164,6 +186,26 @@ POSTGRES_PASSWORD=${dbPassword}
|
|
|
164
186
|
console.warn(chalk.yellow(" Warning: Failed to install dependencies. You may need to run `pnpm install` manually."));
|
|
165
187
|
}
|
|
166
188
|
}
|
|
189
|
+
if (options.introspect) {
|
|
190
|
+
console.log("");
|
|
191
|
+
if (options.installDeps) {
|
|
192
|
+
console.log(chalk.gray(" Introspecting database and generating collections..."));
|
|
193
|
+
console.log("");
|
|
194
|
+
try {
|
|
195
|
+
await execa("pnpm", ["exec", "rebase", "schema", "introspect"], {
|
|
196
|
+
cwd: options.targetDirectory,
|
|
197
|
+
stdio: "inherit"
|
|
198
|
+
});
|
|
199
|
+
console.log(chalk.green(" Database successfully introspected!"));
|
|
200
|
+
} catch {
|
|
201
|
+
console.warn(chalk.yellow(" Warning: Failed to introspect database automatically."));
|
|
202
|
+
console.warn(chalk.yellow(" You can run `pnpm exec rebase schema introspect` manually after setup."));
|
|
203
|
+
}
|
|
204
|
+
} else {
|
|
205
|
+
console.warn(chalk.yellow(" Skipping introspection because dependencies were not installed."));
|
|
206
|
+
console.warn(chalk.yellow(" Run `pnpm install` then `pnpm exec rebase schema introspect` manually."));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
167
209
|
console.log("");
|
|
168
210
|
console.log(`${chalk.green.bold("✓")} Project ${chalk.bold(options.projectName)} created successfully!`);
|
|
169
211
|
console.log("");
|
|
@@ -174,8 +216,15 @@ POSTGRES_PASSWORD=${dbPassword}
|
|
|
174
216
|
console.log(` ${chalk.cyan("pnpm install")}`);
|
|
175
217
|
}
|
|
176
218
|
console.log("");
|
|
177
|
-
|
|
178
|
-
|
|
219
|
+
if (options.databaseUrl) {
|
|
220
|
+
console.log(chalk.gray(" # Your database is configured! Start the dev server:"));
|
|
221
|
+
} else {
|
|
222
|
+
console.log(chalk.gray(" # A local database configuration has been generated in .env"));
|
|
223
|
+
console.log(chalk.gray(" # If using the included docker-compose.yml, start it with:"));
|
|
224
|
+
console.log(` ${chalk.cyan("docker compose up -d")}`);
|
|
225
|
+
console.log("");
|
|
226
|
+
console.log(chalk.gray(" # Then start the dev server:"));
|
|
227
|
+
}
|
|
179
228
|
console.log("");
|
|
180
229
|
console.log(` ${chalk.cyan("pnpm dev")}`);
|
|
181
230
|
console.log("");
|
|
@@ -199,12 +248,54 @@ async function replacePlaceholders(options) {
|
|
|
199
248
|
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
200
249
|
cliVersion = pkg.version || "latest";
|
|
201
250
|
}
|
|
251
|
+
const versionCache = /* @__PURE__ */ new Map();
|
|
252
|
+
const getPackageVersion = async (pkgName) => {
|
|
253
|
+
if (versionCache.has(pkgName)) return versionCache.get(pkgName);
|
|
254
|
+
let versionToUse = cliVersion;
|
|
255
|
+
try {
|
|
256
|
+
const { stdout } = await execa("npm", ["--loglevel", "error", "info", `${pkgName}@${cliVersion}`, "version"]);
|
|
257
|
+
if (!stdout.trim()) throw new Error("Not found");
|
|
258
|
+
versionToUse = stdout.trim();
|
|
259
|
+
} catch {
|
|
260
|
+
try {
|
|
261
|
+
const tag = cliVersion.includes("canary") ? "canary" : "latest";
|
|
262
|
+
const { stdout } = await execa("npm", ["--loglevel", "error", "info", `${pkgName}@${tag}`, "version"]);
|
|
263
|
+
if (!stdout.trim()) throw new Error("Not found");
|
|
264
|
+
versionToUse = stdout.trim();
|
|
265
|
+
} catch {
|
|
266
|
+
try {
|
|
267
|
+
const { stdout } = await execa("npm", ["--loglevel", "error", "info", pkgName, "version"]);
|
|
268
|
+
versionToUse = stdout.trim() || "latest";
|
|
269
|
+
} catch {
|
|
270
|
+
versionToUse = "latest";
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
versionCache.set(pkgName, versionToUse);
|
|
275
|
+
return versionToUse;
|
|
276
|
+
};
|
|
277
|
+
const allPackages = /* @__PURE__ */ new Set();
|
|
278
|
+
const fileContents = /* @__PURE__ */ new Map();
|
|
202
279
|
for (const file of filesToProcess) {
|
|
203
280
|
const fullPath = path.resolve(options.targetDirectory, file);
|
|
204
281
|
if (!fs.existsSync(fullPath)) continue;
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
282
|
+
const content = fs.readFileSync(fullPath, "utf-8");
|
|
283
|
+
fileContents.set(fullPath, content);
|
|
284
|
+
const matches = [...content.matchAll(/"(@rebasepro\/[^"]+)":\s*"workspace:\*"/g)];
|
|
285
|
+
for (const match of matches) {
|
|
286
|
+
allPackages.add(match[1]);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
console.log(chalk.gray(" Resolving package versions..."));
|
|
290
|
+
await Promise.all(Array.from(allPackages).map(getPackageVersion));
|
|
291
|
+
for (const [fullPath, originalContent] of fileContents.entries()) {
|
|
292
|
+
let content = originalContent.replace(/\{\{PROJECT_NAME\}\}/g, options.projectName);
|
|
293
|
+
const matches = [...content.matchAll(/"(@rebasepro\/[^"]+)":\s*"workspace:\*"/g)];
|
|
294
|
+
for (const match of matches) {
|
|
295
|
+
const pkgName = match[1];
|
|
296
|
+
const resolvedVersion = versionCache.get(pkgName) || "latest";
|
|
297
|
+
content = content.replace(new RegExp(`"${pkgName}":\\s*"workspace:\\*"`, "g"), `"${pkgName}": "${resolvedVersion}"`);
|
|
298
|
+
}
|
|
208
299
|
fs.writeFileSync(fullPath, content, "utf-8");
|
|
209
300
|
}
|
|
210
301
|
}
|
|
@@ -378,6 +469,7 @@ function resolvePluginCliScript(backendDir, pluginName) {
|
|
|
378
469
|
path.join(backendDir, "node_modules", pluginName, "src", "cli.ts"),
|
|
379
470
|
path.join(backendDir, "node_modules", pluginName, "dist", "cli.js"),
|
|
380
471
|
// For monorepo dev mode:
|
|
472
|
+
path.resolve(backendDir, "..", "..", "..", "packages", pluginName.replace("@rebasepro/", ""), "src", "cli.ts"),
|
|
381
473
|
path.resolve(backendDir, "..", "..", "packages", pluginName.replace("@rebasepro/", ""), "src", "cli.ts"),
|
|
382
474
|
path.resolve(backendDir, "..", "packages", pluginName.replace("@rebasepro/", ""), "src", "cli.ts")
|
|
383
475
|
];
|
|
@@ -500,11 +592,15 @@ ${chalk.green.bold("Usage")}
|
|
|
500
592
|
${chalk.green.bold("Commands")}
|
|
501
593
|
${chalk.gray("(Commands are provided by your active database driver plugin)")}
|
|
502
594
|
${chalk.blue.bold("generate")} Generate Schema from collection definitions
|
|
595
|
+
${chalk.blue.bold("introspect")} Introspect an existing database to generate collection definitions
|
|
503
596
|
|
|
504
597
|
${chalk.green.bold("generate Options")}
|
|
505
598
|
${chalk.blue("--collections, -c")} Path to collections directory
|
|
506
599
|
${chalk.blue("--output, -o")} Output path for generated schema
|
|
507
600
|
${chalk.blue("--watch, -w")} Watch for changes and regenerate automatically
|
|
601
|
+
|
|
602
|
+
${chalk.green.bold("introspect Options")}
|
|
603
|
+
${chalk.blue("--output, -o")} Output directory for generated collection files
|
|
508
604
|
`);
|
|
509
605
|
}
|
|
510
606
|
async function dbCommand(subcommand, rawArgs) {
|