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
text/typescript
/* 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)
}
}