Skip to content

Commit 46b55ae

Browse files
committed
wip: less rewriting way of adding types
1 parent 608f50a commit 46b55ae

21 files changed

+1118
-327
lines changed

index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ var parseUrl = require('parseurl');
2222
var signature = require('cookie-signature')
2323
var uid = require('uid-safe').sync
2424

25-
var Cookie = require('./session/cookie')
25+
const { Cookie } = require('./session/cookie')
2626
var MemoryStore = require('./session/memory')
27-
var Session = require('./session/session')
27+
const { Session } = require('./session/session')
2828
var Store = require('./session/store')
2929

3030
// environment

session/cookie.js

Lines changed: 78 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -8,125 +8,112 @@
88
'use strict';
99

1010
/**
11-
* @import { CookieSerializeOptions } from "cookie"
12-
* @import { CookieOptions } from "./cookie-options"
11+
* Module dependencies.
1312
*/
1413

14+
const cookie = require('cookie')
15+
const deprecate = require('depd')('express-session')
16+
1517
/**
16-
* Cookie TODO: add description
17-
* @class
18-
* @implements CookieOptions
18+
* @import { CookieOptions } from "./cookie.types"
1919
*/
2020

21+
/**
22+
* @implements {CookieOptions}
23+
*/
2124
class Cookie {
22-
/** @type {Date | undefined} @private */
25+
/** @private @type {Date | undefined} */
2326
_expires;
24-
/** @type {number | undefined} */
27+
/** @type {number | undefined} - Returns the original `maxAge` (time-to-live), in milliseconds, of the session cookie. */
2528
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} */
29+
/** @type {CookieOptions['signed']} */
30+
signed;
31+
/** @type {CookieOptions['httpOnly']} */
3332
httpOnly;
34-
/** @type {string} */
33+
/** @type {CookieOptions['path']} */
3534
path;
36-
/** @type {string | undefined} */
35+
/** @type {CookieOptions['domain']} */
3736
domain;
38-
/** @type {boolean | "auto" | undefined} */
37+
/** @type {CookieOptions['secure']} */
3938
secure;
40-
/** @type {((val: string) => string) | undefined} */
41-
encode;
42-
/** @type {boolean | "lax" | "strict" | "none" | undefined} */
39+
/** @type {CookieOptions['sameSite']} */
4340
sameSite;
4441

4542
/**
4643
* Initialize a new `Cookie` with the given `options`.
44+
*
4745
* @param {CookieOptions} options
48-
* @private
4946
*/
5047
constructor(options) {
48+
this.path = '/';
49+
this.maxAge = undefined;
50+
this.httpOnly = true;
51+
5152
if (options) {
5253
if (typeof options !== 'object') {
5354
throw new TypeError('argument options must be a object')
5455
}
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
56+
57+
/** @type {{[x: string]: any}} */
58+
const thisAsObject = this
59+
/** @type {{[x: string]: any}} */
60+
const optionsAsObject = options
61+
for (var key in optionsAsObject) {
62+
if (key !== 'data') {
63+
thisAsObject[key] = optionsAsObject[key]
64+
}
65+
}
7266
}
73-
}
7467

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
68+
if (this.originalMaxAge === undefined || this.originalMaxAge === null) {
69+
this.originalMaxAge = this.maxAge
70+
}
8871
}
8972

9073
/**
9174
* Set expires `date`.
9275
*
93-
* @param {Date | null | undefined} date
76+
* @param {Date | undefined} date
9477
* @public
9578
*/
9679

9780
set expires(date) {
98-
this._expires = date || undefined
99-
this.originalMaxAge = this.maxAge
81+
/* @type {Date | undefined} */
82+
this._expires = date;
83+
/* @type {number | undefined} */
84+
this.originalMaxAge = this.maxAge;
10085
}
10186

10287
/**
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.
88+
* Get expires `date`.
10589
*
10690
* @return {Date | undefined}
10791
* @public
10892
*/
10993

11094
get expires() {
111-
return this._expires
95+
return this._expires;
11296
}
11397

11498
/**
11599
* Set expires via max-age in `ms`.
116100
*
117-
* @param {number | undefined} ms
101+
* @param {Number | Date | undefined} ms
118102
* @public
119103
*/
120104

