bunup 0.8.45 → 0.8.47

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
@@ -14,18 +14,18 @@
14
14
 
15
15
  Bunup is the **blazing-fast build tool** for TypeScript and JavaScript libraries, designed for flawless developer experience and speed, **powered by Bun**.
16
16
 
17
- ![bunup-demo](https://github.com/user-attachments/assets/ce3bc944-fd8a-47b5-bbcb-00e8224fc387)
17
+ ![bunup-demo](/assets/demo.gif)
18
18
 
19
19
  </div>
20
20
  <!-- markdownlint-restore -->
21
21
 
22
22
  ## Key Features
23
23
 
24
+ - ⚡ **Extremely Fast**: Lightning-fast builds and rebuilds.
24
25
  - 🚀 **Easy to Use**: Bunup preconfigures everything you need out-of-the-box. Just focus on your code.
25
- - 🔥 **Bytecode Generation**: Faster startups by compiling to Bun bytecode—perfect for CLIs.
26
26
  - 📦 **[Workspace](https://bunup.dev/docs/guide/workspaces) Support**: Build multiple packages within one config file and command.
27
27
  - 🔄 **Tsup Familiarity**: Familiar tsup-like CLI and config.
28
- - 🎯 **Bun Target**: First-class bundling support for libraries that are intended to run in Bun.
28
+ - 🎯 **Bun Target**: First-class bundling support for libraries that are intended to run on Bun.
29
29
 
30
30
  ## 📚 Documentation
31
31
 
@@ -27,6 +27,12 @@ type BuildMeta = {
27
27
  rootDir: string
28
28
  };
29
29
  type BuildOutputFile = {
30
+ /**
31
+ * The entry point for which this file was generated
32
+ *
33
+ * Undefined for non-entry point files (e.g., assets, sourcemaps, chunks)
34
+ */
35
+ entrypoint: string | undefined
30
36
  /** The kind of the file */
31
37
  kind: "entry-point" | "chunk" | "asset" | "sourcemap" | "bytecode"
32
38
  /** Path to the generated file */
@@ -31,34 +31,13 @@ import pc2 from "picocolors";
31
31
 
32
32
  // src/plugins/internal/linter.ts
33
33
  var rules = [
34
- {
35
- check: (ctx) => ctx.meta.packageJson.data?.type !== "module" && ctx.options.format.length === 1 && ctx.options.format[0] === "esm",
36
- message: 'You are using only ESM format. It is recommended to add "type": "module" to your package.json to help with module resolution.',
37
- logLevel: "recommended"
38
- },
39
34
  {
40
35
  check: (ctx) => {
41
- const deps = ctx.meta.packageJson.data?.dependencies;
42
- return deps && (("typescript" in deps) || ("@types/node" in deps) || ("@types/bun" in deps));
43
- },
44
- message: "TypeScript or @types/* packages are listed as production dependencies. Consider moving them to devDependencies since they're only needed during development.",
45
- logLevel: "recommended"
46
- },
47
- {
48
- check: (ctx) => {
49
- const hasMinification = ctx.options.minify || ctx.options.minifyWhitespace || ctx.options.minifyIdentifiers || ctx.options.minifySyntax;
36
+ const hasMinification = !!(ctx.options.minify || ctx.options.minifyWhitespace || ctx.options.minifyIdentifiers || ctx.options.minifySyntax);
50
37
  return hasMinification && !ctx.options.sourcemap;
51
38
  },
52
39
  message: `You are using minification without source maps. Consider enabling source maps to help with debugging minified code. Learn more: ${link("https://bunup.dev/docs/guide/options#source-maps")}`,
53
40
  logLevel: "recommended"
54
- },
55
- {
56
- check: (ctx) => {
57
- const pkg = ctx.meta.packageJson.data;
58
- return !pkg?.files && !pkg?.private;
59
- },
60
- message: 'Your package.json is missing a "files" field. This means all files will be published to npm. Consider adding a "files" field to control what gets published.',
61
- logLevel: "info"
62
41
  }
63
42
  ];
64
43
  function linter() {
@@ -320,11 +299,12 @@ async function build(partialOptions, rootDir = process.cwd()) {
320
299
  else if (log.level === "info")
321
300
  logger.info(log.message);
322
301
  }
302
+ let entrypointIndex = 0;
323
303
  for (const file of result.outputs) {
324
304
  const relativePathToRootDir = getRelativePathToRootDir(file.path, rootDir);
325
305
  const relativePathToOutputDir = getRelativePathToOutputDir(relativePathToRootDir, options.outDir);
326
306
  if (file.kind === "entry-point") {
327
- logger.success(`${pc2.dim(options.outDir)}/${relativePathToOutputDir}`, {
307
+ logger.success(`${pc2.dim(`${options.outDir}/`)}${relativePathToOutputDir}`, {
328
308
  identifier: options.name
329
309
  });
330
310
  }
@@ -334,8 +314,10 @@ async function build(partialOptions, rootDir = process.cwd()) {
334
314
  relativePathToOutputDir,
335
315
  dts: false,
336
316
  format: fmt,
337
- kind: file.kind
317
+ kind: file.kind,
318
+ entrypoint: entrypoints[entrypointIndex]
338
319
  });
320
+ entrypointIndex++;
339
321
  }
340
322
  });
341
323
  await Promise.all(buildPromises);
@@ -358,7 +340,7 @@ async function build(partialOptions, rootDir = process.cwd()) {
358
340
  const relativePathToOutputDir = cleanPath(`${file.pathInfo.outputPathWithoutExtension}${dtsExtension}`);
359
341
  const relativePathToRootDir = cleanPath(`${options.outDir}/${relativePathToOutputDir}`);
360
342
  if (file.kind === "entry-point") {
361
- logger.success(`${pc2.dim(options.outDir)}/${relativePathToOutputDir}`, {
343
+ logger.success(`${pc2.dim(`${options.outDir}/`)}${relativePathToOutputDir}`, {
362
344
  identifier: options.name
363
345
  });
364
346
  }
@@ -370,7 +352,8 @@ async function build(partialOptions, rootDir = process.cwd()) {
370
352
  relativePathToOutputDir,
371
353
  dts: true,
372
354
  format: fmt,
373
- kind: file.kind
355
+ kind: file.kind,
356
+ entrypoint: file.entrypoint
374
357
  });
375
358
  }
376
359
  }
package/dist/cli/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  import {
4
4
  build,
5
5
  createBuildOptions
6
- } from "../chunk-pn1qh94w.js";
6
+ } from "../chunk-ffytsq4c.js";
7
7
  import"../chunk-snvybwa2.js";
8
8
  import {
9
9
  processLoadedConfigs
@@ -28,7 +28,7 @@ import { loadConfig } from "coffi";
28
28
  import pc3 from "picocolors";
29
29
  import { exec } from "tinyexec";
30
30
  // package.json
31
- var version = "0.8.45";
31
+ var version = "0.8.47";
32
32
 
33
33
  // src/watch.ts
34
34
  import path from "path";
@@ -532,7 +532,7 @@ async function main(args = Bun.argv.slice(2)) {
532
532
  const timeDisplay = formatTime(buildTimeMs);
533
533
  logger.success(`Build completed in ${pc3.green(timeDisplay)}`);
534
534
  if (cliOptions.watch) {
535
- logger.info("\uD83D\uDC40 Watching for file changes");
535
+ logger.info("Watching for file changes...");
536
536
  }
537
537
  if (cliOptions.onSuccess) {
538
538
  logger.info(`Running command: ${cliOptions.onSuccess}`, {
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Arrayable, BuildOptions, DefineConfigItem, DefineWorkspaceItem, Plugin } from "./chunk-0f0jc2gd";
1
+ import { Arrayable, BuildOptions, DefineConfigItem, DefineWorkspaceItem, Plugin } from "./chunk-djb64jje";
2
2
  declare function build(partialOptions: Partial<BuildOptions>, rootDir?: string): Promise<void>;
3
3
  declare function defineConfig(options: Arrayable<DefineConfigItem>): Arrayable<DefineConfigItem>;
4
4
  declare function defineWorkspace(options: DefineWorkspaceItem[]): DefineWorkspaceItem[];
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  build
4
- } from "./chunk-pn1qh94w.js";
4
+ } from "./chunk-ffytsq4c.js";
5
5
  import"./chunk-snvybwa2.js";
6
6
  import"./chunk-gh7z7s46.js";
7
7
  import"./chunk-a76fsvj7.js";
package/dist/plugins.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { BuildContext, BunupPlugin, MaybePromise, Plugin } from "./chunk-0f0jc2gd";
1
+ import { BuildContext, BunupPlugin, MaybePromise, Plugin } from "./chunk-djb64jje";
2
2
  /**
3
3
  * A plugin that copies files and directories to the output directory.
4
4
  *
@@ -8,10 +8,13 @@ import { BuildContext, BunupPlugin, MaybePromise, Plugin } from "./chunk-0f0jc2g
8
8
  */
9
9
  declare function copy(patterns: string[], outPath?: string): BunupPlugin;
10
10
  type CustomExports = Record<string, string | Record<string, string | Record<string, string>>>;
11
+ type Exclude = ((ctx: BuildContext) => string[] | undefined) | string[];
11
12
  interface ExportsPluginOptions {
12
13
  /**
13
14
  * Additional export fields to preserve alongside automatically generated exports
14
15
  *
16
+ * @see https://bunup.dev/docs/plugins/exports#customexports
17
+ *
15
18
  * @example
16
19
  * ```ts
17
20
  * {
@@ -25,6 +28,12 @@ interface ExportsPluginOptions {
25
28
  * ```
26
29
  */
27
30
  customExports?: (ctx: BuildContext) => CustomExports | undefined;
31
+ /**
32
+ * Entry points to exclude from the exports field
33
+ *
34
+ * @see https://bunup.dev/docs/plugins/exports#exclude
35
+ */
36
+ exclude?: Exclude;
28
37
  }
29
38
  /**
30
39
  * A plugin that generates the exports field in the package.json file automatically.
package/dist/plugins.js CHANGED
@@ -49,64 +49,30 @@ function exports(options = {}) {
49
49
  name: "exports",
50
50
  hooks: {
51
51
  onBuildDone: async (ctx) => {
52
- const { output, options: buildOptions, meta } = ctx;
53
- if (!meta.packageJson.path || !meta.packageJson.data) {
54
- return;
55
- }
56
- try {
57
- const { exportsField, entryPoints } = generateExportsFields(output.files);
58
- const files = Array.isArray(meta.packageJson.data.files) ? [
59
- ...new Set([
60
- ...meta.packageJson.data.files,
61
- buildOptions.outDir
62
- ])
63
- ] : [buildOptions.outDir];
64
- const mergedExports = { ...exportsField };
65
- if (options.customExports) {
66
- for (const [key, value] of Object.entries(options.customExports(ctx) ?? {})) {
67
- if (typeof value === "string") {
68
- mergedExports[key] = value;
69
- } else {
70
- const existingExport = mergedExports[key];
71
- if (typeof existingExport === "object" && existingExport !== null) {
72
- mergedExports[key] = {
73
- ...existingExport,
74
- ...value
75
- };
76
- } else {
77
- mergedExports[key] = value;
78
- }
79
- }
80
- }
81
- }
82
- const { main, module, types, ...restPackageJson } = meta.packageJson.data;
83
- const newPackageJson = {
84
- name: meta.packageJson.data.name,
85
- description: meta.packageJson.data.description,
86
- version: meta.packageJson.data.version,
87
- type: meta.packageJson.data.type,
88
- private: meta.packageJson.data.private,
89
- files,
90
- ...entryPoints,
91
- exports: mergedExports
92
- };
93
- for (const key in restPackageJson) {
94
- if (Object.hasOwn(restPackageJson, key) && !Object.hasOwn(newPackageJson, key)) {
95
- newPackageJson[key] = restPackageJson[key];
96
- }
97
- }
98
- await Bun.write(meta.packageJson.path, JSON.stringify(newPackageJson, null, 2));
99
- } catch {
100
- logger.error("Failed to update package.json");
101
- }
52
+ await processPackageJsonExports(ctx, options);
102
53
  }
103
54
  }
104
55
  };
105
56
  }
106
- function generateExportsFields(files) {
57
+ async function processPackageJsonExports(ctx, options) {
58
+ const { output, options: buildOptions, meta } = ctx;
59
+ if (!meta.packageJson.path || !meta.packageJson.data) {
60
+ return;
61
+ }
62
+ try {
63
+ const { exportsField, entryPoints } = generateExportsFields(output.files, options.exclude, ctx);
64
+ const updatedFiles = createUpdatedFilesArray(meta.packageJson.data, buildOptions.outDir);
65
+ const mergedExports = mergeCustomExportsWithGenerated(exportsField, options.customExports, ctx);
66
+ const newPackageJson = createUpdatedPackageJson(meta.packageJson.data, entryPoints, mergedExports, updatedFiles);
67
+ await Bun.write(meta.packageJson.path, JSON.stringify(newPackageJson, null, 2));
68
+ } catch {
69
+ logger.error("Failed to update package.json");
70
+ }
71
+ }
72
+ function generateExportsFields(files, exclude, ctx) {
107
73
  const exportsField = {};
108
74
  const entryPoints = {};
109
- const filteredFiles = filterFiles(files);
75
+ const filteredFiles = filterFiles(files, exclude, ctx);
110
76
  for (const file of filteredFiles) {
111
77
  const exportType = formatToExportField(file.format, file.dts);
112
78
  const relativePath = `./${cleanPath(file.relativePathToRootDir)}`;
@@ -122,21 +88,76 @@ function generateExportsFields(files) {
122
88
  }
123
89
  return { exportsField, entryPoints };
124
90
  }
125
- function filterFiles(files) {
126
- return files.filter((file) => JS_DTS_RE.test(file.fullPath) && file.kind === "entry-point");
91
+ function createUpdatedFilesArray(packageJsonData, outDir) {
92
+ const existingFiles = Array.isArray(packageJsonData.files) ? packageJsonData.files : [];
93
+ return [...new Set([...existingFiles, outDir])];
94
+ }
95
+ function mergeCustomExportsWithGenerated(baseExports, customExportsProvider, ctx) {
96
+ const mergedExports = { ...baseExports };
97
+ if (!customExportsProvider) {
98
+ return mergedExports;
99
+ }
100
+ const customExports = customExportsProvider(ctx) ?? {};
101
+ for (const [key, value] of Object.entries(customExports)) {
102
+ if (typeof value === "string") {
103
+ mergedExports[key] = value;
104
+ } else {
105
+ const existingExport = mergedExports[key];
106
+ if (typeof existingExport === "object" && existingExport !== null) {
107
+ mergedExports[key] = {
108
+ ...existingExport,
109
+ ...value
110
+ };
111
+ } else {
112
+ mergedExports[key] = value;
113
+ }
114
+ }
115
+ }
116
+ return mergedExports;
117
+ }
118
+ function createUpdatedPackageJson(originalData, entryPoints, exports2, files) {
119
+ const { main, module, types, ...restPackageJson } = originalData;
120
+ const newPackageJson = {
121
+ name: originalData.name,
122
+ description: originalData.description,
123
+ version: originalData.version,
124
+ type: originalData.type,
125
+ private: originalData.private,
126
+ files,
127
+ ...entryPoints,
128
+ exports: exports2
129
+ };
130
+ for (const key in restPackageJson) {
131
+ if (Object.hasOwn(restPackageJson, key) && !Object.hasOwn(newPackageJson, key)) {
132
+ newPackageJson[key] = restPackageJson[key];
133
+ }
134
+ }
135
+ return newPackageJson;
136
+ }
137
+ function filterFiles(files, exclude, ctx) {
138
+ return files.filter((file) => JS_DTS_RE.test(file.fullPath) && file.kind === "entry-point" && file.entrypoint && !isExcluded(file.entrypoint, exclude, ctx));
139
+ }
140
+ function isExcluded(entrypoint, exclude, ctx) {
141
+ if (!exclude) {
142
+ return false;
143
+ }
144
+ if (typeof exclude === "function") {
145
+ const excluded = exclude(ctx);
146
+ if (excluded) {
147
+ return excluded.some((pattern) => new Bun.Glob(pattern).match(entrypoint));
148
+ }
149
+ }
150
+ if (Array.isArray(exclude)) {
151
+ return exclude.some((pattern) => new Bun.Glob(pattern).match(entrypoint));
152
+ }
153
+ return false;
127
154
  }
128
155
  function getExportKey(relativePathToOutputDir) {
129
156
  const pathSegments = cleanPath(removeExtension(relativePathToOutputDir)).split("/");
130
157
  if (pathSegments.length === 1 && pathSegments[0].startsWith("index")) {
131
158
  return ".";
132
159
  }
133
- return `./${pathSegments.filter((p) => !p.startsWith("index")).join("/")}`;
134
- }
135
- function exportFieldToEntryPoint(exportField) {
136
- return exportField === "types" ? "types" : exportField === "require" ? "main" : "module";
137
- }
138
- function formatToExportField(format, dts) {
139
- return dts ? "types" : format === "esm" ? "import" : "require";
160
+ return `./${pathSegments.filter((segment) => !segment.startsWith("index")).join("/")}`;
140
161
  }
141
162
  function removeExtension(filePath) {
142
163
  const basename2 = path.basename(filePath);
@@ -148,6 +169,12 @@ function removeExtension(filePath) {
148
169
  const directory = path.dirname(filePath);
149
170
  return directory === "." ? nameWithoutExtensions : path.join(directory, nameWithoutExtensions);
150
171
  }
172
+ function exportFieldToEntryPoint(exportField) {
173
+ return exportField === "types" ? "types" : exportField === "require" ? "main" : "module";
174
+ }
175
+ function formatToExportField(format, dts) {
176
+ return dts ? "types" : format === "esm" ? "import" : "require";
177
+ }
151
178
  // src/plugins/built-in/inject-styles.ts
152
179
  import path2 from "path";
153
180
  function injectStyles(options) {
package/package.json CHANGED
@@ -1,26 +1,12 @@
1
1
  {
2
2
  "name": "bunup",
3
3
  "description": "⚡ A blazing-fast build tool for your libraries built with Bun.",
4
- "version": "0.8.45",
4
+ "version": "0.8.47",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"
8
8
  ],
9
- "module": "./dist/index.js",
10
- "types": "./dist/index.d.ts",
11
- "exports": {
12
- ".": {
13
- "import": "./dist/index.js",
14
- "types": "./dist/index.d.ts"
15
- },
16
- "./plugins": {
17
- "import": "./dist/plugins.js",
18
- "types": "./dist/plugins.d.ts"
19
- },
20
- "./cli": {
21
- "import": "./dist/cli/index.js"
22
- }
23
- },
9
+ "exports": {},
24
10
  "license": "MIT",
25
11
  "author": "Arshad Yaseen <m@arshadyaseen.com> (https://arshadyaseen.com)",
26
12
  "maintainers": [