@salesforce/webapp-template-app-react-sample-b2e-experimental 1.61.3 → 1.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.a4drules/{graphql.md → features/feature-graphql-graphql-data-access-rule.md} +127 -117
- package/dist/.a4drules/features/feature-react-agentforce-conversation-client-embedded-agent-rule.md +32 -0
- package/dist/.a4drules/features/feature-react-chart-analytics-charts-rule.md +27 -0
- package/dist/.a4drules/skills/feature-graphql-graphql-data-access/SKILL.md +155 -0
- package/dist/.a4drules/{graphql/tools/knowledge/lds-explore-graphql-schema.md → skills/feature-graphql-graphql-data-access/docs/explore-schema.md} +58 -29
- package/dist/.a4drules/{graphql/tools/knowledge/lds-generate-graphql-mutationquery.md → skills/feature-graphql-graphql-data-access/docs/generate-mutation-query.md} +52 -42
- package/dist/.a4drules/{graphql/tools/knowledge/lds-generate-graphql-readquery.md → skills/feature-graphql-graphql-data-access/docs/generate-read-query.md} +32 -22
- package/dist/.a4drules/{graphql/tools/schemas/shared.graphqls → skills/feature-graphql-graphql-data-access/docs/shared-schema.graphqls} +1 -1
- package/dist/.a4drules/skills/feature-micro-frontend-micro-frontend/SKILL.md +137 -0
- package/dist/.a4drules/skills/feature-react-agentforce-conversation-client-embedded-agent/SKILL.md +108 -0
- package/dist/.a4drules/skills/feature-react-agentforce-conversation-client-embedded-agent/docs/embed-examples.md +182 -0
- package/dist/.a4drules/skills/feature-react-chart-analytics-charts/SKILL.md +41 -0
- package/dist/.a4drules/skills/feature-react-chart-analytics-charts/docs/schema-mapping.md +4 -0
- package/dist/.a4drules/webapp-code-quality.md +136 -0
- package/dist/.a4drules/{images.md → webapp-images.md} +6 -4
- package/dist/.a4drules/webapp-no-node-e.md +3 -2
- package/dist/.a4drules/webapp-react.md +149 -0
- package/dist/.a4drules/{typescript.md → webapp-typescript.md} +9 -17
- package/dist/.a4drules/webapp.md +62 -45
- package/dist/CHANGELOG.md +16 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/vite.config.ts +2 -2
- package/dist/package.json +1 -1
- package/package.json +2 -2
- package/dist/.a4drules/README.md +0 -35
- package/dist/.a4drules/a4d-webapp-generate.md +0 -27
- package/dist/.a4drules/build-validation.md +0 -78
- package/dist/.a4drules/code-quality.md +0 -136
- package/dist/.a4drules/graphql/tools/knowledge/lds-guide-graphql.md +0 -205
- package/dist/.a4drules/react.md +0 -388
- package/dist/.a4drules/react_image_processing.md +0 -45
- package/dist/.a4drules/ui-layout.md +0 -23
- package/dist/.a4drules/webapp-nav-and-placeholders.md +0 -33
- package/dist/.a4drules/webapp-ui-first.md +0 -32
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/build/vite.config.d.ts +0 -2
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/build/vite.config.js +0 -93
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: graphql-data-access
|
|
3
|
+
description: Add or modify Salesforce GraphQL data access code. Use when the user asks to fetch, query, or mutate Salesforce data, or add a GraphQL operation for an object like Account, Contact, or Opportunity.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GraphQL Data Access
|
|
7
|
+
|
|
8
|
+
Add or modify Salesforce GraphQL data access code using `getDataSDK()` + `data.graphql?.()` and codegen tooling.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
- User asks to "fetch data from Salesforce"
|
|
13
|
+
- User asks to "query" or "mutate" Salesforce records
|
|
14
|
+
- User wants to add a new GraphQL operation (query or mutation)
|
|
15
|
+
- User asks to add data access for a Salesforce object (Account, Contact, Opportunity, etc.)
|
|
16
|
+
|
|
17
|
+
## Prerequisites
|
|
18
|
+
|
|
19
|
+
The base React app (`base-react-app`) ships with all GraphQL dependencies and tooling pre-configured:
|
|
20
|
+
|
|
21
|
+
- `@salesforce/sdk-data` — runtime SDK for `getDataSDK` and `gql`
|
|
22
|
+
- `@graphql-codegen/cli` + plugins — type generation from `.graphql` files and inline `gql` queries
|
|
23
|
+
- `@graphql-eslint/eslint-plugin` — linting for `.graphql` files and `gql` template literals
|
|
24
|
+
- `graphql` — shared by codegen, ESLint, and schema introspection
|
|
25
|
+
|
|
26
|
+
Before using this skill, ensure:
|
|
27
|
+
|
|
28
|
+
1. The `@salesforce/sdk-data` package is available (provides `getDataSDK`, `gql`, `NodeOfConnection`)
|
|
29
|
+
2. A `schema.graphql` file exists at the project root. If missing, generate it:
|
|
30
|
+
```bash
|
|
31
|
+
npm run graphql:schema
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## npm Scripts
|
|
35
|
+
|
|
36
|
+
The base app provides two npm scripts for GraphQL tooling:
|
|
37
|
+
|
|
38
|
+
- **`npm run graphql:schema`** — Downloads the full GraphQL schema from a connected Salesforce org via introspection. Outputs `schema.graphql` to the project root.
|
|
39
|
+
- **`npm run graphql:codegen`** — Generates TypeScript types from `.graphql` files and inline `gql` queries. Outputs to `src/api/graphql-operations-types.ts`.
|
|
40
|
+
|
|
41
|
+
## Workflow
|
|
42
|
+
|
|
43
|
+
### Step 1: Explore the Schema
|
|
44
|
+
|
|
45
|
+
Before writing any query, verify the target object and its fields exist in the schema.
|
|
46
|
+
|
|
47
|
+
See `docs/explore-schema.md` for detailed guidance on exploring the Salesforce GraphQL schema.
|
|
48
|
+
|
|
49
|
+
Key actions:
|
|
50
|
+
|
|
51
|
+
- Search `schema.graphql` for `type <ObjectName> implements Record` to find available fields
|
|
52
|
+
- Search for `input <ObjectName>_Filter` for filter options
|
|
53
|
+
- Search for `input <ObjectName>_OrderBy` for sorting options
|
|
54
|
+
- For mutations: search for `input <ObjectName>CreateInput` or `<ObjectName>UpdateInput`
|
|
55
|
+
|
|
56
|
+
### Step 2: Choose the Query Pattern
|
|
57
|
+
|
|
58
|
+
**Pattern 1 — External `.graphql` file** (recommended for complex queries):
|
|
59
|
+
|
|
60
|
+
- Queries with variables, fragments, or shared across files
|
|
61
|
+
- Enables full codegen type generation
|
|
62
|
+
- See example: `api/utils/accounts.ts` + `api/utils/query/highRevenueAccountsQuery.graphql`
|
|
63
|
+
|
|
64
|
+
**Pattern 2 — Inline `gql` tag** (recommended for simple queries):
|
|
65
|
+
|
|
66
|
+
- Simple queries without variables
|
|
67
|
+
- Colocated with usage code
|
|
68
|
+
- See example: `api/utils/user.ts`
|
|
69
|
+
|
|
70
|
+
### Step 3: Write the Query
|
|
71
|
+
|
|
72
|
+
For **Pattern 1**:
|
|
73
|
+
|
|
74
|
+
1. Create a `.graphql` file under `src/api/utils/query/`
|
|
75
|
+
2. Follow UIAPI structure: `query { uiapi { query { ObjectName(...) { edges { node { ... } } } } } }`
|
|
76
|
+
3. For mutations, see `docs/generate-mutation-query.md`
|
|
77
|
+
4. For read queries, see `docs/generate-read-query.md`
|
|
78
|
+
|
|
79
|
+
For **Pattern 2**:
|
|
80
|
+
|
|
81
|
+
1. Define query inline using the `gql` template tag
|
|
82
|
+
2. Ensure the query name matches what codegen expects
|
|
83
|
+
|
|
84
|
+
### Step 4: Generate Types
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npm run graphql:codegen
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
This updates `src/api/graphql-operations-types.ts` with:
|
|
91
|
+
|
|
92
|
+
- `<OperationName>Query` or `<OperationName>Mutation` — response type
|
|
93
|
+
- `<OperationName>QueryVariables` or `<OperationName>MutationVariables` — input variables type
|
|
94
|
+
|
|
95
|
+
### Step 5: Implement the Data Access Function
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// Pattern 1
|
|
99
|
+
import { getDataSDK, type NodeOfConnection } from "@salesforce/sdk-data";
|
|
100
|
+
import MY_QUERY from "./query/myQuery.graphql?raw";
|
|
101
|
+
import type { GetMyDataQuery, GetMyDataQueryVariables } from "../graphql-operations-types";
|
|
102
|
+
|
|
103
|
+
type MyNode = NodeOfConnection<GetMyDataQuery["uiapi"]["query"]["MyObject"]>;
|
|
104
|
+
|
|
105
|
+
export async function getMyData(variables: GetMyDataQueryVariables): Promise<MyNode[]> {
|
|
106
|
+
const data = await getDataSDK();
|
|
107
|
+
const response = await data.graphql?.<GetMyDataQuery, GetMyDataQueryVariables>(
|
|
108
|
+
MY_QUERY,
|
|
109
|
+
variables,
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
if (response?.errors?.length) {
|
|
113
|
+
const errorMessages = response.errors.map((e) => e.message).join("; ");
|
|
114
|
+
throw new Error(`GraphQL Error: ${errorMessages}`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return response?.data?.uiapi?.query?.MyObject?.edges?.map((edge) => edge?.node) || [];
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// Pattern 2
|
|
123
|
+
import { getDataSDK, gql } from "@salesforce/sdk-data";
|
|
124
|
+
import type { MySimpleQuery } from "../graphql-operations-types";
|
|
125
|
+
|
|
126
|
+
const MY_QUERY = gql`
|
|
127
|
+
query MySimple {
|
|
128
|
+
uiapi { ... }
|
|
129
|
+
}
|
|
130
|
+
`;
|
|
131
|
+
|
|
132
|
+
export async function getSimpleData(): Promise<SomeType> {
|
|
133
|
+
const data = await getDataSDK();
|
|
134
|
+
const response = await data.graphql?.<MySimpleQuery>(MY_QUERY);
|
|
135
|
+
// check response.errors, then extract response.data
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Step 6: Verify
|
|
140
|
+
|
|
141
|
+
- [ ] Query field names match the schema exactly (case-sensitive)
|
|
142
|
+
- [ ] Response type generic is provided to `data.graphql?.<T>()`
|
|
143
|
+
- [ ] Optional chaining is used for nested response data
|
|
144
|
+
- [ ] Pattern 1: `.graphql` file imported with `?raw` suffix
|
|
145
|
+
- [ ] Pattern 2: Query uses `gql` tag (not plain string)
|
|
146
|
+
- [ ] Generated types imported from `graphql-operations-types.ts`
|
|
147
|
+
|
|
148
|
+
## Reference
|
|
149
|
+
|
|
150
|
+
- Schema exploration: `docs/explore-schema.md`
|
|
151
|
+
- Read query generation: `docs/generate-read-query.md`
|
|
152
|
+
- Mutation query generation: `docs/generate-mutation-query.md`
|
|
153
|
+
- Shared GraphQL schema types: `docs/shared-schema.graphqls`
|
|
154
|
+
- Schema download: `npm run graphql:schema` (in the base app)
|
|
155
|
+
- Type generation: `npm run graphql:codegen` (in the base app)
|
|
@@ -9,8 +9,9 @@ This document provides guidance for AI agents working with the Salesforce GraphQ
|
|
|
9
9
|
> ⚠️ **Important**: The schema file is very large (~265,000+ lines). Do NOT read it entirely. Instead, use targeted searches to find specific types, fields, or operations.
|
|
10
10
|
|
|
11
11
|
If the file is not present, generate it by running:
|
|
12
|
+
|
|
12
13
|
```bash
|
|
13
|
-
npm run graphql:
|
|
14
|
+
npm run graphql:schema
|
|
14
15
|
```
|
|
15
16
|
|
|
16
17
|
## Required Pre-Flight Check
|
|
@@ -18,8 +19,8 @@ npm run graphql:get-schema
|
|
|
18
19
|
**BEFORE generating any GraphQL query, you MUST:**
|
|
19
20
|
|
|
20
21
|
1. **Check if schema exists**: Look for `schema.graphql` in the project root
|
|
21
|
-
2. **If schema is missing**:
|
|
22
|
-
- Run `npm run graphql:
|
|
22
|
+
2. **If schema is missing**:
|
|
23
|
+
- Run `npm run graphql:schema` to download it
|
|
23
24
|
- Wait for the command to complete successfully
|
|
24
25
|
- Then proceed with schema exploration
|
|
25
26
|
3. **If schema exists**: Proceed with targeted searches as described below
|
|
@@ -31,6 +32,7 @@ npm run graphql:get-schema
|
|
|
31
32
|
The schema follows the Salesforce GraphQL Wire Adapter pattern with these main entry points:
|
|
32
33
|
|
|
33
34
|
### Query Entry Point
|
|
35
|
+
|
|
34
36
|
```graphql
|
|
35
37
|
type Query {
|
|
36
38
|
uiapi: UIAPI!
|
|
@@ -38,16 +40,18 @@ type Query {
|
|
|
38
40
|
```
|
|
39
41
|
|
|
40
42
|
### UIAPI Structure
|
|
43
|
+
|
|
41
44
|
```graphql
|
|
42
45
|
type UIAPI {
|
|
43
|
-
query: RecordQuery!
|
|
44
|
-
aggregate: RecordQueryAggregate!
|
|
45
|
-
objectInfos: [ObjectInfo]
|
|
46
|
+
query: RecordQuery! # For querying records
|
|
47
|
+
aggregate: RecordQueryAggregate! # For aggregate queries
|
|
48
|
+
objectInfos: [ObjectInfo] # For metadata
|
|
46
49
|
relatedListByName: RelatedListInfo
|
|
47
50
|
}
|
|
48
51
|
```
|
|
49
52
|
|
|
50
53
|
### Mutation Entry Point
|
|
54
|
+
|
|
51
55
|
```graphql
|
|
52
56
|
type Mutation {
|
|
53
57
|
uiapi(input: UIAPIMutationsInput): UIAPIMutations!
|
|
@@ -59,35 +63,45 @@ type Mutation {
|
|
|
59
63
|
When you need to build a GraphQL query, use these search patterns:
|
|
60
64
|
|
|
61
65
|
### 1. Find Available Fields for a Record Type
|
|
66
|
+
|
|
62
67
|
Search for `type <ObjectName> implements Record` to find all queryable fields:
|
|
68
|
+
|
|
63
69
|
```bash
|
|
64
70
|
# Example: Find Account fields
|
|
65
71
|
grep "^type Account implements Record" schema.graphql -A 50
|
|
66
72
|
```
|
|
67
73
|
|
|
68
74
|
### 2. Find Filter Options for a Record Type
|
|
75
|
+
|
|
69
76
|
Search for `input <ObjectName>_Filter` to find filterable fields and operators:
|
|
77
|
+
|
|
70
78
|
```bash
|
|
71
79
|
# Example: Find Account filter options
|
|
72
80
|
grep "^input Account_Filter" schema.graphql -A 30
|
|
73
81
|
```
|
|
74
82
|
|
|
75
83
|
### 3. Find OrderBy Options
|
|
84
|
+
|
|
76
85
|
Search for `input <ObjectName>_OrderBy` for sorting options:
|
|
86
|
+
|
|
77
87
|
```bash
|
|
78
88
|
# Example: Find Account ordering options
|
|
79
89
|
grep "^input Account_OrderBy" schema.graphql -A 20
|
|
80
90
|
```
|
|
81
91
|
|
|
82
92
|
### 4. Find Mutation Operations
|
|
93
|
+
|
|
83
94
|
Search for operations in `UIAPIMutations`:
|
|
95
|
+
|
|
84
96
|
```bash
|
|
85
97
|
# Example: Find Account mutations
|
|
86
98
|
grep "Account.*Create\|Account.*Update\|Account.*Delete" schema.graphql
|
|
87
99
|
```
|
|
88
100
|
|
|
89
101
|
### 5. Find Input Types for Mutations
|
|
102
|
+
|
|
90
103
|
Search for `input <ObjectName>CreateInput` or `input <ObjectName>UpdateInput`:
|
|
104
|
+
|
|
91
105
|
```bash
|
|
92
106
|
# Example: Find Account create input
|
|
93
107
|
grep "^input AccountCreateInput" schema.graphql -A 30
|
|
@@ -96,32 +110,36 @@ grep "^input AccountCreateInput" schema.graphql -A 30
|
|
|
96
110
|
## Common Operator Types
|
|
97
111
|
|
|
98
112
|
### StringOperators (for text fields)
|
|
113
|
+
|
|
99
114
|
```graphql
|
|
100
115
|
input StringOperators {
|
|
101
|
-
eq: String
|
|
102
|
-
ne: String
|
|
103
|
-
like: String
|
|
104
|
-
lt: String
|
|
105
|
-
gt: String
|
|
106
|
-
lte: String
|
|
107
|
-
gte: String
|
|
108
|
-
in: [String]
|
|
109
|
-
nin: [String]
|
|
116
|
+
eq: String # equals
|
|
117
|
+
ne: String # not equals
|
|
118
|
+
like: String # pattern matching (use % as wildcard)
|
|
119
|
+
lt: String # less than
|
|
120
|
+
gt: String # greater than
|
|
121
|
+
lte: String # less than or equal
|
|
122
|
+
gte: String # greater than or equal
|
|
123
|
+
in: [String] # in list
|
|
124
|
+
nin: [String] # not in list
|
|
110
125
|
}
|
|
111
126
|
```
|
|
112
127
|
|
|
113
128
|
### OrderByClause
|
|
129
|
+
|
|
114
130
|
```graphql
|
|
115
131
|
input OrderByClause {
|
|
116
|
-
order: ResultOrder
|
|
117
|
-
nulls: NullOrder
|
|
132
|
+
order: ResultOrder # ASC or DESC
|
|
133
|
+
nulls: NullOrder # FIRST or LAST
|
|
118
134
|
}
|
|
119
135
|
```
|
|
120
136
|
|
|
121
137
|
## Query Pattern Examples
|
|
122
138
|
|
|
123
139
|
### Basic Query Structure
|
|
140
|
+
|
|
124
141
|
All record queries follow this pattern:
|
|
142
|
+
|
|
125
143
|
```graphql
|
|
126
144
|
query {
|
|
127
145
|
uiapi {
|
|
@@ -146,6 +164,7 @@ query {
|
|
|
146
164
|
```
|
|
147
165
|
|
|
148
166
|
### Example: Query Accounts with Filter
|
|
167
|
+
|
|
149
168
|
```graphql
|
|
150
169
|
query GetHighRevenueAccounts($minRevenue: Currency) {
|
|
151
170
|
uiapi {
|
|
@@ -158,9 +177,15 @@ query GetHighRevenueAccounts($minRevenue: Currency) {
|
|
|
158
177
|
edges {
|
|
159
178
|
node {
|
|
160
179
|
Id
|
|
161
|
-
Name {
|
|
162
|
-
|
|
163
|
-
|
|
180
|
+
Name {
|
|
181
|
+
value
|
|
182
|
+
}
|
|
183
|
+
AnnualRevenue {
|
|
184
|
+
value
|
|
185
|
+
}
|
|
186
|
+
Industry {
|
|
187
|
+
value
|
|
188
|
+
}
|
|
164
189
|
}
|
|
165
190
|
}
|
|
166
191
|
}
|
|
@@ -170,13 +195,16 @@ query GetHighRevenueAccounts($minRevenue: Currency) {
|
|
|
170
195
|
```
|
|
171
196
|
|
|
172
197
|
### Mutation Pattern
|
|
198
|
+
|
|
173
199
|
```graphql
|
|
174
200
|
mutation CreateAccount($input: AccountCreateInput!) {
|
|
175
201
|
uiapi(input: { AccountCreate: { input: $input } }) {
|
|
176
202
|
AccountCreate {
|
|
177
203
|
Record {
|
|
178
204
|
Id
|
|
179
|
-
Name {
|
|
205
|
+
Name {
|
|
206
|
+
value
|
|
207
|
+
}
|
|
180
208
|
}
|
|
181
209
|
}
|
|
182
210
|
}
|
|
@@ -187,11 +215,11 @@ mutation CreateAccount($input: AccountCreateInput!) {
|
|
|
187
215
|
|
|
188
216
|
Salesforce GraphQL returns field values wrapped in typed objects:
|
|
189
217
|
|
|
190
|
-
| Wrapper Type
|
|
191
|
-
|
|
192
|
-
| `StringValue`
|
|
193
|
-
| `IntValue`
|
|
194
|
-
| `BooleanValue`
|
|
218
|
+
| Wrapper Type | Access Pattern |
|
|
219
|
+
| --------------- | ---------------------------------- |
|
|
220
|
+
| `StringValue` | `FieldName { value }` |
|
|
221
|
+
| `IntValue` | `FieldName { value }` |
|
|
222
|
+
| `BooleanValue` | `FieldName { value }` |
|
|
195
223
|
| `DateTimeValue` | `FieldName { value displayValue }` |
|
|
196
224
|
| `PicklistValue` | `FieldName { value displayValue }` |
|
|
197
225
|
| `CurrencyValue` | `FieldName { value displayValue }` |
|
|
@@ -199,8 +227,9 @@ Salesforce GraphQL returns field values wrapped in typed objects:
|
|
|
199
227
|
## Agent Workflow for Building Queries
|
|
200
228
|
|
|
201
229
|
**Pre-requisites (MANDATORY):**
|
|
230
|
+
|
|
202
231
|
- [ ] Verified `schema.graphql` exists in project root
|
|
203
|
-
- [ ] If missing, ran `npm run graphql:
|
|
232
|
+
- [ ] If missing, ran `npm run graphql:schema` and waited for completion
|
|
204
233
|
- [ ] Confirmed connection to correct Salesforce org (if downloading fresh schema)
|
|
205
234
|
|
|
206
235
|
**Workflow Steps:**
|
|
@@ -223,5 +252,5 @@ Salesforce GraphQL returns field values wrapped in typed objects:
|
|
|
223
252
|
|
|
224
253
|
## Related Documentation
|
|
225
254
|
|
|
226
|
-
- For generating mutations and queries, see `
|
|
227
|
-
- For
|
|
255
|
+
- For generating mutations and queries, see `generate-mutation-query.md`
|
|
256
|
+
- For generating read queries, see `generate-read-query.md`
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
# GraphQL Mutation Query Generation
|
|
2
2
|
|
|
3
3
|
**Triggering conditions**
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
1. Only if the schema exploration phase completed successfully
|
|
5
6
|
2. Only if the query to generate is a mutation query
|
|
6
7
|
|
|
7
8
|
## Your Role
|
|
8
9
|
|
|
9
10
|
You are a GraphQL expert and your role is to help generate Salesforce compatible GraphQL mutation queries once the exploration phase has completed.
|
|
10
11
|
|
|
11
|
-
You will leverage the context provided by the requesting user as well as the validation phase provided by the
|
|
12
|
+
You will leverage the context provided by the requesting user as well as the validation phase provided by the schema exploration. This tool will also provide you with a method to dynamically query the target org instance that you will use to test the generated query.
|
|
12
13
|
|
|
13
|
-
If the
|
|
14
|
+
If the schema exploration has not been executed yet, you **MUST** run it first, and then get back to mutation query generation.
|
|
14
15
|
|
|
15
16
|
## Mutation Queries General Information
|
|
16
17
|
|
|
17
18
|
**IMPORTANT**:
|
|
19
|
+
|
|
18
20
|
1. **Mutation Types**: The GraphQL engine supports `Create`, `Update` and `Delete` operations
|
|
19
21
|
2. **Id Based Mutations**: `Update` and `Delete` operations operate on Id-based entity identification
|
|
20
22
|
3. **Mutation Schema**: Defined in the [mutation query schema](#mutation-query-schema) section
|
|
@@ -22,6 +24,7 @@ If the `LDS_Guide_GraphQL` rule has not been executed yet, you **MUST** run it f
|
|
|
22
24
|
## Mutation Query Generation Workflow
|
|
23
25
|
|
|
24
26
|
Strictly follow the rules below when generating the GraphQL mutation query:
|
|
27
|
+
|
|
25
28
|
1. **Input Fields Validation** - Validate that the set of fields validate [input field constraints](#mutation-queries-input-field-constraints)
|
|
26
29
|
2. **Output Fields Validation** - Validate that the set of fields used in the select part of the query validate the [output fields constraints](#mutation-queries-output-field-constraints)
|
|
27
30
|
3. **Type Consistency** - Make sure variables used as query arguments and their related fields share the same GraphQL type
|
|
@@ -31,7 +34,7 @@ Strictly follow the rules below when generating the GraphQL mutation query:
|
|
|
31
34
|
7. **Query Generation** - Use the [mutation query](#mutation-query-templates) template and adjust it based on the selected operation
|
|
32
35
|
8. **Output Format** - Use the [standalone](#mutation-standalone-default-output-format---clean-code-only)
|
|
33
36
|
9. **Test the Query** - Use the [Generated Mutation Query Testing](#generated-mutation-query-testing) workflow to test the generated query
|
|
34
|
-
|
|
37
|
+
1. **Report First** - Always report first, using the proper output format, before testing
|
|
35
38
|
|
|
36
39
|
## Mutation Query Schema
|
|
37
40
|
|
|
@@ -64,32 +67,33 @@ type UIAPIMutations {
|
|
|
64
67
|
## Mutation Queries Input Field Constraints
|
|
65
68
|
|
|
66
69
|
1. **`Create` Mutation Queries**:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
1. **MUST** include all required fields
|
|
71
|
+
2. **MUST** only include createable fields
|
|
72
|
+
3. Child relationships can't be set and **MUST** be excluded
|
|
73
|
+
4. Fields with type `REFERENCE` can only be assigned IDs through their `ApiName` name
|
|
71
74
|
2. **`Update` Mutation Queries**:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
1. **MUST** include the id of the entity to update
|
|
76
|
+
2. **MUST** only include updateable fields
|
|
77
|
+
3. Child relationships can't be set and **MUST** be excluded
|
|
78
|
+
4. Fields with type `REFERENCE` can only be assigned IDs through their `ApiName` name
|
|
76
79
|
3. **`Delete` Mutation Queries**:
|
|
77
|
-
|
|
80
|
+
1. **MUST** include the id of the entity to delete
|
|
78
81
|
|
|
79
82
|
## Mutation Queries Output Field Constraints
|
|
80
83
|
|
|
81
84
|
1. **`Create` and `Update` Mutation Queries**:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
1. **MUST** exclude all child relationships
|
|
86
|
+
2. **MUST** exclude all `REFERENCE` fields, unless accessed through their `ApiName` member (no navigation to referenced entity)
|
|
87
|
+
3. Inaccessible fields will be reported as part of the `errors` attribute in the returned payload
|
|
88
|
+
4. Child relationships **CAN'T** be queried as part of a mutation
|
|
89
|
+
5. Fields with type `REFERENCE` can only be queried through their `ApiName` (no referenced entities navigation, no sub fields)
|
|
87
90
|
2. **`Delete` Mutation Queries**:
|
|
88
|
-
|
|
91
|
+
1. **MUST** only include the `Id` field
|
|
89
92
|
|
|
90
93
|
## Mutation Query Report Template
|
|
91
94
|
|
|
92
95
|
Input arguments:
|
|
96
|
+
|
|
93
97
|
- Required fields: FieldName1 (Type1), FieldName2 (Type2)...
|
|
94
98
|
- Other fields: FieldName3 (Type3)...
|
|
95
99
|
Output fields: FieldNameA (TypeA), FieldNameB (TypeB)...
|
|
@@ -147,66 +151,72 @@ const QUERY_VARIABLES = {
|
|
|
147
151
|
```
|
|
148
152
|
|
|
149
153
|
**❌ DO NOT INCLUDE:**
|
|
154
|
+
|
|
150
155
|
- Explanatory comments about the query
|
|
151
156
|
- Field descriptions
|
|
152
157
|
- Additional text about what the query does
|
|
153
158
|
- Workflow step descriptions
|
|
154
159
|
|
|
155
160
|
**✅ ONLY INCLUDE:**
|
|
161
|
+
|
|
156
162
|
- Raw query string
|
|
157
163
|
- Variables object
|
|
158
164
|
- Nothing else
|
|
159
165
|
|
|
160
166
|
## Generated Mutation Query Testing
|
|
161
167
|
|
|
162
|
-
**Triggering conditions** - **ALL CONDITIONS MUST VALIDATE
|
|
168
|
+
**Triggering conditions** - **ALL CONDITIONS MUST VALIDATE\***
|
|
169
|
+
|
|
163
170
|
1. Only if the [Mutation Query Generation Workflow](#mutation-query-generation-workflow) step global status is `SUCCESS` and you have a generated query
|
|
164
171
|
2. Only if the query to generate is a mutation query
|
|
165
|
-
3. Only if non manual method was used during
|
|
172
|
+
3. Only if non manual method was used during schema exploration to retrieve introspection data
|
|
166
173
|
|
|
167
174
|
**Workflow**
|
|
175
|
+
|
|
168
176
|
1. **Report Step** - Explain that you are able to test the query using the same method used during introspection
|
|
169
|
-
|
|
177
|
+
1. You **MUST** report the method you will use, based on the one you used during schema exploration
|
|
170
178
|
2. **Interactive Step** - Ask the user whether they want you to test the query using the proposed method
|
|
171
|
-
|
|
179
|
+
1. **WAIT** for the user's answer.
|
|
172
180
|
3. **Input Arguments** - You **MUST** ask the user for the input arguments to use
|
|
173
|
-
|
|
181
|
+
1. **WAIT** for the user's answer.
|
|
174
182
|
4. **Test Query** - If the user are OK with you testing the query:
|
|
175
|
-
|
|
176
|
-
|
|
183
|
+
1. Use the selected method to test the query
|
|
184
|
+
2. **IMPORTANT** - If you use the Salesforce CLI `sf api request graphql` command, you will need to inject the variable values directly into the query, as this command doesn't accept variables as a parameter
|
|
177
185
|
5. **Result Analysis** - Retrieve the `data` and `errors` attributes from the returned payload, and report the result of the test as one of the following options:
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
186
|
+
1. `PARTIAL` if `data` is not an empty object, but `errors` is not an empty list - Explanation: some of the queried fields are not accessible on mutations
|
|
187
|
+
2. `FAILED` if `data` is an empty object - Explanation: the query is not valid
|
|
188
|
+
3. `SUCCESS` if `errors` is an empty list
|
|
181
189
|
6. **Remediation Step** - If status is not `SUCCESS`, use the [`FAILED`](#failed-status-handling-workflow) or [`PARTIAL`](#partial-status-handling-workflow) status handling workflows
|
|
182
190
|
|
|
183
191
|
### `FAILED` Status Handling Workflow
|
|
184
192
|
|
|
185
193
|
The query is invalid:
|
|
194
|
+
|
|
186
195
|
1. **Error Analysis** - Parse and categorize the specific error messages
|
|
187
196
|
2. **Root Cause Identification** - Use error message to identify the root cause:
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
197
|
+
- **Execution** - Error contains `invalid cross reference id` or `entity is deleted`
|
|
198
|
+
- **Syntax** - Error contains `invalid syntax`
|
|
199
|
+
- **Validation** - Error contains `validation error`
|
|
200
|
+
- **Type** - Error contains `VariableTypeMismatch` or `UnknownType`
|
|
201
|
+
- **Navigation** - Error contains `is not currently available in mutation results`
|
|
202
|
+
- **API Version** - Query deals with updates, you're testing with Connect API and error contains `Cannot invoke JsonElement.isJsonObject()`
|
|
194
203
|
3. **Targeted Resolution** - Depending on the root cause categorization
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
204
|
+
- **Execution** - You're trying to update or delete an unknown/no longer available entity: either create an entity first, if you have generated the related query, or ask for a valid entity id to use
|
|
205
|
+
- **Syntax** - Update the query using the error message information to fix the syntax errors
|
|
206
|
+
- **Validation** - This field's name is most probably invalid, ask user for clarification and **WAIT** for the user's answer
|
|
207
|
+
- **Type** - Use the error details and GraphQL schema to correct argument's type, and adjust variables accordingly
|
|
208
|
+
- **Navigation** - Use the [`PARTIAL` status handling workflow](#partial-status-handling-workflow) below
|
|
209
|
+
- **API Version** - `Record` selection is only available with API version 64 and higher, **report** the issue, and try again with API version 64
|
|
201
210
|
4. **Test Again** - Resume the [query testing workflow](#generated-mutation-query-testing) with the updated query (increment and track attempt counter)
|
|
202
211
|
5. **Escalation Path** - If targeted resolution fails after 2 attempts, ask for additional details and restart the entire GraphQL workflow, going again through the introspection phase
|
|
203
212
|
|
|
204
213
|
### `PARTIAL` Status Handling Workflow
|
|
205
214
|
|
|
206
215
|
The query can be improved:
|
|
216
|
+
|
|
207
217
|
1. Report the fields mentioned in the `errors` list
|
|
208
218
|
2. Explain that these fields can't be queried as part of a mutation query
|
|
209
219
|
3. Explain that the query might be considered as failing, as it will report errors
|
|
210
220
|
4. Offer to remove the offending fields
|
|
211
221
|
5. **WAIT** for the user's answer
|
|
212
|
-
6. If they are OK with removing the fields restart the [generation workflow](#mutation-query-generation-workflow) with the new field list
|
|
222
|
+
6. If they are OK with removing the fields restart the [generation workflow](#mutation-query-generation-workflow) with the new field list
|