trezy/firebase-system-update

View on GitHub
src/helpers/Cookies.js

Summary

Maintainability
A
0 mins
Test Coverage
const COOKIE_OPTION_BOOLEANS = ['samesite', 'secure']
const COOKIE_OPTION_STRINGS = ['domain', 'expires', 'max-age', 'path']
const RESERVED_COOKIE_NAMES = [
    ...COOKIE_OPTION_BOOLEANS,
    ...COOKIE_OPTION_STRINGS,
]
const REGEX_STRING = `.*?=(.*?)(?:;)((?:(?:(?:${COOKIE_OPTION_BOOLEANS.join('|')})|(?:(?:${COOKIE_OPTION_STRINGS.join('|')})=.*?))(?:;|$))*)`

let cookieString = null
let cookieJar = null

// If a `name` is passed, returns the value of that cookie. Otherwise, return
// the entire cookie jar.
export function get(name) {
    if (document.cookie !== cookieString) {
        updateCachedCookie()
    }

    if (name) {
        return cookieJar[name]
    }

    return cookieJar
}

export function remove(name) {
    const cookie = get(name)
    set(name, ';max-age=0;')
}

export function set(name, value, options = {}) {
    if (RESERVED_COOKIE_NAMES.includes(name)) {
        console.error(`COOKIE HAS NOT BEEN SET: ${name}. ${name} is reserved.`)
    }

    let cookieStringToSet = `${name}=${value}`

    Object.keys(options).forEach(key => {
        if (![...COOKIE_OPTION_STRINGS, 'maxAge'].includes(key)) {
            console.warn(`Unrecognized option set for cookie ${name}: ${key}`)
        }
    })

    if (options.maxAge) {
        cookieStringToSet += `;max-age=${options.maxAge}`
    }

    COOKIE_OPTION_STRINGS.forEach(key => {
        if (options[key]) {
            cookieStringToSet += `;${key}=${options[key]}`
        }
    })

    document.cookie = cookieStringToSet
}

function updateCachedCookie() {
    cookieString = document.cookie

    // Trim spaces around semicolons and equals
    cookieString = cookieString
        .replace(/\s*;\s*/g, ';')
        .replace(/\s*\=\s*/g, '=')

    const cookies = [...document.cookie.matchAll(new RegExp(REGEX_STRING, 'g'))]

    cookieJar = cookies.reduce((accumulator, cookieArray) => {
        const [,
            name,
            value,
            optionsString = '',
        ] = cookieArray

        const options = optionsString
            .replace(/;$/, '')
            .split(';')
            .reduce((optionsAccumulator, optionString) => {
                const [key, value] = optionString.split('=')

                optionsAccumulator[key] = value ?? true

                return optionsAccumulator
            }, {})

        accumulator[name] = {
            options,
            value,
        }

        return accumulator
    }, {})
}