@faststore/core 3.90.1 → 3.91.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 (118) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +43 -43
  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 +10 -10
  12. package/.next/routes-manifest.json +1 -1
  13. package/.next/server/chunks/4168.js +1 -1
  14. package/.next/server/chunks/870.js +1 -1
  15. package/.next/server/chunks/8737.js +1 -0
  16. package/.next/server/chunks/948.js +1 -1
  17. package/.next/server/chunks/9563.js +3 -3
  18. package/.next/server/chunks/9630.js +3 -3
  19. package/.next/server/chunks/UISKUMatrixSidebar.js +1 -1
  20. package/.next/server/functions-config-manifest.json +1 -1
  21. package/.next/server/middleware-build-manifest.js +1 -1
  22. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  23. package/.next/server/pages/404.js.nft.json +1 -1
  24. package/.next/server/pages/500.js.nft.json +1 -1
  25. package/.next/server/pages/[...slug].js +1 -1
  26. package/.next/server/pages/[...slug].js.nft.json +1 -1
  27. package/.next/server/pages/[slug]/p.js +1 -1
  28. package/.next/server/pages/[slug]/p.js.nft.json +1 -1
  29. package/.next/server/pages/_app.js.nft.json +1 -1
  30. package/.next/server/pages/_document.js.nft.json +1 -1
  31. package/.next/server/pages/_error.js.nft.json +1 -1
  32. package/.next/server/pages/api/graphql.js +3 -3
  33. package/.next/server/pages/api/graphql.js.nft.json +1 -1
  34. package/.next/server/pages/api/health/live.js.nft.json +1 -1
  35. package/.next/server/pages/api/health/ready.js.nft.json +1 -1
  36. package/.next/server/pages/api/preview.js.nft.json +1 -1
  37. package/.next/server/pages/checkout.js.nft.json +1 -1
  38. package/.next/server/pages/en-US/404.html +1 -1
  39. package/.next/server/pages/en-US/500.html +1 -1
  40. package/.next/server/pages/en-US/checkout.html +1 -1
  41. package/.next/server/pages/en-US/login.html +1 -1
  42. package/.next/server/pages/en-US/s.html +1 -1
  43. package/.next/server/pages/en-US.html +1 -1
  44. package/.next/server/pages/index.js +1 -1
  45. package/.next/server/pages/index.js.nft.json +1 -1
  46. package/.next/server/pages/login.js.nft.json +1 -1
  47. package/.next/server/pages/pvt/account/403.js +1 -1
  48. package/.next/server/pages/pvt/account/403.js.nft.json +1 -1
  49. package/.next/server/pages/pvt/account/404.js +1 -1
  50. package/.next/server/pages/pvt/account/404.js.nft.json +1 -1
  51. package/.next/server/pages/pvt/account/[...unknown].js.nft.json +1 -1
  52. package/.next/server/pages/pvt/account/orders/[id].js +1 -1
  53. package/.next/server/pages/pvt/account/orders/[id].js.nft.json +1 -1
  54. package/.next/server/pages/pvt/account/orders.js +1 -1
  55. package/.next/server/pages/pvt/account/orders.js.nft.json +1 -1
  56. package/.next/server/pages/pvt/account/profile.js +1 -1
  57. package/.next/server/pages/pvt/account/profile.js.nft.json +1 -1
  58. package/.next/server/pages/pvt/account/security.js +1 -1
  59. package/.next/server/pages/pvt/account/security.js.nft.json +1 -1
  60. package/.next/server/pages/pvt/account/user-details.js +1 -1
  61. package/.next/server/pages/pvt/account/user-details.js.nft.json +1 -1
  62. package/.next/server/pages/pvt/account.js +1 -1
  63. package/.next/server/pages/pvt/account.js.nft.json +1 -1
  64. package/.next/server/pages/s.js +1 -1
  65. package/.next/server/pages/s.js.nft.json +1 -1
  66. package/.next/server/pages-manifest.json +1 -1
  67. package/.next/static/_XLT4LTVmSQNrq66-Y4kE/_buildManifest.js +1 -0
  68. package/.next/static/chunks/{2927.23bae2c79f0ac0f3.js → 2927.5a79877943a6bf7c.js} +1 -1
  69. package/.next/static/chunks/4803.18fbf77cd924d443.js +1 -0
  70. package/.next/static/chunks/{7191-7fb36e620e08cb4c.js → 7191-eef95438b827504b.js} +1 -1
  71. package/.next/static/chunks/9173-51ba7ca2f546f879.js +1 -0
  72. package/.next/static/chunks/9979.aedbc094bdc2c599.js +1 -0
  73. package/.next/static/chunks/{RegionSlider.d295bcc2f86210cd.js → RegionSlider.13955219e942a100.js} +1 -1
  74. package/.next/static/chunks/UISKUMatrixSidebar.2cfa8552a84d2f5f.js +1 -0
  75. package/.next/static/chunks/UIToast.19a8664c01a00d3a.js +1 -0
  76. package/.next/static/chunks/pages/[slug]/{p-323813ea2a7455fb.js → p-5f89d29d02064f15.js} +1 -1
  77. package/.next/static/chunks/pages/_app-a0274d6a8f914190.js +1 -0
  78. package/.next/static/chunks/pages/{index-5c3eb58eefd7cb0f.js → index-f285046ed161df07.js} +1 -1
  79. package/.next/static/chunks/pages/pvt/account/403-91597100f8956385.js +1 -0
  80. package/.next/static/chunks/pages/pvt/account/orders/{[id]-459f6b9a86780410.js → [id]-c9b4eb96df4f566d.js} +1 -1
  81. package/.next/static/chunks/{webpack-7a160aaa24e51946.js → webpack-bce37557948d4c09.js} +1 -1
  82. package/.next/trace +138 -138
  83. package/.turbo/turbo-build.log +21 -21
  84. package/.turbo/turbo-test.log +5 -5
  85. package/@generated/schema.graphql +18 -16
  86. package/CHANGELOG.md +12 -0
  87. package/discovery.config.default.js +1 -1
  88. package/package.json +4 -4
  89. package/src/components/navigation/Navbar/Navbar.tsx +20 -12
  90. package/src/components/navigation/NavbarSlider/NavbarSlider.tsx +15 -8
  91. package/src/experimental/{myAccountSeverSideProps.ts → myAccountServerSideProps.ts} +18 -6
  92. package/src/pages/api/graphql.ts +20 -11
  93. package/src/pages/pvt/account/403.tsx +67 -48
  94. package/src/pages/pvt/account/404.tsx +16 -12
  95. package/src/pages/pvt/account/[...unknown].tsx +1 -1
  96. package/src/pages/pvt/account/index.tsx +0 -12
  97. package/src/pages/pvt/account/orders/[id].tsx +8 -15
  98. package/src/pages/pvt/account/orders/index.tsx +9 -15
  99. package/src/pages/pvt/account/profile.tsx +14 -21
  100. package/src/pages/pvt/account/security.tsx +7 -14
  101. package/src/pages/pvt/account/user-details.tsx +7 -14
  102. package/src/sdk/account/getMyAccountRoutes.ts +3 -2
  103. package/src/sdk/account/refreshToken.ts +50 -0
  104. package/src/sdk/account/useRefreshToken.ts +67 -0
  105. package/src/sdk/account/validateUser.ts +56 -12
  106. package/src/sdk/session/index.ts +75 -34
  107. package/src/server/index.ts +7 -1
  108. package/.next/server/chunks/5335.js +0 -1
  109. package/.next/server/chunks/7947.js +0 -1
  110. package/.next/static/1G1fFBbTvq0WaZ-0pahJG/_buildManifest.js +0 -1
  111. package/.next/static/chunks/2561.c30def9d5569bd92.js +0 -1
  112. package/.next/static/chunks/4803.c1405eca2ccf78c8.js +0 -1
  113. package/.next/static/chunks/9173-045983ab6e18cfb4.js +0 -1
  114. package/.next/static/chunks/UISKUMatrixSidebar.072f0b5bf8e172f6.js +0 -1
  115. package/.next/static/chunks/UIToast.3a8d6b20848b20e2.js +0 -1
  116. package/.next/static/chunks/pages/_app-494fa821daae1608.js +0 -1
  117. package/.next/static/chunks/pages/pvt/account/403-f2858569fde3873b.js +0 -1
  118. /package/.next/static/{1G1fFBbTvq0WaZ-0pahJG → _XLT4LTVmSQNrq66-Y4kE}/_ssgManifest.js +0 -0
