From d6763ce09807cca83b80bbcd0f8f056ba0b792e3 Mon Sep 17 00:00:00 2001
From: Katsuyuki Omuro <komuro@fastly.com>
Date: Tue, 22 Oct 2024 16:38:48 +0900
Subject: [PATCH] Define TypeScript types for API surface

---
 types/cache-override.d.ts | 121 ++++++++++++++++++++++++++++++++++++++
 types/globals.d.ts        |  39 ++++++++++++
 2 files changed, 160 insertions(+)

diff --git a/types/cache-override.d.ts b/types/cache-override.d.ts
index f16b516802..0f62a6054e 100644
--- a/types/cache-override.d.ts
+++ b/types/cache-override.d.ts
@@ -98,6 +98,20 @@ declare module 'fastly:cache-override' {
      *
      * See the [Fastly PCI-Compliant Caching and Delivery documentation](https://docs.fastly.com/products/pci-compliant-caching-and-delivery)
      * for details.
+     *
+     * @param {void} [init.onBeforeSend]
+     * Set a [callback function](https://developer.mozilla.org/en-US/docs/Glossary/Callback_function) to be invoked if a
+     * request is going all the way to a backend, allowing the request to be modified beforehand.
+     *
+     * See [Modifying a request as it is forwarded to a backend](https://www.fastly.com/documentation/guides/concepts/edge-state/cache/#modifying-a-request-as-it-is-forwarded-to-a-backend)
+     * in the Fastly cache interfaces documentation for details.
+     *
+     * @param {void} [init.onAfterSend]
+     * Set a [callback function](https://developer.mozilla.org/en-US/docs/Glossary/Callback_function) to be invoked after
+     * a response has been sent, but before it is stored into the cache.
+     *
+     * See [Controlling cache behavior based on backend response](https://www.fastly.com/documentation/guides/concepts/edge-state/cache/#controlling-cache-behavior-based-on-backend-response)
+     * in the Fastly cache interfaces documentation for details.
      */
     constructor(
       mode: 'none' | 'pass' | 'override',
@@ -106,6 +120,8 @@ declare module 'fastly:cache-override' {
         swr?: number;
         surrogateKey?: string;
         pci?: boolean;
+        onBeforeSend?: (request: Request) => void | PromiseLike<void>;
+        onAfterSend?: (candidateResponse: CandidateResponse) => void | PromiseLike<void>;
       },
     );
 
@@ -147,4 +163,109 @@ declare module 'fastly:cache-override' {
      */
     public pci?: boolean;
   }
+
+  /**
+   * Represents a response from the backend fetched through the readthrough cache interface before it is potentially
+   * stored into the cache. It contains interfaces to read and manipulate headers and cache policy, and a
+   * `bodyTransform` may be set allowing the body to be modified before it is potentially stored.
+   *
+   * If the backend response had a 304 Not Modified status, the `CandidateResponse`
+   * will have status matching the original response, headers corresponding to the
+   * original response updated with the 304 response headers, and will be marked to
+   * revalidate the cache only (i.e., not alter the stored body).
+   */
+  interface CandidateResponse {
+    /**
+     * Get the HTTP headers of the response. Use this object to manipulate the response's
+     * headers.
+     */
+    readonly headers: Headers;
+
+    /* version: string; // HTTP Version */
+
+    /**
+     * Get or set the HTTP status code of the response.
+     */
+    status: number;
+
+    /**
+     * Get or set the Time to Live (TTL) in the cache for this response.
+     */
+    ttl: number;
+
+    /**
+     * The current age of the cached item, relative to the originating backend.
+     */
+    readonly age: number;
+
+    /**
+     * Get or set the time for which a cached item can safely be used after being considered stale.
+     */
+    swr: number;
+
+    /**
+     * Determines whether the cached response is stale.
+     *
+     * A cached response is stale if it has been in the cache beyond its TTL period.
+     */
+    readonly isStale: boolean;
+
+    /**
+     * Get or set the set of request headers for which the response may vary.
+     */
+    vary: Set<string>;
+
+    /**
+     * Get or set the surrogate keys for the cached response.
+     */
+    surrogateKeys: Set<string>;
+
+    /**
+     * Get or set whether this response should only be stored via PCI/HIPAA-compliant non-volatile caching.
+     *
+     * See the [Fastly PCI-Compliant Caching and Delivery documentation](https://docs.fastly.com/products/pci-compliant-caching-and-delivery)
+     * for details.
+     */
+    pci: boolean;
+
+    /**
+     * Determines whether this response should be cached.
+     */
+    readonly isCacheable: boolean;
+
+    /**
+     * Force this response to be stored in the cache, even if its headers or status would normally prevent that.
+     */
+    setCacheable(): void;
+
+    /**
+     * Set the response to not be stored in the cache.
+     *
+     * @param {boolean} recordUncacheable (optional) If true, the cache will record that the originating request
+     * led to an uncacheable response, so that future cache lookups will result in immediately going to the
+     * backend, rather than attempting to coordinate concurrent requests to reduce backend traffic.
+     *
+     * See the [Fastly request collapsing guide](https://www.fastly.com/documentation/guides/concepts/edge-state/cache/request-collapsing/)
+     * for more details on the mechanism that `recordUncacheable` disables.
+     */
+    setUncacheable(recordUncacheable?: boolean): void;
+
+    /**
+     * Get or set a [TransformStream](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream) to be used for
+     * transforming the response body prior to caching.
+     *
+     * Body transformations are performed by specifying a transform, rather than by directly working with the body
+     * during the onAfterSend callback function, because not every response contains a fresh body:
+     * 304 Not Modified responses, which are used to revalidate a stale cached response, are valuable precisely because
+     * they do not retransmit the body.
+     *
+     * For any other response status, the backend response will contain a relevant body, and the `bodyTransform` will
+     * be applied to it. The original backend body is piped to the [`writeable`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream/writable)
+     * end of the transform, and transform is responsible for writing the new body, which will be read out from the
+     * [`readable`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream/readable) end of the transform.
+     * This setup allows the transform to work with streamed chunks of the backend body, rather
+     * than necessarily reading it entirely into memory.
+     */
+    bodyTransform?: TransformStream<Uint8Array, Uint8Array>;
+  }
 }
diff --git a/types/globals.d.ts b/types/globals.d.ts
index aed21792ef..b0b2647dba 100644
--- a/types/globals.d.ts
+++ b/types/globals.d.ts
@@ -1332,6 +1332,45 @@ interface Response extends Body {
    * Set cacheOverride: new CacheOverride("pass") to ensure a value.
    */
   readonly port: number | undefined;
+  /**
+   * Fastly-specific property - Returns whether the `Response` resulted from a cache hit.
+   * For request collapsing, typically one response will show as a miss, and the others
+   * (that awaited that response) will show as hits.
+   */
+  readonly wasCached: boolean;
+  /**
+   * Fastly-specific property - Get the Time to Live (TTL) in the cache for this response, if it is cached.
+   *
+   * The TTL determines the duration of "freshness" for the cached response
+   * after it is inserted into the cache.
+   *
+   * Undefined if the response is not cached.
+   */
+  readonly ttl?: number;
+  /**
+   * Fastly-specific property - The current age of the response, if it is cached.
+   *
+   * Undefined if the response is not cached.
+   */
+  readonly age?: number;
+  /**
+   * Fastly-specific property - The time for which the response can safely be used despite being considered stale, if it is cached.
+   *
+   * Undefined if the response is not cached.
+   */
+  readonly swr?: number;
+  /**
+   * Fastly-specific property - The set of request headers for which the response may vary.
+   *
+   * Undefined if the response is not cached.
+   */
+  readonly vary?: Set<string>;
+  /**
+   * Fastly-specific property - The surrogate keys for the cached response.
+   *
+   * Undefined if the response is not cached.
+   */
+  readonly surrogateKeys?: Set<string>;
   // clone(): Response;
   setManualFramingHeaders(manual: boolean): void;
   /**