@faststore/core 3.98.2 → 3.98.4
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 +24 -24
- package/.next/cache/.tsbuildinfo +1 -1
- package/.next/cache/config.json +3 -3
- 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/prerender-manifest.js +1 -1
- package/.next/prerender-manifest.json +1 -1
- package/.next/react-loadable-manifest.json +7 -7
- package/.next/routes-manifest.json +1 -1
- package/.next/server/chunks/5133.js +1 -1
- package/.next/server/chunks/8971.js +1 -1
- package/.next/server/functions-config-manifest.json +1 -1
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/pages/[...slug].js +1 -1
- package/.next/server/pages/api/preview.js +1 -1
- package/.next/server/pages/en-US/404.html +2 -2
- package/.next/server/pages/en-US/500.html +2 -2
- package/.next/server/pages/en-US/checkout.html +2 -2
- package/.next/server/pages/en-US/login.html +2 -2
- package/.next/server/pages/en-US/s.html +2 -2
- package/.next/server/pages/en-US.html +2 -2
- package/.next/server/pages/s.js +1 -1
- package/.next/server/pages-manifest.json +1 -1
- package/.next/static/{RhuP_UJjSrpDj_sqLfUA9 → 9lFuk39f-HZcrM7Ul1Rlh}/_buildManifest.js +1 -1
- package/.next/static/chunks/{2811.cf089090a8b79215.js → 2811.0a4ea0e6fcf4c4c2.js} +1 -1
- package/.next/static/chunks/{2927.5a79877943a6bf7c.js → 2927.23bae2c79f0ac0f3.js} +1 -1
- package/.next/static/chunks/6656-7e6ea87d91e44b10.js +1 -0
- package/.next/static/chunks/{UIToast.19a8664c01a00d3a.js → UIToast.de15325248043ce5.js} +1 -1
- package/.next/static/chunks/pages/{_app-735c745509e1e8d6.js → _app-8be996b3105d8c26.js} +1 -1
- package/.next/static/chunks/{webpack-e3703857dd8c6937.js → webpack-fd706604cbbdc60f.js} +1 -1
- package/.next/trace +142 -142
- package/.turbo/turbo-build.log +11 -11
- package/.turbo/turbo-test.log +8 -9
- package/CHANGELOG.md +10 -0
- package/package.json +2 -2
- package/src/sdk/graphql/request.ts +1 -1
- package/src/sdk/product/usePageProductsQuery.ts +35 -4
- package/src/sdk/product/useProductGalleryQuery.ts +6 -1
- package/src/server/content/service.ts +3 -1
- package/src/utils/cookieCacheBusting.ts +79 -19
- package/test/utils/cookieCacheBusting.test.ts +167 -75
- package/.next/static/chunks/6656-efc464f20ffeaa51.js +0 -1
- /package/.next/static/{RhuP_UJjSrpDj_sqLfUA9 → 9lFuk39f-HZcrM7Ul1Rlh}/_ssgManifest.js +0 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
|
|
2
|
-
> @faststore/core@3.98.
|
|
2
|
+
> @faststore/core@3.98.3 prebuild /home/runner/work/faststore/faststore/packages/core
|
|
3
3
|
> na run partytown && na run generate
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @faststore/core@3.98.
|
|
6
|
+
> @faststore/core@3.98.3 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.98.
|
|
11
|
+
> @faststore/core@3.98.3 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.98.
|
|
15
|
+
> @faststore/core@3.98.3 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.98.
|
|
20
|
+
> @faststore/core@3.98.3 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.98.
|
|
40
|
+
> @faststore/core@3.98.3 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.98.
|
|
44
|
+
> @faststore/core@3.98.3 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
|
|
@@ -59,8 +59,8 @@ https://nextjs.org/telemetry
|
|
|
59
59
|
Collecting page data ...
|
|
60
60
|
Generating static pages (0/6) ...
|
|
61
61
|
|
|
62
62
|
Generating static pages (1/6)
|
|
63
|
-
|
|
64
63
|
Generating static pages (2/6)
|
|
65
64
|
Warning: Dynamic Content not found for the page: home. Refer to the Dynamic Content documentation at https://developers.vtex.com/docs/guides/faststore/dynamic-content-overview for mapping the page and the corresponding data-fetching function.
|
|
65
|
+
|
|
66
66
|
Generating static pages (2/6)
|
|
67
67
|
|
|
68
68
|
Generating static pages (4/6)
|
|
69
69
|
|
|
70
70
|
✓ Generating static pages (6/6)
|
|
71
71
|
Finalizing page optimization ...
|
|
@@ -81,7 +81,7 @@ Route (pages) Size First Load JS
|
|
|
81
81
|
├ λ /api/health/live 0 B 109 kB
|
|
82
82
|
├ λ /api/health/ready 0 B 109 kB
|
|
83
83
|
├ λ /api/preview 0 B 109 kB
|
|
84
|
-
├ ● /checkout 745 B
|
|
84
|
+
├ ● /checkout 745 B 159 kB
|
|
85
85
|
├ ● /login 1.7 kB 159 kB
|
|
86
86
|
├ λ /pvt/account 245 B 109 kB
|
|
87
87
|
├ ● /pvt/account/[...unknown] 286 B 109 kB
|
|
@@ -103,8 +103,8 @@ Route (pages) Size First Load JS
|
|
|
103
103
|
+ First Load JS shared by all 118 kB
|
|
104
104
|
├ chunks/framework-d514426edf885c68.js 45.4 kB
|
|
105
105
|
├ chunks/main-edeb2c6a5c48bb3f.js 33.2 kB
|
|
106
|
-
├ chunks/pages/_app-
|
|
107
|
-
├ chunks/webpack-
|
|
106
|
+
├ chunks/pages/_app-8be996b3105d8c26.js 26.3 kB
|
|
107
|
+
├ chunks/webpack-fd706604cbbdc60f.js 3.88 kB
|
|
108
108
|
└ css/8a513f4b536b0ab0.css 9.18 kB
|
|
109
109
|
|
|
110
110
|
λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps)
|
package/.turbo/turbo-test.log
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
|
|
2
|
-
> @faststore/core@3.98.
|
|
2
|
+
> @faststore/core@3.98.3 test /home/runner/work/faststore/faststore/packages/core
|
|
3
3
|
> jest
|
|
4
4
|
|
|
5
|
-
PASS test/utils/
|
|
6
|
-
PASS test/utils/
|
|
5
|
+
PASS test/utils/clearCookies.test.ts (12.005 s)
|
|
6
|
+
PASS test/utils/multipleTemplates.test.ts (13.659 s)
|
|
7
7
|
PASS test/server/cms/global.test.ts
|
|
8
|
-
PASS test/utils/cookieCacheBusting.test.ts
|
|
9
|
-
PASS test/server/cms/index.test.ts (
|
|
10
|
-
PASS test/server/index.test.ts (
|
|
11
|
-
A worker process has failed to exit gracefully and has been force exited. This is likely caused by tests leaking due to improper teardown. Try running with --detectOpenHandles to find leaks. Active timers can also cause this, ensure that .unref() was called on them.
|
|
8
|
+
PASS test/utils/cookieCacheBusting.test.ts (15.415 s)
|
|
9
|
+
PASS test/server/cms/index.test.ts (6.077 s)
|
|
10
|
+
PASS test/server/index.test.ts (12.996 s)
|
|
12
11
|
|
|
13
12
|
Test Suites: 6 passed, 6 total
|
|
14
|
-
Tests:
|
|
13
|
+
Tests: 52 passed, 52 total
|
|
15
14
|
Snapshots: 0 total
|
|
16
|
-
Time:
|
|
15
|
+
Time: 27.695 s
|
|
17
16
|
Ran all test suites.
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
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.98.4](https://github.com/vtex/faststore/compare/v3.98.3...v3.98.4) (2026-04-15)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @faststore/core
|
|
9
|
+
|
|
10
|
+
## [3.98.3](https://github.com/vtex/faststore/compare/v3.98.2...v3.98.3) (2026-04-09)
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
- Store ID param sent to Content Platform client ([#3265](https://github.com/vtex/faststore/issues/3265)) ([63fffd8](https://github.com/vtex/faststore/commit/63fffd878403c4d0c9aff8f6d56064dfa42ab833))
|
|
15
|
+
|
|
6
16
|
## [3.98.2](https://github.com/vtex/faststore/compare/v3.98.1...v3.98.2) (2026-04-09)
|
|
7
17
|
|
|
8
18
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faststore/core",
|
|
3
|
-
"version": "3.98.
|
|
3
|
+
"version": "3.98.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -124,5 +124,5 @@
|
|
|
124
124
|
"ts-jest": "29.1.1",
|
|
125
125
|
"typescript": "5.3.2"
|
|
126
126
|
},
|
|
127
|
-
"gitHead": "
|
|
127
|
+
"gitHead": "ee710a0c31c409363948a3c3b7c7c1f26acb25cb"
|
|
128
128
|
}
|
|
@@ -29,7 +29,7 @@ export const request = async <Query = unknown, Variables = unknown>(
|
|
|
29
29
|
variables: Variables,
|
|
30
30
|
options?: RequestOptions
|
|
31
31
|
) => {
|
|
32
|
-
// Get cache busting value based
|
|
32
|
+
// Get cache busting value based on auth state and postal code
|
|
33
33
|
const value = getClientCacheBustingValue()
|
|
34
34
|
|
|
35
35
|
const { data, errors } = await baseRequest<Variables, Query>('/api/graphql', {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import storeConfig from 'discovery.config'
|
|
1
2
|
import { useSearch } from '@faststore/sdk'
|
|
2
3
|
import { gql } from '@generated'
|
|
3
4
|
import type {
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
useState,
|
|
16
17
|
} from 'react'
|
|
17
18
|
import { useQuery } from 'src/sdk/graphql/useQuery'
|
|
19
|
+
import { useSession } from 'src/sdk/session'
|
|
18
20
|
import { generatedBuildTime } from '../../../next-seo.config'
|
|
19
21
|
import { useLocalizedVariables } from './useLocalizedVariables'
|
|
20
22
|
import { useShouldFetchFirstPage } from './useShouldFetchFirstPage'
|
|
@@ -80,8 +82,23 @@ export const useCreateUseGalleryPage = (
|
|
|
80
82
|
params?: UseCreateUseGalleryPageProps
|
|
81
83
|
) => {
|
|
82
84
|
const initialPages = params?.initialPages?.search ? [params.initialPages] : []
|
|
85
|
+
|
|
86
|
+
// Seed the cache with the same region-aware key shape that useGalleryPage uses,
|
|
87
|
+
// so hasSameVariables correctly matches on first mount and avoids an unnecessary
|
|
88
|
+
// re-fetch of the SSR-loaded page.
|
|
89
|
+
const isDeliveryPromiseEnabled = storeConfig.deliveryPromise?.enabled ?? false
|
|
90
|
+
const { postalCode } = useSession()
|
|
83
91
|
const initialVariables = params?.serverManyProductsVariables
|
|
84
|
-
? [
|
|
92
|
+
? [
|
|
93
|
+
getKey(
|
|
94
|
+
isDeliveryPromiseEnabled
|
|
95
|
+
? {
|
|
96
|
+
...params.serverManyProductsVariables,
|
|
97
|
+
_postalCode: postalCode ?? '',
|
|
98
|
+
}
|
|
99
|
+
: params.serverManyProductsVariables
|
|
100
|
+
),
|
|
101
|
+
]
|
|
85
102
|
: []
|
|
86
103
|
|
|
87
104
|
const [pages, setPages] =
|
|
@@ -97,6 +114,8 @@ export const useCreateUseGalleryPage = (
|
|
|
97
114
|
itemsPerPage,
|
|
98
115
|
} = useSearch()
|
|
99
116
|
|
|
117
|
+
const { postalCode, isValidating: isSessionValidating } = useSession()
|
|
118
|
+
|
|
100
119
|
const localizedVariables = useLocalizedVariables({
|
|
101
120
|
first: itemsPerPage,
|
|
102
121
|
after: (itemsPerPage * page).toString(),
|
|
@@ -105,9 +124,20 @@ export const useCreateUseGalleryPage = (
|
|
|
105
124
|
selectedFacets,
|
|
106
125
|
})
|
|
107
126
|
|
|
127
|
+
// Include postalCode in the cache key so pages are invalidated on region change.
|
|
128
|
+
// _postalCode is not sent to the API — it only affects the local cache comparison.
|
|
129
|
+
// Only applied when deliveryPromise is enabled to avoid unnecessary cache fragmentation.
|
|
130
|
+
const localizedVariablesWithRegion = useMemo(
|
|
131
|
+
() =>
|
|
132
|
+
isDeliveryPromiseEnabled
|
|
133
|
+
? { ...localizedVariables, _postalCode: postalCode ?? '' }
|
|
134
|
+
: localizedVariables,
|
|
135
|
+
[localizedVariables, postalCode]
|
|
136
|
+
)
|
|
137
|
+
|
|
108
138
|
const hasSameVariables = deepEquals(
|
|
109
139
|
pagesCache.current[page],
|
|
110
|
-
getKey(
|
|
140
|
+
getKey(localizedVariablesWithRegion)
|
|
111
141
|
)
|
|
112
142
|
|
|
113
143
|
const shouldFetchFirstPage = useShouldFetchFirstPage({
|
|
@@ -123,13 +153,14 @@ export const useCreateUseGalleryPage = (
|
|
|
123
153
|
>(query, localizedVariables, {
|
|
124
154
|
fallbackData: null,
|
|
125
155
|
suspense: true,
|
|
126
|
-
doNotRun:
|
|
156
|
+
doNotRun:
|
|
157
|
+
!shouldFetch || (isDeliveryPromiseEnabled && isSessionValidating),
|
|
127
158
|
})
|
|
128
159
|
|
|
129
160
|
const shouldUpdatePages = data !== null
|
|
130
161
|
|
|
131
162
|
if (shouldUpdatePages) {
|
|
132
|
-
pagesCache.current[page] = getKey(
|
|
163
|
+
pagesCache.current[page] = getKey(localizedVariablesWithRegion)
|
|
133
164
|
|
|
134
165
|
// Update refs
|
|
135
166
|
const newPages = [...pagesRef.current]
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import storeConfig from 'discovery.config'
|
|
1
2
|
import { gql } from '@generated'
|
|
2
3
|
import { useQuery } from 'src/sdk/graphql/useQuery'
|
|
3
4
|
import { useSession } from 'src/sdk/session'
|
|
@@ -138,7 +139,7 @@ export const useProductGalleryQuery = ({
|
|
|
138
139
|
selectedFacets,
|
|
139
140
|
itemsPerPage,
|
|
140
141
|
}: ProductGalleryQueryOptions) => {
|
|
141
|
-
const { locale } = useSession()
|
|
142
|
+
const { locale, isValidating: isSessionValidating } = useSession()
|
|
142
143
|
const { state, setState } = useSearch()
|
|
143
144
|
const localizedVariables = useLocalizedVariables({
|
|
144
145
|
first: itemsPerPage,
|
|
@@ -148,7 +149,10 @@ export const useProductGalleryQuery = ({
|
|
|
148
149
|
selectedFacets,
|
|
149
150
|
})
|
|
150
151
|
|
|
152
|
+
const isDeliveryPromiseEnabled = storeConfig.deliveryPromise?.enabled ?? false
|
|
153
|
+
|
|
151
154
|
const queryResult = useQuery<Query, Variables>(query, localizedVariables, {
|
|
155
|
+
doNotRun: isDeliveryPromiseEnabled && isSessionValidating,
|
|
152
156
|
onSuccess: (data: Query) => {
|
|
153
157
|
const updatedFuzzyFacetValue = data.search.metadata?.fuzzy
|
|
154
158
|
const updatedOperatorFacetValue = data.search.metadata?.logicalOperator
|
|
@@ -196,6 +200,7 @@ export const useProductGalleryQuery = ({
|
|
|
196
200
|
const operatorFacetValue = findFacetValue(selectedFacets, 'operator')
|
|
197
201
|
const shouldRefetchQuery =
|
|
198
202
|
!queryResult.error && (!fuzzyFacetValue || !operatorFacetValue)
|
|
203
|
+
|
|
199
204
|
if (shouldRefetchQuery) {
|
|
200
205
|
// The first result is not relevant, return null data to avoid rendering the page while the query is being re-fetched
|
|
201
206
|
return { ...queryResult, isValidating: true, data: null }
|
|
@@ -187,7 +187,9 @@ export class ContentService {
|
|
|
187
187
|
const { cmsOptions } = options
|
|
188
188
|
const params: Partial<EntryPathParams> = {
|
|
189
189
|
accountName: config.api.storeId,
|
|
190
|
-
storeId:
|
|
190
|
+
storeId:
|
|
191
|
+
(config.contentSource as Record<string, string>)?.project ??
|
|
192
|
+
'faststore',
|
|
191
193
|
contentType: cmsOptions.contentType,
|
|
192
194
|
slug: options.slug,
|
|
193
195
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import storeConfig from 'discovery.config'
|
|
1
2
|
import { sessionStore } from 'src/sdk/session'
|
|
2
3
|
|
|
3
4
|
export const STORAGE_KEY_PERSON_ID = 'faststore_person_id'
|
|
5
|
+
export const STORAGE_KEY_POSTAL_CODE = 'faststore_postal_code'
|
|
4
6
|
export const STORAGE_KEY_CACHE_BUST_LAST_VALUE =
|
|
5
7
|
'faststore_cache_bust_last_value'
|
|
6
8
|
|
|
@@ -17,8 +19,19 @@ const getPersonId = (): string | null => {
|
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
|
-
* Gets
|
|
22
|
+
* Gets postalCode from session when deliveryPromise is enabled.
|
|
23
|
+
* Reads session store directly since vtex_segment is httpOnly and inaccessible via JavaScript.
|
|
24
|
+
* Returns null for stores that don't use delivery promise — postal code has no effect
|
|
25
|
+
* on their facets, so there is no need to fragment the CDN cache by region.
|
|
21
26
|
*/
|
|
27
|
+
const getPostalCode = (): string | null => {
|
|
28
|
+
if (typeof window === 'undefined' || !storeConfig.deliveryPromise?.enabled) {
|
|
29
|
+
return null
|
|
30
|
+
}
|
|
31
|
+
const session = sessionStore.read() ?? sessionStore.readInitial()
|
|
32
|
+
return session?.postalCode ?? null
|
|
33
|
+
}
|
|
34
|
+
|
|
22
35
|
const getStoredPersonId = (): string | null => {
|
|
23
36
|
if (typeof sessionStorage === 'undefined') {
|
|
24
37
|
return null
|
|
@@ -31,6 +44,21 @@ const getStoredPersonId = (): string | null => {
|
|
|
31
44
|
}
|
|
32
45
|
}
|
|
33
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Gets the postal code from sessionStorage (client-side only)
|
|
49
|
+
*/
|
|
50
|
+
const getStoredPostalCode = (): string | null => {
|
|
51
|
+
if (typeof sessionStorage === 'undefined') {
|
|
52
|
+
return null
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
return sessionStorage.getItem(STORAGE_KEY_POSTAL_CODE)
|
|
57
|
+
} catch {
|
|
58
|
+
return null
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
34
62
|
/**
|
|
35
63
|
* Stores the person id in sessionStorage (client-side only)
|
|
36
64
|
*/
|
|
@@ -50,9 +78,22 @@ const storePersonId = (value: string | null): void => {
|
|
|
50
78
|
}
|
|
51
79
|
}
|
|
52
80
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
81
|
+
const storePostalCode = (value: string | null): void => {
|
|
82
|
+
if (typeof sessionStorage === 'undefined') {
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
if (value === null) {
|
|
88
|
+
sessionStorage.removeItem(STORAGE_KEY_POSTAL_CODE)
|
|
89
|
+
} else {
|
|
90
|
+
sessionStorage.setItem(STORAGE_KEY_POSTAL_CODE, value)
|
|
91
|
+
}
|
|
92
|
+
} catch {
|
|
93
|
+
// Ignore storage errors
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
56
97
|
const getLastValue = (): string | null => {
|
|
57
98
|
if (typeof sessionStorage === 'undefined') {
|
|
58
99
|
return null
|
|
@@ -66,7 +107,7 @@ const getLastValue = (): string | null => {
|
|
|
66
107
|
}
|
|
67
108
|
|
|
68
109
|
/**
|
|
69
|
-
* Stores the last
|
|
110
|
+
* Stores the last value in sessionStorage (client-side only)
|
|
70
111
|
*/
|
|
71
112
|
const storeLastValue = (value: string): void => {
|
|
72
113
|
if (typeof sessionStorage === 'undefined') {
|
|
@@ -81,7 +122,7 @@ const storeLastValue = (value: string): void => {
|
|
|
81
122
|
}
|
|
82
123
|
|
|
83
124
|
/**
|
|
84
|
-
* Clears
|
|
125
|
+
* Clears the cache busting related data from sessionStorage (client-side only)
|
|
85
126
|
*/
|
|
86
127
|
const clearCacheBustingStorage = (): void => {
|
|
87
128
|
if (typeof sessionStorage === 'undefined') {
|
|
@@ -90,46 +131,65 @@ const clearCacheBustingStorage = (): void => {
|
|
|
90
131
|
|
|
91
132
|
try {
|
|
92
133
|
sessionStorage.removeItem(STORAGE_KEY_PERSON_ID)
|
|
134
|
+
sessionStorage.removeItem(STORAGE_KEY_POSTAL_CODE)
|
|
93
135
|
sessionStorage.removeItem(STORAGE_KEY_CACHE_BUST_LAST_VALUE)
|
|
94
136
|
} catch {
|
|
95
137
|
// Ignore storage errors
|
|
96
138
|
}
|
|
97
139
|
}
|
|
98
140
|
|
|
141
|
+
const buildValue = (
|
|
142
|
+
personId: string | null,
|
|
143
|
+
postalCode: string | null
|
|
144
|
+
): string => {
|
|
145
|
+
const timestamp = Date.now().toString()
|
|
146
|
+
return [timestamp, personId, postalCode].filter(Boolean).join('::')
|
|
147
|
+
}
|
|
148
|
+
|
|
99
149
|
/**
|
|
100
|
-
* Gets cache busting value for client-side based on
|
|
101
|
-
*
|
|
102
|
-
*
|
|
150
|
+
* Gets cache busting value for client-side GET requests based on session state.
|
|
151
|
+
*
|
|
152
|
+
* Covers two axes that make GraphQL responses user/region-specific:
|
|
153
|
+
* - Auth state (person.id): logged-in users see personalised prices and availability.
|
|
154
|
+
* - Postal code: delivery-promise facets (shipping, delivery-options) differ per region.
|
|
155
|
+
*
|
|
156
|
+
* The value is appended as the `v` query param so the CDN treats each
|
|
157
|
+
* combination as a distinct cache entry. Returns null when neither axis is set,
|
|
158
|
+
* meaning the public CDN cache is shared across all anonymous visitors with no
|
|
159
|
+
* location — which is the correct behaviour for stores without delivery promise.
|
|
103
160
|
*/
|
|
104
161
|
export const getClientCacheBustingValue = (): string | null => {
|
|
105
162
|
const currentPersonId = getPersonId()
|
|
163
|
+
const currentPostalCode = getPostalCode()
|
|
106
164
|
|
|
107
|
-
//
|
|
108
|
-
if (currentPersonId
|
|
165
|
+
// No session-specific data: clear storage and allow shared public CDN caching (don't proceed with cache busting logic)
|
|
166
|
+
if (!currentPersonId && !currentPostalCode) {
|
|
109
167
|
clearCacheBustingStorage()
|
|
110
168
|
return null
|
|
111
169
|
}
|
|
112
170
|
|
|
113
171
|
const storedPersonId = getStoredPersonId()
|
|
172
|
+
const storedPostalCode = getStoredPostalCode()
|
|
114
173
|
|
|
115
|
-
//
|
|
116
|
-
if (
|
|
174
|
+
// Either axis changed: persist new state and generate a fresh cache-busting value
|
|
175
|
+
if (
|
|
176
|
+
currentPersonId !== storedPersonId ||
|
|
177
|
+
currentPostalCode !== storedPostalCode
|
|
178
|
+
) {
|
|
117
179
|
storePersonId(currentPersonId)
|
|
118
|
-
|
|
119
|
-
const value =
|
|
180
|
+
storePostalCode(currentPostalCode)
|
|
181
|
+
const value = buildValue(currentPersonId, currentPostalCode)
|
|
120
182
|
storeLastValue(value)
|
|
121
183
|
return value
|
|
122
184
|
}
|
|
123
185
|
|
|
124
|
-
//
|
|
186
|
+
// Nothing changed: reuse existing value (or create one if storage was cleared)
|
|
125
187
|
const lastValue = getLastValue()
|
|
126
188
|
if (lastValue) {
|
|
127
189
|
return lastValue
|
|
128
190
|
}
|
|
129
191
|
|
|
130
|
-
|
|
131
|
-
const timestamp = Date.now().toString()
|
|
132
|
-
const value = `${timestamp}::${currentPersonId}`
|
|
192
|
+
const value = buildValue(currentPersonId, currentPostalCode)
|
|
133
193
|
storeLastValue(value)
|
|
134
194
|
return value
|
|
135
195
|
}
|