@mitm/common
Advanced tools
Comparing version 1.6.1 to 1.7.0
@@ -1,1 +0,51 @@ | ||
export declare function getStacktrace(): string[]; | ||
import { MonoTypeOperatorFunction } from 'rxjs'; | ||
declare global { | ||
/** | ||
* A global object containing debug utilities for development. | ||
* Make sure to use the debugHelpersConfig() from @mitm/webpack to make it available from the {@link debug} export | ||
* of this module. | ||
*/ | ||
namespace d { | ||
/** | ||
* A variable you can set to change the logging function used by the logging functions of {@link d}. | ||
* @default {@link console.debug} | ||
*/ | ||
let logger: (...args: unknown[]) => void; | ||
/** | ||
* A shortcut for console.debug. | ||
* Also, the function is not sensible to the `this` it's called with, so unlike console.debug(), it may be used | ||
* with any `this` context. | ||
* | ||
* @example | ||
* d.log('debug message'); | ||
* observable.pipe(tap(d.log)); | ||
*/ | ||
function log(...args: unknown[]): void; | ||
/** | ||
* A RxJS operator for logging what happens in an observable. | ||
* Place it in the pipe at the position you want depending on the info you'd like to log, and it will the | ||
* following events of the source's lifecycle: subscribe, unsubscribe, next, complete, error, finalize. | ||
* | ||
* @param name You can pass a name for the observable, so if you log many you can know where the event comes | ||
* from. If no name is passed, the function will use a number, that's incremented for each log$ use. | ||
*/ | ||
function log$<T>(name?: string): MonoTypeOperatorFunction<T>; | ||
/** | ||
* Logs the current stack trace (up to the last call site before logStack()). | ||
* Useful to know from where a piece of code is called. | ||
*/ | ||
function logStack(): void; | ||
} | ||
} | ||
/** | ||
* Gets the current stack trace as an array of strings representing each call. | ||
* The call of getStacktrace() itself is omitted. | ||
* | ||
* @param offset The number of calls to skip at the top of the stack (default 1, which means this function is skipped). | ||
*/ | ||
export declare function getStacktrace(offset?: number): string[]; | ||
/** | ||
* You generally don't want to import this variable, prefer the simpler "d" global variable. | ||
* @see d | ||
*/ | ||
export declare const debug: typeof d; |
164
index.esm.js
@@ -0,3 +1,67 @@ | ||
import { tap } from 'rxjs'; | ||
import { shareReplay } from 'rxjs/operators'; | ||
/** | ||
* Evaluates a value that may be a thunk (arity=0), or returns the value directly. | ||
*/ | ||
function evalThunk(thunk) { | ||
return typeof thunk == 'function' ? thunk() : thunk; | ||
} | ||
/** | ||
* If given an Array, returns it. | ||
* If given an object that's not an Array, return a new array with that object as the single element. | ||
*/ | ||
function normalizeToArray(arrayOrSingle) { | ||
return Array.isArray(arrayOrSingle) ? arrayOrSingle : [arrayOrSingle]; | ||
} | ||
/** | ||
* Checks if any of the given predicates is true, in sequence. | ||
* A predicate can be a thunk, returning the boolean, or a promise that resolves to the boolean. | ||
* Stops at the first predicate that returns true. | ||
*/ | ||
async function any(...conditions) { | ||
for (const condition of conditions) { | ||
if (await evalThunk(condition)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
/** | ||
* Checks if all the of the given predicates are true, in sequence. | ||
* A predicate can be a thunk, returning the boolean, or a promise that resolves to the boolean. | ||
* Stops at the first predicate that returns false. | ||
*/ | ||
async function all(...conditions) { | ||
for (const condition of conditions) { | ||
if (!(await evalThunk(condition))) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
/** | ||
* Returns a new array with elements of the first array grouped by two as a tuple array. | ||
* If the array length is not even, a value can be provided to fill the last slot, otherwise `undefined` is used. | ||
* | ||
* @example | ||
* arrayPairwise([1, 2, 3, 4]); // [[1, 2], [3, 4]] | ||
* arrayPairwise([1, 2, 3]); // [[1, 2], [3, undefined]] | ||
* arrayPairwise([1, 2, 3], 'missing value'); // [[1, 2], [3, 'missing value']] | ||
*/ | ||
function arrayPairwise(array, defaultLastValue) { | ||
return array.reduce((result, value, index) => { | ||
const pair = index <= array.length - 2 ? array.slice(index, index + 2) : [array[index], defaultLastValue]; | ||
index % 2 === 0 && result.push(pair); | ||
return result; | ||
}, []); | ||
} | ||
class Stopwatch { | ||
@@ -18,3 +82,6 @@ constructor() { | ||
start() { | ||
if (this.isRunning) return; | ||
if (this.isRunning) { | ||
return; | ||
} | ||
this.isRunning = true; | ||
@@ -25,3 +92,6 @@ this.timestamps.push(new Date().valueOf()); | ||
stop() { | ||
if (!this.isRunning) return; | ||
if (!this.isRunning) { | ||
return; | ||
} | ||
this.isRunning = false; | ||
@@ -70,72 +140,40 @@ this.timestamps.push(new Date().valueOf()); | ||
/* eslint-disable no-console,no-restricted-globals */ | ||
/** | ||
* Evaluates a value that may be a thunk (arity=0), or returns the value directly. | ||
* Gets the current stack trace as an array of strings representing each call. | ||
* The call of getStacktrace() itself is omitted. | ||
* | ||
* @param offset The number of calls to skip at the top of the stack (default 1, which means this function is skipped). | ||
*/ | ||
function evalThunk(thunk) { | ||
return typeof thunk == 'function' ? thunk() : thunk; | ||
} | ||
/** | ||
* If given an Array, returns it. | ||
* If given an object that's not an Array, return a new array with that object as the single element. | ||
*/ | ||
function getStacktrace(offset = 1) { | ||
var _a, _b; // .slice skips "Error: msg" line and this call on the stack | ||
function normalizeToArray(arrayOrSingle) { | ||
return Array.isArray(arrayOrSingle) ? arrayOrSingle : [arrayOrSingle]; | ||
} | ||
/** | ||
* Checks if any of the given predicates is true, in sequence. | ||
* A predicate can be a thunk, returning the boolean, or a promise that resolves to the boolean. | ||
* Stops at the first predicate that returns true. | ||
*/ | ||
async function any(...conditions) { | ||
for (const condition of conditions) { | ||
if (await evalThunk(condition)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
return (_b = (_a = new Error().stack) === null || _a === void 0 ? void 0 : _a.split('\n').slice(1 + offset).map(line => line.trim())) !== null && _b !== void 0 ? _b : []; | ||
} | ||
let unnamedObservableCounter = 0; | ||
/** | ||
* Checks if all the of the given predicates are true, in sequence. | ||
* A predicate can be a thunk, returning the boolean, or a promise that resolves to the boolean. | ||
* Stops at the first predicate that returns false. | ||
* You generally don't want to import this variable, prefer the simpler "d" global variable. | ||
* @see d | ||
*/ | ||
async function all(...conditions) { | ||
for (const condition of conditions) { | ||
if (!(await evalThunk(condition))) { | ||
return false; | ||
} | ||
} | ||
const debug = { | ||
logger: console.debug, | ||
log: (...args) => debug.logger.apply(console, args), | ||
logStack: () => debug.logger.apply(console, [getStacktrace(2).join('\n')]), | ||
log$: (name = (++unnamedObservableCounter).toString()) => source => source.pipe(tap({ | ||
subscribe: logObservableEvent.bind(void 0, name, 'subscribe'), | ||
unsubscribe: logObservableEvent.bind(void 0, name, 'unsubscribe'), | ||
next: logObservableEvent.bind(void 0, name, 'next'), | ||
complete: logObservableEvent.bind(void 0, name, 'complete'), | ||
error: logObservableEvent.bind(void 0, name, 'error'), | ||
finalize: logObservableEvent.bind(void 0, name, 'finalize') | ||
})) | ||
}; | ||
return true; | ||
function logObservableEvent(name, event, ...args) { | ||
debug.log(`$ [${name}] ${event}${args.length ? ':' : ''}`, ...args); | ||
} | ||
/** | ||
* Returns a new array with elements of the first array grouped by two as a tuple array. | ||
* If the array length is not even, a value can be provided to fill the last slot, otherwise `undefined` is used. | ||
* | ||
* @example | ||
* arrayPairwise([1, 2, 3, 4]); // [[1, 2], [3, 4]] | ||
* arrayPairwise([1, 2, 3]); // [[1, 2], [3, undefined]] | ||
* arrayPairwise([1, 2, 3], 'missing value'); // [[1, 2], [3, 'missing value']] | ||
*/ | ||
function arrayPairwise(array, defaultLastValue) { | ||
return array.reduce((result, value, index) => { | ||
const pair = index <= array.length - 2 ? array.slice(index, index + 2) : [array[index], defaultLastValue]; | ||
index % 2 === 0 && result.push(pair); | ||
return result; | ||
}, []); | ||
} | ||
function getStacktrace() { | ||
var _a, _b; // .slice skips "Error: msg" line and this call on the stack | ||
return (_b = (_a = new Error().stack) === null || _a === void 0 ? void 0 : _a.split('\n').slice(2).map(line => line.trim())) !== null && _b !== void 0 ? _b : []; | ||
} | ||
/** | ||
@@ -218,3 +256,3 @@ * Like the "throw" keyword, but as a function - useful to throw inside or as an expression. | ||
function hasKey(metadata, key) { | ||
return !!metadata && metadata.hasOwnProperty(key); | ||
return !!metadata && key in metadata; | ||
} | ||
@@ -246,3 +284,3 @@ function getValue(documentId, metadata, key, typeGuard = val => typeof val == 'string') { | ||
if (!metadata.hasOwnProperty(key)) { | ||
if (!(key in metadata)) { | ||
throw new MetadataKeyError(documentId, key, 'key is missing'); | ||
@@ -467,2 +505,2 @@ } | ||
export { MetadataError, MetadataKeyError, RolesHierarchy, Stopwatch, StopwatchMutexMap, all, any, arrayContainsId, arrayPairwise, ensureBoolean, ensureInEnum, ensureNotNull, ensureNumber, ensureString, equalIds, ethrow, evalThunk, filterOutNullArrayEntries, getStacktrace, getUnknownValue, getValue, hasKey, normalizeToArray, requireValue, shareReplayOne, swallowException, throwThisShouldNeverHappenError, throwUnexpectedTypeError, wait, waitThenReject }; | ||
export { MetadataError, MetadataKeyError, RolesHierarchy, Stopwatch, StopwatchMutexMap, all, any, arrayContainsId, arrayPairwise, debug, ensureBoolean, ensureInEnum, ensureNotNull, ensureNumber, ensureString, equalIds, ethrow, evalThunk, filterOutNullArrayEntries, getStacktrace, getUnknownValue, getValue, hasKey, normalizeToArray, requireValue, shareReplayOne, swallowException, throwThisShouldNeverHappenError, throwUnexpectedTypeError, wait, waitThenReject }; |
275
index.umd.js
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('rxjs/operators')) : | ||
typeof define === 'function' && define.amd ? define(['exports', 'rxjs/operators'], factory) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Common = {}, global.operators)); | ||
})(this, (function (exports, operators) { 'use strict'; | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('rxjs'), require('rxjs/operators')) : | ||
typeof define === 'function' && define.amd ? define(['exports', 'rxjs', 'rxjs/operators'], factory) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Common = {}, global.rxjs, global.operators)); | ||
})(this, (function (exports, rxjs, operators) { 'use strict'; | ||
var Stopwatch = | ||
/** @class */ | ||
function () { | ||
function Stopwatch() { | ||
this.isRunning = false; | ||
this.timestamps = []; | ||
this.addedMilliseconds = []; | ||
} | ||
Stopwatch.prototype.elapsed = function (allowNegative) { | ||
if (allowNegative === void 0) { | ||
allowNegative = false; | ||
} | ||
var startStopPairs = arrayPairwise(this.timestamps, new Date().valueOf()); | ||
var elapsed = startStopPairs.reduce(function (count, _a) { | ||
var start = _a[0], | ||
stop = _a[1]; | ||
return count + stop - start; | ||
}, 0); | ||
var advanced = this.addedMilliseconds.reduce(function (count, added) { | ||
return count + added; | ||
}, elapsed); | ||
return allowNegative ? advanced : Math.max(0, advanced); | ||
}; | ||
Stopwatch.prototype.start = function () { | ||
if (this.isRunning) return; | ||
this.isRunning = true; | ||
this.timestamps.push(new Date().valueOf()); | ||
}; | ||
Stopwatch.prototype.stop = function () { | ||
if (!this.isRunning) return; | ||
this.isRunning = false; | ||
this.timestamps.push(new Date().valueOf()); | ||
}; | ||
Stopwatch.prototype.reset = function (stop) { | ||
if (stop === void 0) { | ||
stop = true; | ||
} | ||
this.timestamps = []; | ||
this.addedMilliseconds = []; | ||
if (!stop && this.isRunning) { | ||
// restart | ||
this.isRunning = false; | ||
this.start(); | ||
} | ||
}; | ||
Stopwatch.prototype.advanceBy = function (millis) { | ||
this.addedMilliseconds.push(millis); | ||
}; | ||
return Stopwatch; | ||
}(); | ||
/*! ***************************************************************************** | ||
@@ -136,35 +76,12 @@ Copyright (c) Microsoft Corporation. | ||
/** | ||
* Hosts multiple stopwatches, identified by a key. | ||
* Does not allow more than one stopwatch running at a given time, as long as the {@link start} method from this class | ||
* is being used to start a stopwatch. | ||
*/ | ||
var StopwatchMutexMap = | ||
/** @class */ | ||
function (_super) { | ||
__extends(StopwatchMutexMap, _super); | ||
function StopwatchMutexMap() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
StopwatchMutexMap.prototype.for = function (key) { | ||
if (!this.has(key)) { | ||
this.set(key, new Stopwatch()); | ||
function __spreadArray(to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
} | ||
return this.get(key); | ||
}; | ||
StopwatchMutexMap.prototype.start = function (key) { | ||
this.forEach(function (stopwatch) { | ||
return stopwatch.stop(); | ||
}); | ||
this.for(key).start(); | ||
}; | ||
return StopwatchMutexMap; | ||
}(Map); | ||
/** | ||
@@ -311,11 +228,168 @@ * Evaluates a value that may be a thunk (arity=0), or returns the value directly. | ||
function getStacktrace() { | ||
var _a, _b; // .slice skips "Error: msg" line and this call on the stack | ||
var Stopwatch = | ||
/** @class */ | ||
function () { | ||
function Stopwatch() { | ||
this.isRunning = false; | ||
this.timestamps = []; | ||
this.addedMilliseconds = []; | ||
} | ||
Stopwatch.prototype.elapsed = function (allowNegative) { | ||
if (allowNegative === void 0) { | ||
allowNegative = false; | ||
} | ||
return (_b = (_a = new Error().stack) === null || _a === void 0 ? void 0 : _a.split('\n').slice(2).map(function (line) { | ||
var startStopPairs = arrayPairwise(this.timestamps, new Date().valueOf()); | ||
var elapsed = startStopPairs.reduce(function (count, _a) { | ||
var start = _a[0], | ||
stop = _a[1]; | ||
return count + stop - start; | ||
}, 0); | ||
var advanced = this.addedMilliseconds.reduce(function (count, added) { | ||
return count + added; | ||
}, elapsed); | ||
return allowNegative ? advanced : Math.max(0, advanced); | ||
}; | ||
Stopwatch.prototype.start = function () { | ||
if (this.isRunning) { | ||
return; | ||
} | ||
this.isRunning = true; | ||
this.timestamps.push(new Date().valueOf()); | ||
}; | ||
Stopwatch.prototype.stop = function () { | ||
if (!this.isRunning) { | ||
return; | ||
} | ||
this.isRunning = false; | ||
this.timestamps.push(new Date().valueOf()); | ||
}; | ||
Stopwatch.prototype.reset = function (stop) { | ||
if (stop === void 0) { | ||
stop = true; | ||
} | ||
this.timestamps = []; | ||
this.addedMilliseconds = []; | ||
if (!stop && this.isRunning) { | ||
// restart | ||
this.isRunning = false; | ||
this.start(); | ||
} | ||
}; | ||
Stopwatch.prototype.advanceBy = function (millis) { | ||
this.addedMilliseconds.push(millis); | ||
}; | ||
return Stopwatch; | ||
}(); | ||
/** | ||
* Hosts multiple stopwatches, identified by a key. | ||
* Does not allow more than one stopwatch running at a given time, as long as the {@link start} method from this class | ||
* is being used to start a stopwatch. | ||
*/ | ||
var StopwatchMutexMap = | ||
/** @class */ | ||
function (_super) { | ||
__extends(StopwatchMutexMap, _super); | ||
function StopwatchMutexMap() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
StopwatchMutexMap.prototype.for = function (key) { | ||
if (!this.has(key)) { | ||
this.set(key, new Stopwatch()); | ||
} | ||
return this.get(key); | ||
}; | ||
StopwatchMutexMap.prototype.start = function (key) { | ||
this.forEach(function (stopwatch) { | ||
return stopwatch.stop(); | ||
}); | ||
this.for(key).start(); | ||
}; | ||
return StopwatchMutexMap; | ||
}(Map); | ||
/** | ||
* Gets the current stack trace as an array of strings representing each call. | ||
* The call of getStacktrace() itself is omitted. | ||
* | ||
* @param offset The number of calls to skip at the top of the stack (default 1, which means this function is skipped). | ||
*/ | ||
function getStacktrace(offset) { | ||
var _a, _b; | ||
if (offset === void 0) { | ||
offset = 1; | ||
} // .slice skips "Error: msg" line and this call on the stack | ||
return (_b = (_a = new Error().stack) === null || _a === void 0 ? void 0 : _a.split('\n').slice(1 + offset).map(function (line) { | ||
return line.trim(); | ||
})) !== null && _b !== void 0 ? _b : []; | ||
} | ||
var unnamedObservableCounter = 0; | ||
/** | ||
* You generally don't want to import this variable, prefer the simpler "d" global variable. | ||
* @see d | ||
*/ | ||
var debug = { | ||
logger: console.debug, | ||
log: function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
return debug.logger.apply(console, args); | ||
}, | ||
logStack: function () { | ||
return debug.logger.apply(console, [getStacktrace(2).join('\n')]); | ||
}, | ||
log$: function (name) { | ||
if (name === void 0) { | ||
name = (++unnamedObservableCounter).toString(); | ||
} | ||
return function (source) { | ||
return source.pipe(rxjs.tap({ | ||
subscribe: logObservableEvent.bind(void 0, name, 'subscribe'), | ||
unsubscribe: logObservableEvent.bind(void 0, name, 'unsubscribe'), | ||
next: logObservableEvent.bind(void 0, name, 'next'), | ||
complete: logObservableEvent.bind(void 0, name, 'complete'), | ||
error: logObservableEvent.bind(void 0, name, 'error'), | ||
finalize: logObservableEvent.bind(void 0, name, 'finalize') | ||
})); | ||
}; | ||
} | ||
}; | ||
function logObservableEvent(name, event) { | ||
var args = []; | ||
for (var _i = 2; _i < arguments.length; _i++) { | ||
args[_i - 2] = arguments[_i]; | ||
} | ||
debug.log.apply(debug, __spreadArray(["$ [".concat(name, "] ").concat(event).concat(args.length ? ':' : '')], args, false)); | ||
} | ||
/** | ||
@@ -417,3 +491,3 @@ * Like the "throw" keyword, but as a function - useful to throw inside or as an expression. | ||
function hasKey(metadata, key) { | ||
return !!metadata && metadata.hasOwnProperty(key); | ||
return !!metadata && key in metadata; | ||
} | ||
@@ -459,3 +533,3 @@ function getValue(documentId, metadata, key, typeGuard) { | ||
if (!metadata.hasOwnProperty(key)) { | ||
if (!(key in metadata)) { | ||
throw new MetadataKeyError(documentId, key, 'key is missing'); | ||
@@ -720,2 +794,3 @@ } | ||
exports.arrayPairwise = arrayPairwise; | ||
exports.debug = debug; | ||
exports.ensureBoolean = ensureBoolean; | ||
@@ -722,0 +797,0 @@ exports.ensureInEnum = ensureInEnum; |
@@ -1,1 +0,1 @@ | ||
export declare type Type<T> = new (...args: any[]) => T; | ||
export declare type Type<T> = new (...args: unknown[]) => T; |
{ | ||
"name": "@mitm/common", | ||
"version": "1.6.1", | ||
"version": "1.7.0", | ||
"peerDependencies": { | ||
@@ -5,0 +5,0 @@ "rxjs": "^7.4.0" |
56037
1388