Skip to content

Commit

Permalink
feat(Object): add omit & pick fns
Browse files Browse the repository at this point in the history
  • Loading branch information
Thanga-Ganapathy committed Mar 23, 2024
1 parent 362f148 commit 39f3fc1
Show file tree
Hide file tree
Showing 31 changed files with 497 additions and 85 deletions.
5 changes: 5 additions & 0 deletions .changeset/metal-years-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@opentf/utils": minor
---

Added object omit & pick util fns.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ await sleep(1000); // It suspends the exection for 1 second.
- [has](https://js-utils.pages.dev/Object/has)
- [merge](https://js-utils.pages.dev/Object/merge)
- [mergeAll](https://js-utils.pages.dev/Object/mergeAll)
- [omit](https://js-utils.pages.dev/Object/omit)
- [pick](https://js-utils.pages.dev/Object/pick)
- [set](https://js-utils.pages.dev/Object/set)
- [shallowMerge](https://js-utils.pages.dev/Object/shallowMerge)
- [shallowMergeAll](https://js-utils.pages.dev/Object/shallowMergeAll)
Expand Down
10 changes: 5 additions & 5 deletions apps/docs/pages/Array/arrIns.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ Immutable: This does not mutate the given array.
```ts copy
import { arrIns } from '@opentf/utils';

arrIns(
arr: unknown[] = [],
index: number | null,
...items: unknown[]
)
arrIns<T>(
arr: T[] = [],
index: number | null | undefined,
...items: T[]
)
```

## Examples
Expand Down
6 changes: 3 additions & 3 deletions apps/docs/pages/Array/arrReplace.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ Immutable: This does not mutate the given array.
```ts copy
import { arrReplace } from '@opentf/utils';

arrReplace(
arr: unknown[] = [],
arrReplace<T>(
arr: T[] = [],
index?: number | null,
...replacements: unknown[]
...replacements: T[]
)
```

Expand Down
4 changes: 2 additions & 2 deletions apps/docs/pages/Array/arrRm.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ Immutable: This does not mutate the given array.
```ts copy
import { arrRm } from '@opentf/utils';

arrRm(
arr: unknown[] = [],
arrRm<T>(
arr: T[] = [],
index?: number,
count: number = 1
)
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/pages/Object/_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"has": "has",
"merge": "merge",
"mergeAll": "mergeAll",
"omit": "omit",
"pick": "pick",
"set": "set",
"shallowMerge": "shallowMerge",
"shallowMergeAll": "shallowMergeAll",
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/pages/Object/clone.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import REPL from "../../components/REPL";
```ts
import { clone } from '@opentf/utils';

clone(val: T): T;
clone<T>(val: T): T;
```

<Callout type="info">
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/pages/Object/get.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { get } from '@opentf/utils';

get(
obj: object,
path: string | (string | number)[],
path: string | unknown[],
defVal?: unknown
): unknown
```
Expand Down
5 changes: 1 addition & 4 deletions apps/docs/pages/Object/has.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import REPL from "../../components/REPL";
```ts
import { has } from '@opentf/utils';

has(
obj: object,
path: string | (string | number)[] = []
): boolean
has(obj: object, path: string | unknown[]): boolean
```

## Examples
Expand Down
43 changes: 43 additions & 0 deletions apps/docs/pages/Object/omit.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Callout } from "nextra/components";
import REPL from "../../components/REPL";

> Removes all the property paths from the given object for the given list of paths.
<Callout type="info">
The source object can `Plain Object` or `Array`.
</Callout>

## Syntax

```ts
import { omit } from '@opentf/utils';

omit(obj: object, ...paths: (string | unknown[])[])
```

## Examples

```ts
omit({ a: 1, b: 2 }, 'a') //=> { b: 2 }

omit({ a: 1, b: 2 }, ['a']) //=> { b: 2 }

omit([1, 2, 3], '1') //=> [1, 3]

omit([1, 2, 3], 2) //=> [1, 2]

omit({ a: 1, b: 2, c: 3, d: 4 }, 'b', 'd')
//=> {
// a: 1,
// c: 3,
// }

obj = { a: { b: [1, 3, 5] } };
omit(obj, 'a.b[2]') //=> { a: { b: [1, 3] } });
```
## Try

<REPL code={`const { omit } = require('@opentf/utils');
omit({ a: 1, b: 2 }, 'a');
`} />
36 changes: 36 additions & 0 deletions apps/docs/pages/Object/pick.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Callout } from "nextra/components";
import REPL from "../../components/REPL";

> Includes all the property paths from the given object for the given list of paths.
<Callout type="info">
The source object can `Plain Object` or `Array`.
</Callout>

## Syntax

```ts
import { pick } from '@opentf/utils';

pick(obj: object, ...paths: (string | unknown[])[])
```

## Examples

```ts
pick({ a: 1, b: 2 }, 'a') //=> { a: 1 }

pick([1, 2, 3], '0') //=> [1]

pick({ a: { b: { c: 1 }, d: null, e: [10, 20, 30] } }, 'a.b', ['a', 'e', '2'])
//=> {
// a: { b: { c: 1 } },
// e: [30]
// }
```
## Try

<REPL code={`const { pick } = require('@opentf/utils');
pick({ a: 1, b: 2 }, 'a');
`} />
2 changes: 1 addition & 1 deletion apps/docs/pages/Object/set.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { set } from '@opentf/utils';

set<T>(
obj: T,
path: string | (string | number)[],
path: string | unknown[],
value: unknown | ((val: unknown) => unknown)
): T
```
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/pages/Object/unset.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { unset } from '@opentf/utils';

unset<T>(
obj: T,
path: string | (string | number)[]
path: string | unknown[],
): T
```

Expand Down
2 changes: 2 additions & 0 deletions packages/utils/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ await sleep(1000); // It suspends the exection for 1 second.
- [has](https://js-utils.pages.dev/Object/has)
- [merge](https://js-utils.pages.dev/Object/merge)
- [mergeAll](https://js-utils.pages.dev/Object/mergeAll)
- [omit](https://js-utils.pages.dev/Object/omit)
- [pick](https://js-utils.pages.dev/Object/pick)
- [set](https://js-utils.pages.dev/Object/set)
- [shallowMerge](https://js-utils.pages.dev/Object/shallowMerge)
- [shallowMergeAll](https://js-utils.pages.dev/Object/shallowMergeAll)
Expand Down
4 changes: 4 additions & 0 deletions packages/utils/__tests__/object/get.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ describe('Object > get', () => {
expect(get({ a: 1 }, 'a')).toBe(1);

expect(get({ a: { b: 25 } }, 'a.b')).toBe(25);
expect(get({ 'a.b': 1, b: 2 }, ['a.b'])).toBe(1);
const obj = { 'a.b': 2, a: { b: [1, 2, 3] } };
expect(get(obj, ['a.b'])).toBe(2);
expect(get(obj, 'a.b')).toEqual([1, 2, 3]);

expect(get({ user: { email: 'user@example.com' } }, 'user.email')).toBe(
'user@example.com'
Expand Down
62 changes: 62 additions & 0 deletions packages/utils/__tests__/object/omit.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { omit } from '../../src';

describe('Object > omit', () => {
test('remove a prop', () => {
expect(omit({ a: 1, b: 2 }, 'a')).toEqual({ b: 2 });
expect(omit({ a: 1, b: 2 }, ['a'])).toEqual({ b: 2 });
expect(omit({ 'a.b': 1, b: 2 }, ['a.b'])).toEqual({ b: 2 });
});

test('remove multiple props', () => {
expect(omit({ a: 1, b: 2, c: 3, d: 4 }, 'b', 'd')).toEqual({
a: 1,
c: 3,
});
expect(omit({ a: 1, b: 2, c: 3, d: 4 }, 'a', 'b', 'c')).toEqual({ d: 4 });
expect(omit({ 'a.b': 1, b: 2 }, ['a.b'], 'b')).toEqual({});
});

test('remove a deep prop', () => {
expect(omit({ a: { b: { c: 1 } } }, 'a.b.c')).toEqual({ a: { b: {} } });
});

test('remove multiple deep props', () => {
expect(
omit({ a: { b: { c: 1, d: 2, e: 5, f: 6 } } }, 'a.b.c', 'a.b.d', 'a.b.e')
).toEqual({ a: { b: { f: 6 } } });
});

test('remove an index from array', () => {
expect(omit([1, 2, 3], ['0'])).toEqual([2, 3]);
expect(omit([1, 2, 3], ['1'])).toEqual([1, 3]);
expect(omit([1, 2, 3], ['2'])).toEqual([1, 2]);
expect(omit([1, 2, 3], ['3'])).toEqual([1, 2, 3]);
expect(omit([1, 2, 3], ['-1'])).toEqual([1, 2, 3]);
});

test('remove multiple indexes from array', () => {
expect(omit([1, 2, 3], '1', '2')).toEqual([1]);
});

test('remove array items from nested deep obj', () => {
let obj = { a: [1, 3, 5] };
expect(omit(obj, 'a.[0]')).toEqual({ a: [3, 5] });

obj = { a: { b: [1, 3, 5] } };
expect(omit(obj, 'a.b[2]')).toEqual({ a: { b: [1, 3] } });

obj = { a: { b: { c: [1, 3, 5] } } };
expect(omit(obj, 'a.b.c[1]')).toEqual({ a: { b: { c: [1, 5] } } });

obj = {
a: {
b: { c: [1, 3, 5, { d: { e: [10, 20, 40] } }], f: { g: [1, 2, 3] } },
},
};
expect(
omit(obj, ['a', 'b', 'c', 3], ['a', 'b', 'f', 'g', 0], 'a.b.f.g[2]')
).toEqual({
a: { b: { c: [1, 3, 5], f: { g: [2] } } },
});
});
});
82 changes: 82 additions & 0 deletions packages/utils/__tests__/object/pick.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { pick } from '../../src';

describe('Object > pick', () => {
test('invalid', () => {
expect(pick()).toEqual({});
expect(pick(null)).toEqual({});
expect(pick(null, '')).toEqual({});
expect(pick({})).toEqual({});
expect(pick({}, 'a')).toEqual({});
expect(pick({ a: 1 }, 'b')).toEqual({});
expect(pick([])).toEqual([]);
expect(pick([], '0')).toEqual([]);
expect(pick([1], '1')).toEqual([]);
});

test('pick a first level prop', () => {
expect(pick({ a: 1, b: 2 }, 'a')).toEqual({ a: 1 });
expect(pick({ a: 1, b: 2 }, 'b')).toEqual({ b: 2 });
expect(pick({ 'a.b': 1, 'a.c': 2 }, ['a.c'])).toEqual({ 'a.c': 2 });
expect(pick([1, 2, 3], '0')).toEqual([1]);
expect(pick([1, 2, 3], 2)).toEqual([3]);
expect(pick({ '0': 'a', '1': 'b' }, 0)).toEqual({ '0': 'a' });
});

test('pick first level multiple props', () => {
expect(pick({ a: 1, b: 2, c: 3 }, 'a', 'b')).toEqual({ a: 1, b: 2 });
expect(pick({ a: 1, b: 2, c: 3 }, 'b', 'c')).toEqual({ b: 2, c: 3 });
expect(pick([1, 2, 3], '0', '2')).toEqual([1, 3]);
expect(pick([1, 2, 3], '1', 3)).toEqual([2]);
});

test('pick second level props', () => {
expect(pick({ a: { b: 2 } }, 'a.b')).toEqual({ a: { b: 2 } });
expect(pick({ a: { b: 2, c: 3 } }, 'a.c')).toEqual({ a: { c: 3 } });
expect(
pick({ a: { b: { c: 1, d: [1, 2, 3], e: null } } }, 'a.b.d[2]', [
'a',
'b',
'e',
])
).toEqual({ a: { b: { d: [3], e: null } } });
expect(
pick({ a: { b: { c: 1 }, d: null, e: [10, 20, 30] } }, 'a.b', [
'a',
'e',
'2',
])
).toEqual({ a: { b: { c: 1 }, e: [30] } });
});

test('pick deep level props', () => {
expect(pick({ a: { b: { c: 1 } } }, 'a')).toEqual({
a: { b: { c: 1 } },
});

expect(pick({ a: { b: { c: 1 }, d: null } }, 'a.b')).toEqual({
a: { b: { c: 1 } },
});

expect(pick({ a: { b: { c: 1 } } }, 'a.b.c')).toEqual({
a: { b: { c: 1 } },
});

expect(
pick(
{ a: { b: { c: 1, d: 3 } }, a2: { a2b1: 5, a2b2: 6 } },
'a.b.c',
['a', 'b', 'd'],
'a2.a2b2',
['a2', 'a2b1']
)
).toEqual({
a: { b: { c: 1, d: 3 } },
a2: { a2b1: 5, a2b2: 6 },
});
});

test('pick whole object with partial paths', () => {
const obj = { a: { b: { c: 3, d: 4, e: 5 } } };
expect(pick(obj, 'a', 'a.b.c', ['a', 'b', 'e'])).toEqual(obj);
});
});

0 comments on commit 39f3fc1

Please sign in to comment.