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.
Files changed (3) hide show
  1. package/README.md +6 -4
  2. package/index.js +114 -57
  3. 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. **Deploy target** — Local/Node.js or Cloudflare
15
- 3. **Seed demo content** — local target only
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**: optionally seeds demo content, then starts the dev server.
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. Deploy target
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
- : "Project scaffolded",
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 "../platform/cloudflare/database";\n',
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 "../platform/cloudflare/storage";\n',
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.83.0";
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 = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-kide-app",
3
- "version": "0.1.10",
3
+ "version": "0.2.3",
4
4
  "description": "Scaffold a new Kide CMS project",
5
5
  "author": "Matti Hernesniemi",
6
6
  "license": "MIT",