diff --git a/.env.example b/.env.example index a4666dd31..46d641d54 100644 --- a/.env.example +++ b/.env.example @@ -4,3 +4,4 @@ SITE_NAME="Next.js Commerce with Shopware Composable Frontends" SHOPWARE_STORE_DOMAIN="" SHOPWARE_API_TYPE="store-api" SHOPWARE_ACCESS_TOKEN="" +SHOPWARE_USE_SEO_URLS="false" diff --git a/.husky/pre-commit b/.husky/pre-commit old mode 100644 new mode 100755 diff --git a/app/(cms)/[...cms]/page.tsx b/app/(cms)/[...cms]/page.tsx index b7f6d8e72..0a89ab4f8 100644 --- a/app/(cms)/[...cms]/page.tsx +++ b/app/(cms)/[...cms]/page.tsx @@ -8,11 +8,7 @@ export const runtime = 'edge'; export const revalidate = 43200; // 12 hours in seconds -export async function generateMetadata({ - params -}: { - params: { cms: string }; -}): Promise { +export async function generateMetadata({ params }: { params: { cms: string } }): Promise { const page = await getPage(params.cms); if (!page) return notFound(); diff --git a/app/search/(collection)/[...collection]/page.tsx b/app/search/(collection)/[...collection]/page.tsx index 67e3c326d..7de68dae9 100644 --- a/app/search/(collection)/[...collection]/page.tsx +++ b/app/search/(collection)/[...collection]/page.tsx @@ -1,10 +1,13 @@ -import { getCollection, getCollectionProducts } from 'lib/shopware'; import { Metadata } from 'next'; import { notFound } from 'next/navigation'; import Grid from 'components/grid'; +import Collections from 'components/layout/search/collections'; +import FilterList from 'components/layout/search/filter'; import ProductGridItems from 'components/layout/product-grid-items'; import Pagination from 'components/collection/pagination'; + +import { getCollection, getCollectionProducts } from 'lib/shopware'; import { defaultSort, sorting } from 'lib/constants'; export const runtime = 'edge'; @@ -47,13 +50,25 @@ export default async function CategoryPage({ {products.length === 0 ? (

