hydrogen-sanity 4.1.1 → 4.2.0

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/README.md CHANGED
@@ -14,6 +14,7 @@
14
14
  - [Setup CORS for front-end domains](#setup-cors-for-front-end-domains)
15
15
  - [Modify storefront's Content Security Policy (CSP)](#modify-storefronts-content-security-policy-csp)
16
16
  - [Setup Presentation tool](#setup-presentation-tool)
17
+ - [Troubleshooting](#troubleshooting)
17
18
  - [Using `@sanity/client` instead of `hydrogen-sanity`](#using-sanityclient-instead-of-hydrogen-sanity)
18
19
  - [Migration Guides](#migration-guides)
19
20
  - [License](#license)
@@ -51,11 +52,14 @@ pnpm install hydrogen-sanity
51
52
 
52
53
  Update the server file to include the Sanity Loader, and optionally, configure the preview mode if you plan to setup Visual Editing
53
54
 
55
+ > [!NOTE]
56
+ > The examples below are up-to-date as of `npm create @shopify/hydrogen@2024.7.10`
57
+
54
58
  ```ts
55
59
  // ./lib/context.ts
56
60
 
57
61
  // ...all other imports
58
- import {createSanityLoader} from 'hydrogen-sanity';
62
+ import {createSanityContext} from 'hydrogen-sanity';
59
63
 
60
64
  export async function createAppLoadContext(
61
65
  request: Request,
@@ -63,16 +67,21 @@ export async function createAppLoadContext(
63
67
  executionContext: ExecutionContext,
64
68
  ) {
65
69
  // ... Leave all other functions like the Hydrogen context as-is
66
-
67
- // (Prerequisite) If not already initialized, create a `withCache` handler...
68
- const withCache = createWithCache({cache, waitUntil, request})
70
+ const waitUntil = executionContext.waitUntil.bind(executionContext);
71
+ const [cache, session] = await Promise.all([
72
+ caches.open('hydrogen'),
73
+ AppSession.init(request, [env.SESSION_SECRET]),
74
+ ]);
69
75
 
70
76
  // 1. Configure the Sanity Loader and preview mode
71
- const sanity = createSanityLoader({
72
- // Required, to cache responses
73
- withCache,
77
+ const sanity = createSanityContext({
78
+ request,
79
+
80
+ // To use the Hydrogen cache for queries
81
+ cache,
82
+ waitUntil,
74
83
 
75
- // Required:
84
+ // Sanity client configuration
76
85
  client: {
77
86
  projectId: env.SANITY_PROJECT_ID,
78
87
  dataset: env.SANITY_DATASET || 'production',
@@ -156,10 +165,6 @@ declare global {
156
165
  }
157
166
  ```
158
167
 
159
- > [!WARNING]
160
- >
161
- > `hydrogen-sanity` will automatically add `sanity` to the `AppLoadContext` interface
162
-
163
168
  ## Interacting with Sanity data
164
169
 
165
170
  ### Preferred: Cached queries using `loadQuery`
@@ -259,7 +264,7 @@ export async function loader({context}: LoaderArgs) {
259
264
 
260
265
  export function Layout({children}: {children?: React.ReactNode}) {
261
266
  const nonce = useNonce()
262
- const {isPreviewEnabled, ...data} = useRouteLoaderData<RootLoader>('root')
267
+ const data = useRouteLoaderData<RootLoader>('root')
263
268
 
264
269
  return (
265
270
  <html lang="en">
@@ -273,7 +278,7 @@ export function Layout({children}: {children?: React.ReactNode}) {
273
278
  {/* ...rest of the root layout */}
274
279
 
275
280
  {/* Conditionally render `VisualEditing` component only when in preview mode */}
276
- {isPreviewEnabled ? <VisualEditing /> : null}
281
+ {data?.isPreviewEnabled ? <VisualEditing /> : null}
277
282
 
278
283
  <ScrollRestoration nonce={nonce} />
279
284
  <Scripts nonce={nonce} />
@@ -300,7 +305,7 @@ For users to enter preview mode, they will need to visit a route that performs s
300
305
  Add this route to your project like below, or view the source to copy and modify it in your project.
301
306
 
302
307
  ```tsx
303
- // ./app/routes/resource.preview.ts
308
+ // ./app/routes/api.preview.ts
304
309
 
305
310
  export {loader} from 'hydrogen-sanity/preview/route'
306
311
 
@@ -333,11 +338,11 @@ export default async function handleRequest(
333
338
  responseStatusCode: number,
334
339
  responseHeaders: Headers,
335
340
  remixContext: EntryContext,
336
- loadContext: AppLoadContext,
341
+ context: AppLoadContext,
337
342
  ) {
338
- const projectId = loadContext.env.SANITY_PROJECT_ID
339
- const studioHostname = loadContext.env.SANITY_STUDIO_HOSTNAME || 'http://localhost:3333'
340
- const isPreviewEnabled = loadContext.sanity.preview?.enabled
343
+ const projectId = context.env.SANITY_PROJECT_ID
344
+ const studioHostname = context.env.SANITY_STUDIO_HOSTNAME || 'http://localhost:3333'
345
+ const isPreviewEnabled = context.sanity.preview?.enabled
341
346
 
342
347
  const {nonce, header, NonceProvider} = createContentSecurityPolicy({
343
348
  // If your storefront and Studio are on separate domains...
@@ -383,7 +388,7 @@ export default defineConfig({
383
388
  // origin: process.env.SANITY_STUDIO_STOREFRONT_ORIGIN
384
389
  previewMode: {
385
390
  // This path is relative to the origin above and should match the route in your storefront that you've setup above
386
- enable: '/resource/preview',
391
+ enable: '/api/preview',
387
392
  },
388
393
  },
389
394
  }),
@@ -400,6 +405,20 @@ You should now be able to view your Hydrogen app in the Presentation tool, click
400
405
  >
401
406
  > Since Presentation displays your site in an iframe, the session cookie by default won't be sent through. You can learn more about session cookie configuation in [MDN's documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value).
402
407
 
408
+ ### Troubleshooting
409
+
410
+ Are you getting the following error when trying to load your storefront in the Presentation tool?
411
+
412
+ > Unable to connect to visual editing. Make sure you've setup '@sanity/visual-editing' correctly
413
+
414
+ Presentation will throw this error if it can't establish a connection to your storefront. Here are a few things to double-check in your setup to try and troubleshoot:
415
+
416
+ 1. Confirm that you've provided `preview` configuration to the Sanity context.
417
+ 2. Confirm that you've added the `VisualEditing` component to your root layout.
418
+ 3. If you've followed the instructions above, the `VisualEditing` component will be conditionally rendered if the app has been successfully put into preview mode.
419
+ 4. If you're using a session cookie, check your browser devtools and confirm that the cookie has been set as expected.
420
+ 5. Since Presentation loads your storefront in an `iframe`, double check your cookie and CSP configuration.
421
+
403
422
  ## Using `@sanity/client` instead of `hydrogen-sanity`
404
423
 
405
424
  For whatever reason, if you choose not to use `hydrogen-sanity` you could still configure `@sanity/react-loader` or `@sanity/client` to get Sanity content into your Hydrogen storefront.
@@ -424,7 +443,7 @@ export async function createAppLoadContext(
424
443
  const sanity = createClient({
425
444
  projectId: env.SANITY_PROJECT_ID,
426
445
  dataset: env.SANITY_DATASET,
427
- apiVersion: env.SANITY_API_VERSION ?? '2023-03-30',
446
+ apiVersion: env.SANITY_API_VERSION ?? 'v2024-08-08',
428
447
  useCdn: process.env.NODE_ENV === 'production',
429
448
  })
430
449
 
@@ -0,0 +1 @@
1
+ "use strict";exports.a=function(t){return!!t&&"object"==typeof t&&"get"in t&&"function"==typeof t.get&&"set"in t&&"function"==typeof t.set&&"unset"in t&&"function"==typeof t.unset&&"commit"in t&&"function"==typeof t.commit},exports.h=function(t,n){let e=t;return n&&(e+=JSON.stringify(n)),async function(t){const n=await(new TextEncoder).encode(t),e=await crypto.subtle.digest("SHA-256",n);return Array.from(new Uint8Array(e)).map((t=>t.toString(16).padStart(2,"0"))).join("")}(e)};//# sourceMappingURL=utils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import type {HydrogenSession} from '@shopify/hydrogen'\n\nimport type {QueryParams, QueryWithoutParams} from './client'\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 */\nexport function hashQuery(\n query: string,\n params: QueryParams | QueryWithoutParams,\n): Promise<string> {\n let hash = query\n\n if (params) {\n hash += JSON.stringify(params)\n }\n\n return sha256(hash)\n}\n\nexport function assertSession(session: unknown): session is HydrogenSession {\n return (\n !!session &&\n typeof session === 'object' &&\n 'get' in session &&\n typeof session.get === 'function' &&\n 'set' in session &&\n typeof session.set === 'function' &&\n 'unset' in session &&\n typeof session.unset === 'function' &&\n 'commit' in session &&\n typeof session.commit === 'function'\n )\n}\n"],"names":["exports","a","session","get","set","unset","commit","h","query","params","hash","JSON","stringify","async","message","messageBuffer","TextEncoder","encode","hashBuffer","crypto","subtle","digest","Array","from","Uint8Array","map","b","toString","padStart","join","sha256"],"mappings":"aAiDAA,QAAAC,EAbO,SAAuBC,GAC5B,QACIA,GACiB,iBAAZA,GACP,QAASA,GACc,mBAAhBA,EAAQC,KACf,QAASD,GACc,mBAAhBA,EAAQE,KACf,UAAWF,GACc,mBAAlBA,EAAQG,OACf,WAAYH,GACc,mBAAnBA,EAAQI,MAEnB,EAAAN,QAAAO,EA1BgB,SACdC,EACAC,GAEA,IAAIC,EAAOF,EAEX,OAAIC,IACFC,GAAQC,KAAKC,UAAUH,IAtB3BI,eAA6BC,GAE3B,MAAMC,QAAsB,IAAIC,aAAcC,OAAOH,GAE/CI,QAAmBC,OAAOC,OAAOC,OAAO,UAAWN,GAElD,OAAAO,MAAMC,KAAK,IAAIC,WAAWN,IAC9BO,KAAKC,GAAMA,EAAEC,SAAS,IAAIC,SAAS,EAAG,OACtCC,KAAK,GACV,CAgBSC,CAAOpB,EAChB"}
@@ -0,0 +1 @@
1
+ function t(t,n){let e=t;return n&&(e+=JSON.stringify(n)),async function(t){const n=await(new TextEncoder).encode(t),e=await crypto.subtle.digest("SHA-256",n);return Array.from(new Uint8Array(e)).map((t=>t.toString(16).padStart(2,"0"))).join("")}(e)}function n(t){return!!t&&"object"==typeof t&&"get"in t&&"function"==typeof t.get&&"set"in t&&"function"==typeof t.set&&"unset"in t&&"function"==typeof t.unset&&"commit"in t&&"function"==typeof t.commit}export{n as a,t as h};//# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["import type {HydrogenSession} from '@shopify/hydrogen'\n\nimport type {QueryParams, QueryWithoutParams} from './client'\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 */\nexport function hashQuery(\n query: string,\n params: QueryParams | QueryWithoutParams,\n): Promise<string> {\n let hash = query\n\n if (params) {\n hash += JSON.stringify(params)\n }\n\n return sha256(hash)\n}\n\nexport function assertSession(session: unknown): session is HydrogenSession {\n return (\n !!session &&\n typeof session === 'object' &&\n 'get' in session &&\n typeof session.get === 'function' &&\n 'set' in session &&\n typeof session.set === 'function' &&\n 'unset' in session &&\n typeof session.unset === 'function' &&\n 'commit' in session &&\n typeof session.commit === 'function'\n )\n}\n"],"names":["hashQuery","query","params","hash","JSON","stringify","async","message","messageBuffer","TextEncoder","encode","hashBuffer","crypto","subtle","digest","Array","from","Uint8Array","map","b","toString","padStart","join","sha256","assertSession","session","get","set","unset","commit"],"mappings":"AAuBgB,SAAAA,EACdC,EACAC,GAEA,IAAIC,EAAOF,EAEX,OAAIC,IACFC,GAAQC,KAAKC,UAAUH,IAtB3BI,eAA6BC,GAE3B,MAAMC,QAAsB,IAAIC,aAAcC,OAAOH,GAE/CI,QAAmBC,OAAOC,OAAOC,OAAO,UAAWN,GAElD,OAAAO,MAAMC,KAAK,IAAIC,WAAWN,IAC9BO,KAAKC,GAAMA,EAAEC,SAAS,IAAIC,SAAS,EAAG,OACtCC,KAAK,GACV,CAgBSC,CAAOpB,EAChB,CAEO,SAASqB,EAAcC,GAC5B,QACIA,GACiB,iBAAZA,GACP,QAASA,GACc,mBAAhBA,EAAQC,KACf,QAASD,GACc,mBAAhBA,EAAQE,KACf,UAAWF,GACc,mBAAlBA,EAAQG,OACf,WAAYH,GACc,mBAAnBA,EAAQI,MAEnB"}
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@sanity/client"),t=require("@sanity/react-loader"),n=require("@shopify/hydrogen");function r(e,t){let n=e;return t&&(n+=JSON.stringify(t)),async function(e){const t=await(new TextEncoder).encode(e),n=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(n)).map((e=>e.toString(16).padStart(2,"0"))).join("")}(n)}const i=n.CacheLong(),a=t.createQueryStore({client:!1,ssr:!0});Object.defineProperty(exports,"SanityClient",{enumerable:!0,get:function(){return e.SanityClient}}),Object.defineProperty(exports,"createClient",{enumerable:!0,get:function(){return e.createClient}}),exports.createSanityLoader=function(t){const{withCache:o,preview:c,strategy:s}=t;let l=t.client instanceof e.SanityClient?t.client:e.createClient(t.client);if("1"===l.config().apiVersion&&(l=l.withConfig({apiVersion:"v2022-03-07"})),c&&c.enabled){if(!c.token)throw new Error("Enabling preview mode requires a token.");const e=l.withConfig({useCdn:!1,token:c.token,perspective:"previewDrafts",stega:{...l.config().stega,enabled:!0,studioUrl:c.studioUrl}});a.setServerClient(e)}else a.setServerClient(l);return{async loadQuery(e,t,l){const u=c&&c.enabled?n.CacheNone():l?.hydrogen?.cache||s||i,d=await r(e,t);return await o(d,u,(async({addDebugData:n})=>{if("development"===process.env.NODE_ENV){n({displayName:l?.hydrogen?.debug?.displayName||"query Sanity"})}return await a.loadQuery(e,t,l)}))},client:l,preview:c}};//# sourceMappingURL=index.cjs.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@sanity/client"),t=require("@sanity/react-loader"),n=require("@shopify/hydrogen"),i=require("./_chunks-cjs/utils.cjs");const r=n.CacheLong();const a=n.CacheLong();Object.defineProperty(exports,"SanityClient",{enumerable:!0,get:function(){return e.SanityClient}}),Object.defineProperty(exports,"createClient",{enumerable:!0,get:function(){return e.createClient}}),exports.createSanityContext=function(a){const{cache:o,waitUntil:s=()=>Promise.resolve(),request:c,preview:l,defaultStrategy:u}=a,d=o?n.createWithCache({cache:o,waitUntil:s,request:c}):null;let p=a.client instanceof e.SanityClient?a.client:e.createClient(a.client);if("1"===p.config().apiVersion&&(console.warn("No API version specified, defaulting to `v2022-03-07` which supports perspectives.\nYou can find the latest version in the Sanity changelog: https://www.sanity.io/changelog"),p=p.withConfig({apiVersion:"v2022-03-07"})),l&&l.enabled){if(!l.token)throw new Error("Enabling preview mode requires a token.");const e=p.withConfig({useCdn:!1,token:l.token,perspective:"previewDrafts",stega:{...p.config().stega,enabled:!0,studioUrl:l.studioUrl}});t.setServerClient(e)}else t.setServerClient(p);return{async loadQuery(e,a,o){const s=l&&l.enabled?n.CacheNone():o?.hydrogen?.cache||u||r,c=await i.h(e,a);return await(d?d(c,s,(async({addDebugData:n})=>{if("development"===process.env.NODE_ENV){n({displayName:o?.hydrogen?.debug?.displayName||"query Sanity"})}return await t.loadQuery(e,a,o)})):t.loadQuery(e,a,o))},client:p,preview:l}},exports.createSanityLoader=function(r){const{withCache:o,preview:s,strategy:c}=r;let l=r.client instanceof e.SanityClient?r.client:e.createClient(r.client);if("1"===l.config().apiVersion&&(console.warn("No API version specified, defaulting to `v2022-03-07` which supports perspectives.\nYou can find the latest version in the Sanity changelog: https://www.sanity.io/changelog"),l=l.withConfig({apiVersion:"v2022-03-07"})),s&&s.enabled){if(!s.token)throw new Error("Enabling preview mode requires a token.");const e=l.withConfig({useCdn:!1,token:s.token,perspective:"previewDrafts",stega:{...l.config().stega,enabled:!0,studioUrl:s.studioUrl}});t.setServerClient(e)}else t.setServerClient(l);return{async loadQuery(e,r,l){const u=s&&s.enabled?n.CacheNone():l?.hydrogen?.cache||c||a,d=await i.h(e,r);return await o(d,u,(async({addDebugData:n})=>{if("development"===process.env.NODE_ENV){n({displayName:l?.hydrogen?.debug?.displayName||"query Sanity"})}return await t.loadQuery(e,r,l)}))},client:l,preview:s}};//# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/utils.ts","../src/loader.ts"],"sourcesContent":["import type {QueryParams, QueryWithoutParams} from './client'\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 */\nexport function hashQuery(\n query: string,\n params: QueryParams | QueryWithoutParams,\n): Promise<string> {\n let hash = query\n\n if (params) {\n hash += JSON.stringify(params)\n }\n\n return sha256(hash)\n}\n","/* eslint-disable no-return-await */\nimport {createQueryStore, type QueryResponseInitial} from '@sanity/react-loader'\nimport {\n CacheLong,\n CacheNone,\n type CachingStrategy,\n type HydrogenSession,\n type WithCache,\n} from '@shopify/hydrogen'\n\nimport {\n type ClientConfig,\n createClient,\n type QueryParams,\n type QueryWithoutParams,\n type ResponseQueryOptions,\n SanityClient,\n} from './client'\nimport {hashQuery} from './utils'\n\nconst DEFAULT_CACHE_STRATEGY = CacheLong()\n\nexport type CreateSanityLoaderOptions = {\n // TODO: make this optional in dev? Or follow Hydrogen's pattern\n /**\n * Cache control utility from `@shopify/hydrogen`.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching/third-party\n */\n withCache: WithCache\n\n /**\n * Sanity client or configuration to use.\n */\n client: SanityClient | ClientConfig\n\n /**\n * The default caching strategy to use for `loadQuery` subrequests.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies\n *\n * Defaults to `CacheLong`\n */\n strategy?: CachingStrategy | null\n\n /**\n * Configuration for enabling preview mode.\n */\n preview?: {enabled: boolean; token: string; studioUrl: string}\n}\n\ninterface RequestInit {\n hydrogen?: {\n /**\n * The caching strategy to use for the subrequest.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies\n */\n cache?: CachingStrategy\n\n /**\n * Optional debugging information to be displayed in the subrequest profiler.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/debugging/subrequest-profiler#how-to-provide-more-debug-information-for-a-request\n */\n debug?: {\n displayName: string\n }\n }\n}\n\ntype HydrogenResponseQueryOptions = Omit<ResponseQueryOptions, 'next' | 'cache'> & {\n hydrogen?: 'hydrogen' extends keyof RequestInit ? RequestInit['hydrogen'] : never\n}\n\ntype LoadQueryOptions = Pick<\n HydrogenResponseQueryOptions,\n 'perspective' | 'hydrogen' | 'useCdn' | 'stega' | 'headers' | 'tag'\n>\n\nexport type SanityLoader = {\n /**\n * Query Sanity using the loader.\n * @see https://www.sanity.io/docs/loaders\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n loadQuery<T = any>(\n query: string,\n params?: QueryParams,\n options?: LoadQueryOptions,\n ): Promise<QueryResponseInitial<T>>\n\n client: SanityClient\n\n preview?: CreateSanityLoaderOptions['preview']\n}\n\ndeclare module '@shopify/remix-oxygen' {\n /**\n * Declare local additions to the Remix loader context.\n */\n export interface AppLoadContext {\n session: HydrogenSession\n sanity: SanityLoader\n }\n}\n\nconst queryStore = createQueryStore({client: false, ssr: true})\n\n// TODO: rename to match new Hydrogen creator, e.g. `createSanityContext`\n/**\n * @public\n */\nexport function createSanityLoader(options: CreateSanityLoaderOptions): SanityLoader {\n const {withCache, preview, strategy} = options\n let client =\n options.client instanceof SanityClient ? options.client : createClient(options.client)\n\n /**\n * TODO: should this default to the latest API version?\n * Or at least warn if a version that doesn't support perspectives is used?\n */\n if (client.config().apiVersion === '1') {\n client = client.withConfig({apiVersion: 'v2022-03-07'})\n }\n\n if (preview && preview.enabled) {\n if (!preview.token) {\n throw new Error('Enabling preview mode requires a token.')\n }\n\n const previewClient = client.withConfig({\n useCdn: false,\n token: preview.token,\n perspective: 'previewDrafts' as const,\n stega: {\n ...client.config().stega,\n enabled: true,\n studioUrl: preview.studioUrl,\n },\n })\n\n queryStore.setServerClient(previewClient)\n } else {\n queryStore.setServerClient(client)\n }\n\n const sanity = {\n async loadQuery<T>(\n query: string,\n params: QueryParams | QueryWithoutParams,\n loaderOptions?: LoadQueryOptions,\n ): Promise<QueryResponseInitial<T>> {\n // Don't store response if preview is enabled\n const cacheStrategy =\n preview && preview.enabled\n ? CacheNone()\n : loaderOptions?.hydrogen?.cache || strategy || DEFAULT_CACHE_STRATEGY\n\n const queryHash = await hashQuery(query, params)\n\n return await withCache(queryHash, cacheStrategy, async ({addDebugData}) => {\n // eslint-disable-next-line no-process-env\n if (process.env.NODE_ENV === 'development') {\n // Name displayed in the subrequest profiler\n const displayName = loaderOptions?.hydrogen?.debug?.displayName || 'query Sanity'\n\n addDebugData({\n displayName,\n })\n }\n\n return await queryStore.loadQuery<T>(query, params, loaderOptions)\n })\n },\n client,\n preview,\n }\n\n return sanity\n}\n"],"names":["hashQuery","query","params","hash","JSON","stringify","async","message","messageBuffer","TextEncoder","encode","hashBuffer","crypto","subtle","digest","Array","from","Uint8Array","map","b","toString","padStart","join","sha256","DEFAULT_CACHE_STRATEGY","CacheLong","queryStore","createQueryStore","client","ssr","Object","defineProperty","exports","enumerable","get","SanityClient","createClient","createSanityLoader","options","withCache","preview","strategy","config","apiVersion","withConfig","enabled","token","Error","previewClient","useCdn","perspective","stega","studioUrl","setServerClient","loadQuery","loaderOptions","cacheStrategy","CacheNone","hydrogen","cache","queryHash","addDebugData","process","env","NODE_ENV","displayName","debug"],"mappings":"qKAqBgB,SAAAA,EACdC,EACAC,GAEA,IAAIC,EAAOF,EAEX,OAAIC,IACFC,GAAQC,KAAKC,UAAUH,IAtB3BI,eAA6BC,GAE3B,MAAMC,QAAsB,IAAIC,aAAcC,OAAOH,GAE/CI,QAAmBC,OAAOC,OAAOC,OAAO,UAAWN,GAElD,OAAAO,MAAMC,KAAK,IAAIC,WAAWN,IAC9BO,KAAKC,GAAMA,EAAEC,SAAS,IAAIC,SAAS,EAAG,OACtCC,KAAK,GACV,CAgBSC,CAAOpB,EAChB,CCZA,MAAMqB,EAAyBC,EAAAA,YAmFzBC,EAAaC,EAAAA,iBAAiB,CAACC,QAAQ,EAAOC,KAAK,IAyEzDC,OAAAC,eAAAC,QAAA,eAAA,CAAAC,YAAA,EAAAC,IAAA,WAAA,OAAAN,EAAAO,YAAA,IAAAL,OAAAC,eAAAC,QAAA,eAAA,CAAAC,YAAA,EAAAC,IAAA,WAAA,OAAAN,EAAAQ,YAAA,IAAAJ,QAAAK,mBAnEO,SAA4BC,GACjC,MAAMC,UAACA,EAAAC,QAAWA,EAASC,SAAAA,GAAYH,EACnCV,IAAAA,EACFU,EAAQV,kBAAkBO,EAAAA,aAAeG,EAAQV,OAASQ,EAAAA,aAAaE,EAAQV,QAUjF,GAJmC,MAA/BA,EAAOc,SAASC,aAClBf,EAASA,EAAOgB,WAAW,CAACD,WAAY,iBAGtCH,GAAWA,EAAQK,QAAS,CAC9B,IAAKL,EAAQM,MACL,MAAA,IAAIC,MAAM,2CAGZ,MAAAC,EAAgBpB,EAAOgB,WAAW,CACtCK,QAAQ,EACRH,MAAON,EAAQM,MACfI,YAAa,gBACbC,MAAO,IACFvB,EAAOc,SAASS,MACnBN,SAAS,EACTO,UAAWZ,EAAQY,aAIvB1B,EAAW2B,gBAAgBL,EAC7B,MACEtB,EAAW2B,gBAAgBzB,GAGd,MAAA,CACb,eAAM0B,CACJrD,EACAC,EACAqD,GAGA,MAAMC,EACJhB,GAAWA,EAAQK,QACfY,EAAAA,YACAF,GAAeG,UAAUC,OAASlB,GAAYjB,EAE9CoC,QAAkB5D,EAAUC,EAAOC,GAEzC,aAAaqC,EAAUqB,EAAWJ,GAAelD,OAAQuD,mBAEnD,GAAyB,gBAAzBC,QAAQC,IAAIC,SAA4B,CAI7BH,EAAA,CACXI,YAHkBV,GAAeG,UAAUQ,OAAOD,aAAe,gBAKrE,CAEA,aAAavC,EAAW4B,UAAarD,EAAOC,EAAQqD,EAAa,GAErE,EAAA3B,OACAA,EACAY,UAIJ"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/context.ts","../src/loader.ts"],"sourcesContent":["import {loadQuery, type QueryResponseInitial, setServerClient} from '@sanity/react-loader'\nimport {CacheLong, CacheNone, type CachingStrategy, createWithCache} from '@shopify/hydrogen'\n\nimport {\n type ClientConfig,\n createClient,\n type QueryParams,\n type QueryWithoutParams,\n type ResponseQueryOptions,\n SanityClient,\n} from './client'\nimport {hashQuery} from './utils'\n\nconst DEFAULT_CACHE_STRATEGY = CacheLong()\n\ntype WaitUntil = (promise: Promise<unknown>) => void\n\nexport type CreateSanityContextOptions = {\n request: Request\n\n cache?: Cache | undefined\n waitUntil?: WaitUntil | undefined\n\n /**\n * Sanity client or configuration to use.\n */\n client: SanityClient | ClientConfig\n\n /**\n * The default caching strategy to use for `loadQuery` subrequests.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies\n *\n * Defaults to `CacheLong`\n */\n defaultStrategy?: CachingStrategy | null\n\n /**\n * Configuration for enabling preview mode.\n */\n preview?: {enabled: boolean; token: string; studioUrl: string}\n}\n\ninterface RequestInit {\n hydrogen?: {\n /**\n * The caching strategy to use for the subrequest.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies\n */\n cache?: CachingStrategy\n\n /**\n * Optional debugging information to be displayed in the subrequest profiler.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/debugging/subrequest-profiler#how-to-provide-more-debug-information-for-a-request\n */\n debug?: {\n displayName: string\n }\n }\n}\n\ntype HydrogenResponseQueryOptions = Omit<ResponseQueryOptions, 'next' | 'cache'> & {\n hydrogen?: 'hydrogen' extends keyof RequestInit ? RequestInit['hydrogen'] : never\n}\n\ntype LoadQueryOptions = Pick<\n HydrogenResponseQueryOptions,\n 'perspective' | 'hydrogen' | 'useCdn' | 'stega' | 'headers' | 'tag'\n>\n\nexport type SanityContext = {\n /**\n * Query Sanity using the loader.\n * @see https://www.sanity.io/docs/loaders\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n loadQuery<T = any>(\n query: string,\n params?: QueryParams,\n options?: LoadQueryOptions,\n ): Promise<QueryResponseInitial<T>>\n\n client: SanityClient\n\n preview?: CreateSanityContextOptions['preview']\n}\n\n/**\n * @public\n */\nexport function createSanityContext(options: CreateSanityContextOptions): SanityContext {\n const {cache, waitUntil = () => Promise.resolve(), request, preview, defaultStrategy} = options\n const withCache = cache ? createWithCache({cache, waitUntil, request}) : null\n let client =\n options.client instanceof SanityClient ? options.client : createClient(options.client)\n\n if (client.config().apiVersion === '1') {\n console.warn(\n 'No API version specified, defaulting to `v2022-03-07` which supports perspectives.\\nYou can find the latest version in the Sanity changelog: https://www.sanity.io/changelog',\n )\n client = client.withConfig({apiVersion: 'v2022-03-07'})\n }\n\n if (preview && preview.enabled) {\n if (!preview.token) {\n throw new Error('Enabling preview mode requires a token.')\n }\n\n const previewClient = client.withConfig({\n useCdn: false,\n token: preview.token,\n perspective: 'previewDrafts' as const,\n stega: {\n ...client.config().stega,\n enabled: true,\n studioUrl: preview.studioUrl,\n },\n })\n\n setServerClient(previewClient)\n } else {\n setServerClient(client)\n }\n\n const sanity = {\n async loadQuery<T>(\n query: string,\n params: QueryParams | QueryWithoutParams,\n loaderOptions?: LoadQueryOptions,\n ): Promise<QueryResponseInitial<T>> {\n // Don't store response if preview is enabled\n const cacheStrategy =\n preview && preview.enabled\n ? CacheNone()\n : loaderOptions?.hydrogen?.cache || defaultStrategy || DEFAULT_CACHE_STRATEGY\n\n const queryHash = await hashQuery(query, params)\n\n return await (withCache\n ? withCache(queryHash, cacheStrategy, async ({addDebugData}) => {\n if (process.env.NODE_ENV === 'development') {\n // Name displayed in the subrequest profiler\n const displayName = loaderOptions?.hydrogen?.debug?.displayName || 'query Sanity'\n\n addDebugData({\n displayName,\n })\n }\n\n return await loadQuery<T>(query, params, loaderOptions)\n })\n : loadQuery<T>(query, params, loaderOptions))\n },\n client,\n preview,\n }\n\n return sanity\n}\n","import {loadQuery, type QueryResponseInitial, setServerClient} from '@sanity/react-loader'\nimport {CacheLong, CacheNone, type CachingStrategy, type WithCache} from '@shopify/hydrogen'\n\nimport {\n type ClientConfig,\n createClient,\n type QueryParams,\n type QueryWithoutParams,\n type ResponseQueryOptions,\n SanityClient,\n} from './client'\nimport {hashQuery} from './utils'\n\nconst DEFAULT_CACHE_STRATEGY = CacheLong()\n\nexport type CreateSanityLoaderOptions = {\n /**\n * Cache control utility from `@shopify/hydrogen`.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching/third-party\n */\n withCache: WithCache\n\n /**\n * Sanity client or configuration to use.\n */\n client: SanityClient | ClientConfig\n\n /**\n * The default caching strategy to use for `loadQuery` subrequests.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies\n *\n * Defaults to `CacheLong`\n */\n strategy?: CachingStrategy | null\n\n /**\n * Configuration for enabling preview mode.\n */\n preview?: {enabled: boolean; token: string; studioUrl: string}\n}\n\ninterface RequestInit {\n hydrogen?: {\n /**\n * The caching strategy to use for the subrequest.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies\n */\n cache?: CachingStrategy\n\n /**\n * Optional debugging information to be displayed in the subrequest profiler.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/debugging/subrequest-profiler#how-to-provide-more-debug-information-for-a-request\n */\n debug?: {\n displayName: string\n }\n }\n}\n\ntype HydrogenResponseQueryOptions = Omit<ResponseQueryOptions, 'next' | 'cache'> & {\n hydrogen?: 'hydrogen' extends keyof RequestInit ? RequestInit['hydrogen'] : never\n}\n\ntype LoadQueryOptions = Pick<\n HydrogenResponseQueryOptions,\n 'perspective' | 'hydrogen' | 'useCdn' | 'stega' | 'headers' | 'tag'\n>\n\nexport type SanityLoader = {\n /**\n * Query Sanity using the loader.\n * @see https://www.sanity.io/docs/loaders\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n loadQuery<T = any>(\n query: string,\n params?: QueryParams,\n options?: LoadQueryOptions,\n ): Promise<QueryResponseInitial<T>>\n\n client: SanityClient\n\n preview?: CreateSanityLoaderOptions['preview']\n}\n\n/**\n * @deprecated Use `createSanityContext` instead\n */\nexport function createSanityLoader(options: CreateSanityLoaderOptions): SanityLoader {\n const {withCache, preview, strategy} = options\n let client =\n options.client instanceof SanityClient ? options.client : createClient(options.client)\n\n if (client.config().apiVersion === '1') {\n console.warn(\n 'No API version specified, defaulting to `v2022-03-07` which supports perspectives.\\nYou can find the latest version in the Sanity changelog: https://www.sanity.io/changelog',\n )\n client = client.withConfig({apiVersion: 'v2022-03-07'})\n }\n\n if (preview && preview.enabled) {\n if (!preview.token) {\n throw new Error('Enabling preview mode requires a token.')\n }\n\n const previewClient = client.withConfig({\n useCdn: false,\n token: preview.token,\n perspective: 'previewDrafts' as const,\n stega: {\n ...client.config().stega,\n enabled: true,\n studioUrl: preview.studioUrl,\n },\n })\n\n setServerClient(previewClient)\n } else {\n setServerClient(client)\n }\n\n const sanity = {\n async loadQuery<T>(\n query: string,\n params: QueryParams | QueryWithoutParams,\n loaderOptions?: LoadQueryOptions,\n ): Promise<QueryResponseInitial<T>> {\n // Don't store response if preview is enabled\n const cacheStrategy =\n preview && preview.enabled\n ? CacheNone()\n : loaderOptions?.hydrogen?.cache || strategy || DEFAULT_CACHE_STRATEGY\n\n const queryHash = await hashQuery(query, params)\n\n return await withCache(queryHash, cacheStrategy, async ({addDebugData}) => {\n // eslint-disable-next-line no-process-env\n if (process.env.NODE_ENV === 'development') {\n // Name displayed in the subrequest profiler\n const displayName = loaderOptions?.hydrogen?.debug?.displayName || 'query Sanity'\n\n addDebugData({\n displayName,\n })\n }\n\n return await loadQuery<T>(query, params, loaderOptions)\n })\n },\n client,\n preview,\n }\n\n return sanity\n}\n"],"names":["Object","defineProperty","exports","value","client","require","reactLoader","hydrogen","utils","DEFAULT_CACHE_STRATEGY","CacheLong","enumerable","get","SanityClient","createClient","createSanityContext","options","cache","waitUntil","Promise","resolve","request","preview","defaultStrategy","withCache","createWithCache","config","apiVersion","console","warn","withConfig","enabled","token","Error","previewClient","useCdn","perspective","stega","studioUrl","setServerClient","loadQuery","query","params","loaderOptions","cacheStrategy","CacheNone","queryHash","hashQuery","async","addDebugData","process","env","NODE_ENV","displayName","debug","createSanityLoader","strategy"],"mappings":"aAaAA,OAAAC,eAAAC,QAAA,aAAA,CAAAC,OAAA,IAAA,IAAAC,EAAAC,QAAA,kBAAAC,EAAAD,QAAA,wBAAAE,EAAAF,QAAA,qBAAAG,EAAAH,QAAA,2BAAA,MAAMI,EAAyBC,EAAUA,YCAzC,MAAMD,EAAyBC,EAAAA,YA6I/BV,OAAAC,eAAAC,QAAA,eAAA,CAAAS,YAAA,EAAAC,IAAA,WAAA,OAAAR,EAAAS,YAAA,IAAAb,OAAAC,eAAAC,QAAA,eAAA,CAAAS,YAAA,EAAAC,IAAA,WAAA,OAAAR,EAAAU,YAAA,IAAAZ,QAAAa,oBDjEO,SAA6BC,GAC5B,MAAAC,MAACA,YAAOC,EAAY,IAAMC,QAAQC,kBAAWC,UAASC,EAASC,gBAAAA,GAAmBP,EAClFQ,EAAYP,EAAQQ,kBAAgB,CAACR,QAAOC,YAAWG,YAAY,KACrEjB,IAAAA,EACFY,EAAQZ,kBAAkBS,EAAAA,aAAeG,EAAQZ,OAASU,EAAAA,aAAaE,EAAQZ,QASjF,GAPmC,MAA/BA,EAAOsB,SAASC,aAClBC,QAAQC,KACN,gLAEFzB,EAASA,EAAO0B,WAAW,CAACH,WAAY,iBAGtCL,GAAWA,EAAQS,QAAS,CAC9B,IAAKT,EAAQU,MACL,MAAA,IAAIC,MAAM,2CAGZ,MAAAC,EAAgB9B,EAAO0B,WAAW,CACtCK,QAAQ,EACRH,MAAOV,EAAQU,MACfI,YAAa,gBACbC,MAAO,IACFjC,EAAOsB,SAASW,MACnBN,SAAS,EACTO,UAAWhB,EAAQgB,aAIvBC,EAAAA,gBAAgBL,EAClB,MACEK,EAAAA,gBAAgBnC,GAGH,MAAA,CACb,eAAMoC,CACJC,EACAC,EACAC,GAGA,MAAMC,EACJtB,GAAWA,EAAQS,QACfc,EAAAA,YACAF,GAAepC,UAAUU,OAASM,GAAmBd,EAErDqC,QAAkBC,EAAAA,EAAUN,EAAOC,GAElC,aAAOlB,EACVA,EAAUsB,EAAWF,GAAeI,OAAQC,mBACtC,GAAyB,gBAAzBC,QAAQC,IAAIC,SAA4B,CAI7BH,EAAA,CACXI,YAHkBV,GAAepC,UAAU+C,OAAOD,aAAe,gBAKrE,CAEA,aAAab,EAAAA,UAAaC,EAAOC,EAAQC,EAAa,IAExDH,EAAAA,UAAaC,EAAOC,EAAQC,GAClC,EAAAvC,OACAA,EACAkB,UAIJ,ECHApB,QAAAqD,mBAlEO,SAA4BvC,GACjC,MAAMQ,UAACA,EAAAF,QAAWA,EAASkC,SAAAA,GAAYxC,EACnCZ,IAAAA,EACFY,EAAQZ,kBAAkBS,EAAAA,aAAeG,EAAQZ,OAASU,EAAAA,aAAaE,EAAQZ,QASjF,GAPmC,MAA/BA,EAAOsB,SAASC,aAClBC,QAAQC,KACN,gLAEFzB,EAASA,EAAO0B,WAAW,CAACH,WAAY,iBAGtCL,GAAWA,EAAQS,QAAS,CAC9B,IAAKT,EAAQU,MACL,MAAA,IAAIC,MAAM,2CAGZ,MAAAC,EAAgB9B,EAAO0B,WAAW,CACtCK,QAAQ,EACRH,MAAOV,EAAQU,MACfI,YAAa,gBACbC,MAAO,IACFjC,EAAOsB,SAASW,MACnBN,SAAS,EACTO,UAAWhB,EAAQgB,aAIvBC,EAAAA,gBAAgBL,EAClB,MACEK,EAAAA,gBAAgBnC,GAGH,MAAA,CACb,eAAMoC,CACJC,EACAC,EACAC,GAGA,MAAMC,EACJtB,GAAWA,EAAQS,QACfc,EAAAA,YACAF,GAAepC,UAAUU,OAASuC,GAAY/C,EAE9CqC,QAAkBC,EAAAA,EAAUN,EAAOC,GAEzC,aAAalB,EAAUsB,EAAWF,GAAeI,OAAQC,mBAEnD,GAAyB,gBAAzBC,QAAQC,IAAIC,SAA4B,CAI7BH,EAAA,CACXI,YAHkBV,GAAepC,UAAU+C,OAAOD,aAAe,gBAKrE,CAEA,aAAab,EAAAA,UAAaC,EAAOC,EAAQC,EAAa,GAE1D,EAAAvC,OACAA,EACAkB,UAIJ"}
package/dist/index.d.cts CHANGED
@@ -12,6 +12,36 @@ export {createClient}
12
12
  /**
13
13
  * @public
14
14
  */
15
+ export declare function createSanityContext(options: CreateSanityContextOptions): SanityContext
16
+
17
+ declare type CreateSanityContextOptions = {
18
+ request: Request
19
+ cache?: Cache | undefined
20
+ waitUntil?: WaitUntil | undefined
21
+ /**
22
+ * Sanity client or configuration to use.
23
+ */
24
+ client: SanityClient | ClientConfig
25
+ /**
26
+ * The default caching strategy to use for `loadQuery` subrequests.
27
+ * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies
28
+ *
29
+ * Defaults to `CacheLong`
30
+ */
31
+ defaultStrategy?: CachingStrategy | null
32
+ /**
33
+ * Configuration for enabling preview mode.
34
+ */
35
+ preview?: {
36
+ enabled: boolean
37
+ token: string
38
+ studioUrl: string
39
+ }
40
+ }
41
+
42
+ /**
43
+ * @deprecated Use `createSanityContext` instead
44
+ */
15
45
  export declare function createSanityLoader(options: CreateSanityLoaderOptions): SanityLoader
16
46
 
17
47
  declare type CreateSanityLoaderOptions = {
@@ -45,11 +75,20 @@ declare type HydrogenResponseQueryOptions = Omit<ResponseQueryOptions, 'next' |
45
75
  hydrogen?: 'hydrogen' extends keyof RequestInit_2 ? RequestInit_2['hydrogen'] : never
46
76
  }
47
77
 
78
+ declare type HydrogenResponseQueryOptions_2 = Omit<ResponseQueryOptions, 'next' | 'cache'> & {
79
+ hydrogen?: 'hydrogen' extends keyof RequestInit_3 ? RequestInit_3['hydrogen'] : never
80
+ }
81
+
48
82
  declare type LoadQueryOptions = Pick<
49
83
  HydrogenResponseQueryOptions,
50
84
  'perspective' | 'hydrogen' | 'useCdn' | 'stega' | 'headers' | 'tag'
51
85
  >
52
86
 
87
+ declare type LoadQueryOptions_2 = Pick<
88
+ HydrogenResponseQueryOptions_2,
89
+ 'perspective' | 'hydrogen' | 'useCdn' | 'stega' | 'headers' | 'tag'
90
+ >
91
+
53
92
  declare interface RequestInit_2 {
54
93
  hydrogen?: {
55
94
  /**
@@ -67,9 +106,26 @@ declare interface RequestInit_2 {
67
106
  }
68
107
  }
69
108
 
109
+ declare interface RequestInit_3 {
110
+ hydrogen?: {
111
+ /**
112
+ * The caching strategy to use for the subrequest.
113
+ * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies
114
+ */
115
+ cache?: CachingStrategy
116
+ /**
117
+ * Optional debugging information to be displayed in the subrequest profiler.
118
+ * @see https://shopify.dev/docs/custom-storefronts/hydrogen/debugging/subrequest-profiler#how-to-provide-more-debug-information-for-a-request
119
+ */
120
+ debug?: {
121
+ displayName: string
122
+ }
123
+ }
124
+ }
125
+
70
126
  export {SanityClient}
71
127
 
72
- export declare type SanityLoader = {
128
+ export declare type SanityContext = {
73
129
  /**
74
130
  * Query Sanity using the loader.
75
131
  * @see https://www.sanity.io/docs/loaders
@@ -80,19 +136,25 @@ export declare type SanityLoader = {
80
136
  options?: LoadQueryOptions,
81
137
  ): Promise<QueryResponseInitial<T>>
82
138
  client: SanityClient
139
+ preview?: CreateSanityContextOptions['preview']
140
+ }
141
+
142
+ export declare type SanityLoader = {
143
+ /**
144
+ * Query Sanity using the loader.
145
+ * @see https://www.sanity.io/docs/loaders
146
+ */
147
+ loadQuery<T = any>(
148
+ query: string,
149
+ params?: QueryParams,
150
+ options?: LoadQueryOptions_2,
151
+ ): Promise<QueryResponseInitial<T>>
152
+ client: SanityClient
83
153
  preview?: CreateSanityLoaderOptions['preview']
84
154
  }
85
155
 
156
+ declare type WaitUntil = (promise: Promise<unknown>) => void
157
+
86
158
  export * from '@sanity/client'
87
159
 
88
160
  export {}
89
-
90
- declare module '@shopify/remix-oxygen' {
91
- /**
92
- * Declare local additions to the Remix loader context.
93
- */
94
- interface AppLoadContext {
95
- session: HydrogenSession
96
- sanity: SanityLoader
97
- }
98
- }
package/dist/index.d.ts CHANGED
@@ -12,6 +12,36 @@ export {createClient}
12
12
  /**
13
13
  * @public
14
14
  */
15
+ export declare function createSanityContext(options: CreateSanityContextOptions): SanityContext
16
+
17
+ declare type CreateSanityContextOptions = {
18
+ request: Request
19
+ cache?: Cache | undefined
20
+ waitUntil?: WaitUntil | undefined
21
+ /**
22
+ * Sanity client or configuration to use.
23
+ */
24
+ client: SanityClient | ClientConfig
25
+ /**
26
+ * The default caching strategy to use for `loadQuery` subrequests.
27
+ * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies
28
+ *
29
+ * Defaults to `CacheLong`
30
+ */
31
+ defaultStrategy?: CachingStrategy | null
32
+ /**
33
+ * Configuration for enabling preview mode.
34
+ */
35
+ preview?: {
36
+ enabled: boolean
37
+ token: string
38
+ studioUrl: string
39
+ }
40
+ }
41
+
42
+ /**
43
+ * @deprecated Use `createSanityContext` instead
44
+ */
15
45
  export declare function createSanityLoader(options: CreateSanityLoaderOptions): SanityLoader
16
46
 
17
47
  declare type CreateSanityLoaderOptions = {
@@ -45,11 +75,20 @@ declare type HydrogenResponseQueryOptions = Omit<ResponseQueryOptions, 'next' |
45
75
  hydrogen?: 'hydrogen' extends keyof RequestInit_2 ? RequestInit_2['hydrogen'] : never
46
76
  }
47
77
 
78
+ declare type HydrogenResponseQueryOptions_2 = Omit<ResponseQueryOptions, 'next' | 'cache'> & {
79
+ hydrogen?: 'hydrogen' extends keyof RequestInit_3 ? RequestInit_3['hydrogen'] : never
80
+ }
81
+
48
82
  declare type LoadQueryOptions = Pick<
49
83
  HydrogenResponseQueryOptions,
50
84
  'perspective' | 'hydrogen' | 'useCdn' | 'stega' | 'headers' | 'tag'
51
85
  >
52
86
 
87
+ declare type LoadQueryOptions_2 = Pick<
88
+ HydrogenResponseQueryOptions_2,
89
+ 'perspective' | 'hydrogen' | 'useCdn' | 'stega' | 'headers' | 'tag'
90
+ >
91
+
53
92
  declare interface RequestInit_2 {
54
93
  hydrogen?: {
55
94
  /**
@@ -67,9 +106,26 @@ declare interface RequestInit_2 {
67
106
  }
68
107
  }
69
108
 
109
+ declare interface RequestInit_3 {
110
+ hydrogen?: {
111
+ /**
112
+ * The caching strategy to use for the subrequest.
113
+ * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies
114
+ */
115
+ cache?: CachingStrategy
116
+ /**
117
+ * Optional debugging information to be displayed in the subrequest profiler.
118
+ * @see https://shopify.dev/docs/custom-storefronts/hydrogen/debugging/subrequest-profiler#how-to-provide-more-debug-information-for-a-request
119
+ */
120
+ debug?: {
121
+ displayName: string
122
+ }
123
+ }
124
+ }
125
+
70
126
  export {SanityClient}
71
127
 
72
- export declare type SanityLoader = {
128
+ export declare type SanityContext = {
73
129
  /**
74
130
  * Query Sanity using the loader.
75
131
  * @see https://www.sanity.io/docs/loaders
@@ -80,19 +136,25 @@ export declare type SanityLoader = {
80
136
  options?: LoadQueryOptions,
81
137
  ): Promise<QueryResponseInitial<T>>
82
138
  client: SanityClient
139
+ preview?: CreateSanityContextOptions['preview']
140
+ }
141
+
142
+ export declare type SanityLoader = {
143
+ /**
144
+ * Query Sanity using the loader.
145
+ * @see https://www.sanity.io/docs/loaders
146
+ */
147
+ loadQuery<T = any>(
148
+ query: string,
149
+ params?: QueryParams,
150
+ options?: LoadQueryOptions_2,
151
+ ): Promise<QueryResponseInitial<T>>
152
+ client: SanityClient
83
153
  preview?: CreateSanityLoaderOptions['preview']
84
154
  }
85
155
 
156
+ declare type WaitUntil = (promise: Promise<unknown>) => void
157
+
86
158
  export * from '@sanity/client'
87
159
 
88
160
  export {}
89
-
90
- declare module '@shopify/remix-oxygen' {
91
- /**
92
- * Declare local additions to the Remix loader context.
93
- */
94
- interface AppLoadContext {
95
- session: HydrogenSession
96
- sanity: SanityLoader
97
- }
98
- }
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{SanityClient as e,createClient as t}from"@sanity/client";import{SanityClient as n,createClient as i}from"@sanity/client";import{createQueryStore as r}from"@sanity/react-loader";import{CacheLong as a,CacheNone as o}from"@shopify/hydrogen";function s(e,t){let n=e;return t&&(n+=JSON.stringify(t)),async function(e){const t=await(new TextEncoder).encode(e),n=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(n)).map((e=>e.toString(16).padStart(2,"0"))).join("")}(n)}const c=a(),l=r({client:!1,ssr:!0});function d(n){const{withCache:i,preview:r,strategy:a}=n;let d=n.client instanceof e?n.client:t(n.client);if("1"===d.config().apiVersion&&(d=d.withConfig({apiVersion:"v2022-03-07"})),r&&r.enabled){if(!r.token)throw new Error("Enabling preview mode requires a token.");const e=d.withConfig({useCdn:!1,token:r.token,perspective:"previewDrafts",stega:{...d.config().stega,enabled:!0,studioUrl:r.studioUrl}});l.setServerClient(e)}else l.setServerClient(d);return{async loadQuery(e,t,n){const d=r&&r.enabled?o():n?.hydrogen?.cache||a||c,y=await s(e,t);return await i(y,d,(async({addDebugData:i})=>{if("development"===process.env.NODE_ENV){i({displayName:n?.hydrogen?.debug?.displayName||"query Sanity"})}return await l.loadQuery(e,t,n)}))},client:d,preview:r}}export{n as SanityClient,i as createClient,d as createSanityLoader};//# sourceMappingURL=index.js.map
1
+ import{SanityClient as e,createClient as t}from"@sanity/client";import{SanityClient as n,createClient as i}from"@sanity/client";import{setServerClient as a,loadQuery as o}from"@sanity/react-loader";import{CacheLong as r,createWithCache as s,CacheNone as c}from"@shopify/hydrogen";import{h as l}from"./_chunks-es/utils.js";const p=r();function d(n){const{cache:i,waitUntil:r=()=>Promise.resolve(),request:d,preview:u,defaultStrategy:g}=n,w=i?s({cache:i,waitUntil:r,request:d}):null;let h=n.client instanceof e?n.client:t(n.client);if("1"===h.config().apiVersion&&(console.warn("No API version specified, defaulting to `v2022-03-07` which supports perspectives.\nYou can find the latest version in the Sanity changelog: https://www.sanity.io/changelog"),h=h.withConfig({apiVersion:"v2022-03-07"})),u&&u.enabled){if(!u.token)throw new Error("Enabling preview mode requires a token.");const e=h.withConfig({useCdn:!1,token:u.token,perspective:"previewDrafts",stega:{...h.config().stega,enabled:!0,studioUrl:u.studioUrl}});a(e)}else a(h);return{async loadQuery(e,t,n){const i=u&&u.enabled?c():n?.hydrogen?.cache||g||p,a=await l(e,t);return await(w?w(a,i,(async({addDebugData:i})=>{if("development"===process.env.NODE_ENV){i({displayName:n?.hydrogen?.debug?.displayName||"query Sanity"})}return await o(e,t,n)})):o(e,t,n))},client:h,preview:u}}const u=r();function g(n){const{withCache:i,preview:r,strategy:s}=n;let p=n.client instanceof e?n.client:t(n.client);if("1"===p.config().apiVersion&&(console.warn("No API version specified, defaulting to `v2022-03-07` which supports perspectives.\nYou can find the latest version in the Sanity changelog: https://www.sanity.io/changelog"),p=p.withConfig({apiVersion:"v2022-03-07"})),r&&r.enabled){if(!r.token)throw new Error("Enabling preview mode requires a token.");const e=p.withConfig({useCdn:!1,token:r.token,perspective:"previewDrafts",stega:{...p.config().stega,enabled:!0,studioUrl:r.studioUrl}});a(e)}else a(p);return{async loadQuery(e,t,n){const a=r&&r.enabled?c():n?.hydrogen?.cache||s||u,p=await l(e,t);return await i(p,a,(async({addDebugData:i})=>{if("development"===process.env.NODE_ENV){i({displayName:n?.hydrogen?.debug?.displayName||"query Sanity"})}return await o(e,t,n)}))},client:p,preview:r}}export{n as SanityClient,i as createClient,d as createSanityContext,g as createSanityLoader};//# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/utils.ts","../src/loader.ts"],"sourcesContent":["import type {QueryParams, QueryWithoutParams} from './client'\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 */\nexport function hashQuery(\n query: string,\n params: QueryParams | QueryWithoutParams,\n): Promise<string> {\n let hash = query\n\n if (params) {\n hash += JSON.stringify(params)\n }\n\n return sha256(hash)\n}\n","/* eslint-disable no-return-await */\nimport {createQueryStore, type QueryResponseInitial} from '@sanity/react-loader'\nimport {\n CacheLong,\n CacheNone,\n type CachingStrategy,\n type HydrogenSession,\n type WithCache,\n} from '@shopify/hydrogen'\n\nimport {\n type ClientConfig,\n createClient,\n type QueryParams,\n type QueryWithoutParams,\n type ResponseQueryOptions,\n SanityClient,\n} from './client'\nimport {hashQuery} from './utils'\n\nconst DEFAULT_CACHE_STRATEGY = CacheLong()\n\nexport type CreateSanityLoaderOptions = {\n // TODO: make this optional in dev? Or follow Hydrogen's pattern\n /**\n * Cache control utility from `@shopify/hydrogen`.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching/third-party\n */\n withCache: WithCache\n\n /**\n * Sanity client or configuration to use.\n */\n client: SanityClient | ClientConfig\n\n /**\n * The default caching strategy to use for `loadQuery` subrequests.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies\n *\n * Defaults to `CacheLong`\n */\n strategy?: CachingStrategy | null\n\n /**\n * Configuration for enabling preview mode.\n */\n preview?: {enabled: boolean; token: string; studioUrl: string}\n}\n\ninterface RequestInit {\n hydrogen?: {\n /**\n * The caching strategy to use for the subrequest.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies\n */\n cache?: CachingStrategy\n\n /**\n * Optional debugging information to be displayed in the subrequest profiler.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/debugging/subrequest-profiler#how-to-provide-more-debug-information-for-a-request\n */\n debug?: {\n displayName: string\n }\n }\n}\n\ntype HydrogenResponseQueryOptions = Omit<ResponseQueryOptions, 'next' | 'cache'> & {\n hydrogen?: 'hydrogen' extends keyof RequestInit ? RequestInit['hydrogen'] : never\n}\n\ntype LoadQueryOptions = Pick<\n HydrogenResponseQueryOptions,\n 'perspective' | 'hydrogen' | 'useCdn' | 'stega' | 'headers' | 'tag'\n>\n\nexport type SanityLoader = {\n /**\n * Query Sanity using the loader.\n * @see https://www.sanity.io/docs/loaders\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n loadQuery<T = any>(\n query: string,\n params?: QueryParams,\n options?: LoadQueryOptions,\n ): Promise<QueryResponseInitial<T>>\n\n client: SanityClient\n\n preview?: CreateSanityLoaderOptions['preview']\n}\n\ndeclare module '@shopify/remix-oxygen' {\n /**\n * Declare local additions to the Remix loader context.\n */\n export interface AppLoadContext {\n session: HydrogenSession\n sanity: SanityLoader\n }\n}\n\nconst queryStore = createQueryStore({client: false, ssr: true})\n\n// TODO: rename to match new Hydrogen creator, e.g. `createSanityContext`\n/**\n * @public\n */\nexport function createSanityLoader(options: CreateSanityLoaderOptions): SanityLoader {\n const {withCache, preview, strategy} = options\n let client =\n options.client instanceof SanityClient ? options.client : createClient(options.client)\n\n /**\n * TODO: should this default to the latest API version?\n * Or at least warn if a version that doesn't support perspectives is used?\n */\n if (client.config().apiVersion === '1') {\n client = client.withConfig({apiVersion: 'v2022-03-07'})\n }\n\n if (preview && preview.enabled) {\n if (!preview.token) {\n throw new Error('Enabling preview mode requires a token.')\n }\n\n const previewClient = client.withConfig({\n useCdn: false,\n token: preview.token,\n perspective: 'previewDrafts' as const,\n stega: {\n ...client.config().stega,\n enabled: true,\n studioUrl: preview.studioUrl,\n },\n })\n\n queryStore.setServerClient(previewClient)\n } else {\n queryStore.setServerClient(client)\n }\n\n const sanity = {\n async loadQuery<T>(\n query: string,\n params: QueryParams | QueryWithoutParams,\n loaderOptions?: LoadQueryOptions,\n ): Promise<QueryResponseInitial<T>> {\n // Don't store response if preview is enabled\n const cacheStrategy =\n preview && preview.enabled\n ? CacheNone()\n : loaderOptions?.hydrogen?.cache || strategy || DEFAULT_CACHE_STRATEGY\n\n const queryHash = await hashQuery(query, params)\n\n return await withCache(queryHash, cacheStrategy, async ({addDebugData}) => {\n // eslint-disable-next-line no-process-env\n if (process.env.NODE_ENV === 'development') {\n // Name displayed in the subrequest profiler\n const displayName = loaderOptions?.hydrogen?.debug?.displayName || 'query Sanity'\n\n addDebugData({\n displayName,\n })\n }\n\n return await queryStore.loadQuery<T>(query, params, loaderOptions)\n })\n },\n client,\n preview,\n }\n\n return sanity\n}\n"],"names":["hashQuery","query","params","hash","JSON","stringify","async","message","messageBuffer","TextEncoder","encode","hashBuffer","crypto","subtle","digest","Array","from","Uint8Array","map","b","toString","padStart","join","sha256","DEFAULT_CACHE_STRATEGY","CacheLong","queryStore","createQueryStore","client","ssr","createSanityLoader","options","withCache","preview","strategy","SanityClient","createClient","config","apiVersion","withConfig","enabled","token","Error","previewClient","useCdn","perspective","stega","studioUrl","setServerClient","loadQuery","loaderOptions","cacheStrategy","CacheNone","hydrogen","cache","queryHash","addDebugData","process","env","NODE_ENV","displayName","debug"],"mappings":"qPAqBgB,SAAAA,EACdC,EACAC,GAEA,IAAIC,EAAOF,EAEX,OAAIC,IACFC,GAAQC,KAAKC,UAAUH,IAtB3BI,eAA6BC,GAE3B,MAAMC,QAAsB,IAAIC,aAAcC,OAAOH,GAE/CI,QAAmBC,OAAOC,OAAOC,OAAO,UAAWN,GAElD,OAAAO,MAAMC,KAAK,IAAIC,WAAWN,IAC9BO,KAAKC,GAAMA,EAAEC,SAAS,IAAIC,SAAS,EAAG,OACtCC,KAAK,GACV,CAgBSC,CAAOpB,EAChB,CCZA,MAAMqB,EAAyBC,IAmFzBC,EAAaC,EAAiB,CAACC,QAAQ,EAAOC,KAAK,IAMlD,SAASC,EAAmBC,GACjC,MAAMC,UAACA,EAAAC,QAAWA,EAASC,SAAAA,GAAYH,EACnC,IAAAH,EACFG,EAAQH,kBAAkBO,EAAeJ,EAAQH,OAASQ,EAAaL,EAAQH,QAUjF,GAJmC,MAA/BA,EAAOS,SAASC,aAClBV,EAASA,EAAOW,WAAW,CAACD,WAAY,iBAGtCL,GAAWA,EAAQO,QAAS,CAC9B,IAAKP,EAAQQ,MACL,MAAA,IAAIC,MAAM,2CAGZ,MAAAC,EAAgBf,EAAOW,WAAW,CACtCK,QAAQ,EACRH,MAAOR,EAAQQ,MACfI,YAAa,gBACbC,MAAO,IACFlB,EAAOS,SAASS,MACnBN,SAAS,EACTO,UAAWd,EAAQc,aAIvBrB,EAAWsB,gBAAgBL,EAC7B,MACEjB,EAAWsB,gBAAgBpB,GAGd,MAAA,CACb,eAAMqB,CACJhD,EACAC,EACAgD,GAGA,MAAMC,EACJlB,GAAWA,EAAQO,QACfY,IACAF,GAAeG,UAAUC,OAASpB,GAAYV,EAE9C+B,QAAkBvD,EAAUC,EAAOC,GAEzC,aAAa8B,EAAUuB,EAAWJ,GAAe7C,OAAQkD,mBAEnD,GAAyB,gBAAzBC,QAAQC,IAAIC,SAA4B,CAI7BH,EAAA,CACXI,YAHkBV,GAAeG,UAAUQ,OAAOD,aAAe,gBAKrE,CAEA,aAAalC,EAAWuB,UAAahD,EAAOC,EAAQgD,EAAa,GAErE,EACAtB,SACAK,UAIJ"}
1
+ {"version":3,"file":"index.js","sources":["../src/context.ts","../src/loader.ts"],"sourcesContent":["import {loadQuery, type QueryResponseInitial, setServerClient} from '@sanity/react-loader'\nimport {CacheLong, CacheNone, type CachingStrategy, createWithCache} from '@shopify/hydrogen'\n\nimport {\n type ClientConfig,\n createClient,\n type QueryParams,\n type QueryWithoutParams,\n type ResponseQueryOptions,\n SanityClient,\n} from './client'\nimport {hashQuery} from './utils'\n\nconst DEFAULT_CACHE_STRATEGY = CacheLong()\n\ntype WaitUntil = (promise: Promise<unknown>) => void\n\nexport type CreateSanityContextOptions = {\n request: Request\n\n cache?: Cache | undefined\n waitUntil?: WaitUntil | undefined\n\n /**\n * Sanity client or configuration to use.\n */\n client: SanityClient | ClientConfig\n\n /**\n * The default caching strategy to use for `loadQuery` subrequests.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies\n *\n * Defaults to `CacheLong`\n */\n defaultStrategy?: CachingStrategy | null\n\n /**\n * Configuration for enabling preview mode.\n */\n preview?: {enabled: boolean; token: string; studioUrl: string}\n}\n\ninterface RequestInit {\n hydrogen?: {\n /**\n * The caching strategy to use for the subrequest.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies\n */\n cache?: CachingStrategy\n\n /**\n * Optional debugging information to be displayed in the subrequest profiler.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/debugging/subrequest-profiler#how-to-provide-more-debug-information-for-a-request\n */\n debug?: {\n displayName: string\n }\n }\n}\n\ntype HydrogenResponseQueryOptions = Omit<ResponseQueryOptions, 'next' | 'cache'> & {\n hydrogen?: 'hydrogen' extends keyof RequestInit ? RequestInit['hydrogen'] : never\n}\n\ntype LoadQueryOptions = Pick<\n HydrogenResponseQueryOptions,\n 'perspective' | 'hydrogen' | 'useCdn' | 'stega' | 'headers' | 'tag'\n>\n\nexport type SanityContext = {\n /**\n * Query Sanity using the loader.\n * @see https://www.sanity.io/docs/loaders\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n loadQuery<T = any>(\n query: string,\n params?: QueryParams,\n options?: LoadQueryOptions,\n ): Promise<QueryResponseInitial<T>>\n\n client: SanityClient\n\n preview?: CreateSanityContextOptions['preview']\n}\n\n/**\n * @public\n */\nexport function createSanityContext(options: CreateSanityContextOptions): SanityContext {\n const {cache, waitUntil = () => Promise.resolve(), request, preview, defaultStrategy} = options\n const withCache = cache ? createWithCache({cache, waitUntil, request}) : null\n let client =\n options.client instanceof SanityClient ? options.client : createClient(options.client)\n\n if (client.config().apiVersion === '1') {\n console.warn(\n 'No API version specified, defaulting to `v2022-03-07` which supports perspectives.\\nYou can find the latest version in the Sanity changelog: https://www.sanity.io/changelog',\n )\n client = client.withConfig({apiVersion: 'v2022-03-07'})\n }\n\n if (preview && preview.enabled) {\n if (!preview.token) {\n throw new Error('Enabling preview mode requires a token.')\n }\n\n const previewClient = client.withConfig({\n useCdn: false,\n token: preview.token,\n perspective: 'previewDrafts' as const,\n stega: {\n ...client.config().stega,\n enabled: true,\n studioUrl: preview.studioUrl,\n },\n })\n\n setServerClient(previewClient)\n } else {\n setServerClient(client)\n }\n\n const sanity = {\n async loadQuery<T>(\n query: string,\n params: QueryParams | QueryWithoutParams,\n loaderOptions?: LoadQueryOptions,\n ): Promise<QueryResponseInitial<T>> {\n // Don't store response if preview is enabled\n const cacheStrategy =\n preview && preview.enabled\n ? CacheNone()\n : loaderOptions?.hydrogen?.cache || defaultStrategy || DEFAULT_CACHE_STRATEGY\n\n const queryHash = await hashQuery(query, params)\n\n return await (withCache\n ? withCache(queryHash, cacheStrategy, async ({addDebugData}) => {\n if (process.env.NODE_ENV === 'development') {\n // Name displayed in the subrequest profiler\n const displayName = loaderOptions?.hydrogen?.debug?.displayName || 'query Sanity'\n\n addDebugData({\n displayName,\n })\n }\n\n return await loadQuery<T>(query, params, loaderOptions)\n })\n : loadQuery<T>(query, params, loaderOptions))\n },\n client,\n preview,\n }\n\n return sanity\n}\n","import {loadQuery, type QueryResponseInitial, setServerClient} from '@sanity/react-loader'\nimport {CacheLong, CacheNone, type CachingStrategy, type WithCache} from '@shopify/hydrogen'\n\nimport {\n type ClientConfig,\n createClient,\n type QueryParams,\n type QueryWithoutParams,\n type ResponseQueryOptions,\n SanityClient,\n} from './client'\nimport {hashQuery} from './utils'\n\nconst DEFAULT_CACHE_STRATEGY = CacheLong()\n\nexport type CreateSanityLoaderOptions = {\n /**\n * Cache control utility from `@shopify/hydrogen`.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching/third-party\n */\n withCache: WithCache\n\n /**\n * Sanity client or configuration to use.\n */\n client: SanityClient | ClientConfig\n\n /**\n * The default caching strategy to use for `loadQuery` subrequests.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies\n *\n * Defaults to `CacheLong`\n */\n strategy?: CachingStrategy | null\n\n /**\n * Configuration for enabling preview mode.\n */\n preview?: {enabled: boolean; token: string; studioUrl: string}\n}\n\ninterface RequestInit {\n hydrogen?: {\n /**\n * The caching strategy to use for the subrequest.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies\n */\n cache?: CachingStrategy\n\n /**\n * Optional debugging information to be displayed in the subrequest profiler.\n * @see https://shopify.dev/docs/custom-storefronts/hydrogen/debugging/subrequest-profiler#how-to-provide-more-debug-information-for-a-request\n */\n debug?: {\n displayName: string\n }\n }\n}\n\ntype HydrogenResponseQueryOptions = Omit<ResponseQueryOptions, 'next' | 'cache'> & {\n hydrogen?: 'hydrogen' extends keyof RequestInit ? RequestInit['hydrogen'] : never\n}\n\ntype LoadQueryOptions = Pick<\n HydrogenResponseQueryOptions,\n 'perspective' | 'hydrogen' | 'useCdn' | 'stega' | 'headers' | 'tag'\n>\n\nexport type SanityLoader = {\n /**\n * Query Sanity using the loader.\n * @see https://www.sanity.io/docs/loaders\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n loadQuery<T = any>(\n query: string,\n params?: QueryParams,\n options?: LoadQueryOptions,\n ): Promise<QueryResponseInitial<T>>\n\n client: SanityClient\n\n preview?: CreateSanityLoaderOptions['preview']\n}\n\n/**\n * @deprecated Use `createSanityContext` instead\n */\nexport function createSanityLoader(options: CreateSanityLoaderOptions): SanityLoader {\n const {withCache, preview, strategy} = options\n let client =\n options.client instanceof SanityClient ? options.client : createClient(options.client)\n\n if (client.config().apiVersion === '1') {\n console.warn(\n 'No API version specified, defaulting to `v2022-03-07` which supports perspectives.\\nYou can find the latest version in the Sanity changelog: https://www.sanity.io/changelog',\n )\n client = client.withConfig({apiVersion: 'v2022-03-07'})\n }\n\n if (preview && preview.enabled) {\n if (!preview.token) {\n throw new Error('Enabling preview mode requires a token.')\n }\n\n const previewClient = client.withConfig({\n useCdn: false,\n token: preview.token,\n perspective: 'previewDrafts' as const,\n stega: {\n ...client.config().stega,\n enabled: true,\n studioUrl: preview.studioUrl,\n },\n })\n\n setServerClient(previewClient)\n } else {\n setServerClient(client)\n }\n\n const sanity = {\n async loadQuery<T>(\n query: string,\n params: QueryParams | QueryWithoutParams,\n loaderOptions?: LoadQueryOptions,\n ): Promise<QueryResponseInitial<T>> {\n // Don't store response if preview is enabled\n const cacheStrategy =\n preview && preview.enabled\n ? CacheNone()\n : loaderOptions?.hydrogen?.cache || strategy || DEFAULT_CACHE_STRATEGY\n\n const queryHash = await hashQuery(query, params)\n\n return await withCache(queryHash, cacheStrategy, async ({addDebugData}) => {\n // eslint-disable-next-line no-process-env\n if (process.env.NODE_ENV === 'development') {\n // Name displayed in the subrequest profiler\n const displayName = loaderOptions?.hydrogen?.debug?.displayName || 'query Sanity'\n\n addDebugData({\n displayName,\n })\n }\n\n return await loadQuery<T>(query, params, loaderOptions)\n })\n },\n client,\n preview,\n }\n\n return sanity\n}\n"],"names":["SanityClient","createClient","setServerClient","loadQuery","CacheLong","createWithCache","CacheNone","hashQuery","DEFAULT_CACHE_STRATEGY","createSanityContext","options","cache","waitUntil","Promise","resolve","request","preview","defaultStrategy","withCache","client","config","apiVersion","console","warn","withConfig","enabled","token","Error","previewClient","useCdn","perspective","stega","studioUrl","query","params","loaderOptions","cacheStrategy","hydrogen","queryHash","async","addDebugData","process","env","NODE_ENV","displayName","debug","createSanityLoader","strategy"],"mappings":"uBAaAA,kBAAAC,MAAA,wCAAAD,kBAAAC,MAAA,2CAAAC,eAAAC,MAAA,2CAAAC,qBAAAC,eAAAC,MAAA,gCAAAC,MAAA,wBAAA,MAAMC,EAAyBJ,IA4ExB,SAASK,EAAoBC,GAC5B,MAAAC,MAACA,YAAOC,EAAY,IAAMC,QAAQC,kBAAWC,UAASC,EAASC,gBAAAA,GAAmBP,EAClFQ,EAAYP,EAAQN,EAAgB,CAACM,QAAOC,YAAWG,YAAY,KACrE,IAAAI,EACFT,EAAQS,kBAAkBnB,EAAeU,EAAQS,OAASlB,EAAaS,EAAQS,QASjF,GAPmC,MAA/BA,EAAOC,SAASC,aAClBC,QAAQC,KACN,gLAEFJ,EAASA,EAAOK,WAAW,CAACH,WAAY,iBAGtCL,GAAWA,EAAQS,QAAS,CAC9B,IAAKT,EAAQU,MACL,MAAA,IAAIC,MAAM,2CAGZ,MAAAC,EAAgBT,EAAOK,WAAW,CACtCK,QAAQ,EACRH,MAAOV,EAAQU,MACfI,YAAa,gBACbC,MAAO,IACFZ,EAAOC,SAASW,MACnBN,SAAS,EACTO,UAAWhB,EAAQgB,aAIvB9B,EAAgB0B,EAClB,MACE1B,EAAgBiB,GAGH,MAAA,CACb,eAAMhB,CACJ8B,EACAC,EACAC,GAGA,MAAMC,EACJpB,GAAWA,EAAQS,QACfnB,IACA6B,GAAeE,UAAU1B,OAASM,GAAmBT,EAErD8B,QAAkB/B,EAAU0B,EAAOC,GAElC,aAAOhB,EACVA,EAAUoB,EAAWF,GAAeG,OAAQC,mBACtC,GAAyB,gBAAzBC,QAAQC,IAAIC,SAA4B,CAI7BH,EAAA,CACXI,YAHkBT,GAAeE,UAAUQ,OAAOD,aAAe,gBAKrE,CAEA,aAAazC,EAAa8B,EAAOC,EAAQC,EAAa,IAExDhC,EAAa8B,EAAOC,EAAQC,GAClC,EACAhB,SACAH,UAIJ,CChJA,MAAMR,EAAyBJ,IA2ExB,SAAS0C,EAAmBpC,GACjC,MAAMQ,UAACA,EAAAF,QAAWA,EAAS+B,SAAAA,GAAYrC,EACnC,IAAAS,EACFT,EAAQS,kBAAkBnB,EAAeU,EAAQS,OAASlB,EAAaS,EAAQS,QASjF,GAPmC,MAA/BA,EAAOC,SAASC,aAClBC,QAAQC,KACN,gLAEFJ,EAASA,EAAOK,WAAW,CAACH,WAAY,iBAGtCL,GAAWA,EAAQS,QAAS,CAC9B,IAAKT,EAAQU,MACL,MAAA,IAAIC,MAAM,2CAGZ,MAAAC,EAAgBT,EAAOK,WAAW,CACtCK,QAAQ,EACRH,MAAOV,EAAQU,MACfI,YAAa,gBACbC,MAAO,IACFZ,EAAOC,SAASW,MACnBN,SAAS,EACTO,UAAWhB,EAAQgB,aAIvB9B,EAAgB0B,EAClB,MACE1B,EAAgBiB,GAGH,MAAA,CACb,eAAMhB,CACJ8B,EACAC,EACAC,GAGA,MAAMC,EACJpB,GAAWA,EAAQS,QACfnB,IACA6B,GAAeE,UAAU1B,OAASoC,GAAYvC,EAE9C8B,QAAkB/B,EAAU0B,EAAOC,GAEzC,aAAahB,EAAUoB,EAAWF,GAAeG,OAAQC,mBAEnD,GAAyB,gBAAzBC,QAAQC,IAAIC,SAA4B,CAI7BH,EAAA,CACXI,YAHkBT,GAAeE,UAAUQ,OAAOD,aAAe,gBAKrE,CAEA,aAAazC,EAAa8B,EAAOC,EAAQC,EAAa,GAE1D,EACAhB,SACAH,UAIJ"}
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@sanity/preview-url-secret"),t=require("@shopify/remix-oxygen");exports.action=async({context:e,request:s})=>"POST"!==s.method?t.json({message:"Method not allowed"},405):(await e.session.unset("projectId"),t.redirect("/",{headers:{"Set-Cookie":await e.session.commit()}})),exports.loader=async({context:s,request:o})=>{const{sanity:i}=s,r=i.client.config().projectId;if(!i.preview?.token||!r)throw new Response("Unable to enable preview mode. Please check your preview configuration",{status:500});const n=i.client.withConfig({useCdn:!1,token:i.preview.token}),{isValid:a,redirectTo:c="/"}=await e.validatePreviewUrl(n,o.url);if(!a)throw new Response("Invalid secret",{status:401});return await s.session.set("projectId",r),t.redirect(c,{headers:{"Set-Cookie":await s.session.commit()}})};//# sourceMappingURL=route.cjs.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@sanity/preview-url-secret"),r=require("@shopify/remix-oxygen"),t=require("../_chunks-cjs/utils.cjs");exports.action=async({context:e,request:n})=>{if("POST"!==n.method)return r.json({message:"Method not allowed"},405);try{const{session:n}=e;if(!t.a(n))throw new Error("Session is not an instance of HydrogenSession");return await n.unset("projectId"),r.redirect("/")}catch(e){throw console.error(e),new Response("Unable to disable preview mode. Please check your preview configuration",{status:500})}},exports.loader=async({context:n,request:o})=>{try{const{sanity:s,session:i}=n,a=s.client.config().projectId;if(!s.preview)return new Response("Preview mode is not enabled in this environment.",{status:403});if(!s.preview.token)throw new Error("Enabling preview mode requires a token.");if(!a)throw new Error("No `projectId` found in the client config.");if(!t.a(i))throw new Error("Session is not an instance of HydrogenSession");const c=s.client.withConfig({useCdn:!1,token:s.preview.token}),{isValid:w,redirectTo:u="/"}=await e.validatePreviewUrl(c,o.url);return w?(await i.set("projectId",a),r.redirect(u)):new Response("Invalid secret",{status:401})}catch(e){throw console.error(e),new Response("Unable to enable preview mode. Please check your preview configuration",{status:500})}};//# sourceMappingURL=route.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"route.cjs","sources":["../../src/preview/route.ts"],"sourcesContent":["import {validatePreviewUrl} from '@sanity/preview-url-secret'\nimport {type ActionFunction, json, type LoaderFunction, redirect} from '@shopify/remix-oxygen'\n\n/**\n * A `POST` request to this route will exit preview mode\n */\nexport const action: ActionFunction = async ({context, request}) => {\n if (request.method !== 'POST') {\n return json({message: 'Method not allowed'}, 405)\n }\n\n // TODO: make this a callback? `onExitPreview`?\n await context.session.unset('projectId')\n\n // TODO: confirm that the redirect and setting cookie has to happen here?\n return redirect('/', {\n headers: {\n 'Set-Cookie': await context.session.commit(),\n },\n })\n}\n\n/**\n * A `GET` request to this route will enter preview mode\n */\nexport const loader: LoaderFunction = async ({context, request}) => {\n const {sanity} = context\n const projectId = sanity.client.config().projectId\n\n if (!sanity.preview?.token || !projectId) {\n throw new Response('Unable to enable preview mode. Please check your preview configuration', {\n status: 500,\n })\n }\n\n const clientWithToken = sanity.client.withConfig({\n useCdn: false,\n token: sanity.preview.token,\n })\n\n const {isValid, redirectTo = '/'} = await validatePreviewUrl(clientWithToken, request.url)\n\n if (!isValid) {\n throw new Response('Invalid secret', {status: 401})\n }\n\n // TODO: make this a callback? `onEnterPreview`?\n await context.session.set('projectId', projectId)\n\n // TODO: confirm that the redirect and setting cookie has to happen here?\n return redirect(redirectTo, {\n headers: {\n 'Set-Cookie': await context.session.commit(),\n },\n })\n}\n"],"names":["Object","defineProperty","exports","value","previewUrlSecret","require","remixOxygen","action","async","context","request","method","json","message","session","unset","redirect","headers","commit","loader","sanity","projectId","client","config","preview","token","Response","status","clientWithToken","withConfig","useCdn","isValid","redirectTo","validatePreviewUrl","url","set"],"mappings":"aAMaA,OAAAC,eAAAC,QAAA,aAAA,CAAAC,OAAA,IAAA,IAAAC,EAAAC,QAAA,8BAAAC,EAAAD,QAAA,yBAiDbH,QAAAK,OAjDsCC,OAAQC,UAASC,aAC9B,SAAnBA,EAAQC,OACHC,EAAAA,KAAK,CAACC,QAAS,sBAAuB,YAIzCJ,EAAQK,QAAQC,MAAM,aAGrBC,EAAAA,SAAS,IAAK,CACnBC,QAAS,CACP,mBAAoBR,EAAQK,QAAQI,aAsC1ChB,QAAAiB,OA9BsCX,OAAQC,UAASC,cAC/C,MAAAU,OAACA,GAAUX,EACXY,EAAYD,EAAOE,OAAOC,SAASF,UAEzC,IAAKD,EAAOI,SAASC,QAAUJ,EACvB,MAAA,IAAIK,SAAS,yEAA0E,CAC3FC,OAAQ,MAIN,MAAAC,EAAkBR,EAAOE,OAAOO,WAAW,CAC/CC,QAAQ,EACRL,MAAOL,EAAOI,QAAQC,SAGlBM,QAACA,EAAAC,WAASA,EAAa,WAAaC,EAAAA,mBAAmBL,EAAiBlB,EAAQwB,KAEtF,IAAKH,EACH,MAAM,IAAIL,SAAS,iBAAkB,CAACC,OAAQ,MAIhD,aAAMlB,EAAQK,QAAQqB,IAAI,YAAad,GAGhCL,WAASgB,EAAY,CAC1Bf,QAAS,CACP,mBAAoBR,EAAQK,QAAQI,WAEvC"}
1
+ {"version":3,"file":"route.cjs","sources":["../../src/preview/route.ts"],"sourcesContent":["import {validatePreviewUrl} from '@sanity/preview-url-secret'\nimport type {HydrogenSession} from '@shopify/hydrogen'\nimport {type ActionFunction, json, type LoaderFunction, redirect} from '@shopify/remix-oxygen'\n\nimport type {SanityContext} from '../context'\nimport {assertSession} from '../utils'\n\n/**\n * A `POST` request to this route will exit preview mode\n */\nexport const action: ActionFunction = async ({context, request}) => {\n if (request.method !== 'POST') {\n return json({message: 'Method not allowed'}, 405)\n }\n\n try {\n const {session} = context\n if (!assertSession(session)) {\n throw new Error('Session is not an instance of HydrogenSession')\n }\n\n // TODO: make this a callback? `onExitPreview`?\n await session.unset('projectId')\n\n // TODO: confirm that the redirect and setting cookie has to happen here?\n return redirect('/')\n } catch (error) {\n console.error(error)\n throw new Response('Unable to disable preview mode. Please check your preview configuration', {\n status: 500,\n })\n }\n}\n\n/**\n * A `GET` request to this route will enter preview mode\n */\nexport const loader: LoaderFunction = async ({context, request}) => {\n try {\n // TODO: to remove\n const {sanity, session} = context as {sanity: SanityContext; session: HydrogenSession}\n const projectId = sanity.client.config().projectId\n\n if (!sanity.preview) {\n return new Response('Preview mode is not enabled in this environment.', {status: 403})\n }\n\n if (!sanity.preview.token) {\n throw new Error('Enabling preview mode requires a token.')\n }\n\n if (!projectId) {\n throw new Error('No `projectId` found in the client config.')\n }\n\n if (!assertSession(session)) {\n throw new Error('Session is not an instance of HydrogenSession')\n }\n\n const clientWithToken = sanity.client.withConfig({\n useCdn: false,\n token: sanity.preview.token,\n })\n\n const {isValid, redirectTo = '/'} = await validatePreviewUrl(clientWithToken, request.url)\n\n if (!isValid) {\n return new Response('Invalid secret', {status: 401})\n }\n\n // TODO: make this a callback? `onEnterPreview`?\n await session.set('projectId', projectId)\n\n // TODO: confirm that the redirect and setting cookie has to happen here?\n return redirect(redirectTo)\n } catch (error) {\n console.error(error)\n throw new Response('Unable to enable preview mode. Please check your preview configuration', {\n status: 500,\n })\n }\n}\n"],"names":["exports","action","async","context","request","method","json","message","session","assertSession","Error","unset","redirect","error","console","Response","status","loader","sanity","projectId","client","config","preview","token","clientWithToken","withConfig","useCdn","isValid","redirectTo","validatePreviewUrl","url","set"],"mappings":"yLAiFAA,QAAAC,OAvEsCC,OAAQC,UAASC,cACrD,GAAuB,SAAnBA,EAAQC,OACV,OAAOC,EAAKA,KAAA,CAACC,QAAS,sBAAuB,KAG3C,IACI,MAAAC,QAACA,GAAWL,EACd,IAACM,IAAcD,GACX,MAAA,IAAIE,MAAM,iDAIlB,aAAMF,EAAQG,MAAM,aAGbC,EAAAA,SAAS,WACTC,GACP,MAAAC,QAAQD,MAAMA,GACR,IAAIE,SAAS,0EAA2E,CAC5FC,OAAQ,KAEZ,GAkDFhB,QAAAiB,OA5CsCf,OAAQC,UAASC,cACjD,IAEI,MAAAc,OAACA,UAAQV,GAAWL,EACpBgB,EAAYD,EAAOE,OAAOC,SAASF,UAEzC,IAAKD,EAAOI,QACV,OAAO,IAAIP,SAAS,mDAAoD,CAACC,OAAQ,MAG/E,IAACE,EAAOI,QAAQC,MACZ,MAAA,IAAIb,MAAM,2CAGlB,IAAKS,EACG,MAAA,IAAIT,MAAM,8CAGd,IAACD,IAAcD,GACX,MAAA,IAAIE,MAAM,iDAGZ,MAAAc,EAAkBN,EAAOE,OAAOK,WAAW,CAC/CC,QAAQ,EACRH,MAAOL,EAAOI,QAAQC,SAGlBI,QAACA,EAAAC,WAASA,EAAa,WAAaC,EAAAA,mBAAmBL,EAAiBpB,EAAQ0B,KAEtF,OAAKH,SAKCnB,EAAQuB,IAAI,YAAaZ,GAGxBP,EAAAA,SAASgB,IAPP,IAAIb,SAAS,iBAAkB,CAACC,OAAQ,YAQ1CH,GACP,MAAAC,QAAQD,MAAMA,GACR,IAAIE,SAAS,yEAA0E,CAC3FC,OAAQ,KAEZ"}
@@ -1 +1 @@
1
- import{validatePreviewUrl as e}from"@sanity/preview-url-secret";import{json as t,redirect as o}from"@shopify/remix-oxygen";const s=async({context:e,request:s})=>"POST"!==s.method?t({message:"Method not allowed"},405):(await e.session.unset("projectId"),o("/",{headers:{"Set-Cookie":await e.session.commit()}})),i=async({context:t,request:s})=>{const{sanity:i}=t,n=i.client.config().projectId;if(!i.preview?.token||!n)throw new Response("Unable to enable preview mode. Please check your preview configuration",{status:500});const r=i.client.withConfig({useCdn:!1,token:i.preview.token}),{isValid:a,redirectTo:c="/"}=await e(r,s.url);if(!a)throw new Response("Invalid secret",{status:401});return await t.session.set("projectId",n),o(c,{headers:{"Set-Cookie":await t.session.commit()}})};export{s as action,i as loader};//# sourceMappingURL=route.js.map
1
+ import{validatePreviewUrl as e}from"@sanity/preview-url-secret";import{json as o,redirect as n}from"@shopify/remix-oxygen";import{a as t}from"../_chunks-es/utils.js";const r=async({context:e,request:r})=>{if("POST"!==r.method)return o({message:"Method not allowed"},405);try{const{session:o}=e;if(!t(o))throw new Error("Session is not an instance of HydrogenSession");return await o.unset("projectId"),n("/")}catch(e){throw console.error(e),new Response("Unable to disable preview mode. Please check your preview configuration",{status:500})}},s=async({context:o,request:r})=>{try{const{sanity:s,session:i}=o,a=s.client.config().projectId;if(!s.preview)return new Response("Preview mode is not enabled in this environment.",{status:403});if(!s.preview.token)throw new Error("Enabling preview mode requires a token.");if(!a)throw new Error("No `projectId` found in the client config.");if(!t(i))throw new Error("Session is not an instance of HydrogenSession");const c=s.client.withConfig({useCdn:!1,token:s.preview.token}),{isValid:w,redirectTo:p="/"}=await e(c,r.url);return w?(await i.set("projectId",a),n(p)):new Response("Invalid secret",{status:401})}catch(e){throw console.error(e),new Response("Unable to enable preview mode. Please check your preview configuration",{status:500})}};export{r as action,s as loader};//# sourceMappingURL=route.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"route.js","sources":["../../src/preview/route.ts"],"sourcesContent":["import {validatePreviewUrl} from '@sanity/preview-url-secret'\nimport {type ActionFunction, json, type LoaderFunction, redirect} from '@shopify/remix-oxygen'\n\n/**\n * A `POST` request to this route will exit preview mode\n */\nexport const action: ActionFunction = async ({context, request}) => {\n if (request.method !== 'POST') {\n return json({message: 'Method not allowed'}, 405)\n }\n\n // TODO: make this a callback? `onExitPreview`?\n await context.session.unset('projectId')\n\n // TODO: confirm that the redirect and setting cookie has to happen here?\n return redirect('/', {\n headers: {\n 'Set-Cookie': await context.session.commit(),\n },\n })\n}\n\n/**\n * A `GET` request to this route will enter preview mode\n */\nexport const loader: LoaderFunction = async ({context, request}) => {\n const {sanity} = context\n const projectId = sanity.client.config().projectId\n\n if (!sanity.preview?.token || !projectId) {\n throw new Response('Unable to enable preview mode. Please check your preview configuration', {\n status: 500,\n })\n }\n\n const clientWithToken = sanity.client.withConfig({\n useCdn: false,\n token: sanity.preview.token,\n })\n\n const {isValid, redirectTo = '/'} = await validatePreviewUrl(clientWithToken, request.url)\n\n if (!isValid) {\n throw new Response('Invalid secret', {status: 401})\n }\n\n // TODO: make this a callback? `onEnterPreview`?\n await context.session.set('projectId', projectId)\n\n // TODO: confirm that the redirect and setting cookie has to happen here?\n return redirect(redirectTo, {\n headers: {\n 'Set-Cookie': await context.session.commit(),\n },\n })\n}\n"],"names":["validatePreviewUrl","json","redirect","action","async","context","request","method","message","session","unset","headers","commit","loader","sanity","projectId","client","config","preview","token","Response","status","clientWithToken","withConfig","useCdn","isValid","redirectTo","url","set"],"mappings":"6BAMaA,MAAA,4CAAAC,cAAAC,MAAA,wBAAA,MAAAC,EAAyBC,OAAQC,UAASC,aAC9B,SAAnBA,EAAQC,OACHN,EAAK,CAACO,QAAS,sBAAuB,YAIzCH,EAAQI,QAAQC,MAAM,aAGrBR,EAAS,IAAK,CACnBS,QAAS,CACP,mBAAoBN,EAAQI,QAAQG,aAQ7BC,EAAyBT,OAAQC,UAASC,cAC/C,MAAAQ,OAACA,GAAUT,EACXU,EAAYD,EAAOE,OAAOC,SAASF,UAEzC,IAAKD,EAAOI,SAASC,QAAUJ,EACvB,MAAA,IAAIK,SAAS,yEAA0E,CAC3FC,OAAQ,MAIN,MAAAC,EAAkBR,EAAOE,OAAOO,WAAW,CAC/CC,QAAQ,EACRL,MAAOL,EAAOI,QAAQC,SAGlBM,QAACA,EAASC,WAAAA,EAAa,WAAa1B,EAAmBsB,EAAiBhB,EAAQqB,KAEtF,IAAKF,EACH,MAAM,IAAIL,SAAS,iBAAkB,CAACC,OAAQ,MAIhD,aAAMhB,EAAQI,QAAQmB,IAAI,YAAab,GAGhCb,EAASwB,EAAY,CAC1Bf,QAAS,CACP,mBAAoBN,EAAQI,QAAQG,WAEvC"}
1
+ {"version":3,"file":"route.js","sources":["../../src/preview/route.ts"],"sourcesContent":["import {validatePreviewUrl} from '@sanity/preview-url-secret'\nimport type {HydrogenSession} from '@shopify/hydrogen'\nimport {type ActionFunction, json, type LoaderFunction, redirect} from '@shopify/remix-oxygen'\n\nimport type {SanityContext} from '../context'\nimport {assertSession} from '../utils'\n\n/**\n * A `POST` request to this route will exit preview mode\n */\nexport const action: ActionFunction = async ({context, request}) => {\n if (request.method !== 'POST') {\n return json({message: 'Method not allowed'}, 405)\n }\n\n try {\n const {session} = context\n if (!assertSession(session)) {\n throw new Error('Session is not an instance of HydrogenSession')\n }\n\n // TODO: make this a callback? `onExitPreview`?\n await session.unset('projectId')\n\n // TODO: confirm that the redirect and setting cookie has to happen here?\n return redirect('/')\n } catch (error) {\n console.error(error)\n throw new Response('Unable to disable preview mode. Please check your preview configuration', {\n status: 500,\n })\n }\n}\n\n/**\n * A `GET` request to this route will enter preview mode\n */\nexport const loader: LoaderFunction = async ({context, request}) => {\n try {\n // TODO: to remove\n const {sanity, session} = context as {sanity: SanityContext; session: HydrogenSession}\n const projectId = sanity.client.config().projectId\n\n if (!sanity.preview) {\n return new Response('Preview mode is not enabled in this environment.', {status: 403})\n }\n\n if (!sanity.preview.token) {\n throw new Error('Enabling preview mode requires a token.')\n }\n\n if (!projectId) {\n throw new Error('No `projectId` found in the client config.')\n }\n\n if (!assertSession(session)) {\n throw new Error('Session is not an instance of HydrogenSession')\n }\n\n const clientWithToken = sanity.client.withConfig({\n useCdn: false,\n token: sanity.preview.token,\n })\n\n const {isValid, redirectTo = '/'} = await validatePreviewUrl(clientWithToken, request.url)\n\n if (!isValid) {\n return new Response('Invalid secret', {status: 401})\n }\n\n // TODO: make this a callback? `onEnterPreview`?\n await session.set('projectId', projectId)\n\n // TODO: confirm that the redirect and setting cookie has to happen here?\n return redirect(redirectTo)\n } catch (error) {\n console.error(error)\n throw new Response('Unable to enable preview mode. Please check your preview configuration', {\n status: 500,\n })\n }\n}\n"],"names":["action","async","context","request","method","json","message","session","assertSession","Error","unset","redirect","error","console","Response","status","loader","sanity","projectId","client","config","preview","token","clientWithToken","withConfig","useCdn","isValid","redirectTo","validatePreviewUrl","url","set"],"mappings":"sKAUO,MAAMA,EAAyBC,OAAQC,UAASC,cACrD,GAAuB,SAAnBA,EAAQC,OACV,OAAOC,EAAK,CAACC,QAAS,sBAAuB,KAG3C,IACI,MAAAC,QAACA,GAAWL,EACd,IAACM,EAAcD,GACX,MAAA,IAAIE,MAAM,iDAIlB,aAAMF,EAAQG,MAAM,aAGbC,EAAS,WACTC,GACP,MAAAC,QAAQD,MAAMA,GACR,IAAIE,SAAS,0EAA2E,CAC5FC,OAAQ,KAEZ,GAMWC,EAAyBf,OAAQC,UAASC,cACjD,IAEI,MAAAc,OAACA,UAAQV,GAAWL,EACpBgB,EAAYD,EAAOE,OAAOC,SAASF,UAEzC,IAAKD,EAAOI,QACV,OAAO,IAAIP,SAAS,mDAAoD,CAACC,OAAQ,MAG/E,IAACE,EAAOI,QAAQC,MACZ,MAAA,IAAIb,MAAM,2CAGlB,IAAKS,EACG,MAAA,IAAIT,MAAM,8CAGd,IAACD,EAAcD,GACX,MAAA,IAAIE,MAAM,iDAGZ,MAAAc,EAAkBN,EAAOE,OAAOK,WAAW,CAC/CC,QAAQ,EACRH,MAAOL,EAAOI,QAAQC,SAGlBI,QAACA,EAASC,WAAAA,EAAa,WAAaC,EAAmBL,EAAiBpB,EAAQ0B,KAEtF,OAAKH,SAKCnB,EAAQuB,IAAI,YAAaZ,GAGxBP,EAASgB,IAPP,IAAIb,SAAS,iBAAkB,CAACC,OAAQ,YAQ1CH,GACP,MAAAC,QAAQD,MAAMA,GACR,IAAIE,SAAS,yEAA0E,CAC3FC,OAAQ,KAEZ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hydrogen-sanity",
3
- "version": "4.1.1",
3
+ "version": "4.2.0",
4
4
  "description": "Sanity.io toolkit for Hydrogen",
5
5
  "keywords": [
6
6
  "sanity",
@@ -0,0 +1,131 @@
1
+ import type {QueryStore} from '@sanity/react-loader'
2
+ import {CacheShort, WithCache} from '@shopify/hydrogen'
3
+ import groq from 'groq'
4
+ import {beforeEach, describe, expect, it, vi} from 'vitest'
5
+
6
+ import {createClient, SanityClient} from './client'
7
+ import {createSanityContext} from './context'
8
+ import {hashQuery} from './utils'
9
+
10
+ // Mock the global caches object
11
+ const cache = vi.hoisted<Cache>(() => ({
12
+ add: vi.fn().mockResolvedValue(undefined),
13
+ addAll: vi.fn().mockResolvedValue(undefined),
14
+ delete: vi.fn().mockResolvedValue(true),
15
+ keys: vi.fn().mockResolvedValue([]),
16
+ match: vi.fn().mockResolvedValue(undefined),
17
+ matchAll: vi.fn().mockResolvedValue([]),
18
+ put: vi.fn().mockResolvedValue(undefined),
19
+ }))
20
+
21
+ // Mock the Sanity loader
22
+ const loadQuery = vi.hoisted<QueryStore['loadQuery']>(() => vi.fn().mockResolvedValue(null))
23
+
24
+ let withCache = vi.hoisted<WithCache | null>(() => null)
25
+
26
+ vi.mock('@shopify/hydrogen', async (importOriginal) => {
27
+ const module = await importOriginal<typeof import('@shopify/hydrogen')>()
28
+ withCache = vi
29
+ .fn()
30
+ .mockImplementation(module.createWithCache({cache, waitUntil: () => Promise.resolve()}))
31
+
32
+ return {
33
+ ...module,
34
+ createWithCache: vi.fn().mockReturnValue(withCache),
35
+ }
36
+ })
37
+
38
+ vi.mock('@sanity/react-loader', async (importOriginal) => {
39
+ const module = await importOriginal<typeof import('@sanity/react-loader')>()
40
+ const queryStore = module.createQueryStore({client: false, ssr: true})
41
+
42
+ return {
43
+ ...module,
44
+ createQueryStore: vi.fn().mockReturnValue({
45
+ ...queryStore,
46
+ loadQuery,
47
+ }),
48
+ }
49
+ })
50
+
51
+ const client = createClient({projectId: 'my-project-id', dataset: 'my-dataset'})
52
+
53
+ const query = groq`true`
54
+ const params = {}
55
+ const hashedQuery = await hashQuery(query, params)
56
+
57
+ beforeEach(() => {
58
+ vi.clearAllMocks()
59
+ })
60
+
61
+ describe('the Sanity request context', () => {
62
+ const request = new Request('https://example.com')
63
+ const sanityContext = createSanityContext({request, cache, client})
64
+
65
+ it('should return a client', () => {
66
+ expect(sanityContext.client).toSatisfy((contextClient) => contextClient instanceof SanityClient)
67
+ })
68
+
69
+ it('queries should get cached using the default caching strategy', async () => {
70
+ const defaultStrategy = CacheShort()
71
+
72
+ const contextWithDefaultStrategy = createSanityContext({
73
+ request,
74
+ cache,
75
+ client,
76
+ defaultStrategy,
77
+ })
78
+
79
+ await contextWithDefaultStrategy.loadQuery<boolean>(query, params)
80
+ expect(withCache).toHaveBeenCalledWith(hashedQuery, defaultStrategy, expect.any(Function))
81
+ expect(cache.put).toHaveBeenCalled()
82
+ })
83
+
84
+ it('queries should use the cache strategy passed in `loadQuery`', async () => {
85
+ const strategy = CacheShort()
86
+ await sanityContext.loadQuery<boolean>(query, params, {
87
+ hydrogen: {cache: strategy},
88
+ })
89
+ expect(withCache).toHaveBeenCalledWith(hashedQuery, strategy, expect.any(Function))
90
+ expect(cache.put).toHaveBeenCalled()
91
+ })
92
+ })
93
+
94
+ describe('when configured for preview', () => {
95
+ const request = new Request('https://example.com')
96
+ const previewContext = createSanityContext({
97
+ request,
98
+ cache,
99
+ client,
100
+ preview: {
101
+ enabled: true,
102
+ token: 'my-token',
103
+ studioUrl: 'https://example.com',
104
+ },
105
+ })
106
+
107
+ it('should throw if a token is not provided', () => {
108
+ expect(() =>
109
+ // @ts-expect-error meant to test invalid configuration
110
+ createSanityContext({client, preview: {enabled: true}}),
111
+ ).toThrowErrorMatchingInlineSnapshot(`[Error: Enabling preview mode requires a token.]`)
112
+ })
113
+
114
+ it.todo(`shouldn't use API CDN`, () => {
115
+ expect(previewContext.client.config().useCdn).toBe(false)
116
+ })
117
+
118
+ it.todo('should use the `previewDrafts` perspective', () => {
119
+ expect(previewContext.client.config().perspective).toBe('previewDrafts')
120
+ })
121
+
122
+ it('should enable preview mode', () => {
123
+ expect(previewContext.preview?.enabled).toBe(true)
124
+ })
125
+
126
+ it(`shouldn't cache queries`, async () => {
127
+ await previewContext.loadQuery<boolean>(query)
128
+ expect(loadQuery).toHaveBeenCalledOnce()
129
+ expect(cache.put).not.toHaveBeenCalled()
130
+ })
131
+ })
package/src/context.ts ADDED
@@ -0,0 +1,158 @@
1
+ import {loadQuery, type QueryResponseInitial, setServerClient} from '@sanity/react-loader'
2
+ import {CacheLong, CacheNone, type CachingStrategy, createWithCache} from '@shopify/hydrogen'
3
+
4
+ import {
5
+ type ClientConfig,
6
+ createClient,
7
+ type QueryParams,
8
+ type QueryWithoutParams,
9
+ type ResponseQueryOptions,
10
+ SanityClient,
11
+ } from './client'
12
+ import {hashQuery} from './utils'
13
+
14
+ const DEFAULT_CACHE_STRATEGY = CacheLong()
15
+
16
+ type WaitUntil = (promise: Promise<unknown>) => void
17
+
18
+ export type CreateSanityContextOptions = {
19
+ request: Request
20
+
21
+ cache?: Cache | undefined
22
+ waitUntil?: WaitUntil | undefined
23
+
24
+ /**
25
+ * Sanity client or configuration to use.
26
+ */
27
+ client: SanityClient | ClientConfig
28
+
29
+ /**
30
+ * The default caching strategy to use for `loadQuery` subrequests.
31
+ * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies
32
+ *
33
+ * Defaults to `CacheLong`
34
+ */
35
+ defaultStrategy?: CachingStrategy | null
36
+
37
+ /**
38
+ * Configuration for enabling preview mode.
39
+ */
40
+ preview?: {enabled: boolean; token: string; studioUrl: string}
41
+ }
42
+
43
+ interface RequestInit {
44
+ hydrogen?: {
45
+ /**
46
+ * The caching strategy to use for the subrequest.
47
+ * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching#caching-strategies
48
+ */
49
+ cache?: CachingStrategy
50
+
51
+ /**
52
+ * Optional debugging information to be displayed in the subrequest profiler.
53
+ * @see https://shopify.dev/docs/custom-storefronts/hydrogen/debugging/subrequest-profiler#how-to-provide-more-debug-information-for-a-request
54
+ */
55
+ debug?: {
56
+ displayName: string
57
+ }
58
+ }
59
+ }
60
+
61
+ type HydrogenResponseQueryOptions = Omit<ResponseQueryOptions, 'next' | 'cache'> & {
62
+ hydrogen?: 'hydrogen' extends keyof RequestInit ? RequestInit['hydrogen'] : never
63
+ }
64
+
65
+ type LoadQueryOptions = Pick<
66
+ HydrogenResponseQueryOptions,
67
+ 'perspective' | 'hydrogen' | 'useCdn' | 'stega' | 'headers' | 'tag'
68
+ >
69
+
70
+ export type SanityContext = {
71
+ /**
72
+ * Query Sanity using the loader.
73
+ * @see https://www.sanity.io/docs/loaders
74
+ */
75
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
76
+ loadQuery<T = any>(
77
+ query: string,
78
+ params?: QueryParams,
79
+ options?: LoadQueryOptions,
80
+ ): Promise<QueryResponseInitial<T>>
81
+
82
+ client: SanityClient
83
+
84
+ preview?: CreateSanityContextOptions['preview']
85
+ }
86
+
87
+ /**
88
+ * @public
89
+ */
90
+ export function createSanityContext(options: CreateSanityContextOptions): SanityContext {
91
+ const {cache, waitUntil = () => Promise.resolve(), request, preview, defaultStrategy} = options
92
+ const withCache = cache ? createWithCache({cache, waitUntil, request}) : null
93
+ let client =
94
+ options.client instanceof SanityClient ? options.client : createClient(options.client)
95
+
96
+ if (client.config().apiVersion === '1') {
97
+ console.warn(
98
+ 'No API version specified, defaulting to `v2022-03-07` which supports perspectives.\nYou can find the latest version in the Sanity changelog: https://www.sanity.io/changelog',
99
+ )
100
+ client = client.withConfig({apiVersion: 'v2022-03-07'})
101
+ }
102
+
103
+ if (preview && preview.enabled) {
104
+ if (!preview.token) {
105
+ throw new Error('Enabling preview mode requires a token.')
106
+ }
107
+
108
+ const previewClient = client.withConfig({
109
+ useCdn: false,
110
+ token: preview.token,
111
+ perspective: 'previewDrafts' as const,
112
+ stega: {
113
+ ...client.config().stega,
114
+ enabled: true,
115
+ studioUrl: preview.studioUrl,
116
+ },
117
+ })
118
+
119
+ setServerClient(previewClient)
120
+ } else {
121
+ setServerClient(client)
122
+ }
123
+
124
+ const sanity = {
125
+ async loadQuery<T>(
126
+ query: string,
127
+ params: QueryParams | QueryWithoutParams,
128
+ loaderOptions?: LoadQueryOptions,
129
+ ): Promise<QueryResponseInitial<T>> {
130
+ // Don't store response if preview is enabled
131
+ const cacheStrategy =
132
+ preview && preview.enabled
133
+ ? CacheNone()
134
+ : loaderOptions?.hydrogen?.cache || defaultStrategy || DEFAULT_CACHE_STRATEGY
135
+
136
+ const queryHash = await hashQuery(query, params)
137
+
138
+ return await (withCache
139
+ ? withCache(queryHash, cacheStrategy, async ({addDebugData}) => {
140
+ if (process.env.NODE_ENV === 'development') {
141
+ // Name displayed in the subrequest profiler
142
+ const displayName = loaderOptions?.hydrogen?.debug?.displayName || 'query Sanity'
143
+
144
+ addDebugData({
145
+ displayName,
146
+ })
147
+ }
148
+
149
+ return await loadQuery<T>(query, params, loaderOptions)
150
+ })
151
+ : loadQuery<T>(query, params, loaderOptions))
152
+ },
153
+ client,
154
+ preview,
155
+ }
156
+
157
+ return sanity
158
+ }
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './client'
2
+ export {createSanityContext, type SanityContext} from './context'
2
3
  export {createSanityLoader, type SanityLoader} from './loader'
3
4
  // TODO: add default session?
@@ -1,4 +1,3 @@
1
- /* eslint-disable max-nested-callbacks */
2
1
  import type {QueryStore} from '@sanity/react-loader'
3
2
  import {CacheShort, createWithCache} from '@shopify/hydrogen'
4
3
  import groq from 'groq'
package/src/loader.ts CHANGED
@@ -1,12 +1,5 @@
1
- /* eslint-disable no-return-await */
2
- import {createQueryStore, type QueryResponseInitial} from '@sanity/react-loader'
3
- import {
4
- CacheLong,
5
- CacheNone,
6
- type CachingStrategy,
7
- type HydrogenSession,
8
- type WithCache,
9
- } from '@shopify/hydrogen'
1
+ import {loadQuery, type QueryResponseInitial, setServerClient} from '@sanity/react-loader'
2
+ import {CacheLong, CacheNone, type CachingStrategy, type WithCache} from '@shopify/hydrogen'
10
3
 
11
4
  import {
12
5
  type ClientConfig,
@@ -21,7 +14,6 @@ import {hashQuery} from './utils'
21
14
  const DEFAULT_CACHE_STRATEGY = CacheLong()
22
15
 
23
16
  export type CreateSanityLoaderOptions = {
24
- // TODO: make this optional in dev? Or follow Hydrogen's pattern
25
17
  /**
26
18
  * Cache control utility from `@shopify/hydrogen`.
27
19
  * @see https://shopify.dev/docs/custom-storefronts/hydrogen/caching/third-party
@@ -91,32 +83,18 @@ export type SanityLoader = {
91
83
  preview?: CreateSanityLoaderOptions['preview']
92
84
  }
93
85
 
94
- declare module '@shopify/remix-oxygen' {
95
- /**
96
- * Declare local additions to the Remix loader context.
97
- */
98
- export interface AppLoadContext {
99
- session: HydrogenSession
100
- sanity: SanityLoader
101
- }
102
- }
103
-
104
- const queryStore = createQueryStore({client: false, ssr: true})
105
-
106
- // TODO: rename to match new Hydrogen creator, e.g. `createSanityContext`
107
86
  /**
108
- * @public
87
+ * @deprecated Use `createSanityContext` instead
109
88
  */
110
89
  export function createSanityLoader(options: CreateSanityLoaderOptions): SanityLoader {
111
90
  const {withCache, preview, strategy} = options
112
91
  let client =
113
92
  options.client instanceof SanityClient ? options.client : createClient(options.client)
114
93
 
115
- /**
116
- * TODO: should this default to the latest API version?
117
- * Or at least warn if a version that doesn't support perspectives is used?
118
- */
119
94
  if (client.config().apiVersion === '1') {
95
+ console.warn(
96
+ 'No API version specified, defaulting to `v2022-03-07` which supports perspectives.\nYou can find the latest version in the Sanity changelog: https://www.sanity.io/changelog',
97
+ )
120
98
  client = client.withConfig({apiVersion: 'v2022-03-07'})
121
99
  }
122
100
 
@@ -136,9 +114,9 @@ export function createSanityLoader(options: CreateSanityLoaderOptions): SanityLo
136
114
  },
137
115
  })
138
116
 
139
- queryStore.setServerClient(previewClient)
117
+ setServerClient(previewClient)
140
118
  } else {
141
- queryStore.setServerClient(client)
119
+ setServerClient(client)
142
120
  }
143
121
 
144
122
  const sanity = {
@@ -166,7 +144,7 @@ export function createSanityLoader(options: CreateSanityLoaderOptions): SanityLo
166
144
  })
167
145
  }
168
146
 
169
- return await queryStore.loadQuery<T>(query, params, loaderOptions)
147
+ return await loadQuery<T>(query, params, loaderOptions)
170
148
  })
171
149
  },
