@salesforce/afv-skills 1.6.5 → 1.6.7
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/package.json +3 -3
- package/skills/building-ui-bundle-app/SKILL.md +1 -1
- package/skills/building-ui-bundle-frontend/SKILL.md +3 -1
- package/skills/deploying-ui-bundle/SKILL.md +1 -1
- package/skills/generating-experience-lwr-site/SKILL.md +11 -1
- package/skills/generating-experience-lwr-site/docs/update-site-urls.md +100 -0
- package/skills/generating-ui-bundle-features/SKILL.md +1 -1
- package/skills/generating-ui-bundle-metadata/SKILL.md +9 -2
- package/skills/generating-ui-bundle-site/SKILL.md +14 -2
- package/skills/generating-ui-bundle-site/docs/configure-metadata-digital-experience.md +4 -2
- package/skills/generating-ui-bundle-site/docs/update-site-urls.md +100 -0
- package/skills/implementing-ui-bundle-agentforce-conversation-client/SKILL.md +216 -37
- package/skills/implementing-ui-bundle-agentforce-conversation-client/references/style-tokens.md +168 -21
- package/skills/implementing-ui-bundle-file-upload/SKILL.md +1 -1
- package/skills/searching-media/SKILL.md +1 -1
- package/skills/using-ui-bundle-salesforce-data/SKILL.md +338 -92
- package/skills/using-ui-bundle-salesforce-data/references/mutation-query-generation.md +0 -140
- package/skills/using-ui-bundle-salesforce-data/references/query-testing.md +0 -78
- package/skills/using-ui-bundle-salesforce-data/references/read-query-generation.md +0 -307
- package/skills/using-ui-bundle-salesforce-data/references/schema-introspection.md +0 -53
- package/skills/using-ui-bundle-salesforce-data/references/ui-bundle-integration.md +0 -221
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
# UI Bundle Integration
|
|
2
|
-
|
|
3
|
-
## When to Use
|
|
4
|
-
|
|
5
|
-
This guide applies when integrating GraphQL queries into a React UI bundle using `createDataSDK` + codegen from `@salesforce/sdk-data`.
|
|
6
|
-
|
|
7
|
-
## Core Types & Function Signatures
|
|
8
|
-
|
|
9
|
-
### createDataSDK and graphql
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
import { createDataSDK } from "@salesforce/sdk-data";
|
|
13
|
-
|
|
14
|
-
const sdk = await createDataSDK();
|
|
15
|
-
const response = await sdk.graphql?.<ResponseType, VariablesType>(query, variables);
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
`createDataSDK()` returns a `DataSDK` instance. The `graphql` method uses optional chaining (`?.`) because not all surfaces support GraphQL.
|
|
19
|
-
|
|
20
|
-
### gql Template Tag
|
|
21
|
-
|
|
22
|
-
```typescript
|
|
23
|
-
import { gql } from "@salesforce/sdk-data";
|
|
24
|
-
|
|
25
|
-
const MY_QUERY = gql`
|
|
26
|
-
query MyQuery {
|
|
27
|
-
uiapi { ... }
|
|
28
|
-
}
|
|
29
|
-
`;
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
The `gql` tag enables ESLint validation against the schema. Plain template strings bypass validation.
|
|
33
|
-
|
|
34
|
-
### NodeOfConnection
|
|
35
|
-
|
|
36
|
-
```typescript
|
|
37
|
-
import { type NodeOfConnection } from "@salesforce/sdk-data";
|
|
38
|
-
|
|
39
|
-
type AccountNode = NodeOfConnection<GetHighRevenueAccountsQuery["uiapi"]["query"]["Account"]>;
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Use `NodeOfConnection` to extract the node type from a Connection type for cleaner typing.
|
|
43
|
-
|
|
44
|
-
## Query Patterns
|
|
45
|
-
|
|
46
|
-
Choose the pattern based on query complexity:
|
|
47
|
-
|
|
48
|
-
- **Pattern 1 — External `.graphql` file**: Recommended for complex queries with variables, fragments, or shared across files. Full codegen support, syntax highlighting, shareable. Requires codegen step after changes. Does NOT support dynamic queries.
|
|
49
|
-
- **Pattern 2 — Inline `gql` tag**: Recommended for simple queries. Supports dynamic queries (field set varies at runtime). **MUST use `gql` tag** — plain template strings bypass `@graphql-eslint` validation.
|
|
50
|
-
|
|
51
|
-
## Pattern 1: External .graphql File
|
|
52
|
-
|
|
53
|
-
Create a `.graphql` file, run `npm run graphql:codegen`, import with `?raw` suffix, and use generated types.
|
|
54
|
-
|
|
55
|
-
**Required imports:**
|
|
56
|
-
|
|
57
|
-
```typescript
|
|
58
|
-
import { createDataSDK, type NodeOfConnection } from "@salesforce/sdk-data";
|
|
59
|
-
import MY_QUERY from "./query/myQuery.graphql?raw"; // ?raw suffix required
|
|
60
|
-
import type { GetMyDataQuery, GetMyDataQueryVariables } from "../graphql-operations-types";
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
**Example usage:**
|
|
64
|
-
|
|
65
|
-
```typescript
|
|
66
|
-
const sdk = await createDataSDK();
|
|
67
|
-
const response = await sdk.graphql?.<GetMyDataQuery, GetMyDataQueryVariables>(
|
|
68
|
-
MY_QUERY,
|
|
69
|
-
variables
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
if (response?.errors?.length) {
|
|
73
|
-
throw new Error(response.errors.map((e) => e.message).join("; "));
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const nodes = response?.data?.uiapi?.query?.EntityName?.edges?.map((e) => e.node) ?? [];
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## Pattern 2: Inline gql Tag
|
|
80
|
-
|
|
81
|
-
**Required imports:**
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
import { createDataSDK, gql } from "@salesforce/sdk-data";
|
|
85
|
-
import { type CurrentUserQuery } from "../graphql-operations-types";
|
|
86
|
-
|
|
87
|
-
const MY_QUERY = gql`
|
|
88
|
-
query CurrentUser {
|
|
89
|
-
uiapi { ... }
|
|
90
|
-
}
|
|
91
|
-
`;
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
> **MUST use `gql` tag** — plain template strings bypass the `@graphql-eslint` processor entirely, meaning no lint validation against the schema.
|
|
95
|
-
|
|
96
|
-
## Error Handling Strategies
|
|
97
|
-
|
|
98
|
-
**Strategy A — Strict (default):** Treat any errors as failure.
|
|
99
|
-
|
|
100
|
-
```typescript
|
|
101
|
-
if (response?.errors?.length) {
|
|
102
|
-
throw new Error(response.errors.map((e) => e.message).join("; "));
|
|
103
|
-
}
|
|
104
|
-
const result = response?.data;
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
**Strategy B — Tolerant:** Log errors but use available data.
|
|
108
|
-
|
|
109
|
-
```typescript
|
|
110
|
-
if (response?.errors?.length) {
|
|
111
|
-
console.warn("GraphQL partial errors:", response.errors);
|
|
112
|
-
}
|
|
113
|
-
const result = response?.data;
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
**Strategy C — Discriminated:** Fail only when no data is returned. Useful for mutations where some return fields may be inaccessible.
|
|
117
|
-
|
|
118
|
-
```typescript
|
|
119
|
-
if (!response?.data && response?.errors?.length) {
|
|
120
|
-
throw new Error(response.errors.map((e) => e.message).join("; "));
|
|
121
|
-
}
|
|
122
|
-
const result = response?.data;
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
Responses follow `uiapi.query.ObjectName.edges[].node`; fields use `{ value }`.
|
|
126
|
-
|
|
127
|
-
## Conditional Field Selection
|
|
128
|
-
|
|
129
|
-
For dynamic fieldsets with **known** fields, use `@include(if: $condition)` and `@skip(if: $condition)` directives in `.graphql` files. See GraphQL spec for details.
|
|
130
|
-
|
|
131
|
-
## ESLint Validation
|
|
132
|
-
|
|
133
|
-
After writing the query into a source file, validate it against the schema:
|
|
134
|
-
|
|
135
|
-
```bash
|
|
136
|
-
# Run from UI bundle dir (force-app/main/default/uiBundles/<app-name>/)
|
|
137
|
-
npx eslint <path-to-file-containing-query>
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
**How it works:** The ESLint config uses `@graphql-eslint/eslint-plugin` with its `processor`, which extracts GraphQL operations from `gql` template literals in `.ts`/`.tsx` files and validates the extracted `.graphql` virtual files against `schema.graphql`.
|
|
141
|
-
|
|
142
|
-
**Rules enforced:** `no-anonymous-operations`, `no-duplicate-fields`, `known-fragment-names`, `no-undefined-variables`, `no-unused-variables`
|
|
143
|
-
|
|
144
|
-
**On failure:** Fix the reported issues, re-run `npx eslint <file>` until clean, then proceed to testing.
|
|
145
|
-
|
|
146
|
-
> **Prerequisites**: The `schema.graphql` file must exist and project dependencies must be installed (`npm install`).
|
|
147
|
-
|
|
148
|
-
## Codegen
|
|
149
|
-
|
|
150
|
-
Generate TypeScript types from `.graphql` files and inline `gql` queries:
|
|
151
|
-
|
|
152
|
-
```bash
|
|
153
|
-
# Run from UI bundle dir (force-app/main/default/uiBundles/<app-name>/)
|
|
154
|
-
npm run graphql:codegen
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
Output: `src/api/graphql-operations-types.ts`
|
|
158
|
-
|
|
159
|
-
Naming conventions:
|
|
160
|
-
- `<OperationName>Query` / `<OperationName>Mutation` — response types
|
|
161
|
-
- `<OperationName>QueryVariables` / `<OperationName>MutationVariables` — variable types
|
|
162
|
-
|
|
163
|
-
## Anti-Patterns
|
|
164
|
-
|
|
165
|
-
### Direct API Calls
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
// NOT RECOMMENDED: Direct axios/fetch calls for GraphQL
|
|
169
|
-
// PREFERRED: Use the Data SDK
|
|
170
|
-
const sdk = await createDataSDK();
|
|
171
|
-
const response = await sdk.graphql?.<ResponseType>(query, variables);
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
### Missing Type Definitions
|
|
175
|
-
|
|
176
|
-
```typescript
|
|
177
|
-
// NOT RECOMMENDED: Untyped GraphQL calls
|
|
178
|
-
// PREFERRED: Provide response type
|
|
179
|
-
const response = await sdk.graphql?.<GetMyDataQuery>(query);
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
### Plain String Queries (Without gql Tag)
|
|
183
|
-
|
|
184
|
-
```typescript
|
|
185
|
-
// NOT RECOMMENDED: Plain strings bypass ESLint validation
|
|
186
|
-
const query = `query { ... }`;
|
|
187
|
-
|
|
188
|
-
// PREFERRED: Use gql tag for inline queries
|
|
189
|
-
const QUERY = gql`query { ... }`;
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
## Quality Checklists
|
|
193
|
-
|
|
194
|
-
### For Pattern 1 (.graphql files):
|
|
195
|
-
|
|
196
|
-
1. [ ] All field names verified via schema search script
|
|
197
|
-
2. [ ] Create `.graphql` file for the query/mutation
|
|
198
|
-
3. [ ] Run `npm run graphql:codegen` to generate types
|
|
199
|
-
4. [ ] Import query with `?raw` suffix
|
|
200
|
-
5. [ ] Import generated types from `graphql-operations-types.ts`
|
|
201
|
-
6. [ ] Use `sdk.graphql?.<ResponseType>()` with proper generic
|
|
202
|
-
7. [ ] Handle `response.errors` and destructure `response.data`
|
|
203
|
-
8. [ ] Use `NodeOfConnection` for cleaner node types when needed
|
|
204
|
-
9. [ ] Run `npx eslint <file>` from UI bundle dir — fix all GraphQL errors
|
|
205
|
-
|
|
206
|
-
### For Pattern 2 (inline with gql):
|
|
207
|
-
|
|
208
|
-
1. [ ] All field names verified via schema search script
|
|
209
|
-
2. [ ] Define query using `gql` template tag (NOT a plain string)
|
|
210
|
-
3. [ ] Ensure query name matches generated types in `graphql-operations-types.ts`
|
|
211
|
-
4. [ ] Import generated types for the query
|
|
212
|
-
5. [ ] Use `sdk.graphql?.<ResponseType>()` with proper generic
|
|
213
|
-
6. [ ] Handle `response.errors` and destructure `response.data`
|
|
214
|
-
7. [ ] Run `npx eslint <file>` from UI bundle dir — fix all GraphQL errors
|
|
215
|
-
|
|
216
|
-
### General:
|
|
217
|
-
|
|
218
|
-
- [ ] Lint validation passes (`npx eslint <file>` reports no GraphQL errors)
|
|
219
|
-
- [ ] Query field names match the schema exactly (case-sensitive)
|
|
220
|
-
- [ ] Response type generic is provided to `sdk.graphql?.<T>()`
|
|
221
|
-
- [ ] Optional chaining is used for nested response data
|