Skip to content

Commit eb49060

Browse files
committed
feat: create custom lib cli to call tsdown js api
1 parent 7f7bb67 commit eb49060

10 files changed

Lines changed: 158 additions & 82 deletions

File tree

packages/cli/binding/src/cli.rs

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -419,13 +419,6 @@ pub async fn main<
419419
let workspace = Workspace::partial_load(cwd.clone())?;
420420
let lib_fn =
421421
options.map(|o| o.lib).expect("lib command requires CliOptions to be provided");
422-
let lib_config_path = workspace.cache_path().join("vite-lib.config.js");
423-
if write_vite_lib_config(&cwd, &lib_config_path).await? {
424-
args.extend_from_slice(&[
425-
"--config".to_string(),
426-
lib_config_path.as_path().to_string_lossy().into_owned(),
427-
]);
428-
}
429422
let summary = lib(lib_fn, &workspace, args).await?;
430423
workspace.unload().await?;
431424
summary
@@ -574,42 +567,6 @@ async fn read_vite_config_from_workspace_root<
574567
Ok(None)
575568
}
576569

577-
async fn write_vite_lib_config(
578-
workspace_root: &AbsolutePathBuf,
579-
lib_config_path: &AbsolutePathBuf,
580-
) -> Result<bool, Error> {
581-
let relative_vite_config_path =
582-
lib_config_path.strip_prefix(workspace_root).map_err(|e| Error::InvalidRelativePath {
583-
path: e.stripped_path.into(),
584-
reason: e.invalid_path_data_error.into(),
585-
})?;
586-
if let Some(relative_vite_config_path) = relative_vite_config_path {
587-
let relative_prefix = relative_vite_config_path
588-
.as_path()
589-
.components()
590-
.skip(1)
591-
.map(|_| "..".to_string())
592-
.collect::<Vec<_>>()
593-
.join("/");
594-
write(
595-
&lib_config_path,
596-
format!(
597-
r#"let config
598-
try {{
599-
const viteConfig = await import('{relative_prefix}/vite.config.ts')
600-
config = viteConfig.default.lib
601-
}} catch {{
602-
}}
603-
export default config
604-
"#
605-
),
606-
)
607-
.await?;
608-
return Ok(true);
609-
}
610-
Ok(false)
611-
}
612-
613570
#[cfg(test)]
614571
mod tests {
615572
use clap::Parser;

packages/cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"@napi-rs/cli": "^3.4.1",
3636
"@oxc-node/core": "^0.0.32",
3737
"@voidzero-dev/vite-plus-tools": "workspace:",
38+
"cac": "catalog:",
3839
"rolldown": "workspace:*",
3940
"rolldown-plugin-dts": "catalog:",
4041
"tsdown": "catalog:",

packages/cli/snap-tests/command-helper/snap.txt

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,32 +26,30 @@ Options:
2626
-V, --version Print version
2727

2828
> vite lib -h # lib help message
29-
tsdown/<semver>
29+
vite lib
3030

3131
Usage:
32-
$ tsdown [...files]
32+
$ vite lib [...files]
3333

3434
Commands:
3535
[...files] Bundle files
36-
migrate Migrate from tsup to tsdown
3736

3837
For more info, run any command with the `--help` flag:
39-
$ tsdown --help
40-
$ tsdown migrate --help
38+
$ vite lib --help
4139

4240
Options:
43-
-c, --config <filename> Use a custom config file
4441
--config-loader <loader> Config loader to use: auto, native, unrun (default: auto)
4542
--no-config Disable config file (default: true)
4643
-f, --format <format> Bundle format: esm, cjs, iife, umd (default: esm)
4744
--clean Clean output directory, --no-clean to disable
4845
--external <module> Mark dependencies as external
4946
--minify Minify output
50-
--debug Enable debug mode
51-
--debug-logs [feat] Show debug logs
47+
--devtools Enable devtools integration
48+
--debug [feat] Show debug logs
5249
--target <target> Bundle target, e.g "es2015", "esnext"
5350
-l, --logLevel <level> Set log level: info, warn, error, silent
5451
--fail-on-warn Fail on warnings (default: true)
52+
--no-write Disable writing files to disk, incompatible with watch mode (default: true)
5553
-d, --out-dir <dir> Output directory (default: dist)
5654
--treeshake Tree-shake bundle (default: true)
5755
--sourcemap Generate source map (default: false)
@@ -66,16 +64,17 @@ Options:
6664
--from-vite [vitest] Reuse config from Vite or Vitest
6765
--report Size report (default: true)
6866
--env.* <value> Define compile-time env variables
67+
--env-file <file> Load environment variables from a file, when used together with --env, variables in --env take precedence
68+
--env-prefix <prefix> Prefix for env variables to inject into the bundle (default: VITE_LIB_,TSDOWN_)
6969
--on-success <command> Command to run on success
7070
--copy <dir> Copy files to output dir
7171
--public-dir <dir> Alias for --copy, deprecated
7272
--tsconfig <tsconfig> Set tsconfig path
7373
--unbundle Unbundle mode
7474
-W, --workspace [dir] Enable workspace mode
75-
-F, --filter <pattern> Filter workspace packages, e.g. /regex/ or substring
75+
-F, --filter <pattern> Filter configs (cwd or name), e.g. /pkg-name$/ or pkg-name
7676
--exports Generate export-related metadata for package.json (experimental)
7777
-h, --help Display this message
78-
-v, --version Display version number
7978

8079

8180
> vite fmt -h # fmt help message

packages/cli/snap-tests/command-lib-monorepo/snap.txt

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
> vite run hello#build # should build the library
22
~/packages/hello$ vite lib
3-
ℹ tsdown v<semver> powered by rolldown v<semver>
4-
ℹ Using tsdown config: <cwd>/packages/hello/tsdown.config.ts
53
ℹ entry: src/index.ts
64
ℹ Build start
7-
ℹ dist/index.cjs <variable> kB │ gzip: <variable> kB
5+
ℹ dist/index.mjs <variable> kB │ gzip: <variable> kB
86
ℹ 1 files, total: <variable> kB
97
✔ Build complete in <variable>ms
108

@@ -24,15 +22,13 @@ Task Details:
2422
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2523

2624
> ls packages/hello/dist # should have the library
27-
index.cjs
25+
index.mjs
2826

2927
> vite run hello#build # should hit cache
3028
~/packages/hello$ vite lib (✓ cache hit, replaying)
31-
ℹ tsdown v<semver> powered by rolldown v<semver>
32-
ℹ Using tsdown config: <cwd>/packages/hello/tsdown.config.ts
3329
ℹ entry: src/index.ts
3430
ℹ Build start
35-
ℹ dist/index.cjs <variable> kB │ gzip: <variable> kB
31+
ℹ dist/index.mjs <variable> kB │ gzip: <variable> kB
3632
ℹ 1 files, total: <variable> kB
3733
✔ Build complete in <variable>ms
3834

packages/cli/snap-tests/command-lib/snap.txt

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,28 @@
11
> vite lib -h # should print the help message
2-
tsdown/<semver>
2+
vite lib
33

44
Usage:
5-
$ tsdown [...files]
5+
$ vite lib [...files]
66

77
Commands:
88
[...files] Bundle files
9-
migrate Migrate from tsup to tsdown
109

1110
For more info, run any command with the `--help` flag:
12-
$ tsdown --help
13-
$ tsdown migrate --help
11+
$ vite lib --help
1412

1513
Options:
16-
-c, --config <filename> Use a custom config file
1714
--config-loader <loader> Config loader to use: auto, native, unrun (default: auto)
1815
--no-config Disable config file (default: true)
1916
-f, --format <format> Bundle format: esm, cjs, iife, umd (default: esm)
2017
--clean Clean output directory, --no-clean to disable
2118
--external <module> Mark dependencies as external
2219
--minify Minify output
23-
--debug Enable debug mode
24-
--debug-logs [feat] Show debug logs
20+
--devtools Enable devtools integration
21+
--debug [feat] Show debug logs
2522
--target <target> Bundle target, e.g "es2015", "esnext"
2623
-l, --logLevel <level> Set log level: info, warn, error, silent
2724
--fail-on-warn Fail on warnings (default: true)
25+
--no-write Disable writing files to disk, incompatible with watch mode (default: true)
2826
-d, --out-dir <dir> Output directory (default: dist)
2927
--treeshake Tree-shake bundle (default: true)
3028
--sourcemap Generate source map (default: false)
@@ -39,21 +37,20 @@ Options:
3937
--from-vite [vitest] Reuse config from Vite or Vitest
4038
--report Size report (default: true)
4139
--env.* <value> Define compile-time env variables
40+
--env-file <file> Load environment variables from a file, when used together with --env, variables in --env take precedence
41+
--env-prefix <prefix> Prefix for env variables to inject into the bundle (default: VITE_LIB_,TSDOWN_)
4242
--on-success <command> Command to run on success
4343
--copy <dir> Copy files to output dir
4444
--public-dir <dir> Alias for --copy, deprecated
4545
--tsconfig <tsconfig> Set tsconfig path
4646
--unbundle Unbundle mode
4747
-W, --workspace [dir] Enable workspace mode
48-
-F, --filter <pattern> Filter workspace packages, e.g. /regex/ or substring
48+
-F, --filter <pattern> Filter configs (cwd or name), e.g. /pkg-name$/ or pkg-name
4949
--exports Generate export-related metadata for package.json (experimental)
5050
-h, --help Display this message
51-
-v, --version Display version number
5251

5352

5453
> vite lib src/index.ts # should build the library
55-
ℹ tsdown v<semver> powered by rolldown v<semver>
56-
ℹ Using tsdown config: <cwd>/node_modules/.vite/task-cache/vite-lib.config.js
5754
ℹ entry: src/index.ts
5855
ℹ Build start
5956
ℹ dist/index.mjs <variable> kB │ gzip: <variable> kB
@@ -66,8 +63,6 @@ index.mjs
6663

6764
> vite lib src/index.ts # should hit cache
6865
✓ cache hit, replaying
69-
ℹ tsdown v<semver> powered by rolldown v<semver>
70-
ℹ Using tsdown config: <cwd>/node_modules/.vite/task-cache/vite-lib.config.js
7166
ℹ entry: src/index.ts
7267
ℹ Build start
7368
ℹ dist/index.mjs <variable> kB │ gzip: <variable> kB

packages/cli/src/lib-bin.ts

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#!/usr/bin/env node
2+
import module from 'node:module';
3+
4+
import { cac } from 'cac';
5+
import { build, type UserConfig, globalLogger } from 'tsdown';
6+
7+
import { resolveConfig } from './index.js';
8+
9+
const cli = cac('vite lib');
10+
cli.help();
11+
12+
const DEFAULT_ENV_PREFIXES = ['VITE_LIB_', 'TSDOWN_'];
13+
14+
cli
15+
.command('[...files]', 'Bundle files', {
16+
ignoreOptionDefaultValue: true,
17+
allowUnknownOptions: true,
18+
})
19+
// Only support config file in vite.config.ts
20+
// .option('-c, --config <filename>', 'Use a custom config file')
21+
.option('--config-loader <loader>', 'Config loader to use: auto, native, unrun', {
22+
default: 'auto',
23+
})
24+
.option('--no-config', 'Disable config file')
25+
.option('-f, --format <format>', 'Bundle format: esm, cjs, iife, umd', {
26+
default: 'esm',
27+
})
28+
.option('--clean', 'Clean output directory, --no-clean to disable')
29+
.option('--external <module>', 'Mark dependencies as external')
30+
.option('--minify', 'Minify output')
31+
.option('--devtools', 'Enable devtools integration')
32+
.option('--debug [feat]', 'Show debug logs')
33+
.option('--target <target>', 'Bundle target, e.g "es2015", "esnext"')
34+
.option('-l, --logLevel <level>', 'Set log level: info, warn, error, silent')
35+
.option('--fail-on-warn', 'Fail on warnings', { default: true })
36+
.option('--no-write', 'Disable writing files to disk, incompatible with watch mode')
37+
.option('-d, --out-dir <dir>', 'Output directory', { default: 'dist' })
38+
.option('--treeshake', 'Tree-shake bundle', { default: true })
39+
.option('--sourcemap', 'Generate source map', { default: false })
40+
.option('--shims', 'Enable cjs and esm shims ', { default: false })
41+
.option('--platform <platform>', 'Target platform', {
42+
default: 'node',
43+
})
44+
.option('--dts', 'Generate dts files')
45+
.option('--publint', 'Enable publint', { default: false })
46+
.option('--attw', 'Enable Are the types wrong integration', {
47+
default: false,
48+
})
49+
.option('--unused', 'Enable unused dependencies check', { default: false })
50+
.option('-w, --watch [path]', 'Watch mode')
51+
.option('--ignore-watch <path>', 'Ignore custom paths in watch mode')
52+
.option('--from-vite [vitest]', 'Reuse config from Vite or Vitest')
53+
.option('--report', 'Size report', { default: true })
54+
.option('--env.* <value>', 'Define compile-time env variables')
55+
.option(
56+
'--env-file <file>',
57+
'Load environment variables from a file, when used together with --env, variables in --env take precedence',
58+
)
59+
.option('--env-prefix <prefix>', 'Prefix for env variables to inject into the bundle', {
60+
// support `TSDOWN_` for migration compatibility
61+
default: DEFAULT_ENV_PREFIXES,
62+
})
63+
.option('--on-success <command>', 'Command to run on success')
64+
.option('--copy <dir>', 'Copy files to output dir')
65+
.option('--public-dir <dir>', 'Alias for --copy, deprecated')
66+
.option('--tsconfig <tsconfig>', 'Set tsconfig path')
67+
.option('--unbundle', 'Unbundle mode')
68+
.option('-W, --workspace [dir]', 'Enable workspace mode')
69+
.option('-F, --filter <pattern>', 'Filter configs (cwd or name), e.g. /pkg-name$/ or pkg-name')
70+
.option('--exports', 'Generate export-related metadata for package.json (experimental)')
71+
.action(async (input: string[], flags: UserConfig) => {
72+
const viteConfig = await resolveConfig({ root: process.cwd() }, 'build');
73+
if (input.length > 0) flags.entry = input;
74+
// TODO: set default envPrefix after tsdown upgrade
75+
await build({
76+
...(viteConfig.lib as UserConfig),
77+
...flags,
78+
config: false,
79+
});
80+
});
81+
82+
export async function runCLI(): Promise<void> {
83+
cli.parse(process.argv, { run: false });
84+
85+
// TODO: enable debug after tsdown upgrade
86+
// enableDebug(cli.options)
87+
88+
try {
89+
await cli.runMatchedCommand();
90+
} catch (error: any) {
91+
globalLogger.error(String(error.stack || error.message));
92+
process.exit(1);
93+
}
94+
}
95+
96+
if (module.enableCompileCache) {
97+
module.enableCompileCache();
98+
}
99+
runCLI();

packages/cli/src/resolve-lib.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
* Used for: `vite-plus lib` command
99
*/
1010

11-
import { dirname, join } from 'node:path';
11+
import { join } from 'node:path';
1212

13-
import { DEFAULT_ENVS, resolve } from './utils.js';
13+
import { DEFAULT_ENVS } from './utils.js';
1414

1515
/**
1616
* Resolves the Tsdown binary path and environment variables.
@@ -26,12 +26,7 @@ export async function lib(): Promise<{
2626
envs: Record<string, string>;
2727
}> {
2828
// Resolve the bundled Tsdown CLI
29-
const binPath = join(
30-
dirname(resolve('@voidzero-dev/vite-plus-core/package.json')),
31-
'dist',
32-
'tsdown',
33-
'run.js',
34-
);
29+
const binPath = join(import.meta.dirname, 'lib-bin.js');
3530

3631
return {
3732
binPath,

packages/cli/src/testcli.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import cac from 'cac';
2+
3+
const cli = cac('mycli');
4+
5+
cli
6+
.command('[...files]', 'Process files')
7+
.option('-w, --watch [paths]', 'Watch mode', { type: [] })
8+
.option('-v, --verbose', 'Verbose output')
9+
.action((files, options) => {
10+
if (options.watch) {
11+
const paths = options.watch === true ? ['.'] : options.watch;
12+
console.log('Watching:', paths);
13+
}
14+
15+
if (options.verbose) {
16+
console.log('Verbose mode');
17+
}
18+
19+
if (files.length) {
20+
console.log('Files:', files);
21+
}
22+
});
23+
24+
cli.help();
25+
cli.version('1.0.0');
26+
27+
cli.parse();

pnpm-lock.yaml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)