@salesforce/afv-skills 1.8.0 → 1.9.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.
Files changed (488) hide show
  1. package/package.json +1 -1
  2. package/skills/activating-datacloud/CREDITS.md +5 -0
  3. package/skills/activating-datacloud/README.md +39 -0
  4. package/skills/activating-datacloud/SKILL.md +118 -0
  5. package/skills/analyzing-omnistudio-dependencies/CREDITS.md +5 -0
  6. package/skills/analyzing-omnistudio-dependencies/SKILL.md +477 -0
  7. package/skills/analyzing-omnistudio-dependencies/references/dependency-patterns.md +508 -0
  8. package/skills/analyzing-omnistudio-dependencies/references/namespace-guide.md +300 -0
  9. package/skills/building-omnistudio-callable-apex/CREDITS.md +9 -0
  10. package/skills/building-omnistudio-callable-apex/README.md +80 -0
  11. package/skills/building-omnistudio-callable-apex/SKILL.md +276 -0
  12. package/skills/building-omnistudio-callable-apex/assets/pattern_callable_openinterface.cls +40 -0
  13. package/skills/building-omnistudio-callable-apex/assets/pattern_callable_vanilla.cls +32 -0
  14. package/skills/building-omnistudio-callable-apex/assets/pattern_migration.cls +54 -0
  15. package/skills/building-omnistudio-callable-apex/assets/pattern_openinterface.cls +45 -0
  16. package/skills/building-omnistudio-callable-apex/assets/pattern_test_class.cls +65 -0
  17. package/skills/building-omnistudio-callable-apex/examples/Test_QuoteByProductCallable/IndustriesCallableException.cls +7 -0
  18. package/skills/building-omnistudio-callable-apex/examples/Test_QuoteByProductCallable/Industries_QuoteByProductCallable.cls +115 -0
  19. package/skills/building-omnistudio-callable-apex/examples/Test_QuoteByProductCallable/Industries_QuoteByProductCallableTest.cls +189 -0
  20. package/skills/building-omnistudio-callable-apex/examples/Test_QuoteByProductCallable/TRANSCRIPT.md +115 -0
  21. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterface2Conversion/IndustriesCallableException.cls +7 -0
  22. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterface2Conversion/MyCustomCallable.cls +74 -0
  23. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterface2Conversion/MyCustomCallableTest.cls +146 -0
  24. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterface2Conversion/MyCustomRemoteClass.cls +16 -0
  25. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterface2Conversion/TRANSCRIPT.md +120 -0
  26. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterfaceConversion/IndustriesCallableException.cls +7 -0
  27. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterfaceConversion/MyCustomCallable.cls +73 -0
  28. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterfaceConversion/MyCustomCallableTest.cls +128 -0
  29. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterfaceConversion/MyCustomVlocityOpenInterface2.cls +23 -0
  30. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterfaceConversion/TRANSCRIPT.md +75 -0
  31. package/skills/building-omnistudio-datamapper/CREDITS.md +5 -0
  32. package/skills/building-omnistudio-datamapper/SKILL.md +270 -0
  33. package/skills/building-omnistudio-datamapper/assets/completion-summary-template.md +28 -0
  34. package/skills/building-omnistudio-datamapper/assets/omni-data-transform-extract.json +6 -0
  35. package/skills/building-omnistudio-datamapper/assets/omni-data-transform-item.json +12 -0
  36. package/skills/building-omnistudio-datamapper/assets/omni-data-transform-load.json +6 -0
  37. package/skills/building-omnistudio-datamapper/assets/omni-data-transform-transform.json +6 -0
  38. package/skills/building-omnistudio-datamapper/references/best-practices.md +277 -0
  39. package/skills/building-omnistudio-datamapper/references/naming-conventions.md +145 -0
  40. package/skills/building-omnistudio-flexcard/CREDITS.md +5 -0
  41. package/skills/building-omnistudio-flexcard/SKILL.md +325 -0
  42. package/skills/building-omnistudio-flexcard/assets/omni-ui-card.json +10 -0
  43. package/skills/building-omnistudio-flexcard/references/best-practices.md +291 -0
  44. package/skills/building-omnistudio-flexcard/references/data-binding-guide.md +311 -0
  45. package/skills/building-omnistudio-flexcard/references/scoring-rubric.md +66 -0
  46. package/skills/building-omnistudio-flexcard/scripts/flexcard-commands.sh +24 -0
  47. package/skills/building-omnistudio-integration-procedure/CREDITS.md +5 -0
  48. package/skills/building-omnistudio-integration-procedure/SKILL.md +275 -0
  49. package/skills/building-omnistudio-integration-procedure/assets/omni-process-element-dr-extract.json +10 -0
  50. package/skills/building-omnistudio-integration-procedure/assets/omni-process-element-set-values.json +10 -0
  51. package/skills/building-omnistudio-integration-procedure/assets/omni-process-ip.json +12 -0
  52. package/skills/building-omnistudio-integration-procedure/assets/scoring-report-format.txt +14 -0
  53. package/skills/building-omnistudio-integration-procedure/references/best-practices.md +388 -0
  54. package/skills/building-omnistudio-integration-procedure/references/element-types.md +588 -0
  55. package/skills/building-omnistudio-integration-procedure/scripts/cli-commands.sh +18 -0
  56. package/skills/building-omnistudio-omniscript/CREDITS.md +5 -0
  57. package/skills/building-omnistudio-omniscript/SKILL.md +367 -0
  58. package/skills/building-omnistudio-omniscript/assets/omni-process-element-step.json +10 -0
  59. package/skills/building-omnistudio-omniscript/assets/omni-process-element-text-block.json +11 -0
  60. package/skills/building-omnistudio-omniscript/assets/omni-process-omniscript.json +12 -0
  61. package/skills/building-omnistudio-omniscript/references/best-practices.md +480 -0
  62. package/skills/building-omnistudio-omniscript/references/element-types.md +1172 -0
  63. package/skills/building-omnistudio-omniscript/scripts/check-duplicate-omniscript.sh +13 -0
  64. package/skills/building-omnistudio-omniscript/scripts/cli-reference.sh +21 -0
  65. package/skills/building-omnistudio-omniscript/scripts/deploy-omniscript.sh +29 -0
  66. package/skills/building-sf-integrations/CREDITS.md +5 -0
  67. package/skills/building-sf-integrations/README.md +95 -0
  68. package/skills/building-sf-integrations/SKILL.md +192 -0
  69. package/skills/building-sf-integrations/assets/callouts/callout-retry-handler.cls +167 -0
  70. package/skills/building-sf-integrations/assets/callouts/http-response-handler.cls +257 -0
  71. package/skills/building-sf-integrations/assets/callouts/rest-queueable-callout.cls +262 -0
  72. package/skills/building-sf-integrations/assets/callouts/rest-sync-callout.cls +211 -0
  73. package/skills/building-sf-integrations/assets/cdc/cdc-handler.cls +246 -0
  74. package/skills/building-sf-integrations/assets/cdc/cdc-subscriber-trigger.trigger +139 -0
  75. package/skills/building-sf-integrations/assets/endpoint-security/example.cspTrustedSite-meta.xml +58 -0
  76. package/skills/building-sf-integrations/assets/endpoint-security/example.remoteSite-meta.xml +39 -0
  77. package/skills/building-sf-integrations/assets/external-credentials/jwt-external-credential.externalCredential-meta.xml +90 -0
  78. package/skills/building-sf-integrations/assets/external-credentials/oauth-external-credential.externalCredential-meta.xml +87 -0
  79. package/skills/building-sf-integrations/assets/external-services/external-service-operations.md +221 -0
  80. package/skills/building-sf-integrations/assets/external-services/openapi-registration.externalServiceRegistration-meta.xml +193 -0
  81. package/skills/building-sf-integrations/assets/named-credentials/certificate-auth.namedCredential-meta.xml +62 -0
  82. package/skills/building-sf-integrations/assets/named-credentials/custom-auth.namedCredential-meta.xml +71 -0
  83. package/skills/building-sf-integrations/assets/named-credentials/oauth-client-credentials.namedCredential-meta.xml +51 -0
  84. package/skills/building-sf-integrations/assets/named-credentials/oauth-jwt-bearer.namedCredential-meta.xml +67 -0
  85. package/skills/building-sf-integrations/assets/platform-events/event-publisher.cls +191 -0
  86. package/skills/building-sf-integrations/assets/platform-events/event-subscriber-action.cls +295 -0
  87. package/skills/building-sf-integrations/assets/platform-events/event-subscriber-trigger.trigger +108 -0
  88. package/skills/building-sf-integrations/assets/platform-events/platform-event-definition.object-meta.xml +124 -0
  89. package/skills/building-sf-integrations/assets/soap/soap-callout-service.cls +186 -0
  90. package/skills/building-sf-integrations/assets/soap/wsdl2apex-guide.md +213 -0
  91. package/skills/building-sf-integrations/hooks/scripts/suggest_credential_setup.py +271 -0
  92. package/skills/building-sf-integrations/hooks/scripts/validate_integration.py +363 -0
  93. package/skills/building-sf-integrations/references/callout-patterns.md +719 -0
  94. package/skills/building-sf-integrations/references/cdc-guide.md +288 -0
  95. package/skills/building-sf-integrations/references/cli-reference.md +94 -0
  96. package/skills/building-sf-integrations/references/event-driven-architecture-guide.md +266 -0
  97. package/skills/building-sf-integrations/references/event-patterns.md +838 -0
  98. package/skills/building-sf-integrations/references/external-services-guide.md +303 -0
  99. package/skills/building-sf-integrations/references/messaging-api-v2.md +609 -0
  100. package/skills/building-sf-integrations/references/named-credentials-automation.md +201 -0
  101. package/skills/building-sf-integrations/references/named-credentials-guide.md +173 -0
  102. package/skills/building-sf-integrations/references/platform-events-guide.md +288 -0
  103. package/skills/building-sf-integrations/references/rest-callout-patterns.md +288 -0
  104. package/skills/building-sf-integrations/references/scoring-rubric.md +59 -0
  105. package/skills/building-sf-integrations/references/security-best-practices.md +248 -0
  106. package/skills/building-sf-integrations/scripts/README.md +100 -0
  107. package/skills/building-sf-integrations/scripts/configure-named-credential.sh +236 -0
  108. package/skills/building-sf-integrations/scripts/set-api-credential.sh +146 -0
  109. package/skills/building-sf-integrations/scripts/templates/setup-credentials-with-csp.sh +158 -0
  110. package/skills/configuring-connected-apps/CREDITS.md +3 -0
  111. package/skills/configuring-connected-apps/README.md +99 -0
  112. package/skills/configuring-connected-apps/SKILL.md +224 -0
  113. package/skills/configuring-connected-apps/assets/connected-app-basic.xml +29 -0
  114. package/skills/configuring-connected-apps/assets/connected-app-canvas.xml +62 -0
  115. package/skills/configuring-connected-apps/assets/connected-app-jwt.xml +49 -0
  116. package/skills/configuring-connected-apps/assets/connected-app-oauth.xml +65 -0
  117. package/skills/configuring-connected-apps/assets/eca-global-oauth.xml +36 -0
  118. package/skills/configuring-connected-apps/assets/eca-oauth-settings.xml +36 -0
  119. package/skills/configuring-connected-apps/assets/eca-policies.xml +36 -0
  120. package/skills/configuring-connected-apps/assets/external-client-app.xml +35 -0
  121. package/skills/configuring-connected-apps/references/example-usage.md +256 -0
  122. package/skills/configuring-connected-apps/references/migration-guide.md +328 -0
  123. package/skills/configuring-connected-apps/references/oauth-flows-reference.md +660 -0
  124. package/skills/configuring-connected-apps/references/security-checklist.md +209 -0
  125. package/skills/configuring-connected-apps/references/testing-validation-guide.md +275 -0
  126. package/skills/connecting-datacloud/CREDITS.md +5 -0
  127. package/skills/connecting-datacloud/README.md +59 -0
  128. package/skills/connecting-datacloud/SKILL.md +155 -0
  129. package/skills/connecting-datacloud/examples/connections/heroku-postgres.json +15 -0
  130. package/skills/connecting-datacloud/examples/connections/ingest-api-connection.json +5 -0
  131. package/skills/connecting-datacloud/examples/connections/ingest-api-schema.json +31 -0
  132. package/skills/connecting-datacloud/examples/connections/redshift.json +16 -0
  133. package/skills/connecting-datacloud/examples/connections/sharepoint-unstructured.json +20 -0
  134. package/skills/connecting-datacloud/examples/connections/snowflake-connection.json +42 -0
  135. package/skills/debugging-apex-logs/CREDITS.md +22 -0
  136. package/skills/debugging-apex-logs/README.md +74 -0
  137. package/skills/debugging-apex-logs/SKILL.md +172 -0
  138. package/skills/debugging-apex-logs/assets/benchmarking-template.cls +327 -0
  139. package/skills/debugging-apex-logs/assets/cpu-heap-optimization.cls +307 -0
  140. package/skills/debugging-apex-logs/assets/dml-in-loop-fix.cls +219 -0
  141. package/skills/debugging-apex-logs/assets/null-pointer-fix.cls +252 -0
  142. package/skills/debugging-apex-logs/assets/soql-in-loop-fix.cls +157 -0
  143. package/skills/debugging-apex-logs/references/analysis-playbook.md +53 -0
  144. package/skills/debugging-apex-logs/references/benchmarking-guide.md +287 -0
  145. package/skills/debugging-apex-logs/references/cli-commands.md +368 -0
  146. package/skills/debugging-apex-logs/references/common-issues.md +68 -0
  147. package/skills/debugging-apex-logs/references/debug-log-reference.md +328 -0
  148. package/skills/debugging-apex-logs/references/log-analysis-tools.md +248 -0
  149. package/skills/debugging-apex-logs/references/scoring-rubric.md +21 -0
  150. package/skills/deploying-metadata/CREDITS.md +25 -0
  151. package/skills/deploying-metadata/README.md +104 -0
  152. package/skills/deploying-metadata/SKILL.md +214 -0
  153. package/skills/deploying-metadata/assets/destructiveChanges.xml +143 -0
  154. package/skills/deploying-metadata/assets/package.xml +121 -0
  155. package/skills/deploying-metadata/references/agent-deployment-guide.md +628 -0
  156. package/skills/deploying-metadata/references/deploy.sh +73 -0
  157. package/skills/deploying-metadata/references/deployment-report-template.md +89 -0
  158. package/skills/deploying-metadata/references/deployment-workflows.md +395 -0
  159. package/skills/deploying-metadata/references/orchestration.md +183 -0
  160. package/skills/deploying-metadata/references/trigger-deployment-safety.md +376 -0
  161. package/skills/deploying-omnistudio-datapacks/CREDITS.md +5 -0
  162. package/skills/deploying-omnistudio-datapacks/README.md +88 -0
  163. package/skills/deploying-omnistudio-datapacks/SKILL.md +174 -0
  164. package/skills/deploying-omnistudio-datapacks/examples/business-internet-plus-bundle/TRANSCRIPT.md +124 -0
  165. package/skills/deploying-omnistudio-datapacks/examples/business-internet-plus-bundle/deploy-business-internet-plus-bundle.yaml +11 -0
  166. package/skills/deploying-omnistudio-datapacks/examples/business-internet-plus-bundle-deploy/TRANSCRIPT.md +142 -0
  167. package/skills/deploying-omnistudio-datapacks/examples/business-internet-plus-bundle-deploy/deploy-business-internet-plus-bundle.yaml +10 -0
  168. package/skills/deploying-omnistudio-datapacks/references/job-file-template.md +42 -0
  169. package/skills/deploying-omnistudio-datapacks/references/troubleshooting-matrix.md +24 -0
  170. package/skills/developing-agentforce/assets/metadata/http-callout-flow.flow-meta.xml +1 -1
  171. package/skills/developing-agentforce/references/actions-reference.md +8 -8
  172. package/skills/fetching-salesforce-docs/README.md +66 -0
  173. package/skills/fetching-salesforce-docs/SKILL.md +209 -0
  174. package/skills/fetching-salesforce-docs/requirements.txt +2 -0
  175. package/skills/fetching-salesforce-docs/scripts/extract_help_salesforce.py +497 -0
  176. package/skills/fetching-salesforce-docs/scripts/extract_salesforce_doc.py +357 -0
  177. package/skills/fetching-salesforce-docs/scripts/runtime_bootstrap.py +58 -0
  178. package/skills/generating-apex/CREDITS.md +1 -26
  179. package/skills/generating-apex-test/CREDITS.md +2 -27
  180. package/skills/generating-lwc-components/CREDITS.md +5 -0
  181. package/skills/generating-lwc-components/README.md +126 -0
  182. package/skills/generating-lwc-components/SKILL.md +191 -0
  183. package/skills/generating-lwc-components/assets/apex-controller/LwcController.cls +327 -0
  184. package/skills/generating-lwc-components/assets/basic-component/basicComponent.css +72 -0
  185. package/skills/generating-lwc-components/assets/basic-component/basicComponent.html +111 -0
  186. package/skills/generating-lwc-components/assets/basic-component/basicComponent.js +163 -0
  187. package/skills/generating-lwc-components/assets/basic-component/basicComponent.js-meta.xml +137 -0
  188. package/skills/generating-lwc-components/assets/datatable-component/datatableComponent.html +111 -0
  189. package/skills/generating-lwc-components/assets/datatable-component/datatableComponent.js +367 -0
  190. package/skills/generating-lwc-components/assets/flow-screen-component/flowScreenComponent.css +63 -0
  191. package/skills/generating-lwc-components/assets/flow-screen-component/flowScreenComponent.html +154 -0
  192. package/skills/generating-lwc-components/assets/flow-screen-component/flowScreenComponent.js +348 -0
  193. package/skills/generating-lwc-components/assets/flow-screen-component/flowScreenComponent.js-meta.xml +87 -0
  194. package/skills/generating-lwc-components/assets/form-component/formComponent.html +165 -0
  195. package/skills/generating-lwc-components/assets/form-component/formComponent.js +275 -0
  196. package/skills/generating-lwc-components/assets/graphql-component/graphqlComponent.html +100 -0
  197. package/skills/generating-lwc-components/assets/graphql-component/graphqlComponent.js +336 -0
  198. package/skills/generating-lwc-components/assets/jest-test/componentName.test.js.example +371 -0
  199. package/skills/generating-lwc-components/assets/message-channel/RecordSelected.messageChannel-meta.xml +71 -0
  200. package/skills/generating-lwc-components/assets/message-channel/lmsPublisher.js +103 -0
  201. package/skills/generating-lwc-components/assets/message-channel/lmsSubscriber.js +181 -0
  202. package/skills/generating-lwc-components/assets/modal-component/modalComponent.html +85 -0
  203. package/skills/generating-lwc-components/assets/modal-component/modalComponent.js +199 -0
  204. package/skills/generating-lwc-components/assets/record-picker/recordPicker.html +55 -0
  205. package/skills/generating-lwc-components/assets/record-picker/recordPicker.js +199 -0
  206. package/skills/generating-lwc-components/assets/state-store/store.js +282 -0
  207. package/skills/generating-lwc-components/assets/typescript-component/typescriptComponent.css +65 -0
  208. package/skills/generating-lwc-components/assets/typescript-component/typescriptComponent.html +95 -0
  209. package/skills/generating-lwc-components/assets/typescript-component/typescriptComponent.js-meta.xml +75 -0
  210. package/skills/generating-lwc-components/assets/typescript-component/typescriptComponent.test.ts.example +301 -0
  211. package/skills/generating-lwc-components/assets/typescript-component/typescriptComponent.ts +295 -0
  212. package/skills/generating-lwc-components/assets/workspace-api/workspaceComponent.html +71 -0
  213. package/skills/generating-lwc-components/assets/workspace-api/workspaceComponent.js +316 -0
  214. package/skills/generating-lwc-components/hooks/scripts/lwc-lsp-validate.py +295 -0
  215. package/skills/generating-lwc-components/hooks/scripts/post-tool-validate.py +347 -0
  216. package/skills/generating-lwc-components/hooks/scripts/slds_data/deprecated_patterns.json +74 -0
  217. package/skills/generating-lwc-components/hooks/scripts/slds_data/styling_hooks.json +111 -0
  218. package/skills/generating-lwc-components/hooks/scripts/slds_data/valid_slds_classes.json +127 -0
  219. package/skills/generating-lwc-components/hooks/scripts/slds_linter_wrapper.py +294 -0
  220. package/skills/generating-lwc-components/hooks/scripts/slds_rules/__init__.py +22 -0
  221. package/skills/generating-lwc-components/hooks/scripts/template_validator.py +332 -0
  222. package/skills/generating-lwc-components/hooks/scripts/validate_slds.py +595 -0
  223. package/skills/generating-lwc-components/references/accessibility-guide.md +843 -0
  224. package/skills/generating-lwc-components/references/advanced-features.md +108 -0
  225. package/skills/generating-lwc-components/references/async-notification-patterns.md +661 -0
  226. package/skills/generating-lwc-components/references/cli-commands.md +545 -0
  227. package/skills/generating-lwc-components/references/component-patterns.md +1476 -0
  228. package/skills/generating-lwc-components/references/flow-integration-guide.md +675 -0
  229. package/skills/generating-lwc-components/references/jest-testing.md +1011 -0
  230. package/skills/generating-lwc-components/references/lms-guide.md +860 -0
  231. package/skills/generating-lwc-components/references/lwc-best-practices.md +1310 -0
  232. package/skills/generating-lwc-components/references/performance-guide.md +861 -0
  233. package/skills/generating-lwc-components/references/scoring-and-testing.md +116 -0
  234. package/skills/generating-lwc-components/references/slds-blueprints.json +14389 -0
  235. package/skills/generating-lwc-components/references/slds-design-guide.md +166 -0
  236. package/skills/generating-lwc-components/references/state-management.md +642 -0
  237. package/skills/generating-lwc-components/references/template-anti-patterns.md +948 -0
  238. package/skills/generating-lwc-components/references/triangle-pattern.md +365 -0
  239. package/skills/generating-lwc-components/scripts/local-dev-preview.sh +34 -0
  240. package/skills/generating-mermaid-diagrams/CREDITS.md +46 -0
  241. package/skills/generating-mermaid-diagrams/README.md +114 -0
  242. package/skills/generating-mermaid-diagrams/SKILL.md +218 -0
  243. package/skills/generating-mermaid-diagrams/assets/agentforce/agent-flow.md +313 -0
  244. package/skills/generating-mermaid-diagrams/assets/architecture/system-landscape.md +351 -0
  245. package/skills/generating-mermaid-diagrams/assets/datamodel/b2b-commerce-erd.md +317 -0
  246. package/skills/generating-mermaid-diagrams/assets/datamodel/campaigns-erd.md +195 -0
  247. package/skills/generating-mermaid-diagrams/assets/datamodel/consent-erd.md +262 -0
  248. package/skills/generating-mermaid-diagrams/assets/datamodel/files-erd.md +266 -0
  249. package/skills/generating-mermaid-diagrams/assets/datamodel/forecasting-erd.md +261 -0
  250. package/skills/generating-mermaid-diagrams/assets/datamodel/fsl-erd.md +332 -0
  251. package/skills/generating-mermaid-diagrams/assets/datamodel/party-model-erd.md +237 -0
  252. package/skills/generating-mermaid-diagrams/assets/datamodel/quote-order-erd.md +277 -0
  253. package/skills/generating-mermaid-diagrams/assets/datamodel/revenue-cloud-erd.md +343 -0
  254. package/skills/generating-mermaid-diagrams/assets/datamodel/sales-cloud-erd.md +192 -0
  255. package/skills/generating-mermaid-diagrams/assets/datamodel/salesforce-erd.md +209 -0
  256. package/skills/generating-mermaid-diagrams/assets/datamodel/scheduler-erd.md +276 -0
  257. package/skills/generating-mermaid-diagrams/assets/datamodel/service-cloud-erd.md +217 -0
  258. package/skills/generating-mermaid-diagrams/assets/datamodel/territory-management-erd.md +241 -0
  259. package/skills/generating-mermaid-diagrams/assets/integration/api-sequence.md +387 -0
  260. package/skills/generating-mermaid-diagrams/assets/oauth/authorization-code-pkce.md +197 -0
  261. package/skills/generating-mermaid-diagrams/assets/oauth/authorization-code.md +152 -0
  262. package/skills/generating-mermaid-diagrams/assets/oauth/client-credentials.md +233 -0
  263. package/skills/generating-mermaid-diagrams/assets/oauth/device-authorization.md +295 -0
  264. package/skills/generating-mermaid-diagrams/assets/oauth/jwt-bearer.md +256 -0
  265. package/skills/generating-mermaid-diagrams/assets/oauth/refresh-token.md +281 -0
  266. package/skills/generating-mermaid-diagrams/assets/oauth/user-agent-social-sign-on.md +281 -0
  267. package/skills/generating-mermaid-diagrams/assets/role-hierarchy/user-hierarchy.md +322 -0
  268. package/skills/generating-mermaid-diagrams/references/color-palette.md +464 -0
  269. package/skills/generating-mermaid-diagrams/references/diagram-conventions.md +313 -0
  270. package/skills/generating-mermaid-diagrams/references/erd-conventions.md +320 -0
  271. package/skills/generating-mermaid-diagrams/references/mermaid-reference.md +434 -0
  272. package/skills/generating-mermaid-diagrams/references/mermaid-styling.md +81 -0
  273. package/skills/generating-mermaid-diagrams/references/preview-guide.md +49 -0
  274. package/skills/generating-mermaid-diagrams/references/usage-examples.md +340 -0
  275. package/skills/generating-mermaid-diagrams/scripts/README.md +160 -0
  276. package/skills/generating-mermaid-diagrams/scripts/mermaid_preview.py +654 -0
  277. package/skills/generating-mermaid-diagrams/scripts/query-org-metadata.py +293 -0
  278. package/skills/generating-visual-diagrams/CREDITS.md +80 -0
  279. package/skills/generating-visual-diagrams/README.md +83 -0
  280. package/skills/generating-visual-diagrams/SKILL.md +208 -0
  281. package/skills/generating-visual-diagrams/assets/architecture/integration-flow.md +55 -0
  282. package/skills/generating-visual-diagrams/assets/erd/core-objects.md +131 -0
  283. package/skills/generating-visual-diagrams/assets/erd/custom-objects.md +60 -0
  284. package/skills/generating-visual-diagrams/assets/lwc/dashboard-card.md +45 -0
  285. package/skills/generating-visual-diagrams/assets/lwc/data-table.md +57 -0
  286. package/skills/generating-visual-diagrams/assets/lwc/record-form.md +60 -0
  287. package/skills/generating-visual-diagrams/assets/review/apex-review.md +57 -0
  288. package/skills/generating-visual-diagrams/assets/review/lwc-review.md +48 -0
  289. package/skills/generating-visual-diagrams/references/architect-aesthetic-guide.md +257 -0
  290. package/skills/generating-visual-diagrams/references/examples-index.md +35 -0
  291. package/skills/generating-visual-diagrams/references/gemini-cli-setup.md +65 -0
  292. package/skills/generating-visual-diagrams/references/interview-questions.md +529 -0
  293. package/skills/generating-visual-diagrams/references/iteration-workflow.md +173 -0
  294. package/skills/generating-visual-diagrams/scripts/check-prerequisites.sh +101 -0
  295. package/skills/generating-visual-diagrams/scripts/generate_image.py +243 -0
  296. package/skills/handling-sf-data/CREDITS.md +5 -0
  297. package/skills/handling-sf-data/README.md +112 -0
  298. package/skills/handling-sf-data/SKILL.md +235 -0
  299. package/skills/handling-sf-data/assets/bulk/bulk-insert-10000.apex +293 -0
  300. package/skills/handling-sf-data/assets/bulk/bulk-insert-200.apex +208 -0
  301. package/skills/handling-sf-data/assets/bulk/bulk-insert-500.apex +219 -0
  302. package/skills/handling-sf-data/assets/bulk/bulk-upsert-external-id.apex +324 -0
  303. package/skills/handling-sf-data/assets/cleanup/delete-by-created-date.apex +319 -0
  304. package/skills/handling-sf-data/assets/cleanup/delete-by-name.apex +240 -0
  305. package/skills/handling-sf-data/assets/cleanup/delete-test-data.apex +311 -0
  306. package/skills/handling-sf-data/assets/cleanup/rollback-transaction.apex +266 -0
  307. package/skills/handling-sf-data/assets/csv/account-import.csv +11 -0
  308. package/skills/handling-sf-data/assets/csv/contact-import.csv +11 -0
  309. package/skills/handling-sf-data/assets/csv/custom-object-import.csv +11 -0
  310. package/skills/handling-sf-data/assets/csv/opportunity-import.csv +11 -0
  311. package/skills/handling-sf-data/assets/factories/account-factory.apex +165 -0
  312. package/skills/handling-sf-data/assets/factories/case-factory.apex +237 -0
  313. package/skills/handling-sf-data/assets/factories/contact-factory.apex +168 -0
  314. package/skills/handling-sf-data/assets/factories/custom-object-factory.apex +260 -0
  315. package/skills/handling-sf-data/assets/factories/event-factory.apex +275 -0
  316. package/skills/handling-sf-data/assets/factories/hierarchy-factory.apex +372 -0
  317. package/skills/handling-sf-data/assets/factories/lead-factory.apex +190 -0
  318. package/skills/handling-sf-data/assets/factories/opportunity-factory.apex +206 -0
  319. package/skills/handling-sf-data/assets/factories/task-factory.apex +246 -0
  320. package/skills/handling-sf-data/assets/factories/user-factory.apex +278 -0
  321. package/skills/handling-sf-data/assets/json/account-contact-tree.json +130 -0
  322. package/skills/handling-sf-data/assets/json/account-opportunity-tree.json +110 -0
  323. package/skills/handling-sf-data/assets/json/full-hierarchy-tree.json +188 -0
  324. package/skills/handling-sf-data/assets/soql/aggregate.soql +226 -0
  325. package/skills/handling-sf-data/assets/soql/child-to-parent.soql +162 -0
  326. package/skills/handling-sf-data/assets/soql/parent-to-child.soql +153 -0
  327. package/skills/handling-sf-data/assets/soql/polymorphic.soql +198 -0
  328. package/skills/handling-sf-data/assets/soql/subquery.soql +287 -0
  329. package/skills/handling-sf-data/references/anonymous-apex-guide.md +98 -0
  330. package/skills/handling-sf-data/references/bulk-operations-guide.md +94 -0
  331. package/skills/handling-sf-data/references/bulk-testing-example.md +194 -0
  332. package/skills/handling-sf-data/references/cleanup-rollback-example.md +322 -0
  333. package/skills/handling-sf-data/references/cleanup-rollback-guide.md +84 -0
  334. package/skills/handling-sf-data/references/crud-workflow-example.md +183 -0
  335. package/skills/handling-sf-data/references/governor-limits-reference.md +74 -0
  336. package/skills/handling-sf-data/references/orchestration.md +174 -0
  337. package/skills/handling-sf-data/references/relationship-query-examples.md +249 -0
  338. package/skills/handling-sf-data/references/sf-cli-data-commands.md +158 -0
  339. package/skills/handling-sf-data/references/soql-relationship-guide.md +84 -0
  340. package/skills/handling-sf-data/references/test-data-best-practices.md +104 -0
  341. package/skills/handling-sf-data/references/test-data-factory-usage.md +290 -0
  342. package/skills/handling-sf-data/references/test-data-patterns.md +98 -0
  343. package/skills/handling-sf-data/scripts/soql_validator.py +292 -0
  344. package/skills/handling-sf-data/scripts/validate_data_operation.py +379 -0
  345. package/skills/harmonizing-datacloud/CREDITS.md +3 -0
  346. package/skills/harmonizing-datacloud/README.md +31 -0
  347. package/skills/harmonizing-datacloud/SKILL.md +117 -0
  348. package/skills/modeling-omnistudio-epc-catalog/CREDITS.md +14 -0
  349. package/skills/modeling-omnistudio-epc-catalog/README.md +89 -0
  350. package/skills/modeling-omnistudio-epc-catalog/SKILL.md +395 -0
  351. package/skills/modeling-omnistudio-epc-catalog/assets/attribute-assignment-template.json +402 -0
  352. package/skills/modeling-omnistudio-epc-catalog/assets/compiled-attribute-overrides-template.json +43 -0
  353. package/skills/modeling-omnistudio-epc-catalog/assets/completion-block-template.txt +8 -0
  354. package/skills/modeling-omnistudio-epc-catalog/assets/decomposition-relationships-template.json +233 -0
  355. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_AttributeAssignments.json +514 -0
  356. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_CompiledAttributeOverrides.json +21 -0
  357. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_DataPack.json +649 -0
  358. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_DecompositionRelationships.json +200 -0
  359. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_ObjectFieldAttributes.json +138 -0
  360. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_OrchestrationScenarios.json +54 -0
  361. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_OverrideDefinitions.json +266 -0
  362. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_ParentKeys.json +23 -0
  363. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_PriceListEntries.json +54 -0
  364. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_PricebookEntries.json +35 -0
  365. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_ProductChildItems.json +34 -0
  366. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_RuleAssignments.json +21 -0
  367. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_AttributeAssignments.json +410 -0
  368. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_DataPack.json +535 -0
  369. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_DecompositionRelationships.json +35 -0
  370. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_ObjectFieldAttributes.json +138 -0
  371. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_OrchestrationScenarios.json +28 -0
  372. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_ParentKeys.json +23 -0
  373. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_PriceListEntries.json +220 -0
  374. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_PricebookEntries.json +35 -0
  375. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_ProductChildItems.json +414 -0
  376. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_AttributeAssignments.json +382 -0
  377. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_DataPack.json +565 -0
  378. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_DecompositionRelationships.json +35 -0
  379. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_ObjectFieldAttributes.json +104 -0
  380. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_OrchestrationScenarios.json +28 -0
  381. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_ParentKeys.json +13 -0
  382. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_PriceListEntries.json +106 -0
  383. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_PricebookEntries.json +35 -0
  384. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_ProductChildItems.json +72 -0
  385. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_AttributeAssignments.json +142 -0
  386. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_DataPack.json +377 -0
  387. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_DecompositionRelationships.json +35 -0
  388. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_ObjectFieldAttributes.json +36 -0
  389. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_ParentKeys.json +8 -0
  390. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_PriceListEntries.json +54 -0
  391. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_PricebookEntries.json +35 -0
  392. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_ProductChildItems.json +34 -0
  393. package/skills/modeling-omnistudio-epc-catalog/assets/object-field-attributes-template.json +138 -0
  394. package/skills/modeling-omnistudio-epc-catalog/assets/orchestration-scenarios-template.json +54 -0
  395. package/skills/modeling-omnistudio-epc-catalog/assets/override-definitions-template.json +134 -0
  396. package/skills/modeling-omnistudio-epc-catalog/assets/parent-keys-template.json +29 -0
  397. package/skills/modeling-omnistudio-epc-catalog/assets/price-list-entries-template.json +158 -0
  398. package/skills/modeling-omnistudio-epc-catalog/assets/pricebook-entries-template.json +35 -0
  399. package/skills/modeling-omnistudio-epc-catalog/assets/product-child-item-template.json +338 -0
  400. package/skills/modeling-omnistudio-epc-catalog/assets/product2-offer-template.json +527 -0
  401. package/skills/modeling-omnistudio-epc-catalog/examples/.gitkeep +1 -0
  402. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_AttributeAssignments.json +95 -0
  403. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_CompiledAttributeOverrides.json +1 -0
  404. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_DataPack.json +214 -0
  405. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_DecompositionRelationships.json +28 -0
  406. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_ObjectFieldAttributes.json +98 -0
  407. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_OrchestrationScenarios.json +22 -0
  408. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_OverrideDefinitions.json +1 -0
  409. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_ParentKeys.json +13 -0
  410. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_PriceListEntries.json +35 -0
  411. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_PricebookEntries.json +28 -0
  412. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_ProductChildItems.json +110 -0
  413. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/TRANSCRIPT.md +58 -0
  414. package/skills/modeling-omnistudio-epc-catalog/references/epc-field-guide.md +90 -0
  415. package/skills/modeling-omnistudio-epc-catalog/references/naming-conventions.md +80 -0
  416. package/skills/modeling-omnistudio-epc-catalog/references/scoring-model.md +57 -0
  417. package/skills/modeling-omnistudio-epc-catalog/scripts/cli-validation-commands.sh +19 -0
  418. package/skills/modeling-omnistudio-epc-catalog/scripts/sample-invocations.sh +18 -0
  419. package/skills/orchestrating-datacloud/CREDITS.md +15 -0
  420. package/skills/orchestrating-datacloud/README.md +129 -0
  421. package/skills/orchestrating-datacloud/SKILL.md +236 -0
  422. package/skills/orchestrating-datacloud/UPSTREAM.md +45 -0
  423. package/skills/orchestrating-datacloud/assets/definitions/activation-target.template.json +5 -0
  424. package/skills/orchestrating-datacloud/assets/definitions/activation.template.json +7 -0
  425. package/skills/orchestrating-datacloud/assets/definitions/calculated-insight.template.json +7 -0
  426. package/skills/orchestrating-datacloud/assets/definitions/data-action-target.template.json +5 -0
  427. package/skills/orchestrating-datacloud/assets/definitions/data-action.template.json +5 -0
  428. package/skills/orchestrating-datacloud/assets/definitions/data-graph.template.json +21 -0
  429. package/skills/orchestrating-datacloud/assets/definitions/data-stream.template.json +55 -0
  430. package/skills/orchestrating-datacloud/assets/definitions/dmo.template.json +17 -0
  431. package/skills/orchestrating-datacloud/assets/definitions/identity-resolution.template.json +30 -0
  432. package/skills/orchestrating-datacloud/assets/definitions/mapping.template.json +14 -0
  433. package/skills/orchestrating-datacloud/assets/definitions/relationship.template.json +12 -0
  434. package/skills/orchestrating-datacloud/assets/definitions/search-index.template.json +9 -0
  435. package/skills/orchestrating-datacloud/assets/definitions/segment.template.json +16 -0
  436. package/skills/orchestrating-datacloud/references/feature-readiness.md +157 -0
  437. package/skills/orchestrating-datacloud/references/plugin-setup.md +140 -0
  438. package/skills/orchestrating-datacloud/scripts/bootstrap-plugin.sh +53 -0
  439. package/skills/orchestrating-datacloud/scripts/diagnose-org.mjs +511 -0
  440. package/skills/orchestrating-datacloud/scripts/generate-manifest.mjs +68 -0
  441. package/skills/orchestrating-datacloud/scripts/verify-plugin.sh +58 -0
  442. package/skills/preparing-datacloud/CREDITS.md +7 -0
  443. package/skills/preparing-datacloud/README.md +51 -0
  444. package/skills/preparing-datacloud/SKILL.md +191 -0
  445. package/skills/preparing-datacloud/examples/ingestion-api/.env.example +8 -0
  446. package/skills/preparing-datacloud/examples/ingestion-api/README.md +48 -0
  447. package/skills/preparing-datacloud/examples/ingestion-api/send-data.py +144 -0
  448. package/skills/querying-soql/CREDITS.md +21 -0
  449. package/skills/querying-soql/README.md +41 -0
  450. package/skills/querying-soql/SKILL.md +143 -0
  451. package/skills/querying-soql/assets/aggregate-queries.soql +242 -0
  452. package/skills/querying-soql/assets/basic-queries.soql +188 -0
  453. package/skills/querying-soql/assets/bulkified-query-pattern.cls +280 -0
  454. package/skills/querying-soql/assets/optimization-patterns.soql +259 -0
  455. package/skills/querying-soql/assets/relationship-queries.soql +203 -0
  456. package/skills/querying-soql/assets/selector-class.cls +219 -0
  457. package/skills/querying-soql/references/anti-patterns.md +348 -0
  458. package/skills/querying-soql/references/cli-commands.md +358 -0
  459. package/skills/querying-soql/references/field-coverage-rules.md +514 -0
  460. package/skills/querying-soql/references/query-optimization.md +142 -0
  461. package/skills/querying-soql/references/selector-patterns.md +479 -0
  462. package/skills/querying-soql/references/soql-reference.md +227 -0
  463. package/skills/querying-soql/references/soql-syntax-reference.md +208 -0
  464. package/skills/querying-soql/scripts/post-tool-validate.py +322 -0
  465. package/skills/retrieving-datacloud/CREDITS.md +7 -0
  466. package/skills/retrieving-datacloud/README.md +44 -0
  467. package/skills/retrieving-datacloud/SKILL.md +120 -0
  468. package/skills/retrieving-datacloud/examples/search-indexes/hybrid-structured.json +44 -0
  469. package/skills/retrieving-datacloud/examples/search-indexes/vector-knowledge.json +43 -0
  470. package/skills/running-apex-tests/CREDITS.md +22 -0
  471. package/skills/running-apex-tests/README.md +94 -0
  472. package/skills/running-apex-tests/SKILL.md +158 -0
  473. package/skills/running-apex-tests/assets/basic-test.cls +169 -0
  474. package/skills/running-apex-tests/assets/bulk-test.cls +255 -0
  475. package/skills/running-apex-tests/assets/dml-mock.cls +339 -0
  476. package/skills/running-apex-tests/assets/mock-callout-test.cls +353 -0
  477. package/skills/running-apex-tests/assets/stub-provider-example.cls +364 -0
  478. package/skills/running-apex-tests/assets/test-data-factory.cls +328 -0
  479. package/skills/running-apex-tests/hooks/scripts/parse-test-results.py +364 -0
  480. package/skills/running-apex-tests/references/cli-commands.md +289 -0
  481. package/skills/running-apex-tests/references/mocking-patterns.md +500 -0
  482. package/skills/running-apex-tests/references/performance-optimization.md +283 -0
  483. package/skills/running-apex-tests/references/test-fix-loop.md +49 -0
  484. package/skills/running-apex-tests/references/test-patterns.md +154 -0
  485. package/skills/running-apex-tests/references/testing-best-practices.md +509 -0
  486. package/skills/segmenting-datacloud/CREDITS.md +3 -0
  487. package/skills/segmenting-datacloud/README.md +36 -0
  488. package/skills/segmenting-datacloud/SKILL.md +115 -0
