From f3129af4dbf85bb9a6be6a539c15255593357a90 Mon Sep 17 00:00:00 2001 From: Jason Dobry Date: Sun, 21 Sep 2014 23:25:52 -0600 Subject: [PATCH] Stable Version 0.3.0. --- CHANGELOG.md | 7 ++- bower.json | 2 +- dist/js-data-http.js | 99 +++++++++++++++++++++------------------- dist/js-data-http.min.js | 4 +- karma.start.js | 6 ++- package.json | 2 +- src/index.js | 97 ++++++++++++++++++++------------------- test/create.spec.js | 16 +------ test/destroy.spec.js | 16 +------ test/destroyAll.spec.js | 16 +------ test/find.spec.js | 24 ++-------- test/findAll.spec.js | 16 +------ test/update.spec.js | 16 +------ test/updateAll.spec.js | 16 +------ 14 files changed, 131 insertions(+), 206 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91f4065..d31c1fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,9 @@ -##### 0.2.0 - 2 September 2014 +##### 0.3.0 - 21 September 2014 + +###### Backwards compatible API changes +- Small re-organization. + +##### 0.2.0 - 21 September 2014 ###### Backwards compatible API changes - Added deserialize and serialize. diff --git a/bower.json b/bower.json index 88fd44b..66944cb 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "js-data-http", "description": "http adapter for js-data.", - "version": "0.2.0", + "version": "0.3.0", "homepage": "http://www.js-data.io/js-data-http", "repository": { "type": "git", diff --git a/dist/js-data-http.js b/dist/js-data-http.js index b90abfb..ddb85c9 100644 --- a/dist/js-data-http.js +++ b/dist/js-data-http.js @@ -1,7 +1,7 @@ /** * @author Jason Dobry * @file js-data-http.js -* @version 0.2.0 - Homepage +* @version 0.3.0 - Homepage * @copyright (c) 2014 Jason Dobry * @license MIT * @@ -1330,17 +1330,9 @@ function DSHttpAdapter(options) { var dsHttpAdapterPrototype = DSHttpAdapter.prototype; -dsHttpAdapterPrototype.HTTP = function (config, resourceConfig) { +dsHttpAdapterPrototype.HTTP = function (config) { var _this = this; var start = new Date().getTime(); - var deserialize; - if (config.deserialize) { - deserialize = config.deserialize; - delete config.deserialize; - } else { - deserialize = _this.defaults.deserialize; - } - resourceConfig = resourceConfig || {}; config = deepMixIn(config, this.defaults.httpConfig); return http(config).then(function (data) { if (_this.defaults.log) { @@ -1348,21 +1340,21 @@ dsHttpAdapterPrototype.HTTP = function (config, resourceConfig) { args.unshift(data.config.method + ' request: ' + data.config.url + ' Time taken: ' + (new Date().getTime() - start) + 'ms'); _this.defaults.log.apply(_this.defaults.log, args); } - return deserialize(resourceConfig.name, data); + return data; }); }; -dsHttpAdapterPrototype.GET = function (url, config, resourceConfig) { +dsHttpAdapterPrototype.GET = function (url, config) { config = config || {}; if (!('method' in config)) { config.method = 'get'; } return this.HTTP(deepMixIn(config, { url: url - }), resourceConfig); + })); }; -dsHttpAdapterPrototype.POST = function (url, attrs, config, resourceConfig) { +dsHttpAdapterPrototype.POST = function (url, attrs, config) { config = config || {}; if (!('method' in config)) { config.method = 'post'; @@ -1370,10 +1362,10 @@ dsHttpAdapterPrototype.POST = function (url, attrs, config, resourceConfig) { return this.HTTP(deepMixIn(config, { url: url, data: attrs - }), resourceConfig); + })); }; -dsHttpAdapterPrototype.PUT = function (url, attrs, config, resourceConfig) { +dsHttpAdapterPrototype.PUT = function (url, attrs, config) { config = config || {}; if (!('method' in config)) { config.method = 'put'; @@ -1381,62 +1373,68 @@ dsHttpAdapterPrototype.PUT = function (url, attrs, config, resourceConfig) { return this.HTTP(deepMixIn(config, { url: url, data: attrs || {} - }), resourceConfig); + })); }; -dsHttpAdapterPrototype.DEL = function (url, config, resourceConfig) { +dsHttpAdapterPrototype.DEL = function (url, config) { config = config || {}; if (!('method' in config)) { config.method = 'delete'; } return this.HTTP(deepMixIn(config, { url: url - }), resourceConfig); + })); }; dsHttpAdapterPrototype.find = function (resourceConfig, id, options) { + var _this = this; options = options || {}; - return this.GET( + return _this.GET( makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.getEndpoint(id, options), id), - options, - resourceConfig - ); + options + ).then(function (data) { + return (options.deserialize ? options.deserialize : _this.defaults.deserialize)(resourceConfig.name, data); + }); }; dsHttpAdapterPrototype.findAll = function (resourceConfig, params, options) { + var _this = this; options = options || {}; options.params = options.params || {}; if (params) { - params = this.defaults.queryTransform(resourceConfig.name, params); + params = _this.defaults.queryTransform(resourceConfig.name, params); deepMixIn(options.params, params); } - return this.GET( + return _this.GET( makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.getEndpoint(null, options)), - options, - resourceConfig - ); + options + ).then(function (data) { + return (options.deserialize ? options.deserialize : _this.defaults.deserialize)(resourceConfig.name, data); + }); }; dsHttpAdapterPrototype.create = function (resourceConfig, attrs, options) { var _this = this; options = options || {}; - return this.POST( + return _this.POST( makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.getEndpoint(attrs, options)), options.serialize ? options.serialize(resourceConfig.name, attrs) : _this.defaults.serialize(resourceConfig.name, attrs), - options, - resourceConfig - ); + options + ).then(function (data) { + return (options.deserialize ? options.deserialize : _this.defaults.deserialize)(resourceConfig.name, data); + }); }; dsHttpAdapterPrototype.update = function (resourceConfig, id, attrs, options) { var _this = this; options = options || {}; - return this.PUT( + return _this.PUT( makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.getEndpoint(id, options), id), options.serialize ? options.serialize(resourceConfig.name, attrs) : _this.defaults.serialize(resourceConfig.name, attrs), - options, - resourceConfig - ); + options + ).then(function (data) { + return (options.deserialize ? options.deserialize : _this.defaults.deserialize)(resourceConfig.name, data); + }); }; dsHttpAdapterPrototype.updateAll = function (resourceConfig, attrs, params, options) { @@ -1444,38 +1442,43 @@ dsHttpAdapterPrototype.updateAll = function (resourceConfig, attrs, params, opti options = options || {}; options.params = options.params || {}; if (params) { - params = this.defaults.queryTransform(resourceConfig.name, params); + params = _this.defaults.queryTransform(resourceConfig.name, params); deepMixIn(options.params, params); } return this.PUT( makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.getEndpoint(null, options)), options.serialize ? options.serialize(resourceConfig.name, attrs) : _this.defaults.serialize(resourceConfig.name, attrs), - options, - resourceConfig - ); + options + ).then(function (data) { + return (options.deserialize ? options.deserialize : _this.defaults.deserialize)(resourceConfig.name, data); + }); }; dsHttpAdapterPrototype.destroy = function (resourceConfig, id, options) { + var _this = this; options = options || {}; - return this.DEL( + return _this.DEL( makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.getEndpoint(id, options), id), - options, - resourceConfig - ); + options + ).then(function (data) { + return (options.deserialize ? options.deserialize : _this.defaults.deserialize)(resourceConfig.name, data); + }); }; dsHttpAdapterPrototype.destroyAll = function (resourceConfig, params, options) { + var _this = this; options = options || {}; options.params = options.params || {}; if (params) { - params = this.defaults.queryTransform(resourceConfig.name, params); + params = _this.defaults.queryTransform(resourceConfig.name, params); deepMixIn(options.params, params); } return this.DEL( makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.getEndpoint(null, options)), - options, - resourceConfig - ); + options + ).then(function (data) { + return (options.deserialize ? options.deserialize : _this.defaults.deserialize)(resourceConfig.name, data); + }); }; module.exports = DSHttpAdapter; diff --git a/dist/js-data-http.min.js b/dist/js-data-http.min.js index 1f3bf20..2a12532 100644 --- a/dist/js-data-http.min.js +++ b/dist/js-data-http.min.js @@ -1,10 +1,10 @@ /** * @author Jason Dobry * @file js-data-http.min.js -* @version 0.2.0 - Homepage +* @version 0.3.0 - Homepage * @copyright (c) 2014 Jason Dobry * @license MIT * * @overview My Adapter. */ -!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;"undefined"!=typeof window?b=window:"undefined"!=typeof global?b=global:"undefined"!=typeof self&&(b=self),b.DSHttpAdapter=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g=200&&m.status<300?a:b)(d),m=null}};var n=h(j.url)?d.read(j.xsrfCookieName||e.xsrfCookieName):void 0;if(n&&(l[j.xsrfHeaderName||e.xsrfHeaderName]=n),i.forEach(l,function(a,b){k||"content-type"!==b.toLowerCase()?m.setRequestHeader(b,a):delete l[b]}),j.withCredentials&&(m.withCredentials=!0),j.responseType)try{m.responseType=j.responseType}catch(o){if("json"!==m.responseType)throw o}m.send(k)}},{"./../buildUrl":4,"./../cookies":5,"./../defaults":6,"./../parseHeaders":7,"./../transformData":9,"./../urlIsSameOrigin":10,"./../utils":11}],3:[function(a,b){(function(c){function d(){h.forEach(arguments,function(a){j[a]=function(b,c){return j(h.merge(c||{},{method:a,url:b}))}})}function e(){h.forEach(arguments,function(a){j[a]=function(b,c,d){return j(h.merge(d||{},{method:a,url:b,data:c}))}})}var f=a("es6-promise").Promise,g=a("./defaults"),h=a("./utils"),i=a("./spread"),j=b.exports=function(b){b=h.merge({method:"get",transformRequest:g.transformRequest,transformResponse:g.transformResponse},b),b.withCredentials=b.withCredentials||g.withCredentials;var d=new f(function(d,e){try{"undefined"!=typeof window?a("./adapters/xhr")(d,e,b):"undefined"!=typeof c&&a("./adapters/http")(d,e,b)}catch(f){e(f)}});return d.success=function(a){return d.then(function(b){a(b.data,b.status,b.headers,b.config)}),d},d.error=function(a){return d.then(null,function(b){a(b.data,b.status,b.headers,b.config)}),d},d};j.defaults=g,j.all=function(a){return f.all(a)},j.spread=i,d("delete","get","head"),e("post","put","patch")}).call(this,a("_process"))},{"./adapters/http":2,"./adapters/xhr":2,"./defaults":6,"./spread":8,"./utils":11,_process:22,"es6-promise":12}],4:[function(a,b){"use strict";function c(a){return encodeURIComponent(a).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+")}var d=a("./utils");b.exports=function(a,b){if(!b)return a;var e=[];return d.forEach(b,function(a,b){null!==a&&"undefined"!=typeof a&&(d.isArray(a)||(a=[a]),d.forEach(a,function(a){d.isDate(a)?a=a.toISOString():d.isObject(a)&&(a=JSON.stringify(a)),e.push(c(b)+"="+c(a))}))}),e.length>0&&(a+=(-1===a.indexOf("?")?"?":"&")+e.join("&")),a}},{"./utils":11}],5:[function(a,b){"use strict";var c=a("./utils");b.exports={write:function(a,b,d,e,f,g){var h=[];h.push(a+"="+encodeURIComponent(b)),c.isNumber(d)&&h.push("expires="+new Date(d).toGMTString()),c.isString(e)&&h.push("path="+e),c.isString(f)&&h.push("domain="+f),g===!0&&h.push("secure"),document.cookie=h.join("; ")},read:function(a){var b=document.cookie.match(new RegExp("(^|;\\s*)("+a+")=([^;]*)"));return b?decodeURIComponent(b[3]):null},remove:function(a){this.write(a,"",Date.now()-864e5)}}},{"./utils":11}],6:[function(a,b){"use strict";var c=a("./utils"),d=/^\s*(\[|\{[^\{])/,e=/[\}\]]\s*$/,f=/^\)\]\}',?\n/,g={"Content-Type":"application/json;charset=utf-8"};b.exports={transformRequest:[function(a){return!c.isObject(a)||c.isFile(a)||c.isBlob(a)?a:JSON.stringify(a)}],transformResponse:[function(a){return"string"==typeof a&&(a=a.replace(f,""),d.test(a)&&e.test(a)&&(a=JSON.parse(a))),a}],headers:{common:{Accept:"application/json, text/plain, */*"},patch:c.merge(g),post:c.merge(g),put:c.merge(g)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN"}},{"./utils":11}],7:[function(a,b){"use strict";var c=a("./utils");b.exports=function(a){var b,d,e,f={};return a?(c.forEach(a.split("\n"),function(a){e=a.indexOf(":"),b=c.trim(a.substr(0,e)).toLowerCase(),d=c.trim(a.substr(e+1)),b&&(f[b]=f[b]?f[b]+", "+d:d)}),f):f}},{"./utils":11}],8:[function(a,b){b.exports=function(a){return function(b){a.apply(null,b)}}},{}],9:[function(a,b){"use strict";var c=a("./utils");b.exports=function(a,b,d){return c.forEach(d,function(c){a=c(a,b)}),a}},{"./utils":11}],10:[function(a,b){"use strict";function c(a){var b=a;return d&&(f.setAttribute("href",b),b=f.href),f.setAttribute("href",b),{href:f.href,protocol:f.protocol?f.protocol.replace(/:$/,""):"",host:f.host,search:f.search?f.search.replace(/^\?/,""):"",hash:f.hash?f.hash.replace(/^#/,""):"",hostname:f.hostname,port:f.port,pathname:"/"===f.pathname.charAt(0)?f.pathname:"/"+f.pathname}}var d=/(msie|trident)/i.test(navigator.userAgent),e=a("./utils"),f=document.createElement("a"),g=c(window.location.href);b.exports=function(a){var b=e.isString(a)?c(a):a;return b.protocol===g.protocol&&b.host===g.host}},{"./utils":11}],11:[function(a,b){function c(a){return"[object Array]"===m.call(a)}function d(a){return"string"==typeof a}function e(a){return"number"==typeof a}function f(a){return null!==a&&"object"==typeof a}function g(a){return"[object Date]"===m.call(a)}function h(a){return"[object File]"===m.call(a)}function i(a){return"[object Blob]"===m.call(a)}function j(a){return a.replace(/^\s*/,"").replace(/\s*$/,"")}function k(a,b){if(null!==a&&"undefined"!=typeof a){var c=a.constructor===Array||"function"==typeof a.callee;if("object"==typeof a||c||(a=[a]),c)for(var d=0,e=a.length;e>d;d++)b.call(null,a[d],d,a);else for(var f in a)a.hasOwnProperty(f)&&b.call(null,a[f],f,a)}}function l(){var a={};return k(arguments,function(b){k(b,function(b,c){a[c]=b})}),a}var m=Object.prototype.toString;b.exports={isArray:c,isString:d,isNumber:e,isObject:f,isDate:g,isFile:h,isBlob:i,forEach:k,merge:l,trim:j}},{}],12:[function(a,b,c){"use strict";var d=a("./promise/promise").Promise,e=a("./promise/polyfill").polyfill;c.Promise=d,c.polyfill=e},{"./promise/polyfill":16,"./promise/promise":17}],13:[function(a,b,c){"use strict";function d(a){var b=this;if(!e(a))throw new TypeError("You must pass an array to all.");return new b(function(b,c){function d(a){return function(b){e(a,b)}}function e(a,c){h[a]=c,0===--i&&b(h)}var g,h=[],i=a.length;0===i&&b([]);for(var j=0;j0)){var d=c.shift();d()}},!0),function(a){c.push(a),window.postMessage("process-tick","*")}}return function(a){setTimeout(a,0)}}(),d.title="browser",d.browser=!0,d.env={},d.argv=[],d.on=c,d.addListener=c,d.once=c,d.off=c,d.removeListener=c,d.removeAllListeners=c,d.emit=c,d.binding=function(){throw new Error("process.binding is not supported")},d.cwd=function(){return"/"},d.chdir=function(){throw new Error("process.chdir is not supported")}},{}],23:[function(a,b){function c(){}function d(a){this.defaults=new c,g(this.defaults,a)}var e;e=!window&&"undefined"!=typeof b&&b.exports?a("js-data"):window.JSData;var f=e.DSUtils.makePath,g=e.DSUtils.deepMixIn,h=a("axios"),i=c.prototype;i.queryTransform=function(a,b){return b},i.httpConfig={},i.log=console?console.log:function(){},i.deserialize=function(a,b){return b&&"data"in b?b.data:b},i.serialize=function(a,b){return b};var j=d.prototype;j.HTTP=function(a,b){var c,d=this,e=(new Date).getTime();return a.deserialize?(c=a.deserialize,delete a.deserialize):c=d.defaults.deserialize,b=b||{},a=g(a,this.defaults.httpConfig),h(a).then(function(a){if(d.defaults.log){var f=Array.prototype.slice.call(arguments);f.unshift(a.config.method+" request: "+a.config.url+" Time taken: "+((new Date).getTime()-e)+"ms"),d.defaults.log.apply(d.defaults.log,f)}return c(b.name,a)})},j.GET=function(a,b,c){return b=b||{},"method"in b||(b.method="get"),this.HTTP(g(b,{url:a}),c)},j.POST=function(a,b,c,d){return c=c||{},"method"in c||(c.method="post"),this.HTTP(g(c,{url:a,data:b}),d)},j.PUT=function(a,b,c,d){return c=c||{},"method"in c||(c.method="put"),this.HTTP(g(c,{url:a,data:b||{}}),d)},j.DEL=function(a,b,c){return b=b||{},"method"in b||(b.method="delete"),this.HTTP(g(b,{url:a}),c)},j.find=function(a,b,c){return c=c||{},this.GET(f(c.baseUrl||a.baseUrl,a.getEndpoint(b,c),b),c,a)},j.findAll=function(a,b,c){return c=c||{},c.params=c.params||{},b&&(b=this.defaults.queryTransform(a.name,b),g(c.params,b)),this.GET(f(c.baseUrl||a.baseUrl,a.getEndpoint(null,c)),c,a)},j.create=function(a,b,c){var d=this;return c=c||{},this.POST(f(c.baseUrl||a.baseUrl,a.getEndpoint(b,c)),c.serialize?c.serialize(a.name,b):d.defaults.serialize(a.name,b),c,a)},j.update=function(a,b,c,d){var e=this;return d=d||{},this.PUT(f(d.baseUrl||a.baseUrl,a.getEndpoint(b,d),b),d.serialize?d.serialize(a.name,c):e.defaults.serialize(a.name,c),d,a)},j.updateAll=function(a,b,c,d){var e=this;return d=d||{},d.params=d.params||{},c&&(c=this.defaults.queryTransform(a.name,c),g(d.params,c)),this.PUT(f(d.baseUrl||a.baseUrl,a.getEndpoint(null,d)),d.serialize?d.serialize(a.name,b):e.defaults.serialize(a.name,b),d,a)},j.destroy=function(a,b,c){return c=c||{},this.DEL(f(c.baseUrl||a.baseUrl,a.getEndpoint(b,c),b),c,a)},j.destroyAll=function(a,b,c){return c=c||{},c.params=c.params||{},b&&(b=this.defaults.queryTransform(a.name,b),g(c.params,b)),this.DEL(f(c.baseUrl||a.baseUrl,a.getEndpoint(null,c)),c,a)},b.exports=d},{axios:1,"js-data":"js-data"}]},{},[23])(23)}); \ No newline at end of file +!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;"undefined"!=typeof window?b=window:"undefined"!=typeof global?b=global:"undefined"!=typeof self&&(b=self),b.DSHttpAdapter=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g=200&&m.status<300?a:b)(d),m=null}};var n=h(j.url)?d.read(j.xsrfCookieName||e.xsrfCookieName):void 0;if(n&&(l[j.xsrfHeaderName||e.xsrfHeaderName]=n),i.forEach(l,function(a,b){k||"content-type"!==b.toLowerCase()?m.setRequestHeader(b,a):delete l[b]}),j.withCredentials&&(m.withCredentials=!0),j.responseType)try{m.responseType=j.responseType}catch(o){if("json"!==m.responseType)throw o}m.send(k)}},{"./../buildUrl":4,"./../cookies":5,"./../defaults":6,"./../parseHeaders":7,"./../transformData":9,"./../urlIsSameOrigin":10,"./../utils":11}],3:[function(a,b){(function(c){function d(){h.forEach(arguments,function(a){j[a]=function(b,c){return j(h.merge(c||{},{method:a,url:b}))}})}function e(){h.forEach(arguments,function(a){j[a]=function(b,c,d){return j(h.merge(d||{},{method:a,url:b,data:c}))}})}var f=a("es6-promise").Promise,g=a("./defaults"),h=a("./utils"),i=a("./spread"),j=b.exports=function(b){b=h.merge({method:"get",transformRequest:g.transformRequest,transformResponse:g.transformResponse},b),b.withCredentials=b.withCredentials||g.withCredentials;var d=new f(function(d,e){try{"undefined"!=typeof window?a("./adapters/xhr")(d,e,b):"undefined"!=typeof c&&a("./adapters/http")(d,e,b)}catch(f){e(f)}});return d.success=function(a){return d.then(function(b){a(b.data,b.status,b.headers,b.config)}),d},d.error=function(a){return d.then(null,function(b){a(b.data,b.status,b.headers,b.config)}),d},d};j.defaults=g,j.all=function(a){return f.all(a)},j.spread=i,d("delete","get","head"),e("post","put","patch")}).call(this,a("_process"))},{"./adapters/http":2,"./adapters/xhr":2,"./defaults":6,"./spread":8,"./utils":11,_process:22,"es6-promise":12}],4:[function(a,b){"use strict";function c(a){return encodeURIComponent(a).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+")}var d=a("./utils");b.exports=function(a,b){if(!b)return a;var e=[];return d.forEach(b,function(a,b){null!==a&&"undefined"!=typeof a&&(d.isArray(a)||(a=[a]),d.forEach(a,function(a){d.isDate(a)?a=a.toISOString():d.isObject(a)&&(a=JSON.stringify(a)),e.push(c(b)+"="+c(a))}))}),e.length>0&&(a+=(-1===a.indexOf("?")?"?":"&")+e.join("&")),a}},{"./utils":11}],5:[function(a,b){"use strict";var c=a("./utils");b.exports={write:function(a,b,d,e,f,g){var h=[];h.push(a+"="+encodeURIComponent(b)),c.isNumber(d)&&h.push("expires="+new Date(d).toGMTString()),c.isString(e)&&h.push("path="+e),c.isString(f)&&h.push("domain="+f),g===!0&&h.push("secure"),document.cookie=h.join("; ")},read:function(a){var b=document.cookie.match(new RegExp("(^|;\\s*)("+a+")=([^;]*)"));return b?decodeURIComponent(b[3]):null},remove:function(a){this.write(a,"",Date.now()-864e5)}}},{"./utils":11}],6:[function(a,b){"use strict";var c=a("./utils"),d=/^\s*(\[|\{[^\{])/,e=/[\}\]]\s*$/,f=/^\)\]\}',?\n/,g={"Content-Type":"application/json;charset=utf-8"};b.exports={transformRequest:[function(a){return!c.isObject(a)||c.isFile(a)||c.isBlob(a)?a:JSON.stringify(a)}],transformResponse:[function(a){return"string"==typeof a&&(a=a.replace(f,""),d.test(a)&&e.test(a)&&(a=JSON.parse(a))),a}],headers:{common:{Accept:"application/json, text/plain, */*"},patch:c.merge(g),post:c.merge(g),put:c.merge(g)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN"}},{"./utils":11}],7:[function(a,b){"use strict";var c=a("./utils");b.exports=function(a){var b,d,e,f={};return a?(c.forEach(a.split("\n"),function(a){e=a.indexOf(":"),b=c.trim(a.substr(0,e)).toLowerCase(),d=c.trim(a.substr(e+1)),b&&(f[b]=f[b]?f[b]+", "+d:d)}),f):f}},{"./utils":11}],8:[function(a,b){b.exports=function(a){return function(b){a.apply(null,b)}}},{}],9:[function(a,b){"use strict";var c=a("./utils");b.exports=function(a,b,d){return c.forEach(d,function(c){a=c(a,b)}),a}},{"./utils":11}],10:[function(a,b){"use strict";function c(a){var b=a;return d&&(f.setAttribute("href",b),b=f.href),f.setAttribute("href",b),{href:f.href,protocol:f.protocol?f.protocol.replace(/:$/,""):"",host:f.host,search:f.search?f.search.replace(/^\?/,""):"",hash:f.hash?f.hash.replace(/^#/,""):"",hostname:f.hostname,port:f.port,pathname:"/"===f.pathname.charAt(0)?f.pathname:"/"+f.pathname}}var d=/(msie|trident)/i.test(navigator.userAgent),e=a("./utils"),f=document.createElement("a"),g=c(window.location.href);b.exports=function(a){var b=e.isString(a)?c(a):a;return b.protocol===g.protocol&&b.host===g.host}},{"./utils":11}],11:[function(a,b){function c(a){return"[object Array]"===m.call(a)}function d(a){return"string"==typeof a}function e(a){return"number"==typeof a}function f(a){return null!==a&&"object"==typeof a}function g(a){return"[object Date]"===m.call(a)}function h(a){return"[object File]"===m.call(a)}function i(a){return"[object Blob]"===m.call(a)}function j(a){return a.replace(/^\s*/,"").replace(/\s*$/,"")}function k(a,b){if(null!==a&&"undefined"!=typeof a){var c=a.constructor===Array||"function"==typeof a.callee;if("object"==typeof a||c||(a=[a]),c)for(var d=0,e=a.length;e>d;d++)b.call(null,a[d],d,a);else for(var f in a)a.hasOwnProperty(f)&&b.call(null,a[f],f,a)}}function l(){var a={};return k(arguments,function(b){k(b,function(b,c){a[c]=b})}),a}var m=Object.prototype.toString;b.exports={isArray:c,isString:d,isNumber:e,isObject:f,isDate:g,isFile:h,isBlob:i,forEach:k,merge:l,trim:j}},{}],12:[function(a,b,c){"use strict";var d=a("./promise/promise").Promise,e=a("./promise/polyfill").polyfill;c.Promise=d,c.polyfill=e},{"./promise/polyfill":16,"./promise/promise":17}],13:[function(a,b,c){"use strict";function d(a){var b=this;if(!e(a))throw new TypeError("You must pass an array to all.");return new b(function(b,c){function d(a){return function(b){e(a,b)}}function e(a,c){h[a]=c,0===--i&&b(h)}var g,h=[],i=a.length;0===i&&b([]);for(var j=0;j0)){var d=c.shift();d()}},!0),function(a){c.push(a),window.postMessage("process-tick","*")}}return function(a){setTimeout(a,0)}}(),d.title="browser",d.browser=!0,d.env={},d.argv=[],d.on=c,d.addListener=c,d.once=c,d.off=c,d.removeListener=c,d.removeAllListeners=c,d.emit=c,d.binding=function(){throw new Error("process.binding is not supported")},d.cwd=function(){return"/"},d.chdir=function(){throw new Error("process.chdir is not supported")}},{}],23:[function(a,b){function c(){}function d(a){this.defaults=new c,g(this.defaults,a)}var e;e=!window&&"undefined"!=typeof b&&b.exports?a("js-data"):window.JSData;var f=e.DSUtils.makePath,g=e.DSUtils.deepMixIn,h=a("axios"),i=c.prototype;i.queryTransform=function(a,b){return b},i.httpConfig={},i.log=console?console.log:function(){},i.deserialize=function(a,b){return b&&"data"in b?b.data:b},i.serialize=function(a,b){return b};var j=d.prototype;j.HTTP=function(a){var b=this,c=(new Date).getTime();return a=g(a,this.defaults.httpConfig),h(a).then(function(a){if(b.defaults.log){var d=Array.prototype.slice.call(arguments);d.unshift(a.config.method+" request: "+a.config.url+" Time taken: "+((new Date).getTime()-c)+"ms"),b.defaults.log.apply(b.defaults.log,d)}return a})},j.GET=function(a,b){return b=b||{},"method"in b||(b.method="get"),this.HTTP(g(b,{url:a}))},j.POST=function(a,b,c){return c=c||{},"method"in c||(c.method="post"),this.HTTP(g(c,{url:a,data:b}))},j.PUT=function(a,b,c){return c=c||{},"method"in c||(c.method="put"),this.HTTP(g(c,{url:a,data:b||{}}))},j.DEL=function(a,b){return b=b||{},"method"in b||(b.method="delete"),this.HTTP(g(b,{url:a}))},j.find=function(a,b,c){var d=this;return c=c||{},d.GET(f(c.baseUrl||a.baseUrl,a.getEndpoint(b,c),b),c).then(function(b){return(c.deserialize?c.deserialize:d.defaults.deserialize)(a.name,b)})},j.findAll=function(a,b,c){var d=this;return c=c||{},c.params=c.params||{},b&&(b=d.defaults.queryTransform(a.name,b),g(c.params,b)),d.GET(f(c.baseUrl||a.baseUrl,a.getEndpoint(null,c)),c).then(function(b){return(c.deserialize?c.deserialize:d.defaults.deserialize)(a.name,b)})},j.create=function(a,b,c){var d=this;return c=c||{},d.POST(f(c.baseUrl||a.baseUrl,a.getEndpoint(b,c)),c.serialize?c.serialize(a.name,b):d.defaults.serialize(a.name,b),c).then(function(b){return(c.deserialize?c.deserialize:d.defaults.deserialize)(a.name,b)})},j.update=function(a,b,c,d){var e=this;return d=d||{},e.PUT(f(d.baseUrl||a.baseUrl,a.getEndpoint(b,d),b),d.serialize?d.serialize(a.name,c):e.defaults.serialize(a.name,c),d).then(function(b){return(d.deserialize?d.deserialize:e.defaults.deserialize)(a.name,b)})},j.updateAll=function(a,b,c,d){var e=this;return d=d||{},d.params=d.params||{},c&&(c=e.defaults.queryTransform(a.name,c),g(d.params,c)),this.PUT(f(d.baseUrl||a.baseUrl,a.getEndpoint(null,d)),d.serialize?d.serialize(a.name,b):e.defaults.serialize(a.name,b),d).then(function(b){return(d.deserialize?d.deserialize:e.defaults.deserialize)(a.name,b)})},j.destroy=function(a,b,c){var d=this;return c=c||{},d.DEL(f(c.baseUrl||a.baseUrl,a.getEndpoint(b,c),b),c).then(function(b){return(c.deserialize?c.deserialize:d.defaults.deserialize)(a.name,b)})},j.destroyAll=function(a,b,c){var d=this;return c=c||{},c.params=c.params||{},b&&(b=d.defaults.queryTransform(a.name,b),g(c.params,b)),this.DEL(f(c.baseUrl||a.baseUrl,a.getEndpoint(null,c)),c).then(function(b){return(c.deserialize?c.deserialize:d.defaults.deserialize)(a.name,b)})},b.exports=d},{axios:1,"js-data":"js-data"}]},{},[23])(23)}); \ No newline at end of file diff --git a/karma.start.js b/karma.start.js index ec19a80..6155ce1 100644 --- a/karma.start.js +++ b/karma.start.js @@ -1,5 +1,5 @@ // Setup global test variables -var dsHttpAdapter, User, datastore, DSUtils, queryTransform, p1, p2, p3, p4, p5; +var dsHttpAdapter, User, Post, datastore, DSUtils, queryTransform, p1, p2, p3, p4, p5; // Helper globals var fail = function (msg) { @@ -49,6 +49,10 @@ beforeEach(function () { datastore = new JSData.DS(); User = datastore.defineResource('user'); + Post = datastore.defineResource({ + name: 'posts', + baseUrl: 'api' + }); dsHttpAdapter = new DSHttpAdapter({ queryTransform: queryTransform }); diff --git a/package.json b/package.json index 8fde7b7..61237ab 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "js-data-http", "description": "http adapter for js-data.", - "version": "0.2.0", + "version": "0.3.0", "homepage": "http://www.js-data.io/js-data-http", "repository": { "type": "git", diff --git a/src/index.js b/src/index.js index 97fba39..4585c94 100644 --- a/src/index.js +++ b/src/index.js @@ -39,17 +39,9 @@ function DSHttpAdapter(options) { var dsHttpAdapterPrototype = DSHttpAdapter.prototype; -dsHttpAdapterPrototype.HTTP = function (config, resourceConfig) { +dsHttpAdapterPrototype.HTTP = function (config) { var _this = this; var start = new Date().getTime(); - var deserialize; - if (config.deserialize) { - deserialize = config.deserialize; - delete config.deserialize; - } else { - deserialize = _this.defaults.deserialize; - } - resourceConfig = resourceConfig || {}; config = deepMixIn(config, this.defaults.httpConfig); return http(config).then(function (data) { if (_this.defaults.log) { @@ -57,21 +49,21 @@ dsHttpAdapterPrototype.HTTP = function (config, resourceConfig) { args.unshift(data.config.method + ' request: ' + data.config.url + ' Time taken: ' + (new Date().getTime() - start) + 'ms'); _this.defaults.log.apply(_this.defaults.log, args); } - return deserialize(resourceConfig.name, data); + return data; }); }; -dsHttpAdapterPrototype.GET = function (url, config, resourceConfig) { +dsHttpAdapterPrototype.GET = function (url, config) { config = config || {}; if (!('method' in config)) { config.method = 'get'; } return this.HTTP(deepMixIn(config, { url: url - }), resourceConfig); + })); }; -dsHttpAdapterPrototype.POST = function (url, attrs, config, resourceConfig) { +dsHttpAdapterPrototype.POST = function (url, attrs, config) { config = config || {}; if (!('method' in config)) { config.method = 'post'; @@ -79,10 +71,10 @@ dsHttpAdapterPrototype.POST = function (url, attrs, config, resourceConfig) { return this.HTTP(deepMixIn(config, { url: url, data: attrs - }), resourceConfig); + })); }; -dsHttpAdapterPrototype.PUT = function (url, attrs, config, resourceConfig) { +dsHttpAdapterPrototype.PUT = function (url, attrs, config) { config = config || {}; if (!('method' in config)) { config.method = 'put'; @@ -90,62 +82,68 @@ dsHttpAdapterPrototype.PUT = function (url, attrs, config, resourceConfig) { return this.HTTP(deepMixIn(config, { url: url, data: attrs || {} - }), resourceConfig); + })); }; -dsHttpAdapterPrototype.DEL = function (url, config, resourceConfig) { +dsHttpAdapterPrototype.DEL = function (url, config) { config = config || {}; if (!('method' in config)) { config.method = 'delete'; } return this.HTTP(deepMixIn(config, { url: url - }), resourceConfig); + })); }; dsHttpAdapterPrototype.find = function (resourceConfig, id, options) { + var _this = this; options = options || {}; - return this.GET( + return _this.GET( makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.getEndpoint(id, options), id), - options, - resourceConfig - ); + options + ).then(function (data) { + return (options.deserialize ? options.deserialize : _this.defaults.deserialize)(resourceConfig.name, data); + }); }; dsHttpAdapterPrototype.findAll = function (resourceConfig, params, options) { + var _this = this; options = options || {}; options.params = options.params || {}; if (params) { - params = this.defaults.queryTransform(resourceConfig.name, params); + params = _this.defaults.queryTransform(resourceConfig.name, params); deepMixIn(options.params, params); } - return this.GET( + return _this.GET( makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.getEndpoint(null, options)), - options, - resourceConfig - ); + options + ).then(function (data) { + return (options.deserialize ? options.deserialize : _this.defaults.deserialize)(resourceConfig.name, data); + }); }; dsHttpAdapterPrototype.create = function (resourceConfig, attrs, options) { var _this = this; options = options || {}; - return this.POST( + return _this.POST( makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.getEndpoint(attrs, options)), options.serialize ? options.serialize(resourceConfig.name, attrs) : _this.defaults.serialize(resourceConfig.name, attrs), - options, - resourceConfig - ); + options + ).then(function (data) { + return (options.deserialize ? options.deserialize : _this.defaults.deserialize)(resourceConfig.name, data); + }); }; dsHttpAdapterPrototype.update = function (resourceConfig, id, attrs, options) { var _this = this; options = options || {}; - return this.PUT( + return _this.PUT( makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.getEndpoint(id, options), id), options.serialize ? options.serialize(resourceConfig.name, attrs) : _this.defaults.serialize(resourceConfig.name, attrs), - options, - resourceConfig - ); + options + ).then(function (data) { + return (options.deserialize ? options.deserialize : _this.defaults.deserialize)(resourceConfig.name, data); + }); }; dsHttpAdapterPrototype.updateAll = function (resourceConfig, attrs, params, options) { @@ -153,38 +151,43 @@ dsHttpAdapterPrototype.updateAll = function (resourceConfig, attrs, params, opti options = options || {}; options.params = options.params || {}; if (params) { - params = this.defaults.queryTransform(resourceConfig.name, params); + params = _this.defaults.queryTransform(resourceConfig.name, params); deepMixIn(options.params, params); } return this.PUT( makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.getEndpoint(null, options)), options.serialize ? options.serialize(resourceConfig.name, attrs) : _this.defaults.serialize(resourceConfig.name, attrs), - options, - resourceConfig - ); + options + ).then(function (data) { + return (options.deserialize ? options.deserialize : _this.defaults.deserialize)(resourceConfig.name, data); + }); }; dsHttpAdapterPrototype.destroy = function (resourceConfig, id, options) { + var _this = this; options = options || {}; - return this.DEL( + return _this.DEL( makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.getEndpoint(id, options), id), - options, - resourceConfig - ); + options + ).then(function (data) { + return (options.deserialize ? options.deserialize : _this.defaults.deserialize)(resourceConfig.name, data); + }); }; dsHttpAdapterPrototype.destroyAll = function (resourceConfig, params, options) { + var _this = this; options = options || {}; options.params = options.params || {}; if (params) { - params = this.defaults.queryTransform(resourceConfig.name, params); + params = _this.defaults.queryTransform(resourceConfig.name, params); deepMixIn(options.params, params); } return this.DEL( makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.getEndpoint(null, options)), - options, - resourceConfig - ); + options + ).then(function (data) { + return (options.deserialize ? options.deserialize : _this.defaults.deserialize)(resourceConfig.name, data); + }); }; module.exports = DSHttpAdapter; diff --git a/test/create.spec.js b/test/create.spec.js index de0a8f3..2f4c721 100644 --- a/test/create.spec.js +++ b/test/create.spec.js @@ -3,22 +3,10 @@ describe('DSHttpAdapter.create(resourceConfig, attrs, options)', function () { it('should make a POST request', function (done) { var _this = this; - dsHttpAdapter.create({ - baseUrl: 'api', - endpoint: 'posts', - getEndpoint: function () { - return 'posts'; - } - }, { author: 'John', age: 30 }).then(function (data) { + dsHttpAdapter.create(Post, { author: 'John', age: 30 }).then(function (data) { assert.deepEqual(data, p1, 'post should have been created'); - dsHttpAdapter.create({ - baseUrl: 'api', - endpoint: 'posts', - getEndpoint: function () { - return 'posts'; - } - }, { author: 'John', age: 30 }, { baseUrl: 'api2' }).then(function (data) { + dsHttpAdapter.create(Post, { author: 'John', age: 30 }, { baseUrl: 'api2' }).then(function (data) { assert.deepEqual(data, p1, 'post should have been created'); assert.equal(queryTransform.callCount, 0, 'queryTransform should not have been called'); diff --git a/test/destroy.spec.js b/test/destroy.spec.js index 5647df3..a40496b 100644 --- a/test/destroy.spec.js +++ b/test/destroy.spec.js @@ -3,22 +3,10 @@ describe('DSHttpAdapter.destroy(resourceConfig, id, options)', function () { it('should make a DELETE request', function (done) { var _this = this; - dsHttpAdapter.destroy({ - baseUrl: 'api', - endpoint: 'posts', - getEndpoint: function () { - return 'posts'; - } - }, 1).then(function (data) { + dsHttpAdapter.destroy(Post, 1).then(function (data) { assert.deepEqual(data, '1', 'post should have been deleted'); - dsHttpAdapter.destroy({ - baseUrl: 'api', - endpoint: 'posts', - getEndpoint: function () { - return 'posts'; - } - }, 1, { baseUrl: 'api2' }).then(function (data) { + dsHttpAdapter.destroy(Post, 1, { baseUrl: 'api2' }).then(function (data) { assert.deepEqual(data, '1', 'post should have been deleted'); assert.equal(queryTransform.callCount, 0, 'queryTransform should not have been called'); done(); diff --git a/test/destroyAll.spec.js b/test/destroyAll.spec.js index 95f3ff8..fb7a10a 100644 --- a/test/destroyAll.spec.js +++ b/test/destroyAll.spec.js @@ -3,22 +3,10 @@ describe('DSHttpAdapter.destroyAll(resourceConfig, params, options)', function ( it('should make a DELETE request', function (done) { var _this = this; - dsHttpAdapter.destroyAll({ - baseUrl: 'api', - endpoint: 'posts', - getEndpoint: function () { - return 'posts'; - } - }, {}).then(function (data) { + dsHttpAdapter.destroyAll(Post, {}).then(function (data) { assert.equal('', data, 'posts should have been found'); - dsHttpAdapter.destroyAll({ - baseUrl: 'api', - endpoint: 'posts', - getEndpoint: function () { - return 'posts'; - } - }, { + dsHttpAdapter.destroyAll(Post, { where: { author: { '==': 'John' diff --git a/test/find.spec.js b/test/find.spec.js index d8ab060..5482b26 100644 --- a/test/find.spec.js +++ b/test/find.spec.js @@ -3,22 +3,10 @@ describe('DSHttpAdapter.find(resourceConfig, id, options)', function () { it('should make a GET request', function (done) { var _this = this; - dsHttpAdapter.find({ - baseUrl: 'api', - endpoint: 'posts', - getEndpoint: function () { - return 'posts'; - } - }, 1).then(function (data) { + dsHttpAdapter.find(Post, 1).then(function (data) { assert.deepEqual(data, p1, 'post should have been found'); - dsHttpAdapter.find({ - baseUrl: 'api', - endpoint: 'posts', - getEndpoint: function () { - return 'posts'; - } - }, 1, { baseUrl: 'api2' }).then(function (data) { + dsHttpAdapter.find(Post, 1, { baseUrl: 'api2' }).then(function (data) { assert.deepEqual(data, p1, 'post should have been found'); assert.equal(queryTransform.callCount, 0, 'queryTransform should not have been called'); done(); @@ -52,13 +40,7 @@ describe('DSHttpAdapter.find(resourceConfig, id, options)', function () { dsHttpAdapter.defaults.httpConfig.params = { test: 'test' }; dsHttpAdapter.defaults.httpConfig.headers = { Authorization: 'test' }; - dsHttpAdapter.find({ - baseUrl: 'api', - endpoint: 'posts', - getEndpoint: function () { - return 'posts'; - } - }, 1).then(function (data) { + dsHttpAdapter.find(Post, 1).then(function (data) { assert.deepEqual(data, p1, 'post should have been found'); delete dsHttpAdapter.defaults.httpConfig.params; diff --git a/test/findAll.spec.js b/test/findAll.spec.js index a201ed3..f192dd2 100644 --- a/test/findAll.spec.js +++ b/test/findAll.spec.js @@ -3,22 +3,10 @@ describe('dsHttpAdapter.findAll(resourceConfig, params, options)', function () { it('should make a GET request', function (done) { var _this = this; - dsHttpAdapter.findAll({ - baseUrl: 'api', - endpoint: 'posts', - getEndpoint: function () { - return 'posts'; - } - }, {}).then(function (data) { + dsHttpAdapter.findAll(Post, {}).then(function (data) { assert.deepEqual(data, [p1], 'posts should have been found'); - dsHttpAdapter.findAll({ - baseUrl: 'api', - endpoint: 'posts', - getEndpoint: function () { - return 'posts'; - } - }, { + dsHttpAdapter.findAll(Post, { where: { author: { '==': 'John' diff --git a/test/update.spec.js b/test/update.spec.js index 66d745d..f62bb60 100644 --- a/test/update.spec.js +++ b/test/update.spec.js @@ -3,22 +3,10 @@ describe('DSHttpAdapter.update(resourceConfig, id, attrs, options)', function () it('should make a PUT request', function (done) { var _this = this; - dsHttpAdapter.update({ - baseUrl: 'api', - endpoint: 'posts', - getEndpoint: function () { - return 'posts'; - } - }, 1, { author: 'John', age: 30 }).then(function (data) { + dsHttpAdapter.update(Post, 1, { author: 'John', age: 30 }).then(function (data) { assert.deepEqual(data, p1, 'post 5 should have been updated'); - dsHttpAdapter.update({ - baseUrl: 'api', - endpoint: 'posts', - getEndpoint: function () { - return 'posts'; - } - }, 1, { author: 'John', age: 30 }, { baseUrl: 'api2' }).then(function (data) { + dsHttpAdapter.update(Post, 1, { author: 'John', age: 30 }, { baseUrl: 'api2' }).then(function (data) { assert.deepEqual(data, p1, 'post 5 should have been updated'); assert.equal(queryTransform.callCount, 0, 'queryTransform should not have been called'); done(); diff --git a/test/updateAll.spec.js b/test/updateAll.spec.js index 00cfa61..c31f0e5 100644 --- a/test/updateAll.spec.js +++ b/test/updateAll.spec.js @@ -3,22 +3,10 @@ describe('DSHttpAdapter.updateAll(resourceConfig, attrs, params, options)', func it('should make a PUT request', function (done) { var _this = this; - dsHttpAdapter.updateAll({ - baseUrl: 'api', - endpoint: 'posts', - getEndpoint: function () { - return 'posts'; - } - }, { author: 'John', age: 30 }).then(function (data) { + dsHttpAdapter.updateAll(Post, { author: 'John', age: 30 }).then(function (data) { assert.deepEqual(data, [p1], 'posts should have been updated'); - dsHttpAdapter.updateAll({ - baseUrl: 'api', - endpoint: 'posts', - getEndpoint: function () { - return 'posts'; - } - }, { author: 'John', age: 30 }, { + dsHttpAdapter.updateAll(Post, { author: 'John', age: 30 }, { where: { author: { '==': 'John'