create-kide-app 0.0.17 → 0.0.19
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/index.js +73 -23
- package/package.json +1 -1
- package/templates/cloudflare/drizzle.config.ts +12 -6
package/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import * as p from "@clack/prompts";
|
|
4
|
-
import { execSync } from "node:child_process";
|
|
4
|
+
import { execSync, spawn } from "node:child_process";
|
|
5
5
|
import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
@@ -9,6 +9,24 @@ import { fileURLToPath } from "node:url";
|
|
|
9
9
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
10
|
const TEMPLATES_DIR = path.join(__dirname, "templates");
|
|
11
11
|
|
|
12
|
+
// Async spawn wrapper so long-running commands don't block clack spinners
|
|
13
|
+
const runAsync = (cmd, cwd) =>
|
|
14
|
+
new Promise((resolve, reject) => {
|
|
15
|
+
const child = spawn(cmd, { cwd, shell: true });
|
|
16
|
+
let stdout = "";
|
|
17
|
+
let stderr = "";
|
|
18
|
+
child.stdout.on("data", (d) => (stdout += d.toString()));
|
|
19
|
+
child.stderr.on("data", (d) => (stderr += d.toString()));
|
|
20
|
+
child.on("close", (code) => {
|
|
21
|
+
if (code === 0) resolve(stdout);
|
|
22
|
+
else {
|
|
23
|
+
const err = new Error(`Command failed: ${cmd}`);
|
|
24
|
+
err.stderr = stderr;
|
|
25
|
+
reject(err);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
12
30
|
// --- Package manager detection ---
|
|
13
31
|
|
|
14
32
|
const pm = { name: "pnpm", exec: "pnpm dlx", run: "pnpm", install: "pnpm install" };
|
|
@@ -150,7 +168,7 @@ async function main() {
|
|
|
150
168
|
|
|
151
169
|
s.start("Installing dependencies");
|
|
152
170
|
try {
|
|
153
|
-
|
|
171
|
+
await runAsync(pm.install, projectDir);
|
|
154
172
|
s.stop("Dependencies installed");
|
|
155
173
|
} catch {
|
|
156
174
|
s.stop(`${pm.install} failed — run it manually`);
|
|
@@ -199,7 +217,7 @@ async function main() {
|
|
|
199
217
|
|
|
200
218
|
// --- Cloudflare resource setup ---
|
|
201
219
|
|
|
202
|
-
const cf = { d1Created: false, r2Created: false, migrationsApplied: false };
|
|
220
|
+
const cf = { d1Created: false, r2Created: false, migrationsApplied: false, deployed: false, url: null };
|
|
203
221
|
if (target === "cloudflare") {
|
|
204
222
|
const setupNow = await p.confirm({
|
|
205
223
|
message: "Set up Cloudflare resources now? (creates D1 database and R2 bucket)",
|
|
@@ -290,8 +308,10 @@ async function main() {
|
|
|
290
308
|
try {
|
|
291
309
|
execSync(`${pm.exec} drizzle-kit generate`, { cwd: projectDir, stdio: "pipe" });
|
|
292
310
|
s.stop("Migrations generated");
|
|
293
|
-
} catch {
|
|
311
|
+
} catch (err) {
|
|
294
312
|
s.stop("Migration generation failed");
|
|
313
|
+
if (err.stderr) console.error(err.stderr.toString().slice(-800));
|
|
314
|
+
if (err.stdout) console.error(err.stdout.toString().slice(-800));
|
|
295
315
|
}
|
|
296
316
|
|
|
297
317
|
s.start("Applying migrations to remote D1");
|
|
@@ -299,6 +319,7 @@ async function main() {
|
|
|
299
319
|
execSync(`${pm.exec} wrangler d1 migrations apply ${projectName}-db --remote`, {
|
|
300
320
|
cwd: projectDir,
|
|
301
321
|
stdio: "pipe",
|
|
322
|
+
input: "y\n",
|
|
302
323
|
});
|
|
303
324
|
cf.migrationsApplied = true;
|
|
304
325
|
s.stop("Migrations applied");
|
|
@@ -306,6 +327,27 @@ async function main() {
|
|
|
306
327
|
s.stop("Migration apply failed — run manually with: wrangler d1 migrations apply --remote");
|
|
307
328
|
}
|
|
308
329
|
}
|
|
330
|
+
|
|
331
|
+
// Deploy to Cloudflare
|
|
332
|
+
if (cf.migrationsApplied) {
|
|
333
|
+
const doDeploy = await p.confirm({
|
|
334
|
+
message: "Deploy to Cloudflare now?",
|
|
335
|
+
initialValue: true,
|
|
336
|
+
});
|
|
337
|
+
if (!p.isCancel(doDeploy) && doDeploy) {
|
|
338
|
+
s.start("Building and deploying to Cloudflare");
|
|
339
|
+
try {
|
|
340
|
+
const deployOutput = await runAsync(`${pm.run} deploy`, projectDir);
|
|
341
|
+
const urlMatch = deployOutput.match(/https:\/\/[^\s]+\.workers\.dev/);
|
|
342
|
+
if (urlMatch) cf.url = urlMatch[0];
|
|
343
|
+
cf.deployed = true;
|
|
344
|
+
s.stop("Deployed to Cloudflare");
|
|
345
|
+
} catch (err) {
|
|
346
|
+
s.stop("Deploy failed — run manually with: pnpm run deploy");
|
|
347
|
+
if (err.stderr) console.error(err.stderr.slice(-500));
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
309
351
|
}
|
|
310
352
|
}
|
|
311
353
|
}
|
|
@@ -321,26 +363,34 @@ async function main() {
|
|
|
321
363
|
console.log(` To start again: cd ${projectName} && pnpm dev\n`);
|
|
322
364
|
}
|
|
323
365
|
} else {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
)
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
366
|
+
if (cf.deployed && cf.url) {
|
|
367
|
+
p.note([`Live at: ${cf.url}`, `Admin: ${cf.url}/admin`, "", `cd ${projectName}`, "", "Local development:", ` ${pm.run} dev`, "", "Redeploy:", " pnpm run deploy"].join("\n"), "🎉 Your Kide CMS is live");
|
|
368
|
+
p.outro("Project created!");
|
|
369
|
+
} else {
|
|
370
|
+
const lines = [`cd ${projectName}`];
|
|
371
|
+
const remaining = [];
|
|
372
|
+
if (!cf.d1Created) {
|
|
373
|
+
remaining.push(
|
|
374
|
+
` ${pm.exec} wrangler d1 create ${projectName}-db`,
|
|
375
|
+
" # Copy the database_id to wrangler.toml",
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
if (!cf.r2Created) {
|
|
379
|
+
remaining.push(` ${pm.exec} wrangler r2 bucket create ${projectName}-assets`);
|
|
380
|
+
}
|
|
381
|
+
if (!cf.migrationsApplied) {
|
|
382
|
+
remaining.push(` ${pm.exec} wrangler d1 migrations apply ${projectName}-db --remote`);
|
|
383
|
+
}
|
|
384
|
+
if (!cf.deployed) {
|
|
385
|
+
remaining.push(` ${pm.run} run deploy`);
|
|
386
|
+
}
|
|
387
|
+
if (remaining.length > 0) {
|
|
388
|
+
lines.push("", "Remaining setup:", ...remaining);
|
|
389
|
+
}
|
|
390
|
+
lines.push("", "Local development:", ` ${pm.run} dev`);
|
|
391
|
+
p.note(lines.join("\n"), "Next steps");
|
|
392
|
+
p.outro("Project created!");
|
|
340
393
|
}
|
|
341
|
-
lines.push("", "Local development:", ` ${pm.run} dev`, "", "Deploy:", " pnpm run deploy");
|
|
342
|
-
p.note(lines.join("\n"), "Next steps");
|
|
343
|
-
p.outro("Project created!");
|
|
344
394
|
}
|
|
345
395
|
}
|
|
346
396
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
import { readdirSync } from "node:fs";
|
|
1
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
2
2
|
import { defineConfig } from "drizzle-kit";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// Look for the local D1 sqlite file (created by wrangler after first run).
|
|
5
|
+
// Returns null if it doesn't exist yet — `drizzle-kit generate` doesn't need it.
|
|
6
|
+
function getLocalD1Path(): string | null {
|
|
5
7
|
const dir = ".wrangler/state/v3/d1/miniflare-D1DatabaseObject";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
if (!existsSync(dir)) return null;
|
|
9
|
+
try {
|
|
10
|
+
const file = readdirSync(dir).find((f) => f.endsWith(".sqlite") && f !== "*.sqlite");
|
|
11
|
+
return file ? `${dir}/${file}` : null;
|
|
12
|
+
} catch {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
9
15
|
}
|
|
10
16
|
|
|
11
17
|
export default defineConfig({
|
|
@@ -13,6 +19,6 @@ export default defineConfig({
|
|
|
13
19
|
out: "./src/cms/migrations",
|
|
14
20
|
dialect: "sqlite",
|
|
15
21
|
dbCredentials: {
|
|
16
|
-
url: getLocalD1Path(),
|
|
22
|
+
url: getLocalD1Path() ?? ":memory:",
|
|
17
23
|
},
|
|
18
24
|
});
|