@cmssy/cli 10.9.2 → 10.10.0
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.
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { createCmssyPage } from "@cmssy/next/server";
|
|
1
|
+
import { createCmssyPage, CmssyLayoutSlot } from "@cmssy/next/server";
|
|
2
2
|
import { cmssy } from "@/cmssy.config";
|
|
3
3
|
import { blocks } from "@/cmssy/blocks";
|
|
4
4
|
import { CmssyEditor } from "@/cmssy/editor";
|
|
5
|
-
import {
|
|
5
|
+
import { EditableLayout } from "@/cmssy/editable-layout";
|
|
6
6
|
|
|
7
7
|
type PageProps = {
|
|
8
8
|
params: Promise<{ path?: string[] }>;
|
|
@@ -11,19 +11,29 @@ type PageProps = {
|
|
|
11
11
|
|
|
12
12
|
const CmssyPage = createCmssyPage(cmssy, blocks, { editor: CmssyEditor });
|
|
13
13
|
|
|
14
|
-
// The header and
|
|
15
|
-
// app/layout.tsx
|
|
16
|
-
// path is what says which language to render them in
|
|
14
|
+
// The header and footer are layout blocks. They are mounted here rather than in
|
|
15
|
+
// app/layout.tsx because this route knows its path, and the language prefix in
|
|
16
|
+
// that path is what says which language to render them in - reading it from the
|
|
17
17
|
// request header instead would make every page dynamic.
|
|
18
18
|
export default async function Page(props: PageProps) {
|
|
19
19
|
const { path } = await props.params;
|
|
20
|
+
const slot = (position: "header" | "footer") => (
|
|
21
|
+
<CmssyLayoutSlot
|
|
22
|
+
config={cmssy}
|
|
23
|
+
blocks={blocks}
|
|
24
|
+
position={position}
|
|
25
|
+
path={path}
|
|
26
|
+
editable={EditableLayout}
|
|
27
|
+
/>
|
|
28
|
+
);
|
|
29
|
+
|
|
20
30
|
return (
|
|
21
31
|
<>
|
|
22
|
-
|
|
32
|
+
{slot("header")}
|
|
23
33
|
<main>
|
|
24
34
|
<CmssyPage {...props} />
|
|
25
35
|
</main>
|
|
26
|
-
|
|
36
|
+
{slot("footer")}
|
|
27
37
|
</>
|
|
28
38
|
);
|
|
29
39
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { createCmssyEditPage } from "@cmssy/next/server";
|
|
1
|
+
import { createCmssyEditPage, CmssyLayoutSlot } from "@cmssy/next/server";
|
|
2
2
|
import { cmssy } from "@/cmssy.config";
|
|
3
3
|
import { blocks } from "@/cmssy/blocks";
|
|
4
4
|
import { CmssyEditor } from "@/cmssy/editor";
|
|
5
|
-
import {
|
|
5
|
+
import { EditableLayout } from "@/cmssy/editable-layout";
|
|
6
6
|
|
|
7
7
|
// The route the middleware rewrites a verified editor request onto. The public
|
|
8
8
|
// pages stay static, and a static page never sees the query string that would
|
|
@@ -24,13 +24,23 @@ const CmssyEditPage = createCmssyEditPage(cmssy, blocks, {
|
|
|
24
24
|
// header missing here is a header missing in the editor.
|
|
25
25
|
export default async function EditPage(props: PageProps) {
|
|
26
26
|
const { path } = await props.params;
|
|
27
|
+
const slot = (position: "header" | "footer") => (
|
|
28
|
+
<CmssyLayoutSlot
|
|
29
|
+
config={cmssy}
|
|
30
|
+
blocks={blocks}
|
|
31
|
+
position={position}
|
|
32
|
+
path={path}
|
|
33
|
+
editable={EditableLayout}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
|
|
27
37
|
return (
|
|
28
38
|
<>
|
|
29
|
-
|
|
39
|
+
{slot("header")}
|
|
30
40
|
<main>
|
|
31
41
|
<CmssyEditPage {...props} />
|
|
32
42
|
</main>
|
|
33
|
-
|
|
43
|
+
{slot("footer")}
|
|
34
44
|
</>
|
|
35
45
|
);
|
|
36
46
|
}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cmssy/cli",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.10.0",
|
|
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": "10.
|
|
30
|
+
"@cmssy/core": "10.10.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/node": "^20.0.0",
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import { cache } from "react";
|
|
2
|
-
import {
|
|
3
|
-
CmssyServerLayout,
|
|
4
|
-
graphqlRequest,
|
|
5
|
-
resolveEditorLayoutBlockData,
|
|
6
|
-
} from "@cmssy/react";
|
|
7
|
-
import type { CmssyLayoutGroup } from "@cmssy/react";
|
|
8
|
-
import { resolveEditorOrigin } from "@cmssy/next";
|
|
9
|
-
import { isCmssyEditMode } from "@cmssy/next/server";
|
|
10
|
-
import { cmssy } from "@/cmssy.config";
|
|
11
|
-
import { blocks } from "@/cmssy/blocks";
|
|
12
|
-
import { EditableLayout } from "@/cmssy/editable-layout";
|
|
13
|
-
|
|
14
|
-
// The header and the footer are layout blocks: content, not markup. Fetching
|
|
15
|
-
// and rendering them is your app's, so both queries live here.
|
|
16
|
-
const LAYOUTS_QUERY = `query PublicPageLayouts($workspaceSlug: String!, $pageSlug: String!, $previewSecret: String) {
|
|
17
|
-
public {
|
|
18
|
-
page {
|
|
19
|
-
layouts(workspaceSlug: $workspaceSlug, pageSlug: $pageSlug, previewSecret: $previewSecret) {
|
|
20
|
-
position
|
|
21
|
-
blocks { id type content style advanced order isActive }
|
|
22
|
-
settings { desktopWidth mobileBehavior }
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}`;
|
|
27
|
-
|
|
28
|
-
const SITE_CONFIG_QUERY = `query PublicSiteConfig($workspaceSlug: String!) {
|
|
29
|
-
public {
|
|
30
|
-
siteConfig(workspaceSlug: $workspaceSlug) {
|
|
31
|
-
defaultLanguage
|
|
32
|
-
enabledLanguages
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}`;
|
|
36
|
-
|
|
37
|
-
// Both slots render on every page; `cache` makes that one request each.
|
|
38
|
-
const fetchLayouts = cache(
|
|
39
|
-
async (pageSlug: string, previewSecret: string | null) => {
|
|
40
|
-
try {
|
|
41
|
-
const data = await graphqlRequest<{
|
|
42
|
-
public?: { page?: { layouts?: CmssyLayoutGroup[] | null } | null } | null;
|
|
43
|
-
}>(
|
|
44
|
-
cmssy,
|
|
45
|
-
LAYOUTS_QUERY,
|
|
46
|
-
{ workspaceSlug: cmssy.workspaceSlug, pageSlug, previewSecret },
|
|
47
|
-
{ public: true, retry: {} },
|
|
48
|
-
"page layouts",
|
|
49
|
-
);
|
|
50
|
-
return data.public?.page?.layouts ?? [];
|
|
51
|
-
} catch (error) {
|
|
52
|
-
console.error("[cmssy] page layouts could not be fetched", error);
|
|
53
|
-
return [];
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
const fetchLocales = cache(async () => {
|
|
59
|
-
try {
|
|
60
|
-
const data = await graphqlRequest<{
|
|
61
|
-
public?: {
|
|
62
|
-
siteConfig?: {
|
|
63
|
-
defaultLanguage: string | null;
|
|
64
|
-
enabledLanguages: string[] | null;
|
|
65
|
-
} | null;
|
|
66
|
-
} | null;
|
|
67
|
-
}>(
|
|
68
|
-
cmssy,
|
|
69
|
-
SITE_CONFIG_QUERY,
|
|
70
|
-
{ workspaceSlug: cmssy.workspaceSlug },
|
|
71
|
-
{ public: true, retry: {} },
|
|
72
|
-
"site config",
|
|
73
|
-
);
|
|
74
|
-
const config = data.public?.siteConfig;
|
|
75
|
-
// The languages are the workspace's, never this repo's.
|
|
76
|
-
const defaultLocale = config?.defaultLanguage ?? "";
|
|
77
|
-
const enabled = config?.enabledLanguages ?? [];
|
|
78
|
-
return {
|
|
79
|
-
defaultLocale,
|
|
80
|
-
locales: enabled.length > 0 ? enabled : defaultLocale ? [defaultLocale] : [],
|
|
81
|
-
};
|
|
82
|
-
} catch (error) {
|
|
83
|
-
console.error("[cmssy] site config could not be fetched", error);
|
|
84
|
-
return { defaultLocale: "", locales: [] as string[] };
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
export interface CmssyLayoutSlotProps {
|
|
89
|
-
position: "header" | "footer";
|
|
90
|
-
/**
|
|
91
|
-
* The catch-all segments of the route rendering this slot, as routed. The
|
|
92
|
-
* language prefix in them IS the language - reading it here keeps the route
|
|
93
|
-
* statically renderable, where reading the request header would force every
|
|
94
|
-
* page dynamic and kill ISR.
|
|
95
|
-
*/
|
|
96
|
-
path?: string[];
|
|
97
|
-
/** The page whose layout to render. Defaults to the site-wide header/footer. */
|
|
98
|
-
page?: string;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* The site-wide header and footer, rendered the way each mode needs them:
|
|
103
|
-
*
|
|
104
|
-
* - published traffic: server-rendered layout blocks, no client cost;
|
|
105
|
-
* - the editor: the same blocks through the edit bridge, fetched with the
|
|
106
|
-
* preview secret, so what you see is the draft you are editing.
|
|
107
|
-
*
|
|
108
|
-
* Getting this wrong is invisible - the site looks right while the editor shows
|
|
109
|
-
* a header it can select but not fill, or the published version of one.
|
|
110
|
-
*/
|
|
111
|
-
export async function CmssyLayoutSlot({
|
|
112
|
-
position,
|
|
113
|
-
path,
|
|
114
|
-
page = "/",
|
|
115
|
-
}: CmssyLayoutSlotProps) {
|
|
116
|
-
const [editMode, { defaultLocale, locales }] = await Promise.all([
|
|
117
|
-
isCmssyEditMode(),
|
|
118
|
-
fetchLocales(),
|
|
119
|
-
]);
|
|
120
|
-
|
|
121
|
-
const [first] = path ?? [];
|
|
122
|
-
const locale =
|
|
123
|
-
first && first !== defaultLocale && locales.includes(first)
|
|
124
|
-
? first
|
|
125
|
-
: defaultLocale;
|
|
126
|
-
|
|
127
|
-
const groups = await fetchLayouts(
|
|
128
|
-
page,
|
|
129
|
-
editMode ? cmssy.draftSecret : null,
|
|
130
|
-
);
|
|
131
|
-
|
|
132
|
-
if (!editMode) {
|
|
133
|
-
return (
|
|
134
|
-
<CmssyServerLayout
|
|
135
|
-
groups={groups}
|
|
136
|
-
blocks={blocks}
|
|
137
|
-
position={position}
|
|
138
|
-
locale={locale}
|
|
139
|
-
defaultLocale={defaultLocale}
|
|
140
|
-
enabledLocales={locales}
|
|
141
|
-
config={cmssy}
|
|
142
|
-
/>
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const origin = resolveEditorOrigin(cmssy.editorOrigin);
|
|
147
|
-
// The editor canvas renders stored content, and for a relation field that is
|
|
148
|
-
// raw ids - so the server-resolved content is handed over with it.
|
|
149
|
-
const editorData = await resolveEditorLayoutBlockData({
|
|
150
|
-
groups,
|
|
151
|
-
blocks,
|
|
152
|
-
position,
|
|
153
|
-
locale,
|
|
154
|
-
defaultLocale,
|
|
155
|
-
enabledLocales: locales,
|
|
156
|
-
isPreview: true,
|
|
157
|
-
config: cmssy,
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
return (
|
|
161
|
-
<EditableLayout
|
|
162
|
-
groups={groups}
|
|
163
|
-
position={position}
|
|
164
|
-
locale={locale}
|
|
165
|
-
defaultLocale={defaultLocale}
|
|
166
|
-
enabledLocales={locales}
|
|
167
|
-
edit={{ editorOrigin: Array.isArray(origin) ? origin[0] : origin }}
|
|
168
|
-
data={editorData.data}
|
|
169
|
-
resolvedContent={editorData.content}
|
|
170
|
-
/>
|
|
171
|
-
);
|
|
172
|
-
}
|