From dc2ad3e6b8e53ac35f5e1e8e8d78aebe2d9a242a Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 6 Nov 2023 17:50:20 +0700 Subject: [PATCH] sync v2 --- README.md | 6 +- app/components/CountrySelector.tsx | 5 +- app/components/FeaturedProducts.tsx | 8 +- app/components/Layout.tsx | 15 +- app/components/Link.tsx | 6 +- app/data/queries.ts | 5 +- app/hooks/useCartFetchers.tsx | 5 +- app/hooks/usePageAnalytics.tsx | 6 +- app/lib/utils.ts | 9 +- app/root.tsx | 17 ++- ...le).$shopid.orders.$token.authenticate.tsx | 4 +- ....account.activate.$id.$activationToken.tsx | 4 +- app/routes/($locale).account.login.tsx | 8 +- app/routes/($locale).account.logout.ts | 8 +- app/routes/($locale).account.orders.$id.tsx | 8 +- app/routes/($locale).account.recover.tsx | 8 +- app/routes/($locale).account.register.tsx | 8 +- ...$locale).account.reset.$id.$resetToken.tsx | 4 +- app/routes/($locale).account.tsx | 11 +- app/routes/($locale).api.products.tsx | 6 +- ...cale).blogs.$blogHandle.$articleHandle.tsx | 2 +- .../($locale).blogs.$blogHandle._index.tsx | 2 +- app/routes/($locale).cart.$lines.tsx | 4 +- app/routes/($locale).cart.tsx | 17 ++- ...$locale).collections.$collectionHandle.tsx | 2 +- app/routes/($locale).collections._index.tsx | 5 +- app/routes/($locale).collections.all.tsx | 5 +- app/routes/($locale).discount.$code.tsx | 13 +- app/routes/($locale).featured-products.tsx | 6 +- app/routes/($locale).pages.$pageHandle.tsx | 6 +- .../($locale).policies.$policyHandle.tsx | 4 +- app/routes/($locale).policies._index.tsx | 4 +- .../($locale).products.$productHandle.tsx | 9 +- app/routes/($locale).products._index.tsx | 5 +- app/routes/($locale).search.tsx | 6 +- app/routes/[robots.txt].tsx | 4 +- app/routes/[sitemap.xml].tsx | 4 +- package.json | 20 +-- remix.config.js | 16 +-- storefrontapi.generated.d.ts | 132 ++++++++++-------- 40 files changed, 228 insertions(+), 189 deletions(-) diff --git a/README.md b/README.md index 378af33..c61e4fb 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@

