import type { Ref } from "vue"; import type { ConnectionConfig } from "@/types/database"; import { executeWithProductionContextGuard } from "@/lib/database/productionExecutionGuard"; export type RunMongoSidebarMutationOptions = { connection?: ConnectionConfig; database: string; reviewText: string; source: string; loading: Ref; /** Runs after production confirmation and after loading is set (e.g. ensureConnected). */ beforeExecute?: () => Promise; execute: () => Promise; onSuccess: (result: T) => void | Promise; onError?: (error: unknown) => void; }; /** * Shared production-gated mutation shell for Mongo sidebar writes. * Production confirmation runs before loading so cancel never shows a busy state. * * Success is boxed as `{ result }` so void executes are not confused with cancel * (`executeWithProductionContextGuard` returns `undefined` only when cancelled). */ export async function runMongoSidebarMutation(options: RunMongoSidebarMutationOptions): Promise { if (options.loading.value) return; try { const executed = await executeWithProductionContextGuard({ connection: options.connection, database: options.database, reviewText: options.reviewText, source: options.source, execute: async () => { options.loading.value = true; if (options.beforeExecute) { await options.beforeExecute(); } const result = await options.execute(); return { result }; }, }); // Cancel only: guard returns undefined when the user declines production confirmation. if (executed === undefined) return; await options.onSuccess(executed.result); } catch (error: unknown) { options.onError?.(error); } finally { options.loading.value = false; } } // DataGrid and sidebar mutations intentionally share the same production-gated lifecycle. export const runMongoMutation = runMongoSidebarMutation;