next-sanity 13.0.0-cache-components.42 → 13.0.0-cache-components.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,17 +1,244 @@
1
1
  import { t as isCorsOriginError } from "../../../isCorsOriginError.js";
2
- import { d as StrictDefinedFetchType, f as StrictDefinedLiveProps, i as LivePerspective, n as DefinedFetchType, r as DefinedLiveProps, t as DefineLiveOptions } from "../../../types.js";
2
+ import { a as SanityLiveAction, c as SanityLiveOnGoaway, d as SanityLiveOnWelcome, f as StrictDefinedFetchType, i as LivePerspective, l as SanityLiveOnReconnect, n as DefinedFetchType, o as SanityLiveActionContext, p as StrictDefinedLiveProps, r as DefinedLiveProps, s as SanityLiveOnError, t as DefineLiveOptions, u as SanityLiveOnRestart } from "../../../types.js";
3
3
  import { n as resolvePerspectiveFromCookies, t as parseTags } from "../../../parseTags.js";
4
+ /**
5
+ * Set up Sanity Live for Cache Components. `defineLive` returns `sanityFetch`
6
+ * and `<SanityLive />`, which connect your Sanity client to the Live Content API
7
+ * so cached pages can update in response to fine-grained content changes.
8
+ *
9
+ * With `strict: true`, `perspective` and `stega` become required
10
+ * `sanityFetch` options, and `includeDrafts` becomes required on
11
+ * `<SanityLive />`. Resolve dynamic values from `draftMode()` and `cookies()`
12
+ * outside `'use cache'` boundaries, then pass them into cached components.
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
+ * // sanity/live.ts
20
+ * import {cookies, draftMode} from 'next/headers'
21
+ * import {createClient} from 'next-sanity'
22
+ * import {
23
+ * defineLive,
24
+ * resolvePerspectiveFromCookies,
25
+ * type LivePerspective,
26
+ * } from 'next-sanity/live'
27
+ *
28
+ * const client = createClient({
29
+ * projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
30
+ * dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
31
+ * useCdn: true,
32
+ * perspective: 'published',
33
+ * })
34
+ * const token = process.env.SANITY_API_READ_TOKEN
35
+ *
36
+ * export const {sanityFetch, SanityLive} = defineLive({
37
+ * client,
38
+ * browserToken: token,
39
+ * serverToken: token,
40
+ * strict: true,
41
+ * })
42
+ *
43
+ * export interface DynamicFetchOptions {
44
+ * perspective: LivePerspective
45
+ * stega: boolean
46
+ * }
47
+ *
48
+ * // Resolve dynamic values outside 'use cache' boundaries.
49
+ * export async function getDynamicFetchOptions(): Promise<DynamicFetchOptions> {
50
+ * const {isEnabled: isDraftMode} = await draftMode()
51
+ * if (!isDraftMode) {
52
+ * return {perspective: 'published', stega: false}
53
+ * }
54
+ *
55
+ * const jar = await cookies()
56
+ * const perspective = await resolvePerspectiveFromCookies({cookies: jar})
57
+ * return {perspective: perspective ?? 'drafts', stega: true}
58
+ * }
59
+ * ```
60
+ *
61
+ * @example
62
+ * ```tsx
63
+ * // app/layout.tsx
64
+ * import {draftMode} from 'next/headers'
65
+ *
66
+ * import {SanityLive} from '@/sanity/live'
67
+ *
68
+ * export default async function RootLayout({children}: {children: React.ReactNode}) {
69
+ * const {isEnabled: isDraftMode} = await draftMode()
70
+ *
71
+ * return (
72
+ * <html lang="en">
73
+ * <body>
74
+ * {children}
75
+ * <SanityLive includeDrafts={isDraftMode} />
76
+ * </body>
77
+ * </html>
78
+ * )
79
+ * }
80
+ * ```
81
+ *
82
+ * @example
83
+ * ```tsx
84
+ * // app/[slug]/page.tsx
85
+ * import {draftMode} from 'next/headers'
86
+ * import {Suspense} from 'react'
87
+ * import {defineQuery} from 'next-sanity'
88
+ *
89
+ * import {
90
+ * getDynamicFetchOptions,
91
+ * sanityFetch,
92
+ * type DynamicFetchOptions,
93
+ * } from '@/sanity/live'
94
+ *
95
+ * const POSTS_SLUGS_QUERY = defineQuery(`
96
+ * *[_type == "post" && slug.current]{"slug": slug.current}
97
+ * `)
98
+ * const POST_QUERY = defineQuery(`
99
+ * *[_type == "post" && slug.current == $slug][0]
100
+ * `)
101
+ *
102
+ * export async function generateStaticParams() {
103
+ * const {data} = await sanityFetch({
104
+ * query: POSTS_SLUGS_QUERY,
105
+ * perspective: 'published',
106
+ * stega: false,
107
+ * })
108
+ *
109
+ * return data
110
+ * }
111
+ *
112
+ * export default async function Page(props: PageProps<'/[slug]'>) {
113
+ * const {isEnabled: isDraftMode} = await draftMode()
114
+ * if (isDraftMode) {
115
+ * return (
116
+ * <Suspense fallback={<div>Loading...</div>}>
117
+ * <DynamicPage params={props.params} />
118
+ * </Suspense>
119
+ * )
120
+ * }
121
+ *
122
+ * const {slug} = await props.params
123
+ * return <CachedPage slug={slug} perspective="published" stega={false} />
124
+ * }
125
+ *
126
+ * async function DynamicPage(props: Pick<PageProps<'/[slug]'>, 'params'>) {
127
+ * const {slug} = await props.params
128
+ * const {perspective, stega} = await getDynamicFetchOptions()
129
+ *
130
+ * return <CachedPage slug={slug} perspective={perspective} stega={stega} />
131
+ * }
132
+ *
133
+ * async function CachedPage({
134
+ * slug,
135
+ * perspective,
136
+ * stega,
137
+ * }: {slug: string} & DynamicFetchOptions) {
138
+ * 'use cache'
139
+ *
140
+ * const {data} = await sanityFetch({
141
+ * query: POST_QUERY,
142
+ * params: {slug},
143
+ * perspective,
144
+ * stega,
145
+ * })
146
+ *
147
+ * return <pre>{JSON.stringify(data, null, 2)}</pre>
148
+ * }
149
+ * ```
150
+ *
151
+ * @public
152
+ */
4
153
  declare function defineLive(config: DefineLiveOptions & {
5
154
  strict: true;
6
155
  }): {
7
156
  sanityFetch: StrictDefinedFetchType;
8
157
  SanityLive: React.ComponentType<StrictDefinedLiveProps>;
9
158
  };
