afv-library/skills/using-ui-bundle-salesforce-data/references/mutation-query-generation.md
k-j-kim c611126c2f
Rename webapplication skills to ui-bundle @W-21338965@ (#136)
* Rename webapplication skills to ui-bundle

Rename all 7 webapplication skill directories and their content to use
the "ui-bundle" / "UIBundle" naming convention, aligning with the
New++ (TDX) naming strategy.

Directory renames:
- deploying-webapplication → deploying-ui-bundle
- generating-webapplication-{features,metadata,ui} → generating-ui-bundle-*
- implementing-webapplication-{agentforce-conversation-client,file-upload} → implementing-ui-bundle-*
- using-webapplication-salesforce-data → using-ui-bundle-salesforce-data

Content updates across all skills:
- Frontmatter name fields
- Prose: "web application" → "UI bundle"
- Metadata refs: WebApplication → UIBundle, webapplications/ → uiBundles/
- CLI: sf webapp → sf ui-bundle
- NPM packages per rename table
- Cross-skill references and generating-experience-react-site refs

* Rename generating-ui-bundle-ui skill to building-ui-bundle-frontend

The "ui-bundle-ui" name was confusing. "building-ui-bundle-frontend"
better conveys that this skill handles the React frontend layer
within a UI bundle.

---------

Co-authored-by: gbockus-sf <76090802+gbockus-sf@users.noreply.github.com>
2026-03-30 15:17:38 -05:00

141 lines
5.6 KiB
Markdown

# Mutation Query Generation
## Mutation Types
The GraphQL engine supports three mutation operations:
- **Create** — Insert a new record
- **Update** — Modify an existing record (Id-based)
- **Delete** — Remove an existing record (Id-based)
Mutations are GA in API v66+. They live under `mutation { uiapi { ... } }` and only support UI API-available objects.
## Generation Rules
1. **Input fields validation** — Validate that input fields satisfy the constraints for the operation type
2. **Output fields validation** — Validate that output fields satisfy the constraints for the operation type
3. **Type consistency** — Variables used as query arguments and their related fields must share the same GraphQL type. Verify types via the schema search script — do NOT assume types
4. **Input arguments**`input` is the default argument name unless otherwise specified
5. **Output field** — For `Create` and `Update`, the output field is always named `Record` (type: EntityName)
6. **Field name validation** — Every field name in the generated mutation **MUST** match a field confirmed via the schema search script. Do NOT guess or assume field names exist
7. **Raw input values** — Numeric values must be raw numbers without commas, currency symbols, or locale formatting (e.g., `80000` not `"80,000"` or `"$80,000"`). Compound fields (like addresses) require constituent fields (e.g., `BillingCity`, `BillingStreet`) — do not attempt to set the compound wrapper itself.
## Transactional Semantics: `allOrNone`
The `uiapi` mutation input accepts an `allOrNone` argument that controls rollback behavior:
- **`allOrNone: true` (default)** — If any operation fails, all operations in the request are rolled back. Use when operations must succeed or fail together.
- **`allOrNone: false`** — Independent operations can succeed individually. However, dependent operations (those using `@{alias}` references) still roll back together with their dependencies.
Always set `allOrNone` explicitly to make transactional intent clear.
## Mutation Schema Patterns
Replace `EntityName` with the actual entity name (e.g., Account, Case). `Delete` operations use generic `Record` types.
```graphql
input EntityNameCreateRepresentation {
# Subset of EntityName fields
}
input EntityNameCreateInput { EntityName: EntityNameCreateRepresentation! }
type EntityNameCreatePayload { Record: EntityName! }
input EntityNameUpdateRepresentation {
# Subset of EntityName fields
}
input EntityNameUpdateInput { Id: IdOrRef! EntityName: EntityNameUpdateRepresentation! }
type EntityNameUpdatePayload { Record: EntityName! }
input RecordDeleteInput { Id: IdOrRef! }
type RecordDeletePayload { Id: ID }
type UIAPIMutations {
EntityNameCreate(input: EntityNameCreateInput!): EntityNameCreatePayload
EntityNameDelete(input: RecordDeleteInput!): RecordDeletePayload
EntityNameUpdate(input: EntityNameUpdateInput!): EntityNameUpdatePayload
}
```
## Input Field Constraints
### Create
- **Must** include all required fields (unless `defaultedOnCreate` is `true` and not explicitly requested)
- **Must** only include `createable` fields
- Child relationships cannot be set — exclude them
- Reference fields (`REFERENCE` type) can only be assigned IDs through their `ApiName` name
- **No nested child creates** — Creating a record with child relationships in a single create operation is not supported. To create a parent and child together, use separate operations with `IdOrRef` chaining (see [Mutation Chaining](#mutation-chaining)).
### Update
- **Must** include the `Id` of the entity to update
- **Must** only include `updateable` fields
- Child relationships cannot be set — exclude them
- Reference fields (`REFERENCE` type) can only be assigned IDs through their `ApiName` name
### Delete
- **Must** include the `Id` of the entity to delete
## Output Field Constraints
### Create and Update
- **Must** exclude all child relationships (child relationships cannot be queried in mutations)
- **Must** exclude all `REFERENCE` fields unless accessed through their `ApiName` member (no navigation to referenced entity, no sub fields)
- Inaccessible fields are reported in the `errors` attribute of the returned payload
### Delete
- **Must** only include the `Id` field
## Mutation Chaining
Chain related mutations in a single request using references to `Id` values from previous mutations. This is the required approach for creating parent-child records together, since nested child creates are not supported.
1. **Ordering** — Mutation `B` can reference mutation `A` only if `A` comes first in the query
2. **Notation** — Use `SomeId: "@{A}"` in mutation `B` to set a field to the `Id` produced by mutation `A`
3. **IDs only**`@{A}` is always interpreted as the `Id` from mutation `A`
4. **Restrictions**`A` must be a `Create` or `Delete` mutation (chaining from `Update` will fail)
### Chaining Example
```graphql
mutation CreateAccountAndContact {
uiapi(input: { allOrNone: true }) {
AccountCreate(input: { Account: { Name: "Acme" } }) {
Record { Id }
}
ContactCreate(input: { Contact: { LastName: "Smith", AccountId: "@{AccountCreate}" } }) {
Record { Id }
}
}
}
```
## Mutation Query Template
```graphql
mutation mutateEntityName(
# arguments
) {
uiapi(input: { allOrNone: true }) {
EntityNameOperation(input: {
# For Create and Update only:
EntityName: {
# Input fields — use raw values, no formatting
}
# For Update and Delete only:
Id: ... # id here
}) {
# For Create and Update only:
Record {
# Output fields
}
# For Delete only:
Id
}
}
}
```