@shopify/hydrogen 2023.4.0 → 2023.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,41 @@
1
- import { createStorefrontClient as createStorefrontClient$1 } from '@shopify/hydrogen-react';
2
- export { AnalyticsEventName, AnalyticsPageType, ClientBrowserParameters, ExternalVideo, IMAGE_FRAGMENT, Image, MediaFile, ModelViewer, Money, ParsedMetafields, ShopPayButton, ShopifyAddToCart, ShopifyAddToCartPayload, ShopifyAnalytics, ShopifyAnalyticsPayload, ShopifyAnalyticsProduct, ShopifyCookies, ShopifyPageView, ShopifyPageViewPayload, ShopifySalesChannel, StorefrontApiResponse, StorefrontApiResponseError, StorefrontApiResponseOk, StorefrontApiResponseOkPartial, StorefrontApiResponsePartial, Video, flattenConnection, getClientBrowserParameters, getShopifyCookies, parseMetafield, sendShopifyAnalytics, storefrontApiCustomScalars, useMoney, useShopifyCookies } from '@shopify/hydrogen-react';
1
+ import { createStorefrontClient as createStorefrontClient$1, StorefrontClientProps } from '@shopify/hydrogen-react';
2
+ export { AnalyticsEventName, AnalyticsPageType, ClientBrowserParameters, ExternalVideo, IMAGE_FRAGMENT, Image, MediaFile, ModelViewer, Money, ParsedMetafields, ShopPayButton, ShopifyAddToCart, ShopifyAddToCartPayload, ShopifyAnalytics, ShopifyAnalyticsPayload, ShopifyAnalyticsProduct, ShopifyCookies, ShopifyPageView, ShopifyPageViewPayload, ShopifySalesChannel, StorefrontApiResponse, StorefrontApiResponseError, StorefrontApiResponseOk, StorefrontApiResponseOkPartial, StorefrontApiResponsePartial, Video, flattenConnection, getClientBrowserParameters, getShopifyCookies, parseGid, parseMetafield, sendShopifyAnalytics, storefrontApiCustomScalars, useMoney, useShopifyCookies } from '@shopify/hydrogen-react';
3
3
  import { ExecutionArgs } from 'graphql';
4
4
  import { LanguageCode, CountryCode, Maybe } from '@shopify/hydrogen-react/storefront-api-types';
5
5
  import { LoaderArgs, LoaderFunction, SerializeFrom, AppData } from '@remix-run/server-runtime';
6
6
  import * as react from 'react';
7
- import { Params, Location } from '@remix-run/react';
7
+ import { Params, Location, LinkProps } from '@remix-run/react';
8
8
  import { Thing, WithContext } from 'schema-dts';
9
+ import { PageInfo, Maybe as Maybe$1 } from '@shopify/hydrogen/storefront-api-types';
9
10
 
11
+ /**
12
+ * Override options for a cache strategy.
13
+ */
10
14
  interface AllCacheOptions {
15
+ /**
16
+ * The caching mode, generally `public`, `private`, or `no-store`.
17
+ */
11
18
  mode?: string;
19
+ /**
20
+ * The maximum amount of time in seconds that a resource will be considered fresh. See `max-age` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#:~:text=Response%20Directives-,max%2Dage,-The%20max%2Dage).
21
+ */
12
22
  maxAge?: number;
23
+ /**
24
+ * Indicate that the cache should serve the stale response in the background while revalidating the cache. See `stale-while-revalidate` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-while-revalidate).
25
+ */
13
26
  staleWhileRevalidate?: number;
27
+ /**
28
+ * Similar to `maxAge` but specific to shared caches. See `s-maxage` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#s-maxage).
29
+ */
14
30
  sMaxAge?: number;
31
+ /**
32
+ * Indicate that the cache should serve the stale response if an error occurs while revalidating the cache. See `stale-if-error` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-if-error).
33
+ */
15
34
  staleIfError?: number;
16
35
  }
36
+ /**
37
+ * Use the `CachingStrategy` to define a custom caching mechanism for your data. Or use one of the pre-defined caching strategies: CacheNone, CacheShort, CacheLong.
38
+ */
17
39
  type CachingStrategy = AllCacheOptions;
