ecwt 0.2.0-beta.3 → 0.2.0-beta.5

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/README.md CHANGED
@@ -76,7 +76,8 @@ In our example, we use [valibot](https://valibot.dev) library.
76
76
  ```javascript
77
77
  import * as v from 'valibot';
78
78
 
79
- const schema = (value) => v.parse(
79
+ const schema = v.parse.bind(
80
+ null,
80
81
  v.object({
81
82
  user_id: v.number([
82
83
  v.maxValue(10),
@@ -85,7 +86,6 @@ const schema = (value) => v.parse(
85
86
  v.maxLength(10),
86
87
  ]),
87
88
  }),
88
- value,
89
89
  );
90
90
  ```
91
91
 
@@ -197,6 +197,30 @@ If the token is invalid, throws `EcwtInvalidError` which contains `Ecwt` instanc
197
197
  const ecwt = await ecwtFactory.verify(token);
198
198
  ```
199
199
 
200
+ #### Class method `safeVerify`
201
+
202
+ ```typescript
203
+ safeVerify(
204
+ token: string,
205
+ ): Promise<{
206
+ success: boolean,
207
+ ecwt: Ecwt | null,
208
+ }>
209
+ ```
210
+
211
+ The same method as `verify`, but does not throw an error if the token is invalid, expired or revoked.
212
+
213
+ Property `success` is `true` if the token is valid.
214
+
215
+ Property `ecwt` is `null` if the token cannot be parsed, otherwise it contains `Ecwt` instance.
216
+
217
+ ```javascript
218
+ const {
219
+ success,
220
+ ecwt,
221
+ } = await ecwtFactory.safeVerify(token);
222
+ ```
223
+
200
224
  ### `Ecwt`
201
225
 
202
226
  Represents the token. Its counstructor cannot be called by the user.
package/dist/ecwt.cjs CHANGED
@@ -229,17 +229,17 @@ var EcwtFactory = class {
229
229
  * @param {{ [key: string]: number }} [param0.options.senml_key_map] Payload object keys mapped for their SenML keys.
230
230
  */
231
231
  constructor({
232
- redisClient: redisClient2 = null,
233
- lruCache = null,
232
+ redisClient: redisClient2,
233
+ lruCache,
234
234
  snowflakeFactory,
235
235
  options: {
236
- namespace = null,
236
+ namespace,
237
237
  key,
238
238
  validator,
239
239
  senml_key_map
240
240
  }
241
241
  }) {
242
- if (redisClient2 !== null && (redisClient2.constructor.name !== redis_client_constructor_name || getAllKeysList(redisClient2) !== redis_client_keys)) {
242
+ if (redisClient2 !== void 0 && (redisClient2.constructor.name !== redis_client_constructor_name || getAllKeysList(redisClient2) !== redis_client_keys)) {
243
243
  throw new InvalidPackageInstanceError(
244
244
  "redisClient",
245
245
  "Commander extends RedisClient",
@@ -247,7 +247,7 @@ var EcwtFactory = class {
247
247
  );
248
248
  }
249
249
  this.#redisClient = redisClient2;
250
- if (lruCache !== null && lruCache instanceof import_lru_cache.LRUCache !== true) {
250
+ if (lruCache !== void 0 && lruCache instanceof import_lru_cache.LRUCache !== true) {
251
251
  throw new InvalidPackageInstanceError(
252
252
  "lruCache",
253
253
  "LRUCache",
@@ -277,11 +277,11 @@ var EcwtFactory = class {
277
277
  * @async
278
278
  * @param {object} data Data to be stored in token.
279
279
  * @param {object} [options] -
280
- * @param {number} [options.ttl] Time to live in seconds. By default, token will never expire.
280
+ * @param {number | null} [options.ttl] Time to live in seconds. By default, token will never expire.
281
281
  * @returns {Promise<Ecwt>} -
282
282
  */
283
283
  async create(data, {
284
- ttl
284
+ ttl = null
285
285
  } = {}) {
286
286
  if (typeof this.#validator === "function") {
287
287
  data = this.#validator(data);
@@ -319,6 +319,11 @@ var EcwtFactory = class {
319
319
  }
320
320
  );
321
321
  }
322
+ /**
323
+ * Sets data to cache.
324
+ * @param {string} token String representation of token.
325
+ * @param {object} data Data to be stored in cache.
326
+ */
322
327
  #setCache(token, data) {
323
328
  this.#lruCache?.set(
324
329
  token,
@@ -414,10 +419,10 @@ var EcwtFactory = class {
414
419
  * Parses token without throwing errors.
415
420
  * @async
416
421
  * @param {string} token String representation of token.
417
- * @returns {Promise<{ success: boolean, ecwt: Ecwt | null }>} Returns whether token was parsed and verified successfully and Ecwt if parsed.
422
+ * @returns {Promise<{ success: true, ecwt: Ecwt } | { success: false, ecwt: Ecwt | null }>} Returns whether token was parsed and verified successfully and Ecwt if parsed.
418
423
  */
419
424
  async safeVerify(token) {
420
- let ecwt;
425
+ let ecwt = null;
421
426
  try {
422
427
  ecwt = await this.verify(token);
423
428
  return {
@@ -446,7 +451,7 @@ var EcwtFactory = class {
446
451
  * @param {object} options -
447
452
  * @param {string} options.token_id -
448
453
  * @param {number} options.ts_ms_created -
449
- * @param {number} options.ttl_initial -
454
+ * @param {number | null} options.ttl_initial -
450
455
  * @returns {Promise<void>} -
451
456
  */
452
457
  async _revoke({
@@ -458,12 +463,17 @@ var EcwtFactory = class {
458
463
  ttl_initial = ttl_initial ?? Number.MAX_SAFE_INTEGER;
459
464
  const ts_ms_expired = ts_ms_created + ttl_initial * 1e3;
460
465
  if (ts_ms_expired > Date.now()) {
461
- await this.#redisClient.sendCommand([
466
+ await this.#redisClient.MULTI().addCommand([
462
467
  "ZADD",
463
468
  this.#redis_keys.revoked,
464
469
  String(ts_ms_expired),
465
470
  token_id
466
- ]);
471
+ ]).addCommand([
472
+ "ZREMRANGEBYSCORE",
473
+ this.#redis_keys.revoked,
474
+ "-inf",
475
+ String(Date.now())
476
+ ]).EXEC();
467
477
  }
468
478
  } else {
469
479
  console.warn("[ecwt] Redis client is not provided. Tokens cannot be revoked.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ecwt",
3
- "version": "0.2.0-beta.3",
3
+ "version": "0.2.0-beta.5",
4
4
  "description": "Encrypted CBOR-encoded Web Token",
5
5
  "main": "src/main.js",
6
6
  "type": "module",
@@ -32,8 +32,8 @@
32
32
  "eslint-plugin-node": "11.1.0",
33
33
  "eslint-plugin-promise": "6.1.1",
34
34
  "eslint-plugin-unicorn": "47.0.0",
35
- "valibot": "^0.24.1",
36
- "vitest": "1.3.1"
35
+ "valibot": "0.33",
36
+ "vitest": "1.6"
37
37
  },
38
38
  "scripts": {
39
39
  "test": "bun run redis-up && bun test && npm run test-node",
package/src/factory.js CHANGED
@@ -1,4 +1,6 @@
1
1
 
2
+ // @ts-check
3
+
2
4
  import { SnowflakeFactory } from '@kirick/snowflake';
3
5
  import {
4
6
  Encoder as CborEncoder,
@@ -58,18 +60,18 @@ export class EcwtFactory {
58
60
  * @param {{ [key: string]: number }} [param0.options.senml_key_map] Payload object keys mapped for their SenML keys.
59
61
  */
60
62
  constructor({
61
- redisClient = null,
62
- lruCache = null,
63
+ redisClient,
64
+ lruCache,
63
65
  snowflakeFactory,
64
66
  options: {
65
- namespace = null,
67
+ namespace,
66
68
  key,
67
69
  validator,
68
70
  senml_key_map,
69
71
  },
70
72
  }) {
71
73
  if (
72
- redisClient !== null
74
+ redisClient !== undefined
73
75
  && (
74
76
  redisClient.constructor.name !== redis_client_constructor_name
75
77
  || getAllKeysList(redisClient) !== redis_client_keys
@@ -84,7 +86,7 @@ export class EcwtFactory {
84
86
  this.#redisClient = redisClient;
85
87
 
86
88
  if (
87
- lruCache !== null
89
+ lruCache !== undefined
88
90
  && lruCache instanceof LRUCache !== true
89
91
  ) {
90
92
  throw new InvalidPackageInstanceError(
@@ -122,13 +124,13 @@ export class EcwtFactory {
122
124
  * @async
123
125
  * @param {object} data Data to be stored in token.
124
126
  * @param {object} [options] -
125
- * @param {number} [options.ttl] Time to live in seconds. By default, token will never expire.
127
+ * @param {number | null} [options.ttl] Time to live in seconds. By default, token will never expire.
126
128
  * @returns {Promise<Ecwt>} -
127
129
  */
128
130
  async create(
129
131
  data,
130
132
  {
131
- ttl,
133
+ ttl = null,
132
134
  } = {},
133
135
  ) {
134
136
  if (typeof this.#validator === 'function') {
@@ -181,6 +183,11 @@ export class EcwtFactory {
181
183
  );
182
184
  }
183
185
 
186
+ /**
187
+ * Sets data to cache.
188
+ * @param {string} token String representation of token.
189
+ * @param {object} data Data to be stored in cache.
190
+ */
184
191
  #setCache(token, data) {
185
192
  this.#lruCache?.set(
186
193
  token,
@@ -304,10 +311,10 @@ export class EcwtFactory {
304
311
  * Parses token without throwing errors.
305
312
  * @async
306
313
  * @param {string} token String representation of token.
307
- * @returns {Promise<{ success: boolean, ecwt: Ecwt | null }>} Returns whether token was parsed and verified successfully and Ecwt if parsed.
314
+ * @returns {Promise<{ success: true, ecwt: Ecwt } | { success: false, ecwt: Ecwt | null }>} Returns whether token was parsed and verified successfully and Ecwt if parsed.
308
315
  */
309
316
  async safeVerify(token) {
310
- let ecwt;
317
+ let ecwt = null;
311
318
  try {
312
319
  ecwt = await this.verify(token);
313
320
 
@@ -341,7 +348,7 @@ export class EcwtFactory {
341
348
  * @param {object} options -
342
349
  * @param {string} options.token_id -
343
350
  * @param {number} options.ts_ms_created -
344
- * @param {number} options.ttl_initial -
351
+ * @param {number | null} options.ttl_initial -
345
352
  * @returns {Promise<void>} -
346
353
  */
347
354
  async _revoke({
@@ -354,12 +361,26 @@ export class EcwtFactory {
354
361
 
355
362
  const ts_ms_expired = ts_ms_created + (ttl_initial * 1000);
356
363
  if (ts_ms_expired > Date.now()) {
357
- await this.#redisClient.sendCommand([
358
- 'ZADD',
359
- this.#redis_keys.revoked,
360
- String(ts_ms_expired),
361
- token_id,
362
- ]);
364
+ // await this.#redisClient.sendCommand([
365
+ // 'ZADD',
366
+ // this.#redis_keys.revoked,
367
+ // String(ts_ms_expired),
368
+ // token_id,
369
+ // ]);
370
+ await this.#redisClient.MULTI()
371
+ .addCommand([
372
+ 'ZADD',
373
+ this.#redis_keys.revoked,
374
+ String(ts_ms_expired),
375
+ token_id,
376
+ ])
377
+ .addCommand([
378
+ 'ZREMRANGEBYSCORE',
379
+ this.#redis_keys.revoked,
380
+ '-inf',
381
+ String(Date.now()),
382
+ ])
383
+ .EXEC();
363
384
  }
364
385
  }
365
386
  else {
package/src/main.js CHANGED
@@ -1,4 +1,6 @@
1
1
 
2
+ // @ts-check
3
+
2
4
  export { EcwtFactory } from './factory.js';
3
5
  export { Ecwt } from './token.js';
4
6
  export {
package/src/token.js CHANGED
@@ -1,4 +1,6 @@
1
1
 
2
+ // @ts-check
3
+
2
4
  import { toSeconds } from './utils/time.js';
3
5
 
4
6
  /**
@@ -1,4 +1,6 @@
1
1
 
2
+ // @ts-check
3
+
2
4
  import basex from 'base-x';
3
5
 
4
6
  export const base62 = basex('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
@@ -1,4 +1,6 @@
1
1
 
2
+ // @ts-check
3
+
2
4
  export class InvalidPackageInstanceError extends TypeError {
3
5
  constructor(property, class_name, package_name) {
4
6
  super(`Value ${property} must be an instance of ${class_name} from package "${package_name}". That error is probably caused by two separate installations of "${package_name}". Please, make sure that "${package_name}" in your project is matches "peerDependencies" of "ecwt" package.`);
package/src/utils/time.js CHANGED
@@ -1,4 +1,6 @@
1
1
 
2
+ // @ts-check
3
+
2
4
  /**
3
5
  * Convert timestamp in seconds to milliseconds.
4
6
  * @param {*} value Timestamp in milliseconds.