@@ -1,23 +1,23 @@
1
1
 
2
- > @faststore/core@3.90.0 prebuild /home/runner/work/faststore/faststore/packages/core
2
+ > @faststore/core@3.91.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.90.0 partytown /home/runner/work/faststore/faststore/packages/core
6
+ > @faststore/core@3.91.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.90.0 generate /home/runner/work/faststore/faststore/packages/core
11
+ > @faststore/core@3.91.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.90.0 generate:schema /home/runner/work/faststore/faststore/packages/core
15
+ > @faststore/core@3.91.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.90.0 generate:codegen /home/runner/work/faststore/faststore/packages/core
20
+ > @faststore/core@3.91.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.90.0 format:generated /home/runner/work/faststore/faststore/packages/core
40
+ > @faststore/core@3.91.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.90.0 build /home/runner/work/faststore/faststore/packages/core
44
+ > @faststore/core@3.91.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,33 +73,33 @@ 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
- ┌ ● / 7.48 kB 146 kB
76
+ ┌ ● / 7.36 kB 146 kB
77
77
  ├ └ css/c29fee5b9f9d48d9.css 3.07 kB
78
- ├ /_app 0 B 107 kB
78
+ ├ /_app 0 B 108 kB
79
79
  ├ ● /[...slug] 2.49 kB 156 kB
