From b21feb48ff11a5d292fa18392b9cf7a3af26861b Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Fri, 15 Jul 2016 10:01:25 -0700 Subject: [PATCH 01/50] refactor(document): remove function to match python wrapper --- src/api/document.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/api/document.js b/src/api/document.js index c7426df..b7313d9 100644 --- a/src/api/document.js +++ b/src/api/document.js @@ -3,11 +3,6 @@ export default class DocumentAPI { this.client = client; } - list(schema) { - const endpoint = `schemas/${schema}/documents/`; - return this.client.request(endpoint); - } - save(schema, documents) { const endpoint = `schemas/${schema}/documents/`; return this.client.request(endpoint, 'POST', documents); From a5ebba55d42123ad4031c47fb9b222915153a7f8 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 1 Aug 2016 12:24:50 -0700 Subject: [PATCH 02/50] refactor(document api): replace remove function with delete; warn user with a feature deprecated message on using remove --- src/api/document.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/api/document.js b/src/api/document.js index b7313d9..3f551a6 100644 --- a/src/api/document.js +++ b/src/api/document.js @@ -23,8 +23,14 @@ export default class DocumentAPI { return this.client.request(endpoint, 'PATCH', document); } - remove(schema, document_id) { + delete(schema, document_id) { const endpoint = `schemas/${schema}/documents/${document_id}/`; return this.client.request(endpoint, 'DELETE'); } + + remove(schema, document_id) { + console.warn("The function remove() is deprecated, use delete()."); + + return this.delete(schema, document_id); + } } From 272c2d87902a0b2bcb5bba82bde2d5c0d9416c53 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 1 Aug 2016 12:28:17 -0700 Subject: [PATCH 03/50] refactor(file api): replace remove function with delete; warn user with a feature deprecated message on using remove --- src/api/file.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/api/file.js b/src/api/file.js index 08645d1..3861c0a 100644 --- a/src/api/file.js +++ b/src/api/file.js @@ -11,11 +11,17 @@ export default class FileAPI { return this.client.request(`files/${file_id}/`); } - remove(file_id) { - const endpoint = `files/${file_id}/`; + delete(file_id) { + const endpoint = `/files/${file_id}/`; return this.client.request(endpoint, 'DELETE'); } + remove(file_id) { + console.warn("The function remove() is deprecated, use delete()."); + + return this.delete(file_id); + } + save(formData) { return this.client.request('files/', 'POST', formData, true); } From f74122fbb32aff030fd60cd4f9dd3a91b6ce4d81 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 1 Aug 2016 12:30:19 -0700 Subject: [PATCH 04/50] refactor(policy api): replace remove function with delete; warn user with a feature deprecated message on using remove --- src/api/policy.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/api/policy.js b/src/api/policy.js index baed3cd..664d935 100644 --- a/src/api/policy.js +++ b/src/api/policy.js @@ -40,10 +40,16 @@ export default class PolicyAPI { } } - remove(policy_id) { + delete(policy_id) { return this.client.request(`policy/${policy_id}/`, 'DELETE'); } + remove(policy_id) { + console.warn("The function remove() is deprecated, use delete()."); + + return this.delete(policy_id); + } + checkPermission(action, resource) { var payload = { action, From 85f1c0d6f6186340ba1074547ba811f681313ac6 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 1 Aug 2016 12:35:21 -0700 Subject: [PATCH 05/50] refactor(role api): replace remove function with delete; warn user with a feature deprecated message on using remove --- src/api/role.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/api/role.js b/src/api/role.js index 95bc1c2..da31765 100644 --- a/src/api/role.js +++ b/src/api/role.js @@ -36,7 +36,13 @@ export default class RoleAPI { } } - remove(role) { + delete(role) { return this.client.request(`roles/${role}/`, 'DELETE'); } + + remove(role) { + console.warn("The function remove() is deprecated, use delete()."); + + return this.delete(role); + } } From 7c427229415b7d89a0a56b5009a1371a09abf9fd Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 1 Aug 2016 12:36:48 -0700 Subject: [PATCH 06/50] refactor(schema api): replace remove function with delete; warn user with a feature deprecated message on using remove --- src/api/schema.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/api/schema.js b/src/api/schema.js index be0f80e..0c40a87 100644 --- a/src/api/schema.js +++ b/src/api/schema.js @@ -32,7 +32,13 @@ export default class SchemaAPI { } } - remove(schema) { + delete(schema) { return this.client.request(`schemas/${schema}/`, 'DELETE'); } + + remove(schema) { + console.warn("The function remove() is deprecated, use delete()."); + + return this.delete(schema); + } } From 4f5dd5e7f67a53a9874ebfd3be9bf05d42afa276 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 1 Aug 2016 12:37:58 -0700 Subject: [PATCH 07/50] refactor(user api): replace remove function with delete; warn user with a feature deprecated message on using remove --- src/api/user.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/api/user.js b/src/api/user.js index bd58f6c..0cd6f18 100644 --- a/src/api/user.js +++ b/src/api/user.js @@ -36,7 +36,13 @@ export default class UserAPI { } } - remove(user_id) { + delete(user_id) { return this.client.request(`users/${user_id}/`, 'DELETE'); } + + remove(user_id) { + console.warn("The function remove() is deprecated, use delete()."); + + return this.delete(user_id); + } } From badcabd1dd8fd280bbaebadbe41d45953348fc19 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 1 Aug 2016 18:48:53 -0700 Subject: [PATCH 08/50] refactor(query): update Query object to pass in named parameters/objects --- src/query.js | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/query.js b/src/query.js index a41cf78..3204603 100644 --- a/src/query.js +++ b/src/query.js @@ -10,18 +10,19 @@ export default class Query { toJS() { return { + $type: 'query', $schema: this.schema, $query: this.terms }; } get(id) { - this.terms.push(['$get', id]); + this.terms.push(['$get', {id}]); return this; } getAll(ids, index = 'id') { - this.terms.push(['$get_all', [index, ids]]); + this.terms.push(['$get_all', [{index, ids}]]); return this; } @@ -30,17 +31,17 @@ export default class Query { return filterSet.concat(currentFilter.toJS()); }, []); - this.terms.push(['$filter', filterSet]); + this.terms.push(['$filter', {filterSet}]); return this; } hasFields(...fields) { - this.terms.push(['$has_fields', fields]) + this.terms.push(['$has_fields', {fields}]) return this; } withFields(...fields) { - this.terms.push(['$with_fields', fields]) + this.terms.push(['$with_fields', {fields}]) return this; } @@ -55,27 +56,27 @@ export default class Query { } skip(num) { - this.terms.push(['$skip', num]); + this.terms.push(['$skip', {num}]); return this; } limit(num) { - this.terms.push(['$limit', num]); + this.terms.push(['$limit', {num}]); return this; } slice(start, end) { - this.terms.push(['$slice', [start, end]]); + this.terms.push(['$slice', [{start, end}]]); return this; } nth(num) { - this.terms.push(['$nth', num]); + this.terms.push(['$nth', {num}]); return this; } sample(num) { - this.terms.push(['$sample', num]); + this.terms.push(['$sample', {num}]); return this; } @@ -85,12 +86,12 @@ export default class Query { } without(...fields) { - this.terms.push(['$without', fields]); + this.terms.push(['$without', {fields}]); return this; } group(field) { - this.terms.push(['$group', field]); + this.terms.push(['$group', {field}]); return this; } @@ -100,38 +101,42 @@ export default class Query { } sum(field) { - this.terms.push(['$sum', field]); + this.terms.push(['$sum', {field}]); return this; } avg(field) { - this.terms.push(['$avg', field]); + this.terms.push(['$avg', {field}]); return this; } min(field) { - this.terms.push(['$min', field]); + this.terms.push(['$min', {field}]); return this; } max(field) { - this.terms.push(['$max', field]); + this.terms.push(['$max', {field}]); return this; } - between(start, end, index) { - var value = index ? [start, end, index] : [start, end]; + between(options) { + const defaults = { + lowerKey: '$minval', + upperKey: '$maxval' + }; + const value = _.assign(defaults, options); this.terms.push(['$between', value]); return this; - } +} getIntersecting(geometry, index) { - this.terms.push(['$get_intersecting', [index, geometry]]); + this.terms.push(['$get_intersecting', [{index, geometry}]]); return this; } getNearest(geometry, index) { - this.terms.push(['$get_nearest', [index, geometry]]); + this.terms.push(['$get_nearest', [{index, geometry}]]); return this; } } From e7a985d0b0f717ecfad9b6c8855f07b1a38b25bb Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 1 Aug 2016 18:50:49 -0700 Subject: [PATCH 09/50] refactor(query): update orderBy ordering with precede argument with `$`, add depreciation warning when using argument without `$` --- src/query.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/query.js b/src/query.js index 3204603..5ef1073 100644 --- a/src/query.js +++ b/src/query.js @@ -45,13 +45,27 @@ export default class Query { return this; } - orderBy(field, ordering = 'asc') { - if(ordering !== 'asc' && ordering !== 'desc') { + orderBy(key = null, index = null, ordering = '$asc') { + if(['asc', 'desc'].indexOf(ordering) != -1) { + console.warn('asc/desc parameters deprecated. Please use $asc/$desc.'); + ordering = '$' + ordering; + } + + if(['$asc', '$desc'].indexOf(ordering) != -1) { throw new Error('ordering must be desc or asc'); } - ordering = '$' + ordering; - this.terms.push(['$order_by', field, ordering]) + var params = { ordering }; + + if(key !== null) { + params.key = key; + } + + if(index !== null) { + params.index = index; + } + + this.terms.push(['$order_by', params]); return this; } From a2bcb44f5ba66f4f74b70d1003efe0de18c7b83f Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 1 Aug 2016 19:01:12 -0700 Subject: [PATCH 10/50] style(query): moved function to match `python-montage` wrapper --- src/query.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/query.js b/src/query.js index 5ef1073..492e843 100644 --- a/src/query.js +++ b/src/query.js @@ -35,6 +35,16 @@ export default class Query { return this; } + between(options) { + const defaults = { + lowerKey: '$minval', + upperKey: '$maxval' + }; + const value = _.assign(defaults, options); + this.terms.push(['$between', value]); + return this; + } + hasFields(...fields) { this.terms.push(['$has_fields', {fields}]) return this; @@ -134,16 +144,6 @@ export default class Query { return this; } - between(options) { - const defaults = { - lowerKey: '$minval', - upperKey: '$maxval' - }; - const value = _.assign(defaults, options); - this.terms.push(['$between', value]); - return this; -} - getIntersecting(geometry, index) { this.terms.push(['$get_intersecting', [{index, geometry}]]); return this; From 21c80567eb8587dbd11bebf4d1c39e5776d3448b Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 1 Aug 2016 19:04:11 -0700 Subject: [PATCH 11/50] docs(query): add comments for function groups to match the `python-montage` wrapper --- src/query.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/query.js b/src/query.js index 492e843..413b6ef 100644 --- a/src/query.js +++ b/src/query.js @@ -16,6 +16,8 @@ export default class Query { }; } + // Selecting Data + get(id) { this.terms.push(['$get', {id}]); return this; @@ -45,6 +47,8 @@ export default class Query { return this; } + // Transformations + hasFields(...fields) { this.terms.push(['$has_fields', {fields}]) return this; @@ -104,6 +108,8 @@ export default class Query { return this; } + // Manipulation + pluck(...fields) { this.terms.push(['$pluck', fields]); return this; @@ -114,6 +120,8 @@ export default class Query { return this; } + // Aggregation + group(field) { this.terms.push(['$group', {field}]); return this; @@ -144,6 +152,8 @@ export default class Query { return this; } + // Geospatial + getIntersecting(geometry, index) { this.terms.push(['$get_intersecting', [{index, geometry}]]); return this; From bc5bebacda22202ddfa96fe920395572bbe159c9 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 1 Aug 2016 19:08:45 -0700 Subject: [PATCH 12/50] feat(query): add delete function to match the `python-montage` wrapper --- src/query.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/query.js b/src/query.js index 413b6ef..6d0859b 100644 --- a/src/query.js +++ b/src/query.js @@ -163,4 +163,11 @@ export default class Query { this.terms.push(['$get_nearest', [{index, geometry}]]); return this; } + + // Delete + + delete(durability = 'hard', return_changes = false) { + this.terms.push(['$delete', [{durability, return_changes}]]); + return this; + } } From 500793a9e31b0da6b16286f3807fe982de09d70b Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 1 Aug 2016 20:34:37 -0700 Subject: [PATCH 13/50] test(field): add tests for each function in `field.js` --- tests/field_test.js | 129 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 tests/field_test.js diff --git a/tests/field_test.js b/tests/field_test.js new file mode 100644 index 0000000..7f2c0e5 --- /dev/null +++ b/tests/field_test.js @@ -0,0 +1,129 @@ +import expect from 'expect.js'; +import {Field} from '../src/index'; + +describe('Field', () => { + let field; + + beforeEach(function() { + field = new Field('x'); + }); + + describe('#toJS()', () => { + it('should equal a value of $eq', () => { + expect(field.toJS()).to.be.eql([]); + expect(field.eq('y').toJS()).to.be.eql([['x', ['$eq', 'y']]]); + }); + }); + + describe('#eq()', () => { + it('should equal a filter with a value of $eq', () => { + let expectedFilter = [['$eq', 'y']]; + expect(field.eq('y').filters).to.be.eql(expectedFilter); + }); + }); + + describe('#ieq()', () => { + it('should equal a filter with a value of $ieq', () => { + let expectedFilter = [['$ieq', 'y']]; + expect(field.ieq('y').filters).to.be.eql(expectedFilter); + }); + }); + + describe('#ne()', () => { + it('should equal a filter with a value of $ne', () => { + let expectedFilter = [['$ne', 'y']]; + expect(field.ne('y').filters).to.be.eql(expectedFilter); + }); + }); + + describe('#lt()', () => { + it('should equal a filter with a value of $lt', () => { + let expectedFilter = [['$lt', 'y']]; + expect(field.lt('y').filters).to.be.eql(expectedFilter); + }); + }); + + describe('#le()', () => { + it('should equal a filter with a value of $le', () => { + let expectedFilter = [['$le', 'y']]; + expect(field.le('y').filters).to.be.eql(expectedFilter); + }); + }); + + describe('#gt()', () => { + it('should equal a filter with a value of $gt', () => { + let expectedFilter = [['$gt', 'y']]; + expect(field.gt('y').filters).to.be.eql(expectedFilter); + }); + }); + + describe('#ge()', () => { + it('should equal a filter with a value of $ge', () => { + let expectedFilter = [['$ge', 'y']]; + expect(field.ge('y').filters).to.be.eql(expectedFilter); + }); + }); + + describe('#inSet()', () => { + it('should equal a filter with a value of $in', () => { + let expectedFilter = [['$in', 'y']]; + expect(field.inSet('y').filters).to.be.eql(expectedFilter); + }); + }); + + describe('#contains()', () => { + it('should equal a filter with a value of $contains', () => { + let expectedFilter = [['$contains', 'y']]; + expect(field.contains('y').filters).to.be.eql(expectedFilter); + }); + }); + + describe('#regex()', () => { + it('should equal a filter with a value of $regex', () => { + let expectedFilter = [['$regex', 'y']]; + expect(field.regex('y').filters).to.be.eql(expectedFilter); + }); + }); + + describe('#starts()', () => { + it('should equal a filter with a value of $starts', () => { + let expectedFilter = [['$starts', 'y']]; + expect(field.starts('y').filters).to.be.eql(expectedFilter); + }); + }); + + describe('#istarts()', () => { + it('should equal a filter with a value of $istarts', () => { + let expectedFilter = [['$eq', 'y']]; + expect(field.eq('y').filters).to.be.eql(expectedFilter); + }); + }); + + describe('#ends()', () => { + it('should equal a filter with a value of $ends', () => { + let expectedFilter = [['$ends', 'y']]; + expect(field.ends('y').filters).to.be.eql(expectedFilter); + }); + }); + + describe('#iends()', () => { + it('should equal a filter with a value of $iends', () => { + let expectedFilter = [['$iends', 'y']]; + expect(field.iends('y').filters).to.be.eql(expectedFilter); + }); + }); + + describe('#intersects()', () => { + it('should equal a filter with a value of $intersects', () => { + let expectedFilter = [['$intersects', 'y']]; + expect(field.intersects('y').filters).to.be.eql(expectedFilter); + }); + }); + + describe('#includes()', () => { + it('should equal a filter with a value of $includes', () => { + let expectedFilter = [['$includes', 'y']]; + expect(field.includes('y').filters).to.be.eql(expectedFilter); + }); + }); +}); From 8b430e19744177ed63005d3ba0840a92cd186878 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 1 Aug 2016 20:56:13 -0700 Subject: [PATCH 14/50] refactor(query): rename arguments to match the `python-montage` wrapper --- src/query.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/query.js b/src/query.js index 6d0859b..f53dba7 100644 --- a/src/query.js +++ b/src/query.js @@ -83,28 +83,28 @@ export default class Query { return this; } - skip(num) { - this.terms.push(['$skip', {num}]); + skip(n) { + this.terms.push(['$skip', {n}]); return this; } - limit(num) { - this.terms.push(['$limit', {num}]); + limit(n) { + this.terms.push(['$limit', {n}]); return this; } - slice(start, end) { - this.terms.push(['$slice', [{start, end}]]); + slice(startOffset, endOffset) { + this.terms.push(['$slice', [{startOffset, endOffset}]]); return this; } - nth(num) { - this.terms.push(['$nth', {num}]); + nth(n) { + this.terms.push(['$nth', {n}]); return this; } - sample(num) { - this.terms.push(['$sample', {num}]); + sample(n) { + this.terms.push(['$sample', {n}]); return this; } From 63eb9cac7b6fa4810134475381fe9ba82d13c9d5 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 1 Aug 2016 21:56:39 -0700 Subject: [PATCH 15/50] refactor(query): fix logic typo --- src/query.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/query.js b/src/query.js index f53dba7..a634cfa 100644 --- a/src/query.js +++ b/src/query.js @@ -60,12 +60,12 @@ export default class Query { } orderBy(key = null, index = null, ordering = '$asc') { - if(['asc', 'desc'].indexOf(ordering) != -1) { + if(['asc', 'desc'].indexOf(ordering) !== -1) { console.warn('asc/desc parameters deprecated. Please use $asc/$desc.'); ordering = '$' + ordering; } - if(['$asc', '$desc'].indexOf(ordering) != -1) { + if(['$asc', '$desc'].indexOf(ordering) !== -1) { throw new Error('ordering must be desc or asc'); } From 12ff8670791ae016dd099dcdee173fd6f4f77d58 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 1 Aug 2016 21:59:10 -0700 Subject: [PATCH 16/50] test(query): update tests to work with new object parameters in `query.js` - orderBy, between, getIntersecting, and getNearest still not passing --- tests/query_test.js | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/tests/query_test.js b/tests/query_test.js index bf09671..aa53767 100644 --- a/tests/query_test.js +++ b/tests/query_test.js @@ -17,6 +17,7 @@ describe('Query', () => { describe('#toJS()', () => { it('should return a query object', () => { expect(query.toJS()).to.eql({ + $type: 'query', $schema: 'testSchema', $query: [] }); @@ -26,28 +27,28 @@ describe('Query', () => { describe('#get()', () => { it('sets get', () => { query.get('1234'); - expect(query.terms).to.eql([['$get', '1234']]); + expect(query.terms).to.eql([['$get', {'id': '1234'}]]); }); }); describe('#getAll()', () => { it('sets getAll', () => { query.getAll(['1234', 'abcd']); - expect(query.terms).to.eql([['$get_all', ['id', ['1234', 'abcd']]]]); + expect(query.terms).to.eql([['$get_all', [{'ids': ['1234', 'abcd'], 'index': 'id'}]]]); }); }); describe('#hasFields()', () => { it('sets hasFields', () => { query.hasFields('title', 'rating'); - expect(query.terms).to.eql([['$has_fields', ['title', 'rating']]]); + expect(query.terms).to.eql([['$has_fields', {fields: ['title', 'rating']}]]); }); }); describe('#withFields()', () => { it('sets withFields', () => { query.withFields('title', 'rating'); - expect(query.terms).to.eql([['$with_fields', ['title', 'rating']]]); + expect(query.terms).to.eql([['$with_fields', {fields: ['title', 'rating']}]]); }); }); @@ -61,14 +62,14 @@ describe('Query', () => { context('when direction is ascending', () => { it('sets order_by and ascending direction', () => { - query.orderBy('rating', 'asc'); + query.orderBy('rating', '$asc'); expect(query.terms).to.eql([['$order_by', 'rating', '$asc']]); }); }); context('when direction is descending', () => { it('sets order_by and descending direction', () => { - query.orderBy('rating', 'desc'); + query.orderBy('rating', '$desc'); expect(query.terms).to.eql([['$order_by', 'rating', '$desc']]); }); }); @@ -83,35 +84,35 @@ describe('Query', () => { describe('#skip()', () => { it('sets skip', () => { query.skip(10); - expect(query.terms).to.eql([['$skip', 10]]); + expect(query.terms).to.eql([['$skip', {'n': 10}]]); }); }); describe('#limit()', () => { it('sets limit', () => { query.limit(10); - expect(query.terms).to.eql([['$limit', 10]]); + expect(query.terms).to.eql([['$limit', {'n': 10}]]); }); }); describe('#slice()', () => { it('sets slice', () => { query.slice(10, 20); - expect(query.terms).to.eql([['$slice', [10, 20]]]); + expect(query.terms).to.eql([['$slice', [{'startOffset': 10, 'endOffset': 20}]]]); }); }); describe('#nth()', () => { it('sets nth', () => { query.nth(5); - expect(query.terms).to.eql([['$nth', 5]]); + expect(query.terms).to.eql([['$nth', {'n': 5}]]); }); }); describe('#sample()', () => { it('sets sample', () => { query.sample(20); - expect(query.terms).to.eql([['$sample', 20]]); + expect(query.terms).to.eql([['$sample', {'n': 20}]]); }); }); @@ -125,7 +126,7 @@ describe('Query', () => { describe('#without()', () => { it('sets without', () => { query.without('votes', 'rank'); - expect(query.terms).to.eql([['$without', ['votes', 'rank']]]); + expect(query.terms).to.eql([['$without', {'fields': ['votes', 'rank']}]]); }); }); @@ -139,28 +140,28 @@ describe('Query', () => { describe('#sum()', () => { it('sets sum', () => { query.sum('rank'); - expect(query.terms).to.eql([['$sum', 'rank']]); + expect(query.terms).to.eql([['$sum', {'field': 'rank'}]]); }); }); describe('#avg()', () => { it('sets avg', () => { query.avg('rank'); - expect(query.terms).to.eql([['$avg', 'rank']]); + expect(query.terms).to.eql([['$avg', {'field': 'rank'}]]); }); }); describe('#min()', () => { it('sets min', () => { query.min('rating'); - expect(query.terms).to.eql([['$min', 'rating']]); + expect(query.terms).to.eql([['$min', {'field': 'rating'}]]); }); }); describe('#max()', () => { it('sets max', () => { query.max('rating'); - expect(query.terms).to.eql([['$max', 'rating']]); + expect(query.terms).to.eql([['$max', {'field': 'rating'}]]); }); }); @@ -174,11 +175,13 @@ describe('Query', () => { describe('#getIntersecting()', () => { it('sets get_intersecting', () => { var point = { - 'type': 'Point', - 'coordinates': [-120.34589052200315, 36.12704320788633] - }; + 'geometry': { + 'coordinates': [-120.34589052200315, 36.12704320788633], + 'type': 'Point' + } + }; query.getIntersecting(point, 'location'); - expect(query.terms).to.eql([['$get_intersecting', ['location', point]]]); + expect(query.terms).to.eql([['$get_intersecting', [{'index': 'location', point}]]]); }); }); From 9c1d2b13e1cabfbe13ae7e89f483f88d3228dbab Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Tue, 2 Aug 2016 13:58:57 -0700 Subject: [PATCH 17/50] fix(query): rewrite remaining functions to work correctly with object parameters --- src/query.js | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/query.js b/src/query.js index a634cfa..7b3efc0 100644 --- a/src/query.js +++ b/src/query.js @@ -24,7 +24,7 @@ export default class Query { } getAll(ids, index = 'id') { - this.terms.push(['$get_all', [{index, ids}]]); + this.terms.push(['$get_all', {index, ids}]); return this; } @@ -39,11 +39,11 @@ export default class Query { between(options) { const defaults = { - lowerKey: '$minval', - upperKey: '$maxval' + lowerKey : '$minval', + upperKey : '$maxval' }; - const value = _.assign(defaults, options); - this.terms.push(['$between', value]); + const params = _.assign(defaults, options); + this.terms.push(['$between', params]); return this; } @@ -59,23 +59,24 @@ export default class Query { return this; } - orderBy(key = null, index = null, ordering = '$asc') { + orderBy({key, index, ordering}) { + ordering = (ordering === undefined) ? '$asc' : ordering; if(['asc', 'desc'].indexOf(ordering) !== -1) { console.warn('asc/desc parameters deprecated. Please use $asc/$desc.'); ordering = '$' + ordering; } - if(['$asc', '$desc'].indexOf(ordering) !== -1) { - throw new Error('ordering must be desc or asc'); + if(['$asc', '$desc'].indexOf(ordering) === -1) { + throw new Error('ordering must be $desc or $asc'); } var params = { ordering }; - if(key !== null) { + if(key !== undefined) { params.key = key; } - if(index !== null) { + if(index !== undefined) { params.index = index; } @@ -94,7 +95,7 @@ export default class Query { } slice(startOffset, endOffset) { - this.terms.push(['$slice', [{startOffset, endOffset}]]); + this.terms.push(['$slice', {startOffset, endOffset}]); return this; } @@ -111,7 +112,7 @@ export default class Query { // Manipulation pluck(...fields) { - this.terms.push(['$pluck', fields]); + this.terms.push(['$pluck', {fields}]); return this; } @@ -155,19 +156,19 @@ export default class Query { // Geospatial getIntersecting(geometry, index) { - this.terms.push(['$get_intersecting', [{index, geometry}]]); + this.terms.push(['$get_intersecting', {index, geometry}]); return this; } getNearest(geometry, index) { - this.terms.push(['$get_nearest', [{index, geometry}]]); + this.terms.push(['$get_nearest', {index, geometry}]); return this; } // Delete delete(durability = 'hard', return_changes = false) { - this.terms.push(['$delete', [{durability, return_changes}]]); + this.terms.push(['$delete', {durability, return_changes}]); return this; } } From d7e00f728f06f822114f96caabbc3879f826279f Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Tue, 2 Aug 2016 14:00:10 -0700 Subject: [PATCH 18/50] test(query): update remaining tests to work with updated `query.js` --- tests/query_test.js | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/tests/query_test.js b/tests/query_test.js index aa53767..60be5b8 100644 --- a/tests/query_test.js +++ b/tests/query_test.js @@ -34,7 +34,7 @@ describe('Query', () => { describe('#getAll()', () => { it('sets getAll', () => { query.getAll(['1234', 'abcd']); - expect(query.terms).to.eql([['$get_all', [{'ids': ['1234', 'abcd'], 'index': 'id'}]]]); + expect(query.terms).to.eql([['$get_all', {'ids': ['1234', 'abcd'], 'index': 'id'}]]); }); }); @@ -55,22 +55,22 @@ describe('Query', () => { describe('#orderBy()', () => { context('when no direction supplied', () => { it('sets order_by and default direction', () => { - query.orderBy('rating'); - expect(query.terms).to.eql([['$order_by', 'rating', '$asc']]); + query.orderBy({'key': 'rating'}); + expect(query.terms).to.eql([['$order_by', {key: 'rating', ordering: '$asc'}]]); }); }); context('when direction is ascending', () => { it('sets order_by and ascending direction', () => { - query.orderBy('rating', '$asc'); - expect(query.terms).to.eql([['$order_by', 'rating', '$asc']]); + query.orderBy({'key': 'rating', ordering: '$asc'}); + expect(query.terms).to.eql([['$order_by', {key: 'rating', ordering: '$asc'}]]); }); }); context('when direction is descending', () => { it('sets order_by and descending direction', () => { - query.orderBy('rating', '$desc'); - expect(query.terms).to.eql([['$order_by', 'rating', '$desc']]); + query.orderBy({'key': 'rating', ordering: '$desc'}); + expect(query.terms).to.eql([['$order_by', {key: 'rating', ordering: '$desc'}]]); }); }); @@ -98,7 +98,7 @@ describe('Query', () => { describe('#slice()', () => { it('sets slice', () => { query.slice(10, 20); - expect(query.terms).to.eql([['$slice', [{'startOffset': 10, 'endOffset': 20}]]]); + expect(query.terms).to.eql([['$slice', {'startOffset': 10, 'endOffset': 20}]]); }); }); @@ -119,7 +119,7 @@ describe('Query', () => { describe('#pluck()', () => { it('sets pluck', () => { query.pluck('name', 'rank', 'rating'); - expect(query.terms).to.eql([['$pluck', ['name', 'rank', 'rating']]]); + expect(query.terms).to.eql([['$pluck', {'fields': ['name', 'rank', 'rating']}]]); }); }); @@ -167,21 +167,24 @@ describe('Query', () => { describe('#between()', () => { it('sets between', () => { - query.between(0, 10, 'rank'); - expect(query.terms).to.eql([['$between', [0, 10, 'rank']]]); + var params = { + lowerKey: 0, + upperKey: 10, + index: 'rank', + } + query.between(params); + expect(query.terms).to.eql([['$between', params]]); }); }); describe('#getIntersecting()', () => { it('sets get_intersecting', () => { var point = { - 'geometry': { - 'coordinates': [-120.34589052200315, 36.12704320788633], - 'type': 'Point' - } + 'coordinates': [-120.34589052200315, 36.12704320788633], + 'type': 'Point' }; query.getIntersecting(point, 'location'); - expect(query.terms).to.eql([['$get_intersecting', [{'index': 'location', point}]]]); + expect(query.terms).to.eql([['$get_intersecting', {index: 'location', geometry: point}]]); }); }); @@ -192,7 +195,7 @@ describe('Query', () => { 'coordinates': [-120.34589052200315, 36.12704320788633] }; query.getNearest(point, 'location'); - expect(query.terms).to.eql([['$get_nearest', ['location', point]]]); + expect(query.terms).to.eql([['$get_nearest', {index: 'location', geometry: point}]]); }); }); }); From f390f05c2ac2cef9a2f9b0bae33cc156b3076250 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Tue, 2 Aug 2016 14:20:44 -0700 Subject: [PATCH 19/50] fix(field): change parameter from spread operator --- src/field.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/field.js b/src/field.js index 7be6420..58575a7 100644 --- a/src/field.js +++ b/src/field.js @@ -45,8 +45,8 @@ export default class Field { return this; } - inSet(...values) { - this.filters.push(["$in", values]); + inSet(value) { + this.filters.push(["$in", value]); return this; } From 60860d6f0c85fa3edeb0d7272ecd615f8d57afb7 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Wed, 3 Aug 2016 10:46:23 -0700 Subject: [PATCH 20/50] feat(tasks): import TaskAPI to Client script --- src/client.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/client.js b/src/client.js index 1e8a15c..0a73a27 100644 --- a/src/client.js +++ b/src/client.js @@ -9,6 +9,7 @@ import RoleAPI from './api/role'; import SchemaAPI from './api/schema'; import UserAPI from './api/user'; import PolicyAPI from './api/policy'; +import TaskAPI from './api/task'; export default class Client { constructor(project, token) { @@ -23,6 +24,7 @@ export default class Client { this.roles = new RoleAPI(this); this.files = new FileAPI(this); this.policy = new PolicyAPI(this); + this.tasks = new TaskAPI(this); } url(endpoint) { From 101bc0dc8215997f807ada7de4b745f720ac8438 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Wed, 3 Aug 2016 10:47:11 -0700 Subject: [PATCH 21/50] feat(tasks): add TaskAPI script to match the `python-montage` wrapper --- src/api/task.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/api/task.js diff --git a/src/api/task.js b/src/api/task.js new file mode 100644 index 0000000..36a90dd --- /dev/null +++ b/src/api/task.js @@ -0,0 +1,25 @@ +export default class TaskAPI { + constructor(client) { + this.client = client; + } + + run(command, image, token, timeLimit) { + const payload = { command }; + + if (image) { + payload.image = image; + } + if (token) { + payload.token = token; + } + if (timeLimit) { + payload.timeLimit = timeLimit; + } + + return this.client.request(`tasks/`, 'POST', payload); + } + + get(task_id) { + return this.client.request(`tasks/${task_id}/`); + } +} From 4d431af7b4f59f25bce3f112751729085a2be0e0 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Wed, 3 Aug 2016 13:27:52 -0700 Subject: [PATCH 22/50] fix(task): update object name to match server-side name --- src/api/task.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/task.js b/src/api/task.js index 36a90dd..bcd38a1 100644 --- a/src/api/task.js +++ b/src/api/task.js @@ -13,7 +13,7 @@ export default class TaskAPI { payload.token = token; } if (timeLimit) { - payload.timeLimit = timeLimit; + payload.time_limit = timeLimit; } return this.client.request(`tasks/`, 'POST', payload); From 9daef5d0379734de4f3f50c5846246306a0667af Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Wed, 3 Aug 2016 14:37:49 -0700 Subject: [PATCH 23/50] refactor(field): update inSet() to in(); deprecate inSet() --- src/field.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/field.js b/src/field.js index 58575a7..dc73ecb 100644 --- a/src/field.js +++ b/src/field.js @@ -45,11 +45,16 @@ export default class Field { return this; } - inSet(value) { + in(value) { this.filters.push(["$in", value]); return this; } + inSet(value) { + console.warn("The function inSet() is deprecated, use in()."); + return this.in(value); + } + contains(value) { this.filters.push(["$contains", value]); return this; From e8c1f86c8636b5195cf6cc270f9be6210a8bcc58 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Wed, 3 Aug 2016 14:39:18 -0700 Subject: [PATCH 24/50] test(field): update inSet() test to reference in() --- tests/field_test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/field_test.js b/tests/field_test.js index 7f2c0e5..3a118c2 100644 --- a/tests/field_test.js +++ b/tests/field_test.js @@ -64,10 +64,10 @@ describe('Field', () => { }); }); - describe('#inSet()', () => { + describe('#in()', () => { it('should equal a filter with a value of $in', () => { let expectedFilter = [['$in', 'y']]; - expect(field.inSet('y').filters).to.be.eql(expectedFilter); + expect(field.in('y').filters).to.be.eql(expectedFilter); }); }); From 66dae52b650bf79b8143a4c05df6465c556040e6 Mon Sep 17 00:00:00 2001 From: dmpayton Date: Thu, 11 Aug 2016 15:59:35 -0700 Subject: [PATCH 25/50] feat(field): Add a $match operator to replace the (now deprecated) $regex operator. --- src/field.js | 9 +++++++-- tests/field_test.js | 8 ++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/field.js b/src/field.js index dc73ecb..9d4684c 100644 --- a/src/field.js +++ b/src/field.js @@ -60,11 +60,16 @@ export default class Field { return this; } - regex(expression) { - this.filters.push(["$regex", expression]); + match(expression) { + this.filters.push(["$match", expression]); return this; } + regex(expression) { + console.warn("The function regex() is deprecated, please use match()."); + return this.match(expression) + } + starts(value) { this.filters.push(["$starts", value]); return this; diff --git a/tests/field_test.js b/tests/field_test.js index 3a118c2..1ece7ea 100644 --- a/tests/field_test.js +++ b/tests/field_test.js @@ -78,10 +78,10 @@ describe('Field', () => { }); }); - describe('#regex()', () => { - it('should equal a filter with a value of $regex', () => { - let expectedFilter = [['$regex', 'y']]; - expect(field.regex('y').filters).to.be.eql(expectedFilter); + describe('#match()', () => { + it('should equal a filter with a value of $match', () => { + let expectedFilter = [['$match', 'y']]; + expect(field.match('y').filters).to.be.eql(expectedFilter); }); }); From 3290bccd9d9be8b1dc950567d26e51a4342c35ea Mon Sep 17 00:00:00 2001 From: dmpayton Date: Thu, 11 Aug 2016 16:25:48 -0700 Subject: [PATCH 26/50] Add filters to the already-implemented api list methods. --- src/api/file.js | 5 +++-- src/api/role.js | 5 +++-- src/api/schema.js | 5 +++-- src/api/user.js | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/api/file.js b/src/api/file.js index 3861c0a..5a4ad17 100644 --- a/src/api/file.js +++ b/src/api/file.js @@ -3,8 +3,9 @@ export default class FileAPI { this.client = client; } - list() { - return this.client.request('files/'); + list(params) { + params = params ? params : {}; + return this.client.request('files/', 'GET', params); } get(file_id) { diff --git a/src/api/role.js b/src/api/role.js index da31765..fb07d1c 100644 --- a/src/api/role.js +++ b/src/api/role.js @@ -8,8 +8,9 @@ export default class RoleAPI { return this.client.request(`roles/`, 'POST', payload); } - list() { - return this.client.request(`roles/`); + list(params) { + params = params ? params : {}; + return this.client.request(`roles/`, 'GET', params); } get(role) { diff --git a/src/api/schema.js b/src/api/schema.js index 0c40a87..d55cade 100644 --- a/src/api/schema.js +++ b/src/api/schema.js @@ -8,8 +8,9 @@ export default class SchemaAPI { return this.client.request('schemas/', 'POST', payload); } - list() { - return this.client.request('schemas/'); + list(params) { + params = params ? params : {}; + return this.client.request('schemas/', 'GET', params); } get(schema) { diff --git a/src/api/user.js b/src/api/user.js index 0cd6f18..648b764 100644 --- a/src/api/user.js +++ b/src/api/user.js @@ -3,8 +3,9 @@ export default class UserAPI { this.client = client } - list() { - return this.client.request('users/'); + list(params) { + params = params ? params : {}; + return this.client.request('users/', 'GET', params); } create(full_name, email, password) { From 9baafed132a1870796594f17e4d1c260c5648ee6 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Tue, 6 Sep 2016 11:28:07 -0700 Subject: [PATCH 27/50] refactor(client): rename `project` to `subdomain` --- src/client.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client.js b/src/client.js index e1940eb..25ad426 100644 --- a/src/client.js +++ b/src/client.js @@ -10,10 +10,10 @@ import UserAPI from './api/user'; import PolicyAPI from './api/policy'; export default class Client { - constructor(project, token) { + constructor(subdomain, token) { this.protocol = 'https'; this.host = 'mntge.com'; - this.project = project; + this.subdomain = subdomain; this.token = token; this.documents = new DocumentAPI(this); @@ -25,7 +25,7 @@ export default class Client { } url(endpoint) { - return `${this.protocol}://${this.project}.${this.host}/api/v1/${endpoint}`; + return `${this.protocol}://${this.subdomain}.${this.host}/api/v1/${endpoint}`; } authenticate(email, password) { From 1b9078dfc9ac1428a2e86eb4b46e0738525db60b Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Tue, 6 Sep 2016 11:29:01 -0700 Subject: [PATCH 28/50] feat(client): import `ProjectAPI` --- src/client.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/client.js b/src/client.js index 25ad426..8446c10 100644 --- a/src/client.js +++ b/src/client.js @@ -5,6 +5,7 @@ import _ from 'lodash'; import DocumentAPI from './api/document'; import FileAPI from './api/file'; import RoleAPI from './api/role'; +import ProjectAPI from './api/project'; import SchemaAPI from './api/schema'; import UserAPI from './api/user'; import PolicyAPI from './api/policy'; @@ -20,6 +21,7 @@ export default class Client { this.schemas = new SchemaAPI(this); this.users = new UserAPI(this); this.roles = new RoleAPI(this); + this.project = new ProjectAPI(this); this.files = new FileAPI(this); this.policy = new PolicyAPI(this); } From 9745c438dd058a3b451e2dead4cfa18ef287106a Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Tue, 6 Sep 2016 11:30:29 -0700 Subject: [PATCH 29/50] feat(project): add `ProjectAPI` script --- src/api/project.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/api/project.js diff --git a/src/api/project.js b/src/api/project.js new file mode 100644 index 0000000..d7cb95b --- /dev/null +++ b/src/api/project.js @@ -0,0 +1,25 @@ +export default class ProjectAPI { + constructor(client) { + this.client = client; + } + + get() { + return this.client.request(`project`); + } + + update(name, subdomain) { + var payload = {}; + + if(name) { + payload.name = name; + } + + if(subdomain) { + payload.subdomain = subdomain; + } + + if(payload) { + return this.client.request(`project`, 'PATCH', payload); + } + } +} From eed576af5246527818c3e44e1188a320f2d03c35 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Tue, 6 Sep 2016 13:20:15 -0700 Subject: [PATCH 30/50] refactor(task): make optional arguments into options object --- src/api/task.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/task.js b/src/api/task.js index bcd38a1..1603111 100644 --- a/src/api/task.js +++ b/src/api/task.js @@ -3,7 +3,7 @@ export default class TaskAPI { this.client = client; } - run(command, image, token, timeLimit) { + run(command, { image, token, timeLimit }) { const payload = { command }; if (image) { From 5e248168185bc2de605160b1e93f768f467c6add Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Tue, 6 Sep 2016 13:22:39 -0700 Subject: [PATCH 31/50] refactor(api): make optional arguments into options object --- src/api/policy.js | 2 +- src/api/role.js | 2 +- src/api/schema.js | 2 +- src/api/user.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/api/policy.js b/src/api/policy.js index 664d935..53ce0f8 100644 --- a/src/api/policy.js +++ b/src/api/policy.js @@ -20,7 +20,7 @@ export default class PolicyAPI { return this.client.request(`policy/${policy_id}/`); } - update(policy_id, description, policy) { + update(policy_id, { description, policy }) { if(!description && !policy) { throw new Error('Must provide a `description` or `policy`'); } diff --git a/src/api/role.js b/src/api/role.js index da31765..a094e7e 100644 --- a/src/api/role.js +++ b/src/api/role.js @@ -16,7 +16,7 @@ export default class RoleAPI { return this.client.request(`roles/${role}/`); } - update(role, name, add_users, remove_users) { + update(role, { name, add_users, remove_users }) { var payload = {}; if (name) { diff --git a/src/api/schema.js b/src/api/schema.js index 0c40a87..23e540e 100644 --- a/src/api/schema.js +++ b/src/api/schema.js @@ -16,7 +16,7 @@ export default class SchemaAPI { return this.client.request(`schemas/${schema}/`); } - update(schema, name, fields) { + update(schema, { name, fields }) { var payload = {}; if (name) { diff --git a/src/api/user.js b/src/api/user.js index 0cd6f18..a9a0f53 100644 --- a/src/api/user.js +++ b/src/api/user.js @@ -16,7 +16,7 @@ export default class UserAPI { return this.client.request(`users/${user_id}/`); } - update(user_id, full_name, email, password) { + update(user_id, { full_name, email, password }) { var payload = {}; if (full_name) { From fb203b4f73a14380d16554ad76ba5070f4c530fb Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Tue, 6 Sep 2016 16:42:38 -0700 Subject: [PATCH 32/50] refactor(project): make optional arguments into options object --- src/api/project.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/project.js b/src/api/project.js index d7cb95b..ffc2eba 100644 --- a/src/api/project.js +++ b/src/api/project.js @@ -7,7 +7,7 @@ export default class ProjectAPI { return this.client.request(`project`); } - update(name, subdomain) { + update({ name, subdomain }) { var payload = {}; if(name) { From eba24cfa211262eb4371fc2e8070607772bcfe80 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Tue, 6 Sep 2016 16:43:25 -0700 Subject: [PATCH 33/50] refactor(api): check for payload object length before returning --- src/api/policy.js | 2 +- src/api/project.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/policy.js b/src/api/policy.js index 53ce0f8..907fa56 100644 --- a/src/api/policy.js +++ b/src/api/policy.js @@ -35,7 +35,7 @@ export default class PolicyAPI { payload.policy = policy; } - if(payload) { + if (Object.keys(payload).length) { return this.client.request(`policy/${policy_id}/`, 'PATCH', payload); } } diff --git a/src/api/project.js b/src/api/project.js index ffc2eba..c4f8e2d 100644 --- a/src/api/project.js +++ b/src/api/project.js @@ -18,7 +18,7 @@ export default class ProjectAPI { payload.subdomain = subdomain; } - if(payload) { + if (Object.keys(payload).length) { return this.client.request(`project`, 'PATCH', payload); } } From c5cc5f88fd7067a483e8b635eb0eb18b27b0725e Mon Sep 17 00:00:00 2001 From: Nick Herrera Date: Mon, 19 Sep 2016 08:31:53 -0700 Subject: [PATCH 34/50] refactor(tests): change `.to.be.eql()` to `.to.eql()` so that assertions read more naturally --- tests/client_test.js | 8 ++++---- tests/field_test.js | 36 ++++++++++++++++++------------------ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/client_test.js b/tests/client_test.js index bbd13a8..297b313 100644 --- a/tests/client_test.js +++ b/tests/client_test.js @@ -94,7 +94,7 @@ describe('Client', () => { }); client.authenticate('test@example.com', 'letmein').then((response) => { - expect(response).to.be.eql({data: {token: 'USER_TOKEN'}}); + expect(response).to.eql({data: {token: 'USER_TOKEN'}}); expect(client.token).to.eql('USER_TOKEN'); done(); }); @@ -170,7 +170,7 @@ describe('Client', () => { return client.request('#').then(response => { expect().fail(); }, error => { - expect(error).to.be.eql({errors: ['something went wrong']}); + expect(error).to.eql({errors: ['something went wrong']}); done(); }); }); @@ -187,7 +187,7 @@ describe('Client', () => { return client.request('#').then(response => { expect.fail(); }, error => { - expect(error).to.be.eql(['something went wrong']); + expect(error).to.eql(['something went wrong']); }); }); @@ -203,7 +203,7 @@ describe('Client', () => { expect.fail(); }, error => { return error.text().then(text => { - expect(text).to.be.eql('something went wrong'); + expect(text).to.eql('something went wrong'); }); }); }); diff --git a/tests/field_test.js b/tests/field_test.js index 1ece7ea..2191770 100644 --- a/tests/field_test.js +++ b/tests/field_test.js @@ -10,120 +10,120 @@ describe('Field', () => { describe('#toJS()', () => { it('should equal a value of $eq', () => { - expect(field.toJS()).to.be.eql([]); - expect(field.eq('y').toJS()).to.be.eql([['x', ['$eq', 'y']]]); + expect(field.toJS()).to.eql([]); + expect(field.eq('y').toJS()).to.eql([['x', ['$eq', 'y']]]); }); }); describe('#eq()', () => { it('should equal a filter with a value of $eq', () => { let expectedFilter = [['$eq', 'y']]; - expect(field.eq('y').filters).to.be.eql(expectedFilter); + expect(field.eq('y').filters).to.eql(expectedFilter); }); }); describe('#ieq()', () => { it('should equal a filter with a value of $ieq', () => { let expectedFilter = [['$ieq', 'y']]; - expect(field.ieq('y').filters).to.be.eql(expectedFilter); + expect(field.ieq('y').filters).to.eql(expectedFilter); }); }); describe('#ne()', () => { it('should equal a filter with a value of $ne', () => { let expectedFilter = [['$ne', 'y']]; - expect(field.ne('y').filters).to.be.eql(expectedFilter); + expect(field.ne('y').filters).to.eql(expectedFilter); }); }); describe('#lt()', () => { it('should equal a filter with a value of $lt', () => { let expectedFilter = [['$lt', 'y']]; - expect(field.lt('y').filters).to.be.eql(expectedFilter); + expect(field.lt('y').filters).to.eql(expectedFilter); }); }); describe('#le()', () => { it('should equal a filter with a value of $le', () => { let expectedFilter = [['$le', 'y']]; - expect(field.le('y').filters).to.be.eql(expectedFilter); + expect(field.le('y').filters).to.eql(expectedFilter); }); }); describe('#gt()', () => { it('should equal a filter with a value of $gt', () => { let expectedFilter = [['$gt', 'y']]; - expect(field.gt('y').filters).to.be.eql(expectedFilter); + expect(field.gt('y').filters).to.eql(expectedFilter); }); }); describe('#ge()', () => { it('should equal a filter with a value of $ge', () => { let expectedFilter = [['$ge', 'y']]; - expect(field.ge('y').filters).to.be.eql(expectedFilter); + expect(field.ge('y').filters).to.eql(expectedFilter); }); }); describe('#in()', () => { it('should equal a filter with a value of $in', () => { let expectedFilter = [['$in', 'y']]; - expect(field.in('y').filters).to.be.eql(expectedFilter); + expect(field.in('y').filters).to.eql(expectedFilter); }); }); describe('#contains()', () => { it('should equal a filter with a value of $contains', () => { let expectedFilter = [['$contains', 'y']]; - expect(field.contains('y').filters).to.be.eql(expectedFilter); + expect(field.contains('y').filters).to.eql(expectedFilter); }); }); describe('#match()', () => { it('should equal a filter with a value of $match', () => { let expectedFilter = [['$match', 'y']]; - expect(field.match('y').filters).to.be.eql(expectedFilter); + expect(field.match('y').filters).to.eql(expectedFilter); }); }); describe('#starts()', () => { it('should equal a filter with a value of $starts', () => { let expectedFilter = [['$starts', 'y']]; - expect(field.starts('y').filters).to.be.eql(expectedFilter); + expect(field.starts('y').filters).to.eql(expectedFilter); }); }); describe('#istarts()', () => { it('should equal a filter with a value of $istarts', () => { let expectedFilter = [['$eq', 'y']]; - expect(field.eq('y').filters).to.be.eql(expectedFilter); + expect(field.eq('y').filters).to.eql(expectedFilter); }); }); describe('#ends()', () => { it('should equal a filter with a value of $ends', () => { let expectedFilter = [['$ends', 'y']]; - expect(field.ends('y').filters).to.be.eql(expectedFilter); + expect(field.ends('y').filters).to.eql(expectedFilter); }); }); describe('#iends()', () => { it('should equal a filter with a value of $iends', () => { let expectedFilter = [['$iends', 'y']]; - expect(field.iends('y').filters).to.be.eql(expectedFilter); + expect(field.iends('y').filters).to.eql(expectedFilter); }); }); describe('#intersects()', () => { it('should equal a filter with a value of $intersects', () => { let expectedFilter = [['$intersects', 'y']]; - expect(field.intersects('y').filters).to.be.eql(expectedFilter); + expect(field.intersects('y').filters).to.eql(expectedFilter); }); }); describe('#includes()', () => { it('should equal a filter with a value of $includes', () => { let expectedFilter = [['$includes', 'y']]; - expect(field.includes('y').filters).to.be.eql(expectedFilter); + expect(field.includes('y').filters).to.eql(expectedFilter); }); }); }); From f326a6e078976306941828d78ec2f4e90c89beb3 Mon Sep 17 00:00:00 2001 From: Nick Herrera Date: Mon, 19 Sep 2016 08:35:51 -0700 Subject: [PATCH 35/50] style(misc): add missing semi-colons --- src/api/user.js | 2 +- src/client.js | 2 +- src/field.js | 2 +- src/query.js | 4 ++-- tests/client_test.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/api/user.js b/src/api/user.js index 1c376bc..07e200d 100644 --- a/src/api/user.js +++ b/src/api/user.js @@ -10,7 +10,7 @@ export default class UserAPI { create(full_name, email, password) { const payload = { full_name, email, password }; - return this.client.request('users/', 'POST', payload) + return this.client.request('users/', 'POST', payload); } get(user_id) { diff --git a/src/client.js b/src/client.js index 19595e8..3b0d291 100644 --- a/src/client.js +++ b/src/client.js @@ -48,7 +48,7 @@ export default class Client { return this.request('user/'); } - return Promise.reject('The current user is not authenticated.') + return Promise.reject('The current user is not authenticated.'); } execute(queries) { diff --git a/src/field.js b/src/field.js index 9d4684c..fac5a41 100644 --- a/src/field.js +++ b/src/field.js @@ -67,7 +67,7 @@ export default class Field { regex(expression) { console.warn("The function regex() is deprecated, please use match()."); - return this.match(expression) + return this.match(expression); } starts(value) { diff --git a/src/query.js b/src/query.js index 7b3efc0..d31fb67 100644 --- a/src/query.js +++ b/src/query.js @@ -50,12 +50,12 @@ export default class Query { // Transformations hasFields(...fields) { - this.terms.push(['$has_fields', {fields}]) + this.terms.push(['$has_fields', {fields}]); return this; } withFields(...fields) { - this.terms.push(['$with_fields', {fields}]) + this.terms.push(['$with_fields', {fields}]); return this; } diff --git a/tests/client_test.js b/tests/client_test.js index 297b313..1c2769c 100644 --- a/tests/client_test.js +++ b/tests/client_test.js @@ -118,7 +118,7 @@ describe('Client', () => { client.authenticate('fake@example.com', 'invalid').then(response => { expect().fail(); }, error => { - expect(error).to.eql([{'detail': 'Incorrect authentication credentials.'}]) + expect(error).to.eql([{'detail': 'Incorrect authentication credentials.'}]); expect(client.token).to.be(undefined); done(); }); From 81a704b587f9d6f5c47ad6414392b73d808b4b17 Mon Sep 17 00:00:00 2001 From: Nick Herrera Date: Mon, 19 Sep 2016 08:40:47 -0700 Subject: [PATCH 36/50] style(query_test): remove unnecessary quotes from property name --- tests/query_test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/query_test.js b/tests/query_test.js index 60be5b8..3abe720 100644 --- a/tests/query_test.js +++ b/tests/query_test.js @@ -55,21 +55,21 @@ describe('Query', () => { describe('#orderBy()', () => { context('when no direction supplied', () => { it('sets order_by and default direction', () => { - query.orderBy({'key': 'rating'}); + query.orderBy({key: 'rating'}); expect(query.terms).to.eql([['$order_by', {key: 'rating', ordering: '$asc'}]]); }); }); context('when direction is ascending', () => { it('sets order_by and ascending direction', () => { - query.orderBy({'key': 'rating', ordering: '$asc'}); + query.orderBy({key: 'rating', ordering: '$asc'}); expect(query.terms).to.eql([['$order_by', {key: 'rating', ordering: '$asc'}]]); }); }); context('when direction is descending', () => { it('sets order_by and descending direction', () => { - query.orderBy({'key': 'rating', ordering: '$desc'}); + query.orderBy({key: 'rating', ordering: '$desc'}); expect(query.terms).to.eql([['$order_by', {key: 'rating', ordering: '$desc'}]]); }); }); From c18cd371011f68f677332d61c889e2c16af5cbb8 Mon Sep 17 00:00:00 2001 From: Nick Herrera Date: Mon, 19 Sep 2016 08:53:31 -0700 Subject: [PATCH 37/50] style(query_test): add missing semicolon --- tests/query_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/query_test.js b/tests/query_test.js index 3abe720..715dc5a 100644 --- a/tests/query_test.js +++ b/tests/query_test.js @@ -171,7 +171,7 @@ describe('Query', () => { lowerKey: 0, upperKey: 10, index: 'rank', - } + }; query.between(params); expect(query.terms).to.eql([['$between', params]]); }); From b9d21083613c0953a952544b1f2b9d8a476b4d4f Mon Sep 17 00:00:00 2001 From: Nick Herrera Date: Mon, 19 Sep 2016 08:53:59 -0700 Subject: [PATCH 38/50] refactor(client_test): remove unused `Query` import --- tests/client_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/client_test.js b/tests/client_test.js index 1c2769c..731ef32 100644 --- a/tests/client_test.js +++ b/tests/client_test.js @@ -1,6 +1,6 @@ import expect from 'expect.js'; import querystring from 'querystring'; -import {Client, Query} from '../src/index'; +import Client from '../src/client'; import {EventEmitter} from 'events'; var emitter = new EventEmitter(); From a062c1f449d5c9cb31f7fc46abc0720320f52be4 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 19 Sep 2016 15:58:17 -0700 Subject: [PATCH 39/50] refactor(field): remove obsolete code --- src/field.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/field.js b/src/field.js index fac5a41..476c8bf 100644 --- a/src/field.js +++ b/src/field.js @@ -55,11 +55,6 @@ export default class Field { return this.in(value); } - contains(value) { - this.filters.push(["$contains", value]); - return this; - } - match(expression) { this.filters.push(["$match", expression]); return this; From 236d145cad8bd76e95ec7022cec0117270c1629d Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 19 Sep 2016 16:00:37 -0700 Subject: [PATCH 40/50] test(field_test): remove dead code test --- tests/field_test.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/field_test.js b/tests/field_test.js index 2191770..835428c 100644 --- a/tests/field_test.js +++ b/tests/field_test.js @@ -71,13 +71,6 @@ describe('Field', () => { }); }); - describe('#contains()', () => { - it('should equal a filter with a value of $contains', () => { - let expectedFilter = [['$contains', 'y']]; - expect(field.contains('y').filters).to.eql(expectedFilter); - }); - }); - describe('#match()', () => { it('should equal a filter with a value of $match', () => { let expectedFilter = [['$match', 'y']]; From a4c65e41768e33015de799a390c50128b08ade30 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 19 Sep 2016 16:02:53 -0700 Subject: [PATCH 41/50] test(field_test): fix test to use correct field --- tests/field_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/field_test.js b/tests/field_test.js index 835428c..4b6b1df 100644 --- a/tests/field_test.js +++ b/tests/field_test.js @@ -88,7 +88,7 @@ describe('Field', () => { describe('#istarts()', () => { it('should equal a filter with a value of $istarts', () => { let expectedFilter = [['$eq', 'y']]; - expect(field.eq('y').filters).to.eql(expectedFilter); + expect(field.istarts('y').filters).to.eql(expectedFilter); }); }); From 25478aa3bebc27b8342882d0a71cea9c1f6b8e95 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Mon, 19 Sep 2016 16:17:06 -0700 Subject: [PATCH 42/50] test(field_test): finish updating test --- tests/field_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/field_test.js b/tests/field_test.js index 4b6b1df..bb8c045 100644 --- a/tests/field_test.js +++ b/tests/field_test.js @@ -87,7 +87,7 @@ describe('Field', () => { describe('#istarts()', () => { it('should equal a filter with a value of $istarts', () => { - let expectedFilter = [['$eq', 'y']]; + let expectedFilter = [['$istarts', 'y']]; expect(field.istarts('y').filters).to.eql(expectedFilter); }); }); From 1a69190c9734b3ab2cff909f9329466e69cb3554 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Wed, 21 Sep 2016 10:38:52 -0700 Subject: [PATCH 43/50] test(query_test): add test for `group` --- tests/query_test.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/query_test.js b/tests/query_test.js index 715dc5a..71e2654 100644 --- a/tests/query_test.js +++ b/tests/query_test.js @@ -130,6 +130,13 @@ describe('Query', () => { }); }); + describe('#group()', () => { + it('sets group', () => { + query.group('rank'); + expect(query.terms).to.eql([['$group', {'field': 'rank'}]]); + }); + }); + describe('#count()', () => { it('sets count', () => { query.count(); From 4b603b1b1c2bd73bdb207aeec8a88d3debfb45d5 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Wed, 21 Sep 2016 10:39:12 -0700 Subject: [PATCH 44/50] test(query_test): add test for `delete` --- tests/query_test.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/query_test.js b/tests/query_test.js index 71e2654..95b45f0 100644 --- a/tests/query_test.js +++ b/tests/query_test.js @@ -205,4 +205,11 @@ describe('Query', () => { expect(query.terms).to.eql([['$get_nearest', {index: 'location', geometry: point}]]); }); }); + + describe('#delete()', () => { + it('sets delete', () => { + query.delete('hard', false); + expect(query.terms).to.eql([['$delete', {durability: 'hard', return_changes: false}]]); + }); + }); }); From 88b3677717cfd4c98585055d90c92c467d7728e4 Mon Sep 17 00:00:00 2001 From: dmpayton Date: Wed, 21 Sep 2016 15:50:13 -0700 Subject: [PATCH 45/50] =?UTF-8?q?Rewrite=20Query.filter().=20Untested.=20?= =?UTF-8?q?=C2=AF\=5F(=E3=83=84)=5F/=C2=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/query.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/query.js b/src/query.js index d31fb67..5ec8dee 100644 --- a/src/query.js +++ b/src/query.js @@ -28,12 +28,12 @@ export default class Query { return this; } - filter(...filters) { - var filterSet = filters.reduce((filterSet, currentFilter) => { - return filterSet.concat(currentFilter.toJS()); - }, []); - - this.terms.push(['$filter', {filterSet}]); + filter(...filters, kwargs) { + params = {predicate: filters} + if(kwargs.default !== undefined) { + params.default = kwargs.default + } + this.terms.push(['$filter', params]); return this; } From 6f858e41b9f37ea1552d457c208b3cbf02200247 Mon Sep 17 00:00:00 2001 From: dmpayton Date: Wed, 21 Sep 2016 16:31:26 -0700 Subject: [PATCH 46/50] =?UTF-8?q?Re-Rewrite=20Query.filter().=20Untested.?= =?UTF-8?q?=20=C2=AF\=5F(=E3=83=84)=5F/=C2=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/query.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/query.js b/src/query.js index 5ec8dee..32899b5 100644 --- a/src/query.js +++ b/src/query.js @@ -28,10 +28,13 @@ export default class Query { return this; } - filter(...filters, kwargs) { - params = {predicate: filters} - if(kwargs.default !== undefined) { - params.default = kwargs.default + filter() { + var params = {}; + if (arguments[arguments.length - 1] instanceof Array) { + params.predicate = arguments; + } else { + params.predicate = Array.prototype.slice.call(arguments, 0, arguments.length - 1); + params.default = arguments[arguments.length - 1].default; } this.terms.push(['$filter', params]); return this; From 4a6d8008a9932478b687f0c547583e7dcfe8af97 Mon Sep 17 00:00:00 2001 From: Elanna Grossman Date: Wed, 21 Sep 2016 16:48:41 -0700 Subject: [PATCH 47/50] test(query_test): add early implementation of `filter` tests --- tests/query_test.js | 74 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/tests/query_test.js b/tests/query_test.js index 95b45f0..b061280 100644 --- a/tests/query_test.js +++ b/tests/query_test.js @@ -1,11 +1,14 @@ import expect from 'expect.js'; import {Query} from '../src/index'; +import {Field} from '../src/index'; var query; +var field; describe('Query', () => { beforeEach(function() { query = new Query('testSchema'); + field = new Field('x'); }); describe('initialization', () => { @@ -38,6 +41,77 @@ describe('Query', () => { }); }); + describe('#filter()', () => { + context('when ge', () => { + var expected = { + $type: 'query', + $schema: 'testSchema', + $query: [ + ['$filter', {'predicate': + [['rank', ['$ge', 3]]], + }] + ] + }; + + it('sets filter', () => { + expect(query.filter(new Field('rank').ge(3)).toJS()).to.eql(expected); + }); + }); + + context('when multiple', () => { + var expected = { + $type: 'query', + $schema: 'testSchema', + $query: [ + ['$filter', {'predicate': + [['year', ['$ge', 1990]], + ['year', ['$lt', 2000]]], + }] + ] + }; + + it('sets filter', () => { + expect(query.filter(new Field('year').ge(1990).lt(2000)).toJS()).to.eql(expected); + }); + }); + + context('when or', () => { + var expected = { + $type: 'query', + $schema: 'testSchema', + $query: [ + ['$filter', {'predicate': + [['year', ['$lt', 1990]], + ['year', ['$ge', 2000]]], + }] + ] + }; + + it('sets filter', () => { + expect(query.filter(new Field('year').lt(1990).ge(2000)).toJS()).to.eql(expected); + }); + }); + + context('when default is set to true', () => { + var expected = { + $type: 'query', + $schema: 'testSchema', + $query: [ + ['$filter', { + 'predicate':[ + ['year', ['$eq', 2000]] + ], + 'default': true, + }] + ] + }; + + it('sets filter', () => { + expect(query.filter(new Field('year').eq(2000), {default: true}).toJS()).to.eql(expected); + }); + }); + }); + describe('#hasFields()', () => { it('sets hasFields', () => { query.hasFields('title', 'rating'); From d8781d8eab7ff155aed84307040f481211cf39f7 Mon Sep 17 00:00:00 2001 From: dmpayton Date: Wed, 21 Sep 2016 21:23:49 -0700 Subject: [PATCH 48/50] Rewrite Field operators and modifiers to return their data, and test accordingly. --- src/field.js | 126 ++++++++++++-------------------------------- src/query.js | 11 ++-- tests/field_test.js | 67 +++++++++++------------ tests/query_test.js | 10 +++- 4 files changed, 80 insertions(+), 134 deletions(-) diff --git a/src/field.js b/src/field.js index 476c8bf..b4c088c 100644 --- a/src/field.js +++ b/src/field.js @@ -1,97 +1,41 @@ export default class Field { constructor(field) { this.field = field; - this.filters = []; } - toJS() { - return this.filters.map(filter => { - return [this.field, filter]; - }); - } - - eq(value) { - this.filters.push(["$eq", value]); - return this; - } - - ieq(value) { - this.filters.push(["$ieq", value]); - return this; - } - - ne(value) { - this.filters.push(["$ne", value]); - return this; - } - - lt(value) { - this.filters.push(["$lt", value]); - return this; - } - - le(value) { - this.filters.push(["$le", value]); - return this; - } - - gt(value) { - this.filters.push(["$gt", value]); - return this; - } - - ge(value) { - this.filters.push(["$ge", value]); - return this; - } - - in(value) { - this.filters.push(["$in", value]); - return this; - } - - inSet(value) { - console.warn("The function inSet() is deprecated, use in()."); - return this.in(value); - } - - match(expression) { - this.filters.push(["$match", expression]); - return this; - } - - regex(expression) { - console.warn("The function regex() is deprecated, please use match()."); - return this.match(expression); - } - - starts(value) { - this.filters.push(["$starts", value]); - return this; - } - - istarts(value) { - this.filters.push(["$istarts", value]); - return this; - } - - ends(value) { - this.filters.push(["$ends", value]); - return this; - } - - iends(value) { - this.filters.push(["$iends", value]); - return this; - } - - intersects(value) { - this.filters.push(["$intersects", value]); - return this; - } - - includes(value) { - this.filters.push(["$includes", value]); - return this; - } + _operator(operator, value){ + return [this.field, [`$${operator}`, value]] + } + + eq(value){ return this._operator('eq', value); } + ne(value){ return this._operator('ne', value); } + lt(value){ return this._operator('lt', value); } + le(value){ return this._operator('le', value); } + gt(value){ return this._operator('gt', value); } + ge(value){ return this._operator('ge', value); } + ieq(value){ return this._operator('ieq', value); } + in(value){ return this._operator('in', value); } + match(value){ return this._operator('match', value); } + starts(value){ return this._operator('starts', value); } + istarts(value){ return this._operator('istarts', value); } + ends(value){ return this._operator('ends', value); } + iends(value){ return this._operator('iends', value); } + intersects(value){ return this._operator('intersects', value); } + includes(value){ return this._operator('includes', value); } + + _modifier(modifier){ + return new Field(`${this.field}.$${modifier}`); + } + + date(){ return this._modifier('date'); } + time(){ return this._modifier('time'); } + year(){ return this._modifier('year'); } + month(){ return this._modifier('month'); } + day(){ return this._modifier('day'); } + hours(){ return this._modifier('hours'); } + minutes(){ return this._modifier('minutes'); } + seconds(){ return this._modifier('seconds'); } + day_of_month(){ return this._modifier('day_of_month'); } + day_of_year(){ return this._modifier('day_of_year'); } + timezone(){ return this._modifier('timezone'); } } diff --git a/src/query.js b/src/query.js index 32899b5..2e9b6bd 100644 --- a/src/query.js +++ b/src/query.js @@ -1,4 +1,5 @@ import _ from 'lodash'; +import Field from './field' export default class Query { constructor(schema) { @@ -30,12 +31,14 @@ export default class Query { filter() { var params = {}; - if (arguments[arguments.length - 1] instanceof Array) { - params.predicate = arguments; + + if (_.last(arguments) instanceof Array) { + params.predicate = _.slice(arguments) } else { - params.predicate = Array.prototype.slice.call(arguments, 0, arguments.length - 1); - params.default = arguments[arguments.length - 1].default; + params.predicate = _.slice(arguments, 0, arguments.length - 1); + params.default = _.last(arguments).default; } + this.terms.push(['$filter', params]); return this; } diff --git a/tests/field_test.js b/tests/field_test.js index bb8c045..47d0dd7 100644 --- a/tests/field_test.js +++ b/tests/field_test.js @@ -8,115 +8,108 @@ describe('Field', () => { field = new Field('x'); }); - describe('#toJS()', () => { - it('should equal a value of $eq', () => { - expect(field.toJS()).to.eql([]); - expect(field.eq('y').toJS()).to.eql([['x', ['$eq', 'y']]]); - }); - }); - describe('#eq()', () => { it('should equal a filter with a value of $eq', () => { - let expectedFilter = [['$eq', 'y']]; - expect(field.eq('y').filters).to.eql(expectedFilter); + let expectedFilter = ['x', ['$eq', 'y']]; + expect(field.eq('y')).to.eql(expectedFilter); }); }); describe('#ieq()', () => { it('should equal a filter with a value of $ieq', () => { - let expectedFilter = [['$ieq', 'y']]; - expect(field.ieq('y').filters).to.eql(expectedFilter); + let expectedFilter = ['x', ['$ieq', 'y']]; + expect(field.ieq('y')).to.eql(expectedFilter); }); }); describe('#ne()', () => { it('should equal a filter with a value of $ne', () => { - let expectedFilter = [['$ne', 'y']]; - expect(field.ne('y').filters).to.eql(expectedFilter); + let expectedFilter = ['x', ['$ne', 'y']]; + expect(field.ne('y')).to.eql(expectedFilter); }); }); describe('#lt()', () => { it('should equal a filter with a value of $lt', () => { - let expectedFilter = [['$lt', 'y']]; - expect(field.lt('y').filters).to.eql(expectedFilter); + let expectedFilter = ['x', ['$lt', 'y']]; + expect(field.lt('y')).to.eql(expectedFilter); }); }); describe('#le()', () => { it('should equal a filter with a value of $le', () => { - let expectedFilter = [['$le', 'y']]; - expect(field.le('y').filters).to.eql(expectedFilter); + let expectedFilter = ['x', ['$le', 'y']]; + expect(field.le('y')).to.eql(expectedFilter); }); }); describe('#gt()', () => { it('should equal a filter with a value of $gt', () => { - let expectedFilter = [['$gt', 'y']]; - expect(field.gt('y').filters).to.eql(expectedFilter); + let expectedFilter = ['x', ['$gt', 'y']]; + expect(field.gt('y')).to.eql(expectedFilter); }); }); describe('#ge()', () => { it('should equal a filter with a value of $ge', () => { - let expectedFilter = [['$ge', 'y']]; - expect(field.ge('y').filters).to.eql(expectedFilter); + let expectedFilter = ['x', ['$ge', 'y']]; + expect(field.ge('y')).to.eql(expectedFilter); }); }); describe('#in()', () => { it('should equal a filter with a value of $in', () => { - let expectedFilter = [['$in', 'y']]; - expect(field.in('y').filters).to.eql(expectedFilter); + let expectedFilter = ['x', ['$in', 'y']]; + expect(field.in('y')).to.eql(expectedFilter); }); }); describe('#match()', () => { it('should equal a filter with a value of $match', () => { - let expectedFilter = [['$match', 'y']]; - expect(field.match('y').filters).to.eql(expectedFilter); + let expectedFilter = ['x', ['$match', 'y']]; + expect(field.match('y')).to.eql(expectedFilter); }); }); describe('#starts()', () => { it('should equal a filter with a value of $starts', () => { - let expectedFilter = [['$starts', 'y']]; - expect(field.starts('y').filters).to.eql(expectedFilter); + let expectedFilter = ['x', ['$starts', 'y']]; + expect(field.starts('y')).to.eql(expectedFilter); }); }); describe('#istarts()', () => { it('should equal a filter with a value of $istarts', () => { - let expectedFilter = [['$istarts', 'y']]; - expect(field.istarts('y').filters).to.eql(expectedFilter); + let expectedFilter = ['x', ['$istarts', 'y']]; + expect(field.istarts('y')).to.eql(expectedFilter); }); }); describe('#ends()', () => { it('should equal a filter with a value of $ends', () => { - let expectedFilter = [['$ends', 'y']]; - expect(field.ends('y').filters).to.eql(expectedFilter); + let expectedFilter = ['x', ['$ends', 'y']]; + expect(field.ends('y')).to.eql(expectedFilter); }); }); describe('#iends()', () => { it('should equal a filter with a value of $iends', () => { - let expectedFilter = [['$iends', 'y']]; - expect(field.iends('y').filters).to.eql(expectedFilter); + let expectedFilter = ['x', ['$iends', 'y']]; + expect(field.iends('y')).to.eql(expectedFilter); }); }); describe('#intersects()', () => { it('should equal a filter with a value of $intersects', () => { - let expectedFilter = [['$intersects', 'y']]; - expect(field.intersects('y').filters).to.eql(expectedFilter); + let expectedFilter = ['x', ['$intersects', 'y']]; + expect(field.intersects('y')).to.eql(expectedFilter); }); }); describe('#includes()', () => { it('should equal a filter with a value of $includes', () => { - let expectedFilter = [['$includes', 'y']]; - expect(field.includes('y').filters).to.eql(expectedFilter); + let expectedFilter = ['x', ['$includes', 'y']]; + expect(field.includes('y')).to.eql(expectedFilter); }); }); }); diff --git a/tests/query_test.js b/tests/query_test.js index b061280..1605bbb 100644 --- a/tests/query_test.js +++ b/tests/query_test.js @@ -71,7 +71,10 @@ describe('Query', () => { }; it('sets filter', () => { - expect(query.filter(new Field('year').ge(1990).lt(2000)).toJS()).to.eql(expected); + expect(query.filter( + new Field('year').ge(1990), + new Field('year').lt(2000) + ).toJS()).to.eql(expected); }); }); @@ -88,7 +91,10 @@ describe('Query', () => { }; it('sets filter', () => { - expect(query.filter(new Field('year').lt(1990).ge(2000)).toJS()).to.eql(expected); + expect(query.filter( + new Field('year').lt(1990), + new Field('year').ge(2000) + ).toJS()).to.eql(expected); }); }); From 859e55434ae82268f4c1b6c126adbed415f8dbc3 Mon Sep 17 00:00:00 2001 From: dmpayton Date: Wed, 21 Sep 2016 21:29:01 -0700 Subject: [PATCH 49/50] Add .editorconfig --- .editorconfig | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3bb77ba --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +# http://editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{js,jsx}] +indent_size = 2 From 377315b30396424ec9aac56cf5f5bd657d82e7b2 Mon Sep 17 00:00:00 2001 From: dmpayton Date: Wed, 21 Sep 2016 21:29:32 -0700 Subject: [PATCH 50/50] Style: Fix indentation to match .editorconfig. --- src/client.js | 248 +++++++++---------- src/field.js | 70 +++--- src/index.js | 6 +- src/query.js | 350 +++++++++++++-------------- src/scripting.js | 38 +-- tests/query_test.js | 572 ++++++++++++++++++++++---------------------- 6 files changed, 642 insertions(+), 642 deletions(-) diff --git a/src/client.js b/src/client.js index 3b0d291..9dbab11 100644 --- a/src/client.js +++ b/src/client.js @@ -13,116 +13,116 @@ import PolicyAPI from './api/policy'; import TaskAPI from './api/task'; export default class Client { - constructor(subdomain, token) { - this.protocol = 'https'; - this.host = 'mntge.com'; - this.subdomain = subdomain; - this.token = token; - - this.documents = new DocumentAPI(this); - this.schemas = new SchemaAPI(this); - this.users = new UserAPI(this); - this.roles = new RoleAPI(this); - this.project = new ProjectAPI(this); - this.files = new FileAPI(this); - this.policy = new PolicyAPI(this); - this.tasks = new TaskAPI(this); - } - - url(endpoint) { - return `${this.protocol}://${this.subdomain}.${this.host}/api/v1/${endpoint}`; - } - - authenticate(email, password) { - return this.request('user/', 'POST', { - username: email, - password: password - }).then(response => { - this.token = response.data.token; - return response; - }); - } - - user() { - if(this.token) { - return this.request('user/'); - } - - return Promise.reject('The current user is not authenticated.'); - } - - execute(queries) { - var querySet = {}; - - for(var key in queries) { - if(queries.hasOwnProperty(key)) { - querySet[key] = queries[key].toJS(); - } - } - - return this.request('execute/', 'POST', querySet); - } - - request(endpoint, method, data, file) { - var requestUrl = this.url(endpoint); - - var options = { - method: method && method.toUpperCase() || "GET", - headers: { - accept: 'application/json', - 'X-Requested-With': 'XMLHttpRequest' - } - }; - if (!file) { - options.headers['Content-Type'] = 'application/json'; - } - if (data) { - if (options.method === "GET") { - requestUrl += '?' + querystring.stringify(data); - } else { - if(file) options.body = data; - else options.body = JSON.stringify(data); - } - } - if (this.token) { - options.headers.Authorization = `Token ${this.token}`; - } - if (options.body) { - //Varnish and heroku require a content length! - options.headers['Content-Length'] = getByteLen(options.body); - } - - return this._agent(requestUrl, options).then(function(response) { - if(response.status === 204) { - return; - } - if (!response.ok) { - response.request = _.merge({ - url: requestUrl - }, options); - return Promise.reject(response); - } - if (response.status >= 400) { - return response.text().then(body => { - var errorMessage = body || response.statusText; - try { - errorMessage = JSON.parse(body); - } catch (e) {} - return Promise.reject(errorMessage); - }); - } - return response.json(); - }).then(function(payload) { - if (payload && payload.errors) { - return Promise.reject(payload.errors); - } - return payload; - }); - } - - _agent(...args) { - return fetch(...args); - } + constructor(subdomain, token) { + this.protocol = 'https'; + this.host = 'mntge.com'; + this.subdomain = subdomain; + this.token = token; + + this.documents = new DocumentAPI(this); + this.schemas = new SchemaAPI(this); + this.users = new UserAPI(this); + this.roles = new RoleAPI(this); + this.project = new ProjectAPI(this); + this.files = new FileAPI(this); + this.policy = new PolicyAPI(this); + this.tasks = new TaskAPI(this); + } + + url(endpoint) { + return `${this.protocol}://${this.subdomain}.${this.host}/api/v1/${endpoint}`; + } + + authenticate(email, password) { + return this.request('user/', 'POST', { + username: email, + password: password + }).then(response => { + this.token = response.data.token; + return response; + }); + } + + user() { + if(this.token) { + return this.request('user/'); + } + + return Promise.reject('The current user is not authenticated.'); + } + + execute(queries) { + var querySet = {}; + + for(var key in queries) { + if(queries.hasOwnProperty(key)) { + querySet[key] = queries[key].toJS(); + } + } + + return this.request('execute/', 'POST', querySet); + } + + request(endpoint, method, data, file) { + var requestUrl = this.url(endpoint); + + var options = { + method: method && method.toUpperCase() || "GET", + headers: { + accept: 'application/json', + 'X-Requested-With': 'XMLHttpRequest' + } + }; + if (!file) { + options.headers['Content-Type'] = 'application/json'; + } + if (data) { + if (options.method === "GET") { + requestUrl += '?' + querystring.stringify(data); + } else { + if(file) options.body = data; + else options.body = JSON.stringify(data); + } + } + if (this.token) { + options.headers.Authorization = `Token ${this.token}`; + } + if (options.body) { + //Varnish and heroku require a content length! + options.headers['Content-Length'] = getByteLen(options.body); + } + + return this._agent(requestUrl, options).then(function(response) { + if(response.status === 204) { + return; + } + if (!response.ok) { + response.request = _.merge({ + url: requestUrl + }, options); + return Promise.reject(response); + } + if (response.status >= 400) { + return response.text().then(body => { + var errorMessage = body || response.statusText; + try { + errorMessage = JSON.parse(body); + } catch (e) {} + return Promise.reject(errorMessage); + }); + } + return response.json(); + }).then(function(payload) { + if (payload && payload.errors) { + return Promise.reject(payload.errors); + } + return payload; + }); + } + + _agent(...args) { + return fetch(...args); + } } /** @@ -134,18 +134,18 @@ export default class Client { * @return {int} */ function getByteLen(normal_val) { - // Force string type - normal_val = String(normal_val); - - var byteLen = 0; - for (var i = 0; i < normal_val.length; i++) { - var c = normal_val.charCodeAt(i); - byteLen += c < (1 << 7) ? 1 : - c < (1 << 11) ? 2 : - c < (1 << 16) ? 3 : - c < (1 << 21) ? 4 : - c < (1 << 26) ? 5 : - c < (1 << 31) ? 6 : Number.NaN; - } - return byteLen; + // Force string type + normal_val = String(normal_val); + + var byteLen = 0; + for (var i = 0; i < normal_val.length; i++) { + var c = normal_val.charCodeAt(i); + byteLen += c < (1 << 7) ? 1 : + c < (1 << 11) ? 2 : + c < (1 << 16) ? 3 : + c < (1 << 21) ? 4 : + c < (1 << 26) ? 5 : + c < (1 << 31) ? 6 : Number.NaN; + } + return byteLen; } diff --git a/src/field.js b/src/field.js index b4c088c..ffaa75e 100644 --- a/src/field.js +++ b/src/field.js @@ -1,41 +1,41 @@ export default class Field { - constructor(field) { - this.field = field; - } + constructor(field) { + this.field = field; + } - _operator(operator, value){ - return [this.field, [`$${operator}`, value]] - } + _operator(operator, value){ + return [this.field, [`$${operator}`, value]] + } - eq(value){ return this._operator('eq', value); } - ne(value){ return this._operator('ne', value); } - lt(value){ return this._operator('lt', value); } - le(value){ return this._operator('le', value); } - gt(value){ return this._operator('gt', value); } - ge(value){ return this._operator('ge', value); } - ieq(value){ return this._operator('ieq', value); } - in(value){ return this._operator('in', value); } - match(value){ return this._operator('match', value); } - starts(value){ return this._operator('starts', value); } - istarts(value){ return this._operator('istarts', value); } - ends(value){ return this._operator('ends', value); } - iends(value){ return this._operator('iends', value); } - intersects(value){ return this._operator('intersects', value); } - includes(value){ return this._operator('includes', value); } + eq(value){ return this._operator('eq', value); } + ne(value){ return this._operator('ne', value); } + lt(value){ return this._operator('lt', value); } + le(value){ return this._operator('le', value); } + gt(value){ return this._operator('gt', value); } + ge(value){ return this._operator('ge', value); } + ieq(value){ return this._operator('ieq', value); } + in(value){ return this._operator('in', value); } + match(value){ return this._operator('match', value); } + starts(value){ return this._operator('starts', value); } + istarts(value){ return this._operator('istarts', value); } + ends(value){ return this._operator('ends', value); } + iends(value){ return this._operator('iends', value); } + intersects(value){ return this._operator('intersects', value); } + includes(value){ return this._operator('includes', value); } - _modifier(modifier){ - return new Field(`${this.field}.$${modifier}`); - } + _modifier(modifier){ + return new Field(`${this.field}.$${modifier}`); + } - date(){ return this._modifier('date'); } - time(){ return this._modifier('time'); } - year(){ return this._modifier('year'); } - month(){ return this._modifier('month'); } - day(){ return this._modifier('day'); } - hours(){ return this._modifier('hours'); } - minutes(){ return this._modifier('minutes'); } - seconds(){ return this._modifier('seconds'); } - day_of_month(){ return this._modifier('day_of_month'); } - day_of_year(){ return this._modifier('day_of_year'); } - timezone(){ return this._modifier('timezone'); } + date(){ return this._modifier('date'); } + time(){ return this._modifier('time'); } + year(){ return this._modifier('year'); } + month(){ return this._modifier('month'); } + day(){ return this._modifier('day'); } + hours(){ return this._modifier('hours'); } + minutes(){ return this._modifier('minutes'); } + seconds(){ return this._modifier('seconds'); } + day_of_month(){ return this._modifier('day_of_month'); } + day_of_year(){ return this._modifier('day_of_year'); } + timezone(){ return this._modifier('timezone'); } } diff --git a/src/index.js b/src/index.js index 34590b9..3382150 100644 --- a/src/index.js +++ b/src/index.js @@ -3,7 +3,7 @@ import Query from './query'; import Field from './field'; export { - Client, - Field, - Query + Client, + Field, + Query }; diff --git a/src/query.js b/src/query.js index 2e9b6bd..b4a7122 100644 --- a/src/query.js +++ b/src/query.js @@ -2,179 +2,179 @@ import _ from 'lodash'; import Field from './field' export default class Query { - constructor(schema) { - if (!schema) throw 'A schema name is required'; - - this.schema = schema; - this.terms = []; - } - - toJS() { - return { - $type: 'query', - $schema: this.schema, - $query: this.terms - }; - } - - // Selecting Data - - get(id) { - this.terms.push(['$get', {id}]); - return this; - } - - getAll(ids, index = 'id') { - this.terms.push(['$get_all', {index, ids}]); - return this; - } - - filter() { - var params = {}; - - if (_.last(arguments) instanceof Array) { - params.predicate = _.slice(arguments) - } else { - params.predicate = _.slice(arguments, 0, arguments.length - 1); - params.default = _.last(arguments).default; - } - - this.terms.push(['$filter', params]); - return this; - } - - between(options) { - const defaults = { - lowerKey : '$minval', - upperKey : '$maxval' - }; - const params = _.assign(defaults, options); - this.terms.push(['$between', params]); - return this; - } - - // Transformations - - hasFields(...fields) { - this.terms.push(['$has_fields', {fields}]); - return this; - } - - withFields(...fields) { - this.terms.push(['$with_fields', {fields}]); - return this; - } - - orderBy({key, index, ordering}) { - ordering = (ordering === undefined) ? '$asc' : ordering; - if(['asc', 'desc'].indexOf(ordering) !== -1) { - console.warn('asc/desc parameters deprecated. Please use $asc/$desc.'); - ordering = '$' + ordering; - } - - if(['$asc', '$desc'].indexOf(ordering) === -1) { - throw new Error('ordering must be $desc or $asc'); - } - - var params = { ordering }; - - if(key !== undefined) { - params.key = key; - } - - if(index !== undefined) { - params.index = index; - } - - this.terms.push(['$order_by', params]); - return this; - } - - skip(n) { - this.terms.push(['$skip', {n}]); - return this; - } - - limit(n) { - this.terms.push(['$limit', {n}]); - return this; - } - - slice(startOffset, endOffset) { - this.terms.push(['$slice', {startOffset, endOffset}]); - return this; - } - - nth(n) { - this.terms.push(['$nth', {n}]); - return this; - } - - sample(n) { - this.terms.push(['$sample', {n}]); - return this; - } - - // Manipulation - - pluck(...fields) { - this.terms.push(['$pluck', {fields}]); - return this; - } - - without(...fields) { - this.terms.push(['$without', {fields}]); - return this; - } - - // Aggregation - - group(field) { - this.terms.push(['$group', {field}]); - return this; - } - - count() { - this.terms.push(['$count']); - return this; - } - - sum(field) { - this.terms.push(['$sum', {field}]); - return this; - } - - avg(field) { - this.terms.push(['$avg', {field}]); - return this; - } - - min(field) { - this.terms.push(['$min', {field}]); - return this; - } - - max(field) { - this.terms.push(['$max', {field}]); - return this; - } - - // Geospatial - - getIntersecting(geometry, index) { - this.terms.push(['$get_intersecting', {index, geometry}]); - return this; - } - - getNearest(geometry, index) { - this.terms.push(['$get_nearest', {index, geometry}]); - return this; - } - - // Delete - - delete(durability = 'hard', return_changes = false) { - this.terms.push(['$delete', {durability, return_changes}]); - return this; - } + constructor(schema) { + if (!schema) throw 'A schema name is required'; + + this.schema = schema; + this.terms = []; + } + + toJS() { + return { + $type: 'query', + $schema: this.schema, + $query: this.terms + }; + } + + // Selecting Data + + get(id) { + this.terms.push(['$get', {id}]); + return this; + } + + getAll(ids, index = 'id') { + this.terms.push(['$get_all', {index, ids}]); + return this; + } + + filter() { + var params = {}; + + if (_.last(arguments) instanceof Array) { + params.predicate = _.slice(arguments) + } else { + params.predicate = _.slice(arguments, 0, arguments.length - 1); + params.default = _.last(arguments).default; + } + + this.terms.push(['$filter', params]); + return this; + } + + between(options) { + const defaults = { + lowerKey : '$minval', + upperKey : '$maxval' + }; + const params = _.assign(defaults, options); + this.terms.push(['$between', params]); + return this; + } + + // Transformations + + hasFields(...fields) { + this.terms.push(['$has_fields', {fields}]); + return this; + } + + withFields(...fields) { + this.terms.push(['$with_fields', {fields}]); + return this; + } + + orderBy({key, index, ordering}) { + ordering = (ordering === undefined) ? '$asc' : ordering; + if(['asc', 'desc'].indexOf(ordering) !== -1) { + console.warn('asc/desc parameters deprecated. Please use $asc/$desc.'); + ordering = '$' + ordering; + } + + if(['$asc', '$desc'].indexOf(ordering) === -1) { + throw new Error('ordering must be $desc or $asc'); + } + + var params = { ordering }; + + if(key !== undefined) { + params.key = key; + } + + if(index !== undefined) { + params.index = index; + } + + this.terms.push(['$order_by', params]); + return this; + } + + skip(n) { + this.terms.push(['$skip', {n}]); + return this; + } + + limit(n) { + this.terms.push(['$limit', {n}]); + return this; + } + + slice(startOffset, endOffset) { + this.terms.push(['$slice', {startOffset, endOffset}]); + return this; + } + + nth(n) { + this.terms.push(['$nth', {n}]); + return this; + } + + sample(n) { + this.terms.push(['$sample', {n}]); + return this; + } + + // Manipulation + + pluck(...fields) { + this.terms.push(['$pluck', {fields}]); + return this; + } + + without(...fields) { + this.terms.push(['$without', {fields}]); + return this; + } + + // Aggregation + + group(field) { + this.terms.push(['$group', {field}]); + return this; + } + + count() { + this.terms.push(['$count']); + return this; + } + + sum(field) { + this.terms.push(['$sum', {field}]); + return this; + } + + avg(field) { + this.terms.push(['$avg', {field}]); + return this; + } + + min(field) { + this.terms.push(['$min', {field}]); + return this; + } + + max(field) { + this.terms.push(['$max', {field}]); + return this; + } + + // Geospatial + + getIntersecting(geometry, index) { + this.terms.push(['$get_intersecting', {index, geometry}]); + return this; + } + + getNearest(geometry, index) { + this.terms.push(['$get_nearest', {index, geometry}]); + return this; + } + + // Delete + + delete(durability = 'hard', return_changes = false) { + this.terms.push(['$delete', {durability, return_changes}]); + return this; + } } diff --git a/src/scripting.js b/src/scripting.js index e500d6d..e6ac680 100644 --- a/src/scripting.js +++ b/src/scripting.js @@ -1,27 +1,27 @@ class Script { - constructor(name) { - this.name = name - } - - toJS() { - return { - $type: 'script', - $name: this.name - }; - } + constructor(name) { + this.name = name + } + + toJS() { + return { + $type: 'script', + $name: this.name + }; + } } class RunLua { - constructor(code) { - this.code = code; - } + constructor(code) { + this.code = code; + } - toJS() { - return { - $type: 'lua', - $code: this.code - }; - } + toJS() { + return { + $type: 'lua', + $code: this.code + }; + } } diff --git a/tests/query_test.js b/tests/query_test.js index 1605bbb..0149e73 100644 --- a/tests/query_test.js +++ b/tests/query_test.js @@ -6,290 +6,290 @@ var query; var field; describe('Query', () => { - beforeEach(function() { - query = new Query('testSchema'); - field = new Field('x'); - }); - - describe('initialization', () => { - it('should require a schema name', () => { - expect(query.schema).to.be('testSchema'); - }); - }); - - describe('#toJS()', () => { - it('should return a query object', () => { - expect(query.toJS()).to.eql({ - $type: 'query', - $schema: 'testSchema', - $query: [] - }); - }); - }); - - describe('#get()', () => { - it('sets get', () => { - query.get('1234'); - expect(query.terms).to.eql([['$get', {'id': '1234'}]]); - }); - }); - - describe('#getAll()', () => { - it('sets getAll', () => { - query.getAll(['1234', 'abcd']); - expect(query.terms).to.eql([['$get_all', {'ids': ['1234', 'abcd'], 'index': 'id'}]]); - }); - }); - - describe('#filter()', () => { - context('when ge', () => { - var expected = { - $type: 'query', - $schema: 'testSchema', - $query: [ - ['$filter', {'predicate': - [['rank', ['$ge', 3]]], - }] - ] - }; - - it('sets filter', () => { - expect(query.filter(new Field('rank').ge(3)).toJS()).to.eql(expected); - }); - }); - - context('when multiple', () => { - var expected = { - $type: 'query', - $schema: 'testSchema', - $query: [ - ['$filter', {'predicate': - [['year', ['$ge', 1990]], - ['year', ['$lt', 2000]]], - }] - ] - }; - - it('sets filter', () => { - expect(query.filter( - new Field('year').ge(1990), - new Field('year').lt(2000) - ).toJS()).to.eql(expected); - }); - }); - - context('when or', () => { - var expected = { - $type: 'query', - $schema: 'testSchema', - $query: [ - ['$filter', {'predicate': - [['year', ['$lt', 1990]], - ['year', ['$ge', 2000]]], - }] - ] - }; - - it('sets filter', () => { - expect(query.filter( - new Field('year').lt(1990), - new Field('year').ge(2000) - ).toJS()).to.eql(expected); - }); - }); - - context('when default is set to true', () => { - var expected = { - $type: 'query', - $schema: 'testSchema', - $query: [ - ['$filter', { - 'predicate':[ - ['year', ['$eq', 2000]] - ], - 'default': true, - }] - ] - }; - - it('sets filter', () => { - expect(query.filter(new Field('year').eq(2000), {default: true}).toJS()).to.eql(expected); - }); - }); - }); - - describe('#hasFields()', () => { - it('sets hasFields', () => { - query.hasFields('title', 'rating'); - expect(query.terms).to.eql([['$has_fields', {fields: ['title', 'rating']}]]); - }); - }); - - describe('#withFields()', () => { - it('sets withFields', () => { - query.withFields('title', 'rating'); - expect(query.terms).to.eql([['$with_fields', {fields: ['title', 'rating']}]]); - }); - }); - - describe('#orderBy()', () => { - context('when no direction supplied', () => { - it('sets order_by and default direction', () => { - query.orderBy({key: 'rating'}); - expect(query.terms).to.eql([['$order_by', {key: 'rating', ordering: '$asc'}]]); - }); - }); - - context('when direction is ascending', () => { - it('sets order_by and ascending direction', () => { - query.orderBy({key: 'rating', ordering: '$asc'}); - expect(query.terms).to.eql([['$order_by', {key: 'rating', ordering: '$asc'}]]); - }); - }); - - context('when direction is descending', () => { - it('sets order_by and descending direction', () => { - query.orderBy({key: 'rating', ordering: '$desc'}); - expect(query.terms).to.eql([['$order_by', {key: 'rating', ordering: '$desc'}]]); - }); - }); - - context('when direction is invalid', () => { - it('should throw an exception', () => { - expect(query.orderBy).withArgs('rating', -1).to.throwException(); - }); - }); - }); - - describe('#skip()', () => { - it('sets skip', () => { - query.skip(10); - expect(query.terms).to.eql([['$skip', {'n': 10}]]); - }); - }); - - describe('#limit()', () => { - it('sets limit', () => { - query.limit(10); - expect(query.terms).to.eql([['$limit', {'n': 10}]]); - }); - }); - - describe('#slice()', () => { - it('sets slice', () => { - query.slice(10, 20); - expect(query.terms).to.eql([['$slice', {'startOffset': 10, 'endOffset': 20}]]); - }); - }); - - describe('#nth()', () => { - it('sets nth', () => { - query.nth(5); - expect(query.terms).to.eql([['$nth', {'n': 5}]]); - }); - }); - - describe('#sample()', () => { - it('sets sample', () => { - query.sample(20); - expect(query.terms).to.eql([['$sample', {'n': 20}]]); - }); - }); - - describe('#pluck()', () => { - it('sets pluck', () => { - query.pluck('name', 'rank', 'rating'); - expect(query.terms).to.eql([['$pluck', {'fields': ['name', 'rank', 'rating']}]]); - }); - }); - - describe('#without()', () => { - it('sets without', () => { - query.without('votes', 'rank'); - expect(query.terms).to.eql([['$without', {'fields': ['votes', 'rank']}]]); - }); - }); - - describe('#group()', () => { - it('sets group', () => { - query.group('rank'); - expect(query.terms).to.eql([['$group', {'field': 'rank'}]]); - }); - }); - - describe('#count()', () => { - it('sets count', () => { - query.count(); - expect(query.terms).to.eql([['$count']]); - }); - }); - - describe('#sum()', () => { - it('sets sum', () => { - query.sum('rank'); - expect(query.terms).to.eql([['$sum', {'field': 'rank'}]]); - }); - }); - - describe('#avg()', () => { - it('sets avg', () => { - query.avg('rank'); - expect(query.terms).to.eql([['$avg', {'field': 'rank'}]]); - }); - }); - - describe('#min()', () => { - it('sets min', () => { - query.min('rating'); - expect(query.terms).to.eql([['$min', {'field': 'rating'}]]); - }); - }); - - describe('#max()', () => { - it('sets max', () => { - query.max('rating'); - expect(query.terms).to.eql([['$max', {'field': 'rating'}]]); - }); - }); - - describe('#between()', () => { - it('sets between', () => { - var params = { - lowerKey: 0, - upperKey: 10, - index: 'rank', - }; - query.between(params); - expect(query.terms).to.eql([['$between', params]]); - }); - }); - - describe('#getIntersecting()', () => { - it('sets get_intersecting', () => { - var point = { - 'coordinates': [-120.34589052200315, 36.12704320788633], - 'type': 'Point' - }; - query.getIntersecting(point, 'location'); - expect(query.terms).to.eql([['$get_intersecting', {index: 'location', geometry: point}]]); - }); - }); - - describe('#getNearest()', () => { - it('sets get_nearest', () => { - var point = { - 'type': 'Point', - 'coordinates': [-120.34589052200315, 36.12704320788633] - }; - query.getNearest(point, 'location'); - expect(query.terms).to.eql([['$get_nearest', {index: 'location', geometry: point}]]); - }); - }); - - describe('#delete()', () => { - it('sets delete', () => { - query.delete('hard', false); - expect(query.terms).to.eql([['$delete', {durability: 'hard', return_changes: false}]]); - }); - }); + beforeEach(function() { + query = new Query('testSchema'); + field = new Field('x'); + }); + + describe('initialization', () => { + it('should require a schema name', () => { + expect(query.schema).to.be('testSchema'); + }); + }); + + describe('#toJS()', () => { + it('should return a query object', () => { + expect(query.toJS()).to.eql({ + $type: 'query', + $schema: 'testSchema', + $query: [] + }); + }); + }); + + describe('#get()', () => { + it('sets get', () => { + query.get('1234'); + expect(query.terms).to.eql([['$get', {'id': '1234'}]]); + }); + }); + + describe('#getAll()', () => { + it('sets getAll', () => { + query.getAll(['1234', 'abcd']); + expect(query.terms).to.eql([['$get_all', {'ids': ['1234', 'abcd'], 'index': 'id'}]]); + }); + }); + + describe('#filter()', () => { + context('when ge', () => { + var expected = { + $type: 'query', + $schema: 'testSchema', + $query: [ + ['$filter', {'predicate': + [['rank', ['$ge', 3]]], + }] + ] + }; + + it('sets filter', () => { + expect(query.filter(new Field('rank').ge(3)).toJS()).to.eql(expected); + }); + }); + + context('when multiple', () => { + var expected = { + $type: 'query', + $schema: 'testSchema', + $query: [ + ['$filter', {'predicate': + [['year', ['$ge', 1990]], + ['year', ['$lt', 2000]]], + }] + ] + }; + + it('sets filter', () => { + expect(query.filter( + new Field('year').ge(1990), + new Field('year').lt(2000) + ).toJS()).to.eql(expected); + }); + }); + + context('when or', () => { + var expected = { + $type: 'query', + $schema: 'testSchema', + $query: [ + ['$filter', {'predicate': + [['year', ['$lt', 1990]], + ['year', ['$ge', 2000]]], + }] + ] + }; + + it('sets filter', () => { + expect(query.filter( + new Field('year').lt(1990), + new Field('year').ge(2000) + ).toJS()).to.eql(expected); + }); + }); + + context('when default is set to true', () => { + var expected = { + $type: 'query', + $schema: 'testSchema', + $query: [ + ['$filter', { + 'predicate':[ + ['year', ['$eq', 2000]] + ], + 'default': true, + }] + ] + }; + + it('sets filter', () => { + expect(query.filter(new Field('year').eq(2000), {default: true}).toJS()).to.eql(expected); + }); + }); + }); + + describe('#hasFields()', () => { + it('sets hasFields', () => { + query.hasFields('title', 'rating'); + expect(query.terms).to.eql([['$has_fields', {fields: ['title', 'rating']}]]); + }); + }); + + describe('#withFields()', () => { + it('sets withFields', () => { + query.withFields('title', 'rating'); + expect(query.terms).to.eql([['$with_fields', {fields: ['title', 'rating']}]]); + }); + }); + + describe('#orderBy()', () => { + context('when no direction supplied', () => { + it('sets order_by and default direction', () => { + query.orderBy({key: 'rating'}); + expect(query.terms).to.eql([['$order_by', {key: 'rating', ordering: '$asc'}]]); + }); + }); + + context('when direction is ascending', () => { + it('sets order_by and ascending direction', () => { + query.orderBy({key: 'rating', ordering: '$asc'}); + expect(query.terms).to.eql([['$order_by', {key: 'rating', ordering: '$asc'}]]); + }); + }); + + context('when direction is descending', () => { + it('sets order_by and descending direction', () => { + query.orderBy({key: 'rating', ordering: '$desc'}); + expect(query.terms).to.eql([['$order_by', {key: 'rating', ordering: '$desc'}]]); + }); + }); + + context('when direction is invalid', () => { + it('should throw an exception', () => { + expect(query.orderBy).withArgs('rating', -1).to.throwException(); + }); + }); + }); + + describe('#skip()', () => { + it('sets skip', () => { + query.skip(10); + expect(query.terms).to.eql([['$skip', {'n': 10}]]); + }); + }); + + describe('#limit()', () => { + it('sets limit', () => { + query.limit(10); + expect(query.terms).to.eql([['$limit', {'n': 10}]]); + }); + }); + + describe('#slice()', () => { + it('sets slice', () => { + query.slice(10, 20); + expect(query.terms).to.eql([['$slice', {'startOffset': 10, 'endOffset': 20}]]); + }); + }); + + describe('#nth()', () => { + it('sets nth', () => { + query.nth(5); + expect(query.terms).to.eql([['$nth', {'n': 5}]]); + }); + }); + + describe('#sample()', () => { + it('sets sample', () => { + query.sample(20); + expect(query.terms).to.eql([['$sample', {'n': 20}]]); + }); + }); + + describe('#pluck()', () => { + it('sets pluck', () => { + query.pluck('name', 'rank', 'rating'); + expect(query.terms).to.eql([['$pluck', {'fields': ['name', 'rank', 'rating']}]]); + }); + }); + + describe('#without()', () => { + it('sets without', () => { + query.without('votes', 'rank'); + expect(query.terms).to.eql([['$without', {'fields': ['votes', 'rank']}]]); + }); + }); + + describe('#group()', () => { + it('sets group', () => { + query.group('rank'); + expect(query.terms).to.eql([['$group', {'field': 'rank'}]]); + }); + }); + + describe('#count()', () => { + it('sets count', () => { + query.count(); + expect(query.terms).to.eql([['$count']]); + }); + }); + + describe('#sum()', () => { + it('sets sum', () => { + query.sum('rank'); + expect(query.terms).to.eql([['$sum', {'field': 'rank'}]]); + }); + }); + + describe('#avg()', () => { + it('sets avg', () => { + query.avg('rank'); + expect(query.terms).to.eql([['$avg', {'field': 'rank'}]]); + }); + }); + + describe('#min()', () => { + it('sets min', () => { + query.min('rating'); + expect(query.terms).to.eql([['$min', {'field': 'rating'}]]); + }); + }); + + describe('#max()', () => { + it('sets max', () => { + query.max('rating'); + expect(query.terms).to.eql([['$max', {'field': 'rating'}]]); + }); + }); + + describe('#between()', () => { + it('sets between', () => { + var params = { + lowerKey: 0, + upperKey: 10, + index: 'rank', + }; + query.between(params); + expect(query.terms).to.eql([['$between', params]]); + }); + }); + + describe('#getIntersecting()', () => { + it('sets get_intersecting', () => { + var point = { + 'coordinates': [-120.34589052200315, 36.12704320788633], + 'type': 'Point' + }; + query.getIntersecting(point, 'location'); + expect(query.terms).to.eql([['$get_intersecting', {index: 'location', geometry: point}]]); + }); + }); + + describe('#getNearest()', () => { + it('sets get_nearest', () => { + var point = { + 'type': 'Point', + 'coordinates': [-120.34589052200315, 36.12704320788633] + }; + query.getNearest(point, 'location'); + expect(query.terms).to.eql([['$get_nearest', {index: 'location', geometry: point}]]); + }); + }); + + describe('#delete()', () => { + it('sets delete', () => { + query.delete('hard', false); + expect(query.terms).to.eql([['$delete', {durability: 'hard', return_changes: false}]]); + }); + }); });