@duplojs/utils 1.5.15 → 1.6.1

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
@@ -0,0 +1,47 @@
1
+ import { type Finalizer } from "./theFlow";
2
+ /**
3
+ * Registers a final callback handled by the flow runner.
4
+ *
5
+ * **Supported call styles:**
6
+ * - Classic: `finalizer(theFunction)` -> yields a finalizer effect
7
+ *
8
+ * `finalizer` registers logic that is executed by the flow runner when the flow completes.
9
+ * It is useful for cleanup or post-processing that should stay inside the flow effect system.
10
+ * Use it inside `F.run(...)` or inside subflows executed by `F.exec(...)`.
11
+ *
12
+ * ```ts
13
+ * F.run(
14
+ * function *() {
15
+ * yield *F.finalizer(() => void console.log("close connection"));
16
+ * return "done";
17
+ * },
18
+ * ); // "done"
19
+ *
20
+ * F.run(
21
+ * function *() {
22
+ * yield *F.finalizer(() => 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.finalizer(async() => {
31
+ * await Promise.resolve();
32
+ * });
33
+ * return Promise.resolve("done");
34
+ * },
35
+ * ); // Promise<"done">
36
+ * ```
37
+ *
38
+ * @remarks
39
+ * - Finalizers are collected by the flow runner and executed after the flow ends
40
+ *
41
+ * @see [`F.defer`](https://utils.duplojs.dev/en/v1/api/flow/defer) For another cleanup-oriented effect
42
+ * @see https://utils.duplojs.dev/en/v1/api/flow/finalizer
43
+ *
44
+ * @namespace F
45
+ *
46
+ */
47
+ export declare function finalizer<GenericOutput extends unknown>(theFunction: () => GenericOutput): (Generator<Finalizer<GenericOutput>, undefined> | (GenericOutput extends Promise<unknown> ? AsyncGenerator<Finalizer<GenericOutput>, undefined> : never));
@@ -0,0 +1,10 @@
1
+ import { createFinalizer } from './theFlow/finalizer.mjs';
2
+
3
+ /**
4
+ * {@include flow/finalizer/index.md}
5
+ */
6
+ function* finalizer(theFunction) {
7
+ yield createFinalizer(theFunction);
8
+ }
9
+
10
+ export { finalizer };
@@ -0,0 +1,50 @@
1
+ 'use strict';
2
+
3
+ var run = require('./run.cjs');
4
+ var index = require('./theFlow/index.cjs');
5
+ var breakIf = require('./breakIf.cjs');
6
+ var defer$1 = require('./defer.cjs');
7
+ var exec = require('./exec.cjs');
8
+ var exitIf = require('./exitIf.cjs');
9
+ var finalizer$1 = require('./finalizer.cjs');
10
+ var inject = require('./inject.cjs');
11
+ var step$1 = require('./step.cjs');
12
+ var initializer = require('./initializer.cjs');
13
+ var kind = require('./kind.cjs');
14
+ var step = require('./theFlow/step.cjs');
15
+ var exit = require('./theFlow/exit.cjs');
16
+ var _break = require('./theFlow/break.cjs');
17
+ var injection = require('./theFlow/injection.cjs');
18
+ var defer = require('./theFlow/defer.cjs');
19
+ var finalizer = require('./theFlow/finalizer.cjs');
20
+ var dependence = require('./theFlow/dependence.cjs');
21
+
22
+
23
+
24
+ exports.MissingDependenceError = run.MissingDependenceError;
25
+ exports.run = run.run;
26
+ exports.create = index.create;
27
+ exports.theFlowKind = index.theFlowKind;
28
+ exports.breakIf = breakIf.breakIf;
29
+ exports.defer = defer$1.defer;
30
+ exports.exec = exec.exec;
31
+ exports.exitIf = exitIf.exitIf;
32
+ exports.finalizer = finalizer$1.finalizer;
33
+ exports.inject = inject.inject;
34
+ exports.step = step$1.step;
35
+ exports.createInitializer = initializer.createInitializer;
36
+ exports.createFlowKind = kind.createFlowKind;
37
+ exports.createStep = step.createStep;
38
+ exports.stepKind = step.stepKind;
39
+ exports.createExit = exit.createExit;
40
+ exports.exitKind = exit.exitKind;
41
+ exports.breakKind = _break.breakKind;
42
+ exports.createBreak = _break.createBreak;
43
+ exports.createInjection = injection.createInjection;
44
+ exports.injectionKind = injection.injectionKind;
45
+ exports.createDefer = defer.createDefer;
46
+ exports.deferKind = defer.deferKind;
47
+ exports.createFinalizer = finalizer.createFinalizer;
48
+ exports.finalizerKind = finalizer.finalizerKind;
49
+ exports.createDependence = dependence.createDependence;
50
+ exports.dependenceHandlerKind = dependence.dependenceHandlerKind;
@@ -0,0 +1,12 @@
1
+ export * from "./types";
2
+ export * from "./run";
3
+ export * from "./theFlow";
4
+ export * from "./breakIf";
5
+ export * from "./defer";
6
+ export * from "./exec";
7
+ export * from "./exitIf";
8
+ export * from "./finalizer";
9
+ export * from "./inject";
10
+ export * from "./step";
11
+ export * from "./initializer";
12
+ export * from "./kind";
@@ -0,0 +1,18 @@
1
+ export { MissingDependenceError, run } from './run.mjs';
2
+ export { create, theFlowKind } from './theFlow/index.mjs';
3
+ export { breakIf } from './breakIf.mjs';
4
+ export { defer } from './defer.mjs';
5
+ export { exec } from './exec.mjs';
6
+ export { exitIf } from './exitIf.mjs';
7
+ export { finalizer } from './finalizer.mjs';
8
+ export { inject } from './inject.mjs';
9
+ export { step } from './step.mjs';
10
+ export { createInitializer } from './initializer.mjs';
11
+ export { createFlowKind } from './kind.mjs';
12
+ export { createStep, stepKind } from './theFlow/step.mjs';
13
+ export { createExit, exitKind } from './theFlow/exit.mjs';
14
+ export { breakKind, createBreak } from './theFlow/break.mjs';
15
+ export { createInjection, injectionKind } from './theFlow/injection.mjs';
16
+ export { createDefer, deferKind } from './theFlow/defer.mjs';
17
+ export { createFinalizer, finalizerKind } from './theFlow/finalizer.mjs';
18
+ export { createDependence, dependenceHandlerKind } from './theFlow/dependence.mjs';
@@ -0,0 +1,38 @@
1
+ 'use strict';
2
+
3
+ var defer = require('./theFlow/defer.cjs');
4
+ var finalizer = require('./theFlow/finalizer.cjs');
5
+
6
+ /**
7
+ * {@include flow/createInitializer/index.md}
8
+ */
9
+ function createInitializer(initializer, params) {
10
+ return (...args) => {
11
+ const result = initializer(...args);
12
+ const defer$1 = params.defer;
13
+ const finalizer$1 = params.finalizer;
14
+ if (result instanceof Promise) {
15
+ return (async function* () {
16
+ const awaitedResult = await result;
17
+ if (defer$1) {
18
+ yield defer.createDefer(() => defer$1(awaitedResult));
19
+ }
20
+ if (finalizer$1) {
21
+ yield finalizer.createFinalizer(() => finalizer$1(awaitedResult));
22
+ }
23
+ return awaitedResult;
24
+ })();
25
+ }
26
+ return (function* () {
27
+ if (defer$1) {
28
+ yield defer.createDefer(() => defer$1(result));
29
+ }
30
+ if (finalizer$1) {
31
+ yield finalizer.createFinalizer(() => finalizer$1(result));
32
+ }
33
+ return result;
34
+ })();
35
+ };
36
+ }
37
+
38
+ exports.createInitializer = createInitializer;
@@ -0,0 +1,75 @@
1
+ import { type AnyFunction, type IsExtends, type Or } from "../common";
2
+ import { type RequireAtLeastOne } from "../object";
3
+ import { type Defer, type Finalizer } from "./theFlow";
4
+ export interface CreateInitializerParams<GenericOutput extends unknown = unknown> {
5
+ defer?(output: Awaited<GenericOutput>): unknown;
6
+ finalizer?(output: Awaited<GenericOutput>): unknown;
7
+ }
8
+ export type Initializer<GenericArgs extends unknown[], GenericOutput extends unknown, GenericParams extends CreateInitializerParams<GenericOutput>> = Extract<(...args: GenericArgs) => (((GenericParams["finalizer"] extends AnyFunction ? Finalizer<ReturnType<GenericParams["finalizer"]>> : never) | (GenericParams["defer"] extends AnyFunction ? Defer<ReturnType<GenericParams["defer"]>> : never)) extends infer InferredEffect ? (Generator<InferredEffect, Awaited<GenericOutput>> | (Or<[
9
+ IsExtends<GenericOutput, Promise<unknown>>,
10
+ IsExtends<InferredEffect, Finalizer<Promise<unknown>>>,
11
+ IsExtends<InferredEffect, Defer<Promise<unknown>>>
12
+ ]> extends true ? AsyncGenerator<InferredEffect, Awaited<GenericOutput>> : never)) : never), any>;
13
+ /**
14
+ * Creates an initializer that returns a value and automatically registers flow cleanup effects.
15
+ *
16
+ * **Supported call styles:**
17
+ * - Classic: `createInitializer(initializer, params)` -> returns a function that can be yielded inside a flow
18
+ *
19
+ * `createInitializer` wraps an initializer function and turns its result into a flow-friendly generator.
20
+ * Depending on the provided options, it can register a `defer` callback, a `finalizer` callback, or both, using the produced value.
21
+ * The returned initializer can then be executed inside `F.run(...)` like any other flow generator.
22
+ *
23
+ * ```ts
24
+ * const userInitializer = F.createInitializer(
25
+ * (name: string) => ({ name }),
26
+ * { defer: (user) => void console.log(`close:${user.name}`) },
27
+ * );
28
+ *
29
+ * F.run(
30
+ * function *() {
31
+ * return yield *userInitializer("Ada");
32
+ * },
33
+ * ); // { name: "Ada" }
34
+ *
35
+ * const finalizerLogs: string[] = [];
36
+ * const tokenInitializer = F.createInitializer(
37
+ * (id: number) => `token-${id}`,
38
+ * { finalizer: (token) => finalizerLogs.push(token) },
39
+ * );
40
+ *
41
+ * F.run(
42
+ * function *() {
43
+ * return yield *tokenInitializer(42);
44
+ * },
45
+ * ); // "token-42"
46
+ *
47
+ * const asyncInitializer = F.createInitializer(
48
+ * (name: string) => Promise.resolve({
49
+ * name,
50
+ * ready: true,
51
+ * }),
52
+ * { defer: (user) => void console.log(`async:${user.name}`) },
53
+ * );
54
+ *
55
+ * void await F.run(
56
+ * async function *() {
57
+ * const value = yield *asyncInitializer("Linus");
58
+ * // Promise<{ name: string; ready: true }>
59
+ *
60
+ * return;
61
+ * },
62
+ * );
63
+ * ```
64
+ *
65
+ * @remarks
66
+ * - `createInitializer` is useful when a setup step should also declare matching cleanup logic
67
+ *
68
+ * @see [`F.defer`](https://utils.duplojs.dev/en/v1/api/flow/defer) For cleanup callbacks
69
+ * @see [`F.finalizer`](https://utils.duplojs.dev/en/v1/api/flow/finalizer) For final callbacks
70
+ * @see https://utils.duplojs.dev/en/v1/api/flow/createInitializer
71
+ *
72
+ * @namespace F
73
+ *
74
+ */
75
+ export declare function createInitializer<GenericArgs extends unknown[], GenericOutput extends unknown, GenericParams extends CreateInitializerParams<GenericOutput>>(initializer: (...args: GenericArgs) => GenericOutput, params: GenericParams & RequireAtLeastOne<GenericParams, keyof CreateInitializerParams>): Initializer<GenericArgs, GenericOutput, GenericParams>;
@@ -0,0 +1,36 @@
1
+ import { createDefer } from './theFlow/defer.mjs';
2
+ import { createFinalizer } from './theFlow/finalizer.mjs';
3
+
4
+ /**
5
+ * {@include flow/createInitializer/index.md}
6
+ */
7
+ function createInitializer(initializer, params) {
8
+ return (...args) => {
9
+ const result = initializer(...args);
10
+ const defer = params.defer;
11
+ const finalizer = params.finalizer;
12
+ if (result instanceof Promise) {
13
+ return (async function* () {
14
+ const awaitedResult = await result;
15
+ if (defer) {
16
+ yield createDefer(() => defer(awaitedResult));
17
+ }
18
+ if (finalizer) {
19
+ yield createFinalizer(() => finalizer(awaitedResult));
20
+ }
21
+ return awaitedResult;
22
+ })();
23
+ }
24
+ return (function* () {
25
+ if (defer) {
26
+ yield createDefer(() => defer(result));
27
+ }
28
+ if (finalizer) {
29
+ yield createFinalizer(() => finalizer(result));
30
+ }
31
+ return result;
32
+ })();
33
+ };
34
+ }
35
+
36
+ export { createInitializer };
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ var injection = require('./theFlow/injection.cjs');
4
+
5
+ /**
6
+ * {@include flow/inject/index.md}
7
+ */
8
+ function* inject(dependenceHandler) {
9
+ let dependence = undefined;
10
+ yield injection.createInjection({
11
+ dependenceHandler,
12
+ inject: (value) => {
13
+ dependence = value;
14
+ },
15
+ });
16
+ return dependence;
17
+ }
18
+
19
+ exports.inject = inject;
@@ -0,0 +1,46 @@
1
+ import { type DependenceHandler, type Injection } from "./theFlow";
2
+ /**
3
+ * Requests a dependency from the flow runner.
4
+ *
5
+ * **Supported call styles:**
6
+ * - Classic: `inject(dependenceHandler)` -> yields an injection effect and returns the injected value
7
+ *
8
+ * `inject` lets a flow declare that it needs a dependency by using a dependence handler created with `F.createDependence(...)`.
9
+ * When `F.run(...)` or `F.exec(...)` receives matching dependencies, the requested value is injected back into the flow.
10
+ * If the dependency is missing, the runner throws a missing dependence error.
11
+ *
12
+ * ```ts
13
+ * const database = F.createDependence("database")<string>;
14
+ *
15
+ * F.run(
16
+ * function *() {
17
+ * const connection = yield *F.inject(database);
18
+ * return connection;
19
+ * },
20
+ * { dependencies: { database: "main-db" } },
21
+ * ); // "main-db"
22
+ *
23
+ * F.run(
24
+ * function *() {
25
+ * return yield *F.exec(
26
+ * function *() {
27
+ * const connection = yield *F.inject(database);
28
+ * return connection;
29
+ * },
30
+ * { dependencies: { database: "replica-db" } },
31
+ * );
32
+ * },
33
+ * { dependencies: { database: "main-db" } },
34
+ * ); // "replica-db"
35
+ * ```
36
+ *
37
+ * @remarks
38
+ * - `inject` keeps dependencies explicit in flow definitions
39
+ *
40
+ * @see [`F.run`](https://utils.duplojs.dev/en/v1/api/flow/run) For providing dependencies
41
+ * @see https://utils.duplojs.dev/en/v1/api/flow/inject
42
+ *
43
+ * @namespace F
44
+ *
45
+ */
46
+ export declare function inject<GenericDependenceHandler extends DependenceHandler>(dependenceHandler: GenericDependenceHandler): Generator<Injection<GenericDependenceHandler>, ReturnType<GenericDependenceHandler>>;
@@ -0,0 +1,17 @@
1
+ import { createInjection } from './theFlow/injection.mjs';
2
+
3
+ /**
4
+ * {@include flow/inject/index.md}
5
+ */
6
+ function* inject(dependenceHandler) {
7
+ let dependence = undefined;
8
+ yield createInjection({
9
+ dependenceHandler,
10
+ inject: (value) => {
11
+ dependence = value;
12
+ },
13
+ });
14
+ return dependence;
15
+ }
16
+
17
+ export { inject };
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ var kind = require('../common/kind.cjs');
4
+
5
+ const createFlowKind = kind.createKindNamespace(
6
+ // @ts-expect-error reserved kind namespace
7
+ "DuplojsUtilsFlow");
8
+
9
+ exports.createFlowKind = createFlowKind;
@@ -0,0 +1 @@
1
+ export declare const createFlowKind: <GenericName extends string, GenericKindValue extends unknown = unknown>(name: GenericName & import("../string").ForbiddenString<GenericName, "@" | "/">) => import("../common").KindHandler<import("../common").KindDefinition<`@DuplojsUtilsFlow/${GenericName}`, GenericKindValue>>;
@@ -0,0 +1,7 @@
1
+ import { createKindNamespace } from '../common/kind.mjs';
2
+
3
+ const createFlowKind = createKindNamespace(
4
+ // @ts-expect-error reserved kind namespace
5
+ "DuplojsUtilsFlow");
6
+
7
+ export { createFlowKind };
@@ -0,0 +1,139 @@
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 kind$1 = require('./kind.cjs');
7
+ var dependence = require('./theFlow/dependence.cjs');
8
+ var _break = require('./theFlow/break.cjs');
9
+ var exit = require('./theFlow/exit.cjs');
10
+ var step = require('./theFlow/step.cjs');
11
+ var injection = require('./theFlow/injection.cjs');
12
+ var justExec = require('../common/justExec.cjs');
13
+ var kind = require('../common/kind.cjs');
14
+
15
+ class MissingDependenceError extends kind.kindHeritage("missing-dependence-error", kind$1.createFlowKind("missing-dependence-error"), Error) {
16
+ dependenceHandler;
17
+ constructor(dependenceHandler) {
18
+ super({}, [`Missing dependence : ${dependence.dependenceHandlerKind.getValue(dependenceHandler)}`]);
19
+ this.dependenceHandler = dependenceHandler;
20
+ }
21
+ }
22
+ /**
23
+ * {@include flow/run/index.md}
24
+ */
25
+ function run(theFlow, ...[params]) {
26
+ let result = undefined;
27
+ let deferFunctions = undefined;
28
+ let steps = undefined;
29
+ const generator = typeof theFlow === "function"
30
+ ? theFlow(params?.input)
31
+ : index.theFlowKind.getValue(theFlow).run(params?.input);
32
+ if (Symbol.asyncIterator in generator) {
33
+ return (async function () {
34
+ try {
35
+ do {
36
+ result = await generator.next();
37
+ if (result.done === true) {
38
+ break;
39
+ }
40
+ else if (_break.breakKind.has(result.value)) {
41
+ result = await generator.return(_break.breakKind.getValue(result.value).value);
42
+ break;
43
+ }
44
+ else if (exit.exitKind.has(result.value)) {
45
+ result = await generator.return(exit.exitKind.getValue(result.value).value);
46
+ break;
47
+ }
48
+ else if (defer.deferKind.has(result.value)) {
49
+ deferFunctions ??= [];
50
+ deferFunctions.push(defer.deferKind.getValue(result.value));
51
+ }
52
+ else if (finalizer.finalizerKind.has(result.value)) {
53
+ deferFunctions ??= [];
54
+ deferFunctions.push(finalizer.finalizerKind.getValue(result.value));
55
+ }
56
+ else if (params?.includeDetails === true
57
+ && step.stepKind.has(result.value)) {
58
+ steps ??= [];
59
+ steps.push(step.stepKind.getValue(result.value));
60
+ }
61
+ else if (injection.injectionKind.has(result.value)) {
62
+ const injectionProperties = injection.injectionKind.getValue(result.value);
63
+ const dependenceName = dependence.dependenceHandlerKind.getValue(injectionProperties.dependenceHandler);
64
+ if (!params?.dependencies
65
+ || !(dependenceName in params.dependencies)) {
66
+ throw new MissingDependenceError(injectionProperties.dependenceHandler);
67
+ }
68
+ injectionProperties.inject(params.dependencies[dependenceName]);
69
+ }
70
+ } while (true);
71
+ return params?.includeDetails === true
72
+ ? {
73
+ result: result.value,
74
+ steps: steps ?? [],
75
+ }
76
+ : result.value;
77
+ }
78
+ finally {
79
+ await generator.return(undefined);
80
+ if (deferFunctions) {
81
+ await Promise.all(deferFunctions.map(justExec.justExec));
82
+ }
83
+ }
84
+ })();
85
+ }
86
+ try {
87
+ do {
88
+ result = generator.next();
89
+ if (result.done === true) {
90
+ break;
91
+ }
92
+ else if (_break.breakKind.has(result.value)) {
93
+ result = generator.return(_break.breakKind.getValue(result.value).value);
94
+ break;
95
+ }
96
+ else if (exit.exitKind.has(result.value)) {
97
+ result = generator.return(exit.exitKind.getValue(result.value).value);
98
+ break;
99
+ }
100
+ else if (defer.deferKind.has(result.value)) {
101
+ deferFunctions ??= [];
102
+ deferFunctions.push(defer.deferKind.getValue(result.value));
103
+ }
104
+ else if (finalizer.finalizerKind.has(result.value)) {
105
+ deferFunctions ??= [];
106
+ deferFunctions.push(finalizer.finalizerKind.getValue(result.value));
107
+ }
108
+ else if (params?.includeDetails === true
109
+ && step.stepKind.has(result.value)) {
110
+ steps ??= [];
111
+ steps.push(step.stepKind.getValue(result.value));
112
+ }
113
+ else if (injection.injectionKind.has(result.value)) {
114
+ const injectionProperties = injection.injectionKind.getValue(result.value);
115
+ const dependenceName = dependence.dependenceHandlerKind.getValue(injectionProperties.dependenceHandler);
116
+ if (!params?.dependencies
117
+ || !(dependenceName in params.dependencies)) {
118
+ throw new MissingDependenceError(injectionProperties.dependenceHandler);
119
+ }
120
+ injectionProperties.inject(params.dependencies[dependenceName]);
121
+ }
122
+ } while (true);
123
+ return (params?.includeDetails === true
124
+ ? {
125
+ result: result.value,
126
+ steps: steps ?? [],
127
+ }
128
+ : result.value);
129
+ }
130
+ finally {
131
+ generator.return(undefined);
132
+ if (deferFunctions) {
133
+ deferFunctions.map(justExec.justExec);
134
+ }
135
+ }
136
+ }
137
+
138
+ exports.MissingDependenceError = MissingDependenceError;
139
+ exports.run = run;
@@ -0,0 +1,80 @@
1
+ import { type SimplifyTopLevel, type IsEqual, type IsExtends, type Or } from "../common";
2
+ import { type TheFlow, type TheFlowFunction, type FlowInput, type WrapFlow, type TheFlowGenerator, type Exit, type Break, type Step, type FlowDependencies, type DependenceHandler, type ExtractFlowGenerator } from "./theFlow";
3
+ type ComputeRunParams<GenericInput extends unknown, GenericDependencies extends Record<string, unknown>> = SimplifyTopLevel<(Or<[
4
+ IsEqual<GenericInput, unknown>,
5
+ IsEqual<GenericInput, never>,
6
+ IsExtends<GenericInput, undefined>
7
+ ]> extends true ? {
8
+ input?: GenericInput;
9
+ } : {
10
+ input: GenericInput;
11
+ }) & {
12
+ includeDetails?: boolean;
13
+ } & ({} extends GenericDependencies ? {
14
+ dependencies?: GenericDependencies;
15
+ } : {
16
+ dependencies: GenericDependencies;
17
+ })>;
18
+ export interface FlowDetails<GenericValue extends unknown, GenericStepName extends string> {
19
+ result: GenericValue;
20
+ steps: GenericStepName[];
21
+ }
22
+ export type RunResult<GenericFlow extends TheFlow, GenericIncludeDetails extends boolean = false> = (GenericFlow extends TheFlow<infer InferredFunction> ? InferredFunction extends TheFlowFunction<any, infer InferredGenerator> ? InferredGenerator extends TheFlowGenerator<infer InferredOutput, infer InferredEffect> ? ((InferredEffect extends Exit<infer InferredValue> ? InferredValue : InferredEffect extends Break<infer InferredValue> ? InferredValue : never) | InferredOutput) extends infer InferredResult ? IsEqual<GenericIncludeDetails, true> extends true ? FlowDetails<InferredResult, InferredEffect extends Step<infer InferredName> ? InferredName : never> : InferredResult : never : never : never : never) extends infer InferredResult ? ExtractFlowGenerator<GenericFlow> extends AsyncGenerator ? Promise<InferredResult> : InferredResult : never;
23
+ declare const MissingDependenceError_base: new (params: {
24
+ "@DuplojsUtilsFlow/missing-dependence-error"?: unknown;
25
+ }, parentParams: readonly [message?: string | undefined, options?: ErrorOptions | undefined]) => Error & import("../common").Kind<import("../common").KindDefinition<"missing-dependence-error", unknown>, unknown> & import("../common").Kind<import("../common").KindDefinition<"@DuplojsUtilsFlow/missing-dependence-error", unknown>, unknown>;
26
+ export declare class MissingDependenceError extends MissingDependenceError_base {
27
+ dependenceHandler: DependenceHandler;
28
+ constructor(dependenceHandler: DependenceHandler);
29
+ }
30
+ /**
31
+ * Runs a flow and resolves its final result.
32
+ *
33
+ * **Supported call styles:**
34
+ * - Classic with a flow function: `run(theFlow, params?)` -> executes the provided flow function
35
+ * - Classic with a flow instance: `run(theFlow, params?)` -> executes a flow created with `F.create(...)`
36
+ *
37
+ * `run` is the entry point of the flow system.
38
+ * It executes synchronous or asynchronous flows, handles break and exit effects, collects steps when `includeDetails` is enabled, runs deferred and finalizer callbacks, and injects declared dependencies.
39
+ * Use `run` to start a top-level flow and get its final value.
40
+ *
41
+ * ```ts
42
+ * F.run(
43
+ * function *(input: string) {
44
+ * return input.toUpperCase();
45
+ * },
46
+ * { input: "hello" },
47
+ * ); // "HELLO"
48
+ *
49
+ * F.run(
50
+ * function *() {
51
+ * yield *F.step("check cache");
52
+ * yield *F.breakIf(2, (value) => value === 2);
53
+ * return "done";
54
+ * },
55
+ * { includeDetails: true },
56
+ * ); // { result: 2, steps: ["check cache"] }
57
+ *
58
+ * const service = F.createDependence("service")<string>;
59
+ *
60
+ * F.run(
61
+ * function *() {
62
+ * const currentService = yield *F.inject(service);
63
+ * yield *F.finalizer(() => currentService.toUpperCase());
64
+ * return currentService;
65
+ * },
66
+ * { dependencies: { service: "api" } },
67
+ * ); // "api"
68
+ * ```
69
+ *
70
+ * @remarks
71
+ * - `run` returns a `Promise` when the executed flow is asynchronous
72
+ *
73
+ * @see [`F.exec`](https://utils.duplojs.dev/en/v1/api/flow/exec) To run a nested flow from inside another flow
74
+ * @see https://utils.duplojs.dev/en/v1/api/flow/run
75
+ *
76
+ * @namespace F
77
+ *
78
+ */
79
+ export declare function run<GenericFlow extends (TheFlowFunction | TheFlow), GenericWrapFlow extends WrapFlow<GenericFlow>, const GenericParams extends ComputeRunParams<FlowInput<GenericWrapFlow>, FlowDependencies<GenericWrapFlow>>>(theFlow: GenericFlow, ...[params]: ({} extends GenericParams ? [params?: GenericParams] : [params: GenericParams])): RunResult<GenericWrapFlow, IsEqual<GenericParams["includeDetails"], true>>;
80
+ export {};