cache-parser
Advanced tools
Comparing version 1.0.0 to 1.1.0
367
index.d.ts
/** | ||
* The Cache-Control HTTP header field holds directives (instructions) | ||
* — in both requests and responses — that control caching in browsers | ||
* and shared caches (e.g. Proxies, CDNs). | ||
* A simple enum that can help determine the header names. | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control | ||
* The {@link CacheControl} object uses camelCase parameters to help with the javascript | ||
* code. With that said, you can get the same property in kebab-case with the help of this enum: | ||
* | ||
* @example | ||
* | ||
* ```js | ||
* const cacheControl = parse('...'); | ||
* | ||
* const maxAge = cacheControl[HEADER_NAME['max-age']]; | ||
* ``` | ||
*/ | ||
type CacheControl = { | ||
immutable?: boolean; | ||
maxAge?: number; | ||
maxStale?: boolean | number; | ||
minFresh?: number; | ||
mustRevalidate?: boolean; | ||
mustUnderstand?: boolean; | ||
noCache?: boolean; | ||
noStore?: boolean; | ||
noTransform?: boolean; | ||
onlyIfCached?: boolean; | ||
private?: boolean; | ||
proxyRevalidate?: boolean; | ||
public?: boolean; | ||
sMaxage?: number; | ||
staleIfError?: number; | ||
staleWhileRevalidate?: number; | ||
}; | ||
export declare enum HEADER_NAME { | ||
immutable = 'immutable', | ||
maxAge = 'max-age', | ||
maxStale = 'max-stale', | ||
minFresh = 'min-fresh', | ||
mustRevalidate = 'must-revalidate', | ||
mustUnderstand = 'must-understand', | ||
noCache = 'no-cache', | ||
noStore = 'no-store', | ||
noTransform = 'no-transform', | ||
onlyIfCached = 'only-if-cached', | ||
private = 'private', | ||
proxyRevalidate = 'proxy-revalidate', | ||
public = 'public', | ||
sMaxAge = 's-maxage', | ||
staleIfError = 'stale-if-error', | ||
staleWhileRevalidate = 'stale-while-revalidate' | ||
} | ||
export declare const HEADER_NAME: Record<keyof CacheControl, string>; | ||
/** | ||
* Detects if the given parameter is a {@link CacheControl} object. | ||
* | ||
* @param {any} obj The object to test | ||
* @returns {boolean} True if the parameter was created by the {@link parse} function | ||
*/ | ||
export declare function isCacheControl(obj: any): obj is CacheControl; | ||
/** | ||
* Parses the Cache-Control header. | ||
* | ||
* You can check if a object was returned by this function with {@link isCacheControl}. | ||
* | ||
* @param {string} header The header to parse | ||
* @returns {CacheControl} The parsed cache control header | ||
*/ | ||
export declare function parse(header: string): CacheControl; | ||
/** | ||
* @param header the cache control object | ||
* @returns An array of directives an their respective values. | ||
* Return an array of tokens from the header object. | ||
* | ||
* The cache control object does not need to be a CacheControl object from the | ||
* {@link CacheControl}.This means that the parameter do not have to pass in the | ||
* {@link isCacheControl} function. | ||
* | ||
* You can build a string with `.join(', ')` method. | ||
* | ||
* @example | ||
* const tokens = tokenize({ maxAge: 3600, noCache: true }) | ||
* // tokens == ['max-age=3600', 'no-cache'] | ||
* | ||
* const header = tokens.join(', '); | ||
* // header == 'max-age=3600, no-cache' | ||
* ```js | ||
* const tokens = tokenize({ maxAge: 3600, noCache: true }); // ['max-age=3600', | ||
* 'no-cache'] | ||
* | ||
* const header = tokens.join(', '); // 'max-age=3600, no-cache' | ||
* ``` | ||
* | ||
* @param header The cache control object | ||
* @returns An array of directives an their respective values. | ||
*/ | ||
export declare function tokenize(header: { | ||
[K in keyof CacheControl]?: CacheControl[K] | (() => CacheControl[K]); | ||
}): string[]; | ||
export declare function tokenize(header: CacheControl): string[]; | ||
export declare function isCacheControl(header: any): header is CacheControl; | ||
/** | ||
* The Cache-Control HTTP header field holds directives (instructions) — in both requests | ||
* and responses — that control caching in browsers and shared caches (e.g. Proxies, CDNs). | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control | ||
*/ | ||
export declare type CacheControl = { | ||
/** | ||
* The immutable response directive indicates that the response will not be updated | ||
* while it's fresh. | ||
* | ||
* ```txt | ||
* Cache-Control: public, max-age=604800, immutable | ||
* ``` | ||
* | ||
* A modern best practice for static resources is to include version/hashes in their | ||
* URLs, while never modifying the resources — but instead, when necessary, updating the | ||
* resources with newer versions that have new version-numbers/hashes, so that their | ||
* URLs are different. That’s called the cache-busting pattern. | ||
* | ||
* ```html | ||
* <script src=https://example.com/react.0.0.0.js></script> | ||
* ``` | ||
* | ||
* When a user reloads the browser, the browser will send conditional requests for | ||
* validating to the origin server. But it's not necessary to revalidate those kinds of | ||
* static resources even when a user reloads the browser, because they're never | ||
* modified. immutable tells a cache that the response is immutable while it's fresh, | ||
* and avoids those kinds of unnecessary conditional requests to the server. | ||
* | ||
* When you use a cache-busting pattern for resources and apply them to a long max-age, | ||
* you can also add immutable to avoid revalidation. | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#immutable | ||
*/ | ||
immutable?: true; | ||
/** | ||
* The max-age=N response directive indicates that the response remains fresh until N | ||
* seconds after the response is generated. | ||
* | ||
* ```txt | ||
* Cache-Control: max-age=604800 | ||
* ``` | ||
* | ||
* Indicates that caches can store this response and reuse it for subsequent requests | ||
* while it's fresh. | ||
* | ||
* Note that max-age is not the elapsed time since the response was received, but | ||
* instead the elapsed time since the response was generated on the origin server. So if | ||
* the other cache(s) on the path the response takes store it for 100 seconds (indicated | ||
* using the Age response header field), the browser cache would deduct 100 seconds from | ||
* its freshness lifetime. | ||
* | ||
* ```txt | ||
* Cache-Control: max-age=604800 | ||
* Age: 100 | ||
* ``` | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#max-age | ||
*/ | ||
maxAge?: number; | ||
/** | ||
* The max-stale=N request directive indicates that the client allows a stored response | ||
* that is stale within N seconds. | ||
* | ||
* ```txt | ||
* Cache-Control: max-stale=3600 | ||
* ``` | ||
* | ||
* In the case above, if the response with Cache-Control: max-age=604800 was stored on | ||
* caches 3 hours ago, the cache couldn't reuse that response. | ||
* | ||
* Clients can use this header when the origin server is down or too slow and can accept | ||
* cached responses from caches even if they are a bit old. | ||
* | ||
* Note that the major browsers do not support requests with max-stale. | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#max-stale | ||
*/ | ||
maxStale?: number; | ||
/** | ||
* The min-fresh=N request directive indicates that the client allows a stored response | ||
* that is fresh for at least N seconds. | ||
* | ||
* ```txt | ||
* Cache-Control: min-fresh=600 | ||
* ``` | ||
* | ||
* In the case above, if the response with Cache-Control: max-age=3600 was stored in | ||
* caches 51 minutes ago, the cache couldn't reuse that response. | ||
* | ||
* Clients can use this header when the user requires the response to not only be fresh, | ||
* but also requires that it won't be updated for a period of time. | ||
* | ||
* Note that the major browsers do not support requests with min-fresh. | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#min-fresh | ||
*/ | ||
minFresh?: number; | ||
/** | ||
* The must-revalidate response directive indicates that the response can be stored in | ||
* caches and can be reused while fresh. Once it becomes stale, it must be validated | ||
* with the origin server before reuse. | ||
* | ||
* Typically, must-revalidate is used with max-age. | ||
* | ||
* ```txt | ||
* Cache-Control: max-age=604800, must-revalidate | ||
* ``` | ||
* | ||
* HTTP allows caches to reuse stale responses when they are disconnected from the | ||
* origin server. must-revalidate is a way to prevent that, so that the cache either | ||
* revalidates the stored response with the origin server, or if that's not possible it | ||
* generates a 504 (Gateway Timeout) response. | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#must-revalidate | ||
*/ | ||
mustRevalidate?: true; | ||
mustUnderstand?: true; | ||
/** | ||
* The no-cache response directive indicates that the response can be stored in caches, | ||
* but must be validated with the origin server before each reuse — even when the cache | ||
* is disconnected from the origin server. | ||
* | ||
* ```txt | ||
* Cache-Control: no-cache | ||
* ``` | ||
* | ||
* If you want caches to always check for content updates while reusing stored content | ||
* when it hasn't changed, no-cache is the directive to use. It does this by requiring | ||
* caches to revalidate each request with the origin server. | ||
* | ||
* Note that no-cache does not mean "don't cache". no-cache allows caches to store a | ||
* response, but requires them to revalidate it before reuse. If the sense of "don't | ||
* cache" that you want is actually "don't store", then no-store is the directive to use. | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#no-cache | ||
*/ | ||
noCache?: true; | ||
/** | ||
* The no-store response directive indicates that any caches of any kind (private or | ||
* shared) should not store this response. | ||
* | ||
* ```txt | ||
* Cache-Control: no-store | ||
* ``` | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#no-store | ||
*/ | ||
noStore?: true; | ||
/** | ||
* Some intermediaries transform content for various reasons. For example, some convert | ||
* images to reduce transfer size. In some cases, this is undesirable for the content provider. | ||
* | ||
* No-transform indicates that any intermediary (regardless of whether it implements a | ||
* cache) shouldn't transform the response contents. | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#no-transform | ||
*/ | ||
noTransform?: true; | ||
/** | ||
* The client indicates that cache should obtain an already-cached response. If a cache | ||
* has stored a response, it’s reused. | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#only-if-cached | ||
*/ | ||
onlyIfCached?: true; | ||
/** | ||
* The private response directive indicates that the response can be stored only in a | ||
* private cache (e.g. local caches in browsers). | ||
* | ||
* ```txt | ||
* Cache-Control: private | ||
* ``` | ||
* | ||
* You should add the private directive for user-personalized content — in particular, | ||
* responses received after login, and sessions managed via cookies. | ||
* | ||
* If you forget to add private to a response with personalized content, then that | ||
* response can be stored in a shared cache and end up being used by multiple users, | ||
* which can cause personal information to leak. | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#private | ||
*/ | ||
private?: true; | ||
/** | ||
* The proxy-revalidate response directive is the equivalent of must-revalidate, but | ||
* specifically for shared caches only. | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#proxy-revalidate | ||
*/ | ||
proxyRevalidate?: true; | ||
/** | ||
* Responses for requests with Authorization header fields must not be stored in a | ||
* shared cache. But the public directive will cause such responses to be stored in a | ||
* shared cache. | ||
* | ||
* ```txt | ||
* Cache-Control: public | ||
* ``` | ||
* | ||
* In general, when pages are under Basic Auth or Digest Auth, the browser sends | ||
* requests with the Authorization header. That means the response is access-controlled | ||
* for restricted users (who have accounts), and it's fundamentally not | ||
* shared-cacheable, even if it has max-age. | ||
* | ||
* You can use the public directive to unlock that restriction. | ||
* | ||
* ```txt | ||
* Cache-Control: public, max-age=604800 | ||
* ``` | ||
* | ||
* Note that, s-maxage or must-revalidate also unlock that restriction. | ||
* | ||
* If a request doesn’t have an Authorization header, or you are already using s-maxage | ||
* or must-revalidate in the response, then you don't need to use public. | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#public | ||
*/ | ||
public?: true; | ||
/** | ||
* The s-maxage response directive also indicates how long the response is fresh for | ||
* (similar to max-age) — but it is specific to shared caches, and they will ignore | ||
* max-age when it is present. | ||
* | ||
* ```txt | ||
* Cache-Control: s-maxage=604800 | ||
* ``` | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#s-maxage | ||
*/ | ||
sMaxAge?: number; | ||
/** | ||
* The stale-if-error response directive indicates that the cache can reuse a stale | ||
* response when an origin server responds with an error (500, 502, 503, or 504). | ||
* | ||
* ```txt | ||
* Cache-Control: max-age=604800, stale-if-error=86400 | ||
* ``` | ||
* | ||
* In the example above, the response is fresh for 7 days (604800s). After 7 days it | ||
* becomes stale, but it can be used for an extra 1 day (86400s) if the server responds | ||
* with an error. | ||
* | ||
* After a period of time, the stored response became stale normally. That means the | ||
* client will receive an error response as-is if the origin server sends it. | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-if-error | ||
*/ | ||
staleIfError?: number; | ||
/** | ||
* The stale-while-revalidate response directive indicates that the cache could reuse a | ||
* stale response while it revalidates it to a cache. | ||
* | ||
* ```txt | ||
* Cache-Control: max-age=604800, stale-while-revalidate=86400 | ||
* ``` | ||
* | ||
* In the example above, the response is fresh for 7 days (604800s). After 7 days, it | ||
* becomes stale but the cache is allowed to reuse it for any requests that are made in | ||
* the following day (86400s) — provided that they revalidate the response in the background. | ||
* | ||
* Revalidation will make the cache be fresh again, so it appears to clients that it was | ||
* always fresh during that period — effectively hiding the latency penalty of | ||
* revalidation from them. | ||
* | ||
* If no request happened during that period, the cache became stale and the next | ||
* request will revalidate normally. | ||
* | ||
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-while-revalidate | ||
*/ | ||
staleWhileRevalidate?: number; | ||
}; |
146
index.js
@@ -1,7 +0,7 @@ | ||
(function (root) { | ||
!(function (root) { | ||
/** Unique identifier */ | ||
var symbolKey = Symbol('cache-parser'); | ||
var symbolKey = (Symbol || String)('cache-parser'); | ||
/** Headers enum */ | ||
root.HEADER_NAME = { | ||
/** (camelCase=kebabCase) and (kebabCase=camelCase) */ | ||
var HEADER_NAME = { | ||
immutable: 'immutable', | ||
@@ -20,3 +20,3 @@ maxAge: 'max-age', | ||
public: 'public', | ||
sMaxage: 's-maxage', | ||
sMaxAge: 's-maxage', | ||
staleIfError: 'stale-if-error', | ||
@@ -26,12 +26,27 @@ staleWhileRevalidate: 'stale-while-revalidate' | ||
/** Just to test */ | ||
root.toCamelCase = function (kebab) { | ||
return kebab.replace(/-./g, (x) => x[1].toUpperCase()); | ||
}; | ||
for (var key in HEADER_NAME) { | ||
HEADER_NAME[HEADER_NAME[key]] = key; | ||
} | ||
root.isCacheControl = function (cache) { | ||
function toDuration(val) { | ||
return ( | ||
(typeof val === 'string' || typeof val === 'number') && | ||
(val = Number(val)) >= 0 && | ||
val < Infinity | ||
); | ||
} | ||
function toBoolean(val) { | ||
return ( | ||
val === true || | ||
typeof val === 'number' || | ||
(typeof val === 'string' && val !== 'false') | ||
); | ||
} | ||
function isCacheControl(cache) { | ||
return !!cache && !!cache[symbolKey]; | ||
}; | ||
} | ||
root.tokenize = function (header) { | ||
function tokenize(header) { | ||
if (!header || typeof header !== 'object') { | ||
@@ -43,22 +58,36 @@ return []; | ||
for (var camelName in root.HEADER_NAME) { | ||
var value = header[camelName]; | ||
toBoolean(header.immutable) && tokens.push(HEADER_NAME.immutable); | ||
if (!value && value !== 0) continue; | ||
if (typeof value === 'function') value = value(); | ||
toDuration(header.maxAge) && | ||
tokens.push(HEADER_NAME.maxAge + '=' + Number(header.maxAge)); | ||
if (value === false) continue; | ||
if (typeof value === 'number' && (value < 0 || /* Infinity */ value === value / 0)) | ||
continue; | ||
toDuration(header.maxStale) && | ||
tokens.push(HEADER_NAME.maxStale + '=' + Number(header.maxStale)); | ||
var kebabName = root.HEADER_NAME[camelName]; | ||
toDuration(header.minFresh) && | ||
tokens.push(HEADER_NAME.minFresh + '=' + Number(header.minFresh)); | ||
tokens.push(kebabName + (value === true ? '' : '=' + value)); | ||
} | ||
toBoolean(header.mustRevalidate) && tokens.push(HEADER_NAME.mustRevalidate); | ||
toBoolean(header.mustUnderstand) && tokens.push(HEADER_NAME.mustUnderstand); | ||
toBoolean(header.noCache) && tokens.push(HEADER_NAME.noCache); | ||
toBoolean(header.noStore) && tokens.push(HEADER_NAME.noStore); | ||
toBoolean(header.noTransform) && tokens.push(HEADER_NAME.noTransform); | ||
toBoolean(header.onlyIfCached) && tokens.push(HEADER_NAME.onlyIfCached); | ||
toBoolean(header.private) && tokens.push(HEADER_NAME.private); | ||
toBoolean(header.proxyRevalidate) && tokens.push(HEADER_NAME.proxyRevalidate); | ||
toBoolean(header.public) && tokens.push(HEADER_NAME.public); | ||
toDuration(header.sMaxAge) && | ||
tokens.push(HEADER_NAME.sMaxAge + '=' + Number(header.sMaxAge)); | ||
toDuration(header.staleIfError) && | ||
tokens.push(HEADER_NAME.staleIfError + '=' + Number(header.staleIfError)); | ||
toDuration(header.staleWhileRevalidate) && | ||
tokens.push( | ||
HEADER_NAME.staleWhileRevalidate + '=' + Number(header.staleWhileRevalidate) | ||
); | ||
return tokens; | ||
}; | ||
} | ||
root.parse = function (headerStr) { | ||
function parse(headerStr) { | ||
var header = Object.defineProperty({}, symbolKey, { | ||
@@ -75,41 +104,50 @@ configurable: false, | ||
var tokens = headerStr.replace(/\s+/g, '').split(','); | ||
/** (kebabName=rawValue) */ | ||
var rawHeaders = {}; | ||
var tokens = headerStr.toLowerCase().replace(/\s+/g, '').split(','); | ||
for (var i in tokens) { | ||
var token = tokens[i]; | ||
var token = tokens[i].split('=', 2); | ||
// Boolean values - without '=' | ||
if (token.indexOf('=') === -1) { | ||
var name = root.toCamelCase(token); | ||
rawHeaders[token[0]] = token.length === 1 ? true : token[1]; | ||
} | ||
if (!(name in root.HEADER_NAME)) continue; | ||
toBoolean(rawHeaders[HEADER_NAME.immutable]) && (header.immutable = true); | ||
header[name] = true; | ||
continue; | ||
} | ||
toDuration(rawHeaders[HEADER_NAME.maxAge]) && | ||
(header.maxAge = Number(rawHeaders[HEADER_NAME.maxAge])); | ||
toDuration(rawHeaders[HEADER_NAME.maxStale]) && | ||
(header.maxStale = Number(rawHeaders[HEADER_NAME.maxStale])); | ||
toDuration(rawHeaders[HEADER_NAME.minFresh]) && | ||
(header.minFresh = Number(rawHeaders[HEADER_NAME.minFresh])); | ||
var [name, value] = token.split('='); | ||
name = root.toCamelCase(name); | ||
toBoolean(rawHeaders[HEADER_NAME.mustRevalidate]) && (header.mustRevalidate = true); | ||
toBoolean(rawHeaders[HEADER_NAME.mustUnderstand]) && (header.mustUnderstand = true); | ||
toBoolean(rawHeaders[HEADER_NAME.noCache]) && (header.noCache = true); | ||
toBoolean(rawHeaders[HEADER_NAME.noStore]) && (header.noStore = true); | ||
toBoolean(rawHeaders[HEADER_NAME.noTransform]) && (header.noTransform = true); | ||
toBoolean(rawHeaders[HEADER_NAME.onlyIfCached]) && (header.onlyIfCached = true); | ||
toBoolean(rawHeaders[HEADER_NAME.private]) && (header.private = true); | ||
toBoolean(rawHeaders[HEADER_NAME.proxyRevalidate]) && (header.proxyRevalidate = true); | ||
toBoolean(rawHeaders[HEADER_NAME.public]) && (header.public = true); | ||
if (!(name in root.HEADER_NAME)) continue; | ||
toDuration(rawHeaders[HEADER_NAME.sMaxAge]) && | ||
(header.sMaxAge = Number(rawHeaders[HEADER_NAME.sMaxAge])); | ||
toDuration(rawHeaders[HEADER_NAME.staleIfError]) && | ||
(header.staleIfError = Number(rawHeaders[HEADER_NAME.staleIfError])); | ||
toDuration(rawHeaders[HEADER_NAME.staleWhileRevalidate]) && | ||
(header.staleWhileRevalidate = Number( | ||
rawHeaders[HEADER_NAME.staleWhileRevalidate] | ||
)); | ||
// Numbers | ||
var maybeNumber = Number(value); | ||
if (!isNaN(maybeNumber)) { | ||
header[name] = maybeNumber; | ||
continue; | ||
} | ||
return header; | ||
} | ||
// Booleans - with '=' - Just in case :) | ||
if (value === 'false' || value === 'true') { | ||
header[name] = value === 'true'; | ||
continue; | ||
} | ||
root.HEADER_NAME = HEADER_NAME; | ||
root.toDuration = toDuration; | ||
root.toBoolean = toBoolean; | ||
// String | ||
header[name] = value; | ||
} | ||
return header; | ||
}; | ||
root.isCacheControl = isCacheControl; | ||
root.tokenize = tokenize; | ||
root.parse = parse; | ||
})( | ||
@@ -116,0 +154,0 @@ typeof exports !== 'undefined' |
@@ -1,1 +0,1 @@ | ||
!function(e){var a=Symbol("cache-parser");e.HEADER_NAME={immutable:"immutable",maxAge:"max-age",maxStale:"max-stale",minFresh:"min-fresh",mustRevalidate:"must-revalidate",mustUnderstand:"must-understand",noCache:"no-cache",noStore:"no-store",noTransform:"no-transform",onlyIfCached:"only-if-cached",private:"private",proxyRevalidate:"proxy-revalidate",public:"public",sMaxage:"s-maxage",staleIfError:"stale-if-error",staleWhileRevalidate:"stale-while-revalidate"},e.toCamelCase=function(e){return e.replace(/-./g,(e=>e[1].toUpperCase()))},e.isCacheControl=function(e){return!!e&&!!e[a]},e.tokenize=function(a){if(!a||"object"!=typeof a)return[];var r=[];for(var t in e.HEADER_NAME){var n=a[t];if((n||0===n)&&("function"==typeof n&&(n=n()),!1!==n&&("number"!=typeof n||!(n<0||n===n/0)))){var i=e.HEADER_NAME[t];r.push(i+(!0===n?"":"="+n))}}return r},e.parse=function(r){var t=Object.defineProperty({},a,{configurable:!1,enumerable:!1,writable:!1,value:1});if(!r||"string"!=typeof r)return t;var n=r.replace(/\s+/g,"").split(",");for(var i in n){var o=n[i];if(-1!==o.indexOf("=")){var[s,l]=o.split("=");if((s=e.toCamelCase(s))in e.HEADER_NAME){var f=Number(l);isNaN(f)?t[s]="false"!==l&&"true"!==l?l:"true"===l:t[s]=f}}else{var s;if(!((s=e.toCamelCase(o))in e.HEADER_NAME))continue;t[s]=!0}}return t}}("undefined"!=typeof exports?exports:window.CacheParser||(window.CacheParser={})); | ||
!function(e){var a=(Symbol||String)("cache-parser"),r={immutable:"immutable",maxAge:"max-age",maxStale:"max-stale",minFresh:"min-fresh",mustRevalidate:"must-revalidate",mustUnderstand:"must-understand",noCache:"no-cache",noStore:"no-store",noTransform:"no-transform",onlyIfCached:"only-if-cached",private:"private",proxyRevalidate:"proxy-revalidate",public:"public",sMaxAge:"s-maxage",staleIfError:"stale-if-error",staleWhileRevalidate:"stale-while-revalidate"};for(var t in r)r[r[t]]=t;function n(e){return("string"==typeof e||"number"==typeof e)&&(e=Number(e))>=0&&e<1/0}function s(e){return!0===e||"number"==typeof e||"string"==typeof e&&"false"!==e}e.HEADER_NAME=r,e.toDuration=n,e.toBoolean=s,e.isCacheControl=function(e){return!!e&&!!e[a]},e.tokenize=function(e){if(!e||"object"!=typeof e)return[];var a=[];return s(e.immutable)&&a.push(r.immutable),n(e.maxAge)&&a.push(r.maxAge+"="+Number(e.maxAge)),n(e.maxStale)&&a.push(r.maxStale+"="+Number(e.maxStale)),n(e.minFresh)&&a.push(r.minFresh+"="+Number(e.minFresh)),s(e.mustRevalidate)&&a.push(r.mustRevalidate),s(e.mustUnderstand)&&a.push(r.mustUnderstand),s(e.noCache)&&a.push(r.noCache),s(e.noStore)&&a.push(r.noStore),s(e.noTransform)&&a.push(r.noTransform),s(e.onlyIfCached)&&a.push(r.onlyIfCached),s(e.private)&&a.push(r.private),s(e.proxyRevalidate)&&a.push(r.proxyRevalidate),s(e.public)&&a.push(r.public),n(e.sMaxAge)&&a.push(r.sMaxAge+"="+Number(e.sMaxAge)),n(e.staleIfError)&&a.push(r.staleIfError+"="+Number(e.staleIfError)),n(e.staleWhileRevalidate)&&a.push(r.staleWhileRevalidate+"="+Number(e.staleWhileRevalidate)),a},e.parse=function(e){var t=Object.defineProperty({},a,{configurable:!1,enumerable:!1,writable:!1,value:1});if(!e||"string"!=typeof e)return t;var o={},l=e.toLowerCase().replace(/\s+/g,"").split(",");for(var i in l){var u=l[i].split("=",2);o[u[0]]=1===u.length||u[1]}return s(o[r.immutable])&&(t.immutable=!0),n(o[r.maxAge])&&(t.maxAge=Number(o[r.maxAge])),n(o[r.maxStale])&&(t.maxStale=Number(o[r.maxStale])),n(o[r.minFresh])&&(t.minFresh=Number(o[r.minFresh])),s(o[r.mustRevalidate])&&(t.mustRevalidate=!0),s(o[r.mustUnderstand])&&(t.mustUnderstand=!0),s(o[r.noCache])&&(t.noCache=!0),s(o[r.noStore])&&(t.noStore=!0),s(o[r.noTransform])&&(t.noTransform=!0),s(o[r.onlyIfCached])&&(t.onlyIfCached=!0),s(o[r.private])&&(t.private=!0),s(o[r.proxyRevalidate])&&(t.proxyRevalidate=!0),s(o[r.public])&&(t.public=!0),n(o[r.sMaxAge])&&(t.sMaxAge=Number(o[r.sMaxAge])),n(o[r.staleIfError])&&(t.staleIfError=Number(o[r.staleIfError])),n(o[r.staleWhileRevalidate])&&(t.staleWhileRevalidate=Number(o[r.staleWhileRevalidate])),t}}("undefined"!=typeof exports?exports:window.CacheParser||(window.CacheParser={})); |
{ | ||
"name": "cache-parser", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "A minimal Cache-Control header parser", | ||
@@ -14,3 +14,4 @@ "main": "./index.min.js", | ||
"format": "prettier --write .", | ||
"minify": "terser index.js --compress --mangle --output index.min.js" | ||
"minify": "terser index.js --compress --mangle --output index.min.js", | ||
"escheck": "es-check es3 ./index*.js" | ||
}, | ||
@@ -47,6 +48,8 @@ "repository": { | ||
"@types/jest": "^27", | ||
"es-check": "^6.1.1", | ||
"jest": "^27", | ||
"prettier": "*", | ||
"prettier-plugin-jsdoc": "*", | ||
"terser": "^5" | ||
} | ||
} |
@@ -39,2 +39,9 @@ <br /> | ||
></code> | ||
<code | ||
><a href="https://app.codecov.io/gh/arthurfiorette/cache-parser/" | ||
><img | ||
src="https://codecov.io/gh/arthurfiorette/cache-parser/branch/main/graph/badge.svg?token=pdslRMQDtC" | ||
target="_blank" | ||
alt="Coverage" /></a | ||
></code> | ||
</div> | ||
@@ -56,6 +63,7 @@ | ||
- [Installing](#installing) | ||
- [Node](#node) | ||
- [Browser](#browser) | ||
- [Node](#node) | ||
- [Browser](#browser) | ||
- [Browser Compatibility](#browser-compatibility) | ||
- [Getting Started](#getting-started) | ||
- [Some examples](#some-examples) | ||
- [License](#license) | ||
@@ -77,5 +85,5 @@ - [Contact](#contact) | ||
```js | ||
const {} = require('cache-parser'); | ||
const { parse, tokenize } = require('cache-parser'); | ||
// or | ||
import {} from 'cache-parser'; | ||
import { parse, tokenize } from 'cache-parser'; | ||
``` | ||
@@ -90,9 +98,12 @@ | ||
<script crossorigin src="https://cdn.jsdelivr.net/npm/cache-parser@1.0.0"></script> | ||
<script | ||
crossorigin | ||
src="https://cdn.jsdelivr.net/npm/cache-parser@VERSION/index.min.js" | ||
></script> | ||
<!-- or --> | ||
<script crossorigin src="https://unpkg.com/cache-parser@1.0.0"></script> | ||
<script crossorigin src="https://unpkg.com/cache-parser@VERSION/index.min.js"></script> | ||
``` | ||
```js | ||
const {} = window.CacheParser; | ||
const { parse, tokenize } = window.CacheParser; | ||
``` | ||
@@ -104,4 +115,8 @@ | ||
> TODO | ||
Currently this package supports until **ES3**. To maintain this compatibility, our CI is | ||
using [ES Check](https://github.com/yowainwright/es-check). | ||
But you can test this yourself too by running `yarn escheck` or `npm run escheck` on this | ||
code. | ||
<br /> | ||
@@ -111,4 +126,39 @@ | ||
> TODO | ||
This library consists of two important functions: `parse` and `tokenize`. | ||
Every documentation needed by every piece of code is in form of `TSDoc` and `JSDoc` | ||
comments. You can see them [**Here**](/index.d.ts). | ||
### Some examples | ||
Simple header parsing: | ||
```js | ||
import { parse } from 'cache-parser'; | ||
const rawHeader = 'public, max-age=3600'; | ||
const { public, maxAge, immutable } = parse(rawHeader); | ||
console.log(public); // true | ||
console.log(maxAge); // 3600 | ||
console.log(typeof maxAge); // number | ||
console.log(immutable); // undefined | ||
``` | ||
Simple header building: | ||
```ts | ||
import { tokenize } from 'cache-parser'; | ||
/** @type {import('cache-parser').CacheControl} */ | ||
const cacheProperties = { public: true, maxAge: 3600 }; | ||
// ['public', 'max-age=3600'] | ||
const cacheTokens = tokenize(cacheProperties); | ||
// 'public, max-age=3600' | ||
response.headers['Cache-Control'] = tokens.join(', '); | ||
``` | ||
<br /> | ||
@@ -115,0 +165,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
27264
470
172
7
1