|
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