@faststore/core 3.96.2 → 3.96.4-dev.0

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 (47) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +37 -37
  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 +1 -1
  12. package/.next/routes-manifest.json +1 -1
  13. package/.next/server/chunks/948.js +2 -2
  14. package/.next/server/chunks/9563.js +1 -1
  15. package/.next/server/chunks/9630.js +7 -7
  16. package/.next/server/middleware-build-manifest.js +1 -1
  17. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  18. package/.next/server/pages/api/fs/logout.js +1 -0
  19. package/.next/server/pages/api/fs/logout.js.nft.json +1 -0
  20. package/.next/server/pages/api/graphql.js +3 -3
  21. package/.next/server/pages/en-US/404.html +1 -2
  22. package/.next/server/pages/en-US/500.html +1 -2
  23. package/.next/server/pages/en-US/checkout.html +1 -2
  24. package/.next/server/pages/en-US/login.html +1 -2
  25. package/.next/server/pages/en-US/s.html +1 -2
  26. package/.next/server/pages/en-US.html +1 -2
  27. package/.next/server/pages-manifest.json +1 -1
  28. package/.next/static/chunks/4803.9822f0b7e469b933.js +1 -0
  29. package/.next/static/chunks/9173-ab3c4d9d8f978c4b.js +1 -0
  30. package/.next/static/chunks/pages/_app-3898f7fdf2646553.js +1 -0
  31. package/.next/static/chunks/{webpack-237c97ab0eda7441.js → webpack-5ac0858ff0030797.js} +1 -1
  32. package/.next/static/{e2njurziU7hHK8M7cTbr- → iASZ3lkWoTXpcEiPm4xkW}/_buildManifest.js +1 -1
  33. package/.next/trace +139 -138
  34. package/.turbo/turbo-build.log +24 -23
  35. package/.turbo/turbo-test.log +9 -7
  36. package/CHANGELOG.md +32 -0
  37. package/cms/faststore/pages/cms_content_type__landingpage.jsonc +6 -0
  38. package/package.json +7 -7
  39. package/src/components/ThirdPartyScripts/ThirdPartyScripts.tsx +4 -1
  40. package/src/components/account/MyAccountDrawer/OrganizationDrawer/OrganizationDrawer.tsx +104 -4
  41. package/src/pages/api/fs/logout.ts +76 -0
  42. package/src/utils/clearCookies.ts +79 -0
  43. package/test/utils/clearCookies.test.ts +232 -0
  44. package/.next/static/chunks/4803.18fbf77cd924d443.js +0 -1
  45. package/.next/static/chunks/9173-2ed920b87ee6640e.js +0 -1
  46. package/.next/static/chunks/pages/_app-35b56c71ba4f9a54.js +0 -1
  47. /package/.next/static/{e2njurziU7hHK8M7cTbr- → iASZ3lkWoTXpcEiPm4xkW}/_ssgManifest.js +0 -0
@@ -1,23 +1,23 @@
1
1
 
2
- > @faststore/core@3.96.1 prebuild /home/runner/work/faststore/faststore/packages/core
2
+ > @faststore/core@3.96.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.96.1 partytown /home/runner/work/faststore/faststore/packages/core
6
+ > @faststore/core@3.96.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.96.1 generate /home/runner/work/faststore/faststore/packages/core
11
+ > @faststore/core@3.96.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.96.1 generate:schema /home/runner/work/faststore/faststore/packages/core
15
+ > @faststore/core@3.96.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.96.1 generate:codegen /home/runner/work/faststore/faststore/packages/core
20
+ > @faststore/core@3.96.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.96.1 format:generated /home/runner/work/faststore/faststore/packages/core
40
+ > @faststore/core@3.96.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.96.1 build /home/runner/work/faststore/faststore/packages/core
44
+ > @faststore/core@3.96.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
@@ -80,8 +80,8 @@ Import trace for requested module:
80
80
  Collecting page data ...
81
81
  Generating static pages (0/6) ...
82
82
 
83
83
  Generating static pages (1/6)
84
-
85
84
  Generating static pages (2/6)
86
85
  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.
86
+
87
87
  Generating static pages (2/6)
88
88
 
89
89
  Generating static pages (4/6)
90
90
 
