@murky-web/typebuddy 1.0.0 → 1.1.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/README.md +22 -0
- package/dist/index.js +2 -2
- package/dist/rules/async_rule.js +10 -3
- package/dist/rules/maybe_promise_rule.js +28 -7
- package/dist/src/type_helper.js +15 -1
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/rules/async_rule.ts +93 -71
- package/rules/maybe_promise_rule.ts +259 -197
- package/src/type_helper.ts +279 -253
package/src/type_helper.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import type { Maybe } from "./types/maybe.js";
|
|
2
|
+
import type { Failed, Success } from "./types/maybe_promise.js";
|
|
2
3
|
import type { Nullable } from "./types/nullable.js";
|
|
3
4
|
import type { Optional } from "./types/optional.js";
|
|
4
|
-
import type { Failed, Success } from "./types/maybe_promise.js";
|
|
5
5
|
|
|
6
6
|
type UnknownFunction = (...args: readonly never[]) => unknown;
|
|
7
7
|
const EMPTY_LENGTH = 0;
|
|
8
8
|
const uuidRegex =
|
|
9
|
-
|
|
9
|
+
/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/;
|
|
10
10
|
|
|
11
11
|
const ulidRegex = /^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$/;
|
|
12
12
|
|
|
13
13
|
function cloneDefaultArray(
|
|
14
|
-
|
|
14
|
+
defaultValue?: readonly unknown[],
|
|
15
15
|
): unknown[] | undefined {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
if (!defaultValue) {
|
|
17
|
+
return defaultValue;
|
|
18
|
+
}
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
return [...defaultValue];
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -32,15 +32,44 @@ function cloneDefaultArray(
|
|
|
32
32
|
* @example
|
|
33
33
|
* ```typescript
|
|
34
34
|
* const result = await someAsyncFunction();
|
|
35
|
-
* if (isSuccess(result)) {
|
|
36
|
-
* return result.value; // TypeScript knows `value` is of type `T`
|
|
37
|
-
* }
|
|
35
|
+
* if (isSuccess(result)) {
|
|
36
|
+
* return result.value; // TypeScript knows `value` is of type `T`
|
|
37
|
+
* }
|
|
38
38
|
* ```
|
|
39
39
|
*/
|
|
40
40
|
function isSuccess<T>(
|
|
41
|
-
|
|
41
|
+
result: Readonly<Success<T> | Failed>,
|
|
42
42
|
): result is Success<T> {
|
|
43
|
-
|
|
43
|
+
return !result.isError;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Creates a successful result object for MaybePromise-style flows.
|
|
48
|
+
*/
|
|
49
|
+
function ok(): Success<void>;
|
|
50
|
+
function ok<T>(value: T): Success<T>;
|
|
51
|
+
// oxlint-disable-next-line typescript-eslint/prefer-readonly-parameter-types -- ok() intentionally accepts arbitrary payload values, including mutable ones.
|
|
52
|
+
function ok<T>(...args: readonly [T] | []): Success<T | void> {
|
|
53
|
+
const [value] = args;
|
|
54
|
+
return {
|
|
55
|
+
isError: false,
|
|
56
|
+
value,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Creates the default failed result object for MaybePromise-style flows.
|
|
62
|
+
*/
|
|
63
|
+
function err(): Failed;
|
|
64
|
+
function err<T extends null>(value: T): Failed<T>;
|
|
65
|
+
// oxlint-disable-next-line typescript-eslint/prefer-readonly-parameter-types -- err() mirrors ok() and accepts the caller's payload shape without forcing readonly wrappers.
|
|
66
|
+
function err<T extends null>(...args: readonly [T] | []): Failed {
|
|
67
|
+
const [value] = args;
|
|
68
|
+
return {
|
|
69
|
+
isError: true,
|
|
70
|
+
// oxlint-disable-next-line unicorn/no-null -- TypeBuddy models failed states with null by design.
|
|
71
|
+
value: value ?? null,
|
|
72
|
+
};
|
|
44
73
|
}
|
|
45
74
|
|
|
46
75
|
/**
|
|
@@ -51,7 +80,7 @@ function isSuccess<T>(
|
|
|
51
80
|
function isString<T extends string>(value: Nullable<T>): value is T;
|
|
52
81
|
function isString(value: unknown): value is string;
|
|
53
82
|
function isString(value: unknown): value is string {
|
|
54
|
-
|
|
83
|
+
return typeof value === "string";
|
|
55
84
|
}
|
|
56
85
|
|
|
57
86
|
/**
|
|
@@ -60,8 +89,10 @@ function isString(value: unknown): value is string {
|
|
|
60
89
|
* @returns {boolean} True if the value is a string.
|
|
61
90
|
*/
|
|
62
91
|
function isEmptyString(value: unknown): boolean {
|
|
63
|
-
|
|
64
|
-
|
|
92
|
+
if (!isString(value)) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
return value.trim() === "";
|
|
65
96
|
}
|
|
66
97
|
|
|
67
98
|
/**
|
|
@@ -70,7 +101,7 @@ function isEmptyString(value: unknown): boolean {
|
|
|
70
101
|
* @returns {boolean} True if the value is null.
|
|
71
102
|
*/
|
|
72
103
|
function isNull(value: unknown): value is null {
|
|
73
|
-
|
|
104
|
+
return value === null;
|
|
74
105
|
}
|
|
75
106
|
|
|
76
107
|
/**
|
|
@@ -79,7 +110,7 @@ function isNull(value: unknown): value is null {
|
|
|
79
110
|
* @returns {boolean} True if the value is undefined.
|
|
80
111
|
*/
|
|
81
112
|
function isUndefined(value: unknown): value is undefined {
|
|
82
|
-
|
|
113
|
+
return typeof value === "undefined";
|
|
83
114
|
}
|
|
84
115
|
|
|
85
116
|
/**
|
|
@@ -88,7 +119,7 @@ function isUndefined(value: unknown): value is undefined {
|
|
|
88
119
|
* @returns {boolean} True when the value is undefined.
|
|
89
120
|
*/
|
|
90
121
|
function isOptional<T>(value: Optional<T>): value is undefined {
|
|
91
|
-
|
|
122
|
+
return isUndefined(value);
|
|
92
123
|
}
|
|
93
124
|
|
|
94
125
|
/**
|
|
@@ -97,7 +128,7 @@ function isOptional<T>(value: Optional<T>): value is undefined {
|
|
|
97
128
|
* @returns {boolean} True when the value is null.
|
|
98
129
|
*/
|
|
99
130
|
function isMaybe<T>(value: Maybe<T>): value is null {
|
|
100
|
-
|
|
131
|
+
return isNull(value);
|
|
101
132
|
}
|
|
102
133
|
|
|
103
134
|
/**
|
|
@@ -106,7 +137,7 @@ function isMaybe<T>(value: Maybe<T>): value is null {
|
|
|
106
137
|
* @returns {boolean} True when the value is null or undefined.
|
|
107
138
|
*/
|
|
108
139
|
function isNullable<T>(value: Nullable<T>): value is null | undefined {
|
|
109
|
-
|
|
140
|
+
return isNull(value) || isUndefined(value);
|
|
110
141
|
}
|
|
111
142
|
|
|
112
143
|
/**
|
|
@@ -117,7 +148,7 @@ function isNullable<T>(value: Nullable<T>): value is null | undefined {
|
|
|
117
148
|
function isArray<T>(value: Nullable<readonly T[]>): value is readonly T[];
|
|
118
149
|
function isArray(value: unknown): value is readonly unknown[];
|
|
119
150
|
function isArray(value: unknown): value is readonly unknown[] {
|
|
120
|
-
|
|
151
|
+
return Array.isArray(value);
|
|
121
152
|
}
|
|
122
153
|
|
|
123
154
|
/**
|
|
@@ -128,7 +159,7 @@ function isArray(value: unknown): value is readonly unknown[] {
|
|
|
128
159
|
function isEmptyArray<T>(value: Nullable<readonly T[]>): value is readonly T[];
|
|
129
160
|
function isEmptyArray(value: unknown): value is readonly unknown[];
|
|
130
161
|
function isEmptyArray(value: unknown): value is readonly unknown[] {
|
|
131
|
-
|
|
162
|
+
return Array.isArray(value) && value.length === EMPTY_LENGTH;
|
|
132
163
|
}
|
|
133
164
|
|
|
134
165
|
/**
|
|
@@ -139,7 +170,7 @@ function isEmptyArray(value: unknown): value is readonly unknown[] {
|
|
|
139
170
|
function fastIsArray<T>(value: Nullable<readonly T[]>): value is readonly T[];
|
|
140
171
|
function fastIsArray(value: unknown): value is readonly unknown[];
|
|
141
172
|
function fastIsArray(value: unknown): value is readonly unknown[] {
|
|
142
|
-
|
|
173
|
+
return Object.prototype.toString.call(value) === "[object Array]";
|
|
143
174
|
}
|
|
144
175
|
|
|
145
176
|
/**
|
|
@@ -150,10 +181,14 @@ function fastIsArray(value: unknown): value is readonly unknown[] {
|
|
|
150
181
|
function isNumber<T extends number>(value: Nullable<T>): value is T;
|
|
151
182
|
function isNumber(value: unknown): value is number;
|
|
152
183
|
function isNumber(value: unknown): value is number {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
184
|
+
if (typeof value === "string" && value.trim() === "") {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
return (
|
|
188
|
+
typeof value === "number" &&
|
|
189
|
+
!Number.isNaN(value) &&
|
|
190
|
+
Number.isFinite(value)
|
|
191
|
+
);
|
|
157
192
|
}
|
|
158
193
|
|
|
159
194
|
/**
|
|
@@ -162,21 +197,21 @@ function isNumber(value: unknown): value is number {
|
|
|
162
197
|
* @returns {boolean} True if the value is an object.
|
|
163
198
|
*/
|
|
164
199
|
function isObject<T extends Record<string, unknown>>(
|
|
165
|
-
|
|
200
|
+
value: Nullable<T>,
|
|
166
201
|
): value is T;
|
|
167
202
|
function isObject(value: unknown): value is Record<string, unknown>;
|
|
168
203
|
function isObject(value: unknown): value is Record<string, unknown> {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
204
|
+
if (
|
|
205
|
+
typeof value !== "object" ||
|
|
206
|
+
value === null ||
|
|
207
|
+
isArray(value) ||
|
|
208
|
+
Object.prototype.toString.call(value) !== "[object Object]"
|
|
209
|
+
) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
177
212
|
|
|
178
|
-
|
|
179
|
-
|
|
213
|
+
const objectValue: object = value;
|
|
214
|
+
return Object.getPrototypeOf(objectValue) === Object.prototype;
|
|
180
215
|
}
|
|
181
216
|
|
|
182
217
|
/**
|
|
@@ -187,7 +222,7 @@ function isObject(value: unknown): value is Record<string, unknown> {
|
|
|
187
222
|
function isBoolean<T extends boolean>(value: Nullable<T>): value is T;
|
|
188
223
|
function isBoolean(value: unknown): value is boolean;
|
|
189
224
|
function isBoolean(value: unknown): value is boolean {
|
|
190
|
-
|
|
225
|
+
return typeof value === "boolean";
|
|
191
226
|
}
|
|
192
227
|
|
|
193
228
|
/**
|
|
@@ -195,12 +230,10 @@ function isBoolean(value: unknown): value is boolean {
|
|
|
195
230
|
* @param {unknown} value - The value to check.
|
|
196
231
|
* @returns {boolean} True if the value is a function.
|
|
197
232
|
*/
|
|
198
|
-
function isFunction<T extends UnknownFunction>(
|
|
199
|
-
value: Nullable<T>,
|
|
200
|
-
): value is T;
|
|
233
|
+
function isFunction<T extends UnknownFunction>(value: Nullable<T>): value is T;
|
|
201
234
|
function isFunction(value: unknown): value is UnknownFunction;
|
|
202
235
|
function isFunction(value: unknown): value is UnknownFunction {
|
|
203
|
-
|
|
236
|
+
return typeof value === "function";
|
|
204
237
|
}
|
|
205
238
|
|
|
206
239
|
/**
|
|
@@ -209,15 +242,15 @@ function isFunction(value: unknown): value is UnknownFunction {
|
|
|
209
242
|
* @returns {boolean} True if the value is a promise.
|
|
210
243
|
*/
|
|
211
244
|
function isPromise<T>(
|
|
212
|
-
|
|
245
|
+
value: Nullable<Readonly<PromiseLike<T>>>,
|
|
213
246
|
): value is PromiseLike<T>;
|
|
214
247
|
function isPromise(value: unknown): value is PromiseLike<unknown>;
|
|
215
248
|
function isPromise(value: unknown): value is PromiseLike<unknown> {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
249
|
+
if (typeof value !== "object" || value === null) {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
219
252
|
|
|
220
|
-
|
|
253
|
+
return typeof Reflect.get(value, "then") === "function";
|
|
221
254
|
}
|
|
222
255
|
|
|
223
256
|
/**
|
|
@@ -228,7 +261,7 @@ function isPromise(value: unknown): value is PromiseLike<unknown> {
|
|
|
228
261
|
function isError<T extends Error>(value: Nullable<T>): value is T;
|
|
229
262
|
function isError(value: unknown): value is Error;
|
|
230
263
|
function isError(value: unknown): value is Error {
|
|
231
|
-
|
|
264
|
+
return value instanceof Error;
|
|
232
265
|
}
|
|
233
266
|
|
|
234
267
|
/**
|
|
@@ -239,7 +272,7 @@ function isError(value: unknown): value is Error {
|
|
|
239
272
|
function isDate<T extends Date>(value: Nullable<T>): value is T;
|
|
240
273
|
function isDate(value: unknown): value is Date;
|
|
241
274
|
function isDate(value: unknown): value is Date {
|
|
242
|
-
|
|
275
|
+
return value instanceof Date;
|
|
243
276
|
}
|
|
244
277
|
|
|
245
278
|
/**
|
|
@@ -250,7 +283,7 @@ function isDate(value: unknown): value is Date {
|
|
|
250
283
|
function isRegExp<T extends RegExp>(value: Nullable<T>): value is T;
|
|
251
284
|
function isRegExp(value: unknown): value is RegExp;
|
|
252
285
|
function isRegExp(value: unknown): value is RegExp {
|
|
253
|
-
|
|
286
|
+
return value instanceof RegExp;
|
|
254
287
|
}
|
|
255
288
|
|
|
256
289
|
/**
|
|
@@ -261,7 +294,7 @@ function isRegExp(value: unknown): value is RegExp {
|
|
|
261
294
|
function isSymbol<T extends symbol>(value: Nullable<T>): value is T;
|
|
262
295
|
function isSymbol(value: unknown): value is symbol;
|
|
263
296
|
function isSymbol(value: unknown): value is symbol {
|
|
264
|
-
|
|
297
|
+
return typeof value === "symbol";
|
|
265
298
|
}
|
|
266
299
|
|
|
267
300
|
/**
|
|
@@ -270,22 +303,18 @@ function isSymbol(value: unknown): value is symbol {
|
|
|
270
303
|
* @returns {boolean} True if the value is a plain object.
|
|
271
304
|
*/
|
|
272
305
|
function isEmptyObject<T extends Record<string, unknown>>(
|
|
273
|
-
|
|
306
|
+
value: Nullable<T>,
|
|
274
307
|
): value is T;
|
|
275
|
-
function isEmptyObject(
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
)
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
!isEmptyArray(value) &&
|
|
286
|
-
Object.getPrototypeOf(value) === Object.prototype &&
|
|
287
|
-
Object.keys(value).length === EMPTY_LENGTH
|
|
288
|
-
);
|
|
308
|
+
function isEmptyObject(value: unknown): value is Record<string, unknown>;
|
|
309
|
+
function isEmptyObject(value: unknown): value is Record<string, unknown> {
|
|
310
|
+
return (
|
|
311
|
+
typeof value === "object" &&
|
|
312
|
+
!isNull(value) &&
|
|
313
|
+
!isUndefined(value) &&
|
|
314
|
+
!isEmptyArray(value) &&
|
|
315
|
+
Object.getPrototypeOf(value) === Object.prototype &&
|
|
316
|
+
Object.keys(value).length === EMPTY_LENGTH
|
|
317
|
+
);
|
|
289
318
|
}
|
|
290
319
|
|
|
291
320
|
/**
|
|
@@ -295,10 +324,10 @@ function isEmptyObject(
|
|
|
295
324
|
* @returns {boolean} True if the value is an instance of the class.
|
|
296
325
|
*/
|
|
297
326
|
function isInstanceOf<T>(
|
|
298
|
-
|
|
299
|
-
|
|
327
|
+
value: unknown,
|
|
328
|
+
constructor: new (...args: unknown[]) => T,
|
|
300
329
|
): value is T {
|
|
301
|
-
|
|
330
|
+
return value instanceof constructor;
|
|
302
331
|
}
|
|
303
332
|
|
|
304
333
|
/**
|
|
@@ -306,10 +335,8 @@ function isInstanceOf<T>(
|
|
|
306
335
|
* @param {unknown} object - The object to get the keys of.
|
|
307
336
|
* @returns {Array} Keys of object.
|
|
308
337
|
*/
|
|
309
|
-
function getKeys<T extends Record<string, unknown>>(
|
|
310
|
-
|
|
311
|
-
): (keyof T)[] {
|
|
312
|
-
return Object.keys(object) as (keyof T)[];
|
|
338
|
+
function getKeys<T extends Record<string, unknown>>(object: T): (keyof T)[] {
|
|
339
|
+
return Object.keys(object) as (keyof T)[];
|
|
313
340
|
}
|
|
314
341
|
|
|
315
342
|
/**
|
|
@@ -322,21 +349,18 @@ function getKeys<T extends Record<string, unknown>>(
|
|
|
322
349
|
*/
|
|
323
350
|
function parseInteger(value: unknown): Optional<number>;
|
|
324
351
|
function parseInteger(value: unknown, defaultValue: number): number;
|
|
325
|
-
function parseInteger(
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
): Optional<number> {
|
|
329
|
-
if (isNumber(value)) {
|
|
330
|
-
return Math.floor(value);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
if (isString(value)) {
|
|
334
|
-
const parsed = Number(value.trim());
|
|
335
|
-
if (Number.isInteger(parsed)) {
|
|
336
|
-
return parsed;
|
|
352
|
+
function parseInteger(value: unknown, defaultValue?: number): Optional<number> {
|
|
353
|
+
if (isNumber(value)) {
|
|
354
|
+
return Math.floor(value);
|
|
337
355
|
}
|
|
338
|
-
|
|
339
|
-
|
|
356
|
+
|
|
357
|
+
if (isString(value)) {
|
|
358
|
+
const parsed = Number(value.trim());
|
|
359
|
+
if (Number.isInteger(parsed)) {
|
|
360
|
+
return parsed;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return defaultValue;
|
|
340
364
|
}
|
|
341
365
|
|
|
342
366
|
/**
|
|
@@ -345,7 +369,7 @@ function parseInteger(
|
|
|
345
369
|
* @returns {boolean} True if the value is an integer.
|
|
346
370
|
*/
|
|
347
371
|
function isInteger(value: unknown): value is number {
|
|
348
|
-
|
|
372
|
+
return typeof value === "number" && Number.isInteger(value);
|
|
349
373
|
}
|
|
350
374
|
|
|
351
375
|
/**
|
|
@@ -354,11 +378,11 @@ function isInteger(value: unknown): value is number {
|
|
|
354
378
|
* @returns {boolean} True if the value is a float.
|
|
355
379
|
*/
|
|
356
380
|
function isFloat(value: unknown): value is number {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
381
|
+
return (
|
|
382
|
+
typeof value === "number" &&
|
|
383
|
+
!Number.isNaN(value) &&
|
|
384
|
+
!Number.isInteger(value)
|
|
385
|
+
);
|
|
362
386
|
}
|
|
363
387
|
|
|
364
388
|
/**
|
|
@@ -371,21 +395,18 @@ function isFloat(value: unknown): value is number {
|
|
|
371
395
|
*/
|
|
372
396
|
function parseFloat(value: unknown): Optional<number>;
|
|
373
397
|
function parseFloat(value: unknown, defaultValue: number): number;
|
|
374
|
-
function parseFloat(
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
): Optional<number> {
|
|
378
|
-
if (isNumber(value)) {
|
|
379
|
-
return value;
|
|
380
|
-
}
|
|
381
|
-
if (isString(value)) {
|
|
382
|
-
const normalizedValue = value.trim().replace(",", ".");
|
|
383
|
-
const parsed = Number.parseFloat(normalizedValue);
|
|
384
|
-
if (!Number.isNaN(parsed)) {
|
|
385
|
-
return parsed;
|
|
398
|
+
function parseFloat(value: unknown, defaultValue?: number): Optional<number> {
|
|
399
|
+
if (isNumber(value)) {
|
|
400
|
+
return value;
|
|
386
401
|
}
|
|
387
|
-
|
|
388
|
-
|
|
402
|
+
if (isString(value)) {
|
|
403
|
+
const normalizedValue = value.trim().replace(",", ".");
|
|
404
|
+
const parsed = Number.parseFloat(normalizedValue);
|
|
405
|
+
if (!Number.isNaN(parsed)) {
|
|
406
|
+
return parsed;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return defaultValue;
|
|
389
410
|
}
|
|
390
411
|
/**
|
|
391
412
|
* Parses the input value as a number. Returns NaN if the value cannot be
|
|
@@ -397,21 +418,18 @@ function parseFloat(
|
|
|
397
418
|
*/
|
|
398
419
|
function parseNumber(value: unknown): Optional<number>;
|
|
399
420
|
function parseNumber(value: unknown, defaultValue: number): number;
|
|
400
|
-
function parseNumber(
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
if (Number.isFinite(parsed)) {
|
|
411
|
-
return parsed;
|
|
421
|
+
function parseNumber(value: unknown, defaultValue?: number): Optional<number> {
|
|
422
|
+
if (isNumber(value)) {
|
|
423
|
+
return value;
|
|
424
|
+
}
|
|
425
|
+
if (isString(value)) {
|
|
426
|
+
const normalizedValue = value.trim().replace(",", ".");
|
|
427
|
+
const parsed = Number(normalizedValue);
|
|
428
|
+
if (Number.isFinite(parsed)) {
|
|
429
|
+
return parsed;
|
|
430
|
+
}
|
|
412
431
|
}
|
|
413
|
-
|
|
414
|
-
return defaultValue;
|
|
432
|
+
return defaultValue;
|
|
415
433
|
}
|
|
416
434
|
|
|
417
435
|
/**
|
|
@@ -422,20 +440,17 @@ function parseNumber(
|
|
|
422
440
|
* be parsed.
|
|
423
441
|
* @returns {string} The parsed string.
|
|
424
442
|
*/
|
|
425
|
-
function parseString(
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
return value.toString();
|
|
437
|
-
}
|
|
438
|
-
return defaultValue;
|
|
443
|
+
function parseString(value: unknown, defaultValue = ""): string {
|
|
444
|
+
if (isString(value)) {
|
|
445
|
+
return value;
|
|
446
|
+
}
|
|
447
|
+
if (isNumber(value)) {
|
|
448
|
+
return value.toString();
|
|
449
|
+
}
|
|
450
|
+
if (typeof value === "boolean") {
|
|
451
|
+
return value.toString();
|
|
452
|
+
}
|
|
453
|
+
return defaultValue;
|
|
439
454
|
}
|
|
440
455
|
|
|
441
456
|
/**
|
|
@@ -445,27 +460,29 @@ function parseString(
|
|
|
445
460
|
* false, or a plain object whose values are all empty-like.
|
|
446
461
|
*/
|
|
447
462
|
function isEmptyLike(value: unknown): boolean {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
}
|
|
451
|
-
if (isString(value)) {
|
|
452
|
-
return isEmptyString(value);
|
|
453
|
-
}
|
|
454
|
-
if (isArray(value)) {
|
|
455
|
-
return value.every((entry) => {return isEmptyLike(entry)});
|
|
456
|
-
}
|
|
457
|
-
if (isBoolean(value)) {
|
|
458
|
-
return !value;
|
|
459
|
-
}
|
|
460
|
-
if (isObject(value)) {
|
|
461
|
-
if (Object.getPrototypeOf(value) !== Object.prototype) {
|
|
462
|
-
return false;
|
|
463
|
+
if (isNull(value) || isUndefined(value)) {
|
|
464
|
+
return true;
|
|
463
465
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
466
|
+
if (isString(value)) {
|
|
467
|
+
return isEmptyString(value);
|
|
468
|
+
}
|
|
469
|
+
if (isArray(value)) {
|
|
470
|
+
return value.every((entry) => {
|
|
471
|
+
return isEmptyLike(entry);
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
if (isBoolean(value)) {
|
|
475
|
+
return !value;
|
|
476
|
+
}
|
|
477
|
+
if (isObject(value)) {
|
|
478
|
+
if (Object.getPrototypeOf(value) !== Object.prototype) {
|
|
479
|
+
return false;
|
|
480
|
+
}
|
|
481
|
+
return Object.values(value).every((entry) => {
|
|
482
|
+
return isEmptyLike(entry);
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
return false;
|
|
469
486
|
}
|
|
470
487
|
|
|
471
488
|
/**
|
|
@@ -479,15 +496,17 @@ function isEmptyLike(value: unknown): boolean {
|
|
|
479
496
|
* representation of an empty object; otherwise, `false`.
|
|
480
497
|
*/
|
|
481
498
|
function hasEmptyValues(value: unknown): boolean {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
499
|
+
if (isString(value)) {
|
|
500
|
+
try {
|
|
501
|
+
if (isEmptyObject(JSON.parse(value))) {
|
|
502
|
+
return true;
|
|
503
|
+
}
|
|
504
|
+
} catch {
|
|
505
|
+
return isEmptyString(value);
|
|
506
|
+
}
|
|
507
|
+
return isEmptyString(value);
|
|
487
508
|
}
|
|
488
|
-
return
|
|
489
|
-
}
|
|
490
|
-
return isEmptyObject(value);
|
|
509
|
+
return isEmptyObject(value);
|
|
491
510
|
}
|
|
492
511
|
|
|
493
512
|
/**
|
|
@@ -506,30 +525,34 @@ function parseArray<T extends Record<string, unknown>>(value: T): T[];
|
|
|
506
525
|
function parseArray<T>(value: unknown, defaultValue: readonly T[]): T[];
|
|
507
526
|
function parseArray(value: unknown): unknown[] | undefined;
|
|
508
527
|
function parseArray(
|
|
509
|
-
|
|
510
|
-
|
|
528
|
+
value: unknown,
|
|
529
|
+
defaultValue?: readonly unknown[],
|
|
511
530
|
): unknown[] | undefined {
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
531
|
+
if (isArray(value)) {
|
|
532
|
+
return [...value];
|
|
533
|
+
}
|
|
534
|
+
if (isString(value)) {
|
|
535
|
+
const parsed = value
|
|
536
|
+
.split(/[,|;\n\t ]+/)
|
|
537
|
+
.map((entry) => {
|
|
538
|
+
return entry.trim();
|
|
539
|
+
})
|
|
540
|
+
.filter((entry) => {
|
|
541
|
+
return entry.length > EMPTY_LENGTH;
|
|
542
|
+
});
|
|
543
|
+
return parsed;
|
|
544
|
+
}
|
|
545
|
+
if (isNumber(value)) {
|
|
546
|
+
return [value];
|
|
547
|
+
}
|
|
548
|
+
if (isEmptyObject(value)) {
|
|
549
|
+
return [value];
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
if (isNull(value) || isUndefined(value)) {
|
|
553
|
+
return cloneDefaultArray(defaultValue);
|
|
554
|
+
}
|
|
530
555
|
return cloneDefaultArray(defaultValue);
|
|
531
|
-
}
|
|
532
|
-
return cloneDefaultArray(defaultValue);
|
|
533
556
|
}
|
|
534
557
|
|
|
535
558
|
/**
|
|
@@ -539,13 +562,17 @@ function parseArray(
|
|
|
539
562
|
* @returns {boolean} True if the arrays have at least one common value.
|
|
540
563
|
*/
|
|
541
564
|
function arrayContainsCommonValue<T>(
|
|
542
|
-
|
|
543
|
-
|
|
565
|
+
array1: readonly T[],
|
|
566
|
+
array2: readonly T[],
|
|
544
567
|
): boolean {
|
|
545
|
-
|
|
568
|
+
if (!isArray(array1) || !isArray(array2)) {
|
|
569
|
+
return false;
|
|
570
|
+
}
|
|
546
571
|
|
|
547
|
-
|
|
548
|
-
|
|
572
|
+
const valueOccurrences = new Set(array1);
|
|
573
|
+
return array2.some((value) => {
|
|
574
|
+
return valueOccurrences.has(value);
|
|
575
|
+
});
|
|
549
576
|
}
|
|
550
577
|
|
|
551
578
|
/**
|
|
@@ -554,7 +581,7 @@ function arrayContainsCommonValue<T>(
|
|
|
554
581
|
* @returns {boolean} True if the input is a UUID string.
|
|
555
582
|
*/
|
|
556
583
|
function isUuidString(input: unknown): input is string {
|
|
557
|
-
|
|
584
|
+
return isString(input) && uuidRegex.test(input);
|
|
558
585
|
}
|
|
559
586
|
|
|
560
587
|
/**
|
|
@@ -563,7 +590,7 @@ function isUuidString(input: unknown): input is string {
|
|
|
563
590
|
* @returns {boolean} True if the input is a ULID string.
|
|
564
591
|
*/
|
|
565
592
|
function isUlidString(input: unknown): input is string {
|
|
566
|
-
|
|
593
|
+
return typeof input === "string" && ulidRegex.test(input);
|
|
567
594
|
}
|
|
568
595
|
|
|
569
596
|
/**
|
|
@@ -574,71 +601,70 @@ function isUlidString(input: unknown): input is string {
|
|
|
574
601
|
*/
|
|
575
602
|
function parseDomainName(url: string): Optional<string>;
|
|
576
603
|
function parseDomainName(url: string, defaultValue: string): string;
|
|
577
|
-
function parseDomainName(
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
if (normalizedValue === "" || normalizedValue.startsWith("/")) {
|
|
583
|
-
return defaultValue;
|
|
584
|
-
}
|
|
604
|
+
function parseDomainName(url: string, defaultValue?: string): Optional<string> {
|
|
605
|
+
const normalizedValue = url.trim();
|
|
606
|
+
if (normalizedValue === "" || normalizedValue.startsWith("/")) {
|
|
607
|
+
return defaultValue;
|
|
608
|
+
}
|
|
585
609
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
610
|
+
let urlCandidate = normalizedValue;
|
|
611
|
+
if (!normalizedValue.includes("://")) {
|
|
612
|
+
urlCandidate = `https://${normalizedValue}`;
|
|
613
|
+
}
|
|
590
614
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
615
|
+
let hostname = "";
|
|
616
|
+
try {
|
|
617
|
+
({ hostname } = new URL(urlCandidate));
|
|
618
|
+
} catch {
|
|
619
|
+
return defaultValue;
|
|
620
|
+
}
|
|
597
621
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
622
|
+
const normalizedHostname = hostname.replace(/^www\d?\./i, "");
|
|
623
|
+
const [domainName] = normalizedHostname.split(".");
|
|
624
|
+
if (!domainName) {
|
|
625
|
+
return defaultValue;
|
|
626
|
+
}
|
|
603
627
|
|
|
604
|
-
|
|
628
|
+
return domainName;
|
|
605
629
|
}
|
|
606
630
|
|
|
607
631
|
export {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
632
|
+
arrayContainsCommonValue,
|
|
633
|
+
err,
|
|
634
|
+
fastIsArray,
|
|
635
|
+
getKeys,
|
|
636
|
+
hasEmptyValues,
|
|
637
|
+
isArray,
|
|
638
|
+
isBoolean,
|
|
639
|
+
isDate,
|
|
640
|
+
isEmptyArray,
|
|
641
|
+
isEmptyLike,
|
|
642
|
+
isEmptyObject,
|
|
643
|
+
isEmptyString,
|
|
644
|
+
isError,
|
|
645
|
+
isFloat,
|
|
646
|
+
isFunction,
|
|
647
|
+
isInstanceOf,
|
|
648
|
+
isInteger,
|
|
649
|
+
isMaybe,
|
|
650
|
+
isNull,
|
|
651
|
+
isNullable,
|
|
652
|
+
isNumber,
|
|
653
|
+
isObject,
|
|
654
|
+
isOptional,
|
|
655
|
+
isPromise,
|
|
656
|
+
isRegExp,
|
|
657
|
+
isString,
|
|
658
|
+
isSuccess,
|
|
659
|
+
isSymbol,
|
|
660
|
+
isUlidString,
|
|
661
|
+
isUndefined,
|
|
662
|
+
isUuidString,
|
|
663
|
+
ok,
|
|
664
|
+
parseArray,
|
|
665
|
+
parseDomainName,
|
|
666
|
+
parseFloat,
|
|
667
|
+
parseInteger,
|
|
668
|
+
parseNumber,
|
|
669
|
+
parseString,
|
|
644
670
|
};
|