@salesforce/vite-plugin-lwc-ui-bundle 11.11.0 → 11.12.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/dist/index.d.ts CHANGED
@@ -6,5 +6,7 @@ export { builtinProviders as builtins };
6
6
  export { discoverModules } from './discovery';
7
7
  export { lwcProxy } from './plugins/proxy';
8
8
  export type { LwcProxyOptions } from './plugins/proxy';
9
+ export { livePreview } from './plugins/live-preview';
10
+ export type { LivePreviewOptions } from './plugins/live-preview';
9
11
  export default function lwcVitePlugin(options?: LwcVitePluginOptions): Plugin[];
10
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAOnC,OAAO,KAAK,gBAAgB,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAEX,oBAAoB,EAIpB,MAAM,SAAS,CAAC;AAEjB,YAAY,EACX,QAAQ,EACR,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,SAAS,GACT,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,gBAAgB,IAAI,QAAQ,EAAE,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAsCvD,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,MAAM,EAAE,CA8LlF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAQnC,OAAO,KAAK,gBAAgB,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAEX,oBAAoB,EAIpB,MAAM,SAAS,CAAC;AAEjB,YAAY,EACX,QAAQ,EACR,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,SAAS,GACT,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,gBAAgB,IAAI,QAAQ,EAAE,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAsCjE,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,MAAM,EAAE,CAkMlF"}
package/dist/index.js CHANGED
@@ -85,6 +85,39 @@ function lightningNpm({ npmRoot, overrideDirs = [] }) {
85
85
  }
86
86
  };
87
87
  }
