@ixfx/process 0.36.0
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/__tests__/process.test.d.ts +2 -0
- package/dist/__tests__/process.test.d.ts.map +1 -0
- package/dist/__tests__/process.test.js +85 -0
- package/dist/src/basic.d.ts +37 -0
- package/dist/src/basic.d.ts.map +1 -0
- package/dist/src/basic.js +129 -0
- package/dist/src/cancel-error.d.ts +4 -0
- package/dist/src/cancel-error.d.ts.map +1 -0
- package/dist/src/cancel-error.js +6 -0
- package/dist/src/flow.d.ts +7 -0
- package/dist/src/flow.d.ts.map +1 -0
- package/dist/src/flow.js +37 -0
- package/dist/src/if-undefined.d.ts +49 -0
- package/dist/src/if-undefined.d.ts.map +1 -0
- package/dist/src/if-undefined.js +69 -0
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +5 -0
- package/dist/src/seen.d.ts +30 -0
- package/dist/src/seen.d.ts.map +1 -0
- package/dist/src/seen.js +67 -0
- package/dist/src/types.d.ts +51 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +1 -0
- package/dist/src/util.d.ts +10 -0
- package/dist/src/util.d.ts.map +1 -0
- package/dist/src/util.js +11 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +34 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process.test.d.ts","sourceRoot":"","sources":["../../__tests__/process.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { test, expect } from 'vitest';
|
|
2
|
+
import * as Basic from '../src/basic.js';
|
|
3
|
+
import * as Process from '../src/index.js';
|
|
4
|
+
test('seen', () => {
|
|
5
|
+
const c1Results = [];
|
|
6
|
+
const c1 = Process.flow(Process.seenToUndefined(), v => {
|
|
7
|
+
c1Results.push(v);
|
|
8
|
+
});
|
|
9
|
+
c1('hello');
|
|
10
|
+
c1('hello');
|
|
11
|
+
c1('bye');
|
|
12
|
+
expect(c1Results).toEqual([`hello`, undefined, `bye`]);
|
|
13
|
+
const c2Results = [];
|
|
14
|
+
const c2 = Process.flow(Process.seenToUndefinedByKey(), v => {
|
|
15
|
+
c2Results.push(v);
|
|
16
|
+
});
|
|
17
|
+
c2({ name: `a` });
|
|
18
|
+
c2({ name: `b` });
|
|
19
|
+
c2({ name: `a` });
|
|
20
|
+
expect(c2Results).toEqual([{ name: 'a' }, { name: 'b' }, undefined]);
|
|
21
|
+
const c3 = Process.flow(Process.seenLastToUndefined);
|
|
22
|
+
});
|
|
23
|
+
test(`basic`, () => {
|
|
24
|
+
const c1 = Process.flow(Basic.max(), Process.seenLastToUndefined());
|
|
25
|
+
expect(c1(100)).toBe(100);
|
|
26
|
+
expect(c1(90)).toBeFalsy();
|
|
27
|
+
// @ts-expect-error
|
|
28
|
+
expect(c1(null)).toBeFalsy();
|
|
29
|
+
expect(c1(110)).toBe(110);
|
|
30
|
+
const c2Results = [];
|
|
31
|
+
const c2 = Process.flow(Basic.max(), Process.seenLastToUndefined(), Process.ifNotUndefined(v => {
|
|
32
|
+
c2Results.push(v);
|
|
33
|
+
}));
|
|
34
|
+
c2(100);
|
|
35
|
+
c2(90);
|
|
36
|
+
c2(110);
|
|
37
|
+
expect(c2Results).toEqual([100, 110]);
|
|
38
|
+
const c3Results = [];
|
|
39
|
+
const c3 = Process.flow(Basic.max(), Process.seenLastToUndefined(), Process.cancelIfUndefined(), (v => {
|
|
40
|
+
c3Results.push(v);
|
|
41
|
+
}));
|
|
42
|
+
c3(100);
|
|
43
|
+
c3(90);
|
|
44
|
+
c3(110);
|
|
45
|
+
expect(c3Results).toEqual([100, 110]);
|
|
46
|
+
});
|
|
47
|
+
test(`math`, () => {
|
|
48
|
+
const c1 = Process.flow(Basic.max());
|
|
49
|
+
expect(c1(100)).toBe(100);
|
|
50
|
+
expect(c1(110)).toBe(110);
|
|
51
|
+
expect(c1(90)).toBe(110);
|
|
52
|
+
// @ts-expect-error
|
|
53
|
+
expect(c1(undefined)).toBe(110);
|
|
54
|
+
// @ts-expect-error
|
|
55
|
+
expect(c1(null)).toBe(110);
|
|
56
|
+
// @ts-expect-error
|
|
57
|
+
expect(c1(`hello`)).toBe(110);
|
|
58
|
+
const c2 = Process.flow(Basic.min());
|
|
59
|
+
expect(c2(100)).toBe(100);
|
|
60
|
+
expect(c2(110)).toBe(100);
|
|
61
|
+
expect(c2(90)).toBe(90);
|
|
62
|
+
// @ts-expect-error
|
|
63
|
+
expect(c2(undefined)).toBe(90);
|
|
64
|
+
// @ts-expect-error
|
|
65
|
+
expect(c2(null)).toBe(90);
|
|
66
|
+
// @ts-expect-error
|
|
67
|
+
expect(c2(`hello`)).toBe(90);
|
|
68
|
+
const c3 = Process.flow(Basic.sum());
|
|
69
|
+
expect(c3(10)).toBe(10);
|
|
70
|
+
expect(c3(20)).toBe(30);
|
|
71
|
+
expect(c3(30)).toBe(60);
|
|
72
|
+
// @ts-expect-error
|
|
73
|
+
expect(c3(undefined)).toBe(60);
|
|
74
|
+
// @ts-expect-error
|
|
75
|
+
expect(c3(null)).toBe(60);
|
|
76
|
+
// @ts-expect-error
|
|
77
|
+
expect(c3(`hello`)).toBe(60);
|
|
78
|
+
const c4 = Process.flow(Basic.tally(false));
|
|
79
|
+
expect(c4(100)).toBe(1);
|
|
80
|
+
expect(c4(110)).toBe(2);
|
|
81
|
+
expect(c4(90)).toBe(3);
|
|
82
|
+
expect(c4(undefined)).toBe(4);
|
|
83
|
+
expect(c4(null)).toBe(5);
|
|
84
|
+
expect(c4(`hello`)).toBe(6);
|
|
85
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Process, RankFunction, RankOptions } from "./types.js";
|
|
2
|
+
export type { Process } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Outputs the current largest-seen value
|
|
5
|
+
* @returns
|
|
6
|
+
*/
|
|
7
|
+
export declare const max: () => Process<number | number[], number>;
|
|
8
|
+
/**
|
|
9
|
+
* Outputs the current smallest-seen value
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
export declare const min: () => Process<number | number[], number>;
|
|
13
|
+
/**
|
|
14
|
+
* Returns a sum of values
|
|
15
|
+
* @returns
|
|
16
|
+
*/
|
|
17
|
+
export declare const sum: () => Process<number | number[], number>;
|
|
18
|
+
/**
|
|
19
|
+
* Returns the current average of input values
|
|
20
|
+
* @returns
|
|
21
|
+
*/
|
|
22
|
+
export declare const average: () => Process<number | number[], number>;
|
|
23
|
+
/**
|
|
24
|
+
* Returns the tally (ie number of) values
|
|
25
|
+
* @param countArrayItems
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
28
|
+
export declare const tally: (countArrayItems: boolean) => Process<any, number>;
|
|
29
|
+
/**
|
|
30
|
+
* Returns the 'best' value seen so far as determined by a ranking function.
|
|
31
|
+
* This is similar to min/max but usable for objects.
|
|
32
|
+
* @param r
|
|
33
|
+
* @param options
|
|
34
|
+
* @returns
|
|
35
|
+
*/
|
|
36
|
+
export declare function rank<In>(r: RankFunction<In>, options?: Partial<RankOptions>): (value: In) => In | undefined;
|
|
37
|
+
//# sourceMappingURL=basic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basic.d.ts","sourceRoot":"","sources":["../../src/basic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACrE,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C;;;GAGG;AACH,eAAO,MAAM,GAAG,QAAO,OAAO,CAAC,MAAM,GAAG,MAAM,EAAE,EAAE,MAAM,CAWvD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,GAAG,QAAO,OAAO,CAAC,MAAM,GAAG,MAAM,EAAE,EAAE,MAAM,CAWvD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,GAAG,QAAO,OAAO,CAAC,MAAM,GAAG,MAAM,EAAE,EAAE,MAAM,CAWvD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,OAAO,QAAO,OAAO,CAAC,MAAM,GAAG,MAAM,EAAE,EAAE,MAAM,CAa3D,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,KAAK,GAAI,iBAAiB,OAAO,KAAG,OAAO,CAAC,GAAG,EAAE,MAAM,CAYnE,CAAA;AAID;;;;;;GAMG;AACH,wBAAgB,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,EAAE,OAAO,GAAE,OAAO,CAAC,WAAW,CAAM,IAKtE,OAAO,EAAE,oBAqBlB"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outputs the current largest-seen value
|
|
3
|
+
* @returns
|
|
4
|
+
*/
|
|
5
|
+
export const max = () => {
|
|
6
|
+
let max = Number.MIN_SAFE_INTEGER;
|
|
7
|
+
const compute = (value) => {
|
|
8
|
+
const valueArray = Array.isArray(value) ? value : [value];
|
|
9
|
+
for (const subValue of valueArray) {
|
|
10
|
+
if (typeof subValue !== `number`)
|
|
11
|
+
break;
|
|
12
|
+
max = Math.max(subValue, max);
|
|
13
|
+
}
|
|
14
|
+
return max;
|
|
15
|
+
};
|
|
16
|
+
return compute;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Outputs the current smallest-seen value
|
|
20
|
+
* @returns
|
|
21
|
+
*/
|
|
22
|
+
export const min = () => {
|
|
23
|
+
let min = Number.MAX_SAFE_INTEGER;
|
|
24
|
+
const compute = (value) => {
|
|
25
|
+
const valueArray = Array.isArray(value) ? value : [value];
|
|
26
|
+
for (const subValue of valueArray) {
|
|
27
|
+
if (typeof subValue !== `number`)
|
|
28
|
+
break;
|
|
29
|
+
min = Math.min(subValue, min);
|
|
30
|
+
}
|
|
31
|
+
return min;
|
|
32
|
+
};
|
|
33
|
+
return compute;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Returns a sum of values
|
|
37
|
+
* @returns
|
|
38
|
+
*/
|
|
39
|
+
export const sum = () => {
|
|
40
|
+
let t = 0;
|
|
41
|
+
const compute = (value) => {
|
|
42
|
+
const valueArray = Array.isArray(value) ? value : [value];
|
|
43
|
+
for (const subValue of valueArray) {
|
|
44
|
+
if (typeof subValue !== `number`)
|
|
45
|
+
continue;
|
|
46
|
+
t += subValue;
|
|
47
|
+
}
|
|
48
|
+
return t;
|
|
49
|
+
};
|
|
50
|
+
return compute;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Returns the current average of input values
|
|
54
|
+
* @returns
|
|
55
|
+
*/
|
|
56
|
+
export const average = () => {
|
|
57
|
+
let total = 0;
|
|
58
|
+
let tally = 0;
|
|
59
|
+
const compute = (value) => {
|
|
60
|
+
const valueArray = Array.isArray(value) ? value : [value];
|
|
61
|
+
for (const subValue of valueArray) {
|
|
62
|
+
if (typeof subValue !== `number`)
|
|
63
|
+
continue;
|
|
64
|
+
tally++;
|
|
65
|
+
total += subValue;
|
|
66
|
+
}
|
|
67
|
+
return total / tally;
|
|
68
|
+
};
|
|
69
|
+
return compute;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Returns the tally (ie number of) values
|
|
73
|
+
* @param countArrayItems
|
|
74
|
+
* @returns
|
|
75
|
+
*/
|
|
76
|
+
export const tally = (countArrayItems) => {
|
|
77
|
+
let t = 0;
|
|
78
|
+
const compute = (value) => {
|
|
79
|
+
if (countArrayItems) {
|
|
80
|
+
if (Array.isArray(value))
|
|
81
|
+
t += value.length;
|
|
82
|
+
else
|
|
83
|
+
t++;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
t++;
|
|
87
|
+
}
|
|
88
|
+
return t;
|
|
89
|
+
};
|
|
90
|
+
return compute;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Returns the 'best' value seen so far as determined by a ranking function.
|
|
94
|
+
* This is similar to min/max but usable for objects.
|
|
95
|
+
* @param r
|
|
96
|
+
* @param options
|
|
97
|
+
* @returns
|
|
98
|
+
*/
|
|
99
|
+
export function rank(r, options = {}) {
|
|
100
|
+
const includeType = options.includeType;
|
|
101
|
+
const emitEqualRanked = options.emitEqualRanked ?? false;
|
|
102
|
+
const emitRepeatHighest = options.emitRepeatHighest ?? false;
|
|
103
|
+
let best;
|
|
104
|
+
return (value) => {
|
|
105
|
+
if (includeType && typeof value !== includeType)
|
|
106
|
+
return;
|
|
107
|
+
if (best === undefined) {
|
|
108
|
+
best = value;
|
|
109
|
+
return best;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
const result = r(value, best);
|
|
113
|
+
//console.log(`result: ${ result } value: ${ JSON.stringify(value) } best: ${ JSON.stringify(best) }`);
|
|
114
|
+
if (result == `a`) {
|
|
115
|
+
// New value is the current best
|
|
116
|
+
best = value;
|
|
117
|
+
return best;
|
|
118
|
+
}
|
|
119
|
+
else if (result === `eq` && emitEqualRanked) {
|
|
120
|
+
// New value is same rank as previous, but we have flag on
|
|
121
|
+
return best;
|
|
122
|
+
}
|
|
123
|
+
else if (emitRepeatHighest) {
|
|
124
|
+
// Emit current highest due to flag
|
|
125
|
+
return best;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cancel-error.d.ts","sourceRoot":"","sources":["../../src/cancel-error.ts"],"names":[],"mappings":"AAAA,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,GAAG;CAIzB"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Process } from "./types.js";
|
|
2
|
+
export declare function flow<T1, T2>(...processors: [Process<T1, T2>]): (value: T1) => T2;
|
|
3
|
+
export declare function flow<T1, T2, T3>(...processors: [Process<T1, T2>, Process<T2, T3>]): (value: T1) => T3;
|
|
4
|
+
export declare function flow<T1, T2, T3, T4>(...processors: [Process<T1, T2>, Process<T2, T3>, Process<T3, T4>]): (value: T1) => T4;
|
|
5
|
+
export declare function flow<T1, T2, T3, T4, T5>(...processors: [Process<T1, T2>, Process<T2, T3>, Process<T3, T4>, Process<T4, T5>]): (value: T1) => T5;
|
|
6
|
+
export declare function flow<T1, T2, T3, T4, T5, T6>(...processors: [Process<T1, T2>, Process<T2, T3>, Process<T3, T4>, Process<T4, T5>, Process<T5, T6>]): (value: T1) => T6;
|
|
7
|
+
//# sourceMappingURL=flow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/flow.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,YAAY,CAAC;AACtD,wBAAgB,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,UAAU,EAAE,CAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAE,GAAG,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC;AACpF,wBAAgB,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,UAAU,EAAE,CAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAE,GAAG,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC;AACzG,wBAAgB,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,UAAU,EAAE,CAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAE,GAAG,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC;AAC9H,wBAAgB,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,UAAU,EAAE,CAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAE,GAAG,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC;AACnJ,wBAAgB,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,UAAU,EAAE,CAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAE,GAAG,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC"}
|
package/dist/src/flow.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { CancelError } from "./cancel-error.js";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a flow of data processors (up to 5 are supported).
|
|
4
|
+
* The flow is encapsulated in a function that accepts an input value an returns an output.
|
|
5
|
+
*
|
|
6
|
+
* ```js
|
|
7
|
+
* const p = flow(
|
|
8
|
+
* (value:string) => value.toUpperCase(), // Convert to uppercase
|
|
9
|
+
* (value:string) => value.at(0) === 'A') // If first letter is an A, return true
|
|
10
|
+
* );
|
|
11
|
+
* p('apple'); // True
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* Each processing function is expected to take in one input value and return one value.
|
|
15
|
+
* @param processors
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
export function flow(...processors) {
|
|
19
|
+
return (value) => {
|
|
20
|
+
let v = value;
|
|
21
|
+
for (const p of processors) {
|
|
22
|
+
try {
|
|
23
|
+
// @ts-expect-error
|
|
24
|
+
v = p(v);
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
if (err instanceof CancelError) {
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
throw err;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return v;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
/**
|
|
3
|
+
* Calls a function if the input value is not undefined.
|
|
4
|
+
* Return value from function is passed to next function in flow.
|
|
5
|
+
*
|
|
6
|
+
* ```js
|
|
7
|
+
* const flow = Process.flow(
|
|
8
|
+
* Process.max(),
|
|
9
|
+
* Process.seenLastToUndefined(),
|
|
10
|
+
* Process.ifNotUndefined(v => {
|
|
11
|
+
* console.log(`v:`, v);
|
|
12
|
+
* })
|
|
13
|
+
* );
|
|
14
|
+
* flow(100); // Prints 'v:100'
|
|
15
|
+
* flow(90); // Nothing happens max value has not changed
|
|
16
|
+
* flow(110); // Prints 'v:110'
|
|
17
|
+
* ```
|
|
18
|
+
* @param fn
|
|
19
|
+
* @returns
|
|
20
|
+
*/
|
|
21
|
+
export declare function ifNotUndefined<TIn, TOut>(fn: (value: Exclude<TIn, undefined>) => TOut): (value: TIn) => TIn | TOut;
|
|
22
|
+
/**
|
|
23
|
+
* Cancels the remaining flow operations if _undefined_ is an input.
|
|
24
|
+
* See also {@link ifUndefined} or {@link ifNotUndefined}.
|
|
25
|
+
*
|
|
26
|
+
* ```js
|
|
27
|
+
* const c3 = Process.flow(
|
|
28
|
+
* Basic.max(),
|
|
29
|
+
* Process.seenLastToUndefined(),
|
|
30
|
+
* Process.cancelIfUndefined(),
|
|
31
|
+
* (v => {
|
|
32
|
+
* console.log(v);
|
|
33
|
+
* })
|
|
34
|
+
* );
|
|
35
|
+
* c3(100); // Prints '100'
|
|
36
|
+
* c3(90); // Doesn't print anything since max does not change
|
|
37
|
+
* c3(110); // Prints '110'
|
|
38
|
+
* ```
|
|
39
|
+
* @returns
|
|
40
|
+
*/
|
|
41
|
+
export declare function cancelIfUndefined<TIn>(): (value: TIn | undefined) => TIn;
|
|
42
|
+
/**
|
|
43
|
+
* Returns the output of `fn` if the input value is _undefined_.
|
|
44
|
+
* See also: {@link ifNotUndefined} and {@link cancelIfUndefined}.
|
|
45
|
+
* @param fn
|
|
46
|
+
* @returns
|
|
47
|
+
*/
|
|
48
|
+
export declare function ifUndefined<TIn, TOut>(fn: () => TOut): (value: TIn) => TOut | (TIn & ({} | null));
|
|
49
|
+
//# sourceMappingURL=if-undefined.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"if-undefined.d.ts","sourceRoot":"","sources":["../../src/if-undefined.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,KAAK,IAAI,IAC5E,OAAO,GAAG,gBAKnB;AAID;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,MAC3B,OAAO,GAAG,GAAG,SAAS,KAEZ,GAAG,CAEtB;AACD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,IAAI,IAC3C,OAAO,GAAG,gCAInB"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { CancelError } from "./cancel-error.js";
|
|
2
|
+
/**
|
|
3
|
+
/**
|
|
4
|
+
* Calls a function if the input value is not undefined.
|
|
5
|
+
* Return value from function is passed to next function in flow.
|
|
6
|
+
*
|
|
7
|
+
* ```js
|
|
8
|
+
* const flow = Process.flow(
|
|
9
|
+
* Process.max(),
|
|
10
|
+
* Process.seenLastToUndefined(),
|
|
11
|
+
* Process.ifNotUndefined(v => {
|
|
12
|
+
* console.log(`v:`, v);
|
|
13
|
+
* })
|
|
14
|
+
* );
|
|
15
|
+
* flow(100); // Prints 'v:100'
|
|
16
|
+
* flow(90); // Nothing happens max value has not changed
|
|
17
|
+
* flow(110); // Prints 'v:110'
|
|
18
|
+
* ```
|
|
19
|
+
* @param fn
|
|
20
|
+
* @returns
|
|
21
|
+
*/
|
|
22
|
+
export function ifNotUndefined(fn) {
|
|
23
|
+
return (value) => {
|
|
24
|
+
if (value === undefined)
|
|
25
|
+
return value;
|
|
26
|
+
const v = fn(value);
|
|
27
|
+
return v;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Cancels the remaining flow operations if _undefined_ is an input.
|
|
32
|
+
* See also {@link ifUndefined} or {@link ifNotUndefined}.
|
|
33
|
+
*
|
|
34
|
+
* ```js
|
|
35
|
+
* const c3 = Process.flow(
|
|
36
|
+
* Basic.max(),
|
|
37
|
+
* Process.seenLastToUndefined(),
|
|
38
|
+
* Process.cancelIfUndefined(),
|
|
39
|
+
* (v => {
|
|
40
|
+
* console.log(v);
|
|
41
|
+
* })
|
|
42
|
+
* );
|
|
43
|
+
* c3(100); // Prints '100'
|
|
44
|
+
* c3(90); // Doesn't print anything since max does not change
|
|
45
|
+
* c3(110); // Prints '110'
|
|
46
|
+
* ```
|
|
47
|
+
* @returns
|
|
48
|
+
*/
|
|
49
|
+
export function cancelIfUndefined() {
|
|
50
|
+
return (value) => {
|
|
51
|
+
if (value === undefined)
|
|
52
|
+
throw new CancelError(`cancel`);
|
|
53
|
+
return value;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Returns the output of `fn` if the input value is _undefined_.
|
|
58
|
+
* See also: {@link ifNotUndefined} and {@link cancelIfUndefined}.
|
|
59
|
+
* @param fn
|
|
60
|
+
* @returns
|
|
61
|
+
*/
|
|
62
|
+
export function ifUndefined(fn) {
|
|
63
|
+
return (value) => {
|
|
64
|
+
if (value === undefined)
|
|
65
|
+
return fn();
|
|
66
|
+
else
|
|
67
|
+
return value;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,YAAY,CAAC;AAChC,cAAe,YAAY,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Process } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* If a value is same as the previous value, _undefined_ is emitted instead.
|
|
4
|
+
* @param eq Equality function. If not specified, === semantics are used.
|
|
5
|
+
* @returns
|
|
6
|
+
*/
|
|
7
|
+
export declare function seenLastToUndefined<TIn>(eq?: (a: TIn, b: TIn) => boolean): Process<TIn, TIn | undefined>;
|
|
8
|
+
/**
|
|
9
|
+
* If a value is same as any previously-seen value, _undefined_ is emitted instead.
|
|
10
|
+
* It stores all previous values and compares against them for each new value.
|
|
11
|
+
* This would likely be not very efficient compared to {@link seenToUndefinedByKey} which uses a one-time computed
|
|
12
|
+
* key and efficient storage of only the keys (using a Set).
|
|
13
|
+
*
|
|
14
|
+
* @param eq Equality function. If not specified, === semantics are used.
|
|
15
|
+
* @returns
|
|
16
|
+
*/
|
|
17
|
+
export declare function seenToUndefined<TIn>(eq?: (a: TIn, b: TIn) => boolean): Process<TIn, TIn | undefined>;
|
|
18
|
+
/**
|
|
19
|
+
* If a value is the same as any previously-seen value, _undefined_ is emitted instead.
|
|
20
|
+
* This version uses a function to create a string key of the object, by default JSON.stringify.
|
|
21
|
+
* Thus we don't need to store all previously seen objects, just their keys.
|
|
22
|
+
*
|
|
23
|
+
* Alternatively, if a key function doesn't make sense for the value, use
|
|
24
|
+
* {@link seenToUndefined}, which stores the values (less efficient).
|
|
25
|
+
*
|
|
26
|
+
* @param toString
|
|
27
|
+
* @returns
|
|
28
|
+
*/
|
|
29
|
+
export declare function seenToUndefinedByKey<TIn>(toString?: (value: TIn) => string): Process<TIn, TIn | undefined>;
|
|
30
|
+
//# sourceMappingURL=seen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seen.d.ts","sourceRoot":"","sources":["../../src/seen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG1C;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,CAAC,CAUxG;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,CAAC,CAWpG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,CAAC,CAU1G"}
|
package/dist/src/seen.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { isEqualDefault, toStringDefault } from "./util.js";
|
|
2
|
+
/**
|
|
3
|
+
* If a value is same as the previous value, _undefined_ is emitted instead.
|
|
4
|
+
* @param eq Equality function. If not specified, === semantics are used.
|
|
5
|
+
* @returns
|
|
6
|
+
*/
|
|
7
|
+
export function seenLastToUndefined(eq) {
|
|
8
|
+
if (eq === undefined)
|
|
9
|
+
eq = isEqualDefault;
|
|
10
|
+
let lastValue;
|
|
11
|
+
return (value) => {
|
|
12
|
+
if (value !== lastValue) {
|
|
13
|
+
lastValue = value;
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
return undefined;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* If a value is same as any previously-seen value, _undefined_ is emitted instead.
|
|
21
|
+
* It stores all previous values and compares against them for each new value.
|
|
22
|
+
* This would likely be not very efficient compared to {@link seenToUndefinedByKey} which uses a one-time computed
|
|
23
|
+
* key and efficient storage of only the keys (using a Set).
|
|
24
|
+
*
|
|
25
|
+
* @param eq Equality function. If not specified, === semantics are used.
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
28
|
+
export function seenToUndefined(eq) {
|
|
29
|
+
let seen = [];
|
|
30
|
+
if (eq === undefined)
|
|
31
|
+
eq = isEqualDefault;
|
|
32
|
+
return (value) => {
|
|
33
|
+
if (value === undefined)
|
|
34
|
+
return;
|
|
35
|
+
for (const s of seen) {
|
|
36
|
+
if (eq(s, value))
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
seen.push(value);
|
|
40
|
+
return value;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* If a value is the same as any previously-seen value, _undefined_ is emitted instead.
|
|
45
|
+
* This version uses a function to create a string key of the object, by default JSON.stringify.
|
|
46
|
+
* Thus we don't need to store all previously seen objects, just their keys.
|
|
47
|
+
*
|
|
48
|
+
* Alternatively, if a key function doesn't make sense for the value, use
|
|
49
|
+
* {@link seenToUndefined}, which stores the values (less efficient).
|
|
50
|
+
*
|
|
51
|
+
* @param toString
|
|
52
|
+
* @returns
|
|
53
|
+
*/
|
|
54
|
+
export function seenToUndefinedByKey(toString) {
|
|
55
|
+
let seen = new Set();
|
|
56
|
+
if (toString === undefined)
|
|
57
|
+
toString = toStringDefault;
|
|
58
|
+
return (value) => {
|
|
59
|
+
if (value === undefined)
|
|
60
|
+
return;
|
|
61
|
+
const key = toString(value);
|
|
62
|
+
if (seen.has(key))
|
|
63
|
+
return;
|
|
64
|
+
seen.add(key);
|
|
65
|
+
return value;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export type Process<TIn, TOut> = (value: TIn) => TOut;
|
|
2
|
+
export type ProcessFactory<TIn, TOut> = () => Process<TIn, TOut>;
|
|
3
|
+
export type Processors1<T1, T2> = [
|
|
4
|
+
Process<T1, T2>
|
|
5
|
+
];
|
|
6
|
+
export type Processors2<T1, T2, T3> = [
|
|
7
|
+
Process<T1, T2>,
|
|
8
|
+
Process<T2, T3>
|
|
9
|
+
];
|
|
10
|
+
export type Processors3<T1, T2, T3, T4> = [
|
|
11
|
+
Process<T1, T2>,
|
|
12
|
+
Process<T2, T3>,
|
|
13
|
+
Process<T3, T4>
|
|
14
|
+
];
|
|
15
|
+
export type Processors4<T1, T2, T3, T4, T5> = [
|
|
16
|
+
Process<T1, T2>,
|
|
17
|
+
Process<T2, T3>,
|
|
18
|
+
Process<T3, T4>,
|
|
19
|
+
Process<T4, T5>
|
|
20
|
+
];
|
|
21
|
+
export type Processors5<T1, T2, T3, T4, T5, T6> = [
|
|
22
|
+
Process<T1, T2>,
|
|
23
|
+
Process<T2, T3>,
|
|
24
|
+
Process<T3, T4>,
|
|
25
|
+
Process<T4, T5>,
|
|
26
|
+
Process<T5, T6>
|
|
27
|
+
];
|
|
28
|
+
export type Processors<T1, T2, T3, T4, T5, T6> = Processors1<T1, T2> | Processors2<T1, T2, T3> | Processors3<T1, T2, T3, T4> | Processors4<T1, T2, T3, T4, T5> | Processors5<T1, T2, T3, T4, T5, T6>;
|
|
29
|
+
/**
|
|
30
|
+
* A rank function that compares A and B.
|
|
31
|
+
* Returns the highest value, 'a' or 'b'.
|
|
32
|
+
* Returns 'eq' if values are equal
|
|
33
|
+
*/
|
|
34
|
+
export type RankFunction<T> = (a: T, b: T) => `a` | `b` | `eq`;
|
|
35
|
+
export type RankOptions = {
|
|
36
|
+
/**
|
|
37
|
+
* If set, only values with this JS type are included
|
|
38
|
+
*/
|
|
39
|
+
includeType?: `string` | `number` | `object` | `boolean`;
|
|
40
|
+
/**
|
|
41
|
+
* If _true_, also emits values when they rank equal with current highest.
|
|
42
|
+
* _false_ by default
|
|
43
|
+
*/
|
|
44
|
+
emitEqualRanked?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* If _true_, emits the current highest value even if it hasn't changed.
|
|
47
|
+
* This means it will match the tempo of the incoming stream.
|
|
48
|
+
*/
|
|
49
|
+
emitRepeatHighest?: boolean;
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;AACtD,MAAM,MAAM,cAAc,CAAC,GAAG,EAAE,IAAI,IAAI,MAAM,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAEjE,MAAM,MAAM,WAAW,CAAC,EAAE,EAAE,EAAE,IAAI;IAChC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;CAChB,CAAA;AAED,MAAM,MAAM,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI;IACpC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;CAChB,CAAA;AAED,MAAM,MAAM,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI;IACxC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;CAChB,CAAA;AAED,MAAM,MAAM,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI;IAC5C,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;CAChB,CAAA;AAED,MAAM,MAAM,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI;IAChD,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC;CAChB,CAAA;AACD,MAAM,MAAM,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;AAGrM;;;;GAIG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,GAAG,GAAG,GAAG,GAAG,IAAI,CAAA;AAE9D,MAAM,MAAM,WAAW,GAAG;IACxB;;OAEG;IACH,WAAW,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAA;IACxD;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC5B,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default comparer function is equiv to checking `a === b`.
|
|
3
|
+
* Use {@link isEqualValueDefault} to compare by value, via comparing JSON string representation.
|
|
4
|
+
*/
|
|
5
|
+
export declare const isEqualDefault: <T>(a: T, b: T) => boolean;
|
|
6
|
+
/**
|
|
7
|
+
* A default converter to string that uses JSON.stringify if its an object, or the thing itself if it's a string
|
|
8
|
+
*/
|
|
9
|
+
export declare const toStringDefault: <V>(itemToMakeStringFor: V) => string;
|
|
10
|
+
//# sourceMappingURL=util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/util.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,KAAG,OAAkB,CAAC;AAElE;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,EAAE,qBAAqB,CAAC,KAAG,MAGnB,CAAC"}
|
package/dist/src/util.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default comparer function is equiv to checking `a === b`.
|
|
3
|
+
* Use {@link isEqualValueDefault} to compare by value, via comparing JSON string representation.
|
|
4
|
+
*/
|
|
5
|
+
export const isEqualDefault = (a, b) => a === b;
|
|
6
|
+
/**
|
|
7
|
+
* A default converter to string that uses JSON.stringify if its an object, or the thing itself if it's a string
|
|
8
|
+
*/
|
|
9
|
+
export const toStringDefault = (itemToMakeStringFor) => typeof itemToMakeStringFor === `string`
|
|
10
|
+
? itemToMakeStringFor
|
|
11
|
+
: JSON.stringify(itemToMakeStringFor);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["../src/basic.ts","../src/cancel-error.ts","../src/flow.ts","../src/if-undefined.ts","../src/index.ts","../src/seen.ts","../src/types.ts","../src/util.ts","../__tests__/process.test.ts"],"version":"5.8.3"}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ixfx/process",
|
|
3
|
+
"version": "0.36.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"files": [
|
|
8
|
+
"dist/"
|
|
9
|
+
],
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./src/index.ts",
|
|
13
|
+
"import": "./src/index.ts"
|
|
14
|
+
},
|
|
15
|
+
"./basic": {
|
|
16
|
+
"types": "./src/basic.ts",
|
|
17
|
+
"import": "./src/basic.ts"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"main": "dist/src/index.js",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/src/index.d.ts",
|
|
26
|
+
"import": "./dist/src/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./basic": {
|
|
29
|
+
"types": "./dist/src/basic.d.ts",
|
|
30
|
+
"import": "./dist/src/basic.js"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|