@oscarpalmer/atoms 0.154.0 → 0.156.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.
Files changed (66) hide show
  1. package/dist/array/difference.js +5 -0
  2. package/dist/array/exists.js +2 -2
  3. package/dist/array/find.js +2 -2
  4. package/dist/array/index-of.js +2 -2
  5. package/dist/array/{misc.js → index.js} +5 -2
  6. package/dist/array/intersection.js +5 -0
  7. package/dist/array/union.js +5 -0
  8. package/dist/array/unique.js +2 -2
  9. package/dist/atoms.full.js +242 -140
  10. package/dist/function/assert.js +46 -6
  11. package/dist/index.js +11 -7
  12. package/dist/internal/array/find.js +5 -1
  13. package/dist/internal/array/sets.js +30 -0
  14. package/dist/internal/is.js +10 -1
  15. package/dist/internal/value/get.js +2 -10
  16. package/dist/internal/value/has.js +9 -0
  17. package/dist/internal/value/misc.js +30 -2
  18. package/dist/internal/value/set.js +1 -1
  19. package/dist/is.js +1 -10
  20. package/dist/math.js +1 -1
  21. package/dist/value/{get-set.js → handle.js} +2 -1
  22. package/dist/value/merge.js +0 -6
  23. package/package.json +15 -15
  24. package/src/array/difference.ts +40 -0
  25. package/src/array/exists.ts +2 -2
  26. package/src/array/filter.ts +3 -3
  27. package/src/array/find.ts +2 -2
  28. package/src/array/index-of.ts +2 -2
  29. package/src/array/{misc.ts → index.ts} +3 -0
  30. package/src/array/intersection.ts +39 -0
  31. package/src/array/partition.ts +2 -2
  32. package/src/array/select.ts +2 -2
  33. package/src/array/union.ts +39 -0
  34. package/src/array/unique.ts +2 -2
  35. package/src/function/assert.ts +3 -3
  36. package/src/index.ts +4 -6
  37. package/src/internal/array/find.ts +14 -3
  38. package/src/internal/array/sets.ts +74 -0
  39. package/src/internal/is.ts +13 -0
  40. package/src/internal/value/get.ts +2 -27
  41. package/src/internal/value/has.ts +75 -0
  42. package/src/internal/value/misc.ts +65 -5
  43. package/src/internal/value/set.ts +6 -6
  44. package/src/is.ts +3 -15
  45. package/src/value/{get-set.ts → handle.ts} +1 -0
  46. package/src/value/merge.ts +18 -2
  47. package/types/array/difference.d.ts +24 -0
  48. package/types/array/{misc.d.ts → index.d.ts} +3 -0
  49. package/types/array/intersection.d.ts +23 -0
  50. package/types/array/union.d.ts +23 -0
  51. package/types/function/assert.d.ts +41 -3
  52. package/types/index.d.ts +4 -6
  53. package/types/internal/array/find.d.ts +4 -0
  54. package/types/internal/array/sets.d.ts +6 -0
  55. package/types/internal/is.d.ts +7 -0
  56. package/types/internal/value/has.d.ts +40 -0
  57. package/types/internal/value/misc.d.ts +10 -2
  58. package/types/is.d.ts +2 -9
  59. package/types/value/{get-set.d.ts → handle.d.ts} +1 -0
  60. package/types/value/merge.d.ts +7 -0
  61. /package/dist/string/{misc.js → index.js} +0 -0
  62. /package/dist/value/{misc.js → index.js} +0 -0
  63. /package/src/string/{misc.ts → index.ts} +0 -0
  64. /package/src/value/{misc.ts → index.ts} +0 -0
  65. /package/types/string/{misc.d.ts → index.d.ts} +0 -0
  66. /package/types/value/{misc.d.ts → index.d.ts} +0 -0
@@ -0,0 +1,5 @@
1
+ import { COMPARE_SETS_DIFFERENCE, compareSets } from "../internal/array/sets.js";
2
+ function difference(first, second, key) {
3
+ return compareSets(COMPARE_SETS_DIFFERENCE, first, second, key);
4
+ }
5
+ export { difference };
@@ -1,6 +1,6 @@
1
- import { findValue } from "../internal/array/find.js";
1
+ import { FIND_VALUE_INDEX, findValue } from "../internal/array/find.js";
2
2
  function exists(array, ...parameters) {
3
3
  if (parameters.length === 1 && typeof parameters[0] !== "function") return Array.isArray(array) ? array.includes(parameters[0]) : false;
4
- return findValue("index", array, parameters) > -1;
4
+ return findValue(FIND_VALUE_INDEX, array, parameters) > -1;
5
5
  }
6
6
  export { exists };
@@ -1,5 +1,5 @@
1
- import { findValue } from "../internal/array/find.js";
1
+ import { FIND_VALUE_VALUE, findValue } from "../internal/array/find.js";
2
2
  function find(array, ...parameters) {
3
- return findValue("value", array, parameters);
3
+ return findValue(FIND_VALUE_VALUE, array, parameters);
4
4
  }
5
5
  export { find };
