shelving 1.136.0 → 1.138.0
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/package.json +1 -1
- package/util/base64.d.ts +12 -7
- package/util/base64.js +72 -11
- package/util/buffer.d.ts +7 -0
- package/util/buffer.js +12 -0
- package/util/bytes.d.ts +12 -0
- package/util/bytes.js +24 -0
- package/util/index.d.ts +3 -0
- package/util/index.js +3 -0
- package/util/jwt.d.ts +31 -0
- package/util/jwt.js +101 -0
- package/util/validate.d.ts +1 -1
- package/util/validate.js +3 -3
package/package.json
CHANGED
package/util/base64.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { type PossibleBytes } from "./bytes.js";
|
|
2
|
+
/** Encode a string or binary data to Base64 string. */
|
|
3
|
+
export declare function encodeBase64(input: PossibleBytes, pad?: boolean): string;
|
|
4
|
+
/** Decode Base64 string to string. */
|
|
5
|
+
export declare function decodeBase64String(base64: string): string;
|
|
6
|
+
/** Decode URL-safe Base64 string to binary data (as a UInt8Array). */
|
|
7
|
+
export declare function decodeBase64Bytes(base64: string): Uint8Array;
|
|
8
|
+
/** Encode a string or binary data to URL-safe Base64 */
|
|
9
|
+
export declare function encodeBase64Url(input: PossibleBytes, pad?: boolean): string;
|
|
7
10
|
/** Decode a string from URL-safe Base64. */
|
|
8
|
-
export declare function
|
|
11
|
+
export declare function decodeBase64UrlString(base64: string): string;
|
|
12
|
+
/** Decode URL-safe Base64 string to binary data (as a UInt8Array). */
|
|
13
|
+
export declare function decodeBase64UrlBytes(base64: string): Uint8Array;
|
package/util/base64.js
CHANGED
|
@@ -1,16 +1,77 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { requireBytes } from "./bytes.js";
|
|
2
|
+
const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
3
|
+
const BASE64URL_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
4
|
+
/**
|
|
5
|
+
* @todo DH: When it's well supported, use `Uint8Array.toBase64()`: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array/toBase64
|
|
6
|
+
*/
|
|
7
|
+
function _encode(bytes, alphabet, pad) {
|
|
8
|
+
const len = bytes.length;
|
|
9
|
+
let output = "";
|
|
10
|
+
for (let i = 0; i < len; i += 3) {
|
|
11
|
+
const b1 = bytes[i];
|
|
12
|
+
const b2 = i + 1 < len ? bytes[i + 1] : 0;
|
|
13
|
+
const b3 = i + 2 < len ? bytes[i + 2] : 0;
|
|
14
|
+
const combined = (b1 << 16) | (b2 << 8) | b3;
|
|
15
|
+
const c1 = (combined >> 18) & 0x3f;
|
|
16
|
+
const c2 = (combined >> 12) & 0x3f;
|
|
17
|
+
const c3 = (combined >> 6) & 0x3f;
|
|
18
|
+
const c4 = combined & 0x3f;
|
|
19
|
+
output += `${alphabet[c1]}${alphabet[c2]}${i + 1 < len ? alphabet[c3] : pad}${i + 2 < len ? alphabet[c4] : pad}`;
|
|
20
|
+
}
|
|
21
|
+
return output;
|
|
4
22
|
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
23
|
+
function _decode(base64, alphabet) {
|
|
24
|
+
// Create a reverse lookup table: char -> 6-bit value
|
|
25
|
+
const values = new Uint8Array(128);
|
|
26
|
+
for (let i = 0; i < alphabet.length; i++)
|
|
27
|
+
values[alphabet.charCodeAt(i)] = i;
|
|
28
|
+
// Remove padding.
|
|
29
|
+
const cleaned = base64.replace(/=+$/, "");
|
|
30
|
+
const length = cleaned.length;
|
|
31
|
+
// Calculate output byte length
|
|
32
|
+
// Every 4 base64 chars = 3 bytes; adjust for padding
|
|
33
|
+
const outputLength = Math.floor((length * 6) / 8);
|
|
34
|
+
const output = new Uint8Array(outputLength);
|
|
35
|
+
let j = 0;
|
|
36
|
+
for (let i = 0; i < length; i += 4) {
|
|
37
|
+
// Get 4 characters (or less at the end)
|
|
38
|
+
const c1 = values[cleaned.charCodeAt(i)];
|
|
39
|
+
const c2 = values[cleaned.charCodeAt(i + 1)];
|
|
40
|
+
const c3 = i + 2 < length ? values[cleaned.charCodeAt(i + 2)] : 0;
|
|
41
|
+
const c4 = i + 3 < length ? values[cleaned.charCodeAt(i + 3)] : 0;
|
|
42
|
+
// Combine into 24 bits
|
|
43
|
+
const combined = (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
|
|
44
|
+
// Extract bytes and add to output if within range
|
|
45
|
+
if (j < outputLength)
|
|
46
|
+
output[j++] = (combined >> 16) & 0xff;
|
|
47
|
+
if (j < outputLength)
|
|
48
|
+
output[j++] = (combined >> 8) & 0xff;
|
|
49
|
+
if (j < outputLength)
|
|
50
|
+
output[j++] = combined & 0xff;
|
|
51
|
+
}
|
|
52
|
+
return output;
|
|
8
53
|
}
|
|
9
|
-
/** Encode a string to
|
|
10
|
-
export function
|
|
11
|
-
return
|
|
54
|
+
/** Encode a string or binary data to Base64 string. */
|
|
55
|
+
export function encodeBase64(input, pad = true) {
|
|
56
|
+
return _encode(requireBytes(input), BASE64_CHARS, pad ? "=" : "");
|
|
57
|
+
}
|
|
58
|
+
/** Decode Base64 string to string. */
|
|
59
|
+
export function decodeBase64String(base64) {
|
|
60
|
+
return new TextDecoder("utf-8").decode(_decode(base64, BASE64_CHARS));
|
|
61
|
+
}
|
|
62
|
+
/** Decode URL-safe Base64 string to binary data (as a UInt8Array). */
|
|
63
|
+
export function decodeBase64Bytes(base64) {
|
|
64
|
+
return _decode(base64, BASE64_CHARS);
|
|
65
|
+
}
|
|
66
|
+
/** Encode a string or binary data to URL-safe Base64 */
|
|
67
|
+
export function encodeBase64Url(input, pad = false) {
|
|
68
|
+
return _encode(requireBytes(input), BASE64URL_CHARS, pad ? "=" : "");
|
|
12
69
|
}
|
|
13
70
|
/** Decode a string from URL-safe Base64. */
|
|
14
|
-
export function
|
|
15
|
-
return
|
|
71
|
+
export function decodeBase64UrlString(base64) {
|
|
72
|
+
return new TextDecoder("utf-8").decode(_decode(base64, BASE64URL_CHARS));
|
|
73
|
+
}
|
|
74
|
+
/** Decode URL-safe Base64 string to binary data (as a UInt8Array). */
|
|
75
|
+
export function decodeBase64UrlBytes(base64) {
|
|
76
|
+
return _decode(base64, BASE64URL_CHARS);
|
|
16
77
|
}
|
package/util/buffer.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type TypedArray<T extends ArrayBufferLike = ArrayBufferLike> = Uint8Array<T> | Uint16Array<T> | Uint32Array<T> | Int8Array<T> | Int16Array<T> | Int32Array<T> | Float32Array<T> | Float64Array<T>;
|
|
2
|
+
/** Detect if an unknown value is an `ArrayBuffer` (not a view like `Uint8Array` or `Float32Array` or `DataView`). */
|
|
3
|
+
export declare function isBuffer(value: unknown): value is ArrayBuffer;
|
|
4
|
+
/** Detect if an unknown value is an `ArrayBufferView`, like `Uint8Array` or `Float32Array` or `DataView` */
|
|
5
|
+
export declare function isBufferView(value: unknown): value is ArrayBufferView;
|
|
6
|
+
/** Detect if an unknown value is a `TypedArray`, like `Uint8Array` or `Float32Array` (not including `DataView`). */
|
|
7
|
+
export declare function isTypedArray(value: unknown): value is TypedArray;
|
package/util/buffer.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Detect if an unknown value is an `ArrayBuffer` (not a view like `Uint8Array` or `Float32Array` or `DataView`). */
|
|
2
|
+
export function isBuffer(value) {
|
|
3
|
+
return value instanceof ArrayBuffer;
|
|
4
|
+
}
|
|
5
|
+
/** Detect if an unknown value is an `ArrayBufferView`, like `Uint8Array` or `Float32Array` or `DataView` */
|
|
6
|
+
export function isBufferView(value) {
|
|
7
|
+
return ArrayBuffer.isView(value);
|
|
8
|
+
}
|
|
9
|
+
/** Detect if an unknown value is a `TypedArray`, like `Uint8Array` or `Float32Array` (not including `DataView`). */
|
|
10
|
+
export function isTypedArray(value) {
|
|
11
|
+
return value instanceof Object.getPrototypeOf(Uint8Array);
|
|
12
|
+
}
|
package/util/bytes.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Types that can be converted to a `Uint8Array` byte sequence. */
|
|
2
|
+
export type PossibleBytes = Uint8Array | ArrayBuffer | string;
|
|
3
|
+
/**
|
|
4
|
+
* Convert an unknown value to a `Uint8Array` byte sequence, or `undefined` if the value cannot be converted.
|
|
5
|
+
*
|
|
6
|
+
* - ArrayBuffers and TypedArrays are converted to `Uint8Array`
|
|
7
|
+
* - Strings are encoded as UTF-8.
|
|
8
|
+
* - Everything else returns `undefined`
|
|
9
|
+
*/
|
|
10
|
+
export declare function getBytes(value: unknown): Uint8Array | undefined;
|
|
11
|
+
/** Convert an unknown value to a `Uint8Array` byte sequence, or throw `RequiredError` if the value cannot be converted. */
|
|
12
|
+
export declare function requireBytes(value: PossibleBytes): Uint8Array;
|
package/util/bytes.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { RequiredError } from "../error/RequiredError.js";
|
|
2
|
+
/**
|
|
3
|
+
* Convert an unknown value to a `Uint8Array` byte sequence, or `undefined` if the value cannot be converted.
|
|
4
|
+
*
|
|
5
|
+
* - ArrayBuffers and TypedArrays are converted to `Uint8Array`
|
|
6
|
+
* - Strings are encoded as UTF-8.
|
|
7
|
+
* - Everything else returns `undefined`
|
|
8
|
+
*/
|
|
9
|
+
export function getBytes(value) {
|
|
10
|
+
if (value instanceof Uint8Array)
|
|
11
|
+
return value;
|
|
12
|
+
if (value instanceof ArrayBuffer)
|
|
13
|
+
return new Uint8Array(value);
|
|
14
|
+
if (typeof value === "string")
|
|
15
|
+
return new TextEncoder().encode(value);
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
/** Convert an unknown value to a `Uint8Array` byte sequence, or throw `RequiredError` if the value cannot be converted. */
|
|
19
|
+
export function requireBytes(value) {
|
|
20
|
+
const bytes = getBytes(value);
|
|
21
|
+
if (bytes === undefined)
|
|
22
|
+
throw new RequiredError("Value cannot be converted to byte array", { received: value, caller: requireBytes });
|
|
23
|
+
return bytes;
|
|
24
|
+
}
|
package/util/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export * from "./array.js";
|
|
|
2
2
|
export * from "./async.js";
|
|
3
3
|
export * from "./base64.js";
|
|
4
4
|
export * from "./boolean.js";
|
|
5
|
+
export * from "./buffer.js";
|
|
6
|
+
export * from "./bytes.js";
|
|
5
7
|
export * from "./callback.js";
|
|
6
8
|
export * from "./class.js";
|
|
7
9
|
export * from "./color.js";
|
|
@@ -25,6 +27,7 @@ export * from "./hydrate.js";
|
|
|
25
27
|
export * from "./item.js";
|
|
26
28
|
export * from "./iterate.js";
|
|
27
29
|
export * from "./jsx.js";
|
|
30
|
+
export * from "./jwt.js";
|
|
28
31
|
export * from "./lazy.js";
|
|
29
32
|
export * from "./link.js";
|
|
30
33
|
export * from "./map.js";
|
package/util/index.js
CHANGED
|
@@ -2,6 +2,8 @@ export * from "./array.js";
|
|
|
2
2
|
export * from "./async.js";
|
|
3
3
|
export * from "./base64.js";
|
|
4
4
|
export * from "./boolean.js";
|
|
5
|
+
export * from "./buffer.js";
|
|
6
|
+
export * from "./bytes.js";
|
|
5
7
|
export * from "./callback.js";
|
|
6
8
|
export * from "./class.js";
|
|
7
9
|
export * from "./color.js";
|
|
@@ -25,6 +27,7 @@ export * from "./hydrate.js";
|
|
|
25
27
|
export * from "./item.js";
|
|
26
28
|
export * from "./iterate.js";
|
|
27
29
|
export * from "./jsx.js";
|
|
30
|
+
export * from "./jwt.js";
|
|
28
31
|
export * from "./lazy.js";
|
|
29
32
|
export * from "./link.js";
|
|
30
33
|
export * from "./map.js";
|
package/util/jwt.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Data } from "./data.js";
|
|
2
|
+
import type { AnyFunction } from "./function.js";
|
|
3
|
+
/**
|
|
4
|
+
* Encode a JWT and return the string token.
|
|
5
|
+
* - Currently only supports HMAC SHA-512 signing.
|
|
6
|
+
*
|
|
7
|
+
* @throws ValueError If the input parameters, e.g. `secret` or `issuer`, are invalid.
|
|
8
|
+
*/
|
|
9
|
+
export declare function encodeToken(claims: Data, secret: string): Promise<string>;
|
|
10
|
+
/** Parts that make up a JSON Web Token. */
|
|
11
|
+
export type TokenData = {
|
|
12
|
+
header: string;
|
|
13
|
+
payload: string;
|
|
14
|
+
signature: string;
|
|
15
|
+
headerData: Data;
|
|
16
|
+
payloadData: Data;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Split a JSON Web Token into its header, payload, and signature, and decode and parse the JSON.
|
|
20
|
+
*/
|
|
21
|
+
export declare function splitToken(token: unknown): TokenData;
|
|
22
|
+
export declare function _splitToken(caller: AnyFunction, token: unknown): TokenData;
|
|
23
|
+
/**
|
|
24
|
+
* Decode a JWT, verify it, and return the full payload data.
|
|
25
|
+
* - Currently only supports HMAC SHA-512 signing.
|
|
26
|
+
*
|
|
27
|
+
* @throws ValueError If the input parameters, e.g. `secret` or `issuer`, are invalid.
|
|
28
|
+
* @throws RequestError If the token is invalid or malformed.
|
|
29
|
+
* @throws UnauthorizedError If the token signature is incorrect, token is expired or not issued yet.
|
|
30
|
+
*/
|
|
31
|
+
export declare function verifyToken(token: unknown, secret: string): Promise<Data>;
|
package/util/jwt.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { RequestError, UnauthorizedError } from "../error/RequestError.js";
|
|
2
|
+
import { ValueError } from "../error/ValueError.js";
|
|
3
|
+
import { decodeBase64UrlBytes, decodeBase64UrlString, encodeBase64Url } from "./base64.js";
|
|
4
|
+
import { requireBytes } from "./bytes.js";
|
|
5
|
+
import { DAY } from "./constants.js";
|
|
6
|
+
// Constants.
|
|
7
|
+
const TOKEN_HEADER = { alg: "HS512", typ: "JWT" };
|
|
8
|
+
const TOKEN_EXPIRY_MS = DAY * 10;
|
|
9
|
+
const TOKEN_MINIMUM_SECRET = 16;
|
|
10
|
+
function _getKey(secret, ...usages) {
|
|
11
|
+
return crypto.subtle.importKey("raw", requireBytes(secret), { name: "HMAC", hash: { name: "SHA-512" } }, false, usages);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Encode a JWT and return the string token.
|
|
15
|
+
* - Currently only supports HMAC SHA-512 signing.
|
|
16
|
+
*
|
|
17
|
+
* @throws ValueError If the input parameters, e.g. `secret` or `issuer`, are invalid.
|
|
18
|
+
*/
|
|
19
|
+
export async function encodeToken(claims, secret) {
|
|
20
|
+
if (typeof secret !== "string" || secret.length < TOKEN_MINIMUM_SECRET)
|
|
21
|
+
throw new ValueError(`JWT secret must be string with minimum ${TOKEN_MINIMUM_SECRET} characters`, {
|
|
22
|
+
received: secret,
|
|
23
|
+
caller: encodeToken,
|
|
24
|
+
});
|
|
25
|
+
// Encode header.
|
|
26
|
+
const header = encodeBase64Url(JSON.stringify(TOKEN_HEADER));
|
|
27
|
+
// Encode payload.
|
|
28
|
+
const iat = Math.floor(Date.now() / 1000);
|
|
29
|
+
const exp = Math.floor(iat + TOKEN_EXPIRY_MS / 1000);
|
|
30
|
+
const payload = encodeBase64Url(JSON.stringify({ iat, exp, ...claims }));
|
|
31
|
+
// Create signature.
|
|
32
|
+
const key = await _getKey(secret, "sign");
|
|
33
|
+
const signature = encodeBase64Url(await crypto.subtle.sign("HMAC", key, requireBytes(`${header}.${payload}`)));
|
|
34
|
+
// Combine token.
|
|
35
|
+
return `${header}.${payload}.${signature}`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Split a JSON Web Token into its header, payload, and signature, and decode and parse the JSON.
|
|
39
|
+
*/
|
|
40
|
+
export function splitToken(token) {
|
|
41
|
+
return _splitToken(splitToken, token);
|
|
42
|
+
}
|
|
43
|
+
export function _splitToken(caller, token) {
|
|
44
|
+
if (typeof token !== "string")
|
|
45
|
+
throw new RequestError("JWT token must be string", { received: token, caller });
|
|
46
|
+
// Split token.
|
|
47
|
+
const [header, payload, signature] = token.split(".");
|
|
48
|
+
if (!header || !payload || !signature)
|
|
49
|
+
throw new RequestError("JWT token must have header, payload, and signature", { received: token, caller });
|
|
50
|
+
// Decode header.
|
|
51
|
+
let headerData;
|
|
52
|
+
try {
|
|
53
|
+
headerData = JSON.parse(decodeBase64UrlString(header));
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
throw new RequestError("JWT token header must be base64Url encoded JSON", { received: token, caller });
|
|
57
|
+
}
|
|
58
|
+
// Decode payload.
|
|
59
|
+
let payloadData;
|
|
60
|
+
try {
|
|
61
|
+
payloadData = JSON.parse(decodeBase64UrlString(payload));
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
throw new RequestError("JWT token payload must be base64Url encoded JSON", { received: token, caller });
|
|
65
|
+
}
|
|
66
|
+
return { header, payload, headerData, payloadData, signature };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Decode a JWT, verify it, and return the full payload data.
|
|
70
|
+
* - Currently only supports HMAC SHA-512 signing.
|
|
71
|
+
*
|
|
72
|
+
* @throws ValueError If the input parameters, e.g. `secret` or `issuer`, are invalid.
|
|
73
|
+
* @throws RequestError If the token is invalid or malformed.
|
|
74
|
+
* @throws UnauthorizedError If the token signature is incorrect, token is expired or not issued yet.
|
|
75
|
+
*/
|
|
76
|
+
export async function verifyToken(token, secret) {
|
|
77
|
+
if (typeof secret !== "string" || secret.length < TOKEN_MINIMUM_SECRET)
|
|
78
|
+
throw new ValueError(`JWT secret must be string with minimum ${TOKEN_MINIMUM_SECRET} characters`, {
|
|
79
|
+
received: secret,
|
|
80
|
+
caller: verifyToken,
|
|
81
|
+
});
|
|
82
|
+
const { header, payload, signature, headerData, payloadData } = _splitToken(verifyToken, token);
|
|
83
|
+
// Validate header.
|
|
84
|
+
if (headerData.typ !== TOKEN_HEADER.typ)
|
|
85
|
+
throw new RequestError(`JWT header type must be \"${TOKEN_HEADER.typ}\"`, { received: headerData.typ, caller: verifyToken });
|
|
86
|
+
if (headerData.alg !== TOKEN_HEADER.alg)
|
|
87
|
+
throw new RequestError(`JWT header algorithm must be \"${TOKEN_HEADER.alg}\"`, { received: headerData.alg, caller: verifyToken });
|
|
88
|
+
// Validate signature.
|
|
89
|
+
const key = await _getKey(secret, "verify");
|
|
90
|
+
const isValid = await crypto.subtle.verify("HMAC", key, decodeBase64UrlBytes(signature), requireBytes(`${header}.${payload}`));
|
|
91
|
+
if (!isValid)
|
|
92
|
+
throw new UnauthorizedError("JWT signature does not match", { received: token, caller: verifyToken });
|
|
93
|
+
// Validate payload.
|
|
94
|
+
const { iat, exp } = payloadData;
|
|
95
|
+
const now = Math.floor(Date.now() / 1000);
|
|
96
|
+
if (typeof iat === "number" && iat > now)
|
|
97
|
+
throw new UnauthorizedError("JWT not issued yet", { received: iat, caller: verifyToken });
|
|
98
|
+
if (typeof exp === "number" && exp < now)
|
|
99
|
+
throw new UnauthorizedError("JWT has expired", { received: exp, caller: verifyToken });
|
|
100
|
+
return payloadData;
|
|
101
|
+
}
|
package/util/validate.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export type ValidatorsType<T> = {
|
|
|
29
29
|
readonly [K in keyof T]: ValidatorType<T[K]>;
|
|
30
30
|
};
|
|
31
31
|
/** Get value that validates against a given `Validator`, or throw `ValueError` */
|
|
32
|
-
export declare function getValid<T>(
|
|
32
|
+
export declare function getValid<T>(value: unknown, validator: Validator<T>, ErrorConstructor?: Constructor<BaseError, [string, BaseErrorOptions]>): T;
|
|
33
33
|
/**
|
|
34
34
|
* Validate an iterable set of items with a validator.
|
|
35
35
|
*
|
package/util/validate.js
CHANGED
|
@@ -9,13 +9,13 @@ import { isIterable } from "./iterate.js";
|
|
|
9
9
|
import { getNull } from "./null.js";
|
|
10
10
|
import { getUndefined } from "./undefined.js";
|
|
11
11
|
/** Get value that validates against a given `Validator`, or throw `ValueError` */
|
|
12
|
-
export function getValid(
|
|
12
|
+
export function getValid(value, validator, ErrorConstructor = ValueError) {
|
|
13
13
|
try {
|
|
14
|
-
return validator.validate(
|
|
14
|
+
return validator.validate(value);
|
|
15
15
|
}
|
|
16
16
|
catch (thrown) {
|
|
17
17
|
if (thrown instanceof Feedback)
|
|
18
|
-
throw new ErrorConstructor(
|
|
18
|
+
throw new ErrorConstructor(thrown.message, { received: value, cause: thrown, caller: getValid });
|
|
19
19
|
throw thrown;
|
|
20
20
|
}
|
|
21
21
|
}
|