import { isEqual } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; import { isValidMultiStepDef, isValidStepDef, TriggerStepType, ValidStepDef } from '../types/page/event.js'; import { refactorNameInCode, refactorNameInValue, ScopedDataTree } from './refactor.js'; import { Extractor } from './types.js'; type AddUpdate = (value: { propertyName: string; propertyValue: unknown }) => void; export function createTriggerStepRenamer({ oldName, newName, dataTree, addUpdate, extractEvaluationPairs, updateStepIds, namespace }: { oldName: string; newName: string; dataTree: ScopedDataTree; extractEvaluationPairs: Extractor; addUpdate: AddUpdate; updateStepIds?: boolean; // whether or not to regenerate IDs namespace?: string; }) { const renameInTriggerStep = async (step: ValidStepDef, key: string, index: number) => { if (!isValidStepDef(step)) return; if (updateStepIds) { addUpdate({ propertyName: `${key}[${index}].id`, propertyValue: uuidv4() }); } switch (step.type) { case TriggerStepType.RUN_APIS: { if (step.apiNames) { const newValue = step.apiNames.map((name) => (name === oldName ? newName : name)); if (!isEqual(step.apiNames, newValue)) { addUpdate({ propertyName: `${key}[${index}].apiNames`, propertyValue: newValue }); } } if (step.onSuccess && isValidMultiStepDef(step.onSuccess)) { let i = 0; for (const nestedStep of step.onSuccess) { await renameInTriggerStep(nestedStep, `${key}[${index}].onSuccess`, i++); } } if (step.onError && isValidMultiStepDef(step.onError)) { let i = 0; for (const nestedStep of step.onError) { await renameInTriggerStep(nestedStep, `${key}[${index}].onError`, i++); } } break; } case TriggerStepType.CANCEL_APIS: { if (step.apiNames) { const newValue = step.apiNames.map((name) => (name === oldName ? newName : name)); if (!isEqual(step.apiNames, newValue)) { addUpdate({ propertyName: `${key}[${index}].apiNames`, propertyValue: newValue }); } } break; } case TriggerStepType.RUN_JS: { const newValue = await refactorNameInCode({ value: step.code ?? '', oldName, newName, dataTree, extractPairs: extractEvaluationPairs, namespace }); if (!isEqual(step.code, newValue)) { addUpdate({ propertyName: `${key}[${index}].code`, propertyValue: newValue }); } break; } case TriggerStepType.CONTROL_SLIDEOUT: /* falls through */ case TriggerStepType.CONTROL_MODAL: /* falls through */ case TriggerStepType.CONTROL_TIMER: { if (step.name === oldName) { addUpdate({ propertyName: `${key}[${index}].name`, propertyValue: newName }); } break; } case TriggerStepType.NAVIGATE_TO: { const newValue = await refactorNameInValue({ oldValue: step.url, oldName, newName, dataTree, extractPairs: extractEvaluationPairs, namespace }); if (!isEqual(step.url, newValue)) { addUpdate({ propertyName: `${key}[${index}].url`, propertyValue: newValue }); } break; } case TriggerStepType.NAVIGATE_TO_APP: { const newValue = await refactorNameInValue({ oldValue: step.queryParams, oldName, newName, dataTree, extractPairs: extractEvaluationPairs, namespace }); if (!isEqual(step.queryParams, newValue)) { addUpdate({ propertyName: `${key}[${index}].queryParams`, propertyValue: newValue }); } break; } case TriggerStepType.NAVIGATE_TO_ROUTE: { const newQueryParams = await refactorNameInValue({ oldValue: step.queryParams, oldName, newName, dataTree, extractPairs: extractEvaluationPairs, namespace }); const newRouteParams = await refactorNameInValue({ oldValue: step.routeParams, oldName, newName, dataTree, extractPairs: extractEvaluationPairs, namespace }); if (!isEqual(step.queryParams, newQueryParams)) { addUpdate({ propertyName: `${key}[${index}].queryParams`, propertyValue: newQueryParams }); } if (!isEqual(step.routeParams, newRouteParams)) { addUpdate({ propertyName: `${key}[${index}].routeParams`, propertyValue: newRouteParams }); } break; } case TriggerStepType.SET_QUERY_PARAMS: { const newQueryParams = await refactorNameInValue({ oldValue: step.queryParams, oldName, newName, dataTree, extractPairs: extractEvaluationPairs, namespace }); if (!isEqual(step.queryParams, newQueryParams)) { addUpdate({ propertyName: `${key}[${index}].queryParams`, propertyValue: newQueryParams }); } break; } case TriggerStepType.SET_STATE_VAR: { const newValue = await refactorNameInValue({ oldValue: step.value, oldName, newName, dataTree, extractPairs: extractEvaluationPairs, namespace }); if (!isEqual(step.value, newValue)) { addUpdate({ propertyName: `${key}[${index}].value`, propertyValue: newValue }); } if (step.state?.name === oldName) { addUpdate({ propertyName: `${key}[${index}].state.name`, propertyValue: newName }); } break; } case TriggerStepType.RESET_STATE_VAR: { if (step.state?.name === oldName) { addUpdate({ propertyName: `${key}[${index}].state.name`, propertyValue: newName }); } break; } case TriggerStepType.RESET_COMPONENT: { if (step.widget?.name === oldName) { addUpdate({ propertyName: `${key}[${index}].widget.name`, propertyValue: newName }); } break; } case TriggerStepType.SET_COMPONENT_PROPERTY: { if (step.widget?.name === oldName) { addUpdate({ propertyName: `${key}[${index}].widget.name`, propertyValue: newName }); } const newValue = await refactorNameInValue({ oldValue: step.propertyValue, oldName, newName, dataTree, extractPairs: extractEvaluationPairs, namespace }); if (step?.propertyValue !== newValue) { addUpdate({ propertyName: `${key}[${index}].propertyValue`, propertyValue: newValue }); } break; } case TriggerStepType.SHOW_ALERT: { const newValue = await refactorNameInValue({ oldValue: step.message, oldName, newName, dataTree, extractPairs: extractEvaluationPairs, namespace }); if (!isEqual(step.message, newValue)) { addUpdate({ propertyName: `${key}[${index}].message`, propertyValue: newValue }); } break; } case TriggerStepType.SET_PROFILE: { const newValue = await refactorNameInValue({ oldValue: step.profileId, oldName, newName, dataTree, extractPairs: extractEvaluationPairs, namespace }); if (!isEqual(step.profileId, newValue)) { addUpdate({ propertyName: `${key}[${index}].profileId`, propertyValue: newValue }); } break; } case TriggerStepType.TRIGGER_EVENT: { const payload = step.eventPayload ?? {}; // 1. Refactor the name in the values of the eventPayload const newValues: string[] = (await refactorNameInValue({ oldValue: Object.values(payload), oldName, newName, dataTree, extractPairs: extractEvaluationPairs, namespace })) as string[]; const newEventPayload = Object.keys(payload).reduce( (acc, key, i) => { acc[key] = newValues[i]; return acc; }, {} as Record ); if (!isEqual(payload, newEventPayload)) { addUpdate({ propertyName: `${key}[${index}].eventPayload`, propertyValue: newEventPayload }); } // 2. Update the event.name if it matches the oldName if (step.event?.name === oldName) { addUpdate({ propertyName: `${key}[${index}].event.name`, propertyValue: newName }); } break; } case TriggerStepType.RUN_SUPERBLOCKS_OPTIMIZED_APIS: { break; } default: { const exhaustiveCheck: never = step; throw new Error(`Unhandled action case: ${exhaustiveCheck}`); } } }; return renameInTriggerStep; }