UNPKG

@quell/server

Version:

Quell is an open-source NPM package providing a light-weight caching layer implementation and cache invalidation for GraphQL responses on both the client- and server-side. Use Quell to prevent redundant client-side API requests and to minimize costly serv

126 lines (125 loc) 6.46 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createNormalizeForCache = void 0; /** * Creates a normalizeForCache function with the provided configuration * This is the main normalization logic that processes GraphQL responses * and prepares them for caching * @param config - Configuration object * @returns Bound normalizeForCache function */ function createNormalizeForCache(config) { const { writeToCache, updateIdCache } = config; /** * Traverses over response data and formats it appropriately so that it can be stored in the cache. * @param {Object} responseData - Data we received from an external source of data such as a database or API. * @param {Object} map - Map of queries to their desired data types, used to ensure accurate and consistent caching. * @param {Object} protoField - Slice of the prototype currently being used as a template and reference for the responseData to send information to the cache. * @param {string} currName - Parent object name, used to pass into updateIDCache. */ function normalizeForCache(responseData, map = {}, protoField, currName) { return __awaiter(this, void 0, void 0, function* () { console.log("=== NORMALIZE FOR CACHE ==="); console.log("Response Data:", JSON.stringify(responseData, null, 2)); console.log("Proto Field:", JSON.stringify(protoField, null, 2)); // Add safety check if (!responseData) { console.log("ERROR: responseData is undefined or null"); return; } for (const resultName in responseData) { const currField = responseData[resultName]; const currProto = protoField[resultName]; console.log(`Processing field: ${resultName}`); console.log(`currField:`, currField); console.log(`currProto:`, currProto); // Add safety check here too if (!currProto) { console.log(`ERROR: currProto is undefined for field ${resultName}`); continue; } if (Array.isArray(currField)) { yield processArrayData(currField, map, currProto, resultName, currName); } else if (typeof currField === "object") { yield processObjectData(currField, currProto, map, currName, resultName, protoField, responseData); } } }); } /** * Helper function to process array data during normalization */ function processArrayData(currField, map, currProto, resultName, currName) { return __awaiter(this, void 0, void 0, function* () { console.log("=== PROCESSING ARRAY DATA ==="); console.log("Skipping individual array item caching - arrays stored with parent object only"); }); } /** * Helper function to process object data during normalization */ function processObjectData(currField, currProto, map, currName, resultName, protoField, responseData) { return __awaiter(this, void 0, void 0, function* () { // Need to get non-Alias ID for cache // Temporary store for field properties const fieldStore = {}; // Create a cacheID based on __type and __id from the prototype let cacheID = Object.prototype.hasOwnProperty.call(map, currProto.__type) ? map[currProto.__type] : currProto.__type; cacheID += currProto.__id ? `--${currProto.__id}` : ""; // Process each key in the object for (const key in currField) { // Check for ID fields and update cache accordingly if (!currProto.__id && (key === "id" || key === "_id" || key === "ID" || key === "Id")) { const updatedCurrName = updateCurrentName(responseData, cacheID, currName); const cacheIDForIDCache = cacheID; cacheID += `--${currField[key]}`; updateIdCache(cacheIDForIDCache, cacheID, updatedCurrName); } fieldStore[key] = currField[key]; // Recursively process nested objects if (typeof currField[key] === "object" && protoField[resultName] !== null) { yield normalizeForCache({ [key]: currField[key] }, map, { [key]: protoField[resultName][key], }, currName); } } console.log("=== ABOUT TO WRITE TO CACHE ==="); console.log("Cache ID:", cacheID); console.log("Field Store (what will be cached):", JSON.stringify(fieldStore, null, 2)); console.log("Current Field (from response):", JSON.stringify(currField, null, 2)); // Store the object in cache writeToCache(cacheID, fieldStore); }); } /** * Helper function to update the current name based on response data */ function updateCurrentName(responseData, cacheID, currName) { if (responseData[cacheID.toLowerCase()]) { const responseDataAtCacheID = responseData[cacheID.toLowerCase()]; if (typeof responseDataAtCacheID !== "string" && !Array.isArray(responseDataAtCacheID)) { if (typeof responseDataAtCacheID.name === "string") { return responseDataAtCacheID.name; } } } return currName; } return normalizeForCache; } exports.createNormalizeForCache = createNormalizeForCache;