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 +40 -21
- package/dist/_chunks-cjs/utils.cjs +1 -0
- package/dist/_chunks-cjs/utils.cjs.map +1 -0
- package/dist/_chunks-es/utils.js +1 -0
- package/dist/_chunks-es/utils.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +73 -11
- package/dist/index.d.ts +73 -11
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/preview/route.cjs +1 -1
- package/dist/preview/route.cjs.map +1 -1
- package/dist/preview/route.js +1 -1
- package/dist/preview/route.js.map +1 -1
- package/package.json +1 -1
- package/src/context.test.ts +131 -0
- package/src/context.ts +158 -0
- package/src/index.ts +1 -0
- package/src/loader.test.ts +0 -1
- package/src/loader.ts +9 -31
- package/src/preview/route.ts +57 -31
- package/src/utils.ts +17 -0
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 {
|
|
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
|
-
|
|
68
|
-
|
|
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 =
|
|
72
|
-
|
|
73
|
-
|
|
77
|
+
const sanity = createSanityContext({
|
|
78
|
+
request,
|
|
79
|
+
|
|
80
|
+
// To use the Hydrogen cache for queries
|
|
81
|
+
cache,
|
|
82
|
+
waitUntil,
|
|
74
83
|
|
|
75
|
-
//
|
|
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
|
|
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/
|
|
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
|
-
|
|
341
|
+
context: AppLoadContext,
|
|
337
342
|
) {
|
|
338
|
-
const projectId =
|
|
339
|
-
const studioHostname =
|
|
340
|
-
const isPreviewEnabled =
|
|
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: '/
|
|
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 ?? '
|
|
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");
|
|
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
|
package/dist/index.cjs.map
CHANGED
|
@@ -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
|
|
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
|
|
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{
|
|
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"}
|
package/dist/preview/route.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@sanity/preview-url-secret"),
|
|
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
|
|
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"}
|
package/dist/preview/route.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{validatePreviewUrl as e}from"@sanity/preview-url-secret";import{json as
|
|
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
|
|
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
|
@@ -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
package/src/loader.test.ts
CHANGED
package/src/loader.ts
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
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
|
-
* @
|
|
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
|
-
|
|
117
|
+
setServerClient(previewClient)
|
|
140
118
|
} else {
|
|
141
|
-
|
|
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
|
|
147
|
+
return await loadQuery<T>(query, params, loaderOptions)
|
|
170
148
|
})
|
|
171
149
|
},
|
|
172
150
|
client,
|
package/src/preview/route.ts
CHANGED
|
@@ -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
|
-
|
|
13
|
-
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
28
|
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
})
|
|
34
|
-
}
|
|
44
|
+
if (!sanity.preview) {
|
|
45
|
+
return new Response('Preview mode is not enabled in this environment.', {status: 403})
|
|
46
|
+
}
|
|
35
47
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
})
|
|
48
|
+
if (!sanity.preview.token) {
|
|
49
|
+
throw new Error('Enabling preview mode requires a token.')
|
|
50
|
+
}
|
|
40
51
|
|
|
41
|
-
|
|
52
|
+
if (!projectId) {
|
|
53
|
+
throw new Error('No `projectId` found in the client config.')
|
|
54
|
+
}
|
|
42
55
|
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
48
|
-
|
|
71
|
+
// TODO: make this a callback? `onEnterPreview`?
|
|
72
|
+
await session.set('projectId', projectId)
|
|
49
73
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
+
}
|