@prismicio/next 1.1.0-alpha.1 → 1.1.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/dist/PrismicNextLink.d.ts +3 -3
- package/dist/PrismicPreview.cjs +5 -74
- package/dist/PrismicPreview.cjs.map +1 -1
- package/dist/PrismicPreview.d.ts +8 -11
- package/dist/PrismicPreview.js +5 -57
- package/dist/PrismicPreview.js.map +1 -1
- package/dist/PrismicPreviewClient.cjs +85 -0
- package/dist/PrismicPreviewClient.cjs.map +1 -0
- package/dist/PrismicPreviewClient.d.ts +4 -0
- package/dist/PrismicPreviewClient.js +85 -0
- package/dist/PrismicPreviewClient.js.map +1 -0
- package/dist/_node_modules/@prismicio/client/dist/errors/PrismicError.cjs +19 -0
- package/dist/_node_modules/@prismicio/client/dist/errors/PrismicError.cjs.map +1 -0
- package/dist/_node_modules/@prismicio/client/dist/errors/PrismicError.js +19 -0
- package/dist/_node_modules/@prismicio/client/dist/errors/PrismicError.js.map +1 -0
- package/dist/_node_modules/@prismicio/client/dist/getToolbarSrc.cjs +13 -0
- package/dist/_node_modules/@prismicio/client/dist/getToolbarSrc.cjs.map +1 -0
- package/dist/_node_modules/@prismicio/client/dist/getToolbarSrc.js +13 -0
- package/dist/_node_modules/@prismicio/client/dist/getToolbarSrc.js.map +1 -0
- package/dist/_node_modules/@prismicio/client/dist/isRepositoryName.cjs +7 -0
- package/dist/_node_modules/@prismicio/client/dist/isRepositoryName.cjs.map +1 -0
- package/dist/_node_modules/@prismicio/client/dist/isRepositoryName.js +7 -0
- package/dist/_node_modules/@prismicio/client/dist/isRepositoryName.js.map +1 -0
- package/dist/enableAutoPreviews.cjs +17 -6
- package/dist/enableAutoPreviews.cjs.map +1 -1
- package/dist/enableAutoPreviews.d.ts +11 -12
- package/dist/enableAutoPreviews.js +17 -6
- package/dist/enableAutoPreviews.js.map +1 -1
- package/dist/exitPreview.cjs +1 -1
- package/dist/exitPreview.cjs.map +1 -1
- package/dist/exitPreview.d.ts +11 -16
- package/dist/exitPreview.js +1 -1
- package/dist/exitPreview.js.map +1 -1
- package/dist/package.json.cjs +1 -1
- package/dist/package.json.js +1 -1
- package/dist/redirectToPreviewURL.cjs +13 -12
- package/dist/redirectToPreviewURL.cjs.map +1 -1
- package/dist/redirectToPreviewURL.d.ts +23 -21
- package/dist/redirectToPreviewURL.js +13 -12
- package/dist/redirectToPreviewURL.js.map +1 -1
- package/dist/setPreviewData.cjs.map +1 -1
- package/dist/setPreviewData.d.ts +9 -14
- package/dist/setPreviewData.js.map +1 -1
- package/dist/types.d.ts +52 -9
- package/package.json +5 -10
- package/src/PrismicPreview.tsx +13 -131
- package/src/PrismicPreviewClient.tsx +159 -0
- package/src/enableAutoPreviews.ts +73 -45
- package/src/exitPreview.ts +14 -26
- package/src/redirectToPreviewURL.ts +58 -64
- package/src/setPreviewData.ts +10 -14
- package/src/types.ts +58 -9
- package/dist/react-server/PrismicPreview.d.ts +0 -22
- package/dist/react-server/index.d.ts +0 -2
- package/dist/react-server/unsupported.cjs +0 -26
- package/dist/react-server/unsupported.cjs.map +0 -1
- package/dist/react-server/unsupported.d.ts +0 -6
- package/dist/react-server/unsupported.js +0 -26
- package/dist/react-server/unsupported.js.map +0 -1
- package/dist/react-server.cjs +0 -15
- package/dist/react-server.cjs.map +0 -1
- package/dist/react-server.js +0 -15
- package/dist/react-server.js.map +0 -1
- package/src/react-server/PrismicPreview.tsx +0 -74
- package/src/react-server/index.ts +0 -11
- package/src/react-server/unsupported.ts +0 -26
package/dist/types.d.ts
CHANGED
|
@@ -1,21 +1,64 @@
|
|
|
1
|
-
import type { PreviewData
|
|
1
|
+
import type { PreviewData } from "next";
|
|
2
2
|
import type { ClientConfig } from "@prismicio/client";
|
|
3
|
+
declare module "@prismicio/client" {
|
|
4
|
+
interface RequestInitLike {
|
|
5
|
+
next?: RequestInit["next"];
|
|
6
|
+
}
|
|
7
|
+
}
|
|
3
8
|
/**
|
|
4
9
|
* Configuration for creating a Prismic client with automatic preview support in
|
|
5
10
|
* Next.js apps.
|
|
6
11
|
*/
|
|
7
|
-
export type CreateClientConfig = {
|
|
12
|
+
export type CreateClientConfig = ClientConfig & {
|
|
8
13
|
/**
|
|
9
|
-
*
|
|
10
|
-
* from `getStaticProps` or `getServerSideProps`.
|
|
14
|
+
* **Only used in the Pages Directory (/pages).**
|
|
11
15
|
*
|
|
12
|
-
*
|
|
16
|
+
* The `previewData` object provided in the `getStaticProps()` or
|
|
17
|
+
* `getServerSideProps()` context object.
|
|
13
18
|
*/
|
|
14
19
|
previewData?: PreviewData;
|
|
15
20
|
/**
|
|
16
|
-
*
|
|
21
|
+
* **Only used in the Pages Directory (/pages).**
|
|
17
22
|
*
|
|
18
|
-
*
|
|
23
|
+
* The `req` object from a Next.js API route.
|
|
24
|
+
*
|
|
25
|
+
* @see Next.js API route docs: \<https://nextjs.org/docs/api-routes/introduction\>
|
|
19
26
|
*/
|
|
20
|
-
req?:
|
|
21
|
-
}
|
|
27
|
+
req?: NextApiRequestLike;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* The minimal set of properties needed from `next`'s `NextRequest` type.
|
|
31
|
+
*
|
|
32
|
+
* This request type is only compatible with Route Handlers defined in the `app`
|
|
33
|
+
* directory.
|
|
34
|
+
*/
|
|
35
|
+
export type NextRequestLike = {
|
|
36
|
+
headers: {
|
|
37
|
+
get(name: string): string | null;
|
|
38
|
+
};
|
|
39
|
+
url: string;
|
|
40
|
+
nextUrl: unknown;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* The minimal set of properties needed from `next`'s `NextApiRequest` type.
|
|
44
|
+
*
|
|
45
|
+
* This request type is only compatible with API routes defined in the `pages`
|
|
46
|
+
* directory.
|
|
47
|
+
*/
|
|
48
|
+
export type NextApiRequestLike = {
|
|
49
|
+
query: Partial<Record<string, string | string[]>>;
|
|
50
|
+
cookies: Partial<Record<string, string>>;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* The minimal set of properties needed from `next`'s `NextApiResponse` type.
|
|
54
|
+
*
|
|
55
|
+
* This request type is only compatible with API routes defined in the `pages`
|
|
56
|
+
* directory.
|
|
57
|
+
*/
|
|
58
|
+
export type NextApiResponseLike = {
|
|
59
|
+
redirect(url: string): NextApiResponseLike;
|
|
60
|
+
clearPreviewData(): NextApiResponseLike;
|
|
61
|
+
status(statusCode: number): NextApiResponseLike;
|
|
62
|
+
json(body: any): void;
|
|
63
|
+
setPreviewData(data: object | string): NextApiResponseLike;
|
|
64
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prismicio/next",
|
|
3
|
-
"version": "1.1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Helpers to integrate Prismic into Next.js apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -18,14 +18,8 @@
|
|
|
18
18
|
"sideEffects": false,
|
|
19
19
|
"exports": {
|
|
20
20
|
".": {
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
"require": "./dist/react-server.cjs"
|
|
24
|
-
},
|
|
25
|
-
"default": {
|
|
26
|
-
"import": "./dist/index.js",
|
|
27
|
-
"require": "./dist/index.cjs"
|
|
28
|
-
}
|
|
21
|
+
"import": "./dist/index.js",
|
|
22
|
+
"require": "./dist/index.cjs"
|
|
29
23
|
},
|
|
30
24
|
"./package.json": "./package.json"
|
|
31
25
|
},
|
|
@@ -70,7 +64,8 @@
|
|
|
70
64
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
71
65
|
"eslint-plugin-tsdoc": "^0.2.17",
|
|
72
66
|
"happy-dom": "^9.9.2",
|
|
73
|
-
"next": "^13.
|
|
67
|
+
"next": "^13.4.0",
|
|
68
|
+
"node-fetch": "^3.3.1",
|
|
74
69
|
"prettier": "^2.8.8",
|
|
75
70
|
"prettier-plugin-jsdoc": "^0.4.2",
|
|
76
71
|
"react": "^18.1.0",
|
package/src/PrismicPreview.tsx
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
1
|
import * as React from "react";
|
|
4
|
-
import
|
|
2
|
+
import * as prismic from "@prismicio/client";
|
|
5
3
|
import Script from "next/script";
|
|
6
4
|
|
|
7
|
-
import {
|
|
8
|
-
import { getPreviewCookieRepositoryName } from "./lib/getPreviewCookieRepositoryName";
|
|
5
|
+
import { PrismicPreviewClient } from "./PrismicPreviewClient";
|
|
9
6
|
|
|
10
7
|
/**
|
|
11
8
|
* Props for `<PrismicPreview>`.
|
|
@@ -18,26 +15,23 @@ export type PrismicPreviewProps = {
|
|
|
18
15
|
repositoryName: string;
|
|
19
16
|
|
|
20
17
|
/**
|
|
18
|
+
* **Only used in the Pages Directory (/pages).**
|
|
19
|
+
*
|
|
21
20
|
* The URL of your app's Prismic preview endpoint (default: `/api/preview`).
|
|
22
21
|
* This URL will be fetched on preview update events.
|
|
23
|
-
*
|
|
24
|
-
* **Note**: If your `next.config.js` file contains a `basePath`, it is
|
|
25
|
-
* automatically included.
|
|
26
22
|
*/
|
|
27
23
|
updatePreviewURL?: string;
|
|
28
24
|
|
|
29
25
|
/**
|
|
26
|
+
* **Only used in the Pages Directory (/pages).**
|
|
27
|
+
*
|
|
30
28
|
* The URL of your app's exit preview endpoint (default: `/api/exit-preview`).
|
|
31
29
|
* This URL will be fetched on preview exit events.
|
|
32
|
-
*
|
|
33
|
-
* **Note**: If your `next.config.js` file contains a `basePath`, it is
|
|
34
|
-
* automatically included.
|
|
35
30
|
*/
|
|
36
31
|
exitPreviewURL?: string;
|
|
37
32
|
|
|
38
33
|
/**
|
|
39
|
-
* Children to render adjacent to the Prismic Toolbar.
|
|
40
|
-
* will be rendered last.
|
|
34
|
+
* Children to render adjacent to the Prismic Toolbar.
|
|
41
35
|
*/
|
|
42
36
|
children?: React.ReactNode;
|
|
43
37
|
};
|
|
@@ -45,8 +39,8 @@ export type PrismicPreviewProps = {
|
|
|
45
39
|
/**
|
|
46
40
|
* React component that sets up Prismic Previews using the Prismic Toolbar. When
|
|
47
41
|
* the Prismic Toolbar send events to the browser, such as on preview updates
|
|
48
|
-
* and exiting, this component will automatically
|
|
49
|
-
*
|
|
42
|
+
* and exiting, this component will automatically refresh the page with the
|
|
43
|
+
* changes.
|
|
50
44
|
*
|
|
51
45
|
* This component can be wrapped around your app or added anywhere in your app's
|
|
52
46
|
* tree. It must be rendered on every page.
|
|
@@ -54,127 +48,15 @@ export type PrismicPreviewProps = {
|
|
|
54
48
|
export function PrismicPreview({
|
|
55
49
|
repositoryName,
|
|
56
50
|
children,
|
|
57
|
-
|
|
58
|
-
exitPreviewURL = "/api/exit-preview",
|
|
51
|
+
...props
|
|
59
52
|
}: PrismicPreviewProps): JSX.Element {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
const resolvedUpdatePreviewURL = router.basePath + updatePreviewURL;
|
|
63
|
-
const resolvedExitPreviewURL = router.basePath + exitPreviewURL;
|
|
64
|
-
|
|
65
|
-
React.useEffect(() => {
|
|
66
|
-
/**
|
|
67
|
-
* Starts Preview Mode and refreshes the page's props.
|
|
68
|
-
*/
|
|
69
|
-
const startPreviewMode = async () => {
|
|
70
|
-
// Start Next.js Preview Mode via the given preview API endpoint.
|
|
71
|
-
const res = await globalThis.fetch(resolvedUpdatePreviewURL);
|
|
72
|
-
|
|
73
|
-
// We check for `res.redirected` rather than `res.ok`
|
|
74
|
-
// since the update preview endpoint may redirect to a
|
|
75
|
-
// 404 page. As long as it redirects, we know the
|
|
76
|
-
// endpoint exists and at least attempted to set
|
|
77
|
-
// preview data.
|
|
78
|
-
if (res.redirected) {
|
|
79
|
-
globalThis.location.reload();
|
|
80
|
-
} else {
|
|
81
|
-
console.error(
|
|
82
|
-
`[<PrismicPreview>] Failed to start or update Preview Mode using the "${resolvedUpdatePreviewURL}" API endpoint. Does it exist?`,
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
const handlePrismicPreviewUpdate = async (event: Event) => {
|
|
88
|
-
// Prevent the toolbar from reloading the page.
|
|
89
|
-
event.preventDefault();
|
|
90
|
-
|
|
91
|
-
await startPreviewMode();
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const handlePrismicPreviewEnd = async (event: Event) => {
|
|
95
|
-
// Prevent the toolbar from reloading the page.
|
|
96
|
-
event.preventDefault();
|
|
97
|
-
|
|
98
|
-
// Exit Next.js Preview Mode via the given preview API endpoint.
|
|
99
|
-
const res = await globalThis.fetch(resolvedExitPreviewURL);
|
|
100
|
-
|
|
101
|
-
if (res.ok) {
|
|
102
|
-
globalThis.location.reload();
|
|
103
|
-
} else {
|
|
104
|
-
console.error(
|
|
105
|
-
`[<PrismicPreview>] Failed to exit Preview Mode using the "${resolvedExitPreviewURL}" API endpoint. Does it exist?`,
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
if (router.isPreview) {
|
|
111
|
-
// Register Prismic Toolbar event handlers.
|
|
112
|
-
window.addEventListener(
|
|
113
|
-
"prismicPreviewUpdate",
|
|
114
|
-
handlePrismicPreviewUpdate,
|
|
115
|
-
);
|
|
116
|
-
window.addEventListener("prismicPreviewEnd", handlePrismicPreviewEnd);
|
|
117
|
-
} else {
|
|
118
|
-
const prismicPreviewCookie = getPrismicPreviewCookie(
|
|
119
|
-
globalThis.document.cookie,
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
if (prismicPreviewCookie) {
|
|
123
|
-
// If a Prismic preview cookie is present, but Next.js Preview
|
|
124
|
-
// Mode is not active, we must activate Preview Mode manually.
|
|
125
|
-
//
|
|
126
|
-
// This will happen when a visitor accesses the page using a
|
|
127
|
-
// Prismic preview share link.
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Determines if the current location is a descendant of the app's base
|
|
131
|
-
* path.
|
|
132
|
-
*
|
|
133
|
-
* This is used to prevent infinite refrehes; when
|
|
134
|
-
* `isDescendantOfBasePath` is `false`, `router.isPreview` is also
|
|
135
|
-
* `false`.
|
|
136
|
-
*
|
|
137
|
-
* If the app does not have a base path, this should always be `true`.
|
|
138
|
-
*/
|
|
139
|
-
const locationIsDescendantOfBasePath = window.location.href.startsWith(
|
|
140
|
-
window.location.origin + router.basePath,
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
const prismicPreviewCookieRepositoryName =
|
|
144
|
-
getPreviewCookieRepositoryName(prismicPreviewCookie);
|
|
145
|
-
|
|
146
|
-
if (
|
|
147
|
-
locationIsDescendantOfBasePath &&
|
|
148
|
-
prismicPreviewCookieRepositoryName === repositoryName
|
|
149
|
-
) {
|
|
150
|
-
startPreviewMode();
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// On cleanup, unregister Prismic Toolbar event handlers.
|
|
156
|
-
return () => {
|
|
157
|
-
window.removeEventListener(
|
|
158
|
-
"prismicPreviewUpdate",
|
|
159
|
-
handlePrismicPreviewUpdate,
|
|
160
|
-
);
|
|
161
|
-
window.removeEventListener("prismicPreviewEnd", handlePrismicPreviewEnd);
|
|
162
|
-
};
|
|
163
|
-
}, [
|
|
164
|
-
repositoryName,
|
|
165
|
-
resolvedExitPreviewURL,
|
|
166
|
-
resolvedUpdatePreviewURL,
|
|
167
|
-
router.isPreview,
|
|
168
|
-
router.basePath,
|
|
169
|
-
]);
|
|
53
|
+
const toolbarSrc = prismic.getToolbarSrc(repositoryName);
|
|
170
54
|
|
|
171
55
|
return (
|
|
172
56
|
<>
|
|
173
57
|
{children}
|
|
174
|
-
<
|
|
175
|
-
|
|
176
|
-
strategy="lazyOnload"
|
|
177
|
-
/>
|
|
58
|
+
<PrismicPreviewClient repositoryName={repositoryName} {...props} />
|
|
59
|
+
<Script src={toolbarSrc} strategy="lazyOnload" />
|
|
178
60
|
</>
|
|
179
61
|
);
|
|
180
62
|
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect } from "react";
|
|
4
|
+
import { useRouter as usePagesRouter } from "next/router";
|
|
5
|
+
import { useRouter } from "next/navigation";
|
|
6
|
+
|
|
7
|
+
import { getPrismicPreviewCookie } from "./lib/getPrismicPreviewCookie";
|
|
8
|
+
import { getPreviewCookieRepositoryName } from "./lib/getPreviewCookieRepositoryName";
|
|
9
|
+
|
|
10
|
+
import { PrismicPreviewProps } from "./PrismicPreview";
|
|
11
|
+
|
|
12
|
+
type PrismicPreviewClientProps = Omit<PrismicPreviewProps, "children">;
|
|
13
|
+
|
|
14
|
+
export function PrismicPreviewClient({
|
|
15
|
+
repositoryName,
|
|
16
|
+
updatePreviewURL = "/api/preview",
|
|
17
|
+
exitPreviewURL = "/api/exit-preview",
|
|
18
|
+
}: PrismicPreviewClientProps): null {
|
|
19
|
+
let isAppRouter = true;
|
|
20
|
+
let isPreviewMode = false;
|
|
21
|
+
let basePath = "";
|
|
22
|
+
let refresh: () => void;
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
26
|
+
const router = usePagesRouter();
|
|
27
|
+
|
|
28
|
+
isAppRouter = false;
|
|
29
|
+
basePath = router.basePath;
|
|
30
|
+
isPreviewMode = router.isPreview;
|
|
31
|
+
refresh = () => router.replace(router.asPath, undefined, { scroll: false });
|
|
32
|
+
} catch {
|
|
33
|
+
// Assume we are in App Router. Ignore the error.
|
|
34
|
+
|
|
35
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
36
|
+
const router = useRouter();
|
|
37
|
+
|
|
38
|
+
refresh = router.refresh;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
/**
|
|
43
|
+
* Starts Preview Mode and refreshes the page's props.
|
|
44
|
+
*/
|
|
45
|
+
const startPreviewMode = async () => {
|
|
46
|
+
const resolvedUpdatePreviewURL = basePath + updatePreviewURL;
|
|
47
|
+
|
|
48
|
+
// Start Next.js Preview Mode via the given preview API endpoint.
|
|
49
|
+
const res = await globalThis.fetch(resolvedUpdatePreviewURL);
|
|
50
|
+
|
|
51
|
+
// We check for `res.redirected` rather than `res.ok`
|
|
52
|
+
// since the update preview endpoint may redirect to a
|
|
53
|
+
// 404 page. As long as it redirects, we know the
|
|
54
|
+
// endpoint exists and at least attempted to set
|
|
55
|
+
// preview data.
|
|
56
|
+
if (res.redirected) {
|
|
57
|
+
refresh();
|
|
58
|
+
} else {
|
|
59
|
+
console.error(
|
|
60
|
+
`[<PrismicPreview>] Failed to start or update Preview Mode using the "${resolvedUpdatePreviewURL}" API endpoint. Does it exist?`,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const handlePrismicPreviewUpdate = async (event: Event) => {
|
|
66
|
+
// Prevent the toolbar from reloading the page.
|
|
67
|
+
event.preventDefault();
|
|
68
|
+
|
|
69
|
+
if (isAppRouter) {
|
|
70
|
+
refresh();
|
|
71
|
+
} else {
|
|
72
|
+
await startPreviewMode();
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const handlePrismicPreviewEnd = async (event: Event) => {
|
|
77
|
+
// Prevent the toolbar from reloading the page.
|
|
78
|
+
event.preventDefault();
|
|
79
|
+
|
|
80
|
+
if (isAppRouter) {
|
|
81
|
+
refresh();
|
|
82
|
+
} else {
|
|
83
|
+
const resolvedExitPreviewURL = basePath + exitPreviewURL;
|
|
84
|
+
|
|
85
|
+
// Exit Next.js Preview Mode via the given preview API endpoint.
|
|
86
|
+
const res = await globalThis.fetch(resolvedExitPreviewURL);
|
|
87
|
+
|
|
88
|
+
if (res.ok) {
|
|
89
|
+
// TODO: Can we do better than a full page reload?
|
|
90
|
+
// globalThis.location.reload();
|
|
91
|
+
refresh();
|
|
92
|
+
} else {
|
|
93
|
+
console.error(
|
|
94
|
+
`[<PrismicPreview>] Failed to exit Preview Mode using the "${resolvedExitPreviewURL}" API endpoint. Does it exist?`,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
window.addEventListener("prismicPreviewUpdate", handlePrismicPreviewUpdate);
|
|
101
|
+
window.addEventListener("prismicPreviewEnd", handlePrismicPreviewEnd);
|
|
102
|
+
|
|
103
|
+
if (!isPreviewMode) {
|
|
104
|
+
const prismicPreviewCookie = getPrismicPreviewCookie(
|
|
105
|
+
globalThis.document.cookie,
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
if (prismicPreviewCookie) {
|
|
109
|
+
// If a Prismic preview cookie is present, but Next.js Preview
|
|
110
|
+
// Mode is not active, we must activate Preview Mode manually.
|
|
111
|
+
//
|
|
112
|
+
// This will happen when a visitor accesses the page using a
|
|
113
|
+
// Prismic preview share link.
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Determines if the current location is a descendant of the app's base
|
|
117
|
+
* path.
|
|
118
|
+
*
|
|
119
|
+
* This is used to prevent infinite refrehes; when
|
|
120
|
+
* `isDescendantOfBasePath` is `false`, `router.isPreview` is also
|
|
121
|
+
* `false`.
|
|
122
|
+
*
|
|
123
|
+
* If the app does not have a base path, this should always be `true`.
|
|
124
|
+
*/
|
|
125
|
+
const locationIsDescendantOfBasePath = window.location.href.startsWith(
|
|
126
|
+
window.location.origin + basePath,
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const prismicPreviewCookieRepositoryName =
|
|
130
|
+
getPreviewCookieRepositoryName(prismicPreviewCookie);
|
|
131
|
+
|
|
132
|
+
if (
|
|
133
|
+
locationIsDescendantOfBasePath &&
|
|
134
|
+
prismicPreviewCookieRepositoryName === repositoryName
|
|
135
|
+
) {
|
|
136
|
+
startPreviewMode();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return () => {
|
|
142
|
+
window.removeEventListener(
|
|
143
|
+
"prismicPreviewUpdate",
|
|
144
|
+
handlePrismicPreviewUpdate,
|
|
145
|
+
);
|
|
146
|
+
window.removeEventListener("prismicPreviewEnd", handlePrismicPreviewEnd);
|
|
147
|
+
};
|
|
148
|
+
}, [
|
|
149
|
+
basePath,
|
|
150
|
+
exitPreviewURL,
|
|
151
|
+
isAppRouter,
|
|
152
|
+
isPreviewMode,
|
|
153
|
+
refresh,
|
|
154
|
+
repositoryName,
|
|
155
|
+
updatePreviewURL,
|
|
156
|
+
]);
|
|
157
|
+
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
@@ -1,23 +1,8 @@
|
|
|
1
1
|
import { PreviewData } from "next";
|
|
2
|
-
import
|
|
2
|
+
import { cookies } from "next/headers";
|
|
3
|
+
import * as prismic from "@prismicio/client";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
ref: string;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Determines if a Next.js preview data object contains Prismic preview data.
|
|
10
|
-
*
|
|
11
|
-
* @param previewData - The Next.js preview data object to check.
|
|
12
|
-
*
|
|
13
|
-
* @returns `true` if `previewData` contains Prismic preview data, `false`
|
|
14
|
-
* otherwise.
|
|
15
|
-
*/
|
|
16
|
-
const isPrismicNextPreviewData = (
|
|
17
|
-
previewData: PreviewData,
|
|
18
|
-
): previewData is PrismicNextPreviewData => {
|
|
19
|
-
return typeof previewData === "object" && "ref" in previewData;
|
|
20
|
-
};
|
|
5
|
+
import { NextApiRequestLike } from "./types";
|
|
21
6
|
|
|
22
7
|
/**
|
|
23
8
|
* Configuration for `enableAutoPreviews`.
|
|
@@ -37,27 +22,25 @@ export type EnableAutoPreviewsConfig<
|
|
|
37
22
|
prismic.Client,
|
|
38
23
|
"queryContentFromRef" | "enableAutoPreviewsFromReq"
|
|
39
24
|
>;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
);
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* **Only used in the Pages Directory (/pages).**
|
|
28
|
+
*
|
|
29
|
+
* The `previewData` object provided in the `getStaticProps()` or
|
|
30
|
+
* `getServerSideProps()` context object.
|
|
31
|
+
*/
|
|
32
|
+
previewData?: TPreviewData;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* **Only used in the Pages Directory (/pages).**
|
|
36
|
+
*
|
|
37
|
+
* The `req` object from a Next.js API route.
|
|
38
|
+
*
|
|
39
|
+
* @see Next.js API route docs: \<https://nextjs.org/docs/api-routes/introduction\>
|
|
40
|
+
*/
|
|
41
|
+
req?: NextApiRequestLike;
|
|
42
|
+
};
|
|
43
|
+
|
|
61
44
|
/**
|
|
62
45
|
* Configures a Prismic client to automatically query draft content during a
|
|
63
46
|
* preview session. It either takes in a Next.js `getStaticProps` context object
|
|
@@ -69,16 +52,61 @@ export const enableAutoPreviews = <TPreviewData extends PreviewData>(
|
|
|
69
52
|
config: EnableAutoPreviewsConfig<TPreviewData>,
|
|
70
53
|
): void => {
|
|
71
54
|
if ("previewData" in config && config.previewData) {
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
55
|
+
// Assume we are in `getStaticProps()` or
|
|
56
|
+
// `getServerSideProps()` with active Preview Mode (`pages`
|
|
57
|
+
// directory).
|
|
75
58
|
|
|
76
|
-
if (
|
|
77
|
-
config.
|
|
59
|
+
if (
|
|
60
|
+
typeof config.previewData === "object" &&
|
|
61
|
+
"ref" in config.previewData &&
|
|
62
|
+
typeof config.previewData.ref === "string"
|
|
63
|
+
) {
|
|
64
|
+
config.client.queryContentFromRef(config.previewData.ref);
|
|
78
65
|
}
|
|
79
66
|
} else if ("req" in config && config.req) {
|
|
80
|
-
//
|
|
67
|
+
// Assume we are in an API Route (`pages` directory).
|
|
81
68
|
|
|
82
69
|
config.client.enableAutoPreviewsFromReq(config.req);
|
|
70
|
+
} else {
|
|
71
|
+
// Assume we are in App Router (`app` directory) OR
|
|
72
|
+
// `getStaticProps()`/`getServerSideProps()` with an inactive
|
|
73
|
+
// Preview Mode (`pages` directory).
|
|
74
|
+
|
|
75
|
+
// We use a function value so the cookie is checked on every
|
|
76
|
+
// request. We don't have a static value to read from.
|
|
77
|
+
config.client.queryContentFromRef(() => {
|
|
78
|
+
let cookie: string | undefined;
|
|
79
|
+
try {
|
|
80
|
+
cookie = cookies().get(prismic.cookie.preview)?.value;
|
|
81
|
+
} catch {
|
|
82
|
+
// noop - We are probably in
|
|
83
|
+
// `getStaticProps()` or `getServerSideProps()`
|
|
84
|
+
// with inactive Preview Mode where `cookies()`
|
|
85
|
+
// does not work. We don't need to do any
|
|
86
|
+
// preview handling.
|
|
87
|
+
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// We are probably in App Router (`app` directory).
|
|
92
|
+
|
|
93
|
+
// We only return the cookie if a Prismic Preview session is active.
|
|
94
|
+
//
|
|
95
|
+
// An inactive cookie looks like this (URL encoded):
|
|
96
|
+
// {
|
|
97
|
+
// "_tracker": "abc123"
|
|
98
|
+
// }
|
|
99
|
+
//
|
|
100
|
+
// An active cookie looks like this (URL encoded):
|
|
101
|
+
// {
|
|
102
|
+
// "_tracker": "abc123",
|
|
103
|
+
// "example-prismic-repo.prismic.io": {
|
|
104
|
+
// preview: "https://example-prismic-repo.prismic.io/previews/abc:123?websitePreviewId=xyz"
|
|
105
|
+
// }
|
|
106
|
+
// }
|
|
107
|
+
if (cookie && /\.prismic\.io/.test(cookie)) {
|
|
108
|
+
return cookie;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
83
111
|
}
|
|
84
112
|
};
|
package/src/exitPreview.ts
CHANGED
|
@@ -1,46 +1,34 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
|
|
3
|
+
import { NextApiRequestLike, NextApiResponseLike } from "./types";
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Configuration for `exitPreview`.
|
|
5
7
|
*/
|
|
6
8
|
export type ExitPreviewConfig = {
|
|
7
9
|
/**
|
|
8
|
-
* The `req` object from a Next.js API route.
|
|
9
|
-
* the API route.
|
|
10
|
+
* The `req` object from a Next.js API route.
|
|
10
11
|
*
|
|
11
|
-
* @see Next.js API route docs:
|
|
12
|
+
* @see Next.js API route docs: \<https://nextjs.org/docs/api-routes/introduction\>
|
|
12
13
|
*/
|
|
13
|
-
|
|
14
|
-
// redirect the user to the referring URL, but it no longer has that
|
|
15
|
-
// behavior.
|
|
16
|
-
//
|
|
17
|
-
// `req` is retained as a parameter to make setting up an exit preview
|
|
18
|
-
// API route easier (this eliminates the awkward need to handle an
|
|
19
|
-
// unused `req` param).
|
|
20
|
-
//
|
|
21
|
-
// It is also retained in case it is needed in the future, such as
|
|
22
|
-
// reading headers or metadata about the request.
|
|
23
|
-
req: {
|
|
24
|
-
headers: NextApiRequest["headers"];
|
|
25
|
-
};
|
|
14
|
+
req: NextApiRequestLike;
|
|
26
15
|
|
|
27
16
|
/**
|
|
28
|
-
* The `res` object from a Next.js API route.
|
|
29
|
-
* the API route.
|
|
17
|
+
* The `res` object from a Next.js API route.
|
|
30
18
|
*
|
|
31
|
-
* @see Next.js API route docs:
|
|
19
|
+
* @see Next.js API route docs: \<https://nextjs.org/docs/api-routes/introduction\>
|
|
32
20
|
*/
|
|
33
|
-
res:
|
|
34
|
-
clearPreviewData: NextApiResponse["clearPreviewData"];
|
|
35
|
-
status: NextApiResponse["status"];
|
|
36
|
-
json: NextApiResponse["json"];
|
|
37
|
-
};
|
|
21
|
+
res: NextApiResponseLike;
|
|
38
22
|
};
|
|
39
23
|
|
|
40
24
|
/**
|
|
25
|
+
* **Only use this function in the Pages Directory (/pages).**
|
|
26
|
+
*
|
|
41
27
|
* Exits Next.js's Preview Mode from within a Next.js API route.
|
|
42
28
|
*/
|
|
43
|
-
export function exitPreview(
|
|
29
|
+
export async function exitPreview(
|
|
30
|
+
config: ExitPreviewConfig,
|
|
31
|
+
): Promise<NextResponse | void> {
|
|
44
32
|
// Exit the current user from Preview Mode.
|
|
45
33
|
config.res.clearPreviewData();
|
|
46
34
|
|