- Version + Version License: MIT @@ -46,7 +46,7 @@ Follow these steps to get started with Pilot and begin crafting your Hydrogen-dr 1. Install [Weaverse Hydrogen Customizer](https://apps.shopify.com/weaverse) from Shopify App Store. 2. Create new Hydrogen storefront inside Weaverse. 3. Initialize the project and start a local dev server with `@weaverse/cli` tool as instructed in the Weaverse editor. - ![Init Weaverse Storefront](https://cdn.shopify.com/s/files/1/0693/8201/3220/files/init-project_4882deaa-c661-47cc-a7bf-38b2704e6a0b.png?v=1695816089) + ![Init Weaverse Storefront](https://cdn.shopify.com/s/files/1/0838/0052/3057/files/New_storefront.png?v=1699244454) 4. Open the Weaverse editor to start customizing and tailoring your storefront according to your preferences. ## Features overview @@ -270,7 +270,7 @@ And then you can use the data in your component with `Component.props.loaderData Weaverse provides a convenient way to customize your theme inside the **Weaverse editor**. You can add new sections, customize existing ones, and change the theme settings. -![Weaverse Editor](https://cdn.shopify.com/s/files/1/0693/8201/3220/files/Live_demo_-_Weaverse_Hydrogen_2023-09-27_18-58-23.png?v=1695826457) +![Weaverse Editor](https://cdn.shopify.com/s/files/1/0838/0052/3057/files/playground.jpg?v=1699244445) ## References diff --git a/app/components/CountrySelector.tsx b/app/components/CountrySelector.tsx index 9666a1c..2d4ceef 100644 --- a/app/components/CountrySelector.tsx +++ b/app/components/CountrySelector.tsx @@ -8,12 +8,13 @@ import {CartForm} from '@shopify/hydrogen'; import {Heading, Button, IconCheck} from '~/components'; import type {Localizations, Locale} from '~/lib/type'; import {DEFAULT_LOCALE} from '~/lib/utils'; +import {useRootLoaderData} from '~/root'; export function CountrySelector() { - const [root] = useMatches(); const fetcher = useFetcher(); const closeRef = useRef(null); - const selectedLocale = root.data?.selectedLocale ?? DEFAULT_LOCALE; + const rootData = useRootLoaderData(); + const selectedLocale = rootData?.selectedLocale ?? DEFAULT_LOCALE; const {pathname, search} = useLocation(); const pathWithoutLocale = `${pathname.replace( selectedLocale.pathPrefix, diff --git a/app/components/FeaturedProducts.tsx b/app/components/FeaturedProducts.tsx index da72355..b45bcd1 100644 --- a/app/components/FeaturedProducts.tsx +++ b/app/components/FeaturedProducts.tsx @@ -26,8 +26,8 @@ interface FeaturedProductsProps { * @param query a filtering query * @param reverse wether to reverse the product results * @param sortKey Sort the underlying list by the given key. - * @see query https://shopify.dev/api/storefront/2023-07/queries/products - * @see filters https://shopify.dev/api/storefront/2023-07/queries/products#argument-products-query + * @see query https://shopify.dev/api/storefront/current/queries/products + * @see filters https://shopify.dev/api/storefront/current/queries/products#argument-products-query */ export function FeaturedProducts({ count = 4, @@ -38,7 +38,7 @@ export function FeaturedProducts({ reverse, sortKey = 'BEST_SELLING', }: FeaturedProductsProps) { - const {load, data} = useFetcher(); + const {load, data} = useFetcher<{products: Product[]}>(); const queryString = useMemo( () => Object.entries({count, sortKey, query, reverse}) @@ -69,7 +69,7 @@ export function FeaturedProducts({

diff --git a/app/components/Layout.tsx b/app/components/Layout.tsx index d98ba69..714de6a 100644 --- a/app/components/Layout.tsx +++ b/app/components/Layout.tsx @@ -1,4 +1,4 @@ -import {useParams, Form, Await, useMatches} from '@remix-run/react'; +import {useParams, Form, Await} from '@remix-run/react'; import {useWindowScroll} from 'react-use'; import {Disclosure} from '@headlessui/react'; import {Suspense, useEffect, useMemo} from 'react'; @@ -32,6 +32,7 @@ import {useIsHydrated} from '~/hooks/useIsHydrated'; import {useCartFetchers} from '~/hooks/useCartFetchers'; import {Logo} from './Logo'; import clsx from 'clsx'; +import {useRootLoaderData} from '~/root'; type LayoutProps = { children: React.ReactNode; @@ -107,13 +108,13 @@ function Header({title, menu}: {title: string; menu?: EnhancedMenu}) { } function CartDrawer({isOpen, onClose}: {isOpen: boolean; onClose: () => void}) { - const [root] = useMatches(); + const rootData = useRootLoaderData(); return (
}> - + {(cart) => } @@ -295,8 +296,8 @@ function DesktopHeader({ } function AccountLink({className}: {className?: string}) { - const [root] = useMatches(); - const isLoggedIn = root.data?.isLoggedIn; + const rootData = useRootLoaderData(); + const isLoggedIn = rootData?.isLoggedIn; return isLoggedIn ? ( @@ -315,11 +316,11 @@ function CartCount({ isHome: boolean; openCart: () => void; }) { - const [root] = useMatches(); + const rootData = useRootLoaderData(); return ( }> - + {(cart) => ( & { className?: RemixNavLinkProps['className'] | RemixLinkProps['className']; @@ -27,8 +27,8 @@ type LinkProps = Omit & { */ export function Link(props: LinkProps) { const {to, className, ...resOfProps} = props; - const [root] = useMatches(); - const selectedLocale = root.data?.selectedLocale; + const rootData = useRootLoaderData(); + const selectedLocale = rootData?.selectedLocale; let toWithLocale = to; diff --git a/app/data/queries.ts b/app/data/queries.ts index e840683..724049b 100644 --- a/app/data/queries.ts +++ b/app/data/queries.ts @@ -29,7 +29,7 @@ export let HOMEPAGE_SEO_QUERY = `#graphql ${COLLECTION_CONTENT_FRAGMENT} ` as const; -// @see: https://shopify.dev/api/storefront/2023-04/queries/products +// @see: https://shopify.dev/api/storefront/current/queries/products export let HOMEPAGE_FEATURED_PRODUCTS_QUERY = `#graphql query homepageFeaturedProducts($country: CountryCode, $language: LanguageCode) @inContext(country: $country, language: $language) { @@ -42,7 +42,7 @@ export let HOMEPAGE_FEATURED_PRODUCTS_QUERY = `#graphql ${PRODUCT_CARD_FRAGMENT} `; -// @see: https://shopify.dev/api/storefront/2023-04/queries/collections +// @see: https://shopify.dev/api/storefront/current/queries/collections export let FEATURED_COLLECTIONS_QUERY = `#graphql query homepageFeaturedCollections($country: CountryCode, $language: LanguageCode) @inContext(country: $country, language: $language) { @@ -235,7 +235,6 @@ export let COLLECTION_QUERY = `#graphql pageInfo { hasPreviousPage hasNextPage - hasNextPage endCursor startCursor } diff --git a/app/hooks/useCartFetchers.tsx b/app/hooks/useCartFetchers.tsx index 9590a4f..019ed54 100644 --- a/app/hooks/useCartFetchers.tsx +++ b/app/hooks/useCartFetchers.tsx @@ -6,9 +6,8 @@ export function useCartFetchers(actionName: string) { const cartFetchers = []; for (const fetcher of fetchers) { - const formData = fetcher.submission?.formData; - if (formData) { - const formInputs = CartForm.getFormInput(formData); + if (fetcher.formData) { + const formInputs = CartForm.getFormInput(fetcher.formData); if (formInputs.action === actionName) { cartFetchers.push(fetcher); } diff --git a/app/hooks/usePageAnalytics.tsx b/app/hooks/usePageAnalytics.tsx index 54cf51c..80c8078 100644 --- a/app/hooks/usePageAnalytics.tsx +++ b/app/hooks/usePageAnalytics.tsx @@ -11,11 +11,13 @@ export function usePageAnalytics({hasUserConsent}: {hasUserConsent: boolean}) { const data: Record = {}; matches.forEach((event) => { - const eventData = event?.data; + const eventData = event?.data as Record; if (eventData) { eventData['analytics'] && Object.assign(data, eventData['analytics']); - const selectedLocale = eventData['selectedLocale'] || DEFAULT_LOCALE; + const selectedLocale = + (eventData['selectedLocale'] as typeof DEFAULT_LOCALE) || + DEFAULT_LOCALE; Object.assign(data, { currency: selectedLocale.currency, acceptedLanguage: selectedLocale.language, diff --git a/app/lib/utils.ts b/app/lib/utils.ts index 7c60dc6..d57501b 100644 --- a/app/lib/utils.ts +++ b/app/lib/utils.ts @@ -8,6 +8,7 @@ import type { ParentMenuItemFragment, } from 'storefrontapi.generated'; import {countries} from '~/data/countries'; +import {useRootLoaderData} from '~/root'; import type {I18nLocale} from './type'; @@ -296,8 +297,8 @@ export function getLocaleFromRequest(request: Request): I18nLocale { } export function usePrefixPathWithLocale(path: string) { - const [root] = useMatches(); - const selectedLocale = root.data?.selectedLocale ?? DEFAULT_LOCALE; + const rootData = useRootLoaderData(); + const selectedLocale = rootData?.selectedLocale ?? DEFAULT_LOCALE; return `${selectedLocale.pathPrefix}${ path.startsWith('/') ? path : '/' + path @@ -306,8 +307,8 @@ export function usePrefixPathWithLocale(path: string) { export function useIsHomePath() { const {pathname} = useLocation(); - const [root] = useMatches(); - const selectedLocale = root.data?.selectedLocale ?? DEFAULT_LOCALE; + const rootData = useRootLoaderData(); + const selectedLocale = rootData?.selectedLocale ?? DEFAULT_LOCALE; const strippedPathname = pathname.replace(selectedLocale.pathPrefix, ''); return strippedPathname === '/'; } diff --git a/app/root.tsx b/app/root.tsx index 228e005..a541cbb 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -1,8 +1,8 @@ import { defer, - type LinksFunction, - type LoaderArgs, + type LoaderFunctionArgs, type AppLoadContext, + type SerializeFrom, } from '@shopify/remix-oxygen'; import { isRouteErrorResponse, @@ -67,7 +67,12 @@ export const links: LinksFunction = () => { ]; }; -export async function loader({request, context}: LoaderArgs) { +export const useRootLoaderData = () => { + const [root] = useMatches(); + return root?.data as SerializeFrom; +}; + +export async function loader({request, context}: LoaderFunctionArgs) { const {session, storefront, cart} = context; const [customerAccessToken, layout] = await Promise.all([ session.get('customerAccessToken'), @@ -127,9 +132,9 @@ export default withWeaverse(App); const ErrorBoundaryComponent = ({error}: {error: Error}) => { const nonce = useNonce(); - const [root] = useMatches(); - const locale = root?.data?.selectedLocale ?? DEFAULT_LOCALE; const routeError = useRouteError(); + const rootData = useRootLoaderData(); + const locale = rootData?.selectedLocale ?? DEFAULT_LOCALE; const isRouteError = isRouteErrorResponse(routeError); let title = 'Error'; @@ -151,7 +156,7 @@ const ErrorBoundaryComponent = ({error}: {error: Error}) => { {isRouteError ? ( diff --git a/app/routes/($locale).$shopid.orders.$token.authenticate.tsx b/app/routes/($locale).$shopid.orders.$token.authenticate.tsx index 035c5e4..d039484 100644 --- a/app/routes/($locale).$shopid.orders.$token.authenticate.tsx +++ b/app/routes/($locale).$shopid.orders.$token.authenticate.tsx @@ -1,4 +1,4 @@ -import {redirect, type LoaderArgs} from '@shopify/remix-oxygen'; +import {redirect, type LoaderFunctionArgs} from '@shopify/remix-oxygen'; import invariant from 'tiny-invariant'; import {Button, PageHeader} from '~/components'; @@ -10,7 +10,7 @@ import {Button, PageHeader} from '~/components'; that are routing to your Hydrogen storefront. To prevent this, ensure that you redirect those requests back to Shopify. */ -export async function loader({request, context: {storefront}}: LoaderArgs) { +export async function loader({request, context: {storefront}}: LoaderFunctionArgs) { const {origin} = new URL(request.url); const {shop} = await storefront.query( `#graphql diff --git a/app/routes/($locale).account.activate.$id.$activationToken.tsx b/app/routes/($locale).account.activate.$id.$activationToken.tsx index 5e8299d..018b0e9 100644 --- a/app/routes/($locale).account.activate.$id.$activationToken.tsx +++ b/app/routes/($locale).account.activate.$id.$activationToken.tsx @@ -1,5 +1,5 @@ import {json, redirect, type ActionFunction} from '@shopify/remix-oxygen'; -import {Form, useActionData, type V2_MetaFunction} from '@remix-run/react'; +import {Form, useActionData, type MetaFunction} from '@remix-run/react'; import {useRef, useState} from 'react'; import {getInputStyleClasses} from '~/lib/utils'; @@ -93,7 +93,7 @@ export const action: ActionFunction = async ({ } }; -export const meta: V2_MetaFunction = () => { +export const meta: MetaFunction = () => { return [{title: 'Activate Account'}]; }; diff --git a/app/routes/($locale).account.login.tsx b/app/routes/($locale).account.login.tsx index fe9849b..1a2ca9d 100644 --- a/app/routes/($locale).account.login.tsx +++ b/app/routes/($locale).account.login.tsx @@ -3,13 +3,13 @@ import { redirect, type ActionFunction, type AppLoadContext, - type LoaderArgs, + type LoaderFunctionArgs, } from '@shopify/remix-oxygen'; import { Form, useActionData, useLoaderData, - type V2_MetaFunction, + type MetaFunction, } from '@remix-run/react'; import {MouseEvent, useState} from 'react'; @@ -20,7 +20,7 @@ export const handle = { isPublic: true, }; -export async function loader({context, params}: LoaderArgs) { +export async function loader({context, params}: LoaderFunctionArgs) { const customerAccessToken = await context.session.get('customerAccessToken'); if (customerAccessToken) { @@ -89,7 +89,7 @@ export const action: ActionFunction = async ({request, context, params}) => { } }; -export const meta: V2_MetaFunction = () => { +export const meta: MetaFunction = () => { return [{title: 'Login'}]; }; diff --git a/app/routes/($locale).account.logout.ts b/app/routes/($locale).account.logout.ts index 69f2c5d..414de9b 100644 --- a/app/routes/($locale).account.logout.ts +++ b/app/routes/($locale).account.logout.ts @@ -2,8 +2,8 @@ import { redirect, type ActionFunction, type AppLoadContext, - type LoaderArgs, - type ActionArgs, + type LoaderFunctionArgs, + type ActionFunctionArgs, } from '@shopify/remix-oxygen'; export async function doLogout(context: AppLoadContext) { @@ -18,10 +18,10 @@ export async function doLogout(context: AppLoadContext) { }); } -export async function loader({context}: LoaderArgs) { +export async function loader({context}: LoaderFunctionArgs) { return redirect(context.storefront.i18n.pathPrefix); } -export const action: ActionFunction = async ({context}: ActionArgs) => { +export const action: ActionFunction = async ({context}: ActionFunctionArgs) => { return doLogout(context); }; diff --git a/app/routes/($locale).account.orders.$id.tsx b/app/routes/($locale).account.orders.$id.tsx index e28fda4..441fa4e 100644 --- a/app/routes/($locale).account.orders.$id.tsx +++ b/app/routes/($locale).account.orders.$id.tsx @@ -1,17 +1,17 @@ import invariant from 'tiny-invariant'; import clsx from 'clsx'; -import {json, redirect, type LoaderArgs} from '@shopify/remix-oxygen'; -import {useLoaderData, type V2_MetaFunction} from '@remix-run/react'; +import {json, redirect, type LoaderFunctionArgs} from '@shopify/remix-oxygen'; +import {useLoaderData, type MetaFunction} from '@remix-run/react'; import {Money, Image, flattenConnection} from '@shopify/hydrogen'; import {statusMessage} from '~/lib/utils'; import {Link, Heading, PageHeader, Text} from '~/components'; -export const meta: V2_MetaFunction = ({data}) => { +export const meta: MetaFunction = ({data}) => { return [{title: `Order ${data?.order?.name}`}]; }; -export async function loader({request, context, params}: LoaderArgs) { +export async function loader({request, context, params}: LoaderFunctionArgs) { if (!params.id) { return redirect(params?.locale ? `${params.locale}/account` : '/account'); } diff --git a/app/routes/($locale).account.recover.tsx b/app/routes/($locale).account.recover.tsx index f5d0e56..685ca07 100644 --- a/app/routes/($locale).account.recover.tsx +++ b/app/routes/($locale).account.recover.tsx @@ -2,14 +2,14 @@ import { json, redirect, type ActionFunction, - type LoaderArgs, + type LoaderFunctionArgs, } from '@shopify/remix-oxygen'; -import {Form, useActionData, type V2_MetaFunction} from '@remix-run/react'; +import {Form, useActionData, type MetaFunction} from '@remix-run/react'; import {useState, type MouseEvent} from 'react'; import {Button, Input, Link} from '~/components'; -export async function loader({context, params}: LoaderArgs) { +export async function loader({context, params}: LoaderFunctionArgs) { const customerAccessToken = await context.session.get('customerAccessToken'); if (customerAccessToken) { @@ -49,7 +49,7 @@ export const action: ActionFunction = async ({request, context}) => { } }; -export const meta: V2_MetaFunction = () => { +export const meta: MetaFunction = () => { return [{title: 'Recover Password'}]; }; diff --git a/app/routes/($locale).account.register.tsx b/app/routes/($locale).account.register.tsx index d8754d0..3a479b4 100644 --- a/app/routes/($locale).account.register.tsx +++ b/app/routes/($locale).account.register.tsx @@ -2,9 +2,9 @@ import { redirect, json, type ActionFunction, - type LoaderArgs, + type LoaderFunctionArgs, } from '@shopify/remix-oxygen'; -import {Form, useActionData, type V2_MetaFunction} from '@remix-run/react'; +import {Form, useActionData, type MetaFunction} from '@remix-run/react'; import {useState, type MouseEvent} from 'react'; import {getInputStyleClasses} from '~/lib/utils'; @@ -12,7 +12,7 @@ import {Button, Input, Link} from '~/components'; import {doLogin} from './($locale).account.login'; -export async function loader({context, params}: LoaderArgs) { +export async function loader({context, params}: LoaderFunctionArgs) { const customerAccessToken = await context.session.get('customerAccessToken'); if (customerAccessToken) { @@ -86,7 +86,7 @@ export const action: ActionFunction = async ({request, context, params}) => { } }; -export const meta: V2_MetaFunction = () => { +export const meta: MetaFunction = () => { return [{title: 'Register'}]; }; diff --git a/app/routes/($locale).account.reset.$id.$resetToken.tsx b/app/routes/($locale).account.reset.$id.$resetToken.tsx index d3bee49..a16ef41 100644 --- a/app/routes/($locale).account.reset.$id.$resetToken.tsx +++ b/app/routes/($locale).account.reset.$id.$resetToken.tsx @@ -1,5 +1,5 @@ import {json, redirect, type ActionFunction} from '@shopify/remix-oxygen'; -import {Form, useActionData, type V2_MetaFunction} from '@remix-run/react'; +import {Form, useActionData, type MetaFunction} from '@remix-run/react'; import {useRef, useState} from 'react'; import {getInputStyleClasses} from '~/lib/utils'; @@ -89,7 +89,7 @@ export const action: ActionFunction = async ({ } }; -export const meta: V2_MetaFunction = () => { +export const meta: MetaFunction = () => { return [{title: 'Reset Password'}]; }; diff --git a/app/routes/($locale).account.tsx b/app/routes/($locale).account.tsx index 406ec0f..917846b 100644 --- a/app/routes/($locale).account.tsx +++ b/app/routes/($locale).account.tsx @@ -11,7 +11,7 @@ import { json, defer, redirect, - type LoaderArgs, + type LoaderFunctionArgs, type AppLoadContext, } from '@shopify/remix-oxygen'; import {flattenConnection} from '@shopify/hydrogen'; @@ -42,13 +42,13 @@ import { import {doLogout} from './($locale).account.logout'; import {Container} from '~/components/Container'; -// Combining json + Response + defer in a loader breaks the +// Combining json + defer in a loader breaks the // types returned by useLoaderData. This is a temporary fix. type TmpRemixFix = ReturnType>; export const headers = routeHeaders; -export async function loader({request, context, params}: LoaderArgs) { +export async function loader({request, context, params}: LoaderFunctionArgs) { const {pathname} = new URL(request.url); const locale = params.locale; const customerAccessToken = await context.session.get('customerAccessToken'); @@ -58,7 +58,7 @@ export async function loader({request, context, params}: LoaderArgs) { if (!isAuthenticated) { if (isAccountPage) { - return redirect(loginPath) as unknown as TmpRemixFix; + throw redirect(loginPath); } // pass through to public routes return json({isAuthenticated: false}) as unknown as TmpRemixFix; @@ -94,7 +94,8 @@ export default function Authenticated() { // routes that export handle { renderInModal: true } const renderOutletInModal = matches.some((match) => { - return match?.handle?.renderInModal; + const handle = match?.handle as {renderInModal?: boolean}; + return handle?.renderInModal; }); // Public routes diff --git a/app/routes/($locale).api.products.tsx b/app/routes/($locale).api.products.tsx index c27ad7b..2ba6c53 100644 --- a/app/routes/($locale).api.products.tsx +++ b/app/routes/($locale).api.products.tsx @@ -1,4 +1,4 @@ -import {json, type LoaderArgs} from '@shopify/remix-oxygen'; +import {json, type LoaderFunctionArgs} from '@shopify/remix-oxygen'; import type {ProductSortKeys} from '@shopify/hydrogen/storefront-api-types'; import {flattenConnection} from '@shopify/hydrogen'; import invariant from 'tiny-invariant'; @@ -12,9 +12,9 @@ import {PRODUCT_CARD_FRAGMENT} from '~/data/fragments'; * @param reverse * @param sortKey * @returns Product[] - * @see https://shopify.dev/api/storefront/2023-07/queries/products + * @see https://shopify.dev/api/storefront/current/queries/products */ -export async function loader({request, context: {storefront}}: LoaderArgs) { +export async function loader({request, context: {storefront}}: LoaderFunctionArgs) { const url = new URL(request.url); const searchParams = new URLSearchParams(url.search); diff --git a/app/routes/($locale).blogs.$blogHandle.$articleHandle.tsx b/app/routes/($locale).blogs.$blogHandle.$articleHandle.tsx index b528627..0de0472 100644 --- a/app/routes/($locale).blogs.$blogHandle.$articleHandle.tsx +++ b/app/routes/($locale).blogs.$blogHandle.$articleHandle.tsx @@ -1,5 +1,5 @@ import {json, type LinksFunction} from '@shopify/remix-oxygen'; -import {RouteLoaderArgs} from '@weaverse/hydrogen'; +import {type RouteLoaderArgs} from '@weaverse/hydrogen'; import {ArticleDetailsQuery} from 'storefrontapi.generated'; import invariant from 'tiny-invariant'; import {routeHeaders} from '~/data/cache'; diff --git a/app/routes/($locale).blogs.$blogHandle._index.tsx b/app/routes/($locale).blogs.$blogHandle._index.tsx index 923c01f..375532a 100644 --- a/app/routes/($locale).blogs.$blogHandle._index.tsx +++ b/app/routes/($locale).blogs.$blogHandle._index.tsx @@ -1,6 +1,6 @@ import {flattenConnection} from '@shopify/hydrogen'; import {json} from '@shopify/remix-oxygen'; -import {RouteLoaderArgs} from '@weaverse/hydrogen'; +import {type RouteLoaderArgs} from '@weaverse/hydrogen'; import type {BlogQuery} from 'storefrontapi.generated'; import invariant from 'tiny-invariant'; import {routeHeaders} from '~/data/cache'; diff --git a/app/routes/($locale).cart.$lines.tsx b/app/routes/($locale).cart.$lines.tsx index d3df6f5..6621b1e 100644 --- a/app/routes/($locale).cart.$lines.tsx +++ b/app/routes/($locale).cart.$lines.tsx @@ -1,4 +1,4 @@ -import {redirect, type LoaderArgs} from '@shopify/remix-oxygen'; +import {redirect, type LoaderFunctionArgs} from '@shopify/remix-oxygen'; /** * Automatically creates a new cart based on the URL and redirects straight to checkout. @@ -19,7 +19,7 @@ import {redirect, type LoaderArgs} from '@shopify/remix-oxygen'; * ``` * @preserve */ -export async function loader({request, context, params}: LoaderArgs) { +export async function loader({request, context, params}: LoaderFunctionArgs) { const {cart} = context; const {lines} = params; const linesMap = lines?.split(',').map((line) => { diff --git a/app/routes/($locale).cart.tsx b/app/routes/($locale).cart.tsx index a94bfc7..fc16bd1 100644 --- a/app/routes/($locale).cart.tsx +++ b/app/routes/($locale).cart.tsx @@ -1,12 +1,17 @@ -import {Await, useMatches} from '@remix-run/react'; +import {Await} from '@remix-run/react'; import invariant from 'tiny-invariant'; -import {type LoaderArgs, type ActionArgs, json} from '@shopify/remix-oxygen'; +import { + type LoaderFunctionArgs, + type ActionFunctionArgs, + json, +} from '@shopify/remix-oxygen'; import {CartForm, type CartQueryData} from '@shopify/hydrogen'; import {isLocalPath} from '~/lib/utils'; import {Cart} from '~/components'; +import {useRootLoaderData} from '~/root'; -export async function action({request, context}: ActionArgs) { +export async function action({request, context}: ActionFunctionArgs) { const {session, cart} = context; const [formData, customerAccessToken] = await Promise.all([ @@ -78,17 +83,17 @@ export async function action({request, context}: ActionArgs) { ); } -export async function loader({context}: LoaderArgs) { +export async function loader({context}: LoaderFunctionArgs) { const {cart} = context; return json(await cart.get()); } export default function CartRoute() { - const [root] = useMatches(); + const rootData = useRootLoaderData(); // @todo: finish on a separate PR return (
- + {(cart) => }
diff --git a/app/routes/($locale).collections.$collectionHandle.tsx b/app/routes/($locale).collections.$collectionHandle.tsx index 51fa5b4..aa62b13 100644 --- a/app/routes/($locale).collections.$collectionHandle.tsx +++ b/app/routes/($locale).collections.$collectionHandle.tsx @@ -5,7 +5,7 @@ import { } from '@shopify/hydrogen'; import type {ProductCollectionSortKeys} from '@shopify/hydrogen/storefront-api-types'; import {json} from '@shopify/remix-oxygen'; -import {RouteLoaderArgs} from '@weaverse/hydrogen'; +import {type RouteLoaderArgs} from '@weaverse/hydrogen'; import invariant from 'tiny-invariant'; import type {AppliedFilter, SortParam} from '~/components/SortFilter'; import {routeHeaders} from '~/data/cache'; diff --git a/app/routes/($locale).collections._index.tsx b/app/routes/($locale).collections._index.tsx index 6c08a53..70af15f 100644 --- a/app/routes/($locale).collections._index.tsx +++ b/app/routes/($locale).collections._index.tsx @@ -1,5 +1,6 @@ import {getPaginationVariables} from '@shopify/hydrogen'; -import {json, LoaderArgs} from '@shopify/remix-oxygen'; +import {json} from '@shopify/remix-oxygen'; +import {type RouteLoaderArgs} from '@weaverse/hydrogen'; import {routeHeaders} from '~/data/cache'; import {COLLECTIONS_QUERY} from '~/data/queries'; import {seoPayload} from '~/lib/seo.server'; @@ -9,7 +10,7 @@ const PAGINATION_SIZE = 4; export const headers = routeHeaders; -export const loader = async (args: LoaderArgs) => { +export const loader = async (args: RouteLoaderArgs) => { let { request, context: {storefront, weaverse}, diff --git a/app/routes/($locale).collections.all.tsx b/app/routes/($locale).collections.all.tsx index bb2026c..4313c97 100644 --- a/app/routes/($locale).collections.all.tsx +++ b/app/routes/($locale).collections.all.tsx @@ -1,5 +1,6 @@ -import {redirect, type LoaderArgs} from '@shopify/remix-oxygen'; +import {redirect} from '@shopify/remix-oxygen'; +import {type RouteLoaderArgs} from '@weaverse/hydrogen'; -export async function loader({params}: LoaderArgs) { +export async function loader({params}: RouteLoaderArgs) { return redirect(params?.locale ? `${params.locale}/products` : '/products'); } diff --git a/app/routes/($locale).discount.$code.tsx b/app/routes/($locale).discount.$code.tsx index 3c5b2d4..a59a9ae 100644 --- a/app/routes/($locale).discount.$code.tsx +++ b/app/routes/($locale).discount.$code.tsx @@ -1,4 +1,4 @@ -import {redirect, type LoaderArgs} from '@shopify/remix-oxygen'; +import {redirect, type LoaderFunctionArgs} from '@shopify/remix-oxygen'; /** * Automatically applies a discount found on the url @@ -12,7 +12,7 @@ import {redirect, type LoaderArgs} from '@shopify/remix-oxygen'; * ``` * @preserve */ -export async function loader({request, context, params}: LoaderArgs) { +export async function loader({request, context, params}: LoaderFunctionArgs) { const {cart} = context; // N.B. This route will probably be removed in the future. const session = context.session as any; @@ -20,8 +20,13 @@ export async function loader({request, context, params}: LoaderArgs) { const url = new URL(request.url); const searchParams = new URLSearchParams(url.search); - const redirectParam = - searchParams.get('redirect') || searchParams.get('return_to') || '/'; + let redirectParam = + searchParams.get('redirect') || searchParams.get('return_to') || '/'; + + if (redirectParam.includes('//')) { + // Avoid redirecting to external URLs to prevent phishing attacks + redirectParam = '/'; + } searchParams.delete('redirect'); searchParams.delete('return_to'); diff --git a/app/routes/($locale).featured-products.tsx b/app/routes/($locale).featured-products.tsx index 6176cba..71ff9cc 100644 --- a/app/routes/($locale).featured-products.tsx +++ b/app/routes/($locale).featured-products.tsx @@ -1,4 +1,4 @@ -import {json, type LoaderArgs} from '@shopify/remix-oxygen'; +import {json, type LoaderFunctionArgs} from '@shopify/remix-oxygen'; import invariant from 'tiny-invariant'; import { @@ -6,12 +6,12 @@ import { FEATURED_COLLECTION_FRAGMENT, } from '~/data/fragments'; -export async function loader({context: {storefront}}: LoaderArgs) { +export async function loader({context: {storefront}}: LoaderFunctionArgs) { return json(await getFeaturedData(storefront)); } export async function getFeaturedData( - storefront: LoaderArgs['context']['storefront'], + storefront: LoaderFunctionArgs['context']['storefront'], variables: {pageBy?: number} = {}, ) { const data = await storefront.query(FEATURED_ITEMS_QUERY, { diff --git a/app/routes/($locale).pages.$pageHandle.tsx b/app/routes/($locale).pages.$pageHandle.tsx index e35538d..40d61a4 100644 --- a/app/routes/($locale).pages.$pageHandle.tsx +++ b/app/routes/($locale).pages.$pageHandle.tsx @@ -1,14 +1,14 @@ -import {json, type LoaderArgs} from '@shopify/remix-oxygen'; +import {json} from '@shopify/remix-oxygen'; +import {type RouteLoaderArgs} from '@weaverse/hydrogen'; import invariant from 'tiny-invariant'; -import {PageHeader} from '~/components'; import {routeHeaders} from '~/data/cache'; import {seoPayload} from '~/lib/seo.server'; import {WeaverseContent} from '~/weaverse'; export const headers = routeHeaders; -export async function loader({request, params, context}: LoaderArgs) { +export async function loader({request, params, context}: RouteLoaderArgs) { invariant(params.pageHandle, 'Missing page handle'); const {page} = await context.storefront.query(PAGE_QUERY, { diff --git a/app/routes/($locale).policies.$policyHandle.tsx b/app/routes/($locale).policies.$policyHandle.tsx index 49e75f8..0975d95 100644 --- a/app/routes/($locale).policies.$policyHandle.tsx +++ b/app/routes/($locale).policies.$policyHandle.tsx @@ -1,4 +1,4 @@ -import {json, type MetaFunction, type LoaderArgs} from '@shopify/remix-oxygen'; +import {json, type LoaderFunctionArgs} from '@shopify/remix-oxygen'; import {useLoaderData} from '@remix-run/react'; import invariant from 'tiny-invariant'; @@ -8,7 +8,7 @@ import {seoPayload} from '~/lib/seo.server'; export const headers = routeHeaders; -export async function loader({request, params, context}: LoaderArgs) { +export async function loader({request, params, context}: LoaderFunctionArgs) { invariant(params.policyHandle, 'Missing policy handle'); const policyName = params.policyHandle.replace( diff --git a/app/routes/($locale).policies._index.tsx b/app/routes/($locale).policies._index.tsx index 5451325..e7394d7 100644 --- a/app/routes/($locale).policies._index.tsx +++ b/app/routes/($locale).policies._index.tsx @@ -1,4 +1,4 @@ -import {json, type LoaderArgs} from '@shopify/remix-oxygen'; +import {json, type LoaderFunctionArgs} from '@shopify/remix-oxygen'; import {useLoaderData} from '@remix-run/react'; import invariant from 'tiny-invariant'; @@ -9,7 +9,7 @@ import type {NonNullableFields} from '~/lib/type'; export const headers = routeHeaders; -export async function loader({request, context: {storefront}}: LoaderArgs) { +export async function loader({request, context: {storefront}}: LoaderFunctionArgs) { const data = await storefront.query(POLICIES_QUERY); invariant(data, 'No data returned from Shopify API'); diff --git a/app/routes/($locale).products.$productHandle.tsx b/app/routes/($locale).products.$productHandle.tsx index 111c07d..78520d6 100644 --- a/app/routes/($locale).products.$productHandle.tsx +++ b/app/routes/($locale).products.$productHandle.tsx @@ -1,6 +1,7 @@ import type {ShopifyAnalyticsProduct} from '@shopify/hydrogen'; import {AnalyticsPageType} from '@shopify/hydrogen'; -import {defer, LoaderArgs, redirect} from '@shopify/remix-oxygen'; +import {defer, redirect} from '@shopify/remix-oxygen'; +import {type RouteLoaderArgs} from '@weaverse/hydrogen'; import { ProductQuery, ProductRecommendationsQuery, @@ -19,7 +20,7 @@ import {getSelectedProductOptions} from '@weaverse/hydrogen'; export const headers = routeHeaders; -export async function loader({params, request, context}: LoaderArgs) { +export async function loader({params, request, context}: RouteLoaderArgs) { const {productHandle} = params; invariant(productHandle, 'Missing productHandle param, check route filename'); @@ -38,7 +39,7 @@ export async function loader({params, request, context}: LoaderArgs) { } if (!product.selectedVariant) { - return redirectToFirstVariant({product, request}); + throw redirectToFirstVariant({product, request}); } // In order to show which variants are available in the UI, we need to query @@ -106,7 +107,7 @@ function redirectToFirstVariant({ searchParams.set(option.name, option.value); } - throw redirect( + return redirect( `/products/${product!.handle}?${searchParams.toString()}`, 302, ); diff --git a/app/routes/($locale).products._index.tsx b/app/routes/($locale).products._index.tsx index 68800ac..799661c 100644 --- a/app/routes/($locale).products._index.tsx +++ b/app/routes/($locale).products._index.tsx @@ -1,5 +1,6 @@ import {getPaginationVariables} from '@shopify/hydrogen'; -import {json, LoaderArgs} from '@shopify/remix-oxygen'; +import {json} from '@shopify/remix-oxygen'; +import {type RouteLoaderArgs} from '@weaverse/hydrogen'; import invariant from 'tiny-invariant'; import {routeHeaders} from '~/data/cache'; import {ALL_PRODUCTS_QUERY} from '~/data/queries'; @@ -13,7 +14,7 @@ export const headers = routeHeaders; export async function loader({ request, context: {storefront, weaverse}, -}: LoaderArgs) { +}: RouteLoaderArgs) { const variables = getPaginationVariables(request, {pageBy: PAGE_BY}); const data = await storefront.query(ALL_PRODUCTS_QUERY, { diff --git a/app/routes/($locale).search.tsx b/app/routes/($locale).search.tsx index 42e7764..c24cd1c 100644 --- a/app/routes/($locale).search.tsx +++ b/app/routes/($locale).search.tsx @@ -1,4 +1,4 @@ -import {defer, type LoaderArgs} from '@shopify/remix-oxygen'; +import {defer, type LoaderFunctionArgs} from '@shopify/remix-oxygen'; import {Await, Form, useLoaderData} from '@remix-run/react'; import {Suspense} from 'react'; import {Pagination, getPaginationVariables} from '@shopify/hydrogen'; @@ -24,7 +24,7 @@ import { type FeaturedData, } from './($locale).featured-products'; -export async function loader({request, context: {storefront}}: LoaderArgs) { +export async function loader({request, context: {storefront}}: LoaderFunctionArgs) { const searchParams = new URL(request.url).searchParams; const searchTerm = searchParams.get('q')!; const variables = getPaginationVariables(request, {pageBy: 8}); @@ -175,7 +175,7 @@ function NoResults({ } export function getNoResultRecommendations( - storefront: LoaderArgs['context']['storefront'], + storefront: LoaderFunctionArgs['context']['storefront'], ) { return getFeaturedData(storefront, {pageBy: PAGINATION_SIZE}); } diff --git a/app/routes/[robots.txt].tsx b/app/routes/[robots.txt].tsx index 4faf04e..10ca94b 100644 --- a/app/routes/[robots.txt].tsx +++ b/app/routes/[robots.txt].tsx @@ -1,6 +1,6 @@ -import {type LoaderArgs} from '@shopify/remix-oxygen'; +import {type LoaderFunctionArgs} from '@shopify/remix-oxygen'; -export const loader = ({request}: LoaderArgs) => { +export const loader = ({request}: LoaderFunctionArgs) => { const url = new URL(request.url); return new Response(robotsTxtData({url: url.origin}), { diff --git a/app/routes/[sitemap.xml].tsx b/app/routes/[sitemap.xml].tsx index 77064b1..63b13d1 100644 --- a/app/routes/[sitemap.xml].tsx +++ b/app/routes/[sitemap.xml].tsx @@ -1,5 +1,5 @@ import {flattenConnection} from '@shopify/hydrogen'; -import type {LoaderArgs} from '@shopify/remix-oxygen'; +import type {LoaderFunctionArgs} from '@shopify/remix-oxygen'; import invariant from 'tiny-invariant'; import type {SitemapsQuery} from 'storefrontapi.generated'; @@ -17,7 +17,7 @@ interface ProductEntry { }; } -export async function loader({request, context: {storefront}}: LoaderArgs) { +export async function loader({request, context: {storefront}}: LoaderFunctionArgs) { const data = await storefront.query(SITEMAP_QUERY, { variables: { urlLimits: MAX_URLS, diff --git a/package.json b/package.json index f7a6b95..04fbe71 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,9 @@ "private": false, "sideEffects": false, "author": "Weaverse", - "version": "2.2.4", + "version": "2.3.0", "scripts": { - "dev": "shopify hydrogen dev --codegen-unstable --port 3456", + "dev": "shopify hydrogen dev --codegen --port 3456", "build": "shopify hydrogen build", "preview": "npm run build && shopify hydrogen preview", "lint": "eslint --no-error-on-unmatched-pattern --ext .js,.ts,.jsx,.tsx .", @@ -19,12 +19,12 @@ "prettier": "@shopify/prettier-config", "dependencies": { "@headlessui/react": "1.7.17", - "@remix-run/react": "1.19.1", - "@shopify/cli": "3.49.7", - "@shopify/cli-hydrogen": "^5.5.1", - "@shopify/hydrogen": "^2023.7.13", - "@shopify/remix-oxygen": "^1.1.8", - "@weaverse/hydrogen": "2.4.2", + "@remix-run/react": "2.1.0", + "@shopify/cli": "3.50.0", + "@shopify/cli-hydrogen": "^6.0.2", + "@shopify/hydrogen": "^2023.10.2", + "@shopify/remix-oxygen": "^2.0.1", + "@weaverse/hydrogen": "^2.4.3", "clsx": "2.0.0", "cross-env": "7.0.3", "graphql": "16.8.1", @@ -40,8 +40,8 @@ "typographic-base": "1.0.4" }, "devDependencies": { - "@remix-run/dev": "1.19.1", - "@remix-run/eslint-config": "1.19.1", + "@remix-run/dev": "2.1.0", + "@remix-run/eslint-config": "2.1.0", "@shopify/eslint-plugin": "42.1.0", "@shopify/oxygen-workers-types": "3.17.3", "@shopify/prettier-config": "1.1.2", diff --git a/remix.config.js b/remix.config.js index 5fe68db..21b3a6f 100644 --- a/remix.config.js +++ b/remix.config.js @@ -2,7 +2,13 @@ module.exports = { appDirectory: 'app', ignoredRouteFiles: ['**/.*'], - watchPaths: ['./public', './.env'], + watchPaths: [ + './public', + './.env', + '../../packages/core/dist/index.mjs', + '../../packages/react/dist/index.mjs', + '../../packages/hydrogen/dist/index.mjs', + ], server: './server.ts', /** * The following settings are required to deploy Hydrogen apps to Oxygen: @@ -18,12 +24,4 @@ module.exports = { serverMinify: process.env.NODE_ENV === 'production', postcss: true, tailwind: true, - future: { - v2_dev: true, - v2_meta: true, - v2_headers: true, - v2_errorBoundary: true, - v2_routeConvention: true, - v2_normalizeFormMethod: true, - }, }; diff --git a/storefrontapi.generated.d.ts b/storefrontapi.generated.d.ts index 4a14c47..5e0b01d 100644 --- a/storefrontapi.generated.d.ts +++ b/storefrontapi.generated.d.ts @@ -175,7 +175,7 @@ export type ShopQueryQuery = { }; export type SeoCollectionContentQueryVariables = StorefrontAPI.Exact<{ - handle?: StorefrontAPI.InputMaybe; + handle?: StorefrontAPI.InputMaybe; country?: StorefrontAPI.InputMaybe; language?: StorefrontAPI.InputMaybe; }>; @@ -303,7 +303,7 @@ export type HomepageFeaturedCollectionsQuery = { export type ProductInfoQueryVariables = StorefrontAPI.Exact<{ country?: StorefrontAPI.InputMaybe; language?: StorefrontAPI.InputMaybe; - handle: StorefrontAPI.Scalars['String']; + handle: StorefrontAPI.Scalars['String']['input']; }>; export type ProductInfoQuery = { @@ -315,7 +315,7 @@ export type ProductInfoQuery = { export type ProductQueryVariables = StorefrontAPI.Exact<{ country?: StorefrontAPI.InputMaybe; language?: StorefrontAPI.InputMaybe; - handle: StorefrontAPI.Scalars['String']; + handle: StorefrontAPI.Scalars['String']['input']; selectedOptions: | Array | StorefrontAPI.SelectedOptionInput; @@ -438,8 +438,8 @@ export type ProductQuery = { }; export type ProductRecommendationsQueryVariables = StorefrontAPI.Exact<{ - productId: StorefrontAPI.Scalars['ID']; - count?: StorefrontAPI.InputMaybe; + productId: StorefrontAPI.Scalars['ID']['input']; + count?: StorefrontAPI.InputMaybe; country?: StorefrontAPI.InputMaybe; language?: StorefrontAPI.InputMaybe; }>; @@ -506,7 +506,7 @@ export type ProductRecommendationsQuery = { }; export type CollectionInfoQueryVariables = StorefrontAPI.Exact<{ - handle: StorefrontAPI.Scalars['String']; + handle: StorefrontAPI.Scalars['String']['input']; country?: StorefrontAPI.InputMaybe; language?: StorefrontAPI.InputMaybe; }>; @@ -526,18 +526,22 @@ export type CollectionInfoQuery = { }; export type CollectionDetailsQueryVariables = StorefrontAPI.Exact<{ - handle: StorefrontAPI.Scalars['String']; + handle: StorefrontAPI.Scalars['String']['input']; country?: StorefrontAPI.InputMaybe; language?: StorefrontAPI.InputMaybe; filters?: StorefrontAPI.InputMaybe< Array | StorefrontAPI.ProductFilter >; sortKey: StorefrontAPI.ProductCollectionSortKeys; - reverse?: StorefrontAPI.InputMaybe; - first?: StorefrontAPI.InputMaybe; - last?: StorefrontAPI.InputMaybe; - startCursor?: StorefrontAPI.InputMaybe; - endCursor?: StorefrontAPI.InputMaybe; + reverse?: StorefrontAPI.InputMaybe; + first?: StorefrontAPI.InputMaybe; + last?: StorefrontAPI.InputMaybe; + startCursor?: StorefrontAPI.InputMaybe< + StorefrontAPI.Scalars['String']['input'] + >; + endCursor?: StorefrontAPI.InputMaybe< + StorefrontAPI.Scalars['String']['input'] + >; }>; export type CollectionDetailsQuery = { @@ -606,10 +610,14 @@ export type CollectionDetailsQuery = { export type CollectionsQueryVariables = StorefrontAPI.Exact<{ country?: StorefrontAPI.InputMaybe; language?: StorefrontAPI.InputMaybe; - first?: StorefrontAPI.InputMaybe; - last?: StorefrontAPI.InputMaybe; - startCursor?: StorefrontAPI.InputMaybe; - endCursor?: StorefrontAPI.InputMaybe; + first?: StorefrontAPI.InputMaybe; + last?: StorefrontAPI.InputMaybe; + startCursor?: StorefrontAPI.InputMaybe< + StorefrontAPI.Scalars['String']['input'] + >; + endCursor?: StorefrontAPI.InputMaybe< + StorefrontAPI.Scalars['String']['input'] + >; }>; export type CollectionsQuery = { @@ -637,12 +645,18 @@ export type CollectionsQuery = { export type PaginatedProductsSearchQueryVariables = StorefrontAPI.Exact<{ country?: StorefrontAPI.InputMaybe; - endCursor?: StorefrontAPI.InputMaybe; - first?: StorefrontAPI.InputMaybe; + endCursor?: StorefrontAPI.InputMaybe< + StorefrontAPI.Scalars['String']['input'] + >; + first?: StorefrontAPI.InputMaybe; language?: StorefrontAPI.InputMaybe; - last?: StorefrontAPI.InputMaybe; - searchTerm?: StorefrontAPI.InputMaybe; - startCursor?: StorefrontAPI.InputMaybe; + last?: StorefrontAPI.InputMaybe; + searchTerm?: StorefrontAPI.InputMaybe< + StorefrontAPI.Scalars['String']['input'] + >; + startCursor?: StorefrontAPI.InputMaybe< + StorefrontAPI.Scalars['String']['input'] + >; }>; export type PaginatedProductsSearchQuery = { @@ -683,9 +697,9 @@ export type PaginatedProductsSearchQuery = { export type BlogQueryVariables = StorefrontAPI.Exact<{ language?: StorefrontAPI.InputMaybe; - blogHandle: StorefrontAPI.Scalars['String']; - pageBy: StorefrontAPI.Scalars['Int']; - cursor?: StorefrontAPI.InputMaybe; + blogHandle: StorefrontAPI.Scalars['String']['input']; + pageBy: StorefrontAPI.Scalars['Int']['input']; + cursor?: StorefrontAPI.InputMaybe; }>; export type BlogQuery = { @@ -740,8 +754,8 @@ export type ArticleFragment = Pick< export type ArticleDetailsQueryVariables = StorefrontAPI.Exact<{ language?: StorefrontAPI.InputMaybe; - blogHandle: StorefrontAPI.Scalars['String']; - articleHandle: StorefrontAPI.Scalars['String']; + blogHandle: StorefrontAPI.Scalars['String']['input']; + articleHandle: StorefrontAPI.Scalars['String']['input']; }>; export type ArticleDetailsQuery = { @@ -793,10 +807,14 @@ export type ArticleDetailsQuery = { export type AllProductsQueryVariables = StorefrontAPI.Exact<{ country?: StorefrontAPI.InputMaybe; language?: StorefrontAPI.InputMaybe; - first?: StorefrontAPI.InputMaybe; - last?: StorefrontAPI.InputMaybe; - startCursor?: StorefrontAPI.InputMaybe; - endCursor?: StorefrontAPI.InputMaybe; + first?: StorefrontAPI.InputMaybe; + last?: StorefrontAPI.InputMaybe; + startCursor?: StorefrontAPI.InputMaybe< + StorefrontAPI.Scalars['String']['input'] + >; + endCursor?: StorefrontAPI.InputMaybe< + StorefrontAPI.Scalars['String']['input'] + >; }>; export type AllProductsQuery = { @@ -838,7 +856,7 @@ export type AllProductsQuery = { export type VariantsQueryVariables = StorefrontAPI.Exact<{ country?: StorefrontAPI.InputMaybe; language?: StorefrontAPI.InputMaybe; - handle: StorefrontAPI.Scalars['String']; + handle: StorefrontAPI.Scalars['String']['input']; }>; export type VariantsQuery = { @@ -874,8 +892,8 @@ export type VariantsQuery = { export type LayoutQueryVariables = StorefrontAPI.Exact<{ language?: StorefrontAPI.InputMaybe; - headerMenuHandle: StorefrontAPI.Scalars['String']; - footerMenuHandle: StorefrontAPI.Scalars['String']; + headerMenuHandle: StorefrontAPI.Scalars['String']['input']; + footerMenuHandle: StorefrontAPI.Scalars['String']['input']; }>; export type LayoutQuery = { @@ -982,7 +1000,7 @@ export type GetShopPrimaryDomainQuery = { }; export type CustomerActivateMutationVariables = StorefrontAPI.Exact<{ - id: StorefrontAPI.Scalars['ID']; + id: StorefrontAPI.Scalars['ID']['input']; input: StorefrontAPI.CustomerActivateInput; }>; @@ -999,8 +1017,8 @@ export type CustomerActivateMutation = { export type CustomerAddressUpdateMutationVariables = StorefrontAPI.Exact<{ address: StorefrontAPI.MailingAddressInput; - customerAccessToken: StorefrontAPI.Scalars['String']; - id: StorefrontAPI.Scalars['ID']; + customerAccessToken: StorefrontAPI.Scalars['String']['input']; + id: StorefrontAPI.Scalars['ID']['input']; }>; export type CustomerAddressUpdateMutation = { @@ -1012,8 +1030,8 @@ export type CustomerAddressUpdateMutation = { }; export type CustomerAddressDeleteMutationVariables = StorefrontAPI.Exact<{ - customerAccessToken: StorefrontAPI.Scalars['String']; - id: StorefrontAPI.Scalars['ID']; + customerAccessToken: StorefrontAPI.Scalars['String']['input']; + id: StorefrontAPI.Scalars['ID']['input']; }>; export type CustomerAddressDeleteMutation = { @@ -1031,8 +1049,8 @@ export type CustomerAddressDeleteMutation = { export type CustomerDefaultAddressUpdateMutationVariables = StorefrontAPI.Exact<{ - addressId: StorefrontAPI.Scalars['ID']; - customerAccessToken: StorefrontAPI.Scalars['String']; + addressId: StorefrontAPI.Scalars['ID']['input']; + customerAccessToken: StorefrontAPI.Scalars['String']['input']; }>; export type CustomerDefaultAddressUpdateMutation = { @@ -1045,7 +1063,7 @@ export type CustomerDefaultAddressUpdateMutation = { export type CustomerAddressCreateMutationVariables = StorefrontAPI.Exact<{ address: StorefrontAPI.MailingAddressInput; - customerAccessToken: StorefrontAPI.Scalars['String']; + customerAccessToken: StorefrontAPI.Scalars['String']['input']; }>; export type CustomerAddressCreateMutation = { @@ -1060,7 +1078,7 @@ export type CustomerAddressCreateMutation = { }; export type CustomerUpdateMutationVariables = StorefrontAPI.Exact<{ - customerAccessToken: StorefrontAPI.Scalars['String']; + customerAccessToken: StorefrontAPI.Scalars['String']['input']; customer: StorefrontAPI.CustomerUpdateInput; }>; @@ -1177,7 +1195,7 @@ export type LineItemFullFragment = Pick< export type CustomerOrderQueryVariables = StorefrontAPI.Exact<{ country?: StorefrontAPI.InputMaybe; language?: StorefrontAPI.InputMaybe; - orderId: StorefrontAPI.Scalars['ID']; + orderId: StorefrontAPI.Scalars['ID']['input']; }>; export type CustomerOrderQuery = { @@ -1274,7 +1292,7 @@ export type CustomerOrderQuery = { }; export type CustomerRecoverMutationVariables = StorefrontAPI.Exact<{ - email: StorefrontAPI.Scalars['String']; + email: StorefrontAPI.Scalars['String']['input']; }>; export type CustomerRecoverMutation = { @@ -1299,7 +1317,7 @@ export type CustomerCreateMutation = { }; export type CustomerResetMutationVariables = StorefrontAPI.Exact<{ - id: StorefrontAPI.Scalars['ID']; + id: StorefrontAPI.Scalars['ID']['input']; input: StorefrontAPI.CustomerResetInput; }>; @@ -1315,7 +1333,7 @@ export type CustomerResetMutation = { }; export type CustomerDetailsQueryVariables = StorefrontAPI.Exact<{ - customerAccessToken: StorefrontAPI.Scalars['String']; + customerAccessToken: StorefrontAPI.Scalars['String']['input']; country?: StorefrontAPI.InputMaybe; language?: StorefrontAPI.InputMaybe; }>; @@ -1487,9 +1505,9 @@ export type CustomerDetailsFragment = Pick< }; export type ApiAllProductsQueryVariables = StorefrontAPI.Exact<{ - query?: StorefrontAPI.InputMaybe; - count?: StorefrontAPI.InputMaybe; - reverse?: StorefrontAPI.InputMaybe; + query?: StorefrontAPI.InputMaybe; + count?: StorefrontAPI.InputMaybe; + reverse?: StorefrontAPI.InputMaybe; country?: StorefrontAPI.InputMaybe; language?: StorefrontAPI.InputMaybe; sortKey?: StorefrontAPI.InputMaybe; @@ -1530,7 +1548,7 @@ export type ApiAllProductsQuery = { export type FeaturedItemsQueryVariables = StorefrontAPI.Exact<{ country?: StorefrontAPI.InputMaybe; language?: StorefrontAPI.InputMaybe; - pageBy?: StorefrontAPI.InputMaybe; + pageBy?: StorefrontAPI.InputMaybe; }>; export type FeaturedItemsQuery = { @@ -1576,7 +1594,7 @@ export type FeaturedItemsQuery = { export type PageDetailsQueryVariables = StorefrontAPI.Exact<{ language?: StorefrontAPI.InputMaybe; - handle: StorefrontAPI.Scalars['String']; + handle: StorefrontAPI.Scalars['String']['input']; }>; export type PageDetailsQuery = { @@ -1596,10 +1614,10 @@ export type PolicyHandleFragment = Pick< export type PoliciesHandleQueryVariables = StorefrontAPI.Exact<{ language?: StorefrontAPI.InputMaybe; - privacyPolicy: StorefrontAPI.Scalars['Boolean']; - shippingPolicy: StorefrontAPI.Scalars['Boolean']; - termsOfService: StorefrontAPI.Scalars['Boolean']; - refundPolicy: StorefrontAPI.Scalars['Boolean']; + privacyPolicy: StorefrontAPI.Scalars['Boolean']['input']; + shippingPolicy: StorefrontAPI.Scalars['Boolean']['input']; + termsOfService: StorefrontAPI.Scalars['Boolean']['input']; + refundPolicy: StorefrontAPI.Scalars['Boolean']['input']; }>; export type PoliciesHandleQuery = { @@ -1649,7 +1667,7 @@ export type PoliciesIndexQuery = { }; export type SitemapsQueryVariables = StorefrontAPI.Exact<{ - urlLimits?: StorefrontAPI.InputMaybe; + urlLimits?: StorefrontAPI.InputMaybe; language?: StorefrontAPI.InputMaybe; }>; @@ -1711,7 +1729,7 @@ interface GeneratedQueryTypes { return: CollectionInfoQuery; variables: CollectionInfoQueryVariables; }; - '#graphql\n query CollectionDetails(\n $handle: String!\n $country: CountryCode\n $language: LanguageCode\n $filters: [ProductFilter!]\n $sortKey: ProductCollectionSortKeys!\n $reverse: Boolean\n $first: Int\n $last: Int\n $startCursor: String\n $endCursor: String\n ) @inContext(country: $country, language: $language) {\n collection(handle: $handle) {\n id\n handle\n title\n description\n seo {\n description\n title\n }\n image {\n id\n url\n width\n height\n altText\n }\n products(\n first: $first,\n last: $last,\n before: $startCursor,\n after: $endCursor,\n filters: $filters,\n sortKey: $sortKey,\n reverse: $reverse\n ) {\n filters {\n id\n label\n type\n values {\n id\n label\n count\n input\n }\n }\n nodes {\n ...ProductCard\n }\n pageInfo {\n hasPreviousPage\n hasNextPage\n hasNextPage\n endCursor\n startCursor\n }\n }\n }\n collections(first: 100) {\n edges {\n node {\n title\n handle\n }\n }\n }\n }\n #graphql\n fragment ProductCard on Product {\n id\n title\n publishedAt\n handle\n vendor\n variants(first: 1) {\n nodes {\n id\n availableForSale\n image {\n url\n altText\n width\n height\n }\n price {\n amount\n currencyCode\n }\n compareAtPrice {\n amount\n currencyCode\n }\n selectedOptions {\n name\n value\n }\n product {\n handle\n title\n }\n }\n }\n }\n\n': { + '#graphql\n query CollectionDetails(\n $handle: String!\n $country: CountryCode\n $language: LanguageCode\n $filters: [ProductFilter!]\n $sortKey: ProductCollectionSortKeys!\n $reverse: Boolean\n $first: Int\n $last: Int\n $startCursor: String\n $endCursor: String\n ) @inContext(country: $country, language: $language) {\n collection(handle: $handle) {\n id\n handle\n title\n description\n seo {\n description\n title\n }\n image {\n id\n url\n width\n height\n altText\n }\n products(\n first: $first,\n last: $last,\n before: $startCursor,\n after: $endCursor,\n filters: $filters,\n sortKey: $sortKey,\n reverse: $reverse\n ) {\n filters {\n id\n label\n type\n values {\n id\n label\n count\n input\n }\n }\n nodes {\n ...ProductCard\n }\n pageInfo {\n hasPreviousPage\n hasNextPage\n endCursor\n startCursor\n }\n }\n }\n collections(first: 100) {\n edges {\n node {\n title\n handle\n }\n }\n }\n }\n #graphql\n fragment ProductCard on Product {\n id\n title\n publishedAt\n handle\n vendor\n variants(first: 1) {\n nodes {\n id\n availableForSale\n image {\n url\n altText\n width\n height\n }\n price {\n amount\n currencyCode\n }\n compareAtPrice {\n amount\n currencyCode\n }\n selectedOptions {\n name\n value\n }\n product {\n handle\n title\n }\n }\n }\n }\n\n': { return: CollectionDetailsQuery; variables: CollectionDetailsQueryVariables; };