@vpmedia/simplify 1.56.0 โ 1.58.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/CHANGELOG.md +44 -0
- package/package.json +3 -3
- package/src/index.js +1 -0
- package/src/logging/ConsoleLogHandler.js +3 -0
- package/src/pagelifecycle/util.js +6 -6
- package/src/util/error.test.js +11 -0
- package/src/util/fetch.js +4 -8
- package/src/util/fetch.test.js +49 -4
- package/src/util/typecheck.js +114 -0
- package/src/util/typecheck.test.js +19 -0
- package/src/util/validate.js +28 -53
- package/src/util/validate.test.js +4 -18
- package/types/index.d.ts +1 -0
- package/types/logging/ConsoleLogHandler.d.ts.map +1 -1
- package/types/util/fetch.d.ts +1 -0
- package/types/util/fetch.d.ts.map +1 -1
- package/types/util/typecheck.d.ts +41 -0
- package/types/util/typecheck.d.ts.map +1 -0
- package/types/util/validate.d.ts +2 -11
- package/types/util/validate.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,47 @@
|
|
|
1
|
+
## [1.58.0] - 2026-01-13
|
|
2
|
+
|
|
3
|
+
### ๐ผ Other
|
|
4
|
+
|
|
5
|
+
- *(deps)* Bump dependency versions
|
|
6
|
+
|
|
7
|
+
### ๐ Refactor
|
|
8
|
+
|
|
9
|
+
- Use globalThis instead of window
|
|
10
|
+
|
|
11
|
+
### ๐งช Testing
|
|
12
|
+
|
|
13
|
+
- Fixed failing test
|
|
14
|
+
|
|
15
|
+
### โ๏ธ Miscellaneous Tasks
|
|
16
|
+
|
|
17
|
+
- Release
|
|
18
|
+
- Adjusted error message
|
|
19
|
+
- *(release)* V1.58.0
|
|
20
|
+
## [1.57.0] - 2026-01-12
|
|
21
|
+
|
|
22
|
+
### ๐ Features
|
|
23
|
+
|
|
24
|
+
- Added type checker singleton
|
|
25
|
+
- Extend error logging details with cause
|
|
26
|
+
- Enrich exception logging with cause
|
|
27
|
+
|
|
28
|
+
### ๐ผ Other
|
|
29
|
+
|
|
30
|
+
- *(deps)* Bump dependency versions
|
|
31
|
+
|
|
32
|
+
### ๐ Refactor
|
|
33
|
+
|
|
34
|
+
- Separate typecheck and validation modules
|
|
35
|
+
|
|
36
|
+
### ๐งช Testing
|
|
37
|
+
|
|
38
|
+
- Improve fetch retry tests
|
|
39
|
+
- Improve fetch retry test coverage
|
|
40
|
+
|
|
41
|
+
### โ๏ธ Miscellaneous Tasks
|
|
42
|
+
|
|
43
|
+
- Release
|
|
44
|
+
- *(release)* V1.57.0
|
|
1
45
|
## [1.56.0] - 2026-01-12
|
|
2
46
|
|
|
3
47
|
### ๐ผ Other
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vpmedia/simplify",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.58.0",
|
|
4
4
|
"description": "@vpmedia/simplify",
|
|
5
5
|
"author": "Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"@commitlint/cli": "^20.3.1",
|
|
29
29
|
"@commitlint/config-conventional": "^20.3.1",
|
|
30
30
|
"@eslint/js": "^9.39.2",
|
|
31
|
-
"@types/node": "^25.0.
|
|
31
|
+
"@types/node": "^25.0.7",
|
|
32
32
|
"@vitest/coverage-v8": "^4.0.17",
|
|
33
33
|
"eslint": "^9.39.2",
|
|
34
34
|
"eslint-plugin-jsdoc": "^62.0.0",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"oxlint-tsgolint": "^0.11.0",
|
|
41
41
|
"prettier": "^3.7.4",
|
|
42
42
|
"typescript": "^5.9.3",
|
|
43
|
-
"typescript-eslint": "^8.
|
|
43
|
+
"typescript-eslint": "^8.53.0",
|
|
44
44
|
"vitest": "^4.0.17"
|
|
45
45
|
},
|
|
46
46
|
"browserslist": [
|
package/src/index.js
CHANGED
|
@@ -41,6 +41,9 @@ export class ConsoleLogHandler extends AbstractLogHandler {
|
|
|
41
41
|
}
|
|
42
42
|
if (error) {
|
|
43
43
|
extra === undefined ? consoleFunction(logMessage, error) : consoleFunction(logMessage, error, extra);
|
|
44
|
+
if (error.cause) {
|
|
45
|
+
consoleFunction('Error cause', error.cause);
|
|
46
|
+
}
|
|
44
47
|
return;
|
|
45
48
|
}
|
|
46
49
|
extra === undefined ? consoleFunction(logMessage) : consoleFunction(logMessage, extra);
|
|
@@ -104,13 +104,13 @@ export const initPageLifecycle = () => {
|
|
|
104
104
|
onDocumentStateChange(document.readyState);
|
|
105
105
|
const options = { capture: true };
|
|
106
106
|
document.addEventListener('visibilitychange', () => onPageLifecycleStateChange(detectPageLifecycleState()), options);
|
|
107
|
-
//
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
// globalThis.addEventListener('popstate', () => onPageLifecycleStateChange(detectPageLifecycleState()), options);
|
|
108
|
+
globalThis.addEventListener('pageshow', () => onPageLifecycleStateChange(detectPageLifecycleState()), options);
|
|
109
|
+
globalThis.addEventListener('focus', () => onPageLifecycleStateChange(detectPageLifecycleState()), options);
|
|
110
|
+
globalThis.addEventListener('blur', () => onPageLifecycleStateChange(detectPageLifecycleState()), options);
|
|
111
111
|
document.addEventListener('resume', () => onPageLifecycleStateChange(detectPageLifecycleState()), options);
|
|
112
112
|
document.addEventListener('freeze', () => onPageLifecycleStateChange(PAGE_LIFECYCLE_STATE_FROZEN), options);
|
|
113
|
-
|
|
113
|
+
globalThis.addEventListener(
|
|
114
114
|
'pagehide',
|
|
115
115
|
(event) =>
|
|
116
116
|
onPageLifecycleStateChange(event.persisted ? PAGE_LIFECYCLE_STATE_FROZEN : PAGE_LIFECYCLE_STATE_TERMINATED),
|
|
@@ -118,7 +118,7 @@ export const initPageLifecycle = () => {
|
|
|
118
118
|
);
|
|
119
119
|
document.addEventListener('DOMContentLoaded', () => onDocumentStateChange(DOCUMENT_STATE_DOM_LOADED), options);
|
|
120
120
|
document.addEventListener('readystatechange', () => onDocumentStateChange(document.readyState), options);
|
|
121
|
-
|
|
121
|
+
globalThis.addEventListener('load', () => onDocumentStateChange(DOCUMENT_STATE_FULLY_LOADED), options);
|
|
122
122
|
isInitialized = true;
|
|
123
123
|
};
|
|
124
124
|
|
package/src/util/error.test.js
CHANGED
|
@@ -7,3 +7,14 @@ test('Tests getErrorDetails', () => {
|
|
|
7
7
|
expect(errorDetails.message).toBe('Test error');
|
|
8
8
|
expect(errorDetails.cause).toBe('Test cause');
|
|
9
9
|
});
|
|
10
|
+
|
|
11
|
+
test('Tests getErrorDetails with Error cause', () => {
|
|
12
|
+
const error = new Error('Test error', { cause: new Error('Cause error') });
|
|
13
|
+
const errorDetails = getErrorDetails(error);
|
|
14
|
+
expect(errorDetails.type).toBe('Error');
|
|
15
|
+
expect(errorDetails.message).toBe('Test error');
|
|
16
|
+
expect(errorDetails.cause instanceof Error).toBe(true);
|
|
17
|
+
if (errorDetails.cause instanceof Error) {
|
|
18
|
+
expect(errorDetails.cause.message).toBe('Cause error');
|
|
19
|
+
}
|
|
20
|
+
});
|
package/src/util/fetch.js
CHANGED
|
@@ -29,6 +29,7 @@ export class FetchError extends Error {
|
|
|
29
29
|
this.resource = resource;
|
|
30
30
|
this.fetchOptions = fetchOptions;
|
|
31
31
|
this.response = response;
|
|
32
|
+
this.cause = response?.status ?? null;
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
|
|
@@ -53,17 +54,12 @@ export const fetchRetry = async (resource, fetchOptions, retryOptions) => {
|
|
|
53
54
|
while (retryOptions.numTries > 0) {
|
|
54
55
|
logger.info('request', { resource, fetchOptions, retryOptions });
|
|
55
56
|
const controller = new AbortController();
|
|
56
|
-
const timeoutId = setTimeout(() => controller.abort('Fetch
|
|
57
|
+
const timeoutId = setTimeout(() => controller.abort('Fetch timed out'), retryOptions.timeout);
|
|
57
58
|
fetchOptions.signal = controller.signal;
|
|
58
59
|
try {
|
|
59
60
|
const response = await fetch(resource, fetchOptions);
|
|
60
61
|
if (!response.ok) {
|
|
61
|
-
throw new FetchError(
|
|
62
|
-
`fetch ${response.url} returned status ${response.status}`,
|
|
63
|
-
resource,
|
|
64
|
-
fetchOptions,
|
|
65
|
-
response
|
|
66
|
-
);
|
|
62
|
+
throw new FetchError(`Fetch error ${response.status}`, resource, fetchOptions, response);
|
|
67
63
|
}
|
|
68
64
|
logger.info('response', response);
|
|
69
65
|
return response;
|
|
@@ -85,5 +81,5 @@ export const fetchRetry = async (resource, fetchOptions, retryOptions) => {
|
|
|
85
81
|
clearTimeout(timeoutId);
|
|
86
82
|
}
|
|
87
83
|
}
|
|
88
|
-
throw new Error('Fetch
|
|
84
|
+
throw new Error('Fetch failed');
|
|
89
85
|
};
|
package/src/util/fetch.test.js
CHANGED
|
@@ -1,9 +1,54 @@
|
|
|
1
|
+
import { HTTP_404_NOT_FOUND } from '../const/http_status.js';
|
|
1
2
|
import { fetchRetry, FetchError } from './fetch.js';
|
|
2
3
|
|
|
3
4
|
describe('fetchRetry', () => {
|
|
4
|
-
test('
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
test('fetch OK', async () => {
|
|
6
|
+
const response = await fetchRetry('https://jsonplaceholder.typicode.com/todos/1', {
|
|
7
|
+
cache: 'no-cache',
|
|
8
|
+
keepalive: false,
|
|
9
|
+
method: 'GET',
|
|
10
|
+
redirect: 'error',
|
|
11
|
+
});
|
|
12
|
+
const json = await response.json();
|
|
13
|
+
const expectedJSON = {
|
|
14
|
+
completed: false,
|
|
15
|
+
id: 1,
|
|
16
|
+
title: 'delectus aut autem',
|
|
17
|
+
userId: 1,
|
|
18
|
+
};
|
|
19
|
+
expect(json).toEqual(expectedJSON);
|
|
20
|
+
});
|
|
21
|
+
test('fetch unknown scheme', async () => {
|
|
22
|
+
try {
|
|
23
|
+
await fetchRetry('htps://jsonplaceholder', {});
|
|
24
|
+
} catch (error) {
|
|
25
|
+
const typedError = error instanceof Error ? error : new Error(String(error));
|
|
26
|
+
expect(typedError.message).toEqual('fetch failed');
|
|
27
|
+
const typedErrorCause =
|
|
28
|
+
typedError.cause instanceof Error ? typedError.cause : new Error(String(typedError.cause));
|
|
29
|
+
expect(typedErrorCause.message).toEqual('unknown scheme');
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
test('fetch 404 error with retry', async () => {
|
|
33
|
+
try {
|
|
34
|
+
await fetchRetry(
|
|
35
|
+
'https://jsonplaceholder.typicode.com/todos/1',
|
|
36
|
+
{
|
|
37
|
+
cache: 'no-cache',
|
|
38
|
+
keepalive: false,
|
|
39
|
+
method: 'POST',
|
|
40
|
+
redirect: 'error',
|
|
41
|
+
},
|
|
42
|
+
{ numTries: 2, statusExcludes: [], delay: 1 }
|
|
43
|
+
);
|
|
44
|
+
} catch (error) {
|
|
45
|
+
const typedError = error instanceof Error ? error : new Error(String(error));
|
|
46
|
+
expect(typedError).toBeInstanceOf(FetchError);
|
|
47
|
+
if (typedError instanceof FetchError) {
|
|
48
|
+
expect(typedError.message).toBe('Fetch error 404');
|
|
49
|
+
expect(typedError.response.status).toBe(HTTP_404_NOT_FOUND);
|
|
50
|
+
expect(typedError.cause).toBe(HTTP_404_NOT_FOUND);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
8
53
|
});
|
|
9
54
|
});
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Logger } from '../logging/Logger.js';
|
|
2
|
+
import { isArrayOf } from './validate.js';
|
|
3
|
+
|
|
4
|
+
const logger = new Logger('typecheck');
|
|
5
|
+
|
|
6
|
+
export class TypeCheckError extends TypeError {
|
|
7
|
+
/**
|
|
8
|
+
* Creates a new `TypeCheckError` instance.
|
|
9
|
+
* @param {string} message - Error message.
|
|
10
|
+
*/
|
|
11
|
+
constructor(message) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = 'TypeCheckError';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Type check a value using a validator.
|
|
19
|
+
* @template T
|
|
20
|
+
* @param {unknown} value - The value to check.
|
|
21
|
+
* @param {(value: unknown) => value is T} validator - The validator to check with.
|
|
22
|
+
* @returns {T} The type checked value.
|
|
23
|
+
* @throws {TypeCheckError}
|
|
24
|
+
*/
|
|
25
|
+
export const typeCheck = (value, validator) => {
|
|
26
|
+
if (!validator(value)) {
|
|
27
|
+
const name = validator.name || '<anonymous>';
|
|
28
|
+
const display = typeof value === 'string' ? `"${value}"` : Object.prototype.toString.call(value);
|
|
29
|
+
throw new TypeCheckError(`Validation failed: ${name} (${display})`);
|
|
30
|
+
}
|
|
31
|
+
return value;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Type check a value using a validator.
|
|
36
|
+
* @template T
|
|
37
|
+
* @param {unknown[]} value - The value to check.
|
|
38
|
+
* @param {(value: unknown) => value is T} validator - The validator to check the array with.
|
|
39
|
+
* @returns {T[]} The type checked value.
|
|
40
|
+
* @throws {TypeCheckError}
|
|
41
|
+
*/
|
|
42
|
+
export const typeCheckArray = (value, validator) => {
|
|
43
|
+
if (!isArrayOf(value, validator)) {
|
|
44
|
+
const name = validator.name || '<anonymous>';
|
|
45
|
+
const display = typeof value === 'string' ? `"${value}"` : Object.prototype.toString.call(value);
|
|
46
|
+
throw new TypeCheckError(`Validation failed: ${name} (${display})`);
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
class TypeChecker {
|
|
52
|
+
/** @type {TypeChecker} */
|
|
53
|
+
static #instance;
|
|
54
|
+
|
|
55
|
+
/** @type {boolean} */
|
|
56
|
+
#swallowErrors = false;
|
|
57
|
+
|
|
58
|
+
constructor() {
|
|
59
|
+
if (TypeChecker.#instance === undefined) {
|
|
60
|
+
TypeChecker.#instance = this;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Enable or disable swallowing of TypeCheckErrors.
|
|
66
|
+
* @param {boolean} value - Swallow errors flag.
|
|
67
|
+
*/
|
|
68
|
+
setSwallowErrors(value) {
|
|
69
|
+
this.#swallowErrors = Boolean(value);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Type check a single value.
|
|
74
|
+
* @template T
|
|
75
|
+
* @param {unknown} value - The value to check.
|
|
76
|
+
* @param {(value: unknown) => value is T} validator - The validator to check with.
|
|
77
|
+
* @returns {T | null} - The type checked value.
|
|
78
|
+
*/
|
|
79
|
+
check(value, validator) {
|
|
80
|
+
try {
|
|
81
|
+
return typeCheck(value, validator);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
if (this.#swallowErrors && error instanceof TypeCheckError) {
|
|
84
|
+
logger.exception('check', error);
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Type check an array of values.
|
|
93
|
+
* @template T
|
|
94
|
+
* @param {unknown[]} value - The value to check.
|
|
95
|
+
* @param {(value: unknown) => value is T} validator - The validator to check the array with.
|
|
96
|
+
* @returns {T[] | null} - The type checked value.
|
|
97
|
+
*/
|
|
98
|
+
checkArray(value, validator) {
|
|
99
|
+
try {
|
|
100
|
+
return typeCheckArray(value, validator);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
if (this.#swallowErrors && error instanceof TypeCheckError) {
|
|
103
|
+
logger.exception('checkArray', error);
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Export a single shared instance.
|
|
113
|
+
*/
|
|
114
|
+
export const typeChecker = new TypeChecker();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { typeCheck, typeCheckArray, TypeCheckError } from './typecheck.js';
|
|
2
|
+
import { isNumber, isPositiveInteger } from './validate.js';
|
|
3
|
+
|
|
4
|
+
describe('typecheck', () => {
|
|
5
|
+
test('typeCheck', () => {
|
|
6
|
+
expect(() => typeCheck(0.1, isNumber)).not.toThrowError(TypeCheckError);
|
|
7
|
+
expect(() => typeCheck(-0.1, isPositiveInteger)).toThrowError(TypeCheckError);
|
|
8
|
+
expect(() => typeCheck('string', isNumber)).toThrowError(TypeCheckError);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('typeCheckArray', () => {
|
|
12
|
+
expect(() => typeCheckArray([0.1], isNumber)).not.toThrowError(TypeCheckError);
|
|
13
|
+
expect(() => typeCheckArray(['string'], isNumber)).toThrowError(TypeCheckError);
|
|
14
|
+
// @ts-expect-error
|
|
15
|
+
expect(() => typeCheckArray(-0.1, isPositiveInteger)).toThrowError(TypeCheckError);
|
|
16
|
+
// @ts-expect-error
|
|
17
|
+
expect(() => typeCheckArray('string', isNumber)).toThrowError(TypeCheckError);
|
|
18
|
+
});
|
|
19
|
+
});
|
package/src/util/validate.js
CHANGED
|
@@ -9,13 +9,6 @@ import { isEqual, isGreater, isGreaterOrEqual, isInRange, isLess, isLessOrEqual
|
|
|
9
9
|
*/
|
|
10
10
|
export const isBoolean = (value) => typeof value === 'boolean';
|
|
11
11
|
|
|
12
|
-
/**
|
|
13
|
-
* Validates `value` as `function`.
|
|
14
|
-
* @param {unknown} value - Input value.
|
|
15
|
-
* @returns {value is (...args: any[]) => any} `true` if `value` is `function` type.
|
|
16
|
-
*/
|
|
17
|
-
export const isFunction = (value) => typeof value === 'function';
|
|
18
|
-
|
|
19
12
|
/**
|
|
20
13
|
* Validates `value` as `number`.
|
|
21
14
|
* @param {unknown} value - Input value.
|
|
@@ -101,6 +94,13 @@ export const isNullOrUndefined = (value) => isNull(value) || isUndefined(value);
|
|
|
101
94
|
*/
|
|
102
95
|
export const isPlainObject = (value) => Object.prototype.toString.call(value) === '[object Object]';
|
|
103
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Validates `value` as `function`.
|
|
99
|
+
* @param {unknown} value - Input value.
|
|
100
|
+
* @returns {value is (...args: any[]) => any} `true` if `value` is `function` type.
|
|
101
|
+
*/
|
|
102
|
+
export const isFunction = (value) => typeof value === 'function';
|
|
103
|
+
|
|
104
104
|
/**
|
|
105
105
|
* Validates `value` as `type`
|
|
106
106
|
* @template T
|
|
@@ -130,7 +130,7 @@ export const isEnum = (value, choices) => {
|
|
|
130
130
|
/**
|
|
131
131
|
* Type check an array of values using a validator.
|
|
132
132
|
* @template T
|
|
133
|
-
* @param {unknown} values - The value to check.
|
|
133
|
+
* @param {unknown[]} values - The value to check.
|
|
134
134
|
* @param {(value: unknown) => value is T} validator - The validator to check with.
|
|
135
135
|
* @returns {values is T[]} `true` if `values` has only `validator` checked types.
|
|
136
136
|
*/
|
|
@@ -196,79 +196,54 @@ export const refineValidator = (base, predicate, name = null) => {
|
|
|
196
196
|
export const isAnyOf = (a, b) => (value) => a(value) || b(value);
|
|
197
197
|
|
|
198
198
|
export const isNumberGreater = (min) => refineValidator(isNumber, (value) => isGreater(value, min));
|
|
199
|
+
|
|
199
200
|
export const isNumberGreaterOrEqual = (min) => refineValidator(isNumber, (value) => isGreaterOrEqual(value, min));
|
|
201
|
+
|
|
200
202
|
export const isNumberLess = (min) => refineValidator(isNumber, (value) => isLess(value, min));
|
|
203
|
+
|
|
201
204
|
export const isNumberLessOrEqual = (min) => refineValidator(isNumber, (value) => isLessOrEqual(value, min));
|
|
205
|
+
|
|
202
206
|
export const isNumberInRange = (min, max) => refineValidator(isNumber, (value) => isInRange(value, min, max));
|
|
207
|
+
|
|
203
208
|
export const isNumberEqual = (expected) => refineValidator(isNumber, (value) => isEqual(value, expected));
|
|
204
209
|
|
|
205
210
|
export const isIntegerGreater = (min) => refineValidator(isInteger, (value) => isGreater(value, min));
|
|
211
|
+
|
|
206
212
|
export const isIntegerGreaterOrEqual = (min) => refineValidator(isInteger, (value) => isGreaterOrEqual(value, min));
|
|
213
|
+
|
|
207
214
|
export const isIntegerLess = (min) => refineValidator(isInteger, (value) => isLess(value, min));
|
|
215
|
+
|
|
208
216
|
export const isIntegerLessOrEqual = (min) => refineValidator(isInteger, (value) => isLessOrEqual(value, min));
|
|
217
|
+
|
|
209
218
|
export const isIntegerInRange = (min, max) => refineValidator(isInteger, (value) => isInRange(value, min, max));
|
|
219
|
+
|
|
210
220
|
export const isIntegerEqual = (expected) => refineValidator(isInteger, (value) => isEqual(value, expected));
|
|
211
221
|
|
|
212
222
|
export const isStringLengthGreater = (min) => refineValidator(isString, (value) => isGreater(value.length, min));
|
|
223
|
+
|
|
213
224
|
export const isStringLengthGreaterOrEqual = (min) =>
|
|
214
225
|
refineValidator(isString, (value) => isGreaterOrEqual(value.length, min));
|
|
226
|
+
|
|
215
227
|
export const isStringLengthLess = (min) => refineValidator(isString, (value) => isLess(value.length, min));
|
|
228
|
+
|
|
216
229
|
export const isStringLengthLessOrEqual = (min) =>
|
|
217
230
|
refineValidator(isString, (value) => isLessOrEqual(value.length, min));
|
|
231
|
+
|
|
218
232
|
export const isStringLengthInRange = (min, max) =>
|
|
219
233
|
refineValidator(isString, (value) => isInRange(value.length, min, max));
|
|
234
|
+
|
|
220
235
|
export const isStringLengthEqual = (expected) => refineValidator(isString, (value) => isEqual(value.length, expected));
|
|
221
236
|
|
|
222
237
|
export const isArrayLengthGreater = (min) => refineValidator(isArray, (value) => isGreater(value.length, min));
|
|
238
|
+
|
|
223
239
|
export const isArrayLengthGreaterOrEqual = (min) =>
|
|
224
240
|
refineValidator(isArray, (value) => isGreaterOrEqual(value.length, min));
|
|
241
|
+
|
|
225
242
|
export const isArrayLengthLess = (min) => refineValidator(isArray, (value) => isLess(value.length, min));
|
|
243
|
+
|
|
226
244
|
export const isArrayLengthLessOrEqual = (min) => refineValidator(isArray, (value) => isLessOrEqual(value.length, min));
|
|
245
|
+
|
|
227
246
|
export const isArrayLengthInRange = (min, max) =>
|
|
228
247
|
refineValidator(isArray, (value) => isInRange(value.length, min, max));
|
|
229
|
-
export const isArrayLengthEqual = (expected) => refineValidator(isArray, (value) => isEqual(value.length, expected));
|
|
230
|
-
|
|
231
|
-
export class TypeCheckError extends TypeError {
|
|
232
|
-
/**
|
|
233
|
-
* Creates a new `TypeCheckError` instance.
|
|
234
|
-
* @param {string} message - Error message.
|
|
235
|
-
*/
|
|
236
|
-
constructor(message) {
|
|
237
|
-
super(message);
|
|
238
|
-
this.name = 'TypeCheckError';
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Type check a value using a validator.
|
|
244
|
-
* @template T
|
|
245
|
-
* @param {unknown} value - The value to check.
|
|
246
|
-
* @param {(value: unknown) => value is T} validator - The validator to check with.
|
|
247
|
-
* @returns {T} The type checked value.
|
|
248
|
-
* @throws {TypeCheckError}
|
|
249
|
-
*/
|
|
250
|
-
export const typeCheck = (value, validator) => {
|
|
251
|
-
if (!validator(value)) {
|
|
252
|
-
const name = validator.name || '<anonymous>';
|
|
253
|
-
const display = typeof value === 'string' ? `"${value}"` : Object.prototype.toString.call(value);
|
|
254
|
-
throw new TypeCheckError(`Validation failed: ${name} (${display})`);
|
|
255
|
-
}
|
|
256
|
-
return value;
|
|
257
|
-
};
|
|
258
248
|
|
|
259
|
-
|
|
260
|
-
* Type check a value using a validator.
|
|
261
|
-
* @template T
|
|
262
|
-
* @param {unknown[]} value - The value to check.
|
|
263
|
-
* @param {(value: unknown) => value is T} validator - The validator to check the array with.
|
|
264
|
-
* @returns {T[]} The type checked value.
|
|
265
|
-
* @throws {TypeCheckError}
|
|
266
|
-
*/
|
|
267
|
-
export const typeCheckArray = (value, validator) => {
|
|
268
|
-
if (!isArrayOf(value, validator)) {
|
|
269
|
-
const name = validator.name || '<anonymous>';
|
|
270
|
-
const display = typeof value === 'string' ? `"${value}"` : Object.prototype.toString.call(value);
|
|
271
|
-
throw new TypeCheckError(`Validation failed: ${name} (${display})`);
|
|
272
|
-
}
|
|
273
|
-
return value;
|
|
274
|
-
};
|
|
249
|
+
export const isArrayLengthEqual = (expected) => refineValidator(isArray, (value) => isEqual(value.length, expected));
|
|
@@ -19,9 +19,6 @@ import {
|
|
|
19
19
|
isPositiveNumber,
|
|
20
20
|
isString,
|
|
21
21
|
isUndefined,
|
|
22
|
-
typeCheck,
|
|
23
|
-
typeCheckArray,
|
|
24
|
-
TypeCheckError,
|
|
25
22
|
refineValidator,
|
|
26
23
|
isNumberLess,
|
|
27
24
|
isNumberGreater,
|
|
@@ -227,6 +224,7 @@ describe('validate', () => {
|
|
|
227
224
|
expect(isInstance(new CustomError(), {})).toBe(false);
|
|
228
225
|
expect(isInstance(new CustomError(), Error)).toBe(true);
|
|
229
226
|
expect(isInstance(new CustomError(), Number)).toBe(false);
|
|
227
|
+
expect(isInstance(new Date(), Date)).toBe(true);
|
|
230
228
|
});
|
|
231
229
|
|
|
232
230
|
test('isEnum', () => {
|
|
@@ -249,11 +247,14 @@ describe('validate', () => {
|
|
|
249
247
|
});
|
|
250
248
|
|
|
251
249
|
test('isArrayOf', () => {
|
|
250
|
+
// @ts-expect-error
|
|
252
251
|
expect(isArrayOf(0.1, isNumber)).toBe(false);
|
|
253
252
|
expect(isArrayOf([0.1, 'string'], isNumber)).toBe(false);
|
|
254
253
|
expect(isArrayOf([0.1, 0.2], isNumber)).toBe(true);
|
|
255
254
|
expect(isArrayOf([0.1, 1, 2], isInteger)).toBe(false);
|
|
256
255
|
expect(isArrayOf([1, 2], isInteger)).toBe(true);
|
|
256
|
+
expect(isArrayOf([1, 'string', undefined], isAnyOf(isInteger, isNullOrUndefined))).toBe(false);
|
|
257
|
+
expect(isArrayOf([1, null, undefined], isAnyOf(isInteger, isNullOrUndefined))).toBe(true);
|
|
257
258
|
});
|
|
258
259
|
|
|
259
260
|
test('isPlainObjectOf', () => {
|
|
@@ -265,21 +266,6 @@ describe('validate', () => {
|
|
|
265
266
|
expect(isPlainObjectOf({ a: 1, b: 2 }, isInteger)).toBe(true);
|
|
266
267
|
});
|
|
267
268
|
|
|
268
|
-
test('typeCheck', () => {
|
|
269
|
-
expect(() => typeCheck(0.1, isNumber)).not.toThrowError(TypeCheckError);
|
|
270
|
-
expect(() => typeCheck(-0.1, isPositiveInteger)).toThrowError(TypeCheckError);
|
|
271
|
-
expect(() => typeCheck('string', isNumber)).toThrowError(TypeCheckError);
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
test('typeCheckArray', () => {
|
|
275
|
-
expect(() => typeCheckArray([0.1], isNumber)).not.toThrowError(TypeCheckError);
|
|
276
|
-
expect(() => typeCheckArray(['string'], isNumber)).toThrowError(TypeCheckError);
|
|
277
|
-
// @ts-expect-error
|
|
278
|
-
expect(() => typeCheckArray(-0.1, isPositiveInteger)).toThrowError(TypeCheckError);
|
|
279
|
-
// @ts-expect-error
|
|
280
|
-
expect(() => typeCheckArray('string', isNumber)).toThrowError(TypeCheckError);
|
|
281
|
-
});
|
|
282
|
-
|
|
283
269
|
test('isAnyOf', () => {
|
|
284
270
|
expect(isAnyOf(isNumber, isNull)(1)).toBe(true);
|
|
285
271
|
expect(isAnyOf(isNumber, isNull)(null)).toBe(true);
|
package/types/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export * from "./util/object.js";
|
|
|
11
11
|
export * from "./util/query.js";
|
|
12
12
|
export * from "./util/state.js";
|
|
13
13
|
export * from "./util/string.js";
|
|
14
|
+
export * from "./util/typecheck.js";
|
|
14
15
|
export * from "./util/validate.js";
|
|
15
16
|
export { AbstractLogHandler } from "./logging/AbstractLogHandler.js";
|
|
16
17
|
export { ConsoleLogHandler } from "./logging/ConsoleLogHandler.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConsoleLogHandler.d.ts","sourceRoot":"","sources":["../../src/logging/ConsoleLogHandler.js"],"names":[],"mappings":"AAaA;IACE;;;OAGG;IACH,oBAFW,MAAM,EAIhB;
|
|
1
|
+
{"version":3,"file":"ConsoleLogHandler.d.ts","sourceRoot":"","sources":["../../src/logging/ConsoleLogHandler.js"],"names":[],"mappings":"AAaA;IACE;;;OAGG;IACH,oBAFW,MAAM,EAIhB;CA8BF;mCAlDkC,yBAAyB"}
|
package/types/util/fetch.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export class FetchError extends Error {
|
|
|
11
11
|
resource: string | URL | Request;
|
|
12
12
|
fetchOptions: RequestInit;
|
|
13
13
|
response: Response;
|
|
14
|
+
cause: number;
|
|
14
15
|
}
|
|
15
16
|
export function fetchRetry(resource: string | URL | Request, fetchOptions: RequestInit, retryOptions?: {
|
|
16
17
|
delay?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/util/fetch.js"],"names":[],"mappings":"AAeA,yBAA0B,CAAC,CAAC;AAE5B;IACE;;;;;;OAMG;IACH,qBALW,MAAM,YACN,MAAM,GAAG,GAAG,GAAG,OAAO,gBACtB,WAAW,YACX,QAAQ,
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/util/fetch.js"],"names":[],"mappings":"AAeA,yBAA0B,CAAC,CAAC;AAE5B;IACE;;;;;;OAMG;IACH,qBALW,MAAM,YACN,MAAM,GAAG,GAAG,GAAG,OAAO,gBACtB,WAAW,YACX,QAAQ,EASlB;IAJC,iCAAwB;IACxB,0BAAgC;IAChC,mBAAwB;IACxB,cAAqC;CAExC;AASM,qCALI,MAAM,GAAG,GAAG,GAAG,OAAO,gBACtB,WAAW,iBACX;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAC,GAC9E,OAAO,CAAC,QAAQ,CAAC,CA4C7B"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export class TypeCheckError extends TypeError {
|
|
2
|
+
/**
|
|
3
|
+
* Creates a new `TypeCheckError` instance.
|
|
4
|
+
* @param {string} message - Error message.
|
|
5
|
+
*/
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
export function typeCheck<T>(value: unknown, validator: (value: unknown) => value is T): T;
|
|
9
|
+
export function typeCheckArray<T>(value: unknown[], validator: (value: unknown) => value is T): T[];
|
|
10
|
+
/**
|
|
11
|
+
* Export a single shared instance.
|
|
12
|
+
*/
|
|
13
|
+
export const typeChecker: TypeChecker;
|
|
14
|
+
declare class TypeChecker {
|
|
15
|
+
/** @type {TypeChecker} */
|
|
16
|
+
static "__#private@#instance": TypeChecker;
|
|
17
|
+
/**
|
|
18
|
+
* Enable or disable swallowing of TypeCheckErrors.
|
|
19
|
+
* @param {boolean} value - Swallow errors flag.
|
|
20
|
+
*/
|
|
21
|
+
setSwallowErrors(value: boolean): void;
|
|
22
|
+
/**
|
|
23
|
+
* Type check a single value.
|
|
24
|
+
* @template T
|
|
25
|
+
* @param {unknown} value - The value to check.
|
|
26
|
+
* @param {(value: unknown) => value is T} validator - The validator to check with.
|
|
27
|
+
* @returns {T | null} - The type checked value.
|
|
28
|
+
*/
|
|
29
|
+
check<T>(value: unknown, validator: (value: unknown) => value is T): T | null;
|
|
30
|
+
/**
|
|
31
|
+
* Type check an array of values.
|
|
32
|
+
* @template T
|
|
33
|
+
* @param {unknown[]} value - The value to check.
|
|
34
|
+
* @param {(value: unknown) => value is T} validator - The validator to check the array with.
|
|
35
|
+
* @returns {T[] | null} - The type checked value.
|
|
36
|
+
*/
|
|
37
|
+
checkArray<T>(value: unknown[], validator: (value: unknown) => value is T): T[] | null;
|
|
38
|
+
#private;
|
|
39
|
+
}
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=typecheck.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typecheck.d.ts","sourceRoot":"","sources":["../../src/util/typecheck.js"],"names":[],"mappings":"AAKA;IACE;;;OAGG;IACH,qBAFW,MAAM,EAKhB;CACF;AAUM,0BANM,CAAC,SACH,OAAO,aACP,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,GAC5B,CAAC,CAUb;AAUM,+BANM,CAAC,SACH,OAAO,EAAE,aACT,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,GAC5B,CAAC,EAAE,CAUf;AA8DD;;GAEG;AACH,sCAA6C;AA/D7C;IACE,0BAA0B;IAC1B,+BADW,WAAW,CACL;IAWjB;;;OAGG;IACH,wBAFW,OAAO,QAIjB;IAED;;;;;;OAMG;IACH,MALa,CAAC,SACH,OAAO,aACP,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,GAC5B,CAAC,GAAG,IAAI,CAYpB;IAED;;;;;;OAMG;IACH,WALa,CAAC,SACH,OAAO,EAAE,aACT,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,GAC5B,CAAC,EAAE,GAAG,IAAI,CAYtB;;CACF"}
|
package/types/util/validate.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export function isBoolean(value: unknown): value is boolean;
|
|
2
|
-
export function isFunction(value: unknown): value is (...args: any[]) => any;
|
|
3
2
|
export function isNumber(value: unknown): value is number;
|
|
4
3
|
export function isPositiveNumber(value: unknown): value is number;
|
|
5
4
|
export function isNonNegativeNumber(value: unknown): value is number;
|
|
@@ -12,9 +11,10 @@ export function isNull(value: unknown): value is null;
|
|
|
12
11
|
export function isUndefined(value: unknown): value is undefined;
|
|
13
12
|
export function isNullOrUndefined(value: unknown): value is null | undefined;
|
|
14
13
|
export function isPlainObject(value: unknown): value is Record<string, unknown>;
|
|
14
|
+
export function isFunction(value: unknown): value is (...args: any[]) => any;
|
|
15
15
|
export function isInstance<T>(value: unknown, type: new (...args: any[]) => T): value is T;
|
|
16
16
|
export function isEnum(value: unknown, choices: unknown[] | Set<string | number> | Record<string | number, unknown>): boolean;
|
|
17
|
-
export function isArrayOf<T>(values: unknown, validator: (value: unknown) => value is T): values is T[];
|
|
17
|
+
export function isArrayOf<T>(values: unknown[], validator: (value: unknown) => value is T): values is T[];
|
|
18
18
|
export function isPlainObjectOf<T>(record: Record<string | number, unknown>, validator: (value: unknown) => value is T): record is Record<string | number, T>;
|
|
19
19
|
export function refineValidator<T>(base: (value: unknown) => value is T, predicate: (value: T) => boolean, name?: string | null): (value: unknown) => value is T;
|
|
20
20
|
export function isAnyOf<A, B>(a: (value: unknown) => value is A, b: (value: unknown) => value is B): (value: unknown) => value is A | B;
|
|
@@ -42,13 +42,4 @@ export function isArrayLengthLess(min: any): (value: unknown) => value is unknow
|
|
|
42
42
|
export function isArrayLengthLessOrEqual(min: any): (value: unknown) => value is unknown[];
|
|
43
43
|
export function isArrayLengthInRange(min: any, max: any): (value: unknown) => value is unknown[];
|
|
44
44
|
export function isArrayLengthEqual(expected: any): (value: unknown) => value is unknown[];
|
|
45
|
-
export class TypeCheckError extends TypeError {
|
|
46
|
-
/**
|
|
47
|
-
* Creates a new `TypeCheckError` instance.
|
|
48
|
-
* @param {string} message - Error message.
|
|
49
|
-
*/
|
|
50
|
-
constructor(message: string);
|
|
51
|
-
}
|
|
52
|
-
export function typeCheck<T>(value: unknown, validator: (value: unknown) => value is T): T;
|
|
53
|
-
export function typeCheckArray<T>(value: unknown[], validator: (value: unknown) => value is T): T[];
|
|
54
45
|
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/util/validate.js"],"names":[],"mappings":"AASO,iCAHI,OAAO,GACL,KAAK,IAAI,OAAO,CAEiC;AAOvD,
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/util/validate.js"],"names":[],"mappings":"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"}
|