@faststore/core 3.71.0 → 3.72.1

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.
Files changed (113) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +39 -39
  3. package/.next/cache/.tsbuildinfo +1 -1
  4. package/.next/cache/config.json +3 -3
  5. package/.next/cache/webpack/client-production/0.pack +0 -0
  6. package/.next/cache/webpack/client-production/index.pack +0 -0
  7. package/.next/cache/webpack/server-production/0.pack +0 -0
  8. package/.next/cache/webpack/server-production/index.pack +0 -0
  9. package/.next/prerender-manifest.js +1 -1
  10. package/.next/prerender-manifest.json +1 -1
  11. package/.next/react-loadable-manifest.json +13 -13
  12. package/.next/routes-manifest.json +1 -1
  13. package/.next/server/chunks/2570.js +1 -0
  14. package/.next/server/chunks/3918.js +1 -1
  15. package/.next/server/chunks/4168.js +1 -1
  16. package/.next/server/chunks/4365.js +1 -1
  17. package/.next/server/chunks/4913.js +13 -0
  18. package/.next/server/chunks/5723.js +13 -0
  19. package/.next/server/chunks/772.js +6 -0
  20. package/.next/server/chunks/870.js +1 -1
  21. package/.next/server/chunks/948.js +1 -1
  22. package/.next/server/chunks/9563.js +2 -2
  23. package/.next/server/chunks/9630.js +2 -2
  24. package/.next/server/chunks/9990.js +1 -0
  25. package/.next/server/middleware-build-manifest.js +1 -1
  26. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  27. package/.next/server/pages/404.js +1 -1
  28. package/.next/server/pages/404.js.nft.json +1 -1
  29. package/.next/server/pages/500.js +1 -1
  30. package/.next/server/pages/500.js.nft.json +1 -1
  31. package/.next/server/pages/[...slug].js +1 -1
  32. package/.next/server/pages/[...slug].js.nft.json +1 -1
  33. package/.next/server/pages/[slug]/p.js +1 -1
  34. package/.next/server/pages/[slug]/p.js.nft.json +1 -1
  35. package/.next/server/pages/_app.js +1 -1
  36. package/.next/server/pages/_app.js.nft.json +1 -1
  37. package/.next/server/pages/_document.js.nft.json +1 -1
  38. package/.next/server/pages/_error.js +1 -1
  39. package/.next/server/pages/_error.js.nft.json +1 -1
  40. package/.next/server/pages/account/403.js +1 -1
  41. package/.next/server/pages/account/403.js.nft.json +1 -1
  42. package/.next/server/pages/account/404.js +1 -1
  43. package/.next/server/pages/account/404.js.nft.json +1 -1
  44. package/.next/server/pages/account/[...unknown].js +1 -1
  45. package/.next/server/pages/account/[...unknown].js.nft.json +1 -1
  46. package/.next/server/pages/account/orders/[id].js +1 -1
  47. package/.next/server/pages/account/orders/[id].js.nft.json +1 -1
  48. package/.next/server/pages/account/orders.js +1 -1
  49. package/.next/server/pages/account/orders.js.nft.json +1 -1
  50. package/.next/server/pages/account/profile.js +1 -1
  51. package/.next/server/pages/account/profile.js.nft.json +1 -1
  52. package/.next/server/pages/account/security.js +1 -1
  53. package/.next/server/pages/account/security.js.nft.json +1 -1
  54. package/.next/server/pages/account/user-details.js +1 -1
  55. package/.next/server/pages/account/user-details.js.nft.json +1 -1
  56. package/.next/server/pages/account.js +1 -1
  57. package/.next/server/pages/account.js.nft.json +1 -1
  58. package/.next/server/pages/api/graphql.js +2 -2
  59. package/.next/server/pages/api/graphql.js.nft.json +1 -1
  60. package/.next/server/pages/api/health/live.js.nft.json +1 -1
  61. package/.next/server/pages/api/health/ready.js.nft.json +1 -1
  62. package/.next/server/pages/api/preview.js.nft.json +1 -1
  63. package/.next/server/pages/checkout.js +1 -1
  64. package/.next/server/pages/checkout.js.nft.json +1 -1
  65. package/.next/server/pages/en-US/404.html +1 -1
  66. package/.next/server/pages/en-US/500.html +1 -1
  67. package/.next/server/pages/en-US/checkout.html +1 -1
  68. package/.next/server/pages/en-US/login.html +1 -1
  69. package/.next/server/pages/en-US/s.html +1 -1
  70. package/.next/server/pages/en-US.html +1 -1
  71. package/.next/server/pages/index.js +1 -1
  72. package/.next/server/pages/index.js.nft.json +1 -1
  73. package/.next/server/pages/login.js +1 -1
  74. package/.next/server/pages/login.js.nft.json +1 -1
  75. package/.next/server/pages/s.js +1 -1
  76. package/.next/server/pages/s.js.nft.json +1 -1
  77. package/.next/server/pages-manifest.json +1 -1
  78. package/.next/static/chunks/353.3e74b28c8ca649a2.js +1 -0
  79. package/.next/static/chunks/{6393.53e9ea4f29d1bf23.js → 6393.f13568b0fd5f52f6.js} +1 -1
  80. package/.next/static/chunks/7191-a72fe20ee3eb28ec.js +1 -0
  81. package/.next/static/chunks/7692.d434a8499fb2aa03.js +1 -0
  82. package/.next/static/chunks/{9173-ed47aa8015d45a84.js → 9173-3a00edf7b695a319.js} +1 -1
  83. package/.next/static/chunks/{9399.49b20139636a39f2.js → 9399.6bd7f24a04ccfff4.js} +1 -1
  84. package/.next/static/chunks/941.2a946730a9174ed7.js +1 -0
  85. package/.next/static/chunks/pages/_app-4068e2b477988545.js +1 -0
  86. package/.next/static/chunks/{webpack-50cb24c3054682c1.js → webpack-2ddf567180dd5aaa.js} +1 -1
  87. package/.next/static/{nM-tG24KHPHfLNOK1C9F- → rI6VOpaLnNnxZNUT_-Q3V}/_buildManifest.js +1 -1
  88. package/.next/trace +134 -135
  89. package/.turbo/turbo-build.log +29 -29
  90. package/.turbo/turbo-test.log +5 -5
  91. package/@generated/gql.ts +2 -2
  92. package/@generated/graphql.ts +6 -1
  93. package/@generated/persisted-documents.json +1 -1
  94. package/@generated/schema.graphql +4 -0
  95. package/CHANGELOG.md +12 -0
  96. package/discovery.config.default.js +2 -0
  97. package/package.json +5 -4
  98. package/src/components/ui/ProductGallery/ProductGallery.tsx +3 -1
  99. package/src/pages/api/graphql.ts +56 -0
  100. package/src/sdk/graphql/request.ts +13 -0
  101. package/src/sdk/search/useFilter.ts +14 -1
  102. package/src/sdk/session/index.ts +76 -6
  103. package/src/utils/getCookie.ts +22 -0
  104. package/.next/server/chunks/4941.js +0 -6
  105. package/.next/server/chunks/5244.js +0 -1
  106. package/.next/server/chunks/8130.js +0 -13
  107. package/.next/server/chunks/8404.js +0 -13
  108. package/.next/static/chunks/353.7f2181843462717d.js +0 -1
  109. package/.next/static/chunks/7191-df87383e8d7c078f.js +0 -1
  110. package/.next/static/chunks/7692.1597d1d292a09609.js +0 -1
  111. package/.next/static/chunks/941.80a0abd58f11d696.js +0 -1
  112. package/.next/static/chunks/pages/_app-728289774860e9d9.js +0 -1
  113. /package/.next/static/{nM-tG24KHPHfLNOK1C9F- → rI6VOpaLnNnxZNUT_-Q3V}/_ssgManifest.js +0 -0
