UNPKG

mlld

Version:

mlld: a modular prompt scripting language

1 lines 12.9 kB
{"version":3,"sources":["../core/security/ImmutableCache.ts"],"names":["ImmutableCache","constructor","projectPath","options","cacheDir","inMemory","memoryCache","Map","isServerless","startsWith","process","env","LAMBDA_TASK_ROOT","VERCEL","AWS_LAMBDA_FUNCTION_NAME","join","get","url","expectedHash","MLLD_TEST","urlHash","hashUrl","entry","contentHash","content","cachePath","metaPath","metaContent","readFile","meta","JSON","parse","actualHash","createHash","update","digest","remove","error","set","cachedAt","Date","toISOString","size","length","mkdir","recursive","writeFile","stringify","delete","unlink","clear","rm","force","getStats","totalSize","urls","values","push","entries","files","readdir","metaFiles","filter","f","endsWith","metaFile"],"mappings":"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","file":"chunk-RO3YC7AJ.mjs","sourcesContent":["import * as fs from 'fs/promises';\nimport * as path from 'path';\nimport { createHash } from 'crypto';\n\ninterface CacheEntry {\n content: string;\n contentHash: string;\n url: string;\n cachedAt: string;\n size: number;\n}\n\nexport interface ImmutableCacheOptions {\n inMemory?: boolean;\n}\n\nexport class ImmutableCache {\n private cacheDir?: string;\n private inMemory: boolean;\n private memoryCache: Map<string, CacheEntry>;\n \n constructor(projectPath: string, options?: ImmutableCacheOptions) {\n this.inMemory = options?.inMemory || false;\n this.memoryCache = new Map();\n \n if (this.inMemory) {\n // In-memory mode - no filesystem operations\n return;\n }\n \n // In serverless/read-only environments, use /tmp\n // Detect by checking if we're in /var/task (Vercel) or if LAMBDA_TASK_ROOT is set (AWS Lambda)\n const isServerless = projectPath.startsWith('/var/task') || \n process.env.LAMBDA_TASK_ROOT || \n process.env.VERCEL || \n process.env.AWS_LAMBDA_FUNCTION_NAME;\n \n if (isServerless) {\n // Use /tmp which is writable in serverless environments\n this.cacheDir = path.join('/tmp', '.mlld', 'cache', 'imports');\n } else {\n // Store cache in .mlld/cache directory\n this.cacheDir = path.join(projectPath, '.mlld', 'cache', 'imports');\n }\n }\n\n /**\n * Get cached content by URL and hash\n */\n async get(url: string, expectedHash?: string): Promise<string | null> {\n // In test mode, always return cache miss\n if (process.env.MLLD_TEST === '1') {\n return null;\n }\n \n const urlHash = this.hashUrl(url);\n \n // Handle in-memory mode\n if (this.inMemory) {\n const entry = this.memoryCache.get(urlHash);\n if (!entry) return null;\n \n // If hash provided, verify it matches\n if (expectedHash && entry.contentHash !== expectedHash) {\n return null;\n }\n \n return entry.content;\n }\n \n // Filesystem mode\n const cachePath = path.join(this.cacheDir!, urlHash);\n \n try {\n // Read metadata\n const metaPath = `${cachePath}.meta.json`;\n const metaContent = await fs.readFile(metaPath, 'utf8');\n const meta = JSON.parse(metaContent);\n \n // If hash provided, verify it matches\n if (expectedHash && meta.contentHash !== expectedHash) {\n return null;\n }\n \n // Read cached content\n const content = await fs.readFile(cachePath, 'utf8');\n \n // Verify integrity\n const actualHash = createHash('sha256').update(content, 'utf8').digest('hex');\n if (actualHash !== meta.contentHash) {\n // Cache corrupted, remove it\n await this.remove(url);\n return null;\n }\n \n return content;\n } catch (error) {\n // Cache miss or error\n return null;\n }\n }\n\n /**\n * Store content in cache\n */\n async set(url: string, content: string): Promise<string> {\n // In test mode, skip caching\n if (process.env.MLLD_TEST === '1') {\n return createHash('sha256').update(content, 'utf8').digest('hex');\n }\n \n const urlHash = this.hashUrl(url);\n const contentHash = createHash('sha256').update(content, 'utf8').digest('hex');\n \n // Handle in-memory mode\n if (this.inMemory) {\n const entry: CacheEntry = {\n url,\n content,\n contentHash,\n cachedAt: new Date().toISOString(),\n size: content.length\n };\n this.memoryCache.set(urlHash, entry);\n return contentHash;\n }\n \n // Filesystem mode\n // Ensure cache directory exists\n await fs.mkdir(this.cacheDir!, { recursive: true });\n \n const cachePath = path.join(this.cacheDir!, urlHash);\n \n // Write content\n await fs.writeFile(cachePath, content, 'utf8');\n \n // Write metadata\n const meta = {\n url,\n contentHash,\n cachedAt: new Date().toISOString(),\n size: content.length\n };\n await fs.writeFile(`${cachePath}.meta.json`, JSON.stringify(meta, null, 2));\n \n return contentHash;\n }\n\n /**\n * Remove cached entry\n */\n async remove(url: string): Promise<void> {\n const urlHash = this.hashUrl(url);\n \n // Handle in-memory mode\n if (this.inMemory) {\n this.memoryCache.delete(urlHash);\n return;\n }\n \n // Filesystem mode\n const cachePath = path.join(this.cacheDir!, urlHash);\n \n try {\n await fs.unlink(cachePath);\n await fs.unlink(`${cachePath}.meta.json`);\n } catch {\n // Ignore if doesn't exist\n }\n }\n\n /**\n * Clear entire cache\n */\n async clear(): Promise<void> {\n // Handle in-memory mode\n if (this.inMemory) {\n this.memoryCache.clear();\n return;\n }\n \n // Filesystem mode\n try {\n await fs.rm(this.cacheDir!, { recursive: true, force: true });\n } catch {\n // Ignore if doesn't exist\n }\n }\n\n /**\n * Get cache statistics\n */\n async getStats(): Promise<{\n entries: number;\n totalSize: number;\n urls: string[];\n }> {\n // Handle in-memory mode\n if (this.inMemory) {\n let totalSize = 0;\n const urls: string[] = [];\n \n for (const entry of this.memoryCache.values()) {\n totalSize += entry.size;\n urls.push(entry.url);\n }\n \n return {\n entries: this.memoryCache.size,\n totalSize,\n urls\n };\n }\n \n // Filesystem mode\n try {\n const files = await fs.readdir(this.cacheDir!);\n const metaFiles = files.filter(f => f.endsWith('.meta.json'));\n \n let totalSize = 0;\n const urls: string[] = [];\n \n for (const metaFile of metaFiles) {\n const metaPath = path.join(this.cacheDir!, metaFile);\n const metaContent = await fs.readFile(metaPath, 'utf8');\n const meta = JSON.parse(metaContent);\n \n totalSize += meta.size || 0;\n urls.push(meta.url);\n }\n \n return {\n entries: metaFiles.length,\n totalSize,\n urls\n };\n } catch {\n return {\n entries: 0,\n totalSize: 0,\n urls: []\n };\n }\n }\n\n private hashUrl(url: string): string {\n return createHash('sha256').update(url, 'utf8').digest('hex');\n }\n}"]}