cachetta
v0.4.0
Published
File-based caching for TypeScript. Part of the [Cachetta](https://github.com/thekevinscott/cachetta) project, which provides the same caching API in TypeScript and Python -- learn it once, use it in either language.
Readme
Cachetta for TypeScript
File-based caching for TypeScript. Part of the Cachetta project, which provides the same caching API in TypeScript and Python -- learn it once, use it in either language.
Three doc layers: this README (overview), the docs/ folder bundled with this package, and the hosted docs site. Each ## below mirrors a section in docs/javascript.md.
Install
pnpm add cachettaBasic Usage
import { Cachetta, readCache, writeCache } from 'cachetta';
const cache = new Cachetta({
path: './cache.json',
duration: 24 * 60 * 60 * 1000, // 1 day
});
const data = await readCache(cache);
if (!data) await writeCache(cache, await fetchData());Decorators
class DataService {
@Cachetta({ path: '/my-cache.json' })
async getData() { return await fetchData(); }
}Decorated functions always return Promises, even when the original is sync.
Function Wrapper
const cache = new Cachetta({ path: './my-cache.json' });
const cachedGetData = cache(async () => fetchData());
const result = await cachedGetData();Sync API
import { writeCacheSync, readCacheSync } from 'cachetta';
writeCacheSync(cache, { data: 1 });
const data = readCacheSync(cache);
cache.invalidateSync();Per-Argument Cache Files
Pass a function path to vary the cache file by argument. A string path is used verbatim regardless of arguments.
Conditional Caching
const cache = new Cachetta({
path: './cache.json',
condition: (result) => result !== null,
});Stale-While-Revalidate
const cache = new Cachetta({
path: './cache.json',
duration: 60 * 60 * 1000,
staleDuration: 30 * 60 * 1000,
});Cache Invalidation
await cache.invalidate(); // delete the resolved cache file unconditionallyClearing the Cache
await cache.clear(); // sweep dead entries (past duration + staleDuration)
await cache.clear({ force: true }); // remove the whole path, folder and allCache Inspection
await cache.exists(); // boolean
await cache.age(); // ms or null
await cache.info(); // { exists, age, expired, stale, path }Dynamic Cache Paths
@Cachetta({ path: (n) => `./cache/${n}.json` })
async function foo(n) { /* ... */ }Specifying Paths
const newCache = cache.copy({ read: false, duration: 2 * 24 * 60 * 60 * 1000 });Path Contract
path is trusted input, used exactly as given — no sandboxing, no traversal
checks. Never derive it from untrusted data.
Error Handling
readCache returns null for missing or corrupt files.
Logging
import { setLogLevel, setLogger } from 'cachetta';
setLogLevel('debug');Configuration Reference
| Option | Type | Default |
|---|---|---|
| path | string \| Function | required |
| read / write | boolean | true |
| duration | number (ms) | 7 days |
| condition | Function | undefined |
| staleDuration | number | undefined |
