@parsrun/cache 0.1.0
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/README.md +135 -0
- package/dist/adapters/cloudflare-kv.d.ts +51 -0
- package/dist/adapters/cloudflare-kv.js +197 -0
- package/dist/adapters/cloudflare-kv.js.map +1 -0
- package/dist/adapters/index.d.ts +6 -0
- package/dist/adapters/index.js +783 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/memory.d.ts +59 -0
- package/dist/adapters/memory.js +179 -0
- package/dist/adapters/memory.js.map +1 -0
- package/dist/adapters/redis.d.ts +72 -0
- package/dist/adapters/redis.js +242 -0
- package/dist/adapters/redis.js.map +1 -0
- package/dist/adapters/upstash.d.ts +50 -0
- package/dist/adapters/upstash.js +229 -0
- package/dist/adapters/upstash.js.map +1 -0
- package/dist/index.d.ts +140 -0
- package/dist/index.js +978 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +234 -0
- package/dist/types.js +43 -0
- package/dist/types.js.map +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/adapters/memory.ts","../src/adapters/redis.ts","../src/adapters/upstash.ts","../src/adapters/cloudflare-kv.ts","../src/index.ts"],"sourcesContent":["/**\n * @parsrun/cache - Type Definitions\n * Cache types and interfaces\n */\n\n// Re-export types from @parsrun/types for convenience\nexport {\n type,\n cacheSetOptions as parsCacheSetOptions,\n cacheGetResult,\n cacheStats,\n memoryCacheConfig,\n redisCacheConfig,\n upstashCacheConfig,\n cloudflareKvConfig,\n multiTierCacheConfig,\n cacheConfig,\n type CacheSetOptions as ParsCacheSetOptions,\n type CacheGetResult,\n type CacheStats,\n type MemoryCacheConfig as ParsMemoryCacheConfig,\n type RedisCacheConfig as ParsRedisCacheConfig,\n type UpstashCacheConfig as ParsUpstashCacheConfig,\n type CloudflareKvConfig as ParsCloudflareKvConfig,\n type MultiTierCacheConfig,\n type CacheConfig,\n} from \"@parsrun/types\";\n\n/**\n * Cache adapter type\n */\nexport type CacheAdapterType = \"memory\" | \"redis\" | \"upstash\" | \"cloudflare-kv\";\n\n/**\n * Cache entry with metadata\n */\nexport interface CacheEntry<T = unknown> {\n /** Cached value */\n value: T;\n /** Expiration timestamp (ms) */\n expiresAt?: number | undefined;\n /** Original TTL in seconds (for refresh/sliding expiration) */\n ttlSeconds?: number | undefined;\n /** Cache entry tags for invalidation */\n tags?: string[] | undefined;\n /** Cache entry metadata */\n metadata?: Record<string, unknown> | undefined;\n}\n\n/**\n * Cache get options\n */\nexport interface CacheGetOptions {\n /** Whether to update TTL on access (sliding expiration) */\n refresh?: boolean | undefined;\n}\n\n/**\n * Cache set options\n */\nexport interface CacheSetOptions {\n /** Time to live in seconds */\n ttl?: number | undefined;\n /** Tags for cache invalidation */\n tags?: string[] | undefined;\n /** Additional metadata */\n metadata?: Record<string, unknown> | undefined;\n}\n\n/**\n * Cache delete options\n */\nexport interface CacheDeleteOptions {\n /** Delete all entries with matching tags */\n tags?: string[] | undefined;\n}\n\n/**\n * Cache adapter interface\n */\nexport interface CacheAdapter {\n /** Adapter type */\n readonly type: CacheAdapterType;\n\n /**\n * Get a value from cache\n * @param key Cache key\n * @param options Get options\n * @returns Cached value or null if not found/expired\n */\n get<T = unknown>(key: string, options?: CacheGetOptions): Promise<T | null>;\n\n /**\n * Set a value in cache\n * @param key Cache key\n * @param value Value to cache\n * @param options Set options\n */\n set<T = unknown>(key: string, value: T, options?: CacheSetOptions): Promise<void>;\n\n /**\n * Delete a value from cache\n * @param key Cache key\n */\n delete(key: string): Promise<void>;\n\n /**\n * Check if a key exists in cache\n * @param key Cache key\n */\n has(key: string): Promise<boolean>;\n\n /**\n * Clear all entries from cache\n */\n clear?(): Promise<void>;\n\n /**\n * Get multiple values at once\n * @param keys Cache keys\n */\n getMany?<T = unknown>(keys: string[]): Promise<Map<string, T | null>>;\n\n /**\n * Set multiple values at once\n * @param entries Key-value pairs\n * @param options Set options (applied to all)\n */\n setMany?<T = unknown>(entries: Map<string, T>, options?: CacheSetOptions): Promise<void>;\n\n /**\n * Delete multiple keys\n * @param keys Cache keys\n */\n deleteMany?(keys: string[]): Promise<void>;\n\n /**\n * Invalidate entries by tags\n * @param tags Tags to invalidate\n */\n invalidateByTags?(tags: string[]): Promise<void>;\n\n /**\n * Get TTL for a key (in seconds)\n * @param key Cache key\n * @returns TTL in seconds, -1 if no expiry, -2 if key doesn't exist\n */\n ttl?(key: string): Promise<number>;\n\n /**\n * Close/cleanup adapter resources\n */\n close?(): Promise<void>;\n}\n\n/**\n * Cache service configuration\n */\nexport interface CacheServiceConfig {\n /** Cache adapter to use */\n adapter: CacheAdapter;\n /** Default TTL in seconds */\n defaultTtl?: number | undefined;\n /** Key prefix for namespacing */\n keyPrefix?: string | undefined;\n /** Enable debug logging */\n debug?: boolean | undefined;\n}\n\n/**\n * Memory adapter configuration\n */\nexport interface MemoryCacheConfig {\n /** Maximum number of entries */\n maxEntries?: number | undefined;\n /** Cleanup interval in ms (default: 60000) */\n cleanupInterval?: number | undefined;\n}\n\n/**\n * Redis adapter configuration\n */\nexport interface RedisCacheConfig {\n /** Redis connection URL */\n url?: string | undefined;\n /** Redis host */\n host?: string | undefined;\n /** Redis port */\n port?: number | undefined;\n /** Redis password */\n password?: string | undefined;\n /** Redis database number */\n db?: number | undefined;\n /** Key prefix */\n keyPrefix?: string | undefined;\n /** Use TLS */\n tls?: boolean | undefined;\n}\n\n/**\n * Upstash adapter configuration\n */\nexport interface UpstashCacheConfig {\n /** Upstash Redis URL */\n url: string;\n /** Upstash Redis token */\n token: string;\n /** Key prefix */\n keyPrefix?: string | undefined;\n}\n\n/**\n * Cloudflare KV adapter configuration\n */\nexport interface CloudflareKVCacheConfig {\n /** KV namespace binding */\n namespace: KVNamespace;\n /** Key prefix */\n keyPrefix?: string | undefined;\n}\n\n/**\n * KVNamespace interface (Cloudflare Workers)\n */\nexport interface KVNamespace {\n get(key: string, options?: { type?: \"text\" | \"json\" | \"arrayBuffer\" | \"stream\" }): Promise<string | null>;\n get(key: string, options: { type: \"json\" }): Promise<unknown>;\n put(key: string, value: string | ArrayBuffer | ReadableStream, options?: { expiration?: number; expirationTtl?: number; metadata?: unknown }): Promise<void>;\n delete(key: string): Promise<void>;\n list(options?: { prefix?: string | undefined; limit?: number | undefined; cursor?: string | undefined }): Promise<{ keys: Array<{ name: string; expiration?: number; metadata?: unknown }>; list_complete: boolean; cursor?: string }>;\n getWithMetadata<T = unknown>(key: string, options?: { type?: \"text\" | \"json\" | \"arrayBuffer\" | \"stream\" }): Promise<{ value: string | null; metadata: T | null }>;\n}\n\n/**\n * Cache error\n */\nexport class CacheError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly cause?: unknown\n ) {\n super(message);\n this.name = \"CacheError\";\n }\n}\n\n/**\n * Common cache error codes\n */\nexport const CacheErrorCodes = {\n CONNECTION_FAILED: \"CONNECTION_FAILED\",\n OPERATION_FAILED: \"OPERATION_FAILED\",\n SERIALIZATION_ERROR: \"SERIALIZATION_ERROR\",\n INVALID_CONFIG: \"INVALID_CONFIG\",\n NOT_IMPLEMENTED: \"NOT_IMPLEMENTED\",\n} as const;\n","/**\n * @parsrun/cache - Memory Adapter\n * In-memory cache adapter for development and testing\n */\n\nimport type {\n CacheAdapter,\n CacheEntry,\n CacheGetOptions,\n CacheSetOptions,\n MemoryCacheConfig,\n} from \"../types.js\";\n\n/**\n * Memory Cache Adapter\n * Uses in-memory storage with automatic expiration cleanup\n *\n * @example\n * ```typescript\n * const cache = new MemoryCacheAdapter({\n * maxEntries: 1000,\n * cleanupInterval: 60000,\n * });\n *\n * await cache.set('user:123', { name: 'John' }, { ttl: 3600 });\n * const user = await cache.get('user:123');\n * ```\n */\nexport class MemoryCacheAdapter implements CacheAdapter {\n readonly type = \"memory\" as const;\n\n private cache = new Map<string, CacheEntry>();\n private tagIndex = new Map<string, Set<string>>();\n private maxEntries: number;\n private cleanupInterval: number;\n private cleanupTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(config?: MemoryCacheConfig) {\n this.maxEntries = config?.maxEntries ?? 10000;\n this.cleanupInterval = config?.cleanupInterval ?? 60000;\n\n // Start cleanup timer\n if (this.cleanupInterval > 0) {\n this.cleanupTimer = setInterval(() => this.cleanup(), this.cleanupInterval);\n }\n }\n\n async get<T = unknown>(key: string, options?: CacheGetOptions): Promise<T | null> {\n const entry = this.cache.get(key);\n\n if (!entry) {\n return null;\n }\n\n // Check expiration\n if (entry.expiresAt && Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n this.removeFromTagIndex(key, entry.tags);\n return null;\n }\n\n // Refresh TTL if requested (sliding expiration)\n if (options?.refresh && entry.expiresAt && entry.ttlSeconds) {\n entry.expiresAt = Date.now() + entry.ttlSeconds * 1000;\n }\n\n return entry.value as T;\n }\n\n async set<T = unknown>(key: string, value: T, options?: CacheSetOptions): Promise<void> {\n // Enforce max entries (LRU-like: remove oldest)\n if (this.cache.size >= this.maxEntries && !this.cache.has(key)) {\n const oldestKey = this.cache.keys().next().value;\n if (oldestKey) {\n const oldEntry = this.cache.get(oldestKey);\n this.cache.delete(oldestKey);\n if (oldEntry?.tags) {\n this.removeFromTagIndex(oldestKey, oldEntry.tags);\n }\n }\n }\n\n const entry: CacheEntry<T> = {\n value,\n metadata: options?.metadata,\n };\n\n if (options?.ttl) {\n entry.expiresAt = Date.now() + options.ttl * 1000;\n entry.ttlSeconds = options.ttl;\n }\n\n if (options?.tags && options.tags.length > 0) {\n entry.tags = options.tags;\n this.addToTagIndex(key, options.tags);\n }\n\n this.cache.set(key, entry);\n }\n\n async delete(key: string): Promise<void> {\n const entry = this.cache.get(key);\n if (entry?.tags) {\n this.removeFromTagIndex(key, entry.tags);\n }\n this.cache.delete(key);\n }\n\n async has(key: string): Promise<boolean> {\n const entry = this.cache.get(key);\n\n if (!entry) {\n return false;\n }\n\n // Check expiration\n if (entry.expiresAt && Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n this.removeFromTagIndex(key, entry.tags);\n return false;\n }\n\n return true;\n }\n\n async clear(): Promise<void> {\n this.cache.clear();\n this.tagIndex.clear();\n }\n\n async getMany<T = unknown>(keys: string[]): Promise<Map<string, T | null>> {\n const result = new Map<string, T | null>();\n\n for (const key of keys) {\n result.set(key, await this.get<T>(key));\n }\n\n return result;\n }\n\n async setMany<T = unknown>(entries: Map<string, T>, options?: CacheSetOptions): Promise<void> {\n for (const [key, value] of entries) {\n await this.set(key, value, options);\n }\n }\n\n async deleteMany(keys: string[]): Promise<void> {\n for (const key of keys) {\n await this.delete(key);\n }\n }\n\n async invalidateByTags(tags: string[]): Promise<void> {\n const keysToDelete = new Set<string>();\n\n for (const tag of tags) {\n const keys = this.tagIndex.get(tag);\n if (keys) {\n for (const key of keys) {\n keysToDelete.add(key);\n }\n }\n }\n\n for (const key of keysToDelete) {\n await this.delete(key);\n }\n }\n\n async ttl(key: string): Promise<number> {\n const entry = this.cache.get(key);\n\n if (!entry) {\n return -2; // Key doesn't exist\n }\n\n if (!entry.expiresAt) {\n return -1; // No expiration\n }\n\n const remaining = entry.expiresAt - Date.now();\n if (remaining <= 0) {\n return -2; // Expired\n }\n\n return Math.ceil(remaining / 1000);\n }\n\n async close(): Promise<void> {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n this.cleanupTimer = null;\n }\n await this.clear();\n }\n\n /**\n * Get cache statistics\n */\n getStats(): { size: number; maxEntries: number } {\n return {\n size: this.cache.size,\n maxEntries: this.maxEntries,\n };\n }\n\n private addToTagIndex(key: string, tags: string[]): void {\n for (const tag of tags) {\n let keys = this.tagIndex.get(tag);\n if (!keys) {\n keys = new Set();\n this.tagIndex.set(tag, keys);\n }\n keys.add(key);\n }\n }\n\n private removeFromTagIndex(key: string, tags?: string[]): void {\n if (!tags) return;\n\n for (const tag of tags) {\n const keys = this.tagIndex.get(tag);\n if (keys) {\n keys.delete(key);\n if (keys.size === 0) {\n this.tagIndex.delete(tag);\n }\n }\n }\n }\n\n private cleanup(): void {\n const now = Date.now();\n\n for (const [key, entry] of this.cache) {\n if (entry.expiresAt && now > entry.expiresAt) {\n this.removeFromTagIndex(key, entry.tags);\n this.cache.delete(key);\n }\n }\n }\n}\n\n/**\n * Create a memory cache adapter\n */\nexport function createMemoryCacheAdapter(config?: MemoryCacheConfig): MemoryCacheAdapter {\n return new MemoryCacheAdapter(config);\n}\n","/**\n * @parsrun/cache - Redis Adapter\n * Redis cache adapter using ioredis (Node.js)\n */\n\nimport type {\n CacheAdapter,\n CacheGetOptions,\n CacheSetOptions,\n RedisCacheConfig,\n} from \"../types.js\";\nimport { CacheError, CacheErrorCodes } from \"../types.js\";\n\n/**\n * Redis client interface (ioredis compatible)\n */\ninterface RedisClient {\n get(key: string): Promise<string | null>;\n set(key: string, value: string, ...args: (string | number)[]): Promise<\"OK\" | null>;\n del(...keys: string[]): Promise<number>;\n exists(...keys: string[]): Promise<number>;\n ttl(key: string): Promise<number>;\n mget(...keys: string[]): Promise<(string | null)[]>;\n keys(pattern: string): Promise<string[]>;\n flushdb(): Promise<\"OK\">;\n quit(): Promise<\"OK\">;\n pipeline(): RedisPipeline;\n}\n\ninterface RedisPipeline {\n set(key: string, value: string, ...args: (string | number)[]): this;\n exec(): Promise<Array<[Error | null, unknown]>>;\n}\n\n/**\n * Redis Cache Adapter\n * Uses ioredis for Node.js environments\n *\n * @example\n * ```typescript\n * import Redis from 'ioredis';\n *\n * const redis = new Redis(process.env.REDIS_URL);\n * const cache = new RedisCacheAdapter({ client: redis });\n *\n * await cache.set('user:123', { name: 'John' }, { ttl: 3600 });\n * const user = await cache.get('user:123');\n * ```\n */\nexport class RedisCacheAdapter implements CacheAdapter {\n readonly type = \"redis\" as const;\n\n private client: RedisClient;\n private keyPrefix: string;\n private isExternalClient: boolean;\n\n constructor(config: RedisCacheConfig & { client: RedisClient }) {\n this.client = config.client;\n this.keyPrefix = config.keyPrefix ?? \"\";\n this.isExternalClient = true;\n }\n\n private prefixKey(key: string): string {\n return this.keyPrefix ? `${this.keyPrefix}:${key}` : key;\n }\n\n async get<T = unknown>(key: string, _options?: CacheGetOptions): Promise<T | null> {\n try {\n const data = await this.client.get(this.prefixKey(key));\n\n if (!data) {\n return null;\n }\n\n const parsed = JSON.parse(data) as { value: T; tags?: string[] };\n return parsed.value;\n } catch (err) {\n throw new CacheError(\n `Redis get failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async set<T = unknown>(key: string, value: T, options?: CacheSetOptions): Promise<void> {\n try {\n const data = JSON.stringify({\n value,\n tags: options?.tags,\n metadata: options?.metadata,\n });\n\n const prefixedKey = this.prefixKey(key);\n\n if (options?.ttl) {\n await this.client.set(prefixedKey, data, \"EX\", options.ttl);\n } else {\n await this.client.set(prefixedKey, data);\n }\n\n // Store tag-to-key mappings\n if (options?.tags && options.tags.length > 0) {\n const pipeline = this.client.pipeline();\n for (const tag of options.tags) {\n const tagKey = this.prefixKey(`__tag:${tag}`);\n pipeline.set(tagKey, JSON.stringify([...(await this.getTagKeys(tag)), key]));\n }\n await pipeline.exec();\n }\n } catch (err) {\n throw new CacheError(\n `Redis set failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async delete(key: string): Promise<void> {\n try {\n await this.client.del(this.prefixKey(key));\n } catch (err) {\n throw new CacheError(\n `Redis delete failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async has(key: string): Promise<boolean> {\n try {\n const exists = await this.client.exists(this.prefixKey(key));\n return exists > 0;\n } catch (err) {\n throw new CacheError(\n `Redis exists failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async clear(): Promise<void> {\n try {\n if (this.keyPrefix) {\n // Only delete keys with our prefix\n const keys = await this.client.keys(`${this.keyPrefix}:*`);\n if (keys.length > 0) {\n await this.client.del(...keys);\n }\n } else {\n await this.client.flushdb();\n }\n } catch (err) {\n throw new CacheError(\n `Redis clear failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async getMany<T = unknown>(keys: string[]): Promise<Map<string, T | null>> {\n try {\n const prefixedKeys = keys.map((k) => this.prefixKey(k));\n const results = await this.client.mget(...prefixedKeys);\n\n const map = new Map<string, T | null>();\n for (let i = 0; i < keys.length; i++) {\n const data = results[i];\n if (data) {\n const parsed = JSON.parse(data) as { value: T };\n map.set(keys[i] ?? \"\", parsed.value);\n } else {\n map.set(keys[i] ?? \"\", null);\n }\n }\n\n return map;\n } catch (err) {\n throw new CacheError(\n `Redis mget failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async setMany<T = unknown>(entries: Map<string, T>, options?: CacheSetOptions): Promise<void> {\n try {\n const pipeline = this.client.pipeline();\n\n for (const [key, value] of entries) {\n const data = JSON.stringify({\n value,\n tags: options?.tags,\n metadata: options?.metadata,\n });\n\n const prefixedKey = this.prefixKey(key);\n\n if (options?.ttl) {\n pipeline.set(prefixedKey, data, \"EX\", options.ttl);\n } else {\n pipeline.set(prefixedKey, data);\n }\n }\n\n await pipeline.exec();\n } catch (err) {\n throw new CacheError(\n `Redis mset failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async deleteMany(keys: string[]): Promise<void> {\n try {\n const prefixedKeys = keys.map((k) => this.prefixKey(k));\n await this.client.del(...prefixedKeys);\n } catch (err) {\n throw new CacheError(\n `Redis mdel failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async invalidateByTags(tags: string[]): Promise<void> {\n try {\n const keysToDelete: string[] = [];\n\n for (const tag of tags) {\n const keys = await this.getTagKeys(tag);\n keysToDelete.push(...keys);\n }\n\n if (keysToDelete.length > 0) {\n await this.deleteMany(keysToDelete);\n }\n\n // Clean up tag mappings\n const tagKeys = tags.map((tag) => this.prefixKey(`__tag:${tag}`));\n await this.client.del(...tagKeys);\n } catch (err) {\n throw new CacheError(\n `Redis invalidate by tags failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async ttl(key: string): Promise<number> {\n try {\n return await this.client.ttl(this.prefixKey(key));\n } catch (err) {\n throw new CacheError(\n `Redis ttl failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async close(): Promise<void> {\n if (!this.isExternalClient) {\n await this.client.quit();\n }\n }\n\n private async getTagKeys(tag: string): Promise<string[]> {\n const tagKey = this.prefixKey(`__tag:${tag}`);\n const data = await this.client.get(tagKey);\n if (data) {\n return JSON.parse(data) as string[];\n }\n return [];\n }\n}\n\n/**\n * Create a Redis cache adapter\n */\nexport function createRedisCacheAdapter(\n config: RedisCacheConfig & { client: RedisClient }\n): RedisCacheAdapter {\n return new RedisCacheAdapter(config);\n}\n","/**\n * @parsrun/cache - Upstash Adapter\n * Edge-compatible Upstash Redis adapter using fetch API\n */\n\nimport type {\n CacheAdapter,\n CacheGetOptions,\n CacheSetOptions,\n UpstashCacheConfig,\n} from \"../types.js\";\nimport { CacheError, CacheErrorCodes } from \"../types.js\";\n\n/**\n * Upstash Cache Adapter\n * Edge-compatible using HTTP API\n *\n * @example\n * ```typescript\n * const cache = new UpstashCacheAdapter({\n * url: process.env.UPSTASH_REDIS_REST_URL,\n * token: process.env.UPSTASH_REDIS_REST_TOKEN,\n * });\n *\n * await cache.set('user:123', { name: 'John' }, { ttl: 3600 });\n * const user = await cache.get('user:123');\n * ```\n */\nexport class UpstashCacheAdapter implements CacheAdapter {\n readonly type = \"upstash\" as const;\n\n private url: string;\n private token: string;\n private keyPrefix: string;\n\n constructor(config: UpstashCacheConfig) {\n this.url = config.url.replace(/\\/$/, \"\"); // Remove trailing slash\n this.token = config.token;\n this.keyPrefix = config.keyPrefix ?? \"\";\n }\n\n private prefixKey(key: string): string {\n return this.keyPrefix ? `${this.keyPrefix}:${key}` : key;\n }\n\n private async command<T = unknown>(...args: (string | number)[]): Promise<T> {\n try {\n const response = await fetch(this.url, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(args),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Upstash API error: ${error}`);\n }\n\n const data = await response.json() as { result: T; error?: string };\n\n if (data.error) {\n throw new Error(data.error);\n }\n\n return data.result;\n } catch (err) {\n throw new CacheError(\n `Upstash command failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n private async pipeline<T = unknown>(commands: (string | number)[][]): Promise<T[]> {\n try {\n const response = await fetch(`${this.url}/pipeline`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(commands),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Upstash API error: ${error}`);\n }\n\n const data = await response.json() as Array<{ result: T; error?: string }>;\n return data.map((item) => {\n if (item.error) {\n throw new Error(item.error);\n }\n return item.result;\n });\n } catch (err) {\n throw new CacheError(\n `Upstash pipeline failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async get<T = unknown>(key: string, _options?: CacheGetOptions): Promise<T | null> {\n const data = await this.command<string | null>(\"GET\", this.prefixKey(key));\n\n if (!data) {\n return null;\n }\n\n try {\n const parsed = JSON.parse(data) as { value: T };\n return parsed.value;\n } catch {\n // Return raw string if not JSON\n return data as T;\n }\n }\n\n async set<T = unknown>(key: string, value: T, options?: CacheSetOptions): Promise<void> {\n const data = JSON.stringify({\n value,\n tags: options?.tags,\n metadata: options?.metadata,\n });\n\n const prefixedKey = this.prefixKey(key);\n\n if (options?.ttl) {\n await this.command(\"SET\", prefixedKey, data, \"EX\", options.ttl);\n } else {\n await this.command(\"SET\", prefixedKey, data);\n }\n\n // Store tag-to-key mappings\n if (options?.tags && options.tags.length > 0) {\n const commands: (string | number)[][] = [];\n for (const tag of options.tags) {\n commands.push([\"SADD\", this.prefixKey(`__tag:${tag}`), key]);\n }\n await this.pipeline(commands);\n }\n }\n\n async delete(key: string): Promise<void> {\n await this.command(\"DEL\", this.prefixKey(key));\n }\n\n async has(key: string): Promise<boolean> {\n const exists = await this.command<number>(\"EXISTS\", this.prefixKey(key));\n return exists > 0;\n }\n\n async clear(): Promise<void> {\n if (this.keyPrefix) {\n // Scan and delete keys with our prefix\n let cursor = \"0\";\n do {\n const result = await this.command<[string, string[]]>(\n \"SCAN\",\n cursor,\n \"MATCH\",\n `${this.keyPrefix}:*`,\n \"COUNT\",\n 100\n );\n cursor = result[0];\n const keys = result[1];\n\n if (keys.length > 0) {\n await this.command(\"DEL\", ...keys);\n }\n } while (cursor !== \"0\");\n } else {\n await this.command(\"FLUSHDB\");\n }\n }\n\n async getMany<T = unknown>(keys: string[]): Promise<Map<string, T | null>> {\n const prefixedKeys = keys.map((k) => this.prefixKey(k));\n const results = await this.command<(string | null)[]>(\"MGET\", ...prefixedKeys);\n\n const map = new Map<string, T | null>();\n for (let i = 0; i < keys.length; i++) {\n const data = results[i];\n const key = keys[i];\n if (key !== undefined) {\n if (data) {\n try {\n const parsed = JSON.parse(data) as { value: T };\n map.set(key, parsed.value);\n } catch {\n map.set(key, data as T);\n }\n } else {\n map.set(key, null);\n }\n }\n }\n\n return map;\n }\n\n async setMany<T = unknown>(entries: Map<string, T>, options?: CacheSetOptions): Promise<void> {\n const commands: (string | number)[][] = [];\n\n for (const [key, value] of entries) {\n const data = JSON.stringify({\n value,\n tags: options?.tags,\n metadata: options?.metadata,\n });\n\n const prefixedKey = this.prefixKey(key);\n\n if (options?.ttl) {\n commands.push([\"SET\", prefixedKey, data, \"EX\", options.ttl]);\n } else {\n commands.push([\"SET\", prefixedKey, data]);\n }\n }\n\n await this.pipeline(commands);\n }\n\n async deleteMany(keys: string[]): Promise<void> {\n const prefixedKeys = keys.map((k) => this.prefixKey(k));\n await this.command(\"DEL\", ...prefixedKeys);\n }\n\n async invalidateByTags(tags: string[]): Promise<void> {\n const keysToDelete: string[] = [];\n\n // Get all keys for each tag\n for (const tag of tags) {\n const keys = await this.command<string[]>(\"SMEMBERS\", this.prefixKey(`__tag:${tag}`));\n keysToDelete.push(...keys);\n }\n\n if (keysToDelete.length > 0) {\n await this.deleteMany(keysToDelete);\n }\n\n // Clean up tag sets\n const tagKeys = tags.map((tag) => this.prefixKey(`__tag:${tag}`));\n await this.command(\"DEL\", ...tagKeys);\n }\n\n async ttl(key: string): Promise<number> {\n return await this.command<number>(\"TTL\", this.prefixKey(key));\n }\n\n async close(): Promise<void> {\n // No-op for HTTP client\n }\n}\n\n/**\n * Create an Upstash cache adapter\n */\nexport function createUpstashCacheAdapter(config: UpstashCacheConfig): UpstashCacheAdapter {\n return new UpstashCacheAdapter(config);\n}\n","/**\n * @parsrun/cache - Cloudflare KV Adapter\n * Cache adapter for Cloudflare Workers KV\n */\n\nimport type {\n CacheAdapter,\n CacheGetOptions,\n CacheSetOptions,\n CloudflareKVCacheConfig,\n KVNamespace,\n} from \"../types.js\";\nimport { CacheError, CacheErrorCodes } from \"../types.js\";\n\n/**\n * Cloudflare KV Cache Adapter\n * Uses Cloudflare Workers KV for edge caching\n *\n * @example\n * ```typescript\n * // In Cloudflare Workers\n * export default {\n * async fetch(request, env) {\n * const cache = new CloudflareKVCacheAdapter({\n * namespace: env.CACHE_KV,\n * });\n *\n * await cache.set('user:123', { name: 'John' }, { ttl: 3600 });\n * const user = await cache.get('user:123');\n * }\n * }\n * ```\n */\nexport class CloudflareKVCacheAdapter implements CacheAdapter {\n readonly type = \"cloudflare-kv\" as const;\n\n private kv: KVNamespace;\n private keyPrefix: string;\n\n constructor(config: CloudflareKVCacheConfig) {\n this.kv = config.namespace;\n this.keyPrefix = config.keyPrefix ?? \"\";\n }\n\n private prefixKey(key: string): string {\n return this.keyPrefix ? `${this.keyPrefix}:${key}` : key;\n }\n\n async get<T = unknown>(key: string, _options?: CacheGetOptions): Promise<T | null> {\n try {\n const data = await this.kv.get(this.prefixKey(key), { type: \"json\" }) as { value: T; tags?: string[] } | null;\n\n if (!data) {\n return null;\n }\n\n return data.value;\n } catch (err) {\n throw new CacheError(\n `Cloudflare KV get failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async set<T = unknown>(key: string, value: T, options?: CacheSetOptions): Promise<void> {\n try {\n const data = {\n value,\n tags: options?.tags,\n metadata: options?.metadata,\n };\n\n const putOptions: { expirationTtl?: number; metadata?: unknown } = {};\n\n if (options?.ttl) {\n putOptions.expirationTtl = options.ttl;\n }\n\n // Store metadata in KV metadata field\n if (options?.tags || options?.metadata) {\n putOptions.metadata = {\n tags: options.tags,\n ...options.metadata,\n };\n }\n\n await this.kv.put(this.prefixKey(key), JSON.stringify(data), putOptions);\n\n // Store tag-to-key mappings\n if (options?.tags && options.tags.length > 0) {\n for (const tag of options.tags) {\n const tagKey = this.prefixKey(`__tag:${tag}`);\n const existing = await this.kv.get(tagKey, { type: \"json\" }) as string[] | null;\n const keys = existing ? [...new Set([...existing, key])] : [key];\n await this.kv.put(tagKey, JSON.stringify(keys));\n }\n }\n } catch (err) {\n throw new CacheError(\n `Cloudflare KV set failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async delete(key: string): Promise<void> {\n try {\n await this.kv.delete(this.prefixKey(key));\n } catch (err) {\n throw new CacheError(\n `Cloudflare KV delete failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async has(key: string): Promise<boolean> {\n try {\n const value = await this.kv.get(this.prefixKey(key));\n return value !== null;\n } catch (err) {\n throw new CacheError(\n `Cloudflare KV has failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async clear(): Promise<void> {\n try {\n const prefix = this.keyPrefix ? `${this.keyPrefix}:` : \"\";\n let cursor: string | undefined;\n\n do {\n const result = await this.kv.list({\n prefix,\n limit: 1000,\n cursor,\n });\n\n for (const key of result.keys) {\n await this.kv.delete(key.name);\n }\n\n cursor = result.list_complete ? undefined : result.cursor;\n } while (cursor);\n } catch (err) {\n throw new CacheError(\n `Cloudflare KV clear failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async getMany<T = unknown>(keys: string[]): Promise<Map<string, T | null>> {\n const map = new Map<string, T | null>();\n\n // KV doesn't support batch get, so we do parallel fetches\n const promises = keys.map(async (key) => {\n const value = await this.get<T>(key);\n return { key, value };\n });\n\n const results = await Promise.all(promises);\n\n for (const { key, value } of results) {\n map.set(key, value);\n }\n\n return map;\n }\n\n async setMany<T = unknown>(entries: Map<string, T>, options?: CacheSetOptions): Promise<void> {\n // KV doesn't support batch write, so we do parallel writes\n const promises: Promise<void>[] = [];\n\n for (const [key, value] of entries) {\n promises.push(this.set(key, value, options));\n }\n\n await Promise.all(promises);\n }\n\n async deleteMany(keys: string[]): Promise<void> {\n // KV doesn't support batch delete, so we do parallel deletes\n const promises = keys.map((key) => this.delete(key));\n await Promise.all(promises);\n }\n\n async invalidateByTags(tags: string[]): Promise<void> {\n try {\n const keysToDelete = new Set<string>();\n\n for (const tag of tags) {\n const tagKey = this.prefixKey(`__tag:${tag}`);\n const keys = await this.kv.get(tagKey, { type: \"json\" }) as string[] | null;\n\n if (keys) {\n for (const key of keys) {\n keysToDelete.add(key);\n }\n // Delete tag mapping\n await this.kv.delete(tagKey);\n }\n }\n\n if (keysToDelete.size > 0) {\n await this.deleteMany([...keysToDelete]);\n }\n } catch (err) {\n throw new CacheError(\n `Cloudflare KV invalidate by tags failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n CacheErrorCodes.OPERATION_FAILED,\n err\n );\n }\n }\n\n async ttl(_key: string): Promise<number> {\n // Cloudflare KV doesn't expose TTL, return -1 (unknown)\n return -1;\n }\n\n async close(): Promise<void> {\n // No-op for KV\n }\n}\n\n/**\n * Create a Cloudflare KV cache adapter\n */\nexport function createCloudflareKVCacheAdapter(config: CloudflareKVCacheConfig): CloudflareKVCacheAdapter {\n return new CloudflareKVCacheAdapter(config);\n}\n","/**\n * @parsrun/cache\n * Edge-compatible caching for Pars\n *\n * Supports multiple adapters:\n * - Memory (development)\n * - Redis/ioredis (Node.js)\n * - Upstash (Edge)\n * - Cloudflare KV (Workers)\n *\n * @example\n * ```typescript\n * import { createCacheService, createMemoryCacheAdapter } from '@parsrun/cache';\n *\n * const cache = createCacheService({\n * adapter: createMemoryCacheAdapter(),\n * defaultTtl: 3600,\n * keyPrefix: 'myapp',\n * });\n *\n * await cache.set('user:123', { name: 'John' });\n * const user = await cache.get('user:123');\n * ```\n */\n\n// Re-export types\nexport * from \"./types.js\";\n\n// Re-export adapters\nexport {\n MemoryCacheAdapter,\n createMemoryCacheAdapter,\n} from \"./adapters/memory.js\";\n\nexport {\n RedisCacheAdapter,\n createRedisCacheAdapter,\n} from \"./adapters/redis.js\";\n\nexport {\n UpstashCacheAdapter,\n createUpstashCacheAdapter,\n} from \"./adapters/upstash.js\";\n\nexport {\n CloudflareKVCacheAdapter,\n createCloudflareKVCacheAdapter,\n} from \"./adapters/cloudflare-kv.js\";\n\nimport type {\n CacheAdapter,\n CacheGetOptions,\n CacheServiceConfig,\n CacheSetOptions,\n} from \"./types.js\";\n\n/**\n * Cache Service\n * High-level cache service with prefix and default TTL support\n */\nexport class CacheService {\n private adapter: CacheAdapter;\n private defaultTtl: number | undefined;\n private keyPrefix: string;\n private debug: boolean;\n\n constructor(config: CacheServiceConfig) {\n this.adapter = config.adapter;\n this.defaultTtl = config.defaultTtl;\n this.keyPrefix = config.keyPrefix ?? \"\";\n this.debug = config.debug ?? false;\n }\n\n private prefixKey(key: string): string {\n return this.keyPrefix ? `${this.keyPrefix}:${key}` : key;\n }\n\n /**\n * Get adapter type\n */\n get adapterType(): string {\n return this.adapter.type;\n }\n\n /**\n * Get a value from cache\n */\n async get<T = unknown>(key: string, options?: CacheGetOptions): Promise<T | null> {\n const prefixedKey = this.prefixKey(key);\n\n if (this.debug) {\n console.log(`[Cache] GET ${prefixedKey}`);\n }\n\n return this.adapter.get<T>(prefixedKey, options);\n }\n\n /**\n * Set a value in cache\n */\n async set<T = unknown>(key: string, value: T, options?: CacheSetOptions): Promise<void> {\n const prefixedKey = this.prefixKey(key);\n const ttl = options?.ttl ?? this.defaultTtl;\n\n if (this.debug) {\n console.log(`[Cache] SET ${prefixedKey} (ttl: ${ttl ?? \"none\"})`);\n }\n\n await this.adapter.set(prefixedKey, value, { ...options, ttl });\n }\n\n /**\n * Delete a value from cache\n */\n async delete(key: string): Promise<void> {\n const prefixedKey = this.prefixKey(key);\n\n if (this.debug) {\n console.log(`[Cache] DELETE ${prefixedKey}`);\n }\n\n await this.adapter.delete(prefixedKey);\n }\n\n /**\n * Check if a key exists in cache\n */\n async has(key: string): Promise<boolean> {\n return this.adapter.has(this.prefixKey(key));\n }\n\n /**\n * Clear all entries from cache\n */\n async clear(): Promise<void> {\n if (this.adapter.clear) {\n await this.adapter.clear();\n }\n }\n\n /**\n * Get multiple values at once\n */\n async getMany<T = unknown>(keys: string[]): Promise<Map<string, T | null>> {\n const prefixedKeys = keys.map((k) => this.prefixKey(k));\n\n if (this.adapter.getMany) {\n const results = await this.adapter.getMany<T>(prefixedKeys);\n // Unprefix keys in result\n const unprefixed = new Map<string, T | null>();\n let i = 0;\n for (const key of keys) {\n const prefixedKey = prefixedKeys[i];\n if (prefixedKey) {\n unprefixed.set(key, results.get(prefixedKey) ?? null);\n }\n i++;\n }\n return unprefixed;\n }\n\n // Fallback to sequential gets\n const results = new Map<string, T | null>();\n for (const key of keys) {\n results.set(key, await this.get<T>(key));\n }\n return results;\n }\n\n /**\n * Set multiple values at once\n */\n async setMany<T = unknown>(entries: Map<string, T>, options?: CacheSetOptions): Promise<void> {\n const prefixedEntries = new Map<string, T>();\n for (const [key, value] of entries) {\n prefixedEntries.set(this.prefixKey(key), value);\n }\n\n const ttl = options?.ttl ?? this.defaultTtl;\n const opts = { ...options, ttl };\n\n if (this.adapter.setMany) {\n await this.adapter.setMany(prefixedEntries, opts);\n return;\n }\n\n // Fallback to sequential sets\n for (const [key, value] of entries) {\n await this.set(key, value, opts);\n }\n }\n\n /**\n * Delete multiple keys\n */\n async deleteMany(keys: string[]): Promise<void> {\n const prefixedKeys = keys.map((k) => this.prefixKey(k));\n\n if (this.adapter.deleteMany) {\n await this.adapter.deleteMany(prefixedKeys);\n return;\n }\n\n // Fallback to sequential deletes\n for (const key of keys) {\n await this.delete(key);\n }\n }\n\n /**\n * Invalidate entries by tags\n */\n async invalidateByTags(tags: string[]): Promise<void> {\n if (this.adapter.invalidateByTags) {\n await this.adapter.invalidateByTags(tags);\n }\n }\n\n /**\n * Get TTL for a key (in seconds)\n * @returns TTL in seconds, -1 if no expiry, -2 if key doesn't exist\n */\n async ttl(key: string): Promise<number> {\n if (this.adapter.ttl) {\n return this.adapter.ttl(this.prefixKey(key));\n }\n return -1;\n }\n\n /**\n * Get or set a value with callback\n * @param key Cache key\n * @param fn Function to compute value if not cached\n * @param options Set options (applied if value is computed)\n */\n async getOrSet<T>(\n key: string,\n fn: () => T | Promise<T>,\n options?: CacheSetOptions\n ): Promise<T> {\n const cached = await this.get<T>(key);\n\n if (cached !== null) {\n return cached;\n }\n\n const value = await fn();\n await this.set(key, value, options);\n return value;\n }\n\n /**\n * Wrap a function with caching\n */\n wrap<TArgs extends unknown[], TReturn>(\n fn: (...args: TArgs) => Promise<TReturn>,\n keyFn: (...args: TArgs) => string,\n options?: CacheSetOptions\n ): (...args: TArgs) => Promise<TReturn> {\n return async (...args: TArgs): Promise<TReturn> => {\n const key = keyFn(...args);\n return this.getOrSet(key, () => fn(...args), options);\n };\n }\n\n /**\n * Close/cleanup cache resources\n */\n async close(): Promise<void> {\n if (this.adapter.close) {\n await this.adapter.close();\n }\n }\n}\n\n/**\n * Create a cache service\n *\n * @example\n * ```typescript\n * // With Memory (development)\n * const cache = createCacheService({\n * adapter: createMemoryCacheAdapter(),\n * defaultTtl: 3600,\n * });\n *\n * // With Upstash (Edge)\n * const cache = createCacheService({\n * adapter: createUpstashCacheAdapter({\n * url: process.env.UPSTASH_REDIS_REST_URL,\n * token: process.env.UPSTASH_REDIS_REST_TOKEN,\n * }),\n * defaultTtl: 3600,\n * });\n *\n * // With Cloudflare KV (Workers)\n * const cache = createCacheService({\n * adapter: createCloudflareKVCacheAdapter({\n * namespace: env.CACHE_KV,\n * }),\n * });\n * ```\n */\nexport function createCacheService(config: CacheServiceConfig): CacheService {\n return new CacheService(config);\n}\n\n// Default export\nexport default {\n CacheService,\n createCacheService,\n};\n"],"mappings":"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","names":["results"]}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
export { CacheConfig, CacheGetResult, CacheStats, MultiTierCacheConfig, CacheSetOptions as ParsCacheSetOptions, CloudflareKvConfig as ParsCloudflareKvConfig, MemoryCacheConfig as ParsMemoryCacheConfig, RedisCacheConfig as ParsRedisCacheConfig, UpstashCacheConfig as ParsUpstashCacheConfig, cacheConfig, cacheGetResult, cacheStats, cloudflareKvConfig, memoryCacheConfig, multiTierCacheConfig, cacheSetOptions as parsCacheSetOptions, redisCacheConfig, type, upstashCacheConfig } from '@parsrun/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @parsrun/cache - Type Definitions
|
|
5
|
+
* Cache types and interfaces
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Cache adapter type
|
|
10
|
+
*/
|
|
11
|
+
type CacheAdapterType = "memory" | "redis" | "upstash" | "cloudflare-kv";
|
|
12
|
+
/**
|
|
13
|
+
* Cache entry with metadata
|
|
14
|
+
*/
|
|
15
|
+
interface CacheEntry<T = unknown> {
|
|
16
|
+
/** Cached value */
|
|
17
|
+
value: T;
|
|
18
|
+
/** Expiration timestamp (ms) */
|
|
19
|
+
expiresAt?: number | undefined;
|
|
20
|
+
/** Original TTL in seconds (for refresh/sliding expiration) */
|
|
21
|
+
ttlSeconds?: number | undefined;
|
|
22
|
+
/** Cache entry tags for invalidation */
|
|
23
|
+
tags?: string[] | undefined;
|
|
24
|
+
/** Cache entry metadata */
|
|
25
|
+
metadata?: Record<string, unknown> | undefined;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Cache get options
|
|
29
|
+
*/
|
|
30
|
+
interface CacheGetOptions {
|
|
31
|
+
/** Whether to update TTL on access (sliding expiration) */
|
|
32
|
+
refresh?: boolean | undefined;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Cache set options
|
|
36
|
+
*/
|
|
37
|
+
interface CacheSetOptions {
|
|
38
|
+
/** Time to live in seconds */
|
|
39
|
+
ttl?: number | undefined;
|
|
40
|
+
/** Tags for cache invalidation */
|
|
41
|
+
tags?: string[] | undefined;
|
|
42
|
+
/** Additional metadata */
|
|
43
|
+
metadata?: Record<string, unknown> | undefined;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Cache delete options
|
|
47
|
+
*/
|
|
48
|
+
interface CacheDeleteOptions {
|
|
49
|
+
/** Delete all entries with matching tags */
|
|
50
|
+
tags?: string[] | undefined;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Cache adapter interface
|
|
54
|
+
*/
|
|
55
|
+
interface CacheAdapter {
|
|
56
|
+
/** Adapter type */
|
|
57
|
+
readonly type: CacheAdapterType;
|
|
58
|
+
/**
|
|
59
|
+
* Get a value from cache
|
|
60
|
+
* @param key Cache key
|
|
61
|
+
* @param options Get options
|
|
62
|
+
* @returns Cached value or null if not found/expired
|
|
63
|
+
*/
|
|
64
|
+
get<T = unknown>(key: string, options?: CacheGetOptions): Promise<T | null>;
|
|
65
|
+
/**
|
|
66
|
+
* Set a value in cache
|
|
67
|
+
* @param key Cache key
|
|
68
|
+
* @param value Value to cache
|
|
69
|
+
* @param options Set options
|
|
70
|
+
*/
|
|
71
|
+
set<T = unknown>(key: string, value: T, options?: CacheSetOptions): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Delete a value from cache
|
|
74
|
+
* @param key Cache key
|
|
75
|
+
*/
|
|
76
|
+
delete(key: string): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Check if a key exists in cache
|
|
79
|
+
* @param key Cache key
|
|
80
|
+
*/
|
|
81
|
+
has(key: string): Promise<boolean>;
|
|
82
|
+
/**
|
|
83
|
+
* Clear all entries from cache
|
|
84
|
+
*/
|
|
85
|
+
clear?(): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Get multiple values at once
|
|
88
|
+
* @param keys Cache keys
|
|
89
|
+
*/
|
|
90
|
+
getMany?<T = unknown>(keys: string[]): Promise<Map<string, T | null>>;
|
|
91
|
+
/**
|
|
92
|
+
* Set multiple values at once
|
|
93
|
+
* @param entries Key-value pairs
|
|
94
|
+
* @param options Set options (applied to all)
|
|
95
|
+
*/
|
|
96
|
+
setMany?<T = unknown>(entries: Map<string, T>, options?: CacheSetOptions): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Delete multiple keys
|
|
99
|
+
* @param keys Cache keys
|
|
100
|
+
*/
|
|
101
|
+
deleteMany?(keys: string[]): Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Invalidate entries by tags
|
|
104
|
+
* @param tags Tags to invalidate
|
|
105
|
+
*/
|
|
106
|
+
invalidateByTags?(tags: string[]): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Get TTL for a key (in seconds)
|
|
109
|
+
* @param key Cache key
|
|
110
|
+
* @returns TTL in seconds, -1 if no expiry, -2 if key doesn't exist
|
|
111
|
+
*/
|
|
112
|
+
ttl?(key: string): Promise<number>;
|
|
113
|
+
/**
|
|
114
|
+
* Close/cleanup adapter resources
|
|
115
|
+
*/
|
|
116
|
+
close?(): Promise<void>;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Cache service configuration
|
|
120
|
+
*/
|
|
121
|
+
interface CacheServiceConfig {
|
|
122
|
+
/** Cache adapter to use */
|
|
123
|
+
adapter: CacheAdapter;
|
|
124
|
+
/** Default TTL in seconds */
|
|
125
|
+
defaultTtl?: number | undefined;
|
|
126
|
+
/** Key prefix for namespacing */
|
|
127
|
+
keyPrefix?: string | undefined;
|
|
128
|
+
/** Enable debug logging */
|
|
129
|
+
debug?: boolean | undefined;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Memory adapter configuration
|
|
133
|
+
*/
|
|
134
|
+
interface MemoryCacheConfig {
|
|
135
|
+
/** Maximum number of entries */
|
|
136
|
+
maxEntries?: number | undefined;
|
|
137
|
+
/** Cleanup interval in ms (default: 60000) */
|
|
138
|
+
cleanupInterval?: number | undefined;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Redis adapter configuration
|
|
142
|
+
*/
|
|
143
|
+
interface RedisCacheConfig {
|
|
144
|
+
/** Redis connection URL */
|
|
145
|
+
url?: string | undefined;
|
|
146
|
+
/** Redis host */
|
|
147
|
+
host?: string | undefined;
|
|
148
|
+
/** Redis port */
|
|
149
|
+
port?: number | undefined;
|
|
150
|
+
/** Redis password */
|
|
151
|
+
password?: string | undefined;
|
|
152
|
+
/** Redis database number */
|
|
153
|
+
db?: number | undefined;
|
|
154
|
+
/** Key prefix */
|
|
155
|
+
keyPrefix?: string | undefined;
|
|
156
|
+
/** Use TLS */
|
|
157
|
+
tls?: boolean | undefined;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Upstash adapter configuration
|
|
161
|
+
*/
|
|
162
|
+
interface UpstashCacheConfig {
|
|
163
|
+
/** Upstash Redis URL */
|
|
164
|
+
url: string;
|
|
165
|
+
/** Upstash Redis token */
|
|
166
|
+
token: string;
|
|
167
|
+
/** Key prefix */
|
|
168
|
+
keyPrefix?: string | undefined;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Cloudflare KV adapter configuration
|
|
172
|
+
*/
|
|
173
|
+
interface CloudflareKVCacheConfig {
|
|
174
|
+
/** KV namespace binding */
|
|
175
|
+
namespace: KVNamespace;
|
|
176
|
+
/** Key prefix */
|
|
177
|
+
keyPrefix?: string | undefined;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* KVNamespace interface (Cloudflare Workers)
|
|
181
|
+
*/
|
|
182
|
+
interface KVNamespace {
|
|
183
|
+
get(key: string, options?: {
|
|
184
|
+
type?: "text" | "json" | "arrayBuffer" | "stream";
|
|
185
|
+
}): Promise<string | null>;
|
|
186
|
+
get(key: string, options: {
|
|
187
|
+
type: "json";
|
|
188
|
+
}): Promise<unknown>;
|
|
189
|
+
put(key: string, value: string | ArrayBuffer | ReadableStream, options?: {
|
|
190
|
+
expiration?: number;
|
|
191
|
+
expirationTtl?: number;
|
|
192
|
+
metadata?: unknown;
|
|
193
|
+
}): Promise<void>;
|
|
194
|
+
delete(key: string): Promise<void>;
|
|
195
|
+
list(options?: {
|
|
196
|
+
prefix?: string | undefined;
|
|
197
|
+
limit?: number | undefined;
|
|
198
|
+
cursor?: string | undefined;
|
|
199
|
+
}): Promise<{
|
|
200
|
+
keys: Array<{
|
|
201
|
+
name: string;
|
|
202
|
+
expiration?: number;
|
|
203
|
+
metadata?: unknown;
|
|
204
|
+
}>;
|
|
205
|
+
list_complete: boolean;
|
|
206
|
+
cursor?: string;
|
|
207
|
+
}>;
|
|
208
|
+
getWithMetadata<T = unknown>(key: string, options?: {
|
|
209
|
+
type?: "text" | "json" | "arrayBuffer" | "stream";
|
|
210
|
+
}): Promise<{
|
|
211
|
+
value: string | null;
|
|
212
|
+
metadata: T | null;
|
|
213
|
+
}>;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Cache error
|
|
217
|
+
*/
|
|
218
|
+
declare class CacheError extends Error {
|
|
219
|
+
readonly code: string;
|
|
220
|
+
readonly cause?: unknown | undefined;
|
|
221
|
+
constructor(message: string, code: string, cause?: unknown | undefined);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Common cache error codes
|
|
225
|
+
*/
|
|
226
|
+
declare const CacheErrorCodes: {
|
|
227
|
+
readonly CONNECTION_FAILED: "CONNECTION_FAILED";
|
|
228
|
+
readonly OPERATION_FAILED: "OPERATION_FAILED";
|
|
229
|
+
readonly SERIALIZATION_ERROR: "SERIALIZATION_ERROR";
|
|
230
|
+
readonly INVALID_CONFIG: "INVALID_CONFIG";
|
|
231
|
+
readonly NOT_IMPLEMENTED: "NOT_IMPLEMENTED";
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
export { type CacheAdapter, type CacheAdapterType, type CacheDeleteOptions, type CacheEntry, CacheError, CacheErrorCodes, type CacheGetOptions, type CacheServiceConfig, type CacheSetOptions, type CloudflareKVCacheConfig, type KVNamespace, type MemoryCacheConfig, type RedisCacheConfig, type UpstashCacheConfig };
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
import {
|
|
3
|
+
type,
|
|
4
|
+
cacheSetOptions,
|
|
5
|
+
cacheGetResult,
|
|
6
|
+
cacheStats,
|
|
7
|
+
memoryCacheConfig,
|
|
8
|
+
redisCacheConfig,
|
|
9
|
+
upstashCacheConfig,
|
|
10
|
+
cloudflareKvConfig,
|
|
11
|
+
multiTierCacheConfig,
|
|
12
|
+
cacheConfig
|
|
13
|
+
} from "@parsrun/types";
|
|
14
|
+
var CacheError = class extends Error {
|
|
15
|
+
constructor(message, code, cause) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.code = code;
|
|
18
|
+
this.cause = cause;
|
|
19
|
+
this.name = "CacheError";
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var CacheErrorCodes = {
|
|
23
|
+
CONNECTION_FAILED: "CONNECTION_FAILED",
|
|
24
|
+
OPERATION_FAILED: "OPERATION_FAILED",
|
|
25
|
+
SERIALIZATION_ERROR: "SERIALIZATION_ERROR",
|
|
26
|
+
INVALID_CONFIG: "INVALID_CONFIG",
|
|
27
|
+
NOT_IMPLEMENTED: "NOT_IMPLEMENTED"
|
|
28
|
+
};
|
|
29
|
+
export {
|
|
30
|
+
CacheError,
|
|
31
|
+
CacheErrorCodes,
|
|
32
|
+
cacheConfig,
|
|
33
|
+
cacheGetResult,
|
|
34
|
+
cacheStats,
|
|
35
|
+
cloudflareKvConfig,
|
|
36
|
+
memoryCacheConfig,
|
|
37
|
+
multiTierCacheConfig,
|
|
38
|
+
cacheSetOptions as parsCacheSetOptions,
|
|
39
|
+
redisCacheConfig,
|
|
40
|
+
type,
|
|
41
|
+
upstashCacheConfig
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["/**\n * @parsrun/cache - Type Definitions\n * Cache types and interfaces\n */\n\n// Re-export types from @parsrun/types for convenience\nexport {\n type,\n cacheSetOptions as parsCacheSetOptions,\n cacheGetResult,\n cacheStats,\n memoryCacheConfig,\n redisCacheConfig,\n upstashCacheConfig,\n cloudflareKvConfig,\n multiTierCacheConfig,\n cacheConfig,\n type CacheSetOptions as ParsCacheSetOptions,\n type CacheGetResult,\n type CacheStats,\n type MemoryCacheConfig as ParsMemoryCacheConfig,\n type RedisCacheConfig as ParsRedisCacheConfig,\n type UpstashCacheConfig as ParsUpstashCacheConfig,\n type CloudflareKvConfig as ParsCloudflareKvConfig,\n type MultiTierCacheConfig,\n type CacheConfig,\n} from \"@parsrun/types\";\n\n/**\n * Cache adapter type\n */\nexport type CacheAdapterType = \"memory\" | \"redis\" | \"upstash\" | \"cloudflare-kv\";\n\n/**\n * Cache entry with metadata\n */\nexport interface CacheEntry<T = unknown> {\n /** Cached value */\n value: T;\n /** Expiration timestamp (ms) */\n expiresAt?: number | undefined;\n /** Original TTL in seconds (for refresh/sliding expiration) */\n ttlSeconds?: number | undefined;\n /** Cache entry tags for invalidation */\n tags?: string[] | undefined;\n /** Cache entry metadata */\n metadata?: Record<string, unknown> | undefined;\n}\n\n/**\n * Cache get options\n */\nexport interface CacheGetOptions {\n /** Whether to update TTL on access (sliding expiration) */\n refresh?: boolean | undefined;\n}\n\n/**\n * Cache set options\n */\nexport interface CacheSetOptions {\n /** Time to live in seconds */\n ttl?: number | undefined;\n /** Tags for cache invalidation */\n tags?: string[] | undefined;\n /** Additional metadata */\n metadata?: Record<string, unknown> | undefined;\n}\n\n/**\n * Cache delete options\n */\nexport interface CacheDeleteOptions {\n /** Delete all entries with matching tags */\n tags?: string[] | undefined;\n}\n\n/**\n * Cache adapter interface\n */\nexport interface CacheAdapter {\n /** Adapter type */\n readonly type: CacheAdapterType;\n\n /**\n * Get a value from cache\n * @param key Cache key\n * @param options Get options\n * @returns Cached value or null if not found/expired\n */\n get<T = unknown>(key: string, options?: CacheGetOptions): Promise<T | null>;\n\n /**\n * Set a value in cache\n * @param key Cache key\n * @param value Value to cache\n * @param options Set options\n */\n set<T = unknown>(key: string, value: T, options?: CacheSetOptions): Promise<void>;\n\n /**\n * Delete a value from cache\n * @param key Cache key\n */\n delete(key: string): Promise<void>;\n\n /**\n * Check if a key exists in cache\n * @param key Cache key\n */\n has(key: string): Promise<boolean>;\n\n /**\n * Clear all entries from cache\n */\n clear?(): Promise<void>;\n\n /**\n * Get multiple values at once\n * @param keys Cache keys\n */\n getMany?<T = unknown>(keys: string[]): Promise<Map<string, T | null>>;\n\n /**\n * Set multiple values at once\n * @param entries Key-value pairs\n * @param options Set options (applied to all)\n */\n setMany?<T = unknown>(entries: Map<string, T>, options?: CacheSetOptions): Promise<void>;\n\n /**\n * Delete multiple keys\n * @param keys Cache keys\n */\n deleteMany?(keys: string[]): Promise<void>;\n\n /**\n * Invalidate entries by tags\n * @param tags Tags to invalidate\n */\n invalidateByTags?(tags: string[]): Promise<void>;\n\n /**\n * Get TTL for a key (in seconds)\n * @param key Cache key\n * @returns TTL in seconds, -1 if no expiry, -2 if key doesn't exist\n */\n ttl?(key: string): Promise<number>;\n\n /**\n * Close/cleanup adapter resources\n */\n close?(): Promise<void>;\n}\n\n/**\n * Cache service configuration\n */\nexport interface CacheServiceConfig {\n /** Cache adapter to use */\n adapter: CacheAdapter;\n /** Default TTL in seconds */\n defaultTtl?: number | undefined;\n /** Key prefix for namespacing */\n keyPrefix?: string | undefined;\n /** Enable debug logging */\n debug?: boolean | undefined;\n}\n\n/**\n * Memory adapter configuration\n */\nexport interface MemoryCacheConfig {\n /** Maximum number of entries */\n maxEntries?: number | undefined;\n /** Cleanup interval in ms (default: 60000) */\n cleanupInterval?: number | undefined;\n}\n\n/**\n * Redis adapter configuration\n */\nexport interface RedisCacheConfig {\n /** Redis connection URL */\n url?: string | undefined;\n /** Redis host */\n host?: string | undefined;\n /** Redis port */\n port?: number | undefined;\n /** Redis password */\n password?: string | undefined;\n /** Redis database number */\n db?: number | undefined;\n /** Key prefix */\n keyPrefix?: string | undefined;\n /** Use TLS */\n tls?: boolean | undefined;\n}\n\n/**\n * Upstash adapter configuration\n */\nexport interface UpstashCacheConfig {\n /** Upstash Redis URL */\n url: string;\n /** Upstash Redis token */\n token: string;\n /** Key prefix */\n keyPrefix?: string | undefined;\n}\n\n/**\n * Cloudflare KV adapter configuration\n */\nexport interface CloudflareKVCacheConfig {\n /** KV namespace binding */\n namespace: KVNamespace;\n /** Key prefix */\n keyPrefix?: string | undefined;\n}\n\n/**\n * KVNamespace interface (Cloudflare Workers)\n */\nexport interface KVNamespace {\n get(key: string, options?: { type?: \"text\" | \"json\" | \"arrayBuffer\" | \"stream\" }): Promise<string | null>;\n get(key: string, options: { type: \"json\" }): Promise<unknown>;\n put(key: string, value: string | ArrayBuffer | ReadableStream, options?: { expiration?: number; expirationTtl?: number; metadata?: unknown }): Promise<void>;\n delete(key: string): Promise<void>;\n list(options?: { prefix?: string | undefined; limit?: number | undefined; cursor?: string | undefined }): Promise<{ keys: Array<{ name: string; expiration?: number; metadata?: unknown }>; list_complete: boolean; cursor?: string }>;\n getWithMetadata<T = unknown>(key: string, options?: { type?: \"text\" | \"json\" | \"arrayBuffer\" | \"stream\" }): Promise<{ value: string | null; metadata: T | null }>;\n}\n\n/**\n * Cache error\n */\nexport class CacheError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly cause?: unknown\n ) {\n super(message);\n this.name = \"CacheError\";\n }\n}\n\n/**\n * Common cache error codes\n */\nexport const CacheErrorCodes = {\n CONNECTION_FAILED: \"CONNECTION_FAILED\",\n OPERATION_FAILED: \"OPERATION_FAILED\",\n SERIALIZATION_ERROR: \"SERIALIZATION_ERROR\",\n INVALID_CONFIG: \"INVALID_CONFIG\",\n NOT_IMPLEMENTED: \"NOT_IMPLEMENTED\",\n} as const;\n"],"mappings":";AAMA;AAAA,EACE;AAAA,EACmB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAUK;AAkNA,IAAM,aAAN,cAAyB,MAAM;AAAA,EACpC,YACE,SACgB,MACA,OAChB;AACA,UAAM,OAAO;AAHG;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,kBAAkB;AAAA,EAC7B,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,gBAAgB;AAAA,EAChB,iBAAiB;AACnB;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@parsrun/cache",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Edge-compatible caching for Pars - Memory, Redis/Upstash, Cloudflare KV",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./types": {
|
|
15
|
+
"types": "./dist/types.d.ts",
|
|
16
|
+
"import": "./dist/types.js"
|
|
17
|
+
},
|
|
18
|
+
"./adapters": {
|
|
19
|
+
"types": "./dist/adapters/index.d.ts",
|
|
20
|
+
"import": "./dist/adapters/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./adapters/memory": {
|
|
23
|
+
"types": "./dist/adapters/memory.d.ts",
|
|
24
|
+
"import": "./dist/adapters/memory.js"
|
|
25
|
+
},
|
|
26
|
+
"./adapters/redis": {
|
|
27
|
+
"types": "./dist/adapters/redis.d.ts",
|
|
28
|
+
"import": "./dist/adapters/redis.js"
|
|
29
|
+
},
|
|
30
|
+
"./adapters/upstash": {
|
|
31
|
+
"types": "./dist/adapters/upstash.d.ts",
|
|
32
|
+
"import": "./dist/adapters/upstash.js"
|
|
33
|
+
},
|
|
34
|
+
"./adapters/cloudflare-kv": {
|
|
35
|
+
"types": "./dist/adapters/cloudflare-kv.d.ts",
|
|
36
|
+
"import": "./dist/adapters/cloudflare-kv.js"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"README.md"
|
|
42
|
+
],
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsup",
|
|
45
|
+
"dev": "tsup --watch",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"typecheck": "tsc --noEmit"
|
|
48
|
+
},
|
|
49
|
+
"keywords": [
|
|
50
|
+
"cache",
|
|
51
|
+
"redis",
|
|
52
|
+
"upstash",
|
|
53
|
+
"cloudflare-kv",
|
|
54
|
+
"edge",
|
|
55
|
+
"pars"
|
|
56
|
+
],
|
|
57
|
+
"author": "EMS Tech Solutions",
|
|
58
|
+
"license": "MIT",
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"@parsrun/core": "workspace:*",
|
|
61
|
+
"@parsrun/types": "workspace:*"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"tsup": "^8.0.0",
|
|
65
|
+
"typescript": "^5.0.0",
|
|
66
|
+
"vitest": "^2.0.0"
|
|
67
|
+
},
|
|
68
|
+
"peerDependencies": {
|
|
69
|
+
"@upstash/redis": "^1.0.0",
|
|
70
|
+
"ioredis": "^5.0.0"
|
|
71
|
+
},
|
|
72
|
+
"peerDependenciesMeta": {
|
|
73
|
+
"@upstash/redis": {
|
|
74
|
+
"optional": true
|
|
75
|
+
},
|
|
76
|
+
"ioredis": {
|
|
77
|
+
"optional": true
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|