@oscarpalmer/atoms 0.205.0 → 0.207.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 (58) hide show
  1. package/dist/array/reverse.mjs +2 -1
  2. package/dist/array/single.d.mts +3 -3
  3. package/dist/array/sort.mjs +3 -2
  4. package/dist/color/misc/alpha.mjs +1 -1
  5. package/dist/color/misc/get.mjs +1 -1
  6. package/dist/color/space/hsl.mjs +7 -2
  7. package/dist/color/space/hwb.mjs +2 -1
  8. package/dist/color/space/rgb.mjs +22 -13
  9. package/dist/function/retry.mjs +12 -14
  10. package/dist/index.d.mts +105 -55
  11. package/dist/index.mjs +323 -262
  12. package/dist/internal/array/insert.mjs +2 -1
  13. package/dist/internal/function/limit.mjs +9 -9
  14. package/dist/internal/function/work.d.mts +1 -1
  15. package/dist/internal/math/aggregate.d.mts +41 -0
  16. package/dist/internal/math/aggregate.mjs +4 -1
  17. package/dist/internal/math/misc.d.mts +8 -0
  18. package/dist/internal/math/misc.mjs +11 -1
  19. package/dist/internal/models/plan.model.d.mts +23 -0
  20. package/dist/internal/models/plan.model.mjs +7 -0
  21. package/dist/internal/{result/models.d.mts → models/result.model.d.mts} +1 -1
  22. package/dist/internal/random.mjs +2 -1
  23. package/dist/internal/result/attempt.d.mts +59 -0
  24. package/dist/internal/result/attempt.mjs +24 -0
  25. package/dist/internal/result/misc.d.mts +1 -1
  26. package/dist/internal/string/misc.mjs +4 -5
  27. package/dist/internal/value/equal.mjs +2 -1
  28. package/dist/internal/value/has.d.mts +1 -1
  29. package/dist/internal/value/misc.d.mts +1 -1
  30. package/dist/internal/value/misc.mjs +1 -1
  31. package/dist/math.d.mts +3 -52
  32. package/dist/math.mjs +3 -16
  33. package/dist/plan/index.d.mts +38 -0
  34. package/dist/plan/index.mjs +61 -0
  35. package/dist/plan/models.d.mts +2 -0
  36. package/dist/plan/models.mjs +1 -0
  37. package/dist/promise/constants.d.mts +0 -1
  38. package/dist/promise/constants.mjs +1 -2
  39. package/dist/promise/helpers.mjs +1 -1
  40. package/dist/promise/index.mjs +9 -9
  41. package/dist/promise/misc.d.mts +1 -1
  42. package/dist/promise/misc.mjs +1 -1
  43. package/dist/promise/models.d.mts +1 -1
  44. package/dist/queue.mjs +11 -6
  45. package/dist/result/index.d.mts +2 -59
  46. package/dist/result/index.mjs +1 -23
  47. package/dist/result/match.d.mts +1 -1
  48. package/dist/result/misc.d.mts +1 -1
  49. package/dist/result/work/flow.d.mts +1 -1
  50. package/dist/result/work/flow.mjs +2 -1
  51. package/dist/result/work/pipe.d.mts +1 -1
  52. package/dist/result/work/pipe.mjs +2 -1
  53. package/dist/string/fuzzy.mjs +7 -5
  54. package/dist/string/index.mjs +2 -1
  55. package/dist/value/clone.mjs +5 -8
  56. package/dist/value/diff.mjs +3 -2
  57. package/package.json +9 -4
  58. /package/dist/internal/{result/models.mjs → models/result.model.mjs} +0 -0
@@ -1,8 +1,9 @@
1
1
  import { chunk } from "./chunk.mjs";
2
+ import { max, min } from "../math/aggregate.mjs";
2
3
  //#region src/internal/array/insert.ts