80
- ├ ● /[slug]/p 97.6 kB 236 kB
80
+ ├ ● /[slug]/p 97.5 kB 236 kB
81
81
  ├ └ css/a9328b56f3942b82.css 22 kB
82
82
  ├ ○ /404 1.57 kB 140 kB
83
83
  ├ ● /500 1.57 kB 140 kB
84
- ├ λ /api/graphql 0 B 107 kB
85
- ├ λ /api/health/live 0 B 107 kB
86
- ├ λ /api/health/ready 0 B 107 kB
87
- ├ λ /api/preview 0 B 107 kB
84
+ ├ λ /api/graphql 0 B 108 kB
85
+ ├ λ /api/health/live 0 B 108 kB
86
+ ├ λ /api/health/ready 0 B 108 kB
87
+ ├ λ /api/preview 0 B 108 kB
88
88
  ├ ● /checkout 749 B 139 kB
89
89
  ├ ● /login 1.7 kB 140 kB
90
90
  ├ λ /pvt/account 247 B 108 kB
91
91
  ├ ● /pvt/account/[...unknown] 287 B 108 kB
92
- ├ λ /pvt/account/403 2.49 kB 141 kB
92
+ ├ λ /pvt/account/403 2.98 kB 142 kB
93
93
  ├ └ css/c53b17b6fa994508.css 4.66 kB
94
- ├ λ /pvt/account/404 2.18 kB 140 kB
94
+ ├ λ /pvt/account/404 2.18 kB 141 kB
95
95
  ├ └ css/ceb410a7062740d1.css 4.72 kB
96
96
  ├ λ /pvt/account/orders 10.6 kB 149 kB
97
97
  ├ └ css/244373752cfc52c7.css 13.9 kB
98
- ├ λ /pvt/account/orders/[id] 12.1 kB 150 kB
98
+ ├ λ /pvt/account/orders/[id] 12 kB 151 kB
99
99
  ├ └ css/da5bfb1f39c54578.css 13.3 kB
100
- ├ λ /pvt/account/profile 1.98 kB 140 kB
100
+ ├ λ /pvt/account/profile 1.98 kB 141 kB
101
101
  ├ └ css/b65e005fb943434c.css 4.4 kB
102
- ├ λ /pvt/account/security 3.96 kB 142 kB
102
+ ├ λ /pvt/account/security 3.96 kB 143 kB
103
103
  ├ └ css/6bb0abee27fe0019.css 5.65 kB
104
104
  ├ λ /pvt/account/user-details 1.91 kB 140 kB
105
105
  ├ └ css/bd121d85d6ceed46.css 4.52 kB
@@ -107,8 +107,8 @@ Route (pages) Size First Load JS
107
107
  + First Load JS shared by all 111 kB
108
108
  ├ chunks/framework-d514426edf885c68.js 45.4 kB
109
109
  ├ chunks/main-595f5e3b626b9fff.js 33.2 kB
110
- ├ chunks/pages/_app-494fa821daae1608.js 25 kB
111
- ├ chunks/webpack-7a160aaa24e51946.js 3.84 kB
110
+ ├ chunks/pages/_app-a0274d6a8f914190.js 25.2 kB
111
+ ├ chunks/webpack-bce37557948d4c09.js 3.84 kB
112
112
  └ css/24a5e8f6808266fe.css 3.53 kB
113
113
 
114
114
  λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps)
@@ -1,14 +1,14 @@
1
1
 
2
- > @faststore/core@3.90.0 test /home/runner/work/faststore/faststore/packages/core
2
+ > @faststore/core@3.91.0 test /home/runner/work/faststore/faststore/packages/core
3
3
  > jest
4
4
 
5
- PASS test/server/cms/global.test.ts (27.025 s)
6
- PASS test/utils/multipleTemplates.test.ts (27.238 s)
5
+ PASS test/utils/multipleTemplates.test.ts (28.701 s)
6
+ PASS test/server/cms/global.test.ts (28.869 s)
7
7
  PASS test/server/cms/index.test.ts