159
+ /**
160
+ * Set up Sanity Live. `defineLive` returns `sanityFetch` and `<SanityLive />`,
161
+ * which connect your Sanity client to the Live Content API so pages can serve
162
+ * cached content and update in response to fine-grained content changes.
163
+ *
164
+ * @see [Live Content API](https://www.sanity.io/docs/content-lake/live-content-api)
165
+ * @see [Sanity Live](https://www.sanity.io/live)
166
+ *
167
+ * @example
168
+ * ```tsx
169
+ * import {createClient} from 'next-sanity'
170
+ * import {defineLive} from 'next-sanity/live'
171
+ *
172
+ * const client = createClient({
173
+ * projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
174
+ * dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
175
+ * useCdn: true,
176
+ * perspective: 'published',
177
+ * })
178
+ *
179
+ * export const {sanityFetch, SanityLive} = defineLive({
180
+ * client,
181
+ * })
182
+ * ```
183
+ *
184
+ * @example
185
+ * ```tsx
186
+ * // app/layout.tsx
187
+ * import {SanityLive} from '@/sanity/live'
188
+ *
189
+ * export default function RootLayout({children}: {children: React.ReactNode}) {
190
+ * return (
191
+ * <html lang="en">
192
+ * <body>
193
+ * {children}
194
+ * <SanityLive />
195
+ * </body>
196
+ * </html>
197
+ * )
198
+ * }
199
+ * ```
200
+ *
201
+ * @example
202
+ * ```tsx
203
+ * // app/[slug]/page.tsx
204
+ * import {defineQuery} from 'next-sanity'
205
+ * import {sanityFetch} from '@/sanity/live'
206
+ *
207
+ * const POSTS_SLUGS_QUERY = defineQuery(`
208
+ * *[_type == "post" && slug.current]{"slug": slug.current}
209
+ * `)
210
+ * const POST_QUERY = defineQuery(`
211
+ * *[_type == "post" && slug.current == $slug][0]
212
+ * `)
213
+ *
214
+ * export async function generateStaticParams() {
215
+ * const {data} = await sanityFetch({
216
+ * query: POSTS_SLUGS_QUERY,
217
+ * perspective: 'published',
218
+ * stega: false,
219
+ * })
220
+ *
221
+ * return data
222
+ * }
223
+ *
224
+ * export default async function Page(props: PageProps<'/[slug]'>) {
225
+ * const {slug} = await props.params
226
+ * const {data} = await sanityFetch({
227
+ * query: POST_QUERY,
228
+ * params: {slug},
229
+ * })
230
+ *
231
+ * return <pre>{JSON.stringify(data, null, 2)}</pre>
232
+ * }
233
+ * ```
234
+ *
235
+ * @public
236
+ */
10
237
  declare function defineLive(config: DefineLiveOptions & {
11
238
  strict?: false;
12
239
  }): {
13
240
  sanityFetch: DefinedFetchType;
14
241
  SanityLive: React.ComponentType<DefinedLiveProps>;
15
242
  };
