@duplojs/utils 1.6.0 → 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 (54) 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/initializer.d.ts +3 -3
  24. package/dist/flow/queue.cjs +19 -0
  25. package/dist/flow/queue.d.ts +47 -0
  26. package/dist/flow/queue.mjs +17 -0
  27. package/dist/flow/run.cjs +118 -0
  28. package/dist/flow/run.d.ts +6 -4
  29. package/dist/flow/run.mjs +113 -1
  30. package/dist/flow/theFlow/calledByNext.cjs +11 -0
  31. package/dist/flow/theFlow/calledByNext.d.ts +5 -0
  32. package/dist/flow/theFlow/calledByNext.mjs +8 -0
  33. package/dist/flow/theFlow/debounce.cjs +11 -0
  34. package/dist/flow/theFlow/debounce.d.ts +9 -0
  35. package/dist/flow/theFlow/debounce.mjs +8 -0
  36. package/dist/flow/theFlow/index.d.ts +11 -3
  37. package/dist/flow/theFlow/queue.cjs +11 -0
  38. package/dist/flow/theFlow/queue.d.ts +9 -0
  39. package/dist/flow/theFlow/queue.mjs +8 -0
  40. package/dist/flow/theFlow/throttling.cjs +11 -0
  41. package/dist/flow/theFlow/throttling.d.ts +10 -0
  42. package/dist/flow/theFlow/throttling.mjs +8 -0
  43. package/dist/flow/throttling.cjs +27 -0
  44. package/dist/flow/throttling.d.ts +60 -0
  45. package/dist/flow/throttling.mjs +25 -0
  46. package/dist/flow/toFunction.cjs +15 -0
  47. package/dist/flow/toFunction.d.ts +56 -0
  48. package/dist/flow/toFunction.mjs +13 -0
  49. package/dist/index.cjs +6 -0
  50. package/dist/index.mjs +3 -1
  51. package/dist/metadata.json +99 -0
  52. package/dist/object/types/getPropsWithValue.d.ts +1 -1
  53. package/dist/object/types/getPropsWithValueExtends.d.ts +1 -1
  54. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
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";
2
+ import { type TheFlowGenerator, type TheFlow, type TheFlowFunction, type FlowInput, type WrapFlow, type Exit, type Break, type Injection, type Step, type FlowDependencies, type Throttling, type Debounce } from "./theFlow";
3
+ import { type Defer } from "./theFlow/defer";
3
4
  import { type Finalizer } from "./theFlow/finalizer";