91
91
  ✓ Generating static pages (6/6)
92
92
  Finalizing page optimization ...
@@ -91,39 +91,40 @@ Route (pages) Size First Load JS
91
91
  ┌ ● / 7.39 kB 147 kB
92
92
  ├ └ css/02259c549b2179f2.css 3.1 kB
93
93
  ├ /_app 0 B 108 kB
94
- ├ ● /[...slug] 2.55 kB 157 kB
95
- ├ ● /[slug]/p 98.1 kB 237 kB
94
+ ├ ● /[...slug] 2.55 kB 158 kB
95
+ ├ ● /[slug]/p 98.1 kB 238 kB
96
96
  ├ └ css/a6a4ebbe01adbbad.css 22.2 kB
97
- ├ ○ /404 1.57 kB 141 kB
98
- ├ ● /500 1.57 kB 141 kB
97
+ ├ ○ /404 1.57 kB 142 kB
98
+ ├ ● /500 1.57 kB 142 kB
99
+ ├ λ /api/fs/logout 0 B 108 kB
99
100
  ├ λ /api/graphql 0 B 108 kB
100
101
  ├ λ /api/health/live 0 B 108 kB
101
102
  ├ λ /api/health/ready 0 B 108 kB
102
103
  ├ λ /api/preview 0 B 108 kB
103
- ├ ● /checkout 749 B 140 kB
104
- ├ ● /login 1.7 kB 141 kB
105
- ├ λ /pvt/account 247 B 108 kB
104
+ ├ ● /checkout 749 B 141 kB
105
+ ├ ● /login 1.7 kB 142 kB
106
+ ├ λ /pvt/account 247 B 109 kB
106
107
  ├ ● /pvt/account/[...unknown] 287 B 109 kB
107
- ├ λ /pvt/account/403 2.98 kB 142 kB
108
+ ├ λ /pvt/account/403 2.98 kB 143 kB
108
109
  ├ └ css/0fae3d432331aae9.css 4.68 kB
109
110
  ├ λ /pvt/account/404 2.18 kB 142 kB
110
111
  ├ └ css/0fc6b2ff69142c6a.css 4.74 kB
111
- ├ λ /pvt/account/orders 9.78 kB 149 kB
112
+ ├ λ /pvt/account/orders 9.78 kB 150 kB
112
113
  ├ └ css/40a294d0a24ad01d.css 14.1 kB
113
- ├ λ /pvt/account/orders/[id] 12.1 kB 151 kB
114
+ ├ λ /pvt/account/orders/[id] 12.1 kB 152 kB
114
115
  ├ └ css/5eecefd2c6deeee4.css 13.3 kB
115
- ├ λ /pvt/account/profile 1.98 kB 141 kB
116
+ ├ λ /pvt/account/profile 1.98 kB 142 kB
116
117
  ├ └ css/47f1b4e8de15d314.css 4.42 kB
117
- ├ λ /pvt/account/security 3.96 kB 143 kB
118
+ ├ λ /pvt/account/security 3.96 kB 144 kB
118
119
  ├ └ css/973dd40d4773e8cd.css 5.74 kB
119
- ├ λ /pvt/account/user-details 1.91 kB 141 kB
120
+ ├ λ /pvt/account/user-details 1.91 kB 142 kB
120
121
  ├ └ css/05c399956ff24b77.css 4.54 kB
121
122
  └ ● /s 3.36 kB 158 kB
122
123
  + First Load JS shared by all 112 kB
123
124
  ├ chunks/framework-d514426edf885c68.js 45.4 kB
124
125
  ├ chunks/main-ec03882c4375091d.js 33.2 kB
125
- ├ chunks/pages/_app-35b56c71ba4f9a54.js 25.8 kB
126
- ├ chunks/webpack-237c97ab0eda7441.js 3.85 kB
126
+ ├ chunks/pages/_app-3898f7fdf2646553.js 25.8 kB
127
+ ├ chunks/webpack-5ac0858ff0030797.js 3.85 kB
127
128
  └ css/0f070d03aacd9cc5.css 3.57 kB
128
129
 
129
130
  λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps)
@@ -1,15 +1,17 @@
1
1
 