18
40
  type NoStoreStrategy = {
19
41
  mode: string;
@@ -44,93 +66,135 @@ type I18nBase = {
44
66
  language: LanguageCode;
45
67
  country: CountryCode;
46
68
  };
69
+ /**
70
+ * Wraps all the returned utilities from `createStorefrontClient`.
71
+ */
47
72
  type StorefrontClient<TI18n extends I18nBase> = {
48
73
  storefront: Storefront<TI18n>;
49
74
  };
75
+ /**
76
+ * Maps all the queries found in the project to variables and return types.
77
+ */
78
+ interface StorefrontQueries {
79
+ }
80
+ /**
81
+ * Maps all the mutations found in the project to variables and return types.
82
+ */
83
+ interface StorefrontMutations {
84
+ }
85
+ type GenericVariables = ExecutionArgs['variableValues'];
86
+ type EmptyVariables = {
87
+ [key: string]: never;
88
+ };
89
+ type AutoAddedVariableNames = 'country' | 'language';
90
+ type IsOptionalVariables<OperationTypeValue extends {
91
+ variables: any;
92
+ }> = Omit<OperationTypeValue['variables'], AutoAddedVariableNames> extends EmptyVariables ? true : GenericVariables extends OperationTypeValue['variables'] ? true : false;
93
+ type StorefrontCommonOptions<Variables extends GenericVariables> = {
94
+ headers?: HeadersInit;
95
+ storefrontApiVersion?: string;
96
+ } & (IsOptionalVariables<{
97
+ variables: Variables;
98
+ }> extends true ? {
99
+ variables?: Variables;
100
+ } : {
101
+ variables: Variables;
102
+ });
103
+ type StorefrontQuerySecondParam<RawGqlString extends keyof StorefrontQueries | string = string> = (RawGqlString extends keyof StorefrontQueries ? StorefrontCommonOptions<StorefrontQueries[RawGqlString]['variables']> : StorefrontCommonOptions<GenericVariables>) & {
104
+ cache?: CachingStrategy;
105
+ };
106
+ type StorefrontMutateSecondParam<RawGqlString extends keyof StorefrontMutations | string = string> = RawGqlString extends keyof StorefrontMutations ? StorefrontCommonOptions<StorefrontMutations[RawGqlString]['variables']> : StorefrontCommonOptions<GenericVariables>;
107
+ /**
108
+ * Interface to interact with the Storefront API.
109
+ */
50
110
  type Storefront<TI18n extends I18nBase = I18nBase> = {
51
- query: <T>(query: string, payload?: StorefrontCommonOptions & {
52
- cache?: CachingStrategy;
53
- }) => Promise<T>;
54
- mutate: <T>(mutation: string, payload?: StorefrontCommonOptions) => Promise<T>;
111
+ /** The function to run a query on Storefront API. */
112
+ query: <OverrideReturnType = any, RawGqlString extends string = string>(query: RawGqlString, ...options: RawGqlString extends keyof StorefrontQueries ? IsOptionalVariables<StorefrontQueries[RawGqlString]> extends true ? [StorefrontQuerySecondParam<RawGqlString>?] : [StorefrontQuerySecondParam<RawGqlString>] : [StorefrontQuerySecondParam?]) => Promise<RawGqlString extends keyof StorefrontQueries ? StorefrontQueries[RawGqlString]['return'] : OverrideReturnType>;
113
+ /** The function to run a mutation on Storefront API. */
114
+ mutate: <OverrideReturnType = any, RawGqlString extends string = string>(mutation: RawGqlString, ...options: RawGqlString extends keyof StorefrontMutations ? IsOptionalVariables<StorefrontMutations[RawGqlString]> extends true ? [StorefrontMutateSecondParam<RawGqlString>?] : [StorefrontMutateSecondParam<RawGqlString>] : [StorefrontMutateSecondParam?]) => Promise<RawGqlString extends keyof StorefrontMutations ? StorefrontMutations[RawGqlString]['return'] : OverrideReturnType>;
115
+ /** The cache instance passed in from the `createStorefrontClient` argument. */
55
116
  cache?: Cache;
117
+ /** Re-export of [`CacheNone`](/docs/api/hydrogen/utilities/cachenone). */
56
118
  CacheNone: typeof CacheNone;
119
+ /** Re-export of [`CacheLong`](/docs/api/hydrogen/utilities/cachelong). */
57
120
  CacheLong: typeof CacheLong;
121
+ /** Re-export of [`CacheShort`](/docs/api/hydrogen/utilities/cacheshort). */
58
122
  CacheShort: typeof CacheShort;
123
+ /** Re-export of [`CacheCustom`](/docs/api/hydrogen/utilities/cachecustom). */
59
124
  CacheCustom: typeof CacheCustom;
125
+ /** Re-export of [`generateCacheControlHeader`](/docs/api/hydrogen/utilities/generatecachecontrolheader). */
60
126
  generateCacheControlHeader: typeof generateCacheControlHeader;
127
+ /** Returns an object that contains headers that are needed for each query to Storefront API GraphQL endpoint. See [`getPublicTokenHeaders` in Hydrogen React](/docs/api/hydrogen-react/utilities/createstorefrontclient#:~:text=%27graphql%27.-,getPublicTokenHeaders,-(props%3F%3A) for more details. */
61
128
  getPublicTokenHeaders: ReturnType<typeof createStorefrontClient$1>['getPublicTokenHeaders'];
129
+ /** Returns an object that contains headers that are needed for each query to Storefront API GraphQL endpoint for API calls made from a server. See [`getPrivateTokenHeaders` in Hydrogen React](/docs/api/hydrogen-react/utilities/createstorefrontclient#:~:text=storefrontApiVersion-,getPrivateTokenHeaders,-(props%3F%3A) for more details.*/
62
130
  getPrivateTokenHeaders: ReturnType<typeof createStorefrontClient$1>['getPrivateTokenHeaders'];
131
+ /** Creates the fully-qualified URL to your myshopify.com domain. See [`getShopifyDomain` in Hydrogen React](/docs/api/hydrogen-react/utilities/createstorefrontclient#:~:text=StorefrontClientReturn-,getShopifyDomain,-(props%3F%3A) for more details. */
63
132
  getShopifyDomain: ReturnType<typeof createStorefrontClient$1>['getShopifyDomain'];
133
+ /** Creates the fully-qualified URL to your store's GraphQL endpoint. See [`getStorefrontApiUrl` in Hydrogen React](/docs/api/hydrogen-react/utilities/createstorefrontclient#:~:text=storeDomain-,getStorefrontApiUrl,-(props%3F%3A) for more details.*/
64
134
  getApiUrl: ReturnType<typeof createStorefrontClient$1>['getStorefrontApiUrl'];
135
+ /** Determines if the error is resulted from a Storefront API call. */
65
136
  isApiError: (error: any) => boolean;
137
+ /** The `i18n` object passed in from the `createStorefrontClient` argument. */
66
138
  i18n: TI18n;
67
139
  };
68
- type CreateStorefrontClientOptions<TI18n extends I18nBase> = Parameters<typeof createStorefrontClient$1>[0] & {
140
+ type HydrogenClientProps<TI18n> = {
141
+ /** Storefront API headers. If on Oxygen, use `getStorefrontHeaders()` */
69
142
  storefrontHeaders?: StorefrontHeaders;
143
+ /** An instance that implements the [Cache API](https://developer.mozilla.org/en-US/docs/Web/API/Cache) */
70
144
  cache?: Cache;
71
145
  /** @deprecated use storefrontHeaders instead */
72
146
  buyerIp?: string;
73
147
  /** @deprecated use storefrontHeaders instead */
74
148
  requestGroupId?: string | null;
149
+ /** The globally unique identifier for the Shop */
75
150
  storefrontId?: string;
151
+ /** The `waitUntil` function is used to keep the current request/response lifecycle alive even after a response has been sent. It should be provided by your platform. */
76
152
  waitUntil?: ExecutionContext['waitUntil'];
153
+ /** An object containing a country code and language code */
77
154
  i18n?: TI18n;
78
155
  };
156
+ type CreateStorefrontClientOptions<TI18n extends I18nBase> = HydrogenClientProps<TI18n> & StorefrontClientProps;
79
157
  type StorefrontHeaders = {
158
+ /** A unique ID that correlates all sub-requests together. */
80
159
  requestGroupId: string | null;
160
+ /** The IP address of the client. */
81
161
  buyerIp: string | null;
162
+ /** The cookie header from the client */
82
163
  cookie: string | null;
83
164
  };
84
- type StorefrontCommonOptions = {
85
- variables?: ExecutionArgs['variableValues'] & {
86
- country?: CountryCode;
87
- language?: LanguageCode;
88
- };
89
- headers?: HeadersInit;
90
- storefrontApiVersion?: string;
91
- };
92
- type StorefrontQueryOptions = StorefrontCommonOptions & {
93
- query: string;
94
- mutation?: never;
95
- cache?: CachingStrategy;
96
- };
97
- type StorefrontMutationOptions = StorefrontCommonOptions & {
98
- query?: never;
99
- mutation: string;
100
- cache?: never;
101
- };
102
165
  declare const isStorefrontApiError: (error: any) => boolean;
103
- declare function createStorefrontClient<TI18n extends I18nBase>({ storefrontHeaders, cache, waitUntil, buyerIp, i18n, requestGroupId, storefrontId, ...clientOptions }: CreateStorefrontClientOptions<TI18n>): StorefrontClient<TI18n>;
166
+ /**
167
+ * This function extends `createStorefrontClient` from [Hydrogen React](/docs/api/hydrogen-react/latest/utilities/createstorefrontclient). The additional arguments enable internationalization (i18n), caching, and other features particular to Remix and Oxygen.
168
+ *
169
+ * Learn more about [data fetching in Hydrogen](/docs/custom-storefronts/hydrogen/data-fetching/fetch-data).
170
+ */
171
+ declare function createStorefrontClient<TI18n extends I18nBase>(options: CreateStorefrontClientOptions<TI18n>): StorefrontClient<TI18n>;
104
172
 
173
+ /**
174
+ * The cache key is used to uniquely identify a value in the cache.
175
+ */
105
176
  type CacheKey = string | readonly unknown[];
106
177
 
178
+ type CreateWithCacheOptions = {
179
+ /** An instance that implements the [Cache API](https://developer.mozilla.org/en-US/docs/Web/API/Cache) */
180
+ cache: Cache;
181
+ /** The `waitUntil` function is used to keep the current request/response lifecycle alive even after a response has been sent. It should be provided by your platform. */
182
+ waitUntil: ExecutionContext['waitUntil'];
183
+ };
107
184
  /**
108
185
  * Creates a utility function that executes an asynchronous operation
109
186
  * like `fetch` and caches the result according to the strategy provided.
110
187
  * Use this to call any third-party APIs from loaders or actions.
111
188
  * By default, it uses the `CacheShort` strategy.
112
189
  *
113
- * Example:
114
- *
115
- * ```js
116
- * // In your app's `server.ts` file:
117
- * createRequestHandler({
118
- * /* ... *\/,
119
- * getLoadContext: () => ({ withCache: createWithCache_unstable({cache, waitUntil}) })
120
- * });
190
+ */
191
+ declare function createWithCache_unstable<T = unknown>(options: CreateWithCacheOptions): CreateWithCacheReturn<T>;
192
+ /**
193
+ * This is a caching async function. Whatever data is returned from the `actionFn` will be cached according to the strategy provided.
121
194
  *
122
- * // In your route loaders:
123
- * import {CacheShort} from '@shopify/hydrogen';
124
- * export async function loader ({context: {withCache}}) {
125
- * const data = await withCache('my-unique-key', CacheShort(), () => {
126
- * return fetch('https://example.com/api').then(res => res.json());
127
- * });
128
- * ```
195
+ * Use the `CachingStrategy` to define a custom caching mechanism for your data. Or use one of the built-in caching strategies: `CacheNone`, `CacheShort`, `CacheLong`.
129
196
  */
130
- declare function createWithCache_unstable({ cache, waitUntil, }: {
131
- cache: Cache;
132
- waitUntil: ExecutionContext['waitUntil'];
133
- }): <T = unknown>(cacheKey: CacheKey, strategy: CachingStrategy, actionFn: () => T | Promise<T>) => Promise<T>;
197
+ type CreateWithCacheReturn<T> = (cacheKey: CacheKey, strategy: CachingStrategy, actionFn: () => T | Promise<T>) => Promise<T>;
134
198
  type WithCache = ReturnType<typeof createWithCache_unstable>;
135
199
 
136
200
  /**
@@ -164,9 +228,10 @@ type StorefrontRedirect = {
164
228
  *
165
229
  * @see {@link https://help.shopify.com/en/manual/online-store/menus-and-links/url-redirect Creating URL redirects in Shopify}
166
230
  */
167
- declare function storefrontRedirect({ storefront, request, response, }: StorefrontRedirect): Promise<Response>;
231
+ declare function storefrontRedirect(options: StorefrontRedirect): Promise<Response>;
168
232
 
169
- declare function graphiqlLoader({ context }: LoaderArgs): Response;
233
+ type GraphiQLLoader = (args: LoaderArgs) => Promise<Response>;
234
+ declare const graphiqlLoader: GraphiQLLoader;
170
235
 
171
236
  interface SeoConfig<Schema extends Thing = Thing> {
172
237
  /**
@@ -442,10 +507,79 @@ interface SeoHandleFunction<Loader extends LoaderFunction | unknown = unknown, S
442
507
  }): Partial<SeoConfig<StructuredDataSchema>>;
443
508
  }
444
509
  interface SeoProps {
510
+ /** Enable debug mode that prints SEO properties for route in the console */
445
511
  debug?: boolean;
446
512
  }
447
513
  declare function Seo({ debug }: SeoProps): react.FunctionComponentElement<{
448
514
  children?: react.ReactNode;
449
515
  }>;
450
516
 
451
- export { CacheCustom, CacheLong, CacheNone, CacheShort, CreateStorefrontClientOptions, I18nBase, InMemoryCache, Seo, SeoConfig, SeoHandleFunction, Storefront, StorefrontClient, StorefrontMutationOptions, StorefrontQueryOptions, WithCache, createStorefrontClient, createWithCache_unstable, generateCacheControlHeader, graphiqlLoader, isStorefrontApiError, storefrontRedirect };
517
+ type Connection<NodesType> = {
518
+ nodes: Array<NodesType>;
519
+ pageInfo: PageInfo;
520
+ } | {
521
+ edges: {
522
+ node: Array<NodesType>;
523
+ };
524
+ pageInfo: PageInfo;
525
+ };
526
+ interface PaginationInfo<NodesType> {
527
+ /** The paginated array of nodes. You should map over and render this array. */
528
+ nodes: Array<NodesType>;
529
+ /** The `<NextLink>` is a helper component that makes it easy to navigate to the next page of paginated data. Alternatively you can build your own `<Link>` component: `<Link to={nextPageUrl} state={state} preventScrollReset />` */
530
+ NextLink: (props: Omit<LinkProps, 'to'>) => JSX.Element | null;
531
+ /** The `<PreviousLink>` is a helper component that makes it easy to navigate to the previous page of paginated data. Alternatively you can build your own `<Link>` component: `<Link to={previousPageUrl} state={state} preventScrollReset />` */
532
+ PreviousLink: (props: Omit<LinkProps, 'to'>) => JSX.Element | null;
533
+ /** The URL to the previous page of paginated data. Use this prop to build your own `<Link>` component. */
534
+ previousPageUrl: string;
535
+ /** The URL to the next page of paginated data. Use this prop to build your own `<Link>` component. */
536
+ nextPageUrl: string;
537
+ /** True if the cursor has next paginated data */
538
+ hasNextPage: boolean;
539
+ /** True if the cursor has previous paginated data */
540
+ hasPreviousPage: boolean;
541
+ /** True if we are in the process of fetching another page of data */
542
+ isLoading: boolean;
543
+ /** The `state` property is important to use when building your own `<Link>` component if you want paginated data to continuously append to the page. This means that every time the user clicks "Next page", the next page of data will be apppended inline with the previous page. If you want the whole page to re-render with only the next page results, do not pass the `state` prop to the Remix `<Link>` component. */
544
+ state: {
545
+ nodes: Array<NodesType>;
546
+ pageInfo: {
547
+ endCursor: Maybe$1<string> | undefined;
548
+ startCursor: Maybe$1<string> | undefined;
549
+ hasPreviousPage: boolean;
550
+ };
551
+ };
552
+ }
553
+ type PaginationProps<NodesType> = {
554
+ /** The response from `storefront.query` for a paginated request. Make sure the query is passed pagination variables and that the query has `pageInfo` with `hasPreviousPage`, `hasNextpage`, `startCursor`, and `endCursor` defined. */
555
+ connection: Connection<NodesType>;
556
+ /** A render prop that includes pagination data and helpers. */
557
+ children: PaginationRenderProp<NodesType>;
558
+ };
559
+ type PaginationRenderProp<NodesType> = (props: PaginationInfo<NodesType>) => JSX.Element | null;
560
+ /**
561
+ *
562
+ * The [Storefront API uses cursors](https://shopify.dev/docs/api/usage/pagination-graphql) to paginate through lists of data
563
+ * and the \`<Pagination />\` component makes it easy to paginate data from the Storefront API.
564
+ *
565
+ * @prop connection The response from `storefront.query` for a paginated request. Make sure the query is passed pagination variables and that the query has `pageInfo` with `hasPreviousPage`, `hasNextpage`, `startCursor`, and `endCursor` defined.
566
+ * @prop children A render prop that includes pagination data and helpers.
567
+ */
568
+ declare function Pagination<NodesType>({ connection, children, }: PaginationProps<NodesType>): JSX.Element | null;
569
+ /**
570
+ * @param request The request object passed to your Remix loader function.
571
+ * @param options Options for how to configure the pagination variables. Includes the ability to change how many nodes are within each page.
572
+ *
573
+ * @returns Variables to be used with the `storefront.query` function
574
+ */
575
+ declare function getPaginationVariables(request: Request, options?: {
576
+ pageBy: number;
577
+ }): {
578
+ last: number;
579
+ startCursor: string | null;
580
+ } | {
581
+ first: number;
582
+ endCursor: string | null;
583
+ };
584
+
585
+ export { CacheCustom, CacheLong, CacheNone, CacheShort, CreateStorefrontClientOptions, I18nBase, InMemoryCache, Pagination as Pagination__unstable, Seo, SeoConfig, SeoHandleFunction, Storefront, StorefrontClient, StorefrontMutations, StorefrontQueries, WithCache, createStorefrontClient, createWithCache_unstable, generateCacheControlHeader, getPaginationVariables as getPaginationVariables__unstable, graphiqlLoader, isStorefrontApiError, storefrontRedirect };
@@ -1,11 +1,11 @@
1
- import { createStorefrontClient, SHOPIFY_STOREFRONT_ID_HEADER, getShopifyCookies, SHOPIFY_Y, SHOPIFY_STOREFRONT_Y_HEADER, SHOPIFY_S, SHOPIFY_STOREFRONT_S_HEADER } from '@shopify/hydrogen-react';
2
- export { AnalyticsEventName, AnalyticsPageType, ExternalVideo, IMAGE_FRAGMENT, Image, MediaFile, ModelViewer, Money, ShopPayButton, ShopifySalesChannel, Video, flattenConnection, getClientBrowserParameters, getShopifyCookies, parseMetafield, sendShopifyAnalytics, storefrontApiCustomScalars, useMoney, useShopifyCookies } from '@shopify/hydrogen-react';
1
+ import { createStorefrontClient, SHOPIFY_STOREFRONT_ID_HEADER, getShopifyCookies, SHOPIFY_Y, SHOPIFY_STOREFRONT_Y_HEADER, SHOPIFY_S, SHOPIFY_STOREFRONT_S_HEADER, flattenConnection } from '@shopify/hydrogen-react';
2
+ export { AnalyticsEventName, AnalyticsPageType, ExternalVideo, IMAGE_FRAGMENT, Image, MediaFile, ModelViewer, Money, ShopPayButton, ShopifySalesChannel, Video, flattenConnection, getClientBrowserParameters, getShopifyCookies, parseGid, parseMetafield, sendShopifyAnalytics, storefrontApiCustomScalars, useMoney, useShopifyCookies } from '@shopify/hydrogen-react';
3
3
  import { redirect } from '@remix-run/server-runtime';
4
4
  import { lazy, useMemo, createElement, Suspense, Fragment } from 'react';
5
- import { useMatches, useLocation } from '@remix-run/react';
5
+ import { useMatches, useLocation, useNavigation, Link } from '@remix-run/react';
6
6
 
7
- function Y(e){let t=Array.isArray(e)?e:[e],n="";for(let r of t)r!=null&&(typeof r=="object"?!!r.body&&typeof r.body=="string"?n+=r.body:n+=JSON.stringify(r):n+=r);return n}var U="public",Te="private",xe="no-store",J={maxAge:"max-age",staleWhileRevalidate:"stale-while-revalidate",sMaxAge:"s-maxage",staleIfError:"stale-if-error"};function x(e){let t=[];return Object.keys(e).forEach(n=>{n==="mode"?t.push(e[n]):J[n]&&t.push(`${J[n]}=${e[n]}`);}),t.join(", ")}function _(){return {mode:xe}}function z(e){if(e?.mode&&e?.mode!==U&&e?.mode!==Te)throw Error("'mode' must be either 'public' or 'private'")}function g(e){return z(e),{mode:U,maxAge:1,staleWhileRevalidate:9,...e}}function H(e){return z(e),{mode:U,maxAge:3600,staleWhileRevalidate:82800,...e}}function j(e){return e}function R(e){return String(e).includes("__proto__")?JSON.parse(e,we):JSON.parse(e)}function we(e,t){if(e!=="__proto__")return t}function b(e,t){return e&&t?{...e,...t}:e||g()}function v(e){return x(b(e))}async function Re(e,t){if(!e)return;let n=await e.match(t);if(!n){t.url;return}return t.url,n}async function be(e,t,n,r){if(!e)return;let o=b(r);t.headers.set("cache-control",v(b(o,{maxAge:(o.maxAge||0)+(o.staleWhileRevalidate||0)})));let a=v(b(o));n.headers.set("cache-control",a),n.headers.set("real-cache-control",a),n.headers.set("cache-put-date",new Date().toUTCString()),t.url,await e.put(t,n);}async function Ee(e,t){!e||(t.url,await e.delete(t));}function Ae(e,t){let n=t.headers.get("cache-put-date"),r=t.headers.get("real-cache-control"),o=0;if(r){let i=r.match(/max-age=(\d*)/);i&&i.length>1&&(o=parseFloat(i[1]));}if(!n)return !1;let c=(new Date().valueOf()-new Date(n).valueOf())/1e3>o;return c&&(e.url,void 0),c}var E={get:Re,set:be,delete:Ee,generateDefaultCacheControlHeader:v,isStale:Ae};function D(e){return `https://shopify.dev/?${e}`}function Ie(e){return e||g()}async function X(e,t){if(!e)return;let n=D(t),r=new Request(n),o=await E.get(e,r);if(!o)return;let a=await o.text();try{return [R(a),o]}catch{return [a,o]}}async function N(e,t,n,r){if(!e)return;let o=D(t),a=new Request(o),s=new Response(JSON.stringify(n));await E.set(e,a,s,Ie(r));}function Z(e,t){return E.isStale(new Request(D(e)),t)}function ke(e,t){return [e,{status:t.status,statusText:t.statusText,headers:Array.from(t.headers.entries())}]}function ee([e,t]){return [e,new Response(e,t)]}var te=e=>!e?.errors,F=new Set;async function $(e,t,{strategy:n=g(),cacheInstance:r,shouldCacheResult:o=()=>!0,waitUntil:a}){if(!r||!n)return t();let s=Y([...typeof e=="string"?[e]:e]),c=await X(r,s);if(c){let[p,f]=c;if(!F.has(s)&&Z(s,f)){F.add(s);let d=Promise.resolve().then(async()=>{try{let h=await t();o(h)&&await N(r,s,h,n);}catch(h){h.message&&(h.message="SWR in sub-request failed: "+h.message),console.error(h);}finally{F.delete(s);}});a?.(d);}return p}let i=await t();if(o(i)){let p=N(r,s,i,n);a?.(p);}return i}async function re(e,t,{cacheInstance:n,cache:r,cacheKey:o=[e,t],shouldCacheResponse:a=()=>!0,waitUntil:s,returnType:c="json"}={}){return !r&&(!t.method||t.method==="GET")&&(r=g()),$(o,async()=>{let i=await fetch(e,t),p;try{p=await i[c]();}catch{p=await i.text();}return ke(p,i)},{cacheInstance:n,waitUntil:s,strategy:r??null,shouldCacheResult:i=>a(...ee(i))}).then(ee)}var ne="Custom-Storefront-Request-Group-ID",oe="Shopify-Storefront-Buyer-IP";function ae(){return typeof crypto<"u"&&!!crypto.randomUUID?crypto.randomUUID():`weak-${Math.random().toString(16).substring(2)}`}var se=new Set,W=e=>{se.has(e)||(console.warn(e),se.add(e));};var B="2023.4.0";var ue=class extends Error{},Ue=e=>e instanceof ue,_e=/(^|}\s)query[\s({]/im,He=/(^|}\s)mutation[\s({]/im;function pe(e){return e.replace(/\s*#.*$/gm,"").replace(/\s+/gm," ").trim()}var je={language:"EN",country:"US"};function Et({storefrontHeaders:e,cache:t,waitUntil:n,buyerIp:r,i18n:o,requestGroupId:a,storefrontId:s,...c}){t||W("Storefront API client created without a cache instance. This may slow down your sub-requests.");let{getPublicTokenHeaders:i,getPrivateTokenHeaders:p,getStorefrontApiUrl:f,getShopifyDomain:d}=createStorefrontClient(c),m=(c.privateStorefrontToken?p:i)({contentType:"json"});if(m[ne]=e?.requestGroupId||a||ae(),(e?.buyerIp||r)&&(m[oe]=e?.buyerIp||r||""),s&&(m[SHOPIFY_STOREFRONT_ID_HEADER]=s),(m["user-agent"]=`Hydrogen ${B}`),e&&e.cookie){let l=getShopifyCookies(e.cookie??"");l[SHOPIFY_Y]&&(m[SHOPIFY_STOREFRONT_Y_HEADER]=l[SHOPIFY_Y]),l[SHOPIFY_S]&&(m[SHOPIFY_STOREFRONT_S_HEADER]=l[SHOPIFY_S]);}e||W('"requestGroupId" and "buyerIp" will be deprecated in the next calendar release. Please use "getStorefrontHeaders"');async function C({query:l,mutation:S,variables:O,cache:ge,headers:T=[],storefrontApiVersion:de}){let me=T instanceof Headers?Object.fromEntries(T.entries()):Array.isArray(T)?Object.fromEntries(T):T;l=l??S;let P={...O};o&&(!O?.country&&/\$country/.test(l)&&(P.country=o.country),!O?.language&&/\$language/.test(l)&&(P.language=o.language));let ye=f({storefrontApiVersion:de}),Se={method:"POST",headers:{...m,...me},body:JSON.stringify({query:l,variables:P})},[M,L]=await re(ye,Se,{cacheInstance:S?void 0:t,cache:ge||g(),shouldCacheResponse:te,waitUntil:n});if(!L.ok){let q;try{q=R(M);}catch{q=[{message:M}];}le(L,q);}let{data:Ce,errors:V}=M;return V?.length&&le(L,V,ue),Ce}return {storefront:{query:(l,S)=>{if(l=pe(l),He.test(l))throw new Error("storefront.query cannot execute mutations");return C({...S,query:l})},mutate:(l,S)=>{if(l=pe(l),_e.test(l))throw new Error("storefront.mutate cannot execute queries");return C({...S,mutation:l})},cache:t,CacheNone:_,CacheLong:H,CacheShort:g,CacheCustom:j,generateCacheControlHeader:x,getPublicTokenHeaders:i,getPrivateTokenHeaders:p,getShopifyDomain:d,getApiUrl:f,isApiError:Ue,i18n:o??je}}}function le(e,t,n=Error){let r=e.headers.get("x-request-id"),o=r?` - Request ID: ${r}`:"";if(t){let a=typeof t=="string"?t:t.map(s=>s.message).join(`
8
- `);throw new n(a+o)}throw new n(`API response error: ${e.status}`+o)}function Ot({cache:e,waitUntil:t}){return (n,r,o)=>$(n,o,{strategy:r,cacheInstance:e,waitUntil:t})}var G=class{#e;constructor(){this.#e=new Map;}add(t){throw new Error("Method not implemented. Use `put` instead.")}addAll(t){throw new Error("Method not implemented. Use `put` instead.")}matchAll(t,n){throw new Error("Method not implemented. Use `match` instead.")}async put(t,n){if(t.method!=="GET")throw new TypeError("Cannot cache response to non-GET request.");if(n.status===206)throw new TypeError("Cannot cache response to a range request (206 Partial Content).");if(n.headers.get("vary")?.includes("*"))throw new TypeError("Cannot cache response with 'Vary: *' header.");this.#e.set(t.url,{body:new Uint8Array(await n.arrayBuffer()),status:n.status,headers:[...n.headers],timestamp:Date.now()});}async match(t){if(t.method!=="GET")return;let n=this.#e.get(t.url);if(!n)return;let{body:r,timestamp:o,...a}=n,s=new Headers(a.headers),c=s.get("cache-control")||s.get("real-cache-control")||"",i=parseInt(c.match(/max-age=(\d+)/)?.[1]||"0",10),p=parseInt(c.match(/stale-while-revalidate=(\d+)/)?.[1]||"0",10),f=(Date.now()-o)/1e3;if(f>i+p){this.#e.delete(t.url);return}let h=f>i;return s.set("cache",h?"STALE":"HIT"),s.set("date",new Date(o).toUTCString()),new Response(r,{status:a.status??200,headers:s})}async delete(t){return this.#e.has(t.url)?(this.#e.delete(t.url),!0):!1}keys(t){let n=[];for(let r of this.#e.keys())(!t||t.url===r)&&n.push(new Request(r));return Promise.resolve(n)}};async function De({storefront:e,request:t,response:n=new Response("Not Found",{status:404})}){let{pathname:r,search:o}=new URL(t.url),a=r+o;try{let{urlRedirects:s}=await e.query(Fe,{variables:{query:"path:"+a}}),c=s?.edges?.[0]?.node?.target;if(c)return new Response(null,{status:302,headers:{location:c}});let i=new URLSearchParams(o),p=i.get("return_to")||i.get("redirect");if(p){if(Ne(p))return redirect(p);console.warn(`Cross-domain redirects are not supported. Tried to redirect from ${a} to ${p}`);}}catch(s){console.error(`Failed to fetch redirects from Storefront API for route ${a}`,s);}return n}function Ne(e){try{new URL(e);}catch{return !0}return !1}var Fe=`#graphql
7
+ function z(e){let t=Array.isArray(e)?e:[e],n="";for(let r of t)r!=null&&(typeof r=="object"?!!r.body&&typeof r.body=="string"?n+=r.body:n+=JSON.stringify(r):n+=r);return n}var U="public",Pe="private",Re="no-store",Z={maxAge:"max-age",staleWhileRevalidate:"stale-while-revalidate",sMaxAge:"s-maxage",staleIfError:"stale-if-error"};function w(e){let t=[];return Object.keys(e).forEach(n=>{n==="mode"?t.push(e[n]):Z[n]&&t.push(`${Z[n]}=${e[n]}`);}),t.join(", ")}function H(){return {mode:Re}}function ee(e){if(e?.mode&&e?.mode!==U&&e?.mode!==Pe)throw Error("'mode' must be either 'public' or 'private'")}function y(e){return ee(e),{mode:U,maxAge:1,staleWhileRevalidate:9,...e}}function G(e){return ee(e),{mode:U,maxAge:3600,staleWhileRevalidate:82800,...e}}function j(e){return e}function R(e){return String(e).includes("__proto__")?JSON.parse(e,Ie):JSON.parse(e)}function Ie(e,t){if(e!=="__proto__")return t}function I(e,t){return e&&t?{...e,...t}:e||y()}function _(e){return w(I(e))}async function ke(e,t){if(!e)return;let n=await e.match(t);if(!n){t.url;return}return t.url,n}async function Ee(e,t,n,r){if(!e)return;let a=I(r);t.headers.set("cache-control",_(I(a,{maxAge:(a.maxAge||0)+(a.staleWhileRevalidate||0)})));let o=_(I(a));n.headers.set("cache-control",o),n.headers.set("real-cache-control",o),n.headers.set("cache-put-date",new Date().toUTCString()),t.url,await e.put(t,n);}async function Ae(e,t){!e||(t.url,await e.delete(t));}function Oe(e,t){let n=t.headers.get("cache-put-date"),r=t.headers.get("real-cache-control"),a=0;if(r){let c=r.match(/max-age=(\d*)/);c&&c.length>1&&(a=parseFloat(c[1]));}if(!n)return !1;let i=(new Date().valueOf()-new Date(n).valueOf())/1e3>a;return i&&(e.url,void 0),i}var k={get:ke,set:Ee,delete:Ae,generateDefaultCacheControlHeader:_,isStale:Oe};function V(e){return `https://shopify.dev/?${e}`}function Le(e){return e||y()}async function te(e,t){if(!e)return;let n=V(t),r=new Request(n),a=await k.get(e,r);if(!a)return;let o=await a.text();try{return [R(o),a]}catch{return [o,a]}}async function D(e,t,n,r){if(!e)return;let a=V(t),o=new Request(a),s=new Response(JSON.stringify(n));await k.set(e,o,s,Le(r));}function re(e,t){return k.isStale(new Request(V(e)),t)}function ve(e,t){return [e,{status:t.status,statusText:t.statusText,headers:Array.from(t.headers.entries())}]}function ne([e,t]){return [e,new Response(e,t)]}var oe=e=>!e?.errors,F=new Set;async function Q(e,t,{strategy:n=y(),cacheInstance:r,shouldCacheResult:a=()=>!0,waitUntil:o}){if(!r||!n)return t();let s=z([...typeof e=="string"?[e]:e]),i=await te(r,s);if(i){let[p,u]=i;if(!F.has(s)&&re(s,u)){F.add(s);let g=Promise.resolve().then(async()=>{try{let f=await t();a(f)&&await D(r,s,f,n);}catch(f){f.message&&(f.message="SWR in sub-request failed: "+f.message),console.error(f);}finally{F.delete(s);}});o?.(g);}return p}let c=await t();if(a(c)){let p=D(r,s,c,n);o?.(p);}return c}async function ae(e,t,{cacheInstance:n,cache:r,cacheKey:a=[e,t],shouldCacheResponse:o=()=>!0,waitUntil:s,returnType:i="json"}={}){return !r&&(!t.method||t.method==="GET")&&(r=y()),Q(a,async()=>{let c=await fetch(e,t),p;try{p=await c[i]();}catch{p=await c.text();}return ve(p,c)},{cacheInstance:n,waitUntil:s,strategy:r??null,shouldCacheResult:c=>o(...ne(c))}).then(ne)}var se="Custom-Storefront-Request-Group-ID";function ie(){return typeof crypto<"u"&&!!crypto.randomUUID?crypto.randomUUID():`weak-${Math.random().toString(16).substring(2)}`}var ce=new Set,$=e=>{ce.has(e)||(console.warn(e),ce.add(e));};var W="2023.4.2";var ge=class extends Error{},Ge=e=>e instanceof ge,je=/(^|}\s)query[\s({]/im,_e=/(^|}\s)mutation[\s({]/im;function le(e){return e.replace(/\s*#.*$/gm,"").replace(/\s+/gm," ").trim()}var Ve={language:"EN",country:"US"};function qt(e){let{storefrontHeaders:t,cache:n,waitUntil:r,buyerIp:a,i18n:o,requestGroupId:s,storefrontId:i,...c}=e;n||$("Storefront API client created without a cache instance. This may slow down your sub-requests.");let{getPublicTokenHeaders:p,getPrivateTokenHeaders:u,getStorefrontApiUrl:g,getShopifyDomain:f}=createStorefrontClient(c),h=(c.privateStorefrontToken?u:p)({contentType:"json",buyerIp:t?.buyerIp||a});if(h[se]=t?.requestGroupId||s||ie(),i&&(h[SHOPIFY_STOREFRONT_ID_HEADER]=i),(h["user-agent"]=`Hydrogen ${W}`),t&&t.cookie){let l=getShopifyCookies(t.cookie??"");l[SHOPIFY_Y]&&(h[SHOPIFY_STOREFRONT_Y_HEADER]=l[SHOPIFY_Y]),l[SHOPIFY_S]&&(h[SHOPIFY_STOREFRONT_S_HEADER]=l[SHOPIFY_S]);}t||$('"requestGroupId" and "buyerIp" will be deprecated in the next calendar release. Please use "getStorefrontHeaders"');async function m({query:l,mutation:x,variables:L,cache:Se,headers:b=[],storefrontApiVersion:Ce}){let Te=b instanceof Headers?Object.fromEntries(b.entries()):Array.isArray(b)?Object.fromEntries(b):b;l=l??x;let v={...L};o&&(!L?.country&&/\$country/.test(l)&&(v.country=o.country),!L?.language&&/\$language/.test(l)&&(v.language=o.language));let xe=g({storefrontApiVersion:Ce}),be={method:"POST",headers:{...h,...Te},body:JSON.stringify({query:l,variables:v})},[M,q]=await ae(xe,be,{cacheInstance:x?void 0:n,cache:Se||y(),shouldCacheResponse:oe,waitUntil:r});if(!q.ok){let N;try{N=R(M);}catch{N=[{message:M}];}fe(q,N);}let{data:we,errors:X}=M;return X?.length&&fe(q,X,ge),we}return {storefront:{query:(l,x)=>{if(l=le(l),_e.test(l))throw new Error("storefront.query cannot execute mutations");return m({...x,query:l})},mutate:(l,x)=>{if(l=le(l),je.test(l))throw new Error("storefront.mutate cannot execute queries");return m({...x,mutation:l})},cache:n,CacheNone:H,CacheLong:G,CacheShort:y,CacheCustom:j,generateCacheControlHeader:w,getPublicTokenHeaders:p,getPrivateTokenHeaders:u,getShopifyDomain:f,getApiUrl:g,isApiError:Ge,i18n:o??Ve}}}function fe(e,t,n=Error){let r=e.headers.get("x-request-id"),a=r?` - Request ID: ${r}`:"";if(t){let o=typeof t=="string"?t:t.map(s=>s.message).join(`
8
+ `);throw new n(o+a)}throw new n(`API response error: ${e.status}`+a)}function Gt(e){let{cache:t,waitUntil:n}=e;return function(a,o,s){return Q(a,s,{strategy:o,cacheInstance:t,waitUntil:n})}}var B=class{#e;constructor(){this.#e=new Map;}add(t){throw new Error("Method not implemented. Use `put` instead.")}addAll(t){throw new Error("Method not implemented. Use `put` instead.")}matchAll(t,n){throw new Error("Method not implemented. Use `match` instead.")}async put(t,n){if(t.method!=="GET")throw new TypeError("Cannot cache response to non-GET request.");if(n.status===206)throw new TypeError("Cannot cache response to a range request (206 Partial Content).");if(n.headers.get("vary")?.includes("*"))throw new TypeError("Cannot cache response with 'Vary: *' header.");this.#e.set(t.url,{body:new Uint8Array(await n.arrayBuffer()),status:n.status,headers:[...n.headers],timestamp:Date.now()});}async match(t){if(t.method!=="GET")return;let n=this.#e.get(t.url);if(!n)return;let{body:r,timestamp:a,...o}=n,s=new Headers(o.headers),i=s.get("cache-control")||s.get("real-cache-control")||"",c=parseInt(i.match(/max-age=(\d+)/)?.[1]||"0",10),p=parseInt(i.match(/stale-while-revalidate=(\d+)/)?.[1]||"0",10),u=(Date.now()-a)/1e3;if(u>c+p){this.#e.delete(t.url);return}let f=u>c;return s.set("cache",f?"STALE":"HIT"),s.set("date",new Date(a).toUTCString()),new Response(r,{status:o.status??200,headers:s})}async delete(t){return this.#e.has(t.url)?(this.#e.delete(t.url),!0):!1}keys(t){let n=[];for(let r of this.#e.keys())(!t||t.url===r)&&n.push(new Request(r));return Promise.resolve(n)}};async function Fe(e){let{storefront:t,request:n,response:r=new Response("Not Found",{status:404})}=e,{pathname:a,search:o}=new URL(n.url),s=a+o;try{let{urlRedirects:i}=await t.query($e,{variables:{query:"path:"+s}}),c=i?.edges?.[0]?.node?.target;if(c)return new Response(null,{status:302,headers:{location:c}});let p=new URLSearchParams(o),u=p.get("return_to")||p.get("redirect");if(u){if(Qe(u))return redirect(u);console.warn(`Cross-domain redirects are not supported. Tried to redirect from ${s} to ${u}`);}}catch(i){console.error(`Failed to fetch redirects from Storefront API for route ${s}`,i);}return r}function Qe(e){try{new URL(e);}catch{return !0}return !1}var $e=`#graphql
9
9
  query redirects($query: String) {
10
10
  urlRedirects(first: 1, query: $query) {
11
11
  edges {
@@ -15,7 +15,7 @@ function Y(e){let t=Array.isArray(e)?e:[e],n="";for(let r of t)r!=null&&(typeof
15
15
  }
16
16
  }
17
17
  }
18
- `;function $e({context:e}){let t=e?.storefront;if(!t)throw new Error("GraphiQL: Hydrogen's storefront client must be injected in the loader context.");let n=t.getApiUrl(),r=t.getPublicTokenHeaders()["X-Shopify-Storefront-Access-Token"];return new Response(`
18
+ `;var We=async function({context:t}){let n=t?.storefront;if(!n)throw new Error("GraphiQL: Hydrogen's storefront client must be injected in the loader context.");let r=n.getApiUrl(),a=n.getPublicTokenHeaders()["X-Shopify-Storefront-Access-Token"];return new Response(`
19
19
  <!DOCTYPE html>
20
20
  <html lang="en">
21
21
  <head>
@@ -56,9 +56,9 @@ function Y(e){let t=Array.isArray(e)?e:[e],n="";for(let r of t)r!=null&&(typeof
56
56
  ReactDOM.render(
57
57
  React.createElement(GraphiQL, {
58
58
  fetcher: GraphiQL.createFetcher({
59
- url: '${n}',
59
+ url: '${r}',
60
60
  headers: {
61
- 'X-Shopify-Storefront-Access-Token': '${r}',
61
+ 'X-Shopify-Storefront-Access-Token': '${a}',
62
62
  }
63
63
  }),
64
64
  defaultEditorToolsVisibility: true,
@@ -69,8 +69,8 @@ function Y(e){let t=Array.isArray(e)?e:[e],n="";for(let r of t)r!=null&&(typeof
69
69
  <\/script>
70
70
  </body>
71
71
  </html>
72
- `,{status:200,headers:{"content-type":"text/html"}})}var y="Error in SEO input: ",A={title:{validate:e=>{if(typeof e!="string")throw new Error(y.concat("`title` should be a string"));if(typeof e=="string"&&e.length>120)throw new Error(y.concat("`title` should not be longer than 120 characters"));return e}},description:{validate:e=>{if(typeof e!="string")throw new Error(y.concat("`description` should be a string"));if(typeof e=="string"&&e.length>155)throw new Error(y.concat("`description` should not be longer than 155 characters"));return e}},url:{validate:e=>{if(typeof e!="string")throw new Error(y.concat("`url` should be a string"));if(typeof e=="string"&&!e.startsWith("http"))throw new Error(y.concat("`url` should be a valid URL"));return e}},handle:{validate:e=>{if(typeof e!="string")throw new Error(y.concat("`handle` should be a string"));if(typeof e=="string"&&!e.startsWith("@"))throw new Error(y.concat("`handle` should start with `@`"));return e}}};function he(e){let t=[];for(let n of Object.keys(e))switch(n){case"title":{let r=I(A.title,e.title),o=We(e?.titleTemplate,r);if(!o)break;t.push(u("title",{title:o}),u("meta",{property:"og:title",content:o}),u("meta",{name:"twitter:title",content:o}));break}case"description":{let r=I(A.description,e.description);if(!r)break;t.push(u("meta",{name:"description",content:r}),u("meta",{property:"og:description",content:r}),u("meta",{name:"twitter:description",content:r}));break}case"url":{let r=I(A.url,e.url);if(!r)break;t.push(u("link",{rel:"canonical",href:r}),u("meta",{property:"og:url",content:r}));break}case"handle":{let r=I(A.handle,e.handle);if(!r)break;t.push(u("meta",{name:"twitter:site",content:r}),u("meta",{name:"twitter:creator",content:r}));break}case"media":{let r,o=Q(e.media);for(let a of o)if(typeof a=="string"&&t.push(u("meta",{name:"og:image",content:a})),a&&typeof a=="object"){let s=a.type||"image",c=a?{url:a?.url,secure_url:a?.url,type:Be(a.url),width:a?.width,height:a?.height,alt:a?.altText}:{};for(let i of Object.keys(c))c[i]&&(r=c[i],t.push(u("meta",{property:`og:${s}:${i}`,content:r},c.url)));}break}case"jsonLd":{let r=Q(e.jsonLd),o=0;for(let a of r){if(typeof a!="object")continue;let s=u("script",{type:"application/ld+json",children:JSON.stringify(a)},`json-ld-${a?.["@type"]||a?.name||o++}`);t.push(s);}break}case"alternates":{let r=Q(e.alternates);for(let o of r){if(!o)continue;let{language:a,url:s,default:c}=o,i=a?`${a}${c?"-default":""}`:void 0;t.push(u("link",{rel:"alternate",hrefLang:i,href:s}));}break}case"robots":{if(!e.robots)break;let{maxImagePreview:r,maxSnippet:o,maxVideoPreview:a,noArchive:s,noFollow:c,noImageIndex:i,noIndex:p,noSnippet:f,noTranslate:d,unavailableAfter:h}=e.robots,m=[s&&"noarchive",i&&"noimageindex",f&&"nosnippet",d&&"notranslate",r&&`max-image-preview:${r}`,o&&`max-snippet:${o}`,a&&`max-video-preview:${a}`,h&&`unavailable_after:${h}`],C=(p?"noindex":"index")+","+(c?"nofollow":"follow");for(let l of m)l&&(C+=`,${l}`);t.push(u("meta",{name:"robots",content:C}));break}}return t.flat().sort((n,r)=>n.key.localeCompare(r.key))}function u(e,t,n){let r={tag:e,props:{},key:""};return e==="title"?(r.children=t.title,r.key=K(r),r):e==="script"?(r.children=typeof t.children=="string"?t.children:"",r.key=K(r,n),delete t.children,r.props=t,r):(r.props=t,Object.keys(r.props).forEach(o=>!r.props[o]&&delete r.props[o]),r.key=K(r,n),r)}function K(e,t){let{tag:n,props:r}=e;if(n==="title")return "0-title";if(n==="meta"){let o=r.content===t&&typeof r.property=="string"&&!r.property.endsWith("secure_url")&&"0";return [n,...[t,o],r.property||r.name].filter(s=>s).join("-")}return n==="link"?[n,r.rel,r.hrefLang||r.media].filter(a=>a).join("-").replace(/\s+/g,"-"):n==="script"?`${n}-${t}`:`${n}-${r.type}`}function We(e,t){if(!!t)return e?typeof e=="function"?e(t):e.replace("%s",t??""):t}function Be(e){switch(e&&e.split(".").pop()){case"svg":return "image/svg+xml";case"png":return "image/png";case"gif":return "image/gif";case"swf":return "application/x-shockwave-flash";case"mp3":return "audio/mpeg";case"jpg":case"jpeg":default:return "image/jpeg"}}function Q(e){return Array.isArray(e)?e:[e]}function I(e,t){try{return e.validate(t)}catch(n){return console.warn(n.message),t}}var Je=lazy(()=>import('./log-seo-tags-N7J66FN6.js'));function ze({debug:e}){let t=useMatches(),n=useLocation(),r=useMemo(()=>t.flatMap(s=>{let{handle:c,...i}=s,p={...i,...n},f=c?.seo,d=i?.data?.seo;return !f&&!d?[]:f?k(c.seo,p):[d]}).reduce((s,c)=>{Object.keys(c).forEach(p=>!c[p]&&delete c[p]);let{jsonLd:i}=c;return i?s?.jsonLd?Array.isArray(i)?{...s,...c,jsonLd:[...s.jsonLd,...i]}:{...s,...c,jsonLd:[...s.jsonLd,i]}:{...s,...c,jsonLd:[i]}:{...s,...c}},{}),[t,n]),{html:o,loggerMarkup:a}=useMemo(()=>{let s=he(r),c=s.map(p=>p.tag==="script"?createElement(p.tag,{...p.props,key:p.key,dangerouslySetInnerHTML:{__html:p.children}}):createElement(p.tag,{...p.props,key:p.key},p.children)),i=createElement(Suspense,{fallback:null},createElement(Je,{headTags:s}));return {html:c,loggerMarkup:i}},[r]);return createElement(Fragment,null,o,e&&a)}function k(e,...t){if(e instanceof Function)return k(e(...t),...t);let n={};return Array.isArray(e)?(n=e.reduce((r,o)=>[...r,k(o)],[]),n):e instanceof Object?(Object.entries(e).forEach(([o,a])=>{n[o]=k(a,...t);}),n):e}
72
+ `,{status:200,headers:{"content-type":"text/html"}})};var S="Error in SEO input: ",E={title:{validate:e=>{if(typeof e!="string")throw new Error(S.concat("`title` should be a string"));if(typeof e=="string"&&e.length>120)throw new Error(S.concat("`title` should not be longer than 120 characters"));return e}},description:{validate:e=>{if(typeof e!="string")throw new Error(S.concat("`description` should be a string"));if(typeof e=="string"&&e.length>155)throw new Error(S.concat("`description` should not be longer than 155 characters"));return e}},url:{validate:e=>{if(typeof e!="string")throw new Error(S.concat("`url` should be a string"));if(typeof e=="string"&&!e.startsWith("http"))throw new Error(S.concat("`url` should be a valid URL"));return e}},handle:{validate:e=>{if(typeof e!="string")throw new Error(S.concat("`handle` should be a string"));if(typeof e=="string"&&!e.startsWith("@"))throw new Error(S.concat("`handle` should start with `@`"));return e}}};function de(e){let t=[];for(let n of Object.keys(e))switch(n){case"title":{let r=A(E.title,e.title),a=Be(e?.titleTemplate,r);if(!a)break;t.push(d("title",{title:a}),d("meta",{property:"og:title",content:a}),d("meta",{name:"twitter:title",content:a}));break}case"description":{let r=A(E.description,e.description);if(!r)break;t.push(d("meta",{name:"description",content:r}),d("meta",{property:"og:description",content:r}),d("meta",{name:"twitter:description",content:r}));break}case"url":{let r=A(E.url,e.url);if(!r)break;t.push(d("link",{rel:"canonical",href:r}),d("meta",{property:"og:url",content:r}));break}case"handle":{let r=A(E.handle,e.handle);if(!r)break;t.push(d("meta",{name:"twitter:site",content:r}),d("meta",{name:"twitter:creator",content:r}));break}case"media":{let r,a=J(e.media);for(let o of a)if(typeof o=="string"&&t.push(d("meta",{name:"og:image",content:o})),o&&typeof o=="object"){let s=o.type||"image",i=o?{url:o?.url,secure_url:o?.url,type:Ke(o.url),width:o?.width,height:o?.height,alt:o?.altText}:{};for(let c of Object.keys(i))i[c]&&(r=i[c],t.push(d("meta",{property:`og:${s}:${c}`,content:r},i.url)));}break}case"jsonLd":{let r=J(e.jsonLd),a=0;for(let o of r){if(typeof o!="object")continue;let s=d("script",{type:"application/ld+json",children:JSON.stringify(o)},`json-ld-${o?.["@type"]||o?.name||a++}`);t.push(s);}break}case"alternates":{let r=J(e.alternates);for(let a of r){if(!a)continue;let{language:o,url:s,default:i}=a,c=o?`${o}${i?"-default":""}`:void 0;t.push(d("link",{rel:"alternate",hrefLang:c,href:s}));}break}case"robots":{if(!e.robots)break;let{maxImagePreview:r,maxSnippet:a,maxVideoPreview:o,noArchive:s,noFollow:i,noImageIndex:c,noIndex:p,noSnippet:u,noTranslate:g,unavailableAfter:f}=e.robots,T=[s&&"noarchive",c&&"noimageindex",u&&"nosnippet",g&&"notranslate",r&&`max-image-preview:${r}`,a&&`max-snippet:${a}`,o&&`max-video-preview:${o}`,f&&`unavailable_after:${f}`],h=(p?"noindex":"index")+","+(i?"nofollow":"follow");for(let m of T)m&&(h+=`,${m}`);t.push(d("meta",{name:"robots",content:h}));break}}return t.flat().sort((n,r)=>n.key.localeCompare(r.key))}function d(e,t,n){let r={tag:e,props:{},key:""};return e==="title"?(r.children=t.title,r.key=K(r),r):e==="script"?(r.children=typeof t.children=="string"?t.children:"",r.key=K(r,n),delete t.children,r.props=t,r):(r.props=t,Object.keys(r.props).forEach(a=>!r.props[a]&&delete r.props[a]),r.key=K(r,n),r)}function K(e,t){let{tag:n,props:r}=e;if(n==="title")return "0-title";if(n==="meta"){let a=r.content===t&&typeof r.property=="string"&&!r.property.endsWith("secure_url")&&"0";return [n,...[t,a],r.property||r.name].filter(s=>s).join("-")}return n==="link"?[n,r.rel,r.hrefLang||r.media].filter(o=>o).join("-").replace(/\s+/g,"-"):n==="script"?`${n}-${t}`:`${n}-${r.type}`}function Be(e,t){if(!!t)return e?typeof e=="function"?e(t):e.replace("%s",t??""):t}function Ke(e){switch(e&&e.split(".").pop()){case"svg":return "image/svg+xml";case"png":return "image/png";case"gif":return "image/gif";case"swf":return "application/x-shockwave-flash";case"mp3":return "audio/mpeg";case"jpg":case"jpeg":default:return "image/jpeg"}}function J(e){return Array.isArray(e)?e:[e]}function A(e,t){try{return e.validate(t)}catch(n){return console.warn(n.message),t}}var et=lazy(()=>import('./log-seo-tags-N7J66FN6.js'));function tt({debug:e}){let t=useMatches(),n=useLocation(),r=useMemo(()=>t.flatMap(s=>{let{handle:i,...c}=s,p={...c,...n},u=i?.seo,g=c?.data?.seo;return !u&&!g?[]:u?O(i.seo,p):[g]}).reduce((s,i)=>{Object.keys(i).forEach(p=>!i[p]&&delete i[p]);let{jsonLd:c}=i;return c?s?.jsonLd?Array.isArray(c)?{...s,...i,jsonLd:[...s.jsonLd,...c]}:{...s,...i,jsonLd:[...s.jsonLd,c]}:{...s,...i,jsonLd:[c]}:{...s,...i}},{}),[t,n]),{html:a,loggerMarkup:o}=useMemo(()=>{let s=de(r),i=s.map(p=>p.tag==="script"?createElement(p.tag,{...p.props,key:p.key,dangerouslySetInnerHTML:{__html:p.children}}):createElement(p.tag,{...p.props,key:p.key},p.children)),c=createElement(Suspense,{fallback:null},createElement(et,{headTags:s}));return {html:i,loggerMarkup:c}},[r]);return createElement(Fragment,null,a,e&&o)}function O(e,...t){if(e instanceof Function)return O(e(...t),...t);let n={};return Array.isArray(e)?(n=e.reduce((r,a)=>[...r,O(a)],[]),n):e instanceof Object?(Object.entries(e).forEach(([a,o])=>{n[a]=O(o,...t);}),n):e}function ot({connection:e,children:t=()=>(console.warn("<Pagination> requires children to work properly"),null)}){let r=useNavigation().state==="loading",{endCursor:a,hasNextPage:o,hasPreviousPage:s,nextPageUrl:i,nodes:c,previousPageUrl:p,startCursor:u}=at(e),g=useMemo(()=>({pageInfo:{endCursor:a,hasPreviousPage:s,startCursor:u},nodes:c}),[a,s,u,c]),f=useMemo(()=>function(m){return o?createElement(Link,{preventScrollReset:!0,...m,to:i,state:g,replace:!0}):null},[o,i]),T=useMemo(()=>function(m){return s?createElement(Link,{preventScrollReset:!0,...m,to:p,state:g,replace:!0}):null},[s,p]);return t({state:g,hasNextPage:o,hasPreviousPage:s,isLoading:r,nextPageUrl:i,nodes:c,previousPageUrl:p,NextLink:f,PreviousLink:T})}function at(e){let{state:t,search:n}=useLocation(),o=new URLSearchParams(n).get("direction")==="previous",s=useMemo(()=>!t||!t?.nodes?flattenConnection(e):o?[...flattenConnection(e),...t.nodes]:[...t.nodes,...flattenConnection(e)],[t,e]),i=useMemo(()=>{let u=t?.pageInfo?.startCursor===void 0?e.pageInfo.startCursor:t.pageInfo.startCursor,g=t?.pageInfo?.endCursor===void 0?e.pageInfo.endCursor:t.pageInfo.endCursor;t?.nodes&&(o?u=e.pageInfo.startCursor:g=e.pageInfo.endCursor);let f=t?.pageInfo?.hasPreviousPage===void 0?e.pageInfo.hasPreviousPage:t.pageInfo.hasPreviousPage,T=t?.pageInfo?.hasNextPage===void 0?e.pageInfo.hasNextPage:t.pageInfo.hasNextPage;return {startCursor:u,endCursor:g,hasPreviousPage:f,hasNextPage:T}},[o,t,e.pageInfo.hasNextPage,e.pageInfo.hasPreviousPage,e.pageInfo.startCursor,e.pageInfo.endCursor]),c=useMemo(()=>{let u=new URLSearchParams(n);return u.set("direction","previous"),i.startCursor&&u.set("cursor",i.startCursor),`?${u.toString()}`},[n,i.startCursor]),p=useMemo(()=>{let u=new URLSearchParams(n);return u.set("direction","next"),i.endCursor&&u.set("cursor",i.endCursor),`?${u.toString()}`},[n,i.endCursor]);return {...i,previousPageUrl:c,nextPageUrl:p,nodes:s}}function st(e,t={pageBy:20}){if(!(e instanceof Request))throw new Error("getPaginationVariables must be called with the Request object passed to your loader function");let{pageBy:n}=t,r=new URLSearchParams(new URL(e.url).search),a=r.get("cursor")??void 0;return (r.get("direction")==="previous"?"previous":"next")==="previous"?{last:n,startCursor:a??null}:{first:n,endCursor:a??null}}
73
73
 
74
- export { j as CacheCustom, H as CacheLong, _ as CacheNone, g as CacheShort, G as InMemoryCache, ze as Seo, Et as createStorefrontClient, Ot as createWithCache_unstable, x as generateCacheControlHeader, $e as graphiqlLoader, Ue as isStorefrontApiError, De as storefrontRedirect };
74
+ export { j as CacheCustom, G as CacheLong, H as CacheNone, y as CacheShort, B as InMemoryCache, ot as Pagination__unstable, tt as Seo, qt as createStorefrontClient, Gt as createWithCache_unstable, w as generateCacheControlHeader, st as getPaginationVariables__unstable, We as graphiqlLoader, Ge as isStorefrontApiError, Fe as storefrontRedirect };
75
75
  //# sourceMappingURL=out.js.map
76
76
  //# sourceMappingURL=index.js.map