@reykjavik/webtools 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +17 -0
- package/esm/http.d.ts +8 -1
- package/esm/http.js +15 -13
- package/http.d.ts +8 -1
- package/http.js +16 -13
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@ yarn add @reykjavik/webtools
|
|
|
19
19
|
- [Types for HTTP Status code groups](#types-for-http-status-code-groups)
|
|
20
20
|
- [`cacheControl` helper](#cachecontrol-helper)
|
|
21
21
|
- [Type `TTLConfig`](#type-ttlconfig)
|
|
22
|
+
- [`toSec` TTL helper](#tosec-ttl-helper)
|
|
22
23
|
- [`@reykjavik/webtools/next/http`](#reykjavikwebtoolsnexthttp)
|
|
23
24
|
- [`makeErrorizeAppHOC`](#makeerrorizeapphoc)
|
|
24
25
|
- [`showErrorPage` helper](#showerrorpage-helper)
|
|
@@ -155,6 +156,22 @@ Allows setting a "must-revalidate" flag instead of the default "immutable". A
|
|
|
155
156
|
value of `"normal"` omits the flagging and falls back to HTTP's default
|
|
156
157
|
behavior.
|
|
157
158
|
|
|
159
|
+
### `toSec` TTL helper
|
|
160
|
+
|
|
161
|
+
**Syntax:** <code>toSec; (ttl: number | `${number}${'s'|'m'|'h'|'d'|'w'}`) =>
|
|
162
|
+
number</code>
|
|
163
|
+
|
|
164
|
+
Converts a `TTL` (max-age) value into seconds, and returns `0` for bad and/or
|
|
165
|
+
negative input values.
|
|
166
|
+
|
|
167
|
+
```js
|
|
168
|
+
import type { toSec, TTL } from '@reykjavik/webtools/http';
|
|
169
|
+
|
|
170
|
+
const ttl: TTL = '2h';
|
|
171
|
+
|
|
172
|
+
const ttlSec = toSec(ttl);
|
|
173
|
+
```
|
|
174
|
+
|
|
158
175
|
---
|
|
159
176
|
|
|
160
177
|
## `@reykjavik/webtools/next/http`
|
package/esm/http.d.ts
CHANGED
|
@@ -115,7 +115,7 @@ export type HTTP_CLIENT_ERROR_ALL = HTTP_CLIENT_ERROR | typeof HTTP_405_MethodNo
|
|
|
115
115
|
export type HTTP_SERVER_ERROR_ALL = HTTP_SERVER_ERROR | typeof HTTP_501_NotImplemented | typeof HTTP_502_BadGateway | typeof HTTP_503_ServiceUnavailable | typeof HTTP_504_GatewayTimeout | typeof HTTP_505_HTTPVersionNotSupported | typeof HTTP_506_VariantAlsoNegotiates | typeof HTTP_510_NotExtended | typeof HTTP_511_NetworkAuthenticationRequired;
|
|
116
116
|
export type HTTP_ERROR_ALL = HTTP_CLIENT_ERROR_ALL | HTTP_SERVER_ERROR_ALL;
|
|
117
117
|
type TimeUnit = 's' | 'm' | 'h' | 'd' | 'w';
|
|
118
|
-
type TTL = number | `${number}${TimeUnit}`;
|
|
118
|
+
export type TTL = number | `${number}${TimeUnit}`;
|
|
119
119
|
type TTLKeywords = 'permanent' | 'unset' | 'no-cache';
|
|
120
120
|
type TTLObj = {
|
|
121
121
|
/** Sets the cache `max-age=` for the resource. */
|
|
@@ -134,6 +134,13 @@ type TTLObj = {
|
|
|
134
134
|
* @see https://github.com/reykjavikcity/webtools/tree/v0.1#type-ttlconfig
|
|
135
135
|
*/
|
|
136
136
|
export type TTLConfig = TTL | TTLKeywords | TTLObj;
|
|
137
|
+
/**
|
|
138
|
+
* Converts a `TTL` (max-age) value into seconds, and returns `0` for bad
|
|
139
|
+
* and/or negative input values.
|
|
140
|
+
*
|
|
141
|
+
* @see https://github.com/reykjavikcity/webtools/tree/v0.1#tosec-ttl-helper
|
|
142
|
+
*/
|
|
143
|
+
export declare const toSec: (ttl: TTL) => number;
|
|
137
144
|
/**
|
|
138
145
|
* Use this function to quickly set the `Cache-Control` header with a `max-age=`
|
|
139
146
|
* on a HTTP response
|
package/esm/http.js
CHANGED
|
@@ -110,16 +110,19 @@ const unitToSeconds = {
|
|
|
110
110
|
d: 24 * 3600,
|
|
111
111
|
w: 7 * 24 * 3600,
|
|
112
112
|
};
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Converts a `TTL` (max-age) value into seconds, and returns `0` for bad
|
|
115
|
+
* and/or negative input values.
|
|
116
|
+
*
|
|
117
|
+
* @see https://github.com/reykjavikcity/webtools/tree/v0.1#tosec-ttl-helper
|
|
118
|
+
*/
|
|
119
|
+
export const toSec = (ttl) => {
|
|
117
120
|
if (typeof ttl === 'string') {
|
|
118
121
|
const value = parseFloat(ttl);
|
|
119
122
|
const factor = unitToSeconds[ttl.slice(-1)] || 1;
|
|
120
123
|
ttl = value * factor;
|
|
121
124
|
}
|
|
122
|
-
return
|
|
125
|
+
return Math.max(0, Math.round(ttl)) || 0;
|
|
123
126
|
};
|
|
124
127
|
const stabilities = {
|
|
125
128
|
revalidate: ', must-revalidate',
|
|
@@ -163,22 +166,21 @@ export const cacheControl = (response, ttlCfg, eTag) => {
|
|
|
163
166
|
maxAge = undefined;
|
|
164
167
|
}
|
|
165
168
|
}
|
|
166
|
-
maxAge = toSec(maxAge);
|
|
167
169
|
if (maxAge == null) {
|
|
168
170
|
response.removeHeader('Cache-Control');
|
|
169
171
|
return;
|
|
170
172
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const sIE_ttl = toSec(opts.staleIfError);
|
|
174
|
-
const sIE = sIE_ttl != null ? `, stale-if-error=${sIE_ttl}` : '';
|
|
175
|
-
maxAge = Math.round(maxAge);
|
|
176
|
-
if (maxAge <= 0) {
|
|
173
|
+
maxAge = toSec(maxAge);
|
|
174
|
+
if (!maxAge) {
|
|
177
175
|
setCC(response, 'no-cache');
|
|
178
176
|
return;
|
|
179
177
|
}
|
|
178
|
+
const sWR_ttl = toSec(opts.staleWhileRevalidate || 0);
|
|
179
|
+
const sWR = sWR_ttl ? `, stale-while-revalidate=${sWR_ttl}` : '';
|
|
180
|
+
const sIE_ttl = toSec(opts.staleIfError || 0);
|
|
181
|
+
const sIE = sIE_ttl ? `, stale-if-error=${sIE_ttl}` : '';
|
|
180
182
|
const scope = opts.publ ? 'public' : 'private';
|
|
181
183
|
const stability = (opts.stability && stabilities[opts.stability]) || stabilities.immutable;
|
|
182
|
-
eTag != null && response.setHeader('ETag', eTag);
|
|
183
184
|
setCC(response, `${scope}, max-age=${maxAge + sWR + sIE + stability}`);
|
|
185
|
+
eTag != null && response.setHeader('ETag', eTag);
|
|
184
186
|
};
|
package/http.d.ts
CHANGED
|
@@ -115,7 +115,7 @@ export type HTTP_CLIENT_ERROR_ALL = HTTP_CLIENT_ERROR | typeof HTTP_405_MethodNo
|
|
|
115
115
|
export type HTTP_SERVER_ERROR_ALL = HTTP_SERVER_ERROR | typeof HTTP_501_NotImplemented | typeof HTTP_502_BadGateway | typeof HTTP_503_ServiceUnavailable | typeof HTTP_504_GatewayTimeout | typeof HTTP_505_HTTPVersionNotSupported | typeof HTTP_506_VariantAlsoNegotiates | typeof HTTP_510_NotExtended | typeof HTTP_511_NetworkAuthenticationRequired;
|
|
116
116
|
export type HTTP_ERROR_ALL = HTTP_CLIENT_ERROR_ALL | HTTP_SERVER_ERROR_ALL;
|
|
117
117
|
type TimeUnit = 's' | 'm' | 'h' | 'd' | 'w';
|
|
118
|
-
type TTL = number | `${number}${TimeUnit}`;
|
|
118
|
+
export type TTL = number | `${number}${TimeUnit}`;
|
|
119
119
|
type TTLKeywords = 'permanent' | 'unset' | 'no-cache';
|
|
120
120
|
type TTLObj = {
|
|
121
121
|
/** Sets the cache `max-age=` for the resource. */
|
|
@@ -134,6 +134,13 @@ type TTLObj = {
|
|
|
134
134
|
* @see https://github.com/reykjavikcity/webtools/tree/v0.1#type-ttlconfig
|
|
135
135
|
*/
|
|
136
136
|
export type TTLConfig = TTL | TTLKeywords | TTLObj;
|
|
137
|
+
/**
|
|
138
|
+
* Converts a `TTL` (max-age) value into seconds, and returns `0` for bad
|
|
139
|
+
* and/or negative input values.
|
|
140
|
+
*
|
|
141
|
+
* @see https://github.com/reykjavikcity/webtools/tree/v0.1#tosec-ttl-helper
|
|
142
|
+
*/
|
|
143
|
+
export declare const toSec: (ttl: TTL) => number;
|
|
137
144
|
/**
|
|
138
145
|
* Use this function to quickly set the `Cache-Control` header with a `max-age=`
|
|
139
146
|
* on a HTTP response
|
package/http.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.cacheControl = exports.HTTP_511_NetworkAuthenticationRequired = exports.HTTP_510_NotExtended = exports.HTTP_506_VariantAlsoNegotiates = exports.HTTP_505_HTTPVersionNotSupported = exports.HTTP_504_GatewayTimeout = exports.HTTP_503_ServiceUnavailable = exports.HTTP_502_BadGateway = exports.HTTP_501_NotImplemented = exports.HTTP_500_InternalServerError = exports.HTTP_451_UnavailableForLegalReasons = exports.HTTP_431_RequestHeaderFieldsTooLarge = exports.HTTP_429_TooManyRequests = exports.HTTP_428_PreconditionRequired = exports.HTTP_426_UpgradeRequired = exports.HTTP_421_MisdirectedRequest = exports.HTTP_418_ImATeapot = exports.HTTP_417_ExpectationFailed = exports.HTTP_416_RangeNotSatisfiable = exports.HTTP_415_UnsupportedMediaType = exports.HTTP_414_URITooLong = exports.HTTP_413_PayloadTooLarge = exports.HTTP_412_PreconditionFailed = exports.HTTP_411_LengthRequired = exports.HTTP_410_Gone = exports.HTTP_409_Conflict = exports.HTTP_408_RequestTimeout = exports.HTTP_407_ProxyAuthenticationRequired = exports.HTTP_406_NotAcceptable = exports.HTTP_405_MethodNotAllowed = exports.HTTP_404_NotFound = exports.HTTP_403_Forbidden = exports.HTTP_401_Unauthorized = exports.HTTP_400_BadRequest = exports.HTTP_308_PermanentRedirect = exports.HTTP_307_TemporaryRedirect = exports.HTTP_304_NotModified = exports.HTTP_303_SeeOther = exports.HTTP_302_Found = exports.HTTP_301_MovedPermanently = exports.HTTP_206_PartialContent = exports.HTTP_204_NoContent = exports.HTTP_203_NonAuthoritativeInformation = exports.HTTP_202_Accepted = exports.HTTP_201_Created = exports.HTTP_200_OK = exports.HTTP_101_SwitchingProtocols = exports.HTTP_100_Continue = void 0;
|
|
3
|
+
exports.cacheControl = exports.toSec = exports.HTTP_511_NetworkAuthenticationRequired = exports.HTTP_510_NotExtended = exports.HTTP_506_VariantAlsoNegotiates = exports.HTTP_505_HTTPVersionNotSupported = exports.HTTP_504_GatewayTimeout = exports.HTTP_503_ServiceUnavailable = exports.HTTP_502_BadGateway = exports.HTTP_501_NotImplemented = exports.HTTP_500_InternalServerError = exports.HTTP_451_UnavailableForLegalReasons = exports.HTTP_431_RequestHeaderFieldsTooLarge = exports.HTTP_429_TooManyRequests = exports.HTTP_428_PreconditionRequired = exports.HTTP_426_UpgradeRequired = exports.HTTP_421_MisdirectedRequest = exports.HTTP_418_ImATeapot = exports.HTTP_417_ExpectationFailed = exports.HTTP_416_RangeNotSatisfiable = exports.HTTP_415_UnsupportedMediaType = exports.HTTP_414_URITooLong = exports.HTTP_413_PayloadTooLarge = exports.HTTP_412_PreconditionFailed = exports.HTTP_411_LengthRequired = exports.HTTP_410_Gone = exports.HTTP_409_Conflict = exports.HTTP_408_RequestTimeout = exports.HTTP_407_ProxyAuthenticationRequired = exports.HTTP_406_NotAcceptable = exports.HTTP_405_MethodNotAllowed = exports.HTTP_404_NotFound = exports.HTTP_403_Forbidden = exports.HTTP_401_Unauthorized = exports.HTTP_400_BadRequest = exports.HTTP_308_PermanentRedirect = exports.HTTP_307_TemporaryRedirect = exports.HTTP_304_NotModified = exports.HTTP_303_SeeOther = exports.HTTP_302_Found = exports.HTTP_301_MovedPermanently = exports.HTTP_206_PartialContent = exports.HTTP_204_NoContent = exports.HTTP_203_NonAuthoritativeInformation = exports.HTTP_202_Accepted = exports.HTTP_201_Created = exports.HTTP_200_OK = exports.HTTP_101_SwitchingProtocols = exports.HTTP_100_Continue = void 0;
|
|
4
4
|
// INFORMATION
|
|
5
5
|
/** The client should continue the request or ignore the response if the request is already finished. */
|
|
6
6
|
exports.HTTP_100_Continue = 100;
|
|
@@ -113,17 +113,21 @@ const unitToSeconds = {
|
|
|
113
113
|
d: 24 * 3600,
|
|
114
114
|
w: 7 * 24 * 3600,
|
|
115
115
|
};
|
|
116
|
+
/**
|
|
117
|
+
* Converts a `TTL` (max-age) value into seconds, and returns `0` for bad
|
|
118
|
+
* and/or negative input values.
|
|
119
|
+
*
|
|
120
|
+
* @see https://github.com/reykjavikcity/webtools/tree/v0.1#tosec-ttl-helper
|
|
121
|
+
*/
|
|
116
122
|
const toSec = (ttl) => {
|
|
117
|
-
if (ttl == null) {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
123
|
if (typeof ttl === 'string') {
|
|
121
124
|
const value = parseFloat(ttl);
|
|
122
125
|
const factor = unitToSeconds[ttl.slice(-1)] || 1;
|
|
123
126
|
ttl = value * factor;
|
|
124
127
|
}
|
|
125
|
-
return
|
|
128
|
+
return Math.max(0, Math.round(ttl)) || 0;
|
|
126
129
|
};
|
|
130
|
+
exports.toSec = toSec;
|
|
127
131
|
const stabilities = {
|
|
128
132
|
revalidate: ', must-revalidate',
|
|
129
133
|
immutable: ', immutable',
|
|
@@ -166,23 +170,22 @@ const cacheControl = (response, ttlCfg, eTag) => {
|
|
|
166
170
|
maxAge = undefined;
|
|
167
171
|
}
|
|
168
172
|
}
|
|
169
|
-
maxAge = toSec(maxAge);
|
|
170
173
|
if (maxAge == null) {
|
|
171
174
|
response.removeHeader('Cache-Control');
|
|
172
175
|
return;
|
|
173
176
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const sIE_ttl = toSec(opts.staleIfError);
|
|
177
|
-
const sIE = sIE_ttl != null ? `, stale-if-error=${sIE_ttl}` : '';
|
|
178
|
-
maxAge = Math.round(maxAge);
|
|
179
|
-
if (maxAge <= 0) {
|
|
177
|
+
maxAge = (0, exports.toSec)(maxAge);
|
|
178
|
+
if (!maxAge) {
|
|
180
179
|
setCC(response, 'no-cache');
|
|
181
180
|
return;
|
|
182
181
|
}
|
|
182
|
+
const sWR_ttl = (0, exports.toSec)(opts.staleWhileRevalidate || 0);
|
|
183
|
+
const sWR = sWR_ttl ? `, stale-while-revalidate=${sWR_ttl}` : '';
|
|
184
|
+
const sIE_ttl = (0, exports.toSec)(opts.staleIfError || 0);
|
|
185
|
+
const sIE = sIE_ttl ? `, stale-if-error=${sIE_ttl}` : '';
|
|
183
186
|
const scope = opts.publ ? 'public' : 'private';
|
|
184
187
|
const stability = (opts.stability && stabilities[opts.stability]) || stabilities.immutable;
|
|
185
|
-
eTag != null && response.setHeader('ETag', eTag);
|
|
186
188
|
setCC(response, `${scope}, max-age=${maxAge + sWR + sIE + stability}`);
|
|
189
|
+
eTag != null && response.setHeader('ETag', eTag);
|
|
187
190
|
};
|
|
188
191
|
exports.cacheControl = cacheControl;
|
package/package.json
CHANGED