@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 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.56.0",
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.6",
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.52.0",
43
+ "typescript-eslint": "^8.53.0",
44
44
  "vitest": "^4.0.17"
45
45
  },
46
46
  "browserslist": [
package/src/index.js CHANGED
@@ -19,4 +19,5 @@ export * from './util/object.js';
19
19
  export * from './util/query.js';
20
20
  export * from './util/state.js';
21
21
  export * from './util/string.js';
22
+ export * from './util/typecheck.js';
22
23
  export * from './util/validate.js';
@@ -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
- // window.addEventListener('popstate', () => onPageLifecycleStateChange(detectPageLifecycleState()), options);
108
- window.addEventListener('pageshow', () => onPageLifecycleStateChange(detectPageLifecycleState()), options);
109
- window.addEventListener('focus', () => onPageLifecycleStateChange(detectPageLifecycleState()), options);
110
- window.addEventListener('blur', () => onPageLifecycleStateChange(detectPageLifecycleState()), options);
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
- window.addEventListener(
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
- window.addEventListener('load', () => onDocumentStateChange(DOCUMENT_STATE_FULLY_LOADED), options);
121
+ globalThis.addEventListener('load', () => onDocumentStateChange(DOCUMENT_STATE_FULLY_LOADED), options);
122
122
  isInitialized = true;
123
123
  };
124
124
 
@@ -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 is timed out'), retryOptions.timeout);
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 has failed');
84
+ throw new Error('Fetch failed');
89
85
  };
@@ -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('core', () => {
5
- expect(fetchRetry).toBeDefined();
6
- expect(typeof fetchRetry).toBe('function');
7
- expect(FetchError).toBeDefined();
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
+ });
@@ -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;CA2BF;mCA/CkC,yBAAyB"}
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"}
@@ -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,EAQlB;IAHC,iCAAwB;IACxB,0BAAgC;IAChC,mBAAwB;CAE3B;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,CAiD7B"}
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"}
@@ -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,kCAHI,OAAO,GACL,KAAK,IAAI,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAEmB;AAOzD,gCAHI,OAAO,GACL,KAAK,IAAI,MAAM,CAE0D;AAO/E,wCAHI,OAAO,GACL,KAAK,IAAI,MAAM,CAE2C;AAOhE,2CAHI,OAAO,GACL,KAAK,IAAI,MAAM,CAE+C;AAOpE,iCAHI,OAAO,GACL,KAAK,IAAI,MAAM,CAEkD;AAOvE,yCAHI,OAAO,GACL,KAAK,IAAI,MAAM,CAE6C;AAOlE,4CAHI,OAAO,GACL,KAAK,IAAI,MAAM,CAEiD;AAOtE,gCAHI,OAAO,GACL,KAAK,IAAI,MAAM,CAEgC;AAQrD,wBAJM,CAAC,SACH,OAAO,GACL,KAAK,IAAI,CAAC,EAAE,CAE6B;AAO/C,8BAHI,OAAO,GACL,KAAK,IAAI,IAAI,CAEqB;AAOxC,mCAHI,OAAO,GACL,KAAK,IAAI,SAAS,CAE0B;AAOlD,yCAHI,OAAO,GACL,KAAK,IAAI,IAAI,GAAG,SAAS,CAEyC;AAOxE,qCAHI,OAAO,GACL,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEsD;AAS5F,2BALM,CAAC,SACH,OAAO,QACP,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,GACvB,KAAK,IAAI,CAAC,CAE6D;AAQ7E,8BAJI,OAAO,WACP,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,GACjE,OAAO,CAWnB;AASM,0BALM,CAAC,UACH,OAAO,aACP,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,GAC5B,MAAM,IAAI,CAAC,EAAE,CAYzB;AASM,gCALM,CAAC,UACH,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,aAChC,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,GAC5B,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,CAYhD;AAUM,gCANM,CAAC,QACH,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,aAC9B,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,SACrB,MAAM,GAAG,IAAI,GACX,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,CAS1C;AAaM,wBALM,CAAC,EAAE,CAAC,KACN,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,KAC9B,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,GAC5B,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,GAAG,CAAC,CAEiB;AAEzD,mDAxBc,OAAO,KAAK,KAAK,UAAK,CAwBwD;AAC5F,0DAzBc,OAAO,KAAK,KAAK,UAAK,CAyBsE;AAC1G,gDA1Bc,OAAO,KAAK,KAAK,UAAK,CA0BkD;AACtF,uDA3Bc,OAAO,KAAK,KAAK,UAAK,CA2BgE;AACpG,6DA5Bc,OAAO,KAAK,KAAK,UAAK,CA4BkE;AACtG,sDA7Bc,OAAO,KAAK,KAAK,UAAK,CA6B8D;AAElG,oDA/Bc,OAAO,KAAK,KAAK,UAAK,CA+B0D;AAC9F,2DAhCc,OAAO,KAAK,KAAK,UAAK,CAgCwE;AAC5G,iDAjCc,OAAO,KAAK,KAAK,UAAK,CAiCoD;AACxF,wDAlCc,OAAO,KAAK,KAAK,UAAK,CAkCkE;AACtG,8DAnCc,OAAO,KAAK,KAAK,UAAK,CAmCoE;AACxG,uDApCc,OAAO,KAAK,KAAK,UAAK,CAoCgE;AAEpG,yDAtCc,OAAO,KAAK,KAAK,UAAK,CAsCqE;AACzG,gEAvCc,OAAO,KAAK,KAAK,UAAK,CAwCgC;AACpE,sDAzCc,OAAO,KAAK,KAAK,UAAK,CAyC+D;AACnG,6DA1Cc,OAAO,KAAK,KAAK,UAAK,CA2C6B;AACjE,mEA5Cc,OAAO,KAAK,KAAK,UAAK,CA6C8B;AAClE,4DA9Cc,OAAO,KAAK,KAAK,UAAK,CA8C2E;AAE/G,wDAhDc,OAAO,KAAK,KAAK,aAAK,CAgDmE;AACvG,+DAjDc,OAAO,KAAK,KAAK,aAAK,CAkD+B;AACnE,qDAnDc,OAAO,KAAK,KAAK,aAAK,CAmD6D;AACjG,4DApDc,OAAO,KAAK,KAAK,aAAK,CAoD2E;AAC/G,kEArDc,OAAO,KAAK,KAAK,aAAK,CAsD6B;AACjE,2DAvDc,OAAO,KAAK,KAAK,aAAK,CAuDyE;AAEpH;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"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/util/validate.js"],"names":[],"mappings":"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"}