create-kide-app 0.1.10 → 0.2.3
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 +6 -4
- package/index.js +114 -57
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,17 +11,19 @@ pnpm create kide-app my-project
|
|
|
11
11
|
The CLI asks for:
|
|
12
12
|
|
|
13
13
|
1. **Project name** — directory to create
|
|
14
|
-
2. **
|
|
15
|
-
3. **
|
|
14
|
+
2. **Distribution mode** — Package (recommended: thin project + `@kidecms/core` npm dependency; `pnpm exec kide eject` converts to embedded later, one-way) or Embedded (full CMS source in `src/cms/`, yours to modify)
|
|
15
|
+
3. **Deploy target** — Local/Node.js or Cloudflare
|
|
16
|
+
|
|
17
|
+
Every project starts bare-bones: one `pages` collection (`title`, `slug`, `body`) and a minimal public page — no demo content, no seeds.
|
|
16
18
|
|
|
17
19
|
## What it does
|
|
18
20
|
|
|
19
|
-
- Clones the latest Kide CMS from GitHub.
|
|
21
|
+
- Clones the latest Kide CMS release from GitHub (package mode then swaps the embedded runtime for the published `@kidecms/core` at the same version).
|
|
20
22
|
- Applies target-specific configuration (Node.js adapter, or Cloudflare D1/R2/Workers).
|
|
21
23
|
- Installs dependencies with pnpm.
|
|
22
24
|
- Optionally creates a GitHub repo (if the `gh` CLI is installed and authenticated).
|
|
23
25
|
- Generates the CMS schema.
|
|
24
|
-
- For **local**:
|
|
26
|
+
- For **local**: starts the dev server.
|
|
25
27
|
- For **Cloudflare**: logs into wrangler (if needed), creates a D1 database and R2 bucket, applies migrations, builds and deploys, and prints the live URL + admin URL.
|
|
26
28
|
|
|
27
29
|
## Requirements
|
package/index.js
CHANGED
|
@@ -51,6 +51,8 @@ const CLEANUP = [
|
|
|
51
51
|
"docs",
|
|
52
52
|
"CLAUDE.md",
|
|
53
53
|
".claude/settings.local.json",
|
|
54
|
+
".github/workflows", // upstream CI + @kidecms/core release pipeline — wrong in any scaffold
|
|
55
|
+
"scripts/verify-cloudflare.mjs", // needs the adapters/ overlay, which every scaffold deletes
|
|
54
56
|
"data",
|
|
55
57
|
".cms-data",
|
|
56
58
|
"dist",
|
|
@@ -58,6 +60,20 @@ const CLEANUP = [
|
|
|
58
60
|
".DS_Store",
|
|
59
61
|
];
|
|
60
62
|
|
|
63
|
+
// Managed runtime dirs inside src/cms — the contents of the @kidecms/core
|
|
64
|
+
// package. Deleted in package mode (the npm dependency provides them);
|
|
65
|
+
// everything else in src/cms (cms.config, collections, adapters, fields,
|
|
66
|
+
// runtime.ts, migrations) is project-owned and stays in both modes.
|
|
67
|
+
const MANAGED_DIRS = [
|
|
68
|
+
"admin",
|
|
69
|
+
"client",
|
|
70
|
+
"core",
|
|
71
|
+
"internals",
|
|
72
|
+
"middleware",
|
|
73
|
+
"platform",
|
|
74
|
+
"routes",
|
|
75
|
+
];
|
|
76
|
+
|
|
61
77
|
// The project name reaches shell commands (git, wrangler) and path.resolve, so it is
|
|
62
78
|
// validated before either. Restricting it to one path segment of safe characters keeps
|
|
63
79
|
// `$(...)`, backticks, `;` and separators out of those commands and out of the target
|
|
@@ -126,7 +142,30 @@ async function main() {
|
|
|
126
142
|
process.exit(1);
|
|
127
143
|
}
|
|
128
144
|
|
|
129
|
-
// 2.
|
|
145
|
+
// 2. Distribution mode — package is the recommended default; embedded stays
|
|
146
|
+
// first-class for teams that want to own and modify the runtime source.
|
|
147
|
+
const mode = await p.select({
|
|
148
|
+
message: "How do you want the CMS runtime?",
|
|
149
|
+
options: [
|
|
150
|
+
{
|
|
151
|
+
label: "Package",
|
|
152
|
+
value: "package",
|
|
153
|
+
hint: "@kidecms/core dependency",
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
label: "Embedded",
|
|
157
|
+
value: "embedded",
|
|
158
|
+
hint: "full CMS source in src/cms/, yours to modify",
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
if (p.isCancel(mode)) {
|
|
164
|
+
p.cancel("Setup cancelled.");
|
|
165
|
+
process.exit(0);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// 3. Deploy target
|
|
130
169
|
const target = await p.select({
|
|
131
170
|
message: "Where will you deploy?",
|
|
132
171
|
options: [
|
|
@@ -140,21 +179,6 @@ async function main() {
|
|
|
140
179
|
process.exit(0);
|
|
141
180
|
}
|
|
142
181
|
|
|
143
|
-
// 3. Demo content (local only — Cloudflare uses remote D1)
|
|
144
|
-
let seedDemo = false;
|
|
145
|
-
if (target === "local") {
|
|
146
|
-
const seed = await p.confirm({
|
|
147
|
-
message: "Seed database with demo content?",
|
|
148
|
-
initialValue: false,
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
if (p.isCancel(seed)) {
|
|
152
|
-
p.cancel("Setup cancelled.");
|
|
153
|
-
process.exit(0);
|
|
154
|
-
}
|
|
155
|
-
seedDemo = seed;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
182
|
const s = p.spinner();
|
|
159
183
|
|
|
160
184
|
// --- Scaffold via git clone ---
|
|
@@ -197,10 +221,46 @@ async function main() {
|
|
|
197
221
|
rmSync(path.join(projectDir, f), { recursive: true, force: true });
|
|
198
222
|
}
|
|
199
223
|
|
|
224
|
+
// Both modes scaffold the same template at the same tag; package mode then
|
|
225
|
+
// deletes the managed runtime dirs and swaps the workspace link for the
|
|
226
|
+
// published @kidecms/core at exactly that version — same source either way.
|
|
227
|
+
const corePkgPath = path.join(projectDir, "src/cms/package.json");
|
|
228
|
+
let coreVersion = null;
|
|
229
|
+
if (existsSync(corePkgPath)) {
|
|
230
|
+
coreVersion = JSON.parse(readFileSync(corePkgPath, "utf-8")).version;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (mode === "package") {
|
|
234
|
+
if (!coreVersion) {
|
|
235
|
+
s.stop("Scaffolding failed");
|
|
236
|
+
p.cancel(
|
|
237
|
+
"This template release predates package mode — choose Embedded, or wait for the next release.",
|
|
238
|
+
);
|
|
239
|
+
process.exit(1);
|
|
240
|
+
}
|
|
241
|
+
for (const managed of MANAGED_DIRS) {
|
|
242
|
+
rmSync(path.join(projectDir, "src/cms", managed), {
|
|
243
|
+
recursive: true,
|
|
244
|
+
force: true,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
rmSync(corePkgPath, { force: true });
|
|
248
|
+
rmSync(path.join(projectDir, "pnpm-workspace.yaml"), { force: true });
|
|
249
|
+
// Upstream distribution tooling that assumes the embedded workspace package.
|
|
250
|
+
rmSync(path.join(projectDir, "scripts/verify-pack.mjs"), { force: true });
|
|
251
|
+
rmSync(path.join(projectDir, "scripts/verify-package-mode.mjs"), {
|
|
252
|
+
force: true,
|
|
253
|
+
});
|
|
254
|
+
// Worker tests and the Cloudflare type profile live in the deleted
|
|
255
|
+
// src/cms/platform — their configs would match zero files.
|
|
256
|
+
rmSync(path.join(projectDir, "vitest.workers.config.ts"), { force: true });
|
|
257
|
+
rmSync(path.join(projectDir, "tsconfig.cloudflare.json"), { force: true });
|
|
258
|
+
}
|
|
259
|
+
|
|
200
260
|
s.stop(
|
|
201
261
|
templateRef
|
|
202
|
-
? `Project scaffolded from ${templateRef}`
|
|
203
|
-
:
|
|
262
|
+
? `Project scaffolded from ${templateRef} (${mode})`
|
|
263
|
+
: `Project scaffolded (${mode})`,
|
|
204
264
|
);
|
|
205
265
|
|
|
206
266
|
// --- Apply target-specific files ---
|
|
@@ -224,12 +284,18 @@ async function main() {
|
|
|
224
284
|
);
|
|
225
285
|
writeFileSync(
|
|
226
286
|
path.join(projectDir, "src/cms/adapters/db.ts"),
|
|
227
|
-
'export * from "
|
|
287
|
+
'export * from "@kidecms/core/platform/cloudflare/database";\n',
|
|
228
288
|
);
|
|
229
289
|
writeFileSync(
|
|
230
290
|
path.join(projectDir, "src/cms/adapters/storage.ts"),
|
|
231
|
-
'export * from "
|
|
291
|
+
'export * from "@kidecms/core/platform/cloudflare/storage";\n',
|
|
232
292
|
);
|
|
293
|
+
// The adapter test asserts Node filesystem storage — meaningless (and failing)
|
|
294
|
+
// once the adapter re-exports the R2 profile.
|
|
295
|
+
rmSync(path.join(projectDir, "src/cms/adapters/__tests__"), {
|
|
296
|
+
recursive: true,
|
|
297
|
+
force: true,
|
|
298
|
+
});
|
|
233
299
|
}
|
|
234
300
|
|
|
235
301
|
const pkgPath = path.join(projectDir, "package.json");
|
|
@@ -237,6 +303,31 @@ async function main() {
|
|
|
237
303
|
|
|
238
304
|
pkg.name = projectName;
|
|
239
305
|
|
|
306
|
+
// Upstream-repo tooling that no scaffold can run (needs the deleted adapters/ overlay).
|
|
307
|
+
delete pkg.scripts["verify:cloudflare"];
|
|
308
|
+
|
|
309
|
+
if (mode === "package" && pkg.dependencies["@kidecms/core"]) {
|
|
310
|
+
pkg.dependencies["@kidecms/core"] = `^${coreVersion}`;
|
|
311
|
+
delete pkg.scripts["verify:pack"];
|
|
312
|
+
delete pkg.scripts["verify:package"];
|
|
313
|
+
// The runtime (and its worker tests + Cloudflare type profile) now lives in
|
|
314
|
+
// node_modules — keep check/test scoped to project code, and let vitest pass
|
|
315
|
+
// until the project has tests of its own.
|
|
316
|
+
delete pkg.scripts["test:workers"];
|
|
317
|
+
delete pkg.scripts["check:cloudflare"];
|
|
318
|
+
pkg.scripts.check = "astro check && eslint .";
|
|
319
|
+
pkg.scripts.test = "pnpm cms:generate && vitest run --passWithNoTests";
|
|
320
|
+
// Upstream test-fixture tooling lives in the deleted core/__tests__ tree.
|
|
321
|
+
delete pkg.scripts["test:fixtures"];
|
|
322
|
+
rmSync(path.join(projectDir, "scripts/generate-test-fixtures.ts"), {
|
|
323
|
+
force: true,
|
|
324
|
+
});
|
|
325
|
+
// Dev tooling for the deleted worker tests / Cloudflare type profile.
|
|
326
|
+
delete pkg.devDependencies["@cloudflare/vitest-pool-workers"];
|
|
327
|
+
delete pkg.devDependencies["@cloudflare/workers-types"];
|
|
328
|
+
delete pkg.devDependencies["jsdom"];
|
|
329
|
+
}
|
|
330
|
+
|
|
240
331
|
if (target === "cloudflare") {
|
|
241
332
|
delete pkg.dependencies["@astrojs/node"];
|
|
242
333
|
pkg.dependencies["@astrojs/cloudflare"] = "~14.1.7";
|
|
@@ -268,7 +359,7 @@ async function main() {
|
|
|
268
359
|
);
|
|
269
360
|
writeFileSync(path.join(projectDir, "wrangler.toml"), wranglerContent);
|
|
270
361
|
|
|
271
|
-
pkg.devDependencies.wrangler = "^4.
|
|
362
|
+
pkg.devDependencies.wrangler = "^4.121.0";
|
|
272
363
|
|
|
273
364
|
pkg.scripts.dev = "astro dev";
|
|
274
365
|
pkg.scripts.build = "astro build";
|
|
@@ -308,10 +399,11 @@ async function main() {
|
|
|
308
399
|
}
|
|
309
400
|
const versionStamp = {
|
|
310
401
|
template: REPO.replace(/\.git$/, ""),
|
|
311
|
-
kideVersion: pkg.version ?? null,
|
|
402
|
+
kideVersion: coreVersion ?? pkg.version ?? null,
|
|
312
403
|
ref: templateRef ?? "HEAD",
|
|
313
404
|
commit: templateCommit,
|
|
314
405
|
target,
|
|
406
|
+
mode,
|
|
315
407
|
corePath: "src/cms",
|
|
316
408
|
scaffoldedAt: new Date().toISOString(),
|
|
317
409
|
createKideApp: cliVersion,
|
|
@@ -475,41 +567,6 @@ async function main() {
|
|
|
475
567
|
s.stop("Schema generation failed — run `cms:generate` manually");
|
|
476
568
|
}
|
|
477
569
|
|
|
478
|
-
// --- Seed demo content ---
|
|
479
|
-
|
|
480
|
-
if (seedDemo && target === "local") {
|
|
481
|
-
s.start("Pushing schema to database");
|
|
482
|
-
// The guarded sync script (exits non-zero on failure, creates data/ itself) —
|
|
483
|
-
// same path the dev server and deploys use.
|
|
484
|
-
try {
|
|
485
|
-
execSync(`${pm.run} cms:push`, { cwd: projectDir, stdio: "pipe" });
|
|
486
|
-
s.stop("Schema pushed");
|
|
487
|
-
} catch {
|
|
488
|
-
s.stop("Schema push failed — run `pnpm cms:push` manually");
|
|
489
|
-
}
|
|
490
|
-
s.start("Seeding demo content");
|
|
491
|
-
try {
|
|
492
|
-
execSync(`${pm.run} cms:seed`, { cwd: projectDir, stdio: "pipe" });
|
|
493
|
-
s.stop("Demo content seeded");
|
|
494
|
-
} catch (err) {
|
|
495
|
-
s.stop("Seeding failed — run `pnpm cms:seed` manually");
|
|
496
|
-
if (err.stderr) console.error(err.stderr.toString());
|
|
497
|
-
if (err.stdout) console.error(err.stdout.toString());
|
|
498
|
-
}
|
|
499
|
-
} else if (seedDemo && target === "cloudflare") {
|
|
500
|
-
p.note(
|
|
501
|
-
[
|
|
502
|
-
"Seeding for Cloudflare requires a D1 database.",
|
|
503
|
-
"",
|
|
504
|
-
` ${pm.dlx} wrangler d1 create ${projectName}-db`,
|
|
505
|
-
" # then replace the placeholder database_id in wrangler.toml",
|
|
506
|
-
` ${pm.dlx} wrangler d1 migrations apply ${projectName}-db --local`,
|
|
507
|
-
` ${pm.run} cms:seed`,
|
|
508
|
-
].join("\n"),
|
|
509
|
-
"Seed manually",
|
|
510
|
-
);
|
|
511
|
-
}
|
|
512
|
-
|
|
513
570
|
// --- Cloudflare resource setup ---
|
|
514
571
|
|
|
515
572
|
const cf = {
|