@duplojs/utils 1.5.15 → 1.6.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 (68) hide show
  1. package/dist/clean/primitive/operations/equal.d.ts +3 -3
  2. package/dist/common/kind.cjs +2 -1
  3. package/dist/common/kind.d.ts +1 -0
  4. package/dist/common/kind.mjs +2 -1
  5. package/dist/flow/breakIf.cjs +14 -0
  6. package/dist/flow/breakIf.d.ts +50 -0
  7. package/dist/flow/breakIf.mjs +12 -0
  8. package/dist/flow/defer.cjs +12 -0
  9. package/dist/flow/defer.d.ts +47 -0
  10. package/dist/flow/defer.mjs +10 -0
  11. package/dist/flow/exec.cjs +125 -0
  12. package/dist/flow/exec.d.ts +83 -0
  13. package/dist/flow/exec.mjs +123 -0
  14. package/dist/flow/exitIf.cjs +14 -0
  15. package/dist/flow/exitIf.d.ts +67 -0
  16. package/dist/flow/exitIf.mjs +12 -0
  17. package/dist/flow/finalizer.cjs +12 -0
  18. package/dist/flow/finalizer.d.ts +47 -0
  19. package/dist/flow/finalizer.mjs +10 -0
  20. package/dist/flow/index.cjs +50 -0
  21. package/dist/flow/index.d.ts +12 -0
  22. package/dist/flow/index.mjs +18 -0
  23. package/dist/flow/initializer.cjs +38 -0
  24. package/dist/flow/initializer.d.ts +75 -0
  25. package/dist/flow/initializer.mjs +36 -0
  26. package/dist/flow/inject.cjs +19 -0
  27. package/dist/flow/inject.d.ts +46 -0
  28. package/dist/flow/inject.mjs +17 -0
  29. package/dist/flow/kind.cjs +9 -0
  30. package/dist/flow/kind.d.ts +1 -0
  31. package/dist/flow/kind.mjs +7 -0
  32. package/dist/flow/run.cjs +139 -0
  33. package/dist/flow/run.d.ts +80 -0
  34. package/dist/flow/run.mjs +136 -0
  35. package/dist/flow/step.cjs +23 -0
  36. package/dist/flow/step.d.ts +39 -0
  37. package/dist/flow/step.mjs +21 -0
  38. package/dist/flow/theFlow/break.cjs +11 -0
  39. package/dist/flow/theFlow/break.d.ts +7 -0
  40. package/dist/flow/theFlow/break.mjs +8 -0
  41. package/dist/flow/theFlow/defer.cjs +11 -0
  42. package/dist/flow/theFlow/defer.d.ts +5 -0
  43. package/dist/flow/theFlow/defer.mjs +8 -0
  44. package/dist/flow/theFlow/dependence.cjs +17 -0
  45. package/dist/flow/theFlow/dependence.d.ts +50 -0
  46. package/dist/flow/theFlow/dependence.mjs +14 -0
  47. package/dist/flow/theFlow/exit.cjs +11 -0
  48. package/dist/flow/theFlow/exit.d.ts +7 -0
  49. package/dist/flow/theFlow/exit.mjs +8 -0
  50. package/dist/flow/theFlow/finalizer.cjs +11 -0
  51. package/dist/flow/theFlow/finalizer.d.ts +5 -0
  52. package/dist/flow/theFlow/finalizer.mjs +8 -0
  53. package/dist/flow/theFlow/index.cjs +14 -0
  54. package/dist/flow/theFlow/index.d.ts +85 -0
  55. package/dist/flow/theFlow/index.mjs +11 -0
  56. package/dist/flow/theFlow/injection.cjs +11 -0
  57. package/dist/flow/theFlow/injection.d.ts +10 -0
  58. package/dist/flow/theFlow/injection.mjs +8 -0
  59. package/dist/flow/theFlow/step.cjs +11 -0
  60. package/dist/flow/theFlow/step.d.ts +5 -0
  61. package/dist/flow/theFlow/step.mjs +8 -0
  62. package/dist/flow/types/index.d.ts +1 -0
  63. package/dist/index.cjs +3 -0
  64. package/dist/index.d.ts +2 -0
  65. package/dist/index.mjs +3 -0
  66. package/dist/metadata.json +189 -0
  67. package/dist/object/types/requireAtLeastOne.d.ts +2 -1
  68. package/package.json +6 -1
