Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ResolvedConfig interface #15473

Open
4 tasks done
unicornware opened this issue Dec 31, 2023 · 5 comments · May be fixed by #19210
Open
4 tasks done

ResolvedConfig interface #15473

unicornware opened this issue Dec 31, 2023 · 5 comments · May be fixed by #19210

Comments

@unicornware
Copy link

Description

ResolvedConfig is currently defined as a type, but it should be an interface.

Unlike with UserConfig, this means declaration merging cannot be taken advantage of by plugin developers. As a TypeScript developer, this makes typing resolved plugin options unnecessarily difficult. Sharing those options with other plugin developers is not possible without declaration merging, or alternatively, cumbersome and possibly out-of-date patches.

Suggested solution

// packages/vite/src/node/config.ts

interface ResolvedConfig extends Readonly<
  Omit<
    UserConfig,
    | 'assetsInclude'
    | 'build'
    | 'css'
    | 'optimizeDeps'
    | 'plugins'
    | 'worker'
  > & PluginHookUtils
> {
    readonly appType: AppType
    readonly assetsInclude(file: string): boolean
    readonly base: string
    readonly build: ResolvedBuildOptions
    readonly cacheDir: string
    readonly command: 'build' | 'serve'
    readonly configFile: string | undefined
    readonly configFileDependencies: string[]
    readonly createResolver(
      options?: Partial<InternalResolveOptions>
    ): ResolveFn
    readonly css: ResolvedCSSOptions
    readonly env: Record<string, any>
    readonly envDir: string
    readonly esbuild: ESBuildOptions | false
    readonly experimental: ExperimentalOptions
    readonly inlineConfig: InlineConfig
    readonly isProduction: boolean
    readonly isWorker: boolean
    readonly logger: Logger
    readonly mainConfig: ResolvedConfig | null
    readonly mode: string
    readonly optimizeDeps: DepOptimizationOptions
    readonly packageCache: PackageCache
    readonly plugins: readonly Plugin[]
    readonly preview: ResolvedPreviewOptions
    readonly publicDir: string
    readonly rawBase: string
    readonly resolve: Required<ResolveOptions> & { alias: Alias[] }
    readonly root: string
    readonly server: ResolvedServerOptions
    readonly ssr: ResolvedSSROptions
    readonly worker: ResolvedWorkerOptions
}

Alternative

No response

Additional context

The documentation gives the impression ResolvedConfig is an interface. Given the docs, I wasn't sure if this should be a feature request or bug report 😅

Validations

@unicornware
Copy link
Author

still looking for this fix.

@hi-ogawa
Copy link
Collaborator

hi-ogawa commented Oct 15, 2024

While your suggestion seems reasonable, can you elaborate your use case? What I'm wondering is that, since extending UserConfig would also extends ResolveConfig = Readonly<Omit<UserConfig, ..., I suppose you'd like to not extend UserConfig but only ResolveConfig?

As an example, Vitest extends UserConfig to allow defineConfig({ test: ... }) and it also affects ResolvedConfig. https://github.com/vitest-dev/vitest/blob/e03725afddfa9516d2ace1bbe160b6516fc4893c/packages/vitest/src/node/types/vite.ts#L10

@bluwy
Copy link
Member

bluwy commented Oct 23, 2024

If there's no breaking changes to switching to an interface, I think it'll be nice to do so. I personally tend to prefer interface but it looks like the source code now has a mix of interface and type, so it's not very consistent to side towards a pattern.

@lazuee
Copy link

lazuee commented Jan 16, 2025

Make ResolvedConfig an interface to allow extending it.

// assume vite custom plugin interface
type CustomContext = Record<string, any>; 
type ResolvedCustomConfig = Record<string, any>;

declare module "vite" {
  export interface UserConfig {
    __customPluginContext?:
      | {
          customPluginConfig?: Partial<ResolvedCustomConfig>;
        }
      | Partial<CustomContext>;
  }

  export interface ResolvedConfig {
    __customPluginContext: CustomContext;
  }
}

export {};

@lazuee
Copy link

lazuee commented Jan 16, 2025

Why not use an interface?
https://github.com/vitejs/vite/blob/v6.0.7/packages/vite/src/node/config.ts#L535

export interface ResolvedConfig extends Readonly<
  Omit<
    UserConfig,
    | 'plugins'
    | 'css'
    | 'json'
    | 'assetsInclude'
    | 'optimizeDeps'
    | 'worker'
    | 'build'
    | 'dev'
    | 'environments'
    | 'server'
    | 'preview'
  > & {
    configFile: string | undefined
    configFileDependencies: string[]
    inlineConfig: InlineConfig
    root: string
    base: string
    /** @internal */
    decodedBase: string
    /** @internal */
    rawBase: string
    publicDir: string
    cacheDir: string
    command: 'build' | 'serve'
    mode: string
    isWorker: boolean
    // in nested worker bundle to find the main config
    /** @internal */
    mainConfig: ResolvedConfig | null
    /** @internal list of bundle entry id. used to detect recursive worker bundle. */
    bundleChain: string[]
    isProduction: boolean
    envDir: string
    env: Record<string, any>
    resolve: Required<ResolveOptions> & {
      alias: Alias[]
    }
    plugins: readonly Plugin[]
    css: ResolvedCSSOptions
    json: Required<JsonOptions>
    esbuild: ESBuildOptions | false
    server: ResolvedServerOptions
    dev: ResolvedDevEnvironmentOptions
    /** @experimental */
    builder: ResolvedBuilderOptions | undefined
    build: ResolvedBuildOptions
    preview: ResolvedPreviewOptions
    ssr: ResolvedSSROptions
    assetsInclude: (file: string) => boolean
    logger: Logger
    createResolver: (options?: Partial<InternalResolveOptions>) => ResolveFn
    optimizeDeps: DepOptimizationOptions
    /** @internal */
    packageCache: PackageCache
    worker: ResolvedWorkerOptions
    appType: AppType
    experimental: ExperimentalOptions
    environments: Record<string, ResolvedEnvironmentOptions>
    /** @internal */
    fsDenyGlob: AnymatchFn
    /** @internal */
    safeModulePaths: Set<string>
  } & PluginHookUtils
> {}

https://www.diffchecker.com/YFxRGZx8/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants