Skip to content

Commit d610e5f

Browse files
committed
feat: Promise API
1 parent 81bfaf9 commit d610e5f

File tree

5 files changed

+225
-24
lines changed

5 files changed

+225
-24
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,15 @@ Allows to access or modify the session data.
104104

105105
#### Session#destroy(callback)
106106

107-
Allows to destroy the session in the store
107+
Allows to destroy the session in the store. If you do not pass a callback, a Promise will be returned.
108108

109109
#### Session#touch()
110110

111111
Updates the `expires` property of the session.
112112

113113
#### Session#regenerate(callback)
114114

115-
Regenerates the session by generating a new `sessionId` and persist it to the store.
115+
Regenerates the session by generating a new `sessionId` and persist it to the store. If you do not pass a callback, a Promise will be returned.
116116
```js
117117
fastify.get('/regenerate', (request, reply, done) => {
118118
request.session.regenerate(error => {
@@ -127,11 +127,11 @@ fastify.get('/regenerate', (request, reply, done) => {
127127

128128
#### Session#reload(callback)
129129

130-
Reloads the session data from the store and re-populates the `request.session` object.
130+
Reloads the session data from the store and re-populates the `request.session` object. If you do not pass a callback, a Promise will be returned.
131131

132132
#### Session#save(callback)
133133

134-
Save the session back to the store, replacing the contents on the store with the contents in memory.
134+
Save the session back to the store, replacing the contents on the store with the contents in memory. If you do not pass a callback, a Promise will be returned.
135135

136136
#### Session#get(key)
137137

lib/session.js

Lines changed: 76 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,29 @@ module.exports = class Session {
3636
}
3737

3838
regenerate (callback) {
39-
const session = new Session(this[requestKey], this[generateId], this[cookieOptsKey], this[secretKey])
40-
41-
this[requestKey].sessionStore.set(session.sessionId, session, error => {
42-
this[requestKey].session = session
43-
44-
callback(error)
45-
})
39+
if (callback) {
40+
const session = new Session(this[requestKey], this[generateId], this[cookieOptsKey], this[secretKey])
41+
42+
this[requestKey].sessionStore.set(session.sessionId, session, error => {
43+
this[requestKey].session = session
44+
45+
callback(error)
46+
})
47+
} else {
48+
return new Promise((resolve, reject) => {
49+
const session = new Session(this[requestKey], this[generateId], this[cookieOptsKey], this[secretKey])
50+
51+
this[requestKey].sessionStore.set(session.sessionId, session, error => {
52+
this[requestKey].session = session
53+
54+
if (error) {
55+
reject(error)
56+
} else {
57+
resolve()
58+
}
59+
})
60+
})
61+
}
4662
}
4763

4864
[addDataToSession] (prevSession) {
@@ -62,25 +78,65 @@ module.exports = class Session {
6278
}
6379

6480
destroy (callback) {
65-
this[requestKey].sessionStore.destroy(this.sessionId, error => {
66-
this[requestKey].session = null
67-
68-
callback(error)
69-
})
81+
if (callback) {
82+
this[requestKey].sessionStore.destroy(this.sessionId, error => {
83+
this[requestKey].session = null
84+
85+
callback(error)
86+
})
87+
} else {
88+
return new Promise((resolve, reject) => {
89+
this[requestKey].sessionStore.destroy(this.sessionId, error => {
90+
this[requestKey].session = null
91+
92+
if (error) {
93+
reject(error)
94+
} else {
95+
resolve()
96+
}
97+
})
98+
})
99+
}
70100
}
71101

72102
reload (callback) {
73-
this[requestKey].sessionStore.get(this.sessionId, (error, session) => {
74-
this[requestKey].session = new Session(this[requestKey], this[generateId], this[cookieOptsKey], this[secretKey], session)
75-
76-
callback(error)
77-
})
103+
if (callback) {
104+
this[requestKey].sessionStore.get(this.sessionId, (error, session) => {
105+
this[requestKey].session = new Session(this[requestKey], this[generateId], this[cookieOptsKey], this[secretKey], session)
106+
107+
callback(error)
108+
})
109+
} else {
110+
return new Promise((resolve, reject) => {
111+
this[requestKey].sessionStore.get(this.sessionId, (error, session) => {
112+
this[requestKey].session = new Session(this[requestKey], this[generateId], this[cookieOptsKey], this[secretKey], session)
113+
114+
if (error) {
115+
reject(error)
116+
} else {
117+
resolve()
118+
}
119+
})
120+
})
121+
}
78122
}
79123

80124
save (callback) {
81-
this[requestKey].sessionStore.set(this.sessionId, this, error => {
82-
callback(error)
83-
})
125+
if (callback) {
126+
this[requestKey].sessionStore.set(this.sessionId, this, error => {
127+
callback(error)
128+
})
129+
} else {
130+
return new Promise((resolve, reject) => {
131+
this[requestKey].sessionStore.set(this.sessionId, this, error => {
132+
if (error) {
133+
reject(error)
134+
} else {
135+
resolve()
136+
}
137+
})
138+
})
139+
}
84140
}
85141

86142
[sign] () {

test/session.test.js

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,3 +540,139 @@ test('should save the session', async (t) => {
540540

541541
t.is(response.statusCode, 200)
542542
})
543+
544+
test('destroy supports promises', async t => {
545+
t.plan(2)
546+
const port = await testServer(async (request, reply) => {
547+
await t.notThrowsAsync(request.session.destroy())
548+
549+
reply.send(200)
550+
}, DEFAULT_OPTIONS)
551+
552+
const { response } = await request(`http://localhost:${port}`)
553+
554+
t.is(response.statusCode, 200)
555+
})
556+
557+
test('destroy supports rejecting promises', async t => {
558+
t.plan(2)
559+
const port = await testServer(async (request, reply) => {
560+
await t.throwsAsync(request.session.destroy(), { message: 'no can do' })
561+
562+
reply.send(200)
563+
}, {
564+
...DEFAULT_OPTIONS,
565+
store: {
566+
set (id, data, cb) { cb(null) },
567+
get (id, cb) { cb(null) },
568+
destroy (id, cb) { cb(new Error('no can do')) }
569+
}
570+
})
571+
572+
const { response } = await request(`http://localhost:${port}`)
573+
574+
// 200 since we assert inline and swallow the error
575+
t.is(response.statusCode, 200)
576+
})
577+
578+
test('regenerate supports promises', async t => {
579+
t.plan(2)
580+
const port = await testServer(async (request, reply) => {
581+
await t.notThrowsAsync(request.session.regenerate())
582+
583+
reply.send(200)
584+
}, DEFAULT_OPTIONS)
585+
586+
const { response } = await request(`http://localhost:${port}`)
587+
588+
t.is(response.statusCode, 200)
589+
})
590+
591+
test('regenerate supports rejecting promises', async t => {
592+
t.plan(2)
593+
const port = await testServer(async (request, reply) => {
594+
await t.throwsAsync(request.session.regenerate(), { message: 'no can do' })
595+
596+
reply.send(200)
597+
}, {
598+
...DEFAULT_OPTIONS,
599+
store: {
600+
set (id, data, cb) { cb(new Error('no can do')) },
601+
get (id, cb) { cb(null) },
602+
destroy (id, cb) { cb(null) }
603+
}
604+
})
605+
606+
const { response } = await request(`http://localhost:${port}`)
607+
608+
// 200 since we assert inline and swallow the error
609+
t.is(response.statusCode, 200)
610+
})
611+
612+
test('reload supports promises', async t => {
613+
t.plan(2)
614+
const port = await testServer(async (request, reply) => {
615+
await t.notThrowsAsync(request.session.reload())
616+
617+
reply.send(200)
618+
}, DEFAULT_OPTIONS)
619+
620+
const { response } = await request(`http://localhost:${port}`)
621+
622+
t.is(response.statusCode, 200)
623+
})
624+
625+
test('reload supports rejecting promises', async t => {
626+
t.plan(2)
627+
const port = await testServer(async (request, reply) => {
628+
await t.throwsAsync(request.session.reload(), { message: 'no can do' })
629+
630+
reply.send(200)
631+
}, {
632+
...DEFAULT_OPTIONS,
633+
store: {
634+
set (id, data, cb) { cb(null) },
635+
get (id, cb) { cb(new Error('no can do')) },
636+
destroy (id, cb) { cb(null) }
637+
}
638+
})
639+
640+
const { response } = await request(`http://localhost:${port}`)
641+
642+
// 200 since we assert inline and swallow the error
643+
t.is(response.statusCode, 200)
644+
})
645+
646+
test('save supports promises', async t => {
647+
t.plan(2)
648+
const port = await testServer(async (request, reply) => {
649+
await t.notThrowsAsync(request.session.save())
650+
651+
reply.send(200)
652+
}, DEFAULT_OPTIONS)
653+
654+
const { response } = await request(`http://localhost:${port}`)
655+
656+
t.is(response.statusCode, 200)
657+
})
658+
659+
test('save supports rejecting promises', async t => {
660+
t.plan(2)
661+
const port = await testServer(async (request, reply) => {
662+
await t.throwsAsync(request.session.save())
663+
664+
reply.send(200)
665+
}, {
666+
...DEFAULT_OPTIONS,
667+
store: {
668+
set (id, data, cb) { cb(new Error('no can do')) },
669+
get (id, cb) { cb(null) },
670+
save (id, cb) { cb(null) }
671+
}
672+
})
673+
674+
const { response } = await request(`http://localhost:${port}`)
675+
676+
// 200 since we assert inline and swallow the error
677+
t.is(response.statusCode, 200)
678+
})

