@duplojs/utils 1.6.1 → 1.6.2

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 (53) hide show
  1. package/dist/common/asserts.cjs +12 -0
  2. package/dist/common/asserts.d.ts +26 -0
  3. package/dist/common/asserts.mjs +12 -1
  4. package/dist/common/callThen.cjs +14 -0
  5. package/dist/common/callThen.d.ts +35 -0
  6. package/dist/common/callThen.mjs +12 -0
  7. package/dist/common/index.d.ts +2 -0
  8. package/dist/common/queue.cjs +90 -0
  9. package/dist/common/queue.d.ts +46 -0
  10. package/dist/common/queue.mjs +87 -0
  11. package/dist/flow/calledByNext.cjs +13 -0
  12. package/dist/flow/calledByNext.d.ts +47 -0
  13. package/dist/flow/calledByNext.mjs +11 -0
  14. package/dist/flow/debounce.cjs +16 -0
  15. package/dist/flow/debounce.d.ts +63 -0
  16. package/dist/flow/debounce.mjs +14 -0
  17. package/dist/flow/exec.cjs +101 -0
  18. package/dist/flow/exec.d.ts +4 -3
  19. package/dist/flow/exec.mjs +101 -0
  20. package/dist/flow/index.cjs +28 -0
  21. package/dist/flow/index.d.ts +5 -0
  22. package/dist/flow/index.mjs +10 -1
  23. package/dist/flow/queue.cjs +19 -0
  24. package/dist/flow/queue.d.ts +47 -0
  25. package/dist/flow/queue.mjs +17 -0
  26. package/dist/flow/run.cjs +118 -0
  27. package/dist/flow/run.d.ts +6 -4
  28. package/dist/flow/run.mjs +113 -1
  29. package/dist/flow/theFlow/calledByNext.cjs +11 -0
  30. package/dist/flow/theFlow/calledByNext.d.ts +5 -0
  31. package/dist/flow/theFlow/calledByNext.mjs +8 -0
  32. package/dist/flow/theFlow/debounce.cjs +11 -0
  33. package/dist/flow/theFlow/debounce.d.ts +9 -0
  34. package/dist/flow/theFlow/debounce.mjs +8 -0
  35. package/dist/flow/theFlow/index.d.ts +11 -3
  36. package/dist/flow/theFlow/queue.cjs +11 -0
  37. package/dist/flow/theFlow/queue.d.ts +9 -0
  38. package/dist/flow/theFlow/queue.mjs +8 -0
  39. package/dist/flow/theFlow/throttling.cjs +11 -0
  40. package/dist/flow/theFlow/throttling.d.ts +10 -0
  41. package/dist/flow/theFlow/throttling.mjs +8 -0
  42. package/dist/flow/throttling.cjs +27 -0
  43. package/dist/flow/throttling.d.ts +60 -0
  44. package/dist/flow/throttling.mjs +25 -0
  45. package/dist/flow/toFunction.cjs +15 -0
  46. package/dist/flow/toFunction.d.ts +56 -0
  47. package/dist/flow/toFunction.mjs +13 -0
  48. package/dist/index.cjs +6 -0
  49. package/dist/index.mjs +3 -1
  50. package/dist/metadata.json +99 -0
  51. package/dist/object/types/getPropsWithValue.d.ts +1 -1
  52. package/dist/object/types/getPropsWithValueExtends.d.ts +1 -1
  53. package/package.json +1 -1
package/dist/flow/run.mjs CHANGED
@@ -7,6 +7,12 @@ import { breakKind } from './theFlow/break.mjs';
7
7
  import { exitKind } from './theFlow/exit.mjs';
8
8
  import { stepKind } from './theFlow/step.mjs';
9
9
  import { injectionKind } from './theFlow/injection.mjs';