@@ -0,0 +1,1476 @@
1
+ <!-- Parent: generating-lwc-components/SKILL.md -->
2
+ # LWC Component Patterns
3
+
4
+ Comprehensive code examples for common Lightning Web Component patterns.
5
+
6
+ ---
7
+
8
+ ## Table of Contents
9
+
10
+ 1. [PICKLES Framework Details](#pickles-framework-details)
11
+ 2. [Wire Service Patterns](#wire-service-patterns)
12
+ - [Wire vs Imperative Apex Calls](#wire-vs-imperative-apex-calls)
13
+ 3. [GraphQL Patterns](#graphql-patterns)
14
+ 4. [Modal Component Pattern](#modal-component-pattern)
15
+ 5. [Record Picker Pattern](#record-picker-pattern)
16
+ 6. [Workspace API Pattern](#workspace-api-pattern)
17
+ 7. [Parent-Child Communication](#parent-child-communication)
18
+ 8. [Sibling Communication (via Parent)](#sibling-communication-via-parent)
19
+ 9. [Navigation Patterns](#navigation-patterns)
20
+ 10. [TypeScript Patterns](#typescript-patterns)
21
+ 11. [Apex Controller Patterns](#apex-controller-patterns)
22
+
23
+ ---
24
+
25
+ ## PICKLES Framework Details
26
+
27
+ ### P - Prototype
28
+
29
+ **Purpose**: Validate ideas early before full implementation.
30
+
31
+ | Action | Description |
32
+ |--------|-------------|
33
+ | Wireframe | Create high-level component sketches |
34
+ | Mock Data | Use sample data to test functionality |
35
+ | Stakeholder Review | Gather feedback before development |
36
+ | Separation of Concerns | Break into smaller functional pieces |
37
+
38
+ ```javascript
39
+ // Mock data pattern for prototyping
40
+ const MOCK_ACCOUNTS = [
41
+ { Id: '001MOCK001', Name: 'Acme Corp', Industry: 'Technology' },
42
+ { Id: '001MOCK002', Name: 'Global Inc', Industry: 'Finance' }
43
+ ];
44
+
45
+ export default class AccountPrototype extends LightningElement {
46
+ accounts = MOCK_ACCOUNTS; // Replace with wire/Apex later
47
+ }
48
+ ```
49
+
50
+ ### I - Integrate
51
+
52
+ **Purpose**: Determine how components interact with data systems.
53
+
54
+ **Integration Checklist**:
55
+ - [ ] Implement error handling with clear user notifications
56
+ - [ ] Add loading spinners to prevent duplicate requests
57
+ - [ ] Use LDS for single-object operations (minimizes DML)
58
+ - [ ] Respect FLS and CRUD in Apex implementations
59
+ - [ ] Store `wiredResult` for `refreshApex()` support
60
+
61
+ ### C - Composition
62
+
63
+ **Purpose**: Structure how LWCs nest and communicate.
64
+
65
+ **Best Practices**:
66
+ - Maintain shallow component hierarchies (max 3-4 levels)
67
+ - Single responsibility per component
68
+ - Clean up subscriptions in `disconnectedCallback()`
69
+ - Use custom events purposefully, not for every interaction
70
+
71
+ ```javascript
72
+ // Parent-managed composition pattern
73
+ // parent.js
74
+ handleChildEvent(event) {
75
+ this.selectedId = event.detail.id;
76
+ // Update child via @api
77
+ this.template.querySelector('c-child').selectedId = this.selectedId;
78
+ }
79
+ ```
80
+
81
+ ### K - Kinetics
82
+
83
+ **Purpose**: Manage user interaction and event responsiveness.
84
+
85
+ ```javascript
86
+ // Debounce pattern for search
87
+ delayTimeout;
88
+
89
+ handleSearchChange(event) {
90
+ const searchTerm = event.target.value;
91
+ clearTimeout(this.delayTimeout);
92
+ this.delayTimeout = setTimeout(() => {
93
+ this.dispatchEvent(new CustomEvent('search', {
94
+ detail: { searchTerm }
95
+ }));
96
+ }, 300);
97
+ }
98
+ ```
99
+
100
+ ### L - Libraries
101
+
102
+ **Purpose**: Leverage Salesforce-provided and platform tools.
103
+
104
+ **Recommended Platform Features**:
105
+
106
+ | API/Module | Use Case |
107
+ |------------|----------|
108
+ | `lightning/navigation` | Page/record navigation |
109
+ | `lightning/uiRecordApi` | LDS operations (getRecord, updateRecord) |
110
+ | `lightning/platformShowToastEvent` | User notifications |
111
+ | `lightning/modal` | Native modal dialogs |
112
+ | Base Components | Pre-built UI (button, input, datatable) |
113
+ | `lightning/refresh` | Dispatch refresh events |
114
+
115
+ **Avoid reinventing** what base components already provide!
116
+
117
+ ### E - Execution
118
+
119
+ **Purpose**: Optimize performance and resource efficiency.
120
+
121
+ **Performance Checklist**:
122
+ - [ ] Lazy load with `if:true` / `lwc:if`
123
+ - [ ] Use `key` directive in iterations
124
+ - [ ] Cache computed values in getters
125
+ - [ ] Avoid property updates that trigger re-renders
126
+ - [ ] Use browser DevTools Performance tab
127
+
128
+ ### S - Security
129
+
130
+ **Purpose**: Enforce access control and data protection.
131
+
132
+ ```apex
133
+ // Secure Apex pattern
134
+ @AuraEnabled(cacheable=true)
135
+ public static List<Account> getAccounts(String searchTerm) {
136
+ String searchKey = '%' + String.escapeSingleQuotes(searchTerm) + '%';
137
+ return [
138
+ SELECT Id, Name, Industry
139
+ FROM Account
140
+ WHERE Name LIKE :searchKey
141
+ WITH SECURITY_ENFORCED
142
+ LIMIT 50
143
+ ];
144
+ }
145
+ ```
146
+
147
+ ---
148
+
149
+ ## Wire Service Patterns
150
+
151
+ ### Wire vs Imperative Apex Calls
152
+
153
+ LWC can interact with Apex in two ways: **@wire** (reactive/declarative) and **imperative calls** (manual/programmatic). Understanding when to use each is critical for building performant, maintainable components.
154
+
155
+ #### Quick Comparison
156
+
157
+ ```
158
+ ┌─────────────────────────────────────────────────────────────────────────────────────┐
159
+ │ WIRE vs IMPERATIVE APEX CALLS │
160
+ ├──────────────────┬──────────────────────────────┬────────────────────────────────────┤
161
+ │ Aspect │ Wire (@wire) │ Imperative Calls │
162
+ ├──────────────────┼──────────────────────────────┼────────────────────────────────────┤
163
+ │ Execution │ Automatic / Reactive │ Manual / Programmatic │
164
+ │ DML Operations │ ❌ Read-Only │ ✅ Insert / Update / Delete │
165
+ │ Data Updates │ ✅ Auto on Parameter Change │ ❌ Manual Refresh Required │
166
+ │ Control │ ⚠️ Low (framework decides) │ ✅ Full (you decide when/how) │
167
+ │ Error Handling │ ✅ Framework Managed │ ⚠️ Developer Managed │
168
+ │ Supported Objects│ ⚠️ UI API Only │ ✅ All Objects │
169
+ │ Caching │ ✅ Built-in (cacheable=true) │ ❌ No automatic caching │
170
+ └──────────────────┴──────────────────────────────┴────────────────────────────────────┘
171
+ ```
172
+
173
+ #### Pros & Cons
174
+
175
+ | Wire (@wire) | Imperative Calls |
176
+ |--------------|------------------|
177
+ | ✅ Auto UI sync & caching | ✅ Supports DML & all objects |
178
+ | ✅ Less boilerplate code | ✅ Full control over timing |
179
+ | ✅ Reactive to parameter changes | ✅ Can handle complex logic |
180
+ | ❌ Read-only, limited objects | ❌ Manual handling, no auto refresh |
181
+ | ❌ Can't control execution timing | ❌ More error handling code needed |
182
+
183
+ #### When to Use Each
184
+
185
+ **Use Wire (@wire) when:**
186
+ - 📌 Read-only data display
187
+ - 📌 Auto-refresh UI when parameters change
188
+ - 📌 Stable parameters (recordId, filter values)
189
+ - 📌 Working with UI API supported objects
190
+
191
+ **Use Imperative Calls when:**
192
+ - 📌 User actions (clicks, form submissions)
193
+ - 📌 DML operations (Insert, Update, Delete)
194
+ - 📌 Dynamic parameters determined at runtime
195
+ - 📌 Custom objects or complex queries
196
+ - 📌 Need control over execution timing
197
+
198
+ #### Side-by-Side Code Examples
199
+
200
+ **Wire Example** - Data loads automatically when `selectedIndustry` changes:
201
+
202
+ ```javascript
203
+ import { LightningElement, wire } from 'lwc';
204
+ import fetchAccounts from '@salesforce/apex/AccountController.fetchAccounts';
205
+
206
+ export default class WireExample extends LightningElement {
207
+ selectedIndustry = 'Technology';
208
+ accounts;
209
+ error;
210
+
211
+ // Automatically re-fetches when selectedIndustry changes
212
+ @wire(fetchAccounts, { industry: '$selectedIndustry' })
213
+ wiredAccounts({ data, error }) {
214
+ if (data) {
215
+ this.accounts = data;
216
+ this.error = undefined;
217
+ } else if (error) {
218
+ this.error = error;
219
+ this.accounts = undefined;
220
+ }
221
+ }
222
+ }
223
+ ```
224
+
225
+ **Imperative Example** - Data loads only when user triggers action:
226
+
227
+ ```javascript
228
+ import { LightningElement } from 'lwc';
229
+ import fetchAccounts from '@salesforce/apex/AccountController.fetchAccounts';
230
+
231
+ export default class ImperativeExample extends LightningElement {
232
+ selectedIndustry = 'Technology';
233
+ accounts;
234
+ error;
235
+ isLoading = false;
236
+
237
+ // Called explicitly when user clicks button or submits form
238
+ async fetchAccounts() {
239
+ this.isLoading = true;
240
+ try {
241
+ this.accounts = await fetchAccounts({
242
+ industry: this.selectedIndustry
243
+ });
244
+ this.error = undefined;
245
+ } catch (error) {
246
+ this.error = error;
247
+ this.accounts = undefined;
248
+ } finally {
249
+ this.isLoading = false;
250
+ }
251
+ }
252
+ }
253
+ ```
254
+
255
+ #### Decision Tree
256
+
257
+ ```
258
+ ┌─────────────────────────────┐
259
+ │ Need to modify data? │
260
+ │ (Insert/Update/Delete) │
261
+ └─────────────┬───────────────┘
262
+
263
+ ┌─────────────┴───────────────┐
264
+ │ │
265
+ YES NO
266
+ │ │
267
+ ▼ ▼
268
+ ┌─────────────────┐ ┌─────────────────────────┐
269
+ │ IMPERATIVE │ │ Should data auto- │
270
+ │ (Use await) │ │ refresh on param │
271
+ └─────────────────┘ │ change? │
272
+ └───────────┬─────────────┘
273
+
274
+ ┌───────────┴───────────┐
275
+ │ │
276
+ YES NO
277
+ │ │
278
+ ▼ ▼
279
+ ┌─────────────────┐ ┌─────────────────┐
280
+ │ @WIRE │ │ IMPERATIVE │
281
+ │ (Reactive) │ │ (On-demand) │
282
+ └─────────────────┘ └─────────────────┘
283
+ ```
284
+
285
+ ---
286
+
287
+ ### 1. Basic Data Display (Wire Service)
288
+
289
+ ```javascript
290
+ // accountCard.js
291
+ import { LightningElement, api, wire } from 'lwc';
292
+ import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
293
+ import NAME_FIELD from '@salesforce/schema/Account.Name';
294
+ import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry';
295
+
296
+ const FIELDS = [NAME_FIELD, INDUSTRY_FIELD];
297
+
298
+ export default class AccountCard extends LightningElement {
299
+ @api recordId;
300
+
301
+ @wire(getRecord, { recordId: '$recordId', fields: FIELDS })
302
+ account;
303
+
304
+ get name() {
305
+ return getFieldValue(this.account.data, NAME_FIELD);
306
+ }
307
+
308
+ get industry() {
309
+ return getFieldValue(this.account.data, INDUSTRY_FIELD);
310
+ }
311
+
312
+ get isLoading() {
313
+ return !this.account.data && !this.account.error;
314
+ }
315
+ }
316
+ ```
317
+
318
+ ```html
319
+ <!-- accountCard.html -->
320
+ <template>
321
+ <template lwc:if={isLoading}>
322
+ <lightning-spinner alternative-text="Loading"></lightning-spinner>
323
+ </template>
324
+ <template lwc:if={account.data}>
325
+ <div class="slds-box slds-theme_default">
326
+ <h2 class="slds-text-heading_medium">{name}</h2>
327
+ <p class="slds-text-color_weak">{industry}</p>
328
+ </div>
329
+ </template>
330
+ <template lwc:if={account.error}>
331
+ <p class="slds-text-color_error">{account.error.body.message}</p>
332
+ </template>
333
+ </template>
334
+ ```
335
+
336
+ ### 2. Wire Service with Apex
337
+
338
+ ```javascript
339
+ // contactList.js
340
+ import { LightningElement, api, wire } from 'lwc';
341
+ import getContacts from '@salesforce/apex/ContactController.getContacts';
342
+ import { refreshApex } from '@salesforce/apex';
343
+
344
+ export default class ContactList extends LightningElement {
345
+ @api recordId;
346
+ contacts;
347
+ error;
348
+ wiredContactsResult;
349
+
350
+ @wire(getContacts, { accountId: '$recordId' })
351
+ wiredContacts(result) {
352
+ this.wiredContactsResult = result; // Store for refreshApex
353
+ const { error, data } = result;
354
+ if (data) {
355
+ this.contacts = data;
356
+ this.error = undefined;
357
+ } else if (error) {
358
+ this.error = error;
359
+ this.contacts = undefined;
360
+ }
361
+ }
362
+
363
+ async handleRefresh() {
364
+ await refreshApex(this.wiredContactsResult);
365
+ }
366
+ }
367
+ ```
368
+
369
+ ---
370
+
371
+ ## GraphQL Patterns
372
+
373
+ > **Module Note**: `lightning/graphql` supersedes `lightning/uiGraphQLApi` and provides newer features like mutations, optional fields, and dynamic query construction.
374
+
375
+ ### GraphQL Query (Wire Adapter)
376
+
377
+ ```javascript
378
+ // graphqlContacts.js
379
+ import { LightningElement, wire } from 'lwc';
380
+ import { gql, graphql } from 'lightning/graphql';
381
+
382
+ const CONTACTS_QUERY = gql`
383
+ query ContactsQuery($first: Int, $after: String) {
384
+ uiapi {
385
+ query {
386
+ Contact(first: $first, after: $after) {
387
+ edges {
388
+ node {
389
+ Id
390
+ Name { value }
391
+ Email { value }
392
+ Account {
393
+ Name { value }
394
+ }
395
+ }
396
+ cursor
397
+ }
398
+ pageInfo {
399
+ hasNextPage
400
+ endCursor
401
+ }
402
+ }
403
+ }
404
+ }
405
+ }
406
+ `;
407
+
408
+ export default class GraphqlContacts extends LightningElement {
409
+ contacts;
410
+ pageInfo;
411
+ error;
412
+ _cursor;
413
+
414
+ @wire(graphql, {
415
+ query: CONTACTS_QUERY,
416
+ variables: '$queryVariables'
417
+ })
418
+ wiredContacts({ data, error }) {
419
+ if (data) {
420
+ const result = data.uiapi.query.Contact;
421
+ this.contacts = result.edges.map(edge => ({
422
+ id: edge.node.Id,
423
+ name: edge.node.Name.value,
424
+ email: edge.node.Email?.value,
425
+ accountName: edge.node.Account?.Name?.value
426
+ }));
427
+ this.pageInfo = result.pageInfo;
428
+ } else if (error) {
429
+ this.error = error;
430
+ }
431
+ }
432
+
433
+ get queryVariables() {
434
+ return { first: 10, after: this._cursor };
435
+ }
436
+
437
+ loadMore() {
438
+ if (this.pageInfo?.hasNextPage) {
439
+ this._cursor = this.pageInfo.endCursor;
440
+ }
441
+ }
442
+ }
443
+ ```
444
+
445
+ ### GraphQL Mutations (Spring '26 - GA in API 66.0)
446
+
447
+ Mutations allow create, update, and delete operations via GraphQL. Use `executeMutation` for imperative operations.
448
+
449
+ ```javascript
450
+ // graphqlAccountMutation.js
451
+ import { LightningElement, track } from 'lwc';
452
+ import { gql, executeMutation } from 'lightning/graphql';
453
+ import { ShowToastEvent } from 'lightning/platformShowToastEvent';
454
+
455
+ // Create mutation
456
+ const CREATE_ACCOUNT = gql`
457
+ mutation CreateAccount($name: String!, $industry: String) {
458
+ uiapi {
459
+ AccountCreate(input: {
460
+ Account: {
461
+ Name: $name
462
+ Industry: $industry
463
+ }
464
+ }) {
465
+ Record {
466
+ Id
467
+ Name { value }
468
+ Industry { value }
469
+ }
470
+ }
471
+ }
472
+ }
473
+ `;
474
+
475
+ // Update mutation
476
+ const UPDATE_ACCOUNT = gql`
477
+ mutation UpdateAccount($id: ID!, $name: String!) {
478
+ uiapi {
479
+ AccountUpdate(input: {
480
+ Account: {
481
+ Id: $id
482
+ Name: $name
483
+ }
484
+ }) {
485
+ Record {
486
+ Id
487
+ Name { value }
488
+ }
489
+ }
490
+ }
491
+ }
492
+ `;
493
+
494
+ // Delete mutation
495
+ const DELETE_ACCOUNT = gql`
496
+ mutation DeleteAccount($id: ID!) {
497
+ uiapi {
498
+ AccountDelete(input: { Account: { Id: $id } }) {
499
+ Id
500
+ }
501
+ }
502
+ }
503
+ `;
504
+
505
+ export default class GraphqlAccountMutation extends LightningElement {
506
+ @track accountName = '';
507
+ @track industry = '';
508
+ isLoading = false;
509
+
510
+ handleNameChange(event) {
511
+ this.accountName = event.target.value;
512
+ }
513
+
514
+ handleIndustryChange(event) {
515
+ this.industry = event.target.value;
516
+ }
517
+
518
+ async handleCreate() {
519
+ if (!this.accountName) return;
520
+
521
+ this.isLoading = true;
522
+ try {
523
+ const result = await executeMutation(CREATE_ACCOUNT, {
524
+ variables: {
525
+ name: this.accountName,
526
+ industry: this.industry || null
527
+ }
528
+ });
529
+
530
+ const newRecord = result.data.uiapi.AccountCreate.Record;
531
+ this.showToast('Success', `Account "${newRecord.Name.value}" created`, 'success');
532
+ this.resetForm();
533
+ } catch (error) {
534
+ this.handleError(error);
535
+ } finally {
536
+ this.isLoading = false;
537
+ }
538
+ }
539
+
540
+ async handleUpdate(accountId, newName) {
541
+ try {
542
+ const result = await executeMutation(UPDATE_ACCOUNT, {
543
+ variables: { id: accountId, name: newName }
544
+ });
545
+ this.showToast('Success', 'Account updated', 'success');
546
+ return result.data.uiapi.AccountUpdate.Record;
547
+ } catch (error) {
548
+ this.handleError(error);
549
+ }
550
+ }
551
+
552
+ async handleDelete(accountId) {
553
+ try {
554
+ await executeMutation(DELETE_ACCOUNT, {
555
+ variables: { id: accountId }
556
+ });
557
+ this.showToast('Success', 'Account deleted', 'success');
558
+ } catch (error) {
559
+ this.handleError(error);
560
+ }
561
+ }
562
+
563
+ handleError(error) {
564
+ const message = error.graphQLErrors
565
+ ? error.graphQLErrors.map(e => e.message).join(', ')
566
+ : error.message || 'Unknown error';
567
+ this.showToast('Error', message, 'error');
568
+ }
569
+
570
+ showToast(title, message, variant) {
571
+ this.dispatchEvent(new ShowToastEvent({ title, message, variant }));
572
+ }
573
+
574
+ resetForm() {
575
+ this.accountName = '';
576
+ this.industry = '';
577
+ }
578
+ }
579
+ ```
580
+
581
+ ### GraphQL Mutation Operations
582
+
583
+ | Operation | Mutation Type | Notes |
584
+ |-----------|---------------|-------|
585
+ | **Create** | `{Object}Create` | Can request fields from newly created record |
586
+ | **Update** | `{Object}Update` | Cannot query fields in same request |
587
+ | **Delete** | `{Object}Delete` | Cannot query fields in same request |
588
+
589
+ ### allOrNone Parameter
590
+
591
+ Control transaction behavior with `allOrNone` (default: `true`):
592
+
593
+ ```javascript
594
+ const BATCH_CREATE = gql`
595
+ mutation BatchCreate($allOrNone: Boolean = true) {
596
+ uiapi(allOrNone: $allOrNone) {
597
+ acc1: AccountCreate(input: { Account: { Name: "Account 1" } }) {
598
+ Record { Id }
599
+ }
600
+ acc2: AccountCreate(input: { Account: { Name: "Account 2" } }) {
601
+ Record { Id }
602
+ }
603
+ }
604
+ }
605
+ `;
606
+
607
+ // If allOrNone=true: All rollback if any fails
608
+ // If allOrNone=false: Only failed operations rollback
609
+ ```
610
+
611
+ ---
612
+
613
+ ## Modal Component Pattern
614
+
615
+ Based on [James Simone's composable modal pattern](https://www.jamessimone.net/blog/joys-of-apex/lwc-composable-modal/).
616
+
617
+ ```javascript
618
+ // composableModal.js
619
+ import { LightningElement, api } from 'lwc';
620
+
621
+ const OUTER_MODAL_CLASS = 'outerModalContent';
622
+
623
+ export default class ComposableModal extends LightningElement {
624
+ @api modalHeader;
625
+ @api modalTagline;
626
+ @api modalSaveHandler;
627
+
628
+ _isOpen = false;
629
+ _focusableElements = [];
630
+
631
+ @api
632
+ toggleModal() {
633
+ this._isOpen = !this._isOpen;
634
+ if (this._isOpen) {
635
+ this._focusableElements = [...this.querySelectorAll('.focusable')];
636
+ this._focusFirstElement();
637
+ window.addEventListener('keyup', this._handleKeyUp);
638
+ } else {
639
+ window.removeEventListener('keyup', this._handleKeyUp);
640
+ }
641
+ }
642
+
643
+ get modalAriaHidden() {
644
+ return !this._isOpen;
645
+ }
646
+
647
+ get modalClass() {
648
+ return this._isOpen
649
+ ? 'slds-modal slds-visible slds-fade-in-open'
650
+ : 'slds-modal slds-hidden';
651
+ }
652
+
653
+ get backdropClass() {
654
+ return this._isOpen ? 'slds-backdrop slds-backdrop_open' : 'slds-backdrop';
655
+ }
656
+
657
+ _handleKeyUp = (event) => {
658
+ if (event.code === 'Escape') {
659
+ this.toggleModal();
660
+ } else if (event.code === 'Tab') {
661
+ this._handleTabNavigation(event);
662
+ }
663
+ }
664
+
665
+ _handleTabNavigation(event) {
666
+ // Focus trap logic - keep focus within modal
667
+ const activeEl = this.template.activeElement;
668
+ const lastIndex = this._focusableElements.length - 1;
669
+ const currentIndex = this._focusableElements.indexOf(activeEl);
670
+
671
+ if (event.shiftKey && currentIndex === 0) {
672
+ this._focusableElements[lastIndex]?.focus();
673
+ } else if (!event.shiftKey && currentIndex === lastIndex) {
674
+ this._focusFirstElement();
675
+ }
676
+ }
677
+
678
+ _focusFirstElement() {
679
+ if (this._focusableElements.length > 0) {
680
+ this._focusableElements[0].focus();
681
+ }
682
+ }
683
+
684
+ handleBackdropClick(event) {
685
+ if (event.target.classList.contains(OUTER_MODAL_CLASS)) {
686
+ this.toggleModal();
687
+ }
688
+ }
689
+
690
+ handleSave() {
691
+ if (this.modalSaveHandler) {
692
+ this.modalSaveHandler();
693
+ }
694
+ this.toggleModal();
695
+ }
696
+
697
+ disconnectedCallback() {
698
+ window.removeEventListener('keyup', this._handleKeyUp);
699
+ }
700
+ }
701
+ ```
702
+
703
+ ```html
704
+ <!-- composableModal.html -->
705
+ <template>
706
+ <!-- Backdrop -->
707
+ <div class={backdropClass}></div>
708
+
709
+ <!-- Modal -->
710
+ <div class={modalClass}
711
+ role="dialog"
712
+ aria-modal="true"
713
+ aria-hidden={modalAriaHidden}
714
+ aria-labelledby="modal-heading">
715
+
716
+ <div class="slds-modal__container outerModalContent"
717
+ onclick={handleBackdropClick}>
718
+
719
+ <div class="slds-modal__content slds-p-around_medium">
720
+ <!-- Header -->
721
+ <template lwc:if={modalHeader}>
722
+ <h2 id="modal-heading" class="slds-text-heading_medium">
723
+ {modalHeader}
724
+ </h2>
725
+ </template>
726
+ <template lwc:if={modalTagline}>
727
+ <p class="slds-m-top_x-small slds-text-color_weak">
728
+ {modalTagline}
729
+ </p>
730
+ </template>
731
+
732
+ <!-- Slotted Content -->
733
+ <div class="slds-m-top_medium">
734
+ <slot name="modalContent"></slot>
735
+ </div>
736
+
737
+ <!-- Footer -->
738
+ <div class="slds-m-top_medium slds-text-align_right">
739
+ <lightning-button
740
+ label="Cancel"
741
+ onclick={toggleModal}
742
+ class="slds-m-right_x-small focusable">
743
+ </lightning-button>
744
+ <lightning-button
745
+ variant="brand"
746
+ label="Save"
747
+ onclick={handleSave}
748
+ class="focusable">
749
+ </lightning-button>
750
+ </div>
751
+ </div>
752
+ </div>
753
+ </div>
754
+
755
+ <!-- Hidden background content -->
756
+ <div aria-hidden={_isOpen}>
757
+ <slot name="body"></slot>
758
+ </div>
759
+ </template>
760
+ ```
761
+
762
+ ---
763
+
764
+ ## Record Picker Pattern
765
+
766
+ ```javascript
767
+ // recordPicker.js
768
+ import { LightningElement, api } from 'lwc';
769
+
770
+ export default class RecordPicker extends LightningElement {
771
+ @api label = 'Select Record';
772
+ @api objectApiName = 'Account';
773
+ @api placeholder = 'Search...';
774
+ @api required = false;
775
+ @api multiSelect = false;
776
+
777
+ _selectedIds = [];
778
+
779
+ @api
780
+ get value() {
781
+ return this.multiSelect ? this._selectedIds : this._selectedIds[0];
782
+ }
783
+
784
+ set value(val) {
785
+ this._selectedIds = Array.isArray(val) ? val : val ? [val] : [];
786
+ }
787
+
788
+ handleChange(event) {
789
+ const recordId = event.detail.recordId;
790
+ if (this.multiSelect) {
791
+ if (!this._selectedIds.includes(recordId)) {
792
+ this._selectedIds = [...this._selectedIds, recordId];
793
+ }
794
+ } else {
795
+ this._selectedIds = recordId ? [recordId] : [];
796
+ }
797
+
798
+ this.dispatchEvent(new CustomEvent('select', {
799
+ detail: {
800
+ recordId: this.value,
801
+ recordIds: this._selectedIds
802
+ }
803
+ }));
804
+ }
805
+
806
+ handleRemove(event) {
807
+ const idToRemove = event.target.dataset.id;
808
+ this._selectedIds = this._selectedIds.filter(id => id !== idToRemove);
809
+ this.dispatchEvent(new CustomEvent('select', {
810
+ detail: { recordIds: this._selectedIds }
811
+ }));
812
+ }
813
+ }
814
+ ```
815
+
816
+ ```html
817
+ <!-- recordPicker.html -->
818
+ <template>
819
+ <lightning-record-picker
820
+ label={label}
821
+ placeholder={placeholder}
822
+ object-api-name={objectApiName}
823
+ onchange={handleChange}
824
+ required={required}>
825
+ </lightning-record-picker>
826
+
827
+ <template lwc:if={multiSelect}>
828
+ <div class="slds-m-top_x-small">
829
+ <template for:each={_selectedIds} for:item="id">
830
+ <lightning-pill
831
+ key={id}
832
+ label={id}
833
+ data-id={id}
834
+ onremove={handleRemove}>
835
+ </lightning-pill>
836
+ </template>
837
+ </div>
838
+ </template>
839
+ </template>
840
+ ```
841
+
842
+ ---
843
+
844
+ ## Workspace API Pattern
845
+
846
+ ```javascript
847
+ // workspaceTabManager.js
848
+ import { LightningElement, wire } from 'lwc';
849
+ import { IsConsoleNavigation, getFocusedTabInfo, openTab, closeTab,
850
+ setTabLabel, setTabIcon, refreshTab } from 'lightning/platformWorkspaceApi';
851
+
852
+ export default class WorkspaceTabManager extends LightningElement {
853
+ @wire(IsConsoleNavigation) isConsole;
854
+
855
+ async openRecordTab(recordId, objectApiName) {
856
+ if (!this.isConsole) return;
857
+
858
+ await openTab({
859
+ recordId,
860
+ focus: true,
861
+ icon: `standard:${objectApiName.toLowerCase()}`,
862
+ label: 'Loading...'
863
+ });
864
+ }
865
+
866
+ async openSubtab(parentTabId, recordId) {
867
+ if (!this.isConsole) return;
868
+
869
+ await openTab({
870
+ parentTabId,
871
+ recordId,
872
+ focus: true
873
+ });
874
+ }
875
+
876
+ async getCurrentTabInfo() {
877
+ if (!this.isConsole) return null;
878
+ return await getFocusedTabInfo();
879
+ }
880
+
881
+ async updateTabLabel(tabId, label) {
882
+ if (!this.isConsole) return;
883
+ await setTabLabel(tabId, label);
884
+ }
885
+
886
+ async updateTabIcon(tabId, iconName) {
887
+ if (!this.isConsole) return;
888
+ await setTabIcon(tabId, iconName);
889
+ }
890
+
891
+ async refreshCurrentTab() {
892
+ if (!this.isConsole) return;
893
+ const tabInfo = await getFocusedTabInfo();
894
+ await refreshTab(tabInfo.tabId);
895
+ }
896
+
897
+ async closeCurrentTab() {
898
+ if (!this.isConsole) return;
899
+ const tabInfo = await getFocusedTabInfo();
900
+ await closeTab(tabInfo.tabId);
901
+ }
902
+ }
903
+ ```
904
+
905
+ ---
906
+
907
+ <a id="parent-child-communication"></a>
908
+
909
+ ## Parent-Child Communication
910
+
911
+ ```javascript
912
+ // parent.js
913
+ import { LightningElement } from 'lwc';
914
+
915
+ export default class Parent extends LightningElement {
916
+ selectedAccountId;
917
+
918
+ handleAccountSelected(event) {
919
+ this.selectedAccountId = event.detail.accountId;
920
+ }
921
+ }
922
+ ```
923
+
924
+ ```html
925
+ <!-- parent.html -->
926
+ <template>
927
+ <c-account-list onaccountselected={handleAccountSelected}></c-account-list>
928
+ <template lwc:if={selectedAccountId}>
929
+ <c-account-detail account-id={selectedAccountId}></c-account-detail>
930
+ </template>
931
+ </template>
932
+ ```
933
+
934
+ ```javascript
935
+ // child.js (accountList)
936
+ import { LightningElement } from 'lwc';
937
+
938
+ export default class AccountList extends LightningElement {
939
+ handleRowAction(event) {
940
+ const accountId = event.detail.row.Id;
941
+
942
+ // Dispatch event to parent
943
+ this.dispatchEvent(new CustomEvent('accountselected', {
944
+ detail: { accountId },
945
+ bubbles: true,
946
+ composed: false // Don't cross shadow DOM boundaries
947
+ }));
948
+ }
949
+ }
950
+ ```
951
+
952
+ ---
953
+
954
+ ## Sibling Communication (via Parent)
955
+
956
+ When two child components need to communicate but share the same parent, use the **parent as middleware**. This is the recommended pattern for master-detail UIs.
957
+
958
+ ```
959
+ ┌─────────────────────────────────────────────────────────────────────┐
960
+ │ SIBLING COMMUNICATION FLOW │
961
+ ├─────────────────────────────────────────────────────────────────────┤
962
+ │ │
963
+ │ ┌──────────┐ │
964
+ │ │ Parent │ ← Manages state │
965
+ │ └────┬─────┘ │
966
+ │ ┌─────────┴─────────┐ │
967
+ │ │ │ │
968
+ │ CustomEvent @api property │
969
+ │ (up) (down) │
970
+ │ │ │ │
971
+ │ ┌─────┴─────┐ ┌─────┴─────┐ │
972
+ │ │ Child A │ │ Child B │ │
973
+ │ │ (List) │ │ (Detail) │ │
974
+ │ └───────────┘ └───────────┘ │
975
+ │ │
976
+ └─────────────────────────────────────────────────────────────────────┘
977
+ ```
978
+
979
+ **The flow**:
980
+ 1. **Child A** dispatches a custom event (e.g., user selects an account)
981
+ 2. **Parent** catches the event and updates its state
982
+ 3. **Parent** passes data to **Child B** via `@api` property
983
+
984
+ ### Complete Example: Account List → Account Detail
985
+
986
+ ```javascript
987
+ // accountContainer.js - Parent orchestrates communication between siblings
988
+ import { LightningElement } from 'lwc';
989
+
990
+ export default class AccountContainer extends LightningElement {
991
+ // State managed at parent level
992
+ selectedAccountId;
993
+ selectedAccountName;
994
+
995
+ // Child A (accountList) fires this event
996
+ handleAccountSelect(event) {
997
+ this.selectedAccountId = event.detail.accountId;
998
+ this.selectedAccountName = event.detail.accountName;
999
+ }
1000
+
1001
+ // Clear selection (triggered by Child B)
1002
+ handleClearSelection() {
1003
+ this.selectedAccountId = null;
1004
+ this.selectedAccountName = null;
1005
+ }
1006
+
1007
+ get hasSelection() {
1008
+ return !!this.selectedAccountId;
1009
+ }
1010
+ }
1011
+ ```
1012
+
1013
+ ```html
1014
+ <!-- accountContainer.html -->
1015
+ <template>
1016
+ <div class="slds-grid slds-gutters">
1017
+ <!-- Child A: Account List -->
1018
+ <div class="slds-col slds-size_1-of-2">
1019
+ <c-account-list
1020
+ onaccountselect={handleAccountSelect}
1021
+ selected-id={selectedAccountId}>
1022
+ </c-account-list>
1023
+ </div>
1024
+
1025
+ <!-- Child B: Account Detail (receives data via @api) -->
1026
+ <div class="slds-col slds-size_1-of-2">
1027
+ <template lwc:if={hasSelection}>
1028
+ <c-account-detail
1029
+ account-id={selectedAccountId}
1030
+ account-name={selectedAccountName}
1031
+ onclearselection={handleClearSelection}>
1032
+ </c-account-detail>
1033
+ </template>
1034
+ <template lwc:else>
1035
+ <div class="slds-box slds-theme_shade">
1036
+ Select an account to view details
1037
+ </div>
1038
+ </template>
1039
+ </div>
1040
+ </div>
1041
+ </template>
1042
+ ```
1043
+
1044
+ ```javascript
1045
+ // accountList.js - Child A: Dispatches events UP to parent
1046
+ import { LightningElement, api, wire } from 'lwc';
1047
+ import getAccounts from '@salesforce/apex/AccountController.getAccounts';
1048
+
1049
+ export default class AccountList extends LightningElement {
1050
+ @api selectedId; // Highlight selected row (from parent)
1051
+ accounts;
1052
+ error;
1053
+
1054
+ @wire(getAccounts)
1055
+ wiredAccounts({ data, error }) {
1056
+ if (data) {
1057
+ this.accounts = data;
1058
+ this.error = undefined;
1059
+ } else if (error) {
1060
+ this.error = error;
1061
+ this.accounts = undefined;
1062
+ }
1063
+ }
1064
+
1065
+ handleRowClick(event) {
1066
+ const accountId = event.currentTarget.dataset.id;
1067
+ const accountName = event.currentTarget.dataset.name;
1068
+
1069
+ // Dispatch event to parent (not bubbles - parent listens directly)
1070
+ this.dispatchEvent(new CustomEvent('accountselect', {
1071
+ detail: { accountId, accountName }
1072
+ }));
1073
+ }
1074
+
1075
+ // Computed: Check if row should be highlighted
1076
+ getRowClass(accountId) {
1077
+ return accountId === this.selectedId
1078
+ ? 'slds-item slds-is-selected'
1079
+ : 'slds-item';
1080
+ }
1081
+ }
1082
+ ```
1083
+
1084
+ ```javascript
1085
+ // accountDetail.js - Child B: Receives data via @api from parent
1086
+ import { LightningElement, api, wire } from 'lwc';
1087
+ import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
1088
+ import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry';
1089
+ import REVENUE_FIELD from '@salesforce/schema/Account.AnnualRevenue';
1090
+
1091
+ const FIELDS = [INDUSTRY_FIELD, REVENUE_FIELD];
1092
+
1093
+ export default class AccountDetail extends LightningElement {
1094
+ @api accountId; // Received from parent
1095
+ @api accountName; // Received from parent
1096
+
1097
+ @wire(getRecord, { recordId: '$accountId', fields: FIELDS })
1098
+ account;
1099
+
1100
+ get industry() {
1101
+ return getFieldValue(this.account.data, INDUSTRY_FIELD);
1102
+ }
1103
+
1104
+ get revenue() {
1105
+ return getFieldValue(this.account.data, REVENUE_FIELD);
1106
+ }
1107
+
1108
+ get isLoading() {
1109
+ return !this.account.data && !this.account.error;
1110
+ }
1111
+
1112
+ handleClose() {
1113
+ // Dispatch event back to parent to clear selection
1114
+ this.dispatchEvent(new CustomEvent('clearselection'));
1115
+ }
1116
+ }
1117
+ ```
1118
+
1119
+ ### When to Use Sibling Pattern vs LMS
1120
+
1121
+ | Scenario | Sibling Pattern | LMS |
1122
+ |----------|-----------------|-----|
1123
+ | Components share same parent | ✅ Recommended | ❌ Overkill |
1124
+ | State is simple (1-2 values) | ✅ | ❌ |
1125
+ | Need bidirectional updates | ✅ | ✅ |
1126
+ | Components in different DOM trees | ❌ | ✅ Required |
1127
+ | Cross-framework (LWC ↔ Aura) | ❌ | ✅ Required |
1128
+ | Many consumers need same data | ❌ Consider LMS | ✅ |
1129
+ | Component hierarchy is deep (4+ levels) | ❌ Consider LMS | ✅ |
1130
+
1131
+ **Rule of thumb**: If components share a parent and data flow is simple, use sibling pattern. If components are "far apart" in the DOM or you need pub/sub semantics, use LMS.
1132
+
1133
+ ---
1134
+
1135
+ ## Navigation Patterns
1136
+
1137
+ ```javascript
1138
+ // navigator.js
1139
+ import { LightningElement } from 'lwc';
1140
+ import { NavigationMixin } from 'lightning/navigation';
1141
+
1142
+ export default class Navigator extends NavigationMixin(LightningElement) {
1143
+
1144
+ navigateToRecord(recordId, objectApiName = 'Account') {
1145
+ this[NavigationMixin.Navigate]({
1146
+ type: 'standard__recordPage',
1147
+ attributes: {
1148
+ recordId,
1149
+ objectApiName,
1150
+ actionName: 'view'
1151
+ }
1152
+ });
1153
+ }
1154
+
1155
+ navigateToList(objectApiName, filterName = 'Recent') {
1156
+ this[NavigationMixin.Navigate]({
1157
+ type: 'standard__objectPage',
1158
+ attributes: {
1159
+ objectApiName,
1160
+ actionName: 'list'
1161
+ },
1162
+ state: { filterName }
1163
+ });
1164
+ }
1165
+
1166
+ navigateToNewRecord(objectApiName, defaultValues = {}) {
1167
+ this[NavigationMixin.Navigate]({
1168
+ type: 'standard__objectPage',
1169
+ attributes: {
1170
+ objectApiName,
1171
+ actionName: 'new'
1172
+ },
1173
+ state: {
1174
+ defaultFieldValues: Object.entries(defaultValues)
1175
+ .map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
1176
+ .join(',')
1177
+ }
1178
+ });
1179
+ }
1180
+
1181
+ navigateToRelatedList(recordId, relationshipApiName) {
1182
+ this[NavigationMixin.Navigate]({
1183
+ type: 'standard__recordRelationshipPage',
1184
+ attributes: {
1185
+ recordId,
1186
+ relationshipApiName,
1187
+ actionName: 'view'
1188
+ }
1189
+ });
1190
+ }
1191
+
1192
+ navigateToNamedPage(pageName, params = {}) {
1193
+ this[NavigationMixin.Navigate]({
1194
+ type: 'standard__namedPage',
1195
+ attributes: {
1196
+ pageName
1197
+ },
1198
+ state: params
1199
+ });
1200
+ }
1201
+ }
1202
+ ```
1203
+
1204
+ ---
1205
+
1206
+ ## TypeScript Patterns
1207
+
1208
+ ### TypeScript Component Pattern
1209
+
1210
+ ```typescript
1211
+ // accountList.ts
1212
+ import { LightningElement, api, wire, track } from 'lwc';
1213
+ import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
1214
+ import getAccounts from '@salesforce/apex/AccountController.getAccounts';
1215
+ import ACCOUNT_NAME_FIELD from '@salesforce/schema/Account.Name';
1216
+
1217
+ // Define interfaces for type safety
1218
+ interface AccountRecord {
1219
+ Id: string;
1220
+ Name: string;
1221
+ Industry?: string;
1222
+ AnnualRevenue?: number;
1223
+ }
1224
+
1225
+ interface WireResult<T> {
1226
+ data?: T;
1227
+ error?: Error;
1228
+ }
1229
+
1230
+ export default class AccountList extends LightningElement {
1231
+ // Typed @api properties
1232
+ @api recordId: string | undefined;
1233
+
1234
+ @api
1235
+ get maxRecords(): number {
1236
+ return this._maxRecords;
1237
+ }
1238
+ set maxRecords(value: number) {
1239
+ this._maxRecords = value;
1240
+ }
1241
+
1242
+ // Typed @track properties
1243
+ @track private _accounts: AccountRecord[] = [];
1244
+ @track private _error: string | null = null;
1245
+
1246
+ private _maxRecords: number = 10;
1247
+ private _wiredResult: WireResult<AccountRecord[]> | undefined;
1248
+
1249
+ // Typed wire service
1250
+ @wire(getAccounts, { maxRecords: '$maxRecords' })
1251
+ wiredAccounts(result: WireResult<AccountRecord[]>): void {
1252
+ this._wiredResult = result;
1253
+ const { data, error } = result;
1254
+
1255
+ if (data) {
1256
+ this._accounts = data;
1257
+ this._error = null;
1258
+ } else if (error) {
1259
+ this._error = this.reduceErrors(error);
1260
+ this._accounts = [];
1261
+ }
1262
+ }
1263
+
1264
+ // Typed getters
1265
+ get accounts(): AccountRecord[] {
1266
+ return this._accounts;
1267
+ }
1268
+
1269
+ get hasAccounts(): boolean {
1270
+ return this._accounts.length > 0;
1271
+ }
1272
+
1273
+ // Typed event handlers
1274
+ handleSelect(event: CustomEvent<{ accountId: string }>): void {
1275
+ const { accountId } = event.detail;
1276
+ this.dispatchEvent(new CustomEvent('accountselected', {
1277
+ detail: { accountId },
1278
+ bubbles: true,
1279
+ composed: true
1280
+ }));
1281
+ }
1282
+
1283
+ // Typed utility methods
1284
+ private reduceErrors(error: Error | Error[]): string {
1285
+ const errors = Array.isArray(error) ? error : [error];
1286
+ return errors
1287
+ .filter((e): e is Error => e !== null)
1288
+ .map(e => e.message || 'Unknown error')
1289
+ .join('; ');
1290
+ }
1291
+ }
1292
+ ```
1293
+
1294
+ ### TypeScript Jest Test Pattern
1295
+
1296
+ ```typescript
1297
+ // accountList.test.ts
1298
+ import { createElement, LightningElement } from 'lwc';
1299
+ import AccountList from 'c/accountList';
1300
+ import getAccounts from '@salesforce/apex/AccountController.getAccounts';
1301
+
1302
+ // Type definitions for tests
1303
+ interface AccountRecord {
1304
+ Id: string;
1305
+ Name: string;
1306
+ Industry?: string;
1307
+ }
1308
+
1309
+ // Mock Apex
1310
+ jest.mock(
1311
+ '@salesforce/apex/AccountController.getAccounts',
1312
+ () => ({ default: jest.fn() }),
1313
+ { virtual: true }
1314
+ );
1315
+
1316
+ const MOCK_ACCOUNTS: AccountRecord[] = [
1317
+ { Id: '001xx000003DGQ', Name: 'Acme Corp', Industry: 'Technology' }
1318
+ ];
1319
+
1320
+ describe('c-account-list', () => {
1321
+ let element: LightningElement & { maxRecords?: number };
1322
+
1323
+ afterEach(() => {
1324
+ while (document.body.firstChild) {
1325
+ document.body.removeChild(document.body.firstChild);
1326
+ }
1327
+ jest.clearAllMocks();
1328
+ });
1329
+
1330
+ it('displays accounts after data loads', async () => {
1331
+ (getAccounts as jest.Mock).mockResolvedValue(MOCK_ACCOUNTS);
1332
+
1333
+ element = createElement('c-account-list', { is: AccountList });
1334
+ document.body.appendChild(element);
1335
+
1336
+ await Promise.resolve();
1337
+
1338
+ const items = element.shadowRoot?.querySelectorAll('.slds-item');
1339
+ expect(items?.length).toBe(MOCK_ACCOUNTS.length);
1340
+ });
1341
+ });
1342
+ ```
1343
+
1344
+ ### TypeScript Features for LWC
1345
+
1346
+ | Feature | LWC Support | Notes |
1347
+ |---------|-------------|-------|
1348
+ | **Interface definitions** | ✅ | Define shapes for records, events, props |
1349
+ | **Typed @api properties** | ✅ | Getter/setter patterns with types |
1350
+ | **Typed @wire results** | ✅ | Generic `WireResult<T>` pattern |
1351
+ | **Typed event handlers** | ✅ | `CustomEvent<T>` for event detail typing |
1352
+ | **Private class fields** | ✅ | Use `private` keyword |
1353
+ | **Strict null checking** | ✅ | Optional chaining `?.` and nullish coalescing `??` |
1354
+
1355
+ ---
1356
+
1357
+ ## Apex Controller Patterns
1358
+
1359
+ ### Cacheable Methods (for @wire)
1360
+
1361
+ ```apex
1362
+ public with sharing class LwcController {
1363
+
1364
+ @AuraEnabled(cacheable=true)
1365
+ public static List<Account> getAccounts(String searchTerm) {
1366
+ String searchKey = '%' + String.escapeSingleQuotes(searchTerm) + '%';
1367
+ return [
1368
+ SELECT Id, Name, Industry, AnnualRevenue
1369
+ FROM Account
1370
+ WHERE Name LIKE :searchKey
1371
+ WITH SECURITY_ENFORCED
1372
+ ORDER BY Name
1373
+ LIMIT 50
1374
+ ];
1375
+ }
1376
+
1377
+ @AuraEnabled(cacheable=true)
1378
+ public static List<PicklistOption> getIndustryOptions() {
1379
+ List<PicklistOption> options = new List<PicklistOption>();
1380
+ Schema.DescribeFieldResult fieldResult =
1381
+ Account.Industry.getDescribe();
1382
+ for (Schema.PicklistEntry entry : fieldResult.getPicklistValues()) {
1383
+ if (entry.isActive()) {
1384
+ options.add(new PicklistOption(entry.getLabel(), entry.getValue()));
1385
+ }
1386
+ }
1387
+ return options;
1388
+ }
1389
+
1390
+ public class PicklistOption {
1391
+ @AuraEnabled public String label;
1392
+ @AuraEnabled public String value;
1393
+
1394
+ public PicklistOption(String label, String value) {
1395
+ this.label = label;
1396
+ this.value = value;
1397
+ }
1398
+ }
1399
+ }
1400
+ ```
1401
+
1402
+ ### Non-Cacheable Methods (for DML)
1403
+
1404
+ ```apex
1405
+ @AuraEnabled
1406
+ public static Account createAccount(String accountJson) {
1407
+ Account acc = (Account) JSON.deserialize(accountJson, Account.class);
1408
+
1409
+ // FLS check
1410
+ SObjectAccessDecision decision = Security.stripInaccessible(
1411
+ AccessType.CREATABLE,
1412
+ new List<Account>{ acc }
1413
+ );
1414
+
1415
+ insert decision.getRecords();
1416
+ return (Account) decision.getRecords()[0];
1417
+ }
1418
+
1419
+ @AuraEnabled
1420
+ public static void deleteAccounts(List<Id> accountIds) {
1421
+ if (accountIds == null || accountIds.isEmpty()) {
1422
+ throw new AuraHandledException('No accounts to delete');
1423
+ }
1424
+
1425
+ List<Account> toDelete = [
1426
+ SELECT Id FROM Account
1427
+ WHERE Id IN :accountIds
1428
+ WITH SECURITY_ENFORCED
1429
+ ];
1430
+
1431
+ delete toDelete;
1432
+ }
1433
+ ```
1434
+
1435
+ ### Error Handling Pattern
1436
+
1437
+ ```apex
1438
+ @AuraEnabled
1439
+ public static List<Contact> getContactsWithErrorHandling(Id accountId) {
1440
+ try {
1441
+ if (accountId == null) {
1442
+ throw new AuraHandledException('Account ID is required');
1443
+ }
1444
+
1445
+ List<Contact> contacts = [
1446
+ SELECT Id, Name, Email, Phone
1447
+ FROM Contact
1448
+ WHERE AccountId = :accountId
1449
+ WITH SECURITY_ENFORCED
1450
+ ORDER BY Name
1451
+ LIMIT 100
1452
+ ];
1453
+
1454
+ return contacts;
1455
+ } catch (Exception e) {
1456
+ throw new AuraHandledException('Error fetching contacts: ' + e.getMessage());
1457
+ }
1458
+ }
1459
+ ```
1460
+
1461
+ ---
1462
+
1463
+ ## Related Resources
1464
+
1465
+ - [lms-guide.md](lms-guide.md) - Lightning Message Service deep dive
1466
+ - [jest-testing.md](jest-testing.md) - Advanced testing patterns
1467
+ - [accessibility-guide.md](accessibility-guide.md) - WCAG compliance
1468
+ - [performance-guide.md](performance-guide.md) - Optimization techniques
1469
+
1470
+ ---
1471
+
1472
+ ## External References
1473
+
1474
+ - [PICKLES Framework](https://www.salesforceben.com/the-ideal-framework-for-architecting-salesforce-lightning-web-components/) — David Picksley, Third Eye Consulting
1475
+ - [LWC Recipes (GitHub)](https://github.com/trailheadapps/lwc-recipes)
1476
+ - [James Simone - Composable Modal](https://www.jamessimone.net/blog/joys-of-apex/lwc-composable-modal/)