hydrogen-sanity 3.2.0 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Sanity.io <hello@sanity.io>
3
+ Copyright (c) 2024 Sanity.io <hello@sanity.io>
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -33,17 +33,31 @@ Update the server file to include the Sanity client:
33
33
  // ./server.ts
34
34
 
35
35
  // ...all other imports
36
- import {createSanityClient, PreviewSession} from 'hydrogen-sanity';
36
+ import {createSanityClient} from 'hydrogen-sanity';
37
37
 
38
38
  // Inside the default export
39
39
  export default () => {
40
40
 
41
41
  // 1. Add check for Preview Session
42
+ const secrets = [env.SESSION_SECRET];
42
43
  const [cache, session, previewSession] = await Promise.all([
43
44
  caches.open('hydrogen'),
44
- HydrogenSession.init(request, [env.SESSION_SECRET]),
45
+ HydrogenSession.init(request, secrets),
45
46
  // 👇 Add preview session
46
- PreviewSession.init(request, [env.SESSION_SECRET]),
47
+ (async function createPreviewSession() {
48
+ const storage = createCookieSessionStorage({
49
+ cookie: {
50
+ name: '__preview',
51
+ httpOnly: true,
52
+ sameSite: true,
53
+ secrets,
54
+ },
55
+ });
56
+
57
+ const session = await storage.getSession(request.headers.get("Cookie"));
58
+
59
+ return new HydrogenSession(storage, session);
60
+ })(),
47
61
  ]);
48
62
 
49
63
  // Leave all other functions like the storefront client as-is
package/dist/index.d.ts CHANGED
@@ -27,7 +27,7 @@ export declare function createSanityClient(options: CreateSanityClientOptions):
27
27
  declare type CreateSanityClientOptions = EnvironmentOptions & {
28
28
  config: ClientConfig & Required<Pick<ClientConfig, 'projectId' | 'dataset'>>
29
29
  preview?: {
30
- session: PreviewSession
30
+ session: SessionLike
31
31
  token: string
32
32
  perspective?: ClientPerspective
33
33
  }
@@ -58,7 +58,7 @@ export declare function getPreview<
58
58
  >(context: T): ClientConfig_2 | undefined
59
59
 
60
60
  export declare function isPreviewModeEnabled(preview?: Sanity['preview']): preview is {
61
- session: PreviewSession
61
+ session: SessionLike
62
62
  projectId: string
63
63
  dataset: string
64
64
  token: string
@@ -78,7 +78,7 @@ declare type PreviewProps<T> = {
78
78
  export declare function PreviewProvider(props: SanityPreviewProps): ReactElement
79
79
 
80
80
  /**
81
- * TODO: needs inline documentation
81
+ * @deprecated Use `HydrogenSession` or another `SessionLike` implementation instead. This will be removed in a future release.
82
82
  */
83
83
  export declare class PreviewSession {
84
84
  #private
@@ -94,13 +94,13 @@ export declare type Sanity = {
94
94
  client: SanityClient
95
95
  preview?:
96
96
  | {
97
- session: PreviewSession
97
+ session: SessionLike
98
98
  projectId: string
99
99
  dataset: string
100
100
  token: string
101
101
  }
102
102
  | {
103
- session: PreviewSession
103
+ session: SessionLike
104
104
  }
105
105
  query<T>(options: useSanityQuery): Promise<T>
106
106
  query<T>(options: useRawSanityQuery): Promise<RawQueryResponse<T>>
@@ -119,6 +119,13 @@ declare type SanityPreviewProps = Omit<LiveQueryProviderProps, 'client'> & {
119
119
  previewConfig?: ClientConfig
120
120
  }
121
121
 
122
+ export declare interface SessionLike {
123
+ has(key: string): boolean
124
+ destroy(): Promise<string>
125
+ set(key: string, value: any): void
126
+ commit(): Promise<string>
127
+ }
128
+
122
129
  /**
123
130
  * Create an SHA-256 hash as a hex string
124
131
  * @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/client.ts","../src/preview/context.tsx","../src/preview/PreviewProvider.tsx","../src/preview/PreviewSession.ts","../src/preview/SanityPreview.tsx","../src/preview/getPreview.ts"],"sourcesContent":["import {\n type ClientConfig,\n type ClientPerspective,\n createClient,\n type FilteredResponseQueryOptions,\n type QueryParams,\n type RawQueryResponse,\n type SanityClient,\n type UnfilteredResponseQueryOptions,\n} from '@sanity/preview-kit/client'\nimport {CacheLong, createWithCache} from '@shopify/hydrogen'\n\nimport type {PreviewSession} from './preview'\nimport type {CachingStrategy, EnvironmentOptions} from './types'\n\ntype CreateSanityClientOptions = EnvironmentOptions & {\n config: ClientConfig & Required<Pick<ClientConfig, 'projectId' | 'dataset'>>\n preview?: {\n session: PreviewSession\n token: string\n perspective?: ClientPerspective\n }\n}\n\ntype useSanityQuery = {\n query: string\n params?: QueryParams\n cache?: CachingStrategy\n queryOptions?: FilteredResponseQueryOptions\n}\n\ntype useRawSanityQuery = {\n query: string\n params?: QueryParams\n cache?: CachingStrategy\n queryOptions: UnfilteredResponseQueryOptions\n}\n\nexport type Sanity = {\n client: SanityClient\n preview?:\n | {session: PreviewSession; projectId: string; dataset: string; token: string}\n | {session: PreviewSession}\n query<T>(options: useSanityQuery): Promise<T>\n query<T>(options: useRawSanityQuery): Promise<RawQueryResponse<T>>\n}\n\n/**\n * Create Sanity provider with API client.\n */\nexport function createSanityClient(options: CreateSanityClientOptions): Sanity {\n const {cache, waitUntil, preview, config} = options\n\n const sanity: Sanity = {\n client: createClient(config),\n async query<T = any>({\n query,\n params,\n cache: strategy = CacheLong(),\n queryOptions,\n }: useSanityQuery | useRawSanityQuery) {\n const queryHash = await hashQuery(query, params)\n const withCache = createWithCache<T | RawQueryResponse<T>>({\n cache,\n waitUntil,\n })\n\n return withCache(queryHash, strategy, () => {\n if (!queryOptions) {\n return sanity.client.fetch(query, params)\n }\n\n // NOTE: satisfy union type\n if (queryOptions.filterResponse === false) {\n return sanity.client.fetch(query, params, queryOptions)\n }\n\n return sanity.client.fetch(query, params, queryOptions)\n })\n },\n }\n\n if (preview) {\n sanity.preview = {session: preview.session}\n\n if (preview.session.has('projectId')) {\n sanity.preview = {\n ...sanity.preview,\n projectId: config.projectId,\n dataset: config.dataset,\n token: preview.token,\n }\n\n sanity.client = sanity.client.withConfig({\n useCdn: false,\n token: preview.token,\n perspective: preview.perspective || 'previewDrafts',\n ignoreBrowserTokenWarning: true,\n })\n\n sanity.query = ({query, params, queryOptions}) => {\n if (!queryOptions) {\n return sanity.client.fetch(query, params)\n }\n\n // NOTE: satisfy union type\n if (queryOptions.filterResponse === false) {\n return sanity.client.fetch(query, params, queryOptions)\n }\n\n return sanity.client.fetch(query, params, queryOptions)\n }\n }\n }\n\n return sanity\n}\n\nexport function isPreviewModeEnabled(\n preview?: Sanity['preview']\n): preview is {session: PreviewSession; projectId: string; dataset: string; token: string} {\n // @ts-expect-error\n return Boolean(preview && preview.token && preview.token !== null)\n}\n\n/**\n * Create an SHA-256 hash as a hex string\n * @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string\n */\nexport async function sha256(message: string): Promise<string> {\n // encode as UTF-8\n const messageBuffer = await new TextEncoder().encode(message)\n // hash the message\n const hashBuffer = await crypto.subtle.digest('SHA-256', messageBuffer)\n // convert bytes to hex string\n return Array.from(new Uint8Array(hashBuffer))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\n/**\n * Hash query and its parameters for use as cache key\n * NOTE: Oxygen deployment will break if the cache key is long or contains `\\n`\n */\nfunction hashQuery(\n query: useSanityQuery['query'],\n params: useSanityQuery['params']\n): Promise<string> {\n let hash = query\n\n if (params !== null) {\n hash += JSON.stringify(params)\n }\n\n return sha256(hash)\n}\n","import {createContext, useContext} from 'react'\n\nexport const PreviewContext = createContext<{projectId: string} | undefined>(undefined)\n\n/** TODO: needs inline documentation */\nexport const usePreviewContext = () => useContext(PreviewContext)\n","/* eslint-disable react/require-default-props */\nimport type {LiveQueryProviderProps} from '@sanity/preview-kit'\nimport {type ClientConfig, createClient} from '@sanity/preview-kit/client'\nimport {\n lazy,\n type ReactElement,\n type ReactNode,\n Suspense,\n useEffect,\n useState,\n useTransition,\n} from 'react'\n\nimport {PreviewContext} from './context'\n\nconst LiveQueryProvider = lazy(() =>\n import('@sanity/preview-kit').then((m) => ({default: m.LiveQueryProvider}))\n)\n\ntype SanityPreviewProps = Omit<LiveQueryProviderProps, 'client'> & {\n fallback?: ReactNode\n previewConfig?: ClientConfig\n}\n\n/**\n * TODO: inline documentation\n * @see https://www.sanity.io/docs/preview-content-on-site\n */\nexport function PreviewProvider(props: SanityPreviewProps): ReactElement {\n const {children, previewConfig, fallback = children, ...rest} = props\n\n const [, startTransition] = useTransition()\n const [hydrated, setHydrated] = useState(false)\n useEffect(() => startTransition(() => setHydrated(true)), [])\n\n if (!hydrated || !previewConfig || !previewConfig.projectId) {\n return <>{children}</>\n }\n\n const client = createClient(previewConfig)\n\n return (\n <PreviewContext.Provider value={{projectId: previewConfig.projectId}}>\n <Suspense fallback={fallback}>\n <LiveQueryProvider {...rest} client={client}>\n {children}\n </LiveQueryProvider>\n </Suspense>\n </PreviewContext.Provider>\n )\n}\n","import {createCookieSessionStorage, type Session, type SessionStorage} from '@shopify/remix-oxygen'\n\n/**\n * TODO: needs inline documentation\n */\nexport class PreviewSession {\n #sessionStorage: SessionStorage\n #session: Session\n\n constructor(sessionStorage: SessionStorage, session: Session) {\n this.#sessionStorage = sessionStorage\n this.#session = session\n }\n\n static async init(request: Request, secrets: string[]): Promise<PreviewSession> {\n const storage = createCookieSessionStorage({\n cookie: {\n name: '__preview',\n httpOnly: true,\n sameSite: true,\n secrets,\n },\n })\n\n const session = await storage.getSession(request.headers.get('Cookie'))\n\n return new this(storage, session)\n }\n\n has(key: string): boolean {\n return this.#session.has(key)\n }\n\n // get(key: string) {\n // return this.session.get(key);\n // }\n\n destroy(): Promise<string> {\n return this.#sessionStorage.destroySession(this.#session)\n }\n\n // unset(key: string) {\n // this.session.unset(key);\n // }\n\n // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\n set(key: string, value: any): void {\n this.#session.set(key, value)\n }\n\n commit(): Promise<string> {\n return this.#sessionStorage.commitSession(this.#session)\n }\n}\n","/* eslint-disable react/require-default-props */\nimport type {QueryParams} from '@sanity/client'\nimport {useLiveQuery} from '@sanity/preview-kit'\nimport {type ReactElement, type ReactNode} from 'react'\n\nimport {usePreviewContext} from './context'\n\ntype PreviewProps<T> = {\n data: T\n children: ReactNode | ((data?: T | null) => ReactNode)\n query?: string | null\n params?: QueryParams\n}\n\n/**\n * Component to use for rendering in preview mode\n *\n * When provided a Sanity query and render prop,\n * changes will be streamed in the client\n */\nexport function SanityPreview<T = unknown>(props: PreviewProps<T>): ReactElement {\n const {data, children, query, params} = props\n const isPreview = Boolean(usePreviewContext())\n\n if (typeof children !== 'function') {\n return <>{children}</>\n }\n\n if (isPreview && query) {\n return (\n <ResolvePreview<typeof data> query={query} params={params} initialData={data}>\n {children}\n </ResolvePreview>\n )\n }\n\n return <>{children(data)}</>\n}\n\ntype ResolvePreviewProps<T> = {\n initialData?: T | null\n query: string\n params?: QueryParams\n children: (data?: T | null) => ReactNode\n}\n\n/**\n * Subscribe to live preview and delegate rendering to consumer\n */\nfunction ResolvePreview<T = unknown>(props: ResolvePreviewProps<T>) {\n const {initialData, query, params, children} = props\n const [data] = useLiveQuery(initialData, query, params)\n\n return <>{children(data)}</>\n}\n","import type {ClientConfig} from '@sanity/client'\n\nimport {isPreviewModeEnabled, Sanity} from '../client'\n\n/** TODO: inline documentation */\nexport function getPreview<T extends {sanity: Sanity}>(context: T): ClientConfig | undefined {\n return isPreviewModeEnabled(context.sanity.preview)\n ? {\n ...context.sanity.client.config(),\n }\n : undefined\n}\n"],"names":["isPreviewModeEnabled","preview","Boolean","token","async","sha256","message","messageBuffer","TextEncoder","encode","hashBuffer","crypto","subtle","digest","Array","from","Uint8Array","map","b","toString","padStart","join","PreviewContext","createContext","usePreviewContext","useContext","LiveQueryProvider","lazy","import","then","m","default","_sessionStorage","_session","ResolvePreview","props","initialData","query","params","children","data","useLiveQuery","jsx","Fragment","WeakMap","exports","PreviewProvider","previewConfig","fallback","rest","startTransition","useTransition","hydrated","setHydrated","useState","useEffect","projectId","client","createClient","Provider","value","Suspense","PreviewSession","constructor","sessionStorage","session","__privateAdd","this","__privateSet","init","request","secrets","storage","createCookieSessionStorage","cookie","name","httpOnly","sameSite","getSession","headers","get","has","key","__privateGet","destroy","destroySession","set","commit","commitSession","SanityPreview","isPreview","createSanityClient","options","cache","waitUntil","config","sanity","_ref","strategy","CacheLong","queryOptions","queryHash","hash","JSON","stringify","hashQuery","createWithCache","withCache","filterResponse","fetch","dataset","withConfig","useCdn","perspective","ignoreBrowserTokenWarning","_ref2","getPreview","context"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/client.ts","../src/preview/context.tsx","../src/preview/PreviewProvider.tsx","../src/preview/PreviewSession.ts","../src/preview/SanityPreview.tsx","../src/preview/getPreview.ts"],"sourcesContent":["import {\n type ClientConfig,\n type ClientPerspective,\n createClient,\n type FilteredResponseQueryOptions,\n type QueryParams,\n type RawQueryResponse,\n type SanityClient,\n type UnfilteredResponseQueryOptions,\n} from '@sanity/preview-kit/client'\nimport {CacheLong, createWithCache} from '@shopify/hydrogen'\n\nimport type {CachingStrategy, EnvironmentOptions, SessionLike} from './types'\n\ntype CreateSanityClientOptions = EnvironmentOptions & {\n config: ClientConfig & Required<Pick<ClientConfig, 'projectId' | 'dataset'>>\n preview?: {\n session: SessionLike\n token: string\n perspective?: ClientPerspective\n }\n}\n\ntype useSanityQuery = {\n query: string\n params?: QueryParams\n cache?: CachingStrategy\n queryOptions?: FilteredResponseQueryOptions\n}\n\ntype useRawSanityQuery = {\n query: string\n params?: QueryParams\n cache?: CachingStrategy\n queryOptions: UnfilteredResponseQueryOptions\n}\n\nexport type Sanity = {\n client: SanityClient\n preview?:\n | {session: SessionLike; projectId: string; dataset: string; token: string}\n | {session: SessionLike}\n query<T>(options: useSanityQuery): Promise<T>\n query<T>(options: useRawSanityQuery): Promise<RawQueryResponse<T>>\n}\n\n/**\n * Create Sanity provider with API client.\n */\nexport function createSanityClient(options: CreateSanityClientOptions): Sanity {\n const {cache, waitUntil, preview, config} = options\n\n const sanity: Sanity = {\n client: createClient(config),\n async query<T = any>({\n query,\n params,\n cache: strategy = CacheLong(),\n queryOptions,\n }: useSanityQuery | useRawSanityQuery) {\n const queryHash = await hashQuery(query, params)\n const withCache = createWithCache<T | RawQueryResponse<T>>({\n cache,\n waitUntil,\n })\n\n return withCache(queryHash, strategy, () => {\n if (!queryOptions) {\n return sanity.client.fetch(query, params)\n }\n\n // NOTE: satisfy union type\n if (queryOptions.filterResponse === false) {\n return sanity.client.fetch(query, params, queryOptions)\n }\n\n return sanity.client.fetch(query, params, queryOptions)\n })\n },\n }\n\n if (preview) {\n sanity.preview = {session: preview.session}\n\n if (preview.session.has('projectId')) {\n sanity.preview = {\n ...sanity.preview,\n projectId: config.projectId,\n dataset: config.dataset,\n token: preview.token,\n }\n\n sanity.client = sanity.client.withConfig({\n useCdn: false,\n token: preview.token,\n perspective: preview.perspective || 'previewDrafts',\n ignoreBrowserTokenWarning: true,\n })\n\n sanity.query = ({query, params, queryOptions}) => {\n if (!queryOptions) {\n return sanity.client.fetch(query, params)\n }\n\n // NOTE: satisfy union type\n if (queryOptions.filterResponse === false) {\n return sanity.client.fetch(query, params, queryOptions)\n }\n\n return sanity.client.fetch(query, params, queryOptions)\n }\n }\n }\n\n return sanity\n}\n\nexport function isPreviewModeEnabled(\n preview?: Sanity['preview']\n): preview is {session: SessionLike; projectId: string; dataset: string; token: string} {\n // @ts-expect-error\n return Boolean(preview && preview.token && preview.token !== null)\n}\n\n/**\n * Create an SHA-256 hash as a hex string\n * @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string\n */\nexport async function sha256(message: string): Promise<string> {\n // encode as UTF-8\n const messageBuffer = await new TextEncoder().encode(message)\n // hash the message\n const hashBuffer = await crypto.subtle.digest('SHA-256', messageBuffer)\n // convert bytes to hex string\n return Array.from(new Uint8Array(hashBuffer))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\n/**\n * Hash query and its parameters for use as cache key\n * NOTE: Oxygen deployment will break if the cache key is long or contains `\\n`\n */\nfunction hashQuery(\n query: useSanityQuery['query'],\n params: useSanityQuery['params']\n): Promise<string> {\n let hash = query\n\n if (params !== null) {\n hash += JSON.stringify(params)\n }\n\n return sha256(hash)\n}\n","import {createContext, useContext} from 'react'\n\nexport const PreviewContext = createContext<{projectId: string} | undefined>(undefined)\n\n/** TODO: needs inline documentation */\nexport const usePreviewContext = () => useContext(PreviewContext)\n","/* eslint-disable react/require-default-props */\nimport type {LiveQueryProviderProps} from '@sanity/preview-kit'\nimport {type ClientConfig, createClient} from '@sanity/preview-kit/client'\nimport {\n lazy,\n type ReactElement,\n type ReactNode,\n Suspense,\n useEffect,\n useState,\n useTransition,\n} from 'react'\n\nimport {PreviewContext} from './context'\n\nconst LiveQueryProvider = lazy(() =>\n import('@sanity/preview-kit').then((m) => ({default: m.LiveQueryProvider}))\n)\n\ntype SanityPreviewProps = Omit<LiveQueryProviderProps, 'client'> & {\n fallback?: ReactNode\n previewConfig?: ClientConfig\n}\n\n/**\n * TODO: inline documentation\n * @see https://www.sanity.io/docs/preview-content-on-site\n */\nexport function PreviewProvider(props: SanityPreviewProps): ReactElement {\n const {children, previewConfig, fallback = children, ...rest} = props\n\n const [, startTransition] = useTransition()\n const [hydrated, setHydrated] = useState(false)\n useEffect(() => startTransition(() => setHydrated(true)), [])\n\n if (!hydrated || !previewConfig || !previewConfig.projectId) {\n return <>{children}</>\n }\n\n const client = createClient(previewConfig)\n\n return (\n <PreviewContext.Provider value={{projectId: previewConfig.projectId}}>\n <Suspense fallback={fallback}>\n <LiveQueryProvider {...rest} client={client}>\n {children}\n </LiveQueryProvider>\n </Suspense>\n </PreviewContext.Provider>\n )\n}\n","import {createCookieSessionStorage, type Session, type SessionStorage} from '@shopify/remix-oxygen'\n\n/**\n * @deprecated Use `HydrogenSession` or another `SessionLike` implementation instead. This will be removed in a future release.\n */\nexport class PreviewSession {\n #sessionStorage: SessionStorage\n #session: Session\n\n constructor(sessionStorage: SessionStorage, session: Session) {\n this.#sessionStorage = sessionStorage\n this.#session = session\n }\n\n static async init(request: Request, secrets: string[]): Promise<PreviewSession> {\n const storage = createCookieSessionStorage({\n cookie: {\n name: '__preview',\n httpOnly: true,\n sameSite: true,\n secrets,\n },\n })\n\n const session = await storage.getSession(request.headers.get('Cookie'))\n\n return new this(storage, session)\n }\n\n has(key: string): boolean {\n return this.#session.has(key)\n }\n\n // get(key: string) {\n // return this.session.get(key);\n // }\n\n destroy(): Promise<string> {\n return this.#sessionStorage.destroySession(this.#session)\n }\n\n // unset(key: string) {\n // this.session.unset(key);\n // }\n\n // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\n set(key: string, value: any): void {\n this.#session.set(key, value)\n }\n\n commit(): Promise<string> {\n return this.#sessionStorage.commitSession(this.#session)\n }\n}\n","/* eslint-disable react/require-default-props */\nimport type {QueryParams} from '@sanity/client'\nimport {useLiveQuery} from '@sanity/preview-kit'\nimport {type ReactElement, type ReactNode} from 'react'\n\nimport {usePreviewContext} from './context'\n\ntype PreviewProps<T> = {\n data: T\n children: ReactNode | ((data?: T | null) => ReactNode)\n query?: string | null\n params?: QueryParams\n}\n\n/**\n * Component to use for rendering in preview mode\n *\n * When provided a Sanity query and render prop,\n * changes will be streamed in the client\n */\nexport function SanityPreview<T = unknown>(props: PreviewProps<T>): ReactElement {\n const {data, children, query, params} = props\n const isPreview = Boolean(usePreviewContext())\n\n if (typeof children !== 'function') {\n return <>{children}</>\n }\n\n if (isPreview && query) {\n return (\n <ResolvePreview<typeof data> query={query} params={params} initialData={data}>\n {children}\n </ResolvePreview>\n )\n }\n\n return <>{children(data)}</>\n}\n\ntype ResolvePreviewProps<T> = {\n initialData?: T | null\n query: string\n params?: QueryParams\n children: (data?: T | null) => ReactNode\n}\n\n/**\n * Subscribe to live preview and delegate rendering to consumer\n */\nfunction ResolvePreview<T = unknown>(props: ResolvePreviewProps<T>) {\n const {initialData, query, params, children} = props\n const [data] = useLiveQuery(initialData, query, params)\n\n return <>{children(data)}</>\n}\n","import type {ClientConfig} from '@sanity/client'\n\nimport {isPreviewModeEnabled, Sanity} from '../client'\n\n/** TODO: inline documentation */\nexport function getPreview<T extends {sanity: Sanity}>(context: T): ClientConfig | undefined {\n return isPreviewModeEnabled(context.sanity.preview)\n ? {\n ...context.sanity.client.config(),\n }\n : undefined\n}\n"],"names":["isPreviewModeEnabled","preview","Boolean","token","async","sha256","message","messageBuffer","TextEncoder","encode","hashBuffer","crypto","subtle","digest","Array","from","Uint8Array","map","b","toString","padStart","join","PreviewContext","createContext","usePreviewContext","useContext","LiveQueryProvider","lazy","import","then","m","default","_sessionStorage","_session","ResolvePreview","props","initialData","query","params","children","data","useLiveQuery","jsx","Fragment","WeakMap","exports","PreviewProvider","previewConfig","fallback","rest","startTransition","useTransition","hydrated","setHydrated","useState","useEffect","projectId","client","createClient","Provider","value","Suspense","PreviewSession","constructor","sessionStorage","session","__privateAdd","this","__privateSet","init","request","secrets","storage","createCookieSessionStorage","cookie","name","httpOnly","sameSite","getSession","headers","get","has","key","__privateGet","destroy","destroySession","set","commit","commitSession","SanityPreview","isPreview","createSanityClient","options","cache","waitUntil","config","sanity","_ref","strategy","CacheLong","queryOptions","queryHash","hash","JSON","stringify","hashQuery","createWithCache","withCache","filterResponse","fetch","dataset","withConfig","useCdn","perspective","ignoreBrowserTokenWarning","_ref2","getPreview","context"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/client.ts","../src/preview/context.tsx","../src/preview/getPreview.ts","../src/preview/PreviewProvider.tsx","../src/preview/PreviewSession.ts","../src/preview/SanityPreview.tsx"],"sourcesContent":["import {\n type ClientConfig,\n type ClientPerspective,\n createClient,\n type FilteredResponseQueryOptions,\n type QueryParams,\n type RawQueryResponse,\n type SanityClient,\n type UnfilteredResponseQueryOptions,\n} from '@sanity/preview-kit/client'\nimport {CacheLong, createWithCache} from '@shopify/hydrogen'\n\nimport type {PreviewSession} from './preview'\nimport type {CachingStrategy, EnvironmentOptions} from './types'\n\ntype CreateSanityClientOptions = EnvironmentOptions & {\n config: ClientConfig & Required<Pick<ClientConfig, 'projectId' | 'dataset'>>\n preview?: {\n session: PreviewSession\n token: string\n perspective?: ClientPerspective\n }\n}\n\ntype useSanityQuery = {\n query: string\n params?: QueryParams\n cache?: CachingStrategy\n queryOptions?: FilteredResponseQueryOptions\n}\n\ntype useRawSanityQuery = {\n query: string\n params?: QueryParams\n cache?: CachingStrategy\n queryOptions: UnfilteredResponseQueryOptions\n}\n\nexport type Sanity = {\n client: SanityClient\n preview?:\n | {session: PreviewSession; projectId: string; dataset: string; token: string}\n | {session: PreviewSession}\n query<T>(options: useSanityQuery): Promise<T>\n query<T>(options: useRawSanityQuery): Promise<RawQueryResponse<T>>\n}\n\n/**\n * Create Sanity provider with API client.\n */\nexport function createSanityClient(options: CreateSanityClientOptions): Sanity {\n const {cache, waitUntil, preview, config} = options\n\n const sanity: Sanity = {\n client: createClient(config),\n async query<T = any>({\n query,\n params,\n cache: strategy = CacheLong(),\n queryOptions,\n }: useSanityQuery | useRawSanityQuery) {\n const queryHash = await hashQuery(query, params)\n const withCache = createWithCache<T | RawQueryResponse<T>>({\n cache,\n waitUntil,\n })\n\n return withCache(queryHash, strategy, () => {\n if (!queryOptions) {\n return sanity.client.fetch(query, params)\n }\n\n // NOTE: satisfy union type\n if (queryOptions.filterResponse === false) {\n return sanity.client.fetch(query, params, queryOptions)\n }\n\n return sanity.client.fetch(query, params, queryOptions)\n })\n },\n }\n\n if (preview) {\n sanity.preview = {session: preview.session}\n\n if (preview.session.has('projectId')) {\n sanity.preview = {\n ...sanity.preview,\n projectId: config.projectId,\n dataset: config.dataset,\n token: preview.token,\n }\n\n sanity.client = sanity.client.withConfig({\n useCdn: false,\n token: preview.token,\n perspective: preview.perspective || 'previewDrafts',\n ignoreBrowserTokenWarning: true,\n })\n\n sanity.query = ({query, params, queryOptions}) => {\n if (!queryOptions) {\n return sanity.client.fetch(query, params)\n }\n\n // NOTE: satisfy union type\n if (queryOptions.filterResponse === false) {\n return sanity.client.fetch(query, params, queryOptions)\n }\n\n return sanity.client.fetch(query, params, queryOptions)\n }\n }\n }\n\n return sanity\n}\n\nexport function isPreviewModeEnabled(\n preview?: Sanity['preview']\n): preview is {session: PreviewSession; projectId: string; dataset: string; token: string} {\n // @ts-expect-error\n return Boolean(preview && preview.token && preview.token !== null)\n}\n\n/**\n * Create an SHA-256 hash as a hex string\n * @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string\n */\nexport async function sha256(message: string): Promise<string> {\n // encode as UTF-8\n const messageBuffer = await new TextEncoder().encode(message)\n // hash the message\n const hashBuffer = await crypto.subtle.digest('SHA-256', messageBuffer)\n // convert bytes to hex string\n return Array.from(new Uint8Array(hashBuffer))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\n/**\n * Hash query and its parameters for use as cache key\n * NOTE: Oxygen deployment will break if the cache key is long or contains `\\n`\n */\nfunction hashQuery(\n query: useSanityQuery['query'],\n params: useSanityQuery['params']\n): Promise<string> {\n let hash = query\n\n if (params !== null) {\n hash += JSON.stringify(params)\n }\n\n return sha256(hash)\n}\n","import {createContext, useContext} from 'react'\n\nexport const PreviewContext = createContext<{projectId: string} | undefined>(undefined)\n\n/** TODO: needs inline documentation */\nexport const usePreviewContext = () => useContext(PreviewContext)\n","import type {ClientConfig} from '@sanity/client'\n\nimport {isPreviewModeEnabled, Sanity} from '../client'\n\n/** TODO: inline documentation */\nexport function getPreview<T extends {sanity: Sanity}>(context: T): ClientConfig | undefined {\n return isPreviewModeEnabled(context.sanity.preview)\n ? {\n ...context.sanity.client.config(),\n }\n : undefined\n}\n","/* eslint-disable react/require-default-props */\nimport type {LiveQueryProviderProps} from '@sanity/preview-kit'\nimport {type ClientConfig, createClient} from '@sanity/preview-kit/client'\nimport {\n lazy,\n type ReactElement,\n type ReactNode,\n Suspense,\n useEffect,\n useState,\n useTransition,\n} from 'react'\n\nimport {PreviewContext} from './context'\n\nconst LiveQueryProvider = lazy(() =>\n import('@sanity/preview-kit').then((m) => ({default: m.LiveQueryProvider}))\n)\n\ntype SanityPreviewProps = Omit<LiveQueryProviderProps, 'client'> & {\n fallback?: ReactNode\n previewConfig?: ClientConfig\n}\n\n/**\n * TODO: inline documentation\n * @see https://www.sanity.io/docs/preview-content-on-site\n */\nexport function PreviewProvider(props: SanityPreviewProps): ReactElement {\n const {children, previewConfig, fallback = children, ...rest} = props\n\n const [, startTransition] = useTransition()\n const [hydrated, setHydrated] = useState(false)\n useEffect(() => startTransition(() => setHydrated(true)), [])\n\n if (!hydrated || !previewConfig || !previewConfig.projectId) {\n return <>{children}</>\n }\n\n const client = createClient(previewConfig)\n\n return (\n <PreviewContext.Provider value={{projectId: previewConfig.projectId}}>\n <Suspense fallback={fallback}>\n <LiveQueryProvider {...rest} client={client}>\n {children}\n </LiveQueryProvider>\n </Suspense>\n </PreviewContext.Provider>\n )\n}\n","import {createCookieSessionStorage, type Session, type SessionStorage} from '@shopify/remix-oxygen'\n\n/**\n * TODO: needs inline documentation\n */\nexport class PreviewSession {\n #sessionStorage: SessionStorage\n #session: Session\n\n constructor(sessionStorage: SessionStorage, session: Session) {\n this.#sessionStorage = sessionStorage\n this.#session = session\n }\n\n static async init(request: Request, secrets: string[]): Promise<PreviewSession> {\n const storage = createCookieSessionStorage({\n cookie: {\n name: '__preview',\n httpOnly: true,\n sameSite: true,\n secrets,\n },\n })\n\n const session = await storage.getSession(request.headers.get('Cookie'))\n\n return new this(storage, session)\n }\n\n has(key: string): boolean {\n return this.#session.has(key)\n }\n\n // get(key: string) {\n // return this.session.get(key);\n // }\n\n destroy(): Promise<string> {\n return this.#sessionStorage.destroySession(this.#session)\n }\n\n // unset(key: string) {\n // this.session.unset(key);\n // }\n\n // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\n set(key: string, value: any): void {\n this.#session.set(key, value)\n }\n\n commit(): Promise<string> {\n return this.#sessionStorage.commitSession(this.#session)\n }\n}\n","/* eslint-disable react/require-default-props */\nimport type {QueryParams} from '@sanity/client'\nimport {useLiveQuery} from '@sanity/preview-kit'\nimport {type ReactElement, type ReactNode} from 'react'\n\nimport {usePreviewContext} from './context'\n\ntype PreviewProps<T> = {\n data: T\n children: ReactNode | ((data?: T | null) => ReactNode)\n query?: string | null\n params?: QueryParams\n}\n\n/**\n * Component to use for rendering in preview mode\n *\n * When provided a Sanity query and render prop,\n * changes will be streamed in the client\n */\nexport function SanityPreview<T = unknown>(props: PreviewProps<T>): ReactElement {\n const {data, children, query, params} = props\n const isPreview = Boolean(usePreviewContext())\n\n if (typeof children !== 'function') {\n return <>{children}</>\n }\n\n if (isPreview && query) {\n return (\n <ResolvePreview<typeof data> query={query} params={params} initialData={data}>\n {children}\n </ResolvePreview>\n )\n }\n\n return <>{children(data)}</>\n}\n\ntype ResolvePreviewProps<T> = {\n initialData?: T | null\n query: string\n params?: QueryParams\n children: (data?: T | null) => ReactNode\n}\n\n/**\n * Subscribe to live preview and delegate rendering to consumer\n */\nfunction ResolvePreview<T = unknown>(props: ResolvePreviewProps<T>) {\n const {initialData, query, params, children} = props\n const [data] = useLiveQuery(initialData, query, params)\n\n return <>{children(data)}</>\n}\n"],"names":["createSanityClient","options","cache","waitUntil","preview","config","sanity","client","createClient","query","_ref","params","strategy","CacheLong","queryOptions","queryHash","hash","JSON","stringify","sha256","hashQuery","createWithCache","withCache","filterResponse","fetch","session","has","projectId","dataset","token","withConfig","useCdn","perspective","ignoreBrowserTokenWarning","_ref2","isPreviewModeEnabled","Boolean","async","message","messageBuffer","TextEncoder","encode","hashBuffer","crypto","subtle","digest","Array","from","Uint8Array","map","b","toString","padStart","join","PreviewContext","createContext","usePreviewContext","useContext","getPreview","context","LiveQueryProvider","lazy","import","then","m","default","PreviewProvider","props","children","previewConfig","fallback","rest","startTransition","useTransition","hydrated","setHydrated","useState","useEffect","jsx","Provider","value","Suspense","_sessionStorage","_session","PreviewSession","constructor","sessionStorage","__privateAdd","this","__privateSet","init","request","secrets","storage","createCookieSessionStorage","cookie","name","httpOnly","sameSite","getSession","headers","get","key","__privateGet","destroy","destroySession","set","commit","commitSession","SanityPreview","data","isPreview","ResolvePreview","initialData","Fragment","useLiveQuery","WeakMap"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/client.ts","../src/preview/context.tsx","../src/preview/getPreview.ts","../src/preview/PreviewProvider.tsx","../src/preview/PreviewSession.ts","../src/preview/SanityPreview.tsx"],"sourcesContent":["import {\n type ClientConfig,\n type ClientPerspective,\n createClient,\n type FilteredResponseQueryOptions,\n type QueryParams,\n type RawQueryResponse,\n type SanityClient,\n type UnfilteredResponseQueryOptions,\n} from '@sanity/preview-kit/client'\nimport {CacheLong, createWithCache} from '@shopify/hydrogen'\n\nimport type {CachingStrategy, EnvironmentOptions, SessionLike} from './types'\n\ntype CreateSanityClientOptions = EnvironmentOptions & {\n config: ClientConfig & Required<Pick<ClientConfig, 'projectId' | 'dataset'>>\n preview?: {\n session: SessionLike\n token: string\n perspective?: ClientPerspective\n }\n}\n\ntype useSanityQuery = {\n query: string\n params?: QueryParams\n cache?: CachingStrategy\n queryOptions?: FilteredResponseQueryOptions\n}\n\ntype useRawSanityQuery = {\n query: string\n params?: QueryParams\n cache?: CachingStrategy\n queryOptions: UnfilteredResponseQueryOptions\n}\n\nexport type Sanity = {\n client: SanityClient\n preview?:\n | {session: SessionLike; projectId: string; dataset: string; token: string}\n | {session: SessionLike}\n query<T>(options: useSanityQuery): Promise<T>\n query<T>(options: useRawSanityQuery): Promise<RawQueryResponse<T>>\n}\n\n/**\n * Create Sanity provider with API client.\n */\nexport function createSanityClient(options: CreateSanityClientOptions): Sanity {\n const {cache, waitUntil, preview, config} = options\n\n const sanity: Sanity = {\n client: createClient(config),\n async query<T = any>({\n query,\n params,\n cache: strategy = CacheLong(),\n queryOptions,\n }: useSanityQuery | useRawSanityQuery) {\n const queryHash = await hashQuery(query, params)\n const withCache = createWithCache<T | RawQueryResponse<T>>({\n cache,\n waitUntil,\n })\n\n return withCache(queryHash, strategy, () => {\n if (!queryOptions) {\n return sanity.client.fetch(query, params)\n }\n\n // NOTE: satisfy union type\n if (queryOptions.filterResponse === false) {\n return sanity.client.fetch(query, params, queryOptions)\n }\n\n return sanity.client.fetch(query, params, queryOptions)\n })\n },\n }\n\n if (preview) {\n sanity.preview = {session: preview.session}\n\n if (preview.session.has('projectId')) {\n sanity.preview = {\n ...sanity.preview,\n projectId: config.projectId,\n dataset: config.dataset,\n token: preview.token,\n }\n\n sanity.client = sanity.client.withConfig({\n useCdn: false,\n token: preview.token,\n perspective: preview.perspective || 'previewDrafts',\n ignoreBrowserTokenWarning: true,\n })\n\n sanity.query = ({query, params, queryOptions}) => {\n if (!queryOptions) {\n return sanity.client.fetch(query, params)\n }\n\n // NOTE: satisfy union type\n if (queryOptions.filterResponse === false) {\n return sanity.client.fetch(query, params, queryOptions)\n }\n\n return sanity.client.fetch(query, params, queryOptions)\n }\n }\n }\n\n return sanity\n}\n\nexport function isPreviewModeEnabled(\n preview?: Sanity['preview']\n): preview is {session: SessionLike; projectId: string; dataset: string; token: string} {\n // @ts-expect-error\n return Boolean(preview && preview.token && preview.token !== null)\n}\n\n/**\n * Create an SHA-256 hash as a hex string\n * @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string\n */\nexport async function sha256(message: string): Promise<string> {\n // encode as UTF-8\n const messageBuffer = await new TextEncoder().encode(message)\n // hash the message\n const hashBuffer = await crypto.subtle.digest('SHA-256', messageBuffer)\n // convert bytes to hex string\n return Array.from(new Uint8Array(hashBuffer))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\n/**\n * Hash query and its parameters for use as cache key\n * NOTE: Oxygen deployment will break if the cache key is long or contains `\\n`\n */\nfunction hashQuery(\n query: useSanityQuery['query'],\n params: useSanityQuery['params']\n): Promise<string> {\n let hash = query\n\n if (params !== null) {\n hash += JSON.stringify(params)\n }\n\n return sha256(hash)\n}\n","import {createContext, useContext} from 'react'\n\nexport const PreviewContext = createContext<{projectId: string} | undefined>(undefined)\n\n/** TODO: needs inline documentation */\nexport const usePreviewContext = () => useContext(PreviewContext)\n","import type {ClientConfig} from '@sanity/client'\n\nimport {isPreviewModeEnabled, Sanity} from '../client'\n\n/** TODO: inline documentation */\nexport function getPreview<T extends {sanity: Sanity}>(context: T): ClientConfig | undefined {\n return isPreviewModeEnabled(context.sanity.preview)\n ? {\n ...context.sanity.client.config(),\n }\n : undefined\n}\n","/* eslint-disable react/require-default-props */\nimport type {LiveQueryProviderProps} from '@sanity/preview-kit'\nimport {type ClientConfig, createClient} from '@sanity/preview-kit/client'\nimport {\n lazy,\n type ReactElement,\n type ReactNode,\n Suspense,\n useEffect,\n useState,\n useTransition,\n} from 'react'\n\nimport {PreviewContext} from './context'\n\nconst LiveQueryProvider = lazy(() =>\n import('@sanity/preview-kit').then((m) => ({default: m.LiveQueryProvider}))\n)\n\ntype SanityPreviewProps = Omit<LiveQueryProviderProps, 'client'> & {\n fallback?: ReactNode\n previewConfig?: ClientConfig\n}\n\n/**\n * TODO: inline documentation\n * @see https://www.sanity.io/docs/preview-content-on-site\n */\nexport function PreviewProvider(props: SanityPreviewProps): ReactElement {\n const {children, previewConfig, fallback = children, ...rest} = props\n\n const [, startTransition] = useTransition()\n const [hydrated, setHydrated] = useState(false)\n useEffect(() => startTransition(() => setHydrated(true)), [])\n\n if (!hydrated || !previewConfig || !previewConfig.projectId) {\n return <>{children}</>\n }\n\n const client = createClient(previewConfig)\n\n return (\n <PreviewContext.Provider value={{projectId: previewConfig.projectId}}>\n <Suspense fallback={fallback}>\n <LiveQueryProvider {...rest} client={client}>\n {children}\n </LiveQueryProvider>\n </Suspense>\n </PreviewContext.Provider>\n )\n}\n","import {createCookieSessionStorage, type Session, type SessionStorage} from '@shopify/remix-oxygen'\n\n/**\n * @deprecated Use `HydrogenSession` or another `SessionLike` implementation instead. This will be removed in a future release.\n */\nexport class PreviewSession {\n #sessionStorage: SessionStorage\n #session: Session\n\n constructor(sessionStorage: SessionStorage, session: Session) {\n this.#sessionStorage = sessionStorage\n this.#session = session\n }\n\n static async init(request: Request, secrets: string[]): Promise<PreviewSession> {\n const storage = createCookieSessionStorage({\n cookie: {\n name: '__preview',\n httpOnly: true,\n sameSite: true,\n secrets,\n },\n })\n\n const session = await storage.getSession(request.headers.get('Cookie'))\n\n return new this(storage, session)\n }\n\n has(key: string): boolean {\n return this.#session.has(key)\n }\n\n // get(key: string) {\n // return this.session.get(key);\n // }\n\n destroy(): Promise<string> {\n return this.#sessionStorage.destroySession(this.#session)\n }\n\n // unset(key: string) {\n // this.session.unset(key);\n // }\n\n // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\n set(key: string, value: any): void {\n this.#session.set(key, value)\n }\n\n commit(): Promise<string> {\n return this.#sessionStorage.commitSession(this.#session)\n }\n}\n","/* eslint-disable react/require-default-props */\nimport type {QueryParams} from '@sanity/client'\nimport {useLiveQuery} from '@sanity/preview-kit'\nimport {type ReactElement, type ReactNode} from 'react'\n\nimport {usePreviewContext} from './context'\n\ntype PreviewProps<T> = {\n data: T\n children: ReactNode | ((data?: T | null) => ReactNode)\n query?: string | null\n params?: QueryParams\n}\n\n/**\n * Component to use for rendering in preview mode\n *\n * When provided a Sanity query and render prop,\n * changes will be streamed in the client\n */\nexport function SanityPreview<T = unknown>(props: PreviewProps<T>): ReactElement {\n const {data, children, query, params} = props\n const isPreview = Boolean(usePreviewContext())\n\n if (typeof children !== 'function') {\n return <>{children}</>\n }\n\n if (isPreview && query) {\n return (\n <ResolvePreview<typeof data> query={query} params={params} initialData={data}>\n {children}\n </ResolvePreview>\n )\n }\n\n return <>{children(data)}</>\n}\n\ntype ResolvePreviewProps<T> = {\n initialData?: T | null\n query: string\n params?: QueryParams\n children: (data?: T | null) => ReactNode\n}\n\n/**\n * Subscribe to live preview and delegate rendering to consumer\n */\nfunction ResolvePreview<T = unknown>(props: ResolvePreviewProps<T>) {\n const {initialData, query, params, children} = props\n const [data] = useLiveQuery(initialData, query, params)\n\n return <>{children(data)}</>\n}\n"],"names":["createSanityClient","options","cache","waitUntil","preview","config","sanity","client","createClient","query","_ref","params","strategy","CacheLong","queryOptions","queryHash","hash","JSON","stringify","sha256","hashQuery","createWithCache","withCache","filterResponse","fetch","session","has","projectId","dataset","token","withConfig","useCdn","perspective","ignoreBrowserTokenWarning","_ref2","isPreviewModeEnabled","Boolean","async","message","messageBuffer","TextEncoder","encode","hashBuffer","crypto","subtle","digest","Array","from","Uint8Array","map","b","toString","padStart","join","PreviewContext","createContext","usePreviewContext","useContext","getPreview","context","LiveQueryProvider","lazy","import","then","m","default","PreviewProvider","props","children","previewConfig","fallback","rest","startTransition","useTransition","hydrated","setHydrated","useState","useEffect","jsx","Provider","value","Suspense","_sessionStorage","_session","PreviewSession","constructor","sessionStorage","__privateAdd","this","__privateSet","init","request","secrets","storage","createCookieSessionStorage","cookie","name","httpOnly","sameSite","getSession","headers","get","key","__privateGet","destroy","destroySession","set","commit","commitSession","SanityPreview","data","isPreview","ResolvePreview","initialData","Fragment","useLiveQuery","WeakMap"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hydrogen-sanity",
3
- "version": "3.2.0",
3
+ "version": "3.3.1",
4
4
  "description": "Sanity.io toolkit for Hydrogen",
5
5
  "keywords": [
6
6
  "sanity",
@@ -26,8 +26,8 @@
26
26
  ".": {
27
27
  "types": "./dist/index.d.ts",
28
28
  "source": "./src/index.ts",
29
- "require": "./dist/index.js",
30
29
  "import": "./dist/index.mjs",
30
+ "require": "./dist/index.js",
31
31
  "default": "./dist/index.mjs"
32
32
  },
33
33
  "./package.json": "./package.json"
@@ -51,39 +51,39 @@
51
51
  "prepare": "husky install"
52
52
  },
53
53
  "dependencies": {
54
- "@sanity/client": "^6.1.7",
55
- "@sanity/preview-kit": "^2.3.3"
54
+ "@sanity/client": "^6.8.0",
55
+ "@sanity/preview-kit": "^3.2.7"
56
56
  },
57
57
  "devDependencies": {
58
- "@commitlint/cli": "^18.2.0",
59
- "@commitlint/config-conventional": "^18.1.0",
60
- "@sanity/pkg-utils": "^3.2.2",
61
- "@sanity/plugin-kit": "^3.1.7",
62
- "@sanity/semantic-release-preset": "^4.1.1",
63
- "@shopify/hydrogen": "~2023.10.0",
64
- "@shopify/remix-oxygen": "^2.0.0",
65
- "@types/react": "^18.2.14",
66
- "@typescript-eslint/eslint-plugin": "^5.61.0",
67
- "@typescript-eslint/parser": "^5.61.0",
68
- "eslint": "^8.44.0",
69
- "eslint-config-prettier": "^8.8.0",
58
+ "@commitlint/cli": "^18.4.1",
59
+ "@commitlint/config-conventional": "^18.4.0",
60
+ "@sanity/pkg-utils": "^3.2.3",
61
+ "@sanity/plugin-kit": "^3.1.10",
62
+ "@sanity/semantic-release-preset": "^4.1.6",
63
+ "@shopify/hydrogen": "~2024.1.0",
64
+ "@shopify/remix-oxygen": "^2.0.1",
65
+ "@types/react": "^18.2.37",
66
+ "@typescript-eslint/eslint-plugin": "^5.62.0",
67
+ "@typescript-eslint/parser": "^5.62.0",
68
+ "eslint": "^8.53.0",
69
+ "eslint-config-prettier": "^8.10.0",
70
70
  "eslint-config-sanity": "^6.0.0",
71
71
  "eslint-plugin-prettier": "^4.2.1",
72
- "eslint-plugin-react": "^7.32.2",
72
+ "eslint-plugin-react": "^7.33.2",
73
73
  "eslint-plugin-react-hooks": "^4.6.0",
74
74
  "eslint-plugin-simple-import-sort": "^10.0.0",
75
75
  "husky": "^8.0.3",
76
- "lint-staged": "^13.2.3",
76
+ "lint-staged": "^13.3.0",
77
77
  "npm-run-all": "^4.1.5",
78
78
  "prettier": "^2.8.8",
79
- "prettier-plugin-packagejson": "^2.4.4",
79
+ "prettier-plugin-packagejson": "^2.4.6",
80
80
  "react": "^18.2.0",
81
81
  "react-dom": "^18.2.0",
82
- "rimraf": "^5.0.1",
83
- "typescript": "^5.1.6"
82
+ "rimraf": "^5.0.5",
83
+ "typescript": "^5.2.2"
84
84
  },
85
85
  "peerDependencies": {
86
- "@shopify/hydrogen": "~2023.7.0 || ~2023.10.0",
86
+ "@shopify/hydrogen": "~2023.7.0 || ~2023.10.0 || ~2024.1.0",
87
87
  "@shopify/remix-oxygen": "^1.0.0 || ^2.0.0",
88
88
  "react": "^18.0.0",
89
89
  "react-dom": "^18.0.0"
package/src/client.ts CHANGED
@@ -10,13 +10,12 @@ import {
10
10
  } from '@sanity/preview-kit/client'
11
11
  import {CacheLong, createWithCache} from '@shopify/hydrogen'
12
12
 
13
- import type {PreviewSession} from './preview'
14
- import type {CachingStrategy, EnvironmentOptions} from './types'
13
+ import type {CachingStrategy, EnvironmentOptions, SessionLike} from './types'
15
14
 
16
15
  type CreateSanityClientOptions = EnvironmentOptions & {
17
16
  config: ClientConfig & Required<Pick<ClientConfig, 'projectId' | 'dataset'>>
18
17
  preview?: {
19
- session: PreviewSession
18
+ session: SessionLike
20
19
  token: string
21
20
  perspective?: ClientPerspective
22
21
  }
@@ -39,8 +38,8 @@ type useRawSanityQuery = {
39
38
  export type Sanity = {
40
39
  client: SanityClient
41
40
  preview?:
42
- | {session: PreviewSession; projectId: string; dataset: string; token: string}
43
- | {session: PreviewSession}
41
+ | {session: SessionLike; projectId: string; dataset: string; token: string}
42
+ | {session: SessionLike}
44
43
  query<T>(options: useSanityQuery): Promise<T>
45
44
  query<T>(options: useRawSanityQuery): Promise<RawQueryResponse<T>>
46
45
  }
@@ -118,7 +117,7 @@ export function createSanityClient(options: CreateSanityClientOptions): Sanity {
118
117
 
119
118
  export function isPreviewModeEnabled(
120
119
  preview?: Sanity['preview']
121
- ): preview is {session: PreviewSession; projectId: string; dataset: string; token: string} {
120
+ ): preview is {session: SessionLike; projectId: string; dataset: string; token: string} {
122
121
  // @ts-expect-error
123
122
  return Boolean(preview && preview.token && preview.token !== null)
124
123
  }
@@ -1,7 +1,7 @@
1
1
  import {createCookieSessionStorage, type Session, type SessionStorage} from '@shopify/remix-oxygen'
2
2
 
3
3
  /**
4
- * TODO: needs inline documentation
4
+ * @deprecated Use `HydrogenSession` or another `SessionLike` implementation instead. This will be removed in a future release.
5
5
  */
6
6
  export class PreviewSession {
7
7
  #sessionStorage: SessionStorage
package/src/types.ts CHANGED
@@ -19,3 +19,10 @@ export type EnvironmentOptions = {
19
19
 
20
20
  /** @see https://shopify.dev/docs/custom-storefronts/hydrogen/data-fetching/cache#caching-strategies */
21
21
  export type CachingStrategy = ReturnType<typeof CacheShort>
22
+
23
+ export interface SessionLike {
24
+ has(key: string): boolean
25
+ destroy(): Promise<string>
26
+ set(key: string, value: any): void
27
+ commit(): Promise<string>
28
+ }