@@ -1,4 +1,4 @@
1
- import { type ToLargeEnsemble, type Unwrap } from "../../../common";
1
+ import { type Unwrap } from "../../../common";
2
2
  import { type Primitive, type Primitives } from "../base";
3
3
  /**
4
4
  * Compares two wrapped primitives (or a primitive and a raw value) with a type guard.
@@ -34,5 +34,5 @@ import { type Primitive, type Primitives } from "../base";
34
34
  * @namespace C
35
35
  *
36
36
  */
37
- export declare function equal<GenericInput extends Primitives, GenericValue extends (Primitive<ToLargeEnsemble<Unwrap<GenericInput>>> | ToLargeEnsemble<Unwrap<GenericInput>>)>(value: GenericValue): (input: GenericInput) => input is GenericInput & Primitive<Unwrap<GenericValue>>;
38
- export declare function equal<GenericInput extends Primitives, GenericValue extends (Primitive<ToLargeEnsemble<Unwrap<GenericInput>>> | ToLargeEnsemble<Unwrap<GenericInput>>)>(input: GenericInput, value: GenericValue): input is GenericInput & Primitive<Unwrap<GenericValue>>;
37
+ export declare function equal<GenericInput extends Primitives, GenericValue extends (Primitive<Unwrap<GenericInput>> | Unwrap<GenericInput>)>(value: GenericValue): (input: GenericInput) => input is GenericInput & Primitive<Unwrap<GenericValue>>;
38
+ export declare function equal<GenericInput extends Primitives, GenericValue extends (Primitive<Unwrap<GenericInput>> | Unwrap<GenericInput>)>(input: GenericInput, value: GenericValue): input is GenericInput & Primitive<Unwrap<GenericValue>>;
@@ -24,7 +24,8 @@ function createKind(name) {
24
24
  },
25
25
  has(input) {
26
26
  return input
27
- && typeof input === "object"
27
+ && (typeof input === "object"
28
+ || typeof input === "function")
28
29
  && runTimeKey in input;
29
30
  },