types/types.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,19 @@ interface SessionData extends ExpressSessionData {
2727
* Regenerates the session by generating a new `sessionId`.
2828
*/
2929
regenerate(callback: (err?: Error) => void): void;
30+
regenerate(): Promise<void>;
3031

3132
/** Allows to destroy the session in the store. */
3233
destroy(callback: (err?: Error) => void): void;
34+
destroy(): Promise<void>;
3335

3436
/** Reloads the session data from the store and re-populates the request.session object. */
3537
reload(callback: (err?: Error) => void): void;
38+
reload(): Promise<void>;
3639

3740
/** Save the session back to the store, replacing the contents on the store with the contents in memory. */
3841
save(callback: (err?: Error) => void): void;
42+
save(): Promise<void>;
3943

4044
/** sets values in the session. */
4145
set(key: string, value: unknown): void;

types/types.test-d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ app.route({
6161
url: '/',
6262
preHandler(req, _rep, next) {
6363
expectType<void>(req.session.destroy(next));
64+
expectType<Promise<void>>(req.session.destroy());
6465
},
6566
async handler(request, reply) {
6667
expectType<FastifyRequest>(request);
@@ -82,5 +83,9 @@ app.route({
8283
expectType<void>(request.session.destroy(() => {}));
8384
expectType<void>(request.session.regenerate(() => {}));
8485
expectType<void>(request.session.save(() => {}));
86+
expectType<Promise<void>>(request.session.reload());
87+
expectType<Promise<void>>(request.session.destroy());
88+
expectType<Promise<void>>(request.session.regenerate());
89+
expectType<Promise<void>>(request.session.save());
8590
}
8691
});

0 commit comments

Comments
 (0)