4
5
  type ComputeExecParams<GenericInput extends unknown, GenericDependencies extends Record<string, unknown>> = SimplifyTopLevel<(Or<[
5
6
  IsEqual<GenericInput, unknown>,
@@ -13,7 +14,7 @@ type ComputeExecParams<GenericInput extends unknown, GenericDependencies extends
13
14
  dependencies?: GenericDependencies;
14
15
  }>;
15
16
  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
+ ((InferredEffect extends Break<infer InferredValue> ? InferredValue : InferredEffect extends Throttling<infer InferredValue> ? InferredValue : InferredEffect extends Debounce<infer InferredValue> ? InferredValue : never) | InferredOutput),
17
18
  Extract<InferredEffect, Exit | Injection | Finalizer | Step>
18
19
  ] extends [
19
20
  infer InferredOutput,
@@ -79,5 +80,5 @@ export type ExecResult<GenericFlow extends TheFlow> = GenericFlow extends TheFlo
79
80
  * @namespace F
80
81
  *
81
82
  */
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 declare function exec<GenericFlow extends (TheFlowFunction<any, TheFlowGenerator<unknown, Injection | Step | Exit | Break | Defer | Finalizer>> | TheFlow | TheFlowGenerator<unknown, Injection | Step | Exit | Break | Defer | Finalizer>), 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
84
  export {};
@@ -1,12 +1,19 @@
1
1
  import { theFlowKind } from './theFlow/index.mjs';
2
2
  import { deferKind } from './theFlow/defer.mjs';
3
3
  import { finalizerKind } from './theFlow/finalizer.mjs';
4
+ import { throttlingLastTimeWeakStore, throttlingResumerWeakStore, calledByNextFunctionWeakStore, queuesWeakStore, debounceTimeoutIdWeakStore, debounceResumerWeakStore } from './run.mjs';
4
5
  import { justExec } from '../common/justExec.mjs';
5
6
  import { breakKind } from './theFlow/break.mjs';
6
7
  import { exitKind } from './theFlow/exit.mjs';
7
8
  import { stepKind } from './theFlow/step.mjs';
8
9
  import { injectionKind } from './theFlow/injection.mjs';
9
10
  import { dependenceHandlerKind } from './theFlow/dependence.mjs';
11
+ import { throttlingKind } from './theFlow/throttling.mjs';
12
+ import { createExternalPromise } from '../common/externalPromise.mjs';
13
+ import { calledByNextKind } from './theFlow/calledByNext.mjs';
14
+ import { queueKind } from './theFlow/queue.mjs';
15
+ import { createQueue } from '../common/queue.mjs';
16
+ import { debounceKind } from './theFlow/debounce.mjs';
10
17
  import { forward } from '../common/forward.mjs';
11
18
 
12
19
  /**
@@ -15,6 +22,10 @@ import { forward } from '../common/forward.mjs';
15
22
  function exec(theFlow, ...[params]) {
16
23
  let result = undefined;
17
24
  let deferFunctions = undefined;
25
+ let alreadyUseThrottling = undefined;
26
+ let alreadyUseDebounce = undefined;
27
+ let alreadyUseCalledByNext = undefined;
28
+ let alreadyUseQueue = undefined;
18
29
  const generator = justExec(() => {
19
30
  if (Symbol.asyncIterator in theFlow || Symbol.iterator in theFlow) {
20
31
  return forward(theFlow);
@@ -62,10 +73,90 @@ function exec(theFlow, ...[params]) {
62
73
  injectionProperties.inject(params.dependencies[dependenceName]);
63
74
  }
64
75
  }
76
+ else if (throttlingKind.has(result.value)) {
77
+ if (alreadyUseThrottling) {
78
+ continue;
79
+ }
80
+ alreadyUseThrottling = true;
81
+ const { time, keepLast, returnValue } = throttlingKind.getValue(result.value);
82
+ const lastTime = throttlingLastTimeWeakStore.get(theFlow);
83
+ const now = Date.now();
84
+ throttlingLastTimeWeakStore.set(theFlow, now);
85
+ if (typeof lastTime === "number" && (lastTime + time) > now) {
86
+ if (keepLast === true) {
87
+ const resumer = throttlingResumerWeakStore.get(theFlow);
88
+ resumer?.(false);
89
+ const externalPromise = createExternalPromise();
90
+ throttlingResumerWeakStore.set(theFlow, externalPromise.resolve);
91
+ if (await externalPromise.promise) {
92
+ continue;
93
+ }
94
+ }
95
+ result = await generator.return(returnValue);
96
+ break;
97
+ }
98
+ else if (keepLast === true) {
99
+ setTimeout(() => {
100
+ const resumer = throttlingResumerWeakStore.get(theFlow);
101
+ resumer?.(true);
102
+ }, time);
103
+ }
104
+ }
105
+ else if (calledByNextKind.has(result.value)) {
106
+ if (alreadyUseCalledByNext) {
107
+ continue;
108
+ }
109
+ alreadyUseCalledByNext = calledByNextKind.getValue(result.value);
110
+ const lastFunction = calledByNextFunctionWeakStore.get(theFlow);
111
+ const lastResult = lastFunction?.();
112
+ if (lastResult instanceof Promise) {
113
+ await lastResult;
114
+ }
115
+ calledByNextFunctionWeakStore.set(theFlow, alreadyUseCalledByNext);
116
+ }
117
+ else if (queueKind.has(result.value)) {
118
+ if (alreadyUseQueue) {
119
+ continue;
120
+ }
121
+ const { concurrency, injectResolver } = queueKind.getValue(result.value);
122
+ let queue = queuesWeakStore.get(theFlow);
123
+ if (queue === undefined) {
124
+ queue = createQueue({ concurrency });
125
+ queuesWeakStore.set(theFlow, queue);
126
+ }
127
+ alreadyUseQueue = await queue.addExternal();
128
+ injectResolver(alreadyUseQueue);
129
+ }
130
+ else if (debounceKind.has(result.value)) {
131
+ if (alreadyUseDebounce) {
132
+ continue;
133
+ }
134
+ alreadyUseDebounce = true;
135
+ const { time, returnValue } = debounceKind.getValue(result.value);
136
+ const lastTimeout = debounceTimeoutIdWeakStore.get(theFlow);
137
+ clearTimeout(lastTimeout);
138
+ const lastResumer = debounceResumerWeakStore.get(theFlow);
139
+ lastResumer?.(false);
140
+ const externalPromise = createExternalPromise();
141
+ debounceTimeoutIdWeakStore.set(theFlow, setTimeout(() => void externalPromise.resolve(true), time));
142
+ debounceResumerWeakStore.set(theFlow, externalPromise.resolve);
143
+ if (await externalPromise.promise) {
144
+ continue;
145
+ }
146
+ result = await generator.return(returnValue);
147
+ break;
148
+ }
65
149
  } while (true);
66
150
  return result.value;
67
151
  }
68
152
  finally {
153
+ if (alreadyUseCalledByNext
154
+ && calledByNextFunctionWeakStore.get(theFlow) === alreadyUseCalledByNext) {
155
+ calledByNextFunctionWeakStore.delete(theFlow);
156
+ }
157
+ if (alreadyUseQueue) {
158
+ alreadyUseQueue();
159
+ }
69
160
  await generator.return(undefined);
70
161
  if (deferFunctions) {
71
162
  await Promise.all(deferFunctions.map(justExec));
@@ -108,6 +199,16 @@ function exec(theFlow, ...[params]) {
108
199
  injectionProperties.inject(params.dependencies[dependenceName]);
109
200
  }
110
201
  }
202
+ else if (throttlingKind.has(result.value)) {
203
+ const { time, returnValue } = throttlingKind.getValue(result.value);
204
+ const lastTime = throttlingLastTimeWeakStore.get(theFlow);
205
+ const now = Date.now();
206
+ throttlingLastTimeWeakStore.set(theFlow, now);
207
+ if (typeof lastTime === "number" && (lastTime + time) > now) {
208
+ result = generator.return(returnValue);
209
+ break;
210
+ }
211
+ }
111
212
  } while (true);
112
213
  return result.value;
113
214
  }
@@ -11,6 +11,11 @@ var inject = require('./inject.cjs');
11
11
  var step$1 = require('./step.cjs');
12
12
  var initializer = require('./initializer.cjs');
13
13
  var kind = require('./kind.cjs');
14
+ var calledByNext$1 = require('./calledByNext.cjs');
15
+ var queue$1 = require('./queue.cjs');
16
+ var throttling$1 = require('./throttling.cjs');
17
+ var toFunction = require('./toFunction.cjs');
18
+ var debounce$1 = require('./debounce.cjs');
14
19
  var step = require('./theFlow/step.cjs');
15
20
  var exit = require('./theFlow/exit.cjs');
16
21
  var _break = require('./theFlow/break.cjs');
@@ -18,11 +23,21 @@ var injection = require('./theFlow/injection.cjs');
18
23
  var defer = require('./theFlow/defer.cjs');
19
24
  var finalizer = require('./theFlow/finalizer.cjs');
20
25
  var dependence = require('./theFlow/dependence.cjs');
26
+ var throttling = require('./theFlow/throttling.cjs');
27
+ var calledByNext = require('./theFlow/calledByNext.cjs');
28
+ var queue = require('./theFlow/queue.cjs');
29
+ var debounce = require('./theFlow/debounce.cjs');
21
30
 
22
31
 
23
32
 
24
33
  exports.MissingDependenceError = run.MissingDependenceError;
34
+ exports.calledByNextFunctionWeakStore = run.calledByNextFunctionWeakStore;
35
+ exports.debounceResumerWeakStore = run.debounceResumerWeakStore;
36
+ exports.debounceTimeoutIdWeakStore = run.debounceTimeoutIdWeakStore;
37
+ exports.queuesWeakStore = run.queuesWeakStore;
25
38
  exports.run = run.run;
39
+ exports.throttlingLastTimeWeakStore = run.throttlingLastTimeWeakStore;
40
+ exports.throttlingResumerWeakStore = run.throttlingResumerWeakStore;
26
41
  exports.create = index.create;
27
42
  exports.theFlowKind = index.theFlowKind;
28
43
  exports.breakIf = breakIf.breakIf;
@@ -34,6 +49,11 @@ exports.inject = inject.inject;
34
49
  exports.step = step$1.step;
35
50
  exports.createInitializer = initializer.createInitializer;
36
51
  exports.createFlowKind = kind.createFlowKind;
52
+ exports.calledByNext = calledByNext$1.calledByNext;
53
+ exports.queue = queue$1.queue;
54
+ exports.throttling = throttling$1.throttling;
55
+ exports.toFunction = toFunction.toFunction;
56
+ exports.debounce = debounce$1.debounce;
37
57
  exports.createStep = step.createStep;
38
58
  exports.stepKind = step.stepKind;
39
59
  exports.createExit = exit.createExit;
@@ -48,3 +68,11 @@ exports.createFinalizer = finalizer.createFinalizer;
48
68
  exports.finalizerKind = finalizer.finalizerKind;
49
69
  exports.createDependence = dependence.createDependence;
50
70
  exports.dependenceHandlerKind = dependence.dependenceHandlerKind;
71
+ exports.createThrottling = throttling.createThrottling;
72
+ exports.throttlingKind = throttling.throttlingKind;
73
+ exports.calledByNextKind = calledByNext.calledByNextKind;
74
+ exports.createCalledByNext = calledByNext.createCalledByNext;
75
+ exports.createQueue = queue.createQueue;
76
+ exports.queueKind = queue.queueKind;
77
+ exports.createDebounce = debounce.createDebounce;
78
+ exports.debounceKind = debounce.debounceKind;
@@ -10,3 +10,8 @@ export * from "./inject";
10
10
  export * from "./step";
11
11
  export * from "./initializer";
12
12
  export * from "./kind";
13
+ export * from "./calledByNext";
14
+ export * from "./queue";
15
+ export * from "./throttling";
16
+ export * from "./toFunction";
17
+ export * from "./debounce";
@@ -1,4 +1,4 @@
1
- export { MissingDependenceError, run } from './run.mjs';
1
+ export { MissingDependenceError, calledByNextFunctionWeakStore, debounceResumerWeakStore, debounceTimeoutIdWeakStore, queuesWeakStore, run, throttlingLastTimeWeakStore, throttlingResumerWeakStore } from './run.mjs';
2
2
  export { create, theFlowKind } from './theFlow/index.mjs';
3
3
  export { breakIf } from './breakIf.mjs';
4
4
  export { defer } from './defer.mjs';
@@ -9,6 +9,11 @@ export { inject } from './inject.mjs';
9
9
  export { step } from './step.mjs';
10
10
  export { createInitializer } from './initializer.mjs';
11
11
  export { createFlowKind } from './kind.mjs';
12
+ export { calledByNext } from './calledByNext.mjs';
13
+ export { queue } from './queue.mjs';
14
+ export { throttling } from './throttling.mjs';
15
+ export { toFunction } from './toFunction.mjs';
16
+ export { debounce } from './debounce.mjs';
12
17
  export { createStep, stepKind } from './theFlow/step.mjs';
13
18
  export { createExit, exitKind } from './theFlow/exit.mjs';
14
19
  export { breakKind, createBreak } from './theFlow/break.mjs';
@@ -16,3 +21,7 @@ export { createInjection, injectionKind } from './theFlow/injection.mjs';
16
21
  export { createDefer, deferKind } from './theFlow/defer.mjs';
17
22
  export { createFinalizer, finalizerKind } from './theFlow/finalizer.mjs';
18
23
  export { createDependence, dependenceHandlerKind } from './theFlow/dependence.mjs';
24
+ export { createThrottling, throttlingKind } from './theFlow/throttling.mjs';
25
+ export { calledByNextKind, createCalledByNext } from './theFlow/calledByNext.mjs';
26
+ export { createQueue, queueKind } from './theFlow/queue.mjs';
27
+ export { createDebounce, debounceKind } from './theFlow/debounce.mjs';
@@ -21,7 +21,7 @@ export type Initializer<GenericArgs extends unknown[], GenericOutput extends unk
21
21
  * The returned initializer can then be executed inside `F.run(...)` like any other flow generator.
22
22
  *
23
23
  * ```ts
24
- * const userInitializer = createInitializer(
24
+ * const userInitializer = F.createInitializer(
25
25
  * (name: string) => ({ name }),
26
26
  * { defer: (user) => void console.log(`close:${user.name}`) },
27
27
  * );
@@ -33,7 +33,7 @@ export type Initializer<GenericArgs extends unknown[], GenericOutput extends unk
33
33
  * ); // { name: "Ada" }
34
34
  *
35
35
  * const finalizerLogs: string[] = [];
36
- * const tokenInitializer = createInitializer(
36
+ * const tokenInitializer = F.createInitializer(
37
37
  * (id: number) => `token-${id}`,
38
38
  * { finalizer: (token) => finalizerLogs.push(token) },
39
39
  * );
@@ -44,7 +44,7 @@ export type Initializer<GenericArgs extends unknown[], GenericOutput extends unk
44
44
  * },
45
45
  * ); // "token-42"
46
46
  *
47
- * const asyncInitializer = createInitializer(
47
+ * const asyncInitializer = F.createInitializer(
48
48
  * (name: string) => Promise.resolve({
49
49
  * name,
50
50
  * ready: true,
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ var queue$1 = require('./theFlow/queue.cjs');
4
+
5
+ /**
6
+ * {@include flow/queue/index.md}
7
+ */
8
+ async function* queue(params) {
9
+ let resolver = undefined;
10
+ yield queue$1.createQueue({
11
+ concurrency: params?.concurrency ?? 1,
12
+ injectResolver: (injectResolver) => {
13
+ resolver = injectResolver;
14
+ },
15
+ });
16
+ return resolver;
17
+ }
18
+
19
+ exports.queue = queue;
@@ -0,0 +1,47 @@
1
+ import { type OnlyLiteralNumber } from "../common";
2
+ /**
3
+ * Reserves execution through the async flow queue and returns a resolver that releases the reserved slot.
4
+ *
5
+ * **Supported call styles:**
6
+ * - Classic: `queue()` -> yields a queue effect with concurrency `1`
7
+ * - Classic with options: `queue({ concurrency })` -> yields a queue effect with the provided concurrency
8
+ *
9
+ * `queue` is an async flow helper consumed by the runner.
10
+ * It asks the runner to serialize or limit concurrent executions of the same flow.
11
+ * When the slot is granted, the helper returns a `release` function that should be called once the protected section is finished.
12
+ *
13
+ * ```ts
14
+ * const saveFlow = F.create(
15
+ * async function *(name: string) {
16
+ * const release = yield *F.queue({
17
+ * concurrency: 1,
18
+ * });
19
+ *
20
+ * try {
21
+ * return await Promise.resolve(`saved:${name}` as const);
22
+ * } finally {
23
+ * release();
24
+ * }
25
+ * },
26
+ * );
27
+ * const saveUser = F.toFunction(saveFlow);
28
+ *
29
+ * await saveUser("alice"); // Promise<"saved:alice">
30
+ *
31
+ * await saveUser("bob"); // Promise<"saved:bob">
32
+ * ```
33
+ *
34
+ * @remarks
35
+ * - `queue` is meaningful only in asynchronous flows handled by `F.run(...)`
36
+ * - Reuse the same flow reference to share the same queue across runs
37
+ * - If the same flow execution yields `queue(...)` multiple times, only the first yielded effect is applied by the runner
38
+ *
39
+ * @see [`F.run`](https://utils.duplojs.dev/en/v1/api/flow/run) For queue-aware execution
40
+ * @see https://utils.duplojs.dev/en/v1/api/flow/queue
41
+ *
42
+ * @namespace F
43
+ *
44
+ */
45
+ export declare function queue<GenericConcurrency extends number>(params?: {
46
+ concurrency?: GenericConcurrency & OnlyLiteralNumber<GenericConcurrency>;
47
+ }): AsyncGenerator<import("./theFlow").Queue, () => void, unknown>;
@@ -0,0 +1,17 @@
1
+ import { createQueue } from './theFlow/queue.mjs';
2
+
3
+ /**
4
+ * {@include flow/queue/index.md}
5
+ */
6
+ async function* queue(params) {
7
+ let resolver = undefined;
8
+ yield createQueue({
9
+ concurrency: params?.concurrency ?? 1,
10
+ injectResolver: (injectResolver) => {
11
+ resolver = injectResolver;
12
+ },
13
+ });
14
+ return resolver;
15
+ }
16
+
17
+ export { queue };
package/dist/flow/run.cjs CHANGED
@@ -9,6 +9,12 @@ var _break = require('./theFlow/break.cjs');
9
9
  var exit = require('./theFlow/exit.cjs');
10
10
  var step = require('./theFlow/step.cjs');
11
11
  var injection = require('./theFlow/injection.cjs');
12
+ var throttling = require('./theFlow/throttling.cjs');
13
+ var externalPromise = require('../common/externalPromise.cjs');
14
+ var calledByNext = require('./theFlow/calledByNext.cjs');
15
+ var queue = require('./theFlow/queue.cjs');
16
+ var queue$1 = require('../common/queue.cjs');
17
+ var debounce = require('./theFlow/debounce.cjs');
12
18
  var justExec = require('../common/justExec.cjs');
13
19
  var kind = require('../common/kind.cjs');
14
20
 
@@ -19,6 +25,18 @@ class MissingDependenceError extends kind.kindHeritage("missing-dependence-error
19
25
  this.dependenceHandler = dependenceHandler;
20
26
  }
21
27
  }
