@alextheman/utility 5.1.4 → 5.2.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 +84 -23
- package/dist/index.d.cts +34 -6
- package/dist/index.d.ts +34 -6
- package/dist/index.js +84 -23
- package/dist/internal/index.cjs +49 -0
- package/dist/internal/index.d.cts +28 -0
- package/dist/internal/index.d.ts +28 -0
- package/dist/internal/index.js +49 -0
- package/dist/node/index.cjs +90 -41
- package/dist/node/index.js +90 -41
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -164,6 +164,17 @@ var DataError = class DataError extends Error {
|
|
|
164
164
|
Object.defineProperty(this, "message", { enumerable: true });
|
|
165
165
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
166
166
|
}
|
|
167
|
+
static checkCaughtError(error, options) {
|
|
168
|
+
if (DataError.check(error)) {
|
|
169
|
+
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.
|
|
170
|
+
|
|
171
|
+
Expected: ${options.expectedCode}
|
|
172
|
+
Received: ${error.code}
|
|
173
|
+
`, { cause: error });
|
|
174
|
+
return error;
|
|
175
|
+
}
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
167
178
|
/**
|
|
168
179
|
* Checks whether the given input may have been caused by a DataError.
|
|
169
180
|
*
|
|
@@ -176,6 +187,44 @@ var DataError = class DataError extends Error {
|
|
|
176
187
|
const data = input;
|
|
177
188
|
return typeof data === "object" && data !== null && typeof data.message === "string" && typeof data.code === "string" && "data" in data;
|
|
178
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* 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.
|
|
192
|
+
*
|
|
193
|
+
* @param errorFunction - The function expected to throw the error.
|
|
194
|
+
* @param options - Extra options to apply.
|
|
195
|
+
*
|
|
196
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
197
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
198
|
+
*
|
|
199
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
200
|
+
*/
|
|
201
|
+
static expectError(errorFunction, options) {
|
|
202
|
+
try {
|
|
203
|
+
errorFunction();
|
|
204
|
+
} catch (error) {
|
|
205
|
+
return DataError.checkCaughtError(error, options);
|
|
206
|
+
}
|
|
207
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* 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.
|
|
211
|
+
*
|
|
212
|
+
* @param errorFunction - The function expected to throw the error.
|
|
213
|
+
* @param options - Extra options to apply.
|
|
214
|
+
*
|
|
215
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
216
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
217
|
+
*
|
|
218
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
219
|
+
*/
|
|
220
|
+
static async expectErrorAsync(errorFunction, options) {
|
|
221
|
+
try {
|
|
222
|
+
await errorFunction();
|
|
223
|
+
} catch (error) {
|
|
224
|
+
return DataError.checkCaughtError(error, options);
|
|
225
|
+
}
|
|
226
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
227
|
+
}
|
|
179
228
|
};
|
|
180
229
|
|
|
181
230
|
//#endregion
|
|
@@ -430,19 +479,27 @@ function randomiseArray(array) {
|
|
|
430
479
|
* @param stop - The number to stop at (exclusive).
|
|
431
480
|
* @param step - The step size between numbers, defaulting to 1.
|
|
432
481
|
*
|
|
433
|
-
* @throws {
|
|
434
|
-
* @throws {
|
|
482
|
+
* @throws {DataError} If `step` is `0`.
|
|
483
|
+
* @throws {DataError} If `step` direction does not match the order of `start` and `stop`.
|
|
435
484
|
*
|
|
436
485
|
* @returns An array of numbers satisfying the range provided.
|
|
437
486
|
*/
|
|
438
487
|
function range(start, stop, step = 1) {
|
|
439
488
|
const numbers = [];
|
|
440
|
-
if (step === 0) throw new
|
|
489
|
+
if (step === 0) throw new DataError({ step }, "ZERO_STEP_SIZE", "Step size cannot be zero.");
|
|
441
490
|
else if (step > 0) {
|
|
442
|
-
if (start > stop) throw new
|
|
491
|
+
if (start > stop) throw new DataError({
|
|
492
|
+
start,
|
|
493
|
+
stop,
|
|
494
|
+
step
|
|
495
|
+
}, "INVALID_BOUNDARIES", "The starting value cannot be bigger than the final value if step is positive");
|
|
443
496
|
for (let i = start; i < stop; i += step) numbers.push(i);
|
|
444
497
|
} else if (step < 0) {
|
|
445
|
-
if (start < stop) throw new
|
|
498
|
+
if (start < stop) throw new DataError({
|
|
499
|
+
start,
|
|
500
|
+
stop,
|
|
501
|
+
step
|
|
502
|
+
}, "INVALID_BOUNDARIES", "The final value cannot be bigger than the starting value if step is negative");
|
|
446
503
|
for (let i = start; i > stop; i += step) numbers.push(i);
|
|
447
504
|
}
|
|
448
505
|
return numbers;
|
|
@@ -622,7 +679,7 @@ function isMonthlyMultiple(firstDate, secondDate) {
|
|
|
622
679
|
*
|
|
623
680
|
* @param file - The file to convert.
|
|
624
681
|
*
|
|
625
|
-
* @throws {Error} If the file reader gives an error.
|
|
682
|
+
* @throws {Error | DataError} If the file reader gives an error.
|
|
626
683
|
*
|
|
627
684
|
* @returns A promise that resolves to the encoded base 64 string.
|
|
628
685
|
*/
|
|
@@ -632,7 +689,7 @@ function convertFileToBase64(file) {
|
|
|
632
689
|
reader.readAsDataURL(file);
|
|
633
690
|
reader.onload = () => {
|
|
634
691
|
if (reader.result === null) {
|
|
635
|
-
reject(
|
|
692
|
+
reject(new DataError({ result: reader.result }, "FILE_CONVERSION_ERROR", "Could not convert the given file."));
|
|
636
693
|
return;
|
|
637
694
|
}
|
|
638
695
|
resolve(reader.result);
|
|
@@ -648,6 +705,9 @@ function convertFileToBase64(file) {
|
|
|
648
705
|
function getNullableResolutionStrategy(key, strategy) {
|
|
649
706
|
return (typeof strategy === "object" ? strategy[key] : strategy) ?? "empty";
|
|
650
707
|
}
|
|
708
|
+
function isPrimitive(item) {
|
|
709
|
+
return typeof item === "string" || typeof item === "number" || typeof item === "boolean";
|
|
710
|
+
}
|
|
651
711
|
/**
|
|
652
712
|
* Creates FormData from a given object, resolving non-string types as appropriate.
|
|
653
713
|
*
|
|
@@ -674,7 +734,7 @@ function createFormData(data, options = {
|
|
|
674
734
|
formData.append(String(key), JSON.stringify(value));
|
|
675
735
|
break;
|
|
676
736
|
case "omit": break;
|
|
677
|
-
default: throw
|
|
737
|
+
default: throw resolutionStrategy;
|
|
678
738
|
}
|
|
679
739
|
}
|
|
680
740
|
function resolveNullables(key, value, options) {
|
|
@@ -697,10 +757,10 @@ function createFormData(data, options = {
|
|
|
697
757
|
if (Array.isArray(value)) {
|
|
698
758
|
if (value.some((item) => {
|
|
699
759
|
return item instanceof Blob;
|
|
700
|
-
}) && (options.arrayResolution === "stringify" || typeof options.arrayResolution === "object" && options.arrayResolution[key] === "stringify")) throw new
|
|
760
|
+
}) && (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
761
|
if (options.arrayResolution === "multiple" || typeof options.arrayResolution === "object" && options.arrayResolution[key] === "multiple") {
|
|
702
762
|
for (const item of value) {
|
|
703
|
-
if ((
|
|
763
|
+
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
764
|
if (item instanceof Blob) formData.append(String(key), item);
|
|
705
765
|
else formData.append(String(key), String(item));
|
|
706
766
|
}
|
|
@@ -1442,12 +1502,12 @@ async function encryptWithKey(publicKey, plaintextValue) {
|
|
|
1442
1502
|
*
|
|
1443
1503
|
* @param stringToAppendTo - The string to append a semicolon to.
|
|
1444
1504
|
*
|
|
1445
|
-
* @throws {
|
|
1505
|
+
* @throws {DataError} If the string contains multiple lines.
|
|
1446
1506
|
*
|
|
1447
1507
|
* @returns A string with the semicolon appended.
|
|
1448
1508
|
*/
|
|
1449
1509
|
function appendSemicolon(stringToAppendTo) {
|
|
1450
|
-
if (stringToAppendTo.includes("\n")) throw new
|
|
1510
|
+
if (stringToAppendTo.includes("\n")) throw new DataError({ stringToAppendTo }, "MULTIPLE_LINE_ERROR", "Cannot append semicolon to multi-line string.");
|
|
1451
1511
|
const stringWithNoTrailingWhitespace = stringToAppendTo.trimEnd();
|
|
1452
1512
|
if (stringWithNoTrailingWhitespace === "") return "";
|
|
1453
1513
|
return stringWithNoTrailingWhitespace[stringWithNoTrailingWhitespace.length - 1] === ";" ? stringWithNoTrailingWhitespace : `${stringWithNoTrailingWhitespace};`;
|
|
@@ -1499,34 +1559,35 @@ function camelToKebab(string, options = { preserveConsecutiveCapitals: true }) {
|
|
|
1499
1559
|
*
|
|
1500
1560
|
* @category String Helpers
|
|
1501
1561
|
*
|
|
1502
|
-
* @param
|
|
1562
|
+
* @param input - The string to convert.
|
|
1503
1563
|
* @param options - Options to apply to the conversion.
|
|
1504
1564
|
*
|
|
1505
1565
|
* @returns The string converted to camelCase.
|
|
1506
1566
|
*/
|
|
1507
|
-
function kebabToCamel(
|
|
1508
|
-
if (
|
|
1509
|
-
if (
|
|
1567
|
+
function kebabToCamel(input, options) {
|
|
1568
|
+
if (input !== input.toLowerCase()) throw new DataError({ input }, "UPPERCASE_INPUT", "Kebab-case must be purely lowercase.");
|
|
1569
|
+
if (input.startsWith("-") || input.endsWith("-")) throw new DataError({ input }, "TRAILING_DASHES", "Dashes at the start and/or end are not allowed.");
|
|
1570
|
+
if (input.includes("--")) throw new DataError({ input }, "CONSECUTIVE_DASHES", "Consecutive dashes are not allowed.");
|
|
1510
1571
|
let outputString = "";
|
|
1511
1572
|
let skip = false;
|
|
1512
|
-
for (const stringIndex in [...
|
|
1573
|
+
for (const stringIndex in [...input]) {
|
|
1513
1574
|
if (skip) {
|
|
1514
1575
|
skip = false;
|
|
1515
1576
|
continue;
|
|
1516
1577
|
}
|
|
1517
1578
|
const index = parseIntStrict(stringIndex);
|
|
1518
1579
|
if (index === 0 && options?.startWithUpper) {
|
|
1519
|
-
outputString +=
|
|
1580
|
+
outputString += input[index].toUpperCase();
|
|
1520
1581
|
continue;
|
|
1521
1582
|
}
|
|
1522
|
-
if (index ===
|
|
1523
|
-
outputString +=
|
|
1583
|
+
if (index === input.length - 1) {
|
|
1584
|
+
outputString += input[index];
|
|
1524
1585
|
break;
|
|
1525
1586
|
}
|
|
1526
|
-
if (
|
|
1527
|
-
outputString +=
|
|
1587
|
+
if (input[index] === "-" && /^[a-zA-Z]+$/.test(input[index + 1])) {
|
|
1588
|
+
outputString += input[index + 1].toUpperCase();
|
|
1528
1589
|
skip = true;
|
|
1529
|
-
} else outputString +=
|
|
1590
|
+
} else outputString += input[index];
|
|
1530
1591
|
}
|
|
1531
1592
|
return outputString;
|
|
1532
1593
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -87,8 +87,8 @@ declare function randomiseArray<ItemType>(array: ItemType[]): ItemType[];
|
|
|
87
87
|
* @param stop - The number to stop at (exclusive).
|
|
88
88
|
* @param step - The step size between numbers, defaulting to 1.
|
|
89
89
|
*
|
|
90
|
-
* @throws {
|
|
91
|
-
* @throws {
|
|
90
|
+
* @throws {DataError} If `step` is `0`.
|
|
91
|
+
* @throws {DataError} If `step` direction does not match the order of `start` and `stop`.
|
|
92
92
|
*
|
|
93
93
|
* @returns An array of numbers satisfying the range provided.
|
|
94
94
|
*/
|
|
@@ -198,7 +198,7 @@ declare function isSameDate(firstDate: Date, secondDate: Date): boolean;
|
|
|
198
198
|
*
|
|
199
199
|
* @param file - The file to convert.
|
|
200
200
|
*
|
|
201
|
-
* @throws {Error} If the file reader gives an error.
|
|
201
|
+
* @throws {Error | DataError} If the file reader gives an error.
|
|
202
202
|
*
|
|
203
203
|
* @returns A promise that resolves to the encoded base 64 string.
|
|
204
204
|
*/
|
|
@@ -239,6 +239,9 @@ declare class APIError extends Error {
|
|
|
239
239
|
type RecordKey = string | number | symbol;
|
|
240
240
|
//#endregion
|
|
241
241
|
//#region src/root/types/DataError.d.ts
|
|
242
|
+
interface ExpectErrorOptions {
|
|
243
|
+
expectedCode?: string;
|
|
244
|
+
}
|
|
242
245
|
/**
|
|
243
246
|
* Represents errors you may get that may've been caused by a specific piece of data.
|
|
244
247
|
*
|
|
@@ -256,6 +259,7 @@ declare class DataError<DataType extends Record<RecordKey, unknown> = Record<Rec
|
|
|
256
259
|
* @param options - Extra options to pass to super Error constructor.
|
|
257
260
|
*/
|
|
258
261
|
constructor(data: DataType, code?: string, message?: string, options?: ErrorOptions);
|
|
262
|
+
private static checkCaughtError;
|
|
259
263
|
/**
|
|
260
264
|
* Checks whether the given input may have been caused by a DataError.
|
|
261
265
|
*
|
|
@@ -264,6 +268,30 @@ declare class DataError<DataType extends Record<RecordKey, unknown> = Record<Rec
|
|
|
264
268
|
* @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
269
|
*/
|
|
266
270
|
static check<DataType extends Record<RecordKey, unknown> = Record<RecordKey, unknown>>(input: unknown): input is DataError<DataType>;
|
|
271
|
+
/**
|
|
272
|
+
* 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.
|
|
273
|
+
*
|
|
274
|
+
* @param errorFunction - The function expected to throw the error.
|
|
275
|
+
* @param options - Extra options to apply.
|
|
276
|
+
*
|
|
277
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
278
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
279
|
+
*
|
|
280
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
281
|
+
*/
|
|
282
|
+
static expectError(errorFunction: () => unknown, options?: ExpectErrorOptions): DataError;
|
|
283
|
+
/**
|
|
284
|
+
* 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.
|
|
285
|
+
*
|
|
286
|
+
* @param errorFunction - The function expected to throw the error.
|
|
287
|
+
* @param options - Extra options to apply.
|
|
288
|
+
*
|
|
289
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
290
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
291
|
+
*
|
|
292
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
293
|
+
*/
|
|
294
|
+
static expectErrorAsync(errorFunction: () => Promise<unknown>, options?: ExpectErrorOptions): Promise<DataError>;
|
|
267
295
|
}
|
|
268
296
|
//#endregion
|
|
269
297
|
//#region src/root/types/VersionNumber.d.ts
|
|
@@ -821,7 +849,7 @@ declare function encryptWithKey(publicKey: string, plaintextValue: string): Prom
|
|
|
821
849
|
*
|
|
822
850
|
* @param stringToAppendTo - The string to append a semicolon to.
|
|
823
851
|
*
|
|
824
|
-
* @throws {
|
|
852
|
+
* @throws {DataError} If the string contains multiple lines.
|
|
825
853
|
*
|
|
826
854
|
* @returns A string with the semicolon appended.
|
|
827
855
|
*/
|
|
@@ -864,12 +892,12 @@ interface KebabToCamelOptions {
|
|
|
864
892
|
*
|
|
865
893
|
* @category String Helpers
|
|
866
894
|
*
|
|
867
|
-
* @param
|
|
895
|
+
* @param input - The string to convert.
|
|
868
896
|
* @param options - Options to apply to the conversion.
|
|
869
897
|
*
|
|
870
898
|
* @returns The string converted to camelCase.
|
|
871
899
|
*/
|
|
872
|
-
declare function kebabToCamel(
|
|
900
|
+
declare function kebabToCamel(input: string, options?: KebabToCamelOptions): string;
|
|
873
901
|
//#endregion
|
|
874
902
|
//#region src/root/functions/stringHelpers/truncate.d.ts
|
|
875
903
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -87,8 +87,8 @@ declare function randomiseArray<ItemType>(array: ItemType[]): ItemType[];
|
|
|
87
87
|
* @param stop - The number to stop at (exclusive).
|
|
88
88
|
* @param step - The step size between numbers, defaulting to 1.
|
|
89
89
|
*
|
|
90
|
-
* @throws {
|
|
91
|
-
* @throws {
|
|
90
|
+
* @throws {DataError} If `step` is `0`.
|
|
91
|
+
* @throws {DataError} If `step` direction does not match the order of `start` and `stop`.
|
|
92
92
|
*
|
|
93
93
|
* @returns An array of numbers satisfying the range provided.
|
|
94
94
|
*/
|
|
@@ -198,7 +198,7 @@ declare function isSameDate(firstDate: Date, secondDate: Date): boolean;
|
|
|
198
198
|
*
|
|
199
199
|
* @param file - The file to convert.
|
|
200
200
|
*
|
|
201
|
-
* @throws {Error} If the file reader gives an error.
|
|
201
|
+
* @throws {Error | DataError} If the file reader gives an error.
|
|
202
202
|
*
|
|
203
203
|
* @returns A promise that resolves to the encoded base 64 string.
|
|
204
204
|
*/
|
|
@@ -239,6 +239,9 @@ declare class APIError extends Error {
|
|
|
239
239
|
type RecordKey = string | number | symbol;
|
|
240
240
|
//#endregion
|
|
241
241
|
//#region src/root/types/DataError.d.ts
|
|
242
|
+
interface ExpectErrorOptions {
|
|
243
|
+
expectedCode?: string;
|
|
244
|
+
}
|
|
242
245
|
/**
|
|
243
246
|
* Represents errors you may get that may've been caused by a specific piece of data.
|
|
244
247
|
*
|
|
@@ -256,6 +259,7 @@ declare class DataError<DataType extends Record<RecordKey, unknown> = Record<Rec
|
|
|
256
259
|
* @param options - Extra options to pass to super Error constructor.
|
|
257
260
|
*/
|
|
258
261
|
constructor(data: DataType, code?: string, message?: string, options?: ErrorOptions);
|
|
262
|
+
private static checkCaughtError;
|
|
259
263
|
/**
|
|
260
264
|
* Checks whether the given input may have been caused by a DataError.
|
|
261
265
|
*
|
|
@@ -264,6 +268,30 @@ declare class DataError<DataType extends Record<RecordKey, unknown> = Record<Rec
|
|
|
264
268
|
* @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
269
|
*/
|
|
266
270
|
static check<DataType extends Record<RecordKey, unknown> = Record<RecordKey, unknown>>(input: unknown): input is DataError<DataType>;
|
|
271
|
+
/**
|
|
272
|
+
* 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.
|
|
273
|
+
*
|
|
274
|
+
* @param errorFunction - The function expected to throw the error.
|
|
275
|
+
* @param options - Extra options to apply.
|
|
276
|
+
*
|
|
277
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
278
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
279
|
+
*
|
|
280
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
281
|
+
*/
|
|
282
|
+
static expectError(errorFunction: () => unknown, options?: ExpectErrorOptions): DataError;
|
|
283
|
+
/**
|
|
284
|
+
* 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.
|
|
285
|
+
*
|
|
286
|
+
* @param errorFunction - The function expected to throw the error.
|
|
287
|
+
* @param options - Extra options to apply.
|
|
288
|
+
*
|
|
289
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
290
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
291
|
+
*
|
|
292
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
293
|
+
*/
|
|
294
|
+
static expectErrorAsync(errorFunction: () => Promise<unknown>, options?: ExpectErrorOptions): Promise<DataError>;
|
|
267
295
|
}
|
|
268
296
|
//#endregion
|
|
269
297
|
//#region src/root/types/VersionNumber.d.ts
|
|
@@ -821,7 +849,7 @@ declare function encryptWithKey(publicKey: string, plaintextValue: string): Prom
|
|
|
821
849
|
*
|
|
822
850
|
* @param stringToAppendTo - The string to append a semicolon to.
|
|
823
851
|
*
|
|
824
|
-
* @throws {
|
|
852
|
+
* @throws {DataError} If the string contains multiple lines.
|
|
825
853
|
*
|
|
826
854
|
* @returns A string with the semicolon appended.
|
|
827
855
|
*/
|
|
@@ -864,12 +892,12 @@ interface KebabToCamelOptions {
|
|
|
864
892
|
*
|
|
865
893
|
* @category String Helpers
|
|
866
894
|
*
|
|
867
|
-
* @param
|
|
895
|
+
* @param input - The string to convert.
|
|
868
896
|
* @param options - Options to apply to the conversion.
|
|
869
897
|
*
|
|
870
898
|
* @returns The string converted to camelCase.
|
|
871
899
|
*/
|
|
872
|
-
declare function kebabToCamel(
|
|
900
|
+
declare function kebabToCamel(input: string, options?: KebabToCamelOptions): string;
|
|
873
901
|
//#endregion
|
|
874
902
|
//#region src/root/functions/stringHelpers/truncate.d.ts
|
|
875
903
|
/**
|
package/dist/index.js
CHANGED
|
@@ -134,6 +134,17 @@ var DataError = class DataError extends Error {
|
|
|
134
134
|
Object.defineProperty(this, "message", { enumerable: true });
|
|
135
135
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
136
136
|
}
|
|
137
|
+
static checkCaughtError(error, options) {
|
|
138
|
+
if (DataError.check(error)) {
|
|
139
|
+
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.
|
|
140
|
+
|
|
141
|
+
Expected: ${options.expectedCode}
|
|
142
|
+
Received: ${error.code}
|
|
143
|
+
`, { cause: error });
|
|
144
|
+
return error;
|
|
145
|
+
}
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
137
148
|
/**
|
|
138
149
|
* Checks whether the given input may have been caused by a DataError.
|
|
139
150
|
*
|
|
@@ -146,6 +157,44 @@ var DataError = class DataError extends Error {
|
|
|
146
157
|
const data = input;
|
|
147
158
|
return typeof data === "object" && data !== null && typeof data.message === "string" && typeof data.code === "string" && "data" in data;
|
|
148
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* 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.
|
|
162
|
+
*
|
|
163
|
+
* @param errorFunction - The function expected to throw the error.
|
|
164
|
+
* @param options - Extra options to apply.
|
|
165
|
+
*
|
|
166
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
167
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
168
|
+
*
|
|
169
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
170
|
+
*/
|
|
171
|
+
static expectError(errorFunction, options) {
|
|
172
|
+
try {
|
|
173
|
+
errorFunction();
|
|
174
|
+
} catch (error) {
|
|
175
|
+
return DataError.checkCaughtError(error, options);
|
|
176
|
+
}
|
|
177
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* 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.
|
|
181
|
+
*
|
|
182
|
+
* @param errorFunction - The function expected to throw the error.
|
|
183
|
+
* @param options - Extra options to apply.
|
|
184
|
+
*
|
|
185
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
186
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
187
|
+
*
|
|
188
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
189
|
+
*/
|
|
190
|
+
static async expectErrorAsync(errorFunction, options) {
|
|
191
|
+
try {
|
|
192
|
+
await errorFunction();
|
|
193
|
+
} catch (error) {
|
|
194
|
+
return DataError.checkCaughtError(error, options);
|
|
195
|
+
}
|
|
196
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
197
|
+
}
|
|
149
198
|
};
|
|
150
199
|
|
|
151
200
|
//#endregion
|
|
@@ -400,19 +449,27 @@ function randomiseArray(array) {
|
|
|
400
449
|
* @param stop - The number to stop at (exclusive).
|
|
401
450
|
* @param step - The step size between numbers, defaulting to 1.
|
|
402
451
|
*
|
|
403
|
-
* @throws {
|
|
404
|
-
* @throws {
|
|
452
|
+
* @throws {DataError} If `step` is `0`.
|
|
453
|
+
* @throws {DataError} If `step` direction does not match the order of `start` and `stop`.
|
|
405
454
|
*
|
|
406
455
|
* @returns An array of numbers satisfying the range provided.
|
|
407
456
|
*/
|
|
408
457
|
function range(start, stop, step = 1) {
|
|
409
458
|
const numbers = [];
|
|
410
|
-
if (step === 0) throw new
|
|
459
|
+
if (step === 0) throw new DataError({ step }, "ZERO_STEP_SIZE", "Step size cannot be zero.");
|
|
411
460
|
else if (step > 0) {
|
|
412
|
-
if (start > stop) throw new
|
|
461
|
+
if (start > stop) throw new DataError({
|
|
462
|
+
start,
|
|
463
|
+
stop,
|
|
464
|
+
step
|
|
465
|
+
}, "INVALID_BOUNDARIES", "The starting value cannot be bigger than the final value if step is positive");
|
|
413
466
|
for (let i = start; i < stop; i += step) numbers.push(i);
|
|
414
467
|
} else if (step < 0) {
|
|
415
|
-
if (start < stop) throw new
|
|
468
|
+
if (start < stop) throw new DataError({
|
|
469
|
+
start,
|
|
470
|
+
stop,
|
|
471
|
+
step
|
|
472
|
+
}, "INVALID_BOUNDARIES", "The final value cannot be bigger than the starting value if step is negative");
|
|
416
473
|
for (let i = start; i > stop; i += step) numbers.push(i);
|
|
417
474
|
}
|
|
418
475
|
return numbers;
|
|
@@ -592,7 +649,7 @@ function isMonthlyMultiple(firstDate, secondDate) {
|
|
|
592
649
|
*
|
|
593
650
|
* @param file - The file to convert.
|
|
594
651
|
*
|
|
595
|
-
* @throws {Error} If the file reader gives an error.
|
|
652
|
+
* @throws {Error | DataError} If the file reader gives an error.
|
|
596
653
|
*
|
|
597
654
|
* @returns A promise that resolves to the encoded base 64 string.
|
|
598
655
|
*/
|
|
@@ -602,7 +659,7 @@ function convertFileToBase64(file) {
|
|
|
602
659
|
reader.readAsDataURL(file);
|
|
603
660
|
reader.onload = () => {
|
|
604
661
|
if (reader.result === null) {
|
|
605
|
-
reject(
|
|
662
|
+
reject(new DataError({ result: reader.result }, "FILE_CONVERSION_ERROR", "Could not convert the given file."));
|
|
606
663
|
return;
|
|
607
664
|
}
|
|
608
665
|
resolve(reader.result);
|
|
@@ -618,6 +675,9 @@ function convertFileToBase64(file) {
|
|
|
618
675
|
function getNullableResolutionStrategy(key, strategy) {
|
|
619
676
|
return (typeof strategy === "object" ? strategy[key] : strategy) ?? "empty";
|
|
620
677
|
}
|
|
678
|
+
function isPrimitive(item) {
|
|
679
|
+
return typeof item === "string" || typeof item === "number" || typeof item === "boolean";
|
|
680
|
+
}
|
|
621
681
|
/**
|
|
622
682
|
* Creates FormData from a given object, resolving non-string types as appropriate.
|
|
623
683
|
*
|
|
@@ -644,7 +704,7 @@ function createFormData(data, options = {
|
|
|
644
704
|
formData.append(String(key), JSON.stringify(value));
|
|
645
705
|
break;
|
|
646
706
|
case "omit": break;
|
|
647
|
-
default: throw
|
|
707
|
+
default: throw resolutionStrategy;
|
|
648
708
|
}
|
|
649
709
|
}
|
|
650
710
|
function resolveNullables(key, value, options) {
|
|
@@ -667,10 +727,10 @@ function createFormData(data, options = {
|
|
|
667
727
|
if (Array.isArray(value)) {
|
|
668
728
|
if (value.some((item) => {
|
|
669
729
|
return item instanceof Blob;
|
|
670
|
-
}) && (options.arrayResolution === "stringify" || typeof options.arrayResolution === "object" && options.arrayResolution[key] === "stringify")) throw new
|
|
730
|
+
}) && (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
731
|
if (options.arrayResolution === "multiple" || typeof options.arrayResolution === "object" && options.arrayResolution[key] === "multiple") {
|
|
672
732
|
for (const item of value) {
|
|
673
|
-
if ((
|
|
733
|
+
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
734
|
if (item instanceof Blob) formData.append(String(key), item);
|
|
675
735
|
else formData.append(String(key), String(item));
|
|
676
736
|
}
|
|
@@ -1412,12 +1472,12 @@ async function encryptWithKey(publicKey, plaintextValue) {
|
|
|
1412
1472
|
*
|
|
1413
1473
|
* @param stringToAppendTo - The string to append a semicolon to.
|
|
1414
1474
|
*
|
|
1415
|
-
* @throws {
|
|
1475
|
+
* @throws {DataError} If the string contains multiple lines.
|
|
1416
1476
|
*
|
|
1417
1477
|
* @returns A string with the semicolon appended.
|
|
1418
1478
|
*/
|
|
1419
1479
|
function appendSemicolon(stringToAppendTo) {
|
|
1420
|
-
if (stringToAppendTo.includes("\n")) throw new
|
|
1480
|
+
if (stringToAppendTo.includes("\n")) throw new DataError({ stringToAppendTo }, "MULTIPLE_LINE_ERROR", "Cannot append semicolon to multi-line string.");
|
|
1421
1481
|
const stringWithNoTrailingWhitespace = stringToAppendTo.trimEnd();
|
|
1422
1482
|
if (stringWithNoTrailingWhitespace === "") return "";
|
|
1423
1483
|
return stringWithNoTrailingWhitespace[stringWithNoTrailingWhitespace.length - 1] === ";" ? stringWithNoTrailingWhitespace : `${stringWithNoTrailingWhitespace};`;
|
|
@@ -1469,34 +1529,35 @@ function camelToKebab(string, options = { preserveConsecutiveCapitals: true }) {
|
|
|
1469
1529
|
*
|
|
1470
1530
|
* @category String Helpers
|
|
1471
1531
|
*
|
|
1472
|
-
* @param
|
|
1532
|
+
* @param input - The string to convert.
|
|
1473
1533
|
* @param options - Options to apply to the conversion.
|
|
1474
1534
|
*
|
|
1475
1535
|
* @returns The string converted to camelCase.
|
|
1476
1536
|
*/
|
|
1477
|
-
function kebabToCamel(
|
|
1478
|
-
if (
|
|
1479
|
-
if (
|
|
1537
|
+
function kebabToCamel(input, options) {
|
|
1538
|
+
if (input !== input.toLowerCase()) throw new DataError({ input }, "UPPERCASE_INPUT", "Kebab-case must be purely lowercase.");
|
|
1539
|
+
if (input.startsWith("-") || input.endsWith("-")) throw new DataError({ input }, "TRAILING_DASHES", "Dashes at the start and/or end are not allowed.");
|
|
1540
|
+
if (input.includes("--")) throw new DataError({ input }, "CONSECUTIVE_DASHES", "Consecutive dashes are not allowed.");
|
|
1480
1541
|
let outputString = "";
|
|
1481
1542
|
let skip = false;
|
|
1482
|
-
for (const stringIndex in [...
|
|
1543
|
+
for (const stringIndex in [...input]) {
|
|
1483
1544
|
if (skip) {
|
|
1484
1545
|
skip = false;
|
|
1485
1546
|
continue;
|
|
1486
1547
|
}
|
|
1487
1548
|
const index = parseIntStrict(stringIndex);
|
|
1488
1549
|
if (index === 0 && options?.startWithUpper) {
|
|
1489
|
-
outputString +=
|
|
1550
|
+
outputString += input[index].toUpperCase();
|
|
1490
1551
|
continue;
|
|
1491
1552
|
}
|
|
1492
|
-
if (index ===
|
|
1493
|
-
outputString +=
|
|
1553
|
+
if (index === input.length - 1) {
|
|
1554
|
+
outputString += input[index];
|
|
1494
1555
|
break;
|
|
1495
1556
|
}
|
|
1496
|
-
if (
|
|
1497
|
-
outputString +=
|
|
1557
|
+
if (input[index] === "-" && /^[a-zA-Z]+$/.test(input[index + 1])) {
|
|
1558
|
+
outputString += input[index + 1].toUpperCase();
|
|
1498
1559
|
skip = true;
|
|
1499
|
-
} else outputString +=
|
|
1560
|
+
} else outputString += input[index];
|
|
1500
1561
|
}
|
|
1501
1562
|
return outputString;
|
|
1502
1563
|
}
|
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,6 +141,44 @@ 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
|
|
@@ -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,6 +111,44 @@ 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
|
package/dist/node/index.cjs
CHANGED
|
@@ -76,47 +76,6 @@ const FILE_PATH_REGEX = String.raw`^(?<directory>.+)[\/\\](?<base>[^\/\\]+)$`;
|
|
|
76
76
|
//#region src/root/constants/VERSION_NUMBER_REGEX.ts
|
|
77
77
|
const VERSION_NUMBER_REGEX = "^(?:v)?(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$";
|
|
78
78
|
|
|
79
|
-
//#endregion
|
|
80
|
-
//#region src/root/types/DataError.ts
|
|
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
|
-
};
|
|
119
|
-
|
|
120
79
|
//#endregion
|
|
121
80
|
//#region src/root/functions/arrayHelpers/fillArray.ts
|
|
122
81
|
/**
|
|
@@ -419,6 +378,96 @@ const VersionType = {
|
|
|
419
378
|
PATCH: "patch"
|
|
420
379
|
};
|
|
421
380
|
|
|
381
|
+
//#endregion
|
|
382
|
+
//#region src/root/types/DataError.ts
|
|
383
|
+
/**
|
|
384
|
+
* Represents errors you may get that may've been caused by a specific piece of data.
|
|
385
|
+
*
|
|
386
|
+
* @category Types
|
|
387
|
+
*
|
|
388
|
+
* @template DataType - The type of the data that caused the error.
|
|
389
|
+
*/
|
|
390
|
+
var DataError = class DataError extends Error {
|
|
391
|
+
code;
|
|
392
|
+
data;
|
|
393
|
+
/**
|
|
394
|
+
* @param data - The data that caused the error.
|
|
395
|
+
* @param code - A standardised code (e.g. UNEXPECTED_DATA).
|
|
396
|
+
* @param message - A human-readable error message (e.g. The data provided is invalid).
|
|
397
|
+
* @param options - Extra options to pass to super Error constructor.
|
|
398
|
+
*/
|
|
399
|
+
constructor(data, code = "INVALID_DATA", message = "The data provided is invalid", options) {
|
|
400
|
+
super(message, options);
|
|
401
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, new.target);
|
|
402
|
+
this.name = new.target.name;
|
|
403
|
+
this.code = code;
|
|
404
|
+
this.data = data;
|
|
405
|
+
Object.defineProperty(this, "message", { enumerable: true });
|
|
406
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
407
|
+
}
|
|
408
|
+
static checkCaughtError(error, options) {
|
|
409
|
+
if (DataError.check(error)) {
|
|
410
|
+
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.
|
|
411
|
+
|
|
412
|
+
Expected: ${options.expectedCode}
|
|
413
|
+
Received: ${error.code}
|
|
414
|
+
`, { cause: error });
|
|
415
|
+
return error;
|
|
416
|
+
}
|
|
417
|
+
throw error;
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Checks whether the given input may have been caused by a DataError.
|
|
421
|
+
*
|
|
422
|
+
* @param input - The input to check.
|
|
423
|
+
*
|
|
424
|
+
* @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`.
|
|
425
|
+
*/
|
|
426
|
+
static check(input) {
|
|
427
|
+
if (input instanceof DataError) return true;
|
|
428
|
+
const data = input;
|
|
429
|
+
return typeof data === "object" && data !== null && typeof data.message === "string" && typeof data.code === "string" && "data" in data;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* 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.
|
|
433
|
+
*
|
|
434
|
+
* @param errorFunction - The function expected to throw the error.
|
|
435
|
+
* @param options - Extra options to apply.
|
|
436
|
+
*
|
|
437
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
438
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
439
|
+
*
|
|
440
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
441
|
+
*/
|
|
442
|
+
static expectError(errorFunction, options) {
|
|
443
|
+
try {
|
|
444
|
+
errorFunction();
|
|
445
|
+
} catch (error) {
|
|
446
|
+
return DataError.checkCaughtError(error, options);
|
|
447
|
+
}
|
|
448
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* 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.
|
|
452
|
+
*
|
|
453
|
+
* @param errorFunction - The function expected to throw the error.
|
|
454
|
+
* @param options - Extra options to apply.
|
|
455
|
+
*
|
|
456
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
457
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
458
|
+
*
|
|
459
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
460
|
+
*/
|
|
461
|
+
static async expectErrorAsync(errorFunction, options) {
|
|
462
|
+
try {
|
|
463
|
+
await errorFunction();
|
|
464
|
+
} catch (error) {
|
|
465
|
+
return DataError.checkCaughtError(error, options);
|
|
466
|
+
}
|
|
467
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
|
|
422
471
|
//#endregion
|
|
423
472
|
//#region src/root/types/VersionNumber.ts
|
|
424
473
|
/**
|
package/dist/node/index.js
CHANGED
|
@@ -46,47 +46,6 @@ const FILE_PATH_REGEX = String.raw`^(?<directory>.+)[\/\\](?<base>[^\/\\]+)$`;
|
|
|
46
46
|
//#region src/root/constants/VERSION_NUMBER_REGEX.ts
|
|
47
47
|
const VERSION_NUMBER_REGEX = "^(?:v)?(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$";
|
|
48
48
|
|
|
49
|
-
//#endregion
|
|
50
|
-
//#region src/root/types/DataError.ts
|
|
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
|
-
};
|
|
89
|
-
|
|
90
49
|
//#endregion
|
|
91
50
|
//#region src/root/functions/arrayHelpers/fillArray.ts
|
|
92
51
|
/**
|
|
@@ -389,6 +348,96 @@ const VersionType = {
|
|
|
389
348
|
PATCH: "patch"
|
|
390
349
|
};
|
|
391
350
|
|
|
351
|
+
//#endregion
|
|
352
|
+
//#region src/root/types/DataError.ts
|
|
353
|
+
/**
|
|
354
|
+
* Represents errors you may get that may've been caused by a specific piece of data.
|
|
355
|
+
*
|
|
356
|
+
* @category Types
|
|
357
|
+
*
|
|
358
|
+
* @template DataType - The type of the data that caused the error.
|
|
359
|
+
*/
|
|
360
|
+
var DataError = class DataError extends Error {
|
|
361
|
+
code;
|
|
362
|
+
data;
|
|
363
|
+
/**
|
|
364
|
+
* @param data - The data that caused the error.
|
|
365
|
+
* @param code - A standardised code (e.g. UNEXPECTED_DATA).
|
|
366
|
+
* @param message - A human-readable error message (e.g. The data provided is invalid).
|
|
367
|
+
* @param options - Extra options to pass to super Error constructor.
|
|
368
|
+
*/
|
|
369
|
+
constructor(data, code = "INVALID_DATA", message = "The data provided is invalid", options) {
|
|
370
|
+
super(message, options);
|
|
371
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, new.target);
|
|
372
|
+
this.name = new.target.name;
|
|
373
|
+
this.code = code;
|
|
374
|
+
this.data = data;
|
|
375
|
+
Object.defineProperty(this, "message", { enumerable: true });
|
|
376
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
377
|
+
}
|
|
378
|
+
static checkCaughtError(error, options) {
|
|
379
|
+
if (DataError.check(error)) {
|
|
380
|
+
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.
|
|
381
|
+
|
|
382
|
+
Expected: ${options.expectedCode}
|
|
383
|
+
Received: ${error.code}
|
|
384
|
+
`, { cause: error });
|
|
385
|
+
return error;
|
|
386
|
+
}
|
|
387
|
+
throw error;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Checks whether the given input may have been caused by a DataError.
|
|
391
|
+
*
|
|
392
|
+
* @param input - The input to check.
|
|
393
|
+
*
|
|
394
|
+
* @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`.
|
|
395
|
+
*/
|
|
396
|
+
static check(input) {
|
|
397
|
+
if (input instanceof DataError) return true;
|
|
398
|
+
const data = input;
|
|
399
|
+
return typeof data === "object" && data !== null && typeof data.message === "string" && typeof data.code === "string" && "data" in data;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* 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.
|
|
403
|
+
*
|
|
404
|
+
* @param errorFunction - The function expected to throw the error.
|
|
405
|
+
* @param options - Extra options to apply.
|
|
406
|
+
*
|
|
407
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
408
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
409
|
+
*
|
|
410
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
411
|
+
*/
|
|
412
|
+
static expectError(errorFunction, options) {
|
|
413
|
+
try {
|
|
414
|
+
errorFunction();
|
|
415
|
+
} catch (error) {
|
|
416
|
+
return DataError.checkCaughtError(error, options);
|
|
417
|
+
}
|
|
418
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* 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.
|
|
422
|
+
*
|
|
423
|
+
* @param errorFunction - The function expected to throw the error.
|
|
424
|
+
* @param options - Extra options to apply.
|
|
425
|
+
*
|
|
426
|
+
* @throws {Error} Any other errors thrown by the `errorFunction` that are not a `DataError`.
|
|
427
|
+
* @throws {Error} If no `DataError` was thrown by the `errorFunction`
|
|
428
|
+
*
|
|
429
|
+
* @returns The `DataError` that was thrown by the `errorFunction`
|
|
430
|
+
*/
|
|
431
|
+
static async expectErrorAsync(errorFunction, options) {
|
|
432
|
+
try {
|
|
433
|
+
await errorFunction();
|
|
434
|
+
} catch (error) {
|
|
435
|
+
return DataError.checkCaughtError(error, options);
|
|
436
|
+
}
|
|
437
|
+
throw new Error("Expected a DataError to be thrown but none was thrown");
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
|
|
392
441
|
//#endregion
|
|
393
442
|
//#region src/root/types/VersionNumber.ts
|
|
394
443
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alextheman/utility",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.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",
|