@@ -1,23 +1,23 @@
1
1
 
2
- > @faststore/core@3.70.2 prebuild /home/runner/work/faststore/faststore/packages/core
2
+ > @faststore/core@3.72.0 prebuild /home/runner/work/faststore/faststore/packages/core
3
3
  > na run partytown && na run generate
4
4
 
5
5
 
6
- > @faststore/core@3.70.2 partytown /home/runner/work/faststore/faststore/packages/core
6
+ > @faststore/core@3.72.0 partytown /home/runner/work/faststore/faststore/packages/core
7
7
  > partytown copylib ./public/~partytown
8
8
 
9
9
  Partytown lib copied to: /home/runner/work/faststore/faststore/packages/core/public/~partytown
10
10
 
11
- > @faststore/core@3.70.2 generate /home/runner/work/faststore/faststore/packages/core
11
+ > @faststore/core@3.72.0 generate /home/runner/work/faststore/faststore/packages/core
12
12
  > na run generate:schema && na run generate:codegen && na run format:generated
13
13
 
14
14
 
15
- > @faststore/core@3.70.2 generate:schema /home/runner/work/faststore/faststore/packages/core
15
+ > @faststore/core@3.72.0 generate:schema /home/runner/work/faststore/faststore/packages/core
16
16
  > tsx src/server/generator/generateGraphQLSchemaFile.ts
17
17
 
18
18
  Schema GraphQL file generated successfully
19
19
 
20
- > @faststore/core@3.70.2 generate:codegen /home/runner/work/faststore/faststore/packages/core
20
+ > @faststore/core@3.72.0 generate:codegen /home/runner/work/faststore/faststore/packages/core
21
21
  > graphql-codegen
22
22
 
23
23
  [STARTED] Parse Configuration
@@ -37,11 +37,11 @@ Running lifecycle hook "afterStart" scripts...
37
37
  [CLI] Loading Documents
38
38
  [CLI] Generating output
39
39
 
40
- > @faststore/core@3.70.2 format:generated /home/runner/work/faststore/faststore/packages/core
40
+ > @faststore/core@3.72.0 format:generated /home/runner/work/faststore/faststore/packages/core
41
41
  > prettier --write "@generated/**/*.{ts,js,tsx,jsx,json}" --loglevel error
42
42
 
43
43
 
44
- > @faststore/core@3.70.2 build /home/runner/work/faststore/faststore/packages/core
44
+ > @faststore/core@3.72.0 build /home/runner/work/faststore/faststore/packages/core
45
45
  > next build
46
46
 
47
47
  ⚠ No build cache found. Please configure build caching for faster rebuilds. Read more: https://nextjs.org/docs/messages/no-cache