28
+ /** @internal */
29
+ const throttlingLastTimeWeakStore = new WeakMap();
30
+ /** @internal */
31
+ const throttlingResumerWeakStore = new WeakMap();
32
+ /** @internal */
33
+ const debounceTimeoutIdWeakStore = new WeakMap();
34
+ /** @internal */
35
+ const debounceResumerWeakStore = new WeakMap();
36
+ /** @internal */
37
+ const calledByNextFunctionWeakStore = new WeakMap();
38
+ /** @internal */
39
+ const queuesWeakStore = new WeakMap();
22
40
  /**
23
41
  * {@include flow/run/index.md}
24
42
  */
@@ -26,6 +44,10 @@ function run(theFlow, ...[params]) {
26
44
  let result = undefined;
27
45
  let deferFunctions = undefined;
28
46
  let steps = undefined;
47
+ let alreadyUseThrottling = undefined;
48
+ let alreadyUseDebounce = undefined;
49
+ let alreadyUseCalledByNext = undefined;
50
+ let alreadyUseQueue = undefined;
29
51
  const generator = typeof theFlow === "function"
30
52
  ? theFlow(params?.input)
31
53
  : index.theFlowKind.getValue(theFlow).run(params?.input);
@@ -67,6 +89,79 @@ function run(theFlow, ...[params]) {
67
89
  }
68
90
  injectionProperties.inject(params.dependencies[dependenceName]);
69
91
  }
