@croct/sdk 0.15.4 → 0.16.1

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/apiKey.d.ts CHANGED
@@ -1,9 +1,14 @@
1
- /// <reference types="node" />
1
+ export type ParsedPrivateKey = {
2
+ algorithm: string;
3
+ encodedKey: string;
4
+ };
2
5
  export declare class ApiKey {
3
6
  private static readonly IDENTIFIER_PATTERN;
4
7
  private static readonly PRIVATE_KEY_PATTERN;
8
+ private static readonly ALGORITHMS;
5
9
  private readonly identifier;
6
10
  private readonly privateKey?;
11
+ private importedKey;
7
12
  private constructor();
8
13
  static from(apiKey: string | ApiKey): ApiKey;
9
14
  static parse(apiKey: string): ApiKey;
@@ -11,8 +16,31 @@ export declare class ApiKey {
11
16
  getIdentifier(): string;
12
17
  getIdentifierHash(): Promise<string>;
13
18
  hasPrivateKey(): boolean;
14
- getPrivateKey(): string | null;
15
- sign(blob: Buffer): Promise<Buffer>;
19
+ getPrivateKey(): string;
20
+ sign(data: string): Promise<string>;
21
+ getSigningAlgorithm(): string;
22
+ private importKey;
23
+ private getParsedPrivateKey;
16
24
  export(): string;
17
25
  toString(): string;
26
+ /**
27
+ * Create an array buffer from a string.
28
+ *
29
+ * @see https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
30
+ *
31
+ * @param data The string to convert.
32
+ * @returns The array buffer.
33
+ */
34
+ private static createByteArrayFromString;
35
+ private static createByteArrayFromHexString;
36
+ /**
37
+ * Convert an array buffer to a string.
38
+ *
39
+ * @see https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
40
+ *
41
+ * @param buffer The buffer to convert.
42
+ * @returns The string.
43
+ */
44
+ private static convertBufferToString;
45
+ private static convertBufferToHexString;
18
46
  }
package/apiKey.js CHANGED
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ApiKey = void 0;
4
- const crypto = require("crypto");
5
4
  class ApiKey {
6
5
  constructor(identifier, privateKey) {
7
6
  this.identifier = identifier;
@@ -22,68 +21,124 @@ class ApiKey {
22
21
  }
23
22
  static of(identifier, privateKey) {
24
23
  if (!ApiKey.IDENTIFIER_PATTERN.test(identifier)) {
25
- throw new Error('The API key identifier must be a UUID.');
24
+ throw new Error('The identifier must be a UUID.');
26
25
  }
27
- if (privateKey === undefined) {
26
+ if (privateKey === undefined || privateKey === '') {
28
27
  return new ApiKey(identifier);
29
28
  }
30
29
  if (!ApiKey.PRIVATE_KEY_PATTERN.test(privateKey)) {
31
- throw new Error('The API key private key must be a hexadecimal string.');
30
+ throw new Error('The private key is malformed.');
32
31
  }
33
- try {
34
- return new ApiKey(identifier, crypto.createPrivateKey({
35
- key: Buffer.from(privateKey, 'hex'),
36
- format: 'der',
37
- type: 'pkcs8',
38
- }));
39
- }
40
- catch {
41
- throw new Error('Invalid private key.');
32
+ const [algorithmName, encodedKey] = privateKey.split(';');
33
+ if (!(algorithmName in ApiKey.ALGORITHMS)) {
34
+ throw new Error(`Unsupported signing algorithm "${algorithmName}".`);
42
35
  }
36
+ return new ApiKey(identifier, {
37
+ algorithm: algorithmName,
38
+ encodedKey: encodedKey,
39
+ });
43
40
  }
44
41
  getIdentifier() {
45
42
  return this.identifier;
46
43
  }
47
44
  async getIdentifierHash() {
48
- const identifierBytes = Buffer.from(this.identifier.replace(/-/g, ''), 'hex');
45
+ const identifierBytes = ApiKey.createByteArrayFromHexString(this.identifier.replace(/-/g, ''));
49
46
  const rawHash = await crypto.subtle.digest('SHA-256', identifierBytes);
50
- return Buffer.from(rawHash).toString('hex');
47
+ return ApiKey.convertBufferToHexString(rawHash);
51
48
  }
52
49
  hasPrivateKey() {
53
50
  return this.privateKey !== undefined;
54
51
  }
55
52
  getPrivateKey() {
56
- return this.privateKey === undefined
57
- ? null
58
- : this.privateKey
59
- .export({ format: 'der', type: 'pkcs8' })
60
- .toString('hex');
61
- }
62
- sign(blob) {
63
- const { privateKey } = this;
64
- if (privateKey === undefined) {
65
- return Promise.reject(new Error('The API key does not have a private key.'));
53
+ if (this.privateKey === undefined) {
54
+ throw new Error('The API key does not have a private key.');
66
55
  }
67
- return new Promise((resolve, reject) => {
68
- crypto.sign(null, blob, privateKey, (error, signature) => {
69
- if (error == null) {
70
- resolve(signature);
71
- }
72
- else {
73
- reject(error);
74
- }
75
- });
76
- });
56
+ return `${this.privateKey.algorithm};${this.privateKey.encodedKey}`;
57
+ }
58
+ async sign(data) {
59
+ const key = await this.importKey();
60
+ const algorithm = this.getSigningAlgorithm();
61
+ return ApiKey.convertBufferToString(await crypto.subtle.sign(ApiKey.ALGORITHMS[algorithm].signatureAlgorithm, key, ApiKey.createByteArrayFromString(data)));
62
+ }
63
+ getSigningAlgorithm() {
64
+ const { algorithm } = this.getParsedPrivateKey();
65
+ return algorithm;
66
+ }
67
+ importKey() {
68
+ const { algorithm, encodedKey } = this.getParsedPrivateKey();
69
+ if (this.importedKey === undefined) {
70
+ this.importedKey = crypto.subtle
71
+ .importKey('pkcs8', ApiKey.createByteArrayFromString(atob(encodedKey)), ApiKey.ALGORITHMS[algorithm].keyAlgorithm, false, ['sign']);
72
+ }
73
+ return this.importedKey;
74
+ }
75
+ getParsedPrivateKey() {
76
+ if (this.privateKey === undefined) {
77
+ throw new Error('The API key does not have a private key.');
78
+ }
79
+ return this.privateKey;
77
80
  }
78
81
  export() {
79
- const privateKey = this.getPrivateKey();
80
- return this.identifier + (privateKey === null ? '' : `:${privateKey}`);
82
+ return this.identifier + (this.hasPrivateKey() ? `:${this.getPrivateKey()}` : '');
81
83
  }
82
84
  toString() {
83
85
  return '[redacted]';
84
86
  }
87
+ /**
88
+ * Create an array buffer from a string.
89
+ *
90
+ * @see https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
91
+ *
92
+ * @param data The string to convert.
93
+ * @returns The array buffer.
94
+ */
95
+ static createByteArrayFromString(data) {
96
+ const byteArray = new Uint8Array(data.length);
97
+ for (let i = 0; i < byteArray.length; i++) {
98
+ byteArray[i] = data.charCodeAt(i);
99
+ }
100
+ return byteArray;
101
+ }
102
+ static createByteArrayFromHexString(data) {
103
+ const byteArray = new Uint8Array(data.length / 2);
104
+ for (let i = 0; i < byteArray.length; i++) {
105
+ byteArray[i] = parseInt(data.substring(i * 2, i * 2 + 2), 16);
106
+ }
107
+ return byteArray;
108
+ }
109
+ /**
110
+ * Convert an array buffer to a string.
111
+ *
112
+ * @see https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
113
+ *
114
+ * @param buffer The buffer to convert.
115
+ * @returns The string.
116
+ */
117
+ static convertBufferToString(buffer) {
118
+ return String.fromCharCode(...new Uint8Array(buffer));
119
+ }
120
+ static convertBufferToHexString(buffer) {
121
+ const bytes = new Uint8Array(buffer);
122
+ let hexString = '';
123
+ for (let i = 0; i < bytes.length; i++) {
124
+ hexString += bytes[i].toString(16).padStart(2, '0');
125
+ }
126
+ return hexString;
127
+ }
85
128
  }
86
129
  exports.ApiKey = ApiKey;
87
130
  ApiKey.IDENTIFIER_PATTERN = /^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$/i;
88
- ApiKey.PRIVATE_KEY_PATTERN = /^[a-f0-9]+$/i;
131
+ ApiKey.PRIVATE_KEY_PATTERN = /^[a-z0-9]+;[^;]+$/i;
132
+ ApiKey.ALGORITHMS = {
133
+ ES256: {
134
+ keyAlgorithm: {
135
+ name: 'ECDSA',
136
+ namedCurve: 'P-256',
137
+ },
138
+ signatureAlgorithm: {
139
+ name: 'ECDSA',
140
+ hash: 'SHA-256',
141
+ },
142
+ },
143
+ };
89
144
  //# sourceMappingURL=apiKey.js.map
package/apiKey.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"apiKey.js","sourceRoot":"","sources":["src/apiKey.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"apiKey.js","sourceRoot":"","sources":["src/apiKey.ts"],"names":[],"mappings":"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"}
package/base64Url.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare function base64UrlEncode(value: string, utf8?: boolean): string;
2
+ export declare function base64UrlDecode(value: string, utf8?: boolean): string;
package/base64Url.js ADDED
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.base64UrlDecode = exports.base64UrlEncode = void 0;
4
+ function base64Unescape(value) {
5
+ return (value + '==='.slice((value.length + 3) % 4)).replace(/-/g, '+').replace(/_/g, '/');
6
+ }
7
+ function base64Escape(value) {
8
+ return value
9
+ .replace(/\+/g, '-')
10
+ .replace(/\//g, '_')
11
+ .replace(/=/g, '');
12
+ }
13
+ function base64UrlEncode(value, utf8 = false) {
14
+ return utf8
15
+ ? base64Escape(btoa(String.fromCodePoint(...new TextEncoder().encode(value))))
16
+ : base64Escape(btoa(value));
17
+ }
18
+ exports.base64UrlEncode = base64UrlEncode;
19
+ function base64UrlDecode(value, utf8 = false) {
20
+ return utf8
21
+ ? new TextDecoder().decode(Uint8Array.from(atob(base64Unescape(value)), m => m.codePointAt(0)))
22
+ : atob(base64Unescape(value));
23
+ }
24
+ exports.base64UrlDecode = base64UrlDecode;
25
+ //# sourceMappingURL=base64Url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64Url.js","sourceRoot":"","sources":["src/base64Url.ts"],"names":[],"mappings":";;;AAAA,SAAS,cAAc,CAAC,KAAa;IACjC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC/F,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IAC/B,OAAO,KAAK;SACP,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAC3B,CAAC;AAED,SAAgB,eAAe,CAAC,KAAa,EAAE,IAAI,GAAG,KAAK;IACvD,OAAO,IAAI;QACP,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC9E,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AACpC,CAAC;AAJD,0CAIC;AAED,SAAgB,eAAe,CAAC,KAAa,EAAE,IAAI,GAAG,KAAK;IACvD,OAAO,IAAI;QACP,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC,CAAC;QAChG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;AACtC,CAAC;AAJD,0CAIC"}
package/constants.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export declare const BASE_ENDPOINT_URL = "https://api.croct.io";
2
2
  export declare const MAX_QUERY_LENGTH: number;
3
- export declare const VERSION = "0.15.4";
4
- export declare const CLIENT_LIBRARY = "Croct SDK JS v0.15.4";
3
+ export declare const VERSION = "0.16.1";
4
+ export declare const CLIENT_LIBRARY = "Croct SDK JS v0.16.1";
package/constants.js CHANGED
@@ -3,6 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CLIENT_LIBRARY = exports.VERSION = exports.MAX_QUERY_LENGTH = exports.BASE_ENDPOINT_URL = void 0;
4
4
  exports.BASE_ENDPOINT_URL = 'https://api.croct.io';
5
5
  exports.MAX_QUERY_LENGTH = 500;
6
- exports.VERSION = '0.15.4';
6
+ exports.VERSION = '0.16.1';
7
7
  exports.CLIENT_LIBRARY = `Croct SDK JS v${exports.VERSION}`;
8
8
  //# sourceMappingURL=constants.js.map
@@ -2,3 +2,4 @@ export * from './logger';
2
2
  export { ConsoleLogger } from './consoleLogger';
3
3
  export { NamespacedLogger } from './namespacedLogger';
4
4
  export { NullLogger } from './nullLogger';
5
+ export { FilteredLogger } from './filteredLogger';
package/logging/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NullLogger = exports.NamespacedLogger = exports.ConsoleLogger = void 0;
3
+ exports.FilteredLogger = exports.NullLogger = exports.NamespacedLogger = exports.ConsoleLogger = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  tslib_1.__exportStar(require("./logger"), exports);
6
6
  var consoleLogger_1 = require("./consoleLogger");
@@ -9,4 +9,6 @@ var namespacedLogger_1 = require("./namespacedLogger");
9
9
  Object.defineProperty(exports, "NamespacedLogger", { enumerable: true, get: function () { return namespacedLogger_1.NamespacedLogger; } });
10
10
  var nullLogger_1 = require("./nullLogger");
11
11
  Object.defineProperty(exports, "NullLogger", { enumerable: true, get: function () { return nullLogger_1.NullLogger; } });
12
+ var filteredLogger_1 = require("./filteredLogger");
13
+ Object.defineProperty(exports, "FilteredLogger", { enumerable: true, get: function () { return filteredLogger_1.FilteredLogger; } });
12
14
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/logging/index.ts"],"names":[],"mappings":";;;;AAAA,mDAAyB;AACzB,iDAA8C;AAAtC,8GAAA,aAAa,OAAA;AACrB,uDAAoD;AAA5C,oHAAA,gBAAgB,OAAA;AACxB,2CAAwC;AAAhC,wGAAA,UAAU,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/logging/index.ts"],"names":[],"mappings":";;;;AAAA,mDAAyB;AACzB,iDAA8C;AAAtC,8GAAA,aAAa,OAAA;AACrB,uDAAoD;AAA5C,oHAAA,gBAAgB,OAAA;AACxB,2CAAwC;AAAhC,wGAAA,UAAU,OAAA;AAClB,mDAAgD;AAAxC,gHAAA,cAAc,OAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@croct/sdk",
3
- "version": "0.15.4",
3
+ "version": "0.16.1",
4
4
  "description": "Croct SDK for JavaScript.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -29,7 +29,6 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@croct/json": "^2.0.1",
32
- "js-base64": "^3.7.7",
33
32
  "tslib": "^2.5.0"
34
33
  },
35
34
  "devDependencies": {
package/src/apiKey.ts CHANGED
@@ -1,16 +1,38 @@
1
- import * as crypto from 'crypto';
2
- import {KeyObject} from 'crypto';
1
+ export type ParsedPrivateKey = {
2
+ algorithm: string,
3
+ encodedKey: string,
4
+ };
5
+
6
+ type Algorithm = {
7
+ keyAlgorithm: EcKeyImportParams,
8
+ signatureAlgorithm: EcdsaParams,
9
+ };
3
10
 
4
11
  export class ApiKey {
5
12
  private static readonly IDENTIFIER_PATTERN = /^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$/i;
6
13
 
7
- private static readonly PRIVATE_KEY_PATTERN = /^[a-f0-9]+$/i;
14
+ private static readonly PRIVATE_KEY_PATTERN = /^[a-z0-9]+;[^;]+$/i;
15
+
16
+ private static readonly ALGORITHMS: Record<string, Algorithm> = {
17
+ ES256: {
18
+ keyAlgorithm: {
19
+ name: 'ECDSA',
20
+ namedCurve: 'P-256',
21
+ },
22
+ signatureAlgorithm: {
23
+ name: 'ECDSA',
24
+ hash: 'SHA-256',
25
+ },
26
+ },
27
+ };
8
28
 
9
29
  private readonly identifier: string;
10
30
 
11
- private readonly privateKey?: KeyObject;
31
+ private readonly privateKey?: ParsedPrivateKey;
32
+
33
+ private importedKey: Promise<CryptoKey>;
12
34
 
13
- private constructor(identifier: string, privateKey?: KeyObject) {
35
+ private constructor(identifier: string, privateKey?: ParsedPrivateKey) {
14
36
  this.identifier = identifier;
15
37
  this.privateKey = privateKey;
16
38
  }
@@ -35,26 +57,27 @@ export class ApiKey {
35
57
 
36
58
  public static of(identifier: string, privateKey?: string): ApiKey {
37
59
  if (!ApiKey.IDENTIFIER_PATTERN.test(identifier)) {
38
- throw new Error('The API key identifier must be a UUID.');
60
+ throw new Error('The identifier must be a UUID.');
39
61
  }
40
62
 
41
- if (privateKey === undefined) {
63
+ if (privateKey === undefined || privateKey === '') {
42
64
  return new ApiKey(identifier);
43
65
  }
44
66
 
45
67
  if (!ApiKey.PRIVATE_KEY_PATTERN.test(privateKey)) {
46
- throw new Error('The API key private key must be a hexadecimal string.');
68
+ throw new Error('The private key is malformed.');
47
69
  }
48
70
 
49
- try {
50
- return new ApiKey(identifier, crypto.createPrivateKey({
51
- key: Buffer.from(privateKey, 'hex'),
52
- format: 'der',
53
- type: 'pkcs8',
54
- }));
55
- } catch {
56
- throw new Error('Invalid private key.');
71
+ const [algorithmName, encodedKey] = privateKey.split(';');
72
+
73
+ if (!(algorithmName in ApiKey.ALGORITHMS)) {
74
+ throw new Error(`Unsupported signing algorithm "${algorithmName}".`);
57
75
  }
76
+
77
+ return new ApiKey(identifier, {
78
+ algorithm: algorithmName,
79
+ encodedKey: encodedKey,
80
+ });
58
81
  }
59
82
 
60
83
  public getIdentifier(): string {
@@ -62,49 +85,124 @@ export class ApiKey {
62
85
  }
63
86
 
64
87
  public async getIdentifierHash(): Promise<string> {
65
- const identifierBytes = Buffer.from(this.identifier.replace(/-/g, ''), 'hex');
88
+ const identifierBytes = ApiKey.createByteArrayFromHexString(this.identifier.replace(/-/g, ''));
66
89
  const rawHash = await crypto.subtle.digest('SHA-256', identifierBytes);
67
90
 
68
- return Buffer.from(rawHash).toString('hex');
91
+ return ApiKey.convertBufferToHexString(rawHash);
69
92
  }
70
93
 
71
94
  public hasPrivateKey(): boolean {
72
95
  return this.privateKey !== undefined;
73
96
  }
74
97
 
75
- public getPrivateKey(): string|null {
76
- return this.privateKey === undefined
77
- ? null
78
- : this.privateKey
79
- .export({format: 'der', type: 'pkcs8'})
80
- .toString('hex');
98
+ public getPrivateKey(): string {
99
+ if (this.privateKey === undefined) {
100
+ throw new Error('The API key does not have a private key.');
101
+ }
102
+
103
+ return `${this.privateKey.algorithm};${this.privateKey.encodedKey}`;
104
+ }
105
+
106
+ public async sign(data: string): Promise<string> {
107
+ const key = await this.importKey();
108
+ const algorithm = this.getSigningAlgorithm();
109
+
110
+ return ApiKey.convertBufferToString(
111
+ await crypto.subtle.sign(
112
+ ApiKey.ALGORITHMS[algorithm].signatureAlgorithm,
113
+ key,
114
+ ApiKey.createByteArrayFromString(data),
115
+ ),
116
+ );
81
117
  }
82
118
 
83
- public sign(blob: Buffer): Promise<Buffer> {
84
- const {privateKey} = this;
119
+ public getSigningAlgorithm(): string {
120
+ const {algorithm} = this.getParsedPrivateKey();
85
121
 
86
- if (privateKey === undefined) {
87
- return Promise.reject(new Error('The API key does not have a private key.'));
122
+ return algorithm;
123
+ }
124
+
125
+ private importKey(): Promise<CryptoKey> {
126
+ const {algorithm, encodedKey} = this.getParsedPrivateKey();
127
+
128
+ if (this.importedKey === undefined) {
129
+ this.importedKey = crypto.subtle
130
+ .importKey(
131
+ 'pkcs8',
132
+ ApiKey.createByteArrayFromString(atob(encodedKey)),
133
+ ApiKey.ALGORITHMS[algorithm].keyAlgorithm,
134
+ false,
135
+ ['sign'],
136
+ );
88
137
  }
89
138
 
90
- return new Promise((resolve, reject) => {
91
- crypto.sign(null, blob, privateKey, (error, signature) => {
92
- if (error == null) {
93
- resolve(signature);
94
- } else {
95
- reject(error);
96
- }
97
- });
98
- });
139
+ return this.importedKey;
99
140
  }
100
141
 
101
- public export(): string {
102
- const privateKey = this.getPrivateKey();
142
+ private getParsedPrivateKey(): ParsedPrivateKey {
143
+ if (this.privateKey === undefined) {
144
+ throw new Error('The API key does not have a private key.');
145
+ }
146
+
147
+ return this.privateKey;
148
+ }
103
149
 
104
- return this.identifier + (privateKey === null ? '' : `:${privateKey}`);
150
+ public export(): string {
151
+ return this.identifier + (this.hasPrivateKey() ? `:${this.getPrivateKey()}` : '');
105
152
  }
106
153
 
107
154
  public toString(): string {
108
155
  return '[redacted]';
109
156
  }
157
+
158
+ /**
159
+ * Create an array buffer from a string.
160
+ *
161
+ * @see https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
162
+ *
163
+ * @param data The string to convert.
164
+ * @returns The array buffer.
165
+ */
166
+ private static createByteArrayFromString(data: string): Uint8Array {
167
+ const byteArray = new Uint8Array(data.length);
168
+
169
+ for (let i = 0; i < byteArray.length; i++) {
170
+ byteArray[i] = data.charCodeAt(i);
171
+ }
172
+
173
+ return byteArray;
174
+ }
175
+
176
+ private static createByteArrayFromHexString(data: string): Uint8Array {
177
+ const byteArray = new Uint8Array(data.length / 2);
178
+
179
+ for (let i = 0; i < byteArray.length; i++) {
180
+ byteArray[i] = parseInt(data.substring(i * 2, i * 2 + 2), 16);
181
+ }
182
+
183
+ return byteArray;
184
+ }
185
+
186
+ /**
187
+ * Convert an array buffer to a string.
188
+ *
189
+ * @see https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
190
+ *
191
+ * @param buffer The buffer to convert.
192
+ * @returns The string.
193
+ */
194
+ private static convertBufferToString(buffer: ArrayLike<number> | ArrayBufferLike): string {
195
+ return String.fromCharCode(...new Uint8Array(buffer));
196
+ }
197
+
198
+ private static convertBufferToHexString(buffer: ArrayLike<number> | ArrayBufferLike): string {
199
+ const bytes = new Uint8Array(buffer);
200
+ let hexString = '';
201
+
202
+ for (let i = 0; i < bytes.length; i++) {
203
+ hexString += bytes[i].toString(16).padStart(2, '0');
204
+ }
205
+
206
+ return hexString;
207
+ }
110
208
  }
@@ -0,0 +1,22 @@
1
+ function base64Unescape(value: string): string {
2
+ return (value + '==='.slice((value.length + 3) % 4)).replace(/-/g, '+').replace(/_/g, '/');
3
+ }
4
+
5
+ function base64Escape(value: string): string {
6
+ return value
7
+ .replace(/\+/g, '-')
8
+ .replace(/\//g, '_')
9
+ .replace(/=/g, '');
10
+ }
11
+
12
+ export function base64UrlEncode(value: string, utf8 = false): string {
13
+ return utf8
14
+ ? base64Escape(btoa(String.fromCodePoint(...new TextEncoder().encode(value))))
15
+ : base64Escape(btoa(value));
16
+ }
17
+
18
+ export function base64UrlDecode(value: string, utf8 = false): string {
19
+ return utf8
20
+ ? new TextDecoder().decode(Uint8Array.from(atob(base64Unescape(value)), m => m.codePointAt(0)!))
21
+ : atob(base64Unescape(value));
22
+ }
@@ -2,3 +2,4 @@ export * from './logger';
2
2
  export {ConsoleLogger} from './consoleLogger';
3
3
  export {NamespacedLogger} from './namespacedLogger';
4
4
  export {NullLogger} from './nullLogger';
5
+ export {FilteredLogger} from './filteredLogger';
@@ -1,17 +1,17 @@
1
1
  import {JsonObject} from '@croct/json';
2
- import {encodeURI as base64Encode, decode as base64Decode} from 'js-base64';
3
2
  import {tokenSchema} from '../schema';
4
3
  import {formatCause} from '../error';
5
4
  import {ApiKey} from '../apiKey';
5
+ import {base64UrlDecode, base64UrlEncode} from '../base64Url';
6
6
 
7
- export type Headers = {
7
+ export type TokenHeaders = {
8
8
  typ: string,
9
9
  alg: string,
10
10
  kid?: string,
11
11
  appId?: string,
12
12
  };
13
13
 
14
- type Claims = {
14
+ export type TokenClaims = {
15
15
  iss: string,
16
16
  aud: string|string[],
17
17
  iat: number,
@@ -20,18 +20,18 @@ type Claims = {
20
20
  jti?: string,
21
21
  };
22
22
 
23
- export type TokenPayload = JsonObject & Claims;
23
+ export type TokenPayload = JsonObject & TokenClaims;
24
24
 
25
25
  export class Token {
26
26
  private static readonly UUID_PATTERN = /^[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$/;
27
27
 
28
- private readonly headers: Headers;
28
+ private readonly headers: TokenHeaders;
29
29
 
30
30
  private readonly payload: TokenPayload;
31
31
 
32
32
  private readonly signature: string;
33
33
 
34
- private constructor(headers: Headers, payload: TokenPayload, signature = '') {
34
+ private constructor(headers: TokenHeaders, payload: TokenPayload, signature = '') {
35
35
  this.headers = headers;
36
36
  this.payload = payload;
37
37
  this.signature = signature;
@@ -81,8 +81,8 @@ export class Token {
81
81
  let payload;
82
82
 
83
83
  try {
84
- headers = JSON.parse(base64Decode(parts[0]));
85
- payload = JSON.parse(base64Decode(parts[1]));
84
+ headers = JSON.parse(base64UrlDecode(parts[0], true));
85
+ payload = JSON.parse(base64UrlDecode(parts[1], true));
86
86
  } catch (error) {
87
87
  throw new Error('The token is corrupted.');
88
88
  }
@@ -90,7 +90,7 @@ export class Token {
90
90
  return Token.of(headers, payload, parts[2]);
91
91
  }
92
92
 
93
- public static of(headers: Headers, payload: TokenPayload, signature = ''): Token {
93
+ public static of(headers: TokenHeaders, payload: TokenPayload, signature = ''): Token {
94
94
  try {
95
95
  tokenSchema.validate({
96
96
  headers: headers,
@@ -101,23 +101,22 @@ export class Token {
101
101
  throw new Error(`The token is invalid: ${formatCause(violation)}`);
102
102
  }
103
103
 
104
- return new Token(headers as Headers, payload as TokenPayload, signature as string);
104
+ return new Token(headers as TokenHeaders, payload as TokenPayload, signature as string);
105
105
  }
106
106
 
107
107
  public async signedWith(apiKey: ApiKey): Promise<Token> {
108
108
  const keyId = await apiKey.getIdentifierHash();
109
- const headers: Headers = {
109
+ const headers: TokenHeaders = {
110
110
  ...this.headers,
111
111
  kid: keyId,
112
- alg: 'EdDSA',
112
+ alg: apiKey.getSigningAlgorithm(),
113
113
  };
114
114
 
115
- const encodedHeader = base64Encode(JSON.stringify(headers));
116
- const encodedPayload = base64Encode(JSON.stringify(this.payload));
117
- const signatureData = `${encodedHeader}.${encodedPayload}`;
118
- const signature = await apiKey.sign(Buffer.from(signatureData, 'utf-8'));
115
+ const encodedHeader = base64UrlEncode(JSON.stringify(headers), true);
116
+ const encodedPayload = base64UrlEncode(JSON.stringify(this.payload), true);
117
+ const signature = await apiKey.sign(`${encodedHeader}.${encodedPayload}`);
119
118
 
120
- return new Token(headers, this.payload, signature.toString('base64url'));
119
+ return new Token(headers, this.payload, base64UrlEncode(signature, false));
121
120
  }
122
121
 
123
122
  public isSigned(): boolean {
@@ -146,22 +145,7 @@ export class Token {
146
145
  return this.headers.kid === await apiKey.getIdentifierHash();
147
146
  }
148
147
 
149
- public withTokenId(tokenId: string): Token {
150
- if (tokenId === '' || !Token.UUID_PATTERN.test(tokenId)) {
151
- throw new Error('The token ID must be a valid UUID.');
152
- }
153
-
154
- return new Token(
155
- this.headers,
156
- {
157
- ...this.payload,
158
- jti: tokenId,
159
- },
160
- this.signature,
161
- );
162
- }
163
-
164
- public getHeaders(): Headers {
148
+ public getHeaders(): TokenHeaders {
165
149
  return {...this.headers};
166
150
  }
167
151
 
@@ -213,13 +197,84 @@ export class Token {
213
197
  return this.payload.iss;
214
198
  }
215
199
 
200
+ public withTokenId(tokenId: string): Token {
201
+ if (tokenId === '' || !Token.UUID_PATTERN.test(tokenId)) {
202
+ throw new Error('The token ID must be a valid UUID.');
203
+ }
204
+
205
+ return new Token(
206
+ this.headers,
207
+ {
208
+ ...this.payload,
209
+ jti: tokenId,
210
+ },
211
+ this.signature,
212
+ );
213
+ }
214
+
215
+ public withDuration(duration: number, now: number = Math.floor(Date.now() / 1000)): Token {
216
+ return new Token(
217
+ this.headers,
218
+ {
219
+ ...this.payload,
220
+ iat: now,
221
+ exp: now + duration,
222
+ },
223
+ this.signature,
224
+ );
225
+ }
226
+
227
+ public withAddedHeaders(headers: Partial<TokenHeaders>): Token {
228
+ return this.withHeaders({
229
+ ...this.headers,
230
+ ...Object.fromEntries(
231
+ Object.entries(headers)
232
+ .filter(([, value]) => value !== undefined),
233
+ ),
234
+ });
235
+ }
236
+
237
+ public withAddedClaims(claims: Partial<TokenClaims>): Token {
238
+ return this.withPayload({
239
+ ...this.payload,
240
+ ...Object.fromEntries(
241
+ Object.entries(claims)
242
+ .filter(([, value]) => value !== undefined),
243
+ ),
244
+ });
245
+ }
246
+
247
+ public withHeaders(headers: TokenHeaders): Token {
248
+ return new Token(
249
+ headers,
250
+ this.payload,
251
+ this.signature,
252
+ );
253
+ }
254
+
255
+ public withPayload(payload: TokenPayload): Token {
256
+ return new Token(
257
+ this.headers,
258
+ payload,
259
+ this.signature,
260
+ );
261
+ }
262
+
263
+ public withSignature(signature: string): Token {
264
+ return new Token(
265
+ this.headers,
266
+ this.payload,
267
+ signature,
268
+ );
269
+ }
270
+
216
271
  public toJSON(): string {
217
272
  return this.toString();
218
273
  }
219
274
 
220
275
  public toString(): string {
221
- const headers = base64Encode(JSON.stringify(this.headers));
222
- const payload = base64Encode(JSON.stringify(this.payload));
276
+ const headers = base64UrlEncode(JSON.stringify(this.headers), true);
277
+ const payload = base64UrlEncode(JSON.stringify(this.payload), true);
223
278
 
224
279
  return `${headers}.${payload}.${this.signature}`;
225
280
  }
package/token/token.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { JsonObject } from '@croct/json';
2
2
  import { ApiKey } from '../apiKey';
3
- export type Headers = {
3
+ export type TokenHeaders = {
4
4
  typ: string;
5
5
  alg: string;
6
6
  kid?: string;
7
7
  appId?: string;
8
8
  };
9
- type Claims = {
9
+ export type TokenClaims = {
10
10
  iss: string;
11
11
  aud: string | string[];
12
12
  iat: number;
@@ -14,7 +14,7 @@ type Claims = {
14
14
  sub?: string;
15
15
  jti?: string;
16
16
  };
17
- export type TokenPayload = JsonObject & Claims;
17
+ export type TokenPayload = JsonObject & TokenClaims;
18
18
  export declare class Token {
19
19
  private static readonly UUID_PATTERN;
20
20
  private readonly headers;
@@ -23,7 +23,7 @@ export declare class Token {
23
23
  private constructor();
24
24
  static issue(appId: string, subject?: string | null, timestamp?: number): Token;
25
25
  static parse(token: string): Token;
26
- static of(headers: Headers, payload: TokenPayload, signature?: string): Token;
26
+ static of(headers: TokenHeaders, payload: TokenPayload, signature?: string): Token;
27
27
  signedWith(apiKey: ApiKey): Promise<Token>;
28
28
  isSigned(): boolean;
29
29
  isSubject(subject: string): boolean;
@@ -31,8 +31,7 @@ export declare class Token {
31
31
  isValidNow(now?: number): boolean;
32
32
  isNewerThan(token: Token): boolean;
33
33
  matchesKeyId(apiKey: ApiKey): Promise<boolean>;
34
- withTokenId(tokenId: string): Token;
35
- getHeaders(): Headers;
34
+ getHeaders(): TokenHeaders;
36
35
  getPayload(): TokenPayload;
37
36
  getSignature(): string;
38
37
  getApplicationId(): string | null;
@@ -45,6 +44,13 @@ export declare class Token {
45
44
  getTokenId(): string | null;
46
45
  getAudience(): string | string[];
47
46
  getIssuer(): string;
47
+ withTokenId(tokenId: string): Token;
48
+ withDuration(duration: number, now?: number): Token;
49
+ withAddedHeaders(headers: Partial<TokenHeaders>): Token;
50
+ withAddedClaims(claims: Partial<TokenClaims>): Token;
51
+ withHeaders(headers: TokenHeaders): Token;
52
+ withPayload(payload: TokenPayload): Token;
53
+ withSignature(signature: string): Token;
48
54
  toJSON(): string;
49
55
  toString(): string;
50
56
  }
@@ -59,4 +65,3 @@ export declare class FixedTokenProvider implements TokenProvider {
59
65
  constructor(token: Token | null);
60
66
  getToken(): Token | null;
61
67
  }
62
- export {};
package/token/token.js CHANGED
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FixedTokenProvider = exports.Token = void 0;
4
- const js_base64_1 = require("js-base64");
5
4
  const schema_1 = require("../schema");
6
5
  const error_1 = require("../error");
6
+ const base64Url_1 = require("../base64Url");
7
7
  class Token {
8
8
  constructor(headers, payload, signature = '') {
9
9
  this.headers = headers;
@@ -40,8 +40,8 @@ class Token {
40
40
  let headers;
41
41
  let payload;
42
42
  try {
43
- headers = JSON.parse((0, js_base64_1.decode)(parts[0]));
44
- payload = JSON.parse((0, js_base64_1.decode)(parts[1]));
43
+ headers = JSON.parse((0, base64Url_1.base64UrlDecode)(parts[0], true));
44
+ payload = JSON.parse((0, base64Url_1.base64UrlDecode)(parts[1], true));
45
45
  }
46
46
  catch (error) {
47
47
  throw new Error('The token is corrupted.');
@@ -66,13 +66,12 @@ class Token {
66
66
  const headers = {
67
67
  ...this.headers,
68
68
  kid: keyId,
69
- alg: 'EdDSA',
69
+ alg: apiKey.getSigningAlgorithm(),
70
70
  };
71
- const encodedHeader = (0, js_base64_1.encodeURI)(JSON.stringify(headers));
72
- const encodedPayload = (0, js_base64_1.encodeURI)(JSON.stringify(this.payload));
73
- const signatureData = `${encodedHeader}.${encodedPayload}`;
74
- const signature = await apiKey.sign(Buffer.from(signatureData, 'utf-8'));
75
- return new Token(headers, this.payload, signature.toString('base64url'));
71
+ const encodedHeader = (0, base64Url_1.base64UrlEncode)(JSON.stringify(headers), true);
72
+ const encodedPayload = (0, base64Url_1.base64UrlEncode)(JSON.stringify(this.payload), true);
73
+ const signature = await apiKey.sign(`${encodedHeader}.${encodedPayload}`);
74
+ return new Token(headers, this.payload, (0, base64Url_1.base64UrlEncode)(signature, false));
76
75
  }
77
76
  isSigned() {
78
77
  return this.headers.alg !== 'none' && this.signature !== '';
@@ -93,15 +92,6 @@ class Token {
93
92
  async matchesKeyId(apiKey) {
94
93
  return this.headers.kid === await apiKey.getIdentifierHash();
95
94
  }
96
- withTokenId(tokenId) {
97
- if (tokenId === '' || !Token.UUID_PATTERN.test(tokenId)) {
98
- throw new Error('The token ID must be a valid UUID.');
99
- }
100
- return new Token(this.headers, {
101
- ...this.payload,
102
- jti: tokenId,
103
- }, this.signature);
104
- }
105
95
  getHeaders() {
106
96
  return { ...this.headers };
107
97
  }
@@ -146,12 +136,51 @@ class Token {
146
136
  getIssuer() {
147
137
  return this.payload.iss;
148
138
  }
139
+ withTokenId(tokenId) {
140
+ if (tokenId === '' || !Token.UUID_PATTERN.test(tokenId)) {
141
+ throw new Error('The token ID must be a valid UUID.');
142
+ }
143
+ return new Token(this.headers, {
144
+ ...this.payload,
145
+ jti: tokenId,
146
+ }, this.signature);
147
+ }
148
+ withDuration(duration, now = Math.floor(Date.now() / 1000)) {
149
+ return new Token(this.headers, {
150
+ ...this.payload,
151
+ iat: now,
152
+ exp: now + duration,
153
+ }, this.signature);
154
+ }
155
+ withAddedHeaders(headers) {
156
+ return this.withHeaders({
157
+ ...this.headers,
158
+ ...Object.fromEntries(Object.entries(headers)
159
+ .filter(([, value]) => value !== undefined)),
160
+ });
161
+ }
162
+ withAddedClaims(claims) {
163
+ return this.withPayload({
164
+ ...this.payload,
165
+ ...Object.fromEntries(Object.entries(claims)
166
+ .filter(([, value]) => value !== undefined)),
167
+ });
168
+ }
169
+ withHeaders(headers) {
170
+ return new Token(headers, this.payload, this.signature);
171
+ }
172
+ withPayload(payload) {
173
+ return new Token(this.headers, payload, this.signature);
174
+ }
175
+ withSignature(signature) {
176
+ return new Token(this.headers, this.payload, signature);
177
+ }
149
178
  toJSON() {
150
179
  return this.toString();
151
180
  }
152
181
  toString() {
153
- const headers = (0, js_base64_1.encodeURI)(JSON.stringify(this.headers));
154
- const payload = (0, js_base64_1.encodeURI)(JSON.stringify(this.payload));
182
+ const headers = (0, base64Url_1.base64UrlEncode)(JSON.stringify(this.headers), true);
183
+ const payload = (0, base64Url_1.base64UrlEncode)(JSON.stringify(this.payload), true);
155
184
  return `${headers}.${payload}.${this.signature}`;
156
185
  }
157
186
  }
@@ -1 +1 @@
1
- {"version":3,"file":"token.js","sourceRoot":"","sources":["../src/token/token.ts"],"names":[],"mappings":";;;AACA,yCAA4E;AAC5E,sCAAsC;AACtC,oCAAqC;AAqBrC,MAAa,KAAK;IASd,YAAoB,OAAgB,EAAE,OAAqB,EAAE,SAAS,GAAG,EAAE;QACvE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC/B,CAAC;IAEM,MAAM,CAAC,KAAK,CACf,KAAa,EACb,UAAuB,IAAI,EAC3B,YAAoB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QAEjD,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAC3D,CAAC;QAED,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACtD,CAAC;QAED,OAAO,IAAI,KAAK,CACZ;YACI,GAAG,EAAE,KAAK;YACV,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,KAAK;SACf,EACD;YACI,GAAG,EAAE,UAAU;YACf,GAAG,EAAE,UAAU;YACf,GAAG,EAAE,SAAS;YACd,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,EAAC,GAAG,EAAE,OAAO,EAAC,CAAC,CAAC,CAAC,IAAI,CAAC;SAChD,CACJ,CAAC;IACN,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,KAAa;QAC7B,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAClD,CAAC;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAElC,wBAAwB;QACxB,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,OAAO,CAAC;QACZ,IAAI,OAAO,CAAC;QAEZ,IAAI,CAAC;YACD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,kBAAY,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7C,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,kBAAY,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC/C,CAAC;QAED,OAAO,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IAEM,MAAM,CAAC,EAAE,CAAC,OAAgB,EAAE,OAAqB,EAAE,SAAS,GAAG,EAAE;QACpE,IAAI,CAAC;YACD,oBAAW,CAAC,QAAQ,CAAC;gBACjB,OAAO,EAAE,OAAO;gBAChB,OAAO,EAAE,OAAO;gBAChB,SAAS,EAAE,SAAS;aACvB,CAAC,CAAC;QACP,CAAC;QAAC,OAAO,SAAS,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAA,mBAAW,EAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,OAAO,IAAI,KAAK,CAAC,OAAkB,EAAE,OAAuB,EAAE,SAAmB,CAAC,CAAC;IACvF,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,MAAc;QAClC,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC/C,MAAM,OAAO,GAAY;YACrB,GAAG,IAAI,CAAC,OAAO;YACf,GAAG,EAAE,KAAK;YACV,GAAG,EAAE,OAAO;SACf,CAAC;QAEF,MAAM,aAAa,GAAG,IAAA,qBAAY,EAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5D,MAAM,cAAc,GAAG,IAAA,qBAAY,EAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAClE,MAAM,aAAa,GAAG,GAAG,aAAa,IAAI,cAAc,EAAE,CAAC;QAC3D,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC;QAEzE,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;IAC7E,CAAC;IAEM,QAAQ;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,KAAK,MAAM,IAAI,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;IAChE,CAAC;IAEM,SAAS,CAAC,OAAe;QAC5B,OAAO,IAAI,CAAC,UAAU,EAAE,KAAK,OAAO,CAAC;IACzC,CAAC;IAEM,WAAW;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC;IAC1C,CAAC;IAEM,UAAU,CAAC,MAAc,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QACzD,MAAM,EAAC,GAAG,EAAE,GAAG,EAAC,GAAG,IAAI,CAAC,OAAO,CAAC;QAEhC,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,GAAG,IAAI,GAAG,CAAC;IAC3D,CAAC;IAEM,WAAW,CAAC,KAAY;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;IAChD,CAAC;IAEM,KAAK,CAAC,YAAY,CAAC,MAAc;QACpC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,KAAK,MAAM,MAAM,CAAC,iBAAiB,EAAE,CAAC;IACjE,CAAC;IAEM,WAAW,CAAC,OAAe;QAC9B,IAAI,OAAO,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACtD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO,IAAI,KAAK,CACZ,IAAI,CAAC,OAAO,EACZ;YACI,GAAG,IAAI,CAAC,OAAO;YACf,GAAG,EAAE,OAAO;SACf,EACD,IAAI,CAAC,SAAS,CACjB,CAAC;IACN,CAAC;IAEM,UAAU;QACb,OAAO,EAAC,GAAG,IAAI,CAAC,OAAO,EAAC,CAAC;IAC7B,CAAC;IAEM,UAAU;QACb,OAAO,EAAC,GAAG,IAAI,CAAC,OAAO,EAAC,CAAC;IAC7B,CAAC;IAEM,YAAY;QACf,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAEM,gBAAgB;;QACnB,OAAO,MAAA,IAAI,CAAC,OAAO,CAAC,KAAK,mCAAI,IAAI,CAAC;IACtC,CAAC;IAEM,YAAY;QACf,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;IAC5B,CAAC;IAEM,OAAO;QACV,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;IAC5B,CAAC;IAEM,QAAQ;;QACX,OAAO,MAAA,IAAI,CAAC,OAAO,CAAC,GAAG,mCAAI,IAAI,CAAC;IACpC,CAAC;IAEM,UAAU;;QACb,OAAO,MAAA,IAAI,CAAC,OAAO,CAAC,GAAG,mCAAI,IAAI,CAAC;IACpC,CAAC;IAEM,YAAY;QACf,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;IAC5B,CAAC;IAEM,iBAAiB;;QACpB,OAAO,MAAA,IAAI,CAAC,OAAO,CAAC,GAAG,mCAAI,IAAI,CAAC;IACpC,CAAC;IAEM,UAAU;;QACb,OAAO,MAAA,IAAI,CAAC,OAAO,CAAC,GAAG,mCAAI,IAAI,CAAC;IACpC,CAAC;IAEM,WAAW;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;IAC5B,CAAC;IAEM,SAAS;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;IAC5B,CAAC;IAEM,MAAM;QACT,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;IAEM,QAAQ;QACX,MAAM,OAAO,GAAG,IAAA,qBAAY,EAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAG,IAAA,qBAAY,EAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAE3D,OAAO,GAAG,OAAO,IAAI,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;IACrD,CAAC;;AAxML,sBAyMC;AAxM2B,kBAAY,GAAG,6CAA6C,CAAC;AAkNzF,MAAa,kBAAkB;IAG3B,YAAmB,KAAmB;QAClC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC;IAEM,QAAQ;QACX,OAAO,IAAI,CAAC,KAAK,CAAC;IACtB,CAAC;CACJ;AAVD,gDAUC"}
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../src/token/token.ts"],"names":[],"mappings":"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"}