2
- > @faststore/core@3.96.1 test /home/runner/work/faststore/faststore/packages/core
2
+ > @faststore/core@3.96.3 test /home/runner/work/faststore/faststore/packages/core
3
3
  > jest
4
4
 
5
- PASS test/utils/multipleTemplates.test.ts (28.229 s)
6
- PASS test/utils/cookieCacheBusting.test.ts (26.786 s)
5
+ PASS test/utils/multipleTemplates.test.ts (30.887 s)
6
+ PASS test/utils/clearCookies.test.ts (31.406 s)
7
+ PASS test/utils/cookieCacheBusting.test.ts
7
8
  PASS test/server/cms/global.test.ts
8
9
  PASS test/server/cms/index.test.ts
9
- PASS test/server/index.test.ts (31.53 s)
10
+ PASS test/server/index.test.ts (36.367 s)
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.
10
12
 
11
- Test Suites: 5 passed, 5 total
12
- Tests: 27 passed, 27 total
13
+ Test Suites: 6 passed, 6 total
14
+ Tests: 47 passed, 47 total
13
15
  Snapshots: 0 total
14
- Time: 32.796 s
16
+ Time: 37.886 s
15
17
  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.96.4-dev.0](https://github.com/vtex/faststore/compare/v3.96.3...v3.96.4-dev.0) (2026-01-21)
7
+
8
+ # 3.96.0-dev.22 (2026-01-21)
9
+
10
+ **Note:** Version bump only for package @faststore/core
11
+
12
+ ## [3.96.3](https://github.com/vtex/faststore/compare/v3.96.2...v3.96.3) (2026-01-21)
13
+
14
+ **Note:** Version bump only for package @faststore/core
15
+
6
16
  ## [3.96.2](https://github.com/vtex/faststore/compare/v3.96.1...v3.96.2) (2026-01-14)
7
17
 
8
18
  **Note:** Version bump only for package @faststore/core
@@ -17,6 +27,28 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
17
27
 
18
28
  - version 20251223 ([#3161](https://github.com/vtex/faststore/issues/3161)) ([ad5e8d1](https://github.com/vtex/faststore/commit/ad5e8d12fe45f1fb8e1134165172bf1c6b2a91e2))
19
29
 
30
+ # 3.96.0-dev.22 (2026-01-21)
31
+
32
+ **Note:** Version bump only for package @faststore/core
33
+
34
+ # [3.96.0-dev.21](https://github.com/vtex/faststore/compare/v3.96.0-dev.20...v3.96.0-dev.21) (2026-01-08)
35
+
36
+ ### Bug Fixes
37
+
38
+ - Prevent Partytown cross-origin errors in iframe environments ([#3155](https://github.com/vtex/faststore/issues/3155)) ([997252e](https://github.com/vtex/faststore/commit/997252e9a18807f4c26c350197d4f2d139de58f8))
39
+
40
+ # [3.96.0-dev.20](https://github.com/vtex/faststore/compare/v3.96.0-dev.19...v3.96.0-dev.20) (2026-01-08)
41
+
42
+ ### Bug Fixes
43
+
44
+ - Add slug field to landing page schema - CROC-185 ([#3166](https://github.com/vtex/faststore/issues/3166)) ([41b9878](https://github.com/vtex/faststore/commit/41b987825ee5ebb7d311eef33e2ca65034dc130d))
45
+
46
+ # [3.96.0-dev.19](https://github.com/vtex/faststore/compare/v3.96.0-dev.18...v3.96.0-dev.19) (2026-01-08)
47
+
48
+ ### Features
49
+
50
+ - logout clear storage ([#3163](https://github.com/vtex/faststore/issues/3163)) ([1fbacc3](https://github.com/vtex/faststore/commit/1fbacc3b3e32b4f83a2f56c1f97eb0f8ff843f61))
51
+
20
52
  # 3.96.0-dev.18 (2025-12-24)
21
53
 
22
54
  **Note:** Version bump only for package @faststore/core
@@ -5,6 +5,12 @@
5
5
  "type": "object",
6
6
  "title": "Landing Page",
7
7
  "properties": {
8
+ "slug": {
9
+ "widget": {
10
+ "ui:widget": "slug"
11
+ },
12
+ "type": "string"
13
+ },
8
14
  "seo": {
9
15
  "title": "SEO",
10
16
  "description": "Search Engine Optimization options",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faststore/core",
3
- "version": "3.96.2",
3
+ "version": "3.96.4-dev.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -51,11 +51,11 @@
51
51
  "@envelop/graphql-jit": "^8.0.3",
52
52
  "@envelop/parser-cache": "^6.0.2",
53
53
  "@envelop/validation-cache": "^6.0.2",
54
- "@faststore/api": "3.96.2",
55
- "@faststore/graphql-utils": "^3.96.0",
56
- "@faststore/lighthouse": "3.96.0",
57
- "@faststore/sdk": "3.96.0",
58
- "@faststore/ui": "3.96.0",
54
+ "@faststore/api": "3.96.4-dev.0",
55
+ "@faststore/graphql-utils": "^3.96.4-dev.0",
56
+ "@faststore/lighthouse": "3.96.4-dev.0",
57
+ "@faststore/sdk": "3.96.4-dev.0",
58
+ "@faststore/ui": "3.96.4-dev.0",
59
59
  "@graphql-codegen/cli": "5.0.2",
60
60
  "@graphql-codegen/client-preset": "4.2.6",
61
61
  "@graphql-codegen/typescript": "4.0.7",
@@ -123,5 +123,5 @@
123
123
  "ts-jest": "29.1.1",
124
124
  "typescript": "5.3.2"
125
125
  },
126
- "gitHead": "416ed2235804e8f8b39b8351e50f86d5d5b7bd72"
126
+ "gitHead": "e9e8720245637fc18616bdfbac78de7435dba622"
127
127
  }
@@ -37,7 +37,10 @@ function ThirdPartyScripts() {
37
37
  {includeGTM && <GoogleTagManager containerId={gtmContainerId} />}
38
38
  {includeVTEX && <VTEX />}
39
39
  <OverrideComponents.ThirdPartyScripts />
40
- <Partytown key="partytown" />
40
+ {/* Only render Partytown when not in an iframe to prevent cross-origin errors. */}
41
+ {typeof window !== 'undefined' && window.self === window.top && (
42
+ <Partytown key="partytown" />
43
+ )}
41
44
  </>
42
45
  )
43
46
  }
@@ -1,6 +1,12 @@
1
1
  import { SlideOver, useFadeEffect } from '@faststore/ui'
2
2
 
3
3
  import { useSession } from 'src/sdk/session'
4
+ import {
5
+ expireCookieClient,
6
+ getCookieDomains,
7
+ getCookiePaths,
8
+ getVtexCookieNames,
9
+ } from 'src/utils/clearCookies'
4
10
  import storeConfig from '../../../../../discovery.config'
5
11
  import { ProfileSummary } from '../ProfileSummary/ProfileSummary'
6
12
  import { OrganizationDrawerBody } from './OrganizationDrawerBody'
@@ -13,11 +19,105 @@ type OrganizationDrawerProps = {
13
19
  isRepresentative: boolean
14
20
  }
15
21
 
16
- export const doLogout = () => {
22
+ const clearBrowserStorageForCurrentDomain = async () => {
23
+ if (typeof window === 'undefined' || !storeConfig) return
24
+
25
+ // Clear Faststore-specific sessionStorage keys
26
+ try {
27
+ const sessionStorageKeys = [
28
+ 'faststore_session_ready',
29
+ 'faststore_auth_cookie_value',
30
+ 'faststore_cache_bust_last_value',
31
+ ]
32
+
33
+ for (const key of sessionStorageKeys) {
34
+ try {
35
+ window.sessionStorage?.removeItem(key)
36
+ } catch {}
37
+ }
38
+
39
+ // Remove all keys starting with __fs_gallery_page_ (used for PLP pagination)
40
+ try {
41
+ const keysToRemove: string[] = []
42
+ for (let i = 0; i < window.sessionStorage.length; i++) {
43
+ const key = window.sessionStorage.key(i)
44
+ if (key && key.startsWith('__fs_gallery_page_')) {
45
+ keysToRemove.push(key)
46
+ }
47
+ }
48
+ for (const key of keysToRemove) {
49
+ try {
50
+ window.sessionStorage.removeItem(key)
51
+ } catch {}
52
+ }
53
+ } catch {}
54
+ } catch {}
55
+
56
+ // Clear all cookies containing 'vtex' in the name (case-insensitive)
57
+ try {
58
+ const hostname = window.location.hostname
59
+ const secure = window.location.protocol === 'https:'
60
+
61
+ // Extract all cookie names from document.cookie
62
+ const allCookieNames = document.cookie
63
+ .split(';')
64
+ .map((c) => c.trim())
65
+ .filter(Boolean)
66
+ .map((c) => c.split('=')[0])
67
+ .filter(Boolean)
68
+
69
+ const vtexCookieNames = getVtexCookieNames(allCookieNames)
70
+ const paths = getCookiePaths(window.location.pathname || '/')
71
+ const domains = getCookieDomains(hostname)
72
+
73
+ for (const name of vtexCookieNames) {
74
+ for (const path of paths) {
75
+ for (const domain of domains) {
76
+ try {
77
+ expireCookieClient({ name, path, domain, secure })
78
+ } catch {}
79
+ }
80
+ }
81
+ }
82
+ } catch {}
83
+
84
+ // Clear IndexedDB (keyval-store)
85
+ try {
86
+ if (!('indexedDB' in window)) return
87
+
88
+ const idb = window.indexedDB
89
+ if (!idb) return
90
+
91
+ await new Promise<void>((resolve) => {
92
+ const req = idb.deleteDatabase('keyval-store')
93
+ req.onsuccess = () => resolve()
94
+ req.onerror = () => resolve()
95
+ req.onblocked = () => resolve()
96
+ })
97
+ } catch {}
98
+ }
99
+
100
+ export const doLogout = async (_event?: unknown) => {
17
101
  if (!storeConfig) return
18
- window.location.assign(
19
- `${storeConfig.secureSubdomain}/api/vtexid/pub/logout?scope=${storeConfig.api.storeId}&returnUrl=${storeConfig.storeUrl}`
20
- )
102
+
103
+ try {
104
+ // Clear client-side storage (sessionStorage, localStorage, IndexedDB, non-HttpOnly cookies)
105
+ await clearBrowserStorageForCurrentDomain()
106
+
107
+ // Clear HttpOnly cookies via API endpoint (server-side)
108
+ try {
109
+ await fetch('/api/fs/logout', {
110
+ method: 'POST',
111
+ credentials: 'include',
112
+ })
113
+ } catch {
114
+ // Continue even if API call fails
115
+ }
116
+ } finally {
117
+ window.location.assign(
118
+ `${storeConfig.secureSubdomain}/api/vtexid/pub/logout?scope=${storeConfig.api.storeId}&returnUrl=${storeConfig.storeUrl}`
119
+ )
120
+ }
21
121
  }
22
122
 
23
123
  export const OrganizationDrawer = ({
@@ -0,0 +1,76 @@
1
+ import { parse } from 'cookie'
2
+ import type { NextApiHandler, NextApiRequest, NextApiResponse } from 'next'
3
+
4
+ import discoveryConfig from 'discovery.config'
5
+ import {
6
+ expireCookieServer,
7
+ getCookieDomains,
8
+ getVtexCookieNames,
9
+ } from 'src/utils/clearCookies'
10
+
11
+ const ADDITIONAL_COOKIES = ['CheckoutOrderFormOwnership'] as const
12
+
13
+ /**
14
+ * Clears all cookies containing 'vtex' in the name (case-insensitive) + ADDITIONAL_COOKIES
15
+ * This endpoint handles HttpOnly cookies that cannot be cleared via JavaScript
16
+ */
17
+ const handler: NextApiHandler = async (
18
+ request: NextApiRequest,
19
+ response: NextApiResponse
20
+ ) => {
21
+ if (request.method !== 'POST') {
22
+ response.status(405).end()
23
+ return
24
+ }
25
+
26
+ try {
27
+ const hostname = request.headers.host?.split(':')[0] ?? ''
28
+ const cookies = parse(request.headers.cookie ?? '')
29
+ const domains = getCookieDomains(hostname)
30
+ const clearedCookies: string[] = []
31
+
32
+ const vtexCookieNames = getVtexCookieNames(Object.keys(cookies))
33
+
34
+ // Clear vid_rt cookie with specific path (only if refreshToken is enabled)
35
+ if (discoveryConfig.experimental?.refreshToken && cookies.vid_rt) {
36
+ for (const domain of domains) {
37
+ const clearedCookie = expireCookieServer({
38
+ name: 'vid_rt',
39
+ path: '/api/vtexid/refreshtoken/webstore',
40
+ domain,
41
+ })
42
+ clearedCookies.push(clearedCookie)
43
+ }
44
+ }
45
+
46
+ // Clear other cookies with path /
47
+ const otherCookieNames = [
48
+ ...vtexCookieNames,
49
+ ...ADDITIONAL_COOKIES.filter((name) => cookies[name]),
50
+ ]
51
+
52
+ for (const cookieName of otherCookieNames) {
53
+ for (const domain of domains) {
54
+ const clearedCookie = expireCookieServer({
55
+ name: cookieName,
56
+ path: '/',
57
+ domain,
58
+ })
59
+ clearedCookies.push(clearedCookie)
60
+ }
61
+ }
62
+
63
+ if (clearedCookies.length > 0) {
64
+ response.setHeader('set-cookie', clearedCookies)
65
+ }
66
+
67
+ response.status(200).json({ success: true })
68
+ } catch (error) {
69
+ console.error('Error clearing cookies:', error)
70
+ response
71
+ .status(500)
72
+ .json({ success: false, error: 'Failed to clear cookies' })
73
+ }
74
+ }
75
+
76
+ export default handler
@@ -0,0 +1,79 @@
1
+ type ExpireCookieClientParams = {
2
+ name: string
3
+ path: string
4
+ domain?: string
5
+ secure?: boolean
6
+ }
7
+
8
+ type ExpireCookieServerParams = {
9
+ name: string
10
+ path: string
11
+ domain?: string
12
+ }
13
+
14
+ /**
15
+ * Client-side: Expires a cookie by setting it to expire in the past
16
+ */
17
+ export const expireCookieClient = ({
18
+ name,
19
+ path,
20
+ domain,
21
+ secure = false,
22
+ }: ExpireCookieClientParams): void => {
23
+ const domainAttr = domain ? `; domain=${domain}` : ''
24
+ const secureAttr = secure ? '; secure' : ''
25
+ document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; max-age=0; path=${path}${domainAttr}; samesite=lax${secureAttr}`
26
+ }
27
+
28
+ /**
29
+ * Server-side: Generates a Set-Cookie header string to expire a cookie
30
+ */
31
+ export const expireCookieServer = ({
32
+ name,
33
+ path,
34
+ domain,
35
+ }: ExpireCookieServerParams): string => {
36
+ const domainAttr = domain ? `; domain=${domain}` : ''
37
+ return `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; max-age=0; path=${path}${domainAttr}; samesite=lax; httponly`
38
+ }
39
+
40
+ /**
41
+ * Utility functions for clearing cookies
42
+ * Shared logic between client-side and server-side cookie clearing
43
+ */
44
+
45
+ /**
46
+ * Generates domain variations for cookie clearing
47
+ * Tries multiple domain combinations to ensure cookies are cleared regardless of how they were set
48
+ */
49
+ export const getCookieDomains = (
50
+ hostname: string
51
+ ): Array<string | undefined> => [
52
+ undefined, // host-only cookie
53
+ hostname,
54
+ hostname.startsWith('.') ? hostname : `.${hostname}`,
55
+ ]
56
+
57
+ /**
58
+ * Filters cookie names that contain 'vtex' (case-insensitive)
59
+ */
60
+ export const getVtexCookieNames = (cookieNames: string[]): string[] => {
61
+ return cookieNames.filter((name) => name.toLowerCase().includes('vtex'))
62
+ }
63
+
64
+ /**
65
+ * Generates paths to try when clearing cookies
66
+ * Includes root path and all parent paths from current pathname
67
+ */
68
+ export const getCookiePaths = (pathname: string): string[] => {
69
+ const paths: string[] = ['/']
70
+ const pathParts = pathname.split('/').filter(Boolean)
71
+
72
+ let current = ''
73
+ for (const part of pathParts) {
74
+ current += `/${part}`
75
+ if (!paths.includes(current)) paths.push(current)
76
+ }
77
+
78
+ return paths
79
+ }