@salesforce/afv-skills 1.3.0 → 1.4.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.
- package/package.json +3 -3
- package/skills/building-webapp-data-visualization/SKILL.md +1 -1
- package/skills/building-webapp-react-components/SKILL.md +1 -1
- package/skills/configuring-webapp-csp-trusted-sites/SKILL.md +1 -1
- package/skills/configuring-webapp-metadata/SKILL.md +2 -2
- package/skills/creating-webapp/SKILL.md +2 -3
- package/skills/deploying-webapp-to-salesforce/SKILL.md +2 -5
- package/skills/generating-custom-application/SKILL.md +1 -1
- package/skills/generating-custom-field/SKILL.md +1 -1
- package/skills/generating-custom-lightning-type/SKILL.md +1 -1
- package/skills/generating-custom-object/SKILL.md +1 -1
- package/skills/generating-custom-tab/SKILL.md +1 -1
- package/skills/generating-experience-lwr-site/SKILL.md +1 -1
- package/skills/generating-experience-react-site/SKILL.md +1 -1
- package/skills/generating-flexipage/SKILL.md +1 -1
- package/skills/generating-flow/SKILL.md +1 -1
- package/skills/generating-fragment/SKILL.md +1 -1
- package/skills/generating-list-view/SKILL.md +1 -1
- package/skills/generating-permission-set/SKILL.md +1 -1
- package/skills/generating-validation-rule/SKILL.md +1 -1
- package/skills/implementing-webapp-file-upload/SKILL.md +1 -1
- package/skills/installing-webapp-features/SKILL.md +1 -1
- package/skills/managing-webapp-agentforce-conversation-client/SKILL.md +1 -1
- package/skills/trigger-refactor-pipeline/SKILL.md +1 -1
- package/skills/using-webapp-salesforce-data/SKILL.md +363 -0
- package/skills/using-webapp-salesforce-data/graphql-search.sh +139 -0
- package/skills/accessing-webapp-data/SKILL.md +0 -178
- package/skills/exploring-webapp-graphql-schema/SKILL.md +0 -149
- package/skills/fetching-webapp-rest-api/SKILL.md +0 -167
- package/skills/generating-webapp-graphql-mutation-query/SKILL.md +0 -258
- package/skills/generating-webapp-graphql-read-query/SKILL.md +0 -253
- package/skills/using-webapp-graphql/SKILL.md +0 -324
- package/skills/using-webapp-graphql/shared-schema.graphqls +0 -1150
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# graphql-search.sh — Look up one or more Salesforce entities in schema.graphql.
|
|
3
|
+
#
|
|
4
|
+
# Run from the SFDX project root (where schema.graphql lives):
|
|
5
|
+
# bash .a4drules/skills/using-salesforce-data/graphql-search.sh Account
|
|
6
|
+
# bash .a4drules/skills/using-salesforce-data/graphql-search.sh Account Contact Opportunity
|
|
7
|
+
#
|
|
8
|
+
# Pass a custom schema path with -s / --schema:
|
|
9
|
+
# bash .a4drules/skills/using-salesforce-data/graphql-search.sh -s /path/to/schema.graphql Account
|
|
10
|
+
# bash .a4drules/skills/using-salesforce-data/graphql-search.sh --schema ./other/schema.graphql Account Contact
|
|
11
|
+
#
|
|
12
|
+
# Output sections per entity:
|
|
13
|
+
# 1. Type definition — all fields and relationships
|
|
14
|
+
# 2. Filter options — <Entity>_Filter input (for `where:`)
|
|
15
|
+
# 3. Sort options — <Entity>_OrderBy input (for `orderBy:`)
|
|
16
|
+
# 4. Create input — <Entity>CreateRepresentation (for create mutations)
|
|
17
|
+
# 5. Update input — <Entity>UpdateRepresentation (for update mutations)
|
|
18
|
+
|
|
19
|
+
SCHEMA="./schema.graphql"
|
|
20
|
+
|
|
21
|
+
# ── Argument parsing ─────────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
while [[ $# -gt 0 ]]; do
|
|
24
|
+
case "$1" in
|
|
25
|
+
-s|--schema)
|
|
26
|
+
if [[ -z "${2-}" || "$2" == -* ]]; then
|
|
27
|
+
echo "ERROR: --schema requires a file path argument"
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
SCHEMA="$2"
|
|
31
|
+
shift 2
|
|
32
|
+
;;
|
|
33
|
+
--)
|
|
34
|
+
shift
|
|
35
|
+
break
|
|
36
|
+
;;
|
|
37
|
+
-*)
|
|
38
|
+
echo "ERROR: Unknown option: $1"
|
|
39
|
+
echo "Usage: bash $0 [-s <schema-path>] <EntityName> [EntityName2 ...]"
|
|
40
|
+
exit 1
|
|
41
|
+
;;
|
|
42
|
+
*)
|
|
43
|
+
break
|
|
44
|
+
;;
|
|
45
|
+
esac
|
|
46
|
+
done
|
|
47
|
+
|
|
48
|
+
if [ $# -eq 0 ]; then
|
|
49
|
+
echo "Usage: bash $0 [-s <schema-path>] <EntityName> [EntityName2 ...]"
|
|
50
|
+
echo "Example: bash $0 Account"
|
|
51
|
+
echo "Example: bash $0 Account Contact Opportunity"
|
|
52
|
+
echo "Example: bash $0 --schema /path/to/schema.graphql Account"
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
if [ ! -f "$SCHEMA" ]; then
|
|
57
|
+
echo "ERROR: schema.graphql not found at $SCHEMA"
|
|
58
|
+
echo " Make sure you are running from the SFDX project root, or pass the path explicitly:"
|
|
59
|
+
echo " bash $0 --schema <path/to/schema.graphql> <EntityName>"
|
|
60
|
+
echo " If the file is missing entirely, generate it from the webapp dir:"
|
|
61
|
+
echo " cd force-app/main/default/webapplications/<app-name> && npm run graphql:schema"
|
|
62
|
+
exit 1
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# ── Helper: extract lines from a grep match through the closing brace ────────
|
|
66
|
+
# Prints up to MAX_LINES lines after (and including) the first match of PATTERN.
|
|
67
|
+
# Uses a generous line count — blocks are always closed by a "}" line.
|
|
68
|
+
|
|
69
|
+
extract_block() {
|
|
70
|
+
local label="$1"
|
|
71
|
+
local pattern="$2"
|
|
72
|
+
local max_lines="$3"
|
|
73
|
+
|
|
74
|
+
local match
|
|
75
|
+
match=$(grep -nE "$pattern" "$SCHEMA" | head -1)
|
|
76
|
+
|
|
77
|
+
if [ -z "$match" ]; then
|
|
78
|
+
echo " (not found: $pattern)"
|
|
79
|
+
return
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
echo "### $label"
|
|
83
|
+
grep -E "$pattern" "$SCHEMA" -A "$max_lines" | \
|
|
84
|
+
awk '/^\}$/{print; exit} {print}' | \
|
|
85
|
+
head -n "$max_lines"
|
|
86
|
+
echo ""
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
# ── Main loop ────────────────────────────────────────────────────────────────
|
|
90
|
+
|
|
91
|
+
for ENTITY in "$@"; do
|
|
92
|
+
echo ""
|
|
93
|
+
echo "======================================================================"
|
|
94
|
+
echo " SCHEMA LOOKUP: $ENTITY"
|
|
95
|
+
echo "======================================================================"
|
|
96
|
+
echo ""
|
|
97
|
+
|
|
98
|
+
# 1. Type definition — all fields and relationships
|
|
99
|
+
extract_block \
|
|
100
|
+
"Type definition — fields and relationships" \
|
|
101
|
+
"^type ${ENTITY} implements Record" \
|
|
102
|
+
200
|
|
103
|
+
|
|
104
|
+
# 2. Filter input — used in `where:` arguments
|
|
105
|
+
extract_block \
|
|
106
|
+
"Filter options — use in where: { ... }" \
|
|
107
|
+
"^input ${ENTITY}_Filter" \
|
|
108
|
+
100
|
|
109
|
+
|
|
110
|
+
# 3. OrderBy input — used in `orderBy:` arguments
|
|
111
|
+
extract_block \
|
|
112
|
+
"Sort options — use in orderBy: { ... }" \
|
|
113
|
+
"^input ${ENTITY}_OrderBy" \
|
|
114
|
+
60
|
|
115
|
+
|
|
116
|
+
# 4. Create mutation inputs
|
|
117
|
+
extract_block \
|
|
118
|
+
"Create mutation wrapper — ${ENTITY}CreateInput" \
|
|
119
|
+
"^input ${ENTITY}CreateInput" \
|
|
120
|
+
10
|
|
121
|
+
|
|
122
|
+
extract_block \
|
|
123
|
+
"Create mutation fields — ${ENTITY}CreateRepresentation" \
|
|
124
|
+
"^input ${ENTITY}CreateRepresentation" \
|
|
125
|
+
100
|
|
126
|
+
|
|
127
|
+
# 5. Update mutation inputs
|
|
128
|
+
extract_block \
|
|
129
|
+
"Update mutation wrapper — ${ENTITY}UpdateInput" \
|
|
130
|
+
"^input ${ENTITY}UpdateInput" \
|
|
131
|
+
10
|
|
132
|
+
|
|
133
|
+
extract_block \
|
|
134
|
+
"Update mutation fields — ${ENTITY}UpdateRepresentation" \
|
|
135
|
+
"^input ${ENTITY}UpdateRepresentation" \
|
|
136
|
+
100
|
|
137
|
+
|
|
138
|
+
echo ""
|
|
139
|
+
done
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: accessing-webapp-data
|
|
3
|
-
description: Salesforce data access patterns. Use when adding or modifying any code that fetches data from Salesforce (records, Chatter, Connect API, etc.).
|
|
4
|
-
paths:
|
|
5
|
-
- "**/*.ts"
|
|
6
|
-
- "**/*.tsx"
|
|
7
|
-
- "**/*.graphql"
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# Salesforce Data Access
|
|
11
|
-
|
|
12
|
-
Guidance for accessing Salesforce data from web apps. **All Salesforce data fetches MUST use the Data SDK** (`@salesforce/sdk-data`). The SDK provides authentication, CSRF handling, and correct base URL resolution — direct `fetch` or `axios` calls bypass these and are not allowed.
|
|
13
|
-
|
|
14
|
-
## Mandatory: Use the Data SDK
|
|
15
|
-
|
|
16
|
-
> **Every Salesforce data fetch must go through the Data SDK.** Obtain it via `createDataSDK()`, then use `sdk.graphql?.()` or `sdk.fetch?.()`. Never call `fetch()` or `axios` directly for Salesforce endpoints.
|
|
17
|
-
|
|
18
|
-
## Optional Chaining and Graceful Handling
|
|
19
|
-
|
|
20
|
-
**Always use optional chaining** when calling `sdk.graphql` or `sdk.fetch` — these methods may be undefined in some surfaces (e.g., Salesforce ACC, MCP Apps). Handle the case where they are not available gracefully:
|
|
21
|
-
|
|
22
|
-
```typescript
|
|
23
|
-
const sdk = await createDataSDK();
|
|
24
|
-
|
|
25
|
-
// ✅ Use optional chaining
|
|
26
|
-
const response = await sdk.graphql?.(query);
|
|
27
|
-
|
|
28
|
-
// ✅ Check before using fetch
|
|
29
|
-
if (!sdk.fetch) {
|
|
30
|
-
throw new Error("Data SDK fetch is not available in this context");
|
|
31
|
-
}
|
|
32
|
-
const res = await sdk.fetch(url);
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
For GraphQL, if `sdk.graphql` is undefined, the call returns `undefined` — handle that in your logic (e.g., throw a clear error or return a fallback). For `sdk.fetch`, check availability before calling when the operation is required.
|
|
36
|
-
|
|
37
|
-
## Preference: GraphQL First
|
|
38
|
-
|
|
39
|
-
**GraphQL is the preferred method** for querying and mutating Salesforce records. Use it when:
|
|
40
|
-
|
|
41
|
-
- Querying records (Account, Contact, Opportunity, custom objects)
|
|
42
|
-
- Creating, updating, or deleting records (when GraphQL supports the operation)
|
|
43
|
-
- Fetching related data, filters, sorting, pagination
|
|
44
|
-
|
|
45
|
-
**Use `sdk.fetch` only when GraphQL is not sufficient.** For REST API usage, invoke the `fetching-rest-api` skill, which documents:
|
|
46
|
-
|
|
47
|
-
- Chatter API (e.g., `/services/data/v65.0/chatter/users/me`)
|
|
48
|
-
- Connect REST API (e.g., `/services/data/v65.0/connect/file/upload/config`)
|
|
49
|
-
- Apex REST (e.g., `/services/apexrest/auth/login`)
|
|
50
|
-
- UI API REST (e.g., `/services/data/v65.0/ui-api/records/{recordId}`)
|
|
51
|
-
- Einstein LLM Gateway
|
|
52
|
-
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
## Getting the SDK
|
|
56
|
-
|
|
57
|
-
```typescript
|
|
58
|
-
import { createDataSDK } from "@salesforce/sdk-data";
|
|
59
|
-
|
|
60
|
-
const sdk = await createDataSDK();
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
## Example 1: GraphQL (Preferred)
|
|
66
|
-
|
|
67
|
-
For record queries and mutations, use GraphQL via the Data SDK. Invoke the `using-graphql` skill for the full workflow (schema exploration, query authoring, codegen, lint validate).
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
import { createDataSDK, gql } from "@salesforce/sdk-data";
|
|
71
|
-
import type { GetAccountsQuery } from "../graphql-operations-types";
|
|
72
|
-
|
|
73
|
-
const GET_ACCOUNTS = gql`
|
|
74
|
-
query GetAccounts {
|
|
75
|
-
uiapi {
|
|
76
|
-
query {
|
|
77
|
-
Account(first: 10) {
|
|
78
|
-
edges {
|
|
79
|
-
node {
|
|
80
|
-
Id
|
|
81
|
-
Name { value }
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
`;
|
|
89
|
-
|
|
90
|
-
export async function getAccounts() {
|
|
91
|
-
const sdk = await createDataSDK();
|
|
92
|
-
const response = await sdk.graphql?.<GetAccountsQuery>(GET_ACCOUNTS);
|
|
93
|
-
|
|
94
|
-
if (response?.errors?.length) {
|
|
95
|
-
throw new Error(response.errors.map((e) => e.message).join("; "));
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return response?.data?.uiapi?.query?.Account?.edges?.map((e) => e?.node) ?? [];
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
---
|
|
103
|
-
|
|
104
|
-
## Example 2: Fetch (When GraphQL Is Not Sufficient)
|
|
105
|
-
|
|
106
|
-
For REST endpoints that have no GraphQL equivalent, use `sdk.fetch`. **Invoke the `fetching-rest-api` skill** for full documentation of Chatter, Connect REST, Apex REST, UI API REST, and Einstein LLM endpoints.
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
import { createDataSDK } from "@salesforce/sdk-data";
|
|
110
|
-
|
|
111
|
-
declare const __SF_API_VERSION__: string;
|
|
112
|
-
const API_VERSION = typeof __SF_API_VERSION__ !== "undefined" ? __SF_API_VERSION__ : "65.0";
|
|
113
|
-
|
|
114
|
-
export async function getCurrentUser() {
|
|
115
|
-
const sdk = await createDataSDK();
|
|
116
|
-
const response = await sdk.fetch?.(`/services/data/v${API_VERSION}/chatter/users/me`);
|
|
117
|
-
|
|
118
|
-
if (!response?.ok) throw new Error(`HTTP ${response?.status}`);
|
|
119
|
-
const data = await response.json();
|
|
120
|
-
return { id: data.id, name: data.name };
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
## Anti-Patterns (Forbidden)
|
|
127
|
-
|
|
128
|
-
### Direct fetch to Salesforce
|
|
129
|
-
|
|
130
|
-
```typescript
|
|
131
|
-
// ❌ FORBIDDEN — bypasses Data SDK auth and CSRF
|
|
132
|
-
const res = await fetch("/services/data/v65.0/chatter/users/me");
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### Direct axios to Salesforce
|
|
136
|
-
|
|
137
|
-
```typescript
|
|
138
|
-
// ❌ FORBIDDEN — bypasses Data SDK
|
|
139
|
-
const res = await axios.get("/services/data/v65.0/chatter/users/me");
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### Correct approach
|
|
143
|
-
|
|
144
|
-
```typescript
|
|
145
|
-
// ✅ CORRECT — use Data SDK
|
|
146
|
-
const sdk = await createDataSDK();
|
|
147
|
-
const res = await sdk.fetch?.("/services/data/v65.0/chatter/users/me");
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
## Clarifying Vague Data Requests
|
|
153
|
-
|
|
154
|
-
When a user asks about data and the request is vague, **clarify before implementing**. Ask which of the following they want:
|
|
155
|
-
|
|
156
|
-
- **Application code** — Add or modify code in a specific web app so the app performs the data interaction at runtime (e.g., GraphQL query in the React app)
|
|
157
|
-
- **Local SF CLI** — Run Salesforce CLI commands locally (e.g., `sf data query`, `sf data import tree`) to interact with the org from the terminal
|
|
158
|
-
- **Local example data** — Update or add local fixture/example data files (e.g., JSON in `data/`) for development or testing
|
|
159
|
-
- **Other** — Data export, report generation, setup script, etc.
|
|
160
|
-
|
|
161
|
-
Do not assume. A request like "fetch accounts" could mean: (1) add a GraphQL query to the app, (2) run `sf data query` in the terminal, or (3) update sample data files. Confirm the intent before proceeding.
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
## Decision Flow
|
|
166
|
-
|
|
167
|
-
1. **Need to query or mutate Salesforce records?** → Use GraphQL via the Data SDK. Invoke the `using-graphql` skill.
|
|
168
|
-
2. **Need Chatter, Connect REST, Apex REST, UI API REST, or Einstein LLM?** → Use `sdk.fetch`. Invoke the `fetching-rest-api` skill.
|
|
169
|
-
3. **Never** use `fetch`, `axios`, or similar directly for Salesforce API calls.
|
|
170
|
-
|
|
171
|
-
---
|
|
172
|
-
|
|
173
|
-
## Reference
|
|
174
|
-
|
|
175
|
-
- GraphQL workflow: invoke the `using-graphql` skill (`.a4drules/skills/using-graphql/`)
|
|
176
|
-
- REST API via fetch: invoke the `fetching-rest-api` skill (`.a4drules/skills/fetching-rest-api/`)
|
|
177
|
-
- Data SDK package: `@salesforce/sdk-data` (`createDataSDK`, `gql`, `NodeOfConnection`)
|
|
178
|
-
- `createRecord` for UI API record creation: `@salesforce/webapp-experimental/api` (uses Data SDK internally)
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: exploring-webapp-graphql-schema
|
|
3
|
-
description: Explore the Salesforce GraphQL schema via grep-only lookups. Use before generating any GraphQL query — schema exploration must complete first.
|
|
4
|
-
paths:
|
|
5
|
-
- "**/*.ts"
|
|
6
|
-
- "**/*.tsx"
|
|
7
|
-
- "**/*.graphql"
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# Salesforce GraphQL Schema Exploration
|
|
11
|
-
|
|
12
|
-
Guidance for AI agents working with the Salesforce GraphQL API schema. **GREP ONLY** — the schema file is very large (~265,000+ lines). All lookups MUST use grep; do NOT open, read, stream, or parse the file.
|
|
13
|
-
|
|
14
|
-
## Deployment Prerequisites
|
|
15
|
-
|
|
16
|
-
The schema reflects the **current org state**. Custom objects and fields appear only after metadata is deployed.
|
|
17
|
-
|
|
18
|
-
- **Before** running `npm run graphql:schema`: Deploy all metadata (objects, permission sets, layouts) and assign the permission set to the target user. Invoke the `deploying-to-salesforce` skill for the full sequence.
|
|
19
|
-
- **After** any metadata deployment: Re-run `npm run graphql:schema` and `npm run graphql:codegen` so types and queries stay in sync.
|
|
20
|
-
|
|
21
|
-
## Schema File Location
|
|
22
|
-
|
|
23
|
-
**Location:** `schema.graphql` at the **SFDX project root** (NOT inside the webapp dir). All grep commands **must be run from the project root** where `schema.graphql` lives.
|
|
24
|
-
|
|
25
|
-
> ⚠️ **Important (Access Policy - GREP ONLY)**: Do NOT open, view, stream, paginate, or parse the schema with any tool other than grep. All lookups MUST be done via grep using anchored patterns with minimal context as defined below.
|
|
26
|
-
|
|
27
|
-
If the file is not present, generate it by running (from the **webapp dir**, not the project root):
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
# Run from webapp dir (force-app/main/default/webapplications/<app-name>/)
|
|
31
|
-
npm run graphql:schema
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
**BEFORE generating any GraphQL query, you MUST:**
|
|
35
|
-
|
|
36
|
-
1. **Check if schema exists**: Look for `schema.graphql` in the **SFDX project root**
|
|
37
|
-
2. **If schema is missing**:
|
|
38
|
-
- `cd` to the **webapp dir** and run `npm run graphql:schema` to download it
|
|
39
|
-
- Wait for the command to complete successfully
|
|
40
|
-
- Then proceed with grep-only lookups as defined below.
|
|
41
|
-
3. **If schema exists**: Proceed with targeted searches as described below
|
|
42
|
-
|
|
43
|
-
> ⚠️ **DO NOT** generate GraphQL queries without first having access to the schema. Standard field assumptions may not match the target org's configuration.
|
|
44
|
-
|
|
45
|
-
## Schema Structure Overview
|
|
46
|
-
|
|
47
|
-
Main entry points: `Query { uiapi }` for reads; `Mutation { uiapi(input: ...) }` for creates/updates/deletes. Record queries use `uiapi.query.<ObjectName>`.
|
|
48
|
-
|
|
49
|
-
## Allowed Lookups (grep-only)
|
|
50
|
-
|
|
51
|
-
Use ONLY these grep commands to locate specific definitions in schema.graphql. Do not use editors (VS Code/vim/nano), cat/less/more/head/tail, or programmatic parsers (node/python/awk/sed/jq).
|
|
52
|
-
|
|
53
|
-
- Always include:
|
|
54
|
-
- `-n` (line numbers) and `-E` (extended regex)
|
|
55
|
-
- Anchors (`^`) and word boundaries (`\b`)
|
|
56
|
-
- Minimal context with `-A N` (prefer the smallest N that surfaces the needed lines)
|
|
57
|
-
|
|
58
|
-
### 1. Find Available Fields for a Record Type
|
|
59
|
-
|
|
60
|
-
Search for `type <ObjectName> implements Record` to find all queryable fields:
|
|
61
|
-
|
|
62
|
-
```bash
|
|
63
|
-
# Example: Find Account fields (anchored, minimal context)
|
|
64
|
-
grep -nE '^type[[:space:]]+Account[[:space:]]+implements[[:space:]]+Record\b' ./schema.graphql -A 60
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### 2. Find Filter Options for a Record Type
|
|
68
|
-
|
|
69
|
-
Search for `input <ObjectName>_Filter` to find filterable fields and operators:
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
# Example: Find Account filter options (anchored)
|
|
73
|
-
grep -nE '^input[[:space:]]+Account_Filter\b' ./schema.graphql -A 40
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### 3. Find OrderBy Options
|
|
77
|
-
|
|
78
|
-
Search for `input <ObjectName>_OrderBy` for sorting options:
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
# Example: Find Account ordering options (anchored)
|
|
82
|
-
grep -nE '^input[[:space:]]+Account_OrderBy\b' ./schema.graphql -A 30
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### 4. Find Mutation Operations
|
|
86
|
-
|
|
87
|
-
Search for operations in `UIAPIMutations`:
|
|
88
|
-
|
|
89
|
-
```bash
|
|
90
|
-
# Example: Find Account mutations (extended regex)
|
|
91
|
-
grep -nE 'Account.*(Create|Update|Delete)' ./schema.graphql
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### 5. Find Input Types for Mutations
|
|
95
|
-
|
|
96
|
-
Search for `input <ObjectName>CreateInput` or `input <ObjectName>UpdateInput`:
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
# Example: Find Account create input (anchored)
|
|
100
|
-
grep -nE '^input[[:space:]]+AccountCreateInput\b' ./schema.graphql -A 30
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
## Agent Workflow for Building Queries (grep-only)
|
|
104
|
-
|
|
105
|
-
**Pre-requisites (MANDATORY):**
|
|
106
|
-
|
|
107
|
-
- [ ] Verified `schema.graphql` exists in the **SFDX project root**
|
|
108
|
-
- [ ] If missing, ran `npm run graphql:schema` from the **webapp dir** and waited for completion
|
|
109
|
-
- [ ] Confirmed connection to correct Salesforce org (if downloading fresh schema)
|
|
110
|
-
|
|
111
|
-
**Workflow Steps:**
|
|
112
|
-
|
|
113
|
-
1. **Identify the target object** (e.g., Account, Contact, Opportunity)
|
|
114
|
-
2. **Run the "Find Available Fields" grep command** for your object (copy only the field names visible in the grep output; do not open the file)
|
|
115
|
-
3. **Run the "Find Filter Options" grep command** (`<Object>_Filter`) to understand filtering options
|
|
116
|
-
4. **Run the "Find OrderBy Options" grep command** (`<Object>_OrderBy`) for sorting capabilities
|
|
117
|
-
5. **Build the query** following the patterns in the `generating-graphql-read-query` or `generating-graphql-mutation-query` skill using only values returned by grep
|
|
118
|
-
6. **Validate field names** using grep matches (case-sensitive). Do not open or parse the file beyond grep.
|
|
119
|
-
|
|
120
|
-
## Tips for Agents
|
|
121
|
-
|
|
122
|
-
- **Always verify field names** by running the specific grep commands; do not open the schema file
|
|
123
|
-
- **Use grep with anchors and minimal -A context** to explore the schema efficiently—never read or stream the file
|
|
124
|
-
- **Check relationships** by looking for `parentRelationship` and `childRelationship` comments in type definitions
|
|
125
|
-
- **Look for Connection types** (e.g., `AccountConnection`) via grep to understand pagination structure
|
|
126
|
-
- **Custom objects** end with `__c` (e.g., `CustomObject__c`)
|
|
127
|
-
- **Custom fields** also end with `__c` (e.g., `Custom_Field__c`)
|
|
128
|
-
|
|
129
|
-
## Forbidden Operations
|
|
130
|
-
|
|
131
|
-
To prevent accidental large reads, the following are prohibited for schema.graphql:
|
|
132
|
-
|
|
133
|
-
- Opening in any editor (VS Code, vim, nano)
|
|
134
|
-
- Using cat, less, more, head, or tail
|
|
135
|
-
- Programmatic parsing (node, python, awk, sed, jq)
|
|
136
|
-
- Streaming or paginating through large portions of the file
|
|
137
|
-
|
|
138
|
-
If any of the above occurs, stop and replace the action with one of the Allowed Lookups (grep-only).
|
|
139
|
-
|
|
140
|
-
## Output Minimization
|
|
141
|
-
|
|
142
|
-
- Prefer precise, anchored patterns with word boundaries
|
|
143
|
-
- Use the smallest `-A` context that surfaces required lines
|
|
144
|
-
- If results are noisy, refine the regex rather than increasing context
|
|
145
|
-
|
|
146
|
-
## Related Skills
|
|
147
|
-
|
|
148
|
-
- For generating read queries, invoke the `generating-graphql-read-query` skill
|
|
149
|
-
- For generating mutation queries, invoke the `generating-graphql-mutation-query` skill
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: fetching-webapp-rest-api
|
|
3
|
-
description: REST API usage via the Data SDK fetch method. Use when implementing Chatter, Connect REST, Apex REST, UI API REST, or Einstein LLM calls — only when GraphQL is not sufficient.
|
|
4
|
-
paths:
|
|
5
|
-
- "**/*.ts"
|
|
6
|
-
- "**/*.tsx"
|
|
7
|
-
- "**/*.graphql"
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# Salesforce REST API via Data SDK Fetch
|
|
11
|
-
|
|
12
|
-
Use `sdk.fetch` from the Data SDK when GraphQL is not sufficient. The SDK applies authentication, CSRF handling, and base URL resolution. **Always use optional chaining** (`sdk.fetch?.()`) and handle the case where `fetch` is not available.
|
|
13
|
-
|
|
14
|
-
Invoke this skill when you need to call Chatter, Connect REST, Apex REST, UI API REST, or Einstein LLM endpoints.
|
|
15
|
-
|
|
16
|
-
## API Version
|
|
17
|
-
|
|
18
|
-
Use the project's API version. It is typically injected as `__SF_API_VERSION__`; fallback to `"65.0"`:
|
|
19
|
-
|
|
20
|
-
```typescript
|
|
21
|
-
declare const __SF_API_VERSION__: string;
|
|
22
|
-
const API_VERSION = typeof __SF_API_VERSION__ !== "undefined" ? __SF_API_VERSION__ : "65.0";
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Base Path
|
|
26
|
-
|
|
27
|
-
URLs are relative to the Salesforce API base. The SDK prepends the correct base path. Use paths starting with `/services/...`.
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## Chatter API
|
|
32
|
-
|
|
33
|
-
User and collaboration data. No GraphQL equivalent.
|
|
34
|
-
|
|
35
|
-
| Endpoint | Method | Purpose |
|
|
36
|
-
| -------- | ------ | ------- |
|
|
37
|
-
| `/services/data/v{version}/chatter/users/me` | GET | Current user (id, name, email, username) |
|
|
38
|
-
|
|
39
|
-
```typescript
|
|
40
|
-
const sdk = await createDataSDK();
|
|
41
|
-
const response = await sdk.fetch?.(`/services/data/v${API_VERSION}/chatter/users/me`);
|
|
42
|
-
|
|
43
|
-
if (!response?.ok) throw new Error(`HTTP ${response?.status}`);
|
|
44
|
-
const data = await response.json();
|
|
45
|
-
return { id: data.id, name: data.name };
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
---
|
|
49
|
-
|
|
50
|
-
## Connect REST API
|
|
51
|
-
|
|
52
|
-
File and content operations.
|
|
53
|
-
|
|
54
|
-
| Endpoint | Method | Purpose |
|
|
55
|
-
| -------- | ------ | ------- |
|
|
56
|
-
| `/services/data/v{version}/connect/file/upload/config` | GET | Upload config (token, uploadUrl) for file uploads |
|
|
57
|
-
|
|
58
|
-
```typescript
|
|
59
|
-
const sdk = await createDataSDK();
|
|
60
|
-
const configRes = await sdk.fetch?.(`/services/data/v${API_VERSION}/connect/file/upload/config`, {
|
|
61
|
-
method: "GET",
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
if (!configRes?.ok) throw new Error(`Failed to get upload config: ${configRes?.status}`);
|
|
65
|
-
const config = await configRes.json();
|
|
66
|
-
const { token, uploadUrl } = config;
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
---
|
|
70
|
-
|
|
71
|
-
## Apex REST
|
|
72
|
-
|
|
73
|
-
Custom Apex REST resources. Requires corresponding Apex classes in the org. CSRF protection is applied automatically for `services/apexrest` URLs.
|
|
74
|
-
|
|
75
|
-
| Endpoint | Method | Purpose |
|
|
76
|
-
| -------- | ------ | ------- |
|
|
77
|
-
| `/services/apexrest/auth/login` | POST | User login |
|
|
78
|
-
| `/services/apexrest/auth/register` | POST | User registration |
|
|
79
|
-
| `/services/apexrest/auth/forgot-password` | POST | Request password reset |
|
|
80
|
-
| `/services/apexrest/auth/reset-password` | POST | Reset password with token |
|
|
81
|
-
| `/services/apexrest/auth/change-password` | POST | Change password (authenticated) |
|
|
82
|
-
| `/services/apexrest/{resource}` | GET/POST | Custom Apex REST resources |
|
|
83
|
-
|
|
84
|
-
**Example (login):**
|
|
85
|
-
|
|
86
|
-
```typescript
|
|
87
|
-
const sdk = await createDataSDK();
|
|
88
|
-
const response = await sdk.fetch?.("/services/apexrest/auth/login", {
|
|
89
|
-
method: "POST",
|
|
90
|
-
body: JSON.stringify({ email, password, startUrl: "/" }),
|
|
91
|
-
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
|
92
|
-
});
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
Apex REST paths do not include the API version.
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
|
|
99
|
-
## UI API (REST)
|
|
100
|
-
|
|
101
|
-
When GraphQL cannot cover the use case. **Prefer GraphQL** when possible.
|
|
102
|
-
|
|
103
|
-
| Endpoint | Method | Purpose |
|
|
104
|
-
| -------- | ------ | ------- |
|
|
105
|
-
| `/services/data/v{version}/ui-api/records/{recordId}` | GET | Fetch a single record |
|
|
106
|
-
|
|
107
|
-
```typescript
|
|
108
|
-
const sdk = await createDataSDK();
|
|
109
|
-
const response = await sdk.fetch?.(`/services/data/v${API_VERSION}/ui-api/records/${recordId}`);
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
---
|
|
113
|
-
|
|
114
|
-
## Einstein LLM Gateway
|
|
115
|
-
|
|
116
|
-
AI features. Requires Einstein API setup.
|
|
117
|
-
|
|
118
|
-
| Endpoint | Method | Purpose |
|
|
119
|
-
| -------- | ------ | ------- |
|
|
120
|
-
| `/services/data/v{version}/einstein/llm/prompt/generations` | POST | Generate text from Einstein LLM |
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
const sdk = await createDataSDK();
|
|
124
|
-
const response = await sdk.fetch?.(`/services/data/v${API_VERSION}/einstein/llm/prompt/generations`, {
|
|
125
|
-
method: "POST",
|
|
126
|
-
headers: { "Content-Type": "application/json" },
|
|
127
|
-
body: JSON.stringify({
|
|
128
|
-
additionalConfig: { applicationName: "PromptTemplateGenerationsInvocable" },
|
|
129
|
-
promptTextorId: prompt,
|
|
130
|
-
}),
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
if (!response?.ok) throw new Error(`Einstein LLM failed (${response?.status})`);
|
|
134
|
-
const data = await response.json();
|
|
135
|
-
return data?.generations?.[0]?.text ?? "";
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
---
|
|
139
|
-
|
|
140
|
-
## General Pattern
|
|
141
|
-
|
|
142
|
-
```typescript
|
|
143
|
-
import { createDataSDK } from "@salesforce/sdk-data";
|
|
144
|
-
|
|
145
|
-
const sdk = await createDataSDK();
|
|
146
|
-
|
|
147
|
-
if (!sdk.fetch) {
|
|
148
|
-
throw new Error("Data SDK fetch is not available in this context");
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const response = await sdk.fetch(url, {
|
|
152
|
-
method: "GET", // or POST, PUT, PATCH, DELETE
|
|
153
|
-
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
|
154
|
-
body: method !== "GET" ? JSON.stringify(payload) : undefined,
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
158
|
-
const data = await response.json();
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
## Reference
|
|
164
|
-
|
|
165
|
-
- Parent: `accessing-data` — enforces Data SDK usage for all Salesforce data fetches
|
|
166
|
-
- GraphQL: `using-graphql` — use for record queries and mutations when possible
|
|
167
|
-
- `createRecord` from `@salesforce/webapp-experimental/api` for UI API record creation (uses SDK internally)
|