@alextheman/utility 5.19.2 → 5.21.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.js CHANGED
@@ -91,7 +91,7 @@ var CodeError = class CodeError extends Error {
91
91
  */
92
92
  static check(input) {
93
93
  if (input instanceof CodeError) return true;
94
- return typeof input === "object" && input !== null && "message" in input && typeof input.message === "string" && "code" in input && typeof input.code === "string";
94
+ return containsKeys(input, ["message", "code"]) && typeof input.message === "string" && typeof input.code === "string";
95
95
  }
96
96
  static checkCaughtError(error, options) {
97
97
  if (this.check(error)) {
@@ -204,7 +204,11 @@ var DataError$1 = class DataError$1 extends CodeError {
204
204
  */
205
205
  static check(input) {
206
206
  if (input instanceof DataError$1) return true;
207
- return typeof input === "object" && input !== null && "message" in input && typeof input.message === "string" && "code" in input && typeof input.code === "string" && "data" in input && typeof input.data === "object" && input.data !== null;
207
+ return containsKeys(input, [
208
+ "data",
209
+ "code",
210
+ "message"
211
+ ]) && typeof input.message === "string" && typeof input.code === "string" && isNonNullableObject(input.data);
208
212
  }
209
213
  /**
210
214
  * Check a `DataError` against its error code
@@ -301,6 +305,107 @@ function range(start, stop, step = 1) {
301
305
  return numbers;
302
306
  }
303
307
  //#endregion
308
+ //#region src/root/functions/typeAssertions/assertNotNull.ts
309
+ /**
310
+ * Asserts that a given input is not `null`, and throws a DataError if it does.
311
+ *
312
+ * If no error is thrown from this, the input type gets narrowed down to not include `null`.
313
+ *
314
+ * @category Type Assertions
315
+ *
316
+ * @template InputType The type of the input.
317
+ *
318
+ * @param input - The input to assert against
319
+ *
320
+ * @throws {DataError} If the input is `null`.
321
+ */
322
+ function assertNotNull(input) {
323
+ if (input === null) throw new DataError$1({ input }, "NULL_INPUT", "Expected the input not to be null");
324
+ }
325
+ //#endregion
326
+ //#region src/root/functions/typeAssertions/assertNotNullable.ts
327
+ /**
328
+ * Asserts that a given input is not `undefined` or `null`, and throws a DataError if it does.
329
+ *
330
+ * If no error is thrown from this, the input type gets narrowed down to not include `undefined` or `null`.
331
+ *
332
+ * @category Type Assertions
333
+ *
334
+ * @template InputType The type of the input.
335
+ *
336
+ * @param input - The input to assert against.
337
+ *
338
+ * @throws {DataError} If the input is `undefined` or `null`.
339
+ */
340
+ function assertNotNullable(input) {
341
+ if (input === null || input === void 0) throw new DataError$1({ input }, "NULLABLE_INPUT", "Expected the input not to be undefined or null");
342
+ }
343
+ //#endregion
344
+ //#region src/root/functions/typeAssertions/assertNotUndefined.ts
345
+ /**
346
+ * Asserts that a given input is not `undefined`, and throws a DataError if it does.
347
+ *
348
+ * If no error is thrown from this, the input type gets narrowed down to not include `undefined`.
349
+ *
350
+ * @category Type Assertions
351
+ *
352
+ * @template InputType The type of the input.
353
+ *
354
+ * @param input - The input to assert against.
355
+ *
356
+ * @throws {DataError} If the input is `undefined`.
357
+ */
358
+ function assertNotUndefined(input) {
359
+ if (input === void 0) throw new DataError$1({ input }, "UNDEFINED_INPUT", "Expected the input not to be undefined");
360
+ }
361
+ //#endregion
362
+ //#region src/root/functions/typeAssertions/isNonNullableObject.ts
363
+ /**
364
+ * Determines if the given input is a non-nullable object, narrowing the type down as such if it is
365
+ *
366
+ * @category Type Assertions
367
+ *
368
+ * @param input - The input to check
369
+ *
370
+ * @returns `true` if the input is a non-nullable object, and `false` otherwise. The input type will also be narrowed down to be a non-nullable object.
371
+ */
372
+ function isNonNullableObject(input) {
373
+ return typeof input === "object" && input !== null;
374
+ }
375
+ //#endregion
376
+ //#region src/root/functions/typeAssertions/objectContainsKeys.ts
377
+ /**
378
+ * Determines if the given object contains all of the keys provided.
379
+ *
380
+ * @category Type Assertions
381
+ *
382
+ * @param input - The input object to check.
383
+ * @param keys - The keys expected to be in the input object.
384
+ *
385
+ * @returns `true` if the input object contains all provided keys, and `false` otherwise. The input type will also be narrowed down to be a record with the provided keys with an unknown value type.
386
+ */
387
+ function objectContainsKeys(input, keys) {
388
+ const expectedKeys = Array.isArray(keys) ? keys : [keys];
389
+ if (expectedKeys.length === 0) return false;
390
+ for (const key of expectedKeys) if (!(key in input)) return false;
391
+ return true;
392
+ }
393
+ //#endregion
394
+ //#region src/root/functions/typeAssertions/containsKeys.ts
395
+ /**
396
+ * Determines if the given input is a non-nullable object, and if that object contains all of the keys provided.
397
+ *
398
+ * @category Type Assertions
399
+ *
400
+ * @param input - The input to check.
401
+ * @param keys - The keys expected to be in the input if it's an object.
402
+ *
403
+ * @returns `true` if the input is an object containing all provided keys, and `false` otherwise. The input type will also be narrowed down to be a record with the provided keys, each with an unknown value type.
404
+ */
405
+ function containsKeys(input, keys) {
406
+ return isNonNullableObject(input) && objectContainsKeys(input, keys);
407
+ }
408
+ //#endregion
304
409
  //#region src/root/functions/arrayHelpers/fillArray.ts
305
410
  /**
306
411
  * Creates a new array where each element is the result of the provided callback.
@@ -328,7 +433,7 @@ function fillArray(callback, length = 1, options) {
328
433
  return callback(index);
329
434
  });
330
435
  if (outputArray.some((item) => {
331
- return item instanceof Promise || typeof item === "object" && item !== null && "then" in item && typeof item.then === "function";
436
+ return item instanceof Promise || containsKeys(item, "then") && typeof item.then === "function";
332
437
  })) return Promise.all(outputArray);
333
438
  return outputArray;
334
439
  }
@@ -629,7 +734,7 @@ function convertFileToBase64(file) {
629
734
  //#endregion
630
735
  //#region src/root/functions/miscellaneous/createFormData.ts
631
736
  function getNullableResolutionStrategy(key, strategy) {
632
- return (typeof strategy === "object" ? strategy[key] : strategy) ?? "empty";
737
+ return (isNonNullableObject(strategy) ? strategy[key] : strategy) ?? "empty";
633
738
  }
634
739
  function isPrimitive(item) {
635
740
  return typeof item === "string" || typeof item === "number" || typeof item === "boolean";
@@ -698,6 +803,20 @@ function createFormData(data, options = {
698
803
  return formData;
699
804
  }
700
805
  //#endregion
806
+ //#region src/root/functions/miscellaneous/identity.ts
807
+ /**
808
+ * Gives back the original input.
809
+ *
810
+ * @template InputType - The input type.
811
+ *
812
+ * @param input - The input value.
813
+ *
814
+ * @returns The original input value.
815
+ */
816
+ function identity(input) {
817
+ return input;
818
+ }
819
+ //#endregion
701
820
  //#region src/root/functions/miscellaneous/isOrdered.ts
702
821
  /**
703
822
  * Checks to see if the given array is sorted in ascending order.
@@ -828,6 +947,33 @@ I'll commit to you!
828
947
  `;
829
948
  }
830
949
  //#endregion
950
+ //#region src/root/functions/miscellaneous/sortBy.ts
951
+ /**
952
+ * Provides a function to pass to the `sort` or `toSorted` methods on arrays, which will allow those methods to sort the items by the chosen value in the chosen direction.
953
+ *
954
+ * @template ItemType - The type of each array item.
955
+ * @template SortValue - The type of the value to sort by.
956
+ *
957
+ * @param selector - A function that takes the item and returns the value to sort by.
958
+ * @param direction - The sort direction.
959
+ *
960
+ * @returns A function to pass into the `.sort()` or `.toSorted()` methods on arrays.
961
+ */
962
+ function sortBy(selector, direction = "asc") {
963
+ return (first, second) => {
964
+ const firstValue = selector(first);
965
+ const secondValue = selector(second);
966
+ if (firstValue instanceof Date && secondValue instanceof Date) {
967
+ const firstTime = firstValue.getTime();
968
+ const secondTime = secondValue.getTime();
969
+ return direction === "asc" ? firstTime - secondTime : secondTime - firstTime;
970
+ }
971
+ if (firstValue < secondValue) return direction === "asc" ? -1 : 1;
972
+ if (firstValue > secondValue) return direction === "asc" ? 1 : -1;
973
+ return 0;
974
+ };
975
+ }
976
+ //#endregion
831
977
  //#region src/root/functions/miscellaneous/stringifyDotenv.ts
832
978
  /**
833
979
  * Converts an object into a string in .env file format.
@@ -972,6 +1118,12 @@ function parseBoolean(inputString) {
972
1118
  return normalisedString === "true";
973
1119
  }
974
1120
  //#endregion
1121
+ //#region src/root/types/SortDirection.ts
1122
+ const SortDirection = {
1123
+ DESC: "desc",
1124
+ ASC: "asc"
1125
+ };
1126
+ //#endregion
975
1127
  //#region src/root/types/VersionNumber.ts
976
1128
  /**
977
1129
  * Represents a software version number, considered to be made up of a major, minor, and patch part.
@@ -1330,7 +1482,7 @@ function parseVersionType(input) {
1330
1482
  //#endregion
1331
1483
  //#region src/root/functions/recursive/deepCopy.ts
1332
1484
  function callDeepCopy(input) {
1333
- return typeof input === "object" && input !== null ? deepCopy(input) : input;
1485
+ return isNonNullableObject(input) ? deepCopy(input) : input;
1334
1486
  }
1335
1487
  /**
1336
1488
  * Deeply copies an object or array such that all child objects/arrays are also copied.
@@ -1649,7 +1801,7 @@ function interpolateObjects(strings, ...interpolations) {
1649
1801
  * @returns `true` if the input is a valid `TemplateStringsArray`, and false otherwise. The type of the input will also be narrowed down to `TemplateStringsArray` if `true`.
1650
1802
  */
1651
1803
  function isTemplateStringsArray(input) {
1652
- return typeof input === "object" && input !== null && "raw" in input;
1804
+ return containsKeys(input, "raw");
1653
1805
  }
1654
1806
  //#endregion
1655
1807
  //#region src/root/functions/taggedTemplate/normaliseIndents.ts
@@ -1704,7 +1856,7 @@ function reduceLines(lines, { preserveTabs = true }) {
1704
1856
  * @returns An additional function to invoke, or a new string with the strings and interpolations from the template applied, and extraneous indents removed.
1705
1857
  */
1706
1858
  function normaliseIndents(first, ...args) {
1707
- if (typeof first === "object" && first !== null && !Array.isArray(first)) {
1859
+ if (isNonNullableObject(first) && !Array.isArray(first)) {
1708
1860
  const options = first;
1709
1861
  return (strings, ...interpolations) => {
1710
1862
  return normaliseIndents(strings, ...interpolations, options);
@@ -1831,52 +1983,4 @@ var DataError = class DataError extends Error {
1831
1983
  }
1832
1984
  };
1833
1985
  //#endregion
1834
- //#region src/root/errors/assertNotNull.ts
1835
- /**
1836
- * Asserts that a given input is not `null`, and throws a DataError if it does.
1837
- *
1838
- * If no error is thrown from this, the input type gets narrowed down to not include `null`.
1839
- *
1840
- * @template InputType The type of the input.
1841
- *
1842
- * @param input - The input to assert against
1843
- *
1844
- * @throws {DataError} If the input is `null`.
1845
- */
1846
- function assertNotNull(input) {
1847
- if (input === null) throw new DataError$1({ input }, "NULL_INPUT", "Expected the input not to be null");
1848
- }
1849
- //#endregion
1850
- //#region src/root/errors/assertNotNullable.ts
1851
- /**
1852
- * Asserts that a given input is not `undefined` or `null`, and throws a DataError if it does.
1853
- *
1854
- * If no error is thrown from this, the input type gets narrowed down to not include `undefined` or `null`.
1855
- *
1856
- * @template InputType The type of the input.
1857
- *
1858
- * @param input - The input to assert against.
1859
- *
1860
- * @throws {DataError} If the input is `undefined` or `null`.
1861
- */
1862
- function assertNotNullable(input) {
1863
- if (input === null || input === void 0) throw new DataError$1({ input }, "NULLABLE_INPUT", "Expected the input not to be undefined or null");
1864
- }
1865
- //#endregion
1866
- //#region src/root/errors/assertNotUndefined.ts
1867
- /**
1868
- * Asserts that a given input is not `undefined`, and throws a DataError if it does.
1869
- *
1870
- * If no error is thrown from this, the input type gets narrowed down to not include `undefined`.
1871
- *
1872
- * @template InputType The type of the input.
1873
- *
1874
- * @param input - The input to assert against.
1875
- *
1876
- * @throws {DataError} If the input is `undefined`.
1877
- */
1878
- function assertNotUndefined(input) {
1879
- if (input === void 0) throw new DataError$1({ input }, "UNDEFINED_INPUT", "Expected the input not to be undefined");
1880
- }
1881
- //#endregion
1882
- export { APIError, DataError, Env, FILE_PATH_PATTERN, FILE_PATH_REGEX, ONE_DAY_IN_MILLISECONDS, UUID_PATTERN, UUID_REGEX, VERSION_NUMBER_PATTERN, VERSION_NUMBER_REGEX, VersionNumber, VersionType, addDaysToDate, appendSemicolon, assertNotNull, assertNotNullable, assertNotUndefined, az, calculateMonthlyDifference, camelToKebab, convertFileToBase64, createFormData, createTemplateStringsArray, deepCopy, deepFreeze, escapeRegexPattern, fillArray, formatDateAndTime, getRandomNumber, getRecordKeys, getStringsAndInterpolations, httpErrorCodeLookup, interpolate, interpolateObjects, isAnniversary, isLeapYear, isMonthlyMultiple, isOrdered, isSameDate, isTemplateStringsArray, kebabToCamel, normaliseIndents, normalizeIndents, omitProperties, paralleliseArrays, parseBoolean, parseEnv, parseFormData, parseIntStrict, parseUUID, parseVersionType, parseZodSchema, parseZodSchemaAsync, randomiseArray, range, removeDuplicates, removeUndefinedFromObject, sayHello, stringListToArray, stringifyDotenv, toTitleCase, truncate, wait, zodVersionNumber };
1986
+ export { APIError, DataError, Env, FILE_PATH_PATTERN, FILE_PATH_REGEX, ONE_DAY_IN_MILLISECONDS, SortDirection, UUID_PATTERN, UUID_REGEX, VERSION_NUMBER_PATTERN, VERSION_NUMBER_REGEX, VersionNumber, VersionType, addDaysToDate, appendSemicolon, assertNotNull, assertNotNullable, assertNotUndefined, az, calculateMonthlyDifference, camelToKebab, containsKeys, convertFileToBase64, createFormData, createTemplateStringsArray, deepCopy, deepFreeze, escapeRegexPattern, fillArray, formatDateAndTime, getRandomNumber, getRecordKeys, getStringsAndInterpolations, httpErrorCodeLookup, identity, interpolate, interpolateObjects, isAnniversary, isLeapYear, isMonthlyMultiple, isNonNullableObject, isOrdered, isSameDate, isTemplateStringsArray, kebabToCamel, normaliseIndents, normalizeIndents, objectContainsKeys, omitProperties, paralleliseArrays, parseBoolean, parseEnv, parseFormData, parseIntStrict, parseUUID, parseVersionType, parseZodSchema, parseZodSchemaAsync, randomiseArray, range, removeDuplicates, removeUndefinedFromObject, sayHello, sortBy, stringListToArray, stringifyDotenv, toTitleCase, truncate, wait, zodVersionNumber };
@@ -69,7 +69,7 @@ var CodeError = class CodeError extends Error {
69
69
  */
70
70
  static check(input) {
71
71
  if (input instanceof CodeError) return true;
72
- return typeof input === "object" && input !== null && "message" in input && typeof input.message === "string" && "code" in input && typeof input.code === "string";
72
+ return containsKeys(input, ["message", "code"]) && typeof input.message === "string" && typeof input.code === "string";
73
73
  }
74
74
  static checkCaughtError(error, options) {
75
75
  if (this.check(error)) {
@@ -182,7 +182,11 @@ var DataError = class DataError extends CodeError {
182
182
  */
183
183
  static check(input) {
184
184
  if (input instanceof DataError) return true;
185
- return typeof input === "object" && input !== null && "message" in input && typeof input.message === "string" && "code" in input && typeof input.code === "string" && "data" in input && typeof input.data === "object" && input.data !== null;
185
+ return containsKeys(input, [
186
+ "data",
187
+ "code",
188
+ "message"
189
+ ]) && typeof input.message === "string" && typeof input.code === "string" && isNonNullableObject(input.data);
186
190
  }
187
191
  /**
188
192
  * Check a `DataError` against its error code
@@ -240,6 +244,49 @@ var DataError = class DataError extends CodeError {
240
244
  }
241
245
  };
242
246
  //#endregion
247
+ //#region src/root/functions/parsers/parseIntStrict.ts
248
+ /**
249
+ * Converts a string to an integer and throws an error if it cannot be converted.
250
+ *
251
+ * @category Parsers
252
+ *
253
+ * @param string - A string to convert into a number.
254
+ * @param radix - A value between 2 and 36 that specifies the base of the number in string. If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. All other strings are considered decimal.
255
+ *
256
+ * @throws {DataError} If the provided string cannot safely be converted to an integer.
257
+ *
258
+ * @returns The integer parsed from the input string.
259
+ */
260
+ function parseIntStrict(string, radix) {
261
+ const trimmedString = string.trim();
262
+ const maxAllowedAlphabeticalCharacter = radix && radix > 10 && radix <= 36 ? String.fromCharCode(87 + radix - 1) : void 0;
263
+ if (!(radix && radix > 10 && radix <= 36 ? new RegExp(`^[+-]?[0-9a-${maxAllowedAlphabeticalCharacter}]+$`, "i") : /^[+-]?\d+$/).test(trimmedString)) throw new DataError(radix ? {
264
+ string,
265
+ radix
266
+ } : { string }, "INTEGER_PARSING_ERROR", `Only numeric values${radix && radix > 10 && radix <= 36 ? ` or character${radix !== 11 ? "s" : ""} A${radix !== 11 ? `-${maxAllowedAlphabeticalCharacter?.toUpperCase()} ` : " "}` : " "}are allowed.`);
267
+ if (radix && radix < 10 && [...trimmedString.replace(/^[+-]/, "")].some((character) => {
268
+ return parseInt(character) >= radix;
269
+ })) throw new DataError({
270
+ string,
271
+ radix
272
+ }, "INTEGER_PARSING_ERROR", "Value contains one or more digits outside of the range of the given radix.");
273
+ const parseIntResult = parseInt(trimmedString, radix);
274
+ if (isNaN(parseIntResult)) throw new DataError({ string }, "INTEGER_PARSING_ERROR", "Value is not a valid integer.");
275
+ return parseIntResult;
276
+ }
277
+ //#endregion
278
+ //#region src/root/functions/parsers/parseVersionType.ts
279
+ /**
280
+ * Represents the three common software version types.
281
+ *
282
+ * @category Types
283
+ */
284
+ const VersionType = {
285
+ MAJOR: "major",
286
+ MINOR: "minor",
287
+ PATCH: "patch"
288
+ };
289
+ //#endregion
243
290
  //#region src/root/functions/arrayHelpers/range.ts
244
291
  /**
245
292
  * Creates an array of numbers within a given range.
@@ -279,6 +326,53 @@ function range(start, stop, step = 1) {
279
326
  return numbers;
280
327
  }
281
328
  //#endregion
329
+ //#region src/root/functions/typeAssertions/isNonNullableObject.ts
330
+ /**
331
+ * Determines if the given input is a non-nullable object, narrowing the type down as such if it is
332
+ *
333
+ * @category Type Assertions
334
+ *
335
+ * @param input - The input to check
336
+ *
337
+ * @returns `true` if the input is a non-nullable object, and `false` otherwise. The input type will also be narrowed down to be a non-nullable object.
338
+ */
339
+ function isNonNullableObject(input) {
340
+ return typeof input === "object" && input !== null;
341
+ }
342
+ //#endregion
343
+ //#region src/root/functions/typeAssertions/objectContainsKeys.ts
344
+ /**
345
+ * Determines if the given object contains all of the keys provided.
346
+ *
347
+ * @category Type Assertions
348
+ *
349
+ * @param input - The input object to check.
350
+ * @param keys - The keys expected to be in the input object.
351
+ *
352
+ * @returns `true` if the input object contains all provided keys, and `false` otherwise. The input type will also be narrowed down to be a record with the provided keys with an unknown value type.
353
+ */
354
+ function objectContainsKeys(input, keys) {
355
+ const expectedKeys = Array.isArray(keys) ? keys : [keys];
356
+ if (expectedKeys.length === 0) return false;
357
+ for (const key of expectedKeys) if (!(key in input)) return false;
358
+ return true;
359
+ }
360
+ //#endregion
361
+ //#region src/root/functions/typeAssertions/containsKeys.ts
362
+ /**
363
+ * Determines if the given input is a non-nullable object, and if that object contains all of the keys provided.
364
+ *
365
+ * @category Type Assertions
366
+ *
367
+ * @param input - The input to check.
368
+ * @param keys - The keys expected to be in the input if it's an object.
369
+ *
370
+ * @returns `true` if the input is an object containing all provided keys, and `false` otherwise. The input type will also be narrowed down to be a record with the provided keys, each with an unknown value type.
371
+ */
372
+ function containsKeys(input, keys) {
373
+ return isNonNullableObject(input) && objectContainsKeys(input, keys);
374
+ }
375
+ //#endregion
282
376
  //#region src/root/functions/arrayHelpers/fillArray.ts
283
377
  /**
284
378
  * Creates a new array where each element is the result of the provided callback.
@@ -306,7 +400,7 @@ function fillArray(callback, length = 1, options) {
306
400
  return callback(index);
307
401
  });
308
402
  if (outputArray.some((item) => {
309
- return item instanceof Promise || typeof item === "object" && item !== null && "then" in item && typeof item.then === "function";
403
+ return item instanceof Promise || containsKeys(item, "then") && typeof item.then === "function";
310
404
  })) return Promise.all(outputArray);
311
405
  return outputArray;
312
406
  }
@@ -334,49 +428,6 @@ function paralleliseArrays(firstArray, secondArray) {
334
428
  return outputArray;
335
429
  }
336
430
  //#endregion
337
- //#region src/root/functions/parsers/parseIntStrict.ts
338
- /**
339
- * Converts a string to an integer and throws an error if it cannot be converted.
340
- *
341
- * @category Parsers
342
- *
343
- * @param string - A string to convert into a number.
344
- * @param radix - A value between 2 and 36 that specifies the base of the number in string. If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. All other strings are considered decimal.
345
- *
346
- * @throws {DataError} If the provided string cannot safely be converted to an integer.
347
- *
348
- * @returns The integer parsed from the input string.
349
- */
350
- function parseIntStrict(string, radix) {
351
- const trimmedString = string.trim();
352
- const maxAllowedAlphabeticalCharacter = radix && radix > 10 && radix <= 36 ? String.fromCharCode(87 + radix - 1) : void 0;
353
- if (!(radix && radix > 10 && radix <= 36 ? new RegExp(`^[+-]?[0-9a-${maxAllowedAlphabeticalCharacter}]+$`, "i") : /^[+-]?\d+$/).test(trimmedString)) throw new DataError(radix ? {
354
- string,
355
- radix
356
- } : { string }, "INTEGER_PARSING_ERROR", `Only numeric values${radix && radix > 10 && radix <= 36 ? ` or character${radix !== 11 ? "s" : ""} A${radix !== 11 ? `-${maxAllowedAlphabeticalCharacter?.toUpperCase()} ` : " "}` : " "}are allowed.`);
357
- if (radix && radix < 10 && [...trimmedString.replace(/^[+-]/, "")].some((character) => {
358
- return parseInt(character) >= radix;
359
- })) throw new DataError({
360
- string,
361
- radix
362
- }, "INTEGER_PARSING_ERROR", "Value contains one or more digits outside of the range of the given radix.");
363
- const parseIntResult = parseInt(trimmedString, radix);
364
- if (isNaN(parseIntResult)) throw new DataError({ string }, "INTEGER_PARSING_ERROR", "Value is not a valid integer.");
365
- return parseIntResult;
366
- }
367
- //#endregion
368
- //#region src/root/functions/parsers/parseVersionType.ts
369
- /**
370
- * Represents the three common software version types.
371
- *
372
- * @category Types
373
- */
374
- const VersionType = {
375
- MAJOR: "major",
376
- MINOR: "minor",
377
- PATCH: "patch"
378
- };
379
- //#endregion
380
431
  //#region src/root/functions/taggedTemplate/interpolate.ts
381
432
  /**
382
433
  * Returns the result of interpolating a template string when given the strings and interpolations separately.
@@ -456,7 +507,7 @@ function reduceLines(lines, { preserveTabs = true }) {
456
507
  * @returns An additional function to invoke, or a new string with the strings and interpolations from the template applied, and extraneous indents removed.
457
508
  */
458
509
  function normaliseIndents(first, ...args) {
459
- if (typeof first === "object" && first !== null && !Array.isArray(first)) {
510
+ if (isNonNullableObject(first) && !Array.isArray(first)) {
460
511
  const options = first;
461
512
  return (strings, ...interpolations) => {
462
513
  return normaliseIndents(strings, ...interpolations, options);
@@ -44,7 +44,7 @@ var CodeError = class CodeError extends Error {
44
44
  */
45
45
  static check(input) {
46
46
  if (input instanceof CodeError) return true;
47
- return typeof input === "object" && input !== null && "message" in input && typeof input.message === "string" && "code" in input && typeof input.code === "string";
47
+ return containsKeys(input, ["message", "code"]) && typeof input.message === "string" && typeof input.code === "string";
48
48
  }
49
49
  static checkCaughtError(error, options) {
50
50
  if (this.check(error)) {
@@ -157,7 +157,11 @@ var DataError = class DataError extends CodeError {
157
157
  */
158
158
  static check(input) {
159
159
  if (input instanceof DataError) return true;
160
- return typeof input === "object" && input !== null && "message" in input && typeof input.message === "string" && "code" in input && typeof input.code === "string" && "data" in input && typeof input.data === "object" && input.data !== null;
160
+ return containsKeys(input, [
161
+ "data",
162
+ "code",
163
+ "message"
164
+ ]) && typeof input.message === "string" && typeof input.code === "string" && isNonNullableObject(input.data);
161
165
  }
162
166
  /**
163
167
  * Check a `DataError` against its error code
@@ -215,6 +219,49 @@ var DataError = class DataError extends CodeError {
215
219
  }
216
220
  };
217
221
  //#endregion
222
+ //#region src/root/functions/parsers/parseIntStrict.ts
223
+ /**
224
+ * Converts a string to an integer and throws an error if it cannot be converted.
225
+ *
226
+ * @category Parsers
227
+ *
228
+ * @param string - A string to convert into a number.
229
+ * @param radix - A value between 2 and 36 that specifies the base of the number in string. If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. All other strings are considered decimal.
230
+ *
231
+ * @throws {DataError} If the provided string cannot safely be converted to an integer.
232
+ *
233
+ * @returns The integer parsed from the input string.
234
+ */
235
+ function parseIntStrict(string, radix) {
236
+ const trimmedString = string.trim();
237
+ const maxAllowedAlphabeticalCharacter = radix && radix > 10 && radix <= 36 ? String.fromCharCode(87 + radix - 1) : void 0;
238
+ if (!(radix && radix > 10 && radix <= 36 ? new RegExp(`^[+-]?[0-9a-${maxAllowedAlphabeticalCharacter}]+$`, "i") : /^[+-]?\d+$/).test(trimmedString)) throw new DataError(radix ? {
239
+ string,
240
+ radix
241
+ } : { string }, "INTEGER_PARSING_ERROR", `Only numeric values${radix && radix > 10 && radix <= 36 ? ` or character${radix !== 11 ? "s" : ""} A${radix !== 11 ? `-${maxAllowedAlphabeticalCharacter?.toUpperCase()} ` : " "}` : " "}are allowed.`);
242
+ if (radix && radix < 10 && [...trimmedString.replace(/^[+-]/, "")].some((character) => {
243
+ return parseInt(character) >= radix;
244
+ })) throw new DataError({
245
+ string,
246
+ radix
247
+ }, "INTEGER_PARSING_ERROR", "Value contains one or more digits outside of the range of the given radix.");
248
+ const parseIntResult = parseInt(trimmedString, radix);
249
+ if (isNaN(parseIntResult)) throw new DataError({ string }, "INTEGER_PARSING_ERROR", "Value is not a valid integer.");
250
+ return parseIntResult;
251
+ }
252
+ //#endregion
253
+ //#region src/root/functions/parsers/parseVersionType.ts
254
+ /**
255
+ * Represents the three common software version types.
256
+ *
257
+ * @category Types
258
+ */
259
+ const VersionType = {
260
+ MAJOR: "major",
261
+ MINOR: "minor",
262
+ PATCH: "patch"
263
+ };
264
+ //#endregion
218
265
  //#region src/root/functions/arrayHelpers/range.ts
219
266
  /**
220
267
  * Creates an array of numbers within a given range.
@@ -254,6 +301,53 @@ function range(start, stop, step = 1) {
254
301
  return numbers;
255
302
  }
256
303
  //#endregion
304
+ //#region src/root/functions/typeAssertions/isNonNullableObject.ts
305
+ /**
306
+ * Determines if the given input is a non-nullable object, narrowing the type down as such if it is
307
+ *
308
+ * @category Type Assertions
309
+ *
310
+ * @param input - The input to check
311
+ *
312
+ * @returns `true` if the input is a non-nullable object, and `false` otherwise. The input type will also be narrowed down to be a non-nullable object.
313
+ */
314
+ function isNonNullableObject(input) {
315
+ return typeof input === "object" && input !== null;
316
+ }
317
+ //#endregion
318
+ //#region src/root/functions/typeAssertions/objectContainsKeys.ts
319
+ /**
320
+ * Determines if the given object contains all of the keys provided.
321
+ *
322
+ * @category Type Assertions
323
+ *
324
+ * @param input - The input object to check.
325
+ * @param keys - The keys expected to be in the input object.
326
+ *
327
+ * @returns `true` if the input object contains all provided keys, and `false` otherwise. The input type will also be narrowed down to be a record with the provided keys with an unknown value type.
328
+ */
329
+ function objectContainsKeys(input, keys) {
330
+ const expectedKeys = Array.isArray(keys) ? keys : [keys];
331
+ if (expectedKeys.length === 0) return false;
332
+ for (const key of expectedKeys) if (!(key in input)) return false;
333
+ return true;
334
+ }
335
+ //#endregion
336
+ //#region src/root/functions/typeAssertions/containsKeys.ts
337
+ /**
338
+ * Determines if the given input is a non-nullable object, and if that object contains all of the keys provided.
339
+ *
340
+ * @category Type Assertions
341
+ *
342
+ * @param input - The input to check.
343
+ * @param keys - The keys expected to be in the input if it's an object.
344
+ *
345
+ * @returns `true` if the input is an object containing all provided keys, and `false` otherwise. The input type will also be narrowed down to be a record with the provided keys, each with an unknown value type.
346
+ */
347
+ function containsKeys(input, keys) {
348
+ return isNonNullableObject(input) && objectContainsKeys(input, keys);
349
+ }
350
+ //#endregion
257
351
  //#region src/root/functions/arrayHelpers/fillArray.ts
258
352
  /**
259
353
  * Creates a new array where each element is the result of the provided callback.
@@ -281,7 +375,7 @@ function fillArray(callback, length = 1, options) {
281
375
  return callback(index);
282
376
  });
283
377
  if (outputArray.some((item) => {
284
- return item instanceof Promise || typeof item === "object" && item !== null && "then" in item && typeof item.then === "function";
378
+ return item instanceof Promise || containsKeys(item, "then") && typeof item.then === "function";
285
379
  })) return Promise.all(outputArray);
286
380
  return outputArray;
287
381
  }
@@ -309,49 +403,6 @@ function paralleliseArrays(firstArray, secondArray) {
309
403
  return outputArray;
310
404
  }
311
405
  //#endregion
312
- //#region src/root/functions/parsers/parseIntStrict.ts
313
- /**
314
- * Converts a string to an integer and throws an error if it cannot be converted.
315
- *
316
- * @category Parsers
317
- *
318
- * @param string - A string to convert into a number.
319
- * @param radix - A value between 2 and 36 that specifies the base of the number in string. If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. All other strings are considered decimal.
320
- *
321
- * @throws {DataError} If the provided string cannot safely be converted to an integer.
322
- *
323
- * @returns The integer parsed from the input string.
324
- */
325
- function parseIntStrict(string, radix) {
326
- const trimmedString = string.trim();
327
- const maxAllowedAlphabeticalCharacter = radix && radix > 10 && radix <= 36 ? String.fromCharCode(87 + radix - 1) : void 0;
328
- if (!(radix && radix > 10 && radix <= 36 ? new RegExp(`^[+-]?[0-9a-${maxAllowedAlphabeticalCharacter}]+$`, "i") : /^[+-]?\d+$/).test(trimmedString)) throw new DataError(radix ? {
329
- string,
330
- radix
331
- } : { string }, "INTEGER_PARSING_ERROR", `Only numeric values${radix && radix > 10 && radix <= 36 ? ` or character${radix !== 11 ? "s" : ""} A${radix !== 11 ? `-${maxAllowedAlphabeticalCharacter?.toUpperCase()} ` : " "}` : " "}are allowed.`);
332
- if (radix && radix < 10 && [...trimmedString.replace(/^[+-]/, "")].some((character) => {
333
- return parseInt(character) >= radix;
334
- })) throw new DataError({
335
- string,
336
- radix
337
- }, "INTEGER_PARSING_ERROR", "Value contains one or more digits outside of the range of the given radix.");
338
- const parseIntResult = parseInt(trimmedString, radix);
339
- if (isNaN(parseIntResult)) throw new DataError({ string }, "INTEGER_PARSING_ERROR", "Value is not a valid integer.");
340
- return parseIntResult;
341
- }
342
- //#endregion
343
- //#region src/root/functions/parsers/parseVersionType.ts
344
- /**
345
- * Represents the three common software version types.
346
- *
347
- * @category Types
348
- */
349
- const VersionType = {
350
- MAJOR: "major",
351
- MINOR: "minor",
352
- PATCH: "patch"
353
- };
354
- //#endregion
355
406
  //#region src/root/functions/taggedTemplate/interpolate.ts
356
407
  /**
357
408
  * Returns the result of interpolating a template string when given the strings and interpolations separately.
@@ -431,7 +482,7 @@ function reduceLines(lines, { preserveTabs = true }) {
431
482
  * @returns An additional function to invoke, or a new string with the strings and interpolations from the template applied, and extraneous indents removed.
432
483
  */
433
484
  function normaliseIndents(first, ...args) {
434
- if (typeof first === "object" && first !== null && !Array.isArray(first)) {
485
+ if (isNonNullableObject(first) && !Array.isArray(first)) {
435
486
  const options = first;
436
487
  return (strings, ...interpolations) => {
437
488
  return normaliseIndents(strings, ...interpolations, options);