@naturalcycles/js-lib 14.66.0 → 14.69.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -54,7 +54,8 @@ import { Class, ConditionalExcept, ConditionalPick, Merge, Promisable, PromiseVa
54
54
  import { AsyncMapper, AsyncPredicate, BaseDBEntity, CreatedUpdated, CreatedUpdatedId, ObjectWithId, AnyObjectWithId, Saved, Unsaved, BatchResult, InstanceId, IsoDate, IsoDateTime, KeyValueTuple, Mapper, ObjectMapper, ObjectPredicate, Predicate, PromiseMap, AnyObject, AnyFunction, Reviver, SavedDBEntity, StringMap, UnixTimestamp, ValueOf, ValuesOf, _noop, _objectKeys, _passNothingPredicate, _passthroughMapper, _passthroughPredicate, _passUndefinedMapper, _stringMapEntries, _stringMapValues } from './types';
55
55
  import { _gb, _hb, _kb, _mb } from './unit/size.util';
56
56
  import { is } from './vendor/is';
57
- import { CommonLogLevel, CommonLogFunction, CommonLogger, commonLoggerMinLevel, noopLogger, commonLogLevelNumber } from './log/commonLogger';
57
+ import { CommonLogLevel, CommonLogFunction, CommonLogger, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix } from './log/commonLogger';
58
58
  import { _safeJsonStringify } from './string/safeJsonStringify';
59
- export type { MemoCache, PromiseDecoratorCfg, PromiseDecoratorResp, ErrorData, ErrorObject, HttpErrorData, HttpErrorResponse, Admin401ErrorData, Admin403ErrorData, StringMap, PromiseMap, AnyObject, AnyFunction, ValuesOf, ValueOf, KeyValueTuple, ObjectMapper, ObjectPredicate, InstanceId, IsoDate, IsoDateTime, Reviver, PMapOptions, Mapper, AsyncMapper, Predicate, AsyncPredicate, BatchResult, DeferredPromise, PRetryOptions, PTimeoutOptions, TryCatchOptions, StringifyAnyOptions, JsonStringifyFunction, Merge, ReadonlyDeep, Promisable, PromiseValue, Simplify, ConditionalPick, ConditionalExcept, Class, UnixTimestamp, BaseDBEntity, SavedDBEntity, Saved, Unsaved, CreatedUpdated, CreatedUpdatedId, ObjectWithId, AnyObjectWithId, JsonSchema, JsonSchemaAny, JsonSchemaOneOf, JsonSchemaAllOf, JsonSchemaAnyOf, JsonSchemaNot, JsonSchemaRef, JsonSchemaConst, JsonSchemaEnum, JsonSchemaString, JsonSchemaNumber, JsonSchemaBoolean, JsonSchemaNull, JsonSchemaRootObject, JsonSchemaObject, JsonSchemaArray, JsonSchemaTuple, JsonSchemaBuilder, CommonLogLevel, CommonLogFunction, CommonLogger, };
60
- export { is, _Memo, _memoFn, _LogMethod, _getArgsSignature, _createPromiseDecorator, AppError, HttpError, AssertionError, _isErrorObject, _isHttpErrorObject, _isHttpErrorResponse, _assert, _assertEquals, _assertDeepEquals, _assertIsError, _assertIsString, _assertIsNumber, _assertTypeOf, _randomInt, _randomArrayItem, _createDeterministicRandom, _inRange, _stringMapValues, _stringMapEntries, _objectKeys, _capitalize, _upperFirst, _lowerFirst, _split, _removeWhitespace, _substringBefore, _substringBeforeLast, _substringAfter, _substringAfterLast, _substringBetweenLast, _replaceAll, _nl2br, _truncate, _truncateMiddle, _pick, _omit, _filterFalsyValues, _filterUndefinedValues, _filterNullishValues, _filterEmptyArrays, _filterEmptyValues, _filterObject, _undefinedIfEmpty, _isObject, _isPrimitive, _mapKeys, _mapValues, _mapObject, _objectNullValuesToUndefined, _deepEquals, _deepCopy, _isEmptyObject, _isEmpty, _merge, _deepTrim, _sortObjectDeep, _sortObject, _get, _set, _has, _unset, _mask, _invert, _invertMap, _by, _groupBy, _sortBy, _sortNumbers, _toFixed, _toPrecision, _round, _findLast, _takeWhile, _takeRightWhile, _dropWhile, _dropRightWhile, _countBy, _intersection, _difference, _shuffle, _mapToObject, _findKeyByValue, _anyToError, _anyToErrorObject, _errorToErrorObject, _errorObjectToAppError, _range, _uniq, _uniqBy, _flatten, _flattenDeep, _chunk, SimpleMovingAverage, _average, _averageWeighted, _percentile, _median, _debounce, _throttle, _Debounce, _Throttle, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, pBatch, ErrorMode, pFilter, pProps, pDelay, pDefer, pHang, pState, AggregatedError, pRetry, pTimeout, pTuple, _Retry, _Timeout, _tryCatch, _TryCatch, _try, pTry, _jsonParseIfPossible, _stringifyAny, _ms, _since, _hb, _gb, _mb, _kb, _snakeCase, _camelCase, _kebabCase, _sum, _sumBy, _clamp, _last, mergeJsonSchemaObjects, jsonSchema, JsonSchemaAnyBuilder, JSON_SCHEMA_ORDER, generateJsonSchemaFromData, _parseQueryString, _defineLazyProperty, _defineLazyProps, _lazyValue, commonLoggerMinLevel, noopLogger, commonLogLevelNumber, _safeJsonStringify, };
59
+ import { PQueue, PQueueCfg } from './promise/pQueue';
60
+ export type { PQueueCfg, MemoCache, PromiseDecoratorCfg, PromiseDecoratorResp, ErrorData, ErrorObject, HttpErrorData, HttpErrorResponse, Admin401ErrorData, Admin403ErrorData, StringMap, PromiseMap, AnyObject, AnyFunction, ValuesOf, ValueOf, KeyValueTuple, ObjectMapper, ObjectPredicate, InstanceId, IsoDate, IsoDateTime, Reviver, PMapOptions, Mapper, AsyncMapper, Predicate, AsyncPredicate, BatchResult, DeferredPromise, PRetryOptions, PTimeoutOptions, TryCatchOptions, StringifyAnyOptions, JsonStringifyFunction, Merge, ReadonlyDeep, Promisable, PromiseValue, Simplify, ConditionalPick, ConditionalExcept, Class, UnixTimestamp, BaseDBEntity, SavedDBEntity, Saved, Unsaved, CreatedUpdated, CreatedUpdatedId, ObjectWithId, AnyObjectWithId, JsonSchema, JsonSchemaAny, JsonSchemaOneOf, JsonSchemaAllOf, JsonSchemaAnyOf, JsonSchemaNot, JsonSchemaRef, JsonSchemaConst, JsonSchemaEnum, JsonSchemaString, JsonSchemaNumber, JsonSchemaBoolean, JsonSchemaNull, JsonSchemaRootObject, JsonSchemaObject, JsonSchemaArray, JsonSchemaTuple, JsonSchemaBuilder, CommonLogLevel, CommonLogFunction, CommonLogger, };
61
+ export { is, _Memo, _memoFn, _LogMethod, _getArgsSignature, _createPromiseDecorator, AppError, HttpError, AssertionError, _isErrorObject, _isHttpErrorObject, _isHttpErrorResponse, _assert, _assertEquals, _assertDeepEquals, _assertIsError, _assertIsString, _assertIsNumber, _assertTypeOf, _randomInt, _randomArrayItem, _createDeterministicRandom, _inRange, _stringMapValues, _stringMapEntries, _objectKeys, _capitalize, _upperFirst, _lowerFirst, _split, _removeWhitespace, _substringBefore, _substringBeforeLast, _substringAfter, _substringAfterLast, _substringBetweenLast, _replaceAll, _nl2br, _truncate, _truncateMiddle, _pick, _omit, _filterFalsyValues, _filterUndefinedValues, _filterNullishValues, _filterEmptyArrays, _filterEmptyValues, _filterObject, _undefinedIfEmpty, _isObject, _isPrimitive, _mapKeys, _mapValues, _mapObject, _objectNullValuesToUndefined, _deepEquals, _deepCopy, _isEmptyObject, _isEmpty, _merge, _deepTrim, _sortObjectDeep, _sortObject, _get, _set, _has, _unset, _mask, _invert, _invertMap, _by, _groupBy, _sortBy, _sortNumbers, _toFixed, _toPrecision, _round, _findLast, _takeWhile, _takeRightWhile, _dropWhile, _dropRightWhile, _countBy, _intersection, _difference, _shuffle, _mapToObject, _findKeyByValue, _anyToError, _anyToErrorObject, _errorToErrorObject, _errorObjectToAppError, _range, _uniq, _uniqBy, _flatten, _flattenDeep, _chunk, SimpleMovingAverage, _average, _averageWeighted, _percentile, _median, _debounce, _throttle, _Debounce, _Throttle, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, pBatch, ErrorMode, pFilter, pProps, pDelay, pDefer, pHang, pState, AggregatedError, pRetry, pTimeout, pTuple, _Retry, _Timeout, _tryCatch, _TryCatch, _try, pTry, _jsonParseIfPossible, _stringifyAny, _ms, _since, _hb, _gb, _mb, _kb, _snakeCase, _camelCase, _kebabCase, _sum, _sumBy, _clamp, _last, mergeJsonSchemaObjects, jsonSchema, JsonSchemaAnyBuilder, JSON_SCHEMA_ORDER, generateJsonSchemaFromData, _parseQueryString, _defineLazyProperty, _defineLazyProps, _lazyValue, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, _safeJsonStringify, PQueue, };
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports._isObject = exports._undefinedIfEmpty = exports._filterObject = exports._filterEmptyValues = exports._filterEmptyArrays = exports._filterNullishValues = exports._filterUndefinedValues = exports._filterFalsyValues = exports._omit = exports._pick = exports._truncateMiddle = exports._truncate = exports._nl2br = exports._replaceAll = exports._substringBetweenLast = exports._substringAfterLast = exports._substringAfter = exports._substringBeforeLast = exports._substringBefore = exports._removeWhitespace = exports._split = exports._lowerFirst = exports._upperFirst = exports._capitalize = exports._objectKeys = exports._stringMapEntries = exports._stringMapValues = exports._inRange = exports._createDeterministicRandom = exports._randomArrayItem = exports._randomInt = exports._assertTypeOf = exports._assertIsNumber = exports._assertIsString = exports._assertIsError = exports._assertDeepEquals = exports._assertEquals = exports._assert = exports._isHttpErrorResponse = exports._isHttpErrorObject = exports._isErrorObject = exports.AssertionError = exports.HttpError = exports.AppError = exports._createPromiseDecorator = exports._getArgsSignature = exports._LogMethod = exports._memoFn = exports._Memo = exports.is = void 0;
4
4
  exports._average = exports.SimpleMovingAverage = exports._chunk = exports._flattenDeep = exports._flatten = exports._uniqBy = exports._uniq = exports._range = exports._errorObjectToAppError = exports._errorToErrorObject = exports._anyToErrorObject = exports._anyToError = exports._findKeyByValue = exports._mapToObject = exports._shuffle = exports._difference = exports._intersection = exports._countBy = exports._dropRightWhile = exports._dropWhile = exports._takeRightWhile = exports._takeWhile = exports._findLast = exports._round = exports._toPrecision = exports._toFixed = exports._sortNumbers = exports._sortBy = exports._groupBy = exports._by = exports._invertMap = exports._invert = exports._mask = exports._unset = exports._has = exports._set = exports._get = exports._sortObject = exports._sortObjectDeep = exports._deepTrim = exports._merge = exports._isEmpty = exports._isEmptyObject = exports._deepCopy = exports._deepEquals = exports._objectNullValuesToUndefined = exports._mapObject = exports._mapValues = exports._mapKeys = exports._isPrimitive = void 0;
5
5
  exports.JSON_SCHEMA_ORDER = exports.JsonSchemaAnyBuilder = exports.jsonSchema = exports.mergeJsonSchemaObjects = exports._last = exports._clamp = exports._sumBy = exports._sum = exports._kebabCase = exports._camelCase = exports._snakeCase = exports._kb = exports._mb = exports._gb = exports._hb = exports._since = exports._ms = exports._stringifyAny = exports._jsonParseIfPossible = exports.pTry = exports._try = exports._TryCatch = exports._tryCatch = exports._Timeout = exports._Retry = exports.pTuple = exports.pTimeout = exports.pRetry = exports.AggregatedError = exports.pState = exports.pHang = exports.pDefer = exports.pDelay = exports.pProps = exports.pFilter = exports.ErrorMode = exports.pBatch = exports._noop = exports._passNothingPredicate = exports._passthroughPredicate = exports._passUndefinedMapper = exports._passthroughMapper = exports.pMap = exports._Throttle = exports._Debounce = exports._throttle = exports._debounce = exports._median = exports._percentile = exports._averageWeighted = void 0;
6
- exports._safeJsonStringify = exports.commonLogLevelNumber = exports.noopLogger = exports.commonLoggerMinLevel = exports._lazyValue = exports._defineLazyProps = exports._defineLazyProperty = exports._parseQueryString = exports.generateJsonSchemaFromData = void 0;
6
+ exports.PQueue = exports._safeJsonStringify = exports.commonLoggerPrefix = exports.commonLoggerPipe = exports.commonLogLevelNumber = exports.commonLoggerNoop = exports.commonLoggerMinLevel = exports._lazyValue = exports._defineLazyProps = exports._defineLazyProperty = exports._parseQueryString = exports.generateJsonSchemaFromData = void 0;
7
7
  const array_util_1 = require("./array/array.util");
8
8
  Object.defineProperty(exports, "_by", { enumerable: true, get: function () { return array_util_1._by; } });
9
9
  Object.defineProperty(exports, "_chunk", { enumerable: true, get: function () { return array_util_1._chunk; } });
@@ -213,7 +213,11 @@ const is_1 = require("./vendor/is");
213
213
  Object.defineProperty(exports, "is", { enumerable: true, get: function () { return is_1.is; } });
214
214
  const commonLogger_1 = require("./log/commonLogger");
215
215
  Object.defineProperty(exports, "commonLoggerMinLevel", { enumerable: true, get: function () { return commonLogger_1.commonLoggerMinLevel; } });
216
- Object.defineProperty(exports, "noopLogger", { enumerable: true, get: function () { return commonLogger_1.noopLogger; } });
216
+ Object.defineProperty(exports, "commonLoggerNoop", { enumerable: true, get: function () { return commonLogger_1.commonLoggerNoop; } });
217
217
  Object.defineProperty(exports, "commonLogLevelNumber", { enumerable: true, get: function () { return commonLogger_1.commonLogLevelNumber; } });
218
+ Object.defineProperty(exports, "commonLoggerPipe", { enumerable: true, get: function () { return commonLogger_1.commonLoggerPipe; } });
219
+ Object.defineProperty(exports, "commonLoggerPrefix", { enumerable: true, get: function () { return commonLogger_1.commonLoggerPrefix; } });
218
220
  const safeJsonStringify_1 = require("./string/safeJsonStringify");
219
221
  Object.defineProperty(exports, "_safeJsonStringify", { enumerable: true, get: function () { return safeJsonStringify_1._safeJsonStringify; } });
222
+ const pQueue_1 = require("./promise/pQueue");
223
+ Object.defineProperty(exports, "PQueue", { enumerable: true, get: function () { return pQueue_1.PQueue; } });
@@ -33,8 +33,16 @@ export interface CommonLogger {
33
33
  *
34
34
  * @experimental
35
35
  */
36
- export declare const noopLogger: CommonLogger;
36
+ export declare const commonLoggerNoop: CommonLogger;
37
37
  /**
38
38
  * Creates a "child" logger that is "limited" to the specified CommonLogLevel.
39
39
  */
40
40
  export declare function commonLoggerMinLevel(logger: CommonLogger, minLevel: CommonLogLevel, mutate?: boolean): CommonLogger;
41
+ /**
42
+ * Creates a "proxy" CommonLogger that pipes log messages to all provided sub-loggers.
43
+ */
44
+ export declare function commonLoggerPipe(loggers: CommonLogger[]): CommonLogger;
45
+ /**
46
+ * Creates a "child" CommonLogger with prefix (one or multiple).
47
+ */
48
+ export declare function commonLoggerPrefix(logger: CommonLogger, ...prefixes: any[]): CommonLogger;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.commonLoggerMinLevel = exports.noopLogger = exports.commonLogLevelNumber = void 0;
3
+ exports.commonLoggerPrefix = exports.commonLoggerPipe = exports.commonLoggerMinLevel = exports.commonLoggerNoop = exports.commonLogLevelNumber = void 0;
4
4
  const index_1 = require("../index");
5
5
  exports.commonLogLevelNumber = {
6
6
  log: 10,
@@ -12,7 +12,7 @@ exports.commonLogLevelNumber = {
12
12
  *
13
13
  * @experimental
14
14
  */
15
- exports.noopLogger = {
15
+ exports.commonLoggerNoop = {
16
16
  log: index_1._noop,
17
17
  warn: index_1._noop,
18
18
  error: index_1._noop,
@@ -34,10 +34,40 @@ function commonLoggerMinLevel(logger, minLevel, mutate = false) {
34
34
  }
35
35
  return logger;
36
36
  }
37
+ if (level <= exports.commonLogLevelNumber['log']) {
38
+ // All levels are kept
39
+ return logger;
40
+ }
41
+ if (level > exports.commonLogLevelNumber['error']) {
42
+ // "Log nothing" logger
43
+ return exports.commonLoggerNoop;
44
+ }
37
45
  return {
38
- log: level <= exports.commonLogLevelNumber['log'] ? (...args) => logger.log(...args) : index_1._noop,
39
- warn: level <= exports.commonLogLevelNumber['warn'] ? (...args) => logger.warn(...args) : index_1._noop,
40
- error: level <= exports.commonLogLevelNumber['error'] ? (...args) => logger.error(...args) : index_1._noop,
46
+ log: index_1._noop,
47
+ warn: level <= exports.commonLogLevelNumber['warn'] ? logger.warn.bind(logger) : index_1._noop,
48
+ error: logger.error.bind(logger), // otherwise it's "log nothing" logger (same as noopLogger)
41
49
  };
42
50
  }
43
51
  exports.commonLoggerMinLevel = commonLoggerMinLevel;
52
+ /**
53
+ * Creates a "proxy" CommonLogger that pipes log messages to all provided sub-loggers.
54
+ */
55
+ function commonLoggerPipe(loggers) {
56
+ return {
57
+ log: (...args) => loggers.forEach(logger => logger.log(...args)),
58
+ warn: (...args) => loggers.forEach(logger => logger.warn(...args)),
59
+ error: (...args) => loggers.forEach(logger => logger.error(...args)),
60
+ };
61
+ }
62
+ exports.commonLoggerPipe = commonLoggerPipe;
63
+ /**
64
+ * Creates a "child" CommonLogger with prefix (one or multiple).
65
+ */
66
+ function commonLoggerPrefix(logger, ...prefixes) {
67
+ return {
68
+ log: (...args) => logger.log(...prefixes, ...args),
69
+ warn: (...args) => logger.warn(...prefixes, ...args),
70
+ error: (...args) => logger.error(...prefixes, ...args),
71
+ };
72
+ }
73
+ exports.commonLoggerPrefix = commonLoggerPrefix;
@@ -0,0 +1,53 @@
1
+ import { ErrorMode } from '../error/errorMode';
2
+ import { CommonLogger } from '../log/commonLogger';
3
+ export interface PQueueCfg {
4
+ concurrency: number;
5
+ /**
6
+ * Default: THROW_IMMEDIATELY
7
+ *
8
+ * THROW_AGGREGATED is not supported.
9
+ *
10
+ * SUPPRESS_ERRORS will still log errors via logger. It will resolve the `.push` promise with void.
11
+ */
12
+ errorMode?: ErrorMode;
13
+ /**
14
+ * @default true
15
+ */
16
+ /**
17
+ * Default to `console`
18
+ */
19
+ logger?: CommonLogger;
20
+ /**
21
+ * If true - will LOG EVERYTHING:)
22
+ */
23
+ debug?: boolean;
24
+ }
25
+ export declare type PromiseReturningFunction<R> = () => Promise<R>;
26
+ /**
27
+ * Inspired by: https://github.com/sindresorhus/p-queue
28
+ *
29
+ * Allows to push "jobs" to the queue and control its concurrency.
30
+ * Jobs are "promise-returning functions".
31
+ *
32
+ * API is @experimental
33
+ */
34
+ export declare class PQueue {
35
+ constructor(cfg: PQueueCfg);
36
+ private readonly cfg;
37
+ private debug;
38
+ inFlight: number;
39
+ private queue;
40
+ private onIdleListeners;
41
+ get queueSize(): number;
42
+ /**
43
+ * Returns a Promise that resolves when the queue is Idle (next time, since the call).
44
+ * Resolves immediately in case the queue is Idle.
45
+ * Idle means 0 queue and 0 inFlight.
46
+ */
47
+ onIdle(): Promise<void>;
48
+ /**
49
+ * Push PromiseReturningFunction to the Queue.
50
+ * Returns a Promise that resolves (or rejects) with the return value from the Promise.
51
+ */
52
+ push<R>(fn_: PromiseReturningFunction<R>): Promise<R>;
53
+ }
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PQueue = void 0;
4
+ const errorMode_1 = require("../error/errorMode");
5
+ const pDefer_1 = require("./pDefer");
6
+ /**
7
+ * Inspired by: https://github.com/sindresorhus/p-queue
8
+ *
9
+ * Allows to push "jobs" to the queue and control its concurrency.
10
+ * Jobs are "promise-returning functions".
11
+ *
12
+ * API is @experimental
13
+ */
14
+ class PQueue {
15
+ constructor(cfg) {
16
+ this.inFlight = 0;
17
+ this.queue = [];
18
+ this.onIdleListeners = [];
19
+ this.cfg = {
20
+ // concurrency: Number.MAX_SAFE_INTEGER,
21
+ errorMode: errorMode_1.ErrorMode.THROW_IMMEDIATELY,
22
+ logger: console,
23
+ debug: false,
24
+ ...cfg,
25
+ };
26
+ if (!cfg.debug) {
27
+ this.debug = () => { };
28
+ }
29
+ }
30
+ debug(...args) {
31
+ this.cfg.logger.log(...args);
32
+ }
33
+ get queueSize() {
34
+ return this.queue.length;
35
+ }
36
+ /**
37
+ * Returns a Promise that resolves when the queue is Idle (next time, since the call).
38
+ * Resolves immediately in case the queue is Idle.
39
+ * Idle means 0 queue and 0 inFlight.
40
+ */
41
+ onIdle() {
42
+ if (this.queue.length === 0)
43
+ return Promise.resolve();
44
+ const listener = (0, pDefer_1.pDefer)();
45
+ this.onIdleListeners.push(listener);
46
+ return listener;
47
+ }
48
+ /**
49
+ * Push PromiseReturningFunction to the Queue.
50
+ * Returns a Promise that resolves (or rejects) with the return value from the Promise.
51
+ */
52
+ push(fn_) {
53
+ const { concurrency } = this.cfg;
54
+ const fn = fn_;
55
+ fn.defer || (fn.defer = (0, pDefer_1.pDefer)());
56
+ if (this.inFlight < concurrency) {
57
+ // There is room for more jobs. Can start immediately
58
+ this.inFlight++;
59
+ this.debug(`inFlight++ ${this.inFlight}/${concurrency}, queue ${this.queue.length}`);
60
+ fn()
61
+ .then(result => fn.defer.resolve(result))
62
+ .catch(err => {
63
+ this.cfg.logger.error(err);
64
+ if (this.cfg.errorMode === errorMode_1.ErrorMode.SUPPRESS) {
65
+ fn.defer.resolve(); // resolve with `void`
66
+ }
67
+ else {
68
+ // Should be handled on the outside, otherwise it'll cause UnhandledRejection
69
+ fn.defer.reject(err);
70
+ }
71
+ })
72
+ .finally(() => {
73
+ this.inFlight--;
74
+ this.debug(`inFlight-- ${this.inFlight}/${concurrency}, queue ${this.queue.length}`);
75
+ // check if there's room to start next job
76
+ if (this.queue.length && this.inFlight <= concurrency) {
77
+ const nextFn = this.queue.shift();
78
+ void this.push(nextFn);
79
+ }
80
+ else {
81
+ if (this.inFlight === 0) {
82
+ this.debug('onIdle');
83
+ this.onIdleListeners.forEach(defer => defer.resolve());
84
+ this.onIdleListeners.length = 0; // empty the array
85
+ }
86
+ }
87
+ });
88
+ }
89
+ else {
90
+ this.queue.push(fn);
91
+ this.debug(`inFlight ${this.inFlight}/${concurrency}, queue++ ${this.queue.length}`);
92
+ }
93
+ return fn.defer;
94
+ }
95
+ }
96
+ exports.PQueue = PQueue;
@@ -1,3 +1,4 @@
1
+ import { AnyFunction } from '../types';
1
2
  export interface PTimeoutOptions {
2
3
  /**
3
4
  * Timeout in milliseconds.
@@ -19,4 +20,4 @@ export interface PTimeoutOptions {
19
20
  * Throws an Error if the Function is not resolved in a certain time.
20
21
  * If the Function rejects - passes this rejection further.
21
22
  */
22
- export declare function pTimeout<T extends Function>(fn: T, opt: PTimeoutOptions): T;
23
+ export declare function pTimeout<T extends AnyFunction>(fn: T, opt: PTimeoutOptions): T;
@@ -6,7 +6,6 @@ exports.pTimeout = void 0;
6
6
  * Throws an Error if the Function is not resolved in a certain time.
7
7
  * If the Function rejects - passes this rejection further.
8
8
  */
9
- // eslint-disable-next-line @typescript-eslint/ban-types
10
9
  function pTimeout(fn, opt) {
11
10
  // const fname = fn.name || 'function'
12
11
  const { timeout, name, onTimeout } = opt;
package/dist-esm/index.js CHANGED
@@ -50,6 +50,7 @@ import { _ms, _since } from './time/time.util';
50
50
  import { _noop, _objectKeys, _passNothingPredicate, _passthroughMapper, _passthroughPredicate, _passUndefinedMapper, _stringMapEntries, _stringMapValues, } from './types';
51
51
  import { _gb, _hb, _kb, _mb } from './unit/size.util';
52
52
  import { is } from './vendor/is';
53
- import { commonLoggerMinLevel, noopLogger, commonLogLevelNumber, } from './log/commonLogger';
53
+ import { commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, } from './log/commonLogger';
54
54
  import { _safeJsonStringify } from './string/safeJsonStringify';
55
- export { is, _Memo, _memoFn, _LogMethod, _getArgsSignature, _createPromiseDecorator, AppError, HttpError, AssertionError, _isErrorObject, _isHttpErrorObject, _isHttpErrorResponse, _assert, _assertEquals, _assertDeepEquals, _assertIsError, _assertIsString, _assertIsNumber, _assertTypeOf, _randomInt, _randomArrayItem, _createDeterministicRandom, _inRange, _stringMapValues, _stringMapEntries, _objectKeys, _capitalize, _upperFirst, _lowerFirst, _split, _removeWhitespace, _substringBefore, _substringBeforeLast, _substringAfter, _substringAfterLast, _substringBetweenLast, _replaceAll, _nl2br, _truncate, _truncateMiddle, _pick, _omit, _filterFalsyValues, _filterUndefinedValues, _filterNullishValues, _filterEmptyArrays, _filterEmptyValues, _filterObject, _undefinedIfEmpty, _isObject, _isPrimitive, _mapKeys, _mapValues, _mapObject, _objectNullValuesToUndefined, _deepEquals, _deepCopy, _isEmptyObject, _isEmpty, _merge, _deepTrim, _sortObjectDeep, _sortObject, _get, _set, _has, _unset, _mask, _invert, _invertMap, _by, _groupBy, _sortBy, _sortNumbers, _toFixed, _toPrecision, _round, _findLast, _takeWhile, _takeRightWhile, _dropWhile, _dropRightWhile, _countBy, _intersection, _difference, _shuffle, _mapToObject, _findKeyByValue, _anyToError, _anyToErrorObject, _errorToErrorObject, _errorObjectToAppError, _range, _uniq, _uniqBy, _flatten, _flattenDeep, _chunk, SimpleMovingAverage, _average, _averageWeighted, _percentile, _median, _debounce, _throttle, _Debounce, _Throttle, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, pBatch, ErrorMode, pFilter, pProps, pDelay, pDefer, pHang, pState, AggregatedError, pRetry, pTimeout, pTuple, _Retry, _Timeout, _tryCatch, _TryCatch, _try, pTry, _jsonParseIfPossible, _stringifyAny, _ms, _since, _hb, _gb, _mb, _kb, _snakeCase, _camelCase, _kebabCase, _sum, _sumBy, _clamp, _last, mergeJsonSchemaObjects, jsonSchema, JsonSchemaAnyBuilder, JSON_SCHEMA_ORDER, generateJsonSchemaFromData, _parseQueryString, _defineLazyProperty, _defineLazyProps, _lazyValue, commonLoggerMinLevel, noopLogger, commonLogLevelNumber, _safeJsonStringify, };
55
+ import { PQueue } from './promise/pQueue';
56
+ export { is, _Memo, _memoFn, _LogMethod, _getArgsSignature, _createPromiseDecorator, AppError, HttpError, AssertionError, _isErrorObject, _isHttpErrorObject, _isHttpErrorResponse, _assert, _assertEquals, _assertDeepEquals, _assertIsError, _assertIsString, _assertIsNumber, _assertTypeOf, _randomInt, _randomArrayItem, _createDeterministicRandom, _inRange, _stringMapValues, _stringMapEntries, _objectKeys, _capitalize, _upperFirst, _lowerFirst, _split, _removeWhitespace, _substringBefore, _substringBeforeLast, _substringAfter, _substringAfterLast, _substringBetweenLast, _replaceAll, _nl2br, _truncate, _truncateMiddle, _pick, _omit, _filterFalsyValues, _filterUndefinedValues, _filterNullishValues, _filterEmptyArrays, _filterEmptyValues, _filterObject, _undefinedIfEmpty, _isObject, _isPrimitive, _mapKeys, _mapValues, _mapObject, _objectNullValuesToUndefined, _deepEquals, _deepCopy, _isEmptyObject, _isEmpty, _merge, _deepTrim, _sortObjectDeep, _sortObject, _get, _set, _has, _unset, _mask, _invert, _invertMap, _by, _groupBy, _sortBy, _sortNumbers, _toFixed, _toPrecision, _round, _findLast, _takeWhile, _takeRightWhile, _dropWhile, _dropRightWhile, _countBy, _intersection, _difference, _shuffle, _mapToObject, _findKeyByValue, _anyToError, _anyToErrorObject, _errorToErrorObject, _errorObjectToAppError, _range, _uniq, _uniqBy, _flatten, _flattenDeep, _chunk, SimpleMovingAverage, _average, _averageWeighted, _percentile, _median, _debounce, _throttle, _Debounce, _Throttle, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, pBatch, ErrorMode, pFilter, pProps, pDelay, pDefer, pHang, pState, AggregatedError, pRetry, pTimeout, pTuple, _Retry, _Timeout, _tryCatch, _TryCatch, _try, pTry, _jsonParseIfPossible, _stringifyAny, _ms, _since, _hb, _gb, _mb, _kb, _snakeCase, _camelCase, _kebabCase, _sum, _sumBy, _clamp, _last, mergeJsonSchemaObjects, jsonSchema, JsonSchemaAnyBuilder, JSON_SCHEMA_ORDER, generateJsonSchemaFromData, _parseQueryString, _defineLazyProperty, _defineLazyProps, _lazyValue, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, _safeJsonStringify, PQueue, };
@@ -9,7 +9,7 @@ export const commonLogLevelNumber = {
9
9
  *
10
10
  * @experimental
11
11
  */
12
- export const noopLogger = {
12
+ export const commonLoggerNoop = {
13
13
  log: _noop,
14
14
  warn: _noop,
15
15
  error: _noop,
@@ -31,9 +31,37 @@ export function commonLoggerMinLevel(logger, minLevel, mutate = false) {
31
31
  }
32
32
  return logger;
33
33
  }
34
+ if (level <= commonLogLevelNumber['log']) {
35
+ // All levels are kept
36
+ return logger;
37
+ }
38
+ if (level > commonLogLevelNumber['error']) {
39
+ // "Log nothing" logger
40
+ return commonLoggerNoop;
41
+ }
42
+ return {
43
+ log: _noop,
44
+ warn: level <= commonLogLevelNumber['warn'] ? logger.warn.bind(logger) : _noop,
45
+ error: logger.error.bind(logger), // otherwise it's "log nothing" logger (same as noopLogger)
46
+ };
47
+ }
48
+ /**
49
+ * Creates a "proxy" CommonLogger that pipes log messages to all provided sub-loggers.
50
+ */
51
+ export function commonLoggerPipe(loggers) {
52
+ return {
53
+ log: (...args) => loggers.forEach(logger => logger.log(...args)),
54
+ warn: (...args) => loggers.forEach(logger => logger.warn(...args)),
55
+ error: (...args) => loggers.forEach(logger => logger.error(...args)),
56
+ };
57
+ }
58
+ /**
59
+ * Creates a "child" CommonLogger with prefix (one or multiple).
60
+ */
61
+ export function commonLoggerPrefix(logger, ...prefixes) {
34
62
  return {
35
- log: level <= commonLogLevelNumber['log'] ? (...args) => logger.log(...args) : _noop,
36
- warn: level <= commonLogLevelNumber['warn'] ? (...args) => logger.warn(...args) : _noop,
37
- error: level <= commonLogLevelNumber['error'] ? (...args) => logger.error(...args) : _noop,
63
+ log: (...args) => logger.log(...prefixes, ...args),
64
+ warn: (...args) => logger.warn(...prefixes, ...args),
65
+ error: (...args) => logger.error(...prefixes, ...args),
38
66
  };
39
67
  }
@@ -0,0 +1,88 @@
1
+ import { ErrorMode } from '../error/errorMode';
2
+ import { pDefer } from './pDefer';
3
+ /**
4
+ * Inspired by: https://github.com/sindresorhus/p-queue
5
+ *
6
+ * Allows to push "jobs" to the queue and control its concurrency.
7
+ * Jobs are "promise-returning functions".
8
+ *
9
+ * API is @experimental
10
+ */
11
+ export class PQueue {
12
+ constructor(cfg) {
13
+ this.inFlight = 0;
14
+ this.queue = [];
15
+ this.onIdleListeners = [];
16
+ this.cfg = Object.assign({
17
+ // concurrency: Number.MAX_SAFE_INTEGER,
18
+ errorMode: ErrorMode.THROW_IMMEDIATELY, logger: console, debug: false }, cfg);
19
+ if (!cfg.debug) {
20
+ this.debug = () => { };
21
+ }
22
+ }
23
+ debug(...args) {
24
+ this.cfg.logger.log(...args);
25
+ }
26
+ get queueSize() {
27
+ return this.queue.length;
28
+ }
29
+ /**
30
+ * Returns a Promise that resolves when the queue is Idle (next time, since the call).
31
+ * Resolves immediately in case the queue is Idle.
32
+ * Idle means 0 queue and 0 inFlight.
33
+ */
34
+ onIdle() {
35
+ if (this.queue.length === 0)
36
+ return Promise.resolve();
37
+ const listener = pDefer();
38
+ this.onIdleListeners.push(listener);
39
+ return listener;
40
+ }
41
+ /**
42
+ * Push PromiseReturningFunction to the Queue.
43
+ * Returns a Promise that resolves (or rejects) with the return value from the Promise.
44
+ */
45
+ push(fn_) {
46
+ const { concurrency } = this.cfg;
47
+ const fn = fn_;
48
+ fn.defer || (fn.defer = pDefer());
49
+ if (this.inFlight < concurrency) {
50
+ // There is room for more jobs. Can start immediately
51
+ this.inFlight++;
52
+ this.debug(`inFlight++ ${this.inFlight}/${concurrency}, queue ${this.queue.length}`);
53
+ fn()
54
+ .then(result => fn.defer.resolve(result))
55
+ .catch(err => {
56
+ this.cfg.logger.error(err);
57
+ if (this.cfg.errorMode === ErrorMode.SUPPRESS) {
58
+ fn.defer.resolve(); // resolve with `void`
59
+ }
60
+ else {
61
+ // Should be handled on the outside, otherwise it'll cause UnhandledRejection
62
+ fn.defer.reject(err);
63
+ }
64
+ })
65
+ .finally(() => {
66
+ this.inFlight--;
67
+ this.debug(`inFlight-- ${this.inFlight}/${concurrency}, queue ${this.queue.length}`);
68
+ // check if there's room to start next job
69
+ if (this.queue.length && this.inFlight <= concurrency) {
70
+ const nextFn = this.queue.shift();
71
+ void this.push(nextFn);
72
+ }
73
+ else {
74
+ if (this.inFlight === 0) {
75
+ this.debug('onIdle');
76
+ this.onIdleListeners.forEach(defer => defer.resolve());
77
+ this.onIdleListeners.length = 0; // empty the array
78
+ }
79
+ }
80
+ });
81
+ }
82
+ else {
83
+ this.queue.push(fn);
84
+ this.debug(`inFlight ${this.inFlight}/${concurrency}, queue++ ${this.queue.length}`);
85
+ }
86
+ return fn.defer;
87
+ }
88
+ }
@@ -3,7 +3,6 @@
3
3
  * Throws an Error if the Function is not resolved in a certain time.
4
4
  * If the Function rejects - passes this rejection further.
5
5
  */
6
- // eslint-disable-next-line @typescript-eslint/ban-types
7
6
  export function pTimeout(fn, opt) {
8
7
  // const fname = fn.name || 'function'
9
8
  const { timeout, name, onTimeout } = opt;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
- "version": "14.66.0",
3
+ "version": "14.69.1",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "build-prod": "build-prod-esm-cjs",
package/src/index.ts CHANGED
@@ -229,12 +229,16 @@ import {
229
229
  CommonLogFunction,
230
230
  CommonLogger,
231
231
  commonLoggerMinLevel,
232
- noopLogger,
232
+ commonLoggerNoop,
233
233
  commonLogLevelNumber,
234
+ commonLoggerPipe,
235
+ commonLoggerPrefix,
234
236
  } from './log/commonLogger'
235
237
  import { _safeJsonStringify } from './string/safeJsonStringify'
238
+ import { PQueue, PQueueCfg } from './promise/pQueue'
236
239
 
237
240
  export type {
241
+ PQueueCfg,
238
242
  MemoCache,
239
243
  PromiseDecoratorCfg,
240
244
  PromiseDecoratorResp,
@@ -466,7 +470,10 @@ export {
466
470
  _defineLazyProps,
467
471
  _lazyValue,
468
472
  commonLoggerMinLevel,
469
- noopLogger,
473
+ commonLoggerNoop,
470
474
  commonLogLevelNumber,
475
+ commonLoggerPipe,
476
+ commonLoggerPrefix,
471
477
  _safeJsonStringify,
478
+ PQueue,
472
479
  }
@@ -43,7 +43,7 @@ export interface CommonLogger {
43
43
  *
44
44
  * @experimental
45
45
  */
46
- export const noopLogger: CommonLogger = {
46
+ export const commonLoggerNoop: CommonLogger = {
47
47
  log: _noop,
48
48
  warn: _noop,
49
49
  error: _noop,
@@ -71,9 +71,41 @@ export function commonLoggerMinLevel(
71
71
  return logger
72
72
  }
73
73
 
74
+ if (level <= commonLogLevelNumber['log']) {
75
+ // All levels are kept
76
+ return logger
77
+ }
78
+
79
+ if (level > commonLogLevelNumber['error']) {
80
+ // "Log nothing" logger
81
+ return commonLoggerNoop
82
+ }
83
+
84
+ return {
85
+ log: _noop, // otherwise it is "log everything" logger (same logger as input)
86
+ warn: level <= commonLogLevelNumber['warn'] ? logger.warn.bind(logger) : _noop,
87
+ error: logger.error.bind(logger), // otherwise it's "log nothing" logger (same as noopLogger)
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Creates a "proxy" CommonLogger that pipes log messages to all provided sub-loggers.
93
+ */
94
+ export function commonLoggerPipe(loggers: CommonLogger[]): CommonLogger {
95
+ return {
96
+ log: (...args) => loggers.forEach(logger => logger.log(...args)),
97
+ warn: (...args) => loggers.forEach(logger => logger.warn(...args)),
98
+ error: (...args) => loggers.forEach(logger => logger.error(...args)),
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Creates a "child" CommonLogger with prefix (one or multiple).
104
+ */
105
+ export function commonLoggerPrefix(logger: CommonLogger, ...prefixes: any[]): CommonLogger {
74
106
  return {
75
- log: level <= commonLogLevelNumber['log'] ? (...args) => logger.log(...args) : _noop,
76
- warn: level <= commonLogLevelNumber['warn'] ? (...args) => logger.warn(...args) : _noop,
77
- error: level <= commonLogLevelNumber['error'] ? (...args) => logger.error(...args) : _noop,
107
+ log: (...args) => logger.log(...prefixes, ...args),
108
+ warn: (...args) => logger.warn(...prefixes, ...args),
109
+ error: (...args) => logger.error(...prefixes, ...args),
78
110
  }
79
111
  }
@@ -0,0 +1,143 @@
1
+ import { ErrorMode } from '../error/errorMode'
2
+ import { CommonLogger } from '../log/commonLogger'
3
+ import { DeferredPromise, pDefer } from './pDefer'
4
+
5
+ export interface PQueueCfg {
6
+ concurrency: number
7
+
8
+ /**
9
+ * Default: THROW_IMMEDIATELY
10
+ *
11
+ * THROW_AGGREGATED is not supported.
12
+ *
13
+ * SUPPRESS_ERRORS will still log errors via logger. It will resolve the `.push` promise with void.
14
+ */
15
+ errorMode?: ErrorMode
16
+
17
+ /**
18
+ * @default true
19
+ */
20
+ // autoStart?: boolean
21
+
22
+ /**
23
+ * Default to `console`
24
+ */
25
+ logger?: CommonLogger
26
+
27
+ /**
28
+ * If true - will LOG EVERYTHING:)
29
+ */
30
+ debug?: boolean
31
+
32
+ // logStatusChange?: boolean
33
+ // logSizeChange?: boolean
34
+
35
+ // timeout
36
+ }
37
+
38
+ export type PromiseReturningFunction<R> = () => Promise<R>
39
+
40
+ interface PromiseReturningFunctionWithDefer<R> extends PromiseReturningFunction<R> {
41
+ defer: DeferredPromise<R>
42
+ }
43
+
44
+ /**
45
+ * Inspired by: https://github.com/sindresorhus/p-queue
46
+ *
47
+ * Allows to push "jobs" to the queue and control its concurrency.
48
+ * Jobs are "promise-returning functions".
49
+ *
50
+ * API is @experimental
51
+ */
52
+ export class PQueue {
53
+ constructor(cfg: PQueueCfg) {
54
+ this.cfg = {
55
+ // concurrency: Number.MAX_SAFE_INTEGER,
56
+ errorMode: ErrorMode.THROW_IMMEDIATELY,
57
+ logger: console,
58
+ debug: false,
59
+ ...cfg,
60
+ }
61
+
62
+ if (!cfg.debug) {
63
+ this.debug = () => {}
64
+ }
65
+ }
66
+
67
+ private readonly cfg: Required<PQueueCfg>
68
+
69
+ private debug(...args: any[]): void {
70
+ this.cfg.logger.log(...args)
71
+ }
72
+
73
+ inFlight = 0
74
+ private queue: PromiseReturningFunction<any>[] = []
75
+ private onIdleListeners: DeferredPromise[] = []
76
+
77
+ get queueSize(): number {
78
+ return this.queue.length
79
+ }
80
+
81
+ /**
82
+ * Returns a Promise that resolves when the queue is Idle (next time, since the call).
83
+ * Resolves immediately in case the queue is Idle.
84
+ * Idle means 0 queue and 0 inFlight.
85
+ */
86
+ onIdle(): Promise<void> {
87
+ if (this.queue.length === 0) return Promise.resolve()
88
+
89
+ const listener = pDefer()
90
+ this.onIdleListeners.push(listener)
91
+ return listener
92
+ }
93
+
94
+ /**
95
+ * Push PromiseReturningFunction to the Queue.
96
+ * Returns a Promise that resolves (or rejects) with the return value from the Promise.
97
+ */
98
+ push<R>(fn_: PromiseReturningFunction<R>): Promise<R> {
99
+ const { concurrency } = this.cfg
100
+
101
+ const fn = fn_ as PromiseReturningFunctionWithDefer<R>
102
+ fn.defer ||= pDefer<R>()
103
+
104
+ if (this.inFlight < concurrency) {
105
+ // There is room for more jobs. Can start immediately
106
+ this.inFlight++
107
+ this.debug(`inFlight++ ${this.inFlight}/${concurrency}, queue ${this.queue.length}`)
108
+
109
+ fn()
110
+ .then(result => fn.defer.resolve(result))
111
+ .catch(err => {
112
+ this.cfg.logger.error(err)
113
+ if (this.cfg.errorMode === ErrorMode.SUPPRESS) {
114
+ fn.defer.resolve() // resolve with `void`
115
+ } else {
116
+ // Should be handled on the outside, otherwise it'll cause UnhandledRejection
117
+ fn.defer.reject(err)
118
+ }
119
+ })
120
+ .finally(() => {
121
+ this.inFlight--
122
+ this.debug(`inFlight-- ${this.inFlight}/${concurrency}, queue ${this.queue.length}`)
123
+
124
+ // check if there's room to start next job
125
+ if (this.queue.length && this.inFlight <= concurrency) {
126
+ const nextFn = this.queue.shift()!
127
+ void this.push(nextFn)
128
+ } else {
129
+ if (this.inFlight === 0) {
130
+ this.debug('onIdle')
131
+ this.onIdleListeners.forEach(defer => defer.resolve())
132
+ this.onIdleListeners.length = 0 // empty the array
133
+ }
134
+ }
135
+ })
136
+ } else {
137
+ this.queue.push(fn)
138
+ this.debug(`inFlight ${this.inFlight}/${concurrency}, queue++ ${this.queue.length}`)
139
+ }
140
+
141
+ return fn.defer
142
+ }
143
+ }
@@ -1,3 +1,5 @@
1
+ import { AnyFunction } from '../types'
2
+
1
3
  export interface PTimeoutOptions {
2
4
  /**
3
5
  * Timeout in milliseconds.
@@ -22,8 +24,7 @@ export interface PTimeoutOptions {
22
24
  * Throws an Error if the Function is not resolved in a certain time.
23
25
  * If the Function rejects - passes this rejection further.
24
26
  */
25
- // eslint-disable-next-line @typescript-eslint/ban-types
26
- export function pTimeout<T extends Function>(fn: T, opt: PTimeoutOptions): T {
27
+ export function pTimeout<T extends AnyFunction>(fn: T, opt: PTimeoutOptions): T {
27
28
  // const fname = fn.name || 'function'
28
29
  const { timeout, name, onTimeout } = opt
29
30