Compare commits

..

No commits in common. "v1.0.0" and "main" have entirely different histories.
v1.0.0 ... main

10 changed files with 268 additions and 77 deletions

11
.eslintrc.js Normal file
View file

@ -0,0 +1,11 @@
module.exports = {
"extends": "standard",
"plugins": [
"standard",
"promise",
"jest"
],
"env": {
"jest/globals": true
}
};

1
.gitignore vendored
View file

@ -1 +1,2 @@
node_modules
./coverage

View file

@ -1,3 +1,19 @@
env:
global:
- CC_TEST_REPORTER_ID=e1449b0f2e8eba8f08c56a292243145925aeb4f521e5682667ac6d704829ba4c
- GIT_COMMITTED_AT=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then git log -1 --pretty=format:%ct; else git log -1 --skip 1 --pretty=format:%ct; fi)
language: node_js
node_js:
- "7"
before_script:
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
- chmod +x ./cc-test-reporter
script:
- npm run test
# Preferably you will run test-reporter on branch update events. But
# if you setup travis to build PR updates only, you don't need to run
# the line below
- if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT; fi
# In the case where travis is setup to build PR updates only,
# uncomment the line below
# - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT

24
LICENSE Normal file
View file

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org>

85
README.md Normal file
View file

@ -0,0 +1,85 @@
# json-query-chain
[![Build Status](https://travis-ci.org/sharpshark28/json-query-chain.svg?branch=master)](https://travis-ci.org/sharpshark28/json-query-chain) [![npm version](https://badge.fury.io/js/json-query-chain.svg)](https://badge.fury.io/js/json-query-chain) ![Code Coverage](coverage.svg) [![Maintainability](https://api.codeclimate.com/v1/badges/4dc20d8b5e6a7334044d/maintainability)](https://codeclimate.com/github/sharpshark28/json-query-chain/maintainability)
Chain queries onto POJOs to return precise results.
## Usage
```javascript
import Query from 'json-query-chain';
let myQ = new Query(someJsonData)
.search('isActiveUser', true)
.results;
```
### Chainable Methods
#### Search
Currently supports booleans and strings. (See [#1](https://github.com/sharpshark28/json-query-chain/issues/1) for Integer Support)
##### By Boolean
```javascript
.search('isActiveUser', true)
```
##### By String
```javascript
.search('name', 'steele')
```
#### Filter
Simpler version of search using a custom function in the chain.
```javascript
.filter(a => a.age >= 21)
```
##### By Key
```javascript
.filterBy('age', x => x >= 21)
```
#### Sort
##### By Boolean
```javascript
.sort('isActiveUser', true)
```
##### By String
```javascript
.sort('name')
```
##### By Number
```javascript
.sort('netWorth')
```
#### Pagination
Page 1 with 5 results per page.
```javascript
.paginate(1, 5)
```
Page 2 wtih default of 10 results per page.
```javascript
.paginate(2)
```
## Tests
`npm test` runs tests through Jest

1
coverage.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="114" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><mask id="a"><rect width="114" height="20" rx="3" fill="#fff"/></mask><g mask="url(#a)"><path fill="#555" d="M0 0h62v20H0z"/><path fill="#4C1" d="M62 0h52v20H62z"/><path fill="url(#b)" d="M0 0h114v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,DejaVu Sans,Geneva,sans-serif" font-size="11"><text x="31" y="15" fill="#010101" fill-opacity=".3">coverage</text><text x="31" y="14">coverage</text><text x="87" y="15" fill="#010101" fill-opacity=".3">97.22%</text><text x="87" y="14">97.22%</text></g></svg>

After

Width:  |  Height:  |  Size: 735 B

View file

@ -1,47 +1,55 @@
module.exports = class Query {
constructor (data) {
this.data = data.map(item => {
item.sortScore = 0;
return item;
});
};
item.sortScore = 0
return item
})
}
get results () {
return this.data;
};
return this.data
}
filter (func) {
this.data = this.data.filter(func)
return this
}
filterBy (key, func) {
this.data = this.data.filter(item => func(item[key]))
return this
}
search (key, term, score = 0) {
switch (typeof term) {
case 'boolean':
this.data = this.data.filter(item => item[key] === term);
break;
this.data = this.data.filter(item => item[key] === term)
break
case 'string':
if (term.length >= 3) {
this.data = this.data.filter(item => {
let regFind = new RegExp(term, 'gi');
let termMatches = (item[key].match(regFind) || []).length;
item.sortScore += termMatches;
return termMatches;
});
}
break;
this.data = this.data.filter(item => {
let regFind = new RegExp(term, 'gi')
let termMatches = (item[key].match(regFind) || []).length
item.sortScore += termMatches
return termMatches
})
break
}
return this;
};
return this
}
sort (key = 'sortScore') {
this.data = this.data.sort((a, b) => {
if (a[key] < b[key]) return -1;
if (a[key] > b[key]) return 1;
return 0;
});
return this;
};
if (a[key] < b[key]) return -1
if (a[key] > b[key]) return 1
return 0
})
return this
}
paginate (page = 1, perPage = 10) {
let min = page * perPage - perPage;
let max = min + perPage;
this.data = this.data.slice(min, max);
return this;
};
};
let min = page * perPage - perPage
let max = min + perPage
this.data = this.data.slice(min, max)
return this
}
}

View file

