@oscarpalmer/atoms 0.141.2 → 0.143.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 (61) hide show
  1. package/dist/atoms.full.js +185 -72
  2. package/dist/color/misc/is.js +6 -6
  3. package/dist/function/memoize.js +1 -1
  4. package/dist/index.js +7 -6
  5. package/dist/internal/math/aggregate.js +12 -8
  6. package/dist/internal/number.js +1 -1
  7. package/dist/internal/value/partial.js +14 -0
  8. package/dist/is.js +11 -3
  9. package/dist/math.js +21 -5
  10. package/dist/promise.js +107 -36
  11. package/dist/result.js +7 -5
  12. package/dist/sized/map.js +1 -1
  13. package/dist/sized/set.js +2 -2
  14. package/dist/value/misc.js +3 -2
  15. package/dist/value/omit.js +11 -0
  16. package/dist/value/pick.js +11 -0
  17. package/package.json +5 -5
  18. package/src/color/misc/is.ts +6 -6
  19. package/src/function/debounce.ts +2 -2
  20. package/src/function/memoize.ts +1 -1
  21. package/src/function/throttle.ts +2 -2
  22. package/src/index.ts +2 -1
  23. package/src/internal/function/limiter.ts +3 -3
  24. package/src/internal/math/aggregate.ts +19 -10
  25. package/src/internal/number.ts +1 -1
  26. package/src/internal/value/partial.ts +46 -0
  27. package/src/is.ts +11 -2
  28. package/src/math.ts +67 -9
  29. package/src/models.ts +2 -2
  30. package/src/promise.ts +249 -57
  31. package/src/random.ts +2 -2
  32. package/src/result.ts +31 -11
  33. package/src/sized/map.ts +1 -1
  34. package/src/sized/set.ts +2 -2
  35. package/src/value/get-set.ts +1 -1
  36. package/src/value/merge.ts +1 -1
  37. package/src/value/misc.ts +2 -1
  38. package/src/value/omit.ts +19 -0
  39. package/src/value/pick.ts +19 -0
  40. package/types/color/misc/is.d.ts +6 -6
  41. package/types/function/debounce.d.ts +2 -2
  42. package/types/function/memoize.d.ts +1 -1
  43. package/types/function/throttle.d.ts +2 -2
  44. package/types/index.d.ts +2 -1
  45. package/types/internal/function/limiter.d.ts +2 -2
  46. package/types/internal/math/aggregate.d.ts +1 -0
  47. package/types/internal/number.d.ts +1 -1
  48. package/types/internal/value/partial.d.ts +2 -0
  49. package/types/is.d.ts +8 -2
  50. package/types/math.d.ts +20 -0
  51. package/types/models.d.ts +2 -2
  52. package/types/promise.d.ts +68 -11
  53. package/types/random.d.ts +2 -2
  54. package/types/result.d.ts +21 -6
  55. package/types/sized/map.d.ts +1 -1
  56. package/types/sized/set.d.ts +2 -2
  57. package/types/value/misc.d.ts +2 -1
  58. package/types/value/omit.d.ts +8 -0
  59. package/types/value/{partial.d.ts → pick.d.ts} +1 -1
  60. package/dist/value/partial.js +0 -17
  61. package/src/value/partial.ts +0 -39
@@ -273,24 +273,27 @@ function aggregate(type, array, key) {
273
273
  value: NaN
274
274
  };
275
275
  const aggregator = aggregators[type];
276
- const isCallback = typeof key === "function";
276
+ const callback = getAggregateCallback(key);
277
277
  let counted = 0;
278
278
  let aggregated = NaN;
279
279
  let notNumber = true;
280
280
  for (let index = 0; index < length; index += 1) {
281
281
  const item = array[index];
282
- const value = isCallback ? key(item, index, array) : item[key] ?? item;
283
- if (typeof value === "number" && !Number.isNaN(value)) {
284
- aggregated = aggregator(aggregated, value, notNumber);
285
- counted += 1;
286
- notNumber = false;
287
- }
282
+ const value = callback == null ? item : callback(item, index, array);
283
+ if (!isNumber(value)) continue;
284
+ aggregated = aggregator(aggregated, value, notNumber);
285
+ counted += 1;
286
+ notNumber = false;
288
287
  }
289
288
  return {
290
289
  count: counted,
291
290
  value: aggregated
292
291
  };
293
292
  }
293
+ function getAggregateCallback(key) {
294
+ if (key == null) return;
295
+ return typeof key === "function" ? key : (item) => item[key];
296
+ }
294
297
  function max(array, key) {
295
298
  return getAggregated("max", array, key);
296
299
  }
