@chmoyle-conga/graphql-cart
Version:
Cart module for realtime subscriptions to conga cart
176 lines (175 loc) • 8.28 kB
JavaScript
;
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;