@rainbow-o23/n1 1.0.49 → 1.0.51

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 CHANGED
@@ -125,7 +125,8 @@ Pipeline steps provide rich function support, and all the following functions or
125
125
  | $logger | Get logger instance. |
126
126
  | $date.now() | Get current datetime, as string. |
127
127
  | $date.dayjs | Get [Day.js](https://day.js.org/). |
128
- | $math | Get [Math.js](https://mathjs.org) |
128
+ | $math | Get [Math.js](https://mathjs.org). |
129
+ | $decimal(value: string \| number \| Decimal.value) | Create a decimal value by [Decimal.js](https://mikemcl.github.io/decimal.js/). |
129
130
  | $nano(size?: number) | Create a nano string. |
130
131
  | $ascii(size?: number) | Create a nano string, only contains ascii characters (0-9, a-z, A-Z, _). |
131
132
  | $error(options: PipelineStepErrorOptions) | Throw an exposed uncatchable error. |
@@ -138,11 +139,14 @@ Pipeline steps provide rich function support, and all the following functions or
138
139
  | $errors.isUncatchable(e: any) | Check if given is an uncatchable error. |
139
140
  | $file(options: PipelineStepFileOptions) => PipelineStepFile | Create a file instance by given options. |
140
141
  | $clearContextData() | If the pipeline step does not return anything or returns null or undefined, the context will continue to be used without any modifications.<br>So returning this semaphore indicates clearing the step content data. |
141
- | isEmpty: (value: any) | Check if given value is empty or not. Empty includes null value, empty string, array and array likes, map, set and object without keys. |
142
- | isNotEmpty: (value: any) | Check if given value is not empty or not. |
143
- | isBlank: (value: any) | Check if given value is blank or not. Blank means null value or a string has no length after trimming. |
144
- | isNotBlank: (value: any) | Check if given value is not blank or not. |
145
- | trim: (value: any) | Try to trim a string, it's null safe, returns empty string when given value is null. Make sure given value is null or a string, otherwise an exception raised. |
142
+ | isEmpty: (value: any) | **@deprecated**, Use `touch` chain instead. |
143
+ | isNotEmpty: (value: any) | **@deprecated**, Use `touch` chain instead. |
144
+ | isBlank: (value: any) | **@deprecated**, Use `touch` chain instead. |
145
+ | isNotBlank: (value: any) | **@deprecated**, Use `touch` chain instead. |
146
+ | trim: (value: any) | **@deprecated**, Use `touch` chain instead. |
147
+ | touch: (value: any): IValueOperator | Operate given value, do test, transform. |
148
+ | noop: () => void | Noop function. |
149
+ | asyncNoop: () => Promise<void> | Async noop function. |
146
150
 
147
151
  For example:
148
152
 
@@ -248,3 +252,37 @@ includes an additional field called `status`, which represents the HTTP response
248
252
  | `format.datetime` | string | YYYY-MM-DD HH:mm:ss | Default datetime format, follows [Day.js](https://day.js.org/) |
249
253
  | `pipeline.debug.log.enabled` | boolean | false | Enable the pipeline debug log. |
250
254
  | `pipeline.performance.log.enabled` | boolean | false | Enable the pipeline performance log, spent time of pipeline and pipeline step.<br>Translation: If `pipeline.debug.log.enabled` is true, this log output will also be enabled. |
255
+
256
+ ## Value Operator
257
+
258
+ `o23/n1` provides a value operator to operate given value, do test, transform. The value operator is a chainable operation. For example,
259
+
260
+ ```ts
261
+ // chainable operation, do test, transform, or default value
262
+ $.touch('abc').isNotBlank().orUseDefault('default').value(); // 'abc'
263
+ $.touch('').isNotBlank.withDefault('default').value(); // 'default'
264
+ $.touch('123').isNumber().toFixed(2).value(); // '123.00'
265
+ $.touch(void 0).isNumber.useDefault(100).value(); // 100
266
+ $.touch(123).isInt.toFixed2.value(); // '123.00'
267
+ $.touch('123.45').within({min: 100, max: 200}).toFixed3().orElse(150).value(); // '123.450'
268
+
269
+ // success and failure callback
270
+ $.touch(123).isPositive // isPositive 123
271
+ .success((value: number) => console.log('isPositive', value))
272
+ .failure((value: number) => console.log('isNotPositive', value));
273
+ $.touch(-123).isPositive // isNotPositive -123
274
+ .success((value: number) => console.log('isPositive', value))
275
+ .failure((value: number) => console.log('isNotPositive', value));
276
+
277
+ // check
278
+ $.touch(123).isPositive.ok(); // true
279
+ $.touch(-123).isPositive.ok(); // false
280
+
281
+ // promisify
282
+ try {
283
+ const v = await $.touch(123).isPositive.toNumber.promise(); // resolved 123
284
+ await VO.of(-123).isPositive.promise(); // rejected, -123 can be caught in catch block
285
+ } catch (v) {
286
+ console.log(v); // -123
287
+ }
288
+ ```
package/index.cjs CHANGED
@@ -1,36 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var dayjs = require('dayjs');
4
- var ArraySupport = require('dayjs/plugin/arraySupport.js');
5
- var CustomParseFormat = require('dayjs/plugin/customParseFormat.js');
6
- var Duration = require('dayjs/plugin/duration.js');
7
- var IsToday = require('dayjs/plugin/isToday.js');
8
- var ObjectSupport = require('dayjs/plugin/objectSupport.js');
9
- var QuarterOfYear = require('dayjs/plugin/quarterOfYear.js');
10
- var RelativeTime = require('dayjs/plugin/relativeTime.js');
11
- var UTC = require('dayjs/plugin/utc.js');
12
- var WeekOfYear = require('dayjs/plugin/weekOfYear.js');
3
+ var n1 = require('@rainbow-n19/n1');
13
4
  var nanoid = require('nanoid');
14
- var math = require('mathjs');
15
-
16
- function _interopNamespaceDefault(e) {
17
- var n = Object.create(null);
18
- if (e) {
19
- Object.keys(e).forEach(function (k) {
20
- if (k !== 'default') {
21
- var d = Object.getOwnPropertyDescriptor(e, k);
22
- Object.defineProperty(n, k, d.get ? d : {
23
- enumerable: true,
24
- get: function () { return e[k]; }
25
- });
26
- }
27
- });
28
- }
29
- n.default = e;
30
- return Object.freeze(n);
31
- }
32
-
33
- var math__namespace = /*#__PURE__*/_interopNamespaceDefault(math);
5
+ var dayjs = require('dayjs');
6
+ var Decimal = require('decimal.js');
7
+ var mathjs$1 = require('mathjs');
34
8
 
35
9
  const ERR_PIPELINE_NOT_FOUND = 'O01-00001';
36
10
  const ERR_TRIM_NON_STRING = 'O01-00002';
@@ -410,28 +384,53 @@ const createConfig = (logger) => {
410
384
  return new Config(logger ?? createLogger());
411
385
  };
412
386
 
413
- dayjs.extend(WeekOfYear);
414
- dayjs.extend(QuarterOfYear);
415
- dayjs.extend(Duration);
416
- dayjs.extend(IsToday);
417
- dayjs.extend(RelativeTime);
418
- dayjs.extend(ArraySupport);
419
- dayjs.extend(ObjectSupport);
420
- dayjs.extend(CustomParseFormat);
421
- dayjs.extend(UTC);
387
+ /******************************************************************************
388
+ Copyright (c) Microsoft Corporation.
389
+
390
+ Permission to use, copy, modify, and/or distribute this software for any
391
+ purpose with or without fee is hereby granted.
392
+
393
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
394
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
395
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
396
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
397
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
398
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
399
+ PERFORMANCE OF THIS SOFTWARE.
400
+ ***************************************************************************** */
401
+ /* global Reflect, Promise, SuppressedError, Symbol */
402
+
403
+
404
+ function __decorate(decorators, target, key, desc) {
405
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
406
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
407
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
408
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
409
+ }
410
+
411
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
412
+ var e = new Error(message);
413
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
414
+ };
415
+
416
+ const StaticImplements = () => {
417
+ return (_constructor) => {
418
+ };
419
+ };
422
420
 
421
+ var StepHelpersUtils_1;
423
422
  const PIPELINE_STEP_FILE_SYMBOL = Symbol();
424
423
  const PIPELINE_STEP_RETURN_NULL = Symbol();
425
- class StepHelpersUtils {
424
+ exports.StepHelpersUtils = class StepHelpersUtils {
425
+ static { StepHelpersUtils_1 = this; }
426
426
  static asciiNanoId = nanoid.customAlphabet('1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_', 32);
427
- static OBJECT_PROTOTYPE = Object.prototype;
428
427
  constructor() {
429
428
  }
430
429
  static $nano(size) {
431
430
  return nanoid.nanoid(size);
432
431
  }
433
432
  static $ascii(size) {
434
- return StepHelpersUtils.asciiNanoId(size);
433
+ return StepHelpersUtils_1.asciiNanoId(size);
435
434
  }
436
435
  static createCatchableError = (options) => {
437
436
  throw new CatchableError(options.code, options.reason);
@@ -452,14 +451,14 @@ class StepHelpersUtils {
452
451
  return e != null && e instanceof UncatchableError;
453
452
  };
454
453
  static $errors = {
455
- catchable: StepHelpersUtils.createCatchableError,
456
- isCatchable: StepHelpersUtils.isCatchableError,
457
- exposed: StepHelpersUtils.createExposedUncatchableError,
458
- isExposed: StepHelpersUtils.isExposedUncatchableError,
459
- uncatchable: StepHelpersUtils.createUncatchableError,
460
- isUncatchable: StepHelpersUtils.isUncatchableError
454
+ catchable: StepHelpersUtils_1.createCatchableError,
455
+ isCatchable: StepHelpersUtils_1.isCatchableError,
456
+ exposed: StepHelpersUtils_1.createExposedUncatchableError,
457
+ isExposed: StepHelpersUtils_1.isExposedUncatchableError,
458
+ uncatchable: StepHelpersUtils_1.createUncatchableError,
459
+ isUncatchable: StepHelpersUtils_1.isUncatchableError
461
460
  };
462
- static createFile(options) {
461
+ static $file(options) {
463
462
  return {
464
463
  $file: PIPELINE_STEP_FILE_SYMBOL,
465
464
  name: options.name, type: options.type,
@@ -470,48 +469,25 @@ class StepHelpersUtils {
470
469
  return PIPELINE_STEP_RETURN_NULL;
471
470
  }
472
471
  static isPrototype(value) {
473
- const Ctor = value && value.constructor;
474
- const proto = (typeof Ctor === 'function' && Ctor.prototype) || StepHelpersUtils.OBJECT_PROTOTYPE;
475
- return value === proto;
472
+ return n1.isPrototype(value);
476
473
  }
477
474
  static isLength(value) {
478
- return typeof value === 'number' && value > -1 && value % 1 === 0 && value <= Number.MAX_SAFE_INTEGER;
475
+ return n1.isLength(value);
479
476
  }
480
477
  static isArrayLike(value) {
481
- return value != null && typeof value !== 'function' && StepHelpersUtils.isLength(value.length);
478
+ return n1.isArrayLike(value);
482
479
  }
483
480
  static isEmpty(value) {
484
- if (value == null) {
485
- return true;
486
- }
487
- if (StepHelpersUtils.isArrayLike(value) && (Array.isArray(value) || typeof value === 'string')) {
488
- return value.length === 0;
489
- }
490
- else if (value instanceof Map) {
491
- return value.size === 0;
492
- }
493
- else if (value instanceof Set) {
494
- return value.size === 0;
495
- }
496
- else if (StepHelpersUtils.isPrototype(value)) {
497
- return Object.keys(value).length === 0;
498
- }
499
- return false;
481
+ return n1.ValueOperator.of(value).isEmpty().ok();
500
482
  }
501
483
  static isNotEmpty(value) {
502
- return !StepHelpersUtils.isEmpty(value);
484
+ return n1.ValueOperator.of(value).isNotEmpty().ok();
503
485
  }
504
486
  static isBlank(value) {
505
- if (value == null) {
506
- return true;
507
- }
508
- if (typeof value !== 'string') {
509
- return false;
510
- }
511
- return value.trim().length === 0;
487
+ return n1.ValueOperator.of(value).isBlank().ok();
512
488
  }
513
489
  static isNotBlank(value) {
514
- return !StepHelpersUtils.isBlank(value);
490
+ return n1.ValueOperator.of(value).isNotBlank().ok();
515
491
  }
516
492
  static trim(value) {
517
493
  if (value == null) {
@@ -522,7 +498,17 @@ class StepHelpersUtils {
522
498
  }
523
499
  throw new UncatchableError(ERR_TRIM_NON_STRING, `Cannot apply trim to non-string object[type=${typeof value}, value=${value}].`);
524
500
  }
525
- }
501
+ static touch(value) {
502
+ return n1.ValueOperator.of(value);
503
+ }
504
+ static noop() {
505
+ }
506
+ static async asyncNoop() {
507
+ }
508
+ };
509
+ exports.StepHelpersUtils = StepHelpersUtils_1 = __decorate([
510
+ StaticImplements()
511
+ ], exports.StepHelpersUtils);
526
512
 
527
513
  class PerformanceExecution {
528
514
  options;
@@ -636,22 +622,31 @@ const RegisteredHelpers = { helpers: {} };
636
622
  const registerToStepHelpers = (helpers) => {
637
623
  RegisteredHelpers.helpers = helpers ?? {};
638
624
  };
625
+ const mathjs = mathjs$1.create(mathjs$1.all, { number: 'BigNumber', precision: 32 });
639
626
  const createStepHelpers = (config, logger) => {
640
- return {
627
+ const helpers = {
641
628
  ...RegisteredHelpers.helpers,
642
629
  $config: config, $logger: logger,
643
630
  $date: new PipelineStepDateHelper(config),
644
- $math: math__namespace,
645
- $nano: StepHelpersUtils.$nano, $ascii: StepHelpersUtils.$ascii,
646
- $error: StepHelpersUtils.createExposedUncatchableError,
631
+ $math: mathjs,
632
+ $decimal: (value) => new Decimal(value),
633
+ $nano: exports.StepHelpersUtils.$nano, $ascii: exports.StepHelpersUtils.$ascii,
634
+ $error: exports.StepHelpersUtils.createExposedUncatchableError,
647
635
  $errorCodes: ErrorCodes,
648
- $errors: StepHelpersUtils.$errors,
649
- $file: StepHelpersUtils.createFile,
650
- $clearContextData: StepHelpersUtils.$clearContextData,
651
- isEmpty: StepHelpersUtils.isEmpty, isNotEmpty: StepHelpersUtils.isNotEmpty,
652
- isBlank: StepHelpersUtils.isBlank, isNotBlank: StepHelpersUtils.isNotBlank,
653
- trim: StepHelpersUtils.trim
636
+ $errors: exports.StepHelpersUtils.$errors,
637
+ $file: exports.StepHelpersUtils.$file,
638
+ $clearContextData: exports.StepHelpersUtils.$clearContextData,
639
+ isEmpty: exports.StepHelpersUtils.isEmpty, isNotEmpty: exports.StepHelpersUtils.isNotEmpty,
640
+ isBlank: exports.StepHelpersUtils.isBlank, isNotBlank: exports.StepHelpersUtils.isNotBlank,
641
+ trim: exports.StepHelpersUtils.trim,
642
+ touch: exports.StepHelpersUtils.touch,
643
+ noop: exports.StepHelpersUtils.noop, asyncNoop: exports.StepHelpersUtils.asyncNoop
654
644
  };
645
+ return new Proxy(helpers, {
646
+ set(_target, _p, _value, _receiver) {
647
+ return false;
648
+ }
649
+ });
655
650
  };
656
651
 
657
652
  class AbstractPipelineStep extends AbstractPipelineExecution {
@@ -811,7 +806,6 @@ exports.PIPELINE_STEP_RETURN_NULL = PIPELINE_STEP_RETURN_NULL;
811
806
  exports.PerformanceExecution = PerformanceExecution;
812
807
  exports.PipelineRepository = PipelineRepository;
813
808
  exports.PipelineStepDateHelper = PipelineStepDateHelper;
814
- exports.StepHelpersUtils = StepHelpersUtils;
815
809
  exports.UncatchableError = UncatchableError;
816
810
  exports.createConfig = createConfig;
817
811
  exports.createLogger = createLogger;
package/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import './lib/envs';
1
2
  export * from './lib/utils';
2
3
  export * from './lib/pipeline';
3
4
  export * from './lib/repo';
package/index.js CHANGED
@@ -1,15 +1,8 @@
1
- import dayjs from 'dayjs';
2
- import ArraySupport from 'dayjs/plugin/arraySupport.js';
3
- import CustomParseFormat from 'dayjs/plugin/customParseFormat.js';
4
- import Duration from 'dayjs/plugin/duration.js';
5
- import IsToday from 'dayjs/plugin/isToday.js';
6
- import ObjectSupport from 'dayjs/plugin/objectSupport.js';
7
- import QuarterOfYear from 'dayjs/plugin/quarterOfYear.js';
8
- import RelativeTime from 'dayjs/plugin/relativeTime.js';
9
- import UTC from 'dayjs/plugin/utc.js';
10
- import WeekOfYear from 'dayjs/plugin/weekOfYear.js';
1
+ import { isPrototype, isLength, isArrayLike, ValueOperator } from '@rainbow-n19/n1';
11
2
  import { customAlphabet, nanoid } from 'nanoid';
12
- import * as math from 'mathjs';
3
+ import dayjs from 'dayjs';
4
+ import Decimal from 'decimal.js';
5
+ import { create, all } from 'mathjs';
13
6
 
14
7
  const ERR_PIPELINE_NOT_FOUND = 'O01-00001';
15
8
  const ERR_TRIM_NON_STRING = 'O01-00002';
@@ -389,28 +382,53 @@ const createConfig = (logger) => {
389
382
  return new Config(logger ?? createLogger());
390
383
  };
391
384
 
392
- dayjs.extend(WeekOfYear);
393
- dayjs.extend(QuarterOfYear);
394
- dayjs.extend(Duration);
395
- dayjs.extend(IsToday);
396
- dayjs.extend(RelativeTime);
397
- dayjs.extend(ArraySupport);
398
- dayjs.extend(ObjectSupport);
399
- dayjs.extend(CustomParseFormat);
400
- dayjs.extend(UTC);
385
+ /******************************************************************************
386
+ Copyright (c) Microsoft Corporation.
387
+
388
+ Permission to use, copy, modify, and/or distribute this software for any
389
+ purpose with or without fee is hereby granted.
390
+
391
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
392
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
393
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
394
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
395
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
396
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
397
+ PERFORMANCE OF THIS SOFTWARE.
398
+ ***************************************************************************** */
399
+ /* global Reflect, Promise, SuppressedError, Symbol */
400
+
401
+
402
+ function __decorate(decorators, target, key, desc) {
403
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
404
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
405
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
406
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
407
+ }
408
+
409
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
410
+ var e = new Error(message);
411
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
412
+ };
401
413
 
414
+ const StaticImplements = () => {
415
+ return (_constructor) => {
416
+ };
417
+ };
418
+
419
+ var StepHelpersUtils_1;
402
420
  const PIPELINE_STEP_FILE_SYMBOL = Symbol();
403
421
  const PIPELINE_STEP_RETURN_NULL = Symbol();
404
- class StepHelpersUtils {
422
+ let StepHelpersUtils = class StepHelpersUtils {
423
+ static { StepHelpersUtils_1 = this; }
405
424
  static asciiNanoId = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_', 32);
406
- static OBJECT_PROTOTYPE = Object.prototype;
407
425
  constructor() {
408
426
  }
409
427
  static $nano(size) {
410
428
  return nanoid(size);
411
429
  }
412
430
  static $ascii(size) {
413
- return StepHelpersUtils.asciiNanoId(size);
431
+ return StepHelpersUtils_1.asciiNanoId(size);
414
432
  }
415
433
  static createCatchableError = (options) => {
416
434
  throw new CatchableError(options.code, options.reason);
@@ -431,14 +449,14 @@ class StepHelpersUtils {
431
449
  return e != null && e instanceof UncatchableError;
432
450
  };
433
451
  static $errors = {
434
- catchable: StepHelpersUtils.createCatchableError,
435
- isCatchable: StepHelpersUtils.isCatchableError,
436
- exposed: StepHelpersUtils.createExposedUncatchableError,
437
- isExposed: StepHelpersUtils.isExposedUncatchableError,
438
- uncatchable: StepHelpersUtils.createUncatchableError,
439
- isUncatchable: StepHelpersUtils.isUncatchableError
452
+ catchable: StepHelpersUtils_1.createCatchableError,
453
+ isCatchable: StepHelpersUtils_1.isCatchableError,
454
+ exposed: StepHelpersUtils_1.createExposedUncatchableError,
455
+ isExposed: StepHelpersUtils_1.isExposedUncatchableError,
456
+ uncatchable: StepHelpersUtils_1.createUncatchableError,
457
+ isUncatchable: StepHelpersUtils_1.isUncatchableError
440
458
  };
441
- static createFile(options) {
459
+ static $file(options) {
442
460
  return {
443
461
  $file: PIPELINE_STEP_FILE_SYMBOL,
444
462
  name: options.name, type: options.type,
@@ -449,48 +467,25 @@ class StepHelpersUtils {
449
467
  return PIPELINE_STEP_RETURN_NULL;
450
468
  }
451
469
  static isPrototype(value) {
452
- const Ctor = value && value.constructor;
453
- const proto = (typeof Ctor === 'function' && Ctor.prototype) || StepHelpersUtils.OBJECT_PROTOTYPE;
454
- return value === proto;
470
+ return isPrototype(value);
455
471
  }
456
472
  static isLength(value) {
457
- return typeof value === 'number' && value > -1 && value % 1 === 0 && value <= Number.MAX_SAFE_INTEGER;
473
+ return isLength(value);
458
474
  }
459
475
  static isArrayLike(value) {
460
- return value != null && typeof value !== 'function' && StepHelpersUtils.isLength(value.length);
476
+ return isArrayLike(value);
461
477
  }
462
478
  static isEmpty(value) {
463
- if (value == null) {
464
- return true;
465
- }
466
- if (StepHelpersUtils.isArrayLike(value) && (Array.isArray(value) || typeof value === 'string')) {
467
- return value.length === 0;
468
- }
469
- else if (value instanceof Map) {
470
- return value.size === 0;
471
- }
472
- else if (value instanceof Set) {
473
- return value.size === 0;
474
- }
475
- else if (StepHelpersUtils.isPrototype(value)) {
476
- return Object.keys(value).length === 0;
477
- }
478
- return false;
479
+ return ValueOperator.of(value).isEmpty().ok();
479
480
  }
480
481
  static isNotEmpty(value) {
481
- return !StepHelpersUtils.isEmpty(value);
482
+ return ValueOperator.of(value).isNotEmpty().ok();
482
483
  }
483
484
  static isBlank(value) {
484
- if (value == null) {
485
- return true;
486
- }
487
- if (typeof value !== 'string') {
488
- return false;
489
- }
490
- return value.trim().length === 0;
485
+ return ValueOperator.of(value).isBlank().ok();
491
486
  }
492
487
  static isNotBlank(value) {
493
- return !StepHelpersUtils.isBlank(value);
488
+ return ValueOperator.of(value).isNotBlank().ok();
494
489
  }
495
490
  static trim(value) {
496
491
  if (value == null) {
@@ -501,7 +496,17 @@ class StepHelpersUtils {
501
496
  }
502
497
  throw new UncatchableError(ERR_TRIM_NON_STRING, `Cannot apply trim to non-string object[type=${typeof value}, value=${value}].`);
503
498
  }
504
- }
499
+ static touch(value) {
500
+ return ValueOperator.of(value);
501
+ }
502
+ static noop() {
503
+ }
504
+ static async asyncNoop() {
505
+ }
506
+ };
507
+ StepHelpersUtils = StepHelpersUtils_1 = __decorate([
508
+ StaticImplements()
509
+ ], StepHelpersUtils);
505
510
 
506
511
  class PerformanceExecution {
507
512
  options;
@@ -615,22 +620,31 @@ const RegisteredHelpers = { helpers: {} };
615
620
  const registerToStepHelpers = (helpers) => {
616
621
  RegisteredHelpers.helpers = helpers ?? {};
617
622
  };
623
+ const mathjs = create(all, { number: 'BigNumber', precision: 32 });
618
624
  const createStepHelpers = (config, logger) => {
619
- return {
625
+ const helpers = {
620
626
  ...RegisteredHelpers.helpers,
621
627
  $config: config, $logger: logger,
622
628
  $date: new PipelineStepDateHelper(config),
623
- $math: math,
629
+ $math: mathjs,
630
+ $decimal: (value) => new Decimal(value),
624
631
  $nano: StepHelpersUtils.$nano, $ascii: StepHelpersUtils.$ascii,
625
632
  $error: StepHelpersUtils.createExposedUncatchableError,
626
633
  $errorCodes: ErrorCodes,
627
634
  $errors: StepHelpersUtils.$errors,
628
- $file: StepHelpersUtils.createFile,
635
+ $file: StepHelpersUtils.$file,
629
636
  $clearContextData: StepHelpersUtils.$clearContextData,
630
637
  isEmpty: StepHelpersUtils.isEmpty, isNotEmpty: StepHelpersUtils.isNotEmpty,
631
638
  isBlank: StepHelpersUtils.isBlank, isNotBlank: StepHelpersUtils.isNotBlank,
632
- trim: StepHelpersUtils.trim
639
+ trim: StepHelpersUtils.trim,
640
+ touch: StepHelpersUtils.touch,
641
+ noop: StepHelpersUtils.noop, asyncNoop: StepHelpersUtils.asyncNoop
633
642
  };
643
+ return new Proxy(helpers, {
644
+ set(_target, _p, _value, _receiver) {
645
+ return false;
646
+ }
647
+ });
634
648
  };
635
649
 
636
650
  class AbstractPipelineStep extends AbstractPipelineExecution {
package/lib/envs.d.ts ADDED
@@ -0,0 +1 @@
1
+ import '@rainbow-n19/n1';
@@ -1,4 +1,3 @@
1
- export * from './envs';
2
1
  export * from './pipeline-execution';
3
2
  export * from './pipeline-step';
4
3
  export * from './pipeline';
@@ -1,5 +1,6 @@
1
+ import { IValueOperator } from '@rainbow-n19/n1';
1
2
  import { CatchableError, ExposedUncatchableError, UncatchableError } from '../utils';
2
- import { PipelineStepHelpers } from './index';
3
+ import { PipelineStepHelpers } from './step-helpers';
3
4
  export interface PipelineStepErrorOptions {
4
5
  status: number;
5
6
  code: string;
@@ -18,9 +19,30 @@ export interface PipelineStepFile {
18
19
  type?: string;
19
20
  content: Buffer;
20
21
  }
22
+ export interface IStepHelpersUtils {
23
+ $nano: (size?: number) => string;
24
+ $ascii: (size?: number) => string;
25
+ $errors: {
26
+ catchable: (options: Omit<PipelineStepErrorOptions, 'status'>) => never;
27
+ isCatchable: (e: any) => e is CatchableError;
28
+ exposed: (options: PipelineStepErrorOptions) => never;
29
+ isExposed: (e: any) => e is ExposedUncatchableError;
30
+ uncatchable: (options: Omit<PipelineStepErrorOptions, 'status'>) => never;
31
+ isUncatchable: (e: any) => e is UncatchableError;
32
+ };
33
+ $file: (options: PipelineStepFileOptions) => PipelineStepFile;
34
+ $clearContextData: () => typeof PIPELINE_STEP_RETURN_NULL;
35
+ isEmpty: (value: any) => boolean;
36
+ isNotEmpty: (value: any) => boolean;
37
+ isBlank: (value: any) => boolean;
38
+ isNotBlank: (value: any) => boolean;
39
+ trim: (value: any) => string;
40
+ touch: (value: any) => IValueOperator;
41
+ noop: (value: any) => void;
42
+ asyncNoop: (value: any) => Promise<void>;
43
+ }
21
44
  export declare class StepHelpersUtils {
22
45
  private static asciiNanoId;
23
- private static OBJECT_PROTOTYPE;
24
46
  private constructor();
25
47
  static $nano(size?: number): string;
26
48
  static $ascii(size?: number): string;
@@ -31,7 +53,7 @@ export declare class StepHelpersUtils {
31
53
  static createUncatchableError: (options: Omit<PipelineStepErrorOptions, "status">) => never;
32
54
  static isUncatchableError: (e: any) => e is UncatchableError;
33
55
  static readonly $errors: PipelineStepHelpers['$errors'];
34
- static createFile(options: PipelineStepFileOptions): PipelineStepFile;
56
+ static $file(options: PipelineStepFileOptions): PipelineStepFile;
35
57
  static $clearContextData(): typeof PIPELINE_STEP_RETURN_NULL;
36
58
  static isPrototype(value: any): boolean;
37
59
  static isLength(value: any): boolean;
@@ -41,4 +63,7 @@ export declare class StepHelpersUtils {
41
63
  static isBlank(value: any): boolean;
42
64
  static isNotBlank(value: any): boolean;
43
65
  static trim(value: any): string;
66
+ static touch(value: any): IValueOperator;
67
+ static noop(): void;
68
+ static asyncNoop(): Promise<void>;
44
69
  }
@@ -1,7 +1,8 @@
1
1
  import dayjs from 'dayjs';
2
- import * as math from 'mathjs';
3
- import { CatchableError, Config, DateTime, ExposedUncatchableError, Logger, UncatchableError } from '../utils';
4
- import { PIPELINE_STEP_RETURN_NULL, PipelineStepErrorOptions, PipelineStepFile, PipelineStepFileOptions } from './step-helpers-utils';
2
+ import Decimal from 'decimal.js';
3
+ import { MathJsInstance } from 'mathjs';
4
+ import { Config, DateTime, Logger } from '../utils';
5
+ import { IStepHelpersUtils, PipelineStepErrorOptions } from './step-helpers-utils';
5
6
  export declare class PipelineStepDateHelper {
6
7
  private readonly _dateTimeFormat;
7
8
  constructor(config: Config);
@@ -9,32 +10,17 @@ export declare class PipelineStepDateHelper {
9
10
  now(): DateTime;
10
11
  get dayjs(): typeof dayjs;
11
12
  }
12
- export type PipelineStepMathHelper = typeof math;
13
- export interface PipelineStepHelpers {
13
+ export type PipelineStepMathHelper = MathJsInstance;
14
+ export type PipelineStepDecimalHelper = (value: Decimal.Value) => Decimal;
15
+ export interface PipelineStepHelpers extends IStepHelpersUtils {
14
16
  $config?: Config;
15
17
  $logger?: Logger;
16
18
  $date: PipelineStepDateHelper;
17
19
  $math: PipelineStepMathHelper;
18
- $nano: (size?: number) => string;
19
- $ascii: (size?: number) => string;
20
+ $decimal: PipelineStepDecimalHelper;
20
21
  $error: (options: PipelineStepErrorOptions) => never;
21
22
  $errorCodes: Readonly<Record<string, string>>;
22
- $errors: {
23
- catchable: (options: Omit<PipelineStepErrorOptions, 'status'>) => never;
24
- isCatchable: (e: any) => e is CatchableError;
25
- exposed: (options: PipelineStepErrorOptions) => never;
26
- isExposed: (e: any) => e is ExposedUncatchableError;
27
- uncatchable: (options: Omit<PipelineStepErrorOptions, 'status'>) => never;
28
- isUncatchable: (e: any) => e is UncatchableError;
29
- };
30
- $file: (options: PipelineStepFileOptions) => PipelineStepFile;
31
- $clearContextData: () => typeof PIPELINE_STEP_RETURN_NULL;
32
- isEmpty: (value: any) => boolean;
33
- isNotEmpty: (value: any) => boolean;
34
- isBlank: (value: any) => boolean;
35
- isNotBlank: (value: any) => boolean;
36
- trim: (value: any) => string;
37
23
  [key: string]: any;
38
24
  }
39
25
  export declare const registerToStepHelpers: (helpers: Record<string, any>) => void;
40
- export declare const createStepHelpers: (config: Config, logger: Logger) => PipelineStepHelpers;
26
+ export declare const createStepHelpers: (config: Config, logger: Logger) => Readonly<PipelineStepHelpers>;
@@ -0,0 +1 @@
1
+ export declare const StaticImplements: <T>() => <U extends T>(_constructor: U) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rainbow-o23/n1",
3
- "version": "1.0.49",
3
+ "version": "1.0.51",
4
4
  "description": "o23 interfaces",
5
5
  "main": "index.cjs",
6
6
  "module": "index.js",
@@ -9,7 +9,7 @@
9
9
  "scripts": {
10
10
  "build": "rollup -c",
11
11
  "build:ci": "rollup -c rollup.config.ci.js",
12
- "test": "echo \"Error: no test specified\" && exit 1"
12
+ "test": "jest"
13
13
  },
14
14
  "repository": {
15
15
  "type": "git",
@@ -21,7 +21,9 @@
21
21
  "url": "https://github.com/InsureMO/rainbow-o23/issues"
22
22
  },
23
23
  "dependencies": {
24
+ "@rainbow-n19/n1": "latest",
24
25
  "dayjs": "^1.11.13",
26
+ "decimal.js": "^10.4.3",
25
27
  "mathjs": "^13.2.1",
26
28
  "nanoid": "3.3.7"
27
29
  },
@@ -37,11 +39,32 @@
37
39
  "@typescript-eslint/parser": "^8.13.0",
38
40
  "eslint": "^9.8.0",
39
41
  "rollup": "^3.29.5",
40
- "rollup-plugin-tslint": "^0.2.2",
41
42
  "rollup-plugin-typescript2": "^0.34.1",
42
43
  "tslib": "^2.4.1",
43
44
  "typescript": "5.5.4"
44
45
  },
46
+ "jest": {
47
+ "moduleFileExtensions": [
48
+ "js",
49
+ "json",
50
+ "ts"
51
+ ],
52
+ "testRegex": "(/test/.*\\.(test|spec))\\.[tj]sx?$",
53
+ "testPathIgnorePatterns": [
54
+ "/node_modules/"
55
+ ],
56
+ "transform": {
57
+ "^.+\\.(t|j)s$": "ts-jest"
58
+ },
59
+ "collectCoverageFrom": [
60
+ "src/**/*.(t|j)s"
61
+ ],
62
+ "coverageDirectory": "./coverage",
63
+ "coverageReporters": [
64
+ "html"
65
+ ],
66
+ "testEnvironment": "node"
67
+ },
45
68
  "volta": {
46
69
  "extends": "../package.json"
47
70
  }
@@ -18,13 +18,15 @@ export const buildConfig = (lint) => {
18
18
  ],
19
19
  plugins: [
20
20
  lint ? eslint({exclude: ['../node_modules/**', 'node_modules/**']}) : null,
21
- // lint ? tslint({exclude: ['../node_modules/**', 'node_modules/**']}) : null,
22
21
  typescript({clean: true}),
23
22
  babel({babelHelpers: 'bundled'})
24
23
  ].filter(x => x != null),
25
24
  external(id) {
26
25
  return ["dayjs/plugin/"].some(scope => id.startsWith(scope))
27
- || ['nanoid', 'dayjs', 'mathjs'].includes(id);
26
+ || [
27
+ '@rainbow-n19/n1',
28
+ 'nanoid', 'dayjs', 'mathjs', 'decimal.js'
29
+ ].includes(id);
28
30
  }
29
31
  };
30
32
  };
package/src/index.ts CHANGED
@@ -1,3 +1,6 @@
1
+ // make sure it is the first one
2
+ import './lib/envs';
3
+
1
4
  export * from './lib/utils';
2
5
 
3
6
  export * from './lib/pipeline';
@@ -0,0 +1,2 @@
1
+ // initial dayjs and decimal.js
2
+ import '@rainbow-n19/n1';
@@ -1,4 +1,3 @@
1
- export * from './envs';
2
1
  export * from './pipeline-execution';
3
2
  export * from './pipeline-step';
4
3
  export * from './pipeline';
@@ -1,6 +1,8 @@
1
+ import {isArrayLike, isLength, isPrototype, IValueOperator, ValueOperator} from '@rainbow-n19/n1';
1
2
  import {customAlphabet, nanoid} from 'nanoid';
2
3
  import {CatchableError, ERR_TRIM_NON_STRING, ExposedUncatchableError, UncatchableError} from '../utils';
3
- import {PipelineStepHelpers} from './index';
4
+ import {PipelineStepHelpers} from './step-helpers';
5
+ import {StaticImplements} from './types';
4
6
 
5
7
  export interface PipelineStepErrorOptions {
6
8
  // exactly same as http status
@@ -25,10 +27,51 @@ export interface PipelineStepFile {
25
27
  content: Buffer;
26
28
  }
27
29
 
30
+ export interface IStepHelpersUtils {
31
+ $nano: (size?: number) => string;
32
+ $ascii: (size?: number) => string;
33
+ $errors: {
34
+ catchable: (options: Omit<PipelineStepErrorOptions, 'status'>) => never;
35
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
+ isCatchable: (e: any) => e is CatchableError;
37
+ exposed: (options: PipelineStepErrorOptions) => never;
38
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
+ isExposed: (e: any) => e is ExposedUncatchableError;
40
+ uncatchable: (options: Omit<PipelineStepErrorOptions, 'status'>) => never;
41
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
+ isUncatchable: (e: any) => e is UncatchableError;
43
+ };
44
+ /** create a file */
45
+ $file: (options: PipelineStepFileOptions) => PipelineStepFile;
46
+ $clearContextData: () => typeof PIPELINE_STEP_RETURN_NULL;
47
+ /** @deprecated */
48
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
49
+ isEmpty: (value: any) => boolean;
50
+ /** @deprecated */
51
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
52
+ isNotEmpty: (value: any) => boolean;
53
+ /** @deprecated */
54
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
+ isBlank: (value: any) => boolean;
56
+ /** @deprecated */
57
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
58
+ isNotBlank: (value: any) => boolean;
59
+ /** @deprecated */
60
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
+ trim: (value: any) => string;
62
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
63
+ touch: (value: any) => IValueOperator;
64
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
65
+ noop: (value: any) => void;
66
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
67
+ asyncNoop: (value: any) => Promise<void>;
68
+ }
69
+
70
+ @StaticImplements<IStepHelpersUtils>()
28
71
  export class StepHelpersUtils {
29
72
  private static asciiNanoId = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_', 32);
30
- private static OBJECT_PROTOTYPE = Object.prototype;
31
73
 
74
+ // noinspection JSUnusedLocalSymbols
32
75
  private constructor() {
33
76
  // avoid extend
34
77
  }
@@ -75,7 +118,7 @@ export class StepHelpersUtils {
75
118
  };
76
119
 
77
120
  // file
78
- public static createFile(options: PipelineStepFileOptions): PipelineStepFile {
121
+ public static $file(options: PipelineStepFileOptions): PipelineStepFile {
79
122
  return {
80
123
  $file: PIPELINE_STEP_FILE_SYMBOL,
81
124
  name: options.name, type: options.type,
@@ -91,61 +134,71 @@ export class StepHelpersUtils {
91
134
  // utils
92
135
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
93
136
  public static isPrototype(value: any): boolean {
94
- const Ctor = value && value.constructor;
95
- const proto = (typeof Ctor === 'function' && Ctor.prototype) || StepHelpersUtils.OBJECT_PROTOTYPE;
96
-
97
- return value === proto;
137
+ return isPrototype(value);
98
138
  }
99
139
 
140
+ /**
141
+ * return true when given value is an integral number, and greater than or equals 0
142
+ */
100
143
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
101
144
  public static isLength(value: any): boolean {
102
- return typeof value === 'number' && value > -1 && value % 1 === 0 && value <= Number.MAX_SAFE_INTEGER;
145
+ return isLength(value);
103
146
  }
104
147
 
148
+ /**
149
+ * return true when given value is not null, not undefined, not function and has length property.
150
+ */
105
151
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
106
152
  public static isArrayLike(value: any): boolean {
107
- return value != null && typeof value !== 'function' && StepHelpersUtils.isLength(value.length);
153
+ return isArrayLike(value);
108
154
  }
109
155
 
156
+ /**
157
+ * return true when given value
158
+ * 1. is null or undefined
159
+ * 2. is array like, array or string, and length is 0
160
+ * 3. is map, and size is 0
161
+ * 4. is set, and size is 0
162
+ * 5. is object, and has no own enumerable property
163
+ * @deprecated use {@link touch} instead
164
+ */
110
165
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
111
166
  public static isEmpty(value: any): boolean {
112
- if (value == null) {
113
- return true;
114
- }
115
- if (StepHelpersUtils.isArrayLike(value) && (Array.isArray(value) || typeof value === 'string')) {
116
- return value.length === 0;
117
- } else if (value instanceof Map) {
118
- return value.size === 0;
119
- } else if (value instanceof Set) {
120
- return value.size === 0;
121
- } else if (StepHelpersUtils.isPrototype(value)) {
122
- return Object.keys(value).length === 0;
123
- }
124
-
125
- return false;
167
+ return ValueOperator.of(value).isEmpty().ok();
126
168
  }
127
169
 
170
+ /**
171
+ * return true when given value is not {@link isEmpty}
172
+ * @deprecated use {@link touch} instead
173
+ */
128
174
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
129
175
  public static isNotEmpty(value: any): boolean {
130
- return !StepHelpersUtils.isEmpty(value);
176
+ return ValueOperator.of(value).isNotEmpty().ok();
131
177
  }
132
178
 
179
+ /**
180
+ * return true when given value is null, undefined or blank string.
181
+ * @deprecated use {@link touch} instead
182
+ */
133
183
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
134
184
  public static isBlank(value: any): boolean {
135
- if (value == null) {
136
- return true;
137
- }
138
- if (typeof value !== 'string') {
139
- return false;
140
- }
141
- return value.trim().length === 0;
185
+ return ValueOperator.of(value).isBlank().ok();
142
186
  }
143
187
 
188
+ /**
189
+ * return true when given value is not {@link isBlank}
190
+ * @deprecated use {@link touch} instead
191
+ */
144
192
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
145
193
  public static isNotBlank(value: any): boolean {
146
- return !StepHelpersUtils.isBlank(value);
194
+ return ValueOperator.of(value).isNotBlank().ok();
147
195
  }
148
196
 
197
+ /**
198
+ * return trimmed string, or empty string when given value is null or undefined.
199
+ * or throw exception when given value is not null, not undefined, and not a string
200
+ * @deprecated use {@link touch} instead
201
+ */
149
202
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
150
203
  public static trim(value: any): string {
151
204
  if (value == null) {
@@ -156,4 +209,23 @@ export class StepHelpersUtils {
156
209
  }
157
210
  throw new UncatchableError(ERR_TRIM_NON_STRING, `Cannot apply trim to non-string object[type=${typeof value}, value=${value}].`);
158
211
  }
212
+
213
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
214
+ public static touch(value: any): IValueOperator {
215
+ return ValueOperator.of(value);
216
+ }
217
+
218
+ /**
219
+ * do nothing
220
+ */
221
+ public static noop(): void {
222
+ // do nothing
223
+ }
224
+
225
+ /**
226
+ * do nothing
227
+ */
228
+ public static async asyncNoop(): Promise<void> {
229
+ // do nothing
230
+ }
159
231
  }
@@ -1,21 +1,8 @@
1
1
  import dayjs from 'dayjs';
2
- import * as math from 'mathjs';
3
- import {
4
- CatchableError,
5
- Config,
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 = typeof math;
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
- $nano: (size?: number) => string;
48
- $ascii: (size?: number) => string;
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
- export const createStepHelpers = (config: Config, logger: Logger): PipelineStepHelpers => {
88
- return {
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: 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.createFile,
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,7 @@
1
+ export const StaticImplements = <T>() => {
2
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
3
+ return <U extends T>(_constructor: U) => {
4
+ // since only one static method, no need to execute constructor anymore
5
+ // constructor;
6
+ };
7
+ };
@@ -0,0 +1,55 @@
1
+ // noinspection ES6PreferShortImport
2
+
3
+ import Decimal from 'decimal.js';
4
+ import * as math from 'mathjs';
5
+ import {ValueOperator as VO} from '../src/lib/pipeline/step-helpers-value-operator';
6
+
7
+ describe('Value test chain', () => {
8
+ test('Test 1', async () => {
9
+ expect(VO.from('abc').isNotBlank().orUseDefault('default').value()).toEqual('abc');
10
+ expect(VO.from('').isNotBlank.withDefault('default').value()).toEqual('default');
11
+ expect(VO.from('123').isNumber().toFixed(2).value()).toEqual('123.00');
12
+ expect(VO.from(void 0).isNumber.useDefault(100).value()).toEqual(100);
13
+ expect(VO.with(123).isInt.toFixed2.value()).toEqual('123.00');
14
+ expect(VO.of('123.45').within({min: 100, max: 200}).toFixed3().orElse(150).value()).toEqual('123.450');
15
+ console.log({
16
+ 'math: number, 5.0000000000000001': math.isInteger(5.0000000000000001),
17
+ 'math: string, 5.0000000000000001': math.isInteger('5.0000000000000001' as any),
18
+ 'decimal: number, 5.0000000000000001': new Decimal(5.0000000000000001).isInteger(),
19
+ 'decimal: string, 5.0000000000000001': new Decimal('5.0000000000000001').isInteger(),
20
+ 'math: 0.1 + 0.2': math.chain(0.1).add(0.2).done(),
21
+ 'math: add("0.1 + 0.2")': math.evaluate('0.1 + 0.2'),
22
+ 'decimal: 0.1 + 0.2': new Decimal(0.1).add(0.2).toNumber()
23
+ });
24
+
25
+ VO.of(123).isPositive
26
+ .success((value: number) => console.log('isPositive', value))
27
+ .failure((value: number) => console.log('isNotPositive', value));
28
+ VO.of(-123).isPositive
29
+ .success((value: number) => console.log('isPositive', value))
30
+ .failure((value: number) => console.log('isNotPositive', value));
31
+ expect(VO.of(123).isPositive.ok()).toEqual(true);
32
+ expect(VO.of(-123).isPositive.ok()).toEqual(false);
33
+ try {
34
+ const v = await VO.of(123).isPositive.toNumber.promise();
35
+ expect(v).toEqual(123);
36
+ await VO.of(-123).isPositive.promise();
37
+ } catch (v) {
38
+ expect(v).toEqual(-123);
39
+ }
40
+
41
+ // console.log(new Decimal({} as any).isInteger());
42
+ interface AskImportConfigRequest {
43
+ type?: string;
44
+ pageSize?: number;
45
+ pageNumber?: number;
46
+ }
47
+
48
+ const {type, pageSize, pageNumber} = {} as AskImportConfigRequest;
49
+ const criteria: AskImportConfigRequest = {type};
50
+ criteria.pageSize = VO.of(pageSize).isPositive.toFixed0.toNumber.orUseDefault(20).value();
51
+ criteria.pageNumber = VO.of(pageNumber).isPositive.toFixed0.toNumber.orUseDefault(1).value();
52
+ });
53
+
54
+ afterAll((done) => done());
55
+ });
@@ -1 +0,0 @@
1
- export {};
@@ -1,20 +0,0 @@
1
- import dayjs from 'dayjs';
2
- import ArraySupport from 'dayjs/plugin/arraySupport.js';
3
- import CustomParseFormat from 'dayjs/plugin/customParseFormat.js';
4
- import Duration from 'dayjs/plugin/duration.js';
5
- import IsToday from 'dayjs/plugin/isToday.js';
6
- import ObjectSupport from 'dayjs/plugin/objectSupport.js';
7
- import QuarterOfYear from 'dayjs/plugin/quarterOfYear.js';
8
- import RelativeTime from 'dayjs/plugin/relativeTime.js';
9
- import UTC from 'dayjs/plugin/utc.js';
10
- import WeekOfYear from 'dayjs/plugin/weekOfYear.js';
11
-
12
- dayjs.extend(WeekOfYear);
13
- dayjs.extend(QuarterOfYear);
14
- dayjs.extend(Duration);
15
- dayjs.extend(IsToday);
16
- dayjs.extend(RelativeTime);
17
- dayjs.extend(ArraySupport);
18
- dayjs.extend(ObjectSupport);
19
- dayjs.extend(CustomParseFormat);
20
- dayjs.extend(UTC);