@rebasepro/cli 0.0.1-canary.d44c30b → 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 +116 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +116 -13
- 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 +3 -3
- package/templates/template/config/collections/posts.ts +3 -3
- package/templates/template/frontend/package.json +1 -1
- 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,16 +80,31 @@ 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
|
-
const
|
|
85
|
-
const
|
|
97
|
+
const targetDirectory = path.resolve(process.cwd(), nameArg || answers.projectName);
|
|
98
|
+
const projectName = path.basename(targetDirectory);
|
|
86
99
|
const templateDirectory = path.resolve(cliRoot, "templates", "template");
|
|
87
100
|
return {
|
|
88
101
|
projectName,
|
|
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("");
|
|
@@ -193,11 +242,60 @@ async function replacePlaceholders(options) {
|
|
|
193
242
|
"config/package.json",
|
|
194
243
|
"frontend/index.html"
|
|
195
244
|
];
|
|
245
|
+
const packageJsonPath = path.resolve(cliRoot, "package.json");
|
|
246
|
+
let cliVersion = "latest";
|
|
247
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
248
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
249
|
+
cliVersion = pkg.version || "latest";
|
|
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();
|
|
196
279
|
for (const file of filesToProcess) {
|
|
197
280
|
const fullPath = path.resolve(options.targetDirectory, file);
|
|
198
281
|
if (!fs.existsSync(fullPath)) continue;
|
|
199
|
-
|
|
200
|
-
|
|
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
|
+
}
|
|
201
299
|
fs.writeFileSync(fullPath, content, "utf-8");
|
|
202
300
|
}
|
|
203
301
|
}
|
|
@@ -371,6 +469,7 @@ function resolvePluginCliScript(backendDir, pluginName) {
|
|
|
371
469
|
path.join(backendDir, "node_modules", pluginName, "src", "cli.ts"),
|
|
372
470
|
path.join(backendDir, "node_modules", pluginName, "dist", "cli.js"),
|
|
373
471
|
// For monorepo dev mode:
|
|
472
|
+
path.resolve(backendDir, "..", "..", "..", "packages", pluginName.replace("@rebasepro/", ""), "src", "cli.ts"),
|
|
374
473
|
path.resolve(backendDir, "..", "..", "packages", pluginName.replace("@rebasepro/", ""), "src", "cli.ts"),
|
|
375
474
|
path.resolve(backendDir, "..", "packages", pluginName.replace("@rebasepro/", ""), "src", "cli.ts")
|
|
376
475
|
];
|
|
@@ -493,11 +592,15 @@ ${chalk.green.bold("Usage")}
|
|
|
493
592
|
${chalk.green.bold("Commands")}
|
|
494
593
|
${chalk.gray("(Commands are provided by your active database driver plugin)")}
|
|
495
594
|
${chalk.blue.bold("generate")} Generate Schema from collection definitions
|
|
595
|
+
${chalk.blue.bold("introspect")} Introspect an existing database to generate collection definitions
|
|
496
596
|
|
|
497
597
|
${chalk.green.bold("generate Options")}
|
|
498
598
|
${chalk.blue("--collections, -c")} Path to collections directory
|
|
499
599
|
${chalk.blue("--output, -o")} Output path for generated schema
|
|
500
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
|
|
501
604
|
`);
|
|
502
605
|
}
|
|
503
606
|
async function dbCommand(subcommand, rawArgs) {
|