Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ecee5ab

Browse files
committedFeb 22, 2023
added is object fn, updated clean object fn
1 parent 06b79f6 commit ecee5ab

File tree

9 files changed

+3258
-3182
lines changed

9 files changed

+3258
-3182
lines changed
 

‎README.md

Lines changed: 115 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,12 @@ yarn add @idapgroup/js-object-utils
1515

1616
## Usage
1717

18-
### createFormData
19-
20-
Serialize object to FormData instance.
18+
### isObject
2119

22-
[DEMO](https://stackblitz.com/edit/typescript-br9t3k?file=index.ts)
20+
Detect is object created by the `Object` constructor
2321

2422
```js
25-
import { createFormData } from '@idapgroup/js-object-utils';
23+
import { isObject } from '@idapgroup/js-object-utils';
2624

2725
const object = {
2826
/**
@@ -31,36 +29,61 @@ const object = {
3129
*/
3230
};
3331

34-
const options = {
35-
/**
36-
* prefix for form data key
37-
* defaults empty string
38-
*/
39-
keyPrefix: '',
32+
const isObj = isObject(object) // true of false;
33+
```
4034

41-
/**
42-
* prefix index for form data key
43-
* defaults to null
44-
*/
45-
index: null,
35+
### createFormData
4636

47-
/**
48-
* callback fn for convert true or false
49-
* defaults true or false to '1' or '0' respectively
50-
*/
51-
booleanMapper: (val: boolean) => (val ? '1' : '0'),
37+
Serialize object to FormData instance.
5238

53-
/**
54-
* allow empty string or array
55-
* defaults to false
56-
*/
57-
allowEmptyValues: false,
39+
[DEMO](https://stackblitz.com/edit/typescript-br9t3k?file=index.ts)
40+
41+
<details>
42+
<summary>Options</summary>
43+
44+
```js
45+
const options = {
46+
/**
47+
* prefix for form data key
48+
* defaults empty string
49+
*/
50+
keyPrefix: '',
51+
52+
/**
53+
* prefix index for form data key
54+
* defaults to null
55+
*/
56+
index: null,
57+
58+
/**
59+
* callback fn for convert true or false
60+
* defaults true or false to '1' or '0' respectively
61+
*/
62+
booleanMapper: (val: boolean) => (val ? '1' : '0'),
5863

64+
/**
65+
* allow empty string or array
66+
* defaults to false
67+
*/
68+
allowEmptyValues: false,
69+
70+
/**
71+
* allow nullable values, ignore if emptyValues not allow
72+
* defaults to false
73+
*/
74+
allowNullableValues: false,
75+
};
76+
```
77+
</details>
78+
79+
```js
80+
import { createFormData } from '@idapgroup/js-object-utils';
81+
82+
const object = {
5983
/**
60-
* allow nullable values, ignore if emptyValues not allow
61-
* defaults to false
84+
* key-value mapping
85+
* values can be primitives or objects
6286
*/
63-
allowNullableValues: false,
6487
};
6588

6689
const formData = createFormData(
@@ -76,6 +99,39 @@ Serialize object to object with key and primitive value.
7699

77100
[DEMO](https://stackblitz.com/edit/typescript-1tpwga?file=index.ts)
78101

102+
<details>
103+
<summary>Options</summary>
104+
105+
```js
106+
const options = {
107+
/**
108+
* prefix for form data key
109+
* defaults empty string
110+
*/
111+
keyPrefix: '',
112+
113+
/**
114+
* prefix index for form data key
115+
* defaults to null
116+
*/
117+
index: null,
118+
119+
/**
120+
* prefix index for form data key
121+
* defaults to null
122+
*/
123+
toString: null,
124+
125+
/**
126+
* callback fn for convert true or false
127+
* defaults true or false to '1' or '0' respectively
128+
*/
129+
booleanMapper: (val: boolean) => (val ? '1' : '0'),
130+
};
131+
```
132+
133+
</details>
134+
79135
```js
80136
import { createURLParams } from '@idapgroup/js-object-utils';
81137

@@ -86,34 +142,43 @@ const object = {
86142
*/
87143
};
88144

89-
const options = {
90-
/**
91-
* prefix for form data key
92-
* defaults empty string
93-
*/
94-
keyPrefix: '',
145+
const params = createURLParams(
146+
object,
147+
options, // optional
148+
);
149+
```
95150

96-
/**
97-
* prefix index for form data key
98-
* defaults to null
99-
*/
100-
index: null,
101151

102-
/**
103-
* prefix index for form data key
104-
* defaults to null
105-
*/
106-
toString: null,
152+
### cleanObject
153+
154+
Remove nullable/empty values in object
107155

156+
<details>
157+
<summary>Options</summary>
158+
159+
```js
160+
const options = {
161+
/**
162+
* remove empty string, object, array in object
163+
* defaults false
164+
*/
165+
removeEmptyValues: false,
166+
};
167+
```
168+
</details>
169+
170+
```js
171+
import { cleanObject } from '@idapgroup/js-object-utils';
172+
173+
const object = {
108174
/**
109-
* callback fn for convert true or false
110-
* defaults true or false to '1' or '0' respectively
175+
* key-value mapping
176+
* values can be primitives or objects
111177
*/
112-
booleanMapper: (val: boolean) => (val ? '1' : '0'),
113178
};
114179

115-
const params = createURLParams(
116-
object,
180+
const obj = cleanObject(
181+
object,
117182
options, // optional
118183
);
119184
```

‎package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
},
1212
"license": "MIT",
1313
"scripts": {
14-
"build": "rm -rf build/ && run-p build:*",
14+
"build": "rimraf build/ && run-p build:*",
1515
"build:main": "tsc -p tsconfig.json",
1616
"build:module": "tsc -p tsconfig.module.json",
1717
"fix": "run-s fix:*",
@@ -46,6 +46,7 @@
4646
"npm-run-all": "^4.1.5",
4747
"nyc": "^15.1.0",
4848
"prettier": "^2.8.3",
49+
"rimraf": "^4.1.2",
4950
"ts-node": "^10.9.1",
5051
"typescript": "^4.9.4"
5152
},
@@ -66,7 +67,9 @@
6667
"formData",
6768
"object to formData",
6869
"object to url params",
69-
"url params"
70+
"url params",
71+
"is object",
72+
"clean object"
7073
],
7174
"author": "idapgroup"
7275
}

‎src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export { createURLParams } from './lib/create-url-params';
22
export { createFormData } from './lib/create-form-data';
33
export { cleanObject } from './lib/clean-object';
4+
export { isObject } from './lib/is-object';
45
export * from './types/create-url-params';
56
export * from './types/create-form-data';
67
export * from './types/clean-object';

‎src/lib/clean-object.ts

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,41 @@
1-
import { CleanObjectConfig, Record } from '../types/clean-object';
1+
import { CleanObjectConfig } from '../types/clean-object';
2+
3+
import { isObject } from './is-object';
24

35
const defaultConfig: CleanObjectConfig = {
46
removeEmptyValues: false,
57
};
68

9+
const isEmptyObject = (o: object) => Object.keys(o).length === 0;
10+
711
const needSkipValue = (
812
value: unknown,
913
{ removeEmptyValues }: CleanObjectConfig
1014
): boolean => {
1115
if (value === null || value === undefined) {
1216
return true;
1317
}
14-
if (typeof value !== 'string') {
15-
return false;
18+
if (removeEmptyValues) {
19+
if (Array.isArray(value)) {
20+
return value.length === 0;
21+
}
22+
if (typeof value === 'string') {
23+
return !value;
24+
}
25+
if (isObject(value) && isEmptyObject(value)) {
26+
return true;
27+
}
1628
}
17-
return value === '' && removeEmptyValues;
29+
return false;
1830
};
1931

20-
export const cleanObject = (
21-
obj: Record,
32+
export const cleanObject = <T extends object>(
33+
obj: T,
2234
config?: Partial<CleanObjectConfig>
23-
): Record => {
35+
): object => {
2436
const cfg = Object.assign({ ...defaultConfig }, config || {});
2537

26-
if (obj === null || obj === undefined) {
27-
return {};
28-
}
29-
30-
if (obj instanceof Blob || obj instanceof File || obj instanceof Date) {
38+
if (!isObject(obj)) {
3139
return obj;
3240
}
3341

@@ -39,22 +47,22 @@ export const cleanObject = (
3947

4048
const keys = Object.keys(obj);
4149
if (!keys.length) {
42-
return {};
50+
return obj;
4351
}
4452

45-
return keys.reduce((acc: Record, key) => {
46-
const item = obj[key];
53+
return keys.reduce((acc: object, key) => {
54+
const item = obj[key as keyof T];
4755
if (needSkipValue(item, cfg)) {
4856
return acc;
4957
}
5058
if (Array.isArray(item)) {
5159
if (!item.length && cfg.removeEmptyValues) {
5260
return acc;
5361
}
54-
const mapped = item.reduce((arr: Record[], curr) => {
55-
if (typeof curr === 'object' && curr) {
62+
const mapped = item.reduce((arr: object[], curr) => {
63+
if (isObject(curr)) {
5664
const cleared = cleanObject(curr, cfg);
57-
if (!Object.keys(cleared).length && cfg.removeEmptyValues) {
65+
if (isEmptyObject(cleared) && cfg.removeEmptyValues) {
5866
return arr;
5967
}
6068
return [...arr, cleared];
@@ -65,9 +73,9 @@ export const cleanObject = (
6573
return { ...acc, [`${key}`]: mapped };
6674
}
6775

68-
if (typeof item === 'object' && item) {
69-
const mapped = cleanObject(item as Record, cfg);
70-
if (!Object.keys(mapped).length && cfg.removeEmptyValues) {
76+
if (item && typeof item === 'object' && isObject(item)) {
77+
const mapped = cleanObject(item, cfg);
78+
if (isEmptyObject(mapped) && cfg.removeEmptyValues) {
7179
return acc;
7280
}
7381
return { ...acc, [`${key}`]: mapped };

‎src/lib/is-object.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export const isObject = (o: object): boolean =>
2+
Object.prototype.toString.call(o) === '[object Object]';

‎src/types/clean-object.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
export interface Record {
2-
[key: string]: unknown;
3-
}
4-
51
export interface CleanObjectConfig {
62
removeEmptyValues: boolean;
73
}

‎test/clean-object.spec.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ use(deepEqualInAnyOrder);
99
describe('cleanObject function', () => {
1010
it('should be success for simple values', () => {
1111
expect(cleanObject({})).to.deep.equal({});
12-
expect(cleanObject(null)).to.deep.equal({});
12+
expect(cleanObject(null)).to.deep.equal(null);
1313
const date = new Date();
1414
expect(cleanObject(date)).to.deep.equal(date);
1515
expect(cleanObject([])).to.deep.equal([]);
16+
const str = new String('test');
17+
expect(cleanObject(str)).to.deep.equal(str);
1618
});
1719

1820
it('should be success for nullable values obj', () => {
@@ -27,7 +29,7 @@ describe('cleanObject function', () => {
2729
active: false,
2830
status: null,
2931
file,
30-
previous: [],
32+
previous: [[]],
3133
obj: {},
3234
},
3335
file,
@@ -41,7 +43,7 @@ describe('cleanObject function', () => {
4143
subscription: {
4244
active: false,
4345
file,
44-
previous: [],
46+
previous: [[]],
4547
obj: {},
4648
},
4749
file,
@@ -50,7 +52,7 @@ describe('cleanObject function', () => {
5052
};
5153
expect(cleanObject(obj)).to.deep.equal(expectedResult);
5254
});
53-
it('should be success for empty string and array in obj', () => {
55+
it('should be success with removeEmptyValues option', () => {
5456
const obj = {
5557
id: 1,
5658
name: 'test',

0 commit comments

Comments
 (0)
Please sign in to comment.