@prismicio/next 1.7.0 → 2.0.0-alpha.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.
Files changed (150) hide show
  1. package/README.md +5 -3
  2. package/dist/PrismicNextImage.d.ts +7 -8
  3. package/dist/PrismicNextImage.js +8 -8
  4. package/dist/PrismicNextImage.js.map +1 -1
  5. package/dist/PrismicNextLink.d.ts +99 -100
  6. package/dist/PrismicNextLink.js +3 -5
  7. package/dist/PrismicNextLink.js.map +1 -1
  8. package/dist/PrismicPreview.d.ts +5 -13
  9. package/dist/PrismicPreview.js +6 -9
  10. package/dist/PrismicPreview.js.map +1 -1
  11. package/dist/PrismicPreviewClient.d.ts +5 -3
  12. package/dist/PrismicPreviewClient.js +58 -69
  13. package/dist/PrismicPreviewClient.js.map +1 -1
  14. package/dist/createLocaleRedirect.d.ts +8 -15
  15. package/dist/createLocaleRedirect.js +4 -28
  16. package/dist/createLocaleRedirect.js.map +1 -1
  17. package/dist/enableAutoPreviews.d.ts +7 -31
  18. package/dist/enableAutoPreviews.js +24 -35
  19. package/dist/enableAutoPreviews.js.map +1 -1
  20. package/dist/exitPreview.d.ts +5 -47
  21. package/dist/exitPreview.js +8 -15
  22. package/dist/exitPreview.js.map +1 -1
  23. package/dist/imgixLoader.js.map +1 -1
  24. package/dist/index.d.ts +15 -18
  25. package/dist/index.js +2 -4
  26. package/dist/index.js.map +1 -1
  27. package/dist/lib/devMsg.d.ts +1 -1
  28. package/dist/lib/devMsg.js.map +1 -1
  29. package/dist/package.json.js +1 -1
  30. package/dist/pages/PrismicPreview.d.ts +31 -0
  31. package/dist/pages/PrismicPreview.js +64 -0
  32. package/dist/pages/PrismicPreview.js.map +1 -0
  33. package/dist/pages/enableAutoPreviews.d.ts +31 -0
  34. package/dist/pages/enableAutoPreviews.js +19 -0
  35. package/dist/pages/enableAutoPreviews.js.map +1 -0
  36. package/dist/pages/exitPreview.d.ts +33 -0
  37. package/dist/pages/exitPreview.js +10 -0
  38. package/dist/pages/exitPreview.js.map +1 -0
  39. package/dist/pages/index.d.ts +18 -0
  40. package/dist/pages/redirectToPreviewURL.d.ts +43 -0
  41. package/dist/pages/redirectToPreviewURL.js +16 -0
  42. package/dist/pages/redirectToPreviewURL.js.map +1 -0
  43. package/dist/{setPreviewData.d.ts → pages/setPreviewData.d.ts} +3 -9
  44. package/dist/{setPreviewData.js → pages/setPreviewData.js} +2 -2
  45. package/dist/pages/setPreviewData.js.map +1 -0
  46. package/dist/pages/types.d.ts +30 -0
  47. package/dist/pages.js +21 -0
  48. package/dist/pages.js.map +1 -0
  49. package/dist/redirectToPreviewURL.d.ts +11 -41
  50. package/dist/redirectToPreviewURL.js +16 -22
  51. package/dist/redirectToPreviewURL.js.map +1 -1
  52. package/dist/types.d.ts +2 -51
  53. package/package.json +61 -54
  54. package/src/PrismicNextImage.tsx +19 -16
  55. package/src/PrismicNextLink.tsx +17 -13
  56. package/src/PrismicPreview.tsx +18 -30
  57. package/src/PrismicPreviewClient.tsx +111 -138
  58. package/src/createLocaleRedirect.ts +14 -56
  59. package/src/enableAutoPreviews.ts +38 -110
  60. package/src/exitPreview.ts +18 -79
  61. package/src/index.ts +15 -26
  62. package/src/lib/devMsg.ts +1 -1
  63. package/src/pages/PrismicPreview.tsx +145 -0
  64. package/src/pages/enableAutoPreviews.ts +62 -0
  65. package/src/pages/exitPreview.ts +45 -0
  66. package/src/pages/index.ts +27 -0
  67. package/src/pages/redirectToPreviewURL.ts +77 -0
  68. package/src/{setPreviewData.ts → pages/setPreviewData.ts} +5 -11
  69. package/src/pages/types.ts +36 -0
  70. package/src/redirectToPreviewURL.ts +44 -95
  71. package/src/types.ts +2 -56
  72. package/dist/PrismicNextImage.cjs +0 -64
  73. package/dist/PrismicNextImage.cjs.map +0 -1
  74. package/dist/PrismicNextLink.cjs +0 -40
  75. package/dist/PrismicNextLink.cjs.map +0 -1
  76. package/dist/PrismicPreview.cjs +0 -18
  77. package/dist/PrismicPreview.cjs.map +0 -1
  78. package/dist/PrismicPreviewClient.cjs +0 -81
  79. package/dist/PrismicPreviewClient.cjs.map +0 -1
  80. package/dist/_node_modules/@prismicio/client/dist/cookie.cjs +0 -5
  81. package/dist/_node_modules/@prismicio/client/dist/cookie.cjs.map +0 -1
  82. package/dist/_node_modules/@prismicio/client/dist/cookie.js +0 -5
  83. package/dist/_node_modules/@prismicio/client/dist/cookie.js.map +0 -1
  84. package/dist/_node_modules/@prismicio/client/dist/errors/PrismicError.cjs +0 -16
  85. package/dist/_node_modules/@prismicio/client/dist/errors/PrismicError.cjs.map +0 -1
  86. package/dist/_node_modules/@prismicio/client/dist/errors/PrismicError.js +0 -16
  87. package/dist/_node_modules/@prismicio/client/dist/errors/PrismicError.js.map +0 -1
  88. package/dist/_node_modules/@prismicio/client/dist/getToolbarSrc.cjs +0 -13
  89. package/dist/_node_modules/@prismicio/client/dist/getToolbarSrc.cjs.map +0 -1
  90. package/dist/_node_modules/@prismicio/client/dist/getToolbarSrc.js +0 -13
  91. package/dist/_node_modules/@prismicio/client/dist/getToolbarSrc.js.map +0 -1
  92. package/dist/_node_modules/@prismicio/client/dist/helpers/asLink.cjs +0 -47
  93. package/dist/_node_modules/@prismicio/client/dist/helpers/asLink.cjs.map +0 -1
  94. package/dist/_node_modules/@prismicio/client/dist/helpers/asLink.js +0 -47
  95. package/dist/_node_modules/@prismicio/client/dist/helpers/asLink.js.map +0 -1
  96. package/dist/_node_modules/@prismicio/client/dist/helpers/asLinkAttrs.cjs +0 -28
  97. package/dist/_node_modules/@prismicio/client/dist/helpers/asLinkAttrs.cjs.map +0 -1
  98. package/dist/_node_modules/@prismicio/client/dist/helpers/asLinkAttrs.js +0 -28
  99. package/dist/_node_modules/@prismicio/client/dist/helpers/asLinkAttrs.js.map +0 -1
  100. package/dist/_node_modules/@prismicio/client/dist/helpers/documentToLinkField.cjs +0 -27
  101. package/dist/_node_modules/@prismicio/client/dist/helpers/documentToLinkField.cjs.map +0 -1
  102. package/dist/_node_modules/@prismicio/client/dist/helpers/documentToLinkField.js +0 -27
  103. package/dist/_node_modules/@prismicio/client/dist/helpers/documentToLinkField.js.map +0 -1
  104. package/dist/_node_modules/@prismicio/client/dist/helpers/isFilled.cjs +0 -14
  105. package/dist/_node_modules/@prismicio/client/dist/helpers/isFilled.cjs.map +0 -1
  106. package/dist/_node_modules/@prismicio/client/dist/helpers/isFilled.js +0 -14
  107. package/dist/_node_modules/@prismicio/client/dist/helpers/isFilled.js.map +0 -1
  108. package/dist/_node_modules/@prismicio/client/dist/isRepositoryName.cjs +0 -7
  109. package/dist/_node_modules/@prismicio/client/dist/isRepositoryName.cjs.map +0 -1
  110. package/dist/_node_modules/@prismicio/client/dist/isRepositoryName.js +0 -7
  111. package/dist/_node_modules/@prismicio/client/dist/isRepositoryName.js.map +0 -1
  112. package/dist/_node_modules/@prismicio/client/dist/lib/isInternalURL.cjs +0 -9
  113. package/dist/_node_modules/@prismicio/client/dist/lib/isInternalURL.cjs.map +0 -1
  114. package/dist/_node_modules/@prismicio/client/dist/lib/isInternalURL.js +0 -9
  115. package/dist/_node_modules/@prismicio/client/dist/lib/isInternalURL.js.map +0 -1
  116. package/dist/_node_modules/@prismicio/client/dist/types/value/link.cjs +0 -10
  117. package/dist/_node_modules/@prismicio/client/dist/types/value/link.cjs.map +0 -1
  118. package/dist/_node_modules/@prismicio/client/dist/types/value/link.js +0 -10
  119. package/dist/_node_modules/@prismicio/client/dist/types/value/link.js.map +0 -1
  120. package/dist/createLocaleRedirect.cjs +0 -32
  121. package/dist/createLocaleRedirect.cjs.map +0 -1
  122. package/dist/enableAutoPreviews.cjs +0 -40
  123. package/dist/enableAutoPreviews.cjs.map +0 -1
  124. package/dist/exitPreview.cjs +0 -20
  125. package/dist/exitPreview.cjs.map +0 -1
  126. package/dist/imgixLoader.cjs +0 -17
  127. package/dist/imgixLoader.cjs.map +0 -1
  128. package/dist/index.cjs +0 -21
  129. package/dist/index.cjs.map +0 -1
  130. package/dist/lib/devMsg.cjs +0 -8
  131. package/dist/lib/devMsg.cjs.map +0 -1
  132. package/dist/lib/getPreviewCookieRepositoryName.cjs +0 -7
  133. package/dist/lib/getPreviewCookieRepositoryName.cjs.map +0 -1
  134. package/dist/lib/getPreviewCookieRepositoryName.d.ts +0 -9
  135. package/dist/lib/getPreviewCookieRepositoryName.js +0 -7
  136. package/dist/lib/getPreviewCookieRepositoryName.js.map +0 -1
  137. package/dist/lib/getPrismicPreviewCookie.cjs +0 -21
  138. package/dist/lib/getPrismicPreviewCookie.cjs.map +0 -1
  139. package/dist/lib/getPrismicPreviewCookie.d.ts +0 -9
  140. package/dist/lib/getPrismicPreviewCookie.js +0 -21
  141. package/dist/lib/getPrismicPreviewCookie.js.map +0 -1
  142. package/dist/package.json.cjs +0 -5
  143. package/dist/package.json.cjs.map +0 -1
  144. package/dist/redirectToPreviewURL.cjs +0 -30
  145. package/dist/redirectToPreviewURL.cjs.map +0 -1
  146. package/dist/setPreviewData.cjs +0 -11
  147. package/dist/setPreviewData.cjs.map +0 -1
  148. package/dist/setPreviewData.js.map +0 -1
  149. package/src/lib/getPreviewCookieRepositoryName.ts +0 -14
  150. package/src/lib/getPrismicPreviewCookie.ts +0 -33
