@decocms/nextjs 8.0.0 → 8.4.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.
- package/README.md +77 -332
- package/dist/DraftPreviewIndicator.d.ts +7 -0
- package/dist/DraftPreviewIndicator.d.ts.map +1 -0
- package/dist/DraftPreviewIndicator.js +19 -0
- package/dist/DraftPreviewIndicator.js.map +1 -0
- package/dist/StudioBridge.d.ts +16 -0
- package/dist/StudioBridge.d.ts.map +1 -0
- package/dist/StudioBridge.js +17 -0
- package/dist/StudioBridge.js.map +1 -0
- package/dist/draft.d.ts +35 -0
- package/dist/draft.d.ts.map +1 -0
- package/dist/draft.js +43 -0
- package/dist/draft.js.map +1 -0
- package/dist/drafts.d.ts +94 -0
- package/dist/drafts.d.ts.map +1 -0
- package/dist/drafts.js +210 -0
- package/dist/drafts.js.map +1 -0
- package/dist/image-loader/index.d.ts +36 -0
- package/dist/image-loader/index.d.ts.map +1 -0
- package/dist/image-loader/index.js +27 -0
- package/dist/image-loader/index.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/proxy/index.d.ts +79 -0
- package/dist/proxy/index.d.ts.map +1 -0
- package/dist/proxy/index.js +92 -0
- package/dist/proxy/index.js.map +1 -0
- package/dist/server/index.d.ts +46 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +64 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/slot.d.ts +6 -0
- package/dist/server/slot.d.ts.map +1 -0
- package/dist/server/slot.js +13 -0
- package/dist/server/slot.js.map +1 -0
- package/dist/studio.d.ts +30 -0
- package/dist/studio.d.ts.map +1 -0
- package/dist/studio.js +55 -0
- package/dist/studio.js.map +1 -0
- package/package.json +41 -22
- package/src/DraftPreviewIndicator.tsx +17 -16
- package/src/StudioBridge.ts +23 -0
- package/src/config/index.cjs +78 -0
- package/src/config/index.d.cts +27 -0
- package/src/draft.ts +30 -210
- package/src/drafts.ts +229 -0
- package/src/image-loader/index.ts +62 -0
- package/src/index.ts +31 -43
- package/src/proxy/index.ts +161 -0
- package/src/server/index.ts +77 -0
- package/src/server/slot.ts +14 -0
- package/src/studio.ts +54 -0
- package/src/ClientOnlySection.tsx +0 -20
- package/src/DecoPageRenderer.test.tsx +0 -37
- package/src/DecoPageRenderer.tsx +0 -107
- package/src/DecoRootLayout.test.tsx +0 -22
- package/src/DecoRootLayout.tsx +0 -82
- package/src/DeferredSection.test.tsx +0 -27
- package/src/DeferredSection.tsx +0 -59
- package/src/DraftPreviewBadge.render.test.tsx +0 -16
- package/src/DraftPreviewBadge.test.ts +0 -37
- package/src/DraftPreviewBadge.tsx +0 -252
- package/src/SectionRenderer.test.tsx +0 -97
- package/src/SectionRenderer.tsx +0 -58
- package/src/config.cjs +0 -92
- package/src/config.d.cts +0 -4
- package/src/config.test.ts +0 -86
- package/src/createDecoPage.draft.test.tsx +0 -91
- package/src/createDecoPage.test.tsx +0 -63
- package/src/createDecoPage.tsx +0 -173
- package/src/createDecoPreviewPage.test.tsx +0 -71
- package/src/createDecoPreviewPage.tsx +0 -108
- package/src/decoMark.ts +0 -11
- package/src/draft.test.ts +0 -73
- package/src/draftConstants.test.ts +0 -21
- package/src/draftConstants.ts +0 -15
- package/src/draftMiddleware.test.ts +0 -147
- package/src/draftMiddleware.ts +0 -136
- package/src/routeHandlers.test.ts +0 -243
- package/src/routeHandlers.ts +0 -227
- package/src/setup.test.ts +0 -253
- package/src/setup.ts +0 -180
- package/tsconfig.json +0 -7
package/dist/drafts.d.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which hosts may render drafts: v7's allowlist (`@decocms/blocks` 7.x
|
|
3
|
+
* `cms/draftSource.ts`: `readAllowedHosts`, `isDraftHostAllowed`,
|
|
4
|
+
* `isDraftPreviewEnabled`), ported as is. v7 read its override from the
|
|
5
|
+
* `DECO_ALLOWED_PREVIEW_HOSTS` variable; here it is the `previewHosts` option,
|
|
6
|
+
* and the site passes the same options to the proxy (`decideDraft`) and to
|
|
7
|
+
* its pages (`bindDraft`).
|
|
8
|
+
*
|
|
9
|
+
* - The site's own preview hosts: the ones it declares, in the `CMS` block or
|
|
10
|
+
* as `createCMS({ preview: { hosts } })` (matched as `cms.draftPointer`
|
|
11
|
+
* matches them). A site that declares none has none, as in v7: blocks'
|
|
12
|
+
* own default (every host) doesn't count as a declaration.
|
|
13
|
+
* - The hosts Deco runs the site on, named after the site and always added:
|
|
14
|
+
* `<site>.deco.site` and `<site>.deco-cx.workers.dev`, exact.
|
|
15
|
+
* - `previewHosts: [...]` replaces the site's own list (the inferred hosts are
|
|
16
|
+
* still added); `previewHosts: "none"` turns previews off on every host.
|
|
17
|
+
*
|
|
18
|
+
* Hosts compare exactly, lowercased, port included (`localhost:3000`). The
|
|
19
|
+
* host is the one the visitor asked for: `x-forwarded-host` behind a proxy,
|
|
20
|
+
* else `host`.
|
|
21
|
+
*
|
|
22
|
+
* The draft itself is the capability: a host check only bounds where a draft
|
|
23
|
+
* link works. A request the check refuses gets the release, never an error.
|
|
24
|
+
*
|
|
25
|
+
* No React, no Next.js and no module state: the proxy and the pages share it.
|
|
26
|
+
*/
|
|
27
|
+
import { type CMS, type RequestLike } from "@decocms/blocks";
|
|
28
|
+
export interface PreviewPolicy {
|
|
29
|
+
/** The site's name: `<site>.deco.site` and `<site>.deco-cx.workers.dev` may preview. */
|
|
30
|
+
site?: string;
|
|
31
|
+
/** Replaces the `CMS` block's preview hosts; `"none"` turns previews off everywhere. */
|
|
32
|
+
previewHosts?: readonly string[] | "none";
|
|
33
|
+
}
|
|
34
|
+
/** The hosts Deco runs `site` on, which may always preview (unless previews are off). */
|
|
35
|
+
export declare function inferredPreviewHosts(site: string | undefined): string[];
|
|
36
|
+
/**
|
|
37
|
+
* Whether `host` may preview without asking the CMS: `true` (an override or
|
|
38
|
+
* inferred host), `false` (previews off, or the override leaves it out), or
|
|
39
|
+
* `"cms"` when only the site's declared preview hosts can say (none declared:
|
|
40
|
+
* `false`, see {@link declaresPreviewHosts}).
|
|
41
|
+
*/
|
|
42
|
+
export declare function previewHostDecision(host: string, policy: PreviewPolicy): boolean | "cms";
|
|
43
|
+
/**
|
|
44
|
+
* Whether any host may preview (v7's `isDraftPreviewEnabled`): a page checks
|
|
45
|
+
* it before it reads the request's headers, so a site with previews off never
|
|
46
|
+
* turns a static page dynamic. `false` for `previewHosts: "none"`; `true` with
|
|
47
|
+
* a site name or an override list; otherwise whether the site declares
|
|
48
|
+
* preview hosts and they allow any.
|
|
49
|
+
*/
|
|
50
|
+
export declare function isDraftPreviewEnabled(cms: Pick<CMS, "settings" | "forRelease">, policy: PreviewPolicy): Promise<boolean>;
|
|
51
|
+
/**
|
|
52
|
+
* Whether the site declares its own preview hosts: in the `CMS` block, or as
|
|
53
|
+
* `createCMS`'s `preview.hosts`. When it declares none, `cms.settings()`
|
|
54
|
+
* reports blocks' default, every host (`["*"]`), which v7 never had: there,
|
|
55
|
+
* a site without a list previewed only on its Deco hosts. The saved `CMS`
|
|
56
|
+
* block tells an explicit `["*"]` from that default.
|
|
57
|
+
*/
|
|
58
|
+
export declare function declaresPreviewHosts(cms: Pick<CMS, "settings" | "forRelease">): Promise<boolean>;
|
|
59
|
+
/**
|
|
60
|
+
* The pointer a request carries, as `@decocms/blocks` reads it: `?__draft=`
|
|
61
|
+
* first, then the draft cookie; `null` for `?__draft=off` and for a value
|
|
62
|
+
* that doesn't parse.
|
|
63
|
+
*/
|
|
64
|
+
export declare function readDraftPointer(request: RequestLike): string | null;
|
|
65
|
+
/** Whether the request carries a draft signal at all: without one the CMS is never asked. */
|
|
66
|
+
export declare function hasDraftSignal(request: RequestLike): boolean;
|
|
67
|
+
/** The host the visitor asked for: the first `x-forwarded-host`, else `host`. */
|
|
68
|
+
export declare function requestHost(headers: {
|
|
69
|
+
get(name: string): string | null;
|
|
70
|
+
}): string | null;
|
|
71
|
+
/**
|
|
72
|
+
* The request as the draft check should see it: `pathAndQuery` on the host
|
|
73
|
+
* the visitor asked for (`x-forwarded-host` behind a proxy, else `host`), so
|
|
74
|
+
* the host check judges the public hostname rather than the origin's, or
|
|
75
|
+
* `fallbackHost` when the headers name none. `null` when no host is known.
|
|
76
|
+
*/
|
|
77
|
+
export declare function requestLike(headers: Headers, pathAndQuery: string, fallbackHost?: string): RequestLike | null;
|
|
78
|
+
/**
|
|
79
|
+
* The draft `request` renders under `policy`, or `null` for the release: the
|
|
80
|
+
* pointer it carries, on a host the policy (or, when only it can say, the
|
|
81
|
+
* `CMS` block) allows.
|
|
82
|
+
*/
|
|
83
|
+
export declare function allowedDraft(cms: Pick<CMS, "draftPointer" | "settings" | "forRelease">, request: RequestLike, policy: PreviewPolicy): Promise<string | null>;
|
|
84
|
+
/**
|
|
85
|
+
* The draft cookie: the same `Set-Cookie` `cms.draftCookie` writes (a test
|
|
86
|
+
* holds the two together). Studio frames the site cross-site, hence
|
|
87
|
+
* `SameSite=None; Partitioned`.
|
|
88
|
+
*/
|
|
89
|
+
export declare function draftCookie(value: string, extra?: string[]): string;
|
|
90
|
+
/** Whether the request ends a preview (`?__draft=off`): the cookie goes on any host. */
|
|
91
|
+
export declare function endsPreview(request: RequestLike): boolean;
|
|
92
|
+
/** Whether the request's own `?__draft=` carries `pointer` (a draft link, not the cookie). */
|
|
93
|
+
export declare function fromDraftLink(request: RequestLike, pointer: string): boolean;
|
|
94
|
+
//# sourceMappingURL=drafts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drafts.d.ts","sourceRoot":"","sources":["../src/drafts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,KAAK,GAAG,EAAqB,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGhF,MAAM,WAAW,aAAa;IAC5B,wFAAwF;IACxF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC;CAC3C;AAED,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAGvE;AAOD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,GAAG,KAAK,CAQxF;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,UAAU,GAAG,YAAY,CAAC,EACzC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,OAAO,CAAC,CAMlB;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,UAAU,GAAG,YAAY,CAAC,GACxC,OAAO,CAAC,OAAO,CAAC,CAUlB;AA8BD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAMpE;AAED,6FAA6F;AAC7F,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAI5D;AAED,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAIxF;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,YAAY,CAAC,EAAE,MAAM,GACpB,WAAW,GAAG,IAAI,CAQpB;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,cAAc,GAAG,UAAU,GAAG,YAAY,CAAC,EAC1D,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAexB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAM,EAAO,GAAG,MAAM,CAUvE;AAED,wFAAwF;AACxF,wBAAgB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAEzD;AAED,8FAA8F;AAC9F,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAE5E"}
|
package/dist/drafts.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which hosts may render drafts: v7's allowlist (`@decocms/blocks` 7.x
|
|
3
|
+
* `cms/draftSource.ts`: `readAllowedHosts`, `isDraftHostAllowed`,
|
|
4
|
+
* `isDraftPreviewEnabled`), ported as is. v7 read its override from the
|
|
5
|
+
* `DECO_ALLOWED_PREVIEW_HOSTS` variable; here it is the `previewHosts` option,
|
|
6
|
+
* and the site passes the same options to the proxy (`decideDraft`) and to
|
|
7
|
+
* its pages (`bindDraft`).
|
|
8
|
+
*
|
|
9
|
+
* - The site's own preview hosts: the ones it declares, in the `CMS` block or
|
|
10
|
+
* as `createCMS({ preview: { hosts } })` (matched as `cms.draftPointer`
|
|
11
|
+
* matches them). A site that declares none has none, as in v7: blocks'
|
|
12
|
+
* own default (every host) doesn't count as a declaration.
|
|
13
|
+
* - The hosts Deco runs the site on, named after the site and always added:
|
|
14
|
+
* `<site>.deco.site` and `<site>.deco-cx.workers.dev`, exact.
|
|
15
|
+
* - `previewHosts: [...]` replaces the site's own list (the inferred hosts are
|
|
16
|
+
* still added); `previewHosts: "none"` turns previews off on every host.
|
|
17
|
+
*
|
|
18
|
+
* Hosts compare exactly, lowercased, port included (`localhost:3000`). The
|
|
19
|
+
* host is the one the visitor asked for: `x-forwarded-host` behind a proxy,
|
|
20
|
+
* else `host`.
|
|
21
|
+
*
|
|
22
|
+
* The draft itself is the capability: a host check only bounds where a draft
|
|
23
|
+
* link works. A request the check refuses gets the release, never an error.
|
|
24
|
+
*
|
|
25
|
+
* No React, no Next.js and no module state: the proxy and the pages share it.
|
|
26
|
+
*/
|
|
27
|
+
import { parseDraftPointer } from "@decocms/blocks";
|
|
28
|
+
import { DRAFT_COOKIE, DRAFT_PARAM } from "./draft.js";
|
|
29
|
+
/** The hosts Deco runs `site` on, which may always preview (unless previews are off). */
|
|
30
|
+
export function inferredPreviewHosts(site) {
|
|
31
|
+
const s = (site ?? "").trim().toLowerCase();
|
|
32
|
+
return s ? [`${s}.deco.site`, `${s}.deco-cx.workers.dev`] : [];
|
|
33
|
+
}
|
|
34
|
+
function overrideHosts(policy) {
|
|
35
|
+
if (policy.previewHosts === "none")
|
|
36
|
+
return ["none"];
|
|
37
|
+
return (policy.previewHosts ?? []).map((h) => h.trim().toLowerCase()).filter(Boolean);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Whether `host` may preview without asking the CMS: `true` (an override or
|
|
41
|
+
* inferred host), `false` (previews off, or the override leaves it out), or
|
|
42
|
+
* `"cms"` when only the site's declared preview hosts can say (none declared:
|
|
43
|
+
* `false`, see {@link declaresPreviewHosts}).
|
|
44
|
+
*/
|
|
45
|
+
export function previewHostDecision(host, policy) {
|
|
46
|
+
const override = overrideHosts(policy);
|
|
47
|
+
if (override.includes("none"))
|
|
48
|
+
return false;
|
|
49
|
+
const h = host.trim().toLowerCase();
|
|
50
|
+
if (h === "")
|
|
51
|
+
return false;
|
|
52
|
+
if (inferredPreviewHosts(policy.site).includes(h))
|
|
53
|
+
return true;
|
|
54
|
+
if (policy.previewHosts !== undefined)
|
|
55
|
+
return override.includes(h);
|
|
56
|
+
return "cms";
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Whether any host may preview (v7's `isDraftPreviewEnabled`): a page checks
|
|
60
|
+
* it before it reads the request's headers, so a site with previews off never
|
|
61
|
+
* turns a static page dynamic. `false` for `previewHosts: "none"`; `true` with
|
|
62
|
+
* a site name or an override list; otherwise whether the site declares
|
|
63
|
+
* preview hosts and they allow any.
|
|
64
|
+
*/
|
|
65
|
+
export async function isDraftPreviewEnabled(cms, policy) {
|
|
66
|
+
const override = overrideHosts(policy);
|
|
67
|
+
if (override.includes("none"))
|
|
68
|
+
return false;
|
|
69
|
+
if (inferredPreviewHosts(policy.site).length > 0)
|
|
70
|
+
return true;
|
|
71
|
+
if (policy.previewHosts !== undefined)
|
|
72
|
+
return override.length > 0;
|
|
73
|
+
return (await declaresPreviewHosts(cms)) && (await cms.settings()).preview.hosts.length > 0;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Whether the site declares its own preview hosts: in the `CMS` block, or as
|
|
77
|
+
* `createCMS`'s `preview.hosts`. When it declares none, `cms.settings()`
|
|
78
|
+
* reports blocks' default, every host (`["*"]`), which v7 never had: there,
|
|
79
|
+
* a site without a list previewed only on its Deco hosts. The saved `CMS`
|
|
80
|
+
* block tells an explicit `["*"]` from that default.
|
|
81
|
+
*/
|
|
82
|
+
export async function declaresPreviewHosts(cms) {
|
|
83
|
+
const { hosts } = (await cms.settings()).preview;
|
|
84
|
+
if (hosts.length !== 1 || hosts[0] !== "*")
|
|
85
|
+
return true;
|
|
86
|
+
try {
|
|
87
|
+
const [block] = await cms.forRelease().resolve("CMS", { run: false });
|
|
88
|
+
const preview = isRecord(block) ? block.preview : undefined;
|
|
89
|
+
return isRecord(preview) && ("hosts" in preview || "__resolveType" in preview);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function isRecord(value) {
|
|
96
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
97
|
+
}
|
|
98
|
+
const DRAFT_OFF = "off";
|
|
99
|
+
function draftParam(request) {
|
|
100
|
+
try {
|
|
101
|
+
return new URL(request.url, "http://localhost").searchParams.get(DRAFT_PARAM);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function readCookie(header, name) {
|
|
108
|
+
if (!header)
|
|
109
|
+
return null;
|
|
110
|
+
for (const part of header.split(";")) {
|
|
111
|
+
const eq = part.indexOf("=");
|
|
112
|
+
if (eq === -1 || part.slice(0, eq).trim() !== name)
|
|
113
|
+
continue;
|
|
114
|
+
try {
|
|
115
|
+
return decodeURIComponent(part.slice(eq + 1).trim());
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The pointer a request carries, as `@decocms/blocks` reads it: `?__draft=`
|
|
125
|
+
* first, then the draft cookie; `null` for `?__draft=off` and for a value
|
|
126
|
+
* that doesn't parse.
|
|
127
|
+
*/
|
|
128
|
+
export function readDraftPointer(request) {
|
|
129
|
+
const param = draftParam(request);
|
|
130
|
+
if (param === DRAFT_OFF)
|
|
131
|
+
return null;
|
|
132
|
+
if (param && parseDraftPointer(param) !== null)
|
|
133
|
+
return param;
|
|
134
|
+
const cookie = readCookie(request.headers.get("cookie"), DRAFT_COOKIE);
|
|
135
|
+
return cookie && parseDraftPointer(cookie) !== null ? cookie : null;
|
|
136
|
+
}
|
|
137
|
+
/** Whether the request carries a draft signal at all: without one the CMS is never asked. */
|
|
138
|
+
export function hasDraftSignal(request) {
|
|
139
|
+
return (draftParam(request) !== null || readCookie(request.headers.get("cookie"), DRAFT_COOKIE) !== null);
|
|
140
|
+
}
|
|
141
|
+
/** The host the visitor asked for: the first `x-forwarded-host`, else `host`. */
|
|
142
|
+
export function requestHost(headers) {
|
|
143
|
+
const forwarded = headers.get("x-forwarded-host")?.split(",")[0]?.trim();
|
|
144
|
+
const host = forwarded || headers.get("host")?.trim();
|
|
145
|
+
return host || null;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* The request as the draft check should see it: `pathAndQuery` on the host
|
|
149
|
+
* the visitor asked for (`x-forwarded-host` behind a proxy, else `host`), so
|
|
150
|
+
* the host check judges the public hostname rather than the origin's, or
|
|
151
|
+
* `fallbackHost` when the headers name none. `null` when no host is known.
|
|
152
|
+
*/
|
|
153
|
+
export function requestLike(headers, pathAndQuery, fallbackHost) {
|
|
154
|
+
const host = requestHost(headers) ?? (fallbackHost || null);
|
|
155
|
+
if (!host)
|
|
156
|
+
return null;
|
|
157
|
+
try {
|
|
158
|
+
return { url: new URL(pathAndQuery, `https://${host}`).href, headers };
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The draft `request` renders under `policy`, or `null` for the release: the
|
|
166
|
+
* pointer it carries, on a host the policy (or, when only it can say, the
|
|
167
|
+
* `CMS` block) allows.
|
|
168
|
+
*/
|
|
169
|
+
export async function allowedDraft(cms, request, policy) {
|
|
170
|
+
const pointer = readDraftPointer(request);
|
|
171
|
+
if (pointer === null)
|
|
172
|
+
return null;
|
|
173
|
+
let host;
|
|
174
|
+
try {
|
|
175
|
+
host = new URL(request.url).host;
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
const decision = previewHostDecision(host, policy);
|
|
181
|
+
const allowed = decision === "cms"
|
|
182
|
+
? (await declaresPreviewHosts(cms)) && (await cms.draftPointer(request)) !== null
|
|
183
|
+
: decision;
|
|
184
|
+
return allowed ? pointer : null;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* The draft cookie: the same `Set-Cookie` `cms.draftCookie` writes (a test
|
|
188
|
+
* holds the two together). Studio frames the site cross-site, hence
|
|
189
|
+
* `SameSite=None; Partitioned`.
|
|
190
|
+
*/
|
|
191
|
+
export function draftCookie(value, extra = []) {
|
|
192
|
+
return [
|
|
193
|
+
`${DRAFT_COOKIE}=${value}`,
|
|
194
|
+
"Path=/",
|
|
195
|
+
...extra,
|
|
196
|
+
"HttpOnly",
|
|
197
|
+
"Secure",
|
|
198
|
+
"SameSite=None",
|
|
199
|
+
"Partitioned",
|
|
200
|
+
].join("; ");
|
|
201
|
+
}
|
|
202
|
+
/** Whether the request ends a preview (`?__draft=off`): the cookie goes on any host. */
|
|
203
|
+
export function endsPreview(request) {
|
|
204
|
+
return draftParam(request) === DRAFT_OFF;
|
|
205
|
+
}
|
|
206
|
+
/** Whether the request's own `?__draft=` carries `pointer` (a draft link, not the cookie). */
|
|
207
|
+
export function fromDraftLink(request, pointer) {
|
|
208
|
+
return draftParam(request) === pointer;
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=drafts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drafts.js","sourceRoot":"","sources":["../src/drafts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@decocms/nextjs/image-loader`: a next/image loader over an `ImageUrl` from
|
|
3
|
+
* `@decocms/blocks/image`. The site's `loaderFile` is one line:
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* // src/image-loader.ts (next.config: images: { loader: "custom", loaderFile: "./src/image-loader.ts" })
|
|
7
|
+
* import { createDecoImageLoader } from "@decocms/nextjs/image-loader";
|
|
8
|
+
* import { imageUrl } from "./imageUrl";
|
|
9
|
+
* export default createDecoImageLoader(imageUrl);
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* A source the `ImageUrl` resizes gets its provider's URL; any other source
|
|
13
|
+
* goes to `fallback` (`nextImageOptimizer` sends it through Next's own
|
|
14
|
+
* `/_next/image`), or comes back unchanged. No React, no module state.
|
|
15
|
+
*/
|
|
16
|
+
import type { ImageUrl, Quality } from "@decocms/blocks/image";
|
|
17
|
+
/** What next/image passes a loader (`ImageLoaderProps`), with Deco's named tiers allowed as quality. */
|
|
18
|
+
export interface DecoImageLoaderProps {
|
|
19
|
+
src: string;
|
|
20
|
+
width: number;
|
|
21
|
+
quality?: Quality;
|
|
22
|
+
}
|
|
23
|
+
export type DecoImageLoader = (props: DecoImageLoaderProps) => string;
|
|
24
|
+
export interface DecoImageLoaderOptions {
|
|
25
|
+
/** The URL of a source no provider resizes; `null` keeps `src`. Default: `src` unchanged. */
|
|
26
|
+
fallback?: (props: DecoImageLoaderProps) => string | null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Next's built-in optimizer (`/_next/image?url=&w=&q=`), for sources no
|
|
30
|
+
* provider resizes: a local `/public` file, another host listed in
|
|
31
|
+
* `images.remotePatterns`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function nextImageOptimizer({ src, width, quality }: DecoImageLoaderProps): string;
|
|
34
|
+
/** The next/image loader for `url`. */
|
|
35
|
+
export declare function createDecoImageLoader(url: ImageUrl, options?: DecoImageLoaderOptions): DecoImageLoader;
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/image-loader/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAE/D,wGAAwG;AACxG,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,oBAAoB,KAAK,MAAM,CAAC;AAEtE,MAAM,WAAW,sBAAsB;IACrC,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,MAAM,GAAG,IAAI,CAAC;CAC3D;AAID;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,oBAAoB,GAAG,MAAM,CAQxF;AAED,uCAAuC;AACvC,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,QAAQ,EACb,OAAO,GAAE,sBAA2B,GACnC,eAAe,CASjB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const TIER_VALUES = { low: 60, medium: 70, high: 80, original: 100 };
|
|
2
|
+
/**
|
|
3
|
+
* Next's built-in optimizer (`/_next/image?url=&w=&q=`), for sources no
|
|
4
|
+
* provider resizes: a local `/public` file, another host listed in
|
|
5
|
+
* `images.remotePatterns`.
|
|
6
|
+
*/
|
|
7
|
+
export function nextImageOptimizer({ src, width, quality }) {
|
|
8
|
+
const params = new URLSearchParams();
|
|
9
|
+
params.set("url", src);
|
|
10
|
+
params.set("w", width.toString());
|
|
11
|
+
if (quality) {
|
|
12
|
+
params.set("q", String(typeof quality === "string" ? TIER_VALUES[quality] : quality));
|
|
13
|
+
}
|
|
14
|
+
return `/_next/image?${params.toString()}`;
|
|
15
|
+
}
|
|
16
|
+
/** The next/image loader for `url`. */
|
|
17
|
+
export function createDecoImageLoader(url, options = {}) {
|
|
18
|
+
const { fallback } = options;
|
|
19
|
+
return (props) => {
|
|
20
|
+
const { src, width, quality } = props;
|
|
21
|
+
if (url.isOptimizable(src)) {
|
|
22
|
+
return url(src, quality === undefined ? { width } : { width, quality });
|
|
23
|
+
}
|
|
24
|
+
return fallback?.(props) ?? src;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/image-loader/index.ts"],"names":[],"mappings":"AA+BA,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAW,CAAC;AAE9E;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAwB;IAC9E,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACvB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IAClC,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,gBAAgB,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;AAC7C,CAAC;AAED,uCAAuC;AACvC,MAAM,UAAU,qBAAqB,CACnC,GAAa,EACb,OAAO,GAA2B,EAAE;IAEpC,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAC7B,OAAO,CAAC,KAAK,EAAE,EAAE;QACf,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;QACtC,IAAI,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1E,CAAC;QACD,OAAO,QAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC;IAClC,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@decocms/nextjs`: the components a Next.js App Router site adds, and the
|
|
3
|
+
* names and lists the proxy, the pages and `withDeco()` share.
|
|
4
|
+
*
|
|
5
|
+
* - `DraftPreviewIndicator`: the "Preview mode" badge on a page rendered from
|
|
6
|
+
* a draft (`bindDraft` from `@decocms/nextjs/server`), outside Studio's frame.
|
|
7
|
+
* - `StudioBridge`: one line in the root layout, `<StudioBridge site="my-store" />`,
|
|
8
|
+
* lets Studio's site editor drive the page when Studio frames it
|
|
9
|
+
* (`@decocms/blocks/preview`'s, answering `STUDIO_ORIGINS`). It renders an
|
|
10
|
+
* inline script with no React hooks, so a Server Component renders it as is.
|
|
11
|
+
* Outside Studio's frame, "." opens the page in Studio's editor.
|
|
12
|
+
* - `StudioPage`: rendered inside each CMS page, `<StudioPage pathTemplate={page.path} />`,
|
|
13
|
+
* tells the bridge which page "." opens (the root layout doesn't re-render per page).
|
|
14
|
+
* - `DRAFT_PARAM`, `DRAFT_COOKIE`, `DRAFT_HEADER`, `draftResponseHeaders`,
|
|
15
|
+
* `STUDIO_ORIGINS`, `STUDIO_FRAME_ANCESTORS`, `isStudioOrigin`: for a site
|
|
16
|
+
* that needs them in its own code (a route that sets its own headers, a CSP
|
|
17
|
+
* it writes itself). The package's own copy: it never imports
|
|
18
|
+
* `@decocms/tanstack`.
|
|
19
|
+
*
|
|
20
|
+
* The proxy (`/proxy`), the pages (`/server`), `next.config` (`/config`) and the
|
|
21
|
+
* image loader (`/image-loader`) are separate subpaths, so the proxy never
|
|
22
|
+
* loads React.
|
|
23
|
+
*/
|
|
24
|
+
export { DraftBadge, StudioPage, type StudioPageInfo } from "@decocms/blocks/preview";
|
|
25
|
+
export { DraftPreviewIndicator, type DraftPreviewIndicatorProps, } from "./DraftPreviewIndicator.tsx";
|
|
26
|
+
export { DRAFT_COOKIE, DRAFT_HEADER, DRAFT_PARAM, draftResponseHeaders } from "./draft.ts";
|
|
27
|
+
export { StudioBridge, type StudioBridgeProps } from "./StudioBridge.ts";
|
|
28
|
+
export { isStudioOrigin, STUDIO_FRAME_ANCESTORS, STUDIO_ORIGINS } from "./studio.ts";
|
|
29
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACtF,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,GAChC,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@decocms/nextjs`: the components a Next.js App Router site adds, and the
|
|
3
|
+
* names and lists the proxy, the pages and `withDeco()` share.
|
|
4
|
+
*
|
|
5
|
+
* - `DraftPreviewIndicator`: the "Preview mode" badge on a page rendered from
|
|
6
|
+
* a draft (`bindDraft` from `@decocms/nextjs/server`), outside Studio's frame.
|
|
7
|
+
* - `StudioBridge`: one line in the root layout, `<StudioBridge site="my-store" />`,
|
|
8
|
+
* lets Studio's site editor drive the page when Studio frames it
|
|
9
|
+
* (`@decocms/blocks/preview`'s, answering `STUDIO_ORIGINS`). It renders an
|
|
10
|
+
* inline script with no React hooks, so a Server Component renders it as is.
|
|
11
|
+
* Outside Studio's frame, "." opens the page in Studio's editor.
|
|
12
|
+
* - `StudioPage`: rendered inside each CMS page, `<StudioPage pathTemplate={page.path} />`,
|
|
13
|
+
* tells the bridge which page "." opens (the root layout doesn't re-render per page).
|
|
14
|
+
* - `DRAFT_PARAM`, `DRAFT_COOKIE`, `DRAFT_HEADER`, `draftResponseHeaders`,
|
|
15
|
+
* `STUDIO_ORIGINS`, `STUDIO_FRAME_ANCESTORS`, `isStudioOrigin`: for a site
|
|
16
|
+
* that needs them in its own code (a route that sets its own headers, a CSP
|
|
17
|
+
* it writes itself). The package's own copy: it never imports
|
|
18
|
+
* `@decocms/tanstack`.
|
|
19
|
+
*
|
|
20
|
+
* The proxy (`/proxy`), the pages (`/server`), `next.config` (`/config`) and the
|
|
21
|
+
* image loader (`/image-loader`) are separate subpaths, so the proxy never
|
|
22
|
+
* loads React.
|
|
23
|
+
*/
|
|
24
|
+
export { DraftBadge, StudioPage } from "@decocms/blocks/preview";
|
|
25
|
+
export { DraftPreviewIndicator, } from "./DraftPreviewIndicator.js";
|
|
26
|
+
export { DRAFT_COOKIE, DRAFT_HEADER, DRAFT_PARAM, draftResponseHeaders } from "./draft.js";
|
|
27
|
+
export { StudioBridge } from "./StudioBridge.js";
|
|
28
|
+
export { isStudioOrigin, STUDIO_FRAME_ANCESTORS, STUDIO_ORIGINS } from "./studio.js";
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAuB,MAAM,yBAAyB,CAAC;AACtF,OAAO,EACL,qBAAqB,GAEtB,MAAM,4BAA6B,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,EAAE,YAAY,EAA0B,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@decocms/nextjs/proxy`: draft previews in a Next.js proxy (`proxy.ts`, or
|
|
3
|
+
* `middleware.ts` before Next 16). No React and no block map: pass the proxy
|
|
4
|
+
* a CMS handle made with an empty block map and the app's options, which
|
|
5
|
+
* shares the app's instance (one per process) without pulling the site's
|
|
6
|
+
* sections into the proxy bundle:
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* // src/cms.proxy.ts
|
|
10
|
+
* export const proxyCms = createCMS({ blocks: {}, ...cmsConfig });
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* A site with a proxy of its own calls the pieces (`decideDraft`, then
|
|
14
|
+
* `draftRequestHeaders` on the request it forwards, then `applyDraft` on the
|
|
15
|
+
* response); a site without one exports `draftProxy(...)`.
|
|
16
|
+
*
|
|
17
|
+
* Statically rendered pages can't read a draft, so a drafted request to one
|
|
18
|
+
* is rewritten onto a dynamic draft route (`/_draft/<path>`, mounted as
|
|
19
|
+
* `app/%5Fdraft/...`: a literal `_draft` folder is private in Next and never
|
|
20
|
+
* routes).
|
|
21
|
+
*/
|
|
22
|
+
import type { CMS } from "@decocms/blocks";
|
|
23
|
+
import { type NextRequest, NextResponse } from "next/server.js";
|
|
24
|
+
import { type PreviewPolicy } from "../drafts.ts";
|
|
25
|
+
export { inferredPreviewHosts, type PreviewPolicy, previewHostDecision, requestLike, } from "../drafts.ts";
|
|
26
|
+
/** What the proxy needs from the CMS: the site's declared preview hosts and their check. */
|
|
27
|
+
export type CMSHandle = Pick<CMS, "draftPointer" | "settings" | "forRelease">;
|
|
28
|
+
/** What the proxy does with a request's draft state. */
|
|
29
|
+
export interface DraftDecision {
|
|
30
|
+
/** The draft this request renders, after the host check; `null` for the release. */
|
|
31
|
+
pointer: string | null;
|
|
32
|
+
/** The `Set-Cookie` the response carries: storing a draft link's pointer, or ending a preview. */
|
|
33
|
+
setCookie: string | null;
|
|
34
|
+
}
|
|
35
|
+
/** The URL prefix a drafted request is rewritten onto (`app/%5Fdraft/[[...path]]`). */
|
|
36
|
+
export declare const DRAFT_ROUTE_PREFIX = "/_draft";
|
|
37
|
+
/**
|
|
38
|
+
* The draft a request renders and the cookie its response sets, under
|
|
39
|
+
* `policy` (the same options the pages pass to `bindDraft`). A request with
|
|
40
|
+
* no `?__draft=` and no draft cookie never reaches the CMS.
|
|
41
|
+
*/
|
|
42
|
+
export declare function decideDraft(cms: CMSHandle, request: NextRequest | Request, policy?: PreviewPolicy): Promise<DraftDecision>;
|
|
43
|
+
/**
|
|
44
|
+
* The request headers to forward: the accepted pointer on `x-deco-draft`, so
|
|
45
|
+
* the root layout can bind the draft on the same request (a layout gets no
|
|
46
|
+
* `searchParams`, and on a draft link the cookie is only on the response).
|
|
47
|
+
* A copy that arrives from outside is always removed.
|
|
48
|
+
*/
|
|
49
|
+
export declare function draftRequestHeaders(request: NextRequest | Request, decision: DraftDecision): Headers;
|
|
50
|
+
/** Whether `pathname` is on the draft route: a site answers a direct hit there with its 404. */
|
|
51
|
+
export declare function isDraftRoutePath(pathname: string): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* The rewrite of a drafted request onto the draft route, keeping its path and
|
|
54
|
+
* forwarding the pointer; `null` when the request isn't drafted or is already
|
|
55
|
+
* on the draft route.
|
|
56
|
+
*/
|
|
57
|
+
export declare function rewriteToDraftRoute(request: NextRequest, decision: DraftDecision): NextResponse | null;
|
|
58
|
+
/**
|
|
59
|
+
* The cookie and the response headers of a draft: `Set-Cookie`, and for a
|
|
60
|
+
* drafted response `Cache-Control: no-store, private`, `Vary: Cookie` and
|
|
61
|
+
* `X-Robots-Tag: noindex, nofollow` (`draftResponseHeaders`). With the
|
|
62
|
+
* pointer in a cookie a draft shares its URL with the published page, so a
|
|
63
|
+
* cache keyed on the URL alone would serve it to visitors.
|
|
64
|
+
*/
|
|
65
|
+
export declare function applyDraft<R extends Response>(response: R, decision: DraftDecision): R;
|
|
66
|
+
export interface DraftProxyOptions extends PreviewPolicy {
|
|
67
|
+
/**
|
|
68
|
+
* Which drafted requests go to the draft route (a statically rendered
|
|
69
|
+
* page's). Default: every drafted request outside the draft route. Return
|
|
70
|
+
* `false` for a route that is already dynamic and binds the draft itself.
|
|
71
|
+
*/
|
|
72
|
+
rewrite?: (request: NextRequest) => boolean;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The whole draft flow for a site with no proxy of its own:
|
|
76
|
+
* `export const proxy = draftProxy(proxyCms, { site: "my-store" })`.
|
|
77
|
+
*/
|
|
78
|
+
export declare function draftProxy(cms: CMSHandle, options?: DraftProxyOptions): (request: NextRequest) => Promise<NextResponse>;
|
|
79
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/proxy/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,KAAK,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEhE,OAAO,EAML,KAAK,aAAa,EAEnB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,oBAAoB,EACpB,KAAK,aAAa,EAClB,mBAAmB,EACnB,WAAW,GACZ,MAAM,cAAc,CAAC;AAEtB,4FAA4F;AAC5F,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,GAAG,UAAU,GAAG,YAAY,CAAC,CAAC;AAE9E,wDAAwD;AACxD,MAAM,WAAW,aAAa;IAC5B,oFAAoF;IACpF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,kGAAkG;IAClG,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,uFAAuF;AACvF,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAI5C;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,SAAS,EACd,OAAO,EAAE,WAAW,GAAG,OAAO,EAC9B,MAAM,GAAE,aAAkB,GACzB,OAAO,CAAC,aAAa,CAAC,CAYxB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,WAAW,GAAG,OAAO,EAC9B,QAAQ,EAAE,aAAa,GACtB,OAAO,CAKT;AAED,gGAAgG;AAChG,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,aAAa,GACtB,YAAY,GAAG,IAAI,CAQrB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,aAAa,GAAG,CAAC,CAMtF;AAED,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC;CAC7C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,SAAS,EACd,OAAO,GAAE,iBAAsB,GAC9B,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAUjD"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { NextResponse } from "next/server.js";
|
|
2
|
+
import { DRAFT_HEADER, draftResponseHeaders } from "../draft.js";
|
|
3
|
+
import { allowedDraft, draftCookie, endsPreview, fromDraftLink, hasDraftSignal, requestLike, } from "../drafts.js";
|
|
4
|
+
export { inferredPreviewHosts, previewHostDecision, requestLike, } from "../drafts.js";
|
|
5
|
+
/** The URL prefix a drafted request is rewritten onto (`app/%5Fdraft/[[...path]]`). */
|
|
6
|
+
export const DRAFT_ROUTE_PREFIX = "/_draft";
|
|
7
|
+
const INERT = Object.freeze({ pointer: null, setCookie: null });
|
|
8
|
+
/**
|
|
9
|
+
* The draft a request renders and the cookie its response sets, under
|
|
10
|
+
* `policy` (the same options the pages pass to `bindDraft`). A request with
|
|
11
|
+
* no `?__draft=` and no draft cookie never reaches the CMS.
|
|
12
|
+
*/
|
|
13
|
+
export async function decideDraft(cms, request, policy = {}) {
|
|
14
|
+
const url = new URL(request.url);
|
|
15
|
+
const like = requestLike(request.headers, url.pathname + url.search, url.host);
|
|
16
|
+
if (like === null || !hasDraftSignal(like))
|
|
17
|
+
return INERT;
|
|
18
|
+
// Ending a preview is allowed on any host, so a cookie set earlier always goes.
|
|
19
|
+
if (endsPreview(like))
|
|
20
|
+
return { pointer: null, setCookie: draftCookie("", ["Max-Age=0"]) };
|
|
21
|
+
const pointer = await allowedDraft(cms, like, policy);
|
|
22
|
+
if (pointer === null)
|
|
23
|
+
return INERT;
|
|
24
|
+
return {
|
|
25
|
+
pointer,
|
|
26
|
+
setCookie: fromDraftLink(like, pointer) ? draftCookie(encodeURIComponent(pointer)) : null,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The request headers to forward: the accepted pointer on `x-deco-draft`, so
|
|
31
|
+
* the root layout can bind the draft on the same request (a layout gets no
|
|
32
|
+
* `searchParams`, and on a draft link the cookie is only on the response).
|
|
33
|
+
* A copy that arrives from outside is always removed.
|
|
34
|
+
*/
|
|
35
|
+
export function draftRequestHeaders(request, decision) {
|
|
36
|
+
const headers = new Headers(request.headers);
|
|
37
|
+
if (decision.pointer)
|
|
38
|
+
headers.set(DRAFT_HEADER, decision.pointer);
|
|
39
|
+
else
|
|
40
|
+
headers.delete(DRAFT_HEADER);
|
|
41
|
+
return headers;
|
|
42
|
+
}
|
|
43
|
+
/** Whether `pathname` is on the draft route: a site answers a direct hit there with its 404. */
|
|
44
|
+
export function isDraftRoutePath(pathname) {
|
|
45
|
+
return pathname === DRAFT_ROUTE_PREFIX || pathname.startsWith(`${DRAFT_ROUTE_PREFIX}/`);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The rewrite of a drafted request onto the draft route, keeping its path and
|
|
49
|
+
* forwarding the pointer; `null` when the request isn't drafted or is already
|
|
50
|
+
* on the draft route.
|
|
51
|
+
*/
|
|
52
|
+
export function rewriteToDraftRoute(request, decision) {
|
|
53
|
+
if (!decision.pointer)
|
|
54
|
+
return null;
|
|
55
|
+
const url = request.nextUrl.clone();
|
|
56
|
+
if (isDraftRoutePath(url.pathname))
|
|
57
|
+
return null;
|
|
58
|
+
url.pathname = `${DRAFT_ROUTE_PREFIX}${url.pathname}`;
|
|
59
|
+
return NextResponse.rewrite(url, {
|
|
60
|
+
request: { headers: draftRequestHeaders(request, decision) },
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The cookie and the response headers of a draft: `Set-Cookie`, and for a
|
|
65
|
+
* drafted response `Cache-Control: no-store, private`, `Vary: Cookie` and
|
|
66
|
+
* `X-Robots-Tag: noindex, nofollow` (`draftResponseHeaders`). With the
|
|
67
|
+
* pointer in a cookie a draft shares its URL with the published page, so a
|
|
68
|
+
* cache keyed on the URL alone would serve it to visitors.
|
|
69
|
+
*/
|
|
70
|
+
export function applyDraft(response, decision) {
|
|
71
|
+
if (decision.setCookie)
|
|
72
|
+
response.headers.append("set-cookie", decision.setCookie);
|
|
73
|
+
for (const [name, value] of Object.entries(draftResponseHeaders(decision.pointer))) {
|
|
74
|
+
response.headers.set(name, value);
|
|
75
|
+
}
|
|
76
|
+
return response;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The whole draft flow for a site with no proxy of its own:
|
|
80
|
+
* `export const proxy = draftProxy(proxyCms, { site: "my-store" })`.
|
|
81
|
+
*/
|
|
82
|
+
export function draftProxy(cms, options = {}) {
|
|
83
|
+
const { rewrite = () => true, ...policy } = options;
|
|
84
|
+
return async (request) => {
|
|
85
|
+
const decision = await decideDraft(cms, request, policy);
|
|
86
|
+
const rewritten = rewrite(request) ? rewriteToDraftRoute(request, decision) : null;
|
|
87
|
+
const response = rewritten ??
|
|
88
|
+
NextResponse.next({ request: { headers: draftRequestHeaders(request, decision) } });
|
|
89
|
+
return applyDraft(response, decision);
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/proxy/index.ts"],"names":[],"mappings":"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"}
|