Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | 5x 5x 7x 5x 3x 5x 2x 2x 2x 2x 1x 1x 1x 1x 1x 12x 1x 1x 5x 1x 1x 1x 3x | // Cloudflare Cache API helpers for edge-level response caching.
// The Cache API (`caches.default`) stores Response objects at the edge CDN.
// Unlike KV or D1, cached responses are served before the Worker executes.
//
// IMPORTANT: The Cache API is only available in production Cloudflare Workers.
// In local dev (`wrangler dev --local`) and tests, `caches` is undefined.
// All helpers gracefully degrade to no-ops in those environments.
/**
* Detect local development: wrangler dev now provides `caches` but we
* don't want edge caching to hide fresh data during development.
* In production, the Worker URL uses the real domain (e.g. api.interioring.com).
* In local dev, it uses localhost or 127.0.0.1.
*/
function isLocalDev(request?: Request): boolean {
/* v8 ignore start -- V8 artifact: callers always pass request */
if (!request) return false;
/* v8 ignore stop */
const url = new URL(request.url);
return (
url.hostname === "localhost" || url.hostname === "127.0.0.1"
);
}
/**
* Check if the Cache API is available and should be used.
* Disabled in local dev to ensure fresh data during development.
*/
function isCacheAvailable(request?: Request): boolean {
if (typeof caches === "undefined") return false;
if (request && isLocalDev(request)) return false;
return true;
}
/**
* Attempt to retrieve a cached response from the Cloudflare edge cache.
* Returns null if the Cache API is unavailable, in local dev, or no match found.
*/
export async function getEdgeCachedResponse(
request: Request,
): Promise<Response | null> {
if (!isCacheAvailable(request)) return null;
const cache = caches.default;
const match = await cache.match(request);
return match ?? null;
}
/**
* Store a response in the Cloudflare edge cache with the given TTL (seconds).
* The response is cloned with an explicit Cache-Control header so the edge
* knows how long to keep it. No-op in local dev.
*/
export async function putEdgeCacheResponse(
request: Request,
response: Response,
ttl: number,
): Promise<void> {
if (!isCacheAvailable(request)) return;
const cache = caches.default;
const headers = new Headers(response.headers);
headers.set("Cache-Control", `public, max-age=${ttl}`);
const cached = new Response(response.body, {
status: response.status,
headers,
});
await cache.put(request, cached);
}
/**
* Purge a single URL from the Cloudflare edge cache.
* Useful when pro data changes and stale marketplace responses
* should be evicted. No-op in local dev.
*/
export async function purgeEdgeCache(url: string): Promise<void> {
if (typeof caches === "undefined") return;
const cache = caches.default;
await cache.delete(new Request(url));
}
/**
* Purge all marketplace-related edge cache entries for a given base URL.
* Clears the main list endpoints that are most likely stale after a pro
* or project change.
*/
export async function purgeMarketplaceCache(baseUrl: string): Promise<void> {
if (typeof caches === "undefined") return;
const cache = caches.default;
// Purge known high-traffic list endpoints
const paths = ["/api/marketplace/pros", "/api/marketplace/projects", "/api/marketplace/blogs"];
await Promise.all(
paths.map((path) => cache.delete(new Request(`${baseUrl}${path}`))),
);
}
|