Skip to content

Commit

Permalink
feat(utilities): added util to set object value at path
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewcourtice committed Sep 23, 2022
1 parent 6fe7008 commit fe419d4
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 13 deletions.
26 changes: 14 additions & 12 deletions packages/utilities/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
export { default as identity } from './function/identity';
export { default as functionIdentity } from './function/identity';

export { default as clone } from './object/clone';
export { default as lock } from './object/lock';
export { default as overwrite } from './object/overwrite';
export { default as omit } from './object/omit';
export { default as fromPath } from './object/from-path';
export { default as toPath } from './object/to-path';
export { default as objectClone } from './object/clone';
export { default as objectLock } from './object/lock';
export { default as objectOverwrite } from './object/overwrite';
export { default as objectOmit } from './object/omit';
export { default as objectFromPath } from './object/from-path';
export { default as objectToPath } from './object/to-path';
export { default as objectTrace } from './object/trace';
export { default as objectSet } from './object/set';

export { default as getType } from './type/get-type';
export { default as isArray } from './type/is-array';
export { default as isFunction } from './type/is-function';
export { default as isObject } from './type/is-object';
export { default as isNil } from './type/is-nil';
export { default as typeGetType } from './type/get-type';
export { default as typeIsArray } from './type/is-array';
export { default as typeIsFunction } from './type/is-function';
export { default as typeIsObject } from './type/is-object';
export { default as typeIsNil } from './type/is-nil';

export * from './types';
2 changes: 1 addition & 1 deletion packages/utilities/src/object/from-path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import isArray from '../type/is-array';

export default function fromPath<TValue extends object>(value: TValue, path: string | PropertyKey[]): unknown {
const nodes = isArray(path) ? path : path.split('/');
return nodes.reduce((branch, node) => (branch as any)?.[node], value);
return nodes.reduce((branch, node) => (branch as any)[node], value);
}
20 changes: 20 additions & 0 deletions packages/utilities/src/object/set.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import fromPath from './from-path';
import isArray from '../type/is-array';
import isNil from '../type/is-nil';
import overwrite from './overwrite';

export default function setObjectValue<TTarget extends object>(target: TTarget, path: string | PropertyKey[], value: any, ignorePattern?: RegExp) {
const nodes = (isArray(path) ? path : path.split('/')).slice();
const key = nodes.pop();

if (isNil(key) || key === '') {
return overwrite(target, value, ignorePattern);
}

if (ignorePattern?.test(key.toString())) {
return;
}

const parent = fromPath(target, nodes) as Record<PropertyKey, unknown>;
parent[key] = value;
}
21 changes: 21 additions & 0 deletions packages/utilities/src/object/trace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
function traceObjectPath<TValue extends object>(onAccess: (key: PropertyKey) => void): TValue {
return new Proxy({} as TValue, {
get(target, key) {
onAccess(key);
return traceObjectPath(onAccess);
},
});
}

export default function traceObject<TValue extends object>() {
const nodes = new Set<PropertyKey>();
const value = traceObjectPath<TValue>(key => nodes.add(key));
const getNodes = () => Array.from(nodes);
const resetNodes = () => nodes.clear();

return {
value,
getNodes,
resetNodes,
};
}
45 changes: 45 additions & 0 deletions packages/utilities/test/object/set.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import set from '../../src/object/set';

import {
describe,
expect,
test,
} from 'vitest';

describe('Utilities', () => {

describe('Object Set', () => {

test('Should set a value at a given path', () => {
const source = {
propA: 1,
propB: 'foo',
propC: 'bar',
propD: [1, 2, 3],
propE: {
propEA: 5,
},
};

set(source, 'propB', 'blah');
expect(source.propB).toBe('blah');

set(source, 'propD/1', 15);
expect(source.propD[1]).toBe(15);

set(source, 'propE/propEA', 10);
expect(source.propE.propEA).toBe(10);

set(source, 'propC', 'bingo', /^propC/);
expect(source.propC).toBe('bar');

set(source, '', {
thing: 'hello',
});
expect(source).toHaveProperty('thing');
expect(source.thing).toBe('hello');
});

});

});

0 comments on commit fe419d4

Please sign in to comment.