92
+ else if (throttling.throttlingKind.has(result.value)) {
93
+ if (alreadyUseThrottling) {
94
+ continue;
95
+ }
96
+ alreadyUseThrottling = true;
97
+ const { time, keepLast, returnValue } = throttling.throttlingKind.getValue(result.value);
98
+ const lastTime = throttlingLastTimeWeakStore.get(theFlow);
99
+ const now = Date.now();
100
+ throttlingLastTimeWeakStore.set(theFlow, now);
101
+ if (typeof lastTime === "number" && (lastTime + time) > now) {
102
+ if (keepLast === true) {
103
+ const resumer = throttlingResumerWeakStore.get(theFlow);
104
+ resumer?.(false);
105
+ const externalPromise$1 = externalPromise.createExternalPromise();
106
+ throttlingResumerWeakStore.set(theFlow, externalPromise$1.resolve);
107
+ if (await externalPromise$1.promise) {
108
+ continue;
109
+ }
110
+ }
111
+ result = await generator.return(returnValue);
112
+ break;
113
+ }
114
+ else if (keepLast === true) {
115
+ setTimeout(() => {
116
+ const resumer = throttlingResumerWeakStore.get(theFlow);
117
+ resumer?.(true);
118
+ }, time);
119
+ }
120
+ }
121
+ else if (calledByNext.calledByNextKind.has(result.value)) {
122
+ if (alreadyUseCalledByNext) {
123
+ continue;
124
+ }
125
+ alreadyUseCalledByNext = calledByNext.calledByNextKind.getValue(result.value);
126
+ const lastFunction = calledByNextFunctionWeakStore.get(theFlow);
127
+ const lastResult = lastFunction?.();
128
+ if (lastResult instanceof Promise) {
129
+ await lastResult;
130
+ }
131
+ calledByNextFunctionWeakStore.set(theFlow, alreadyUseCalledByNext);
132
+ }
133
+ else if (queue.queueKind.has(result.value)) {
134
+ if (alreadyUseQueue) {
135
+ continue;
136
+ }
137
+ const { concurrency, injectResolver } = queue.queueKind.getValue(result.value);
138
+ let queue$2 = queuesWeakStore.get(theFlow);
139
+ if (queue$2 === undefined) {
140
+ queue$2 = queue$1.createQueue({ concurrency });
141
+ queuesWeakStore.set(theFlow, queue$2);
142
+ }
143
+ alreadyUseQueue = await queue$2.addExternal();
144
+ injectResolver(alreadyUseQueue);
145
+ }
146
+ else if (debounce.debounceKind.has(result.value)) {
147
+ if (alreadyUseDebounce) {
148
+ continue;
149
+ }
150
+ alreadyUseDebounce = true;
151
+ const { time, returnValue } = debounce.debounceKind.getValue(result.value);
152
+ const lastTimeout = debounceTimeoutIdWeakStore.get(theFlow);
153
+ clearTimeout(lastTimeout);
154
+ const lastResumer = debounceResumerWeakStore.get(theFlow);
155
+ lastResumer?.(false);
156
+ const externalPromise$1 = externalPromise.createExternalPromise();
157
+ debounceTimeoutIdWeakStore.set(theFlow, setTimeout(() => void externalPromise$1.resolve(true), time));
158
+ debounceResumerWeakStore.set(theFlow, externalPromise$1.resolve);
159
+ if (await externalPromise$1.promise) {
160
+ continue;
161
+ }
162
+ result = await generator.return(returnValue);
163
+ break;
164
+ }
70
165
  } while (true);
