@naturalcycles/js-lib
Advanced tools
Comparing version 3.2.0 to 4.0.0
@@ -0,1 +1,19 @@ | ||
# [4.0.0](https://github.com/NaturalCycles/js-lib/compare/v3.2.0...v4.0.0) (2019-03-09) | ||
### Code Refactoring | ||
* "flatten" utils into functions ([eba7d97](https://github.com/NaturalCycles/js-lib/commit/eba7d97)) | ||
### BREAKING CHANGES | ||
* all "utils" from this package are now flattened and just their functions are exported. | ||
Example. | ||
Before: objectUtil.by() | ||
After: by() | ||
Before: import { objectUtil } from '@naturalcycles/js-lib' | ||
After: import { by } from '@naturalcycles/js-lib' | ||
# [3.2.0](https://github.com/NaturalCycles/js-lib/compare/v3.1.0...v3.2.0) (2019-03-08) | ||
@@ -2,0 +20,0 @@ |
import { memo } from './decorators/memo.decorator'; | ||
import { memoCache } from './decorators/memoCache.decorator'; | ||
import { AppError } from './error/app.error'; | ||
import { errorSharedUtil } from './error/error.shared.util'; | ||
import { anyToErrorMessage, anyToErrorObject, appErrorToErrorObject, appErrorToHttpError, errorObjectToAppError, errorObjectToHttpError, errorToErrorObject, } from './error/error.util'; | ||
import { HttpError } from './error/http.error'; | ||
import { deepFreeze, silentConsole } from './testing/test.shared.util'; | ||
import { objectUtil } from './util/object.util'; | ||
import { randomSharedUtil } from './util/random.shared.util'; | ||
import { scriptSharedUtil } from './util/script.shared.util'; | ||
import { stringSharedUtil } from './util/string.shared.util'; | ||
export { memo, memoCache, AppError, HttpError, deepFreeze, silentConsole, errorSharedUtil, objectUtil, randomSharedUtil, scriptSharedUtil, stringSharedUtil, }; | ||
import { arrayToHash, by, classToPlain, deepCopy, deepEquals, deepFreeze, deepTrim, filterEmptyStringValues, filterFalsyValues, filterUndefinedValues, filterValues, getKeyByValue, invertMap, invertObject, isEmptyObject, isObject, mask, mergeDeep, objectNullValuesToUndefined, pick, sortObjectDeep, transformValues, unsetValue, } from './util/object.util'; | ||
import { randomInt } from './util/random.util'; | ||
import { loadScript } from './util/script.util'; | ||
import { capitalizeFirstLetter, lowercaseFirstLetter, removeWhitespace } from './util/string.util'; | ||
import { silentConsole } from './util/test.util'; | ||
export { memo, memoCache, AppError, HttpError, silentConsole, randomInt, loadScript, capitalizeFirstLetter, lowercaseFirstLetter, removeWhitespace, pick, filterFalsyValues, filterEmptyStringValues, filterUndefinedValues, filterValues, transformValues, objectNullValuesToUndefined, deepEquals, deepCopy, isObject, isEmptyObject, mergeDeep, deepTrim, sortObjectDeep, unsetValue, mask, arrayToHash, classToPlain, getKeyByValue, invertObject, invertMap, by, deepFreeze, anyToErrorMessage, anyToErrorObject, errorToErrorObject, errorObjectToAppError, errorObjectToHttpError, appErrorToErrorObject, appErrorToHttpError, }; | ||
//# sourceMappingURL=index.js.map |
@@ -1,203 +0,213 @@ | ||
export class ObjectUtil { | ||
// Picks just allowed fields and no other fields | ||
// pick<T> (obj: any, fields: string[], initialObject = {}): T { | ||
pick(obj, fields, initialObject = {}) { | ||
if (!obj || !fields || !fields.length) | ||
return obj; | ||
const o = initialObject; | ||
fields.forEach(k => { | ||
if (k in obj) | ||
o[k] = obj[k]; | ||
// Picks just allowed fields and no other fields | ||
// pick<T> (obj: any, fields: string[], initialObject = {}): T { | ||
export function pick(obj, fields, initialObject = {}) { | ||
if (!obj || !fields || !fields.length) | ||
return obj; | ||
const o = initialObject; | ||
fields.forEach(k => { | ||
if (k in obj) | ||
o[k] = obj[k]; | ||
}); | ||
return o; | ||
} | ||
/** | ||
* Does NOT mutate (unless "mutate" flag is set) | ||
* Removes "falsy" value from the object. | ||
*/ | ||
export function filterFalsyValues(_obj, mutate = false) { | ||
return filterValues(_obj, (k, v) => !!v, mutate); | ||
} | ||
export function filterEmptyStringValues(_obj, mutate = false) { | ||
return filterValues(_obj, (k, v) => v !== '', mutate); | ||
} | ||
export function filterUndefinedValues(_obj, mutate = false) { | ||
return filterValues(_obj, (k, v) => v !== undefined && v !== null, mutate); | ||
} | ||
export function filterValues(_obj, predicate, mutate = false) { | ||
if (!isObject(_obj)) | ||
return _obj; | ||
const o = mutate ? _obj : Object.assign({}, _obj); | ||
Object.keys(o).forEach(k => { | ||
const keep = predicate(k, o[k]); | ||
if (!keep) | ||
delete o[k]; | ||
}); | ||
return o; | ||
} | ||
export function transformValues(_obj, transformFn, mutate = false) { | ||
if (!isObject(_obj)) | ||
return _obj; | ||
const o = mutate ? _obj : Object.assign({}, _obj); | ||
Object.keys(o).forEach(k => { | ||
o[k] = transformFn(k, o[k]); | ||
}); | ||
return o; | ||
} | ||
export function objectNullValuesToUndefined(_obj, mutate = false) { | ||
return transformValues(_obj, (k, v) => { | ||
if (v === null) | ||
return undefined; | ||
return v; | ||
}, mutate); | ||
} | ||
export function deepEquals(a, b) { | ||
return JSON.stringify(sortObjectDeep(a)) === JSON.stringify(sortObjectDeep(b)); | ||
} | ||
/** | ||
* Deep copy object (by json parse/stringify). | ||
*/ | ||
export function deepCopy(o) { | ||
return JSON.parse(JSON.stringify(o)); | ||
} | ||
export function isObject(item) { | ||
return (item && typeof item === 'object' && !Array.isArray(item) && item !== null) || false; | ||
} | ||
export function isEmptyObject(obj) { | ||
return obj && obj.constructor === Object && Object.keys(obj).length === 0; | ||
} | ||
// from: https://gist.github.com/Salakar/1d7137de9cb8b704e48a | ||
export function mergeDeep(target, source) { | ||
if (isObject(target) && isObject(source)) { | ||
Object.keys(source).forEach(key => { | ||
if (isObject(source[key])) { | ||
if (!target[key]) | ||
Object.assign(target, { [key]: {} }); | ||
mergeDeep(target[key], source[key]); | ||
} | ||
else { | ||
Object.assign(target, { [key]: source[key] }); | ||
} | ||
}); | ||
return o; | ||
} | ||
/** | ||
* Does NOT mutate (unless "mutate" flag is set) | ||
* Removes "falsy" value from the object. | ||
*/ | ||
filterFalsyValues(_obj, mutate = false) { | ||
return this.filterValues(_obj, (k, v) => !!v, mutate); | ||
} | ||
filterEmptyStringValues(_obj, mutate = false) { | ||
return this.filterValues(_obj, (k, v) => v !== '', mutate); | ||
} | ||
filterUndefinedValues(_obj, mutate = false) { | ||
return this.filterValues(_obj, (k, v) => v !== undefined && v !== null, mutate); | ||
} | ||
filterValues(_obj, predicate, mutate = false) { | ||
if (!this.isObject(_obj)) | ||
return _obj; | ||
const o = mutate ? _obj : Object.assign({}, _obj); | ||
Object.keys(o).forEach(k => { | ||
const keep = predicate(k, o[k]); | ||
if (!keep) | ||
delete o[k]; | ||
}); | ||
return target; | ||
} | ||
/** | ||
* Mutates | ||
*/ | ||
export function deepTrim(o) { | ||
if (!o) | ||
return o; | ||
if (typeof o === 'string') { | ||
return o.trim(); | ||
} | ||
transformValues(_obj, transformFn, mutate = false) { | ||
if (!this.isObject(_obj)) | ||
return _obj; | ||
const o = mutate ? _obj : Object.assign({}, _obj); | ||
else if (typeof o === 'object') { | ||
Object.keys(o).forEach(k => { | ||
o[k] = transformFn(k, o[k]); | ||
o[k] = deepTrim(o[k]); | ||
}); | ||
return o; | ||
} | ||
objectNullValuesToUndefined(_obj, mutate = false) { | ||
return this.transformValues(_obj, (k, v) => { | ||
if (v === null) | ||
return undefined; | ||
return v; | ||
}, mutate); | ||
return o; | ||
} | ||
function defaultSortFn(a, b) { | ||
return a.localeCompare(b); | ||
} | ||
// based on: https://github.com/IndigoUnited/js-deep-sort-object | ||
export function sortObjectDeep(o) { | ||
// array | ||
if (Array.isArray(o)) { | ||
return o.map(i => sortObjectDeep(i)); | ||
} | ||
deepEquals(a, b) { | ||
return JSON.stringify(this.sortObjectDeep(a)) === JSON.stringify(this.sortObjectDeep(b)); | ||
if (isObject(o)) { | ||
const out = {}; | ||
Object.keys(o) | ||
.sort((a, b) => defaultSortFn(a, b)) | ||
.forEach(k => { | ||
out[k] = sortObjectDeep(o[k]); | ||
}); | ||
return out; | ||
} | ||
/** | ||
* Deep copy object (by json parse/stringify). | ||
*/ | ||
deepCopy(o) { | ||
return JSON.parse(JSON.stringify(o)); | ||
return o; | ||
} | ||
// from: https://github.com/jonschlinkert/unset-value | ||
// mutates obj | ||
export function unsetValue(obj, prop) { | ||
if (!isObject(obj)) { | ||
return; | ||
} | ||
isObject(item) { | ||
return (item && typeof item === 'object' && !Array.isArray(item) && item !== null) || false; | ||
if (obj.hasOwnProperty(prop)) { | ||
delete obj[prop]; | ||
return; | ||
} | ||
isEmptyObject(obj) { | ||
return obj && obj.constructor === Object && Object.keys(obj).length === 0; | ||
const segs = prop.split('.'); | ||
let last = segs.pop(); | ||
while (segs.length && segs[segs.length - 1].slice(-1) === '\\') { | ||
last = segs.pop().slice(0, -1) + '.' + last; | ||
} | ||
// from: https://gist.github.com/Salakar/1d7137de9cb8b704e48a | ||
mergeDeep(target, source) { | ||
if (this.isObject(target) && this.isObject(source)) { | ||
Object.keys(source).forEach(key => { | ||
if (this.isObject(source[key])) { | ||
if (!target[key]) | ||
Object.assign(target, { [key]: {} }); | ||
this.mergeDeep(target[key], source[key]); | ||
} | ||
else { | ||
Object.assign(target, { [key]: source[key] }); | ||
} | ||
}); | ||
} | ||
return target; | ||
while (segs.length && isObject(obj)) { | ||
const k = (prop = segs.shift()); | ||
obj = obj[k]; | ||
} | ||
/** | ||
* Mutates | ||
*/ | ||
deepTrim(o) { | ||
if (!o) | ||
return o; | ||
if (typeof o === 'string') { | ||
return o.trim(); | ||
} | ||
else if (typeof o === 'object') { | ||
Object.keys(o).forEach(k => { | ||
o[k] = this.deepTrim(o[k]); | ||
}); | ||
} | ||
if (!isObject(obj)) | ||
return; | ||
delete obj[last]; | ||
} | ||
/** | ||
* Returns object with filtered keys from "exclude" array. | ||
* E.g: | ||
* mask({...}, [ | ||
* 'account.id', | ||
* 'account.updated', | ||
* ]) | ||
* | ||
* Pass deepCopy if you want to protect the whole object (not just first level) from mutation. | ||
*/ | ||
export function mask(_o, exclude, _deepCopy = false) { | ||
let o = Object.assign({}, _o); | ||
if (_deepCopy) | ||
o = deepCopy(o); | ||
exclude.forEach(e => { | ||
// eval(`delete o.${e}`) | ||
unsetValue(o, e); | ||
}); | ||
return o; | ||
} | ||
/** | ||
* Turns ['a', b'] into {a: true, b: true} | ||
*/ | ||
export function arrayToHash(a = []) { | ||
return a.reduce((o, item) => { | ||
o[item] = true; | ||
return o; | ||
} | ||
defaultSortFn(a, b) { | ||
return a.localeCompare(b); | ||
} | ||
// based on: https://github.com/IndigoUnited/js-deep-sort-object | ||
sortObjectDeep(o) { | ||
// array | ||
if (Array.isArray(o)) { | ||
return o.map(i => this.sortObjectDeep(i)); | ||
}, {}); | ||
} | ||
export function classToPlain(obj = {}) { | ||
return JSON.parse(JSON.stringify(obj)); | ||
} | ||
export function getKeyByValue(object, value) { | ||
if (!isObject(object)) | ||
return; | ||
return Object.keys(object).find(k => object[k] === value); | ||
} | ||
export function invertObject(o) { | ||
const inv = {}; | ||
Object.keys(o).forEach(k => { | ||
inv[o[k]] = k; | ||
}); | ||
return inv; | ||
} | ||
export function invertMap(m) { | ||
const inv = new Map(); | ||
m.forEach((v, k) => inv.set(v, k)); | ||
return inv; | ||
} | ||
export function by(items = [], by) { | ||
const r = {}; | ||
items.forEach((item) => { | ||
if (item[by]) | ||
r[item[by]] = item; | ||
}); | ||
return r; | ||
} | ||
// Source: https://github.com/substack/deep-freeze/blob/master/index.js | ||
export function deepFreeze(o) { | ||
Object.freeze(o); | ||
Object.getOwnPropertyNames(o).forEach(prop => { | ||
if (o.hasOwnProperty(prop) && | ||
o[prop] !== null && | ||
(typeof o[prop] === 'object' || typeof o[prop] === 'function') && | ||
!Object.isFrozen(o[prop])) { | ||
deepFreeze(o[prop]); | ||
} | ||
if (this.isObject(o)) { | ||
const out = {}; | ||
Object.keys(o) | ||
.sort((a, b) => this.defaultSortFn(a, b)) | ||
.forEach(k => { | ||
out[k] = this.sortObjectDeep(o[k]); | ||
}); | ||
return out; | ||
} | ||
return o; | ||
} | ||
// from: https://github.com/jonschlinkert/unset-value | ||
// mutates obj | ||
unsetValue(obj, prop) { | ||
if (!this.isObject(obj)) { | ||
return; | ||
} | ||
if (obj.hasOwnProperty(prop)) { | ||
delete obj[prop]; | ||
return; | ||
} | ||
const segs = prop.split('.'); | ||
let last = segs.pop(); | ||
while (segs.length && segs[segs.length - 1].slice(-1) === '\\') { | ||
last = segs.pop().slice(0, -1) + '.' + last; | ||
} | ||
while (segs.length && this.isObject(obj)) { | ||
const k = (prop = segs.shift()); | ||
obj = obj[k]; | ||
} | ||
if (!this.isObject(obj)) | ||
return; | ||
delete obj[last]; | ||
} | ||
/** | ||
* Returns object with filtered keys from "exclude" array. | ||
* E.g: | ||
* mask({...}, [ | ||
* 'account.id', | ||
* 'account.updated', | ||
* ]) | ||
* | ||
* Pass deepCopy if you want to protect the whole object (not just first level) from mutation. | ||
*/ | ||
mask(_o, exclude, deepCopy = false) { | ||
let o = Object.assign({}, _o); | ||
if (deepCopy) | ||
o = this.deepCopy(o); | ||
exclude.forEach(e => { | ||
// eval(`delete o.${e}`) | ||
this.unsetValue(o, e); | ||
}); | ||
return o; | ||
} | ||
/** | ||
* Turns ['a', b'] into {a: true, b: true} | ||
*/ | ||
arrayToHash(a = []) { | ||
return a.reduce((o, item) => { | ||
o[item] = true; | ||
return o; | ||
}, {}); | ||
} | ||
classToPlain(obj = {}) { | ||
return JSON.parse(JSON.stringify(obj)); | ||
} | ||
getKeyByValue(object, value) { | ||
if (!this.isObject(object)) | ||
return; | ||
return Object.keys(object).find(k => object[k] === value); | ||
} | ||
invertObject(o) { | ||
const inv = {}; | ||
Object.keys(o).forEach(k => { | ||
inv[o[k]] = k; | ||
}); | ||
return inv; | ||
} | ||
invertMap(m) { | ||
const inv = new Map(); | ||
m.forEach((v, k) => inv.set(v, k)); | ||
return inv; | ||
} | ||
by(items = [], by) { | ||
const r = {}; | ||
items.forEach((item) => { | ||
if (item[by]) | ||
r[item[by]] = item; | ||
}); | ||
return r; | ||
} | ||
}); | ||
return o; | ||
} | ||
export const objectUtil = new ObjectUtil(); | ||
//# sourceMappingURL=object.util.js.map |
@@ -5,10 +5,10 @@ import { memo } from './decorators/memo.decorator'; | ||
import { ErrorData, ErrorObject, ErrorResponse, HttpErrorData, HttpErrorResponse } from './error/error.model'; | ||
import { errorSharedUtil } from './error/error.shared.util'; | ||
import { anyToErrorMessage, anyToErrorObject, appErrorToErrorObject, appErrorToHttpError, errorObjectToAppError, errorObjectToHttpError, errorToErrorObject } from './error/error.util'; | ||
import { HttpError } from './error/http.error'; | ||
import { deepFreeze, silentConsole } from './testing/test.shared.util'; | ||
import { ClassType, PromiseMap, StringMap } from './types'; | ||
import { objectUtil } from './util/object.util'; | ||
import { randomSharedUtil } from './util/random.shared.util'; | ||
import { scriptSharedUtil } from './util/script.shared.util'; | ||
import { stringSharedUtil } from './util/string.shared.util'; | ||
export { memo, memoCache, ErrorData, ErrorObject, HttpErrorData, ErrorResponse, HttpErrorResponse, AppError, HttpError, deepFreeze, silentConsole, errorSharedUtil, objectUtil, randomSharedUtil, scriptSharedUtil, stringSharedUtil, StringMap, PromiseMap, ClassType, }; | ||
import { arrayToHash, by, classToPlain, deepCopy, deepEquals, deepFreeze, deepTrim, filterEmptyStringValues, filterFalsyValues, filterUndefinedValues, filterValues, getKeyByValue, invertMap, invertObject, isEmptyObject, isObject, mask, mergeDeep, objectNullValuesToUndefined, pick, sortObjectDeep, transformValues, unsetValue } from './util/object.util'; | ||
import { randomInt } from './util/random.util'; | ||
import { loadScript } from './util/script.util'; | ||
import { capitalizeFirstLetter, lowercaseFirstLetter, removeWhitespace } from './util/string.util'; | ||
import { silentConsole } from './util/test.util'; | ||
export { memo, memoCache, ErrorData, ErrorObject, HttpErrorData, ErrorResponse, HttpErrorResponse, AppError, HttpError, silentConsole, randomInt, loadScript, StringMap, PromiseMap, ClassType, capitalizeFirstLetter, lowercaseFirstLetter, removeWhitespace, pick, filterFalsyValues, filterEmptyStringValues, filterUndefinedValues, filterValues, transformValues, objectNullValuesToUndefined, deepEquals, deepCopy, isObject, isEmptyObject, mergeDeep, deepTrim, sortObjectDeep, unsetValue, mask, arrayToHash, classToPlain, getKeyByValue, invertObject, invertMap, by, deepFreeze, anyToErrorMessage, anyToErrorObject, errorToErrorObject, errorObjectToAppError, errorObjectToHttpError, appErrorToErrorObject, appErrorToHttpError, }; |
@@ -9,17 +9,46 @@ "use strict"; | ||
exports.AppError = app_error_1.AppError; | ||
const error_shared_util_1 = require("./error/error.shared.util"); | ||
exports.errorSharedUtil = error_shared_util_1.errorSharedUtil; | ||
const error_util_1 = require("./error/error.util"); | ||
exports.anyToErrorMessage = error_util_1.anyToErrorMessage; | ||
exports.anyToErrorObject = error_util_1.anyToErrorObject; | ||
exports.appErrorToErrorObject = error_util_1.appErrorToErrorObject; | ||
exports.appErrorToHttpError = error_util_1.appErrorToHttpError; | ||
exports.errorObjectToAppError = error_util_1.errorObjectToAppError; | ||
exports.errorObjectToHttpError = error_util_1.errorObjectToHttpError; | ||
exports.errorToErrorObject = error_util_1.errorToErrorObject; | ||
const http_error_1 = require("./error/http.error"); | ||
exports.HttpError = http_error_1.HttpError; | ||
const test_shared_util_1 = require("./testing/test.shared.util"); | ||
exports.deepFreeze = test_shared_util_1.deepFreeze; | ||
exports.silentConsole = test_shared_util_1.silentConsole; | ||
const object_util_1 = require("./util/object.util"); | ||
exports.objectUtil = object_util_1.objectUtil; | ||
const random_shared_util_1 = require("./util/random.shared.util"); | ||
exports.randomSharedUtil = random_shared_util_1.randomSharedUtil; | ||
const script_shared_util_1 = require("./util/script.shared.util"); | ||
exports.scriptSharedUtil = script_shared_util_1.scriptSharedUtil; | ||
const string_shared_util_1 = require("./util/string.shared.util"); | ||
exports.stringSharedUtil = string_shared_util_1.stringSharedUtil; | ||
exports.arrayToHash = object_util_1.arrayToHash; | ||
exports.by = object_util_1.by; | ||
exports.classToPlain = object_util_1.classToPlain; | ||
exports.deepCopy = object_util_1.deepCopy; | ||
exports.deepEquals = object_util_1.deepEquals; | ||
exports.deepFreeze = object_util_1.deepFreeze; | ||
exports.deepTrim = object_util_1.deepTrim; | ||
exports.filterEmptyStringValues = object_util_1.filterEmptyStringValues; | ||
exports.filterFalsyValues = object_util_1.filterFalsyValues; | ||
exports.filterUndefinedValues = object_util_1.filterUndefinedValues; | ||
exports.filterValues = object_util_1.filterValues; | ||
exports.getKeyByValue = object_util_1.getKeyByValue; | ||
exports.invertMap = object_util_1.invertMap; | ||
exports.invertObject = object_util_1.invertObject; | ||
exports.isEmptyObject = object_util_1.isEmptyObject; | ||
exports.isObject = object_util_1.isObject; | ||
exports.mask = object_util_1.mask; | ||
exports.mergeDeep = object_util_1.mergeDeep; | ||
exports.objectNullValuesToUndefined = object_util_1.objectNullValuesToUndefined; | ||
exports.pick = object_util_1.pick; | ||
exports.sortObjectDeep = object_util_1.sortObjectDeep; | ||
exports.transformValues = object_util_1.transformValues; | ||
exports.unsetValue = object_util_1.unsetValue; | ||
const random_util_1 = require("./util/random.util"); | ||
exports.randomInt = random_util_1.randomInt; | ||
const script_util_1 = require("./util/script.util"); | ||
exports.loadScript = script_util_1.loadScript; | ||
const string_util_1 = require("./util/string.util"); | ||
exports.capitalizeFirstLetter = string_util_1.capitalizeFirstLetter; | ||
exports.lowercaseFirstLetter = string_util_1.lowercaseFirstLetter; | ||
exports.removeWhitespace = string_util_1.removeWhitespace; | ||
const test_util_1 = require("./util/test.util"); | ||
exports.silentConsole = test_util_1.silentConsole; | ||
//# sourceMappingURL=index.js.map |
import { StringMap } from '../types'; | ||
export declare class ObjectUtil { | ||
pick<T>(obj: T, fields?: string[], initialObject?: Partial<T>): T; | ||
/** | ||
* Does NOT mutate (unless "mutate" flag is set) | ||
* Removes "falsy" value from the object. | ||
*/ | ||
filterFalsyValues<T>(_obj: T, mutate?: boolean): T; | ||
filterEmptyStringValues<T>(_obj: T, mutate?: boolean): T; | ||
filterUndefinedValues<T>(_obj: T, mutate?: boolean): T; | ||
filterValues<T>(_obj: T, predicate: (key: any, value: any) => boolean, mutate?: boolean): T; | ||
transformValues<T>(_obj: T, transformFn: (key: any, value: any) => any, mutate?: boolean): T; | ||
objectNullValuesToUndefined<T>(_obj: T, mutate?: boolean): T; | ||
deepEquals(a: object, b: object): boolean; | ||
/** | ||
* Deep copy object (by json parse/stringify). | ||
*/ | ||
deepCopy<T>(o: T): T; | ||
isObject(item: any): boolean; | ||
isEmptyObject(obj: any): boolean; | ||
mergeDeep(target: any, source: any): any; | ||
/** | ||
* Mutates | ||
*/ | ||
deepTrim(o: any): any; | ||
private defaultSortFn; | ||
sortObjectDeep<T>(o: T): T; | ||
unsetValue(obj: any, prop: string): void; | ||
/** | ||
* Returns object with filtered keys from "exclude" array. | ||
* E.g: | ||
* mask({...}, [ | ||
* 'account.id', | ||
* 'account.updated', | ||
* ]) | ||
* | ||
* Pass deepCopy if you want to protect the whole object (not just first level) from mutation. | ||
*/ | ||
mask<T extends object>(_o: T, exclude: string[], deepCopy?: boolean): T; | ||
/** | ||
* Turns ['a', b'] into {a: true, b: true} | ||
*/ | ||
arrayToHash(a?: any[]): { | ||
[k: string]: boolean; | ||
}; | ||
classToPlain<T = any>(obj?: any): T; | ||
getKeyByValue<T = any>(object: any, value: any): T | undefined; | ||
invertObject<T>(o: any): T; | ||
invertMap<K, V>(m: Map<K, V>): Map<V, K>; | ||
by<T = any>(items: T[] | undefined, by: string): StringMap<T>; | ||
} | ||
export declare const objectUtil: ObjectUtil; | ||
export declare function pick<T>(obj: T, fields?: string[], initialObject?: Partial<T>): T; | ||
/** | ||
* Does NOT mutate (unless "mutate" flag is set) | ||
* Removes "falsy" value from the object. | ||
*/ | ||
export declare function filterFalsyValues<T>(_obj: T, mutate?: boolean): T; | ||
export declare function filterEmptyStringValues<T>(_obj: T, mutate?: boolean): T; | ||
export declare function filterUndefinedValues<T>(_obj: T, mutate?: boolean): T; | ||
export declare function filterValues<T>(_obj: T, predicate: (key: any, value: any) => boolean, mutate?: boolean): T; | ||
export declare function transformValues<T>(_obj: T, transformFn: (key: any, value: any) => any, mutate?: boolean): T; | ||
export declare function objectNullValuesToUndefined<T>(_obj: T, mutate?: boolean): T; | ||
export declare function deepEquals(a: object, b: object): boolean; | ||
/** | ||
* Deep copy object (by json parse/stringify). | ||
*/ | ||
export declare function deepCopy<T>(o: T): T; | ||
export declare function isObject(item: any): boolean; | ||
export declare function isEmptyObject(obj: any): boolean; | ||
export declare function mergeDeep(target: any, source: any): any; | ||
/** | ||
* Mutates | ||
*/ | ||
export declare function deepTrim(o: any): any; | ||
export declare function sortObjectDeep<T>(o: T): T; | ||
export declare function unsetValue(obj: any, prop: string): void; | ||
/** | ||
* Returns object with filtered keys from "exclude" array. | ||
* E.g: | ||
* mask({...}, [ | ||
* 'account.id', | ||
* 'account.updated', | ||
* ]) | ||
* | ||
* Pass deepCopy if you want to protect the whole object (not just first level) from mutation. | ||
*/ | ||
export declare function mask<T extends object>(_o: T, exclude: string[], _deepCopy?: boolean): T; | ||
/** | ||
* Turns ['a', b'] into {a: true, b: true} | ||
*/ | ||
export declare function arrayToHash(a?: any[]): { | ||
[k: string]: boolean; | ||
}; | ||
export declare function classToPlain<T = any>(obj?: any): T; | ||
export declare function getKeyByValue<T = any>(object: any, value: any): T | undefined; | ||
export declare function invertObject<T>(o: any): T; | ||
export declare function invertMap<K, V>(m: Map<K, V>): Map<V, K>; | ||
export declare function by<T = any>(items: T[] | undefined, by: string): StringMap<T>; | ||
export declare function deepFreeze(o: any): void; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
class ObjectUtil { | ||
// Picks just allowed fields and no other fields | ||
// pick<T> (obj: any, fields: string[], initialObject = {}): T { | ||
pick(obj, fields, initialObject = {}) { | ||
if (!obj || !fields || !fields.length) | ||
return obj; | ||
const o = initialObject; | ||
fields.forEach(k => { | ||
if (k in obj) | ||
o[k] = obj[k]; | ||
// Picks just allowed fields and no other fields | ||
// pick<T> (obj: any, fields: string[], initialObject = {}): T { | ||
function pick(obj, fields, initialObject = {}) { | ||
if (!obj || !fields || !fields.length) | ||
return obj; | ||
const o = initialObject; | ||
fields.forEach(k => { | ||
if (k in obj) | ||
o[k] = obj[k]; | ||
}); | ||
return o; | ||
} | ||
exports.pick = pick; | ||
/** | ||
* Does NOT mutate (unless "mutate" flag is set) | ||
* Removes "falsy" value from the object. | ||
*/ | ||
function filterFalsyValues(_obj, mutate = false) { | ||
return filterValues(_obj, (k, v) => !!v, mutate); | ||
} | ||
exports.filterFalsyValues = filterFalsyValues; | ||
function filterEmptyStringValues(_obj, mutate = false) { | ||
return filterValues(_obj, (k, v) => v !== '', mutate); | ||
} | ||
exports.filterEmptyStringValues = filterEmptyStringValues; | ||
function filterUndefinedValues(_obj, mutate = false) { | ||
return filterValues(_obj, (k, v) => v !== undefined && v !== null, mutate); | ||
} | ||
exports.filterUndefinedValues = filterUndefinedValues; | ||
function filterValues(_obj, predicate, mutate = false) { | ||
if (!isObject(_obj)) | ||
return _obj; | ||
const o = mutate ? _obj : Object.assign({}, _obj); | ||
Object.keys(o).forEach(k => { | ||
const keep = predicate(k, o[k]); | ||
if (!keep) | ||
delete o[k]; | ||
}); | ||
return o; | ||
} | ||
exports.filterValues = filterValues; | ||
function transformValues(_obj, transformFn, mutate = false) { | ||
if (!isObject(_obj)) | ||
return _obj; | ||
const o = mutate ? _obj : Object.assign({}, _obj); | ||
Object.keys(o).forEach(k => { | ||
o[k] = transformFn(k, o[k]); | ||
}); | ||
return o; | ||
} | ||
exports.transformValues = transformValues; | ||
function objectNullValuesToUndefined(_obj, mutate = false) { | ||
return transformValues(_obj, (k, v) => { | ||
if (v === null) | ||
return undefined; | ||
return v; | ||
}, mutate); | ||
} | ||
exports.objectNullValuesToUndefined = objectNullValuesToUndefined; | ||
function deepEquals(a, b) { | ||
return JSON.stringify(sortObjectDeep(a)) === JSON.stringify(sortObjectDeep(b)); | ||
} | ||
exports.deepEquals = deepEquals; | ||
/** | ||
* Deep copy object (by json parse/stringify). | ||
*/ | ||
function deepCopy(o) { | ||
return JSON.parse(JSON.stringify(o)); | ||
} | ||
exports.deepCopy = deepCopy; | ||
function isObject(item) { | ||
return (item && typeof item === 'object' && !Array.isArray(item) && item !== null) || false; | ||
} | ||
exports.isObject = isObject; | ||
function isEmptyObject(obj) { | ||
return obj && obj.constructor === Object && Object.keys(obj).length === 0; | ||
} | ||
exports.isEmptyObject = isEmptyObject; | ||
// from: https://gist.github.com/Salakar/1d7137de9cb8b704e48a | ||
function mergeDeep(target, source) { | ||
if (isObject(target) && isObject(source)) { | ||
Object.keys(source).forEach(key => { | ||
if (isObject(source[key])) { | ||
if (!target[key]) | ||
Object.assign(target, { [key]: {} }); | ||
mergeDeep(target[key], source[key]); | ||
} | ||
else { | ||
Object.assign(target, { [key]: source[key] }); | ||
} | ||
}); | ||
return o; | ||
} | ||
/** | ||
* Does NOT mutate (unless "mutate" flag is set) | ||
* Removes "falsy" value from the object. | ||
*/ | ||
filterFalsyValues(_obj, mutate = false) { | ||
return this.filterValues(_obj, (k, v) => !!v, mutate); | ||
} | ||
filterEmptyStringValues(_obj, mutate = false) { | ||
return this.filterValues(_obj, (k, v) => v !== '', mutate); | ||
} | ||
filterUndefinedValues(_obj, mutate = false) { | ||
return this.filterValues(_obj, (k, v) => v !== undefined && v !== null, mutate); | ||
} | ||
filterValues(_obj, predicate, mutate = false) { | ||
if (!this.isObject(_obj)) | ||
return _obj; | ||
const o = mutate ? _obj : Object.assign({}, _obj); | ||
Object.keys(o).forEach(k => { | ||
const keep = predicate(k, o[k]); | ||
if (!keep) | ||
delete o[k]; | ||
}); | ||
return target; | ||
} | ||
exports.mergeDeep = mergeDeep; | ||
/** | ||
* Mutates | ||
*/ | ||
function deepTrim(o) { | ||
if (!o) | ||
return o; | ||
if (typeof o === 'string') { | ||
return o.trim(); | ||
} | ||
transformValues(_obj, transformFn, mutate = false) { | ||
if (!this.isObject(_obj)) | ||
return _obj; | ||
const o = mutate ? _obj : Object.assign({}, _obj); | ||
else if (typeof o === 'object') { | ||
Object.keys(o).forEach(k => { | ||
o[k] = transformFn(k, o[k]); | ||
o[k] = deepTrim(o[k]); | ||
}); | ||
return o; | ||
} | ||
objectNullValuesToUndefined(_obj, mutate = false) { | ||
return this.transformValues(_obj, (k, v) => { | ||
if (v === null) | ||
return undefined; | ||
return v; | ||
}, mutate); | ||
return o; | ||
} | ||
exports.deepTrim = deepTrim; | ||
function defaultSortFn(a, b) { | ||
return a.localeCompare(b); | ||
} | ||
// based on: https://github.com/IndigoUnited/js-deep-sort-object | ||
function sortObjectDeep(o) { | ||
// array | ||
if (Array.isArray(o)) { | ||
return o.map(i => sortObjectDeep(i)); | ||
} | ||
deepEquals(a, b) { | ||
return JSON.stringify(this.sortObjectDeep(a)) === JSON.stringify(this.sortObjectDeep(b)); | ||
if (isObject(o)) { | ||
const out = {}; | ||
Object.keys(o) | ||
.sort((a, b) => defaultSortFn(a, b)) | ||
.forEach(k => { | ||
out[k] = sortObjectDeep(o[k]); | ||
}); | ||
return out; | ||
} | ||
/** | ||
* Deep copy object (by json parse/stringify). | ||
*/ | ||
deepCopy(o) { | ||
return JSON.parse(JSON.stringify(o)); | ||
return o; | ||
} | ||
exports.sortObjectDeep = sortObjectDeep; | ||
// from: https://github.com/jonschlinkert/unset-value | ||
// mutates obj | ||
function unsetValue(obj, prop) { | ||
if (!isObject(obj)) { | ||
return; | ||
} | ||
isObject(item) { | ||
return (item && typeof item === 'object' && !Array.isArray(item) && item !== null) || false; | ||
if (obj.hasOwnProperty(prop)) { | ||
delete obj[prop]; | ||
return; | ||
} | ||
isEmptyObject(obj) { | ||
return obj && obj.constructor === Object && Object.keys(obj).length === 0; | ||
const segs = prop.split('.'); | ||
let last = segs.pop(); | ||
while (segs.length && segs[segs.length - 1].slice(-1) === '\\') { | ||
last = segs.pop().slice(0, -1) + '.' + last; | ||
} | ||
// from: https://gist.github.com/Salakar/1d7137de9cb8b704e48a | ||
mergeDeep(target, source) { | ||
if (this.isObject(target) && this.isObject(source)) { | ||
Object.keys(source).forEach(key => { | ||
if (this.isObject(source[key])) { | ||
if (!target[key]) | ||
Object.assign(target, { [key]: {} }); | ||
this.mergeDeep(target[key], source[key]); | ||
} | ||
else { | ||
Object.assign(target, { [key]: source[key] }); | ||
} | ||
}); | ||
} | ||
return target; | ||
while (segs.length && isObject(obj)) { | ||
const k = (prop = segs.shift()); | ||
obj = obj[k]; | ||
} | ||
/** | ||
* Mutates | ||
*/ | ||
deepTrim(o) { | ||
if (!o) | ||
return o; | ||
if (typeof o === 'string') { | ||
return o.trim(); | ||
} | ||
else if (typeof o === 'object') { | ||
Object.keys(o).forEach(k => { | ||
o[k] = this.deepTrim(o[k]); | ||
}); | ||
} | ||
if (!isObject(obj)) | ||
return; | ||
delete obj[last]; | ||
} | ||
exports.unsetValue = unsetValue; | ||
/** | ||
* Returns object with filtered keys from "exclude" array. | ||
* E.g: | ||
* mask({...}, [ | ||
* 'account.id', | ||
* 'account.updated', | ||
* ]) | ||
* | ||
* Pass deepCopy if you want to protect the whole object (not just first level) from mutation. | ||
*/ | ||
function mask(_o, exclude, _deepCopy = false) { | ||
let o = Object.assign({}, _o); | ||
if (_deepCopy) | ||
o = deepCopy(o); | ||
exclude.forEach(e => { | ||
// eval(`delete o.${e}`) | ||
unsetValue(o, e); | ||
}); | ||
return o; | ||
} | ||
exports.mask = mask; | ||
/** | ||
* Turns ['a', b'] into {a: true, b: true} | ||
*/ | ||
function arrayToHash(a = []) { | ||
return a.reduce((o, item) => { | ||
o[item] = true; | ||
return o; | ||
} | ||
defaultSortFn(a, b) { | ||
return a.localeCompare(b); | ||
} | ||
// based on: https://github.com/IndigoUnited/js-deep-sort-object | ||
sortObjectDeep(o) { | ||
// array | ||
if (Array.isArray(o)) { | ||
return o.map(i => this.sortObjectDeep(i)); | ||
}, {}); | ||
} | ||
exports.arrayToHash = arrayToHash; | ||
function classToPlain(obj = {}) { | ||
return JSON.parse(JSON.stringify(obj)); | ||
} | ||
exports.classToPlain = classToPlain; | ||
function getKeyByValue(object, value) { | ||
if (!isObject(object)) | ||
return; | ||
return Object.keys(object).find(k => object[k] === value); | ||
} | ||
exports.getKeyByValue = getKeyByValue; | ||
function invertObject(o) { | ||
const inv = {}; | ||
Object.keys(o).forEach(k => { | ||
inv[o[k]] = k; | ||
}); | ||
return inv; | ||
} | ||
exports.invertObject = invertObject; | ||
function invertMap(m) { | ||
const inv = new Map(); | ||
m.forEach((v, k) => inv.set(v, k)); | ||
return inv; | ||
} | ||
exports.invertMap = invertMap; | ||
function by(items = [], by) { | ||
const r = {}; | ||
items.forEach((item) => { | ||
if (item[by]) | ||
r[item[by]] = item; | ||
}); | ||
return r; | ||
} | ||
exports.by = by; | ||
// Source: https://github.com/substack/deep-freeze/blob/master/index.js | ||
function deepFreeze(o) { | ||
Object.freeze(o); | ||
Object.getOwnPropertyNames(o).forEach(prop => { | ||
if (o.hasOwnProperty(prop) && | ||
o[prop] !== null && | ||
(typeof o[prop] === 'object' || typeof o[prop] === 'function') && | ||
!Object.isFrozen(o[prop])) { | ||
deepFreeze(o[prop]); | ||
} | ||
if (this.isObject(o)) { | ||
const out = {}; | ||
Object.keys(o) | ||
.sort((a, b) => this.defaultSortFn(a, b)) | ||
.forEach(k => { | ||
out[k] = this.sortObjectDeep(o[k]); | ||
}); | ||
return out; | ||
} | ||
return o; | ||
} | ||
// from: https://github.com/jonschlinkert/unset-value | ||
// mutates obj | ||
unsetValue(obj, prop) { | ||
if (!this.isObject(obj)) { | ||
return; | ||
} | ||
if (obj.hasOwnProperty(prop)) { | ||
delete obj[prop]; | ||
return; | ||
} | ||
const segs = prop.split('.'); | ||
let last = segs.pop(); | ||
while (segs.length && segs[segs.length - 1].slice(-1) === '\\') { | ||
last = segs.pop().slice(0, -1) + '.' + last; | ||
} | ||
while (segs.length && this.isObject(obj)) { | ||
const k = (prop = segs.shift()); | ||
obj = obj[k]; | ||
} | ||
if (!this.isObject(obj)) | ||
return; | ||
delete obj[last]; | ||
} | ||
/** | ||
* Returns object with filtered keys from "exclude" array. | ||
* E.g: | ||
* mask({...}, [ | ||
* 'account.id', | ||
* 'account.updated', | ||
* ]) | ||
* | ||
* Pass deepCopy if you want to protect the whole object (not just first level) from mutation. | ||
*/ | ||
mask(_o, exclude, deepCopy = false) { | ||
let o = Object.assign({}, _o); | ||
if (deepCopy) | ||
o = this.deepCopy(o); | ||
exclude.forEach(e => { | ||
// eval(`delete o.${e}`) | ||
this.unsetValue(o, e); | ||
}); | ||
return o; | ||
} | ||
/** | ||
* Turns ['a', b'] into {a: true, b: true} | ||
*/ | ||
arrayToHash(a = []) { | ||
return a.reduce((o, item) => { | ||
o[item] = true; | ||
return o; | ||
}, {}); | ||
} | ||
classToPlain(obj = {}) { | ||
return JSON.parse(JSON.stringify(obj)); | ||
} | ||
getKeyByValue(object, value) { | ||
if (!this.isObject(object)) | ||
return; | ||
return Object.keys(object).find(k => object[k] === value); | ||
} | ||
invertObject(o) { | ||
const inv = {}; | ||
Object.keys(o).forEach(k => { | ||
inv[o[k]] = k; | ||
}); | ||
return inv; | ||
} | ||
invertMap(m) { | ||
const inv = new Map(); | ||
m.forEach((v, k) => inv.set(v, k)); | ||
return inv; | ||
} | ||
by(items = [], by) { | ||
const r = {}; | ||
items.forEach((item) => { | ||
if (item[by]) | ||
r[item[by]] = item; | ||
}); | ||
return r; | ||
} | ||
}); | ||
return o; | ||
} | ||
exports.ObjectUtil = ObjectUtil; | ||
exports.objectUtil = new ObjectUtil(); | ||
exports.deepFreeze = deepFreeze; | ||
//# sourceMappingURL=object.util.js.map |
{ | ||
"name": "@naturalcycles/js-lib", | ||
"version": "3.2.0", | ||
"version": "4.0.0", | ||
"scripts": { | ||
@@ -5,0 +5,0 @@ "build": "del ./dist && tsc", |
@@ -11,10 +11,42 @@ import { memo } from './decorators/memo.decorator' | ||
} from './error/error.model' | ||
import { errorSharedUtil } from './error/error.shared.util' | ||
import { | ||
anyToErrorMessage, | ||
anyToErrorObject, | ||
appErrorToErrorObject, | ||
appErrorToHttpError, | ||
errorObjectToAppError, | ||
errorObjectToHttpError, | ||
errorToErrorObject, | ||
} from './error/error.util' | ||
import { HttpError } from './error/http.error' | ||
import { deepFreeze, silentConsole } from './testing/test.shared.util' | ||
import { ClassType, PromiseMap, StringMap } from './types' | ||
import { objectUtil } from './util/object.util' | ||
import { randomSharedUtil } from './util/random.shared.util' | ||
import { scriptSharedUtil } from './util/script.shared.util' | ||
import { stringSharedUtil } from './util/string.shared.util' | ||
import { | ||
arrayToHash, | ||
by, | ||
classToPlain, | ||
deepCopy, | ||
deepEquals, | ||
deepFreeze, | ||
deepTrim, | ||
filterEmptyStringValues, | ||
filterFalsyValues, | ||
filterUndefinedValues, | ||
filterValues, | ||
getKeyByValue, | ||
invertMap, | ||
invertObject, | ||
isEmptyObject, | ||
isObject, | ||
mask, | ||
mergeDeep, | ||
objectNullValuesToUndefined, | ||
pick, | ||
sortObjectDeep, | ||
transformValues, | ||
unsetValue, | ||
} from './util/object.util' | ||
import { randomInt } from './util/random.util' | ||
import { loadScript } from './util/script.util' | ||
import { capitalizeFirstLetter, lowercaseFirstLetter, removeWhitespace } from './util/string.util' | ||
import { silentConsole } from './util/test.util' | ||
@@ -31,12 +63,41 @@ export { | ||
HttpError, | ||
deepFreeze, | ||
silentConsole, | ||
errorSharedUtil, | ||
objectUtil, | ||
randomSharedUtil, | ||
scriptSharedUtil, | ||
stringSharedUtil, | ||
randomInt, | ||
loadScript, | ||
StringMap, | ||
PromiseMap, | ||
ClassType, | ||
capitalizeFirstLetter, | ||
lowercaseFirstLetter, | ||
removeWhitespace, | ||
pick, | ||
filterFalsyValues, | ||
filterEmptyStringValues, | ||
filterUndefinedValues, | ||
filterValues, | ||
transformValues, | ||
objectNullValuesToUndefined, | ||
deepEquals, | ||
deepCopy, | ||
isObject, | ||
isEmptyObject, | ||
mergeDeep, | ||
deepTrim, | ||
sortObjectDeep, | ||
unsetValue, | ||
mask, | ||
arrayToHash, | ||
classToPlain, | ||
getKeyByValue, | ||
invertObject, | ||
invertMap, | ||
by, | ||
deepFreeze, | ||
anyToErrorMessage, | ||
anyToErrorObject, | ||
errorToErrorObject, | ||
errorObjectToAppError, | ||
errorObjectToHttpError, | ||
appErrorToErrorObject, | ||
appErrorToHttpError, | ||
} |
import { StringMap } from '../types' | ||
export class ObjectUtil { | ||
// Picks just allowed fields and no other fields | ||
// pick<T> (obj: any, fields: string[], initialObject = {}): T { | ||
pick<T> (obj: T, fields?: string[], initialObject: Partial<T> = {}): T { | ||
if (!obj || !fields || !fields.length) return obj | ||
// Picks just allowed fields and no other fields | ||
// pick<T> (obj: any, fields: string[], initialObject = {}): T { | ||
export function pick<T> (obj: T, fields?: string[], initialObject: Partial<T> = {}): T { | ||
if (!obj || !fields || !fields.length) return obj | ||
const o: any = initialObject | ||
const o: any = initialObject | ||
fields.forEach(k => { | ||
if (k in obj) o[k] = (obj as any)[k] | ||
}) | ||
fields.forEach(k => { | ||
if (k in obj) o[k] = (obj as any)[k] | ||
}) | ||
return o | ||
} | ||
return o | ||
} | ||
/** | ||
* Does NOT mutate (unless "mutate" flag is set) | ||
* Removes "falsy" value from the object. | ||
*/ | ||
filterFalsyValues<T> (_obj: T, mutate = false): T { | ||
return this.filterValues(_obj, (k, v) => !!v, mutate) | ||
} | ||
/** | ||
* Does NOT mutate (unless "mutate" flag is set) | ||
* Removes "falsy" value from the object. | ||
*/ | ||
export function filterFalsyValues<T> (_obj: T, mutate = false): T { | ||
return filterValues(_obj, (k, v) => !!v, mutate) | ||
} | ||
filterEmptyStringValues<T> (_obj: T, mutate = false): T { | ||
return this.filterValues(_obj, (k, v) => v !== '', mutate) | ||
} | ||
export function filterEmptyStringValues<T> (_obj: T, mutate = false): T { | ||
return filterValues(_obj, (k, v) => v !== '', mutate) | ||
} | ||
filterUndefinedValues<T> (_obj: T, mutate = false): T { | ||
return this.filterValues(_obj, (k, v) => v !== undefined && v !== null, mutate) | ||
} | ||
export function filterUndefinedValues<T> (_obj: T, mutate = false): T { | ||
return filterValues(_obj, (k, v) => v !== undefined && v !== null, mutate) | ||
} | ||
filterValues<T> (_obj: T, predicate: (key: any, value: any) => boolean, mutate = false): T { | ||
if (!this.isObject(_obj)) return _obj | ||
export function filterValues<T> ( | ||
_obj: T, | ||
predicate: (key: any, value: any) => boolean, | ||
mutate = false, | ||
): T { | ||
if (!isObject(_obj)) return _obj | ||
const o: any = mutate ? _obj : { ...(_obj as any) } | ||
const o: any = mutate ? _obj : { ...(_obj as any) } | ||
Object.keys(o).forEach(k => { | ||
const keep = predicate(k, o[k]) | ||
if (!keep) delete o[k] | ||
}) | ||
Object.keys(o).forEach(k => { | ||
const keep = predicate(k, o[k]) | ||
if (!keep) delete o[k] | ||
}) | ||
return o | ||
} | ||
return o | ||
} | ||
transformValues<T> (_obj: T, transformFn: (key: any, value: any) => any, mutate = false): T { | ||
if (!this.isObject(_obj)) return _obj | ||
export function transformValues<T> ( | ||
_obj: T, | ||
transformFn: (key: any, value: any) => any, | ||
mutate = false, | ||
): T { | ||
if (!isObject(_obj)) return _obj | ||
const o: any = mutate ? _obj : { ...(_obj as any) } | ||
const o: any = mutate ? _obj : { ...(_obj as any) } | ||
Object.keys(o).forEach(k => { | ||
o[k] = transformFn(k, o[k]) | ||
}) | ||
Object.keys(o).forEach(k => { | ||
o[k] = transformFn(k, o[k]) | ||
}) | ||
return o | ||
} | ||
return o | ||
} | ||
objectNullValuesToUndefined<T> (_obj: T, mutate = false): T { | ||
return this.transformValues( | ||
_obj, | ||
(k, v) => { | ||
if (v === null) return undefined | ||
return v | ||
}, | ||
mutate, | ||
) | ||
} | ||
export function objectNullValuesToUndefined<T> (_obj: T, mutate = false): T { | ||
return transformValues( | ||
_obj, | ||
(k, v) => { | ||
if (v === null) return undefined | ||
return v | ||
}, | ||
mutate, | ||
) | ||
} | ||
deepEquals (a: object, b: object): boolean { | ||
return JSON.stringify(this.sortObjectDeep(a)) === JSON.stringify(this.sortObjectDeep(b)) | ||
} | ||
export function deepEquals (a: object, b: object): boolean { | ||
return JSON.stringify(sortObjectDeep(a)) === JSON.stringify(sortObjectDeep(b)) | ||
} | ||
/** | ||
* Deep copy object (by json parse/stringify). | ||
*/ | ||
deepCopy<T> (o: T): T { | ||
return JSON.parse(JSON.stringify(o)) | ||
} | ||
/** | ||
* Deep copy object (by json parse/stringify). | ||
*/ | ||
export function deepCopy<T> (o: T): T { | ||
return JSON.parse(JSON.stringify(o)) | ||
} | ||
isObject (item: any): boolean { | ||
return (item && typeof item === 'object' && !Array.isArray(item) && item !== null) || false | ||
export function isObject (item: any): boolean { | ||
return (item && typeof item === 'object' && !Array.isArray(item) && item !== null) || false | ||
} | ||
export function isEmptyObject (obj: any): boolean { | ||
return obj && obj.constructor === Object && Object.keys(obj).length === 0 | ||
} | ||
// from: https://gist.github.com/Salakar/1d7137de9cb8b704e48a | ||
export function mergeDeep (target: any, source: any): any { | ||
if (isObject(target) && isObject(source)) { | ||
Object.keys(source).forEach(key => { | ||
if (isObject(source[key])) { | ||
if (!target[key]) Object.assign(target, { [key]: {} }) | ||
mergeDeep(target[key], source[key]) | ||
} else { | ||
Object.assign(target, { [key]: source[key] }) | ||
} | ||
}) | ||
} | ||
return target | ||
} | ||
isEmptyObject (obj: any): boolean { | ||
return obj && obj.constructor === Object && Object.keys(obj).length === 0 | ||
/** | ||
* Mutates | ||
*/ | ||
export function deepTrim (o: any): any { | ||
if (!o) return o | ||
if (typeof o === 'string') { | ||
return o.trim() | ||
} else if (typeof o === 'object') { | ||
Object.keys(o).forEach(k => { | ||
o[k] = deepTrim(o[k]) | ||
}) | ||
} | ||
// from: https://gist.github.com/Salakar/1d7137de9cb8b704e48a | ||
mergeDeep (target: any, source: any): any { | ||
if (this.isObject(target) && this.isObject(source)) { | ||
Object.keys(source).forEach(key => { | ||
if (this.isObject(source[key])) { | ||
if (!target[key]) Object.assign(target, { [key]: {} }) | ||
this.mergeDeep(target[key], source[key]) | ||
} else { | ||
Object.assign(target, { [key]: source[key] }) | ||
} | ||
}) | ||
} | ||
return target | ||
return o | ||
} | ||
function defaultSortFn (a: any, b: any): number { | ||
return a.localeCompare(b) | ||
} | ||
// based on: https://github.com/IndigoUnited/js-deep-sort-object | ||
export function sortObjectDeep<T> (o: T): T { | ||
// array | ||
if (Array.isArray(o)) { | ||
return o.map(i => sortObjectDeep(i)) as any | ||
} | ||
/** | ||
* Mutates | ||
*/ | ||
deepTrim (o: any): any { | ||
if (!o) return o | ||
if (isObject(o)) { | ||
const out: any = {} | ||
if (typeof o === 'string') { | ||
return o.trim() | ||
} else if (typeof o === 'object') { | ||
Object.keys(o).forEach(k => { | ||
o[k] = this.deepTrim(o[k]) | ||
Object.keys(o) | ||
.sort((a, b) => defaultSortFn(a, b)) | ||
.forEach(k => { | ||
out[k] = sortObjectDeep((o as any)[k]) | ||
}) | ||
} | ||
return o | ||
return out | ||
} | ||
private defaultSortFn (a: any, b: any): number { | ||
return a.localeCompare(b) | ||
return o | ||
} | ||
// from: https://github.com/jonschlinkert/unset-value | ||
// mutates obj | ||
export function unsetValue (obj: any, prop: string): void { | ||
if (!isObject(obj)) { | ||
return | ||
} | ||
if (obj.hasOwnProperty(prop)) { | ||
delete obj[prop] | ||
return | ||
} | ||
// based on: https://github.com/IndigoUnited/js-deep-sort-object | ||
sortObjectDeep<T> (o: T): T { | ||
// array | ||
if (Array.isArray(o)) { | ||
return o.map(i => this.sortObjectDeep(i)) as any | ||
} | ||
const segs = prop.split('.') | ||
let last = segs.pop() | ||
while (segs.length && segs[segs.length - 1].slice(-1) === '\\') { | ||
last = segs.pop()!.slice(0, -1) + '.' + last | ||
} | ||
while (segs.length && isObject(obj)) { | ||
const k = (prop = segs.shift()!) | ||
obj = obj[k] | ||
} | ||
if (!isObject(obj)) return | ||
delete obj[last!] | ||
} | ||
if (this.isObject(o)) { | ||
const out: any = {} | ||
/** | ||
* Returns object with filtered keys from "exclude" array. | ||
* E.g: | ||
* mask({...}, [ | ||
* 'account.id', | ||
* 'account.updated', | ||
* ]) | ||
* | ||
* Pass deepCopy if you want to protect the whole object (not just first level) from mutation. | ||
*/ | ||
export function mask<T extends object> (_o: T, exclude: string[], _deepCopy = false): T { | ||
let o = { ...(_o as object) } | ||
if (_deepCopy) o = deepCopy(o) | ||
Object.keys(o) | ||
.sort((a, b) => this.defaultSortFn(a, b)) | ||
.forEach(k => { | ||
out[k] = this.sortObjectDeep((o as any)[k]) | ||
}) | ||
exclude.forEach(e => { | ||
// eval(`delete o.${e}`) | ||
unsetValue(o, e) | ||
}) | ||
return o as T | ||
} | ||
return out | ||
} | ||
/** | ||
* Turns ['a', b'] into {a: true, b: true} | ||
*/ | ||
export function arrayToHash (a: any[] = []): { [k: string]: boolean } { | ||
return a.reduce((o, item) => { | ||
o[item] = true | ||
return o | ||
} | ||
}, {}) | ||
} | ||
// from: https://github.com/jonschlinkert/unset-value | ||
// mutates obj | ||
unsetValue (obj: any, prop: string): void { | ||
if (!this.isObject(obj)) { | ||
return | ||
} | ||
if (obj.hasOwnProperty(prop)) { | ||
delete obj[prop] | ||
return | ||
} | ||
export function classToPlain<T = any> (obj: any = {}): T { | ||
return JSON.parse(JSON.stringify(obj)) | ||
} | ||
const segs = prop.split('.') | ||
let last = segs.pop() | ||
while (segs.length && segs[segs.length - 1].slice(-1) === '\\') { | ||
last = segs.pop()!.slice(0, -1) + '.' + last | ||
} | ||
while (segs.length && this.isObject(obj)) { | ||
const k = (prop = segs.shift()!) | ||
obj = obj[k] | ||
} | ||
if (!this.isObject(obj)) return | ||
delete obj[last!] | ||
} | ||
export function getKeyByValue<T = any> (object: any, value: any): T | undefined { | ||
if (!isObject(object)) return | ||
return Object.keys(object).find(k => object[k] === value) as any | ||
} | ||
/** | ||
* Returns object with filtered keys from "exclude" array. | ||
* E.g: | ||
* mask({...}, [ | ||
* 'account.id', | ||
* 'account.updated', | ||
* ]) | ||
* | ||
* Pass deepCopy if you want to protect the whole object (not just first level) from mutation. | ||
*/ | ||
mask<T extends object> (_o: T, exclude: string[], deepCopy = false): T { | ||
let o = { ...(_o as object) } | ||
if (deepCopy) o = this.deepCopy(o) | ||
export function invertObject<T> (o: any): T { | ||
const inv: any = {} | ||
Object.keys(o).forEach(k => { | ||
inv[o[k]] = k | ||
}) | ||
return inv | ||
} | ||
exclude.forEach(e => { | ||
// eval(`delete o.${e}`) | ||
this.unsetValue(o, e) | ||
}) | ||
return o as T | ||
} | ||
export function invertMap<K, V> (m: Map<K, V>): Map<V, K> { | ||
const inv = new Map<V, K>() | ||
m.forEach((v, k) => inv.set(v, k)) | ||
return inv | ||
} | ||
/** | ||
* Turns ['a', b'] into {a: true, b: true} | ||
*/ | ||
arrayToHash (a: any[] = []): { [k: string]: boolean } { | ||
return a.reduce((o, item) => { | ||
o[item] = true | ||
return o | ||
}, {}) | ||
} | ||
export function by<T = any> (items: T[] = [], by: string): StringMap<T> { | ||
const r: StringMap<T> = {} | ||
items.forEach((item: any) => { | ||
if (item[by]) r[item[by]] = item | ||
}) | ||
return r | ||
} | ||
classToPlain<T = any> (obj: any = {}): T { | ||
return JSON.parse(JSON.stringify(obj)) | ||
} | ||
// Source: https://github.com/substack/deep-freeze/blob/master/index.js | ||
export function deepFreeze (o: any): void { | ||
Object.freeze(o) | ||
getKeyByValue<T = any> (object: any, value: any): T | undefined { | ||
if (!this.isObject(object)) return | ||
return Object.keys(object).find(k => object[k] === value) as any | ||
} | ||
Object.getOwnPropertyNames(o).forEach(prop => { | ||
if ( | ||
o.hasOwnProperty(prop) && | ||
o[prop] !== null && | ||
(typeof o[prop] === 'object' || typeof o[prop] === 'function') && | ||
!Object.isFrozen(o[prop]) | ||
) { | ||
deepFreeze(o[prop]) | ||
} | ||
}) | ||
invertObject<T> (o: any): T { | ||
const inv: any = {} | ||
Object.keys(o).forEach(k => { | ||
inv[o[k]] = k | ||
}) | ||
return inv | ||
} | ||
invertMap<K, V> (m: Map<K, V>): Map<V, K> { | ||
const inv = new Map<V, K>() | ||
m.forEach((v, k) => inv.set(v, k)) | ||
return inv | ||
} | ||
by<T = any> (items: T[] = [], by: string): StringMap<T> { | ||
const r: StringMap<T> = {} | ||
items.forEach((item: any) => { | ||
if (item[by]) r[item[by]] = item | ||
}) | ||
return r | ||
} | ||
return o | ||
} | ||
export const objectUtil = new ObjectUtil() |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
106296
1873