ecwt 0.1.1-beta.1 → 0.1.1-beta.101
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 +30 -31
- package/dist/ecwt.cjs +58 -31
- package/package.json +9 -8
- package/src/factory.js +52 -35
- package/src/main.js +5 -0
- package/src/token.js +4 -0
- package/src/utils/errors.js +6 -0
package/README.md
CHANGED
|
@@ -69,32 +69,24 @@ const lruCache = new LRUCache({
|
|
|
69
69
|
|
|
70
70
|
#### Validation library of your choice (optional)
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
By specifying the schema, you also validate the payloads. Schema is a function that takes a value and returns it back or throws.
|
|
73
73
|
|
|
74
74
|
In our example, we use [valibot](https://valibot.dev) library.
|
|
75
75
|
|
|
76
76
|
```javascript
|
|
77
|
-
import
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
).success,
|
|
91
|
-
nick: (value) => safeParse(
|
|
92
|
-
string([
|
|
93
|
-
maxLength(10),
|
|
94
|
-
]),
|
|
95
|
-
value,
|
|
96
|
-
).success,
|
|
97
|
-
};
|
|
77
|
+
import * as v from 'valibot';
|
|
78
|
+
|
|
79
|
+
const schema = (value) => v.parse(
|
|
80
|
+
v.object({
|
|
81
|
+
user_id: v.number([
|
|
82
|
+
v.maxValue(10),
|
|
83
|
+
]),
|
|
84
|
+
nick: v.string([
|
|
85
|
+
v.maxLength(10),
|
|
86
|
+
]),
|
|
87
|
+
}),
|
|
88
|
+
value,
|
|
89
|
+
);
|
|
98
90
|
```
|
|
99
91
|
|
|
100
92
|
That schema will prevent creating tokens for users with ID greater than 10 and nicknames longer than 10 characters.
|
|
@@ -111,14 +103,15 @@ constructor({
|
|
|
111
103
|
options: {
|
|
112
104
|
namespace: string?,
|
|
113
105
|
key: Buffer,
|
|
114
|
-
schema:
|
|
115
|
-
|
|
116
|
-
|
|
106
|
+
schema: (value: any) => any,
|
|
107
|
+
senmlKeyMap: {
|
|
108
|
+
[key: string]: number,
|
|
109
|
+
}?,
|
|
117
110
|
},
|
|
118
111
|
})
|
|
119
112
|
```
|
|
120
113
|
|
|
121
|
-
Create your `EcwtFactory` instance to create, and
|
|
114
|
+
Create your `EcwtFactory` instance to create, validate and revoke tokens.
|
|
122
115
|
|
|
123
116
|
```javascript
|
|
124
117
|
import { EcwtFactory } from 'ecwt';
|
|
@@ -135,10 +128,16 @@ const ecwtFactory = new EcwtFactory({
|
|
|
135
128
|
'base64',
|
|
136
129
|
),
|
|
137
130
|
schema,
|
|
131
|
+
senml_key_map: {
|
|
132
|
+
user_id: 1,
|
|
133
|
+
nick: 2,
|
|
134
|
+
},
|
|
138
135
|
},
|
|
139
136
|
});
|
|
140
137
|
```
|
|
141
138
|
|
|
139
|
+
To reduce token size, which is especially important to reduce amount of data sent over the network, you can use `options.senml_key_map` to map keys to numbers. This way, CBOR encoder will use numbers instead of strings in object keys. You **should never change** number assigned to a key or **reassign number** to another key to avoid breaking the schema. For more information, see [RFC 8428](https://datatracker.ietf.org/doc/html/rfc8428#section-6).
|
|
140
|
+
|
|
142
141
|
#### Class method `create`
|
|
143
142
|
|
|
144
143
|
```typescript
|
|
@@ -156,15 +155,15 @@ Creates a token.
|
|
|
156
155
|
|
|
157
156
|
`options.ttl` specifies the time to live of the token in seconds. If set to null, token will never expire.
|
|
158
157
|
|
|
159
|
-
> **Be careful with `ttl=null`!**
|
|
158
|
+
> **Be careful with `ttl = null`!**
|
|
160
159
|
>
|
|
161
|
-
> Revoked tokens are stored in Redis until they expire.
|
|
160
|
+
> Revoked tokens are stored in Redis until they expire. Never-expiring tokens will be stored in Redis **forever**, which will lead to uncontrolled Redis database growth.
|
|
162
161
|
|
|
163
162
|
Returns `Ecwt` instance.
|
|
164
163
|
|
|
165
164
|
```javascript
|
|
166
165
|
// Example
|
|
167
|
-
const
|
|
166
|
+
const ecwt = await ecwtFactory.create(
|
|
168
167
|
{
|
|
169
168
|
user_id: 1,
|
|
170
169
|
nick: 'kirick',
|
|
@@ -195,12 +194,12 @@ Returns `Ecwt` instance.
|
|
|
195
194
|
If the token is invalid, throws `EcwtInvalidError` which contains `Ecwt` instance in the `ecwt` property.
|
|
196
195
|
|
|
197
196
|
```javascript
|
|
198
|
-
const
|
|
197
|
+
const ecwt = await ecwtFactory.verify(token);
|
|
199
198
|
```
|
|
200
199
|
|
|
201
200
|
### `Ecwt`
|
|
202
201
|
|
|
203
|
-
Represents the token.
|
|
202
|
+
Represents the token. Its counstructor cannot be called by the user.
|
|
204
203
|
|
|
205
204
|
```javascript
|
|
206
205
|
import { Ecwt } from 'ecwt';
|
package/dist/ecwt.cjs
CHANGED
|
@@ -30,7 +30,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
var main_exports = {};
|
|
31
31
|
__export(main_exports, {
|
|
32
32
|
Ecwt: () => Ecwt,
|
|
33
|
-
|
|
33
|
+
EcwtExpiredError: () => EcwtExpiredError,
|
|
34
|
+
EcwtFactory: () => EcwtFactory,
|
|
35
|
+
EcwtInvalidError: () => EcwtInvalidError,
|
|
36
|
+
EcwtRevokedError: () => EcwtRevokedError
|
|
34
37
|
});
|
|
35
38
|
module.exports = __toCommonJS(main_exports);
|
|
36
39
|
|
|
@@ -142,6 +145,10 @@ var Ecwt = class {
|
|
|
142
145
|
}
|
|
143
146
|
return this.#ttl_initial - toSeconds(Date.now() - this.snowflake.timestamp);
|
|
144
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Revokes token.
|
|
150
|
+
* @returns {Promise<void>} -
|
|
151
|
+
*/
|
|
145
152
|
/* async */
|
|
146
153
|
revoke() {
|
|
147
154
|
return this.#ecwtFactory._revoke({
|
|
@@ -162,6 +169,11 @@ var InvalidPackageInstanceError = class extends TypeError {
|
|
|
162
169
|
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.`);
|
|
163
170
|
}
|
|
164
171
|
};
|
|
172
|
+
var EcwtParseError = class extends Error {
|
|
173
|
+
constructor() {
|
|
174
|
+
super("Cannot parse data to Ecwt token.");
|
|
175
|
+
}
|
|
176
|
+
};
|
|
165
177
|
var EcwtInvalidError = class extends Error {
|
|
166
178
|
constructor(ecwt) {
|
|
167
179
|
super("Ecwt token is invalid.");
|
|
@@ -201,8 +213,8 @@ var EcwtFactory = class {
|
|
|
201
213
|
#snowflakeFactory;
|
|
202
214
|
#redis_keys = {};
|
|
203
215
|
#encryption_key;
|
|
204
|
-
#
|
|
205
|
-
#
|
|
216
|
+
#validator;
|
|
217
|
+
#cborEncoder;
|
|
206
218
|
/**
|
|
207
219
|
*
|
|
208
220
|
* @param {object} param0 -
|
|
@@ -212,7 +224,8 @@ var EcwtFactory = class {
|
|
|
212
224
|
* @param {object} param0.options -
|
|
213
225
|
* @param {string} [param0.options.namespace] Namespace for Redis keys.
|
|
214
226
|
* @param {Buffer} param0.options.key Encryption key, 64 bytes
|
|
215
|
-
* @param {
|
|
227
|
+
* @param {(value: any) => any} [param0.options.validator] Validator for token data. Should return validated value or throw an error.
|
|
228
|
+
* @param {{ [key: string]: number }} [param0.options.senml_key_map] Payload object keys mapped for their SenML keys.
|
|
216
229
|
*/
|
|
217
230
|
constructor({
|
|
218
231
|
redisClient: redisClient2 = null,
|
|
@@ -221,7 +234,8 @@ var EcwtFactory = class {
|
|
|
221
234
|
options: {
|
|
222
235
|
namespace = null,
|
|
223
236
|
key,
|
|
224
|
-
|
|
237
|
+
validator,
|
|
238
|
+
senml_key_map
|
|
225
239
|
}
|
|
226
240
|
}) {
|
|
227
241
|
if (redisClient2 !== null && (redisClient2.constructor.name !== redis_client_constructor_name || getAllKeysList(redisClient2) !== redis_client_keys)) {
|
|
@@ -250,8 +264,12 @@ var EcwtFactory = class {
|
|
|
250
264
|
this.#snowflakeFactory = snowflakeFactory;
|
|
251
265
|
this.#redis_keys.revoked = `${REDIS_PREFIX}${namespace}:revoked`;
|
|
252
266
|
this.#encryption_key = key;
|
|
253
|
-
this.#
|
|
254
|
-
|
|
267
|
+
this.#validator = validator;
|
|
268
|
+
if (senml_key_map) {
|
|
269
|
+
this.#cborEncoder = new import_cbor_x.Encoder({
|
|
270
|
+
keyMap: senml_key_map
|
|
271
|
+
});
|
|
272
|
+
}
|
|
255
273
|
}
|
|
256
274
|
/**
|
|
257
275
|
* Creates new token.
|
|
@@ -264,24 +282,19 @@ var EcwtFactory = class {
|
|
|
264
282
|
async create(data, {
|
|
265
283
|
ttl
|
|
266
284
|
} = {}) {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
const value = data[key];
|
|
270
|
-
const validator = this.#schema[key];
|
|
271
|
-
if (typeof validator === "function" && validator(value) !== true) {
|
|
272
|
-
throw new TypeError(`Value "${value}" of property "${key}" is invalid.`);
|
|
273
|
-
}
|
|
274
|
-
payload.push(value);
|
|
285
|
+
if (typeof this.#validator === "function") {
|
|
286
|
+
data = this.#validator(data);
|
|
275
287
|
}
|
|
276
288
|
if (typeof ttl !== "number" && Number.isNaN(ttl) !== true && ttl !== null) {
|
|
277
289
|
throw new TypeError("TTL must be a number or null.");
|
|
278
290
|
}
|
|
279
291
|
const snowflake = await this.#snowflakeFactory.createSafe();
|
|
280
|
-
const
|
|
292
|
+
const payload = [
|
|
281
293
|
snowflake.toBuffer(),
|
|
282
294
|
ttl,
|
|
283
|
-
|
|
284
|
-
]
|
|
295
|
+
data
|
|
296
|
+
];
|
|
297
|
+
const token_raw = this.#cborEncoder ? this.#cborEncoder.encode(payload) : (0, import_cbor_x.encode)(payload);
|
|
285
298
|
const token_encrypted = await import_evilcrypt.v2.encrypt(
|
|
286
299
|
token_raw,
|
|
287
300
|
this.#encryption_key
|
|
@@ -332,20 +345,31 @@ var EcwtFactory = class {
|
|
|
332
345
|
const token_encrypted = Buffer.from(
|
|
333
346
|
base62.decode(token)
|
|
334
347
|
);
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
348
|
+
let token_raw;
|
|
349
|
+
try {
|
|
350
|
+
token_raw = await (0, import_evilcrypt.decrypt)(
|
|
351
|
+
token_encrypted,
|
|
352
|
+
this.#encryption_key
|
|
353
|
+
);
|
|
354
|
+
} catch {
|
|
355
|
+
throw new EcwtParseError();
|
|
356
|
+
}
|
|
357
|
+
const payload = this.#cborEncoder ? this.#cborEncoder.decode(token_raw) : (0, import_cbor_x.decode)(token_raw);
|
|
339
358
|
const [
|
|
340
|
-
snowflake_buffer
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
359
|
+
snowflake_buffer
|
|
360
|
+
] = payload;
|
|
361
|
+
[
|
|
362
|
+
,
|
|
363
|
+
ttl_initial,
|
|
364
|
+
data
|
|
365
|
+
] = payload;
|
|
344
366
|
snowflake = this.#snowflakeFactory.parse(snowflake_buffer);
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
367
|
+
if (typeof this.#validator === "function") {
|
|
368
|
+
try {
|
|
369
|
+
data = this.#validator(data);
|
|
370
|
+
} catch {
|
|
371
|
+
throw new EcwtParseError();
|
|
372
|
+
}
|
|
349
373
|
}
|
|
350
374
|
this.#setCache(
|
|
351
375
|
token,
|
|
@@ -426,5 +450,8 @@ var EcwtFactory = class {
|
|
|
426
450
|
// Annotate the CommonJS export names for ESM import in node:
|
|
427
451
|
0 && (module.exports = {
|
|
428
452
|
Ecwt,
|
|
429
|
-
|
|
453
|
+
EcwtExpiredError,
|
|
454
|
+
EcwtFactory,
|
|
455
|
+
EcwtInvalidError,
|
|
456
|
+
EcwtRevokedError
|
|
430
457
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ecwt",
|
|
3
|
-
"version": "0.1.1-beta.
|
|
3
|
+
"version": "0.1.1-beta.101",
|
|
4
4
|
"description": "Encrypted CBOR-encoded Web Token",
|
|
5
5
|
"main": "src/main.js",
|
|
6
6
|
"type": "module",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
22
|
"@kirick/snowflake": "^0.2.1-beta.1",
|
|
23
|
-
"lru-cache": "^
|
|
23
|
+
"lru-cache": "^9 || ^10",
|
|
24
24
|
"redis": "^4"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
@@ -28,20 +28,21 @@
|
|
|
28
28
|
"eslint": "8.41.0",
|
|
29
29
|
"eslint-config-xo": "0.43.1",
|
|
30
30
|
"eslint-plugin-import": "2.27.5",
|
|
31
|
-
"eslint-plugin-jsdoc": "
|
|
31
|
+
"eslint-plugin-jsdoc": "46.9.1",
|
|
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
|
-
"
|
|
36
|
-
"
|
|
35
|
+
"valibot": "^0.24.1",
|
|
36
|
+
"vitest": "1.3.1"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
|
-
"test": "bun run redis-up && npm run test-node
|
|
40
|
-
"test-node": "
|
|
39
|
+
"test": "bun run redis-up && bun test && npm run test-node",
|
|
40
|
+
"test-node": "vitest run --no-file-parallelism",
|
|
41
41
|
"coverage": "bun run redis-up && bun test --coverage",
|
|
42
42
|
"build": "bun run build-cjs",
|
|
43
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
|
|
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",
|
|
45
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",
|
|
46
47
|
"redis-down": "docker stop test-redis-ecwt-test"
|
|
47
48
|
},
|
package/src/factory.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import { SnowflakeFactory } from '@kirick/snowflake';
|
|
3
3
|
import {
|
|
4
|
+
Encoder as CborEncoder,
|
|
4
5
|
encode as cborEncode,
|
|
5
6
|
decode as cborDecode } from 'cbor-x';
|
|
6
7
|
import {
|
|
@@ -13,7 +14,8 @@ import { base62 } from './utils/base62.js';
|
|
|
13
14
|
import {
|
|
14
15
|
InvalidPackageInstanceError,
|
|
15
16
|
EcwtExpiredError,
|
|
16
|
-
EcwtRevokedError
|
|
17
|
+
EcwtRevokedError,
|
|
18
|
+
EcwtParseError } from './utils/errors.js';
|
|
17
19
|
|
|
18
20
|
const REDIS_PREFIX = '@ecwt:';
|
|
19
21
|
|
|
@@ -39,8 +41,8 @@ export class EcwtFactory {
|
|
|
39
41
|
#redis_keys = {};
|
|
40
42
|
#encryption_key;
|
|
41
43
|
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
+
#validator;
|
|
45
|
+
#cborEncoder;
|
|
44
46
|
|
|
45
47
|
/**
|
|
46
48
|
*
|
|
@@ -51,7 +53,8 @@ export class EcwtFactory {
|
|
|
51
53
|
* @param {object} param0.options -
|
|
52
54
|
* @param {string} [param0.options.namespace] Namespace for Redis keys.
|
|
53
55
|
* @param {Buffer} param0.options.key Encryption key, 64 bytes
|
|
54
|
-
* @param {
|
|
56
|
+
* @param {(value: any) => any} [param0.options.validator] Validator for token data. Should return validated value or throw an error.
|
|
57
|
+
* @param {{ [key: string]: number }} [param0.options.senml_key_map] Payload object keys mapped for their SenML keys.
|
|
55
58
|
*/
|
|
56
59
|
constructor({
|
|
57
60
|
redisClient = null,
|
|
@@ -60,7 +63,8 @@ export class EcwtFactory {
|
|
|
60
63
|
options: {
|
|
61
64
|
namespace = null,
|
|
62
65
|
key,
|
|
63
|
-
|
|
66
|
+
validator,
|
|
67
|
+
senml_key_map,
|
|
64
68
|
},
|
|
65
69
|
}) {
|
|
66
70
|
if (
|
|
@@ -103,8 +107,13 @@ export class EcwtFactory {
|
|
|
103
107
|
|
|
104
108
|
this.#encryption_key = key;
|
|
105
109
|
|
|
106
|
-
this.#
|
|
107
|
-
|
|
110
|
+
this.#validator = validator;
|
|
111
|
+
|
|
112
|
+
if (senml_key_map) {
|
|
113
|
+
this.#cborEncoder = new CborEncoder({
|
|
114
|
+
keyMap: senml_key_map,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
108
117
|
}
|
|
109
118
|
|
|
110
119
|
/**
|
|
@@ -121,19 +130,8 @@ export class EcwtFactory {
|
|
|
121
130
|
ttl,
|
|
122
131
|
} = {},
|
|
123
132
|
) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const value = data[key];
|
|
127
|
-
const validator = this.#schema[key];
|
|
128
|
-
|
|
129
|
-
if (
|
|
130
|
-
typeof validator === 'function'
|
|
131
|
-
&& validator(value) !== true
|
|
132
|
-
) {
|
|
133
|
-
throw new TypeError(`Value "${value}" of property "${key}" is invalid.`);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
payload.push(value);
|
|
133
|
+
if (typeof this.#validator === 'function') {
|
|
134
|
+
data = this.#validator(data);
|
|
137
135
|
}
|
|
138
136
|
|
|
139
137
|
if (
|
|
@@ -146,11 +144,14 @@ export class EcwtFactory {
|
|
|
146
144
|
|
|
147
145
|
const snowflake = await this.#snowflakeFactory.createSafe();
|
|
148
146
|
|
|
149
|
-
const
|
|
147
|
+
const payload = [
|
|
150
148
|
snowflake.toBuffer(),
|
|
151
149
|
ttl,
|
|
152
|
-
|
|
153
|
-
]
|
|
150
|
+
data,
|
|
151
|
+
];
|
|
152
|
+
const token_raw = this.#cborEncoder
|
|
153
|
+
? this.#cborEncoder.encode(payload)
|
|
154
|
+
: cborEncode(payload);
|
|
154
155
|
|
|
155
156
|
const token_encrypted = await evilcryptV2.encrypt(
|
|
156
157
|
token_raw,
|
|
@@ -205,29 +206,45 @@ export class EcwtFactory {
|
|
|
205
206
|
let data;
|
|
206
207
|
|
|
207
208
|
const cached_entry = this.#lruCache?.info(token);
|
|
208
|
-
// token is cached
|
|
209
|
+
// token is not cached
|
|
209
210
|
if (cached_entry === undefined) {
|
|
210
211
|
const token_encrypted = Buffer.from(
|
|
211
212
|
base62.decode(token),
|
|
212
213
|
);
|
|
213
214
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
215
|
+
let token_raw;
|
|
216
|
+
try {
|
|
217
|
+
token_raw = await evilcryptDecrypt(
|
|
218
|
+
token_encrypted,
|
|
219
|
+
this.#encryption_key,
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
throw new EcwtParseError();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const payload = this.#cborEncoder
|
|
227
|
+
? this.#cborEncoder.decode(token_raw)
|
|
228
|
+
: cborDecode(token_raw);
|
|
218
229
|
|
|
219
230
|
const [
|
|
220
231
|
snowflake_buffer,
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
232
|
+
] = payload;
|
|
233
|
+
[
|
|
234
|
+
,
|
|
235
|
+
ttl_initial,
|
|
236
|
+
data,
|
|
237
|
+
] = payload;
|
|
224
238
|
|
|
225
239
|
snowflake = this.#snowflakeFactory.parse(snowflake_buffer);
|
|
226
|
-
ttl_initial = _ttl_initial;
|
|
227
240
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
241
|
+
if (typeof this.#validator === 'function') {
|
|
242
|
+
try {
|
|
243
|
+
data = this.#validator(data);
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
throw new EcwtParseError();
|
|
247
|
+
}
|
|
231
248
|
}
|
|
232
249
|
|
|
233
250
|
this.#setCache(
|
package/src/main.js
CHANGED
package/src/token.js
CHANGED
|
@@ -120,6 +120,10 @@ export class Ecwt {
|
|
|
120
120
|
return this.#ttl_initial - toSeconds(Date.now() - this.snowflake.timestamp);
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Revokes token.
|
|
125
|
+
* @returns {Promise<void>} -
|
|
126
|
+
*/
|
|
123
127
|
/* async */ revoke() {
|
|
124
128
|
return this.#ecwtFactory._revoke({
|
|
125
129
|
token_id: this.id,
|
package/src/utils/errors.js
CHANGED
|
@@ -5,6 +5,12 @@ export class InvalidPackageInstanceError extends TypeError {
|
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
export class EcwtParseError extends Error {
|
|
9
|
+
constructor() {
|
|
10
|
+
super('Cannot parse data to Ecwt token.');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
8
14
|
export class EcwtInvalidError extends Error {
|
|
9
15
|
constructor(ecwt) {
|
|
10
16
|
super('Ecwt token is invalid.');
|