@alextheman/utility 5.1.4 → 5.3.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/dist/index.cjs +89 -23
- package/dist/index.d.cts +38 -7
- package/dist/index.d.ts +38 -7
- package/dist/index.js +89 -24
- package/dist/internal/index.cjs +53 -0
- package/dist/internal/index.d.cts +28 -0
- package/dist/internal/index.d.ts +28 -0
- package/dist/internal/index.js +53 -0
- package/dist/node/index.cjs +94 -41
- package/dist/node/index.js +94 -41
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -38,6 +38,10 @@ const FILE_PATH_REGEX = String.raw`^(?<directory>.+)[\/\\](?<base>[^\/\\]+)$`;
|
|
|
38
38
|
//#region src/root/constants/NAMESPACE_EXPORT_REGEX.ts
|
|
39
39
|
const NAMESPACE_EXPORT_REGEX = "export\\s+\\*\\s+from";
|
|
40
40
|
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/root/constants/ONE_DAY_IN_MILLISECONDS.ts
|
|
43
|
+
const ONE_DAY_IN_MILLISECONDS = 1440 * 60 * 1e3;
|
|
44
|
+
|
|
41
45
|
//#endregion
|
|
42
46
|
//#region src/root/constants/VERSION_NUMBER_REGEX.ts
|
|
43
47
|
const VERSION_NUMBER_REGEX = "^(?:v)?(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$";
|
|
@@ -164,6 +168,17 @@ var DataError = class DataError extends Error {
|
|
|
164
168
|
Object.defineProperty(this, "message", { enumerable: true });
|
|
165
169
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
166
170
|
}
|
|
171
|
+
static checkCaughtError(error, options) {
|
|
172
|
+
if (DataError.check(error)) {
|
|
173
|
+
if (options?.expectedCode && error.code !== options.expectedCode) throw new Error(normaliseIndents`The error code on the thrown error does not match the expected error code.
|
|
174
|
+
|
|
175
|
+
Expected: ${options.expectedCode}
|
|
176
|
+
Received: ${error.code}
|
|
177
|
+
`, { cause: error });
|
|
178
|
+
return error;
|
|
179
|
+
}
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
167
182
|
/**
|
|
168
183
|
* Checks whether the given input may have been caused by a DataError.
|
|
169
184
|
*
|
|
@@ -176,6 +191,44 @@ var DataError = class DataError extends Error {
|
|
|
176
191
|
const data = input;
|
|
177
192
|
return typeof data === "object" && data !== null && typeof data.message === "string" && typeof data.code === "string" && "data" in data;
|
|
178
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* Gets the thrown `DataError` from a given function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
196
|
+
*
|
|
197
|
+
* @param errorFunction - The function expected to throw the error.
|
|
198
|
+
* @param options - Extra options to apply.
|
|
199
|
+
*
|
|
200
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
201
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
202
|
+
*
|
|
203
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
204
|
+
*/
|
|
205
|
+
static expectError(errorFunction, options) {
|
|
206
|
+
try {
|
|
207
|
+
errorFunction();
|
|
208
|
+
} catch (error) {
|
|
209
|
+
return DataError.checkCaughtError(error, options);
|
|
210
|
+
}
|
|
211
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Gets the thrown `DataError` from a given asynchronous function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
215
|
+
*
|
|
216
|
+
* @param errorFunction - The function expected to throw the error.
|
|
217
|
+
* @param options - Extra options to apply.
|
|
218
|
+
*
|
|
219
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
220
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
221
|
+
*
|
|
222
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
223
|
+
*/
|
|
224
|
+
static async expectErrorAsync(errorFunction, options) {
|
|
225
|
+
try {
|
|
226
|
+
await errorFunction();
|
|
227
|
+
} catch (error) {
|
|
228
|
+
return DataError.checkCaughtError(error, options);
|
|
229
|
+
}
|
|
230
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
231
|
+
}
|
|
179
232
|
};
|
|
180
233
|
|
|
181
234
|
//#endregion
|
|
@@ -430,19 +483,27 @@ function randomiseArray(array) {
|
|
|
430
483
|
* @param stop - The number to stop at (exclusive).
|
|
431
484
|
* @param step - The step size between numbers, defaulting to 1.
|
|
432
485
|
*
|
|
433
|
-
* @throws {
|
|
434
|
-
* @throws {
|
|
486
|
+
* @throws {DataError} If `step` is `0`.
|
|
487
|
+
* @throws {DataError} If `step` direction does not match the order of `start` and `stop`.
|
|
435
488
|
*
|
|
436
489
|
* @returns An array of numbers satisfying the range provided.
|
|
437
490
|
*/
|
|
438
491
|
function range(start, stop, step = 1) {
|
|
439
492
|
const numbers = [];
|
|
440
|
-
if (step === 0) throw new
|
|
493
|
+
if (step === 0) throw new DataError({ step }, "ZERO_STEP_SIZE", "Step size cannot be zero.");
|
|
441
494
|
else if (step > 0) {
|
|
442
|
-
if (start > stop) throw new
|
|
495
|
+
if (start > stop) throw new DataError({
|
|
496
|
+
start,
|
|
497
|
+
stop,
|
|
498
|
+
step
|
|
499
|
+
}, "INVALID_BOUNDARIES", "The starting value cannot be bigger than the final value if step is positive");
|
|
443
500
|
for (let i = start; i < stop; i += step) numbers.push(i);
|
|
444
501
|
} else if (step < 0) {
|
|
445
|
-
if (start < stop) throw new
|
|
502
|
+
if (start < stop) throw new DataError({
|
|
503
|
+
start,
|
|
504
|
+
stop,
|
|
505
|
+
step
|
|
506
|
+
}, "INVALID_BOUNDARIES", "The final value cannot be bigger than the starting value if step is negative");
|
|
446
507
|
for (let i = start; i > stop; i += step) numbers.push(i);
|
|
447
508
|
}
|
|
448
509
|
return numbers;
|
|
@@ -622,7 +683,7 @@ function isMonthlyMultiple(firstDate, secondDate) {
|
|
|
622
683
|
*
|
|
623
684
|
* @param file - The file to convert.
|
|
624
685
|
*
|
|
625
|
-
* @throws {Error} If the file reader gives an error.
|
|
686
|
+
* @throws {Error | DataError} If the file reader gives an error.
|
|
626
687
|
*
|
|
627
688
|
* @returns A promise that resolves to the encoded base 64 string.
|
|
628
689
|
*/
|
|
@@ -632,7 +693,7 @@ function convertFileToBase64(file) {
|
|
|
632
693
|
reader.readAsDataURL(file);
|
|
633
694
|
reader.onload = () => {
|
|
634
695
|
if (reader.result === null) {
|
|
635
|
-
reject(
|
|
696
|
+
reject(new DataError({ result: reader.result }, "FILE_CONVERSION_ERROR", "Could not convert the given file."));
|
|
636
697
|
return;
|
|
637
698
|
}
|
|
638
699
|
resolve(reader.result);
|
|
@@ -648,6 +709,9 @@ function convertFileToBase64(file) {
|
|
|
648
709
|
function getNullableResolutionStrategy(key, strategy) {
|
|
649
710
|
return (typeof strategy === "object" ? strategy[key] : strategy) ?? "empty";
|
|
650
711
|
}
|
|
712
|
+
function isPrimitive(item) {
|
|
713
|
+
return typeof item === "string" || typeof item === "number" || typeof item === "boolean";
|
|
714
|
+
}
|
|
651
715
|
/**
|
|
652
716
|
* Creates FormData from a given object, resolving non-string types as appropriate.
|
|
653
717
|
*
|
|
@@ -674,7 +738,7 @@ function createFormData(data, options = {
|
|
|
674
738
|
formData.append(String(key), JSON.stringify(value));
|
|
675
739
|
break;
|
|
676
740
|
case "omit": break;
|
|
677
|
-
default: throw
|
|
741
|
+
default: throw resolutionStrategy;
|
|
678
742
|
}
|
|
679
743
|
}
|
|
680
744
|
function resolveNullables(key, value, options) {
|
|
@@ -697,10 +761,10 @@ function createFormData(data, options = {
|
|
|
697
761
|
if (Array.isArray(value)) {
|
|
698
762
|
if (value.some((item) => {
|
|
699
763
|
return item instanceof Blob;
|
|
700
|
-
}) && (options.arrayResolution === "stringify" || typeof options.arrayResolution === "object" && options.arrayResolution[key] === "stringify")) throw new
|
|
764
|
+
}) && (options.arrayResolution === "stringify" || typeof options.arrayResolution === "object" && options.arrayResolution[key] === "stringify")) throw new DataError({ value }, "CANNOT_STRINGIFY_BLOB", "Files/blobs cannot be stringified. Please change the resolution option for this item to \"multiple\" instead.");
|
|
701
765
|
if (options.arrayResolution === "multiple" || typeof options.arrayResolution === "object" && options.arrayResolution[key] === "multiple") {
|
|
702
766
|
for (const item of value) {
|
|
703
|
-
if ((
|
|
767
|
+
if (!isPrimitive(item) && !(item instanceof Blob)) throw new DataError({ item }, "NON_PRIMITIVE_ARRAY_ITEMS_FOUND", "Cannot directly add non-primitive data to FormData. Please change the resolution option for this item to \"stringify\" instead.");
|
|
704
768
|
if (item instanceof Blob) formData.append(String(key), item);
|
|
705
769
|
else formData.append(String(key), String(item));
|
|
706
770
|
}
|
|
@@ -1442,12 +1506,12 @@ async function encryptWithKey(publicKey, plaintextValue) {
|
|
|
1442
1506
|
*
|
|
1443
1507
|
* @param stringToAppendTo - The string to append a semicolon to.
|
|
1444
1508
|
*
|
|
1445
|
-
* @throws {
|
|
1509
|
+
* @throws {DataError} If the string contains multiple lines.
|
|
1446
1510
|
*
|
|
1447
1511
|
* @returns A string with the semicolon appended.
|
|
1448
1512
|
*/
|
|
1449
1513
|
function appendSemicolon(stringToAppendTo) {
|
|
1450
|
-
if (stringToAppendTo.includes("\n")) throw new
|
|
1514
|
+
if (stringToAppendTo.includes("\n")) throw new DataError({ stringToAppendTo }, "MULTIPLE_LINE_ERROR", "Cannot append semicolon to multi-line string.");
|
|
1451
1515
|
const stringWithNoTrailingWhitespace = stringToAppendTo.trimEnd();
|
|
1452
1516
|
if (stringWithNoTrailingWhitespace === "") return "";
|
|
1453
1517
|
return stringWithNoTrailingWhitespace[stringWithNoTrailingWhitespace.length - 1] === ";" ? stringWithNoTrailingWhitespace : `${stringWithNoTrailingWhitespace};`;
|
|
@@ -1499,34 +1563,35 @@ function camelToKebab(string, options = { preserveConsecutiveCapitals: true }) {
|
|
|
1499
1563
|
*
|
|
1500
1564
|
* @category String Helpers
|
|
1501
1565
|
*
|
|
1502
|
-
* @param
|
|
1566
|
+
* @param input - The string to convert.
|
|
1503
1567
|
* @param options - Options to apply to the conversion.
|
|
1504
1568
|
*
|
|
1505
1569
|
* @returns The string converted to camelCase.
|
|
1506
1570
|
*/
|
|
1507
|
-
function kebabToCamel(
|
|
1508
|
-
if (
|
|
1509
|
-
if (
|
|
1571
|
+
function kebabToCamel(input, options) {
|
|
1572
|
+
if (input !== input.toLowerCase()) throw new DataError({ input }, "UPPERCASE_INPUT", "Kebab-case must be purely lowercase.");
|
|
1573
|
+
if (input.startsWith("-") || input.endsWith("-")) throw new DataError({ input }, "TRAILING_DASHES", "Dashes at the start and/or end are not allowed.");
|
|
1574
|
+
if (input.includes("--")) throw new DataError({ input }, "CONSECUTIVE_DASHES", "Consecutive dashes are not allowed.");
|
|
1510
1575
|
let outputString = "";
|
|
1511
1576
|
let skip = false;
|
|
1512
|
-
for (const stringIndex in [...
|
|
1577
|
+
for (const stringIndex in [...input]) {
|
|
1513
1578
|
if (skip) {
|
|
1514
1579
|
skip = false;
|
|
1515
1580
|
continue;
|
|
1516
1581
|
}
|
|
1517
1582
|
const index = parseIntStrict(stringIndex);
|
|
1518
1583
|
if (index === 0 && options?.startWithUpper) {
|
|
1519
|
-
outputString +=
|
|
1584
|
+
outputString += input[index].toUpperCase();
|
|
1520
1585
|
continue;
|
|
1521
1586
|
}
|
|
1522
|
-
if (index ===
|
|
1523
|
-
outputString +=
|
|
1587
|
+
if (index === input.length - 1) {
|
|
1588
|
+
outputString += input[index];
|
|
1524
1589
|
break;
|
|
1525
1590
|
}
|
|
1526
|
-
if (
|
|
1527
|
-
outputString +=
|
|
1591
|
+
if (input[index] === "-" && /^[a-zA-Z]+$/.test(input[index + 1])) {
|
|
1592
|
+
outputString += input[index + 1].toUpperCase();
|
|
1528
1593
|
skip = true;
|
|
1529
|
-
} else outputString +=
|
|
1594
|
+
} else outputString += input[index];
|
|
1530
1595
|
}
|
|
1531
1596
|
return outputString;
|
|
1532
1597
|
}
|
|
@@ -1553,6 +1618,7 @@ exports.DataError = DataError;
|
|
|
1553
1618
|
exports.Env = Env;
|
|
1554
1619
|
exports.FILE_PATH_REGEX = FILE_PATH_REGEX;
|
|
1555
1620
|
exports.NAMESPACE_EXPORT_REGEX = NAMESPACE_EXPORT_REGEX;
|
|
1621
|
+
exports.ONE_DAY_IN_MILLISECONDS = ONE_DAY_IN_MILLISECONDS;
|
|
1556
1622
|
exports.VERSION_NUMBER_REGEX = VERSION_NUMBER_REGEX;
|
|
1557
1623
|
exports.VersionNumber = VersionNumber;
|
|
1558
1624
|
exports.VersionType = VersionType;
|
package/dist/index.d.cts
CHANGED
|
@@ -7,6 +7,9 @@ declare const FILE_PATH_REGEX: string;
|
|
|
7
7
|
//#region src/root/constants/NAMESPACE_EXPORT_REGEX.d.ts
|
|
8
8
|
declare const NAMESPACE_EXPORT_REGEX = "export\\s+\\*\\s+from";
|
|
9
9
|
//#endregion
|
|
10
|
+
//#region src/root/constants/ONE_DAY_IN_MILLISECONDS.d.ts
|
|
11
|
+
declare const ONE_DAY_IN_MILLISECONDS: number;
|
|
12
|
+
//#endregion
|
|
10
13
|
//#region src/root/constants/VERSION_NUMBER_REGEX.d.ts
|
|
11
14
|
declare const VERSION_NUMBER_REGEX: string;
|
|
12
15
|
//#endregion
|
|
@@ -87,8 +90,8 @@ declare function randomiseArray<ItemType>(array: ItemType[]): ItemType[];
|
|
|
87
90
|
* @param stop - The number to stop at (exclusive).
|
|
88
91
|
* @param step - The step size between numbers, defaulting to 1.
|
|
89
92
|
*
|
|
90
|
-
* @throws {
|
|
91
|
-
* @throws {
|
|
93
|
+
* @throws {DataError} If `step` is `0`.
|
|
94
|
+
* @throws {DataError} If `step` direction does not match the order of `start` and `stop`.
|
|
92
95
|
*
|
|
93
96
|
* @returns An array of numbers satisfying the range provided.
|
|
94
97
|
*/
|
|
@@ -198,7 +201,7 @@ declare function isSameDate(firstDate: Date, secondDate: Date): boolean;
|
|
|
198
201
|
*
|
|
199
202
|
* @param file - The file to convert.
|
|
200
203
|
*
|
|
201
|
-
* @throws {Error} If the file reader gives an error.
|
|
204
|
+
* @throws {Error | DataError} If the file reader gives an error.
|
|
202
205
|
*
|
|
203
206
|
* @returns A promise that resolves to the encoded base 64 string.
|
|
204
207
|
*/
|
|
@@ -239,6 +242,9 @@ declare class APIError extends Error {
|
|
|
239
242
|
type RecordKey = string | number | symbol;
|
|
240
243
|
//#endregion
|
|
241
244
|
//#region src/root/types/DataError.d.ts
|
|
245
|
+
interface ExpectErrorOptions {
|
|
246
|
+
expectedCode?: string;
|
|
247
|
+
}
|
|
242
248
|
/**
|
|
243
249
|
* Represents errors you may get that may've been caused by a specific piece of data.
|
|
244
250
|
*
|
|
@@ -256,6 +262,7 @@ declare class DataError<DataType extends Record<RecordKey, unknown> = Record<Rec
|
|
|
256
262
|
* @param options - Extra options to pass to super Error constructor.
|
|
257
263
|
*/
|
|
258
264
|
constructor(data: DataType, code?: string, message?: string, options?: ErrorOptions);
|
|
265
|
+
private static checkCaughtError;
|
|
259
266
|
/**
|
|
260
267
|
* Checks whether the given input may have been caused by a DataError.
|
|
261
268
|
*
|
|
@@ -264,6 +271,30 @@ declare class DataError<DataType extends Record<RecordKey, unknown> = Record<Rec
|
|
|
264
271
|
* @returns `true` if the input is a DataError, and `false` otherwise. The type of the input will also be narrowed down to DataError if `true`.
|
|
265
272
|
*/
|
|
266
273
|
static check<DataType extends Record<RecordKey, unknown> = Record<RecordKey, unknown>>(input: unknown): input is DataError<DataType>;
|
|
274
|
+
/**
|
|
275
|
+
* Gets the thrown `DataError` from a given function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
276
|
+
*
|
|
277
|
+
* @param errorFunction - The function expected to throw the error.
|
|
278
|
+
* @param options - Extra options to apply.
|
|
279
|
+
*
|
|
280
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
281
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
282
|
+
*
|
|
283
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
284
|
+
*/
|
|
285
|
+
static expectError(errorFunction: () => unknown, options?: ExpectErrorOptions): DataError;
|
|
286
|
+
/**
|
|
287
|
+
* Gets the thrown `DataError` from a given asynchronous function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
288
|
+
*
|
|
289
|
+
* @param errorFunction - The function expected to throw the error.
|
|
290
|
+
* @param options - Extra options to apply.
|
|
291
|
+
*
|
|
292
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
293
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
294
|
+
*
|
|
295
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
296
|
+
*/
|
|
297
|
+
static expectErrorAsync(errorFunction: () => Promise<unknown>, options?: ExpectErrorOptions): Promise<DataError>;
|
|
267
298
|
}
|
|
268
299
|
//#endregion
|
|
269
300
|
//#region src/root/types/VersionNumber.d.ts
|
|
@@ -821,7 +852,7 @@ declare function encryptWithKey(publicKey: string, plaintextValue: string): Prom
|
|
|
821
852
|
*
|
|
822
853
|
* @param stringToAppendTo - The string to append a semicolon to.
|
|
823
854
|
*
|
|
824
|
-
* @throws {
|
|
855
|
+
* @throws {DataError} If the string contains multiple lines.
|
|
825
856
|
*
|
|
826
857
|
* @returns A string with the semicolon appended.
|
|
827
858
|
*/
|
|
@@ -864,12 +895,12 @@ interface KebabToCamelOptions {
|
|
|
864
895
|
*
|
|
865
896
|
* @category String Helpers
|
|
866
897
|
*
|
|
867
|
-
* @param
|
|
898
|
+
* @param input - The string to convert.
|
|
868
899
|
* @param options - Options to apply to the conversion.
|
|
869
900
|
*
|
|
870
901
|
* @returns The string converted to camelCase.
|
|
871
902
|
*/
|
|
872
|
-
declare function kebabToCamel(
|
|
903
|
+
declare function kebabToCamel(input: string, options?: KebabToCamelOptions): string;
|
|
873
904
|
//#endregion
|
|
874
905
|
//#region src/root/functions/stringHelpers/truncate.d.ts
|
|
875
906
|
/**
|
|
@@ -1052,4 +1083,4 @@ declare function normaliseIndents(strings: TemplateStringsArray, ...interpolatio
|
|
|
1052
1083
|
*/
|
|
1053
1084
|
declare const normalizeIndents: typeof normaliseIndents;
|
|
1054
1085
|
//#endregion
|
|
1055
|
-
export { APIError, ArrayElement, CallReturnType, CamelToKebabOptions, CreateEnumType, CreateFormDataOptions, CreateFormDataOptionsNullableResolution, CreateFormDataOptionsUndefinedOrNullResolution, DataError, DisallowUndefined, Env, FILE_PATH_REGEX, FormDataArrayResolutionStrategy, FormDataNullableResolutionStrategy, HTTPErrorCode, IgnoreCase, IsTypeArgumentString, KebabToCamelOptions, NAMESPACE_EXPORT_REGEX, NonUndefined, NormaliseIndentsFunction, NormaliseIndentsOptions, NormalizeIndentsFunction, NormalizeIndentsOptions, OptionalOnCondition, ParallelTuple, RecordKey, RemoveUndefined, StringListToArrayOptions, VERSION_NUMBER_REGEX, VersionNumber, FormatOptionsBase as VersionNumberToStringOptions, VersionType, addDaysToDate, appendSemicolon, camelToKebab, convertFileToBase64, createFormData, createTemplateStringsArray, deepCopy, deepFreeze, encryptWithKey, fillArray, formatDateAndTime, getRandomNumber, getRecordKeys, getStringsAndInterpolations, httpErrorCodeLookup, interpolate, interpolateObjects, isAnniversary, isLeapYear, isMonthlyMultiple, isOrdered, isSameDate, isTemplateStringsArray, kebabToCamel, normaliseIndents, normalizeIndents, omitProperties, paralleliseArrays, parseBoolean, parseEnv, parseFormData, parseIntStrict, parseVersionType, parseZodSchema, parseZodSchemaAsync, randomiseArray, range, removeDuplicates, removeUndefinedFromObject, sayHello, stringListToArray, stringifyDotenv, truncate, wait, zodVersionNumber };
|
|
1086
|
+
export { APIError, ArrayElement, CallReturnType, CamelToKebabOptions, CreateEnumType, CreateFormDataOptions, CreateFormDataOptionsNullableResolution, CreateFormDataOptionsUndefinedOrNullResolution, DataError, DisallowUndefined, Env, FILE_PATH_REGEX, FormDataArrayResolutionStrategy, FormDataNullableResolutionStrategy, HTTPErrorCode, IgnoreCase, IsTypeArgumentString, KebabToCamelOptions, NAMESPACE_EXPORT_REGEX, NonUndefined, NormaliseIndentsFunction, NormaliseIndentsOptions, NormalizeIndentsFunction, NormalizeIndentsOptions, ONE_DAY_IN_MILLISECONDS, OptionalOnCondition, ParallelTuple, RecordKey, RemoveUndefined, StringListToArrayOptions, VERSION_NUMBER_REGEX, VersionNumber, FormatOptionsBase as VersionNumberToStringOptions, VersionType, addDaysToDate, appendSemicolon, camelToKebab, convertFileToBase64, createFormData, createTemplateStringsArray, deepCopy, deepFreeze, encryptWithKey, fillArray, formatDateAndTime, getRandomNumber, getRecordKeys, getStringsAndInterpolations, httpErrorCodeLookup, interpolate, interpolateObjects, isAnniversary, isLeapYear, isMonthlyMultiple, isOrdered, isSameDate, isTemplateStringsArray, kebabToCamel, normaliseIndents, normalizeIndents, omitProperties, paralleliseArrays, parseBoolean, parseEnv, parseFormData, parseIntStrict, parseVersionType, parseZodSchema, parseZodSchemaAsync, randomiseArray, range, removeDuplicates, removeUndefinedFromObject, sayHello, stringListToArray, stringifyDotenv, truncate, wait, zodVersionNumber };
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,9 @@ declare const FILE_PATH_REGEX: string;
|
|
|
7
7
|
//#region src/root/constants/NAMESPACE_EXPORT_REGEX.d.ts
|
|
8
8
|
declare const NAMESPACE_EXPORT_REGEX = "export\\s+\\*\\s+from";
|
|
9
9
|
//#endregion
|
|
10
|
+
//#region src/root/constants/ONE_DAY_IN_MILLISECONDS.d.ts
|
|
11
|
+
declare const ONE_DAY_IN_MILLISECONDS: number;
|
|
12
|
+
//#endregion
|
|
10
13
|
//#region src/root/constants/VERSION_NUMBER_REGEX.d.ts
|
|
11
14
|
declare const VERSION_NUMBER_REGEX: string;
|
|
12
15
|
//#endregion
|
|
@@ -87,8 +90,8 @@ declare function randomiseArray<ItemType>(array: ItemType[]): ItemType[];
|
|
|
87
90
|
* @param stop - The number to stop at (exclusive).
|
|
88
91
|
* @param step - The step size between numbers, defaulting to 1.
|
|
89
92
|
*
|
|
90
|
-
* @throws {
|
|
91
|
-
* @throws {
|
|
93
|
+
* @throws {DataError} If `step` is `0`.
|
|
94
|
+
* @throws {DataError} If `step` direction does not match the order of `start` and `stop`.
|
|
92
95
|
*
|
|
93
96
|
* @returns An array of numbers satisfying the range provided.
|
|
94
97
|
*/
|
|
@@ -198,7 +201,7 @@ declare function isSameDate(firstDate: Date, secondDate: Date): boolean;
|
|
|
198
201
|
*
|
|
199
202
|
* @param file - The file to convert.
|
|
200
203
|
*
|
|
201
|
-
* @throws {Error} If the file reader gives an error.
|
|
204
|
+
* @throws {Error | DataError} If the file reader gives an error.
|
|
202
205
|
*
|
|
203
206
|
* @returns A promise that resolves to the encoded base 64 string.
|
|
204
207
|
*/
|
|
@@ -239,6 +242,9 @@ declare class APIError extends Error {
|
|
|
239
242
|
type RecordKey = string | number | symbol;
|
|
240
243
|
//#endregion
|
|
241
244
|
//#region src/root/types/DataError.d.ts
|
|
245
|
+
interface ExpectErrorOptions {
|
|
246
|
+
expectedCode?: string;
|
|
247
|
+
}
|
|
242
248
|
/**
|
|
243
249
|
* Represents errors you may get that may've been caused by a specific piece of data.
|
|
244
250
|
*
|
|
@@ -256,6 +262,7 @@ declare class DataError<DataType extends Record<RecordKey, unknown> = Record<Rec
|
|
|
256
262
|
* @param options - Extra options to pass to super Error constructor.
|
|
257
263
|
*/
|
|
258
264
|
constructor(data: DataType, code?: string, message?: string, options?: ErrorOptions);
|
|
265
|
+
private static checkCaughtError;
|
|
259
266
|
/**
|
|
260
267
|
* Checks whether the given input may have been caused by a DataError.
|
|
261
268
|
*
|
|
@@ -264,6 +271,30 @@ declare class DataError<DataType extends Record<RecordKey, unknown> = Record<Rec
|
|
|
264
271
|
* @returns `true` if the input is a DataError, and `false` otherwise. The type of the input will also be narrowed down to DataError if `true`.
|
|
265
272
|
*/
|
|
266
273
|
static check<DataType extends Record<RecordKey, unknown> = Record<RecordKey, unknown>>(input: unknown): input is DataError<DataType>;
|
|
274
|
+
/**
|
|
275
|
+
* Gets the thrown `DataError` from a given function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
276
|
+
*
|
|
277
|
+
* @param errorFunction - The function expected to throw the error.
|
|
278
|
+
* @param options - Extra options to apply.
|
|
279
|
+
*
|
|
280
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
281
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
282
|
+
*
|
|
283
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
284
|
+
*/
|
|
285
|
+
static expectError(errorFunction: () => unknown, options?: ExpectErrorOptions): DataError;
|
|
286
|
+
/**
|
|
287
|
+
* Gets the thrown `DataError` from a given asynchronous function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
288
|
+
*
|
|
289
|
+
* @param errorFunction - The function expected to throw the error.
|
|
290
|
+
* @param options - Extra options to apply.
|
|
291
|
+
*
|
|
292
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
293
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
294
|
+
*
|
|
295
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
296
|
+
*/
|
|
297
|
+
static expectErrorAsync(errorFunction: () => Promise<unknown>, options?: ExpectErrorOptions): Promise<DataError>;
|
|
267
298
|
}
|
|
268
299
|
//#endregion
|
|
269
300
|
//#region src/root/types/VersionNumber.d.ts
|
|
@@ -821,7 +852,7 @@ declare function encryptWithKey(publicKey: string, plaintextValue: string): Prom
|
|
|
821
852
|
*
|
|
822
853
|
* @param stringToAppendTo - The string to append a semicolon to.
|
|
823
854
|
*
|
|
824
|
-
* @throws {
|
|
855
|
+
* @throws {DataError} If the string contains multiple lines.
|
|
825
856
|
*
|
|
826
857
|
* @returns A string with the semicolon appended.
|
|
827
858
|
*/
|
|
@@ -864,12 +895,12 @@ interface KebabToCamelOptions {
|
|
|
864
895
|
*
|
|
865
896
|
* @category String Helpers
|
|
866
897
|
*
|
|
867
|
-
* @param
|
|
898
|
+
* @param input - The string to convert.
|
|
868
899
|
* @param options - Options to apply to the conversion.
|
|
869
900
|
*
|
|
870
901
|
* @returns The string converted to camelCase.
|
|
871
902
|
*/
|
|
872
|
-
declare function kebabToCamel(
|
|
903
|
+
declare function kebabToCamel(input: string, options?: KebabToCamelOptions): string;
|
|
873
904
|
//#endregion
|
|
874
905
|
//#region src/root/functions/stringHelpers/truncate.d.ts
|
|
875
906
|
/**
|
|
@@ -1052,4 +1083,4 @@ declare function normaliseIndents(strings: TemplateStringsArray, ...interpolatio
|
|
|
1052
1083
|
*/
|
|
1053
1084
|
declare const normalizeIndents: typeof normaliseIndents;
|
|
1054
1085
|
//#endregion
|
|
1055
|
-
export { APIError, type ArrayElement, type CallReturnType, CamelToKebabOptions, type CreateEnumType, type CreateFormDataOptions, type CreateFormDataOptionsNullableResolution, type CreateFormDataOptionsUndefinedOrNullResolution, DataError, type DisallowUndefined, Env, FILE_PATH_REGEX, type FormDataArrayResolutionStrategy, type FormDataNullableResolutionStrategy, type HTTPErrorCode, type IgnoreCase, type IsTypeArgumentString, KebabToCamelOptions, NAMESPACE_EXPORT_REGEX, type NonUndefined, NormaliseIndentsFunction, NormaliseIndentsOptions, NormalizeIndentsFunction, NormalizeIndentsOptions, type OptionalOnCondition, ParallelTuple, type RecordKey, type RemoveUndefined, type StringListToArrayOptions, VERSION_NUMBER_REGEX, VersionNumber, type FormatOptionsBase as VersionNumberToStringOptions, VersionType, addDaysToDate, appendSemicolon, camelToKebab, convertFileToBase64, createFormData, createTemplateStringsArray, deepCopy, deepFreeze, encryptWithKey, fillArray, formatDateAndTime, getRandomNumber, getRecordKeys, getStringsAndInterpolations, httpErrorCodeLookup, interpolate, interpolateObjects, isAnniversary, isLeapYear, isMonthlyMultiple, isOrdered, isSameDate, isTemplateStringsArray, kebabToCamel, normaliseIndents, normalizeIndents, omitProperties, paralleliseArrays, parseBoolean, parseEnv, parseFormData, parseIntStrict, parseVersionType, parseZodSchema, parseZodSchemaAsync, randomiseArray, range, removeDuplicates, removeUndefinedFromObject, sayHello, stringListToArray, stringifyDotenv, truncate, wait, zodVersionNumber };
|
|
1086
|
+
export { APIError, type ArrayElement, type CallReturnType, CamelToKebabOptions, type CreateEnumType, type CreateFormDataOptions, type CreateFormDataOptionsNullableResolution, type CreateFormDataOptionsUndefinedOrNullResolution, DataError, type DisallowUndefined, Env, FILE_PATH_REGEX, type FormDataArrayResolutionStrategy, type FormDataNullableResolutionStrategy, type HTTPErrorCode, type IgnoreCase, type IsTypeArgumentString, KebabToCamelOptions, NAMESPACE_EXPORT_REGEX, type NonUndefined, NormaliseIndentsFunction, NormaliseIndentsOptions, NormalizeIndentsFunction, NormalizeIndentsOptions, ONE_DAY_IN_MILLISECONDS, type OptionalOnCondition, ParallelTuple, type RecordKey, type RemoveUndefined, type StringListToArrayOptions, VERSION_NUMBER_REGEX, VersionNumber, type FormatOptionsBase as VersionNumberToStringOptions, VersionType, addDaysToDate, appendSemicolon, camelToKebab, convertFileToBase64, createFormData, createTemplateStringsArray, deepCopy, deepFreeze, encryptWithKey, fillArray, formatDateAndTime, getRandomNumber, getRecordKeys, getStringsAndInterpolations, httpErrorCodeLookup, interpolate, interpolateObjects, isAnniversary, isLeapYear, isMonthlyMultiple, isOrdered, isSameDate, isTemplateStringsArray, kebabToCamel, normaliseIndents, normalizeIndents, omitProperties, paralleliseArrays, parseBoolean, parseEnv, parseFormData, parseIntStrict, parseVersionType, parseZodSchema, parseZodSchemaAsync, randomiseArray, range, removeDuplicates, removeUndefinedFromObject, sayHello, stringListToArray, stringifyDotenv, truncate, wait, zodVersionNumber };
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,10 @@ const FILE_PATH_REGEX = String.raw`^(?<directory>.+)[\/\\](?<base>[^\/\\]+)$`;
|
|
|
8
8
|
//#region src/root/constants/NAMESPACE_EXPORT_REGEX.ts
|
|
9
9
|
const NAMESPACE_EXPORT_REGEX = "export\\s+\\*\\s+from";
|
|
10
10
|
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/root/constants/ONE_DAY_IN_MILLISECONDS.ts
|
|
13
|
+
const ONE_DAY_IN_MILLISECONDS = 1440 * 60 * 1e3;
|
|
14
|
+
|
|
11
15
|
//#endregion
|
|
12
16
|
//#region src/root/constants/VERSION_NUMBER_REGEX.ts
|
|
13
17
|
const VERSION_NUMBER_REGEX = "^(?:v)?(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$";
|
|
@@ -134,6 +138,17 @@ var DataError = class DataError extends Error {
|
|
|
134
138
|
Object.defineProperty(this, "message", { enumerable: true });
|
|
135
139
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
136
140
|
}
|
|
141
|
+
static checkCaughtError(error, options) {
|
|
142
|
+
if (DataError.check(error)) {
|
|
143
|
+
if (options?.expectedCode && error.code !== options.expectedCode) throw new Error(normaliseIndents`The error code on the thrown error does not match the expected error code.
|
|
144
|
+
|
|
145
|
+
Expected: ${options.expectedCode}
|
|
146
|
+
Received: ${error.code}
|
|
147
|
+
`, { cause: error });
|
|
148
|
+
return error;
|
|
149
|
+
}
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
137
152
|
/**
|
|
138
153
|
* Checks whether the given input may have been caused by a DataError.
|
|
139
154
|
*
|
|
@@ -146,6 +161,44 @@ var DataError = class DataError extends Error {
|
|
|
146
161
|
const data = input;
|
|
147
162
|
return typeof data === "object" && data !== null && typeof data.message === "string" && typeof data.code === "string" && "data" in data;
|
|
148
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Gets the thrown `DataError` from a given function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
166
|
+
*
|
|
167
|
+
* @param errorFunction - The function expected to throw the error.
|
|
168
|
+
* @param options - Extra options to apply.
|
|
169
|
+
*
|
|
170
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
171
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
172
|
+
*
|
|
173
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
174
|
+
*/
|
|
175
|
+
static expectError(errorFunction, options) {
|
|
176
|
+
try {
|
|
177
|
+
errorFunction();
|
|
178
|
+
} catch (error) {
|
|
179
|
+
return DataError.checkCaughtError(error, options);
|
|
180
|
+
}
|
|
181
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Gets the thrown `DataError` from a given asynchronous function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
185
|
+
*
|
|
186
|
+
* @param errorFunction - The function expected to throw the error.
|
|
187
|
+
* @param options - Extra options to apply.
|
|
188
|
+
*
|
|
189
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
190
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
191
|
+
*
|
|
192
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
193
|
+
*/
|
|
194
|
+
static async expectErrorAsync(errorFunction, options) {
|
|
195
|
+
try {
|
|
196
|
+
await errorFunction();
|
|
197
|
+
} catch (error) {
|
|
198
|
+
return DataError.checkCaughtError(error, options);
|
|
199
|
+
}
|
|
200
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
201
|
+
}
|
|
149
202
|
};
|
|
150
203
|
|
|
151
204
|
//#endregion
|
|
@@ -400,19 +453,27 @@ function randomiseArray(array) {
|
|
|
400
453
|
* @param stop - The number to stop at (exclusive).
|
|
401
454
|
* @param step - The step size between numbers, defaulting to 1.
|
|
402
455
|
*
|
|
403
|
-
* @throws {
|
|
404
|
-
* @throws {
|
|
456
|
+
* @throws {DataError} If `step` is `0`.
|
|
457
|
+
* @throws {DataError} If `step` direction does not match the order of `start` and `stop`.
|
|
405
458
|
*
|
|
406
459
|
* @returns An array of numbers satisfying the range provided.
|
|
407
460
|
*/
|
|
408
461
|
function range(start, stop, step = 1) {
|
|
409
462
|
const numbers = [];
|
|
410
|
-
if (step === 0) throw new
|
|
463
|
+
if (step === 0) throw new DataError({ step }, "ZERO_STEP_SIZE", "Step size cannot be zero.");
|
|
411
464
|
else if (step > 0) {
|
|
412
|
-
if (start > stop) throw new
|
|
465
|
+
if (start > stop) throw new DataError({
|
|
466
|
+
start,
|
|
467
|
+
stop,
|
|
468
|
+
step
|
|
469
|
+
}, "INVALID_BOUNDARIES", "The starting value cannot be bigger than the final value if step is positive");
|
|
413
470
|
for (let i = start; i < stop; i += step) numbers.push(i);
|
|
414
471
|
} else if (step < 0) {
|
|
415
|
-
if (start < stop) throw new
|
|
472
|
+
if (start < stop) throw new DataError({
|
|
473
|
+
start,
|
|
474
|
+
stop,
|
|
475
|
+
step
|
|
476
|
+
}, "INVALID_BOUNDARIES", "The final value cannot be bigger than the starting value if step is negative");
|
|
416
477
|
for (let i = start; i > stop; i += step) numbers.push(i);
|
|
417
478
|
}
|
|
418
479
|
return numbers;
|
|
@@ -592,7 +653,7 @@ function isMonthlyMultiple(firstDate, secondDate) {
|
|
|
592
653
|
*
|
|
593
654
|
* @param file - The file to convert.
|
|
594
655
|
*
|
|
595
|
-
* @throws {Error} If the file reader gives an error.
|
|
656
|
+
* @throws {Error | DataError} If the file reader gives an error.
|
|
596
657
|
*
|
|
597
658
|
* @returns A promise that resolves to the encoded base 64 string.
|
|
598
659
|
*/
|
|
@@ -602,7 +663,7 @@ function convertFileToBase64(file) {
|
|
|
602
663
|
reader.readAsDataURL(file);
|
|
603
664
|
reader.onload = () => {
|
|
604
665
|
if (reader.result === null) {
|
|
605
|
-
reject(
|
|
666
|
+
reject(new DataError({ result: reader.result }, "FILE_CONVERSION_ERROR", "Could not convert the given file."));
|
|
606
667
|
return;
|
|
607
668
|
}
|
|
608
669
|
resolve(reader.result);
|
|
@@ -618,6 +679,9 @@ function convertFileToBase64(file) {
|
|
|
618
679
|
function getNullableResolutionStrategy(key, strategy) {
|
|
619
680
|
return (typeof strategy === "object" ? strategy[key] : strategy) ?? "empty";
|
|
620
681
|
}
|
|
682
|
+
function isPrimitive(item) {
|
|
683
|
+
return typeof item === "string" || typeof item === "number" || typeof item === "boolean";
|
|
684
|
+
}
|
|
621
685
|
/**
|
|
622
686
|
* Creates FormData from a given object, resolving non-string types as appropriate.
|
|
623
687
|
*
|
|
@@ -644,7 +708,7 @@ function createFormData(data, options = {
|
|
|
644
708
|
formData.append(String(key), JSON.stringify(value));
|
|
645
709
|
break;
|
|
646
710
|
case "omit": break;
|
|
647
|
-
default: throw
|
|
711
|
+
default: throw resolutionStrategy;
|
|
648
712
|
}
|
|
649
713
|
}
|
|
650
714
|
function resolveNullables(key, value, options) {
|
|
@@ -667,10 +731,10 @@ function createFormData(data, options = {
|
|
|
667
731
|
if (Array.isArray(value)) {
|
|
668
732
|
if (value.some((item) => {
|
|
669
733
|
return item instanceof Blob;
|
|
670
|
-
}) && (options.arrayResolution === "stringify" || typeof options.arrayResolution === "object" && options.arrayResolution[key] === "stringify")) throw new
|
|
734
|
+
}) && (options.arrayResolution === "stringify" || typeof options.arrayResolution === "object" && options.arrayResolution[key] === "stringify")) throw new DataError({ value }, "CANNOT_STRINGIFY_BLOB", "Files/blobs cannot be stringified. Please change the resolution option for this item to \"multiple\" instead.");
|
|
671
735
|
if (options.arrayResolution === "multiple" || typeof options.arrayResolution === "object" && options.arrayResolution[key] === "multiple") {
|
|
672
736
|
for (const item of value) {
|
|
673
|
-
if ((
|
|
737
|
+
if (!isPrimitive(item) && !(item instanceof Blob)) throw new DataError({ item }, "NON_PRIMITIVE_ARRAY_ITEMS_FOUND", "Cannot directly add non-primitive data to FormData. Please change the resolution option for this item to \"stringify\" instead.");
|
|
674
738
|
if (item instanceof Blob) formData.append(String(key), item);
|
|
675
739
|
else formData.append(String(key), String(item));
|
|
676
740
|
}
|
|
@@ -1412,12 +1476,12 @@ async function encryptWithKey(publicKey, plaintextValue) {
|
|
|
1412
1476
|
*
|
|
1413
1477
|
* @param stringToAppendTo - The string to append a semicolon to.
|
|
1414
1478
|
*
|
|
1415
|
-
* @throws {
|
|
1479
|
+
* @throws {DataError} If the string contains multiple lines.
|
|
1416
1480
|
*
|
|
1417
1481
|
* @returns A string with the semicolon appended.
|
|
1418
1482
|
*/
|
|
1419
1483
|
function appendSemicolon(stringToAppendTo) {
|
|
1420
|
-
if (stringToAppendTo.includes("\n")) throw new
|
|
1484
|
+
if (stringToAppendTo.includes("\n")) throw new DataError({ stringToAppendTo }, "MULTIPLE_LINE_ERROR", "Cannot append semicolon to multi-line string.");
|
|
1421
1485
|
const stringWithNoTrailingWhitespace = stringToAppendTo.trimEnd();
|
|
1422
1486
|
if (stringWithNoTrailingWhitespace === "") return "";
|
|
1423
1487
|
return stringWithNoTrailingWhitespace[stringWithNoTrailingWhitespace.length - 1] === ";" ? stringWithNoTrailingWhitespace : `${stringWithNoTrailingWhitespace};`;
|
|
@@ -1469,34 +1533,35 @@ function camelToKebab(string, options = { preserveConsecutiveCapitals: true }) {
|
|
|
1469
1533
|
*
|
|
1470
1534
|
* @category String Helpers
|
|
1471
1535
|
*
|
|
1472
|
-
* @param
|
|
1536
|
+
* @param input - The string to convert.
|
|
1473
1537
|
* @param options - Options to apply to the conversion.
|
|
1474
1538
|
*
|
|
1475
1539
|
* @returns The string converted to camelCase.
|
|
1476
1540
|
*/
|
|
1477
|
-
function kebabToCamel(
|
|
1478
|
-
if (
|
|
1479
|
-
if (
|
|
1541
|
+
function kebabToCamel(input, options) {
|
|
1542
|
+
if (input !== input.toLowerCase()) throw new DataError({ input }, "UPPERCASE_INPUT", "Kebab-case must be purely lowercase.");
|
|
1543
|
+
if (input.startsWith("-") || input.endsWith("-")) throw new DataError({ input }, "TRAILING_DASHES", "Dashes at the start and/or end are not allowed.");
|
|
1544
|
+
if (input.includes("--")) throw new DataError({ input }, "CONSECUTIVE_DASHES", "Consecutive dashes are not allowed.");
|
|
1480
1545
|
let outputString = "";
|
|
1481
1546
|
let skip = false;
|
|
1482
|
-
for (const stringIndex in [...
|
|
1547
|
+
for (const stringIndex in [...input]) {
|
|
1483
1548
|
if (skip) {
|
|
1484
1549
|
skip = false;
|
|
1485
1550
|
continue;
|
|
1486
1551
|
}
|
|
1487
1552
|
const index = parseIntStrict(stringIndex);
|
|
1488
1553
|
if (index === 0 && options?.startWithUpper) {
|
|
1489
|
-
outputString +=
|
|
1554
|
+
outputString += input[index].toUpperCase();
|
|
1490
1555
|
continue;
|
|
1491
1556
|
}
|
|
1492
|
-
if (index ===
|
|
1493
|
-
outputString +=
|
|
1557
|
+
if (index === input.length - 1) {
|
|
1558
|
+
outputString += input[index];
|
|
1494
1559
|
break;
|
|
1495
1560
|
}
|
|
1496
|
-
if (
|
|
1497
|
-
outputString +=
|
|
1561
|
+
if (input[index] === "-" && /^[a-zA-Z]+$/.test(input[index + 1])) {
|
|
1562
|
+
outputString += input[index + 1].toUpperCase();
|
|
1498
1563
|
skip = true;
|
|
1499
|
-
} else outputString +=
|
|
1564
|
+
} else outputString += input[index];
|
|
1500
1565
|
}
|
|
1501
1566
|
return outputString;
|
|
1502
1567
|
}
|
|
@@ -1518,4 +1583,4 @@ function truncate(stringToTruncate, maxLength = 5) {
|
|
|
1518
1583
|
}
|
|
1519
1584
|
|
|
1520
1585
|
//#endregion
|
|
1521
|
-
export { APIError, DataError, Env, FILE_PATH_REGEX, NAMESPACE_EXPORT_REGEX, VERSION_NUMBER_REGEX, VersionNumber, VersionType, addDaysToDate, appendSemicolon, camelToKebab, convertFileToBase64, createFormData, createTemplateStringsArray, deepCopy, deepFreeze, encryptWithKey, fillArray, formatDateAndTime, getRandomNumber, getRecordKeys, getStringsAndInterpolations, httpErrorCodeLookup, interpolate, interpolateObjects, isAnniversary, isLeapYear, isMonthlyMultiple, isOrdered, isSameDate, isTemplateStringsArray, kebabToCamel, normaliseIndents, normalizeIndents, omitProperties, paralleliseArrays, parseBoolean, parseEnv, parseFormData, parseIntStrict, parseVersionType, parseZodSchema, parseZodSchemaAsync, randomiseArray, range, removeDuplicates, removeUndefinedFromObject, sayHello, stringListToArray, stringifyDotenv, truncate, wait, zodVersionNumber };
|
|
1586
|
+
export { APIError, DataError, Env, FILE_PATH_REGEX, NAMESPACE_EXPORT_REGEX, ONE_DAY_IN_MILLISECONDS, VERSION_NUMBER_REGEX, VersionNumber, VersionType, addDaysToDate, appendSemicolon, camelToKebab, convertFileToBase64, createFormData, createTemplateStringsArray, deepCopy, deepFreeze, encryptWithKey, fillArray, formatDateAndTime, getRandomNumber, getRecordKeys, getStringsAndInterpolations, httpErrorCodeLookup, interpolate, interpolateObjects, isAnniversary, isLeapYear, isMonthlyMultiple, isOrdered, isSameDate, isTemplateStringsArray, kebabToCamel, normaliseIndents, normalizeIndents, omitProperties, paralleliseArrays, parseBoolean, parseEnv, parseFormData, parseIntStrict, parseVersionType, parseZodSchema, parseZodSchemaAsync, randomiseArray, range, removeDuplicates, removeUndefinedFromObject, sayHello, stringListToArray, stringifyDotenv, truncate, wait, zodVersionNumber };
|
package/dist/internal/index.cjs
CHANGED
|
@@ -118,6 +118,17 @@ var DataError = class DataError extends Error {
|
|
|
118
118
|
Object.defineProperty(this, "message", { enumerable: true });
|
|
119
119
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
120
120
|
}
|
|
121
|
+
static checkCaughtError(error, options) {
|
|
122
|
+
if (DataError.check(error)) {
|
|
123
|
+
if (options?.expectedCode && error.code !== options.expectedCode) throw new Error(normaliseIndents`The error code on the thrown error does not match the expected error code.
|
|
124
|
+
|
|
125
|
+
Expected: ${options.expectedCode}
|
|
126
|
+
Received: ${error.code}
|
|
127
|
+
`, { cause: error });
|
|
128
|
+
return error;
|
|
129
|
+
}
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
121
132
|
/**
|
|
122
133
|
* Checks whether the given input may have been caused by a DataError.
|
|
123
134
|
*
|
|
@@ -130,12 +141,54 @@ var DataError = class DataError extends Error {
|
|
|
130
141
|
const data = input;
|
|
131
142
|
return typeof data === "object" && data !== null && typeof data.message === "string" && typeof data.code === "string" && "data" in data;
|
|
132
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Gets the thrown `DataError` from a given function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
146
|
+
*
|
|
147
|
+
* @param errorFunction - The function expected to throw the error.
|
|
148
|
+
* @param options - Extra options to apply.
|
|
149
|
+
*
|
|
150
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
151
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
152
|
+
*
|
|
153
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
154
|
+
*/
|
|
155
|
+
static expectError(errorFunction, options) {
|
|
156
|
+
try {
|
|
157
|
+
errorFunction();
|
|
158
|
+
} catch (error) {
|
|
159
|
+
return DataError.checkCaughtError(error, options);
|
|
160
|
+
}
|
|
161
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Gets the thrown `DataError` from a given asynchronous function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
165
|
+
*
|
|
166
|
+
* @param errorFunction - The function expected to throw the error.
|
|
167
|
+
* @param options - Extra options to apply.
|
|
168
|
+
*
|
|
169
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
170
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
171
|
+
*
|
|
172
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
173
|
+
*/
|
|
174
|
+
static async expectErrorAsync(errorFunction, options) {
|
|
175
|
+
try {
|
|
176
|
+
await errorFunction();
|
|
177
|
+
} catch (error) {
|
|
178
|
+
return DataError.checkCaughtError(error, options);
|
|
179
|
+
}
|
|
180
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
181
|
+
}
|
|
133
182
|
};
|
|
134
183
|
|
|
135
184
|
//#endregion
|
|
136
185
|
//#region src/root/constants/FILE_PATH_REGEX.ts
|
|
137
186
|
const FILE_PATH_REGEX = String.raw`^(?<directory>.+)[\/\\](?<base>[^\/\\]+)$`;
|
|
138
187
|
|
|
188
|
+
//#endregion
|
|
189
|
+
//#region src/root/constants/ONE_DAY_IN_MILLISECONDS.ts
|
|
190
|
+
const ONE_DAY_IN_MILLISECONDS = 1440 * 60 * 1e3;
|
|
191
|
+
|
|
139
192
|
//#endregion
|
|
140
193
|
//#region src/root/constants/VERSION_NUMBER_REGEX.ts
|
|
141
194
|
const VERSION_NUMBER_REGEX = "^(?:v)?(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$";
|
|
@@ -9,6 +9,9 @@ import { ExecaMethod } from "execa";
|
|
|
9
9
|
type RecordKey = string | number | symbol;
|
|
10
10
|
//#endregion
|
|
11
11
|
//#region src/root/types/DataError.d.ts
|
|
12
|
+
interface ExpectErrorOptions {
|
|
13
|
+
expectedCode?: string;
|
|
14
|
+
}
|
|
12
15
|
/**
|
|
13
16
|
* Represents errors you may get that may've been caused by a specific piece of data.
|
|
14
17
|
*
|
|
@@ -26,6 +29,7 @@ declare class DataError<DataType extends Record<RecordKey, unknown> = Record<Rec
|
|
|
26
29
|
* @param options - Extra options to pass to super Error constructor.
|
|
27
30
|
*/
|
|
28
31
|
constructor(data: DataType, code?: string, message?: string, options?: ErrorOptions);
|
|
32
|
+
private static checkCaughtError;
|
|
29
33
|
/**
|
|
30
34
|
* Checks whether the given input may have been caused by a DataError.
|
|
31
35
|
*
|
|
@@ -34,6 +38,30 @@ declare class DataError<DataType extends Record<RecordKey, unknown> = Record<Rec
|
|
|
34
38
|
* @returns `true` if the input is a DataError, and `false` otherwise. The type of the input will also be narrowed down to DataError if `true`.
|
|
35
39
|
*/
|
|
36
40
|
static check<DataType extends Record<RecordKey, unknown> = Record<RecordKey, unknown>>(input: unknown): input is DataError<DataType>;
|
|
41
|
+
/**
|
|
42
|
+
* Gets the thrown `DataError` from a given function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
43
|
+
*
|
|
44
|
+
* @param errorFunction - The function expected to throw the error.
|
|
45
|
+
* @param options - Extra options to apply.
|
|
46
|
+
*
|
|
47
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
48
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
49
|
+
*
|
|
50
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
51
|
+
*/
|
|
52
|
+
static expectError(errorFunction: () => unknown, options?: ExpectErrorOptions): DataError;
|
|
53
|
+
/**
|
|
54
|
+
* Gets the thrown `DataError` from a given asynchronous function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
55
|
+
*
|
|
56
|
+
* @param errorFunction - The function expected to throw the error.
|
|
57
|
+
* @param options - Extra options to apply.
|
|
58
|
+
*
|
|
59
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
60
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
61
|
+
*
|
|
62
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
63
|
+
*/
|
|
64
|
+
static expectErrorAsync(errorFunction: () => Promise<unknown>, options?: ExpectErrorOptions): Promise<DataError>;
|
|
37
65
|
}
|
|
38
66
|
//#endregion
|
|
39
67
|
//#region src/root/types/CreateEnumType.d.ts
|
package/dist/internal/index.d.ts
CHANGED
|
@@ -10,6 +10,9 @@ import { ExecaMethod } from "execa";
|
|
|
10
10
|
type RecordKey = string | number | symbol;
|
|
11
11
|
//#endregion
|
|
12
12
|
//#region src/root/types/DataError.d.ts
|
|
13
|
+
interface ExpectErrorOptions {
|
|
14
|
+
expectedCode?: string;
|
|
15
|
+
}
|
|
13
16
|
/**
|
|
14
17
|
* Represents errors you may get that may've been caused by a specific piece of data.
|
|
15
18
|
*
|
|
@@ -27,6 +30,7 @@ declare class DataError<DataType extends Record<RecordKey, unknown> = Record<Rec
|
|
|
27
30
|
* @param options - Extra options to pass to super Error constructor.
|
|
28
31
|
*/
|
|
29
32
|
constructor(data: DataType, code?: string, message?: string, options?: ErrorOptions);
|
|
33
|
+
private static checkCaughtError;
|
|
30
34
|
/**
|
|
31
35
|
* Checks whether the given input may have been caused by a DataError.
|
|
32
36
|
*
|
|
@@ -35,6 +39,30 @@ declare class DataError<DataType extends Record<RecordKey, unknown> = Record<Rec
|
|
|
35
39
|
* @returns `true` if the input is a DataError, and `false` otherwise. The type of the input will also be narrowed down to DataError if `true`.
|
|
36
40
|
*/
|
|
37
41
|
static check<DataType extends Record<RecordKey, unknown> = Record<RecordKey, unknown>>(input: unknown): input is DataError<DataType>;
|
|
42
|
+
/**
|
|
43
|
+
* Gets the thrown `DataError` from a given function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
44
|
+
*
|
|
45
|
+
* @param errorFunction - The function expected to throw the error.
|
|
46
|
+
* @param options - Extra options to apply.
|
|
47
|
+
*
|
|
48
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
49
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
50
|
+
*
|
|
51
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
52
|
+
*/
|
|
53
|
+
static expectError(errorFunction: () => unknown, options?: ExpectErrorOptions): DataError;
|
|
54
|
+
/**
|
|
55
|
+
* Gets the thrown `DataError` from a given asynchronous function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
56
|
+
*
|
|
57
|
+
* @param errorFunction - The function expected to throw the error.
|
|
58
|
+
* @param options - Extra options to apply.
|
|
59
|
+
*
|
|
60
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
61
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
62
|
+
*
|
|
63
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
64
|
+
*/
|
|
65
|
+
static expectErrorAsync(errorFunction: () => Promise<unknown>, options?: ExpectErrorOptions): Promise<DataError>;
|
|
38
66
|
}
|
|
39
67
|
//#endregion
|
|
40
68
|
//#region src/root/types/CreateEnumType.d.ts
|
package/dist/internal/index.js
CHANGED
|
@@ -88,6 +88,17 @@ var DataError = class DataError extends Error {
|
|
|
88
88
|
Object.defineProperty(this, "message", { enumerable: true });
|
|
89
89
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
90
90
|
}
|
|
91
|
+
static checkCaughtError(error, options) {
|
|
92
|
+
if (DataError.check(error)) {
|
|
93
|
+
if (options?.expectedCode && error.code !== options.expectedCode) throw new Error(normaliseIndents`The error code on the thrown error does not match the expected error code.
|
|
94
|
+
|
|
95
|
+
Expected: ${options.expectedCode}
|
|
96
|
+
Received: ${error.code}
|
|
97
|
+
`, { cause: error });
|
|
98
|
+
return error;
|
|
99
|
+
}
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
91
102
|
/**
|
|
92
103
|
* Checks whether the given input may have been caused by a DataError.
|
|
93
104
|
*
|
|
@@ -100,12 +111,54 @@ var DataError = class DataError extends Error {
|
|
|
100
111
|
const data = input;
|
|
101
112
|
return typeof data === "object" && data !== null && typeof data.message === "string" && typeof data.code === "string" && "data" in data;
|
|
102
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Gets the thrown `DataError` from a given function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
116
|
+
*
|
|
117
|
+
* @param errorFunction - The function expected to throw the error.
|
|
118
|
+
* @param options - Extra options to apply.
|
|
119
|
+
*
|
|
120
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
121
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
122
|
+
*
|
|
123
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
124
|
+
*/
|
|
125
|
+
static expectError(errorFunction, options) {
|
|
126
|
+
try {
|
|
127
|
+
errorFunction();
|
|
128
|
+
} catch (error) {
|
|
129
|
+
return DataError.checkCaughtError(error, options);
|
|
130
|
+
}
|
|
131
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Gets the thrown `DataError` from a given asynchronous function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
135
|
+
*
|
|
136
|
+
* @param errorFunction - The function expected to throw the error.
|
|
137
|
+
* @param options - Extra options to apply.
|
|
138
|
+
*
|
|
139
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
140
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
141
|
+
*
|
|
142
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
143
|
+
*/
|
|
144
|
+
static async expectErrorAsync(errorFunction, options) {
|
|
145
|
+
try {
|
|
146
|
+
await errorFunction();
|
|
147
|
+
} catch (error) {
|
|
148
|
+
return DataError.checkCaughtError(error, options);
|
|
149
|
+
}
|
|
150
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
151
|
+
}
|
|
103
152
|
};
|
|
104
153
|
|
|
105
154
|
//#endregion
|
|
106
155
|
//#region src/root/constants/FILE_PATH_REGEX.ts
|
|
107
156
|
const FILE_PATH_REGEX = String.raw`^(?<directory>.+)[\/\\](?<base>[^\/\\]+)$`;
|
|
108
157
|
|
|
158
|
+
//#endregion
|
|
159
|
+
//#region src/root/constants/ONE_DAY_IN_MILLISECONDS.ts
|
|
160
|
+
const ONE_DAY_IN_MILLISECONDS = 1440 * 60 * 1e3;
|
|
161
|
+
|
|
109
162
|
//#endregion
|
|
110
163
|
//#region src/root/constants/VERSION_NUMBER_REGEX.ts
|
|
111
164
|
const VERSION_NUMBER_REGEX = "^(?:v)?(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$";
|
package/dist/node/index.cjs
CHANGED
|
@@ -73,49 +73,12 @@ const normaliseImportPath = normalizeImportPath;
|
|
|
73
73
|
const FILE_PATH_REGEX = String.raw`^(?<directory>.+)[\/\\](?<base>[^\/\\]+)$`;
|
|
74
74
|
|
|
75
75
|
//#endregion
|
|
76
|
-
//#region src/root/constants/
|
|
77
|
-
const
|
|
76
|
+
//#region src/root/constants/ONE_DAY_IN_MILLISECONDS.ts
|
|
77
|
+
const ONE_DAY_IN_MILLISECONDS = 1440 * 60 * 1e3;
|
|
78
78
|
|
|
79
79
|
//#endregion
|
|
80
|
-
//#region src/root/
|
|
81
|
-
|
|
82
|
-
* Represents errors you may get that may've been caused by a specific piece of data.
|
|
83
|
-
*
|
|
84
|
-
* @category Types
|
|
85
|
-
*
|
|
86
|
-
* @template DataType - The type of the data that caused the error.
|
|
87
|
-
*/
|
|
88
|
-
var DataError = class DataError extends Error {
|
|
89
|
-
code;
|
|
90
|
-
data;
|
|
91
|
-
/**
|
|
92
|
-
* @param data - The data that caused the error.
|
|
93
|
-
* @param code - A standardised code (e.g. UNEXPECTED_DATA).
|
|
94
|
-
* @param message - A human-readable error message (e.g. The data provided is invalid).
|
|
95
|
-
* @param options - Extra options to pass to super Error constructor.
|
|
96
|
-
*/
|
|
97
|
-
constructor(data, code = "INVALID_DATA", message = "The data provided is invalid", options) {
|
|
98
|
-
super(message, options);
|
|
99
|
-
if (Error.captureStackTrace) Error.captureStackTrace(this, new.target);
|
|
100
|
-
this.name = new.target.name;
|
|
101
|
-
this.code = code;
|
|
102
|
-
this.data = data;
|
|
103
|
-
Object.defineProperty(this, "message", { enumerable: true });
|
|
104
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Checks whether the given input may have been caused by a DataError.
|
|
108
|
-
*
|
|
109
|
-
* @param input - The input to check.
|
|
110
|
-
*
|
|
111
|
-
* @returns `true` if the input is a DataError, and `false` otherwise. The type of the input will also be narrowed down to DataError if `true`.
|
|
112
|
-
*/
|
|
113
|
-
static check(input) {
|
|
114
|
-
if (input instanceof DataError) return true;
|
|
115
|
-
const data = input;
|
|
116
|
-
return typeof data === "object" && data !== null && typeof data.message === "string" && typeof data.code === "string" && "data" in data;
|
|
117
|
-
}
|
|
118
|
-
};
|
|
80
|
+
//#region src/root/constants/VERSION_NUMBER_REGEX.ts
|
|
81
|
+
const VERSION_NUMBER_REGEX = "^(?:v)?(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$";
|
|
119
82
|
|
|
120
83
|
//#endregion
|
|
121
84
|
//#region src/root/functions/arrayHelpers/fillArray.ts
|
|
@@ -419,6 +382,96 @@ const VersionType = {
|
|
|
419
382
|
PATCH: "patch"
|
|
420
383
|
};
|
|
421
384
|
|
|
385
|
+
//#endregion
|
|
386
|
+
//#region src/root/types/DataError.ts
|
|
387
|
+
/**
|
|
388
|
+
* Represents errors you may get that may've been caused by a specific piece of data.
|
|
389
|
+
*
|
|
390
|
+
* @category Types
|
|
391
|
+
*
|
|
392
|
+
* @template DataType - The type of the data that caused the error.
|
|
393
|
+
*/
|
|
394
|
+
var DataError = class DataError extends Error {
|
|
395
|
+
code;
|
|
396
|
+
data;
|
|
397
|
+
/**
|
|
398
|
+
* @param data - The data that caused the error.
|
|
399
|
+
* @param code - A standardised code (e.g. UNEXPECTED_DATA).
|
|
400
|
+
* @param message - A human-readable error message (e.g. The data provided is invalid).
|
|
401
|
+
* @param options - Extra options to pass to super Error constructor.
|
|
402
|
+
*/
|
|
403
|
+
constructor(data, code = "INVALID_DATA", message = "The data provided is invalid", options) {
|
|
404
|
+
super(message, options);
|
|
405
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, new.target);
|
|
406
|
+
this.name = new.target.name;
|
|
407
|
+
this.code = code;
|
|
408
|
+
this.data = data;
|
|
409
|
+
Object.defineProperty(this, "message", { enumerable: true });
|
|
410
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
411
|
+
}
|
|
412
|
+
static checkCaughtError(error, options) {
|
|
413
|
+
if (DataError.check(error)) {
|
|
414
|
+
if (options?.expectedCode && error.code !== options.expectedCode) throw new Error(normaliseIndents`The error code on the thrown error does not match the expected error code.
|
|
415
|
+
|
|
416
|
+
Expected: ${options.expectedCode}
|
|
417
|
+
Received: ${error.code}
|
|
418
|
+
`, { cause: error });
|
|
419
|
+
return error;
|
|
420
|
+
}
|
|
421
|
+
throw error;
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Checks whether the given input may have been caused by a DataError.
|
|
425
|
+
*
|
|
426
|
+
* @param input - The input to check.
|
|
427
|
+
*
|
|
428
|
+
* @returns `true` if the input is a DataError, and `false` otherwise. The type of the input will also be narrowed down to DataError if `true`.
|
|
429
|
+
*/
|
|
430
|
+
static check(input) {
|
|
431
|
+
if (input instanceof DataError) return true;
|
|
432
|
+
const data = input;
|
|
433
|
+
return typeof data === "object" && data !== null && typeof data.message === "string" && typeof data.code === "string" && "data" in data;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Gets the thrown `DataError` from a given function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
437
|
+
*
|
|
438
|
+
* @param errorFunction - The function expected to throw the error.
|
|
439
|
+
* @param options - Extra options to apply.
|
|
440
|
+
*
|
|
441
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
442
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
443
|
+
*
|
|
444
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
445
|
+
*/
|
|
446
|
+
static expectError(errorFunction, options) {
|
|
447
|
+
try {
|
|
448
|
+
errorFunction();
|
|
449
|
+
} catch (error) {
|
|
450
|
+
return DataError.checkCaughtError(error, options);
|
|
451
|
+
}
|
|
452
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Gets the thrown `DataError` from a given asynchronous function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
456
|
+
*
|
|
457
|
+
* @param errorFunction - The function expected to throw the error.
|
|
458
|
+
* @param options - Extra options to apply.
|
|
459
|
+
*
|
|
460
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
461
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
462
|
+
*
|
|
463
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
464
|
+
*/
|
|
465
|
+
static async expectErrorAsync(errorFunction, options) {
|
|
466
|
+
try {
|
|
467
|
+
await errorFunction();
|
|
468
|
+
} catch (error) {
|
|
469
|
+
return DataError.checkCaughtError(error, options);
|
|
470
|
+
}
|
|
471
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
|
|
422
475
|
//#endregion
|
|
423
476
|
//#region src/root/types/VersionNumber.ts
|
|
424
477
|
/**
|
package/dist/node/index.js
CHANGED
|
@@ -43,49 +43,12 @@ const normaliseImportPath = normalizeImportPath;
|
|
|
43
43
|
const FILE_PATH_REGEX = String.raw`^(?<directory>.+)[\/\\](?<base>[^\/\\]+)$`;
|
|
44
44
|
|
|
45
45
|
//#endregion
|
|
46
|
-
//#region src/root/constants/
|
|
47
|
-
const
|
|
46
|
+
//#region src/root/constants/ONE_DAY_IN_MILLISECONDS.ts
|
|
47
|
+
const ONE_DAY_IN_MILLISECONDS = 1440 * 60 * 1e3;
|
|
48
48
|
|
|
49
49
|
//#endregion
|
|
50
|
-
//#region src/root/
|
|
51
|
-
|
|
52
|
-
* Represents errors you may get that may've been caused by a specific piece of data.
|
|
53
|
-
*
|
|
54
|
-
* @category Types
|
|
55
|
-
*
|
|
56
|
-
* @template DataType - The type of the data that caused the error.
|
|
57
|
-
*/
|
|
58
|
-
var DataError = class DataError extends Error {
|
|
59
|
-
code;
|
|
60
|
-
data;
|
|
61
|
-
/**
|
|
62
|
-
* @param data - The data that caused the error.
|
|
63
|
-
* @param code - A standardised code (e.g. UNEXPECTED_DATA).
|
|
64
|
-
* @param message - A human-readable error message (e.g. The data provided is invalid).
|
|
65
|
-
* @param options - Extra options to pass to super Error constructor.
|
|
66
|
-
*/
|
|
67
|
-
constructor(data, code = "INVALID_DATA", message = "The data provided is invalid", options) {
|
|
68
|
-
super(message, options);
|
|
69
|
-
if (Error.captureStackTrace) Error.captureStackTrace(this, new.target);
|
|
70
|
-
this.name = new.target.name;
|
|
71
|
-
this.code = code;
|
|
72
|
-
this.data = data;
|
|
73
|
-
Object.defineProperty(this, "message", { enumerable: true });
|
|
74
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Checks whether the given input may have been caused by a DataError.
|
|
78
|
-
*
|
|
79
|
-
* @param input - The input to check.
|
|
80
|
-
*
|
|
81
|
-
* @returns `true` if the input is a DataError, and `false` otherwise. The type of the input will also be narrowed down to DataError if `true`.
|
|
82
|
-
*/
|
|
83
|
-
static check(input) {
|
|
84
|
-
if (input instanceof DataError) return true;
|
|
85
|
-
const data = input;
|
|
86
|
-
return typeof data === "object" && data !== null && typeof data.message === "string" && typeof data.code === "string" && "data" in data;
|
|
87
|
-
}
|
|
88
|
-
};
|
|
50
|
+
//#region src/root/constants/VERSION_NUMBER_REGEX.ts
|
|
51
|
+
const VERSION_NUMBER_REGEX = "^(?:v)?(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$";
|
|
89
52
|
|
|
90
53
|
//#endregion
|
|
91
54
|
//#region src/root/functions/arrayHelpers/fillArray.ts
|
|
@@ -389,6 +352,96 @@ const VersionType = {
|
|
|
389
352
|
PATCH: "patch"
|
|
390
353
|
};
|
|
391
354
|
|
|
355
|
+
//#endregion
|
|
356
|
+
//#region src/root/types/DataError.ts
|
|
357
|
+
/**
|
|
358
|
+
* Represents errors you may get that may've been caused by a specific piece of data.
|
|
359
|
+
*
|
|
360
|
+
* @category Types
|
|
361
|
+
*
|
|
362
|
+
* @template DataType - The type of the data that caused the error.
|
|
363
|
+
*/
|
|
364
|
+
var DataError = class DataError extends Error {
|
|
365
|
+
code;
|
|
366
|
+
data;
|
|
367
|
+
/**
|
|
368
|
+
* @param data - The data that caused the error.
|
|
369
|
+
* @param code - A standardised code (e.g. UNEXPECTED_DATA).
|
|
370
|
+
* @param message - A human-readable error message (e.g. The data provided is invalid).
|
|
371
|
+
* @param options - Extra options to pass to super Error constructor.
|
|
372
|
+
*/
|
|
373
|
+
constructor(data, code = "INVALID_DATA", message = "The data provided is invalid", options) {
|
|
374
|
+
super(message, options);
|
|
375
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, new.target);
|
|
376
|
+
this.name = new.target.name;
|
|
377
|
+
this.code = code;
|
|
378
|
+
this.data = data;
|
|
379
|
+
Object.defineProperty(this, "message", { enumerable: true });
|
|
380
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
381
|
+
}
|
|
382
|
+
static checkCaughtError(error, options) {
|
|
383
|
+
if (DataError.check(error)) {
|
|
384
|
+
if (options?.expectedCode && error.code !== options.expectedCode) throw new Error(normaliseIndents`The error code on the thrown error does not match the expected error code.
|
|
385
|
+
|
|
386
|
+
Expected: ${options.expectedCode}
|
|
387
|
+
Received: ${error.code}
|
|
388
|
+
`, { cause: error });
|
|
389
|
+
return error;
|
|
390
|
+
}
|
|
391
|
+
throw error;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Checks whether the given input may have been caused by a DataError.
|
|
395
|
+
*
|
|
396
|
+
* @param input - The input to check.
|
|
397
|
+
*
|
|
398
|
+
* @returns `true` if the input is a DataError, and `false` otherwise. The type of the input will also be narrowed down to DataError if `true`.
|
|
399
|
+
*/
|
|
400
|
+
static check(input) {
|
|
401
|
+
if (input instanceof DataError) return true;
|
|
402
|
+
const data = input;
|
|
403
|
+
return typeof data === "object" && data !== null && typeof data.message === "string" && typeof data.code === "string" && "data" in data;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Gets the thrown `DataError` from a given function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
407
|
+
*
|
|
408
|
+
* @param errorFunction - The function expected to throw the error.
|
|
409
|
+
* @param options - Extra options to apply.
|
|
410
|
+
*
|
|
411
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
412
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
413
|
+
*
|
|
414
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
415
|
+
*/
|
|
416
|
+
static expectError(errorFunction, options) {
|
|
417
|
+
try {
|
|
418
|
+
errorFunction();
|
|
419
|
+
} catch (error) {
|
|
420
|
+
return DataError.checkCaughtError(error, options);
|
|
421
|
+
}
|
|
422
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Gets the thrown `DataError` from a given asynchronous function if one was thrown, and re-throws any other errors, or throws a default `DataError` if no error thrown.
|
|
426
|
+
*
|
|
427
|
+
* @param errorFunction - The function expected to throw the error.
|
|
428
|
+
* @param options - Extra options to apply.
|
|
429
|
+
*
|
|
430
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
431
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
432
|
+
*
|
|
433
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
434
|
+
*/
|
|
435
|
+
static async expectErrorAsync(errorFunction, options) {
|
|
436
|
+
try {
|
|
437
|
+
await errorFunction();
|
|
438
|
+
} catch (error) {
|
|
439
|
+
return DataError.checkCaughtError(error, options);
|
|
440
|
+
}
|
|
441
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
|
|
392
445
|
//#endregion
|
|
393
446
|
//#region src/root/types/VersionNumber.ts
|
|
394
447
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alextheman/utility",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.3.0",
|
|
4
4
|
"description": "Helpful utility functions.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"zod": "^4.3.6"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@alextheman/eslint-plugin": "^5.
|
|
39
|
+
"@alextheman/eslint-plugin": "^5.8.2",
|
|
40
40
|
"@types/node": "^25.3.0",
|
|
41
41
|
"alex-c-line": "^1.28.0",
|
|
42
42
|
"dotenv-cli": "^11.0.0",
|