UNPKG

iopa

Version:

API-first, Internet of Things (IoT) stack for Typescript, official implementation of the Internet Open Protocols Alliance (IOPA) reference pattern

105 lines (97 loc) 2.63 kB
/* eslint-disable @rushstack/typedef-var */ import { EpochOrFromNow, ICookieOptions, TimeString } from '@iopa/types' const mins = ['m', 'min', 'mins', 'minute', 'minutes'] const hrs = ['h', 'hr', 'hrs', 'hour', 'hours'] const days = ['d', 'day', 'days'] const weeks = ['w', 'wk', 'wks', 'week', 'weeks'] const timeUnits: string[][] = [mins, hrs, days, weeks] export function getSeconds(timeString: TimeString): number { const [val, unit] = timeString.split(' ') const time = Number.parseInt(val, 10) if (Number.isNaN(time)) { return 0 } const multipliers: number[] = [60, 3600, 86400, 604800] for (let i = 0; i < timeUnits.length; i++) { if (timeUnits[i].includes(unit)) { return time * multipliers[i] } } return 0 } function getMaxAge(age: TimeString): string { return `Max-Age=${getSeconds(age)}` } function getExpires(date: EpochOrFromNow): string { if (typeof date === 'number') { return `Expires=${new Date(date).toUTCString()}` } return `Expires=${new Date( Date.now() + getSeconds(date) * 1000 ).toUTCString()}` } function mapOptionsToString({ options }: { options: { expires?: EpochOrFromNow maxAge?: TimeString domain?: string path?: string secure?: boolean httpOnly?: boolean sameSite?: 'Strict' | 'Lax' | 'None' } }): string { const { expires, maxAge, domain, path, secure, httpOnly, sameSite } = options let opt = '' if (expires) { opt += ` ${getExpires(expires)};` } if (maxAge) { opt += ` ${getMaxAge(maxAge)};` } if (domain) { opt += ` Domain=${domain};` } if (path) { opt += ` Path=${path};` } if (secure) { opt += ' Secure;' } if (httpOnly) { opt += ' HttpOnly;' } if (sameSite) { opt += ` SameSite=${sameSite};` } return opt } // mapOptionsToString({ httpOnly: true, secure: true, sameSite: 'Lax', maxAge: '7 days', expires: '52 wk', path: '/auth', domain: 'site.com' }); // ' Expires=Tue, 20 Jan 1970 00:54:53 GMT; Max-Age=604800; Domain=site.com; Path=/auth; Secure; HttpOnly; SameSite=Lax;'; export default { set: ( headers: Headers, name: string, value: string, options?: ICookieOptions ) => { let cookie = `${name}=${value};` if (options) { cookie += mapOptionsToString({ options }) } headers.append('set-cookie', cookie) }, clear: ( headers: Headers, name: string, options?: Pick<ICookieOptions, 'domain' | 'path'> ) => { let cookie = `${name}=; ${getExpires(0)};` if (options) { cookie += mapOptionsToString({ options }) } headers.append('set-cookie', cookie) } }