Skip to content

Commit f0ef731

Browse files
committed
feat: add config-loader cli option
closes #479
1 parent 7b54118 commit f0ef731

File tree

7 files changed

+79
-11
lines changed

7 files changed

+79
-11
lines changed

docs/options/config-file.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ tsdown --no-config
6262

6363
This is useful if you want to rely solely on command-line options or default settings.
6464

65+
## Config Loaders
66+
67+
`tsdown` supports multiple config loaders to accommodate various file formats. You can select a config loader using the `--config-loader` option. The available loaders are:
68+
69+
- `auto` (default): Utilizes native runtime loading for TypeScript if supported; otherwise, defaults to `unconfig`.
70+
- `native`: Loads TypeScript configuration files using native runtime support. Requires a compatible environment, such as the latest Node.js, Deno, or Bun.
71+
- `unconfig`: Loads configuration files with the `unconfig` library, ensuring broad compatibility across different runtimes.
72+
73+
> [!TIP]
74+
> Node.js does not natively support importing TypeScript files without specifying the file extension. If you are using Node.js and want to load a TypeScript config file without including the `.ts` extension, consider using the `unconfig` loader for seamless compatibility.
75+
6576
## Extending Vite or Vitest Config (Experimental)
6677

6778
`tsdown` provides an **experimental** feature to extend your existing Vite or Vitest configuration files. This allows you to reuse specific configuration options, such as `resolve` and `plugins`, while ignoring others that are not relevant to `tsdown`.

docs/reference/cli.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ Specify a custom configuration file. Use this option to define the path to the c
1818

1919
See also [Config File](../options/config-file.md).
2020

21+
## `--config-loader <loader>`
22+
23+
Specifies which config loader to use.
24+
25+
See also [Config File](../options/config-file.md).
26+
2127
## `--no-config`
2228

2329
Disable loading a configuration file. This is useful if you want to rely solely on command-line options or default settings.

docs/zh-CN/options/config-file.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ tsdown --no-config
6262

6363
这在您希望仅依赖命令行选项或默认设置时非常有用。
6464

65+
## 配置加载器
66+
67+
`tsdown` 支持多种配置加载器,以适配不同的文件格式。您可以通过 `--config-loader` 选项选择配置加载器。可用的加载器包括:
68+
69+
- `auto`(默认):如果运行时支持,则使用原生方式加载 TypeScript,否则回退到 `unconfig`
70+
- `native`:通过原生运行时支持加载 TypeScript 配置文件。需要兼容的环境,如最新版 Node.js、Deno 或 Bun。
71+
- `unconfig`:使用 `unconfig` 库加载配置文件,确保在不同运行时下具有广泛兼容性。
72+
73+
> [!TIP]
74+
> Node.js 原生不支持在不指定文件扩展名的情况下导入 TypeScript 文件。如果您在 Node.js 环境下希望加载不带 `.ts` 扩展名的 TypeScript 配置文件,建议使用 `unconfig` 加载器以获得更好的兼容性。
75+
6576
## 扩展 Vite 或 Vitest 配置(实验性功能){#extending-vite-or-vitest-config-experimental}
6677

6778
`tsdown` 提供了一个**实验性**功能,允许您扩展现有的 Vite 或 Vitest 配置文件。通过此功能,您可以复用特定的配置选项(如 `resolve``plugins`),同时忽略与 `tsdown` 无关的其他选项。

docs/zh-CN/reference/cli.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ tsdown src/index.ts src/util.ts
1818

1919
另请参阅 [配置文件](../options/config-file.md)
2020

21+
## `--config-loader <loader>`
22+
23+
指定要使用的配置加载器。
24+
25+
另请参阅 [配置文件](../options/config-file.md)
26+
2127
## `--no-config`
2228

2329
禁用加载配置文件。如果您希望仅依赖命令行选项或默认设置,此选项非常有用。

src/cli.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ cli
1717
allowUnknownOptions: true,
1818
})
1919
.option('-c, --config <filename>', 'Use a custom config file')
20+
.option(
21+
'--config-loader <loader>',
22+
'Config loader to use: auto, native, unconfig',
23+
{ default: 'auto' },
24+
)
2025
.option('--no-config', 'Disable config file')
2126
.option('-f, --format <format>', 'Bundle format: esm, cjs, iife, umd', {
2227
default: 'esm',

src/options/config.ts

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,18 @@ export async function loadConfigFile(
7777
}
7878
}
7979

80-
const nativeTS =
81-
process.features.typescript || process.versions.bun || process.versions.deno
80+
let isNative = false
81+
if (!loaded) {
82+
if (!options.configLoader || options.configLoader === 'auto') {
83+
isNative = !!(
84+
process.features.typescript ||
85+
process.versions.bun ||
86+
process.versions.deno
87+
)
88+
} else if (options.configLoader === 'native') {
89+
isNative = true
90+
}
91+
}
8292

8393
let { config, sources } = await loadConfig
8494
.async<UserConfig | UserConfigFn>({
@@ -88,14 +98,7 @@ export async function loadConfigFile(
8898
{
8999
files: 'tsdown.config',
90100
extensions: ['ts', 'mts', 'cts', 'js', 'mjs', 'cjs', 'json', ''],
91-
parser:
92-
loaded || !nativeTS
93-
? 'auto'
94-
: async (filepath) => {
95-
const mod = await import(pathToFileURL(filepath).href)
96-
const config = mod.default || mod
97-
return config
98-
},
101+
parser: isNative ? nativeImport : 'auto',
99102
},
100103
{
101104
files: 'package.json',
@@ -126,3 +129,20 @@ export async function loadConfigFile(
126129
file,
127130
}
128131
}
132+
133+
async function nativeImport(id: string) {
134+
const mod = await import(pathToFileURL(id).href).catch((error) => {
135+
const cannotFindModule = error?.message?.includes?.('Cannot find module')
136+
if (cannotFindModule) {
137+
const configError = new Error(
138+
`Failed to load the config file. Try setting the --config-loader CLI flag to \`unconfig\`.\n\n${error.message}`,
139+
)
140+
configError.cause = error
141+
throw configError
142+
} else {
143+
throw error
144+
}
145+
})
146+
const config = mod.default || mod
147+
return config
148+
}

src/options/types.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,12 @@ export interface Options {
351351
*/
352352
config?: boolean | string
353353

354+
/**
355+
* Config loader to use. It can only be set via CLI or API.
356+
* @default 'auto'
357+
*/
358+
configLoader?: 'auto' | 'native' | 'unconfig'
359+
354360
/**
355361
* Reuse config from Vite or Vitest (experimental)
356362
* @default false
@@ -454,7 +460,9 @@ export interface Options {
454460
/**
455461
* Options without specifying config file path.
456462
*/
457-
export type UserConfig = Arrayable<Omit<Options, 'config' | 'filter'>>
463+
export type UserConfig = Arrayable<
464+
Omit<Options, 'config' | 'filter' | 'configLoader'>
465+
>
458466
export type UserConfigFn = (cliOptions: Options) => Awaitable<UserConfig>
459467
export type NormalizedUserConfig = Exclude<UserConfig, any[]>
460468

@@ -470,6 +478,7 @@ export type ResolvedOptions = Omit<
470478
| 'logLevel'
471479
| 'failOnWarn'
472480
| 'customLogger'
481+
| 'configLoader'
473482
>,
474483
| 'globalName'
475484
| 'inputOptions'

0 commit comments

Comments
 (0)