@salesforce/afv-skills 1.56.0 → 1.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/commerce-b2b-open-code-components-integrate/SKILL.md +1 -1
- package/skills/commerce-b2b-open-code-components-replace/SKILL.md +16 -16
- package/skills/dx-devops-project-manage/SKILL.md +1 -1
- package/skills/experience-cms-content-generate/SKILL.md +1 -1
- package/skills/experience-cms-content-render/SKILL.md +3 -3
- package/skills/experience-cms-content-render/assets/angular/MediaRenderer.component.ts +35 -7
- package/skills/experience-cms-content-render/assets/angular/cms-item.service.ts +13 -4
- package/skills/experience-cms-content-render/assets/react/MediaRenderer.tsx +30 -8
- package/skills/experience-cms-content-render/assets/react/useCmsItem.ts +14 -4
- package/skills/experience-cms-content-render/assets/shared/cmsCore.types.ts +11 -1
- package/skills/experience-cms-content-render/assets/shared/externalRefs.ts +1 -1
- package/skills/experience-cms-content-render/assets/shared/mediaLabels.ts +62 -0
- package/skills/experience-cms-content-render/references/init-scaffold.md +13 -6
- package/skills/experience-content-media-stock-image-search/SKILL.md +0 -1
- package/skills/experience-lwc-design-generate/SKILL.md +1 -1
- package/skills/experience-lwc-legacy-migrate/SKILL.md +212 -0
- package/skills/experience-lwc-legacy-migrate/assets/lo20-host-page-template.html +192 -0
- package/skills/experience-lwc-legacy-migrate/references/aura-to-lwc-completeness-checklist.md +188 -0
- package/skills/experience-lwc-legacy-migrate/references/lightning-out-2-system-reference.md +495 -0
- package/skills/experience-lwc-legacy-migrate/references/lightning-out-beta-to-2-migration.md +824 -0
- package/skills/experience-lwc-legacy-migrate/scripts/convert-lo-names.py +94 -0
- package/skills/experience-lwc-legacy-migrate/scripts/validate-lo20-page.py +133 -0
- package/skills/experience-ui-bundle-project-generate/SKILL.md +14 -40
- package/skills/experience-ui-bundle-project-generate/scripts/flatten-project.mjs +33 -11
- package/skills/experience-ui-bundle-project-generate/scripts/generate-project.mjs +77 -0
- package/skills/experience-ui-bundle-project-generate/scripts/install-deps.mjs +95 -0
- package/skills/integration-connectivity-connected-app-configure/SKILL.md +5 -5
- package/skills/integration-connectivity-generate/SKILL.md +10 -10
- package/skills/integration-connectivity-generate/scripts/configure-named-credential.sh +2 -2
- package/skills/platform-apex-test-generate/SKILL.md +1 -1
- package/skills/platform-apex-test-run/SKILL.md +1 -1
- package/skills/platform-custom-field-generate/SKILL.md +1 -1
- package/skills/platform-custom-lightning-type-generate/SKILL.md +1 -1
- package/skills/platform-custom-metadata-type-generate/SKILL.md +1 -1
- package/skills/platform-custom-object-generate/SKILL.md +1 -1
- package/skills/platform-custom-report-type-generate/SKILL.md +1 -1
- package/skills/platform-custom-setting-generate/SKILL.md +1 -1
- package/skills/platform-data-and-tooling-api-context-get/SKILL.md +1 -1
- package/skills/platform-data-manage/SKILL.md +10 -10
- package/skills/platform-flexipage-generate/SKILL.md +1 -1
- package/skills/platform-lightning-app-coordinate/SKILL.md +1 -1
- package/skills/platform-metadata-api-context-get/SKILL.md +1 -1
- package/skills/platform-metadata-retrieve/SKILL.md +1 -1
- package/skills/platform-permission-set-generate/SKILL.md +1 -1
- package/skills/platform-report-generate/SKILL.md +1 -1
- package/skills/platform-salesforce-connect-adapter-generate/SKILL.md +4 -4
- package/skills/platform-sharing-owd-configure/SKILL.md +1 -1
- package/skills/platform-sharing-rules-generate/SKILL.md +1 -1
- package/skills/platform-soql-query/SKILL.md +1 -1
- package/skills/platform-value-set-generate/SKILL.md +1 -1
- package/skills/service-agentforce-human-escalation-configure/SKILL.md +4 -0
- package/skills/service-agentforce-human-escalation-configure/scripts/tests/_bootstrap.py +26 -6
- package/skills/service-agentforce-human-escalation-configure/scripts/tests/test_escalation_contracts.py +5 -4
- package/skills/service-de-waba-integrate/SKILL.md +2 -1
- package/skills/service-digital-engagement-deployment-configure/SKILL.md +2 -0
- package/skills/service-digital-engagement-deployment-configure/scripts/check-api-version.sh +29 -0
- package/skills/service-email-to-case-configure/SKILL.md +1 -1
- package/skills/service-omni-channel-setup-coordinate/SKILL.md +1 -0
- package/skills/service-omni-command-center-analyze/SKILL.md +1 -0
- package/skills/service-omni-command-center-configure/SKILL.md +92 -0
- package/skills/service-omni-command-center-configure/references/api-notes.md +50 -0
- package/skills/service-omni-command-center-configure/scripts/configure-and-report.sh +257 -0
- package/skills/service-omni-command-center-configure/scripts/settings_document.py +97 -0
- package/skills/service-omni-command-center-configure/scripts/tests/test_command_center_configure_contracts.py +206 -0
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
Lightning Out 2.0 is **not** a simple library upgrade. It is an entirely different embedding paradigm built on Web Components and iframes. This reference captures the essential architecture, constraints, and mental model.
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
### 1. Foundational Mental Model
|
|
6
|
+
|
|
7
|
+
#### Core Principle: Dual-Context Architecture
|
|
8
|
+
|
|
9
|
+
LO 2.0 creates a **two-world system** on every host page:
|
|
10
|
+
|
|
11
|
+
| Context | Runs on | Contains | Controlled by |
|
|
12
|
+
| ---------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------- | ------------------ |
|
|
13
|
+
| **Host page context** | The external (non-Salesforce) page | LO 2.0 web components (shells), the `lightning-out-application` element, host page JS | The developer |
|
|
14
|
+
| **Salesforce context** | Inside iframes within closed shadow DOMs | The actual LWC components, Salesforce platform services (LDS, Apex, etc.) | Salesforce runtime |
|
|
15
|
+
|
|
16
|
+
**Why this matters for migration**: In Lightning Out Beta, the LWC ran directly on the host page via `$Lightning.createComponent()`. In LO 2.0, the LWC is isolated inside an iframe. This means:
|
|
17
|
+
|
|
18
|
+
- Host page JavaScript **cannot** directly access DOM inside the LWC.
|
|
19
|
+
- The LWC **cannot** directly access host page DOM.
|
|
20
|
+
- Communication must go through the event bridge (see Section 5).
|
|
21
|
+
- CSS from the host page does **not** cascade into the iframe (see Section 4).
|
|
22
|
+
|
|
23
|
+
#### The Three Pillars of a LO 2.0 App
|
|
24
|
+
|
|
25
|
+
Every LO 2.0 app on a host page consists of exactly three elements:
|
|
26
|
+
|
|
27
|
+
1. **The LO 2.0 JavaScript library** — A `<script>` tag that loads the LO 2.0 runtime, which registers the custom elements.
|
|
28
|
+
2. **The `<lightning-out-application>` element** — A non-visual web component that holds the app configuration (auth, optional app ID, component list). There should be **exactly one** per app.
|
|
29
|
+
3. **One or more LO 2.0 web component shells** — Elements like `<c-my-component>` that mirror the embedded LWC components. Each shell contains an iframe with a closed shadow DOM root.
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
Host Page
|
|
33
|
+
├── <script src="...lightning.out.latest/index.iife.prod.js">
|
|
34
|
+
├── <lightning-out-application app-id="..." frontdoor-url="..." components="c-my-comp">
|
|
35
|
+
└── <c-my-comp style="--custom-color: blue;">
|
|
36
|
+
└── #shadow-root (closed)
|
|
37
|
+
└── <iframe>
|
|
38
|
+
└── <html> (Salesforce context)
|
|
39
|
+
└── <body>
|
|
40
|
+
└── <c-my-comp style="--custom-color: blue;"> ← actual LWC
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
### 2. Initialization Lifecycle (Exact Sequence)
|
|
46
|
+
|
|
47
|
+
Understanding the initialization order is critical for writing correct mount and readiness code.
|
|
48
|
+
|
|
49
|
+
#### Step-by-Step Flow
|
|
50
|
+
|
|
51
|
+
1. **End user opens host page** — The host page HTML loads.
|
|
52
|
+
2. **LO 2.0 library script loads** (async) — Registers `lightning-out-application` and other custom elements with the browser's `customElements` registry.
|
|
53
|
+
3. **Host page obtains a frontdoor URL** — Via the UI Bridge API, exchanging a Salesforce access token or Session ID. If the user is not authenticated, an OAuth flow (PKCE) is triggered first.
|
|
54
|
+
4. **Host page sets `frontdoor-url`** on `<lightning-out-application>` — This is done programmatically at runtime. The element must already have `components` set (and optionally `app-id`, if the app requires it).
|
|
55
|
+
5. **LO 2.0 establishes a session** using the frontdoor URL — The `lightning-out-application` element initiates a Salesforce session.
|
|
56
|
+
6. **`lo.application.ready` fires** — Indicates the Salesforce session was established successfully.
|
|
57
|
+
7. **LO 2.0 web component shells initialize** — Each shell creates an iframe that becomes the root of a closed shadow DOM.
|
|
58
|
+
8. **Inside the iframes, the actual LWC components initialize** — They run in the Salesforce context with full platform access.
|
|
59
|
+
9. **`lo.component.ready` fires** — Indicates the component rendered successfully inside its iframe.
|
|
60
|
+
|
|
61
|
+
#### Error Events
|
|
62
|
+
|
|
63
|
+
- **`lo.application.error`** — Session establishment failed. Has `detail.message` and `detail.originalError`.
|
|
64
|
+
- **`lo.component.error`** — Component render failed or runtime error in the LWC. Same detail structure.
|
|
65
|
+
|
|
66
|
+
#### Key Timing Implications
|
|
67
|
+
|
|
68
|
+
- The LO 2.0 library loads **asynchronously**. The `lightning-out-application` custom element may not be registered when your script runs. You **must** poll `customElements.get('lightning-out-application')` before creating/appending the element.
|
|
69
|
+
- The `frontdoor-url` attribute **must** be set dynamically at runtime. It cannot be hardcoded in HTML (the URL is session-specific and short-lived).
|
|
70
|
+
- Component readiness can be detected via `customElements.whenDefined('c-my-component')` — but the argument **must be a string literal**, not a variable (browsers resolve this at parse time in some implementations, and LO 2.0's internal custom element registration relies on the literal name).
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### 3. Authentication Model
|
|
75
|
+
|
|
76
|
+
#### Beta vs. 2.0 Authentication
|
|
77
|
+
|
|
78
|
+
| Aspect | Lightning Out Beta | Lightning Out 2.0 |
|
|
79
|
+
| ---------------- | ---------------------------------------------------- | -------------------------------------------------------------- |
|
|
80
|
+
| Auth mechanism | Hardcoded session token passed to `$Lightning.use()` | OAuth 2.0 PKCE flow → frontdoor URL |
|
|
81
|
+
| Token location | In JavaScript source (insecure) | Never exposed in source; exchanged via UI Bridge API |
|
|
82
|
+
| Session init | `$Lightning.use(app, callback, endpoint, token)` | Set `frontdoor-url` attribute on `<lightning-out-application>` |
|
|
83
|
+
| User requirement | Authenticated Salesforce user | Authenticated Salesforce user (unauthenticated not supported) |
|
|
84
|
+
|
|
85
|
+
#### OAuth 2.0 PKCE Flow in LO 2.0
|
|
86
|
+
|
|
87
|
+
The typical flow involves:
|
|
88
|
+
|
|
89
|
+
1. Store OAuth config in `localStorage` (`orgMyDomainURL`, `loAppID`, `loECAKey`, `lo2_returnTo`).
|
|
90
|
+
2. Redirect user to OAuth callback page (e.g., `/frontdoor-url.html`).
|
|
91
|
+
3. Callback page completes PKCE, obtains frontdoor URL.
|
|
92
|
+
4. Callback page communicates the frontdoor URL back to the host page via **three redundant channels**:
|
|
93
|
+
- `window.postMessage()` — For same-window communication.
|
|
94
|
+
- `BroadcastChannel('lo2auth')` — For same-origin, cross-tab communication.
|
|
95
|
+
- `localStorage` event (`lo2_frontdoor_result`) — Fallback for cross-tab communication.
|
|
96
|
+
|
|
97
|
+
#### Why Three Channels?
|
|
98
|
+
|
|
99
|
+
Browser support and tab lifecycle vary. `postMessage` works when the callback is in the same tab. `BroadcastChannel` works cross-tab but isn't supported everywhere. The `storage` event is the most broadly supported cross-tab mechanism. Listening on all three ensures reliable auth completion.
|
|
100
|
+
|
|
101
|
+
#### Constraint: No Client Credentials Flow
|
|
102
|
+
|
|
103
|
+
LO 2.0 does not support OAuth 2.0 client credentials flow because that flow lacks user context. Every LO 2.0 session requires an authenticated Salesforce user identity.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
### 4. Styling System — What Crosses the iframe Boundary
|
|
108
|
+
|
|
109
|
+
#### The Fundamental Rule
|
|
110
|
+
|
|
111
|
+
**Only CSS custom properties (variables with `--` prefix) cross from the host page into the iframe.** Standard CSS properties like `font-size`, `background-color`, `font-family` are **blocked** at the iframe boundary.
|
|
112
|
+
|
|
113
|
+
#### What Works
|
|
114
|
+
|
|
115
|
+
- SLDS 1 styling hooks: `--slds-c-card-color-background`, `--slds-c-card-text-color`, etc.
|
|
116
|
+
- SLDS 2 global styling hooks: `--slds-g-color-brand-base-30`, `--slds-g-font-scale-3`, etc.
|
|
117
|
+
- Custom CSS properties: `--custom-color`, `--my-app-spacing`, etc.
|
|
118
|
+
- CSS custom property values with `var()` fallbacks: `var(--slds-g-color-brand-base-30, #022ac0)`.
|
|
119
|
+
|
|
120
|
+
#### What Does NOT Work
|
|
121
|
+
|
|
122
|
+
- Direct CSS properties: `font-family: cursive` — **will be ignored**.
|
|
123
|
+
- Direct CSS properties: `font-size: 120%` — **will be ignored**.
|
|
124
|
+
- Any standard CSS property that is not a custom property (no `--` prefix).
|
|
125
|
+
|
|
126
|
+
#### How to Style LO 2.0 Components
|
|
127
|
+
|
|
128
|
+
1. **In the LWC's CSS file**, declare CSS custom properties on `:host` and reference them in rules:
|
|
129
|
+
```css
|
|
130
|
+
:host {
|
|
131
|
+
--custom-color: #b50be3;
|
|
132
|
+
}
|
|
133
|
+
h1 {
|
|
134
|
+
color: var(--custom-color);
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
2. **On the host page**, override the custom properties via the `style` attribute:
|
|
138
|
+
```html
|
|
139
|
+
<c-my-comp style="--custom-color: #8c23a8;"></c-my-comp>
|
|
140
|
+
```
|
|
141
|
+
3. Properties can also be set via JSON in the Lightning Out 2.0 App Manager or programmatically via `setAttribute('style', ...)`.
|
|
142
|
+
|
|
143
|
+
#### Supported Standard Attributes
|
|
144
|
+
|
|
145
|
+
These standard HTML attributes **are** passed through to the LWC:
|
|
146
|
+
`autocapitalize`, `autocorrect`, `dir`, `enterkeyhint`, `inputmode`, `lang`, `spellcheck`, `title`, `translate`.
|
|
147
|
+
|
|
148
|
+
#### Supported ARIA Attributes
|
|
149
|
+
|
|
150
|
+
`aria-disabled`, `aria-hidden`, `aria-label`, `aria-live`, `aria-modal`, `aria-pressed`, `aria-valuemax`, `aria-valuemin`, `aria-valuenow`.
|
|
151
|
+
|
|
152
|
+
#### Blocked Standard Attributes
|
|
153
|
+
|
|
154
|
+
These are **NOT** passed through:
|
|
155
|
+
`accesskey`, `autofocus`, `draggable`, `exportparts`, `hidden`, `inert`, `nonce`, `part`, `slot`, `tabindex`.
|
|
156
|
+
|
|
157
|
+
#### Blocked ARIA Attributes (Reference-Based)
|
|
158
|
+
|
|
159
|
+
These ARIA attributes that reference other elements by ID are blocked because IDs don't cross iframe boundaries:
|
|
160
|
+
`aria-activedescendant`, `aria-controls`, `aria-describedby`, `aria-details`, `aria-errormessage`, `aria-flowto`, `aria-labelledby`, `aria-owns`.
|
|
161
|
+
|
|
162
|
+
#### Custom Attributes
|
|
163
|
+
|
|
164
|
+
All custom `@api` properties exposed on the LWC are supported as HTML attributes on the LO 2.0 shell — **unless the attribute name starts with an underscore** (`_`). Attributes are passed in kebab-case (e.g., LWC property `cardBody` → HTML attribute `card-body`).
|
|
165
|
+
|
|
166
|
+
Passing an unsupported attribute silently does nothing — no compilation or runtime error is raised.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
### 5. Event System — Cross-iframe Communication
|
|
171
|
+
|
|
172
|
+
#### How It Works Internally
|
|
173
|
+
|
|
174
|
+
LO 2.0 uses `window.postMessage()` under the hood to bridge events across the iframe boundary. However, from the developer's perspective, the standard `EventTarget` and `CustomEvent` APIs are used directly.
|
|
175
|
+
|
|
176
|
+
#### Event Mirroring
|
|
177
|
+
|
|
178
|
+
The LO 2.0 web component shell on the host page **mirrors** the embedded LWC component in the iframe. This mirroring extends to events:
|
|
179
|
+
|
|
180
|
+
- **Adding a listener** on the shell also adds it on the LWC inside the iframe.
|
|
181
|
+
- **Dispatching an event** on the shell also dispatches it on the LWC inside the iframe.
|
|
182
|
+
- Events dispatched **inside the LWC** bubble up to the shell on the host page.
|
|
183
|
+
- Events dispatched **on the shell** propagate down to the LWC inside the iframe.
|
|
184
|
+
|
|
185
|
+
#### Required Event Configuration
|
|
186
|
+
|
|
187
|
+
Custom events that need to cross the iframe boundary **must** set:
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
new CustomEvent('myEvent', {
|
|
191
|
+
detail: {
|
|
192
|
+
/* payload */
|
|
193
|
+
},
|
|
194
|
+
bubbles: true, // Required: to cross shadow DOM boundary
|
|
195
|
+
composed: true, // Required: to cross shadow DOM boundary
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Without `bubbles: true` and `composed: true`, the event will not pass through the closed shadow DOM.
|
|
200
|
+
|
|
201
|
+
#### Host Page → LWC Communication
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
// On the host page:
|
|
205
|
+
const loComponent = document.querySelector('c-my-component');
|
|
206
|
+
loComponent.dispatchEvent(
|
|
207
|
+
new CustomEvent('sendMessageToLWC', {
|
|
208
|
+
detail: { message: 'Hello from host' },
|
|
209
|
+
bubbles: true,
|
|
210
|
+
composed: true,
|
|
211
|
+
}),
|
|
212
|
+
);
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
```javascript
|
|
216
|
+
// In the LWC (connectedCallback):
|
|
217
|
+
this.addEventListener('sendMessageToLWC', this.handleMessage);
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
#### LWC → Host Page Communication
|
|
221
|
+
|
|
222
|
+
```javascript
|
|
223
|
+
// In the LWC:
|
|
224
|
+
this.dispatchEvent(
|
|
225
|
+
new CustomEvent('lwcMessageToHost', {
|
|
226
|
+
detail: { message: 'Hello from LWC' },
|
|
227
|
+
bubbles: true,
|
|
228
|
+
composed: true,
|
|
229
|
+
}),
|
|
230
|
+
);
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
```javascript
|
|
234
|
+
// On the host page:
|
|
235
|
+
const loComponent = document.querySelector('c-my-component');
|
|
236
|
+
loComponent.addEventListener('lwcMessageToHost', (event) => {
|
|
237
|
+
console.log(event.detail.message);
|
|
238
|
+
});
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
#### Timing Consideration
|
|
242
|
+
|
|
243
|
+
Set event listeners on the LO 2.0 shell component **after** the application and component have loaded. For example, conditionally set listeners after the `frontdoor-url` attribute is set or after `lo.component.ready` fires.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
### 6. Hard Constraints & Limitations
|
|
248
|
+
|
|
249
|
+
These are non-negotiable platform boundaries. No workaround exists for these limitations.
|
|
250
|
+
|
|
251
|
+
#### Component Constraints
|
|
252
|
+
|
|
253
|
+
- **Only custom LWC components** can be embedded. Standard LWC components (`lightning-button`, `lightning-card`, etc.) must be **wrapped** inside a custom LWC. Even when wrapped, they may not be fully styled or behave as documented.
|
|
254
|
+
- **No Aura components** — Neither custom nor standard Aura components are supported. This includes Aura apps — the `c:OrgFarmOut` Aura app pattern from Beta is replaced by the `app-id` attribute.
|
|
255
|
+
- **No `lightning/navigation`** — Page navigation within embedded components is not supported.
|
|
256
|
+
|
|
257
|
+
#### Security & Cookie Constraints
|
|
258
|
+
|
|
259
|
+
- **Third-party cookies required** — End users must have third-party (cross-origin) cookies enabled in their browser. Cross-domain Salesforce session cookies must also be enabled in the org.
|
|
260
|
+
- **No LO 2.0 library loading from LWC** — Lightning Web Security (LWS) blocks insertion of `<script>` elements. The library must be loaded from the host page directly.
|
|
261
|
+
|
|
262
|
+
#### Authentication Constraints
|
|
263
|
+
|
|
264
|
+
- **Authenticated users only** — Unauthenticated access is not supported.
|
|
265
|
+
- **No client credentials flow** — Requires user context (PKCE or session-based).
|
|
266
|
+
|
|
267
|
+
#### Style Constraints (Summary)
|
|
268
|
+
|
|
269
|
+
- Only CSS custom properties (`--` prefix) cross the iframe boundary.
|
|
270
|
+
- Standard CSS properties set on the shell are NOT applied inside the iframe.
|
|
271
|
+
- Blocked attributes (see Section 4) silently fail — no error raised.
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
### 7. Component Naming Conventions
|
|
276
|
+
|
|
277
|
+
#### Conversion from Aura to LO 2.0
|
|
278
|
+
|
|
279
|
+
Aura components use the `namespace:componentName` format. LO 2.0 uses kebab-case web component format.
|
|
280
|
+
|
|
281
|
+
**Algorithm:**
|
|
282
|
+
|
|
283
|
+
1. Remove `c:` prefix.
|
|
284
|
+
2. Insert hyphen before each uppercase letter.
|
|
285
|
+
3. Convert entire string to lowercase.
|
|
286
|
+
4. Add `c-` prefix.
|
|
287
|
+
|
|
288
|
+
**Examples:**
|
|
289
|
+
| Aura Format | LO 2.0 Kebab-Case |
|
|
290
|
+
|---|---|
|
|
291
|
+
| `c:myComponent` | `c-my-component` |
|
|
292
|
+
| `c:loBetaEntryForm` | `c-lo-beta-entry-form` |
|
|
293
|
+
| `c:userDashboard` | `c-user-dashboard` |
|
|
294
|
+
|
|
295
|
+
**Mixed-case namespaces** use underscores to separate namespace parts:
|
|
296
|
+
| Namespace/Component | LO 2.0 Format |
|
|
297
|
+
|---|---|
|
|
298
|
+
| `complexNs/lwcComponent` | `complex_ns-lwc-component` |
|
|
299
|
+
|
|
300
|
+
#### Attribute Name Conversion
|
|
301
|
+
|
|
302
|
+
LWC `@api` properties in camelCase become kebab-case HTML attributes:
|
|
303
|
+
| LWC Property | HTML Attribute |
|
|
304
|
+
|---|---|
|
|
305
|
+
| `contactId` | `contact-id` |
|
|
306
|
+
| `recordId` | `record-id` |
|
|
307
|
+
| `isActive` | `is-active` |
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
### 8. Domain Transformation Rules
|
|
312
|
+
|
|
313
|
+
The Salesforce domain format changes between Beta and 2.0:
|
|
314
|
+
|
|
315
|
+
| Component | Beta | 2.0 |
|
|
316
|
+
| -------------- | ----------------------------------------------- | ---------------------------------------------------- |
|
|
317
|
+
| Domain suffix | `.lightning.force.com` | `.my.salesforce.com` |
|
|
318
|
+
| Full pattern | `https://[subdomain].lightning.[pod].force.com` | `https://[subdomain].my.[pod].salesforce.com` |
|
|
319
|
+
| Library path | `/lightning/lightning.out.js` | `/lightning/lightning.out.latest/index.iife.prod.js` |
|
|
320
|
+
| Script loading | `<script src="...">` | `<script async src="...">` (note: `async` attribute) |
|
|
321
|
+
|
|
322
|
+
**Example transformation:**
|
|
323
|
+
|
|
324
|
+
```text
|
|
325
|
+
Beta: https://orgfarm-5b43fe90c6.test1.lightning.pc-rnd.force.com
|
|
326
|
+
LO 2.0: https://orgfarm-5b43fe90c6.test1.my.pc-rnd.salesforce.com
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
### 9. Configuration Methods for Component Properties
|
|
332
|
+
|
|
333
|
+
LO 2.0 supports three ways to set component properties:
|
|
334
|
+
|
|
335
|
+
#### A. Declarative (HTML)
|
|
336
|
+
|
|
337
|
+
Set attributes directly on the LO 2.0 web component shell in the host page HTML:
|
|
338
|
+
|
|
339
|
+
```html
|
|
340
|
+
<c-my-comp style="--slds-c-card-color-background: var(--secondary-color);" card-body="Custom text"></c-my-comp>
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
#### B. Programmatic (JavaScript)
|
|
344
|
+
|
|
345
|
+
Use DOM API methods to create and configure the component:
|
|
346
|
+
|
|
347
|
+
```javascript
|
|
348
|
+
const comp = document.createElement('c-my-comp');
|
|
349
|
+
comp.setAttribute('style', '--custom-color: blue;');
|
|
350
|
+
comp.setAttribute('card-body', 'Custom text');
|
|
351
|
+
document.body.appendChild(comp);
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
#### C. App Manager (Setup UI)
|
|
355
|
+
|
|
356
|
+
In the Lightning Out 2.0 App Manager, properties are set as a JSON object on each component:
|
|
357
|
+
|
|
358
|
+
```json
|
|
359
|
+
{
|
|
360
|
+
"style": "--slds-c-card-color-background: #ccc; --custom-color: blue;",
|
|
361
|
+
"card-body": "Custom text"
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
All three methods produce the same result: attributes on the LO 2.0 shell are mirrored to the LWC inside the iframe.
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
### 10. Critical Patterns for Correct Migration Code
|
|
370
|
+
|
|
371
|
+
These patterns are derived from real migration failures and represent hard requirements for a working LO 2.0 host page.
|
|
372
|
+
|
|
373
|
+
#### Pattern 1: The `boot()` Wrapper
|
|
374
|
+
|
|
375
|
+
All initialization logic MUST be wrapped in a single `boot()` function called at the end of the script. Do NOT split initialization into separate functions like `initializeOAuth()` and `setupCallbackListeners()`.
|
|
376
|
+
|
|
377
|
+
**Why**: Consolidating init in `boot()` ensures a single error boundary, predictable execution order, and a clear entry point. Splitting it risks partial initialization on error.
|
|
378
|
+
|
|
379
|
+
#### Pattern 2: `customElements.whenDefined()` Requires a String Literal
|
|
380
|
+
|
|
381
|
+
```javascript
|
|
382
|
+
// WRONG — will silently fail or behave unpredictably
|
|
383
|
+
const components = "c-my-component";
|
|
384
|
+
customElements.whenDefined(components).then(() => { ... });
|
|
385
|
+
|
|
386
|
+
// CORRECT — use the literal string directly
|
|
387
|
+
customElements.whenDefined('c-my-component').then(() => { ... });
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
**Why**: The browser's custom elements API and LO 2.0's internal registration can behave differently when a variable is passed vs. a literal. Always use the literal.
|
|
391
|
+
|
|
392
|
+
#### Pattern 3: `mountLo20()` Must Accept Two Parameters
|
|
393
|
+
|
|
394
|
+
```javascript
|
|
395
|
+
function mountLo20(frontdoorUrl, orgUrl) { ... }
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
**Why**: All three OAuth callback channels (`postMessage`, `BroadcastChannel`, `storage`) may pass both `frontdoorUrl` and `orgUrl`. Even if `orgUrl` is unused, the function signature must match what callers pass.
|
|
399
|
+
|
|
400
|
+
#### Pattern 4: Always `clearCachedResult()` Before Mounting
|
|
401
|
+
|
|
402
|
+
```javascript
|
|
403
|
+
clearCachedResult();
|
|
404
|
+
mountLo20(data.frontdoorUrl, data.orgUrl);
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
**Why**: Stale cache entries can cause duplicate mounts or auth loops. Clear before every mount call.
|
|
408
|
+
|
|
409
|
+
#### Pattern 5: Validate Data in Every Listener
|
|
410
|
+
|
|
411
|
+
Every OAuth callback listener must check three conditions:
|
|
412
|
+
|
|
413
|
+
```javascript
|
|
414
|
+
if (!data) return; // No data at all
|
|
415
|
+
if (data.error) return showError(...); // Auth error
|
|
416
|
+
if (!data.frontdoorUrl) return; // Incomplete data
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
#### Pattern 6: No Inline `display: none` on Component Tags
|
|
420
|
+
|
|
421
|
+
```html
|
|
422
|
+
<!-- WRONG -->
|
|
423
|
+
<c-my-component style="display: none"></c-my-component>
|
|
424
|
+
|
|
425
|
+
<!-- CORRECT -->
|
|
426
|
+
<c-my-component></c-my-component>
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**Why**: LO 2.0 initializes the component shell and its iframe. Adding `display: none` directly on the component tag can interfere with this initialization. Instead, control visibility through a separate loading element.
|
|
430
|
+
|
|
431
|
+
#### Pattern 7: Wrap `BroadcastChannel` in try-catch
|
|
432
|
+
|
|
433
|
+
```javascript
|
|
434
|
+
try {
|
|
435
|
+
const bc = new BroadcastChannel('lo2auth');
|
|
436
|
+
bc.onmessage = (evt) => { ... };
|
|
437
|
+
} catch (e) {
|
|
438
|
+
// Not supported in all browsers
|
|
439
|
+
}
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
#### Pattern 8: Poll for Custom Element Registration
|
|
443
|
+
|
|
444
|
+
The LO 2.0 library loads asynchronously. Before creating `lightning-out-application`, you must poll:
|
|
445
|
+
|
|
446
|
+
```javascript
|
|
447
|
+
function tryMount() {
|
|
448
|
+
if (!customElements?.get?.('lightning-out-application')) return false;
|
|
449
|
+
// ... create and append the element
|
|
450
|
+
return true;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const start = Date.now();
|
|
454
|
+
(function tick() {
|
|
455
|
+
if (tryMount()) return;
|
|
456
|
+
if (Date.now() - start > 15000) {
|
|
457
|
+
showError('Timeout');
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
setTimeout(tick, 50);
|
|
461
|
+
})();
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
### 11. What Changes During Migration (Summary)
|
|
467
|
+
|
|
468
|
+
| Aspect | Lightning Out Beta | Lightning Out 2.0 |
|
|
469
|
+
| ------------------- | ---------------------------------------------------------- | ---------------------------------------------------------------------- |
|
|
470
|
+
| Library URL | `.lightning.force.com/lightning/lightning.out.js` | `.my.salesforce.com/lightning/lightning.out.latest/index.iife.prod.js` |
|
|
471
|
+
| Script loading | Synchronous | Asynchronous (`async` attribute) |
|
|
472
|
+
| App reference | Aura app name (`c:OrgFarmOut`) | Optional 18-character App ID from Setup |
|
|
473
|
+
| Component naming | Aura format (`c:myComponent`) | Kebab-case (`c-my-component`) |
|
|
474
|
+
| Component init | `$Lightning.createComponent(name, attrs, domId, callback)` | Declarative HTML tag + `<lightning-out-application>` |
|
|
475
|
+
| Attributes | JavaScript object passed to `createComponent` | HTML attributes in kebab-case on the component tag |
|
|
476
|
+
| Readiness | Callback parameter in `createComponent` | `customElements.whenDefined('c-my-component')` |
|
|
477
|
+
| Auth | Hardcoded token in `$Lightning.use()` | OAuth PKCE → frontdoor URL set at runtime |
|
|
478
|
+
| Component isolation | Runs directly on host page | Runs inside iframe within closed shadow DOM |
|
|
479
|
+
| DOM access | Host JS can access component DOM | Host JS **cannot** access component DOM |
|
|
480
|
+
| CSS inheritance | Host page CSS cascades to component | **Only** CSS custom properties cross the boundary |
|
|
481
|
+
| Event communication | Direct DOM events | Mirrored events bridged via `postMessage` internally |
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
### 12. What to Preserve During Migration
|
|
486
|
+
|
|
487
|
+
When migrating a host page, the following elements from the original page **must be preserved**:
|
|
488
|
+
|
|
489
|
+
1. **HTML structure** — Layout, hierarchy, and element order. Don't restructure.
|
|
490
|
+
2. **Existing CSS and classes** — All host page styling remains unchanged.
|
|
491
|
+
3. **Loading indicators** — Hook into existing UI elements; don't create new ones.
|
|
492
|
+
4. **Error display mechanisms** — Use the page's existing error handling.
|
|
493
|
+
5. **Event handlers on non-LO elements** — Any click handlers, form logic, etc.
|
|
494
|
+
6. **Business logic from Beta callbacks** — Move callback logic from `$Lightning.createComponent`'s callback to `customElements.whenDefined().then()`.
|
|
495
|
+
7. **Element IDs and selectors** — Use the page's actual IDs, not template defaults.
|