UNPKG

@graphql-mesh/plugin-response-cache

Version:
113 lines (112 loc) 4.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const plugin_response_cache_1 = require("@graphql-yoga/plugin-response-cache"); const string_interpolation_1 = require("@graphql-mesh/string-interpolation"); const cross_helpers_1 = require("@graphql-mesh/cross-helpers"); const defaultBuildResponseCacheKey = async (params) => (0, string_interpolation_1.hashObject)(params); function generateSessionIdFactory(sessionIdDef) { if (sessionIdDef == null) { return function voidSession() { return null; }; } return function session(context) { return string_interpolation_1.stringInterpolator.parse(sessionIdDef, { context, env: cross_helpers_1.process.env, }); }; } function generateEnabledFactory(ifDef) { return function enabled(context) { // eslint-disable-next-line no-new-func return new Function(`return ${ifDef}`)(); }; } function getBuildResponseCacheKey(cacheKeyDef) { return function buildResponseCacheKey(cacheKeyParameters) { let cacheKey = string_interpolation_1.stringInterpolator.parse(cacheKeyDef, { ...cacheKeyParameters, env: cross_helpers_1.process.env, }); if (!cacheKey) { cacheKey = defaultBuildResponseCacheKey(cacheKeyParameters); } return cacheKey; }; } function getShouldCacheResult(shouldCacheResultDef) { return function shouldCacheResult({ result }) { // eslint-disable-next-line no-new-func return new Function(`return ${shouldCacheResultDef}`)(); }; } function getCacheForResponseCache(meshCache) { return { get(responseId) { return meshCache.get(`response-cache:${responseId}`); }, async set(responseId, data, entities, ttl) { const ttlConfig = Number.isFinite(ttl) ? { ttl: ttl / 1000 } : undefined; await Promise.all([...entities].map(async ({ typename, id }) => { const entryId = `${typename}.${id}`; await meshCache.set(`response-cache:${entryId}:${responseId}`, {}, ttlConfig); await meshCache.set(`response-cache:${responseId}:${entryId}`, {}, ttlConfig); })); return meshCache.set(`response-cache:${responseId}`, data, ttlConfig); }, async invalidate(entitiesToRemove) { const responseIdsToCheck = new Set(); await Promise.all([...entitiesToRemove].map(async ({ typename, id }) => { const entryId = `${typename}.${id}`; const cacheEntriesToDelete = await meshCache.getKeysByPrefix(`response-cache:${entryId}:`); await Promise.all(cacheEntriesToDelete.map(cacheEntryName => { const [, , responseId] = cacheEntryName.split(':'); responseIdsToCheck.add(responseId); return meshCache.delete(entryId); })); })); await Promise.all([...responseIdsToCheck].map(async (responseId) => { const cacheEntries = await meshCache.getKeysByPrefix(`response-cache:${responseId}:`); if (cacheEntries.length === 0) { await meshCache.delete(`response-cache:${responseId}`); } })); }, }; } function useMeshResponseCache(options) { const ttlPerType = {}; const ttlPerSchemaCoordinate = {}; if (options.ttlPerCoordinate) { for (const ttlConfig of options.ttlPerCoordinate) { if (ttlConfig.coordinate.includes('.')) { ttlPerSchemaCoordinate[ttlConfig.coordinate] = ttlConfig.ttl; } else { ttlPerType[ttlConfig.coordinate] = ttlConfig.ttl; } } } return (0, plugin_response_cache_1.useResponseCache)({ ttl: options.ttl, ignoredTypes: options.ignoredTypes, idFields: options.idFields, invalidateViaMutation: options.invalidateViaMutation, includeExtensionMetadata: options.includeExtensionMetadata != null ? options.includeExtensionMetadata : cross_helpers_1.process.env.DEBUG === '1', ttlPerType, ttlPerSchemaCoordinate, session: generateSessionIdFactory(options.sessionId), enabled: options.if ? generateEnabledFactory(options.if) : undefined, buildResponseCacheKey: options.cacheKey ? getBuildResponseCacheKey(options.cacheKey) : undefined, shouldCacheResult: options.shouldCacheResult ? getShouldCacheResult(options.shouldCacheResult) : undefined, cache: getCacheForResponseCache(options.cache), }); } exports.default = useMeshResponseCache;