@@ -1,5 +1,5 @@
1
- import { findValue } from "../internal/array/find.js";
1
+ import { FIND_VALUE_INDEX, findValue } from "../internal/array/find.js";
2
2
  function indexOf(array, ...parameters) {
3
- return findValue("index", array, parameters);
3
+ return findValue(FIND_VALUE_INDEX, array, parameters);
4
4
  }
5
5
  export { indexOf };
@@ -1,3 +1,4 @@
1
+ import { difference } from "./difference.js";
1
2
  import { exists } from "./exists.js";
2
3
  import { filter } from "./filter.js";
3
4
  import { find } from "./find.js";
@@ -6,9 +7,10 @@ import { range, times } from "./from.js";
6
7
  import { getArray } from "./get.js";
7
8
  import { indexOf } from "./index-of.js";
8
9
  import { chunk } from "../internal/array/chunk.js";
9
- import { insert } from "./insert.js";
10
10
  import { compact } from "../internal/array/compact.js";
11
11
  import { shuffle } from "../internal/array/shuffle.js";
12
+ import { insert } from "./insert.js";
13
+ import { intersection } from "./intersection.js";
12
14
  import { partition } from "./partition.js";
13
15
  import { push } from "./push.js";
14
16
  import { select } from "./select.js";
@@ -16,5 +18,6 @@ import { sort } from "./sort.js";
16
18
  import { splice } from "./splice.js";
17
19
  import { toSet } from "./to-set.js";
18
20
  import { toggle } from "./toggle.js";
21
+ import { union } from "./union.js";
19
22
  import { update } from "./update.js";
20
- export { chunk, compact, exists, filter, find, flatten, getArray, indexOf, insert, partition, push, range, select, shuffle, sort, splice, times, toSet, toggle, update };
23
+ export { chunk, compact, difference, exists, filter, find, flatten, getArray, indexOf, insert, intersection, partition, push, range, select, shuffle, sort, splice, times, toSet, toggle, union, update };
@@ -0,0 +1,5 @@
1
+ import { COMPARE_SETS_INTERSECTION, compareSets } from "../internal/array/sets.js";
2
+ function intersection(first, second, key) {
3
+ return compareSets(COMPARE_SETS_INTERSECTION, first, second, key);
4
+ }
5
+ export { intersection };
@@ -0,0 +1,5 @@
1
+ import { COMPARE_SETS_UNION, compareSets } from "../internal/array/sets.js";
2
+ function union(first, second, key) {
3
+ return compareSets(COMPARE_SETS_UNION, first, second, key);
4
+ }
5
+ export { union };
@@ -1,6 +1,6 @@
1
- import { findValues } from "../internal/array/find.js";
1
+ import { FIND_VALUES_UNIQUE, findValues } from "../internal/array/find.js";
2
2
  function unique(array, key) {
3
3
  if (!Array.isArray(array)) return [];
4
- return array.length > 1 ? findValues("unique", array, [key, void 0]).matched : array;
4
+ return array.length > 1 ? findValues(FIND_VALUES_UNIQUE, array, [key, void 0]).matched : array;
5
5
  }
6
6
  export { unique };
@@ -86,6 +86,15 @@ function isConstructor(value) {
86
86
  return typeof value === "function" && value.prototype?.constructor === value;
87
87
  }
