|
8 | 8 | 'use strict'; |
9 | 9 |
|
10 | 10 | /** |
11 | | - * Module dependencies. |
| 11 | + * @import { CookieSerializeOptions } from "cookie" |
| 12 | + * @import { CookieOptions } from "./cookie-options" |
12 | 13 | */ |
13 | 14 |
|
14 | | -var cookie = require('cookie') |
15 | | -var deprecate = require('depd')('express-session') |
16 | | - |
17 | 15 | /** |
18 | | - * Initialize a new `Cookie` with the given `options`. |
19 | | - * |
20 | | - * @param {IncomingMessage} req |
21 | | - * @param {Object} options |
22 | | - * @api private |
| 16 | + * Cookie TODO: add description |
| 17 | + * @class |
| 18 | + * @implements CookieOptions |
23 | 19 | */ |
24 | 20 |
|
25 | | -var Cookie = module.exports = function Cookie(options) { |
26 | | - this.path = '/'; |
27 | | - this.maxAge = null; |
28 | | - this.httpOnly = true; |
29 | | - |
30 | | - if (options) { |
31 | | - if (typeof options !== 'object') { |
32 | | - throw new TypeError('argument options must be a object') |
33 | | - } |
| 21 | +class Cookie { |
| 22 | + /** @type {Date | undefined} @private */ |
| 23 | + _expires; |
| 24 | + /** @type {number | undefined} */ |
| 25 | + originalMaxAge; |
| 26 | + /** @type {boolean | undefined} */ |
| 27 | + partitioned; |
| 28 | + /** @type { "low" | "medium" | "high" | undefined} */ |
| 29 | + priority; |
| 30 | + /** @type {boolean | undefined} */ |
| 31 | + signed; // FIXME: how this is used?? |
| 32 | + /** @type {boolean} */ |
| 33 | + httpOnly; |
| 34 | + /** @type {string} */ |
| 35 | + path; |
| 36 | + /** @type {string | undefined} */ |
| 37 | + domain; |
| 38 | + /** @type {boolean | "auto" | undefined} */ |
| 39 | + secure; |
| 40 | + /** @type {((val: string) => string) | undefined} */ |
| 41 | + encode; |
| 42 | + /** @type {boolean | "lax" | "strict" | "none" | undefined} */ |
| 43 | + sameSite; |
34 | 44 |
|
35 | | - for (var key in options) { |
36 | | - if (key !== 'data') { |
37 | | - this[key] = options[key] |
| 45 | + /** |
| 46 | + * Initialize a new `Cookie` with the given `options`. |
| 47 | + * @param {CookieOptions} options |
| 48 | + * @private |
| 49 | + */ |
| 50 | + constructor(options) { |
| 51 | + if (options) { |
| 52 | + if (typeof options !== 'object') { |
| 53 | + throw new TypeError('argument options must be a object') |
38 | 54 | } |
| 55 | + console.log(`CookieOptions: ${JSON.stringify(options)}`) |
| 56 | + this.maxAge = options.maxAge |
| 57 | + this.originalMaxAge ??= options.maxAge // FIXME: rethink this |
| 58 | + |
| 59 | + this.partitioned = options.partitioned |
| 60 | + this.priority = options.priority |
| 61 | + this.secure = options.secure |
| 62 | + this.httpOnly = options.httpOnly ?? true |
| 63 | + this.domain = options.domain |
| 64 | + this.path = options.path || '/' |
| 65 | + this.sameSite = options.sameSite |
| 66 | + |
| 67 | + this.signed = options.signed // FIXME: how this is used?? |
| 68 | + this.encode = options.encode // FIXME: is this used / real ?? |
| 69 | + } else { |
| 70 | + this.path = '/' |
| 71 | + this.httpOnly = true |
39 | 72 | } |
40 | 73 | } |
41 | 74 |
|
42 | | - if (this.originalMaxAge === undefined || this.originalMaxAge === null) { |
43 | | - this.originalMaxAge = this.maxAge |
| 75 | + /** |
| 76 | + * Initialize a new `Cookie` using stored cookie data. |
| 77 | + * @param {CookieOptions & {expires?: string, originalMaxAge?: number}} data |
| 78 | + * @returns {Cookie} |
| 79 | + * @protected |
| 80 | + */ |
| 81 | + static fromJSON(data) { |
| 82 | + console.log(`Cookie.fromJSON: ${JSON.stringify(data)}`) |
| 83 | + const { expires, originalMaxAge, ...options } = data |
| 84 | + const cookie = new Cookie(options) |
| 85 | + cookie.expires = expires ? new Date(expires) : undefined |
| 86 | + cookie.originalMaxAge = originalMaxAge |
| 87 | + return cookie |
44 | 88 | } |
45 | | -}; |
46 | | - |
47 | | -/*! |
48 | | - * Prototype. |
49 | | - */ |
50 | | - |
51 | | -Cookie.prototype = { |
52 | 89 |
|
53 | 90 | /** |
54 | 91 | * Set expires `date`. |
55 | 92 | * |
56 | | - * @param {Date} date |
57 | | - * @api public |
| 93 | + * @param {Date | null | undefined} date |
| 94 | + * @public |
58 | 95 | */ |
59 | 96 |
|
60 | 97 | set expires(date) { |
61 | | - this._expires = date; |
62 | | - this.originalMaxAge = this.maxAge; |
63 | | - }, |
| 98 | + this._expires = date || undefined |
| 99 | + this.originalMaxAge = this.maxAge |
| 100 | + } |
64 | 101 |
|
65 | 102 | /** |
66 | | - * Get expires `date`. |
| 103 | + * Get expires `Date` object to be the value for the `Expires Set-Cookie` attribute. |
| 104 | + * By default, no expiration is set, and most clients will consider this a "non-persistent cookie" and will delete it on a condition like exiting a web browser application. |
67 | 105 | * |
68 | | - * @return {Date} |
69 | | - * @api public |
| 106 | + * @return {Date | undefined} |
| 107 | + * @public |
70 | 108 | */ |
71 | 109 |
|
72 | 110 | get expires() { |
73 | | - return this._expires; |
74 | | - }, |
| 111 | + return this._expires |
| 112 | + } |
75 | 113 |
|
76 | 114 | /** |
77 | 115 | * Set expires via max-age in `ms`. |
78 | 116 | * |
79 | | - * @param {Number} ms |
80 | | - * @api public |
| 117 | + * @param {number | undefined} ms |
| 118 | + * @public |
81 | 119 | */ |
82 | 120 |
|
83 | 121 | set maxAge(ms) { |
84 | | - if (ms && typeof ms !== 'number' && !(ms instanceof Date)) { |
85 | | - throw new TypeError('maxAge must be a number or Date') |
86 | | - } |
87 | | - |
88 | | - if (ms instanceof Date) { |
89 | | - deprecate('maxAge as Date; pass number of milliseconds instead') |
| 122 | + if (ms !== undefined) { |
| 123 | + if (typeof ms !== 'number') { |
| 124 | + throw new TypeError('maxAge must be a number') |
| 125 | + } |
| 126 | + this.expires = new Date(Date.now() + ms) |
| 127 | + } else { |
| 128 | + this.expires = undefined |
90 | 129 | } |
91 | | - |
92 | | - this.expires = typeof ms === 'number' |
93 | | - ? new Date(Date.now() + ms) |
94 | | - : ms; |
95 | | - }, |
| 130 | + } |
96 | 131 |
|
97 | 132 | /** |
98 | 133 | * Get expires max-age in `ms`. |
99 | 134 | * |
100 | | - * @return {Number} |
101 | | - * @api public |
| 135 | + * @return {number | undefined} |
| 136 | + * @public |
102 | 137 | */ |
103 | 138 |
|
104 | 139 | get maxAge() { |
105 | 140 | return this.expires instanceof Date |
106 | 141 | ? this.expires.valueOf() - Date.now() |
107 | | - : this.expires; |
108 | | - }, |
| 142 | + : this.expires |
| 143 | + } |
109 | 144 |
|
110 | 145 | /** |
111 | 146 | * Return cookie data object. |
112 | 147 | * |
113 | | - * @return {Object} |
114 | | - * @api private |
| 148 | + * @return {CookieSerializeOptions} |
| 149 | + * @private |
115 | 150 | */ |
116 | 151 |
|
117 | 152 | get data() { |
| 153 | + if (this.secure === 'auto') { |
| 154 | + throw new Error("Invalid runtime state, the Cookie.secure == 'auto', which should not be possible.") |
| 155 | + } |
118 | 156 | return { |
119 | | - originalMaxAge: this.originalMaxAge, |
120 | 157 | partitioned: this.partitioned, |
121 | 158 | priority: this.priority |
122 | | - , expires: this._expires |
| 159 | + , expires: this.expires |
123 | 160 | , secure: this.secure |
124 | 161 | , httpOnly: this.httpOnly |
125 | 162 | , domain: this.domain |
126 | 163 | , path: this.path |
127 | 164 | , sameSite: this.sameSite |
128 | 165 | } |
129 | | - }, |
130 | | - |
131 | | - /** |
132 | | - * Return a serialized cookie string. |
133 | | - * |
134 | | - * @return {String} |
135 | | - * @api public |
136 | | - */ |
137 | | - |
138 | | - serialize: function(name, val){ |
139 | | - return cookie.serialize(name, val, this.data); |
140 | | - }, |
| 166 | + } |
141 | 167 |
|
142 | 168 | /** |
143 | 169 | * Return JSON representation of this cookie. |
144 | 170 | * |
145 | | - * @return {Object} |
146 | | - * @api private |
| 171 | + * Used by `JSON.stringify` |
| 172 | + * |
| 173 | + * @returns {Object} |
| 174 | + * @protected |
147 | 175 | */ |
148 | 176 |
|
149 | | - toJSON: function(){ |
150 | | - return this.data; |
| 177 | + toJSON() { |
| 178 | + const data = { |
| 179 | + ...this.data, |
| 180 | + expires: this.expires, |
| 181 | + originalMaxAge: this.originalMaxAge, |
| 182 | + } |
| 183 | + console.log(`Cookie.toJSON: ${JSON.stringify(data)}`) |
| 184 | + return data |
151 | 185 | } |
152 | | -}; |
| 186 | +} |
| 187 | + |
| 188 | +module.exports = Cookie |
0 commit comments