10
+ import { throttlingKind } from './theFlow/throttling.mjs';
11
+ import { createExternalPromise } from '../common/externalPromise.mjs';
12
+ import { calledByNextKind } from './theFlow/calledByNext.mjs';
13
+ import { queueKind } from './theFlow/queue.mjs';
14
+ import { createQueue } from '../common/queue.mjs';
15
+ import { debounceKind } from './theFlow/debounce.mjs';
10
16
  import { justExec } from '../common/justExec.mjs';
11
17
  import { kindHeritage } from '../common/kind.mjs';
12
18
 
@@ -17,6 +23,18 @@ class MissingDependenceError extends kindHeritage("missing-dependence-error", cr
17
23
  this.dependenceHandler = dependenceHandler;
18
24
  }
19
25
  }
26
+ /** @internal */
27
+ const throttlingLastTimeWeakStore = new WeakMap();
28
+ /** @internal */
29
+ const throttlingResumerWeakStore = new WeakMap();
30
+ /** @internal */
31
+ const debounceTimeoutIdWeakStore = new WeakMap();
32
+ /** @internal */
33
+ const debounceResumerWeakStore = new WeakMap();
34
+ /** @internal */
35
+ const calledByNextFunctionWeakStore = new WeakMap();
36
+ /** @internal */
37
+ const queuesWeakStore = new WeakMap();
20
38
  /**
21
39
  * {@include flow/run/index.md}
22
40
  */
@@ -24,6 +42,10 @@ function run(theFlow, ...[params]) {
24
42
  let result = undefined;
25
43
  let deferFunctions = undefined;
26
44
  let steps = undefined;
45
+ let alreadyUseThrottling = undefined;
46
+ let alreadyUseDebounce = undefined;
47
+ let alreadyUseCalledByNext = undefined;
48
+ let alreadyUseQueue = undefined;
27
49
  const generator = typeof theFlow === "function"
28
50
  ? theFlow(params?.input)
29
51
  : theFlowKind.getValue(theFlow).run(params?.input);
@@ -65,6 +87,79 @@ function run(theFlow, ...[params]) {
65
87
  }
66
88
  injectionProperties.inject(params.dependencies[dependenceName]);
67
89
  }
90
+ else if (throttlingKind.has(result.value)) {
91
+ if (alreadyUseThrottling) {
92
+ continue;
93
+ }
94
+ alreadyUseThrottling = true;
95
+ const { time, keepLast, returnValue } = throttlingKind.getValue(result.value);
96
+ const lastTime = throttlingLastTimeWeakStore.get(theFlow);
97
+ const now = Date.now();
98
+ throttlingLastTimeWeakStore.set(theFlow, now);
99
+ if (typeof lastTime === "number" && (lastTime + time) > now) {
100
+ if (keepLast === true) {
101
+ const resumer = throttlingResumerWeakStore.get(theFlow);
102
+ resumer?.(false);
103
+ const externalPromise = createExternalPromise();
104
+ throttlingResumerWeakStore.set(theFlow, externalPromise.resolve);
105
+ if (await externalPromise.promise) {
106
+ continue;
107
+ }
108
+ }
109
+ result = await generator.return(returnValue);
110
+ break;
111
+ }
112
+ else if (keepLast === true) {
113
+ setTimeout(() => {
114
+ const resumer = throttlingResumerWeakStore.get(theFlow);
115
+ resumer?.(true);
116
+ }, time);
117
+ }
118
+ }
119
+ else if (calledByNextKind.has(result.value)) {
120
+ if (alreadyUseCalledByNext) {
121
+ continue;
122
+ }
123
+ alreadyUseCalledByNext = calledByNextKind.getValue(result.value);
124
+ const lastFunction = calledByNextFunctionWeakStore.get(theFlow);
125
+ const lastResult = lastFunction?.();
126
+ if (lastResult instanceof Promise) {
127
+ await lastResult;
128
+ }
129
+ calledByNextFunctionWeakStore.set(theFlow, alreadyUseCalledByNext);
130
+ }
131
+ else if (queueKind.has(result.value)) {
132
+ if (alreadyUseQueue) {
133
+ continue;
134
+ }
135
+ const { concurrency, injectResolver } = queueKind.getValue(result.value);
136
+ let queue = queuesWeakStore.get(theFlow);
137
+ if (queue === undefined) {
138
+ queue = createQueue({ concurrency });
139
+ queuesWeakStore.set(theFlow, queue);
140
+ }
141
+ alreadyUseQueue = await queue.addExternal();
142
+ injectResolver(alreadyUseQueue);
143
+ }
144
+ else if (debounceKind.has(result.value)) {
145
+ if (alreadyUseDebounce) {
146
+ continue;
147
+ }
148
+ alreadyUseDebounce = true;
149
+ const { time, returnValue } = debounceKind.getValue(result.value);
150
+ const lastTimeout = debounceTimeoutIdWeakStore.get(theFlow);
151
+ clearTimeout(lastTimeout);
152
+ const lastResumer = debounceResumerWeakStore.get(theFlow);
153
+ lastResumer?.(false);
154
+ const externalPromise = createExternalPromise();
155
+ debounceTimeoutIdWeakStore.set(theFlow, setTimeout(() => void externalPromise.resolve(true), time));
156
+ debounceResumerWeakStore.set(theFlow, externalPromise.resolve);
157
+ if (await externalPromise.promise) {
158
+ continue;
159
+ }
160
+ result = await generator.return(returnValue);
161
+ break;
162
+ }
68
163
  } while (true);
