scc-universal 1.1.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/.claude-plugin/plugin.json +44 -0
- package/.cursor/agents/deep-researcher.md +142 -0
- package/.cursor/agents/doc-updater.md +219 -0
- package/.cursor/agents/eval-runner.md +335 -0
- package/.cursor/agents/learning-engine.md +210 -0
- package/.cursor/agents/loop-operator.md +245 -0
- package/.cursor/agents/refactor-cleaner.md +119 -0
- package/.cursor/agents/sf-admin-agent.md +127 -0
- package/.cursor/agents/sf-agentforce-agent.md +126 -0
- package/.cursor/agents/sf-apex-agent.md +117 -0
- package/.cursor/agents/sf-architect.md +426 -0
- package/.cursor/agents/sf-aura-reviewer.md +369 -0
- package/.cursor/agents/sf-bugfix-agent.md +101 -0
- package/.cursor/agents/sf-flow-agent.md +155 -0
- package/.cursor/agents/sf-integration-agent.md +141 -0
- package/.cursor/agents/sf-lwc-agent.md +123 -0
- package/.cursor/agents/sf-review-agent.md +357 -0
- package/.cursor/agents/sf-visualforce-reviewer.md +465 -0
- package/.cursor/hooks/adapter.js +81 -0
- package/.cursor/hooks/after-file-edit.js +26 -0
- package/.cursor/hooks/after-mcp-execution.js +12 -0
- package/.cursor/hooks/after-shell-execution.js +30 -0
- package/.cursor/hooks/after-tab-file-edit.js +12 -0
- package/.cursor/hooks/before-mcp-execution.js +11 -0
- package/.cursor/hooks/before-read-file.js +13 -0
- package/.cursor/hooks/before-shell-execution.js +29 -0
- package/.cursor/hooks/before-submit-prompt.js +23 -0
- package/.cursor/hooks/pre-compact.js +7 -0
- package/.cursor/hooks/session-end.js +10 -0
- package/.cursor/hooks/session-start.js +10 -0
- package/.cursor/hooks/stop.js +18 -0
- package/.cursor/hooks/subagent-start.js +10 -0
- package/.cursor/hooks/subagent-stop.js +10 -0
- package/.cursor/hooks.json +107 -0
- package/.cursor/skills/aside/SKILL.md +115 -0
- package/.cursor/skills/checkpoint/SKILL.md +50 -0
- package/.cursor/skills/configure-scc/SKILL.md +160 -0
- package/.cursor/skills/continuous-agent-loop/SKILL.md +260 -0
- package/.cursor/skills/mcp-server-patterns/SKILL.md +142 -0
- package/.cursor/skills/model-route/SKILL.md +81 -0
- package/.cursor/skills/prompt-optimizer/SKILL.md +366 -0
- package/.cursor/skills/refactor-clean/SKILL.md +133 -0
- package/.cursor/skills/resume-session/SKILL.md +111 -0
- package/.cursor/skills/save-session/SKILL.md +183 -0
- package/.cursor/skills/search-first/SKILL.md +140 -0
- package/.cursor/skills/security-scan/SKILL.md +142 -0
- package/.cursor/skills/sessions/SKILL.md +124 -0
- package/.cursor/skills/sf-agentforce-development/SKILL.md +449 -0
- package/.cursor/skills/sf-apex-async-patterns/SKILL.md +324 -0
- package/.cursor/skills/sf-apex-best-practices/SKILL.md +421 -0
- package/.cursor/skills/sf-apex-constraints/SKILL.md +79 -0
- package/.cursor/skills/sf-apex-cursor/SKILL.md +336 -0
- package/.cursor/skills/sf-apex-enterprise-patterns/SKILL.md +344 -0
- package/.cursor/skills/sf-apex-testing/SKILL.md +407 -0
- package/.cursor/skills/sf-api-design/SKILL.md +237 -0
- package/.cursor/skills/sf-approval-processes/SKILL.md +312 -0
- package/.cursor/skills/sf-aura-development/SKILL.md +260 -0
- package/.cursor/skills/sf-build-fix/SKILL.md +120 -0
- package/.cursor/skills/sf-data-modeling/SKILL.md +274 -0
- package/.cursor/skills/sf-debugging/SKILL.md +362 -0
- package/.cursor/skills/sf-deployment/SKILL.md +291 -0
- package/.cursor/skills/sf-deployment-constraints/SKILL.md +153 -0
- package/.cursor/skills/sf-devops-ci-cd/SKILL.md +322 -0
- package/.cursor/skills/sf-docs-lookup/SKILL.md +100 -0
- package/.cursor/skills/sf-e2e-testing/SKILL.md +321 -0
- package/.cursor/skills/sf-experience-cloud/SKILL.md +248 -0
- package/.cursor/skills/sf-flow-development/SKILL.md +376 -0
- package/.cursor/skills/sf-governor-limits/SKILL.md +319 -0
- package/.cursor/skills/sf-harness-audit/SKILL.md +139 -0
- package/.cursor/skills/sf-help/SKILL.md +156 -0
- package/.cursor/skills/sf-integration/SKILL.md +479 -0
- package/.cursor/skills/sf-lwc-constraints/SKILL.md +128 -0
- package/.cursor/skills/sf-lwc-development/SKILL.md +302 -0
- package/.cursor/skills/sf-lwc-testing/SKILL.md +387 -0
- package/.cursor/skills/sf-metadata-management/SKILL.md +285 -0
- package/.cursor/skills/sf-platform-events-cdc/SKILL.md +372 -0
- package/.cursor/skills/sf-quickstart/SKILL.md +170 -0
- package/.cursor/skills/sf-security/SKILL.md +330 -0
- package/.cursor/skills/sf-security-constraints/SKILL.md +125 -0
- package/.cursor/skills/sf-soql-constraints/SKILL.md +129 -0
- package/.cursor/skills/sf-soql-optimization/SKILL.md +353 -0
- package/.cursor/skills/sf-tdd-workflow/SKILL.md +332 -0
- package/.cursor/skills/sf-testing-constraints/SKILL.md +198 -0
- package/.cursor/skills/sf-trigger-constraints/SKILL.md +88 -0
- package/.cursor/skills/sf-trigger-frameworks/SKILL.md +343 -0
- package/.cursor/skills/sf-visualforce-development/SKILL.md +259 -0
- package/.cursor/skills/strategic-compact/SKILL.md +205 -0
- package/.cursor/skills/update-docs/SKILL.md +162 -0
- package/.cursor/skills/update-platform-docs/SKILL.md +86 -0
- package/.cursor-plugin/plugin.json +26 -0
- package/LICENSE +21 -0
- package/README.md +522 -0
- package/agents/deep-researcher.md +145 -0
- package/agents/doc-updater.md +222 -0
- package/agents/eval-runner.md +340 -0
- package/agents/learning-engine.md +211 -0
- package/agents/loop-operator.md +247 -0
- package/agents/refactor-cleaner.md +122 -0
- package/agents/sf-admin-agent.md +131 -0
- package/agents/sf-agentforce-agent.md +132 -0
- package/agents/sf-apex-agent.md +124 -0
- package/agents/sf-architect.md +435 -0
- package/agents/sf-aura-reviewer.md +372 -0
- package/agents/sf-bugfix-agent.md +105 -0
- package/agents/sf-flow-agent.md +159 -0
- package/agents/sf-integration-agent.md +146 -0
- package/agents/sf-lwc-agent.md +127 -0
- package/agents/sf-review-agent.md +366 -0
- package/agents/sf-visualforce-reviewer.md +468 -0
- package/assets/logo.svg +18 -0
- package/docs/ARCHITECTURE.md +133 -0
- package/docs/authoring-guide.md +373 -0
- package/docs/hook-development.md +578 -0
- package/docs/token-optimization.md +139 -0
- package/docs/workflow-examples.md +645 -0
- package/examples/agentforce-action/README.md +227 -0
- package/examples/apex-trigger-handler/README.md +114 -0
- package/examples/devops-pipeline/README.md +325 -0
- package/examples/flow-automation/README.md +188 -0
- package/examples/integration-pattern/README.md +416 -0
- package/examples/lwc-component/README.md +180 -0
- package/examples/platform-events/README.md +492 -0
- package/examples/scratch-org-setup/README.md +138 -0
- package/examples/security-audit/README.md +244 -0
- package/examples/visualforce-migration/README.md +314 -0
- package/hooks/hooks.json +338 -0
- package/hooks/memory-persistence/README.md +73 -0
- package/manifests/install-modules.json +217 -0
- package/manifests/install-profiles.json +17 -0
- package/mcp-configs/mcp-servers.json +19 -0
- package/package.json +89 -0
- package/schemas/hooks.schema.json +123 -0
- package/schemas/install-modules.schema.json +76 -0
- package/schemas/install-profiles.schema.json +28 -0
- package/schemas/install-state.schema.json +73 -0
- package/schemas/package-manager.schema.json +18 -0
- package/schemas/plugin.schema.json +112 -0
- package/schemas/scc-install-config.schema.json +29 -0
- package/schemas/state-store.schema.json +111 -0
- package/scripts/cli/install-apply.js +170 -0
- package/scripts/cli/uninstall.js +193 -0
- package/scripts/hooks/check-console-log.js +101 -0
- package/scripts/hooks/check-hook-enabled.js +17 -0
- package/scripts/hooks/check-platform-docs-age.js +48 -0
- package/scripts/hooks/cost-tracker.js +78 -0
- package/scripts/hooks/doc-file-warning.js +63 -0
- package/scripts/hooks/evaluate-session.js +98 -0
- package/scripts/hooks/governor-check.js +220 -0
- package/scripts/hooks/learning-observe.sh +206 -0
- package/scripts/hooks/mcp-health-check.js +588 -0
- package/scripts/hooks/post-bash-build-complete.js +34 -0
- package/scripts/hooks/post-bash-pr-created.js +43 -0
- package/scripts/hooks/post-edit-console-warn.js +61 -0
- package/scripts/hooks/post-edit-format.js +79 -0
- package/scripts/hooks/post-edit-typecheck.js +98 -0
- package/scripts/hooks/post-write.js +168 -0
- package/scripts/hooks/pre-bash-git-push-reminder.js +35 -0
- package/scripts/hooks/pre-bash-tmux-reminder.js +47 -0
- package/scripts/hooks/pre-compact.js +51 -0
- package/scripts/hooks/pre-tool-use.js +163 -0
- package/scripts/hooks/pre-write-doc-warn.js +9 -0
- package/scripts/hooks/quality-gate.js +251 -0
- package/scripts/hooks/run-with-flags-shell.sh +32 -0
- package/scripts/hooks/run-with-flags.js +135 -0
- package/scripts/hooks/session-end-marker.js +29 -0
- package/scripts/hooks/session-end.js +311 -0
- package/scripts/hooks/session-start.js +202 -0
- package/scripts/hooks/sfdx-scanner-check.js +142 -0
- package/scripts/hooks/sfdx-validate.js +119 -0
- package/scripts/hooks/stop-hook.js +170 -0
- package/scripts/hooks/suggest-compact.js +67 -0
- package/scripts/lib/agent-adapter.js +82 -0
- package/scripts/lib/apex-analysis.js +194 -0
- package/scripts/lib/hook-flags.js +74 -0
- package/scripts/lib/install-config.js +73 -0
- package/scripts/lib/install-executor.js +363 -0
- package/scripts/lib/install-state.js +121 -0
- package/scripts/lib/orchestration-session.js +299 -0
- package/scripts/lib/package-manager.js +124 -0
- package/scripts/lib/project-detect.js +228 -0
- package/scripts/lib/schema-validator.js +190 -0
- package/scripts/lib/skill-adapter.js +100 -0
- package/scripts/lib/state-store.js +376 -0
- package/scripts/lib/tmux-worktree-orchestrator.js +598 -0
- package/scripts/lib/utils.js +313 -0
- package/scripts/scc.js +164 -0
- package/skills/_reference/AGENTFORCE_PATTERNS.md +112 -0
- package/skills/_reference/APEX_CURSOR.md +159 -0
- package/skills/_reference/API_VERSIONS.md +78 -0
- package/skills/_reference/APPROVAL_PROCESSES.md +105 -0
- package/skills/_reference/ASYNC_PATTERNS.md +163 -0
- package/skills/_reference/AURA_COMPONENTS.md +146 -0
- package/skills/_reference/DATA_MIGRATION_PATTERNS.md +151 -0
- package/skills/_reference/DATA_MODELING.md +124 -0
- package/skills/_reference/DEBUGGING_TOOLS.md +140 -0
- package/skills/_reference/DEPLOYMENT_CHECKLIST.md +87 -0
- package/skills/_reference/DEPRECATIONS.md +79 -0
- package/skills/_reference/DOCKER_CI_PATTERNS.md +138 -0
- package/skills/_reference/ENTERPRISE_PATTERNS.md +122 -0
- package/skills/_reference/EXPERIENCE_CLOUD.md +143 -0
- package/skills/_reference/FLOW_PATTERNS.md +113 -0
- package/skills/_reference/GOVERNOR_LIMITS.md +77 -0
- package/skills/_reference/INTEGRATION_PATTERNS.md +105 -0
- package/skills/_reference/LWC_PATTERNS.md +79 -0
- package/skills/_reference/METADATA_TYPES.md +115 -0
- package/skills/_reference/NAMING_CONVENTIONS.md +84 -0
- package/skills/_reference/PACKAGE_DEVELOPMENT.md +150 -0
- package/skills/_reference/PLATFORM_EVENTS.md +121 -0
- package/skills/_reference/REPORTING_API.md +143 -0
- package/skills/_reference/SCRATCH_ORG_PATTERNS.md +126 -0
- package/skills/_reference/SECURITY_PATTERNS.md +127 -0
- package/skills/_reference/SHARING_MODEL.md +120 -0
- package/skills/_reference/SOQL_PATTERNS.md +119 -0
- package/skills/_reference/TESTING_STANDARDS.md +96 -0
- package/skills/_reference/TRIGGER_PATTERNS.md +114 -0
- package/skills/_reference/VISUALFORCE_PATTERNS.md +121 -0
- package/skills/aside/SKILL.md +118 -0
- package/skills/checkpoint/SKILL.md +53 -0
- package/skills/configure-scc/SKILL.md +163 -0
- package/skills/continuous-agent-loop/SKILL.md +264 -0
- package/skills/mcp-server-patterns/SKILL.md +146 -0
- package/skills/model-route/SKILL.md +84 -0
- package/skills/prompt-optimizer/SKILL.md +369 -0
- package/skills/refactor-clean/SKILL.md +136 -0
- package/skills/resume-session/SKILL.md +114 -0
- package/skills/save-session/SKILL.md +186 -0
- package/skills/search-first/SKILL.md +144 -0
- package/skills/security-scan/SKILL.md +146 -0
- package/skills/sessions/SKILL.md +127 -0
- package/skills/sf-agentforce-development/SKILL.md +450 -0
- package/skills/sf-apex-async-patterns/SKILL.md +326 -0
- package/skills/sf-apex-best-practices/SKILL.md +425 -0
- package/skills/sf-apex-constraints/SKILL.md +81 -0
- package/skills/sf-apex-cursor/SKILL.md +338 -0
- package/skills/sf-apex-enterprise-patterns/SKILL.md +348 -0
- package/skills/sf-apex-testing/SKILL.md +409 -0
- package/skills/sf-api-design/SKILL.md +238 -0
- package/skills/sf-approval-processes/SKILL.md +315 -0
- package/skills/sf-aura-development/SKILL.md +263 -0
- package/skills/sf-build-fix/SKILL.md +121 -0
- package/skills/sf-data-modeling/SKILL.md +278 -0
- package/skills/sf-debugging/SKILL.md +363 -0
- package/skills/sf-deployment/SKILL.md +295 -0
- package/skills/sf-deployment-constraints/SKILL.md +155 -0
- package/skills/sf-devops-ci-cd/SKILL.md +325 -0
- package/skills/sf-docs-lookup/SKILL.md +103 -0
- package/skills/sf-e2e-testing/SKILL.md +324 -0
- package/skills/sf-experience-cloud/SKILL.md +249 -0
- package/skills/sf-flow-development/SKILL.md +377 -0
- package/skills/sf-governor-limits/SKILL.md +323 -0
- package/skills/sf-harness-audit/SKILL.md +142 -0
- package/skills/sf-help/SKILL.md +159 -0
- package/skills/sf-integration/SKILL.md +483 -0
- package/skills/sf-lwc-constraints/SKILL.md +130 -0
- package/skills/sf-lwc-development/SKILL.md +303 -0
- package/skills/sf-lwc-testing/SKILL.md +388 -0
- package/skills/sf-metadata-management/SKILL.md +288 -0
- package/skills/sf-platform-events-cdc/SKILL.md +375 -0
- package/skills/sf-quickstart/SKILL.md +173 -0
- package/skills/sf-security/SKILL.md +334 -0
- package/skills/sf-security-constraints/SKILL.md +127 -0
- package/skills/sf-soql-constraints/SKILL.md +131 -0
- package/skills/sf-soql-optimization/SKILL.md +354 -0
- package/skills/sf-tdd-workflow/SKILL.md +336 -0
- package/skills/sf-testing-constraints/SKILL.md +200 -0
- package/skills/sf-trigger-constraints/SKILL.md +90 -0
- package/skills/sf-trigger-frameworks/SKILL.md +347 -0
- package/skills/sf-visualforce-development/SKILL.md +260 -0
- package/skills/strategic-compact/SKILL.md +208 -0
- package/skills/update-docs/SKILL.md +165 -0
- package/skills/update-platform-docs/SKILL.md +90 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
<!-- Source: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_class_System_Cursor.htm -->
|
|
2
|
+
<!-- Last verified: API v66.0 — 2026-03-29 -->
|
|
3
|
+
<!-- WARNING: Web fetch of canonical URL failed (JS-rendered page). Facts extracted from SCC skill sf-apex-cursor. Verify against official docs before relying on limits. -->
|
|
4
|
+
|
|
5
|
+
# Apex Cursor Reference
|
|
6
|
+
|
|
7
|
+
## Classes
|
|
8
|
+
|
|
9
|
+
| Class | Purpose | AuraEnabled |
|
|
10
|
+
|-------|---------|-------------|
|
|
11
|
+
| `Database.Cursor` | Server-side pointer for paginated SOQL iteration | No (use PaginationCursor) |
|
|
12
|
+
| `Database.PaginationCursor` | UI-oriented cursor for LWC / `@AuraEnabled` methods | Yes |
|
|
13
|
+
|
|
14
|
+
## Database.Cursor Methods
|
|
15
|
+
|
|
16
|
+
| Method | Return Type | Description |
|
|
17
|
+
|--------|-------------|-------------|
|
|
18
|
+
| `Database.getCursor(String soql)` | `Database.Cursor` | Open a new cursor from a SOQL query |
|
|
19
|
+
| `Database.getCursor(String cursorId)` | `Database.Cursor` | Re-open a serialized cursor in a new transaction |
|
|
20
|
+
| `cursor.fetch(Integer offset, Integer pageSize)` | `List<SObject>` | Fetch a page of records starting at offset |
|
|
21
|
+
| `cursor.getNumRecords()` | `Integer` | Total row count the cursor can return |
|
|
22
|
+
| `cursor.getId()` | `String` | Serialize cursor ID for cross-transaction use |
|
|
23
|
+
| `cursor.close()` | `void` | Release server-side resources |
|
|
24
|
+
|
|
25
|
+
## Database.PaginationCursor Methods
|
|
26
|
+
|
|
27
|
+
| Method | Return Type | Description |
|
|
28
|
+
|--------|-------------|-------------|
|
|
29
|
+
| `Database.getPaginationCursor(String soql)` | `Database.PaginationCursor` | Open a new pagination cursor |
|
|
30
|
+
| `Database.getPaginationCursor(String cursorId)` | `Database.PaginationCursor` | Resume from a client-provided cursor ID |
|
|
31
|
+
| `cursor.fetch(Integer pageSize)` | `List<SObject>` | Fetch next page (auto-advances position) |
|
|
32
|
+
| `cursor.hasMore()` | `Boolean` | Whether more pages remain |
|
|
33
|
+
| `cursor.getNumRecords()` | `Integer` | Total row count |
|
|
34
|
+
| `cursor.getId()` | `String` | Cursor ID safe to return to LWC client |
|
|
35
|
+
|
|
36
|
+
## Governor Limits
|
|
37
|
+
|
|
38
|
+
| Constraint | Value |
|
|
39
|
+
|------------|-------|
|
|
40
|
+
| Max records per cursor | 50,000,000 |
|
|
41
|
+
| Cursor lifetime (sync transaction) | 10 minutes |
|
|
42
|
+
| Cursor lifetime (async / Queueable) | 60 minutes |
|
|
43
|
+
| Max page size per `fetch()` call | 2,000 rows |
|
|
44
|
+
| Max open cursors per transaction | 10 |
|
|
45
|
+
|
|
46
|
+
## Availability
|
|
47
|
+
|
|
48
|
+
| Detail | Value |
|
|
49
|
+
|--------|-------|
|
|
50
|
+
| GA release | Spring '26 |
|
|
51
|
+
| Minimum API version | 66.0 |
|
|
52
|
+
|
|
53
|
+
## Exception Types
|
|
54
|
+
|
|
55
|
+
| Exception | Cause |
|
|
56
|
+
|-----------|-------|
|
|
57
|
+
| `System.CursorException: Cursor has been closed` | Called `fetch()` after `close()` |
|
|
58
|
+
| `System.CursorException: Cursor has expired` | Exceeded 10 min (sync) or 60 min (async) |
|
|
59
|
+
| `System.CursorException: Maximum cursors exceeded` | More than 10 open cursors in one transaction |
|
|
60
|
+
| `System.QueryException: Non-selective query` | WHERE clause not indexed on large table |
|
|
61
|
+
|
|
62
|
+
## Cursor vs OFFSET vs Batch Apex
|
|
63
|
+
|
|
64
|
+
| Approach | Max Records | Heap Impact | Best For |
|
|
65
|
+
|----------|-------------|-------------|----------|
|
|
66
|
+
| SOQL `OFFSET` | 2,000 | Full result set in heap | Small UI pagination |
|
|
67
|
+
| Batch Apex (`QueryLocator`) | Unlimited | Per-execute governor reset | Background mass processing |
|
|
68
|
+
| `Cursor` class | 50,000,000 | Per-page only | Large paginated reports, async chaining, LWC infinite scroll |
|
|
69
|
+
|
|
70
|
+
## Performance Guidance
|
|
71
|
+
|
|
72
|
+
| Record Count | Recommended Approach |
|
|
73
|
+
|-------------|----------------------|
|
|
74
|
+
| < 200 | Standard SOQL with `LIMIT` |
|
|
75
|
+
| 200 - 2,000 | `OFFSET` pagination |
|
|
76
|
+
| 2,000 - 50,000 | `Cursor` |
|
|
77
|
+
| 50,000+ | `Cursor` + Queueable chaining |
|
|
78
|
+
| Batch processing | `Database.QueryLocator` |
|
|
79
|
+
|
|
80
|
+
## Key Rules
|
|
81
|
+
|
|
82
|
+
- Always close cursors in a `finally` block to prevent server-side resource leaks.
|
|
83
|
+
- `Cursor` is read-only; collect IDs separately for DML.
|
|
84
|
+
- Cursor ID is serializable; pass it across Queueable jobs for async chaining.
|
|
85
|
+
- OFFSET forces the DB to skip N rows per request; Cursor maintains a server-side pointer with no scanning overhead.
|
|
86
|
+
|
|
87
|
+
## Error Recovery Patterns
|
|
88
|
+
|
|
89
|
+
### try/finally Cursor Cleanup
|
|
90
|
+
|
|
91
|
+
Always close cursors in `finally` to prevent resource leaks, even on exceptions.
|
|
92
|
+
|
|
93
|
+
```apex
|
|
94
|
+
Database.Cursor cursor = Database.getCursor('SELECT Id, Name FROM Account');
|
|
95
|
+
try {
|
|
96
|
+
Integer total = cursor.getNumRecords();
|
|
97
|
+
for (Integer offset = 0; offset < total; offset += 200) {
|
|
98
|
+
List<Account> page = (List<Account>) cursor.fetch(offset, 200);
|
|
99
|
+
// process page...
|
|
100
|
+
}
|
|
101
|
+
} finally {
|
|
102
|
+
cursor.close();
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Expired Cursor Recovery
|
|
107
|
+
|
|
108
|
+
If a cursor expires mid-pagination (10 min sync, 60 min async), catch the exception and re-open from the last known offset.
|
|
109
|
+
|
|
110
|
+
```apex
|
|
111
|
+
public static void processLargeDataset(String soql) {
|
|
112
|
+
Database.Cursor cursor = Database.getCursor(soql);
|
|
113
|
+
Integer offset = 0;
|
|
114
|
+
try {
|
|
115
|
+
Integer total = cursor.getNumRecords();
|
|
116
|
+
while (offset < total) {
|
|
117
|
+
try {
|
|
118
|
+
List<SObject> page = cursor.fetch(offset, 2000);
|
|
119
|
+
processBatch(page);
|
|
120
|
+
offset += page.size();
|
|
121
|
+
} catch (System.CursorException e) {
|
|
122
|
+
if (e.getMessage().contains('expired')) {
|
|
123
|
+
cursor = Database.getCursor(soql); // re-open
|
|
124
|
+
continue; // retry from same offset
|
|
125
|
+
}
|
|
126
|
+
throw e;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
} finally {
|
|
130
|
+
cursor.close();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### PaginationCursor — LWC @AuraEnabled Pattern
|
|
136
|
+
|
|
137
|
+
Return cursor ID to client; handle expiry by issuing a fresh cursor.
|
|
138
|
+
|
|
139
|
+
```apex
|
|
140
|
+
@AuraEnabled
|
|
141
|
+
public static Map<String, Object> getPage(String cursorId, String soql) {
|
|
142
|
+
Database.PaginationCursor cursor;
|
|
143
|
+
try {
|
|
144
|
+
cursor = (cursorId != null)
|
|
145
|
+
? Database.getPaginationCursor(cursorId)
|
|
146
|
+
: Database.getPaginationCursor(soql);
|
|
147
|
+
} catch (System.CursorException e) {
|
|
148
|
+
// Cursor expired — start fresh
|
|
149
|
+
cursor = Database.getPaginationCursor(soql);
|
|
150
|
+
}
|
|
151
|
+
List<SObject> records = cursor.fetch(200);
|
|
152
|
+
return new Map<String, Object>{
|
|
153
|
+
'records' => records,
|
|
154
|
+
'cursorId' => cursor.getId(),
|
|
155
|
+
'hasMore' => cursor.hasMore(),
|
|
156
|
+
'totalCount' => cursor.getNumRecords()
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
```
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Salesforce API Versions — Feature Tracker
|
|
2
|
+
|
|
3
|
+
> Last verified: 2026-03-31 against Spring '26 (API v66.0)
|
|
4
|
+
> Source: <https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_versions.htm>
|
|
5
|
+
>
|
|
6
|
+
> **MAINTENANCE:**
|
|
7
|
+
>
|
|
8
|
+
> 1. When a new release ships: add section at TOP with `Added: YYYY-MM`
|
|
9
|
+
> 2. Remove sections older than 24 months (model knows them by then)
|
|
10
|
+
> 3. Update "Last verified" date
|
|
11
|
+
> 4. Deprecations go in DEPRECATIONS.md (separate file, independent cadence)
|
|
12
|
+
> 5. Releases and deprecations are INDEPENDENT — a new release does NOT deprecate the previous one
|
|
13
|
+
|
|
14
|
+
## Spring '26 — API v66.0 (Current) `Added: 2026-03`
|
|
15
|
+
|
|
16
|
+
| Feature | Version | Status | Description |
|
|
17
|
+
|---------|---------|--------|-------------|
|
|
18
|
+
| `Database.Cursor` / `Database.getCursor()` | v66.0 | GA | Paginate up to 50M SOQL rows |
|
|
19
|
+
| `Database.PaginationCursor` | v66.0 | GA | `@AuraEnabled`-compatible cursor for LWC |
|
|
20
|
+
| GraphQL Mutations in LWC | v66.0 | GA | `executeMutation` for create/update/delete |
|
|
21
|
+
| Named Query API | v66.0 | GA | Custom SOQL exposed as REST endpoints |
|
|
22
|
+
| Autonomous Actions | v66.0 | GA | Expose Apex REST / `@AuraEnabled` as Agentforce actions via OpenAPI |
|
|
23
|
+
| SLDS 2.0 | v66.0 | GA | New Lightning Design System |
|
|
24
|
+
| `RunRelevantTests` test level | v66.0 | **Beta** | Smart test selection — do NOT rely on for production |
|
|
25
|
+
| `@testFor` annotation | v66.0 | **Beta** | Map test class to production class (pairs with RunRelevantTests) |
|
|
26
|
+
| LWC Complex Template Expressions | v66.0 | **Beta/Pilot** | Do NOT use in production |
|
|
27
|
+
| Agent Script | v66.0 | **Public Beta** | Deterministic + LLM blocks, no GA date |
|
|
28
|
+
|
|
29
|
+
## Winter '26 — API v65.0 `Added: 2026-03`
|
|
30
|
+
|
|
31
|
+
| Feature | Version | Status | Description |
|
|
32
|
+
|---------|---------|--------|-------------|
|
|
33
|
+
| SOAP `login()` removed | v65.0 | Breaking | Use OAuth 2.0 instead |
|
|
34
|
+
| Abstract/override access modifiers | v65.0 | Breaking | Must add explicit public/protected/global |
|
|
35
|
+
| GraphQL optional fields (`lightning/graphql`) | v65.0 | GA | Resilient queries with optional field support |
|
|
36
|
+
| Unified Logic Testing | v65.0 | GA | Apex + Flow tests in single command |
|
|
37
|
+
| External Services binary files | v65.0 | GA | Upload/download up to 16 MB via OpenAPI 3.0 |
|
|
38
|
+
|
|
39
|
+
## Summer '25 — API v64.0 `Added: 2026-03`
|
|
40
|
+
|
|
41
|
+
| Feature | Version | Status | Description |
|
|
42
|
+
|---------|---------|--------|-------------|
|
|
43
|
+
| API v21–30 retired | v64.0 | Breaking | Minimum supported version: v31.0 |
|
|
44
|
+
| OpenAPI support for REST API | v64.0 | GA | Client SDK generation from OpenAPI spec |
|
|
45
|
+
| Data Cloud Enrichment APIs | v64.0 | GA | Enriched related lists on Cases, Contracts |
|
|
46
|
+
| Streaming API disconnect handling | v64.0 | GA | `/meta/disconnect` channel for connection status |
|
|
47
|
+
|
|
48
|
+
## Stable Version-Gated Features (Older — retained for reference)
|
|
49
|
+
|
|
50
|
+
| Feature | Min API Version | Release | Notes |
|
|
51
|
+
|---|---|---|---|
|
|
52
|
+
| Null coalescing operator (`??`) | v60.0 | Spring '24 | `value ?? defaultValue` |
|
|
53
|
+
| `Database.queryWithBinds()` | v57.0 | Spring '23 | Safe dynamic SOQL with bind maps |
|
|
54
|
+
| `WITH USER_MODE` / `AccessLevel.USER_MODE` | v57.0 | Spring '23 GA | CRUD + FLS enforcement (Beta v55.0 Summer '22) |
|
|
55
|
+
| `Assert` class (`Assert.areEqual`, etc.) | v56.0 | Winter '23 | Replaces `System.assertEquals` |
|
|
56
|
+
| External Credentials | v54.0 | Spring '22 | Secure OAuth/JWT/API key storage |
|
|
57
|
+
| Null-safe navigation (`?.`) | v50.0 | Winter '21 | `obj?.field?.subfield` |
|
|
58
|
+
| `WITH SECURITY_ENFORCED` | v48.0 | Spring '20 | CRUD + FLS for reads (older pattern) |
|
|
59
|
+
| `Security.stripInaccessible()` | v48.0 | Spring '20 | Bulk FLS enforcement |
|
|
60
|
+
|
|
61
|
+
## Version Selection Guide
|
|
62
|
+
|
|
63
|
+
| Scenario | Recommendation |
|
|
64
|
+
|---|---|
|
|
65
|
+
| New project | Use v66.0 (Spring '26 GA) |
|
|
66
|
+
| Existing project | Match `sfdx-project.json` `sourceApiVersion` |
|
|
67
|
+
| Managed package | Pin to minimum supported version for subscriber compatibility |
|
|
68
|
+
| `RunRelevantTests` adoption | Requires `sourceApiVersion` >= v66.0 (Beta — not for production) |
|
|
69
|
+
|
|
70
|
+
## sfdx-project.json Version Setting
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"sourceApiVersion": "66.0"
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
This controls the API version used for `sf project deploy` and `sf project retrieve`. Individual class `-meta.xml` files can override with their own `<apiVersion>` value.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<!-- Source: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_process_classes.htm -->
|
|
2
|
+
<!-- Last verified: API v66.0 — 2026-03-29 -->
|
|
3
|
+
<!-- WARNING: Web fetch of canonical URL failed (JS-rendered page). Facts extracted from SCC skill sf-approval-processes. Verify against official docs before relying on class signatures. -->
|
|
4
|
+
|
|
5
|
+
# Approval Processes Reference
|
|
6
|
+
|
|
7
|
+
## Apex Approval Classes
|
|
8
|
+
|
|
9
|
+
| Class | Purpose |
|
|
10
|
+
|-------|---------|
|
|
11
|
+
| `Approval.ProcessSubmitRequest` | Submit a record for approval |
|
|
12
|
+
| `Approval.ProcessWorkitemRequest` | Approve, reject, or remove a pending work item |
|
|
13
|
+
| `Approval.ProcessResult` | Result returned by `Approval.process()` |
|
|
14
|
+
|
|
15
|
+
## Approval.ProcessSubmitRequest Methods
|
|
16
|
+
|
|
17
|
+
| Method | Parameter | Description |
|
|
18
|
+
|--------|-----------|-------------|
|
|
19
|
+
| `setObjectId(Id)` | Record ID | Record to submit for approval |
|
|
20
|
+
| `setSubmitterId(Id)` | User ID | User submitting the request |
|
|
21
|
+
| `setComments(String)` | Text | Submission comments |
|
|
22
|
+
| `setSkipEntryCriteria(Boolean)` | true/false | Bypass entry criteria check |
|
|
23
|
+
| `setProcessDefinitionNameOrId(String)` | Name or ID | Target a specific approval process |
|
|
24
|
+
| `setNextApproverIds(List<Id>)` | User IDs | Explicitly set next approver(s) |
|
|
25
|
+
|
|
26
|
+
## Approval.ProcessWorkitemRequest Methods
|
|
27
|
+
|
|
28
|
+
| Method | Parameter | Description |
|
|
29
|
+
|--------|-----------|-------------|
|
|
30
|
+
| `setWorkitemId(Id)` | Work item ID | The pending work item to act on |
|
|
31
|
+
| `setAction(String)` | `'Approve'` / `'Reject'` / `'Remove'` | Action to take |
|
|
32
|
+
| `setComments(String)` | Text | Approver/rejector comments |
|
|
33
|
+
|
|
34
|
+
## Approval.ProcessResult Methods
|
|
35
|
+
|
|
36
|
+
| Method | Return Type | Description |
|
|
37
|
+
|--------|-------------|-------------|
|
|
38
|
+
| `isSuccess()` | `Boolean` | Whether the operation succeeded |
|
|
39
|
+
| `getInstanceId()` | `Id` | ProcessInstance ID |
|
|
40
|
+
| `getInstanceStatus()` | `String` | `'Pending'`, `'Approved'`, `'Rejected'` |
|
|
41
|
+
| `getNewWorkitemIds()` | `List<Id>` | Work item IDs created by this step |
|
|
42
|
+
| `getErrors()` | `List<Database.Error>` | Error details on failure |
|
|
43
|
+
|
|
44
|
+
## Entry Point
|
|
45
|
+
|
|
46
|
+
| Method | Signature |
|
|
47
|
+
|--------|-----------|
|
|
48
|
+
| `Approval.process()` | `Approval.ProcessResult Approval.process(Approval.ProcessSubmitRequest req)` |
|
|
49
|
+
| `Approval.process()` | `Approval.ProcessResult Approval.process(Approval.ProcessWorkitemRequest req)` |
|
|
50
|
+
|
|
51
|
+
## Approval Step Properties
|
|
52
|
+
|
|
53
|
+
| Property | Options |
|
|
54
|
+
|----------|---------|
|
|
55
|
+
| Approver type | User field, Manager field, Queue, Related user |
|
|
56
|
+
| Step criteria | All records OR filter criteria (step-specific) |
|
|
57
|
+
| Reject behavior | Final rejection OR go to previous step |
|
|
58
|
+
| Unanimity | All must approve OR first response |
|
|
59
|
+
|
|
60
|
+
## Approval Actions by Phase
|
|
61
|
+
|
|
62
|
+
| Phase | Available Actions |
|
|
63
|
+
|-------|-------------------|
|
|
64
|
+
| Initial Submission | Field Update, Email Alert, Record Lock, Outbound Message |
|
|
65
|
+
| Final Approval | Field Update, Email Alert, Record Unlock, Workflow Task, Outbound Message |
|
|
66
|
+
| Final Rejection | Field Update, Email Alert, Record Unlock |
|
|
67
|
+
| Recall | Record Unlock, Field Update |
|
|
68
|
+
|
|
69
|
+
## Related Standard Objects
|
|
70
|
+
|
|
71
|
+
| Object | Purpose | Key Fields |
|
|
72
|
+
|--------|---------|------------|
|
|
73
|
+
| `ProcessInstance` | One approval submission | `TargetObjectId`, `Status`, `CreatedDate` |
|
|
74
|
+
| `ProcessInstanceWorkitem` | A pending approval task | `ActorId`, `ProcessInstanceId` |
|
|
75
|
+
| `ProcessInstanceStep` | One completed step in history | `StepStatus`, `Comments`, `ActorId`, `CreatedDate` |
|
|
76
|
+
| `ProcessInstanceHistory` | Union of steps and work items | `StepStatus`, `Comments`, `Actor.Name` |
|
|
77
|
+
|
|
78
|
+
## Key SOQL Queries
|
|
79
|
+
|
|
80
|
+
| Purpose | Object | Filter |
|
|
81
|
+
|---------|--------|--------|
|
|
82
|
+
| Pending items for current user | `ProcessInstanceWorkitem` | `WHERE ActorId = :UserInfo.getUserId()` |
|
|
83
|
+
| Approval history for a record | `ProcessInstanceStep` | `WHERE ProcessInstance.TargetObjectId = :recordId` |
|
|
84
|
+
| Active work item for a record | `ProcessInstanceWorkitem` | `WHERE ProcessInstance.TargetObjectId = :recordId AND ProcessInstance.Status = 'Pending'` |
|
|
85
|
+
|
|
86
|
+
## Metadata Deployment
|
|
87
|
+
|
|
88
|
+
| Item | Path | package.xml Type |
|
|
89
|
+
|------|------|------------------|
|
|
90
|
+
| Approval process | `approvalProcesses/<Object>.<Name>.approvalProcess-meta.xml` | `ApprovalProcess` |
|
|
91
|
+
| Member format | `<Object>.<ProcessName>` (e.g., `Opportunity.Discount_Approval`) | -- |
|
|
92
|
+
|
|
93
|
+
## Spring '26 Feature
|
|
94
|
+
|
|
95
|
+
| Feature | Detail |
|
|
96
|
+
|---------|--------|
|
|
97
|
+
| Integrated Approval Screen Component | Screen Flow component for in-flow approve/reject with history display |
|
|
98
|
+
|
|
99
|
+
## Key Rules
|
|
100
|
+
|
|
101
|
+
- Approval processes cannot be created programmatically in Apex tests; deploy via metadata.
|
|
102
|
+
- Record locking is enforced at the UI/API level, not within Apex test context.
|
|
103
|
+
- Dependencies (users, queues, email templates) must exist in target org before deploying approval processes.
|
|
104
|
+
- Use Queues as approvers for vacation coverage; any queue member can approve.
|
|
105
|
+
- Use Flow-based dynamic approvers to route based on amount, region, or other criteria.
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Async Apex Patterns -- Reference
|
|
2
|
+
|
|
3
|
+
> Source: <https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_async_overview.htm>
|
|
4
|
+
> Also: <https://architect.salesforce.com/decision-guides/async-processing>
|
|
5
|
+
> Last verified: API v66.0, Spring '26 (2026-03-28)
|
|
6
|
+
|
|
7
|
+
## Pattern Summary
|
|
8
|
+
|
|
9
|
+
| Pattern | Interface / Annotation | Entry Point | Returns |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| **Future** | `@future` / `@future(callout=true)` | `MyClass.myMethod(args)` | `void` (no job ID) |
|
|
12
|
+
| **Queueable** | `Queueable` (+optional `Database.AllowsCallouts`) | `System.enqueueJob(new MyJob())` | `Id` (AsyncApexJob ID) |
|
|
13
|
+
| **Batch** | `Database.Batchable<SObject>` (+optional `Database.Stateful`, `Database.AllowsCallouts`) | `Database.executeBatch(new MyBatch(), scopeSize)` | `Id` (AsyncApexJob ID) |
|
|
14
|
+
| **Schedulable** | `Schedulable` | `System.schedule(name, cron, new MyJob())` | `Id` (CronTrigger ID) |
|
|
15
|
+
|
|
16
|
+
## Method Signatures
|
|
17
|
+
|
|
18
|
+
**@future** -- `@future public static void doWork(List<Id> ids) { }` / `@future(callout=true) public static void doCallout(String url) { }`
|
|
19
|
+
|
|
20
|
+
- Must be `static`. Return: `void` only. Params: **primitives and collections of primitives only** (no SObjects).
|
|
21
|
+
|
|
22
|
+
**Queueable** -- `public class MyJob implements Queueable { public void execute(QueueableContext ctx) { } }`
|
|
23
|
+
|
|
24
|
+
- Invoke: `Id jobId = System.enqueueJob(new MyJob());`
|
|
25
|
+
|
|
26
|
+
**Batch** -- `implements Database.Batchable<SObject>`
|
|
27
|
+
|
|
28
|
+
- `Database.QueryLocator start(Database.BatchableContext bc)` -- up to **50M rows**
|
|
29
|
+
- `Iterable<SObject> start(Database.BatchableContext bc)` -- alternative, 50K row limit
|
|
30
|
+
- `void execute(Database.BatchableContext bc, List<SObject> scope)` -- scope 1-2000, default 200
|
|
31
|
+
- `void finish(Database.BatchableContext bc)`
|
|
32
|
+
- Invoke: `Database.executeBatch(new MyBatch(), 200);`
|
|
33
|
+
- Must be **outer class**. Add `Database.Stateful` to retain state across `execute()` calls.
|
|
34
|
+
|
|
35
|
+
**Schedulable** -- `public class MyJob implements Schedulable { public void execute(SchedulableContext ctx) { } }`
|
|
36
|
+
|
|
37
|
+
- Invoke: `System.schedule('Daily 5AM', '0 0 5 * * ?', new MyJob());`
|
|
38
|
+
- CRON format: `Seconds Minutes Hours Day Month DayOfWeek OptionalYear`
|
|
39
|
+
|
|
40
|
+
## Concurrency and Chaining Limits
|
|
41
|
+
|
|
42
|
+
| Constraint | Limit |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `@future` calls per sync transaction | 50 |
|
|
45
|
+
| `@future` from async context | **Not allowed** (cannot call future from future/batch) |
|
|
46
|
+
| Queueable jobs per sync transaction | 50 |
|
|
47
|
+
| Queueable jobs from async context | 1 (chaining) |
|
|
48
|
+
| Queueable chain depth (Dev/Trial orgs) | 5 |
|
|
49
|
+
| Queueable chain depth (Enterprise+) | Unlimited (configurable via `AsyncOptions`) |
|
|
50
|
+
| Concurrent active Batch jobs | 5 |
|
|
51
|
+
| Batch jobs in flex queue | 100 |
|
|
52
|
+
| Scheduled jobs per org | 100 |
|
|
53
|
+
| Daily async method executions | max(250,000, user_licenses x 200) |
|
|
54
|
+
|
|
55
|
+
## Queueable Advanced Features (API v50.0+)
|
|
56
|
+
|
|
57
|
+
**AsyncOptions** -- pass as second arg to `System.enqueueJob(job, opts)`:
|
|
58
|
+
|
|
59
|
+
- `opts.MinimumQueueableDelayInMinutes` -- 0-10 minutes
|
|
60
|
+
- `opts.MaximumQueueableStackDepth` -- cap chain depth
|
|
61
|
+
- `opts.DuplicateSignature` -- `new QueueableDuplicateSignature.Builder().addId(id).build()`
|
|
62
|
+
|
|
63
|
+
**AsyncInfo** -- runtime introspection:
|
|
64
|
+
|
|
65
|
+
- `AsyncInfo.getCurrentQueueableStackDepth()`, `.getMaximumQueueableStackDepth()`, `.hasMaxStackDepth()`
|
|
66
|
+
|
|
67
|
+
**Transaction Finalizers** -- `implements Finalizer` with `void execute(FinalizerContext ctx)`:
|
|
68
|
+
|
|
69
|
+
- Attach inside Queueable: `System.attachFinalizer(new MyFinalizer());`
|
|
70
|
+
- `ctx.getResult()` returns `SUCCESS` or `UNHANDLED_EXCEPTION`; `ctx.getAsyncApexJobId()` returns parent job ID.
|
|
71
|
+
- Runs after Queueable completes (success **or** failure). Can catch `System.LimitException` (normally uncatchable).
|
|
72
|
+
- Can enqueue a new Queueable for retry (max 5 consecutive retries recommended).
|
|
73
|
+
|
|
74
|
+
## Governor Limit Differences (Sync vs Async)
|
|
75
|
+
|
|
76
|
+
See `GOVERNOR_LIMITS.md` for full table. Key elevated limits in async context:
|
|
77
|
+
|
|
78
|
+
| Resource | Synchronous | Async (@future / Queueable / Batch) |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| SOQL queries | 100 | 200 |
|
|
81
|
+
| CPU time | 10,000 ms | 60,000 ms |
|
|
82
|
+
| Heap size | 6 MB | 12 MB |
|
|
83
|
+
|
|
84
|
+
DML, callouts, and SOQL row limits remain **unchanged** between sync and async.
|
|
85
|
+
|
|
86
|
+
## Decision Matrix
|
|
87
|
+
|
|
88
|
+
| Criterion | @future | Queueable | Batch | Schedulable |
|
|
89
|
+
|---|---|---|---|---|
|
|
90
|
+
| **Record volume** | Small | Small-Medium | Large (up to 50M) | N/A (delegates) |
|
|
91
|
+
| **Complex types as input** | No (primitives only) | Yes | Yes | N/A |
|
|
92
|
+
| **Job monitoring** | No | Yes (job ID) | Yes (job ID) | Yes (cron ID) |
|
|
93
|
+
| **Chaining** | No | Yes (1 per async) | No | No |
|
|
94
|
+
| **Callouts** | `@future(callout=true)` | `Database.AllowsCallouts` | `Database.AllowsCallouts` | No (sync context) |
|
|
95
|
+
| **Error recovery** | None | Transaction Finalizers | `finish()` method | None |
|
|
96
|
+
| **Execution timing** | ASAP, no SLA | ASAP + optional delay (0-10 min) | Queued, off-peak | Cron schedule |
|
|
97
|
+
| **Typical use case** | Simple fire-and-forget | Callouts, chained steps | Data cleansing, migration | Daily/weekly maintenance |
|
|
98
|
+
|
|
99
|
+
**Default recommendation (Spring '26):** Use **Queueable** unless you need Batch's 50M-row capacity or Schedulable's cron timing. `@future` is legacy; Queueable supersedes it in all scenarios.
|
|
100
|
+
|
|
101
|
+
## Error Recovery Patterns
|
|
102
|
+
|
|
103
|
+
### Transaction Finalizer Retry
|
|
104
|
+
|
|
105
|
+
Finalizers run after a Queueable completes — even on `System.LimitException`. Use for retry with backoff.
|
|
106
|
+
|
|
107
|
+
```apex
|
|
108
|
+
public class RetryableJob implements Queueable {
|
|
109
|
+
private Integer attempt;
|
|
110
|
+
public RetryableJob(Integer attempt) { this.attempt = attempt; }
|
|
111
|
+
|
|
112
|
+
public void execute(QueueableContext ctx) {
|
|
113
|
+
System.attachFinalizer(new RetryFinalizer(attempt));
|
|
114
|
+
// ... main work ...
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public class RetryFinalizer implements Finalizer {
|
|
119
|
+
private Integer attempt;
|
|
120
|
+
public RetryFinalizer(Integer attempt) { this.attempt = attempt; }
|
|
121
|
+
|
|
122
|
+
public void execute(FinalizerContext ctx) {
|
|
123
|
+
if (ctx.getResult() == ParentJobResult.UNHANDLED_EXCEPTION && attempt < 3) {
|
|
124
|
+
System.enqueueJob(new RetryableJob(attempt + 1));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Platform Event Partial Publish Handling
|
|
131
|
+
|
|
132
|
+
`EventBus.publish()` returns a list of `Database.SaveResult`. Check each for failures.
|
|
133
|
+
|
|
134
|
+
```apex
|
|
135
|
+
List<Order_Event__e> events = new List<Order_Event__e>{ /* ... */ };
|
|
136
|
+
List<Database.SaveResult> results = EventBus.publish(events);
|
|
137
|
+
for (Integer i = 0; i < results.size(); i++) {
|
|
138
|
+
if (!results[i].isSuccess()) {
|
|
139
|
+
for (Database.Error err : results[i].getErrors()) {
|
|
140
|
+
Logger.error('Event publish failed at index ' + i + ': ' + err.getMessage());
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### EventBus.RetryableException in Subscribers
|
|
147
|
+
|
|
148
|
+
Throw `EventBus.RetryableException` in an event trigger subscriber to request platform retry (up to 9 retries over 24 hours).
|
|
149
|
+
|
|
150
|
+
```apex
|
|
151
|
+
trigger OrderEventTrigger on Order_Event__e (after insert) {
|
|
152
|
+
for (Order_Event__e evt : Trigger.New) {
|
|
153
|
+
try {
|
|
154
|
+
OrderProcessor.process(evt);
|
|
155
|
+
} catch (CalloutException e) {
|
|
156
|
+
// Transient error — request retry
|
|
157
|
+
throw new EventBus.RetryableException(e.getMessage());
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The platform automatically sets the replay pointer back and re-delivers the event batch. Do NOT throw `RetryableException` for permanent failures (bad data, missing config) — those will retry forever until the 24-hour window expires.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<!-- Source: https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/intro_framework.htm -->
|
|
2
|
+
<!-- Last verified: API v66.0 — 2026-03-29 -->
|
|
3
|
+
<!-- WARNING: Web fetch of canonical URL failed (JS-rendered page). Facts extracted from SCC skill sf-aura-development. Verify against official docs before relying on framework details. -->
|
|
4
|
+
|
|
5
|
+
# Aura Components Reference
|
|
6
|
+
|
|
7
|
+
## Status
|
|
8
|
+
|
|
9
|
+
Aura is in **maintenance mode** (since LWC introduction, 2019). Use LWC for all new development.
|
|
10
|
+
|
|
11
|
+
## Component Bundle Structure
|
|
12
|
+
|
|
13
|
+
| File | Extension | Required | Purpose |
|
|
14
|
+
|------|-----------|----------|---------|
|
|
15
|
+
| Component markup | `.cmp` | Yes | XML template with markup and attributes |
|
|
16
|
+
| Client-side controller | `Controller.js` | No | Action handlers (thin; delegates to helper) |
|
|
17
|
+
| Helper | `Helper.js` | No | Reusable business logic |
|
|
18
|
+
| Renderer | `Renderer.js` | No | Custom rendering overrides (rare) |
|
|
19
|
+
| Styles | `.css` | No | Component-scoped CSS |
|
|
20
|
+
| Design | `.design` | No | App Builder property editor config |
|
|
21
|
+
| Documentation | `.auradoc` | No | Displayed in Component Library |
|
|
22
|
+
| SVG icon | `.svg` | No | Custom icon (60x60) |
|
|
23
|
+
| Metadata | `.cmp-meta.xml` | Yes (deploy) | apiVersion, description |
|
|
24
|
+
|
|
25
|
+
Bundle path: `force-app/main/default/aura/<ComponentName>/`
|
|
26
|
+
|
|
27
|
+
## Attribute Types
|
|
28
|
+
|
|
29
|
+
| Category | Types |
|
|
30
|
+
|----------|-------|
|
|
31
|
+
| Primitive | `String`, `Integer`, `Decimal`, `Boolean`, `Date` |
|
|
32
|
+
| Collection | `String[]`, `Account[]`, `Map` |
|
|
33
|
+
| SObject | Any SObject name (e.g., `Contact`, `Account`) |
|
|
34
|
+
| Generic | `Object` (use sparingly) |
|
|
35
|
+
|
|
36
|
+
## Attribute Rules
|
|
37
|
+
|
|
38
|
+
- Always provide `default` for collection types to avoid null reference errors.
|
|
39
|
+
- Use `access="private"` for internal-only attributes.
|
|
40
|
+
- Use `type="Object"` sparingly; prefer typed attributes.
|
|
41
|
+
|
|
42
|
+
## Event Model
|
|
43
|
+
|
|
44
|
+
| Aspect | Component Event | Application Event |
|
|
45
|
+
|--------|----------------|-------------------|
|
|
46
|
+
| Type attribute | `type="COMPONENT"` | `type="APPLICATION"` |
|
|
47
|
+
| Scope | Parent-child only | Any component on the page |
|
|
48
|
+
| Propagation | Bubbles up containment hierarchy | Broadcast to all handlers |
|
|
49
|
+
| Registration | `<aura:registerEvent>` in child | `<aura:registerEvent>` in sender |
|
|
50
|
+
| Handling | `<aura:handler>` in parent | `<aura:handler>` anywhere |
|
|
51
|
+
| Performance | Lightweight | Heavier (all handlers evaluated) |
|
|
52
|
+
| LWC equivalent | `CustomEvent` | Lightning Message Service |
|
|
53
|
+
|
|
54
|
+
## Lifecycle Handlers
|
|
55
|
+
|
|
56
|
+
| Handler | Fires When | LWC Equivalent |
|
|
57
|
+
|---------|-----------|----------------|
|
|
58
|
+
| `aura:handler name="init"` | Component initialized | `connectedCallback()` |
|
|
59
|
+
| `aura:handler name="render"` | After render | `renderedCallback()` |
|
|
60
|
+
| `aura:handler name="destroy"` | Component destroyed | `disconnectedCallback()` |
|
|
61
|
+
| `aura:handler name="change"` | Attribute value changes | Reactive `@api` setter |
|
|
62
|
+
|
|
63
|
+
## Server-Side Communication
|
|
64
|
+
|
|
65
|
+
| Pattern | Code | Description |
|
|
66
|
+
|---------|------|-------------|
|
|
67
|
+
| Enqueue action | `$A.enqueueAction(action)` | All Apex calls go through the action queue |
|
|
68
|
+
| Set parameters | `action.setParams({...})` | Pass arguments to `@AuraEnabled` method |
|
|
69
|
+
| Callback states | `SUCCESS`, `ERROR`, `INCOMPLETE` | Always handle all three |
|
|
70
|
+
| Storable action | `action.setStorable()` | Client-side caching; only for `cacheable=true` methods |
|
|
71
|
+
| Background action | `action.setBackground()` | Lower priority; does not block UI queue |
|
|
72
|
+
|
|
73
|
+
## Storable Action Rules
|
|
74
|
+
|
|
75
|
+
- Only use on `@AuraEnabled(cacheable=true)` methods.
|
|
76
|
+
- Callback may fire twice: once from cache, once from server.
|
|
77
|
+
- Never use for DML operations.
|
|
78
|
+
- Cache key = action name + parameters.
|
|
79
|
+
|
|
80
|
+
## Security Model
|
|
81
|
+
|
|
82
|
+
| Layer | Scope |
|
|
83
|
+
|-------|-------|
|
|
84
|
+
| Locker Service (legacy) | DOM isolation via SecureElement wrappers; namespace-scoped `document.cookie` |
|
|
85
|
+
| Lightning Web Security (current) | Standard APIs with fewer restrictions |
|
|
86
|
+
| CSP restrictions | No `eval()`, no `new Function()`, no inline `onclick` attributes |
|
|
87
|
+
| `$A.getCallback()` | Required for all async code outside Aura lifecycle (setTimeout, Promises) |
|
|
88
|
+
|
|
89
|
+
## Key Framework Objects
|
|
90
|
+
|
|
91
|
+
| Object | Purpose |
|
|
92
|
+
|--------|---------|
|
|
93
|
+
| `$A` | Framework namespace; `$A.enqueueAction()`, `$A.get()`, `$A.getCallback()`, `$A.createComponent()` |
|
|
94
|
+
| `component` | Current component instance; `.get()`, `.set()`, `.find()`, `.getEvent()`, `.isValid()`, `.getGlobalId()` |
|
|
95
|
+
| `event` | Event object; `.getParam()`, `.setParams()`, `.fire()`, `.stopPropagation()`, `.getPhase()`, `.getSource()` |
|
|
96
|
+
| `helper` | Shared across all instances of the component on the same page |
|
|
97
|
+
|
|
98
|
+
## Common Interfaces
|
|
99
|
+
|
|
100
|
+
| Interface | Purpose |
|
|
101
|
+
|-----------|---------|
|
|
102
|
+
| `force:appHostable` | Can be used as a Lightning app tab |
|
|
103
|
+
| `flexipage:availableForAllPageTypes` | Available in App Builder on all page types |
|
|
104
|
+
| `force:hasRecordId` | Receives record ID from record pages |
|
|
105
|
+
| `force:hasSObjectName` | Receives object API name |
|
|
106
|
+
|
|
107
|
+
## Aura-to-LWC Migration Map
|
|
108
|
+
|
|
109
|
+
| Aura | LWC |
|
|
110
|
+
|------|-----|
|
|
111
|
+
| `aura:attribute` | `@api` property |
|
|
112
|
+
| `aura:handler name="init"` | `connectedCallback()` |
|
|
113
|
+
| `aura:handler name="render"` | `renderedCallback()` |
|
|
114
|
+
| `aura:handler name="destroy"` | `disconnectedCallback()` |
|
|
115
|
+
| `aura:if` / `aura:set else` | `lwc:if` / `lwc:elseif` / `lwc:else` |
|
|
116
|
+
| `aura:iteration` | `for:each` / `iterator` (requires `key`) |
|
|
117
|
+
| `$A.enqueueAction()` | `@wire` or imperative `async/await` import |
|
|
118
|
+
| `component.get("v.attr")` | `this.propertyName` |
|
|
119
|
+
| `component.set("v.attr", val)` | `this.propertyName = val` (reactive) |
|
|
120
|
+
| `component.find("auraId")` | `this.template.querySelector()` |
|
|
121
|
+
| `action.setStorable()` | `@wire` with `cacheable=true` |
|
|
122
|
+
| Helper.js (separate file) | Class methods in single JS file |
|
|
123
|
+
| `$A.getCallback()` | Not needed (LWC handles async natively) |
|
|
124
|
+
| `$A.createComponent()` | `lwc:component` with `lwc:is` (API 59+) |
|
|
125
|
+
| Application events | Lightning Message Service |
|
|
126
|
+
| Component events | `CustomEvent` |
|
|
127
|
+
| Locker Service | Lightning Web Security |
|
|
128
|
+
| `aura:dependency` | ES module `import` |
|
|
129
|
+
|
|
130
|
+
## Migration Strategy (ordered)
|
|
131
|
+
|
|
132
|
+
| Step | Action |
|
|
133
|
+
|------|--------|
|
|
134
|
+
| 1 | Inventory all Aura components, dependencies, and usage locations |
|
|
135
|
+
| 2 | Prioritize leaf components (no child Aura dependencies) |
|
|
136
|
+
| 3 | Wrap: replace Aura parents with LWC, keep Aura children via interop |
|
|
137
|
+
| 4 | Convert: rewrite using LWC patterns |
|
|
138
|
+
| 5 | Test: validate behavior parity |
|
|
139
|
+
| 6 | Deploy: replace Aura references on pages/apps |
|
|
140
|
+
|
|
141
|
+
## LWC-in-Aura Interop Rules
|
|
142
|
+
|
|
143
|
+
- LWC components embed directly in Aura markup: `<c:lwcChild record-id="{!v.recordId}" />`
|
|
144
|
+
- Aura passes data to LWC via attributes mapped to `@api` properties.
|
|
145
|
+
- LWC sends data to Aura via `CustomEvent`; Aura reads via `event.getParam("detail")`.
|
|
146
|
+
- Pubsub pattern is deprecated; use Lightning Message Service for cross-framework communication.
|