@puckeditor/cli 0.24.0-canary.301a0304 → 0.24.0-canary.55558da4

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 CHANGED
@@ -22,6 +22,7 @@ npx @puckeditor/cli add cloud # connect Puck Cloud
22
22
  npx @puckeditor/cli add ai # add the Puck AI plugin
23
23
  npx @puckeditor/cli status # show what's set up
24
24
  npx @puckeditor/cli doctor # diagnose problems
25
+ npx @puckeditor/cli frameworks # show supported frameworks and versions
25
26
  npx @puckeditor/cli docs # read the docs for this version
26
27
  ```
27
28
 
package/dist/bin.mjs CHANGED
@@ -190,12 +190,13 @@ var resolveInstalledVersion = (vfs, fromDir, name) => {
190
190
  dir = parent;
191
191
  }
192
192
  };
193
- var majorOf = (versionOrRange) => {
193
+ var versionOf = (versionOrRange) => {
194
194
  if (!versionOrRange) return null;
195
195
  const cleaned = versionOrRange.replace(/^(workspace:|npm:[^@]+@)/, "");
196
- const match = /(\d+)(?:\.\d+)?/.exec(cleaned);
197
- return match ? Number(match[1]) : null;
196
+ const match = /(\d+)(?:\.(\d+))?/.exec(cleaned);
197
+ return match ? [Number(match[1]), Number(match[2] ?? 0)] : null;
198
198
  };
199
+ var majorOf = (versionOrRange) => versionOf(versionOrRange)?.[0] ?? null;
199
200
 
200
201
  // src/detect/server.ts
201
202
  import path2 from "path";
@@ -283,7 +284,42 @@ var FRAMEWORK_LABELS = {
283
284
  hono: "Hono",
284
285
  express: "Express"
285
286
  };
287
+ var MIN_VERSIONS = {
288
+ next: "15",
289
+ "react-router": "7",
290
+ // Server route handlers on createFileRoute arrived in the Start RC
291
+ "tanstack-start": "1.132",
292
+ // vinext 1.0 moved to Vite 8, which the recipe uses
293
+ vinext: "1",
294
+ // @hono/vite-dev-server is built and tested against Vite 6
295
+ vite: "6",
296
+ // @astrojs/node 11, which `astro add node` installs, needs Astro 7
297
+ astro: "7",
298
+ // @hono/node-server 2 needs Hono 4
299
+ hono: "4",
300
+ // express.json() arrived in 4.16
301
+ express: "4.16"
302
+ };
286
303
  var SUPPORTED_FRAMEWORKS = "Next.js (App Router), React Router 7 framework mode, TanStack Start, vinext, Astro and Vite React apps, or a Hono or Express server";
304
+ var unsupportedVersion = (id, version, range) => {
305
+ const found = versionOf(version) ?? versionOf(range);
306
+ const [major, minor] = versionOf(MIN_VERSIONS[id]);
307
+ if (!found || found[0] > major || found[0] === major && found[1] >= minor)
308
+ return null;
309
+ const label2 = FRAMEWORK_LABELS[id];
310
+ return {
311
+ status: "unsupported",
312
+ error: {
313
+ code: "PUCK-CLI-UNSUPPORTED-FRAMEWORK-VERSION",
314
+ message: `${label2} ${version ?? range} is not supported. Upgrade to ${label2} ${MIN_VERSIONS[id]} or later, or integrate Puck manually.`,
315
+ details: {
316
+ docs: MANUAL_INTEGRATION_DOCS_URL,
317
+ version: version ?? range,
318
+ minVersion: MIN_VERSIONS[id]
319
+ }
320
+ }
321
+ };
322
+ };
287
323
  var firstExisting = (vfs, root, candidates) => candidates.find((c) => vfs.exists(path3.join(root, c))) ?? null;
288
324
  var CONFIG_EXTENSIONS = ["ts", "mts", "js", "mjs", "cts", "cjs"];
289
325
  var findViteConfig = (vfs, root) => firstExisting(
@@ -338,19 +374,8 @@ var detectNext = (vfs, root, range) => {
338
374
  const major = majorOf(version) ?? majorOf(range) ?? 16;
339
375
  const layout = detectAppRouter(vfs, root, "Next.js");
340
376
  if ("status" in layout) return layout;
341
- if (major < 15) {
342
- return {
343
- status: "unsupported",
344
- error: {
345
- code: "PUCK-CLI-UNSUPPORTED-FRAMEWORK-VERSION",
346
- message: `Next.js ${version ?? range} is not supported. Upgrade to Next.js 15 or later, or integrate Puck manually.`,
347
- details: {
348
- docs: MANUAL_INTEGRATION_DOCS_URL,
349
- version: version ?? range
350
- }
351
- }
352
- };
353
- }
377
+ const tooOld = unsupportedVersion("next", version, range);
378
+ if (tooOld) return tooOld;
354
379
  return {
355
380
  status: "detected",
356
381
  info: {
@@ -364,6 +389,8 @@ var detectNext = (vfs, root, range) => {
364
389
  };
365
390
  var detectVinext = (vfs, root, range) => {
366
391
  const version = resolveInstalledVersion(vfs, root, "vinext");
392
+ const tooOld = unsupportedVersion("vinext", version, range);
393
+ if (tooOld) return tooOld;
367
394
  const layout = detectAppRouter(vfs, root, "vinext");
368
395
  if ("status" in layout) return layout;
369
396
  const base = layout.baseDir ? `${layout.baseDir}/` : "";
@@ -385,16 +412,8 @@ var detectVinext = (vfs, root, range) => {
385
412
  var detectReactRouter = (vfs, root, range) => {
386
413
  const version = resolveInstalledVersion(vfs, root, "@react-router/dev") ?? resolveInstalledVersion(vfs, root, "react-router");
387
414
  const major = majorOf(version) ?? majorOf(range);
388
- if (major !== null && major < 7) {
389
- return {
390
- status: "unsupported",
391
- error: {
392
- code: "PUCK-CLI-UNSUPPORTED-FRAMEWORK-VERSION",
393
- message: `React Router ${version ?? range} is not supported. Upgrade to React Router 7 framework mode.`,
394
- details: { docs: MANUAL_INTEGRATION_DOCS_URL }
395
- }
396
- };
397
- }
415
+ const tooOld = unsupportedVersion("react-router", version, range);
416
+ if (tooOld) return tooOld;
398
417
  const configFile = firstExisting(
399
418
  vfs,
400
419
  root,
@@ -456,6 +475,8 @@ var detectReactRouter = (vfs, root, range) => {
456
475
  };
457
476
  var detectTanStackStart = (vfs, root, range) => {
458
477
  const version = resolveInstalledVersion(vfs, root, "@tanstack/react-start");
478
+ const tooOld = unsupportedVersion("tanstack-start", version, range);
479
+ if (tooOld) return tooOld;
459
480
  const viteConfig = findViteConfig(vfs, root);
460
481
  const code = viteConfig ? vfs.readText(path3.join(root, viteConfig)) ?? "" : "";
461
482
  const dirs = { srcDirectory: "src", routesDirectory: "routes" };
@@ -503,6 +524,8 @@ var detectVite = (vfs, root, range, deps) => {
503
524
  (f) => Boolean(f) && vfs.exists(path3.join(root, f))
504
525
  ) ?? null;
505
526
  const version = resolveInstalledVersion(vfs, root, "vite");
527
+ const tooOld = unsupportedVersion("vite", version, range);
528
+ if (tooOld) return tooOld;
506
529
  const viteConfig = findViteConfig(vfs, root);
507
530
  const code = viteConfig ? vfs.readText(path3.join(root, viteConfig)) ?? "" : "";
508
531
  return {
@@ -527,6 +550,8 @@ var ASTRO_ADAPTERS = [
527
550
  ];
528
551
  var detectAstro = (vfs, root, range, deps) => {
529
552
  const version = resolveInstalledVersion(vfs, root, "astro");
553
+ const tooOld = unsupportedVersion("astro", version, range);
554
+ if (tooOld) return tooOld;
530
555
  const config = firstExisting(
531
556
  vfs,
532
557
  root,
@@ -550,6 +575,8 @@ var detectAstro = (vfs, root, range, deps) => {
550
575
  };
551
576
  var detectServer = (id) => (vfs, root, range, deps) => {
552
577
  const version = resolveInstalledVersion(vfs, root, id);
578
+ const tooOld = unsupportedVersion(id, version, range);
579
+ if (tooOld) return tooOld;
553
580
  return {
554
581
  status: "detected",
555
582
  info: {
@@ -775,6 +802,7 @@ var COMMAND_OPTIONS = {
775
802
  status: ["json", "help", "version", "cwd", "workspace", "config"],
776
803
  doctor: ["json", "help", "version", "cwd", "workspace", "config", "offline"],
777
804
  docs: ["json", "help", "version"],
805
+ frameworks: ["json", "help", "version"],
778
806
  help: GLOBAL
779
807
  };
780
808
  var COMMANDS = [
@@ -783,6 +811,7 @@ var COMMANDS = [
783
811
  "status",
784
812
  "doctor",
785
813
  "docs",
814
+ "frameworks",
786
815
  "help"
787
816
  ];
788
817
  var FRAMEWORKS = FRAMEWORK_IDS;
@@ -1132,6 +1161,10 @@ var COMMANDS2 = [
1132
1161
  name: "doctor",
1133
1162
  description: "Diagnose problems and suggest fixes (read-only)"
1134
1163
  },
1164
+ {
1165
+ name: "frameworks",
1166
+ description: "Show the supported frameworks and versions"
1167
+ },
1135
1168
  {
1136
1169
  name: "docs <command>",
1137
1170
  description: "Read the docs for this version: ls, cat <page>, find <query>, grep <text>"
@@ -4671,6 +4704,26 @@ var statusTable = (result) => {
4671
4704
  const width = Math.max(...rows.map(([k]) => k.length), 0) + 2;
4672
4705
  return rows.map(([k, v]) => `${k.padEnd(width)}${v}`);
4673
4706
  };
4707
+ var frameworksTable = (frameworks) => {
4708
+ const rows = [
4709
+ ["Framework", "ID", "Versions", "Editor", "Puck Cloud & AI", "Notes"],
4710
+ ...frameworks.map((f) => [
4711
+ f.name,
4712
+ f.id,
4713
+ `${f.minVersion}+`,
4714
+ f.kind === "server" ? "API only" : "\u2713",
4715
+ f.needsServer ? "needs a server*" : "\u2713",
4716
+ f.notes
4717
+ ])
4718
+ ];
4719
+ const widths = rows[0].map(
4720
+ (_, i) => Math.max(...rows.map((row) => row[i].length))
4721
+ );
4722
+ return rows.map((row, r) => {
4723
+ const line = row.map((cell, i) => i === row.length - 1 ? cell : cell.padEnd(widths[i])).join(" ").trimEnd();
4724
+ return r === 0 ? pc.bold(line) : line;
4725
+ });
4726
+ };
4674
4727
  var presentHuman = (out, result, secrets) => {
4675
4728
  const lines = [];
4676
4729
  const write = () => out.write(secrets.scrub(lines.join("\n")) + "\n");
@@ -4704,6 +4757,18 @@ var presentHuman = (out, result, secrets) => {
4704
4757
  lines.push(` ${" ".repeat(24)} ${pc.cyan(f.fix)}`);
4705
4758
  }
4706
4759
  lines.push("", result.message);
4760
+ } else if (result.command === "frameworks" && result.status !== "error") {
4761
+ lines.push(...frameworksTable(result.frameworks ?? []));
4762
+ const needServer = (result.frameworks ?? []).filter((f) => f.needsServer);
4763
+ if (needServer.length) {
4764
+ lines.push(
4765
+ "",
4766
+ `* ${needServer.map((f) => f.name).join(
4767
+ " and "
4768
+ )} need a server for Puck Cloud and Puck AI, unless they already have one. Choose one with --backend.`
4769
+ );
4770
+ }
4771
+ lines.push("", pc.dim(result.message));
4707
4772
  } else if (result.command === "docs" && result.status !== "error") {
4708
4773
  const { page, pages, matches } = result.docs ?? {};
4709
4774
  if (page) lines.push(page.content.trimEnd());
@@ -4765,7 +4830,7 @@ var presentHuman = (out, result, secrets) => {
4765
4830
  ...result.warnings.map((w) => `${pc.yellow("!")} ${w.message}`)
4766
4831
  );
4767
4832
  }
4768
- if (result.status !== "error" && result.command !== "doctor" && result.command !== "docs" && result.nextSteps.length) {
4833
+ if (result.status !== "error" && result.command !== "doctor" && result.command !== "docs" && result.command !== "frameworks" && result.nextSteps.length) {
4769
4834
  lines.push(
4770
4835
  "",
4771
4836
  pc.bold("Next:"),
@@ -7090,6 +7155,41 @@ var runDocs = async (rc, positionals) => {
7090
7155
  return result;
7091
7156
  };
7092
7157
 
7158
+ // src/commands/frameworks.ts
7159
+ var NOTES = {
7160
+ next: "App Router, in app/ or src/app/",
7161
+ "react-router": "Framework mode",
7162
+ "tanstack-start": "",
7163
+ vinext: "App Router, in app/ or src/app/",
7164
+ vite: "React apps using @vitejs/plugin-react",
7165
+ astro: "Adds React with astro add react if needed",
7166
+ hono: "Serves the APIs for an editor in another app",
7167
+ express: "Serves the APIs for an editor in another app"
7168
+ };
7169
+ var frameworkSupport = () => FRAMEWORK_IDS.map((id) => {
7170
+ const adapter = ADAPTERS[id];
7171
+ return {
7172
+ id,
7173
+ name: FRAMEWORK_LABELS[id],
7174
+ minVersion: MIN_VERSIONS[id],
7175
+ kind: adapter.kind ?? "app",
7176
+ needsServer: Boolean(adapter.backend),
7177
+ notes: NOTES[id]
7178
+ };
7179
+ });
7180
+ var runFrameworks = async (_rc, positionals) => {
7181
+ if (positionals.length > 0) {
7182
+ throw new CliError(
7183
+ "PUCK-CLI-INVALID-ARGS",
7184
+ `\`frameworks\` doesn't take arguments. Run \`${CANONICAL_INVOCATION} frameworks\`.`
7185
+ );
7186
+ }
7187
+ const result = emptyResult("frameworks");
7188
+ result.frameworks = frameworkSupport();
7189
+ result.message = `Create a new app with \`${CANONICAL_INVOCATION} init --framework <id>\`.`;
7190
+ return result;
7191
+ };
7192
+
7093
7193
  // src/cli.ts
