UNPKG

hydrogen-sanity

Version:
232 lines (225 loc) 9.1 kB
import { CacheLong, createWithCache } from '@shopify/hydrogen'; import { SanityClient, createClient } from '@sanity/client'; import { createElement, useMemo, lazy, Suspense, useSyncExternalStore, useId, useEffect } from 'react'; import { isPreviewEnabled, usePreviewMode } from './preview/index.js'; import { SanityProvider, useSanityProviderValue } from './_chunks-es/provider.js'; export { Sanity } from './_chunks-es/provider.js'; import { getPerspectiveFromUrl, supportsPerspectiveStack, getPerspective, hashQuery, isServer } from './_chunks-es/utils.js'; import { createImageUrlBuilder } from '@sanity/image-url'; import { jsx } from 'react/jsx-runtime'; import { useQuery as useQuery$1 } from '@sanity/react-loader'; export { useEncodeDataAttribute } from '@sanity/react-loader'; import { registerQuery } from './_chunks-es/registry.js'; export { createDataAttribute } from '@sanity/core-loader/create-data-attribute'; const DEFAULT_API_VERSION = "v2025-02-19"; const DEFAULT_CACHE_STRATEGY = CacheLong(); let didWarnAboutNoApiVersion = false; let didWarnAboutNoPerspectiveSupport = false; let didWarnAboutLoadQuery = false; async function createSanityContext(options) { const { cache, waitUntil = () => Promise.resolve(), request, preview, defaultStrategy } = options; const withCache = cache ? createWithCache({ cache, waitUntil, request }) : null; let client = options.client instanceof SanityClient ? options.client : createClient(options.client); if (client.config().apiVersion === "1") { if (process.env.NODE_ENV === "development" && !didWarnAboutNoApiVersion) { console.warn( ` No API version specified, defaulting to \`${DEFAULT_API_VERSION}\` which supports perspectives and Content Releases. You can find the latest version in the Sanity changelog: https://www.sanity.io/changelog. `.trim() ); didWarnAboutNoApiVersion = true; } client = client.withConfig({ apiVersion: DEFAULT_API_VERSION }); } let previewEnabled = false; if (preview) { if (!preview.token) { throw new Error("Enabling preview mode requires a token."); } previewEnabled = isPreviewEnabled(client.config().projectId, preview.session); if (previewEnabled) { const apiVersion2 = client.config().apiVersion; let perspective; const urlPerspective = getPerspectiveFromUrl(request.url); if (urlPerspective !== void 0 && !(Array.isArray(urlPerspective) && !supportsPerspectiveStack(apiVersion2))) { perspective = urlPerspective; } else if (supportsPerspectiveStack(apiVersion2)) { perspective = getPerspective(preview.session); } else { if (process.env.NODE_ENV === "development" && !didWarnAboutNoPerspectiveSupport) { console.warn( `API version \`${apiVersion2}\` does not support perspective stacks. Using \`previewDrafts\` perspective. Consider upgrading to \`v2025-02-19\` or later for full perspective support.` ); didWarnAboutNoPerspectiveSupport = true; } perspective = "previewDrafts"; } client = client.withConfig({ useCdn: false, token: preview.token, perspective }); } } const { apiHost, projectId, dataset, apiVersion } = client.config(); const providerValue = { projectId, dataset, apiHost, apiVersion, previewEnabled, perspective: client.config().perspective || "published", stegaEnabled: client.config().stega?.enabled ?? false }; return { /** * Loads a Sanity query with client-side loader support and Hydrogen cache integration. * Bypasses Hydrogen cache in preview mode. */ async loadQuery(query, params, loaderOptions) { const { setServerClient } = await import('@sanity/react-loader'); setServerClient(client); if (!previewEnabled && process.env.NODE_ENV === "development" && !didWarnAboutLoadQuery) { console.warn( `\`loadQuery\` is being called outside of preview mode. Consider using \`query\` instead, which automatically handles both preview and production modes efficiently, or use \`fetch\`. \`loadQuery\` is intended to be called conditionally in preview and visual editing contexts.` ); didWarnAboutLoadQuery = true; } if (!withCache || previewEnabled) { const { loadQuery } = await import('@sanity/react-loader'); const resolvedOptions = previewEnabled && !loaderOptions?.perspective ? { ...loaderOptions, perspective: client.config().perspective } : loaderOptions; return await loadQuery(query, params, resolvedOptions); } const cacheStrategy = loaderOptions?.hydrogen?.cache || defaultStrategy || DEFAULT_CACHE_STRATEGY; const queryHash = await hashQuery(query, params); const shouldCacheResult = loaderOptions?.hydrogen?.shouldCacheResult ?? (() => true); return await withCache.run( { cacheKey: queryHash, cacheStrategy, shouldCacheResult }, async ({ addDebugData }) => { const displayName = loaderOptions?.hydrogen?.debug?.displayName || "query Sanity"; addDebugData({ displayName }); const { loadQuery } = await import('@sanity/react-loader'); return await loadQuery(query, params, loaderOptions); } ); }, /** * Executes a Sanity query with Hydrogen cache integration. * Direct client fetch without loader integration. Bypasses cache in preview mode. */ async fetch(query, params = {}, fetchOptions) { if (!withCache || previewEnabled) { return await client.fetch(query, params, fetchOptions); } const cacheStrategy = fetchOptions?.hydrogen?.cache || defaultStrategy || DEFAULT_CACHE_STRATEGY; const queryHash = await hashQuery(query, params); return await withCache.run( { cacheKey: queryHash, cacheStrategy, shouldCacheResult: () => true }, async ({ addDebugData }) => { const displayName = fetchOptions?.hydrogen?.debug?.displayName || "fetch Sanity"; addDebugData({ displayName }); return await client.fetch(query, params, fetchOptions); } ); }, /** * Automatic query method that automatically adapts based on preview mode state. * Uses `loadQuery` (with client-side loader integration) when preview is enabled, `fetch` otherwise. * Bypasses cache in preview mode. */ async query(query, params, queryOptions) { return await (previewEnabled ? this.loadQuery : this.fetch)(query, params, queryOptions); }, /** The configured Sanity client instance */ client, /** Preview configuration with session-based state, undefined when preview is not configured */ preview: preview ? { ...preview, enabled: previewEnabled } : void 0, /** * React Provider component that serializes Sanity configuration across server-client boundary. */ SanityProvider({ children }) { return createElement( SanityProvider, { value: Object.freeze(providerValue) }, children ); } }; } function useImageUrlBuilder() { const { projectId, dataset, apiHost } = useSanityProviderValue(); return useMemo(() => { return createImageUrlBuilder({ config: () => ({ projectId, dataset, apiHost }) }); }, [apiHost, dataset, projectId]); } function useImageUrl(source) { const builder = useImageUrlBuilder(); return builder.image(source); } function SanityQueryFallback() { return null; } function useIsHydrated() { return useSyncExternalStore( // eslint-disable-next-line no-empty-function () => () => { }, () => true, () => false ); } const QueryClient = isServer() ? SanityQueryFallback : lazy( () => ( /** * `lazy` expects the component as the default export * @see https://react.dev/reference/react/lazy */ import('./_chunks-es/Query.client.js') ) ); const noopEncodeDataAttribute = Object.assign(() => void 0, { scope: () => noopEncodeDataAttribute }); function Query({ query, params, options, children, ...suspenseProps }) { const isPreviewMode = usePreviewMode(); const isHydrated = useIsHydrated(); if (isPreviewMode && isHydrated) { return /* @__PURE__ */ jsx(Suspense, { ...suspenseProps, fallback: suspenseProps.fallback ?? /* @__PURE__ */ jsx(SanityQueryFallback, {}), children: /* @__PURE__ */ jsx( QueryClient, { query, params, options, children } ) }); } return children(options.initial, noopEncodeDataAttribute); } function useQuery(query, params, options) { const id = useId(); useEffect(() => { const unregister = registerQuery(id); return unregister; }, [id]); return useQuery$1(query, params, options); } export { DEFAULT_API_VERSION, DEFAULT_CACHE_STRATEGY, Query, createSanityContext, getPerspectiveFromUrl, useImageUrl, useImageUrlBuilder, useQuery, useSanityProviderValue }; //# sourceMappingURL=index.js.map