@salesforce/vite-plugin-lwc-ui-bundle 1.131.1 → 1.131.3
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/README.md +36 -0
- package/dist/providers/index.js +2 -2
- package/dist/providers/index.js.map +1 -1
- package/docs/consumer-guide.md +429 -0
- package/package.json +4 -3
- package/skills/setup-lwc-vite-plugin/SKILL.md +242 -0
- package/docs/user-guide.md +0 -377
package/README.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Vite plugin for compiling and running LWC components off-platform. Bundles the full compilation pipeline — scoped module providers, Lightning npm resolution, missing CSS handling, and the Vite/LWC bridge — behind a single configurable entry point.
|
|
4
4
|
|
|
5
|
+
> **Getting started?** See the [Consumer Guide](docs/consumer-guide.md) for a
|
|
6
|
+
> step-by-step walkthrough of adding this plugin to an existing LWC project.
|
|
7
|
+
|
|
5
8
|
## Installation
|
|
6
9
|
|
|
7
10
|
```bash
|
|
@@ -220,3 +223,36 @@ globalThis.__sfdc_sdk__ = await createDataSDK({ uiBundle: { basePath: "/" } });
|
|
|
220
223
|
| ---------- | --------- | ------------------ | ------------------------------------ |
|
|
221
224
|
| `orgAlias` | `string` | sf CLI default org | Salesforce org alias |
|
|
222
225
|
| `debug` | `boolean` | `false` | Log each proxied request to terminal |
|
|
226
|
+
|
|
227
|
+
## Claude Code Skill
|
|
228
|
+
|
|
229
|
+
This package includes a [Claude Code](https://docs.anthropic.com/en/docs/claude-code) skill that interactively sets up the plugin in your LWC project. It detects your project structure, asks which component to use as the root, inspects the component tree for GraphQL/label/base-component usage, and generates all the config files.
|
|
230
|
+
|
|
231
|
+
### Installing the skill
|
|
232
|
+
|
|
233
|
+
**Option A — Global (available in all projects):**
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
cp -r node_modules/@salesforce/vite-plugin-lwc-ui-bundle/skills/setup-lwc-vite-plugin \
|
|
237
|
+
~/.claude/skills/setup-lwc-vite-plugin
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Option B — Project-scoped (available only in this project):**
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
mkdir -p .claude/skills
|
|
244
|
+
cp -r node_modules/@salesforce/vite-plugin-lwc-ui-bundle/skills/setup-lwc-vite-plugin \
|
|
245
|
+
.claude/skills/setup-lwc-vite-plugin
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Using the skill
|
|
249
|
+
|
|
250
|
+
Once installed, the skill triggers automatically in Claude Code when you ask things like:
|
|
251
|
+
|
|
252
|
+
- "Set up vite-plugin-lwc-ui-bundle in my project"
|
|
253
|
+
- "I want to run my LWC components outside Salesforce"
|
|
254
|
+
- "Build a static LWC bundle"
|
|
255
|
+
- "Add Vite to my SFDX project"
|
|
256
|
+
- "Compile LWC off-platform"
|
|
257
|
+
|
|
258
|
+
You can also invoke it explicitly with `/setup-lwc-vite-plugin`.
|
package/dist/providers/index.js
CHANGED
|
@@ -321,7 +321,7 @@ export class graphql {
|
|
|
321
321
|
try {
|
|
322
322
|
// 1. UIBundle / local dev: use globalThis.__sfdc_sdk__.graphql if available
|
|
323
323
|
if (typeof globalThis.__sfdc_sdk__?.graphql === 'function') {
|
|
324
|
-
const result = await globalThis.__sfdc_sdk__.graphql(query, variables);
|
|
324
|
+
const result = await globalThis.__sfdc_sdk__.graphql({ query, variables });
|
|
325
325
|
this._emit({ data: result?.data, errors: result?.errors });
|
|
326
326
|
return;
|
|
327
327
|
}
|
|
@@ -389,7 +389,7 @@ export async function executeMutation(config) {
|
|
|
389
389
|
try {
|
|
390
390
|
// 1. UIBundle / local dev
|
|
391
391
|
if (typeof globalThis.__sfdc_sdk__?.graphql === 'function') {
|
|
392
|
-
const result = await globalThis.__sfdc_sdk__.graphql(query, variables ?? {});
|
|
392
|
+
const result = await globalThis.__sfdc_sdk__.graphql({ query, variables: variables ?? {} });
|
|
393
393
|
return { data: result?.data, errors: result?.errors };
|
|
394
394
|
}
|
|
395
395
|
// 2. MCP surface
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/providers/label.ts","../../src/providers/i18n.ts","../../src/providers/gate.ts","../../src/providers/access-check.ts","../../src/providers/client.ts","../../src/providers/primitive-utils.ts","../../src/providers/lightning-graphql.ts"],"sourcesContent":["/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport type { Provider } from \"../types\";\n\nconst LABEL_DEFAULTS: Record<string, string> = {\n\t\"LightningForm.edit\": \"Edit\",\n\t\"LightningForm.save\": \"Save\",\n\t\"LightningForm.cancel\": \"Cancel\",\n\t\"LightningForm.error\": \"Error\",\n\t\"RecordDetailUC.Expand\": \"Expand\",\n\t\"RecordDetailUC.Collapse\": \"Collapse\",\n\t\"Global_Entity.created_by\": \"Created By\",\n\t\"Global_Entity.last_modified_by\": \"Last Modified By\",\n\t\"DetailError.GenericSaveError\": \"An error occurred while saving.\",\n\t\"MobileWebError.NoPreEditAccess\": \"You don't have access to edit this record.\",\n\t\"DuplicateList.ToastMessageBlock\": \"Duplicate records were found.\",\n\t\"DuplicateList.NonBlockingHeaderText\": \"Duplicate records found\",\n\t\"DuplicateList.ToastMessageAlertEdit\": \"Duplicate records were found. You can continue editing.\",\n\t\"Errors.ErrorPopoverHeading\": \"Error\",\n};\n\nexport function label(overrides: Record<string, string> = {}): Provider {\n\tconst defaults = { ...LABEL_DEFAULTS, ...overrides };\n\treturn {\n\t\tprefix: \"@salesforce/label/\",\n\t\tresolve(specifier) {\n\t\t\tif (!specifier.startsWith(\"@salesforce/label/\")) return null;\n\n\t\t\tconst key = specifier.slice(\"@salesforce/label/\".length);\n\t\t\tconst fallbackLabel = key\n\t\t\t\t.split(\".\")\n\t\t\t\t.at(-1)!\n\t\t\t\t.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n\t\t\t\t.replace(/_/g, \" \")\n\t\t\t\t.trim();\n\t\t\tconst value = defaults[key] ?? fallbackLabel;\n\t\t\treturn `export default ${JSON.stringify(value)};`;\n\t\t},\n\t};\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport type { Provider } from \"../types\";\n\nconst BROWSER_DERIVED = new Set([\n\t\"lang\",\n\t\"dir\",\n\t\"locale\",\n\t\"currency\",\n\t\"timeZone\",\n\t\"firstDayOfWeek\",\n]);\n\nconst STATIC_DEFAULTS: Record<string, string> = {\n\t\"dateTime.shortDateFormat\": \"M/d/yyyy\",\n\t\"dateTime.mediumDateFormat\": \"MMM d, yyyy\",\n\t\"dateTime.longDateFormat\": \"MMMM d, yyyy\",\n\t\"dateTime.shortTimeFormat\": \"h:mm a\",\n\t\"dateTime.mediumTimeFormat\": \"h:mm:ss a\",\n\t\"dateTime.longTimeFormat\": \"h:mm:ss a z\",\n\t\"dateTime.shortDateTimeFormat\": \"M/d/yyyy, h:mm a\",\n\t\"number.numberFormat\": \"#,##0.##\",\n\t\"number.currencyFormat\": \"¤#,##0.00\",\n\t\"number.decimalSeparator\": \".\",\n\t\"number.groupingSeparator\": \",\",\n\t\"number.percentFormat\": \"#,##0%\",\n\t\"number.percentSign\": \"%\",\n\t\"number.plusSign\": \"+\",\n\t\"number.minusSign\": \"-\",\n\t\"number.exponentialSign\": \"E\",\n\t\"number.superscriptingExponentSign\": \"×\",\n\t\"number.perMilleSign\": \"‰\",\n\t\"number.infinity\": \"∞\",\n\t\"number.nan\": \"NaN\",\n\t\"number.currencySymbol\": \"$\",\n\tdefaultCalendar: \"gregory\",\n\tdefaultNumberingSystem: \"latn\",\n};\n\nconst MONTHS_WIDE = [\n\t\"January\",\n\t\"February\",\n\t\"March\",\n\t\"April\",\n\t\"May\",\n\t\"June\",\n\t\"July\",\n\t\"August\",\n\t\"September\",\n\t\"October\",\n\t\"November\",\n\t\"December\",\n];\nconst MONTHS_ABBR = [\n\t\"Jan\",\n\t\"Feb\",\n\t\"Mar\",\n\t\"Apr\",\n\t\"May\",\n\t\"Jun\",\n\t\"Jul\",\n\t\"Aug\",\n\t\"Sep\",\n\t\"Oct\",\n\t\"Nov\",\n\t\"Dec\",\n];\nconst DAYS_WIDE = [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"];\nconst DAYS_ABBR = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n\nconst OBJECT_DEFAULTS: Record<string, unknown> = {\n\t\"common.digits\": { latn: \"0123456789\" },\n\t\"common.calendarData\": {\n\t\tgregory: { calendarSystem: \"solar\", eras: {} },\n\t},\n\tcalendarData: {\n\t\tgregory: {\n\t\t\tmonths: {\n\t\t\t\tformat: {\n\t\t\t\t\twide: MONTHS_WIDE,\n\t\t\t\t\tabbreviated: MONTHS_ABBR,\n\t\t\t\t\tnarrow: MONTHS_ABBR,\n\t\t\t\t},\n\t\t\t},\n\t\t\tdays: {\n\t\t\t\tformat: {\n\t\t\t\t\twide: DAYS_WIDE,\n\t\t\t\t\tabbreviated: DAYS_ABBR,\n\t\t\t\t\tnarrow: DAYS_ABBR,\n\t\t\t\t},\n\t\t\t},\n\t\t\tdayPeriods: {\n\t\t\t\tformat: {\n\t\t\t\t\twide: [\"AM\", \"PM\"],\n\t\t\t\t\tabbreviated: [\"am\", \"pm\"],\n\t\t\t\t\tnarrow: [\"a\", \"p\"],\n\t\t\t\t},\n\t\t\t},\n\t\t\teras: {\n\t\t\t\teraAbbr: [\"AD\"],\n\t\t\t\teraNames: [\"Anno Domini\"],\n\t\t\t\teraNarrow: [\"A\"],\n\t\t\t},\n\t\t},\n\t},\n};\n\nconst RUNTIME_SOURCE = `\nconst RTL_LANGS = new Set([\n 'ar', 'arc', 'dv', 'fa', 'ha', 'he', 'khw', 'ks', 'ku', 'ps', 'ur', 'yi',\n]);\n\nfunction getLocale() {\n if (typeof navigator === 'undefined') return 'en-US';\n return navigator.language || 'en-US';\n}\n\nfunction getLang() {\n return getLocale().split('-')[0];\n}\n\nfunction getDir() {\n return RTL_LANGS.has(getLang()) ? 'rtl' : 'ltr';\n}\n\nfunction getCurrency() {\n try {\n const parts = new Intl.NumberFormat(getLocale(), {\n style: 'currency',\n currency: 'USD',\n currencyDisplay: 'code',\n }).resolvedOptions();\n return parts.currency || 'USD';\n } catch {\n return 'USD';\n }\n}\n\nfunction getTimeZone() {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';\n } catch {\n return 'UTC';\n }\n}\n\nfunction getFirstDayOfWeek() {\n try {\n const loc = new Intl.Locale(getLocale());\n if (loc.weekInfo) return String(loc.weekInfo.firstDay);\n if (typeof loc.getWeekInfo === 'function') return String(loc.getWeekInfo().firstDay);\n } catch { /* unsupported in this browser */ }\n return '7';\n}\n\nconst values = {\n lang: getLang(),\n dir: getDir(),\n locale: getLocale(),\n currency: getCurrency(),\n timeZone: getTimeZone(),\n firstDayOfWeek: getFirstDayOfWeek(),\n};\n\nexport default values['__KEY__'];\n`;\n\nexport interface I18nOptions {\n\tstaticOverrides?: Record<string, string>;\n\tobjectOverrides?: Record<string, unknown>;\n}\n\nexport function i18n(options: I18nOptions = {}): Provider {\n\tconst { staticOverrides = {}, objectOverrides = {} } = options;\n\tconst statics = { ...STATIC_DEFAULTS, ...staticOverrides };\n\tconst objects = { ...OBJECT_DEFAULTS, ...objectOverrides };\n\n\treturn {\n\t\tprefix: \"@salesforce/i18n/\",\n\t\tresolve(specifier) {\n\t\t\tif (!specifier.startsWith(\"@salesforce/i18n/\")) return null;\n\n\t\t\tconst key = specifier.slice(\"@salesforce/i18n/\".length);\n\n\t\t\tif (BROWSER_DERIVED.has(key)) {\n\t\t\t\treturn RUNTIME_SOURCE.replace(\"__KEY__\", key);\n\t\t\t}\n\n\t\t\tif (key in objects) {\n\t\t\t\treturn `export default ${JSON.stringify(objects[key])};`;\n\t\t\t}\n\n\t\t\tconst value = statics[key] ?? key;\n\t\t\treturn `export default ${JSON.stringify(value)};`;\n\t\t},\n\t};\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport type { Provider } from \"../types\";\n\nexport function gate(overrides: Record<string, boolean> = {}): Provider {\n\treturn {\n\t\tprefix: \"@salesforce/gate/\",\n\t\tresolve(specifier) {\n\t\t\tif (!specifier.startsWith(\"@salesforce/gate/\")) return null;\n\t\t\tconst name = specifier.slice(\"@salesforce/gate/\".length);\n\t\t\tconst isOpen = overrides[name] ?? true;\n\t\t\treturn `export default { isOpen: () => ${isOpen} };`;\n\t\t},\n\t};\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport type { Provider } from \"../types\";\n\nexport function accessCheck(overrides: Record<string, boolean> = {}): Provider {\n\treturn {\n\t\tprefix: \"@salesforce/accessCheck/\",\n\t\tresolve(specifier) {\n\t\t\tif (!specifier.startsWith(\"@salesforce/accessCheck/\")) return null;\n\t\t\tconst name = specifier.slice(\"@salesforce/accessCheck/\".length);\n\t\t\tconst value = overrides[name] ?? false;\n\t\t\treturn `export default ${value};`;\n\t\t},\n\t};\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport type { Provider } from \"../types\";\n\nconst FORM_FACTOR_SOURCE = `\nfunction getFormFactor() {\n if (typeof window === 'undefined') return 'Large';\n if (window.matchMedia('(max-width: 767px)').matches) return 'Small';\n if (window.matchMedia('(max-width: 1023px)').matches) return 'Medium';\n return 'Large';\n}\n\nexport default getFormFactor();\n`;\n\nexport function client(): Provider {\n\treturn {\n\t\tprefix: \"@salesforce/client/\",\n\t\tresolve(specifier) {\n\t\t\tif (specifier === \"@salesforce/client/formFactor\") {\n\t\t\t\treturn FORM_FACTOR_SOURCE;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t};\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport type { Provider } from \"../types\";\n\nexport function primitiveUtils(): Provider {\n\treturn {\n\t\tprefix: \"lightning/primitiveUtils\",\n\t\tmatch(id) {\n\t\t\treturn id === \"lightning/primitiveUtils\";\n\t\t},\n\t\tresolve(specifier) {\n\t\t\tif (specifier !== \"lightning/primitiveUtils\") return null;\n\n\t\t\treturn `export function normalizeBoolean(value) {\n return typeof value === 'string' || !!value;\n}\n\nexport function reflectAttribute(element, attrName, value) {\n if (!element) return;\n if (typeof value === 'string') {\n element.setAttribute(attrName, value);\n } else if (value === true) {\n element.setAttribute(attrName, '');\n } else if (!value) {\n element.removeAttribute(attrName);\n } else {\n console.warn(\\`Invalid attribute value for \"\\${attrName}\": \\${value}\\`);\n }\n}\n`;\n\t\t},\n\t};\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport type { Provider } from \"../types\";\n\nexport interface LightningGraphqlOptions {\n\t/**\n\t * Name of the MCP tool to call for GraphQL query execution.\n\t * Defaults to `'graphqlQuery'`.\n\t *\n\t * The tool must accept `{ query: string; variables?: Record<string, unknown> }`\n\t * and return a GraphQL-shaped response: `{ data: unknown; errors?: unknown[] }`.\n\t *\n\t * The result is normalised across surfaces:\n\t * - OpenAI surface: `sdk.callTool()` resolves with `{ result: \"<JSON string>\" }`\n\t * - MCP Apps surface: `sdk.callTool()` resolves with `{ structuredContent, content }`\n\t */\n\ttoolName?: string;\n}\n\n/**\n * Off-platform implementation of `lightning/graphql`.\n *\n * Provides the `gql` tagged-template helper and a `graphql` wire adapter that\n * executes GraphQL queries by calling an MCP tool via `@salesforce/sdk-chat`.\n *\n * `getChatSDK()` auto-detects the host surface:\n * - `window.openai` present → OpenAI/ChatGPT bridge (`window.openai.callTool`)\n * - Inside an iframe → MCP Apps JSON-RPC session (with OpenAI fallback)\n * - Neither → UIBundle stub (no callTool; adapter emits an error)\n *\n * The tool name is configurable via `options.toolName` (default `'graphqlQuery'`).\n * Requires `@salesforce/sdk-chat` as a peer dependency.\n */\nfunction buildGraphqlSource(toolName: string): string {\n\treturn `\nimport { getChatSDK } from '@salesforce/sdk-chat';\n\nexport function gql(strings, ...values) {\n let result = '';\n strings.forEach((string, i) => {\n result += string;\n if (i < values.length) result += String(values[i]);\n });\n return result;\n}\n\nexport class graphql {\n _dataCallback;\n _config;\n\n constructor(dataCallback) {\n this._dataCallback = dataCallback;\n }\n\n connect() { this._fetch(); }\n disconnect() {}\n\n update(config) {\n this._config = config;\n this._fetch();\n }\n\n refresh() {\n return this._fetch();\n }\n\n async _fetch() {\n const query = this._config?.query;\n const variables = this._config?.variables ?? {};\n\n if (!query) {\n this._emit({ data: undefined, errors: undefined });\n return;\n }\n\n try {\n // 1. UIBundle / local dev: use globalThis.__sfdc_sdk__.graphql if available\n if (typeof globalThis.__sfdc_sdk__?.graphql === 'function') {\n const result = await globalThis.__sfdc_sdk__.graphql(query, variables);\n this._emit({ data: result?.data, errors: result?.errors });\n return;\n }\n\n // 2. MCP surface: use getChatSDK().callTool\n const sdk = await getChatSDK();\n\n if (typeof sdk.callTool !== 'function') {\n throw new Error(\n '[lightning/graphql] No data surface available. ' +\n 'Either initialise globalThis.__sfdc_sdk__ with createDataSDK, ' +\n 'or run inside a ChatGPT / MCP Apps context.'\n );\n }\n\n const raw = await sdk.callTool({\n toolName: ${JSON.stringify(toolName)},\n params: { query, variables },\n });\n\n // Normalise result across surfaces:\n // - OpenAI surface: { result: \"<JSON string of { data, errors }>\" }\n // - MCP Apps surface: { structuredContent: { data, errors }, content: [...] }\n let result;\n if (raw?.structuredContent !== undefined) {\n result = raw.structuredContent;\n } else if (typeof raw?.result === 'string') {\n const parsed = JSON.parse(raw.result);\n if (Array.isArray(parsed)) {\n // MCP content array - extract text from first text block\n const textBlock = parsed.find(\n (b) => b && b.type === 'text' && typeof b.text === 'string',\n );\n const text = textBlock ? textBlock.text : null;\n if (text) {\n try { result = JSON.parse(text); } catch { result = { errors: [{ message: text }] }; }\n } else {\n result = {};\n }\n } else {\n result = parsed;\n }\n } else {\n result = raw ?? {};\n }\n\n this._emit({ data: result?.data, errors: result?.errors });\n } catch (error) {\n this._emit({ data: undefined, errors: [{ message: error.message }] });\n }\n }\n\n _emit({ data, errors }) {\n this._dataCallback({\n data,\n error: errors?.length ? errors : undefined,\n refresh: () => this.refresh(),\n });\n }\n}\n\nexport async function executeMutation(config) {\n const { query, variables } = config;\n if (!query) return { data: undefined, errors: [{ message: 'No query provided' }] };\n try {\n // 1. UIBundle / local dev\n if (typeof globalThis.__sfdc_sdk__?.graphql === 'function') {\n const result = await globalThis.__sfdc_sdk__.graphql(query, variables ?? {});\n return { data: result?.data, errors: result?.errors };\n }\n // 2. MCP surface\n const sdk = await getChatSDK();\n if (typeof sdk.callTool !== 'function') {\n throw new Error('[lightning/graphql] No data surface available.');\n }\n const raw = await sdk.callTool({\n toolName: ${JSON.stringify(toolName)},\n params: { query, variables: variables ?? {} },\n });\n let result;\n if (raw?.structuredContent !== undefined) {\n result = raw.structuredContent;\n } else if (typeof raw?.result === 'string') {\n const parsed = JSON.parse(raw.result);\n if (Array.isArray(parsed)) {\n const textBlock = parsed.find(\n (b) => b && b.type === 'text' && typeof b.text === 'string',\n );\n const text = textBlock ? textBlock.text : null;\n if (text) {\n try { result = JSON.parse(text); } catch { result = { errors: [{ message: text }] }; }\n } else {\n result = {};\n }\n } else {\n result = parsed;\n }\n } else {\n result = raw ?? {};\n }\n return { data: result?.data, errors: result?.errors };\n } catch (error) {\n return { data: undefined, errors: [{ message: error.message }] };\n }\n}\n`;\n}\n\nexport function lightningGraphql(options: LightningGraphqlOptions = {}): Provider {\n\tconst toolName = options.toolName ?? \"graphqlQuery\";\n\treturn {\n\t\tprefix: \"lightning/graphql\",\n\t\tresolve(specifier) {\n\t\t\tif (specifier !== \"lightning/graphql\") return null;\n\t\t\treturn buildGraphqlSource(toolName);\n\t\t},\n\t};\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/providers/label.ts","../../src/providers/i18n.ts","../../src/providers/gate.ts","../../src/providers/access-check.ts","../../src/providers/client.ts","../../src/providers/primitive-utils.ts","../../src/providers/lightning-graphql.ts"],"sourcesContent":["/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport type { Provider } from \"../types\";\n\nconst LABEL_DEFAULTS: Record<string, string> = {\n\t\"LightningForm.edit\": \"Edit\",\n\t\"LightningForm.save\": \"Save\",\n\t\"LightningForm.cancel\": \"Cancel\",\n\t\"LightningForm.error\": \"Error\",\n\t\"RecordDetailUC.Expand\": \"Expand\",\n\t\"RecordDetailUC.Collapse\": \"Collapse\",\n\t\"Global_Entity.created_by\": \"Created By\",\n\t\"Global_Entity.last_modified_by\": \"Last Modified By\",\n\t\"DetailError.GenericSaveError\": \"An error occurred while saving.\",\n\t\"MobileWebError.NoPreEditAccess\": \"You don't have access to edit this record.\",\n\t\"DuplicateList.ToastMessageBlock\": \"Duplicate records were found.\",\n\t\"DuplicateList.NonBlockingHeaderText\": \"Duplicate records found\",\n\t\"DuplicateList.ToastMessageAlertEdit\": \"Duplicate records were found. You can continue editing.\",\n\t\"Errors.ErrorPopoverHeading\": \"Error\",\n};\n\nexport function label(overrides: Record<string, string> = {}): Provider {\n\tconst defaults = { ...LABEL_DEFAULTS, ...overrides };\n\treturn {\n\t\tprefix: \"@salesforce/label/\",\n\t\tresolve(specifier) {\n\t\t\tif (!specifier.startsWith(\"@salesforce/label/\")) return null;\n\n\t\t\tconst key = specifier.slice(\"@salesforce/label/\".length);\n\t\t\tconst fallbackLabel = key\n\t\t\t\t.split(\".\")\n\t\t\t\t.at(-1)!\n\t\t\t\t.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n\t\t\t\t.replace(/_/g, \" \")\n\t\t\t\t.trim();\n\t\t\tconst value = defaults[key] ?? fallbackLabel;\n\t\t\treturn `export default ${JSON.stringify(value)};`;\n\t\t},\n\t};\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport type { Provider } from \"../types\";\n\nconst BROWSER_DERIVED = new Set([\n\t\"lang\",\n\t\"dir\",\n\t\"locale\",\n\t\"currency\",\n\t\"timeZone\",\n\t\"firstDayOfWeek\",\n]);\n\nconst STATIC_DEFAULTS: Record<string, string> = {\n\t\"dateTime.shortDateFormat\": \"M/d/yyyy\",\n\t\"dateTime.mediumDateFormat\": \"MMM d, yyyy\",\n\t\"dateTime.longDateFormat\": \"MMMM d, yyyy\",\n\t\"dateTime.shortTimeFormat\": \"h:mm a\",\n\t\"dateTime.mediumTimeFormat\": \"h:mm:ss a\",\n\t\"dateTime.longTimeFormat\": \"h:mm:ss a z\",\n\t\"dateTime.shortDateTimeFormat\": \"M/d/yyyy, h:mm a\",\n\t\"number.numberFormat\": \"#,##0.##\",\n\t\"number.currencyFormat\": \"¤#,##0.00\",\n\t\"number.decimalSeparator\": \".\",\n\t\"number.groupingSeparator\": \",\",\n\t\"number.percentFormat\": \"#,##0%\",\n\t\"number.percentSign\": \"%\",\n\t\"number.plusSign\": \"+\",\n\t\"number.minusSign\": \"-\",\n\t\"number.exponentialSign\": \"E\",\n\t\"number.superscriptingExponentSign\": \"×\",\n\t\"number.perMilleSign\": \"‰\",\n\t\"number.infinity\": \"∞\",\n\t\"number.nan\": \"NaN\",\n\t\"number.currencySymbol\": \"$\",\n\tdefaultCalendar: \"gregory\",\n\tdefaultNumberingSystem: \"latn\",\n};\n\nconst MONTHS_WIDE = [\n\t\"January\",\n\t\"February\",\n\t\"March\",\n\t\"April\",\n\t\"May\",\n\t\"June\",\n\t\"July\",\n\t\"August\",\n\t\"September\",\n\t\"October\",\n\t\"November\",\n\t\"December\",\n];\nconst MONTHS_ABBR = [\n\t\"Jan\",\n\t\"Feb\",\n\t\"Mar\",\n\t\"Apr\",\n\t\"May\",\n\t\"Jun\",\n\t\"Jul\",\n\t\"Aug\",\n\t\"Sep\",\n\t\"Oct\",\n\t\"Nov\",\n\t\"Dec\",\n];\nconst DAYS_WIDE = [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"];\nconst DAYS_ABBR = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n\nconst OBJECT_DEFAULTS: Record<string, unknown> = {\n\t\"common.digits\": { latn: \"0123456789\" },\n\t\"common.calendarData\": {\n\t\tgregory: { calendarSystem: \"solar\", eras: {} },\n\t},\n\tcalendarData: {\n\t\tgregory: {\n\t\t\tmonths: {\n\t\t\t\tformat: {\n\t\t\t\t\twide: MONTHS_WIDE,\n\t\t\t\t\tabbreviated: MONTHS_ABBR,\n\t\t\t\t\tnarrow: MONTHS_ABBR,\n\t\t\t\t},\n\t\t\t},\n\t\t\tdays: {\n\t\t\t\tformat: {\n\t\t\t\t\twide: DAYS_WIDE,\n\t\t\t\t\tabbreviated: DAYS_ABBR,\n\t\t\t\t\tnarrow: DAYS_ABBR,\n\t\t\t\t},\n\t\t\t},\n\t\t\tdayPeriods: {\n\t\t\t\tformat: {\n\t\t\t\t\twide: [\"AM\", \"PM\"],\n\t\t\t\t\tabbreviated: [\"am\", \"pm\"],\n\t\t\t\t\tnarrow: [\"a\", \"p\"],\n\t\t\t\t},\n\t\t\t},\n\t\t\teras: {\n\t\t\t\teraAbbr: [\"AD\"],\n\t\t\t\teraNames: [\"Anno Domini\"],\n\t\t\t\teraNarrow: [\"A\"],\n\t\t\t},\n\t\t},\n\t},\n};\n\nconst RUNTIME_SOURCE = `\nconst RTL_LANGS = new Set([\n 'ar', 'arc', 'dv', 'fa', 'ha', 'he', 'khw', 'ks', 'ku', 'ps', 'ur', 'yi',\n]);\n\nfunction getLocale() {\n if (typeof navigator === 'undefined') return 'en-US';\n return navigator.language || 'en-US';\n}\n\nfunction getLang() {\n return getLocale().split('-')[0];\n}\n\nfunction getDir() {\n return RTL_LANGS.has(getLang()) ? 'rtl' : 'ltr';\n}\n\nfunction getCurrency() {\n try {\n const parts = new Intl.NumberFormat(getLocale(), {\n style: 'currency',\n currency: 'USD',\n currencyDisplay: 'code',\n }).resolvedOptions();\n return parts.currency || 'USD';\n } catch {\n return 'USD';\n }\n}\n\nfunction getTimeZone() {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';\n } catch {\n return 'UTC';\n }\n}\n\nfunction getFirstDayOfWeek() {\n try {\n const loc = new Intl.Locale(getLocale());\n if (loc.weekInfo) return String(loc.weekInfo.firstDay);\n if (typeof loc.getWeekInfo === 'function') return String(loc.getWeekInfo().firstDay);\n } catch { /* unsupported in this browser */ }\n return '7';\n}\n\nconst values = {\n lang: getLang(),\n dir: getDir(),\n locale: getLocale(),\n currency: getCurrency(),\n timeZone: getTimeZone(),\n firstDayOfWeek: getFirstDayOfWeek(),\n};\n\nexport default values['__KEY__'];\n`;\n\nexport interface I18nOptions {\n\tstaticOverrides?: Record<string, string>;\n\tobjectOverrides?: Record<string, unknown>;\n}\n\nexport function i18n(options: I18nOptions = {}): Provider {\n\tconst { staticOverrides = {}, objectOverrides = {} } = options;\n\tconst statics = { ...STATIC_DEFAULTS, ...staticOverrides };\n\tconst objects = { ...OBJECT_DEFAULTS, ...objectOverrides };\n\n\treturn {\n\t\tprefix: \"@salesforce/i18n/\",\n\t\tresolve(specifier) {\n\t\t\tif (!specifier.startsWith(\"@salesforce/i18n/\")) return null;\n\n\t\t\tconst key = specifier.slice(\"@salesforce/i18n/\".length);\n\n\t\t\tif (BROWSER_DERIVED.has(key)) {\n\t\t\t\treturn RUNTIME_SOURCE.replace(\"__KEY__\", key);\n\t\t\t}\n\n\t\t\tif (key in objects) {\n\t\t\t\treturn `export default ${JSON.stringify(objects[key])};`;\n\t\t\t}\n\n\t\t\tconst value = statics[key] ?? key;\n\t\t\treturn `export default ${JSON.stringify(value)};`;\n\t\t},\n\t};\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport type { Provider } from \"../types\";\n\nexport function gate(overrides: Record<string, boolean> = {}): Provider {\n\treturn {\n\t\tprefix: \"@salesforce/gate/\",\n\t\tresolve(specifier) {\n\t\t\tif (!specifier.startsWith(\"@salesforce/gate/\")) return null;\n\t\t\tconst name = specifier.slice(\"@salesforce/gate/\".length);\n\t\t\tconst isOpen = overrides[name] ?? true;\n\t\t\treturn `export default { isOpen: () => ${isOpen} };`;\n\t\t},\n\t};\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport type { Provider } from \"../types\";\n\nexport function accessCheck(overrides: Record<string, boolean> = {}): Provider {\n\treturn {\n\t\tprefix: \"@salesforce/accessCheck/\",\n\t\tresolve(specifier) {\n\t\t\tif (!specifier.startsWith(\"@salesforce/accessCheck/\")) return null;\n\t\t\tconst name = specifier.slice(\"@salesforce/accessCheck/\".length);\n\t\t\tconst value = overrides[name] ?? false;\n\t\t\treturn `export default ${value};`;\n\t\t},\n\t};\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport type { Provider } from \"../types\";\n\nconst FORM_FACTOR_SOURCE = `\nfunction getFormFactor() {\n if (typeof window === 'undefined') return 'Large';\n if (window.matchMedia('(max-width: 767px)').matches) return 'Small';\n if (window.matchMedia('(max-width: 1023px)').matches) return 'Medium';\n return 'Large';\n}\n\nexport default getFormFactor();\n`;\n\nexport function client(): Provider {\n\treturn {\n\t\tprefix: \"@salesforce/client/\",\n\t\tresolve(specifier) {\n\t\t\tif (specifier === \"@salesforce/client/formFactor\") {\n\t\t\t\treturn FORM_FACTOR_SOURCE;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t};\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport type { Provider } from \"../types\";\n\nexport function primitiveUtils(): Provider {\n\treturn {\n\t\tprefix: \"lightning/primitiveUtils\",\n\t\tmatch(id) {\n\t\t\treturn id === \"lightning/primitiveUtils\";\n\t\t},\n\t\tresolve(specifier) {\n\t\t\tif (specifier !== \"lightning/primitiveUtils\") return null;\n\n\t\t\treturn `export function normalizeBoolean(value) {\n return typeof value === 'string' || !!value;\n}\n\nexport function reflectAttribute(element, attrName, value) {\n if (!element) return;\n if (typeof value === 'string') {\n element.setAttribute(attrName, value);\n } else if (value === true) {\n element.setAttribute(attrName, '');\n } else if (!value) {\n element.removeAttribute(attrName);\n } else {\n console.warn(\\`Invalid attribute value for \"\\${attrName}\": \\${value}\\`);\n }\n}\n`;\n\t\t},\n\t};\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport type { Provider } from \"../types\";\n\nexport interface LightningGraphqlOptions {\n\t/**\n\t * Name of the MCP tool to call for GraphQL query execution.\n\t * Defaults to `'graphqlQuery'`.\n\t *\n\t * The tool must accept `{ query: string; variables?: Record<string, unknown> }`\n\t * and return a GraphQL-shaped response: `{ data: unknown; errors?: unknown[] }`.\n\t *\n\t * The result is normalised across surfaces:\n\t * - OpenAI surface: `sdk.callTool()` resolves with `{ result: \"<JSON string>\" }`\n\t * - MCP Apps surface: `sdk.callTool()` resolves with `{ structuredContent, content }`\n\t */\n\ttoolName?: string;\n}\n\n/**\n * Off-platform implementation of `lightning/graphql`.\n *\n * Provides the `gql` tagged-template helper and a `graphql` wire adapter that\n * executes GraphQL queries by calling an MCP tool via `@salesforce/sdk-chat`.\n *\n * `getChatSDK()` auto-detects the host surface:\n * - `window.openai` present → OpenAI/ChatGPT bridge (`window.openai.callTool`)\n * - Inside an iframe → MCP Apps JSON-RPC session (with OpenAI fallback)\n * - Neither → UIBundle stub (no callTool; adapter emits an error)\n *\n * The tool name is configurable via `options.toolName` (default `'graphqlQuery'`).\n * Requires `@salesforce/sdk-chat` as a peer dependency.\n */\nfunction buildGraphqlSource(toolName: string): string {\n\treturn `\nimport { getChatSDK } from '@salesforce/sdk-chat';\n\nexport function gql(strings, ...values) {\n let result = '';\n strings.forEach((string, i) => {\n result += string;\n if (i < values.length) result += String(values[i]);\n });\n return result;\n}\n\nexport class graphql {\n _dataCallback;\n _config;\n\n constructor(dataCallback) {\n this._dataCallback = dataCallback;\n }\n\n connect() { this._fetch(); }\n disconnect() {}\n\n update(config) {\n this._config = config;\n this._fetch();\n }\n\n refresh() {\n return this._fetch();\n }\n\n async _fetch() {\n const query = this._config?.query;\n const variables = this._config?.variables ?? {};\n\n if (!query) {\n this._emit({ data: undefined, errors: undefined });\n return;\n }\n\n try {\n // 1. UIBundle / local dev: use globalThis.__sfdc_sdk__.graphql if available\n if (typeof globalThis.__sfdc_sdk__?.graphql === 'function') {\n const result = await globalThis.__sfdc_sdk__.graphql({ query, variables });\n this._emit({ data: result?.data, errors: result?.errors });\n return;\n }\n\n // 2. MCP surface: use getChatSDK().callTool\n const sdk = await getChatSDK();\n\n if (typeof sdk.callTool !== 'function') {\n throw new Error(\n '[lightning/graphql] No data surface available. ' +\n 'Either initialise globalThis.__sfdc_sdk__ with createDataSDK, ' +\n 'or run inside a ChatGPT / MCP Apps context.'\n );\n }\n\n const raw = await sdk.callTool({\n toolName: ${JSON.stringify(toolName)},\n params: { query, variables },\n });\n\n // Normalise result across surfaces:\n // - OpenAI surface: { result: \"<JSON string of { data, errors }>\" }\n // - MCP Apps surface: { structuredContent: { data, errors }, content: [...] }\n let result;\n if (raw?.structuredContent !== undefined) {\n result = raw.structuredContent;\n } else if (typeof raw?.result === 'string') {\n const parsed = JSON.parse(raw.result);\n if (Array.isArray(parsed)) {\n // MCP content array - extract text from first text block\n const textBlock = parsed.find(\n (b) => b && b.type === 'text' && typeof b.text === 'string',\n );\n const text = textBlock ? textBlock.text : null;\n if (text) {\n try { result = JSON.parse(text); } catch { result = { errors: [{ message: text }] }; }\n } else {\n result = {};\n }\n } else {\n result = parsed;\n }\n } else {\n result = raw ?? {};\n }\n\n this._emit({ data: result?.data, errors: result?.errors });\n } catch (error) {\n this._emit({ data: undefined, errors: [{ message: error.message }] });\n }\n }\n\n _emit({ data, errors }) {\n this._dataCallback({\n data,\n error: errors?.length ? errors : undefined,\n refresh: () => this.refresh(),\n });\n }\n}\n\nexport async function executeMutation(config) {\n const { query, variables } = config;\n if (!query) return { data: undefined, errors: [{ message: 'No query provided' }] };\n try {\n // 1. UIBundle / local dev\n if (typeof globalThis.__sfdc_sdk__?.graphql === 'function') {\n const result = await globalThis.__sfdc_sdk__.graphql({ query, variables: variables ?? {} });\n return { data: result?.data, errors: result?.errors };\n }\n // 2. MCP surface\n const sdk = await getChatSDK();\n if (typeof sdk.callTool !== 'function') {\n throw new Error('[lightning/graphql] No data surface available.');\n }\n const raw = await sdk.callTool({\n toolName: ${JSON.stringify(toolName)},\n params: { query, variables: variables ?? {} },\n });\n let result;\n if (raw?.structuredContent !== undefined) {\n result = raw.structuredContent;\n } else if (typeof raw?.result === 'string') {\n const parsed = JSON.parse(raw.result);\n if (Array.isArray(parsed)) {\n const textBlock = parsed.find(\n (b) => b && b.type === 'text' && typeof b.text === 'string',\n );\n const text = textBlock ? textBlock.text : null;\n if (text) {\n try { result = JSON.parse(text); } catch { result = { errors: [{ message: text }] }; }\n } else {\n result = {};\n }\n } else {\n result = parsed;\n }\n } else {\n result = raw ?? {};\n }\n return { data: result?.data, errors: result?.errors };\n } catch (error) {\n return { data: undefined, errors: [{ message: error.message }] };\n }\n}\n`;\n}\n\nexport function lightningGraphql(options: LightningGraphqlOptions = {}): Provider {\n\tconst toolName = options.toolName ?? \"graphqlQuery\";\n\treturn {\n\t\tprefix: \"lightning/graphql\",\n\t\tresolve(specifier) {\n\t\t\tif (specifier !== \"lightning/graphql\") return null;\n\t\t\treturn buildGraphqlSource(toolName);\n\t\t},\n\t};\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
# Compiling LWC Components Off-Platform with @salesforce/vite-plugin-lwc-ui-bundle
|
|
2
|
+
|
|
3
|
+
This guide walks you through adding `@salesforce/vite-plugin-lwc-ui-bundle` to an
|
|
4
|
+
existing LWC project so you can compile your components into a single self-contained
|
|
5
|
+
`dist/index.html` that runs in any browser — no Salesforce org required.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Prerequisites
|
|
10
|
+
|
|
11
|
+
- **Node.js** >= 20.0.0
|
|
12
|
+
- **LWC components** in a project directory (standard SFDX project or custom layout)
|
|
13
|
+
- **Salesforce CLI** (`sf`) — only needed if connecting to a real org (Tier 2)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Overview
|
|
18
|
+
|
|
19
|
+
The plugin supports two tiers of usage:
|
|
20
|
+
|
|
21
|
+
| Tier | What You Get | Org Required? |
|
|
22
|
+
| ------------------------------- | ------------------------------------------ | ------------------ |
|
|
23
|
+
| **Tier 1: Off-Platform Build** | Static bundle with mock data, labels, i18n | No |
|
|
24
|
+
| **Tier 2: Live Org Connection** | Real GraphQL queries, live Salesforce data | Yes (via `sf` CLI) |
|
|
25
|
+
|
|
26
|
+
Start with Tier 1. Add Tier 2 later if your components use `lightning/graphql` or
|
|
27
|
+
need live data.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Tier 1: Off-Platform Build
|
|
32
|
+
|
|
33
|
+
### Project Structure
|
|
34
|
+
|
|
35
|
+
You need to add **3 files** to your project and update `package.json`:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
my-lwc-project/
|
|
39
|
+
├── force-app/main/default/lwc/ ← your existing LWC components
|
|
40
|
+
│ ├── myApp/
|
|
41
|
+
│ │ ├── myApp.js
|
|
42
|
+
│ │ ├── myApp.html
|
|
43
|
+
│ │ └── myApp.js-meta.xml
|
|
44
|
+
│ └── myComponent/
|
|
45
|
+
│ ├── myComponent.js
|
|
46
|
+
│ ├── myComponent.html
|
|
47
|
+
│ └── myComponent.js-meta.xml
|
|
48
|
+
├── bootstrap.js ← NEW: mounts your root component
|
|
49
|
+
├── index.html ← NEW: entry point
|
|
50
|
+
├── vite.config.js ← NEW: plugin configuration
|
|
51
|
+
└── package.json ← UPDATED: add deps and scripts
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Step 1: Install Dependencies
|
|
55
|
+
|
|
56
|
+
**Option A — Quick install command:**
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install @salesforce/vite-plugin-lwc-ui-bundle @lwc/rollup-plugin vite vite-plugin-singlefile --save-dev
|
|
60
|
+
npm install lwc @salesforce-ux/design-system lightning-base-components
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Option B — Add to `package.json` manually, then `npm install`:**
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"type": "module",
|
|
68
|
+
"scripts": {
|
|
69
|
+
"dev": "vite",
|
|
70
|
+
"build": "vite build",
|
|
71
|
+
"preview": "vite preview"
|
|
72
|
+
},
|
|
73
|
+
"dependencies": {
|
|
74
|
+
"@salesforce-ux/design-system": "^2.29.1",
|
|
75
|
+
"lightning-base-components": "^1.28.17-alpha",
|
|
76
|
+
"lwc": "^9.0.0"
|
|
77
|
+
},
|
|
78
|
+
"devDependencies": {
|
|
79
|
+
"@lwc/rollup-plugin": "^9.0.0",
|
|
80
|
+
"@salesforce/vite-plugin-lwc-ui-bundle": "^1.0.0",
|
|
81
|
+
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0",
|
|
82
|
+
"vite-plugin-singlefile": "^2.3.0"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
> **Important:** Add `"type": "module"` to your `package.json` if it is not already
|
|
88
|
+
> present. This is required for Vite's ESM-based config.
|
|
89
|
+
|
|
90
|
+
> **Note:** `@lwc/rollup-plugin` is a required peer dependency of the plugin.
|
|
91
|
+
> `lightning-base-components` is only needed if your components use `lightning/*`
|
|
92
|
+
> base components (e.g., `lightning-card`, `lightning-button`).
|
|
93
|
+
|
|
94
|
+
### Step 2: Create `vite.config.js`
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
import { defineConfig } from "vite";
|
|
98
|
+
import lwcVitePlugin, { builtins } from "@salesforce/vite-plugin-lwc-ui-bundle";
|
|
99
|
+
import { viteSingleFile } from "vite-plugin-singlefile";
|
|
100
|
+
|
|
101
|
+
export default defineConfig({
|
|
102
|
+
build: {
|
|
103
|
+
target: "esnext",
|
|
104
|
+
minify: false,
|
|
105
|
+
},
|
|
106
|
+
plugins: [
|
|
107
|
+
lwcVitePlugin({
|
|
108
|
+
modules: {
|
|
109
|
+
// Flat SFDX structure: specify { path, namespace }
|
|
110
|
+
dirs: [{ path: "force-app/main/default/lwc", namespace: "c" }],
|
|
111
|
+
|
|
112
|
+
// Include if your components use lightning/* base components
|
|
113
|
+
npm: ["lightning-base-components"],
|
|
114
|
+
},
|
|
115
|
+
providers: [
|
|
116
|
+
builtins.label(),
|
|
117
|
+
builtins.i18n(),
|
|
118
|
+
builtins.client(),
|
|
119
|
+
builtins.gate(),
|
|
120
|
+
builtins.accessCheck(),
|
|
121
|
+
],
|
|
122
|
+
}),
|
|
123
|
+
viteSingleFile(),
|
|
124
|
+
],
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### Component Directory Configuration
|
|
129
|
+
|
|
130
|
+
The plugin supports two directory structures:
|
|
131
|
+
|
|
132
|
+
**Flat SFDX structure** (standard Salesforce DX — most common):
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
force-app/main/default/lwc/
|
|
136
|
+
myApp/
|
|
137
|
+
myApp.js
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Use `{ path, namespace }` to assign a namespace:
|
|
141
|
+
|
|
142
|
+
```js
|
|
143
|
+
dirs: [{ path: "force-app/main/default/lwc", namespace: "c" }];
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Components are importable as `c/myApp` and rendered as `<c-my-app>`.
|
|
147
|
+
|
|
148
|
+
**Namespaced structure** (off-core projects):
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
src/lwc/
|
|
152
|
+
myNamespace/
|
|
153
|
+
myComponent/
|
|
154
|
+
myComponent.js
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Omit `namespace` — the sub-directory name becomes the namespace:
|
|
158
|
+
|
|
159
|
+
```js
|
|
160
|
+
dirs: ["src/lwc"];
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Components are importable as `myNamespace/myComponent`.
|
|
164
|
+
|
|
165
|
+
#### Configuring Labels
|
|
166
|
+
|
|
167
|
+
The `builtins.label()` provider handles `@salesforce/label/*` imports. How you
|
|
168
|
+
configure it depends on your project:
|
|
169
|
+
|
|
170
|
+
**SFDX project with `CustomLabels.labels-meta.xml`:**
|
|
171
|
+
|
|
172
|
+
Copy label values from your XML into the label provider config:
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
builtins.label({
|
|
176
|
+
"c.appTitle": "My LWC App",
|
|
177
|
+
"c.saveButton": "Save",
|
|
178
|
+
"c.cancelButton": "Cancel",
|
|
179
|
+
}),
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Off-core project (no labels XML):**
|
|
183
|
+
|
|
184
|
+
Pass label key-value pairs directly. If no override is provided for a key, the
|
|
185
|
+
plugin returns a human-readable fallback derived from the key name (e.g.,
|
|
186
|
+
`c.appTitle` renders as "App Title").
|
|
187
|
+
|
|
188
|
+
```js
|
|
189
|
+
// Minimal — uses fallback display for all labels
|
|
190
|
+
builtins.label(),
|
|
191
|
+
|
|
192
|
+
// With explicit overrides
|
|
193
|
+
builtins.label({
|
|
194
|
+
"c.appTitle": "My App Title",
|
|
195
|
+
"c.greeting": "Welcome!",
|
|
196
|
+
}),
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### Why `gate()` and `accessCheck()` Are Needed
|
|
200
|
+
|
|
201
|
+
Even if your components don't use `@salesforce/gate/*` or `@salesforce/accessCheck/*`
|
|
202
|
+
directly, **`lightning-base-components` does internally**. Without these providers,
|
|
203
|
+
you'll get runtime errors like:
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
Uncaught TypeError: Cannot read properties of undefined (reading 'isOpen')
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Always include `builtins.gate()` and `builtins.accessCheck()` when using
|
|
210
|
+
`lightning-base-components`.
|
|
211
|
+
|
|
212
|
+
### Step 3: Create `index.html`
|
|
213
|
+
|
|
214
|
+
```html
|
|
215
|
+
<!doctype html>
|
|
216
|
+
<html lang="en">
|
|
217
|
+
<head>
|
|
218
|
+
<meta charset="UTF-8" />
|
|
219
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
220
|
+
<title>My LWC App</title>
|
|
221
|
+
</head>
|
|
222
|
+
<body>
|
|
223
|
+
<div id="app"></div>
|
|
224
|
+
<script>
|
|
225
|
+
globalThis.lwcRuntimeFlags = { DISABLE_SYNTHETIC_SHADOW: true };
|
|
226
|
+
</script>
|
|
227
|
+
<script type="module" src="/bootstrap.js"></script>
|
|
228
|
+
</body>
|
|
229
|
+
</html>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Step 4: Create `bootstrap.js`
|
|
233
|
+
|
|
234
|
+
```js
|
|
235
|
+
import "@salesforce-ux/design-system/assets/styles/salesforce-lightning-design-system.css";
|
|
236
|
+
import "@lwc/synthetic-shadow";
|
|
237
|
+
import { createElement } from "lwc";
|
|
238
|
+
|
|
239
|
+
// Import your root component using its LWC specifier: <namespace>/<componentName>
|
|
240
|
+
import App from "c/myApp";
|
|
241
|
+
|
|
242
|
+
// Mount it — tag name is the kebab-case version of the specifier
|
|
243
|
+
const el = createElement("c-my-app", { is: App });
|
|
244
|
+
document.getElementById("app").appendChild(el);
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Replace `c/myApp` and `c-my-app` with your actual root component name.
|
|
248
|
+
|
|
249
|
+
### Step 5: Build and Test
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
# Production build — outputs dist/index.html (single-file bundle)
|
|
253
|
+
npm run build
|
|
254
|
+
|
|
255
|
+
# Open directly in browser
|
|
256
|
+
open dist/index.html
|
|
257
|
+
|
|
258
|
+
# Or use dev server with live reload
|
|
259
|
+
npm run dev
|
|
260
|
+
# Open http://localhost:5173
|
|
261
|
+
|
|
262
|
+
# Or preview the production build
|
|
263
|
+
npm run preview
|
|
264
|
+
# Open http://localhost:4173
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Tier 2: Live Org Connection (lwcProxy)
|
|
270
|
+
|
|
271
|
+
If your components use `lightning/graphql` or need live Salesforce data, add
|
|
272
|
+
`lwcProxy()` to connect to a real org during development.
|
|
273
|
+
|
|
274
|
+
### Prerequisites
|
|
275
|
+
|
|
276
|
+
- Salesforce CLI installed and an org connected: `sf org display`
|
|
277
|
+
- Additional packages: `@salesforce/sdk-data` and `@salesforce/ui-bundle`
|
|
278
|
+
|
|
279
|
+
### Step 1: Install Additional Dependencies
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
npm install @salesforce/sdk-data @salesforce/ui-bundle
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Step 2: Update `vite.config.js`
|
|
286
|
+
|
|
287
|
+
Add `lwcProxy()` before `lwcVitePlugin()` and add `builtins.lightningGraphql()`
|
|
288
|
+
to providers:
|
|
289
|
+
|
|
290
|
+
```js
|
|
291
|
+
import { defineConfig } from "vite";
|
|
292
|
+
import lwcVitePlugin, { builtins, lwcProxy } from "@salesforce/vite-plugin-lwc-ui-bundle";
|
|
293
|
+
import { viteSingleFile } from "vite-plugin-singlefile";
|
|
294
|
+
|
|
295
|
+
export default defineConfig({
|
|
296
|
+
build: {
|
|
297
|
+
target: "esnext",
|
|
298
|
+
minify: false,
|
|
299
|
+
},
|
|
300
|
+
plugins: [
|
|
301
|
+
lwcProxy({ debug: true }),
|
|
302
|
+
// lwcProxy({ orgAlias: "my-org", debug: true }), // explicit org
|
|
303
|
+
lwcVitePlugin({
|
|
304
|
+
modules: {
|
|
305
|
+
dirs: [{ path: "force-app/main/default/lwc", namespace: "c" }],
|
|
306
|
+
npm: ["lightning-base-components"],
|
|
307
|
+
},
|
|
308
|
+
providers: [
|
|
309
|
+
builtins.label(),
|
|
310
|
+
builtins.i18n(),
|
|
311
|
+
builtins.client(),
|
|
312
|
+
builtins.gate(),
|
|
313
|
+
builtins.accessCheck(),
|
|
314
|
+
builtins.lightningGraphql(),
|
|
315
|
+
],
|
|
316
|
+
}),
|
|
317
|
+
viteSingleFile(),
|
|
318
|
+
],
|
|
319
|
+
});
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Step 3: Update `bootstrap.js`
|
|
323
|
+
|
|
324
|
+
Initialize the Data SDK before mounting your app. This requires top-level `await`
|
|
325
|
+
(hence `target: "esnext"` in the vite config):
|
|
326
|
+
|
|
327
|
+
```js
|
|
328
|
+
import "@salesforce-ux/design-system/assets/styles/salesforce-lightning-design-system.css";
|
|
329
|
+
import "@lwc/synthetic-shadow";
|
|
330
|
+
import { createElement } from "lwc";
|
|
331
|
+
|
|
332
|
+
// Initialize SDK — lwcProxy() handles /services/* in the Vite dev server
|
|
333
|
+
import { createDataSDK } from "@salesforce/sdk-data";
|
|
334
|
+
try {
|
|
335
|
+
globalThis.__sfdc_sdk__ = await createDataSDK({ uiBundle: { basePath: "/" } });
|
|
336
|
+
} catch (_err) {
|
|
337
|
+
globalThis.__sfdc_sdk__ = {};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Import your root component
|
|
341
|
+
import App from "c/myApp";
|
|
342
|
+
|
|
343
|
+
const el = createElement("c-my-app", { is: App });
|
|
344
|
+
document.getElementById("app").appendChild(el);
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Step 4: Run Dev Server
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
npm run dev
|
|
351
|
+
# Terminal shows: [lwc-proxy] Connected to https://your-org.my.salesforce.com
|
|
352
|
+
# Open http://localhost:5173
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Components using `@wire(graphql, ...)` will now execute real GraphQL queries
|
|
356
|
+
against your connected org. The proxy intercepts `/services/*` calls inside
|
|
357
|
+
the Vite dev server — no separate proxy process needed.
|
|
358
|
+
|
|
359
|
+
> **Note:** `lwcProxy()` works with `npm run dev` only. The production build
|
|
360
|
+
> (`dist/index.html`) does not include the proxy — it's a static file. For
|
|
361
|
+
> production use with live data, you need a separate API proxy or MCP server.
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Common Errors
|
|
366
|
+
|
|
367
|
+
### `Cannot read properties of undefined (reading 'isOpen')`
|
|
368
|
+
|
|
369
|
+
Missing `gate()` provider. `lightning-base-components` use gates internally.
|
|
370
|
+
Add `builtins.gate()` to your providers array.
|
|
371
|
+
|
|
372
|
+
### `Rollup failed to resolve import "lightning/button"`
|
|
373
|
+
|
|
374
|
+
Your component uses a Lightning Base Component. Add to `vite.config.js`:
|
|
375
|
+
|
|
376
|
+
```js
|
|
377
|
+
modules: {
|
|
378
|
+
npm: ["lightning-base-components"],
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### `Top-level await is not available in the configured target environment`
|
|
383
|
+
|
|
384
|
+
Your `bootstrap.js` uses top-level `await` (required for Data SDK). Add
|
|
385
|
+
`target: "esnext"` to the build config:
|
|
386
|
+
|
|
387
|
+
```js
|
|
388
|
+
build: { target: "esnext" },
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### `[scoped-module-providers] Unhandled import: @salesforce/label/...`
|
|
392
|
+
|
|
393
|
+
Expected — the plugin returns the label key as display text by default.
|
|
394
|
+
To provide specific label values:
|
|
395
|
+
|
|
396
|
+
```js
|
|
397
|
+
builtins.label({ "c.Save": "Save", "c.Cancel": "Cancel" }),
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### `Rollup failed to resolve import "force/someModule"`
|
|
401
|
+
|
|
402
|
+
Core-only module not available off-platform. Add a stub:
|
|
403
|
+
|
|
404
|
+
```js
|
|
405
|
+
// stubs/someModule.js
|
|
406
|
+
export const someExport = () => {};
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
```js
|
|
410
|
+
// vite.config.js
|
|
411
|
+
lwcVitePlugin({ stubs: { "force/someModule": "./stubs/someModule.js" } });
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### Component renders but looks unstyled
|
|
415
|
+
|
|
416
|
+
Add SLDS import to `bootstrap.js`:
|
|
417
|
+
|
|
418
|
+
```js
|
|
419
|
+
import "@salesforce-ux/design-system/assets/styles/salesforce-lightning-design-system.css";
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## Reference
|
|
425
|
+
|
|
426
|
+
- **npm:** https://www.npmjs.com/package/@salesforce/vite-plugin-lwc-ui-bundle
|
|
427
|
+
- **Source:** https://github.com/salesforce-experience-platform-emu/webapps/tree/main/packages/vite-plugin-lwc-ui-bundle
|
|
428
|
+
- **User Guide:** https://github.com/salesforce-experience-platform-emu/webapps/blob/main/packages/vite-plugin-lwc-ui-bundle/docs/user-guide.md
|
|
429
|
+
- **Example project:** https://git.soma.salesforce.com/sisi-zhang/my-lwc-app-test
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/vite-plugin-lwc-ui-bundle",
|
|
3
|
-
"version": "1.131.
|
|
3
|
+
"version": "1.131.3",
|
|
4
4
|
"description": "Vite plugin for compiling LWC components into static bundles for off-platform and MCP use",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"author": "Salesforce",
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
"files": [
|
|
38
38
|
"dist",
|
|
39
39
|
"README.md",
|
|
40
|
-
"docs"
|
|
40
|
+
"docs",
|
|
41
|
+
"skills"
|
|
41
42
|
],
|
|
42
43
|
"scripts": {
|
|
43
44
|
"build": "vite build",
|
|
@@ -59,7 +60,7 @@
|
|
|
59
60
|
}
|
|
60
61
|
},
|
|
61
62
|
"devDependencies": {
|
|
62
|
-
"@salesforce/sdk-chat": "^1.131.
|
|
63
|
+
"@salesforce/sdk-chat": "^1.131.3",
|
|
63
64
|
"typescript": "^5.9.3",
|
|
64
65
|
"vite": "^7.0.0",
|
|
65
66
|
"vite-plugin-dts": "^4.5.4",
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: setup-lwc-vite-plugin
|
|
3
|
+
description: >
|
|
4
|
+
Set up @salesforce/vite-plugin-lwc-ui-bundle in an LWC project so components
|
|
5
|
+
compile and run off-platform in a browser. Use this skill whenever someone wants
|
|
6
|
+
to: run LWC components outside Salesforce, build a static LWC bundle, add Vite
|
|
7
|
+
to an SFDX or LWC project, compile LWC for a browser, create a standalone LWC
|
|
8
|
+
app, set up an LWC dev server, or use vite-plugin-lwc-ui-bundle. Also use it
|
|
9
|
+
when the user mentions "off-platform LWC", "LWC bundle", "LWC without Salesforce",
|
|
10
|
+
"LWC without an org", "Vite + LWC", or "compile LWC off-core".
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Setup @salesforce/vite-plugin-lwc-ui-bundle
|
|
14
|
+
|
|
15
|
+
This skill adds `@salesforce/vite-plugin-lwc-ui-bundle` to an existing LWC project,
|
|
16
|
+
producing a single `dist/index.html` that runs in any browser without a Salesforce org.
|
|
17
|
+
|
|
18
|
+
## What the plugin does
|
|
19
|
+
|
|
20
|
+
It wraps the full LWC compilation pipeline behind a single Vite plugin: scoped module
|
|
21
|
+
providers (labels, i18n, gates, etc.), Lightning npm resolution, missing CSS handling,
|
|
22
|
+
and the Vite/LWC bridge. The output is a self-contained HTML file with all JS and CSS
|
|
23
|
+
inlined.
|
|
24
|
+
|
|
25
|
+
## Reference material
|
|
26
|
+
|
|
27
|
+
The `references/consumer-guide.md` file contains exact file templates, dependency
|
|
28
|
+
versions, and config snippets. Read it when you need to generate `vite.config.js`,
|
|
29
|
+
`index.html`, `bootstrap.js`, or `package.json` updates. This skill tells you
|
|
30
|
+
_when and why_ to use each piece; the consumer guide gives you the exact _what_.
|
|
31
|
+
|
|
32
|
+
## Interactive Setup Flow
|
|
33
|
+
|
|
34
|
+
Walk the user through these steps in order. Ask questions — don't assume.
|
|
35
|
+
|
|
36
|
+
### Step 1: Detect the project
|
|
37
|
+
|
|
38
|
+
LWC projects come in two layouts, and the directory structure determines how
|
|
39
|
+
`modules.dirs` must be configured. Detecting the layout first avoids misconfigured
|
|
40
|
+
imports that silently fail at build time.
|
|
41
|
+
|
|
42
|
+
Check in order:
|
|
43
|
+
|
|
44
|
+
1. `sfdx-project.json` in the project root → **SFDX project**. Components live at
|
|
45
|
+
`force-app/main/default/lwc/` in a flat structure where every component shares
|
|
46
|
+
the `c` namespace. Configure as `dirs: [{ path: "force-app/main/default/lwc", namespace: "c" }]`.
|
|
47
|
+
2. Directories matching `src/lwc/` or `modules/` → **off-core project**. Sub-directories
|
|
48
|
+
are namespaces (e.g., `src/lwc/myNs/myComponent/`). Configure as `dirs: ["src/lwc"]`.
|
|
49
|
+
3. If neither found, ask the user where their LWC components live.
|
|
50
|
+
|
|
51
|
+
Read `package.json` to understand what's already installed — avoid adding duplicate
|
|
52
|
+
dependencies later.
|
|
53
|
+
|
|
54
|
+
### Step 2: Ask for the root component
|
|
55
|
+
|
|
56
|
+
The plugin compiles a tree starting from one root component that gets mounted in the
|
|
57
|
+
HTML page. The user needs to tell you which one, since there's no reliable way to
|
|
58
|
+
auto-detect the "main" component.
|
|
59
|
+
|
|
60
|
+
List the discovered components and ask:
|
|
61
|
+
|
|
62
|
+
> "Which component should be the root of your app? This is the one that gets
|
|
63
|
+
> mounted in the HTML page."
|
|
64
|
+
|
|
65
|
+
Present the component names as a numbered list for easy selection.
|
|
66
|
+
|
|
67
|
+
### Step 3: Inspect the component tree
|
|
68
|
+
|
|
69
|
+
This step drives every downstream decision: which providers to include, whether
|
|
70
|
+
`lightning-base-components` is needed, and whether to offer Tier 2 (live org). Getting
|
|
71
|
+
this right prevents cryptic build errors.
|
|
72
|
+
|
|
73
|
+
Starting from the root component, trace the dependency tree:
|
|
74
|
+
|
|
75
|
+
1. Read the root component's `.html` file — find all `c-*` tags (or other
|
|
76
|
+
namespace tags) to identify child components
|
|
77
|
+
2. Recursively read each child component's `.js` and `.html`
|
|
78
|
+
3. Collect all imports across the tree:
|
|
79
|
+
- `@salesforce/label/*` → label keys (need `builtins.label()`)
|
|
80
|
+
- `lightning/graphql` or `@wire(graphql` → needs GraphQL support
|
|
81
|
+
- `lightning/*` base components → needs `lightning-base-components` npm package,
|
|
82
|
+
plus `gate()`, `accessCheck()`, and `primitiveUtils()` providers because
|
|
83
|
+
base components use these modules internally even if user code doesn't
|
|
84
|
+
- `@salesforce/gate/*`, `@salesforce/accessCheck/*` → handled by providers
|
|
85
|
+
- `@salesforce/i18n/*` → i18n provider
|
|
86
|
+
- `@salesforce/client/*` → client provider (provides `formFactor` based on viewport width)
|
|
87
|
+
- `lightning/primitiveUtils` → primitiveUtils provider
|
|
88
|
+
|
|
89
|
+
Report what you found:
|
|
90
|
+
|
|
91
|
+
> "I traced your component tree from `c/app`. Here's what I found:
|
|
92
|
+
>
|
|
93
|
+
> - 5 components total
|
|
94
|
+
> - 3 label imports: `c.appTitle`, `c.greeting`, `c.save`
|
|
95
|
+
> - Uses `lightning-card` (needs lightning-base-components)
|
|
96
|
+
> - Uses `lightning/graphql` (needs lwcProxy for live data)
|
|
97
|
+
> - No gate/accessCheck imports in your code, but lightning-base-components
|
|
98
|
+
> uses them internally — I'll include those providers automatically."
|
|
99
|
+
|
|
100
|
+
### Step 4: Decide the tier
|
|
101
|
+
|
|
102
|
+
The plugin supports two tiers. This determines which dependencies and bootstrap
|
|
103
|
+
code to generate.
|
|
104
|
+
|
|
105
|
+
| Tier | What you get | Org required? |
|
|
106
|
+
| ------------------------------- | ------------------------------------------ | ------------------ |
|
|
107
|
+
| **Tier 1: Off-Platform Build** | Static bundle with mock data, labels, i18n | No |
|
|
108
|
+
| **Tier 2: Live Org Connection** | Real GraphQL queries via `lwcProxy()` | Yes (via `sf` CLI) |
|
|
109
|
+
|
|
110
|
+
If GraphQL usage was detected in Step 3, ask:
|
|
111
|
+
|
|
112
|
+
> "Your components use `lightning/graphql`. Do you want to connect to a real
|
|
113
|
+
> Salesforce org for live data during development?
|
|
114
|
+
>
|
|
115
|
+
> A) Yes — I have an org connected via `sf` CLI (adds lwcProxy + Data SDK)
|
|
116
|
+
> B) No — use mock data for now (GraphQL wire adapter returns empty results)"
|
|
117
|
+
|
|
118
|
+
If no GraphQL detected, default to Tier 1 — there's no benefit to Tier 2 without
|
|
119
|
+
GraphQL or live data needs.
|
|
120
|
+
|
|
121
|
+
### Step 5: Resolve label values
|
|
122
|
+
|
|
123
|
+
Labels need explicit values because the plugin can't read them from an org at build
|
|
124
|
+
time. Getting them right here means the user sees realistic text immediately instead
|
|
125
|
+
of placeholder keys.
|
|
126
|
+
|
|
127
|
+
1. **SFDX project**: Check for `force-app/main/default/labels/CustomLabels.labels-meta.xml`.
|
|
128
|
+
If found, parse it and extract `<fullName>` → `<value>` pairs for the label
|
|
129
|
+
keys discovered in Step 3.
|
|
130
|
+
2. **Off-core project or no labels XML**: For each label key found, use a
|
|
131
|
+
placeholder value derived from the key (e.g., `c.appTitle` → `"App Title"`).
|
|
132
|
+
|
|
133
|
+
Tell the user what labels you found and the values you'll use:
|
|
134
|
+
|
|
135
|
+
> "I found 3 label imports. Here are the values I'll configure:
|
|
136
|
+
>
|
|
137
|
+
> - `c.appTitle` → "My LWC App" (from CustomLabels.labels-meta.xml)
|
|
138
|
+
> - `c.greeting` → "Welcome!" (from CustomLabels.labels-meta.xml)
|
|
139
|
+
> - `c.save` → "Save" (fallback — not found in labels XML)
|
|
140
|
+
>
|
|
141
|
+
> You can change these in `vite.config.js` later."
|
|
142
|
+
|
|
143
|
+
If no labels were found at all, still include `builtins.label()` with no overrides.
|
|
144
|
+
The plugin returns a human-readable fallback for unknown keys, and
|
|
145
|
+
`lightning-base-components` may use labels internally.
|
|
146
|
+
|
|
147
|
+
### Step 6: Generate files
|
|
148
|
+
|
|
149
|
+
Read `references/consumer-guide.md` for the exact file templates. Generate these
|
|
150
|
+
files, adapting the templates based on what you learned in Steps 1-5:
|
|
151
|
+
|
|
152
|
+
#### Files to create or update
|
|
153
|
+
|
|
154
|
+
1. **`package.json`** — merge in dependencies and scripts (don't overwrite existing).
|
|
155
|
+
See "Step 1: Install Dependencies" in the consumer guide for the full dep list.
|
|
156
|
+
- Add `"type": "module"` if not present
|
|
157
|
+
- Only add `lightning-base-components` and `@salesforce-ux/design-system` if
|
|
158
|
+
the component tree uses `lightning/*` base components
|
|
159
|
+
- For Tier 2, also add `@salesforce/sdk-data` and `@salesforce/ui-bundle`
|
|
160
|
+
|
|
161
|
+
2. **`vite.config.js`** — see "Step 2" in the consumer guide for the template.
|
|
162
|
+
Adapt based on your findings:
|
|
163
|
+
- Set `dirs` for the detected project structure (SFDX vs namespaced)
|
|
164
|
+
- Populate `builtins.label({...})` with values from Step 5
|
|
165
|
+
- Include `builtins.primitiveUtils()` if using `lightning-base-components`
|
|
166
|
+
- Include `builtins.lightningGraphql()` only if GraphQL was detected
|
|
167
|
+
- Remove `npm: ["lightning-base-components"]` if no base components used
|
|
168
|
+
- For Tier 2, add `lwcProxy()` before `lwcVitePlugin()` in the plugins array
|
|
169
|
+
|
|
170
|
+
3. **`index.html`** — see "Step 3" in the consumer guide.
|
|
171
|
+
|
|
172
|
+
4. **`bootstrap.js`** (project root) — see "Step 4" (Tier 1) or "Step 3" (Tier 2)
|
|
173
|
+
in the consumer guide. Replace the component name with the actual root from
|
|
174
|
+
Step 2. Remove the SLDS CSS import if `lightning-base-components` is not used.
|
|
175
|
+
|
|
176
|
+
#### Advanced options (use only when needed)
|
|
177
|
+
|
|
178
|
+
The plugin accepts additional options for complex projects. Only add these if the
|
|
179
|
+
component tree inspection reveals a need:
|
|
180
|
+
|
|
181
|
+
- **`stubs`**: Map bare module specifiers to stub files for core-only modules
|
|
182
|
+
not available off-platform (e.g., `{ "force/someModule": "./stubs/someModule.js" }`).
|
|
183
|
+
Needed when components import platform modules like `aura`, `logger`, or
|
|
184
|
+
`force/*` that don't exist outside Salesforce.
|
|
185
|
+
- **`lwcOptions`**: Pass-through options for `@lwc/rollup-plugin` to configure
|
|
186
|
+
LWC compiler behavior (e.g., `{ enableDynamicComponents: true }`). Only needed
|
|
187
|
+
for projects using advanced LWC features like dynamic component creation.
|
|
188
|
+
- **`passthroughRules`**: Let specific imports bypass the provider system. Each
|
|
189
|
+
rule has a `specifierPrefix` and `importerPattern` — when both match, the import
|
|
190
|
+
resolves normally. Useful when an npm package (like `lightning-base-components`)
|
|
191
|
+
has its own label definitions that shouldn't be intercepted by your label provider.
|
|
192
|
+
- **`ignorePatterns`**: Specifier prefixes that providers should never intercept.
|
|
193
|
+
Defaults include `@salesforce/sdk-*` and `@salesforce/core`. Extend this if
|
|
194
|
+
you have imports that look like provider-handled patterns but should resolve
|
|
195
|
+
through normal Node module resolution.
|
|
196
|
+
|
|
197
|
+
### Step 7: Install and build
|
|
198
|
+
|
|
199
|
+
Run:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
npm install
|
|
203
|
+
npm run build
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
If the build succeeds, report the output file size and open it:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
open dist/index.html
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
If the build fails, diagnose and fix. See the "Common Errors" section in
|
|
213
|
+
`references/consumer-guide.md` for the full troubleshooting guide. The most
|
|
214
|
+
frequent issues:
|
|
215
|
+
|
|
216
|
+
- **`Cannot read properties of undefined (reading 'isOpen')`**: Missing `gate()`
|
|
217
|
+
or `accessCheck()` provider — `lightning-base-components` use gates internally.
|
|
218
|
+
- **`Rollup failed to resolve import "lightning/button"`**: Missing
|
|
219
|
+
`npm: ["lightning-base-components"]` in modules config.
|
|
220
|
+
- **`Unhandled import: @salesforce/label/...`**: Expected warning — the plugin
|
|
221
|
+
returns the key as display text. Add overrides to `builtins.label()` to customize.
|
|
222
|
+
- **`Top-level await is not available`**: Missing `target: "esnext"` in build config.
|
|
223
|
+
- **`Rollup failed to resolve import "force/someModule"`**: Core-only module. Add
|
|
224
|
+
a stub via the `stubs` option.
|
|
225
|
+
- **Component renders but looks unstyled**: Missing SLDS CSS import in bootstrap.js.
|
|
226
|
+
|
|
227
|
+
### Step 8: Test dev server (Tier 2 only)
|
|
228
|
+
|
|
229
|
+
If lwcProxy was configured:
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
npm run dev
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Confirm the terminal shows `[lwc-proxy] Connected to https://...`. Open
|
|
236
|
+
`http://localhost:5173` and verify GraphQL queries return real data.
|
|
237
|
+
|
|
238
|
+
## Reference
|
|
239
|
+
|
|
240
|
+
- npm: https://www.npmjs.com/package/@salesforce/vite-plugin-lwc-ui-bundle
|
|
241
|
+
- README: https://github.com/salesforce-experience-platform-emu/webapps/tree/main/packages/vite-plugin-lwc-ui-bundle
|
|
242
|
+
- Consumer Guide: https://github.com/salesforce-experience-platform-emu/webapps/blob/main/packages/vite-plugin-lwc-ui-bundle/docs/consumer-guide.md
|
package/docs/user-guide.md
DELETED
|
@@ -1,377 +0,0 @@
|
|
|
1
|
-
# User Guide: Compiling LWC Components into a Static Bundle
|
|
2
|
-
|
|
3
|
-
This guide walks through using `@salesforce/vite-plugin-lwc-ui-bundle` to compile
|
|
4
|
-
your existing LWC components into a single self-contained `dist/index.html` —
|
|
5
|
-
no server required, opens directly in a browser.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Prerequisites
|
|
10
|
-
|
|
11
|
-
- Node.js >= 20.0.0
|
|
12
|
-
- Your LWC components already exist in a Salesforce DX project
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## Project Structure
|
|
17
|
-
|
|
18
|
-
The example project `my-lwc-app` uses the standard Salesforce DX flat structure:
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
my-lwc-app/
|
|
22
|
-
├── force-app/main/default/lwc/
|
|
23
|
-
│ ├── helloApp/ ← component directly, no namespace folder
|
|
24
|
-
│ │ ├── helloApp.js
|
|
25
|
-
│ │ ├── helloApp.html
|
|
26
|
-
│ │ └── helloApp.js-meta.xml
|
|
27
|
-
│ └── helloMessage/
|
|
28
|
-
│ ├── helloMessage.js
|
|
29
|
-
│ ├── helloMessage.html
|
|
30
|
-
│ └── helloMessage.js-meta.xml
|
|
31
|
-
├── src/
|
|
32
|
-
│ └── bootstrap.js ← mounts root component
|
|
33
|
-
├── index.html ← entry point
|
|
34
|
-
├── vite.config.js ← plugin config
|
|
35
|
-
└── package.json
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Use `namespace: 'c'` in `vite.config.js` to tell the plugin to treat this flat
|
|
39
|
-
structure as namespace `c` — components are then importable as `'c/helloApp'`.
|
|
40
|
-
|
|
41
|
-
---
|
|
42
|
-
|
|
43
|
-
## Step 1: Add Files
|
|
44
|
-
|
|
45
|
-
### `package.json`
|
|
46
|
-
|
|
47
|
-
```json
|
|
48
|
-
{
|
|
49
|
-
"name": "my-lwc-app",
|
|
50
|
-
"version": "1.0.0",
|
|
51
|
-
"type": "module",
|
|
52
|
-
"scripts": {
|
|
53
|
-
"build": "vite build",
|
|
54
|
-
"dev": "vite",
|
|
55
|
-
"preview": "vite preview"
|
|
56
|
-
},
|
|
57
|
-
"devDependencies": {
|
|
58
|
-
"@lwc/rollup-plugin": "^9.0.0",
|
|
59
|
-
"@salesforce/vite-plugin-lwc-ui-bundle": "^1.0.0",
|
|
60
|
-
"vite": "^7.0.0",
|
|
61
|
-
"vite-plugin-singlefile": "^2.3.0"
|
|
62
|
-
},
|
|
63
|
-
"dependencies": {
|
|
64
|
-
"@salesforce-ux/design-system": "^2.29.1",
|
|
65
|
-
"lightning-base-components": "^1.28.17-alpha",
|
|
66
|
-
"lwc": "^9.0.0"
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### `vite.config.js`
|
|
72
|
-
|
|
73
|
-
```js
|
|
74
|
-
import { defineConfig } from "vite";
|
|
75
|
-
import lwcVitePlugin from "@salesforce/vite-plugin-lwc-ui-bundle";
|
|
76
|
-
import { viteSingleFile } from "vite-plugin-singlefile";
|
|
77
|
-
|
|
78
|
-
export default defineConfig({
|
|
79
|
-
build: {
|
|
80
|
-
target: "esnext", // required for top-level await in bootstrap.js
|
|
81
|
-
},
|
|
82
|
-
plugins: [
|
|
83
|
-
lwcVitePlugin({
|
|
84
|
-
modules: {
|
|
85
|
-
// Flat DX structure: specify { path, namespace } per directory
|
|
86
|
-
// Use a plain string if your dir already has namespace sub-folders
|
|
87
|
-
dirs: [{ path: "force-app/main/default/lwc", namespace: "c" }],
|
|
88
|
-
|
|
89
|
-
// Include if your components use lightning/* base components
|
|
90
|
-
npm: ["lightning-base-components"],
|
|
91
|
-
},
|
|
92
|
-
}),
|
|
93
|
-
viteSingleFile(), // inlines everything into a single index.html
|
|
94
|
-
],
|
|
95
|
-
});
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### `index.html`
|
|
99
|
-
|
|
100
|
-
```html
|
|
101
|
-
<!doctype html>
|
|
102
|
-
<html lang="en">
|
|
103
|
-
<head>
|
|
104
|
-
<meta charset="UTF-8" />
|
|
105
|
-
<title>My LWC App</title>
|
|
106
|
-
</head>
|
|
107
|
-
<body>
|
|
108
|
-
<div id="app"></div>
|
|
109
|
-
<script>
|
|
110
|
-
globalThis.lwcRuntimeFlags = { DISABLE_SYNTHETIC_SHADOW: true };
|
|
111
|
-
</script>
|
|
112
|
-
<script type="module" src="/src/bootstrap.js"></script>
|
|
113
|
-
</body>
|
|
114
|
-
</html>
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### `src/bootstrap.js`
|
|
118
|
-
|
|
119
|
-
```js
|
|
120
|
-
import "@salesforce-ux/design-system/assets/styles/salesforce-lightning-design-system.css";
|
|
121
|
-
import "@lwc/synthetic-shadow";
|
|
122
|
-
import { createElement } from "lwc";
|
|
123
|
-
|
|
124
|
-
// Import your root component using its LWC specifier: <namespace>/<componentName>
|
|
125
|
-
import App from "c/helloApp";
|
|
126
|
-
|
|
127
|
-
// Mount it — tag name is the kebab-case version of the specifier
|
|
128
|
-
const el = createElement("c-hello-app", { is: App });
|
|
129
|
-
document.getElementById("app").appendChild(el);
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
---
|
|
133
|
-
|
|
134
|
-
## Step 2: Install Dependencies
|
|
135
|
-
|
|
136
|
-
```bash
|
|
137
|
-
npm install
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
---
|
|
141
|
-
|
|
142
|
-
## Step 3: Build
|
|
143
|
-
|
|
144
|
-
```bash
|
|
145
|
-
npm run build
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
Output: `dist/index.html` — a single file with all JS and CSS inlined.
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
## Step 4: Test
|
|
153
|
-
|
|
154
|
-
**Option A — Open directly in browser:**
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
open dist/index.html
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
**Option B — Dev server with live reload:**
|
|
161
|
-
|
|
162
|
-
```bash
|
|
163
|
-
npm run dev
|
|
164
|
-
# Open http://localhost:5173
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
**Option C — Preview the production build:**
|
|
168
|
-
|
|
169
|
-
```bash
|
|
170
|
-
npm run preview
|
|
171
|
-
# Open http://localhost:4173
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
---
|
|
175
|
-
|
|
176
|
-
## Component Namespace Convention
|
|
177
|
-
|
|
178
|
-
The plugin supports two directory structures:
|
|
179
|
-
|
|
180
|
-
### Flat DX structure (standard Salesforce DX)
|
|
181
|
-
|
|
182
|
-
```
|
|
183
|
-
force-app/main/default/lwc/
|
|
184
|
-
helloApp/
|
|
185
|
-
helloApp.js
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
Use `{ path, namespace }` per directory to specify the namespace:
|
|
189
|
-
|
|
190
|
-
```js
|
|
191
|
-
modules: {
|
|
192
|
-
dirs: [{ path: "force-app/main/default/lwc", namespace: "c" }];
|
|
193
|
-
}
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
| Directory | LWC Specifier | HTML Tag |
|
|
197
|
-
| ------------------- | ------------------ | ----------------- |
|
|
198
|
-
| `lwc/helloApp/` | `'c/helloApp'` | `c-hello-app` |
|
|
199
|
-
| `lwc/helloMessage/` | `'c/helloMessage'` | `c-hello-message` |
|
|
200
|
-
|
|
201
|
-
### Namespaced structure
|
|
202
|
-
|
|
203
|
-
```
|
|
204
|
-
modules/
|
|
205
|
-
records/
|
|
206
|
-
accountOutputName/
|
|
207
|
-
accountOutputName.js
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
Omit `namespace` — the sub-directory name is used as the namespace:
|
|
211
|
-
|
|
212
|
-
```js
|
|
213
|
-
modules: {
|
|
214
|
-
dirs: ["modules"];
|
|
215
|
-
}
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
| Directory | LWC Specifier | HTML Tag |
|
|
219
|
-
| ------------------------------------ | ----------------------------- | ----------------------------- |
|
|
220
|
-
| `modules/records/accountOutputName/` | `'records/accountOutputName'` | `records-account-output-name` |
|
|
221
|
-
|
|
222
|
-
---
|
|
223
|
-
|
|
224
|
-
## Common Errors
|
|
225
|
-
|
|
226
|
-
### `Rollup failed to resolve import "lightning/button"`
|
|
227
|
-
|
|
228
|
-
Your component uses a Lightning Base Component. Add to `vite.config.js`:
|
|
229
|
-
|
|
230
|
-
```js
|
|
231
|
-
modules: {
|
|
232
|
-
npm: ["lightning-base-components"];
|
|
233
|
-
}
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
### `[scoped-module-providers] Unhandled import: @salesforce/label/...`
|
|
237
|
-
|
|
238
|
-
Expected — the plugin returns the label key as display text by default.
|
|
239
|
-
To provide real label values:
|
|
240
|
-
|
|
241
|
-
```js
|
|
242
|
-
import { builtins } from "@salesforce/vite-plugin-lwc-ui-bundle";
|
|
243
|
-
|
|
244
|
-
lwcVitePlugin({
|
|
245
|
-
providers: [builtins.label({ "c.Save": "Save", "c.Cancel": "Cancel" })],
|
|
246
|
-
});
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
### Component renders but looks unstyled
|
|
250
|
-
|
|
251
|
-
Add SLDS import to `src/bootstrap.js`:
|
|
252
|
-
|
|
253
|
-
```js
|
|
254
|
-
import "@salesforce-ux/design-system/assets/styles/salesforce-lightning-design-system.css";
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
### `[scoped-module-providers] Unhandled import: @salesforce/user/Id`
|
|
258
|
-
|
|
259
|
-
Expected warning — `@salesforce/user/*` imports return `undefined` by default.
|
|
260
|
-
To provide real values (e.g. current user ID), add the user provider:
|
|
261
|
-
|
|
262
|
-
```js
|
|
263
|
-
import { builtins } from "@salesforce/vite-plugin-lwc-ui-bundle";
|
|
264
|
-
|
|
265
|
-
lwcVitePlugin({
|
|
266
|
-
providers: [
|
|
267
|
-
builtins.user({ Id: "005xx000001X8AAAA" }), // optional: override user fields
|
|
268
|
-
],
|
|
269
|
-
});
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
### `Top-level await is not available in the configured target environment`
|
|
273
|
-
|
|
274
|
-
Your `bootstrap.js` uses top-level `await` (required when initialising the Data
|
|
275
|
-
SDK). Add `target: 'esnext'` to the build config:
|
|
276
|
-
|
|
277
|
-
```js
|
|
278
|
-
export default defineConfig({
|
|
279
|
-
build: { target: "esnext" },
|
|
280
|
-
plugins: [...],
|
|
281
|
-
});
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
### `Rollup failed to resolve import "force/someModule"`
|
|
285
|
-
|
|
286
|
-
Core-only module — add a stub:
|
|
287
|
-
|
|
288
|
-
```js
|
|
289
|
-
// stubs/someModule.js
|
|
290
|
-
export const someExport = () => {};
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
```js
|
|
294
|
-
// vite.config.js
|
|
295
|
-
lwcVitePlugin({ stubs: { "force/someModule": "./stubs/someModule.js" } });
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
---
|
|
299
|
-
|
|
300
|
-
## Connecting to a Real Salesforce Org (lwcProxy)
|
|
301
|
-
|
|
302
|
-
By default the plugin runs fully off-platform with mock data. To connect your
|
|
303
|
-
components to a real Salesforce org in local dev — enabling `lightning/graphql`
|
|
304
|
-
to execute real queries — add `lwcProxy()` alongside `lwcVitePlugin()`.
|
|
305
|
-
|
|
306
|
-
### Prerequisites
|
|
307
|
-
|
|
308
|
-
- Salesforce CLI installed and an org connected: `sf org display`
|
|
309
|
-
- Additional packages: `@salesforce/sdk-data` and `@salesforce/ui-bundle`
|
|
310
|
-
|
|
311
|
-
```bash
|
|
312
|
-
npm install @salesforce/sdk-data @salesforce/ui-bundle
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
### 1. Add lwcProxy to vite.config.js
|
|
316
|
-
|
|
317
|
-
```js
|
|
318
|
-
import { defineConfig } from "vite";
|
|
319
|
-
import lwcVitePlugin, { lwcProxy } from "@salesforce/vite-plugin-lwc-ui-bundle";
|
|
320
|
-
import { viteSingleFile } from "vite-plugin-singlefile";
|
|
321
|
-
|
|
322
|
-
export default defineConfig({
|
|
323
|
-
build: {
|
|
324
|
-
target: "esnext", // required for top-level await in bootstrap.js
|
|
325
|
-
},
|
|
326
|
-
plugins: [
|
|
327
|
-
lwcProxy(), // auto-reads sf CLI default org credentials
|
|
328
|
-
// lwcProxy({ orgAlias: "my-org", debug: true }) // explicit org + verbose logging
|
|
329
|
-
lwcVitePlugin({
|
|
330
|
-
modules: {
|
|
331
|
-
dirs: [{ path: "force-app/main/default/lwc", namespace: "c" }],
|
|
332
|
-
},
|
|
333
|
-
}),
|
|
334
|
-
viteSingleFile(),
|
|
335
|
-
],
|
|
336
|
-
});
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
### 2. Initialise the Data SDK in bootstrap.js
|
|
340
|
-
|
|
341
|
-
The SDK must be initialised before any component that uses `lightning/graphql`
|
|
342
|
-
mounts. Use a top-level `await` import to guarantee ordering:
|
|
343
|
-
|
|
344
|
-
```js
|
|
345
|
-
import "@salesforce-ux/design-system/assets/styles/salesforce-lightning-design-system.css";
|
|
346
|
-
import "@lwc/synthetic-shadow";
|
|
347
|
-
import { createElement } from "lwc";
|
|
348
|
-
|
|
349
|
-
// Initialise the Data SDK — lwcProxy() handles /services/* on the Vite dev server
|
|
350
|
-
import { createDataSDK } from "@salesforce/sdk-data";
|
|
351
|
-
try {
|
|
352
|
-
globalThis.__sfdc_sdk__ = await createDataSDK({
|
|
353
|
-
uiBundle: { basePath: "/" },
|
|
354
|
-
});
|
|
355
|
-
} catch (_err) {
|
|
356
|
-
globalThis.__sfdc_sdk__ = {};
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
import App from "c/helloApp";
|
|
360
|
-
const el = createElement("c-hello-app", { is: App });
|
|
361
|
-
document.getElementById("app").appendChild(el);
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
### 3. Run the dev server
|
|
365
|
-
|
|
366
|
-
```bash
|
|
367
|
-
npm run dev
|
|
368
|
-
# Terminal shows: [lwc-proxy] Connected to https://your-org.my.salesforce.com
|
|
369
|
-
# Open http://localhost:5173
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
Components using `lightning/graphql` will now execute real GraphQL queries
|
|
373
|
-
against your org. The proxy intercepts `/services/*` calls inside the Vite dev
|
|
374
|
-
server — no separate proxy process needed.
|
|
375
|
-
|
|
376
|
-
> **Note:** The `basePath: '/'` setting works for `npm run dev` only. For
|
|
377
|
-
> production builds (`dist/index.html`), a standalone proxy server is required.
|