Skip to content

Commit 85a2947

Browse files
authored
Make callbacks optional for async functions (#430)
1 parent 7f995db commit 85a2947

File tree

2 files changed

+62
-57
lines changed

2 files changed

+62
-57
lines changed

index.ts

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import {SessionData, Store} from "express-session"
22

3-
const noop = (_err?: unknown, _data?: any) => {}
3+
type Callback = (_err?: unknown, _data?: any) => any
4+
5+
function optionalCb(err: unknown, data: unknown, cb?: Callback) {
6+
if (cb) return cb(err, data)
7+
if (err) throw err
8+
return data
9+
}
410

511
interface NormalizedRedisClient {
612
get(key: string): Promise<string | null>
@@ -96,93 +102,94 @@ export class RedisStore extends Store {
96102
}
97103
}
98104

99-
async get(sid: string, cb = noop) {
105+
async get(sid: string, cb?: Callback) {
100106
let key = this.prefix + sid
101107
try {
102108
let data = await this.client.get(key)
103-
if (!data) return cb()
104-
return cb(null, await this.serializer.parse(data))
109+
if (!data) return optionalCb(null, null, cb)
110+
return optionalCb(null, await this.serializer.parse(data), cb)
105111
} catch (err) {
106-
return cb(err)
112+
return optionalCb(err, null, cb)
107113
}
108114
}
109115

110-
async set(sid: string, sess: SessionData, cb = noop) {
116+
async set(sid: string, sess: SessionData, cb?: Callback) {
111117
let key = this.prefix + sid
112118
let ttl = this._getTTL(sess)
113119
try {
114120
if (ttl > 0) {
115121
let val = this.serializer.stringify(sess)
116122
if (this.disableTTL) await this.client.set(key, val)
117123
else await this.client.set(key, val, ttl)
118-
return cb()
124+
return optionalCb(null, null, cb)
119125
} else {
120126
return this.destroy(sid, cb)
121127
}
122128
} catch (err) {
123-
return cb(err)
129+
return optionalCb(err, null, cb)
124130
}
125131
}
126132

127-
async touch(sid: string, sess: SessionData, cb = noop) {
133+
async touch(sid: string, sess: SessionData, cb?: Callback) {
128134
let key = this.prefix + sid
129-
if (this.disableTouch || this.disableTTL) return cb()
135+
if (this.disableTouch || this.disableTTL) return optionalCb(null, null, cb)
130136
try {
131137
await this.client.expire(key, this._getTTL(sess))
132-
return cb()
138+
return optionalCb(null, null, cb)
133139
} catch (err) {
134-
return cb(err)
140+
return optionalCb(err, null, cb)
135141
}
136142
}
137143

138-
async destroy(sid: string, cb = noop) {
144+
async destroy(sid: string, cb?: Callback) {
139145
let key = this.prefix + sid
140146
try {
141147
await this.client.del([key])
142-
return cb()
148+
return optionalCb(null, null, cb)
143149
} catch (err) {
144-
return cb(err)
150+
return optionalCb(err, null, cb)
145151
}
146152
}
147153

148-
async clear(cb = noop) {
154+
async clear(cb?: Callback) {
149155
try {
150156
let keys = await this._getAllKeys()
151-
if (!keys.length) return cb()
157+
if (!keys.length) return optionalCb(null, null, cb)
152158
await this.client.del(keys)
153-
return cb()
159+
return optionalCb(null, null, cb)
154160
} catch (err) {
155-
return cb(err)
161+
return optionalCb(err, null, cb)
156162
}
157163
}
158164

159-
async length(cb = noop) {
165+
async length(cb?: Callback) {
160166
try {
161167
let keys = await this._getAllKeys()
162-
return cb(null, keys.length)
168+
return optionalCb(null, keys.length, cb)
163169
} catch (err) {
164-
return cb(err)
170+
return optionalCb(err, null, cb)
165171
}
166172
}
167173

168-
async ids(cb = noop) {
174+
async ids(cb?: Callback) {
169175
let len = this.prefix.length
170176
try {
171177
let keys = await this._getAllKeys()
172-
return cb(
178+
return optionalCb(
173179
null,
174180
keys.map((k) => k.substring(len)),
181+
cb,
175182
)
176183
} catch (err) {
177-
return cb(err)
184+
return optionalCb(err, null, cb)
178185
}
179186
}
180187

181-
async all(cb = noop) {
188+
async all(cb?: Callback) {
182189
let len = this.prefix.length
183190
try {
184191
let keys = await this._getAllKeys()
185-
if (keys.length === 0) return cb(null, [])
192+
if (keys.length === 0) return optionalCb(null, [], cb)
186193

187194
let data = await this.client.mget(keys)
188195
let results = data.reduce((acc, raw, idx) => {
@@ -192,9 +199,9 @@ export class RedisStore extends Store {
192199
acc.push(sess)
193200
return acc
194201
}, [] as SessionData[])
195-
return cb(null, results)
202+
return optionalCb(null, results, cb)
196203
} catch (err) {
197-
return cb(err)
204+
return optionalCb(err, null, cb)
198205
}
199206
}
200207

index_test.ts

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {Cookie} from "express-session"
22
import {Redis} from "ioredis"
3-
import {promisify} from "node:util"
43
import {createClient} from "redis"
54
import {expect, test} from "vitest"
65
import {RedisStore} from "./"
@@ -44,73 +43,72 @@ test("ioredis", async () => {
4443
test("teardown", redisSrv.disconnect)
4544

4645
async function lifecycleTest(store: RedisStore, client: any): Promise<void> {
47-
const P = (f: any) => promisify(f).bind(store)
48-
let res = await P(store.clear)()
46+
let res = await store.clear()
4947

50-
let sess = {foo: "bar"}
51-
await P(store.set)("123", sess)
48+
let sess = {foo: "bar", cookie: {originalMaxAge: null}}
49+
await store.set("123", sess)
5250

53-
res = await P(store.get)("123")
51+
res = await store.get("123")
5452
expect(res).toEqual(sess)
5553

5654
let ttl = await client.ttl("sess:123")
5755
expect(ttl).toBeGreaterThanOrEqual(86399)
5856

5957
ttl = 60
60-
let expires = new Date(Date.now() + ttl * 1000).toISOString()
61-
await P(store.set)("456", {cookie: {expires}})
58+
let expires = new Date(Date.now() + ttl * 1000)
59+
await store.set("456", {cookie: {originalMaxAge: null, expires}})
6260
ttl = await client.ttl("sess:456")
6361
expect(ttl).toBeLessThanOrEqual(60)
6462

6563
ttl = 90
66-
let expires2 = new Date(Date.now() + ttl * 1000).toISOString()
67-
await P(store.touch)("456", {cookie: {expires: expires2}})
64+
let expires2 = new Date(Date.now() + ttl * 1000)
65+
await store.touch("456", {cookie: {originalMaxAge: null, expires: expires2}})
6866
ttl = await client.ttl("sess:456")
6967
expect(ttl).toBeGreaterThan(60)
7068

71-
res = await P(store.length)()
69+
res = await store.length()
7270
expect(res).toBe(2) // stored two keys length
7371

74-
res = await P(store.ids)()
72+
res = await store.ids()
7573
res.sort()
7674
expect(res).toEqual(["123", "456"])
7775

78-
res = await P(store.all)()
76+
res = await store.all()
7977
res.sort((a: any, b: any) => (a.id > b.id ? 1 : -1))
8078
expect(res).toEqual([
81-
{id: "123", foo: "bar"},
82-
{id: "456", cookie: {expires}},
79+
{id: "123", foo: "bar", cookie: {originalMaxAge: null}},
80+
{id: "456", cookie: {originalMaxAge: null, expires: expires.toISOString()}},
8381
])
8482

85-
await P(store.destroy)("456")
86-
res = await P(store.length)()
83+
await store.destroy("456")
84+
res = await store.length()
8785
expect(res).toBe(1) // one key remains
8886

89-
res = await P(store.clear)()
87+
res = await store.clear()
9088

91-
res = await P(store.length)()
89+
res = await store.length()
9290
expect(res).toBe(0) // no keys remain
9391

9492
let count = 1000
9593
await load(store, count)
9694

97-
res = await P(store.length)()
95+
res = await store.length()
9896
expect(res).toBe(count)
9997

100-
await P(store.clear)()
101-
res = await P(store.length)()
98+
await store.clear()
99+
res = await store.length()
102100
expect(res).toBe(0)
103101

104-
expires = new Date(Date.now() + ttl * 1000).toISOString() // expires in the future
105-
res = await P(store.set)("789", {cookie: {expires}})
102+
expires = new Date(Date.now() + ttl * 1000) // expires in the future
103+
res = await store.set("789", {cookie: {originalMaxAge: null, expires}})
106104

107-
res = await P(store.length)()
105+
res = await store.length()
108106
expect(res).toBe(1)
109107

110-
expires = new Date(Date.now() - ttl * 1000).toISOString() // expires in the past
111-
await P(store.set)("789", {cookie: {expires}})
108+
expires = new Date(Date.now() - ttl * 1000) // expires in the past
109+
await store.set("789", {cookie: {originalMaxAge: null, expires}})
112110

113-
res = await P(store.length)()
111+
res = await store.length()
114112
expect(res).toBe(0) // no key remains and that includes session 789
115113
}
116114

0 commit comments

Comments
 (0)