UNPKG

@chmoyle-conga/graphql-cart

Version:

Cart module for realtime subscriptions to conga cart

176 lines (175 loc) 8.28 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.onFinalize = exports.finalize = exports.initialize = exports.onDisplayActions = exports.configuration = exports.onConfiguration = exports.cart = exports.onCart = void 0; const core_1 = require("@apollo/client/core"); const lodash_1 = require("lodash"); const environment_1 = __importDefault(require("./environment")); const client_manager_1 = __importDefault(require("./client-manager")); // Error handling remains the same. const onError = (callback, error, _retryFn, attempts = 0) => { if (error.networkError && error.networkError.statusCode === 401 && _retryFn) { client_manager_1.default.initialize(); if (attempts < 3) _retryFn(attempts + 1); } if (callback.error) { callback.error(error); } else { console.error(error); } }; const subscriptionCache = new Map(); const dataCache = new Map(); // Abstracted function to handle query execution with retry logic. function executeQueryWithRetry(entity, cartId, query, callback, opts, attempts = 0) { // Extract pageNumber and pageSize if they exist, otherwise don't set defaults here const pageNumber = opts === null || opts === void 0 ? void 0 : opts.pageNumber; const pageSize = opts === null || opts === void 0 ? void 0 : opts.pageSize; const flowName = opts === null || opts === void 0 ? void 0 : opts.flowName; const filters = opts === null || opts === void 0 ? void 0 : opts.filters; // Construct arguments string conditionally based on the presence of pageNumber and pageSize let args = `id: "${cartId}"`; if (pageNumber !== undefined) args += `, pageNumber: ${pageNumber}`; if (pageSize !== undefined) args += `, pageSize: ${pageSize}`; if (flowName !== undefined) args += `, flowName: "${flowName}"`; if (filters !== undefined) args += `, filters: ${JSON.stringify(filters)}`; // Construct the gql query with conditional arguments const gqlQuery = (0, core_1.gql) `query { ${entity}(${args}) ${query} }`; // Build query options, only include fetchPolicy if explicitly provided const queryOptions = { query: gqlQuery }; if (opts === null || opts === void 0 ? void 0 : opts.fetchPolicy) { queryOptions.fetchPolicy = opts.fetchPolicy; } client_manager_1.default.client.query(queryOptions).then((result) => { if (result.data) { callback.next((0, lodash_1.cloneDeep)(result.data[entity])); } }).catch((error) => onError(callback, error, () => executeQueryWithRetry(entity, cartId, query, callback, opts, attempts + 1), attempts)); } // Abstracted function for subscription logic. function subscribeToUpdates(entity, subscriptionEntity, cartId, query, callback, opts) { const key = `${entity}-${cartId}-${subscriptionEntity}-${JSON.stringify(opts)}`; // Extract pageNumber and pageSize if they exist, otherwise don't set defaults here const pageNumber = opts === null || opts === void 0 ? void 0 : opts.pageNumber; const pageSize = opts === null || opts === void 0 ? void 0 : opts.pageSize; // Construct arguments string conditionally based on the presence of pageNumber and pageSize let args = `id: "${cartId}"`; if (pageNumber !== undefined) args += `, pageNumber: ${pageNumber}`; if (pageSize !== undefined) args += `, pageSize: ${pageSize}`; if (opts && opts.delta !== undefined) args += `, delta: ${opts.delta}`; if (opts && opts.flowName) args += `, flowName: "${opts.flowName}"`; if (opts && opts.filters) args += `, filters: ${JSON.stringify(opts.filters)}`; // Construct the subscription query with conditional arguments const subscriptionQuery = ` subscription { ${subscriptionEntity}(${args}) ${query} } `; const subscription = client_manager_1.default.sseClient.subscribe({ query: subscriptionQuery }, { next: (data) => { try { const oldData = dataCache.get(key); const newData = (0, lodash_1.cloneDeep)(data.data[subscriptionEntity]); if (opts === null || opts === void 0 ? void 0 : opts.disableFilter) { dataCache.set(key, newData); callback.next(newData, oldData); } else { if ((0, lodash_1.isNil)(oldData) || !(0, lodash_1.isEqual)(oldData, newData)) { dataCache.set(key, newData); callback.next(newData, oldData); } } } catch (e) { if (data && data.data) { callback.next((0, lodash_1.cloneDeep)(data.data)); } else if (data && data.errors) { onError(callback, data.errors); } else { onError(callback, e); } } }, error: (error) => onError(callback, error), complete: () => { } }); if (subscriptionCache.has(key)) subscriptionCache.get(key)(); subscriptionCache.set(key, subscription); return subscription; } // Unified function to replace _onCart, _onConfiguration, _onDisplayActions function onEntityUpdate(entity, subscriptionEntity, cartId, query, callback, opts) { const key = `${entity}-${cartId}-${subscriptionEntity}-${JSON.stringify(opts)}`; if (opts === null || opts === void 0 ? void 0 : opts.takeSnapshot) { executeQueryWithRetry(entity, cartId, query, callback, opts); } const fn = subscribeToUpdates(entity, subscriptionEntity, cartId, query, callback, opts); return { unsubscribe: () => { fn(); subscriptionCache.delete(key); client_manager_1.default.client.cache.reset(); } }; } // Memoized wrappers const onCart = (cartId, query, callback, opts) => onEntityUpdate('cart', 'onCartStatus', cartId, query, callback, opts); exports.onCart = onCart; const onConfiguration = (cartId, query, callback, opts) => onEntityUpdate('configuration', 'onConfiguration', cartId, query, callback, opts); exports.onConfiguration = onConfiguration; const onDisplayActions = (cartId, query, callback, opts) => onEntityUpdate('displayActions', 'onDisplayAction', cartId, query, callback, opts); exports.onDisplayActions = onDisplayActions; const onFinalize = (cartId, query, callback, opts) => onEntityUpdate('finalize', 'onFinalize', cartId, query, callback, opts); exports.onFinalize = onFinalize; const cart = (cartId, query, opts) => { return new Promise((resolve, reject) => { executeQueryWithRetry('cart', cartId, query, { next: (cart) => resolve(cart), error: (error) => reject(error) }, opts); }); }; exports.cart = cart; const configuration = (cartId, query, opts) => { return new Promise((resolve, reject) => { executeQueryWithRetry('configuration', cartId, query, { next: (config) => resolve(config), error: (error) => reject(error) }, opts); }); }; exports.configuration = configuration; const finalize = (cartId, query, opts) => { return new Promise((resolve, reject) => { executeQueryWithRetry('finalize', cartId, query, { next: (finalize) => resolve(finalize), error: (error) => reject(error) }, opts); }); }; exports.finalize = finalize; function memoizationResolver(cartId, query, callback, opts) { return `${cartId}-${query}-${(opts === null || opts === void 0 ? void 0 : opts.pageNumber) || 1}-${(opts === null || opts === void 0 ? void 0 : opts.pageSize) || 500}`; } const initialize = (_environment) => { environment_1.default.initialize(_environment); client_manager_1.default.initialize(); }; exports.initialize = initialize;