Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

resource-client

Package Overview
Dependencies
Maintainers
2
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

resource-client - npm Package Compare versions

Comparing version 2.1.0 to 2.3.0

lib/request_validator.js

372

lib/index.js
// Generated by CoffeeScript 1.9.3
var Promise, _, defaultActions, request, resourceClient, urlBuilder,
var Promise, _, defaultActions, request, requestValidator, resourceClient, urlBuilder,
slice = [].slice;

@@ -11,2 +11,4 @@

requestValidator = require('./request_validator');
urlBuilder = require('./url_builder');

@@ -16,11 +18,17 @@

module.exports = resourceClient = function(resourceOptions) {
/*
Create resource with default configuration
@param {Object} [resourceConfig] - configuration shared for all actions on this resource
*/
module.exports = resourceClient = function(resourceConfig) {
var Resource, actionConfig, actionName, handleResponse, resourceRequest;
if (resourceOptions.params == null) {
resourceOptions.params = {};
if (resourceConfig.params == null) {
resourceConfig.params = {};
}
if (resourceOptions.json == null) {
resourceOptions.json = true;
if (resourceConfig.json == null) {
resourceConfig.json = true;
}
resourceRequest = request.defaults(resourceOptions);
resourceRequest = request.defaults(resourceConfig);
Resource = (function() {

@@ -38,17 +46,32 @@ function Resource(newObject) {

})();
Resource.action = function(actionName, actionOptions) {
/*
Register an action for the resource
@param {String} actionName - name of action being registered
@param {Object} [actionConfig] - configuration for this particular action
*/
Resource.action = function(actionName, actionConfig) {
var actionRequest, actionUrl, ref;
actionOptions.params = {};
actionUrl = actionOptions.url || resourceOptions.url;
actionRequest = resourceRequest.defaults(actionOptions);
if (actionOptions.method === 'GET' && !actionOptions.isArray) {
if (typeof actionName !== 'string') {
throw new TypeError('actionName must be a string');
}
if ((ref = actionConfig.method) !== 'GET' && ref !== 'POST' && ref !== 'PUT' && ref !== 'DELETE') {
throw new TypeError('actionConfig.method must be GET POST PUT or DELETE');
}
if (actionConfig.params == null) {
actionConfig.params = {};
}
actionUrl = actionConfig.url || resourceConfig.url;
actionRequest = Promise.promisify(resourceRequest.defaults(actionConfig));
if (actionConfig.method === 'GET') {
/*
* get single w/ params (class method).
*
* call w/ `({params}, {requestOptions}, callback)`
* OR `({params}, callback)`
Send a GET request with specified configuration
@param {Object} [params] - url params and query params for this action
@param {Object} [requestOptions] - custom options set for just this request (such as headers)
@param {Function} [callback] - if you don't want to use promises. Can be first second, or third parameter.
@returns {Promise} - resolves to returned resource(s)
*/
return Resource[actionName] = function() {
var done, opts, promise;
var done, opts, requestOptions, requestParams;
opts = 1 <= arguments.length ? slice.call(arguments, 0) : [];

@@ -58,35 +81,45 @@ if (typeof opts[opts.length - 1] === 'function') {

}
promise = new Promise((function(_this) {
return function(resolve, reject) {
var requestOptions, requestParams;
requestParams = opts.shift() || {};
requestOptions = opts.pop() || {};
requestOptions.url = (function() {
var mergedParams;
mergedParams = _.assign({}, resourceOptions.params, actionOptions.params, requestParams);
return urlBuilder.build(actionUrl, mergedParams);
})();
return actionRequest.get(requestOptions, function(err, response) {
return handleResponse({
err: err,
response: response,
resolve: resolve,
reject: reject
});
requestParams = opts.shift() || {};
requestOptions = opts.pop() || {};
requestOptions.url = (function() {
var mergedParams;
mergedParams = _.assign({}, resourceConfig.params, actionConfig.params, requestParams);
return urlBuilder.build(actionUrl, mergedParams);
})();
return Promise["try"]((function(_this) {
return function() {
requestValidator.validateUrlParams({
requestParams: requestParams,
actionConfig: actionConfig,
resourceConfig: resourceConfig,
actionName: actionName
});
requestValidator.validateQueryParams({
requestParams: requestParams,
actionConfig: actionConfig,
resourceConfig: resourceConfig,
actionName: actionName
});
return actionRequest(requestOptions);
};
})(this));
return promise.nodeify(done);
})(this)).spread(function(response) {
return handleResponse({
response: response,
actionConfig: actionConfig,
actionName: actionName
});
}).nodeify(done);
};
} else if (actionOptions.method === 'GET' && actionOptions.isArray) {
} else {
/*
* get multi w/o params (class method).
*
* call w/ `({params}, {requestOptions}, [callback])`
* OR `({params}, [callback])`
* OR `([callback])`
Send a PUT, POST, or DELETE request with specified configuration
@param {Object} [params] - url params and query params for this action
@param {Object} [body] - request body
@param {Object} [requestOptions] - custom options set for just this request (such as headers)
@param {Function} [callback] - if you don't want to use promises. Can be first second, third, or fourth parameter.
@returns {Promise} - resolves to returned resource(s)
*/
return Resource[actionName] = function() {
var done, opts, promise;
Resource[actionName] = function() {
var done, opts, requestBody, requestOptions, requestParams;
opts = 1 <= arguments.length ? slice.call(arguments, 0) : [];

@@ -96,118 +129,139 @@ if (typeof opts[opts.length - 1] === 'function') {

}
promise = new Promise((function(_this) {
return function(resolve, reject) {
var requestOptions, requestParams;
requestParams = opts.shift() || {};
requestOptions = opts.pop() || {};
requestOptions.url = (function() {
var mergedParams;
mergedParams = _.assign({}, resourceOptions.params, actionOptions.params, requestParams);
return urlBuilder.build(actionUrl, mergedParams);
})();
return actionRequest.get(requestOptions, function(err, response) {
return handleResponse({
err: err,
response: response,
resolve: resolve,
reject: reject,
actionOptions: actionOptions
});
requestParams = opts.shift() || {};
requestBody = opts.shift() || {};
requestOptions = opts.pop() || {};
requestOptions.body = requestBody;
requestOptions.url = (function() {
var mergedParams;
mergedParams = _.assign({}, resourceConfig.params, actionConfig.params, requestParams);
return urlBuilder.build(actionUrl, mergedParams, requestOptions.body);
})();
return Promise["try"]((function(_this) {
return function() {
requestValidator.validateUrlParams({
requestParams: requestParams,
actionConfig: actionConfig,
resourceConfig: resourceConfig,
actionName: actionName,
requestBody: requestBody
});
requestValidator.validateQueryParams({
requestParams: requestParams,
actionConfig: actionConfig,
resourceConfig: resourceConfig,
actionName: actionName,
requestBody: requestBody
});
requestValidator.validateRequestBody({
actionConfig: actionConfig,
resourceConfig: resourceConfig,
actionName: actionName,
requestBody: requestBody
});
return actionRequest(requestOptions);
};
})(this));
return promise.nodeify(done);
})(this)).spread((function(_this) {
return function(response) {
return handleResponse({
response: response,
actionConfig: actionConfig,
actionName: actionName
});
};
})(this)).nodeify(done);
};
} else if ((ref = actionOptions.method) === 'PUT' || ref === 'POST' || ref === 'DELETE') {
return (function(methodFn) {
if (methodFn === 'delete') {
methodFn = 'del';
/*
Send a PUT, POST, or DELETE request with specified configuration. Sends the instantiated
object as the body of the request
@param {Object} [params] - url params and query params for this action
@param {Object} [requestOptions] - custom options set for just this request (such as headers)
@param {Function} [callback] - if you don't want to use promises. Can be first second, or third parameter.
@returns {Promise} - resolves to returned resource
*/
return Resource.prototype[actionName] = function() {
var done, i, opts, requestOptions, requestParams;
opts = 2 <= arguments.length ? slice.call(arguments, 0, i = arguments.length - 1) : (i = 0, []), done = arguments[i++];
if (typeof opts[opts.length - 1] === 'function') {
done = opts.pop();
}
/*
* modify single (class method).
*
* call w/ `({params}, body, {requestOptions}, [callback])`
* OR `({params}, body, [callback])`
* OR `({params}, [callback])`
*/
Resource[actionName] = function() {
var done, opts, promise;
opts = 1 <= arguments.length ? slice.call(arguments, 0) : [];
if (typeof opts[opts.length - 1] === 'function') {
done = opts.pop();
}
promise = new Promise((function(_this) {
return function(resolve, reject) {
var requestBody, requestOptions, requestParams;
requestParams = opts.shift() || {};
requestBody = opts.shift() || {};
requestOptions = opts.pop() || {};
requestOptions.body = requestBody;
requestOptions.url = (function() {
var mergedParams;
mergedParams = _.assign({}, resourceOptions.params, actionOptions.params, requestParams);
return urlBuilder.build(actionUrl, mergedParams, requestOptions.body);
})();
return actionRequest[methodFn](requestOptions, function(err, response) {
return handleResponse({
err: err,
response: response,
resolve: resolve,
reject: reject
});
});
};
})(this));
return promise.nodeify(done);
};
/*
* modify single (instance method).
*
* call w/ `({params}, {requestOptions}, [callback])`
* OR `({params}, [callback])`
* OR `([callback])`
*/
return Resource.prototype[actionName] = function() {
var done, i, opts, promise;
opts = 2 <= arguments.length ? slice.call(arguments, 0, i = arguments.length - 1) : (i = 0, []), done = arguments[i++];
if (typeof opts[opts.length - 1] === 'function') {
done = opts.pop();
}
promise = new Promise((function(_this) {
return function(resolve, reject) {
var requestOptions, requestParams;
requestParams = opts.shift() || {};
requestOptions = opts.pop() || {};
requestOptions.body = _this;
requestOptions.url = (function() {
var mergedParams;
mergedParams = _.assign({}, resourceOptions.params, actionOptions.params, requestParams);
return urlBuilder.build(actionUrl, mergedParams, requestOptions.body);
})();
return actionRequest[methodFn](requestOptions, function(err, response) {
return handleResponse({
err: err,
response: response,
originalObject: this,
resolve: resolve,
reject: reject
});
});
};
})(this));
return promise.nodeify(done);
};
})(actionOptions.method.toLowerCase());
requestParams = opts.shift() || {};
requestOptions = opts.pop() || {};
requestOptions.body = this;
requestOptions.url = (function() {
var mergedParams;
mergedParams = _.assign({}, resourceConfig.params, actionConfig.params, requestParams);
return urlBuilder.build(actionUrl, mergedParams, requestOptions.body);
})();
return Promise["try"]((function(_this) {
return function() {
requestValidator.validateUrlParams({
requestParams: requestParams,
actionConfig: actionConfig,
resourceConfig: resourceConfig,
actionName: actionName,
requestBody: _this
});
requestValidator.validateQueryParams({
requestParams: requestParams,
actionConfig: actionConfig,
resourceConfig: resourceConfig,
actionName: actionName,
requestBody: _this
});
requestValidator.validateRequestBody({
actionConfig: actionConfig,
resourceConfig: resourceConfig,
actionName: actionName,
requestBody: _this
});
return actionRequest(requestOptions);
};
})(this)).spread((function(_this) {
return function(response) {
return handleResponse({
response: response,
actionConfig: actionConfig,
resourceConfig: resourceConfig,
actionName: actionName,
originalObject: _this
});
};
})(this)).nodeify(done);
};
}
};
/*
@param {Object} response - request response object
@param {Object} actionConfig
@param {String} actionName
@param {Object} [originalObject] - original resource instance that was saved
- once successful, original instance will be updated in place with the response object
*/
handleResponse = function(arg) {
var actionOptions, err, errorMessage, originalObject, ref, reject, resolve, resource, resources, response;
err = arg.err, response = arg.response, originalObject = arg.originalObject, resolve = arg.resolve, reject = arg.reject, actionOptions = arg.actionOptions;
if (actionOptions == null) {
actionOptions = {};
var actionConfig, actionName, errorMessage, originalObject, ref, resource, resources, response;
response = arg.response, actionConfig = arg.actionConfig, actionName = arg.actionName, originalObject = arg.originalObject;
if (typeof response !== 'object') {
throw new TypeError('response must be an object');
}
if (err) {
return reject(err);
} else if ((200 <= (ref = response.statusCode) && ref < 300)) {
if (typeof actionConfig !== 'object') {
throw new TypeError('actionConfig must be an object');
}
if (typeof actionName !== 'string') {
throw new TypeError('actionName must be a string');
}
if ((originalObject != null) && typeof originalObject !== 'object') {
throw new TypeError('originalObject must be an object');
}
if (actionConfig == null) {
actionConfig = {};
}
if ((200 <= (ref = response.statusCode) && ref < 300)) {
requestValidator.validateResponseBody({
actionConfig: actionConfig,
resourceConfig: resourceConfig,
actionName: actionName,
responseBody: response.body
});
if (Array.isArray(response.body)) {

@@ -217,17 +271,21 @@ resources = response.body.map(function(resource) {

});
if (actionOptions.returnFirst) {
if (actionConfig.returnFirst) {
resources = resources[0];
}
return resolve(resources);
return resources;
} else {
resource = originalObject != null ? _.assign(originalObject, response.body) : new Resource(response.body);
return resolve(resource);
return resource;
}
} else if (response.statusCode === 404) {
return resolve(void 0);
return void 0;
} else {
errorMessage = JSON.stringify(response.body);
return reject(new Error(errorMessage));
throw new Error(errorMessage);
}
};
/*
Add default methods.
*/
for (actionName in defaultActions) {

@@ -234,0 +292,0 @@ actionConfig = defaultActions[actionName];

@@ -9,6 +9,5 @@ // Generated by CoffeeScript 1.9.3

Build url from url template
@param urlTemplate - url that can contain variables such as /products/:_id
@param params - params to populate the url. Will fill url params first, and then
all remaining params will become query params
@param params - params to populate the url.
- Will fill url params first, and then all remaining params will become query params
@param [body] - body object to use for populating params (when params are defined using @, eg. {_id: '@_id'})

@@ -15,0 +14,0 @@ */

{
"name": "resource-client",
"version": "2.1.0",
"version": "2.3.0",
"description": "Easily create api clients for your server side resources.",

@@ -26,2 +26,3 @@ "author": "Good Eggs <open-source@goodeggs.com>",

"bluebird": "^2.9.30",
"goodeggs-json-schema-validator": "^2.0.2",
"lodash": "^3.0.0",

@@ -32,6 +33,7 @@ "request": "2.54.0",

"devDependencies": {
"chai": "^2.1.0",
"chai-as-promised": "^5.1.0",
"coffee-script": ">=1.7.x",
"fibrous": "^0.3.3",
"mocha": "~1.x.x",
"chai": "^2.1.0",
"fibrous": "^0.3.3",
"nock": "^1.6.1"

@@ -38,0 +40,0 @@ },

# Resource Client
Easily create node API clients for your APIs. Inspired by [Angular Resource](https://docs.angularjs.org/api/ngResource/service/$resource).
Easily create node API clients for your APIs. Inspired by [Angular Resource](https://docs.angularjs.org/api/ngResource/service/$resource) and [Angular Validated Resource](https://github.com/goodeggs/angular-validated-resource).

@@ -41,2 +41,26 @@ [![NPM version](http://img.shields.io/npm/v/resource-client.svg?style=flat-square)](https://www.npmjs.org/package/resource-client)

You can also configure the resource to use JSON schema validation for every request:
```javascript
var resourceClient = require('resource-client');
var Product = resourceClient({
url: 'http://www.mysite.com/api/products/:_id',
headers: {
'X-Secret-Token': 'ABCD1234'
}
// recommended that you do not allow unkown properties when testing.
banUnknownProperties: true
});
Product.action('update', {
method: 'PUT'
// will reject or pass error to callback if validation fails for any of the below
urlParamsSchema: require('./product_schemas/update/url_params.json')
queryParamsSchema: require('./product_schemas/update/query_params.json')
requestBodySchema: require('./product_schemas/update/request_body.json')
responseBodySchema: require('./product_schemas/update/response_body.json')
})
```
## Creating a Resource

@@ -43,0 +67,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc