@faststore/core 3.0.16 → 3.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +3 -3
- package/.next/cache/.tsbuildinfo +1 -1
- package/.next/cache/config.json +3 -3
- package/.next/cache/eslint/.cache_1gneedd +1 -1
- package/.next/cache/webpack/client-production/0.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/0.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/next-minimal-server.js.nft.json +1 -1
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.js +1 -1
- package/.next/prerender-manifest.json +1 -1
- package/.next/routes-manifest.json +1 -1
- package/.next/server/chunks/242.js +1 -1
- package/.next/server/chunks/640.js +1 -1
- package/.next/server/chunks/646.js +2 -2
- package/.next/server/chunks/659.js +2 -2
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/pages/404.js +1 -1
- package/.next/server/pages/500.js +1 -1
- package/.next/server/pages/[...slug].js +1 -1
- package/.next/server/pages/[slug]/p.js +1 -1
- package/.next/server/pages/account.js +1 -1
- package/.next/server/pages/api/graphql.js +1 -1
- package/.next/server/pages/checkout.js +1 -1
- package/.next/server/pages/en-US/404.html +2 -2
- package/.next/server/pages/en-US/500.html +2 -2
- package/.next/server/pages/en-US/account.html +2 -2
- package/.next/server/pages/en-US/checkout.html +2 -2
- package/.next/server/pages/en-US/login.html +2 -2
- package/.next/server/pages/en-US/s.html +2 -2
- package/.next/server/pages/en-US.html +2 -2
- package/.next/server/pages/index.js +1 -1
- package/.next/server/pages/login.js +1 -1
- package/.next/server/pages/s.js +1 -1
- package/.next/server/pages-manifest.json +1 -1
- package/.next/static/chunks/pages/{[...slug]-84926ee31c8f6fee.js → [...slug]-bcaf61b01157d8cb.js} +1 -1
- package/.next/static/{RX_p788L2keTWhdlgySlF → rG9HjHHbItuqOEnXtbNZ5}/_buildManifest.js +1 -1
- package/.next/trace +91 -91
- package/.turbo/turbo-test.log +9 -9
- package/cms/faststore/content-types.json +14 -1
- package/package.json +3 -3
- package/src/components/templates/ProductListingPage/ProductListing.tsx +4 -4
- package/src/components/templates/ProductListingPage/ProductListingPage.tsx +1 -1
- package/src/pages/[...slug].tsx +5 -24
- package/src/server/cms/index.ts +1 -1
- package/src/server/cms/plp.ts +74 -0
- package/src/utils/utilities.ts +53 -0
- /package/.next/static/{RX_p788L2keTWhdlgySlF → rG9HjHHbItuqOEnXtbNZ5}/_ssgManifest.js +0 -0
package/.turbo/turbo-test.log
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
$ jest
|
|
2
|
-
PASS test/server/index.test.ts (21.
|
|
2
|
+
PASS test/server/index.test.ts (21.291 s)
|
|
3
3
|
FastStore GraphQL Layer
|
|
4
4
|
@faststore/api
|
|
5
|
-
✓ should return a valid GraphQL schema (
|
|
6
|
-
✓ should return a valid GraphQL schema contain all expected types (
|
|
5
|
+
✓ should return a valid GraphQL schema (10 ms)
|
|
6
|
+
✓ should return a valid GraphQL schema contain all expected types (7 ms)
|
|
7
7
|
✓ should return a valid GraphQL schema contain all expected queries (2 ms)
|
|
8
8
|
✓ should return a valid GraphQL schema contain all expected mutations
|
|
9
9
|
VTEX API Extension
|
|
10
|
-
✓ getTypeDefsFromFolder function should return an Array (
|
|
10
|
+
✓ getTypeDefsFromFolder function should return an Array (31 ms)
|
|
11
11
|
Third Party API Extension
|
|
12
|
-
✓ getTypeDefsFromFolder function should return an Array (
|
|
12
|
+
✓ getTypeDefsFromFolder function should return an Array (8 ms)
|
|
13
13
|
Final Schema after merging
|
|
14
|
-
✓ should return a valid merged GraphQL schema (
|
|
14
|
+
✓ should return a valid merged GraphQL schema (51 ms)
|
|
15
15
|
Envelop
|
|
16
|
-
✓ should exist with its plugins (
|
|
17
|
-
✓ should handle options and execute (
|
|
16
|
+
✓ should exist with its plugins (58 ms)
|
|
17
|
+
✓ should handle options and execute (174 ms)
|
|
18
18
|
|
|
19
19
|
Test Suites: 1 passed, 1 total
|
|
20
20
|
Tests: 9 passed, 9 total
|
|
21
21
|
Snapshots: 0 total
|
|
22
|
-
Time: 21.
|
|
22
|
+
Time: 21.381 s
|
|
23
23
|
Ran all test suites.
|
|
@@ -129,11 +129,24 @@
|
|
|
129
129
|
"id": "plp",
|
|
130
130
|
"name": "Product List Page",
|
|
131
131
|
"scopes": ["plp"],
|
|
132
|
-
"isSingleton": true,
|
|
133
132
|
"configurationSchemaSets": [
|
|
134
133
|
{
|
|
135
134
|
"name": "Settings",
|
|
136
135
|
"configurations": [
|
|
136
|
+
{
|
|
137
|
+
"name": "template",
|
|
138
|
+
"schema": {
|
|
139
|
+
"title": "Template",
|
|
140
|
+
"type": "object",
|
|
141
|
+
"properties": {
|
|
142
|
+
"value": {
|
|
143
|
+
"title": "PLP template value (e.g. Slug: /department/category/subcategory)",
|
|
144
|
+
"type": "string",
|
|
145
|
+
"description": "PLP slug template (e.g. /office or /office/chairs) representing the /department/category/subcategory template). If this field is left empty, the generic PLP template will be applied."
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
},
|
|
137
150
|
{
|
|
138
151
|
"name": "productGallery",
|
|
139
152
|
"schema": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faststore/core",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.20",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": "vtex/faststore",
|
|
6
6
|
"browserslist": "supports es6-module and not dead",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@envelop/graphql-jit": "^1.1.1",
|
|
40
40
|
"@envelop/parser-cache": "^2.2.0",
|
|
41
41
|
"@envelop/validation-cache": "^2.2.0",
|
|
42
|
-
"@faststore/api": "^3.0.
|
|
42
|
+
"@faststore/api": "^3.0.20",
|
|
43
43
|
"@faststore/components": "^3.0.7",
|
|
44
44
|
"@faststore/graphql-utils": "^3.0.13",
|
|
45
45
|
"@faststore/sdk": "^3.0.7",
|
|
@@ -128,5 +128,5 @@
|
|
|
128
128
|
"node": "18.19.0",
|
|
129
129
|
"yarn": "1.19.1"
|
|
130
130
|
},
|
|
131
|
-
"gitHead": "
|
|
131
|
+
"gitHead": "c75d1f53d7efeae52483db94d9e66ddbebb8de5f"
|
|
132
132
|
}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
+
import { useSearch } from '@faststore/sdk'
|
|
1
2
|
import type { ServerCollectionPageQueryQuery } from '@generated/graphql'
|
|
3
|
+
import deepmerge from 'deepmerge'
|
|
2
4
|
import { OverriddenDefaultBreadcrumb as Breadcrumb } from 'src/components/sections/Breadcrumb/OverriddenDefaultBreadcrumb'
|
|
3
5
|
import { OverriddenDefaultHero as Hero } from 'src/components/sections/Hero/OverriddenDefaultHero'
|
|
4
6
|
import { OverriddenDefaultProductGallery as ProductGallery } from 'src/components/sections/ProductGallery/OverriddenDefaultProductGallery'
|
|
5
7
|
import { OverriddenDefaultProductShelf as ProductShelf } from 'src/components/sections/ProductShelf/OverriddenDefaultProductShelf'
|
|
6
8
|
import ScrollToTopButton from 'src/components/sections/ScrollToTopButton'
|
|
7
9
|
import { ITEMS_PER_PAGE } from 'src/constants'
|
|
8
|
-
import deepmerge from 'deepmerge'
|
|
9
|
-
import { useSearch } from '@faststore/sdk'
|
|
10
10
|
|
|
11
11
|
import type { ComponentType } from 'react'
|
|
12
12
|
import RenderSections from 'src/components/cms/RenderSections'
|
|
13
13
|
import CUSTOM_COMPONENTS from 'src/customizations/src/components'
|
|
14
|
-
import { PLPContentType } from 'src/server/cms'
|
|
14
|
+
import { PLPContentType } from 'src/server/cms/plp'
|
|
15
15
|
|
|
16
|
+
import PageProvider, { PLPContext } from 'src/sdk/overrides/PageProvider'
|
|
16
17
|
import {
|
|
17
18
|
useCreateUseGalleryPage,
|
|
18
19
|
UseGalleryPageContext,
|
|
19
20
|
} from 'src/sdk/product/usePageProductsQuery'
|
|
20
21
|
import { useProductGalleryQuery } from 'src/sdk/product/useProductGalleryQuery'
|
|
21
|
-
import PageProvider, { PLPContext } from 'src/sdk/overrides/PageProvider'
|
|
22
22
|
|
|
23
23
|
export type ProductListingPageProps = {
|
|
24
24
|
data: ServerCollectionPageQueryQuery
|
|
@@ -12,7 +12,7 @@ import type { ServerCollectionPageQueryQuery } from '@generated/graphql'
|
|
|
12
12
|
import { ITEMS_PER_PAGE } from 'src/constants'
|
|
13
13
|
import { useApplySearchState } from 'src/sdk/search/state'
|
|
14
14
|
|
|
15
|
-
import { PLPContentType } from 'src/server/cms'
|
|
15
|
+
import { PLPContentType } from 'src/server/cms/plp'
|
|
16
16
|
|
|
17
17
|
import storeConfig from '../../../../faststore.config'
|
|
18
18
|
import ProductListing from './ProductListing'
|
package/src/pages/[...slug].tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { isNotFoundError } from '@faststore/api'
|
|
2
|
-
import storeConfig from 'faststore.config'
|
|
3
2
|
import type { GetStaticPaths, GetStaticProps } from 'next'
|
|
4
3
|
|
|
5
4
|
import { gql } from '@generated'
|
|
@@ -22,7 +21,8 @@ import LandingPage, {
|
|
|
22
21
|
import ProductListingPage, {
|
|
23
22
|
ProductListingPageProps,
|
|
24
23
|
} from 'src/components/templates/ProductListingPage'
|
|
25
|
-
import {
|
|
24
|
+
import { PageContentType } from 'src/server/cms'
|
|
25
|
+
import { getPLP, PLPContentType } from 'src/server/cms/plp'
|
|
26
26
|
|
|
27
27
|
type BaseProps = {
|
|
28
28
|
globalSections: GlobalSectionsData
|
|
@@ -101,7 +101,7 @@ export const getStaticProps: GetStaticProps<
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
const [{ data, errors = [] }] = await Promise.all([
|
|
104
|
+
const [{ data, errors = [] }, cmsPage] = await Promise.all([
|
|
105
105
|
execute<
|
|
106
106
|
ServerCollectionPageQueryQueryVariables,
|
|
107
107
|
ServerCollectionPageQueryQuery
|
|
@@ -109,28 +109,9 @@ export const getStaticProps: GetStaticProps<
|
|
|
109
109
|
variables: { slug },
|
|
110
110
|
operation: query,
|
|
111
111
|
}),
|
|
112
|
+
getPLP(slug, previewData),
|
|
112
113
|
])
|
|
113
114
|
|
|
114
|
-
let pageData
|
|
115
|
-
|
|
116
|
-
if (storeConfig.cms.data) {
|
|
117
|
-
const cmsData = JSON.parse(storeConfig.cms.data)
|
|
118
|
-
const page = cmsData['plp'][0]
|
|
119
|
-
|
|
120
|
-
if (page) {
|
|
121
|
-
pageData = await getPage<PLPContentType>({
|
|
122
|
-
contentType: 'plp',
|
|
123
|
-
documentId: page.documentId,
|
|
124
|
-
versionId: page.versionId,
|
|
125
|
-
})
|
|
126
|
-
}
|
|
127
|
-
} else {
|
|
128
|
-
pageData = await getPage<PLPContentType>({
|
|
129
|
-
...(previewData?.contentType === 'plp' ? previewData : null),
|
|
130
|
-
contentType: 'plp',
|
|
131
|
-
})
|
|
132
|
-
}
|
|
133
|
-
|
|
134
115
|
const notFound = errors.find(isNotFoundError)
|
|
135
116
|
|
|
136
117
|
if (notFound) {
|
|
@@ -147,7 +128,7 @@ export const getStaticProps: GetStaticProps<
|
|
|
147
128
|
return {
|
|
148
129
|
props: {
|
|
149
130
|
data,
|
|
150
|
-
page:
|
|
131
|
+
page: cmsPage,
|
|
151
132
|
globalSections: await globalSectionsPromise,
|
|
152
133
|
type: 'plp',
|
|
153
134
|
key: slug,
|
package/src/server/cms/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ContentData, ContentTypeOptions, Locator } from '@vtex/client-cms'
|
|
2
2
|
import ClientCMS from '@vtex/client-cms'
|
|
3
|
+
|
|
3
4
|
import MissingContentError from 'src/sdk/error/MissingContentError'
|
|
4
5
|
import MultipleContentError from 'src/sdk/error/MultipleContentError'
|
|
5
6
|
import config from '../../../faststore.config'
|
|
@@ -20,7 +21,6 @@ type ProductGallerySettings = {
|
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
export type PLPContentType = ContentData & ProductGallerySettings
|
|
24
24
|
export type SearchContentType = ContentData & ProductGallerySettings
|
|
25
25
|
|
|
26
26
|
export type PageContentType = ContentData & {
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { ContentData, Locator } from '@vtex/client-cms'
|
|
2
|
+
import MissingContentError from 'src/sdk/error/MissingContentError'
|
|
3
|
+
import { findBestPLPTemplate } from 'src/utils/utilities'
|
|
4
|
+
import config from '../../../faststore.config'
|
|
5
|
+
import { Options, getCMSPage, getPage } from '../cms'
|
|
6
|
+
|
|
7
|
+
type PLPSettings = {
|
|
8
|
+
settings: {
|
|
9
|
+
template?: {
|
|
10
|
+
value?: string
|
|
11
|
+
}
|
|
12
|
+
productGallery: {
|
|
13
|
+
itemsPerPage: number
|
|
14
|
+
sortBySelection: string
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type PLPfromCmsEnvData = {
|
|
20
|
+
documentId: string
|
|
21
|
+
versionId: string
|
|
22
|
+
} & PLPSettings
|
|
23
|
+
|
|
24
|
+
export type PLPContentType = ContentData & PLPSettings
|
|
25
|
+
|
|
26
|
+
export const getPLP = async (slug: string, previewData: Locator) => {
|
|
27
|
+
if (config.cms.data) {
|
|
28
|
+
const cmsData = JSON.parse(config.cms.data)
|
|
29
|
+
const allPLPsFromCmsEnvData: PLPfromCmsEnvData[] = cmsData['plp']
|
|
30
|
+
|
|
31
|
+
return await getPLPFromCmsEnvData(`/${slug}/p`, allPLPsFromCmsEnvData, {
|
|
32
|
+
...(previewData?.contentType === 'plp' ? previewData : null),
|
|
33
|
+
contentType: 'plp',
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return (await getPLPFromCms(`/${slug}/p`, {
|
|
38
|
+
...(previewData?.contentType === 'plp' ? previewData : null),
|
|
39
|
+
contentType: 'plp',
|
|
40
|
+
})) as PLPContentType
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const getPLPFromCmsEnvData = async (
|
|
44
|
+
slug: string,
|
|
45
|
+
allPLPsFromCMSData: PLPfromCmsEnvData[],
|
|
46
|
+
options: Options
|
|
47
|
+
): Promise<PLPContentType> => {
|
|
48
|
+
const pages: PLPfromCmsEnvData[] = allPLPsFromCMSData ?? []
|
|
49
|
+
|
|
50
|
+
if (!pages[0]) {
|
|
51
|
+
throw new MissingContentError(options)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const template = findBestPLPTemplate(pages, slug)
|
|
55
|
+
|
|
56
|
+
return getPage<PLPContentType>({
|
|
57
|
+
contentType: 'plp',
|
|
58
|
+
documentId: template.documentId as string,
|
|
59
|
+
versionId: template.versionId,
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const getPLPFromCms = async (
|
|
64
|
+
slug: string,
|
|
65
|
+
options: Options
|
|
66
|
+
): Promise<Partial<PLPContentType>> => {
|
|
67
|
+
const pages = (await getCMSPage(options)).data
|
|
68
|
+
|
|
69
|
+
if (!pages[0]) {
|
|
70
|
+
throw new MissingContentError(options)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return findBestPLPTemplate(pages, slug)
|
|
74
|
+
}
|
package/src/utils/utilities.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ServerProductQueryQuery } from '@generated/graphql'
|
|
2
2
|
import { PDPContentType } from 'src/server/cms/pdp'
|
|
3
|
+
import { PLPContentType } from 'src/server/cms/plp'
|
|
3
4
|
|
|
4
5
|
//Input "Example Text!". Output: example-text
|
|
5
6
|
export function textToKebabCase(text: string): string {
|
|
@@ -15,6 +16,58 @@ export function textToKebabCase(text: string): string {
|
|
|
15
16
|
return kebabCase ?? ''
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
export function normalizePLPSlug(slug: string) {
|
|
20
|
+
// Remove extra slashes at the beginning and end
|
|
21
|
+
let normalizedSlug = slug.replace(/^\/+|\/+$/g, '')
|
|
22
|
+
|
|
23
|
+
// Remove duplicate slashes and white spaces throughout the string
|
|
24
|
+
normalizedSlug = normalizedSlug.replace(/\/+/g, '/').replace(/\s+/g, '')
|
|
25
|
+
|
|
26
|
+
return '/' + normalizedSlug.toLowerCase()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function findPLPTemplateBySlug(pages: Partial<PLPContentType>[], slug: string) {
|
|
30
|
+
return pages.find((page) => {
|
|
31
|
+
// generic PLP template
|
|
32
|
+
if (!page.settings?.template?.value) return false
|
|
33
|
+
|
|
34
|
+
const templateValue = normalizePLPSlug(page.settings?.template?.value)
|
|
35
|
+
return templateValue === slug
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Find the best PLP template from the CMS based on the slug passed as param.
|
|
41
|
+
*
|
|
42
|
+
* This function iterates the slug until there is no slashes (/), prioritizing the following order:
|
|
43
|
+
* 1. A PLP template that matches the subcategory (e.g. slug = /department/category/subcategory).
|
|
44
|
+
* 2. A PLP template that matches the category (e.g. slug = /department/category).
|
|
45
|
+
* 3. A PLP template that matches the department (e.g. slug = /department).
|
|
46
|
+
* 4. If no matches are found, use the generic PLP template.
|
|
47
|
+
*
|
|
48
|
+
* @param pages
|
|
49
|
+
* @param originalSlug
|
|
50
|
+
* @returns The best PLP template page for the slug
|
|
51
|
+
*/
|
|
52
|
+
export function findBestPLPTemplate(
|
|
53
|
+
pages: Partial<PLPContentType>[],
|
|
54
|
+
originalSlug: string
|
|
55
|
+
) {
|
|
56
|
+
let slug = normalizePLPSlug(originalSlug)
|
|
57
|
+
let foundPageTemplate = findPLPTemplateBySlug(pages, slug)
|
|
58
|
+
|
|
59
|
+
while (!foundPageTemplate && slug.lastIndexOf('/') !== -1) {
|
|
60
|
+
slug = slug.substring(0, slug.lastIndexOf('/'))
|
|
61
|
+
foundPageTemplate = findPLPTemplateBySlug(pages, slug)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
foundPageTemplate ||
|
|
66
|
+
pages.find((page) => !page.settings?.template?.value) ||
|
|
67
|
+
pages[0]
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
18
71
|
export function normalizePDPTemplate(templateValue: string) {
|
|
19
72
|
// Remove extra slashes, white spaces at the beginning and end
|
|
20
73
|
let formattedValue = templateValue.trim().replace(/^\/+|\/+$/g, '')
|
|
File without changes
|