@oscarpalmer/atoms 0.207.0 → 0.209.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -4589,18 +4589,76 @@ export declare function setValue<Data extends PlainObject>(data: Data, path: str
4589
4589
  //#endregion
4590
4590
  //#region src/internal/models/plan.model.d.ts
4591
4591
  /**
4592
- * A plan of execution that can yield intermediate results and eventually return a value or an error.
4592
+ * An asynchronous plan of execution that can yield intermediate results and eventually return a result
4593
4593
  */
4594
- type Plan<out Value, out Error = unknown> = {
4594
+ type AsyncPlan<Value, Error = unknown> = {
4595
+ /**
4596
+ * Get the asynchronous generator for the plan
4597
+ *
4598
+ * @returns Asynchronous generator
4599
+ */
4600
+ [Symbol.asyncIterator]: () => AsyncGenerator<unknown, Value, unknown>;
4601
+ /**
4602
+ * Run the plan to completion
4603
+ *
4604
+ * @returns Result
4605
+ */
4606
+ run: () => Promise<Result<Value, Error>>;
4607
+ };
4608
+ /**
4609
+ * A plan of execution that can yield intermediate results and eventually return a result
4610
+ */
4611
+ type Plan<Value, Error = unknown> = {
4612
+ /**
4613
+ * Get the generator for the plan
4614
+ *
4615
+ * @returns Generator
4616
+ */
4617
+ [Symbol.iterator]: () => Generator<unknown, Value, unknown>;
4595
4618
  /**
4596
4619
  * Run the plan to completion
4597
4620
  *
4598
- * @returns Final result, or an error
4621
+ * @returns Result
4599
4622
  */
4600
- run: () => Error | Value;
4623
+ run: () => Result<Value, Error>;
4601
4624
  };
4602
4625
  //#endregion
4603
4626
  //#region src/plan/index.d.ts
4627
+ /**
4628
+ * Create a plan for an asynchronous generator function
4629
+ *
4630
+ * @param generator Generator to plan for
4631
+ * @returns Generator plan
4632
+ */
4633
+ export declare function asyncPlan<Value = unknown, Error = unknown>(generator: () => AsyncGenerator<unknown, Value, unknown>): AsyncPlan<Value, Error>;
4634
+ /**
4635
+ * Run an asynchronous generator to completion
4636
+ *
4637
+ * @param generator Generator to run
4638
+ * @returns Result
4639
+ */
4640
+ export declare function asyncRun<Value = unknown, Error = unknown>(generator: () => AsyncGenerator<unknown, Value, unknown>): Promise<Result<Value, Error>>;
4641
+ /**
4642
+ * Run an asynchronous plan to completion
4643
+ *
4644
+ * @param plan Plan to run
4645
+ * @returns Result
4646
+ */
4647
+ export declare function asyncRun<Value = unknown, Error = unknown>(plan: AsyncPlan<Value, Error>): Promise<Result<Value, Error>>;
4648
+ /**
4649
+ * Is the value an asynchronous plan?
4650
+ *
4651
+ * @param value Value to check
4652
+ * @returns `true` if the value is an asynchronous plan, otherwise `false`
4653
+ */
4654
+ export declare function isAsyncPlan<Value = unknown, Error = unknown>(value: unknown): value is AsyncPlan<Value, Error>;
4655
+ /**
4656
+ * Is the value an asynchronous generator function?
4657
+ *
4658
+ * @param value Value to check
4659
+ * @returns `true` if the value is an asynchronous generator function, otherwise `false`
4660
+ */
4661
+ export declare function isAsyncGenerator(value: unknown): value is () => AsyncGenerator;
4604
4662
  /**
4605
4663
  * Is the value a generator function?
4606
4664
  *
@@ -4626,16 +4684,22 @@ export declare function plan<Value = unknown, Error = unknown>(generator: () =>
4626
4684
  * Run a generator to completion
4627
4685
  *
4628
4686
  * @param generator Generator to run
4629
- * @returns Final result, or an error
4687
+ * @returns Result
4630
4688
  */
4631
- export declare function run<Value = unknown, Error = unknown>(generator: () => Generator<unknown, Value, unknown>): Error | Value;
4689
+ export declare function run<Value = unknown, Error = unknown>(generator: () => Generator<unknown, Value, unknown>): Result<Value, Error>;
4632
4690
  /**
4633
4691
  * Run a plan to completion
4634
4692
  *
4635
4693
  * @param plan Plan to run
4636
- * @returns Final result, or an error
4694
+ * @returns Result
4637
4695
  */
4638
- export declare function run<Value = unknown, Error = unknown>(plan: Plan<Value, Error>): Error | Value;
4696
+ export declare function run<Value = unknown, Error = unknown>(plan: Plan<Value, Error>): Result<Value, Error>;
4697
+ export declare namespace plan {
4698
+ export var async: typeof asyncPlan;
4699
+ }
4700
+ export declare namespace run {
4701
+ export var async: typeof asyncRun;
4702
+ }
4639
4703
  //#endregion
4640
4704
  //#region src/internal/aborter.d.ts
4641
4705
  type Aborter = {
package/dist/index.mjs CHANGED
@@ -2746,17 +2746,71 @@ function setValue(data, path, value, ignoreCase) {
2746
2746
  return data;
2747
2747
  }
2748
2748
  const SET_EXPRESSION_INDEX = /^\d+$/;
2749
+ //#endregion
2750
+ //#region src/internal/models/plan.model.ts
2751
+ const GENERATOR_NAME_ASYNC = "AsyncGeneratorFunction";
2752
+ const GENERATOR_NAME_SYNC = "GeneratorFunction";
2749
2753
  const PLAN_MESSAGE_PLAN_INPUT = "plan requires a generator function";
2750
2754
  const PLAN_MESSAGE_RUN_INPUT = "run requires a plan or a generator function";
2751
2755
  const PLAN_SYMBOL = Symbol("plan");
2756
+ const PLAN_TYPE_PLAN_ASYNC = "asyncPlan";
2757
+ const PLAN_TYPE_PLAN_SYNC = "plan";
2752
2758
  //#endregion
2753
2759
  //#region src/plan/index.ts
2760
+ function AsyncPlan(generator) {
2761
+ this[PLAN_SYMBOL] = {
2762
+ generator,
2763
+ type: PLAN_TYPE_PLAN_ASYNC
2764
+ };
2765
+ }
2766
+ AsyncPlan.prototype[Symbol.asyncIterator] = function() {
2767
+ return this[PLAN_SYMBOL].generator();
2768
+ };
2769
+ AsyncPlan.prototype.run = runAsyncPlan;
2754
2770
  function Plan(generator) {
2755
- this[PLAN_SYMBOL] = { generator };
2771
+ this[PLAN_SYMBOL] = {
2772
+ generator,
2773
+ type: PLAN_TYPE_PLAN_SYNC
2774
+ };
2756
2775
  }
2776
+ Plan.prototype[Symbol.iterator] = function() {
2777
+ return this[PLAN_SYMBOL].generator();
2778
+ };
2757
2779
  Plan.prototype.run = runPlan;
2780
+ function asyncExecute(callback) {
2781
+ return asyncAttempt(async () => {
2782
+ const generator = callback();
2783
+ let lastValue;
2784
+ while (true) {
2785
+ const next = await generator.next();
2786
+ const { done } = next;
2787
+ let value = next.value;
2788
+ if (value instanceof Error) throw value;
2789
+ if (isError(value)) throw value.error;
2790
+ if (isOk(value)) value = value.value;
2791
+ lastValue = value;
2792
+ if (done === true) break;
2793
+ }
2794
+ return lastValue;
2795
+ });
2796
+ }
2797
+ /**
2798
+ * Create a plan for an asynchronous generator function
2799
+ *
2800
+ * @param generator Generator to plan for
2801
+ * @returns Generator plan
2802
+ */
2803
+ function asyncPlan(generator) {
2804
+ if (!isAsyncGenerator(generator)) throw new Error(PLAN_MESSAGE_PLAN_INPUT);
2805
+ return new AsyncPlan(generator);
2806
+ }
2807
+ async function asyncRun(input) {
2808
+ if (isAsyncPlan(input)) return input.run();
2809
+ if (!isAsyncGenerator(input)) throw new Error(PLAN_MESSAGE_RUN_INPUT);
2810
+ return asyncExecute(input);
2811
+ }
2758
2812
  function execute(callback) {
2759
- const result = attempt(() => {
2813
+ return attempt(() => {
2760
2814
  const generator = callback();
2761
2815
  let lastValue;
2762
2816
  while (true) {
@@ -2764,12 +2818,31 @@ function execute(callback) {
2764
2818
  const { done } = next;
2765
2819
  let { value } = next;
2766
2820
  if (value instanceof Error) throw value;
2821
+ if (isError(value)) throw value.error;
2822
+ if (isOk(value)) value = value.value;
2767
2823
  lastValue = value;
2768
2824
  if (done === true) break;
2769
2825
  }
2770
2826
  return lastValue;
2771
2827
  });
2772
- return result.ok ? result.value : result.error;
2828
+ }
2829
+ /**
2830
+ * Is the value an asynchronous plan?
2831
+ *
2832
+ * @param value Value to check
2833
+ * @returns `true` if the value is an asynchronous plan, otherwise `false`
2834
+ */
2835
+ function isAsyncPlan(value) {
2836
+ return isPlanInstance(PLAN_TYPE_PLAN_ASYNC, value);
2837
+ }
2838
+ /**
2839
+ * Is the value an asynchronous generator function?
2840
+ *
2841
+ * @param value Value to check
2842
+ * @returns `true` if the value is an asynchronous generator function, otherwise `false`
2843
+ */
2844
+ function isAsyncGenerator(value) {
2845
+ return isGeneratorInstance(GENERATOR_NAME_ASYNC, value);
2773
2846
  }
2774
2847
  /**
2775
2848
  * Is the value a generator function?
@@ -2778,7 +2851,10 @@ function execute(callback) {
2778
2851
  * @returns `true` if the value is a generator function, otherwise `false`
2779
2852
  */
2780
2853
  function isGenerator(value) {
2781
- return typeof value === "function" && value.constructor.name === "GeneratorFunction" && typeof value.prototype.next === "function" && typeof value.prototype.return === "function" && typeof value.prototype.throw === "function";
2854
+ return isGeneratorInstance(GENERATOR_NAME_SYNC, value);
2855
+ }
2856
+ function isGeneratorInstance(name, value) {
2857
+ return typeof value === "function" && value !== null && value.constructor.name === name && typeof value.prototype.next === "function" && typeof value.prototype.return === "function" && typeof value.prototype.throw === "function";
2782
2858
  }
2783
2859
  /**
2784
2860
  * Is the value a plan?
@@ -2787,7 +2863,10 @@ function isGenerator(value) {
2787
2863
  * @returns `true` if the value is a plan, otherwise `false`
2788
2864
  */
2789
2865
  function isPlan(value) {
2790
- return typeof value === "object" && value !== null && PLAN_SYMBOL in value;
2866
+ return isPlanInstance(PLAN_TYPE_PLAN_SYNC, value);
2867
+ }
2868
+ function isPlanInstance(type, value) {
2869
+ return typeof value === "object" && value !== null && PLAN_SYMBOL in value && value[PLAN_SYMBOL].type === type;
2791
2870
  }
2792
2871
  /**
2793
2872
  * Create a plan for a generator function
@@ -2804,9 +2883,14 @@ function run(input) {
2804
2883
  if (!isGenerator(input)) throw new Error(PLAN_MESSAGE_RUN_INPUT);
2805
2884
  return execute(input);
2806
2885
  }
2886
+ function runAsyncPlan() {
2887
+ return asyncExecute(this[PLAN_SYMBOL].generator);
2888
+ }
2807
2889
  function runPlan() {
2808
2890
  return execute(this[PLAN_SYMBOL].generator);
2809
2891
  }
2892
+ plan.async = asyncPlan;
2893
+ run.async = asyncRun;
2810
2894
  //#endregion
2811
2895
  //#region src/internal/aborter.ts
2812
2896
  function createAborter(value, onAbort) {
@@ -6908,4 +6992,4 @@ var SizedSet = class extends Set {
6908
6992
  }
6909
6993
  };
6910
6994
  //#endregion
6911
- export { CancelablePromise, Logger, PromiseTimeoutError, QueueError, RetryError, SORT_DIRECTION_ASCENDING, SORT_DIRECTION_DESCENDING, SizedMap, SizedSet, push as append, push, assert, assertCondition, assertDefined, assertInstanceOf, assertIs, assertProperty, assign, asyncAttempt, asyncDebounce, asyncFlow, asyncMatchResult, asyncOnce, asyncPipe, asyncThrottle, attempt, attemptAsyncFlow, attemptAsyncPipe, attemptFlow, attemptPipe, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, ceil, chunk, clamp, clone, compact, compare, copy, count, debounce, deburr, dedent, delay, deregisterCloner, deregisterComparator, deregisterEqualizer, diff, difference, drop, endsWith, endsWithArray, equal, error, exclude, exists, filter, filterAndMap, filterAndMap as select, find, findLast, first, firstOrDefault, flatFreeze, flatten, floor, flow, freeze, fromQuery, toPromise as fromResult, toPromise, fuzzy, fuzzyMatch, getArray, getArrayComparison, getColor, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getHwbColor, getHwbaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloatingNumber as getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getSortedIndex, getString, getTimedPromise, getUuid, getValue, groupArraysBy, groupBy, handleResult, hasValue, hasValueResult, herald, hexToHsl, hexToHsla, hexToHwb, hexToHwba, hexToRgb, hexToRgba, hslToHex, hslToHwb, hslToHwba, hslToRgb, hslToRgba, hwbToHex, hwbToHsl, hwbToHsla, hwbToRgb, hwbToRgba, ignoreKey, inMap, inSet, includes, includesArray, indexOf, indexOfArray, initializeAssigner, initializeCloner, initializeEqualizer, initializeMerger, initializeNormalizer, initializeSorter, initializeTemplater, initializeTransformer, insert, interpolate, intersection, isArrayOrPlainObject, isAsyncOnce, isBeacon, isBeaconSubscription, isColor, isConstructor, isEmpty, isError, isFrozen, isFulfilled, isFuzzy, isGenerator, isHerald, isHeraldEvents, isHeraldSubscription, isHexColor, isHslColor, isHslaColor, isHwbColor, isHwbaColor, isInstanceOf, isKey, isKeyedQueue, isLogger, isNonArrayOrPlainObject, isNonConstructor, isNonEmpty, isNonInstanceOf, isNonKey, isNonNullable, isNonNullableOrEmpty, isNonNullableOrWhitespace, isNonNumber, isNonNumerical, isNonObject, isNonPlainObject, isNonPrimitive, isNonTemplateStringsArray, isNonTypedArray, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isObservable, isOk, isOnce, isPlainObject, isPlan, isPrimitive, isQueue, isQueueInstance, isRejected, isResult, isRgbColor, isRgbaColor, isSorted, isSubscription, isSubscriptions, isTemplateStringsArray, isTimeLogger, isTypedArray, join, kebabCase, keyedQueue, last, lastIndexOf, lastOrDefault, lowerCase, mapAndFilter, mapAndFilter as reverseSelect, matchResult, max, median, memoize, merge, min, move, moveIndices, moveToIndex, noop, normalize, ok, omit, once, parse, partition, pascalCase, pick, pipe, plan, promises, queue, range, registerCloner, registerComparator, registerEqualizer, resultPromises, retry, reverse, rgbToHex, rgbToHsl, rgbToHsla, rgbToHwb, rgbToHwba, round, run, setValue, settlePromise, shake, shuffle, single, slice, smush, snakeCase, sort, splice, startsWith, startsWithArray, subscriptions, sum, swap, take, template, throttle, timed, times, titleCase, toMap, toMapArrays, toQuery, toRecord, toRecordArrays, toResult, toSet, toggle, transform, trim, truncate, tryDecode, tryEncode, union, unique, unsmush, unwrap, update, upperCase, words };
6995
+ export { CancelablePromise, Logger, PromiseTimeoutError, QueueError, RetryError, SORT_DIRECTION_ASCENDING, SORT_DIRECTION_DESCENDING, SizedMap, SizedSet, push as append, push, assert, assertCondition, assertDefined, assertInstanceOf, assertIs, assertProperty, assign, asyncAttempt, asyncDebounce, asyncFlow, asyncMatchResult, asyncOnce, asyncPipe, asyncPlan, asyncRun, asyncThrottle, attempt, attemptAsyncFlow, attemptAsyncPipe, attemptFlow, attemptPipe, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, ceil, chunk, clamp, clone, compact, compare, copy, count, debounce, deburr, dedent, delay, deregisterCloner, deregisterComparator, deregisterEqualizer, diff, difference, drop, endsWith, endsWithArray, equal, error, exclude, exists, filter, filterAndMap, filterAndMap as select, find, findLast, first, firstOrDefault, flatFreeze, flatten, floor, flow, freeze, fromQuery, toPromise as fromResult, toPromise, fuzzy, fuzzyMatch, getArray, getArrayComparison, getColor, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getHwbColor, getHwbaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloatingNumber as getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getSortedIndex, getString, getTimedPromise, getUuid, getValue, groupArraysBy, groupBy, handleResult, hasValue, hasValueResult, herald, hexToHsl, hexToHsla, hexToHwb, hexToHwba, hexToRgb, hexToRgba, hslToHex, hslToHwb, hslToHwba, hslToRgb, hslToRgba, hwbToHex, hwbToHsl, hwbToHsla, hwbToRgb, hwbToRgba, ignoreKey, inMap, inSet, includes, includesArray, indexOf, indexOfArray, initializeAssigner, initializeCloner, initializeEqualizer, initializeMerger, initializeNormalizer, initializeSorter, initializeTemplater, initializeTransformer, insert, interpolate, intersection, isArrayOrPlainObject, isAsyncGenerator, isAsyncOnce, isAsyncPlan, isBeacon, isBeaconSubscription, isColor, isConstructor, isEmpty, isError, isFrozen, isFulfilled, isFuzzy, isGenerator, isHerald, isHeraldEvents, isHeraldSubscription, isHexColor, isHslColor, isHslaColor, isHwbColor, isHwbaColor, isInstanceOf, isKey, isKeyedQueue, isLogger, isNonArrayOrPlainObject, isNonConstructor, isNonEmpty, isNonInstanceOf, isNonKey, isNonNullable, isNonNullableOrEmpty, isNonNullableOrWhitespace, isNonNumber, isNonNumerical, isNonObject, isNonPlainObject, isNonPrimitive, isNonTemplateStringsArray, isNonTypedArray, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isObservable, isOk, isOnce, isPlainObject, isPlan, isPrimitive, isQueue, isQueueInstance, isRejected, isResult, isRgbColor, isRgbaColor, isSorted, isSubscription, isSubscriptions, isTemplateStringsArray, isTimeLogger, isTypedArray, join, kebabCase, keyedQueue, last, lastIndexOf, lastOrDefault, lowerCase, mapAndFilter, mapAndFilter as reverseSelect, matchResult, max, median, memoize, merge, min, move, moveIndices, moveToIndex, noop, normalize, ok, omit, once, parse, partition, pascalCase, pick, pipe, plan, promises, queue, range, registerCloner, registerComparator, registerEqualizer, resultPromises, retry, reverse, rgbToHex, rgbToHsl, rgbToHsla, rgbToHwb, rgbToHwba, round, run, setValue, settlePromise, shake, shuffle, single, slice, smush, snakeCase, sort, splice, startsWith, startsWithArray, subscriptions, sum, swap, take, template, throttle, timed, times, titleCase, toMap, toMapArrays, toQuery, toRecord, toRecordArrays, toResult, toSet, toggle, transform, trim, truncate, tryDecode, tryEncode, union, unique, unsmush, unwrap, update, upperCase, words };
@@ -1,23 +1,60 @@
1
+ import { Result } from "./result.model.mjs";
1
2
  //#region src/internal/models/plan.model.d.ts
3
+ /**
4
+ * An asynchronous plan of execution that can yield intermediate results and eventually return a result
5
+ */
6
+ export type AsyncPlan<Value, Error = unknown> = {
7
+ /**
8
+ * Get the asynchronous generator for the plan
9
+ *
10
+ * @returns Asynchronous generator
11
+ */
12
+ [Symbol.asyncIterator]: () => AsyncGenerator<unknown, Value, unknown>;
13
+ /**
14
+ * Run the plan to completion
15
+ *
16
+ * @returns Result
17
+ */
18
+ run: () => Promise<Result<Value, Error>>;
19
+ };
20
+ type AsyncPlanState = {
21
+ generator: () => AsyncGenerator;
22
+ } & BaseState<typeof PLAN_TYPE_PLAN_ASYNC>;
23
+ type BaseState<Type extends PlanType> = {
24
+ type: Type;
25
+ };
26
+ export type InternalAsyncPlan = {
27
+ [PLAN_SYMBOL]: AsyncPlanState;
28
+ } & AsyncPlan<never, never>;
2
29
  export type InternalPlan = {
3
30
  [PLAN_SYMBOL]: PlanState;
4
31
  } & Plan<never, never>;
5
32
  /**
6
- * A plan of execution that can yield intermediate results and eventually return a value or an error.
33
+ * A plan of execution that can yield intermediate results and eventually return a result
7
34
  */
8
- export type Plan<out Value, out Error = unknown> = {
35
+ export type Plan<Value, Error = unknown> = {
36
+ /**
37
+ * Get the generator for the plan
38
+ *
39
+ * @returns Generator
40
+ */
41
+ [Symbol.iterator]: () => Generator<unknown, Value, unknown>;
9
42
  /**
10
43
  * Run the plan to completion
11
44
  *
12
- * @returns Final result, or an error
45
+ * @returns Result
13
46
  */
14
- run: () => Error | Value;
47
+ run: () => Result<Value, Error>;
15
48
  };
16
49
  type PlanState = {
17
50
  generator: () => Generator;
18
- };
19
- export declare const GENERATOR_NAME = "GeneratorFunction";
51
+ } & BaseState<typeof PLAN_TYPE_PLAN_SYNC>;
52
+ export type PlanType = "asyncPlan" | "plan";
53
+ export declare const GENERATOR_NAME_ASYNC = "AsyncGeneratorFunction";
54
+ export declare const GENERATOR_NAME_SYNC = "GeneratorFunction";
20
55
  export declare const PLAN_MESSAGE_PLAN_INPUT = "plan requires a generator function";
21
56
  export declare const PLAN_MESSAGE_RUN_INPUT = "run requires a plan or a generator function";
22
57
  export declare const PLAN_SYMBOL: symbol;
58
+ export declare const PLAN_TYPE_PLAN_ASYNC: PlanType;
59
+ export declare const PLAN_TYPE_PLAN_SYNC: PlanType;
23
60
  //#endregion
@@ -1,7 +1,10 @@
1
1
  //#region src/internal/models/plan.model.ts
2
- const GENERATOR_NAME = "GeneratorFunction";
2
+ const GENERATOR_NAME_ASYNC = "AsyncGeneratorFunction";
3
+ const GENERATOR_NAME_SYNC = "GeneratorFunction";
3
4
  const PLAN_MESSAGE_PLAN_INPUT = "plan requires a generator function";
4
5
  const PLAN_MESSAGE_RUN_INPUT = "run requires a plan or a generator function";
5
6
  const PLAN_SYMBOL = Symbol("plan");
7
+ const PLAN_TYPE_PLAN_ASYNC = "asyncPlan";
8
+ const PLAN_TYPE_PLAN_SYNC = "plan";
6
9
  //#endregion
7
- export { GENERATOR_NAME, PLAN_MESSAGE_PLAN_INPUT, PLAN_MESSAGE_RUN_INPUT, PLAN_SYMBOL };
10
+ export { GENERATOR_NAME_ASYNC, GENERATOR_NAME_SYNC, PLAN_MESSAGE_PLAN_INPUT, PLAN_MESSAGE_RUN_INPUT, PLAN_SYMBOL, PLAN_TYPE_PLAN_ASYNC, PLAN_TYPE_PLAN_SYNC };
@@ -1,5 +1,41 @@
1
- import { Plan } from "../internal/models/plan.model.mjs";
1
+ import { Result } from "../internal/models/result.model.mjs";
2
+ import { AsyncPlan, Plan } from "../internal/models/plan.model.mjs";
2
3
  //#region src/plan/index.d.ts
4
+ /**
5
+ * Create a plan for an asynchronous generator function
6
+ *
7
+ * @param generator Generator to plan for
8
+ * @returns Generator plan
9
+ */
10
+ export declare function asyncPlan<Value = unknown, Error = unknown>(generator: () => AsyncGenerator<unknown, Value, unknown>): AsyncPlan<Value, Error>;
11
+ /**
12
+ * Run an asynchronous generator to completion
13
+ *
14
+ * @param generator Generator to run
15
+ * @returns Result
16
+ */
17
+ export declare function asyncRun<Value = unknown, Error = unknown>(generator: () => AsyncGenerator<unknown, Value, unknown>): Promise<Result<Value, Error>>;
18
+ /**
19
+ * Run an asynchronous plan to completion
20
+ *
21
+ * @param plan Plan to run
22
+ * @returns Result
23
+ */
24
+ export declare function asyncRun<Value = unknown, Error = unknown>(plan: AsyncPlan<Value, Error>): Promise<Result<Value, Error>>;
25
+ /**
26
+ * Is the value an asynchronous plan?
27
+ *
28
+ * @param value Value to check
29
+ * @returns `true` if the value is an asynchronous plan, otherwise `false`
30
+ */
31
+ export declare function isAsyncPlan<Value = unknown, Error = unknown>(value: unknown): value is AsyncPlan<Value, Error>;
32
+ /**
33
+ * Is the value an asynchronous generator function?
34
+ *
35
+ * @param value Value to check
36
+ * @returns `true` if the value is an asynchronous generator function, otherwise `false`
37
+ */
38
+ export declare function isAsyncGenerator(value: unknown): value is () => AsyncGenerator;
3
39
  /**
4
40
  * Is the value a generator function?
5
41
  *
@@ -25,14 +61,20 @@ export declare function plan<Value = unknown, Error = unknown>(generator: () =>
25
61
  * Run a generator to completion
26
62
  *
27
63
  * @param generator Generator to run
28
- * @returns Final result, or an error
64
+ * @returns Result
29
65
  */
30
- export declare function run<Value = unknown, Error = unknown>(generator: () => Generator<unknown, Value, unknown>): Error | Value;
66
+ export declare function run<Value = unknown, Error = unknown>(generator: () => Generator<unknown, Value, unknown>): Result<Value, Error>;
31
67
  /**
32
68
  * Run a plan to completion
33
69
  *
34
70
  * @param plan Plan to run
35
- * @returns Final result, or an error
71
+ * @returns Result
36
72
  */
37
- export declare function run<Value = unknown, Error = unknown>(plan: Plan<Value, Error>): Error | Value;
73
+ export declare function run<Value = unknown, Error = unknown>(plan: Plan<Value, Error>): Result<Value, Error>;
74
+ export declare namespace plan {
75
+ export var async: typeof asyncPlan;
76
+ }
77
+ export declare namespace run {
78
+ export var async: typeof asyncRun;
79
+ }
38
80
  //#endregion
@@ -1,12 +1,62 @@
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";
1
+ import { isError, isOk } from "../internal/result/misc.mjs";
2
+ import "../result/misc.mjs";
3
+ import { asyncAttempt, attempt } from "../internal/result/attempt.mjs";
4
+ import { GENERATOR_NAME_ASYNC, GENERATOR_NAME_SYNC, PLAN_MESSAGE_PLAN_INPUT, PLAN_MESSAGE_RUN_INPUT, PLAN_SYMBOL, PLAN_TYPE_PLAN_ASYNC, PLAN_TYPE_PLAN_SYNC } from "../internal/models/plan.model.mjs";
3
5
  //#region src/plan/index.ts
6
+ function AsyncPlan(generator) {
7
+ this[PLAN_SYMBOL] = {
8
+ generator,
9
+ type: PLAN_TYPE_PLAN_ASYNC
10
+ };
11
+ }
12
+ AsyncPlan.prototype[Symbol.asyncIterator] = function() {
13
+ return this[PLAN_SYMBOL].generator();
14
+ };
15
+ AsyncPlan.prototype.run = runAsyncPlan;
4
16
  function Plan(generator) {
5
- this[PLAN_SYMBOL] = { generator };
17
+ this[PLAN_SYMBOL] = {
18
+ generator,
19
+ type: PLAN_TYPE_PLAN_SYNC
20
+ };
6
21
  }
22
+ Plan.prototype[Symbol.iterator] = function() {
23
+ return this[PLAN_SYMBOL].generator();
24
+ };
7
25
  Plan.prototype.run = runPlan;
26
+ function asyncExecute(callback) {
27
+ return asyncAttempt(async () => {
28
+ const generator = callback();
29
+ let lastValue;
30
+ while (true) {
31
+ const next = await generator.next();
32
+ const { done } = next;
33
+ let value = next.value;
34
+ if (value instanceof Error) throw value;
35
+ if (isError(value)) throw value.error;
36
+ if (isOk(value)) value = value.value;
37
+ lastValue = value;
38
+ if (done === true) break;
39
+ }
40
+ return lastValue;
41
+ });
42
+ }
43
+ /**
44
+ * Create a plan for an asynchronous generator function
45
+ *
46
+ * @param generator Generator to plan for
47
+ * @returns Generator plan
48
+ */
49
+ function asyncPlan(generator) {
50
+ if (!isAsyncGenerator(generator)) throw new Error(PLAN_MESSAGE_PLAN_INPUT);
51
+ return new AsyncPlan(generator);
52
+ }
53
+ async function asyncRun(input) {
54
+ if (isAsyncPlan(input)) return input.run();
55
+ if (!isAsyncGenerator(input)) throw new Error(PLAN_MESSAGE_RUN_INPUT);
56
+ return asyncExecute(input);
57
+ }
8
58
  function execute(callback) {
9
- const result = attempt(() => {
59
+ return attempt(() => {
10
60
  const generator = callback();
11
61
  let lastValue;
12
62
  while (true) {
@@ -14,12 +64,31 @@ function execute(callback) {
14
64
  const { done } = next;
15
65
  let { value } = next;
16
66
  if (value instanceof Error) throw value;
67
+ if (isError(value)) throw value.error;
68
+ if (isOk(value)) value = value.value;
17
69
  lastValue = value;
18
70
  if (done === true) break;
19
71
  }
20
72
  return lastValue;
21
73
  });
22
- return result.ok ? result.value : result.error;
74
+ }
75
+ /**
76
+ * Is the value an asynchronous plan?
77
+ *
78
+ * @param value Value to check
79
+ * @returns `true` if the value is an asynchronous plan, otherwise `false`
80
+ */
81
+ function isAsyncPlan(value) {
82
+ return isPlanInstance(PLAN_TYPE_PLAN_ASYNC, value);
83
+ }
84
+ /**
85
+ * Is the value an asynchronous generator function?
86
+ *
87
+ * @param value Value to check
88
+ * @returns `true` if the value is an asynchronous generator function, otherwise `false`
89
+ */
90
+ function isAsyncGenerator(value) {
91
+ return isGeneratorInstance(GENERATOR_NAME_ASYNC, value);
23
92
  }
24
93
  /**
25
94
  * Is the value a generator function?
@@ -28,7 +97,10 @@ function execute(callback) {
28
97
  * @returns `true` if the value is a generator function, otherwise `false`
29
98
  */
30
99
  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";
100
+ return isGeneratorInstance(GENERATOR_NAME_SYNC, value);
101
+ }
102
+ function isGeneratorInstance(name, value) {
103
+ return typeof value === "function" && value !== null && value.constructor.name === name && typeof value.prototype.next === "function" && typeof value.prototype.return === "function" && typeof value.prototype.throw === "function";
32
104
  }
33
105
  /**
34
106
  * Is the value a plan?
@@ -37,7 +109,10 @@ function isGenerator(value) {
37
109
  * @returns `true` if the value is a plan, otherwise `false`
38
110
  */
39
111
  function isPlan(value) {
40
- return typeof value === "object" && value !== null && PLAN_SYMBOL in value;
112
+ return isPlanInstance(PLAN_TYPE_PLAN_SYNC, value);
113
+ }
114
+ function isPlanInstance(type, value) {
115
+ return typeof value === "object" && value !== null && PLAN_SYMBOL in value && value[PLAN_SYMBOL].type === type;
41
116
  }
42
117
  /**
43
118
  * Create a plan for a generator function
@@ -54,8 +129,13 @@ function run(input) {
54
129
  if (!isGenerator(input)) throw new Error(PLAN_MESSAGE_RUN_INPUT);
55
130
  return execute(input);
56
131
  }
132
+ function runAsyncPlan() {
133
+ return asyncExecute(this[PLAN_SYMBOL].generator);
134
+ }
57
135
  function runPlan() {
58
136
  return execute(this[PLAN_SYMBOL].generator);
59
137
  }
138
+ plan.async = asyncPlan;
139
+ run.async = asyncRun;
60
140
  //#endregion
61
- export { isGenerator, isPlan, plan, run };
141
+ export { asyncPlan, asyncRun, isAsyncGenerator, isAsyncPlan, isGenerator, isPlan, plan, run };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oscarpalmer/atoms",
3
- "version": "0.207.0",
3
+ "version": "0.209.0",
4
4
  "description": "Atomic utilities for making your JavaScript better.",
5
5
  "keywords": [
6
6
  "array",