UNPKG

ghunti-devour-client

Version:

A lightweight, framework agnostic, flexible JSON API client

427 lines (388 loc) 14.1 kB
'use strict'; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var axios = require('axios'); var pluralize = require('pluralize'); var _ = require('lodash'); var Promise = require('es6-promise').Promise; var deserialize = require('./middleware/json-api/_deserialize'); var serialize = require('./middleware/json-api/_serialize'); var Minilog = require('minilog'); /* * == JsonApiMiddleware * * Here we construct the middleware stack that will handle building and making * requests, as well as serializing and deserializing our payloads. Users can * easily construct their own middleware layers that adhere to different * standards. * */ var jsonApiHttpBasicAuthMiddleware = require('./middleware/json-api/req-http-basic-auth'); var jsonApiPostMiddleware = require('./middleware/json-api/req-post'); var jsonApiPatchMiddleware = require('./middleware/json-api/req-patch'); var jsonApiDeleteMiddleware = require('./middleware/json-api/req-delete'); var jsonApiGetMiddleware = require('./middleware/json-api/req-get'); var jsonApiHeadersMiddleware = require('./middleware/json-api/req-headers'); var railsParamsSerializer = require('./middleware/json-api/rails-params-serializer'); var sendRequestMiddleware = require('./middleware/request'); var deserializeResponseMiddleware = require('./middleware/json-api/res-deserialize'); var processErrors = require('./middleware/json-api/res-errors'); var jsonApiMiddleware = [jsonApiHttpBasicAuthMiddleware, jsonApiPostMiddleware, jsonApiPatchMiddleware, jsonApiDeleteMiddleware, jsonApiGetMiddleware, jsonApiHeadersMiddleware, railsParamsSerializer, sendRequestMiddleware, processErrors, deserializeResponseMiddleware]; var JsonApi = function () { function JsonApi() { var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; _classCallCheck(this, JsonApi); if (!(arguments.length === 2 && _.isString(arguments[0]) && _.isArray(arguments[1])) && !(arguments.length === 1 && (_.isPlainObject(arguments[0]) || _.isString(arguments[0])))) { throw new Error('Invalid argument, initialize Devour with an object.'); } var defaults = { middleware: jsonApiMiddleware, logger: true, resetBuilderOnCall: true, auth: {} }; var deprecatedConstructos = function deprecatedConstructos(args) { return args.length === 2 || args.length === 1 && _.isString(args[0]); }; if (deprecatedConstructos(arguments)) { defaults.apiUrl = arguments[0]; if (arguments.length === 2) { defaults.middleware = arguments[1]; } } options = _.assign(defaults, options); var middleware = options.middleware; this._originalMiddleware = middleware.slice(0); this.middleware = middleware.slice(0); this.headers = {}; this.axios = axios; this.auth = options.auth; this.apiUrl = options.apiUrl; this.models = {}; this.deserialize = deserialize; this.serialize = serialize; this.builderStack = []; this.resetBuilderOnCall = !!options.resetBuilderOnCall; this.logger = Minilog('devour'); options.logger ? Minilog.enable() : Minilog.disable(); if (deprecatedConstructos(arguments)) { this.logger.warn('Constructor (apiUrl, middleware) has been deprecated, initialize Devour with an object.'); } } _createClass(JsonApi, [{ key: 'enableLogging', value: function enableLogging() { var enabled = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0]; enabled ? Minilog.enable() : Minilog.disable(); } }, { key: 'one', value: function one(model, id) { this.builderStack.push({ model: model, id: id, path: this.resourcePathFor(model, id) }); return this; } }, { key: 'all', value: function all(model) { this.builderStack.push({ model: model, path: this.collectionPathFor(model) }); return this; } }, { key: 'resetBuilder', value: function resetBuilder() { this.builderStack = []; } }, { key: 'buildPath', value: function buildPath() { return _.map(this.builderStack, 'path').join('/'); } }, { key: 'buildUrl', value: function buildUrl() { return this.apiUrl + '/' + this.buildPath(); } }, { key: 'get', value: function get() { var params = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; var req = { method: 'GET', url: this.urlFor(), data: {}, params: params }; if (this.resetBuilderOnCall) { this.resetBuilder(); } return this.runMiddleware(req); } }, { key: 'post', value: function post(payload) { var params = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; var lastRequest = _.chain(this.builderStack).last(); var req = { method: 'POST', url: this.urlFor(), model: lastRequest.get('model').value(), data: payload, params: params }; if (this.resetBuilderOnCall) { this.resetBuilder(); } return this.runMiddleware(req); } }, { key: 'patch', value: function patch(payload) { var params = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; var lastRequest = _.chain(this.builderStack).last(); var req = { method: 'PATCH', url: this.urlFor(), model: lastRequest.get('model').value(), data: payload, params: params }; if (this.resetBuilderOnCall) { this.resetBuilder(); } return this.runMiddleware(req); } }, { key: 'destroy', value: function destroy() { if (arguments.length === 2) { var req = { method: 'DELETE', url: this.urlFor({ model: arguments[0], id: arguments[1] }), model: arguments[0], data: {} }; return this.runMiddleware(req); } else { var lastRequest = _.chain(this.builderStack).last(); var _req = { method: 'DELETE', url: this.urlFor(), model: lastRequest.get('model').value(), data: arguments[0] || {} }; if (this.resetBuilderOnCall) { this.resetBuilder(); } return this.runMiddleware(_req); } } }, { key: 'insertMiddlewareBefore', value: function insertMiddlewareBefore(middlewareName, newMiddleware) { this.insertMiddleware(middlewareName, 'before', newMiddleware); } }, { key: 'insertMiddlewareAfter', value: function insertMiddlewareAfter(middlewareName, newMiddleware) { this.insertMiddleware(middlewareName, 'after', newMiddleware); } }, { key: 'insertMiddleware', value: function insertMiddleware(middlewareName, direction, newMiddleware) { var middleware = this.middleware.filter(function (middleware) { return middleware.name === middlewareName; }); if (middleware.length > 0) { var index = this.middleware.indexOf(middleware[0]); if (direction === 'after') { index = index + 1; } this.middleware.splice(index, 0, newMiddleware); } } }, { key: 'replaceMiddleware', value: function replaceMiddleware(middlewareName, newMiddleware) { var index = _.findIndex(this.middleware, ['name', middlewareName]); this.middleware[index] = newMiddleware; } }, { key: 'define', value: function define(modelName, attributes) { var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; this.models[modelName] = { attributes: attributes, options: options }; } }, { key: 'resetMiddleware', value: function resetMiddleware() { this.middleware = this._originalMiddleware.slice(0); } }, { key: 'applyRequestMiddleware', value: function applyRequestMiddleware(promise) { var requestMiddlewares = this.middleware.filter(function (middleware) { return middleware.req; }); requestMiddlewares.forEach(function (middleware) { promise = promise.then(middleware.req); }); return promise; } }, { key: 'applyResponseMiddleware', value: function applyResponseMiddleware(promise) { var responseMiddleware = this.middleware.filter(function (middleware) { return middleware.res; }); responseMiddleware.forEach(function (middleware) { promise = promise.then(middleware.res); }); return promise; } }, { key: 'applyErrorMiddleware', value: function applyErrorMiddleware(promise) { var errorsMiddleware = this.middleware.filter(function (middleware) { return middleware.error; }); errorsMiddleware.forEach(function (middleware) { promise = promise.then(middleware.error); }); return promise; } }, { key: 'runMiddleware', value: function runMiddleware(req) { var _this = this; var payload = { req: req, jsonApi: this }; var requestPromise = Promise.resolve(payload); requestPromise = this.applyRequestMiddleware(requestPromise); return requestPromise.then(function (res) { payload.res = res; var responsePromise = Promise.resolve(payload); return _this.applyResponseMiddleware(responsePromise); }).catch(function (err) { _this.logger.error(err); var errorPromise = Promise.resolve(err); return _this.applyErrorMiddleware(errorPromise).then(function (err) { return Promise.reject(err); }); }); } }, { key: 'request', value: function request(url) { var method = arguments.length <= 1 || arguments[1] === undefined ? 'GET' : arguments[1]; var params = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; var data = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3]; var req = { url: url, method: method, params: params, data: data }; return this.runMiddleware(req); } }, { key: 'find', value: function find(modelName, id) { var params = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; var req = { method: 'GET', url: this.urlFor({ model: modelName, id: id }), model: modelName, data: {}, params: params }; return this.runMiddleware(req); } }, { key: 'findAll', value: function findAll(modelName) { var params = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; var req = { method: 'GET', url: this.urlFor({ model: modelName }), model: modelName, params: params, data: {} }; return this.runMiddleware(req); } }, { key: 'create', value: function create(modelName, payload) { var req = { method: 'POST', url: this.urlFor({ model: modelName }), model: modelName, data: payload }; return this.runMiddleware(req); } }, { key: 'update', value: function update(modelName, payload) { var req = { method: 'PATCH', url: this.urlFor({ model: modelName, id: payload.id }), model: modelName, data: payload }; return this.runMiddleware(req); } }, { key: 'modelFor', value: function modelFor(modelName) { return this.models[modelName]; } }, { key: 'collectionPathFor', value: function collectionPathFor(modelName) { var collectionPath = _.get(this.models[modelName], 'options.collectionPath') || pluralize(modelName); return '' + collectionPath; } }, { key: 'resourcePathFor', value: function resourcePathFor(modelName, id) { var collectionPath = this.collectionPathFor(modelName); return collectionPath + '/' + encodeURIComponent(id); } }, { key: 'collectionUrlFor', value: function collectionUrlFor(modelName) { var collectionPath = this.collectionPathFor(modelName); return this.apiUrl + '/' + collectionPath; } }, { key: 'resourceUrlFor', value: function resourceUrlFor(modelName, id) { var resourcePath = this.resourcePathFor(modelName, id); return this.apiUrl + '/' + resourcePath; } }, { key: 'urlFor', value: function urlFor() { var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; if (!_.isUndefined(options.model) && !_.isUndefined(options.id)) { return this.resourceUrlFor(options.model, options.id); } else if (!_.isUndefined(options.model)) { return this.collectionUrlFor(options.model); } else { return this.buildUrl(); } } }, { key: 'pathFor', value: function pathFor() { var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; if (!_.isUndefined(options.model) && !_.isUndefined(options.id)) { return this.resourcePathFor(options.model, options.id); } else if (!_.isUndefined(options.model)) { return this.collectionPathFor(options.model); } else { return this.buildPath(); } } }]); return JsonApi; }(); module.exports = JsonApi;