afv-library/samples/webapp-template-app-react-sample-b2x-experimental/.a4drules/skills/feature-graphql-graphql-data-access/SKILL.md

156 lines
5.5 KiB
Markdown

---
name: graphql-data-access
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.
---
# GraphQL Data Access
Add or modify Salesforce GraphQL data access code using `getDataSDK()` + `data.graphql?.()` and codegen tooling.
## When to Use
- User asks to "fetch data from Salesforce"
- User asks to "query" or "mutate" Salesforce records
- User wants to add a new GraphQL operation (query or mutation)
- User asks to add data access for a Salesforce object (Account, Contact, Opportunity, etc.)
## Prerequisites
The base React app (`base-react-app`) ships with all GraphQL dependencies and tooling pre-configured:
- `@salesforce/sdk-data` — runtime SDK for `getDataSDK` and `gql`
- `@graphql-codegen/cli` + plugins — type generation from `.graphql` files and inline `gql` queries
- `@graphql-eslint/eslint-plugin` — linting for `.graphql` files and `gql` template literals
- `graphql` — shared by codegen, ESLint, and schema introspection
Before using this skill, ensure:
1. The `@salesforce/sdk-data` package is available (provides `getDataSDK`, `gql`, `NodeOfConnection`)
2. A `schema.graphql` file exists at the project root. If missing, generate it:
```bash
npm run graphql:schema
```
## npm Scripts
The base app provides two npm scripts for GraphQL tooling:
- **`npm run graphql:schema`** — Downloads the full GraphQL schema from a connected Salesforce org via introspection. Outputs `schema.graphql` to the project root.
- **`npm run graphql:codegen`** — Generates TypeScript types from `.graphql` files and inline `gql` queries. Outputs to `src/api/graphql-operations-types.ts`.
## Workflow
### Step 1: Explore the Schema
Before writing any query, verify the target object and its fields exist in the schema.
See `docs/explore-schema.md` for detailed guidance on exploring the Salesforce GraphQL schema.
Key actions:
- Search `schema.graphql` for `type <ObjectName> implements Record` to find available fields
- Search for `input <ObjectName>_Filter` for filter options
- Search for `input <ObjectName>_OrderBy` for sorting options
- For mutations: search for `input <ObjectName>CreateInput` or `<ObjectName>UpdateInput`
### Step 2: Choose the Query Pattern
**Pattern 1 — External `.graphql` file** (recommended for complex queries):
- Queries with variables, fragments, or shared across files
- Enables full codegen type generation
- See example: `api/utils/accounts.ts` + `api/utils/query/highRevenueAccountsQuery.graphql`
**Pattern 2 — Inline `gql` tag** (recommended for simple queries):
- Simple queries without variables
- Colocated with usage code
- See example: `api/utils/user.ts`
### Step 3: Write the Query
For **Pattern 1**:
1. Create a `.graphql` file under `src/api/utils/query/`
2. Follow UIAPI structure: `query { uiapi { query { ObjectName(...) { edges { node { ... } } } } } }`
3. For mutations, see `docs/generate-mutation-query.md`
4. For read queries, see `docs/generate-read-query.md`
For **Pattern 2**:
1. Define query inline using the `gql` template tag
2. Ensure the query name matches what codegen expects
### Step 4: Generate Types
```bash
npm run graphql:codegen
```
This updates `src/api/graphql-operations-types.ts` with:
- `<OperationName>Query` or `<OperationName>Mutation` — response type
- `<OperationName>QueryVariables` or `<OperationName>MutationVariables` — input variables type
### Step 5: Implement the Data Access Function
```typescript
// Pattern 1
import { getDataSDK, type NodeOfConnection } from "@salesforce/sdk-data";
import MY_QUERY from "./query/myQuery.graphql?raw";
import type { GetMyDataQuery, GetMyDataQueryVariables } from "../graphql-operations-types";
type MyNode = NodeOfConnection<GetMyDataQuery["uiapi"]["query"]["MyObject"]>;
export async function getMyData(variables: GetMyDataQueryVariables): Promise<MyNode[]> {
const data = await getDataSDK();
const response = await data.graphql?.<GetMyDataQuery, GetMyDataQueryVariables>(
MY_QUERY,
variables,
);
if (response?.errors?.length) {
const errorMessages = response.errors.map((e) => e.message).join("; ");
throw new Error(`GraphQL Error: ${errorMessages}`);
}
return response?.data?.uiapi?.query?.MyObject?.edges?.map((edge) => edge?.node) || [];
}
```
```typescript
// Pattern 2
import { getDataSDK, gql } from "@salesforce/sdk-data";
import type { MySimpleQuery } from "../graphql-operations-types";
const MY_QUERY = gql`
query MySimple {
uiapi { ... }
}
`;
export async function getSimpleData(): Promise<SomeType> {
const data = await getDataSDK();
const response = await data.graphql?.<MySimpleQuery>(MY_QUERY);
// check response.errors, then extract response.data
}
```
### Step 6: Verify
- [ ] Query field names match the schema exactly (case-sensitive)
- [ ] Response type generic is provided to `data.graphql?.<T>()`
- [ ] Optional chaining is used for nested response data
- [ ] Pattern 1: `.graphql` file imported with `?raw` suffix
- [ ] Pattern 2: Query uses `gql` tag (not plain string)
- [ ] Generated types imported from `graphql-operations-types.ts`
## Reference
- Schema exploration: `docs/explore-schema.md`
- Read query generation: `docs/generate-read-query.md`
- Mutation query generation: `docs/generate-mutation-query.md`
- Shared GraphQL schema types: `docs/shared-schema.graphqls`
- Schema download: `npm run graphql:schema` (in the base app)
- Type generation: `npm run graphql:codegen` (in the base app)