30
31
  getValue(input) {
@@ -94,6 +94,7 @@ export interface ReservedKindNamespace {
94
94
  DuplojsUtilsError: true;
95
95
  DuplojsUtilsClean: true;
96
96
  DuplojsUtilsDate: true;
97
+ DuplojsUtilsFlow: true;
97
98
  }
98
99
  type ForbiddenKindNamespace<GenericValue extends string> = (ForbiddenKindCharacters<GenericValue> & ForbiddenString<GenericValue, GetPropsWithValue<ReservedKindNamespace, true>>);
99
100
  /**
@@ -22,7 +22,8 @@ function createKind(name) {
22
22
  },
23
23
  has(input) {
24
24
  return input
25
- && typeof input === "object"
25
+ && (typeof input === "object"
26
+ || typeof input === "function")
26
27
  && runTimeKey in input;
27
28
  },
28
29
  getValue(input) {
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+
3
+ var _break = require('./theFlow/break.cjs');
4
+
5
+ function* breakIf(value, thePredicate) {
6
+ if (thePredicate(value) === true) {
7
+ yield _break.createBreak(value);
8
+ }
9
+ else {
10
+ return value;
11
+ }
12
+ }
13
+
14
+ exports.breakIf = breakIf;
@@ -0,0 +1,50 @@
1
+ import { type NeverCoalescing } from "../common";
2
+ import { type Break } from "./theFlow";
3
+ /**
4
+ * Breaks a flow when a predicate matches a value.
5
+ *
6
+ * **Supported call styles:**
7
+ * - Classic boolean predicate: `breakIf(value, thePredicate)` -> yields a break effect or returns the value
8
+ * - Classic predicate overload: `breakIf(value, thePredicate)` -> narrows the matched value type before breaking
9
+ *
10
+ * `breakIf` is designed to be used inside `F.run(...)` or a nested flow executed by `F.exec(...)`.
11
+ * When the predicate returns `true`, the current flow stops with the provided value as a break result.
12
+ * When the predicate returns `false`, the original value is returned and the flow continues normally.
13
+ *
14
+ * ```ts
15
+ * F.run(
16
+ * function *() {
17
+ * yield *F.breakIf(2, (value) => value === 2);
18
+ *
19
+ * return "test";
20
+ * },
21
+ * ); // 2
22
+ *
23
+ * F.run(
24
+ * function *() {
25
+ * const value = yield *F.breakIf("keep", (value) => value === "stop");
26
+ * return value;
27
+ * },
28
+ * ); // "keep"
29
+ *
30
+ * F.run(
31
+ * function *() {
32
+ * yield *F.step("before break");
33
+ * yield *F.breakIf(2, (value) => value === 2);
34
+ * return "done";
35
+ * },
36
+ * { includeDetails: true },
37
+ * ); // { result: 2, steps: ["before break"] }
38
+ * ```
39
+ *
40
+ * @remarks
41
+ * - Use `breakIf` to stop the current flow without exiting outer flows
42
+ *
43
+ * @see [`F.exitIf`](https://utils.duplojs.dev/en/v1/api/flow/exitIf) To exit a flow instead of breaking it
44
+ * @see https://utils.duplojs.dev/en/v1/api/flow/breakIf
45
+ *
46
+ * @namespace F
47
+ *
48
+ */
49
+ export declare function breakIf<GenericValue extends unknown, GenericPredicate extends GenericValue>(value: GenericValue, thePredicate: (value: GenericValue) => value is GenericPredicate): Generator<Break<NeverCoalescing<Extract<GenericValue, GenericPredicate>, GenericPredicate>>, Exclude<GenericValue, GenericPredicate>>;
50
+ export declare function breakIf<GenericValue extends unknown>(value: GenericValue, thePredicate: (value: GenericValue) => boolean): Generator<Break<GenericValue>, GenericValue>;
@@ -0,0 +1,12 @@
1
+ import { createBreak } from './theFlow/break.mjs';
2
+
3
+ function* breakIf(value, thePredicate) {
4
+ if (thePredicate(value) === true) {
5
+ yield createBreak(value);
6
+ }
7
+ else {
8
+ return value;
9
+ }
10
+ }
11
+
12
+ export { breakIf };
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ var defer$1 = require('./theFlow/defer.cjs');
4
+
5
+ /**
6
+ * {@include flow/defer/index.md}
7
+ */
8
+ function* defer(theFunction) {
9
+ yield defer$1.createDefer(theFunction);
10
+ }
11
+
12
+ exports.defer = defer;
@@ -0,0 +1,47 @@
1
+ import { type Defer } from "./theFlow";
2
+ /**
3
+ * Registers a cleanup callback that runs when the flow finishes.
4
+ *
5
+ * **Supported call styles:**
6
+ * - Classic: `defer(theFunction)` -> yields a defer effect
7
+ *
8
+ * `defer` stores a callback that is executed after the flow has completed.
9
+ * It is useful for releasing resources, closing handles, or running cleanup logic after a `break` or a normal return.
10
+ * Use it inside `F.run(...)` or inside subflows executed by `F.exec(...)`.
11
+ *
12
+ * ```ts
13
+ * F.run(
14
+ * function *() {
15
+ * yield *F.defer(() => void console.log("close connection"));
16
+ * return "done";
17
+ * },
18
+ * ); // "done"
19
+ *
20
+ * F.run(
21
+ * function *() {
22
+ * yield *F.defer(() => void console.log("clear cache"));
23
+ * yield *F.breakIf(2, (value) => value === 2);
24
+ * return "done";
25
+ * },
26
+ * ); // 2
27
+ *
28
+ * await F.run(
29
+ * async function *() {
30
+ * yield *F.defer(async() => {
31
+ * await Promise.resolve();
32
+ * });
33
+ * return Promise.resolve("done");
34
+ * },
35
+ * ); // Promise<"done">
36
+ * ```
37
+ *
38
+ * @remarks
39
+ * - Deferred callbacks run after the flow result has been computed
40
+ *
41
+ * @see [`F.finalizer`](https://utils.duplojs.dev/en/v1/api/flow/finalizer) To register final logic in the same flow system
42
+ * @see https://utils.duplojs.dev/en/v1/api/flow/defer
43
+ *
44
+ * @namespace F
45
+ *
46
+ */
47
+ export declare function defer<GenericOutput extends unknown>(theFunction: () => GenericOutput): (Generator<Defer<GenericOutput>, undefined> | (GenericOutput extends Promise<unknown> ? AsyncGenerator<Defer<GenericOutput>, undefined> : never));
@@ -0,0 +1,10 @@
1
+ import { createDefer } from './theFlow/defer.mjs';
2
+
3
+ /**
4
+ * {@include flow/defer/index.md}
5
+ */
6
+ function* defer(theFunction) {
7
+ yield createDefer(theFunction);
8
+ }
9
+
10
+ export { defer };
@@ -0,0 +1,125 @@
1
+ 'use strict';
2
+
3
+ var index = require('./theFlow/index.cjs');
4
+ var defer = require('./theFlow/defer.cjs');
5
+ var finalizer = require('./theFlow/finalizer.cjs');
6
+ var justExec = require('../common/justExec.cjs');
7
+ var _break = require('./theFlow/break.cjs');
8
+ var exit = require('./theFlow/exit.cjs');
9
+ var step = require('./theFlow/step.cjs');
10
+ var injection = require('./theFlow/injection.cjs');
11
+ var dependence = require('./theFlow/dependence.cjs');
12
+ var forward = require('../common/forward.cjs');
13
+
14
+ /**
15
+ * {@include flow/exec/index.md}
16
+ */
17
+ function exec(theFlow, ...[params]) {
18
+ let result = undefined;
19
+ let deferFunctions = undefined;
20
+ const generator = justExec.justExec(() => {
21
+ if (Symbol.asyncIterator in theFlow || Symbol.iterator in theFlow) {
22
+ return forward.forward(theFlow);
23
+ }
24
+ else if (typeof theFlow === "function") {
25
+ return theFlow(params?.input);
26
+ }
27
+ else {
28
+ return index.theFlowKind.getValue(theFlow).run(params?.input);
29
+ }
30
+ });
31
+ if (Symbol.asyncIterator in generator) {
32
+ return (async function* () {
33
+ try {
34
+ do {
35
+ result = await generator.next();
36
+ if (result.done === true) {
37
+ break;
38
+ }
39
+ else if (_break.breakKind.has(result.value)) {
40
+ result = await generator.return(_break.breakKind.getValue(result.value).value);
41
+ break;
42
+ }
43
+ else if (exit.exitKind.has(result.value)) {
44
+ yield result.value;
45
+ }
46
+ else if (defer.deferKind.has(result.value)) {
47
+ deferFunctions ??= [];
48
+ deferFunctions.push(defer.deferKind.getValue(result.value));
49
+ }
50
+ else if (finalizer.finalizerKind.has(result.value)) {
51
+ yield result.value;
52
+ }
53
+ else if (step.stepKind.has(result.value)) {
54
+ yield result.value;
55
+ }
56
+ else if (injection.injectionKind.has(result.value)) {
57
+ const injectionProperties = injection.injectionKind.getValue(result.value);
58
+ const dependenceName = dependence.dependenceHandlerKind.getValue(injectionProperties.dependenceHandler);
59
+ if (!params?.dependencies
60
+ || !(dependenceName in params.dependencies)) {
61
+ yield result.value;
62
+ }
63
+ else {
64
+ injectionProperties.inject(params.dependencies[dependenceName]);
65
+ }
66
+ }
67
+ } while (true);
68
+ return result.value;
69
+ }
70
+ finally {
71
+ await generator.return(undefined);
72
+ if (deferFunctions) {
73
+ await Promise.all(deferFunctions.map(justExec.justExec));
74
+ }
75
+ }
76
+ })();
77
+ }
78
+ return (function* () {
79
+ try {
80
+ do {
81
+ result = generator.next();
82
+ if (result.done === true) {
83
+ break;
84
+ }
85
+ else if (_break.breakKind.has(result.value)) {
86
+ result = generator.return(_break.breakKind.getValue(result.value).value);
87
+ break;
88
+ }
89
+ else if (exit.exitKind.has(result.value)) {
90
+ yield result.value;
91
+ }
92
+ else if (defer.deferKind.has(result.value)) {
93
+ deferFunctions ??= [];
94
+ deferFunctions.push(defer.deferKind.getValue(result.value));
95
+ }
96
+ else if (finalizer.finalizerKind.has(result.value)) {
97
+ yield result.value;
98
+ }
99
+ else if (step.stepKind.has(result.value)) {
100
+ yield result.value;
101
+ }
102
+ else if (injection.injectionKind.has(result.value)) {
103
+ const injectionProperties = injection.injectionKind.getValue(result.value);
104
+ const dependenceName = dependence.dependenceHandlerKind.getValue(injectionProperties.dependenceHandler);
105
+ if (!params?.dependencies
106
+ || !(dependenceName in params.dependencies)) {
107
+ yield result.value;
108
+ }
109
+ else {
110
+ injectionProperties.inject(params.dependencies[dependenceName]);
111
+ }
112
+ }
113
+ } while (true);
114
+ return result.value;
115
+ }
116
+ finally {
117
+ generator.return(undefined);
118
+ if (deferFunctions) {
119
+ deferFunctions.map(justExec.justExec);
120
+ }
121
+ }
122
+ })();
123
+ }
124
+
125
+ exports.exec = exec;
@@ -0,0 +1,83 @@
1
+ import { type SimplifyTopLevel, type IsEqual, type IsExtends, type Or } from "../common";
2
+ import { type TheFlowGenerator, type TheFlow, type TheFlowFunction, type FlowInput, type WrapFlow, type Exit, type Break, type Injection, type Step, type FlowDependencies } from "./theFlow";
3
+ import { type Finalizer } from "./theFlow/finalizer";
4
+ type ComputeExecParams<GenericInput extends unknown, GenericDependencies extends Record<string, unknown>> = SimplifyTopLevel<(Or<[
5
+ IsEqual<GenericInput, unknown>,
6
+ IsEqual<GenericInput, never>,
7
+ IsExtends<GenericInput, undefined>
8
+ ]> extends true ? {
9
+ input?: GenericInput;
10
+ } : {
11
+ input: GenericInput;
12
+ }) & {
13
+ dependencies?: GenericDependencies;
14
+ }>;
15
+ export type ExecResult<GenericFlow extends TheFlow> = GenericFlow extends TheFlow<infer InferredFunction> ? InferredFunction extends TheFlowFunction<any, infer InferredGenerator> ? InferredGenerator extends TheFlowGenerator<infer InferredOutput, infer InferredEffect> ? [
16
+ ((InferredEffect extends Break<infer InferredValue> ? InferredValue : never) | InferredOutput),
17
+ Extract<InferredEffect, Exit | Injection | Finalizer | Step>
18
+ ] extends [
19
+ infer InferredOutput,
20
+ infer InferredEffect
21
+ ] ? InferredGenerator extends AsyncGenerator ? AsyncGenerator<InferredEffect, InferredOutput> : Generator<InferredEffect, InferredOutput> : never : never : never : never;
22
+ /**
23
+ * Executes a nested flow inside the current flow.
24
+ *
25
+ * **Supported call styles:**
26
+ * - Classic with a flow function: `exec(theFlow, params?)` -> runs the provided flow function
27
+ * - Classic with a flow instance: `exec(theFlow, params?)` -> runs a flow created with `F.create(...)`
28
+ * - Classic with a generator: `exec(theGenerator, params?)` -> runs an existing generator directly
29
+ *
30
+ * `exec` lets a parent flow call another flow while staying in the same execution model.
31
+ * Break values are converted into the local return value of `exec`, while exit, step, injection, and finalizer effects are forwarded to the outer flow.
32
+ * It can be used in synchronous and asynchronous flows.
33
+ *
34
+ * ```ts
35
+ *
36
+ * const upperCaseFlow = F.create(
37
+ * function *(input: string) {
38
+ * return input.toUpperCase();
39
+ * },
40
+ * );
41
+ *
42
+ * const userFlow = F.create(
43
+ * function *(id: number) {
44
+ * return `user-${id}`;
45
+ * },
46
+ * );
47
+ *
48
+ * const breakableFlow = F.create(
49
+ * function *(value: number) {
50
+ * yield *F.breakIf(value, (current) => current === 2);
51
+ * return "done";
52
+ * },
53
+ * );
54
+ *
55
+ * F.run(
56
+ * function *() {
57
+ * return yield *F.exec(upperCaseFlow, { input: "hello" });
58
+ * },
59
+ * ); // "HELLO"
60
+ *
61
+ * F.run(
62
+ * function *() {
63
+ * return yield *F.exec(userFlow, { input: 42 });
64
+ * },
65
+ * ); // "user-42"
66
+ *
67
+ * F.run(
68
+ * function *() {
69
+ * return yield *F.exec(breakableFlow, { input: 2 });
70
+ * },
71
+ * ```
72
+ *
73
+ * @remarks
74
+ * - `exec` is useful for composing small flows into larger ones
75
+ *
76
+ * @see [`F.run`](https://utils.duplojs.dev/en/v1/api/flow/run) To execute the root flow
77
+ * @see https://utils.duplojs.dev/en/v1/api/flow/exec
78
+ *
79
+ * @namespace F
80
+ *
81
+ */
82
+ export declare function exec<GenericFlow extends (TheFlowFunction | TheFlow | TheFlowGenerator), GenericWrapFlow extends WrapFlow<GenericFlow>, const GenericParams extends ComputeExecParams<FlowInput<GenericWrapFlow>, FlowDependencies<GenericWrapFlow>>>(theFlow: GenericFlow, ...[params]: ({} extends GenericParams ? [params?: GenericParams] : [params: GenericParams])): ExecResult<WrapFlow<GenericFlow>>;
83
+ export {};
@@ -0,0 +1,123 @@
1
+ import { theFlowKind } from './theFlow/index.mjs';
2
+ import { deferKind } from './theFlow/defer.mjs';
3
+ import { finalizerKind } from './theFlow/finalizer.mjs';
4
+ import { justExec } from '../common/justExec.mjs';
5
+ import { breakKind } from './theFlow/break.mjs';
6
+ import { exitKind } from './theFlow/exit.mjs';
7
+ import { stepKind } from './theFlow/step.mjs';
8
+ import { injectionKind } from './theFlow/injection.mjs';
9
+ import { dependenceHandlerKind } from './theFlow/dependence.mjs';
10
+ import { forward } from '../common/forward.mjs';
11
+
12
+ /**
13
+ * {@include flow/exec/index.md}
14
+ */
15
+ function exec(theFlow, ...[params]) {
16
+ let result = undefined;
17
+ let deferFunctions = undefined;
18
+ const generator = justExec(() => {
19
+ if (Symbol.asyncIterator in theFlow || Symbol.iterator in theFlow) {
20
+ return forward(theFlow);
21
+ }
22
+ else if (typeof theFlow === "function") {
23
+ return theFlow(params?.input);
24
+ }
25
+ else {
26
+ return theFlowKind.getValue(theFlow).run(params?.input);
27
+ }
28
+ });
29
+ if (Symbol.asyncIterator in generator) {
30
+ return (async function* () {
31
+ try {
32
+ do {
33
+ result = await generator.next();
34
+ if (result.done === true) {
35
+ break;
36
+ }
37
+ else if (breakKind.has(result.value)) {
38
+ result = await generator.return(breakKind.getValue(result.value).value);
39
+ break;
40
+ }
41
+ else if (exitKind.has(result.value)) {
42
+ yield result.value;
43
+ }
44
+ else if (deferKind.has(result.value)) {
45
+ deferFunctions ??= [];
46
+ deferFunctions.push(deferKind.getValue(result.value));
47
+ }
48
+ else if (finalizerKind.has(result.value)) {
49
+ yield result.value;
50
+ }
51
+ else if (stepKind.has(result.value)) {
52
+ yield result.value;
53
+ }
54
+ else if (injectionKind.has(result.value)) {
55
+ const injectionProperties = injectionKind.getValue(result.value);
56
+ const dependenceName = dependenceHandlerKind.getValue(injectionProperties.dependenceHandler);
57
+ if (!params?.dependencies
58
+ || !(dependenceName in params.dependencies)) {
59
+ yield result.value;
60
+ }
61
+ else {
62
+ injectionProperties.inject(params.dependencies[dependenceName]);
63
+ }
64
+ }
65
+ } while (true);
66
+ return result.value;
67
+ }
68
+ finally {
69
+ await generator.return(undefined);
70
+ if (deferFunctions) {
71
+ await Promise.all(deferFunctions.map(justExec));
72
+ }
73
+ }
74
+ })();
75
+ }
76
+ return (function* () {
77
+ try {
78
+ do {
79
+ result = generator.next();
80
+ if (result.done === true) {
81
+ break;
82
+ }
83
+ else if (breakKind.has(result.value)) {
84
+ result = generator.return(breakKind.getValue(result.value).value);
85
+ break;
86
+ }
87
+ else if (exitKind.has(result.value)) {
88
+ yield result.value;
89
+ }
90
+ else if (deferKind.has(result.value)) {
91
+ deferFunctions ??= [];
92
+ deferFunctions.push(deferKind.getValue(result.value));
93
+ }
94
+ else if (finalizerKind.has(result.value)) {
95
+ yield result.value;
96
+ }
97
+ else if (stepKind.has(result.value)) {
98
+ yield result.value;
99
+ }
100
+ else if (injectionKind.has(result.value)) {
101
+ const injectionProperties = injectionKind.getValue(result.value);
102
+ const dependenceName = dependenceHandlerKind.getValue(injectionProperties.dependenceHandler);
103
+ if (!params?.dependencies
104
+ || !(dependenceName in params.dependencies)) {
105
+ yield result.value;
106
+ }
107
+ else {
108
+ injectionProperties.inject(params.dependencies[dependenceName]);
109
+ }
110
+ }
111
+ } while (true);
112
+ return result.value;
113
+ }
114
+ finally {
115
+ generator.return(undefined);
116
+ if (deferFunctions) {
117
+ deferFunctions.map(justExec);
118
+ }
119
+ }
120
+ })();
121
+ }
122
+
123
+ export { exec };
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+
3
+ var exit = require('./theFlow/exit.cjs');
4
+
5
+ function* exitIf(value, thePredicate) {
6
+ if (thePredicate(value) === true) {
7
+ yield exit.createExit(value);
8
+ }
9
+ else {
10
+ return value;
11
+ }
12
+ }
13
+
14
+ exports.exitIf = exitIf;
@@ -0,0 +1,67 @@
1
+ import { type NeverCoalescing } from "../common";
2
+ import { type Exit } from "./theFlow";
3
+ /**
4
+ * Exits a flow when a predicate matches a value.
5
+ *
6
+ * **Supported call styles:**
7
+ * - Classic boolean predicate: `exitIf(value, thePredicate)` -> yields an exit effect or returns the value
8
+ * - Classic predicate overload: `exitIf(value, thePredicate)` -> narrows the matched value type before exiting
9
+ *
10
+ * `exitIf` is designed to be used inside `F.run(...)` or a nested flow executed by `F.exec(...)`.
11
+ * When the predicate returns `true`, the current flow exits with the provided value.
12
+ * When the predicate returns `false`, the original value is returned and the flow continues normally.
13
+ * Because the exit effect is forwarded through nested `exec(...)` calls, it can stop a deeply nested flow from any depth.
14
+ *
15
+ * ```ts
16
+ * const thirdLevelFlow = F.create(
17
+ * function *() {
18
+ * yield *F.exitIf("stop", (value) => value === "stop");
19
+ * return "done";
20
+ * },
21
+ * );
22
+ *
23
+ * const secondLevelFlow = F.create(
24
+ * function *() {
25
+ * return yield *F.exec(thirdLevelFlow);
26
+ * },
27
+ * );
28
+ *
29
+ * const firstLevelFlow = F.create(
30
+ * function *() {
31
+ * return yield *F.exec(secondLevelFlow);
32
+ * },
33
+ * );
34
+ *
35
+ * F.run(
36
+ * function *() {
37
+ * return yield *F.exitIf(2, (value) => value === 2);
38
+ * },
39
+ * ); // 2
40
+ *
41
+ * F.run(
42
+ * function *() {
43
+ * const value = yield *F.exitIf("keep", (value) => value === "stop");
44
+ * return value;
45
+ * },
46
+ * ); // "keep"
47
+ *
48
+ * F.run(
49
+ * function *() {
50
+ * yield *F.step("before deep exit");
51
+ * return yield *F.exec(firstLevelFlow);
52
+ * },
53
+ * { includeDetails: true },
54
+ * ); // { result: "stop", steps: ["before deep exit"] }
55
+ * ```
56
+ *
57
+ * @remarks
58
+ * - Use `exitIf` when the whole running flow should stop with a value
59
+ *
60
+ * @see [`F.breakIf`](https://utils.duplojs.dev/en/v1/api/flow/breakIf) To stop only the current local flow branch
61
+ * @see https://utils.duplojs.dev/en/v1/api/flow/exitIf
62
+ *
63
+ * @namespace F
64
+ *
65
+ */
66
+ export declare function exitIf<GenericValue extends unknown, GenericPredicate extends GenericValue>(value: GenericValue, thePredicate: (value: GenericValue) => value is GenericPredicate): Generator<Exit<NeverCoalescing<Extract<GenericValue, GenericPredicate>, GenericPredicate>>, Exclude<GenericValue, GenericPredicate>>;
67
+ export declare function exitIf<GenericValue extends unknown>(value: GenericValue, thePredicate: (value: GenericValue) => boolean): Generator<Exit<GenericValue>, GenericValue>;
@@ -0,0 +1,12 @@
1
+ import { createExit } from './theFlow/exit.mjs';
2
+
3
+ function* exitIf(value, thePredicate) {
4
+ if (thePredicate(value) === true) {
5
+ yield createExit(value);
6
+ }
7
+ else {
8
+ return value;
9
+ }
10
+ }
11
+
12
+ export { exitIf };
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ var finalizer$1 = require('./theFlow/finalizer.cjs');
4
+
5
+ /**
6
+ * {@include flow/finalizer/index.md}
7
+ */
8
+ function* finalizer(theFunction) {
9
+ yield finalizer$1.createFinalizer(theFunction);
10
+ }
11
+
12
+ exports.finalizer = finalizer;