{`No products found in this collection`}

) : ( -
- - - - +
+
+ +
+
+ + + + +
+
+ +
)} diff --git a/app/search/layout.tsx b/app/search/layout.tsx index 872276d7e..7bd3f1593 100644 --- a/app/search/layout.tsx +++ b/app/search/layout.tsx @@ -1,21 +1,11 @@ import Footer from 'components/layout/footer'; -import Collections from 'components/layout/search/collections'; -import FilterList from 'components/layout/search/filter'; -import { sorting } from 'lib/constants'; import { Suspense } from 'react'; +// @ToDo: We could use dynamic Layout per page, see https://nextjs.org/docs/pages/building-your-application/routing/pages-and-layouts#with-typescript export default function SearchLayout({ children }: { children: React.ReactNode }) { return ( -
-
- -
-
{children}
-
- -
-
+ {children}
); diff --git a/app/search/loading.tsx b/app/search/loading.tsx index 3b4bd399f..730c40184 100644 --- a/app/search/loading.tsx +++ b/app/search/loading.tsx @@ -1,13 +1,25 @@ import Grid from 'components/grid'; +import FilterList from 'components/layout/search/filter'; +import { sorting } from 'lib/constants'; export default function Loading() { return ( - - {Array(12) - .fill(0) - .map((_, index) => { - return ; - })} - +
+
+
+ + {Array(12) + .fill(0) + .map((_, index) => { + return ( + + ); + })} + +
+
+ +
+
); } diff --git a/app/search/page.tsx b/app/search/page.tsx index 3eeac0c6a..13b1ac2f2 100644 --- a/app/search/page.tsx +++ b/app/search/page.tsx @@ -1,5 +1,6 @@ import Grid from 'components/grid'; import ProductGridItems from 'components/layout/product-grid-items'; +import FilterList from 'components/layout/search/filter'; import { defaultSort, sorting } from 'lib/constants'; import { getSearchCollectionProducts } from 'lib/shopware'; @@ -23,18 +24,32 @@ export default async function SearchPage({ return ( <> - {searchValue ? ( -

- {products.length === 0 - ? 'There are no products that match ' - : `Showing ${products.length} ${resultsText} for `} - "{searchValue}" -

+ {searchValue && products.length === 0 ? ( +
+

+ {'There are no products that match '} + "{searchValue}" +

+
) : null} {products.length > 0 ? ( - - - +
+
+ {searchValue ? ( +

+ {`Showing ${products.length} ${resultsText} for `} + "{searchValue}" +

+ ) : null} +

Good place to add other suggest search terms ;)

+
+ + + +
+ +
+
) : null} ); diff --git a/app/sitemap.ts b/app/sitemap.ts index d1b685ff1..e1196555b 100644 --- a/app/sitemap.ts +++ b/app/sitemap.ts @@ -19,9 +19,7 @@ export default async function sitemap(): Promise
- // ); + return ( +
+
+ {[...products, ...products].map((product, i) => ( + + {product.featuredImage ? ( + {product.title} + ) : null} +
+
+ {product.title} +
+
+ + ))} +
+
+ ); } diff --git a/components/cart/actions.ts b/components/cart/actions.ts index b5a187971..75b1a14b7 100644 --- a/components/cart/actions.ts +++ b/components/cart/actions.ts @@ -59,4 +59,3 @@ export const updateItemQuantity = async ({ return new Error('Error updating item quantity', { cause: e }); } }; - diff --git a/components/cart/add-to-cart.tsx b/components/cart/add-to-cart.tsx index 5362ff590..e353938ee 100644 --- a/components/cart/add-to-cart.tsx +++ b/components/cart/add-to-cart.tsx @@ -6,17 +6,17 @@ import { useRouter, useSearchParams } from 'next/navigation'; import { useEffect, useState, useTransition } from 'react'; import LoadingDots from 'components/loading-dots'; -import { ProductVariant } from 'lib/shopify/types'; import { Product } from 'lib/shopware/types'; +import { ProductVariant } from 'lib/shopware/types'; export function AddToCart({ product, variants, - availableForSale, + availableForSale }: { variants: ProductVariant[]; availableForSale: boolean; - product: Product + product: Product; }) { const [selectedVariantId, setSelectedVariantId] = useState(variants[0]?.id); const router = useRouter(); @@ -44,10 +44,10 @@ export function AddToCart({ startTransition(async () => { const error = await addItem(product.id); - if (error) { - console.error(error); - return; - } + if (error) { + console.error(error); + return; + } router.refresh(); }); diff --git a/components/cart/delete-item-button.tsx b/components/cart/delete-item-button.tsx index 4684f5a92..395d96606 100644 --- a/components/cart/delete-item-button.tsx +++ b/components/cart/delete-item-button.tsx @@ -3,7 +3,7 @@ import LoadingDots from 'components/loading-dots'; import { useRouter } from 'next/navigation'; import clsx from 'clsx'; -import type { CartItem } from 'lib/shopify/types'; +import type { CartItem } from 'lib/shopware/types'; import { useTransition } from 'react'; import { removeItem } from 'components/cart/actions'; diff --git a/components/cart/edit-item-quantity-button.tsx b/components/cart/edit-item-quantity-button.tsx index ea17eaf92..0bef12636 100644 --- a/components/cart/edit-item-quantity-button.tsx +++ b/components/cart/edit-item-quantity-button.tsx @@ -6,7 +6,7 @@ import { removeItem, updateItemQuantity } from 'components/cart/actions'; import MinusIcon from 'components/icons/minus'; import PlusIcon from 'components/icons/plus'; import LoadingDots from 'components/loading-dots'; -import type { CartItem } from 'lib/shopify/types'; +import type { CartItem } from 'lib/shopware/types'; export default function EditItemQuantityButton({ item, diff --git a/components/cart/index.tsx b/components/cart/index.tsx index 6a68685ff..88088edd1 100644 --- a/components/cart/index.tsx +++ b/components/cart/index.tsx @@ -9,8 +9,12 @@ export default async function Cart() { let cartIdUpdated = false; const cart = await getCart(cartId); + if (!cart) { + return null; + } + if (cartId !== cart.id) { cartIdUpdated = true; } return ; -} \ No newline at end of file +} diff --git a/components/cart/modal.tsx b/components/cart/modal.tsx index 71deaa6a4..1e315ec88 100644 --- a/components/cart/modal.tsx +++ b/components/cart/modal.tsx @@ -9,7 +9,7 @@ import CloseIcon from 'components/icons/close'; import ShoppingBagIcon from 'components/icons/shopping-bag'; import Price from 'components/price'; import { DEFAULT_OPTION } from 'lib/constants'; -import type { Cart } from 'lib/shopify/types'; +import type { Cart } from 'lib/shopware/types'; import { createUrl } from 'lib/utils'; import { Fragment, useEffect, useRef, useState } from 'react'; import { useCookies } from 'react-cookie'; @@ -110,7 +110,7 @@ export default function CartModal({ cart, cartIdUpdated }: { cart: Cart; cartIdU }); const merchandiseUrl = createUrl( - `/product/${item.merchandise.product.handle}`, + `/product/${item.merchandise.product.path}`, new URLSearchParams(merchandiseSearchParams) ); diff --git a/components/collection/pagination.tsx b/components/collection/pagination.tsx index ad3692498..bfd8aec31 100644 --- a/components/collection/pagination.tsx +++ b/components/collection/pagination.tsx @@ -1,10 +1,18 @@ -'use client' +'use client'; import ReactPaginate from 'react-paginate'; import { createUrl } from 'lib/utils'; import { usePathname, useSearchParams, useRouter } from 'next/navigation'; -export default function Pagination({ itemsPerPage, itemsTotal, currentPage }: { itemsPerPage: number, itemsTotal: number, currentPage: number }) { +export default function Pagination({ + itemsPerPage, + itemsTotal, + currentPage +}: { + itemsPerPage: number; + itemsTotal: number; + currentPage: number; +}) { const router = useRouter(); const pathname = usePathname(); const currentParams = useSearchParams(); @@ -12,20 +20,26 @@ export default function Pagination({ itemsPerPage, itemsTotal, currentPage }: { const sort = currentParams.get('sort'); const pageCount = Math.ceil(itemsTotal / itemsPerPage); - // Invoke when user click to request another page. + // Invoke when user click to request another page. test const handlePageClick = (event: clickEvent) => { const page = event.selected; const newPage = page + 1; - let newUrl = createUrl(pathname, new URLSearchParams({ - ...(q && { q }), - ...(sort && { sort }), - })); - if (page !== 0) { - newUrl = createUrl(pathname, new URLSearchParams({ + let newUrl = createUrl( + pathname, + new URLSearchParams({ ...(q && { q }), - ...(sort && { sort }), - page: newPage.toString(), - })); + ...(sort && { sort }) + }) + ); + if (page !== 0) { + newUrl = createUrl( + pathname, + new URLSearchParams({ + ...(q && { q }), + ...(sort && { sort }), + page: newPage.toString() + }) + ); } router.replace(newUrl); }; @@ -65,4 +79,4 @@ type clickEvent = { isNext: boolean; isBreak: boolean; isActive: boolean; -} \ No newline at end of file +}; diff --git a/components/grid/three-items.tsx b/components/grid/three-items.tsx index a7d2b9010..27242bef5 100644 --- a/components/grid/three-items.tsx +++ b/components/grid/three-items.tsx @@ -1,5 +1,6 @@ import { GridTileImage } from 'components/grid/tile'; import { getCollectionProducts } from 'lib/shopware'; +import { isSeoUrls } from 'lib/shopware/helpers'; import type { Product } from 'lib/shopware/types'; import Link from 'next/link'; @@ -37,8 +38,11 @@ function ThreeItemGridItem({ export async function ThreeItemGrid() { // Collections that start with `hidden-*` are hidden from the search page. + const collectionName = isSeoUrls() + ? 'Summer-BBQ/Hidden-Category' + : '4ab73c06d90d4a5cb312209a64480d87'; const { products: homepageItems } = await getCollectionProducts({ - collection: 'Summer-BBQ/Hidden-Category' + collection: collectionName }); if (!homepageItems[0] || !homepageItems[1] || !homepageItems[2]) return null; diff --git a/components/grid/tile.tsx b/components/grid/tile.tsx index b2f219276..3b6d7c2fa 100644 --- a/components/grid/tile.tsx +++ b/components/grid/tile.tsx @@ -41,7 +41,8 @@ export function GridTileImage({ {props.src ? ( {props.title {menu.map((item: Menu) => ( - < nav className="col-span-1 lg:col-span-3" key={item.title + item.type} > - { - item.type === "headline" ? ( - {item.title} - ) : null - } + ))} -
- +
+
@@ -77,15 +80,17 @@ export default async function Footer() { className="text-black dark:text-white" >
- Shopware Composable Frontends Logo + width={40} + height={40} + >
- + ); } diff --git a/components/layout/navbar/mobile-menu.tsx b/components/layout/navbar/mobile-menu.tsx index 6ede894ae..ececc0a96 100644 --- a/components/layout/navbar/mobile-menu.tsx +++ b/components/layout/navbar/mobile-menu.tsx @@ -7,7 +7,7 @@ import { Fragment, useEffect, useState } from 'react'; import CloseIcon from 'components/icons/close'; import MenuIcon from 'components/icons/menu'; -import { Menu } from 'lib/shopify/types'; +import { Menu } from 'lib/shopware/types'; import Search from './search'; export default function MobileMenu({ menu }: { menu: Menu[] }) { diff --git a/components/layout/search/collections.tsx b/components/layout/search/collections.tsx index 0d2289e1a..2009790ee 100644 --- a/components/layout/search/collections.tsx +++ b/components/layout/search/collections.tsx @@ -1,15 +1,15 @@ import clsx from 'clsx'; import { Suspense } from 'react'; -import { getStaticCollections } from 'lib/shopware'; +import { getSubCollections } from 'lib/shopware'; import FilterList from './filter'; -import { transformStaticCollectionToList } from 'lib/shopware/transform'; +import { transformCollectionToList } from 'lib/shopware/transform'; -async function CollectionList() { - const collections = await getStaticCollections(); +async function CollectionList({ collection }: { collection: string }) { + const collections = await getSubCollections(collection); if (collections) { - const list = transformStaticCollectionToList(collections); - return ; + const list = transformCollectionToList(collections); + if (list.length > 0) return ; } } @@ -17,7 +17,7 @@ const skeleton = 'mb-3 h-4 w-5/6 animate-pulse rounded'; const activeAndTitles = 'bg-gray-800 dark:bg-gray-300'; const items = 'bg-gray-400 dark:bg-gray-700'; -export default function Collections() { +export default function Collections({ collection }: { collection: string }) { return ( } > - + ); } diff --git a/components/product/gallery.tsx b/components/product/gallery.tsx index 12690d11e..92cd9432b 100644 --- a/components/product/gallery.tsx +++ b/components/product/gallery.tsx @@ -84,8 +84,8 @@ export function Gallery({ diff --git a/components/product/variant-selector.tsx b/components/product/variant-selector.tsx index 520818516..fd46261f9 100644 --- a/components/product/variant-selector.tsx +++ b/components/product/variant-selector.tsx @@ -1,7 +1,7 @@ 'use client'; import clsx from 'clsx'; -import { ProductOption, ProductVariant } from 'lib/shopify/types'; +import { ProductOption, ProductVariant } from 'lib/shopware/types'; import { createUrl } from 'lib/utils'; import Link from 'next/link'; import { usePathname, useRouter, useSearchParams } from 'next/navigation'; diff --git a/lib/shopware/api-extended.ts b/lib/shopware/api-extended.ts index 07845b473..d4915593b 100644 --- a/lib/shopware/api-extended.ts +++ b/lib/shopware/api-extended.ts @@ -57,9 +57,10 @@ export type ExtendedProductListingResult = Omit & { - products?: ExtendedProduct[]; -}[]; +> & + { + products?: ExtendedProduct[]; + }[]; export type ExtendedCategory = Omit & { children?: ExtendedCategory[]; @@ -104,7 +105,7 @@ type extendedReadProductCrossSellings = { /** Found cross sellings */ 200: { content: { - 'application/json': ExtendedCrossSellingElementCollection + 'application/json': ExtendedCrossSellingElementCollection; }; }; }; diff --git a/lib/shopware/api.ts b/lib/shopware/api.ts index ed73ee8b4..f6e06bef6 100644 --- a/lib/shopware/api.ts +++ b/lib/shopware/api.ts @@ -1,4 +1,4 @@ -import { createAPIClient, RequestReturnType } from '@shopware/api-client'; +import { createAPIClient, RequestReturnType, ApiClientError } from '@shopware/api-client'; import { operations } from '@shopware/api-client/api-types'; import { cookies } from 'next/headers'; import { @@ -16,15 +16,13 @@ import { SeoURLResultSW, StoreNavigationTypeSW } from './types'; - -const domainSW = `https://${process.env.SHOPWARE_STORE_DOMAIN!}/${process.env.SHOPWARE_API_TYPE!}`; -const accessTokenSW = `${process.env.SHOPWARE_ACCESS_TOKEN}`; +import { getStoreDomainWithApiType, getAccessToken, getApiType } from 'lib/shopware/helpers'; function getApiClient(cartId?: string) { const apiInstance = createAPIClient({ - baseURL: domainSW, - accessToken: accessTokenSW, - apiType: 'store-api', + baseURL: getStoreDomainWithApiType(), + accessToken: getAccessToken(), + apiType: getApiType(), contextToken: cartId, onContextChanged(newContextToken: string) { //cookies().set('sw-context-token', newContextToken); @@ -43,117 +41,208 @@ export type ApiReturnType = RequestRetu export async function requestNavigation( type: StoreNavigationTypeSW, depth: number -): Promise { - return await getApiClient(cookies().get('sw-context-token')).invoke( - 'readNavigation post /navigation/{activeId}/{rootId} sw-include-seo-urls', - { - activeId: type, - rootId: type, - depth: depth +): Promise { + try { + return await getApiClient().invoke( + 'readNavigation post /navigation/{activeId}/{rootId} sw-include-seo-urls', + { + activeId: type, + rootId: type, + depth: depth + } + ); + } catch (error) { + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); } - ); + } } export async function requestCategory( categoryId: string, criteria?: Partial -): Promise { - return await getApiClient().invoke('readCategory post /category/{navigationId}?slots', { - navigationId: categoryId, - criteria - }); +): Promise { + try { + return await getApiClient().invoke('readCategory post /category/{navigationId}?slots', { + navigationId: categoryId, + criteria + }); + } catch (error) { + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } + } } export async function requestCategoryList( criteria: Partial -): Promise { - return await getApiClient().invoke('readCategoryList post /category', criteria); +): Promise { + try { + return await getApiClient().invoke('readCategoryList post /category', criteria); + } catch (error) { + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } + } } export async function requestProductsCollection( criteria: Partial -): Promise { - return await getApiClient().invoke('readProduct post /product', criteria); +): Promise { + try { + return await getApiClient().invoke('readProduct post /product', criteria); + } catch (error) { + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } + } } export async function requestCategoryProductsCollection( categoryId: string, criteria: Partial -): Promise { - return await getApiClient().invoke('readProductListing post /product-listing/{categoryId}', { - ...criteria, - categoryId: categoryId - }); +): Promise { + try { + return await getApiClient().invoke('readProductListing post /product-listing/{categoryId}', { + ...criteria, + categoryId: categoryId + }); + } catch (error) { + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } + } } export async function requestSearchCollectionProducts( criteria?: Partial -): Promise { - return await getApiClient().invoke('searchPage post /search', { - search: encodeURIComponent(criteria?.query || ''), - ...criteria - }); +): Promise { + try { + return await getApiClient().invoke('searchPage post /search', { + search: encodeURIComponent(criteria?.query || ''), + ...criteria + }); + } catch (error) { + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } + } } export async function requestSeoUrls(routeName: RouteNames, page: number = 1, limit: number = 100) { - return await getApiClient().invoke('readSeoUrl post /seo-url', { - page: page, - limit: limit, - filter: [ - { - type: 'equals', - field: 'routeName', - value: routeName - } - ] - }); + try { + return await getApiClient().invoke('readSeoUrl post /seo-url', { + page: page, + limit: limit, + filter: [ + { + type: 'equals', + field: 'routeName', + value: routeName + } + ] + }); + } catch (error) { + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } + } } export async function requestSeoUrl( handle: string, page: number = 1, limit: number = 1 -): Promise { - return await getApiClient().invoke('readSeoUrl post /seo-url', { - page: page, - limit: limit, - filter: [ - { - type: 'multi', - // @ts-ignore - operator: 'or', - queries: [ - { - type: 'equals', - field: 'seoPathInfo', - value: handle + '/' - }, - { - type: 'equals', - field: 'seoPathInfo', - value: handle - } - ] - } - ] - }); +): Promise { + try { + const criteriaSeoUrls = { + page: page, + limit: limit, + filter: [ + { + type: 'multi', + operator: 'or', + queries: [ + { + type: 'equals', + field: 'seoPathInfo', + value: handle + '/' + }, + { + type: 'equals', + field: 'seoPathInfo', + value: handle + } + ] + } + ] + }; + // @ts-ignore + return await getApiClient().invoke('readSeoUrl post /seo-url', criteriaSeoUrls); + } catch (error) { + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } + } } export async function requestCrossSell( productId: string, criteria?: Partial -): Promise { - return await getApiClient().invoke( - 'readProductCrossSellings post /product/{productId}/cross-selling', - { - productId: productId, - ...criteria +): Promise { + try { + return await getApiClient().invoke( + 'readProductCrossSellings post /product/{productId}/cross-selling', + { + productId: productId, + ...criteria + } + ); + } catch (error) { + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); } - ); + } } export async function requestCart(cartId?: string) { - return getApiClient(cartId).invoke('readCart get /checkout/cart?name', {}); + try { + return getApiClient(cartId).invoke('readCart get /checkout/cart?name', {}); + } catch (error) { + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } + } } export async function requestContext(cartId?: string) { @@ -174,4 +263,4 @@ export async function requestAddToCart(itemId: string, cartId: string) { } catch (e) { console.error('e', e); } -} \ No newline at end of file +} diff --git a/lib/shopware/criteria.ts b/lib/shopware/criteria.ts index 9abaa0899..0de5b1007 100644 --- a/lib/shopware/criteria.ts +++ b/lib/shopware/criteria.ts @@ -165,7 +165,7 @@ export function getStaticCollectionCriteria(page: number = 1, limit: number = 20 export function getDefaultSubCategoriesCriteria( categoryId: string, page: number = 1, - limit: number = 10 + limit: number = 1 ) { return { page: page, diff --git a/lib/shopware/helpers.ts b/lib/shopware/helpers.ts new file mode 100644 index 000000000..38ea90fb4 --- /dev/null +++ b/lib/shopware/helpers.ts @@ -0,0 +1,25 @@ +export function getAccessToken(): string { + return `${process.env.SHOPWARE_ACCESS_TOKEN}`; +} + +export function getStoreDomainWithApiType(): string { + return getStoreDomain() + '/' + getApiType(); +} + +export function getStoreDomain(protocol: boolean = true): string { + return protocol + ? `https://${process.env.SHOPWARE_STORE_DOMAIN!}` + : `${process.env.SHOPWARE_STORE_DOMAIN!}`; +} + +export function getApiType(): 'store-api' | 'admin-api' { + if (`${process.env.SHOPWARE_API_TYPE!}` === 'admin-api') { + return 'admin-api'; + } + + return 'store-api'; +} + +export function isSeoUrls(): boolean { + return `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true'; +} diff --git a/lib/shopware/index.ts b/lib/shopware/index.ts index a7a7fe1b4..b380e0050 100644 --- a/lib/shopware/index.ts +++ b/lib/shopware/index.ts @@ -1,4 +1,3 @@ -import { Cart } from 'lib/shopify/types'; import { requestCart, requestCategory, @@ -19,8 +18,8 @@ import { getDefaultProductCriteria, getDefaultProductsCriteria, getDefaultSearchProductsCriteria, - getSortingCriteria, - getStaticCollectionCriteria + getDefaultSubCategoriesCriteria, + getSortingCriteria } from './criteria'; import { transformCollection, @@ -29,16 +28,19 @@ import { transformPage, transformProduct, transformProducts, - transformStaticCollection + transformSubCollection } from './transform'; import { ApiSchemas, + Cart, + CategoryListingResultSW, Menu, Page, Product, ProductListingCriteria, StoreNavigationTypeSW } from './types'; +import { isSeoUrls } from 'lib/shopware/helpers'; export async function getMenu(params?: { type?: StoreNavigationTypeSW; @@ -52,39 +54,66 @@ export async function getMenu(params?: { } export async function getPage(handle: string | []): Promise { - const pageHandle = transformHandle(handle).replace('cms/', ''); - const seoUrlElement = await getFirstSeoUrlElement(pageHandle); - if (seoUrlElement) { - const resCategory = await getCategory(seoUrlElement); + let seoUrlElement; + let pageIdOrHandle = decodeURIComponent(transformHandle(handle)).replace('cms/', ''); - return resCategory ? transformPage(seoUrlElement, resCategory) : undefined; + if (isSeoUrls()) { + seoUrlElement = await getFirstSeoUrlElement(pageIdOrHandle); + if (seoUrlElement) { + pageIdOrHandle = seoUrlElement.foreignKey; + } + + if (!seoUrlElement) { + console.log('[getPage] Did not found any seoUrl element with page handle:', pageIdOrHandle); + } } + + const category = await getCategory(pageIdOrHandle); + if (!category) { + console.log('[getPage] Did not found any category with handle:', pageIdOrHandle); + } + + return category ? transformPage(category, seoUrlElement) : undefined; } export async function getFirstSeoUrlElement( handle: string ): Promise { - const resSeoUrl = await requestSeoUrl(handle); - if (resSeoUrl.elements && resSeoUrl.elements.length > 0 && resSeoUrl.elements[0]) { - return resSeoUrl.elements[0]; + const seoURL = await requestSeoUrl(handle); + if (seoURL && seoURL.elements && seoURL.elements.length > 0 && seoURL.elements[0]) { + return seoURL.elements[0]; } } export async function getFirstProduct(productId: string): Promise { const productCriteria = getDefaultProductCriteria(productId); - const res: ExtendedProductListingResult = await requestProductsCollection(productCriteria); - if (res.elements && res.elements.length > 0 && res.elements[0]) { - return res.elements[0]; + const listing: ExtendedProductListingResult | undefined = await requestProductsCollection( + productCriteria + ); + if (listing && listing.elements && listing.elements.length > 0 && listing.elements[0]) { + return listing.elements[0]; } } // ToDo: should be more dynamic (depending on handle), should work with server and not client see generateStaticParams from next.js -export async function getStaticCollections() { - // @ToDo: This is an example about multi-filter with new store API client - // @ts-ignore - const resCategory = await requestCategoryList(getStaticCollectionCriteria()); +export async function getSubCollections(collection: string) { + const collectionName = decodeURIComponent(transformHandle(collection ?? '')); + let criteria = getDefaultSubCategoriesCriteria(collectionName); + let res: CategoryListingResultSW | undefined = undefined; + const parentCollectionName = + Array.isArray(collection) && collection[0] ? collection[0] : undefined; - return resCategory ? transformStaticCollection(resCategory) : []; + if (isSeoUrls()) { + const seoUrlElement = await getFirstSeoUrlElement(collectionName); + if (seoUrlElement) { + criteria = getDefaultSubCategoriesCriteria(seoUrlElement.foreignKey); + } + } + + // @ts-ignore + res = await requestCategoryList(criteria); + + return res ? transformSubCollection(res, parentCollectionName) : []; } export async function getSearchCollectionProducts(params?: { @@ -99,9 +128,34 @@ export async function getSearchCollectionProducts(params?: { const sorting = getSortingCriteria(params?.sortKey, params?.reverse); const searchCriteria = { ...criteria, ...sorting }; - const res = await requestSearchCollectionProducts(searchCriteria); + const search = await requestSearchCollectionProducts(searchCriteria); + if (isSeoUrls() && search) { + search.elements = await changeVariantUrlToParentUrl(search); + } - return res ? transformProducts(res) : []; + return search ? transformProducts(search) : []; +} + +export async function changeVariantUrlToParentUrl( + collection: ExtendedProductListingResult +): Promise { + const newElements: ExtendedProduct[] = []; + if (collection.elements && collection.elements.length > 0) { + await Promise.all( + collection.elements.map(async (item) => { + if (item.parentId && item.seoUrls && item.seoUrls[0]) { + const parentProduct = await getFirstProduct(item.parentId); + if (parentProduct && parentProduct.seoUrls && parentProduct.seoUrls[0]) { + item.seoUrls[0].seoPathInfo = parentProduct.seoUrls[0].seoPathInfo; + } + } + + newElements.push(item); + }) + ); + } + + return newElements; } export async function getCollectionProducts(params?: { @@ -112,12 +166,12 @@ export async function getCollectionProducts(params?: { categoryId?: string; defaultSearchCriteria?: Partial; }): Promise<{ products: Product[]; total: number; limit: number }> { - let res; + let products; let category = params?.categoryId; - const collectionName = transformHandle(params?.collection ?? ''); + const collectionName = decodeURIComponent(transformHandle(params?.collection ?? '')); const sorting = getSortingCriteria(params?.sortKey, params?.reverse); - if (!category && collectionName !== '') { + if (isSeoUrls() && !category && collectionName !== '') { const seoUrlElement = await getFirstSeoUrlElement(collectionName); if (seoUrlElement) { category = seoUrlElement.foreignKey; @@ -130,37 +184,56 @@ export async function getCollectionProducts(params?: { } } + if (!isSeoUrls()) { + category = collectionName ?? undefined; + } + if (category) { const criteria = !params?.defaultSearchCriteria ? getDefaultProductsCriteria(params?.page) : params?.defaultSearchCriteria; const productsCriteria = { ...criteria, ...sorting }; - res = await requestCategoryProductsCollection(category, productsCriteria); + products = await requestCategoryProductsCollection(category, productsCriteria); + if (products) { + products.elements = await changeVariantUrlToParentUrl(products); + } } - return res - ? { products: transformProducts(res), total: res.total ?? 0, limit: res.limit ?? 0 } + return products + ? { + products: transformProducts(products), + total: products.total ?? 0, + limit: products.limit ?? 0 + } : { products: [], total: 0, limit: 0 }; } export async function getCategory( - seoUrl: ApiSchemas['SeoUrl'], + categoryId: string, cms: boolean = false -): Promise { +): Promise { const criteria = cms ? getDefaultCategoryWithCmsCriteria() : getDefaultCategoryCriteria(); - const resCategory = await requestCategory(seoUrl.foreignKey, criteria); - - return resCategory; + return await requestCategory(categoryId, criteria); } // This function is only used for generateMetadata at app/search/(collection)/[...collection]/page.tsx export async function getCollection(handle: string | []) { - const collectionName = transformHandle(handle); - const seoUrlElement = await getFirstSeoUrlElement(collectionName); - if (seoUrlElement) { - const resCategory = await getCategory(seoUrlElement); - const path = seoUrlElement.seoPathInfo ?? ''; - const collection = transformCollection(seoUrlElement, resCategory); + let path; + let seoUrlElement; + let categoryIdOrHandle = decodeURIComponent(transformHandle(handle)); + + if (isSeoUrls()) { + seoUrlElement = await getFirstSeoUrlElement(categoryIdOrHandle); + if (seoUrlElement) { + categoryIdOrHandle = seoUrlElement.foreignKey; + path = seoUrlElement.seoPathInfo ?? ''; + } + } + + const category = await getCategory(categoryIdOrHandle); + if (category) { + const collection = transformCollection(category, seoUrlElement); + path = path ?? category.id ?? ''; return { ...collection, @@ -171,10 +244,10 @@ export async function getCollection(handle: string | []) { export async function getProductSeoUrls() { const productSeoUrls: { path: string; updatedAt: string }[] = []; - const res = await requestSeoUrls('frontend.detail.page'); + const seoUrls = await requestSeoUrls('frontend.detail.page'); - if (res.elements && res.elements.length > 0) { - res.elements.map((item) => + if (seoUrls && seoUrls.elements && seoUrls.elements.length > 0) { + seoUrls.elements.map((item) => productSeoUrls.push({ path: item.seoPathInfo, updatedAt: item.updatedAt ?? item.createdAt }) ); } @@ -185,16 +258,20 @@ export async function getProductSeoUrls() { export async function getProduct(handle: string | []): Promise { let productSW: ExtendedProduct | undefined; let productId: string | undefined; - const productHandle = transformHandle(handle); + const productHandle = decodeURIComponent(transformHandle(handle)); + productId = productHandle; // if we do not use seoUrls the handle should be the product id - const seoUrlElement = await getFirstSeoUrlElement(productHandle); - if (seoUrlElement) { - productId = seoUrlElement.foreignKey; + if (isSeoUrls()) { + const seoUrlElement = await getFirstSeoUrlElement(productHandle); + if (seoUrlElement) { + productId = seoUrlElement.foreignKey; + } } if (!productId) { - console.log('[getProduct][search] Did not found any product with handle:', productHandle); + console.log('[getProduct][search] Did not found any product with handle:', handle); } + if (productId) { const firstProduct = await getFirstProduct(productId); if (firstProduct) { @@ -217,65 +294,74 @@ export async function getProductRecommendations(productId: string): Promise { +export async function getCart(cartId?: string): Promise { const cartData = await requestCart(cartId); - - let cart: Cart = { - checkoutUrl: 'https://frontends-demo.vercel.app', - cost: { - subtotalAmount: { - amount: cartData.price?.positionPrice?.toString() || '0', - currencyCode: 'EUR' - }, - totalAmount: { - amount: cartData.price?.totalPrice?.toString() || '0', - currencyCode: 'EUR' - }, - totalTaxAmount: { - amount: '0', - currencyCode: 'EUR' - } - }, - id: cartData.token || '', - lines: - cartData.lineItems?.map((lineItem) => ({ - id: lineItem.referencedId || '', - quantity: lineItem.quantity, - cost: { - totalAmount: { - amount: (lineItem as any)?.price?.totalPrice || '' - } + if (cartData) { + // @ToDo: should be moved to transformCart function + const cart: Cart = { + checkoutUrl: 'https://frontends-demo.vercel.app', + cost: { + subtotalAmount: { + amount: cartData.price?.positionPrice?.toString() || '0', + currencyCode: 'EUR' }, - merchandise: { - id: lineItem.referencedId, - title: lineItem.label, - selectedOptions: [], - product: { - description: lineItem.description, - descriptionHtml: lineItem.description, - id: lineItem.referencedId, - images: [], - seo: { - description: lineItem.description, - title: lineItem.label - }, - availableForSale: true, - featuredImage: { - altText: 'Cover image of ' + lineItem.label, - url: (lineItem as any).cover?.url - }, - handle: '', - options: [], - variants: [], - priceRange: {}, - tags: [], - title: lineItem.label, - updatedAt: (lineItem as any)?.payload?.updatedAt - } + totalAmount: { + amount: cartData.price?.totalPrice?.toString() || '0', + currencyCode: 'EUR' + }, + totalTaxAmount: { + amount: '0', + currencyCode: 'EUR' } - })) || [], - totalQuantity: cartData.lineItems?.length || 0 - }; - - return cart; + }, + id: cartData.token || '', + lines: + cartData.lineItems?.map((lineItem) => ({ + id: lineItem.referencedId || '', + quantity: lineItem.quantity ?? 0, + cost: { + totalAmount: { + amount: (lineItem as any)?.price?.totalPrice || '', + currencyCode: 'EUR' + } + }, + merchandise: { + id: lineItem.referencedId ?? '', + title: lineItem.label ?? '', + selectedOptions: [], + product: { + description: lineItem.description ?? '', + descriptionHtml: lineItem.description ?? '', + id: lineItem.referencedId ?? '', + images: [], + path: '', + seo: { + description: lineItem.description ?? '', + title: lineItem.label ?? '' + }, + availableForSale: true, + featuredImage: (lineItem as any).cover?.url, + handle: '', + options: [], + variants: [], + priceRange: { + minVariantPrice: { + amount: '', // @ToDo: should be correct value + currencyCode: 'EUR' + }, + maxVariantPrice: { + amount: '', // @ToDo: should be correct value + currencyCode: 'EUR' + } + }, + tags: [], + title: lineItem.label ?? '', + updatedAt: (lineItem as any)?.payload?.updatedAt + } + } + })) || [], + totalQuantity: cartData.lineItems?.length || 0 + }; + return cart; + } } diff --git a/lib/shopware/transform.ts b/lib/shopware/transform.ts index 8b0c23d83..1341dee7d 100644 --- a/lib/shopware/transform.ts +++ b/lib/shopware/transform.ts @@ -15,6 +15,7 @@ import { ExtendedProductListingResult } from './api-extended'; import { ListItem } from 'components/layout/search/filter'; +import { isSeoUrls } from 'lib/shopware/helpers'; export function transformMenu(res: ExtendedCategory[], type: string) { const menu: Menu[] = []; @@ -25,24 +26,29 @@ export function transformMenu(res: ExtendedCategory[], type: string) { } function transformMenuItem(item: ExtendedCategory, type: string): Menu { + const path = isSeoUrls() + ? item.seoUrls && item.seoUrls.length > 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo + ? type === 'footer-navigation' + ? '/cms/' + item.seoUrls[0].seoPathInfo + : '/search/' + item.seoUrls[0].seoPathInfo + : '' + : type === 'footer-navigation' + ? '/cms/' + item.id ?? '' + : '/search/' + item.id ?? ''; + // @ToDo: currently only footer-navigation is used for cms pages, this need to be more dynamic (shoud depending on the item) return { id: item.id ?? '', title: item.name, children: item.children?.map((item) => transformMenuItem(item, type)) ?? [], - path: - item.seoUrls && item.seoUrls.length > 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo - ? type === 'footer-navigation' - ? '/cms/' + item.seoUrls[0].seoPathInfo - : '/search/' + item.seoUrls[0].seoPathInfo - : '', + path: path, type: item.children && item.children.length > 0 ? 'headline' : 'link' }; } export function transformPage( - seoUrlElement: ApiSchemas['SeoUrl'], - category: ExtendedCategory + category: ExtendedCategory, + seoUrlElement?: ApiSchemas['SeoUrl'] ): Page { let plainHtmlContent; if (category.cmsPage) { @@ -51,20 +57,20 @@ export function transformPage( } return { - id: seoUrlElement.id ?? '', + id: seoUrlElement?.id ?? category.id ?? '', title: category.translated?.metaTitle ?? category.name ?? '', - handle: seoUrlElement.seoPathInfo, + handle: seoUrlElement?.seoPathInfo ?? category.id ?? '', body: plainHtmlContent ?? category.description ?? '', bodySummary: category.translated?.metaDescription ?? category.description ?? '', seo: { title: category.translated?.metaTitle ?? category.name ?? '', description: category.translated?.metaDescription ?? category.description ?? '' }, - createdAt: seoUrlElement.createdAt ?? '', - updatedAt: seoUrlElement.updatedAt ?? '', - routeName: seoUrlElement.routeName, + createdAt: seoUrlElement?.createdAt ?? category.createdAt ?? '', + updatedAt: seoUrlElement?.updatedAt ?? category.updatedAt ?? '', + routeName: seoUrlElement?.routeName, originalCmsPage: category.cmsPage, - foreignKey: seoUrlElement.foreignKey + foreignKey: seoUrlElement?.foreignKey ?? category.id }; } @@ -89,55 +95,89 @@ export function transformToPlainHtmlContent(cmsPage: ExtendedCmsPage): string { } export function transformCollection( - seoUrlElement: ApiSchemas['SeoUrl'], - resCategory: ExtendedCategory + resCategory: ExtendedCategory, + seoUrlElement?: ApiSchemas['SeoUrl'] ) { return { - handle: seoUrlElement.seoPathInfo, + handle: seoUrlElement?.seoPathInfo ?? resCategory.id ?? '', title: resCategory.translated?.metaTitle ?? resCategory.name ?? '', description: resCategory.description ?? '', seo: { title: resCategory.translated?.metaTitle ?? resCategory.name ?? '', description: resCategory.translated?.metaDescription ?? resCategory.description ?? '' }, - updatedAt: seoUrlElement.updatedAt ?? seoUrlElement.createdAt ?? '' + updatedAt: + seoUrlElement?.updatedAt ?? + seoUrlElement?.createdAt ?? + resCategory.updatedAt ?? + resCategory.createdAt }; } -export function transformStaticCollection(resCategory: CategoryListingResultSW): Collection[] { +export function transformSubCollection( + category: CategoryListingResultSW, + parentCollectionName?: string +): Collection[] { const collection: Collection[] = []; - if (resCategory.elements && resCategory.elements.length > 0) { - resCategory.elements.map((item) => - collection.push({ - handle: - item.seoUrls && item.seoUrls.length > 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo - ? item.seoUrls[0].seoPathInfo - : '', - title: item.translated?.metaTitle ?? item.name ?? '', - description: item.description ?? '', - seo: { - title: item.translated?.metaTitle ?? item.name ?? '', - description: item.translated?.metaDescription ?? item.description ?? '' - }, - updatedAt: item.updatedAt ?? item.createdAt ?? '' - }) - ); + if (category.elements && category.elements[0] && category.elements[0].children) { + // we do not support type links at the moment and show only visible categories + category.elements[0].children + .filter((item) => item.visible) + .filter((item) => item.type !== 'link') + .map((item) => { + const handle = + isSeoUrls() && item.seoUrls ? findHandle(item.seoUrls, parentCollectionName) : item.id; + if (handle) { + collection.push({ + handle: handle, + title: item.translated?.metaTitle ?? item.name ?? '', + description: item.description ?? '', + seo: { + title: item.translated?.metaTitle ?? item.name ?? '', + description: item.translated?.metaDescription ?? item.description ?? '' + }, + childCount: item.childCount ?? 0, + updatedAt: item.updatedAt ?? item.createdAt ?? '' + }); + } + }); } return collection; } -export function transformStaticCollectionToList(collection: Collection[]): ListItem[] { +// small function to find longest handle and to make sure parent collection name is in the path +function findHandle(seoUrls: ApiSchemas['SeoUrl'][], parentCollectionName?: string): string { + let handle: string = ''; + seoUrls.map((item) => { + if ( + !item.isDeleted && + item.isCanonical && + item.seoPathInfo && + item.seoPathInfo.length > handle.length && + item.seoPathInfo.includes(parentCollectionName ?? '') + ) { + handle = item.seoPathInfo; + } + }); + + return handle; +} + +export function transformCollectionToList(collection: Collection[]): ListItem[] { const listItem: ListItem[] = []; if (collection && collection.length > 0) { - collection.map((item) => + collection.map((item) => { + // we asume that when there is not product child count it must be a cms page + const pagePrefix = item.childCount === 0 ? '/cms' : '/search'; + const newHandle = item.handle.replace('Main-navigation/', ''); listItem.push({ title: item.title, - path: `/search/${item.handle}` - }) - ); + path: `${pagePrefix}/${newHandle}` + }); + }); } return listItem; @@ -157,12 +197,17 @@ export function transformProduct(item: ExtendedProduct): Product { const productOptions = transformOptions(item); const productVariants = transformVariants(item); - return { - id: item.id ?? '', - path: + let path = item.parentId ?? item.id ?? ''; + if (isSeoUrls()) { + path = item.seoUrls && item.seoUrls.length > 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo ? item.seoUrls[0].seoPathInfo - : '', + : ''; + } + + return { + id: item.id ?? '', + path: path, availableForSale: item.available ?? false, title: item.translated ? item.translated.name ?? '' : item.name, description: item.translated?.metaDescription @@ -213,9 +258,11 @@ function transformOptions(parent: ExtendedProduct): ProductOption[] { const productOptions: ProductOption[] = []; if (parent.children && parent.parentId === null && parent.children.length > 0) { const group: { [key: string]: string[] } = {}; + const groupId: { [key: string]: string } = {}; parent.children.map((child) => { child.options?.map((option) => { if (option && option.group) { + groupId[option.group.name] = option.groupId; group[option.group.name] = group[option.group.name] ? [...new Set([...(group[option.group.name] as []), ...[option.name]])] : [option.name]; @@ -223,13 +270,15 @@ function transformOptions(parent: ExtendedProduct): ProductOption[] { }); }); - if (parent.id) { - for (const [key, value] of Object.entries(group)) { - productOptions.push({ - id: parent.id, - name: key, - values: value - }); + for (const [key, value] of Object.entries(group)) { + for (const [currentGroupName, currentGroupId] of Object.entries(groupId)) { + if (key === currentGroupName) { + productOptions.push({ + id: currentGroupId, + name: key, + values: value + }); + } } } } diff --git a/lib/shopware/types.ts b/lib/shopware/types.ts index 405ed0b42..d91f58b77 100644 --- a/lib/shopware/types.ts +++ b/lib/shopware/types.ts @@ -10,7 +10,11 @@ export type ProductListingCriteria = { query: string; } & Omit & ExtendedCriteria; -export type RouteNames = 'frontend.navigation.page' | 'frontend.detail.page' | 'frontend.account.customer-group-registration.page' | 'frontend.landing.page' +export type RouteNames = + | 'frontend.navigation.page' + | 'frontend.detail.page' + | 'frontend.account.customer-group-registration.page' + | 'frontend.landing.page'; /** Return Types */ export type CategoryListingResultSW = { @@ -96,5 +100,35 @@ export type Collection = { title: string; description: string; seo: SEO; + childCount: number; updatedAt: string; }; + +export type Cart = { + id: string; + checkoutUrl: string; + cost: { + subtotalAmount: Money; + totalAmount: Money; + totalTaxAmount: Money; + }; + lines: CartItem[]; + totalQuantity: number; +}; + +export type CartItem = { + id: string; + quantity: number; + cost: { + totalAmount: Money; + }; + merchandise: { + id: string; + title: string; + selectedOptions: { + name: string; + value: string; + }[]; + product: Product; + }; +}; diff --git a/package.json b/package.json index edaf14907..e58c6ff57 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "private": true, "engines": { - "node": ">=16", - "pnpm": ">=7" + "node": ">=18", + "pnpm": ">=8" }, "scripts": { "build": "next build", @@ -15,42 +15,39 @@ "test": "pnpm lint && pnpm prettier:check", "test:e2e": "playwright test" }, - "git": { - "pre-commit": "lint-staged" - }, "lint-staged": { "*": "prettier --write --ignore-unknown" }, "dependencies": { "@headlessui/react": "^1.7.15", - "@shopware/api-client": "0.0.0-canary-20230706101754", + "@shopware/api-client": "0.0.0-canary-20230713092547", "@vercel/og": "^0.5.8", "clsx": "^1.2.1", "is-empty-iterable": "^3.0.0", - "next": "13.4.9", + "next": "13.4.10", "react": "18.2.0", "react-cookie": "^4.1.1", "react-dom": "18.2.0", "react-paginate": "^8.2.0" }, "devDependencies": { - "@playwright/test": "^1.35.1", + "@playwright/test": "^1.36.1", "@tailwindcss/typography": "^0.5.9", - "@types/node": "^20.4.1", - "@types/react": "18.2.14", - "@types/react-dom": "18.2.6", + "@types/node": "^20.4.2", + "@types/react": "18.2.15", + "@types/react-dom": "18.2.7", "@vercel/git-hooks": "^1.0.0", "autoprefixer": "^10.4.14", - "eslint": "^8.44.0", - "eslint-config-next": "^13.4.9", + "eslint": "^8.45.0", + "eslint-config-next": "^13.4.10", "eslint-config-prettier": "^8.8.0", - "eslint-plugin-unicorn": "^47.0.0", + "eslint-plugin-unicorn": "^48.0.0", "husky": "^8.0.3", "lint-staged": "^13.2.3", - "postcss": "^8.4.25", - "prettier": "^2.8.8", - "prettier-plugin-tailwindcss": "^0.3.0", - "tailwindcss": "^3.3.2", + "postcss": "^8.4.26", + "prettier": "^3.0.0", + "prettier-plugin-tailwindcss": "^0.4.1", + "tailwindcss": "^3.3.3", "typescript": "5.1.6" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dcd7e05f8..ee21b2876 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ dependencies: specifier: ^1.7.15 version: 1.7.15(react-dom@18.2.0)(react@18.2.0) '@shopware/api-client': - specifier: 0.0.0-canary-20230706101754 - version: link:../../frontends/packages/api-client-next + specifier: 0.0.0-canary-20230713092547 + version: 0.0.0-canary-20230713092547 '@vercel/og': specifier: ^0.5.8 version: 0.5.8 @@ -21,8 +21,8 @@ dependencies: specifier: ^3.0.0 version: 3.0.0 next: - specifier: 13.4.9 - version: 13.4.9(react-dom@18.2.0)(react@18.2.0) + specifier: 13.4.10 + version: 13.4.10(react-dom@18.2.0)(react@18.2.0) react: specifier: 18.2.0 version: 18.2.0 @@ -38,38 +38,38 @@ dependencies: devDependencies: '@playwright/test': - specifier: ^1.35.1 - version: 1.35.1 + specifier: ^1.36.1 + version: 1.36.1 '@tailwindcss/typography': specifier: ^0.5.9 - version: 0.5.9(tailwindcss@3.3.2) + version: 0.5.9(tailwindcss@3.3.3) '@types/node': - specifier: ^20.4.1 - version: 20.4.1 + specifier: ^20.4.2 + version: 20.4.2 '@types/react': - specifier: 18.2.14 - version: 18.2.14 + specifier: 18.2.15 + version: 18.2.15 '@types/react-dom': - specifier: 18.2.6 - version: 18.2.6 + specifier: 18.2.7 + version: 18.2.7 '@vercel/git-hooks': specifier: ^1.0.0 version: 1.0.0 autoprefixer: specifier: ^10.4.14 - version: 10.4.14(postcss@8.4.25) + version: 10.4.14(postcss@8.4.26) eslint: - specifier: ^8.44.0 - version: 8.44.0 + specifier: ^8.45.0 + version: 8.45.0 eslint-config-next: - specifier: ^13.4.9 - version: 13.4.9(eslint@8.44.0)(typescript@5.1.6) + specifier: ^13.4.10 + version: 13.4.10(eslint@8.45.0)(typescript@5.1.6) eslint-config-prettier: specifier: ^8.8.0 - version: 8.8.0(eslint@8.44.0) + version: 8.8.0(eslint@8.45.0) eslint-plugin-unicorn: - specifier: ^47.0.0 - version: 47.0.0(eslint@8.44.0) + specifier: ^48.0.0 + version: 48.0.0(eslint@8.45.0) husky: specifier: ^8.0.3 version: 8.0.3 @@ -77,17 +77,17 @@ devDependencies: specifier: ^13.2.3 version: 13.2.3 postcss: - specifier: ^8.4.25 - version: 8.4.25 + specifier: ^8.4.26 + version: 8.4.26 prettier: - specifier: ^2.8.8 - version: 2.8.8 + specifier: ^3.0.0 + version: 3.0.0 prettier-plugin-tailwindcss: - specifier: ^0.3.0 - version: 0.3.0(prettier@2.8.8) + specifier: ^0.4.1 + version: 0.4.1(prettier@3.0.0)https://boxblinkracer.com/blog/shopware-ai-demodata tailwindcss: - specifier: ^3.3.2 - version: 3.3.2 + specifier: ^3.3.3 + version: 3.3.3 typescript: specifier: 5.1.6 version: 5.1.6 @@ -120,7 +120,7 @@ packages: resolution: {integrity: sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-validator-identifier': 7.22.5 + '@babel/helper-validator-identifier': 7.22.5https://boxblinkracer.com/blog/shopware-ai-demodata chalk: 2.4.2 js-tokens: 4.0.0 dev: true @@ -132,13 +132,13 @@ packages: regenerator-runtime: 0.13.11 dev: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.44.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.45.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.44.0 + eslint: 8.45.0 eslint-visitor-keys: 3.4.1 dev: true @@ -153,7 +153,7 @@ packages: dependencies: ajv: 6.12.6 debug: 4.3.4 - espree: 9.6.0 + espree: 9.6.1 globals: 13.20.0 ignore: 5.2.4 import-fresh: 3.3.0 @@ -235,18 +235,18 @@ packages: '@jridgewell/sourcemap-codec': 1.4.14 dev: true - /@next/env@13.4.9: - resolution: {integrity: sha512-vuDRK05BOKfmoBYLNi2cujG2jrYbEod/ubSSyqgmEx9n/W3eZaJQdRNhTfumO+qmq/QTzLurW487n/PM/fHOkw==} + /@next/env@13.4.10: + resolution: {integrity: sha512-3G1yD/XKTSLdihyDSa8JEsaWOELY+OWe08o0LUYzfuHp1zHDA8SObQlzKt+v+wrkkPcnPweoLH1ImZeUa0A1NQ==} dev: false - /@next/eslint-plugin-next@13.4.9: - resolution: {integrity: sha512-nDtGpa992tNyAkT/KmSMy7QkHfNZmGCBYhHtafU97DubqxzNdvLsqRtliQ4FU04CysRCtvP2hg8rRC1sAKUTUA==} + /@next/eslint-plugin-next@13.4.10: + resolution: {integrity: sha512-YJqyq6vk39JQfvaNtN83t/p5Jy45+bazRL+V4QI8FPd3FBqFYMEsULiwRLgSJMgFqkk4t4JbeZurz+gILEAFpA==} dependencies: glob: 7.1.7 dev: true - /@next/swc-darwin-arm64@13.4.9: - resolution: {integrity: sha512-TVzGHpZoVBk3iDsTOQA/R6MGmFp0+17SWXMEWd6zG30AfuELmSSMe2SdPqxwXU0gbpWkJL1KgfLzy5ReN0crqQ==} + /@next/swc-darwin-arm64@13.4.10: + resolution: {integrity: sha512-4bsdfKmmg7mgFGph0UorD1xWfZ5jZEw4kKRHYEeTK9bT1QnMbPVPlVXQRIiFPrhoDQnZUoa6duuPUJIEGLV1Jg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -254,8 +254,8 @@ packages: dev: false optional: true - /@next/swc-darwin-x64@13.4.9: - resolution: {integrity: sha512-aSfF1fhv28N2e7vrDZ6zOQ+IIthocfaxuMWGReB5GDriF0caTqtHttAvzOMgJgXQtQx6XhyaJMozLTSEXeNN+A==} + /@next/swc-darwin-x64@13.4.10: + resolution: {integrity: sha512-ngXhUBbcZIWZWqNbQSNxQrB9T1V+wgfCzAor2olYuo/YpaL6mUYNUEgeBMhr8qwV0ARSgKaOp35lRvB7EmCRBg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -263,8 +263,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-gnu@13.4.9: - resolution: {integrity: sha512-JhKoX5ECzYoTVyIy/7KykeO4Z2lVKq7HGQqvAH+Ip9UFn1MOJkOnkPRB7v4nmzqAoY+Je05Aj5wNABR1N18DMg==} + /@next/swc-linux-arm64-gnu@13.4.10: + resolution: {integrity: sha512-SjCZZCOmHD4uyM75MVArSAmF5Y+IJSGroPRj2v9/jnBT36SYFTORN8Ag/lhw81W9EeexKY/CUg2e9mdebZOwsg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -272,8 +272,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-musl@13.4.9: - resolution: {integrity: sha512-OOn6zZBIVkm/4j5gkPdGn4yqQt+gmXaLaSjRSO434WplV8vo2YaBNbSHaTM9wJpZTHVDYyjzuIYVEzy9/5RVZw==} + /@next/swc-linux-arm64-musl@13.4.10: + resolution: {integrity: sha512-F+VlcWijX5qteoYIOxNiBbNE8ruaWuRlcYyIRK10CugqI/BIeCDzEDyrHIHY8AWwbkTwe6GRHabMdE688Rqq4Q==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -281,8 +281,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-gnu@13.4.9: - resolution: {integrity: sha512-iA+fJXFPpW0SwGmx/pivVU+2t4zQHNOOAr5T378PfxPHY6JtjV6/0s1vlAJUdIHeVpX98CLp9k5VuKgxiRHUpg==} + /@next/swc-linux-x64-gnu@13.4.10: + resolution: {integrity: sha512-WDv1YtAV07nhfy3i1visr5p/tjiH6CeXp4wX78lzP1jI07t4PnHHG1WEDFOduXh3WT4hG6yN82EQBQHDi7hBrQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -290,8 +290,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-musl@13.4.9: - resolution: {integrity: sha512-rlNf2WUtMM+GAQrZ9gMNdSapkVi3koSW3a+dmBVp42lfugWVvnyzca/xJlN48/7AGx8qu62WyO0ya1ikgOxh6A==} + /@next/swc-linux-x64-musl@13.4.10: + resolution: {integrity: sha512-zFkzqc737xr6qoBgDa3AwC7jPQzGLjDlkNmt/ljvQJ/Veri5ECdHjZCUuiTUfVjshNIIpki6FuP0RaQYK9iCRg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -299,8 +299,8 @@ packages: dev: false optional: true - /@next/swc-win32-arm64-msvc@13.4.9: - resolution: {integrity: sha512-5T9ybSugXP77nw03vlgKZxD99AFTHaX8eT1ayKYYnGO9nmYhJjRPxcjU5FyYI+TdkQgEpIcH7p/guPLPR0EbKA==} + /@next/swc-win32-arm64-msvc@13.4.10: + resolution: {integrity: sha512-IboRS8IWz5mWfnjAdCekkl8s0B7ijpWeDwK2O8CdgZkoCDY0ZQHBSGiJ2KViAG6+BJVfLvcP+a2fh6cdyBr9QQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -308,8 +308,8 @@ packages: dev: false optional: true - /@next/swc-win32-ia32-msvc@13.4.9: - resolution: {integrity: sha512-ojZTCt1lP2ucgpoiFgrFj07uq4CZsq4crVXpLGgQfoFq00jPKRPgesuGPaz8lg1yLfvafkU3Jd1i8snKwYR3LA==} + /@next/swc-win32-ia32-msvc@13.4.10: + resolution: {integrity: sha512-bSA+4j8jY4EEiwD/M2bol4uVEu1lBlgsGdvM+mmBm/BbqofNBfaZ2qwSbwE2OwbAmzNdVJRFRXQZ0dkjopTRaQ==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -317,8 +317,8 @@ packages: dev: false optional: true - /@next/swc-win32-x64-msvc@13.4.9: - resolution: {integrity: sha512-QbT03FXRNdpuL+e9pLnu+XajZdm/TtIXVYY4lA9t+9l0fLZbHXDYEKitAqxrOj37o3Vx5ufxiRAniaIebYDCgw==} + /@next/swc-win32-x64-msvc@13.4.10: + resolution: {integrity: sha512-g2+tU63yTWmcVQKDGY0MV1PjjqgZtwM4rB1oVVi/v0brdZAcrcTV+04agKzWtvWroyFz6IqtT0MoZJA7PNyLVw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -347,8 +347,8 @@ packages: fastq: 1.15.0 dev: true - /@pkgr/utils@2.4.1: - resolution: {integrity: sha512-JOqwkgFEyi+OROIyq7l4Jy28h/WwhDnG/cPkXG2Z1iFbubB6jsHW1NDvmyOzTBxHr3yg68YGirmh1JUgMqa+9w==} + /@pkgr/utils@2.4.2: + resolution: {integrity: sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} dependencies: cross-spawn: 7.0.3 @@ -359,13 +359,13 @@ packages: tslib: 2.6.0 dev: true - /@playwright/test@1.35.1: - resolution: {integrity: sha512-b5YoFe6J9exsMYg0pQAobNDR85T1nLumUYgUTtKm4d21iX2L7WqKq9dW8NGJ+2vX0etZd+Y7UeuqsxDXm9+5ZA==} + /@playwright/test@1.36.1: + resolution: {integrity: sha512-YK7yGWK0N3C2QInPU6iaf/L3N95dlGdbsezLya4n0ZCh3IL7VgPGxC6Gnznh9ApWdOmkJeleT2kMTcWPRZvzqg==} engines: {node: '>=16'} hasBin: true dependencies: - '@types/node': 20.4.1 - playwright-core: 1.35.1 + '@types/node': 20.4.2 + playwright-core: 1.36.1 optionalDependencies: fsevents: 2.3.2 dev: true @@ -379,6 +379,12 @@ packages: resolution: {integrity: sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==} dev: true + /@shopware/api-client@0.0.0-canary-20230713092547: + resolution: {integrity: sha512-+5dHwprTnpwtHQl3eletxpvMexqKf9N8fIiecqaeemrsWLkiFyAouP76UzYPVjEF54neOOaAI0DuIBvi2w4WXg==} + dependencies: + ofetch: 1.1.1 + dev: false + /@shuding/opentype.js@1.4.0-beta.0: resolution: {integrity: sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==} engines: {node: '>= 8.0.0'} @@ -394,7 +400,7 @@ packages: tslib: 2.6.0 dev: false - /@tailwindcss/typography@0.5.9(tailwindcss@3.3.2): + /@tailwindcss/typography@0.5.9(tailwindcss@3.3.3): resolution: {integrity: sha512-t8Sg3DyynFysV9f4JDOVISGsjazNb48AeIYQwcL+Bsq5uf4RYL75C1giZ43KISjeDGBaTN3Kxh7Xj/vRSMJUUg==} peerDependencies: tailwindcss: '>=3.0.0 || insiders' @@ -403,7 +409,7 @@ packages: lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 postcss-selector-parser: 6.0.10 - tailwindcss: 3.3.2 + tailwindcss: 3.3.3 dev: true /@types/cookie@0.3.3: @@ -413,7 +419,7 @@ packages: /@types/hoist-non-react-statics@3.3.1: resolution: {integrity: sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==} dependencies: - '@types/react': 18.2.14 + '@types/react': 18.2.15 hoist-non-react-statics: 3.3.2 dev: false @@ -421,8 +427,8 @@ packages: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: true - /@types/node@20.4.1: - resolution: {integrity: sha512-JIzsAvJeA/5iY6Y/OxZbv1lUcc8dNSE77lb2gnBH+/PJ3lFR1Ccvgwl5JWnHAkNHcRsT0TbpVOsiMKZ1F/yyJg==} + /@types/node@20.4.2: + resolution: {integrity: sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==} dev: true /@types/normalize-package-data@2.4.1: @@ -432,14 +438,14 @@ packages: /@types/prop-types@15.7.5: resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} - /@types/react-dom@18.2.6: - resolution: {integrity: sha512-2et4PDvg6PVCyS7fuTc4gPoksV58bW0RwSxWKcPRcHZf0PRUGq03TKcD/rUHe3azfV6/5/biUBJw+HhCQjaP0A==} + /@types/react-dom@18.2.7: + resolution: {integrity: sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==} dependencies: - '@types/react': 18.2.14 + '@types/react': 18.2.15 dev: true - /@types/react@18.2.14: - resolution: {integrity: sha512-A0zjq+QN/O0Kpe30hA1GidzyFjatVvrpIvWLxD+xv67Vt91TWWgco9IvrJBkeyHm1trGaFS/FSGqPlhyeZRm0g==} + /@types/react@18.2.15: + resolution: {integrity: sha512-oEjE7TQt1fFTFSbf8kkNuc798ahTUzn3Le67/PWjE8MAfYAD/qB7O8hSTcromLFqHCt9bcdOg5GXMokzTjJ5SA==} dependencies: '@types/prop-types': 15.7.5 '@types/scheduler': 0.16.3 @@ -448,8 +454,8 @@ packages: /@types/scheduler@0.16.3: resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} - /@typescript-eslint/parser@5.61.0(eslint@8.44.0)(typescript@5.1.6): - resolution: {integrity: sha512-yGr4Sgyh8uO6fSi9hw3jAFXNBHbCtKKFMdX2IkT3ZqpKmtAq3lHS4ixB/COFuAIJpwl9/AqF7j72ZDWYKmIfvg==} + /@typescript-eslint/parser@5.62.0(eslint@8.45.0)(typescript@5.1.6): + resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -458,31 +464,31 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 5.61.0 - '@typescript-eslint/types': 5.61.0 - '@typescript-eslint/typescript-estree': 5.61.0(typescript@5.1.6) + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6) debug: 4.3.4 - eslint: 8.44.0 + eslint: 8.45.0 typescript: 5.1.6 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/scope-manager@5.61.0: - resolution: {integrity: sha512-W8VoMjoSg7f7nqAROEmTt6LoBpn81AegP7uKhhW5KzYlehs8VV0ZW0fIDVbcZRcaP3aPSW+JZFua+ysQN+m/Nw==} + /@typescript-eslint/scope-manager@5.62.0: + resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.61.0 - '@typescript-eslint/visitor-keys': 5.61.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 dev: true - /@typescript-eslint/types@5.61.0: - resolution: {integrity: sha512-ldyueo58KjngXpzloHUog/h9REmHl59G1b3a5Sng1GfBo14BkS3ZbMEb3693gnP1k//97lh7bKsp6/V/0v1veQ==} + /@typescript-eslint/types@5.62.0: + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/typescript-estree@5.61.0(typescript@5.1.6): - resolution: {integrity: sha512-Fud90PxONnnLZ36oR5ClJBLTLfU4pIWBmnvGwTbEa2cXIqj70AEDEmOmpkFComjBZ/037ueKrOdHuYmSFVD7Rw==} + /@typescript-eslint/typescript-estree@5.62.0(typescript@5.1.6): + resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: typescript: '*' @@ -490,23 +496,23 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 5.61.0 - '@typescript-eslint/visitor-keys': 5.61.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 - semver: 7.5.3 + semver: 7.5.4 tsutils: 3.21.0(typescript@5.1.6) typescript: 5.1.6 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/visitor-keys@5.61.0: - resolution: {integrity: sha512-50XQ5VdbWrX06mQXhy93WywSFZZGsv3EOjq+lqp6WC2t+j3mb6A9xYVdrRxafvK88vg9k9u+CT4l6D8PEatjKg==} + /@typescript-eslint/visitor-keys@5.62.0: + resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.61.0 + '@typescript-eslint/types': 5.62.0 eslint-visitor-keys: 3.4.1 dev: true @@ -630,7 +636,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.22.1 get-intrinsic: 1.2.1 is-string: 1.0.7 dev: true @@ -646,7 +652,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.22.1 es-shim-unscopables: 1.0.0 dev: true @@ -656,7 +662,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.22.1 es-shim-unscopables: 1.0.0 dev: true @@ -665,11 +671,23 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.22.1 es-shim-unscopables: 1.0.0 get-intrinsic: 1.2.1 dev: true + /arraybuffer.prototype.slice@1.0.1: + resolution: {integrity: sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.2 + define-properties: 1.2.0 + get-intrinsic: 1.2.1 + is-array-buffer: 3.0.2 + is-shared-array-buffer: 1.0.2 + dev: true + /ast-types-flow@0.0.7: resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} dev: true @@ -679,7 +697,7 @@ packages: engines: {node: '>=8'} dev: true - /autoprefixer@10.4.14(postcss@8.4.25): + /autoprefixer@10.4.14(postcss@8.4.26): resolution: {integrity: sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==} engines: {node: ^10 || ^12 || >=14} hasBin: true @@ -687,11 +705,11 @@ packages: postcss: ^8.1.0 dependencies: browserslist: 4.21.9 - caniuse-lite: 1.0.30001512 + caniuse-lite: 1.0.30001516 fraction.js: 4.2.0 normalize-range: 0.1.2 picocolors: 1.0.0 - postcss: 8.4.25 + postcss: 8.4.26 postcss-value-parser: 4.2.0 dev: true @@ -756,9 +774,9 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001512 - electron-to-chromium: 1.4.451 - node-releases: 2.0.12 + caniuse-lite: 1.0.30001516 + electron-to-chromium: 1.4.461 + node-releases: 2.0.13 update-browserslist-db: 1.0.11(browserslist@4.21.9) dev: true @@ -802,8 +820,8 @@ packages: resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} dev: false - /caniuse-lite@1.0.30001512: - resolution: {integrity: sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw==} + /caniuse-lite@1.0.30001516: + resolution: {integrity: sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==} /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -1073,8 +1091,8 @@ packages: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: true - /electron-to-chromium@1.4.451: - resolution: {integrity: sha512-YYbXHIBxAHe3KWvGOJOuWa6f3tgow44rBW+QAuwVp2DvGqNZeE//K2MowNdWS7XE8li5cgQDrX1LdBr41LufkA==} + /electron-to-chromium@1.4.461: + resolution: {integrity: sha512-1JkvV2sgEGTDXjdsaQCeSwYYuhLRphRpc+g6EHTFELJXEiznLt3/0pZ9JuAOQ5p2rI3YxKTbivtvajirIfhrEQ==} dev: true /emoji-regex@10.2.1: @@ -1103,11 +1121,12 @@ packages: is-arrayish: 0.2.1 dev: true - /es-abstract@1.21.2: - resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==} + /es-abstract@1.22.1: + resolution: {integrity: sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==} engines: {node: '>= 0.4'} dependencies: array-buffer-byte-length: 1.0.0 + arraybuffer.prototype.slice: 1.0.1 available-typed-arrays: 1.0.5 call-bind: 1.0.2 es-set-tostringtag: 2.0.1 @@ -1134,13 +1153,17 @@ packages: object-keys: 1.1.1 object.assign: 4.1.4 regexp.prototype.flags: 1.5.0 + safe-array-concat: 1.0.0 safe-regex-test: 1.0.0 string.prototype.trim: 1.2.7 string.prototype.trimend: 1.0.6 string.prototype.trimstart: 1.0.6 + typed-array-buffer: 1.0.0 + typed-array-byte-length: 1.0.0 + typed-array-byte-offset: 1.0.0 typed-array-length: 1.0.4 unbox-primitive: 1.0.2 - which-typed-array: 1.1.9 + which-typed-array: 1.1.10 dev: true /es-set-tostringtag@2.0.1: @@ -1186,8 +1209,8 @@ packages: engines: {node: '>=10'} dev: true - /eslint-config-next@13.4.9(eslint@8.44.0)(typescript@5.1.6): - resolution: {integrity: sha512-0fLtKRR268NArpqeXXwnLgMXPvF64YESQvptVg+RMLCaijKm3FICN9Y7Jc1p2o+yrWwE4DufJXDM/Vo53D1L7g==} + /eslint-config-next@13.4.10(eslint@8.45.0)(typescript@5.1.6): + resolution: {integrity: sha512-+JjcM6lQmFR5Mw0ORm9o1CR29+z/uajgSfYAPEGIBxOhTHBgCMs7ysuwi72o7LkMmA8E3N7/h09pSGZxs0s85g==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 typescript: '>=3.3.1' @@ -1195,29 +1218,29 @@ packages: typescript: optional: true dependencies: - '@next/eslint-plugin-next': 13.4.9 + '@next/eslint-plugin-next': 13.4.10 '@rushstack/eslint-patch': 1.3.2 - '@typescript-eslint/parser': 5.61.0(eslint@8.44.0)(typescript@5.1.6) - eslint: 8.44.0 + '@typescript-eslint/parser': 5.62.0(eslint@8.45.0)(typescript@5.1.6) + eslint: 8.45.0 eslint-import-resolver-node: 0.3.7 - eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.61.0)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.44.0) - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.61.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.44.0) - eslint-plugin-jsx-a11y: 6.7.1(eslint@8.44.0) - eslint-plugin-react: 7.32.2(eslint@8.44.0) - eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.44.0) + eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.45.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.45.0) + eslint-plugin-jsx-a11y: 6.7.1(eslint@8.45.0) + eslint-plugin-react: 7.32.2(eslint@8.45.0) + eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.45.0) typescript: 5.1.6 transitivePeerDependencies: - eslint-import-resolver-webpack - supports-color dev: true - /eslint-config-prettier@8.8.0(eslint@8.44.0): + /eslint-config-prettier@8.8.0(eslint@8.45.0): resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 8.44.0 + eslint: 8.45.0 dev: true /eslint-import-resolver-node@0.3.7: @@ -1230,7 +1253,7 @@ packages: - supports-color dev: true - /eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.61.0)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.44.0): + /eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.45.0): resolution: {integrity: sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -1239,9 +1262,9 @@ packages: dependencies: debug: 4.3.4 enhanced-resolve: 5.15.0 - eslint: 8.44.0 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.61.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.44.0) - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.61.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.44.0) + eslint: 8.45.0 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.45.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.45.0) get-tsconfig: 4.6.2 globby: 13.2.2 is-core-module: 2.12.1 @@ -1254,7 +1277,7 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.61.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.44.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.45.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -1275,16 +1298,16 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.61.0(eslint@8.44.0)(typescript@5.1.6) + '@typescript-eslint/parser': 5.62.0(eslint@8.45.0)(typescript@5.1.6) debug: 3.2.7 - eslint: 8.44.0 + eslint: 8.45.0 eslint-import-resolver-node: 0.3.7 - eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.61.0)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.44.0) + eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.45.0) transitivePeerDependencies: - supports-color dev: true - /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.61.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.44.0): + /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.45.0): resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} engines: {node: '>=4'} peerDependencies: @@ -1294,22 +1317,22 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.61.0(eslint@8.44.0)(typescript@5.1.6) + '@typescript-eslint/parser': 5.62.0(eslint@8.45.0)(typescript@5.1.6) array-includes: 3.1.6 array.prototype.flat: 1.3.1 array.prototype.flatmap: 1.3.1 debug: 3.2.7 doctrine: 2.1.0 - eslint: 8.44.0 + eslint: 8.45.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.61.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.44.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.45.0) has: 1.0.3 is-core-module: 2.12.1 is-glob: 4.0.3 minimatch: 3.1.2 object.values: 1.1.6 resolve: 1.22.2 - semver: 6.3.0 + semver: 6.3.1 tsconfig-paths: 3.14.2 transitivePeerDependencies: - eslint-import-resolver-typescript @@ -1317,7 +1340,7 @@ packages: - supports-color dev: true - /eslint-plugin-jsx-a11y@6.7.1(eslint@8.44.0): + /eslint-plugin-jsx-a11y@6.7.1(eslint@8.45.0): resolution: {integrity: sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==} engines: {node: '>=4.0'} peerDependencies: @@ -1332,26 +1355,26 @@ packages: axobject-query: 3.2.1 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 8.44.0 + eslint: 8.45.0 has: 1.0.3 jsx-ast-utils: 3.3.4 language-tags: 1.0.5 minimatch: 3.1.2 object.entries: 1.1.6 object.fromentries: 2.0.6 - semver: 6.3.0 + semver: 6.3.1 dev: true - /eslint-plugin-react-hooks@5.0.0-canary-7118f5dd7-20230705(eslint@8.44.0): + /eslint-plugin-react-hooks@5.0.0-canary-7118f5dd7-20230705(eslint@8.45.0): resolution: {integrity: sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw==} engines: {node: '>=10'} peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 dependencies: - eslint: 8.44.0 + eslint: 8.45.0 dev: true - /eslint-plugin-react@7.32.2(eslint@8.44.0): + /eslint-plugin-react@7.32.2(eslint@8.45.0): resolution: {integrity: sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==} engines: {node: '>=4'} peerDependencies: @@ -1361,7 +1384,7 @@ packages: array.prototype.flatmap: 1.3.1 array.prototype.tosorted: 1.1.1 doctrine: 2.1.0 - eslint: 8.44.0 + eslint: 8.45.0 estraverse: 5.3.0 jsx-ast-utils: 3.3.4 minimatch: 3.1.2 @@ -1371,21 +1394,21 @@ packages: object.values: 1.1.6 prop-types: 15.8.1 resolve: 2.0.0-next.4 - semver: 6.3.0 + semver: 6.3.1 string.prototype.matchall: 4.0.8 dev: true - /eslint-plugin-unicorn@47.0.0(eslint@8.44.0): - resolution: {integrity: sha512-ivB3bKk7fDIeWOUmmMm9o3Ax9zbMz1Bsza/R2qm46ufw4T6VBFBaJIR1uN3pCKSmSXm8/9Nri8V+iUut1NhQGA==} + /eslint-plugin-unicorn@48.0.0(eslint@8.45.0): + resolution: {integrity: sha512-8fk/v3p1ro34JSVDBEmtOq6EEQRpMR0iTir79q69KnXFZ6DJyPkT3RAi+ZoTqhQMdDSpGh8BGR68ne1sP5cnAA==} engines: {node: '>=16'} peerDependencies: - eslint: '>=8.38.0' + eslint: '>=8.44.0' dependencies: '@babel/helper-validator-identifier': 7.22.5 - '@eslint-community/eslint-utils': 4.4.0(eslint@8.44.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.45.0) ci-info: 3.8.0 clean-regexp: 1.0.0 - eslint: 8.44.0 + eslint: 8.45.0 esquery: 1.5.0 indent-string: 4.0.0 is-builtin-module: 3.2.1 @@ -1395,13 +1418,12 @@ packages: read-pkg-up: 7.0.1 regexp-tree: 0.1.27 regjsparser: 0.10.0 - safe-regex: 2.1.1 - semver: 7.5.3 + semver: 7.5.4 strip-indent: 3.0.0 dev: true - /eslint-scope@7.2.0: - resolution: {integrity: sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==} + /eslint-scope@7.2.1: + resolution: {integrity: sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: esrecurse: 4.3.0 @@ -1413,12 +1435,12 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint@8.44.0: - resolution: {integrity: sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==} + /eslint@8.45.0: + resolution: {integrity: sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.44.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.45.0) '@eslint-community/regexpp': 4.5.1 '@eslint/eslintrc': 2.1.0 '@eslint/js': 8.44.0 @@ -1431,9 +1453,9 @@ packages: debug: 4.3.4 doctrine: 3.0.0 escape-string-regexp: 4.0.0 - eslint-scope: 7.2.0 + eslint-scope: 7.2.1 eslint-visitor-keys: 3.4.1 - espree: 9.6.0 + espree: 9.6.1 esquery: 1.5.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 @@ -1443,7 +1465,6 @@ packages: globals: 13.20.0 graphemer: 1.4.0 ignore: 5.2.4 - import-fresh: 3.3.0 imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 @@ -1455,14 +1476,13 @@ packages: natural-compare: 1.4.0 optionator: 0.9.3 strip-ansi: 6.0.1 - strip-json-comments: 3.1.1 text-table: 0.2.0 transitivePeerDependencies: - supports-color dev: true - /espree@9.6.0: - resolution: {integrity: sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==} + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: acorn: 8.10.0 @@ -1631,7 +1651,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.22.1 functions-have-names: 1.2.3 dev: true @@ -2075,6 +2095,10 @@ packages: is-docker: 2.2.1 dev: true + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true @@ -2330,8 +2354,8 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true - /next@13.4.9(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-vtefFm/BWIi/eWOqf1GsmKG3cjKw1k3LjuefKRcL3iiLl3zWzFdPG3as6xtxrGO6gwTzzaO1ktL4oiHt/uvTjA==} + /next@13.4.10(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-4ep6aKxVTQ7rkUW2fBLhpBr/5oceCuf4KmlUpvG/aXuDTIf9mexNSpabUD6RWPspu6wiJJvozZREhXhueYO36A==} engines: {node: '>=16.8.0'} hasBin: true peerDependencies: @@ -2348,10 +2372,10 @@ packages: sass: optional: true dependencies: - '@next/env': 13.4.9 + '@next/env': 13.4.10 '@swc/helpers': 0.5.1 busboy: 1.6.0 - caniuse-lite: 1.0.30001512 + caniuse-lite: 1.0.30001516 postcss: 8.4.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -2359,22 +2383,26 @@ packages: watchpack: 2.4.0 zod: 3.21.4 optionalDependencies: - '@next/swc-darwin-arm64': 13.4.9 - '@next/swc-darwin-x64': 13.4.9 - '@next/swc-linux-arm64-gnu': 13.4.9 - '@next/swc-linux-arm64-musl': 13.4.9 - '@next/swc-linux-x64-gnu': 13.4.9 - '@next/swc-linux-x64-musl': 13.4.9 - '@next/swc-win32-arm64-msvc': 13.4.9 - '@next/swc-win32-ia32-msvc': 13.4.9 - '@next/swc-win32-x64-msvc': 13.4.9 + '@next/swc-darwin-arm64': 13.4.10 + '@next/swc-darwin-x64': 13.4.10 + '@next/swc-linux-arm64-gnu': 13.4.10 + '@next/swc-linux-arm64-musl': 13.4.10 + '@next/swc-linux-x64-gnu': 13.4.10 + '@next/swc-linux-x64-musl': 13.4.10 + '@next/swc-win32-arm64-msvc': 13.4.10 + '@next/swc-win32-ia32-msvc': 13.4.10 + '@next/swc-win32-x64-msvc': 13.4.10 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros dev: false - /node-releases@2.0.12: - resolution: {integrity: sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==} + /node-fetch-native@1.2.0: + resolution: {integrity: sha512-5IAMBTl9p6PaAjYCnMv5FmqIF6GcZnawAVnzaCG0rX2aYZJ4CxEkZNtVPuTRug7fL7wyM5BQYTlAzcyMPi6oTQ==} + dev: false + + /node-releases@2.0.13: + resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} dev: true /normalize-package-data@2.5.0: @@ -2382,7 +2410,7 @@ packages: dependencies: hosted-git-info: 2.8.9 resolve: 1.22.2 - semver: 5.7.1 + semver: 5.7.2 validate-npm-package-license: 3.0.4 dev: true @@ -2444,7 +2472,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.22.1 dev: true /object.fromentries@2.0.6: @@ -2453,14 +2481,14 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.22.1 dev: true /object.hasown@1.1.2: resolution: {integrity: sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==} dependencies: define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.22.1 dev: true /object.values@1.1.6: @@ -2469,7 +2497,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.22.1 dev: true /once@1.4.0: @@ -2635,8 +2663,8 @@ packages: engines: {node: '>= 6'} dev: true - /playwright-core@1.35.1: - resolution: {integrity: sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==} + /playwright-core@1.36.1: + resolution: {integrity: sha512-7+tmPuMcEW4xeCL9cp9KxmYpQYHKkyjwoXRnoeTowaeNat8PoBMk/HwCYhqkH2fRkshfKEOiVus/IhID2Pg8kg==} engines: {node: '>=16'} hasBin: true dev: true @@ -2646,29 +2674,29 @@ packages: engines: {node: '>=4'} dev: true - /postcss-import@15.1.0(postcss@8.4.25): + /postcss-import@15.1.0(postcss@8.4.26): resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} engines: {node: '>=14.0.0'} peerDependencies: postcss: ^8.0.0 dependencies: - postcss: 8.4.25 + postcss: 8.4.26 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.2 dev: true - /postcss-js@4.0.1(postcss@8.4.25): + /postcss-js@4.0.1(postcss@8.4.26): resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} engines: {node: ^12 || ^14 || >= 16} peerDependencies: postcss: ^8.4.21 dependencies: camelcase-css: 2.0.1 - postcss: 8.4.25 + postcss: 8.4.26 dev: true - /postcss-load-config@4.0.1(postcss@8.4.25): + /postcss-load-config@4.0.1(postcss@8.4.26): resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==} engines: {node: '>= 14'} peerDependencies: @@ -2681,17 +2709,17 @@ packages: optional: true dependencies: lilconfig: 2.1.0 - postcss: 8.4.25 + postcss: 8.4.26 yaml: 2.3.1 dev: true - /postcss-nested@6.0.1(postcss@8.4.25): + /postcss-nested@6.0.1(postcss@8.4.26): resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} engines: {node: '>=12.0'} peerDependencies: postcss: ^8.2.14 dependencies: - postcss: 8.4.25 + postcss: 8.4.26 postcss-selector-parser: 6.0.13 dev: true @@ -2723,8 +2751,8 @@ packages: source-map-js: 1.0.2 dev: false - /postcss@8.4.25: - resolution: {integrity: sha512-7taJ/8t2av0Z+sQEvNzCkpDynl0tX3uJMCODi6nT3PfASC7dYCWV9aQ+uiCf+KBD4SEFcu+GvJdGdwzQ6OSjCw==} + /postcss@8.4.26: + resolution: {integrity: sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw==} engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.6 @@ -2737,8 +2765,8 @@ packages: engines: {node: '>= 0.8.0'} dev: true - /prettier-plugin-tailwindcss@0.3.0(prettier@2.8.8): - resolution: {integrity: sha512-009/Xqdy7UmkcTBpwlq7jsViDqXAYSOMLDrHAdTMlVZOrKfM2o9Ci7EMWTMZ7SkKBFTG04UM9F9iM2+4i6boDA==} + /prettier-plugin-tailwindcss@0.4.1(prettier@3.0.0): + resolution: {integrity: sha512-hwn2EiJmv8M+AW4YDkbjJ6HlZCTzLyz1QlySn9sMuKV/Px0fjwldlB7tol8GzdgqtkdPtzT3iJ4UzdnYXP25Ag==} engines: {node: '>=12.17.0'} peerDependencies: '@ianvs/prettier-plugin-sort-imports': '*' @@ -2746,7 +2774,7 @@ packages: '@shopify/prettier-plugin-liquid': '*' '@shufo/prettier-plugin-blade': '*' '@trivago/prettier-plugin-sort-imports': '*' - prettier: '>=2.2.0' + prettier: ^2.2 || ^3.0 prettier-plugin-astro: '*' prettier-plugin-css-order: '*' prettier-plugin-import-sort: '*' @@ -2789,12 +2817,12 @@ packages: prettier-plugin-twig-melody: optional: true dependencies: - prettier: 2.8.8 + prettier: 3.0.0 dev: true - /prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} + /prettier@3.0.0: + resolution: {integrity: sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==} + engines: {node: '>=14'} hasBin: true dev: true @@ -2981,6 +3009,16 @@ packages: tslib: 2.6.0 dev: true + /safe-array-concat@1.0.0: + resolution: {integrity: sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + /safe-regex-test@1.0.0: resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} dependencies: @@ -2989,12 +3027,6 @@ packages: is-regex: 1.1.4 dev: true - /safe-regex@2.1.1: - resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==} - dependencies: - regexp-tree: 0.1.27 - dev: true - /satori@0.10.1: resolution: {integrity: sha512-F4bTCkDp931tLb7+UCNPBuSQwXhikrUkI4fBQo6fA8lF0Evqqgg3nDyUpRktQpR5Ry1DIiIVqLyEwkAms87ykg==} engines: {node: '>=16'} @@ -3017,18 +3049,18 @@ packages: loose-envify: 1.4.0 dev: false - /semver@5.7.1: - resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} + /semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true dev: true - /semver@6.3.0: - resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true dev: true - /semver@7.5.3: - resolution: {integrity: sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==} + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} engines: {node: '>=10'} hasBin: true dependencies: @@ -3158,7 +3190,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.22.1 get-intrinsic: 1.2.1 has-symbols: 1.0.3 internal-slot: 1.0.5 @@ -3172,7 +3204,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.22.1 dev: true /string.prototype.trimend@1.0.6: @@ -3180,7 +3212,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.22.1 dev: true /string.prototype.trimstart@1.0.6: @@ -3188,7 +3220,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.22.1 dev: true /strip-ansi@6.0.1: @@ -3249,8 +3281,8 @@ packages: react: 18.2.0 dev: false - /sucrase@3.32.0: - resolution: {integrity: sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==} + /sucrase@3.33.0: + resolution: {integrity: sha512-ARGC7vbufOHfpvyGcZZXFaXCMZ9A4fffOGC5ucOW7+WHDGlAe8LJdf3Jts1sWhDeiI1RSWrKy5Hodl+JWGdW2A==} engines: {node: '>=8'} hasBin: true dependencies: @@ -3286,12 +3318,12 @@ packages: resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} engines: {node: ^14.18.0 || >=16.0.0} dependencies: - '@pkgr/utils': 2.4.1 + '@pkgr/utils': 2.4.2 tslib: 2.6.0 dev: true - /tailwindcss@3.3.2: - resolution: {integrity: sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==} + /tailwindcss@3.3.3: + resolution: {integrity: sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==} engines: {node: '>=14.0.0'} hasBin: true dependencies: @@ -3309,15 +3341,14 @@ packages: normalize-path: 3.0.0 object-hash: 3.0.0 picocolors: 1.0.0 - postcss: 8.4.25 - postcss-import: 15.1.0(postcss@8.4.25) - postcss-js: 4.0.1(postcss@8.4.25) - postcss-load-config: 4.0.1(postcss@8.4.25) - postcss-nested: 6.0.1(postcss@8.4.25) + postcss: 8.4.26 + postcss-import: 15.1.0(postcss@8.4.26) + postcss-js: 4.0.1(postcss@8.4.26) + postcss-load-config: 4.0.1(postcss@8.4.26) + postcss-nested: 6.0.1(postcss@8.4.26) postcss-selector-parser: 6.0.13 - postcss-value-parser: 4.2.0 resolve: 1.22.2 - sucrase: 3.32.0 + sucrase: 3.33.0 transitivePeerDependencies: - ts-node dev: true @@ -3421,6 +3452,36 @@ packages: engines: {node: '>=8'} dev: true + /typed-array-buffer@1.0.0: + resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-typed-array: 1.1.10 + dev: true + + /typed-array-byte-length@1.0.0: + resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.10 + dev: true + + /typed-array-byte-offset@1.0.0: + resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.10 + dev: true + /typed-array-length@1.0.4: resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} dependencies: @@ -3509,8 +3570,8 @@ packages: is-symbol: 1.0.4 dev: true - /which-typed-array@1.1.9: - resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} + /which-typed-array@1.1.10: + resolution: {integrity: sha512-uxoA5vLUfRPdjCuJ1h5LlYdmTLbYfums398v3WLkM+i/Wltl2/XyZpQWKbN++ck5L64SR/grOHqtXCUKmlZPNA==} engines: {node: '>= 0.4'} dependencies: available-typed-arrays: 1.0.5