@oddsquad/vite-plugin-lit 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/README.md +30 -12
  3. package/bin.mjs +107 -5
  4. package/dist/client/assets/{browser-agent-rpc-BXhoSh1z-DXAVFObe.js → browser-agent-rpc-BXhoSh1z-BuCvPGjS.js} +3 -3
  5. package/dist/client/assets/{browser-agent-rpc-BXhoSh1z-DXAVFObe.js.map → browser-agent-rpc-BXhoSh1z-BuCvPGjS.js.map} +1 -1
  6. package/dist/client/assets/{index-DVr5EnyB.js → index-D632jo79.js} +45 -19
  7. package/dist/client/assets/index-D632jo79.js.map +1 -0
  8. package/dist/client/index.html +1 -1
  9. package/dist/standalone/lit-devtools.js +6820 -0
  10. package/lib/confine.d.ts +22 -0
  11. package/lib/confine.d.ts.map +1 -0
  12. package/lib/confine.js +39 -0
  13. package/lib/confine.js.map +1 -0
  14. package/lib/devframe/allowed-origins.d.ts +13 -0
  15. package/lib/devframe/allowed-origins.d.ts.map +1 -0
  16. package/lib/devframe/allowed-origins.js +63 -0
  17. package/lib/devframe/allowed-origins.js.map +1 -0
  18. package/lib/devframe/definition.d.ts +10 -2
  19. package/lib/devframe/definition.d.ts.map +1 -1
  20. package/lib/devframe/definition.js +31 -9
  21. package/lib/devframe/definition.js.map +1 -1
  22. package/lib/devframe/protocol.d.ts +7 -3
  23. package/lib/devframe/protocol.d.ts.map +1 -1
  24. package/lib/devframe/protocol.js.map +1 -1
  25. package/lib/devframe/vite.d.ts.map +1 -1
  26. package/lib/devframe/vite.js +3 -0
  27. package/lib/devframe/vite.js.map +1 -1
  28. package/lib/http.d.ts +5 -0
  29. package/lib/http.d.ts.map +1 -1
  30. package/lib/http.js +5 -0
  31. package/lib/http.js.map +1 -1
  32. package/lib/options.d.ts +26 -0
  33. package/lib/options.d.ts.map +1 -1
  34. package/lib/options.js +19 -0
  35. package/lib/options.js.map +1 -1
  36. package/lib/plugin.d.ts.map +1 -1
  37. package/lib/plugin.js +3 -0
  38. package/lib/plugin.js.map +1 -1
  39. package/lib/plugins/open-in-editor.d.ts.map +1 -1
  40. package/lib/plugins/open-in-editor.js +11 -19
  41. package/lib/plugins/open-in-editor.js.map +1 -1
  42. package/lib/plugins/private-fields.d.ts +27 -0
  43. package/lib/plugins/private-fields.d.ts.map +1 -0
  44. package/lib/plugins/private-fields.js +259 -0
  45. package/lib/plugins/private-fields.js.map +1 -0
  46. package/lib/runtime/child-state.d.ts +100 -0
  47. package/lib/runtime/child-state.d.ts.map +1 -0
  48. package/lib/runtime/child-state.js +446 -0
  49. package/lib/runtime/child-state.js.map +1 -0
  50. package/lib/runtime/inspector/install.js +4 -1
  51. package/lib/runtime/inspector/install.js.map +1 -1
  52. package/lib/runtime/patch.d.ts +24 -0
  53. package/lib/runtime/patch.d.ts.map +1 -1
  54. package/lib/runtime/patch.js +22 -1
  55. package/lib/runtime/patch.js.map +1 -1
  56. package/lib/runtime/rpc-transport.d.ts +8 -0
  57. package/lib/runtime/rpc-transport.d.ts.map +1 -1
  58. package/lib/runtime/rpc-transport.js +1 -0
  59. package/lib/runtime/rpc-transport.js.map +1 -1
  60. package/lib/runtime/source-overlay/editors.d.ts.map +1 -1
  61. package/lib/runtime/source-overlay/editors.js +9 -4
  62. package/lib/runtime/source-overlay/editors.js.map +1 -1
  63. package/lib/runtime/standalone.d.ts +27 -0
  64. package/lib/runtime/standalone.d.ts.map +1 -0
  65. package/lib/runtime/standalone.js +50 -0
  66. package/lib/runtime/standalone.js.map +1 -0
  67. package/lib/runtime/timeline/install.js +4 -2
  68. package/lib/runtime/timeline/install.js.map +1 -1
  69. package/lib/runtime/timeline/lifecycle.d.ts.map +1 -1
  70. package/lib/runtime/timeline/lifecycle.js +5 -1
  71. package/lib/runtime/timeline/lifecycle.js.map +1 -1
  72. package/lib/snapshot.d.ts +2 -1
  73. package/lib/snapshot.d.ts.map +1 -1
  74. package/lib/snapshot.js +17 -1
  75. package/lib/snapshot.js.map +1 -1
  76. package/lib/source-meta.d.ts.map +1 -1
  77. package/lib/source-meta.js +40 -1
  78. package/lib/source-meta.js.map +1 -1
  79. package/package.json +18 -14
  80. package/types/timeline.d.ts +4 -1
  81. package/types/timeline.d.ts.map +1 -1
  82. package/types/timeline.js.map +1 -1
  83. package/dist/client/assets/index-DVr5EnyB.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/lib/devframe/protocol.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;GAOG;AAEH,OAAO,EAAC,oBAAoB,EAAC,MAAM,yBAAyB,CAAC;AAkB7D,iFAAiF;AACjF,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AAErC,kEAAkE;AAClE,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,CAAC;AAE3C,uEAAuE;AACvE,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAEzC;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAE7C,oDAAoD;AACpD,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;AAEvC,gDAAgD;AAChD,MAAM,CAAC,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAErD,kDAAkD;AAClD,MAAM,CAAC,MAAM,qBAAqB,GAAG,mBAAmB,CAAC;AAEzD,8CAA8C;AAC9C,MAAM,CAAC,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,kBAAkB,CAAC;AAEvD,+CAA+C;AAC/C,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AAEnD,yCAAyC;AACzC,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AAErC,+CAA+C;AAC/C,MAAM,CAAC,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAEjD,8CAA8C;AAC9C,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAE/C,uDAAuD;AACvD,MAAM,CAAC,MAAM,yBAAyB,GAAG,uBAAuB,CAAC;AAEjE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC;AAqB7C,gEAAgE;AAChE,MAAM,CAAC,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAmBrD,wEAAwE;AACxE,MAAM,CAAC,MAAM,qBAAqB,GAAG,mBAAmB,CAAC;AAEzD,sDAAsD;AACtD,MAAM,CAAC,MAAM,yBAAyB,GAAG,uBAAuB,CAAC;AAEjE,uEAAuE;AACvE,MAAM,CAAC,MAAM,oBAAoB,GAAG,kBAAkB,CAAC;AAEvD;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC;AAEzC;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAkB/C,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IACjD,MAAM,EAAE,oBAAoB;IAC5B,YAAY,EAAE,EAAE;CACjB,CAAC;AAiFF;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GACtB;IACE,eAAe,EAAE,qBAAqB;IACtC,YAAY,EAAE,kBAAkB;IAChC,oBAAoB,EAAE,yBAAyB;IAC/C,KAAK,EAAE,mBAAmB;IAC1B,QAAQ,EAAE,sBAAsB;CACjC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Shared wire contract between the Lit devframe's node-side definition\n * ({@link ../definition.ts}) and its panel: shared-state / streaming /\n * RPC-function names, their payload shapes, and the `devframe` registry\n * augmentations that type them end to end.\n *\n * @see plans/devframe-foundation.md\n */\n\nimport {DEFAULT_LAYERS_STATE} from '../../types/timeline.js';\nimport type {\n FeatureSettings,\n OverrideBaselines,\n SettingsOverride,\n TimelineEvent,\n TimelineLayer,\n TimelineLayersState,\n} from '../../types/timeline.js';\nimport type {\n InspectorCommand,\n InspectorDetails,\n InspectorMessage,\n InspectorTreeNode,\n} from '../../types/inspector.js';\nimport type {HmrIncompatibilityEvent} from '../../types/hmr-incompatibility.js';\nimport type {ComponentRollup, UpdateCycle} from '../timeline/derive.js';\n\n/** The devframe's scope id. RPC names become `lit:*`, MCP wire names `lit_*`. */\nexport const LIT_DEVFRAME_ID = 'lit';\n\n/** Shared-state key holding the {@link SessionState} snapshot. */\nexport const SESSION_STATE_KEY = 'session';\n\n/** Streaming channel name the timeline event batches are pushed on. */\nexport const TIMELINE_STREAM_NAME = 'timeline';\n\n/**\n * Id of the one long-lived timeline stream. Fixed rather than discovered:\n * there is exactly one page feed per dev session, so the panel can subscribe\n * without a round trip to look the id up. The node side re-`start()`s this id\n * if the transport dropped the stream after the last subscriber left.\n */\nexport const TIMELINE_STREAM_ID = 'live';\n\n/**\n * Cap on the node-side recent-events ring buffer. It is also the history a\n * (re)connecting panel is seeded with (see {@link RPC_TIMELINE_HISTORY}).\n */\nexport const RECENT_EVENTS_BUFFER_SIZE = 512;\n\n/** Bare (unscoped) name of the `get-meta` query. */\nexport const RPC_GET_META = 'get-meta';\n\n/** Bare name of the `list-components` query. */\nexport const RPC_LIST_COMPONENTS = 'list-components';\n\n/** Bare name of the `component-details` query. */\nexport const RPC_COMPONENT_DETAILS = 'component-details';\n\n/** Bare name of the `recent-events` query. */\nexport const RPC_RECENT_EVENTS = 'recent-events';\n\n/**\n * Bare name of the `timeline-history` query: the node's whole recent-events\n * buffer, oldest first, as `TimelineEvent[]`. What a live panel seeds itself\n * with on connect, since the stream only carries events from then on. Not\n * `recent-events`, whose live answer is filtered and capped for agents.\n */\nexport const RPC_TIMELINE_HISTORY = 'timeline-history';\n\n/** Bare name of the `update-summary` query. */\nexport const RPC_UPDATE_SUMMARY = 'update-summary';\n\n/** Bare name of the `inspect` action. */\nexport const RPC_INSPECT = 'inspect';\n\n/** Bare name of the `set-recording` action. */\nexport const RPC_SET_RECORDING = 'set-recording';\n\n/** Bare name of the `toggle-layer` action. */\nexport const RPC_TOGGLE_LAYER = 'toggle-layer';\n\n/** Bare name of the `set-settings-override` action. */\nexport const RPC_SET_SETTINGS_OVERRIDE = 'set-settings-override';\n\n/** Bare name of the `open-source` action. */\nexport const RPC_OPEN_SOURCE = 'open-source';\n\n/** Arguments for {@link RPC_OPEN_SOURCE}. */\nexport interface OpenSourceArgs {\n /**\n * The path as the panel has it: what the transform injected, so relative\n * to the Vite root (or absolute, when the file lives outside it).\n */\n file: string;\n line?: number;\n}\n\n/** What {@link RPC_OPEN_SOURCE} reports back. */\nexport interface OpenSourceResult {\n /**\n * False when no open service is installed on the host, which is the\n * panel's cue to fall back to `/__lit-open-in-editor`.\n */\n opened: boolean;\n}\n\n/** Freeze the current session into a static panel directory. */\nexport const RPC_EXPORT_SNAPSHOT = 'export-snapshot';\n\n/** Arguments for {@link RPC_EXPORT_SNAPSHOT}. */\nexport interface ExportSnapshotArgs {\n /**\n * Where to write. Relative paths resolve against the dev server's cwd.\n * Defaults to `lit-devtools-snapshot`.\n */\n outDir?: string;\n}\n\n/** What {@link RPC_EXPORT_SNAPSHOT} reports back, for the panel to display. */\nexport interface ExportSnapshotResult {\n outDir: string;\n events: number;\n components: number;\n details: number;\n}\n\n/** Bare name of the `inspector-message` client (node → panel) event. */\nexport const RPC_INSPECTOR_MESSAGE = 'inspector-message';\n\n/** Bare name of the `hmr-incompatibilities` query. */\nexport const RPC_HMR_INCOMPATIBILITIES = 'hmr-incompatibilities';\n\n/** Bare name of the `hmr-incompatible` client (node → panel) event. */\nexport const RPC_HMR_INCOMPATIBLE = 'hmr-incompatible';\n\n/**\n * Bare name of the page-to-server event. A page runtime that is not on a Vite\n * dev server's HMR socket sends every channel message it would have sent over\n * `import.meta.hot` as `page-send(channel, data)`.\n */\nexport const RPC_PAGE_SEND = 'page-send';\n\n/**\n * Bare name of the server-to-page client event, the reverse direction of\n * {@link RPC_PAGE_SEND}: `page-receive(channel, data)`. Broadcast to every\n * connected client and marked optional, since the panel does not register it.\n */\nexport const RPC_PAGE_RECEIVE = 'page-receive';\n\n/**\n * Recording/layers snapshot shared between every surface (panel, page\n * runtime, MCP). Survives reconnect; mutated either by the `set-recording` /\n * `toggle-layer` actions below or directly by a panel through the generic\n * shared-state RPC devframe provides.\n *\n * `layers.recordingState` is the single authority for \"is recording\" — the\n * runtime's own layer state carries it, so a separate flag here would be a\n * second copy to keep in sync.\n */\nexport interface SessionState {\n layers: TimelineLayersState;\n /** Layers announced at runtime by app code through `addTimelineLayer()`. */\n customLayers: TimelineLayer[];\n}\n\nexport const DEFAULT_SESSION_STATE: SessionState = {\n layers: DEFAULT_LAYERS_STATE,\n customLayers: [],\n};\n\n/** Result of the `get-meta` query. */\nexport interface LitGetMetaResult {\n version: string;\n /** Built-in layers followed by any runtime-announced custom ones. */\n layers: TimelineLayer[];\n features: FeatureSettings | null;\n /** Channel and id to pass to `rpc.streaming.subscribe()`. */\n stream: {channel: string; id: string};\n}\n\n/** Argument of the `component-details` query. */\nexport interface ComponentDetailsArgs {\n id: number;\n}\n\n/** Argument of the `recent-events` query. */\nexport interface RecentEventsArgs {\n layerId?: string;\n elementId?: number;\n /**\n * Only events from the last `sinceMs` milliseconds, measured against\n * the newest event currently in the buffer — not wall-clock time.\n * `TimelineEvent.time` is \"ms since recording started\" in the page\n * (see `runtime/timeline/clock.ts`), which has no fixed relationship\n * to this process's clock.\n */\n sinceMs?: number;\n /** Default 50, hard ceiling 200 regardless of what's requested. */\n limit?: number;\n}\n\n/** Result of the `recent-events` query. */\nexport interface RecentEventsResult {\n /** Whether the timeline is currently recording. */\n recording: boolean;\n /** Most recent events matching the filters, oldest first. */\n events: TimelineEvent[];\n /** Total events currently held in the ring buffer, before filtering. */\n bufferSize: number;\n /** True if filtering matched more events than were returned. */\n truncated: boolean;\n}\n\n/** Argument of the `update-summary` query. */\nexport interface UpdateSummaryArgs {\n /** Restrict to one component, by tag name. */\n tagName?: string;\n /** Same window semantics as {@link RecentEventsArgs.sinceMs}. */\n sinceMs?: number;\n /** Cycles returned (the component totals always cover the whole window).\n * Default 50, hard ceiling 200. */\n limit?: number;\n}\n\n/** Result of the `update-summary` query. */\nexport interface UpdateSummaryResult {\n /** Whether the timeline is currently recording. */\n recording: boolean;\n /** Per-component totals over the window, slowest first. */\n components: ComponentRollup[];\n /** The most recent update cycles in the window, oldest first. */\n cycles: UpdateCycle[];\n /** Total events currently held in the ring buffer, before derivation. */\n bufferSize: number;\n /** True if more cycles were derived than were returned. */\n truncated: boolean;\n}\n\n/** Argument of the `set-recording` action. */\nexport interface SetRecordingArgs {\n recording: boolean;\n}\n\n/** Argument of the `toggle-layer` action. */\nexport interface ToggleLayerArgs {\n layerId: string;\n enabled: boolean;\n}\n\n/**\n * Maps a {@link TimelineLayer.id} to the {@link TimelineLayersState} flag\n * that gates it. Custom layers have no flag and are always on.\n */\nexport const LAYER_FLAGS: Readonly<Record<string, keyof TimelineLayersState>> =\n {\n 'lit-lifecycle': 'litLifecycleEnabled',\n 'lit-render': 'litRenderEnabled',\n 'lit-render-verbose': 'litRenderVerboseEnabled',\n mouse: 'mouseEventEnabled',\n keyboard: 'keyboardEventEnabled',\n };\n\n// Hand-typed rather than derived through `RpcDefinitionsToFunctionsWithNamespace`\n// (also exported by `devframe/rpc`): the definitions themselves live in\n// definition.ts next to their handlers, and hand-typing here avoids a\n// value-level dependency from this shared-contract module back onto it.\ndeclare module 'devframe' {\n interface DevframeRpcServerFunctions {\n 'lit:get-meta': () => Promise<LitGetMetaResult>;\n 'lit:list-components': () => Promise<InspectorTreeNode[]>;\n 'lit:component-details': (\n args: ComponentDetailsArgs\n ) => Promise<InspectorDetails | null>;\n 'lit:recent-events': (\n args?: RecentEventsArgs\n ) => Promise<RecentEventsResult>;\n 'lit:timeline-history': () => Promise<TimelineEvent[]>;\n 'lit:update-summary': (\n args?: UpdateSummaryArgs\n ) => Promise<UpdateSummaryResult>;\n 'lit:inspect': (command: InspectorCommand) => Promise<void>;\n 'lit:set-recording': (args: SetRecordingArgs) => Promise<void>;\n 'lit:toggle-layer': (args: ToggleLayerArgs) => Promise<void>;\n 'lit:set-settings-override': (override: SettingsOverride) => Promise<void>;\n 'lit:open-source': (args: OpenSourceArgs) => Promise<OpenSourceResult>;\n 'lit:export-snapshot': (\n args: ExportSnapshotArgs\n ) => Promise<ExportSnapshotResult>;\n 'lit:hmr-incompatibilities': () => Promise<HmrIncompatibilityEvent[]>;\n 'lit:page-send': (channel: string, data?: unknown) => void;\n }\n\n interface DevframeRpcClientFunctions {\n 'lit:inspector-message': (message: InspectorMessage) => void;\n 'lit:hmr-incompatible': (event: HmrIncompatibilityEvent) => void;\n 'lit:page-receive': (channel: string, data?: unknown) => void;\n }\n\n interface DevframeSettingsRegistry {\n lit: {\n /** Panel chrome preference. Mirrors `COLOR_SCHEME_LS_KEY`. */\n appearance?: 'auto' | 'dark' | 'light';\n /**\n * The Settings tab's live overrides, stored as one blob the way the\n * panel already treats them. Mirrors `SETTINGS_OVERRIDE_LS_KEY`, which\n * stays: the page runtime reads it synchronously at module-init time,\n * long before any client exists, and every settings-store read is\n * async by design.\n */\n override?: SettingsOverride;\n /**\n * The config value each overridden key was set against. A sibling of\n * `override` so the runtime never sees it. Mirrors\n * `OVERRIDE_BASELINES_LS_KEY`.\n */\n overrideBaselines?: OverrideBaselines;\n };\n }\n}\n"]}
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/lib/devframe/protocol.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;GAOG;AAEH,OAAO,EAAC,oBAAoB,EAAC,MAAM,yBAAyB,CAAC;AAkB7D,iFAAiF;AACjF,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AAErC,kEAAkE;AAClE,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,CAAC;AAE3C,uEAAuE;AACvE,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAEzC;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAE7C,oDAAoD;AACpD,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;AAEvC,gDAAgD;AAChD,MAAM,CAAC,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAErD,kDAAkD;AAClD,MAAM,CAAC,MAAM,qBAAqB,GAAG,mBAAmB,CAAC;AAEzD,8CAA8C;AAC9C,MAAM,CAAC,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,kBAAkB,CAAC;AAEvD,+CAA+C;AAC/C,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AAEnD,yCAAyC;AACzC,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AAErC,+CAA+C;AAC/C,MAAM,CAAC,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAEjD,8CAA8C;AAC9C,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAE/C,uDAAuD;AACvD,MAAM,CAAC,MAAM,yBAAyB,GAAG,uBAAuB,CAAC;AAEjE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC;AAuB7C,gEAAgE;AAChE,MAAM,CAAC,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAqBrD,wEAAwE;AACxE,MAAM,CAAC,MAAM,qBAAqB,GAAG,mBAAmB,CAAC;AAEzD,sDAAsD;AACtD,MAAM,CAAC,MAAM,yBAAyB,GAAG,uBAAuB,CAAC;AAEjE,uEAAuE;AACvE,MAAM,CAAC,MAAM,oBAAoB,GAAG,kBAAkB,CAAC;AAEvD;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC;AAEzC;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAkB/C,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IACjD,MAAM,EAAE,oBAAoB;IAC5B,YAAY,EAAE,EAAE;CACjB,CAAC;AAiFF;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GACtB;IACE,eAAe,EAAE,qBAAqB;IACtC,YAAY,EAAE,kBAAkB;IAChC,oBAAoB,EAAE,yBAAyB;IAC/C,KAAK,EAAE,mBAAmB;IAC1B,QAAQ,EAAE,sBAAsB;CACjC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Shared wire contract between the Lit devframe's node-side definition\n * ({@link ../definition.ts}) and its panel: shared-state / streaming /\n * RPC-function names, their payload shapes, and the `devframe` registry\n * augmentations that type them end to end.\n *\n * @see plans/devframe-foundation.md\n */\n\nimport {DEFAULT_LAYERS_STATE} from '../../types/timeline.js';\nimport type {\n FeatureSettings,\n OverrideBaselines,\n SettingsOverride,\n TimelineEvent,\n TimelineLayer,\n TimelineLayersState,\n} from '../../types/timeline.js';\nimport type {\n InspectorCommand,\n InspectorDetails,\n InspectorMessage,\n InspectorTreeNode,\n} from '../../types/inspector.js';\nimport type {HmrIncompatibilityEvent} from '../../types/hmr-incompatibility.js';\nimport type {ComponentRollup, UpdateCycle} from '../timeline/derive.js';\n\n/** The devframe's scope id. RPC names become `lit:*`, MCP wire names `lit_*`. */\nexport const LIT_DEVFRAME_ID = 'lit';\n\n/** Shared-state key holding the {@link SessionState} snapshot. */\nexport const SESSION_STATE_KEY = 'session';\n\n/** Streaming channel name the timeline event batches are pushed on. */\nexport const TIMELINE_STREAM_NAME = 'timeline';\n\n/**\n * Id of the one long-lived timeline stream. Fixed rather than discovered:\n * there is exactly one page feed per dev session, so the panel can subscribe\n * without a round trip to look the id up. The node side re-`start()`s this id\n * if the transport dropped the stream after the last subscriber left.\n */\nexport const TIMELINE_STREAM_ID = 'live';\n\n/**\n * Cap on the node-side recent-events ring buffer. It is also the history a\n * (re)connecting panel is seeded with (see {@link RPC_TIMELINE_HISTORY}).\n */\nexport const RECENT_EVENTS_BUFFER_SIZE = 512;\n\n/** Bare (unscoped) name of the `get-meta` query. */\nexport const RPC_GET_META = 'get-meta';\n\n/** Bare name of the `list-components` query. */\nexport const RPC_LIST_COMPONENTS = 'list-components';\n\n/** Bare name of the `component-details` query. */\nexport const RPC_COMPONENT_DETAILS = 'component-details';\n\n/** Bare name of the `recent-events` query. */\nexport const RPC_RECENT_EVENTS = 'recent-events';\n\n/**\n * Bare name of the `timeline-history` query: the node's whole recent-events\n * buffer, oldest first, as `TimelineEvent[]`. What a live panel seeds itself\n * with on connect, since the stream only carries events from then on. Not\n * `recent-events`, whose live answer is filtered and capped for agents.\n */\nexport const RPC_TIMELINE_HISTORY = 'timeline-history';\n\n/** Bare name of the `update-summary` query. */\nexport const RPC_UPDATE_SUMMARY = 'update-summary';\n\n/** Bare name of the `inspect` action. */\nexport const RPC_INSPECT = 'inspect';\n\n/** Bare name of the `set-recording` action. */\nexport const RPC_SET_RECORDING = 'set-recording';\n\n/** Bare name of the `toggle-layer` action. */\nexport const RPC_TOGGLE_LAYER = 'toggle-layer';\n\n/** Bare name of the `set-settings-override` action. */\nexport const RPC_SET_SETTINGS_OVERRIDE = 'set-settings-override';\n\n/** Bare name of the `open-source` action. */\nexport const RPC_OPEN_SOURCE = 'open-source';\n\n/** Arguments for {@link RPC_OPEN_SOURCE}. */\nexport interface OpenSourceArgs {\n /**\n * The path as the panel has it: what the transform injected, so relative\n * to the Vite root (or absolute, when the file lives outside it).\n */\n file: string;\n line?: number;\n}\n\n/** What {@link RPC_OPEN_SOURCE} reports back. */\nexport interface OpenSourceResult {\n /**\n * False when no open service is installed on the host, which is the\n * panel's cue to fall back to `/__lit-open-in-editor`. Also false when the\n * file is missing or outside the allowed roots; the endpoint refuses those\n * paths too.\n */\n opened: boolean;\n}\n\n/** Freeze the current session into a static panel directory. */\nexport const RPC_EXPORT_SNAPSHOT = 'export-snapshot';\n\n/** Arguments for {@link RPC_EXPORT_SNAPSHOT}. */\nexport interface ExportSnapshotArgs {\n /**\n * Where to write. Relative paths resolve against the dev server's cwd,\n * and the result has to stay beneath it. Defaults to\n * `lit-devtools-snapshot`. An existing directory is only replaced when it\n * holds an earlier snapshot.\n */\n outDir?: string;\n}\n\n/** What {@link RPC_EXPORT_SNAPSHOT} reports back, for the panel to display. */\nexport interface ExportSnapshotResult {\n outDir: string;\n events: number;\n components: number;\n details: number;\n}\n\n/** Bare name of the `inspector-message` client (node → panel) event. */\nexport const RPC_INSPECTOR_MESSAGE = 'inspector-message';\n\n/** Bare name of the `hmr-incompatibilities` query. */\nexport const RPC_HMR_INCOMPATIBILITIES = 'hmr-incompatibilities';\n\n/** Bare name of the `hmr-incompatible` client (node → panel) event. */\nexport const RPC_HMR_INCOMPATIBLE = 'hmr-incompatible';\n\n/**\n * Bare name of the page-to-server event. A page runtime that is not on a Vite\n * dev server's HMR socket sends every channel message it would have sent over\n * `import.meta.hot` as `page-send(channel, data)`.\n */\nexport const RPC_PAGE_SEND = 'page-send';\n\n/**\n * Bare name of the server-to-page client event, the reverse direction of\n * {@link RPC_PAGE_SEND}: `page-receive(channel, data)`. Broadcast to every\n * connected client and marked optional, since the panel does not register it.\n */\nexport const RPC_PAGE_RECEIVE = 'page-receive';\n\n/**\n * Recording/layers snapshot shared between every surface (panel, page\n * runtime, MCP). Survives reconnect; mutated either by the `set-recording` /\n * `toggle-layer` actions below or directly by a panel through the generic\n * shared-state RPC devframe provides.\n *\n * `layers.recordingState` is the single authority for \"is recording\" — the\n * runtime's own layer state carries it, so a separate flag here would be a\n * second copy to keep in sync.\n */\nexport interface SessionState {\n layers: TimelineLayersState;\n /** Layers announced at runtime by app code through `addTimelineLayer()`. */\n customLayers: TimelineLayer[];\n}\n\nexport const DEFAULT_SESSION_STATE: SessionState = {\n layers: DEFAULT_LAYERS_STATE,\n customLayers: [],\n};\n\n/** Result of the `get-meta` query. */\nexport interface LitGetMetaResult {\n version: string;\n /** Built-in layers followed by any runtime-announced custom ones. */\n layers: TimelineLayer[];\n features: FeatureSettings | null;\n /** Channel and id to pass to `rpc.streaming.subscribe()`. */\n stream: {channel: string; id: string};\n}\n\n/** Argument of the `component-details` query. */\nexport interface ComponentDetailsArgs {\n id: number;\n}\n\n/** Argument of the `recent-events` query. */\nexport interface RecentEventsArgs {\n layerId?: string;\n elementId?: number;\n /**\n * Only events from the last `sinceMs` milliseconds, measured against\n * the newest event currently in the buffer — not wall-clock time.\n * `TimelineEvent.time` is \"ms since recording started\" in the page\n * (see `runtime/timeline/clock.ts`), which has no fixed relationship\n * to this process's clock.\n */\n sinceMs?: number;\n /** Default 50, hard ceiling 200 regardless of what's requested. */\n limit?: number;\n}\n\n/** Result of the `recent-events` query. */\nexport interface RecentEventsResult {\n /** Whether the timeline is currently recording. */\n recording: boolean;\n /** Most recent events matching the filters, oldest first. */\n events: TimelineEvent[];\n /** Total events currently held in the ring buffer, before filtering. */\n bufferSize: number;\n /** True if filtering matched more events than were returned. */\n truncated: boolean;\n}\n\n/** Argument of the `update-summary` query. */\nexport interface UpdateSummaryArgs {\n /** Restrict to one component, by tag name. */\n tagName?: string;\n /** Same window semantics as {@link RecentEventsArgs.sinceMs}. */\n sinceMs?: number;\n /** Cycles returned (the component totals always cover the whole window).\n * Default 50, hard ceiling 200. */\n limit?: number;\n}\n\n/** Result of the `update-summary` query. */\nexport interface UpdateSummaryResult {\n /** Whether the timeline is currently recording. */\n recording: boolean;\n /** Per-component totals over the window, slowest first. */\n components: ComponentRollup[];\n /** The most recent update cycles in the window, oldest first. */\n cycles: UpdateCycle[];\n /** Total events currently held in the ring buffer, before derivation. */\n bufferSize: number;\n /** True if more cycles were derived than were returned. */\n truncated: boolean;\n}\n\n/** Argument of the `set-recording` action. */\nexport interface SetRecordingArgs {\n recording: boolean;\n}\n\n/** Argument of the `toggle-layer` action. */\nexport interface ToggleLayerArgs {\n layerId: string;\n enabled: boolean;\n}\n\n/**\n * Maps a {@link TimelineLayer.id} to the {@link TimelineLayersState} flag\n * that gates it. Custom layers have no flag and are always on.\n */\nexport const LAYER_FLAGS: Readonly<Record<string, keyof TimelineLayersState>> =\n {\n 'lit-lifecycle': 'litLifecycleEnabled',\n 'lit-render': 'litRenderEnabled',\n 'lit-render-verbose': 'litRenderVerboseEnabled',\n mouse: 'mouseEventEnabled',\n keyboard: 'keyboardEventEnabled',\n };\n\n// Hand-typed rather than derived through `RpcDefinitionsToFunctionsWithNamespace`\n// (also exported by `devframe/rpc`): the definitions themselves live in\n// definition.ts next to their handlers, and hand-typing here avoids a\n// value-level dependency from this shared-contract module back onto it.\ndeclare module 'devframe' {\n interface DevframeRpcServerFunctions {\n 'lit:get-meta': () => Promise<LitGetMetaResult>;\n 'lit:list-components': () => Promise<InspectorTreeNode[]>;\n 'lit:component-details': (\n args: ComponentDetailsArgs\n ) => Promise<InspectorDetails | null>;\n 'lit:recent-events': (\n args?: RecentEventsArgs\n ) => Promise<RecentEventsResult>;\n 'lit:timeline-history': () => Promise<TimelineEvent[]>;\n 'lit:update-summary': (\n args?: UpdateSummaryArgs\n ) => Promise<UpdateSummaryResult>;\n 'lit:inspect': (command: InspectorCommand) => Promise<void>;\n 'lit:set-recording': (args: SetRecordingArgs) => Promise<void>;\n 'lit:toggle-layer': (args: ToggleLayerArgs) => Promise<void>;\n 'lit:set-settings-override': (override: SettingsOverride) => Promise<void>;\n 'lit:open-source': (args: OpenSourceArgs) => Promise<OpenSourceResult>;\n 'lit:export-snapshot': (\n args: ExportSnapshotArgs\n ) => Promise<ExportSnapshotResult>;\n 'lit:hmr-incompatibilities': () => Promise<HmrIncompatibilityEvent[]>;\n 'lit:page-send': (channel: string, data?: unknown) => void;\n }\n\n interface DevframeRpcClientFunctions {\n 'lit:inspector-message': (message: InspectorMessage) => void;\n 'lit:hmr-incompatible': (event: HmrIncompatibilityEvent) => void;\n 'lit:page-receive': (channel: string, data?: unknown) => void;\n }\n\n interface DevframeSettingsRegistry {\n lit: {\n /** Panel chrome preference. Mirrors `COLOR_SCHEME_LS_KEY`. */\n appearance?: 'auto' | 'dark' | 'light';\n /**\n * The Settings tab's live overrides, stored as one blob the way the\n * panel already treats them. Mirrors `SETTINGS_OVERRIDE_LS_KEY`, which\n * stays: the page runtime reads it synchronously at module-init time,\n * long before any client exists, and every settings-store read is\n * async by design.\n */\n override?: SettingsOverride;\n /**\n * The config value each overridden key was set against. A sibling of\n * `override` so the runtime never sees it. Mirrors\n * `OVERRIDE_BASELINES_LS_KEY`.\n */\n overrideBaselines?: OverrideBaselines;\n };\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../../src/lib/devframe/vite.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../../src/lib/devframe/vite.ts"],"names":[],"mappings":"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"}
@@ -231,6 +231,7 @@ export function createLitDevframePlugin(options) {
231
231
  // Only known once `setup()` has the dev server, which is after the
232
232
  // definition is built -- hence the getter.
233
233
  let viteRoot;
234
+ let fsAllow = [];
234
235
  const definition = createLitDevframe({
235
236
  source,
236
237
  version: options.version,
@@ -238,6 +239,7 @@ export function createLitDevframePlugin(options) {
238
239
  configuredEditor: options.configuredEditor,
239
240
  clientAssets: options.clientAssets,
240
241
  sourceRoot: () => viteRoot,
242
+ allowedRoots: () => fsAllow,
241
243
  });
242
244
  return {
243
245
  name: `devframe:${LIT_DEVFRAME_ID}`,
@@ -252,6 +254,7 @@ export function createLitDevframePlugin(options) {
252
254
  // available on the context by now.
253
255
  if (ctx.viteServer) source.bind(ctx.viteServer, ctx);
254
256
  viteRoot = ctx.viteServer?.config.root;
257
+ fsAllow = ctx.viteServer?.config.server.fs?.allow ?? [];
255
258
  await ctx.install(definition);
256
259
  // The overlay picker as a palette command with a managed shortcut.
257
260
  // Only meaningful when the source overlay is enabled, since that is
@@ -1 +1 @@
1
- {"version":3,"file":"vite.js","sourceRoot":"","sources":["../../src/lib/devframe/vite.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Mounts the Lit devframe ({@link createLitDevframe}) into the Vite DevTools\n * hub and bridges the page runtime's `import.meta.hot` transport to the\n * definition's `TimelineSource` port. Everything Vite-specific lives here:\n * the definition itself must keep running under `createDevServer()` with no\n * Vite installed.\n *\n * Vite DevTools 0.7+ is itself built on devframe, so its plugin context is a\n * devframe hub context: `ctx.install(definition)` serves the panel SPA from\n * the definition's `clientAssets`, registers its dock, and exposes its RPC\n * over the hub's authenticated WebSocket. That is all\n * `createPluginFromDevframe()` from `@vitejs/devtools-kit` does, so calling\n * `install` directly keeps DevTools an optional peer we never import at\n * runtime — the hook below is duck-typed, exactly as the panel's previous\n * dock registration was.\n *\n * @see plans/devframe-foundation.md\n */\n\nimport type {Plugin, ViteDevServer} from 'vite';\nimport type {DevframeDefinition} from 'devframe';\nimport {\n INSPECT_CMD_CHANNEL,\n INSPECT_DATA_CHANNEL,\n INSPECT_OVERLAY_TOGGLE_CHANNEL,\n} from '../../types/inspector.js';\nimport type {\n InspectorCommand,\n InspectorMessage,\n} from '../../types/inspector.js';\nimport {HMR_INCOMPATIBLE_CHANNEL} from '../../types/hmr-incompatibility.js';\nimport type {HmrIncompatibilityEvent} from '../../types/hmr-incompatibility.js';\nimport {SETTINGS_OVERRIDE_CHANNEL} from '../../types/timeline.js';\nimport type {\n FeatureSettings,\n SettingsOverride,\n TimelineEvent,\n TimelineLayer,\n TimelineLayersState,\n} from '../../types/timeline.js';\nimport {createLitDevframe} from './definition.js';\nimport {LIT_DEVFRAME_ID} from './protocol.js';\nimport {layersWireFormat} from './source.js';\nimport type {TimelineSink, TimelineSource} from './source.js';\n\nexport {createLitDevframe};\n\n/**\n * The slice of the Vite DevTools hub context this plugin uses. Structurally a\n * subset of `ViteDevToolsNodeContext` from `@vitejs/devtools-kit/node`;\n * declared here so the package never imports that optional peer at runtime.\n * Install `@vitejs/devtools-kit` as a dev dependency to check it against the\n * real declarations.\n */\ninterface DevToolsHubContext {\n readonly viteServer?: ViteDevServer;\n /** Serve a devframe's SPA, register its dock, and run its `setup()`. */\n install: (\n devframe: DevframeDefinition,\n options?: {base?: string; dock?: Record<string, unknown>}\n ) => Promise<void>;\n docks?: {\n activate?: (dockId: string, params?: Record<string, unknown>) => void;\n };\n commands?: {register?: (command: Record<string, unknown>) => unknown};\n /**\n * The hub's host runtime. Structurally the slice of devframe's\n * `DevframeHost` {@link registerInstance} needs; `DevframeHubContext`\n * extends `DevframeNodeContext`, which carries it.\n */\n host?: {resolveOrigin?: () => string};\n}\n\ndeclare module 'vite' {\n interface Plugin {\n /** Vite DevTools plugin hook, contributed by `@vitejs/devtools`. */\n devtools?: {\n capabilities?: {dev?: boolean; build?: boolean};\n setup: (ctx: DevToolsHubContext) => void | Promise<void>;\n };\n }\n}\n\nexport interface CreateLitDevframePluginOptions {\n version: string;\n features?: () => FeatureSettings | null;\n /** See {@link CreateLitDevframeOptions.configuredEditor}. */\n configuredEditor?: () => string | undefined;\n /** Override the built panel SPA directory. Defaults to `dist/client`. */\n clientAssets?: string;\n}\n\n/**\n * `TimelineSource` over a Vite dev server's `hot` channel.\n *\n * `install()` runs the definition's `setup()` — and therefore\n * `source.attach()` — before it resolves, so this is attached before a dev\n * server is necessarily in hand. Calls made before {@link bind} are dropped\n * rather than buffered: nothing can emit a page-runtime event until a page\n * has connected to a bound server.\n */\nexport class HotTimelineSource implements TimelineSource {\n #hot: ViteDevServer['hot'] | undefined;\n #sink: TimelineSink | undefined;\n #hub: DevToolsHubContext | undefined;\n\n /**\n * Wire the source to a live dev server. Call once, from `devtools.setup()`.\n * `hub` is optional: without it the bridge still carries page traffic both\n * ways, it just cannot bring the dock to the front on an overlay pick.\n */\n bind(server: ViteDevServer, hub?: DevToolsHubContext): void {\n this.#hub = hub;\n const hot = server.hot;\n this.#hot = hot;\n\n hot.on('lit:timeline:push-event', (data: {events?: TimelineEvent[]}) => {\n this.#sink?.pushEvents(data.events ?? []);\n });\n\n hot.on('lit:timeline:custom-layer', (data: {layer?: TimelineLayer}) => {\n if (!data.layer?.id) return;\n this.#sink?.addLayer(data.layer);\n });\n\n hot.on(INSPECT_DATA_CHANNEL, (data: InspectorMessage) => {\n // An overlay pick means the developer clicked an element in the page and\n // wants the Components tab. Bring the dock forward from the node side\n // rather than having the panel reach into the parent frame.\n if (data.type === 'pick') {\n // Carry the target with the activation, not just the dock id: the\n // params ride the hub's `devframe:docks:active` state, so a panel\n // that mounts *because of* this pick still lands on the right\n // element instead of racing the separate `pick` message.\n this.#hub?.docks?.activate?.(LIT_DEVFRAME_ID, {componentId: data.id});\n }\n this.#sink?.inspectorMessage(data);\n });\n\n hot.on(HMR_INCOMPATIBLE_CHANNEL, (event: HmrIncompatibilityEvent) => {\n this.#sink?.hmrIncompatible(event);\n });\n\n // The runtime announces itself on every connect. It boots from the\n // compiled-in defaults (recording off), so the session's current state\n // has to be pushed back down or a page that loads while recording is on\n // captures nothing while every surface still reports `recording: true`.\n hot.on('lit:timeline:runtime-ready', () => {\n this.#sink?.runtimeReady();\n });\n }\n\n /** Toggle the page's inspect overlay. Also used by the palette command. */\n toggleOverlay(): void {\n this.#hot?.send(INSPECT_OVERLAY_TOGGLE_CHANNEL);\n }\n\n attach(sink: TimelineSink): () => void {\n this.#sink = sink;\n return () => {\n if (this.#sink === sink) this.#sink = undefined;\n };\n }\n\n sendInspector(cmd: InspectorCommand): void {\n this.#hot?.send(INSPECT_CMD_CHANNEL, cmd);\n }\n\n setRecording(recording: boolean): void {\n this.#hot?.send('lit:timeline:recording-changed', {recording});\n }\n\n setLayers(layers: TimelineLayersState): void {\n this.#hot?.send('lit:timeline:layers-changed', layersWireFormat(layers));\n }\n\n setSettingsOverride(override: SettingsOverride): void {\n this.#hot?.send(SETTINGS_OVERRIDE_CHANNEL, override);\n }\n}\n\n/**\n * One warning per process, not per dev server: a restart-heavy session\n * should not paper the terminal with the same advisory. Carries the reason,\n * because \"discovery unavailable\" with no cause is the kind of message that\n * costs an afternoon when the guess below finally goes stale.\n */\nlet warnedDiscoveryUnavailable = false;\n\nconst warnDiscoveryUnavailable = (reason: string): void => {\n if (warnedDiscoveryUnavailable) return;\n warnedDiscoveryUnavailable = true;\n console.warn(\n `[lit-plugin] devframe instance-registry discovery unavailable ` +\n `(${reason}); stdio MCP clients cannot auto-discover this dev ` +\n `server. The MCP endpoint itself is unaffected — point clients at ` +\n `<dev-server-origin>/__devtools/__mcp directly.`\n );\n};\n\n/**\n * Publish this devframe in devframe's global instance registry\n * (`~/.devframe/instances/`), so stdio MCP connectors — `devframe connect`,\n * this package's own `lit-devtools mcp` — find the running dev server\n * without port guessing.\n *\n * `createDevServer()` registers itself, but this plugin never goes through\n * it: it mounts into the Vite DevTools hub, and `@vitejs/devtools@0.7.5`\n * calls `initHub()` with no `register` option, which defaults to off. So a\n * Vite-hosted devframe is invisible to discovery unless a plugin publishes\n * the record itself — which is all this does. `registerDevframeInstance()`\n * is documented for exactly this case (\"custom hosts that serve a devframe\n * in-process call this explicitly with the origin they are reachable at\"),\n * and the registry is a directory of per-`pid`+`port` JSON files, so\n * registrants coexist.\n *\n * The mount path is the soft spot: `/__devtools/` is where this version of\n * Vite DevTools mounts, not a promise about where a devframe host mounts in\n * general. So the guess is verified before it is published — the same\n * `probeDevframeOrigin()` primitive the registry's own liveness check uses\n * has to answer at that base, or nothing is registered. A record that\n * doesn't answer is worse than no record: an agent dials it and gets 404s\n * from a server that claimed to be there.\n *\n * The MCP path is then taken from what that probe *reports* rather than\n * assumed to be the `__mcp` default, which removes the second guess\n * entirely. Note the two path conventions in play: `__connection.json`\n * serves `mcp.path` **relative** to the base (`\"__mcp\"`), while a registry\n * record stores it **absolute** (`\"/__devtools/__mcp\"`) because the\n * connector dials `origin + record.mcp.path` directly. Joining the two is\n * exactly what devframe's own `probePort()` does with its root-mounted\n * probe.\n *\n * Known sharp edge: records are keyed by `pid`+`port` alone. Another\n * devframe-hosting plugin in the same Vite process would share this file,\n * and whichever unregisters first removes it for both. Single-devframe use\n * is the common case and there is no cross-plugin coordination primitive\n * today.\n */\nasync function registerInstance(\n ctx: DevToolsHubContext,\n name: string\n): Promise<{unregister: () => void} | {reason: string}> {\n // Both imports are dynamic and optional: `@vitejs/devtools-kit` is an\n // optional peer this package must never hard-resolve, and `devframe`'s\n // `internal` subpath is only needed on this path.\n const constants = await import('@vitejs/devtools-kit/constants').catch(\n () => null\n );\n const internal = await import('devframe/internal').catch(() => null);\n if (!constants) return {reason: '@vitejs/devtools-kit not resolvable'};\n if (!internal) return {reason: 'devframe/internal not resolvable'};\n\n const basePath = constants.DEVTOOLS_MOUNT_PATH;\n const origin = ctx.host?.resolveOrigin?.();\n if (!origin) return {reason: 'host origin unavailable'};\n\n const probed = await internal.probeDevframeOrigin(origin, basePath);\n if (!probed) {\n return {reason: `no devframe answered at ${origin}${basePath}`};\n }\n\n // Relative (`\"__mcp\"`) as served, absolute as stored — see above. A host\n // that already reports an absolute path is passed through unchanged.\n const reported = probed.meta.mcp?.path;\n const mcpPath =\n reported === undefined\n ? null\n : reported.startsWith('/')\n ? reported\n : `${basePath}${reported}`;\n\n const {unregister} = internal.registerDevframeInstance({\n pid: process.pid,\n // The probe reports the origin that actually answered — a `localhost`\n // bind may only be dialable as `127.0.0.1` or `[::1]` — so its port is\n // the one truly listening, which `config.server.port` is not when the\n // configured port was taken.\n port: Number(new URL(probed.origin).port) || 0,\n origin: probed.origin,\n basePath,\n id: LIT_DEVFRAME_ID,\n name,\n rootDir: process.cwd(),\n // Registering with `mcp: null` is honest rather than useless: the\n // connector surfaces the instance with its own \"MCP disabled\" hint,\n // which beats the instance being invisible.\n mcp: mcpPath === null ? null : {path: mcpPath},\n startedAt: Date.now(),\n });\n return {unregister};\n}\n\n/**\n * Register once the dev server is actually accepting connections. The\n * DevTools `setup()` hook runs during server construction, well before\n * `listen()` resolves, so probing from there always fails to connect — the\n * record has to wait for the port it is about to advertise to be real.\n */\nfunction registerInstanceWhenListening(\n ctx: DevToolsHubContext,\n name: string\n): void {\n const httpServer = ctx.viteServer?.httpServer;\n if (!httpServer) {\n // Middleware mode: no server of our own to advertise.\n warnDiscoveryUnavailable('no HTTP server (middleware mode?)');\n return;\n }\n\n const run = (): void => {\n registerInstance(ctx, name)\n .then((result) => {\n if ('unregister' in result) {\n httpServer.once('close', result.unregister);\n } else {\n warnDiscoveryUnavailable(result.reason);\n }\n })\n .catch((error: unknown) => {\n warnDiscoveryUnavailable(String(error));\n });\n };\n\n if (httpServer.listening) run();\n else httpServer.once('listening', run);\n}\n\n/**\n * The Vite plugin that mounts the Lit devframe on the DevTools hub. A no-op\n * when DevTools is not active: without it nothing calls `devtools.setup()`,\n * so the definition is never installed and the panel simply isn't there.\n */\nexport function createLitDevframePlugin(\n options: CreateLitDevframePluginOptions\n): Plugin {\n const source = new HotTimelineSource();\n // Only known once `setup()` has the dev server, which is after the\n // definition is built -- hence the getter.\n let viteRoot: string | undefined;\n const definition = createLitDevframe({\n source,\n version: options.version,\n features: options.features,\n configuredEditor: options.configuredEditor,\n clientAssets: options.clientAssets,\n sourceRoot: () => viteRoot,\n });\n\n return {\n name: `devframe:${LIT_DEVFRAME_ID}`,\n devtools: {\n // The panel reflects a running page, so there is nothing to mount\n // during `vite build`. A static snapshot goes through\n // `devframe/adapters/build` instead.\n capabilities: {dev: true, build: false},\n async setup(ctx) {\n // Bind before installing: `install()` runs the definition's `setup()`,\n // which attaches to this source, and the dev server is already\n // available on the context by now.\n if (ctx.viteServer) source.bind(ctx.viteServer, ctx);\n viteRoot = ctx.viteServer?.config.root;\n await ctx.install(definition);\n\n // The overlay picker as a palette command with a managed shortcut.\n // Only meaningful when the source overlay is enabled, since that is\n // what draws the picker in the page.\n if (options.features?.()?.sourceOverlay.enabled) {\n ctx.commands?.register?.({\n id: 'lit:overlay:toggle',\n title: 'Pick Lit Element',\n description:\n 'Click to inspect in the Components panel, hold Meta/Ctrl and click to open in your editor',\n icon: 'ph:crosshair-duotone',\n category: 'Lit',\n keybindings: [{key: 'Meta+Shift+E'}],\n handler: () => source.toggleOverlay(),\n });\n }\n\n // Discovery is a convenience on top of a panel that already works,\n // so this never blocks `setup()` and never throws: a failure costs\n // the user the stdio MCP shortcut, and the direct URL still works.\n registerInstanceWhenListening(ctx, definition.name);\n },\n },\n };\n}\n\n/**\n * The page-runtime bridge on its own, for a host that drives its own mount\n * (or a test that wants to observe page traffic without a hub). Bind it to a\n * dev server, then either hand it to {@link createLitDevframe} or\n * {@link TimelineSource.attach} your own sink.\n */\nexport const createHotTimelineSource = (): HotTimelineSource =>\n new HotTimelineSource();\n"]}
1
+ {"version":3,"file":"vite.js","sourceRoot":"","sources":["../../src/lib/devframe/vite.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Mounts the Lit devframe ({@link createLitDevframe}) into the Vite DevTools\n * hub and bridges the page runtime's `import.meta.hot` transport to the\n * definition's `TimelineSource` port. Everything Vite-specific lives here:\n * the definition itself must keep running under `createDevServer()` with no\n * Vite installed.\n *\n * Vite DevTools 0.7+ is itself built on devframe, so its plugin context is a\n * devframe hub context: `ctx.install(definition)` serves the panel SPA from\n * the definition's `clientAssets`, registers its dock, and exposes its RPC\n * over the hub's authenticated WebSocket. That is all\n * `createPluginFromDevframe()` from `@vitejs/devtools-kit` does, so calling\n * `install` directly keeps DevTools an optional peer we never import at\n * runtime — the hook below is duck-typed, exactly as the panel's previous\n * dock registration was.\n *\n * @see plans/devframe-foundation.md\n */\n\nimport type {Plugin, ViteDevServer} from 'vite';\nimport type {DevframeDefinition} from 'devframe';\nimport {\n INSPECT_CMD_CHANNEL,\n INSPECT_DATA_CHANNEL,\n INSPECT_OVERLAY_TOGGLE_CHANNEL,\n} from '../../types/inspector.js';\nimport type {\n InspectorCommand,\n InspectorMessage,\n} from '../../types/inspector.js';\nimport {HMR_INCOMPATIBLE_CHANNEL} from '../../types/hmr-incompatibility.js';\nimport type {HmrIncompatibilityEvent} from '../../types/hmr-incompatibility.js';\nimport {SETTINGS_OVERRIDE_CHANNEL} from '../../types/timeline.js';\nimport type {\n FeatureSettings,\n SettingsOverride,\n TimelineEvent,\n TimelineLayer,\n TimelineLayersState,\n} from '../../types/timeline.js';\nimport {createLitDevframe} from './definition.js';\nimport {LIT_DEVFRAME_ID} from './protocol.js';\nimport {layersWireFormat} from './source.js';\nimport type {TimelineSink, TimelineSource} from './source.js';\n\nexport {createLitDevframe};\n\n/**\n * The slice of the Vite DevTools hub context this plugin uses. Structurally a\n * subset of `ViteDevToolsNodeContext` from `@vitejs/devtools-kit/node`;\n * declared here so the package never imports that optional peer at runtime.\n * Install `@vitejs/devtools-kit` as a dev dependency to check it against the\n * real declarations.\n */\ninterface DevToolsHubContext {\n readonly viteServer?: ViteDevServer;\n /** Serve a devframe's SPA, register its dock, and run its `setup()`. */\n install: (\n devframe: DevframeDefinition,\n options?: {base?: string; dock?: Record<string, unknown>}\n ) => Promise<void>;\n docks?: {\n activate?: (dockId: string, params?: Record<string, unknown>) => void;\n };\n commands?: {register?: (command: Record<string, unknown>) => unknown};\n /**\n * The hub's host runtime. Structurally the slice of devframe's\n * `DevframeHost` {@link registerInstance} needs; `DevframeHubContext`\n * extends `DevframeNodeContext`, which carries it.\n */\n host?: {resolveOrigin?: () => string};\n}\n\ndeclare module 'vite' {\n interface Plugin {\n /** Vite DevTools plugin hook, contributed by `@vitejs/devtools`. */\n devtools?: {\n capabilities?: {dev?: boolean; build?: boolean};\n setup: (ctx: DevToolsHubContext) => void | Promise<void>;\n };\n }\n}\n\nexport interface CreateLitDevframePluginOptions {\n version: string;\n features?: () => FeatureSettings | null;\n /** See {@link CreateLitDevframeOptions.configuredEditor}. */\n configuredEditor?: () => string | undefined;\n /** Override the built panel SPA directory. Defaults to `dist/client`. */\n clientAssets?: string;\n}\n\n/**\n * `TimelineSource` over a Vite dev server's `hot` channel.\n *\n * `install()` runs the definition's `setup()` — and therefore\n * `source.attach()` — before it resolves, so this is attached before a dev\n * server is necessarily in hand. Calls made before {@link bind} are dropped\n * rather than buffered: nothing can emit a page-runtime event until a page\n * has connected to a bound server.\n */\nexport class HotTimelineSource implements TimelineSource {\n #hot: ViteDevServer['hot'] | undefined;\n #sink: TimelineSink | undefined;\n #hub: DevToolsHubContext | undefined;\n\n /**\n * Wire the source to a live dev server. Call once, from `devtools.setup()`.\n * `hub` is optional: without it the bridge still carries page traffic both\n * ways, it just cannot bring the dock to the front on an overlay pick.\n */\n bind(server: ViteDevServer, hub?: DevToolsHubContext): void {\n this.#hub = hub;\n const hot = server.hot;\n this.#hot = hot;\n\n hot.on('lit:timeline:push-event', (data: {events?: TimelineEvent[]}) => {\n this.#sink?.pushEvents(data.events ?? []);\n });\n\n hot.on('lit:timeline:custom-layer', (data: {layer?: TimelineLayer}) => {\n if (!data.layer?.id) return;\n this.#sink?.addLayer(data.layer);\n });\n\n hot.on(INSPECT_DATA_CHANNEL, (data: InspectorMessage) => {\n // An overlay pick means the developer clicked an element in the page and\n // wants the Components tab. Bring the dock forward from the node side\n // rather than having the panel reach into the parent frame.\n if (data.type === 'pick') {\n // Carry the target with the activation, not just the dock id: the\n // params ride the hub's `devframe:docks:active` state, so a panel\n // that mounts *because of* this pick still lands on the right\n // element instead of racing the separate `pick` message.\n this.#hub?.docks?.activate?.(LIT_DEVFRAME_ID, {componentId: data.id});\n }\n this.#sink?.inspectorMessage(data);\n });\n\n hot.on(HMR_INCOMPATIBLE_CHANNEL, (event: HmrIncompatibilityEvent) => {\n this.#sink?.hmrIncompatible(event);\n });\n\n // The runtime announces itself on every connect. It boots from the\n // compiled-in defaults (recording off), so the session's current state\n // has to be pushed back down or a page that loads while recording is on\n // captures nothing while every surface still reports `recording: true`.\n hot.on('lit:timeline:runtime-ready', () => {\n this.#sink?.runtimeReady();\n });\n }\n\n /** Toggle the page's inspect overlay. Also used by the palette command. */\n toggleOverlay(): void {\n this.#hot?.send(INSPECT_OVERLAY_TOGGLE_CHANNEL);\n }\n\n attach(sink: TimelineSink): () => void {\n this.#sink = sink;\n return () => {\n if (this.#sink === sink) this.#sink = undefined;\n };\n }\n\n sendInspector(cmd: InspectorCommand): void {\n this.#hot?.send(INSPECT_CMD_CHANNEL, cmd);\n }\n\n setRecording(recording: boolean): void {\n this.#hot?.send('lit:timeline:recording-changed', {recording});\n }\n\n setLayers(layers: TimelineLayersState): void {\n this.#hot?.send('lit:timeline:layers-changed', layersWireFormat(layers));\n }\n\n setSettingsOverride(override: SettingsOverride): void {\n this.#hot?.send(SETTINGS_OVERRIDE_CHANNEL, override);\n }\n}\n\n/**\n * One warning per process, not per dev server: a restart-heavy session\n * should not paper the terminal with the same advisory. Carries the reason,\n * because \"discovery unavailable\" with no cause is the kind of message that\n * costs an afternoon when the guess below finally goes stale.\n */\nlet warnedDiscoveryUnavailable = false;\n\nconst warnDiscoveryUnavailable = (reason: string): void => {\n if (warnedDiscoveryUnavailable) return;\n warnedDiscoveryUnavailable = true;\n console.warn(\n `[lit-plugin] devframe instance-registry discovery unavailable ` +\n `(${reason}); stdio MCP clients cannot auto-discover this dev ` +\n `server. The MCP endpoint itself is unaffected — point clients at ` +\n `<dev-server-origin>/__devtools/__mcp directly.`\n );\n};\n\n/**\n * Publish this devframe in devframe's global instance registry\n * (`~/.devframe/instances/`), so stdio MCP connectors — `devframe connect`,\n * this package's own `lit-devtools mcp` — find the running dev server\n * without port guessing.\n *\n * `createDevServer()` registers itself, but this plugin never goes through\n * it: it mounts into the Vite DevTools hub, and `@vitejs/devtools@0.7.5`\n * calls `initHub()` with no `register` option, which defaults to off. So a\n * Vite-hosted devframe is invisible to discovery unless a plugin publishes\n * the record itself — which is all this does. `registerDevframeInstance()`\n * is documented for exactly this case (\"custom hosts that serve a devframe\n * in-process call this explicitly with the origin they are reachable at\"),\n * and the registry is a directory of per-`pid`+`port` JSON files, so\n * registrants coexist.\n *\n * The mount path is the soft spot: `/__devtools/` is where this version of\n * Vite DevTools mounts, not a promise about where a devframe host mounts in\n * general. So the guess is verified before it is published — the same\n * `probeDevframeOrigin()` primitive the registry's own liveness check uses\n * has to answer at that base, or nothing is registered. A record that\n * doesn't answer is worse than no record: an agent dials it and gets 404s\n * from a server that claimed to be there.\n *\n * The MCP path is then taken from what that probe *reports* rather than\n * assumed to be the `__mcp` default, which removes the second guess\n * entirely. Note the two path conventions in play: `__connection.json`\n * serves `mcp.path` **relative** to the base (`\"__mcp\"`), while a registry\n * record stores it **absolute** (`\"/__devtools/__mcp\"`) because the\n * connector dials `origin + record.mcp.path` directly. Joining the two is\n * exactly what devframe's own `probePort()` does with its root-mounted\n * probe.\n *\n * Known sharp edge: records are keyed by `pid`+`port` alone. Another\n * devframe-hosting plugin in the same Vite process would share this file,\n * and whichever unregisters first removes it for both. Single-devframe use\n * is the common case and there is no cross-plugin coordination primitive\n * today.\n */\nasync function registerInstance(\n ctx: DevToolsHubContext,\n name: string\n): Promise<{unregister: () => void} | {reason: string}> {\n // Both imports are dynamic and optional: `@vitejs/devtools-kit` is an\n // optional peer this package must never hard-resolve, and `devframe`'s\n // `internal` subpath is only needed on this path.\n const constants = await import('@vitejs/devtools-kit/constants').catch(\n () => null\n );\n const internal = await import('devframe/internal').catch(() => null);\n if (!constants) return {reason: '@vitejs/devtools-kit not resolvable'};\n if (!internal) return {reason: 'devframe/internal not resolvable'};\n\n const basePath = constants.DEVTOOLS_MOUNT_PATH;\n const origin = ctx.host?.resolveOrigin?.();\n if (!origin) return {reason: 'host origin unavailable'};\n\n const probed = await internal.probeDevframeOrigin(origin, basePath);\n if (!probed) {\n return {reason: `no devframe answered at ${origin}${basePath}`};\n }\n\n // Relative (`\"__mcp\"`) as served, absolute as stored — see above. A host\n // that already reports an absolute path is passed through unchanged.\n const reported = probed.meta.mcp?.path;\n const mcpPath =\n reported === undefined\n ? null\n : reported.startsWith('/')\n ? reported\n : `${basePath}${reported}`;\n\n const {unregister} = internal.registerDevframeInstance({\n pid: process.pid,\n // The probe reports the origin that actually answered — a `localhost`\n // bind may only be dialable as `127.0.0.1` or `[::1]` — so its port is\n // the one truly listening, which `config.server.port` is not when the\n // configured port was taken.\n port: Number(new URL(probed.origin).port) || 0,\n origin: probed.origin,\n basePath,\n id: LIT_DEVFRAME_ID,\n name,\n rootDir: process.cwd(),\n // Registering with `mcp: null` is honest rather than useless: the\n // connector surfaces the instance with its own \"MCP disabled\" hint,\n // which beats the instance being invisible.\n mcp: mcpPath === null ? null : {path: mcpPath},\n startedAt: Date.now(),\n });\n return {unregister};\n}\n\n/**\n * Register once the dev server is actually accepting connections. The\n * DevTools `setup()` hook runs during server construction, well before\n * `listen()` resolves, so probing from there always fails to connect — the\n * record has to wait for the port it is about to advertise to be real.\n */\nfunction registerInstanceWhenListening(\n ctx: DevToolsHubContext,\n name: string\n): void {\n const httpServer = ctx.viteServer?.httpServer;\n if (!httpServer) {\n // Middleware mode: no server of our own to advertise.\n warnDiscoveryUnavailable('no HTTP server (middleware mode?)');\n return;\n }\n\n const run = (): void => {\n registerInstance(ctx, name)\n .then((result) => {\n if ('unregister' in result) {\n httpServer.once('close', result.unregister);\n } else {\n warnDiscoveryUnavailable(result.reason);\n }\n })\n .catch((error: unknown) => {\n warnDiscoveryUnavailable(String(error));\n });\n };\n\n if (httpServer.listening) run();\n else httpServer.once('listening', run);\n}\n\n/**\n * The Vite plugin that mounts the Lit devframe on the DevTools hub. A no-op\n * when DevTools is not active: without it nothing calls `devtools.setup()`,\n * so the definition is never installed and the panel simply isn't there.\n */\nexport function createLitDevframePlugin(\n options: CreateLitDevframePluginOptions\n): Plugin {\n const source = new HotTimelineSource();\n // Only known once `setup()` has the dev server, which is after the\n // definition is built -- hence the getter.\n let viteRoot: string | undefined;\n let fsAllow: readonly string[] = [];\n const definition = createLitDevframe({\n source,\n version: options.version,\n features: options.features,\n configuredEditor: options.configuredEditor,\n clientAssets: options.clientAssets,\n sourceRoot: () => viteRoot,\n allowedRoots: () => fsAllow,\n });\n\n return {\n name: `devframe:${LIT_DEVFRAME_ID}`,\n devtools: {\n // The panel reflects a running page, so there is nothing to mount\n // during `vite build`. A static snapshot goes through\n // `devframe/adapters/build` instead.\n capabilities: {dev: true, build: false},\n async setup(ctx) {\n // Bind before installing: `install()` runs the definition's `setup()`,\n // which attaches to this source, and the dev server is already\n // available on the context by now.\n if (ctx.viteServer) source.bind(ctx.viteServer, ctx);\n viteRoot = ctx.viteServer?.config.root;\n fsAllow = ctx.viteServer?.config.server.fs?.allow ?? [];\n await ctx.install(definition);\n\n // The overlay picker as a palette command with a managed shortcut.\n // Only meaningful when the source overlay is enabled, since that is\n // what draws the picker in the page.\n if (options.features?.()?.sourceOverlay.enabled) {\n ctx.commands?.register?.({\n id: 'lit:overlay:toggle',\n title: 'Pick Lit Element',\n description:\n 'Click to inspect in the Components panel, hold Meta/Ctrl and click to open in your editor',\n icon: 'ph:crosshair-duotone',\n category: 'Lit',\n keybindings: [{key: 'Meta+Shift+E'}],\n handler: () => source.toggleOverlay(),\n });\n }\n\n // Discovery is a convenience on top of a panel that already works,\n // so this never blocks `setup()` and never throws: a failure costs\n // the user the stdio MCP shortcut, and the direct URL still works.\n registerInstanceWhenListening(ctx, definition.name);\n },\n },\n };\n}\n\n/**\n * The page-runtime bridge on its own, for a host that drives its own mount\n * (or a test that wants to observe page traffic without a hub). Bind it to a\n * dev server, then either hand it to {@link createLitDevframe} or\n * {@link TimelineSource.attach} your own sink.\n */\nexport const createHotTimelineSource = (): HotTimelineSource =>\n new HotTimelineSource();\n"]}
package/lib/http.d.ts CHANGED
@@ -24,6 +24,11 @@ export interface TrustHeaders {
24
24
  * user-typed URL) are ours, `cross-site`/`same-site` are not.
25
25
  * A request is trusted only when every signal it does carry says same-origin,
26
26
  * and at least one of them is present.
27
+ *
28
+ * This does not stop DNS rebinding, where a hostile page reaches the server
29
+ * under its own name and `Origin` and `Host` agree. Vite's
30
+ * `server.allowedHosts` check does, and it runs before any plugin middleware,
31
+ * so this doesn't repeat it (source-overlay_test pins that ordering).
27
32
  */
28
33
  export declare const isTrustedRequest: (headers: TrustHeaders) => boolean;
29
34
  //# sourceMappingURL=http.d.ts.map
package/lib/http.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/lib/http.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,YAAa,YAAY,KAAG,OAgBxD,CAAC"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/lib/http.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,gBAAgB,YAAa,YAAY,KAAG,OAgBxD,CAAC"}
package/lib/http.js CHANGED
@@ -14,6 +14,11 @@
14
14
  * user-typed URL) are ours, `cross-site`/`same-site` are not.
15
15
  * A request is trusted only when every signal it does carry says same-origin,
16
16
  * and at least one of them is present.
17
+ *
18
+ * This does not stop DNS rebinding, where a hostile page reaches the server
19
+ * under its own name and `Origin` and `Host` agree. Vite's
20
+ * `server.allowedHosts` check does, and it runs before any plugin middleware,
21
+ * so this doesn't repeat it (source-overlay_test pins that ordering).
17
22
  */
18
23
  export const isTrustedRequest = (headers) => {
19
24
  const site = headers['sec-fetch-site'];
package/lib/http.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/lib/http.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAaH;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAqB,EAAW,EAAE;IACjE,MAAM,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,IAAI,IAAI,KAAK,aAAa,IAAI,IAAI,KAAK,MAAM;YAAE,OAAO,KAAK,CAAC;IAC9D,CAAC;IACD,MAAM,EAAC,MAAM,EAAE,IAAI,EAAC,GAAG,OAAO,CAAC;IAC/B,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QAC9C,IAAI,CAAC;YACH,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,sEAAsE;IACtE,OAAO,IAAI,KAAK,SAAS,CAAC;AAC5B,CAAC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Headers the trust check looks at. Both the open-in-editor endpoint and the\n * timeline/inspector endpoints are local-only dev tooling: only the page the\n * dev server itself served may drive them.\n */\nexport interface TrustHeaders {\n origin?: string;\n host?: string;\n 'sec-fetch-site'?: string;\n}\n\n/**\n * True when the request demonstrably comes from the dev server's own page.\n *\n * Two independent signals, because neither is present on every request:\n * - `Origin` is sent on CORS-mode fetches and on every non-GET/HEAD request,\n * but NOT on a plain cross-site GET (`<img>`, `<iframe>`, a navigation).\n * - `Sec-Fetch-Site` is sent by Chromium and Firefox on every request and is\n * the signal that covers exactly that gap; `same-origin` and `none` (a\n * user-typed URL) are ours, `cross-site`/`same-site` are not.\n * A request is trusted only when every signal it does carry says same-origin,\n * and at least one of them is present.\n */\nexport const isTrustedRequest = (headers: TrustHeaders): boolean => {\n const site = headers['sec-fetch-site'];\n if (site !== undefined) {\n if (site !== 'same-origin' && site !== 'none') return false;\n }\n const {origin, host} = headers;\n if (origin !== undefined && origin !== 'null') {\n try {\n if (new URL(origin).host !== host) return false;\n } catch {\n return false;\n }\n return true;\n }\n // No `Origin`: trust only when `Sec-Fetch-Site` vouched for it above.\n return site !== undefined;\n};\n"]}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/lib/http.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAaH;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAqB,EAAW,EAAE;IACjE,MAAM,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,IAAI,IAAI,KAAK,aAAa,IAAI,IAAI,KAAK,MAAM;YAAE,OAAO,KAAK,CAAC;IAC9D,CAAC;IACD,MAAM,EAAC,MAAM,EAAE,IAAI,EAAC,GAAG,OAAO,CAAC;IAC/B,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QAC9C,IAAI,CAAC;YACH,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,sEAAsE;IACtE,OAAO,IAAI,KAAK,SAAS,CAAC;AAC5B,CAAC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Headers the trust check looks at. Both the open-in-editor endpoint and the\n * timeline/inspector endpoints are local-only dev tooling: only the page the\n * dev server itself served may drive them.\n */\nexport interface TrustHeaders {\n origin?: string;\n host?: string;\n 'sec-fetch-site'?: string;\n}\n\n/**\n * True when the request demonstrably comes from the dev server's own page.\n *\n * Two independent signals, because neither is present on every request:\n * - `Origin` is sent on CORS-mode fetches and on every non-GET/HEAD request,\n * but NOT on a plain cross-site GET (`<img>`, `<iframe>`, a navigation).\n * - `Sec-Fetch-Site` is sent by Chromium and Firefox on every request and is\n * the signal that covers exactly that gap; `same-origin` and `none` (a\n * user-typed URL) are ours, `cross-site`/`same-site` are not.\n * A request is trusted only when every signal it does carry says same-origin,\n * and at least one of them is present.\n *\n * This does not stop DNS rebinding, where a hostile page reaches the server\n * under its own name and `Origin` and `Host` agree. Vite's\n * `server.allowedHosts` check does, and it runs before any plugin middleware,\n * so this doesn't repeat it (source-overlay_test pins that ordering).\n */\nexport const isTrustedRequest = (headers: TrustHeaders): boolean => {\n const site = headers['sec-fetch-site'];\n if (site !== undefined) {\n if (site !== 'same-origin' && site !== 'none') return false;\n }\n const {origin, host} = headers;\n if (origin !== undefined && origin !== 'null') {\n try {\n if (new URL(origin).host !== host) return false;\n } catch {\n return false;\n }\n return true;\n }\n // No `Origin`: trust only when `Sec-Fetch-Site` vouched for it above.\n return site !== undefined;\n};\n"]}
package/lib/options.d.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import type { SourceOverlayOptions } from './types.js';
7
7
  import type { FeatureSettings, SettingSources } from '../types/timeline.js';
8
+ import type { ChildStateMode } from './runtime/child-state.js';
8
9
  /**
9
10
  * On-page HMR feedback: a small pulsing indicator in the corner of the host
10
11
  * page that briefly animates on each HMR update, for at-a-glance feedback
@@ -34,11 +35,34 @@ export interface HmrOptions {
34
35
  * opt-in. Defaults to `false`.
35
36
  */
36
37
  reconnect?: boolean;
38
+ /**
39
+ * Rewrite native `#private` class members to stable `Symbol.for` keys in
40
+ * dev so classes using them can be hot-patched in place. This trades real
41
+ * privacy and brand checks for working HMR, in dev only; builds are never
42
+ * touched. Defaults to `true`.
43
+ */
44
+ privateFields?: boolean;
37
45
  /**
38
46
  * What to do when a component can't be hot-patched in place (e.g.
39
47
  * standard `accessor` decorators). Defaults to `'reload'`.
40
48
  */
41
49
  onIncompatible?: 'reload' | 'warn';
50
+ /**
51
+ * What happens to custom elements inside a template whose text a hot patch
52
+ * changed. lit-html clones fresh DOM for the edited template, so those
53
+ * elements are re-created.
54
+ *
55
+ * - `'reset'`: they start over from their defaults.
56
+ * - `'transfer'`: each new element takes the old one's reactive properties
57
+ * and `#private` state (keys the new template binds or sets as an
58
+ * attribute keep the template's value).
59
+ * - `'reuse'`: where the new element carries no bindings, the old element
60
+ * (identity, shadow DOM, controllers) is put back in its place; elsewhere
61
+ * as `'transfer'`.
62
+ *
63
+ * Defaults to `'transfer'`.
64
+ */
65
+ childState?: ChildStateMode;
42
66
  /**
43
67
  * The on-page update indicator. `true` enables it without a count; an
44
68
  * object configures it. Forced off when HMR itself is disabled. Defaults
@@ -106,7 +130,9 @@ export interface LitPluginOptions {
106
130
  export interface ResolvedOptions {
107
131
  hmrEnabled: boolean;
108
132
  reconnect: boolean;
133
+ privateFields: boolean;
109
134
  onIncompatible: 'reload' | 'warn';
135
+ childState: ChildStateMode;
110
136
  indicator: false | {
111
137
  count: boolean;
112
138
  };
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/lib/options.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EACV,eAAe,EAEf,cAAc,EACf,MAAM,sBAAsB,CAAC;AAG9B;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,cAAc,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAEnC;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAC;CAC3C;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,YAAY,CAAC;AASrE;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,GAAG,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IAE3B;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,oBAAoB,CAAC;IAE/C;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,QAAQ,GAAG,MAAM,CAAC;IAClC,SAAS,EAAE,KAAK,GAAG;QAAC,KAAK,EAAE,OAAO,CAAA;KAAC,CAAC;IACpC,aAAa,EAAE,KAAK,GAAG,oBAAoB,CAAC;IAC5C,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,aAAa,CAAC;IAC7B;;;OAGG;IACH,OAAO,EAAE,cAAc,CAAC;CACzB;AAED,8CAA8C;AAC9C,eAAO,MAAM,UAAU,eAAe,CAAC;AA6DvC;;;GAGG;AACH,eAAO,MAAM,cAAc,YAChB,gBAAgB,OACpB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC1B,eAiGF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,MAAO,eAAe,KAAG,eAqBtD,CAAC"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/lib/options.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EACV,eAAe,EAEf,cAAc,EACf,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,0BAA0B,CAAC;AAE7D;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,cAAc,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAEnC;;;;;;;;;;;;;;OAcG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;IAE5B;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAC;CAC3C;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,YAAY,CAAC;AASrE;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,GAAG,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IAE3B;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,oBAAoB,CAAC;IAE/C;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,QAAQ,GAAG,MAAM,CAAC;IAClC,UAAU,EAAE,cAAc,CAAC;IAC3B,SAAS,EAAE,KAAK,GAAG;QAAC,KAAK,EAAE,OAAO,CAAA;KAAC,CAAC;IACpC,aAAa,EAAE,KAAK,GAAG,oBAAoB,CAAC;IAC5C,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,aAAa,CAAC;IAC7B;;;OAGG;IACH,OAAO,EAAE,cAAc,CAAC;CACzB;AAED,8CAA8C;AAC9C,eAAO,MAAM,UAAU,eAAe,CAAC;AAmEvC;;;GAGG;AACH,eAAO,MAAM,cAAc,YAChB,gBAAgB,OACpB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC1B,eAkHF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,MAAO,eAAe,KAAG,eAsBtD,CAAC"}
package/lib/options.js CHANGED
@@ -8,6 +8,7 @@ const CSS_SHEET_BUILD_MODES = ['auto', 'url', 'inline', 'inline-raw'];
8
8
  /** Env var prefix consumed at config time. */
9
9
  export const ENV_PREFIX = 'LIT_PLUGIN';
10
10
  const ON_INCOMPATIBLE_MODES = ['reload', 'warn'];
11
+ const CHILD_STATE_MODES = ['reset', 'transfer', 'reuse'];
11
12
  /** Parse a boolean-ish env string; `undefined` when unset/unrecognized. */
12
13
  const envBool = (v) =>
13
14
  v === 'true' || v === '1'
@@ -64,6 +65,11 @@ export const resolveOptions = (options, env) => {
64
65
  envBool(env[`${ENV_PREFIX}_HMR_RECONNECT`]),
65
66
  false
66
67
  );
68
+ const privateFields = pick(
69
+ hmrObj?.privateFields,
70
+ envBool(env[`${ENV_PREFIX}_HMR_PRIVATE_FIELDS`]),
71
+ true
72
+ );
67
73
  const onIncompatible = pick(
68
74
  hmrObj?.onIncompatible,
69
75
  envEnum(
@@ -73,6 +79,15 @@ export const resolveOptions = (options, env) => {
73
79
  ),
74
80
  'reload'
75
81
  );
82
+ const childState = pick(
83
+ hmrObj?.childState,
84
+ envEnum(
85
+ env[`${ENV_PREFIX}_HMR_CHILD_STATE`],
86
+ CHILD_STATE_MODES,
87
+ `${ENV_PREFIX}_HMR_CHILD_STATE`
88
+ ),
89
+ 'transfer'
90
+ );
76
91
  const ind = hmrObj?.indicator;
77
92
  const indObj = typeof ind === 'object' ? ind : undefined;
78
93
  const indEnabled = pick(
@@ -91,6 +106,7 @@ export const resolveOptions = (options, env) => {
91
106
  const sources = {
92
107
  hmrReconnect: reconnect.source,
93
108
  hmrOnIncompatible: onIncompatible.source,
109
+ hmrChildState: childState.source,
94
110
  hmrIndicatorVisible: indEnabled.source,
95
111
  hmrIndicatorCount: indCount.source,
96
112
  };
@@ -136,7 +152,9 @@ export const resolveOptions = (options, env) => {
136
152
  return {
137
153
  hmrEnabled,
138
154
  reconnect: reconnect.value,
155
+ privateFields: privateFields.value,
139
156
  onIncompatible: onIncompatible.value,
157
+ childState: childState.value,
140
158
  indicator,
141
159
  sourceOverlay,
142
160
  timeline,
@@ -158,6 +176,7 @@ export const toFeatureSettings = (r) => {
158
176
  enabled: r.hmrEnabled,
159
177
  reconnect: r.reconnect,
160
178
  onIncompatible: r.onIncompatible,
179
+ childState: r.childState,
161
180
  indicatorEnabled: r.indicator !== false,
162
181
  indicatorCount: r.indicator !== false && r.indicator.count,
163
182
  },
@@ -1 +1 @@
1
- {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/lib/options.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport type {SourceOverlayOptions} from './types.js';\nimport type {\n FeatureSettings,\n SettingSource,\n SettingSources,\n} from '../types/timeline.js';\nimport {BUILTIN_EDITORS} from './runtime/source-overlay/editors.js';\n\n/**\n * On-page HMR feedback: a small pulsing indicator in the corner of the host\n * page that briefly animates on each HMR update, for at-a-glance feedback\n * without watching the console.\n */\nexport interface HmrIndicatorOptions {\n /** Inject the indicator element. Defaults to `true` (when HMR is enabled). */\n enabled?: boolean;\n\n /**\n * Show a cumulative update count next to the dot (idle opacity 0.5 instead\n * of fully transparent). Defaults to `false`.\n */\n count?: boolean;\n}\n\n/**\n * HMR for Lit component classes and its on-page feedback.\n */\nexport interface HmrOptions {\n /**\n * Enable in-place HMR for Lit component classes. When `false`, the plugin\n * skips all HMR transforms and runtime injection. Defaults to `true`.\n */\n enabled?: boolean;\n\n /**\n * Cycle `disconnectedCallback()`/`connectedCallback()` on live instances\n * after a hot patch. Interning makes this mostly unnecessary, so it's\n * opt-in. Defaults to `false`.\n */\n reconnect?: boolean;\n\n /**\n * What to do when a component can't be hot-patched in place (e.g.\n * standard `accessor` decorators). Defaults to `'reload'`.\n */\n onIncompatible?: 'reload' | 'warn';\n\n /**\n * The on-page update indicator. `true` enables it without a count; an\n * object configures it. Forced off when HMR itself is disabled. Defaults\n * to enabled (without a count).\n */\n indicator?: boolean | HmrIndicatorOptions;\n}\n\n/**\n * What a `?css-sheet` import compiles to under `vite build`.\n *\n * - `'url'`: fetch-backed sheet over the emitted `.css` asset.\n * - `'inline'`: css text embedded in the JS chunk, processed by the css\n * pipeline (`?inline`).\n * - `'inline-raw'`: css text embedded verbatim, skipping the css pipeline\n * (`?raw`).\n * - `'auto'`: `'inline'` when `build.lib` is set, `'url'` otherwise.\n */\nexport type CssSheetBuild = 'auto' | 'url' | 'inline' | 'inline-raw';\n\nconst CSS_SHEET_BUILD_MODES: readonly CssSheetBuild[] = [\n 'auto',\n 'url',\n 'inline',\n 'inline-raw',\n];\n\n/**\n * Options for the Lit Vite plugin.\n *\n * Every option also resolves from environment variables (and `.env` files)\n * with the `LIT_PLUGIN` prefix — e.g. `LIT_PLUGIN_HMR_INDICATOR=true`. Options\n * passed here take precedence over env vars, which take precedence over the\n * built-in defaults.\n */\nexport interface LitPluginOptions {\n /**\n * HMR for Lit components and its on-page feedback. `true`/`false` toggles\n * the whole feature (patching and indicator); an object configures it.\n * Defaults to enabled.\n */\n hmr?: boolean | HmrOptions;\n\n /**\n * Dev-only click-to-open-in-IDE inspector for Lit custom elements.\n * Toggle with Ctrl+Shift+S (configurable via `key`). Defaults to `false`.\n */\n sourceOverlay?: boolean | SourceOverlayOptions;\n\n /**\n * Vite DevTools Timeline panel — a Vue DevTools–style layered event stream\n * for Lit lifecycle, render, mouse, and keyboard events.\n *\n * Requires `@vitejs/devtools` in the Vite config and the `@vitejs/devtools`\n * Vite plugin (`DevTools()`) to be active. Defaults to `false` while\n * experimental.\n *\n * `true` enables all built-in layers with defaults.\n */\n timeline?: boolean;\n\n /**\n * What a `?css-sheet` import compiles to under `vite build`.\n * - `'url'`: fetch-backed sheet over the emitted `.css` asset\n * - `'inline'`: css text embedded in the JS chunk, processed by the css\n * pipeline (`?inline`)\n * - `'inline-raw'`: css text embedded verbatim, skipping the css pipeline\n * (`?raw`)\n * - `'auto'`: `'inline'` when `build.lib` is set, `'url'` otherwise\n *\n * Dev is always the fetch-backed HMR form regardless of this setting.\n * Defaults to `'auto'`.\n */\n cssSheetBuild?: CssSheetBuild;\n}\n\n/** Plugin options after merging explicit options, env vars, and defaults. */\nexport interface ResolvedOptions {\n hmrEnabled: boolean;\n reconnect: boolean;\n onIncompatible: 'reload' | 'warn';\n indicator: false | {count: boolean};\n sourceOverlay: false | SourceOverlayOptions;\n timeline: boolean;\n cssSheetBuild: CssSheetBuild;\n /**\n * Which layer each panel-visible setting came from. Source-overlay keys are\n * present only when the overlay is enabled.\n */\n sources: SettingSources;\n}\n\n/** Env var prefix consumed at config time. */\nexport const ENV_PREFIX = 'LIT_PLUGIN';\n\nconst ON_INCOMPATIBLE_MODES: readonly ('reload' | 'warn')[] = [\n 'reload',\n 'warn',\n];\n\n/** Parse a boolean-ish env string; `undefined` when unset/unrecognized. */\nconst envBool = (v: string | undefined): boolean | undefined =>\n v === 'true' || v === '1'\n ? true\n : v === 'false' || v === '0'\n ? false\n : undefined;\n\n/** Parse a numeric env string; `undefined` when unset/non-numeric. */\nconst envNum = (v: string | undefined): number | undefined => {\n if (v === undefined || v === '') return undefined;\n const n = Number(v);\n return Number.isNaN(n) ? undefined : n;\n};\n\n/**\n * Parse a string against a closed set of values; `undefined` (with a warning)\n * when set to something outside it, so a typo falls back to the default\n * instead of silently disabling a feature.\n */\nconst envEnum = <T extends string>(\n v: string | undefined,\n allowed: readonly T[],\n source: string\n): T | undefined => {\n if (v === undefined || v === '') return undefined;\n if ((allowed as readonly string[]).includes(v)) return v as T;\n console.warn(\n `[lit-plugin] ignoring ${source}=${JSON.stringify(v)}; expected one of ` +\n allowed.map((a) => JSON.stringify(a)).join(', ')\n );\n return undefined;\n};\n\n/** Keys a `LIT_PLUGIN_SOURCE_OVERLAY_EDITOR` value may name. */\nconst EDITOR_KEYS: readonly string[] = Object.keys(BUILTIN_EDITORS);\n\n/** Which layer supplied a value: the first of option, env that is defined. */\nconst sourceOf = (option: unknown, env: unknown): SettingSource =>\n option !== undefined ? 'option' : env !== undefined ? 'env' : 'default';\n\n/**\n * Take the first defined of an explicit option and an env value, else the\n * default, and record which layer won.\n */\nconst pick = <T>(\n option: T | undefined,\n env: T | undefined,\n fallback: T\n): {value: T; source: SettingSource} => ({\n value: option ?? env ?? fallback,\n source: sourceOf(option, env),\n});\n\n/**\n * Merge explicit options over env vars over defaults (in that precedence) into\n * the flat shape the plugin hooks consume.\n */\nexport const resolveOptions = (\n options: LitPluginOptions,\n env: Record<string, string>\n): ResolvedOptions => {\n const hmr = options.hmr;\n const hmrObj = typeof hmr === 'object' ? hmr : undefined;\n const hmrEnabled =\n (typeof hmr === 'boolean' ? hmr : hmrObj?.enabled) ??\n envBool(env[`${ENV_PREFIX}_HMR`]) ??\n true;\n const reconnect = pick(\n hmrObj?.reconnect,\n envBool(env[`${ENV_PREFIX}_HMR_RECONNECT`]),\n false\n );\n const onIncompatible = pick<'reload' | 'warn'>(\n hmrObj?.onIncompatible,\n envEnum(\n env[`${ENV_PREFIX}_HMR_ON_INCOMPATIBLE`],\n ON_INCOMPATIBLE_MODES,\n `${ENV_PREFIX}_HMR_ON_INCOMPATIBLE`\n ),\n 'reload'\n );\n\n const ind = hmrObj?.indicator;\n const indObj = typeof ind === 'object' ? ind : undefined;\n const indEnabled = pick(\n typeof ind === 'boolean' ? ind : indObj?.enabled,\n envBool(env[`${ENV_PREFIX}_HMR_INDICATOR`]),\n true\n );\n const indCount = pick(\n indObj?.count,\n envBool(env[`${ENV_PREFIX}_HMR_INDICATOR_COUNT`]),\n false\n );\n // The indicator is meaningless without HMR, so it follows the master toggle.\n const indicator =\n hmrEnabled && indEnabled.value ? {count: indCount.value} : false;\n\n const sources: SettingSources = {\n hmrReconnect: reconnect.source,\n hmrOnIncompatible: onIncompatible.source,\n hmrIndicatorVisible: indEnabled.source,\n hmrIndicatorCount: indCount.source,\n };\n\n const so = options.sourceOverlay;\n const soExplicit =\n typeof so === 'boolean' ? so : so === undefined ? undefined : true;\n const soEnabled =\n soExplicit ?? envBool(env[`${ENV_PREFIX}_SOURCE_OVERLAY`]) ?? false;\n let sourceOverlay: false | SourceOverlayOptions = false;\n if (soEnabled) {\n const base: SourceOverlayOptions = typeof so === 'object' ? {...so} : {};\n // Defaults for these are applied later (toFeatureSettings / the runtime),\n // so only option-vs-env is decided here; neither set means 'default'.\n const envKey = env[`${ENV_PREFIX}_SOURCE_OVERLAY_KEY`] || undefined;\n const envThrottle = envNum(env[`${ENV_PREFIX}_SOURCE_OVERLAY_THROTTLE_MS`]);\n // Only read (and warn about) the env editor when no option supplies one.\n const envEditor =\n base.editor === undefined\n ? envEnum(\n env[`${ENV_PREFIX}_SOURCE_OVERLAY_EDITOR`],\n EDITOR_KEYS,\n `${ENV_PREFIX}_SOURCE_OVERLAY_EDITOR`\n )\n : undefined;\n sources.sourceOverlayKey = sourceOf(base.key, envKey);\n sources.sourceOverlayEditor = sourceOf(base.editor, envEditor);\n sources.sourceOverlayThrottleMs = sourceOf(base.throttleMs, envThrottle);\n base.key ??= envKey;\n base.editor ??= envEditor;\n base.throttleMs ??= envThrottle;\n sourceOverlay = base;\n }\n\n const timeline =\n options.timeline ?? envBool(env[`${ENV_PREFIX}_TIMELINE`]) ?? false;\n\n const cssSheetBuild =\n envEnum(options.cssSheetBuild, CSS_SHEET_BUILD_MODES, 'cssSheetBuild') ??\n envEnum(\n env[`${ENV_PREFIX}_CSS_SHEET_BUILD`],\n CSS_SHEET_BUILD_MODES,\n `${ENV_PREFIX}_CSS_SHEET_BUILD`\n ) ??\n 'auto';\n\n return {\n hmrEnabled,\n reconnect: reconnect.value,\n onIncompatible: onIncompatible.value,\n indicator,\n sourceOverlay,\n timeline,\n cssSheetBuild,\n sources,\n };\n};\n\n/**\n * Flattens resolved options into the JSON-serializable shape the panel's\n * Settings tab consumes (callback options like `exclude`/`onSelect` dropped;\n * a custom editor object reported as `\"custom\"`). Default key/editor/throttle\n * are applied here so the panel shows the effective values the runtime uses.\n */\nexport const toFeatureSettings = (r: ResolvedOptions): FeatureSettings => {\n const so = r.sourceOverlay;\n const editor = so === false ? undefined : so.editor;\n return {\n hmr: {\n enabled: r.hmrEnabled,\n reconnect: r.reconnect,\n onIncompatible: r.onIncompatible,\n indicatorEnabled: r.indicator !== false,\n indicatorCount: r.indicator !== false && r.indicator.count,\n },\n sourceOverlay: {\n enabled: so !== false,\n key: (so === false ? undefined : so.key) ?? 's',\n editor:\n typeof editor === 'string' ? editor : editor ? 'custom' : 'vscode',\n throttleMs: (so === false ? undefined : so.throttleMs) ?? 50,\n },\n timeline: r.timeline,\n sources: {...r.sources},\n };\n};\n"]}
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/lib/options.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport type {SourceOverlayOptions} from './types.js';\nimport type {\n FeatureSettings,\n SettingSource,\n SettingSources,\n} from '../types/timeline.js';\nimport {BUILTIN_EDITORS} from './runtime/source-overlay/editors.js';\nimport type {ChildStateMode} from './runtime/child-state.js';\n\n/**\n * On-page HMR feedback: a small pulsing indicator in the corner of the host\n * page that briefly animates on each HMR update, for at-a-glance feedback\n * without watching the console.\n */\nexport interface HmrIndicatorOptions {\n /** Inject the indicator element. Defaults to `true` (when HMR is enabled). */\n enabled?: boolean;\n\n /**\n * Show a cumulative update count next to the dot (idle opacity 0.5 instead\n * of fully transparent). Defaults to `false`.\n */\n count?: boolean;\n}\n\n/**\n * HMR for Lit component classes and its on-page feedback.\n */\nexport interface HmrOptions {\n /**\n * Enable in-place HMR for Lit component classes. When `false`, the plugin\n * skips all HMR transforms and runtime injection. Defaults to `true`.\n */\n enabled?: boolean;\n\n /**\n * Cycle `disconnectedCallback()`/`connectedCallback()` on live instances\n * after a hot patch. Interning makes this mostly unnecessary, so it's\n * opt-in. Defaults to `false`.\n */\n reconnect?: boolean;\n\n /**\n * Rewrite native `#private` class members to stable `Symbol.for` keys in\n * dev so classes using them can be hot-patched in place. This trades real\n * privacy and brand checks for working HMR, in dev only; builds are never\n * touched. Defaults to `true`.\n */\n privateFields?: boolean;\n\n /**\n * What to do when a component can't be hot-patched in place (e.g.\n * standard `accessor` decorators). Defaults to `'reload'`.\n */\n onIncompatible?: 'reload' | 'warn';\n\n /**\n * What happens to custom elements inside a template whose text a hot patch\n * changed. lit-html clones fresh DOM for the edited template, so those\n * elements are re-created.\n *\n * - `'reset'`: they start over from their defaults.\n * - `'transfer'`: each new element takes the old one's reactive properties\n * and `#private` state (keys the new template binds or sets as an\n * attribute keep the template's value).\n * - `'reuse'`: where the new element carries no bindings, the old element\n * (identity, shadow DOM, controllers) is put back in its place; elsewhere\n * as `'transfer'`.\n *\n * Defaults to `'transfer'`.\n */\n childState?: ChildStateMode;\n\n /**\n * The on-page update indicator. `true` enables it without a count; an\n * object configures it. Forced off when HMR itself is disabled. Defaults\n * to enabled (without a count).\n */\n indicator?: boolean | HmrIndicatorOptions;\n}\n\n/**\n * What a `?css-sheet` import compiles to under `vite build`.\n *\n * - `'url'`: fetch-backed sheet over the emitted `.css` asset.\n * - `'inline'`: css text embedded in the JS chunk, processed by the css\n * pipeline (`?inline`).\n * - `'inline-raw'`: css text embedded verbatim, skipping the css pipeline\n * (`?raw`).\n * - `'auto'`: `'inline'` when `build.lib` is set, `'url'` otherwise.\n */\nexport type CssSheetBuild = 'auto' | 'url' | 'inline' | 'inline-raw';\n\nconst CSS_SHEET_BUILD_MODES: readonly CssSheetBuild[] = [\n 'auto',\n 'url',\n 'inline',\n 'inline-raw',\n];\n\n/**\n * Options for the Lit Vite plugin.\n *\n * Every option also resolves from environment variables (and `.env` files)\n * with the `LIT_PLUGIN` prefix — e.g. `LIT_PLUGIN_HMR_INDICATOR=true`. Options\n * passed here take precedence over env vars, which take precedence over the\n * built-in defaults.\n */\nexport interface LitPluginOptions {\n /**\n * HMR for Lit components and its on-page feedback. `true`/`false` toggles\n * the whole feature (patching and indicator); an object configures it.\n * Defaults to enabled.\n */\n hmr?: boolean | HmrOptions;\n\n /**\n * Dev-only click-to-open-in-IDE inspector for Lit custom elements.\n * Toggle with Ctrl+Shift+S (configurable via `key`). Defaults to `false`.\n */\n sourceOverlay?: boolean | SourceOverlayOptions;\n\n /**\n * Vite DevTools Timeline panel — a Vue DevTools–style layered event stream\n * for Lit lifecycle, render, mouse, and keyboard events.\n *\n * Requires `@vitejs/devtools` in the Vite config and the `@vitejs/devtools`\n * Vite plugin (`DevTools()`) to be active. Defaults to `false` while\n * experimental.\n *\n * `true` enables all built-in layers with defaults.\n */\n timeline?: boolean;\n\n /**\n * What a `?css-sheet` import compiles to under `vite build`.\n * - `'url'`: fetch-backed sheet over the emitted `.css` asset\n * - `'inline'`: css text embedded in the JS chunk, processed by the css\n * pipeline (`?inline`)\n * - `'inline-raw'`: css text embedded verbatim, skipping the css pipeline\n * (`?raw`)\n * - `'auto'`: `'inline'` when `build.lib` is set, `'url'` otherwise\n *\n * Dev is always the fetch-backed HMR form regardless of this setting.\n * Defaults to `'auto'`.\n */\n cssSheetBuild?: CssSheetBuild;\n}\n\n/** Plugin options after merging explicit options, env vars, and defaults. */\nexport interface ResolvedOptions {\n hmrEnabled: boolean;\n reconnect: boolean;\n privateFields: boolean;\n onIncompatible: 'reload' | 'warn';\n childState: ChildStateMode;\n indicator: false | {count: boolean};\n sourceOverlay: false | SourceOverlayOptions;\n timeline: boolean;\n cssSheetBuild: CssSheetBuild;\n /**\n * Which layer each panel-visible setting came from. Source-overlay keys are\n * present only when the overlay is enabled.\n */\n sources: SettingSources;\n}\n\n/** Env var prefix consumed at config time. */\nexport const ENV_PREFIX = 'LIT_PLUGIN';\n\nconst ON_INCOMPATIBLE_MODES: readonly ('reload' | 'warn')[] = [\n 'reload',\n 'warn',\n];\n\nconst CHILD_STATE_MODES: readonly ChildStateMode[] = [\n 'reset',\n 'transfer',\n 'reuse',\n];\n\n/** Parse a boolean-ish env string; `undefined` when unset/unrecognized. */\nconst envBool = (v: string | undefined): boolean | undefined =>\n v === 'true' || v === '1'\n ? true\n : v === 'false' || v === '0'\n ? false\n : undefined;\n\n/** Parse a numeric env string; `undefined` when unset/non-numeric. */\nconst envNum = (v: string | undefined): number | undefined => {\n if (v === undefined || v === '') return undefined;\n const n = Number(v);\n return Number.isNaN(n) ? undefined : n;\n};\n\n/**\n * Parse a string against a closed set of values; `undefined` (with a warning)\n * when set to something outside it, so a typo falls back to the default\n * instead of silently disabling a feature.\n */\nconst envEnum = <T extends string>(\n v: string | undefined,\n allowed: readonly T[],\n source: string\n): T | undefined => {\n if (v === undefined || v === '') return undefined;\n if ((allowed as readonly string[]).includes(v)) return v as T;\n console.warn(\n `[lit-plugin] ignoring ${source}=${JSON.stringify(v)}; expected one of ` +\n allowed.map((a) => JSON.stringify(a)).join(', ')\n );\n return undefined;\n};\n\n/** Keys a `LIT_PLUGIN_SOURCE_OVERLAY_EDITOR` value may name. */\nconst EDITOR_KEYS: readonly string[] = Object.keys(BUILTIN_EDITORS);\n\n/** Which layer supplied a value: the first of option, env that is defined. */\nconst sourceOf = (option: unknown, env: unknown): SettingSource =>\n option !== undefined ? 'option' : env !== undefined ? 'env' : 'default';\n\n/**\n * Take the first defined of an explicit option and an env value, else the\n * default, and record which layer won.\n */\nconst pick = <T>(\n option: T | undefined,\n env: T | undefined,\n fallback: T\n): {value: T; source: SettingSource} => ({\n value: option ?? env ?? fallback,\n source: sourceOf(option, env),\n});\n\n/**\n * Merge explicit options over env vars over defaults (in that precedence) into\n * the flat shape the plugin hooks consume.\n */\nexport const resolveOptions = (\n options: LitPluginOptions,\n env: Record<string, string>\n): ResolvedOptions => {\n const hmr = options.hmr;\n const hmrObj = typeof hmr === 'object' ? hmr : undefined;\n const hmrEnabled =\n (typeof hmr === 'boolean' ? hmr : hmrObj?.enabled) ??\n envBool(env[`${ENV_PREFIX}_HMR`]) ??\n true;\n const reconnect = pick(\n hmrObj?.reconnect,\n envBool(env[`${ENV_PREFIX}_HMR_RECONNECT`]),\n false\n );\n const privateFields = pick(\n hmrObj?.privateFields,\n envBool(env[`${ENV_PREFIX}_HMR_PRIVATE_FIELDS`]),\n true\n );\n const onIncompatible = pick<'reload' | 'warn'>(\n hmrObj?.onIncompatible,\n envEnum(\n env[`${ENV_PREFIX}_HMR_ON_INCOMPATIBLE`],\n ON_INCOMPATIBLE_MODES,\n `${ENV_PREFIX}_HMR_ON_INCOMPATIBLE`\n ),\n 'reload'\n );\n const childState = pick<ChildStateMode>(\n hmrObj?.childState,\n envEnum(\n env[`${ENV_PREFIX}_HMR_CHILD_STATE`],\n CHILD_STATE_MODES,\n `${ENV_PREFIX}_HMR_CHILD_STATE`\n ),\n 'transfer'\n );\n\n const ind = hmrObj?.indicator;\n const indObj = typeof ind === 'object' ? ind : undefined;\n const indEnabled = pick(\n typeof ind === 'boolean' ? ind : indObj?.enabled,\n envBool(env[`${ENV_PREFIX}_HMR_INDICATOR`]),\n true\n );\n const indCount = pick(\n indObj?.count,\n envBool(env[`${ENV_PREFIX}_HMR_INDICATOR_COUNT`]),\n false\n );\n // The indicator is meaningless without HMR, so it follows the master toggle.\n const indicator =\n hmrEnabled && indEnabled.value ? {count: indCount.value} : false;\n\n const sources: SettingSources = {\n hmrReconnect: reconnect.source,\n hmrOnIncompatible: onIncompatible.source,\n hmrChildState: childState.source,\n hmrIndicatorVisible: indEnabled.source,\n hmrIndicatorCount: indCount.source,\n };\n\n const so = options.sourceOverlay;\n const soExplicit =\n typeof so === 'boolean' ? so : so === undefined ? undefined : true;\n const soEnabled =\n soExplicit ?? envBool(env[`${ENV_PREFIX}_SOURCE_OVERLAY`]) ?? false;\n let sourceOverlay: false | SourceOverlayOptions = false;\n if (soEnabled) {\n const base: SourceOverlayOptions = typeof so === 'object' ? {...so} : {};\n // Defaults for these are applied later (toFeatureSettings / the runtime),\n // so only option-vs-env is decided here; neither set means 'default'.\n const envKey = env[`${ENV_PREFIX}_SOURCE_OVERLAY_KEY`] || undefined;\n const envThrottle = envNum(env[`${ENV_PREFIX}_SOURCE_OVERLAY_THROTTLE_MS`]);\n // Only read (and warn about) the env editor when no option supplies one.\n const envEditor =\n base.editor === undefined\n ? envEnum(\n env[`${ENV_PREFIX}_SOURCE_OVERLAY_EDITOR`],\n EDITOR_KEYS,\n `${ENV_PREFIX}_SOURCE_OVERLAY_EDITOR`\n )\n : undefined;\n sources.sourceOverlayKey = sourceOf(base.key, envKey);\n sources.sourceOverlayEditor = sourceOf(base.editor, envEditor);\n sources.sourceOverlayThrottleMs = sourceOf(base.throttleMs, envThrottle);\n base.key ??= envKey;\n base.editor ??= envEditor;\n base.throttleMs ??= envThrottle;\n sourceOverlay = base;\n }\n\n const timeline =\n options.timeline ?? envBool(env[`${ENV_PREFIX}_TIMELINE`]) ?? false;\n\n const cssSheetBuild =\n envEnum(options.cssSheetBuild, CSS_SHEET_BUILD_MODES, 'cssSheetBuild') ??\n envEnum(\n env[`${ENV_PREFIX}_CSS_SHEET_BUILD`],\n CSS_SHEET_BUILD_MODES,\n `${ENV_PREFIX}_CSS_SHEET_BUILD`\n ) ??\n 'auto';\n\n return {\n hmrEnabled,\n reconnect: reconnect.value,\n privateFields: privateFields.value,\n onIncompatible: onIncompatible.value,\n childState: childState.value,\n indicator,\n sourceOverlay,\n timeline,\n cssSheetBuild,\n sources,\n };\n};\n\n/**\n * Flattens resolved options into the JSON-serializable shape the panel's\n * Settings tab consumes (callback options like `exclude`/`onSelect` dropped;\n * a custom editor object reported as `\"custom\"`). Default key/editor/throttle\n * are applied here so the panel shows the effective values the runtime uses.\n */\nexport const toFeatureSettings = (r: ResolvedOptions): FeatureSettings => {\n const so = r.sourceOverlay;\n const editor = so === false ? undefined : so.editor;\n return {\n hmr: {\n enabled: r.hmrEnabled,\n reconnect: r.reconnect,\n onIncompatible: r.onIncompatible,\n childState: r.childState,\n indicatorEnabled: r.indicator !== false,\n indicatorCount: r.indicator !== false && r.indicator.count,\n },\n sourceOverlay: {\n enabled: so !== false,\n key: (so === false ? undefined : so.key) ?? 's',\n editor:\n typeof editor === 'string' ? editor : editor ? 'custom' : 'vscode',\n throttleMs: (so === false ? undefined : so.throttleMs) ?? 50,\n },\n timeline: r.timeline,\n sources: {...r.sources},\n };\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/lib/plugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAU,KAAK,MAAM,EAAC,MAAM,MAAM,CAAC;AAO1C,OAAO,EAEL,KAAK,gBAAgB,EAItB,MAAM,cAAc,CAAC;AAUtB,OAAO,EAAC,4BAA4B,EAAC,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAC,aAAa,EAAC,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAC,kBAAkB,EAAC,MAAM,+BAA+B,CAAC;AACjE,YAAY,EACV,mBAAmB,EACnB,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAC,cAAc,EAAC,MAAM,cAAc,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,SAAS,aAAa,gBAAgB,KAAQ,MAAM,EAuRhE,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/lib/plugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAU,KAAK,MAAM,EAAC,MAAM,MAAM,CAAC;AAO1C,OAAO,EAEL,KAAK,gBAAgB,EAItB,MAAM,cAAc,CAAC;AAWtB,OAAO,EAAC,4BAA4B,EAAC,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAC,aAAa,EAAC,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAC,kBAAkB,EAAC,MAAM,+BAA+B,CAAC;AACjE,YAAY,EACV,mBAAmB,EACnB,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAC,cAAc,EAAC,MAAM,cAAc,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,SAAS,aAAa,gBAAgB,KAAQ,MAAM,EAyRhE,CAAC"}
package/lib/plugin.js CHANGED
@@ -19,6 +19,7 @@ import {
19
19
  import {litCssQueries} from './plugins/css-queries.js';
20
20
  import {litTimelineVirtual} from './plugins/timeline-virtual.js';
21
21
  import {litCssLiterals} from './plugins/css-literals.js';
22
+ import {litPrivateFields} from './plugins/private-fields.js';
22
23
  import {resolveRuntimeModule, JS_FILE_RE} from './plugins/shared.js';
23
24
  export {createOpenInEditorMiddleware} from './plugins/open-in-editor.js';
24
25
  export {litCssQueries} from './plugins/css-queries.js';
@@ -179,6 +180,7 @@ export const litPlugin = (options = {}) => {
179
180
  const runtimeOptions = {
180
181
  reconnect: resolved.reconnect,
181
182
  onIncompatible: resolved.onIncompatible,
183
+ childState: resolved.childState,
182
184
  };
183
185
  return {
184
186
  code:
@@ -274,6 +276,7 @@ export const litPlugin = (options = {}) => {
274
276
  litCssQueries(() => resolved.cssSheetBuild),
275
277
  litTimelineVirtual(() => resolved.timeline),
276
278
  litCssLiterals(),
279
+ litPrivateFields(() => resolved.hmrEnabled && resolved.privateFields),
277
280
  sourceOverlayPlugin,
278
281
  hmr,
279
282
  ];