8
- PASS test/server/index.test.ts (30.022 s)
8
+ PASS test/server/index.test.ts (32.67 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.191 s
13
+ Time: 34.049 s
14
14
  Ran all test suites.
@@ -5,6 +5,8 @@ schema {
5
5
 
6
6
  directive @cacheControl(sMaxAge: Int, staleWhileRevalidate: Int, scope: String) on FIELD_DEFINITION
7
7
 
8
+ directive @auth on FIELD_DEFINITION
9
+
8
10
  """Address information."""
9
11
  type Address {
10
12
  """Address postal code"""
@@ -948,12 +950,12 @@ type Query {
948
950
  product(
949
951
  """An array of selected search facets."""
950
952
  locator: [IStoreSelectedFacet!]!
951
- ): StoreProduct! @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
953
+ ): StoreProduct! @cacheControl(scope: "public", sMaxAge: 300, staleWhileRevalidate: 3600)
952
954
  """Returns the details of a collection based on the collection slug."""
953
955
  collection(
954
956
  """Collection slug."""
955
957
  slug: String!
956
- ): StoreCollection! @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
958
+ ): StoreCollection! @cacheControl(scope: "public", sMaxAge: 300, staleWhileRevalidate: 3600)
957
959
  """Returns the result of a product, facet, or suggestion search."""
958
960
  search(
959
961
  """Search pagination argument, indicating how many results should be returned from the complete result list."""
@@ -968,23 +970,23 @@ type Query {
968
970
  selectedFacets: [IStoreSelectedFacet!]
969
971
  """Search advertisement products return in result."""
970
972
  sponsoredCount: Int
971
- ): StoreSearchResult! @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
973
+ ): StoreSearchResult! @cacheControl(scope: "public", sMaxAge: 300, staleWhileRevalidate: 3600)
972
974
  """Returns information about all products."""
973
975
  allProducts(
974
976
  """Product pagination argument, indicating how many items should be returned from the complete result list."""
975
977
  first: Int!
976
978
  """Product pagination argument, indicating the cursor corresponding with the item after which the items should be fetched."""
977
979
  after: String
978
- ): StoreProductConnection! @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
980
+ ): StoreProductConnection! @cacheControl(scope: "public", sMaxAge: 300, staleWhileRevalidate: 3600)
979
981
  """Returns information about selected products."""
980
- products(productIds: [String!]!): [StoreProduct!]! @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
982
+ products(productIds: [String!]!): [StoreProduct!]! @cacheControl(scope: "public", sMaxAge: 300, staleWhileRevalidate: 3600)
981
983
  """Returns information about all collections."""
982
984
  allCollections(
983
985
  """Collection pagination argument, indicating how many items should be returned from the complete result list."""
984
986
  first: Int!
985
987
  """Collection pagination argument, indicating the cursor corresponding with the item after which the items should be fetched."""
986
988
  after: String
987
- ): StoreCollectionConnection! @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
989
+ ): StoreCollectionConnection! @cacheControl(scope: "public", sMaxAge: 300, staleWhileRevalidate: 3600)
988
990
  """Returns information about shipping simulation."""
989
991
  shipping(
990
992
  """List of SKU products"""
@@ -993,7 +995,7 @@ type Query {
993
995
  postalCode: String!
994
996
  """Country of postal code"""
995
997
  country: String!
996
- ): ShippingData @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
998
+ ): ShippingData @cacheControl(scope: "public", sMaxAge: 300, staleWhileRevalidate: 3600)
997
999
  """Returns if there's a redirect for a search."""
998
1000
  redirect(
999
1001
  """Search term."""
@@ -1011,22 +1013,22 @@ type Query {
1011
1013
  country: String!
1012
1014
  """Sales channel of the navigation"""
1013
1015
  salesChannel: String
1014
- ): SellersData @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
1016
+ ): SellersData @cacheControl(scope: "public", sMaxAge: 300, staleWhileRevalidate: 3600)
1015
1017
  """Returns information about the profile."""
1016
1018
  profile(
1017
1019
  """Identifier for user."""
1018
1020
  id: String!
1019
- ): Profile @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
1021
+ ): Profile @cacheControl(scope: "public", sMaxAge: 300, staleWhileRevalidate: 3600)
1020
1022
  """Returns the total product count information based on a specific location accessible through the VTEX segment cookie."""
1021
1023
  productCount(
1022
1024
  """Search term."""
1023
1025
  term: String
1024
- ): ProductCountResult @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
1026
+ ): ProductCountResult @cacheControl(scope: "public", sMaxAge: 300, staleWhileRevalidate: 3600)
1025
1027
  """Returns information about the Details of an User Order."""
1026
1028
  userOrder(
1027
1029
  """Identifier for the order."""
1028
1030
  orderId: String!
1029
- ): UserOrderResult @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
1031
+ ): UserOrderResult @auth @cacheControl(scope: "private", sMaxAge: 300, staleWhileRevalidate: 3600)
1030
1032
  """Returns information about the list of Orders that the User can view."""
1031
1033
  listUserOrders(
1032
1034
  """Page number of the list of orders."""
@@ -1043,18 +1045,18 @@ type Query {
1043
1045
  text: String
1044
1046
  """Client email used to filter of the list of orders."""
1045
1047
  clientEmail: String
1046
- ): UserOrderListMinimalResult @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
1048
+ ): UserOrderListMinimalResult @auth @cacheControl(scope: "private", sMaxAge: 300, staleWhileRevalidate: 3600)
1047
1049
  """Returns information about the current user details."""
