tsdown 0.2.17 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # tsdown [![npm](https://img.shields.io/npm/v/tsdown.svg)](https://npmjs.com/package/tsdown) [![Unit Test](https://github.com/sxzz/tsdown/actions/workflows/unit-test.yml/badge.svg)](https://github.com/sxzz/tsdown/actions/workflows/unit-test.yml) [![JSR](https://jsr.io/badges/@sxzz/tsdown)](https://jsr.io/@sxzz/tsdown)
2
2
 
3
- An even faster bundler powered by Rolldown.
3
+ An even faster bundler powered by [Rolldown](https://github.com/rolldown/rolldown).
4
4
 
5
5
  > [!NOTE]
6
6
  > 🚧 **Work in Progress**
@@ -0,0 +1,28 @@
1
+ import { debug } from "./logger-Pk57TMWT.js";
2
+ import path from "node:path";
3
+
4
+ //#region src/features/external.ts
5
+ function ExternalPlugin(pkg, skipNodeModulesBundle) {
6
+ const deps = Array.from(getProductionDeps(pkg));
7
+ return {
8
+ name: "tsdown:external",
9
+ resolveId(id, importer, { isEntry }) {
10
+ if (isEntry) return;
11
+ let shouldExternal = skipNodeModulesBundle && !path.isAbsolute(id) && id[0] !== ".";
12
+ shouldExternal ||= deps.some((dep) => id === dep || id.startsWith(`${dep}/`));
13
+ if (shouldExternal) {
14
+ debug("[external]", "External dependency:", id);
15
+ return {
16
+ id,
17
+ external: true
18
+ };
19
+ }
20
+ }
21
+ };
22
+ }
23
+ function getProductionDeps(pkg) {
24
+ return new Set([...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]);
25
+ }
26
+
27
+ //#endregion
28
+ export { ExternalPlugin };
@@ -1,2 +1,2 @@
1
- import type { Options } from '../options';
2
- export declare function resolveEntry(entry: Options['entry']): Promise<string[] | Record<string, string>>;
1
+ import type { Options } from "../options.js";
2
+ export declare function resolveEntry(entry: Options["entry"]): Promise<string[] | Record<string, string>>;
@@ -1,6 +1,5 @@
1
- import type { ResolvedOptions } from '../options';
2
- import type { PackageJson } from 'pkg-types';
3
- import type { InputOptions, Plugin } from 'rolldown';
4
- export type External = InputOptions['external'];
5
- export declare function ExternalPlugin(pkg: PackageJson | undefined, platform: ResolvedOptions['platform']): Plugin;
1
+ import type { PackageJson } from "pkg-types";
2
+ import type { InputOptions, Plugin } from "rolldown";
3
+ export type External = InputOptions["external"];
4
+ export declare function ExternalPlugin(pkg: PackageJson, skipNodeModulesBundle?: boolean): Plugin;
6
5
  export declare function getProductionDeps(pkg: PackageJson): Set<string>;
@@ -1,2 +1,2 @@
1
- import type { Format } from '../options';
2
- export declare function resolveOutputExtension(pkg: any, format: Format): 'mjs' | 'cjs' | 'js';
1
+ import type { ModuleFormat } from "rolldown";
2
+ export declare function resolveOutputExtension(pkg: any, format: ModuleFormat): "mjs" | "cjs" | "js";
@@ -0,0 +1,7 @@
1
+ import type { FSWatcher } from "chokidar";
2
+ export interface Shortcut {
3
+ key: string;
4
+ description: string;
5
+ action: () => void | Promise<void>;
6
+ }
7
+ export declare function shortcuts(watcher: FSWatcher, rebuild: () => void): void;
@@ -1,2 +1,3 @@
1
- import type { ResolvedOptions } from '../options';
2
- export declare function watchBuild(options: ResolvedOptions, rebuild: () => void): Promise<void>;
1
+ import type { ResolvedOptions } from "../options.js";
2
+ import type { FSWatcher } from "chokidar";
3
+ export declare function watchBuild(options: ResolvedOptions, rebuild: () => void): Promise<FSWatcher>;
package/dist/index.d.ts CHANGED
@@ -1,12 +1,18 @@
1
- import { type Options, type OptionsWithoutConfig } from './options';
2
- import { logger } from './utils/logger';
1
+ import { type Config, type Options, type ResolvedOptions } from "./options.js";
2
+ import { logger } from "./utils/logger.js";
3
3
  /**
4
- * Build with tsdown.
5
- */
6
- export declare function build(userOptions?: Omit<Options, 'silent'>): Promise<void>;
4
+ * Build with tsdown.
5
+ */
6
+ export declare function build(userOptions?: Omit<Options, "silent">): Promise<void>;
7
7
  /**
8
- * Defines the configuration for tsdown.
9
- */
10
- export declare function defineConfig(options: OptionsWithoutConfig): OptionsWithoutConfig;
8
+ * Build a single configuration.
9
+ *
10
+ * @param resolved Resolved options
11
+ */
12
+ export declare function buildSingle(resolved: ResolvedOptions): Promise<void>;
13
+ /**
14
+ * Defines the configuration for tsdown.
15
+ */
16
+ export declare function defineConfig(options: Config): Config;
11
17
  export { logger };
12
- export type { Options, OptionsWithoutConfig };
18
+ export type { Config, Options };
package/dist/index.js CHANGED
@@ -1,14 +1,15 @@
1
- import { logger } from "./logger-e0Fr5WMR.js";
2
- import { ExternalPlugin } from "./external-m3ERo7i1.js";
3
- import { default as process, default as process$1, default as process$2 } from "node:process";
1
+ import { debug, logger } from "./logger-Pk57TMWT.js";
2
+ import { ExternalPlugin } from "./external-9r3oq3tH.js";
3
+ import process, { default as process$1, default as process$2, default as process$3 } from "node:process";
4
4
  import { rolldown } from "rolldown";
5
5
  import { IsolatedDecl } from "unplugin-isolated-decl";
6
6
  import { Unused } from "unplugin-unused";
7
7
  import { access, readdir, rm, stat } from "node:fs/promises";
8
- import { default as path, default as path$1, default as path$2 } from "node:path";
8
+ import path, { default as path$1, default as path$2 } from "node:path";
9
9
  import { glob, glob as glob$1 } from "tinyglobby";
10
10
  import { readPackageJSON } from "pkg-types";
11
- import { default as pc, default as pc$1 } from "picocolors";
11
+ import readline from "node:readline";
12
+ import pc, { default as pc$1, default as pc$2 } from "picocolors";
12
13
  import { loadConfig } from "unconfig";
13
14
 
14
15
  //#region src/utils/fs.ts
@@ -21,14 +22,13 @@ function fsExists(path$3) {
21
22
  async function cleanOutDir(cwd, patterns) {
22
23
  const files = [];
23
24
  if (await fsExists(cwd)) files.push(...(await readdir(cwd)).map((file) => path$2.resolve(cwd, file)));
24
- if (patterns.length) {
25
- files.push(...await glob$1(patterns, {
26
- cwd,
27
- absolute: true
28
- }));
29
- }
25
+ if (patterns.length) files.push(...await glob$1(patterns, {
26
+ cwd,
27
+ absolute: true
28
+ }));
30
29
  logger.info("Cleaning output folder");
31
30
  for (const file of files) {
31
+ debug("[clean]", "Removing", file);
32
32
  await rm(file, {
33
33
  force: true,
34
34
  recursive: true
@@ -42,13 +42,12 @@ async function readPackageJson(dir) {
42
42
  const packageJsonPath = path$1.join(dir, "package.json");
43
43
  const exists = await fsExists(packageJsonPath);
44
44
  if (!exists) return;
45
+ debug("Reading package.json:", packageJsonPath);
45
46
  return readPackageJSON(packageJsonPath);
46
47
  }
47
48
  function getPackageType(pkg) {
48
49
  if (pkg?.type) {
49
- if (!["module", "commonjs"].includes(pkg.type)) {
50
- throw new Error(`Invalid package.json type: ${pkg.type}`);
51
- }
50
+ if (!["module", "commonjs"].includes(pkg.type)) throw new Error(`Invalid package.json type: ${pkg.type}`);
52
51
  return pkg.type;
53
52
  }
54
53
  return "commonjs";
@@ -59,30 +58,74 @@ function getPackageType(pkg) {
59
58
  function resolveOutputExtension(pkg, format) {
60
59
  const moduleType = getPackageType(pkg);
61
60
  switch (format) {
62
- case "iife": return "js";
63
61
  case "es":
64
62
  case "esm":
65
- case "module": {
66
- return moduleType === "module" ? "js" : "mjs";
67
- }
63
+ case "module": return moduleType === "module" ? "js" : "mjs";
68
64
  case "cjs":
69
- case "commonjs": {
70
- return moduleType === "module" ? "cjs" : "js";
65
+ case "commonjs": return moduleType === "module" ? "cjs" : "js";
66
+ default: return "js";
67
+ }
68
+ }
69
+
70
+ //#endregion
71
+ //#region src/features/shortcuts.ts
72
+ function shortcuts(watcher, rebuild) {
73
+ let actionRunning = false;
74
+ async function onInput(input) {
75
+ if (actionRunning) return;
76
+ const SHORTCUTS = [
77
+ {
78
+ key: "r",
79
+ description: "rebuild",
80
+ action() {
81
+ rebuild();
82
+ }
83
+ },
84
+ {
85
+ key: "c",
86
+ description: "clear console",
87
+ action() {
88
+ console.clear();
89
+ }
90
+ },
91
+ {
92
+ key: "q",
93
+ description: "quit",
94
+ action() {
95
+ rl.close();
96
+ return watcher.close();
97
+ }
98
+ }
99
+ ];
100
+ if (input === "h") {
101
+ const loggedKeys = new Set();
102
+ logger.info(" Shortcuts");
103
+ for (const shortcut$1 of SHORTCUTS) {
104
+ if (loggedKeys.has(shortcut$1.key)) continue;
105
+ loggedKeys.add(shortcut$1.key);
106
+ if (shortcut$1.action == null) continue;
107
+ logger.info(pc$2.dim(" press ") + pc$2.bold(`${shortcut$1.key} + enter`) + pc$2.dim(` to ${shortcut$1.description}`));
108
+ }
109
+ return;
71
110
  }
111
+ const shortcut = SHORTCUTS.find((shortcut$1) => shortcut$1.key === input);
112
+ if (!shortcut) return;
113
+ actionRunning = true;
114
+ await shortcut.action();
115
+ actionRunning = false;
72
116
  }
117
+ const rl = readline.createInterface({ input: process$3.stdin });
118
+ rl.on("line", onInput);
73
119
  }
74
120
 
75
121
  //#endregion
76
122
  //#region src/utils/general.ts
77
123
  function toArray(val, defaultValue) {
78
- if (Array.isArray(val)) {
79
- return val;
80
- } else if (val == null) {
124
+ if (Array.isArray(val)) return val;
125
+ else if (val == null) {
81
126
  if (defaultValue) return [defaultValue];
82
127
  return [];
83
- } else {
84
- return [val];
85
- }
128
+ } else return [val];
86
129
  }
87
130
  function debounce(fn, wait) {
88
131
  let timeout;
@@ -114,31 +157,24 @@ async function watchBuild(options, rebuild) {
114
157
  logger.info(`Change detected: ${type} ${file}`);
115
158
  debouncedRebuild();
116
159
  });
160
+ return watcher;
117
161
  }
118
162
 
119
163
  //#endregion
120
164
  //#region src/features/entry.ts
121
165
  async function resolveEntry(entry) {
122
- if (!entry || Object.keys(entry).length === 0) {
123
- throw new Error(`No input files, try "tsdown <your-file>" instead`);
124
- }
125
- if (typeof entry === "string") {
126
- entry = [entry];
127
- }
166
+ if (!entry || Object.keys(entry).length === 0) throw new Error(`No input files, try "tsdown <your-file>" instead`);
167
+ if (typeof entry === "string") entry = [entry];
128
168
  if (Array.isArray(entry)) {
129
169
  const resolvedEntry = await glob(entry);
130
170
  if (resolvedEntry.length > 0) {
131
171
  entry = resolvedEntry;
132
172
  logger.info(`entry: ${pc$1.blue(entry.join(", "))}`);
133
- } else {
134
- throw new Error(`Cannot find entry: ${entry}`);
135
- }
173
+ } else throw new Error(`Cannot find entry: ${entry}`);
136
174
  } else {
137
175
  const files = Object.values(entry);
138
176
  files.forEach((filename) => {
139
- if (!fsExists(filename)) {
140
- throw new Error(`Cannot find entry: ${filename}`);
141
- }
177
+ if (!fsExists(filename)) throw new Error(`Cannot find entry: ${filename}`);
142
178
  });
143
179
  logger.info(`entry: ${pc$1.blue(files.join(", "))}`);
144
180
  }
@@ -147,38 +183,39 @@ async function resolveEntry(entry) {
147
183
 
148
184
  //#endregion
149
185
  //#region src/options.ts
150
- async function normalizeOptions(options) {
151
- options = {
152
- ...await loadConfigFile(options),
153
- ...options
154
- };
155
- let { entry, format = ["es"], plugins = [], external, clean = false, silent = false, treeshake = true, platform = "node", outDir = "dist", sourcemap = false, dts = false, unused = false, minify, alias, watch = false, inputOptions, outputOptions } = options;
156
- entry = await resolveEntry(entry);
157
- format = toArray(format, "es");
158
- if (clean === true) clean = [];
159
- return {
160
- entry,
161
- plugins,
162
- external,
163
- format,
164
- outDir: path.resolve(outDir),
165
- clean,
166
- silent,
167
- alias,
168
- treeshake,
169
- platform,
170
- sourcemap,
171
- dts,
172
- unused,
173
- minify,
174
- watch,
175
- inputOptions,
176
- outputOptions
177
- };
186
+ async function resolveOptions(options) {
187
+ const [config, configFile] = await loadConfigFile(options);
188
+ if (config.length === 0) config.push({});
189
+ return [await Promise.all(config.map(async (subConfig) => {
190
+ const subOptions = {
191
+ ...subConfig,
192
+ ...options
193
+ };
194
+ let { entry, format = ["es"], plugins = [], clean = false, silent = false, treeshake = true, platform = "node", outDir = "dist", sourcemap = false, dts = false, unused = false, watch = false, skipNodeModulesBundle = false } = subOptions;
195
+ entry = await resolveEntry(entry);
196
+ format = toArray(format, "es");
197
+ if (clean === true) clean = [];
198
+ return {
199
+ ...subOptions,
200
+ entry,
201
+ plugins,
202
+ format,
203
+ outDir: path.resolve(outDir),
204
+ clean,
205
+ silent,
206
+ treeshake,
207
+ platform,
208
+ sourcemap,
209
+ dts,
210
+ unused,
211
+ watch,
212
+ skipNodeModulesBundle
213
+ };
214
+ })), configFile];
178
215
  }
179
216
  async function loadConfigFile(options) {
180
217
  let { config: filePath } = options;
181
- if (filePath === false) return {};
218
+ if (filePath === false) return [[]];
182
219
  let cwd = process$1.cwd();
183
220
  let overrideConfig = false;
184
221
  let stats;
@@ -188,9 +225,7 @@ async function loadConfigFile(options) {
188
225
  overrideConfig = true;
189
226
  filePath = resolved;
190
227
  cwd = path.dirname(filePath);
191
- } else {
192
- cwd = resolved;
193
- }
228
+ } else cwd = resolved;
194
229
  }
195
230
  const { config, sources } = await loadConfig({
196
231
  sources: overrideConfig ? [{
@@ -216,59 +251,66 @@ async function loadConfigFile(options) {
216
251
  cwd,
217
252
  defaults: {}
218
253
  });
219
- if (sources.length > 0) {
220
- logger.info(`Using tsdown config: ${pc.underline(sources.join(", "))}`);
221
- }
222
- return config;
254
+ if (sources.length > 0) logger.info(`Using tsdown config: ${pc.underline(sources.join(", "))}`);
255
+ const file = sources[0];
256
+ return [toArray(config), file];
223
257
  }
224
258
 
225
259
  //#endregion
226
260
  //#region src/index.ts
227
261
  async function build(userOptions = {}) {
228
- const resolved = await normalizeOptions(userOptions);
229
- const { entry, external, plugins, outDir, format, clean, platform, alias, treeshake, sourcemap, dts, minify, watch, unused } = resolved;
262
+ debug("Loading config");
263
+ const [resolved, configFile] = await resolveOptions(userOptions);
264
+ if (configFile) debug("Loaded config:", configFile);
265
+ await Promise.all(resolved.map(buildSingle));
266
+ }
267
+ async function buildSingle(resolved) {
268
+ const { entry, external, plugins, outDir, format, clean, platform, alias, treeshake, sourcemap, dts, minify, watch, unused, onSuccess } = resolved;
230
269
  if (clean) await cleanOutDir(outDir, clean);
231
270
  const pkg = await readPackageJson(process.cwd());
232
- let startTime;
233
- await rebuild(true);
234
- if (watch) {
235
- await watchBuild(resolved, rebuild);
236
- }
237
- async function rebuild(first) {
238
- startTime = performance.now();
239
- const inputOptions = {
240
- input: entry,
241
- external,
242
- resolve: { alias },
243
- treeshake,
244
- platform,
245
- plugins: [
246
- ExternalPlugin(pkg, platform),
247
- dts && IsolatedDecl.rolldown(dts === true ? {} : dts),
248
- unused && Unused.rolldown(unused === true ? {} : unused),
249
- ...plugins
250
- ].filter((plugin) => !!plugin),
251
- ...resolved.inputOptions
271
+ let startTime = performance.now();
272
+ const inputOptions = {
273
+ input: entry,
274
+ external,
275
+ resolve: { alias },
276
+ treeshake,
277
+ platform,
278
+ plugins: [
279
+ pkg && ExternalPlugin(pkg, resolved.skipNodeModulesBundle),
280
+ unused && Unused.rolldown(unused === true ? {} : unused),
281
+ dts && IsolatedDecl.rolldown(dts === true ? {} : dts),
282
+ ...plugins
283
+ ].filter((plugin) => !!plugin),
284
+ ...resolved.inputOptions
285
+ };
286
+ const build$1 = await rolldown(inputOptions);
287
+ const outputOptions = await Promise.all(format.map(async (format$1) => {
288
+ const extension = resolveOutputExtension(pkg, format$1);
289
+ const outputOptions$1 = {
290
+ format: format$1,
291
+ name: resolved.globalName,
292
+ sourcemap,
293
+ dir: outDir,
294
+ minify,
295
+ entryFileNames: `[name].${extension}`,
296
+ chunkFileNames: `[name]-[hash].${extension}`
252
297
  };
253
- const build$1 = await rolldown(inputOptions);
254
- await Promise.all(format.map(async (format$1) => {
255
- const extension = resolveOutputExtension(pkg, format$1);
256
- const outputOptions = {
257
- format: format$1,
258
- sourcemap,
259
- dir: outDir,
260
- minify,
261
- entryFileNames: `[name].${extension}`,
262
- chunkFileNames: `[name]-[hash].${extension}`
263
- };
264
- const userOutputOptions = typeof resolved.outputOptions === "function" ? await resolved.outputOptions(outputOptions, format$1) : resolved.outputOptions;
265
- return await build$1.write({
266
- ...outputOptions,
267
- ...userOutputOptions
268
- });
269
- }));
270
- await build$1.close();
298
+ const userOutputOptions = typeof resolved.outputOptions === "function" ? await resolved.outputOptions(outputOptions$1, format$1) : resolved.outputOptions;
299
+ return {
300
+ ...outputOptions$1,
301
+ ...userOutputOptions
302
+ };
303
+ }));
304
+ await writeBundle(true);
305
+ if (watch) {
306
+ const watcher = await watchBuild(resolved, writeBundle);
307
+ shortcuts(watcher, writeBundle);
308
+ } else await build$1.close();
309
+ async function writeBundle(first) {
310
+ if (!first) startTime = performance.now();
311
+ await Promise.all(outputOptions.map((outputOptions$1) => build$1.write(outputOptions$1)));
271
312
  logger.success(`${first ? "Build" : "Rebuild"} complete in ${Math.round(performance.now() - startTime)}ms`);
313
+ await onSuccess?.();
272
314
  }
273
315
  }
274
316
  function defineConfig(options) {
@@ -276,4 +318,4 @@ function defineConfig(options) {
276
318
  }
277
319
 
278
320
  //#endregion
279
- export { build, defineConfig, logger };
321
+ export { build, buildSingle, defineConfig, logger };
@@ -1,7 +1,9 @@
1
1
  import { consola } from "consola";
2
+ import Debug from "debug";
2
3
 
3
4
  //#region src/utils/logger.ts
4
5
  const logger = consola.withTag("tsdown");
6
+ const debug = Debug("tsdown");
5
7
 
6
8
  //#endregion
7
- export { logger };
9
+ export { debug, logger };
package/dist/options.d.ts CHANGED
@@ -1,48 +1,54 @@
1
- import type { External } from './features/external';
2
- import type { MarkPartial, MaybePromise, Overwrite } from './utils/types';
3
- import type { InputOptions, OutputOptions } from 'rolldown';
4
- import type { Options as IsolatedDeclOptions } from 'unplugin-isolated-decl';
5
- import type { Options as UnusedOptions } from 'unplugin-unused';
6
- export type Format = 'es' | 'cjs' | 'esm' | 'module' | 'commonjs' | 'iife';
7
- export type Sourcemap = boolean | 'inline' | 'hidden';
1
+ import type { External } from "./features/external.js";
2
+ import type { Arrayable, MarkPartial, MaybePromise, Overwrite } from "./utils/types.js";
3
+ import type { InputOptions, ModuleFormat, OutputOptions } from "rolldown";
4
+ import type { Options as IsolatedDeclOptions } from "unplugin-isolated-decl";
5
+ import type { Options as UnusedOptions } from "unplugin-unused";
6
+ export type Sourcemap = boolean | "inline" | "hidden";
8
7
  /**
9
- * Options for tsdown.
10
- */
8
+ * Options for tsdown.
9
+ */
11
10
  export interface Options {
12
- entry?: InputOptions['input'];
13
- format?: Format | Format[];
14
- plugins?: InputOptions['plugins'];
15
- external?: External;
16
- outDir?: string;
17
- clean?: boolean | string[];
18
- silent?: boolean;
19
- config?: boolean | string;
20
- sourcemap?: Sourcemap;
21
- alias?: Record<string, string>;
22
- /** @default true */
23
- treeshake?: boolean;
24
- /** @default false */
25
- minify?: boolean;
26
- /** @default 'node' */
27
- platform?: 'node' | 'neutral' | 'browser';
28
- /**
29
- * Enable dts generation with `isolatedDeclarations` (experimental)
30
- */
31
- dts?: boolean | IsolatedDeclOptions;
32
- /**
33
- * Enable unused dependencies check with `unplugin-unused` (experimental)
34
- */
35
- unused?: boolean | UnusedOptions;
36
- watch?: boolean | string | string[];
37
- inputOptions?: InputOptions;
38
- outputOptions?: OutputOptions | ((options: OutputOptions, format: Format) => MaybePromise<OutputOptions | void | null>);
11
+ entry?: InputOptions["input"];
12
+ format?: ModuleFormat | ModuleFormat[];
13
+ globalName?: string;
14
+ plugins?: InputOptions["plugins"];
15
+ external?: External;
16
+ outDir?: string;
17
+ clean?: boolean | string[];
18
+ silent?: boolean;
19
+ config?: boolean | string;
20
+ sourcemap?: Sourcemap;
21
+ alias?: Record<string, string>;
22
+ /** @default true */
23
+ treeshake?: boolean;
24
+ /** @default false */
25
+ minify?: boolean;
26
+ /** @default 'node' */
27
+ platform?: "node" | "neutral" | "browser";
28
+ /**
29
+ * Enable dts generation with `isolatedDeclarations` (experimental)
30
+ */
31
+ dts?: boolean | IsolatedDeclOptions;
32
+ /**
33
+ * Enable unused dependencies check with `unplugin-unused` (experimental)
34
+ */
35
+ unused?: boolean | UnusedOptions;
36
+ watch?: boolean | string | string[];
37
+ inputOptions?: InputOptions;
38
+ outputOptions?: OutputOptions | ((options: OutputOptions, format: ModuleFormat) => MaybePromise<OutputOptions | void | null>);
39
+ onSuccess?: () => void | Promise<void>;
40
+ /**
41
+ * Skip bundling node_modules.
42
+ */
43
+ skipNodeModulesBundle?: boolean;
39
44
  }
40
45
  /**
41
- * Options without specifying config file path.
42
- */
43
- export type OptionsWithoutConfig = Omit<Options, 'config'>;
44
- export type ResolvedOptions = Omit<Overwrite<MarkPartial<Options, 'inputOptions' | 'outputOptions' | 'minify' | 'alias' | 'external'>, {
45
- format: Format[];
46
- clean: string[] | false;
47
- }>, 'config'>;
48
- export declare function normalizeOptions(options: Options): Promise<ResolvedOptions>;
46
+ * Options without specifying config file path.
47
+ */
48
+ export type Config = Arrayable<Omit<Options, "config">>;
49
+ export type ResolvedConfig = Extract<Config, any[]>;
50
+ export type ResolvedOptions = Omit<Overwrite<MarkPartial<Options, "globalName" | "inputOptions" | "outputOptions" | "minify" | "alias" | "external" | "onSuccess">, {
51
+ format: ModuleFormat[];
52
+ clean: string[] | false;
53
+ }>, "config">;
54
+ export declare function resolveOptions(options: Options): Promise<[configs: ResolvedOptions[], configFile?: string]>;
package/dist/plugins.d.ts CHANGED
@@ -1 +1 @@
1
- export { ExternalPlugin } from './features/external';
1
+ export { ExternalPlugin } from "./features/external.js";
package/dist/plugins.js CHANGED
@@ -1,3 +1,4 @@
1
- import { ExternalPlugin } from "./external-m3ERo7i1.js";
1
+ import "./logger-Pk57TMWT.js";
2
+ import { ExternalPlugin } from "./external-9r3oq3tH.js";
2
3
 
3
4
  export { ExternalPlugin };
package/dist/run.js CHANGED
@@ -1,18 +1,18 @@
1
- import { logger } from "./logger-e0Fr5WMR.js";
2
- import { default as process } from "node:process";
1
+ import { logger } from "./logger-Pk57TMWT.js";
2
+ import process from "node:process";
3
3
  import { VERSION as rolldownVersion } from "rolldown";
4
- import { default as pc } from "picocolors";
4
+ import pc from "picocolors";
5
5
  import { cac } from "cac";
6
6
 
7
7
  //#region package.json
8
- const version = "0.2.17";
8
+ const version = "0.3.1";
9
9
 
10
10
  //#endregion
11
11
  //#region src/cli.ts
12
12
  async function runCLI() {
13
13
  const cli = cac("tsdown");
14
- cli.command("[...files]", "Bundle files", { ignoreOptionDefaultValue: true }).option("-c, --config <filename>", "Use a custom config file").option("--no-config", "Disable config file").option("--format <format>", "Bundle format: esm, cjs, iife", { default: "esm" }).option("--clean", "Clean output directory").option("--minify", "Minify output").option("--silent", "Suppress non-error logs").option("-d, --out-dir <dir>", "Output directory", { default: "dist" }).option("--treeshake", "Tree-shake bundle", { default: true }).option("--sourcemap", "Generate source map", { default: false }).option("--platform <platform>", "Target platform", { default: "node" }).option("--watch", "Watch mode").action(async (input, flags) => {
15
- logger.level = flags.silent ? 0 : 3;
14
+ cli.command("[...files]", "Bundle files", { ignoreOptionDefaultValue: true }).option("-c, --config <filename>", "Use a custom config file").option("--no-config", "Disable config file").option("--format <format>", "Bundle format: esm, cjs, iife", { default: "esm" }).option("--clean", "Clean output directory").option("--minify", "Minify output").option("--silent", "Suppress non-error logs").option("-d, --out-dir <dir>", "Output directory", { default: "dist" }).option("--treeshake", "Tree-shake bundle", { default: true }).option("--sourcemap", "Generate source map", { default: false }).option("--platform <platform>", "Target platform", { default: "node" }).option("-w, --watch", "Watch mode").action(async (input, flags) => {
15
+ if (!("CONSOLA_LEVEL" in process.env)) logger.level = flags.silent ? 0 : 3;
16
16
  logger.info(`tsdown ${pc.dim(`v${version}`)} powered by rolldown ${pc.dim(`v${rolldownVersion}`)}`);
17
17
  const { build } = await import("./index.js");
18
18
  if (input.length > 0) flags.entry = input;
@@ -1,5 +1,7 @@
1
- import { type ConsolaInstance } from 'consola';
1
+ import { type ConsolaInstance } from "consola";
2
+ import Debug from "debug";
2
3
  /**
3
- * Logger instance
4
- */
4
+ * Logger instance
5
+ */
5
6
  export declare const logger: ConsolaInstance;
7
+ export declare const debug: Debug.Debugger;
@@ -1,3 +1,3 @@
1
- import { type PackageJson } from 'pkg-types';
1
+ import { type PackageJson } from "pkg-types";
2
2
  export declare function readPackageJson(dir: string): Promise<PackageJson | undefined>;
3
- export declare function getPackageType(pkg: PackageJson | undefined): 'module' | 'commonjs';
3
+ export declare function getPackageType(pkg: PackageJson | undefined): "module" | "commonjs";
@@ -1,3 +1,10 @@
1
- export type Overwrite<T, U> = Omit<T, keyof U> & U;
1
+ export type Overwrite<
2
+ T,
3
+ U
4
+ > = Omit<T, keyof U> & U;
2
5
  export type MaybePromise<T> = T | Promise<T>;
3
- export type MarkPartial<T, K extends keyof T> = Omit<Required<T>, K> & Partial<Pick<T, K>>;
6
+ export type MarkPartial<
7
+ T,
8
+ K extends keyof T
9
+ > = Omit<Required<T>, K> & Partial<Pick<T, K>>;
10
+ export type Arrayable<T> = T | T[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsdown",
3
- "version": "0.2.17",
3
+ "version": "0.3.1",
4
4
  "description": "An even faster bundler powered by Rolldown.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -42,27 +42,30 @@
42
42
  "cac": "^6.7.14",
43
43
  "chokidar": "^4.0.1",
44
44
  "consola": "^3.2.3",
45
- "picocolors": "^1.1.0",
46
- "pkg-types": "^1.2.0",
45
+ "debug": "^4.3.7",
46
+ "picocolors": "^1.1.1",
47
+ "pkg-types": "^1.2.1",
47
48
  "rolldown": "nightly",
48
- "tinyglobby": "^0.2.6",
49
+ "tinyglobby": "^0.2.10",
49
50
  "unconfig": "^0.6.0",
50
- "unplugin-isolated-decl": "^0.6.5",
51
+ "unplugin-isolated-decl": "^0.7.2",
51
52
  "unplugin-unused": "^0.2.3"
52
53
  },
53
54
  "devDependencies": {
54
- "@sxzz/eslint-config": "^4.2.0",
55
+ "@sxzz/eslint-config": "^4.4.1",
55
56
  "@sxzz/prettier-config": "^2.0.2",
56
- "@types/node": "^22.7.4",
57
- "bumpp": "^9.6.1",
58
- "eslint": "^9.11.1",
59
- "execa": "^9.4.0",
60
- "fdir": "^6.3.0",
57
+ "@types/debug": "^4.1.12",
58
+ "@types/node": "^22.9.1",
59
+ "bumpp": "^9.8.1",
60
+ "eslint": "^9.15.0",
61
+ "execa": "^9.5.1",
62
+ "fdir": "^6.4.2",
63
+ "oxc-transform": "^0.36.0",
61
64
  "prettier": "^3.3.3",
62
- "tsup": "^8.3.0",
63
- "tsx": "^4.19.1",
64
- "typescript": "~5.6.2",
65
- "vitest": "^2.1.1"
65
+ "tsup": "^8.3.5",
66
+ "tsx": "^4.19.2",
67
+ "typescript": "~5.6.3",
68
+ "vitest": "^2.1.5"
66
69
  },
67
70
  "engines": {
68
71
  "node": ">=18.0.0"
@@ -1,25 +0,0 @@
1
- import { isBuiltin } from "node:module";
2
-
3
- //#region src/features/external.ts
4
- function ExternalPlugin(pkg, platform) {
5
- const deps = pkg && Array.from(getProductionDeps(pkg));
6
- return {
7
- name: "tsdown:external",
8
- resolveId(id) {
9
- let shouldExternal = deps && deps.some((dep) => id === dep || id.startsWith(`${dep}/`));
10
- shouldExternal ||= platform === "node" && isBuiltin(id);
11
- if (shouldExternal) {
12
- return {
13
- id,
14
- external: true
15
- };
16
- }
17
- }
18
- };
19
- }
20
- function getProductionDeps(pkg) {
21
- return new Set([...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]);
22
- }
23
-
24
- //#endregion
25
- export { ExternalPlugin };