@dungarees/jwt 0.11.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/fake.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import type { JWTPayload, JwtService } from './type.ts';
2
+ export declare const createFakeJwtService: <PAYLOAD extends JWTPayload>(invalid?: PAYLOAD[]) => JwtService<PAYLOAD>;
package/fake.js ADDED
@@ -0,0 +1,34 @@
1
+ import { isDeepEqual } from '@dungarees/core/util.ts';
2
+ // The token is the JSON of its payload: readable in a failing test, and cheap enough to create in
3
+ // a loop, which a real signature is not.
4
+ export const createFakeJwtService = (invalid = []) => {
5
+ const parseToken = (token) => {
6
+ const parsed = jsonOrUndefined(token);
7
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
8
+ return undefined;
9
+ }
10
+ // The token was produced by createToken below, so its shape is whatever the caller passed in.
11
+ // There is no schema for a generic PAYLOAD to narrow it against.
12
+ return parsed;
13
+ };
14
+ return {
15
+ createToken: async (payload) => JSON.stringify(payload),
16
+ verifyToken: async (token) => {
17
+ const payload = parseToken(token);
18
+ if (payload === undefined || invalid.some((rejected) => isDeepEqual(rejected, payload))) {
19
+ throw new Error('Could not parse JWT token.');
20
+ }
21
+ return { payload };
22
+ },
23
+ decodeToken: (token) => ({ payload: parseToken(token) }),
24
+ };
25
+ };
26
+ // JSON.parse is typed `any`, so this narrows it to unknown at the one place it is read.
27
+ const jsonOrUndefined = (json) => {
28
+ try {
29
+ return JSON.parse(json);
30
+ }
31
+ catch {
32
+ return undefined;
33
+ }
34
+ };
package/package.json ADDED
@@ -0,0 +1,447 @@
1
+ {
2
+ "name": "@dungarees/jwt",
3
+ "engines": {
4
+ "node": ">=25.0.0"
5
+ },
6
+ "scripts": {
7
+ "type-check": "tsc --noEmit"
8
+ },
9
+ "type": "module",
10
+ "dependencies": {
11
+ "@dungarees/core": "*",
12
+ "jose": "^6.2.12"
13
+ },
14
+ "devDependencies": {
15
+ "typescript": "^5.9.3",
16
+ "vitest": "^3.0.2"
17
+ },
18
+ "author": "info@productkind.com",
19
+ "license": "MIT",
20
+ "version": "0.11.4",
21
+ "exports": {
22
+ "./fake.ts": {
23
+ "import": "./fake.js",
24
+ "types": "./fake.d.ts"
25
+ },
26
+ "./node_modules/typescript/lib/lib.d.ts": {
27
+ "import": "./node_modules/typescript/lib/lib.d.js",
28
+ "types": "./node_modules/typescript/lib/lib.d.d.ts"
29
+ },
30
+ "./node_modules/typescript/lib/lib.decorators.d.ts": {
31
+ "import": "./node_modules/typescript/lib/lib.decorators.d.js",
32
+ "types": "./node_modules/typescript/lib/lib.decorators.d.d.ts"
33
+ },
34
+ "./node_modules/typescript/lib/lib.decorators.legacy.d.ts": {
35
+ "import": "./node_modules/typescript/lib/lib.decorators.legacy.d.js",
36
+ "types": "./node_modules/typescript/lib/lib.decorators.legacy.d.d.ts"
37
+ },
38
+ "./node_modules/typescript/lib/lib.dom.asynciterable.d.ts": {
39
+ "import": "./node_modules/typescript/lib/lib.dom.asynciterable.d.js",
40
+ "types": "./node_modules/typescript/lib/lib.dom.asynciterable.d.d.ts"
41
+ },
42
+ "./node_modules/typescript/lib/lib.dom.d.ts": {
43
+ "import": "./node_modules/typescript/lib/lib.dom.d.js",
44
+ "types": "./node_modules/typescript/lib/lib.dom.d.d.ts"
45
+ },
46
+ "./node_modules/typescript/lib/lib.dom.iterable.d.ts": {
47
+ "import": "./node_modules/typescript/lib/lib.dom.iterable.d.js",
48
+ "types": "./node_modules/typescript/lib/lib.dom.iterable.d.d.ts"
49
+ },
50
+ "./node_modules/typescript/lib/lib.es2015.collection.d.ts": {
51
+ "import": "./node_modules/typescript/lib/lib.es2015.collection.d.js",
52
+ "types": "./node_modules/typescript/lib/lib.es2015.collection.d.d.ts"
53
+ },
54
+ "./node_modules/typescript/lib/lib.es2015.core.d.ts": {
55
+ "import": "./node_modules/typescript/lib/lib.es2015.core.d.js",
56
+ "types": "./node_modules/typescript/lib/lib.es2015.core.d.d.ts"
57
+ },
58
+ "./node_modules/typescript/lib/lib.es2015.d.ts": {
59
+ "import": "./node_modules/typescript/lib/lib.es2015.d.js",
60
+ "types": "./node_modules/typescript/lib/lib.es2015.d.d.ts"
61
+ },
62
+ "./node_modules/typescript/lib/lib.es2015.generator.d.ts": {
63
+ "import": "./node_modules/typescript/lib/lib.es2015.generator.d.js",
64
+ "types": "./node_modules/typescript/lib/lib.es2015.generator.d.d.ts"
65
+ },
66
+ "./node_modules/typescript/lib/lib.es2015.iterable.d.ts": {
67
+ "import": "./node_modules/typescript/lib/lib.es2015.iterable.d.js",
68
+ "types": "./node_modules/typescript/lib/lib.es2015.iterable.d.d.ts"
69
+ },
70
+ "./node_modules/typescript/lib/lib.es2015.promise.d.ts": {
71
+ "import": "./node_modules/typescript/lib/lib.es2015.promise.d.js",
72
+ "types": "./node_modules/typescript/lib/lib.es2015.promise.d.d.ts"
73
+ },
74
+ "./node_modules/typescript/lib/lib.es2015.proxy.d.ts": {
75
+ "import": "./node_modules/typescript/lib/lib.es2015.proxy.d.js",
76
+ "types": "./node_modules/typescript/lib/lib.es2015.proxy.d.d.ts"
77
+ },
78
+ "./node_modules/typescript/lib/lib.es2015.reflect.d.ts": {
79
+ "import": "./node_modules/typescript/lib/lib.es2015.reflect.d.js",
80
+ "types": "./node_modules/typescript/lib/lib.es2015.reflect.d.d.ts"
81
+ },
82
+ "./node_modules/typescript/lib/lib.es2015.symbol.d.ts": {
83
+ "import": "./node_modules/typescript/lib/lib.es2015.symbol.d.js",
84
+ "types": "./node_modules/typescript/lib/lib.es2015.symbol.d.d.ts"
85
+ },
86
+ "./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts": {
87
+ "import": "./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.js",
88
+ "types": "./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.d.ts"
89
+ },
90
+ "./node_modules/typescript/lib/lib.es2016.array.include.d.ts": {
91
+ "import": "./node_modules/typescript/lib/lib.es2016.array.include.d.js",
92
+ "types": "./node_modules/typescript/lib/lib.es2016.array.include.d.d.ts"
93
+ },
94
+ "./node_modules/typescript/lib/lib.es2016.d.ts": {
95
+ "import": "./node_modules/typescript/lib/lib.es2016.d.js",
96
+ "types": "./node_modules/typescript/lib/lib.es2016.d.d.ts"
97
+ },
98
+ "./node_modules/typescript/lib/lib.es2016.full.d.ts": {
99
+ "import": "./node_modules/typescript/lib/lib.es2016.full.d.js",
100
+ "types": "./node_modules/typescript/lib/lib.es2016.full.d.d.ts"
101
+ },
102
+ "./node_modules/typescript/lib/lib.es2016.intl.d.ts": {
103
+ "import": "./node_modules/typescript/lib/lib.es2016.intl.d.js",
104
+ "types": "./node_modules/typescript/lib/lib.es2016.intl.d.d.ts"
105
+ },
106
+ "./node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts": {
107
+ "import": "./node_modules/typescript/lib/lib.es2017.arraybuffer.d.js",
108
+ "types": "./node_modules/typescript/lib/lib.es2017.arraybuffer.d.d.ts"
109
+ },
110
+ "./node_modules/typescript/lib/lib.es2017.d.ts": {
111
+ "import": "./node_modules/typescript/lib/lib.es2017.d.js",
112
+ "types": "./node_modules/typescript/lib/lib.es2017.d.d.ts"
113
+ },
114
+ "./node_modules/typescript/lib/lib.es2017.date.d.ts": {
115
+ "import": "./node_modules/typescript/lib/lib.es2017.date.d.js",
116
+ "types": "./node_modules/typescript/lib/lib.es2017.date.d.d.ts"
117
+ },
118
+ "./node_modules/typescript/lib/lib.es2017.full.d.ts": {
119
+ "import": "./node_modules/typescript/lib/lib.es2017.full.d.js",
120
+ "types": "./node_modules/typescript/lib/lib.es2017.full.d.d.ts"
121
+ },
122
+ "./node_modules/typescript/lib/lib.es2017.intl.d.ts": {
123
+ "import": "./node_modules/typescript/lib/lib.es2017.intl.d.js",
124
+ "types": "./node_modules/typescript/lib/lib.es2017.intl.d.d.ts"
125
+ },
126
+ "./node_modules/typescript/lib/lib.es2017.object.d.ts": {
127
+ "import": "./node_modules/typescript/lib/lib.es2017.object.d.js",
128
+ "types": "./node_modules/typescript/lib/lib.es2017.object.d.d.ts"
129
+ },
130
+ "./node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts": {
131
+ "import": "./node_modules/typescript/lib/lib.es2017.sharedmemory.d.js",
132
+ "types": "./node_modules/typescript/lib/lib.es2017.sharedmemory.d.d.ts"
133
+ },
134
+ "./node_modules/typescript/lib/lib.es2017.string.d.ts": {
135
+ "import": "./node_modules/typescript/lib/lib.es2017.string.d.js",
136
+ "types": "./node_modules/typescript/lib/lib.es2017.string.d.d.ts"
137
+ },
138
+ "./node_modules/typescript/lib/lib.es2017.typedarrays.d.ts": {
139
+ "import": "./node_modules/typescript/lib/lib.es2017.typedarrays.d.js",
140
+ "types": "./node_modules/typescript/lib/lib.es2017.typedarrays.d.d.ts"
141
+ },
142
+ "./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts": {
143
+ "import": "./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.js",
144
+ "types": "./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.d.ts"
145
+ },
146
+ "./node_modules/typescript/lib/lib.es2018.asynciterable.d.ts": {
147
+ "import": "./node_modules/typescript/lib/lib.es2018.asynciterable.d.js",
148
+ "types": "./node_modules/typescript/lib/lib.es2018.asynciterable.d.d.ts"
149
+ },
150
+ "./node_modules/typescript/lib/lib.es2018.d.ts": {
151
+ "import": "./node_modules/typescript/lib/lib.es2018.d.js",
152
+ "types": "./node_modules/typescript/lib/lib.es2018.d.d.ts"
153
+ },
154
+ "./node_modules/typescript/lib/lib.es2018.full.d.ts": {
155
+ "import": "./node_modules/typescript/lib/lib.es2018.full.d.js",
156
+ "types": "./node_modules/typescript/lib/lib.es2018.full.d.d.ts"
157
+ },
158
+ "./node_modules/typescript/lib/lib.es2018.intl.d.ts": {
159
+ "import": "./node_modules/typescript/lib/lib.es2018.intl.d.js",
160
+ "types": "./node_modules/typescript/lib/lib.es2018.intl.d.d.ts"
161
+ },
162
+ "./node_modules/typescript/lib/lib.es2018.promise.d.ts": {
163
+ "import": "./node_modules/typescript/lib/lib.es2018.promise.d.js",
164
+ "types": "./node_modules/typescript/lib/lib.es2018.promise.d.d.ts"
165
+ },
166
+ "./node_modules/typescript/lib/lib.es2018.regexp.d.ts": {
167
+ "import": "./node_modules/typescript/lib/lib.es2018.regexp.d.js",
168
+ "types": "./node_modules/typescript/lib/lib.es2018.regexp.d.d.ts"
169
+ },
170
+ "./node_modules/typescript/lib/lib.es2019.array.d.ts": {
171
+ "import": "./node_modules/typescript/lib/lib.es2019.array.d.js",
172
+ "types": "./node_modules/typescript/lib/lib.es2019.array.d.d.ts"
173
+ },
174
+ "./node_modules/typescript/lib/lib.es2019.d.ts": {
175
+ "import": "./node_modules/typescript/lib/lib.es2019.d.js",
176
+ "types": "./node_modules/typescript/lib/lib.es2019.d.d.ts"
177
+ },
178
+ "./node_modules/typescript/lib/lib.es2019.full.d.ts": {
179
+ "import": "./node_modules/typescript/lib/lib.es2019.full.d.js",
180
+ "types": "./node_modules/typescript/lib/lib.es2019.full.d.d.ts"
181
+ },
182
+ "./node_modules/typescript/lib/lib.es2019.intl.d.ts": {
183
+ "import": "./node_modules/typescript/lib/lib.es2019.intl.d.js",
184
+ "types": "./node_modules/typescript/lib/lib.es2019.intl.d.d.ts"
185
+ },
186
+ "./node_modules/typescript/lib/lib.es2019.object.d.ts": {
187
+ "import": "./node_modules/typescript/lib/lib.es2019.object.d.js",
188
+ "types": "./node_modules/typescript/lib/lib.es2019.object.d.d.ts"
189
+ },
190
+ "./node_modules/typescript/lib/lib.es2019.string.d.ts": {
191
+ "import": "./node_modules/typescript/lib/lib.es2019.string.d.js",
192
+ "types": "./node_modules/typescript/lib/lib.es2019.string.d.d.ts"
193
+ },
194
+ "./node_modules/typescript/lib/lib.es2019.symbol.d.ts": {
195
+ "import": "./node_modules/typescript/lib/lib.es2019.symbol.d.js",
196
+ "types": "./node_modules/typescript/lib/lib.es2019.symbol.d.d.ts"
197
+ },
198
+ "./node_modules/typescript/lib/lib.es2020.bigint.d.ts": {
199
+ "import": "./node_modules/typescript/lib/lib.es2020.bigint.d.js",
200
+ "types": "./node_modules/typescript/lib/lib.es2020.bigint.d.d.ts"
201
+ },
202
+ "./node_modules/typescript/lib/lib.es2020.d.ts": {
203
+ "import": "./node_modules/typescript/lib/lib.es2020.d.js",
204
+ "types": "./node_modules/typescript/lib/lib.es2020.d.d.ts"
205
+ },
206
+ "./node_modules/typescript/lib/lib.es2020.date.d.ts": {
207
+ "import": "./node_modules/typescript/lib/lib.es2020.date.d.js",
208
+ "types": "./node_modules/typescript/lib/lib.es2020.date.d.d.ts"
209
+ },
210
+ "./node_modules/typescript/lib/lib.es2020.full.d.ts": {
211
+ "import": "./node_modules/typescript/lib/lib.es2020.full.d.js",
212
+ "types": "./node_modules/typescript/lib/lib.es2020.full.d.d.ts"
213
+ },
214
+ "./node_modules/typescript/lib/lib.es2020.intl.d.ts": {
215
+ "import": "./node_modules/typescript/lib/lib.es2020.intl.d.js",
216
+ "types": "./node_modules/typescript/lib/lib.es2020.intl.d.d.ts"
217
+ },
218
+ "./node_modules/typescript/lib/lib.es2020.number.d.ts": {
219
+ "import": "./node_modules/typescript/lib/lib.es2020.number.d.js",
220
+ "types": "./node_modules/typescript/lib/lib.es2020.number.d.d.ts"
221
+ },
222
+ "./node_modules/typescript/lib/lib.es2020.promise.d.ts": {
223
+ "import": "./node_modules/typescript/lib/lib.es2020.promise.d.js",
224
+ "types": "./node_modules/typescript/lib/lib.es2020.promise.d.d.ts"
225
+ },
226
+ "./node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts": {
227
+ "import": "./node_modules/typescript/lib/lib.es2020.sharedmemory.d.js",
228
+ "types": "./node_modules/typescript/lib/lib.es2020.sharedmemory.d.d.ts"
229
+ },
230
+ "./node_modules/typescript/lib/lib.es2020.string.d.ts": {
231
+ "import": "./node_modules/typescript/lib/lib.es2020.string.d.js",
232
+ "types": "./node_modules/typescript/lib/lib.es2020.string.d.d.ts"
233
+ },
234
+ "./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts": {
235
+ "import": "./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.js",
236
+ "types": "./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.d.ts"
237
+ },
238
+ "./node_modules/typescript/lib/lib.es2021.d.ts": {
239
+ "import": "./node_modules/typescript/lib/lib.es2021.d.js",
240
+ "types": "./node_modules/typescript/lib/lib.es2021.d.d.ts"
241
+ },
242
+ "./node_modules/typescript/lib/lib.es2021.full.d.ts": {
243
+ "import": "./node_modules/typescript/lib/lib.es2021.full.d.js",
244
+ "types": "./node_modules/typescript/lib/lib.es2021.full.d.d.ts"
245
+ },
246
+ "./node_modules/typescript/lib/lib.es2021.intl.d.ts": {
247
+ "import": "./node_modules/typescript/lib/lib.es2021.intl.d.js",
248
+ "types": "./node_modules/typescript/lib/lib.es2021.intl.d.d.ts"
249
+ },
250
+ "./node_modules/typescript/lib/lib.es2021.promise.d.ts": {
251
+ "import": "./node_modules/typescript/lib/lib.es2021.promise.d.js",
252
+ "types": "./node_modules/typescript/lib/lib.es2021.promise.d.d.ts"
253
+ },
254
+ "./node_modules/typescript/lib/lib.es2021.string.d.ts": {
255
+ "import": "./node_modules/typescript/lib/lib.es2021.string.d.js",
256
+ "types": "./node_modules/typescript/lib/lib.es2021.string.d.d.ts"
257
+ },
258
+ "./node_modules/typescript/lib/lib.es2021.weakref.d.ts": {
259
+ "import": "./node_modules/typescript/lib/lib.es2021.weakref.d.js",
260
+ "types": "./node_modules/typescript/lib/lib.es2021.weakref.d.d.ts"
261
+ },
262
+ "./node_modules/typescript/lib/lib.es2022.array.d.ts": {
263
+ "import": "./node_modules/typescript/lib/lib.es2022.array.d.js",
264
+ "types": "./node_modules/typescript/lib/lib.es2022.array.d.d.ts"
265
+ },
266
+ "./node_modules/typescript/lib/lib.es2022.d.ts": {
267
+ "import": "./node_modules/typescript/lib/lib.es2022.d.js",
268
+ "types": "./node_modules/typescript/lib/lib.es2022.d.d.ts"
269
+ },
270
+ "./node_modules/typescript/lib/lib.es2022.error.d.ts": {
271
+ "import": "./node_modules/typescript/lib/lib.es2022.error.d.js",
272
+ "types": "./node_modules/typescript/lib/lib.es2022.error.d.d.ts"
273
+ },
274
+ "./node_modules/typescript/lib/lib.es2022.full.d.ts": {
275
+ "import": "./node_modules/typescript/lib/lib.es2022.full.d.js",
276
+ "types": "./node_modules/typescript/lib/lib.es2022.full.d.d.ts"
277
+ },
278
+ "./node_modules/typescript/lib/lib.es2022.intl.d.ts": {
279
+ "import": "./node_modules/typescript/lib/lib.es2022.intl.d.js",
280
+ "types": "./node_modules/typescript/lib/lib.es2022.intl.d.d.ts"
281
+ },
282
+ "./node_modules/typescript/lib/lib.es2022.object.d.ts": {
283
+ "import": "./node_modules/typescript/lib/lib.es2022.object.d.js",
284
+ "types": "./node_modules/typescript/lib/lib.es2022.object.d.d.ts"
285
+ },
286
+ "./node_modules/typescript/lib/lib.es2022.regexp.d.ts": {
287
+ "import": "./node_modules/typescript/lib/lib.es2022.regexp.d.js",
288
+ "types": "./node_modules/typescript/lib/lib.es2022.regexp.d.d.ts"
289
+ },
290
+ "./node_modules/typescript/lib/lib.es2022.string.d.ts": {
291
+ "import": "./node_modules/typescript/lib/lib.es2022.string.d.js",
292
+ "types": "./node_modules/typescript/lib/lib.es2022.string.d.d.ts"
293
+ },
294
+ "./node_modules/typescript/lib/lib.es2023.array.d.ts": {
295
+ "import": "./node_modules/typescript/lib/lib.es2023.array.d.js",
296
+ "types": "./node_modules/typescript/lib/lib.es2023.array.d.d.ts"
297
+ },
298
+ "./node_modules/typescript/lib/lib.es2023.collection.d.ts": {
299
+ "import": "./node_modules/typescript/lib/lib.es2023.collection.d.js",
300
+ "types": "./node_modules/typescript/lib/lib.es2023.collection.d.d.ts"
301
+ },
302
+ "./node_modules/typescript/lib/lib.es2023.d.ts": {
303
+ "import": "./node_modules/typescript/lib/lib.es2023.d.js",
304
+ "types": "./node_modules/typescript/lib/lib.es2023.d.d.ts"
305
+ },
306
+ "./node_modules/typescript/lib/lib.es2023.full.d.ts": {
307
+ "import": "./node_modules/typescript/lib/lib.es2023.full.d.js",
308
+ "types": "./node_modules/typescript/lib/lib.es2023.full.d.d.ts"
309
+ },
310
+ "./node_modules/typescript/lib/lib.es2023.intl.d.ts": {
311
+ "import": "./node_modules/typescript/lib/lib.es2023.intl.d.js",
312
+ "types": "./node_modules/typescript/lib/lib.es2023.intl.d.d.ts"
313
+ },
314
+ "./node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts": {
315
+ "import": "./node_modules/typescript/lib/lib.es2024.arraybuffer.d.js",
316
+ "types": "./node_modules/typescript/lib/lib.es2024.arraybuffer.d.d.ts"
317
+ },
318
+ "./node_modules/typescript/lib/lib.es2024.collection.d.ts": {
319
+ "import": "./node_modules/typescript/lib/lib.es2024.collection.d.js",
320
+ "types": "./node_modules/typescript/lib/lib.es2024.collection.d.d.ts"
321
+ },
322
+ "./node_modules/typescript/lib/lib.es2024.d.ts": {
323
+ "import": "./node_modules/typescript/lib/lib.es2024.d.js",
324
+ "types": "./node_modules/typescript/lib/lib.es2024.d.d.ts"
325
+ },
326
+ "./node_modules/typescript/lib/lib.es2024.full.d.ts": {
327
+ "import": "./node_modules/typescript/lib/lib.es2024.full.d.js",
328
+ "types": "./node_modules/typescript/lib/lib.es2024.full.d.d.ts"
329
+ },
330
+ "./node_modules/typescript/lib/lib.es2024.object.d.ts": {
331
+ "import": "./node_modules/typescript/lib/lib.es2024.object.d.js",
332
+ "types": "./node_modules/typescript/lib/lib.es2024.object.d.d.ts"
333
+ },
334
+ "./node_modules/typescript/lib/lib.es2024.promise.d.ts": {
335
+ "import": "./node_modules/typescript/lib/lib.es2024.promise.d.js",
336
+ "types": "./node_modules/typescript/lib/lib.es2024.promise.d.d.ts"
337
+ },
338
+ "./node_modules/typescript/lib/lib.es2024.regexp.d.ts": {
339
+ "import": "./node_modules/typescript/lib/lib.es2024.regexp.d.js",
340
+ "types": "./node_modules/typescript/lib/lib.es2024.regexp.d.d.ts"
341
+ },
342
+ "./node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts": {
343
+ "import": "./node_modules/typescript/lib/lib.es2024.sharedmemory.d.js",
344
+ "types": "./node_modules/typescript/lib/lib.es2024.sharedmemory.d.d.ts"
345
+ },
346
+ "./node_modules/typescript/lib/lib.es2024.string.d.ts": {
347
+ "import": "./node_modules/typescript/lib/lib.es2024.string.d.js",
348
+ "types": "./node_modules/typescript/lib/lib.es2024.string.d.d.ts"
349
+ },
350
+ "./node_modules/typescript/lib/lib.es5.d.ts": {
351
+ "import": "./node_modules/typescript/lib/lib.es5.d.js",
352
+ "types": "./node_modules/typescript/lib/lib.es5.d.d.ts"
353
+ },
354
+ "./node_modules/typescript/lib/lib.es6.d.ts": {
355
+ "import": "./node_modules/typescript/lib/lib.es6.d.js",
356
+ "types": "./node_modules/typescript/lib/lib.es6.d.d.ts"
357
+ },
358
+ "./node_modules/typescript/lib/lib.esnext.array.d.ts": {
359
+ "import": "./node_modules/typescript/lib/lib.esnext.array.d.js",
360
+ "types": "./node_modules/typescript/lib/lib.esnext.array.d.d.ts"
361
+ },
362
+ "./node_modules/typescript/lib/lib.esnext.collection.d.ts": {
363
+ "import": "./node_modules/typescript/lib/lib.esnext.collection.d.js",
364
+ "types": "./node_modules/typescript/lib/lib.esnext.collection.d.d.ts"
365
+ },
366
+ "./node_modules/typescript/lib/lib.esnext.d.ts": {
367
+ "import": "./node_modules/typescript/lib/lib.esnext.d.js",
368
+ "types": "./node_modules/typescript/lib/lib.esnext.d.d.ts"
369
+ },
370
+ "./node_modules/typescript/lib/lib.esnext.decorators.d.ts": {
371
+ "import": "./node_modules/typescript/lib/lib.esnext.decorators.d.js",
372
+ "types": "./node_modules/typescript/lib/lib.esnext.decorators.d.d.ts"
373
+ },
374
+ "./node_modules/typescript/lib/lib.esnext.disposable.d.ts": {
375
+ "import": "./node_modules/typescript/lib/lib.esnext.disposable.d.js",
376
+ "types": "./node_modules/typescript/lib/lib.esnext.disposable.d.d.ts"
377
+ },
378
+ "./node_modules/typescript/lib/lib.esnext.error.d.ts": {
379
+ "import": "./node_modules/typescript/lib/lib.esnext.error.d.js",
380
+ "types": "./node_modules/typescript/lib/lib.esnext.error.d.d.ts"
381
+ },
382
+ "./node_modules/typescript/lib/lib.esnext.float16.d.ts": {
383
+ "import": "./node_modules/typescript/lib/lib.esnext.float16.d.js",
384
+ "types": "./node_modules/typescript/lib/lib.esnext.float16.d.d.ts"
385
+ },
386
+ "./node_modules/typescript/lib/lib.esnext.full.d.ts": {
387
+ "import": "./node_modules/typescript/lib/lib.esnext.full.d.js",
388
+ "types": "./node_modules/typescript/lib/lib.esnext.full.d.d.ts"
389
+ },
390
+ "./node_modules/typescript/lib/lib.esnext.intl.d.ts": {
391
+ "import": "./node_modules/typescript/lib/lib.esnext.intl.d.js",
392
+ "types": "./node_modules/typescript/lib/lib.esnext.intl.d.d.ts"
393
+ },
394
+ "./node_modules/typescript/lib/lib.esnext.iterator.d.ts": {
395
+ "import": "./node_modules/typescript/lib/lib.esnext.iterator.d.js",
396
+ "types": "./node_modules/typescript/lib/lib.esnext.iterator.d.d.ts"
397
+ },
398
+ "./node_modules/typescript/lib/lib.esnext.promise.d.ts": {
399
+ "import": "./node_modules/typescript/lib/lib.esnext.promise.d.js",
400
+ "types": "./node_modules/typescript/lib/lib.esnext.promise.d.d.ts"
401
+ },
402
+ "./node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts": {
403
+ "import": "./node_modules/typescript/lib/lib.esnext.sharedmemory.d.js",
404
+ "types": "./node_modules/typescript/lib/lib.esnext.sharedmemory.d.d.ts"
405
+ },
406
+ "./node_modules/typescript/lib/lib.scripthost.d.ts": {
407
+ "import": "./node_modules/typescript/lib/lib.scripthost.d.js",
408
+ "types": "./node_modules/typescript/lib/lib.scripthost.d.d.ts"
409
+ },
410
+ "./node_modules/typescript/lib/lib.webworker.asynciterable.d.ts": {
411
+ "import": "./node_modules/typescript/lib/lib.webworker.asynciterable.d.js",
412
+ "types": "./node_modules/typescript/lib/lib.webworker.asynciterable.d.d.ts"
413
+ },
414
+ "./node_modules/typescript/lib/lib.webworker.d.ts": {
415
+ "import": "./node_modules/typescript/lib/lib.webworker.d.js",
416
+ "types": "./node_modules/typescript/lib/lib.webworker.d.d.ts"
417
+ },
418
+ "./node_modules/typescript/lib/lib.webworker.importscripts.d.ts": {
419
+ "import": "./node_modules/typescript/lib/lib.webworker.importscripts.d.js",
420
+ "types": "./node_modules/typescript/lib/lib.webworker.importscripts.d.d.ts"
421
+ },
422
+ "./node_modules/typescript/lib/lib.webworker.iterable.d.ts": {
423
+ "import": "./node_modules/typescript/lib/lib.webworker.iterable.d.js",
424
+ "types": "./node_modules/typescript/lib/lib.webworker.iterable.d.d.ts"
425
+ },
426
+ "./node_modules/typescript/lib/tsserverlibrary.d.ts": {
427
+ "import": "./node_modules/typescript/lib/tsserverlibrary.d.js",
428
+ "types": "./node_modules/typescript/lib/tsserverlibrary.d.d.ts"
429
+ },
430
+ "./node_modules/typescript/lib/typescript.d.ts": {
431
+ "import": "./node_modules/typescript/lib/typescript.d.js",
432
+ "types": "./node_modules/typescript/lib/typescript.d.d.ts"
433
+ },
434
+ "./service.test.ts": {
435
+ "import": "./service.test.js",
436
+ "types": "./service.test.d.ts"
437
+ },
438
+ "./service.ts": {
439
+ "import": "./service.js",
440
+ "types": "./service.d.ts"
441
+ },
442
+ "./type.ts": {
443
+ "import": "./type.js",
444
+ "types": "./type.d.ts"
445
+ }
446
+ }
447
+ }
package/service.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import type { JWTPayload, JwtService, JwtServiceConfig } from './type.ts';
2
+ export declare const DEFAULT_JWT_ALGORITHM = "HS256";
3
+ export declare const DEFAULT_JWT_EXPIRATION_TIME = "30d";
4
+ export declare const createJwtService: <PAYLOAD extends JWTPayload>({ secret, algorithm, expirationTime, }: JwtServiceConfig) => JwtService<PAYLOAD>;
package/service.js ADDED
@@ -0,0 +1,34 @@
1
+ import { createCausedError } from '@dungarees/core/error.ts';
2
+ import { decodeJwt, jwtVerify, SignJWT } from 'jose';
3
+ export const DEFAULT_JWT_ALGORITHM = 'HS256';
4
+ export const DEFAULT_JWT_EXPIRATION_TIME = '30d';
5
+ export const createJwtService = ({ secret, algorithm = DEFAULT_JWT_ALGORITHM, expirationTime = DEFAULT_JWT_EXPIRATION_TIME, }) => {
6
+ const encodedSecret = new TextEncoder().encode(secret);
7
+ return {
8
+ createToken: async (payload) => await new SignJWT(payload)
9
+ .setProtectedHeader({ alg: algorithm })
10
+ .setIssuedAt()
11
+ .setExpirationTime(expirationTime)
12
+ .sign(encodedSecret),
13
+ verifyToken: async (token) => {
14
+ try {
15
+ const { payload } = await jwtVerify(token, encodedSecret);
16
+ return { payload };
17
+ }
18
+ catch (cause) {
19
+ throw createCausedError({ message: 'Could not parse JWT token.', cause });
20
+ }
21
+ },
22
+ // Reads the payload without verifying the signature, so the caller must not trust it for
23
+ // anything but display. An undecodable token is reported as no payload rather than as a throw,
24
+ // because a caller reaching for a token it cannot read has nothing to recover from.
25
+ decodeToken: (token) => {
26
+ try {
27
+ return { payload: decodeJwt(token) };
28
+ }
29
+ catch {
30
+ return { payload: undefined };
31
+ }
32
+ },
33
+ };
34
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,94 @@
1
+ import { createFakeJwtService } from './fake.js';
2
+ import { createJwtService } from './service.js';
3
+ import { expect, test } from 'vitest';
4
+ const SECRET = 'secret';
5
+ test('a token created by the service verifies back to its payload', async () => {
6
+ const jwt = createJwtService({ secret: SECRET });
7
+ const token = await jwt.createToken({ id: 1 });
8
+ expect((await jwt.verifyToken(token)).payload.id).toBe(1);
9
+ });
10
+ test('createToken produces the three dot-separated parts of a JWT', async () => {
11
+ const jwt = createJwtService({ secret: SECRET });
12
+ const token = await jwt.createToken({ id: 1 });
13
+ expect(token.split('.')).toHaveLength(3);
14
+ });
15
+ test('createToken stamps an issued-at and an expiry on the token', async () => {
16
+ const jwt = createJwtService({ secret: SECRET });
17
+ const token = await jwt.createToken({ id: 1 });
18
+ const { payload } = await jwt.verifyToken(token);
19
+ expect(payload.iat).toEqual(expect.any(Number));
20
+ expect(payload.exp).toEqual(expect.any(Number));
21
+ });
22
+ test('verifyToken rejects a string that is not a token at all', async () => {
23
+ const jwt = createJwtService({ secret: SECRET });
24
+ await expect(jwt.verifyToken('invalid')).rejects.toThrow('Could not parse JWT token.');
25
+ });
26
+ test('verifyToken rejects a token signed with a different secret', async () => {
27
+ const signed = await createJwtService({ secret: 'other-secret' }).createToken({
28
+ id: 1,
29
+ });
30
+ const jwt = createJwtService({ secret: SECRET });
31
+ await expect(jwt.verifyToken(signed)).rejects.toThrow('Could not parse JWT token.');
32
+ });
33
+ test('verifyToken rejects a token whose payload has been tampered with', async () => {
34
+ const jwt = createJwtService({ secret: SECRET });
35
+ const [header, , signature] = (await jwt.createToken({ id: 1 })).split('.');
36
+ const tamperedPayload = Buffer.from(JSON.stringify({ id: 2 })).toString('base64url');
37
+ await expect(jwt.verifyToken(`${header}.${tamperedPayload}.${signature}`)).rejects.toThrow('Could not parse JWT token.');
38
+ });
39
+ test('verifyToken keeps the underlying failure as the cause', async () => {
40
+ const jwt = createJwtService({ secret: SECRET });
41
+ await expect(jwt.verifyToken('invalid')).rejects.toHaveProperty('cause');
42
+ });
43
+ test('verifyToken rejects an expired token', async () => {
44
+ const jwt = createJwtService({ secret: SECRET, expirationTime: '0s' });
45
+ const token = await jwt.createToken({ id: 1 });
46
+ await expect(jwt.verifyToken(token)).rejects.toThrow('Could not parse JWT token.');
47
+ });
48
+ test('decodeToken reads the payload without checking the signature', async () => {
49
+ const signed = await createJwtService({ secret: 'other-secret' }).createToken({
50
+ id: 1,
51
+ });
52
+ const jwt = createJwtService({ secret: SECRET });
53
+ expect(jwt.decodeToken(signed).payload?.id).toBe(1);
54
+ });
55
+ test('decodeToken reports an undecodable token as no payload rather than throwing', () => {
56
+ const jwt = createJwtService({ secret: SECRET });
57
+ expect(jwt.decodeToken('invalid')).toEqual({ payload: undefined });
58
+ });
59
+ test('the fake service round-trips a payload', async () => {
60
+ const jwt = createFakeJwtService();
61
+ const token = await jwt.createToken({ id: 1 });
62
+ expect((await jwt.verifyToken(token)).payload).toEqual({ id: 1 });
63
+ });
64
+ test('the fake service decodes its own token', async () => {
65
+ const jwt = createFakeJwtService();
66
+ const token = await jwt.createToken({ id: 1 });
67
+ expect(jwt.decodeToken(token).payload).toEqual({ id: 1 });
68
+ });
69
+ test('the fake service rejects a payload it was told is invalid', async () => {
70
+ const jwt = createFakeJwtService([{ id: 2 }]);
71
+ const token = await jwt.createToken({ id: 2 });
72
+ await expect(jwt.verifyToken(token)).rejects.toThrow('Could not parse JWT token.');
73
+ });
74
+ test('the fake service still accepts payloads it was not told about', async () => {
75
+ const jwt = createFakeJwtService([{ id: 2 }]);
76
+ const token = await jwt.createToken({ id: 1 });
77
+ expect((await jwt.verifyToken(token)).payload).toEqual({ id: 1 });
78
+ });
79
+ test('the fake service rejects a token that is not one of its own', async () => {
80
+ const jwt = createFakeJwtService();
81
+ await expect(jwt.verifyToken('invalid')).rejects.toThrow('Could not parse JWT token.');
82
+ });
83
+ test('the fake service reports an undecodable token as no payload', () => {
84
+ const jwt = createFakeJwtService();
85
+ expect(jwt.decodeToken('invalid')).toEqual({ payload: undefined });
86
+ });
87
+ test('the fake service rejects a token holding a JSON scalar rather than a payload', async () => {
88
+ const jwt = createFakeJwtService();
89
+ await expect(jwt.verifyToken('42')).rejects.toThrow('Could not parse JWT token.');
90
+ });
91
+ test('the fake service rejects a token holding a JSON array', () => {
92
+ const jwt = createFakeJwtService();
93
+ expect(jwt.decodeToken('[1,2]')).toEqual({ payload: undefined });
94
+ });
package/type.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ import type { JWTPayload as JoseJWTPayload } from 'jose';
2
+ export type JWTPayload = JoseJWTPayload;
3
+ export type VerifiedPayload<PAYLOAD extends JWTPayload> = PAYLOAD & JWTPayload;
4
+ export type JwtService<PAYLOAD extends JWTPayload> = {
5
+ decodeToken: (token: string) => {
6
+ payload: VerifiedPayload<PAYLOAD> | undefined;
7
+ };
8
+ verifyToken: (token: string) => Promise<{
9
+ payload: VerifiedPayload<PAYLOAD>;
10
+ }>;
11
+ createToken: (payload: PAYLOAD) => Promise<string>;
12
+ };
13
+ export type JwtServiceConfig = {
14
+ secret: string;
15
+ algorithm?: string;
16
+ expirationTime?: string | number;
17
+ };
package/type.js ADDED
@@ -0,0 +1 @@
1
+ export {};