69
164
  return params?.includeDetails === true
70
165
  ? {
@@ -74,6 +169,13 @@ function run(theFlow, ...[params]) {
74
169
  : result.value;
75
170
  }
76
171
  finally {
172
+ if (alreadyUseCalledByNext
173
+ && calledByNextFunctionWeakStore.get(theFlow) === alreadyUseCalledByNext) {
174
+ calledByNextFunctionWeakStore.delete(theFlow);
175
+ }
176
+ if (alreadyUseQueue) {
177
+ alreadyUseQueue();
178
+ }
77
179
  await generator.return(undefined);
78
180
  if (deferFunctions) {
79
181
  await Promise.all(deferFunctions.map(justExec));
@@ -117,6 +219,16 @@ function run(theFlow, ...[params]) {
117
219
  }
118
220
  injectionProperties.inject(params.dependencies[dependenceName]);
119
221
  }
222
+ else if (throttlingKind.has(result.value)) {
223
+ const { time, returnValue } = throttlingKind.getValue(result.value);
224
+ const lastTime = throttlingLastTimeWeakStore.get(theFlow);
225
+ const now = Date.now();
226
+ throttlingLastTimeWeakStore.set(theFlow, now);
227
+ if (typeof lastTime === "number" && (lastTime + time) > now) {
228
+ result = generator.return(returnValue);
229
+ break;
230
+ }
231
+ }
120
232
  } while (true);
121
233
  return (params?.includeDetails === true
122
234
  ? {
@@ -133,4 +245,4 @@ function run(theFlow, ...[params]) {
133
245
  }
134
246
  }
135
247
 
136
- export { MissingDependenceError, run };
248
+ export { MissingDependenceError, calledByNextFunctionWeakStore, debounceResumerWeakStore, debounceTimeoutIdWeakStore, queuesWeakStore, run, throttlingLastTimeWeakStore, throttlingResumerWeakStore };
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ var kind = require('../kind.cjs');
4
+
5
+ const calledByNextKind = kind.createFlowKind("called-by-next");
6
+ function createCalledByNext(value) {
7
+ return calledByNextKind.setTo({}, value);
8
+ }
9
+
10
+ exports.calledByNextKind = calledByNextKind;
11
+ exports.createCalledByNext = createCalledByNext;
@@ -0,0 +1,5 @@
1
+ import { type AnyFunction, type Kind } from "../../common";
2
+ export declare const calledByNextKind: import("../../common").KindHandler<import("../../common").KindDefinition<"@DuplojsUtilsFlow/called-by-next", AnyFunction<[], unknown>>>;
3
+ export interface CalledByNext<GenericValue extends unknown = unknown> extends Kind<typeof calledByNextKind.definition, () => GenericValue> {
4
+ }
5
+ export declare function createCalledByNext<GenericOutput extends unknown>(value: () => GenericOutput): CalledByNext<GenericOutput>;
@@ -0,0 +1,8 @@
1
+ import { createFlowKind } from '../kind.mjs';
2
+
3
+ const calledByNextKind = createFlowKind("called-by-next");
4
+ function createCalledByNext(value) {
5
+ return calledByNextKind.setTo({}, value);
6
+ }
7
+
8
+ export { calledByNextKind, createCalledByNext };
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ var kind = require('../kind.cjs');
4
+
5
+ const debounceKind = kind.createFlowKind("debounce");
6
+ function createDebounce(properties) {
7
+ return debounceKind.setTo({}, properties);
8
+ }
9
+
10
+ exports.createDebounce = createDebounce;
11
+ exports.debounceKind = debounceKind;
@@ -0,0 +1,9 @@
1
+ import { type Kind } from "../../common";
2
+ export declare const debounceKind: import("../../common").KindHandler<import("../../common").KindDefinition<"@DuplojsUtilsFlow/debounce", unknown>>;
3
+ export interface DebounceProperties<GenericValue extends unknown = unknown> {
4
+ time: number;
5
+ returnValue: GenericValue;
6
+ }
7
+ export interface Debounce<GenericValue extends unknown = unknown> extends Kind<typeof debounceKind.definition, DebounceProperties<GenericValue>> {
8
+ }
9
+ export declare function createDebounce<GenericValue extends unknown>(properties: DebounceProperties<GenericValue>): Debounce<GenericValue>;
@@ -0,0 +1,8 @@
1
+ import { createFlowKind } from '../kind.mjs';
2
+
3
+ const debounceKind = createFlowKind("debounce");
4
+ function createDebounce(properties) {
5
+ return debounceKind.setTo({}, properties);
6
+ }
7
+
8
+ export { createDebounce, debounceKind };
@@ -6,6 +6,10 @@ import { type Break } from "./break";
6
6
  import { type Defer } from "./defer";
7
7
  import { type Finalizer } from "./finalizer";
8
8
  import { type DependenceHandler, type dependenceHandlerKind } from "./dependence";
9
+ import { type Throttling } from "./throttling";
10
+ import { type CalledByNext } from "./calledByNext";
11
+ import { type Queue } from "./queue";
12
+ import { type Debounce } from "./debounce";
9
13
  export * from "./step";
10
14
  export * from "./exit";
11
15
  export * from "./break";
@@ -13,8 +17,12 @@ export * from "./injection";
13
17
  export * from "./defer";
14
18
  export * from "./finalizer";
15
19
  export * from "./dependence";
16
- export type Effect = (Injection | Step | Exit | Break | Defer | Finalizer);
17
- export type TheFlowGenerator<GenericOutput extends unknown = unknown, GenericEffect extends Effect = Effect> = (Generator<GenericEffect, GenericOutput> | AsyncGenerator<GenericEffect, GenericOutput>);
20
+ export * from "./throttling";
21
+ export * from "./calledByNext";
22
+ export * from "./queue";
23
+ export * from "./debounce";
24
+ export type Effect = (Injection | Step | Exit | Break | Defer | Finalizer | Throttling | CalledByNext | Queue | Debounce);
25
+ export type TheFlowGenerator<GenericOutput extends unknown = unknown, GenericEffect extends Effect = Effect> = (Generator<Exclude<GenericEffect, (Queue | CalledByNext | Debounce)>, GenericOutput> | AsyncGenerator<GenericEffect, GenericOutput>);
18
26
  export type TheFlowFunction<GenericInput extends any = any, GenericGenerator extends TheFlowGenerator = TheFlowGenerator> = (input: GenericInput) => GenericGenerator;
19
27
  export interface TheFlowProperties<GenericFunction extends TheFlowFunction = TheFlowFunction> {
20
28
  run: GenericFunction;
@@ -78,7 +86,7 @@ export interface TheFlow<GenericFunction extends TheFlowFunction = TheFlowFuncti
78
86
  */
79
87
  export declare function create<GenericTheFlowFunction extends TheFlowFunction>(theFunction: GenericTheFlowFunction): TheFlow<GenericTheFlowFunction>;
80
88
  export type FlowInput<GenericFlow extends TheFlow> = GenericFlow extends TheFlow<infer InferredFunction> ? InferredFunction extends TheFlowFunction<infer InferredInput> ? InferredInput : never : never;
81
- export type WrapFlow<GenericFlow extends (TheFlow | TheFlowFunction | TheFlowGenerator)> = GenericFlow extends TheFlowGenerator ? TheFlow<TheFlowFunction<unknown, GenericFlow>> : GenericFlow extends TheFlowFunction ? TheFlow<GenericFlow> : GenericFlow;
89
+ export type WrapFlow<GenericFlow extends (TheFlow | TheFlowFunction | TheFlowGenerator)> = GenericFlow extends TheFlowGenerator ? TheFlow<TheFlowFunction<unknown, GenericFlow>> : GenericFlow extends TheFlowFunction ? TheFlow<GenericFlow> : Extract<GenericFlow, TheFlow>;
82
90
  export type FlowDependencies<GenericFlow extends TheFlow> = (ExtractFlowGenerator<GenericFlow> extends TheFlowGenerator<any, infer InferredEffect> ? InferredEffect extends Injection<infer InferredDependenceHandler> ? InferredDependenceHandler : never : never) extends infer InferredDependenceHandler extends DependenceHandler ? {
83
91
  [Dependence in InferredDependenceHandler as Extract<GetKindValue<typeof dependenceHandlerKind, Dependence>, string>]: ReturnType<InferredDependenceHandler>;
84
92
  } : never;
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ var kind = require('../kind.cjs');
4
+
5
+ const queueKind = kind.createFlowKind("queue");
6
+ function createQueue(properties) {
7
+ return queueKind.setTo({}, properties);
8
+ }
9
+
10
+ exports.createQueue = createQueue;
11
+ exports.queueKind = queueKind;
@@ -0,0 +1,9 @@
1
+ import { type Kind } from "../../common";
2
+ export declare const queueKind: import("../../common").KindHandler<import("../../common").KindDefinition<"@DuplojsUtilsFlow/queue", unknown>>;
3
+ export interface QueueProperties {
4
+ concurrency: number;
5
+ injectResolver(resolver: () => void): void;
6
+ }
7
+ export interface Queue extends Kind<typeof queueKind.definition, QueueProperties> {
8
+ }
9
+ export declare function createQueue(properties: QueueProperties): Queue;
@@ -0,0 +1,8 @@
1
+ import { createFlowKind } from '../kind.mjs';
2
+
3
+ const queueKind = createFlowKind("queue");
4
+ function createQueue(properties) {
5
+ return queueKind.setTo({}, properties);
6
+ }
7
+
8
+ export { createQueue, queueKind };
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ var kind = require('../kind.cjs');
4
+
5
+ const throttlingKind = kind.createFlowKind("throttling");
6
+ function createThrottling(properties) {
7
+ return throttlingKind.setTo({}, properties);
8
+ }
9
+
10
+ exports.createThrottling = createThrottling;
11
+ exports.throttlingKind = throttlingKind;
@@ -0,0 +1,10 @@
1
+ import { type Kind } from "../../common";
2
+ export declare const throttlingKind: import("../../common").KindHandler<import("../../common").KindDefinition<"@DuplojsUtilsFlow/throttling", unknown>>;
3
+ export interface ThrottlingProperties<GenericValue extends unknown = unknown> {
4
+ time: number;
5
+ returnValue: GenericValue;
6
+ keepLast: boolean;
7
+ }
8
+ export interface Throttling<GenericValue extends unknown = unknown> extends Kind<typeof throttlingKind.definition, ThrottlingProperties<GenericValue>> {
9
+ }
10
+ export declare function createThrottling<GenericValue extends unknown>(properties: ThrottlingProperties<GenericValue>): Throttling<GenericValue>;
@@ -0,0 +1,8 @@
1
+ import { createFlowKind } from '../kind.mjs';
2
+
3
+ const throttlingKind = createFlowKind("throttling");
4
+ function createThrottling(properties) {
5
+ return throttlingKind.setTo({}, properties);
6
+ }
7
+
8
+ export { createThrottling, throttlingKind };
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+
3
+ var throttling$1 = require('./theFlow/throttling.cjs');
4
+
5
+ /**
6
+ * {@include flow/throttling/index.md}
7
+ */
8
+ function throttling(time, params) {
9
+ if (params?.keepLast === true) {
10
+ return (async function* () {
11
+ yield throttling$1.createThrottling({
12
+ time,
13
+ returnValue: params?.returnValue,
14
+ keepLast: true,
15
+ });
16
+ })();
17
+ }
18
+ return (function* () {
19
+ yield throttling$1.createThrottling({
20
+ time,
21
+ returnValue: params?.returnValue,
22
+ keepLast: false,
23
+ });
24
+ })();
25
+ }
26
+
27
+ exports.throttling = throttling;
@@ -0,0 +1,60 @@
1
+ import { type OnlyLiteralBoolean, type IsEqual } from "../common";
2
+ import { type Throttling } from "./theFlow";
3
+ /**
4
+ * Throttles repeated runs of the same flow and can return a fallback value when a run happens too early.
5
+ *
6
+ * **Supported call styles:**
7
+ * - Classic: `throttling(time)` -> yields a throttling effect
8
+ * - Classic with options: `throttling(time, params)` -> yields a throttling effect with a fallback return value and optional `keepLast`
9
+ *
10
+ * `throttling` lets the runner decide whether the current run should continue or stop early depending on the previous execution time of the same flow.
11
+ * When a run happens inside the throttling window, the runner can return `params.returnValue`.
12
+ * With `keepLast: true`, the runner keeps the last skipped async run and resumes it after the delay.
13
+ *
14
+ * ```ts
15
+ * const searchFlow = F.create(
16
+ * function *(query: string) {
17
+ * yield *F.throttling(
18
+ * 300,
19
+ * { returnValue: "skipped" as const },
20
+ * );
21
+ * return query;
22
+ * },
23
+ * );
24
+ * const runSearch = F.toFunction(searchFlow);
25
+ *
26
+ * runSearch("first"); // "first"
27
+ *
28
+ * runSearch("second"); // "skipped"
29
+ *
30
+ * const latestFlow = F.create(
31
+ * async function *(value: string) {
32
+ * yield *F.throttling(
33
+ * 500,
34
+ * {
35
+ * returnValue: "ignored" as const,
36
+ * keepLast: true,
37
+ * },
38
+ * );
39
+ * return Promise.resolve(value);
40
+ * },
41
+ * );
42
+ * const runLatestFlow = F.toFunction(latestFlow);
43
+ * await runLatestFlow("latest"); // Promise<"latest" | "ignored">
44
+ * ```
45
+ *
46
+ * @remarks
47
+ * - `keepLast: true` changes the helper to an async generator because the runner may resume the latest skipped run later
48
+ * - Throttling state is attached to the flow reference, so examples should reuse the same created flow or wrapped function
49
+ * - If the same flow execution yields `throttling(...)` multiple times, only the first yielded effect is applied by the runner
50
+ *
51
+ * @see [`F.run`](https://utils.duplojs.dev/en/v1/api/flow/run) For the throttling behavior implemented by the runner
52
+ * @see https://utils.duplojs.dev/en/v1/api/flow/throttling
53
+ *
54
+ * @namespace F
55
+ *
56
+ */
57
+ export declare function throttling<GenericValue extends unknown = undefined, GenericKeepLast extends boolean = false>(time: number, params?: {
58
+ returnValue?: GenericValue;
59
+ keepLast?: GenericKeepLast & OnlyLiteralBoolean<GenericKeepLast>;
60
+ }): IsEqual<GenericKeepLast, true> extends true ? AsyncGenerator<Throttling<NoInfer<GenericValue>>, undefined> : Generator<Throttling<NoInfer<GenericValue>>, undefined>;
@@ -0,0 +1,25 @@
1
+ import { createThrottling } from './theFlow/throttling.mjs';
2
+
3
+ /**
4
+ * {@include flow/throttling/index.md}
5
+ */
6
+ function throttling(time, params) {
7
+ if (params?.keepLast === true) {
8
+ return (async function* () {
9
+ yield createThrottling({
10
+ time,
11
+ returnValue: params?.returnValue,
12
+ keepLast: true,
13
+ });
14
+ })();
15
+ }
16
+ return (function* () {
17
+ yield createThrottling({
18
+ time,
19
+ returnValue: params?.returnValue,
20
+ keepLast: false,
21
+ });
22
+ })();
23
+ }
24
+
25
+ export { throttling };
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ var run = require('./run.cjs');
4
+
5
+ /**
6
+ * {@include flow/toFunction/index.md}
7
+ */
8
+ function toFunction(flow, ...[params]) {
9
+ return (input) => run.run(flow, {
10
+ ...params,
11
+ input,
12
+ });
13
+ }
14
+
15
+ exports.toFunction = toFunction;
@@ -0,0 +1,56 @@
1
+ import { type SimplifyTopLevel, type IsEqual } from "../common";
2
+ import { type RunResult } from "./run";
3
+ import { type WrapFlow, type TheFlow, type TheFlowFunction, type FlowDependencies, type TheFlowGenerator } from "./theFlow";
4
+ type ComputeToFunctionParams<GenericDependencies extends Record<string, unknown> = Record<string, unknown>> = SimplifyTopLevel<{
5
+ includeDetails?: boolean;
6
+ } & ({} extends GenericDependencies ? {
7
+ dependencies?: GenericDependencies;
8
+ } : {
9
+ dependencies: GenericDependencies;
10
+ })>;
11
+ /**
12
+ * Converts a flow into a plain callable function that delegates to `F.run(...)`.
13
+ *
14
+ * **Supported call styles:**
15
+ * - Classic with a flow function: `toFunction(flow, params?)` -> returns a callable function
16
+ * - Classic with a flow instance: `toFunction(flow, params?)` -> returns a callable function
17
+ *
18
+ * `toFunction` wraps a flow function or a flow created with `F.create(...)` and returns a regular function that accepts only the flow input.
19
+ * The provided options are forwarded to `F.run(...)`, which means you can preconfigure `includeDetails` and `dependencies`.
20
+ * Use it when a flow should be exposed as a reusable application function instead of being run manually each time.
21
+ *
22
+ * ```ts
23
+ * const runUppercase = F.toFunction(
24
+ * function *(input: string) {
25
+ * yield *F.step("uppercase");
26
+ * return input.toUpperCase();
27
+ * },
28
+ * );
29
+ * runUppercase("duplo"); // "DUPLO"
30
+ *
31
+ * const runWithDetails = F.toFunction(
32
+ * function *(input: string) {
33
+ * yield *F.step("format");
34
+ * return input.length;
35
+ * },
36
+ * { includeDetails: true },
37
+ * );
38
+ * runWithDetails("hello"); // { result: 5, steps: ["format"] }
39
+ *
40
+ * const service = F.createDependence("service")<string>;
41
+ * const runWithDependencies = F.toFunction(
42
+ * function *(input: string) {
43
+ * const currentService = yield *F.inject(service);
44
+ * ```
45
+ *
46
+ * @remarks
47
+ * - `toFunction` keeps the same sync or async return shape as `F.run(...)` for the wrapped flow
48
+ *
49
+ * @see [`F.run`](https://utils.duplojs.dev/en/v1/api/flow/run) For the execution behavior used internally
50
+ * @see https://utils.duplojs.dev/en/v1/api/flow/toFunction
51
+ *
52
+ * @namespace F
53
+ *
54
+ */
55
+ export declare function toFunction<GenericInput extends unknown, GenericOutput extends TheFlowGenerator, GenericWrapFlow extends WrapFlow<TheFlowFunction<GenericInput, GenericOutput>>, const GenericParams extends ComputeToFunctionParams<FlowDependencies<GenericWrapFlow>>>(flow: (TheFlowFunction<GenericInput, GenericOutput> | TheFlow<TheFlowFunction<GenericInput, GenericOutput>>), ...[params]: ({} extends GenericParams ? [params?: GenericParams] : [params: GenericParams])): (input: GenericInput) => RunResult<GenericWrapFlow, IsEqual<GenericParams["includeDetails"], true>>;
56
+ export {};
@@ -0,0 +1,13 @@
1
+ import { run } from './run.mjs';
2
+
3
+ /**
4
+ * {@include flow/toFunction/index.md}
5
+ */
6
+ function toFunction(flow, ...[params]) {
7
+ return (input) => run(flow, {
8
+ ...params,
9
+ input,
10
+ });
11
+ }
12
+
13
+ export { toFunction };
package/dist/index.cjs CHANGED
@@ -67,6 +67,8 @@ var path = require('./common/path.cjs');
67
67
  var transformer = require('./common/transformer.cjs');
68
68
  var toRegExp = require('./common/toRegExp.cjs');
69
69
  var justExec = require('./common/justExec.cjs');
70
+ var callThen = require('./common/callThen.cjs');
71
+ var queue = require('./common/queue.cjs');
70
72
 
71
73
 
72
74
 
@@ -160,6 +162,7 @@ exports.toCurriedPredicate = toCurriedPredicate.toCurriedPredicate;
160
162
  exports.pipeCall = pipeCall.pipeCall;
161
163
  exports.AssertsError = asserts.AssertsError;
162
164
  exports.asserts = asserts.asserts;
165
+ exports.forwardAsserts = asserts.forwardAsserts;
163
166
  Object.defineProperty(exports, "Path", {
164
167
  enumerable: true,
165
168
  get: function () { return path.Path; }
@@ -170,3 +173,6 @@ exports.toNative = transformer.toNative;
170
173
  exports.transformer = transformer.transformer;
171
174
  exports.toRegExp = toRegExp.toRegExp;
172
175
  exports.justExec = justExec.justExec;
176
+ exports.callThen = callThen.callThen;
177
+ exports.createQueue = queue.createQueue;
178
+ exports.queueKind = queue.queueKind;
package/dist/index.mjs CHANGED
@@ -86,8 +86,10 @@ export { hasSomeKinds } from './common/hasSomeKinds.mjs';
86
86
  export { hasKinds } from './common/hasKinds.mjs';
87
87
  export { toCurriedPredicate } from './common/toCurriedPredicate.mjs';
88
88
  export { pipeCall } from './common/pipeCall.mjs';
89
- export { AssertsError, asserts } from './common/asserts.mjs';
89
+ export { AssertsError, asserts, forwardAsserts } from './common/asserts.mjs';
90
90
  export { Path } from './common/path.mjs';
91
91
  export { createTransformer, toJSON, toNative, transformer } from './common/transformer.mjs';
92
92
  export { toRegExp } from './common/toRegExp.mjs';
93
93
  export { justExec } from './common/justExec.mjs';
94
+ export { callThen } from './common/callThen.mjs';
95
+ export { createQueue, queueKind } from './common/queue.mjs';