@rainbow-o23/n1 1.0.49 → 1.0.50
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/README.md +44 -6
- package/index.cjs +641 -78
- package/index.d.ts +1 -0
- package/index.js +598 -54
- package/lib/pipeline/index.d.ts +2 -1
- package/lib/pipeline/step-helpers-utils.d.ts +28 -3
- package/lib/pipeline/step-helpers-value-operator.d.ts +34 -0
- package/lib/pipeline/step-helpers.d.ts +9 -23
- package/lib/pipeline/types.d.ts +1 -0
- package/lib/pipeline/value-operators/action-types.d.ts +18 -0
- package/lib/pipeline/value-operators/index.d.ts +8 -0
- package/lib/pipeline/value-operators/test-any-actions.d.ts +10 -0
- package/lib/pipeline/value-operators/test-decimal-actions.d.ts +25 -0
- package/lib/pipeline/value-operators/test-string-actions.d.ts +2 -0
- package/lib/pipeline/value-operators/testers.d.ts +36 -0
- package/lib/pipeline/value-operators/transform-decimal-actions.d.ts +21 -0
- package/lib/pipeline/value-operators/transform-string-actions.d.ts +10 -0
- package/lib/pipeline/value-operators/transformers.d.ts +31 -0
- package/package.json +25 -3
- package/rollup.config.base.js +1 -2
- package/src/index.ts +3 -0
- package/src/lib/pipeline/index.ts +2 -1
- package/src/lib/pipeline/step-helpers-utils.ts +105 -29
- package/src/lib/pipeline/step-helpers-value-operator.ts +307 -0
- package/src/lib/pipeline/step-helpers.ts +24 -50
- package/src/lib/pipeline/types.ts +7 -0
- package/src/lib/pipeline/value-operators/action-types.ts +8 -0
- package/src/lib/pipeline/value-operators/index.ts +10 -0
- package/src/lib/pipeline/value-operators/test-any-actions.ts +58 -0
- package/src/lib/pipeline/value-operators/test-decimal-actions.ts +85 -0
- package/src/lib/pipeline/value-operators/test-string-actions.ts +15 -0
- package/src/lib/pipeline/value-operators/testers.ts +59 -0
- package/src/lib/pipeline/value-operators/transform-decimal-actions.ts +88 -0
- package/src/lib/pipeline/value-operators/transform-string-actions.ts +49 -0
- package/src/lib/pipeline/value-operators/transformers.ts +34 -0
- package/test/value-test.test.ts +55 -0
- /package/lib/{pipeline/envs.d.ts → envs.d.ts} +0 -0
- /package/src/lib/{pipeline/envs.ts → envs.ts} +0 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import {StaticImplements} from './types';
|
|
2
|
+
import {
|
|
3
|
+
AllTesters,
|
|
4
|
+
AllTransformers,
|
|
5
|
+
RegisteredValueAction,
|
|
6
|
+
RegisteredValueActionWithParams,
|
|
7
|
+
ValueAction,
|
|
8
|
+
ValueActionFailed,
|
|
9
|
+
ValueActionPassed
|
|
10
|
+
} from './value-operators';
|
|
11
|
+
|
|
12
|
+
interface ValueOperatorBase {
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
+
$value?: any;
|
|
15
|
+
$allowMoreAction: boolean;
|
|
16
|
+
$actions?: Array<ValueAction>;
|
|
17
|
+
$allowUseDefault: boolean;
|
|
18
|
+
$defaultUsed: boolean;
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
+
$defaultValue?: any;
|
|
21
|
+
// control
|
|
22
|
+
$allowNoParamFuncCall: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* function call is allowed for tester and transformer, only when the {@link $allowNoParamFuncCall} is true.
|
|
27
|
+
* and once it is called, set {@link $allowNoParamFuncCall} to false.
|
|
28
|
+
* otherwise, throw exception.
|
|
29
|
+
*/
|
|
30
|
+
const applyOperator = (operator: IValueOperator, base: ValueOperatorBase) => {
|
|
31
|
+
if (base.$allowNoParamFuncCall) {
|
|
32
|
+
base.$allowNoParamFuncCall = false;
|
|
33
|
+
return operator;
|
|
34
|
+
} else {
|
|
35
|
+
throw new Error(`Function call is not allowed from: ${operator}.`);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const NOT_FOUND = Symbol('not found');
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
40
|
+
type ValueActionFind = (operator: IValueOperator, base: ValueOperatorBase, prop: string) => IValueOperator | ((...args: Array<any>) => IValueOperator) | symbol;
|
|
41
|
+
const findValueAction = (actions: Record<string, RegisteredValueAction | RegisteredValueActionWithParams>): ValueActionFind => {
|
|
42
|
+
return (operator: IValueOperator, base: ValueOperatorBase, prop: string) => {
|
|
43
|
+
const tester = actions[prop];
|
|
44
|
+
if (tester == null) {
|
|
45
|
+
return NOT_FOUND;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
base.$allowUseDefault = true;
|
|
49
|
+
if (base.$actions == null) {
|
|
50
|
+
base.$actions = [];
|
|
51
|
+
}
|
|
52
|
+
if (tester.type === 'func') {
|
|
53
|
+
// push to tester stack
|
|
54
|
+
base.$actions.push(tester.func);
|
|
55
|
+
base.$allowNoParamFuncCall = true;
|
|
56
|
+
return operator;
|
|
57
|
+
} else if (tester.type === 'param') {
|
|
58
|
+
// build a function to accept parameters
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
60
|
+
return (...args: Array<any>) => {
|
|
61
|
+
base.$actions.push(tester.func(...args));
|
|
62
|
+
return operator;
|
|
63
|
+
};
|
|
64
|
+
} else {
|
|
65
|
+
throw new Error(`Unknown tester type: ${tester}.`);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
const findTester = findValueAction(AllTesters);
|
|
70
|
+
const findTransformer = findValueAction(AllTransformers);
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
72
|
+
type UseDefaultFind = (operator: IValueOperator, base: ValueOperatorBase, prop: string) => ((defaultValue: any) => IValueOperator) | undefined | symbol;
|
|
73
|
+
const findUseDefault: UseDefaultFind = (operator: IValueOperator, base: ValueOperatorBase, prop: string) => {
|
|
74
|
+
if (!base.$allowUseDefault || !['orUseDefault', 'useDefault', 'withDefault', 'orElse', 'else'].includes(prop)) {
|
|
75
|
+
return NOT_FOUND;
|
|
76
|
+
}
|
|
77
|
+
if ((base.$actions == null || base.$actions.length === 0)) {
|
|
78
|
+
// no action defined, use default value directly, no way
|
|
79
|
+
return (void 0);
|
|
80
|
+
}
|
|
81
|
+
base.$allowMoreAction = false;
|
|
82
|
+
base.$allowUseDefault = false;
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
84
|
+
return (defaultValue: any) => {
|
|
85
|
+
base.$defaultUsed = true;
|
|
86
|
+
base.$defaultValue = defaultValue;
|
|
87
|
+
return operator;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
type ValueFind = (operator: IValueOperator, base: ValueOperatorBase, prop: string) => (<T>() => T) | undefined | symbol;
|
|
91
|
+
const createValueRetrieveFunc = (base: ValueOperatorBase) => {
|
|
92
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
93
|
+
return <T>(): ValueActionPassed<T> | ValueActionFailed<any> => {
|
|
94
|
+
const tested = {test: true, value: base.$value};
|
|
95
|
+
for (const action of (base.$actions ?? [])) {
|
|
96
|
+
const result = action(tested.value);
|
|
97
|
+
if (!result.test) {
|
|
98
|
+
// failed on action proceeding, ignore all tailing actions, and use original value
|
|
99
|
+
tested.test = false;
|
|
100
|
+
tested.value = base.$value;
|
|
101
|
+
break;
|
|
102
|
+
} else {
|
|
103
|
+
// action proceeded successfully
|
|
104
|
+
tested.value = result.value;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (tested.test) {
|
|
108
|
+
// all actions proceeded, and value might be transformed, do nothing
|
|
109
|
+
} else if (base.$defaultUsed) {
|
|
110
|
+
// failed on action proceeding, use default value if defined
|
|
111
|
+
// therefore, final result has been treated as success
|
|
112
|
+
tested.test = true;
|
|
113
|
+
tested.value = base.$defaultValue as T;
|
|
114
|
+
} else {
|
|
115
|
+
// failed on acton proceeding, and no default value defined, return value itself
|
|
116
|
+
tested.value = base.$value;
|
|
117
|
+
}
|
|
118
|
+
return tested;
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
const findValue: ValueFind = (_operator: IValueOperator, base: ValueOperatorBase, prop: string) => {
|
|
122
|
+
if (prop !== 'value') {
|
|
123
|
+
return NOT_FOUND;
|
|
124
|
+
}
|
|
125
|
+
if ((base.$actions == null || base.$actions.length === 0)) {
|
|
126
|
+
// no action defined, get value directly, no way
|
|
127
|
+
return (void 0);
|
|
128
|
+
}
|
|
129
|
+
// return value anyway, no matter success or failure
|
|
130
|
+
return <T>(): T => createValueRetrieveFunc(base)<T>().value;
|
|
131
|
+
};
|
|
132
|
+
type SuccessCallback = (callback: <T>(value: T) => void) => ({ failure: (callback: <V>(value: V) => void) => void });
|
|
133
|
+
type FailureCallback = (callback: <V>(value: V) => void) => ({ success: (callback: <T>(value: T) => void) => void });
|
|
134
|
+
type SuccessOrFailureCallbackFind = (operator: IValueOperator, base: ValueOperatorBase, prop: string) => SuccessCallback | FailureCallback | undefined | symbol;
|
|
135
|
+
const findSuccessOrFailureCallback: SuccessOrFailureCallbackFind = (_operator: IValueOperator, base: ValueOperatorBase, prop: string) => {
|
|
136
|
+
if (prop !== 'success' && prop !== 'failure') {
|
|
137
|
+
return NOT_FOUND;
|
|
138
|
+
}
|
|
139
|
+
if ((base.$actions == null || base.$actions.length === 0)) {
|
|
140
|
+
// no action defined, get value directly, no way
|
|
141
|
+
return (void 0);
|
|
142
|
+
}
|
|
143
|
+
switch (prop) {
|
|
144
|
+
case 'success':
|
|
145
|
+
return (callback: <T>(value: T) => void) => {
|
|
146
|
+
const tested = createValueRetrieveFunc(base)();
|
|
147
|
+
if (tested.test) {
|
|
148
|
+
callback(tested.value);
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
failure: (callback: <T>(value: T) => void): void => {
|
|
152
|
+
if (!tested.test) {
|
|
153
|
+
callback(tested.value);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
case 'failure':
|
|
159
|
+
return (callback: <V>(value: V) => void) => {
|
|
160
|
+
const tested = createValueRetrieveFunc(base)();
|
|
161
|
+
if (!tested.test) {
|
|
162
|
+
callback(tested.value);
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
success: (callback: <T>(value: T) => void): void => {
|
|
166
|
+
if (tested.test) {
|
|
167
|
+
callback(tested.value);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
default:
|
|
173
|
+
throw new Error(`Unknown callback type: ${prop}.`);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
type OKFind = (operator: IValueOperator, base: ValueOperatorBase, prop: string) => (() => boolean) | symbol;
|
|
177
|
+
const findOK: OKFind = (operator: IValueOperator, base: ValueOperatorBase, prop: string) => {
|
|
178
|
+
if (prop !== 'ok') {
|
|
179
|
+
return NOT_FOUND;
|
|
180
|
+
}
|
|
181
|
+
if ((base.$actions == null || base.$actions.length === 0)) {
|
|
182
|
+
// no action defined, get value directly, no way
|
|
183
|
+
return (void 0);
|
|
184
|
+
}
|
|
185
|
+
return (): boolean => createValueRetrieveFunc(base)().test;
|
|
186
|
+
};
|
|
187
|
+
type PromiseFind = (operator: IValueOperator, base: ValueOperatorBase, prop: string) => (<T>() => Promise<T>) | symbol;
|
|
188
|
+
const findPromise: PromiseFind = (_operator: IValueOperator, base: ValueOperatorBase, prop: string) => {
|
|
189
|
+
if (prop !== 'promise') {
|
|
190
|
+
return NOT_FOUND;
|
|
191
|
+
}
|
|
192
|
+
if ((base.$actions == null || base.$actions.length === 0)) {
|
|
193
|
+
// no action defined, get value directly, no way
|
|
194
|
+
return (void 0);
|
|
195
|
+
}
|
|
196
|
+
return async <T>(): Promise<T> => {
|
|
197
|
+
const tested = createValueRetrieveFunc(base)();
|
|
198
|
+
if (tested.test) {
|
|
199
|
+
return Promise.resolve(tested.value as T);
|
|
200
|
+
} else {
|
|
201
|
+
return Promise.reject(tested.value);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
const getFromOperator = (operator: IValueOperator, base: ValueOperatorBase, prop: string) => {
|
|
206
|
+
// set to false anyway
|
|
207
|
+
base.$allowNoParamFuncCall = false;
|
|
208
|
+
const finds = [
|
|
209
|
+
findTester, findTransformer, findUseDefault,
|
|
210
|
+
findValue, findSuccessOrFailureCallback, findOK, findPromise
|
|
211
|
+
];
|
|
212
|
+
for (const find of finds) {
|
|
213
|
+
const result = find(operator, base, prop);
|
|
214
|
+
if (result !== NOT_FOUND) {
|
|
215
|
+
return result;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// not found, return undefined
|
|
219
|
+
return (void 0);
|
|
220
|
+
};
|
|
221
|
+
const createOperator = (base: ValueOperatorBase): IValueOperator => {
|
|
222
|
+
const operatorBase = () => {
|
|
223
|
+
};
|
|
224
|
+
operatorBase.$base = base;
|
|
225
|
+
const operator = new Proxy(operatorBase, {
|
|
226
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
|
227
|
+
apply(base: typeof operatorBase, _thisArg: any, _argArray: any[]): any {
|
|
228
|
+
return applyOperator(operator, base.$base);
|
|
229
|
+
},
|
|
230
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
|
231
|
+
get(base: any, p: string, _receiver: any): any {
|
|
232
|
+
return getFromOperator(operator, base.$base, p);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
return operator;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export interface FinalValueRetriever {
|
|
239
|
+
value: <T>() => T;
|
|
240
|
+
success: <T>(value: T) => { failure: <V>(value: V) => void };
|
|
241
|
+
failure: <V>(value: V) => { success: <T>(value: T) => void };
|
|
242
|
+
ok: () => boolean;
|
|
243
|
+
// parameter of reject original value
|
|
244
|
+
promise: <T>() => Promise<T>;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export interface DefaultValueSetter extends FinalValueRetriever {
|
|
248
|
+
// once, or ignored
|
|
249
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
250
|
+
orUseDefault: (defaultValue: any) => FinalValueRetriever;
|
|
251
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
252
|
+
useDefault: (defaultValue: any) => FinalValueRetriever;
|
|
253
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
254
|
+
withDefault: (defaultValue: any) => FinalValueRetriever;
|
|
255
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
256
|
+
orElse: (defaultValue: any) => FinalValueRetriever;
|
|
257
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
258
|
+
else: (defaultValue: any) => FinalValueRetriever;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
type ActionType<T> = T extends RegisteredValueAction
|
|
262
|
+
? (ValueActionsWithDefault & (() => ValueActionsWithDefault))
|
|
263
|
+
: T extends RegisteredValueActionWithParams ? ((...args: Parameters<T['func']>) => ValueActionsWithDefault) : never;
|
|
264
|
+
export type ValueActions =
|
|
265
|
+
& { [K in keyof typeof AllTesters]: ActionType<typeof AllTesters[K]> }
|
|
266
|
+
& { [K in keyof typeof AllTransformers]: ActionType<typeof AllTransformers[K]> };
|
|
267
|
+
export type ValueActionsWithDefault = ValueActions & DefaultValueSetter;
|
|
268
|
+
|
|
269
|
+
export type IValueOperator = ValueActions;
|
|
270
|
+
|
|
271
|
+
export interface IValueOperatorBoostrap {
|
|
272
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
273
|
+
of(value: any): IValueOperator;
|
|
274
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
275
|
+
from(value: any): IValueOperator;
|
|
276
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
277
|
+
with(value: any): IValueOperator;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
@StaticImplements<IValueOperatorBoostrap>()
|
|
281
|
+
class ValueOperatorBootstrap {
|
|
282
|
+
// noinspection JSUnusedLocalSymbols
|
|
283
|
+
private constructor() {
|
|
284
|
+
// avoid extend
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
288
|
+
public static of(value: any): IValueOperator {
|
|
289
|
+
return createOperator({
|
|
290
|
+
$value: value,
|
|
291
|
+
$allowMoreAction: true, $allowUseDefault: false, $defaultUsed: false,
|
|
292
|
+
$allowNoParamFuncCall: false
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
297
|
+
public static from(value: any): IValueOperator {
|
|
298
|
+
return ValueOperatorBootstrap.of(value);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
302
|
+
public static with(value: any): IValueOperator {
|
|
303
|
+
return ValueOperatorBootstrap.of(value);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export const ValueOperator: IValueOperatorBoostrap = ValueOperatorBootstrap;
|
|
@@ -1,21 +1,8 @@
|
|
|
1
1
|
import dayjs from 'dayjs';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
DateTime,
|
|
7
|
-
ErrorCodes,
|
|
8
|
-
ExposedUncatchableError,
|
|
9
|
-
Logger,
|
|
10
|
-
UncatchableError
|
|
11
|
-
} from '../utils';
|
|
12
|
-
import {
|
|
13
|
-
PIPELINE_STEP_RETURN_NULL,
|
|
14
|
-
PipelineStepErrorOptions,
|
|
15
|
-
PipelineStepFile,
|
|
16
|
-
PipelineStepFileOptions,
|
|
17
|
-
StepHelpersUtils
|
|
18
|
-
} from './step-helpers-utils';
|
|
2
|
+
import Decimal from 'decimal.js';
|
|
3
|
+
import {all, create, MathJsInstance} from 'mathjs';
|
|
4
|
+
import {Config, DateTime, ErrorCodes, Logger} from '../utils';
|
|
5
|
+
import {IStepHelpersUtils, PipelineStepErrorOptions, StepHelpersUtils} from './step-helpers-utils';
|
|
19
6
|
|
|
20
7
|
export class PipelineStepDateHelper {
|
|
21
8
|
private readonly _dateTimeFormat: string;
|
|
@@ -37,42 +24,19 @@ export class PipelineStepDateHelper {
|
|
|
37
24
|
}
|
|
38
25
|
}
|
|
39
26
|
|
|
40
|
-
export type PipelineStepMathHelper =
|
|
27
|
+
export type PipelineStepMathHelper = MathJsInstance;
|
|
28
|
+
export type PipelineStepDecimalHelper = (value: Decimal.Value) => Decimal;
|
|
41
29
|
|
|
42
|
-
export interface PipelineStepHelpers {
|
|
30
|
+
export interface PipelineStepHelpers extends IStepHelpersUtils {
|
|
43
31
|
$config?: Config;
|
|
44
32
|
$logger?: Logger;
|
|
45
33
|
$date: PipelineStepDateHelper;
|
|
46
34
|
$math: PipelineStepMathHelper;
|
|
47
|
-
$
|
|
48
|
-
|
|
35
|
+
$decimal: PipelineStepDecimalHelper;
|
|
36
|
+
|
|
49
37
|
/** create an exposed uncatchable error*/
|
|
50
38
|
$error: (options: PipelineStepErrorOptions) => never;
|
|
51
39
|
$errorCodes: Readonly<Record<string, string>>;
|
|
52
|
-
$errors: {
|
|
53
|
-
catchable: (options: Omit<PipelineStepErrorOptions, 'status'>) => never;
|
|
54
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
55
|
-
isCatchable: (e: any) => e is CatchableError;
|
|
56
|
-
exposed: (options: PipelineStepErrorOptions) => never;
|
|
57
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
58
|
-
isExposed: (e: any) => e is ExposedUncatchableError;
|
|
59
|
-
uncatchable: (options: Omit<PipelineStepErrorOptions, 'status'>) => never;
|
|
60
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
61
|
-
isUncatchable: (e: any) => e is UncatchableError;
|
|
62
|
-
};
|
|
63
|
-
/** create a file */
|
|
64
|
-
$file: (options: PipelineStepFileOptions) => PipelineStepFile;
|
|
65
|
-
$clearContextData: () => typeof PIPELINE_STEP_RETURN_NULL;
|
|
66
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
67
|
-
isEmpty: (value: any) => boolean;
|
|
68
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
69
|
-
isNotEmpty: (value: any) => boolean;
|
|
70
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
71
|
-
isBlank: (value: any) => boolean;
|
|
72
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
|
-
isNotBlank: (value: any) => boolean;
|
|
74
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
75
|
-
trim: (value: any) => string;
|
|
76
40
|
|
|
77
41
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
78
42
|
[key: string]: any;
|
|
@@ -84,13 +48,15 @@ export const registerToStepHelpers = (helpers: Record<string, any>) => {
|
|
|
84
48
|
RegisteredHelpers.helpers = helpers ?? {};
|
|
85
49
|
};
|
|
86
50
|
|
|
87
|
-
|
|
88
|
-
|
|
51
|
+
const mathjs = create(all, {number: 'BigNumber', precision: 32});
|
|
52
|
+
export const createStepHelpers = (config: Config, logger: Logger): Readonly<PipelineStepHelpers> => {
|
|
53
|
+
const helpers: PipelineStepHelpers = {
|
|
89
54
|
...RegisteredHelpers.helpers,
|
|
90
55
|
$config: config, $logger: logger,
|
|
91
56
|
// date
|
|
92
57
|
$date: new PipelineStepDateHelper(config),
|
|
93
|
-
$math:
|
|
58
|
+
$math: mathjs,
|
|
59
|
+
$decimal: (value: Decimal.Value) => new Decimal(value),
|
|
94
60
|
// nano
|
|
95
61
|
$nano: StepHelpersUtils.$nano, $ascii: StepHelpersUtils.$ascii,
|
|
96
62
|
// errors
|
|
@@ -98,12 +64,20 @@ export const createStepHelpers = (config: Config, logger: Logger): PipelineStepH
|
|
|
98
64
|
$errorCodes: ErrorCodes,
|
|
99
65
|
$errors: StepHelpersUtils.$errors,
|
|
100
66
|
// file
|
|
101
|
-
$file: StepHelpersUtils
|
|
67
|
+
$file: StepHelpersUtils.$file,
|
|
102
68
|
// semaphore
|
|
103
69
|
$clearContextData: StepHelpersUtils.$clearContextData,
|
|
104
70
|
// utilities
|
|
105
71
|
isEmpty: StepHelpersUtils.isEmpty, isNotEmpty: StepHelpersUtils.isNotEmpty,
|
|
106
72
|
isBlank: StepHelpersUtils.isBlank, isNotBlank: StepHelpersUtils.isNotBlank,
|
|
107
|
-
trim: StepHelpersUtils.trim
|
|
73
|
+
trim: StepHelpersUtils.trim,
|
|
74
|
+
touch: StepHelpersUtils.touch,
|
|
75
|
+
noop: StepHelpersUtils.noop, asyncNoop: StepHelpersUtils.asyncNoop
|
|
108
76
|
};
|
|
77
|
+
return new Proxy(helpers, {
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
|
79
|
+
set(_target: PipelineStepHelpers, _p: string | symbol, _value: any, _receiver: any): boolean {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
});
|
|
109
83
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type ValueActionPassed<V> = { test: true, value: V };
|
|
2
|
+
export type ValueActionFailed<V> = { test: false, value: V };
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4
|
+
export type ValueAction<From = any, To = any> = (value?: From) => ValueActionPassed<To> | ValueActionFailed<From>;
|
|
5
|
+
export type RegisteredValueAction = { type: 'func', func: ValueAction }
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
|
+
export type RegisteredValueActionWithParams<F = (...args: Array<any>) => ValueAction> = { type: 'param', func: F };
|
|
8
|
+
export const OBJECT_PROTOTYPE = Object.prototype;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './action-types';
|
|
2
|
+
|
|
3
|
+
export * from './test-any-actions';
|
|
4
|
+
export * from './test-string-actions';
|
|
5
|
+
export * from './test-decimal-actions';
|
|
6
|
+
export * from './testers';
|
|
7
|
+
|
|
8
|
+
export * from './transform-string-actions';
|
|
9
|
+
export * from './transform-decimal-actions';
|
|
10
|
+
export * from './transformers';
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {OBJECT_PROTOTYPE, ValueAction} from './action-types';
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4
|
+
export const isLength = (value: any): boolean => {
|
|
5
|
+
return typeof value === 'number' && value > -1 && value % 1 === 0 && value <= Number.MAX_SAFE_INTEGER;
|
|
6
|
+
};
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
|
+
export const isArrayLike = (value: any): boolean => {
|
|
9
|
+
return value != null && typeof value !== 'function' && isLength(value.length);
|
|
10
|
+
};
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
export const isPrototype = (value: any): boolean => {
|
|
13
|
+
const Ctor = value && value.constructor;
|
|
14
|
+
const proto = (typeof Ctor === 'function' && Ctor.prototype) || OBJECT_PROTOTYPE;
|
|
15
|
+
|
|
16
|
+
return value === proto;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
+
export const isNull: ValueAction<any, null | undefined> = (value?: any) => {
|
|
21
|
+
return value == null
|
|
22
|
+
? {test: true, value: value as null | undefined}
|
|
23
|
+
: {test: false, value};
|
|
24
|
+
};
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
|
+
export const isNotNull: ValueAction<any, NonNullable<any>> = (value?: any) => ({test: !isNull(value).test, value});
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
export const isEmpty: ValueAction = (value?: any) => {
|
|
29
|
+
if (value == null) {
|
|
30
|
+
return {test: true, value: value as null | undefined};
|
|
31
|
+
}
|
|
32
|
+
let length: number | null = null;
|
|
33
|
+
if (isArrayLike(value) && (Array.isArray(value) || typeof value === 'string')) {
|
|
34
|
+
length = value.length;
|
|
35
|
+
} else if (value instanceof Map) {
|
|
36
|
+
length = value.size;
|
|
37
|
+
} else if (value instanceof Set) {
|
|
38
|
+
length = value.size;
|
|
39
|
+
} else if (isPrototype(value)) {
|
|
40
|
+
length = Object.keys(value).length;
|
|
41
|
+
}
|
|
42
|
+
return {test: length === 0, value};
|
|
43
|
+
};
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
+
export const isNotEmpty: ValueAction = (value?: any) => ({test: !isEmpty(value).test, value});
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
47
|
+
export const isBlank: ValueAction<any, null | undefined | string> = (value?: any) => {
|
|
48
|
+
switch (true) {
|
|
49
|
+
case (value == null):
|
|
50
|
+
return {test: true, value: value as null | undefined};
|
|
51
|
+
case (typeof value === 'string' && value.trim().length === 0):
|
|
52
|
+
return {test: true, value: value as string};
|
|
53
|
+
default:
|
|
54
|
+
return {test: false, value};
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
58
|
+
export const isNotBlank: ValueAction = (value?: any) => ({test: !isBlank(value).test, value});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import Decimal from 'decimal.js';
|
|
2
|
+
import {ValueAction} from './action-types';
|
|
3
|
+
import {toDecimal} from './transform-decimal-actions';
|
|
4
|
+
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
|
+
export const isDecimal: ValueAction<any, Decimal> = (value?: any) => {
|
|
7
|
+
const {test, value: decimal} = toDecimal(value);
|
|
8
|
+
return {test, value: test ? decimal : value};
|
|
9
|
+
};
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
|
+
export const isInteger: ValueAction<any, Decimal> = (value?: any) => {
|
|
12
|
+
const {test, value: decimal} = toDecimal(value);
|
|
13
|
+
return (test && decimal.isInteger()) ? {test: true, value: decimal} : {test: false, value};
|
|
14
|
+
};
|
|
15
|
+
export type DecimalInterval = 'closed' | 'c' | 'open' | 'o' | 'left-open' | 'lo' | 'right-open' | 'ro';
|
|
16
|
+
export type DecimalInRangeOptions =
|
|
17
|
+
& { interval?: DecimalInterval }
|
|
18
|
+
& ({ min: Decimal.Value; max?: Decimal.Value; } | { min?: Decimal.Value; max: Decimal.Value; })
|
|
19
|
+
/**
|
|
20
|
+
* @param options.min value of range, might be included or not
|
|
21
|
+
* @param options.max max value of range, might be included or not
|
|
22
|
+
* @param options.interval closed, c -> [min, max]; open, o -> (min, max); left-open, lo -> (min, max]; right-open, ro -> [min, max)
|
|
23
|
+
*/
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
|
+
export const isInRange = (options: DecimalInRangeOptions): ValueAction<any, Decimal> => {
|
|
26
|
+
const {min, max, interval = 'closed'} = options;
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
return (value?: any) => {
|
|
29
|
+
const {test, value: decimal} = toDecimal(value);
|
|
30
|
+
if (!test) {
|
|
31
|
+
return {test: false, value};
|
|
32
|
+
}
|
|
33
|
+
let pass = false;
|
|
34
|
+
switch (interval) {
|
|
35
|
+
case 'open':
|
|
36
|
+
case 'o':
|
|
37
|
+
pass = (min == null || decimal.gt(min)) && (max == null || decimal.lt(max));
|
|
38
|
+
break;
|
|
39
|
+
case 'left-open':
|
|
40
|
+
case 'lo':
|
|
41
|
+
pass = (min == null || decimal.gt(min)) && (max == null || decimal.lte(max));
|
|
42
|
+
break;
|
|
43
|
+
case 'right-open':
|
|
44
|
+
case 'ro':
|
|
45
|
+
pass = (min == null || decimal.gte(min)) && (max == null || decimal.lt(max));
|
|
46
|
+
break;
|
|
47
|
+
case 'closed':
|
|
48
|
+
case 'c':
|
|
49
|
+
default:
|
|
50
|
+
pass = (min == null || decimal.gte(min)) && (max == null || decimal.lte(max));
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
return pass ? {test: true, value: decimal} : {test: false, value};
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
export const isPositive = isInRange({min: 0, interval: 'left-open'});
|
|
57
|
+
export const isNotPositive = isInRange({max: 0});
|
|
58
|
+
export const isNegative = isInRange({max: 0, interval: 'right-open'});
|
|
59
|
+
export const isNotNegative = isInRange({min: 0});
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
61
|
+
export const isZero: ValueAction<any, Decimal> = (value?: any) => {
|
|
62
|
+
const {test, value: decimal} = toDecimal(value);
|
|
63
|
+
return (test && decimal.isZero()) ? {test: true, value: decimal} : {test: false, value};
|
|
64
|
+
};
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
66
|
+
export const isNotZero: ValueAction<any, Decimal> = (value?: any) => {
|
|
67
|
+
const {test, value: decimal} = toDecimal(value);
|
|
68
|
+
return (test && !decimal.isZero()) ? {test: true, value: decimal} : {test: false, value};
|
|
69
|
+
};
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
71
|
+
export const isGreaterThan = (compare: Decimal.Value): ValueAction<any, Decimal> => {
|
|
72
|
+
return isInRange({min: compare, interval: 'left-open'});
|
|
73
|
+
};
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
75
|
+
export const isGreaterThanOrEqual = (compare: Decimal.Value): ValueAction<any, Decimal> => {
|
|
76
|
+
return isInRange({min: compare});
|
|
77
|
+
};
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
79
|
+
export const isLessThan = (compare: Decimal.Value): ValueAction<any, Decimal> => {
|
|
80
|
+
return isInRange({max: compare, interval: 'right-open'});
|
|
81
|
+
};
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
83
|
+
export const isLessThanOrEqual = (compare: Decimal.Value): ValueAction<any, Decimal> => {
|
|
84
|
+
return isInRange({max: compare});
|
|
85
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {ValueAction} from './action-types';
|
|
2
|
+
|
|
3
|
+
export const regexp = (regexp: RegExp): ValueAction => {
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
|
+
return (value?: any) => {
|
|
6
|
+
if (value == null) {
|
|
7
|
+
return {test: false, value};
|
|
8
|
+
}
|
|
9
|
+
const type = typeof value;
|
|
10
|
+
if (['string', 'number', 'bigint'].includes(type)) {
|
|
11
|
+
return {test: regexp.test(value), value};
|
|
12
|
+
}
|
|
13
|
+
return {test: false, value};
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {RegisteredValueAction, RegisteredValueActionWithParams} from './action-types';
|
|
2
|
+
import {isBlank, isEmpty, isNotBlank, isNotEmpty, isNotNull, isNull} from './test-any-actions';
|
|
3
|
+
import {
|
|
4
|
+
isDecimal,
|
|
5
|
+
isGreaterThan,
|
|
6
|
+
isGreaterThanOrEqual,
|
|
7
|
+
isInRange,
|
|
8
|
+
isInteger,
|
|
9
|
+
isLessThan,
|
|
10
|
+
isLessThanOrEqual,
|
|
11
|
+
isNegative,
|
|
12
|
+
isNotNegative,
|
|
13
|
+
isNotPositive,
|
|
14
|
+
isNotZero,
|
|
15
|
+
isPositive,
|
|
16
|
+
isZero
|
|
17
|
+
} from './test-decimal-actions';
|
|
18
|
+
import {regexp} from './test-string-actions';
|
|
19
|
+
|
|
20
|
+
const testers = {
|
|
21
|
+
// any
|
|
22
|
+
isNull: {type: 'func', func: isNull} as RegisteredValueAction,
|
|
23
|
+
isNotNull: {type: 'func', func: isNotNull} as RegisteredValueAction,
|
|
24
|
+
isEmpty: {type: 'func', func: isEmpty} as RegisteredValueAction,
|
|
25
|
+
isNotEmpty: {type: 'func', func: isNotEmpty} as RegisteredValueAction,
|
|
26
|
+
isBlank: {type: 'func', func: isBlank} as RegisteredValueAction,
|
|
27
|
+
isNotBlank: {type: 'func', func: isNotBlank} as RegisteredValueAction,
|
|
28
|
+
// string
|
|
29
|
+
regexp: {type: 'param', func: regexp} as RegisteredValueActionWithParams<typeof regexp>,
|
|
30
|
+
regex: {type: 'param', func: regexp} as RegisteredValueActionWithParams<typeof regexp>,
|
|
31
|
+
matches: {type: 'param', func: regexp} as RegisteredValueActionWithParams<typeof regexp>,
|
|
32
|
+
// decimal, return decimal if test pass
|
|
33
|
+
isNumber: {type: 'func', func: isDecimal} as RegisteredValueAction,
|
|
34
|
+
isDecimal: {type: 'func', func: isDecimal} as RegisteredValueAction,
|
|
35
|
+
isInteger: {type: 'func', func: isInteger} as RegisteredValueAction,
|
|
36
|
+
isInt: {type: 'func', func: isInteger} as RegisteredValueAction,
|
|
37
|
+
isPositive: {type: 'func', func: isPositive} as RegisteredValueAction,
|
|
38
|
+
isNotPositive: {type: 'func', func: isNotPositive} as RegisteredValueAction,
|
|
39
|
+
isNegative: {type: 'func', func: isNegative} as RegisteredValueAction,
|
|
40
|
+
isNotNegative: {type: 'func', func: isNotNegative} as RegisteredValueAction,
|
|
41
|
+
isZero: {type: 'func', func: isZero} as RegisteredValueAction,
|
|
42
|
+
isNotZero: {type: 'func', func: isNotZero} as RegisteredValueAction,
|
|
43
|
+
// decimal with params, return decimal if test pass
|
|
44
|
+
isGreaterThan: {type: 'param', func: isGreaterThan} as RegisteredValueActionWithParams<typeof isGreaterThan>,
|
|
45
|
+
gt: {type: 'param', func: isGreaterThan} as RegisteredValueActionWithParams<typeof isGreaterThan>,
|
|
46
|
+
isGreaterThanOrEqual: {
|
|
47
|
+
type: 'param', func: isGreaterThanOrEqual
|
|
48
|
+
} as RegisteredValueActionWithParams<typeof isGreaterThanOrEqual>,
|
|
49
|
+
gte: {type: 'param', func: isGreaterThanOrEqual} as RegisteredValueActionWithParams<typeof isGreaterThanOrEqual>,
|
|
50
|
+
isLessThan: {type: 'param', func: isLessThan} as RegisteredValueActionWithParams<typeof isLessThan>,
|
|
51
|
+
lt: {type: 'param', func: isLessThan} as RegisteredValueActionWithParams<typeof isLessThan>,
|
|
52
|
+
isLessThanOrEqual: {
|
|
53
|
+
type: 'param', func: isLessThanOrEqual
|
|
54
|
+
} as RegisteredValueActionWithParams<typeof isLessThanOrEqual>,
|
|
55
|
+
lte: {type: 'param', func: isLessThanOrEqual} as RegisteredValueActionWithParams<typeof isLessThanOrEqual>,
|
|
56
|
+
isInRange: {type: 'param', func: isInRange} as RegisteredValueActionWithParams<typeof isInRange>,
|
|
57
|
+
within: {type: 'param', func: isInRange} as RegisteredValueActionWithParams<typeof isInRange>
|
|
58
|
+
};
|
|
59
|
+
export const AllTesters: Readonly<typeof testers> = testers;
|