172
150
  client,
@@ -1,6 +1,10 @@
1
1
  import {validatePreviewUrl} from '@sanity/preview-url-secret'
2
+ import type {HydrogenSession} from '@shopify/hydrogen'
2
3
  import {type ActionFunction, json, type LoaderFunction, redirect} from '@shopify/remix-oxygen'
3
4
 
5
+ import type {SanityContext} from '../context'
6
+ import {assertSession} from '../utils'
7
+
4
8
  /**
5
9
  * A `POST` request to this route will exit preview mode
6
10
  */
@@ -9,48 +13,70 @@ export const action: ActionFunction = async ({context, request}) => {
9
13
  return json({message: 'Method not allowed'}, 405)
10
14
  }
11
15
 
12
- // TODO: make this a callback? `onExitPreview`?
13
- await context.session.unset('projectId')
16
+ try {
17
+ const {session} = context
18
+ if (!assertSession(session)) {
19
+ throw new Error('Session is not an instance of HydrogenSession')
20
+ }
21
+
22
+ // TODO: make this a callback? `onExitPreview`?
23
+ await session.unset('projectId')
14
24
 
15
- // TODO: confirm that the redirect and setting cookie has to happen here?
16
- return redirect('/', {
17
- headers: {
18
- 'Set-Cookie': await context.session.commit(),
19
- },
20
- })
25
+ // TODO: confirm that the redirect and setting cookie has to happen here?
26
+ return redirect('/')
27
+ } catch (error) {
28
+ console.error(error)
29
+ throw new Response('Unable to disable preview mode. Please check your preview configuration', {
30
+ status: 500,
31
+ })
32
+ }
21
33
  }
