@salesforce/webapp-template-feature-react-authentication-experimental 1.105.0 → 1.106.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.
Files changed (62) hide show
  1. package/dist/.a4drules/skills/{feature-react-chart-analytics-charts → building-analytics-charts}/SKILL.md +1 -1
  2. package/dist/.a4drules/skills/{webapp-react-data-visualization → building-data-visualization}/SKILL.md +3 -3
  3. package/dist/.a4drules/skills/{webapp-react-data-visualization → building-data-visualization}/implementation/donut-chart.md +1 -1
  4. package/dist/.a4drules/skills/{webapp-react-interactive-map → building-interactive-map}/SKILL.md +1 -1
  5. package/dist/.a4drules/skills/{webapp-react → building-react-components}/SKILL.md +1 -1
  6. package/dist/.a4drules/skills/{webapp-react-weather-widget → building-weather-widget}/SKILL.md +2 -2
  7. package/dist/.a4drules/skills/{webapp-csp-trusted-sites → configuring-csp-trusted-sites}/SKILL.md +1 -1
  8. package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/SKILL.md +14 -14
  9. package/dist/.a4drules/skills/{feature-micro-frontend-micro-frontend → generating-micro-frontend-lwc}/SKILL.md +1 -1
  10. package/dist/.a4drules/skills/{feature-react-file-upload-file-upload → implementing-file-upload}/SKILL.md +1 -1
  11. package/dist/.a4drules/skills/{webapp-features → installing-webapp-features}/SKILL.md +1 -1
  12. package/dist/.a4drules/skills/{feature-react-agentforce-conversation-client-embedded-agent → integrating-agentforce-conversation-client}/SKILL.md +1 -1
  13. package/dist/.a4drules/skills/{webapp-unsplash-images → integrating-unsplash-images}/SKILL.md +1 -1
  14. package/dist/.a4drules/skills/salesforce-data-access/SKILL.md +165 -0
  15. package/dist/.a4drules/skills/salesforce-graphql/SKILL.md +323 -0
  16. package/dist/.a4drules/skills/salesforce-graphql-explore-schema/SKILL.md +160 -0
  17. package/dist/.a4drules/skills/{feature-graphql-graphql-data-access/docs/generate-mutation-query.md → salesforce-graphql-mutation-query/SKILL.md} +72 -42
  18. package/dist/.a4drules/skills/salesforce-graphql-read-query/SKILL.md +253 -0
  19. package/dist/.a4drules/skills/salesforce-rest-api-fetch/SKILL.md +167 -0
  20. package/dist/.a4drules/webapp-react.md +2 -50
  21. package/dist/AGENT.md +5 -0
  22. package/dist/CHANGELOG.md +19 -0
  23. package/dist/force-app/main/default/webapplications/feature-react-authentication/eslint.config.js +42 -27
  24. package/dist/force-app/main/default/webapplications/feature-react-authentication/vite.config.ts +17 -13
  25. package/dist/package.json +1 -1
  26. package/package.json +2 -2
  27. package/dist/.a4drules/features/feature-graphql-graphql-data-access-rule.md +0 -470
  28. package/dist/.a4drules/skills/feature-graphql-graphql-data-access/SKILL.md +0 -155
  29. package/dist/.a4drules/skills/feature-graphql-graphql-data-access/docs/explore-schema.md +0 -256
  30. package/dist/.a4drules/skills/feature-graphql-graphql-data-access/docs/generate-read-query.md +0 -202
  31. /package/dist/.a4drules/skills/{feature-react-chart-analytics-charts → building-analytics-charts}/docs/schema-mapping.md +0 -0
  32. /package/dist/.a4drules/skills/{webapp-react-data-visualization → building-data-visualization}/implementation/dashboard-layout.md +0 -0
  33. /package/dist/.a4drules/skills/{webapp-react-data-visualization → building-data-visualization}/implementation/stat-card.md +0 -0
  34. /package/dist/.a4drules/skills/{webapp-react-interactive-map → building-interactive-map}/implementation/geocoding.md +0 -0
  35. /package/dist/.a4drules/skills/{webapp-react-interactive-map → building-interactive-map}/implementation/leaflet-map.md +0 -0
  36. /package/dist/.a4drules/skills/{webapp-react → building-react-components}/implementation/component.md +0 -0
  37. /package/dist/.a4drules/skills/{webapp-react → building-react-components}/implementation/header-footer.md +0 -0
  38. /package/dist/.a4drules/skills/{webapp-react → building-react-components}/implementation/page.md +0 -0
  39. /package/dist/.a4drules/skills/{webapp-react-weather-widget → building-weather-widget}/implementation/weather-hook.md +0 -0
  40. /package/dist/.a4drules/skills/{webapp-react-weather-widget → building-weather-widget}/implementation/weather-ui.md +0 -0
  41. /package/dist/.a4drules/skills/{webapp-csp-trusted-sites → configuring-csp-trusted-sites}/implementation/metadata-format.md +0 -0
  42. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/data/charts.csv +0 -0
  43. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/data/colors.csv +0 -0
  44. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/data/icons.csv +0 -0
  45. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/data/landing.csv +0 -0
  46. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/data/products.csv +0 -0
  47. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/data/react-performance.csv +0 -0
  48. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/data/stacks/html-tailwind.csv +0 -0
  49. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/data/stacks/react.csv +0 -0
  50. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/data/stacks/shadcn.csv +0 -0
  51. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/data/styles.csv +0 -0
  52. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/data/typography.csv +0 -0
  53. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/data/ui-reasoning.csv +0 -0
  54. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/data/ux-guidelines.csv +0 -0
  55. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/data/web-interface.csv +0 -0
  56. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/scripts/core.js +0 -0
  57. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/scripts/design_system.js +0 -0
  58. /package/dist/.a4drules/skills/{webapp-ui-ux → designing-webapp-ui-ux}/scripts/search.js +0 -0
  59. /package/dist/.a4drules/skills/{feature-react-agentforce-conversation-client-embedded-agent → integrating-agentforce-conversation-client}/docs/embed-examples.md +0 -0
  60. /package/dist/.a4drules/skills/{feature-react-agentforce-conversation-client-embedded-agent → integrating-agentforce-conversation-client}/docs/troubleshooting.md +0 -0
  61. /package/dist/.a4drules/skills/{webapp-unsplash-images → integrating-unsplash-images}/implementation/usage.md +0 -0
  62. /package/dist/.a4drules/skills/{feature-graphql-graphql-data-access/docs → salesforce-graphql}/shared-schema.graphqls +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/webapp-template-feature-react-authentication-experimental",
