@windrun-huaiin/third-ui 30.1.0 → 31.0.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.
- package/README.md +109 -143
- package/dist/ai/ai-prompt-textarea.js +5 -5
- package/dist/ai/ai-prompt-textarea.mjs +5 -5
- package/dist/clerk/clerk-auth-appearance.d.ts +13 -0
- package/dist/clerk/clerk-auth-appearance.js +19 -0
- package/dist/clerk/clerk-auth-appearance.mjs +15 -0
- package/dist/clerk/clerk-auth-modal-appearance.d.ts +12 -0
- package/dist/clerk/clerk-auth-modal-appearance.js +17 -0
- package/dist/clerk/clerk-auth-modal-appearance.mjs +14 -0
- package/dist/clerk/clerk-page-context-generator.js +3 -3
- package/dist/clerk/clerk-page-context-generator.mjs +3 -3
- package/dist/clerk/clerk-page-generator.js +4 -4
- package/dist/clerk/clerk-page-generator.mjs +4 -4
- package/dist/clerk/clerk-user-client.js +2 -1
- package/dist/clerk/clerk-user-client.mjs +2 -1
- package/dist/clerk/fingerprint/fingerprint-client.d.ts +10 -10
- package/dist/clerk/fingerprint/fingerprint-client.js +20 -20
- package/dist/clerk/fingerprint/fingerprint-client.mjs +20 -20
- package/dist/clerk/fingerprint/fingerprint-provider.d.ts +3 -3
- package/dist/clerk/fingerprint/fingerprint-provider.js +8 -8
- package/dist/clerk/fingerprint/fingerprint-provider.mjs +8 -8
- package/dist/clerk/fingerprint/fingerprint-server.d.ts +12 -12
- package/dist/clerk/fingerprint/fingerprint-server.js +17 -17
- package/dist/clerk/fingerprint/fingerprint-server.mjs +17 -17
- package/dist/clerk/fingerprint/fingerprint-shared.d.ts +3 -3
- package/dist/clerk/fingerprint/fingerprint-shared.js +10 -10
- package/dist/clerk/fingerprint/fingerprint-shared.mjs +10 -10
- package/dist/clerk/fingerprint/types.d.ts +0 -1
- package/dist/clerk/fingerprint/use-fingerprint.js +7 -7
- package/dist/clerk/fingerprint/use-fingerprint.mjs +7 -7
- package/dist/clerk/signin-with-fingerprint-client.d.ts +2 -2
- package/dist/clerk/signin-with-fingerprint-client.js +7 -6
- package/dist/clerk/signin-with-fingerprint-client.mjs +7 -6
- package/dist/clerk/signup-button-with-fingerprint-client.js +6 -4
- package/dist/clerk/signup-button-with-fingerprint-client.mjs +6 -4
- package/dist/clerk/signup-with-fingerprint-client.d.ts +2 -2
- package/dist/clerk/signup-with-fingerprint-client.js +7 -6
- package/dist/clerk/signup-with-fingerprint-client.mjs +7 -6
- package/dist/fuma/heavy/mermaid.js +1 -1
- package/dist/fuma/heavy/mermaid.mjs +1 -1
- package/dist/fuma/site-x.js +0 -1
- package/dist/fuma/site-x.mjs +0 -1
- package/dist/main/calendar/calendar-date-range-input.js +1 -1
- package/dist/main/calendar/calendar-date-range-input.mjs +1 -1
- package/dist/main/credit/types.d.ts +8 -8
- package/dist/main/money-price/index.d.ts +1 -1
- package/dist/main/money-price/money-price-button.js +10 -10
- package/dist/main/money-price/money-price-button.mjs +10 -10
- package/dist/main/money-price/money-price-config-util.d.ts +30 -30
- package/dist/main/money-price/money-price-config-util.js +48 -48
- package/dist/main/money-price/money-price-config-util.mjs +48 -48
- package/dist/main/money-price/money-price-interactive.js +30 -18
- package/dist/main/money-price/money-price-interactive.mjs +30 -18
- package/dist/main/money-price/money-price-types.d.ts +7 -1
- package/dist/main/money-price/money-price-types.js +2 -2
- package/dist/main/money-price/money-price-types.mjs +2 -2
- package/dist/main/money-price/server.d.ts +1 -1
- package/dist/main/pill-select/x-pill-select.js +2 -2
- package/dist/main/pill-select/x-pill-select.mjs +2 -2
- package/dist/main/server.d.ts +1 -1
- package/package.json +13 -7
- package/src/ai/ai-prompt-textarea.tsx +6 -6
- package/src/clerk/clerk-auth-appearance.ts +16 -0
- package/src/clerk/clerk-page-context-generator.tsx +3 -5
- package/src/clerk/clerk-page-generator.tsx +9 -8
- package/src/clerk/clerk-user-client.tsx +14 -5
- package/src/clerk/fingerprint/fingerprint-client.ts +20 -20
- package/src/clerk/fingerprint/fingerprint-provider.tsx +11 -11
- package/src/clerk/fingerprint/fingerprint-server.ts +17 -17
- package/src/clerk/fingerprint/fingerprint-shared.ts +10 -10
- package/src/clerk/fingerprint/types.ts +0 -1
- package/src/clerk/fingerprint/use-fingerprint.ts +7 -7
- package/src/clerk/signin-with-fingerprint-client.tsx +7 -7
- package/src/clerk/signup-button-with-fingerprint-client.tsx +7 -5
- package/src/clerk/signup-with-fingerprint-client.tsx +7 -7
- package/src/fuma/base/custom-home-layout.tsx +4 -4
- package/src/fuma/heavy/mermaid.tsx +1 -1
- package/src/fuma/site-x.tsx +0 -1
- package/src/main/calendar/calendar-date-range-input.tsx +1 -1
- package/src/main/credit/types.ts +8 -8
- package/src/main/gallery/gallery-mobile-swiper.tsx +0 -1
- package/src/main/gallery/gallery-server.tsx +2 -2
- package/src/main/money-price/index.ts +2 -0
- package/src/main/money-price/money-price-button.tsx +10 -10
- package/src/main/money-price/money-price-config-util.ts +49 -49
- package/src/main/money-price/money-price-interactive.tsx +40 -20
- package/src/main/money-price/money-price-types.ts +21 -14
- package/src/main/money-price/server.ts +2 -0
- package/src/main/pill-select/x-pill-select.tsx +2 -2
- package/src/main/server.ts +3 -1
- package/src/styles/third-ui.css +8 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Fingerprint Client Utilities
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Client-only fingerprint generation and management logic.
|
|
4
|
+
* Must be used only in browser environments.
|
|
5
5
|
*/
|
|
6
6
|
type FirstTouchData = {
|
|
7
7
|
landingUrl?: string;
|
|
@@ -25,29 +25,29 @@ type FirstTouchData = {
|
|
|
25
25
|
};
|
|
26
26
|
export declare function getOrCreateFirstTouchData(): FirstTouchData | null;
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
28
|
+
* Generate a fingerprint ID from real browser characteristics.
|
|
29
|
+
* Uses FingerprintJS to collect browser signals and create a stable identifier.
|
|
30
30
|
*/
|
|
31
31
|
export declare function generateFingerprintId(): Promise<string>;
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
33
|
+
* Get the current fingerprint ID.
|
|
34
34
|
*/
|
|
35
35
|
export declare function getFingerprintId(): string | null;
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
37
|
+
* Store a fingerprint ID.
|
|
38
38
|
*/
|
|
39
39
|
export declare function setFingerprintId(fingerprintId: string): void;
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
41
|
+
* Clear the fingerprint ID.
|
|
42
42
|
*/
|
|
43
43
|
export declare function clearFingerprintId(): void;
|
|
44
44
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
45
|
+
* Get or generate a fingerprint ID.
|
|
46
|
+
* Automatically creates one when none exists.
|
|
47
47
|
*/
|
|
48
48
|
export declare function getOrGenerateFingerprintId(): Promise<string>;
|
|
49
49
|
/**
|
|
50
|
-
*
|
|
50
|
+
* Create fetch headers containing the fingerprint ID.
|
|
51
51
|
*/
|
|
52
52
|
export declare function createFingerprintHeaders(): Promise<Record<string, string>>;
|
|
53
53
|
/**
|
|
@@ -6,28 +6,28 @@ var fingerprintShared = require('./fingerprint-shared.js');
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Fingerprint Client Utilities
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* Client-only fingerprint generation and management logic.
|
|
10
|
+
* Must be used only in browser environments.
|
|
11
11
|
*/
|
|
12
12
|
const FIRST_TOUCH_MAX_LENGTH = 2048;
|
|
13
13
|
const FIRST_TOUCH_COOKIE_DAYS = 30;
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* Check fingerprint ID in browser storage, including localStorage and cookies.
|
|
16
|
+
* Returns a valid ID or null.
|
|
17
17
|
*/
|
|
18
18
|
function checkStoredFingerprintId() {
|
|
19
19
|
if (typeof window === 'undefined') {
|
|
20
20
|
return null;
|
|
21
21
|
}
|
|
22
|
-
//
|
|
22
|
+
// Prefer localStorage.
|
|
23
23
|
const localStorageId = getLocalStorageValue(fingerprintShared.FINGERPRINT_STORAGE_KEY);
|
|
24
24
|
if (localStorageId && fingerprintShared.isValidFingerprintId(localStorageId)) {
|
|
25
25
|
return localStorageId;
|
|
26
26
|
}
|
|
27
|
-
//
|
|
27
|
+
// Check cookies.
|
|
28
28
|
const cookieId = getCookieValue(fingerprintShared.FINGERPRINT_COOKIE_NAME);
|
|
29
29
|
if (cookieId && fingerprintShared.isValidFingerprintId(cookieId)) {
|
|
30
|
-
//
|
|
30
|
+
// Sync back to localStorage.
|
|
31
31
|
setLocalStorageValue(fingerprintShared.FINGERPRINT_STORAGE_KEY, cookieId);
|
|
32
32
|
return cookieId;
|
|
33
33
|
}
|
|
@@ -152,32 +152,32 @@ function getOrCreateFirstTouchData() {
|
|
|
152
152
|
return created;
|
|
153
153
|
}
|
|
154
154
|
/**
|
|
155
|
-
*
|
|
156
|
-
*
|
|
155
|
+
* Generate a fingerprint ID from real browser characteristics.
|
|
156
|
+
* Uses FingerprintJS to collect browser signals and create a stable identifier.
|
|
157
157
|
*/
|
|
158
158
|
function generateFingerprintId() {
|
|
159
159
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
160
160
|
if (typeof window === 'undefined') {
|
|
161
161
|
throw new Error('generateFingerprintId can only be used in browser environment');
|
|
162
162
|
}
|
|
163
|
-
//
|
|
163
|
+
// Check for an existing ID.
|
|
164
164
|
const existingId = checkStoredFingerprintId();
|
|
165
165
|
if (existingId) {
|
|
166
166
|
return existingId;
|
|
167
167
|
}
|
|
168
168
|
try {
|
|
169
|
-
//
|
|
169
|
+
// Generate a fingerprint with FingerprintJS.
|
|
170
170
|
const fp = yield FingerprintJS.load();
|
|
171
171
|
const result = yield fp.get();
|
|
172
172
|
const fingerprintId = `fp_${result.visitorId}`;
|
|
173
|
-
//
|
|
173
|
+
// Store in localStorage and cookies.
|
|
174
174
|
setLocalStorageValue(fingerprintShared.FINGERPRINT_STORAGE_KEY, fingerprintId);
|
|
175
175
|
setCookie(fingerprintShared.FINGERPRINT_COOKIE_NAME, fingerprintId, 365);
|
|
176
176
|
return fingerprintId;
|
|
177
177
|
}
|
|
178
178
|
catch (error) {
|
|
179
179
|
console.warn('Failed to generate fingerprint with FingerprintJS:', error);
|
|
180
|
-
//
|
|
180
|
+
// Fallback: generate an ID from timestamp and randomness.
|
|
181
181
|
const fallbackId = `fp_fallback_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
|
|
182
182
|
setLocalStorageValue(fingerprintShared.FINGERPRINT_STORAGE_KEY, fallbackId);
|
|
183
183
|
setCookie(fingerprintShared.FINGERPRINT_COOKIE_NAME, fallbackId, 365);
|
|
@@ -186,13 +186,13 @@ function generateFingerprintId() {
|
|
|
186
186
|
});
|
|
187
187
|
}
|
|
188
188
|
/**
|
|
189
|
-
*
|
|
189
|
+
* Get the current fingerprint ID.
|
|
190
190
|
*/
|
|
191
191
|
function getFingerprintId() {
|
|
192
192
|
return checkStoredFingerprintId();
|
|
193
193
|
}
|
|
194
194
|
/**
|
|
195
|
-
*
|
|
195
|
+
* Store a fingerprint ID.
|
|
196
196
|
*/
|
|
197
197
|
function setFingerprintId(fingerprintId) {
|
|
198
198
|
if (typeof window === 'undefined') {
|
|
@@ -205,7 +205,7 @@ function setFingerprintId(fingerprintId) {
|
|
|
205
205
|
setCookie(fingerprintShared.FINGERPRINT_COOKIE_NAME, fingerprintId, 365);
|
|
206
206
|
}
|
|
207
207
|
/**
|
|
208
|
-
*
|
|
208
|
+
* Clear the fingerprint ID.
|
|
209
209
|
*/
|
|
210
210
|
function clearFingerprintId() {
|
|
211
211
|
if (typeof window === 'undefined') {
|
|
@@ -215,8 +215,8 @@ function clearFingerprintId() {
|
|
|
215
215
|
deleteCookie(fingerprintShared.FINGERPRINT_COOKIE_NAME);
|
|
216
216
|
}
|
|
217
217
|
/**
|
|
218
|
-
*
|
|
219
|
-
*
|
|
218
|
+
* Get or generate a fingerprint ID.
|
|
219
|
+
* Automatically creates one when none exists.
|
|
220
220
|
*/
|
|
221
221
|
function getOrGenerateFingerprintId() {
|
|
222
222
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -228,7 +228,7 @@ function getOrGenerateFingerprintId() {
|
|
|
228
228
|
});
|
|
229
229
|
}
|
|
230
230
|
/**
|
|
231
|
-
*
|
|
231
|
+
* Create fetch headers containing the fingerprint ID.
|
|
232
232
|
*/
|
|
233
233
|
function createFingerprintHeaders() {
|
|
234
234
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -259,7 +259,7 @@ function createFingerprintFetch() {
|
|
|
259
259
|
return fetch(url, Object.assign(Object.assign({}, init), { headers }));
|
|
260
260
|
});
|
|
261
261
|
}
|
|
262
|
-
//
|
|
262
|
+
// Private cookie helpers.
|
|
263
263
|
function getCookieValue(name) {
|
|
264
264
|
var _a;
|
|
265
265
|
if (typeof document === 'undefined') {
|
|
@@ -4,28 +4,28 @@ import { FINGERPRINT_STORAGE_KEY, FINGERPRINT_COOKIE_NAME, isValidFingerprintId,
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Fingerprint Client Utilities
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Client-only fingerprint generation and management logic.
|
|
8
|
+
* Must be used only in browser environments.
|
|
9
9
|
*/
|
|
10
10
|
const FIRST_TOUCH_MAX_LENGTH = 2048;
|
|
11
11
|
const FIRST_TOUCH_COOKIE_DAYS = 30;
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* Check fingerprint ID in browser storage, including localStorage and cookies.
|
|
14
|
+
* Returns a valid ID or null.
|
|
15
15
|
*/
|
|
16
16
|
function checkStoredFingerprintId() {
|
|
17
17
|
if (typeof window === 'undefined') {
|
|
18
18
|
return null;
|
|
19
19
|
}
|
|
20
|
-
//
|
|
20
|
+
// Prefer localStorage.
|
|
21
21
|
const localStorageId = getLocalStorageValue(FINGERPRINT_STORAGE_KEY);
|
|
22
22
|
if (localStorageId && isValidFingerprintId(localStorageId)) {
|
|
23
23
|
return localStorageId;
|
|
24
24
|
}
|
|
25
|
-
//
|
|
25
|
+
// Check cookies.
|
|
26
26
|
const cookieId = getCookieValue(FINGERPRINT_COOKIE_NAME);
|
|
27
27
|
if (cookieId && isValidFingerprintId(cookieId)) {
|
|
28
|
-
//
|
|
28
|
+
// Sync back to localStorage.
|
|
29
29
|
setLocalStorageValue(FINGERPRINT_STORAGE_KEY, cookieId);
|
|
30
30
|
return cookieId;
|
|
31
31
|
}
|
|
@@ -150,32 +150,32 @@ function getOrCreateFirstTouchData() {
|
|
|
150
150
|
return created;
|
|
151
151
|
}
|
|
152
152
|
/**
|
|
153
|
-
*
|
|
154
|
-
*
|
|
153
|
+
* Generate a fingerprint ID from real browser characteristics.
|
|
154
|
+
* Uses FingerprintJS to collect browser signals and create a stable identifier.
|
|
155
155
|
*/
|
|
156
156
|
function generateFingerprintId() {
|
|
157
157
|
return __awaiter(this, void 0, void 0, function* () {
|
|
158
158
|
if (typeof window === 'undefined') {
|
|
159
159
|
throw new Error('generateFingerprintId can only be used in browser environment');
|
|
160
160
|
}
|
|
161
|
-
//
|
|
161
|
+
// Check for an existing ID.
|
|
162
162
|
const existingId = checkStoredFingerprintId();
|
|
163
163
|
if (existingId) {
|
|
164
164
|
return existingId;
|
|
165
165
|
}
|
|
166
166
|
try {
|
|
167
|
-
//
|
|
167
|
+
// Generate a fingerprint with FingerprintJS.
|
|
168
168
|
const fp = yield FingerprintJS.load();
|
|
169
169
|
const result = yield fp.get();
|
|
170
170
|
const fingerprintId = `fp_${result.visitorId}`;
|
|
171
|
-
//
|
|
171
|
+
// Store in localStorage and cookies.
|
|
172
172
|
setLocalStorageValue(FINGERPRINT_STORAGE_KEY, fingerprintId);
|
|
173
173
|
setCookie(FINGERPRINT_COOKIE_NAME, fingerprintId, 365);
|
|
174
174
|
return fingerprintId;
|
|
175
175
|
}
|
|
176
176
|
catch (error) {
|
|
177
177
|
console.warn('Failed to generate fingerprint with FingerprintJS:', error);
|
|
178
|
-
//
|
|
178
|
+
// Fallback: generate an ID from timestamp and randomness.
|
|
179
179
|
const fallbackId = `fp_fallback_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
|
|
180
180
|
setLocalStorageValue(FINGERPRINT_STORAGE_KEY, fallbackId);
|
|
181
181
|
setCookie(FINGERPRINT_COOKIE_NAME, fallbackId, 365);
|
|
@@ -184,13 +184,13 @@ function generateFingerprintId() {
|
|
|
184
184
|
});
|
|
185
185
|
}
|
|
186
186
|
/**
|
|
187
|
-
*
|
|
187
|
+
* Get the current fingerprint ID.
|
|
188
188
|
*/
|
|
189
189
|
function getFingerprintId() {
|
|
190
190
|
return checkStoredFingerprintId();
|
|
191
191
|
}
|
|
192
192
|
/**
|
|
193
|
-
*
|
|
193
|
+
* Store a fingerprint ID.
|
|
194
194
|
*/
|
|
195
195
|
function setFingerprintId(fingerprintId) {
|
|
196
196
|
if (typeof window === 'undefined') {
|
|
@@ -203,7 +203,7 @@ function setFingerprintId(fingerprintId) {
|
|
|
203
203
|
setCookie(FINGERPRINT_COOKIE_NAME, fingerprintId, 365);
|
|
204
204
|
}
|
|
205
205
|
/**
|
|
206
|
-
*
|
|
206
|
+
* Clear the fingerprint ID.
|
|
207
207
|
*/
|
|
208
208
|
function clearFingerprintId() {
|
|
209
209
|
if (typeof window === 'undefined') {
|
|
@@ -213,8 +213,8 @@ function clearFingerprintId() {
|
|
|
213
213
|
deleteCookie(FINGERPRINT_COOKIE_NAME);
|
|
214
214
|
}
|
|
215
215
|
/**
|
|
216
|
-
*
|
|
217
|
-
*
|
|
216
|
+
* Get or generate a fingerprint ID.
|
|
217
|
+
* Automatically creates one when none exists.
|
|
218
218
|
*/
|
|
219
219
|
function getOrGenerateFingerprintId() {
|
|
220
220
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -226,7 +226,7 @@ function getOrGenerateFingerprintId() {
|
|
|
226
226
|
});
|
|
227
227
|
}
|
|
228
228
|
/**
|
|
229
|
-
*
|
|
229
|
+
* Create fetch headers containing the fingerprint ID.
|
|
230
230
|
*/
|
|
231
231
|
function createFingerprintHeaders() {
|
|
232
232
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -257,7 +257,7 @@ function createFingerprintFetch() {
|
|
|
257
257
|
return fetch(url, Object.assign(Object.assign({}, init), { headers }));
|
|
258
258
|
});
|
|
259
259
|
}
|
|
260
|
-
//
|
|
260
|
+
// Private cookie helpers.
|
|
261
261
|
function getCookieValue(name) {
|
|
262
262
|
var _a;
|
|
263
263
|
if (typeof document === 'undefined') {
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import type { FingerprintContextType, FingerprintProviderProps } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Fingerprint Provider Component
|
|
5
|
-
*
|
|
5
|
+
* Provides fingerprint and anonymous user management for the application.
|
|
6
6
|
*/
|
|
7
7
|
export declare function FingerprintProvider({ children, config }: FingerprintProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
8
8
|
/**
|
|
@@ -11,7 +11,7 @@ export declare function FingerprintProvider({ children, config }: FingerprintPro
|
|
|
11
11
|
export declare function useFingerprintContext(): FingerprintContextType;
|
|
12
12
|
/**
|
|
13
13
|
* Safe hook to use fingerprint context - returns null if no provider
|
|
14
|
-
*
|
|
14
|
+
* Returns null when no provider is available.
|
|
15
15
|
*/
|
|
16
16
|
export declare function useFingerprintContextSafe(): FingerprintContextType | null;
|
|
17
17
|
/**
|
|
@@ -20,6 +20,6 @@ export declare function useFingerprintContextSafe(): FingerprintContextType | nu
|
|
|
20
20
|
*/
|
|
21
21
|
export declare function withFingerprint<P extends object>(Component: React.ComponentType<P>, config: FingerprintProviderProps['config']): (props: P) => import("react/jsx-runtime").JSX.Element;
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
23
|
+
* Component for displaying user status and credit information for debugging.
|
|
24
24
|
*/
|
|
25
25
|
export declare function FingerprintStatus(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -23,7 +23,7 @@ function useFingerprintStatusTranslations() {
|
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
25
|
* Fingerprint Provider Component
|
|
26
|
-
*
|
|
26
|
+
* Provides fingerprint and anonymous user management for the application.
|
|
27
27
|
*/
|
|
28
28
|
function FingerprintProvider({ children, config }) {
|
|
29
29
|
const fingerprintData = useFingerprint.useFingerprint(config);
|
|
@@ -41,7 +41,7 @@ function useFingerprintContext() {
|
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
43
|
* Safe hook to use fingerprint context - returns null if no provider
|
|
44
|
-
*
|
|
44
|
+
* Returns null when no provider is available.
|
|
45
45
|
*/
|
|
46
46
|
function useFingerprintContextSafe() {
|
|
47
47
|
const context = React.useContext(FingerprintContext);
|
|
@@ -57,7 +57,7 @@ function withFingerprint(Component, config) {
|
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
60
|
-
*
|
|
60
|
+
* Component for displaying user status and credit information for debugging.
|
|
61
61
|
*/
|
|
62
62
|
function FingerprintStatus() {
|
|
63
63
|
const translations = useFingerprintStatusTranslations();
|
|
@@ -275,8 +275,8 @@ function FingerprintStatus() {
|
|
|
275
275
|
{ label: translations.labels.priceId, value: jsxRuntime.jsx(ui.CopyableText, { text: (xSubscription === null || xSubscription === void 0 ? void 0 : xSubscription.priceId) || '' }) },
|
|
276
276
|
] })] })) : (jsxRuntime.jsxs("div", { className: "space-y-3 rounded-xl border border-slate-200/70 bg-white/85 p-4 shadow-sm dark:border-white/12 dark:bg-slate-900/45", children: [jsxRuntime.jsx(PanelHeader, { icon: jsxRuntime.jsx(icons.DatabaseZapIcon, { className: "size-4" }), title: translations.sections.concurrentBaseInfo, rightInfo: jsxRuntime.jsx(StatusTag, { value: isRunningTest ? translations.status.pending : translations.status.idle, translations: translations }) }), jsxRuntime.jsxs("div", { className: "space-y-2 text-xs text-slate-500 dark:text-slate-300", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxRuntime.jsx("span", { className: "text-slate-400 dark:text-slate-500", children: translations.labels.realBrowser }), jsxRuntime.jsx(ui.CopyableText, { text: fingerprintId || '' })] }), jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsx("span", { className: "text-slate-400 dark:text-slate-500", children: translations.labels.testOverride }), jsxRuntime.jsxs("div", { className: "flex items-center gap-2 py-1", children: [jsxRuntime.jsx("div", { className: "min-w-0 flex-1 rounded-lg border border-slate-200 bg-white px-3 py-2 font-mono text-[0.5rem] sm:text-[0.625rem] md:text-xs leading-tight text-slate-700 dark:border-white/10 dark:bg-slate-950 dark:text-slate-100", children: jsxRuntime.jsx(ui.CopyableText, { text: activeDebugFingerprintId || '' }) }), jsxRuntime.jsx("button", { type: "button", disabled: isRunningTest, onClick: regenerateTestFingerprint, "aria-label": translations.actions.generateNewTestFingerprintAriaLabel, className: "inline-flex size-9 items-center justify-center rounded-lg border border-slate-200 bg-slate-50 text-slate-700 transition hover:border-slate-300 hover:bg-slate-100 disabled:cursor-not-allowed disabled:opacity-50 dark:border-white/10 dark:bg-slate-950 dark:text-slate-100 dark:hover:bg-slate-900", children: jsxRuntime.jsx(icons.RefreshCcwIcon, { className: "size-4" }) })] })] })] }), jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: [jsxRuntime.jsx("button", { type: "button", disabled: isRunningTest, onClick: runContextParallelInitTest, className: utils.cn('shrink-0 rounded-full border px-3 py-2 text-xs font-semibold transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-50', themedGhostButtonClass), children: translations.actions.frontendPreventionTest }), jsxRuntime.jsx("button", { type: "button", disabled: isRunningTest, onClick: runRawParallelPostTest, className: utils.cn('shrink-0 rounded-full border px-3 py-2 text-xs font-semibold text-white shadow-sm transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-50', 'border-transparent', lib.themeButtonGradientClass, lib.themeButtonGradientHoverClass), children: translations.actions.backendIdempotencyTest })] }), jsxRuntime.jsx("div", { className: "rounded-lg border border-dashed border-slate-200 bg-slate-50/80 p-3 dark:border-white/10 dark:bg-slate-950/50", children: jsxRuntime.jsx("pre", { className: "overflow-x-auto whitespace-pre-wrap break-all font-mono text-[11px] leading-5 text-slate-600 dark:text-slate-300", children: testResult || translations.placeholders.noTestExecutedYet }) })] })), error && (jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3 rounded-xl border border-amber-200 bg-amber-50 p-3 text-xs text-amber-600 shadow-sm dark:border-amber-500/40 dark:bg-amber-500/10 dark:text-amber-200", children: [jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [jsxRuntime.jsx(icons.XIcon, { className: "mt-0.5 size-4 shrink-0" }), jsxRuntime.jsx("span", { children: error })] }), jsxRuntime.jsx("button", { type: "button", "aria-label": translations.actions.dismissErrorAriaLabel, onClick: clearError, className: "shrink-0 rounded-full p-1 text-amber-500 transition hover:bg-amber-100 hover:text-amber-700 dark:text-amber-200 dark:hover:bg-amber-500/10 dark:hover:text-amber-100", children: jsxRuntime.jsx(icons.XIcon, { className: "size-4" }) })] }))] })] })] }))] }));
|
|
277
277
|
}
|
|
278
|
-
/* ====================
|
|
279
|
-
//
|
|
278
|
+
/* ==================== Helper Components ==================== */
|
|
279
|
+
// Header row with icon and title on the left, right-aligned metadata on the right.
|
|
280
280
|
function PanelHeader({ icon, title, rightInfo }) {
|
|
281
281
|
return (jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-3", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm font-semibold text-slate-700 dark:text-slate-100", children: [jsxRuntime.jsx("span", { className: "flex size-6 items-center justify-center rounded-full bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-300", children: icon }), jsxRuntime.jsx("span", { className: utils.cn("rounded-full bg-purple-100 px-2 py-1 text-xs font-bold", lib.themeIconColor), children: title })] }), jsxRuntime.jsx("span", { className: "text-sm font-medium text-slate-600 dark:text-slate-300", children: rightInfo })] }));
|
|
282
282
|
}
|
|
@@ -319,17 +319,17 @@ function StatusTag({ value, translations, }) {
|
|
|
319
319
|
return jsxRuntime.jsx("span", { className: "text-slate-400", children: translations.placeholders.none });
|
|
320
320
|
const normalized = value.toLowerCase();
|
|
321
321
|
const colorMap = {
|
|
322
|
-
//
|
|
322
|
+
// Green: normal or active.
|
|
323
323
|
registered: 'bg-green-100 text-green-700 dark:bg-green-500/20 dark:text-green-300',
|
|
324
324
|
active: 'bg-green-100 text-green-700 dark:bg-green-500/20 dark:text-green-300',
|
|
325
325
|
trialing: 'bg-green-100 text-green-700 dark:bg-green-500/20 dark:text-green-300',
|
|
326
|
-
//
|
|
326
|
+
// Gray: inactive or deleted.
|
|
327
327
|
canceled: 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-400',
|
|
328
328
|
frozen: 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-400',
|
|
329
329
|
deleted: 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-400',
|
|
330
330
|
expired: 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-400',
|
|
331
331
|
past_due: 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-400',
|
|
332
|
-
//
|
|
332
|
+
// Amber: pending or exceptional states.
|
|
333
333
|
pending: 'bg-amber-100 text-amber-700 dark:bg-amber-500/20 dark:text-amber-300',
|
|
334
334
|
failed: 'bg-amber-100 text-amber-700 dark:bg-amber-500/20 dark:text-amber-300',
|
|
335
335
|
unpaid: 'bg-amber-100 text-amber-700 dark:bg-amber-500/20 dark:text-amber-300',
|
|
@@ -21,7 +21,7 @@ function useFingerprintStatusTranslations() {
|
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* Fingerprint Provider Component
|
|
24
|
-
*
|
|
24
|
+
* Provides fingerprint and anonymous user management for the application.
|
|
25
25
|
*/
|
|
26
26
|
function FingerprintProvider({ children, config }) {
|
|
27
27
|
const fingerprintData = useFingerprint(config);
|
|
@@ -39,7 +39,7 @@ function useFingerprintContext() {
|
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
41
|
* Safe hook to use fingerprint context - returns null if no provider
|
|
42
|
-
*
|
|
42
|
+
* Returns null when no provider is available.
|
|
43
43
|
*/
|
|
44
44
|
function useFingerprintContextSafe() {
|
|
45
45
|
const context = useContext(FingerprintContext);
|
|
@@ -55,7 +55,7 @@ function withFingerprint(Component, config) {
|
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
/**
|
|
58
|
-
*
|
|
58
|
+
* Component for displaying user status and credit information for debugging.
|
|
59
59
|
*/
|
|
60
60
|
function FingerprintStatus() {
|
|
61
61
|
const translations = useFingerprintStatusTranslations();
|
|
@@ -273,8 +273,8 @@ function FingerprintStatus() {
|
|
|
273
273
|
{ label: translations.labels.priceId, value: jsx(CopyableText, { text: (xSubscription === null || xSubscription === void 0 ? void 0 : xSubscription.priceId) || '' }) },
|
|
274
274
|
] })] })) : (jsxs("div", { className: "space-y-3 rounded-xl border border-slate-200/70 bg-white/85 p-4 shadow-sm dark:border-white/12 dark:bg-slate-900/45", children: [jsx(PanelHeader, { icon: jsx(DatabaseZapIcon, { className: "size-4" }), title: translations.sections.concurrentBaseInfo, rightInfo: jsx(StatusTag, { value: isRunningTest ? translations.status.pending : translations.status.idle, translations: translations }) }), jsxs("div", { className: "space-y-2 text-xs text-slate-500 dark:text-slate-300", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsx("span", { className: "text-slate-400 dark:text-slate-500", children: translations.labels.realBrowser }), jsx(CopyableText, { text: fingerprintId || '' })] }), jsxs("div", { className: "space-y-1", children: [jsx("span", { className: "text-slate-400 dark:text-slate-500", children: translations.labels.testOverride }), jsxs("div", { className: "flex items-center gap-2 py-1", children: [jsx("div", { className: "min-w-0 flex-1 rounded-lg border border-slate-200 bg-white px-3 py-2 font-mono text-[0.5rem] sm:text-[0.625rem] md:text-xs leading-tight text-slate-700 dark:border-white/10 dark:bg-slate-950 dark:text-slate-100", children: jsx(CopyableText, { text: activeDebugFingerprintId || '' }) }), jsx("button", { type: "button", disabled: isRunningTest, onClick: regenerateTestFingerprint, "aria-label": translations.actions.generateNewTestFingerprintAriaLabel, className: "inline-flex size-9 items-center justify-center rounded-lg border border-slate-200 bg-slate-50 text-slate-700 transition hover:border-slate-300 hover:bg-slate-100 disabled:cursor-not-allowed disabled:opacity-50 dark:border-white/10 dark:bg-slate-950 dark:text-slate-100 dark:hover:bg-slate-900", children: jsx(RefreshCcwIcon, { className: "size-4" }) })] })] })] }), jsxs("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: [jsx("button", { type: "button", disabled: isRunningTest, onClick: runContextParallelInitTest, className: cn('shrink-0 rounded-full border px-3 py-2 text-xs font-semibold transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-50', themedGhostButtonClass), children: translations.actions.frontendPreventionTest }), jsx("button", { type: "button", disabled: isRunningTest, onClick: runRawParallelPostTest, className: cn('shrink-0 rounded-full border px-3 py-2 text-xs font-semibold text-white shadow-sm transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-50', 'border-transparent', themeButtonGradientClass, themeButtonGradientHoverClass), children: translations.actions.backendIdempotencyTest })] }), jsx("div", { className: "rounded-lg border border-dashed border-slate-200 bg-slate-50/80 p-3 dark:border-white/10 dark:bg-slate-950/50", children: jsx("pre", { className: "overflow-x-auto whitespace-pre-wrap break-all font-mono text-[11px] leading-5 text-slate-600 dark:text-slate-300", children: testResult || translations.placeholders.noTestExecutedYet }) })] })), error && (jsxs("div", { className: "flex items-start justify-between gap-3 rounded-xl border border-amber-200 bg-amber-50 p-3 text-xs text-amber-600 shadow-sm dark:border-amber-500/40 dark:bg-amber-500/10 dark:text-amber-200", children: [jsxs("div", { className: "flex items-start gap-2", children: [jsx(XIcon, { className: "mt-0.5 size-4 shrink-0" }), jsx("span", { children: error })] }), jsx("button", { type: "button", "aria-label": translations.actions.dismissErrorAriaLabel, onClick: clearError, className: "shrink-0 rounded-full p-1 text-amber-500 transition hover:bg-amber-100 hover:text-amber-700 dark:text-amber-200 dark:hover:bg-amber-500/10 dark:hover:text-amber-100", children: jsx(XIcon, { className: "size-4" }) })] }))] })] })] }))] }));
|
|
275
275
|
}
|
|
276
|
-
/* ====================
|
|
277
|
-
//
|
|
276
|
+
/* ==================== Helper Components ==================== */
|
|
277
|
+
// Header row with icon and title on the left, right-aligned metadata on the right.
|
|
278
278
|
function PanelHeader({ icon, title, rightInfo }) {
|
|
279
279
|
return (jsxs("div", { className: "flex items-center justify-between mb-3", children: [jsxs("div", { className: "flex items-center gap-2 text-sm font-semibold text-slate-700 dark:text-slate-100", children: [jsx("span", { className: "flex size-6 items-center justify-center rounded-full bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-300", children: icon }), jsx("span", { className: cn("rounded-full bg-purple-100 px-2 py-1 text-xs font-bold", themeIconColor), children: title })] }), jsx("span", { className: "text-sm font-medium text-slate-600 dark:text-slate-300", children: rightInfo })] }));
|
|
280
280
|
}
|
|
@@ -317,17 +317,17 @@ function StatusTag({ value, translations, }) {
|
|
|
317
317
|
return jsx("span", { className: "text-slate-400", children: translations.placeholders.none });
|
|
318
318
|
const normalized = value.toLowerCase();
|
|
319
319
|
const colorMap = {
|
|
320
|
-
//
|
|
320
|
+
// Green: normal or active.
|
|
321
321
|
registered: 'bg-green-100 text-green-700 dark:bg-green-500/20 dark:text-green-300',
|
|
322
322
|
active: 'bg-green-100 text-green-700 dark:bg-green-500/20 dark:text-green-300',
|
|
323
323
|
trialing: 'bg-green-100 text-green-700 dark:bg-green-500/20 dark:text-green-300',
|
|
324
|
-
//
|
|
324
|
+
// Gray: inactive or deleted.
|
|
325
325
|
canceled: 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-400',
|
|
326
326
|
frozen: 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-400',
|
|
327
327
|
deleted: 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-400',
|
|
328
328
|
expired: 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-400',
|
|
329
329
|
past_due: 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-400',
|
|
330
|
-
//
|
|
330
|
+
// Amber: pending or exceptional states.
|
|
331
331
|
pending: 'bg-amber-100 text-amber-700 dark:bg-amber-500/20 dark:text-amber-300',
|
|
332
332
|
failed: 'bg-amber-100 text-amber-700 dark:bg-amber-500/20 dark:text-amber-300',
|
|
333
333
|
unpaid: 'bg-amber-100 text-amber-700 dark:bg-amber-500/20 dark:text-amber-300',
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Fingerprint Server Utilities
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Server-only fingerprint ID extraction and validation logic.
|
|
4
|
+
* Safe for server usage without browser APIs or FingerprintJS.
|
|
5
5
|
*/
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* Extract fingerprint ID from a request.
|
|
8
|
+
* Priority: header > cookie > query parameter.
|
|
9
|
+
* Safe to use on the server.
|
|
10
10
|
*/
|
|
11
11
|
export declare function extractFingerprintId(headers: Headers | Record<string, string>, cookies?: Record<string, string>, query?: Record<string, string | undefined>): string | null;
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* Generate a server-side fallback fingerprint ID.
|
|
14
|
+
* Used when the client cannot generate a fingerprint.
|
|
15
|
+
* Safe to use on the server.
|
|
16
16
|
*/
|
|
17
17
|
export declare function generateServerFingerprintId(): string;
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* Extract fingerprint ID from a Next.js Request object.
|
|
20
|
+
* Convenience helper for Next.js API routes.
|
|
21
21
|
*/
|
|
22
22
|
export declare function extractFingerprintFromNextRequest(request: Request): string | null;
|
|
23
23
|
type NextHeadersLike = Pick<Headers, 'forEach'>;
|
|
@@ -28,8 +28,8 @@ type NextCookiesLike = {
|
|
|
28
28
|
}>;
|
|
29
29
|
};
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
31
|
+
* Extract fingerprint ID from Next.js runtime headers/cookies stores.
|
|
32
|
+
* Reusable in App Router server components and Server Actions.
|
|
33
33
|
*/
|
|
34
34
|
export declare function extractFingerprintFromNextStores(params: {
|
|
35
35
|
headers: NextHeadersLike;
|
|
@@ -4,30 +4,30 @@ var fingerprintShared = require('./fingerprint-shared.js');
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Fingerprint Server Utilities
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Server-only fingerprint ID extraction and validation logic.
|
|
8
|
+
* Safe for server usage without browser APIs or FingerprintJS.
|
|
9
9
|
*/
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* Extract fingerprint ID from a request.
|
|
12
|
+
* Priority: header > cookie > query parameter.
|
|
13
|
+
* Safe to use on the server.
|
|
14
14
|
*/
|
|
15
15
|
function extractFingerprintId(headers, cookies, query) {
|
|
16
|
-
// 1.
|
|
16
|
+
// 1. Read from header.
|
|
17
17
|
const headerValue = headers instanceof Headers
|
|
18
18
|
? headers.get(fingerprintShared.FINGERPRINT_HEADER_NAME)
|
|
19
19
|
: headers[fingerprintShared.FINGERPRINT_HEADER_NAME];
|
|
20
20
|
if (headerValue && fingerprintShared.isValidFingerprintId(headerValue)) {
|
|
21
21
|
return headerValue;
|
|
22
22
|
}
|
|
23
|
-
// 2.
|
|
23
|
+
// 2. Read from cookie.
|
|
24
24
|
if (cookies) {
|
|
25
25
|
const cookieValue = cookies[fingerprintShared.FINGERPRINT_COOKIE_NAME];
|
|
26
26
|
if (cookieValue && fingerprintShared.isValidFingerprintId(cookieValue)) {
|
|
27
27
|
return cookieValue;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
// 3.
|
|
30
|
+
// 3. Read from query parameters.
|
|
31
31
|
if (query) {
|
|
32
32
|
const queryValue = query.fingerprint_id || query.fp_id;
|
|
33
33
|
if (queryValue && fingerprintShared.isValidFingerprintId(queryValue)) {
|
|
@@ -37,20 +37,20 @@ function extractFingerprintId(headers, cookies, query) {
|
|
|
37
37
|
return null;
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
40
|
+
* Generate a server-side fallback fingerprint ID.
|
|
41
|
+
* Used when the client cannot generate a fingerprint.
|
|
42
|
+
* Safe to use on the server.
|
|
43
43
|
*/
|
|
44
44
|
function generateServerFingerprintId() {
|
|
45
45
|
return `fp_server_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
48
|
+
* Extract fingerprint ID from a Next.js Request object.
|
|
49
|
+
* Convenience helper for Next.js API routes.
|
|
50
50
|
*/
|
|
51
51
|
function extractFingerprintFromNextRequest(request) {
|
|
52
52
|
const headers = request.headers;
|
|
53
|
-
//
|
|
53
|
+
// Try cookies by parsing the cookie header.
|
|
54
54
|
const cookieHeader = headers.get('cookie');
|
|
55
55
|
const cookies = {};
|
|
56
56
|
if (cookieHeader) {
|
|
@@ -61,7 +61,7 @@ function extractFingerprintFromNextRequest(request) {
|
|
|
61
61
|
}
|
|
62
62
|
});
|
|
63
63
|
}
|
|
64
|
-
//
|
|
64
|
+
// Try URL query parameters.
|
|
65
65
|
const url = new URL(request.url);
|
|
66
66
|
const query = {};
|
|
67
67
|
url.searchParams.forEach((value, key) => {
|
|
@@ -70,8 +70,8 @@ function extractFingerprintFromNextRequest(request) {
|
|
|
70
70
|
return extractFingerprintId(headers, cookies, query);
|
|
71
71
|
}
|
|
72
72
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
73
|
+
* Extract fingerprint ID from Next.js runtime headers/cookies stores.
|
|
74
|
+
* Reusable in App Router server components and Server Actions.
|
|
75
75
|
*/
|
|
76
76
|
function extractFingerprintFromNextStores(params) {
|
|
77
77
|
const cookieMap = params.cookies
|