22
34
 
23
35
  /**
24
36
  * A `GET` request to this route will enter preview mode
25
37
  */
26
38
  export const loader: LoaderFunction = async ({context, request}) => {
27
- const {sanity} = context
28
- const projectId = sanity.client.config().projectId
39
+ try {
40
+ // TODO: to remove
41
+ const {sanity, session} = context as {sanity: SanityContext; session: HydrogenSession}
42
+ const projectId = sanity.client.config().projectId
29
43
 
30
- if (!sanity.preview?.token || !projectId) {
31
- throw new Response('Unable to enable preview mode. Please check your preview configuration', {
32
- status: 500,
33
- })
34
- }
44
+ if (!sanity.preview) {
45
+ return new Response('Preview mode is not enabled in this environment.', {status: 403})
46
+ }
35
47
 
36
- const clientWithToken = sanity.client.withConfig({
37
- useCdn: false,
38
- token: sanity.preview.token,
39
- })
48
+ if (!sanity.preview.token) {
49
+ throw new Error('Enabling preview mode requires a token.')
50
+ }
40
51
 
41
- const {isValid, redirectTo = '/'} = await validatePreviewUrl(clientWithToken, request.url)
52
+ if (!projectId) {
53
+ throw new Error('No `projectId` found in the client config.')
54
+ }
42
55
 
43
- if (!isValid) {
44
- throw new Response('Invalid secret', {status: 401})
45
- }
56
+ if (!assertSession(session)) {
57
+ throw new Error('Session is not an instance of HydrogenSession')
58
+ }
59
+
60
+ const clientWithToken = sanity.client.withConfig({
61
+ useCdn: false,
62
+ token: sanity.preview.token,
63
+ })
64
+
65
+ const {isValid, redirectTo = '/'} = await validatePreviewUrl(clientWithToken, request.url)
66
+
67
+ if (!isValid) {
68
+ return new Response('Invalid secret', {status: 401})
69
+ }
46
70
 
47
- // TODO: make this a callback? `onEnterPreview`?
48
- await context.session.set('projectId', projectId)
71
+ // TODO: make this a callback? `onEnterPreview`?
72
+ await session.set('projectId', projectId)
49
73
 
50
- // TODO: confirm that the redirect and setting cookie has to happen here?
51
- return redirect(redirectTo, {
52
- headers: {
53
- 'Set-Cookie': await context.session.commit(),
54
- },
55
- })
74
+ // TODO: confirm that the redirect and setting cookie has to happen here?
75
+ return redirect(redirectTo)
76
+ } catch (error) {
77
+ console.error(error)
78
+ throw new Response('Unable to enable preview mode. Please check your preview configuration', {
79
+ status: 500,
80
+ })
81
+ }
56
82
  }
package/src/utils.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type {HydrogenSession} from '@shopify/hydrogen'
2
+
1
3
  import type {QueryParams, QueryWithoutParams} from './client'
2
4
 
3
5
  /**
@@ -31,3 +33,18 @@ export function hashQuery(
31
33
 
32
34
  return sha256(hash)
33
35
  }
36
+
37
+ export function assertSession(session: unknown): session is HydrogenSession {
38
+ return (
39
+ !!session &&
40
+ typeof session === 'object' &&
41
+ 'get' in session &&
42
+ typeof session.get === 'function' &&
43
+ 'set' in session &&
44
+ typeof session.set === 'function' &&
45
+ 'unset' in session &&
46
+ typeof session.unset === 'function' &&
47
+ 'commit' in session &&
48
+ typeof session.commit === 'function'
49
+ )
50
+ }