@@ -665,7 +668,7 @@ function clamp(value, minimum, maximum, loop) {
665
668
  /**
666
669
  * Get the number value from an unknown value _(based on Lodash)_
667
670
  * @param value Original value
668
- * @returns The value as a number, or `NaN` if the value is unable to be parsed
671
+ * @returns Original value as a number, or `NaN` if the value is unable to be parsed
669
672
  */
670
673
  function getNumber(value) {
671
674
  if (typeof value === "number") return value;
@@ -699,7 +702,7 @@ const MAXIMUM_DEFAULT = 1048576;
699
702
  /**
700
703
  * A Map with a maximum size
701
704
  *
702
- * Behaviour is similar to a _LRU_-cache, where the least recently used entries are removed
705
+ * Behavior is similar to a _LRU_-cache, where the least recently used entries are removed
703
706
  */
704
707
  var SizedMap = class extends Map {
705
708
  /**
@@ -795,7 +798,7 @@ var Memoized = class {
795
798
  /**
796
799
  * Get a result from the cache
797
800
  * @param key Key to get
798
- * @returns The cached result or `undefined` if it does not exist
801
+ * @returns Cached result or `undefined` if it does not exist
799
802
  */
800
803
  get(key) {
801
804
  return this.#state.cache?.get(key);
@@ -1637,22 +1640,37 @@ function mergeValues(values, options, validate, prefix) {
1637
1640
  const actual = validate ? values.filter(isArrayOrPlainObject) : values;
1638
1641
  return actual.length > 1 ? mergeObjects(actual, options, prefix) : actual[0] ?? {};
1639
1642
  }
1640
- /**
1641
- * Create a new object with only the specified keys
1642
- * @param value Original object
1643
- * @param keys Keys to use
1644
- * @returns Partial object with only the specified keys
1645
- */
1646
- function partial(value, keys) {
1647
- if (typeof value !== "object" || value === null || Object.keys(value).length === 0 || !Array.isArray(keys) || keys.length === 0) return {};
1643
+ function partial(value, providedKeys, omit) {
1644
+ if (typeof value !== "object" || value === null) return {};
1645
+ const keys = omit ? Object.keys(value) : Array.isArray(providedKeys) ? providedKeys : [];
1648
1646
  const { length } = keys;
1647
+ if (length === 0) return omit ? value : {};
1649
1648
  const partials = {};
1650
1649
  for (let index = 0; index < length; index += 1) {
1651
1650
  const key = keys[index];
1652
- if (key in value) partials[key] = value[key];
1651
+ if (!(key in value)) continue;
1652
+ if (omit ? !providedKeys.includes(key) : true) partials[key] = value[key];
1653
1653
  }
1654
1654
  return partials;
1655
1655
  }
1656
+ /**
1657
+ * Create a new object without the specified keys
1658
+ * @param value Original object
1659
+ * @param keys Keys to omit
1660
+ * @returns Partial object without the specified keys
1661
+ */
1662
+ function omit(value, keys) {
1663
+ return partial(value, keys, true);
1664
+ }
1665
+ /**
1666
+ * Create a new object with only the specified keys
1667
+ * @param value Original object
1668
+ * @param keys Keys to use
1669
+ * @returns Partial object with only the specified keys
1670
+ */
1671
+ function pick(value, keys) {
1672
+ return partial(value, keys, false);
1673
+ }
1656
1674
  function flattenObject(value, depth, smushed, prefix) {
1657
1675
  if (depth >= MAX_DEPTH) return {};
1658
1676
  if (smushed.has(value)) return smushed.get(value);
@@ -1983,7 +2001,7 @@ function isBytey(value) {
1983
2001
  }
1984
2002
  /**
1985
2003
  * Is the value a Color?
1986
- * @param value The value to check
2004
+ * @param value Value to check
1987
2005
  * @returns `true` if the value is a Color, otherwise `false`
1988
2006
  */
1989
2007
  function isColor(value) {
@@ -2005,7 +2023,7 @@ function isDegree(value) {
2005
2023
  }
2006
2024
  /**
2007
2025
  * Is the value a hex color?
2008
- * @param value The value to check
2026
+ * @param value Value to check
2009
2027
  * @param alpha Allow alpha channel? _(defaults to `true`)_
2010
2028
  * @returns `true` if the value is a hex color, otherwise `false`
2011
2029
  */
@@ -2017,7 +2035,7 @@ function isHexColor(value, alpha) {
2017
2035
  }
2018
2036
  /**
2019
2037
  * Is the value an HSLA color?
2020
- * @param value The value to check
2038
+ * @param value Value to check
2021
2039
  * @returns `true` if the value is an HSLA color, otherwise `false`
2022
2040
  */
2023
2041
  function isHslaColor(value) {
@@ -2025,7 +2043,7 @@ function isHslaColor(value) {
2025
2043
  }
2026
2044
  /**
2027
2045
  * Is the value an HSL color?
2028
- * @param value The value to check
2046
+ * @param value Value to check
2029
2047
  * @returns `true` if the value is an HSL color, otherwise `false`
2030
2048
  */
2031
2049
  function isHslColor(value) {
@@ -2036,7 +2054,7 @@ function isHslLike(value) {
2036
2054
  }
2037
2055
  /**
2038
2056
  * Is the value an RGBA color?
2039
- * @param value The value to check
2057
+ * @param value Value to check
2040
2058
  * @returns `true` if the value is an RGBA color, otherwise `false`
2041
2059
  */
2042
2060
  function isRgbaColor(value) {
@@ -2044,7 +2062,7 @@ function isRgbaColor(value) {
2044
2062
  }
2045
2063
  /**
2046
2064
  * Is the value an RGB color?
2047
- * @param value The value to check
2065
+ * @param value Value to check
2048
2066
  * @returns `true` if the value is an RGB color, otherwise `false`
2049
2067
  */
2050
2068
  function isRgbColor(value) {
@@ -2544,8 +2562,8 @@ function getColor(value) {
2544
2562
  }
2545
2563
  /**
2546
2564
  * Is the value empty, or only containing `null` or `undefined` values?
2547
- * @param value Object to check
2548
- * @returns `true` if the object is considered empty, otherwise `false`
2565
+ * @param value Value to check
2566
+ * @returns `true` if the value is considered empty, otherwise `false`
2549
2567
  */
2550
2568
  function isEmpty(value) {
2551
2569
  if (value == null) return true;
@@ -2556,6 +2574,14 @@ function isEmpty(value) {
2556
2574
  return true;
2557
2575
  }
2558
2576
  /**
2577
+ * Is the value not `undefined` or `null`?
2578
+ * @param value Value to check
2579
+ * @returns `true` if the value is not `undefined` or `null`, otherwise `false`
2580
+ */
2581
+ function isNonNullable(value) {
2582
+ return value != null;
2583
+ }
2584
+ /**
2559
2585
  * Is the value `undefined` or `null`?
2560
2586
  * @param value Value to check
2561
2587
  * @returns `true` if the value is `undefined` or `null`, otherwise `false`
@@ -2723,9 +2749,8 @@ function average(array, key) {
2723
2749
  function count(array, key, value) {
2724
2750
  if (!Array.isArray(array)) return NaN;
2725
2751
  const { length } = array;
2726
- if (key == null) return length;
2727
- if (typeof key !== "string" && typeof key !== "function") return NaN;
2728
- const callback = typeof key === "function" ? key : (item) => item[key];
2752
+ const callback = getAggregateCallback(key);
2753
+ if (callback == null) return length;
2729
2754
  let counted = 0;
2730
2755
  for (let index = 0; index < length; index += 1) {
2731
2756
  const item = array[index];
@@ -2733,6 +2758,22 @@ function count(array, key, value) {
2733
2758
  }
2734
2759
  return counted;
2735
2760
  }
2761
+ function median(array, key) {
2762
+ let length = Array.isArray(array) ? array.length : 0;
2763
+ if (!Array.isArray(array) || length === 0) return NaN;
2764
+ if (length === 1) return isNumber(array[0]) ? array[0] : NaN;
2765
+ let values = array;
2766
+ const callback = getAggregateCallback(key);
2767
+ if (callback != null) values = array.map((item, index) => callback(item, index, array));
2768
+ const numbers = values.filter(isNumber).sort((first, second) => first - second);
2769
+ length = numbers.length;
2770
+ if (length % 2 === 0) {
2771
+ const first = length / 2 - 1;
2772
+ const second = length / 2;
2773
+ return (numbers[first] + numbers[second]) / 2;
2774
+ }
2775
+ return numbers[Math.floor(length / 2)];
2776
+ }
2736
2777
  function min(array, key) {
2737
2778
  return getAggregated("min", array, key);
2738
2779
  }
@@ -2751,12 +2792,38 @@ function round(value, decimals) {
2751
2792
  function sum(array, key) {
2752
2793
  return getAggregated("sum", array, key);
2753
2794
  }
2795
+ var CancelablePromise = class extends Promise {
2796
+ #rejector;
2797
+ constructor(executor) {
2798
+ let rejector;
2799
+ super((resolve, reject) => {
2800
+ rejector = reject;
2801
+ executor(resolve, reject);
2802
+ });
2803
+ this.#rejector = rejector;
2804
+ }
2805
+ /**
2806
+ * Cancel the promise, rejecting it with an optional reason
2807
+ * @param reason Optional reason for canceling the promise
2808
+ */
2809
+ cancel(reason) {
2810
+ this.#rejector(reason);
2811
+ }
2812
+ };
2754
2813
  var PromiseTimeoutError = class extends Error {
2755
2814
  constructor() {
2756
2815
  super(MESSAGE_TIMEOUT);
2757
2816
  this.name = ERROR_NAME$1;
2758
2817
  }
2759
2818
  };
2819
+ /**
2820
+ * Create a cancelable promise
2821
+ * @param executor Executor function for the promise
2822
+ * @returns Cancelable promise
2823
+ */
2824
+ function cancelable(executor) {
2825
+ return new CancelablePromise(executor);
2826
+ }
2760
2827
  function delay(options) {
2761
2828
  const { signal, time } = getPromiseOptions(options);
2762
2829
  if (signal?.aborted ?? false) return Promise.reject(signal.reason);
@@ -2764,25 +2831,25 @@ function delay(options) {
2764
2831
  clearTimeout(timeout);
2765
2832
  rejector(signal.reason);
2766
2833
  }
2767
- signal?.addEventListener("abort", abort, abortOptions$1);
2834
+ signal?.addEventListener("abort", abort, ABORT_OPTIONS);
2768
2835
  let rejector;
2769
2836
  let timeout;
2770
2837
  return new Promise((resolve, reject) => {
2771
2838
  rejector = reject;
2772
2839
  timeout = setTimeout(() => {
2773
- signal?.removeEventListener("abort", abort);
2774
- resolve();
2840
+ settlePromise(abort, resolve, void 0, signal);
2775
2841
  }, time);
2776
2842
  });
2777
2843
  }
2778
- function getBooleanOrDefault$1(value, defaultValue) {
2779
- return typeof value === "boolean" ? value : defaultValue;
2780
- }
2781
2844
  function getNumberOrDefault$1(value) {
2782
2845
  return typeof value === "number" && value > 0 ? value : 0;
2783
2846
  }
2784
2847
  function getPromiseOptions(input) {
2785
2848
  if (typeof input === "number") return { time: getNumberOrDefault$1(input) };
2849
+ if (input instanceof AbortSignal) return {
2850
+ signal: input,
2851
+ time: 0
2852
+ };
2786
2853
  const options = typeof input === "object" && input !== null ? input : {};
2787
2854
  return {
2788
2855
  signal: options.signal instanceof AbortSignal ? options.signal : void 0,
@@ -2790,32 +2857,54 @@ function getPromiseOptions(input) {
2790
2857
  };
2791
2858
  }
2792
2859
  function getPromisesOptions(input) {
2793
- if (typeof input === "boolean") return { eager: input };
2860
+ if (typeof input === "string") return { strategy: getStrategyOrDefault(input) };
2794
2861
  if (input instanceof AbortSignal) return {
2795
- eager: false,
2796
- signal: input
2862
+ signal: input,
2863
+ strategy: DEFAULT_STRATEGY
2797
2864
  };
2798
2865
  const options = typeof input === "object" && input !== null ? input : {};
2799
2866
  return {
2800
- eager: getBooleanOrDefault$1(options.eager, false),
2801
- signal: options.signal instanceof AbortSignal ? options.signal : void 0
2867
+ signal: options.signal instanceof AbortSignal ? options.signal : void 0,
2868
+ strategy: getStrategyOrDefault(options.strategy)
2802
2869
  };
2803
2870
  }
2871
+ function getStrategyOrDefault(value) {
2872
+ return strategies.has(value) ? value : DEFAULT_STRATEGY;
2873
+ }
2874
+ async function getTimed(promise, time, signal) {
2875
+ function abort() {
2876
+ clearTimeout(timeout);
2877
+ rejector(signal.reason);
2878
+ }
2879
+ signal?.addEventListener(EVENT_NAME$1, abort, ABORT_OPTIONS);
2880
+ let rejector;
2881
+ let timeout;
2882
+ return Promise.race([promise, new Promise((_, reject) => {
2883
+ rejector = reject;
2884
+ timeout = setTimeout(() => {
2885
+ settlePromise(abort, reject, new PromiseTimeoutError(), signal);
2886
+ }, time);
2887
+ })]).then((value) => {
2888
+ clearTimeout(timeout);
2889
+ signal?.removeEventListener(EVENT_NAME$1, abort);
2890
+ return value;
2891
+ });
2892
+ }
2804
2893
  function handleResult(status, parameters) {
2805
- const { data, eager, handlers, index, signal, value } = parameters;
2894
+ const { abort, complete, data, handlers, index, signal, value } = parameters;
2806
2895
  if (signal?.aborted ?? false) return;
2807
- if (eager && status === TYPE_REJECTED) {
2808
- handlers.reject(value);
2896
+ if (!complete && status === TYPE_REJECTED) {
2897
+ settlePromise(abort, handlers.reject, value, signal);
2809
2898
  return;
2810
2899
  }
2811
- data.result[index] = eager ? value : status === TYPE_FULFILLED ? {
2900
+ data.result[index] = !complete ? value : status === TYPE_FULFILLED ? {
2812
2901
  status,
2813
2902
  value
2814
2903
  } : {
2815
2904
  status,
2816
2905
  reason: value
2817
2906
  };
2818
- if (index === data.last) handlers.resolve(data.result);
2907
+ if (index === data.last) settlePromise(abort, handlers.resolve, data.result, signal);
2819
2908
  }
2820
2909
  /**
2821
2910
  * Is the value a fulfilled promise result?
@@ -2837,15 +2926,17 @@ function isType(value, type) {
2837
2926
  return typeof value === "object" && value !== null && value.status === type;
2838
2927
  }
2839
2928
  async function promises(items, options) {
2929
+ const { signal, strategy } = getPromisesOptions(options);
2930
+ if (signal?.aborted ?? false) return Promise.reject(signal.reason);
2931
+ if (!Array.isArray(items)) return Promise.reject(new TypeError(MESSAGE_EXPECTATION_PROMISES));
2840
2932
  const actual = items.filter((item) => item instanceof Promise);
2841
2933
  const { length } = actual;
2842
- const { eager, signal } = getPromisesOptions(options);
2843
- if (signal?.aborted ?? false) return Promise.reject(signal.reason);
2844
2934
  if (length === 0) return actual;
2935
+ const complete = strategy === DEFAULT_STRATEGY;
2845
2936
  function abort() {
2846
2937
  handlers.reject(signal.reason);
2847
2938
  }
2848
- signal?.addEventListener("abort", abort, abortOptions$1);
2939
+ signal?.addEventListener("abort", abort, ABORT_OPTIONS);
2849
2940
  const data = {
2850
2941
  last: length - 1,
2851
2942
  result: []
@@ -2857,15 +2948,17 @@ async function promises(items, options) {
2857
2948
  resolve
2858
2949
  };
2859
2950
  for (let index = 0; index < length; index += 1) actual[index].then((value) => handleResult(TYPE_FULFILLED, {
2951
+ abort,
2952
+ complete,
2860
2953
  data,
2861
- eager,
2862
2954
  handlers,
2863
2955
  index,
2864
2956
  signal,
2865
2957
  value
2866
2958
  })).catch((reason) => handleResult(TYPE_REJECTED, {
2959
+ abort,
2960
+ complete,
2867
2961
  data,
2868
- eager,
2869
2962
  handlers,
2870
2963
  index,
2871
2964
  signal,
@@ -2873,31 +2966,50 @@ async function promises(items, options) {
2873
2966
  }));
2874
2967
  });
2875
2968
  }
2876
- function timed(promise, options) {
2877
- if (!(promise instanceof Promise)) throw new TypeError(MESSAGE_EXPECTATION);
2969
+ function settlePromise(aborter, settler, value, signal) {
2970
+ signal?.removeEventListener(EVENT_NAME$1, aborter);
2971
+ settler(value);
2972
+ }
2973
+ async function timed(promise, options) {
2974
+ if (!(promise instanceof Promise)) return Promise.reject(new TypeError(MESSAGE_EXPECTATION_TIMED));
2975
+ const { signal, time } = getPromiseOptions(options);
2976
+ if (signal?.aborted ?? false) return Promise.reject(signal.reason);
2977
+ return time > 0 ? getTimed(promise, time, signal) : promise;
2978
+ }
2979
+ async function attemptPromise(value, options) {
2980
+ const isFunction = typeof value === "function";
2981
+ if (!isFunction && !(value instanceof Promise)) return Promise.reject(new TypeError(MESSAGE_EXPECTATION_ATTEMPT));
2878
2982
  const { signal, time } = getPromiseOptions(options);
2879
2983
  if (signal?.aborted ?? false) return Promise.reject(signal.reason);
2880
- if (time <= 0) return promise;
2881
2984
  function abort() {
2882
- clearTimeout(timeout);
2883
2985
  rejector(signal.reason);
2884
2986
  }
2885
- signal?.addEventListener(EVENT_NAME$1, abort, abortOptions$1);
2987
+ async function handler(resolve, reject) {
2988
+ try {
2989
+ let result = isFunction ? value() : await value;
2990
+ if (result instanceof Promise) result = await result;
2991
+ settlePromise(abort, resolve, result, signal);
2992
+ } catch (error) {
2993
+ settlePromise(abort, reject, error, signal);
2994
+ }
2995
+ }
2886
2996
  let rejector;
2887
- let timeout;
2888
- return Promise.race([promise, new Promise((_, reject) => {
2997
+ signal?.addEventListener(EVENT_NAME$1, abort, ABORT_OPTIONS);
2998
+ const promise = new Promise((resolve, reject) => {
2889
2999
  rejector = reject;
2890
- timeout = setTimeout(() => {
2891
- signal?.removeEventListener(EVENT_NAME$1, abort);
2892
- reject(new PromiseTimeoutError());
2893
- }, time);
2894
- })]);
3000
+ handler(resolve, reject);
3001
+ });
3002
+ return time > 0 ? getTimed(promise, time, signal) : promise;
2895
3003
  }
2896
- const abortOptions$1 = { once: true };
3004
+ const ABORT_OPTIONS = { once: true };
3005
+ const DEFAULT_STRATEGY = "complete";
2897
3006
  const ERROR_NAME$1 = "PromiseTimeoutError";
2898
3007
  const EVENT_NAME$1 = "abort";
2899
- const MESSAGE_EXPECTATION = "Timed function expected a Promise";
3008
+ const MESSAGE_EXPECTATION_ATTEMPT = "Attempt expected a function or a promise";
3009
+ const MESSAGE_EXPECTATION_PROMISES = "Promises expected an array of promises";
3010
+ const MESSAGE_EXPECTATION_TIMED = "Timed function expected a Promise";
2900
3011
  const MESSAGE_TIMEOUT = "Promise timed out";
3012
+ const strategies = new Set(["complete", "first"]);
2901
3013
  const TYPE_FULFILLED = "fulfilled";
2902
3014
  const TYPE_REJECTED = "rejected";
2903
3015
  /**
@@ -3272,17 +3384,18 @@ function ok(value) {
3272
3384
  value
3273
3385
  };
3274
3386
  }
3275
- function result(callback, err) {
3387
+ function attempt(callback, err) {
3276
3388
  try {
3277
3389
  return ok(callback());
3278
3390
  } catch (thrown) {
3279
3391
  return getError(err ?? thrown, err == null ? void 0 : thrown);
3280
3392
  }
3281
3393
  }
3282
- result.async = asyncResult;
3283
- async function asyncResult(callback, err) {
3394
+ attempt.async = asyncAttempt;
3395
+ attempt.promise = attemptPromise;
3396
+ async function asyncAttempt(value, err) {
3284
3397
  try {
3285
- return ok(await callback());
3398
+ return ok(await (typeof value === "function" ? value() : value));
3286
3399
  } catch (thrown) {
3287
3400
  return getError(err ?? thrown, err == null ? void 0 : thrown);
3288
3401
  }
@@ -3292,7 +3405,7 @@ function unwrap(value, defaultValue) {
3292
3405
  }
3293
3406
  /**
3294
3407
  * - A Set with a maximum size
3295
- * - Behaviour is similar to a _LRU_-cache, where the oldest values are removed
3408
+ * - Behavior is similar to a _LRU_-cache, where the oldest values are removed
3296
3409
  */
3297
3410
  var SizedSet = class extends Set {
3298
3411
  /**
@@ -3330,7 +3443,7 @@ var SizedSet = class extends Set {
3330
3443
  * Get a value from the SizedSet, if it exists _(and move it to the end)_
3331
3444
  * @param value Value to get from the SizedSet
3332
3445
  * @param update Update the value's position in the SizedSet? _(defaults to `false`)_
3333
- * @returns The value if it exists, otherwise `undefined`
3446
+ * @returns Found value if it exists, otherwise `undefined`
3334
3447
  */
3335
3448
  get(value, update) {
3336
3449
  if (this.has(value)) {
@@ -3342,4 +3455,4 @@ var SizedSet = class extends Set {
3342
3455
  }
3343
3456
  }
3344
3457
  };
3345
- export { frame_rate_default as FRAME_RATE_MS, PromiseTimeoutError, QueueError, SizedMap, SizedSet, average, beacon, between, camelCase, capitalize, chunk, clamp, clone, compact, compare, count, debounce, delay, diff, endsWith, equal, error, exists, filter, find, flatten, fromQuery, 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, isKey, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isOk, isPlainObject, isPrimitive, isRejected, isResult, isRgbColor, isRgbLike, isRgbaColor, isTypedArray, join, kebabCase, logger, lowerCase, max, memoize, merge, min, noop, ok, parse, partial, pascalCase, promises, push, queue, result, rgbToHex, rgbToHsl, rgbToHsla, round, setValue, shuffle, smush, snakeCase, sort, splice, startsWith, sum, template, throttle, timed, titleCase, toMap, toQuery, toRecord, toSet, trim, truncate, tryDecode, tryEncode, unique, unsmush, unwrap, upperCase, words };
3458
+ export { CancelablePromise, frame_rate_default as FRAME_RATE_MS, PromiseTimeoutError, QueueError, SizedMap, SizedSet, attempt, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, chunk, clamp, clone, compact, compare, count, debounce, delay, diff, endsWith, equal, error, exists, filter, find, flatten, fromQuery, 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, 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, pascalCase, pick, promises, push, queue, rgbToHex, rgbToHsl, rgbToHsla, round, setValue, shuffle, smush, snakeCase, sort, splice, startsWith, sum, template, throttle, timed, titleCase, toMap, toQuery, toRecord, toSet, trim, truncate, tryDecode, tryEncode, unique, unsmush, unwrap, upperCase, words };
@@ -11,7 +11,7 @@ function isBytey(value) {
11
11
  }
12
12
  /**
13
13
  * Is the value a Color?
14
- * @param value The value to check
14
+ * @param value Value to check
15
15
  * @returns `true` if the value is a Color, otherwise `false`
16
16
  */
17
17
  function isColor(value) {
@@ -33,7 +33,7 @@ function isDegree(value) {
33
33
  }
34
34
  /**
35
35
  * Is the value a hex color?
36
- * @param value The value to check
36
+ * @param value Value to check
37
37
  * @param alpha Allow alpha channel? _(defaults to `true`)_
38
38
  * @returns `true` if the value is a hex color, otherwise `false`
39
39
  */
@@ -45,7 +45,7 @@ function isHexColor(value, alpha) {
45
45
  }
46
46
  /**
47
47
  * Is the value an HSLA color?
48
- * @param value The value to check
48
+ * @param value Value to check
49
49
  * @returns `true` if the value is an HSLA color, otherwise `false`
50
50
  */
51
51
  function isHslaColor(value) {
@@ -53,7 +53,7 @@ function isHslaColor(value) {
53
53
  }
54
54
  /**
55
55
  * Is the value an HSL color?
56
- * @param value The value to check
56
+ * @param value Value to check
57
57
  * @returns `true` if the value is an HSL color, otherwise `false`
58
58
  */
59
59
  function isHslColor(value) {
@@ -64,7 +64,7 @@ function isHslLike(value) {
64
64
  }
65
65
  /**
66
66
  * Is the value an RGBA color?
67
- * @param value The value to check
67
+ * @param value Value to check
68
68
  * @returns `true` if the value is an RGBA color, otherwise `false`
69
69
  */
70
70
  function isRgbaColor(value) {
@@ -72,7 +72,7 @@ function isRgbaColor(value) {
72
72
  }
73
73
  /**
74
74
  * Is the value an RGB color?
75
- * @param value The value to check
75
+ * @param value Value to check
76
76
  * @returns `true` if the value is an RGB color, otherwise `false`
77
77
  */
78
78
  function isRgbColor(value) {
@@ -54,7 +54,7 @@ var Memoized = class {
54
54
  /**
55
55
  * Get a result from the cache
56
56
  * @param key Key to get
57
- * @returns The cached result or `undefined` if it does not exist
57
+ * @returns Cached result or `undefined` if it does not exist
58
58
  */
59
59
  get(key) {
60
60
  return this.#state.cache?.get(key);
package/dist/index.js CHANGED
@@ -45,16 +45,17 @@ import { template } from "./string/template.js";
45
45
  import { clone } from "./value/clone.js";
46
46
  import { diff } from "./value/diff.js";
47
47
  import { merge } from "./value/merge.js";
48
- import { partial } from "./value/partial.js";
48
+ import { omit } from "./value/omit.js";
49
+ import { pick } from "./value/pick.js";
49
50
  import { smush } from "./value/smush.js";
50
51
  import { unsmush } from "./value/unsmush.js";
51
- import { isEmpty, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumerical, isObject, isPrimitive } from "./is.js";
52
+ import { isEmpty, isNonNullable, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumerical, isObject, isPrimitive } from "./is.js";
52
53
  import { logger } from "./logger.js";
53
- import { average, count, min, round, sum } from "./math.js";
54
- import { PromiseTimeoutError, delay, isFulfilled, isRejected, promises, timed } from "./promise.js";
54
+ import { average, count, median, min, round, sum } from "./math.js";
55
+ import { CancelablePromise, PromiseTimeoutError, attemptPromise, cancelable, delay, isFulfilled, isRejected, promises, timed } from "./promise.js";
55
56
  import { fromQuery, toQuery } from "./query.js";
56
57
  import { QueueError, queue } from "./queue.js";
57
58
  import { getRandomBoolean, getRandomCharacters, getRandomColor, getRandomHex, getRandomItem, getRandomItems } from "./random.js";
58
- import { error, isError, isOk, isResult, ok, result, unwrap } from "./result.js";
59
+ import { attempt, error, isError, isOk, isResult, ok, unwrap } from "./result.js";
59
60
  import { SizedSet } from "./sized/set.js";
60
- export { frame_rate_default as FRAME_RATE_MS, PromiseTimeoutError, QueueError, SizedMap, SizedSet, average, beacon, between, camelCase, capitalize, chunk, clamp, clone, compact, compare, count, debounce, delay, diff, endsWith, equal, error, exists, filter, find, flatten, fromQuery, 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, isKey, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isOk, isPlainObject, isPrimitive, isRejected, isResult, isRgbColor, isRgbLike, isRgbaColor, isTypedArray, join, kebabCase, logger, lowerCase, max, memoize, merge, min, noop, ok, parse, partial, pascalCase, promises, push, queue, result, rgbToHex, rgbToHsl, rgbToHsla, round, setValue, shuffle, smush, snakeCase, sort, splice, startsWith, sum, template, throttle, timed, titleCase, toMap, toQuery, toRecord, toSet, trim, truncate, tryDecode, tryEncode, unique, unsmush, unwrap, upperCase, words };
61
+ export { CancelablePromise, frame_rate_default as FRAME_RATE_MS, PromiseTimeoutError, QueueError, SizedMap, SizedSet, attempt, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, chunk, clamp, clone, compact, compare, count, debounce, delay, diff, endsWith, equal, error, exists, filter, find, flatten, fromQuery, 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, 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, pascalCase, pick, promises, push, queue, rgbToHex, rgbToHsl, rgbToHsla, round, setValue, shuffle, smush, snakeCase, sort, splice, startsWith, sum, template, throttle, timed, titleCase, toMap, toQuery, toRecord, toSet, trim, truncate, tryDecode, tryEncode, unique, unsmush, unwrap, upperCase, words };
@@ -1,3 +1,4 @@
1
+ import { isNumber } from "../is.js";
1
2
  function aggregate(type, array, key) {
2
3
  const length = Array.isArray(array) ? array.length : 0;
3
4
  if (length === 0) return {
@@ -5,24 +6,27 @@ function aggregate(type, array, key) {
5
6
  value: NaN
6
7
  };
7
8
  const aggregator = aggregators[type];
8
- const isCallback = typeof key === "function";
9
+ const callback = getAggregateCallback(key);
9
10
  let counted = 0;
10
11
  let aggregated = NaN;
11
12
  let notNumber = true;
12
13
  for (let index = 0; index < length; index += 1) {
13
14
  const item = array[index];
14
- const value = isCallback ? key(item, index, array) : item[key] ?? item;
15
- if (typeof value === "number" && !Number.isNaN(value)) {
16
- aggregated = aggregator(aggregated, value, notNumber);
17
- counted += 1;
18
- notNumber = false;
19
- }
15
+ const value = callback == null ? item : callback(item, index, array);
16
+ if (!isNumber(value)) continue;
17
+ aggregated = aggregator(aggregated, value, notNumber);
18
+ counted += 1;
19
+ notNumber = false;
20
20
  }
21
21
  return {
22
22
  count: counted,
23
23
  value: aggregated
24
24
  };
25
25
  }
26
+ function getAggregateCallback(key) {
27
+ if (key == null) return;
28
+ return typeof key === "function" ? key : (item) => item[key];
29
+ }
26
30
  function max(array, key) {
27
31
  return getAggregated("max", array, key);
28
32
  }
@@ -39,4 +43,4 @@ var aggregators = {
39
43
  min: (current, value, notNumber) => notNumber || value < current ? value : current,
40
44
  sum: calculateSum
41
45
  };
42
- export { aggregate, getAggregated, max };
46
+ export { aggregate, getAggregateCallback, getAggregated, max };
@@ -35,7 +35,7 @@ function clamp(value, minimum, maximum, loop) {
35
35
  /**
36
36
  * Get the number value from an unknown value _(based on Lodash)_
37
37
  * @param value Original value
38
- * @returns The value as a number, or `NaN` if the value is unable to be parsed
38
+ * @returns Original value as a number, or `NaN` if the value is unable to be parsed
39
39
  */
40
40
  function getNumber(value) {
41
41
  if (typeof value === "number") return value;
@@ -0,0 +1,14 @@
1
+ function partial(value, providedKeys, omit) {
2
+ if (typeof value !== "object" || value === null) return {};
3
+ const keys = omit ? Object.keys(value) : Array.isArray(providedKeys) ? providedKeys : [];
4
+ const { length } = keys;
5
+ if (length === 0) return omit ? value : {};
6
+ const partials = {};
7
+ for (let index = 0; index < length; index += 1) {
8
+ const key = keys[index];
9
+ if (!(key in value)) continue;
10
+ if (omit ? !providedKeys.includes(key) : true) partials[key] = value[key];
11
+ }
12
+ return partials;
13
+ }
14
+ export { partial };