@@ -73,19 +73,19 @@ Warning: Dynamic Content not found for the page: home. Refer to the Dynamic Cont
73
73
  Collecting build traces ...
74
74
 
75
75
  Route (pages) Size First Load JS
76
- ┌ ● / 3.66 kB 139 kB
76
+ ┌ ● / 3.66 kB 140 kB
77
77
  ├ └ css/b1806cbafd0c1f81.css 3.06 kB
78
- ├ /_app 0 B 105 kB
79
- ├ ● /[...slug] 2.45 kB 147 kB
80
- ├ ● /[slug]/p 32.6 kB 168 kB
78
+ ├ /_app 0 B 106 kB
79
+ ├ ● /[...slug] 2.45 kB 148 kB
80
+ ├ ● /[slug]/p 32.6 kB 169 kB
81
81
  ├ ├ css/a3ca6a9b63f657be.css 5.75 kB
82
82
  ├ ├ css/62a5153ac7061286.css 6.11 kB
83
83
  ├ └ css/6831395ff5fd317a.css 16.1 kB
84
- ├ ○ /404 1.55 kB 137 kB
85
- ├ ● /500 1.55 kB 137 kB
86
- ├ λ /account 240 B 105 kB
87
- ├ ● /account/[...unknown] 281 B 105 kB
88
- ├ λ /account/403 2.44 kB 138 kB
84
+ ├ ○ /404 1.55 kB 138 kB
85
+ ├ ● /500 1.55 kB 138 kB
86
+ ├ λ /account 240 B 106 kB
87
+ ├ ● /account/[...unknown] 281 B 106 kB
88
+ ├ λ /account/403 2.44 kB 139 kB
89
89
  ├ └ css/b7bba8fce075688b.css 4.2 kB
90
90
  ├ λ /account/404 2.13 kB 138 kB
91
91
  ├ └ css/5347dbc8b71de47d.css 4.25 kB
@@ -93,24 +93,24 @@ Route (pages) Size First Load JS
93
93
  ├ └ css/3d41485722b4e3f5.css 12.1 kB
94
94
  ├ λ /account/orders/[id] 12.1 kB 148 kB
95
95
  ├ └ css/70353bf19c496790.css 12.6 kB
96
- ├ λ /account/profile 1.79 kB 137 kB
96
+ ├ λ /account/profile 1.79 kB 138 kB
97
97
  ├ └ css/831a1f72fe4b2d80.css 3.97 kB
98
- ├ λ /account/security 2.48 kB 138 kB
98
+ ├ λ /account/security 2.48 kB 139 kB
99
99
  ├ └ css/32b1696118552960.css 5.19 kB
100
- ├ λ /account/user-details 1.74 kB 137 kB
100
+ ├ λ /account/user-details 1.74 kB 138 kB
101
101
  ├ └ css/e46393a76c5d93a9.css 4.17 kB
102
- ├ λ /api/graphql 0 B 105 kB
103
- ├ λ /api/health/live 0 B 105 kB
104
- ├ λ /api/health/ready 0 B 105 kB
105
- ├ λ /api/preview 0 B 105 kB
106
- ├ ● /checkout 737 B 136 kB
107
- ├ ● /login 1.68 kB 137 kB
108
- └ ● /s 3.28 kB 148 kB
109
- + First Load JS shared by all 108 kB
102
+ ├ λ /api/graphql 0 B 106 kB
103
+ ├ λ /api/health/live 0 B 106 kB
104
+ ├ λ /api/health/ready 0 B 106 kB
105
+ ├ λ /api/preview 0 B 106 kB
106
+ ├ ● /checkout 737 B 137 kB
107
+ ├ ● /login 1.68 kB 138 kB
108
+ └ ● /s 3.28 kB 149 kB
109
+ + First Load JS shared by all 109 kB
110
110
  ├ chunks/framework-807b0f81cbc129f0.js 45.4 kB
111
111
  ├ chunks/main-f658704b53a96ab1.js 33.1 kB
112
- ├ chunks/pages/_app-728289774860e9d9.js 22.8 kB
113
- ├ chunks/webpack-50cb24c3054682c1.js 3.81 kB
112
+ ├ chunks/pages/_app-4068e2b477988545.js 23.5 kB
113
+ ├ chunks/webpack-2ddf567180dd5aaa.js 3.81 kB
114
114
  └ css/0a57ee6c7a57788c.css 3.49 kB
115
115
 
116
116
  λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps)
@@ -1,14 +1,14 @@
1
1
 
2
- > @faststore/core@3.70.2 test /home/runner/work/faststore/faststore/packages/core
2
+ > @faststore/core@3.72.0 test /home/runner/work/faststore/faststore/packages/core
3
3
  > jest
4
4
 
5
- PASS test/server/cms/global.test.ts (26.235 s)
6
- PASS test/utils/multipleTemplates.test.ts (26.425 s)
5
+ PASS test/utils/multipleTemplates.test.ts (26.191 s)
6
+ PASS test/server/cms/global.test.ts (26.533 s)
7
7
  PASS test/server/cms/index.test.ts
8
- PASS test/server/index.test.ts (29.853 s)
8
+ PASS test/server/index.test.ts (30.044 s)
9
9
 
