UNPKG

@solomonai/cache

Version:

<div align="center"> <h1 align="center">@solomonai/cache</h1> <h5>Cache all the things</h5> </div>

1 lines 20.3 kB
{"version":3,"sources":["../src/errors.ts","../src/stores/cloudflare.ts","../src/stores/memory.ts","../src/stores/upstash-redis.ts","../src/stores/libsql.ts"],"names":["Ok","key"],"mappings":"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","file":"stores.mjs","sourcesContent":["import { BaseError } from \"@unkey/error\";\n\nexport class CacheError extends BaseError {\n public readonly name = \"CacheError\";\n public readonly retry = false;\n\n public readonly tier: string;\n public readonly key: string;\n\n constructor(opts: {\n tier: string;\n key: string;\n message: string;\n }) {\n super(opts);\n this.name = \"CacheError\";\n this.tier = opts.tier;\n this.key = opts.key;\n }\n}\n","import { Err, Ok, type Result } from \"@unkey/error\";\nimport superjson from \"superjson\";\nimport { CacheError } from \"../errors\";\nimport type { Entry, Store } from \"./interface\";\n\nexport type CloudflareStoreConfig = {\n domain: string;\n zoneId: string;\n /**\n * This token must have at least\n */\n cloudflareApiKey: string;\n\n /**\n * As your data changes, it is important to keep backwards compatibility in mind. If your cached\n * values are no longer backwards compatible, it can cause problems. For example when a value\n * changes from optional to required. In these cases you should purge the entire cache by setting\n * a new `cacheBuster` value. The `cacheBuster` is used as part of the cache key and changes\n * ensure you are not reading old data anymore.\n *\n * @default \"v1\"\n */\n cacheBuster?: string;\n};\n\nexport class CloudflareStore<TNamespace extends string, TValue = any>\n implements Store<TNamespace, TValue>\n{\n private readonly config: CloudflareStoreConfig;\n public readonly name = \"cloudflare\";\n\n constructor(config: CloudflareStoreConfig) {\n this.config = config;\n }\n\n private createCacheKey(namespace: TNamespace, key: string): URL {\n return new URL(\n `https://${this.config.domain}/cache/${this.config.cacheBuster ?? \"v1\"}/${String(\n namespace,\n )}/${key}`,\n );\n }\n\n public async get(\n namespace: TNamespace,\n key: string,\n ): Promise<Result<Entry<TValue> | undefined, CacheError>> {\n let res: Response;\n try {\n // @ts-expect-error I don't know why this is not working\n res = await caches.default.match(new Request(this.createCacheKey(namespace, key)));\n } catch (err) {\n return Err(\n new CacheError({\n tier: this.name,\n key,\n message: (err as Error).message,\n }),\n );\n }\n if (!res) {\n return Ok(undefined);\n }\n const raw = await res.text();\n try {\n const entry = superjson.parse(raw) as Entry<TValue>;\n return Ok(entry);\n } catch (err) {\n return Err(\n new CacheError({\n tier: this.name,\n key,\n message: (err as Error).message,\n }),\n );\n }\n }\n\n public async set(\n namespace: TNamespace,\n key: string,\n entry: Entry<TValue>,\n ): Promise<Result<void, CacheError>> {\n const req = new Request(this.createCacheKey(namespace, key));\n const res = new Response(superjson.stringify(entry), {\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": `public, max-age=${Math.floor(entry.staleUntil / 1000)}`,\n },\n });\n try {\n // @ts-expect-error I don't know why this is not working\n await caches.default.put(req, res);\n return Ok();\n } catch (err) {\n return Err(\n new CacheError({\n tier: this.name,\n key,\n message: (err as Error).message,\n }),\n );\n }\n }\n\n public async remove(\n namespace: TNamespace,\n keys: string | string[],\n ): Promise<Result<void, CacheError>> {\n const cacheKeys = (Array.isArray(keys) ? keys : [keys]).map((key) =>\n this.createCacheKey(namespace, key),\n );\n\n // @ts-expect-error I don't know why this is not working\n await Promise.all(cacheKeys.map((key) => caches.default.delete(key)));\n\n return await fetch(\n `https://api.cloudflare.com/client/v4zones/${this.config.zoneId}/purge_cache`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.config.cloudflareApiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n files: cacheKeys.map((k) => k.toString()),\n }),\n },\n )\n .then((res) => res.body?.cancel())\n .then(() => Ok())\n .catch((err) =>\n Err(\n new CacheError({\n tier: this.name,\n key: keys.toString(),\n message: (err as Error).message,\n }),\n ),\n );\n }\n}\n","import { Ok, type Result } from \"@unkey/error\";\nimport type { CacheError } from \"../errors\";\nimport type { Entry, Store } from \"./interface\";\n\nexport type MemoryStoreConfig<TValue> = {\n /**\n * Remove expired entries on every `set` operation\n *\n * This flag is unstable and may be changed or removed later.\n *\n * ```\n */\n unstableEvictOnSet?: {\n /**\n * Provide a number between 0 and 1 to calculate whether eviction should run on each set.\n * @example\n * ```\n * 1 -> run eviction on every `set`\n * 0.5 -> run eviction on every 2nd `set`\n * 0 or undefined -> disable\n */\n frequency: number;\n\n /**\n * Remove items until the number of items in the map is lower than `maxItems`\n */\n maxItems: number;\n };\n persistentMap: Map<string, TValue>;\n};\n\nexport class MemoryStore<TNamespace extends string, TValue = any>\n implements Store<TNamespace, TValue>\n{\n private readonly state: Map<string, { expires: number; entry: Entry<TValue> }>;\n private readonly unstableEvictOnSet?: { frequency: number; maxItems: number };\n\n public readonly name = \"memory\";\n\n constructor(config: MemoryStoreConfig<{ expires: number; entry: Entry<TValue> }>) {\n this.state = config.persistentMap;\n this.unstableEvictOnSet = config.unstableEvictOnSet;\n }\n\n private buildCacheKey(namespace: TNamespace, key: string): string {\n return [namespace, key].join(\"::\");\n }\n\n public async get(\n namespace: TNamespace,\n key: string,\n ): Promise<Result<Entry<TValue> | undefined, CacheError>> {\n const value = this.state.get(this.buildCacheKey(namespace, key));\n if (!value) {\n return Promise.resolve(Ok(undefined));\n }\n if (value.expires <= Date.now()) {\n await this.remove(namespace, key);\n }\n return Promise.resolve(Ok(value.entry));\n }\n\n public async set(\n namespace: TNamespace,\n key: string,\n entry: Entry<TValue>,\n ): Promise<Result<void, CacheError>> {\n this.state.set(this.buildCacheKey(namespace, key), {\n expires: entry.staleUntil,\n entry,\n });\n\n if (this.unstableEvictOnSet && Math.random() < this.unstableEvictOnSet.frequency) {\n /**\n * First delete all the expired ones\n */\n const now = Date.now();\n this.state.forEach((value, key, map) => {\n if (value.expires < now) {\n map.delete(key);\n }\n });\n\n /**\n * If that's not enough, we delete oldest first\n */\n for (const [k] of this.state) {\n if (this.state.size <= this.unstableEvictOnSet!.maxItems) {\n break;\n }\n\n this.state.delete(k);\n }\n }\n\n return Promise.resolve(Ok());\n }\n\n public async remove(\n namespace: TNamespace,\n keys: string | string[],\n ): Promise<Result<void, CacheError>> {\n const cacheKeys = (Array.isArray(keys) ? keys : [keys]).map((key) =>\n this.buildCacheKey(namespace, key).toString(),\n );\n for (const key of cacheKeys) {\n this.state.delete(key);\n }\n return Promise.resolve(Ok());\n }\n}\n","import { Ok, type Result } from \"@unkey/error\";\nimport type { Redis } from \"@upstash/redis\";\n\nimport type { CacheError } from \"../errors\";\nimport type { Entry, Store } from \"./interface\";\n\nexport type UpstashRedisStoreConfig = {\n redis: Redis;\n};\n\nexport class UpstashRedisStore<TNamespace extends string, TValue = any>\n implements Store<TNamespace, TValue>\n{\n private readonly redis: Redis;\n public readonly name = \"upstash-redis\";\n\n constructor(config: UpstashRedisStoreConfig) {\n this.redis = config.redis;\n }\n\n private buildCacheKey(namespace: TNamespace, key: string): string {\n return [namespace, key].join(\"::\");\n }\n\n public async get(\n namespace: TNamespace,\n key: string,\n ): Promise<Result<Entry<TValue> | undefined, CacheError>> {\n const value = await this.redis.get<Entry<TValue>>(this.buildCacheKey(namespace, key));\n if (!value) {\n return Ok(undefined);\n }\n return Ok(value);\n }\n\n public async set(\n namespace: TNamespace,\n key: string,\n entry: Entry<TValue>,\n ): Promise<Result<void, CacheError>> {\n await this.redis.set<Entry<TValue>>(this.buildCacheKey(namespace, key), entry, {\n pxat: entry.staleUntil,\n });\n return Ok();\n }\n\n public async remove(\n namespace: TNamespace,\n keys: string | string[],\n ): Promise<Result<void, CacheError>> {\n const cacheKeys = (Array.isArray(keys) ? keys : [keys]).map((key) =>\n this.buildCacheKey(namespace, key).toString(),\n );\n this.redis.del(...cacheKeys);\n return Ok();\n }\n}\n","import type { Client } from \"@libsql/client\";\nimport { Ok, type Result } from \"@unkey/error\";\n\nimport type { CacheError } from \"../errors\";\nimport type { Entry, Store } from \"./interface\";\n\nexport type LibsqlStoreConfig = {\n client: Client;\n tableName?: string;\n};\n\nexport class LibSQLStore<TNamespace extends string, TValue = any>\n implements Store<TNamespace, TValue>\n{\n private readonly tableName: string;\n private readonly client: Client;\n public readonly name = \"libsql\";\n\n constructor(config: LibsqlStoreConfig) {\n this.client = config.client;\n this.tableName = config.tableName || \"cache\";\n }\n\n private buildCacheKey(namespace: TNamespace, key: string): string {\n return `${namespace}::${key}`;\n }\n\n public async get(\n namespace: TNamespace,\n key: string,\n ): Promise<Result<Entry<TValue> | undefined, CacheError>> {\n try {\n const result = await this.client.execute({\n sql: `SELECT value, freshUntil, staleUntil FROM ${this.tableName} WHERE key = ?`,\n args: [this.buildCacheKey(namespace, key)],\n });\n\n if (result.rows.length === 0) {\n return Ok(undefined);\n }\n\n const row = result.rows[0];\n const entry: Entry<TValue> = {\n value: JSON.parse(row.value as string),\n freshUntil: Number(row.freshUntil),\n staleUntil: Number(row.staleUntil),\n };\n\n return Ok(entry);\n } catch {\n return Ok(undefined);\n }\n }\n\n public async set(\n namespace: TNamespace,\n key: string,\n entry: Entry<TValue>,\n ): Promise<Result<void, CacheError>> {\n try {\n await this.client.execute({\n sql: `INSERT OR REPLACE INTO ${this.tableName} (key, value, freshUntil, staleUntil)\n VALUES (?, ?, ?, ?)`,\n args: [\n this.buildCacheKey(namespace, key),\n JSON.stringify(entry.value),\n entry.freshUntil,\n entry.staleUntil,\n ],\n });\n\n return Ok();\n } catch {\n return Ok();\n }\n }\n\n public async remove(\n namespace: TNamespace,\n keys: string | string[],\n ): Promise<Result<void, CacheError>> {\n const cacheKeys = (Array.isArray(keys) ? keys : [keys]).map((key) =>\n this.buildCacheKey(namespace, key).toString(),\n );\n\n try {\n await Promise.all(\n cacheKeys.map((cacheKey) =>\n this.client.execute({\n sql: `DELETE FROM ${this.tableName} WHERE key = ?`,\n args: [cacheKey],\n }),\n ),\n );\n\n return Ok();\n } catch {\n return Ok();\n }\n }\n}\n"]}