5.1 KiB
Migration — old Data SDK → @salesforce/platform-sdk
The Data SDK changed in two breaking ways (PR #502, shipped in @salesforce/platform-sdk
v10.10.1):
- Package renamed —
@salesforce/sdk-data→@salesforce/platform-sdk. sdk.graphqlreshaped from a callable method into a namespace with.query()and.mutate(), both taking an options object.
Any remaining
@salesforce/sdk-datastrings in the webapps repo are staledist/build artifacts only — not canonical. Always import from@salesforce/platform-sdk.
This is the only document where the dead callable API appears, for comparison. Everywhere else in this skill uses the new API exclusively.
1. Import
- import { createDataSDK, gql, type NodeOfConnection } from "@salesforce/sdk-data";
+ import { createDataSDK, gql, type NodeOfConnection, type CacheControl } from "@salesforce/platform-sdk";
createDataSDK, gql, NodeOfConnection, and CacheControl all export from
@salesforce/platform-sdk.
2. Query call
- // OLD — callable, positional args, returns a response object with .data / .errors
- const response = await sdk.graphql?.<GetAccountsQuery, GetAccountsQueryVariables>(GET_ACCOUNTS, variables);
- const accounts = response?.data?.uiapi?.query?.Account?.edges ?? [];
- if (response?.errors?.length) { /* ... */ }
+ // NEW — namespace method, options bag, returns a reactive QueryResult
+ const result = await sdk.graphql!.query<GetAccountsQuery, GetAccountsQueryVariables>({
+ query: GET_ACCOUNTS,
+ variables,
+ });
+ const accounts = result.data?.uiapi?.query?.Account?.edges ?? [];
+ if (result.errors?.length) { /* ... */ }
Passing the generated <GetAccountsQuery> type parameter makes result.data fully typed — no
as any cast needed.
Mapping:
| Old | New |
|---|---|
sdk.graphql?.(QUERY, vars) |
sdk.graphql!.query({ query: QUERY, variables: vars }) |
positional <T, V>(query, variables) |
type params on query<T, V>(options) |
response.data / response.errors |
result.data / result.errors (same fields) |
| (none) | result.subscribe(cb) / result.refresh() — new reactive handle |
| (none) | cacheControl option — new per-call cache policy |
3. Mutation call
The old callable form was used for mutations too. Mutations now have their own method, and the
operation key is mutation, not query:
- const response = await sdk.graphql?.<CreateAccountMutation>(CREATE_ACCOUNT, { input });
+ const { data, errors } = await sdk.graphql!.mutate<CreateAccountMutation, CreateAccountMutationVariables>({
+ mutation: CREATE_ACCOUNT, // key is `mutation`, not `query`
+ variables: { input },
+ });
mutate() returns { data, errors } only — no subscribe/refresh, and it is never
cached. To refresh a list after a mutation, hold the query result and call
result.refresh() (see caching.md).
4. Optional chaining → non-null assertion
The old guidance was "always use optional chaining" (sdk.graphql?.()). Real consumer code now
uses the non-null assertion after createDataSDK():
- const response = await sdk.graphql?.(QUERY, vars);
+ const result = await sdk.graphql!.query({ query: QUERY, variables: vars });
sdk.graphql may still be undefined on some surfaces. Use ! when you know the surface
supports data ops; use an explicit guard if it might not:
if (!sdk.graphql) throw new Error("GraphQL not available on this surface");
const result = await sdk.graphql.query({ query: QUERY, variables: vars });
5. Codegen types — unchanged generation, new call placement
npm run graphql:codegen and the generated type names (<Op>Query / <Op>QueryVariables /
<Op>Mutation / <Op>MutationVariables) are unchanged. Only where the type params attach
moves — from the callable to the namespace method:
- await sdk.graphql?.<GetAccountsQuery, GetAccountsQueryVariables>(GET_ACCOUNTS, variables);
+ await sdk.graphql!.query<GetAccountsQuery, GetAccountsQueryVariables>({ query: GET_ACCOUNTS, variables });
6. New capabilities to consider while migrating
The reshape also unlocked the freshness features (none required to get back to working). The one
migration-specific gotcha: caching is now on by default (300s, WebApp) — if any code relied
on every call hitting the network, add cacheControl: "no-cache" to it. The reactive
subscribe/refresh handle and the rest of cacheControl are in caching.md.
7. Migration checklist
- Replace every
@salesforce/sdk-dataimport with@salesforce/platform-sdk - Convert every
sdk.graphql?.(q, v)query tosdk.graphql!.query({ query: q, variables: v }) - Convert every mutation call to
sdk.graphql!.mutate({ mutation: m, variables: v })(key ismutation) - Move generated type params onto
query<T,V>/mutate<T,V> - Rename
response→result;response.data/.errors→result.data/.errors - Add a
cacheControl: "no-cache"to any call that genuinely must always hit the network - Re-run
npm run graphql:codegenandnpx eslint <file>