10
10
  Test Suites: 4 passed, 4 total
11
11
  Tests: 22 passed, 22 total
12
12
  Snapshots: 0 total
13
- Time: 31.157 s
13
+ Time: 31.403 s
14
14
  Ran all test suites.
package/@generated/gql.ts CHANGED
@@ -82,7 +82,7 @@ const documents = {
82
82
  types.ClientSearchSuggestionsQueryDocument,
83
83
  '\n query ClientTopSearchSuggestionsQuery(\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]\n ) {\n ...ClientTopSearchSuggestions\n search(first: 5, term: $term, selectedFacets: $selectedFacets) {\n suggestions {\n terms {\n value\n }\n }\n }\n }\n':
84
84
  types.ClientTopSearchSuggestionsQueryDocument,
85
- '\n mutation ValidateSession($session: IStoreSession!, $search: String!) {\n validateSession(session: $session, search: $search) {\n locale\n channel\n country\n addressType\n postalCode\n city\n deliveryMode {\n deliveryChannel\n deliveryMethod\n deliveryWindow {\n startDate\n endDate\n }\n }\n geoCoordinates {\n latitude\n longitude\n }\n currency {\n code\n symbol\n }\n person {\n id\n email\n givenName\n familyName\n }\n b2b {\n customerId\n isRepresentative\n unitName\n unitId\n firstName\n lastName\n userName\n userEmail\n savedPostalCode\n }\n marketingData {\n utmCampaign\n utmMedium\n utmSource\n utmiCampaign\n utmiPage\n utmiPart\n }\n }\n }\n':
85
+ '\n mutation ValidateSession($session: IStoreSession!, $search: String!) {\n validateSession(session: $session, search: $search) {\n locale\n channel\n country\n addressType\n postalCode\n city\n deliveryMode {\n deliveryChannel\n deliveryMethod\n deliveryWindow {\n startDate\n endDate\n }\n }\n geoCoordinates {\n latitude\n longitude\n }\n currency {\n code\n symbol\n }\n person {\n id\n email\n givenName\n familyName\n }\n b2b {\n customerId\n isRepresentative\n unitName\n unitId\n firstName\n lastName\n userName\n userEmail\n savedPostalCode\n }\n marketingData {\n utmCampaign\n utmMedium\n utmSource\n utmiCampaign\n utmiPage\n utmiPart\n }\n refreshAfter\n }\n }\n':
86
86
  types.ValidateSessionDocument,
87
87
  '\n query ClientShippingSimulationQuery(\n $postalCode: String!\n $country: String!\n $items: [IShippingItem!]!\n ) {\n ...ClientShippingSimulation\n shipping(items: $items, postalCode: $postalCode, country: $country) {\n logisticsInfo {\n slas {\n carrier\n price\n availableDeliveryWindows {\n startDateUtc\n endDateUtc\n price\n listPrice\n }\n shippingEstimate\n localizedEstimates\n deliveryChannel\n }\n }\n address {\n city\n neighborhood\n state\n }\n }\n }\n':
88
88
  types.ClientShippingSimulationQueryDocument,
@@ -304,7 +304,7 @@ export function gql(
304
304
  * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
305
305
  */
306
306
  export function gql(
307
- source: '\n mutation ValidateSession($session: IStoreSession!, $search: String!) {\n validateSession(session: $session, search: $search) {\n locale\n channel\n country\n addressType\n postalCode\n city\n deliveryMode {\n deliveryChannel\n deliveryMethod\n deliveryWindow {\n startDate\n endDate\n }\n }\n geoCoordinates {\n latitude\n longitude\n }\n currency {\n code\n symbol\n }\n person {\n id\n email\n givenName\n familyName\n }\n b2b {\n customerId\n isRepresentative\n unitName\n unitId\n firstName\n lastName\n userName\n userEmail\n savedPostalCode\n }\n marketingData {\n utmCampaign\n utmMedium\n utmSource\n utmiCampaign\n utmiPage\n utmiPart\n }\n }\n }\n'
307
+ source: '\n mutation ValidateSession($session: IStoreSession!, $search: String!) {\n validateSession(session: $session, search: $search) {\n locale\n channel\n country\n addressType\n postalCode\n city\n deliveryMode {\n deliveryChannel\n deliveryMethod\n deliveryWindow {\n startDate\n endDate\n }\n }\n geoCoordinates {\n latitude\n longitude\n }\n currency {\n code\n symbol\n }\n person {\n id\n email\n givenName\n familyName\n }\n b2b {\n customerId\n isRepresentative\n unitName\n unitId\n firstName\n lastName\n userName\n userEmail\n savedPostalCode\n }\n marketingData {\n utmCampaign\n utmMedium\n utmSource\n utmiCampaign\n utmiPage\n utmiPart\n }\n refreshAfter\n }\n }\n'
308
308
  ): typeof import('./graphql').ValidateSessionDocument
309
309
  /**
310
310
  * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
@@ -571,6 +571,8 @@ export type IStoreSession = {
571
571
  person: InputMaybe<IStorePerson>
572
572
  /** Session input postal code. */
573
573
  postalCode: InputMaybe<Scalars['String']['input']>
574
+ /** Refresh token after Information. */
575
+ refreshAfter: InputMaybe<Scalars['String']['input']>
574
576
  }
575
577
 
576
578
  /** Input to the cancel order API. */
@@ -1543,6 +1545,8 @@ export type StoreSession = {
1543
1545
  person: Maybe<StorePerson>
1544
1546
  /** Session postal code. */
1545
1547
  postalCode: Maybe<Scalars['String']['output']>
1548
+ /** Refresh token after Information. */
1549
+ refreshAfter: Maybe<Scalars['String']['output']>
1546
1550
  }
1547
1551
 
1548
1552
  /** Product search results sorting options. */
@@ -3372,6 +3376,7 @@ export type ValidateSessionMutation = {
3372
3376
  addressType: string | null
3373
3377
  postalCode: string | null
3374
3378
  city: string | null
3379
+ refreshAfter: string | null
3375
3380
  deliveryMode: {
3376
3381
  deliveryChannel: string
3377
3382
  deliveryMethod: string
@@ -4166,7 +4171,7 @@ export const ClientTopSearchSuggestionsQueryDocument = {
4166
4171
  export const ValidateSessionDocument = {
4167
4172
  __meta__: {
4168
4173
  operationName: 'ValidateSession',
4169
- operationHash: '259dd10b1c65ce4b20c9181feb7bec85ecb402e6',
4174
+ operationHash: '5da2700f5a69ee8835b1cb6c69e14f4b6e12c4df',
4170
4175
  },
4171
4176
  } as unknown as TypedDocumentString<
4172
4177
  ValidateSessionMutation,
@@ -21,7 +21,7 @@
21
21
  "34ea14c0d4a57ddf9bc11e4be0cd2b5a6506d3d4": "query ClientProfileQuery($id: String!) { profile(id: $id) { addresses { city country geoCoordinate postalCode } } }",
22
22
  "b548281d477a173be7b6960434604d69769a97e7": "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 skuVariants { activeVariations allVariantsByName availableVariations slugsMap } } name offers { lowPrice lowPriceWithTaxes offers { availability listPrice listPriceWithTaxes price priceWithTaxes quantity seller { identifier } } } id: productID sku slug unitMultiplier } 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 }",
23
23
  "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 }",
24
- "259dd10b1c65ce4b20c9181feb7bec85ecb402e6": "mutation ValidateSession($search: String!, $session: IStoreSession!) { validateSession(session: $session, search: $search) { addressType b2b { customerId firstName isRepresentative lastName savedPostalCode unitId unitName userEmail userName } channel city country currency { code symbol } deliveryMode { deliveryChannel deliveryMethod deliveryWindow { endDate startDate } } geoCoordinates { latitude longitude } locale marketingData { utmCampaign utmMedium utmSource utmiCampaign utmiPage utmiPart } person { email familyName givenName id } postalCode } }",
24
+ "5da2700f5a69ee8835b1cb6c69e14f4b6e12c4df": "mutation ValidateSession($search: String!, $session: IStoreSession!) { validateSession(session: $session, search: $search) { addressType b2b { customerId firstName isRepresentative lastName savedPostalCode unitId unitName userEmail userName } channel city country currency { code symbol } deliveryMode { deliveryChannel deliveryMethod deliveryWindow { endDate startDate } } geoCoordinates { latitude longitude } locale marketingData { utmCampaign utmMedium utmSource utmiCampaign utmiPage utmiPart } person { email familyName givenName id } postalCode refreshAfter } }",
25
25
  "c35bad22f67f3eb34fea52bb49efa6b1da6b728d": "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 deliveryChannel localizedEstimates price shippingEstimate } } } ...ClientShippingSimulation }",
26
26
  "5c2181dde311ca80b72e0cc76ac0855d8aa8b51e": "fragment ClientManyProducts on Query { search( first: $first after: $after sort: $sort term: $term selectedFacets: $selectedFacets sponsoredCount: $sponsoredCount ) { 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 skuVariants { activeVariations allVariantsByName availableVariations slugsMap } } name offers { lowPrice lowPriceWithTaxes offers { availability listPrice listPriceWithTaxes price priceWithTaxes quantity seller { identifier } } } id: productID sku slug unitMultiplier } fragment SearchEvent_metadata on SearchMetadata { fuzzy isTermMisspelled logicalOperator } query ServerManyProductsQuery($after: String, $first: Int!, $selectedFacets: [IStoreSelectedFacet!]!, $sort: StoreSort!, $sponsoredCount: Int, $term: String!) { search( first: $first after: $after sort: $sort term: $term selectedFacets: $selectedFacets sponsoredCount: $sponsoredCount ) { metadata { ...SearchEvent_metadata } products { edges { node { ...ProductSummary_product } } pageInfo { totalCount } } } ...ClientManyProducts }"
27
27
  }
@@ -1207,6 +1207,8 @@ type StoreSession {
1207
1207
  b2b: StoreB2B
1208
1208
  """Marketing information."""
1209
1209
  marketingData: StoreMarketingData
1210
+ """Refresh token after Information."""
1211
+ refreshAfter: String
1210
1212
  }
1211
1213
 
1212
1214
  type StoreB2B {
@@ -1259,6 +1261,8 @@ input IStoreSession {
1259
1261
  b2b: IStoreB2B
1260
1262
  """Marketing information input."""
1261
1263
  marketingData: IStoreMarketingData
1264
+ """Refresh token after Information."""
1265
+ refreshAfter: String
1262
1266
  }
1263
1267
 
1264
1268
  """Shipping Simulation item input."""
package/CHANGELOG.md CHANGED
@@ -3,6 +3,18 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [3.72.1](https://github.com/vtex/faststore/compare/v3.72.0...v3.72.1) (2025-08-07)
7
+
8
+ ### Bug Fixes
9
+
10
+ - Prevent PLPs' specific facets being cleared ([#2977](https://github.com/vtex/faststore/issues/2977)) ([e15ec3e](https://github.com/vtex/faststore/commit/e15ec3e851269d768a632da8683b5345937b66ca)), closes [vtex-sites/faststoreqa.store#853](https://github.com/vtex-sites/faststoreqa.store/issues/853)
11
+
12
+ # [3.72.0](https://github.com/vtex/faststore/compare/v3.71.0...v3.72.0) (2025-08-05)
13
+
14
+ ### Features
15
+
16
+ - refresh token - SFS-2462 ([#2936](https://github.com/vtex/faststore/issues/2936)) ([0fc856f](https://github.com/vtex/faststore/commit/0fc856f46ffe800debccd90078564e9ff524e727)), closes [#1](https://github.com/vtex/faststore/issues/1) [#2](https://github.com/vtex/faststore/issues/2)
17
+
6
18
  # [3.71.0](https://github.com/vtex/faststore/compare/v3.70.2...v3.71.0) (2025-08-05)
7
19
 
8
20
  ### Features
@@ -66,6 +66,7 @@ module.exports = {
66
66
  utmiPart: '',
67
67
  utmiPage: '',
68
68
  },
69
+ refreshAfter: null, // timestamp in seconds e.g. '1743042990'
69
70
  },
70
71
 
71
72
  // Default cart
@@ -150,5 +151,6 @@ module.exports = {
150
151
  maxAge: 0, // 0 disables cache, 5 * 60 enable cache control maxAge 5 minutes
151
152
  staleWhileRevalidate: 60,
152
153
  },
154
+ refreshToken: false,
153
155
  },
154
156
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faststore/core",
3
- "version": "3.71.0",
3
+ "version": "3.72.1",
4
4
  "license": "MIT",
5
5
  "repository": "vtex/faststore",
6
6
  "browserslist": "supports es6-module and not dead",
@@ -44,10 +44,10 @@
44
44
  "@envelop/graphql-jit": "^8.0.3",
45
45
  "@envelop/parser-cache": "^6.0.2",
46
46
  "@envelop/validation-cache": "^6.0.2",
47
- "@faststore/api": "^3.71.0",
47
+ "@faststore/api": "^3.72.0",
48
48
  "@faststore/graphql-utils": "^3.56.1",
49
49
  "@faststore/lighthouse": "^3.56.1",
50
- "@faststore/sdk": "^3.68.0",
50
+ "@faststore/sdk": "^3.72.0",
51
51
  "@faststore/ui": "^3.70.2",
52
52
  "@graphql-codegen/cli": "5.0.2",
53
53
  "@graphql-codegen/client-preset": "4.2.6",
@@ -72,6 +72,7 @@
72
72
  "fs-extra": "^10.1.0",
73
73
  "graphql": "^15.6.0",
74
74
  "include-media": "^1.4.10",
75
+ "isomorphic-unfetch": "^3.1.0",
75
76
  "next": "^13.5.9",
76
77
  "next-seo": "^6.6.0",
77
78
  "postcss": "^8.4.4",
@@ -107,5 +108,5 @@
107
108
  "ts-jest": "29.1.1",
108
109
  "typescript": "5.3.2"
109
110
  },
110
- "gitHead": "b7c679e5d2795a867964017fdbb2b08eaec20e09"
111
+ "gitHead": "0fea186218657d0b90320ac376072e7f65192782"
111
112
  }
@@ -109,7 +109,9 @@ function ProductGallery({
109
109
 
110
110
  const hasFacetsLoaded = Boolean(data?.search?.facets)
111
111
  const hasProductsLoaded = Boolean(data?.search?.products)
112
- const filter = useFilter(facets)
112
+ const initialSelectedFacets =
113
+ (data as PLPContext['data'])?.collection?.meta?.selectedFacets ?? []
114
+ const filter = useFilter(facets, initialSelectedFacets)
113
115
 
114
116
  return (
115
117
  <section data-testid="product-gallery" data-fs-product-listing>
@@ -1,11 +1,13 @@
1
1
  import {
2
2
  BadRequestError,
3
+ UnauthorizedError,
3
4
  isFastStoreError,
4
5
  stringifyCacheControl,
5
6
  } from '@faststore/api'
6
7
  import type { NextApiHandler, NextApiRequest } from 'next'
7
8
 
8
9
  import discoveryConfig from 'discovery.config'
10
+ import { getJWTAutCookie, isExpired } from 'src/utils/getCookie'
9
11
  import { execute } from '../../server'
10
12
 
11
13
  const ONE_MINUTE = 60
@@ -75,6 +77,54 @@ const handler: NextApiHandler = async (request, response) => {
75
77
  try {
76
78
  const { operation, variables, query } = parseRequest(request)
77
79
 
80
+ if (
81
+ operation.__meta__.operationName === 'ValidateSession' &&
82
+ discoveryConfig.experimental?.refreshToken
83
+ ) {
84
+ const jwt = getJWTAutCookie({
85
+ headers: request.headers,
86
+ account: discoveryConfig.api.storeId,
87
+ })
88
+
89
+ const tokenExpired = Boolean(jwt && isExpired(Number(jwt?.exp)))
90
+
91
+ const refreshAfterExist = !!variables?.session?.refreshAfter
92
+
93
+ const refreshAfterExpired =
94
+ refreshAfterExist && isExpired(Number(variables.session.refreshAfter))
95
+
96
+ const tokenExistAndIsFirstRefreshTokenRequest =
97
+ !!jwt && !refreshAfterExist
98
+
99
+ // when token expired, browser clears the cookie, but we still have the refreshAfter in session and the refresh token cookie
100
+ const tokenNotExistAndRefreshAfterExistAndIsExpired =
101
+ !jwt && !!refreshAfterExist && refreshAfterExpired
102
+
103
+ const tokenExpiredAndRefreshAfterIsNullOrExpired =
104
+ tokenExpired && (!refreshAfterExist || refreshAfterExpired)
105
+
106
+ const shouldRefreshToken =
107
+ tokenExistAndIsFirstRefreshTokenRequest ||
108
+ tokenNotExistAndRefreshAfterExistAndIsExpired ||
109
+ tokenExpiredAndRefreshAfterIsNullOrExpired
110
+
111
+ if (shouldRefreshToken) {
112
+ throw new UnauthorizedError(
113
+ 'Unauthorized: Token expired. Please login again or refresh the page.'
114
+ )
115
+ }
116
+ }
117
+
118
+ // Prevents to call ValidateSession or ValidateCartMutation without session (required) and get GraphQLError
119
+ const doNotRun =
120
+ (operation.__meta__.operationName === 'ValidateSession' ||
121
+ operation.__meta__.operationName === 'ValidateCartMutation') &&
122
+ !variables?.session
123
+
124
+ if (doNotRun) {
125
+ return
126
+ }
127
+
78
128
  const { data, errors, extensions } = await execute(
79
129
  {
80
130
  operation,
@@ -138,7 +188,13 @@ const handler: NextApiHandler = async (request, response) => {
138
188
  return
139
189
  }
140
190
 
191
+ if (err instanceof UnauthorizedError) {
192
+ response.status(401).end()
193
+ return
194
+ }
195
+
141
196
  response.status(500).end()
197
+ return
142
198
  }
143
199
  }
144
200
 
@@ -81,5 +81,18 @@ const baseRequest = async <V = any, D = any>(
81
81
  },
82
82
  })
83
83
 
84
+ if (!response.ok) {
85
+ const statusText = response.statusText
86
+ return {
87
+ errors: [
88
+ {
89
+ status: response.status,
90
+ message: statusText,
91
+ },
92
+ ],
93
+ data: undefined,
94
+ } as GraphQLResponse<D>
95
+ }
96
+
84
97
  return response.json()
85
98
  }
@@ -88,7 +88,10 @@ const reducer = (state: State, action: Action) => {
88
88
  return state
89
89
  }
90
90
 
91
- export const useFilter = (allFacets: Filter_FacetsFragment[]) => {
91
+ export const useFilter = (
92
+ allFacets: Filter_FacetsFragment[],
93
+ initialSelectedFacets?: IStoreSelectedFacet[]
94
+ ) => {
92
95
  const {
93
96
  state: { selectedFacets },
94
97
  } = useSearch()
@@ -134,6 +137,16 @@ export const useFilter = (allFacets: Filter_FacetsFragment[]) => {
134
137
  [allFacets, selectedMap]
135
138
  )
136
139
 
140
+ // Restore initial PLP facets after clearing filters (e.g. { key: category-n, value: 'electronics' })
141
+ useEffect(() => {
142
+ if (initialSelectedFacets && selected.length === 0) {
143
+ dispatch({
144
+ type: 'selectFacets',
145
+ payload: initialSelectedFacets,
146
+ })
147
+ }
148
+ }, [initialSelectedFacets, selected])
149
+
137
150
  useEffect(() => {
138
151
  dispatch({
139
152
  type: 'selectFacets',
@@ -1,5 +1,6 @@
1
1
  import type { Session } from '@faststore/sdk'
2
2
  import { createSessionStore } from '@faststore/sdk'
3
+ import fetch from 'isomorphic-unfetch'
3
4
  import { useMemo } from 'react'
4
5
 
5
6
  import { gql } from '@generated'
@@ -7,12 +8,16 @@ import type {
7
8
  ValidateSessionMutation,
8
9
  ValidateSessionMutationVariables,
9
10
  } from '@generated/graphql'
11
+ import discoveryConfig from 'discovery.config'
12
+ import { sanitizeHost } from 'src/utils/utilities'
10
13
  import storeConfig from '../../../discovery.config'
11
14
  import { cartStore } from '../cart'
12
15
  import { request } from '../graphql/request'
13
16
  import { getSavedAddress } from '../profile'
14
17
  import { createValidationStore, useStore } from '../useStore'
15
18
 
19
+ const REFRESH_TOKEN_URL = `${discoveryConfig.storeUrl}/api/vtexid/refreshtoken/webstore`
20
+
16
21
  export const mutation = gql(`
17
22
  mutation ValidateSession($session: IStoreSession!, $search: String!) {
18
23
  validateSession(session: $session, search: $search) {
@@ -63,6 +68,7 @@ export const mutation = gql(`
63
68
  utmiPage
64
69
  utmiPart
65
70
  }
71
+ refreshAfter
66
72
  }
67
73
  }
68
74
  `)
@@ -107,12 +113,54 @@ export const validateSession = async (session: Session) => {
107
113
  }
108
114
  }
109
115
 
110
- const data = await request<
111
- ValidateSessionMutation,
112
- ValidateSessionMutationVariables
113
- >(mutation, { session, search: window.location.search })
116
+ try {
117
+ // Prevents to call ValidateSession without session (required) and get Error
118
+ if (!session) {
119
+ return null
120
+ }
121
+
122
+ const data = await request<
123
+ ValidateSessionMutation,
124
+ ValidateSessionMutationVariables
125
+ >(mutation, { session, search: window.location.search })
126
+
127
+ return data.validateSession
128
+ } catch (error) {
129
+ const shouldRefreshToken =
130
+ error?.status === 401 && storeConfig.experimental?.refreshToken
131
+
132
+ if (shouldRefreshToken) {
133
+ const headers: HeadersInit = {
134
+ 'content-type': 'application/json',
135
+ Host: `${sanitizeHost(discoveryConfig.storeUrl)}`,
136
+ }
137
+
138
+ const result = await fetchWithRetry(REFRESH_TOKEN_URL, {
139
+ credentials: 'include',
140
+ headers,
141
+ body: JSON.stringify({}),
142
+ method: 'POST',
143
+ })
144
+
145
+ if (result?.status?.toLowerCase?.() === 'success') {
146
+ const refreshAfter = String(
147
+ Math.floor(new Date(result?.refreshAfter).getTime() / 1000)
148
+ )
114
149
 
115
- return data.validateSession
150
+ sessionStore.set({
151
+ ...session,
152
+ refreshAfter,
153
+ })
154
+ } else {
155
+ // If the refresh token fails 3x, set the refreshAfter to now + 1 hour
156
+ // so that we can postpone refreshToken request and continue the ValidateSession request
157
+ sessionStore.set({
158
+ ...session,
159
+ refreshAfter: String(Math.floor(Date.now() / 1000) + 1 * 60 * 60), // now + 1 hour
160
+ })
161
+ }
162
+ }
163
+ }
116
164
  }
117
165
 
118
166
  const [validationStore, onValidate] = createValidationStore(validateSession)
@@ -145,8 +193,10 @@ interface SessionOptions {
145
193
  */
146
194
 
147
195
  export const useSession = ({ filter }: SessionOptions = { filter: true }) => {
148
- let { channel, ...session } = useStore(sessionStore)
196
+ const currentSessionStore = sessionStore.read() ?? sessionStore.readInitial()
197
+ const resultSessionStore = useStore(sessionStore)
149
198
  const isValidating = useStore(validationStore)
199
+ let { channel, ...session } = resultSessionStore ?? currentSessionStore
150
200
 
151
201
  if (filter) {
152
202
  const { hasOnlyDefaultSalesChannel, ...filteredChannel } =
@@ -163,3 +213,23 @@ export const useSession = ({ filter }: SessionOptions = { filter: true }) => {
163
213
  [isValidating, session, channel]
164
214
  )
165
215
  }
216
+
217
+ async function fetchWithRetry(
218
+ url: RequestInfo | URL,
219
+ init?: RequestInit,
220
+ maxRetries = 3
221
+ ) {
222
+ for (let i = 0; i < maxRetries; i++) {
223
+ try {
224
+ const res = await fetch(url, init)
225
+ if (res.status !== 200) continue
226
+
227
+ const data = await res.json()
228
+ if (data.status?.toLowerCase?.() === 'success') {
229
+ return data
230
+ }
231
+ } catch {}
232
+ }
233
+
234
+ return
235
+ }
@@ -1,3 +1,13 @@
1
+ import { parse } from 'cookie'
2
+ import type { NextApiRequest } from 'next/types'
3
+
4
+ type Params = {
5
+ headers?: Record<string, string> | NextApiRequest['headers']
6
+ account: string
7
+ }
8
+
9
+ const MILLISECONDS_PER_SECOND = 1000
10
+
1
11
  export function getCookie(name: string): string | undefined {
2
12
  const cookieString = decodeURIComponent(document.cookie)
3
13
  const cookies = cookieString.split(';')
@@ -19,3 +29,15 @@ export function parseJwt(token: string) {
19
29
  }
20
30
  return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString())
21
31
  }
32
+
33
+ export function getJWTAutCookie({ headers, account }: Params) {
34
+ const authCookie = parse(headers?.cookie ?? '')?.[
35
+ 'VtexIdclientAutCookie_' + account
36
+ ]
37
+ return parseJwt(authCookie)
38
+ }
39
+
40
+ export function isExpired(exp: number): boolean {
41
+ const now = Math.floor(Date.now() / MILLISECONDS_PER_SECOND)
42
+ return now > exp
43
+ }