88
88
  /**
89
+ * Is the value an instance of the constructor?
90
+ * @param constructor Class constructor
91
+ * @param value Value to check
92
+ * @returns `true` if the value is an instance of the constructor, otherwise `false`
93
+ */
94
+ function isInstanceOf(constructor, value) {
95
+ return isConstructor(constructor) && value instanceof constructor;
96
+ }
97
+ /**
89
98
  * Is the value a key?
90
99
  * @param value Value to check
91
100
  * @returns `true` if the value is a `Key` _(`number` or `string`)_, otherwise `false`
@@ -175,6 +184,37 @@ function shuffle(array) {
175
184
  }
176
185
  return shuffled;
177
186
  }
187
+ function compareSets(type, first, second, key) {
188
+ if (!Array.isArray(first)) return [];
189
+ const isDifference = type === COMPARE_SETS_DIFFERENCE;
190
+ const isIntersection = type === COMPARE_SETS_INTERSECTION;
191
+ const isUnion = type === COMPARE_SETS_UNION;
192
+ if (first.length === 0) return isDifference ? [...first] : isIntersection ? [] : [...second];
193
+ if (!Array.isArray(second) || second.length === 0) return isIntersection ? [] : [...first];
194
+ const callback = getArrayCallback(key);
195
+ const values = isUnion ? first : second;
196
+ let { length } = values;
197
+ const set = /* @__PURE__ */ new Set([]);
198
+ for (let index = 0; index < length; index += 1) {
199
+ const item = values[index];
200
+ set.add(callback?.(item, index, values) ?? item);
201
+ }
202
+ const source = isUnion ? second : first;
203
+ length = source.length;
204
+ const result = isUnion ? [...first] : [];
205
+ for (let index = 0; index < length; index += 1) {
206
+ const item = source[index];
207
+ const value = callback?.(item, index, source) ?? item;
208
+ if (isIntersection ? set.has(value) : !set.has(value)) result.push(item);
209
+ }
210
+ return result;
211
+ }
212
+ const COMPARE_SETS_DIFFERENCE = "difference";
213
+ const COMPARE_SETS_INTERSECTION = "intersection";
214
+ const COMPARE_SETS_UNION = "union";
215
+ function difference(first, second, key) {
216
+ return compareSets(COMPARE_SETS_DIFFERENCE, first, second, key);
217
+ }
178
218
  function findValue(type, array, parameters) {
179
219
  const findIndex = type === "index";
180
220
  if (!Array.isArray(array) || array.length === 0) return findIndex ? -1 : void 0;
@@ -204,12 +244,12 @@ function findValues(type, array, parameters, mapper) {
204
244
  const { length } = array;
205
245
  const { bool, key, value } = getParameters(parameters);
206
246
  const callbacks = getArrayCallbacks(bool, key);
207
- if (type === "unique" && callbacks?.keyed == null && length >= UNIQUE_THRESHOLD) {
247
+ if (type === FIND_VALUES_UNIQUE && callbacks?.keyed == null && length >= UNIQUE_THRESHOLD) {
208
248
  result.matched = [...new Set(array)];
209
249
  return result;
210
250
  }
211
251
  const mapCallback = typeof mapper === "function" ? mapper : void 0;
212
- if (callbacks?.bool != null || type === "all" && key == null) {
252
+ if (callbacks?.bool != null || type === FIND_VALUES_ALL && key == null) {
213
253
  const callback = callbacks?.bool ?? ((item) => Object.is(item, value));
214
254
  for (let index = 0; index < length; index += 1) {
215
255
  const item = array[index];
@@ -222,7 +262,7 @@ function findValues(type, array, parameters, mapper) {
222
262
  for (let index = 0; index < length; index += 1) {
223
263
  const item = array[index];
224
264
  const keyed = callbacks?.keyed?.(item, index, array) ?? item;
225
- if (type === "all" && Object.is(keyed, value) || type === "unique" && !keys.has(keyed)) {
265
+ if (type === FIND_VALUES_ALL && Object.is(keyed, value) || type === FIND_VALUES_UNIQUE && !keys.has(keyed)) {
226
266
  keys.add(keyed);
227
267
  result.matched.push(mapCallback?.(item, index, array) ?? item);
228
268
  } else result.notMatched.push(item);
@@ -237,20 +277,24 @@ function getParameters(original) {
237
277
  value: length === 1 && typeof original[0] !== "function" ? original[0] : original[1]
238
278
  };
239
279
  }
280
+ const FIND_VALUE_INDEX = "index";
281
+ const FIND_VALUE_VALUE = "value";
282
+ const FIND_VALUES_ALL = "all";
283
+ const FIND_VALUES_UNIQUE = "unique";
240
284
  const UNIQUE_THRESHOLD = 100;
241
285
  function exists(array, ...parameters) {
242
286
  if (parameters.length === 1 && typeof parameters[0] !== "function") return Array.isArray(array) ? array.includes(parameters[0]) : false;
243
- return findValue("index", array, parameters) > -1;
287
+ return findValue(FIND_VALUE_INDEX, array, parameters) > -1;
244
288
  }
245
289
  function filter(array, ...parameters) {
246
- return findValues("all", array, parameters).matched;
290
+ return findValues(FIND_VALUES_ALL, array, parameters).matched;
247
291
  }
248
292
  filter.remove = removeFiltered;
249
293
  function removeFiltered(array, ...parameters) {
250
- return findValues("all", array, parameters).notMatched;
294
+ return findValues(FIND_VALUES_ALL, array, parameters).notMatched;
251
295
  }
252
296
  function find(array, ...parameters) {
253
- return findValue("value", array, parameters);
297
+ return findValue(FIND_VALUE_VALUE, array, parameters);
254
298
  }
255
299
  /**
256
300
  * Flatten an array _(using native `flat` and maximum depth)_
@@ -292,7 +336,7 @@ function getArray(value, indiced) {
292
336
  return array;
293
337
  }
294
338
  function indexOf(array, ...parameters) {
295
- return findValue("index", array, parameters);
339
+ return findValue(FIND_VALUE_INDEX, array, parameters);
296
340
  }
297
341
  function insertChunkedValues(type, array, items, start, deleteCount) {
298
342
  const actualDeleteCount = deleteCount < 0 ? 0 : deleteCount;
@@ -318,8 +362,11 @@ function insertValues(type, array, items, start, deleteCount) {
318
362
  function insert(array, indexOrItems, items) {
319
363
  return insertValues("insert", array, items == null ? indexOrItems : items, typeof indexOrItems === "number" ? indexOrItems : array?.length, 0);
320
364
  }
365
+ function intersection(first, second, key) {
366
+ return compareSets(COMPARE_SETS_INTERSECTION, first, second, key);
367
+ }
321
368
  function partition(array, ...parameters) {
322
- const { matched, notMatched } = findValues("all", array, parameters);
369
+ const { matched, notMatched } = findValues(FIND_VALUES_ALL, array, parameters);
323
370
  return [matched, notMatched];
324
371
  }
325
372
  /**
@@ -332,7 +379,7 @@ function push(array, pushed) {
332
379
  return insertValues("push", array, pushed, array.length, 0);
333
380
  }
334
381
  function select(array, ...parameters) {
335
- return findValues("all", array, parameters, parameters.pop()).matched;
382
+ return findValues(FIND_VALUES_ALL, array, parameters, parameters.pop()).matched;
336
383
  }
337
384
  function aggregate(type, array, key) {
338
385
  const length = Array.isArray(array) ? array.length : 0;
@@ -639,6 +686,9 @@ function updateInArray(array, items, key, replace) {
639
686
  function toggle(array, values, key) {
640
687
  return updateInArray(array, values, key, false);
641
688
  }
689
+ function union(first, second, key) {
690
+ return compareSets(COMPARE_SETS_UNION, first, second, key);
691
+ }
642
692
  function update(array, values, key) {
643
693
  return updateInArray(array, values, key, true);
644
694
  }
@@ -675,7 +725,7 @@ function toRecordArrays(array, first, second) {
675
725
  }
676
726
  function unique(array, key) {
677
727
  if (!Array.isArray(array)) return [];
678
- return array.length > 1 ? findValues("unique", array, [key, void 0]).matched : array;
728
+ return array.length > 1 ? findValues(FIND_VALUES_UNIQUE, array, [key, void 0]).matched : array;
679
729
  }
680
730
  function getInterval(value) {
681
731
  return typeof value === "number" && value > 0 ? value : 0;
@@ -1036,24 +1086,64 @@ function isOk(value) {
1036
1086
  function isResult(value) {
1037
1087
  return _isResult(value, true) || _isResult(value, false);
1038
1088
  }
1089
+ /**
1090
+ * Asserts that a condition is true, throwing an error if it is not
1091
+ * @param condition Condition to assert
1092
+ * @param message Error message
1093
+ * @param error Error constructor
1094
+ */
1039
1095
  function assert(condition, message, error) {
1040
1096
  if (!condition()) throw new (error ?? Error)(message);
1041
1097
  }
1042
- assert.condition = (condition, message, error) => {
1098
+ assert.condition = assertCondition;
1099
+ assert.defined = assertDefined;
1100
+ assert.instanceOf = assertInstanceOf;
1101
+ assert.is = assertIs;
1102
+ /**
1103
+ * Creates an asserter that asserts a condition is true, throwing an error if it is not
1104
+ * @param condition Condition to assert
1105
+ * @param message Error message
1106
+ * @param error Error constructor
1107
+ * @returns Asserter
1108
+ */
1109
+ function assertCondition(condition, message, error) {
1043
1110
  return (value) => {
1044
1111
  assert(() => condition(value), message, error);
1045
1112
  };
1046
- };
1047
- assert.instanceOf = (constructor, message, error) => {
1113
+ }
1114
+ /**
1115
+ * Asserts that a value is defined throwing an error if it is not
1116
+ * @param value Value to assert
1117
+ * @param message Error message
1118
+ */
1119
+ function assertDefined(value, message) {
1120
+ assert(() => value != null, message ?? MESSAGE_VALUE_DEFINED);
1121
+ }
1122
+ /**
1123
+ * Creates an asserter that asserts a value is an instance of a constructor, throwing an error if it is not
1124
+ * @param constructor Constructor to check against
1125
+ * @param message Error message
1126
+ * @param error Error constructor
1127
+ * @returns Asserter
1128
+ */
1129
+ function assertInstanceOf(constructor, message, error) {
1048
1130
  return (value) => {
1049
1131
  assert(() => value instanceof constructor, message, error);
1050
1132
  };
1051
- };
1052
- assert.is = (condition, message, error) => {
1133
+ }
1134
+ /**
1135
+ * Creates an asserter that asserts a value is of a specific type, throwing an error if it is not
1136
+ * @param condition Type guard function to check the value
1137
+ * @param message Error message
1138
+ * @param error Error constructor
1139
+ * @returns Asserter
1140
+ */
1141
+ function assertIs(condition, message, error) {
1053
1142
  return (value) => {
1054
1143
  assert(() => condition(value), message, error);
1055
1144
  };
1056
- };
1145
+ }
1146
+ const MESSAGE_VALUE_DEFINED = "Expected value to be defined";
1057
1147
  function asyncFlow(...fns) {
1058
1148
  assertFlowFunctions(fns);
1059
1149
  return (...args) => asyncWork(args.map((value) => {
@@ -1284,6 +1374,27 @@ function findKey(needle, haystack) {
1284
1374
  const index = keys.map((key) => key.toLowerCase()).indexOf(needle.toLowerCase());
1285
1375
  return index > -1 ? keys[index] : needle;
1286
1376
  }
1377
+ function getNestedValue(data, path, ignoreCase) {
1378
+ if (typeof data !== "object" || data === null || typeof path !== "string" || path.trim().length === 0) return {
1379
+ exists: false,
1380
+ value: void 0
1381
+ };
1382
+ const shouldIgnoreCase = ignoreCase === true;
1383
+ const paths = getPaths(path, shouldIgnoreCase);
1384
+ if (typeof paths === "string") return handleValue(data, paths, null, true, shouldIgnoreCase);
1385
+ const { length } = paths;
1386
+ let current = data;
1387
+ for (let index = 0; index < length; index += 1) {
1388
+ const part = paths[index];
1389
+ const handled = handleValue(current, part, null, true, shouldIgnoreCase);
1390
+ if (!handled.exists) return handled;
1391
+ current = handled.value;
1392
+ }
1393
+ return {
1394
+ exists: true,
1395
+ value: current
1396
+ };
1397
+ }
1287
1398
  function getPaths(path, lowercase) {
1288
1399
  const normalized = lowercase ? path.toLowerCase() : path;
1289
1400
  if (!EXPRESSION_NESTED.test(normalized)) return normalized;
@@ -1292,23 +1403,29 @@ function getPaths(path, lowercase) {
1292
1403
  function handleValue(data, path, value, get, ignoreCase) {
1293
1404
  if (typeof data === "object" && data !== null && !ignoreKey(path)) {
1294
1405
  const key = ignoreCase ? findKey(path, data) : path;
1295
- if (get) return data[key];
1406
+ if (get) return {
1407
+ exists: key in data,
1408
+ value: data[key]
1409
+ };
1296
1410
  data[key] = typeof value === "function" ? value(data[key]) : value;
1297
1411
  }
1412
+ if (get) return {
1413
+ exists: false,
1414
+ value: void 0
1415
+ };
1298
1416
  }
1299
1417
  const EXPRESSION_BRACKET = /\[(\w+)\]/g;
1300
1418
  const EXPRESSION_DOTS = /^\.|\.$/g;
1301
1419
  const EXPRESSION_NESTED = /\.|\[\w+\]/;
1302
1420
  function getValue(data, path, ignoreCase) {
1303
- if (typeof data !== "object" || data === null || typeof path !== "string" || path.trim().length === 0) return;
1304
- const shouldIgnoreCase = ignoreCase === true;
1305
- const paths = getPaths(path, shouldIgnoreCase);
1306
- if (typeof paths === "string") return handleValue(data, paths, null, true, shouldIgnoreCase);
1307
- const { length } = paths;
1308
- let index = 0;
1309
- let value = data;
1310
- while (index < length && value != null) value = handleValue(value, paths[index++], null, true, shouldIgnoreCase);
1311
- return value;
1421
+ return getNestedValue(data, path, ignoreCase === true).value;
1422
+ }
1423
+ function hasValue(data, path, ignoreCase) {
1424
+ return getNestedValue(data, path, ignoreCase === true).exists;
1425
+ }
1426
+ hasValue.get = getWithHasValue;
1427
+ function getWithHasValue(data, path, ignoreCase) {
1428
+ return getNestedValue(data, path, ignoreCase === true);
1312
1429
  }
1313
1430
  function setValue(data, path, value, ignoreCase) {
1314
1431
  if (typeof data !== "object" || data === null || typeof path !== "string" || path.trim().length === 0) return data;
@@ -1327,7 +1444,7 @@ function setValue(data, path, value, ignoreCase) {
1327
1444
  handleValue(target, currentPath, value, false, shouldIgnoreCase);
1328
1445
  break;
1329
1446
  }
1330
- let next = handleValue(target, currentPath, null, true, shouldIgnoreCase);
1447
+ let next = handleValue(target, currentPath, null, true, shouldIgnoreCase).value;
1331
1448
  if (typeof next !== "object" || next === null) {
1332
1449
  const nextPath = paths[index + 1];
1333
1450
  if (EXPRESSION_INDEX.test(nextPath)) next = Array.from({ length: Number.parseInt(nextPath, 10) + 1 }, () => void 0);
@@ -1451,45 +1568,6 @@ const REPLACEMENT_CAMEL_CASE = "$1-$2";
1451
1568
  let memoizedCapitalize;
1452
1569
  let memoizedTitleCase;
1453
1570
  /**
1454
- * Check if a string ends with a specified substring
1455
- * @param haystack String to look in
1456
- * @param needle String to look for
1457
- * @param ignoreCase Ignore case when matching? _(defaults to `false`)_
1458
- * @returns `true` if the string ends with the given substring, otherwise `false`
1459
- */
1460
- function endsWith(haystack, needle, ignoreCase) {
1461
- return match("endsWith", haystack, needle, ignoreCase === true);
1462
- }
1463
- /**
1464
- * Check if a string includes a specified substring
1465
- * @param haystack String to look in
1466
- * @param needle String to look for
1467
- * @param ignoreCase Ignore case when matching? _(defaults to `false`)_
1468
- * @returns `true` if the string includes the given substring, otherwise `false`
1469
- */
1470
- function includes(haystack, needle, ignoreCase) {
1471
- return match("includes", haystack, needle, ignoreCase === true);
1472
- }
1473
- function match(type, haystack, needle, ignoreCase) {
1474
- if (typeof haystack !== "string" || typeof needle !== "string") return false;
1475
- matchMemoizers[type] ??= memoize(matchCallback.bind(type));
1476
- return matchMemoizers[type].run(haystack, needle, ignoreCase);
1477
- }
1478
- function matchCallback(haystack, needle, ignoreCase) {
1479
- return (ignoreCase ? haystack.toLocaleLowerCase() : haystack)[this](ignoreCase ? needle.toLocaleLowerCase() : needle);
1480
- }
1481
- /**
1482
- * Check if a string starts with a specified substring
1483
- * @param haystack String to look in
1484
- * @param needle String to look for
1485
- * @param ignoreCase Ignore case when matching? _(defaults to `false`)_
1486
- * @returns `true` if the string starts with the given substring, otherwise `false`
1487
- */
1488
- function startsWith(haystack, needle, ignoreCase) {
1489
- return match("startsWith", haystack, needle, ignoreCase === true);
1490
- }
1491
- const matchMemoizers = {};
1492
- /**
1493
1571
  * Get a new UUID-string _(version 4)_
1494
1572
  * @returns UUID string
1495
1573
  */
@@ -1544,6 +1622,45 @@ function truncate(value, length, suffix) {
1544
1622
  const truncatedLength = length - actualSuffixLength;
1545
1623
  return `${value.slice(0, truncatedLength)}${actualSuffix}`;
1546
1624
  }
1625
+ /**
1626
+ * Check if a string ends with a specified substring
1627
+ * @param haystack String to look in
1628
+ * @param needle String to look for
1629
+ * @param ignoreCase Ignore case when matching? _(defaults to `false`)_
1630
+ * @returns `true` if the string ends with the given substring, otherwise `false`
1631
+ */
1632
+ function endsWith(haystack, needle, ignoreCase) {
1633
+ return match("endsWith", haystack, needle, ignoreCase === true);
1634
+ }
1635
+ /**
1636
+ * Check if a string includes a specified substring
1637
+ * @param haystack String to look in
1638
+ * @param needle String to look for
1639
+ * @param ignoreCase Ignore case when matching? _(defaults to `false`)_
1640
+ * @returns `true` if the string includes the given substring, otherwise `false`
1641
+ */
1642
+ function includes(haystack, needle, ignoreCase) {
1643
+ return match("includes", haystack, needle, ignoreCase === true);
1644
+ }
1645
+ function match(type, haystack, needle, ignoreCase) {
1646
+ if (typeof haystack !== "string" || typeof needle !== "string") return false;
1647
+ matchMemoizers[type] ??= memoize(matchCallback.bind(type));
1648
+ return matchMemoizers[type].run(haystack, needle, ignoreCase);
1649
+ }
1650
+ function matchCallback(haystack, needle, ignoreCase) {
1651
+ return (ignoreCase ? haystack.toLocaleLowerCase() : haystack)[this](ignoreCase ? needle.toLocaleLowerCase() : needle);
1652
+ }
1653
+ /**
1654
+ * Check if a string starts with a specified substring
1655
+ * @param haystack String to look in
1656
+ * @param needle String to look for
1657
+ * @param ignoreCase Ignore case when matching? _(defaults to `false`)_
1658
+ * @returns `true` if the string starts with the given substring, otherwise `false`
1659
+ */
1660
+ function startsWith(haystack, needle, ignoreCase) {
1661
+ return match("startsWith", haystack, needle, ignoreCase === true);
1662
+ }
1663
+ const matchMemoizers = {};
1547
1664
  function getTemplateOptions(input) {
1548
1665
  const options = isPlainObject(input) ? input : {};
1549
1666
  return {
@@ -1800,68 +1917,6 @@ function setChanges(parameters) {
1800
1917
  const diffsLength = diffs.length;
1801
1918
  for (let diffIndex = 0; diffIndex < diffsLength; diffIndex += 1) changes.push(diffs[diffIndex]);
1802
1919
  }
1803
- function getMergeOptions(options) {
1804
- const actual = {
1805
- replaceableObjects: void 0,
1806
- skipNullableAny: false,
1807
- skipNullableInArrays: false
1808
- };
1809
- if (typeof options !== "object" || options == null) return actual;
1810
- actual.replaceableObjects = getReplaceableObjects(options.replaceableObjects);
1811
- actual.skipNullableAny = options.skipNullableAny === true;
1812
- actual.skipNullableInArrays = options.skipNullableInArrays === true;
1813
- return actual;
1814
- }
1815
- function getReplaceableObjects(value) {
1816
- const items = (Array.isArray(value) ? value : [value]).filter((item) => typeof item === "string" || item instanceof RegExp);
1817
- if (items.length > 0) return (name) => items.some((item) => typeof item === "string" ? item === name : item.test(name));
1818
- }
1819
- function handleMerge(values, options) {
1820
- return !Array.isArray(values) || values.length === 0 ? {} : mergeValues(values, options, true);
1821
- }
1822
- /**
1823
- * Merge multiple arrays or objects into a single one
1824
- * @param values Values to merge
1825
- * @param options Merging options
1826
- * @returns Merged value
1827
- */
1828
- function merge(values, options) {
1829
- return handleMerge(values, getMergeOptions(options));
1830
- }
1831
- merge.initialize = initializeMerger;
1832
- /**
1833
- * Create a merger with predefined options
1834
- * @param options Merging options
1835
- * @returns Merger function
1836
- */
1837
- function initializeMerger(options) {
1838
- const actual = getMergeOptions(options);
1839
- return (values) => handleMerge(values, actual);
1840
- }
1841
- function mergeObjects(values, options, prefix) {
1842
- const { length } = values;
1843
- const isArray = values.every(Array.isArray);
1844
- const merged = isArray ? [] : {};
1845
- for (let outerIndex = 0; outerIndex < length; outerIndex += 1) {
1846
- const item = values[outerIndex];
1847
- const keys = Object.keys(item);
1848
- const size = keys.length;
1849
- for (let innerIndex = 0; innerIndex < size; innerIndex += 1) {
1850
- const key = keys[innerIndex];
1851
- const full = join([prefix, key], ".");
1852
- const next = item[key];
1853
- const previous = merged[key];
1854
- if (next == null && (options.skipNullableAny || isArray && options.skipNullableInArrays)) continue;
1855
- if (isArrayOrPlainObject(next) && isArrayOrPlainObject(previous) && !(options.replaceableObjects?.(full) ?? false)) merged[key] = mergeValues([previous, next], options, false, full);
1856
- else merged[key] = next;
1857
- }
1858
- }
1859
- return merged;
1860
- }
1861
- function mergeValues(values, options, validate, prefix) {
1862
- const actual = validate ? values.filter(isArrayOrPlainObject) : values;
1863
- return actual.length > 1 ? mergeObjects(actual, options, prefix) : actual[0] ?? {};
1864
- }
1865
1920
  function partial(value, providedKeys, omit) {
1866
1921
  if (typeof value !== "object" || value === null) return {};
1867
1922
  const keys = omit ? Object.keys(value) : Array.isArray(providedKeys) ? providedKeys : [];
@@ -1958,6 +2013,62 @@ function unsmush(value) {
1958
2013
  }
1959
2014
  return unsmushed;
1960
2015
  }
2016
+ function getMergeOptions(options) {
2017
+ const actual = {
2018
+ replaceableObjects: void 0,
2019
+ skipNullableAny: false,
2020
+ skipNullableInArrays: false
2021
+ };
2022
+ if (typeof options !== "object" || options == null) return actual;
2023
+ actual.replaceableObjects = getReplaceableObjects(options.replaceableObjects);
2024
+ actual.skipNullableAny = options.skipNullableAny === true;
2025
+ actual.skipNullableInArrays = options.skipNullableInArrays === true;
2026
+ return actual;
2027
+ }
2028
+ function getReplaceableObjects(value) {
2029
+ const items = (Array.isArray(value) ? value : [value]).filter((item) => typeof item === "string" || item instanceof RegExp);
2030
+ if (items.length > 0) return (name) => items.some((item) => typeof item === "string" ? item === name : item.test(name));
2031
+ }
2032
+ function handleMerge(values, options) {
2033
+ return !Array.isArray(values) || values.length === 0 ? {} : mergeValues(values, options, true);
2034
+ }
2035
+ function merge(values, options) {
2036
+ return handleMerge(values, getMergeOptions(options));
2037
+ }
2038
+ merge.initialize = initializeMerger;
2039
+ /**
2040
+ * Create a merger with predefined options
2041
+ * @param options Merging options
2042
+ * @returns Merger function
2043
+ */
2044
+ function initializeMerger(options) {
2045
+ const actual = getMergeOptions(options);
2046
+ return (values) => handleMerge(values, actual);
2047
+ }
2048
+ function mergeObjects(values, options, prefix) {
2049
+ const { length } = values;
2050
+ const isArray = values.every(Array.isArray);
2051
+ const merged = isArray ? [] : {};
2052
+ for (let outerIndex = 0; outerIndex < length; outerIndex += 1) {
2053
+ const item = values[outerIndex];
2054
+ const keys = Object.keys(item);
2055
+ const size = keys.length;
2056
+ for (let innerIndex = 0; innerIndex < size; innerIndex += 1) {
2057
+ const key = keys[innerIndex];
2058
+ const full = join([prefix, key], ".");
2059
+ const next = item[key];
2060
+ const previous = merged[key];
2061
+ if (next == null && (options.skipNullableAny || isArray && options.skipNullableInArrays)) continue;
2062
+ if (isArrayOrPlainObject(next) && isArrayOrPlainObject(previous) && !(options.replaceableObjects?.(full) ?? false)) merged[key] = mergeValues([previous, next], options, false, full);
2063
+ else merged[key] = next;
2064
+ }
2065
+ }
2066
+ return merged;
2067
+ }
2068
+ function mergeValues(values, options, validate, prefix) {
2069
+ const actual = validate ? values.filter(isArrayOrPlainObject) : values;
2070
+ return actual.length > 1 ? mergeObjects(actual, options, prefix) : actual[0] ?? {};
2071
+ }
1961
2072
  var Beacon = class {
1962
2073
  #options;
1963
2074
  #state;
@@ -2796,15 +2907,6 @@ function isEmpty(value) {
2796
2907
  return true;
2797
2908
  }
2798
2909
  /**
2799
- * Is the value an instance of the constructor?
2800
- * @param constructor Class constructor
2801
- * @param value Value to check
2802
- * @returns `true` if the value is an instance of the constructor, otherwise `false`
2803
- */
2804
- function isInstanceOf(constructor, value) {
2805
- return isConstructor(constructor) && value instanceof constructor;
2806
- }
2807
- /**
2808
2910
  * Is the value not `undefined` or `null`?
2809
2911
  * @param value Value to check
2810
2912
  * @returns `true` if the value is not `undefined` or `null`, otherwise `false`
@@ -3010,12 +3112,12 @@ function floor(value, decimals) {
3010
3112
  function median(array, key) {
3011
3113
  let length = Array.isArray(array) ? array.length : 0;
3012
3114
  if (!Array.isArray(array) || length === 0) return NaN;
3013
- if (length === 1) return isNumber(array[0]) ? array[0] : NaN;
3014
3115
  let values = array;
3015
3116
  const callback = getAggregateCallback(key);
3016
3117
  if (callback != null) values = array.map((item, index) => callback(item, index, array));
3017
3118
  const numbers = values.filter(isNumber).sort((first, second) => first - second);
3018
3119
  length = numbers.length;
3120
+ if (length === 1) return numbers[0];
3019
3121
  if (length % 2 === 0) {
3020
3122
  const first = length / 2 - 1;
3021
3123
  const second = length / 2;
@@ -3772,4 +3874,4 @@ var SizedSet = class extends Set {
3772
3874
  }
3773
3875
  }
3774
3876
  };
3775
- export { CancelablePromise, PromiseTimeoutError, QueueError, RetryError, SizedMap, SizedSet, attempt, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, ceil, chunk, clamp, clone, compact, compare, count, debounce, delay, diff, endsWith, equal, error, exists, filter, find, flatten, floor, flow, toResult as fromPromise, toResult, fromQuery, toPromise as fromResult, toPromise, getArray, getColor, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getString, getUuid, getValue, groupBy, hexToHsl, hexToHsla, hexToRgb, hexToRgba, hslToHex, hslToRgb, hslToRgba, ignoreKey, includes, indexOf, insert, isArrayOrPlainObject, isColor, isConstructor, isEmpty, isError, isFulfilled, isHexColor, isHslColor, isHslLike, isHslaColor, isInstanceOf, isKey, isNonNullable, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isOk, isPlainObject, isPrimitive, isRejected, isResult, isRgbColor, isRgbLike, isRgbaColor, isTypedArray, join, kebabCase, logger, lowerCase, max, median, memoize, merge, min, noop, ok, omit, parse, partition, pascalCase, pick, pipe, promises, push, queue, range, retry, rgbToHex, rgbToHsl, rgbToHsla, round, select, setValue, shuffle, smush, snakeCase, sort, splice, startsWith, sum, template, throttle, timed, times, titleCase, toMap, toQuery, toRecord, toSet, toggle, trim, truncate, tryDecode, tryEncode, unique, unsmush, unwrap, update, upperCase, words };
3877
+ export { CancelablePromise, PromiseTimeoutError, QueueError, RetryError, SizedMap, SizedSet, attempt, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, ceil, chunk, clamp, clone, compact, compare, count, debounce, delay, diff, difference, endsWith, equal, error, exists, filter, find, flatten, floor, flow, toResult as fromPromise, toResult, fromQuery, toPromise as fromResult, toPromise, getArray, getColor, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getString, getUuid, getValue, groupBy, hasValue, hexToHsl, hexToHsla, hexToRgb, hexToRgba, hslToHex, hslToRgb, hslToRgba, ignoreKey, includes, indexOf, insert, intersection, isArrayOrPlainObject, isColor, isConstructor, isEmpty, isError, isFulfilled, isHexColor, isHslColor, isHslLike, isHslaColor, isInstanceOf, isKey, isNonNullable, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isOk, isPlainObject, isPrimitive, isRejected, isResult, isRgbColor, isRgbLike, isRgbaColor, isTypedArray, join, kebabCase, logger, lowerCase, max, median, memoize, merge, min, noop, ok, omit, parse, partition, pascalCase, pick, pipe, promises, push, queue, range, retry, rgbToHex, rgbToHsl, rgbToHsla, round, select, setValue, shuffle, smush, snakeCase, sort, splice, startsWith, sum, template, throttle, timed, times, titleCase, toMap, toQuery, toRecord, toSet, toggle, trim, truncate, tryDecode, tryEncode, union, unique, unsmush, unwrap, update, upperCase, words };