@@ -1,60 +1,18 @@
1
- import Negotiator from "negotiator";
2
- import { match } from "@formatjs/intl-localematcher";
3
- import * as prismic from "@prismicio/client";
4
-
5
- import { NextRequestLike } from "./types";
6
-
7
- export type CreateLocaleRedirectConfig = {
8
- request: NextRequestLike;
9
- client: Pick<prismic.Client, "getRepository">;
10
- localeOverrides?: Record<string, string>;
11
- omitDefaultLocale?: boolean;
12
- };
1
+ import { devMsg } from "./lib/devMsg.js";
13
2
 
14
3
  /**
15
- * Creates a `Response` that redirects a request to the requester's preferred
16
- * locale. This function returns `undefined` if the request already contains a
17
- * locale.
18
- *
19
- * @returns A `Response` if the request should be redirected, `undefined`
20
- * otherwise.
4
+ * @deprecated `createLocaleRedirect()` has been removed due to performance
5
+ * issues.
21
6
  */
22
- export const createLocaleRedirect = async (
23
- config: CreateLocaleRedirectConfig,
24
- ): Promise<Response | undefined> => {
25
- const repository = await config.client.getRepository();
26
-
27
- const locales = repository.languages.map((language) => {
28
- return config.localeOverrides?.[language.id] ?? language.id;
29
- });
30
- const defaultLocale = locales[0];
31
-
32
- const { pathname } = config.request.nextUrl;
33
- const pathnameHasLocale = locales.some(
34
- (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`,
7
+ export function createLocaleRedirect() {
8
+ throw new Error(
9
+ `createLocaleRedirect() has been removed due to performance issues. See ${devMsg(
10
+ "replace-createLocaleRedirect",
11
+ )} for more details.`,
35
12
  );
36
-
37
- if (pathnameHasLocale) {
38
- return;
39
- }
40
-
41
- let locale = defaultLocale;
42
-
43
- const headers = {
44
- "accept-language":
45
- config.request.headers.get("accept-language") ?? undefined,
46
- };
47
-
48
- if (headers["accept-language"]) {
49
- const languages = new Negotiator({ headers }).languages();
50
- locale = match(languages, locales, defaultLocale);
51
- }
52
-
53
- if (locale === defaultLocale && config.omitDefaultLocale) {
54
- return;
55
- }
56
-
57
- config.request.nextUrl.pathname = `/${locale}${pathname}`;
58
-
59
- return Response.redirect(config.request.nextUrl as URL);
60
- };
13
+ }
14
+ /**
15
+ * @deprecated `createLocaleRedirect()` has been removed due to performance
16
+ * issues.
17
+ */
18
+ export type CreateLocaleRedirectConfig = never;
@@ -1,125 +1,53 @@
1
- import { draftMode, cookies } from "next/headers";
2
- import { PreviewData } from "next";
3
- import * as prismic from "@prismicio/client";
1
+ import { type Client, cookie as prismicCookie } from "@prismicio/client";
4
2
 
5
- import { NextApiRequestLike, PrismicPreviewData } from "./types";
6
-
7
- /**
8
- * Configuration for `enableAutoPreviews`.
9
- *
10
- * @typeParam TPreviewData - Next.js preview data object.
11
- */
12
- export type EnableAutoPreviewsConfig<
13
- TPreviewData extends PreviewData = PreviewData,
14
- > = {
15
- /**
16
- * Prismic client with which automatic previews will be enabled.
17
- */
3
+ /** Configuration for `enableAutoPreviews`. */
4
+ export type EnableAutoPreviewsConfig = {
5
+ /** Prismic client with which automatic previews will be enabled. */
18
6
  // `Pick` is used to use the smallest possible subset of
19
7
  // `prismic.Client`. Doing this reduces the surface area for breaking
20
8
  // type changes.
21
- client: Pick<
22
- prismic.Client,
23
- "queryContentFromRef" | "enableAutoPreviewsFromReq"
24
- >;
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
-
44
- const isPrismicPreviewData = (input: unknown): input is PrismicPreviewData => {
45
- return typeof input === "object" && input !== null && "ref" in input;
9
+ client: Pick<Client, "queryContentFromRef" | "enableAutoPreviewsFromReq">;
46
10
  };
47
11
 
48
12
  /**
49
13
  * Configures a Prismic client to automatically query draft content during a
50
- * preview session. It either takes in a Next.js `getStaticProps` context object
51
- * or a Next.js API endpoint request object.
14
+ * preview session.
52
15
  *
53
16
  * @param config - Configuration for the function.
54
17
  */
55
- export const enableAutoPreviews = <TPreviewData extends PreviewData>(
56
- config: EnableAutoPreviewsConfig<TPreviewData>,
57
- ): void => {
58
- if ("previewData" in config && config.previewData) {
59
- // Assume we are in `getStaticProps()` or
60
- // `getServerSideProps()` with active Preview Mode (`pages`
61
- // directory).
62
-
63
- if (isPrismicPreviewData(config.previewData)) {
64
- config.client.queryContentFromRef(config.previewData.ref);
18
+ export function enableAutoPreviews(config: EnableAutoPreviewsConfig): void {
19
+ // We use a function value so the cookie is checked on every
20
+ // request. We don't have a static value to read from.
21
+ config.client.queryContentFromRef(async () => {
22
+ // Need this to avoid the following Next.js build-time error:
23
+ // You're importing a component that needs next/headers. That only works
24
+ // in a Server Component which is not supported in the pages/ directory.
25
+ const { cookies, draftMode } = await import("next/headers");
26
+
27
+ let isDraftModeEnabled = false;
28
+ try {
29
+ isDraftModeEnabled = (await draftMode()).isEnabled;
30
+ } catch {
31
+ // `draftMode()` may have been called in a palce that
32
+ // does not have access to its async storage. This
33
+ // occurs in places like `generateStaticParams()`. We
34
+ // can ignore this case.
35
+ return;
36
+ }
37
+ if (!isDraftModeEnabled) {
38
+ return;
65
39
  }
66
- } else if ("req" in config && config.req) {
67
- // Assume we are in an API Route (`pages` directory).
68
-
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 isDraftModeEnabled = false;
79
- try {
80
- isDraftModeEnabled = draftMode().isEnabled;
81
- } catch {
82
- // This catch block may be reached if
83
- // `draftMode()` is called in a place that does
84
- // not have access to its async storage. We can
85
- // ignore this case.
86
-
87
- return;
88
- }
89
-
90
- if (!isDraftModeEnabled) {
91
- return;
92
- }
93
40
 
94
- let cookie: string | undefined;
95
- try {
96
- cookie = cookies().get(prismic.cookie.preview)?.value;
97
- } catch {
98
- // We are probably in `getStaticProps()` or
99
- // `getServerSideProps()` with inactive Preview
100
- // Mode where `cookies()` does not work. We
101
- // don't need to do any preview handling.
41
+ const cookie = (await cookies()).get(prismicCookie.preview)?.value;
42
+ if (!cookie) {
43
+ return;
44
+ }
102
45
 
103
- return;
104
- }
46
+ const isActiveCookie = cookie.includes("websitePreviewId=");
47
+ if (!isActiveCookie) {
48
+ return;
49
+ }
105
50
 
106
- // We only return the cookie if a Prismic Preview session is active.
107
- //
108
- // An inactive cookie looks like this (URL encoded):
109
- // {
110
- // "_tracker": "abc123"
111
- // }
112
- //
113
- // An active cookie looks like this (URL encoded):
114
- // {
115
- // "_tracker": "abc123",
116
- // "example-prismic-repo.prismic.io": {
117
- // preview: "https://example-prismic-repo.prismic.io/previews/abc:123?websitePreviewId=xyz"
118
- // }
119
- // }
120
- if (cookie && /\.prismic\.io/.test(cookie)) {
121
- return cookie;
122
- }
123
- });
124
- }
125
- };
51
+ return cookie;
52
+ });
53
+ }
@@ -1,92 +1,31 @@
1
- import { draftMode } from "next/headers";
2
-
3
- import { NextApiRequestLike, NextApiResponseLike } from "./types";
4
-
5
- /**
6
- * @deprecated Use `ExitPreviewAPIRouteConfig` instead when `exitPreview()` is
7
- * used in a Pages Router API endpoint. `exitPreview()` does not require any
8
- * configuration when used in an App Router Route Handler.
9
- */
10
- export type ExitPreviewConfig = ExitPreviewAPIRouteConfig;
11
-
12
- /**
13
- * Configuration for `exitPreview()` when used in a Pages Router API route.
14
- */
15
- export type ExitPreviewAPIRouteConfig = {
16
- /**
17
- * **Only use this parameter in the Pages Directory (/pages).**
18
- *
19
- * The `req` object from a Next.js API route.
20
- *
21
- * @see Next.js API route docs: \<https://nextjs.org/docs/api-routes/introduction\>
22
- */
23
- req?: NextApiRequestLike;
24
-
25
- /**
26
- * **Only use this parameter in the Pages Directory (/pages).**
27
- *
28
- * The `res` object from a Next.js API route.
29
- *
30
- * @see Next.js API route docs: \<https://nextjs.org/docs/api-routes/introduction\>
31
- */
32
- res?: NextApiResponseLike;
33
- };
34
-
35
1
  /**
36
2
  * Ends a Prismic preview session within a Next.js app. This function should be
37
- * used in a Router Handler or an API route, depending on whether you are using
38
- * the App Router or Pages Router.
3
+ * used in a Router Handler.
39
4
  *
40
- * @example Usage within an App Router Route Handler.
5
+ * @example
41
6
  *
42
7
  * ```typescript
43
8
  * // src/app/api/exit-preview/route.js
44
9
  *
45
10
  * import { exitPreview } from "@prismicio/next";
46
11
  *
47
- * export function GET() {
48
- * return exitPreview();
49
- * }
50
- * ```
51
- *
52
- * @example Usage within a Pages Router API Route.
53
- *
54
- * ```typescript
55
- * // src/pages/api/exit-preview.js
56
- *
57
- * import { exitPreview } from "@prismicio/next";
58
- *
59
- * export default function handler(req, res) {
60
- * exitPreview({ req, res });
12
+ * export async function GET() {
13
+ * return await exitPreview();
61
14
  * }
62
15
  * ```
63
16
  */
64
- export function exitPreview(): Response;
65
- export function exitPreview(config: ExitPreviewAPIRouteConfig): void;
66
- export function exitPreview(
67
- config?: ExitPreviewAPIRouteConfig,
68
- ): Response | void {
69
- if (config?.res) {
70
- // Assume Preview Mode is being used.
71
-
72
- config.res.clearPreviewData();
73
-
74
- // `Cache-Control` header is used to prevent CDN-level caching.
75
- config.res.setHeader("Cache-Control", "no-store");
76
-
77
- config.res.json({ success: true });
78
-
79
- return;
80
- } else {
81
- // Assume Draft Mode is being used.
82
-
83
- draftMode().disable();
84
-
85
- // `Cache-Control` header is used to prevent CDN-level caching.
86
- return new Response(JSON.stringify({ success: true }), {
87
- headers: {
88
- "Cache-Control": "no-store",
89
- },
90
- });
91
- }
17
+ export async function exitPreview(): Promise<Response> {
18
+ // Need this to avoid the following Next.js build-time error:
19
+ // You're importing a component that needs next/headers. That only works
20
+ // in a Server Component which is not supported in the pages/ directory.
21
+ const { draftMode } = await import("next/headers");
22
+
23
+ (await draftMode()).disable();
24
+
25
+ // `Cache-Control` header is used to prevent CDN-level caching.
26
+ return new Response(JSON.stringify({ success: true }), {
27
+ headers: {
28
+ "Cache-Control": "no-store",
29
+ },
30
+ });
92
31
  }
package/src/index.ts CHANGED
@@ -1,34 +1,23 @@
1
- export { setPreviewData } from "./setPreviewData";
2
- export type { SetPreviewDataConfig } from "./setPreviewData";
1
+ export { exitPreview } from "./exitPreview.js";
3
2
 
4
- export { exitPreview } from "./exitPreview";
5
- export type {
6
- ExitPreviewConfig,
7
- ExitPreviewAPIRouteConfig,
8
- } from "./exitPreview";
3
+ export { PrismicPreview } from "./PrismicPreview.js";
4
+ export type { PrismicPreviewProps } from "./PrismicPreview.js";
9
5
 
10
- export { PrismicPreview } from "./PrismicPreview";
11
- export type { PrismicPreviewProps } from "./PrismicPreview";
6
+ export { PrismicNextLink } from "./PrismicNextLink.js";
7
+ export type { PrismicNextLinkProps } from "./PrismicNextLink.js";
12
8
 
13
- export { PrismicNextLink } from "./PrismicNextLink";
14
- export type { PrismicNextLinkProps } from "./PrismicNextLink";
9
+ export { enableAutoPreviews } from "./enableAutoPreviews.js";
10
+ export type { EnableAutoPreviewsConfig } from "./enableAutoPreviews.js";
15
11
 
16
- export { enableAutoPreviews } from "./enableAutoPreviews";
17
- export type { EnableAutoPreviewsConfig } from "./enableAutoPreviews";
12
+ export { redirectToPreviewURL } from "./redirectToPreviewURL.js";
13
+ export type { RedirectToPreviewURLConfig } from "./redirectToPreviewURL.js";
18
14
 
19
- export { redirectToPreviewURL } from "./redirectToPreviewURL";
20
- export type {
21
- RedirectToPreviewURLConfig,
22
- RedirectToPreviewURLRouteHandlerConfig,
23
- RedirectToPreviewURLAPIEndpointConfig,
24
- } from "./redirectToPreviewURL";
15
+ export { PrismicNextImage } from "./PrismicNextImage.js";
16
+ export type { PrismicNextImageProps } from "./PrismicNextImage.js";
25
17
 
26
- export { createLocaleRedirect } from "./createLocaleRedirect";
27
- export type { CreateLocaleRedirectConfig } from "./createLocaleRedirect";
18
+ export { imgixLoader } from "./imgixLoader.js";
28
19
 
29
- export { PrismicNextImage } from "./PrismicNextImage";
30
- export type { PrismicNextImageProps } from "./PrismicNextImage";
20
+ export type { CreateClientConfig } from "./types.js";
31
21
 
32
- export { imgixLoader } from "./imgixLoader";
33
-
34
- export type { CreateClientConfig, PrismicPreviewData } from "./types";
22
+ export { createLocaleRedirect } from "./createLocaleRedirect.js";
23
+ export type { CreateLocaleRedirectConfig } from "./createLocaleRedirect.js";
package/src/lib/devMsg.ts CHANGED
@@ -7,7 +7,7 @@ import { version } from "../../package.json";
7
7
  *
8
8
  * ```ts
9
9
  * devMsg("missing-param");
10
- * // => "https://prismic.dev/msg/next/v1.2.3/missing-param.md"
10
+ * // => "https://prismic.dev/msg/next/v1.2.3/missing-param"
11
11
  * ```
12
12
  *
13
13
  * @param slug - Slug for the message. This corresponds to a Markdown file in
@@ -0,0 +1,145 @@
1
+ import { type ReactNode, useEffect, JSX } from "react";
2
+ import { useRouter } from "next/router";
3
+ import Script from "next/script";
4
+ import { getToolbarSrc, cookie as prismicCookie } from "@prismicio/client";
5
+
6
+ /** Props for `<PrismicPreview>`. */
7
+ export type PrismicPreviewProps = {
8
+ /**
9
+ * The name of your Prismic repository. A Prismic Toolbar will be registered
10
+ * using this repository.
11
+ */
12
+ repositoryName: string;
13
+
14
+ /**
15
+ * The URL of your app's Prismic preview endpoint (default: `/api/preview`).
16
+ * This URL will be fetched on preview update events.
17
+ */
18
+ updatePreviewURL?: string;
19
+
20
+ /**
21
+ * The URL of your app's exit preview endpoint (default: `/api/exit-preview`).
22
+ * This URL will be fetched on preview exit events.
23
+ */
24
+ exitPreviewURL?: string;
25
+
26
+ /** Children to render adjacent to the Prismic Toolbar. */
27
+ children?: ReactNode;
28
+ };
29
+
30
+ /**
31
+ * React component that sets up Prismic Previews using the Prismic Toolbar. When
32
+ * the Prismic Toolbar send events to the browser, such as on preview updates
33
+ * and exiting, this component will automatically refresh the page with the
34
+ * changes.
35
+ *
36
+ * This component can be wrapped around your app or added anywhere in your app's
37
+ * tree. It must be rendered on every page.
38
+ */
39
+ export function PrismicPreview(props: PrismicPreviewProps): JSX.Element {
40
+ const {
41
+ repositoryName,
42
+ updatePreviewURL = "/api/preview",
43
+ exitPreviewURL = "/api/exit-preview",
44
+ children,
45
+ } = props;
46
+
47
+ const router = useRouter();
48
+
49
+ const toolbarSrc = getToolbarSrc(repositoryName);
50
+
51
+ useEffect(() => {
52
+ const controller = new AbortController();
53
+
54
+ window.addEventListener("prismicPreviewUpdate", onUpdate, {
55
+ signal: controller.signal,
56
+ });
57
+ window.addEventListener("prismicPreviewEnd", onEnd, {
58
+ signal: controller.signal,
59
+ });
60
+
61
+ // Start the preview for preview share links. Previews from
62
+ // share links do not go to the `updatePreviewURL` like a normal
63
+ // preview.
64
+ //
65
+ // We check that the current URL is a descendant of the base
66
+ // path to prevent infinite refrehes.
67
+ if (
68
+ window.location.href.startsWith(
69
+ window.location.origin + router.basePath,
70
+ ) &&
71
+ getPreviewCookieRepositoryName() === repositoryName &&
72
+ !router.isPreview
73
+ ) {
74
+ start();
75
+ }
76
+
77
+ function onEnd(event: Event) {
78
+ event.preventDefault();
79
+ fetch(router.basePath + exitPreviewURL, { signal: controller.signal })
80
+ .then((res) => {
81
+ if (!res.ok) {
82
+ console.error(
83
+ `[<PrismicPreview>] Failed to exit Preview Mode using the "${exitPreviewURL}" API endpoint. Does it exist?`,
84
+ );
85
+
86
+ return;
87
+ }
88
+
89
+ refresh();
90
+ })
91
+ .catch(() => {});
92
+ }
93
+
94
+ function onUpdate(event: Event) {
95
+ event.preventDefault();
96
+ start();
97
+ }
98
+
99
+ function start() {
100
+ // We check `opaqueredirect` because we don't care if
101
+ // the redirect was successful or not. As long as it
102
+ // redirects, we know the endpoint exists and at least
103
+ // attempted to set preview data.
104
+ fetch(router.basePath + updatePreviewURL, {
105
+ redirect: "manual",
106
+ signal: controller.signal,
107
+ })
108
+ .then((res) => {
109
+ if (res.type !== "opaqueredirect") {
110
+ console.error(
111
+ `[<PrismicPreview>] Failed to start or update the preview using "${updatePreviewURL}". Does it exist?`,
112
+ );
113
+
114
+ return;
115
+ }
116
+
117
+ refresh();
118
+ })
119
+ .catch(() => {});
120
+ }
121
+
122
+ function refresh() {
123
+ router.replace(router.asPath, undefined, { scroll: false });
124
+ }
125
+
126
+ return () => controller.abort();
127
+ }, [exitPreviewURL, updatePreviewURL, repositoryName, router]);
128
+
129
+ return (
130
+ <>
131
+ {children}
132
+ <Script src={toolbarSrc} strategy="lazyOnload" />
133
+ </>
134
+ );
135
+ }
136
+
137
+ function getPreviewCookieRepositoryName() {
138
+ const cookie = window.document.cookie
139
+ .split("; ")
140
+ .find((row) => row.startsWith(`${prismicCookie.preview}=`))
141
+ ?.split("=")[1];
142
+
143
+ return (decodeURIComponent(cookie ?? "").match(/"([^"]+)\.prismic\.io"/) ||
144
+ [])[1];
145
+ }
@@ -0,0 +1,62 @@
1
+ import type { PreviewData } from "next";
2
+ import type { Client } from "@prismicio/client";
3
+
4
+ import type { NextApiRequestLike } from "./types.js";
5
+
6
+ /**
7
+ * Configuration for `enableAutoPreviews`.
8
+ *
9
+ * @typeParam TPreviewData - Next.js preview data object.
10
+ */
11
+ export type EnableAutoPreviewsConfig = {
12
+ /** Prismic client with which automatic previews will be enabled. */
13
+ // `Pick` is used to use the smallest possible subset of
14
+ // `prismic.Client`. Doing this reduces the surface area for breaking
15
+ // type changes.
16
+ client: Pick<Client, "queryContentFromRef" | "enableAutoPreviewsFromReq">;
17
+
18
+ /**
19
+ * The `previewData` object provided in the `getStaticProps()` or
20
+ * `getServerSideProps()` context object.
21
+ */
22
+ previewData?: PreviewData;
23
+
24
+ /**
25
+ * The `req` object from a Next.js API route.
26
+ *
27
+ * @see Next.js API route docs: \<https://nextjs.org/docs/api-routes/introduction\>
28
+ */
29
+ req?: NextApiRequestLike;
30
+ };
31
+
32
+ /**
33
+ * Configures a Prismic client to automatically query draft content during a
34
+ * preview session. It either takes in a Next.js `getStaticProps` context object
35
+ * or a Next.js API endpoint request object.
36
+ *
37
+ * @param config - Configuration for the function.
38
+ */
39
+ export function enableAutoPreviews(config: EnableAutoPreviewsConfig): void {
40
+ if ("previewData" in config && config.previewData) {
41
+ // Assume we are in `getStaticProps()` or
42
+ // `getServerSideProps()` with active Preview Mode.
43
+
44
+ if (isPrismicPreviewData(config.previewData)) {
45
+ config.client.queryContentFromRef(config.previewData.ref);
46
+ }
47
+
48
+ return;
49
+ }
50
+
51
+ if ("req" in config && config.req) {
52
+ // Assume we are in an API Route.
53
+
54
+ config.client.enableAutoPreviewsFromReq(config.req);
55
+
56
+ return;
57
+ }
58
+ }
59
+
60
+ function isPrismicPreviewData(input: unknown): input is { ref: string } {
61
+ return typeof input === "object" && input !== null && "ref" in input;
62
+ }
@@ -0,0 +1,45 @@
1
+ import type { NextApiRequestLike, NextApiResponseLike } from "./types.js";
2
+
3
+ /** Configuration for `exitPreview()`. */
4
+ export type ExitPreviewAPIRouteConfig = {
5
+ /**
6
+ * The `req` object from a Next.js API route.
7
+ *
8
+ * @see Next.js API route docs: \<https://nextjs.org/docs/api-routes/introduction\>
9
+ */
10
+ req?: NextApiRequestLike;
11
+
12
+ /**
13
+ * The `res` object from a Next.js API route.
14
+ *
15
+ * @see Next.js API route docs: \<https://nextjs.org/docs/api-routes/introduction\>
16
+ */
17
+ res: NextApiResponseLike;
18
+ };
19
+
20
+ /**
21
+ * Ends a Prismic preview session within a Next.js app. This function should be
22
+ * used in an API route.
23
+ *
24
+ * @example
25
+ *
26
+ * ```typescript
27
+ * // src/pages/api/exit-preview.js
28
+ *
29
+ * import { exitPreview } from "@prismicio/next";
30
+ *
31
+ * export default function handler(_req, res) {
32
+ * return exitPreview({ res });
33
+ * }
34
+ * ```
35
+ */
36
+ export function exitPreview(config: ExitPreviewAPIRouteConfig): void {
37
+ config.res.clearPreviewData();
38
+
39
+ // `Cache-Control` header is used to prevent CDN-level caching.
40
+ config.res.setHeader("Cache-Control", "no-store");
41
+
42
+ config.res.json({ success: true });
43
+
44
+ return;
45
+ }