Skip to content

Commit 0c0c8f2

Browse files
committed
feat(*): initial commit
0 parents  commit 0c0c8f2

File tree

11 files changed

+6434
-0
lines changed

11 files changed

+6434
-0
lines changed

.github/workflows/pull_requests.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Pull Requests
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- master
7+
8+
jobs:
9+
test:
10+
name: Test on node ${{ matrix.node_version }} and ${{ matrix.os }}
11+
runs-on: ubuntu-latest
12+
13+
strategy:
14+
matrix:
15+
node-version: [11.x]
16+
17+
steps:
18+
- uses: actions/checkout@v1
19+
- name: Use Node.js ${{ matrix.node-version }}
20+
uses: actions/setup-node@v1
21+
with:
22+
node-version: ${{ matrix.node-version }}
23+
- name: npm install, build and test
24+
run: |
25+
yarn install
26+
yarn build
27+
yarn test
28+
env:
29+
CI: true

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
*.log
2+
.DS_Store
3+
node_modules
4+
.rts2_cache_cjs
5+
.rts2_cache_esm
6+
.rts2_cache_umd
7+
.rts2_cache_system
8+
dist

.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
!/dist

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019 Rohman Habib M
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# purify-obj
2+
3+
> Purify & clean objects recursively, deleting undefined & null or falsy properties.
4+
5+
## Install
6+
7+
```
8+
$ npm install purify-obj
9+
```
10+
11+
Or
12+
13+
```
14+
$ yarn add purify-obj
15+
```
16+
17+
## Usage
18+
19+
```js
20+
import { PurifyObj } from "purify-obj";
21+
// Or
22+
const { PurifyObj } = require("purify-obj");
23+
// Or you can use the `po` shortcut
24+
import { po } from "purify-obj";
25+
26+
const object = {
27+
className: "only-this-obj-key-will-persist",
28+
disabled: "",
29+
autoComplete: false,
30+
checked: undefined,
31+
spellCheck: null
32+
};
33+
const newObject = po(object);
34+
//=> {className: 'only-this-obj-key-will-persist'}
35+
```
36+
37+
## API
38+
39+
### PurifyObj(source, strict)
40+
41+
#### source
42+
43+
Type: `object`
44+
45+
Source object to purify properties from.
46+
47+
#### strict
48+
49+
Type: `boolean`
50+
51+
Strict will purify all falsy key
52+
53+
## Local Development
54+
55+
Below is a list of commands you will probably find useful.
56+
57+
### `npm start` or `yarn start`
58+
59+
Runs the project in development/watch mode. Your project will be rebuilt upon changes. TSDX has a special logger for you convenience. Error messages are pretty printed and formatted for compatibility VS Code's Problems tab.
60+
61+
Your library will be rebuilt if you make edits.
62+
63+
### `npm run build` or `yarn build`
64+
65+
Bundles the package to the `dist` folder.
66+
The package is optimized and bundled with Rollup into multiple formats (CommonJS, UMD, and ES Module).
67+
68+
### `npm test` or `yarn test`
69+
70+
Runs the test watcher (Jest) in an interactive mode.
71+
By default, runs tests related to files changed since the last commit.
72+
73+
## Related
74+
75+
- [clean-obj](https://github.com/ricardofbarros/clean-obj) - Clean objects recursively, deleting undefined & null or falsy properties.

package.json

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"name": "purify-obj",
3+
"version": "0.1.0",
4+
"license": "MIT",
5+
"main": "dist/index.js",
6+
"module": "dist/purify-obj.esm.js",
7+
"typings": "dist/index.d.ts",
8+
"repository": "rohmanhm/purify-obj",
9+
"description": "Purify & clean objects recursively, deleting undefined & null or falsy properties.",
10+
"author": {
11+
"name": "Rohman Habib M",
12+
"email": "rohmanhm@icloud.com",
13+
"url": "https://rohmanhm.github.com"
14+
},
15+
"keywords": [
16+
"purify",
17+
"clean",
18+
"object",
19+
"key",
20+
"keys",
21+
"value",
22+
"values",
23+
"iterate",
24+
"iterator"
25+
],
26+
"files": [
27+
"dist"
28+
],
29+
"scripts": {
30+
"start": "tsdx watch",
31+
"build": "tsdx build",
32+
"test": "tsdx test",
33+
"lint": "tsdx lint"
34+
},
35+
"peerDependencies": {},
36+
"husky": {
37+
"hooks": {
38+
"pre-commit": "tsdx lint"
39+
}
40+
},
41+
"prettier": {
42+
"printWidth": 80,
43+
"semi": true,
44+
"singleQuote": true,
45+
"trailingComma": "es5"
46+
},
47+
"devDependencies": {
48+
"@types/jest": "^24.0.23",
49+
"husky": "^3.1.0",
50+
"tsdx": "^0.11.0",
51+
"tslib": "^1.10.0",
52+
"typescript": "^3.7.2"
53+
}
54+
}