71
166
  return params?.includeDetails === true
72
167
  ? {
@@ -76,6 +171,13 @@ function run(theFlow, ...[params]) {
76
171
  : result.value;
77
172
  }
78
173
  finally {
174
+ if (alreadyUseCalledByNext
175
+ && calledByNextFunctionWeakStore.get(theFlow) === alreadyUseCalledByNext) {
176
+ calledByNextFunctionWeakStore.delete(theFlow);
177
+ }
178
+ if (alreadyUseQueue) {
179
+ alreadyUseQueue();
180
+ }
79
181
  await generator.return(undefined);
80
182
  if (deferFunctions) {
81
183
  await Promise.all(deferFunctions.map(justExec.justExec));
@@ -119,6 +221,16 @@ function run(theFlow, ...[params]) {
119
221
  }
120
222
  injectionProperties.inject(params.dependencies[dependenceName]);
121
223
  }
224
+ else if (throttling.throttlingKind.has(result.value)) {
225
+ const { time, returnValue } = throttling.throttlingKind.getValue(result.value);
226
+ const lastTime = throttlingLastTimeWeakStore.get(theFlow);
227
+ const now = Date.now();
228
+ throttlingLastTimeWeakStore.set(theFlow, now);
229
+ if (typeof lastTime === "number" && (lastTime + time) > now) {
230
+ result = generator.return(returnValue);
231
+ break;
232
+ }
233
+ }
122
234
  } while (true);
123
235
  return (params?.includeDetails === true
124
236
  ? {
@@ -136,4 +248,10 @@ function run(theFlow, ...[params]) {
136
248
  }
137
249
 
138
250
  exports.MissingDependenceError = MissingDependenceError;
251
+ exports.calledByNextFunctionWeakStore = calledByNextFunctionWeakStore;
252
+ exports.debounceResumerWeakStore = debounceResumerWeakStore;
253
+ exports.debounceTimeoutIdWeakStore = debounceTimeoutIdWeakStore;
254
+ exports.queuesWeakStore = queuesWeakStore;
139
255
  exports.run = run;
256
+ exports.throttlingLastTimeWeakStore = throttlingLastTimeWeakStore;
257
+ exports.throttlingResumerWeakStore = throttlingResumerWeakStore;
@@ -1,6 +1,8 @@
1
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<[
2
+ import { type TheFlow, type TheFlowFunction, type FlowInput, type WrapFlow, type TheFlowGenerator, type Exit, type Break, type Step, type FlowDependencies, type DependenceHandler, type ExtractFlowGenerator, type Throttling, type Injection, type Debounce } from "./theFlow";
3
+ import { type Defer } from "./theFlow/defer";
4
+ import { type Finalizer } from "./theFlow/finalizer";
5
+ type ComputeRunParams<GenericInput extends unknown = unknown, GenericDependencies extends Record<string, unknown> = Record<string, unknown>> = SimplifyTopLevel<(Or<[
4
6
  IsEqual<GenericInput, unknown>,
5
7
  IsEqual<GenericInput, never>,
6
8
  IsExtends<GenericInput, undefined>
@@ -19,7 +21,7 @@ export interface FlowDetails<GenericValue extends unknown, GenericStepName exten
19
21
  result: GenericValue;
20
22
  steps: GenericStepName[];
21
23
  }
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;
24
+ 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 : InferredEffect extends Throttling<infer InferredValue> ? InferredValue : InferredEffect extends Debounce<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
25
  declare const MissingDependenceError_base: new (params: {
24
26
  "@DuplojsUtilsFlow/missing-dependence-error"?: unknown;
25
27
  }, 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>;
@@ -76,5 +78,5 @@ export declare class MissingDependenceError extends MissingDependenceError_base
76
78
  * @namespace F
77
79
  *
78
80
  */
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>>;
81
+ export declare function run<GenericFlow extends (TheFlowFunction<any, TheFlowGenerator<unknown, Injection | Step | Exit | Break | Defer | Finalizer>> | 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
82
  export {};