Skip to content

Commit

Permalink
v2.0.0 🕺🏻
Browse files Browse the repository at this point in the history
  • Loading branch information
mesqueeb committed Feb 22, 2020
1 parent 861068c commit 313446e
Show file tree
Hide file tree
Showing 21 changed files with 1,984 additions and 2,024 deletions.
8 changes: 8 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# don't ever lint node_modules
node_modules
# don't lint build output (make sure it's set to your correct build folder name)
dist
# don't lint nyc coverage output
coverage

test
17 changes: 17 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// npm i -D @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-config-prettier eslint-plugin-tree-shaking
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'tree-shaking'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'prettier/@typescript-eslint'
],
rules: {
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/ban-ts-ignore': 'off',
'tree-shaking/no-side-effects-in-initialization': 'error'
}
}
Binary file added .github/typescript-fillable.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/typescript-guard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"printWidth": 100,
"tabWidth": 2,
"singleQuote": true,
"trailingComma": "es5",
"semi": false,
"bracketSpacing": true,
"quoteProps": "consistent"
}
73 changes: 40 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ Filter out object props based on "fillables" and "guard". A simple & small integ

## Motivation

I created this package because I needed to filter object props on fillables or guard and **have support for sub-properties**.
I created this package because I needed:

- be able to filter out object props based on just what we need - aka "fillables"
- be able to filter out object props based on what we don't need - aka "guarded" props
- **supports for nested properties**
- supports wildcards `*` for nested properties

## Meet the family

Expand All @@ -22,70 +27,72 @@ I created this package because I needed to filter object props on fillables or g

## Usage

You can filter out any prop in an object based on fillables or guard.
### Fillable

With `fillable` pass an array of keys of an object - the props which may stay.

```js
import { fillable } from 'filter-anything'

- Fillables: Array of keys - the props which may stay
- 0 fillables = all props stay
- 1 or more fillables = only those props stay (any prop not in fillables is removed)
- Guard: Array of keys - the props which should be removed
- adding any prop here will make sure it's removed
const squirtle = { id: '007', name: 'Squirtle', type: 'water' }

You can use it by doing `filter(object, fillables, guard)` and it will return the `object` with just the props as per the fillables and/or guard!
const withoutId = fillable(squirtle, ['name', 'type'])
// returns { name: 'Squirtle', type: 'water' }
```

### Simple example
### Guard

In the example below we want to get rid of the properties called "discard1" and "discard2".
With `guard` pass an array of keys of an object - the props which should be removed.

```js
import filter from 'filter-anything'

const doc = {keep1: '📌', keep2: '🧷', keep3: '📎', discard1: '✂️', discard2: '🖍'}
import { guard } from 'filter-anything'

// via fillables
const fillables = ['keep1', 'keep2', 'keep3']
filter(doc, fillables)
// returns {keep1: 1, keep2: 1, keep3: 1}
const squirtle = { id: '007', name: 'Squirtle', type: 'water' }

// OR via guard
const guard = ['discard1', 'discard2']
filter(doc, [], guard)
// returns {keep1: 1, keep2: 1, keep3: 1}
const withoutId = guard(squirtle, ['name', 'type'])
// returns { name: 'Squirtle', type: 'water' }
```

### Nested example
### TypeScript

TypeScript users will love this, because, as you can see, the result has the correct type automatically!

![typescript example fillable](https://raw.githubusercontent.com/mesqueeb/filter-anything/master/.github/typescript-fillable.png)
![typescript example guard](https://raw.githubusercontent.com/mesqueeb/filter-anything/master/.github/typescript-guard.png)

### Nested props

In the example below we want to get rid of the **nested property** called "discard".

```js
const doc = {items: {keep: '📌', discard: '✂️'}}
const doc = { items: { keep: '📌', discard: '✂️' } }

// via fillables:
const fillables = ['items.keep']
filter(doc, fillables)
fillable(doc, ['items.keep'])
// returns {items: {keep: '📌'}}

// OR via guard:
const guard = ['items.discard']
filter(doc, [], guard)
guard(doc, ['items.discard'])
// returns {items: {keep: '📌'}}
```

> Please note that TypeScript users will need to cast the result when using nested props.
## Wildcards

Yes! You can also work with wildcards by using `*` in the path.

```js
const doc = {
'123': {keep: '📌', discard: '✂️'},
'456': {keep: '📌', discard: '✂️'}
'123': { keep: '📌', discard: '✂️' },
'456': { keep: '📌', discard: '✂️' },
}
// use wildcard *
const guard = ['*.discard']
filter(doc, [], guard)
guard(doc, ['*.discard'])
// returns {
// '123': {keep: '📌'},
// '456': {keep: '📌'}
// }
```

> Please note that TypeScript users will need to cast the result when using wildcards props.
Feel free to open issues for any requests, questions or bugs!
33 changes: 15 additions & 18 deletions build/rollup.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import typescript from 'rollup-plugin-typescript2'
// ------------------------------------------------------------------------------------------
const pkg = require('../package.json')
const name = pkg.name
const className = name.replace(/(^\w|-\w)/g, c => c.replace('-', '').toUpperCase())
const className = name.replace(/(^\w|-\w)/g, c =>
c.replace('-', '').toUpperCase()
)
const external = Object.keys(pkg.dependencies || [])
const plugins = [
typescript({useTsconfigDeclarationDir: true}),
]
const plugins = [typescript({ useTsconfigDeclarationDir: true })]

// ------------------------------------------------------------------------------------------
// Builds
Expand All @@ -37,10 +37,13 @@ function defaults (config) {
}
// defaults.output
config.output = config.output.map(output => {
return Object.assign({
sourcemap: false,
name: className,
}, output)
return Object.assign(
{
sourcemap: false,
name: className
},
output
)
})
return Object.assign(defaults, config)
}
Expand All @@ -49,14 +52,8 @@ export default [
defaults({
input: 'src/index.ts',
output: [
{file: 'dist/index.cjs.js', format: 'cjs'},
{file: 'dist/index.esm.js', format: 'esm'},
],
}),
defaults({
input: 'src/pathsAreEqual.ts',
output: [
{file: 'test/helpers/pathsAreEqual.cjs.js', format: 'cjs'},
],
}),
{ file: 'dist/index.cjs.js', format: 'cjs' },
{ file: 'dist/index.esm.js', format: 'esm' }
]
})
]
77 changes: 60 additions & 17 deletions dist/index.cjs.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,35 @@
'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var isWhat = require('is-what');