@ -1,79 +1,109 @@
const Query = require('./index');
const TestData = require('./testdata.json');
const Query = require('./index')
const TestData = require('./testdata.json')
test('should not modify passed data without chain alterations', () => {
let query = new Query(TestData)
.results;
.results
expect(query).toMatchObject(TestData);
});
expect(query).toMatchObject(TestData)
})
test('should paginate with default params', () => {
let query = new Query(TestData)
.paginate()
.results;
.paginate()
.results
expect(query.length).toBe(9);
});
expect(query.length).toBe(9)
})
test('should paginate with custom page length', () => {
let query = new Query(TestData)
.paginate(1, 3)
.results;
.paginate(1, 3)
.results
expect(query.length).toBe(3);
expect(query.length).toBe(3)
expect(query[0].name).toBe('Haynes Meadows')
});
})
test('should paginate to second page with custom page length', () => {
let query = new Query(TestData)
.paginate(2, 3)
.results;
.paginate(2, 3)
.results
expect(query.length).toBe(3);
expect(query.length).toBe(3)
expect(query[0].name).toBe('Howard Buckley')
});
})
test('should search by boolean isActive', () => {
let query = new Query(TestData)
.search('isActive', true)
.results;
.search('isActive', true)
.results
expect(query.length).toBe(4);
});
expect(query.length).toBe(4)
})
test('should search by age', () => {
test('should search by name', () => {
let query = new Query(TestData)
.search('name', 'steele')
.results;
.search('name', 'steele')
.results
expect(query.length).toBe(2);
});
expect(query.length).toBe(2)
})
test('should sort by boolean isActive', () => {
let query = new Query(TestData)
.sort('isActive')
.results;
.sort('isActive')
.results
expect(query[0].name).toBe('Katelyn Steele');
});
expect(query[0].name).toBe('Katelyn Steele')
})
test('should sort by number netWorth', () => {
let query = new Query(TestData)
.sort('netWorth')
.results
expect(query[0].name).toBe('Howard Buckley') // Negative
expect(query[1].name).toBe('Natalia Petty') // 0
expect(query[query.length - 1].name).toBe('Newman Mays') // Richest
})
test('should sort by string name', () => {
let query = new Query(TestData)
.sort('name')
.results;
.sort('name')
.results
expect(query[0].name).toBe('Dudley Conner');
});
expect(query[0].name).toBe('Dudley Conner')
})
test('should filter', () => {
let isAgeOver33 = a => a.age > 33
let query = new Query(TestData)
.filter(isAgeOver33)
.results
expect(query[0].name).toBe('Howard Buckley')
})
test('should filter by key', () => {
let isNumGT33 = num => num > 33
let query = new Query(TestData)
.filterBy('age', isNumGT33)
.results
expect(query[0].name).toBe('Howard Buckley')
})
test('should chain everything together', () => {
let query = new Query(TestData)
.search('isActive', true)
.sort('name')
.paginate(1, 2)
.results;
.search('isActive', true)
.sort('name')
.paginate(1, 2)
.results
expect(query.length).toBe(2);
expect(query[0].name).toBe('Dudley Conner');
expect(query[query.length - 1].name).toBe('Haynes Meadows');
});
expect(query.length).toBe(2)
expect(query[0].name).toBe('Dudley Conner')
expect(query[query.length - 1].name).toBe('Haynes Meadows')
})

View file

@ -1,22 +1,32 @@
{
"name": "json-query-chain",
"version": "1.0.0",
"version": "1.1.3",
"description": "Chain queries onto POJOs to return precise results.",
"main": "index.js",
"scripts": {
"test": "jest"
"test": "jest --coverage && npm run badge",
"badge": "lcov-badge coverage/lcov.info -o coverage.svg",
"lint": "eslint ./*.js"
},
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/sharpshark28/json-query-chain.git"
},
"author": "Joe Wroten <joe@wroten.me>",
"author": "Ava Wroten <ava@wroten.me>",
"license": "ISC",
"bugs": {
"url": "https://github.com/sharpshark28/json-query-chain/issues"
},
"homepage": "https://github.com/sharpshark28/json-query-chain#readme",
"devDependencies": {
"jest": "^20.0.4"
"eslint": "^4.18.1",
"eslint-config-standard": "^11.0.0",
"eslint-plugin-import": "^2.9.0",
"eslint-plugin-jest": "^21.12.2",
"eslint-plugin-node": "^6.0.0",
"eslint-plugin-promise": "^3.6.0",
"eslint-plugin-standard": "^3.0.1",
"jest": "^20.0.4",
"lcov-badge": "^1.0.4"
}
}

View file

@ -3,6 +3,7 @@
"_id": "5928038b69b33613f3577487",
"isActive": true,
"age": 20,
"netWorth": 54200.49,
"name": "Haynes Meadows",
"tags": [
"et",
@ -18,6 +19,7 @@
"_id": "5928038ba2400e7e09550991",
"isActive": false,
"age": 22,
"netWorth": 11900,
"name": "Katelyn Steele",
"tags": [
"cupidatat",
@ -33,6 +35,7 @@
"_id": "5928038bff4df5c29016be22",
"isActive": false,
"age": 29,
"netWorth": 0,
"name": "Natalia Petty",
"tags": [
"nulla",
@ -48,6 +51,7 @@
"_id": "5928038b496f64e646cb8d69",
"isActive": false,
"age": 34,
"netWorth": -5000.2,
"name": "Howard Buckley",
"tags": [
"qui",
@ -63,6 +67,7 @@
"_id": "5928038b4d214186ba1e7fa2",
"isActive": false,
"age": 22,
"netWorth": 401512.99,
"name": "Jenkins Mosley",
"tags": [
"adipisicing",