next-sanity 13.0.0-cache-components.48 → 13.0.0-cache-components.50

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,6 +1,6 @@
1
1
  import { n as NextStudioLayout, t as NextStudioNoScript } from "./NextStudioNoScript.js";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
- import { useMemo, useSyncExternalStore } from "react";
3
+ import { useDeferredValue, useMemo, useSyncExternalStore } from "react";
4
4
  import { Studio } from "sanity";
5
5
  import { createHashHistory } from "history";
6
6
  /** @internal */
@@ -43,7 +43,7 @@ function createHashHistoryForStudio() {
43
43
  }
44
44
  /** @internal */
45
45
  function useIsMounted() {
46
- return useSyncExternalStore(emptySubscribe, () => true, () => false);
46
+ return useDeferredValue(useSyncExternalStore(emptySubscribe, () => true, () => false), false);
47
47
  }
48
48
  const emptySubscribe = () => () => {};
49
49
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"NextStudio.js","names":[],"sources":["../src/studio/client-component/createHashHistoryForStudio.ts","../src/studio/client-component/useIsMounted.ts","../src/studio/client-component/NextStudio.tsx"],"sourcesContent":["// oxlint-disable unbound-method\nimport {createHashHistory, type History, type Listener} from 'history'\n\n/** @internal */\nexport function createHashHistoryForStudio(): History {\n const history = createHashHistory()\n return {\n get action() {\n return history.action\n },\n get location() {\n return history.location\n },\n get createHref() {\n return history.createHref\n },\n get push() {\n return history.push\n },\n get replace() {\n return history.replace\n },\n get go() {\n return history.go\n },\n get back() {\n return history.back\n },\n get forward() {\n return history.forward\n },\n get block() {\n return history.block\n },\n // Overriding listen to workaround a problem where native history provides history.listen(location => void), but the npm package is history.listen(({action, location}) => void)\n listen(listener: Listener) {\n // return history.listen(({ action, location }) => {\n return history.listen(({location}) => {\n // console.debug('history.listen', action, location)\n // @ts-expect-error -- working around a bug? in studio\n listener(location)\n })\n },\n }\n}\n","import {useSyncExternalStore} from 'react'\n\n/** @internal */\nexport function useIsMounted(): boolean {\n return useSyncExternalStore(\n emptySubscribe,\n () => true,\n () => false,\n )\n}\nconst emptySubscribe = () => () => {}\n","import {useMemo} from 'react'\nimport {Studio, type StudioProps} from 'sanity'\n\nimport {NextStudioLayout} from '../NextStudioLayout'\nimport {NextStudioNoScript} from '../NextStudioNoScript'\nimport {createHashHistoryForStudio} from './createHashHistoryForStudio'\nimport {useIsMounted} from './useIsMounted'\n\n/** @public */\nexport interface NextStudioProps extends StudioProps {\n children?: React.ReactNode\n /**\n * Render the <noscript> tag\n * @defaultValue true\n * @alpha\n */\n unstable__noScript?: boolean\n /**\n * The 'hash' option is new feature that is not yet stable for production, but is available for testing and its API won't change in a breaking way.\n * If 'hash' doesn't work for you, or if you want to use a memory based history, you can use the `unstable_history` prop instead.\n * @alpha\n * @defaultValue 'browser'\n */\n history?: 'browser' | 'hash'\n}\n/**\n * Override how the Studio renders by passing children.\n * This is useful for advanced use cases where you're using StudioProvider and StudioLayout instead of Studio:\n * ```\n * import {StudioProvider, StudioLayout} from 'sanity'\n * import {NextStudio} from 'next-sanity/studio'\n * <NextStudio config={config}>\n * <StudioProvider config={config}>\n * <CustomComponentThatUsesContextFromStudioProvider />\n * <StudioLayout />\n * </StudioProvider>\n * </NextStudio>\n * ```\n * @public\n */\nexport default function NextStudioComponent({\n children,\n config,\n unstable__noScript = true,\n scheme,\n history,\n ...props\n}: NextStudioProps): React.JSX.Element {\n const isMounted = useIsMounted()\n const unstableHistory = useMemo<typeof props.unstable_history>(() => {\n if (props.unstable_history && history) {\n throw new Error('Cannot use both `unstable_history` and `history` props at the same time')\n }\n\n if (isMounted && history === 'hash') {\n return createHashHistoryForStudio()\n }\n return props.unstable_history\n }, [history, isMounted, props.unstable_history])\n\n return (\n <>\n {unstable__noScript && <NextStudioNoScript />}\n <NextStudioLayout>\n {history === 'hash' && !isMounted\n ? null\n : children || (\n <Studio\n config={config}\n scheme={scheme}\n unstable_globalStyles\n {...props}\n unstable_history={unstableHistory}\n />\n )}\n </NextStudioLayout>\n </>\n )\n}\n"],"mappings":";;;;;;AAIA,SAAgB,6BAAsC;CACpD,MAAM,UAAU,mBAAmB;AACnC,QAAO;EACL,IAAI,SAAS;AACX,UAAO,QAAQ;;EAEjB,IAAI,WAAW;AACb,UAAO,QAAQ;;EAEjB,IAAI,aAAa;AACf,UAAO,QAAQ;;EAEjB,IAAI,OAAO;AACT,UAAO,QAAQ;;EAEjB,IAAI,UAAU;AACZ,UAAO,QAAQ;;EAEjB,IAAI,KAAK;AACP,UAAO,QAAQ;;EAEjB,IAAI,OAAO;AACT,UAAO,QAAQ;;EAEjB,IAAI,UAAU;AACZ,UAAO,QAAQ;;EAEjB,IAAI,QAAQ;AACV,UAAO,QAAQ;;EAGjB,OAAO,UAAoB;AAEzB,UAAO,QAAQ,QAAQ,EAAC,eAAc;AAGpC,aAAS,SAAS;KAClB;;EAEL;;;ACxCH,SAAgB,eAAwB;AACtC,QAAO,qBACL,sBACM,YACA,MACP;;AAEH,MAAM,6BAA6B;;;;;;;;;;;;;;;;AC8BnC,SAAwB,oBAAoB,EAC1C,UACA,QACA,qBAAqB,MACrB,QACA,SACA,GAAG,SACkC;CACrC,MAAM,YAAY,cAAc;CAChC,MAAM,kBAAkB,cAA6C;AACnE,MAAI,MAAM,oBAAoB,QAC5B,OAAM,IAAI,MAAM,0EAA0E;AAG5F,MAAI,aAAa,YAAY,OAC3B,QAAO,4BAA4B;AAErC,SAAO,MAAM;IACZ;EAAC;EAAS;EAAW,MAAM;EAAiB,CAAC;AAEhD,QACE,qBAAA,UAAA,EAAA,UAAA,CACG,sBAAsB,oBAAC,oBAAD,EAAsB,CAAA,EAC7C,oBAAC,kBAAD,EAAA,UACG,YAAY,UAAU,CAAC,YACpB,OACA,YACE,oBAAC,QAAD;EACU;EACA;EACR,uBAAA;EACA,GAAI;EACJ,kBAAkB;EAClB,CAAA,EAES,CAAA,CAClB,EAAA,CAAA"}
1
+ {"version":3,"file":"NextStudio.js","names":[],"sources":["../src/studio/client-component/createHashHistoryForStudio.ts","../src/studio/client-component/useIsMounted.ts","../src/studio/client-component/NextStudio.tsx"],"sourcesContent":["// oxlint-disable unbound-method\nimport {createHashHistory, type History, type Listener} from 'history'\n\n/** @internal */\nexport function createHashHistoryForStudio(): History {\n const history = createHashHistory()\n return {\n get action() {\n return history.action\n },\n get location() {\n return history.location\n },\n get createHref() {\n return history.createHref\n },\n get push() {\n return history.push\n },\n get replace() {\n return history.replace\n },\n get go() {\n return history.go\n },\n get back() {\n return history.back\n },\n get forward() {\n return history.forward\n },\n get block() {\n return history.block\n },\n // Overriding listen to workaround a problem where native history provides history.listen(location => void), but the npm package is history.listen(({action, location}) => void)\n listen(listener: Listener) {\n // return history.listen(({ action, location }) => {\n return history.listen(({location}) => {\n // console.debug('history.listen', action, location)\n // @ts-expect-error -- working around a bug? in studio\n listener(location)\n })\n },\n }\n}\n","import {useDeferredValue, useSyncExternalStore} from 'react'\n\n/** @internal */\nexport function useIsMounted(): boolean {\n return useDeferredValue(\n useSyncExternalStore(\n emptySubscribe,\n () => true,\n () => false,\n ),\n false,\n )\n}\nconst emptySubscribe = () => () => {}\n","import {useMemo} from 'react'\nimport {Studio, type StudioProps} from 'sanity'\n\nimport {NextStudioLayout} from '../NextStudioLayout'\nimport {NextStudioNoScript} from '../NextStudioNoScript'\nimport {createHashHistoryForStudio} from './createHashHistoryForStudio'\nimport {useIsMounted} from './useIsMounted'\n\n/** @public */\nexport interface NextStudioProps extends StudioProps {\n children?: React.ReactNode\n /**\n * Render the <noscript> tag\n * @defaultValue true\n * @alpha\n */\n unstable__noScript?: boolean\n /**\n * The 'hash' option is new feature that is not yet stable for production, but is available for testing and its API won't change in a breaking way.\n * If 'hash' doesn't work for you, or if you want to use a memory based history, you can use the `unstable_history` prop instead.\n * @alpha\n * @defaultValue 'browser'\n */\n history?: 'browser' | 'hash'\n}\n/**\n * Override how the Studio renders by passing children.\n * This is useful for advanced use cases where you're using StudioProvider and StudioLayout instead of Studio:\n * ```\n * import {StudioProvider, StudioLayout} from 'sanity'\n * import {NextStudio} from 'next-sanity/studio'\n * <NextStudio config={config}>\n * <StudioProvider config={config}>\n * <CustomComponentThatUsesContextFromStudioProvider />\n * <StudioLayout />\n * </StudioProvider>\n * </NextStudio>\n * ```\n * @public\n */\nexport default function NextStudioComponent({\n children,\n config,\n unstable__noScript = true,\n scheme,\n history,\n ...props\n}: NextStudioProps): React.JSX.Element {\n const isMounted = useIsMounted()\n const unstableHistory = useMemo<typeof props.unstable_history>(() => {\n if (props.unstable_history && history) {\n throw new Error('Cannot use both `unstable_history` and `history` props at the same time')\n }\n\n if (isMounted && history === 'hash') {\n return createHashHistoryForStudio()\n }\n return props.unstable_history\n }, [history, isMounted, props.unstable_history])\n\n return (\n <>\n {unstable__noScript && <NextStudioNoScript />}\n <NextStudioLayout>\n {history === 'hash' && !isMounted\n ? null\n : children || (\n <Studio\n config={config}\n scheme={scheme}\n unstable_globalStyles\n {...props}\n unstable_history={unstableHistory}\n />\n )}\n </NextStudioLayout>\n </>\n )\n}\n"],"mappings":";;;;;;AAIA,SAAgB,6BAAsC;CACpD,MAAM,UAAU,mBAAmB;AACnC,QAAO;EACL,IAAI,SAAS;AACX,UAAO,QAAQ;;EAEjB,IAAI,WAAW;AACb,UAAO,QAAQ;;EAEjB,IAAI,aAAa;AACf,UAAO,QAAQ;;EAEjB,IAAI,OAAO;AACT,UAAO,QAAQ;;EAEjB,IAAI,UAAU;AACZ,UAAO,QAAQ;;EAEjB,IAAI,KAAK;AACP,UAAO,QAAQ;;EAEjB,IAAI,OAAO;AACT,UAAO,QAAQ;;EAEjB,IAAI,UAAU;AACZ,UAAO,QAAQ;;EAEjB,IAAI,QAAQ;AACV,UAAO,QAAQ;;EAGjB,OAAO,UAAoB;AAEzB,UAAO,QAAQ,QAAQ,EAAC,eAAc;AAGpC,aAAS,SAAS;KAClB;;EAEL;;;ACxCH,SAAgB,eAAwB;AACtC,QAAO,iBACL,qBACE,sBACM,YACA,MACP,EACD,MACD;;AAEH,MAAM,6BAA6B;;;;;;;;;;;;;;;;AC2BnC,SAAwB,oBAAoB,EAC1C,UACA,QACA,qBAAqB,MACrB,QACA,SACA,GAAG,SACkC;CACrC,MAAM,YAAY,cAAc;CAChC,MAAM,kBAAkB,cAA6C;AACnE,MAAI,MAAM,oBAAoB,QAC5B,OAAM,IAAI,MAAM,0EAA0E;AAG5F,MAAI,aAAa,YAAY,OAC3B,QAAO,4BAA4B;AAErC,SAAO,MAAM;IACZ;EAAC;EAAS;EAAW,MAAM;EAAiB,CAAC;AAEhD,QACE,qBAAA,UAAA,EAAA,UAAA,CACG,sBAAsB,oBAAC,oBAAD,EAAsB,CAAA,EAC7C,oBAAC,kBAAD,EAAA,UACG,YAAY,UAAU,CAAC,YACpB,OACA,YACE,oBAAC,QAAD;EACU;EACA;EACR,uBAAA;EACA,GAAI;EACJ,kBAAkB;EAClB,CAAA,EAES,CAAA,CAClB,EAAA,CAAA"}
@@ -128,15 +128,12 @@ function VisualEditing(props) {
128
128
  routerRef.current.refresh();
129
129
  break;
130
130
  case "mutation":
131
- if (payload.livePreviewEnabled) {
132
- console.debug("Live preview is setup, mutation is skipped assuming its handled by the live preview");
133
- return false;
134
- }
131
+ if (payload.livePreviewEnabled) return false;
135
132
  routerRef.current.refresh();
136
133
  break;
137
134
  default: throw new Error("Unknown refresh source", { cause: payload });
138
135
  }
