utils.ts90 lines · main
1export function getCookie(name: string): string | undefined {
2 if (typeof document === 'undefined') return undefined
3 const escapedName = name.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
4 const match = document.cookie.match(new RegExp(`(^| )${escapedName}=([^;]+)`))
5 return match ? decodeURIComponent(match[2]) : undefined
6}
7
8export function setCookie(name: string, value: string, path: string = '/') {
9 if (typeof document === 'undefined') return
10 document.cookie = `${name}=${encodeURIComponent(value)}; path=${path}`
11}
12
13export function deleteCookie(name: string) {
14 if (typeof document === 'undefined') return
15 document.cookie = `${name}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`
16}
17
18export function safeJsonParse<T>(value: string | undefined, fallback: T, context?: string): T {
19 if (!value) return fallback
20 try {
21 return JSON.parse(value) as T
22 } catch (error) {
23 if (process.env.NODE_ENV === 'development') {
24 console.warn(`[DevToolbar] Failed to parse JSON${context ? ` for ${context}` : ''}:`, error)
25 }
26 return fallback
27 }
28}
29
30export const PH_ORIGINALS_KEY = 'devToolbarFlagOriginals:posthog'
31export const CC_ORIGINALS_KEY = 'devToolbarFlagOriginals:configcat'
32
33export function readOriginals(
34 key: typeof PH_ORIGINALS_KEY | typeof CC_ORIGINALS_KEY
35): Record<string, unknown> {
36 if (typeof window === 'undefined') return {}
37 try {
38 const stored = window.localStorage.getItem(key)
39 return stored ? JSON.parse(stored) : {}
40 } catch (error) {
41 if (process.env.NODE_ENV === 'development') {
42 console.warn(`[DevToolbar] Failed to read originals from ${key}:`, error)
43 }
44 return {}
45 }
46}
47
48export function writeOriginals(
49 key: typeof PH_ORIGINALS_KEY | typeof CC_ORIGINALS_KEY,
50 value: Record<string, unknown>
51) {
52 if (typeof window === 'undefined') return
53 if (Object.keys(value).length === 0) {
54 window.localStorage.removeItem(key)
55 return
56 }
57 window.localStorage.setItem(key, JSON.stringify(value))
58}
59
60export function valuesAreEqual(a: unknown, b: unknown): boolean {
61 if (a === b) return true
62 if (a == null || b == null) return false
63 if (typeof a === 'number' || typeof b === 'number') {
64 const numA = Number(a)
65 const numB = Number(b)
66 if (Number.isNaN(numA) || Number.isNaN(numB)) return false
67 return numA === numB
68 }
69 if (typeof a === 'boolean' || typeof b === 'boolean') {
70 return a === b
71 }
72 return String(a) === String(b)
73}
74
75export function parseOverrideValue(value: unknown, original: unknown): unknown {
76 if (typeof original === 'number') {
77 const parsed = Number(value)
78 return Number.isNaN(parsed) ? original : parsed
79 }
80 if (typeof original === 'boolean') {
81 if (typeof value === 'string') {
82 return value.toLowerCase() === 'true'
83 }
84 return Boolean(value)
85 }
86 if (typeof original === 'string') {
87 return String(value)
88 }
89 return value
90}