/** * Copyright (c) 2026, Salesforce, Inc., * All rights reserved. * For full license text, see the LICENSE.txt file */ import { buildOutput } from "./build-output.js"; import { getSchemaWithPriming } from "./get-schema-with-priming.js"; import { type DeleteSpec, type ToolOutput } from "./types.js"; import { assertGraphqlName } from "../lib/graphql-name.js"; import { selectDottedFieldPath } from "../lib/path-selection.js"; import { type PrimeDeps } from "../lib/prime-schema.js"; import { addVariable, createSession, deepSetArg } from "../lib/session.js"; import { mutationFieldPath } from "../lib/uiapi.js"; /** * Build a UIAPI delete mutation against a Salesforce org. Implements * `sf_gql_delete` intent for the graphiti MCP server (FR-5.7). * * Unlike create/update, delete is uniform across SObjects: * - The input type is the schema-wide `RecordDeleteInput!`, NOT an * ``-specific input. Every `Delete` mutation field * accepts the same `RecordDeleteInput!` carrying the record `Id`. * - The result is a `RecordDeletePayload` exposing only `Id` (a plain * `ID`, not a value wrapper), so the selection is always `Id` and * there is no `Record` sub-path — hence no `returnFields`. * * Implicit behaviors not visible in the signature: * - `inputVariable` defaults to `"input"`, declared as * `$: RecordDeleteInput!`. A leading `$` is stripped. * - Operation name defaults to `Delete` (e.g. `DeleteAccount`). * * Throws on invalid `object`, `inputVariable`, or `operationName` (must be * valid GraphQL Names), auth-missing, or introspection failure (via * `getSchemaWithPriming`); never throws on validation or codegen * failure (those surface as `warnings[]`). */ export async function buildDelete(spec: DeleteSpec, deps?: PrimeDeps): Promise { assertGraphqlName(spec.object, "buildDelete", "object"); const inputVar = (spec.inputVariable ?? "input").replace(/^\$/, ""); assertGraphqlName(inputVar, "buildDelete", "inputVariable"); const { schema, primingNote, instanceUrl } = await getSchemaWithPriming(spec.org, deps); const session = createSession(spec.org, "mutation", instanceUrl); session.operationName = spec.operationName ?? "Delete" + spec.object; assertGraphqlName(session.operationName, "buildDelete", "operationName"); const fieldPath = mutationFieldPath(spec.object, "Delete"); addVariable(session, inputVar, "RecordDeleteInput!"); deepSetArg(session, fieldPath, "input", [], "$" + inputVar); // Delete payloads expose only `Id` (a plain ID — never a value wrapper). // The selection is a literal single segment on the mutation field, so // `selectDottedFieldPath` cannot realistically throw here: there is no // user-supplied dotted path (unlike `buildMutation`'s `returnFields`) and // no top-level mutation-arg context that raises `MutationContextError`. selectDottedFieldPath(session, schema, fieldPath, "Id"); return buildOutput(session, schema, primingNote, []); }