ecwt 0.2.0-beta.5 → 0.2.1-beta.2

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.
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -51,21 +52,7 @@ function toSeconds(value) {
51
52
  }
52
53
 
53
54
  // src/token.js
54
- function assign(target, key, value) {
55
- Object.defineProperty(
56
- target,
57
- key,
58
- {
59
- value,
60
- enumerable: true,
61
- writable: false,
62
- configurable: false
63
- }
64
- );
65
- }
66
55
  var Ecwt = class {
67
- #ecwtFactory;
68
- #ttl_initial;
69
56
  /**
70
57
  * Token string representation.
71
58
  * @type {string}
@@ -92,17 +79,21 @@ var Ecwt = class {
92
79
  ts_expired;
93
80
  /**
94
81
  * Data stored in token.
95
- * @type {{ [key: string]: any }}
82
+ * @type {D}
96
83
  * @readonly
97
84
  */
98
85
  data;
86
+ /** @type {EcwtFactory} */
87
+ #ecwtFactory;
88
+ /** @type {number | null} */
89
+ #ttl_initial;
99
90
  /**
100
91
  * @param {EcwtFactory} ecwtFactory -
101
92
  * @param {object} options -
102
93
  * @param {string} options.token String representation of token.
103
94
  * @param {Snowflake} options.snowflake -
104
- * @param {number?} options.ttl_initial Time to live in seconds at the moment of token creation.
105
- * @param {object} options.data Data stored in token.
95
+ * @param {number | null} options.ttl_initial Time to live in seconds at the moment of token creation.
96
+ * @param {D} options.data Data stored in token.
106
97
  */
107
98
  constructor(ecwtFactory, {
108
99
  token,
@@ -112,23 +103,11 @@ var Ecwt = class {
112
103
  }) {
113
104
  this.#ecwtFactory = ecwtFactory;
114
105
  this.#ttl_initial = ttl_initial;
115
- assign(this, "token", token);
116
- assign(
117
- this,
118
- "id",
119
- snowflake.toBase62()
120
- );
121
- assign(this, "snowflake", snowflake);
122
- assign(
123
- this,
124
- "ts_expired",
125
- this.#getTimestampExpired()
126
- );
127
- assign(
128
- this,
129
- "data",
130
- Object.freeze(data)
131
- );
106
+ this.token = token;
107
+ this.id = snowflake.toBase62();
108
+ this.snowflake = snowflake;
109
+ this.ts_expired = this.#getTimestampExpired();
110
+ this.data = Object.freeze(data);
132
111
  }
133
112
  #getTimestampExpired() {
134
113
  if (this.#ttl_initial === null) {
@@ -166,6 +145,11 @@ var base62 = (0, import_base_x.default)("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabc
166
145
 
167
146
  // src/utils/errors.js
168
147
  var InvalidPackageInstanceError = class extends TypeError {
148
+ /**
149
+ * @param {string} property -
150
+ * @param {string} class_name -
151
+ * @param {string} package_name -
152
+ */
169
153
  constructor(property, class_name, package_name) {
170
154
  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.`);
171
155
  }
@@ -176,24 +160,20 @@ var EcwtParseError = class extends Error {
176
160
  }
177
161
  };
178
162
  var EcwtInvalidError = class extends Error {
163
+ message = "Ecwt token is invalid.";
164
+ /**
165
+ * @param {Ecwt} ecwt -
166
+ */
179
167
  constructor(ecwt) {
180
- super("Ecwt token is invalid.");
168
+ super();
181
169
  this.ecwt = ecwt;
182
170
  }
183
171
  };
184
172
  var EcwtExpiredError = class extends EcwtInvalidError {
185
- constructor(ecwt) {
186
- super();
187
- this.ecwt = ecwt;
188
- this.message = "Ecwt is expired.";
189
- }
173
+ message = "Ecwt is expired.";
190
174
  };
191
175
  var EcwtRevokedError = class extends EcwtInvalidError {
192
- constructor(ecwt) {
193
- super();
194
- this.ecwt = ecwt;
195
- this.message = "Ecwt is revoked.";
196
- }
176
+ message = "Ecwt is revoked.";
197
177
  };
198
178
 
199
179
  // src/factory.js
@@ -212,21 +192,21 @@ var EcwtFactory = class {
212
192
  #redisClient;
213
193
  #lruCache;
214
194
  #snowflakeFactory;
215
- #redis_keys = {};
195
+ #redis_key_revoked;
216
196
  #encryption_key;
217
197
  #validator;
218
- #cborEncoder;
198
+ /** @type {CborEncoder | null} */
199
+ #cborEncoder = null;
219
200
  /**
220
- *
221
201
  * @param {object} param0 -
222
- * @param {import('redis').RedisClientType} [param0.redisClient] RedisClient instance. If not provided, tokens will not be revoked and cannot be checked for revocation.
223
- * @param {LRUCache} [param0.lruCache] LRUCache instance. If not provided, tokens will be decrypted every time they are verified.
202
+ * @param {import('redis').RedisClientType<import('redis').RedisModules, import('redis').RedisFunctions, import('redis').RedisScripts>} [param0.redisClient] RedisClient instance. If not provided, tokens will not be revoked and cannot be checked for revocation.
203
+ * @param {LRUCache<string, CacheValue>} [param0.lruCache] LRUCache instance. If not provided, tokens will be decrypted every time they are verified.
224
204
  * @param {SnowflakeFactory} param0.snowflakeFactory SnowflakeFactory instance.
225
205
  * @param {object} param0.options -
226
206
  * @param {string} [param0.options.namespace] Namespace for Redis keys.
227
207
  * @param {Buffer} param0.options.key Encryption key, 64 bytes
228
208
  * @param {(value: any) => any} [param0.options.validator] Validator for token data. Should return validated value or throw an error.
229
- * @param {{ [key: string]: number }} [param0.options.senml_key_map] Payload object keys mapped for their SenML keys.
209
+ * @param {Record<string, number>} [param0.options.senml_key_map] Payload object keys mapped for their SenML keys.
230
210
  */
231
211
  constructor({
232
212
  redisClient: redisClient2,
@@ -263,7 +243,7 @@ var EcwtFactory = class {
263
243
  );
264
244
  }
265
245
  this.#snowflakeFactory = snowflakeFactory;
266
- this.#redis_keys.revoked = `${REDIS_PREFIX}${namespace}:revoked`;
246
+ this.#redis_key_revoked = `${REDIS_PREFIX}${namespace}:revoked`;
267
247
  this.#encryption_key = key;
268
248
  this.#validator = validator;
269
249
  if (senml_key_map) {
@@ -275,7 +255,7 @@ var EcwtFactory = class {
275
255
  /**
276
256
  * Creates new token.
277
257
  * @async
278
- * @param {object} data Data to be stored in token.
258
+ * @param {D} data Data to be stored in token.
279
259
  * @param {object} [options] -
280
260
  * @param {number | null} [options.ttl] Time to live in seconds. By default, token will never expire.
281
261
  * @returns {Promise<Ecwt>} -
@@ -322,14 +302,14 @@ var EcwtFactory = class {
322
302
  /**
323
303
  * Sets data to cache.
324
304
  * @param {string} token String representation of token.
325
- * @param {object} data Data to be stored in cache.
305
+ * @param {CacheValue} cache_value Data to be stored in cache.
326
306
  */
327
- #setCache(token, data) {
307
+ #setCache(token, cache_value) {
328
308
  this.#lruCache?.set(
329
309
  token,
330
- data,
331
- {
332
- ttl: data.ttl * 1e3
310
+ cache_value,
311
+ cache_value.ttl_initial === null ? void 0 : {
312
+ ttl: cache_value.ttl_initial * 1e3
333
313
  }
334
314
  );
335
315
  }
@@ -406,7 +386,7 @@ var EcwtFactory = class {
406
386
  }
407
387
  if (this.#redisClient) {
408
388
  const score = await this.#redisClient.ZSCORE(
409
- this.#redis_keys.revoked,
389
+ this.#redis_key_revoked,
410
390
  ecwt.id
411
391
  );
412
392
  if (score !== null) {
@@ -465,12 +445,12 @@ var EcwtFactory = class {
465
445
  if (ts_ms_expired > Date.now()) {
466
446
  await this.#redisClient.MULTI().addCommand([
467
447
  "ZADD",
468
- this.#redis_keys.revoked,
448
+ this.#redis_key_revoked,
469
449
  String(ts_ms_expired),
470
450
  token_id
471
451
  ]).addCommand([
472
452
  "ZREMRANGEBYSCORE",
473
- this.#redis_keys.revoked,
453
+ this.#redis_key_revoked,
474
454
  "-inf",
475
455
  String(Date.now())
476
456
  ]).EXEC();
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "ecwt",
3
- "version": "0.2.0-beta.5",
3
+ "version": "0.2.1-beta.2",
4
4
  "description": "Encrypted CBOR-encoded Web Token",
5
- "main": "src/main.js",
6
5
  "type": "module",
6
+ "main": "src/main.js",
7
+ "types": "types/main.d.ts",
7
8
  "exports": {
8
9
  ".": {
9
10
  "import": "./src/main.js",
10
- "require": "./dist/ecwt.cjs"
11
+ "require": "./dist/main.cjs"
11
12
  }
12
13
  },
13
14
  "engines": {
@@ -16,35 +17,36 @@
16
17
  "dependencies": {
17
18
  "base-x": "4.0.0",
18
19
  "cbor-x": "1.5.6",
19
- "evilcrypt": "0.2.0-beta.4"
20
+ "evilcrypt": "0.2.1-beta.1"
20
21
  },
21
22
  "peerDependencies": {
22
- "@kirick/snowflake": "^0.2.1-beta.1",
23
+ "@kirick/snowflake": "^0.2.2-beta.2",
23
24
  "lru-cache": "^9 || ^10",
24
25
  "redis": "^4"
25
26
  },
26
27
  "devDependencies": {
27
28
  "@babel/eslint-parser": "7.21.8",
29
+ "@types/node": "^20.14.9",
28
30
  "eslint": "8.41.0",
29
31
  "eslint-config-xo": "0.43.1",
30
32
  "eslint-plugin-import": "2.27.5",
31
- "eslint-plugin-jsdoc": "46.9.1",
33
+ "eslint-plugin-jsdoc": "46.5.0",
32
34
  "eslint-plugin-node": "11.1.0",
33
35
  "eslint-plugin-promise": "6.1.1",
34
36
  "eslint-plugin-unicorn": "47.0.0",
35
- "valibot": "0.33",
36
- "vitest": "1.6"
37
+ "valibot": "^0.33",
38
+ "vitest": "^1.6"
37
39
  },
38
40
  "scripts": {
39
- "test": "bun run redis-up && bun test && npm run test-node",
40
- "test-node": "vitest run --no-file-parallelism",
41
- "coverage": "bun run redis-up && bun test --coverage",
42
- "build": "bun run build-cjs",
43
- "build-cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/ecwt.cjs src/main.js",
44
- "npm-publish": "bun run build && bun run eslint . && bun run test && npm publish; bun run redis-down",
45
- "npm-publish-beta": "bun run build && bun run eslint . && bun run test && npm publish --tag beta; bun run redis-down",
46
- "redis-up": "docker ps | grep test-redis-ecwt-test >/dev/null || docker run --rm -d -p 16274:6379 --name test-redis-ecwt-test redis:7-alpine",
47
- "redis-down": "docker stop test-redis-ecwt-test"
41
+ "test": "export REDIS_PORT=16274 ; bun run redis:up && npm run test:vitest && bun test --coverage ; bun run redis:down",
42
+ "test:vitest": "vitest run --no-file-parallelism",
43
+ "build": "bun run build:types && bun run build:cjs",
44
+ "build:cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/main.cjs src/main.js",
45
+ "build:types": "bunx tsc --skipLibCheck --declaration --emitDeclarationOnly --outDir types",
46
+ "lint": "eslint . && bunx tsc --skipLibCheck --noemit",
47
+ "publish:npm": "bun run build && bun run lint && bun run test && npm publish",
48
+ "redis:up": "docker ps | grep test-ecwt >/dev/null || docker run --rm -d -p $REDIS_PORT:6379 --name test-ecwt redis:7-alpine",
49
+ "redis:down": "docker stop test-ecwt || true"
48
50
  },
49
51
  "repository": {
50
52
  "type": "git",
package/src/factory.js CHANGED
@@ -1,5 +1,13 @@
1
1
 
2
- // @ts-check
2
+ /**
3
+ * @typedef {import('@kirick/snowflake').Snowflake} Snowflake
4
+ */
5
+ /**
6
+ * @typedef {object} CacheValue
7
+ * @property {Snowflake} snowflake -
8
+ * @property {number | null} ttl_initial -
9
+ * @property {Record<string, any>} data -
10
+ */
3
11
 
4
12
  import { SnowflakeFactory } from '@kirick/snowflake';
5
13
  import {
@@ -22,7 +30,10 @@ import {
22
30
 
23
31
  const REDIS_PREFIX = '@ecwt:';
24
32
 
25
- // eslint-disable-next-line jsdoc/require-jsdoc
33
+ /**
34
+ * @param {object} value -
35
+ * @returns {string} -
36
+ */
26
37
  function getAllKeysList(value) {
27
38
  const keys = [];
28
39
  // eslint-disable-next-line guard-for-in
@@ -36,28 +47,31 @@ const redisClient = createClient();
36
47
  const redis_client_constructor_name = redisClient.constructor.name;
37
48
  const redis_client_keys = getAllKeysList(redisClient);
38
49
 
50
+ /**
51
+ * @template {Record<string, any>} [D=Record<string, any>]
52
+ */
39
53
  export class EcwtFactory {
40
54
  #redisClient;
41
55
  #lruCache;
42
56
  #snowflakeFactory;
43
57
 
44
- #redis_keys = {};
58
+ #redis_key_revoked;
45
59
  #encryption_key;
46
60
 
47
61
  #validator;
48
- #cborEncoder;
62
+ /** @type {CborEncoder | null} */
63
+ #cborEncoder = null;
49
64
 
50
65
  /**
51
- *
52
66
  * @param {object} param0 -
53
- * @param {import('redis').RedisClientType} [param0.redisClient] RedisClient instance. If not provided, tokens will not be revoked and cannot be checked for revocation.
54
- * @param {LRUCache} [param0.lruCache] LRUCache instance. If not provided, tokens will be decrypted every time they are verified.
67
+ * @param {import('redis').RedisClientType<import('redis').RedisModules, import('redis').RedisFunctions, import('redis').RedisScripts>} [param0.redisClient] RedisClient instance. If not provided, tokens will not be revoked and cannot be checked for revocation.
68
+ * @param {LRUCache<string, CacheValue>} [param0.lruCache] LRUCache instance. If not provided, tokens will be decrypted every time they are verified.
55
69
  * @param {SnowflakeFactory} param0.snowflakeFactory SnowflakeFactory instance.
56
70
  * @param {object} param0.options -
57
71
  * @param {string} [param0.options.namespace] Namespace for Redis keys.
58
72
  * @param {Buffer} param0.options.key Encryption key, 64 bytes
59
73
  * @param {(value: any) => any} [param0.options.validator] Validator for token data. Should return validated value or throw an error.
60
- * @param {{ [key: string]: number }} [param0.options.senml_key_map] Payload object keys mapped for their SenML keys.
74
+ * @param {Record<string, number>} [param0.options.senml_key_map] Payload object keys mapped for their SenML keys.
61
75
  */
62
76
  constructor({
63
77
  redisClient,
@@ -106,7 +120,7 @@ export class EcwtFactory {
106
120
  }
107
121
  this.#snowflakeFactory = snowflakeFactory;
108
122
 
109
- this.#redis_keys.revoked = `${REDIS_PREFIX}${namespace}:revoked`;
123
+ this.#redis_key_revoked = `${REDIS_PREFIX}${namespace}:revoked`;
110
124
 
111
125
  this.#encryption_key = key;
112
126
 
@@ -122,7 +136,7 @@ export class EcwtFactory {
122
136
  /**
123
137
  * Creates new token.
124
138
  * @async
125
- * @param {object} data Data to be stored in token.
139
+ * @param {D} data Data to be stored in token.
126
140
  * @param {object} [options] -
127
141
  * @param {number | null} [options.ttl] Time to live in seconds. By default, token will never expire.
128
142
  * @returns {Promise<Ecwt>} -
@@ -186,15 +200,17 @@ export class EcwtFactory {
186
200
  /**
187
201
  * Sets data to cache.
188
202
  * @param {string} token String representation of token.
189
- * @param {object} data Data to be stored in cache.
203
+ * @param {CacheValue} cache_value Data to be stored in cache.
190
204
  */
191
- #setCache(token, data) {
205
+ #setCache(token, cache_value) {
192
206
  this.#lruCache?.set(
193
207
  token,
194
- data,
195
- {
196
- ttl: data.ttl * 1000,
197
- },
208
+ cache_value,
209
+ cache_value.ttl_initial === null
210
+ ? undefined
211
+ : {
212
+ ttl: cache_value.ttl_initial * 1000,
213
+ },
198
214
  );
199
215
  }
200
216
 
@@ -296,7 +312,7 @@ export class EcwtFactory {
296
312
 
297
313
  if (this.#redisClient) {
298
314
  const score = await this.#redisClient.ZSCORE(
299
- this.#redis_keys.revoked,
315
+ this.#redis_key_revoked,
300
316
  ecwt.id,
301
317
  );
302
318
  if (score !== null) {
@@ -370,13 +386,13 @@ export class EcwtFactory {
370
386
  await this.#redisClient.MULTI()
371
387
  .addCommand([
372
388
  'ZADD',
373
- this.#redis_keys.revoked,
389
+ this.#redis_key_revoked,
374
390
  String(ts_ms_expired),
375
391
  token_id,
376
392
  ])
377
393
  .addCommand([
378
394
  'ZREMRANGEBYSCORE',
379
- this.#redis_keys.revoked,
395
+ this.#redis_key_revoked,
380
396
  '-inf',
381
397
  String(Date.now()),
382
398
  ])
package/src/main.js CHANGED
@@ -1,6 +1,4 @@
1
1
 
2
- // @ts-check
3
-
4
2
  export { EcwtFactory } from './factory.js';
5
3
  export { Ecwt } from './token.js';
6
4
  export {
package/src/token.js CHANGED
@@ -1,6 +1,4 @@
1
1
 
2
- // @ts-check
3
-
4
2
  import { toSeconds } from './utils/time.js';
5
3
 
6
4
  /**
@@ -9,28 +7,9 @@ import { toSeconds } from './utils/time.js';
9
7
  */
10
8
 
11
9
  /**
12
- * Assigns property to object.
13
- * @param {object} target -
14
- * @param {string} key -
15
- * @param {any} value -
10
+ * @template {Record<string, any>} [D=Record<string, any>]
16
11
  */
17
- function assign(target, key, value) {
18
- Object.defineProperty(
19
- target,
20
- key,
21
- {
22
- value,
23
- enumerable: true,
24
- writable: false,
25
- configurable: false,
26
- },
27
- );
28
- }
29
-
30
12
  export class Ecwt {
31
- #ecwtFactory;
32
- #ttl_initial;
33
-
34
13
  /**
35
14
  * Token string representation.
36
15
  * @type {string}
@@ -57,18 +36,23 @@ export class Ecwt {
57
36
  ts_expired;
58
37
  /**
59
38
  * Data stored in token.
60
- * @type {{ [key: string]: any }}
39
+ * @type {D}
61
40
  * @readonly
62
41
  */
63
42
  data;
64
43
 
44
+ /** @type {EcwtFactory} */
45
+ #ecwtFactory;
46
+ /** @type {number | null} */
47
+ #ttl_initial;
48
+
65
49
  /**
66
50
  * @param {EcwtFactory} ecwtFactory -
67
51
  * @param {object} options -
68
52
  * @param {string} options.token String representation of token.
69
53
  * @param {Snowflake} options.snowflake -
70
- * @param {number?} options.ttl_initial Time to live in seconds at the moment of token creation.
71
- * @param {object} options.data Data stored in token.
54
+ * @param {number | null} options.ttl_initial Time to live in seconds at the moment of token creation.
55
+ * @param {D} options.data Data stored in token.
72
56
  */
73
57
  constructor(
74
58
  ecwtFactory,
@@ -80,26 +64,13 @@ export class Ecwt {
80
64
  },
81
65
  ) {
82
66
  this.#ecwtFactory = ecwtFactory;
83
-
84
67
  this.#ttl_initial = ttl_initial;
85
68
 
86
- assign(this, 'token', token);
87
- assign(
88
- this,
89
- 'id',
90
- snowflake.toBase62(),
91
- );
92
- assign(this, 'snowflake', snowflake);
93
- assign(
94
- this,
95
- 'ts_expired',
96
- this.#getTimestampExpired(),
97
- );
98
- assign(
99
- this,
100
- 'data',
101
- Object.freeze(data),
102
- );
69
+ this.token = token;
70
+ this.id = snowflake.toBase62();
71
+ this.snowflake = snowflake;
72
+ this.ts_expired = this.#getTimestampExpired();
73
+ this.data = Object.freeze(data);
103
74
  }
104
75
 
105
76
  #getTimestampExpired() {
@@ -1,6 +1,4 @@
1
1
 
2
- // @ts-check
3
-
4
2
  import basex from 'base-x';
5
3
 
6
4
  export const base62 = basex('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
@@ -1,7 +1,14 @@
1
1
 
2
- // @ts-check
2
+ /**
3
+ * @typedef {import('../token.js').Ecwt} Ecwt
4
+ */
3
5
 
4
6
  export class InvalidPackageInstanceError extends TypeError {
7
+ /**
8
+ * @param {string} property -
9
+ * @param {string} class_name -
10
+ * @param {string} package_name -
11
+ */
5
12
  constructor(property, class_name, package_name) {
6
13
  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.`);
7
14
  }
@@ -20,8 +27,13 @@ export class EcwtParseError extends Error {
20
27
  * Error thrown when parsed Ecwt is invalid.
21
28
  */
22
29
  export class EcwtInvalidError extends Error {
30
+ message = 'Ecwt token is invalid.';
31
+
32
+ /**
33
+ * @param {Ecwt} ecwt -
34
+ */
23
35
  constructor(ecwt) {
24
- super('Ecwt token is invalid.');
36
+ super();
25
37
 
26
38
  this.ecwt = ecwt;
27
39
  }
@@ -31,22 +43,12 @@ export class EcwtInvalidError extends Error {
31
43
  * Error thrown when parsed Ecwt is expired.
32
44
  */
33
45
  export class EcwtExpiredError extends EcwtInvalidError {
34
- constructor(ecwt) {
35
- super();
36
-
37
- this.ecwt = ecwt;
38
- this.message = 'Ecwt is expired.';
39
- }
46
+ message = 'Ecwt is expired.';
40
47
  }
41
48
 
42
49
  /**
43
50
  * Error thrown when parsed Ecwt is revoked.
44
51
  */
45
52
  export class EcwtRevokedError extends EcwtInvalidError {
46
- constructor(ecwt) {
47
- super();
48
-
49
- this.ecwt = ecwt;
50
- this.message = 'Ecwt is revoked.';
51
- }
53
+ message = 'Ecwt is revoked.';
52
54
  }
package/src/utils/time.js CHANGED
@@ -1,6 +1,4 @@
1
1
 
2
- // @ts-check
3
-
4
2
  /**
5
3
  * Convert timestamp in seconds to milliseconds.
6
4
  * @param {*} value Timestamp in milliseconds.
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "outDir": "./dist/",
4
+ "target": "esnext",
5
+ "module": "esnext",
6
+ "checkJs": true,
7
+ "allowJs": true,
8
+ "moduleResolution": "node",
9
+ "allowSyntheticDefaultImports": true,
10
+ "strict": true
11
+ },
12
+ "include": [
13
+ "src/**/*"
14
+ ],
15
+ "exclude": [
16
+ "node_modules/",
17
+ "dist/"
18
+ ]
19
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * @template {Record<string, any>} [D=Record<string, any>]
3
+ */
4
+ export class EcwtFactory<D extends Record<string, any> = Record<string, any>> {
5
+ /**
6
+ * @param {object} param0 -
7
+ * @param {import('redis').RedisClientType<import('redis').RedisModules, import('redis').RedisFunctions, import('redis').RedisScripts>} [param0.redisClient] RedisClient instance. If not provided, tokens will not be revoked and cannot be checked for revocation.
8
+ * @param {LRUCache<string, CacheValue>} [param0.lruCache] LRUCache instance. If not provided, tokens will be decrypted every time they are verified.
9
+ * @param {SnowflakeFactory} param0.snowflakeFactory SnowflakeFactory instance.
10
+ * @param {object} param0.options -
11
+ * @param {string} [param0.options.namespace] Namespace for Redis keys.
12
+ * @param {Buffer} param0.options.key Encryption key, 64 bytes
13
+ * @param {(value: any) => any} [param0.options.validator] Validator for token data. Should return validated value or throw an error.
14
+ * @param {Record<string, number>} [param0.options.senml_key_map] Payload object keys mapped for their SenML keys.
15
+ */
16
+ constructor({ redisClient, lruCache, snowflakeFactory, options: { namespace, key, validator, senml_key_map, }, }: {
17
+ redisClient?: import("redis").RedisClientType<import("redis").RedisModules, import("redis").RedisFunctions, import("redis").RedisScripts> | undefined;
18
+ lruCache?: LRUCache<string, CacheValue, any> | undefined;
19
+ snowflakeFactory: SnowflakeFactory;
20
+ options: {
21
+ namespace?: string | undefined;
22
+ key: Buffer;
23
+ validator?: ((value: any) => any) | undefined;
24
+ senml_key_map?: Record<string, number> | undefined;
25
+ };
26
+ });
27
+ /**
28
+ * Creates new token.
29
+ * @async
30
+ * @param {D} data Data to be stored in token.
31
+ * @param {object} [options] -
32
+ * @param {number | null} [options.ttl] Time to live in seconds. By default, token will never expire.
33
+ * @returns {Promise<Ecwt>} -
34
+ */
35
+ create(data: D, { ttl, }?: {
36
+ ttl?: number | null | undefined;
37
+ } | undefined): Promise<Ecwt>;
38
+ /**
39
+ * Parses token.
40
+ * @async
41
+ * @param {string} token String representation of token.
42
+ * @returns {Promise<Ecwt>} -
43
+ */
44
+ verify(token: string): Promise<Ecwt>;
45
+ /**
46
+ * Parses token without throwing errors.
47
+ * @async
48
+ * @param {string} token String representation of token.
49
+ * @returns {Promise<{ success: true, ecwt: Ecwt } | { success: false, ecwt: Ecwt | null }>} Returns whether token was parsed and verified successfully and Ecwt if parsed.
50
+ */
51
+ safeVerify(token: string): Promise<{
52
+ success: true;
53
+ ecwt: Ecwt;
54
+ } | {
55
+ success: false;
56
+ ecwt: Ecwt | null;
57
+ }>;
58
+ /**
59
+ * Revokes token.
60
+ * @async
61
+ * @param {object} options -
62
+ * @param {string} options.token_id -
63
+ * @param {number} options.ts_ms_created -
64
+ * @param {number | null} options.ttl_initial -
65
+ * @returns {Promise<void>} -
66
+ */
67
+ _revoke({ token_id, ts_ms_created, ttl_initial, }: {
68
+ token_id: string;
69
+ ts_ms_created: number;
70
+ ttl_initial: number | null;
71
+ }): Promise<void>;
72
+ /**
73
+ * Purges cache.
74
+ * @private
75
+ * @returns {void} -
76
+ */
77
+ private _purgeCache;
78
+ #private;
79
+ }
80
+ export type Snowflake = import("@kirick/snowflake").Snowflake;
81
+ export type CacheValue = {
82
+ /**
83
+ * -
84
+ */
85
+ snowflake: Snowflake;
86
+ /**
87
+ * -
88
+ */
89
+ ttl_initial: number | null;
90
+ /**
91
+ * -
92
+ */
93
+ data: Record<string, any>;
94
+ };
95
+ import { Ecwt } from './token.js';
96
+ import { LRUCache } from 'lru-cache';
97
+ import { SnowflakeFactory } from '@kirick/snowflake';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export { EcwtFactory } from "./factory.js";
2
+ export { Ecwt } from "./token.js";
3
+ export { EcwtParseError, EcwtInvalidError, EcwtExpiredError, EcwtRevokedError } from "./utils/errors.js";
@@ -0,0 +1,66 @@
1
+ /**
2
+ * @typedef {import('@kirick/snowflake').Snowflake} Snowflake
3
+ * @typedef {import('./factory.js').EcwtFactory} EcwtFactory
4
+ */
5
+ /**
6
+ * @template {Record<string, any>} [D=Record<string, any>]
7
+ */
8
+ export class Ecwt<D extends Record<string, any> = Record<string, any>> {
9
+ /**
10
+ * @param {EcwtFactory} ecwtFactory -
11
+ * @param {object} options -
12
+ * @param {string} options.token String representation of token.
13
+ * @param {Snowflake} options.snowflake -
14
+ * @param {number | null} options.ttl_initial Time to live in seconds at the moment of token creation.
15
+ * @param {D} options.data Data stored in token.
16
+ */
17
+ constructor(ecwtFactory: EcwtFactory, { token, snowflake, ttl_initial, data, }: {
18
+ token: string;
19
+ snowflake: Snowflake;
20
+ ttl_initial: number | null;
21
+ data: D;
22
+ });
23
+ /**
24
+ * Token string representation.
25
+ * @type {string}
26
+ * @readonly
27
+ */
28
+ readonly token: string;
29
+ /**
30
+ * Token ID.
31
+ * @type {string}
32
+ * @readonly
33
+ */
34
+ readonly id: string;
35
+ /**
36
+ * Snowflake associated with token.
37
+ * @type {Snowflake}
38
+ * @readonly
39
+ */
40
+ readonly snowflake: Snowflake;
41
+ /**
42
+ * Timestamp when token expires in seconds.
43
+ * @type {number?}
44
+ * @readonly
45
+ */
46
+ readonly ts_expired: number | null;
47
+ /**
48
+ * Data stored in token.
49
+ * @type {D}
50
+ * @readonly
51
+ */
52
+ readonly data: D;
53
+ /**
54
+ * Actual time to live in seconds.
55
+ * @returns {number | null} -
56
+ */
57
+ getTTL(): number | null;
58
+ /**
59
+ * Revokes token.
60
+ * @returns {Promise<void>} -
61
+ */
62
+ revoke(): Promise<void>;
63
+ #private;
64
+ }
65
+ export type Snowflake = import("@kirick/snowflake").Snowflake;
66
+ export type EcwtFactory = import("./factory.js").EcwtFactory;
@@ -0,0 +1,2 @@
1
+ export const base62: basex.BaseConverter;
2
+ import basex from 'base-x';
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @typedef {import('../token.js').Ecwt} Ecwt
3
+ */
4
+ export class InvalidPackageInstanceError extends TypeError {
5
+ /**
6
+ * @param {string} property -
7
+ * @param {string} class_name -
8
+ * @param {string} package_name -
9
+ */
10
+ constructor(property: string, class_name: string, package_name: string);
11
+ }
12
+ /**
13
+ * Error thrown when string token cannot be parsed to Ecwt.
14
+ */
15
+ export class EcwtParseError extends Error {
16
+ constructor();
17
+ }
18
+ /**
19
+ * Error thrown when parsed Ecwt is invalid.
20
+ */
21
+ export class EcwtInvalidError extends Error {
22
+ /**
23
+ * @param {Ecwt} ecwt -
24
+ */
25
+ constructor(ecwt: Ecwt);
26
+ ecwt: import("../token.js").Ecwt<Record<string, any>>;
27
+ }
28
+ /**
29
+ * Error thrown when parsed Ecwt is expired.
30
+ */
31
+ export class EcwtExpiredError extends EcwtInvalidError {
32
+ }
33
+ /**
34
+ * Error thrown when parsed Ecwt is revoked.
35
+ */
36
+ export class EcwtRevokedError extends EcwtInvalidError {
37
+ }
38
+ export type Ecwt = import("../token.js").Ecwt;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Convert timestamp in seconds to milliseconds.
3
+ * @param {*} value Timestamp in milliseconds.
4
+ * @returns {number} Timestamp in seconds.
5
+ */
6
+ export function toSeconds(value: any): number;