import Webhook from "./webhook"; // Store any repeated body parameters in an array // and replace them in the webhook with an index in the array export function deduplicateWebhooks(webhooks: Record>): any[] { /** * Build a map of all objects by name */ const objectsByName: Record = {}; const objectCount: Record = {}; for (const webhook of iterateWebhooks(webhooks)) { for (const param of webhook.bodyParameters) { objectsByName[param.name] ||= []; const index = findOrAdd(param, objectsByName[param.name]); const key = `${param.name}:${index}`; objectCount[key] ||= 0; objectCount[key]++; } } /** * Replace any duplicated body parameters with an index */ const duplicatedBodyParams: any[] = []; const bodyParamIndexMap: Record = {}; for (const webhook of iterateWebhooks(webhooks)) { const newParams: any[] = []; for (const param of webhook.bodyParameters) { const index = find(param, objectsByName[param.name]); const key = `${param.name}:${index}`; if (objectCount[key] > 1) { newParams.push(indexForParam(param, index, bodyParamIndexMap, duplicatedBodyParams)); } else { // If an object is only used once, keep it inline newParams.push(param); } } webhook.bodyParameters = newParams; } return duplicatedBodyParams; } function* iterateWebhooks(webhooks: Record>) { for (const webhookActions of Object.values(webhooks)) { for (const webhook of Object.values(webhookActions)) { yield webhook; } } } function findOrAdd(param: any, objects: any[]): number { for (const [index, object] of objects.entries()) { if (JSON.stringify(object) === JSON.stringify(param)) { return index; } } return objects.push(param) - 1; } function find(param: any, objects: any[]): number { for (const [index, object] of objects.entries()) { if (JSON.stringify(object) === JSON.stringify(param)) { return index; } } throw new Error(`Could not find object ${param.name}`); } function indexForParam( param: any, paramNameIndex: number, objectIndexMap: Record, duplicatedBodyParams: any[] ): number { const key = `${param.name}:${paramNameIndex}`; const existingIndex = objectIndexMap[key]; if (existingIndex !== undefined) { // Object has already been added to the array return existingIndex; } // Add the object to the array const objIdx = duplicatedBodyParams.push(param) - 1; objectIndexMap[key] = objIdx; return objIdx; }