121105
set maxAge(ms) {
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
106+
if (ms && typeof ms !== 'number' && !(ms instanceof Date)) {
107+
throw new TypeError('maxAge must be a number or Date')
108+
}
109+
110+
if (ms instanceof Date) {
111+
deprecate('maxAge as Date; pass number of milliseconds instead')
129112
}
113+
114+
this.expires = typeof ms === 'number'
115+
? new Date(Date.now() + ms)
116+
: ms;
130117
}
131118

132119
/**
@@ -139,24 +126,23 @@ class Cookie {
139126
get maxAge() {
140127
return this.expires instanceof Date
141128
? this.expires.valueOf() - Date.now()
142-
: this.expires
129+
: this.expires;
143130
}
144131

145132
/**
146133
* Return cookie data object.
147134
*
148-
* @return {CookieSerializeOptions}
149-
* @private
135+
* @this {Cookie & CookieOptions}
136+
* @return {Object}
137+
* @public
150138
*/
151139

152140
get data() {
153-
if (this.secure === 'auto') {
154-
throw new Error("Invalid runtime state, the Cookie.secure == 'auto', which should not be possible.")
155-
}
156141
return {
142+
originalMaxAge: this.originalMaxAge,
157143
partitioned: this.partitioned,
158144
priority: this.priority
159-
, expires: this.expires
145+
, expires: this._expires
160146
, secure: this.secure
161147
, httpOnly: this.httpOnly
162148
, domain: this.domain
@@ -166,23 +152,30 @@ class Cookie {
166152
}
167153

168154
/**
169-
* Return JSON representation of this cookie.
155+
* Return a serialized cookie string.
170156
*
171-
* Used by `JSON.stringify`
157+
* @param {string} name
158+
* @param {string} val
159+
* @return {string}
160+
* @public
161+
*/
162+
163+
serialize(name, val) {
164+
return cookie.serialize(name, val, this.data);
165+
}
166+
167+
/**
168+
* Return JSON representation of this cookie.
172169
*
173-
* @returns {Object}
174-
* @protected
170+
* @return {Object}
171+
* @private
175172
*/
176173

177174
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
175+
return this.data;
185176
}
186177
}
187178

188-
module.exports = Cookie
179+
module.exports = {
180+
Cookie,
181+
}

session/cookie-options.d.ts renamed to session/cookie.types.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export declare interface CookieOptions {
1+
export interface CookieOptions {
22
/**
33
* Specifies the number (in milliseconds) to use when calculating the `Expires Set-Cookie` attribute.
44
* This is done by taking the current server time and adding `maxAge` milliseconds to the value to calculate an `Expires` datetime. By default, no maximum age is set.
@@ -38,6 +38,17 @@ export declare interface CookieOptions {
3838

3939
signed?: boolean | undefined;
4040

41+
/**
42+
* Specifies the `Date` object to be the value for the `Expires Set-Cookie` attribute.
43+
* 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.
44+
*
45+
* If both `expires` and `maxAge` are set in the options, then the last one defined in the object is what is used.
46+
*
47+
* @deprecated The `expires` option should not be set directly; instead only use the `maxAge` option
48+
* @see maxAge
49+
*/
50+
expires?: Date | null | undefined;
51+
4152
/**
4253
* Specifies the boolean value for the `HttpOnly Set-Cookie` attribute. When truthy, the `HttpOnly` attribute is set, otherwise it is not.
4354
* By default, the `HttpOnly` attribute is set.

session/request.types.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import type { SessionData } from "./session.types"
2+
import type { Store } from "./store"
3+
import type { Session } from "./session"
4+
5+
declare global {
6+
namespace Express {
7+
type SessionStore = Store & { generate: (req: Request) => void };
8+
9+
// Inject additional properties on express.Request
10+
interface Request {
11+
/**
12+
* This request's `Session` object.
13+
* Even though this property isn't marked as optional, it won't exist until you use the `express-session` middleware
14+
* [Declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) can be used to add your own properties.
15+
*
16+
* @see SessionData
17+
*/
18+
session: Session & Partial<SessionData>;
19+
20+
/**
21+
* This request's session ID.
22+
* Even though this property isn't marked as optional, it won't exist until you use the `express-session` middleware
23+
*/
24+
sessionID: string;
25+
26+
/**
27+
* The Store in use.
28+
* Even though this property isn't marked as optional, it won't exist until you use the `express-session` middleware
29+
* The function `generate` is added by express-session
30+
*/
31+
sessionStore: SessionStore;
32+
}
33+
}
34+
}
35+
36+
export type Request = Express.Request

0 commit comments

Comments
 (0)