mlld
Version:
mlld: llm scripting language
1 lines • 11.5 kB
Source Map (JSON)
{"version":3,"sources":["../core/security/ImmutableCache.ts"],"names":[],"mappings":"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","file":"chunk-VXCS2D4R.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}"]}