3
4
  function insertChunkedValues(type, array, items, start, deleteCount) {
4
5
  const actualDeleteCount = deleteCount < 0 ? 0 : deleteCount;
5
- const actualStart = Math.min(Math.max(0, start), array.length);
6
+ const actualStart = min([max([0, start]), array.length]);
6
7
  const chunked = chunk(items);
7
8
  const lastIndex = chunked.length - 1;
8
9
  let index = chunked.length;
@@ -1,3 +1,4 @@
1
+ import { asyncAttempt } from "../result/attempt.mjs";
1
2
  import { getNumberOrDefault } from "../defaults.mjs";
2
3
  //#region src/internal/function/limit.ts
3
4
  const LIMITER_NAME_ASYNC = "asyncLimiter";
@@ -51,15 +52,14 @@ async function handleAsyncLimiter(state, item) {
51
52
  if (state.interval === 0 || now - state.start >= state.interval - LIMITER_OFFSET) {
52
53
  state.start = state.throttle ? now : void 0;
53
54
  item.running = true;
54
- try {
55
- let result = state.callback(...item.parameters);
56
- if (result instanceof Promise) result = await result;
57
- item.resolve(result);
58
- } catch (error) {
59
- item.reject(error);
60
- } finally {
61
- item.running = false;
62
- }
55
+ const result = await asyncAttempt(async () => {
56
+ let value = state.callback(...item.parameters);
57
+ if (value instanceof Promise) value = await value;
58
+ return value;
59
+ });
60
+ if (result.ok) item.resolve(result.value);
61
+ else item.reject(result.error);
62
+ item.running = false;
63
63
  } else state.timer = startTimer(() => handleAsyncLimiter(state, item));
64
64
  }
65
65
  function handleLimiter(state) {
@@ -1,5 +1,5 @@
1
1
  import { GenericCallback } from "../../models.mjs";
2
- import { UnwrapValue } from "../result/models.mjs";
2
+ import { UnwrapValue } from "../models/result.model.mjs";
3
3
  //#region src/internal/function/work.d.ts
4
4
  /**
5
5
  * A synchronous _Flow_, a function that pipe a value through a series of functions
@@ -99,6 +99,47 @@ export declare function max<Item extends PlainObject>(items: Item[], key: keyof
99
99
  * @returns Maximum value, or `Number.NaN` if no maximum can be found
100
100
  */
101
101
  export declare function max(values: number[]): number;
102
+ /**
103
+ * Get the minimum value from a list of items
104
+ *
105
+ * @param items List of items
106
+ * @param callback Callback to get an item's value
107
+ * @param first Return only the first item with the minimum value
108
+ * @returns First item with the minimum value, or `undefined` if no minimum can be found
109
+ */
110
+ export declare function min<Item>(items: Item[], callback: (item: Item, index: number, array: Item[]) => number, first: true): Item | undefined;
111
+ /**
112
+ * Get the minimum value from a list of items
113
+ *
114
+ * @param items List of items
115
+ * @param key Key to use for value
116
+ * @param first Return only the first item with the minimum value
117
+ * @returns First item with the minimum value, or `undefined` if no minimum can be found
118
+ */
119
+ export declare function min<Item extends PlainObject>(items: Item[], key: keyof NumericalValues<Item>, first: true): Item | undefined;
120
+ /**
121
+ * Get the minimum value from a list of items
122
+ *
123
+ * @param items List of items
124
+ * @param callback Callback to get an item's value
125
+ * @returns Items with the minimum value
126
+ */
127
+ export declare function min<Item>(items: Item[], callback: (item: Item, index: number, array: Item[]) => number): Item[];
128
+ /**
129
+ * Get the minimum value from a list of items
130
+ *
131
+ * @param items List of items
132
+ * @param key Key to use for value
133
+ * @returns Items with the minimum value
134
+ */
135
+ export declare function min<Item extends PlainObject>(items: Item[], key: keyof NumericalValues<Item>): Item[];
136
+ /**
137
+ * Get the minimum value from a list of numbers
138
+ *
139
+ * @param values List of numbers
140
+ * @returns Minimum value, or `Number.NaN` if no minimum can be found
141
+ */
142
+ export declare function min(values: number[]): number;
102
143
  export declare const AGGREGATION_AVERAGE: AggregationType;
103
144
  export declare const AGGREGATION_MAX = "max";
104
145
  export declare const AGGREGATION_MIN = "min";
@@ -59,6 +59,9 @@ function isMinValue(aggregation, value) {
59
59
  function max(array, key, first) {
60
60
  return getAggregated("max", array, key, first);
61
61
  }
62
+ function min(array, key, first) {
63
+ return getAggregated("min", array, key, first);
64
+ }
62
65
  const AGGREGATION_AVERAGE = "average";
63
66
  const AGGREGATION_MAX = "max";
64
67
  const AGGREGATION_MIN = "min";
@@ -70,4 +73,4 @@ const aggregators = {
70
73
  sum: calculateSum
71
74
  };
72
75
  //#endregion
73
- export { AGGREGATION_AVERAGE, AGGREGATION_MAX, AGGREGATION_MIN, AGGREGATION_SUM, aggregate, getAggregateCallback, getAggregated, max };
76
+ export { AGGREGATION_AVERAGE, AGGREGATION_MAX, AGGREGATION_MIN, AGGREGATION_SUM, aggregate, getAggregateCallback, getAggregated, max, min };
@@ -1,4 +1,12 @@
1
1
  //#region src/internal/math/misc.d.ts
2
+ /**
3
+ * Round a number down
4
+ *
5
+ * @param value Number to round down
6
+ * @param decimals Number of decimal places to round to _(defaults to `0`)_
7
+ * @returns Rounded number, or `Number.NaN` if the value if unable to be rounded
8
+ */
9
+ export declare function floor(value: number, decimals?: number): number;
2
10
  /**
3
11
  * Round a number
4
12
  *
@@ -1,5 +1,15 @@
1
1
  //#region src/internal/math/misc.ts
2
2
  /**
3
+ * Round a number down
4
+ *
5
+ * @param value Number to round down
6
+ * @param decimals Number of decimal places to round to _(defaults to `0`)_
7
+ * @returns Rounded number, or `Number.NaN` if the value if unable to be rounded
8
+ */
9
+ function floor(value, decimals) {
10
+ return roundNumber(Math.floor, value, decimals);
11
+ }
12
+ /**
3
13
  * Round a number
4
14
  *
5
15
  * @param value Number to round
@@ -16,4 +26,4 @@ function roundNumber(callback, value, decimals) {
16
26
  return callback((value + Number.EPSILON) * mod) / mod;
17
27
  }
18
28
  //#endregion
19
- export { round, roundNumber };
29
+ export { floor, round, roundNumber };
@@ -0,0 +1,23 @@
1
+ //#region src/internal/models/plan.model.d.ts
2
+ export type InternalPlan = {
3
+ [PLAN_SYMBOL]: PlanState;
4
+ } & Plan<never, never>;
5
+ /**
6
+ * A plan of execution that can yield intermediate results and eventually return a value or an error.
7
+ */
8
+ export type Plan<out Value, out Error = unknown> = {
9
+ /**
10
+ * Run the plan to completion
11
+ *
12
+ * @returns Final result, or an error
13
+ */
14
+ run: () => Error | Value;
15
+ };
16
+ type PlanState = {
17
+ generator: () => Generator;
18
+ };
19
+ export declare const GENERATOR_NAME = "GeneratorFunction";
20
+ export declare const PLAN_MESSAGE_PLAN_INPUT = "plan requires a generator function";
21
+ export declare const PLAN_MESSAGE_RUN_INPUT = "run requires a plan or a generator function";
22
+ export declare const PLAN_SYMBOL: symbol;
23
+ //#endregion
@@ -0,0 +1,7 @@
1
+ //#region src/internal/models/plan.model.ts
2
+ const GENERATOR_NAME = "GeneratorFunction";
3
+ const PLAN_MESSAGE_PLAN_INPUT = "plan requires a generator function";
4
+ const PLAN_MESSAGE_RUN_INPUT = "run requires a plan or a generator function";
5
+ const PLAN_SYMBOL = Symbol("plan");
6
+ //#endregion
7
+ export { GENERATOR_NAME, PLAN_MESSAGE_PLAN_INPUT, PLAN_MESSAGE_RUN_INPUT, PLAN_SYMBOL };
@@ -1,5 +1,5 @@
1
1
  import { GenericCallback } from "../../models.mjs";
2
- //#region src/internal/result/models.d.ts
2
+ //#region src/internal/models/result.model.d.ts
3
3
  /**
4
4
  * An unknown result
5
5
  */
@@ -1,4 +1,5 @@
1
1
  import { isNumber } from "./is.mjs";
2
+ import { floor } from "./math/misc.mjs";
2
3
  //#region src/internal/random.ts
3
4
  function getRandomFloatingNumberValue(inclusive, minimum, maximum) {
4
5
  let maxFloat = isNumber(maximum) && maximum <= Number.MAX_SAFE_INTEGER ? maximum : Number.MAX_SAFE_INTEGER;
@@ -25,7 +26,7 @@ function getRandomFloatingNumber(minimum, maximum) {
25
26
  * @returns Random integer
26
27
  */
27
28
  function getRandomInteger(minimum, maximum) {
28
- return Math.floor(getRandomFloatingNumberValue(true, minimum, maximum));
29
+ return floor(getRandomFloatingNumberValue(true, minimum, maximum));
29
30
  }
30
31
  //#endregion
31
32
  export { getRandomFloatingNumber, getRandomInteger };
@@ -0,0 +1,59 @@
1
+ import { ExtendedResult, Result } from "../models/result.model.mjs";
2
+ //#region src/internal/result/attempt.d.ts
3
+ /**
4
+ * Executes a _Promise_, catching any errors, and returns a result
5
+ *
6
+ * _Available as `asyncAttempt` and `attempt.async`_
7
+ *
8
+ * @param promise _Promise_ to execute
9
+ * @param error Error value
10
+ * @returns Callback result
11
+ */
12
+ export declare function asyncAttempt<Value, E>(promise: Promise<Value>, error: E): Promise<ExtendedResult<Awaited<Value>, E>>;
13
+ /**
14
+ * Executes a callback asynchronously, catching any errors, and returns a result
15
+ *
16
+ * _Available as `asyncAttempt` and `attempt.async`_
17
+ *
18
+ * @param callback Callback to execute
19
+ * @param error Error value
20
+ * @returns Callback result
21
+ */
22
+ export declare function asyncAttempt<Value, E>(callback: () => Promise<Value>, error: E): Promise<ExtendedResult<Awaited<Value>, E>>;
23
+ /**
24
+ * Executes a _Promise_, catching any errors, and returns a result
25
+ *
26
+ * _Available as `asyncAttempt` and `attempt.async`_
27
+ *
28
+ * @param promise _Promise_ to execute
29
+ * @returns Callback result
30
+ */
31
+ export declare function asyncAttempt<Value>(promise: Promise<Value>): Promise<Result<Awaited<Value>>>;
32
+ /**
33
+ * Executes a callback asynchronously, catching any errors, and returns a result
34
+ *
35
+ * _Available as `asyncAttempt` and `attempt.async`_
36
+ *
37
+ * @param callback Callback to execute
38
+ * @returns Callback result
39
+ */
40
+ export declare function asyncAttempt<Value>(callback: () => Promise<Value>): Promise<Result<Awaited<Value>>>;
41
+ /**
42
+ * Executes a callback, catching any errors, and returns a result
43
+ *
44
+ * @param callback Callback to execute
45
+ * @param error Error value
46
+ * @returns Callback result
47
+ */
48
+ export declare function attempt<Value, E>(callback: () => Value, error: E): ExtendedResult<Value, E>;
49
+ /**
50
+ * Executes a callback, catching any errors, and returns a result
51
+ *
52
+ * @param callback Callback to execute
53
+ * @returns Callback result
54
+ */
55
+ export declare function attempt<Value>(callback: () => Value): Result<Value, Error>;
56
+ export declare namespace attempt {
57
+ export var async: typeof asyncAttempt;
58
+ }
59
+ //#endregion
@@ -0,0 +1,24 @@
1
+ import { getError, ok } from "./misc.mjs";
2
+ //#region src/internal/result/attempt.ts
3
+ async function asyncAttempt(value, err) {
4
+ try {
5
+ let result;
6
+ if (typeof value === "function") result = value();
7
+ else result = value;
8
+ if (result instanceof Promise) result = await result;
9
+ return ok(result);
10
+ } catch (thrown) {
11
+ return getError(err ?? thrown, err == null ? void 0 : thrown);
12
+ }
13
+ }
14
+ function attempt(callback, err) {
15
+ try {
16
+ const value = callback();
17
+ return ok(value);
18
+ } catch (thrown) {
19
+ return getError(err ?? thrown, err == null ? void 0 : thrown);
20
+ }
21
+ }
22
+ attempt.async = asyncAttempt;
23
+ //#endregion
24
+ export { asyncAttempt, attempt };
@@ -1,4 +1,4 @@
1
- import { Err, ExtendedErr, Ok, Result } from "./models.mjs";
1
+ import { Err, ExtendedErr, Ok, Result } from "../models/result.model.mjs";
2
2
  //#region src/internal/result/misc.d.ts
3
3
  /**
4
4
  * Creates an extended error result
@@ -1,3 +1,6 @@
1
+ import { unwrap } from "../result/misc.mjs";
2
+ import "../../result/misc.mjs";
3
+ import { attempt } from "../result/attempt.mjs";
1
4
  //#region src/internal/string/misc.ts
2
5
  /**
3
6
  * Get the string value from any value
@@ -57,11 +60,7 @@ function join(array, delimiter) {
57
60
  return values.join(typeof delimiter === "string" ? delimiter : "");
58
61
  }
59
62
  function tryCallback(value, callback) {
60
- try {
61
- return callback(value);
62
- } catch {
63
- return value;
64
- }
63
+ return unwrap(attempt(() => callback(value)), value);
65
64
  }
66
65
  function tryDecode(value) {
67
66
  return tryCallback(value, decodeURIComponent);
@@ -1,4 +1,5 @@
1
1
  import { isNonPlainObject, isPlainObject, isPrimitive, isTypedArray } from "../is.mjs";
2
+ import { round } from "../math/misc.mjs";
2
3
  import { createCompareHandler } from "./handlers.mjs";
3
4
  //#region src/internal/value/equal.ts
4
5
  function Equalizer(options) {
@@ -60,7 +61,7 @@ function equalArray(first, second, options) {
60
61
  if (length !== second.length) return false;
61
62
  let offset = 0;
62
63
  if (length >= EQUAL_ARRAY_THRESHOLD) {
63
- offset = Math.round(length / EQUAL_ARRAY_PEEK_PERCENTAGE);
64
+ offset = round(length / EQUAL_ARRAY_PEEK_PERCENTAGE);
64
65
  offset = offset > EQUAL_ARRAY_THRESHOLD ? EQUAL_ARRAY_THRESHOLD : offset;
65
66
  for (let index = 0; index < offset; index += 1) if (!(equalValue(first[index], second[index], options) && equalValue(first[length - index - 1], second[length - index - 1], options))) return false;
66
67
  }
@@ -1,5 +1,5 @@
1
1
  import { NestedKeys, NestedValue, PlainObject, ToString } from "../../models.mjs";
2
- import { Result } from "../result/models.mjs";
2
+ import { Result } from "../models/result.model.mjs";
3
3
  //#region src/internal/value/has.d.ts
4
4
  /**
5
5
  * Check if a property is defined in an object
@@ -1,4 +1,4 @@
1
- import { Result } from "../result/models.mjs";
1
+ import { Result } from "../models/result.model.mjs";
2
2
  //#region src/internal/value/misc.d.ts
3
3
  export declare function findKey(needle: string, haystack: object): string;
4
4
  export declare function getNestedValue(data: object, path: string, ignoreCase: boolean): Result<unknown, string>;
@@ -1,5 +1,5 @@
1
- import { ignoreKey } from "../string/misc.mjs";
2
1
  import { error, ok } from "../result/misc.mjs";
2
+ import { ignoreKey } from "../string/misc.mjs";
3
3
  //#region src/internal/value/misc.ts
4
4
  function findKey(needle, haystack) {
5
5
  const keys = Object.keys(haystack);
package/dist/math.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { NumericalValues, PlainObject } from "./models.mjs";
2
- import { max } from "./internal/math/aggregate.mjs";
3
- import { round } from "./internal/math/misc.mjs";
2
+ import { max, min } from "./internal/math/aggregate.mjs";
3
+ import { floor, round } from "./internal/math/misc.mjs";
4
4
  //#region src/math.d.ts
5
5
  /**
6
6
  * Get the average value from a list of items
@@ -58,14 +58,6 @@ export declare function count<Item extends PlainObject, ItemKey extends keyof It
58
58
  * @returns Number of items, or `Number.NaN` if no count can be calculated
59
59
  */
60
60
  export declare function count(values: unknown[]): number;
61
- /**
62
- * Round a number down
63
- *
64
- * @param value Number to round down
65
- * @param decimals Number of decimal places to round to _(defaults to `0`)_
66
- * @returns Rounded number, or `Number.NaN` if the value if unable to be rounded
67
- */
68
- export declare function floor(value: number, decimals?: number): number;
69
61
  /**
70
62
  * Get the median value from a list of items
71
63
  *
@@ -89,47 +81,6 @@ export declare function median<Item extends PlainObject>(array: Item[], key: key
89
81
  * @returns Median value, or `Number.NaN` if no median can be calculated
90
82
  */
91
83
  export declare function median(array: number[]): number;
92
- /**
93
- * Get the minimum value from a list of items
94
- *
95
- * @param items List of items
96
- * @param callback Callback to get an item's value
97
- * @param first Return only the first item with the minimum value
98
- * @returns First item with the minimum value, or `undefined` if no minimum can be found
99
- */
100
- export declare function min<Item>(items: Item[], callback: (item: Item, index: number, array: Item[]) => number, first: true): Item | undefined;
101
- /**
102
- * Get the minimum value from a list of items
103
- *
104
- * @param items List of items
105
- * @param key Key to use for value
106
- * @param first Return only the first item with the minimum value
107
- * @returns First item with the minimum value, or `undefined` if no minimum can be found
108
- */
109
- export declare function min<Item extends PlainObject>(items: Item[], key: keyof NumericalValues<Item>, first: true): Item | undefined;
110
- /**
111
- * Get the minimum value from a list of items
112
- *
113
- * @param items List of items
114
- * @param callback Callback to get an item's value
115
- * @returns Items with the minimum value
116
- */
117
- export declare function min<Item>(items: Item[], callback: (item: Item, index: number, array: Item[]) => number): Item[];
118
- /**
119
- * Get the minimum value from a list of items
120
- *
121
- * @param items List of items
122
- * @param key Key to use for value
123
- * @returns Items with the minimum value
124
- */
125
- export declare function min<Item extends PlainObject>(items: Item[], key: keyof NumericalValues<Item>): Item[];
126
- /**
127
- * Get the minimum value from a list of numbers
128
- *
129
- * @param values List of numbers
130
- * @returns Minimum value, or `Number.NaN` if no minimum can be found
131
- */
132
- export declare function min(values: number[]): number;
133
84
  /**
134
85
  * Get the sum of a list of items
135
86
  *
@@ -154,4 +105,4 @@ export declare function sum<Item extends PlainObject>(items: Item[], key: keyof
154
105
  */
155
106
  export declare function sum(values: number[]): number;
156
107
  //#endregion
157
- export { max, round };
108
+ export { floor, max, min, round };
package/dist/math.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { isNumber } from "./internal/is.mjs";
2
- import { AGGREGATION_AVERAGE, aggregate, getAggregateCallback, getAggregated, max } from "./internal/math/aggregate.mjs";
3
- import { round, roundNumber } from "./internal/math/misc.mjs";
2
+ import { floor, round, roundNumber } from "./internal/math/misc.mjs";
3
+ import { AGGREGATION_AVERAGE, aggregate, getAggregateCallback, getAggregated, max, min } from "./internal/math/aggregate.mjs";
4
4
  //#region src/math.ts
5
5
  function average(array, key) {
6
6
  const aggregated = aggregate(AGGREGATION_AVERAGE, array, key);
@@ -28,16 +28,6 @@ function count(array, key, value) {
28
28
  }
29
29
  return counted;
30
30
  }
31
- /**
32
- * Round a number down
33
- *
34
- * @param value Number to round down
35
- * @param decimals Number of decimal places to round to _(defaults to `0`)_
36
- * @returns Rounded number, or `Number.NaN` if the value if unable to be rounded
37
- */
38
- function floor(value, decimals) {
39
- return roundNumber(Math.floor, value, decimals);
40
- }
41
31
  function median(array, key) {
42
32
  let length = Array.isArray(array) ? array.length : 0;
43
33
  if (!Array.isArray(array) || length === 0) return NaN;
@@ -52,10 +42,7 @@ function median(array, key) {
52
42
  const second = length / 2;
53
43
  return (numbers[first] + numbers[second]) / 2;
54
44
  }
55
- return numbers[Math.floor(length / 2)];
56
- }
57
- function min(array, key, first) {
58
- return getAggregated("min", array, key, first);
45
+ return numbers[floor(length / 2)];
59
46
  }
60
47
  function sum(array, key) {
61
48
  return getAggregated("sum", array, key);
@@ -0,0 +1,38 @@
1
+ import { Plan } from "../internal/models/plan.model.mjs";
2
+ //#region src/plan/index.d.ts
3
+ /**
4
+ * Is the value a generator function?
5
+ *
6
+ * @param value Value to check
7
+ * @returns `true` if the value is a generator function, otherwise `false`
8
+ */
9
+ export declare function isGenerator(value: unknown): value is () => Generator;
10
+ /**
11
+ * Is the value a plan?
12
+ *
13
+ * @param value Value to check
14
+ * @returns `true` if the value is a plan, otherwise `false`
15
+ */
16
+ export declare function isPlan<Value = unknown, Error = unknown>(value: unknown): value is Plan<Value, Error>;
17
+ /**
18
+ * Create a plan for a generator function
19
+ *
20
+ * @param generator Generator to plan for
21
+ * @returns Generator plan
22
+ */
23
+ export declare function plan<Value = unknown, Error = unknown>(generator: () => Generator<unknown, Value, Error>): Plan<Value, Error>;
24
+ /**
25
+ * Run a generator to completion
26
+ *
27
+ * @param generator Generator to run
28
+ * @returns Final result, or an error
29
+ */
30
+ export declare function run<Value = unknown, Error = unknown>(generator: () => Generator<unknown, Value, unknown>): Error | Value;
31
+ /**
32
+ * Run a plan to completion
33
+ *
34
+ * @param plan Plan to run
35
+ * @returns Final result, or an error
36
+ */
37
+ export declare function run<Value = unknown, Error = unknown>(plan: Plan<Value, Error>): Error | Value;
38
+ //#endregion
@@ -0,0 +1,61 @@
1
+ import { attempt } from "../internal/result/attempt.mjs";
2
+ import { PLAN_MESSAGE_PLAN_INPUT, PLAN_MESSAGE_RUN_INPUT, PLAN_SYMBOL } from "../internal/models/plan.model.mjs";
3
+ //#region src/plan/index.ts
4
+ function Plan(generator) {
5
+ this[PLAN_SYMBOL] = { generator };
6
+ }
7
+ Plan.prototype.run = runPlan;
8
+ function execute(callback) {
9
+ const result = attempt(() => {
10
+ const generator = callback();
11
+ let lastValue;
12
+ while (true) {
13
+ const next = generator.next();
14
+ const { done } = next;
15
+ let { value } = next;
16
+ if (value instanceof Error) throw value;
17
+ lastValue = value;
18
+ if (done === true) break;
19
+ }
20
+ return lastValue;
21
+ });
22
+ return result.ok ? result.value : result.error;
23
+ }
24
+ /**
25
+ * Is the value a generator function?
26
+ *
27
+ * @param value Value to check
28
+ * @returns `true` if the value is a generator function, otherwise `false`
29
+ */
30
+ function isGenerator(value) {
31
+ return typeof value === "function" && value.constructor.name === "GeneratorFunction" && typeof value.prototype.next === "function" && typeof value.prototype.return === "function" && typeof value.prototype.throw === "function";
32
+ }
33
+ /**
34
+ * Is the value a plan?
35
+ *
36
+ * @param value Value to check
37
+ * @returns `true` if the value is a plan, otherwise `false`
38
+ */
39
+ function isPlan(value) {
40
+ return typeof value === "object" && value !== null && PLAN_SYMBOL in value;
41
+ }
42
+ /**
43
+ * Create a plan for a generator function
44
+ *
45
+ * @param generator Generator to plan for
46
+ * @returns Generator plan
47
+ */
48
+ function plan(generator) {
49
+ if (!isGenerator(generator)) throw new Error(PLAN_MESSAGE_PLAN_INPUT);
50
+ return new Plan(generator);
51
+ }
52
+ function run(input) {
53
+ if (isPlan(input)) return input.run();
54
+ if (!isGenerator(input)) throw new Error(PLAN_MESSAGE_RUN_INPUT);
55
+ return execute(input);
56
+ }
57
+ function runPlan() {
58
+ return execute(this[PLAN_SYMBOL].generator);
59
+ }
60
+ //#endregion
61
+ export { isGenerator, isPlan, plan, run };
@@ -0,0 +1,2 @@
1
+ import { Plan } from "../internal/models/plan.model.mjs";
2
+ export type { Plan };
@@ -0,0 +1 @@
1
+ export {};
@@ -6,7 +6,6 @@ export declare const PROMISE_ABORT_OPTIONS: {
6
6
  };
7
7
  export declare const PROMISE_ERROR_NAME = "PromiseTimeoutError";
8
8
  export declare const PROMISE_MESSAGE_EXPECTATION_ATTEMPT = "Attempt expected a function or a promise";
9
- export declare const PROMISE_MESSAGE_EXPECTATION_ITEMS_EMPTY = "promises expected at least one promise-function or promise in the array or object";
10
9
  export declare const PROMISE_MESSAGE_EXPECTATION_ITEMS_TYPE = "promises expected an array or object holding promise-functions or promises";
11
10
  export declare const PROMISE_MESSAGE_EXPECTATION_RESULT = "toResult expected a Promise";
12
11
  export declare const PROMISE_MESSAGE_EXPECTATION_TIMED = "Timed function expected a Promise";
@@ -3,7 +3,6 @@ const PROMISE_ABORT_EVENT = "abort";
3
3
  const PROMISE_ABORT_OPTIONS = { once: true };
4
4
  const PROMISE_ERROR_NAME = "PromiseTimeoutError";
5
5
  const PROMISE_MESSAGE_EXPECTATION_ATTEMPT = "Attempt expected a function or a promise";
6
- const PROMISE_MESSAGE_EXPECTATION_ITEMS_EMPTY = "promises expected at least one promise-function or promise in the array or object";
7
6
  const PROMISE_MESSAGE_EXPECTATION_ITEMS_TYPE = "promises expected an array or object holding promise-functions or promises";
8
7
  const PROMISE_MESSAGE_EXPECTATION_RESULT = "toResult expected a Promise";
9
8
  const PROMISE_MESSAGE_EXPECTATION_TIMED = "Timed function expected a Promise";
@@ -13,4 +12,4 @@ const PROMISE_STRATEGY_DEFAULT = "complete";
13
12
  const PROMISE_TYPE_FULFILLED = "fulfilled";
14
13
  const PROMISE_TYPE_REJECTED = "rejected";
15
14
  //#endregion
16
- export { PROMISE_ABORT_EVENT, PROMISE_ABORT_OPTIONS, PROMISE_ERROR_NAME, PROMISE_MESSAGE_EXPECTATION_ATTEMPT, PROMISE_MESSAGE_EXPECTATION_ITEMS_EMPTY, PROMISE_MESSAGE_EXPECTATION_ITEMS_TYPE, PROMISE_MESSAGE_EXPECTATION_RESULT, PROMISE_MESSAGE_EXPECTATION_TIMED, PROMISE_MESSAGE_TIMEOUT, PROMISE_STRATEGY_ALL, PROMISE_STRATEGY_DEFAULT, PROMISE_TYPE_FULFILLED, PROMISE_TYPE_REJECTED };
15
+ export { PROMISE_ABORT_EVENT, PROMISE_ABORT_OPTIONS, PROMISE_ERROR_NAME, PROMISE_MESSAGE_EXPECTATION_ATTEMPT, PROMISE_MESSAGE_EXPECTATION_ITEMS_TYPE, PROMISE_MESSAGE_EXPECTATION_RESULT, PROMISE_MESSAGE_EXPECTATION_TIMED, PROMISE_MESSAGE_TIMEOUT, PROMISE_STRATEGY_ALL, PROMISE_STRATEGY_DEFAULT, PROMISE_TYPE_FULFILLED, PROMISE_TYPE_REJECTED };
@@ -1,6 +1,6 @@
1
1
  import { isPlainObject } from "../internal/is.mjs";
2
- import { getNumberOrDefault } from "../internal/defaults.mjs";
3
2
  import { error, ok } from "../internal/result/misc.mjs";
3
+ import { getNumberOrDefault } from "../internal/defaults.mjs";
4
4
  import { PROMISE_STRATEGY_ALL, PROMISE_STRATEGY_DEFAULT, PROMISE_TYPE_FULFILLED, PROMISE_TYPE_REJECTED } from "./constants.mjs";
5
5
  //#region src/promise/helpers.ts
6
6
  function createPromiseOptions(input) {