feat(value-matcher): new package (#30)

This commit is contained in:
Julien Fontanet
2017-12-27 15:21:27 +01:00
committed by GitHub
parent a505ded8a1
commit 22e3037e85
6 changed files with 226 additions and 0 deletions

View File

@@ -30,6 +30,7 @@
"testRegex": "\\.spec\\.js$",
"transform": {
"complex-matcher/.+\\.jsx?$": "babel-7-jest",
"value-matcher/.+\\.jsx?$": "babel-7-jest",
"xo-cli/.+\\.jsx?$": "babel-7-jest",
"\\.jsx?$": "babel-jest"
}

View File

@@ -0,0 +1,27 @@
const { NODE_ENV = 'development' } = process.env
const __PROD__ = NODE_ENV === 'production'
const __TEST__ = NODE_ENV === 'test'
module.exports = {
comments: !__PROD__,
compact: __PROD__,
ignore: __TEST__ ? undefined : [ /\.spec\.js$/ ],
presets: [
[
'@babel/env',
{
debug: !__TEST__,
loose: true,
shippedProposals: true,
targets: __PROD__
? {
browsers: '>2%',
node: '4',
}
: { node: 'current' },
useBuiltIns: 'usage',
},
],
'@babel/flow',
],
}

View File

@@ -0,0 +1,24 @@
/benchmark/
/benchmarks/
*.bench.js
*.bench.js.map
/examples/
example.js
example.js.map
*.example.js
*.example.js.map
/fixture/
/fixtures/
*.fixture.js
*.fixture.js.map
*.fixtures.js
*.fixtures.js.map
/test/
/tests/
*.spec.js
*.spec.js.map
__snapshots__/

View File

@@ -0,0 +1,66 @@
# value-matcher [![Build Status](https://travis-ci.org/vatefr/xen-orchestra.png?branch=master)](https://travis-ci.org/vatefr/xen-orchestra)
> ${pkg.description}
## Install
Installation of the [npm package](https://npmjs.org/package/value-matcher):
```
> npm install --save value-matcher
```
## Usage
```js
import { createPredicate } from 'value-matcher'
[
{ user: 'sam', age: 65, active: false },
{ user: 'barney', age: 36, active: true },
{ user: 'fred', age: 40, active: false },
].filter(createPredicate({
__or: [
{ user: 'sam' },
{ active: true },
],
}))
// [
// { user: 'sam', age: 65, active: false },
// { user: 'barney', age: 36, active: true },
// ]
```
## Development
```
# Install dependencies
> yarn
# Run the tests
> yarn test
# Continuously compile
> yarn dev
# Continuously run the tests
> yarn dev-test
# Build for production (automatically called by npm install)
> yarn build
```
## Contributions
Contributions are *very* welcomed, either on the documentation or on
the code.
You may:
- report any [issue](https://github.com/vatesfr/xo-web/issues)
you've encountered;
- fork and create a pull request.
## License
ISC © [Vates SAS](https://vates.fr)

View File

@@ -0,0 +1,45 @@
{
"private": true,
"name": "value-matcher",
"version": "0.0.0",
"license": "ISC",
"description": "",
"keywords": [],
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/packages/value-matcher",
"bugs": "https://github.com/vatesfr/xo-web/issues",
"repository": {
"type": "git",
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"author": {
"name": "Julien Fontanet",
"email": "julien.fontanet@isonoe.net"
},
"preferGlobal": false,
"main": "dist/",
"bin": {},
"files": [
"dist/"
],
"engines": {
"node": ">=4"
},
"dependencies": {
"@babel/polyfill": "^7.0.0-beta.36"
},
"devDependencies": {
"@babel/cli": "^7.0.0-beta.36",
"@babel/core": "^7.0.0-beta.36",
"@babel/preset-env": "^7.0.0-beta.36",
"@babel/preset-flow": "^7.0.0-beta.36",
"cross-env": "^5.1.3",
"rimraf": "^2.6.2"
},
"scripts": {
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "rimraf dist/",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
}
}

View File

@@ -0,0 +1,63 @@
// @flow
// eslint-disable-next-line no-use-before-define
export type Pattern = OrPattern | NotPattern | ObjectPattern | ArrayPattern | ValuePattern
// one of the pattern must match
type OrPattern = {| __or: Array<Pattern> |}
// the pattern must not match
type NotPattern = {| __not: Pattern |}
// value is an object with properties matching the patterns
type ObjectPattern = { [string]: Pattern }
// value is an array and each patterns must match a different item
type ArrayPattern = Array<Pattern>
// value equals the pattern
type ValuePattern = bool | number | string
const match = (pattern: Pattern, value: any) => {
if (Array.isArray(pattern)) {
return Array.isArray(value) && pattern.every((subpattern, i) =>
// FIXME: subpatterns should match different subvalues
value.some(subvalue => match(subpattern, subvalue))
)
}
if (pattern !== null && typeof pattern === 'object') {
const keys = Object.keys(pattern)
const { length } = keys
if (length === 1) {
const [ key ] = keys
if (key === '__or') {
const orPattern: OrPattern = (pattern: any)
return orPattern.__or.some(subpattern => match(subpattern, value))
}
if (key === '__not') {
const notPattern: NotPattern = (pattern: any)
return !match(notPattern.__not, value)
}
}
if (value === null || typeof value !== 'object') {
return false
}
const objectPattern: ObjectPattern = (pattern: any)
for (let i = 0; i < length; ++i) {
const key = keys[i]
const subvalue = value[key]
if (subvalue === undefined || !match(objectPattern[key], subvalue)) {
return false
}
}
return true
}
return pattern === value
}
export const createPredicate = (pattern: Pattern) => (value: any) => match(pattern, value)