Repository: vitejs/vite
File: packages/vite/src/node/config.ts (TypeScript)

Code before:
     * We recommend using `import.meta.hot` rather than connecting
     * to the WebSocket server directly.
     * If you have a usecase that requires connecting to the WebSocket
     * server, please create an issue so that we can discuss.
     *
     * @deprecated
     */
    webSocketToken: string
    /** @internal */
    fsDenyGlob: AnymatchFn
    /** @internal */
    safeModulePaths: Set<string>
    /** @internal */
    nativePluginEnabledLevel: number
    /** @internal */
    [SYMBOL_RESOLVED_CONFIG]: true
  } & PluginHookUtils
> {}

export async function resolveDevToolsConfig(
  config: DevToolsConfig | boolean | undefined,
  host: string | boolean | undefined,
): Promise<ResolvedDevToolsConfig> {
  const resolvedHostname = await resolveHostname(host)
  const fallbackHostname = resolvedHostname.host ?? 'localhost'
  return normalizeDevToolsConfig(config, fallbackHostname)
}

// inferred ones are omitted
const configDefaults = Object.freeze({
  define: {},
  dev: {
    warmup: [],
    // preTransformRequests
    /** @experimental */
    sourcemap: { js: true },
    sourcemapIgnoreList: undefined,
    // createEnvironment
    // recoverable
    // moduleRunnerTransform
  },
  build: buildEnvironmentOptionsDefaults,
  resolve: {
    // mainFields
    // conditions
    externalConditions: [...DEFAULT_EXTERNAL_CONDITIONS],
    extensions: DEFAULT_EXTENSIONS,
    dedupe: [],
    /** @experimental */
    noExternal: [],
    external: [],

Review comment (suggestion):
`resolveDevToolsConfig` is called during config resolution regardless of whether devtools are enabled, so it should be safe when `@vitejs/devtools` isn't installed. With the current implementation, the required normalizer will already have been imported at module load time. If you move to a dynamic import, also consider short-circuiting for `config` unset/false to avoid any dependency lookup and to preserve current behavior when devtools integration is not used.

Code after:
     * to the WebSocket server directly.
     * If you have a usecase that requires connecting to the WebSocket
     * server, please create an issue so that we can discuss.
     *
     * @deprecated
     */
    webSocketToken: string
    /** @internal */
    fsDenyGlob: AnymatchFn
    /** @internal */
    safeModulePaths: Set<string>
    /** @internal */
    nativePluginEnabledLevel: number
    /** @internal */
    [SYMBOL_RESOLVED_CONFIG]: true
  } & PluginHookUtils
> {}

export async function resolveDevToolsConfig(
  config: DevToolsConfig | boolean | undefined,
  host: string | boolean | undefined,
  logger: Logger,
): Promise<ResolvedDevToolsConfig> {
  const isEnabled = config === true || !!(config && config.enabled)
  const resolvedHostname = await resolveHostname(host)
  const fallbackHostname = resolvedHostname.host ?? 'localhost'
  const fallbackConfig = {
    config: {
      host: fallbackHostname,
    },
    enabled: false,
  }
  if (!isEnabled) {
    return fallbackConfig
  }

  try {
    const { normalizeDevToolsConfig } = await import('@vitejs/devtools/config')
    return normalizeDevToolsConfig(config, fallbackHostname)
  } catch (e) {
    logger.error(
      colors.red(
        `Failed to load Vite DevTools config: ${e.message || e.stack}`,
      ),
      { error: e },
    )
    return fallbackConfig
  }
}

// inferred ones are omitted