From 35dd8b7bede9388ef0abb8204d952986dc43cdac Mon Sep 17 00:00:00 2001 From: Vladimir Ivakin Date: Tue, 9 May 2023 22:17:53 +0200 Subject: [PATCH] fix(mergeConfig): don't accept callback config mergeConfig function doesn't work with config in callback form. To make the error more transparent added both a runtime and type checks. --- docs/guide/api-javascript.md | 4 ++++ .../vite/src/node/__tests__/config.spec.ts | 23 ++++++++++++++++++- packages/vite/src/node/utils.ts | 13 ++++++++--- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/docs/guide/api-javascript.md b/docs/guide/api-javascript.md index 41086c8d3404df..cb1540950ec23c 100644 --- a/docs/guide/api-javascript.md +++ b/docs/guide/api-javascript.md @@ -266,6 +266,10 @@ function mergeConfig( Deeply merge two Vite configs. `isRoot` represents the level within the Vite config which is being merged. For example, set `false` if you're merging two `build` options. +::: tip NOTE +`mergeConfig` accepts only config in object form. If you have a config in callback form, you should call it before passing into `mergeConfig`. +::: + ## `searchForWorkspaceRoot` **Type Signature:** diff --git a/packages/vite/src/node/__tests__/config.spec.ts b/packages/vite/src/node/__tests__/config.spec.ts index 606b25fa8e148e..e84f71d7f5dac7 100644 --- a/packages/vite/src/node/__tests__/config.spec.ts +++ b/packages/vite/src/node/__tests__/config.spec.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from 'vitest' import type { InlineConfig } from '..' import type { PluginOption, UserConfig, UserConfigExport } from '../config' -import { resolveConfig } from '../config' +import { defineConfig, resolveConfig } from '../config' import { resolveEnvPrefix } from '../env' import { mergeConfig } from '../publicUtils' @@ -184,6 +184,27 @@ describe('mergeConfig', () => { expect(mergeConfig(baseConfig, newConfig)).toEqual(mergedConfig) expect(mergeConfig(newConfig, baseConfig)).toEqual(mergedConfig) }) + + test('throws error with functions', () => { + const baseConfig = defineConfig(() => ({ base: 'base' })) + const newConfig = defineConfig(() => ({ base: 'new' })) + + expect(() => + mergeConfig( + // @ts-expect-error TypeScript shouldn't give you to pass a function as argument + baseConfig, + newConfig, + ), + ).toThrowError('Cannot merge config in form of callback') + + expect(() => + mergeConfig( + {}, + // @ts-expect-error TypeScript shouldn't give you to pass a function as argument + newConfig, + ), + ).toThrowError('Cannot merge config in form of callback') + }) }) describe('resolveEnvPrefix', () => { diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index effea7fb34a126..ed5ca6e48dc089 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -1037,11 +1037,18 @@ function mergeConfigRecursively( return merged } -export function mergeConfig( - defaults: Record, - overrides: Record, +export function mergeConfig< + D extends Record, + O extends Record, +>( + defaults: D extends Function ? never : D, + overrides: O extends Function ? never : O, isRoot = true, ): Record { + if (typeof defaults === 'function' || typeof overrides === 'function') { + throw new Error(`Cannot merge config in form of callback`) + } + return mergeConfigRecursively(defaults, overrides, isRoot ? '' : '.') }