From 8dcf6db08f4e3d3d57b059d76c23067159893a4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Wed, 12 Jul 2023 14:24:43 +0200 Subject: [PATCH 01/29] feat(poc): test commit --- components/collection/pagination.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/collection/pagination.tsx b/components/collection/pagination.tsx index ad3692498..2d560cf52 100644 --- a/components/collection/pagination.tsx +++ b/components/collection/pagination.tsx @@ -12,7 +12,7 @@ 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; From 8550185eaebe220b4bf0f39300927d03ef69c3be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Thu, 13 Jul 2023 12:05:07 +0200 Subject: [PATCH 02/29] feat(poc): carousel and improved sub-collections --- .../(collection)/[...collection]/page.tsx | 24 ++++-- app/search/layout.tsx | 14 +--- app/search/page.tsx | 32 +++++--- components/carousel.tsx | 63 ++++++++-------- components/collection/pagination.tsx | 40 ++++++---- components/layout/search/collections.tsx | 16 ++-- lib/shopware/criteria.ts | 2 +- lib/shopware/index.ts | 72 ++++++++++++------ lib/shopware/transform.ts | 73 +++++++++++++------ lib/shopware/types.ts | 30 ++++++++ 10 files changed, 239 insertions(+), 127 deletions(-) diff --git a/app/search/(collection)/[...collection]/page.tsx b/app/search/(collection)/[...collection]/page.tsx index 67e3c326d..0bce5ab50 100644 --- a/app/search/(collection)/[...collection]/page.tsx +++ b/app/search/(collection)/[...collection]/page.tsx @@ -3,6 +3,8 @@ 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 { defaultSort, sorting } from 'lib/constants'; @@ -47,13 +49,21 @@ 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/page.tsx b/app/search/page.tsx index 3eeac0c6a..a8940ac44 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'; @@ -22,19 +23,32 @@ export default async function SearchPage({ const resultsText = products.length > 1 ? 'results' : 'result'; return ( - <> - {searchValue ? ( + <>{searchValue && products.length === 0 ? ( +

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

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

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

+ ) : null} +

Good place to add other suggest search terms ;)