16
- export { type LivePerspective, defineLive, isCorsOriginError, parseTags, resolvePerspectiveFromCookies };
243
+ export { type DefineLiveOptions, type DefinedFetchType, type DefinedLiveProps, type LivePerspective, type SanityLiveAction, type SanityLiveActionContext, type SanityLiveOnError, type SanityLiveOnGoaway, type SanityLiveOnReconnect, type SanityLiveOnRestart, type SanityLiveOnWelcome, type StrictDefinedFetchType, type StrictDefinedLiveProps, defineLive, isCorsOriginError, parseTags, resolvePerspectiveFromCookies };
17
244
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../../src/live/conditions/react-server/defineLive.tsx"],"mappings":";;;iBAmBgB,UAAA,CAAW,MAAA,EAAQ,iBAAA;EAAqB,MAAA;AAAA;EACtD,WAAA,EAAa,sBAAA;EACb,UAAA,EAAY,KAAA,CAAM,aAAA,CAAc,sBAAA;AAAA;AAAA,iBAElB,UAAA,CAAW,MAAA,EAAQ,iBAAA;EAAqB,MAAA;AAAA;EACtD,WAAA,EAAa,gBAAA;EACb,UAAA,EAAY,KAAA,CAAM,aAAA,CAAc,gBAAA;AAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../../src/live/conditions/react-server/defineLive.tsx"],"mappings":";;;;;;AAwKA;;;;;;;;;;;;;;;;;;;;AAkFA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAlFgB,UAAA,CAAW,MAAA,EAAQ,iBAAA;EAAqB,MAAA;AAAA;EACtD,WAAA,EAAa,sBAAA;EACb,UAAA,EAAY,KAAA,CAAM,aAAA,CAAc,sBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgFlB,UAAA,CAAW,MAAA,EAAQ,iBAAA;EAAqB,MAAA;AAAA;EACtD,WAAA,EAAa,gBAAA;EACb,UAAA,EAAY,KAAA,CAAM,aAAA,CAAc,gBAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["SanityLive","SanityLiveClientComponent"],"sources":["../../../../src/live/conditions/react-server/defineLive.tsx"],"sourcesContent":["import {type ClientPerspective, type QueryParams} from '@sanity/client'\nimport {perspectiveCookieName} from '@sanity/preview-url-secret/constants'\nimport {SanityLive as SanityLiveClientComponent} from 'next-sanity/live/client-components'\nimport {refreshAction, revalidateSyncTagsAction} from 'next-sanity/live/server-actions'\nimport {PHASE_PRODUCTION_BUILD} from 'next/constants'\nimport {cookies, draftMode} from 'next/headers'\nimport {preconnect} from 'react-dom'\n\nimport {cacheTagPrefixes} from '#live/constants'\nimport {sanitizePerspective} from '#live/sanitizePerspective'\nimport {validateStrictFetchOptions, validateStrictSanityLiveProps} from '#live/strictValidation'\nimport type {\n DefinedFetchType,\n DefinedLiveProps,\n DefineLiveOptions,\n StrictDefinedFetchType,\n StrictDefinedLiveProps,\n} from '#live/types'\n\nexport function defineLive(config: DefineLiveOptions & {strict: true}): {\n sanityFetch: StrictDefinedFetchType\n SanityLive: React.ComponentType<StrictDefinedLiveProps>\n}\nexport function defineLive(config: DefineLiveOptions & {strict?: false}): {\n sanityFetch: DefinedFetchType\n SanityLive: React.ComponentType<DefinedLiveProps>\n}\nexport function defineLive(config: DefineLiveOptions) {\n const {\n client: _client,\n serverToken,\n browserToken,\n stega: stegaEnabled = true,\n strict = false,\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, perspective: originalPerspective = 'published'} = 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 if (strict) {\n validateStrictFetchOptions({perspective: _perspective, stega: _stega})\n }\n const stega = strict\n ? _stega!\n : (_stega ?? (stegaEnabled && studioUrlDefined && (await draftMode()).isEnabled))\n const perspective = strict\n ? _perspective!\n : (_perspective ??\n (await resolveCookiePerspective(\n originalPerspective === 'raw' ? 'published' : originalPerspective,\n )))\n const useCdn = perspective === 'published'\n const isBuildPhase = process.env['NEXT_PHASE'] === PHASE_PRODUCTION_BUILD\n const cacheMode = useCdn && !isBuildPhase ? 'noStale' : undefined\n const cacheTagPrefix =\n perspective === 'published' ? cacheTagPrefixes.published : cacheTagPrefixes.drafts\n\n // 1. Fetch the tags first, with an uncached request, but that does not count towards the Sanity API quota\n const {syncTags} = await client.fetch(query, await params, {\n filterResponse: false,\n perspective: perspective as ClientPerspective,\n stega: false,\n returnQuery: false,\n useCdn,\n cacheMode,\n tag: [requestTag, 'fetch-sync-tags'].filter(Boolean).join('.'),\n })\n\n const cacheTags = [...tags, ...(syncTags?.map((tag) => `${cacheTagPrefix}${tag}`) || [])]\n\n // 2. Then fetch the data, using the fetch cache with specified tags\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: false, 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 if (strict) {\n validateStrictSanityLiveProps(props)\n }\n const {\n includeDrafts = (await draftMode()).isEnabled,\n action = revalidateSyncTagsAction,\n onReconnect = refreshAction,\n onRestart = refreshAction,\n\n onWelcome = false,\n onError = false,\n onGoAway = false,\n\n refreshOnMount,\n refreshOnFocus,\n refreshOnReconnect,\n requestTag = 'next-loader.live',\n } = props\n const {projectId, dataset, apiHost, apiVersion, useProjectHostname, requestTagPrefix} =\n client.config()\n const shouldIncludeDrafts = typeof browserToken === 'string' && includeDrafts\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 config={{\n projectId,\n dataset,\n apiHost,\n apiVersion,\n useProjectHostname,\n requestTagPrefix,\n token: shouldIncludeDrafts ? browserToken : undefined,\n }}\n includeDrafts={shouldIncludeDrafts}\n action={action}\n onReconnect={onReconnect}\n onRestart={onRestart}\n onWelcome={onWelcome}\n onError={onError}\n onGoAway={onGoAway}\n requestTag={requestTag}\n refreshOnMount={refreshOnMount}\n refreshOnFocus={refreshOnFocus}\n refreshOnReconnect={refreshOnReconnect}\n />\n )\n }\n SanityLive.displayName = 'SanityLiveServerComponent'\n\n return {sanityFetch, SanityLive}\n}\n\nasync function resolveCookiePerspective(\n fallback: Exclude<ClientPerspective, 'raw'>,\n): 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 : fallback\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["SanityLive","SanityLiveClientComponent"],"sources":["../../../../src/live/conditions/react-server/defineLive.tsx"],"sourcesContent":["import {type ClientPerspective, type QueryParams} from '@sanity/client'\nimport {perspectiveCookieName} from '@sanity/preview-url-secret/constants'\nimport {SanityLive as SanityLiveClientComponent} from 'next-sanity/live/client-components'\nimport {refreshAction, revalidateSyncTagsAction} from 'next-sanity/live/server-actions'\nimport {PHASE_PRODUCTION_BUILD} from 'next/constants'\nimport {cookies, draftMode} from 'next/headers'\nimport {preconnect} from 'react-dom'\n\nimport {cacheTagPrefixes} from '#live/constants'\nimport {sanitizePerspective} from '#live/sanitizePerspective'\nimport {validateStrictFetchOptions, validateStrictSanityLiveProps} from '#live/strictValidation'\nimport type {\n DefinedFetchType,\n DefinedLiveProps,\n DefineLiveOptions,\n StrictDefinedFetchType,\n StrictDefinedLiveProps,\n} from '#live/types'\n\n/**\n * Set up Sanity Live for Cache Components. `defineLive` returns `sanityFetch`\n * and `<SanityLive />`, which connect your Sanity client to the Live Content API\n * so cached pages can update in response to fine-grained content changes.\n *\n * With `strict: true`, `perspective` and `stega` become required\n * `sanityFetch` options, and `includeDrafts` becomes required on\n * `<SanityLive />`. Resolve dynamic values from `draftMode()` and `cookies()`\n * outside `'use cache'` boundaries, then pass them into cached components.\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 * // sanity/live.ts\n * import {cookies, draftMode} from 'next/headers'\n * import {createClient} from 'next-sanity'\n * import {\n * defineLive,\n * resolvePerspectiveFromCookies,\n * type LivePerspective,\n * } 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 * strict: true,\n * })\n *\n * export interface DynamicFetchOptions {\n * perspective: LivePerspective\n * stega: boolean\n * }\n *\n * // Resolve dynamic values outside 'use cache' boundaries.\n * export async function getDynamicFetchOptions(): Promise<DynamicFetchOptions> {\n * const {isEnabled: isDraftMode} = await draftMode()\n * if (!isDraftMode) {\n * return {perspective: 'published', stega: false}\n * }\n *\n * const jar = await cookies()\n * const perspective = await resolvePerspectiveFromCookies({cookies: jar})\n * return {perspective: perspective ?? 'drafts', stega: true}\n * }\n * ```\n *\n * @example\n * ```tsx\n * // app/layout.tsx\n * import {draftMode} from 'next/headers'\n *\n * import {SanityLive} from '@/sanity/live'\n *\n * export default async function RootLayout({children}: {children: React.ReactNode}) {\n * const {isEnabled: isDraftMode} = await draftMode()\n *\n * return (\n * <html lang=\"en\">\n * <body>\n * {children}\n * <SanityLive includeDrafts={isDraftMode} />\n * </body>\n * </html>\n * )\n * }\n * ```\n *\n * @example\n * ```tsx\n * // app/[slug]/page.tsx\n * import {draftMode} from 'next/headers'\n * import {Suspense} from 'react'\n * import {defineQuery} from 'next-sanity'\n *\n * import {\n * getDynamicFetchOptions,\n * sanityFetch,\n * type DynamicFetchOptions,\n * } 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 {isEnabled: isDraftMode} = await draftMode()\n * if (isDraftMode) {\n * return (\n * <Suspense fallback={<div>Loading...</div>}>\n * <DynamicPage params={props.params} />\n * </Suspense>\n * )\n * }\n *\n * const {slug} = await props.params\n * return <CachedPage slug={slug} perspective=\"published\" stega={false} />\n * }\n *\n * async function DynamicPage(props: Pick<PageProps<'/[slug]'>, 'params'>) {\n * const {slug} = await props.params\n * const {perspective, stega} = await getDynamicFetchOptions()\n *\n * return <CachedPage slug={slug} perspective={perspective} stega={stega} />\n * }\n *\n * async function CachedPage({\n * slug,\n * perspective,\n * stega,\n * }: {slug: string} & DynamicFetchOptions) {\n * 'use cache'\n *\n * const {data} = await sanityFetch({\n * query: POST_QUERY,\n * params: {slug},\n * perspective,\n * stega,\n * })\n *\n * return <pre>{JSON.stringify(data, null, 2)}</pre>\n * }\n * ```\n *\n * @public\n */\nexport function defineLive(config: DefineLiveOptions & {strict: true}): {\n sanityFetch: StrictDefinedFetchType\n SanityLive: React.ComponentType<StrictDefinedLiveProps>\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 *\n * export const {sanityFetch, SanityLive} = defineLive({\n * client,\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 & {strict?: false}): {\n sanityFetch: DefinedFetchType\n SanityLive: React.ComponentType<DefinedLiveProps>\n}\nexport function defineLive(config: DefineLiveOptions) {\n const {\n client: _client,\n serverToken,\n browserToken,\n stega: stegaEnabled = true,\n strict = false,\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, perspective: originalPerspective = 'published'} = 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 if (strict) {\n validateStrictFetchOptions({perspective: _perspective, stega: _stega})\n }\n const stega = strict\n ? _stega!\n : (_stega ?? (stegaEnabled && studioUrlDefined && (await draftMode()).isEnabled))\n const perspective = strict\n ? _perspective!\n : (_perspective ??\n (await resolveCookiePerspective(\n originalPerspective === 'raw' ? 'published' : originalPerspective,\n )))\n const useCdn = perspective === 'published'\n const isBuildPhase = process.env['NEXT_PHASE'] === PHASE_PRODUCTION_BUILD\n const cacheMode = useCdn && !isBuildPhase ? 'noStale' : undefined\n const cacheTagPrefix =\n perspective === 'published' ? cacheTagPrefixes.published : cacheTagPrefixes.drafts\n\n // 1. Fetch the tags first, with an uncached request, but that does not count towards the Sanity API quota\n const {syncTags} = await client.fetch(query, await params, {\n filterResponse: false,\n perspective: perspective as ClientPerspective,\n stega: false,\n returnQuery: false,\n useCdn,\n cacheMode,\n tag: [requestTag, 'fetch-sync-tags'].filter(Boolean).join('.'),\n })\n\n const cacheTags = [...tags, ...(syncTags?.map((tag) => `${cacheTagPrefix}${tag}`) || [])]\n\n // 2. Then fetch the data, using the fetch cache with specified tags\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: false, 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 if (strict) {\n validateStrictSanityLiveProps(props)\n }\n const {\n includeDrafts = (await draftMode()).isEnabled,\n action = revalidateSyncTagsAction,\n onReconnect = refreshAction,\n onRestart = refreshAction,\n\n onWelcome = false,\n onError = false,\n onGoAway = false,\n\n refreshOnMount,\n refreshOnFocus,\n refreshOnReconnect,\n requestTag = 'next-loader.live',\n } = props\n const {projectId, dataset, apiHost, apiVersion, useProjectHostname, requestTagPrefix} =\n client.config()\n const shouldIncludeDrafts = typeof browserToken === 'string' && includeDrafts\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 config={{\n projectId,\n dataset,\n apiHost,\n apiVersion,\n useProjectHostname,\n requestTagPrefix,\n token: shouldIncludeDrafts ? browserToken : undefined,\n }}\n includeDrafts={shouldIncludeDrafts}\n action={action}\n onReconnect={onReconnect}\n onRestart={onRestart}\n onWelcome={onWelcome}\n onError={onError}\n onGoAway={onGoAway}\n requestTag={requestTag}\n refreshOnMount={refreshOnMount}\n refreshOnFocus={refreshOnFocus}\n refreshOnReconnect={refreshOnReconnect}\n />\n )\n }\n SanityLive.displayName = 'SanityLiveServerComponent'\n\n return {sanityFetch, SanityLive}\n}\n\nasync function resolveCookiePerspective(\n fallback: Exclude<ClientPerspective, 'raw'>,\n): 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 : fallback\n}\n"],"mappings":"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"}
@@ -8,4 +8,4 @@ declare function revalidateSyncTagsAction(unsafeTags: unknown): Promise<void>;
8
8
  */
9
9
  declare function refreshAction(): Promise<void>;
10
10
  export { refreshAction, revalidateSyncTagsAction };
11
- //# sourceMappingURL=index.default.d.ts.map
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":"AAUA;;;AAAA,iBAAsB,wBAAA,CAAyB,UAAA,YAAsB,OAAA;;AAyBrE;;;iBAAsB,aAAA,CAAA,GAAiB,OAAA"}
@@ -24,4 +24,4 @@ async function refreshAction() {
24
24
  }
25
25
  export { refreshAction, revalidateSyncTagsAction };
26
26
 
27
- //# sourceMappingURL=index.next-js.js.map
27
+ //# 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 {refresh, revalidateTag} from 'next/cache'\nimport {draftMode} from 'next/headers'\n\nimport {parseTags} from '#live/parseTags'\n\n/**\n * @alpha CAUTION: this is an internal action and does not follow semver. Using it directly is at your own risk.\n */\nexport async function revalidateSyncTagsAction(unsafeTags: unknown): Promise<void> {\n const {tags, prefixType} = parseTags(unsafeTags)\n if ((await draftMode()).isEnabled) {\n console.warn(\n `<SanityLive ${prefixType === 'drafts' ? 'includeDrafts ' : ''}/> action called in draft mode, cache is bypassed in draft mode so the refresh() function is called instead of updateTag()`,\n {tags},\n )\n refresh()\n return undefined\n }\n\n for (const tag of tags) {\n revalidateTag(tag, 'max')\n }\n\n // oxlint-disable-next-line no-console\n console.log(\n `<SanityLive ${prefixType === 'drafts' ? 'includeDrafts ' : ''}/> revalidated tags: ${tags.join(', ')} with cache profile \"max\" `,\n )\n}\n\n/**\n * Used by `<SanityLive onReconnect={refreshAction} onRestart={refreshAction} />`\n * @deprecated - refactor `onReconnect` and `onRestart` to support `() => 'refresh'`\n */\nexport async function refreshAction(): Promise<void> {\n refresh()\n}\n"],"mappings":";;;;;;;AAUA,eAAsB,yBAAyB,YAAoC;CACjF,MAAM,EAAC,MAAM,eAAc,UAAU,WAAW;AAChD,MAAK,MAAM,WAAW,EAAE,WAAW;AACjC,UAAQ,KACN,eAAe,eAAe,WAAW,mBAAmB,GAAG,6HAC/D,EAAC,MAAK,CACP;AACD,WAAS;AACT;;AAGF,MAAK,MAAM,OAAO,KAChB,eAAc,KAAK,MAAM;AAI3B,SAAQ,IACN,eAAe,eAAe,WAAW,mBAAmB,GAAG,uBAAuB,KAAK,KAAK,KAAK,CAAC,4BACvG;;;;;;AAOH,eAAsB,gBAA+B;AACnD,UAAS"}
package/dist/types.d.ts CHANGED
@@ -5,29 +5,47 @@ import { ClientPerspective, ClientReturn, ContentSourceMap, LiveEvent, QueryPara
5
5
  */
6
6
  type LivePerspective = Exclude<ClientPerspective, "raw">;
7
7
  /**
8
- * TODO: docs
8
+ * Fetches data through the configured Sanity client and returns the result
9
+ * together with the source map and cache tags that Sanity Live uses for
10
+ * targeted revalidation.
11
+ *
12
+ * Returned by `defineLive({strict: false})` and `defineLive({strict: undefined})`.
9
13
  */
10
14
  type DefinedFetchType = <const QueryString extends string>(options: {
15
+ /**
16
+ * GROQ query to execute.
17
+ */
11
18
  query: QueryString;
19
+ /**
20
+ * Parameters used by the GROQ query.
21
+ */
12
22
  params?: QueryParams | Promise<QueryParams>;
13
23
  /**
14
- * @defaultValue 'published'
24
+ * Content perspective used for the fetch.
25
+ *
26
+ * @defaultValue The configured client perspective, usually `'published'`.
15
27
  */
16
28
  perspective?: LivePerspective;
17
29
  /**
18
- * Enables stega encoding of the data, this is typically only used in draft mode in conjunction with `perspective: 'drafts'` and with `@sanity/visual-editing` setup.
30
+ * Enables stega encoding of the data. This is typically only used in draft
31
+ * mode with `perspective: 'drafts'` and `@sanity/visual-editing`.
32
+ *
19
33
  * @defaultValue `false`
20
34
  */
21
35
  stega?: boolean;
22
36
  /**
23
- * Custom cache tags that can be used with next's `updateTag` functions for custom `read-your-write` server actions,
24
- * for example a like button that uses client.mutate to update a document and then immediately shows the result.
37
+ * Additional cache tags to associate with this fetch.
38
+ *
39
+ * `sanityFetch` automatically adds Sanity Live sync tags for the query. Use
40
+ * this for custom tags that should also be invalidated by your own server
41
+ * actions, for example after a mutation that needs read-your-own-write UI.
25
42
  */
26
43
  tags?: string[];
27
44
  /**
28
- * This request tag is used to identify the request when viewing request logs from your Sanity Content Lake.
45
+ * Request tag used to identify the request in Sanity Content Lake logs.
46
+ *
29
47
  * @see https://www.sanity.io/docs/reference-api-request-tags
30
- * @defaultValue 'next-loader.fetch'
48
+ * @defaultValue `'next-loader.fetch'` or `'next-loader.fetch.cache-components'`
31
49
  */
32
50
  requestTag?: string;
33
51
  }) => Promise<{
@@ -36,125 +54,176 @@ type DefinedFetchType = <const QueryString extends string>(options: {
36
54
  tags: string[];
37
55
  }>;
38
56
  /**
39
- * TODO: docs
57
+ * Context passed to Sanity Live event handlers.
40
58
  */
41
59
  interface SanityLiveActionContext {
60
+ /**
61
+ * Whether the current `<SanityLive />` connection includes draft and content
62
+ * release version events.
63
+ */
42
64
  includeDrafts: boolean;
43
65
  }
44
66
  /**
45
- * TODO: docs
46
- * Has a default implementation tailed the nextjs env and config
67
+ * Server action invoked when Sanity Live receives a content-change message.
68
+ *
69
+ * The argument is the list of cache tags derived from the Live Content API
70
+ * event. The default action revalidates those tags. Return `'refresh'` from a
71
+ * custom action to also call `router.refresh()` in the browser.
47
72
  */
48
73
  type SanityLiveAction = (unsafeTags: unknown) => Promise<void | "refresh">;
49
74
  /**
50
- * TODO: docs
51
- * If not defined it'll throw the error during render instead, which will crash the react app
52
- * unless there's an <ErrorBoundary> surrounding the <SanityLive> component
75
+ * Handles connection, parsing, and event-processing errors.
76
+ *
77
+ * If no handler is provided, the error is thrown during render so it can be
78
+ * caught by the nearest React error boundary.
53
79
  */
54
80
  type SanityLiveOnError = (event: unknown, context: SanityLiveActionContext) => void | Promise<void>;
55
81
  /**
56
- * TODO: docs
57
- * Optional, logs console.info by default
82
+ * Handles the Live Content API `welcome` event.
83
+ *
84
+ * This event fires when the EventSource connection is established. Some export
85
+ * conditions log a connection message by default; pass `false` to
86
+ * `<SanityLive onWelcome={false} />` to disable that behavior.
58
87
  */
59
88
  type SanityLiveOnWelcome = (event: Extract<LiveEvent, {
60
89
  type: "welcome";
61
90
  }>, context: SanityLiveActionContext) => void | Promise<void>;
62
91
  /**
63
- * TODO: docs
92
+ * Handles the Live Content API `reconnect` event.
93
+ *
94
+ * The default behavior refreshes the route so Server Components can render with
95
+ * fresh data after reconnecting.
64
96
  */
65
97
  type SanityLiveOnReconnect = (event: Extract<LiveEvent, {
66
98
  type: "reconnect";
67
99
  }>, context: SanityLiveActionContext) => void | Promise<void>;
68
100
  /**
69
- * TODO: docs
101
+ * Handles the Live Content API `restart` event.
102
+ *
103
+ * The default behavior refreshes the route so Server Components can render with
104
+ * fresh data after the Live Content API restarts.
70
105
  */
71
106
  type SanityLiveOnRestart = (event: Extract<LiveEvent, {
72
107
  type: "restart";
73
108
  }>, context: SanityLiveActionContext) => void | Promise<void>;
74
109
  /**
75
- * TODO: docs
76
- * This event is fired when the API has hit the limit of concurrent connections, and the API will not deliver live events, in this case long polling intervals is a possible fallback strategy.
77
- * By default a message will be logged to the console, that creates a refresh interval of 30 seconds.
78
- * If you set your own event handler make sure you call `setPollingInterval` if you want to activate long-polling, otherwise content goes stale.
110
+ * Handles the Live Content API `goaway` event.
111
+ *
112
+ * This event means the API closed the live connection and will not deliver live
113
+ * events. This can happen when connection limits are reached. A polling refresh
114
+ * interval is the usual fallback; call `setPollingInterval()` from a custom
115
+ * handler to keep content fresh.
79
116
  */
80
117
  type SanityLiveOnGoaway = (event: Extract<LiveEvent, {
81
118
  type: "goaway";
82
119
  }>, context: SanityLiveActionContext, setPollingInterval: (interval: number) => void) => void | Promise<void>;
83
120
  interface DefinedLiveProps {
84
121
  /**
85
- * TODO: docs, settings this to `true` enables live events for draft content and requires `browserToken` to be set.
122
+ * Include draft and content release version events in the live connection.
123
+ *
124
+ * Set this to `true` when draft mode is enabled. A `browserToken` must be
125
+ * configured in `defineLive()` for draft events to be included.
126
+ *
127
+ * @defaultValue `false`
86
128
  */
87
129
  includeDrafts?: boolean;
88
130
  /**
89
- * TODO: docs
131
+ * Server action called for each content-change message from the Live Content
132
+ * API.
133
+ *
134
+ * The default action revalidates the cache tags produced by `sanityFetch`.
90
135
  */
91
136
  action?: SanityLiveAction;
92
137
  /**
93
- * TODO: docs
138
+ * Custom error handler. Pass `false` to disable custom handling and throw
139
+ * errors to the nearest React error boundary.
94
140
  */
95
141
  onError?: SanityLiveOnError | false;
96
142
  /**
97
- * TODO: docs
143
+ * Custom handler for the `welcome` event. Pass `false` to disable the default
144
+ * connection log.
98
145
  */
99
146
  onWelcome?: SanityLiveOnWelcome | false;
100
147
  /**
101
- * TODO: docs
148
+ * Custom handler for the `reconnect` event. Pass `false` to disable the
149
+ * default refresh behavior.
102
150
  */
103
151
  onReconnect?: SanityLiveOnReconnect | false;
104
152
  /**
105
- * TODO: docs
153
+ * Custom handler for the `restart` event. Pass `false` to disable the default
154
+ * refresh behavior.
106
155
  */
107
156
  onRestart?: SanityLiveOnRestart | false;
108
157
  /**
109
- *
158
+ * Custom handler for the `goaway` event. Pass `false` to disable the default
159
+ * long-polling fallback.
110
160
  */
111
161
  onGoAway?: SanityLiveOnGoaway | false;
112
162
  /**
113
- * Automatic refresh of RSC when the component <SanityLive /> is mounted.
163
+ * Refresh Server Components once when `<SanityLive />` mounts.
164
+ *
165
+ * This can close the gap between the initial server render and the browser
166
+ * establishing the live EventSource connection.
167
+ *
114
168
  * @defaultValue `false`
115
169
  */
116
170
  refreshOnMount?: boolean;
117
171
  /**
118
- * Automatically refresh when window gets focused
172
+ * Refresh Server Components when the page becomes visible or the window
173
+ * regains focus.
174
+ *
119
175
  * @defaultValue `false`
120
176
  */
121
177
  refreshOnFocus?: boolean;
122
178
  /**
123
- * Automatically refresh when the browser regains a network connection (via navigator.onLine)
124
- * @defaultValue `false`
179
+ * Refresh Server Components when the browser regains a network connection.
125
180
  */
126
181
  refreshOnReconnect?: boolean;
127
182
  /**
128
- * This request tag is used to identify the request when viewing request logs from your Sanity Content Lake.
183
+ * Request tag used to identify the live EventSource request in Sanity Content
184
+ * Lake logs.
185
+ *
129
186
  * @see https://www.sanity.io/docs/reference-api-request-tags
130
- * @defaultValue 'next-loader.live'|'next-loader.live.cache-components'
187
+ * @defaultValue `'next-loader.live'` or `'next-loader.live.cache-components'`
131
188
  */
132
189
  requestTag?: string;
133
190
  }
134
191
  interface DefineLiveOptions {
135
192
  /**
136
- * Required for `fetch()` and `<Live>` to work
193
+ * Sanity client used by `sanityFetch()` and `<SanityLive />`.
137
194
  */
138
195
  client: SanityClient;
139
196
  /**
140
- * Optional. If provided then the token needs to have permissions to query documents with `drafts.` prefixes in order for `perspective: 'drafts'` to work.
141
- * This token is never shared with the browser, unless you reuse it in `browserToken`..
197
+ * Token used by the server to query drafts and content release versions.
198
+ *
199
+ * This token is never shared with the browser unless you also pass it as
200
+ * `browserToken`.
142
201
  */
143
202
  serverToken?: string | false;
144
203
  /**
145
- * Optional. This token is shared with the browser when `<Live>` is given a `perspective` prop other than `"published"`, and should only have access to query published documents.
146
- * It is used to setup a `Live Draft Content` EventSource connection, and enables live previewing drafts stand-alone, outside of Presentation Tool.
204
+ * Token shared with the browser when `<SanityLive includeDrafts />` opens a
205
+ * draft-capable live connection.
206
+ *
207
+ * Use a browser-safe token with the minimum read permissions needed for live
208
+ * previewing drafts outside Presentation Tool.
147
209
  */
148
210
  browserToken?: string | false;
149
211
  /**
150
- * Optional. Include stega encoding when draft mode is enabled.
151
- * @deprecated This option is deprecated, as it does not have an effect when `cacheComponents: true`
152
- * @defaultValue `true`
212
+ * Include stega encoding automatically when draft mode is enabled.
213
+ *
214
+ * @deprecated This option does not affect the `next-js` export condition used
215
+ * with `cacheComponents: true`. Pass `stega` to `sanityFetch()` instead.
216
+ * @defaultValue `true`
153
217
  */
154
218
  stega?: boolean;
155
219
  /**
156
- * When `true`, requires explicit `includeDrafts` on `<SanityLive>` and explicit `perspective`/`stega` on `sanityFetch`.
157
- * Use this to prepare for migrating to `cacheComponents: true` while still using `cacheComponents: false`.
220
+ * Require explicit live-content options at every call site.
221
+ *
222
+ * When `true`, `includeDrafts` is required on `<SanityLive />` and
223
+ * `perspective`/`stega` are required on `sanityFetch()`. This matches the
224
+ * explicit data flow needed inside Cache Components, where `draftMode()` and
225
+ * `cookies()` must be resolved outside `'use cache'` boundaries.
226
+ *
158
227
  * @defaultValue `false`
159
228
  */
160
229
  strict?: boolean;
@@ -182,5 +251,5 @@ type StrictDefinedFetchType = <const QueryString extends string>(options: {
182
251
  sourceMap: ContentSourceMap | null;
183
252
  tags: string[];
184
253
  }>;
185
- export { SanityLiveAction as a, SanityLiveOnReconnect as c, StrictDefinedFetchType as d, StrictDefinedLiveProps as f, LivePerspective as i, SanityLiveOnRestart as l, DefinedFetchType as n, SanityLiveOnError as o, DefinedLiveProps as r, SanityLiveOnGoaway as s, DefineLiveOptions as t, SanityLiveOnWelcome as u };
254
+ export { SanityLiveAction as a, SanityLiveOnGoaway as c, SanityLiveOnWelcome as d, StrictDefinedFetchType as f, LivePerspective as i, SanityLiveOnReconnect as l, DefinedFetchType as n, SanityLiveActionContext as o, StrictDefinedLiveProps as p, DefinedLiveProps as r, SanityLiveOnError as s, DefineLiveOptions as t, SanityLiveOnRestart as u };
186
255
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../src/live/shared/types.ts"],"mappings":";;AAcA;;;KAAY,eAAA,GAAkB,OAAA,CAAQ,iBAAA;;AAKtC;;KAAY,gBAAA,sCAAsD,OAAA;EAChE,KAAA,EAAO,WAAA;EACP,MAAA,GAAS,WAAA,GAAc,OAAA,CAAQ,WAAA;;;;EAI/B,WAAA,GAAc,eAAA;;;;;EAKd,KAAA;;;;;EAKA,IAAA;;;;;;EAMA,UAAA;AAAA,MACI,OAAA;EACJ,IAAA,EAAM,YAAA,CAAa,WAAA;EACnB,SAAA,EAAW,gBAAA;EACX,IAAA;AAAA;;;;UAMe,uBAAA;EACf,aAAA;AAAA;AADF;;;;AAAA,KAQY,gBAAA,IAAoB,UAAA,cAAwB,OAAA;AAAxD;;;;;AAAA,KAMY,iBAAA,IACV,KAAA,WACA,OAAA,EAAS,uBAAA,YACC,OAAA;;;;;KAKA,mBAAA,IACV,KAAA,EAAO,OAAA,CAAQ,SAAA;EAAY,IAAA;AAAA,IAC3B,OAAA,EAAS,uBAAA,YACC,OAAA;;;AAHZ;KAOY,qBAAA,IACV,KAAA,EAAO,OAAA,CAAQ,SAAA;EAAY,IAAA;AAAA,IAC3B,OAAA,EAAS,uBAAA,YACC,OAAA;;;;KAIA,mBAAA,IACV,KAAA,EAAO,OAAA,CAAQ,SAAA;EAAY,IAAA;AAAA,IAC3B,OAAA,EAAS,uBAAA,YACC,OAAA;;;;;;;KAOA,kBAAA,IACV,KAAA,EAAO,OAAA,CAAQ,SAAA;EAAY,IAAA;AAAA,IAC3B,OAAA,EAAS,uBAAA,EACT,kBAAA,GAAqB,QAAA,6BACX,OAAA;AAAA,UAOK,gBAAA;;;;EAIf,aAAA;;;;EAIA,MAAA,GAAS,gBAAA;;;;EAIT,OAAA,GAAU,iBAAA;EAjCZ;;;EAqCE,SAAA,GAAY,mBAAA;;;;EAIZ,WAAA,GAAc,qBAAA;EAtCJ;;;EA0CV,SAAA,GAAY,mBAAA;;;;EAIZ,QAAA,GAAW,kBAAA;;;AAvCb;;EA6CE,cAAA;;;;;EAKA,cAAA;EA9CU;;;;EAmDV,kBAAA;;;;;;EAOA,UAAA;AAAA;AAAA,UAGe,iBAAA;EAtDA;;;EA0Df,MAAA,EAAQ,YAAA;;;;;EAKR,WAAA;EAnCW;;;;EAwCX,YAAA;;;;;;EAMA,KAAA;;;;;;EAMA,MAAA;AAAA;;;AA1BF;;UAiCiB,sBAAA,SAA+B,IAAA,CAAK,gBAAA;EACnD,aAAA;AAAA;;;;;KAOU,sBAAA,sCAA4D,OAAA;EACtE,KAAA,EAAO,WAAA;EACP,MAAA,GAAS,WAAA,GAAc,OAAA,CAAQ,WAAA;EAC/B,WAAA,EAAa,eAAA;EACb,KAAA;EACA,IAAA;EACA,UAAA;AAAA,MACI,OAAA;EACJ,IAAA,EAAM,YAAA,CAAa,WAAA;EACnB,SAAA,EAAW,gBAAA;EACX,IAAA;AAAA"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../src/live/shared/types.ts"],"mappings":";;AAcA;;;KAAY,eAAA,GAAkB,OAAA,CAAQ,iBAAA;;AAStC;;;;;;KAAY,gBAAA,sCAAsD,OAAA;;;;EAIhE,KAAA,EAAO,WAAA;;;;EAIP,MAAA,GAAS,WAAA,GAAc,OAAA,CAAQ,WAAA;;;;;;EAM/B,WAAA,GAAc,eAAA;;;;;;;EAOd,KAAA;;;;;;;;EAQA,IAAA;EAiBF;;;;;AAeA;EAzBE,UAAA;AAAA,MACI,OAAA;EACJ,IAAA,EAAM,YAAA,CAAa,WAAA;EACnB,SAAA,EAAW,gBAAA;EACX,IAAA;AAAA;;;;UAMe,uBAAA;;;;;EAKf,aAAA;AAAA;;;;;;;;KAUU,gBAAA,IAAoB,UAAA,cAAwB,OAAA;;;;;;;KAO5C,iBAAA,IACV,KAAA,WACA,OAAA,EAAS,uBAAA,YACC,OAAA;;AAkBZ;;;;;;KAVY,mBAAA,IACV,KAAA,EAAO,OAAA,CAAQ,SAAA;EAAY,IAAA;AAAA,IAC3B,OAAA,EAAS,uBAAA,YACC,OAAA;;;;;;;KAOA,qBAAA,IACV,KAAA,EAAO,OAAA,CAAQ,SAAA;EAAY,IAAA;AAAA,IAC3B,OAAA,EAAS,uBAAA,YACC,OAAA;AAOZ;;;;;;AAAA,KAAY,mBAAA,IACV,KAAA,EAAO,OAAA,CAAQ,SAAA;EAAY,IAAA;AAAA,IAC3B,OAAA,EAAS,uBAAA,YACC,OAAA;;;;;;;;;KASA,kBAAA,IACV,KAAA,EAAO,OAAA,CAAQ,SAAA;EAAY,IAAA;AAAA,IAC3B,OAAA,EAAS,uBAAA,EACT,kBAAA,GAAqB,QAAA,6BACX,OAAA;AAAA,UAOK,gBAAA;;;;;;;;;EASf,aAAA;;;;;AATF;;EAgBE,MAAA,GAAS,gBAAA;;;;;EAKT,OAAA,GAAU,iBAAA;;;;;EAKV,SAAA,GAAY,mBAAA;;;;;EAKZ,WAAA,GAAc,qBAAA;;;;;EAKd,SAAA,GAAY,mBAAA;;;;;EAKZ,QAAA,GAAW,kBAAA;;;AAiCb;;;;;;EAvBE,cAAA;;;;;;AAoEF;EA7DE,cAAA;;;;EAIA,kBAAA;;;;AAiEF;;;;EAxDE,UAAA;AAAA;AAAA,UAGe,iBAAA;;;;EAIf,MAAA,EAAQ,YAAA;;;;;;;EAOR,WAAA;;;;;;;;EAQA,YAAA;;;;;;;;EAQA,KAAA;;;;;;;;;;;EAWA,MAAA;AAAA;;;;;UAOe,sBAAA,SAA+B,IAAA,CAAK,gBAAA;EACnD,aAAA;AAAA;;;;;KAOU,sBAAA,sCAA4D,OAAA;EACtE,KAAA,EAAO,WAAA;EACP,MAAA,GAAS,WAAA,GAAc,OAAA,CAAQ,WAAA;EAC/B,WAAA,EAAa,eAAA;EACb,KAAA;EACA,IAAA;EACA,UAAA;AAAA,MACI,OAAA;EACJ,IAAA,EAAM,YAAA,CAAa,WAAA;EACnB,SAAA,EAAW,gBAAA;EACX,IAAA;AAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-sanity",
3
- "version": "13.0.0-cache-components.42",
3
+ "version": "13.0.0-cache-components.43",
4
4
  "description": "Sanity.io toolkit for Next.js",
5
5
  "keywords": [
6
6
  "live",
@@ -48,10 +48,7 @@
48
48
  },
49
49
  "./live/cache-life": "./dist/live/cache-life.js",
50
50
  "./live/client-components": "./dist/live/client-components/index.js",
51
- "./live/server-actions": {
52
- "next-js": "./dist/live/server-actions/index.next-js.js",
53
- "default": "./dist/live/server-actions/index.default.js"
54
- },
51
+ "./live/server-actions": "./dist/live/server-actions/index.js",
55
52
  "./studio": "./dist/studio/index.js",
56
53
  "./studio/client-component": "./dist/studio/client-component/index.js",
57
54
  "./visual-editing": "./dist/visual-editing/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.default.d.ts","names":[],"sources":["../../../src/live/server-actions/index.default.ts"],"mappings":"AAUA;;;AAAA,iBAAsB,wBAAA,CAAyB,UAAA,YAAsB,OAAA;;AAyBrE;;;iBAAsB,aAAA,CAAA,GAAiB,OAAA"}