{"version":3,"sources":["../../src/helpers/tracing.ts","../../src/helpers/sender.ts","../../src/helpers/embeddingContext.tsx","../../src/helpers/uuid.ts"],"sourcesContent":["import { parse as parseCookieString } from 'cookie'\n\nimport {\n    FINGERPRINT_ID_COOKIE_NAME,\n    getClientSideFingerprint,\n} from './sender'\nimport { generateUUIDv4 } from './uuid'\n\nexport type TracingOptions = {\n    serviceUrl: string\n    codeVersion: string\n    target?: string\n    previousHeaders?: Record<string, string>\n}\n\nconst SSR_DEFAULT_FINGERPRINT = 'webAppSSR'\nconst COOKIE_HEADER_NAME = 'cookie'\nconst REMOTE_APP_HEADER_NAME = 'x-remote-app'\nconst REMOTE_VERSION_HEADER_NAME = 'x-remote-version'\nconst REMOTE_CLIENT_HEADER_NAME = 'x-remote-client'\nconst REMOTE_ENV_HEADER_NAME = 'x-remote-env'\nconst TARGET_HEADER_NAME = 'x-target'\nconst START_REQUEST_ID_HEADER_NAME = 'x-start-request-id'\nconst PARENT_REQUEST_ID_HEADER_NAME = 'x-parent-request-id'\n\nfunction generateRequestId () {\n    return `BR${generateUUIDv4().replaceAll('-', '')}`\n}\n\nexport function getAppTracingHeaders (options: TracingOptions) {\n    const reqId = generateRequestId()\n\n    const headers: Record<string, string> = {\n        ...options.previousHeaders,\n        [REMOTE_APP_HEADER_NAME]: options.serviceUrl,\n        [REMOTE_VERSION_HEADER_NAME]: options.codeVersion,\n        [PARENT_REQUEST_ID_HEADER_NAME]: reqId,\n        [START_REQUEST_ID_HEADER_NAME]: reqId,\n    }\n\n    if (options.target) {\n        headers[TARGET_HEADER_NAME] = options.target\n    }\n\n    headers[REMOTE_ENV_HEADER_NAME] = typeof document === 'undefined' ? 'SSR' : 'CSR'\n\n    // NOTE: CSR\n    if (typeof document !== 'undefined' && document.cookie) {\n        headers[REMOTE_CLIENT_HEADER_NAME] = getClientSideFingerprint()\n    } else if (headers[COOKIE_HEADER_NAME]) {\n        const ssrCookies = parseCookieString(headers[COOKIE_HEADER_NAME])\n\n        headers[REMOTE_CLIENT_HEADER_NAME] = ssrCookies[FINGERPRINT_ID_COOKIE_NAME] || SSR_DEFAULT_FINGERPRINT\n    }\n\n    return headers\n}","import { getCookie, setCookie } from 'cookies-next'\n\nimport { getEmbeddingContext } from './embeddingContext'\nimport { generateUUIDv4 } from './uuid'\n\ntype SenderInfo = {\n    dv: number\n    fingerprint: string\n}\n\n/** Name of the cookie in which the fingerprint will be stored */\nexport const FINGERPRINT_ID_COOKIE_NAME = 'fingerprint'\n/** Default fingerprint length */\nexport const FINGERPRINT_ID_LENGTH = 32\n/** Fingerprint cookie should be persistent, so we are giving it a big maxAge */\nconst VERY_LONG_MAX_AGE_IN_SECONDS = Math.pow(2, 31) - 1 // Around 68 years in seconds\n\nfunction makeId (length: number): string {\n    const croppedLength = Math.min(length, 32)\n\n    return generateUUIDv4().replaceAll('-', '').substring(0, croppedLength)\n}\n\nexport function generateFingerprint (): string {\n    return makeId(FINGERPRINT_ID_LENGTH)\n}\n\n/**\n * Creates a device fingerprint in the browser environment\n * that can be used to send mutations in open-condo applications,\n * uses cookies for storage between sessions.\n * Mostly used to generate the sender field in getClientSideSenderInfo.\n * So consider using it instead\n */\nexport function getClientSideFingerprint (): string {\n    // NOTE: if we're inside another application, use its device id as fingerprint, but not persist it in cookie\n    const embeddingContext = getEmbeddingContext()\n    if (embeddingContext) {\n        return embeddingContext.ctx.device.id\n    }\n\n    let fingerprint = getCookie(FINGERPRINT_ID_COOKIE_NAME)\n    if (!fingerprint) {\n        fingerprint = generateFingerprint()\n    }\n    // Since 2022 browsers maintain cookie for 400 days at max, so let's update cookie expiration time\n    setCookie(FINGERPRINT_ID_COOKIE_NAME, fingerprint, {\n        maxAge: VERY_LONG_MAX_AGE_IN_SECONDS, // no \"maxAge\" or \"expires\" means that cookie clears when session ends (f.e. when browser closes)\n    })\n\n    return fingerprint\n}\n\n/**\n * Creates a device fingerprint in the browser environment\n * that can be used to send mutations in open-condo applications.\n * Uses cookies for storage between sessions\n * @example\n *  submitReadingsMutation({\n *     variables: {\n *         data: {\n *             ...values,\n *             dv: 1,\n *             sender: getClientSideSenderInfo(),\n *             meter: { connect: { id: meter.id } },\n *             source: { connect: { id: METER_READING_MOBILE_APP_SOURCE_ID } },\n *         },\n *     },\n * })\n */\nexport function getClientSideSenderInfo (): SenderInfo {\n    return {\n        dv: 1,\n        fingerprint: getClientSideFingerprint(),\n    }\n}\n","import { deleteCookie, getCookie, setCookie } from 'cookies-next'\nimport React, { useEffect, useMemo, useState, createContext, useContext } from 'react'\nimport { z } from 'zod'\n\nimport { generateUUIDv4 } from './uuid'\n\nimport type { AppType, Optional } from './common/types'\nimport type { IncomingMessage, ServerResponse } from 'http'\n\nconst EMBEDDING_CONTEXT_COOKIE_NAME = 'embeddingContext'\nconst EMBEDDING_CONTEXT_QUERY_PARAM = 'embeddingContext'\nconst EMBEDDING_CONTEXT_PRIMARY_TAB_SESSION_STORAGE_KEY = 'isEmbeddingContextProvider'\nconst EMBEDDING_CONTEXT_PROP_NAME = '__EMBEDDING_CONTEXT__'\nconst EMBEDDING_CONTEXT_CLEANUP_POLLING_TIMEOUT_IN_MS = 2_000\n\nconst EMBEDDING_CONTEXT_SCHEMA = z.strictObject({\n    dv: z.literal(1),\n    app: z.strictObject({\n        id: z.string(),\n        version: z.string().optional(),\n        build: z.string().optional(),\n    }),\n    platform: z.enum(['iOS', 'Android', 'web']),\n    os: z.strictObject({\n        name: z.string(),\n        version: z.string().optional(),\n    }).optional(),\n    device: z.strictObject({\n        id: z.string(),\n    }),\n})\n\nconst EMBEDDING_CONTEXT_WITH_SOURCE_SCHEMA = z.strictObject({\n    ctx: EMBEDDING_CONTEXT_SCHEMA,\n    source: z.enum(['query', 'cookie']),\n})\n\nconst IS_PRIMARY_ALIVE_MESSAGE_SCHEMA = z.object({\n    type: z.literal('EmbeddingContextPrimaryPolling'),\n    data: z.strictObject({\n        requestId: z.string(),\n    }),\n})\n\nconst IS_PRIMARY_ALIVE_RESPONSE_SCHEMA = z.object({\n    type: z.literal('EmbeddingContextPrimaryPollingResult'),\n    data: z.strictObject({\n        requestId: z.string(),\n        isPrimary: z.boolean(),\n    }),\n})\n\nexport type EmbeddingContext = z.infer<typeof EMBEDDING_CONTEXT_SCHEMA>\ntype EmbeddingContextWithSource = z.infer<typeof EMBEDDING_CONTEXT_WITH_SOURCE_SCHEMA>\ntype IsPrimaryAliveMessage = z.infer<typeof IS_PRIMARY_ALIVE_MESSAGE_SCHEMA>\ntype IsPrimaryAliveResponse = z.infer<typeof IS_PRIMARY_ALIVE_RESPONSE_SCHEMA>\n\nconst ReactEmbeddingContext = createContext<EmbeddingContext | null>(null)\n\nexport function useEmbeddingContext (): EmbeddingContext | null {\n    return useContext(ReactEmbeddingContext)\n}\n\nfunction b64toContext (b64: string): EmbeddingContext | null {\n    try {\n        const bytes = Uint8Array.from(atob(b64), c => c.charCodeAt(0))\n        const decodedUTFString = new TextDecoder().decode(bytes)\n        const parsedCtx = JSON.parse(decodedUTFString)\n        return EMBEDDING_CONTEXT_SCHEMA.parse(parsedCtx)\n    } catch {\n        return null\n    }\n}\n\nfunction contextToB64 (ctx: EmbeddingContext): string {\n    const stringCtx = JSON.stringify(ctx)\n    const bytes = new TextEncoder().encode(stringCtx)\n    return btoa(String.fromCharCode(...bytes))\n}\n\nexport function getEmbeddingContext (req?: Optional<IncomingMessage>, res?: Optional<ServerResponse>): EmbeddingContextWithSource | null {\n    // NOTE: context can be found in query for primary tab\n    try {\n        const queryParamValue = req\n            ? new URL(req.url ?? '/', 'https://_').searchParams.get(EMBEDDING_CONTEXT_QUERY_PARAM)\n            : new URLSearchParams(window.location.search).get(EMBEDDING_CONTEXT_QUERY_PARAM)\n        if (queryParamValue) {\n            const ctx = b64toContext(decodeURIComponent(queryParamValue))\n            if (ctx) return { ctx, source: 'query' }\n        }\n    } catch {\n        // NOTE: decodeURIComponent might throw on invalid input, ignore it as non-valid query-param\n    }\n\n    // NOTE: context can be found in cookie for secondary tabs\n    const cookieValue = getCookie(EMBEDDING_CONTEXT_COOKIE_NAME, { req, res })\n    if (cookieValue) {\n        const ctx = b64toContext(cookieValue)\n        if (ctx) return { ctx, source: 'cookie' }\n    }\n\n    return null\n}\n\nexport function withEmbeddingContext<\n    PropsType extends Record<string, unknown>,\n    ComponentType,\n    RouterType,\n> (App: AppType<PropsType, ComponentType, RouterType>): AppType<PropsType, ComponentType, RouterType> {\n    const WithEmbeddingContext: AppType<PropsType, ComponentType, RouterType> = (props) => {\n        const { pageProps } = props\n\n        const propsContextWithSource = useMemo(() => {\n            const { success, data } = EMBEDDING_CONTEXT_WITH_SOURCE_SCHEMA.safeParse(pageProps[EMBEDDING_CONTEXT_PROP_NAME])\n            if (!success) return null\n            return data\n        }, [pageProps])\n\n        const [embeddingContext, setEmbeddingContext] = useState<EmbeddingContext | null>(propsContextWithSource?.ctx ?? null)\n        const [isPrimaryTab, setIsPrimaryTab] = useState<boolean | null>(propsContextWithSource?.source === 'query' ? true : null)\n        const [bcChannel, setBCChannel] = useState<BroadcastChannel | null>(null)\n\n        useEffect(() => {\n            // NOTE: if primary tab, save it in session storage, so it won't be lost on user navigation\n            if (isPrimaryTab === true && typeof window !== 'undefined') {\n                window.sessionStorage.setItem(EMBEDDING_CONTEXT_PRIMARY_TAB_SESSION_STORAGE_KEY, 'true')\n            }\n            // NOTE: restore primary tab status if it was lost on navigation\n            if (isPrimaryTab === null && typeof window !== 'undefined') {\n                setIsPrimaryTab(window.sessionStorage.getItem(EMBEDDING_CONTEXT_PRIMARY_TAB_SESSION_STORAGE_KEY) === 'true')\n            }\n        }, [isPrimaryTab])\n\n        useEffect(() => {\n            if (typeof window === 'undefined' || !('BroadcastChannel' in window)) return\n\n            const bc = new BroadcastChannel('embeddingContext')\n            setBCChannel(bc)\n\n            return () => {\n                bc.close()\n                setBCChannel(null)\n            }\n        }, [])\n\n        // NOTE: Embedding context is shared between tabs by browser technology (cookies)\n        // so each new page can obtain it in initial props in SSR and CSR\n        // The problem is cookie might not be cleaned up on tab close, so we use 2 tricks:\n        // 1. save primary tab status in session storage, so it won't be lost on user navigation\n        // 2. use BroadcastChannel to poll if primary tab is still alive, if not, clean up cookie\n        useEffect(() => {\n            if (isPrimaryTab === null || !bcChannel) return\n\n            if (isPrimaryTab) {\n                const primaryListener = (e: MessageEvent) => {\n                    const { success, data } = IS_PRIMARY_ALIVE_MESSAGE_SCHEMA.safeParse(e.data)\n                    if (!success || !data?.data?.requestId) return\n\n                    const response: IsPrimaryAliveResponse = {\n                        type: 'EmbeddingContextPrimaryPollingResult',\n                        data: {\n                            isPrimary: true,\n                            requestId: data.data.requestId,\n                        },\n                    }\n\n                    bcChannel.postMessage(response)\n                }\n\n                bcChannel.addEventListener('message', primaryListener)\n\n                return () => {\n                    bcChannel.removeEventListener('message', primaryListener)\n                }\n            }\n\n            const requestId = generateUUIDv4()\n            const timeout = setTimeout(() => {\n                deleteCookie(EMBEDDING_CONTEXT_COOKIE_NAME)\n                setEmbeddingContext(null)\n                setIsPrimaryTab(false)\n            }, EMBEDDING_CONTEXT_CLEANUP_POLLING_TIMEOUT_IN_MS)\n\n            const secondaryListener = (e: MessageEvent) => {\n                const { success, data } = IS_PRIMARY_ALIVE_RESPONSE_SCHEMA.safeParse(e.data)\n                if (!success || data?.data.requestId !== requestId) return\n\n                clearTimeout(timeout)\n            }\n\n            bcChannel.addEventListener('message', secondaryListener)\n\n            const pollMessage: IsPrimaryAliveMessage = {\n                type: 'EmbeddingContextPrimaryPolling',\n                data: {\n                    requestId,\n                },\n            }\n            bcChannel.postMessage(pollMessage)\n\n            return () => {\n                bcChannel.removeEventListener('message', secondaryListener)\n                clearTimeout(timeout)\n            }\n\n        }, [bcChannel, isPrimaryTab])\n\n        return (\n            <ReactEmbeddingContext.Provider value={embeddingContext}>\n                <App {...props} />\n            </ReactEmbeddingContext.Provider>\n        )\n    }\n\n    const appGetInitialProps = App.getInitialProps\n    if (appGetInitialProps) {\n        WithEmbeddingContext.getInitialProps = async function (context) {\n            const appProps = await appGetInitialProps(context)\n            const { ctx } = context\n            const embeddingContextWithSource = getEmbeddingContext(ctx.req, ctx.res)\n            if (embeddingContextWithSource && embeddingContextWithSource.source === 'query') {\n                // Save context in cookie for new tabs\n                setCookie(EMBEDDING_CONTEXT_COOKIE_NAME, contextToB64(embeddingContextWithSource.ctx), {\n                    req: ctx.req,\n                    res: ctx.res,\n                })\n            }\n\n            return {\n                ...appProps,\n                pageProps: {\n                    ...appProps.pageProps,\n                    [EMBEDDING_CONTEXT_PROP_NAME]: embeddingContextWithSource,\n                },\n            }\n        }\n    }\n\n    return WithEmbeddingContext\n}","import { randomBytes } from 'crypto'\n\n/**\n * Generates v4 UUIDs in both browser and Node environments\n * @example\n * const uuid = generateUUIDv4()\n */\nexport function generateUUIDv4 (): string {\n    let randomValues: Uint8Array\n\n    if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n        // Browser or Node.js (if Node 19+ supports crypto.randomUUID)\n        return crypto.randomUUID()\n    } else if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) {\n        // Browser environment\n        randomValues = new Uint8Array(16)\n        window.crypto.getRandomValues(randomValues)\n    } else {\n        // Node.js environment\n        randomValues = randomBytes(16)\n    }\n\n    // Setting the version (4) and variant (RFC4122)\n    randomValues[6] = (randomValues[6] & 0x0f) | 0x40 // version 4\n    randomValues[8] = (randomValues[8] & 0x3f) | 0x80 // variant\n\n    return [...randomValues]\n        .map((value, index) => {\n            const hex = value.toString(16).padStart(2, '0')\n            if (index === 4 || index === 6 || index === 8 || index === 10) {\n                return `-${hex}`\n            }\n            return hex\n        })\n        .join('')\n}\n"],"mappings":";AAAA,SAAS,SAAS,yBAAyB;;;ACA3C,SAAS,aAAAA,YAAW,aAAAC,kBAAiB;;;ACArC,SAAS,cAAc,WAAW,iBAAiB;AACnD,OAAO,SAAS,WAAW,SAAS,UAAU,eAAe,kBAAkB;AAC/E,SAAS,SAAS;;;ACFlB,SAAS,mBAAmB;AAOrB,SAAS,iBAA0B;AACtC,MAAI;AAEJ,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,YAAY;AAE1E,WAAO,OAAO,WAAW;AAAA,EAC7B,WAAW,OAAO,WAAW,eAAe,OAAO,UAAU,OAAO,OAAO,iBAAiB;AAExF,mBAAe,IAAI,WAAW,EAAE;AAChC,WAAO,OAAO,gBAAgB,YAAY;AAAA,EAC9C,OAAO;AAEH,mBAAe,YAAY,EAAE;AAAA,EACjC;AAGA,eAAa,CAAC,IAAK,aAAa,CAAC,IAAI,KAAQ;AAC7C,eAAa,CAAC,IAAK,aAAa,CAAC,IAAI,KAAQ;AAE7C,SAAO,CAAC,GAAG,YAAY,EAClB,IAAI,CAAC,OAAO,UAAU;AACnB,UAAM,MAAM,MAAM,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAC9C,QAAI,UAAU,KAAK,UAAU,KAAK,UAAU,KAAK,UAAU,IAAI;AAC3D,aAAO,IAAI,GAAG;AAAA,IAClB;AACA,WAAO;AAAA,EACX,CAAC,EACA,KAAK,EAAE;AAChB;;;AD1BA,IAAM,gCAAgC;AACtC,IAAM,gCAAgC;AAKtC,IAAM,2BAA2B,EAAE,aAAa;AAAA,EAC5C,IAAI,EAAE,QAAQ,CAAC;AAAA,EACf,KAAK,EAAE,aAAa;AAAA,IAChB,IAAI,EAAE,OAAO;AAAA,IACb,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,IAC7B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,CAAC;AAAA,EACD,UAAU,EAAE,KAAK,CAAC,OAAO,WAAW,KAAK,CAAC;AAAA,EAC1C,IAAI,EAAE,aAAa;AAAA,IACf,MAAM,EAAE,OAAO;AAAA,IACf,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,CAAC,EAAE,SAAS;AAAA,EACZ,QAAQ,EAAE,aAAa;AAAA,IACnB,IAAI,EAAE,OAAO;AAAA,EACjB,CAAC;AACL,CAAC;AAED,IAAM,uCAAuC,EAAE,aAAa;AAAA,EACxD,KAAK;AAAA,EACL,QAAQ,EAAE,KAAK,CAAC,SAAS,QAAQ,CAAC;AACtC,CAAC;AAED,IAAM,kCAAkC,EAAE,OAAO;AAAA,EAC7C,MAAM,EAAE,QAAQ,gCAAgC;AAAA,EAChD,MAAM,EAAE,aAAa;AAAA,IACjB,WAAW,EAAE,OAAO;AAAA,EACxB,CAAC;AACL,CAAC;AAED,IAAM,mCAAmC,EAAE,OAAO;AAAA,EAC9C,MAAM,EAAE,QAAQ,sCAAsC;AAAA,EACtD,MAAM,EAAE,aAAa;AAAA,IACjB,WAAW,EAAE,OAAO;AAAA,IACpB,WAAW,EAAE,QAAQ;AAAA,EACzB,CAAC;AACL,CAAC;AAOD,IAAM,wBAAwB,cAAuC,IAAI;AAMzE,SAAS,aAAc,KAAsC;AACzD,MAAI;AACA,UAAM,QAAQ,WAAW,KAAK,KAAK,GAAG,GAAG,OAAK,EAAE,WAAW,CAAC,CAAC;AAC7D,UAAM,mBAAmB,IAAI,YAAY,EAAE,OAAO,KAAK;AACvD,UAAM,YAAY,KAAK,MAAM,gBAAgB;AAC7C,WAAO,yBAAyB,MAAM,SAAS;AAAA,EACnD,QAAQ;AACJ,WAAO;AAAA,EACX;AACJ;AAQO,SAAS,oBAAqB,KAAiC,KAAmE;AAErI,MAAI;AACA,UAAM,kBAAkB,MAClB,IAAI,IAAI,IAAI,OAAO,KAAK,WAAW,EAAE,aAAa,IAAI,6BAA6B,IACnF,IAAI,gBAAgB,OAAO,SAAS,MAAM,EAAE,IAAI,6BAA6B;AACnF,QAAI,iBAAiB;AACjB,YAAM,MAAM,aAAa,mBAAmB,eAAe,CAAC;AAC5D,UAAI,IAAK,QAAO,EAAE,KAAK,QAAQ,QAAQ;AAAA,IAC3C;AAAA,EACJ,QAAQ;AAAA,EAER;AAGA,QAAM,cAAc,UAAU,+BAA+B,EAAE,KAAK,IAAI,CAAC;AACzE,MAAI,aAAa;AACb,UAAM,MAAM,aAAa,WAAW;AACpC,QAAI,IAAK,QAAO,EAAE,KAAK,QAAQ,SAAS;AAAA,EAC5C;AAEA,SAAO;AACX;;;AD3FO,IAAM,6BAA6B;AAEnC,IAAM,wBAAwB;AAErC,IAAM,+BAA+B,KAAK,IAAI,GAAG,EAAE,IAAI;AAEvD,SAAS,OAAQ,QAAwB;AACrC,QAAM,gBAAgB,KAAK,IAAI,QAAQ,EAAE;AAEzC,SAAO,eAAe,EAAE,WAAW,KAAK,EAAE,EAAE,UAAU,GAAG,aAAa;AAC1E;AAEO,SAAS,sBAA+B;AAC3C,SAAO,OAAO,qBAAqB;AACvC;AASO,SAAS,2BAAoC;AAEhD,QAAM,mBAAmB,oBAAoB;AAC7C,MAAI,kBAAkB;AAClB,WAAO,iBAAiB,IAAI,OAAO;AAAA,EACvC;AAEA,MAAI,cAAcC,WAAU,0BAA0B;AACtD,MAAI,CAAC,aAAa;AACd,kBAAc,oBAAoB;AAAA,EACtC;AAEA,EAAAC,WAAU,4BAA4B,aAAa;AAAA,IAC/C,QAAQ;AAAA;AAAA,EACZ,CAAC;AAED,SAAO;AACX;;;ADpCA,IAAM,0BAA0B;AAChC,IAAM,qBAAqB;AAC3B,IAAM,yBAAyB;AAC/B,IAAM,6BAA6B;AACnC,IAAM,4BAA4B;AAClC,IAAM,yBAAyB;AAC/B,IAAM,qBAAqB;AAC3B,IAAM,+BAA+B;AACrC,IAAM,gCAAgC;AAEtC,SAAS,oBAAqB;AAC1B,SAAO,KAAK,eAAe,EAAE,WAAW,KAAK,EAAE,CAAC;AACpD;AAEO,SAAS,qBAAsB,SAAyB;AAC3D,QAAM,QAAQ,kBAAkB;AAEhC,QAAM,UAAkC;AAAA,IACpC,GAAG,QAAQ;AAAA,IACX,CAAC,sBAAsB,GAAG,QAAQ;AAAA,IAClC,CAAC,0BAA0B,GAAG,QAAQ;AAAA,IACtC,CAAC,6BAA6B,GAAG;AAAA,IACjC,CAAC,4BAA4B,GAAG;AAAA,EACpC;AAEA,MAAI,QAAQ,QAAQ;AAChB,YAAQ,kBAAkB,IAAI,QAAQ;AAAA,EAC1C;AAEA,UAAQ,sBAAsB,IAAI,OAAO,aAAa,cAAc,QAAQ;AAG5E,MAAI,OAAO,aAAa,eAAe,SAAS,QAAQ;AACpD,YAAQ,yBAAyB,IAAI,yBAAyB;AAAA,EAClE,WAAW,QAAQ,kBAAkB,GAAG;AACpC,UAAM,aAAa,kBAAkB,QAAQ,kBAAkB,CAAC;AAEhE,YAAQ,yBAAyB,IAAI,WAAW,0BAA0B,KAAK;AAAA,EACnF;AAEA,SAAO;AACX;","names":["getCookie","setCookie","getCookie","setCookie"]}