Created
July 8, 2024 07:43
-
-
Save Aschen/55eaf738c424d4339960b46416044cd1 to your computer and use it in GitHub Desktop.
VCR for methods
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const YAML = require('yaml') | |
import Path from 'node:path' | |
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs' | |
import { createHash } from 'node:crypto' | |
export function vcr({ | |
instance, | |
methods, | |
mode = 'cache', | |
verbose = true, | |
basePath = '.cache', | |
}: { | |
instance: any | |
methods: string[] | |
mode?: 'record' | 'playback' | 'cache' | |
verbose?: boolean | |
basePath?: string | |
}) { | |
for (const method of methods) { | |
if (typeof instance[method] !== 'function') { | |
throw new Error(`"${instance.name}.${method} is not a function`) | |
} | |
const originalMethod = instance[method].bind(instance) | |
const className = instance.constructor.name | |
const mockPath = Path.join(basePath, className) | |
mkdirSync(mockPath, { recursive: true }) | |
verbose && | |
console.info( | |
`Wrap method "${className}.${method}" with cache mode ${mode}` | |
) | |
instance[method] = async function (...args: any[]) { | |
const hash = createHash('sha256') | |
.update(JSON.stringify(args)) | |
.digest('hex') | |
const filePath = Path.join(mockPath, `${hash}.yaml`) | |
const exists = existsSync(filePath) | |
if (!exists && mode === 'playback') { | |
throw new Error(`Cannot find cached result in playback mode`) | |
} | |
if (exists && mode === 'cache') { | |
verbose && | |
console.info(`Get cache for "${className}.${method}" at ${filePath}`) | |
return YAML.parse(readFileSync(filePath, 'utf-8')).result | |
} | |
console.log('vcr before') | |
const result = await originalMethod(...args) | |
console.log('vcr after') | |
if (mode !== 'playback') { | |
console.info(`Set cache for "${className}.${method}" at ${filePath}`) | |
writeFileSync( | |
filePath, | |
YAML.stringify({ | |
arguments: args, | |
result, | |
}) | |
) | |
} | |
return result | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment