@cmssy/cli 11.4.2 → 11.5.1

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.
@@ -0,0 +1,19 @@
1
+ import type { ReactNode } from "react";
2
+ import { resolveCmssyLocale } from "@cmssy/core";
3
+ import { cmssy } from "@/cmssy.config";
4
+
5
+ type LayoutProps = {
6
+ children: ReactNode;
7
+ params: Promise<{ path?: string[] }>;
8
+ };
9
+
10
+ export default async function RootLayout({ children, params }: LayoutProps) {
11
+ const { path } = await params;
12
+ const locale = await resolveCmssyLocale(cmssy, path);
13
+
14
+ return (
15
+ <html lang={locale}>
16
+ <body>{children}</body>
17
+ </html>
18
+ );
19
+ }
@@ -0,0 +1,19 @@
1
+ import type { ReactNode } from "react";
2
+ import { resolveCmssyLocale } from "@cmssy/core";
3
+ import { cmssy } from "@/cmssy.config";
4
+
5
+ type LayoutProps = {
6
+ children: ReactNode;
7
+ params: Promise<{ path?: string[] }>;
8
+ };
9
+
10
+ export default async function EditRootLayout({ children, params }: LayoutProps) {
11
+ const { path } = await params;
12
+ const locale = await resolveCmssyLocale(cmssy, path);
13
+
14
+ return (
15
+ <html lang={locale}>
16
+ <body>{children}</body>
17
+ </html>
18
+ );
19
+ }
@@ -0,0 +1,64 @@
1
+ import {
2
+ isRouteErrorResponse,
3
+ Links,
4
+ Meta,
5
+ Outlet,
6
+ Scripts,
7
+ ScrollRestoration,
8
+ } from "react-router";
9
+ import { useCmssyLocale } from "@cmssy/remix";
10
+
11
+ import type { Route } from "./+types/root";
12
+
13
+ export function Layout({ children }: { children: React.ReactNode }) {
14
+ const locale = useCmssyLocale();
15
+
16
+ return (
17
+ <html lang={locale}>
18
+ <head>
19
+ <meta charSet="utf-8" />
20
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
21
+ <Meta />
22
+ <Links />
23
+ </head>
24
+ <body>
25
+ {children}
26
+ <ScrollRestoration />
27
+ <Scripts />
28
+ </body>
29
+ </html>
30
+ );
31
+ }
32
+
33
+ export default function App() {
34
+ return <Outlet />;
35
+ }
36
+
37
+ export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
38
+ let message = "Oops!";
39
+ let details = "An unexpected error occurred.";
40
+ let stack: string | undefined;
41
+
42
+ if (isRouteErrorResponse(error)) {
43
+ message = error.status === 404 ? "404" : "Error";
44
+ details =
45
+ error.status === 404
46
+ ? "The requested page could not be found."
47
+ : error.statusText || details;
48
+ } else if (import.meta.env.DEV && error && error instanceof Error) {
49
+ details = error.message;
50
+ stack = error.stack;
51
+ }
52
+
53
+ return (
54
+ <main>
55
+ <h1>{message}</h1>
56
+ <p>{details}</p>
57
+ {stack && (
58
+ <pre>
59
+ <code>{stack}</code>
60
+ </pre>
61
+ )}
62
+ </main>
63
+ );
64
+ }
package/dist/index.js CHANGED
@@ -171,7 +171,9 @@ var FRAMEWORKS = [
171
171
  "cmssy/editable-layout.tsx",
172
172
  "blocks/hero/block.ts",
173
173
  "blocks/hero/Hero.tsx",
174
+ "app/[[...path]]/layout.tsx",
174
175
  "app/[[...path]]/page.tsx",
176
+ "app/cmssy-edit/[[...path]]/layout.tsx",
175
177
  "app/cmssy-edit/[[...path]]/page.tsx",
176
178
  "app/api/draft/route.ts"
177
179
  ]
