@salesforce/webapp-template-base-sfdx-project-experimental 1.111.0 → 1.112.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.
@@ -111,7 +111,7 @@ Apps run behind dynamic base paths. Router navigation (`<Link to>`, `navigate()`
111
111
 
112
112
  ## Module Restrictions
113
113
 
114
- React apps must NOT import Salesforce platform modules like `lightning/*` or `@wire` (LWC-only). For data access, invoke the **accessing-data** skill.
114
+ React apps must NOT import Salesforce platform modules like `lightning/*` or `@wire` (LWC-only). For data access, invoke the **using-salesforce-data** skill.
115
115
 
116
116
  # Frontend Aesthetics
117
117
 
@@ -138,4 +138,3 @@ Only stop when:
138
138
  - All checklist items are completed and quality gates pass, or
139
139
  - A blocking error cannot be resolved after reasonable remediation, or
140
140
  - The user explicitly asks to pause.
141
-
@@ -225,5 +225,4 @@ The project includes `scripts/setup-cli.mjs` which runs this sequence in batch.
225
225
 
226
226
  ## Related Skills
227
227
 
228
- - **exploring-graphql-schema** — Schema exploration (grep-only) after schema exists
229
- - **using-graphql** — Full GraphQL workflow (explore, query, codegen, lint)
228
+ - **using-salesforce-data** — Full data access workflow (GraphQL queries/mutations, REST APIs, schema exploration, webapp integration)
@@ -0,0 +1,268 @@
1
+ ---
2
+ name: using-salesforce-data
3
+ description: Salesforce data access for reads, mutations, and REST APIs. Use when the user wants to fetch, display, create, update, or delete Salesforce records; add data fetching to a component; query Accounts, Contacts, Opportunities, or custom objects; call Chatter, Connect, or Apex REST APIs; or integrate Salesforce data into a webapp.
4
+ paths:
5
+ - "**/*.ts"
6
+ - "**/*.tsx"
7
+ - "**/*.graphql"
8
+ ---
9
+
10
+ # Salesforce Data Access
11
+
12
+ ## When to Use
13
+
14
+ Use this skill when the user wants to:
15
+
16
+ - **Fetch or display Salesforce data** — Query records (Account, Contact, Opportunity, custom objects) to show in a component
17
+ - **Create, update, or delete records** — Perform mutations on Salesforce data
18
+ - **Add data fetching to a component** — Wire up a React component to Salesforce data
19
+ - **Call REST APIs** — Use Chatter, Connect, Apex REST, or UI API endpoints
20
+ - **Explore the org schema** — Discover available objects, fields, or relationships
21
+
22
+ ## Data SDK Requirement
23
+
24
+ > **All Salesforce data access MUST use the Data SDK** (`@salesforce/sdk-data`). The SDK handles authentication, CSRF, and base URL resolution. Never use `fetch()` or `axios` directly.
25
+
26
+ ```typescript
27
+ import { createDataSDK, gql } from "@salesforce/sdk-data";
28
+
29
+ const sdk = await createDataSDK();
30
+
31
+ // GraphQL for record queries/mutations (PREFERRED)
32
+ const response = await sdk.graphql?.<ResponseType>(query, variables);
33
+
34
+ // REST for Chatter, Connect, Apex REST (when GraphQL insufficient)
35
+ const res = await sdk.fetch?.("/services/data/v65.0/chatter/users/me");
36
+ ```
37
+
38
+ **Always use optional chaining** (`sdk.graphql?.()`, `sdk.fetch?.()`) — these methods may be undefined in some surfaces.
39
+
40
+ ## Decision: GraphQL vs REST
41
+
42
+ | Need | Method | Example |
43
+ |------|--------|---------|
44
+ | Query/mutate records | `sdk.graphql` | Account, Contact, custom objects |
45
+ | Chatter API | `sdk.fetch` | `/chatter/users/me` |
46
+ | Connect REST | `sdk.fetch` | `/connect/file/upload/config` |
47
+ | Apex REST | `sdk.fetch` | `/services/apexrest/auth/login` |
48
+ | Einstein LLM | `sdk.fetch` | `/einstein/llm/prompt/generations` |
49
+
50
+ **GraphQL is preferred** for record operations. Use REST only when GraphQL doesn't cover the use case.
51
+
52
+ ---
53
+
54
+ ## GraphQL Workflow
55
+
56
+ ### Step 1: Acquire Schema
57
+
58
+ The `schema.graphql` file (265K+ lines) is the source of truth. **Use grep only** — never open or parse the file directly.
59
+
60
+ 1. Check if `schema.graphql` exists at the SFDX project root
61
+ 2. If missing, run from the **webapp dir**: `npm run graphql:schema`
62
+ 3. Custom objects appear only after metadata is deployed
63
+
64
+ ### Step 2: Identify & Introspect Entities
65
+
66
+ Map user intent to PascalCase names ("accounts" → `Account`). Validate via grep:
67
+
68
+ ```bash
69
+ # From project root — find entity fields
70
+ grep -nE '^type Account implements Record' ./schema.graphql -A 100
71
+
72
+ # Find filter options
73
+ grep -nE '^input Account_Filter' ./schema.graphql -A 50
74
+
75
+ # Find mutation input
76
+ grep -nE '^input AccountCreateInput' ./schema.graphql -A 50
77
+ ```
78
+
79
+ **Maximum 3 introspection cycles.** If entities remain unknown, ask the user.
80
+
81
+ ### Step 3: Generate Query
82
+
83
+ Use the templates below. Every field name **must** be verified via grep.
84
+
85
+ #### Read Query Template
86
+
87
+ ```graphql
88
+ query GetAccounts {
89
+ uiapi {
90
+ query {
91
+ Account(where: { Industry: { eq: "Technology" } }, first: 10) {
92
+ edges {
93
+ node {
94
+ Id
95
+ Name @optional { value }
96
+ Industry @optional { value }
97
+ # Parent relationship
98
+ Owner @optional { Name { value } }
99
+ # Child relationship
100
+ Contacts @optional {
101
+ edges { node { Name @optional { value } } }
102
+ }
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ **FLS Resilience**: Apply `@optional` to all record fields. The server omits inaccessible fields instead of failing. Consuming code must use optional chaining:
112
+
113
+ ```typescript
114
+ const name = node.Name?.value ?? "";
115
+ ```
116
+
117
+ #### Mutation Template
118
+
119
+ ```graphql
120
+ mutation CreateAccount($input: AccountCreateInput!) {
121
+ uiapi {
122
+ AccountCreate(input: $input) {
123
+ Record { Id Name { value } }
124
+ }
125
+ }
126
+ }
127
+ ```
128
+
129
+ **Mutation constraints:**
130
+ - Create: Include required fields, only `createable` fields, no child relationships
131
+ - Update: Include `Id`, only `updateable` fields
132
+ - Delete: Include `Id` only
133
+
134
+ ### Step 4: Validate & Test
135
+
136
+ 1. **Lint**: `npx eslint <file>` from webapp dir
137
+ 2. **Test**: Ask user before testing. For mutations, request input values — never fabricate data.
138
+
139
+ ```bash
140
+ # From project root
141
+ sf api request rest /services/data/v65.0/graphql \
142
+ --method POST \
143
+ --body '{"query":"..."}'
144
+ ```
145
+
146
+ ---
147
+
148
+ ## Webapp Integration (React)
149
+
150
+ ### Pattern 1: External .graphql File (Recommended)
151
+
152
+ ```typescript
153
+ import { createDataSDK, type NodeOfConnection } from "@salesforce/sdk-data";
154
+ import GET_ACCOUNTS from "./query/getAccounts.graphql?raw";
155
+ import type { GetAccountsQuery } from "../graphql-operations-types";
156
+
157
+ const sdk = await createDataSDK();
158
+ const response = await sdk.graphql?.<GetAccountsQuery>(GET_ACCOUNTS);
159
+
160
+ if (response?.errors?.length) {
161
+ throw new Error(response.errors.map(e => e.message).join("; "));
162
+ }
163
+
164
+ const accounts = response?.data?.uiapi?.query?.Account?.edges?.map(e => e.node) ?? [];
165
+ ```
166
+
167
+ After creating/modifying `.graphql` files, run: `npm run graphql:codegen`
168
+
169
+ ### Pattern 2: Inline gql Tag
170
+
171
+ ```typescript
172
+ import { createDataSDK, gql } from "@salesforce/sdk-data";
173
+
174
+ const GET_CURRENT_USER = gql`
175
+ query CurrentUser {
176
+ uiapi { currentUser { Id Name { value } } }
177
+ }
178
+ `;
179
+
180
+ const response = await sdk.graphql?.<CurrentUserQuery>(GET_CURRENT_USER);
181
+ ```
182
+
183
+ **Must use `gql` tag** — plain template strings bypass ESLint validation.
184
+
185
+ ---
186
+
187
+ ## REST API Patterns
188
+
189
+ Use `sdk.fetch` when GraphQL is insufficient:
190
+
191
+ ```typescript
192
+ declare const __SF_API_VERSION__: string;
193
+ const API_VERSION = typeof __SF_API_VERSION__ !== "undefined" ? __SF_API_VERSION__ : "65.0";
194
+
195
+ // Chatter — current user
196
+ const res = await sdk.fetch?.(`/services/data/v${API_VERSION}/chatter/users/me`);
197
+
198
+ // Connect — file upload config
199
+ const res = await sdk.fetch?.(`/services/data/v${API_VERSION}/connect/file/upload/config`);
200
+
201
+ // Apex REST (no version in path)
202
+ const res = await sdk.fetch?.("/services/apexrest/auth/login", {
203
+ method: "POST",
204
+ body: JSON.stringify({ email, password }),
205
+ headers: { "Content-Type": "application/json" },
206
+ });
207
+
208
+ // Einstein LLM
209
+ const res = await sdk.fetch?.(`/services/data/v${API_VERSION}/einstein/llm/prompt/generations`, {
210
+ method: "POST",
211
+ body: JSON.stringify({ promptTextorId: prompt }),
212
+ });
213
+ ```
214
+
215
+ ---
216
+
217
+ ## Directory Structure
218
+
219
+ ```
220
+ <project-root>/ ← SFDX project root
221
+ ├── schema.graphql ← grep target (lives here)
222
+ ├── sfdx-project.json
223
+ └── force-app/main/default/webapplications/<app-name>/ ← webapp dir
224
+ ├── package.json ← npm scripts
225
+ ├── codegen.yml
226
+ └── src/
227
+ └── api/graphql-operations-types.ts ← generated types
228
+ ```
229
+
230
+ | Command | Run From | Why |
231
+ |---------|----------|-----|
232
+ | `npm run graphql:schema` | webapp dir | Script in webapp's package.json |
233
+ | `npm run graphql:codegen` | webapp dir | Reads codegen.yml |
234
+ | `npx eslint <file>` | webapp dir | Reads eslint.config.js |
235
+ | `grep ... schema.graphql` | project root | Schema lives at root |
236
+ | `sf api request rest` | project root | Needs sfdx-project.json |
237
+
238
+ ---
239
+
240
+ ## Quick Reference
241
+
242
+ ### Grep Patterns (from project root)
243
+
244
+ | Pattern | Context | Purpose |
245
+ |---------|---------|---------|
246
+ | `^type <Entity> implements Record` | `-A 100` | Entity fields |
247
+ | `^input <Entity>_Filter` | `-A 50` | Filter options |
248
+ | `^input <Entity>_OrderBy` | `-A 30` | Sort options |
249
+ | `^input <Entity>CreateInput` | `-A 50` | Create mutation input |
250
+ | `^input <Entity>UpdateInput` | `-A 50` | Update mutation input |
251
+
252
+ ### Error Categories
253
+
254
+ | Error Contains | Resolution |
255
+ |----------------|------------|
256
+ | `invalid syntax` | Fix syntax per error message |
257
+ | `validation error` | Re-grep to verify field name |
258
+ | `VariableTypeMismatch` | Correct argument type from schema |
259
+ | `invalid cross reference id` | Entity deleted — ask for valid Id |
260
+
261
+ ### Checklist
262
+
263
+ - [ ] All field names verified via grep
264
+ - [ ] `@optional` applied to record fields (reads)
265
+ - [ ] Optional chaining in consuming code
266
+ - [ ] `gql` tag used (not plain strings)
267
+ - [ ] Lint passes: `npx eslint <file>`
268
+ - [ ] Types generated: `npm run graphql:codegen`
package/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
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.112.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.111.0...v1.112.0) (2026-03-20)
7
+
8
+
9
+ ### Features
10
+
11
+ * unify 4 GraphQL skills into single using-graphql skill ([#325](https://github.com/salesforce-experience-platform-emu/webapps/issues/325)) ([3935407](https://github.com/salesforce-experience-platform-emu/webapps/commit/393540779c2da76d7f181f62738aa3d4613a2805))
12
+
13
+
14
+
15
+
16
+
6
17
  # [1.111.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.110.1...v1.111.0) (2026-03-19)
7
18
 
8
19
  **Note:** Version bump only for package @salesforce/webapp-template-base-sfdx-project-experimental
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/webapp-template-base-sfdx-project-experimental",
3
- "version": "1.111.0",
3
+ "version": "1.112.0",
4
4
  "description": "Base SFDX project template",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "publishConfig": {
@@ -1,178 +0,0 @@
1
- ---
2
- name: accessing-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-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