bunup 0.14.11 → 0.14.13

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
@@ -10,10 +10,10 @@
10
10
  ![Bunup](/assets/bunup-title.svg)
11
11
 
12
12
  [![NPM Version](https://img.shields.io/npm/v/bunup?logo=npm&logoColor=212121&label=version&labelColor=ffc44e&color=212121)](https://npmjs.com/package/bunup)
13
- [![Built with Bun](https://img.shields.io/badge/Built_with-Bun-fbf0df?logo=bun&labelColor=212121)](https://bun.sh)
13
+ [![Built with Bun](https://img.shields.io/badge/Built_with-Bun-fbf0df?logo=bun&labelColor=212121)](https://bun.com)
14
14
  [![sponsor](https://img.shields.io/badge/sponsor-EA4AAA?logo=githubsponsors&labelColor=FAFAFA)](https://github.com/sponsors/arshad-yaseen)
15
15
 
16
- Bunup helps you ship TypeScript/React libraries faster with great DX — built on Bun.
16
+ Bunup helps you ship TypeScript/React libraries faster with great DX — built on [Bun](https://bun.com)'s native bundler.
17
17
  </div>
18
18
  <!-- markdownlint-restore -->
19
19
 
@@ -77,6 +77,8 @@ For more, see the full documentation: https://bunup.dev
77
77
 
78
78
  We welcome contributions! Please read the [contributing guide](CONTRIBUTING.md).
79
79
 
80
+ ![Contributors](https://contributors-table.vercel.app/image?repo=bunup/bunup&width=50&columns=15)
81
+
80
82
  <div align="center">
81
83
 
82
84
  <img src="https://cdn.jsdelivr.net/gh/arshad-yaseen/static/sponsors.svg" alt="Sponsors" />
package/dist/cli/index.js CHANGED
@@ -2,34 +2,154 @@
2
2
  // @bun
3
3
  import {
4
4
  build,
5
- printBuildReport,
6
5
  processLoadedConfigs,
7
6
  resolveBuildOptions
8
- } from "../shared/bunup-nsnkrmw3.js";
7
+ } from "../shared/bunup-0cz3ntgr.js";
9
8
  import {
10
9
  BunupCLIError,
11
10
  BunupWatchError,
12
11
  __require,
13
12
  __toESM,
14
13
  ensureArray,
14
+ formatFileSize,
15
15
  getShortFilePath,
16
16
  handleError,
17
17
  handleErrorAndExit,
18
+ isJavascriptFile,
19
+ isTypeScriptFile,
18
20
  logTime,
19
21
  logger,
20
22
  parseErrorMessage
21
- } from "../shared/bunup-er5nnjqp.js";
23
+ } from "../shared/bunup-025ckbke.js";
22
24
 
23
25
  // packages/bunup/src/cli/index.ts
24
26
  import { loadConfig } from "coffi";
25
- import pc3 from "picocolors";
27
+ import pc4 from "picocolors";
26
28
  // packages/bunup/package.json
27
- var version = "0.14.11";
29
+ var version = "0.14.13";
30
+
31
+ // packages/bunup/src/printer/print-build-report.ts
32
+ import { promisify } from "util";
33
+ import { brotliCompress } from "zlib";
34
+ import pc from "picocolors";
35
+ var brotliAsync = promisify(brotliCompress);
36
+ async function printBuildReport(buildOutput) {
37
+ const options = buildOutput.options;
38
+ const { gzip = true, brotli = false, maxBundleSize } = options.report ?? {};
39
+ const showCompression = gzip || brotli;
40
+ const files = await Promise.all(buildOutput.files.map(async (file) => {
41
+ const pathRelative = file.pathRelativeToOutdir;
42
+ const bunFile = Bun.file(file.fullPath);
43
+ const size = bunFile.size;
44
+ const isDts = file.dts && file.kind === "entry-point";
45
+ const isJs = isTypeScriptFile(file.fullPath) || isJavascriptFile(file.fullPath);
46
+ let gzipSize;
47
+ let brotliSize;
48
+ if (showCompression) {
49
+ const uint8 = new Uint8Array(await bunFile.arrayBuffer());
50
+ const [gzipResult, brotliResult] = await Promise.all([
51
+ gzip ? Promise.resolve(Bun.gzipSync(uint8)) : Promise.resolve(null),
52
+ brotli ? brotliAsync(uint8) : Promise.resolve(null)
53
+ ]);
54
+ gzipSize = gzipResult?.length;
55
+ brotliSize = brotliResult?.length;
56
+ }
57
+ return {
58
+ path: pathRelative,
59
+ fullPath: `${options.outDir}/${pathRelative}`,
60
+ size,
61
+ gzipSize,
62
+ brotliSize,
63
+ format: file.format,
64
+ isDts,
65
+ isJs
66
+ };
67
+ }));
68
+ const totalSize = files.reduce((sum, file) => sum + file.size, 0);
69
+ const totalGzipSize = files.reduce((sum, file) => sum + (file.gzipSize || 0), 0);
70
+ const totalBrotliSize = files.reduce((sum, file) => sum + (file.brotliSize || 0), 0);
71
+ const formats = ensureArray(options.format);
72
+ const showFormat = formats.length > 1 || formats[0] === "cjs";
73
+ const formatLabelWidth = showFormat ? Math.max(...formats.map((f) => `[${f}] `.length)) : 0;
74
+ const pathWidth = Math.max(...files.map((f) => f.fullPath.length), "Output".length);
75
+ const sizeWidth = Math.max(formatFileSize(totalSize).length, "Raw".length);
76
+ const gzipWidth = gzip ? Math.max(formatFileSize(totalGzipSize).length, "Gzip".length) : 0;
77
+ const brotliWidth = brotli ? Math.max(formatFileSize(totalBrotliSize).length, "Brotli".length) : 0;
78
+ const pad = (str, width, align = "left") => {
79
+ const diff = width - str.length;
80
+ return align === "left" ? str + " ".repeat(Math.max(0, diff)) : " ".repeat(Math.max(0, diff)) + str;
81
+ };
82
+ console.log("");
83
+ if (options.name) {
84
+ console.log("");
85
+ console.log(` ${pc.bgBlueBright(` ${options.name} `)}`);
86
+ }
87
+ console.log("");
88
+ const headers = [
89
+ pad(" Output", pathWidth + formatLabelWidth + 2),
90
+ pad("Raw", sizeWidth, "right")
91
+ ];
92
+ if (gzip)
93
+ headers.push(pad("Gzip", gzipWidth, "right"));
94
+ if (brotli)
95
+ headers.push(pad("Brotli", brotliWidth, "right"));
96
+ console.log(pc.dim(headers.join(" ")));
97
+ console.log("");
98
+ for (const file of files) {
99
+ let formatLabel = "";
100
+ if (showFormat) {
101
+ let plainFormatLabel = "";
102
+ if (file.isJs) {
103
+ plainFormatLabel = `[${file.format}] `;
104
+ }
105
+ formatLabel = pc.dim(pad(plainFormatLabel, formatLabelWidth));
106
+ }
107
+ const outDirWithSlash = `${options.outDir}/`;
108
+ const fileName = file.isDts ? pc.green(pc.bold(file.path)) : file.path;
109
+ const styledPath = `${pc.dim(outDirWithSlash)}${fileName}`;
110
+ const plainPath = `${outDirWithSlash}${file.path}`;
111
+ const filePathColumn = ` ${formatLabel}${styledPath}${" ".repeat(Math.max(0, pathWidth - plainPath.length))}`;
112
+ const fileRow = [
113
+ filePathColumn,
114
+ pad(formatFileSize(file.size), sizeWidth, "right")
115
+ ];
116
+ if (gzip) {
117
+ const gzipStr = file.gzipSize ? formatFileSize(file.gzipSize) : pc.dim("-");
118
+ fileRow.push(pad(gzipStr, gzipWidth, "right"));
119
+ }
120
+ if (brotli) {
121
+ const brotliStr = file.brotliSize ? formatFileSize(file.brotliSize) : pc.dim("-");
122
+ fileRow.push(pad(brotliStr, brotliWidth, "right"));
123
+ }
124
+ console.log(fileRow.join(" "));
125
+ }
126
+ console.log("");
127
+ const summaryRow = [
128
+ ` ${pc.bold(pad(`${files.length} files`, pathWidth + formatLabelWidth))}`,
129
+ pc.bold(pad(formatFileSize(totalSize), sizeWidth, "right"))
130
+ ];
131
+ if (gzip && totalGzipSize > 0) {
132
+ summaryRow.push(pc.bold(pad(formatFileSize(totalGzipSize), gzipWidth, "right")));
133
+ } else if (gzip) {
134
+ summaryRow.push(pad("", gzipWidth));
135
+ }
136
+ if (brotli && totalBrotliSize > 0) {
137
+ summaryRow.push(pc.bold(pad(formatFileSize(totalBrotliSize), brotliWidth, "right")));
138
+ } else if (brotli) {
139
+ summaryRow.push(pad("", brotliWidth));
140
+ }
141
+ console.log(summaryRow.join(" "));
142
+ if (maxBundleSize && totalSize > maxBundleSize) {
143
+ console.log("");
144
+ console.warn(pc.yellow(` Bundle size ${pc.bold(formatFileSize(totalSize))} exceeds limit ${pc.bold(formatFileSize(maxBundleSize))}`));
145
+ }
146
+ console.log("");
147
+ }
28
148
 
29
149
  // packages/bunup/src/watch.ts
30
150
  import path from "path";
31
- import pc from "picocolors";
32
- async function watch(userOptions, rootDir) {
151
+ import pc2 from "picocolors";
152
+ async function watch(userOptions, rootDir, configFilePath) {
33
153
  const watchPaths = new Set;
34
154
  const options = resolveBuildOptions(userOptions);
35
155
  const uniqueEntries = new Set(ensureArray(options.entry));
@@ -38,6 +158,9 @@ async function watch(userOptions, rootDir) {
38
158
  const parentDir = path.dirname(entryPath);
39
159
  watchPaths.add(parentDir);
40
160
  }
161
+ if (configFilePath) {
162
+ watchPaths.add(configFilePath);
163
+ }
41
164
  const chokidar = await import("chokidar");
42
165
  const watcher = chokidar.watch(Array.from(watchPaths), {
43
166
  ignoreInitial: true,
@@ -67,14 +190,14 @@ async function watch(userOptions, rootDir) {
67
190
  lastChangedFile = changed;
68
191
  if (!initial) {
69
192
  console.log(`
70
- ${buildCount > 1 ? pc.magentaBright(`[x${buildCount}] `) : ""}${pc.green(`Changed:`)} ${changed}${options.name ? ` ${pc.bgBlueBright(` ${options.name} `)}` : ""}`);
193
+ ${buildCount > 1 ? pc2.magentaBright(`[x${buildCount}] `) : ""}${pc2.green(`Changed:`)} ${changed}${options.name ? ` ${pc2.bgBlueBright(` ${options.name} `)}` : ""}`);
71
194
  }
72
195
  const start = performance.now();
73
- const buildOutput = await build(options, rootDir);
74
- await printBuildReport(buildOutput, options);
196
+ const buildOutput = await build(userOptions, rootDir);
197
+ await printBuildReport(buildOutput);
75
198
  if (!initial) {
76
199
  console.log(`
77
- ${pc.green("\u2713")} Rebuild completed in ${pc.green(logTime(performance.now() - start))}`);
200
+ ${pc2.green("\u2713")} Rebuild completed in ${pc2.green(logTime(performance.now() - start))}`);
78
201
  }
79
202
  } catch (error) {
80
203
  handleError(error);
@@ -82,30 +205,42 @@ async function watch(userOptions, rootDir) {
82
205
  isRebuilding = false;
83
206
  }
84
207
  };
85
- watcher.on("change", (path2) => {
86
- triggerRebuild(false, getShortFilePath(path2));
208
+ watcher.on("change", (changedPath) => {
209
+ if (configFilePath && changedPath === configFilePath) {
210
+ console.log(pc2.yellow(` Please restart watch mode to apply configuration changes.
211
+ `));
212
+ cleanup();
213
+ return;
214
+ }
215
+ triggerRebuild(false, getShortFilePath(changedPath));
87
216
  });
88
217
  watcher.on("error", (error) => {
89
218
  throw new BunupWatchError(`Watcher error: ${parseErrorMessage(error)}`);
90
219
  });
220
+ const cleanup = async () => {
221
+ await watcher.close();
222
+ process.exit(0);
223
+ };
224
+ process.on("SIGINT", cleanup);
225
+ process.on("SIGTERM", cleanup);
91
226
  await triggerRebuild(true);
92
227
  }
93
228
 
94
229
  // packages/bunup/src/cli/options.ts
95
- import pc2 from "picocolors";
230
+ import pc3 from "picocolors";
96
231
  import { cli, z } from "zlye";
97
232
  var program = cli().name("bunup").version(version).description("A blazing-fast build tool for your TypeScript/React libraries - built on Bun").with({
98
233
  ignoreOptionDefaultValue: true
99
234
  }).example([
100
- pc2.gray(`${pc2.blue("bunup")} # Basic build`),
101
- pc2.gray(`${pc2.blue("bunup src/index.ts")} # Single entry file`),
102
- pc2.gray(`${pc2.blue("bunup src/**/*.ts")} # Glob pattern for multiple files`),
103
- pc2.gray(`${pc2.blue("bunup --watch")} # Watch mode`),
104
- pc2.gray(`${pc2.blue("bunup --format cjs,esm")} # Multiple formats`),
105
- pc2.gray(`${pc2.blue("bunup --target bun")} # Bun target`),
106
- pc2.gray(`${pc2.blue("bunup src/cli.ts")} # Multiple entries`),
107
- pc2.gray(`${pc2.blue("bunup --dts.splitting")} # Declaration splitting`),
108
- pc2.gray(`${pc2.blue("bunup --no-clean")} # Disable cleaning output directory before build`)
235
+ pc3.gray(`${pc3.blue("bunup")} # Basic build`),
236
+ pc3.gray(`${pc3.blue("bunup src/index.ts")} # Single entry file`),
237
+ pc3.gray(`${pc3.blue("bunup src/**/*.ts")} # Glob pattern for multiple files`),
238
+ pc3.gray(`${pc3.blue("bunup --watch")} # Watch mode`),
239
+ pc3.gray(`${pc3.blue("bunup --format cjs,esm")} # Multiple formats`),
240
+ pc3.gray(`${pc3.blue("bunup --target bun")} # Bun target`),
241
+ pc3.gray(`${pc3.blue("bunup src/cli.ts")} # Multiple entries`),
242
+ pc3.gray(`${pc3.blue("bunup --dts.splitting")} # Declaration splitting`),
243
+ pc3.gray(`${pc3.blue("bunup --no-clean")} # Disable cleaning output directory before build`)
109
244
  ]).option("entry", z.union(z.string().describe("Entry file or glob pattern"), z.array(z.string()).describe("Multiple entry files or globs")).alias("e").optional()).option("config", z.union(z.string().describe("Path to a custom configuration file").alias("c").example("./configs/custom.bunup.config.js"), z.boolean().describe("Whether to use a configuration file").default(true)).optional()).option("filter", z.array(z.string()).describe("Filter workspace packages by name").optional()).option("name", z.string().describe("Name of the build configuration (for logging and identification)").example("my-library").optional()).option("out-dir", z.string().describe("Output directory for bundled files").alias("o").default("dist")).option("format", z.union(z.string().choices(["esm", "cjs", "iife"]).describe("Single output format"), z.array(z.string().choices(["esm", "cjs", "iife"])).describe("Multiple output formats")).alias("f").default("esm")).option("minify", z.boolean().describe("Enable all minification options (whitespace, identifiers, syntax)").optional()).option("minify-whitespace", z.boolean().describe("Minify whitespace in the output to reduce file size").optional()).option("minify-identifiers", z.boolean().describe("Minify identifiers by renaming variables to shorter names").optional()).option("minify-syntax", z.boolean().describe("Minify syntax by optimizing code structure").optional()).option("watch", z.boolean().describe("Watch for file changes and rebuild automatically").optional()).option("clean", z.boolean().describe("Clean the output directory before building").default(true)).option("silent", z.boolean().describe("Disable logging during the build process").alias("q").optional()).option("splitting", z.boolean().describe("Enable code splitting").default(true, "enabled by default for ESM format")).option("conditions", z.array(z.string()).describe("Package.json export conditions for import resolution").optional()).option("target", z.string().choices(["bun", "node", "browser"]).describe("Target environment for the bundle").alias("t").default("node")).option("external", z.array(z.string()).describe("External packages that should not be bundled").optional()).option("no-external", z.array(z.string()).describe("Packages that should be bundled even if listed in external").optional()).option("shims", z.boolean().describe("Enable shims for Node.js globals and ESM/CJS interoperability").optional()).option("report", z.object({
110
245
  gzip: z.boolean().describe("Enable gzip compression size calculation").default(true),
111
246
  brotli: z.boolean().describe("Enable brotli compression size calculation").optional(),
@@ -185,6 +320,7 @@ async function main(args = Bun.argv.slice(2)) {
185
320
  }
186
321
  logger.info("Build started");
187
322
  const startTime = performance.now();
323
+ const buildOutputs = [];
188
324
  await Promise.all(configsToProcess.flatMap(({ options, rootDir }) => {
189
325
  const optionsArray = ensureArray(options);
190
326
  return optionsArray.map(async (o) => {
@@ -193,23 +329,23 @@ async function main(args = Bun.argv.slice(2)) {
193
329
  ...removeCliOnlyOptions(cliOptions)
194
330
  };
195
331
  if (userOptions.watch) {
196
- await watch(userOptions, rootDir);
332
+ await watch(userOptions, rootDir, filepath);
197
333
  } else {
198
- await build(userOptions, rootDir);
334
+ buildOutputs.push(await build(userOptions, rootDir));
199
335
  }
200
336
  });
201
337
  }));
338
+ const buildTimeMs = performance.now() - startTime;
339
+ if (!cliOptions.watch && !shouldSilent) {
340
+ await Promise.all(buildOutputs.map((o) => printBuildReport(o)));
341
+ }
202
342
  if (cliOptions.watch) {
203
343
  console.log(`
204
- ${pc3.bgMagentaBright(" WATCH ")} Watching for file changes...
344
+ ${pc4.bgMagentaBright(" WATCH ")} Watching for file changes...
205
345
  `);
206
346
  }
207
- const buildTimeMs = performance.now() - startTime;
208
347
  logger.space();
209
- logger.success(`Build completed in ${pc3.green(logTime(buildTimeMs))}`);
210
- if (!cliOptions.watch) {
211
- process.exit(process.exitCode ?? 0);
212
- }
348
+ logger.success(`Build completed in ${pc4.green(logTime(buildTimeMs))}`);
213
349
  }
214
350
  var CLI_ONLY_OPTIONS = ["config", "filter"];
215
351
  function removeCliOnlyOptions(options) {
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Arrayable, BuildContext, BuildMeta, BuildOptions, BuildOutput, BuildOutputFile, BunupPlugin, DefineConfigItem, DefineWorkspaceItem, WithOptional } from "./shared/bunup-zenttvjh";
1
+ import { Arrayable, BuildContext, BuildMeta, BuildOptions, BuildOutput, BuildOutputFile, BunupPlugin, DefineConfigItem, DefineWorkspaceItem, WithOptional } from "./shared/bunup-kgz99eee";
2
2
  declare function build(userOptions: Partial<BuildOptions>, rootDir?: string): Promise<BuildOutput>;
3
3
  declare function defineConfig(options: Arrayable<DefineConfigItem>): Arrayable<DefineConfigItem>;
4
4
  declare function defineWorkspace(options: WithOptional<DefineWorkspaceItem, "config">[], sharedOptions?: Partial<DefineConfigItem>): DefineWorkspaceItem[];
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  // @bun
2
2
  import {
3
3
  build
4
- } from "./shared/bunup-nsnkrmw3.js";
5
- import"./shared/bunup-er5nnjqp.js";
4
+ } from "./shared/bunup-0cz3ntgr.js";
5
+ import"./shared/bunup-025ckbke.js";
6
6
  // packages/bunup/src/define.ts
7
7
  function defineConfig(options) {
8
8
  return options;
package/dist/plugins.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { BuildOptions, BunupPlugin, BunupPluginHooks, exports, injectStyles, unused } from "./shared/bunup-zenttvjh";
1
+ import { BuildOptions, BunupPlugin, BunupPluginHooks, exports, injectStyles, unused } from "./shared/bunup-kgz99eee";
2
2
  type CopyOptions = {
3
3
  /** Whether to follow symbolic links when copying files. */
4
4
  followSymlinks?: boolean
package/dist/plugins.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  logger,
8
8
  shims,
9
9
  unused
10
- } from "./shared/bunup-er5nnjqp.js";
10
+ } from "./shared/bunup-025ckbke.js";
11
11
 
12
12
  // packages/bunup/src/plugins/copy.ts
13
13
  import { basename, extname, join } from "path";
@@ -60,6 +60,7 @@ class CopyBuilder {
60
60
  } else {
61
61
  destinationPath = buildOptions.outDir;
62
62
  }
63
+ const activeFiles = new Set;
63
64
  for (const pattern of this._patterns) {
64
65
  const glob = new Bun.Glob(pattern);
65
66
  for await (const scannedPath of glob.scan({
@@ -69,6 +70,7 @@ class CopyBuilder {
69
70
  followSymlinks: this._options?.followSymlinks
70
71
  })) {
71
72
  const sourcePath = join(meta.rootDir, scannedPath);
73
+ activeFiles.add(sourcePath);
72
74
  if (isWatchMode && watchBehavior === "changed") {
73
75
  const stat = await Bun.file(sourcePath).stat();
74
76
  const lastModified = stat?.mtime?.getTime() ?? 0;
@@ -93,6 +95,13 @@ class CopyBuilder {
93
95
  }
94
96
  }
95
97
  }
98
+ if (isWatchMode && watchBehavior === "changed") {
99
+ for (const cachedPath of this._fileCache.keys()) {
100
+ if (!activeFiles.has(cachedPath)) {
101
+ this._fileCache.delete(cachedPath);
102
+ }
103
+ }
104
+ }
96
105
  }
97
106
  };
98
107
  }
@@ -31,9 +31,6 @@ class Logger {
31
31
  }
32
32
  return Logger.instance;
33
33
  }
34
- dispose() {
35
- this.loggedOnceMessages.clear();
36
- }
37
34
  setSilent(value) {
38
35
  this.silent = value ?? false;
39
36
  }
@@ -131,6 +128,14 @@ class Logger {
131
128
  console.log(...args);
132
129
  }
133
130
  }
131
+ list(items, options) {
132
+ return items.map((item) => {
133
+ const bullet = pc.cyan("-");
134
+ const text = options?.dim ? pc.dim(item) : item;
135
+ return ` ${bullet} ${text}`;
136
+ }).join(`
137
+ `);
138
+ }
134
139
  }
135
140
  function logTime(ms) {
136
141
  return ms >= 1000 ? pc.green(`${(ms / 1000).toFixed(2)}s`) : pc.green(`${Math.round(ms)}ms`);
@@ -227,9 +232,12 @@ var handleError = (error, context) => {
227
232
  errorType = "BUNUP ERROR";
228
233
  }
229
234
  const knownError = KNOWN_ERRORS.find((error2) => error2.pattern.test(errorMessage) && (error2.errorType === errorType || !error2.errorType));
230
- if (!knownError && errorType) {
235
+ if (!knownError) {
231
236
  console.error(`
232
- ${pc2.red(errorType)} ${contextPrefix}${errorMessage}`);
237
+ ${pc2.bgRed(` ${errorType} `)}
238
+ ${contextPrefix}${errorMessage}`.split(`
239
+ `).map((line) => ` ${line}`).join(`
240
+ `));
233
241
  }
234
242
  if (knownError) {
235
243
  console.log(`
@@ -249,10 +257,30 @@ ${pc2.red(errorType)} ${contextPrefix}${errorMessage}`);
249
257
 
250
258
  <!-- Please provide any additional context about what you were trying to do when the error occurred -->`);
251
259
  console.error(pc2.white(`
252
- If you think this is a bug, please `) + link(issueUrl.toString(), "open an issue") + ` with details about this error
260
+ If you think this is a bug, please `) + link(issueUrl.toString(), "open an issue") + ` with details about this error
253
261
  `);
254
262
  }
255
263
  };
264
+ var noEntryPointsFoundError = (defaultEntrypoints) => {
265
+ return `${pc2.red(pc2.bold(`
266
+ No entry points found`))}
267
+
268
+ ` + `Looked for these default entry points:
269
+
270
+ ` + logger.list(defaultEntrypoints, { dim: true }) + `
271
+
272
+ You can specify entry points via CLI like ${pc2.green("bunup lib/main.ts")}, ` + `use multiple entries like ${pc2.green("bunup components/button.tsx utils/format.ts")}, or add the entry option in your bunup config.`;
273
+ };
274
+ var invalidEntryPointsError = (userEntrypoints) => {
275
+ const entryPointsFormatted = logger.list(userEntrypoints, { dim: true });
276
+ const isMultiple = userEntrypoints.length > 1;
277
+ return `${pc2.red(pc2.bold(`
278
+ Entry ${isMultiple ? "points do not exist" : "point does not exist"}`))}
279
+
280
+ ${entryPointsFormatted}
281
+
282
+ Please check that ${isMultiple ? "these paths exist and point" : "this path exists and points"} to ${isMultiple ? "valid files" : "a valid file"}.`;
283
+ };
256
284
  var handleErrorAndExit = (error, context) => {
257
285
  handleError(error, context);
258
286
  process.exit(1);
@@ -272,7 +300,7 @@ var CSS_RE = /\.(css)$/;
272
300
 
273
301
  // packages/bunup/src/utils.ts
274
302
  function ensureArray(value) {
275
- return Array.isArray(value) ? value : [value];
303
+ return Array.isArray(value) ? value : [value].filter(Boolean);
276
304
  }
277
305
  function ensureObject(value) {
278
306
  return typeof value === "object" && value !== null ? value : {};
@@ -325,41 +353,45 @@ function getShortFilePath(filePath, maxLength = 3) {
325
353
  return shortPath;
326
354
  }
327
355
  async function cleanOutDir(rootDir, outDir) {
356
+ const normalizedOutDir = path.normalize(outDir);
357
+ if (["/", ".", "..", "~"].includes(normalizedOutDir) || normalizedOutDir.startsWith("/") || normalizedOutDir.startsWith("~")) {
358
+ throw new BunupBuildError(`Invalid output directory: "${outDir}" is not allowed`);
359
+ }
328
360
  const outDirPath = path.join(rootDir, outDir);
361
+ if (!path.normalize(outDirPath).startsWith(path.normalize(rootDir))) {
362
+ throw new BunupBuildError(`Output directory "${outDir}" escapes root directory`);
363
+ }
329
364
  try {
330
365
  await fs.rm(outDirPath, { recursive: true, force: true });
366
+ await fs.mkdir(outDirPath, { recursive: true });
331
367
  } catch (error) {
332
- throw new BunupBuildError(`Failed to clean output directory: ${error}`);
368
+ throw new BunupBuildError(`Failed to manage output directory: ${error}`);
333
369
  }
334
- await fs.mkdir(outDirPath, { recursive: true });
335
370
  }
336
371
  function cleanPath(path2) {
337
- let cleaned = normalize(path2).replace(/\\/g, "/");
338
- cleaned = cleaned.replace(/^[a-zA-Z]:\//, "");
339
- cleaned = cleaned.replace(/^\/+/, "");
340
- cleaned = cleaned.replace(/\/+/g, "/");
341
- return cleaned;
372
+ return normalize(path2).replace(/\\/g, "/").replace(/^[a-zA-Z]:\//, "").replace(/^\/+/, "").replace(/\/+/g, "/");
342
373
  }
374
+ var listFormatter = new Intl.ListFormat("en", {
375
+ style: "long",
376
+ type: "conjunction"
377
+ });
343
378
  function formatListWithAnd(arr) {
344
- return new Intl.ListFormat("en", {
345
- style: "long",
346
- type: "conjunction"
347
- }).format(arr);
379
+ return listFormatter.format(arr);
348
380
  }
349
- async function getFilesFromGlobs(patterns, cwd) {
381
+ function getFilesFromGlobs(patterns, cwd) {
350
382
  const includePatterns = patterns.filter((p) => !p.startsWith("!"));
351
383
  const excludePatterns = patterns.filter((p) => p.startsWith("!")).map((p) => p.slice(1));
352
384
  const includedFiles = new Set;
353
385
  for (const pattern of includePatterns) {
354
386
  const glob = new Bun.Glob(pattern);
355
- for await (const file of glob.scan(cwd)) {
387
+ for (const file of glob.scanSync(cwd)) {
356
388
  includedFiles.add(file);
357
389
  }
358
390
  }
359
391
  if (excludePatterns.length > 0) {
360
392
  for (const pattern of excludePatterns) {
361
393
  const glob = new Bun.Glob(pattern);
362
- for await (const file of glob.scan(cwd)) {
394
+ for (const file of glob.scanSync(cwd)) {
363
395
  includedFiles.delete(file);
364
396
  }
365
397
  }
@@ -866,4 +898,4 @@ function unused(options = {}) {
866
898
  };
867
899
  }
868
900
 
869
- export { __toESM, __require, logTime, logger, BunupBuildError, BunupDTSBuildError, BunupCLIError, BunupWatchError, parseErrorMessage, handleError, handleErrorAndExit, ensureArray, ensureObject, getDefaultJsOutputExtension, getDefaultDtsOutputExtention, getPackageDeps, formatFileSize, getShortFilePath, cleanOutDir, cleanPath, getFilesFromGlobs, isTypeScriptFile, isJavascriptFile, replaceExtension, isGlobPattern, exports, injectStyles, shims, unused };
901
+ export { __toESM, __require, logTime, logger, BunupBuildError, BunupDTSBuildError, BunupCLIError, BunupWatchError, parseErrorMessage, handleError, noEntryPointsFoundError, invalidEntryPointsError, handleErrorAndExit, ensureArray, ensureObject, getDefaultJsOutputExtension, getDefaultDtsOutputExtention, getPackageDeps, formatFileSize, getShortFilePath, cleanOutDir, cleanPath, formatListWithAnd, getFilesFromGlobs, isTypeScriptFile, isJavascriptFile, replaceExtension, isGlobPattern, exports, injectStyles, shims, unused };
@@ -7,21 +7,22 @@ import {
7
7
  ensureArray,
8
8
  ensureObject,
9
9
  exports,
10
- formatFileSize,
10
+ formatListWithAnd,
11
11
  getDefaultDtsOutputExtention,
12
12
  getDefaultJsOutputExtension,
13
13
  getFilesFromGlobs,
14
14
  getPackageDeps,
15
15
  getShortFilePath,
16
16
  injectStyles,
17
+ invalidEntryPointsError,
17
18
  isJavascriptFile,
18
- isTypeScriptFile,
19
19
  logger,
20
+ noEntryPointsFoundError,
20
21
  parseErrorMessage,
21
22
  replaceExtension,
22
23
  shims,
23
24
  unused
24
- } from "./bunup-er5nnjqp.js";
25
+ } from "./bunup-025ckbke.js";
25
26
 
26
27
  // packages/bunup/src/loaders.ts
27
28
  import path from "path";
@@ -29,7 +30,7 @@ import { loadConfig } from "coffi";
29
30
  async function processLoadedConfigs(config, cwd, filter) {
30
31
  return Array.isArray(config) && "root" in config[0] ? config.filter((c) => filter ? filter.includes(c.name) : true).map((c) => ({
31
32
  rootDir: path.resolve(cwd, c.root),
32
- options: addField(c.config, "name", c.name)
33
+ options: setOrSuffixField(c.config, "name", c.name)
33
34
  })) : [
34
35
  {
35
36
  rootDir: cwd,
@@ -37,10 +38,23 @@ async function processLoadedConfigs(config, cwd, filter) {
37
38
  }
38
39
  ];
39
40
  }
40
- function addField(objectOrArray, field, value) {
41
- return Array.isArray(objectOrArray) ? objectOrArray.map((o) => ({ ...o, [field]: value })) : { ...objectOrArray, [field]: value };
41
+ function setOrSuffixField(objectOrArray, field, prefix) {
42
+ const addPrefix = (obj) => {
43
+ const existingValue = obj[field];
44
+ const newValue = existingValue ? `${prefix}-${existingValue}` : prefix;
45
+ return { ...obj, [field]: newValue };
46
+ };
47
+ return Array.isArray(objectOrArray) ? objectOrArray.map(addPrefix) : addPrefix(objectOrArray);
42
48
  }
43
49
  async function loadPackageJson(cwd = process.cwd()) {
50
+ const packageJsonPath = path.join(cwd, "package.json");
51
+ try {
52
+ const data = await Bun.file(packageJsonPath).json();
53
+ return {
54
+ data,
55
+ path: packageJsonPath
56
+ };
57
+ } catch {}
44
58
  const { config, filepath } = await loadConfig({
45
59
  name: "package",
46
60
  cwd,
@@ -192,16 +206,17 @@ ${text}`;
192
206
  }
193
207
 
194
208
  // packages/bunup/src/options.ts
209
+ var DEFAULT_ENTYPOINTS = [
210
+ "index.ts",
211
+ "index.tsx",
212
+ "src/index.ts",
213
+ "src/index.tsx",
214
+ "cli.ts",
215
+ "src/cli.ts",
216
+ "src/cli/index.ts"
217
+ ];
195
218
  var DEFAULT_OPTIONS = {
196
- entry: [
197
- "index.ts",
198
- "index.tsx",
199
- "src/index.ts",
200
- "src/index.tsx",
201
- "cli.ts",
202
- "src/cli.ts",
203
- "src/cli/index.ts"
204
- ],
219
+ entry: DEFAULT_ENTYPOINTS,
205
220
  format: "esm",
206
221
  outDir: "dist",
207
222
  target: "node",
@@ -311,122 +326,6 @@ async function runPluginBuildDoneHooks(bunupPlugins, options, output, meta) {
311
326
  }
312
327
  }
313
328
 
314
- // packages/bunup/src/printer/print-build-report.ts
315
- import { promisify } from "util";
316
- import { brotliCompress } from "zlib";
317
- import pc from "picocolors";
318
- var brotliAsync = promisify(brotliCompress);
319
- async function printBuildReport(buildOutput, options) {
320
- const { gzip = true, brotli = false, maxBundleSize } = options.report ?? {};
321
- const showCompression = gzip || brotli;
322
- const files = await Promise.all(buildOutput.files.map(async (file) => {
323
- const pathRelative = file.pathRelativeToOutdir;
324
- const size = Bun.file(file.fullPath).size;
325
- const isDts = file.dts && file.kind === "entry-point";
326
- const isJs = isTypeScriptFile(file.fullPath) || isJavascriptFile(file.fullPath);
327
- let gzipSize;
328
- let brotliSize;
329
- if (showCompression) {
330
- const buffer = await Bun.file(file.fullPath).arrayBuffer();
331
- const uint8 = new Uint8Array(buffer);
332
- const [gzipResult, brotliResult] = await Promise.all([
333
- gzip ? Promise.resolve(Bun.gzipSync(uint8)) : Promise.resolve(null),
334
- brotli ? brotliAsync(uint8) : Promise.resolve(null)
335
- ]);
336
- gzipSize = gzipResult?.length;
337
- brotliSize = brotliResult?.length;
338
- }
339
- return {
340
- path: pathRelative,
341
- fullPath: `${options.outDir}/${pathRelative}`,
342
- size,
343
- gzipSize,
344
- brotliSize,
345
- format: file.format,
346
- isDts,
347
- isJs
348
- };
349
- }));
350
- const totalSize = files.reduce((sum, file) => sum + file.size, 0);
351
- const totalGzipSize = files.reduce((sum, file) => sum + (file.gzipSize || 0), 0);
352
- const totalBrotliSize = files.reduce((sum, file) => sum + (file.brotliSize || 0), 0);
353
- const formats = ensureArray(options.format);
354
- const showFormat = formats.length > 1 || formats[0] === "cjs";
355
- const formatLabelWidth = showFormat ? Math.max(...formats.map((f) => `[${f}] `.length)) : 0;
356
- const pathWidth = Math.max(...files.map((f) => f.fullPath.length), "Output".length);
357
- const sizeWidth = Math.max(formatFileSize(totalSize).length, "Raw".length);
358
- const gzipWidth = gzip ? Math.max(formatFileSize(totalGzipSize).length, "Gzip".length) : 0;
359
- const brotliWidth = brotli ? Math.max(formatFileSize(totalBrotliSize).length, "Brotli".length) : 0;
360
- const pad = (str, width, align = "left") => {
361
- const diff = width - str.length;
362
- return align === "left" ? str + " ".repeat(Math.max(0, diff)) : " ".repeat(Math.max(0, diff)) + str;
363
- };
364
- console.log("");
365
- if (options.name) {
366
- console.log("");
367
- console.log(` ${pc.bgBlueBright(` ${options.name} `)}`);
368
- }
369
- console.log("");
370
- const headers = [
371
- pad(" Output", pathWidth + formatLabelWidth + 2),
372
- pad("Raw", sizeWidth, "right")
373
- ];
374
- if (gzip)
375
- headers.push(pad("Gzip", gzipWidth, "right"));
376
- if (brotli)
377
- headers.push(pad("Brotli", brotliWidth, "right"));
378
- console.log(pc.dim(headers.join(" ")));
379
- console.log("");
380
- for (const file of files) {
381
- let formatLabel = "";
382
- if (showFormat) {
383
- if (file.isJs) {
384
- formatLabel = pc.dim(`[${file.format}] `);
385
- }
386
- formatLabel = pad(formatLabel, formatLabelWidth);
387
- }
388
- const outDirWithSlash = `${options.outDir}/`;
389
- const fileName = file.isDts ? pc.green(pc.bold(file.path)) : file.path;
390
- const styledPath = `${pc.dim(outDirWithSlash)}${fileName}`;
391
- const plainPath = `${outDirWithSlash}${file.path}`;
392
- const filePathColumn = ` ${formatLabel}${styledPath}${" ".repeat(Math.max(0, pathWidth - plainPath.length))}`;
393
- const fileRow = [
394
- filePathColumn,
395
- pad(formatFileSize(file.size), sizeWidth, "right")
396
- ];
397
- if (gzip) {
398
- const gzipStr = file.gzipSize ? formatFileSize(file.gzipSize) : pc.dim("-");
399
- fileRow.push(pad(gzipStr, gzipWidth, "right"));
400
- }
401
- if (brotli) {
402
- const brotliStr = file.brotliSize ? formatFileSize(file.brotliSize) : pc.dim("-");
403
- fileRow.push(pad(brotliStr, brotliWidth, "right"));
404
- }
405
- console.log(fileRow.join(" "));
406
- }
407
- console.log("");
408
- const summaryRow = [
409
- ` ${pc.bold(pad(`${files.length} files`, pathWidth + formatLabelWidth))}`,
410
- pc.bold(pad(formatFileSize(totalSize), sizeWidth, "right"))
411
- ];
412
- if (gzip && totalGzipSize > 0) {
413
- summaryRow.push(pc.bold(pad(formatFileSize(totalGzipSize), gzipWidth, "right")));
414
- } else if (gzip) {
415
- summaryRow.push(pad("", gzipWidth));
416
- }
417
- if (brotli && totalBrotliSize > 0) {
418
- summaryRow.push(pc.bold(pad(formatFileSize(totalBrotliSize), brotliWidth, "right")));
419
- } else if (brotli) {
420
- summaryRow.push(pad("", brotliWidth));
421
- }
422
- console.log(summaryRow.join(" "));
423
- if (maxBundleSize && totalSize > maxBundleSize) {
424
- console.log("");
425
- console.warn(pc.yellow(` Bundle size ${pc.bold(formatFileSize(totalSize))} exceeds limit ${pc.bold(formatFileSize(maxBundleSize))}`));
426
- }
427
- console.log("");
428
- }
429
-
430
329
  // packages/bunup/src/build.ts
431
330
  var ac = null;
432
331
  async function build(userOptions, rootDir = process.cwd()) {
@@ -434,16 +333,14 @@ async function build(userOptions, rootDir = process.cwd()) {
434
333
  ac.abort();
435
334
  }
436
335
  ac = new AbortController;
336
+ const options = resolveBuildOptions(userOptions);
437
337
  const buildOutput = {
438
- files: []
338
+ files: [],
339
+ options
439
340
  };
440
- const options = resolveBuildOptions(userOptions);
441
341
  if (options.silent) {
442
342
  logger.setSilent(options.silent);
443
343
  }
444
- if (!options.entry || options.entry.length === 0 || !options.outDir) {
445
- throw new BunupBuildError("Nothing to build. Please make sure you have provided a proper bunup configuration or cli arguments.");
446
- }
447
344
  if (options.clean) {
448
345
  cleanOutDir(rootDir, options.outDir);
449
346
  }
@@ -460,29 +357,45 @@ async function build(userOptions, rootDir = process.cwd()) {
460
357
  const bunupPlugins = filterBunupPlugins(allPlugins);
461
358
  const bunPlugins = filterBunPlugins(allPlugins);
462
359
  await runPluginBuildStartHooks(bunupPlugins, options);
463
- const entrypoints = await getFilesFromGlobs(ensureArray(options.entry), rootDir);
360
+ const entryArray = ensureArray(options.entry);
361
+ const entrypoints = getFilesFromGlobs(entryArray, rootDir);
464
362
  if (!entrypoints.length) {
465
- throw new BunupBuildError(`One or more of the entrypoints you provided do not exist. Please check that each entrypoint points to a valid file.`);
363
+ if (!ensureArray(userOptions.entry).length) {
364
+ throw new BunupBuildError(noEntryPointsFoundError(DEFAULT_ENTYPOINTS));
365
+ }
366
+ throw new BunupBuildError(invalidEntryPointsError(entryArray));
466
367
  }
467
- const buildPromises = ensureArray(options.format).flatMap(async (fmt) => {
368
+ logger.info(`entry: ${formatListWithAnd(entrypoints)}`, {
369
+ identifier: options.name,
370
+ once: options.name,
371
+ muted: true
372
+ });
373
+ const absoluteEntrypoints = entrypoints.map((file) => `${rootDir}/${file}`);
374
+ const resolvedDefine = getResolvedDefine(options.define, options.env);
375
+ const resolvedMinify = getResolvedMinify(options);
376
+ const resolvedTarget = getResolvedTarget(options.target);
377
+ const resolvedSourcemap = getResolvedSourcemap(options.sourcemap);
378
+ const resolvedEnv = getResolvedEnv(options.env);
379
+ const chunkNaming = getDefaultChunkNaming(options.name);
380
+ const buildPromises = ensureArray(options.format).map(async (fmt) => {
468
381
  const result = await Bun.build({
469
- entrypoints: entrypoints.map((file) => `${rootDir}/${file}`),
382
+ entrypoints: absoluteEntrypoints,
470
383
  format: fmt,
471
384
  splitting: getResolvedSplitting(options.splitting, fmt),
472
- define: getResolvedDefine(options.define, options.env),
473
- minify: getResolvedMinify(options),
474
- target: getResolvedTarget(options.target),
475
- sourcemap: getResolvedSourcemap(options.sourcemap),
385
+ define: resolvedDefine,
386
+ minify: resolvedMinify,
387
+ target: resolvedTarget,
388
+ sourcemap: resolvedSourcemap,
476
389
  loader: options.loader,
477
390
  drop: options.drop,
478
391
  naming: {
479
- chunk: getDefaultChunkNaming(options.name)
392
+ chunk: chunkNaming
480
393
  },
481
394
  conditions: options.conditions,
482
395
  banner: options.banner,
483
396
  footer: options.footer,
484
397
  publicPath: options.publicPath,
485
- env: getResolvedEnv(options.env),
398
+ env: resolvedEnv,
486
399
  ignoreDCEAnnotations: options.ignoreDCEAnnotations,
487
400
  emitDCEAnnotations: options.emitDCEAnnotations,
488
401
  throw: false,
@@ -565,10 +478,7 @@ async function build(userOptions, rootDir = process.cwd()) {
565
478
  if (options.onSuccess) {
566
479
  await executeOnSuccess(options.onSuccess, options, ac.signal);
567
480
  }
568
- if (!options.watch && !logger.isSilent()) {
569
- await printBuildReport(buildOutput, options);
570
- }
571
481
  return buildOutput;
572
482
  }
573
483
 
574
- export { processLoadedConfigs, resolveBuildOptions, printBuildReport, build };
484
+ export { processLoadedConfigs, resolveBuildOptions, build };
@@ -41,6 +41,8 @@ type BuildOutputFile = {
41
41
  type BuildOutput = {
42
42
  /** Array of generated files with their paths and contents */
43
43
  files: BuildOutputFile[]
44
+ /** Options used for the build */
45
+ options: BuildOptions
44
46
  };
45
47
  /**
46
48
  * Context provided to build hooks
@@ -378,7 +380,7 @@ interface BuildOptions {
378
380
  * Can be 'none', 'linked', 'external', or 'inline'
379
381
  * Can also be a boolean - when true, it will use 'inline'
380
382
  *
381
- * @see https://bun.sh/docs/bundler#sourcemap
383
+ * @see https://bun.com/docs/bundler#sourcemap
382
384
  *
383
385
  * @default 'none'
384
386
  *
@@ -392,7 +394,7 @@ interface BuildOptions {
392
394
  * Define global constants for the build
393
395
  * These values will be replaced at build time
394
396
  *
395
- * @see https://bun.sh/docs/bundler#define
397
+ * @see https://bun.com/docs/bundler#define
396
398
  *
397
399
  * @example
398
400
  * define: {
@@ -426,7 +428,7 @@ interface BuildOptions {
426
428
  /**
427
429
  * A banner to be added to the final bundle, this can be a directive like "use client" for react or a comment block such as a license for the code.
428
430
  *
429
- * @see https://bun.sh/docs/bundler#banner
431
+ * @see https://bun.com/docs/bundler#banner
430
432
  *
431
433
  * @example
432
434
  * banner: '"use client";'
@@ -435,7 +437,7 @@ interface BuildOptions {
435
437
  /**
436
438
  * A footer to be added to the final bundle, this can be something like a comment block for a license or just a fun easter egg.
437
439
  *
438
- * @see https://bun.sh/docs/bundler#footer
440
+ * @see https://bun.com/docs/bundler#footer
439
441
  *
440
442
  * @example
441
443
  * footer: '// built with love in SF'
@@ -444,16 +446,16 @@ interface BuildOptions {
444
446
  /**
445
447
  * Remove function calls from a bundle. For example, `drop: ["console"]` will remove all calls to `console.log`. Arguments to calls will also be removed, regardless of if those arguments may have side effects. Dropping `debugger` will remove all `debugger` statements.
446
448
  *
447
- * @see https://bun.sh/docs/bundler#drop
449
+ * @see https://bun.com/docs/bundler#drop
448
450
  *
449
451
  * @example
450
452
  * drop: ["console", "debugger", "anyIdentifier.or.propertyAccess"]
451
453
  */
452
454
  drop?: string[];
453
455
  /**
454
- * A map of file extensions to [built-in loader names](https://bun.sh/docs/bundler/loaders#built-in-loaders). This can be used to quickly customize how certain files are loaded.
456
+ * A map of file extensions to [built-in loader names](https://bun.com/docs/bundler/loaders#built-in-loaders). This can be used to quickly customize how certain files are loaded.
455
457
  *
456
- * @see https://bun.sh/docs/bundler#loader
458
+ * @see https://bun.com/docs/bundler#loader
457
459
  *
458
460
  * @example
459
461
  * loader: {
@@ -494,7 +496,7 @@ interface BuildOptions {
494
496
  * Note: Values are injected at build time. Secrets or private keys should be excluded
495
497
  * from inlining when targeting browser environments.
496
498
  *
497
- * @see https://bun.sh/docs/bundler#env to learn more about inline, disable, prefix, and object modes
499
+ * @see https://bun.com/docs/bundler#env to learn more about inline, disable, prefix, and object modes
498
500
  *
499
501
  * @example
500
502
  * // Inline all environment variables available at build time
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bunup",
3
3
  "description": "⚡ A blazing-fast build tool for your libraries built with Bun.",
4
- "version": "0.14.11",
4
+ "version": "0.14.13",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"
@@ -47,7 +47,7 @@
47
47
  "bunup": "dist/cli/index.js"
48
48
  },
49
49
  "dependencies": {
50
- "@bunup/dts": "0.14.10",
50
+ "@bunup/dts": "0.14.13",
51
51
  "chokidar": "^4.0.3",
52
52
  "coffi": "^0.1.35",
53
53
  "lightningcss": "^1.30.1",
@@ -55,7 +55,7 @@
55
55
  "tinyexec": "^1.0.1",
56
56
  "tree-kill": "^1.2.2",
57
57
  "zlye": "^0.4.4",
58
- "@bunup/shared": "0.14.10"
58
+ "@bunup/shared": "0.14.13"
59
59
  },
60
60
  "peerDependencies": {
61
61
  "typescript": ">=4.5.0"