@salesforce/webapp-template-feature-react-chart-experimental 1.56.0 → 1.56.1
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/code-quality.md +0 -1
- package/dist/.a4drules/graphql.md +102 -51
- package/dist/.a4drules/react.md +67 -66
- package/dist/.a4drules/typescript.md +10 -21
- package/dist/CHANGELOG.md +8 -0
- package/dist/force-app/main/default/webapplications/feature-react-chart/package-lock.json +15 -15
- package/dist/package.json +1 -1
- package/package.json +3 -3
|
@@ -28,24 +28,71 @@ For a GraphQL operation named `GetHighRevenueAccounts`:
|
|
|
28
28
|
|
|
29
29
|
## Core Types & Function Signatures
|
|
30
30
|
|
|
31
|
-
###
|
|
32
|
-
|
|
31
|
+
### getDataSDK Function
|
|
32
|
+
Available from `@salesforce/webapp-experimental/api`:
|
|
33
33
|
|
|
34
34
|
```typescript
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
import { getDataSDK } from '@salesforce/webapp-experimental/api';
|
|
36
|
+
|
|
37
|
+
const data = await getDataSDK();
|
|
38
|
+
const response = await data.graphql?.<ResponseType, VariablesType>(query, variables);
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
- `
|
|
42
|
-
|
|
41
|
+
`getDataSDK()` returns a lazily-initialized `DataSDK` singleton. The `graphql` method uses optional chaining (`?.`) because not all surfaces support GraphQL.
|
|
42
|
+
|
|
43
|
+
### GraphQLResponse Shape
|
|
44
|
+
`data.graphql?.()` returns `GraphQLResponse<T>`. Callers destructure `{ data, errors }` and handle errors themselves:
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
interface GraphQLResponse<T> {
|
|
48
|
+
data: T;
|
|
49
|
+
errors?: Array<{
|
|
50
|
+
message: string;
|
|
51
|
+
locations?: Array<{ line: number; column: number }>;
|
|
52
|
+
path?: string[];
|
|
53
|
+
}>;
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Handling Mixed Responses (Partial Success)
|
|
58
|
+
|
|
59
|
+
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:
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
// Strategy A: Strict — treat any errors as failure (default for most queries)
|
|
63
|
+
if (response?.errors?.length) {
|
|
64
|
+
throw new Error(response.errors.map(e => e.message).join('; '));
|
|
65
|
+
}
|
|
66
|
+
const result = response?.data;
|
|
67
|
+
|
|
68
|
+
// Strategy B: Tolerant — log errors but use partial data
|
|
69
|
+
if (response?.errors?.length) {
|
|
70
|
+
console.warn('GraphQL partial errors:', response.errors);
|
|
71
|
+
}
|
|
72
|
+
const result = response?.data;
|
|
73
|
+
|
|
74
|
+
// Strategy C: Discriminated — fail only when no data came back
|
|
75
|
+
if (response?.errors?.length && !response?.data) {
|
|
76
|
+
throw new Error(response.errors.map(e => e.message).join('; '));
|
|
77
|
+
}
|
|
78
|
+
if (response?.errors?.length) {
|
|
79
|
+
console.warn('Partial success with errors:', response.errors);
|
|
80
|
+
}
|
|
81
|
+
const result = response?.data;
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**When to use each:**
|
|
85
|
+
- **Strategy A** — Default. Use for queries where incomplete data would be misleading (e.g., financial summaries, approval workflows).
|
|
86
|
+
- **Strategy B** — Use when partial data is still useful and the UI can degrade gracefully (e.g., dashboard tiles, optional fields).
|
|
87
|
+
- **Strategy C** — Use for mutations where the operation may succeed but some return fields are inaccessible.
|
|
88
|
+
|
|
89
|
+
For mutation-specific partial responses, see `docs/generate-mutation-query.md` which covers `PARTIAL` and `FAILED` status handling workflows.
|
|
43
90
|
|
|
44
91
|
### gql Template Tag
|
|
45
|
-
Also
|
|
92
|
+
Also available from `@salesforce/webapp-experimental/api` for inline query definitions:
|
|
46
93
|
|
|
47
94
|
```typescript
|
|
48
|
-
import { gql } from '
|
|
95
|
+
import { gql } from '@salesforce/webapp-experimental/api';
|
|
49
96
|
|
|
50
97
|
const MY_QUERY = gql`
|
|
51
98
|
query MyQuery {
|
|
@@ -58,25 +105,11 @@ const MY_QUERY = gql`
|
|
|
58
105
|
|
|
59
106
|
The `gql` tag is a template literal that allows defining GraphQL queries inline while maintaining syntax highlighting in most editors.
|
|
60
107
|
|
|
61
|
-
### GraphQLResponse Shape
|
|
62
|
-
The raw response wrapper (handled internally by `executeGraphQL`):
|
|
63
|
-
|
|
64
|
-
```typescript
|
|
65
|
-
interface GraphQLResponse<T> {
|
|
66
|
-
data: T;
|
|
67
|
-
errors?: Array<{
|
|
68
|
-
message: string;
|
|
69
|
-
locations?: Array<{ line: number; column: number }>;
|
|
70
|
-
path?: string[];
|
|
71
|
-
}>;
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
108
|
### NodeOfConnection Utility Type
|
|
76
109
|
Extract the node type from a connection (edges/node pattern):
|
|
77
110
|
|
|
78
111
|
```typescript
|
|
79
|
-
import { type NodeOfConnection } from '
|
|
112
|
+
import { type NodeOfConnection } from '@salesforce/webapp-experimental/api';
|
|
80
113
|
|
|
81
114
|
// Extract Account node type from the query response
|
|
82
115
|
type AccountNode = NodeOfConnection<
|
|
@@ -147,26 +180,32 @@ This generates types in `graphql-operations-types.ts`:
|
|
|
147
180
|
|
|
148
181
|
#### Step 3: Import and Use
|
|
149
182
|
```typescript
|
|
150
|
-
import {
|
|
183
|
+
import { getDataSDK, type NodeOfConnection } from '@salesforce/webapp-experimental/api';
|
|
151
184
|
import MY_QUERY from './query/myQuery.graphql?raw';
|
|
152
185
|
import type {
|
|
153
186
|
GetMyDataQuery,
|
|
154
187
|
GetMyDataQueryVariables,
|
|
155
188
|
} from '../graphql-operations-types';
|
|
156
189
|
|
|
157
|
-
// Extract node type for cleaner return types
|
|
158
190
|
type MyNode = NodeOfConnection<GetMyDataQuery['uiapi']['query']['MyObject']>;
|
|
159
191
|
|
|
160
192
|
export async function getMyData(
|
|
161
193
|
variables: GetMyDataQueryVariables
|
|
162
194
|
): Promise<MyNode[]> {
|
|
163
|
-
const
|
|
164
|
-
|
|
195
|
+
const data = await getDataSDK();
|
|
196
|
+
const response = await data.graphql?.<GetMyDataQuery, GetMyDataQueryVariables>(MY_QUERY, variables);
|
|
197
|
+
|
|
198
|
+
if (response?.errors?.length) {
|
|
199
|
+
const errorMessages = response.errors.map(e => e.message).join('; ');
|
|
200
|
+
throw new Error(`GraphQL Error: ${errorMessages}`);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return response?.data?.uiapi?.query?.MyObject?.edges?.map(edge => edge?.node) || [];
|
|
165
204
|
}
|
|
166
205
|
```
|
|
167
206
|
|
|
168
207
|
**Key imports for Pattern 1:**
|
|
169
|
-
- `
|
|
208
|
+
- `getDataSDK` - Get the DataSDK singleton
|
|
170
209
|
- `NodeOfConnection` - Extract node types from connection responses
|
|
171
210
|
- Query from `.graphql` file with `?raw` suffix
|
|
172
211
|
- Generated types from `graphql-operations-types.ts`
|
|
@@ -193,7 +232,7 @@ export async function getMyData(
|
|
|
193
232
|
For simpler queries without variables or when colocation is preferred:
|
|
194
233
|
|
|
195
234
|
```typescript
|
|
196
|
-
import {
|
|
235
|
+
import { getDataSDK, gql } from '@salesforce/webapp-experimental/api';
|
|
197
236
|
import { type CurrentUserQuery } from '../graphql-operations-types';
|
|
198
237
|
|
|
199
238
|
const CURRENT_USER_QUERY = gql`
|
|
@@ -216,9 +255,14 @@ interface User {
|
|
|
216
255
|
|
|
217
256
|
export async function getCurrentUser(): Promise<User | null> {
|
|
218
257
|
try {
|
|
219
|
-
const
|
|
258
|
+
const data = await getDataSDK();
|
|
259
|
+
const response = await data.graphql?.<CurrentUserQuery>(CURRENT_USER_QUERY);
|
|
260
|
+
|
|
261
|
+
if (response?.errors?.length) {
|
|
262
|
+
throw new Error(response.errors.map(e => e.message).join('; '));
|
|
263
|
+
}
|
|
220
264
|
|
|
221
|
-
const userData = response
|
|
265
|
+
const userData = response?.data?.uiapi.currentUser;
|
|
222
266
|
|
|
223
267
|
if (!userData) {
|
|
224
268
|
throw new Error('No user data found');
|
|
@@ -236,7 +280,7 @@ export async function getCurrentUser(): Promise<User | null> {
|
|
|
236
280
|
```
|
|
237
281
|
|
|
238
282
|
**Key imports for Pattern 2:**
|
|
239
|
-
- `
|
|
283
|
+
- `getDataSDK` - Get the DataSDK singleton
|
|
240
284
|
- `gql` - Template tag for inline query definition
|
|
241
285
|
- Generated types from `graphql-operations-types.ts`
|
|
242
286
|
|
|
@@ -259,7 +303,7 @@ See `force-app/main/default/webapplications/<appName>/src/api/utils/accounts.ts`
|
|
|
259
303
|
1. Importing query from `.graphql` file with `?raw` suffix
|
|
260
304
|
2. Importing generated types from `graphql-operations-types.ts`
|
|
261
305
|
3. Using `NodeOfConnection` to extract node types
|
|
262
|
-
4. Proper typing with `
|
|
306
|
+
4. Proper typing with `data.graphql?.<ResponseType>(query, variables)`
|
|
263
307
|
5. Safe data extraction from the nested response
|
|
264
308
|
|
|
265
309
|
### Pattern 2 Example: user.ts
|
|
@@ -315,14 +359,15 @@ fragment ContactFields on Account {
|
|
|
315
359
|
|
|
316
360
|
### Usage
|
|
317
361
|
```typescript
|
|
318
|
-
import {
|
|
362
|
+
import { getDataSDK } from '@salesforce/webapp-experimental/api';
|
|
319
363
|
import QUERY from './query/getAccountDetails.graphql?raw';
|
|
320
364
|
import type {
|
|
321
365
|
GetAccountDetailsQuery,
|
|
322
366
|
GetAccountDetailsQueryVariables,
|
|
323
367
|
} from '../graphql-operations-types';
|
|
324
368
|
|
|
325
|
-
const data = await
|
|
369
|
+
const data = await getDataSDK();
|
|
370
|
+
const response = await data.graphql?.<GetAccountDetailsQuery, GetAccountDetailsQueryVariables>(QUERY, {
|
|
326
371
|
id: accountId,
|
|
327
372
|
includeFinancials: userWantsFinancials,
|
|
328
373
|
includeContacts: userWantsContacts,
|
|
@@ -343,32 +388,38 @@ const data = await executeGraphQL<GetAccountDetailsQuery>(QUERY, {
|
|
|
343
388
|
// NOT RECOMMENDED: Direct axios/fetch calls for GraphQL
|
|
344
389
|
const response = await axios.post('/graphql', { query });
|
|
345
390
|
|
|
346
|
-
// PREFERRED: Use
|
|
347
|
-
const data = await
|
|
391
|
+
// PREFERRED: Use the DataSDK
|
|
392
|
+
const data = await getDataSDK();
|
|
393
|
+
const response = await data.graphql?.<ResponseType>(query, variables);
|
|
348
394
|
```
|
|
349
395
|
|
|
350
396
|
### Missing Type Definitions
|
|
351
397
|
```typescript
|
|
352
398
|
// NOT RECOMMENDED: Untyped GraphQL calls
|
|
353
|
-
const data = await
|
|
399
|
+
const data = await getDataSDK();
|
|
400
|
+
await data.graphql?.(query);
|
|
354
401
|
|
|
355
402
|
// PREFERRED: Provide response type
|
|
356
|
-
const data = await
|
|
403
|
+
const data = await getDataSDK();
|
|
404
|
+
const response = await data.graphql?.<GetMyDataQuery>(query);
|
|
357
405
|
```
|
|
358
406
|
|
|
359
407
|
### Plain String Queries (Without gql Tag)
|
|
360
408
|
```typescript
|
|
361
409
|
// NOT RECOMMENDED: Plain string queries without gql tag
|
|
362
410
|
const query = `query { ... }`;
|
|
363
|
-
const data = await
|
|
411
|
+
const data = await getDataSDK();
|
|
412
|
+
await data.graphql?.(query);
|
|
364
413
|
|
|
365
414
|
// PREFERRED: Use gql tag for inline queries
|
|
366
415
|
const QUERY = gql`query { ... }`;
|
|
367
|
-
const data = await
|
|
416
|
+
const data = await getDataSDK();
|
|
417
|
+
const response = await data.graphql?.<ResponseType>(QUERY);
|
|
368
418
|
|
|
369
419
|
// OR: Use .graphql file for complex queries
|
|
370
420
|
import QUERY from './query/myQuery.graphql?raw';
|
|
371
|
-
const data = await
|
|
421
|
+
const data = await getDataSDK();
|
|
422
|
+
const response = await data.graphql?.<ResponseType>(QUERY);
|
|
372
423
|
```
|
|
373
424
|
|
|
374
425
|
**Why avoid plain strings:**
|
|
@@ -376,11 +427,11 @@ const data = await executeGraphQL<ResponseType>(QUERY);
|
|
|
376
427
|
- Harder to maintain and refactor
|
|
377
428
|
- More error-prone
|
|
378
429
|
|
|
379
|
-
## Benefits of
|
|
380
|
-
-
|
|
430
|
+
## Benefits of the DataSDK GraphQL API
|
|
431
|
+
- Uses the DataSDK with proper authentication and CSRF token handling
|
|
381
432
|
- Consistent typing with `GraphQLResponse<T>` interface
|
|
382
|
-
-
|
|
383
|
-
-
|
|
433
|
+
- Optional chaining (`?.`) safely handles surfaces where GraphQL is unavailable
|
|
434
|
+
- Callers get full `GraphQLResponse<T>` for flexible error handling
|
|
384
435
|
|
|
385
436
|
## Quality Checklist
|
|
386
437
|
Before completing GraphQL data access code:
|
|
@@ -390,7 +441,7 @@ Before completing GraphQL data access code:
|
|
|
390
441
|
2. [ ] Run `npm run graphql:codegen` to generate types
|
|
391
442
|
3. [ ] Import query with `?raw` suffix
|
|
392
443
|
4. [ ] Import generated types from `graphql-operations-types.ts`
|
|
393
|
-
5. [ ] Use `
|
|
444
|
+
5. [ ] Use `data.graphql?.<ResponseType>()` with proper generic
|
|
394
445
|
6. [ ] Use `NodeOfConnection` for cleaner node types when needed
|
|
395
446
|
7. [ ] Handle optional chaining for nested response data
|
|
396
447
|
8. [ ] Follow the pattern in `accounts.ts`
|
|
@@ -399,8 +450,8 @@ Before completing GraphQL data access code:
|
|
|
399
450
|
1. [ ] Define query using `gql` template tag
|
|
400
451
|
2. [ ] Ensure query name matches generated types in `graphql-operations-types.ts`
|
|
401
452
|
3. [ ] Import generated types for the query
|
|
402
|
-
4. [ ] Use `
|
|
403
|
-
5. [ ] Handle errors
|
|
453
|
+
4. [ ] Use `data.graphql?.<ResponseType>()` with proper generic
|
|
454
|
+
5. [ ] Handle `response.errors` and destructure `response.data`
|
|
404
455
|
6. [ ] Handle optional chaining for nested response data
|
|
405
456
|
7. [ ] Follow the pattern in `user.ts`
|
|
406
457
|
|
package/dist/.a4drules/react.md
CHANGED
|
@@ -123,7 +123,7 @@ Before implementing data access, **MUST** verify `orchestrate_lds_data_requireme
|
|
|
123
123
|
|
|
124
124
|
## Data Access Rules (CRITICAL)
|
|
125
125
|
|
|
126
|
-
- MANDATORY: Use `
|
|
126
|
+
- MANDATORY: Use the DataSDK (`getDataSDK()` from `@salesforce/webapp-experimental/api`) for all API calls from React. The SDK handles authentication and CSRF token management. Do NOT use `axios` or raw `fetch` for Salesforce API calls.
|
|
127
127
|
|
|
128
128
|
### Data Access Workflow (MANDATORY)
|
|
129
129
|
|
|
@@ -158,46 +158,12 @@ The LWC MCP server's `orchestrate_lds_data_requirements` tool follows this prior
|
|
|
158
158
|
|
|
159
159
|
The following code examples serve as reference patterns for React applications. **Always consult the LWC MCP server's `orchestrate_lds_data_requirements` tool first** to ensure you're using the most appropriate pattern and latest best practices for your specific use case.
|
|
160
160
|
|
|
161
|
-
UI API example (read):
|
|
162
|
-
|
|
163
|
-
```javascript
|
|
164
|
-
async function fetchRecord(recordId) {
|
|
165
|
-
try {
|
|
166
|
-
const res = await axios.get(
|
|
167
|
-
`/services/data/v62.0/ui-api/records/${recordId}`
|
|
168
|
-
);
|
|
169
|
-
return res.data;
|
|
170
|
-
} catch (error) {
|
|
171
|
-
const text = error.message;
|
|
172
|
-
throw new Error(`UI API failed: ${error.status} ${text}`);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
GraphQL utility (supports both queries and mutations):
|
|
178
|
-
|
|
179
|
-
```javascript
|
|
180
|
-
export async function sfGraphQL(query, variables = {}) {
|
|
181
|
-
try {
|
|
182
|
-
const res = await axios.post('/services/data/v62.0/graphql', {
|
|
183
|
-
query,
|
|
184
|
-
variables,
|
|
185
|
-
});
|
|
186
|
-
const json = res.data;
|
|
187
|
-
if (Array.isArray(json.errors) && json.errors.length) {
|
|
188
|
-
throw new Error(json.errors.map(e => e.message).join('; '));
|
|
189
|
-
}
|
|
190
|
-
return json.data;
|
|
191
|
-
} catch (error) {
|
|
192
|
-
throw new Error(`GraphQL error: ${error.status}`);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
```
|
|
196
|
-
|
|
197
161
|
GraphQL query example:
|
|
198
162
|
|
|
199
|
-
```
|
|
200
|
-
|
|
163
|
+
```typescript
|
|
164
|
+
import { getDataSDK, gql } from '@salesforce/webapp-experimental/api';
|
|
165
|
+
|
|
166
|
+
const GET_ACCOUNT = gql`
|
|
201
167
|
query GetAccount($id: ID!) {
|
|
202
168
|
uiapi {
|
|
203
169
|
query {
|
|
@@ -216,13 +182,22 @@ const GET_ACCOUNT = `
|
|
|
216
182
|
}
|
|
217
183
|
`;
|
|
218
184
|
|
|
219
|
-
const
|
|
185
|
+
const data = await getDataSDK();
|
|
186
|
+
const response = await data.graphql?.<GetAccountQuery>(GET_ACCOUNT, { id: '001...' });
|
|
187
|
+
|
|
188
|
+
if (response?.errors?.length) {
|
|
189
|
+
throw new Error(response.errors.map(e => e.message).join('; '));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const account = response?.data;
|
|
220
193
|
```
|
|
221
194
|
|
|
222
195
|
GraphQL mutation example:
|
|
223
196
|
|
|
224
|
-
```
|
|
225
|
-
|
|
197
|
+
```typescript
|
|
198
|
+
import { getDataSDK, gql } from '@salesforce/webapp-experimental/api';
|
|
199
|
+
|
|
200
|
+
const UPDATE_ACCOUNT = gql`
|
|
226
201
|
mutation UpdateAccount($id: ID!, $name: String!) {
|
|
227
202
|
uiapi {
|
|
228
203
|
AccountUpdate(input: {
|
|
@@ -242,10 +217,32 @@ const UPDATE_ACCOUNT = `
|
|
|
242
217
|
}
|
|
243
218
|
`;
|
|
244
219
|
|
|
245
|
-
const
|
|
220
|
+
const data = await getDataSDK();
|
|
221
|
+
const result = await data.graphql?.<UpdateAccountMutation>(UPDATE_ACCOUNT, {
|
|
246
222
|
id: '001...',
|
|
247
223
|
name: 'New Name',
|
|
248
224
|
});
|
|
225
|
+
|
|
226
|
+
if (result?.errors?.length) {
|
|
227
|
+
throw new Error(result.errors.map(e => e.message).join('; '));
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
UI API example (using the SDK's fetch):
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
import { getDataSDK } from '@salesforce/webapp-experimental/api';
|
|
235
|
+
|
|
236
|
+
async function fetchRecord(recordId: string) {
|
|
237
|
+
const data = await getDataSDK();
|
|
238
|
+
const response = await data.fetch!(`/services/data/v62.0/ui-api/records/${recordId}`);
|
|
239
|
+
|
|
240
|
+
if (!response.ok) {
|
|
241
|
+
throw new Error(`UI API failed: ${response.status}`);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return response.json();
|
|
245
|
+
}
|
|
249
246
|
```
|
|
250
247
|
|
|
251
248
|
## Einstein LLM Gateway (AI/Generative Features)
|
|
@@ -259,30 +256,35 @@ Einstein LLM Gateway provides AI and generative capabilities for your React appl
|
|
|
259
256
|
|
|
260
257
|
### Einstein LLM Gateway Pattern
|
|
261
258
|
|
|
262
|
-
```
|
|
263
|
-
|
|
259
|
+
```typescript
|
|
260
|
+
import { getDataSDK } from '@salesforce/webapp-experimental/api';
|
|
261
|
+
|
|
262
|
+
async function callEinsteinGenerations({ prompt, model = 'gpt-4', signal }: {
|
|
263
|
+
prompt: string;
|
|
264
|
+
model?: string;
|
|
265
|
+
signal?: AbortSignal;
|
|
266
|
+
}): Promise<string> {
|
|
264
267
|
const url = '/services/data/v62.0/einstein/llm/prompt/generations';
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
promptTextorId: prompt,
|
|
268
|
+
const sdk = await getDataSDK();
|
|
269
|
+
const resp = await sdk.fetch!(url, {
|
|
270
|
+
method: 'POST',
|
|
271
|
+
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
272
|
+
body: JSON.stringify({
|
|
273
|
+
additionalConfig: {
|
|
274
|
+
applicationName: 'PromptTemplateGenerationsInvocable',
|
|
275
|
+
model,
|
|
274
276
|
},
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
throw new Error(
|
|
283
|
-
error.message || `Einstein LLM request failed (${error.status})`
|
|
284
|
-
);
|
|
277
|
+
promptTextorId: prompt,
|
|
278
|
+
}),
|
|
279
|
+
signal,
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
if (!resp.ok) {
|
|
283
|
+
throw new Error(`Einstein LLM request failed (${resp.status})`);
|
|
285
284
|
}
|
|
285
|
+
|
|
286
|
+
const data = await resp.json();
|
|
287
|
+
return data?.generations?.[0]?.text || '';
|
|
286
288
|
}
|
|
287
289
|
```
|
|
288
290
|
|
|
@@ -324,9 +326,8 @@ async function safeFetch(recordId) {
|
|
|
324
326
|
|
|
325
327
|
### Authentication Error Handling (MANDATORY)
|
|
326
328
|
|
|
327
|
-
-
|
|
329
|
+
- The Data SDK handles 401/403 errors.
|
|
328
330
|
- When a 401 (Unauthorized) or 403 (Forbidden) response is received, trigger a page refresh with `window.location.reload()` to redirect to login.
|
|
329
|
-
- Always return `Promise.reject(error)` after handling authentication errors to maintain proper error flow.
|
|
330
331
|
|
|
331
332
|
### Notes
|
|
332
333
|
|
|
@@ -133,33 +133,22 @@ interface Account extends SalesforceRecord {
|
|
|
133
133
|
Name: { value: string };
|
|
134
134
|
Industry?: { value: string | null };
|
|
135
135
|
}
|
|
136
|
-
|
|
137
|
-
// Type API functions
|
|
138
|
-
async function fetchAccount(id: string): Promise<Account> {
|
|
139
|
-
const response = await axios.get<Account>(`/services/data/v62.0/ui-api/records/${id}`);
|
|
140
|
-
return response.data;
|
|
141
|
-
}
|
|
142
136
|
```
|
|
143
137
|
|
|
144
|
-
### GraphQL
|
|
145
|
-
|
|
146
|
-
interface GraphQLResponse<T> {
|
|
147
|
-
data: T;
|
|
148
|
-
errors?: Array<{ message: string; locations?: Array<{ line: number; column: number }> }>;
|
|
149
|
-
}
|
|
138
|
+
### GraphQL via DataSDK
|
|
139
|
+
Use `getDataSDK()` from `@salesforce/webapp-experimental/api` for all GraphQL operations. The SDK handles authentication and CSRF token management:
|
|
150
140
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
query,
|
|
154
|
-
variables,
|
|
155
|
-
});
|
|
141
|
+
```typescript
|
|
142
|
+
import { getDataSDK } from '@salesforce/webapp-experimental/api';
|
|
156
143
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
144
|
+
const data = await getDataSDK();
|
|
145
|
+
const response = await data.graphql?.<GetAccountsQuery>(QUERY, variables);
|
|
160
146
|
|
|
161
|
-
|
|
147
|
+
if (response?.errors?.length) {
|
|
148
|
+
throw new Error(response.errors.map(e => e.message).join('; '));
|
|
162
149
|
}
|
|
150
|
+
|
|
151
|
+
const accounts = response?.data;
|
|
163
152
|
```
|
|
164
153
|
|
|
165
154
|
## Error Handling Types
|
package/dist/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [1.56.1](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.56.0...v1.56.1) (2026-02-25)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @salesforce/webapp-template-base-sfdx-project-experimental
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
6
14
|
# [1.56.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.55.0...v1.56.0) (2026-02-25)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @salesforce/webapp-template-base-sfdx-project-experimental
|
|
@@ -6069,19 +6069,19 @@
|
|
|
6069
6069
|
}
|
|
6070
6070
|
},
|
|
6071
6071
|
"node_modules/@salesforce/sdk-core": {
|
|
6072
|
-
"version": "1.
|
|
6073
|
-
"resolved": "https://registry.npmjs.org/@salesforce/sdk-core/-/sdk-core-1.
|
|
6074
|
-
"integrity": "sha512-
|
|
6072
|
+
"version": "1.56.0",
|
|
6073
|
+
"resolved": "https://registry.npmjs.org/@salesforce/sdk-core/-/sdk-core-1.56.0.tgz",
|
|
6074
|
+
"integrity": "sha512-53S8tkgkyTCc7LMZjJSOekyR1EBkqcYkORRyfl2TH4gVYpeUjjoeEE7ilVV1b9oMeV5x7Bn0BuHuAs3vLGJkrw==",
|
|
6075
6075
|
"license": "SEE LICENSE IN LICENSE.txt"
|
|
6076
6076
|
},
|
|
6077
6077
|
"node_modules/@salesforce/sdk-data": {
|
|
6078
|
-
"version": "1.
|
|
6079
|
-
"resolved": "https://registry.npmjs.org/@salesforce/sdk-data/-/sdk-data-1.
|
|
6080
|
-
"integrity": "sha512-
|
|
6078
|
+
"version": "1.56.0",
|
|
6079
|
+
"resolved": "https://registry.npmjs.org/@salesforce/sdk-data/-/sdk-data-1.56.0.tgz",
|
|
6080
|
+
"integrity": "sha512-w6CTntTspVcILVGSBM8TQ61YA70vB+dU0cH+p2YLjI8ZiP1ZWdjGN/pDy5Dle9+4Gxat0shcXgnVPBmX3Xlapg==",
|
|
6081
6081
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6082
6082
|
"dependencies": {
|
|
6083
6083
|
"@conduit-client/salesforce-lightning-service-worker": "^3.7.0",
|
|
6084
|
-
"@salesforce/sdk-core": "^1.
|
|
6084
|
+
"@salesforce/sdk-core": "^1.56.0"
|
|
6085
6085
|
}
|
|
6086
6086
|
},
|
|
6087
6087
|
"node_modules/@salesforce/ts-types": {
|
|
@@ -6094,15 +6094,15 @@
|
|
|
6094
6094
|
}
|
|
6095
6095
|
},
|
|
6096
6096
|
"node_modules/@salesforce/vite-plugin-webapp-experimental": {
|
|
6097
|
-
"version": "1.
|
|
6098
|
-
"resolved": "https://registry.npmjs.org/@salesforce/vite-plugin-webapp-experimental/-/vite-plugin-webapp-experimental-1.
|
|
6099
|
-
"integrity": "sha512-
|
|
6097
|
+
"version": "1.56.0",
|
|
6098
|
+
"resolved": "https://registry.npmjs.org/@salesforce/vite-plugin-webapp-experimental/-/vite-plugin-webapp-experimental-1.56.0.tgz",
|
|
6099
|
+
"integrity": "sha512-lD6US3e/bwooMW4EmLoGhbnQzQhPXWUC9WG85yiEiLPyHyfHi3D4b1QUrlVHxsxlvYC3YesVx0boDfTVl/VICw==",
|
|
6100
6100
|
"dev": true,
|
|
6101
6101
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6102
6102
|
"dependencies": {
|
|
6103
6103
|
"@babel/core": "^7.28.4",
|
|
6104
6104
|
"@babel/helper-plugin-utils": "^7.28.3",
|
|
6105
|
-
"@salesforce/webapp-experimental": "^1.
|
|
6105
|
+
"@salesforce/webapp-experimental": "^1.56.0"
|
|
6106
6106
|
},
|
|
6107
6107
|
"engines": {
|
|
6108
6108
|
"node": ">=20.0.0"
|
|
@@ -6112,13 +6112,13 @@
|
|
|
6112
6112
|
}
|
|
6113
6113
|
},
|
|
6114
6114
|
"node_modules/@salesforce/webapp-experimental": {
|
|
6115
|
-
"version": "1.
|
|
6116
|
-
"resolved": "https://registry.npmjs.org/@salesforce/webapp-experimental/-/webapp-experimental-1.
|
|
6117
|
-
"integrity": "sha512-
|
|
6115
|
+
"version": "1.56.0",
|
|
6116
|
+
"resolved": "https://registry.npmjs.org/@salesforce/webapp-experimental/-/webapp-experimental-1.56.0.tgz",
|
|
6117
|
+
"integrity": "sha512-i4yG9URMxZi8EsY2QV0OHsSPT0/Bkv/+702D0OpcQxC+fy0wLSSMUzaTh1vW4txikbZf26tToxN/qyp1NY0zNA==",
|
|
6118
6118
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6119
6119
|
"dependencies": {
|
|
6120
6120
|
"@salesforce/core": "^8.23.4",
|
|
6121
|
-
"@salesforce/sdk-data": "^1.
|
|
6121
|
+
"@salesforce/sdk-data": "^1.56.0",
|
|
6122
6122
|
"axios": "^1.7.7",
|
|
6123
6123
|
"micromatch": "^4.0.8",
|
|
6124
6124
|
"path-to-regexp": "^8.3.0"
|
package/dist/package.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/webapp-template-feature-react-chart-experimental",
|
|
3
|
-
"version": "1.56.
|
|
3
|
+
"version": "1.56.1",
|
|
4
4
|
"description": "Chart feature with analytics chart components, agent skills, and rules (Recharts)",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"author": "",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"clean": "rm -rf dist"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@salesforce/webapp-experimental": "^1.56.
|
|
30
|
+
"@salesforce/webapp-experimental": "^1.56.1",
|
|
31
31
|
"@types/react": "^19.2.7",
|
|
32
32
|
"@types/react-dom": "^19.2.3",
|
|
33
33
|
"react-dom": "^19.2.1",
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "c900d757a03250a770c5312dbef2013de91e7bb3"
|
|
55
55
|
}
|