vue-api-query
Advanced tools
Comparing version
@@ -33,8 +33,4 @@ "use strict"; | ||
this.payload = null; | ||
this.fields = { | ||
fields: {} | ||
}; | ||
this.filters = { | ||
filter: {} | ||
}; | ||
this.fields = {}; | ||
this.filters = {}; | ||
this.parser = new _Parser.default(this); | ||
@@ -87,4 +83,4 @@ } // query string parsed | ||
if (fields[0].constructor === String || fields[0].constructor === Array) { | ||
this.fields.fields[this.model.resource()] = fields.join(','); | ||
if (fields[0].constructor === String || Array.isArray(fields[0])) { | ||
this.fields[this.model.resource()] = fields.join(','); | ||
} // related entities .select({ posts: ['title', 'content'], user: ['age', 'firstname']} ) | ||
@@ -99,3 +95,3 @@ | ||
_this.fields.fields[key] = value.join(','); | ||
_this.fields[key] = value.join(','); | ||
}); | ||
@@ -111,3 +107,3 @@ } | ||
if (Array.isArray(value) || value instanceof Object) throw new Error('The VALUE must be primitive on where() method.'); | ||
this.filters.filter[key] = value; | ||
this.filters[key] = value; | ||
return this; | ||
@@ -119,3 +115,3 @@ } | ||
if (!Array.isArray(array)) throw new Error('The second argument on whereIn() method must be an array.'); | ||
this.filters.filter[key] = array.join(','); | ||
this.filters[key] = array.join(','); | ||
return this; | ||
@@ -122,0 +118,0 @@ } |
@@ -83,3 +83,40 @@ "use strict"; | ||
key: "custom", | ||
value: function custom(resource) { | ||
value: function custom() { | ||
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
if (args.length === 0) { | ||
throw new Error('The custom() method takes a minimum of one argument.'); | ||
} // It would be unintuitive for users to manage where the '/' has to be for | ||
// multiple arguments. We don't need it for the first argument if it's | ||
// a string, but subsequent string arguments need the '/' at the beginning. | ||
// We handle this implementation detail here to simplify the readme. | ||
var slash = ''; | ||
var resource = ''; | ||
args.forEach(function (value) { | ||
switch (true) { | ||
case typeof value === 'string': | ||
resource += slash + value.replace(/^\/+/, ''); | ||
break; | ||
case value instanceof Model: | ||
resource += slash + value.resource(); | ||
if (value.isValidId(value.getPrimaryKey())) { | ||
resource += '/' + value.getPrimaryKey(); | ||
} | ||
break; | ||
default: | ||
throw new Error('Arguments to custom() must be strings or instances of Model.'); | ||
} | ||
if (!slash.length) { | ||
slash = '/'; | ||
} | ||
}); | ||
this._customResource = resource; | ||
@@ -112,4 +149,4 @@ return this; | ||
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { | ||
args[_key3] = arguments[_key3]; | ||
} | ||
@@ -171,2 +208,15 @@ | ||
} | ||
}, { | ||
key: "parameterNames", | ||
value: function parameterNames() { | ||
return { | ||
include: 'include', | ||
filter: 'filter', | ||
sort: 'sort', | ||
fields: 'fields', | ||
append: 'append', | ||
page: 'page', | ||
limit: 'limit' | ||
}; | ||
} | ||
/** | ||
@@ -173,0 +223,0 @@ * Query |
@@ -10,2 +10,4 @@ "use strict"; | ||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); | ||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); | ||
@@ -60,3 +62,3 @@ | ||
value: function hasFields() { | ||
return Object.keys(this.builder.fields.fields).length > 0; | ||
return Object.keys(this.builder.fields).length > 0; | ||
} | ||
@@ -66,3 +68,3 @@ }, { | ||
value: function hasFilters() { | ||
return Object.keys(this.builder.filters.filter).length > 0; | ||
return Object.keys(this.builder.filters).length > 0; | ||
} | ||
@@ -94,2 +96,7 @@ }, { | ||
} | ||
}, { | ||
key: "parameterNames", | ||
value: function parameterNames() { | ||
return this.builder.model.parameterNames(); | ||
} | ||
/** | ||
@@ -106,3 +113,3 @@ * Parsers | ||
this.uri += this.prepend() + 'include=' + this.builder.includes; | ||
this.uri += this.prepend() + this.parameterNames().include + '=' + this.builder.includes; | ||
} | ||
@@ -116,3 +123,3 @@ }, { | ||
this.uri += this.prepend() + 'append=' + this.builder.appends; | ||
this.uri += this.prepend() + this.parameterNames().append + '=' + this.builder.appends; | ||
} | ||
@@ -126,3 +133,4 @@ }, { | ||
this.uri += this.prepend() + _qs.default.stringify(this.builder.fields, { | ||
var fields = (0, _defineProperty2.default)({}, this.parameterNames().fields, this.builder.fields); | ||
this.uri += this.prepend() + _qs.default.stringify(fields, { | ||
encode: false | ||
@@ -138,3 +146,4 @@ }); | ||
this.uri += this.prepend() + _qs.default.stringify(this.builder.filters, { | ||
var filters = (0, _defineProperty2.default)({}, this.parameterNames().filter, this.builder.filters); | ||
this.uri += this.prepend() + _qs.default.stringify(filters, { | ||
encode: false | ||
@@ -150,3 +159,3 @@ }); | ||
this.uri += this.prepend() + 'sort=' + this.builder.sorts; | ||
this.uri += this.prepend() + this.parameterNames().sort + '=' + this.builder.sorts; | ||
} | ||
@@ -160,3 +169,3 @@ }, { | ||
this.uri += this.prepend() + 'page=' + this.builder.pageValue; | ||
this.uri += this.prepend() + this.parameterNames().page + '=' + this.builder.pageValue; | ||
} | ||
@@ -170,3 +179,3 @@ }, { | ||
this.uri += this.prepend() + 'limit=' + this.builder.limitValue; | ||
this.uri += this.prepend() + this.parameterNames().limit + '=' + this.builder.limitValue; | ||
} | ||
@@ -173,0 +182,0 @@ }, { |
@@ -91,5 +91,5 @@ "use strict"; | ||
key: "custom", | ||
value: function custom(resource) { | ||
value: function custom() { | ||
var self = this.instance(); | ||
self.custom(resource); | ||
self.custom.apply(self, arguments); | ||
return self; | ||
@@ -96,0 +96,0 @@ } |
{ | ||
"name": "vue-api-query", | ||
"version": "1.3.0", | ||
"version": "1.4.0", | ||
"description": "💎 Elegant and simple way to build requests for REST API", | ||
@@ -5,0 +5,0 @@ "main": "build/index.js", |
@@ -258,2 +258,15 @@ <p align="center"> | ||
The `custom()` method can be called with multiple arguments to build | ||
resource endpoints and hierarchies. Simply supply them in the correct order. | ||
Any combination of strings and models is possible. | ||
```js | ||
let user = new User({ id: 1 }) | ||
let post = new Post() | ||
// GET /users/1/posts/latest | ||
const result = await Post.custom(user, post, 'latest').get() | ||
``` | ||
# Full example | ||
@@ -260,0 +273,0 @@ |
@@ -48,3 +48,36 @@ import Builder from './Builder'; | ||
custom(resource) { | ||
custom(...args) { | ||
if(args.length === 0) { | ||
throw new Error('The custom() method takes a minimum of one argument.') | ||
} | ||
// It would be unintuitive for users to manage where the '/' has to be for | ||
// multiple arguments. We don't need it for the first argument if it's | ||
// a string, but subsequent string arguments need the '/' at the beginning. | ||
// We handle this implementation detail here to simplify the readme. | ||
let slash = ''; | ||
let resource = ''; | ||
args.forEach(value => { | ||
switch(true) { | ||
case (typeof value === 'string'): | ||
resource += slash + value.replace(/^\/+/, ''); | ||
break; | ||
case (value instanceof Model): | ||
resource += slash + value.resource(); | ||
if(value.isValidId(value.getPrimaryKey())) { | ||
resource += '/' + value.getPrimaryKey(); | ||
} | ||
break; | ||
default: | ||
throw new Error('Arguments to custom() must be strings or instances of Model.') | ||
} | ||
if( !slash.length ) { | ||
slash = '/'; | ||
} | ||
}); | ||
this._customResource = resource | ||
@@ -51,0 +84,0 @@ |
@@ -70,5 +70,5 @@ /** | ||
static custom(resource) { | ||
static custom(...args) { | ||
let self = this.instance() | ||
self.custom(resource) | ||
self.custom(...args) | ||
@@ -75,0 +75,0 @@ return self |
@@ -314,2 +314,29 @@ import Post from './dummy/models/Post' | ||
test('custom() gracefully handles accidental / for string arguments', async () => { | ||
axiosMock.onAny().reply((config) => { | ||
expect(config.url).toBe('postz/recent') | ||
return [200, {}] | ||
}) | ||
const post = await Post.custom('/postz', 'recent').first() | ||
}) | ||
test('custom() called with multiple objects/strings gets the correct resource', async () => { | ||
let user | ||
let comment | ||
axiosMock.onAny().reply((config) => { | ||
expect(config.method).toEqual('get') | ||
expect(config.url).toEqual('users/1/postz/comments') | ||
return [200, {}] | ||
}) | ||
user = new User({ id: 1 }) | ||
comment = new Comment() | ||
const result = await Comment.custom(user, 'postz', comment).get() | ||
}) | ||
test('a request from hasMany() method hits right resource', async () => { | ||
@@ -473,2 +500,18 @@ let user | ||
}) | ||
test('it throws a error when a custom() parameter is not a valid Model or a string', () => { | ||
errorModel = () => { | ||
const post = new Post({ text: 'Hello' }).custom() | ||
} | ||
expect(errorModel).toThrow('The custom() method takes a minimum of one argument.') | ||
errorModel = () => { | ||
const user = new User({ name: 'Mary' }) | ||
const post = new Post({ text: 'Hello' }).custom(user, 'a-string', 42) | ||
} | ||
expect(errorModel).toThrow('Arguments to custom() must be strings or instances of Model.') | ||
}) | ||
}) |
241631
1.96%2058
5.27%769
1.72%