@duplojs/utils 1.6.1 → 1.6.3

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 (169) hide show
  1. package/dist/array/types/createTuple.d.ts +1 -1
  2. package/dist/clean/constraint/base.cjs +7 -0
  3. package/dist/clean/constraint/base.d.ts +26 -6
  4. package/dist/clean/constraint/base.mjs +7 -0
  5. package/dist/clean/constraint/cast.cjs +18 -0
  6. package/dist/clean/constraint/cast.d.ts +29 -0
  7. package/dist/clean/constraint/cast.mjs +16 -0
  8. package/dist/clean/constraint/defaultConstraint/number.cjs +2 -10
  9. package/dist/clean/constraint/defaultConstraint/number.d.ts +12 -37
  10. package/dist/clean/constraint/defaultConstraint/number.mjs +3 -10
  11. package/dist/clean/constraint/defaultConstraint/string.d.ts +9 -5
  12. package/dist/clean/constraint/index.d.ts +1 -0
  13. package/dist/clean/constraint/set.cjs +7 -1
  14. package/dist/clean/constraint/set.d.ts +25 -5
  15. package/dist/clean/constraint/set.mjs +7 -1
  16. package/dist/clean/entity/index.cjs +14 -4
  17. package/dist/clean/entity/index.d.ts +11 -1
  18. package/dist/clean/entity/index.mjs +15 -6
  19. package/dist/clean/index.cjs +5 -1
  20. package/dist/clean/index.d.ts +1 -0
  21. package/dist/clean/index.mjs +4 -2
  22. package/dist/clean/newType.cjs +6 -1
  23. package/dist/clean/newType.d.ts +20 -5
  24. package/dist/clean/newType.mjs +6 -1
  25. package/dist/clean/primitive/operations/equal.cjs +3 -0
  26. package/dist/clean/primitive/operations/equal.d.ts +2 -2
  27. package/dist/clean/primitive/operations/equal.mjs +3 -0
  28. package/dist/clean/toMapDataParser.cjs +52 -0
  29. package/dist/clean/toMapDataParser.d.ts +53 -0
  30. package/dist/clean/toMapDataParser.mjs +50 -0
  31. package/dist/common/asserts.cjs +12 -0
  32. package/dist/common/asserts.d.ts +26 -0
  33. package/dist/common/asserts.mjs +12 -1
  34. package/dist/common/callThen.cjs +14 -0
  35. package/dist/common/callThen.d.ts +35 -0
  36. package/dist/common/callThen.mjs +12 -0
  37. package/dist/common/index.d.ts +3 -0
  38. package/dist/common/printer.cjs +73 -0
  39. package/dist/common/printer.d.ts +139 -0
  40. package/dist/common/printer.mjs +73 -0
  41. package/dist/common/queue.cjs +90 -0
  42. package/dist/common/queue.d.ts +46 -0
  43. package/dist/common/queue.mjs +87 -0
  44. package/dist/common/types/and.d.ts +1 -2
  45. package/dist/common/types/or.d.ts +1 -2
  46. package/dist/dataParser/base.cjs +12 -35
  47. package/dist/dataParser/base.d.ts +6 -9
  48. package/dist/dataParser/base.mjs +8 -30
  49. package/dist/dataParser/error.cjs +39 -21
  50. package/dist/dataParser/error.d.ts +19 -19
  51. package/dist/dataParser/error.mjs +37 -18
  52. package/dist/dataParser/extended/index.cjs +3 -4
  53. package/dist/dataParser/extended/index.mjs +1 -1
  54. package/dist/dataParser/identifier.d.ts +6 -6
  55. package/dist/dataParser/index.cjs +3 -6
  56. package/dist/dataParser/index.mjs +2 -2
  57. package/dist/dataParser/parsers/array/checkers/max.cjs +3 -6
  58. package/dist/dataParser/parsers/array/checkers/max.mjs +4 -7
  59. package/dist/dataParser/parsers/array/checkers/min.cjs +3 -6
  60. package/dist/dataParser/parsers/array/checkers/min.mjs +4 -7
  61. package/dist/dataParser/parsers/array/index.cjs +8 -8
  62. package/dist/dataParser/parsers/array/index.mjs +4 -4
  63. package/dist/dataParser/parsers/bigint/checkers/max.cjs +2 -2
  64. package/dist/dataParser/parsers/bigint/checkers/max.mjs +3 -3
  65. package/dist/dataParser/parsers/bigint/checkers/min.cjs +2 -2
  66. package/dist/dataParser/parsers/bigint/checkers/min.mjs +3 -3
  67. package/dist/dataParser/parsers/bigint/index.cjs +2 -2
  68. package/dist/dataParser/parsers/bigint/index.mjs +3 -3
  69. package/dist/dataParser/parsers/boolean.cjs +3 -3
  70. package/dist/dataParser/parsers/boolean.mjs +4 -4
  71. package/dist/dataParser/parsers/date.cjs +4 -4
  72. package/dist/dataParser/parsers/date.mjs +5 -5
  73. package/dist/dataParser/parsers/empty.cjs +2 -2
  74. package/dist/dataParser/parsers/empty.mjs +3 -3
  75. package/dist/dataParser/parsers/literal.cjs +2 -2
  76. package/dist/dataParser/parsers/literal.mjs +3 -3
  77. package/dist/dataParser/parsers/nil.cjs +2 -2
  78. package/dist/dataParser/parsers/nil.mjs +3 -3
  79. package/dist/dataParser/parsers/number/checkers/int.cjs +2 -2
  80. package/dist/dataParser/parsers/number/checkers/int.mjs +3 -3
  81. package/dist/dataParser/parsers/number/checkers/max.cjs +3 -1
  82. package/dist/dataParser/parsers/number/checkers/max.mjs +4 -2
  83. package/dist/dataParser/parsers/number/checkers/min.cjs +3 -1
  84. package/dist/dataParser/parsers/number/checkers/min.mjs +4 -2
  85. package/dist/dataParser/parsers/number/index.cjs +2 -2
  86. package/dist/dataParser/parsers/number/index.mjs +3 -3
  87. package/dist/dataParser/parsers/object/index.cjs +8 -8
  88. package/dist/dataParser/parsers/object/index.mjs +4 -4
  89. package/dist/dataParser/parsers/pipe.cjs +25 -10
  90. package/dist/dataParser/parsers/pipe.mjs +22 -7
  91. package/dist/dataParser/parsers/record/index.cjs +18 -16
  92. package/dist/dataParser/parsers/record/index.mjs +8 -6
  93. package/dist/dataParser/parsers/recover.cjs +7 -6
  94. package/dist/dataParser/parsers/recover.mjs +2 -1
  95. package/dist/dataParser/parsers/refine.cjs +3 -1
  96. package/dist/dataParser/parsers/refine.mjs +4 -2
  97. package/dist/dataParser/parsers/string/checkers/email.cjs +2 -2
  98. package/dist/dataParser/parsers/string/checkers/email.mjs +3 -3
  99. package/dist/dataParser/parsers/string/checkers/max.cjs +3 -1
  100. package/dist/dataParser/parsers/string/checkers/max.mjs +4 -2
  101. package/dist/dataParser/parsers/string/checkers/min.cjs +3 -1
  102. package/dist/dataParser/parsers/string/checkers/min.mjs +4 -2
  103. package/dist/dataParser/parsers/string/checkers/regex.cjs +2 -2
  104. package/dist/dataParser/parsers/string/checkers/regex.mjs +3 -3
  105. package/dist/dataParser/parsers/string/checkers/url.cjs +4 -4
  106. package/dist/dataParser/parsers/string/checkers/url.mjs +5 -5
  107. package/dist/dataParser/parsers/string/index.cjs +2 -2
  108. package/dist/dataParser/parsers/string/index.mjs +3 -3
  109. package/dist/dataParser/parsers/templateLiteral/index.cjs +2 -2
  110. package/dist/dataParser/parsers/templateLiteral/index.mjs +3 -3
  111. package/dist/dataParser/parsers/time/checkers/max.cjs +3 -1
  112. package/dist/dataParser/parsers/time/checkers/max.mjs +4 -2
  113. package/dist/dataParser/parsers/time/checkers/min.cjs +3 -1
  114. package/dist/dataParser/parsers/time/checkers/min.mjs +4 -2
  115. package/dist/dataParser/parsers/time/index.cjs +4 -4
  116. package/dist/dataParser/parsers/time/index.mjs +5 -5
  117. package/dist/dataParser/parsers/transform.cjs +6 -6
  118. package/dist/dataParser/parsers/transform.d.ts +2 -2
  119. package/dist/dataParser/parsers/transform.mjs +4 -4
  120. package/dist/dataParser/parsers/tuple.cjs +14 -14
  121. package/dist/dataParser/parsers/tuple.mjs +4 -4
  122. package/dist/dataParser/parsers/union.cjs +26 -8
  123. package/dist/dataParser/parsers/union.mjs +26 -8
  124. package/dist/flow/calledByNext.cjs +13 -0
  125. package/dist/flow/calledByNext.d.ts +47 -0
  126. package/dist/flow/calledByNext.mjs +11 -0
  127. package/dist/flow/debounce.cjs +16 -0
  128. package/dist/flow/debounce.d.ts +63 -0
  129. package/dist/flow/debounce.mjs +14 -0
  130. package/dist/flow/exec.cjs +101 -0
  131. package/dist/flow/exec.d.ts +4 -3
  132. package/dist/flow/exec.mjs +101 -0
  133. package/dist/flow/index.cjs +28 -0
  134. package/dist/flow/index.d.ts +5 -0
  135. package/dist/flow/index.mjs +10 -1
  136. package/dist/flow/queue.cjs +19 -0
  137. package/dist/flow/queue.d.ts +47 -0
  138. package/dist/flow/queue.mjs +17 -0
  139. package/dist/flow/run.cjs +118 -0
  140. package/dist/flow/run.d.ts +6 -4
  141. package/dist/flow/run.mjs +113 -1
  142. package/dist/flow/theFlow/calledByNext.cjs +11 -0
  143. package/dist/flow/theFlow/calledByNext.d.ts +5 -0
  144. package/dist/flow/theFlow/calledByNext.mjs +8 -0
  145. package/dist/flow/theFlow/debounce.cjs +11 -0
  146. package/dist/flow/theFlow/debounce.d.ts +9 -0
  147. package/dist/flow/theFlow/debounce.mjs +8 -0
  148. package/dist/flow/theFlow/index.d.ts +11 -3
  149. package/dist/flow/theFlow/queue.cjs +11 -0
  150. package/dist/flow/theFlow/queue.d.ts +9 -0
  151. package/dist/flow/theFlow/queue.mjs +8 -0
  152. package/dist/flow/theFlow/throttling.cjs +11 -0
  153. package/dist/flow/theFlow/throttling.d.ts +10 -0
  154. package/dist/flow/theFlow/throttling.mjs +8 -0
  155. package/dist/flow/throttling.cjs +27 -0
  156. package/dist/flow/throttling.d.ts +60 -0
  157. package/dist/flow/throttling.mjs +25 -0
  158. package/dist/flow/toFunction.cjs +15 -0
  159. package/dist/flow/toFunction.d.ts +56 -0
  160. package/dist/flow/toFunction.mjs +13 -0
  161. package/dist/index.cjs +11 -0
  162. package/dist/index.mjs +4 -1
  163. package/dist/metadata.json +126 -0
  164. package/dist/number/types/isGreater.d.ts +26 -3
  165. package/dist/object/types/getPropsWithValue.d.ts +1 -1
  166. package/dist/object/types/getPropsWithValueExtends.d.ts +1 -1
  167. package/dist/string/length.d.ts +2 -2
  168. package/dist/string/types/split.d.ts +6 -5
  169. package/package.json +1 -1
@@ -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 {};
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;