1048
- userDetails: StoreUserDetails! @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
1050
+ userDetails: StoreUserDetails! @auth @cacheControl(scope: "private", sMaxAge: 300, staleWhileRevalidate: 3600)
1049
1051
  """Returns the account profile information for the current authenticated user (b2b or b2c user)."""
1050
- accountProfile: StoreAccountProfile! @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
1052
+ accountProfile: StoreAccountProfile! @auth @cacheControl(scope: "private", sMaxAge: 300, staleWhileRevalidate: 3600)
1051
1053
  """Returns information about the user validation."""
1052
- validateUser: ValidateUserData @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
1054
+ validateUser: ValidateUserData @auth @cacheControl(scope: "private", sMaxAge: 300, staleWhileRevalidate: 3600)
1053
1055
  """Returns a list of pickup points near to the given geo coordinates."""
1054
1056
  pickupPoints(
1055
1057
  """Geo coordinates input."""
1056
1058
  geoCoordinates: IStoreGeoCoordinates
1057
- ): PickupPoints @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600)
1059
+ ): PickupPoints @cacheControl(scope: "public", sMaxAge: 300, staleWhileRevalidate: 3600)
1058
1060
  }
1059
1061
 
1060
1062
  type ValidateUserData {
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.91.1](https://github.com/vtex/faststore/compare/v3.91.0...v3.91.1) (2025-10-24)
7
+
8
+ ### Bug Fixes
9
+
10
+ - signin button flickering - SFS-2862 ([#3078](https://github.com/vtex/faststore/issues/3078)) ([edd4ac0](https://github.com/vtex/faststore/commit/edd4ac084817467e6dcedc6cd5fe89923b0f55e3))
11
+
12
+ # [3.91.0](https://github.com/vtex/faststore/compare/v3.90.1...v3.91.0) (2025-10-24)
13
+
14
+ ### Features
15
+
16
+ - user validation improvements + refresh token SSR and api - SFS-2909 ([#3065](https://github.com/vtex/faststore/issues/3065)) ([97071ee](https://github.com/vtex/faststore/commit/97071ee21fcee0b038dfafa06633ef597136898e))
17
+
6
18
  ## [3.90.1](https://github.com/vtex/faststore/compare/v3.90.0...v3.90.1) (2025-10-20)
7
19
 
8
20
  ### Bug Fixes
@@ -149,7 +149,7 @@ module.exports = {
149
149
  enableVtexAssetsLoader: false,
150
150
  graphqlCacheControl: {
151
151
  maxAge: 0, // 0 disables cache, 5 * 60 enable cache control maxAge 5 minutes
152
- staleWhileRevalidate: 60,
152
+ staleWhileRevalidate: 60 * 60, // 1 hour
153
153
  },
154
154
  refreshToken: false,
155
155
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faststore/core",
3
- "version": "3.90.1",
3
+ "version": "3.91.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.90.0",
47
+ "@faststore/api": "^3.91.0",
48
48
  "@faststore/graphql-utils": "^3.89.2",
49
49
  "@faststore/lighthouse": "^3.89.2",
50
- "@faststore/sdk": "^3.90.0",
50
+ "@faststore/sdk": "^3.91.1",
51
51
  "@faststore/ui": "^3.89.2",
52
52
  "@graphql-codegen/cli": "5.0.2",
53
53
  "@graphql-codegen/client-preset": "4.2.6",
@@ -116,5 +116,5 @@
116
116
  "ts-jest": "29.1.1",
117
117
  "typescript": "5.3.2"
118
118
  },
119
- "gitHead": "63c402037eecf654247a393ce446167169466558"
119
+ "gitHead": "118484d3785eb470f0dbac737843f3cfc340f32a"
120
120
  }
@@ -1,14 +1,15 @@
1
- import { useCallback, useRef, useState } from 'react'
2
1
  import dynamic from 'next/dynamic'
2
+ import { useCallback, useRef, useState } from 'react'
3
3
 
4
4
  import { Icon as UIIcon, useScrollDirection, useUI } from '@faststore/ui'
5
5
 
6
+ import { Skeleton as UISkeleton } from '@faststore/ui'
7
+ import { OrganizationSignInButton } from 'src/components/account/MyAccountDrawer/OrganizationSignInButton'
8
+ import CartToggle from 'src/components/cart/CartToggle'
6
9
  import type { SearchInputRef } from 'src/components/search/SearchInput'
7
10
  import SearchInput from 'src/components/search/SearchInput'
8
- import CartToggle from 'src/components/cart/CartToggle'
9
11
  import Link from 'src/components/ui/Link'
10
12
  import Logo from 'src/components/ui/Logo'
11
- import { OrganizationSignInButton } from 'src/components/account/MyAccountDrawer/OrganizationSignInButton'
12
13
  import { useOverrideComponents } from 'src/sdk/overrides/OverrideContext'
13
14
  import { useSession } from 'src/sdk/session'
14
15
  import useScreenResize from 'src/sdk/ui/useScreenResize'
@@ -99,8 +100,8 @@ function Navbar({
99
100
  } = useOverrideComponents<'Navbar'>()
100
101
  const scrollDirection = useScrollDirection()
101
102
  const { openNavbar, navbar: displayNavbar } = useUI()
102
- const { isDesktop, isMobile } = useScreenResize()
103
- const { b2b } = useSession()
103
+ const { isDesktop } = useScreenResize()
104
+ const { b2b, isSessionReady } = useSession()
104
105
 
105
106
  const searchMobileRef = useRef<SearchInputRef>(null)
106
107
  const [searchExpanded, setSearchExpanded] = useState(false)
@@ -185,14 +186,21 @@ function Navbar({
185
186
  aria-hidden={!searchExpanded}
186
187
  />
187
188
  )}
188
- {!isMobile &&
189
- (isOrganizationEnabled ? (
190
- <OrganizationSignInButton
191
- icon={signInButton.icon}
192
- isRepresentative={isRepresentative}
193
- />
189
+ {isDesktop &&
190
+ (isSessionReady ? (
191
+ isOrganizationEnabled ? (
192
+ <OrganizationSignInButton
193
+ icon={signInButton.icon}
194
+ isRepresentative={isRepresentative}
195
+ />
196
+ ) : (
197
+ <ButtonSignIn.Component {...signInButton} />
198
+ )
194
199
  ) : (
195
- <ButtonSignIn.Component {...signInButton} />
200
+ <UISkeleton
201
+ data-fs-navbar-signin-skeleton
202
+ size={{ width: '140px', height: '2.5rem' }}
203
+ />
196
204
  ))}
197
205
 
198
206
  <CartToggle {...cart} />
@@ -1,4 +1,4 @@
1
- import { useFadeEffect, useUI } from '@faststore/ui'
1
+ import { Skeleton as UISkeleton, useFadeEffect, useUI } from '@faststore/ui'
2
2
  import { Suspense } from 'react'
3
3
 
4
4
  import storeConfig from 'discovery.config'
@@ -39,7 +39,7 @@ function NavbarSlider({
39
39
 
40
40
  const { closeNavbar } = useUI()
41
41
  const { fade, fadeOut } = useFadeEffect()
42
- const { b2b } = useSession()
42
+ const { b2b, isSessionReady } = useSession()
43
43
 
44
44
  const isFaststoreMyAccountEnabled =
45
45
  storeConfig.experimental?.enableFaststoreMyAccount
@@ -76,13 +76,20 @@ function NavbarSlider({
76
76
  </NavbarSliderContent.Component>
77
77
  <NavbarSliderFooter.Component {...NavbarSliderFooter.props}>
78
78
  <Suspense fallback={<ButtonSignInFallback />}>
79
- {isOrganizationEnabled ? (
80
- <OrganizationSignInButton
81
- icon={signInButton.icon}
82
- isRepresentative={isRepresentative}
83
- />
79
+ {isSessionReady ? (
80
+ isOrganizationEnabled ? (
81
+ <OrganizationSignInButton
82
+ icon={signInButton.icon}
83
+ isRepresentative={isRepresentative}
84
+ />
85
+ ) : (
86
+ <ButtonSignIn.Component {...signInButton} />
87
+ )
84
88
  ) : (
85
- <ButtonSignIn.Component {...signInButton} />
89
+ <UISkeleton
90
+ data-fs-navbar-slider-signin-skeleton
91
+ size={{ width: '140px', height: '2.5rem' }}
92
+ />
86
93
  )}
87
94
  </Suspense>
88
95
  </NavbarSliderFooter.Component>
@@ -37,9 +37,10 @@ export const getServerSideProps: GetServerSideProps<
37
37
  Record<string, string>,
38
38
  Locator
39
39
  > = async (context) => {
40
- const isValid = await validateUser(context)
40
+ const validationResult = await validateUser(context)
41
41
 
42
- if (!isValid) {
42
+ // Guard clause: Early redirect to login if user is invalid and doesn't need refresh
43
+ if (!validationResult.isValid && !validationResult.needsRefresh) {
43
44
  return {
44
45
  redirect: {
45
46
  destination: '/login',
@@ -48,10 +49,16 @@ export const getServerSideProps: GetServerSideProps<
48
49
  }
49
50
  }
50
51
 
51
- const isRepresentative = getIsRepresentative({
52
- headers: context.req.headers as Record<string, string>,
53
- account: storeConfig.api.storeId,
54
- })
52
+ // Handle refresh token case with minimal props
53
+ if (!validationResult.isValid && validationResult.needsRefresh) {
54
+ const currentPath = context.req.url || '/pvt/account'
55
+ return {
56
+ redirect: {
57
+ destination: `/pvt/account/403?from=${encodeURIComponent(currentPath)}`,
58
+ permanent: false,
59
+ },
60
+ }
61
+ }
55
62
 
56
63
  const { isFaststoreMyAccountEnabled, redirect } = getMyAccountRedirect({
57
64
  query: context.query,
@@ -61,6 +68,11 @@ export const getServerSideProps: GetServerSideProps<
61
68
  return { redirect }
62
69
  }
63
70
 
71
+ const isRepresentative = getIsRepresentative({
72
+ headers: context.req.headers as Record<string, string>,
73
+ account: storeConfig.api.storeId,
74
+ })
75
+
64
76
  const [
65
77
  globalSectionsPromise,
66
78
  globalSectionsHeaderPromise,
@@ -10,7 +10,8 @@ import discoveryConfig from 'discovery.config'
10
10
  import { getJWTAutCookie, isExpired } from 'src/utils/getCookie'
11
11
  import { execute } from '../../server'
12
12
 
13
- const ONE_MINUTE = 60
13
+ const DEFAULT_MAX_AGE = 5 * 60 // 5 minutes
14
+ const DEFAULT_STALE_WHILE_REVALIDATE = 60 * 60 // 1 hour
14
15
 
15
16
  /**
16
17
  * This function replaces the setCookie domain so that we can use localhost in dev environment.
@@ -144,26 +145,34 @@ const handler: NextApiHandler = async (request, response) => {
144
145
  return
145
146
  }
146
147
 
147
- const cacheControl =
148
- !hasErrors && extensions.cacheControl
149
- ? stringifyCacheControl(extensions.cacheControl)
150
- : 'no-cache, no-store'
151
-
152
- if (
148
+ if (extensions.cacheControl) {
149
+ const cacheControl = stringifyCacheControl(extensions.cacheControl)
150
+ response.setHeader('cache-control', cacheControl)
151
+ } else if (
153
152
  request.method === 'GET' &&
154
- discoveryConfig?.experimental?.graphqlCacheControl?.maxAge
153
+ operation.__meta__.operationName?.toLowerCase()?.endsWith('query')
155
154
  ) {
156
- const maxAge = discoveryConfig.experimental.graphqlCacheControl.maxAge
155
+ const maxAge =
156
+ discoveryConfig?.experimental?.graphqlCacheControl?.maxAge &&
157
+ discoveryConfig?.experimental?.graphqlCacheControl?.maxAge > 0
158
+ ? discoveryConfig.experimental.graphqlCacheControl.maxAge
159
+ : DEFAULT_MAX_AGE // 5 minutes
160
+
157
161
  const staleWhileRevalidate =
158
162
  discoveryConfig?.experimental?.graphqlCacheControl
159
- ?.staleWhileRevalidate ?? ONE_MINUTE
163
+ ?.staleWhileRevalidate &&
164
+ discoveryConfig?.experimental?.graphqlCacheControl
165
+ ?.staleWhileRevalidate > 0
166
+ ? discoveryConfig.experimental.graphqlCacheControl
167
+ .staleWhileRevalidate
168
+ : DEFAULT_STALE_WHILE_REVALIDATE // 1 hour
160
169
 
161
170
  response.setHeader(
162
171
  'cache-control',
163
172
  `public, s-maxage=${maxAge}, stale-while-revalidate=${staleWhileRevalidate}`
164
173
  )
165
174
  } else {
166
- response.setHeader('cache-control', cacheControl)
175
+ response.setHeader('cache-control', 'no-cache, no-store')
167
176
  }
168
177
 
169
178
  const setCookieValues = Array.from(extensions.cookies.values())
@@ -19,13 +19,14 @@ import RenderSections from 'src/components/cms/RenderSections'
19
19
  import { OverriddenDefaultEmptyState as EmptyState } from 'src/components/sections/EmptyState/OverriddenDefaultEmptyState'
20
20
  import CUSTOM_COMPONENTS from 'src/customizations/src/components'
21
21
  import PLUGINS_COMPONENTS from 'src/plugins'
22
- import { validateUser } from 'src/sdk/account/validateUser'
22
+ import { useRefreshToken } from 'src/sdk/account/useRefreshToken'
23
23
  import PageProvider from 'src/sdk/overrides/PageProvider'
24
24
  import { execute } from 'src/server'
25
- import { type PageContentType, getPage } from 'src/server/cms'
26
25
  import { injectGlobalSections } from 'src/server/cms/global'
27
26
  import { getMyAccountRedirect } from 'src/utils/myAccountRedirect'
28
27
 
28
+ import storeConfig from 'discovery.config'
29
+
29
30
  /* A list of components that can be used in the CMS. */
30
31
  const COMPONENTS: Record<string, ComponentType<any>> = {
31
32
  ...GLOBAL_COMPONENTS,
@@ -34,14 +35,31 @@ const COMPONENTS: Record<string, ComponentType<any>> = {
34
35
  }
35
36
 
36
37
  type Props = {
37
- globalSections: GlobalSectionsData
38
- accountName: ServerAccountPageQueryQuery['accountProfile']['name']
38
+ globalSections?: GlobalSectionsData
39
+ accountName?: ServerAccountPageQueryQuery['accountProfile']['name']
40
+ needsRefreshToken?: boolean
41
+ fromPage?: string
39
42
  }
40
43
 
41
- function Page({ globalSections: globalSectionsProp, accountName }: Props) {
44
+ function Page({
45
+ globalSections: globalSectionsProp,
46
+ accountName,
47
+ needsRefreshToken,
48
+ fromPage,
49
+ }: Props) {
42
50
  const { sections: globalSections, settings: globalSettings } =
43
- globalSectionsProp ?? {}
51
+ globalSectionsProp ?? { sections: [], settings: {} }
52
+
53
+ // Use the new hook to handle refresh token with session management
54
+ const { shouldShow403 } = useRefreshToken(needsRefreshToken, fromPage)
44
55
 
56
+ // Handle refresh token case - show loading while attempting refresh
57
+ if (needsRefreshToken && !shouldShow403) {
58
+ console.info('Refreshing authentication...')
59
+ return <></>
60
+ }
61
+
62
+ // Show 403 page if refresh failed or if we don't need refresh token
45
63
  return (
46
64
  <PageProvider context={{ globalSettings }}>
47
65
  <RenderSections globalSections={globalSections} components={COMPONENTS}>
@@ -77,13 +95,50 @@ export const getServerSideProps: GetServerSideProps<
77
95
  Record<string, string>,
78
96
  Locator
79
97
  > = async (context) => {
80
- const isValid = await validateUser(context)
98
+ const [
99
+ globalSectionsPromise,
100
+ globalSectionsHeaderPromise,
101
+ globalSectionsFooterPromise,
102
+ ] = getGlobalSectionsData(context.previewData)
103
+
104
+ const [account, globalSections, globalSectionsHeader, globalSectionsFooter] =
105
+ await Promise.all([
106
+ execute<
107
+ ServerAccountPageQueryQueryVariables,
108
+ ServerAccountPageQueryQuery
109
+ >(
110
+ {
111
+ variables: {},
112
+ operation: query,
113
+ },
114
+ { headers: { ...context.req.headers } }
115
+ ),
116
+ globalSectionsPromise,
117
+ globalSectionsHeaderPromise,
118
+ globalSectionsFooterPromise,
119
+ ])
120
+
121
+ const globalSectionsResult = injectGlobalSections({
122
+ globalSections,
123
+ globalSectionsHeader,
124
+ globalSectionsFooter,
125
+ })
126
+
127
+ if (account.errors) {
128
+ console.error(...account.errors)
129
+
130
+ const statusCode: number = (account.errors[0] as any)?.extensions?.status
131
+
132
+ const fromPage =
133
+ typeof context.query.from === 'string' ? context.query.from : ''
81
134
 
82
- if (!isValid) {
83
135
  return {
84
- redirect: {
85
- destination: '/login',
86
- permanent: false,
136
+ props: {
137
+ globalSections: globalSectionsResult,
138
+ needsRefreshToken:
139
+ (statusCode === 401 || statusCode === 403) &&
140
+ storeConfig.experimental?.refreshToken,
141
+ fromPage,
87
142
  },
88
143
  }
89
144
  }
@@ -96,47 +151,11 @@ export const getServerSideProps: GetServerSideProps<
96
151
  return { redirect }
97
152
  }
98
153
 
99
- const [
100
- globalSectionsPromise,
101
- globalSectionsHeaderPromise,
102
- globalSectionsFooterPromise,
103
- ] = getGlobalSectionsData(context.previewData)
104
-
105
- const [
106
- page,
107
- account,
108
- globalSections,
109
- globalSectionsHeader,
110
- globalSectionsFooter,
111
- ] = await Promise.all([
112
- getPage<PageContentType>({
113
- ...(context.previewData?.contentType === '403' && context.previewData),
114
- contentType: '403',
115
- }),
116
- execute<ServerAccountPageQueryQueryVariables, ServerAccountPageQueryQuery>(
117
- {
118
- variables: {},
119
- operation: query,
120
- },
121
- { headers: { ...context.req.headers } }
122
- ),
123
- globalSectionsPromise,
124
- globalSectionsHeaderPromise,
125
- globalSectionsFooterPromise,
126
- ])
127
-
128
- const globalSectionsResult = injectGlobalSections({
129
- globalSections,
130
- globalSectionsHeader,
131
- globalSectionsFooter,
132
- })
133
-
134
154
  return {
135
155
  props: {
136
156
  // The sections from the CMS page are not utilized here for the My Account page.
137
- // page,
138
157
  globalSections: globalSectionsResult,
139
- accountName: account.data.accountProfile.name,
158
+ accountName: account?.data?.accountProfile?.name ?? '',
140
159
  },
141
160
  }
142
161
  }