7094
7194
  var exitCodeFor = (result) => {
7095
7195
  if (result.status === "error")
@@ -7145,6 +7245,8 @@ var runCli = async (argv, deps) => {
7145
7245
  else if (command === "add") result = await runAdd(rc, positionals);
7146
7246
  else if (command === "status") result = await runStatus(rc);
7147
7247
  else if (command === "docs") result = await runDocs(rc, positionals);
7248
+ else if (command === "frameworks")
7249
+ result = await runFrameworks(rc, positionals);
7148
7250
  else result = await runDoctor(rc);
7149
7251
  } catch (err) {
7150
7252
  result = errorResult(command, err, flags.dryRun);
@@ -7280,7 +7382,7 @@ runCli(process.argv.slice(2), {
7280
7382
  stdout: process.stdout,
7281
7383
  stderr: process.stderr,
7282
7384
  stdinIsTTY: Boolean(process.stdin.isTTY),
7283
- cliVersion: "0.24.0-canary.301a0304",
7385
+ cliVersion: "0.24.0-canary.55558da4",
7284
7386
  runner: createRunner(env),
7285
7387
  fetch: globalThis.fetch,
7286
7388
  openUrl,
package/dist/docs/cli.md CHANGED
@@ -21,14 +21,16 @@ Puck AI is optional. It's the editor plugin that uses Puck Cloud as its backend,
21
21
 
22
22
  - Next.js 15+ using the App Router (`app/` or `src/app/`)
23
23
  - React Router 7+ in framework mode
24
- - [TanStack Start](https://tanstack.com/start) 1.x
25
- - [vinext](https://github.com/cloudflare/vinext) using the App Router
26
- - [Vite](https://vite.dev) React apps (see [Vite and Astro](#vite-and-astro))
24
+ - [TanStack Start](https://tanstack.com/start) 1.132+
25
+ - [vinext](https://github.com/cloudflare/vinext) 1+ using the App Router
26
+ - [Vite](https://vite.dev) 6+ React apps (see [Vite and Astro](#vite-and-astro))
27
27
  - [Astro](https://astro.build) 7+ (see [Vite and Astro](#vite-and-astro))
28
- - [Hono](https://hono.dev) and [Express](https://expressjs.com) servers (see [Servers](#servers))
28
+ - [Hono](https://hono.dev) 4+ and [Express](https://expressjs.com) 4.16+ servers (see [Servers](#servers))
29
29
  - npm, pnpm, Yarn and Bun, including workspaces
30
30
  - TypeScript projects
31
31
 
32
+ Run `npx @puckeditor/cli frameworks` to see what the CLI sets up for each framework. Older versions fail with `PUCK-CLI-UNSUPPORTED-FRAMEWORK-VERSION`.
33
+
32
34
  When the CLI can't safely change something, like an existing `middleware.ts`, it leaves the file alone and tells you exactly what to add.
33
35
 
34
36
  ## Vite and Astro
@@ -159,6 +161,7 @@ npx skills add puckeditor/skills --skill puck
159
161
  | `add ai` | Add the Puck AI plugin (adds Puck Cloud first if needed) |
160
162
  | `status` | Show what's installed and configured |
161
163
  | `doctor` | Diagnose problems and suggest fixes. Never makes changes |
164
+ | `frameworks` | Show the supported frameworks and versions |
162
165
  | `docs` | Read these docs: `ls`, `cat <page>`, `find <query>`, `grep <text>` |
163
166
 
164
167
  ## Flags
@@ -27,13 +27,18 @@ puckPages.get("/api/pages", async (req, res) => {
27
27
  puckPages.post(
28
28
  "/api/pages",
29
29
  express.json({ limit: "10mb" }),
30
- async (req, res) => {
31
- const { path, data } = req.body;
32
- const pages = await readPages();
33
-
34
- pages[path] = data;
35
- await fs.writeFile(databasePath, JSON.stringify(pages));
36
-
37
- res.json({ status: "ok" });
30
+ async (req, res, next) => {
31
+ // Express 4 doesn't pass errors from async handlers to next()
32
+ try {
33
+ const { path, data } = req.body;
34
+ const pages = await readPages();
35
+
36
+ pages[path] = data;
37
+ await fs.writeFile(databasePath, JSON.stringify(pages));
38
+
39
+ res.json({ status: "ok" });
40
+ } catch (error) {
41
+ next(error);
42
+ }
38
43
  }
39
44
  );
@@ -27,13 +27,18 @@ puckPages.get("/api/pages", async (req, res) => {
27
27
  puckPages.post(
28
28
  "/api/pages",
29
29
  express.json({ limit: "10mb" }),
30
- async (req, res) => {
31
- const { path, data } = req.body;
32
- const pages = await readPages();
33
-
34
- pages[path] = data;
35
- await fs.writeFile(databasePath, JSON.stringify(pages));
36
-
37
- res.json({ status: "ok" });
30
+ async (req, res, next) => {
31
+ // Express 4 doesn't pass errors from async handlers to next()
32
+ try {
33
+ const { path, data } = req.body;
34
+ const pages = await readPages();
35
+
36
+ pages[path] = data;
37
+ await fs.writeFile(databasePath, JSON.stringify(pages));
38
+
39
+ res.json({ status: "ok" });
40
+ } catch (error) {
41
+ next(error);
42
+ }
38
43
  }
39
44
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@puckeditor/cli",
3
- "version": "0.24.0-canary.301a0304",
3
+ "version": "0.24.0-canary.55558da4",
4
4
  "description": "Set up Puck and Puck Cloud from the command line. Built for coding agents, friendly for humans.",
5
5
  "author": "Chris Villa <chris@puckeditor.com>",
6
6
  "repository": {