Compare commits

..

19 commits
v1.1.0 ... main

Author SHA1 Message Date
Ava Gaiety Wroten
74bfa76a4e Update package.json 2020-09-21 23:27:13 +00:00
Jo Wroten
4c31065249 Add LICENSE 2019-08-07 03:33:03 +00:00
sharpshark28
195121070f 1.1.3 2018-02-22 19:28:53 -06:00
sharpshark28
01ca521789 Eslint 2018-02-22 19:14:15 -06:00
sharpshark28
182b8be1d4 Removing codeclimate yml 2018-02-22 18:55:58 -06:00
sharpshark28
70cfecd483 Code climate badge fix 2018-02-22 18:54:57 -06:00
sharpshark28
a53e88ac9e Coverage badge 2018-02-22 18:45:22 -06:00
sharpshark28
c95faba670 Coverage 2018-02-22 18:44:27 -06:00
Joe L Wroten
f037201b20 Merge pull request #12 from sharpshark28/climateyml
Code climate yml
2017-08-20 21:16:11 -05:00
Joe L Wroten
fd4e034cd9 Merge branch 'master' into climateyml 2017-08-20 21:14:08 -05:00
sharpshark28
457b4bc1da Code climate yml 2017-08-20 21:12:18 -05:00
Joe L Wroten
6c24592e43 Merge pull request #10 from sharpshark28/CodeClimate
Code climate fixes, travis config, badge
2017-08-20 20:25:24 -05:00
sharpshark28
a45271da5a Code climate fixes, travis config, badge 2017-08-20 20:21:44 -05:00
sharpshark28
9616a5b783 1.1.2 2017-08-17 18:21:29 -05:00
Joe L Wroten
652d417f66 Merge pull request #6 from sharpshark28/2
Test to prove sorting by integer works
2017-08-17 18:21:13 -05:00
sharpshark28
82e9f5ed5b Filter docs 2017-08-17 18:21:06 -05:00
sharpshark28
6364d326cd Test to prove sorting by integer works 2017-08-17 18:17:06 -05:00
sharpshark28
a10ac23e1a 1.1.1 2017-08-17 18:02:06 -05:00
sharpshark28
810e7c7b5a Search works with any length of term 2017-08-17 18:01:46 -05:00
10 changed files with 189 additions and 95 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 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 language: node_js
node_js: node_js:
- "7" - "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>

View file

@ -1,6 +1,6 @@
# json-query-chain # 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) [![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. Chain queries onto POJOs to return precise results.
@ -32,9 +32,21 @@ Currently supports booleans and strings. (See [#1](https://github.com/sharpshark
.search('name', 'steele') .search('name', 'steele')
``` ```
#### Sort #### Filter
Currently supports booleans and strings. (See [#1](https://github.com/sharpshark28/json-query-chain/issues/2) for Integer Support) 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 ##### By Boolean
@ -48,6 +60,12 @@ Currently supports booleans and strings. (See [#1](https://github.com/sharpshark
.sort('name') .sort('name')
``` ```
##### By Number
```javascript
.sort('netWorth')
```
#### Pagination #### Pagination
Page 1 with 5 results per page. Page 1 with 5 results per page.

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

View file

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

View file

@ -1,22 +1,32 @@
{ {
"name": "json-query-chain", "name": "json-query-chain",
"version": "1.1.0", "version": "1.1.3",
"description": "Chain queries onto POJOs to return precise results.", "description": "Chain queries onto POJOs to return precise results.",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "jest" "test": "jest --coverage && npm run badge",
"badge": "lcov-badge coverage/lcov.info -o coverage.svg",
"lint": "eslint ./*.js"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+ssh://git@github.com/sharpshark28/json-query-chain.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", "license": "ISC",
"bugs": { "bugs": {
"url": "https://github.com/sharpshark28/json-query-chain/issues" "url": "https://github.com/sharpshark28/json-query-chain/issues"
}, },
"homepage": "https://github.com/sharpshark28/json-query-chain#readme", "homepage": "https://github.com/sharpshark28/json-query-chain#readme",
"devDependencies": { "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", "_id": "5928038b69b33613f3577487",
"isActive": true, "isActive": true,
"age": 20, "age": 20,
"netWorth": 54200.49,
"name": "Haynes Meadows", "name": "Haynes Meadows",
"tags": [ "tags": [
"et", "et",
@ -18,6 +19,7 @@
"_id": "5928038ba2400e7e09550991", "_id": "5928038ba2400e7e09550991",
"isActive": false, "isActive": false,
"age": 22, "age": 22,
"netWorth": 11900,
"name": "Katelyn Steele", "name": "Katelyn Steele",
"tags": [ "tags": [
"cupidatat", "cupidatat",
@ -33,6 +35,7 @@
"_id": "5928038bff4df5c29016be22", "_id": "5928038bff4df5c29016be22",
"isActive": false, "isActive": false,
"age": 29, "age": 29,
"netWorth": 0,
"name": "Natalia Petty", "name": "Natalia Petty",
"tags": [ "tags": [
"nulla", "nulla",
@ -48,6 +51,7 @@
"_id": "5928038b496f64e646cb8d69", "_id": "5928038b496f64e646cb8d69",
"isActive": false, "isActive": false,
"age": 34, "age": 34,
"netWorth": -5000.2,
"name": "Howard Buckley", "name": "Howard Buckley",
"tags": [ "tags": [
"qui", "qui",
@ -63,6 +67,7 @@
"_id": "5928038b4d214186ba1e7fa2", "_id": "5928038b4d214186ba1e7fa2",
"isActive": false, "isActive": false,
"age": 22, "age": 22,
"netWorth": 401512.99,
"name": "Jenkins Mosley", "name": "Jenkins Mosley",
"tags": [ "tags": [
"adipisicing", "adipisicing",