Skip to content

Commit

Permalink
Merge pull request #55 from jpodwys/next
Browse files Browse the repository at this point in the history
2.0.0 -- superagent 2 and 3 compatibility
  • Loading branch information
Joe Podwys authored May 15, 2017
2 parents bc96ad2 + 348a1ab commit 7336b18
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 134 deletions.
79 changes: 33 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

Superagent with flexible built-in caching.

> Note: superagent-cache is a global patch for superagent. If you prefer the same built-in caching as a superagent plugin, see [superagent-cache-plugin](https://github.com/jpodwys/superagent-cache-plugin).
Now compatible with superagent `2.x` and `3.x`.

Currently tested against superagent `1.x`.
> Note: superagent-cache is a global patch for superagent. If you prefer the same built-in caching as a superagent plugin, see [superagent-cache-plugin](https://github.com/jpodwys/superagent-cache-plugin).
Upgrading from an older version or seeing a bug? Please see the [Breaking Change History](#breaking-change-history) section.

Expand All @@ -30,7 +30,8 @@ Upgrading from an older version or seeing a bug? Please see the [Breaking Change

Require and instantiate superagent-cache as follows to get the [default configuration](#what-does-the-default-configuration-give-me):
```javascript
var superagent = require('superagent-cache')();
var superagent = require('superagent');
require('superagent-cache')(superagent);
```
Now you're ready for the magic! All of your existing `GET` and `HEAD` requests will be cached with no extra bloat in your queries! Any matching `DELETE`, `POST`, `PUT`, or `PATCH` requests will automatically invalidate the associated cache key and value.
```javascript
Expand Down Expand Up @@ -91,11 +92,11 @@ By default, `superagent-cache` stores data in a bundled instance of [cacheModule

# What Does the Default Configuration Give Me?

You get the 'default configuration' when you don't provide any params to the `require('superagent-cache')()` command. This will return a fresh instance of `superagent` and bundle an instance of [cacheModule](https://github.com/jpodwys/cache-service-cache-module) for storing data. `cacheModule` is a slim, in-memory cache.
You get the 'default configuration' when you only provide a superagent instance to the `require('superagent-cache')()` command. This will patch the passed instance of `superagent` and bundle an instance of [cacheModule](https://github.com/jpodwys/cache-service-cache-module) for storing data. `cacheModule` is a slim, in-memory cache.

# How Do I Use a Custom Configuration?

To use a custom configuraiton, take advantage of the the three optional params you can hand to `superagent-cache`'s [`require` command](#user-content-requiresuperagent-cachesuperagent-cache) (`superagent`, `cache`, and `defaults`) as follows:
To use a custom configuraiton, take advantage of the the two optional params you can hand to `superagent-cache`'s [`require` command](#user-content-requiresuperagent-cachesuperagent-cache) (`cache`, and `defaults`) as follows:

```javascript
//Require superagent and the cache module I want
Expand All @@ -108,7 +109,7 @@ var defaults = {cacheWhenEmpty: false, expiration: 900};
require('superagent-cache')(superagent, redisCache, defaults);
```

This example allows you to provide your own instance of `superagent` to be patched as well as allowing you to pass in your own, pre-instantiated cache and some defaults for superagent-cache to use with all queries. Here's a list of [supported caches](#supported-caches).
This example patches your instance of `superagent` as allowing you to pass in your own, pre-instantiated cache and some defaults for superagent-cache to use with all queries. Here's a list of [supported caches](#supported-caches).

The `cache` param can be either a pre-instantiated cache module, or a [`cacheModuleConfig` object](https://github.com/jpodwys/cache-service-cache-module#cache-module-configuration-options) to be used with superagent-cache's bundled [`cacheModule`](https://github.com/jpodwys/cache-service-cache-module) instance.

Expand All @@ -122,8 +123,8 @@ All options that can be passed to the `defaults` `require` param can be overwrit

* responseProp
* prune
* pruneParams
* pruneOptions
* pruneQuery
* pruneHeader
* expiration
* cacheWhenEmpty
* doQuery
Expand Down Expand Up @@ -169,26 +170,6 @@ Same as superagent except that superagent's response object will be cached.

Same as superagent except that the generated cache key will be automatically invalidated when these `HTTP` verbs are used.

## .then(resolve, reject)

In its [`1.3.0` release](https://github.com/visionmedia/superagent/releases/tag/v1.3.0), superagent added fake promise support in the form of a `.then()` chainable that accepts two functions. Before superagent `2.x`, this function does not return a real promise. Rather, it calls `.end()` internally and then decides which function (`resolve` or `reject`) to call. (superagent-cache does not yet support superagent `2.x`.)

> Should work with [`superagent-promise`](https://github.com/lightsofapollo/superagent-promise), [`superagent-bluebird-promise`](https://github.com/KyleAMathews/superagent-bluebird-promise), and [`superagent-promise-plugin`](https://github.com/jomaxx/superagent-promise-plugin) (perhaps others as well).
I've overwritten superagent's `.then()` so that the provided `resolve` function accepts the generate cache key as follows:

```javascript
superagent
.get(uri)
.then(function (response, key){
// handle response--key is available if desired
}, function (err){
// handle the error
}
);

```

## .end(callback ([err,] response [, key]))

Same as superagent except it optionally exposes the key superagent-cache generates as the third param in the callback's argument list. See the [usage example](#end-callback-argument-list-options) for a more detailed explanation.
Expand Down Expand Up @@ -245,9 +226,9 @@ superagent
);
```

## .pruneParams(params)
## .pruneQuery(params)

In the event that you need certain query params to execute a query but cannot have those params as part of your cache key (useful when security or time-related params are sent), use `.pruneParams()` to remove those properties. Pass `.pruneParams()` an array containing the param keys you want omitted from the cache key.
In the event that you need certain query params to execute a query but cannot have those params as part of your cache key (useful when security or time-related params are sent), use `.pruneQuery()` to remove those properties. Pass `.pruneQuery()` an array containing the param keys you want omitted from the cache key.

#### Arguments

Expand All @@ -261,16 +242,16 @@ In the event that you need certain query params to execute a query but cannot ha
superagent
.get(uri)
.query(query)
.pruneParams(['token'])
.pruneQuery(['token'])
.end(function (error, response){
// handle response
}
);
```

## .pruneOptions(options)
## .pruneHeader(options)

This function works just like the `.pruneParams()` funciton except that it modifies the arguments passed to the `.set()` chainable method (headers) rather than those passed to the `.query()` chainable method.
This function works just like the `.pruneQuery()` funciton except that it modifies the arguments passed to the `.set()` chainable method (headers) rather than those passed to the `.query()` chainable method.

#### Arguments

Expand All @@ -284,7 +265,7 @@ This function works just like the `.pruneParams()` funciton except that it modif
superagent
.get(uri)
.set(options)
.pruneOptions(['token'])
.pruneHeader(['token'])
.end(function (error, response){
// handle response
}
Expand Down Expand Up @@ -345,7 +326,7 @@ Tell the underlying `cache` provided in the `require` command to enable backgrou

* value: boolean || function || undefined, default: true

## ._end(callback (err, response))
## ._superagentCache_originalEnd(callback (err, response))

This is a convenience method that allows you to skip all caching logic and use superagent as normal.

Expand Down Expand Up @@ -469,12 +450,7 @@ However, you can only get it when you pass 3 params to the callback's argument l

## Various ways of requiring superagent-cache

#### When no params are passed

```javascript
//...it will return a patched superagent instance and create a cache-service instance with the default configuration
var superagent = require('superagent-cache')();
```
> NOTE: You must pass your own superagent instance or superagent-cache will throw an error.
#### When only `superagent` is passed

Expand All @@ -484,23 +460,25 @@ var superagent = require('superagent');
require('superagent-cache')(superagent)
```

#### When only `cache` is passed
#### When `superagent` and `cache` are passed

> Example 1
```javascript
//...it will return a patched superagent instance and consume cache as its data store
//...it will patched the provided superagent instance and consume cache as its data store
var superagent = require('superagent');
var redisModule = require('cache-service-redis');
var redisCache = new redisModule({redisEnv: 'REDISCLOUD_URL'});
var superagent = require('superagent-cache')(null, redisCache);
var superagent = require('superagent-cache')(superagent, redisCache);
```

> Example 2
```javascript
//...it will return a patched superagent instance and consume cache as its cacheModuleConfig for use with the bundled instance of cacheModule
//...it will patched the provided superagent instance and consume cache as its cacheModuleConfig for use with the bundled instance of cacheModule
var superagent = require('superagent');
var cacheModuleConfig = {storage: 'session', defaultExpiration: 60};
var superagent = require('superagent-cache')(null, cacheModuleConfig);
var superagent = require('superagent-cache')(superagent, cacheModuleConfig);
```

#### With `defaults`
Expand All @@ -509,6 +487,15 @@ The `defaults` object can be passed as the third param at any time. It does not

# Breaking Change History

#### 2.0.0

* Now compatible with superagent `2.x` and `3.x`
* Because superagent-cache is now compatible with superagent 1, 2, and 3, it does not bundle an instance of superagent. As a result, you must always provide your own instance to be patched.
* `._end` is now `._superagentCache_originalEnd` to prevent future naming colisions
* `.pruneParams` is now `.pruneQuery` for clarity
* `.pruneOptions` is now `.pruneHeader` for clarity
* The `resolve` function passed to `.then` no longer exposes the generated cache key like it did when using superagent `^1.3.0` with superagent-cache `^1.5.0` (but using `.end` still does)

#### 1.3.5

In superagent `1.7.0`, the superagent team introduced some internal changes to how they handle headers. As a result, you must use superagent-cache `1.3.5` or later to be compatible with superagent `1.7.0` or later. All versions of superagent-cache (to this point) should be backwards compatible with all versions of superagent going back to at least version `1.1.0`. To be clear, this was no one's fault. However, I have reached out to the superagent team to see what I can do to help minimize internally breaking changes in the future.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"name": "superagent-cache",
"version": "1.7.2",
"version": "2.0.0",
"description": "Superagent with flexible built-in caching.",
"main": "superagentCache.js",
"dependencies": {
"superagent": "1.7.2",
"cache-service-cache-module": "1.x"
},
"devDependencies": {
"superagent": "3.x",
"es6-promise": "3.0.2",
"expect": "1.6.0",
"express": "3.4.3",
Expand Down
51 changes: 17 additions & 34 deletions superagentCache.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ var utils = require('./utils');
/**
* superagentCache constructor
* @constructor
* @param {superagent} agent (optional)
* @param {superagent} superagent
* @param {cache module} cache (optional)
* @param {object} defaults (optional)
*/
module.exports = function(agent, cache, defaults){
module.exports = function(superagent, cache, defaults){

var superagent = (agent) ? agent : require('superagent');
if(!superagent) throw 'superagent-cache requires a superagent instance.';

if(!superagent.patchedBySuperagentCache){
superagent.cache = (cache && cache.get) ? cache : new (require('cache-service-cache-module'))(cache);
Expand All @@ -32,19 +32,19 @@ module.exports = function(agent, cache, defaults){

/**
* Remove the given params from the query object after executing an http query and before generating a cache key
* @param {array of strings} pruneParams
* @param {array of strings} pruneQuery
*/
Request.prototype.pruneParams = function(pruneParams){
props.pruneParams = pruneParams;
Request.prototype.pruneQuery = function(pruneQuery){
props.pruneQuery = pruneQuery;
return this;
}

/**
* Remove the given options from the headers object after executing an http query and before generating a cache key
* @param {boolean} pruneOptions
* @param {boolean} pruneHeader
*/
Request.prototype.pruneOptions = function(pruneOptions){
props.pruneOptions = pruneOptions;
Request.prototype.pruneHeader = function(pruneHeader){
props.pruneHeader = pruneHeader;
return this;
}

Expand Down Expand Up @@ -76,7 +76,7 @@ module.exports = function(agent, cache, defaults){
}

/**
* Whether to cache superagent's http response object when it "empty"--especially useful with .prune and .pruneParams
* Whether to cache superagent's http response object when it "empty"--especially useful with .prune and .pruneQuery
* @param {boolean} cacheWhenEmpty
*/
Request.prototype.cacheWhenEmpty = function(cacheWhenEmpty){
Expand Down Expand Up @@ -114,29 +114,16 @@ module.exports = function(agent, cache, defaults){
}

/**
* Overwrites superagent's fake promise support and adds the generated cache key
* Only applies if Request.prototype.promise is not set
* Fixes this isse: https://github.com/jpodwys/superagent-cache/issues/38
* An alias for the .end function
*/
if(!Request.prototype.promise){
Request.prototype.then = function(fulfill, reject){
return this.end(function (err, response, key) {
err ? reject(err) : fulfill(response, key);
});
}
}

/**
* An alias for the .end function because I use ._end and .end for other things
*/
Request.prototype.execute = Request.prototype.end;
Request.prototype._superagentCache_execute = Request.prototype.end;

/**
* Wraps the .end function so that .resetProps gets called--callable so that no caching logic takes place
*/
Request.prototype._end = function(cb){
Request.prototype._superagentCache_originalEnd = function(cb){
props = utils.resetProps(superagent.defaults);
this.execute(cb);
this._superagentCache_execute(cb);
}

/**
Expand Down Expand Up @@ -165,7 +152,7 @@ module.exports = function(agent, cache, defaults){
return superagent.pendingRequests[key].push(cb);
}
}
_this._end(function (err, response){
_this._superagentCache_originalEnd(function (err, response){
if(err){
utils.handlePendingRequests(curProps, superagent, key, err, response);
return utils.callbackExecutor(cb, err, response, key);
Expand Down Expand Up @@ -205,7 +192,7 @@ module.exports = function(agent, cache, defaults){
});
}
else{
this._end(function (err, response){
this._superagentCache_originalEnd(function (err, response){
if(err){
return utils.callbackExecutor(cb, err, response, key);
}
Expand All @@ -220,15 +207,11 @@ module.exports = function(agent, cache, defaults){
}
}
else{
this._end(function (err, response){
this._superagentCache_originalEnd(function (err, response){
return utils.callbackExecutor(cb, err, response, undefined);
});
}
}
}

if(!agent){
return superagent;
}

}
Loading

0 comments on commit 7336b18

Please sign in to comment.