+
+ + + +
+ +
+
) : null} ); diff --git a/components/carousel.tsx b/components/carousel.tsx index 86f05c54c..3d1986aaf 100644 --- a/components/carousel.tsx +++ b/components/carousel.tsx @@ -3,39 +3,36 @@ import Image from 'next/image'; import Link from 'next/link'; export async function Carousel() { - // Collections that start with `hidden-*` are hidden from the search page. - // const products = await getCollectionProducts({ collection: 'hidden-homepage-carousel' }); + const { products } = await getCollectionProducts({ collection: 'Summer-BBQ/Hidden-Carousel-Category' }); - // if (!products?.length) return null; + if (!products?.length) return null; - return null; - - // return ( - //
- //
- // {[...products, ...products].map((product, i) => ( - // - // {product.featuredImage ? ( - // {product.title} - // ) : null} - //
- //
- // {product.title} - //
- //
- // - // ))} - //
- //
- // ); + return ( +
+
+ {[...products, ...products].map((product, i) => ( + + {product.featuredImage ? ( + {product.title} + ) : null} +
+
+ {product.title} +
+
+ + ))} +
+
+ ); } diff --git a/components/collection/pagination.tsx b/components/collection/pagination.tsx index 2d560cf52..40ad782f3 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. test + // Invoke when user click to request another page. 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/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/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/index.ts b/lib/shopware/index.ts index bb974a196..febe5e013 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,10 +28,12 @@ import { transformPage, transformProduct, transformProducts, - transformStaticCollection + transformSubCollection } from './transform'; import { ApiSchemas, + Cart, + CategoryListingResultSW, Menu, Page, Product, @@ -55,9 +56,17 @@ 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); + const category = await getCategory(seoUrlElement); - return resCategory ? transformPage(seoUrlElement, resCategory) : undefined; + if (!category) { + console.log('[getPage] Did not found any category with page handle:', pageHandle); + } + + return category ? transformPage(seoUrlElement, category) : undefined; + } + + if (!seoUrlElement) { + console.log('[getPage] Did not found any seoUrl element with page handle:', pageHandle); } } @@ -79,12 +88,19 @@ export async function getFirstProduct(productId: string): Promise { const cartData = await requestCart(); + // @ToDo: should be moved to transformCart function let cart: Cart = { checkoutUrl: 'https://frontends-demo.vercel.app', cost: { @@ -240,33 +257,44 @@ export async function getCart(): Promise { lines: cartData.lineItems?.map((lineItem) => ({ id: lineItem.id || '', - quantity: lineItem.quantity, + quantity: lineItem.quantity ?? 0, cost: { totalAmount: { - amount: (lineItem as any)?.price?.totalPrice || '' + amount: (lineItem as any)?.price?.totalPrice || '', + currencyCode: 'EUR' } }, merchandise: { - id: lineItem.referencedId, - title: lineItem.label, + id: lineItem.referencedId ?? '', + title: lineItem.label ?? '', selectedOptions: [], product: { - description: lineItem.description, - descriptionHtml: lineItem.description, - id: lineItem.referencedId, + description: lineItem.description ?? '', + descriptionHtml: lineItem.description ?? '', + id: lineItem.referencedId ?? '', images: [], + path: '', seo: { - description: lineItem.description, - title: lineItem.label + description: lineItem.description ?? '', + title: lineItem.label ?? '' }, availableForSale: true, featuredImage: (lineItem as any).cover?.url, handle: '', options: [], variants: [], - priceRange: {}, + priceRange: { + minVariantPrice: { + amount: '', // @ToDo: should be correct value + currencyCode: 'EUR' + }, + maxVariantPrice: { + amount: '', // @ToDo: should be correct value + currencyCode: 'EUR' + } + }, tags: [], - title: lineItem.label, + title: lineItem.label ?? '', updatedAt: (lineItem as any)?.payload?.updatedAt } } diff --git a/lib/shopware/transform.ts b/lib/shopware/transform.ts index 8b0c23d83..3afef3a06 100644 --- a/lib/shopware/transform.ts +++ b/lib/shopware/transform.ts @@ -104,40 +104,69 @@ export function transformCollection( }; } -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 = item.seoUrls ? findHandle(item.seoUrls, parentCollectionName) : undefined; + 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; diff --git a/lib/shopware/types.ts b/lib/shopware/types.ts index 405ed0b42..4e4331d80 100644 --- a/lib/shopware/types.ts +++ b/lib/shopware/types.ts @@ -96,5 +96,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; + }; +}; \ No newline at end of file From b6cff9ba012e548ad09102fe19aa603a7d3b45c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Thu, 13 Jul 2023 12:19:38 +0200 Subject: [PATCH 03/29] feat(poc): test commit --- components/collection/pagination.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/collection/pagination.tsx b/components/collection/pagination.tsx index 40ad782f3..bfd8aec31 100644 --- a/components/collection/pagination.tsx +++ b/components/collection/pagination.tsx @@ -20,7 +20,7 @@ export default function Pagination({ 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; From 33d780d427b5968596065b708f3b04d93cc4ab13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Thu, 13 Jul 2023 13:21:20 +0200 Subject: [PATCH 04/29] feat(poc): update dependencies --- .husky/pre-commit | 0 lib/shopware/index.ts | 2 +- package.json | 15 ++- pnpm-lock.yaml | 222 ++++++++++++++++++++++-------------------- 4 files changed, 124 insertions(+), 115 deletions(-) mode change 100644 => 100755 .husky/pre-commit diff --git a/.husky/pre-commit b/.husky/pre-commit old mode 100644 new mode 100755 diff --git a/lib/shopware/index.ts b/lib/shopware/index.ts index febe5e013..7af3cfa6e 100644 --- a/lib/shopware/index.ts +++ b/lib/shopware/index.ts @@ -237,7 +237,7 @@ export async function getCart(): Promise { const cartData = await requestCart(); // @ToDo: should be moved to transformCart function - let cart: Cart = { + const cart: Cart = { checkoutUrl: 'https://frontends-demo.vercel.app', cost: { subtotalAmount: { diff --git a/package.json b/package.json index edaf14907..ed0046c91 100644 --- a/package.json +++ b/package.json @@ -15,15 +15,12 @@ "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", @@ -34,11 +31,11 @@ "react-paginate": "^8.2.0" }, "devDependencies": { - "@playwright/test": "^1.35.1", + "@playwright/test": "^1.36.0", "@tailwindcss/typography": "^0.5.9", - "@types/node": "^20.4.1", + "@types/node": "^20.4.2", "@types/react": "18.2.14", - "@types/react-dom": "18.2.6", + "@types/react-dom": "18.2.7", "@vercel/git-hooks": "^1.0.0", "autoprefixer": "^10.4.14", "eslint": "^8.44.0", @@ -48,8 +45,8 @@ "husky": "^8.0.3", "lint-staged": "^13.2.3", "postcss": "^8.4.25", - "prettier": "^2.8.8", - "prettier-plugin-tailwindcss": "^0.3.0", + "prettier": "^3.0.0", + "prettier-plugin-tailwindcss": "^0.4.0", "tailwindcss": "^3.3.2", "typescript": "5.1.6" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 169c48afc..8d7e59991 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: 0.0.0-canary-20230706101754 + specifier: 0.0.0-canary-20230713092547 + version: 0.0.0-canary-20230713092547 '@vercel/og': specifier: ^0.5.8 version: 0.5.8 @@ -38,20 +38,20 @@ dependencies: devDependencies: '@playwright/test': - specifier: ^1.35.1 - version: 1.35.1 + specifier: ^1.36.0 + version: 1.36.0 '@tailwindcss/typography': specifier: ^0.5.9 version: 0.5.9(tailwindcss@3.3.2) '@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 '@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 @@ -80,11 +80,11 @@ devDependencies: specifier: ^8.4.25 version: 8.4.25 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.0 + version: 0.4.0(prettier@3.0.0) tailwindcss: specifier: ^3.3.2 version: 3.3.2 @@ -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.0: + resolution: {integrity: sha512-yN+fvMYtiyLFDCQos+lWzoX4XW3DNuaxjBu68G0lkgLgC6BP+m/iTxJQoSicz/x2G5EsrqlZTqTIP9sTgLQerg==} 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.0 optionalDependencies: fsevents: 2.3.2 dev: true @@ -379,8 +379,8 @@ packages: resolution: {integrity: sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==} dev: true - /@shopware/api-client@0.0.0-canary-20230706101754: - resolution: {integrity: sha512-h7nCTWVu6bLbxdKT8vEJcUVKVu/RveaZ3M1PxrQAMiP6b2nQeqRh5+QlqTEFGk+Middy11MINH70Wp6GMx+Y+A==} + /@shopware/api-client@0.0.0-canary-20230713092547: + resolution: {integrity: sha512-+5dHwprTnpwtHQl3eletxpvMexqKf9N8fIiecqaeemrsWLkiFyAouP76UzYPVjEF54neOOaAI0DuIBvi2w4WXg==} dependencies: ofetch: 1.1.1 dev: false @@ -427,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: @@ -438,8 +438,8 @@ 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 dev: true @@ -454,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.44.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 @@ -464,9 +464,9 @@ 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 typescript: 5.1.6 @@ -474,21 +474,21 @@ packages: - 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: '*' @@ -496,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 @@ -636,7 +636,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 get-intrinsic: 1.2.1 is-string: 1.0.7 dev: true @@ -652,7 +652,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 es-shim-unscopables: 1.0.0 dev: true @@ -662,7 +662,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 es-shim-unscopables: 1.0.0 dev: true @@ -671,7 +671,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 es-shim-unscopables: 1.0.0 get-intrinsic: 1.2.1 dev: true @@ -693,7 +693,7 @@ packages: postcss: ^8.1.0 dependencies: browserslist: 4.21.9 - caniuse-lite: 1.0.30001512 + caniuse-lite: 1.0.30001515 fraction.js: 4.2.0 normalize-range: 0.1.2 picocolors: 1.0.0 @@ -762,9 +762,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.30001515 + electron-to-chromium: 1.4.459 + node-releases: 2.0.13 update-browserslist-db: 1.0.11(browserslist@4.21.9) dev: true @@ -808,8 +808,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.30001515: + resolution: {integrity: sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA==} /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -1083,8 +1083,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.459: + resolution: {integrity: sha512-XXRS5NFv8nCrBL74Rm3qhJjA2VCsRFx0OjHKBMPI0otij56aun8UWiKTDABmd5/7GTR021pA4wivs+Ri6XCElg==} dev: true /emoji-regex@10.2.1: @@ -1113,8 +1113,8 @@ packages: is-arrayish: 0.2.1 dev: true - /es-abstract@1.21.2: - resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==} + /es-abstract@1.21.3: + resolution: {integrity: sha512-ZU4miiY1j3sGPFLJ34VJXEqhpmL+HGByCinGHv4HC+Fxl2fI2Z4yR6tl0mORnDr6PA8eihWo4LmSWDbvhALckg==} engines: {node: '>= 0.4'} dependencies: array-buffer-byte-length: 1.0.0 @@ -1148,9 +1148,10 @@ packages: string.prototype.trim: 1.2.7 string.prototype.trimend: 1.0.6 string.prototype.trimstart: 1.0.6 + 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: @@ -1207,11 +1208,11 @@ packages: dependencies: '@next/eslint-plugin-next': 13.4.9 '@rushstack/eslint-patch': 1.3.2 - '@typescript-eslint/parser': 5.61.0(eslint@8.44.0)(typescript@5.1.6) + '@typescript-eslint/parser': 5.62.0(eslint@8.44.0)(typescript@5.1.6) eslint: 8.44.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-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.44.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.62.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) @@ -1240,7 +1241,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.44.0): resolution: {integrity: sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -1250,8 +1251,8 @@ packages: 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-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.44.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.44.0) get-tsconfig: 4.6.2 globby: 13.2.2 is-core-module: 2.12.1 @@ -1264,7 +1265,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.44.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -1285,16 +1286,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.44.0)(typescript@5.1.6) debug: 3.2.7 eslint: 8.44.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.44.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.44.0): resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} engines: {node: '>=4'} peerDependencies: @@ -1304,7 +1305,7 @@ 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.44.0)(typescript@5.1.6) array-includes: 3.1.6 array.prototype.flat: 1.3.1 array.prototype.flatmap: 1.3.1 @@ -1312,14 +1313,14 @@ packages: doctrine: 2.1.0 eslint: 8.44.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.44.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 @@ -1349,7 +1350,7 @@ packages: 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): @@ -1381,7 +1382,7 @@ 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 @@ -1406,7 +1407,7 @@ packages: 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 @@ -1641,7 +1642,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 functions-have-names: 1.2.3 dev: true @@ -2361,7 +2362,7 @@ packages: '@next/env': 13.4.9 '@swc/helpers': 0.5.1 busboy: 1.6.0 - caniuse-lite: 1.0.30001512 + caniuse-lite: 1.0.30001515 postcss: 8.4.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -2387,8 +2388,8 @@ packages: resolution: {integrity: sha512-5IAMBTl9p6PaAjYCnMv5FmqIF6GcZnawAVnzaCG0rX2aYZJ4CxEkZNtVPuTRug7fL7wyM5BQYTlAzcyMPi6oTQ==} dev: false - /node-releases@2.0.12: - resolution: {integrity: sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==} + /node-releases@2.0.13: + resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} dev: true /normalize-package-data@2.5.0: @@ -2396,7 +2397,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 @@ -2458,7 +2459,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 dev: true /object.fromentries@2.0.6: @@ -2467,14 +2468,14 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 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.21.3 dev: true /object.values@1.1.6: @@ -2483,7 +2484,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 dev: true /ofetch@1.1.1: @@ -2657,8 +2658,8 @@ packages: engines: {node: '>= 6'} dev: true - /playwright-core@1.35.1: - resolution: {integrity: sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==} + /playwright-core@1.36.0: + resolution: {integrity: sha512-7RTr8P6YJPAqB+8j5ATGHqD6LvLLM39sYVNsslh78g8QeLcBs5750c6+msjrHUwwGt+kEbczBj1XB22WMwn+WA==} engines: {node: '>=16'} hasBin: true dev: true @@ -2759,8 +2760,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.0(prettier@3.0.0): + resolution: {integrity: sha512-Rna0sDPETA0KNhMHlN8wxKNgfSa8mTl2hPPAGxnbv6tUcHT6J4RQmQ8TLXyhB7Dm5Von4iHloBxTyClYM6wT0A==} engines: {node: '>=12.17.0'} peerDependencies: '@ianvs/prettier-plugin-sort-imports': '*' @@ -2768,7 +2769,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: '*' @@ -2811,12 +2812,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 @@ -3039,18 +3040,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: @@ -3180,7 +3181,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 get-intrinsic: 1.2.1 has-symbols: 1.0.3 internal-slot: 1.0.5 @@ -3194,7 +3195,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 dev: true /string.prototype.trimend@1.0.6: @@ -3202,7 +3203,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 dev: true /string.prototype.trimstart@1.0.6: @@ -3210,7 +3211,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 dev: true /strip-ansi@6.0.1: @@ -3308,7 +3309,7 @@ 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 @@ -3443,6 +3444,17 @@ packages: engines: {node: '>=8'} 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: @@ -3535,8 +3547,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 From f21f41c59d9c4d62423059fae98aa3d659b822b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Thu, 13 Jul 2023 14:14:40 +0200 Subject: [PATCH 05/29] feat(poc): fix thumbnail gallery --- components/grid/tile.tsx | 3 ++- components/product/gallery.tsx | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) 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 From 3d857f471efca3e540a33e0de55fbf0078b7d14a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Thu, 13 Jul 2023 14:15:10 +0200 Subject: [PATCH 06/29] feat(poc): use group id instead of parent id --- lib/shopware/transform.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/shopware/transform.ts b/lib/shopware/transform.ts index 3afef3a06..b9bfab8f5 100644 --- a/lib/shopware/transform.ts +++ b/lib/shopware/transform.ts @@ -242,9 +242,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]; @@ -252,13 +254,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 + }); + } } } } From 245127227e9df55e0a48336c88b959ccb18d8f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Thu, 13 Jul 2023 16:18:09 +0200 Subject: [PATCH 07/29] feat(poc): if parent change variant url --- lib/shopware/index.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/shopware/index.ts b/lib/shopware/index.ts index 7af3cfa6e..17d568725 100644 --- a/lib/shopware/index.ts +++ b/lib/shopware/index.ts @@ -116,10 +116,33 @@ export async function getSearchCollectionProducts(params?: { const searchCriteria = { ...criteria, ...sorting }; const res = await requestSearchCollectionProducts(searchCriteria); + res.elements = await changeVariantUrlToParentUrl(res); return res ? transformProducts(res) : []; } +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?: { collection: string; page?: number; @@ -152,6 +175,7 @@ export async function getCollectionProducts(params?: { : params?.defaultSearchCriteria; const productsCriteria = { ...criteria, ...sorting }; res = await requestCategoryProductsCollection(category, productsCriteria); + res.elements = await changeVariantUrlToParentUrl(res); } return res From 85e05847823058bfb4083ec9b59292819d2f8d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Thu, 13 Jul 2023 16:46:37 +0200 Subject: [PATCH 08/29] feat(poc): improve loading style --- .../(collection)/[...collection]/page.tsx | 13 +++++++--- app/search/loading.tsx | 26 ++++++++++++++----- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/app/search/(collection)/[...collection]/page.tsx b/app/search/(collection)/[...collection]/page.tsx index 0bce5ab50..7de68dae9 100644 --- a/app/search/(collection)/[...collection]/page.tsx +++ b/app/search/(collection)/[...collection]/page.tsx @@ -1,4 +1,3 @@ -import { getCollection, getCollectionProducts } from 'lib/shopware'; import { Metadata } from 'next'; import { notFound } from 'next/navigation'; @@ -7,6 +6,8 @@ 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'; @@ -49,7 +50,7 @@ export default async function CategoryPage({ {products.length === 0 ? (

{`No products found in this collection`}

) : ( -
+
@@ -57,8 +58,12 @@ export default async function CategoryPage({ -
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 ( + + ); + })} + +
+
+ +
+
); } From d24146d45e5ef2bd78d52be0900935cbfb3c9e68 Mon Sep 17 00:00:00 2001 From: mkucmus Date: Thu, 13 Jul 2023 11:40:21 +0200 Subject: [PATCH 09/29] fix: use referencedId for item id --- lib/shopware/index.ts | 67 ++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/lib/shopware/index.ts b/lib/shopware/index.ts index 17d568725..437a81752 100644 --- a/lib/shopware/index.ts +++ b/lib/shopware/index.ts @@ -1,44 +1,44 @@ import { - requestCart, - requestCategory, - requestCategoryList, - requestCategoryProductsCollection, - requestCrossSell, - requestNavigation, - requestProductsCollection, - requestSearchCollectionProducts, - requestSeoUrl, - requestSeoUrls +requestCart, +requestCategory, +requestCategoryList, +requestCategoryProductsCollection, +requestCrossSell, +requestNavigation, +requestProductsCollection, +requestSearchCollectionProducts, +requestSeoUrl, +requestSeoUrls } from './api'; import { ExtendedCategory, ExtendedProduct, ExtendedProductListingResult } from './api-extended'; import { - getDefaultCategoryCriteria, - getDefaultCategoryWithCmsCriteria, - getDefaultCrossSellingCriteria, - getDefaultProductCriteria, - getDefaultProductsCriteria, - getDefaultSearchProductsCriteria, - getDefaultSubCategoriesCriteria, - getSortingCriteria +getDefaultCategoryCriteria, +getDefaultCategoryWithCmsCriteria, +getDefaultCrossSellingCriteria, +getDefaultProductCriteria, +getDefaultProductsCriteria, +getDefaultSearchProductsCriteria, +getDefaultSubCategoriesCriteria, +getSortingCriteria } from './criteria'; import { - transformCollection, - transformHandle, - transformMenu, - transformPage, - transformProduct, - transformProducts, - transformSubCollection +transformCollection, +transformHandle, +transformMenu, +transformPage, +transformProduct, +transformProducts, +transformSubCollection } from './transform'; import { - ApiSchemas, - Cart, - CategoryListingResultSW, - Menu, - Page, - Product, - ProductListingCriteria, - StoreNavigationTypeSW +ApiSchemas, +Cart, +CategoryListingResultSW, +Menu, +Page, +Product, +ProductListingCriteria, +StoreNavigationTypeSW } from './types'; export async function getMenu(params?: { @@ -282,6 +282,7 @@ export async function getCart(): Promise { cartData.lineItems?.map((lineItem) => ({ id: lineItem.id || '', quantity: lineItem.quantity ?? 0, + id: lineItem.referencedId || '', cost: { totalAmount: { amount: (lineItem as any)?.price?.totalPrice || '', From d61acff7d15d068efeeea3ca3498581902a14c4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Fri, 14 Jul 2023 11:30:47 +0200 Subject: [PATCH 10/29] feat(poc): change types for cart component --- components/cart/delete-item-button.tsx | 2 +- components/cart/edit-item-quantity-button.tsx | 2 +- components/cart/modal.tsx | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) 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/modal.tsx b/components/cart/modal.tsx index bb14abf2a..ae6f19d59 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'; @@ -109,7 +109,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) ); From ed9d1dd2a18be204a08fd50fe10110968492bfbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Fri, 14 Jul 2023 11:34:31 +0200 Subject: [PATCH 11/29] feat(poc): update packages --- package.json | 14 ++--- pnpm-lock.yaml | 155 ++++++++++++++++++++++++------------------------- 2 files changed, 84 insertions(+), 85 deletions(-) diff --git a/package.json b/package.json index ed0046c91..4b7fa9153 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", @@ -24,7 +24,7 @@ "@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", @@ -34,20 +34,20 @@ "@playwright/test": "^1.36.0", "@tailwindcss/typography": "^0.5.9", "@types/node": "^20.4.2", - "@types/react": "18.2.14", + "@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-config-next": "^13.4.10", "eslint-config-prettier": "^8.8.0", "eslint-plugin-unicorn": "^47.0.0", "husky": "^8.0.3", "lint-staged": "^13.2.3", - "postcss": "^8.4.25", + "postcss": "^8.4.26", "prettier": "^3.0.0", "prettier-plugin-tailwindcss": "^0.4.0", - "tailwindcss": "^3.3.2", + "tailwindcss": "^3.3.3", "typescript": "5.1.6" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8d7e59991..37061ba9f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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 @@ -42,13 +42,13 @@ devDependencies: version: 1.36.0 '@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.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.7 version: 18.2.7 @@ -57,13 +57,13 @@ devDependencies: 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 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.44.0)(typescript@5.1.6) eslint-config-prettier: specifier: ^8.8.0 version: 8.8.0(eslint@8.44.0) @@ -77,8 +77,8 @@ 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: ^3.0.0 version: 3.0.0 @@ -86,8 +86,8 @@ devDependencies: specifier: ^0.4.0 version: 0.4.0(prettier@3.0.0) 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 @@ -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] @@ -400,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' @@ -409,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: @@ -419,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 @@ -441,11 +441,11 @@ packages: /@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 @@ -685,7 +685,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 @@ -697,7 +697,7 @@ packages: 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 @@ -763,7 +763,7 @@ packages: hasBin: true dependencies: caniuse-lite: 1.0.30001515 - electron-to-chromium: 1.4.459 + electron-to-chromium: 1.4.460 node-releases: 2.0.13 update-browserslist-db: 1.0.11(browserslist@4.21.9) dev: true @@ -1083,8 +1083,8 @@ packages: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: true - /electron-to-chromium@1.4.459: - resolution: {integrity: sha512-XXRS5NFv8nCrBL74Rm3qhJjA2VCsRFx0OjHKBMPI0otij56aun8UWiKTDABmd5/7GTR021pA4wivs+Ri6XCElg==} + /electron-to-chromium@1.4.460: + resolution: {integrity: sha512-kKiHnbrHME7z8E6AYaw0ehyxY5+hdaRmeUbjBO22LZMdqTYCO29EvF0T1cQ3pJ1RN5fyMcHl1Lmcsdt9WWJpJQ==} dev: true /emoji-regex@10.2.1: @@ -1197,8 +1197,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.44.0)(typescript@5.1.6): + resolution: {integrity: sha512-+JjcM6lQmFR5Mw0ORm9o1CR29+z/uajgSfYAPEGIBxOhTHBgCMs7ysuwi72o7LkMmA8E3N7/h09pSGZxs0s85g==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 typescript: '>=3.3.1' @@ -1206,7 +1206,7 @@ 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.62.0(eslint@8.44.0)(typescript@5.1.6) eslint: 8.44.0 @@ -2341,8 +2341,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: @@ -2359,7 +2359,7 @@ 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.30001515 @@ -2370,15 +2370,15 @@ 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 @@ -2669,29 +2669,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: @@ -2704,17 +2704,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 @@ -2746,8 +2746,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 @@ -3313,8 +3313,8 @@ packages: 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: @@ -3332,13 +3332,12 @@ 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 transitivePeerDependencies: From ab2959fa15344d22844d8d9d1584e36bd0079e6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Fri, 14 Jul 2023 11:37:42 +0200 Subject: [PATCH 12/29] feat(poc): fix cart type --- lib/shopware/index.ts | 69 +++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/lib/shopware/index.ts b/lib/shopware/index.ts index 437a81752..bd52877d8 100644 --- a/lib/shopware/index.ts +++ b/lib/shopware/index.ts @@ -1,44 +1,44 @@ import { -requestCart, -requestCategory, -requestCategoryList, -requestCategoryProductsCollection, -requestCrossSell, -requestNavigation, -requestProductsCollection, -requestSearchCollectionProducts, -requestSeoUrl, -requestSeoUrls + requestCart, + requestCategory, + requestCategoryList, + requestCategoryProductsCollection, + requestCrossSell, + requestNavigation, + requestProductsCollection, + requestSearchCollectionProducts, + requestSeoUrl, + requestSeoUrls } from './api'; import { ExtendedCategory, ExtendedProduct, ExtendedProductListingResult } from './api-extended'; import { -getDefaultCategoryCriteria, -getDefaultCategoryWithCmsCriteria, -getDefaultCrossSellingCriteria, -getDefaultProductCriteria, -getDefaultProductsCriteria, -getDefaultSearchProductsCriteria, -getDefaultSubCategoriesCriteria, -getSortingCriteria + getDefaultCategoryCriteria, + getDefaultCategoryWithCmsCriteria, + getDefaultCrossSellingCriteria, + getDefaultProductCriteria, + getDefaultProductsCriteria, + getDefaultSearchProductsCriteria, + getDefaultSubCategoriesCriteria, + getSortingCriteria } from './criteria'; import { -transformCollection, -transformHandle, -transformMenu, -transformPage, -transformProduct, -transformProducts, -transformSubCollection + transformCollection, + transformHandle, + transformMenu, + transformPage, + transformProduct, + transformProducts, + transformSubCollection } from './transform'; import { -ApiSchemas, -Cart, -CategoryListingResultSW, -Menu, -Page, -Product, -ProductListingCriteria, -StoreNavigationTypeSW + ApiSchemas, + Cart, + CategoryListingResultSW, + Menu, + Page, + Product, + ProductListingCriteria, + StoreNavigationTypeSW } from './types'; export async function getMenu(params?: { @@ -280,9 +280,8 @@ export async function getCart(): Promise { id: cartData.token || '', lines: cartData.lineItems?.map((lineItem) => ({ - id: lineItem.id || '', - quantity: lineItem.quantity ?? 0, id: lineItem.referencedId || '', + quantity: lineItem.quantity ?? 0, cost: { totalAmount: { amount: (lineItem as any)?.price?.totalPrice || '', From 88f0016a1c1fcef122b4066fb45003edbbbafb6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Fri, 14 Jul 2023 12:41:33 +0200 Subject: [PATCH 13/29] feat(poc): try fix 404 error on prod dep --- lib/shopware/api.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/shopware/api.ts b/lib/shopware/api.ts index 89c666674..35655a275 100644 --- a/lib/shopware/api.ts +++ b/lib/shopware/api.ts @@ -123,6 +123,16 @@ export async function requestSeoUrl( type: 'equals', field: 'seoPathInfo', value: handle + }, + { + type: 'equals', + field: 'seoPathInfo', + value: decodeURI(handle) + '/' + }, + { + type: 'equals', + field: 'seoPathInfo', + value: decodeURI(handle) } ] } @@ -145,4 +155,4 @@ export async function requestCrossSell( export async function requestCart() { return apiInstance.invoke('readCart get /checkout/cart?name', {}); -} \ No newline at end of file +} From f2bf4d34b74dba039389bf51d3efb324320a6465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Fri, 14 Jul 2023 12:49:26 +0200 Subject: [PATCH 14/29] feat(poc): try fix 404 error on prod dep --- lib/shopware/api.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/shopware/api.ts b/lib/shopware/api.ts index 35655a275..13892765f 100644 --- a/lib/shopware/api.ts +++ b/lib/shopware/api.ts @@ -127,12 +127,12 @@ export async function requestSeoUrl( { type: 'equals', field: 'seoPathInfo', - value: decodeURI(handle) + '/' + value: decodeURIComponent(handle) + '/' }, { type: 'equals', field: 'seoPathInfo', - value: decodeURI(handle) + value: decodeURIComponent(handle) } ] } From 09ecbe89e32abd24f40069ba842917bb953d43a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Fri, 14 Jul 2023 12:55:01 +0200 Subject: [PATCH 15/29] feat(poc): next dump try --- lib/shopware/api.ts | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/shopware/api.ts b/lib/shopware/api.ts index 13892765f..b89f33ca2 100644 --- a/lib/shopware/api.ts +++ b/lib/shopware/api.ts @@ -105,6 +105,7 @@ export async function requestSeoUrl( page: number = 1, limit: number = 1 ): Promise { + const fixedHandle = handle.replace('%2F', '/'); return await apiInstance.invoke('readSeoUrl post /seo-url', { page: page, limit: limit, @@ -117,22 +118,12 @@ export async function requestSeoUrl( { type: 'equals', field: 'seoPathInfo', - value: handle + '/' + value: fixedHandle + '/' }, { type: 'equals', field: 'seoPathInfo', - value: handle - }, - { - type: 'equals', - field: 'seoPathInfo', - value: decodeURIComponent(handle) + '/' - }, - { - type: 'equals', - field: 'seoPathInfo', - value: decodeURIComponent(handle) + value: fixedHandle } ] } From 179b92d5d8705d04c51795b5e8b7ce0aec5edf39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Fri, 14 Jul 2023 13:04:52 +0200 Subject: [PATCH 16/29] feat(poc): cahnge runtime for test --- app/(cms)/[...cms]/page.tsx | 8 ++----- app/(cms)/opengraph-image.tsx | 2 +- app/api/revalidate/route.ts | 2 +- app/opengraph-image.tsx | 2 +- app/page.tsx | 2 +- app/product/[...handle]/page.tsx | 2 +- .../(collection)/[...collection]/page.tsx | 2 +- app/search/(collection)/opengraph-image.tsx | 2 +- app/search/page.tsx | 23 ++++++++++--------- lib/shopware/api.ts | 5 ++-- 10 files changed, 23 insertions(+), 27 deletions(-) diff --git a/app/(cms)/[...cms]/page.tsx b/app/(cms)/[...cms]/page.tsx index b7f6d8e72..8afa7edeb 100644 --- a/app/(cms)/[...cms]/page.tsx +++ b/app/(cms)/[...cms]/page.tsx @@ -4,15 +4,11 @@ import Prose from 'components/prose'; import { getPage } from 'lib/shopware'; import { notFound } from 'next/navigation'; -export const runtime = 'edge'; +export const runtime = 'nodejs'; 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/(cms)/opengraph-image.tsx b/app/(cms)/opengraph-image.tsx index db45917a7..9f954dde6 100644 --- a/app/(cms)/opengraph-image.tsx +++ b/app/(cms)/opengraph-image.tsx @@ -1,7 +1,7 @@ import OpengraphImage from 'components/opengraph-image'; import { getPage } from 'lib/shopware'; -export const runtime = 'edge'; +export const runtime = 'nodejs'; export default async function Image({ params }: { params: { page: string } }) { const page = await getPage(params.page); diff --git a/app/api/revalidate/route.ts b/app/api/revalidate/route.ts index 94ddfff9b..da250294c 100644 --- a/app/api/revalidate/route.ts +++ b/app/api/revalidate/route.ts @@ -3,7 +3,7 @@ import { revalidateTag } from 'next/cache'; import { headers } from 'next/headers'; import { NextRequest, NextResponse } from 'next/server'; -export const runtime = 'edge'; +export const runtime = 'nodejs'; // We always need to respond with a 200 status code to Shopify, // otherwise it will continue to retry the request. diff --git a/app/opengraph-image.tsx b/app/opengraph-image.tsx index 23762cbdd..29e3f703a 100644 --- a/app/opengraph-image.tsx +++ b/app/opengraph-image.tsx @@ -1,6 +1,6 @@ import OpengraphImage from 'components/opengraph-image'; -export const runtime = 'edge'; +export const runtime = 'nodejs'; export default async function Image() { return await OpengraphImage(); diff --git a/app/page.tsx b/app/page.tsx index 5f357726a..e1bd0d998 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -3,7 +3,7 @@ import { ThreeItemGrid } from 'components/grid/three-items'; import Footer from 'components/layout/footer'; import { Suspense } from 'react'; -export const runtime = 'edge'; +export const runtime = 'nodejs'; export const metadata = { description: 'High-performance ecommerce store built with Next.js, Vercel, and Shopware.', diff --git a/app/product/[...handle]/page.tsx b/app/product/[...handle]/page.tsx index 573fe475b..6f7a76400 100644 --- a/app/product/[...handle]/page.tsx +++ b/app/product/[...handle]/page.tsx @@ -13,7 +13,7 @@ import { HIDDEN_PRODUCT_TAG } from 'lib/constants'; import { getProduct, getProductRecommendations } from 'lib/shopware'; import { Image } from 'lib/shopware/types'; -export const runtime = 'edge'; +export const runtime = 'nodejs'; export async function generateMetadata({ params diff --git a/app/search/(collection)/[...collection]/page.tsx b/app/search/(collection)/[...collection]/page.tsx index 7de68dae9..c4d1950a5 100644 --- a/app/search/(collection)/[...collection]/page.tsx +++ b/app/search/(collection)/[...collection]/page.tsx @@ -10,7 +10,7 @@ import Pagination from 'components/collection/pagination'; import { getCollection, getCollectionProducts } from 'lib/shopware'; import { defaultSort, sorting } from 'lib/constants'; -export const runtime = 'edge'; +export const runtime = 'nodejs'; export async function generateMetadata({ params diff --git a/app/search/(collection)/opengraph-image.tsx b/app/search/(collection)/opengraph-image.tsx index 98cd40853..d1e08d1f7 100644 --- a/app/search/(collection)/opengraph-image.tsx +++ b/app/search/(collection)/opengraph-image.tsx @@ -1,7 +1,7 @@ import OpengraphImage from 'components/opengraph-image'; import { getCollection } from 'lib/shopware'; -export const runtime = 'edge'; +export const runtime = 'nodejs'; export default async function Image({ params }: { params: { collection: string } }) { const collection = await getCollection(params.collection); diff --git a/app/search/page.tsx b/app/search/page.tsx index a8940ac44..5200149ec 100644 --- a/app/search/page.tsx +++ b/app/search/page.tsx @@ -4,7 +4,7 @@ import FilterList from 'components/layout/search/filter'; import { defaultSort, sorting } from 'lib/constants'; import { getSearchCollectionProducts } from 'lib/shopware'; -export const runtime = 'edge'; +export const runtime = 'nodejs'; export const metadata = { title: 'Search', @@ -23,16 +23,17 @@ export default async function SearchPage({ const resultsText = products.length > 1 ? 'results' : 'result'; return ( - <>{searchValue && products.length === 0 ? ( -
-

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

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

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

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

@@ -40,7 +41,7 @@ export default async function SearchPage({ "{searchValue}"

) : null} -

Good place to add other suggest search terms ;)

+

Good place to add other suggest search terms ;)

diff --git a/lib/shopware/api.ts b/lib/shopware/api.ts index b89f33ca2..81985dc5f 100644 --- a/lib/shopware/api.ts +++ b/lib/shopware/api.ts @@ -105,7 +105,6 @@ export async function requestSeoUrl( page: number = 1, limit: number = 1 ): Promise { - const fixedHandle = handle.replace('%2F', '/'); return await apiInstance.invoke('readSeoUrl post /seo-url', { page: page, limit: limit, @@ -118,12 +117,12 @@ export async function requestSeoUrl( { type: 'equals', field: 'seoPathInfo', - value: fixedHandle + '/' + value: handle + '/' }, { type: 'equals', field: 'seoPathInfo', - value: fixedHandle + value: handle } ] } From 1bfbd903cc235714b8c758f9e1d688358ba4fe40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Fri, 14 Jul 2023 13:08:06 +0200 Subject: [PATCH 17/29] feat(poc): change runtime for test --- app/(cms)/opengraph-image.tsx | 2 +- app/opengraph-image.tsx | 2 +- app/search/(collection)/opengraph-image.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/(cms)/opengraph-image.tsx b/app/(cms)/opengraph-image.tsx index 9f954dde6..db45917a7 100644 --- a/app/(cms)/opengraph-image.tsx +++ b/app/(cms)/opengraph-image.tsx @@ -1,7 +1,7 @@ import OpengraphImage from 'components/opengraph-image'; import { getPage } from 'lib/shopware'; -export const runtime = 'nodejs'; +export const runtime = 'edge'; export default async function Image({ params }: { params: { page: string } }) { const page = await getPage(params.page); diff --git a/app/opengraph-image.tsx b/app/opengraph-image.tsx index 29e3f703a..23762cbdd 100644 --- a/app/opengraph-image.tsx +++ b/app/opengraph-image.tsx @@ -1,6 +1,6 @@ import OpengraphImage from 'components/opengraph-image'; -export const runtime = 'nodejs'; +export const runtime = 'edge'; export default async function Image() { return await OpengraphImage(); diff --git a/app/search/(collection)/opengraph-image.tsx b/app/search/(collection)/opengraph-image.tsx index d1e08d1f7..98cd40853 100644 --- a/app/search/(collection)/opengraph-image.tsx +++ b/app/search/(collection)/opengraph-image.tsx @@ -1,7 +1,7 @@ import OpengraphImage from 'components/opengraph-image'; import { getCollection } from 'lib/shopware'; -export const runtime = 'nodejs'; +export const runtime = 'edge'; export default async function Image({ params }: { params: { collection: string } }) { const collection = await getCollection(params.collection); From eacf390afae16f3863dafba061817709f9a364f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Fri, 14 Jul 2023 13:36:05 +0200 Subject: [PATCH 18/29] feat(poc): revert changes --- app/(cms)/[...cms]/page.tsx | 2 +- app/api/revalidate/route.ts | 2 +- app/page.tsx | 2 +- app/product/[...handle]/page.tsx | 2 +- app/search/(collection)/[...collection]/page.tsx | 2 +- app/search/page.tsx | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/(cms)/[...cms]/page.tsx b/app/(cms)/[...cms]/page.tsx index 8afa7edeb..0a89ab4f8 100644 --- a/app/(cms)/[...cms]/page.tsx +++ b/app/(cms)/[...cms]/page.tsx @@ -4,7 +4,7 @@ import Prose from 'components/prose'; import { getPage } from 'lib/shopware'; import { notFound } from 'next/navigation'; -export const runtime = 'nodejs'; +export const runtime = 'edge'; export const revalidate = 43200; // 12 hours in seconds diff --git a/app/api/revalidate/route.ts b/app/api/revalidate/route.ts index da250294c..94ddfff9b 100644 --- a/app/api/revalidate/route.ts +++ b/app/api/revalidate/route.ts @@ -3,7 +3,7 @@ import { revalidateTag } from 'next/cache'; import { headers } from 'next/headers'; import { NextRequest, NextResponse } from 'next/server'; -export const runtime = 'nodejs'; +export const runtime = 'edge'; // We always need to respond with a 200 status code to Shopify, // otherwise it will continue to retry the request. diff --git a/app/page.tsx b/app/page.tsx index e1bd0d998..5f357726a 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -3,7 +3,7 @@ import { ThreeItemGrid } from 'components/grid/three-items'; import Footer from 'components/layout/footer'; import { Suspense } from 'react'; -export const runtime = 'nodejs'; +export const runtime = 'edge'; export const metadata = { description: 'High-performance ecommerce store built with Next.js, Vercel, and Shopware.', diff --git a/app/product/[...handle]/page.tsx b/app/product/[...handle]/page.tsx index 6f7a76400..573fe475b 100644 --- a/app/product/[...handle]/page.tsx +++ b/app/product/[...handle]/page.tsx @@ -13,7 +13,7 @@ import { HIDDEN_PRODUCT_TAG } from 'lib/constants'; import { getProduct, getProductRecommendations } from 'lib/shopware'; import { Image } from 'lib/shopware/types'; -export const runtime = 'nodejs'; +export const runtime = 'edge'; export async function generateMetadata({ params diff --git a/app/search/(collection)/[...collection]/page.tsx b/app/search/(collection)/[...collection]/page.tsx index c4d1950a5..7de68dae9 100644 --- a/app/search/(collection)/[...collection]/page.tsx +++ b/app/search/(collection)/[...collection]/page.tsx @@ -10,7 +10,7 @@ import Pagination from 'components/collection/pagination'; import { getCollection, getCollectionProducts } from 'lib/shopware'; import { defaultSort, sorting } from 'lib/constants'; -export const runtime = 'nodejs'; +export const runtime = 'edge'; export async function generateMetadata({ params diff --git a/app/search/page.tsx b/app/search/page.tsx index 5200149ec..13b1ac2f2 100644 --- a/app/search/page.tsx +++ b/app/search/page.tsx @@ -4,7 +4,7 @@ import FilterList from 'components/layout/search/filter'; import { defaultSort, sorting } from 'lib/constants'; import { getSearchCollectionProducts } from 'lib/shopware'; -export const runtime = 'nodejs'; +export const runtime = 'edge'; export const metadata = { title: 'Search', From 47291853e3b7b9e2d682755aaab287ca10f6fa53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Mon, 17 Jul 2023 08:44:21 +0200 Subject: [PATCH 19/29] feat(poc): add log for api client --- app/sitemap.ts | 4 +- components/carousel.tsx | 4 +- components/cart/index.tsx | 2 +- components/layout/footer.tsx | 31 +++-- lib/shopware/api-extended.ts | 9 +- lib/shopware/api.ts | 184 ++++++++++++++++----------- lib/shopware/types.ts | 8 +- package.json | 8 +- pnpm-lock.yaml | 238 ++++++++++++++++++++--------------- 9 files changed, 289 insertions(+), 199 deletions(-) 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; -} \ No newline at end of file +} diff --git a/components/layout/footer.tsx b/components/layout/footer.tsx index dc17c763d..47404d475 100644 --- a/components/layout/footer.tsx +++ b/components/layout/footer.tsx @@ -1,4 +1,5 @@ import Link from 'next/link'; +import Image from 'next/image'; import GitHubIcon from 'components/icons/github'; import LogoIcon from 'components/icons/logo'; @@ -25,12 +26,8 @@ export default async function Footer() {
{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/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 81985dc5f..b77d1227d 100644 --- a/lib/shopware/api.ts +++ b/lib/shopware/api.ts @@ -34,115 +34,155 @@ export type ApiReturnType = RequestRetu export async function requestNavigation( type: StoreNavigationTypeSW, depth: number -): Promise { - return await apiInstance.invoke( - 'readNavigation post /navigation/{activeId}/{rootId} sw-include-seo-urls', - { - activeId: type, - rootId: type, - depth: depth - } - ); +): Promise { + try { + return await apiInstance.invoke( + 'readNavigation post /navigation/{activeId}/{rootId} sw-include-seo-urls', + { + activeId: type, + rootId: type, + depth: depth + } + ); + } catch (error) { + console.log(error); + } } export async function requestCategory( categoryId: string, criteria?: Partial -): Promise { - return await apiInstance.invoke('readCategory post /category/{navigationId}?slots', { - navigationId: categoryId, - criteria - }); +): Promise { + try { + return await apiInstance.invoke('readCategory post /category/{navigationId}?slots', { + navigationId: categoryId, + criteria + }); + } catch (error) { + console.log(error); + } } export async function requestCategoryList( criteria: Partial -): Promise { - return await apiInstance.invoke('readCategoryList post /category', criteria); +): Promise { + try { + return await apiInstance.invoke('readCategoryList post /category', criteria); + } catch (error) { + console.log(error); + } } export async function requestProductsCollection( criteria: Partial -): Promise { - return await apiInstance.invoke('readProduct post /product', criteria); +): Promise { + try { + return await apiInstance.invoke('readProduct post /product', criteria); + } catch (error) { + console.log(error); + } } export async function requestCategoryProductsCollection( categoryId: string, criteria: Partial -): Promise { - return await apiInstance.invoke('readProductListing post /product-listing/{categoryId}', { - ...criteria, - categoryId: categoryId - }); +): Promise { + try { + return await apiInstance.invoke('readProductListing post /product-listing/{categoryId}', { + ...criteria, + categoryId: categoryId + }); + } catch (error) { + console.log(error); + } } export async function requestSearchCollectionProducts( criteria?: Partial -): Promise { - return await apiInstance.invoke('searchPage post /search', { - search: encodeURIComponent(criteria?.query || ''), - ...criteria - }); +): Promise { + try { + return await apiInstance.invoke('searchPage post /search', { + search: encodeURIComponent(criteria?.query || ''), + ...criteria + }); + } catch (error) { + console.log(error); + } } export async function requestSeoUrls(routeName: RouteNames, page: number = 1, limit: number = 100) { - return await apiInstance.invoke('readSeoUrl post /seo-url', { - page: page, - limit: limit, - filter: [ - { - type: 'equals', - field: 'routeName', - value: routeName - } - ] - }); + try { + return await apiInstance.invoke('readSeoUrl post /seo-url', { + page: page, + limit: limit, + filter: [ + { + type: 'equals', + field: 'routeName', + value: routeName + } + ] + }); + } catch (error) { + console.log(error); + } } export async function requestSeoUrl( handle: string, page: number = 1, limit: number = 1 -): Promise { - return await apiInstance.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 { + return await apiInstance.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 + } + ] + } + ] + }); + } catch (error) { + console.log(error); + } } export async function requestCrossSell( productId: string, criteria?: Partial -): Promise { - return await apiInstance.invoke( - 'readProductCrossSellings post /product/{productId}/cross-selling', - { - productId: productId, - ...criteria - } - ); +): Promise { + try { + return await apiInstance.invoke( + 'readProductCrossSellings post /product/{productId}/cross-selling', + { + productId: productId, + ...criteria + } + ); + } catch (error) { + console.log(error); + } } export async function requestCart() { - return apiInstance.invoke('readCart get /checkout/cart?name', {}); + try { + return apiInstance.invoke('readCart get /checkout/cart?name', {}); + } catch (error) { + console.log(error); + } } diff --git a/lib/shopware/types.ts b/lib/shopware/types.ts index 4e4331d80..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 = { @@ -127,4 +131,4 @@ export type CartItem = { }[]; product: Product; }; -}; \ No newline at end of file +}; diff --git a/package.json b/package.json index 4b7fa9153..e58c6ff57 100644 --- a/package.json +++ b/package.json @@ -31,22 +31,22 @@ "react-paginate": "^8.2.0" }, "devDependencies": { - "@playwright/test": "^1.36.0", + "@playwright/test": "^1.36.1", "@tailwindcss/typography": "^0.5.9", "@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": "^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.26", "prettier": "^3.0.0", - "prettier-plugin-tailwindcss": "^0.4.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 37061ba9f..e114d524b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,8 +38,8 @@ dependencies: devDependencies: '@playwright/test': - specifier: ^1.36.0 - version: 1.36.0 + specifier: ^1.36.1 + version: 1.36.1 '@tailwindcss/typography': specifier: ^0.5.9 version: 0.5.9(tailwindcss@3.3.3) @@ -59,17 +59,17 @@ devDependencies: specifier: ^10.4.14 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.10 - version: 13.4.10(eslint@8.44.0)(typescript@5.1.6) + 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 @@ -83,8 +83,8 @@ devDependencies: specifier: ^3.0.0 version: 3.0.0 prettier-plugin-tailwindcss: - specifier: ^0.4.0 - version: 0.4.0(prettier@3.0.0) + specifier: ^0.4.1 + version: 0.4.1(prettier@3.0.0) tailwindcss: specifier: ^3.3.3 version: 3.3.3 @@ -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 @@ -359,13 +359,13 @@ packages: tslib: 2.6.0 dev: true - /@playwright/test@1.36.0: - resolution: {integrity: sha512-yN+fvMYtiyLFDCQos+lWzoX4XW3DNuaxjBu68G0lkgLgC6BP+m/iTxJQoSicz/x2G5EsrqlZTqTIP9sTgLQerg==} + /@playwright/test@1.36.1: + resolution: {integrity: sha512-YK7yGWK0N3C2QInPU6iaf/L3N95dlGdbsezLya4n0ZCh3IL7VgPGxC6Gnznh9ApWdOmkJeleT2kMTcWPRZvzqg==} engines: {node: '>=16'} hasBin: true dependencies: '@types/node': 20.4.2 - playwright-core: 1.36.0 + playwright-core: 1.36.1 optionalDependencies: fsevents: 2.3.2 dev: true @@ -454,7 +454,7 @@ packages: /@types/scheduler@0.16.3: resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} - /@typescript-eslint/parser@5.62.0(eslint@8.44.0)(typescript@5.1.6): + /@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: @@ -468,7 +468,7 @@ packages: '@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 @@ -636,7 +636,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.3 + es-abstract: 1.22.1 get-intrinsic: 1.2.1 is-string: 1.0.7 dev: true @@ -652,7 +652,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.3 + es-abstract: 1.22.1 es-shim-unscopables: 1.0.0 dev: true @@ -662,7 +662,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.3 + es-abstract: 1.22.1 es-shim-unscopables: 1.0.0 dev: true @@ -671,11 +671,23 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.3 + 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 @@ -693,7 +705,7 @@ packages: postcss: ^8.1.0 dependencies: browserslist: 4.21.9 - caniuse-lite: 1.0.30001515 + caniuse-lite: 1.0.30001516 fraction.js: 4.2.0 normalize-range: 0.1.2 picocolors: 1.0.0 @@ -762,8 +774,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001515 - electron-to-chromium: 1.4.460 + 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 @@ -808,8 +820,8 @@ packages: resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} dev: false - /caniuse-lite@1.0.30001515: - resolution: {integrity: sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA==} + /caniuse-lite@1.0.30001516: + resolution: {integrity: sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==} /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -1083,8 +1095,8 @@ packages: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: true - /electron-to-chromium@1.4.460: - resolution: {integrity: sha512-kKiHnbrHME7z8E6AYaw0ehyxY5+hdaRmeUbjBO22LZMdqTYCO29EvF0T1cQ3pJ1RN5fyMcHl1Lmcsdt9WWJpJQ==} + /electron-to-chromium@1.4.461: + resolution: {integrity: sha512-1JkvV2sgEGTDXjdsaQCeSwYYuhLRphRpc+g6EHTFELJXEiznLt3/0pZ9JuAOQ5p2rI3YxKTbivtvajirIfhrEQ==} dev: true /emoji-regex@10.2.1: @@ -1113,11 +1125,12 @@ packages: is-arrayish: 0.2.1 dev: true - /es-abstract@1.21.3: - resolution: {integrity: sha512-ZU4miiY1j3sGPFLJ34VJXEqhpmL+HGByCinGHv4HC+Fxl2fI2Z4yR6tl0mORnDr6PA8eihWo4LmSWDbvhALckg==} + /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 @@ -1144,10 +1157,13 @@ 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 @@ -1197,7 +1213,7 @@ packages: engines: {node: '>=10'} dev: true - /eslint-config-next@13.4.10(eslint@8.44.0)(typescript@5.1.6): + /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 @@ -1208,27 +1224,27 @@ packages: dependencies: '@next/eslint-plugin-next': 13.4.10 '@rushstack/eslint-patch': 1.3.2 - '@typescript-eslint/parser': 5.62.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.62.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.62.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: @@ -1241,7 +1257,7 @@ packages: - supports-color dev: true - /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.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: @@ -1250,9 +1266,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.62.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.62.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 @@ -1265,7 +1281,7 @@ packages: - supports-color dev: true - /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.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: @@ -1286,16 +1302,16 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.62.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.62.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.62.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: @@ -1305,15 +1321,15 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.62.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.62.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 @@ -1328,7 +1344,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: @@ -1343,7 +1359,7 @@ 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 @@ -1353,16 +1369,16 @@ packages: 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: @@ -1372,7 +1388,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 @@ -1386,17 +1402,17 @@ packages: 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 @@ -1406,13 +1422,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.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 @@ -1424,12 +1439,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 @@ -1442,9 +1457,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 @@ -1454,7 +1469,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 @@ -1466,14 +1480,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 @@ -1642,7 +1655,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.3 + es-abstract: 1.22.1 functions-have-names: 1.2.3 dev: true @@ -2086,6 +2099,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 @@ -2362,7 +2379,7 @@ packages: '@next/env': 13.4.10 '@swc/helpers': 0.5.1 busboy: 1.6.0 - caniuse-lite: 1.0.30001515 + caniuse-lite: 1.0.30001516 postcss: 8.4.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -2459,7 +2476,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.3 + es-abstract: 1.22.1 dev: true /object.fromentries@2.0.6: @@ -2468,14 +2485,14 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.3 + 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.3 + es-abstract: 1.22.1 dev: true /object.values@1.1.6: @@ -2484,7 +2501,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.3 + es-abstract: 1.22.1 dev: true /ofetch@1.1.1: @@ -2658,8 +2675,8 @@ packages: engines: {node: '>= 6'} dev: true - /playwright-core@1.36.0: - resolution: {integrity: sha512-7RTr8P6YJPAqB+8j5ATGHqD6LvLLM39sYVNsslh78g8QeLcBs5750c6+msjrHUwwGt+kEbczBj1XB22WMwn+WA==} + /playwright-core@1.36.1: + resolution: {integrity: sha512-7+tmPuMcEW4xeCL9cp9KxmYpQYHKkyjwoXRnoeTowaeNat8PoBMk/HwCYhqkH2fRkshfKEOiVus/IhID2Pg8kg==} engines: {node: '>=16'} hasBin: true dev: true @@ -2760,8 +2777,8 @@ packages: engines: {node: '>= 0.8.0'} dev: true - /prettier-plugin-tailwindcss@0.4.0(prettier@3.0.0): - resolution: {integrity: sha512-Rna0sDPETA0KNhMHlN8wxKNgfSa8mTl2hPPAGxnbv6tUcHT6J4RQmQ8TLXyhB7Dm5Von4iHloBxTyClYM6wT0A==} + /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': '*' @@ -3004,6 +3021,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: @@ -3012,12 +3039,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'} @@ -3181,7 +3202,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.3 + es-abstract: 1.22.1 get-intrinsic: 1.2.1 has-symbols: 1.0.3 internal-slot: 1.0.5 @@ -3195,7 +3216,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.3 + es-abstract: 1.22.1 dev: true /string.prototype.trimend@1.0.6: @@ -3203,7 +3224,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.3 + es-abstract: 1.22.1 dev: true /string.prototype.trimstart@1.0.6: @@ -3211,7 +3232,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.3 + es-abstract: 1.22.1 dev: true /strip-ansi@6.0.1: @@ -3272,8 +3293,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: @@ -3339,7 +3360,7 @@ packages: postcss-nested: 6.0.1(postcss@8.4.26) postcss-selector-parser: 6.0.13 resolve: 1.22.2 - sucrase: 3.32.0 + sucrase: 3.33.0 transitivePeerDependencies: - ts-node dev: true @@ -3443,6 +3464,25 @@ 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'} From 67e5c46b9b74dd4d1b897717d7f04fb58cdc660d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Mon, 17 Jul 2023 08:53:24 +0200 Subject: [PATCH 20/29] feat(poc): add log for api client --- components/cart/index.tsx | 4 + lib/shopware/index.ts | 198 ++++++++++++++++++++------------------ 2 files changed, 108 insertions(+), 94 deletions(-) diff --git a/components/cart/index.tsx b/components/cart/index.tsx index 2b1add5d9..bbb760d47 100644 --- a/components/cart/index.tsx +++ b/components/cart/index.tsx @@ -7,6 +7,10 @@ export default async function Cart() { let cartIdUpdated = true; const cart = await getCart(); + if (!cart) { + return null; + } + if (cartId !== cart.id) { cartIdUpdated = true; } diff --git a/lib/shopware/index.ts b/lib/shopware/index.ts index bd52877d8..40c5982e9 100644 --- a/lib/shopware/index.ts +++ b/lib/shopware/index.ts @@ -73,17 +73,19 @@ export async function getPage(handle: string | []): Promise { 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]; } } @@ -115,10 +117,12 @@ export async function getSearchCollectionProducts(params?: { const sorting = getSortingCriteria(params?.sortKey, params?.reverse); const searchCriteria = { ...criteria, ...sorting }; - const res = await requestSearchCollectionProducts(searchCriteria); - res.elements = await changeVariantUrlToParentUrl(res); + const search = await requestSearchCollectionProducts(searchCriteria); + if (search) { + search.elements = await changeVariantUrlToParentUrl(search); + } - return res ? transformProducts(res) : []; + return search ? transformProducts(search) : []; } export async function changeVariantUrlToParentUrl( @@ -151,7 +155,7 @@ 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 sorting = getSortingCriteria(params?.sortKey, params?.reverse); @@ -174,23 +178,27 @@ export async function getCollectionProducts(params?: { ? getDefaultProductsCriteria(params?.page) : params?.defaultSearchCriteria; const productsCriteria = { ...criteria, ...sorting }; - res = await requestCategoryProductsCollection(category, productsCriteria); - res.elements = await changeVariantUrlToParentUrl(res); + 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'], cms: boolean = false -): Promise { +): Promise { const criteria = cms ? getDefaultCategoryWithCmsCriteria() : getDefaultCategoryCriteria(); - const resCategory = await requestCategory(seoUrl.foreignKey, criteria); - - return resCategory; + return await requestCategory(seoUrl.foreignKey, criteria); } // This function is only used for generateMetadata at app/search/(collection)/[...collection]/page.tsx @@ -198,23 +206,25 @@ export async function getCollection(handle: string | []) { const collectionName = transformHandle(handle); const seoUrlElement = await getFirstSeoUrlElement(collectionName); if (seoUrlElement) { - const resCategory = await getCategory(seoUrlElement); + const category = await getCategory(seoUrlElement); const path = seoUrlElement.seoPathInfo ?? ''; - const collection = transformCollection(seoUrlElement, resCategory); + if (category) { + const collection = transformCollection(seoUrlElement, category); - return { - ...collection, - path: `/search/${path}` - }; + return { + ...collection, + path: `/search/${path}` + }; + } } } 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 }) ); } @@ -257,74 +267,74 @@ export async function getProductRecommendations(productId: string): Promise { +export async function getCart(): Promise { const cartData = await requestCart(); - - // @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' - }, - 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 ?? 0, - cost: { - totalAmount: { - amount: (lineItem as any)?.price?.totalPrice || '', - currencyCode: 'EUR' - } + 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: [], - 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 - } + 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; + } } From 6e09bf12c4c847d1bd54938189f3b6d059edd617 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Mon, 17 Jul 2023 09:10:09 +0200 Subject: [PATCH 21/29] feat(poc): remove router from layout navbar --- components/layout/navbar/search.tsx | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/components/layout/navbar/search.tsx b/components/layout/navbar/search.tsx index fff895f43..c11aa2eff 100644 --- a/components/layout/navbar/search.tsx +++ b/components/layout/navbar/search.tsx @@ -1,28 +1,29 @@ 'use client'; -import { useRouter, useSearchParams } from 'next/navigation'; +// import { useRouter, useSearchParams } from 'next/navigation'; import SearchIcon from 'components/icons/search'; -import { createUrl } from 'lib/utils'; +// import { createUrl } from 'lib/utils'; export default function Search() { - const router = useRouter(); - const searchParams = useSearchParams(); + //const router = useRouter(); + //const searchParams = useSearchParams(); function onSubmit(e: React.FormEvent) { e.preventDefault(); const val = e.target as HTMLFormElement; const search = val.search as HTMLInputElement; - const newParams = new URLSearchParams(searchParams.toString()); + console.log(`Search:` + search); + // const newParams = new URLSearchParams(searchParams.toString()); - if (search.value) { - newParams.set('q', search.value); - } else { - newParams.delete('q'); - } + // if (search.value) { + // newParams.set('q', search.value); + // } else { + // newParams.delete('q'); + // } - router.push(createUrl('/search', newParams)); + // router.push(createUrl('/search', newParams)); } return ( @@ -35,7 +36,7 @@ export default function Search() { name="search" placeholder="Search for products..." autoComplete="off" - defaultValue={searchParams?.get('q') || ''} + // defaultValue={searchParams?.get('q') || ''} className="w-full px-4 py-2 text-black dark:bg-black dark:text-gray-100" />
From ea259358b2b21bf08e665ab29759a1767fa0d5e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Mon, 17 Jul 2023 09:22:11 +0200 Subject: [PATCH 22/29] feat(poc): revert and change filter --- components/layout/navbar/search.tsx | 24 ++++++++++++------------ lib/shopware/api.ts | 24 +++++++----------------- 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/components/layout/navbar/search.tsx b/components/layout/navbar/search.tsx index c11aa2eff..bf4d12230 100644 --- a/components/layout/navbar/search.tsx +++ b/components/layout/navbar/search.tsx @@ -1,13 +1,13 @@ 'use client'; -// import { useRouter, useSearchParams } from 'next/navigation'; +import { useRouter, useSearchParams } from 'next/navigation'; import SearchIcon from 'components/icons/search'; -// import { createUrl } from 'lib/utils'; +import { createUrl } from 'lib/utils'; export default function Search() { - //const router = useRouter(); - //const searchParams = useSearchParams(); + const router = useRouter(); + const searchParams = useSearchParams(); function onSubmit(e: React.FormEvent) { e.preventDefault(); @@ -15,15 +15,15 @@ export default function Search() { const val = e.target as HTMLFormElement; const search = val.search as HTMLInputElement; console.log(`Search:` + search); - // const newParams = new URLSearchParams(searchParams.toString()); + const newParams = new URLSearchParams(searchParams.toString()); - // if (search.value) { - // newParams.set('q', search.value); - // } else { - // newParams.delete('q'); - // } + if (search.value) { + newParams.set('q', search.value); + } else { + newParams.delete('q'); + } - // router.push(createUrl('/search', newParams)); + router.push(createUrl('/search', newParams)); } return ( @@ -36,7 +36,7 @@ export default function Search() { name="search" placeholder="Search for products..." autoComplete="off" - // defaultValue={searchParams?.get('q') || ''} + defaultValue={searchParams?.get('q') || ''} className="w-full px-4 py-2 text-black dark:bg-black dark:text-gray-100" />
diff --git a/lib/shopware/api.ts b/lib/shopware/api.ts index b77d1227d..98f0d32ec 100644 --- a/lib/shopware/api.ts +++ b/lib/shopware/api.ts @@ -134,29 +134,19 @@ export async function requestSeoUrl( limit: number = 1 ): Promise { try { - return await apiInstance.invoke('readSeoUrl post /seo-url', { + const criteria = { page: page, limit: limit, filter: [ { - type: 'multi', - // @ts-ignore - operator: 'or', - queries: [ - { - type: 'equals', - field: 'seoPathInfo', - value: handle + '/' - }, - { - type: 'equals', - field: 'seoPathInfo', - value: handle - } - ] + type: 'contains', + field: 'seoPathInfo', + value: handle } ] - }); + }; + console.log(criteria); + return await apiInstance.invoke('readSeoUrl post /seo-url', criteria); } catch (error) { console.log(error); } From cbf9e7fd38c9a2f3325d599382e8db73e5ebb3ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Mon, 17 Jul 2023 11:01:12 +0200 Subject: [PATCH 23/29] feat(poc): change log to error --- lib/shopware/api.ts | 73 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/lib/shopware/api.ts b/lib/shopware/api.ts index 98f0d32ec..cfa4f9c3a 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 { ExtendedCategory, @@ -45,7 +45,12 @@ export async function requestNavigation( } ); } catch (error) { - console.log(error); + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } } } @@ -59,7 +64,12 @@ export async function requestCategory( criteria }); } catch (error) { - console.log(error); + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } } } @@ -69,7 +79,12 @@ export async function requestCategoryList( try { return await apiInstance.invoke('readCategoryList post /category', criteria); } catch (error) { - console.log(error); + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } } } @@ -79,7 +94,12 @@ export async function requestProductsCollection( try { return await apiInstance.invoke('readProduct post /product', criteria); } catch (error) { - console.log(error); + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } } } @@ -93,7 +113,12 @@ export async function requestCategoryProductsCollection( categoryId: categoryId }); } catch (error) { - console.log(error); + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } } } @@ -106,7 +131,12 @@ export async function requestSearchCollectionProducts( ...criteria }); } catch (error) { - console.log(error); + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } } } @@ -124,7 +154,12 @@ export async function requestSeoUrls(routeName: RouteNames, page: number = 1, li ] }); } catch (error) { - console.log(error); + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } } } @@ -145,10 +180,14 @@ export async function requestSeoUrl( } ] }; - console.log(criteria); return await apiInstance.invoke('readSeoUrl post /seo-url', criteria); } catch (error) { - console.log(error); + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } } } @@ -165,7 +204,12 @@ export async function requestCrossSell( } ); } catch (error) { - console.log(error); + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } } } @@ -173,6 +217,11 @@ export async function requestCart() { try { return apiInstance.invoke('readCart get /checkout/cart?name', {}); } catch (error) { - console.log(error); + if (error instanceof ApiClientError) { + console.error(error); + console.error('Details:', error.details); + } else { + console.error('==>', error); + } } } From cc073977938858d9ad648bdf03849e2e6debde4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Mon, 17 Jul 2023 11:13:05 +0200 Subject: [PATCH 24/29] feat(poc): add decodeURIComponent --- lib/shopware/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/shopware/index.ts b/lib/shopware/index.ts index 40c5982e9..fb2d1e4a2 100644 --- a/lib/shopware/index.ts +++ b/lib/shopware/index.ts @@ -53,7 +53,7 @@ export async function getMenu(params?: { } export async function getPage(handle: string | []): Promise { - const pageHandle = transformHandle(handle).replace('cms/', ''); + const pageHandle = decodeURIComponent(transformHandle(handle)).replace('cms/', ''); const seoUrlElement = await getFirstSeoUrlElement(pageHandle); if (seoUrlElement) { const category = await getCategory(seoUrlElement); @@ -157,7 +157,7 @@ export async function getCollectionProducts(params?: { }): Promise<{ products: Product[]; total: number; limit: number }> { 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 !== '') { @@ -203,7 +203,7 @@ export async function getCategory( // 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 collectionName = decodeURIComponent(transformHandle(handle)); const seoUrlElement = await getFirstSeoUrlElement(collectionName); if (seoUrlElement) { const category = await getCategory(seoUrlElement); @@ -235,7 +235,7 @@ 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)); const seoUrlElement = await getFirstSeoUrlElement(productHandle); if (seoUrlElement) { From 2ee6394d279f51c80e4dd92bc2a316a285385f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Mon, 17 Jul 2023 11:42:15 +0200 Subject: [PATCH 25/29] feat(poc): test something --- lib/shopware/api.ts | 3 ++- lib/shopware/index.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/shopware/api.ts b/lib/shopware/api.ts index cfa4f9c3a..377517fe9 100644 --- a/lib/shopware/api.ts +++ b/lib/shopware/api.ts @@ -169,6 +169,7 @@ export async function requestSeoUrl( limit: number = 1 ): Promise { try { + const testing = handle.replace('cms/', '').replace('product/', '').replace('search/', ''); const criteria = { page: page, limit: limit, @@ -176,7 +177,7 @@ export async function requestSeoUrl( { type: 'contains', field: 'seoPathInfo', - value: handle + value: testing } ] }; diff --git a/lib/shopware/index.ts b/lib/shopware/index.ts index fb2d1e4a2..7858d9fa5 100644 --- a/lib/shopware/index.ts +++ b/lib/shopware/index.ts @@ -53,7 +53,7 @@ export async function getMenu(params?: { } export async function getPage(handle: string | []): Promise { - const pageHandle = decodeURIComponent(transformHandle(handle)).replace('cms/', ''); + const pageHandle = decodeURIComponent(transformHandle(handle)); const seoUrlElement = await getFirstSeoUrlElement(pageHandle); if (seoUrlElement) { const category = await getCategory(seoUrlElement); From 744243c3d864019ed755046a4160a52f2513725a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Mon, 17 Jul 2023 12:00:48 +0200 Subject: [PATCH 26/29] feat(poc): test something --- lib/shopware/api.ts | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/lib/shopware/api.ts b/lib/shopware/api.ts index 377517fe9..46d924035 100644 --- a/lib/shopware/api.ts +++ b/lib/shopware/api.ts @@ -168,20 +168,53 @@ export async function requestSeoUrl( page: number = 1, limit: number = 1 ): Promise { + console.log(handle); try { - const testing = handle.replace('cms/', '').replace('product/', '').replace('search/', ''); - const criteria = { + const FirstCriteria = { + page: page, + limit: limit, + filter: [ + { + type: 'multi', + // @ts-ignore + operator: 'or', + queries: [ + { + type: 'equals', + field: 'seoPathInfo', + value: handle + '/' + }, + { + type: 'equals', + field: 'seoPathInfo', + value: handle + } + ] + } + ] + }; + // @ts-ignore + const firstResult = await apiInstance.invoke('readSeoUrl post /seo-url', FirstCriteria); + if (firstResult.total && firstResult.total > 0) { + return firstResult; + } + + const lastPart = handle.split('/').pop() + ''; + console.log(lastPart); + + const SecondCriteria = { page: page, limit: limit, filter: [ { type: 'contains', field: 'seoPathInfo', - value: testing + value: lastPart } ] }; - return await apiInstance.invoke('readSeoUrl post /seo-url', criteria); + + return await apiInstance.invoke('readSeoUrl post /seo-url', SecondCriteria); } catch (error) { if (error instanceof ApiClientError) { console.error(error); From 46e003196ff9a7a352294afc090a512c3691d90f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Mon, 17 Jul 2023 15:56:32 +0200 Subject: [PATCH 27/29] feat(poc): seoUrls yes or no env --- .env.example | 1 + components/carousel.tsx | 6 ++- components/grid/three-items.tsx | 6 ++- lib/shopware/api.ts | 26 +-------- lib/shopware/index.ts | 93 +++++++++++++++++++++------------ lib/shopware/transform.ts | 65 +++++++++++++++-------- 6 files changed, 115 insertions(+), 82 deletions(-) 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/components/carousel.tsx b/components/carousel.tsx index 45b845ef5..d30ac01a9 100644 --- a/components/carousel.tsx +++ b/components/carousel.tsx @@ -3,8 +3,12 @@ import Image from 'next/image'; import Link from 'next/link'; export async function Carousel() { + const collectionName = + `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true' + ? 'Summer-BBQ/Hidden-Carousel-Category' + : 'ff7bf3c59f1342a685844fbf8fdf9dc8'; const { products } = await getCollectionProducts({ - collection: 'Summer-BBQ/Hidden-Carousel-Category' + collection: collectionName }); if (!products?.length) return null; diff --git a/components/grid/three-items.tsx b/components/grid/three-items.tsx index a7d2b9010..723bc3095 100644 --- a/components/grid/three-items.tsx +++ b/components/grid/three-items.tsx @@ -37,8 +37,12 @@ function ThreeItemGridItem({ export async function ThreeItemGrid() { // Collections that start with `hidden-*` are hidden from the search page. + const collectionName = + `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true' + ? '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/lib/shopware/api.ts b/lib/shopware/api.ts index 46d924035..193cf5af8 100644 --- a/lib/shopware/api.ts +++ b/lib/shopware/api.ts @@ -168,15 +168,13 @@ export async function requestSeoUrl( page: number = 1, limit: number = 1 ): Promise { - console.log(handle); try { - const FirstCriteria = { + const criteriaSeoUrls = { page: page, limit: limit, filter: [ { type: 'multi', - // @ts-ignore operator: 'or', queries: [ { @@ -194,27 +192,7 @@ export async function requestSeoUrl( ] }; // @ts-ignore - const firstResult = await apiInstance.invoke('readSeoUrl post /seo-url', FirstCriteria); - if (firstResult.total && firstResult.total > 0) { - return firstResult; - } - - const lastPart = handle.split('/').pop() + ''; - console.log(lastPart); - - const SecondCriteria = { - page: page, - limit: limit, - filter: [ - { - type: 'contains', - field: 'seoPathInfo', - value: lastPart - } - ] - }; - - return await apiInstance.invoke('readSeoUrl post /seo-url', SecondCriteria); + return await apiInstance.invoke('readSeoUrl post /seo-url', criteriaSeoUrls); } catch (error) { if (error instanceof ApiClientError) { console.error(error); diff --git a/lib/shopware/index.ts b/lib/shopware/index.ts index 7858d9fa5..a35478929 100644 --- a/lib/shopware/index.ts +++ b/lib/shopware/index.ts @@ -40,6 +40,7 @@ import { ProductListingCriteria, StoreNavigationTypeSW } from './types'; +const useSeoUrls = `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true'; export async function getMenu(params?: { type?: StoreNavigationTypeSW; @@ -53,21 +54,26 @@ export async function getMenu(params?: { } export async function getPage(handle: string | []): Promise { - const pageHandle = decodeURIComponent(transformHandle(handle)); - const seoUrlElement = await getFirstSeoUrlElement(pageHandle); - if (seoUrlElement) { - const category = await getCategory(seoUrlElement); + let seoUrlElement; + let pageIdOrHandle = decodeURIComponent(transformHandle(handle)).replace('cms/', ''); - if (!category) { - console.log('[getPage] Did not found any category with page handle:', pageHandle); + if (useSeoUrls) { + seoUrlElement = await getFirstSeoUrlElement(pageIdOrHandle); + if (seoUrlElement) { + pageIdOrHandle = seoUrlElement.foreignKey; } - return category ? transformPage(seoUrlElement, category) : undefined; + if (!seoUrlElement) { + console.log('[getPage] Did not found any seoUrl element with page handle:', pageIdOrHandle); + } } - if (!seoUrlElement) { - console.log('[getPage] Did not found any seoUrl element with page handle:', pageHandle); + 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( @@ -91,17 +97,22 @@ export async function getFirstProduct(productId: string): Promise { const criteria = cms ? getDefaultCategoryWithCmsCriteria() : getDefaultCategoryCriteria(); - return await requestCategory(seoUrl.foreignKey, criteria); + 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 = decodeURIComponent(transformHandle(handle)); - const seoUrlElement = await getFirstSeoUrlElement(collectionName); - if (seoUrlElement) { - const category = await getCategory(seoUrlElement); - const path = seoUrlElement.seoPathInfo ?? ''; - if (category) { - const collection = transformCollection(seoUrlElement, category); + let path; + let seoUrlElement; + let categoryIdOrHandle = decodeURIComponent(transformHandle(handle)); - return { - ...collection, - path: `/search/${path}` - }; + if (useSeoUrls) { + 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, + path: `/search/${path}` + }; + } } export async function getProductSeoUrls() { @@ -236,15 +259,19 @@ export async function getProduct(handle: string | []): Promise 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,18 +95,22 @@ 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 }; } @@ -116,7 +126,10 @@ export function transformSubCollection( .filter((item) => item.visible) .filter((item) => item.type !== 'link') .map((item) => { - const handle = item.seoUrls ? findHandle(item.seoUrls, parentCollectionName) : undefined; + const handle = + item.seoUrls && `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true' + ? findHandle(item.seoUrls, parentCollectionName) + : item.id; if (handle) { collection.push({ handle: handle, @@ -183,15 +196,21 @@ export function transformProducts(res: ExtendedProductListingResult): Product[] } export function transformProduct(item: ExtendedProduct): Product { + const useSeoUrls = `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true'; const productOptions = transformOptions(item); const productVariants = transformVariants(item); - return { - id: item.id ?? '', - path: + let path = item.id ? item.id : ''; + if (useSeoUrls) { + 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 From b56e4828e3d4419523d9756cdf37e18b0657cfa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Mon, 17 Jul 2023 16:32:26 +0200 Subject: [PATCH 28/29] feat(poc): fix parent id --- components/cart/add-to-cart.tsx | 2 +- components/product/variant-selector.tsx | 2 +- lib/shopware/index.ts | 2 +- lib/shopware/transform.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/cart/add-to-cart.tsx b/components/cart/add-to-cart.tsx index eecee848e..3cc403315 100644 --- a/components/cart/add-to-cart.tsx +++ b/components/cart/add-to-cart.tsx @@ -6,7 +6,7 @@ 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 { ProductVariant } from 'lib/shopware/types'; export function AddToCart({ variants, 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/index.ts b/lib/shopware/index.ts index a35478929..d915a3617 100644 --- a/lib/shopware/index.ts +++ b/lib/shopware/index.ts @@ -129,7 +129,7 @@ export async function getSearchCollectionProducts(params?: { const searchCriteria = { ...criteria, ...sorting }; const search = await requestSearchCollectionProducts(searchCriteria); - if (search) { + if (useSeoUrls && search) { search.elements = await changeVariantUrlToParentUrl(search); } diff --git a/lib/shopware/transform.ts b/lib/shopware/transform.ts index 36f45f556..32d1fc248 100644 --- a/lib/shopware/transform.ts +++ b/lib/shopware/transform.ts @@ -200,7 +200,7 @@ export function transformProduct(item: ExtendedProduct): Product { const productOptions = transformOptions(item); const productVariants = transformVariants(item); - let path = item.id ? item.id : ''; + let path = item.parentId ?? item.id ?? ''; if (useSeoUrls) { path = item.seoUrls && item.seoUrls.length > 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo From a66652fc82e36edbba27294598d7ac135c2f44ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Wed, 19 Jul 2023 09:50:46 +0200 Subject: [PATCH 29/29] feat(poc): add helpers --- components/carousel.tsx | 8 +++---- components/grid/three-items.tsx | 8 +++---- components/layout/navbar/mobile-menu.tsx | 2 +- components/layout/navbar/search.tsx | 1 - lib/shopware/api.ts | 10 ++++----- lib/shopware/helpers.ts | 25 ++++++++++++++++++++++ lib/shopware/index.ts | 18 ++++++++-------- lib/shopware/transform.ts | 27 +++++++++++------------- 8 files changed, 59 insertions(+), 40 deletions(-) create mode 100644 lib/shopware/helpers.ts diff --git a/components/carousel.tsx b/components/carousel.tsx index d30ac01a9..e8a080c5b 100644 --- a/components/carousel.tsx +++ b/components/carousel.tsx @@ -1,12 +1,12 @@ import { getCollectionProducts } from 'lib/shopware'; +import { isSeoUrls } from 'lib/shopware/helpers'; import Image from 'next/image'; import Link from 'next/link'; export async function Carousel() { - const collectionName = - `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true' - ? 'Summer-BBQ/Hidden-Carousel-Category' - : 'ff7bf3c59f1342a685844fbf8fdf9dc8'; + const collectionName = isSeoUrls() + ? 'Summer-BBQ/Hidden-Carousel-Category' + : 'ff7bf3c59f1342a685844fbf8fdf9dc8'; const { products } = await getCollectionProducts({ collection: collectionName }); diff --git a/components/grid/three-items.tsx b/components/grid/three-items.tsx index 723bc3095..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,10 +38,9 @@ function ThreeItemGridItem({ export async function ThreeItemGrid() { // Collections that start with `hidden-*` are hidden from the search page. - const collectionName = - `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true' - ? 'Summer-BBQ/Hidden-Category' - : '4ab73c06d90d4a5cb312209a64480d87'; + const collectionName = isSeoUrls() + ? 'Summer-BBQ/Hidden-Category' + : '4ab73c06d90d4a5cb312209a64480d87'; const { products: homepageItems } = await getCollectionProducts({ collection: collectionName }); 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/navbar/search.tsx b/components/layout/navbar/search.tsx index bf4d12230..fff895f43 100644 --- a/components/layout/navbar/search.tsx +++ b/components/layout/navbar/search.tsx @@ -14,7 +14,6 @@ export default function Search() { const val = e.target as HTMLFormElement; const search = val.search as HTMLInputElement; - console.log(`Search:` + search); const newParams = new URLSearchParams(searchParams.toString()); if (search.value) { diff --git a/lib/shopware/api.ts b/lib/shopware/api.ts index 193cf5af8..5283390a5 100644 --- a/lib/shopware/api.ts +++ b/lib/shopware/api.ts @@ -15,14 +15,12 @@ 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'; const apiInstance = createAPIClient({ - baseURL: domainSW, - accessToken: accessTokenSW, - apiType: 'store-api' + baseURL: getStoreDomainWithApiType(), + accessToken: getAccessToken(), + apiType: getApiType() }); // reimport operations return types to use it in application 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 d915a3617..ee82563b7 100644 --- a/lib/shopware/index.ts +++ b/lib/shopware/index.ts @@ -40,7 +40,7 @@ import { ProductListingCriteria, StoreNavigationTypeSW } from './types'; -const useSeoUrls = `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true'; +import { isSeoUrls } from 'lib/shopware/helpers'; export async function getMenu(params?: { type?: StoreNavigationTypeSW; @@ -57,7 +57,7 @@ export async function getPage(handle: string | []): Promise { let seoUrlElement; let pageIdOrHandle = decodeURIComponent(transformHandle(handle)).replace('cms/', ''); - if (useSeoUrls) { + if (isSeoUrls()) { seoUrlElement = await getFirstSeoUrlElement(pageIdOrHandle); if (seoUrlElement) { pageIdOrHandle = seoUrlElement.foreignKey; @@ -103,7 +103,7 @@ export async function getSubCollections(collection: string) { const parentCollectionName = Array.isArray(collection) && collection[0] ? collection[0] : undefined; - if (useSeoUrls) { + if (isSeoUrls()) { const seoUrlElement = await getFirstSeoUrlElement(collectionName); if (seoUrlElement) { criteria = getDefaultSubCategoriesCriteria(seoUrlElement.foreignKey); @@ -129,7 +129,7 @@ export async function getSearchCollectionProducts(params?: { const searchCriteria = { ...criteria, ...sorting }; const search = await requestSearchCollectionProducts(searchCriteria); - if (useSeoUrls && search) { + if (isSeoUrls() && search) { search.elements = await changeVariantUrlToParentUrl(search); } @@ -171,7 +171,7 @@ export async function getCollectionProducts(params?: { const collectionName = decodeURIComponent(transformHandle(params?.collection ?? '')); const sorting = getSortingCriteria(params?.sortKey, params?.reverse); - if (useSeoUrls && !category && collectionName !== '') { + if (isSeoUrls() && !category && collectionName !== '') { const seoUrlElement = await getFirstSeoUrlElement(collectionName); if (seoUrlElement) { category = seoUrlElement.foreignKey; @@ -184,8 +184,8 @@ export async function getCollectionProducts(params?: { } } - if (!useSeoUrls) { - category = params?.collection ?? undefined; + if (!isSeoUrls()) { + category = collectionName ?? undefined; } if (category) { @@ -222,7 +222,7 @@ export async function getCollection(handle: string | []) { let seoUrlElement; let categoryIdOrHandle = decodeURIComponent(transformHandle(handle)); - if (useSeoUrls) { + if (isSeoUrls()) { seoUrlElement = await getFirstSeoUrlElement(categoryIdOrHandle); if (seoUrlElement) { categoryIdOrHandle = seoUrlElement.foreignKey; @@ -261,7 +261,7 @@ export async function getProduct(handle: string | []): Promise 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 ?? ''; + 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 { @@ -127,9 +127,7 @@ export function transformSubCollection( .filter((item) => item.type !== 'link') .map((item) => { const handle = - item.seoUrls && `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true' - ? findHandle(item.seoUrls, parentCollectionName) - : item.id; + isSeoUrls() && item.seoUrls ? findHandle(item.seoUrls, parentCollectionName) : item.id; if (handle) { collection.push({ handle: handle, @@ -196,12 +194,11 @@ export function transformProducts(res: ExtendedProductListingResult): Product[] } export function transformProduct(item: ExtendedProduct): Product { - const useSeoUrls = `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true'; const productOptions = transformOptions(item); const productVariants = transformVariants(item); let path = item.parentId ?? item.id ?? ''; - if (useSeoUrls) { + if (isSeoUrls()) { path = item.seoUrls && item.seoUrls.length > 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo ? item.seoUrls[0].seoPathInfo