@cf-wasm/og
Version:
Generate Open Graph Images dynamically from HTML/CSS without a browser.
121 lines (120 loc) • 4.16 kB
JavaScript
const require_maps = require("./maps.cjs");
//#region src/core/cache.ts
/** Cache instance map */
const CACHE_INSTANCE_MAP = /* @__PURE__ */ new Map();
/** A Cache like no-op object */
const CACHE_INTERFACE = {
add: () => Promise.resolve(),
addAll: () => Promise.resolve(),
delete: () => Promise.resolve(false),
keys: () => Promise.resolve([]),
match: () => Promise.resolve(void 0),
matchAll: () => Promise.resolve([]),
put: () => Promise.resolve()
};
/** Cache utils */
var CacheUtils = class {
constructor() {
this._enabled = true;
this.store = "cf-wasm-og-cache";
this.cacheControlHeader = "public, max-age=604800, s-maxage=43200";
}
/**
* Indicates whether {@link Cache} api is supported
* in current environment or not
*/
get supported() {
return typeof caches !== "undefined";
}
/** Enables cache */
enable() {
this._enabled = true;
}
/** Disables cache */
disable() {
this._enabled = false;
}
/**
* Sets execution context
*
* Example for Cloudflare workers:
*
* ```ts
* import { cache } from "@cf-wasm/og";
*
* export interface Env {}
*
* export default {
* fetch(req: Request, env: Env, ctx: ExecutionContext) {
* cache.setExecutionContext(ctx);
*
* // ...
* }
* }
* ```
*/
setExecutionContext(ctx) {
if (typeof ctx?.waitUntil !== "function") throw new TypeError("Provided object is not an execution context object.");
this._waitUntil = (promise) => ctx.waitUntil(promise);
}
/**
* Opens a cache
*
* @param cacheName If provided, the name of cache to be opened
*
* @returns A promise which resolves to {@link Cache}
*/
async open(cacheName) {
if (typeof this.store === "object") return this.store;
const name = typeof cacheName === "string" ? cacheName : this.store;
const store = this.supported ? CACHE_INSTANCE_MAP.get(name) ?? await caches.open(name) : CACHE_INTERFACE;
CACHE_INSTANCE_MAP.set(name, store);
return store;
}
/**
* Serve cached assets
*
* @param key The cache key
* @param fallback The fallback function which provides the {@link Response} when cache key is not matched
* @param param2 Options
*
* @returns A promise which resolves to {@link Response}
*/
async serve(key, fallback, { cache: cacheStore, preserveHeaders, overwriteCacheControl = true } = {}) {
const store = cacheStore ?? await this.open();
let response;
if (!this._enabled || !this.supported || !this._waitUntil) {
const fallbackResponse = await fallback(key, store);
if (fallbackResponse instanceof Response) response = new Response(fallbackResponse.body, fallbackResponse);
} else {
response = await store.match(key).then((res) => res?.ok ? res : void 0);
if (!response) {
const fallbackResponse = await fallback(key, store);
if (fallbackResponse instanceof Response) {
response = new Response(fallbackResponse.body, fallbackResponse);
if (preserveHeaders !== true) response.headers.forEach((value, _key) => {
if (preserveHeaders === false) response?.headers.delete(_key);
else if (typeof preserveHeaders === "function" && !preserveHeaders(_key, value, response, store, key)) response?.headers.delete(_key);
else if (!(Array.isArray(preserveHeaders) ? preserveHeaders : ["content-type", "cache-control"]).map((e) => e.toLowerCase()).includes(_key.toLowerCase())) response?.headers.delete(_key);
});
if (overwriteCacheControl === true || typeof overwriteCacheControl === "string" || !response.headers.has("Cache-Control")) response.headers.set("Cache-Control", typeof overwriteCacheControl === "string" ? overwriteCacheControl : this.cacheControlHeader);
const promise = store.put(key, response.clone());
this._waitUntil(promise);
}
} else response = new Response(response.body, response);
}
return response;
}
clearMaps() {
require_maps.ASSET_CACHE_MAP.clear();
CACHE_INSTANCE_MAP.clear();
require_maps.EMOJI_CACHE_MAP.clear();
require_maps.FONT_CACHE_MAP.clear();
}
};
const cache = new CacheUtils();
//#endregion
exports.CACHE_INSTANCE_MAP = CACHE_INSTANCE_MAP;
exports.CACHE_INTERFACE = CACHE_INTERFACE;
exports.cache = cache;
//# sourceMappingURL=cache.cjs.map