@dr.pogodin/react-global-state
Version:
Hook-based global state for React
91 lines (85 loc) • 3.12 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.cloneDeepForLog = cloneDeepForLog;
exports.escape = escape;
exports.hash = hash;
exports.isDebugMode = isDebugMode;
var _lodash = require("lodash");
// TODO: This (ForceT, LockT, and TypeLock) probably should be moved to JS Utils
// lib.
/**
* Given the type of state, `StateT`, and the type of state path, `PathT`,
* it evaluates the type of value at that path of the state, if it can be
* evaluated from the path type (it is possible when `PathT` is a string
* literal type, and `StateT` elements along this path have appropriate
* types); otherwise it falls back to the specified `UnknownT` type,
* which should be set either `never` (for input arguments), or `void`
* (for return types) - `never` and `void` in those places forbid assignments,
* and are not auto-inferred to more permissible types.
*
* BEWARE: When StateT is any the construct resolves to any for any string
* paths.
*/
/**
* Returns 'true' if debug logging should be performed; 'false' otherwise.
*
* BEWARE: The actual safeguards for the debug logging still should read
* if (process.env.NODE_ENV !== 'production' && isDebugMode()) {
* // Some debug logging
* }
* to ensure that debug code is stripped out by Webpack in production mode.
*
* @returns
* @ignore
*/
function isDebugMode() {
try {
return process.env.NODE_ENV !== 'production' && !!process.env.REACT_GLOBAL_STATE_DEBUG;
} catch {
return false;
}
}
const cloneDeepBailKeys = new Set();
/**
* Deep-clones given value for logging purposes, or returns the value itself
* if the previous clone attempt, with the same key, took more than 300ms
* (to avoid situations when large payload in the global state slows down
* development versions of the app due to the logging overhead).
*/
function cloneDeepForLog(value, key = '') {
if (cloneDeepBailKeys.has(key)) {
// eslint-disable-next-line no-console
console.warn(`The logged value won't be clonned (key "${key}").`);
return value;
}
const start = Date.now();
const res = (0, _lodash.cloneDeep)(value);
const time = Date.now() - start;
if (time > 300) {
// eslint-disable-next-line no-console
console.warn(`${time}ms spent to clone the logged value (key "${key}").`);
cloneDeepBailKeys.add(key);
}
return res;
}
/**
* Converts given value to an escaped string. For now, we are good with the most
* trivial escape logic:
* - '%' characters are replaced by '%0' code pair;
* - '/' characters are replaced by '%1' code pair.
*/
function escape(x) {
return typeof x === 'string' ? x.replace(/%/g, '%0').replace(/\//g, '%1') : x.toString();
}
/**
* Hashes given string array. For our current needs we are fine to go with
* the most trivial implementation, which probably should not be called "hash"
* in the strict sense: we just escape each given string to not include '/'
* characters, and then we join all those strings using '/' as the separator.
*/
function hash(items) {
return items.map(escape).join('/');
}
//# sourceMappingURL=utils.js.map