next-sanity 12.4.0 → 12.4.2
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/PresentationComlink.js.map +1 -1
- package/dist/SanityLive.js +9 -9
- package/dist/SanityLive.js.map +1 -1
- package/dist/isCorsOriginError.js.map +1 -1
- package/dist/live/client-components/index.d.ts +6 -20
- package/dist/live/client-components/index.d.ts.map +1 -1
- package/dist/live/client-components/index.js +1 -1
- package/dist/live/client-components/index.js.map +1 -1
- package/dist/live/conditions/default/index.d.ts +83 -5
- package/dist/live/conditions/default/index.d.ts.map +1 -1
- package/dist/live/conditions/default/index.js +78 -0
- package/dist/live/conditions/default/index.js.map +1 -1
- package/dist/live/conditions/next-js/index.d.ts +83 -5
- package/dist/live/conditions/next-js/index.d.ts.map +1 -1
- package/dist/live/conditions/next-js/index.js +78 -0
- package/dist/live/conditions/next-js/index.js.map +1 -1
- package/dist/live/conditions/react-server/index.d.ts +88 -2
- package/dist/live/conditions/react-server/index.d.ts.map +1 -0
- package/dist/live/conditions/react-server/index.js +148 -68
- package/dist/live/conditions/react-server/index.js.map +1 -1
- package/dist/live/server-actions/index.d.ts +11 -0
- package/dist/live/server-actions/index.d.ts.map +1 -0
- package/dist/live/server-actions/{index.default.js → index.js} +7 -1
- package/dist/live/server-actions/index.js.map +1 -0
- package/dist/{defineLive.d.ts → types.d.ts} +39 -26
- package/dist/types.d.ts.map +1 -0
- package/dist/visual-editing/server-actions/index.d.ts +2 -2
- package/dist/visual-editing/server-actions/index.js +3 -3
- package/dist/visual-editing/server-actions/index.js.map +1 -1
- package/package.json +4 -6
- package/dist/defineLive.d.ts.map +0 -1
- package/dist/live/server-actions/index.default.d.ts +0 -5
- package/dist/live/server-actions/index.default.d.ts.map +0 -1
- package/dist/live/server-actions/index.default.js.map +0 -1
|
@@ -1,3 +1,89 @@
|
|
|
1
1
|
import { t as isCorsOriginError } from "../../../isCorsOriginError.js";
|
|
2
|
-
import { i as
|
|
3
|
-
|
|
2
|
+
import { i as LivePerspective, n as DefinedFetchType, r as DefinedLiveProps, t as DefineLiveOptions } from "../../../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Set up Sanity Live. `defineLive` returns `sanityFetch` and `<SanityLive />`,
|
|
5
|
+
* which connect your Sanity client to the Live Content API so pages can serve
|
|
6
|
+
* cached content and update in response to fine-grained content changes.
|
|
7
|
+
*
|
|
8
|
+
* @see [Live Content API](https://www.sanity.io/docs/content-lake/live-content-api)
|
|
9
|
+
* @see [Sanity Live](https://www.sanity.io/live)
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* import {createClient} from 'next-sanity'
|
|
14
|
+
* import {defineLive} from 'next-sanity/live'
|
|
15
|
+
*
|
|
16
|
+
* const client = createClient({
|
|
17
|
+
* projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
|
|
18
|
+
* dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
|
|
19
|
+
* useCdn: true,
|
|
20
|
+
* perspective: 'published',
|
|
21
|
+
* })
|
|
22
|
+
* const token = process.env.SANITY_API_READ_TOKEN
|
|
23
|
+
*
|
|
24
|
+
* export const {sanityFetch, SanityLive} = defineLive({
|
|
25
|
+
* client,
|
|
26
|
+
* browserToken: token,
|
|
27
|
+
* serverToken: token,
|
|
28
|
+
* })
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* // app/layout.tsx
|
|
34
|
+
* import {SanityLive} from '@/sanity/live'
|
|
35
|
+
*
|
|
36
|
+
* export default function RootLayout({children}: {children: React.ReactNode}) {
|
|
37
|
+
* return (
|
|
38
|
+
* <html lang="en">
|
|
39
|
+
* <body>
|
|
40
|
+
* {children}
|
|
41
|
+
* <SanityLive />
|
|
42
|
+
* </body>
|
|
43
|
+
* </html>
|
|
44
|
+
* )
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```tsx
|
|
50
|
+
* // app/[slug]/page.tsx
|
|
51
|
+
* import {defineQuery} from 'next-sanity'
|
|
52
|
+
* import {sanityFetch} from '@/sanity/live'
|
|
53
|
+
*
|
|
54
|
+
* const POSTS_SLUGS_QUERY = defineQuery(`
|
|
55
|
+
* *[_type == "post" && slug.current]{"slug": slug.current}
|
|
56
|
+
* `)
|
|
57
|
+
* const POST_QUERY = defineQuery(`
|
|
58
|
+
* *[_type == "post" && slug.current == $slug][0]
|
|
59
|
+
* `)
|
|
60
|
+
*
|
|
61
|
+
* export async function generateStaticParams() {
|
|
62
|
+
* const {data} = await sanityFetch({
|
|
63
|
+
* query: POSTS_SLUGS_QUERY,
|
|
64
|
+
* perspective: 'published',
|
|
65
|
+
* stega: false,
|
|
66
|
+
* })
|
|
67
|
+
*
|
|
68
|
+
* return data
|
|
69
|
+
* }
|
|
70
|
+
*
|
|
71
|
+
* export default async function Page(props: PageProps<'/[slug]'>) {
|
|
72
|
+
* const {slug} = await props.params
|
|
73
|
+
* const {data} = await sanityFetch({
|
|
74
|
+
* query: POST_QUERY,
|
|
75
|
+
* params: {slug},
|
|
76
|
+
* })
|
|
77
|
+
*
|
|
78
|
+
* return <pre>{JSON.stringify(data, null, 2)}</pre>
|
|
79
|
+
* }
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* @public
|
|
83
|
+
*/
|
|
84
|
+
declare function defineLive(config: DefineLiveOptions): {
|
|
85
|
+
sanityFetch: DefinedFetchType;
|
|
86
|
+
SanityLive: React.ComponentType<DefinedLiveProps>;
|
|
87
|
+
};
|
|
88
|
+
export { type DefineLiveOptions as DefineSanityLiveOptions, type DefinedFetchType as DefinedSanityFetchType, type DefinedLiveProps as DefinedSanityLiveProps, type LivePerspective, defineLive, isCorsOriginError };
|
|
89
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../../src/live/conditions/react-server/defineLive.tsx"],"mappings":";;;;AA2FA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAgB,UAAA,CAAW,MAAA,EAAQ,iBAAA;EACjC,WAAA,EAAa,gBAAA;EACb,UAAA,EAAY,KAAA,CAAM,aAAA,CAAc,gBAAA;AAAA"}
|
|
@@ -3,11 +3,88 @@ import { t as sanitizePerspective } from "../../../sanitizePerspective.js";
|
|
|
3
3
|
import { perspectiveCookieName } from "@sanity/preview-url-secret/constants";
|
|
4
4
|
import { cookies, draftMode } from "next/headers";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
|
-
import "@sanity/client";
|
|
7
6
|
import { SanityLive } from "next-sanity/live/client-components";
|
|
8
7
|
import { PHASE_PRODUCTION_BUILD } from "next/constants";
|
|
9
8
|
import { preconnect } from "react-dom";
|
|
10
9
|
/**
|
|
10
|
+
* Set up Sanity Live. `defineLive` returns `sanityFetch` and `<SanityLive />`,
|
|
11
|
+
* which connect your Sanity client to the Live Content API so pages can serve
|
|
12
|
+
* cached content and update in response to fine-grained content changes.
|
|
13
|
+
*
|
|
14
|
+
* @see [Live Content API](https://www.sanity.io/docs/content-lake/live-content-api)
|
|
15
|
+
* @see [Sanity Live](https://www.sanity.io/live)
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* import {createClient} from 'next-sanity'
|
|
20
|
+
* import {defineLive} from 'next-sanity/live'
|
|
21
|
+
*
|
|
22
|
+
* const client = createClient({
|
|
23
|
+
* projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
|
|
24
|
+
* dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
|
|
25
|
+
* useCdn: true,
|
|
26
|
+
* perspective: 'published',
|
|
27
|
+
* })
|
|
28
|
+
* const token = process.env.SANITY_API_READ_TOKEN
|
|
29
|
+
*
|
|
30
|
+
* export const {sanityFetch, SanityLive} = defineLive({
|
|
31
|
+
* client,
|
|
32
|
+
* browserToken: token,
|
|
33
|
+
* serverToken: token,
|
|
34
|
+
* })
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* // app/layout.tsx
|
|
40
|
+
* import {SanityLive} from '@/sanity/live'
|
|
41
|
+
*
|
|
42
|
+
* export default function RootLayout({children}: {children: React.ReactNode}) {
|
|
43
|
+
* return (
|
|
44
|
+
* <html lang="en">
|
|
45
|
+
* <body>
|
|
46
|
+
* {children}
|
|
47
|
+
* <SanityLive />
|
|
48
|
+
* </body>
|
|
49
|
+
* </html>
|
|
50
|
+
* )
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```tsx
|
|
56
|
+
* // app/[slug]/page.tsx
|
|
57
|
+
* import {defineQuery} from 'next-sanity'
|
|
58
|
+
* import {sanityFetch} from '@/sanity/live'
|
|
59
|
+
*
|
|
60
|
+
* const POSTS_SLUGS_QUERY = defineQuery(`
|
|
61
|
+
* *[_type == "post" && slug.current]{"slug": slug.current}
|
|
62
|
+
* `)
|
|
63
|
+
* const POST_QUERY = defineQuery(`
|
|
64
|
+
* *[_type == "post" && slug.current == $slug][0]
|
|
65
|
+
* `)
|
|
66
|
+
*
|
|
67
|
+
* export async function generateStaticParams() {
|
|
68
|
+
* const {data} = await sanityFetch({
|
|
69
|
+
* query: POSTS_SLUGS_QUERY,
|
|
70
|
+
* perspective: 'published',
|
|
71
|
+
* stega: false,
|
|
72
|
+
* })
|
|
73
|
+
*
|
|
74
|
+
* return data
|
|
75
|
+
* }
|
|
76
|
+
*
|
|
77
|
+
* export default async function Page(props: PageProps<'/[slug]'>) {
|
|
78
|
+
* const {slug} = await props.params
|
|
79
|
+
* const {data} = await sanityFetch({
|
|
80
|
+
* query: POST_QUERY,
|
|
81
|
+
* params: {slug},
|
|
82
|
+
* })
|
|
83
|
+
*
|
|
84
|
+
* return <pre>{JSON.stringify(data, null, 2)}</pre>
|
|
85
|
+
* }
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
11
88
|
* @public
|
|
12
89
|
*/
|
|
13
90
|
function defineLive(config) {
|
|
@@ -21,74 +98,77 @@ function defineLive(config) {
|
|
|
21
98
|
});
|
|
22
99
|
const { token: originalToken } = client.config();
|
|
23
100
|
const studioUrlDefined = typeof client.config().stega.studioUrl !== "undefined";
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
revalidate,
|
|
53
|
-
tags: cacheTags
|
|
54
|
-
},
|
|
55
|
-
useCdn,
|
|
56
|
-
cacheMode,
|
|
57
|
-
tag: requestTag
|
|
58
|
-
});
|
|
59
|
-
return {
|
|
60
|
-
data: result,
|
|
61
|
-
sourceMap: resultSourceMap || null,
|
|
101
|
+
const sanityFetch = async function sanityFetch({ query, params = {}, stega: _stega, tags = [], perspective: _perspective, tag, requestTag = tag ?? "next-loader.fetch" }) {
|
|
102
|
+
const stega = _stega ?? (stegaEnabled && studioUrlDefined && (await draftMode()).isEnabled);
|
|
103
|
+
const perspective = _perspective ?? await resolveCookiePerspective();
|
|
104
|
+
const useCdn = perspective === "published";
|
|
105
|
+
const revalidate = fetchOptions?.revalidate !== void 0 ? fetchOptions.revalidate : process.env.NODE_ENV === "production" ? false : void 0;
|
|
106
|
+
const isBuildPhase = process.env["NEXT_PHASE"] === PHASE_PRODUCTION_BUILD;
|
|
107
|
+
const cacheMode = useCdn && !isBuildPhase ? "noStale" : void 0;
|
|
108
|
+
const { syncTags } = await client.fetch(query, await params, {
|
|
109
|
+
filterResponse: false,
|
|
110
|
+
perspective,
|
|
111
|
+
stega: false,
|
|
112
|
+
returnQuery: false,
|
|
113
|
+
next: {
|
|
114
|
+
revalidate,
|
|
115
|
+
tags: [...tags, "sanity:fetch-sync-tags"]
|
|
116
|
+
},
|
|
117
|
+
useCdn,
|
|
118
|
+
cacheMode,
|
|
119
|
+
tag: [requestTag, "fetch-sync-tags"].filter(Boolean).join(".")
|
|
120
|
+
});
|
|
121
|
+
const cacheTags = [...tags, ...syncTags?.map((tag) => `sanity:${tag}`) || []];
|
|
122
|
+
const { result, resultSourceMap } = await client.fetch(query, await params, {
|
|
123
|
+
filterResponse: false,
|
|
124
|
+
perspective,
|
|
125
|
+
stega,
|
|
126
|
+
token: perspective !== "published" && serverToken ? serverToken : originalToken,
|
|
127
|
+
next: {
|
|
128
|
+
revalidate,
|
|
62
129
|
tags: cacheTags
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
130
|
+
},
|
|
131
|
+
useCdn,
|
|
132
|
+
cacheMode,
|
|
133
|
+
tag: requestTag
|
|
134
|
+
});
|
|
135
|
+
return {
|
|
136
|
+
data: result,
|
|
137
|
+
sourceMap: resultSourceMap || null,
|
|
138
|
+
tags: cacheTags
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
const SanityLive$2 = async function SanityLive$1(props) {
|
|
142
|
+
const { refreshOnMount, refreshOnFocus, refreshOnReconnect, tag, requestTag = tag, onError, onGoAway, intervalOnGoAway, revalidateSyncTags, waitFor } = props;
|
|
143
|
+
const { projectId, dataset, apiHost, apiVersion, useProjectHostname, requestTagPrefix } = client.config();
|
|
144
|
+
const { isEnabled: isDraftModeEnabled } = await draftMode();
|
|
145
|
+
const { origin } = new URL(client.getUrl("", false));
|
|
146
|
+
preconnect(origin);
|
|
147
|
+
return /* @__PURE__ */ jsx(SanityLive, {
|
|
148
|
+
projectId,
|
|
149
|
+
dataset,
|
|
150
|
+
apiHost,
|
|
151
|
+
apiVersion,
|
|
152
|
+
useProjectHostname,
|
|
153
|
+
requestTagPrefix,
|
|
154
|
+
requestTag,
|
|
155
|
+
token: typeof browserToken === "string" && isDraftModeEnabled ? browserToken : void 0,
|
|
156
|
+
draftModeEnabled: isDraftModeEnabled,
|
|
157
|
+
draftModePerspective: await resolveCookiePerspective(),
|
|
158
|
+
refreshOnMount,
|
|
159
|
+
refreshOnFocus,
|
|
160
|
+
refreshOnReconnect,
|
|
161
|
+
onError,
|
|
162
|
+
onGoAway,
|
|
163
|
+
intervalOnGoAway,
|
|
164
|
+
revalidateSyncTags,
|
|
165
|
+
waitFor
|
|
166
|
+
});
|
|
167
|
+
};
|
|
168
|
+
SanityLive$2.displayName = "SanityLiveServerComponent";
|
|
169
|
+
return {
|
|
170
|
+
sanityFetch,
|
|
171
|
+
SanityLive: SanityLive$2
|
|
92
172
|
};
|
|
93
173
|
}
|
|
94
174
|
async function resolveCookiePerspective() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["SanityLive","SanityLiveClientComponent"],"sources":["../../../../src/live/conditions/react-server/defineLive.tsx"],"sourcesContent":["import {\n type ClientPerspective,\n type ClientReturn,\n type ContentSourceMap,\n type LiveEventGoAway,\n type QueryParams,\n type SanityClient,\n type SyncTag,\n} from '@sanity/client'\nimport {perspectiveCookieName} from '@sanity/preview-url-secret/constants'\nimport {SanityLive as SanityLiveClientComponent} from 'next-sanity/live/client-components'\nimport {PHASE_PRODUCTION_BUILD} from 'next/constants'\nimport {draftMode, cookies} from 'next/headers'\nimport {preconnect} from 'react-dom'\n\nimport {sanitizePerspective} from '#live/sanitizePerspective'\n\n/**\n * @public\n */\nexport type DefinedSanityFetchType = <const QueryString extends string>(options: {\n query: QueryString\n params?: QueryParams | Promise<QueryParams>\n /**\n * Add custom `next.tags` to the underlying fetch request.\n * @see https://nextjs.org/docs/app/api-reference/functions/fetch#optionsnexttags\n * This can be used in conjunction with custom fallback revalidation strategies, as well as with custom Server Actions that mutate data and want to render with fresh data right away (faster than the Live Event latency).\n * @defaultValue `['sanity']`\n */\n tags?: string[]\n perspective?: Exclude<ClientPerspective, 'raw'>\n stega?: boolean\n /**\n * @deprecated use `requestTag` instead\n */\n tag?: never\n /**\n * This request tag is used to identify the request when viewing request logs from your Sanity Content Lake.\n * @see https://www.sanity.io/docs/reference-api-request-tags\n * @defaultValue 'next-loader.fetch'\n */\n requestTag?: string\n}) => Promise<{\n data: ClientReturn<QueryString>\n sourceMap: ContentSourceMap | null\n tags: string[]\n}>\n\n/**\n * @public\n */\nexport interface DefinedSanityLiveProps {\n /**\n * Automatic refresh of RSC when the component <SanityLive /> is mounted.\n * Note that this is different from revalidation, which is based on tags and causes `sanityFetch` calls to be re-fetched.\n * @defaultValue `true`\n */\n refreshOnMount?: boolean\n /**\n * Automatically refresh when window gets focused\n * Note that this is different from revalidation, which is based on tags and causes `sanityFetch` calls to be re-fetched.\n * @defaultValue `false` if draftMode().isEnabled, otherwise `true` if not inside an iframe\n */\n refreshOnFocus?: boolean\n /**\n * Automatically refresh when the browser regains a network connection (via navigator.onLine)\n * Note that this is different from revalidation, which is based on tags and causes `sanityFetch` calls to be re-fetched.\n * @defaultValue `true`\n */\n refreshOnReconnect?: boolean\n /**\n * Automatically refresh on an interval when the Live Event API emits a `goaway` event, which indicates that the connection is rejected or closed.\n * This typically happens if the connection limit is reached, or if the connection is idle for too long.\n * To disable this long polling fallback behavior set `intervalOnGoAway` to `false` or `0`.\n * You can also use `onGoAway` to handle the `goaway` event in your own way, and read the reason why the event was emitted.\n * @defaultValue `30_000` 30 seconds interval\n */\n intervalOnGoAway?: number | false\n\n /**\n * Delays events until after a Sanity Function has processed them and called the callback endpoint.\n * When omitted, events are delivered immediately.\n */\n waitFor?: 'function'\n\n /**\n * @deprecated use `requestTag` instead\n */\n tag?: never\n\n /**\n * This request tag is used to identify the request when viewing request logs from your Sanity Content Lake.\n * @see https://www.sanity.io/docs/reference-api-request-tags\n * @defaultValue 'next-loader.live'\n */\n requestTag?: string\n\n /**\n * Handle errors from the Live Events subscription.\n * By default it's reported using `console.error`, you can override this prop to handle it in your own way.\n */\n onError?: (error: unknown) => void\n\n /**\n * Handle the `goaway` event if the connection is rejected/closed.\n * `event.reason` will be a string of why the event was emitted, for example `'connection limit reached'`.\n * When this happens the `<SanityLive />` will fallback to long polling with a default interval of 30 seconds, providing your own `onGoAway` handler does not change this behavior.\n * If you want to disable long polling set `intervalOnGoAway` to `false` or `0`.\n */\n onGoAway?: (event: LiveEventGoAway, intervalOnGoAway: number | false) => void\n\n /**\n * Override how cache tags are invalidated, you need to pass a server action here.\n * You can also pass a `use client` function here, and have `router.refresh()` be called if the promise resolves to `'refresh'`.\n */\n revalidateSyncTags?: (tags: SyncTag[]) => Promise<void | 'refresh'>\n}\n\n/**\n * @public\n */\nexport interface DefineSanityLiveOptions {\n /**\n * Required for `sanityFetch` and `SanityLive` to work\n */\n client: SanityClient\n /**\n * Optional. If provided then the token needs to have permissions to query documents with `drafts.` prefixes in order for `perspective: 'drafts'` to work.\n * This token is not shared with the browser.\n */\n serverToken?: string | false\n /**\n * Optional. This token is shared with the browser, and should only have access to query published documents.\n * It is used to setup a `Live Draft Content` EventSource connection, and enables live previewing drafts stand-alone, outside of Presentation Tool.\n */\n browserToken?: string | false\n /**\n * Fetch options used by `sanityFetch`\n * @deprecated this option is removed in the next major version, use `export const revalidate` on the `page.tsx` or `layout.tsx` instead\n */\n fetchOptions?: {\n /**\n * Optional, enables time based revalidation in addition to the EventSource connection.\n * @defaultValue `false`\n */\n revalidate?: number | false\n }\n /**\n * Optional. Include stega encoding when draft mode is enabled.\n * @defaultValue `true`\n */\n stega?: boolean\n}\n\n/**\n * @public\n */\nexport function defineLive(config: DefineSanityLiveOptions): {\n /**\n * Use this function to fetch data from Sanity in your React Server Components.\n * @public\n */\n sanityFetch: DefinedSanityFetchType\n /**\n * Render this in your root layout.tsx to make your page revalidate on new content live, automatically.\n * @public\n */\n SanityLive: React.ComponentType<DefinedSanityLiveProps>\n} {\n const {\n client: _client,\n serverToken,\n browserToken,\n fetchOptions,\n stega: stegaEnabled = true,\n } = config\n\n if (!_client) {\n throw new Error('`client` is required for `defineLive` to function')\n }\n\n if (process.env.NODE_ENV !== 'production' && !serverToken && serverToken !== false) {\n console.warn(\n 'No `serverToken` provided to `defineLive`. This means that only published content will be fetched and respond to live events. You can silence this warning by setting `serverToken: false`.',\n )\n }\n\n if (process.env.NODE_ENV !== 'production' && !browserToken && browserToken !== false) {\n console.warn(\n 'No `browserToken` provided to `defineLive`. This means that live previewing drafts will only work when using the Presentation Tool in your Sanity Studio. To support live previewing drafts stand-alone, provide a `browserToken`. It is shared with the browser so it should only have Viewer rights or lower. You can silence this warning by setting `browserToken: false`.',\n )\n }\n\n const client = _client.withConfig({allowReconfigure: false, useCdn: false})\n const {token: originalToken} = client.config()\n const studioUrlDefined = typeof client.config().stega.studioUrl !== 'undefined'\n\n const sanityFetch: DefinedSanityFetchType = async function sanityFetch<\n const QueryString extends string,\n >({\n query,\n params = {},\n stega: _stega,\n tags = [],\n perspective: _perspective,\n tag,\n requestTag = tag ?? 'next-loader.fetch',\n }: {\n query: QueryString\n params?: QueryParams | Promise<QueryParams>\n stega?: boolean\n tags?: string[]\n perspective?: Exclude<ClientPerspective, 'raw'>\n tag?: string\n requestTag?: string\n }) {\n const stega = _stega ?? (stegaEnabled && studioUrlDefined && (await draftMode()).isEnabled)\n const perspective = _perspective ?? (await resolveCookiePerspective())\n const useCdn = perspective === 'published'\n const revalidate =\n fetchOptions?.revalidate !== undefined\n ? fetchOptions.revalidate\n : process.env.NODE_ENV === 'production'\n ? false\n : undefined\n const isBuildPhase = process.env['NEXT_PHASE'] === PHASE_PRODUCTION_BUILD\n const cacheMode = useCdn && !isBuildPhase ? 'noStale' : undefined\n\n const {syncTags} = await client.fetch(query, await params, {\n filterResponse: false,\n perspective: perspective as ClientPerspective,\n stega: false,\n returnQuery: false,\n next: {revalidate, tags: [...tags, 'sanity:fetch-sync-tags']},\n useCdn,\n cacheMode,\n tag: [requestTag, 'fetch-sync-tags'].filter(Boolean).join('.'),\n })\n\n const cacheTags = [...tags, ...(syncTags?.map((tag) => `sanity:${tag}`) || [])]\n\n const {result, resultSourceMap} = await client.fetch(query, await params, {\n filterResponse: false,\n perspective: perspective as ClientPerspective,\n stega,\n token: perspective !== 'published' && serverToken ? serverToken : originalToken,\n next: {revalidate, tags: cacheTags},\n useCdn,\n cacheMode,\n tag: requestTag,\n })\n return {data: result, sourceMap: resultSourceMap || null, tags: cacheTags}\n }\n\n const SanityLive: React.ComponentType<DefinedSanityLiveProps> = async function SanityLive(props) {\n const {\n refreshOnMount,\n refreshOnFocus,\n refreshOnReconnect,\n tag,\n requestTag = tag,\n onError,\n onGoAway,\n intervalOnGoAway,\n revalidateSyncTags,\n waitFor,\n } = props\n const {projectId, dataset, apiHost, apiVersion, useProjectHostname, requestTagPrefix} =\n client.config()\n const {isEnabled: isDraftModeEnabled} = await draftMode()\n\n // Preconnect to the Live Event API origin early, as the Sanity API is almost always on a different origin than the app\n const {origin} = new URL(client.getUrl('', false))\n preconnect(origin)\n\n return (\n <SanityLiveClientComponent\n projectId={projectId}\n dataset={dataset}\n apiHost={apiHost}\n apiVersion={apiVersion}\n useProjectHostname={useProjectHostname}\n requestTagPrefix={requestTagPrefix}\n requestTag={requestTag}\n token={typeof browserToken === 'string' && isDraftModeEnabled ? browserToken : undefined}\n draftModeEnabled={isDraftModeEnabled}\n draftModePerspective={await resolveCookiePerspective()}\n refreshOnMount={refreshOnMount}\n refreshOnFocus={refreshOnFocus}\n refreshOnReconnect={refreshOnReconnect}\n onError={onError}\n onGoAway={onGoAway}\n intervalOnGoAway={intervalOnGoAway}\n revalidateSyncTags={revalidateSyncTags}\n waitFor={waitFor}\n />\n )\n }\n\n return {\n sanityFetch,\n SanityLive,\n }\n}\n\nasync function resolveCookiePerspective(): Promise<Exclude<ClientPerspective, 'raw'>> {\n return (await draftMode()).isEnabled\n ? (await cookies()).has(perspectiveCookieName)\n ? sanitizePerspective((await cookies()).get(perspectiveCookieName)?.value, 'drafts')\n : 'drafts'\n : 'published'\n}\n"],"mappings":";;;;;;;;;;;;AA6JA,SAAgB,WAAW,QAWzB;CACA,MAAM,EACJ,QAAQ,SACR,aACA,cACA,cACA,OAAO,eAAe,SACpB;AAEJ,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,oDAAoD;AAGtE,KAAI,QAAQ,IAAI,aAAa,gBAAgB,CAAC,eAAe,gBAAgB,MAC3E,SAAQ,KACN,8LACD;AAGH,KAAI,QAAQ,IAAI,aAAa,gBAAgB,CAAC,gBAAgB,iBAAiB,MAC7E,SAAQ,KACN,iXACD;CAGH,MAAM,SAAS,QAAQ,WAAW;EAAC,kBAAkB;EAAO,QAAQ;EAAM,CAAC;CAC3E,MAAM,EAAC,OAAO,kBAAiB,OAAO,QAAQ;CAC9C,MAAM,mBAAmB,OAAO,OAAO,QAAQ,CAAC,MAAM,cAAc;AAwGpE,QAAO;EACL,aAAA,eAvGyD,YAEzD,EACA,OACA,SAAS,EAAE,EACX,OAAO,QACP,OAAO,EAAE,EACT,aAAa,cACb,KACA,aAAa,OAAO,uBASnB;GACD,MAAM,QAAQ,WAAW,gBAAgB,qBAAqB,MAAM,WAAW,EAAE;GACjF,MAAM,cAAc,gBAAiB,MAAM,0BAA0B;GACrE,MAAM,SAAS,gBAAgB;GAC/B,MAAM,aACJ,cAAc,eAAe,KAAA,IACzB,aAAa,aACb,QAAQ,IAAI,aAAa,eACvB,QACA,KAAA;GACR,MAAM,eAAe,QAAQ,IAAI,kBAAkB;GACnD,MAAM,YAAY,UAAU,CAAC,eAAe,YAAY,KAAA;GAExD,MAAM,EAAC,aAAY,MAAM,OAAO,MAAM,OAAO,MAAM,QAAQ;IACzD,gBAAgB;IACH;IACb,OAAO;IACP,aAAa;IACb,MAAM;KAAC;KAAY,MAAM,CAAC,GAAG,MAAM,yBAAyB;KAAC;IAC7D;IACA;IACA,KAAK,CAAC,YAAY,kBAAkB,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI;IAC/D,CAAC;GAEF,MAAM,YAAY,CAAC,GAAG,MAAM,GAAI,UAAU,KAAK,QAAQ,UAAU,MAAM,IAAI,EAAE,CAAE;GAE/E,MAAM,EAAC,QAAQ,oBAAmB,MAAM,OAAO,MAAM,OAAO,MAAM,QAAQ;IACxE,gBAAgB;IACH;IACb;IACA,OAAO,gBAAgB,eAAe,cAAc,cAAc;IAClE,MAAM;KAAC;KAAY,MAAM;KAAU;IACnC;IACA;IACA,KAAK;IACN,CAAC;AACF,UAAO;IAAC,MAAM;IAAQ,WAAW,mBAAmB;IAAM,MAAM;IAAU;;EAkD1E,YAAA,eA/C6EA,aAAW,OAAO;GAC/F,MAAM,EACJ,gBACA,gBACA,oBACA,KACA,aAAa,KACb,SACA,UACA,kBACA,oBACA,YACE;GACJ,MAAM,EAAC,WAAW,SAAS,SAAS,YAAY,oBAAoB,qBAClE,OAAO,QAAQ;GACjB,MAAM,EAAC,WAAW,uBAAsB,MAAM,WAAW;GAGzD,MAAM,EAAC,WAAU,IAAI,IAAI,OAAO,OAAO,IAAI,MAAM,CAAC;AAClD,cAAW,OAAO;AAElB,UACE,oBAACC,YAAD;IACa;IACF;IACA;IACG;IACQ;IACF;IACN;IACZ,OAAO,OAAO,iBAAiB,YAAY,qBAAqB,eAAe,KAAA;IAC/E,kBAAkB;IAClB,sBAAsB,MAAM,0BAA0B;IACtC;IACA;IACI;IACX;IACC;IACQ;IACE;IACX;IACT,CAAA;;EAOL;;AAGH,eAAe,2BAAuE;AACpF,SAAQ,MAAM,WAAW,EAAE,aACtB,MAAM,SAAS,EAAE,IAAI,sBAAsB,GAC1C,qBAAqB,MAAM,SAAS,EAAE,IAAI,sBAAsB,EAAE,OAAO,SAAS,GAClF,WACF"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["SanityLive","SanityLiveClientComponent"],"sources":["../../../../src/live/conditions/react-server/defineLive.tsx"],"sourcesContent":["import type {ClientPerspective, QueryParams} from '@sanity/client'\nimport {perspectiveCookieName} from '@sanity/preview-url-secret/constants'\nimport {SanityLive as SanityLiveClientComponent} from 'next-sanity/live/client-components'\nimport {PHASE_PRODUCTION_BUILD} from 'next/constants'\nimport {cookies, draftMode} from 'next/headers'\nimport {preconnect} from 'react-dom'\n\nimport {sanitizePerspective} from '#live/sanitizePerspective'\nimport type {DefinedFetchType, DefinedLiveProps, DefineLiveOptions} from '#live/types'\n\n/**\n * Set up Sanity Live. `defineLive` returns `sanityFetch` and `<SanityLive />`,\n * which connect your Sanity client to the Live Content API so pages can serve\n * cached content and update in response to fine-grained content changes.\n *\n * @see [Live Content API](https://www.sanity.io/docs/content-lake/live-content-api)\n * @see [Sanity Live](https://www.sanity.io/live)\n *\n * @example\n * ```tsx\n * import {createClient} from 'next-sanity'\n * import {defineLive} from 'next-sanity/live'\n *\n * const client = createClient({\n * projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,\n * dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,\n * useCdn: true,\n * perspective: 'published',\n * })\n * const token = process.env.SANITY_API_READ_TOKEN\n *\n * export const {sanityFetch, SanityLive} = defineLive({\n * client,\n * browserToken: token,\n * serverToken: token,\n * })\n * ```\n *\n * @example\n * ```tsx\n * // app/layout.tsx\n * import {SanityLive} from '@/sanity/live'\n *\n * export default function RootLayout({children}: {children: React.ReactNode}) {\n * return (\n * <html lang=\"en\">\n * <body>\n * {children}\n * <SanityLive />\n * </body>\n * </html>\n * )\n * }\n * ```\n *\n * @example\n * ```tsx\n * // app/[slug]/page.tsx\n * import {defineQuery} from 'next-sanity'\n * import {sanityFetch} from '@/sanity/live'\n *\n * const POSTS_SLUGS_QUERY = defineQuery(`\n * *[_type == \"post\" && slug.current]{\"slug\": slug.current}\n * `)\n * const POST_QUERY = defineQuery(`\n * *[_type == \"post\" && slug.current == $slug][0]\n * `)\n *\n * export async function generateStaticParams() {\n * const {data} = await sanityFetch({\n * query: POSTS_SLUGS_QUERY,\n * perspective: 'published',\n * stega: false,\n * })\n *\n * return data\n * }\n *\n * export default async function Page(props: PageProps<'/[slug]'>) {\n * const {slug} = await props.params\n * const {data} = await sanityFetch({\n * query: POST_QUERY,\n * params: {slug},\n * })\n *\n * return <pre>{JSON.stringify(data, null, 2)}</pre>\n * }\n * ```\n *\n * @public\n */\nexport function defineLive(config: DefineLiveOptions): {\n sanityFetch: DefinedFetchType\n SanityLive: React.ComponentType<DefinedLiveProps>\n} {\n const {\n client: _client,\n serverToken,\n browserToken,\n fetchOptions,\n stega: stegaEnabled = true,\n } = config\n\n if (!_client) {\n throw new Error('`client` is required for `defineLive` to function')\n }\n\n if (process.env.NODE_ENV !== 'production' && !serverToken && serverToken !== false) {\n console.warn(\n 'No `serverToken` provided to `defineLive`. This means that only published content will be fetched and respond to live events. You can silence this warning by setting `serverToken: false`.',\n )\n }\n\n if (process.env.NODE_ENV !== 'production' && !browserToken && browserToken !== false) {\n console.warn(\n 'No `browserToken` provided to `defineLive`. This means that live previewing drafts will only work when using the Presentation Tool in your Sanity Studio. To support live previewing drafts stand-alone, provide a `browserToken`. It is shared with the browser so it should only have Viewer rights or lower. You can silence this warning by setting `browserToken: false`.',\n )\n }\n\n const client = _client.withConfig({allowReconfigure: false, useCdn: false})\n const {token: originalToken} = client.config()\n const studioUrlDefined = typeof client.config().stega.studioUrl !== 'undefined'\n\n const sanityFetch: DefinedFetchType = async function sanityFetch<\n const QueryString extends string,\n >({\n query,\n params = {},\n stega: _stega,\n tags = [],\n perspective: _perspective,\n tag,\n requestTag = tag ?? 'next-loader.fetch',\n }: {\n query: QueryString\n params?: QueryParams | Promise<QueryParams>\n stega?: boolean\n tags?: string[]\n perspective?: Exclude<ClientPerspective, 'raw'>\n tag?: string\n requestTag?: string\n }) {\n const stega = _stega ?? (stegaEnabled && studioUrlDefined && (await draftMode()).isEnabled)\n const perspective = _perspective ?? (await resolveCookiePerspective())\n const useCdn = perspective === 'published'\n const revalidate =\n fetchOptions?.revalidate !== undefined\n ? fetchOptions.revalidate\n : process.env.NODE_ENV === 'production'\n ? false\n : undefined\n const isBuildPhase = process.env['NEXT_PHASE'] === PHASE_PRODUCTION_BUILD\n const cacheMode = useCdn && !isBuildPhase ? 'noStale' : undefined\n\n const {syncTags} = await client.fetch(query, await params, {\n filterResponse: false,\n perspective: perspective as ClientPerspective,\n stega: false,\n returnQuery: false,\n next: {revalidate, tags: [...tags, 'sanity:fetch-sync-tags']},\n useCdn,\n cacheMode,\n tag: [requestTag, 'fetch-sync-tags'].filter(Boolean).join('.'),\n })\n\n const cacheTags = [...tags, ...(syncTags?.map((tag) => `sanity:${tag}`) || [])]\n\n const {result, resultSourceMap} = await client.fetch(query, await params, {\n filterResponse: false,\n perspective: perspective as ClientPerspective,\n stega,\n token: perspective !== 'published' && serverToken ? serverToken : originalToken,\n next: {revalidate, tags: cacheTags},\n useCdn,\n cacheMode,\n tag: requestTag,\n })\n return {data: result, sourceMap: resultSourceMap || null, tags: cacheTags}\n }\n\n const SanityLive: React.ComponentType<DefinedLiveProps> = async function SanityLive(props) {\n const {\n refreshOnMount,\n refreshOnFocus,\n refreshOnReconnect,\n tag,\n requestTag = tag,\n onError,\n onGoAway,\n intervalOnGoAway,\n revalidateSyncTags,\n waitFor,\n } = props\n const {projectId, dataset, apiHost, apiVersion, useProjectHostname, requestTagPrefix} =\n client.config()\n const {isEnabled: isDraftModeEnabled} = await draftMode()\n\n // Preconnect to the Live Event API origin early, as the Sanity API is almost always on a different origin than the app\n const {origin} = new URL(client.getUrl('', false))\n preconnect(origin)\n\n return (\n <SanityLiveClientComponent\n projectId={projectId}\n dataset={dataset}\n apiHost={apiHost}\n apiVersion={apiVersion}\n useProjectHostname={useProjectHostname}\n requestTagPrefix={requestTagPrefix}\n requestTag={requestTag}\n token={typeof browserToken === 'string' && isDraftModeEnabled ? browserToken : undefined}\n draftModeEnabled={isDraftModeEnabled}\n draftModePerspective={await resolveCookiePerspective()}\n refreshOnMount={refreshOnMount}\n refreshOnFocus={refreshOnFocus}\n refreshOnReconnect={refreshOnReconnect}\n onError={onError}\n onGoAway={onGoAway}\n intervalOnGoAway={intervalOnGoAway}\n revalidateSyncTags={revalidateSyncTags}\n waitFor={waitFor}\n />\n )\n }\n SanityLive.displayName = 'SanityLiveServerComponent'\n\n return {sanityFetch, SanityLive}\n}\n\nasync function resolveCookiePerspective(): Promise<Exclude<ClientPerspective, 'raw'>> {\n return (await draftMode()).isEnabled\n ? (await cookies()).has(perspectiveCookieName)\n ? sanitizePerspective((await cookies()).get(perspectiveCookieName)?.value, 'drafts')\n : 'drafts'\n : 'published'\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2FA,SAAgB,WAAW,QAGzB;CACA,MAAM,EACJ,QAAQ,SACR,aACA,cACA,cACA,OAAO,eAAe,SACpB;AAEJ,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,oDAAoD;AAGtE,KAAI,QAAQ,IAAI,aAAa,gBAAgB,CAAC,eAAe,gBAAgB,MAC3E,SAAQ,KACN,8LACD;AAGH,KAAI,QAAQ,IAAI,aAAa,gBAAgB,CAAC,gBAAgB,iBAAiB,MAC7E,SAAQ,KACN,iXACD;CAGH,MAAM,SAAS,QAAQ,WAAW;EAAC,kBAAkB;EAAO,QAAQ;EAAM,CAAC;CAC3E,MAAM,EAAC,OAAO,kBAAiB,OAAO,QAAQ;CAC9C,MAAM,mBAAmB,OAAO,OAAO,QAAQ,CAAC,MAAM,cAAc;CAEpE,MAAM,cAAgC,eAAe,YAEnD,EACA,OACA,SAAS,EAAE,EACX,OAAO,QACP,OAAO,EAAE,EACT,aAAa,cACb,KACA,aAAa,OAAO,uBASnB;EACD,MAAM,QAAQ,WAAW,gBAAgB,qBAAqB,MAAM,WAAW,EAAE;EACjF,MAAM,cAAc,gBAAiB,MAAM,0BAA0B;EACrE,MAAM,SAAS,gBAAgB;EAC/B,MAAM,aACJ,cAAc,eAAe,KAAA,IACzB,aAAa,aACb,QAAQ,IAAI,aAAa,eACvB,QACA,KAAA;EACR,MAAM,eAAe,QAAQ,IAAI,kBAAkB;EACnD,MAAM,YAAY,UAAU,CAAC,eAAe,YAAY,KAAA;EAExD,MAAM,EAAC,aAAY,MAAM,OAAO,MAAM,OAAO,MAAM,QAAQ;GACzD,gBAAgB;GACH;GACb,OAAO;GACP,aAAa;GACb,MAAM;IAAC;IAAY,MAAM,CAAC,GAAG,MAAM,yBAAyB;IAAC;GAC7D;GACA;GACA,KAAK,CAAC,YAAY,kBAAkB,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI;GAC/D,CAAC;EAEF,MAAM,YAAY,CAAC,GAAG,MAAM,GAAI,UAAU,KAAK,QAAQ,UAAU,MAAM,IAAI,EAAE,CAAE;EAE/E,MAAM,EAAC,QAAQ,oBAAmB,MAAM,OAAO,MAAM,OAAO,MAAM,QAAQ;GACxE,gBAAgB;GACH;GACb;GACA,OAAO,gBAAgB,eAAe,cAAc,cAAc;GAClE,MAAM;IAAC;IAAY,MAAM;IAAU;GACnC;GACA;GACA,KAAK;GACN,CAAC;AACF,SAAO;GAAC,MAAM;GAAQ,WAAW,mBAAmB;GAAM,MAAM;GAAU;;CAG5E,MAAMA,eAAoD,eAAeA,aAAW,OAAO;EACzF,MAAM,EACJ,gBACA,gBACA,oBACA,KACA,aAAa,KACb,SACA,UACA,kBACA,oBACA,YACE;EACJ,MAAM,EAAC,WAAW,SAAS,SAAS,YAAY,oBAAoB,qBAClE,OAAO,QAAQ;EACjB,MAAM,EAAC,WAAW,uBAAsB,MAAM,WAAW;EAGzD,MAAM,EAAC,WAAU,IAAI,IAAI,OAAO,OAAO,IAAI,MAAM,CAAC;AAClD,aAAW,OAAO;AAElB,SACE,oBAACC,YAAD;GACa;GACF;GACA;GACG;GACQ;GACF;GACN;GACZ,OAAO,OAAO,iBAAiB,YAAY,qBAAqB,eAAe,KAAA;GAC/E,kBAAkB;GAClB,sBAAsB,MAAM,0BAA0B;GACtC;GACA;GACI;GACX;GACC;GACQ;GACE;GACX;GACT,CAAA;;AAGN,cAAW,cAAc;AAEzB,QAAO;EAAC;EAAa,YAAA;EAAW;;AAGlC,eAAe,2BAAuE;AACpF,SAAQ,MAAM,WAAW,EAAE,aACtB,MAAM,SAAS,EAAE,IAAI,sBAAsB,GAC1C,qBAAqB,MAAM,SAAS,EAAE,IAAI,sBAAsB,EAAE,OAAO,SAAS,GAClF,WACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ClientPerspective, SyncTag } from "@sanity/client";
|
|
2
|
+
/**
|
|
3
|
+
* @internal CAUTION: this is an internal action and does not follow semver. Using it directly is at your own risk.
|
|
4
|
+
*/
|
|
5
|
+
declare function revalidateSyncTags(tags: SyncTag[]): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* @internal CAUTION: this is an internal action and does not follow semver. Using it directly is at your own risk.
|
|
8
|
+
*/
|
|
9
|
+
declare function setPerspectiveCookie(perspective: ClientPerspective): Promise<void>;
|
|
10
|
+
export { revalidateSyncTags, setPerspectiveCookie };
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/live/server-actions/index.ts"],"mappings":";;AAYA;;iBAAsB,kBAAA,CAAmB,IAAA,EAAM,OAAA,KAAY,OAAA;;;;iBA2BrC,oBAAA,CAAqB,WAAA,EAAa,iBAAA,GAAoB,OAAA"}
|
|
@@ -3,6 +3,9 @@ import { t as sanitizePerspective } from "../../sanitizePerspective.js";
|
|
|
3
3
|
import { perspectiveCookieName } from "@sanity/preview-url-secret/constants";
|
|
4
4
|
import { cookies, draftMode } from "next/headers";
|
|
5
5
|
import { revalidateTag, updateTag } from "next/cache";
|
|
6
|
+
/**
|
|
7
|
+
* @internal CAUTION: this is an internal action and does not follow semver. Using it directly is at your own risk.
|
|
8
|
+
*/
|
|
6
9
|
async function revalidateSyncTags(tags) {
|
|
7
10
|
const { isEnabled: isDraftMode } = await draftMode();
|
|
8
11
|
if (!isDraftMode) revalidateTag("sanity:fetch-sync-tags", "max");
|
|
@@ -15,6 +18,9 @@ async function revalidateSyncTags(tags) {
|
|
|
15
18
|
}
|
|
16
19
|
console.log(`<SanityLive /> ${isDraftMode ? `revalidated tags: ${logTags.join(", ")} with cache profile "max" ` : `updated tags: ${logTags.join(", ")} and revalidated tag: "sanity:fetch-sync-tags" with cache profile "max"`}`);
|
|
17
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* @internal CAUTION: this is an internal action and does not follow semver. Using it directly is at your own risk.
|
|
23
|
+
*/
|
|
18
24
|
async function setPerspectiveCookie(perspective) {
|
|
19
25
|
if (!(await draftMode()).isEnabled) return;
|
|
20
26
|
const sanitizedPerspective = sanitizePerspective(perspective, "drafts");
|
|
@@ -28,4 +34,4 @@ async function setPerspectiveCookie(perspective) {
|
|
|
28
34
|
}
|
|
29
35
|
export { revalidateSyncTags, setPerspectiveCookie };
|
|
30
36
|
|
|
31
|
-
//# sourceMappingURL=index.
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/live/server-actions/index.ts"],"sourcesContent":["'use server'\n\nimport type {ClientPerspective, SyncTag} from '@sanity/client'\nimport {perspectiveCookieName} from '@sanity/preview-url-secret/constants'\nimport {revalidateTag, updateTag} from 'next/cache'\nimport {cookies, draftMode} from 'next/headers'\n\nimport {sanitizePerspective} from '#live/sanitizePerspective'\n\n/**\n * @internal CAUTION: this is an internal action and does not follow semver. Using it directly is at your own risk.\n */\nexport async function revalidateSyncTags(tags: SyncTag[]): Promise<void> {\n const {isEnabled: isDraftMode} = await draftMode()\n\n if (!isDraftMode) {\n revalidateTag('sanity:fetch-sync-tags', 'max')\n }\n\n const logTags: string[] = []\n for (const _tag of tags) {\n const tag = `sanity:${_tag}`\n if (isDraftMode) {\n revalidateTag(tag, 'max')\n } else {\n updateTag(tag)\n }\n logTags.push(tag)\n }\n\n // oxlint-disable-next-line no-console\n console.log(\n `<SanityLive /> ${isDraftMode ? `revalidated tags: ${logTags.join(', ')} with cache profile \"max\" ` : `updated tags: ${logTags.join(', ')} and revalidated tag: \"sanity:fetch-sync-tags\" with cache profile \"max\"`}`,\n )\n}\n\n/**\n * @internal CAUTION: this is an internal action and does not follow semver. Using it directly is at your own risk.\n */\nexport async function setPerspectiveCookie(perspective: ClientPerspective): Promise<void> {\n if (!(await draftMode()).isEnabled) {\n // throw new Error('Draft mode is not enabled, setting perspective cookie is not allowed')\n return\n }\n const sanitizedPerspective = sanitizePerspective(perspective, 'drafts')\n if (perspective !== sanitizedPerspective) {\n throw new Error(`Invalid perspective`, {cause: perspective})\n }\n\n ;(await cookies()).set(\n perspectiveCookieName,\n Array.isArray(sanitizedPerspective) ? sanitizedPerspective.join(',') : sanitizedPerspective,\n {\n httpOnly: true,\n path: '/',\n secure: true,\n sameSite: 'none',\n },\n )\n}\n"],"mappings":";;;;;;;;AAYA,eAAsB,mBAAmB,MAAgC;CACvE,MAAM,EAAC,WAAW,gBAAe,MAAM,WAAW;AAElD,KAAI,CAAC,YACH,eAAc,0BAA0B,MAAM;CAGhD,MAAM,UAAoB,EAAE;AAC5B,MAAK,MAAM,QAAQ,MAAM;EACvB,MAAM,MAAM,UAAU;AACtB,MAAI,YACF,eAAc,KAAK,MAAM;MAEzB,WAAU,IAAI;AAEhB,UAAQ,KAAK,IAAI;;AAInB,SAAQ,IACN,kBAAkB,cAAc,qBAAqB,QAAQ,KAAK,KAAK,CAAC,8BAA8B,iBAAiB,QAAQ,KAAK,KAAK,CAAC,2EAC3I;;;;;AAMH,eAAsB,qBAAqB,aAA+C;AACxF,KAAI,EAAE,MAAM,WAAW,EAAE,UAEvB;CAEF,MAAM,uBAAuB,oBAAoB,aAAa,SAAS;AACvE,KAAI,gBAAgB,qBAClB,OAAM,IAAI,MAAM,uBAAuB,EAAC,OAAO,aAAY,CAAC;AAG7D,EAAC,MAAM,SAAS,EAAE,IACjB,uBACA,MAAM,QAAQ,qBAAqB,GAAG,qBAAqB,KAAK,IAAI,GAAG,sBACvE;EACE,UAAU;EACV,MAAM;EACN,QAAQ;EACR,UAAU;EACX,CACF"}
|
|
@@ -1,19 +1,43 @@
|
|
|
1
|
-
import { ClientPerspective, ClientReturn, ContentSourceMap, LiveEventGoAway, QueryParams, SanityClient, SyncTag } from "
|
|
1
|
+
import { ClientPerspective, ClientReturn, ContentSourceMap, LiveEventGoAway, QueryParams, SanityClient, SyncTag } from "next-sanity";
|
|
2
2
|
/**
|
|
3
|
+
* Perspectives supported by Sanity Live.
|
|
4
|
+
* Using the legacy `'raw'` perspective is not supported and leads to undefined behavior.
|
|
5
|
+
*/
|
|
6
|
+
type LivePerspective = Exclude<ClientPerspective, "raw">;
|
|
7
|
+
/**
|
|
8
|
+
* Use this function to fetch data from Sanity in your React Server Components.
|
|
9
|
+
* When used within a `generateMetadata` or `generateViewport` function, make sure you set `stega: false`.
|
|
10
|
+
* When used within a `generateStaticParams` function, make sure you set `stega: false` and `perspective: 'published'`.
|
|
3
11
|
* @public
|
|
4
12
|
*/
|
|
5
|
-
type
|
|
13
|
+
type DefinedFetchType = <const QueryString extends string>(options: {
|
|
14
|
+
/**
|
|
15
|
+
* GROQ query to execute.
|
|
16
|
+
*/
|
|
6
17
|
query: QueryString;
|
|
18
|
+
/**
|
|
19
|
+
* Parameters used by the GROQ query.
|
|
20
|
+
*/
|
|
7
21
|
params?: QueryParams | Promise<QueryParams>;
|
|
8
22
|
/**
|
|
23
|
+
* Content perspective used for the fetch.
|
|
24
|
+
*
|
|
25
|
+
* @defaultValue 'published' or when in draft mode it's 'drafts' or the value of a cookie named 'sanity-preview-perspective' that is set by `defineEnableDraftMode`.
|
|
26
|
+
*/
|
|
27
|
+
perspective?: LivePerspective;
|
|
28
|
+
/**
|
|
29
|
+
* Enables stega encoding of the data. This is typically only used in draft
|
|
30
|
+
* mode with `perspective: 'drafts'` and `@sanity/visual-editing`.
|
|
31
|
+
*
|
|
32
|
+
* @defaultValue `false` or when in draft mode it's `true`
|
|
33
|
+
*/
|
|
34
|
+
stega?: boolean;
|
|
35
|
+
/**
|
|
9
36
|
* Add custom `next.tags` to the underlying fetch request.
|
|
10
37
|
* @see https://nextjs.org/docs/app/api-reference/functions/fetch#optionsnexttags
|
|
11
38
|
* This can be used in conjunction with custom fallback revalidation strategies, as well as with custom Server Actions that mutate data and want to render with fresh data right away (faster than the Live Event latency).
|
|
12
|
-
* @defaultValue `['sanity']`
|
|
13
39
|
*/
|
|
14
40
|
tags?: string[];
|
|
15
|
-
perspective?: Exclude<ClientPerspective, "raw">;
|
|
16
|
-
stega?: boolean;
|
|
17
41
|
/**
|
|
18
42
|
* @deprecated use `requestTag` instead
|
|
19
43
|
*/
|
|
@@ -25,14 +49,15 @@ type DefinedSanityFetchType = <const QueryString extends string>(options: {
|
|
|
25
49
|
*/
|
|
26
50
|
requestTag?: string;
|
|
27
51
|
}) => Promise<{
|
|
28
|
-
data: ClientReturn<QueryString>;
|
|
52
|
+
data: ClientReturn<QueryString, unknown>;
|
|
29
53
|
sourceMap: ContentSourceMap | null;
|
|
30
54
|
tags: string[];
|
|
31
55
|
}>;
|
|
32
56
|
/**
|
|
57
|
+
* Render this in your root layout.tsx to make your page revalidate on new content live, automatically.
|
|
33
58
|
* @public
|
|
34
59
|
*/
|
|
35
|
-
interface
|
|
60
|
+
interface DefinedLiveProps {
|
|
36
61
|
/**
|
|
37
62
|
* Automatic refresh of RSC when the component <SanityLive /> is mounted.
|
|
38
63
|
* Note that this is different from revalidation, which is based on tags and causes `sanityFetch` calls to be re-fetched.
|
|
@@ -60,8 +85,11 @@ interface DefinedSanityLiveProps {
|
|
|
60
85
|
*/
|
|
61
86
|
intervalOnGoAway?: number | false;
|
|
62
87
|
/**
|
|
63
|
-
* Delays events until after a Sanity Function has processed them and called the callback endpoint.
|
|
88
|
+
* Delays events until after a configured Sanity Function has processed them and called the callback endpoint.
|
|
64
89
|
* When omitted, events are delivered immediately.
|
|
90
|
+
*
|
|
91
|
+
* @remarks
|
|
92
|
+
* When set, any custom `revalidateSyncTags` will not be called — revalidation is handled by the Function instead.
|
|
65
93
|
*/
|
|
66
94
|
waitFor?: "function";
|
|
67
95
|
/**
|
|
@@ -95,7 +123,7 @@ interface DefinedSanityLiveProps {
|
|
|
95
123
|
/**
|
|
96
124
|
* @public
|
|
97
125
|
*/
|
|
98
|
-
interface
|
|
126
|
+
interface DefineLiveOptions {
|
|
99
127
|
/**
|
|
100
128
|
* Required for `sanityFetch` and `SanityLive` to work
|
|
101
129
|
*/
|
|
@@ -127,20 +155,5 @@ interface DefineSanityLiveOptions {
|
|
|
127
155
|
*/
|
|
128
156
|
stega?: boolean;
|
|
129
157
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
*/
|
|
133
|
-
declare function defineLive(config: DefineSanityLiveOptions): {
|
|
134
|
-
/**
|
|
135
|
-
* Use this function to fetch data from Sanity in your React Server Components.
|
|
136
|
-
* @public
|
|
137
|
-
*/
|
|
138
|
-
sanityFetch: DefinedSanityFetchType;
|
|
139
|
-
/**
|
|
140
|
-
* Render this in your root layout.tsx to make your page revalidate on new content live, automatically.
|
|
141
|
-
* @public
|
|
142
|
-
*/
|
|
143
|
-
SanityLive: React.ComponentType<DefinedSanityLiveProps>;
|
|
144
|
-
};
|
|
145
|
-
export { defineLive as i, DefinedSanityFetchType as n, DefinedSanityLiveProps as r, DefineSanityLiveOptions as t };
|
|
146
|
-
//# sourceMappingURL=defineLive.d.ts.map
|
|
158
|
+
export { LivePerspective as i, DefinedFetchType as n, DefinedLiveProps as r, DefineLiveOptions as t };
|
|
159
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../src/live/shared/types.ts"],"mappings":";;AAcA;;;KAAY,eAAA,GAAkB,OAAA,CAAQ,iBAAA;;AAQtC;;;;;KAAY,gBAAA,sCAAsD,OAAA;;;;EAIhE,KAAA,EAAO,WAAA;;;;EAIP,MAAA,GAAS,WAAA,GAAc,OAAA,CAAQ,WAAA;;;;;;EAM/B,WAAA,GAAc,eAAA;;;;;;;EAOd,KAAA;;;;;;EAMA,IAAA;;;;EAIA,GAAA;EAiBF;;;;;EAXE,UAAA;AAAA,MACI,OAAA;EACJ,IAAA,EAAM,YAAA,CAAa,WAAA;EACnB,SAAA,EAAW,gBAAA;EACX,IAAA;AAAA;;;;;UAOe,gBAAA;;;;;;EAMf,cAAA;;;;;;EAMA,cAAA;EA6De;;;;;EAvDf,kBAAA;;;;;;;;EAQA,gBAAA;;;;;;;;EASA,OAAA;;;;EAKA,GAAA;;;;;;EAOA,UAAA;;;;;EAMA,OAAA,IAAW,KAAA;;;;;;;EAQX,QAAA,IAAY,KAAA,EAAO,eAAA,EAAiB,gBAAA;;;;;EAMpC,kBAAA,IAAsB,IAAA,EAAM,OAAA,OAAc,OAAA;AAAA;;;;UAM3B,iBAAA;;;;EAIf,MAAA,EAAQ,YAAA;;;;;EAKR,WAAA;;;;;EAKA,YAAA;;;;;EAKA,YAAA;;;;;IAKE,UAAA;EAAA;;;;;EAMF,KAAA;AAAA"}
|
|
@@ -2,6 +2,6 @@ import { ClientPerspective } from "@sanity/client";
|
|
|
2
2
|
/**
|
|
3
3
|
* @internal CAUTION: this is an internal action and does not follow semver. Using it directly is at your own risk.
|
|
4
4
|
*/
|
|
5
|
-
declare function
|
|
6
|
-
export {
|
|
5
|
+
declare function perspectiveChangeAction(perspective: ClientPerspective): Promise<void>;
|
|
6
|
+
export { perspectiveChangeAction };
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -6,13 +6,13 @@ import { refresh } from "next/cache";
|
|
|
6
6
|
/**
|
|
7
7
|
* @internal CAUTION: this is an internal action and does not follow semver. Using it directly is at your own risk.
|
|
8
8
|
*/
|
|
9
|
-
async function
|
|
9
|
+
async function perspectiveChangeAction(perspective) {
|
|
10
10
|
const sanitizedPerspective = sanitizePerspective(perspective, "drafts");
|
|
11
11
|
if (!sanitizedPerspective || Array.isArray(sanitizedPerspective) && sanitizedPerspective.length === 0) throw new Error(`Invalid perspective`, { cause: perspective });
|
|
12
12
|
const nextPerspective = Array.isArray(sanitizedPerspective) ? sanitizedPerspective.join(",") : sanitizedPerspective;
|
|
13
13
|
const jar = await cookies();
|
|
14
14
|
if (nextPerspective === jar.get(perspectiveCookieName)?.value && process.env.NODE_ENV !== "production") {
|
|
15
|
-
console.debug("
|
|
15
|
+
console.debug("perspectiveChangeAction", "Perspective is the same, skipping", nextPerspective);
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
18
|
jar.set(perspectiveCookieName, nextPerspective, {
|
|
@@ -23,6 +23,6 @@ async function actionPerspectiveChange(perspective) {
|
|
|
23
23
|
});
|
|
24
24
|
refresh();
|
|
25
25
|
}
|
|
26
|
-
export {
|
|
26
|
+
export { perspectiveChangeAction };
|
|
27
27
|
|
|
28
28
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/visual-editing/server-actions/index.ts"],"sourcesContent":["'use server'\n\nimport type {ClientPerspective} from '@sanity/client'\nimport {perspectiveCookieName} from '@sanity/preview-url-secret/constants'\nimport {refresh} from 'next/cache'\nimport {cookies} from 'next/headers'\n\nimport {sanitizePerspective} from '#live/sanitizePerspective'\n\n/**\n * @internal CAUTION: this is an internal action and does not follow semver. Using it directly is at your own risk.\n */\nexport async function
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/visual-editing/server-actions/index.ts"],"sourcesContent":["'use server'\n\nimport type {ClientPerspective} from '@sanity/client'\nimport {perspectiveCookieName} from '@sanity/preview-url-secret/constants'\nimport {refresh} from 'next/cache'\nimport {cookies} from 'next/headers'\n\nimport {sanitizePerspective} from '#live/sanitizePerspective'\n\n/**\n * @internal CAUTION: this is an internal action and does not follow semver. Using it directly is at your own risk.\n */\nexport async function perspectiveChangeAction(perspective: ClientPerspective): Promise<void> {\n const sanitizedPerspective = sanitizePerspective(perspective, 'drafts')\n if (\n !sanitizedPerspective ||\n (Array.isArray(sanitizedPerspective) && sanitizedPerspective.length === 0)\n ) {\n throw new Error(`Invalid perspective`, {cause: perspective})\n }\n\n const nextPerspective = Array.isArray(sanitizedPerspective)\n ? sanitizedPerspective.join(',')\n : sanitizedPerspective\n const jar = await cookies()\n if (\n nextPerspective === jar.get(perspectiveCookieName)?.value &&\n process.env.NODE_ENV !== 'production'\n ) {\n // oxlint-disable-next-line no-console\n console.debug('perspectiveChangeAction', 'Perspective is the same, skipping', nextPerspective)\n return\n }\n jar.set(perspectiveCookieName, nextPerspective, {\n httpOnly: true,\n path: '/',\n secure: true,\n sameSite: 'none',\n })\n\n refresh()\n}\n"],"mappings":";;;;;;;;AAYA,eAAsB,wBAAwB,aAA+C;CAC3F,MAAM,uBAAuB,oBAAoB,aAAa,SAAS;AACvE,KACE,CAAC,wBACA,MAAM,QAAQ,qBAAqB,IAAI,qBAAqB,WAAW,EAExE,OAAM,IAAI,MAAM,uBAAuB,EAAC,OAAO,aAAY,CAAC;CAG9D,MAAM,kBAAkB,MAAM,QAAQ,qBAAqB,GACvD,qBAAqB,KAAK,IAAI,GAC9B;CACJ,MAAM,MAAM,MAAM,SAAS;AAC3B,KACE,oBAAoB,IAAI,IAAI,sBAAsB,EAAE,SACpD,QAAQ,IAAI,aAAa,cACzB;AAEA,UAAQ,MAAM,2BAA2B,qCAAqC,gBAAgB;AAC9F;;AAEF,KAAI,IAAI,uBAAuB,iBAAiB;EAC9C,UAAU;EACV,MAAM;EACN,QAAQ;EACR,UAAU;EACX,CAAC;AAEF,UAAS"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-sanity",
|
|
3
|
-
"version": "12.4.
|
|
3
|
+
"version": "12.4.2",
|
|
4
4
|
"description": "Sanity.io toolkit for Next.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"live",
|
|
@@ -47,9 +47,7 @@
|
|
|
47
47
|
"default": "./dist/live/conditions/default/index.js"
|
|
48
48
|
},
|
|
49
49
|
"./live/client-components": "./dist/live/client-components/index.js",
|
|
50
|
-
"./live/server-actions":
|
|
51
|
-
"default": "./dist/live/server-actions/index.default.js"
|
|
52
|
-
},
|
|
50
|
+
"./live/server-actions": "./dist/live/server-actions/index.js",
|
|
53
51
|
"./studio": "./dist/studio/index.js",
|
|
54
52
|
"./studio/client-component": "./dist/studio/client-component/index.js",
|
|
55
53
|
"./visual-editing": "./dist/visual-editing/index.js",
|
|
@@ -59,7 +57,7 @@
|
|
|
59
57
|
"./package.json": "./package.json"
|
|
60
58
|
},
|
|
61
59
|
"dependencies": {
|
|
62
|
-
"@portabletext/react": "^6.0
|
|
60
|
+
"@portabletext/react": "^6.1.0",
|
|
63
61
|
"@sanity/client": "^7.22.0",
|
|
64
62
|
"@sanity/comlink": "^4.0.1",
|
|
65
63
|
"@sanity/presentation-comlink": "^2.0.1",
|
|
@@ -79,7 +77,7 @@
|
|
|
79
77
|
"@vitejs/plugin-react": "^6.0.1",
|
|
80
78
|
"@vitest/coverage-v8": "^4.1.5",
|
|
81
79
|
"js-yaml": "^4.1.1",
|
|
82
|
-
"next": "16.3.0-canary.
|
|
80
|
+
"next": "16.3.0-canary.10",
|
|
83
81
|
"publint": "^0.3.18",
|
|
84
82
|
"react": "^19.2.5",
|
|
85
83
|
"react-dom": "^19.2.5",
|
package/dist/defineLive.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"defineLive.d.ts","names":[],"sources":["../src/live/conditions/react-server/defineLive.tsx"],"mappings":";;AAoBA;;KAAY,sBAAA,sCAA4D,OAAA;EACtE,KAAA,EAAO,WAAA;EACP,MAAA,GAAS,WAAA,GAAc,OAAA,CAAQ,WAAA;;;;;;;EAO/B,IAAA;EACA,WAAA,GAAc,OAAA,CAAQ,iBAAA;EACtB,KAAA;EAWI;;;EAPJ,GAAA;;;;;;EAMA,UAAA;AAAA,MACI,OAAA;EACJ,IAAA,EAAM,YAAA,CAAa,WAAA;EACnB,SAAA,EAAW,gBAAA;EACX,IAAA;AAAA;;;;UAMe,sBAAA;;;;;;EAMf,cAAA;EANF;;;;;EAYE,cAAA;;;;;;EAMA,kBAAA;;;;;;;;EAQA,gBAAA;;;;;EAMA,OAAA;;;AAsCF;EAjCE,GAAA;;;;;;EAOA,UAAA;;;;;EAMA,OAAA,IAAW,KAAA;EAwDb;;;;;;EAhDE,QAAA,IAAY,KAAA,EAAO,eAAA,EAAiB,gBAAA;;;;;EAMpC,kBAAA,IAAsB,IAAA,EAAM,OAAA,OAAc,OAAA;AAAA;;;;UAM3B,uBAAA;;;;EAIf,MAAA,EAAQ,YAAA;;;;;EAKR,WAAA;;;;;EAKA,YAAA;;;;;EAKA,YAAA;;;;;IAKE,UAAA;EAAA;;;;;EAMF,KAAA;AAAA;;;;iBAMc,UAAA,CAAW,MAAA,EAAQ,uBAAA;;;;;EAKjC,WAAA,EAAa,sBAAA;;;;;EAKb,UAAA,EAAY,KAAA,CAAM,aAAA,CAAc,sBAAA;AAAA"}
|