3
- "version": "1.105.0",
3
+ "version": "1.106.0",
4
4
  "description": "Authentication feature for web applications",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "author": "",
@@ -16,7 +16,7 @@
16
16
  "clean": "rm -rf dist"
17
17
  },
18
18
  "devDependencies": {
19
- "@salesforce/webapp-experimental": "^1.105.0",
19
+ "@salesforce/webapp-experimental": "^1.106.0",
20
20
  "@tanstack/react-form": "^1.27.7",
21
21
  "@types/react": "^19.2.7",
22
22
  "@types/react-dom": "^19.2.3",
@@ -1,470 +0,0 @@
1
- ---
2
- paths:
3
- - "**/*.ts"
4
- - "**/*.tsx"
5
- ---
6
-
7
- # GraphQL Data Access
8
-
9
- Instructs agents to use the established GraphQL utilities for Salesforce data access.
10
-
11
- ## TypeScript Types & Code Generation
12
-
13
- ### Generated Types File
14
-
15
- Types are auto-generated at: `src/api/graphql-operations-types.ts`
16
-
17
- ### Generation Command
18
-
19
- ```bash
20
- npm run graphql:codegen
21
- ```
22
-
23
- The codegen configuration is at `codegen.yml` and generates types from:
24
-
25
- - Schema: `schema.graphql` (project root)
26
- - Documents: `src/**/*.{graphql,ts,tsx}`
27
-
28
- ### Type Naming Convention
29
-
30
- For a GraphQL operation named `GetHighRevenueAccounts`:
31
-
32
- - **Query/Mutation Response Type**: `GetHighRevenueAccountsQuery` or `GetHighRevenueAccountsMutation`
33
- - **Input Variables Type**: `GetHighRevenueAccountsQueryVariables` or `GetHighRevenueAccountsMutationVariables`
34
-
35
- ## Core Types & Function Signatures
36
-
37
- ### getDataSDK Function
38
-
39
- Available from `@salesforce/sdk-data`:
40
-
41
- ```typescript
42
- import { getDataSDK } from "@salesforce/sdk-data";
43
-
44
- const data = await getDataSDK();
45
- const response = await data.graphql?.<ResponseType, VariablesType>(query, variables);
46
- ```
47
-
48
- `getDataSDK()` returns a lazily-initialized `DataSDK` singleton. The `graphql` method uses optional chaining (`?.`) because not all surfaces support GraphQL.
49
-
50
- ### gql Template Tag
51
-
52
- Also available from `@salesforce/sdk-data` for inline query definitions:
53
-
54
- ```typescript
55
- import { gql } from "@salesforce/sdk-data";
56
-
57
- const MY_QUERY = gql`
58
- query MyQuery {
59
- uiapi {
60
- ...
61
- }
62
- }
63
- `;
64
- ```
65
-
66
- The `gql` tag is a template literal that allows defining GraphQL queries inline while maintaining syntax highlighting in most editors.
67
-
68
- ### GraphQLResponse Shape
69
-
70
- `data.graphql?.()` returns `GraphQLResponse<T>`. Callers destructure `{ data, errors }` and handle errors themselves:
71
-
72
- ```typescript
73
- interface GraphQLResponse<T> {
74
- data: T;
75
- errors?: Array<{
76
- message: string;
77
- locations?: Array<{ line: number; column: number }>;
78
- path?: string[];
79
- }>;
80
- }
81
- ```
82
-
83
- ### Handling Mixed Responses (Partial Success)
84
-
85
- GraphQL can return **both `data` and `errors`** in the same response (partial success). For example, some fields may resolve while others fail due to field-level security. Choose a strategy per use case:
86
-
87
- ```typescript
88
- // Strategy A: Strict — treat any errors as failure (default for most queries)
89
- if (response?.errors?.length) {
90
- throw new Error(response.errors.map((e) => e.message).join("; "));
91
- }
92
- const result = response?.data;
93
-
94
- // Strategy B: Tolerant — log errors but use partial data
95
- if (response?.errors?.length) {
96
- console.warn("GraphQL partial errors:", response.errors);
97
- }
98
- const result = response?.data;
99
-
100
- // Strategy C: Discriminated — fail only when no data came back
101
- if (response?.errors?.length && !response?.data) {
102
- throw new Error(response.errors.map((e) => e.message).join("; "));
103
- }
104
- if (response?.errors?.length) {
105
- console.warn("Partial success with errors:", response.errors);
106
- }
107
- const result = response?.data;
108
- ```
109
-
110
- **When to use each:**
111
-
112
- - **Strategy A** — Default. Use for queries where incomplete data would be misleading (e.g., financial summaries, approval workflows).
113
- - **Strategy B** — Use when partial data is still useful and the UI can degrade gracefully (e.g., dashboard tiles, optional fields).
114
- - **Strategy C** — Use for mutations where the operation may succeed but some return fields are inaccessible.
115
-
116
- For mutation-specific partial responses, see `docs/generate-mutation-query.md` which covers `PARTIAL` and `FAILED` status handling workflows.
117
-
118
- ### NodeOfConnection Utility Type
119
-
120
- Extract the node type from a connection (edges/node pattern):
121
-
122
- ```typescript
123
- import { type NodeOfConnection } from "@salesforce/sdk-data";
124
-
125
- // Extract Account node type from the query response
126
- type AccountNode = NodeOfConnection<GetHighRevenueAccountsQuery["uiapi"]["query"]["Account"]>;
127
- ```
128
-
129
- ### UIAPI Response Shape
130
-
131
- All Salesforce GraphQL record queries follow this structure (https://developer.salesforce.com/docs/platform/graphql/guide/query-record-objects.html):
132
-
133
- ```typescript
134
- interface UIAPIQueryResponse {
135
- uiapi: {
136
- query: {
137
- [ObjectName]: {
138
- edges?: Array<{
139
- node?: {
140
- Id: string;
141
- [FieldName]?: { value?: FieldType | null } | null;
142
- // Reference fields include the related record
143
- [ReferenceField]?: {
144
- value?: string | null; // The ID
145
- [RelatedField]?: { value?: RelatedType | null } | null;
146
- } | null;
147
- } | null;
148
- } | null> | null;
149
- } | null;
150
- };
151
- };
152
- }
153
- ```
154
-
155
- ## Required Workflow
156
-
157
- There are **two acceptable patterns** for defining GraphQL queries:
158
-
159
- ### Pattern 1: External .graphql File (Recommended for complex queries)
160
-
161
- #### Step 1: Create .graphql File
162
-
163
- Store queries in `.graphql` files for codegen to process:
164
-
165
- ```graphql
166
- # src/api/utils/query/myQuery.graphql
167
- query GetMyData($myVariable: String) {
168
- uiapi {
169
- query {
170
- MyObject(first: 10, where: { Field: { eq: $myVariable } }) {
171
- edges {
172
- node {
173
- Id
174
- Name {
175
- value
176
- }
177
- }
178
- }
179
- }
180
- }
181
- }
182
- }
183
- ```
184
-
185
- #### Step 2: Run Code Generation
186
-
187
- ```bash
188
- npm run graphql:codegen
189
- ```
190
-
191
- This generates types in `graphql-operations-types.ts`:
192
-
193
- - `GetMyDataQuery` - response type
194
- - `GetMyDataQueryVariables` - variables type
195
-
196
- #### Step 3: Import and Use
197
-
198
- ```typescript
199
- import { getDataSDK, type NodeOfConnection } from "@salesforce/sdk-data";
200
- import MY_QUERY from "./query/myQuery.graphql?raw";
201
- import type { GetMyDataQuery, GetMyDataQueryVariables } from "../graphql-operations-types";
202
-
203
- type MyNode = NodeOfConnection<GetMyDataQuery["uiapi"]["query"]["MyObject"]>;
204
-
205
- export async function getMyData(variables: GetMyDataQueryVariables): Promise<MyNode[]> {
206
- const data = await getDataSDK();
207
- const response = await data.graphql?.<GetMyDataQuery, GetMyDataQueryVariables>(
208
- MY_QUERY,
209
- variables,
210
- );
211
-
212
- if (response?.errors?.length) {
213
- const errorMessages = response.errors.map((e) => e.message).join("; ");
214
- throw new Error(`GraphQL Error: ${errorMessages}`);
215
- }
216
-
217
- return response?.data?.uiapi?.query?.MyObject?.edges?.map((edge) => edge?.node) || [];
218
- }
219
- ```
220
-
221
- **Key imports for Pattern 1:**
222
-
223
- - `getDataSDK` - Get the DataSDK singleton
224
- - `NodeOfConnection` - Extract node types from connection responses
225
- - Query from `.graphql` file with `?raw` suffix
226
- - Generated types from `graphql-operations-types.ts`
227
-
228
- **Pattern 1 Benefits:**
229
-
230
- - Full codegen support with automatic type generation
231
- - Syntax highlighting and validation in `.graphql` files
232
- - Easier to share queries across multiple files/components
233
- - Better for complex queries with fragments and multiple variables
234
- - IDE support for GraphQL (autocomplete, validation)
235
- - Queries can be tested independently
236
- - Clear separation of concerns between query definition and usage
237
-
238
- **Pattern 1 Limitations:**
239
-
240
- - Requires separate file management
241
- - Extra step to run codegen after query changes
242
- - More boilerplate (file import with `?raw`, separate file to maintain)
243
- - Slight overhead for very simple queries
244
- - Need to navigate between files during development
245
- - Doesn't support dynamic queries (e.g., the set of fields changes based on runtime conditions and cannot be predetermined)
246
-
247
- ### Pattern 2: Inline Query with gql Tag (Recommended for simple queries)
248
-
249
- For simpler queries without variables or when colocation is preferred:
250
-
251
- ```typescript
252
- import { getDataSDK, gql } from "@salesforce/sdk-data";
253
- import { type CurrentUserQuery } from "../graphql-operations-types";
254
-
255
- const CURRENT_USER_QUERY = gql`
256
- query CurrentUser {
257
- uiapi {
258
- currentUser {
259
- Id
260
- Name {
261
- value
262
- }
263
- }
264
- }
265
- }
266
- `;
267
-
268
- interface User {
269
- id: string;
270
- name: string;
271
- }
272
-
273
- export async function getCurrentUser(): Promise<User | null> {
274
- try {
275
- const data = await getDataSDK();
276
- const response = await data.graphql?.<CurrentUserQuery>(CURRENT_USER_QUERY);
277
-
278
- if (response?.errors?.length) {
279
- throw new Error(response.errors.map((e) => e.message).join("; "));
280
- }
281
-
282
- const userData = response?.data?.uiapi.currentUser;
283
-
284
- if (!userData) {
285
- throw new Error("No user data found");
286
- }
287
-
288
- return {
289
- id: userData.Id,
290
- name: userData.Name?.value || "User",
291
- };
292
- } catch (error) {
293
- console.error("Error fetching user data:", error);
294
- throw error;
295
- }
296
- }
297
- ```
298
-
299
- **Key imports for Pattern 2:**
300
-
301
- - `getDataSDK` - Get the DataSDK singleton
302
- - `gql` - Template tag for inline query definition
303
- - Generated types from `graphql-operations-types.ts`
304
-
305
- **Pattern 2 Benefits:**
306
-
307
- - Query is colocated with usage code
308
- - Supports dynamic queries (e.g., the set of fields changes based on runtime conditions and cannot be predetermined)
309
- - No separate file to maintain
310
- - Still gets type-checked against generated types
311
- - Simpler for straightforward queries
312
-
313
- **Pattern 2 Limitations:**
314
-
315
- - Inline queries without `gql` template tag are not processed by codegen
316
- - Must manually ensure query name matches generated types
317
- - Less suitable for complex queries with fragments
318
-
319
- ## Conditional Field Selection with Directives
320
-
321
- For dynamic fieldsets with known fields that should be conditionally included, use GraphQL directives instead of building queries dynamically. This preserves type generation while allowing runtime control.
322
-
323
- ### Directives
324
-
325
- - **`@include(if: $condition)`** - include field/fragment when `$condition` is `true`
326
- - **`@skip(if: $condition)`** - skip field/fragment when `$condition` is `true`
327
-
328
- ### Example with Fragments
329
-
330
- ```graphql
331
- query GetAccountDetails($id: ID!, $includeFinancials: Boolean!, $includeContacts: Boolean!) {
332
- uiapi {
333
- query {
334
- Account(where: { Id: { eq: $id } }) {
335
- edges {
336
- node {
337
- Id
338
- Name {
339
- value
340
- }
341
- ...FinancialFields @include(if: $includeFinancials)
342
- ...ContactFields @include(if: $includeContacts)
343
- }
344
- }
345
- }
346
- }
347
- }
348
- }
349
-
350
- fragment FinancialFields on Account {
351
- AnnualRevenue {
352
- value
353
- }
354
- NumberOfEmployees {
355
- value
356
- }
357
- }
358
-
359
- fragment ContactFields on Account {
360
- Phone {
361
- value
362
- }
363
- Website {
364
- value
365
- }
366
- }
367
- ```
368
-
369
- ### Usage
370
-
371
- ```typescript
372
- import { getDataSDK } from "@salesforce/sdk-data";
373
- import QUERY from "./query/getAccountDetails.graphql?raw";
374
- import type {
375
- GetAccountDetailsQuery,
376
- GetAccountDetailsQueryVariables,
377
- } from "../graphql-operations-types";
378
-
379
- const data = await getDataSDK();
380
- const response = await data.graphql?.<GetAccountDetailsQuery, GetAccountDetailsQueryVariables>(
381
- QUERY,
382
- {
383
- id: accountId,
384
- includeFinancials: userWantsFinancials,
385
- includeContacts: userWantsContacts,
386
- },
387
- );
388
- ```
389
-
390
- ## Anti-Patterns (Not Recommended)
391
-
392
- ### Direct API Calls
393
-
394
- ```typescript
395
- // NOT RECOMMENDED: Direct axios/fetch calls for GraphQL
396
- const response = await axios.post("/graphql", { query });
397
-
398
- // PREFERRED: Use the DataSDK
399
- const data = await getDataSDK();
400
- const response = await data.graphql?.<ResponseType>(query, variables);
401
- ```
402
-
403
- ### Missing Type Definitions
404
-
405
- ```typescript
406
- // NOT RECOMMENDED: Untyped GraphQL calls
407
- const data = await getDataSDK();
408
- await data.graphql?.(query);
409
-
410
- // PREFERRED: Provide response type
411
- const data = await getDataSDK();
412
- const response = await data.graphql?.<GetMyDataQuery>(query);
413
- ```
414
-
415
- ### Plain String Queries (Without gql Tag)
416
-
417
- ```typescript
418
- // NOT RECOMMENDED: Plain string queries without gql tag
419
- const query = `query { ... }`;
420
- const data = await getDataSDK();
421
- await data.graphql?.(query);
422
-
423
- // PREFERRED: Use gql tag for inline queries
424
- const QUERY = gql`query { ... }`;
425
- const data = await getDataSDK();
426
- const response = await data.graphql?.<ResponseType>(QUERY);
427
-
428
- // OR: Use .graphql file for complex queries
429
- import QUERY from "./query/myQuery.graphql?raw";
430
- const data = await getDataSDK();
431
- const response = await data.graphql?.<ResponseType>(QUERY);
432
- ```
433
-
434
- ## Benefits of the DataSDK GraphQL API
435
-
436
- - Uses the DataSDK with proper authentication and CSRF token handling
437
- - Consistent typing with `GraphQLResponse<T>` interface
438
- - Optional chaining (`?.`) safely handles surfaces where GraphQL is unavailable
439
- - Callers get full `GraphQLResponse<T>` for flexible error handling
440
-
441
- ## Quality Checklist
442
-
443
- Before completing GraphQL data access code:
444
-
445
- ### For Pattern 1 (.graphql files):
446
-
447
- 1. [ ] Create `.graphql` file for the query/mutation
448
- 2. [ ] Run `npm run graphql:codegen` to generate types
449
- 3. [ ] Import query with `?raw` suffix
450
- 4. [ ] Import generated types from `graphql-operations-types.ts`
451
- 5. [ ] Use `data.graphql?.<ResponseType>()` with proper generic
452
- 6. [ ] Handle `response.errors` and destructure `response.data`
453
- 7. [ ] Use `NodeOfConnection` for cleaner node types when needed
454
- 8. [ ] Handle optional chaining for nested response data
455
- 9. [ ] Follow the pattern in `accounts.ts`
456
-
457
- ### For Pattern 2 (inline with gql):
458
-
459
- 1. [ ] Define query using `gql` template tag
460
- 2. [ ] Ensure query name matches generated types in `graphql-operations-types.ts`
461
- 3. [ ] Import generated types for the query
462
- 4. [ ] Use `data.graphql?.<ResponseType>()` with proper generic
463
- 5. [ ] Handle `response.errors` and destructure `response.data`
464
- 6. [ ] Handle optional chaining for nested response data
465
- 7. [ ] Follow the pattern in `user.ts`
466
-
467
- ### General:
468
-
469
- - [ ] Choose Pattern 1 for complex queries with variables, fragments, or when shared
470
- - [ ] Choose Pattern 2 for simple, colocated queries without complex requirements
@@ -1,155 +0,0 @@
1
- ---
2
- name: feature-graphql-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)