@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.
- package/dist/common/asserts.cjs +12 -0
- package/dist/common/asserts.d.ts +26 -0
- package/dist/common/asserts.mjs +12 -1
- package/dist/common/callThen.cjs +14 -0
- package/dist/common/callThen.d.ts +35 -0
- package/dist/common/callThen.mjs +12 -0
- package/dist/common/index.d.ts +2 -0
- package/dist/common/queue.cjs +90 -0
- package/dist/common/queue.d.ts +46 -0
- package/dist/common/queue.mjs +87 -0
- package/dist/flow/calledByNext.cjs +13 -0
- package/dist/flow/calledByNext.d.ts +47 -0
- package/dist/flow/calledByNext.mjs +11 -0
- package/dist/flow/debounce.cjs +16 -0
- package/dist/flow/debounce.d.ts +63 -0
- package/dist/flow/debounce.mjs +14 -0
- package/dist/flow/exec.cjs +101 -0
- package/dist/flow/exec.d.ts +4 -3
- package/dist/flow/exec.mjs +101 -0
- package/dist/flow/index.cjs +28 -0
- package/dist/flow/index.d.ts +5 -0
- package/dist/flow/index.mjs +10 -1
- package/dist/flow/queue.cjs +19 -0
- package/dist/flow/queue.d.ts +47 -0
- package/dist/flow/queue.mjs +17 -0
- package/dist/flow/run.cjs +118 -0
- package/dist/flow/run.d.ts +6 -4
- package/dist/flow/run.mjs +113 -1
- package/dist/flow/theFlow/calledByNext.cjs +11 -0
- package/dist/flow/theFlow/calledByNext.d.ts +5 -0
- package/dist/flow/theFlow/calledByNext.mjs +8 -0
- package/dist/flow/theFlow/debounce.cjs +11 -0
- package/dist/flow/theFlow/debounce.d.ts +9 -0
- package/dist/flow/theFlow/debounce.mjs +8 -0
- package/dist/flow/theFlow/index.d.ts +11 -3
- package/dist/flow/theFlow/queue.cjs +11 -0
- package/dist/flow/theFlow/queue.d.ts +9 -0
- package/dist/flow/theFlow/queue.mjs +8 -0
- package/dist/flow/theFlow/throttling.cjs +11 -0
- package/dist/flow/theFlow/throttling.d.ts +10 -0
- package/dist/flow/theFlow/throttling.mjs +8 -0
- package/dist/flow/throttling.cjs +27 -0
- package/dist/flow/throttling.d.ts +60 -0
- package/dist/flow/throttling.mjs +25 -0
- package/dist/flow/toFunction.cjs +15 -0
- package/dist/flow/toFunction.d.ts +56 -0
- package/dist/flow/toFunction.mjs +13 -0
- package/dist/index.cjs +6 -0
- package/dist/index.mjs +3 -1
- package/dist/metadata.json +99 -0
- package/dist/object/types/getPropsWithValue.d.ts +1 -1
- package/dist/object/types/getPropsWithValueExtends.d.ts +1 -1
- 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,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>;
|
|
@@ -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
|
|
17
|
-
export
|
|
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,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,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 {};
|
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';
|