@ti-engine/core 1.3.3 → 1.3.6
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/CHANGELOG.md +23 -0
- package/README.md +106 -95
- package/bin/localization/labels.json +101 -98
- package/components/exchange/message-dispatcher.js +4 -4
- package/components/exchange/message-tracer.js +4 -3
- package/components/service-caller.js +1 -1
- package/components/service-consumer.js +2 -2
- package/components/service-instance.js +3 -3
- package/components/service-provider.js +2 -2
- package/integrations/redis-integration.js +11 -10
- package/package.json +3 -4
- package/utils/exceptions.js +117 -22
- package/utils/logger.js +1 -1
- package/utils/tools.js +142 -96
package/utils/tools.js
CHANGED
|
@@ -7,19 +7,21 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
const _ = require( "lodash" );
|
|
10
|
-
const fs = require( "fs-extra" );
|
|
11
10
|
const crypto = require( "node:crypto" );
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
13
|
* @typedef {Object} TiEnumValue
|
|
15
14
|
* @property {number|string} value
|
|
16
15
|
* @property {string} name
|
|
17
|
-
* @property {string} description
|
|
16
|
+
* @property {string} [description]
|
|
18
17
|
*/
|
|
19
18
|
|
|
20
19
|
/**
|
|
21
20
|
* @typedef {Object} TiEnum
|
|
22
21
|
* @property {Object.<number|string,TiEnumValue>} properties
|
|
22
|
+
* @property {function( (number|string), [string] ): (string|undefined)} name
|
|
23
|
+
* @property {function( (number|string), [string] ): (string|undefined)} description
|
|
24
|
+
* @property {function( (number|string) ): boolean} contains
|
|
23
25
|
*/
|
|
24
26
|
|
|
25
27
|
/**
|
|
@@ -38,38 +40,113 @@ module.exports.getUUID = () => {
|
|
|
38
40
|
*
|
|
39
41
|
* @method
|
|
40
42
|
* @param {Object} seed
|
|
41
|
-
* @returns {Object}
|
|
43
|
+
* @returns {Object} This is a {@link TiEnum} object. Setting the proper reference here would unfortunately break IDE support.
|
|
42
44
|
* @public
|
|
43
45
|
*/
|
|
44
46
|
module.exports.enum = ( seed ) => {
|
|
45
|
-
|
|
47
|
+
const enumObject = Object.create( null );
|
|
48
|
+
const properties = Object.create( null );
|
|
49
|
+
const reserved = new Set( [ "properties", "name", "description", "contains", "__proto__", "prototype", "constructor" ] );
|
|
46
50
|
|
|
47
51
|
_.forOwn( seed, ( value, key ) => {
|
|
48
|
-
if (
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
if ( !reserved.has( key ) ) {
|
|
53
|
+
if ( Array.isArray( value ) ) {
|
|
54
|
+
enumObject[ key ] = value[ 0 ];
|
|
55
|
+
properties[ value[ 0 ] ] = {
|
|
56
|
+
value: value[ 0 ],
|
|
57
|
+
name: value[ 1 ],
|
|
58
|
+
description: value[ 2 ]
|
|
59
|
+
};
|
|
60
|
+
} else {
|
|
61
|
+
enumObject[ key ] = value;
|
|
62
|
+
properties[ value ] = {
|
|
63
|
+
value: value,
|
|
64
|
+
name: key
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
} );
|
|
69
|
+
Object.values( properties ).forEach( Object.freeze );
|
|
70
|
+
Object.freeze( properties );
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Used to get the name of an {@link TiEnumValue} if such value exists.
|
|
74
|
+
*
|
|
75
|
+
* @method
|
|
76
|
+
* @param {number|string} value
|
|
77
|
+
* @param {string} [placeholder=undefined] If provided it will be returned when the enum value does not have a name defined.
|
|
78
|
+
* @returns {string|undefined}
|
|
79
|
+
* @public
|
|
80
|
+
*/
|
|
81
|
+
const name = ( value, placeholder = undefined ) => {
|
|
82
|
+
return ( properties[ value ] ) ? properties[ value ].name : placeholder;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Used to get the description of an {@link TiEnumValue} if such value exists.
|
|
87
|
+
*
|
|
88
|
+
* @method
|
|
89
|
+
* @param {number|string} value
|
|
90
|
+
* @param {string} [placeholder=undefined] If provided it will be returned when the enum value does not have a description defined.
|
|
91
|
+
* @returns {string|undefined}
|
|
92
|
+
* @public
|
|
93
|
+
*/
|
|
94
|
+
const description = ( value, placeholder = undefined ) => {
|
|
95
|
+
if ( !properties[ value ] ) {
|
|
96
|
+
return placeholder;
|
|
55
97
|
} else {
|
|
56
|
-
properties[ value ]
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
98
|
+
return ( properties[ value ].description !== undefined ) ? properties[ value ].description : placeholder;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Used to check if the provided value is contained in the provided {@link TiEnum} list.
|
|
104
|
+
*
|
|
105
|
+
* @method
|
|
106
|
+
* @param {number|string} value
|
|
107
|
+
* @returns {boolean}
|
|
108
|
+
* @public
|
|
109
|
+
*/
|
|
110
|
+
const contains = ( value ) => {
|
|
111
|
+
return !!( properties[ value ] );
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
Object.defineProperties( enumObject, {
|
|
115
|
+
contains: {
|
|
116
|
+
enumerable: false,
|
|
117
|
+
configurable: false,
|
|
118
|
+
writable: false,
|
|
119
|
+
value: contains
|
|
120
|
+
},
|
|
121
|
+
description: {
|
|
122
|
+
enumerable: false,
|
|
123
|
+
configurable: false,
|
|
124
|
+
writable: false,
|
|
125
|
+
value: description
|
|
126
|
+
},
|
|
127
|
+
name: {
|
|
128
|
+
enumerable: false,
|
|
129
|
+
configurable: false,
|
|
130
|
+
writable: false,
|
|
131
|
+
value: name
|
|
132
|
+
},
|
|
133
|
+
properties: {
|
|
134
|
+
enumerable: false,
|
|
135
|
+
configurable: false,
|
|
136
|
+
writable: false,
|
|
137
|
+
value: properties
|
|
61
138
|
}
|
|
62
139
|
} );
|
|
63
|
-
|
|
140
|
+
Object.freeze( enumObject );
|
|
64
141
|
|
|
65
|
-
|
|
66
|
-
return seed;
|
|
142
|
+
return enumObject;
|
|
67
143
|
};
|
|
68
144
|
|
|
69
145
|
/**
|
|
70
146
|
* Used to get the name of an {@link TiEnum} value if such exists.
|
|
71
147
|
*
|
|
72
148
|
* @method
|
|
149
|
+
* @deprecated Use the 'name' property of the provided {@link TiEnum} instead.
|
|
73
150
|
* @param {TiEnum} enumList
|
|
74
151
|
* @param {number|string} enumValue
|
|
75
152
|
* @param {string} [placeholder=undefined] If provided it will be returned when the enum value does not have a name defined.
|
|
@@ -81,7 +158,7 @@ module.exports.getEnumName = ( enumList, enumValue, placeholder = undefined ) =>
|
|
|
81
158
|
};
|
|
82
159
|
|
|
83
160
|
/**
|
|
84
|
-
* Convert an Error to JSON object.
|
|
161
|
+
* Convert an Error to a JSON object.
|
|
85
162
|
* <br/>
|
|
86
163
|
* NOTE: If the value provided is not an error, then it will just be cloned.
|
|
87
164
|
*
|
|
@@ -123,7 +200,7 @@ module.exports.toBool = ( value ) => {
|
|
|
123
200
|
};
|
|
124
201
|
|
|
125
202
|
/**
|
|
126
|
-
* Will return UTC date string in format YYYY-MM-DD from the provided date.
|
|
203
|
+
* Will return a UTC date string in format YYYY-MM-DD from the provided date.
|
|
127
204
|
*
|
|
128
205
|
* @method
|
|
129
206
|
* @param {Date} date
|
|
@@ -131,15 +208,14 @@ module.exports.toBool = ( value ) => {
|
|
|
131
208
|
* @public
|
|
132
209
|
*/
|
|
133
210
|
module.exports.getUTCDateString = ( date ) => {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return String( year + "-" + month + "-" + day );
|
|
211
|
+
const year = date.getUTCFullYear();
|
|
212
|
+
const month = String( date.getUTCMonth() + 1 ).padStart( 2, "0" );
|
|
213
|
+
const day = String( date.getUTCDate() ).padStart( 2, "0" );
|
|
214
|
+
return `${ year }-${ month }-${ day }`;
|
|
139
215
|
};
|
|
140
216
|
|
|
141
217
|
/**
|
|
142
|
-
* Will return UTC time string in format hh:mm:ss.MMM
|
|
218
|
+
* Will return a UTC time string in format hh:mm:ss, or hh:mm:ss.MMM when useMilliseconds is true.
|
|
143
219
|
*
|
|
144
220
|
* @method
|
|
145
221
|
* @param {Date} date
|
|
@@ -147,13 +223,12 @@ module.exports.getUTCDateString = ( date ) => {
|
|
|
147
223
|
* @returns {string}
|
|
148
224
|
* @public
|
|
149
225
|
*/
|
|
150
|
-
module.exports.getUTCTimeString = ( date, useMilliseconds ) => {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return String( hours + ":" + minutes + ":" + seconds + ( ( useMilliseconds ) ? "." + milliseconds : "" ) );
|
|
226
|
+
module.exports.getUTCTimeString = ( date, useMilliseconds = false ) => {
|
|
227
|
+
const hours = String( date.getUTCHours() ).padStart( 2, "0" );
|
|
228
|
+
const minutes = String( date.getUTCMinutes() ).padStart( 2, "0" );
|
|
229
|
+
const seconds = String( date.getUTCSeconds() ).padStart( 2, "0" );
|
|
230
|
+
const milliseconds = useMilliseconds ? `${ String( date.getUTCMilliseconds() ).padStart( 3, "0" ) }` : "";
|
|
231
|
+
return `${ hours }:${ minutes }:${ seconds }${ useMilliseconds ? `.${ milliseconds }` : "" }`;
|
|
157
232
|
};
|
|
158
233
|
|
|
159
234
|
/**
|
|
@@ -181,7 +256,7 @@ module.exports.getUTCTimeString = ( date, useMilliseconds ) => {
|
|
|
181
256
|
*
|
|
182
257
|
* @method
|
|
183
258
|
* @param {Object} object
|
|
184
|
-
* @param {function} [replacer]
|
|
259
|
+
* @param {function( Object ): Object} [replacer]
|
|
185
260
|
* @returns {Object}
|
|
186
261
|
* @public
|
|
187
262
|
*/
|
|
@@ -315,7 +390,7 @@ module.exports.retrocycle = ( $ ) => {
|
|
|
315
390
|
*
|
|
316
391
|
* @method
|
|
317
392
|
* @param {Object} value
|
|
318
|
-
* @
|
|
393
|
+
* @returns {string|*}
|
|
319
394
|
* @public
|
|
320
395
|
*/
|
|
321
396
|
module.exports.stringifyJSON = ( value ) => {
|
|
@@ -345,7 +420,7 @@ module.exports.isJsonString = ( string ) => {
|
|
|
345
420
|
*
|
|
346
421
|
* @method
|
|
347
422
|
* @param {string} value
|
|
348
|
-
* @
|
|
423
|
+
* @returns {Object|string}
|
|
349
424
|
* @public
|
|
350
425
|
*/
|
|
351
426
|
module.exports.parseJSON = ( value ) => {
|
|
@@ -364,7 +439,7 @@ module.exports.parseJSON = ( value ) => {
|
|
|
364
439
|
*
|
|
365
440
|
* @param {Object} input
|
|
366
441
|
* @recursion
|
|
367
|
-
* @
|
|
442
|
+
* @returns {string|null}
|
|
368
443
|
* @public
|
|
369
444
|
*/
|
|
370
445
|
module.exports.decomposeJSON = ( input ) => {
|
|
@@ -399,50 +474,6 @@ module.exports.decomposeJSON = ( input ) => {
|
|
|
399
474
|
return decomposed;
|
|
400
475
|
};
|
|
401
476
|
|
|
402
|
-
/**
|
|
403
|
-
* Used to create a CSV file from the provided data.
|
|
404
|
-
*
|
|
405
|
-
* @method
|
|
406
|
-
* @param {Object[]} data
|
|
407
|
-
* @param {string} filePath
|
|
408
|
-
* @param {string} fileName
|
|
409
|
-
* @return {Promise}
|
|
410
|
-
* @public
|
|
411
|
-
*/
|
|
412
|
-
module.exports.createCSVFile = ( data, filePath, fileName ) => {
|
|
413
|
-
return new Promise( ( resolve, reject ) => {
|
|
414
|
-
let fileData = "";
|
|
415
|
-
if ( data && data.length > 0 ) {
|
|
416
|
-
let keys = [];
|
|
417
|
-
_.forOwn( data[ 0 ], ( value, key ) => {
|
|
418
|
-
keys.push( key );
|
|
419
|
-
} );
|
|
420
|
-
keys.sort();
|
|
421
|
-
|
|
422
|
-
_.forEach( keys, ( key, idx ) => {
|
|
423
|
-
fileData += key + ( ( idx < keys.length - 1 ) ? "," : "" );
|
|
424
|
-
} );
|
|
425
|
-
fileData += "\n";
|
|
426
|
-
|
|
427
|
-
_.forEach( data, ( entry ) => {
|
|
428
|
-
_.forEach( keys, ( key, idx ) => {
|
|
429
|
-
fileData += entry[ key ] + ( ( idx < keys.length - 1 ) ? "," : "" );
|
|
430
|
-
} );
|
|
431
|
-
fileData += "\n";
|
|
432
|
-
} );
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
fs.ensureDir( filePath ).then( () => {
|
|
436
|
-
const fullPath = filePath + "/" + Date.now() + "-" + fileName + ".csv";
|
|
437
|
-
return fs.appendFile( fullPath, fileData );
|
|
438
|
-
} ).then( () => {
|
|
439
|
-
resolve();
|
|
440
|
-
} ).catch( ( error ) => {
|
|
441
|
-
reject( error );
|
|
442
|
-
} );
|
|
443
|
-
} );
|
|
444
|
-
};
|
|
445
|
-
|
|
446
477
|
/**
|
|
447
478
|
* Used to create retry policy for the execution of an operation.
|
|
448
479
|
*
|
|
@@ -457,8 +488,12 @@ class RetryPolicy {
|
|
|
457
488
|
|
|
458
489
|
/**
|
|
459
490
|
* @constructor
|
|
491
|
+
* @param {number} maxAttempts The maximum number of attempts to execute the operation.
|
|
460
492
|
*/
|
|
461
493
|
constructor( maxAttempts ) {
|
|
494
|
+
if ( !Number.isInteger( maxAttempts ) || maxAttempts < 1 ) {
|
|
495
|
+
throw new TypeError( "maxAttempts must be a positive integer" );
|
|
496
|
+
}
|
|
462
497
|
this.#maxAttempts = maxAttempts;
|
|
463
498
|
}
|
|
464
499
|
|
|
@@ -468,13 +503,13 @@ class RetryPolicy {
|
|
|
468
503
|
* Used to start execution of the provided operation.
|
|
469
504
|
*
|
|
470
505
|
* @method
|
|
471
|
-
* @param {Object} context The context in which the operation will be executed (i.e
|
|
472
|
-
* @param {function} operation Operation to be executed;
|
|
473
|
-
* @param {Array} params The arguments to be provided to the operation upon execution.
|
|
506
|
+
* @param {Object} context The context in which the operation will be executed (i.e., this reference).
|
|
507
|
+
* @param {function( ...* ): Promise<*>} operation Operation to be executed; must return a Promise.
|
|
508
|
+
* @param {Array<*>} [params=[]] The arguments to be provided to the operation upon execution.
|
|
474
509
|
* @returns {Promise}
|
|
475
510
|
* @public
|
|
476
511
|
*/
|
|
477
|
-
execute( context, operation, params ) {
|
|
512
|
+
execute( context, operation, params = [] ) {
|
|
478
513
|
return this.#retry( context, operation, params, 1, undefined );
|
|
479
514
|
}
|
|
480
515
|
|
|
@@ -495,7 +530,7 @@ class RetryPolicy {
|
|
|
495
530
|
* Used to register a method that will be automatically called on each execution retry (after the initial one).
|
|
496
531
|
*
|
|
497
532
|
* @method
|
|
498
|
-
* @param {function( number )} action The current attempt
|
|
533
|
+
* @param {function( number, (Error|undefined) )} action The current attempt and last error are provided.
|
|
499
534
|
* @public
|
|
500
535
|
*/
|
|
501
536
|
onRetry( action ) {
|
|
@@ -511,8 +546,8 @@ class RetryPolicy {
|
|
|
511
546
|
*
|
|
512
547
|
* @method
|
|
513
548
|
* @param {Object} context
|
|
514
|
-
* @param {function} operation
|
|
515
|
-
* @param {Array} params
|
|
549
|
+
* @param {function( ...* ): Promise<*>} operation Operation to be executed; must return a Promise.
|
|
550
|
+
* @param {Array<*>} params The arguments to be provided to the operation upon execution.
|
|
516
551
|
* @param {number} attempt
|
|
517
552
|
* @param {Error} error
|
|
518
553
|
* @returns {Promise}
|
|
@@ -523,14 +558,25 @@ class RetryPolicy {
|
|
|
523
558
|
return Promise.reject( error );
|
|
524
559
|
} else {
|
|
525
560
|
if ( attempt > 1 && this.#onRetry ) {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
if ( this.#onFailedAttempt ) {
|
|
530
|
-
this.#onFailedAttempt( error );
|
|
561
|
+
try {
|
|
562
|
+
this.#onRetry( attempt, error );
|
|
563
|
+
} catch ( _ ) { /* ignore observer errors */
|
|
531
564
|
}
|
|
532
|
-
|
|
533
|
-
|
|
565
|
+
}
|
|
566
|
+
return Promise
|
|
567
|
+
.resolve()
|
|
568
|
+
.then( () => {
|
|
569
|
+
return operation.apply( context, params );
|
|
570
|
+
} )
|
|
571
|
+
.catch( ( error ) => {
|
|
572
|
+
if ( this.#onFailedAttempt ) {
|
|
573
|
+
try {
|
|
574
|
+
this.#onFailedAttempt( error );
|
|
575
|
+
} catch ( _ ) { /* ignore observer errors */
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
return this.#retry( context, operation, params, ( attempt + 1 ), error );
|
|
579
|
+
} );
|
|
534
580
|
}
|
|
535
581
|
}
|
|
536
582
|
|