function pathsAreEqual (path, wildcardPath) {
function pathsAreEqual(path, wildcardPath) {
var wildcardPathPieces = wildcardPath.split('.');
var pathWithWildcards = path.split('.')
var pathWithWildcards = path
.split('.')
.reduce(function (carry, piece, index) {
var add = (wildcardPathPieces[index] === '*') ? '*' : piece;
var add = wildcardPathPieces[index] === '*' ? '*' : piece;
carry.push(add);
return carry;
}, []).join('.');
return (pathWithWildcards === wildcardPath);
}, [])
.join('.');
return pathWithWildcards === wildcardPath;
}

function recursiveFilter(obj, fillables, guard, pathUntilNow) {
function recursiveFilter(obj, fillables, guarded, pathUntilNow) {
if (pathUntilNow === void 0) { pathUntilNow = ''; }
if (!isWhat.isPlainObject(obj)) {
return obj;
}
// @ts-ignore
return Object.keys(obj).reduce(function (carry, key) {
var path = pathUntilNow;
if (path)
path += '.';
path += key;
// check guard regardless
if (guard.some(function (guardPath) { return pathsAreEqual(path, guardPath); })) {
if (guarded.some(function (guardPath) { return pathsAreEqual(path, guardPath); })) {
return carry;
}
var value = obj[key];
Expand Down Expand Up @@ -54,23 +59,61 @@ function recursiveFilter(obj, fillables, guard, pathUntilNow) {
carry[key] = value;
return carry;
}
carry[key] = recursiveFilter(obj[key], fillables, guard, path);
carry[key] = recursiveFilter(obj[key], fillables, guarded, path);
return carry;
}, {});
}
}

/**
* Checks all props of an object and deletes guarded and non-fillables.
* Returns a new object with only the props passed as fillables
*
* @export
* @param {object} obj the target object to check
* @param {string[]} [fillables=[]] an array of strings, with the props which should be allowed on returned object
* @param {string[]} [guard=[]] an array of strings, with the props which should NOT be allowed on returned object
* @returns {AnyObject} the cleaned object after deleting guard and non-fillables
*/
function index (obj, fillables, guard) {
if (fillables === void 0) { fillables = []; }
if (guard === void 0) { guard = []; }
return recursiveFilter(obj, fillables, guard);
}
function fillable(obj, fillables) {
// @ts-ignore
if (!fillables.length)
return {};
// @ts-ignore
return recursiveFilter(obj, fillables, []);
}
/**
* Returns a new object without guarded props
*
* @export
* @param {object} obj the target object to check
* @param {string[]} [guarded=[]] an array of strings, with the props which should NOT be allowed on returned object
* @returns {AnyObject} the cleaned object after deleting guard and non-fillables
*/
function guard(obj, guarded) {
// @ts-ignore
return recursiveFilter(obj, [], guarded);
}
// /**
// * Returns a new object but with only the props passed as fillables and/or without guarded props
// *
// * @export
// * @param {object} obj the target object to check
// * @param {string[]} fillables array of strings, with the props which should be allowed on returned object
// * @param {string[]} [guarded=[]] an array of strings, with the props which should NOT be allowed on returned object
// * @returns {AnyObject} the cleaned object after deleting guard and non-fillables
// */
// export function filter<
// T extends object,
// KeyToKeep extends string,
// KeyToDelete extends string,
// KeysToKeep extends KeyToKeep[],
// KeysToDelete extends KeyToDelete[]
// > (
// obj: T,
// fillables: KeysToKeep,
// guarded?: KeysToDelete
// ) {
// // @ts-ignore
// return recursiveFilter(obj, fillables, guarded)
// }

module.exports = index;
exports.fillable = fillable;
exports.guard = guard;
Loading

0 comments on commit 313446e

Please sign in to comment.