prisma-cache-nosql
Version:
<div> <a href="https://www.npmjs.com/package/prisma-cache-nosql"> <img alt="npm" src="https://img.shields.io/npm/v/prisma-cache-nosql?logo=npm&logoColor=white"> </a> <a href="https://github.com/BearToCode/prisma-cache-nosql/blob/master/LICENSE"> <i
119 lines (116 loc) • 5.49 kB
JavaScript
import { Logger } from './utils/logger.js';
import { Prisma } from '@prisma/client';
import { DefaultCacheConfig } from './types.js';
export { SupportedOperations } from './types.js';
export { adapterAceBase } from './storage/acebase.js';
export { adapterMemory } from './storage/memory.js';
function cache(opts) {
const logger = new Logger(opts?.logLevel);
const db = opts.adapter({ logger });
return Prisma.defineExtension((client) => {
/**
* Call the base prisma client method.
* @param model The model name
* @param operation The operation to perform
* @returns The base result.
*/
const callBaseMethod = async (model, operation, args) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return client[model][operation](args);
};
/**
* Overwrite a prisma client method with caching.
* @param operation The operation to perform
* @returns The overwritten method.
*/
const overrideMethod = (operation) => {
return async function (args) {
const context = Prisma.getExtensionContext(this);
const model = context.$name;
if (!model) {
logger.error(`context.$name is undefined`);
throw new Error('context.$name is undefined');
}
let queryCacheArgs = undefined;
if (typeof args === 'object' && args !== null && !Array.isArray(args)) {
// If we don't do this TypeScript complains about wrong types
// Maybe there is a better way.
const _args = args;
queryCacheArgs = _args.cache ?? undefined;
delete _args.cache;
}
const cacheConfig = queryCacheArgs ?? opts.models?.[model] ?? opts.default ?? DefaultCacheConfig;
logger.debug(`Cache config for model ${model} with operation ${operation}: `, cacheConfig);
if (cacheConfig.get) {
const cached = await db.get({ model, operation, args });
const useCache = cached &&
(cached._cache.expires_at === false || cached._cache.expires_at > Date.now()) &&
(cacheConfig.get === true ||
cached._cache.cached_at + cacheConfig.get.max > Date.now());
if (useCache) {
logger.log(`Found cached value for model ${model} with operation ${operation}`);
logger.debug(`Found cached value with age ${(new Date().getTime() - cached._cache.cached_at).toFixed(0)}ms: `, cached);
return cached.result;
}
}
const base = await callBaseMethod(model, operation, args);
if (cacheConfig.set) {
const cached_at = Date.now();
const expires_at = cacheConfig.set === true ? false : cached_at + cacheConfig.set.ttl;
const pack = { result: base, _cache: { cached_at, expires_at } };
logger.log(`Set cache for model ${model} with operation ${operation}`);
logger.debug(`Set cache: `, pack);
await db.set({ model, operation, args }, pack);
}
return base;
};
};
return client.$extends({
name: 'prisma-cache',
model: {
$allModels: {
async findUnique(args) {
return overrideMethod('findUnique').call(this, args);
},
async findUniqueOrThrow(args) {
return overrideMethod('findUniqueOrThrow').call(this, args);
},
async findFirst(args) {
return overrideMethod('findFirst').call(this, args);
},
async findFirstOrThrow(args) {
return overrideMethod('findFirstOrThrow').call(this, args);
},
async findMany(args) {
return overrideMethod('findMany').call(this, args);
},
async count(args) {
return overrideMethod('count').call(this, args);
},
async aggregate(args) {
return overrideMethod('aggregate').call(this, args);
},
async groupBy(args) {
return overrideMethod('groupBy').call(this, args);
},
async clearCache() {
const context = Prisma.getExtensionContext(this);
const model = context.$name;
if (!model) {
logger.error(`context.$name is undefined`);
throw new Error('context.$name is undefined');
}
return db.clear(model);
}
}
},
client: {
async clearCache() {
return db.clearAll();
}
}
});
});
}
export { DefaultCacheConfig, cache };
//# sourceMappingURL=index.js.map