chore: trim shared lodash helpers
This commit is contained in:
@@ -11,11 +11,8 @@ export * from './resources';
|
|||||||
export * from './state-handler';
|
export * from './state-handler';
|
||||||
export * from './to';
|
export * from './to';
|
||||||
export * from './tree';
|
export * from './tree';
|
||||||
|
export * from './object';
|
||||||
export * from './unique';
|
export * from './unique';
|
||||||
export * from './update-css-variables';
|
export * from './update-css-variables';
|
||||||
export * from './util';
|
export * from './util';
|
||||||
export * from './window';
|
export * from './window';
|
||||||
export { default as cloneDeep } from 'lodash.clonedeep';
|
|
||||||
export { default as get } from 'lodash.get';
|
|
||||||
export { default as isEqual } from 'lodash.isequal';
|
|
||||||
export { default as set } from 'lodash.set';
|
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
type KeyPath = Array<number | string> | number | string;
|
||||||
|
|
||||||
|
const keyPathPattern = /[^.[\]]+|\[(\d+)\]/g;
|
||||||
|
|
||||||
|
function toKeyPath(path: KeyPath): Array<number | string> {
|
||||||
|
if (Array.isArray(path)) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
if (typeof path === 'number') {
|
||||||
|
return [path];
|
||||||
|
}
|
||||||
|
const keys: Array<number | string> = [];
|
||||||
|
path.replace(keyPathPattern, (match, index) => {
|
||||||
|
keys.push(index === undefined ? match : Number(index));
|
||||||
|
return match;
|
||||||
|
});
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cloneDeep<T>(value: T): T {
|
||||||
|
if (value === null || typeof value !== 'object') {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
if (value instanceof Date) {
|
||||||
|
return new Date(value) as T;
|
||||||
|
}
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.map((item) => cloneDeep(item)) as T;
|
||||||
|
}
|
||||||
|
if (value instanceof Map) {
|
||||||
|
return new Map(
|
||||||
|
[...value.entries()].map(([key, item]) => [cloneDeep(key), cloneDeep(item)]),
|
||||||
|
) as T;
|
||||||
|
}
|
||||||
|
if (value instanceof Set) {
|
||||||
|
return new Set([...value.values()].map((item) => cloneDeep(item))) as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = {} as Record<string, unknown>;
|
||||||
|
for (const [key, item] of Object.entries(value)) {
|
||||||
|
result[key] = cloneDeep(item);
|
||||||
|
}
|
||||||
|
return result as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get<T = any>(
|
||||||
|
object: any,
|
||||||
|
path: KeyPath,
|
||||||
|
defaultValue?: T,
|
||||||
|
): T | undefined {
|
||||||
|
let result = object;
|
||||||
|
for (const key of toKeyPath(path)) {
|
||||||
|
if (result == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
result = result[key as keyof typeof result];
|
||||||
|
}
|
||||||
|
return result === undefined ? defaultValue : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set<T extends Record<string, any>>(
|
||||||
|
object: T,
|
||||||
|
path: KeyPath,
|
||||||
|
value: unknown,
|
||||||
|
): T {
|
||||||
|
const keys = toKeyPath(path);
|
||||||
|
let cursor: Record<string, any> = object;
|
||||||
|
|
||||||
|
keys.forEach((key, index) => {
|
||||||
|
if (index === keys.length - 1) {
|
||||||
|
cursor[key] = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextKey = keys[index + 1];
|
||||||
|
cursor[key] ??= typeof nextKey === 'number' ? [] : {};
|
||||||
|
cursor = cursor[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isEqual(left: unknown, right: unknown): boolean {
|
||||||
|
if (Object.is(left, right)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (left instanceof Date && right instanceof Date) {
|
||||||
|
return left.getTime() === right.getTime();
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
left === null ||
|
||||||
|
right === null ||
|
||||||
|
typeof left !== 'object' ||
|
||||||
|
typeof right !== 'object'
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Array.isArray(left) || Array.isArray(right)) {
|
||||||
|
if (!Array.isArray(left) || !Array.isArray(right)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
left.length === right.length &&
|
||||||
|
left.every((item, index) => isEqual(item, right[index]))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const leftKeys = Object.keys(left);
|
||||||
|
const rightKeys = Object.keys(right);
|
||||||
|
return (
|
||||||
|
leftKeys.length === rightKeys.length &&
|
||||||
|
leftKeys.every((key) =>
|
||||||
|
isEqual(
|
||||||
|
(left as Record<string, unknown>)[key],
|
||||||
|
(right as Record<string, unknown>)[key],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { cloneDeep, get, isEqual, set };
|
||||||
Reference in New Issue
Block a user