88
+ function livePreview(options = {}) {
89
+ let isServe = false;
90
+ return {
91
+ name: "vite-plugin-lwc-live-preview",
92
+ enforce: "pre",
93
+ configResolved(config) {
94
+ isServe = config.command === "serve";
95
+ },
96
+ transformIndexHtml: {
97
+ order: "pre",
98
+ async handler(html) {
99
+ if (!isServe) return html;
100
+ try {
101
+ const { injectLivePreviewScript } = await import("@salesforce/ui-bundle/proxy");
102
+ const injected = injectLivePreviewScript(html);
103
+ if (options.debug) {
104
+ console.log("[lwc-live-preview] Injected Live Preview bridge script");
105
+ }
106
+ return injected;
107
+ } catch (error) {
108
+ if (options.debug) {
109
+ const msg = error instanceof Error ? error.message : String(error);
110
+ console.warn(
111
+ `[lwc-live-preview] @salesforce/ui-bundle not available; skipping Live Preview injection.
112
+ ${msg}`
113
+ );
114
+ }
115
+ return html;
116
+ }
117
+ }
118
+ }
119
+ };
120
+ }
88
121
  function lwcBridge(isComponentAsset) {
89
122
  return {
90
123
  name: "vite-plugin-lwc-bridge",
@@ -453,6 +486,10 @@ function lwcVitePlugin(options = {}) {
453
486
  (p) => p.passthroughRules ?? []
454
487
  );
455
488
  const plugins = [
489
+ // Dev-only: injects the Live Preview bridge into index.html so LWC UI
490
+ // Bundles work with the VSCode Live Preview extension. No-op during
491
+ // `vite build`; degrades silently if @salesforce/ui-bundle is absent.
492
+ livePreview(),
456
493
  {
457
494
  name: "vite-plugin-lwc-optimize-deps",
458
495
  config() {
@@ -552,6 +589,7 @@ export {
552
589
  i as builtins,
553
590
  lwcVitePlugin as default,
554
591
  discoverModules,
592
+ livePreview,
555
593
  lwcProxy
556
594
  };
557
595
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/discovery.ts","../src/plugins/lightning-npm.ts","../src/plugins/lwc-bridge.ts","../src/plugins/lwc-wrapper.ts","../src/plugins/missing-css.ts","../src/plugins/scoped-providers.ts","../src/plugins/proxy.ts","../src/index.ts"],"sourcesContent":["/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport { existsSync, readdirSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { DirConfig, DiscoveredModule } from \"./types\";\n\nexport function discoverModules(dirs: (string | DirConfig)[] = []): DiscoveredModule[] {\n\tconst modules: DiscoveredModule[] = [];\n\n\tfor (const dir of dirs) {\n\t\tconst dirPath = typeof dir === \"string\" ? dir : dir.path;\n\t\tconst namespace = typeof dir === \"string\" ? undefined : dir.namespace;\n\t\tconst resolvedDir = path.resolve(dirPath);\n\n\t\tif (!existsSync(resolvedDir) || !statSync(resolvedDir).isDirectory()) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (namespace) {\n\t\t\t// Flat DX structure: <dir>/<componentName>/<componentName>.js\n\t\t\tfor (const name of readdirSync(resolvedDir)) {\n\t\t\t\tconst fullPath = path.join(resolvedDir, name);\n\t\t\t\tif (!statSync(fullPath).isDirectory()) continue;\n\n\t\t\t\tconst entryPath = path.join(fullPath, `${name}.js`);\n\t\t\t\tif (existsSync(entryPath)) {\n\t\t\t\t\tmodules.push({\n\t\t\t\t\t\tname: `${namespace}/${name}`,\n\t\t\t\t\t\tpath: path.resolve(entryPath),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Standard structure: <dir>/<namespace>/<componentName>/<componentName>.js\n\t\t\tfor (const ns of readdirSync(resolvedDir)) {\n\t\t\t\tconst nsDir = path.join(resolvedDir, ns);\n\t\t\t\tif (!statSync(nsDir).isDirectory()) continue;\n\n\t\t\t\tfor (const name of readdirSync(nsDir)) {\n\t\t\t\t\tconst fullPath = path.join(nsDir, name);\n\t\t\t\t\tif (!statSync(fullPath).isDirectory()) continue;\n\n\t\t\t\t\tconst entryPath = path.join(fullPath, `${name}.js`);\n\t\t\t\t\tif (existsSync(entryPath)) {\n\t\t\t\t\t\tmodules.push({\n\t\t\t\t\t\t\tname: `${ns}/${name}`,\n\t\t\t\t\t\t\tpath: path.resolve(entryPath),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn modules;\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { Plugin } from \"vite\";\nimport type { LightningNpmOptions } from \"../types\";\n\nfunction resolveJsFromRoot(root: string, sub: string): string | null {\n\tconst segments = sub.split(\"/\");\n\tconst leaf = segments[segments.length - 1];\n\tconst nested = path.join(root, ...segments, `${leaf}.js`);\n\tif (existsSync(nested)) return nested;\n\tconst flat = path.join(root, `${sub}.js`);\n\tif (existsSync(flat)) return flat;\n\treturn null;\n}\n\nfunction resolveCssFromRoot(root: string, sub: string): string | null {\n\tconst segments = sub.split(\"/\");\n\tconst leaf = segments[segments.length - 1];\n\tconst nested = path.join(root, ...segments, `${leaf}.css`);\n\treturn existsSync(nested) ? nested : null;\n}\n\nexport function lightningNpm({ npmRoot, overrideDirs = [] }: LightningNpmOptions): Plugin {\n\treturn {\n\t\tname: \"vite-plugin-resolve-lightning-npm\",\n\t\tenforce: \"pre\",\n\n\t\tresolveId(importee) {\n\t\t\tif (!importee.startsWith(\"lightning/\")) return null;\n\n\t\t\tconst sub = importee.slice(\"lightning/\".length);\n\t\t\tconst segments = sub.split(\"/\");\n\t\t\tconst leaf = segments[segments.length - 1];\n\n\t\t\tfor (const dir of overrideDirs) {\n\t\t\t\tconst overridePath = path.join(dir, ...segments, `${leaf}.js`);\n\t\t\t\tif (existsSync(overridePath)) return null;\n\t\t\t}\n\n\t\t\tconst npmJs = resolveJsFromRoot(npmRoot, sub);\n\t\t\tif (npmJs) return npmJs;\n\n\t\t\tfor (const dir of overrideDirs) {\n\t\t\t\tconst cssFallback = path.join(dir, ...segments, `${leaf}.css`);\n\t\t\t\tif (existsSync(cssFallback)) return cssFallback;\n\t\t\t}\n\n\t\t\treturn resolveCssFromRoot(npmRoot, sub);\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 { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { Plugin, ResolvedConfig } from \"vite\";\n\nexport function lwcBridge(isComponentAsset: (id: string) => boolean): Plugin {\n\treturn {\n\t\tname: \"vite-plugin-lwc-bridge\",\n\t\tenforce: \"pre\",\n\n\t\tconfigResolved(config: ResolvedConfig) {\n\t\t\tfor (const plugin of config.plugins) {\n\t\t\t\tif (plugin.name === \"vite:css\" || plugin.name === \"vite:css-post\") {\n\t\t\t\t\tconst p = plugin as unknown as Record<string, unknown>;\n\t\t\t\t\tconst origTransform = p[\"transform\"];\n\t\t\t\t\tif (!origTransform) continue;\n\n\t\t\t\t\tif (typeof origTransform === \"function\") {\n\t\t\t\t\t\t// Vite <7: transform is a plain function\n\t\t\t\t\t\tp[\"transform\"] = function (\n\t\t\t\t\t\t\tthis: unknown,\n\t\t\t\t\t\t\tcode: string,\n\t\t\t\t\t\t\tid: string,\n\t\t\t\t\t\t\t...rest: unknown[]\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tif (isComponentAsset(id)) return;\n\t\t\t\t\t\t\treturn (origTransform as (...a: unknown[]) => unknown).call(this, code, id, ...rest);\n\t\t\t\t\t\t};\n\t\t\t\t\t} else if (\n\t\t\t\t\t\ttypeof origTransform === \"object\" &&\n\t\t\t\t\t\ttypeof (origTransform as Record<string, unknown>)[\"handler\"] === \"function\"\n\t\t\t\t\t) {\n\t\t\t\t\t\t// Vite 7+: transform is { handler, order? }\n\t\t\t\t\t\tconst origHandler = (origTransform as Record<string, unknown>)[\"handler\"] as (\n\t\t\t\t\t\t\t...a: unknown[]\n\t\t\t\t\t\t) => unknown;\n\t\t\t\t\t\tp[\"transform\"] = {\n\t\t\t\t\t\t\t...(origTransform as object),\n\t\t\t\t\t\t\thandler: function (this: unknown, code: string, id: string, ...rest: unknown[]) {\n\t\t\t\t\t\t\t\tif (isComponentAsset(id)) return;\n\t\t\t\t\t\t\t\treturn origHandler.call(this, code, id, ...rest);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tresolveId(id, importer) {\n\t\t\tif (id.startsWith(\"@lwc/resources/\")) {\n\t\t\t\treturn id;\n\t\t\t}\n\n\t\t\tconst cleanId = id.split(\"?\", 2)[0] ?? id;\n\n\t\t\tif (cleanId.endsWith(\".html\") && isComponentAsset(cleanId) && !id.includes(\"?lwc\")) {\n\t\t\t\treturn `${cleanId}?lwc`;\n\t\t\t}\n\n\t\t\tif (!importer) return null;\n\t\t\tif (!cleanId.endsWith(\".html\")) return null;\n\t\t\tif (!cleanId.startsWith(\"./\") && !cleanId.startsWith(\"../\")) return null;\n\t\t\tif (!isComponentAsset(importer)) return null;\n\n\t\t\tconst resolved = path.resolve(path.dirname(importer.split(\"?\")[0] ?? importer), cleanId);\n\n\t\t\tif (existsSync(resolved)) {\n\t\t\t\treturn resolved + \"?lwc\";\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\n\t\tload(id) {\n\t\t\tif (id.startsWith(\"@lwc/resources/\")) {\n\t\t\t\treturn \"export default undefined;\";\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 { Plugin } from \"vite\";\n\ntype AnyFn = (this: unknown, ...args: unknown[]) => unknown;\ntype LwcRollupFactory = (options: Record<string, unknown>) => Plugin;\ntype LazyLwcRollupLoader = () => Promise<LwcRollupFactory>;\n\nexport function lwcWrapper(\n\tlazyLoader: LazyLwcRollupLoader,\n\toptions: Record<string, unknown>,\n\tisComponentAsset?: (id: string) => boolean,\n): Plugin {\n\tlet pluginPromise: Promise<Plugin> | null = null;\n\n\tconst getPlugin = () => {\n\t\tif (!pluginPromise) {\n\t\t\tpluginPromise = lazyLoader().then((factory) => factory(options));\n\t\t}\n\t\treturn pluginPromise;\n\t};\n\n\treturn {\n\t\tname: \"vite-plugin-lwc-wrapper\",\n\t\tenforce: \"pre\" as const,\n\t\tasync resolveId(importee: string, importer?: string) {\n\t\t\tif (importer?.split(\"?\")[0]?.endsWith(\"index.html\") && !importer.includes(\"html-proxy\"))\n\t\t\t\treturn null;\n\t\t\tif (importee.startsWith(\"/@\") || importee.startsWith(\"\\0\")) return null;\n\t\t\tif (importer?.includes(\"/node_modules/vite/\")) return null;\n\t\t\tconst plugin = await getPlugin();\n\t\t\treturn typeof plugin.resolveId === \"function\"\n\t\t\t\t? (plugin.resolveId as AnyFn).call(this, importee, importer)\n\t\t\t\t: null;\n\t\t},\n\t\tasync load(id: string) {\n\t\t\tconst plugin = await getPlugin();\n\t\t\treturn typeof plugin.load === \"function\" ? (plugin.load as AnyFn).call(this, id) : null;\n\t\t},\n\t\tasync transform(code: string, id: string) {\n\t\t\t// Only pass files to the LWC compiler if they are LWC component assets.\n\t\t\t// Non-component files (SDK sources, node_modules, etc.) must be skipped.\n\t\t\tif (isComponentAsset && !isComponentAsset(id)) return null;\n\t\t\tconst plugin = await getPlugin();\n\t\t\treturn typeof plugin.transform === \"function\"\n\t\t\t\t? (plugin.transform as AnyFn).call(this, code, id)\n\t\t\t\t: null;\n\t\t},\n\t} as Plugin;\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { Plugin } from \"vite\";\n\nconst LWC_EMPTY_CSS = \"\\0lwc-empty-css\";\n\nexport function missingCss(): Plugin {\n\treturn {\n\t\tname: \"vite-plugin-lwc-missing-css\",\n\t\tenforce: \"pre\",\n\n\t\tresolveId(id, importer) {\n\t\t\tif (!importer || !id.startsWith(\"./\") || !id.includes(\".css\")) return null;\n\t\t\tconst importerPath = importer.split(\"?\")[0] ?? importer;\n\t\t\tif (!importerPath.endsWith(\".html\")) return null;\n\n\t\t\tconst resolved = path.resolve(path.dirname(importerPath), id.split(\"?\")[0] ?? id);\n\t\t\tif (existsSync(resolved)) return null;\n\n\t\t\treturn `${LWC_EMPTY_CSS}?${id}`;\n\t\t},\n\n\t\tload(id) {\n\t\t\tif (id.startsWith(LWC_EMPTY_CSS)) {\n\t\t\t\treturn \"export default undefined\";\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 { Plugin } from \"vite\";\nimport type { Provider, ScopedProvidersOptions } from \"../types\";\n\nconst VIRTUAL_PREFIX = \"\\0sf-provider:\";\n\nexport function scopedProviders(\n\tproviders: Provider[] = [],\n\toptions: ScopedProvidersOptions = {},\n): Plugin {\n\tconst { ignorePatterns = [], interceptPrefixes = [], passthroughRules = [] } = options;\n\n\tconst prefixSet = new Set<string>();\n\tfor (const p of providers) {\n\t\tif (p.prefix) prefixSet.add(p.prefix);\n\t}\n\n\tfunction shouldIntercept(id: string): boolean {\n\t\tfor (const prefix of prefixSet) {\n\t\t\tif (id === prefix || id.startsWith(prefix)) return true;\n\t\t}\n\t\tfor (const prefix of interceptPrefixes) {\n\t\t\tif (id.startsWith(prefix)) return true;\n\t\t}\n\t\tfor (const p of providers) {\n\t\t\tif (!p.prefix && typeof p.match === \"function\" && p.match(id)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\treturn {\n\t\tname: \"vite-plugin-scoped-module-providers\",\n\t\tenforce: \"pre\",\n\n\t\tresolveId(id, importer) {\n\t\t\t// Explicit provider prefix always wins over ignorePatterns —\n\t\t\t// if a provider is registered for a specifier, it always handles it.\n\t\t\tconst handledByProvider = [...prefixSet].some((p) => id === p || id.startsWith(p + \"/\"));\n\n\t\t\tif (!handledByProvider) {\n\t\t\t\tif (!shouldIntercept(id)) return null;\n\n\t\t\t\tfor (const pattern of ignorePatterns) {\n\t\t\t\t\tif (id.startsWith(pattern)) return null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const rule of passthroughRules) {\n\t\t\t\tif (\n\t\t\t\t\timporter &&\n\t\t\t\t\tid.startsWith(rule.specifierPrefix) &&\n\t\t\t\t\timporter.includes(rule.importerPattern)\n\t\t\t\t) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn VIRTUAL_PREFIX + id;\n\t\t},\n\n\t\tload(id) {\n\t\t\tif (!id.startsWith(VIRTUAL_PREFIX)) return null;\n\n\t\t\tconst specifier = id.slice(VIRTUAL_PREFIX.length);\n\n\t\t\tfor (const provider of providers) {\n\t\t\t\tconst result = provider.resolve(specifier);\n\t\t\t\tif (result != null) return result;\n\t\t\t}\n\n\t\t\tconsole.warn(\n\t\t\t\t`[scoped-module-providers] Unhandled import: ${specifier} — returning undefined`,\n\t\t\t);\n\t\t\treturn `export default undefined;`;\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 * as http from \"node:http\";\nimport * as https from \"node:https\";\nimport type { Plugin } from \"vite\";\n\nexport interface LwcProxyOptions {\n\t/** Salesforce org alias (defaults to the sf CLI default org) */\n\torgAlias?: string;\n\t/** Enable verbose request logging */\n\tdebug?: boolean;\n}\n\n/**\n * Vite plugin that proxies Salesforce API calls to a connected org.\n *\n * Uses the same authentication approach as @salesforce/vite-plugin-ui-bundle —\n * reads credentials from the sf CLI via @salesforce/ui-bundle/app.\n *\n * Intercepts requests to /services/ and /lwr/ and forwards them to Salesforce\n * with the org's access token. Handles token refresh on 401/403 responses.\n *\n * Usage in vite.config.js:\n * import { lwcProxy } from '@salesforce/vite-plugin-lwc-ui-bundle';\n * plugins: [lwcVitePlugin(...), lwcProxy()]\n *\n * Then initialise the SDK in your app's bootstrap:\n * import { createDataSDK } from '@salesforce/platform-sdk';\n * globalThis.__sfdc_sdk__ = await createDataSDK({ uiBundle: { basePath: '/' } });\n */\nexport function lwcProxy(options: LwcProxyOptions = {}): Plugin {\n\tlet instanceUrl: string | undefined;\n\tlet accessToken: string | undefined;\n\tconst orgAlias: string | undefined = options.orgAlias;\n\n\tasync function loadOrgInfo(): Promise<void> {\n\t\ttry {\n\t\t\t// Dynamically import to avoid bundling @salesforce/ui-bundle at build time\n\t\t\tconst { getOrgInfo } = await import(\"@salesforce/ui-bundle/app\");\n\t\t\tconst info = await getOrgInfo(orgAlias);\n\t\t\tif (info) {\n\t\t\t\tinstanceUrl = info.rawInstanceUrl ?? info.instanceUrl;\n\t\t\t\taccessToken = info.accessToken;\n\t\t\t\tif (options.debug) {\n\t\t\t\t\tconsole.log(`[lwc-proxy] Connected to ${instanceUrl}`);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst msg = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.error(\n\t\t\t\t`[lwc-proxy] Failed to load org info — is a Salesforce org connected?\\n ${msg}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync function refreshToken(): Promise<void> {\n\t\ttry {\n\t\t\tconst { refreshOrgAuth } = await import(\"@salesforce/ui-bundle/app\");\n\t\t\tconst info = await refreshOrgAuth(orgAlias ?? \"\");\n\t\t\tif (info) {\n\t\t\t\tinstanceUrl = info.rawInstanceUrl ?? info.instanceUrl;\n\t\t\t\taccessToken = info.accessToken;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore refresh errors\n\t\t}\n\t}\n\n\treturn {\n\t\tname: \"vite-plugin-lwc-proxy\",\n\t\tenforce: \"pre\",\n\n\t\tasync configResolved() {\n\t\t\tawait loadOrgInfo();\n\t\t},\n\n\t\tconfigureServer(server) {\n\t\t\tserver.middlewares.use(async (req, res, next) => {\n\t\t\t\tconst url = req.url ?? \"\";\n\n\t\t\t\t// Only proxy Salesforce API paths\n\t\t\t\tif (!url.startsWith(\"/services/\") && !url.startsWith(\"/lwr/\")) {\n\t\t\t\t\treturn next();\n\t\t\t\t}\n\n\t\t\t\tif (!instanceUrl || !accessToken) {\n\t\t\t\t\tres.writeHead(503, { \"Content-Type\": \"application/json\" });\n\t\t\t\t\tres.end(\n\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\terror: \"SERVICE_UNAVAILABLE\",\n\t\t\t\t\t\t\tmessage: \"Salesforce org not connected. Run: sf org display\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst forward = async (token: string): Promise<void> => {\n\t\t\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t\t\tconst targetUrl = new URL(url, instanceUrl);\n\t\t\t\t\t\tconst isHttps = targetUrl.protocol === \"https:\";\n\t\t\t\t\t\tconst transport = isHttps ? https : http;\n\n\t\t\t\t\t\tif (options.debug) {\n\t\t\t\t\t\t\tconsole.log(`[lwc-proxy] ${req.method} ${url}`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Strip hop-by-hop headers\n\t\t\t\t\t\tconst headers: Record<string, string | string[]> = {};\n\t\t\t\t\t\tfor (const [key, value] of Object.entries(req.headers)) {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t![\n\t\t\t\t\t\t\t\t\t\"host\",\n\t\t\t\t\t\t\t\t\t\"connection\",\n\t\t\t\t\t\t\t\t\t\"keep-alive\",\n\t\t\t\t\t\t\t\t\t\"proxy-authenticate\",\n\t\t\t\t\t\t\t\t\t\"proxy-authorization\",\n\t\t\t\t\t\t\t\t\t\"te\",\n\t\t\t\t\t\t\t\t\t\"trailers\",\n\t\t\t\t\t\t\t\t\t\"transfer-encoding\",\n\t\t\t\t\t\t\t\t\t\"upgrade\",\n\t\t\t\t\t\t\t\t].includes(key.toLowerCase()) &&\n\t\t\t\t\t\t\t\tvalue !== undefined\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\theaders[key] = value as string | string[];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\theaders[\"host\"] = targetUrl.host;\n\t\t\t\t\t\theaders[\"authorization\"] = `Bearer ${token}`;\n\t\t\t\t\t\theaders[\"cookie\"] = `sid=${token}`;\n\n\t\t\t\t\t\tconst proxyReq = transport.request(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmethod: req.method,\n\t\t\t\t\t\t\t\thostname: targetUrl.hostname,\n\t\t\t\t\t\t\t\tport: targetUrl.port || (isHttps ? 443 : 80),\n\t\t\t\t\t\t\t\tpath: targetUrl.pathname + targetUrl.search,\n\t\t\t\t\t\t\t\theaders,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t(proxyRes) => {\n\t\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\t\tres.writeHead(proxyRes.statusCode ?? 200, proxyRes.headers);\n\t\t\t\t\t\t\t\tproxyRes.pipe(res);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\treq.pipe(proxyReq);\n\t\t\t\t\t\tproxyReq.on(\"error\", reject);\n\t\t\t\t\t});\n\t\t\t\t};\n\n\t\t\t\ttry {\n\t\t\t\t\tawait forward(accessToken!);\n\n\t\t\t\t\t// On 401/403, refresh token and retry once\n\t\t\t\t\t// Note: we can't easily check status here since we piped to res,\n\t\t\t\t\t// so we rely on the transform hook below for retries in future iterations\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (options.debug) {\n\t\t\t\t\t\tconsole.error(\"[lwc-proxy] Request failed:\", error);\n\t\t\t\t\t}\n\t\t\t\t\t// Try refreshing token and retry\n\t\t\t\t\tawait refreshToken();\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait forward(accessToken!);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tnext(err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\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 { createRequire } from \"node:module\";\nimport path from \"node:path\";\nimport type { Plugin } from \"vite\";\nimport { discoverModules } from \"./discovery\";\nimport { lightningNpm } from \"./plugins/lightning-npm\";\nimport { lwcBridge } from \"./plugins/lwc-bridge\";\nimport { lwcWrapper } from \"./plugins/lwc-wrapper\";\nimport { missingCss } from \"./plugins/missing-css\";\nimport { scopedProviders } from \"./plugins/scoped-providers\";\nimport * as builtinProviders from \"./providers/index\";\nimport type {\n\tDirConfig,\n\tLwcVitePluginOptions,\n\tNpmModuleConfig,\n\tPassthroughRule,\n\tProvider,\n} from \"./types\";\n\nexport type {\n\tProvider,\n\tLwcVitePluginOptions,\n\tPassthroughRule,\n\tDiscoveredModule,\n\tDirConfig,\n} from \"./types\";\nexport { builtinProviders as builtins };\nexport { discoverModules } from \"./discovery\";\nexport { lwcProxy } from \"./plugins/proxy\";\nexport type { LwcProxyOptions } from \"./plugins/proxy\";\n\nfunction defaultProviders(): (Provider | Plugin)[] {\n\treturn [\n\t\tbuiltinProviders.label(),\n\t\tbuiltinProviders.i18n(),\n\t\tbuiltinProviders.accessCheck(),\n\t\tbuiltinProviders.apex(),\n\t\tbuiltinProviders.client(),\n\t\tbuiltinProviders.gate(),\n\t\tbuiltinProviders.messageChannel(),\n\t\tbuiltinProviders.messageService(),\n\t\tbuiltinProviders.navigation(),\n\t\tbuiltinProviders.primitiveUtils(),\n\t\tbuiltinProviders.lds(),\n\t];\n}\n\n/** Distinguishes a scoped-providers `Provider` from a raw Vite `Plugin`. */\nfunction isProvider(item: Provider | Plugin): item is Provider {\n\treturn typeof (item as Provider).resolve === \"function\";\n}\n\nasync function loadLwcRollup() {\n\ttry {\n\t\t// Use dynamic import to load ESM-only @lwc/rollup-plugin (peer dep, types not guaranteed)\n\t\tconst mod = await (import(\"@lwc/rollup-plugin\") as Promise<Record<string, unknown>>);\n\t\treturn (mod[\"default\"] ?? mod) as unknown as (options: Record<string, unknown>) => Plugin;\n\t} catch (error) {\n\t\tconst errMsg = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(\n\t\t\t\"@salesforce/vite-plugin-lwc-ui-bundle requires @lwc/rollup-plugin as a peer dependency. \" +\n\t\t\t\t\"Install it with: npm install -D @lwc/rollup-plugin\\n\" +\n\t\t\t\t`Debug: cwd=${process.cwd()}, error=${errMsg}`,\n\t\t);\n\t}\n}\n\nexport default function lwcVitePlugin(options: LwcVitePluginOptions = {}): Plugin[] {\n\tconst {\n\t\tmodules = {},\n\t\tproviders,\n\t\tstubs = {},\n\t\tlwcOptions = {},\n\t\tignorePatterns = [\n\t\t\t// Legacy @salesforce/sdk-* prefix — kept for external consumers still on the\n\t\t\t// pre-rename package names. The `@salesforce/platform-sdk-` prefix covers the\n\t\t\t// individual platform-sdk-* packages (still in place pending deprecation);\n\t\t\t// `@salesforce/platform-sdk` (no trailing dash) covers the consolidated package.\n\t\t\t\"@salesforce/sdk-\",\n\t\t\t\"@salesforce/platform-sdk-\",\n\t\t\t\"@salesforce/platform-sdk\",\n\t\t\t\"@salesforce/core\",\n\t\t\t\"@salesforce/vite-plugin-lwc-ui-bundle\",\n\t\t],\n\t\tpassthroughRules = [],\n\t\tbundle = true,\n\t} = options;\n\n\tconst resolvedItems = providers ?? defaultProviders();\n\tconst resolvedProviders = resolvedItems.filter(isProvider);\n\tconst rawPlugins = resolvedItems.filter((item): item is Plugin => !isProvider(item));\n\n\tconst { dirs = [], npm: npmPackages = [] } = modules;\n\n\tconst resolvedDirs: DirConfig[] = dirs.map((d) =>\n\t\ttypeof d === \"string\"\n\t\t\t? { path: path.resolve(d), namespace: \"\" }\n\t\t\t: { ...d, path: path.resolve(d.path) },\n\t);\n\n\tconst npmConfigs: NpmModuleConfig[] = npmPackages.map((pkg) =>\n\t\ttypeof pkg === \"string\" ? { npm: pkg } : pkg,\n\t);\n\n\tconst require = createRequire(import.meta.url);\n\tconst npmRoots = npmConfigs.map((cfg) => {\n\t\tconst pkgJson = require.resolve(`${cfg.npm}/package.json`);\n\t\treturn path.join(path.dirname(pkgJson), \"src\", \"lightning\");\n\t});\n\n\tconst discoveredModules = discoverModules(dirs);\n\n\tconst lwcModules = [...npmConfigs, ...discoveredModules];\n\n\tconst lightningOverrideDirs = resolvedDirs.map((d) => path.join(d.path, \"lightning\"));\n\n\tfunction isComponentAsset(id: string): boolean {\n\t\tconst clean = id.split(\"?\")[0] ?? id;\n\t\tfor (const dir of resolvedDirs) {\n\t\t\tif (clean.includes(dir.path)) return true;\n\t\t}\n\t\tfor (const cfg of npmConfigs) {\n\t\t\tif (clean.includes(cfg.npm)) return true;\n\t\t}\n\t\treturn clean.includes(\"@lwc/\") || clean.startsWith(\"\\0lwc-empty-css\");\n\t}\n\n\tconst stubAliases: Record<string, string> = {};\n\tfor (const [specifier, stubPath] of Object.entries(stubs)) {\n\t\tstubAliases[specifier] = path.resolve(stubPath);\n\t}\n\n\tconst interceptPrefixes = new Set<string>();\n\tfor (const p of resolvedProviders) {\n\t\tif (p.prefix && p.prefix.startsWith(\"@\")) {\n\t\t\tinterceptPrefixes.add(p.prefix.split(\"/\")[0] + \"/\");\n\t\t}\n\t}\n\n\t// Plugin-style providers (e.g. lds()) can contribute passthroughRules so\n\t// imports made from inside their virtual modules reach the real npm\n\t// package instead of being claimed by scopedProviders' broad\n\t// `@salesforce/` interceptPrefix.\n\tconst pluginPassthroughRules = rawPlugins.flatMap(\n\t\t(p) => (p as { passthroughRules?: PassthroughRule[] }).passthroughRules ?? [],\n\t);\n\n\tconst plugins: Plugin[] = [\n\t\t{\n\t\t\tname: \"vite-plugin-lwc-optimize-deps\",\n\t\t\tconfig() {\n\t\t\t\treturn {\n\t\t\t\t\toptimizeDeps: {\n\t\t\t\t\t\texclude: [\"lwc\"],\n\t\t\t\t\t\tesbuildOptions: {\n\t\t\t\t\t\t\tplugins: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: \"lwc-html-stub\",\n\t\t\t\t\t\t\t\t\tsetup(build: {\n\t\t\t\t\t\t\t\t\t\tonResolve: (\n\t\t\t\t\t\t\t\t\t\t\toptions: { filter: RegExp },\n\t\t\t\t\t\t\t\t\t\t\tcallback: (args: { path: string }) => {\n\t\t\t\t\t\t\t\t\t\t\t\tpath: string;\n\t\t\t\t\t\t\t\t\t\t\t\texternal: boolean;\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t) => void;\n\t\t\t\t\t\t\t\t\t}) {\n\t\t\t\t\t\t\t\t\t\t// esbuild cannot process LWC HTML templates (?lwc suffix).\n\t\t\t\t\t\t\t\t\t\t// Mark them as external so Vite's own plugin handles them.\n\t\t\t\t\t\t\t\t\t\tbuild.onResolve({ filter: /\\.html/ }, (args: { path: string }) => ({\n\t\t\t\t\t\t\t\t\t\t\tpath: args.path,\n\t\t\t\t\t\t\t\t\t\t\texternal: true,\n\t\t\t\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t\t// plugins returned by plugin-style builtins (e.g. lds())\n\t\t...rawPlugins,\n\t\tscopedProviders(resolvedProviders, {\n\t\t\tignorePatterns,\n\t\t\tinterceptPrefixes: [...interceptPrefixes],\n\t\t\tpassthroughRules: [...passthroughRules, ...pluginPassthroughRules],\n\t\t}),\n\n\t\t...npmRoots.map((npmRoot) =>\n\t\t\tlightningNpm({\n\t\t\t\tnpmRoot,\n\t\t\t\toverrideDirs: lightningOverrideDirs,\n\t\t\t}),\n\t\t),\n\n\t\tmissingCss(),\n\t\tlwcBridge(isComponentAsset),\n\t\tlwcWrapper(\n\t\t\tloadLwcRollup,\n\t\t\t{\n\t\t\t\trootDir: process.cwd(),\n\t\t\t\t...lwcOptions,\n\t\t\t\tmodules: lwcModules,\n\t\t\t\texclude: [\n\t\t\t\t\t\"**/index.html\",\n\t\t\t\t\t\"**/node_modules/vite/**\",\n\t\t\t\t\t\"**/node_modules/.vite/**\",\n\t\t\t\t\t...((lwcOptions.exclude as string[]) || []),\n\t\t\t\t],\n\t\t\t},\n\t\t\tisComponentAsset,\n\t\t),\n\t];\n\n\tif (Object.keys(stubAliases).length > 0) {\n\t\tplugins.push({\n\t\t\tname: \"vite-plugin-lwc-stubs\",\n\t\t\tenforce: \"pre\",\n\t\t\tconfig() {\n\t\t\t\treturn {\n\t\t\t\t\tresolve: {\n\t\t\t\t\t\talias: stubAliases,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t});\n\t}\n\n\tif (!bundle) {\n\t\tplugins.push({\n\t\t\tname: \"vite-plugin-lwc-output-multifile\",\n\t\t\tenforce: \"pre\",\n\t\t\tconfig() {\n\t\t\t\treturn {\n\t\t\t\t\tbuild: {\n\t\t\t\t\t\toutDir: \"dist\",\n\t\t\t\t\t\tassetsDir: \".\",\n\t\t\t\t\t\tcssCodeSplit: true,\n\t\t\t\t\t\trollupOptions: {\n\t\t\t\t\t\t\toutput: {\n\t\t\t\t\t\t\t\tentryFileNames: \"js/[name]-[hash].js\",\n\t\t\t\t\t\t\t\tchunkFileNames: \"js/[name]-[hash].js\",\n\t\t\t\t\t\t\t\tassetFileNames(info: { names?: string[]; name?: string }) {\n\t\t\t\t\t\t\t\t\tconst name = info.names?.[0] ?? info.name ?? \"\";\n\t\t\t\t\t\t\t\t\tif (name.endsWith(\".css\")) return \"css/[name]-[hash].css\";\n\t\t\t\t\t\t\t\t\treturn \"assets/[name]-[hash][extname]\";\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t});\n\t}\n\n\treturn plugins;\n}\n"],"names":["builtinProviders.label","builtinProviders.i18n","builtinProviders.accessCheck","builtinProviders.apex","builtinProviders.client","builtinProviders.gate","builtinProviders.messageChannel","builtinProviders.messageService","builtinProviders.navigation","builtinProviders.primitiveUtils","builtinProviders.lds","require"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/discovery.ts","../src/plugins/lightning-npm.ts","../src/plugins/live-preview.ts","../src/plugins/lwc-bridge.ts","../src/plugins/lwc-wrapper.ts","../src/plugins/missing-css.ts","../src/plugins/scoped-providers.ts","../src/plugins/proxy.ts","../src/index.ts"],"sourcesContent":["/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport { existsSync, readdirSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { DirConfig, DiscoveredModule } from \"./types\";\n\nexport function discoverModules(dirs: (string | DirConfig)[] = []): DiscoveredModule[] {\n\tconst modules: DiscoveredModule[] = [];\n\n\tfor (const dir of dirs) {\n\t\tconst dirPath = typeof dir === \"string\" ? dir : dir.path;\n\t\tconst namespace = typeof dir === \"string\" ? undefined : dir.namespace;\n\t\tconst resolvedDir = path.resolve(dirPath);\n\n\t\tif (!existsSync(resolvedDir) || !statSync(resolvedDir).isDirectory()) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (namespace) {\n\t\t\t// Flat DX structure: <dir>/<componentName>/<componentName>.js\n\t\t\tfor (const name of readdirSync(resolvedDir)) {\n\t\t\t\tconst fullPath = path.join(resolvedDir, name);\n\t\t\t\tif (!statSync(fullPath).isDirectory()) continue;\n\n\t\t\t\tconst entryPath = path.join(fullPath, `${name}.js`);\n\t\t\t\tif (existsSync(entryPath)) {\n\t\t\t\t\tmodules.push({\n\t\t\t\t\t\tname: `${namespace}/${name}`,\n\t\t\t\t\t\tpath: path.resolve(entryPath),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Standard structure: <dir>/<namespace>/<componentName>/<componentName>.js\n\t\t\tfor (const ns of readdirSync(resolvedDir)) {\n\t\t\t\tconst nsDir = path.join(resolvedDir, ns);\n\t\t\t\tif (!statSync(nsDir).isDirectory()) continue;\n\n\t\t\t\tfor (const name of readdirSync(nsDir)) {\n\t\t\t\t\tconst fullPath = path.join(nsDir, name);\n\t\t\t\t\tif (!statSync(fullPath).isDirectory()) continue;\n\n\t\t\t\t\tconst entryPath = path.join(fullPath, `${name}.js`);\n\t\t\t\t\tif (existsSync(entryPath)) {\n\t\t\t\t\t\tmodules.push({\n\t\t\t\t\t\t\tname: `${ns}/${name}`,\n\t\t\t\t\t\t\tpath: path.resolve(entryPath),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn modules;\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { Plugin } from \"vite\";\nimport type { LightningNpmOptions } from \"../types\";\n\nfunction resolveJsFromRoot(root: string, sub: string): string | null {\n\tconst segments = sub.split(\"/\");\n\tconst leaf = segments[segments.length - 1];\n\tconst nested = path.join(root, ...segments, `${leaf}.js`);\n\tif (existsSync(nested)) return nested;\n\tconst flat = path.join(root, `${sub}.js`);\n\tif (existsSync(flat)) return flat;\n\treturn null;\n}\n\nfunction resolveCssFromRoot(root: string, sub: string): string | null {\n\tconst segments = sub.split(\"/\");\n\tconst leaf = segments[segments.length - 1];\n\tconst nested = path.join(root, ...segments, `${leaf}.css`);\n\treturn existsSync(nested) ? nested : null;\n}\n\nexport function lightningNpm({ npmRoot, overrideDirs = [] }: LightningNpmOptions): Plugin {\n\treturn {\n\t\tname: \"vite-plugin-resolve-lightning-npm\",\n\t\tenforce: \"pre\",\n\n\t\tresolveId(importee) {\n\t\t\tif (!importee.startsWith(\"lightning/\")) return null;\n\n\t\t\tconst sub = importee.slice(\"lightning/\".length);\n\t\t\tconst segments = sub.split(\"/\");\n\t\t\tconst leaf = segments[segments.length - 1];\n\n\t\t\tfor (const dir of overrideDirs) {\n\t\t\t\tconst overridePath = path.join(dir, ...segments, `${leaf}.js`);\n\t\t\t\tif (existsSync(overridePath)) return null;\n\t\t\t}\n\n\t\t\tconst npmJs = resolveJsFromRoot(npmRoot, sub);\n\t\t\tif (npmJs) return npmJs;\n\n\t\t\tfor (const dir of overrideDirs) {\n\t\t\t\tconst cssFallback = path.join(dir, ...segments, `${leaf}.css`);\n\t\t\t\tif (existsSync(cssFallback)) return cssFallback;\n\t\t\t}\n\n\t\t\treturn resolveCssFromRoot(npmRoot, sub);\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 { Plugin } from \"vite\";\n\nexport interface LivePreviewOptions {\n\t/** Enable verbose logging */\n\tdebug?: boolean;\n}\n\n/**\n * Vite plugin that injects the Salesforce Live Preview bridge script into the\n * dev server's HTML so LWC UI Bundles work with the VSCode Live Preview\n * extension.\n *\n * The bridge (from `@salesforce/ui-bundle/proxy`) establishes a `postMessage`\n * channel from the previewed iframe to the VSCode webview: it forwards runtime\n * errors, unhandled rejections, network failures, and compile errors, plus\n * copy/paste, keyboard shortcuts, and a heartbeat. It is the same script the\n * React/generic `@salesforce/vite-plugin-ui-bundle` injects — sharing it keeps\n * the two dev-server paths behaviourally identical.\n *\n * Injection is **dev-only** (Vite `command === \"serve\"`). The compiled bundle\n * targets MCP hosts (ChatGPT, MCP Apps) and must never carry the dev bridge, so\n * the `transformIndexHtml` hook is a no-op during `vite build`.\n *\n * `@salesforce/ui-bundle` is an optional peer dependency; if it is not\n * installed the injection is skipped silently (a warning is logged only in\n * `debug` mode) and the dev server runs without Live Preview support.\n *\n * Included by default in `lwcVitePlugin()`. Available standalone for callers\n * who compose their own plugin array:\n * import { livePreview } from '@salesforce/vite-plugin-lwc-ui-bundle';\n * plugins: [livePreview(), lwcVitePlugin({ providers: [...] })]\n */\nexport function livePreview(options: LivePreviewOptions = {}): Plugin {\n\tlet isServe = false;\n\n\treturn {\n\t\tname: \"vite-plugin-lwc-live-preview\",\n\t\tenforce: \"pre\",\n\n\t\tconfigResolved(config) {\n\t\t\tisServe = config.command === \"serve\";\n\t\t},\n\n\t\ttransformIndexHtml: {\n\t\t\torder: \"pre\",\n\t\t\tasync handler(html) {\n\t\t\t\t// Only inject during local dev (`vite` / `vite dev`). Never during\n\t\t\t\t// `vite build` — the artifact ships to MCP hosts without the bridge.\n\t\t\t\tif (!isServe) return html;\n\n\t\t\t\ttry {\n\t\t\t\t\t// Dynamic import: @salesforce/ui-bundle is an OPTIONAL peer dep,\n\t\t\t\t\t// so a missing install must degrade gracefully, not hard-fail.\n\t\t\t\t\tconst { injectLivePreviewScript } = await import(\"@salesforce/ui-bundle/proxy\");\n\t\t\t\t\tconst injected = injectLivePreviewScript(html);\n\t\t\t\t\tif (options.debug) {\n\t\t\t\t\t\tconsole.log(\"[lwc-live-preview] Injected Live Preview bridge script\");\n\t\t\t\t\t}\n\t\t\t\t\treturn injected;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (options.debug) {\n\t\t\t\t\t\tconst msg = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`[lwc-live-preview] @salesforce/ui-bundle not available; skipping Live Preview injection.\\n ${msg}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn html;\n\t\t\t\t}\n\t\t\t},\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 { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { Plugin, ResolvedConfig } from \"vite\";\n\nexport function lwcBridge(isComponentAsset: (id: string) => boolean): Plugin {\n\treturn {\n\t\tname: \"vite-plugin-lwc-bridge\",\n\t\tenforce: \"pre\",\n\n\t\tconfigResolved(config: ResolvedConfig) {\n\t\t\tfor (const plugin of config.plugins) {\n\t\t\t\tif (plugin.name === \"vite:css\" || plugin.name === \"vite:css-post\") {\n\t\t\t\t\tconst p = plugin as unknown as Record<string, unknown>;\n\t\t\t\t\tconst origTransform = p[\"transform\"];\n\t\t\t\t\tif (!origTransform) continue;\n\n\t\t\t\t\tif (typeof origTransform === \"function\") {\n\t\t\t\t\t\t// Vite <7: transform is a plain function\n\t\t\t\t\t\tp[\"transform\"] = function (\n\t\t\t\t\t\t\tthis: unknown,\n\t\t\t\t\t\t\tcode: string,\n\t\t\t\t\t\t\tid: string,\n\t\t\t\t\t\t\t...rest: unknown[]\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tif (isComponentAsset(id)) return;\n\t\t\t\t\t\t\treturn (origTransform as (...a: unknown[]) => unknown).call(this, code, id, ...rest);\n\t\t\t\t\t\t};\n\t\t\t\t\t} else if (\n\t\t\t\t\t\ttypeof origTransform === \"object\" &&\n\t\t\t\t\t\ttypeof (origTransform as Record<string, unknown>)[\"handler\"] === \"function\"\n\t\t\t\t\t) {\n\t\t\t\t\t\t// Vite 7+: transform is { handler, order? }\n\t\t\t\t\t\tconst origHandler = (origTransform as Record<string, unknown>)[\"handler\"] as (\n\t\t\t\t\t\t\t...a: unknown[]\n\t\t\t\t\t\t) => unknown;\n\t\t\t\t\t\tp[\"transform\"] = {\n\t\t\t\t\t\t\t...(origTransform as object),\n\t\t\t\t\t\t\thandler: function (this: unknown, code: string, id: string, ...rest: unknown[]) {\n\t\t\t\t\t\t\t\tif (isComponentAsset(id)) return;\n\t\t\t\t\t\t\t\treturn origHandler.call(this, code, id, ...rest);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tresolveId(id, importer) {\n\t\t\tif (id.startsWith(\"@lwc/resources/\")) {\n\t\t\t\treturn id;\n\t\t\t}\n\n\t\t\tconst cleanId = id.split(\"?\", 2)[0] ?? id;\n\n\t\t\tif (cleanId.endsWith(\".html\") && isComponentAsset(cleanId) && !id.includes(\"?lwc\")) {\n\t\t\t\treturn `${cleanId}?lwc`;\n\t\t\t}\n\n\t\t\tif (!importer) return null;\n\t\t\tif (!cleanId.endsWith(\".html\")) return null;\n\t\t\tif (!cleanId.startsWith(\"./\") && !cleanId.startsWith(\"../\")) return null;\n\t\t\tif (!isComponentAsset(importer)) return null;\n\n\t\t\tconst resolved = path.resolve(path.dirname(importer.split(\"?\")[0] ?? importer), cleanId);\n\n\t\t\tif (existsSync(resolved)) {\n\t\t\t\treturn resolved + \"?lwc\";\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\n\t\tload(id) {\n\t\t\tif (id.startsWith(\"@lwc/resources/\")) {\n\t\t\t\treturn \"export default undefined;\";\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 { Plugin } from \"vite\";\n\ntype AnyFn = (this: unknown, ...args: unknown[]) => unknown;\ntype LwcRollupFactory = (options: Record<string, unknown>) => Plugin;\ntype LazyLwcRollupLoader = () => Promise<LwcRollupFactory>;\n\nexport function lwcWrapper(\n\tlazyLoader: LazyLwcRollupLoader,\n\toptions: Record<string, unknown>,\n\tisComponentAsset?: (id: string) => boolean,\n): Plugin {\n\tlet pluginPromise: Promise<Plugin> | null = null;\n\n\tconst getPlugin = () => {\n\t\tif (!pluginPromise) {\n\t\t\tpluginPromise = lazyLoader().then((factory) => factory(options));\n\t\t}\n\t\treturn pluginPromise;\n\t};\n\n\treturn {\n\t\tname: \"vite-plugin-lwc-wrapper\",\n\t\tenforce: \"pre\" as const,\n\t\tasync resolveId(importee: string, importer?: string) {\n\t\t\tif (importer?.split(\"?\")[0]?.endsWith(\"index.html\") && !importer.includes(\"html-proxy\"))\n\t\t\t\treturn null;\n\t\t\tif (importee.startsWith(\"/@\") || importee.startsWith(\"\\0\")) return null;\n\t\t\tif (importer?.includes(\"/node_modules/vite/\")) return null;\n\t\t\tconst plugin = await getPlugin();\n\t\t\treturn typeof plugin.resolveId === \"function\"\n\t\t\t\t? (plugin.resolveId as AnyFn).call(this, importee, importer)\n\t\t\t\t: null;\n\t\t},\n\t\tasync load(id: string) {\n\t\t\tconst plugin = await getPlugin();\n\t\t\treturn typeof plugin.load === \"function\" ? (plugin.load as AnyFn).call(this, id) : null;\n\t\t},\n\t\tasync transform(code: string, id: string) {\n\t\t\t// Only pass files to the LWC compiler if they are LWC component assets.\n\t\t\t// Non-component files (SDK sources, node_modules, etc.) must be skipped.\n\t\t\tif (isComponentAsset && !isComponentAsset(id)) return null;\n\t\t\tconst plugin = await getPlugin();\n\t\t\treturn typeof plugin.transform === \"function\"\n\t\t\t\t? (plugin.transform as AnyFn).call(this, code, id)\n\t\t\t\t: null;\n\t\t},\n\t} as Plugin;\n}\n","/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { Plugin } from \"vite\";\n\nconst LWC_EMPTY_CSS = \"\\0lwc-empty-css\";\n\nexport function missingCss(): Plugin {\n\treturn {\n\t\tname: \"vite-plugin-lwc-missing-css\",\n\t\tenforce: \"pre\",\n\n\t\tresolveId(id, importer) {\n\t\t\tif (!importer || !id.startsWith(\"./\") || !id.includes(\".css\")) return null;\n\t\t\tconst importerPath = importer.split(\"?\")[0] ?? importer;\n\t\t\tif (!importerPath.endsWith(\".html\")) return null;\n\n\t\t\tconst resolved = path.resolve(path.dirname(importerPath), id.split(\"?\")[0] ?? id);\n\t\t\tif (existsSync(resolved)) return null;\n\n\t\t\treturn `${LWC_EMPTY_CSS}?${id}`;\n\t\t},\n\n\t\tload(id) {\n\t\t\tif (id.startsWith(LWC_EMPTY_CSS)) {\n\t\t\t\treturn \"export default undefined\";\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 { Plugin } from \"vite\";\nimport type { Provider, ScopedProvidersOptions } from \"../types\";\n\nconst VIRTUAL_PREFIX = \"\\0sf-provider:\";\n\nexport function scopedProviders(\n\tproviders: Provider[] = [],\n\toptions: ScopedProvidersOptions = {},\n): Plugin {\n\tconst { ignorePatterns = [], interceptPrefixes = [], passthroughRules = [] } = options;\n\n\tconst prefixSet = new Set<string>();\n\tfor (const p of providers) {\n\t\tif (p.prefix) prefixSet.add(p.prefix);\n\t}\n\n\tfunction shouldIntercept(id: string): boolean {\n\t\tfor (const prefix of prefixSet) {\n\t\t\tif (id === prefix || id.startsWith(prefix)) return true;\n\t\t}\n\t\tfor (const prefix of interceptPrefixes) {\n\t\t\tif (id.startsWith(prefix)) return true;\n\t\t}\n\t\tfor (const p of providers) {\n\t\t\tif (!p.prefix && typeof p.match === \"function\" && p.match(id)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\treturn {\n\t\tname: \"vite-plugin-scoped-module-providers\",\n\t\tenforce: \"pre\",\n\n\t\tresolveId(id, importer) {\n\t\t\t// Explicit provider prefix always wins over ignorePatterns —\n\t\t\t// if a provider is registered for a specifier, it always handles it.\n\t\t\tconst handledByProvider = [...prefixSet].some((p) => id === p || id.startsWith(p + \"/\"));\n\n\t\t\tif (!handledByProvider) {\n\t\t\t\tif (!shouldIntercept(id)) return null;\n\n\t\t\t\tfor (const pattern of ignorePatterns) {\n\t\t\t\t\tif (id.startsWith(pattern)) return null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const rule of passthroughRules) {\n\t\t\t\tif (\n\t\t\t\t\timporter &&\n\t\t\t\t\tid.startsWith(rule.specifierPrefix) &&\n\t\t\t\t\timporter.includes(rule.importerPattern)\n\t\t\t\t) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn VIRTUAL_PREFIX + id;\n\t\t},\n\n\t\tload(id) {\n\t\t\tif (!id.startsWith(VIRTUAL_PREFIX)) return null;\n\n\t\t\tconst specifier = id.slice(VIRTUAL_PREFIX.length);\n\n\t\t\tfor (const provider of providers) {\n\t\t\t\tconst result = provider.resolve(specifier);\n\t\t\t\tif (result != null) return result;\n\t\t\t}\n\n\t\t\tconsole.warn(\n\t\t\t\t`[scoped-module-providers] Unhandled import: ${specifier} — returning undefined`,\n\t\t\t);\n\t\t\treturn `export default undefined;`;\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 * as http from \"node:http\";\nimport * as https from \"node:https\";\nimport type { Plugin } from \"vite\";\n\nexport interface LwcProxyOptions {\n\t/** Salesforce org alias (defaults to the sf CLI default org) */\n\torgAlias?: string;\n\t/** Enable verbose request logging */\n\tdebug?: boolean;\n}\n\n/**\n * Vite plugin that proxies Salesforce API calls to a connected org.\n *\n * Uses the same authentication approach as @salesforce/vite-plugin-ui-bundle —\n * reads credentials from the sf CLI via @salesforce/ui-bundle/app.\n *\n * Intercepts requests to /services/ and /lwr/ and forwards them to Salesforce\n * with the org's access token. Handles token refresh on 401/403 responses.\n *\n * Usage in vite.config.js:\n * import { lwcProxy } from '@salesforce/vite-plugin-lwc-ui-bundle';\n * plugins: [lwcVitePlugin(...), lwcProxy()]\n *\n * Then initialise the SDK in your app's bootstrap:\n * import { createDataSDK } from '@salesforce/platform-sdk';\n * globalThis.__sfdc_sdk__ = await createDataSDK({ uiBundle: { basePath: '/' } });\n */\nexport function lwcProxy(options: LwcProxyOptions = {}): Plugin {\n\tlet instanceUrl: string | undefined;\n\tlet accessToken: string | undefined;\n\tconst orgAlias: string | undefined = options.orgAlias;\n\n\tasync function loadOrgInfo(): Promise<void> {\n\t\ttry {\n\t\t\t// Dynamically import to avoid bundling @salesforce/ui-bundle at build time\n\t\t\tconst { getOrgInfo } = await import(\"@salesforce/ui-bundle/app\");\n\t\t\tconst info = await getOrgInfo(orgAlias);\n\t\t\tif (info) {\n\t\t\t\tinstanceUrl = info.rawInstanceUrl ?? info.instanceUrl;\n\t\t\t\taccessToken = info.accessToken;\n\t\t\t\tif (options.debug) {\n\t\t\t\t\tconsole.log(`[lwc-proxy] Connected to ${instanceUrl}`);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst msg = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.error(\n\t\t\t\t`[lwc-proxy] Failed to load org info — is a Salesforce org connected?\\n ${msg}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync function refreshToken(): Promise<void> {\n\t\ttry {\n\t\t\tconst { refreshOrgAuth } = await import(\"@salesforce/ui-bundle/app\");\n\t\t\tconst info = await refreshOrgAuth(orgAlias ?? \"\");\n\t\t\tif (info) {\n\t\t\t\tinstanceUrl = info.rawInstanceUrl ?? info.instanceUrl;\n\t\t\t\taccessToken = info.accessToken;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore refresh errors\n\t\t}\n\t}\n\n\treturn {\n\t\tname: \"vite-plugin-lwc-proxy\",\n\t\tenforce: \"pre\",\n\n\t\tasync configResolved() {\n\t\t\tawait loadOrgInfo();\n\t\t},\n\n\t\tconfigureServer(server) {\n\t\t\tserver.middlewares.use(async (req, res, next) => {\n\t\t\t\tconst url = req.url ?? \"\";\n\n\t\t\t\t// Only proxy Salesforce API paths\n\t\t\t\tif (!url.startsWith(\"/services/\") && !url.startsWith(\"/lwr/\")) {\n\t\t\t\t\treturn next();\n\t\t\t\t}\n\n\t\t\t\tif (!instanceUrl || !accessToken) {\n\t\t\t\t\tres.writeHead(503, { \"Content-Type\": \"application/json\" });\n\t\t\t\t\tres.end(\n\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\terror: \"SERVICE_UNAVAILABLE\",\n\t\t\t\t\t\t\tmessage: \"Salesforce org not connected. Run: sf org display\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst forward = async (token: string): Promise<void> => {\n\t\t\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t\t\tconst targetUrl = new URL(url, instanceUrl);\n\t\t\t\t\t\tconst isHttps = targetUrl.protocol === \"https:\";\n\t\t\t\t\t\tconst transport = isHttps ? https : http;\n\n\t\t\t\t\t\tif (options.debug) {\n\t\t\t\t\t\t\tconsole.log(`[lwc-proxy] ${req.method} ${url}`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Strip hop-by-hop headers\n\t\t\t\t\t\tconst headers: Record<string, string | string[]> = {};\n\t\t\t\t\t\tfor (const [key, value] of Object.entries(req.headers)) {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t![\n\t\t\t\t\t\t\t\t\t\"host\",\n\t\t\t\t\t\t\t\t\t\"connection\",\n\t\t\t\t\t\t\t\t\t\"keep-alive\",\n\t\t\t\t\t\t\t\t\t\"proxy-authenticate\",\n\t\t\t\t\t\t\t\t\t\"proxy-authorization\",\n\t\t\t\t\t\t\t\t\t\"te\",\n\t\t\t\t\t\t\t\t\t\"trailers\",\n\t\t\t\t\t\t\t\t\t\"transfer-encoding\",\n\t\t\t\t\t\t\t\t\t\"upgrade\",\n\t\t\t\t\t\t\t\t].includes(key.toLowerCase()) &&\n\t\t\t\t\t\t\t\tvalue !== undefined\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\theaders[key] = value as string | string[];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\theaders[\"host\"] = targetUrl.host;\n\t\t\t\t\t\theaders[\"authorization\"] = `Bearer ${token}`;\n\t\t\t\t\t\theaders[\"cookie\"] = `sid=${token}`;\n\n\t\t\t\t\t\tconst proxyReq = transport.request(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmethod: req.method,\n\t\t\t\t\t\t\t\thostname: targetUrl.hostname,\n\t\t\t\t\t\t\t\tport: targetUrl.port || (isHttps ? 443 : 80),\n\t\t\t\t\t\t\t\tpath: targetUrl.pathname + targetUrl.search,\n\t\t\t\t\t\t\t\theaders,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t(proxyRes) => {\n\t\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\t\tres.writeHead(proxyRes.statusCode ?? 200, proxyRes.headers);\n\t\t\t\t\t\t\t\tproxyRes.pipe(res);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\treq.pipe(proxyReq);\n\t\t\t\t\t\tproxyReq.on(\"error\", reject);\n\t\t\t\t\t});\n\t\t\t\t};\n\n\t\t\t\ttry {\n\t\t\t\t\tawait forward(accessToken!);\n\n\t\t\t\t\t// On 401/403, refresh token and retry once\n\t\t\t\t\t// Note: we can't easily check status here since we piped to res,\n\t\t\t\t\t// so we rely on the transform hook below for retries in future iterations\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (options.debug) {\n\t\t\t\t\t\tconsole.error(\"[lwc-proxy] Request failed:\", error);\n\t\t\t\t\t}\n\t\t\t\t\t// Try refreshing token and retry\n\t\t\t\t\tawait refreshToken();\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait forward(accessToken!);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tnext(err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\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 { createRequire } from \"node:module\";\nimport path from \"node:path\";\nimport type { Plugin } from \"vite\";\nimport { discoverModules } from \"./discovery\";\nimport { lightningNpm } from \"./plugins/lightning-npm\";\nimport { livePreview } from \"./plugins/live-preview\";\nimport { lwcBridge } from \"./plugins/lwc-bridge\";\nimport { lwcWrapper } from \"./plugins/lwc-wrapper\";\nimport { missingCss } from \"./plugins/missing-css\";\nimport { scopedProviders } from \"./plugins/scoped-providers\";\nimport * as builtinProviders from \"./providers/index\";\nimport type {\n\tDirConfig,\n\tLwcVitePluginOptions,\n\tNpmModuleConfig,\n\tPassthroughRule,\n\tProvider,\n} from \"./types\";\n\nexport type {\n\tProvider,\n\tLwcVitePluginOptions,\n\tPassthroughRule,\n\tDiscoveredModule,\n\tDirConfig,\n} from \"./types\";\nexport { builtinProviders as builtins };\nexport { discoverModules } from \"./discovery\";\nexport { lwcProxy } from \"./plugins/proxy\";\nexport type { LwcProxyOptions } from \"./plugins/proxy\";\nexport { livePreview } from \"./plugins/live-preview\";\nexport type { LivePreviewOptions } from \"./plugins/live-preview\";\n\nfunction defaultProviders(): (Provider | Plugin)[] {\n\treturn [\n\t\tbuiltinProviders.label(),\n\t\tbuiltinProviders.i18n(),\n\t\tbuiltinProviders.accessCheck(),\n\t\tbuiltinProviders.apex(),\n\t\tbuiltinProviders.client(),\n\t\tbuiltinProviders.gate(),\n\t\tbuiltinProviders.messageChannel(),\n\t\tbuiltinProviders.messageService(),\n\t\tbuiltinProviders.navigation(),\n\t\tbuiltinProviders.primitiveUtils(),\n\t\tbuiltinProviders.lds(),\n\t];\n}\n\n/** Distinguishes a scoped-providers `Provider` from a raw Vite `Plugin`. */\nfunction isProvider(item: Provider | Plugin): item is Provider {\n\treturn typeof (item as Provider).resolve === \"function\";\n}\n\nasync function loadLwcRollup() {\n\ttry {\n\t\t// Use dynamic import to load ESM-only @lwc/rollup-plugin (peer dep, types not guaranteed)\n\t\tconst mod = await (import(\"@lwc/rollup-plugin\") as Promise<Record<string, unknown>>);\n\t\treturn (mod[\"default\"] ?? mod) as unknown as (options: Record<string, unknown>) => Plugin;\n\t} catch (error) {\n\t\tconst errMsg = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(\n\t\t\t\"@salesforce/vite-plugin-lwc-ui-bundle requires @lwc/rollup-plugin as a peer dependency. \" +\n\t\t\t\t\"Install it with: npm install -D @lwc/rollup-plugin\\n\" +\n\t\t\t\t`Debug: cwd=${process.cwd()}, error=${errMsg}`,\n\t\t);\n\t}\n}\n\nexport default function lwcVitePlugin(options: LwcVitePluginOptions = {}): Plugin[] {\n\tconst {\n\t\tmodules = {},\n\t\tproviders,\n\t\tstubs = {},\n\t\tlwcOptions = {},\n\t\tignorePatterns = [\n\t\t\t// Legacy @salesforce/sdk-* prefix — kept for external consumers still on the\n\t\t\t// pre-rename package names. The `@salesforce/platform-sdk-` prefix covers the\n\t\t\t// individual platform-sdk-* packages (still in place pending deprecation);\n\t\t\t// `@salesforce/platform-sdk` (no trailing dash) covers the consolidated package.\n\t\t\t\"@salesforce/sdk-\",\n\t\t\t\"@salesforce/platform-sdk-\",\n\t\t\t\"@salesforce/platform-sdk\",\n\t\t\t\"@salesforce/core\",\n\t\t\t\"@salesforce/vite-plugin-lwc-ui-bundle\",\n\t\t],\n\t\tpassthroughRules = [],\n\t\tbundle = true,\n\t} = options;\n\n\tconst resolvedItems = providers ?? defaultProviders();\n\tconst resolvedProviders = resolvedItems.filter(isProvider);\n\tconst rawPlugins = resolvedItems.filter((item): item is Plugin => !isProvider(item));\n\n\tconst { dirs = [], npm: npmPackages = [] } = modules;\n\n\tconst resolvedDirs: DirConfig[] = dirs.map((d) =>\n\t\ttypeof d === \"string\"\n\t\t\t? { path: path.resolve(d), namespace: \"\" }\n\t\t\t: { ...d, path: path.resolve(d.path) },\n\t);\n\n\tconst npmConfigs: NpmModuleConfig[] = npmPackages.map((pkg) =>\n\t\ttypeof pkg === \"string\" ? { npm: pkg } : pkg,\n\t);\n\n\tconst require = createRequire(import.meta.url);\n\tconst npmRoots = npmConfigs.map((cfg) => {\n\t\tconst pkgJson = require.resolve(`${cfg.npm}/package.json`);\n\t\treturn path.join(path.dirname(pkgJson), \"src\", \"lightning\");\n\t});\n\n\tconst discoveredModules = discoverModules(dirs);\n\n\tconst lwcModules = [...npmConfigs, ...discoveredModules];\n\n\tconst lightningOverrideDirs = resolvedDirs.map((d) => path.join(d.path, \"lightning\"));\n\n\tfunction isComponentAsset(id: string): boolean {\n\t\tconst clean = id.split(\"?\")[0] ?? id;\n\t\tfor (const dir of resolvedDirs) {\n\t\t\tif (clean.includes(dir.path)) return true;\n\t\t}\n\t\tfor (const cfg of npmConfigs) {\n\t\t\tif (clean.includes(cfg.npm)) return true;\n\t\t}\n\t\treturn clean.includes(\"@lwc/\") || clean.startsWith(\"\\0lwc-empty-css\");\n\t}\n\n\tconst stubAliases: Record<string, string> = {};\n\tfor (const [specifier, stubPath] of Object.entries(stubs)) {\n\t\tstubAliases[specifier] = path.resolve(stubPath);\n\t}\n\n\tconst interceptPrefixes = new Set<string>();\n\tfor (const p of resolvedProviders) {\n\t\tif (p.prefix && p.prefix.startsWith(\"@\")) {\n\t\t\tinterceptPrefixes.add(p.prefix.split(\"/\")[0] + \"/\");\n\t\t}\n\t}\n\n\t// Plugin-style providers (e.g. lds()) can contribute passthroughRules so\n\t// imports made from inside their virtual modules reach the real npm\n\t// package instead of being claimed by scopedProviders' broad\n\t// `@salesforce/` interceptPrefix.\n\tconst pluginPassthroughRules = rawPlugins.flatMap(\n\t\t(p) => (p as { passthroughRules?: PassthroughRule[] }).passthroughRules ?? [],\n\t);\n\n\tconst plugins: Plugin[] = [\n\t\t// Dev-only: injects the Live Preview bridge into index.html so LWC UI\n\t\t// Bundles work with the VSCode Live Preview extension. No-op during\n\t\t// `vite build`; degrades silently if @salesforce/ui-bundle is absent.\n\t\tlivePreview(),\n\t\t{\n\t\t\tname: \"vite-plugin-lwc-optimize-deps\",\n\t\t\tconfig() {\n\t\t\t\treturn {\n\t\t\t\t\toptimizeDeps: {\n\t\t\t\t\t\texclude: [\"lwc\"],\n\t\t\t\t\t\tesbuildOptions: {\n\t\t\t\t\t\t\tplugins: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: \"lwc-html-stub\",\n\t\t\t\t\t\t\t\t\tsetup(build: {\n\t\t\t\t\t\t\t\t\t\tonResolve: (\n\t\t\t\t\t\t\t\t\t\t\toptions: { filter: RegExp },\n\t\t\t\t\t\t\t\t\t\t\tcallback: (args: { path: string }) => {\n\t\t\t\t\t\t\t\t\t\t\t\tpath: string;\n\t\t\t\t\t\t\t\t\t\t\t\texternal: boolean;\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t) => void;\n\t\t\t\t\t\t\t\t\t}) {\n\t\t\t\t\t\t\t\t\t\t// esbuild cannot process LWC HTML templates (?lwc suffix).\n\t\t\t\t\t\t\t\t\t\t// Mark them as external so Vite's own plugin handles them.\n\t\t\t\t\t\t\t\t\t\tbuild.onResolve({ filter: /\\.html/ }, (args: { path: string }) => ({\n\t\t\t\t\t\t\t\t\t\t\tpath: args.path,\n\t\t\t\t\t\t\t\t\t\t\texternal: true,\n\t\t\t\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t\t// plugins returned by plugin-style builtins (e.g. lds())\n\t\t...rawPlugins,\n\t\tscopedProviders(resolvedProviders, {\n\t\t\tignorePatterns,\n\t\t\tinterceptPrefixes: [...interceptPrefixes],\n\t\t\tpassthroughRules: [...passthroughRules, ...pluginPassthroughRules],\n\t\t}),\n\n\t\t...npmRoots.map((npmRoot) =>\n\t\t\tlightningNpm({\n\t\t\t\tnpmRoot,\n\t\t\t\toverrideDirs: lightningOverrideDirs,\n\t\t\t}),\n\t\t),\n\n\t\tmissingCss(),\n\t\tlwcBridge(isComponentAsset),\n\t\tlwcWrapper(\n\t\t\tloadLwcRollup,\n\t\t\t{\n\t\t\t\trootDir: process.cwd(),\n\t\t\t\t...lwcOptions,\n\t\t\t\tmodules: lwcModules,\n\t\t\t\texclude: [\n\t\t\t\t\t\"**/index.html\",\n\t\t\t\t\t\"**/node_modules/vite/**\",\n\t\t\t\t\t\"**/node_modules/.vite/**\",\n\t\t\t\t\t...((lwcOptions.exclude as string[]) || []),\n\t\t\t\t],\n\t\t\t},\n\t\t\tisComponentAsset,\n\t\t),\n\t];\n\n\tif (Object.keys(stubAliases).length > 0) {\n\t\tplugins.push({\n\t\t\tname: \"vite-plugin-lwc-stubs\",\n\t\t\tenforce: \"pre\",\n\t\t\tconfig() {\n\t\t\t\treturn {\n\t\t\t\t\tresolve: {\n\t\t\t\t\t\talias: stubAliases,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t});\n\t}\n\n\tif (!bundle) {\n\t\tplugins.push({\n\t\t\tname: \"vite-plugin-lwc-output-multifile\",\n\t\t\tenforce: \"pre\",\n\t\t\tconfig() {\n\t\t\t\treturn {\n\t\t\t\t\tbuild: {\n\t\t\t\t\t\toutDir: \"dist\",\n\t\t\t\t\t\tassetsDir: \".\",\n\t\t\t\t\t\tcssCodeSplit: true,\n\t\t\t\t\t\trollupOptions: {\n\t\t\t\t\t\t\toutput: {\n\t\t\t\t\t\t\t\tentryFileNames: \"js/[name]-[hash].js\",\n\t\t\t\t\t\t\t\tchunkFileNames: \"js/[name]-[hash].js\",\n\t\t\t\t\t\t\t\tassetFileNames(info: { names?: string[]; name?: string }) {\n\t\t\t\t\t\t\t\t\tconst name = info.names?.[0] ?? info.name ?? \"\";\n\t\t\t\t\t\t\t\t\tif (name.endsWith(\".css\")) return \"css/[name]-[hash].css\";\n\t\t\t\t\t\t\t\t\treturn \"assets/[name]-[hash][extname]\";\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t});\n\t}\n\n\treturn plugins;\n}\n"],"names":["builtinProviders.label","builtinProviders.i18n","builtinProviders.accessCheck","builtinProviders.apex","builtinProviders.client","builtinProviders.gate","builtinProviders.messageChannel","builtinProviders.messageService","builtinProviders.navigation","builtinProviders.primitiveUtils","builtinProviders.lds","require"],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { Plugin } from 'vite';
2
+ export interface LivePreviewOptions {
3
+ /** Enable verbose logging */
4
+ debug?: boolean;
5
+ }
6
+ /**
7
+ * Vite plugin that injects the Salesforce Live Preview bridge script into the
8
+ * dev server's HTML so LWC UI Bundles work with the VSCode Live Preview
9
+ * extension.
10
+ *
11
+ * The bridge (from `@salesforce/ui-bundle/proxy`) establishes a `postMessage`
12
+ * channel from the previewed iframe to the VSCode webview: it forwards runtime
13
+ * errors, unhandled rejections, network failures, and compile errors, plus
14
+ * copy/paste, keyboard shortcuts, and a heartbeat. It is the same script the
15
+ * React/generic `@salesforce/vite-plugin-ui-bundle` injects — sharing it keeps
16
+ * the two dev-server paths behaviourally identical.
17
+ *
18
+ * Injection is **dev-only** (Vite `command === "serve"`). The compiled bundle
19
+ * targets MCP hosts (ChatGPT, MCP Apps) and must never carry the dev bridge, so
20
+ * the `transformIndexHtml` hook is a no-op during `vite build`.
21
+ *
22
+ * `@salesforce/ui-bundle` is an optional peer dependency; if it is not
23
+ * installed the injection is skipped silently (a warning is logged only in
24
+ * `debug` mode) and the dev server runs without Live Preview support.
25
+ *
26
+ * Included by default in `lwcVitePlugin()`. Available standalone for callers
27
+ * who compose their own plugin array:
28
+ * import { livePreview } from '@salesforce/vite-plugin-lwc-ui-bundle';
29
+ * plugins: [livePreview(), lwcVitePlugin({ providers: [...] })]
30
+ */
31
+ export declare function livePreview(options?: LivePreviewOptions): Plugin;
32
+ //# sourceMappingURL=live-preview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-preview.d.ts","sourceRoot":"","sources":["../../src/plugins/live-preview.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,MAAM,WAAW,kBAAkB;IAClC,6BAA6B;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,MAAM,CAuCpE"}
@@ -433,6 +433,25 @@ npm run preview
433
433
  # Open http://localhost:4173
434
434
  ```
435
435
 
436
+ #### Live Preview & HMR (local dev)
437
+
438
+ The dev server (`npm run dev` / `vite`) gives you two local-dev conveniences out
439
+ of the box — no extra config:
440
+
441
+ - **VSCode Live Preview** — `lwcVitePlugin()` includes a `livePreview()` plugin
442
+ by default that injects the Salesforce Live Preview bridge into the served
443
+ `index.html` (dev only — never in `vite build`). Open the served URL in the
444
+ VSCode Live Preview extension and runtime/compile errors surface in the editor
445
+ panel. If the optional `@salesforce/ui-bundle` peer is not installed, injection
446
+ is skipped silently and the dev server still runs.
447
+ - **Hot Module Replacement** — editing a component's `.js`/`.html`/`.css` and
448
+ saving triggers Vite's watcher, which pushes a reload frame to the browser in
449
+ ~1s. No rebuild, no redeploy.
450
+
451
+ For API access against a real org during local dev, and for the full
452
+ verification matrix behind these features, see
453
+ [Live Preview & HMR verification](live-preview-hmr-verification.md).
454
+
436
455
  ### Step 6: Validate via MCP Server (optional)
437
456
 
438
457
  Once `dist/index.html` builds clean, you can validate the compiled bundle end-to-end by serving it through agentic-api-service and exercising it from MCP Inspector / MCP Jam / ChatGPT — closer to production than the local mock path. The `test-mcp-server` skill bundled with this plugin walks through the setup interactively (sfdc-bazel checkout, OrgFarm or Falcon test org, OAuth token generation, swapping your bundle into a UI-resource path, and connecting a test client).
@@ -508,6 +527,7 @@ import "@salesforce-ux/design-system/assets/styles/salesforce-lightning-design-s
508
527
 
509
528
  ## Reference
510
529
 
530
+ - **Live Preview & HMR verification:** [live-preview-hmr-verification.md](live-preview-hmr-verification.md) — how local dev (Live Preview, HMR, dev-gateway) works and is verified
511
531
  - **npm:** https://www.npmjs.com/package/@salesforce/vite-plugin-lwc-ui-bundle
512
532
  - **Source:** https://github.com/salesforce-experience-platform-emu/webapps/tree/main/packages/vite-plugin-lwc-ui-bundle
513
533
  - **User Guide:** https://github.com/salesforce-experience-platform-emu/webapps/blob/main/packages/vite-plugin-lwc-ui-bundle/docs/user-guide.md
@@ -0,0 +1,205 @@
1
+ # Live Preview & HMR Verification — LWC UI Bundles (W-22167046)
2
+
3
+ This runbook is the authoritative record of **how each acceptance criterion for
4
+ local development of LWC UI Bundles is verified** — both by the automated test
5
+ suite in this package and by a manual walkthrough against a real org.
6
+
7
+ > **TL;DR** — Local dev for an LWC UI Bundle is `vite` (dev server) with two
8
+ > dev-only plugins wired in:
9
+ >
10
+ > - `livePreview()` — injects the VSCode Live Preview bridge into the served
11
+ > HTML (included by default in `lwcVitePlugin()`).
12
+ > - `lwcProxy()` — a dev-gateway that forwards `/services/*` and `/lwr/*` to your
13
+ > connected org with real auth (add it alongside `lwcVitePlugin()`).
14
+ >
15
+ > HMR is Vite's own file-watch → WebSocket push; an LWC component edit produces a
16
+ > `full-reload` frame with no rebuild and no org redeploy.
17
+
18
+ ---
19
+
20
+ ## The local-dev architecture
21
+
22
+ A React/generic UI Bundle uses `@salesforce/vite-plugin-ui-bundle`, which owns a
23
+ full dev server (live-preview injection + proxy + HMR). An **LWC** UI Bundle uses
24
+ `@salesforce/vite-plugin-lwc-ui-bundle`, which is focused on LWC compilation. The
25
+ dev-loop capabilities are provided by two composable plugins in this package:
26
+
27
+ | Capability | Provided by | Default? |
28
+ | ---------------------------------- | --------------------------------------- | -------- |
29
+ | LWC compilation (`.js/.html/.css`) | `lwcVitePlugin()` core plugins | yes |
30
+ | Live Preview bridge injection | `livePreview()` | **yes** |
31
+ | Dev-gateway (org auth passthrough) | `lwcProxy()` | no¹ |
32
+ | HMR / file-watch reload | Vite core (no custom `handleHotUpdate`) | yes |
33
+
34
+ ¹ `lwcProxy()` is opt-in because it requires a connected `sf` CLI org and the
35
+ `@salesforce/ui-bundle` optional peer dep. Add it explicitly:
36
+
37
+ ```js
38
+ // vite.config.js
39
+ import { defineConfig } from "vite";
40
+ import lwcVitePlugin, { lwcProxy } from "@salesforce/vite-plugin-lwc-ui-bundle";
41
+
42
+ export default defineConfig({
43
+ plugins: [
44
+ lwcVitePlugin({ modules: { dirs: ["src/modules"] } }), // includes livePreview()
45
+ lwcProxy(), // dev-gateway to the connected org
46
+ ],
47
+ });
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Acceptance criteria → verification
53
+
54
+ ### AC1 — Live Preview VSCode extension works with LWC bundles
55
+
56
+ **How it works.** `livePreview()` registers a `transformIndexHtml` hook
57
+ (`order: "pre"`) that, on the dev server only (`command === "serve"`), calls
58
+ `injectLivePreviewScript()` from `@salesforce/ui-bundle/proxy`. That injects the
59
+ same `<script data-live-preview>` bridge the React path uses — establishing the
60
+ `postMessage` channel to the VSCode webview (runtime errors, network failures,
61
+ compile errors, copy/paste, keyboard shortcuts, heartbeat). It is a **no-op
62
+ during `vite build`**, so the shipped MCP-host artifact never carries the bridge.
63
+ `@salesforce/ui-bundle` is an optional peer dep, so a missing install degrades
64
+ silently (dev server still serves, just without the bridge).
65
+
66
+ **Automated verification.**
67
+
68
+ - `tests/live-preview.test.ts` (8 tests) — injects on `serve`; does **not**
69
+ inject on `build`; no-op before `configResolved`; idempotent (no
70
+ double-inject); graceful degradation when `@salesforce/ui-bundle/proxy` throws;
71
+ present in the default `lwcVitePlugin()` array.
72
+ - `tests/dev-server.e2e.test.ts` › "injects the Live Preview bridge into served
73
+ HTML" — boots a **real** Vite dev server, fetches `/`, and asserts the
74
+ `data-live-preview` marker is present alongside `/@vite/client` (proving it's
75
+ the genuine dev pipeline, not a mock).
76
+
77
+ **Manual verification.**
78
+
79
+ 1. `npm run dev` (or `vite`) in the consumer project.
80
+ 2. In VSCode, open the Live Preview extension on the served URL.
81
+ 3. Introduce a runtime error in a component; confirm it surfaces in the VSCode
82
+ Live Preview panel (bridge is live).
83
+ 4. `View Source` on the served page → `<script data-live-preview>` is present.
84
+ 5. `vite build` → open `dist/index.html` → the bridge is **absent**.
85
+
86
+ ### AC2 — Hot Module Replacement (HMR) functions correctly
87
+
88
+ **How it works.** The LWC plugin does not override `handleHotUpdate`, so Vite's
89
+ default HMR applies. Editing an LWC module the dev server is tracking triggers
90
+ Vite's file watcher, which pushes an HMR frame (a `full-reload` for LWC
91
+ component graphs) over the HMR WebSocket to every connected client.
92
+
93
+ **Automated verification.**
94
+
95
+ - `tests/dev-server.e2e.test.ts` › "pushes an HMR reload frame when a served
96
+ module is edited" — boots a real Vite dev server, connects a `vite-hmr`
97
+ WebSocket client, warms the module graph, edits a served module on disk, and
98
+ asserts a `full-reload`/`update` frame arrives over the socket.
99
+
100
+ > **Determinism note.** The test uses `usePolling` watch + `realpathSync` on
101
+ > the temp dir (macOS `/tmp` and `/var/folders` are symlinks; a path mismatch
102
+ > silently drops watch events) and waits ~250ms after `connected` before
103
+ > editing — the polling watcher needs a beat to record its baseline stat of the
104
+ > file _after_ the warm request pulls it into the module graph. Editing the
105
+ > instant `connected` arrives races that baseline and the change is missed.
106
+ > This was root-caused from a flaky run; the fixed test is green 20/20.
107
+
108
+ **Manual verification.**
109
+
110
+ 1. `vite` dev server running, page open in a browser.
111
+ 2. Edit a component `.js`/`.html`/`.css` and save.
112
+ 3. The browser reloads within ~1s reflecting the change; the DevTools Network
113
+ tab shows the HMR WebSocket frame, not a full page navigation you triggered.
114
+
115
+ ### AC3 — Local dev-gateway handles Salesforce authentication
116
+
117
+ **How it works.** `lwcProxy()` reads org credentials from the `sf` CLI via
118
+ `getOrgInfo()` (from `@salesforce/ui-bundle/app`) at `configResolved`. Its
119
+ `configureServer` middleware intercepts `/services/*` and `/lwr/*`, rewrites the
120
+ `host` header to the org, strips hop-by-hop headers, and forwards with
121
+ `Authorization: Bearer <token>` + `Cookie: sid=<token>`. On a transport failure
122
+ it calls `refreshOrgAuth()` and retries once with the fresh token. With no org
123
+ connected it returns `503 SERVICE_UNAVAILABLE`.
124
+
125
+ **Automated verification.**
126
+
127
+ - `tests/proxy.test.ts` (10 tests) — boots the middleware behind a **real
128
+ loopback HTTP server** with a stand-in org server, and asserts:
129
+ - `/services/*` forwarded with `Bearer` + `sid` auth and rewritten `host`.
130
+ - `/lwr/*` forwarded likewise.
131
+ - Hop-by-hop headers (`proxy-authorization`) stripped; app headers preserved.
132
+ - Non-API paths pass through to `next()` (not proxied).
133
+ - `503` for API paths when no org is connected.
134
+ - Transport failure → `refreshOrgAuth()` → retry carries the **fresh** token.
135
+ - Retry-also-fails surfaces the error via `next(err)`.
136
+
137
+ **Manual verification.**
138
+
139
+ 1. `sf org login web` (or `sf org display` to confirm a default org).
140
+ 2. `vite` with `lwcProxy()` in the plugin array.
141
+ 3. `curl http://localhost:<port>/services/data/v65.0/limits` → real org JSON,
142
+ authenticated with your session (no manual token handling).
143
+ 4. `sf org logout` → same request returns `503`.
144
+
145
+ ### AC4 — Real-time updates without full redeployment
146
+
147
+ Same mechanism as AC2: an on-disk file save drives the update. There is **no
148
+ `vite build`, no `sf project deploy`, no org round-trip** in the edit→see loop —
149
+ the dev server recompiles the changed module and pushes the frame.
150
+
151
+ **Automated verification.** Covered by the AC2 e2e test: the reload frame is
152
+ produced by a plain `writeFileSync` to the module — the assertion explicitly
153
+ represents "a plain file save, no build step, no org deploy."
154
+
155
+ **Manual verification.** During AC2's manual step, confirm you never ran a build
156
+ or deploy command between the edit and the browser update.
157
+
158
+ ### AC5 — API access against real org data works locally
159
+
160
+ `lwcProxy()` (AC3) is what makes real org data reachable from the locally-served
161
+ bundle: the app's Data SDK (`createDataSDK({ uiBundle: { basePath: "/" } })`)
162
+ issues `/services/data/.../graphql` and REST calls that the gateway forwards to
163
+ the org.
164
+
165
+ **Automated verification.**
166
+
167
+ - `tests/proxy.test.ts` › "streams a POST body (e.g. GraphQL) through to the
168
+ org" — a UI-API GraphQL POST body is streamed intact to the org server and the
169
+ 200 response flows back.
170
+
171
+ **Manual verification.**
172
+
173
+ 1. In a component, use a wire/imperative call or a `createDataSDK` GraphQL query
174
+ against a real object (e.g. `Account`).
175
+ 2. With `lwcProxy()` + a connected org, load the page → real records render.
176
+ 3. Network tab shows `/services/data/v65.0/graphql` returning org data.
177
+
178
+ ---
179
+
180
+ ## Running the verification suite
181
+
182
+ ```bash
183
+ # From repo root — all LWC-plugin tests (unit + e2e), Nx-cached:
184
+ npx lerna run test --scope @salesforce/vite-plugin-lwc-ui-bundle
185
+
186
+ # Just the local-dev tests:
187
+ cd packages/vite-plugin-lwc-ui-bundle
188
+ npx vitest run tests/live-preview.test.ts tests/proxy.test.ts tests/dev-server.e2e.test.ts
189
+ ```
190
+
191
+ The e2e file boots real Vite dev servers and opens HMR WebSockets, so it declares
192
+ `ws` as a devDependency and carries generous per-test timeouts; servers are torn
193
+ down in `afterEach`.
194
+
195
+ ---
196
+
197
+ ## Summary matrix
198
+
199
+ | AC | Capability | Automated coverage | Manual check |
200
+ | --- | ----------------------------- | -------------------------------------------------------- | ----------------------------------- |
201
+ | AC1 | Live Preview bridge injection | `live-preview.test.ts` (8), `dev-server.e2e` inject test | VSCode Live Preview + View Source |
202
+ | AC2 | HMR functions | `dev-server.e2e` reload-frame test | Edit component → browser reloads |
203
+ | AC3 | Dev-gateway auth | `proxy.test.ts` (10) | `curl /services/data/...` + logout |
204
+ | AC4 | Updates without redeploy | `dev-server.e2e` reload-frame test (plain file save) | No build/deploy in edit loop |
205
+ | AC5 | Real org API access | `proxy.test.ts` GraphQL-POST stream test | Wire/SDK query renders real records |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/vite-plugin-lwc-ui-bundle",
3
- "version": "11.11.0",
3
+ "version": "11.12.0",
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",
@@ -74,9 +74,9 @@
74
74
  },
75
75
  "peerDependencies": {
76
76
  "@lwc/rollup-plugin": "^9.0.0",
77
- "@salesforce/platform-sdk": "^11.11.0",
77
+ "@salesforce/platform-sdk": "^11.12.0",
78
78
  "@salesforce/state-managers-uiapi": "^0.31.0",
79
- "@salesforce/ui-bundle": "^11.11.0",
79
+ "@salesforce/ui-bundle": "^11.12.0",
80
80
  "lwc": "^9.0.0",
81
81
  "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0",
82
82
  "zod": "^3.23.8"
@@ -100,11 +100,13 @@
100
100
  "devDependencies": {
101
101
  "@conduit-client/bindings-utils": "3.19.6",
102
102
  "@conduit-client/command-base": "3.19.6",
103
- "@salesforce/platform-sdk": "^11.11.0",
103
+ "@salesforce/platform-sdk": "^11.12.0",
104
+ "@types/ws": "^8.5.12",
104
105
  "typescript": "^5.9.3",
105
106
  "vite": "^7.0.0",
106
107
  "vite-plugin-dts": "^4.5.4",
107
108
  "vitest": "^4.0.6",
109
+ "ws": "^8.19.0",
108
110
  "zod": "^3.23.8"
109
111
  },
110
112
  "engines": {
@@ -652,6 +652,14 @@ Open `http://localhost:5173` and confirm:
652
652
  - If no mocks were generated, chat wrappers show "Waiting for tool
653
653
  output..." and `@wire` adapters return no data. That's expected; the
654
654
  bundle will work once deployed to a real MCP server.
655
+ - **HMR:** edit a component `.js`/`.html`/`.css` and save — the browser
656
+ reloads in ~1s with the change, no rebuild or redeploy.
657
+ - **VSCode Live Preview:** `lwcVitePlugin()` injects the Live Preview
658
+ bridge into the dev-served HTML by default (dev only — never in
659
+ `vite build`), so opening the served URL in the VSCode Live Preview
660
+ extension surfaces runtime/compile errors in the editor. If the
661
+ optional `@salesforce/ui-bundle` peer isn't installed, the bridge is
662
+ skipped silently and the dev server still runs (see pitfall #16).
655
663
 
656
664
  If something renders wrong, check `references/known-pitfalls.md`. The
657
665
  most common dev-time issues are graphql wire adapters returning empty
@@ -411,3 +411,32 @@ explicit re-trigger (`setConfig` / `refresh()`) at the mutation site,
411
411
  or a broadcast/event the dependent state managers listen for. The
412
412
  plugin cannot synthesize a Luvio store — that's a §11 Risk 1 contract
413
413
  baked into the off-core uplift.
414
+
415
+ ## 16. VSCode Live Preview bridge missing in the dev server
416
+
417
+ **Symptom:** The dev server (`npm run dev`) serves the page, but the
418
+ VSCode Live Preview extension shows no runtime/compile errors and the
419
+ served HTML has no `<script data-live-preview>` tag. Nothing crashes —
420
+ the bridge is just silently absent.
421
+
422
+ **Cause:** `lwcVitePlugin()` injects the Live Preview bridge via a
423
+ default `livePreview()` plugin that dynamically imports
424
+ `injectLivePreviewScript` from `@salesforce/ui-bundle/proxy`.
425
+ `@salesforce/ui-bundle` is an **optional** peer dependency; if it isn't
426
+ installed, the import fails and injection is skipped by design (so the
427
+ dev server still runs without it) rather than hard-failing. Injection is
428
+ also dev-only — it never runs during `vite build`, so `dist/index.html`
429
+ correctly never carries the bridge.
430
+
431
+ **Fix:** Install the optional peer in the consumer to enable the bridge:
432
+
433
+ ```bash
434
+ npm install -D @salesforce/ui-bundle
435
+ ```
436
+
437
+ Then restart `npm run dev` and confirm `<script data-live-preview>`
438
+ appears in the served page source. To see why it was skipped, construct
439
+ the plugin with `livePreview({ debug: true })` (or run with plugin debug
440
+ logging) — it logs the underlying import error. Note the bridge is a
441
+ local-dev convenience only; its absence never affects the compiled
442
+ bundle.