text: // @ts-check
  /* eslint-disable consistent-return, global-require */
  
  const preambleCode = `
  // taken from: https://github.com/open-wc/open-wc/blob/master/packages/dev-server-hmr/src/wcHmrRuntime.js
  
  const proxiesForKeys = new Map();
  const keysForClasses = new Map();
  
  function trackConnectedElements(hmrClass) {
    const connectedElements = new Set();
    const originalCb = hmrClass.prototype.connectedCallback;
  
    // eslint-disable-next-line no-param-reassign
    hmrClass.prototype.connectedCallback = function connectedCallback(...args) {
      if (originalCb) {
        originalCb.call(this, ...args);
      }
      connectedElements.add(this);
    };
  
    const originalDcb = hmrClass.prototype.disconnectedCallback;
    // eslint-disable-next-line no-param-reassign
    hmrClass.prototype.disconnectedCallback = function disconnectedCallback(
      ...args
    ) {
      if (originalDcb) {
        originalDcb.call(this, ...args);
      }
      connectedElements.delete(this);
    };
    return connectedElements;
  }
  
  const proxyMethods = [
    'construct',
    'defineProperty',
    'deleteProperty',
    'getOwnPropertyDescriptor',
    'getPrototypeOf',
    'setPrototypeOf',
    'isExtensible',
    'ownKeys',
    'preventExtensions',
    'has',
    'get',
    'set',
  ];
  
  /**
   * Creates a proxy for the given target, and fowards any calls to the most up to the latest
   * version of the target. (ex. the latest hot replaced class).
   */
  function createProxy(originalTarget, getCurrentTarget) {
    const proxyHandler = {};
    for (const method of proxyMethods) {
      proxyHandler[method] = (_, ...args) => {
        if (method === 'get' && args[0] === 'prototype') {
          // prototype must always return original target value
          return Reflect[method](_, ...args);
        }
        return Reflect[method](getCurrentTarget(), ...args);
      };
    }
    return new Proxy(originalTarget, proxyHandler);
  }
  
  /**
   * Replaces all prototypes in the inheritance chain with a proxy
   * that references the latest implementation
   */
  function replacePrototypesWithProxies(instance) {
    let previous = instance;
    let proto = Object.getPrototypeOf(instance);
  
    while (proto && proto.constructor !== HTMLElement) {
      const key = keysForClasses.get(proto.constructor);
      if (key) {
        // this is a prototype that might be hot-replaced later
        const getCurrentProto = () =>
          proxiesForKeys.get(key).currentClass.prototype;
        Object.setPrototypeOf(previous, createProxy(proto, getCurrentProto));
      }
  
      previous = proto;
      proto = Object.getPrototypeOf(proto);
    }
  }
  
  export class WebComponentHmr extends HTMLElement {
    constructor(...args) {
      super(...args);
      const key = keysForClasses.get(this.constructor);
      // check if the constructor is registered
      if (key) {
        const p = proxiesForKeys.get(key);
        // replace the constructor with a proxy that references the latest implementation of this class
        this.constructor = p.currentProxy;
      }
      // replace prototype chain with a proxy to the latest prototype implementation
      replacePrototypesWithProxies(this);
    }
  }
  
  window.WebComponentHmr = WebComponentHmr;
  
  /**
   * Injects the WebComponentHmr class into the inheritance chain
   */
  function injectInheritsHmrClass(clazz) {
    let parent = clazz;
    let proto = Object.getPrototypeOf(clazz);
    // walk prototypes until we reach HTMLElement
    while (proto && proto !== HTMLElement) {
      parent = proto;
      proto = Object.getPrototypeOf(proto);
    }
  
    if (proto !== HTMLElement) {
      // not a web component
      return;
    }
    if (parent === WebComponentHmr) {
      // class already inherits WebComponentHmr
      return;
    }
    Object.setPrototypeOf(parent, WebComponentHmr);
  }
  
  /**
   * Registers a web component class. Triggers a hot replacement if the
   * class was already registered before.
   */
  export function register(key, clazz) {
    const existing = proxiesForKeys.get(key);
    if (!existing) {
      // this class was not yet registered,
  
      // create a proxy that will forward to the latest implementation
      const proxy = createProxy(
        clazz,
        () => proxiesForKeys.get(key).currentClass,
      );
      // inject a HMR class into the inheritance chain
      injectInheritsHmrClass(clazz);
      // keep track of all connected elements for this class
      const connectedElements = trackConnectedElements(clazz);
  
      proxiesForKeys.set(key, {
        originalProxy: proxy,
        currentProxy: proxy,
        originalClass: clazz,
        currentClass: clazz,
        connectedElements,
      });
      keysForClasses.set(clazz, key);
      return proxy;
    }
    // class was already registered before
  
    // register new class, all calls will be proxied to this class
    const previousProxy = existing.currentProxy;
    const currentProxy = createProxy(
      clazz,
      () => proxiesForKeys.get(key).currentClass,
    );
    existing.currentClass = clazz;
    existing.currentProxy = currentProxy;
  
    Promise.resolve().then(() => {
      // call optional HMR on the class if they exist, after next microtask to ensure
      // module bodies have executed fully
      if (clazz.hotReplacedCallback) {
        try {
          clazz.hotReplacedCallback();
        } catch (error) {
          console.error(error);
        }
      }
  
      for (const element of existing.connectedElements) {
        if (element.constructor === previousProxy) {
          // we need to update the constructor of the element to match to newly created proxy
          // but we should only do this for elements that was directly created with this class
          // and not for elements that extend this
          element.constructor = currentProxy;
        }
  
        if (element.hotReplacedCallback) {
          try {
            element.hotReplacedCallback();
          } catch (error) {
            console.error(error);
          }
        }
      }
    });
  
    // the original proxy already forwards to the new class but we're return a new proxy
    // because access to 'prototype' must return the original value and we need to be able to
    // manipulate the prototype on the new class
    return currentProxy;
  }
  
  // override global define to allow double registrations
  const originalDefine = window.customElements.define;
  window.customElements.define = (tagName, classObj, ...rest) => {
    register(tagName, classObj);
  
    if (!window.customElements.get(tagName)) {
      originalDefine.call(window.customElements, tagName, classObj, ...rest);
    }
  };
  `;
  
  /**
   * Transform plugin for transforming and injecting per-file refresh code.
   *
   * @returns {import('vite').Plugin}
   */
  module.exports = function LitRefreshPlugin() {
    let shouldSkip = false;
  
    return {
      name: "lit-element-refresh",
  
      configResolved(config) {
        shouldSkip = config.command === "build" || config.isProduction;
      },
  
      transform(code, id, ssr) {
        if (shouldSkip || ssr) {
          return;
        }
  
        if (!/\.(t|j)sx?$/.test(id) || id.includes("node_modules")) {
          return;
        }
  
        // plain js/ts files can't use React without importing it, so skip
        // them whenever possible
        if (!code.includes("lit")) {
          return;
        }
  
        const header = `
          // taken from: https://github.com/open-wc/open-wc/blob/master/packages/dev-server-hmr/src/presets/lit.js
  
          import { adoptStyles, supportsAdoptingStyleSheets, LitElement as Element } from 'lit';
  
          // static callback
          Element.hotReplacedCallback = function hotReplacedCallback() {
            this.finalize();
          };
          // instance callback
          Element.prototype.hotReplacedCallback = function hotReplacedCallback() {
            if (!supportsAdoptingStyleSheets) {
              const nodes = Array.from(this.renderRoot.children);
              for (const node of nodes) {
                if (node.tagName.toLowerCase() === 'style') {
                  node.remove();
                }
              }
            }
            this.constructor.finalizeStyles();
            if (window.ShadowRoot && this.renderRoot instanceof window.ShadowRoot) {
              adoptStyles(
                this.renderRoot,
                this.constructor.elementStyles
              );
            }
            this.requestUpdate();
          };
        `;
  
        const footer = `
          if (import.meta.hot) {
            import.meta.hot.accept(() => {});
          }
        `;
  
        return {
          code: `${header}${code}${footer}`,
        };
      },
  
      transformIndexHtml() {
        if (shouldSkip) {
          return;
        }
  
        return [
          {
            tag: "script",
            attrs: { type: "module" },
            children: preambleCode,
          },
        ];
      },
    };
  };
  
  module.exports.preambleCode = preambleCode;
  