@@ -202,6 +204,7 @@ var FRAMEWORKS = [
202
204
  dependencies: ["@cmssy/remix", "@cmssy/react", "@cmssy/core"],
203
205
  files: [
204
206
  "cmssy.config.ts",
207
+ "app/root.tsx",
205
208
  "app/routes.ts",
206
209
  "app/cmssy/blocks.ts",
207
210
  "app/cmssy/editor.tsx",
@@ -507,13 +510,17 @@ var CLI_PACKAGE_JSON = fileURLToPath(
507
510
  );
508
511
  function frameworkFiles(framework, root) {
509
512
  const srcPrefix = framework.name === "next" ? nextSrcPrefix(root) : "";
510
- return [
513
+ const files = [
511
514
  { asset: "env.example", target: ".env.example" },
512
515
  ...framework.files.map((path) => ({
513
516
  asset: path,
514
517
  target: framework.name === "next" ? `${srcPrefix}${path}` : path
515
518
  }))
516
519
  ];
520
+ if (framework.name === "next" && existingFile(root, `${srcPrefix}app/layout`)) {
521
+ return files.filter((file) => !file.target.endsWith("/layout.tsx"));
522
+ }
523
+ return files;
517
524
  }
518
525
  function cliVersion() {
519
526
  const pkg = JSON.parse(readFileSync3(CLI_PACKAGE_JSON, "utf8"));
@@ -548,16 +555,36 @@ function detectInstallCommand(root) {
548
555
  }
549
556
  return "npm install";
550
557
  }
558
+ function existingFile(root, base) {
559
+ return ["tsx", "ts", "jsx", "js"].map((extension) => `${base}.${extension}`).find((candidate) => existsSync3(join3(root, candidate)));
560
+ }
551
561
  function frameworkNotes(framework, root, skipped) {
552
562
  const notes = [];
553
563
  if (framework.name === "next") {
554
- const home = `${nextSrcPrefix(root)}app/page.tsx`;
555
- if (existsSync3(join3(root, home))) {
564
+ const prefix = nextSrcPrefix(root);
565
+ const home = existingFile(root, `${prefix}app/page`);
566
+ if (home) {
556
567
  notes.push({
557
568
  status: "unknown",
558
569
  message: `${home} conflicts with the cmssy catch-all route - delete it and the cmssy page serves /`
559
570
  });
560
571
  }
572
+ const rootLayout = existingFile(root, `${prefix}app/layout`);
573
+ if (rootLayout) {
574
+ notes.push({
575
+ status: "fail",
576
+ message: `${rootLayout} outranks the cmssy root layouts, so they were NOT written and <html lang> stays whatever that file says`,
577
+ fix: `delete ${rootLayout} and rerun, then move its global CSS import and metadata into BOTH ${prefix}app/[[...path]]/layout.tsx and ${prefix}app/cmssy-edit/[[...path]]/layout.tsx - they are separate roots, and an editor preview with no CSS is the usual way to find out you only did one. Routes outside the cmssy catch-alls need a root layout of their own once it is gone: move them under a route group, e.g. ${prefix}app/(site)/layout.tsx, or the build fails with "doesn't have a root layout".`
578
+ });
579
+ }
580
+ for (const layout of ["app/[[...path]]", "app/cmssy-edit/[[...path]]"]) {
581
+ if (!rootLayout && skipped.includes(`${prefix}${layout}/layout.tsx`)) {
582
+ notes.push({
583
+ status: "unknown",
584
+ message: `${prefix}${layout}/layout.tsx already existed - set <html lang={await resolveCmssyLocale(cmssy, path)}> there yourself (import from @cmssy/core), or the site declares one language while rendering another`
585
+ });
586
+ }
587
+ }
561
588
  }
562
589
  if (framework.name === "astro") {
563
590
  notes.push({
@@ -577,6 +604,12 @@ function frameworkNotes(framework, root, skipped) {
577
604
  message: "app/routes.ts already existed - mount routes/page.tsx (index + splat) there yourself, or rerun with --force"
578
605
  });
579
606
  }
607
+ if (framework.name === "remix" && skipped.includes("app/root.tsx")) {
608
+ notes.push({
609
+ status: "unknown",
610
+ message: "app/root.tsx already existed - set <html lang={useCmssyLocale()}> in its Layout yourself (import from @cmssy/remix), or the site declares one language while rendering another"
611
+ });
612
+ }
580
613
  return notes;
581
614
  }
582
615
  function runInit(options, deps) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmssy/cli",
3
- "version": "11.4.2",
3
+ "version": "11.5.1",
4
4
  "description": "The cmssy CLI: `cmssy init` wires cmssy into an existing Next.js, Astro or React Router app; `cmssy link` connects it to a workspace and verifies the editor wiring.",
5
5
  "keywords": [
6
6
  "cmssy",
@@ -27,7 +27,7 @@
27
27
  "assets"
28
28
  ],
29
29
  "dependencies": {
30
- "@cmssy/core": "11.4.2"
30
+ "@cmssy/core": "11.5.1"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^20.0.0",