construct-hub 0.4.406 → 0.4.407

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/.jsii CHANGED
@@ -20923,6 +20923,6 @@
20923
20923
  "symbolId": "src/package-sources/npmjs:NpmJsProps"
20924
20924
  }
20925
20925
  },
20926
- "version": "0.4.406",
20927
- "fingerprint": "5379+UKO8y9O52KgeTHqS82hUautprL/GZzSVEbKEzI="
20926
+ "version": "0.4.407",
20927
+ "fingerprint": "Olo02dJRKQdfX2Qi6ClG7C6TzZQF99FL4ZR3TcdJjho="
20928
20928
  }
@@ -36820,6 +36820,17 @@ var require_http_cache_semantics = __commonJS({
36820
36820
  return parts.join(", ");
36821
36821
  }
36822
36822
  module2.exports = class CachePolicy {
36823
+ /**
36824
+ * Creates a new CachePolicy instance.
36825
+ * @param {HttpRequest} req - Incoming client request.
36826
+ * @param {HttpResponse} res - Received server response.
36827
+ * @param {Object} [options={}] - Configuration options.
36828
+ * @param {boolean} [options.shared=true] - Is the cache shared (a public proxy)? `false` for personal browser caches.
36829
+ * @param {number} [options.cacheHeuristic=0.1] - Fallback heuristic (age fraction) for cache duration.
36830
+ * @param {number} [options.immutableMinTimeToLive=86400000] - Minimum TTL for immutable responses in milliseconds.
36831
+ * @param {boolean} [options.ignoreCargoCult=false] - Detect nonsense cache headers, and override them.
36832
+ * @param {any} [options._fromObject] - Internal parameter for deserialization. Do not use.
36833
+ */
36823
36834
  constructor(req, res, {
36824
36835
  shared,
36825
36836
  cacheHeuristic,
@@ -36837,6 +36848,7 @@ var require_http_cache_semantics = __commonJS({
36837
36848
  this._assertRequestHasHeaders(req);
36838
36849
  this._responseTime = this.now();
36839
36850
  this._isShared = shared !== false;
36851
+ this._ignoreCargoCult = !!ignoreCargoCult;
36840
36852
  this._cacheHeuristic = void 0 !== cacheHeuristic ? cacheHeuristic : 0.1;
36841
36853
  this._immutableMinTtl = void 0 !== immutableMinTimeToLive ? immutableMinTimeToLive : 24 * 3600 * 1e3;
36842
36854
  this._status = "status" in res ? res.status : 200;
@@ -36848,7 +36860,7 @@ var require_http_cache_semantics = __commonJS({
36848
36860
  this._noAuthorization = !req.headers.authorization;
36849
36861
  this._reqHeaders = res.headers.vary ? req.headers : null;
36850
36862
  this._reqcc = parseCacheControl(req.headers["cache-control"]);
36851
- if (ignoreCargoCult && "pre-check" in this._rescc && "post-check" in this._rescc) {
36863
+ if (this._ignoreCargoCult && "pre-check" in this._rescc && "post-check" in this._rescc) {
36852
36864
  delete this._rescc["pre-check"];
36853
36865
  delete this._rescc["post-check"];
36854
36866
  delete this._rescc["no-cache"];
@@ -36864,9 +36876,17 @@ var require_http_cache_semantics = __commonJS({
36864
36876
  this._rescc["no-cache"] = true;
36865
36877
  }
36866
36878
  }
36879
+ /**
36880
+ * You can monkey-patch it for testing.
36881
+ * @returns {number} Current time in milliseconds.
36882
+ */
36867
36883
  now() {
36868
36884
  return Date.now();
36869
36885
  }
36886
+ /**
36887
+ * Determines if the response is storable in a cache.
36888
+ * @returns {boolean} `false` if can never be cached.
36889
+ */
36870
36890
  storable() {
36871
36891
  return !!(!this._reqcc["no-store"] && // A cache MUST NOT store a response to any request, unless:
36872
36892
  // The request method is understood by the cache and defined as being cacheable, and
@@ -36882,42 +36902,142 @@ var require_http_cache_semantics = __commonJS({
36882
36902
  this._rescc["max-age"] || this._isShared && this._rescc["s-maxage"] || this._rescc.public || // has a status code that is defined as cacheable by default
36883
36903
  statusCodeCacheableByDefault.has(this._status)));
36884
36904
  }
36905
+ /**
36906
+ * @returns {boolean} true if expiration is explicitly defined.
36907
+ */
36885
36908
  _hasExplicitExpiration() {
36886
- return this._isShared && this._rescc["s-maxage"] || this._rescc["max-age"] || this._resHeaders.expires;
36909
+ return !!(this._isShared && this._rescc["s-maxage"] || this._rescc["max-age"] || this._resHeaders.expires);
36887
36910
  }
36911
+ /**
36912
+ * @param {HttpRequest} req - a request
36913
+ * @throws {Error} if the headers are missing.
36914
+ */
36888
36915
  _assertRequestHasHeaders(req) {
36889
36916
  if (!req || !req.headers) {
36890
36917
  throw Error("Request headers missing");
36891
36918
  }
36892
36919
  }
36920
+ /**
36921
+ * Checks if the request matches the cache and can be satisfied from the cache immediately,
36922
+ * without having to make a request to the server.
36923
+ *
36924
+ * This doesn't support `stale-while-revalidate`. See `evaluateRequest()` for a more complete solution.
36925
+ *
36926
+ * @param {HttpRequest} req - The new incoming HTTP request.
36927
+ * @returns {boolean} `true`` if the cached response used to construct this cache policy satisfies the request without revalidation.
36928
+ */
36893
36929
  satisfiesWithoutRevalidation(req) {
36930
+ const result = this.evaluateRequest(req);
36931
+ return !result.revalidation;
36932
+ }
36933
+ /**
36934
+ * @param {{headers: Record<string, string>, synchronous: boolean}|undefined} revalidation - Revalidation information, if any.
36935
+ * @returns {{response: {headers: Record<string, string>}, revalidation: {headers: Record<string, string>, synchronous: boolean}|undefined}} An object with a cached response headers and revalidation info.
36936
+ */
36937
+ _evaluateRequestHitResult(revalidation) {
36938
+ return {
36939
+ response: {
36940
+ headers: this.responseHeaders()
36941
+ },
36942
+ revalidation
36943
+ };
36944
+ }
36945
+ /**
36946
+ * @param {HttpRequest} request - new incoming
36947
+ * @param {boolean} synchronous - whether revalidation must be synchronous (not s-w-r).
36948
+ * @returns {{headers: Record<string, string>, synchronous: boolean}} An object with revalidation headers and a synchronous flag.
36949
+ */
36950
+ _evaluateRequestRevalidation(request, synchronous) {
36951
+ return {
36952
+ synchronous,
36953
+ headers: this.revalidationHeaders(request)
36954
+ };
36955
+ }
36956
+ /**
36957
+ * @param {HttpRequest} request - new incoming
36958
+ * @returns {{response: undefined, revalidation: {headers: Record<string, string>, synchronous: boolean}}} An object indicating no cached response and revalidation details.
36959
+ */
36960
+ _evaluateRequestMissResult(request) {
36961
+ return {
36962
+ response: void 0,
36963
+ revalidation: this._evaluateRequestRevalidation(request, true)
36964
+ };
36965
+ }
36966
+ /**
36967
+ * Checks if the given request matches this cache entry, and how the cache can be used to satisfy it. Returns an object with:
36968
+ *
36969
+ * ```
36970
+ * {
36971
+ * // If defined, you must send a request to the server.
36972
+ * revalidation: {
36973
+ * headers: {}, // HTTP headers to use when sending the revalidation response
36974
+ * // If true, you MUST wait for a response from the server before using the cache
36975
+ * // If false, this is stale-while-revalidate. The cache is stale, but you can use it while you update it asynchronously.
36976
+ * synchronous: bool,
36977
+ * },
36978
+ * // If defined, you can use this cached response.
36979
+ * response: {
36980
+ * headers: {}, // Updated cached HTTP headers you must use when responding to the client
36981
+ * },
36982
+ * }
36983
+ * ```
36984
+ * @param {HttpRequest} req - new incoming HTTP request
36985
+ * @returns {{response: {headers: Record<string, string>}|undefined, revalidation: {headers: Record<string, string>, synchronous: boolean}|undefined}} An object containing keys:
36986
+ * - revalidation: { headers: Record<string, string>, synchronous: boolean } Set if you should send this to the origin server
36987
+ * - response: { headers: Record<string, string> } Set if you can respond to the client with these cached headers
36988
+ */
36989
+ evaluateRequest(req) {
36894
36990
  this._assertRequestHasHeaders(req);
36991
+ if (this._rescc["must-revalidate"]) {
36992
+ return this._evaluateRequestMissResult(req);
36993
+ }
36994
+ if (!this._requestMatches(req, false)) {
36995
+ return this._evaluateRequestMissResult(req);
36996
+ }
36895
36997
  const requestCC = parseCacheControl(req.headers["cache-control"]);
36896
36998
  if (requestCC["no-cache"] || /no-cache/.test(req.headers.pragma)) {
36897
- return false;
36999
+ return this._evaluateRequestMissResult(req);
36898
37000
  }
36899
- if (requestCC["max-age"] && this.age() > requestCC["max-age"]) {
36900
- return false;
37001
+ if (requestCC["max-age"] && this.age() > toNumberOrZero(requestCC["max-age"])) {
37002
+ return this._evaluateRequestMissResult(req);
36901
37003
  }
36902
- if (requestCC["min-fresh"] && this.timeToLive() < 1e3 * requestCC["min-fresh"]) {
36903
- return false;
37004
+ if (requestCC["min-fresh"] && this.maxAge() - this.age() < toNumberOrZero(requestCC["min-fresh"])) {
37005
+ return this._evaluateRequestMissResult(req);
36904
37006
  }
36905
37007
  if (this.stale()) {
36906
- const allowsStale = requestCC["max-stale"] && !this._rescc["must-revalidate"] && (true === requestCC["max-stale"] || requestCC["max-stale"] > this.age() - this.maxAge());
36907
- if (!allowsStale) {
36908
- return false;
37008
+ const allowsStaleWithoutRevalidation = "max-stale" in requestCC && (true === requestCC["max-stale"] || requestCC["max-stale"] > this.age() - this.maxAge());
37009
+ if (allowsStaleWithoutRevalidation) {
37010
+ return this._evaluateRequestHitResult(void 0);
37011
+ }
37012
+ if (this.useStaleWhileRevalidate()) {
37013
+ return this._evaluateRequestHitResult(this._evaluateRequestRevalidation(req, false));
36909
37014
  }
37015
+ return this._evaluateRequestMissResult(req);
36910
37016
  }
36911
- return this._requestMatches(req, false);
37017
+ return this._evaluateRequestHitResult(void 0);
36912
37018
  }
37019
+ /**
37020
+ * @param {HttpRequest} req - check if this is for the same cache entry
37021
+ * @param {boolean} allowHeadMethod - allow a HEAD method to match.
37022
+ * @returns {boolean} `true` if the request matches.
37023
+ */
36913
37024
  _requestMatches(req, allowHeadMethod) {
36914
- return (!this._url || this._url === req.url) && this._host === req.headers.host && // the request method associated with the stored response allows it to be used for the presented request, and
37025
+ return !!((!this._url || this._url === req.url) && this._host === req.headers.host && // the request method associated with the stored response allows it to be used for the presented request, and
36915
37026
  (!req.method || this._method === req.method || allowHeadMethod && "HEAD" === req.method) && // selecting header fields nominated by the stored response (if any) match those presented, and
36916
- this._varyMatches(req);
37027
+ this._varyMatches(req));
36917
37028
  }
37029
+ /**
37030
+ * Determines whether storing authenticated responses is allowed.
37031
+ * @returns {boolean} `true` if allowed.
37032
+ */
36918
37033
  _allowsStoringAuthenticated() {
36919
- return this._rescc["must-revalidate"] || this._rescc.public || this._rescc["s-maxage"];
37034
+ return !!(this._rescc["must-revalidate"] || this._rescc.public || this._rescc["s-maxage"]);
36920
37035
  }
37036
+ /**
37037
+ * Checks whether the Vary header in the response matches the new request.
37038
+ * @param {HttpRequest} req - incoming HTTP request
37039
+ * @returns {boolean} `true` if the vary headers match.
37040
+ */
36921
37041
  _varyMatches(req) {
36922
37042
  if (!this._resHeaders.vary) {
36923
37043
  return true;
@@ -36931,6 +37051,11 @@ var require_http_cache_semantics = __commonJS({
36931
37051
  }
36932
37052
  return true;
36933
37053
  }
37054
+ /**
37055
+ * Creates a copy of the given headers without any hop-by-hop headers.
37056
+ * @param {Record<string, string>} inHeaders - old headers from the cached response
37057
+ * @returns {Record<string, string>} A new headers object without hop-by-hop headers.
37058
+ */
36934
37059
  _copyWithoutHopByHopHeaders(inHeaders) {
36935
37060
  const headers = {};
36936
37061
  for (const name in inHeaders) {
@@ -36955,6 +37080,11 @@ var require_http_cache_semantics = __commonJS({
36955
37080
  }
36956
37081
  return headers;
36957
37082
  }
37083
+ /**
37084
+ * Returns the response headers adjusted for serving the cached response.
37085
+ * Removes hop-by-hop headers and updates the Age and Date headers.
37086
+ * @returns {Record<string, string>} The adjusted response headers.
37087
+ */
36958
37088
  responseHeaders() {
36959
37089
  const headers = this._copyWithoutHopByHopHeaders(this._resHeaders);
36960
37090
  const age = this.age();
@@ -36966,8 +37096,8 @@ var require_http_cache_semantics = __commonJS({
36966
37096
  return headers;
36967
37097
  }
36968
37098
  /**
36969
- * Value of the Date response header or current time if Date was invalid
36970
- * @return timestamp
37099
+ * Returns the Date header value from the response or the current time if invalid.
37100
+ * @returns {number} Timestamp (in milliseconds) representing the Date header or response time.
36971
37101
  */
36972
37102
  date() {
36973
37103
  const serverDate = Date.parse(this._resHeaders.date);
@@ -36979,23 +37109,27 @@ var require_http_cache_semantics = __commonJS({
36979
37109
  /**
36980
37110
  * Value of the Age header, in seconds, updated for the current time.
36981
37111
  * May be fractional.
36982
- *
36983
- * @return Number
37112
+ * @returns {number} The age in seconds.
36984
37113
  */
36985
37114
  age() {
36986
37115
  let age = this._ageValue();
36987
37116
  const residentTime = (this.now() - this._responseTime) / 1e3;
36988
37117
  return age + residentTime;
36989
37118
  }
37119
+ /**
37120
+ * @returns {number} The Age header value as a number.
37121
+ */
36990
37122
  _ageValue() {
36991
37123
  return toNumberOrZero(this._resHeaders.age);
36992
37124
  }
36993
37125
  /**
36994
- * Value of applicable max-age (or heuristic equivalent) in seconds. This counts since response's `Date`.
37126
+ * Possibly outdated value of applicable max-age (or heuristic equivalent) in seconds.
37127
+ * This counts since response's `Date`.
36995
37128
  *
36996
37129
  * For an up-to-date value, see `timeToLive()`.
36997
37130
  *
36998
- * @return Number
37131
+ * Returns the maximum age (freshness lifetime) of the response in seconds.
37132
+ * @returns {number} The max-age value in seconds.
36999
37133
  */
37000
37134
  maxAge() {
37001
37135
  if (!this.storable() || this._rescc["no-cache"]) {
@@ -37038,24 +37172,52 @@ var require_http_cache_semantics = __commonJS({
37038
37172
  }
37039
37173
  return defaultMinTtl;
37040
37174
  }
37175
+ /**
37176
+ * Remaining time this cache entry may be useful for, in *milliseconds*.
37177
+ * You can use this as an expiration time for your cache storage.
37178
+ *
37179
+ * Prefer this method over `maxAge()`, because it includes other factors like `age` and `stale-while-revalidate`.
37180
+ * @returns {number} Time-to-live in milliseconds.
37181
+ */
37041
37182
  timeToLive() {
37042
37183
  const age = this.maxAge() - this.age();
37043
37184
  const staleIfErrorAge = age + toNumberOrZero(this._rescc["stale-if-error"]);
37044
37185
  const staleWhileRevalidateAge = age + toNumberOrZero(this._rescc["stale-while-revalidate"]);
37045
- return Math.max(0, age, staleIfErrorAge, staleWhileRevalidateAge) * 1e3;
37186
+ return Math.round(Math.max(0, age, staleIfErrorAge, staleWhileRevalidateAge) * 1e3);
37046
37187
  }
37188
+ /**
37189
+ * If true, this cache entry is past its expiration date.
37190
+ * Note that stale cache may be useful sometimes, see `evaluateRequest()`.
37191
+ * @returns {boolean} `false` doesn't mean it's fresh nor usable
37192
+ */
37047
37193
  stale() {
37048
37194
  return this.maxAge() <= this.age();
37049
37195
  }
37196
+ /**
37197
+ * @returns {boolean} `true` if `stale-if-error` condition allows use of a stale response.
37198
+ */
37050
37199
  _useStaleIfError() {
37051
37200
  return this.maxAge() + toNumberOrZero(this._rescc["stale-if-error"]) > this.age();
37052
37201
  }
37202
+ /** See `evaluateRequest()` for a more complete solution
37203
+ * @returns {boolean} `true` if `stale-while-revalidate` is currently allowed.
37204
+ */
37053
37205
  useStaleWhileRevalidate() {
37054
- return this.maxAge() + toNumberOrZero(this._rescc["stale-while-revalidate"]) > this.age();
37206
+ const swr = toNumberOrZero(this._rescc["stale-while-revalidate"]);
37207
+ return swr > 0 && this.maxAge() + swr > this.age();
37055
37208
  }
37209
+ /**
37210
+ * Creates a `CachePolicy` instance from a serialized object.
37211
+ * @param {Object} obj - The serialized object.
37212
+ * @returns {CachePolicy} A new CachePolicy instance.
37213
+ */
37056
37214
  static fromObject(obj) {
37057
37215
  return new this(void 0, void 0, { _fromObject: obj });
37058
37216
  }
37217
+ /**
37218
+ * @param {any} obj - The serialized object.
37219
+ * @throws {Error} If already initialized or if the object is invalid.
37220
+ */
37059
37221
  _fromObject(obj) {
37060
37222
  if (this._responseTime) throw Error("Reinitialized");
37061
37223
  if (!obj || obj.v !== 1) throw Error("Invalid serialization");
@@ -37063,6 +37225,7 @@ var require_http_cache_semantics = __commonJS({
37063
37225
  this._isShared = obj.sh;
37064
37226
  this._cacheHeuristic = obj.ch;
37065
37227
  this._immutableMinTtl = obj.imm !== void 0 ? obj.imm : 24 * 3600 * 1e3;
37228
+ this._ignoreCargoCult = !!obj.icc;
37066
37229
  this._status = obj.st;
37067
37230
  this._resHeaders = obj.resh;
37068
37231
  this._rescc = obj.rescc;
@@ -37073,6 +37236,10 @@ var require_http_cache_semantics = __commonJS({
37073
37236
  this._reqHeaders = obj.reqh;
37074
37237
  this._reqcc = obj.reqcc;
37075
37238
  }
37239
+ /**
37240
+ * Serializes the `CachePolicy` instance into a JSON-serializable object.
37241
+ * @returns {Object} The serialized object.
37242
+ */
37076
37243
  toObject() {
37077
37244
  return {
37078
37245
  v: 1,
@@ -37080,6 +37247,7 @@ var require_http_cache_semantics = __commonJS({
37080
37247
  sh: this._isShared,
37081
37248
  ch: this._cacheHeuristic,
37082
37249
  imm: this._immutableMinTtl,
37250
+ icc: this._ignoreCargoCult,
37083
37251
  st: this._status,
37084
37252
  resh: this._resHeaders,
37085
37253
  rescc: this._rescc,
@@ -37097,6 +37265,8 @@ var require_http_cache_semantics = __commonJS({
37097
37265
  *
37098
37266
  * Hop by hop headers are always stripped.
37099
37267
  * Revalidation headers may be added or removed, depending on request.
37268
+ * @param {HttpRequest} incomingReq - The incoming HTTP request.
37269
+ * @returns {Record<string, string>} The headers for the revalidation request.
37100
37270
  */
37101
37271
  revalidationHeaders(incomingReq) {
37102
37272
  this._assertRequestHasHeaders(incomingReq);
@@ -37135,15 +37305,18 @@ var require_http_cache_semantics = __commonJS({
37135
37305
  * Returns {policy, modified} where modified is a boolean indicating
37136
37306
  * whether the response body has been modified, and old cached body can't be used.
37137
37307
  *
37138
- * @return {Object} {policy: CachePolicy, modified: Boolean}
37308
+ * @param {HttpRequest} request - The latest HTTP request asking for the cached entry.
37309
+ * @param {HttpResponse} response - The latest revalidation HTTP response from the origin server.
37310
+ * @returns {{policy: CachePolicy, modified: boolean, matches: boolean}} The updated policy and modification status.
37311
+ * @throws {Error} If the response headers are missing.
37139
37312
  */
37140
37313
  revalidatedPolicy(request, response) {
37141
37314
  this._assertRequestHasHeaders(request);
37142
37315
  if (this._useStaleIfError() && isErrorResponse(response)) {
37143
37316
  return {
37317
+ policy: this,
37144
37318
  modified: false,
37145
- matches: false,
37146
- policy: this
37319
+ matches: true
37147
37320
  };
37148
37321
  }
37149
37322
  if (!response || !response.headers) {
@@ -37163,9 +37336,15 @@ var require_http_cache_semantics = __commonJS({
37163
37336
  matches = true;
37164
37337
  }
37165
37338
  }
37339
+ const optionsCopy = {
37340
+ shared: this._isShared,
37341
+ cacheHeuristic: this._cacheHeuristic,
37342
+ immutableMinTimeToLive: this._immutableMinTtl,
37343
+ ignoreCargoCult: this._ignoreCargoCult
37344
+ };
37166
37345
  if (!matches) {
37167
37346
  return {
37168
- policy: new this.constructor(request, response),
37347
+ policy: new this.constructor(request, response, optionsCopy),
37169
37348
  // Client receiving 304 without body, even if it's invalid/mismatched has no option
37170
37349
  // but to reuse a cached body. We don't have a good way to tell clients to do
37171
37350
  // error recovery in such case.
@@ -37183,11 +37362,7 @@ var require_http_cache_semantics = __commonJS({
37183
37362
  headers
37184
37363
  });
37185
37364
  return {
37186
- policy: new this.constructor(request, newResponse, {
37187
- shared: this._isShared,
37188
- cacheHeuristic: this._cacheHeuristic,
37189
- immutableMinTimeToLive: this._immutableMinTtl
37190
- }),
37365
+ policy: new this.constructor(request, newResponse, optionsCopy),
37191
37366
  modified: false,
37192
37367
  matches: true
37193
37368
  };