agent-docs 1.0.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/.cursor/plans/OPTIMISE.md +379 -0
- package/.cursor/plans/VERSIONING.md +207 -0
- package/.cursor/rules/IMPORTANT.mdc +97 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +13 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
- package/.github/dependabot.yml +38 -0
- package/.github/pull_request_template.md +10 -0
- package/.github/workflows/format.yml +35 -0
- package/CODE_OF_CONDUCT.md +64 -0
- package/CONTRIBUTING.md +52 -0
- package/LICENSE.md +20 -0
- package/PLAN.md +707 -0
- package/README.md +133 -0
- package/SECURITY.md +21 -0
- package/docs/APEXANNOTATIONS.md +472 -0
- package/docs/APEXDOC.md +198 -0
- package/docs/CML.md +877 -0
- package/docs/CODEANALYZER.md +435 -0
- package/docs/CONTEXTDEFINITIONS.md +617 -0
- package/docs/ESLINT.md +827 -0
- package/docs/ESLINTJSDOC.md +520 -0
- package/docs/FIELDSERVICE.md +4452 -0
- package/docs/GRAPHBINARY.md +208 -0
- package/docs/GRAPHENGINE.md +616 -0
- package/docs/GRAPHML.md +337 -0
- package/docs/GRAPHSON.md +302 -0
- package/docs/GREMLIN.md +490 -0
- package/docs/GRYO.md +232 -0
- package/docs/HUSKY.md +106 -0
- package/docs/JEST.md +387 -0
- package/docs/JORJE.md +537 -0
- package/docs/JSDOC.md +621 -0
- package/docs/PMD.md +910 -0
- package/docs/PNPM.md +409 -0
- package/docs/PRETTIER.md +716 -0
- package/docs/PRETTIERAPEX.md +874 -0
- package/docs/REVENUETRANSACTIONMANAGEMENT.md +887 -0
- package/docs/TINKERPOP.md +252 -0
- package/docs/VITEST.md +706 -0
- package/docs/VSCODE.md +231 -0
- package/docs/XPATH31.md +213 -0
- package/package.json +32 -0
- package/postinstall.mjs +51 -0
- package/prettier.config.js +18 -0
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# agent-docs
|
|
2
|
+
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
|
|
5
|
+
A reusable set of low-token AI agent instruction documents ("docs") for
|
|
6
|
+
AI-enabled IDEs.
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
**Docs** are markdown files containing distilled technical, style,
|
|
11
|
+
architectural, and philosophical knowledge. They are designed to be:
|
|
12
|
+
|
|
13
|
+
- **Low token count** - Optimized for efficient AI agent consumption
|
|
14
|
+
- **Comprehensive** - Complete coverage of essential information
|
|
15
|
+
- **Reusable** - Shareable across projects and teams
|
|
16
|
+
|
|
17
|
+
Inspired by _The Matrix_ (1999), where Neo says "I know kung fu" after having
|
|
18
|
+
knowledge uploaded directly into his brain. In that scene, Neo instantly gains
|
|
19
|
+
complete knowledge and skills without needing to learn through practice - the
|
|
20
|
+
knowledge is simply "there" when needed. Similarly, agent-docs creates
|
|
21
|
+
comprehensive documentation "programs" that can be referenced by AI agents,
|
|
22
|
+
giving them instant, complete knowledge about libraries, frameworks, and tools.
|
|
23
|
+
Just as Neo could access kung fu knowledge instantly, AI agents can reference
|
|
24
|
+
these docs to immediately understand APIs, patterns, best practices, and
|
|
25
|
+
architectural decisions without needing to search or learn incrementally. The
|
|
26
|
+
docs serve as the "knowledge upload" that makes the AI agent instantly capable
|
|
27
|
+
with any technology.
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
1. **Clone the repository (optional, for local development of agent-docs
|
|
32
|
+
itself):**
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git clone https://github.com/starch-uk/agent-docs.git
|
|
36
|
+
cd agent-docs
|
|
37
|
+
pnpm install
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
2. **Add to your project:**
|
|
41
|
+
|
|
42
|
+
You can add agent-docs to your project in several ways:
|
|
43
|
+
- **As an npm dependency (recommended):**
|
|
44
|
+
Add `@starch-uk/agent-docs` to your `package.json` and install with your
|
|
45
|
+
package manager (e.g. `pnpm install`, `npm install`, or `yarn add`).
|
|
46
|
+
|
|
47
|
+
When installed this way, a `postinstall` script runs in the consuming
|
|
48
|
+
project:
|
|
49
|
+
- If your project does **not** already have a `docs/` directory, the
|
|
50
|
+
script will create a single link from your project's `docs/` directory
|
|
51
|
+
to this package's `docs/` directory:
|
|
52
|
+
- On Unix/macOS, a directory symlink is created
|
|
53
|
+
- On Windows, a junction is created
|
|
54
|
+
- If your project **already has** a `docs/` directory, the script does
|
|
55
|
+
nothing, and your existing docs layout is left unchanged.
|
|
56
|
+
|
|
57
|
+
- **As a git submodule:**
|
|
58
|
+
`git submodule add https://github.com/starch-uk/agent-docs.git`
|
|
59
|
+
|
|
60
|
+
- **As a manual symlink/junction (if you want explicit control):**
|
|
61
|
+
- **Unix/macOS:** `ln -s /path/to/agent-docs/docs ./docs`
|
|
62
|
+
- **Windows:** `mklink /J docs C:\path\to\agent-docs\docs`
|
|
63
|
+
|
|
64
|
+
3. **Configure your IDE agent:**
|
|
65
|
+
|
|
66
|
+
Update your IDE agent rules (e.g., Cursor's `.cursor/rules/` or similar) to
|
|
67
|
+
reference the linked docs using `@filename` syntax or relative paths:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
Reference documentation from ./docs/ when needed:
|
|
71
|
+
- @PMD.md for PMD rules and configuration
|
|
72
|
+
- @XPATH31.md for XPath 3.1 syntax
|
|
73
|
+
- @ESLINT.md for ESLint configuration
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Documentation
|
|
77
|
+
|
|
78
|
+
The `docs/` directory contains generated documentation files. Each doc follows a
|
|
79
|
+
structured format optimized for AI agent consumption:
|
|
80
|
+
|
|
81
|
+
- **APEXANNOTATIONS.md** - Apex annotations reference
|
|
82
|
+
- **APEXDOC.md** - ApexDoc documentation tool reference
|
|
83
|
+
- **CML.md** - Constraint Modeling Language (CML) reference for Salesforce
|
|
84
|
+
Revenue Cloud Product Configurator
|
|
85
|
+
- **CODEANALYZER.md** - Salesforce Code Analyzer configuration (includes CLI
|
|
86
|
+
Commands, CPD Engine, Flow Scanner Engine, Regex Engine, RetireJS Engine, and
|
|
87
|
+
MCP tools)
|
|
88
|
+
- **CONTEXTDEFINITIONS.md** - Salesforce Context Definitions reference for
|
|
89
|
+
Dynamic Revenue Orchestrator (DRO)
|
|
90
|
+
- **ESLINT.md** - ESLint configuration and rules reference
|
|
91
|
+
- **ESLINTJSDOC.md** - ESLint JSDoc plugin reference
|
|
92
|
+
- **FIELDSERVICE.md** - Salesforce Field Service reference
|
|
93
|
+
- **GRAPHBINARY.md** - Graph Binary format reference
|
|
94
|
+
- **GRAPHENGINE.md** - Graph Engine reference
|
|
95
|
+
- **GRAPHML.md** - GraphML format reference
|
|
96
|
+
- **GRAPHSON.md** - GraphSON format reference
|
|
97
|
+
- **GREMLIN.md** - Gremlin query language reference
|
|
98
|
+
- **GRYO.md** - Gryo binary format reference
|
|
99
|
+
- **HUSKY.md** - Husky git hooks tool reference
|
|
100
|
+
- **JEST.md** - Jest testing framework reference
|
|
101
|
+
- **JORJE.md** - Jorje Apex parser reference
|
|
102
|
+
- **JSDOC.md** - JSDoc documentation generator reference
|
|
103
|
+
- **PMD.md** - PMD static analysis tool reference (includes Apex AST reference
|
|
104
|
+
and suppressing warnings)
|
|
105
|
+
- **PNPM.md** - pnpm package manager reference
|
|
106
|
+
- **PRETTIER.md** - Prettier code formatter reference
|
|
107
|
+
- **PRETTIERAPEX.md** - Prettier Apex plugin reference
|
|
108
|
+
- **REVENUETRANSACTIONMANAGEMENT.md** - Salesforce Revenue Cloud Transaction
|
|
109
|
+
Management reference
|
|
110
|
+
- **TINKERPOP.md** - Apache TinkerPop graph computing framework reference
|
|
111
|
+
- **VITEST.md** - Vitest testing framework reference
|
|
112
|
+
- **VSCODE.md** - VS Code editor reference
|
|
113
|
+
- **XPATH31.md** - XPath 3.1 query language reference
|
|
114
|
+
|
|
115
|
+
## Contributing
|
|
116
|
+
|
|
117
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on contributing to this
|
|
118
|
+
project.
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
This project is licensed under the MIT License - see [LICENSE.md](LICENSE.md)
|
|
123
|
+
for details.
|
|
124
|
+
|
|
125
|
+
## Security
|
|
126
|
+
|
|
127
|
+
For security concerns, please see [SECURITY.md](SECURITY.md).
|
|
128
|
+
|
|
129
|
+
## Support
|
|
130
|
+
|
|
131
|
+
- **Issues:** [GitHub Issues](https://github.com/starch-uk/agent-docs/issues)
|
|
132
|
+
- **Repository:**
|
|
133
|
+
[https://github.com/starch-uk/agent-docs](https://github.com/starch-uk/agent-docs)
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
We release patches for security vulnerabilities as they are identified. Please
|
|
6
|
+
ensure you are using the latest version of the software.
|
|
7
|
+
|
|
8
|
+
| Version | Supported |
|
|
9
|
+
| -------- | ------------------ |
|
|
10
|
+
| >= 1.0.0 | :white_check_mark: |
|
|
11
|
+
| < 1.0.0 | :x: |
|
|
12
|
+
|
|
13
|
+
## Reporting a Vulnerability
|
|
14
|
+
|
|
15
|
+
If you discover a security vulnerability, please report it by emailing
|
|
16
|
+
**security@starch.uk**.
|
|
17
|
+
|
|
18
|
+
**Please do not** open a public GitHub issue for security vulnerabilities.
|
|
19
|
+
|
|
20
|
+
We will respond as promptly as possible to address the issue. We appreciate your
|
|
21
|
+
help in keeping the project secure.
|
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
# Apex Annotations Reference
|
|
2
|
+
|
|
3
|
+
> **Version**: 1.0.0
|
|
4
|
+
|
|
5
|
+
> **Syntax**: `@AnnotationName` or `@AnnotationName(param='value')` — uses
|
|
6
|
+
> single quotes (not double)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Lightning/UI
|
|
11
|
+
|
|
12
|
+
### @AuraEnabled
|
|
13
|
+
|
|
14
|
+
Exposes method/property to Lightning Components (Aura/LWC).
|
|
15
|
+
|
|
16
|
+
```apex
|
|
17
|
+
@AuraEnabled // Basic
|
|
18
|
+
@AuraEnabled(cacheable=true) // Cached, no DML
|
|
19
|
+
@AuraEnabled(cacheable=true scope='global') // Global cache (API 55.0+)
|
|
20
|
+
@AuraEnabled(continuation=true) // Long-running callouts
|
|
21
|
+
@AuraEnabled(continuation=true cacheable=true) // Space separator, not comma
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
| Parameter | Type | Default | Description |
|
|
25
|
+
| -------------- | ------- | ------- | ------------------------------------------- |
|
|
26
|
+
| `cacheable` | Boolean | `false` | Cached; no DML/future/callouts allowed |
|
|
27
|
+
| `scope` | String | — | `'global'` enables global cache (API 55.0+) |
|
|
28
|
+
| `continuation` | Boolean | `false` | Returns Continuation object |
|
|
29
|
+
|
|
30
|
+
**Requirements**: `public static` | **Restrictions**: `cacheable=true` prohibits
|
|
31
|
+
DML, `@future`, callouts; API 55.0+ no overloads
|
|
32
|
+
|
|
33
|
+
```apex
|
|
34
|
+
public class AccountController {
|
|
35
|
+
@AuraEnabled(cacheable=true)
|
|
36
|
+
public static List<Account> getAccounts() {
|
|
37
|
+
return [SELECT Id, Name FROM Account LIMIT 10];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### @RemoteAction
|
|
43
|
+
|
|
44
|
+
Exposes method to JavaScript in Visualforce pages.
|
|
45
|
+
|
|
46
|
+
```apex
|
|
47
|
+
@RemoteAction
|
|
48
|
+
public static String processData(String input) { return 'Processed: ' + input; }
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Requirements**: `public static` or `global static` | **Restrictions**:
|
|
52
|
+
Incompatible with `@AuraEnabled`; class must be VF controller/extension
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## REST API
|
|
57
|
+
|
|
58
|
+
### @RestResource
|
|
59
|
+
|
|
60
|
+
Exposes class as REST endpoint.
|
|
61
|
+
|
|
62
|
+
```apex
|
|
63
|
+
@RestResource(urlMapping='/account/*')
|
|
64
|
+
global class AccountRestService {
|
|
65
|
+
@HttpGet
|
|
66
|
+
global static Account getAccount() {
|
|
67
|
+
RestRequest req = RestContext.request;
|
|
68
|
+
String accountId = req.requestURI.substring(req.requestURI.lastIndexOf('/') + 1);
|
|
69
|
+
return [SELECT Id, Name FROM Account WHERE Id = :accountId];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@HttpPost
|
|
73
|
+
global static Account createAccount(String name) {
|
|
74
|
+
Account acc = new Account(Name = name);
|
|
75
|
+
insert acc;
|
|
76
|
+
return acc;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@HttpDelete
|
|
80
|
+
global static void deleteAccount() {
|
|
81
|
+
RestRequest req = RestContext.request;
|
|
82
|
+
String accountId = req.requestURI.substring(req.requestURI.lastIndexOf('/') + 1);
|
|
83
|
+
delete [SELECT Id FROM Account WHERE Id = :accountId];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
| Parameter | Type | Required | Description |
|
|
89
|
+
| ------------ | ------ | -------- | --------------------------------------------- |
|
|
90
|
+
| `urlMapping` | String | Yes | URL path (must start with `/`, max 255 chars) |
|
|
91
|
+
|
|
92
|
+
**Requirements**: Class must be `global` | **URL rules**: Wildcards `*` allowed;
|
|
93
|
+
case-sensitive matching
|
|
94
|
+
|
|
95
|
+
### HTTP Method Annotations
|
|
96
|
+
|
|
97
|
+
| Annotation | HTTP Method | Signature |
|
|
98
|
+
| ------------- | ----------- | --------------------------------------- |
|
|
99
|
+
| `@HttpGet` | GET | `global static ReturnType methodName()` |
|
|
100
|
+
| `@HttpPost` | POST | `global static ReturnType methodName()` |
|
|
101
|
+
| `@HttpPut` | PUT | `global static ReturnType methodName()` |
|
|
102
|
+
| `@HttpPatch` | PATCH | `global static ReturnType methodName()` |
|
|
103
|
+
| `@HttpDelete` | DELETE | `global static ReturnType methodName()` |
|
|
104
|
+
|
|
105
|
+
**Requirements**: `global static`; must be in `@RestResource` class
|
|
106
|
+
|
|
107
|
+
**Access request body**:
|
|
108
|
+
|
|
109
|
+
```apex
|
|
110
|
+
RestRequest req = RestContext.request;
|
|
111
|
+
Map<String, Object> data = (Map<String, Object>) JSON.deserializeUntyped(req.requestBody.toString());
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Asynchronous Processing
|
|
117
|
+
|
|
118
|
+
### @Future
|
|
119
|
+
|
|
120
|
+
Executes method asynchronously in separate thread.
|
|
121
|
+
|
|
122
|
+
```apex
|
|
123
|
+
@Future
|
|
124
|
+
@Future(callout=true)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
| Parameter | Type | Default | Description |
|
|
128
|
+
| --------- | ------- | ------- | ------------------------- |
|
|
129
|
+
| `callout` | Boolean | `false` | Enables external callouts |
|
|
130
|
+
|
|
131
|
+
**Requirements**: `public static void` | **Param types**: Primitives,
|
|
132
|
+
arrays/collections of primitives/IDs only (no sObjects) **Restrictions**:
|
|
133
|
+
`callout=true` prohibits DML
|
|
134
|
+
|
|
135
|
+
```apex
|
|
136
|
+
public class AsyncProcessor {
|
|
137
|
+
@Future
|
|
138
|
+
public static void processRecords(Set<Id> recordIds) {
|
|
139
|
+
List<Account> accounts = [SELECT Id FROM Account WHERE Id IN :recordIds];
|
|
140
|
+
// Processing...
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@Future(callout=true)
|
|
144
|
+
public static void makeCallout(String data) {
|
|
145
|
+
Http http = new Http();
|
|
146
|
+
HttpRequest req = new HttpRequest();
|
|
147
|
+
req.setEndpoint('https://api.example.com');
|
|
148
|
+
req.setMethod('POST');
|
|
149
|
+
req.setBody(data);
|
|
150
|
+
http.send(req);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Flow/Process Builder
|
|
158
|
+
|
|
159
|
+
### @InvocableMethod
|
|
160
|
+
|
|
161
|
+
Exposes method to Flow, Process Builder, Agentforce, Einstein bots.
|
|
162
|
+
|
|
163
|
+
```apex
|
|
164
|
+
@InvocableMethod(label='Method Label' description='Description' category='Category')
|
|
165
|
+
public static List<ReturnType> methodName(List<InputType> inputs) { }
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
| Parameter | Type | Description |
|
|
169
|
+
| --------------------- | ------- | ---------------------------------------------- |
|
|
170
|
+
| `label` | String | Display label in UI |
|
|
171
|
+
| `description` | String | Description in UI |
|
|
172
|
+
| `callout` | Boolean | Enables external callouts |
|
|
173
|
+
| `category` | String | Category in Flow Builder |
|
|
174
|
+
| `configurationEditor` | String | Custom property editor |
|
|
175
|
+
| `capabilityType` | String | Capability integration (`Name://Name`) |
|
|
176
|
+
| `iconName` | String | Custom icon (SVG from static resource or SLDS) |
|
|
177
|
+
|
|
178
|
+
**Requirements**: `public static` or `global static`; outer class only; one per
|
|
179
|
+
class **Params**: Single `List` (primitives, sObjects, or `@InvocableVariable`
|
|
180
|
+
classes) **Returns**: `void` or `List` **Restrictions**: Incompatible with
|
|
181
|
+
`@AuraEnabled`
|
|
182
|
+
|
|
183
|
+
```apex
|
|
184
|
+
public class FlowUtilities {
|
|
185
|
+
@InvocableMethod(label='Update Account Status')
|
|
186
|
+
public static List<String> updateAccountStatus(List<Id> accountIds) {
|
|
187
|
+
List<Account> accounts = [SELECT Id FROM Account WHERE Id IN :accountIds];
|
|
188
|
+
for (Account acc : accounts) { acc.Status__c = 'Active'; }
|
|
189
|
+
update accounts;
|
|
190
|
+
return new List<String>{'Success'};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### @InvocableVariable
|
|
196
|
+
|
|
197
|
+
Exposes property as Flow input/output variable.
|
|
198
|
+
|
|
199
|
+
```apex
|
|
200
|
+
@InvocableVariable(label='Label' description='Desc' required=true)
|
|
201
|
+
public Type variableName;
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
| Parameter | Type | Default | Description |
|
|
205
|
+
| ----------------- | ------- | ------- | ---------------------------------------------------------- |
|
|
206
|
+
| `label` | String | — | Display label |
|
|
207
|
+
| `description` | String | — | Description |
|
|
208
|
+
| `required` | Boolean | `false` | Required input (ignored for outputs) |
|
|
209
|
+
| `defaultValue` | String | — | Default value (Boolean/Decimal/Double/Integer/Long/String) |
|
|
210
|
+
| `placeholderText` | String | — | Placeholder text (Double/Integer/String) |
|
|
211
|
+
|
|
212
|
+
**Requirements**: Member variable (not static/local/final); `public` or `global`
|
|
213
|
+
**Types**: Primitives (except Object), sObjects, Lists
|
|
214
|
+
|
|
215
|
+
```apex
|
|
216
|
+
public class AccountUpdateRequest {
|
|
217
|
+
@InvocableVariable(label='Account ID' required=true)
|
|
218
|
+
public Id accountId;
|
|
219
|
+
|
|
220
|
+
@InvocableVariable(label='New Status')
|
|
221
|
+
public String status;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
public class FlowUtilities {
|
|
225
|
+
@InvocableMethod
|
|
226
|
+
public static List<Account> updateAccounts(List<AccountUpdateRequest> requests) {
|
|
227
|
+
List<Account> accounts = new List<Account>();
|
|
228
|
+
for (AccountUpdateRequest req : requests) {
|
|
229
|
+
accounts.add(new Account(Id = req.accountId, Status__c = req.status));
|
|
230
|
+
}
|
|
231
|
+
update accounts;
|
|
232
|
+
return accounts;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Testing
|
|
240
|
+
|
|
241
|
+
### @IsTest
|
|
242
|
+
|
|
243
|
+
Marks test class/method. Test code doesn't count against org limits.
|
|
244
|
+
|
|
245
|
+
```apex
|
|
246
|
+
@IsTest
|
|
247
|
+
@IsTest(SeeAllData=true) // Access org data (not recommended)
|
|
248
|
+
@IsTest(OnInstall=true) // Run during package install
|
|
249
|
+
@IsTest(IsParallel=true) // Enable parallel execution
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
| Parameter | Type | Default | Description |
|
|
253
|
+
| ------------ | ------- | ------- | ----------------------------------------- |
|
|
254
|
+
| `SeeAllData` | Boolean | `false` | Access org data (avoid; use `@TestSetup`) |
|
|
255
|
+
| `OnInstall` | Boolean | `false` | Run during package installation |
|
|
256
|
+
| `IsParallel` | Boolean | `false` | Allow parallel execution |
|
|
257
|
+
|
|
258
|
+
**Requirements**: Class should be `private`; methods must be `static void`
|
|
259
|
+
**Restrictions**: `SeeAllData=true` + `IsParallel=true` incompatible;
|
|
260
|
+
`IsParallel=true` prohibits `Test.getStandardPricebookId()`,
|
|
261
|
+
`System.schedule()`, `System.enqueueJob()`, `ContentNote` insert,
|
|
262
|
+
`User`/`GroupMember` creation
|
|
263
|
+
|
|
264
|
+
### @TestSetup
|
|
265
|
+
|
|
266
|
+
Creates shared test data for all test methods.
|
|
267
|
+
|
|
268
|
+
```apex
|
|
269
|
+
@TestSetup
|
|
270
|
+
static void setup() {
|
|
271
|
+
insert new Account(Name = 'Test Account');
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**Requirements**: `static void`; one per class **Restrictions**: Incompatible
|
|
276
|
+
with `@IsTest(SeeAllData=true)`; API 24.0+
|
|
277
|
+
|
|
278
|
+
### @TestVisible
|
|
279
|
+
|
|
280
|
+
Makes private/protected members accessible to tests.
|
|
281
|
+
|
|
282
|
+
```apex
|
|
283
|
+
public class MyService {
|
|
284
|
+
@TestVisible
|
|
285
|
+
private static String helperMethod(String input) {
|
|
286
|
+
return input.toUpperCase();
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
@IsTest
|
|
291
|
+
private class MyServiceTest {
|
|
292
|
+
@IsTest
|
|
293
|
+
static void testHelper() {
|
|
294
|
+
System.assertEquals('TEST', MyService.helperMethod('test'));
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Utility
|
|
302
|
+
|
|
303
|
+
### @Deprecated
|
|
304
|
+
|
|
305
|
+
Marks code as deprecated (managed packages only).
|
|
306
|
+
|
|
307
|
+
```apex
|
|
308
|
+
@Deprecated
|
|
309
|
+
public static void oldMethod() { }
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
**Restrictions**: Managed packages only; cannot deprecate `webservice`,
|
|
313
|
+
individual enum values, interface methods, abstract methods; cannot undeprecate
|
|
314
|
+
after release
|
|
315
|
+
|
|
316
|
+
### @SuppressWarnings
|
|
317
|
+
|
|
318
|
+
Suppresses compiler/PMD warnings.
|
|
319
|
+
|
|
320
|
+
```apex
|
|
321
|
+
@SuppressWarnings('PMD.UnusedLocalVariable')
|
|
322
|
+
@SuppressWarnings('PMD.UnusedLocalVariable, PMD.UnusedPrivateMethod') // Multiple
|
|
323
|
+
@SuppressWarnings('PMD') // All PMD warnings
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### @ReadOnly
|
|
327
|
+
|
|
328
|
+
Enables read-only mode; increases query limit to 1M rows.
|
|
329
|
+
|
|
330
|
+
```apex
|
|
331
|
+
@ReadOnly
|
|
332
|
+
public static List<Account> generateReport() {
|
|
333
|
+
return [SELECT Id, Name FROM Account]; // Up to 1M rows
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**Restrictions**: No DML, no `System.schedule()`, no async jobs; top-level must
|
|
338
|
+
be web service or scheduled execution
|
|
339
|
+
|
|
340
|
+
### @JsonAccess
|
|
341
|
+
|
|
342
|
+
Controls JSON serialization/deserialization access.
|
|
343
|
+
|
|
344
|
+
```apex
|
|
345
|
+
@JsonAccess(serializable='always' deserializable='always')
|
|
346
|
+
public class MyClass { }
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
| Parameter | Values | Description |
|
|
350
|
+
| ---------------- | --------------------------------------------------------- | ----------------------- |
|
|
351
|
+
| `serializable` | `'always'`, `'never'`, `'sameNamespace'`, `'samePackage'` | Serialization control |
|
|
352
|
+
| `deserializable` | `'always'`, `'never'`, `'sameNamespace'`, `'samePackage'` | Deserialization control |
|
|
353
|
+
|
|
354
|
+
**Defaults**: API 48.0-: `deserializable='always'`,
|
|
355
|
+
`serializable='sameNamespace'` | API 49.0+: Both `'sameNamespace'`
|
|
356
|
+
|
|
357
|
+
### @NamespaceAccessible
|
|
358
|
+
|
|
359
|
+
Grants cross-namespace access in 2GP packages.
|
|
360
|
+
|
|
361
|
+
```apex
|
|
362
|
+
@NamespaceAccessible
|
|
363
|
+
public class CrossNamespaceClass { }
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
**Usage**: 2GP managed packages only; `global` is always accessible (no
|
|
367
|
+
annotation needed) **Restrictions**: API 47.0+ incompatible with `@AuraEnabled`;
|
|
368
|
+
API 50.0+ requires outer class also annotated
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## Compatibility Matrix
|
|
373
|
+
|
|
374
|
+
| Status | Combinations |
|
|
375
|
+
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
376
|
+
| ✓ Compatible | `@AuraEnabled` + `@Deprecated`, `@IsTest` + `@TestSetup`, `@TestVisible` + access modifiers |
|
|
377
|
+
| ✗ Incompatible | `@AuraEnabled` + `@InvocableMethod`, `@AuraEnabled` + `@RemoteAction`, `@Future` + `@AuraEnabled(cacheable=true)`, `@Future(callout=true)` + DML |
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## PMD AST
|
|
382
|
+
|
|
383
|
+
```xpath
|
|
384
|
+
//Method[Annotation[@Name='Future']]
|
|
385
|
+
//Class[Annotation[@Name='IsTest']]
|
|
386
|
+
//Annotation[@Name='AuraEnabled']
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
```
|
|
390
|
+
Annotation {
|
|
391
|
+
@Name: Identifier (e.g., "Future", "AuraEnabled")
|
|
392
|
+
parameters: List<AnnotationParameter>
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## Common Patterns
|
|
399
|
+
|
|
400
|
+
### Lightning Component
|
|
401
|
+
|
|
402
|
+
```apex
|
|
403
|
+
@AuraEnabled(cacheable=true)
|
|
404
|
+
public static List<Account> getAccounts() {
|
|
405
|
+
return [SELECT Id, Name FROM Account LIMIT 10];
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### REST API
|
|
410
|
+
|
|
411
|
+
```apex
|
|
412
|
+
@RestResource(urlMapping='/account/*')
|
|
413
|
+
global class AccountRestService {
|
|
414
|
+
@HttpGet
|
|
415
|
+
global static Account getAccount() {
|
|
416
|
+
RestRequest req = RestContext.request;
|
|
417
|
+
String id = req.requestURI.substring(req.requestURI.lastIndexOf('/') + 1);
|
|
418
|
+
return [SELECT Id, Name FROM Account WHERE Id = :id];
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Flow Invocable
|
|
424
|
+
|
|
425
|
+
```apex
|
|
426
|
+
@InvocableMethod(label='Update Account')
|
|
427
|
+
public static List<String> updateAccount(List<Id> accountIds) {
|
|
428
|
+
List<Account> accs = [SELECT Id FROM Account WHERE Id IN :accountIds];
|
|
429
|
+
for (Account a : accs) { a.Status__c = 'Active'; }
|
|
430
|
+
update accs;
|
|
431
|
+
return new List<String>{'Success'};
|
|
432
|
+
}
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### Test Class
|
|
436
|
+
|
|
437
|
+
```apex
|
|
438
|
+
@IsTest
|
|
439
|
+
private class MyServiceTest {
|
|
440
|
+
@TestSetup
|
|
441
|
+
static void setup() {
|
|
442
|
+
insert new Account(Name = 'Test Account');
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
@IsTest
|
|
446
|
+
static void testMethod() {
|
|
447
|
+
Account acc = [SELECT Id FROM Account LIMIT 1];
|
|
448
|
+
System.assertNotEquals(null, acc);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
## Best Practices
|
|
456
|
+
|
|
457
|
+
| Practice | Description |
|
|
458
|
+
| ---------------------------- | ------------------------------------ |
|
|
459
|
+
| Specify `cacheable` | Always explicit for `@AuraEnabled` |
|
|
460
|
+
| Avoid `SeeAllData` | Use `@TestSetup` instead |
|
|
461
|
+
| Prefer Queueable | Over `@Future` for complex async |
|
|
462
|
+
| Use `@TestVisible` sparingly | Prefer testing public interfaces |
|
|
463
|
+
| Document suppressions | Comment why `@SuppressWarnings` used |
|
|
464
|
+
| Validate REST inputs | Always sanitize in `@RestResource` |
|
|
465
|
+
|
|
466
|
+
---
|
|
467
|
+
|
|
468
|
+
## Related
|
|
469
|
+
|
|
470
|
+
- [ApexDoc Reference](APEXDOC.md)
|
|
471
|
+
- [PMD Apex AST](PMD.md#apex-ast-reference)
|
|
472
|
+
- [Salesforce Apex Annotations](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation.htm)
|