UNPKG

@nasriya/hypercloud

Version:

Nasriya HyperCloud is a lightweight Node.js HTTP2 framework.

165 lines (164 loc) 7.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const ms_1 = __importDefault(require("ms")); class Cookies { #_response; constructor(res) { this.#_response = res; } /** * Create a cookie on the browser * * **Examples** * * ```js * server.use('*', (request, response) => { * // Create a session until the tab is closed * response.cookies.create('session_id', 'session_jwt', { * httpOnly: true, * secure: true, * priority: 'High' * }) * }) * ``` * @param {string} name The name of the cookie * @param {string} value The value of the cookie * @param {CookieOptions} [options] Customize the cookie with options * @returns {HyperCloudResponse} */ create(name, value, options) { const cookie = []; const ONEYEAR = 31_536_000_000; // in ms try { if (typeof name !== 'string') { throw new TypeError(`The cookie name should be a string. Instead got ${typeof name}`); } if (name.length === 0) { throw `The cookie name cannot be empty`; } if (typeof value !== 'string') { throw new TypeError(`The cookie value should be a string. Instead got ${typeof value}`); } if (value.length === 0) { throw `The cookie value cannot be empty`; } cookie.push(`${name}=${value}`); if (options && 'secure' in options) { if (typeof options.secure !== 'boolean') { throw new TypeError(`The "secure" option expects a boolean value. Instead got ${typeof options.secure}`); } if (options.secure === true) { cookie.push('Secure'); } } if (options && 'httpOnly' in options) { if (typeof options.httpOnly !== 'boolean') { throw new TypeError(`The "httpOnly" option expects a boolean value. Instead got ${typeof options.httpOnly}`); } if (options.httpOnly === true) { cookie.push('HttpOnly'); } } if (options && 'maxAge' in options) { if (!(typeof options.maxAge === 'number' || typeof options.maxAge === 'string')) { throw new TypeError(`The "maxAge" value should either be a number of milliseconds or a string.`); } if (typeof options.maxAge === 'string') { if (options.maxAge.length === 0) { throw new SyntaxError(`The maxAge string value cannot be empty`); } const value = (0, ms_1.default)(options.maxAge); if (typeof value !== 'number') { throw new SyntaxError(`${options.maxAge} is not a valid maxAge value`); } options.maxAge = value; } if (options.maxAge < 0) { throw new RangeError(`The maxAge cannot be a negative value`); } if (options.maxAge > ONEYEAR) { throw new RangeError(`The maxAge value should not be more than one year`); } cookie.push(`Max-Age=${options.maxAge}`); } if (options && 'domain' in options) { if (typeof options.domain !== 'string') { throw new TypeError(`The "domain" value should be a string. Instead got ${typeof options.domain}`); } cookie.push(`Domain=${options.domain}`); } if (options && 'path' in options) { if (typeof options.path !== 'string') { throw new TypeError(`The "path" option is expecting a string value, but instead got ${typeof options.path}`); } cookie.push(`Path=${options.path}`); } if (options && 'expires' in options) { if (!(options.expires instanceof Date)) { throw new TypeError(`The "expires" option is expecting a Date instance, but instead got ${typeof options.expires}`); } const now = new Date(); if (now > options.expires) { throw `The "Expires" value cannot be in the past`; } cookie.push(`Expires=${options.expires.toUTCString()}`); } if (options && 'sameSite' in options) { if (typeof options.sameSite !== 'string') { throw new TypeError(`The "sameSite" option is expecting a string value, but instead got ${typeof options.sameSite}`); } const x = ['Strict', 'Lax', 'None']; if (!x.includes(options.sameSite)) { throw new RangeError(`The ${options.sameSite} is not a valid "sameSite". Valid options are: ${x.join(', ')}.`); } if (options.sameSite === 'None') { if (options?.secure !== true) { throw new SyntaxError(`The "sameSite" value cannot be set to "None" unless you also set the "secure" option to true`); } } cookie.push(`SameSite=${options.sameSite}`); } if (options && 'priority' in options) { if (typeof options.priority !== 'string') { throw new TypeError(`The "priority" option can only be a string, instead got ${typeof options.priority}`); } const x = ['High', 'Medium', 'Low']; if (!x.includes(options.priority)) { throw new RangeError(`The provided "priority" value (${options.priority}) is not a valid priority option. Valid options are: ${x.join(', ')}.`); } cookie.push(`Priority=${options.priority}`); } this.#_response.setHeader('Set-Cookie', cookie.join('; ')); return this.#_response; } catch (error) { if (typeof error === 'string') { error = `Unable to create cookie: ${error}`; } if (error instanceof Error && typeof error?.message === 'string') { error.message = `Unable to create cookie: ${error.message}`; } throw error; } } /** * Instruct the browser to delete a cookie * @param {string} name The name of the cookie to delete * @returns {HyperCloudResponse} */ delete(name) { if (typeof name !== 'string' || name?.length === 0) { throw `(${name}) is not a valid cookie name`; } this.#_response.setHeader('Set-Cookie', `${name}=deleted; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/`); return this.#_response; } /** * Get a list of all the created cookies */ get list() { return this.#_response.getHeaders()['set-cookie']; } } exports.default = Cookies;