mirror of
https://github.com/forcedotcom/afv-library.git
synced 2026-07-31 04:01:24 +08:00
* 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>
141 lines
5.6 KiB
Markdown
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
|
|
}
|
|
}
|
|
}
|
|
```
|