Comparing version
27
index.js
@@ -26,2 +26,3 @@ "use strict"; | ||
var freeze = true; | ||
var deepFreeze = false; | ||
var cache = new AsyncCache(initCache({age: 60})); | ||
@@ -59,2 +60,6 @@ var cacheKeyFn = behavior.cacheKeyFn || calculateCacheKey; | ||
if (behavior.hasOwnProperty("deepFreeze")) { | ||
deepFreeze = !!behavior.deepFreeze; | ||
} | ||
if (behavior.hasOwnProperty("followRedirect")) { | ||
@@ -102,7 +107,27 @@ followRedirect = !!behavior.followRedirect; | ||
function deepFreezeObj(obj) { | ||
var propNames = Object.getOwnPropertyNames(obj); | ||
propNames.forEach(function(name) { | ||
var prop = obj[name]; | ||
if (typeof prop === "object" && prop !== null) { | ||
deepFreezeObj(prop); | ||
} | ||
}); | ||
return Object.freeze(obj); | ||
} | ||
function handleSuccess(url, cacheKey, res, content, resolvedCallback) { | ||
var maxAge = maxAgeFn(getMaxAge(res.headers["cache-control"]), cacheKey, res, content); | ||
if (freeze && typeof content === "object") { | ||
var contentType = typeof content; | ||
if (deepFreeze && contentType === "object") { | ||
deepFreezeObj(content); | ||
} else if (freeze && contentType === "object") { | ||
Object.freeze(content); | ||
} | ||
if (onSuccess) { | ||
@@ -109,0 +134,0 @@ onSuccess(url, cacheKey, res, content); |
{ | ||
"name": "exp-fetch", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"description": "A small pluggable fetch lib", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -8,3 +8,3 @@ fetch | ||
### Usage | ||
By default fetch will treat all response codes expect 200 and 404 as errors. 404 will yield `null` and 200 the body | ||
By default fetch will treat all response codes except 200 and 404 as errors. 404 will yield `null` and 200 the body. | ||
@@ -19,4 +19,5 @@ #### Caching | ||
```javascript | ||
var fetchBuilder = require("exp-fetch"); | ||
var behavior = {}; | ||
var fetch = fetchBuilder(behavior); | ||
var fetch = fetchBuilder(behavior).fetch; | ||
fetch("http://example.com/resource.json", function (err, content) { | ||
@@ -30,4 +31,5 @@ // Do something with the result | ||
```javascript | ||
var fetchBuilder = require("exp-fetch"); | ||
var behavior = {}; | ||
var fetch = fetchBuilder(behavior); | ||
var fetch = fetchBuilder(behavior).fetch; | ||
fetch("http://example.com/resource.json").then(function (content) { | ||
@@ -41,4 +43,5 @@ // Do something with the result | ||
```javascript | ||
var fetchBuilder = require("exp-fetch"); | ||
var behavior = {}; | ||
var fetch = fetchBuilder(behavior); | ||
var fetch = fetchBuilder(behavior).fetch; | ||
var options = { | ||
@@ -58,4 +61,5 @@ url: "http://example.com/resource.json", | ||
```javascript | ||
var fetchBuilder = require("exp-fetch"); | ||
var behavior = { httpMethod: "POST"}; | ||
var poster = fetchBuilder(behavior); | ||
var poster = fetchBuilder(behavior).fetch; | ||
var body = { | ||
@@ -74,2 +78,3 @@ "query": "some string" | ||
* `freeze`: (default:`true`). When this option is set to false it will not freeze the response so it can be modified. ("use strict" is needed) | ||
* `deepFreeze`: (default:`false`). When this option is set to true it will freeze the response _recursively_ so that it or any objects it contains can't be modified. ("use strict" is needed) | ||
* `cache`: (default: `an instance of AsyncCache`) (https://github.com/ExpressenAB/exp-asynccache). To disable caching set `{cache: null}` | ||
@@ -93,9 +98,14 @@ * `cacheKeyFn`: (default: caches on the url + sha1 of the body) An optional formatting function for finding the cache-key. One might, for example, want to cache on an url with the get params stripped. | ||
The difference between `freeze` and `deepFreeze` is that `deepFreeze` walks the object graph and freezes any | ||
child objects in the retrieved data. `freeze` only freezes the root object but still allows modifications | ||
to nested objects. `deepFreeze` will be slower since it is recursive. | ||
#### CacheKeyFn | ||
```javascript | ||
var fetchBuilder = require("exp-fetch"); | ||
var keyFinder = function (url) { | ||
return url.replace(/\//g, ""); | ||
} | ||
var fetch = fetchBuilder({cacheKeyFn: keyFinder}); | ||
var fetch = fetchBuilder({cacheKeyFn: keyFinder}).fetch; | ||
Promise.all([ | ||
@@ -113,2 +123,3 @@ fetch("http://example.com/foo/bar") | ||
```javascript | ||
var fetchBuilder = require("exp-fetch"); | ||
var valueFn = function (body, headers, statusCode) { | ||
@@ -121,3 +132,3 @@ return { | ||
} | ||
var fetch = fetchBuilder({cacheValueFn: valueFn}); | ||
var fetch = fetchBuilder({cacheValueFn: valueFn}).fetch; | ||
fetch("http://example.com/resource.json", function (err, value) { | ||
@@ -132,6 +143,7 @@ // value will be something like: | ||
```javascript | ||
var fetchBuilder = require("exp-fetch"); | ||
function cacheNothing(maxAge, key, res, content) { | ||
return -1; | ||
} | ||
var fetch = fetchBuilder({maxAgeFn: cacheNothing}); | ||
var fetch = fetchBuilder({maxAgeFn: cacheNothing}).fetch; | ||
``` | ||
@@ -173,3 +185,3 @@ | ||
var fetch = fetchBuilder({onRequestInit: onRequestInit}); | ||
var fetch = fetchBuilder({onRequestInit: onRequestInit}).fetch; | ||
``` | ||
@@ -206,6 +218,6 @@ | ||
```javascript | ||
var fetchBuilder = require("exp-fetch"); | ||
var behavior = {}; | ||
var fetch = fetchBuilder(behavior); | ||
var stats = fetch.stats(); | ||
console.log("Hit ration", stats.cacheHitRatio); | ||
var stats = fetchBuilder(behavior).stats; | ||
console.log("Hit ratio", stats().cacheHitRatio); | ||
``` |
@@ -98,15 +98,30 @@ "use strict"; | ||
var localFetch = fetchBuilder({freeze:false, clone: false}).fetch; | ||
fake.get(path).times(2).reply(200, {some: "content"}, {"cache-control": "no-cache"}); | ||
fetch(host + path, function (err, content) { | ||
should.throw(function () { | ||
content.prop1 = true; | ||
}, TypeError); | ||
localFetch(host + path, function (err, content) { | ||
should.not.throw(function () { | ||
content.prop1 = true; | ||
}, TypeError); | ||
done(err); | ||
}); | ||
fake.get(path).reply(200, {some: "content", child: { some: "child-content" }}, {"cache-control": "no-cache"}); | ||
localFetch(host + path, function (err, content) { | ||
Object.isFrozen(content).should.be.false; | ||
Object.isFrozen(content.child).should.be.false; | ||
done(err); | ||
}); | ||
}); | ||
it("should freeze the result root but not descendants by default", function (done) { | ||
var localFetch = fetchBuilder({clone: false}).fetch; | ||
fake.get(path).reply(200, {some: "content", child: { some: "child-content" }}, {"cache-control": "no-cache"}); | ||
localFetch(host + path, function (err, content) { | ||
Object.isFrozen(content).should.be.true; | ||
Object.isFrozen(content.child).should.be.false; | ||
done(err); | ||
}); | ||
}); | ||
it("should freeze objects recursively if deepFreeze is set to true", function (done) { | ||
var localFetch = fetchBuilder({deepFreeze:true, clone: false}).fetch; | ||
fake.get(path).reply(200, {some: "content", child: { some: "child-content" }}, {"cache-control": "no-cache"}); | ||
localFetch(host + path, function (err, content) { | ||
Object.isFrozen(content).should.be.true; | ||
Object.isFrozen(content.child).should.be.true; | ||
done(err); | ||
}); | ||
}); | ||
}); | ||
@@ -113,0 +128,0 @@ |
Sorry, the diff of this file is not supported yet
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
51370
4.49%1168
2.55%212
6%65
-2.99%