@faststore/core 3.0.151 → 3.0.153
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 +26 -26
- 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-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/3202.js +1 -1
- package/.next/server/chunks/350.js +1 -1
- package/.next/server/chunks/5484.js +1 -1
- package/.next/server/chunks/5671.js +1 -1
- package/.next/server/chunks/9646.js +3 -2
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/pages/[...slug].js +1 -1
- package/.next/server/pages/api/graphql.js +1 -1
- package/.next/server/pages/api/preview.js +1 -1
- package/.next/server/pages/en-US/404.html +1 -1
- package/.next/server/pages/en-US/404.json +1 -1
- package/.next/server/pages/en-US/500.html +1 -1
- package/.next/server/pages/en-US/500.json +1 -1
- package/.next/server/pages/en-US/account.html +1 -1
- package/.next/server/pages/en-US/account.json +1 -1
- package/.next/server/pages/en-US/checkout.html +1 -1
- package/.next/server/pages/en-US/checkout.json +1 -1
- package/.next/server/pages/en-US/login.html +1 -1
- package/.next/server/pages/en-US/login.json +1 -1
- package/.next/server/pages/en-US/s.html +1 -1
- package/.next/server/pages/en-US/s.json +1 -1
- package/.next/server/pages/en-US.html +2 -2
- package/.next/server/pages/en-US.json +1 -1
- package/.next/server/pages/s.js +1 -1
- package/.next/static/{dy3ygqBtz-vKIoH-4l0Gg → FXMFCIKLN-fFiSeONDqs3}/_buildManifest.js +1 -1
- package/.next/static/chunks/{202.adc31e548eafb936.js → 202.2a784500752e6a56.js} +1 -1
- package/.next/static/chunks/{484.3e4d0dcb4c646a45.js → 484.755bc4e4fb57ebb9.js} +1 -1
- package/.next/static/chunks/{707-83d159430b49c007.js → 707-6818d9951a83f35f.js} +1 -1
- package/.next/static/chunks/973-d39dc88330d50aca.js +1 -0
- package/.next/static/chunks/pages/{[...slug]-7251a2458aa75965.js → [...slug]-0db45ebf94081661.js} +1 -1
- package/.next/static/chunks/pages/{s-9002e83fb35c96b7.js → s-7ad120ac3e73cbea.js} +1 -1
- package/.next/static/chunks/{webpack-39f5c3558a96182c.js → webpack-ab89187244c136e9.js} +1 -1
- package/.next/trace +98 -98
- package/.turbo/turbo-build.log +3 -3
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-test.log +5 -5
- package/@generated/gql.ts +2 -2
- package/@generated/graphql.ts +16 -4
- package/@generated/persisted-documents.json +2 -2
- package/@generated/schema.graphql +2 -0
- package/package.json +9 -9
- package/src/components/templates/SearchPage/SearchWrapper.tsx +6 -5
- package/src/pages/api/preview.ts +33 -11
- package/src/sdk/analytics/platform/vtex/search.ts +29 -1
- package/src/sdk/analytics/types.ts +14 -0
- package/src/sdk/product/useProductGalleryQuery.ts +44 -2
- package/src/sdk/search/state.ts +6 -1
- package/src/sdk/search/useSuggestions.ts +3 -3
- package/.next/static/chunks/973-840ef2154b9d2940.js +0 -1
- /package/.next/static/{dy3ygqBtz-vKIoH-4l0Gg → FXMFCIKLN-fFiSeONDqs3}/_ssgManifest.js +0 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -49,7 +49,7 @@ Route (pages) Size First Load JS
|
|
|
49
49
|
┌ ● / 1.23 kB 139 kB
|
|
50
50
|
├ └ css/197e314c5a03eabd.css 740 B
|
|
51
51
|
├ /_app 0 B 91 kB
|
|
52
|
-
├ ● /[...slug] 2.79 kB
|
|
52
|
+
├ ● /[...slug] 2.79 kB 153 kB
|
|
53
53
|
├ └ css/e47f1a002bdcf76f.css 2.38 kB
|
|
54
54
|
├ ● /[slug]/p 12.3 kB 150 kB
|
|
55
55
|
├ └ css/9b6bba2472d272ec.css 10.5 kB
|
|
@@ -67,11 +67,11 @@ Route (pages) Size First Load JS
|
|
|
67
67
|
├ chunks/framework-8e279965036b6169.js 45.4 kB
|
|
68
68
|
├ chunks/main-029f1328cfee9686.js 33.1 kB
|
|
69
69
|
├ chunks/pages/_app-cb1c3a94f987c5c8.js 9.87 kB
|
|
70
|
-
├ chunks/webpack-
|
|
70
|
+
├ chunks/webpack-ab89187244c136e9.js 2.74 kB
|
|
71
71
|
└ css/ee0556daedda6306.css 3.07 kB
|
|
72
72
|
|
|
73
73
|
λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps)
|
|
74
74
|
○ (Static) automatically rendered as static HTML (uses no initial props)
|
|
75
75
|
● (SSG) automatically generated as static HTML + JSON (uses getStaticProps)
|
|
76
76
|
|
|
77
|
-
Done in
|
|
77
|
+
Done in 70.84s.
|
package/.turbo/turbo-lint.log
CHANGED
package/.turbo/turbo-test.log
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
yarn run v1.22.22
|
|
2
2
|
$ jest
|
|
3
|
-
PASS test/utils/multipleTemplates.test.ts (
|
|
4
|
-
PASS test/server/cms/index.test.ts (
|
|
5
|
-
PASS test/server/index.test.ts (
|
|
3
|
+
PASS test/utils/multipleTemplates.test.ts (33.959 s)
|
|
4
|
+
PASS test/server/cms/index.test.ts (34.228 s)
|
|
5
|
+
PASS test/server/index.test.ts (38.562 s)
|
|
6
6
|
|
|
7
7
|
Test Suites: 3 passed, 3 total
|
|
8
8
|
Tests: 19 passed, 19 total
|
|
9
9
|
Snapshots: 0 total
|
|
10
|
-
Time:
|
|
10
|
+
Time: 39.653 s
|
|
11
11
|
Ran all test suites.
|
|
12
|
-
Done in 41.
|
|
12
|
+
Done in 41.17s.
|
package/@generated/gql.ts
CHANGED
|
@@ -44,7 +44,7 @@ const documents = {
|
|
|
44
44
|
types.SubscribeToNewsletterDocument,
|
|
45
45
|
'\n query ClientManyProductsQuery(\n $first: Int!\n $after: String\n $sort: StoreSort!\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]!\n ) {\n ...ClientManyProducts\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n ) {\n products {\n pageInfo {\n totalCount\n }\n edges {\n node {\n ...ProductSummary_product\n }\n }\n }\n }\n }\n':
|
|
46
46
|
types.ClientManyProductsQueryDocument,
|
|
47
|
-
'\n query ClientProductGalleryQuery(\n $first: Int!\n $after: String!\n $sort: StoreSort!\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]!\n ) {\n ...ClientProductGallery\n redirect(term: $term, selectedFacets: $selectedFacets) {\n url\n }\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n ) {\n products {\n pageInfo {\n totalCount\n }\n }\n facets {\n ...Filter_facets\n }\n metadata {\n ...SearchEvent_metadata\n }\n }\n }\n\n fragment SearchEvent_metadata on SearchMetadata {\n isTermMisspelled\n logicalOperator\n }\n':
|
|
47
|
+
'\n query ClientProductGalleryQuery(\n $first: Int!\n $after: String!\n $sort: StoreSort!\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]!\n ) {\n ...ClientProductGallery\n redirect(term: $term, selectedFacets: $selectedFacets) {\n url\n }\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n ) {\n products {\n pageInfo {\n totalCount\n }\n }\n facets {\n ...Filter_facets\n }\n metadata {\n ...SearchEvent_metadata\n }\n }\n }\n\n fragment SearchEvent_metadata on SearchMetadata {\n isTermMisspelled\n logicalOperator\n fuzzy\n }\n':
|
|
48
48
|
types.ClientProductGalleryQueryDocument,
|
|
49
49
|
'\n query ClientProductQuery($locator: [IStoreSelectedFacet!]!) {\n ...ClientProduct\n product(locator: $locator) {\n ...ProductDetailsFragment_product\n }\n }\n':
|
|
50
50
|
types.ClientProductQueryDocument,
|
|
@@ -158,7 +158,7 @@ export function gql(
|
|
|
158
158
|
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
|
159
159
|
*/
|
|
160
160
|
export function gql(
|
|
161
|
-
source: '\n query ClientProductGalleryQuery(\n $first: Int!\n $after: String!\n $sort: StoreSort!\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]!\n ) {\n ...ClientProductGallery\n redirect(term: $term, selectedFacets: $selectedFacets) {\n url\n }\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n ) {\n products {\n pageInfo {\n totalCount\n }\n }\n facets {\n ...Filter_facets\n }\n metadata {\n ...SearchEvent_metadata\n }\n }\n }\n\n fragment SearchEvent_metadata on SearchMetadata {\n isTermMisspelled\n logicalOperator\n }\n'
|
|
161
|
+
source: '\n query ClientProductGalleryQuery(\n $first: Int!\n $after: String!\n $sort: StoreSort!\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]!\n ) {\n ...ClientProductGallery\n redirect(term: $term, selectedFacets: $selectedFacets) {\n url\n }\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n ) {\n products {\n pageInfo {\n totalCount\n }\n }\n facets {\n ...Filter_facets\n }\n metadata {\n ...SearchEvent_metadata\n }\n }\n }\n\n fragment SearchEvent_metadata on SearchMetadata {\n isTermMisspelled\n logicalOperator\n fuzzy\n }\n'
|
|
162
162
|
): typeof import('./graphql').ClientProductGalleryQueryDocument
|
|
163
163
|
/**
|
|
164
164
|
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
package/@generated/graphql.ts
CHANGED
|
@@ -523,6 +523,8 @@ export type QueryShippingArgs = {
|
|
|
523
523
|
|
|
524
524
|
/** Search result. */
|
|
525
525
|
export type SearchMetadata = {
|
|
526
|
+
/** Indicates how the search engine corrected the misspelled word by using fuzzy logic. */
|
|
527
|
+
fuzzy: Maybe<Scalars['String']['output']>
|
|
526
528
|
/** Indicates if the search term was misspelled. */
|
|
527
529
|
isTermMisspelled: Scalars['Boolean']['output']
|
|
528
530
|
/** Logical operator used to run the search. */
|
|
@@ -1504,13 +1506,18 @@ export type ClientProductGalleryQueryQuery = {
|
|
|
1504
1506
|
max: { selected: number; absolute: number }
|
|
1505
1507
|
}
|
|
1506
1508
|
>
|
|
1507
|
-
metadata: {
|
|
1509
|
+
metadata: {
|
|
1510
|
+
isTermMisspelled: boolean
|
|
1511
|
+
logicalOperator: string
|
|
1512
|
+
fuzzy: string | null
|
|
1513
|
+
} | null
|
|
1508
1514
|
}
|
|
1509
1515
|
}
|
|
1510
1516
|
|
|
1511
1517
|
export type SearchEvent_MetadataFragment = {
|
|
1512
1518
|
isTermMisspelled: boolean
|
|
1513
1519
|
logicalOperator: string
|
|
1520
|
+
fuzzy: string | null
|
|
1514
1521
|
}
|
|
1515
1522
|
|
|
1516
1523
|
export type ClientProductQueryQueryVariables = Exact<{
|
|
@@ -1597,7 +1604,11 @@ export type ClientSearchSuggestionsQueryQuery = {
|
|
|
1597
1604
|
}>
|
|
1598
1605
|
}
|
|
1599
1606
|
products: { pageInfo: { totalCount: number } }
|
|
1600
|
-
metadata: {
|
|
1607
|
+
metadata: {
|
|
1608
|
+
isTermMisspelled: boolean
|
|
1609
|
+
logicalOperator: string
|
|
1610
|
+
fuzzy: string | null
|
|
1611
|
+
} | null
|
|
1601
1612
|
}
|
|
1602
1613
|
}
|
|
1603
1614
|
|
|
@@ -2047,6 +2058,7 @@ export const SearchEvent_MetadataFragmentDoc = new TypedDocumentString(
|
|
|
2047
2058
|
fragment SearchEvent_metadata on SearchMetadata {
|
|
2048
2059
|
isTermMisspelled
|
|
2049
2060
|
logicalOperator
|
|
2061
|
+
fuzzy
|
|
2050
2062
|
}
|
|
2051
2063
|
`,
|
|
2052
2064
|
{ fragmentName: 'SearchEvent_metadata' }
|
|
@@ -2099,7 +2111,7 @@ export const ClientManyProductsQueryDocument = {
|
|
|
2099
2111
|
export const ClientProductGalleryQueryDocument = {
|
|
2100
2112
|
__meta__: {
|
|
2101
2113
|
operationName: 'ClientProductGalleryQuery',
|
|
2102
|
-
operationHash: '
|
|
2114
|
+
operationHash: 'bfc40da32b60f9404a4adb96b0856e3fbb04b076',
|
|
2103
2115
|
},
|
|
2104
2116
|
} as unknown as TypedDocumentString<
|
|
2105
2117
|
ClientProductGalleryQueryQuery,
|
|
@@ -2117,7 +2129,7 @@ export const ClientProductQueryDocument = {
|
|
|
2117
2129
|
export const ClientSearchSuggestionsQueryDocument = {
|
|
2118
2130
|
__meta__: {
|
|
2119
2131
|
operationName: 'ClientSearchSuggestionsQuery',
|
|
2120
|
-
operationHash: '
|
|
2132
|
+
operationHash: '47e48eaee91d16a4237eb2c1241bc2ed3e2ad9bb',
|
|
2121
2133
|
},
|
|
2122
2134
|
} as unknown as TypedDocumentString<
|
|
2123
2135
|
ClientSearchSuggestionsQueryQuery,
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
"c2b3f8bff73ebf6ac79d758c66cabbc21ba9fcc0": "fragment CartItem on StoreOffer { itemOffered { ...CartProductItem } listPrice listPriceWithTaxes price priceWithTaxes quantity seller { identifier } } fragment CartMessage on StoreCartMessage { status text } fragment CartProductItem on StoreProduct { additionalProperty { name propertyID value valueReference } brand { name } gtin image { alternateName url } isVariantOf { name productGroupID skuVariants { activeVariations availableVariations slugsMap } } name sku unitMultiplier } mutation ValidateCartMutation($cart: IStoreCart!, $session: IStoreSession!) { validateCart(cart: $cart, session: $session) { messages { ...CartMessage } order { acceptedOffer { ...CartItem } orderNumber shouldSplitItem } } }",
|
|
5
5
|
"feb7005103a859e2bc8cf2360d568806fd88deba": "mutation SubscribeToNewsletter($data: IPersonNewsletter!) { subscribeToNewsletter(data: $data) { id } }",
|
|
6
6
|
"ad2eb78cfccb9dbd5a9f2d1e150cc70fea5da99a": "fragment ClientManyProducts on Query { search( first: $first after: $after sort: $sort term: $term selectedFacets: $selectedFacets ) { products { pageInfo { totalCount } } } } fragment ProductSummary_product on StoreProduct { additionalProperty { name propertyID value valueReference } advertisement { adId adResponseId } brand { brandName: name } brand { name } gtin image { alternateName url } isVariantOf { name productGroupID } name offers { lowPrice lowPriceWithTaxes offers { availability listPrice listPriceWithTaxes price quantity seller { identifier } } } id: productID sku slug } query ClientManyProductsQuery($after: String, $first: Int!, $selectedFacets: [IStoreSelectedFacet!]!, $sort: StoreSort!, $term: String!) { search( first: $first after: $after sort: $sort term: $term selectedFacets: $selectedFacets ) { products { edges { node { ...ProductSummary_product } } pageInfo { totalCount } } } ...ClientManyProducts }",
|
|
7
|
-
"
|
|
7
|
+
"bfc40da32b60f9404a4adb96b0856e3fbb04b076": "fragment ClientProductGallery on Query { search( first: $first after: $after sort: $sort term: $term selectedFacets: $selectedFacets ) { products { pageInfo { totalCount } } } } fragment Filter_facets on StoreFacet { ... on StoreFacetBoolean { __typename key label values { label quantity selected value } } ... on StoreFacetRange { __typename key label max { absolute selected } min { absolute selected } } } fragment SearchEvent_metadata on SearchMetadata { fuzzy isTermMisspelled logicalOperator } query ClientProductGalleryQuery($after: String!, $first: Int!, $selectedFacets: [IStoreSelectedFacet!]!, $sort: StoreSort!, $term: String!) { redirect(term: $term, selectedFacets: $selectedFacets) { url } search( first: $first after: $after sort: $sort term: $term selectedFacets: $selectedFacets ) { facets { ...Filter_facets } metadata { ...SearchEvent_metadata } products { pageInfo { totalCount } } } ...ClientProductGallery }",
|
|
8
8
|
"7d121ef8d4dc99174e64e4429a9b977b8bbebed8": "fragment CartProductItem on StoreProduct { additionalProperty { name propertyID value valueReference } brand { name } gtin image { alternateName url } isVariantOf { name productGroupID skuVariants { activeVariations availableVariations slugsMap } } name sku unitMultiplier } fragment ClientProduct on Query { product(locator: $locator) { id: productID } } fragment ProductDetailsFragment_product on StoreProduct { additionalProperty { name propertyID value valueReference } brand { name } description gtin image { alternateName url } isVariantOf { name productGroupID skuVariants { activeVariations availableVariations slugsMap } } name offers { lowPrice lowPriceWithTaxes offers { availability listPrice listPriceWithTaxes price priceWithTaxes seller { identifier } } } id: productID sku unitMultiplier ...CartProductItem } query ClientProductQuery($locator: [IStoreSelectedFacet!]!) { product(locator: $locator) { ...ProductDetailsFragment_product } ...ClientProduct }",
|
|
9
|
-
"
|
|
9
|
+
"47e48eaee91d16a4237eb2c1241bc2ed3e2ad9bb": "fragment ClientSearchSuggestions on Query { search(first: 5, term: $term, selectedFacets: $selectedFacets) { suggestions { terms { value } } } } fragment ProductSummary_product on StoreProduct { additionalProperty { name propertyID value valueReference } advertisement { adId adResponseId } brand { brandName: name } brand { name } gtin image { alternateName url } isVariantOf { name productGroupID } name offers { lowPrice lowPriceWithTaxes offers { availability listPrice listPriceWithTaxes price quantity seller { identifier } } } id: productID sku slug } fragment SearchEvent_metadata on SearchMetadata { fuzzy isTermMisspelled logicalOperator } query ClientSearchSuggestionsQuery($selectedFacets: [IStoreSelectedFacet!], $term: String!) { search(first: 5, term: $term, selectedFacets: $selectedFacets) { metadata { ...SearchEvent_metadata } products { pageInfo { totalCount } } suggestions { products { ...ProductSummary_product } terms { value } } } ...ClientSearchSuggestions }",
|
|
10
10
|
"e2385b0f11726d0068f96548f57a8dd441c064e3": "fragment ClientTopSearchSuggestions on Query { search(first: 5, term: $term, selectedFacets: $selectedFacets) { suggestions { terms { value } } } } query ClientTopSearchSuggestionsQuery($selectedFacets: [IStoreSelectedFacet!], $term: String!) { search(first: 5, term: $term, selectedFacets: $selectedFacets) { suggestions { terms { value } } } ...ClientTopSearchSuggestions }",
|
|
11
11
|
"1e69c734ed31bd9e763a34fe9660f5bbad3fd143": "mutation ValidateSession($search: String!, $session: IStoreSession!) { validateSession(session: $session, search: $search) { addressType b2b { customerId } channel country currency { code symbol } deliveryMode { deliveryChannel deliveryMethod deliveryWindow { endDate startDate } } geoCoordinates { latitude longitude } locale person { email familyName givenName id } postalCode } }",
|
|
12
12
|
"d6667f1de2a26b94b9b55f4b25d7d823f82635a0": "fragment ClientShippingSimulation on Query { shipping(items: $items, postalCode: $postalCode, country: $country) { address { city } } } query ClientShippingSimulationQuery($country: String!, $items: [IShippingItem!]!, $postalCode: String!) { shipping(items: $items, postalCode: $postalCode, country: $country) { address { city neighborhood state } logisticsInfo { slas { availableDeliveryWindows { endDateUtc listPrice price startDateUtc } carrier localizedEstimates price shippingEstimate } } } ...ClientShippingSimulation }"
|
|
@@ -545,6 +545,8 @@ type SearchMetadata {
|
|
|
545
545
|
isTermMisspelled: Boolean!
|
|
546
546
|
"""Logical operator used to run the search."""
|
|
547
547
|
logicalOperator: String!
|
|
548
|
+
"""Indicates how the search engine corrected the misspelled word by using fuzzy logic."""
|
|
549
|
+
fuzzy: String
|
|
548
550
|
}
|
|
549
551
|
|
|
550
552
|
"""Search result."""
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faststore/core",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.153",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": "vtex/faststore",
|
|
6
6
|
"browserslist": "supports es6-module and not dead",
|
|
@@ -43,12 +43,12 @@
|
|
|
43
43
|
"@envelop/graphql-jit": "^8.0.3",
|
|
44
44
|
"@envelop/parser-cache": "^6.0.2",
|
|
45
45
|
"@envelop/validation-cache": "^6.0.2",
|
|
46
|
-
"@faststore/api": "^3.0.
|
|
47
|
-
"@faststore/components": "^3.0.
|
|
48
|
-
"@faststore/graphql-utils": "^3.0.
|
|
49
|
-
"@faststore/lighthouse": "^3.0.
|
|
50
|
-
"@faststore/sdk": "^3.0.
|
|
51
|
-
"@faststore/ui": "^3.0.
|
|
46
|
+
"@faststore/api": "^3.0.152",
|
|
47
|
+
"@faststore/components": "^3.0.152",
|
|
48
|
+
"@faststore/graphql-utils": "^3.0.152",
|
|
49
|
+
"@faststore/lighthouse": "^3.0.152",
|
|
50
|
+
"@faststore/sdk": "^3.0.152",
|
|
51
|
+
"@faststore/ui": "^3.0.152",
|
|
52
52
|
"@graphql-codegen/cli": "5.0.2",
|
|
53
53
|
"@graphql-codegen/client-preset": "4.2.6",
|
|
54
54
|
"@graphql-codegen/typescript": "4.0.7",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"devDependencies": {
|
|
88
88
|
"@cypress/code-coverage": "^3.12.1",
|
|
89
89
|
"@envelop/testing": "^6.0.0",
|
|
90
|
-
"@faststore/eslint-config": "^3.0.
|
|
90
|
+
"@faststore/eslint-config": "^3.0.152",
|
|
91
91
|
"@lhci/cli": "^0.9.0",
|
|
92
92
|
"@testing-library/cypress": "^10.0.1",
|
|
93
93
|
"@types/cypress": "^1.1.3",
|
|
@@ -128,5 +128,5 @@
|
|
|
128
128
|
"node": "18.19.0",
|
|
129
129
|
"yarn": "1.19.1"
|
|
130
130
|
},
|
|
131
|
-
"gitHead": "
|
|
131
|
+
"gitHead": "6f2e5b5970de162e5c425f70ce20552fe195a3de"
|
|
132
132
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { useRouter } from 'next/router'
|
|
2
1
|
import { useSearch } from '@faststore/sdk'
|
|
2
|
+
import { useRouter } from 'next/router'
|
|
3
3
|
|
|
4
|
-
import type { SearchContentType } from 'src/server/cms'
|
|
5
|
-
import type { SearchPageContextType } from 'src/pages/s'
|
|
6
|
-
import { useProductGalleryQuery } from 'src/sdk/product/useProductGalleryQuery'
|
|
7
|
-
import Section from 'src/components/sections/Section'
|
|
8
4
|
import EmptyState from 'src/components/sections/EmptyState'
|
|
9
5
|
import ProductGalleryStyles from 'src/components/sections/ProductGallery/section.module.scss'
|
|
6
|
+
import Section from 'src/components/sections/Section'
|
|
7
|
+
import type { SearchPageContextType } from 'src/pages/s'
|
|
8
|
+
import { useProductGalleryQuery } from 'src/sdk/product/useProductGalleryQuery'
|
|
9
|
+
import type { SearchContentType } from 'src/server/cms'
|
|
10
10
|
|
|
11
11
|
import SearchPage from './SearchPage'
|
|
12
12
|
|
|
@@ -37,6 +37,7 @@ export default function SearchWrapper({
|
|
|
37
37
|
const {
|
|
38
38
|
state: { term, sort, selectedFacets },
|
|
39
39
|
} = useSearch()
|
|
40
|
+
|
|
40
41
|
const { data: pageProductGalleryData, isValidating } = useProductGalleryQuery(
|
|
41
42
|
{
|
|
42
43
|
term,
|
package/src/pages/api/preview.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { NextApiHandler, NextApiRequest } from 'next'
|
|
2
|
+
import type { Locator } from '@vtex/client-cms'
|
|
2
3
|
|
|
3
4
|
import { clientCMS } from 'src/server/cms'
|
|
4
5
|
import { previewRedirects } from '../../../discovery.config'
|
|
@@ -20,10 +21,7 @@ const pickParam = (req: NextApiRequest, parameter: string) => {
|
|
|
20
21
|
const maybeParam = req.query[parameter]
|
|
21
22
|
|
|
22
23
|
if (typeof maybeParam !== 'string') {
|
|
23
|
-
|
|
24
|
-
`Parameter ${parameter} missing from querystring`,
|
|
25
|
-
400
|
|
26
|
-
)
|
|
24
|
+
return undefined
|
|
27
25
|
}
|
|
28
26
|
|
|
29
27
|
return maybeParam
|
|
@@ -32,14 +30,37 @@ const pickParam = (req: NextApiRequest, parameter: string) => {
|
|
|
32
30
|
// TODO: Improve security by disabling CMS preview in production
|
|
33
31
|
const handler: NextApiHandler = async (req, res) => {
|
|
34
32
|
try {
|
|
35
|
-
const locator =
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
const locator = [
|
|
34
|
+
'contentType',
|
|
35
|
+
'documentId',
|
|
36
|
+
'versionId',
|
|
37
|
+
'releaseId',
|
|
38
|
+
].reduce((acc, param) => {
|
|
39
|
+
const value = pickParam(req, param)
|
|
40
|
+
|
|
41
|
+
if (value !== undefined) acc[param] = value
|
|
42
|
+
|
|
43
|
+
return acc
|
|
44
|
+
}, {} as Record<string, string>)
|
|
45
|
+
|
|
46
|
+
// Check if required path params are present
|
|
47
|
+
if (!locator.contentType || !locator.documentId) {
|
|
48
|
+
throw new StatusError(
|
|
49
|
+
`The following path params are required: contentType, documentId`,
|
|
50
|
+
400
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Check if at least one of the querystring params are present
|
|
55
|
+
if (!locator.versionId && !locator.releaseId) {
|
|
56
|
+
throw new StatusError(
|
|
57
|
+
`One of the following querystring params are required: versionId, releaseId`,
|
|
58
|
+
400
|
|
59
|
+
)
|
|
39
60
|
}
|
|
40
61
|
|
|
41
62
|
// Fetch CMS to check if the provided `locator` exists
|
|
42
|
-
const page = await clientCMS.getCMSPage(locator)
|
|
63
|
+
const page = await clientCMS.getCMSPage(locator as Locator)
|
|
43
64
|
|
|
44
65
|
// If the content doesn't exist prevent preview mode from being enabled
|
|
45
66
|
if (!page) {
|
|
@@ -56,8 +77,9 @@ const handler: NextApiHandler = async (req, res) => {
|
|
|
56
77
|
})
|
|
57
78
|
|
|
58
79
|
// Redirect to the path from the fetched locator
|
|
59
|
-
|
|
60
|
-
|
|
80
|
+
const redirects = previewRedirects as Record<string, string>
|
|
81
|
+
if (redirects[locator.contentType]) {
|
|
82
|
+
res.redirect(redirects[locator.contentType])
|
|
61
83
|
return
|
|
62
84
|
}
|
|
63
85
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { AnalyticsEvent } from '@faststore/sdk'
|
|
5
5
|
import type {
|
|
6
|
+
IntelligentSearchAutocompleteQueryEvent,
|
|
6
7
|
IntelligentSearchQueryEvent,
|
|
7
8
|
SearchSelectItemEvent,
|
|
8
9
|
} from '../../types'
|
|
@@ -66,6 +67,15 @@ type SearchEvent =
|
|
|
66
67
|
url: string
|
|
67
68
|
type: 'search.query'
|
|
68
69
|
}
|
|
70
|
+
| {
|
|
71
|
+
text: string
|
|
72
|
+
misspelled: boolean
|
|
73
|
+
match: number
|
|
74
|
+
operator: string
|
|
75
|
+
locale: string
|
|
76
|
+
url: string
|
|
77
|
+
type: 'search.autocomplete.query'
|
|
78
|
+
}
|
|
69
79
|
|
|
70
80
|
const sendEvent = (options: SearchEvent & { url?: string }) =>
|
|
71
81
|
fetch(`https://sp.vtex.com/event-api/v1/${config.api.storeId}/event`, {
|
|
@@ -86,7 +96,11 @@ const isFullTextSearch = (url: URL) =>
|
|
|
86
96
|
/^\/s(\/)?$/g.test(url.pathname)
|
|
87
97
|
|
|
88
98
|
const handleEvent = (
|
|
89
|
-
event:
|
|
99
|
+
event:
|
|
100
|
+
| AnalyticsEvent
|
|
101
|
+
| SearchSelectItemEvent
|
|
102
|
+
| IntelligentSearchQueryEvent
|
|
103
|
+
| IntelligentSearchAutocompleteQueryEvent
|
|
90
104
|
) => {
|
|
91
105
|
switch (event.name) {
|
|
92
106
|
case 'search_select_item': {
|
|
@@ -128,6 +142,20 @@ const handleEvent = (
|
|
|
128
142
|
break
|
|
129
143
|
}
|
|
130
144
|
|
|
145
|
+
case 'intelligent_search_autocomplete_query': {
|
|
146
|
+
sendEvent({
|
|
147
|
+
type: 'search.autocomplete.query',
|
|
148
|
+
url: event.params.url,
|
|
149
|
+
text: event.params.term,
|
|
150
|
+
misspelled: event.params.isTermMisspelled,
|
|
151
|
+
match: event.params.totalCount,
|
|
152
|
+
operator: event.params.logicalOperator,
|
|
153
|
+
locale: event.params.locale,
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
break
|
|
157
|
+
}
|
|
158
|
+
|
|
131
159
|
default:
|
|
132
160
|
}
|
|
133
161
|
}
|
|
@@ -34,3 +34,17 @@ export interface IntelligentSearchQueryEvent {
|
|
|
34
34
|
name: 'intelligent_search_query'
|
|
35
35
|
params: IntelligentSearchQueryParams
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
export interface IntelligentSearchAutocompleteQueryParams {
|
|
39
|
+
url: string
|
|
40
|
+
locale: string
|
|
41
|
+
term: string
|
|
42
|
+
logicalOperator: string
|
|
43
|
+
isTermMisspelled: boolean
|
|
44
|
+
totalCount: number
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface IntelligentSearchAutocompleteQueryEvent {
|
|
48
|
+
name: 'intelligent_search_autocomplete_query'
|
|
49
|
+
params: IntelligentSearchAutocompleteQueryParams
|
|
50
|
+
}
|
|
@@ -3,6 +3,7 @@ import { useQuery } from 'src/sdk/graphql/useQuery'
|
|
|
3
3
|
import { useSession } from 'src/sdk/session'
|
|
4
4
|
import { useLocalizedVariables } from './useLocalizedVariables'
|
|
5
5
|
|
|
6
|
+
import { useSearch } from '@faststore/sdk'
|
|
6
7
|
import { Facet } from '@faststore/sdk/dist/types'
|
|
7
8
|
import type {
|
|
8
9
|
ClientManyProductsQueryQueryVariables,
|
|
@@ -53,6 +54,7 @@ export const query = gql(`
|
|
|
53
54
|
fragment SearchEvent_metadata on SearchMetadata {
|
|
54
55
|
isTermMisspelled
|
|
55
56
|
logicalOperator
|
|
57
|
+
fuzzy
|
|
56
58
|
}
|
|
57
59
|
`)
|
|
58
60
|
|
|
@@ -63,6 +65,14 @@ type ProductGalleryQueryOptions = {
|
|
|
63
65
|
term: ClientManyProductsQueryQueryVariables['term']
|
|
64
66
|
}
|
|
65
67
|
|
|
68
|
+
export const findFacetValue = (
|
|
69
|
+
facets: Facet[],
|
|
70
|
+
searchParam: string
|
|
71
|
+
): string | null => {
|
|
72
|
+
const facet = facets.find(({ key }) => key === searchParam)
|
|
73
|
+
return facet?.value ?? null
|
|
74
|
+
}
|
|
75
|
+
|
|
66
76
|
export const useProductGalleryQuery = ({
|
|
67
77
|
term,
|
|
68
78
|
sort,
|
|
@@ -70,6 +80,7 @@ export const useProductGalleryQuery = ({
|
|
|
70
80
|
itemsPerPage,
|
|
71
81
|
}: ProductGalleryQueryOptions) => {
|
|
72
82
|
const { locale } = useSession()
|
|
83
|
+
const { state, setState } = useSearch()
|
|
73
84
|
const localizedVariables = useLocalizedVariables({
|
|
74
85
|
first: itemsPerPage,
|
|
75
86
|
after: '0',
|
|
@@ -78,9 +89,12 @@ export const useProductGalleryQuery = ({
|
|
|
78
89
|
selectedFacets,
|
|
79
90
|
})
|
|
80
91
|
|
|
81
|
-
|
|
92
|
+
const fuzzyFacetValue = findFacetValue(selectedFacets, 'fuzzy')
|
|
93
|
+
const operatorFacetValue = findFacetValue(selectedFacets, 'operator')
|
|
94
|
+
|
|
95
|
+
const queryResult = useQuery<Query, Variables>(query, localizedVariables, {
|
|
82
96
|
onSuccess: (data) => {
|
|
83
|
-
if (data && term) {
|
|
97
|
+
if (data && term && fuzzyFacetValue && operatorFacetValue) {
|
|
84
98
|
import('@faststore/sdk').then(({ sendAnalyticsEvent }) => {
|
|
85
99
|
sendAnalyticsEvent<IntelligentSearchQueryEvent>({
|
|
86
100
|
name: 'intelligent_search_query',
|
|
@@ -97,4 +111,32 @@ export const useProductGalleryQuery = ({
|
|
|
97
111
|
}
|
|
98
112
|
},
|
|
99
113
|
})
|
|
114
|
+
|
|
115
|
+
// If there is no fuzzy or operator facet, we need to add them to the selectedFacets and re-fetch the query
|
|
116
|
+
const shouldRefetchQuery =
|
|
117
|
+
!queryResult.error && (!fuzzyFacetValue || !operatorFacetValue)
|
|
118
|
+
|
|
119
|
+
if (shouldRefetchQuery) {
|
|
120
|
+
if (queryResult.data) {
|
|
121
|
+
setState({
|
|
122
|
+
...state,
|
|
123
|
+
selectedFacets: [
|
|
124
|
+
...selectedFacets,
|
|
125
|
+
{
|
|
126
|
+
key: 'fuzzy',
|
|
127
|
+
value: queryResult.data.search.metadata?.fuzzy ?? 'auto',
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
key: 'operator',
|
|
131
|
+
value: queryResult.data.search.metadata?.logicalOperator ?? 'and',
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// The first result is not relevant, return null data to avoid rendering the page while the query is being re-fetched
|
|
138
|
+
return { ...queryResult, isValidating: true, data: null }
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return queryResult
|
|
100
142
|
}
|
package/src/sdk/search/state.ts
CHANGED
|
@@ -5,7 +5,12 @@ export const useApplySearchState = () => {
|
|
|
5
5
|
const router = useRouter()
|
|
6
6
|
|
|
7
7
|
return useCallback(
|
|
8
|
-
(url: URL) =>
|
|
8
|
+
(url: URL) => {
|
|
9
|
+
const newUrl = `${url.pathname}${url.search}`
|
|
10
|
+
return url.searchParams.has('fuzzy') && url.searchParams.has('operator')
|
|
11
|
+
? router.replace(newUrl)
|
|
12
|
+
: router.push(newUrl)
|
|
13
|
+
},
|
|
9
14
|
[router]
|
|
10
15
|
)
|
|
11
16
|
}
|
|
@@ -7,7 +7,7 @@ import type {
|
|
|
7
7
|
ClientSearchSuggestionsQueryQuery as Query,
|
|
8
8
|
ClientSearchSuggestionsQueryQueryVariables as Variables,
|
|
9
9
|
} from '@generated/graphql'
|
|
10
|
-
import type {
|
|
10
|
+
import type { IntelligentSearchAutocompleteQueryEvent } from '../analytics/types'
|
|
11
11
|
|
|
12
12
|
import { useSession } from '../session'
|
|
13
13
|
|
|
@@ -55,8 +55,8 @@ function useSuggestions(term: string) {
|
|
|
55
55
|
onSuccess: (callbackData) => {
|
|
56
56
|
if (callbackData && term) {
|
|
57
57
|
import('@faststore/sdk').then(({ sendAnalyticsEvent }) => {
|
|
58
|
-
sendAnalyticsEvent<
|
|
59
|
-
name: '
|
|
58
|
+
sendAnalyticsEvent<IntelligentSearchAutocompleteQueryEvent>({
|
|
59
|
+
name: 'intelligent_search_autocomplete_query',
|
|
60
60
|
params: {
|
|
61
61
|
locale,
|
|
62
62
|
term,
|