139
- return false;
136
+ return new Promise((resolve) => setTimeout(resolve, 1e3));
140
137
  }, []);
141
138
  return /* @__PURE__ */ jsx(VisualEditing$1, {
142
139
  plugins,
@@ -1 +1 @@
1
- {"version":3,"file":"VisualEditing.js","names":["VisualEditingComponent"],"sources":["../src/visual-editing/client-component/utils.ts","../src/visual-editing/client-component/VisualEditing.tsx"],"sourcesContent":["/**\n * From: https://github.com/vercel/next.js/blob/5469e6427b54ab7e9876d4c85b47f9c3afdc5c1f/packages/next/src/shared/lib/router/utils/path-has-prefix.ts#L10-L17\n * Checks if a given path starts with a given prefix. It ensures it matches\n * exactly without containing extra chars. e.g. prefix /docs should replace\n * for /docs, /docs/, /docs/a but not /docsss\n * @param path The path to check.\n * @param prefix The prefix to check against.\n */\nfunction pathHasPrefix(path: string, prefix: string): boolean {\n if (typeof path !== 'string') {\n return false\n }\n\n const {pathname} = parsePath(path)\n return pathname === prefix || pathname.startsWith(`${prefix}/`)\n}\n\n/**\n * From: https://github.com/vercel/next.js/blob/5469e6427b54ab7e9876d4c85b47f9c3afdc5c1f/packages/next/src/shared/lib/router/utils/parse-path.ts#L6-L22\n * Given a path this function will find the pathname, query and hash and return\n * them. This is useful to parse full paths on the client side.\n * @param path A path to parse e.g. /foo/bar?id=1#hash\n */\nfunction parsePath(path: string): {\n pathname: string\n query: string\n hash: string\n} {\n const hashIndex = path.indexOf('#')\n const queryIndex = path.indexOf('?')\n const hasQuery = queryIndex > -1 && (hashIndex < 0 || queryIndex < hashIndex)\n\n if (hasQuery || hashIndex > -1) {\n return {\n pathname: path.substring(0, hasQuery ? queryIndex : hashIndex),\n query: hasQuery ? path.substring(queryIndex, hashIndex > -1 ? hashIndex : undefined) : '',\n hash: hashIndex > -1 ? path.slice(hashIndex) : '',\n }\n }\n\n return {pathname: path, query: '', hash: ''}\n}\n\n/**\n * From: https://github.com/vercel/next.js/blob/5469e6427b54ab7e9876d4c85b47f9c3afdc5c1f/packages/next/src/shared/lib/router/utils/add-path-prefix.ts#L3C1-L14C2\n * Adds the provided prefix to the given path. It first ensures that the path\n * is indeed starting with a slash.\n */\nexport function addPathPrefix(path: string, prefix?: string): string {\n if (!path.startsWith('/') || !prefix) {\n return path\n }\n // If the path is exactly '/' then return just the prefix\n if (path === '/' && prefix) {\n return prefix\n }\n\n const {pathname, query, hash} = parsePath(path)\n return `${prefix}${pathname}${query}${hash}`\n}\n\n/**\n * From: https://github.com/vercel/next.js/blob/5469e6427b54ab7e9876d4c85b47f9c3afdc5c1f/packages/next/src/shared/lib/router/utils/remove-path-prefix.ts#L3-L39\n * Given a path and a prefix it will remove the prefix when it exists in the\n * given path. It ensures it matches exactly without containing extra chars\n * and if the prefix is not there it will be noop.\n *\n * @param path The path to remove the prefix from.\n * @param prefix The prefix to be removed.\n */\nexport function removePathPrefix(path: string, prefix: string): string {\n // If the path doesn't start with the prefix we can return it as is. This\n // protects us from situations where the prefix is a substring of the path\n // prefix such as:\n //\n // For prefix: /blog\n //\n // /blog -> true\n // /blog/ -> true\n // /blog/1 -> true\n // /blogging -> false\n // /blogging/ -> false\n // /blogging/1 -> false\n if (!pathHasPrefix(path, prefix)) {\n return path\n }\n\n // Remove the prefix from the path via slicing.\n const withoutPrefix = path.slice(prefix.length)\n\n // If the path without the prefix starts with a `/` we can return it as is.\n if (withoutPrefix.startsWith('/')) {\n return withoutPrefix\n }\n\n // If the path without the prefix doesn't start with a `/` we need to add it\n // back to the path to make sure it's a valid path.\n return `/${withoutPrefix}`\n}\n\n/**\n * From: https://github.com/vercel/next.js/blob/dfe7fc03e2268e7cb765dce6a89e02c831c922d5/packages/next/src/client/normalize-trailing-slash.ts#L16\n * Normalizes the trailing slash of a path according to the `trailingSlash` option\n * in `next.config.js`.\n */\nexport const normalizePathTrailingSlash = (path: string, trailingSlash: boolean): string => {\n const {pathname, query, hash} = parsePath(path)\n if (trailingSlash) {\n if (pathname.endsWith('/')) {\n return `${pathname}${query}${hash}`\n }\n return `${pathname}/${query}${hash}`\n }\n\n return `${removeTrailingSlash(pathname)}${query}${hash}`\n}\n\n/**\n * From: https://github.com/vercel/next.js/blob/dfe7fc03e2268e7cb765dce6a89e02c831c922d5/packages/next/src/shared/lib/router/utils/remove-trailing-slash.ts#L8\n * Removes the trailing slash for a given route or page path. Preserves the\n * root page. Examples:\n * - `/foo/bar/` -> `/foo/bar`\n * - `/foo/bar` -> `/foo/bar`\n * - `/` -> `/`\n */\nfunction removeTrailingSlash(route: string) {\n return route.replace(/\\/$/, '') || '/'\n}\n","import {\n type HistoryAdapter,\n type HistoryAdapterNavigate,\n type HistoryRefresh,\n VisualEditing as VisualEditingComponent,\n type VisualEditingOptions,\n} from '@sanity/visual-editing/react'\nimport {usePathname, useRouter, useSearchParams} from 'next/navigation'\nimport {useCallback, useEffect, useMemo, useRef, useState} from 'react'\n\nimport {addPathPrefix, normalizePathTrailingSlash, removePathPrefix} from './utils'\n\n/**\n * @public\n */\nexport interface VisualEditingProps extends Omit<VisualEditingOptions, 'history'> {\n /**\n * @deprecated The histoy adapter is already implemented\n */\n history?: never\n /**\n * If next.config.ts is configured with a basePath we try to configure it automatically,\n * you can disable this by setting basePath to ''.\n * @example basePath=\"/my-custom-base-path\"\n * @alpha experimental and may change without notice\n * @defaultValue process.env.__NEXT_ROUTER_BASEPATH || ''\n */\n basePath?: string\n /**\n * If next.config.ts is configured with a `trailingSlash` we try to detect it automatically,\n * it can be controlled manually by passing a boolean.\n * @example trailingSlash={true}\n * @alpha experimental and may change without notice\n * @defaultValue Boolean(process.env.__NEXT_TRAILING_SLASH)\n */\n trailingSlash?: boolean\n}\n\nexport default function VisualEditing(props: VisualEditingProps): React.JSX.Element | null {\n const {\n basePath = '',\n plugins,\n components,\n refresh,\n trailingSlash = false,\n zIndex,\n onPerspectiveChange,\n } = props\n\n const router = useRouter()\n const routerRef = useRef(router)\n const [navigate, setNavigate] = useState<HistoryAdapterNavigate | undefined>()\n\n useEffect(() => {\n routerRef.current = router\n }, [router])\n\n const history = useMemo<HistoryAdapter>(\n () => ({\n subscribe: (_navigate) => {\n setNavigate(() => _navigate)\n return () => setNavigate(undefined)\n },\n update: (update) => {\n switch (update.type) {\n case 'push':\n return routerRef.current.push(removePathPrefix(update.url, basePath))\n case 'pop':\n return routerRef.current.back()\n case 'replace':\n return routerRef.current.replace(removePathPrefix(update.url, basePath))\n default:\n throw new Error(`Unknown update type`, {cause: update})\n }\n },\n }),\n [basePath],\n )\n\n const pathname = usePathname()\n const searchParams = useSearchParams()\n useEffect(() => {\n if (navigate) {\n navigate({\n type: 'push',\n url: normalizePathTrailingSlash(\n addPathPrefix(\n `${pathname}${searchParams?.size ? `?${searchParams.toString()}` : ''}`,\n basePath,\n ),\n trailingSlash,\n ),\n })\n }\n }, [basePath, navigate, pathname, searchParams, trailingSlash])\n\n const handleRefresh = useCallback((payload: HistoryRefresh): false => {\n switch (payload.source) {\n case 'manual':\n routerRef.current.refresh()\n break\n case 'mutation': {\n if (payload.livePreviewEnabled) {\n // oxlint-disable-next-line no-console\n console.debug(\n 'Live preview is setup, mutation is skipped assuming its handled by the live preview',\n )\n return false\n }\n routerRef.current.refresh()\n break\n }\n default:\n throw new Error('Unknown refresh source', {cause: payload})\n }\n return false\n }, [])\n\n return (\n <VisualEditingComponent\n plugins={plugins}\n components={components}\n history={history}\n portal\n refresh={refresh ?? handleRefresh}\n onPerspectiveChange={onPerspectiveChange}\n zIndex={zIndex}\n />\n )\n}\n"],"mappings":";;;;;;;;;;;;AAQA,SAAS,cAAc,MAAc,QAAyB;AAC5D,KAAI,OAAO,SAAS,SAClB,QAAO;CAGT,MAAM,EAAC,aAAY,UAAU,KAAK;AAClC,QAAO,aAAa,UAAU,SAAS,WAAW,GAAG,OAAO,GAAG;;;;;;;;AASjE,SAAS,UAAU,MAIjB;CACA,MAAM,YAAY,KAAK,QAAQ,IAAI;CACnC,MAAM,aAAa,KAAK,QAAQ,IAAI;CACpC,MAAM,WAAW,aAAa,OAAO,YAAY,KAAK,aAAa;AAEnE,KAAI,YAAY,YAAY,GAC1B,QAAO;EACL,UAAU,KAAK,UAAU,GAAG,WAAW,aAAa,UAAU;EAC9D,OAAO,WAAW,KAAK,UAAU,YAAY,YAAY,KAAK,YAAY,KAAA,EAAU,GAAG;EACvF,MAAM,YAAY,KAAK,KAAK,MAAM,UAAU,GAAG;EAChD;AAGH,QAAO;EAAC,UAAU;EAAM,OAAO;EAAI,MAAM;EAAG;;;;;;;AAQ9C,SAAgB,cAAc,MAAc,QAAyB;AACnE,KAAI,CAAC,KAAK,WAAW,IAAI,IAAI,CAAC,OAC5B,QAAO;AAGT,KAAI,SAAS,OAAO,OAClB,QAAO;CAGT,MAAM,EAAC,UAAU,OAAO,SAAQ,UAAU,KAAK;AAC/C,QAAO,GAAG,SAAS,WAAW,QAAQ;;;;;;;;;;;AAYxC,SAAgB,iBAAiB,MAAc,QAAwB;AAarE,KAAI,CAAC,cAAc,MAAM,OAAO,CAC9B,QAAO;CAIT,MAAM,gBAAgB,KAAK,MAAM,OAAO,OAAO;AAG/C,KAAI,cAAc,WAAW,IAAI,CAC/B,QAAO;AAKT,QAAO,IAAI;;;;;;;AAQb,MAAa,8BAA8B,MAAc,kBAAmC;CAC1F,MAAM,EAAC,UAAU,OAAO,SAAQ,UAAU,KAAK;AAC/C,KAAI,eAAe;AACjB,MAAI,SAAS,SAAS,IAAI,CACxB,QAAO,GAAG,WAAW,QAAQ;AAE/B,SAAO,GAAG,SAAS,GAAG,QAAQ;;AAGhC,QAAO,GAAG,oBAAoB,SAAS,GAAG,QAAQ;;;;;;;;;;AAWpD,SAAS,oBAAoB,OAAe;AAC1C,QAAO,MAAM,QAAQ,OAAO,GAAG,IAAI;;ACxFrC,SAAwB,cAAc,OAAqD;CACzF,MAAM,EACJ,WAAW,IACX,SACA,YACA,SACA,gBAAgB,OAChB,QACA,wBACE;CAEJ,MAAM,SAAS,WAAW;CAC1B,MAAM,YAAY,OAAO,OAAO;CAChC,MAAM,CAAC,UAAU,eAAe,UAA8C;AAE9E,iBAAgB;AACd,YAAU,UAAU;IACnB,CAAC,OAAO,CAAC;CAEZ,MAAM,UAAU,eACP;EACL,YAAY,cAAc;AACxB,qBAAkB,UAAU;AAC5B,gBAAa,YAAY,KAAA,EAAU;;EAErC,SAAS,WAAW;AAClB,WAAQ,OAAO,MAAf;IACE,KAAK,OACH,QAAO,UAAU,QAAQ,KAAK,iBAAiB,OAAO,KAAK,SAAS,CAAC;IACvE,KAAK,MACH,QAAO,UAAU,QAAQ,MAAM;IACjC,KAAK,UACH,QAAO,UAAU,QAAQ,QAAQ,iBAAiB,OAAO,KAAK,SAAS,CAAC;IAC1E,QACE,OAAM,IAAI,MAAM,uBAAuB,EAAC,OAAO,QAAO,CAAC;;;EAG9D,GACD,CAAC,SAAS,CACX;CAED,MAAM,WAAW,aAAa;CAC9B,MAAM,eAAe,iBAAiB;AACtC,iBAAgB;AACd,MAAI,SACF,UAAS;GACP,MAAM;GACN,KAAK,2BACH,cACE,GAAG,WAAW,cAAc,OAAO,IAAI,aAAa,UAAU,KAAK,MACnE,SACD,EACD,cACD;GACF,CAAC;IAEH;EAAC;EAAU;EAAU;EAAU;EAAc;EAAc,CAAC;CAE/D,MAAM,gBAAgB,aAAa,YAAmC;AACpE,UAAQ,QAAQ,QAAhB;GACE,KAAK;AACH,cAAU,QAAQ,SAAS;AAC3B;GACF,KAAK;AACH,QAAI,QAAQ,oBAAoB;AAE9B,aAAQ,MACN,sFACD;AACD,YAAO;;AAET,cAAU,QAAQ,SAAS;AAC3B;GAEF,QACE,OAAM,IAAI,MAAM,0BAA0B,EAAC,OAAO,SAAQ,CAAC;;AAE/D,SAAO;IACN,EAAE,CAAC;AAEN,QACE,oBAACA,iBAAD;EACW;EACG;EACH;EACT,QAAA;EACA,SAAS,WAAW;EACC;EACb;EACR,CAAA"}
1
+ {"version":3,"file":"VisualEditing.js","names":["VisualEditingComponent"],"sources":["../src/visual-editing/client-component/utils.ts","../src/visual-editing/client-component/VisualEditing.tsx"],"sourcesContent":["/**\n * From: https://github.com/vercel/next.js/blob/5469e6427b54ab7e9876d4c85b47f9c3afdc5c1f/packages/next/src/shared/lib/router/utils/path-has-prefix.ts#L10-L17\n * Checks if a given path starts with a given prefix. It ensures it matches\n * exactly without containing extra chars. e.g. prefix /docs should replace\n * for /docs, /docs/, /docs/a but not /docsss\n * @param path The path to check.\n * @param prefix The prefix to check against.\n */\nfunction pathHasPrefix(path: string, prefix: string): boolean {\n if (typeof path !== 'string') {\n return false\n }\n\n const {pathname} = parsePath(path)\n return pathname === prefix || pathname.startsWith(`${prefix}/`)\n}\n\n/**\n * From: https://github.com/vercel/next.js/blob/5469e6427b54ab7e9876d4c85b47f9c3afdc5c1f/packages/next/src/shared/lib/router/utils/parse-path.ts#L6-L22\n * Given a path this function will find the pathname, query and hash and return\n * them. This is useful to parse full paths on the client side.\n * @param path A path to parse e.g. /foo/bar?id=1#hash\n */\nfunction parsePath(path: string): {\n pathname: string\n query: string\n hash: string\n} {\n const hashIndex = path.indexOf('#')\n const queryIndex = path.indexOf('?')\n const hasQuery = queryIndex > -1 && (hashIndex < 0 || queryIndex < hashIndex)\n\n if (hasQuery || hashIndex > -1) {\n return {\n pathname: path.substring(0, hasQuery ? queryIndex : hashIndex),\n query: hasQuery ? path.substring(queryIndex, hashIndex > -1 ? hashIndex : undefined) : '',\n hash: hashIndex > -1 ? path.slice(hashIndex) : '',\n }\n }\n\n return {pathname: path, query: '', hash: ''}\n}\n\n/**\n * From: https://github.com/vercel/next.js/blob/5469e6427b54ab7e9876d4c85b47f9c3afdc5c1f/packages/next/src/shared/lib/router/utils/add-path-prefix.ts#L3C1-L14C2\n * Adds the provided prefix to the given path. It first ensures that the path\n * is indeed starting with a slash.\n */\nexport function addPathPrefix(path: string, prefix?: string): string {\n if (!path.startsWith('/') || !prefix) {\n return path\n }\n // If the path is exactly '/' then return just the prefix\n if (path === '/' && prefix) {\n return prefix\n }\n\n const {pathname, query, hash} = parsePath(path)\n return `${prefix}${pathname}${query}${hash}`\n}\n\n/**\n * From: https://github.com/vercel/next.js/blob/5469e6427b54ab7e9876d4c85b47f9c3afdc5c1f/packages/next/src/shared/lib/router/utils/remove-path-prefix.ts#L3-L39\n * Given a path and a prefix it will remove the prefix when it exists in the\n * given path. It ensures it matches exactly without containing extra chars\n * and if the prefix is not there it will be noop.\n *\n * @param path The path to remove the prefix from.\n * @param prefix The prefix to be removed.\n */\nexport function removePathPrefix(path: string, prefix: string): string {\n // If the path doesn't start with the prefix we can return it as is. This\n // protects us from situations where the prefix is a substring of the path\n // prefix such as:\n //\n // For prefix: /blog\n //\n // /blog -> true\n // /blog/ -> true\n // /blog/1 -> true\n // /blogging -> false\n // /blogging/ -> false\n // /blogging/1 -> false\n if (!pathHasPrefix(path, prefix)) {\n return path\n }\n\n // Remove the prefix from the path via slicing.\n const withoutPrefix = path.slice(prefix.length)\n\n // If the path without the prefix starts with a `/` we can return it as is.\n if (withoutPrefix.startsWith('/')) {\n return withoutPrefix\n }\n\n // If the path without the prefix doesn't start with a `/` we need to add it\n // back to the path to make sure it's a valid path.\n return `/${withoutPrefix}`\n}\n\n/**\n * From: https://github.com/vercel/next.js/blob/dfe7fc03e2268e7cb765dce6a89e02c831c922d5/packages/next/src/client/normalize-trailing-slash.ts#L16\n * Normalizes the trailing slash of a path according to the `trailingSlash` option\n * in `next.config.js`.\n */\nexport const normalizePathTrailingSlash = (path: string, trailingSlash: boolean): string => {\n const {pathname, query, hash} = parsePath(path)\n if (trailingSlash) {\n if (pathname.endsWith('/')) {\n return `${pathname}${query}${hash}`\n }\n return `${pathname}/${query}${hash}`\n }\n\n return `${removeTrailingSlash(pathname)}${query}${hash}`\n}\n\n/**\n * From: https://github.com/vercel/next.js/blob/dfe7fc03e2268e7cb765dce6a89e02c831c922d5/packages/next/src/shared/lib/router/utils/remove-trailing-slash.ts#L8\n * Removes the trailing slash for a given route or page path. Preserves the\n * root page. Examples:\n * - `/foo/bar/` -> `/foo/bar`\n * - `/foo/bar` -> `/foo/bar`\n * - `/` -> `/`\n */\nfunction removeTrailingSlash(route: string) {\n return route.replace(/\\/$/, '') || '/'\n}\n","import {\n type HistoryAdapter,\n type HistoryAdapterNavigate,\n type HistoryRefresh,\n VisualEditing as VisualEditingComponent,\n type VisualEditingOptions,\n} from '@sanity/visual-editing/react'\nimport {usePathname, useRouter, useSearchParams} from 'next/navigation'\nimport {useCallback, useEffect, useMemo, useRef, useState} from 'react'\n\nimport {addPathPrefix, normalizePathTrailingSlash, removePathPrefix} from './utils'\n\n/**\n * @public\n */\nexport interface VisualEditingProps extends Omit<VisualEditingOptions, 'history'> {\n /**\n * @deprecated The histoy adapter is already implemented\n */\n history?: never\n /**\n * If next.config.ts is configured with a basePath we try to configure it automatically,\n * you can disable this by setting basePath to ''.\n * @example basePath=\"/my-custom-base-path\"\n * @alpha experimental and may change without notice\n * @defaultValue process.env.__NEXT_ROUTER_BASEPATH || ''\n */\n basePath?: string\n /**\n * If next.config.ts is configured with a `trailingSlash` we try to detect it automatically,\n * it can be controlled manually by passing a boolean.\n * @example trailingSlash={true}\n * @alpha experimental and may change without notice\n * @defaultValue Boolean(process.env.__NEXT_TRAILING_SLASH)\n */\n trailingSlash?: boolean\n}\n\nexport default function VisualEditing(props: VisualEditingProps): React.JSX.Element | null {\n const {\n basePath = '',\n plugins,\n components,\n refresh,\n trailingSlash = false,\n zIndex,\n onPerspectiveChange,\n } = props\n\n const router = useRouter()\n const routerRef = useRef(router)\n const [navigate, setNavigate] = useState<HistoryAdapterNavigate | undefined>()\n\n useEffect(() => {\n routerRef.current = router\n }, [router])\n\n const history = useMemo<HistoryAdapter>(\n () => ({\n subscribe: (_navigate) => {\n setNavigate(() => _navigate)\n return () => setNavigate(undefined)\n },\n update: (update) => {\n switch (update.type) {\n case 'push':\n return routerRef.current.push(removePathPrefix(update.url, basePath))\n case 'pop':\n return routerRef.current.back()\n case 'replace':\n return routerRef.current.replace(removePathPrefix(update.url, basePath))\n default:\n throw new Error(`Unknown update type`, {cause: update})\n }\n },\n }),\n [basePath],\n )\n\n const pathname = usePathname()\n const searchParams = useSearchParams()\n useEffect(() => {\n if (navigate) {\n navigate({\n type: 'push',\n url: normalizePathTrailingSlash(\n addPathPrefix(\n `${pathname}${searchParams?.size ? `?${searchParams.toString()}` : ''}`,\n basePath,\n ),\n trailingSlash,\n ),\n })\n }\n }, [basePath, navigate, pathname, searchParams, trailingSlash])\n\n const handleRefresh = useCallback((payload: HistoryRefresh): false | Promise<void> => {\n switch (payload.source) {\n case 'manual':\n routerRef.current.refresh()\n break\n case 'mutation': {\n if (payload.livePreviewEnabled) {\n return false\n }\n routerRef.current.refresh()\n break\n }\n default:\n throw new Error('Unknown refresh source', {cause: payload})\n }\n return new Promise((resolve) => setTimeout(resolve, 1_000))\n }, [])\n\n return (\n <VisualEditingComponent\n plugins={plugins}\n components={components}\n history={history}\n portal\n refresh={refresh ?? handleRefresh}\n onPerspectiveChange={onPerspectiveChange}\n zIndex={zIndex}\n />\n )\n}\n"],"mappings":"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"}
@@ -251,21 +251,52 @@ declare function defineLive(config: DefineLiveOptions & {
251
251
  * @example
252
252
  * ```tsx
253
253
  * import {cookies, draftMode} from 'next/headers'
254
+ * import {defineQuery} from 'next-sanity'
254
255
  * import {resolvePerspectiveFromCookies, type LivePerspective} from 'next-sanity/live'
255
- * import {sanityFetch} from '#sanity/live'
256
+ * import {sanityFetch, sanityFetchStaticParams} from '#sanity/live'
257
+ *
258
+ * export async function generateStaticParams() {
259
+ * const query = defineQuery(`*[_type == "page" && defined(slug.current)]{"slug": slug.current}`)
260
+ * return await sanityFetchStaticParams({query})
261
+ * }
256
262
  *
257
- * function Page() {
263
+ * export default async function Page({params}: PageProps<'/[slug]'>) {
258
264
  * const {isEnabled: isDraftMode} = await draftMode()
259
- * let perspective: LivePerspective = 'published'
260
- * if(isDraftMode) {
261
- * perspective = await resolvePerspectiveFromCookies({cookies: await cookies()})
265
+ *
266
+ * if (isDraftMode) {
267
+ * return (
268
+ * <Suspense>
269
+ * <DynamicPage params={params} />
270
+ * </Suspense>
271
+ * )
262
272
  * }
263
- * const {data} = await cachedFetch({query, perspective, stega: isDraftMode})
273
+ *
274
+ * const {slug} = await params
275
+ *
276
+ * return <CachedPage slug={slug} perspective="published" stega={false} />
264
277
  * }
265
- * function cachedFetch({query, params, perspective, stega}: {query: string, perspective: LivePerspective, stega: boolean}) {}) {
278
+ *
279
+ * async function DynamicPage({params}: Pick<PageProps<'/[slug]'>, 'params'>) {
280
+ * const {slug} = await params
281
+ * const perspective = await resolvePerspectiveFromCookies({cookies: await cookies()})
282
+ *
283
+ * return <CachedPage slug={slug} perspective={perspective} stega />
284
+ * }
285
+ *
286
+ * async function CachedPage({
287
+ * slug,
288
+ * perspective,
289
+ * stega,
290
+ * }: Awaited<PageProps<'/[slug]'>['params']> & {
291
+ * perspective: LivePerspective
292
+ * stega: boolean
293
+ * }) {
266
294
  * 'use cache'
267
- * const {data} = await sanityFetch({query, params, perspective, stega})
268
- * return {data}
295
+ *
296
+ * const query = defineQuery(`*[_type == "page" && slug.current == $slug][0]`)
297
+ * const {data} = await sanityFetch({query, params: {slug}, perspective, stega})
298
+ *
299
+ * return <article>...</article>
269
300
  * }
270
301
  * ```
271
302
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../../src/live/conditions/default/index.ts"],"mappings":";;;;;AA8JA;;;;;;;;;;;;;;;;;;;;AAqFA;;;;;;;;;;;;;;;;;;;;AAuDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA5IgB,UAAA,CAAW,MAAA,EAAQ,iBAAA;EAAqB,MAAA;AAAA;EACtD,WAAA,EAAa,sBAAA;EACb,UAAA,EAAY,KAAA,CAAM,aAAA,CAAc,sBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmFlB,UAAA,CAAW,MAAA,EAAQ,iBAAA;EAAqB,MAAA;AAAA;EACtD,WAAA,EAAa,gBAAA;EACb,UAAA,EAAY,KAAA,CAAM,aAAA,CAAc,gBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAqDrB,6BAAA,SAAsC,+BAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../../src/live/conditions/default/index.ts"],"mappings":";;;;;AA8JA;;;;;;;;;;;;;;;;;;;;AAqFA;;;;;;;;;;;;;;;;;;;;AAsFA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA3KgB,UAAA,CAAW,MAAA,EAAQ,iBAAA;EAAqB,MAAA;AAAA;EACtD,WAAA,EAAa,sBAAA;EACb,UAAA,EAAY,KAAA,CAAM,aAAA,CAAc,sBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmFlB,UAAA,CAAW,MAAA,EAAQ,iBAAA;EAAqB,MAAA;AAAA;EACtD,WAAA,EAAa,gBAAA;EACb,UAAA,EAAY,KAAA,CAAM,aAAA,CAAc,gBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAoFrB,6BAAA,SAAsC,+BAAA"}
@@ -11,21 +11,52 @@ function defineLive(_config) {
11
11
  * @example
12
12
  * ```tsx
13
13
  * import {cookies, draftMode} from 'next/headers'
14
+ * import {defineQuery} from 'next-sanity'
14
15
  * import {resolvePerspectiveFromCookies, type LivePerspective} from 'next-sanity/live'
15
- * import {sanityFetch} from '#sanity/live'
16
+ * import {sanityFetch, sanityFetchStaticParams} from '#sanity/live'
16
17
  *
17
- * function Page() {
18
+ * export async function generateStaticParams() {
19
+ * const query = defineQuery(`*[_type == "page" && defined(slug.current)]{"slug": slug.current}`)
20
+ * return await sanityFetchStaticParams({query})
21
+ * }
22
+ *
23
+ * export default async function Page({params}: PageProps<'/[slug]'>) {
18
24
  * const {isEnabled: isDraftMode} = await draftMode()
19
- * let perspective: LivePerspective = 'published'
20
- * if(isDraftMode) {
21
- * perspective = await resolvePerspectiveFromCookies({cookies: await cookies()})
25
+ *
26
+ * if (isDraftMode) {
27
+ * return (
28
+ * <Suspense>
29
+ * <DynamicPage params={params} />
30
+ * </Suspense>
31
+ * )
22
32
  * }
23
- * const {data} = await cachedFetch({query, perspective, stega: isDraftMode})
33
+ *
34
+ * const {slug} = await params
35
+ *
36
+ * return <CachedPage slug={slug} perspective="published" stega={false} />
24
37
  * }
25
- * function cachedFetch({query, params, perspective, stega}: {query: string, perspective: LivePerspective, stega: boolean}) {}) {
38
+ *
39
+ * async function DynamicPage({params}: Pick<PageProps<'/[slug]'>, 'params'>) {
40
+ * const {slug} = await params
41
+ * const perspective = await resolvePerspectiveFromCookies({cookies: await cookies()})
42
+ *
43
+ * return <CachedPage slug={slug} perspective={perspective} stega />
44
+ * }
45
+ *
46
+ * async function CachedPage({
47
+ * slug,
48
+ * perspective,
49
+ * stega,
50
+ * }: Awaited<PageProps<'/[slug]'>['params']> & {
51
+ * perspective: LivePerspective
52
+ * stega: boolean
53
+ * }) {
26
54
  * 'use cache'
27
- * const {data} = await sanityFetch({query, params, perspective, stega})
28
- * return {data}
55
+ *
56
+ * const query = defineQuery(`*[_type == "page" && slug.current == $slug][0]`)
57
+ * const {data} = await sanityFetch({query, params: {slug}, perspective, stega})
58
+ *
59
+ * return <article>...</article>
29
60
  * }
30
61
  * ```
31
62
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/live/conditions/default/index.ts"],"sourcesContent":["import type {resolvePerspectiveFromCookies as _resolvePerspectiveFromCookies} from '#live/resolvePerspectiveFromCookies'\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 * 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 & {strict?: false}): {\n sanityFetch: DefinedFetchType\n SanityLive: React.ComponentType<DefinedLiveProps>\n}\nexport function defineLive(_config: DefineLiveOptions): never {\n throw new Error(`defineLive can't be imported by a client component`)\n}\n\nexport type {\n DefinedFetchType,\n DefinedLiveProps,\n DefineLiveOptions,\n LivePerspective,\n SanityLiveAction,\n SanityLiveActionContext,\n SanityLiveOnError,\n SanityLiveOnGoaway,\n SanityLiveOnReconnect,\n SanityLiveOnRestart,\n SanityLiveOnWelcome,\n StrictDefinedFetchType,\n StrictDefinedLiveProps,\n} from '#live/types'\n\nexport {isCorsOriginError} from '#live/isCorsOriginError'\nexport {parseTags} from '#live/parseTags'\n\n/**\n * This helper is intended for use with Next.js Cache Components (`cacheComponents: true`),\n * where `cookies()` and `draftMode()` cannot be called inside `'use cache'` boundaries.\n * Resolve the perspective once outside the cache boundary and pass it in as a prop / cache key.\n *\n * @example\n * ```tsx\n * import {cookies, draftMode} from 'next/headers'\n * import {resolvePerspectiveFromCookies, type LivePerspective} from 'next-sanity/live'\n * import {sanityFetch} from '#sanity/live'\n *\n * function Page() {\n * const {isEnabled: isDraftMode} = await draftMode()\n * let perspective: LivePerspective = 'published'\n * if(isDraftMode) {\n * perspective = await resolvePerspectiveFromCookies({cookies: await cookies()})\n * }\n * const {data} = await cachedFetch({query, perspective, stega: isDraftMode})\n * }\n * function cachedFetch({query, params, perspective, stega}: {query: string, perspective: LivePerspective, stega: boolean}) {}) {\n * 'use cache'\n * const {data} = await sanityFetch({query, params, perspective, stega})\n * return {data}\n * }\n * ```\n *\n * @public\n */\nexport const resolvePerspectiveFromCookies: typeof _resolvePerspectiveFromCookies = () => {\n throw new Error(`resolvePerspectiveFromCookies can't be imported by a client component`)\n}\n"],"mappings":";;AAuPA,SAAgB,WAAW,SAAmC;AAC5D,OAAM,IAAI,MAAM,qDAAqD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDvE,MAAa,sCAA6E;AACxF,OAAM,IAAI,MAAM,wEAAwE"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/live/conditions/default/index.ts"],"sourcesContent":["import type {resolvePerspectiveFromCookies as _resolvePerspectiveFromCookies} from '#live/resolvePerspectiveFromCookies'\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 * 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 & {strict?: false}): {\n sanityFetch: DefinedFetchType\n SanityLive: React.ComponentType<DefinedLiveProps>\n}\nexport function defineLive(_config: DefineLiveOptions): never {\n throw new Error(`defineLive can't be imported by a client component`)\n}\n\nexport type {\n DefinedFetchType,\n DefinedLiveProps,\n DefineLiveOptions,\n LivePerspective,\n SanityLiveAction,\n SanityLiveActionContext,\n SanityLiveOnError,\n SanityLiveOnGoaway,\n SanityLiveOnReconnect,\n SanityLiveOnRestart,\n SanityLiveOnWelcome,\n StrictDefinedFetchType,\n StrictDefinedLiveProps,\n} from '#live/types'\n\nexport {isCorsOriginError} from '#live/isCorsOriginError'\nexport {parseTags} from '#live/parseTags'\n\n/**\n * This helper is intended for use with Next.js Cache Components (`cacheComponents: true`),\n * where `cookies()` and `draftMode()` cannot be called inside `'use cache'` boundaries.\n * Resolve the perspective once outside the cache boundary and pass it in as a prop / cache key.\n *\n * @example\n * ```tsx\n * import {cookies, draftMode} from 'next/headers'\n * import {defineQuery} from 'next-sanity'\n * import {resolvePerspectiveFromCookies, type LivePerspective} from 'next-sanity/live'\n * import {sanityFetch, sanityFetchStaticParams} from '#sanity/live'\n *\n * export async function generateStaticParams() {\n * const query = defineQuery(`*[_type == \"page\" && defined(slug.current)]{\"slug\": slug.current}`)\n * return await sanityFetchStaticParams({query})\n * }\n *\n * export default async function Page({params}: PageProps<'/[slug]'>) {\n * const {isEnabled: isDraftMode} = await draftMode()\n *\n * if (isDraftMode) {\n * return (\n * <Suspense>\n * <DynamicPage params={params} />\n * </Suspense>\n * )\n * }\n *\n * const {slug} = await params\n *\n * return <CachedPage slug={slug} perspective=\"published\" stega={false} />\n * }\n *\n * async function DynamicPage({params}: Pick<PageProps<'/[slug]'>, 'params'>) {\n * const {slug} = await params\n * const perspective = await resolvePerspectiveFromCookies({cookies: await cookies()})\n *\n * return <CachedPage slug={slug} perspective={perspective} stega />\n * }\n *\n * async function CachedPage({\n * slug,\n * perspective,\n * stega,\n * }: Awaited<PageProps<'/[slug]'>['params']> & {\n * perspective: LivePerspective\n * stega: boolean\n * }) {\n * 'use cache'\n *\n * const query = defineQuery(`*[_type == \"page\" && slug.current == $slug][0]`)\n * const {data} = await sanityFetch({query, params: {slug}, perspective, stega})\n *\n * return <article>...</article>\n * }\n * ```\n *\n * @public\n */\nexport const resolvePerspectiveFromCookies: typeof _resolvePerspectiveFromCookies = () => {\n throw new Error(`resolvePerspectiveFromCookies can't be imported by a client component`)\n}\n"],"mappings":";;AAuPA,SAAgB,WAAW,SAAmC;AAC5D,OAAM,IAAI,MAAM,qDAAqD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiFvE,MAAa,sCAA6E;AACxF,OAAM,IAAI,MAAM,wEAAwE"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../../src/live/conditions/react-server/defineLive.tsx"],"mappings":";;;;;;AAwKA;;;;;;;;;;;;;;;;;;;;AAqFA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBArFgB,UAAA,CAAW,MAAA,EAAQ,iBAAA;EAAqB,MAAA;AAAA;EACtD,WAAA,EAAa,sBAAA;EACb,UAAA,EAAY,KAAA,CAAM,aAAA,CAAc,sBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmFlB,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":";;;;;;AAyKA;;;;;;;;;;;;;;;;;;;;AAqFA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBArFgB,UAAA,CAAW,MAAA,EAAQ,iBAAA;EAAqB,MAAA;AAAA;EACtD,WAAA,EAAa,sBAAA;EACb,UAAA,EAAY,KAAA,CAAM,aAAA,CAAc,sBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmFlB,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} 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 * 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 & {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 query,\n params = {},\n stega: _stega,\n tags = [],\n perspective: _perspective,\n requestTag = 'next-loader.fetch',\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 waitFor,\n requestTag = 'next-loader.live',\n\n action,\n onReconnect = refreshAction,\n onRestart = refreshAction,\n onWelcome = false,\n onError = false,\n onGoAway = false,\n\n refreshOnMount,\n refreshOnFocus,\n refreshOnReconnect,\n } = props\n const {projectId, dataset, apiHost, apiVersion, useProjectHostname, requestTagPrefix} =\n client.config()\n const shouldIncludeDrafts = typeof browserToken === 'string' && includeDrafts\n const shouldWaitFor = waitFor === 'function' && !shouldIncludeDrafts ? waitFor : undefined\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 waitFor={shouldWaitFor}\n action={action ?? (shouldWaitFor === 'function' ? refreshAction : revalidateSyncTagsAction)}\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} 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 LivePerspective,\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 * 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 & {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 query,\n params = {},\n stega: _stega,\n tags = [],\n perspective: _perspective,\n requestTag = 'next-loader.fetch',\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 waitFor,\n requestTag = 'next-loader.live',\n\n action,\n onReconnect = refreshAction,\n onRestart = refreshAction,\n onWelcome = false,\n onError = false,\n onGoAway = false,\n\n refreshOnMount,\n refreshOnFocus,\n refreshOnReconnect,\n } = props\n const {projectId, dataset, apiHost, apiVersion, useProjectHostname, requestTagPrefix} =\n client.config()\n const shouldIncludeDrafts = typeof browserToken === 'string' && includeDrafts\n const shouldWaitFor = waitFor === 'function' && !shouldIncludeDrafts ? waitFor : undefined\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 waitFor={shouldWaitFor}\n action={action ?? (shouldWaitFor === 'function' ? refreshAction : revalidateSyncTagsAction)}\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(fallback: LivePerspective): Promise<LivePerspective> {\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":";;;;;;;;;;;;;AAkQA,SAAgB,WAAW,QAA2B;CACpD,MAAM,EACJ,QAAQ,SACR,aACA,cACA,OAAO,eAAe,MACtB,SAAS,UACP;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,eAAe,aAAa,sBAAsB,gBAAe,OAAO,QAAQ;CAC9F,MAAM,mBAAmB,OAAO,OAAO,QAAQ,CAAC,MAAM,cAAc;CAEpE,MAAM,cAAgC,eAAe,YAAY,EAC/D,OACA,SAAS,EAAE,EACX,OAAO,QACP,OAAO,EAAE,EACT,aAAa,cACb,aAAa,uBACZ;AACD,MAAI,OACF,4BAA2B;GAAC,aAAa;GAAc,OAAO;GAAO,CAAC;EAExE,MAAM,QAAQ,SACV,SACC,WAAW,gBAAgB,qBAAqB,MAAM,WAAW,EAAE;EACxE,MAAM,cAAc,SAChB,eACC,gBACA,MAAM,yBACL,wBAAwB,QAAQ,cAAc,oBAC/C;EACL,MAAM,SAAS,gBAAgB;EAC/B,MAAM,eAAe,QAAQ,IAAI,kBAAkB;EACnD,MAAM,YAAY,UAAU,CAAC,eAAe,YAAY,KAAA;EACxD,MAAM,iBACJ,gBAAgB,cAAc,iBAAiB,YAAY,iBAAiB;EAG9E,MAAM,EAAC,aAAY,MAAM,OAAO,MAAM,OAAO,MAAM,QAAQ;GACzD,gBAAgB;GACH;GACb,OAAO;GACP,aAAa;GACb;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,GAAG,iBAAiB,MAAM,IAAI,EAAE,CAAE;EAGzF,MAAM,EAAC,QAAQ,oBAAmB,MAAM,OAAO,MAAM,OAAO,MAAM,QAAQ;GACxE,gBAAgB;GACH;GACb;GACA,OAAO,gBAAgB,eAAe,cAAc,cAAc;GAClE,MAAM;IAAC,YAAY;IAAO,MAAM;IAAU;GAC1C;GACA;GACA,KAAK;GACN,CAAC;AACF,SAAO;GAAC,MAAM;GAAQ,WAAW,mBAAmB;GAAM,MAAM;GAAU;;CAG5E,MAAMA,eAAoD,eAAeA,aAAW,OAAO;AACzF,MAAI,OACF,+BAA8B,MAAM;EAEtC,MAAM,EACJ,iBAAiB,MAAM,WAAW,EAAE,WACpC,SACA,aAAa,oBAEb,QACA,cAAc,eACd,YAAY,eACZ,YAAY,OACZ,UAAU,OACV,WAAW,OAEX,gBACA,gBACA,uBACE;EACJ,MAAM,EAAC,WAAW,SAAS,SAAS,YAAY,oBAAoB,qBAClE,OAAO,QAAQ;EACjB,MAAM,sBAAsB,OAAO,iBAAiB,YAAY;EAChE,MAAM,gBAAgB,YAAY,cAAc,CAAC,sBAAsB,UAAU,KAAA;EAGjF,MAAM,EAAC,WAAU,IAAI,IAAI,OAAO,OAAO,IAAI,MAAM,CAAC;AAClD,aAAW,OAAO;AAElB,SACE,oBAACC,YAAD;GACE,QAAQ;IACN;IACA;IACA;IACA;IACA;IACA;IACA,OAAO,sBAAsB,eAAe,KAAA;IAC7C;GACD,eAAe;GACf,SAAS;GACT,QAAQ,WAAW,kBAAkB,aAAa,gBAAgB;GACrD;GACF;GACA;GACF;GACC;GACE;GACI;GACA;GACI;GACpB,CAAA;;AAGN,cAAW,cAAc;AAEzB,QAAO;EAAC;EAAa,YAAA;EAAW;;AAGlC,eAAe,yBAAyB,UAAqD;AAC3F,SAAQ,MAAM,WAAW,EAAE,aACtB,MAAM,SAAS,EAAE,IAAI,sBAAsB,GAC1C,qBAAqB,MAAM,SAAS,EAAE,IAAI,sBAAsB,EAAE,OAAO,SAAS,GAClF,WACF"}
@@ -1,5 +1,6 @@
1
+ import { i as LivePerspective } from "./types.js";
1
2
  import { cookies } from "next/headers";
2
- import { ClientPerspective, SyncTag } from "@sanity/client";
3
+ import { SyncTag } from "@sanity/client";
3
4
  /**
4
5
  * This helper is intended for use with Next.js Cache Components (`cacheComponents: true`),
5
6
  * where `cookies()` and `draftMode()` cannot be called inside `'use cache'` boundaries.
@@ -8,21 +9,52 @@ import { ClientPerspective, SyncTag } from "@sanity/client";
8
9
  * @example
9
10
  * ```tsx
10
11
  * import {cookies, draftMode} from 'next/headers'
12
+ * import {defineQuery} from 'next-sanity'
11
13
  * import {resolvePerspectiveFromCookies, type LivePerspective} from 'next-sanity/live'
12
- * import {sanityFetch} from '#sanity/live'
14
+ * import {sanityFetch, sanityFetchStaticParams} from '#sanity/live'
13
15
  *
14
- * function Page() {
16
+ * export async function generateStaticParams() {
17
+ * const query = defineQuery(`*[_type == "page" && defined(slug.current)]{"slug": slug.current}`)
18
+ * return await sanityFetchStaticParams({query})
19
+ * }
20
+ *
21
+ * export default async function Page({params}: PageProps<'/[slug]'>) {
15
22
  * const {isEnabled: isDraftMode} = await draftMode()
16
- * let perspective: LivePerspective = 'published'
17
- * if(isDraftMode) {
18
- * perspective = await resolvePerspectiveFromCookies({cookies: await cookies()})
23
+ *
24
+ * if (isDraftMode) {
25
+ * return (
26
+ * <Suspense>
27
+ * <DynamicPage params={params} />
28
+ * </Suspense>
29
+ * )
19
30
  * }
20
- * const {data} = await cachedFetch({query, perspective, stega: isDraftMode})
31
+ *
32
+ * const {slug} = await params
33
+ *
34
+ * return <CachedPage slug={slug} perspective="published" stega={false} />
21
35
  * }
22
- * function cachedFetch({query, params, perspective, stega}: {query: string, perspective: LivePerspective, stega: boolean}) {}) {
36
+ *
37
+ * async function DynamicPage({params}: Pick<PageProps<'/[slug]'>, 'params'>) {
38
+ * const {slug} = await params
39
+ * const perspective = await resolvePerspectiveFromCookies({cookies: await cookies()})
40
+ *
41
+ * return <CachedPage slug={slug} perspective={perspective} stega />
42
+ * }
43
+ *
44
+ * async function CachedPage({
45
+ * slug,
46
+ * perspective,
47
+ * stega,
48
+ * }: Awaited<PageProps<'/[slug]'>['params']> & {
49
+ * perspective: LivePerspective
50
+ * stega: boolean
51
+ * }) {
23
52
  * 'use cache'
24
- * const {data} = await sanityFetch({query, params, perspective, stega})
25
- * return {data}
53
+ *
54
+ * const query = defineQuery(`*[_type == "page" && slug.current == $slug][0]`)
55
+ * const {data} = await sanityFetch({query, params: {slug}, perspective, stega})
56
+ *
57
+ * return <article>...</article>
26
58
  * }
27
59
  * ```
28
60
  *
@@ -32,7 +64,7 @@ declare function resolvePerspectiveFromCookies({
32
64
  cookies: jar
33
65
  }: {
34
66
  cookies: Awaited<ReturnType<typeof cookies>>;
35
- }): Promise<Exclude<ClientPerspective, "raw">>;
67
+ }): Promise<LivePerspective>;
36
68
  declare const cacheTagPrefixes: {
37
69
  published: string;
38
70
  drafts: string;
@@ -1 +1 @@
1
- {"version":3,"file":"parseTags.d.ts","names":[],"sources":["../src/live/shared/resolvePerspectiveFromCookies.ts","../src/live/shared/constants.ts","../src/live/shared/parseTags.ts"],"mappings":";;;AAkCA;;;;;;;;;;;;;;;;;;;;;;;;AC3BA;;;iBD2BsB,6BAAA,CAAA;EACpB,OAAA,EAAS;AAAA;EAET,OAAA,EAAS,OAAA,CAAQ,UAAA,QAAkB,OAAA;AAAA,IACjC,OAAA,CAAQ,OAAA,CAAQ,iBAAA;AAAA,cC/BP,gBAAA;EACX,SAAA;EACA,MAAA;AAAA;AAAA,UCLQ,mBAAA;EACR,IAAA,YAAgB,gBAAA,CAAiB,SAAA,GAAY,OAAA;EAC7C,MAAA,SAAe,gBAAA,CAAiB,SAAA;EAChC,UAAA;AAAA;AAAA,UAEQ,eAAA;EACR,IAAA,YAAgB,gBAAA,CAAiB,MAAA,GAAS,OAAA;EAC1C,MAAA,SAAe,gBAAA,CAAiB,MAAA;EAChC,UAAA;AAAA;AAAA,KAEG,UAAA,GAAa,mBAAA,GAAsB,eAAA;;;;;;;;;;;;;;;ADPxC;;;;;;ACL+B;iBAmCf,SAAA,CAAU,UAAA,YAAsB,UAAA"}
1
+ {"version":3,"file":"parseTags.d.ts","names":[],"sources":["../src/live/shared/resolvePerspectiveFromCookies.ts","../src/live/shared/constants.ts","../src/live/shared/parseTags.ts"],"mappings":";;;;;AAiEA;;;;;;;;;;;;;;;;;;;;;;AC1DA;;;;;;ACL+B;;;;;;;;;;;;;;;;;;AAK7B;;;;;;;;;;;iBF0DoB,6BAAA,CAAA;EACpB,OAAA,EAAS;AAAA;EAET,OAAA,EAAS,OAAA,CAAQ,UAAA,QAAkB,OAAA;AAAA,IACjC,OAAA,CAAQ,eAAA;AAAA,cC9DC,gBAAA;EACX,SAAA;EACA,MAAA;AAAA;AAAA,UCLQ,mBAAA;EACR,IAAA,YAAgB,gBAAA,CAAiB,SAAA,GAAY,OAAA;EAC7C,MAAA,SAAe,gBAAA,CAAiB,SAAA;EAChC,UAAA;AAAA;AAAA,UAEQ,eAAA;EACR,IAAA,YAAgB,gBAAA,CAAiB,MAAA,GAAS,OAAA;EAC1C,MAAA,SAAe,gBAAA,CAAiB,MAAA;EAChC,UAAA;AAAA;AAAA,KAEG,UAAA,GAAa,mBAAA,GAAsB,eAAA;;;;;;;;;;;;;;ADPxC;;;;;;ACL+B;;iBAmCf,SAAA,CAAU,UAAA,YAAsB,UAAA"}
@@ -16,21 +16,52 @@ function validateStrictFetchOptions(options) {
16
16
  * @example
17
17
  * ```tsx
18
18
  * import {cookies, draftMode} from 'next/headers'
19
+ * import {defineQuery} from 'next-sanity'
19
20
  * import {resolvePerspectiveFromCookies, type LivePerspective} from 'next-sanity/live'
20
- * import {sanityFetch} from '#sanity/live'
21
+ * import {sanityFetch, sanityFetchStaticParams} from '#sanity/live'
21
22
  *
22
- * function Page() {
23
+ * export async function generateStaticParams() {
24
+ * const query = defineQuery(`*[_type == "page" && defined(slug.current)]{"slug": slug.current}`)
25
+ * return await sanityFetchStaticParams({query})
26
+ * }
27
+ *
28
+ * export default async function Page({params}: PageProps<'/[slug]'>) {
23
29
  * const {isEnabled: isDraftMode} = await draftMode()
24
- * let perspective: LivePerspective = 'published'
25
- * if(isDraftMode) {
26
- * perspective = await resolvePerspectiveFromCookies({cookies: await cookies()})
30
+ *
31
+ * if (isDraftMode) {
32
+ * return (
33
+ * <Suspense>
34
+ * <DynamicPage params={params} />
35
+ * </Suspense>
36
+ * )
27
37
  * }
28
- * const {data} = await cachedFetch({query, perspective, stega: isDraftMode})
38
+ *
39
+ * const {slug} = await params
40
+ *
41
+ * return <CachedPage slug={slug} perspective="published" stega={false} />
29
42
  * }
30
- * function cachedFetch({query, params, perspective, stega}: {query: string, perspective: LivePerspective, stega: boolean}) {}) {
43
+ *
44
+ * async function DynamicPage({params}: Pick<PageProps<'/[slug]'>, 'params'>) {
45
+ * const {slug} = await params
46
+ * const perspective = await resolvePerspectiveFromCookies({cookies: await cookies()})
47
+ *
48
+ * return <CachedPage slug={slug} perspective={perspective} stega />
49
+ * }
50
+ *
51
+ * async function CachedPage({
52
+ * slug,
53
+ * perspective,
54
+ * stega,
55
+ * }: Awaited<PageProps<'/[slug]'>['params']> & {
56
+ * perspective: LivePerspective
57
+ * stega: boolean
58
+ * }) {
31
59
  * 'use cache'
32
- * const {data} = await sanityFetch({query, params, perspective, stega})
33
- * return {data}
60
+ *
61
+ * const query = defineQuery(`*[_type == "page" && slug.current == $slug][0]`)
62
+ * const {data} = await sanityFetch({query, params: {slug}, perspective, stega})
63
+ *
64
+ * return <article>...</article>
34
65
  * }
35
66
  * ```
36
67
  *
@@ -1 +1 @@
1
- {"version":3,"file":"resolvePerspectiveFromCookies.js","names":[],"sources":["../src/live/shared/strictValidation.ts","../src/live/shared/resolvePerspectiveFromCookies.ts"],"sourcesContent":["import {generateHelpUrl} from '@sanity/generate-help-url'\n\nexport function validateStrictSanityLiveProps(props: {includeDrafts?: unknown}): void {\n if (typeof props.includeDrafts !== 'boolean') {\n throw new Error(\n `<SanityLive> requires an explicit \\`includeDrafts\\` prop (true or false) when \\`strict: true\\` is set on \\`defineLive\\`.\\n\\nMore information: ${generateHelpUrl('next-sanity-live-strict')}`,\n {cause: props},\n )\n }\n}\n\nexport function validateStrictFetchOptions(options: {\n perspective?: unknown\n stega?: unknown\n}): void {\n if (typeof options.perspective === 'undefined' || options.perspective === null) {\n throw new Error(\n `sanityFetch() requires an explicit \\`perspective\\` option when \\`strict: true\\` is set on \\`defineLive\\`.\\n\\nMore information: ${generateHelpUrl('next-sanity-fetch-strict')}`,\n {cause: options},\n )\n }\n if (typeof options.stega !== 'boolean') {\n throw new Error(\n `sanityFetch() requires an explicit \\`stega\\` option (true or false) when \\`strict: true\\` is set on \\`defineLive\\`.\\n\\nMore information: ${generateHelpUrl('next-sanity-fetch-strict')}`,\n {cause: options},\n )\n }\n}\n","import type {ClientPerspective} from '@sanity/client'\nimport {perspectiveCookieName} from '@sanity/preview-url-secret/constants'\nimport type {cookies} from 'next/headers'\n\nimport {sanitizePerspective} from '#live/sanitizePerspective'\n\n/**\n * This helper is intended for use with Next.js Cache Components (`cacheComponents: true`),\n * where `cookies()` and `draftMode()` cannot be called inside `'use cache'` boundaries.\n * Resolve the perspective once outside the cache boundary and pass it in as a prop / cache key.\n *\n * @example\n * ```tsx\n * import {cookies, draftMode} from 'next/headers'\n * import {resolvePerspectiveFromCookies, type LivePerspective} from 'next-sanity/live'\n * import {sanityFetch} from '#sanity/live'\n *\n * function Page() {\n * const {isEnabled: isDraftMode} = await draftMode()\n * let perspective: LivePerspective = 'published'\n * if(isDraftMode) {\n * perspective = await resolvePerspectiveFromCookies({cookies: await cookies()})\n * }\n * const {data} = await cachedFetch({query, perspective, stega: isDraftMode})\n * }\n * function cachedFetch({query, params, perspective, stega}: {query: string, perspective: LivePerspective, stega: boolean}) {}) {\n * 'use cache'\n * const {data} = await sanityFetch({query, params, perspective, stega})\n * return {data}\n * }\n * ```\n *\n * @public\n */\nexport async function resolvePerspectiveFromCookies({\n cookies: jar,\n}: {\n cookies: Awaited<ReturnType<typeof cookies>>\n}): Promise<Exclude<ClientPerspective, 'raw'>> {\n return jar.has(perspectiveCookieName)\n ? sanitizePerspective(jar.get(perspectiveCookieName)?.value, 'drafts')\n : 'drafts'\n}\n"],"mappings":";;;AAEA,SAAgB,8BAA8B,OAAwC;AACpF,KAAI,OAAO,MAAM,kBAAkB,UACjC,OAAM,IAAI,MACR,iJAAiJ,gBAAgB,0BAA0B,IAC3L,EAAC,OAAO,OAAM,CACf;;AAIL,SAAgB,2BAA2B,SAGlC;AACP,KAAI,OAAO,QAAQ,gBAAgB,eAAe,QAAQ,gBAAgB,KACxE,OAAM,IAAI,MACR,kIAAkI,gBAAgB,2BAA2B,IAC7K,EAAC,OAAO,SAAQ,CACjB;AAEH,KAAI,OAAO,QAAQ,UAAU,UAC3B,OAAM,IAAI,MACR,4IAA4I,gBAAgB,2BAA2B,IACvL,EAAC,OAAO,SAAQ,CACjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACSL,eAAsB,8BAA8B,EAClD,SAAS,OAGoC;AAC7C,QAAO,IAAI,IAAI,sBAAsB,GACjC,oBAAoB,IAAI,IAAI,sBAAsB,EAAE,OAAO,SAAS,GACpE"}
1
+ {"version":3,"file":"resolvePerspectiveFromCookies.js","names":[],"sources":["../src/live/shared/strictValidation.ts","../src/live/shared/resolvePerspectiveFromCookies.ts"],"sourcesContent":["import {generateHelpUrl} from '@sanity/generate-help-url'\n\nexport function validateStrictSanityLiveProps(props: {includeDrafts?: unknown}): void {\n if (typeof props.includeDrafts !== 'boolean') {\n throw new Error(\n `<SanityLive> requires an explicit \\`includeDrafts\\` prop (true or false) when \\`strict: true\\` is set on \\`defineLive\\`.\\n\\nMore information: ${generateHelpUrl('next-sanity-live-strict')}`,\n {cause: props},\n )\n }\n}\n\nexport function validateStrictFetchOptions(options: {\n perspective?: unknown\n stega?: unknown\n}): void {\n if (typeof options.perspective === 'undefined' || options.perspective === null) {\n throw new Error(\n `sanityFetch() requires an explicit \\`perspective\\` option when \\`strict: true\\` is set on \\`defineLive\\`.\\n\\nMore information: ${generateHelpUrl('next-sanity-fetch-strict')}`,\n {cause: options},\n )\n }\n if (typeof options.stega !== 'boolean') {\n throw new Error(\n `sanityFetch() requires an explicit \\`stega\\` option (true or false) when \\`strict: true\\` is set on \\`defineLive\\`.\\n\\nMore information: ${generateHelpUrl('next-sanity-fetch-strict')}`,\n {cause: options},\n )\n }\n}\n","import {perspectiveCookieName} from '@sanity/preview-url-secret/constants'\nimport type {cookies} from 'next/headers'\n\nimport {sanitizePerspective} from '#live/sanitizePerspective'\nimport type {LivePerspective} from '#live/types'\n\n/**\n * This helper is intended for use with Next.js Cache Components (`cacheComponents: true`),\n * where `cookies()` and `draftMode()` cannot be called inside `'use cache'` boundaries.\n * Resolve the perspective once outside the cache boundary and pass it in as a prop / cache key.\n *\n * @example\n * ```tsx\n * import {cookies, draftMode} from 'next/headers'\n * import {defineQuery} from 'next-sanity'\n * import {resolvePerspectiveFromCookies, type LivePerspective} from 'next-sanity/live'\n * import {sanityFetch, sanityFetchStaticParams} from '#sanity/live'\n *\n * export async function generateStaticParams() {\n * const query = defineQuery(`*[_type == \"page\" && defined(slug.current)]{\"slug\": slug.current}`)\n * return await sanityFetchStaticParams({query})\n * }\n *\n * export default async function Page({params}: PageProps<'/[slug]'>) {\n * const {isEnabled: isDraftMode} = await draftMode()\n *\n * if (isDraftMode) {\n * return (\n * <Suspense>\n * <DynamicPage params={params} />\n * </Suspense>\n * )\n * }\n *\n * const {slug} = await params\n *\n * return <CachedPage slug={slug} perspective=\"published\" stega={false} />\n * }\n *\n * async function DynamicPage({params}: Pick<PageProps<'/[slug]'>, 'params'>) {\n * const {slug} = await params\n * const perspective = await resolvePerspectiveFromCookies({cookies: await cookies()})\n *\n * return <CachedPage slug={slug} perspective={perspective} stega />\n * }\n *\n * async function CachedPage({\n * slug,\n * perspective,\n * stega,\n * }: Awaited<PageProps<'/[slug]'>['params']> & {\n * perspective: LivePerspective\n * stega: boolean\n * }) {\n * 'use cache'\n *\n * const query = defineQuery(`*[_type == \"page\" && slug.current == $slug][0]`)\n * const {data} = await sanityFetch({query, params: {slug}, perspective, stega})\n *\n * return <article>...</article>\n * }\n * ```\n *\n * @public\n */\nexport async function resolvePerspectiveFromCookies({\n cookies: jar,\n}: {\n cookies: Awaited<ReturnType<typeof cookies>>\n}): Promise<LivePerspective> {\n return jar.has(perspectiveCookieName)\n ? sanitizePerspective(jar.get(perspectiveCookieName)?.value, 'drafts')\n : 'drafts'\n}\n"],"mappings":";;;AAEA,SAAgB,8BAA8B,OAAwC;AACpF,KAAI,OAAO,MAAM,kBAAkB,UACjC,OAAM,IAAI,MACR,iJAAiJ,gBAAgB,0BAA0B,IAC3L,EAAC,OAAO,OAAM,CACf;;AAIL,SAAgB,2BAA2B,SAGlC;AACP,KAAI,OAAO,QAAQ,gBAAgB,eAAe,QAAQ,gBAAgB,KACxE,OAAM,IAAI,MACR,kIAAkI,gBAAgB,2BAA2B,IAC7K,EAAC,OAAO,SAAQ,CACjB;AAEH,KAAI,OAAO,QAAQ,UAAU,UAC3B,OAAM,IAAI,MACR,4IAA4I,gBAAgB,2BAA2B,IACvL,EAAC,OAAO,SAAQ,CACjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACwCL,eAAsB,8BAA8B,EAClD,SAAS,OAGkB;AAC3B,QAAO,IAAI,IAAI,sBAAsB,GACjC,oBAAoB,IAAI,IAAI,sBAAsB,EAAE,OAAO,SAAS,GACpE"}
@@ -1 +1 @@
1
- {"version":3,"file":"sanitizePerspective.js","names":[],"sources":["../src/live/shared/sanitizePerspective.ts"],"sourcesContent":["import {validateApiPerspective, type ClientPerspective} from '@sanity/client'\n\n// @TODO split into sanitizePerspective and parsePerspective, expose parsePerspective on the /live export\nexport function sanitizePerspective(\n _perspective: unknown,\n fallback: 'drafts' | 'published',\n): Exclude<ClientPerspective, 'raw'> {\n const perspective =\n typeof _perspective === 'string' && _perspective.includes(',')\n ? _perspective.split(',')\n : Array.isArray(_perspective)\n ? _perspective.filter(Boolean)\n : _perspective\n try {\n validateApiPerspective(perspective)\n return perspective === 'raw' ? fallback : perspective\n } catch (err) {\n console.warn(`Invalid perspective:`, _perspective, perspective, err)\n return fallback\n }\n}\n"],"mappings":";AAGA,SAAgB,oBACd,cACA,UACmC;CACnC,MAAM,cACJ,OAAO,iBAAiB,YAAY,aAAa,SAAS,IAAI,GAC1D,aAAa,MAAM,IAAI,GACvB,MAAM,QAAQ,aAAa,GACzB,aAAa,OAAO,QAAQ,GAC5B;AACR,KAAI;AACF,yBAAuB,YAAY;AACnC,SAAO,gBAAgB,QAAQ,WAAW;UACnC,KAAK;AACZ,UAAQ,KAAK,wBAAwB,cAAc,aAAa,IAAI;AACpE,SAAO"}
1
+ {"version":3,"file":"sanitizePerspective.js","names":[],"sources":["../src/live/shared/sanitizePerspective.ts"],"sourcesContent":["import {validateApiPerspective} from '@sanity/client'\n\nimport type {LivePerspective} from '#live/types'\n\n// @TODO split into sanitizePerspective and parsePerspective, expose parsePerspective on the /live export\nexport function sanitizePerspective(\n _perspective: unknown,\n fallback: 'drafts' | 'published',\n): LivePerspective {\n const perspective =\n typeof _perspective === 'string' && _perspective.includes(',')\n ? _perspective.split(',')\n : Array.isArray(_perspective)\n ? _perspective.filter(Boolean)\n : _perspective\n try {\n validateApiPerspective(perspective)\n return perspective === 'raw' ? fallback : perspective\n } catch (err) {\n console.warn(`Invalid perspective:`, _perspective, perspective, err)\n return fallback\n }\n}\n"],"mappings":";AAKA,SAAgB,oBACd,cACA,UACiB;CACjB,MAAM,cACJ,OAAO,iBAAiB,YAAY,aAAa,SAAS,IAAI,GAC1D,aAAa,MAAM,IAAI,GACvB,MAAM,QAAQ,aAAa,GACzB,aAAa,OAAO,QAAQ,GAC5B;AACR,KAAI;AACF,yBAAuB,YAAY;AACnC,SAAO,gBAAgB,QAAQ,WAAW;UACnC,KAAK;AACZ,UAAQ,KAAK,wBAAwB,cAAc,aAAa,IAAI;AACpE,SAAO"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-sanity",
3
- "version": "13.0.0-cache-components.48",
3
+ "version": "13.0.0-cache-components.50",
4
4
  "description": "Sanity.io toolkit for Next.js",
5
5
  "keywords": [
6
6
  "live",
@@ -61,7 +61,7 @@
61
61
  "@portabletext/react": "^6.2.0",
62
62
  "@sanity/client": "^7.22.0",
63
63
  "@sanity/generate-help-url": "^4.0.0",
64
- "@sanity/preview-url-secret": "^4.0.5",
64
+ "@sanity/preview-url-secret": "^4.0.6",
65
65
  "@sanity/visual-editing": "^5.3.4",
66
66
  "@sanity/webhook": "^4.0.4",
67
67
  "groq": "^5.24.0",
@@ -76,7 +76,7 @@
76
76
  "@vitejs/plugin-react": "^6.0.1",
77
77
  "@vitest/coverage-v8": "^4.1.5",
78
78
  "js-yaml": "^4.1.1",
79
- "next": "16.3.0-canary.13",
79
+ "next": "16.3.0-canary.14",
80
80
  "publint": "^0.3.18",
81
81
  "react": "^19.2.6",
82
82
  "react-dom": "^19.2.6",