src/index.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { isEmpty } from './isEmpty';
2+
3+
// Type of object shape
4+
export type ObjectShape = { [key: string]: any };
5+
// Type of ignored type
6+
export type IgnoredTypes = null | undefined;
7+
// Util to extract type from <T> value
8+
export type MethodKeys<T, U> = {
9+
[P in keyof T]: T[P] extends U ? never : P;
10+
}[keyof T];
11+
// Util to remove ignored key
12+
export type RemoveIgnoredKey<T> = Pick<T, MethodKeys<T, IgnoredTypes>> | null;
13+
// Type object return
14+
export type PurifyObjReturn<ObjectType> = RemoveIgnoredKey<ObjectType>;
15+
16+
const toStr = Object.prototype.toString;
17+
18+
export function PurifyObj<ObjectType extends ObjectShape>(
19+
obj: ObjectType,
20+
strict?: boolean
21+
): PurifyObjReturn<ObjectType> {
22+
strict = strict || false;
23+
24+
let newObj = _purifyObj(obj, strict);
25+
26+
if (newObj === null) {
27+
newObj = {} as any;
28+
}
29+
30+
return newObj;
31+
}
32+
33+
export const po = PurifyObj;
34+
35+
function _purifyObj<ObjectType extends ObjectShape>(
36+
obj: ObjectType,
37+
strict: boolean
38+
): PurifyObjReturn<ObjectType> {
39+
let k: string;
40+
for (k in obj) {
41+
purifyProperty(k, obj[k], obj);
42+
}
43+
44+
// Check if the object is empty
45+
// If it is return null to delete the object
46+
if (!isEmpty(obj)) {
47+
return obj;
48+
} else {
49+
return null;
50+
}
51+
52+
function purifyProperty(key: string, value: any, ref: ObjectShape) {
53+
if (!shouldPurifyProperty(value)) {
54+
delete ref[key];
55+
return;
56+
}
57+
58+
const typeOfValue = typeof value;
59+
60+
// If value is an object (excluding date objects)
61+
if (typeOfValue === 'object' && toStr.call(value) !== '[object Date]') {
62+
// Exception - If array
63+
if (toStr.call(obj[k]) === '[object Array]') {
64+
ref[key] = ref[key].filter(shouldPurifyProperty);
65+
} else {
66+
_purifyObj(ref[key], strict);
67+
}
68+
69+
if (isEmpty(ref[key])) {
70+
delete ref[key];
71+
}
72+
}
73+
}
74+
75+
function shouldPurifyProperty(value: any) {
76+
return !(!value && (strict || (!strict && value == null)));
77+
}
78+
}
79+
80+
export { isEmpty };

src/isEmpty.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const hasOwnProp = Object.prototype.hasOwnProperty;
2+
3+
export function isEmpty<ObjectType extends { [key: string]: unknown }>(
4+
obj: ObjectType
5+
) {
6+
// Check if obj has .length property
7+
// and if === 0 - it's empty
8+
if (obj.length) {
9+
return obj.length === 0;
10+
}
11+
12+
// Otherwise, does it have any properties of its own?
13+
for (const key in obj) {
14+
if (hasOwnProp.call(obj, key)) return false;
15+
}
16+
17+
// Fallback
18+
return true;
19+
}

test/index.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { po } from '../src';
2+
3+
test('remove null and undefined key value', () => {
4+
const expected = {
5+
className: 'only-this-obj-key-will-persist',
6+
disabled: '',
7+
autoComplete: false,
8+
};
9+
10+
const actual = po({
11+
...expected,
12+
disabled: '',
13+
autoComplete: false,
14+
checked: undefined,
15+
spellCheck: null,
16+
});
17+
18+
expect(actual).toEqual(expected);
19+
});
20+
21+
test('strict mode remove falsy key value', () => {
22+
const expected = {
23+
className: 'only-this-obj-key-will-persist',
24+
};
25+
26+
const actual = po(
27+
{
28+
...expected,
29+
disabled: '',
30+
autoComplete: false,
31+
checked: undefined,
32+
spellCheck: null,
33+
},
34+
true
35+
);
36+
37+
expect(actual).toEqual(expected);
38+
});

tsconfig.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"include": ["src", "types", "test"],
3+
"compilerOptions": {
4+
"target": "es5",
5+
"module": "esnext",
6+
"lib": ["dom", "esnext"],
7+
"importHelpers": true,
8+
"declaration": true,
9+
"sourceMap": true,
10+
"rootDir": "./",
11+
"strict": true,
12+
"strictNullChecks": true,
13+
"strictFunctionTypes": true,
14+
"strictPropertyInitialization": true,
15+
"noImplicitThis": true,
16+
"alwaysStrict": true,
17+
"noUnusedLocals": true,
18+
"noUnusedParameters": true,
19+
"noImplicitReturns": true,
20+
"noFallthroughCasesInSwitch": true,
21+
"moduleResolution": "node",
22+
"baseUrl": "./",
23+
"esModuleInterop": true
24+
}
25+
}

0 commit comments

Comments
 (0)