bunup 0.1.6 → 0.1.9

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/build/cli.js CHANGED
@@ -1,932 +1,6 @@
1
1
  #!/usr/bin/env bun
2
- 'use strict';
3
-
4
- var fs2 = require('fs');
5
- var path2 = require('path');
6
- var oxc = require('oxc-transform');
7
- var rollup = require('rollup');
8
- var dtsPlugin = require('rollup-plugin-dts');
9
- var chokidar = require('chokidar');
10
-
11
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
-
13
- var fs2__default = /*#__PURE__*/_interopDefault(fs2);
14
- var path2__default = /*#__PURE__*/_interopDefault(path2);
15
- var oxc__default = /*#__PURE__*/_interopDefault(oxc);
16
- var dtsPlugin__default = /*#__PURE__*/_interopDefault(dtsPlugin);
17
- var chokidar__default = /*#__PURE__*/_interopDefault(chokidar);
18
-
19
- // src/errors.ts
20
- var parseErrorMessage = (error) => {
21
- if (error instanceof Error) {
22
- return error.message;
23
- }
24
- return String(error);
25
- };
26
- var handleError = (error, context) => {
27
- const errorMessage = parseErrorMessage(error);
28
- const contextPrefix = "";
29
- console.error(`\x1B[31m[ERROR]\x1B[0m ${contextPrefix}${errorMessage}`);
30
- if (process.env.NODE_ENV !== "production" && error instanceof Error && error.stack) {
31
- console.error(
32
- "\x1B[2m" + error.stack.split("\n").slice(1).join("\n") + "\x1B[0m"
33
- );
34
- }
35
- };
36
-
37
- // src/utils.ts
38
- function escapeRegExp(string) {
39
- return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
40
- }
41
- function generateRandomSuffix(length = 8) {
42
- return Math.random().toString(36).substring(2, 2 + length);
43
- }
44
- function getDefaultOutputExtension(format, packageType) {
45
- switch (format) {
46
- case "esm":
47
- return ".mjs";
48
- case "cjs":
49
- return isModulePackage(packageType) ? ".cjs" : ".js";
50
- case "iife":
51
- return ".global.js";
52
- }
53
- }
54
- function getDefaultDtsExtention(format, packageType) {
55
- switch (format) {
56
- case "esm":
57
- return ".d.mts";
58
- case "cjs":
59
- return isModulePackage(packageType) ? ".d.cts" : ".d.ts";
60
- case "iife":
61
- return ".d.ts";
62
- }
63
- }
64
- function isModulePackage(packageType) {
65
- return packageType === "module";
66
- }
67
- function formatTime(ms) {
68
- return ms >= 1e3 ? `${(ms / 1e3).toFixed(2)}s` : `${Math.round(ms)}ms`;
69
- }
70
- function getPackageDeps(packageJson) {
71
- if (!packageJson) return [];
72
- return Array.from(
73
- /* @__PURE__ */ new Set([
74
- ...Object.keys(packageJson.dependencies || {}),
75
- ...Object.keys(packageJson.peerDependencies || {})
76
- ])
77
- );
78
- }
79
- function getResolvedSplitting(splitting, format) {
80
- return splitting === void 0 ? format === "esm" : splitting;
81
- }
82
-
83
- // src/helpers/external.ts
84
- function processPatterns(patterns) {
85
- return patterns.map(
86
- (pattern) => typeof pattern === "string" ? new RegExp(`^${escapeRegExp(pattern)}($|\\/|\\\\)`) : pattern
87
- );
88
- }
89
- function getExternalPatterns(options, packageJson) {
90
- return processPatterns(options.external || []).concat(
91
- getPackageDeps(packageJson).map(
92
- (dep) => new RegExp(`^${escapeRegExp(dep)}($|\\/|\\\\)`)
93
- )
94
- );
95
- }
96
- function getNoExternalPatterns(options) {
97
- return processPatterns(options.noExternal || []);
98
- }
99
-
100
- // src/logger.ts
101
- var logger = {
102
- MAX_LABEL_LENGTH: 5,
103
- colors: {
104
- cli: "183",
105
- info: "240",
106
- warn: "221",
107
- error: "203",
108
- progress: {
109
- ESM: "214",
110
- CJS: "114",
111
- IIFE: "105",
112
- DTS: "75"
113
- },
114
- default: "255"
115
- },
116
- labels: {
117
- cli: "BUNUP",
118
- info: "INFO",
119
- warn: "WARN",
120
- error: "ERROR"
121
- },
122
- formatMessage(colorCode, label, message) {
123
- const padding = " ".repeat(
124
- Math.max(0, this.MAX_LABEL_LENGTH - label.length)
125
- );
126
- return `\x1B[38;5;${colorCode}m[${label}]\x1B[0m ${padding}${message}`;
127
- },
128
- cli(message) {
129
- const label = this.labels.cli;
130
- console.log(this.formatMessage(this.colors.cli, label, message));
131
- },
132
- info(message) {
133
- const label = this.labels.info;
134
- console.log(this.formatMessage(this.colors.info, label, message));
135
- },
136
- warn(message) {
137
- const label = this.labels.warn;
138
- console.warn(this.formatMessage(this.colors.warn, label, message));
139
- },
140
- error(message) {
141
- const label = this.labels.error;
142
- console.error(this.formatMessage(this.colors.error, label, message));
143
- },
144
- progress(label, message) {
145
- const labelStr = String(label);
146
- let colorCode = this.colors.default;
147
- for (const [key, value] of Object.entries(this.colors.progress)) {
148
- if (labelStr.includes(key)) {
149
- colorCode = value;
150
- break;
151
- }
152
- }
153
- console.log(this.formatMessage(colorCode, labelStr, message));
154
- }
155
- };
156
- function getLoggerProgressLabel(label, name) {
157
- return `${name ? `${name.replace(/-/g, "_")}_` : ""}${label}`.toUpperCase();
158
- }
159
-
160
- // src/options.ts
161
- var DEFAULT_OPTIONS = {
162
- entry: [],
163
- format: ["esm"],
164
- outDir: "dist",
165
- minify: false,
166
- watch: false,
167
- dts: false,
168
- target: "node",
169
- external: [],
170
- clean: true
171
- };
172
- function createDefaultBunBuildOptions(options, rootDir) {
173
- return {
174
- outdir: `${rootDir}/${options.outDir}`,
175
- minify: createMinifyOptions(options),
176
- target: options.target,
177
- splitting: options.splitting
178
- };
179
- }
180
- function createMinifyOptions(options) {
181
- const { minify, minifyWhitespace, minifyIdentifiers, minifySyntax } = options;
182
- const defaultValue = minify === true;
183
- return {
184
- whitespace: minifyWhitespace ?? defaultValue,
185
- identifiers: minifyIdentifiers ?? defaultValue,
186
- syntax: minifySyntax ?? defaultValue
187
- };
188
- }
189
-
190
- // src/loaders.ts
191
- async function loadConfigs(cwd) {
192
- const configs = [];
193
- for (const ext of [
194
- ".ts",
195
- ".js",
196
- ".mjs",
197
- ".cjs",
198
- ".mts",
199
- ".cts",
200
- ".json",
201
- ".jsonc"
202
- ]) {
203
- const filePath = path2__default.default.join(cwd, `bunup.config${ext}`);
204
- try {
205
- if (!fs2__default.default.existsSync(filePath)) continue;
206
- let content;
207
- if (ext === ".json" || ext === ".jsonc") {
208
- const text = fs2__default.default.readFileSync(filePath, "utf8");
209
- content = JSON.parse(text);
210
- } else {
211
- const imported = await import(`file://${filePath}`);
212
- content = imported.default || imported;
213
- if (!content) {
214
- logger.warn(`No default export found in ${filePath}`);
215
- content = {};
216
- }
217
- }
218
- if (Array.isArray(content)) {
219
- for (const item of content) {
220
- configs.push({
221
- options: { ...DEFAULT_OPTIONS, ...item },
222
- rootDir: cwd
223
- });
224
- }
225
- } else {
226
- configs.push({
227
- options: { ...DEFAULT_OPTIONS, ...content },
228
- rootDir: cwd
229
- });
230
- }
231
- break;
232
- } catch (error) {
233
- logger.error(
234
- `Failed to load config from ${filePath}: ${parseErrorMessage(error)}`
235
- );
236
- }
237
- if (configs.length > 0) break;
238
- }
239
- return configs;
240
- }
241
- function loadPackageJson(cwd) {
242
- const packageJsonPath = path2__default.default.join(cwd, "package.json");
243
- try {
244
- if (!fs2__default.default.existsSync(packageJsonPath)) {
245
- return null;
246
- }
247
- const text = fs2__default.default.readFileSync(packageJsonPath, "utf8");
248
- const content = JSON.parse(text);
249
- return content;
250
- } catch (error) {
251
- logger.error(
252
- `Failed to load package.json at ${packageJsonPath}: ${parseErrorMessage(error)}`
253
- );
254
- return null;
255
- }
256
- }
257
-
258
- // src/dts/index.ts
259
- async function generateDts(rootDir, entry, format, options) {
260
- const { absoluteRootDir, absoluteEntry } = validateInputs(rootDir, entry);
261
- const tsFiles = await collectTsFiles(absoluteEntry);
262
- const dtsMap = await generateDtsContent(tsFiles);
263
- return bundleDtsContent(
264
- absoluteEntry,
265
- dtsMap,
266
- format,
267
- options,
268
- absoluteRootDir
269
- );
270
- }
271
- async function collectTsFiles(entry) {
272
- const visited = /* @__PURE__ */ new Set();
273
- const toVisit = [entry];
274
- while (toVisit.length > 0) {
275
- const current = toVisit.pop();
276
- if (!current || visited.has(current)) continue;
277
- visited.add(current);
278
- try {
279
- const sourceText = await fs2__default.default.promises.readFile(current, "utf8");
280
- const relativeImports = extractRelativeImports(sourceText);
281
- for (const relImport of relativeImports) {
282
- const importDir = path2__default.default.dirname(current);
283
- const absImport = path2__default.default.resolve(importDir, relImport);
284
- const possiblePaths = [
285
- absImport,
286
- `${absImport}.ts`,
287
- `${absImport}.tsx`,
288
- `${absImport}/index.ts`,
289
- `${absImport}/index.tsx`
290
- ];
291
- for (const tsFile of possiblePaths) {
292
- if (fs2__default.default.existsSync(tsFile) && tsFile.endsWith(".ts") && !visited.has(tsFile)) {
293
- toVisit.push(tsFile);
294
- break;
295
- }
296
- }
297
- }
298
- } catch (error) {
299
- logger.warn(
300
- `Error processing ${current}: ${error instanceof Error ? error.message : String(error)}`
301
- );
302
- }
303
- }
304
- return visited;
305
- }
306
- function extractRelativeImports(sourceText) {
307
- const imports = /* @__PURE__ */ new Set();
308
- try {
309
- const importExportRegex = /(?:import|export)(?:(?:[\s\n]*(?:type[\s\n]+)?(?:\*|\{[^}]*\}|[\w$]+)[\s\n]+from[\s\n]*)|[\s\n]+)(["'`])([^'"]+)\1/g;
310
- let match;
311
- while ((match = importExportRegex.exec(sourceText)) !== null) {
312
- const importPath = match[2];
313
- if (importPath.startsWith(".")) {
314
- imports.add(importPath);
315
- }
316
- }
317
- const sideEffectImportRegex = /import\s+(["'`])([^'"]+)\1\s*;?/g;
318
- while ((match = sideEffectImportRegex.exec(sourceText)) !== null) {
319
- const importPath = match[2];
320
- if (importPath.startsWith(".")) {
321
- imports.add(importPath);
322
- }
323
- }
324
- const dynamicImportRegex = /import\s*\(\s*(["'`])([^'"]+)\1\s*\)/g;
325
- while ((match = dynamicImportRegex.exec(sourceText)) !== null) {
326
- const importPath = match[2];
327
- if (importPath.startsWith(".")) {
328
- imports.add(importPath);
329
- }
330
- }
331
- } catch (error) {
332
- logger.warn(
333
- `Error extracting imports: ${error instanceof Error ? error.message : String(error)}`
334
- );
335
- }
336
- return Array.from(imports);
337
- }
338
- async function generateDtsContent(tsFiles) {
339
- const dtsMap = /* @__PURE__ */ new Map();
340
- await Promise.all(
341
- Array.from(tsFiles).map(async (tsFile) => {
342
- try {
343
- const dtsPath = tsFile.replace(/\.tsx?$/, ".d.ts");
344
- const sourceText = await fs2__default.default.promises.readFile(tsFile, "utf8");
345
- const { code: declaration } = oxc__default.default.isolatedDeclaration(
346
- tsFile,
347
- sourceText
348
- );
349
- if (declaration) {
350
- dtsMap.set(dtsPath, declaration);
351
- }
352
- } catch (error) {
353
- logger.warn(
354
- `Failed to generate declaration for ${tsFile}: ${error instanceof Error ? error.message : String(error)}`
355
- );
356
- }
357
- })
358
- );
359
- return dtsMap;
360
- }
361
- async function bundleDtsContent(entryFile, dtsMap, format, options, rootDir) {
362
- const VIRTUAL_PREFIX = "\0virtual:";
363
- const entryDtsPath = entryFile.replace(/\.tsx?$/, ".d.ts");
364
- const virtualEntry = `${VIRTUAL_PREFIX}${entryDtsPath}`;
365
- const virtualPlugin = {
366
- name: "virtual-dts",
367
- resolveId(source, importer) {
368
- if (source.startsWith(VIRTUAL_PREFIX)) {
369
- return source;
370
- }
371
- if (importer?.startsWith(VIRTUAL_PREFIX)) {
372
- const importerPath = importer.slice(VIRTUAL_PREFIX.length);
373
- const importerDir = path2__default.default.dirname(importerPath);
374
- if (source.startsWith(".")) {
375
- const resolvedPath = path2__default.default.resolve(importerDir, source);
376
- for (const ext of ["", ".d.ts", "/index.d.ts"]) {
377
- const fullPath = `${resolvedPath}${ext}`;
378
- if (dtsMap.has(fullPath)) {
379
- return `${VIRTUAL_PREFIX}${fullPath}`;
380
- }
381
- }
382
- }
383
- }
384
- return null;
385
- },
386
- load(id) {
387
- if (id.startsWith(VIRTUAL_PREFIX)) {
388
- const actualPath = id.slice(VIRTUAL_PREFIX.length);
389
- return dtsMap.get(actualPath) || null;
390
- }
391
- return null;
392
- }
393
- };
394
- const packageJson = loadPackageJson(rootDir);
395
- const externalPatterns = getExternalPatterns(options, packageJson);
396
- const noExternalPatterns = getNoExternalPatterns(options);
397
- let bundle;
398
- try {
399
- bundle = await rollup.rollup({
400
- input: virtualEntry,
401
- onwarn(warning, handler) {
402
- if (warning.code === "UNRESOLVED_IMPORT" || warning.code === "CIRCULAR_DEPENDENCY" || warning.code === "EMPTY_BUNDLE") {
403
- return;
404
- }
405
- handler(warning);
406
- },
407
- plugins: [virtualPlugin, dtsPlugin__default.default()],
408
- external: (source) => externalPatterns.some((re) => re.test(source)) && !noExternalPatterns.some((re) => re.test(source))
409
- });
410
- const { output } = await bundle.generate({ format });
411
- if (!output[0]?.code) {
412
- throw new Error("Generated bundle is empty");
413
- }
414
- return output[0].code;
415
- } catch (error) {
416
- throw new Error(`DTS bundling failed: ${parseErrorMessage(error)}`);
417
- } finally {
418
- if (bundle) await bundle.close();
419
- }
420
- }
421
- function validateInputs(rootDir, entry) {
422
- const absoluteRootDir = path2__default.default.resolve(rootDir);
423
- const absoluteEntry = path2__default.default.resolve(absoluteRootDir, entry);
424
- if (!fs2__default.default.existsSync(absoluteRootDir)) {
425
- throw new Error(`Root directory does not exist: ${absoluteRootDir}`);
426
- }
427
- if (!fs2__default.default.existsSync(absoluteEntry)) {
428
- throw new Error(`Entry file does not exist: ${absoluteEntry}`);
429
- }
430
- if (!absoluteEntry.endsWith(".ts")) {
431
- throw new Error(
432
- `Entry file must be a TypeScript file (.ts): ${absoluteEntry}`
433
- );
434
- }
435
- if (path2__default.default.relative(absoluteRootDir, absoluteEntry).startsWith("..")) {
436
- throw new Error(`Entry file must be within rootDir: ${absoluteEntry}`);
437
- }
438
- return { absoluteRootDir, absoluteEntry };
439
- }
440
-
441
- // src/dts/worker.ts
442
- self.onmessage = async (event) => {
443
- const { name, rootDir, outDir, entry, format, packageType, options } = event.data;
444
- try {
445
- const content = await generateDts(rootDir, entry.path, format, options);
446
- const extension = getDefaultDtsExtention(format, packageType);
447
- const outputRelativePath = `${outDir}/${entry.name}${extension}`;
448
- const outputPath = `${rootDir}/${outputRelativePath}`;
449
- await Bun.write(outputPath, content);
450
- const response = {
451
- name,
452
- success: true,
453
- outputRelativePath
454
- };
455
- self.postMessage(response);
456
- } catch (error) {
457
- const response = {
458
- success: false,
459
- error: parseErrorMessage(error)
460
- };
461
- self.postMessage(response);
462
- }
463
- };
464
- var DtsWorker = class {
465
- constructor(maxWorkers = navigator.hardwareConcurrency || 4) {
466
- this.workers = [];
467
- this.queue = [];
468
- this.busyWorkers = /* @__PURE__ */ new Set();
469
- this.isShuttingDown = false;
470
- this.maxWorkers = maxWorkers;
471
- }
472
- async process(task) {
473
- if (this.isShuttingDown) {
474
- throw new Error("Worker pool is shutting down");
475
- }
476
- return new Promise((resolve, reject) => {
477
- this.queue.push({ task, resolve, reject });
478
- this.processQueue();
479
- });
480
- }
481
- processQueue() {
482
- if (this.queue.length === 0 || this.isShuttingDown) return;
483
- if (this.workers.length < this.maxWorkers) {
484
- const worker = new Worker(path2__default.default.join(__dirname, "./dtsWorker.js"));
485
- this.workers.push(worker);
486
- this.assignTaskToWorker(worker);
487
- } else {
488
- const availableWorker = this.workers.find(
489
- (w) => !this.busyWorkers.has(w)
490
- );
491
- if (availableWorker) {
492
- this.assignTaskToWorker(availableWorker);
493
- }
494
- }
495
- }
496
- assignTaskToWorker(worker) {
497
- const queueItem = this.queue.shift();
498
- if (!queueItem) return;
499
- const { task, resolve, reject } = queueItem;
500
- this.busyWorkers.add(worker);
501
- const cleanup = () => {
502
- this.busyWorkers.delete(worker);
503
- if (this.isShuttingDown && this.busyWorkers.size === 0) {
504
- this.terminateAllWorkers();
505
- } else {
506
- this.processQueue();
507
- }
508
- };
509
- worker.onmessage = (event) => {
510
- if (event.data.success) {
511
- logger.progress(
512
- getLoggerProgressLabel("DTS", event.data.name),
513
- event.data.outputRelativePath
514
- );
515
- resolve();
516
- } else {
517
- logger.error(`DTS generation failed: ${event.data.error}`);
518
- reject(new Error(event.data.error));
519
- }
520
- cleanup();
521
- };
522
- worker.onerror = (error) => {
523
- const errorMessage = parseErrorMessage(error);
524
- logger.error(`Worker error: ${errorMessage}`);
525
- reject(error);
526
- cleanup();
527
- };
528
- worker.postMessage(task);
529
- }
530
- terminateAllWorkers() {
531
- this.workers.forEach((worker) => {
532
- try {
533
- worker.terminate();
534
- } catch (error) {
535
- logger.error(
536
- `Error terminating worker: ${parseErrorMessage(error)}`
537
- );
538
- }
539
- });
540
- this.workers = [];
541
- this.busyWorkers.clear();
542
- }
543
- async cleanup() {
544
- this.isShuttingDown = true;
545
- if (this.busyWorkers.size === 0) {
546
- this.terminateAllWorkers();
547
- return;
548
- }
549
- return new Promise((resolve) => {
550
- const checkInterval = setInterval(() => {
551
- if (this.busyWorkers.size === 0) {
552
- clearInterval(checkInterval);
553
- this.terminateAllWorkers();
554
- resolve();
555
- }
556
- }, 100);
557
- setTimeout(() => {
558
- clearInterval(checkInterval);
559
- this.terminateAllWorkers();
560
- resolve();
561
- }, 5e3);
562
- });
563
- }
564
- };
565
-
566
- // src/helpers/entry.ts
567
- function getEntryNameOnly(entry) {
568
- return entry.split("/").pop()?.split(".").slice(0, -1).join(".") || "";
569
- }
570
- function normalizeEntryToProcessableEntries(entry) {
571
- const result = [];
572
- const usedNames = /* @__PURE__ */ new Set();
573
- function addEntry(name, path6) {
574
- if (usedNames.has(name)) {
575
- const randomSuffix = generateRandomSuffix();
576
- result.push({ name: `${name}_${randomSuffix}`, path: path6 });
577
- } else {
578
- result.push({ name, path: path6 });
579
- usedNames.add(name);
580
- }
581
- }
582
- if (Array.isArray(entry)) {
583
- for (const item of entry) {
584
- const name = getEntryNameOnly(item);
585
- addEntry(name, item);
586
- }
587
- } else {
588
- Object.entries(entry).forEach(([name, path6]) => {
589
- addEntry(name, path6);
590
- });
591
- }
592
- return result;
593
- }
594
- function getEntryNamingFormat(name, extension) {
595
- return `[dir]/${name}${extension}`;
596
- }
597
-
598
- // src/plugins/external.ts
599
- function externalPlugin(externalPatterns, noExternalPatterns) {
600
- return {
601
- name: "bunup:external-plugin",
602
- setup(build2) {
603
- build2.onResolve({ filter: /.*/ }, (args) => {
604
- const importPath = args.path;
605
- const isExternal = externalPatterns.some((re) => re.test(importPath)) && !noExternalPatterns.some((re) => re.test(importPath));
606
- if (isExternal) {
607
- return { path: importPath, external: true };
608
- }
609
- return null;
610
- });
611
- }
612
- };
613
- }
614
-
615
- // src/build.ts
616
- async function build(options, rootDir) {
617
- if (!options.entry || options.entry.length === 0 || !options.outDir) {
618
- logger.cli(
619
- "Nothing to build. Please make sure you have provided a proper bunup configuration or cli arguments."
620
- );
621
- return;
622
- }
623
- const startTime = performance.now();
624
- logger.cli("Build started");
625
- const packageJson = loadPackageJson(rootDir);
626
- const packageType = packageJson?.type;
627
- const externalPatterns = getExternalPatterns(options, packageJson);
628
- const noExternalPatterns = getNoExternalPatterns(options);
629
- const plugins = [externalPlugin(externalPatterns, noExternalPatterns)];
630
- const processableEntries = normalizeEntryToProcessableEntries(
631
- options.entry
632
- );
633
- const buildPromises = options.format.flatMap(
634
- (fmt) => processableEntries.map(
635
- (entry) => buildEntry(options, rootDir, entry, fmt, packageType, plugins)
636
- )
637
- );
638
- try {
639
- await Promise.all(buildPromises);
640
- const buildTimeMs = performance.now() - startTime;
641
- const timeDisplay = formatTime(buildTimeMs);
642
- logger.cli(`\u26A1 Build success in ${timeDisplay}`);
643
- } catch (error) {
644
- logger.error("Build process encountered errors.");
645
- process.exit(1);
646
- }
647
- if (options.dts) {
648
- const dtsStartTime = performance.now();
649
- logger.progress("DTS", "Bundling types");
650
- const formatsToProcess = options.format.filter((fmt) => {
651
- if (fmt === "iife" && !isModulePackage(packageType) && options.format.includes("cjs")) {
652
- return false;
653
- }
654
- return true;
655
- });
656
- const dtsEntry = options.dts === true ? processableEntries : normalizeEntryToProcessableEntries(options.dts.entry);
657
- const dtsWorker = new DtsWorker();
658
- try {
659
- const dtsPromises = formatsToProcess.flatMap(
660
- (fmt) => dtsEntry.map(
661
- (entry) => generateDtsForEntry(
662
- options,
663
- rootDir,
664
- entry,
665
- fmt,
666
- packageType,
667
- dtsWorker
668
- )
669
- )
670
- );
671
- await Promise.all(dtsPromises);
672
- const dtsTimeMs = performance.now() - dtsStartTime;
673
- const dtsTimeDisplay = formatTime(dtsTimeMs);
674
- logger.progress("DTS", `Bundled types in ${dtsTimeDisplay}`);
675
- } catch (error) {
676
- await dtsWorker.cleanup();
677
- }
678
- await dtsWorker.cleanup();
679
- }
680
- }
681
- async function generateDtsForEntry(options, rootDir, entry, fmt, packageType, dtsWorker) {
682
- const task = {
683
- name: options.name,
684
- rootDir,
685
- outDir: options.outDir,
686
- entry,
687
- format: fmt,
688
- packageType,
689
- options
690
- };
691
- await dtsWorker.process(task);
692
- }
693
- async function buildEntry(options, rootDir, entry, fmt, packageType, plugins) {
694
- const extension = getDefaultOutputExtension(fmt, packageType);
695
- const defaultBunBuildOptions = createDefaultBunBuildOptions(
696
- options,
697
- rootDir
698
- );
699
- const result = await Bun.build({
700
- ...defaultBunBuildOptions,
701
- entrypoints: [`${rootDir}/${entry.path}`],
702
- format: fmt,
703
- naming: { entry: getEntryNamingFormat(entry.name, extension) },
704
- splitting: getResolvedSplitting(options.splitting, fmt),
705
- plugins
706
- });
707
- if (!result.success) {
708
- result.logs.forEach((log) => {
709
- if (log.level === "error") logger.error(log.message);
710
- else if (log.level === "warning") logger.warn(log.message);
711
- else if (log.level === "info") logger.info(log.message);
712
- });
713
- throw new Error(`Build failed for ${entry} (${fmt})`);
714
- }
715
- logger.progress(
716
- getLoggerProgressLabel(fmt, options.name),
717
- `${options.outDir}/${entry.name}${extension}`
718
- );
719
- }
720
-
721
- // src/cli-parse.ts
722
- var cliOptionAliases = {
723
- n: "name",
724
- f: "format",
725
- o: "outDir",
726
- m: "minify",
727
- w: "watch",
728
- d: "dts",
729
- e: "external",
730
- t: "target",
731
- mw: "minifyWhitespace",
732
- mi: "minifyIdentifiers",
733
- ms: "minifySyntax",
734
- c: "clean",
735
- s: "splitting",
736
- ne: "noExternal"
737
- };
738
- var cliOptionHandlers = {
739
- name: (value, args) => {
740
- args.name = value;
741
- },
742
- format: (value, args) => {
743
- args.format = value.split(",");
744
- },
745
- outDir: (value, args) => {
746
- args.outDir = value;
747
- },
748
- minify: (value, args) => {
749
- args.minify = !!value;
750
- },
751
- watch: (value, args) => {
752
- args.watch = !!value;
753
- },
754
- dts: (value, args) => {
755
- args.dts = !!value;
756
- },
757
- external: (value, args) => {
758
- args.external = value.split(",");
759
- },
760
- minifyWhitespace: (value, args) => {
761
- args.minifyWhitespace = !!value;
762
- },
763
- minifyIdentifiers: (value, args) => {
764
- args.minifyIdentifiers = !!value;
765
- },
766
- minifySyntax: (value, args) => {
767
- args.minifySyntax = !!value;
768
- },
769
- target: (value, args) => {
770
- args.target = value;
771
- },
772
- clean: (value, args) => {
773
- args.clean = !!value;
774
- },
775
- splitting: (value, args) => {
776
- args.splitting = !!value;
777
- },
778
- noExternal: (value, args) => {
779
- args.noExternal = value.split(",");
780
- }
781
- };
782
- function parseCliOptions(argv) {
783
- const cliOptions = {};
784
- for (let i = 0; i < argv.length; i++) {
785
- const arg = argv[i];
786
- if (arg.startsWith("--") || arg.startsWith("-")) {
787
- const isShortOption = arg.startsWith("-") && !arg.startsWith("--");
788
- const key = isShortOption ? arg.slice(1) : arg.slice(2);
789
- const resolvedKey = isShortOption ? cliOptionAliases[key] : key;
790
- const handler = cliOptionHandlers[resolvedKey];
791
- if (!handler) {
792
- logger.error(`Unknown option: ${key}`);
793
- continue;
794
- }
795
- const nextArg = argv[i + 1];
796
- const value = nextArg && !nextArg.startsWith("-") ? nextArg : true;
797
- handler(value, cliOptions);
798
- if (typeof value === "string") {
799
- i++;
800
- }
801
- } else {
802
- if (!cliOptions.entry) {
803
- cliOptions.entry = [];
804
- }
805
- if (Array.isArray(cliOptions.entry)) {
806
- cliOptions.entry.push(arg);
807
- }
808
- }
809
- }
810
- return cliOptions;
811
- }
812
-
813
- // src/runtime.ts
814
- (() => {
815
- if (typeof Bun === "undefined") {
816
- logger.error(
817
- "Bunup requires Bun to run.\nTo install Bun, visit https://bun.sh/docs/installation"
818
- );
819
- process.exit(1);
820
- }
821
- })();
822
- async function watch(options, rootDir) {
823
- const watchPaths = /* @__PURE__ */ new Set();
824
- const normalizedEntry = normalizeEntryToProcessableEntries(options.entry);
825
- normalizedEntry.forEach((entry) => {
826
- const entryPath = path2__default.default.resolve(rootDir, entry.path);
827
- const parentDir = path2__default.default.dirname(entryPath);
828
- watchPaths.add(parentDir);
829
- });
830
- const watcher = chokidar__default.default.watch(Array.from(watchPaths), {
831
- persistent: true,
832
- ignoreInitial: true,
833
- awaitWriteFinish: {
834
- stabilityThreshold: 100,
835
- pollInterval: 50
836
- },
837
- atomic: true,
838
- ignorePermissionErrors: true,
839
- ignored: [/[\\/]\.git[\\/]/, /[\\/]node_modules[\\/]/, options.outDir]
840
- });
841
- let debounceTimer = null;
842
- let isRebuilding = false;
843
- const triggerRebuild = async (changedFile) => {
844
- if (isRebuilding) return;
845
- isRebuilding = true;
846
- try {
847
- await build(
848
- {
849
- ...options,
850
- entry: [changedFile],
851
- clean: false
852
- },
853
- rootDir
854
- );
855
- } catch (error) {
856
- logger.error(`Build failed: ${error}`);
857
- } finally {
858
- isRebuilding = false;
859
- }
860
- };
861
- watcher.on("change", (filePath) => {
862
- const changedFile = path2__default.default.relative(rootDir, filePath);
863
- logger.cli(`File changed: ${changedFile}`);
864
- if (debounceTimer) {
865
- clearTimeout(debounceTimer);
866
- }
867
- debounceTimer = setTimeout(() => triggerRebuild(changedFile), 300);
868
- });
869
- watcher.on("error", (error) => {
870
- logger.error(`Watcher error: ${error}`);
871
- });
872
- }
873
-
874
- // src/cli.ts
875
- async function main(args = Bun.argv.slice(2)) {
876
- const cliOptions = parseCliOptions(args);
877
- const configs = await loadConfigs(process.cwd());
878
- const rootDir = process.cwd();
879
- if (cliOptions.watch) {
880
- logger.cli("Starting watch mode");
881
- logger.cli(`Watching for file changes`);
882
- }
883
- if (configs.length === 0) {
884
- const mergedOptions = {
885
- ...DEFAULT_OPTIONS,
886
- ...cliOptions
887
- };
888
- if (mergedOptions.clean) cleanOutDir(rootDir, mergedOptions.outDir);
889
- await handleBuild(mergedOptions, rootDir);
890
- } else {
891
- for (const { options, rootDir: rootDir2 } of configs) {
892
- if (options.clean) cleanOutDir(rootDir2, options.outDir);
893
- }
894
- await Promise.all(
895
- configs.map(async ({ options, rootDir: rootDir2 }) => {
896
- const mergedOptions = {
897
- ...DEFAULT_OPTIONS,
898
- ...options,
899
- ...cliOptions
900
- };
901
- await handleBuild(mergedOptions, rootDir2);
902
- })
903
- );
904
- }
905
- if (!cliOptions.watch) {
906
- process.exit(0);
907
- }
908
- }
909
- async function handleBuild(options, rootDir) {
910
- if (options.watch) {
911
- await watch(options, rootDir);
912
- } else {
913
- await build(options, rootDir);
914
- }
915
- }
916
- function cleanOutDir(rootDir, outdir) {
917
- const outdirPath = path2__default.default.join(rootDir, outdir);
918
- if (fs2__default.default.existsSync(outdirPath)) {
919
- try {
920
- fs2__default.default.rmSync(outdirPath, { recursive: true, force: true });
921
- } catch (error) {
922
- logger.error(`Failed to clean output directory: ${error}`);
923
- }
924
- }
925
- fs2__default.default.mkdirSync(outdirPath, { recursive: true });
926
- }
927
- main().catch((error) => {
928
- handleError(error);
929
- process.exit(1);
930
- });
931
-
932
- exports.main = main;
2
+ // @bun @bun-cjs
3
+ (function(exports, require, module, __filename, __dirname) {var ar=require("node:module");var er=Object.create;var{getPrototypeOf:nr,defineProperty:j,getOwnPropertyNames:or}=Object;var ir=Object.prototype.hasOwnProperty;var m=(r,t,s)=>{s=r!=null?er(nr(r)):{};let n=t||!r||!r.__esModule?j(s,"default",{value:r,enumerable:!0}):s;for(let e of or(r))if(!ir.call(n,e))j(n,e,{get:()=>r[e],enumerable:!0});return n};var v=m(require("fs")),Z=m(require("path"));var A=require("node:os"),b=m(require("node:path")),N=require("node:worker_threads");var p=(r)=>{if(r instanceof Error)return r.message;return String(r)},R=(r,t)=>{let s=p(r),n=t?`[${t}] `:"";if(console.error(`\x1B[31m[ERROR]\x1B[0m ${n}${s}`),r instanceof Error&&r.stack)console.error("\x1B[2m"+r.stack.split(`
4
+ `).slice(1).join(`
5
+ `)+"\x1B[0m")};var i={MAX_LABEL_LENGTH:5,colors:{cli:"183",info:"240",warn:"221",error:"203",progress:{ESM:"214",CJS:"114",IIFE:"105",DTS:"75"},default:"255"},labels:{cli:"BUNUP",info:"INFO",warn:"WARN",error:"ERROR"},formatMessage(r,t,s){let n=" ".repeat(Math.max(0,this.MAX_LABEL_LENGTH-t.length));return`\x1B[38;5;${r}m[${t}]\x1B[0m ${n}${s}`},cli(r){let t=this.labels.cli;console.log(this.formatMessage(this.colors.cli,t,r))},info(r){let t=this.labels.info;console.log(this.formatMessage(this.colors.info,t,r))},warn(r){let t=this.labels.warn;console.warn(this.formatMessage(this.colors.warn,t,r))},error(r){let t=this.labels.error;console.error(this.formatMessage(this.colors.error,t,r))},progress(r,t){let s=String(r),n=this.colors.default;for(let[e,o]of Object.entries(this.colors.progress))if(s.includes(e)){n=o;break}console.log(this.formatMessage(n,s,t))}};function E(r,t){return`${t?`${t.replace(/-/g,"_")}_`:""}${r}`.toUpperCase()}var __dirname="/home/runner/work/bunup/bunup/src/dts";class W{workers=[];queue=[];maxWorkers;busyWorkers=new Set;isShuttingDown=!1;constructor(r=A.cpus().length||4){this.maxWorkers=r}async process(r){if(this.isShuttingDown)throw new Error("Worker pool is shutting down");return new Promise((t,s)=>{this.queue.push({task:r,resolve:t,reject:s}),this.processQueue()})}processQueue(){if(this.queue.length===0||this.isShuttingDown)return;if(this.workers.length<this.maxWorkers){let r=new N.Worker(b.default.join(__dirname,"./dtsWorker.js"));this.workers.push(r),this.assignTaskToWorker(r)}else{let r=this.workers.find((t)=>!this.busyWorkers.has(t));if(r)this.assignTaskToWorker(r)}}assignTaskToWorker(r){let t=this.queue.shift();if(!t)return;let{task:s,resolve:n,reject:e}=t;this.busyWorkers.add(r);let o=()=>{if(this.busyWorkers.delete(r),this.isShuttingDown&&this.busyWorkers.size===0)this.terminateAllWorkers();else this.processQueue()};r.on("message",(a)=>{if(a.success)i.progress(E("DTS",a.name),a.outputRelativePath),n();else i.error(`DTS generation failed: ${a.error}`),e(new Error(a.error));o()}),r.on("error",(a)=>{let l=p(a);i.error(`Worker error: ${l}`),e(a),o()}),r.postMessage(s)}terminateAllWorkers(){this.workers.forEach((r)=>{try{r.terminate()}catch(t){i.error(`Error terminating worker: ${p(t)}`)}}),this.workers=[],this.busyWorkers.clear()}async cleanup(){if(this.isShuttingDown=!0,this.busyWorkers.size===0){this.terminateAllWorkers();return}return new Promise((r)=>{let t=setInterval(()=>{if(this.busyWorkers.size===0)clearInterval(t),this.terminateAllWorkers(),r()},100);setTimeout(()=>{clearInterval(t),this.terminateAllWorkers(),r()},5000)})}}function k(r){return r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function F(r=8){return Math.random().toString(36).substring(2,2+r)}function M(r,t){switch(r){case"esm":return".mjs";case"cjs":return $(t)?".cjs":".js";case"iife":return".global.js"}}function $(r){return r==="module"}function C(r){return r>=1000?`${(r/1000).toFixed(2)}s`:`${Math.round(r)}ms`}function I(r){if(!r)return[];return Array.from(new Set([...Object.keys(r.dependencies||{}),...Object.keys(r.peerDependencies||{})]))}function L(r,t){return r===void 0?t==="esm":r}function cr(r){return r.split("/").pop()?.split(".").slice(0,-1).join(".")||""}function d(r){let t=[],s=new Set;function n(e,o){if(s.has(e)){let a=F();t.push({name:`${e}_${a}`,path:o})}else t.push({name:e,path:o}),s.add(e)}if(Array.isArray(r))for(let e of r){let o=cr(e);n(o,e)}else Object.entries(r).forEach(([e,o])=>{n(e,o)});return t}function P(r,t){return`[dir]/${r}${t}`}function _(r){return r.map((t)=>typeof t==="string"?new RegExp(`^${k(t)}($|\\/|\\\\)`):t)}function H(r,t){return _(r.external||[]).concat(I(t).map((s)=>new RegExp(`^${k(s)}($|\\/|\\\\)`)))}function q(r){return _(r.noExternal||[])}var x=m(require("node:fs")),B=m(require("node:path"));var h={entry:[],format:["esm"],outDir:"dist",minify:!1,watch:!1,dts:!1,target:"node",external:[],clean:!0};function D(r,t){return{outdir:`${t}/${r.outDir}`,minify:ur(r),target:r.target,splitting:r.splitting}}function ur(r){let{minify:t,minifyWhitespace:s,minifyIdentifiers:n,minifySyntax:e}=r,o=t===!0;return{whitespace:s??o,identifiers:n??o,syntax:e??o}}async function U(r){let t=[];for(let s of[".ts",".js",".mjs",".cjs",".mts",".cts",".json",".jsonc"]){let n=B.default.join(r,`bunup.config${s}`);try{if(!x.default.existsSync(n))continue;let e;if(s===".json"||s===".jsonc"){let o=x.default.readFileSync(n,"utf8");e=JSON.parse(o)}else{let o=await import(`file://${n}`);if(e=o.default||o,!e)i.warn(`No default export found in ${n}`),e={}}if(Array.isArray(e))for(let o of e)t.push({options:{...h,...o},rootDir:r});else t.push({options:{...h,...e},rootDir:r});break}catch(e){i.error(`Failed to load config from ${n}: ${p(e)}`)}if(t.length>0)break}return t}function Q(r){let t=B.default.join(r,"package.json");try{if(!x.default.existsSync(t))return null;let s=x.default.readFileSync(t,"utf8");return JSON.parse(s)}catch(s){return i.error(`Failed to load package.json at ${t}: ${p(s)}`),null}}function G(r,t){return{name:"bunup:external-plugin",setup(s){s.onResolve({filter:/.*/},(n)=>{let e=n.path;if(r.some((a)=>a.test(e))&&!t.some((a)=>a.test(e)))return{path:e,external:!0};return null})}}}async function O(r,t){if(!r.entry||r.entry.length===0||!r.outDir){i.cli("Nothing to build. Please make sure you have provided a proper bunup configuration or cli arguments.");return}let s=performance.now();i.cli("Build started");let n=Q(t),e=n?.type,o=H(r,n),a=q(r),l=[G(o,a)],u=d(r.entry),c=r.format.flatMap((f)=>u.map((g)=>fr(r,t,g,f,e,l)));try{await Promise.all(c);let f=performance.now()-s,g=C(f);i.cli(`⚡ Build success in ${g}`)}catch(f){i.error("Build process encountered errors."),process.exit(1)}if(r.dts){let f=performance.now();i.progress("DTS","Bundling types");let g=r.format.filter((w)=>{if(w==="iife"&&!$(e)&&r.format.includes("cjs"))return!1;return!0}),J=r.dts===!0?u:d(r.dts.entry),S=new W;try{let w=g.flatMap((tr)=>J.map((sr)=>lr(r,t,sr,tr,e,S)));await Promise.all(w);let V=performance.now()-f,rr=C(V);i.progress("DTS",`Bundled types in ${rr}`)}catch(w){await S.cleanup()}await S.cleanup()}}async function lr(r,t,s,n,e,o){let a={name:r.name,rootDir:t,outDir:r.outDir,entry:s,format:n,packageType:e,options:r};await o.process(a)}async function fr(r,t,s,n,e,o){let a=M(n,e),l=D(r,t),u=await Bun.build({...l,entrypoints:[`${t}/${s.path}`],format:n,naming:{entry:P(s.name,a)},splitting:L(r.splitting,n),plugins:o,throw:!1});if(!u.success)throw u.logs.forEach((c)=>{if(c.level==="error")i.error(c.message);else if(c.level==="warning")i.warn(c.message);else if(c.level==="info")i.info(c.message)}),new Error(`Build failed for ${s} (${n})`);i.progress(E(n,r.name),`${r.outDir}/${s.name}${a}`)}var mr={n:"name",f:"format",o:"outDir",m:"minify",w:"watch",d:"dts",e:"external",t:"target",mw:"minifyWhitespace",mi:"minifyIdentifiers",ms:"minifySyntax",c:"clean",s:"splitting",ne:"noExternal"},pr={name:(r,t)=>{t.name=r},format:(r,t)=>{t.format=r.split(",")},outDir:(r,t)=>{t.outDir=r},minify:(r,t)=>{t.minify=!!r},watch:(r,t)=>{t.watch=!!r},dts:(r,t)=>{t.dts=!!r},external:(r,t)=>{t.external=r.split(",")},minifyWhitespace:(r,t)=>{t.minifyWhitespace=!!r},minifyIdentifiers:(r,t)=>{t.minifyIdentifiers=!!r},minifySyntax:(r,t)=>{t.minifySyntax=!!r},target:(r,t)=>{t.target=r},clean:(r,t)=>{t.clean=!!r},splitting:(r,t)=>{t.splitting=!!r},noExternal:(r,t)=>{t.noExternal=r.split(",")}};function X(r){let t={};for(let s=0;s<r.length;s++){let n=r[s];if(n.startsWith("--")||n.startsWith("-")){let e=n.startsWith("-")&&!n.startsWith("--"),o=e?n.slice(1):n.slice(2),a=e?mr[o]:o,l=pr[a];if(!l){i.error(`Unknown option: ${o}`);continue}let u=r[s+1],c=u&&!u.startsWith("-")?u:!0;if(l(c,t),typeof c==="string")s++}else{if(!t.entry)t.entry=[];if(Array.isArray(t.entry))t.entry.push(n)}}return t}(()=>{if(typeof Bun==="undefined")i.error(`Bunup requires Bun to run.
6
+ To install Bun, visit https://bun.sh/docs/installation`),process.exit(1)})();var y=m(require("node:path")),z=m(require("chokidar"));async function K(r,t){let s=new Set;d(r.entry).forEach((u)=>{let c=y.default.resolve(t,u.path),f=y.default.dirname(c);s.add(f)});let e=z.default.watch(Array.from(s),{persistent:!0,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50},atomic:!0,ignorePermissionErrors:!0,ignored:[/[\\/]\.git[\\/]/,/[\\/]node_modules[\\/]/,r.outDir]}),o=null,a=!1,l=async(u)=>{if(a)return;a=!0;try{await O({...r,entry:[u],clean:!1},t)}catch(c){i.error(`Build failed: ${c}`)}finally{a=!1}};e.on("change",(u)=>{let c=y.default.relative(t,u);if(i.cli(`File changed: ${c}`),o)clearTimeout(o);o=setTimeout(()=>l(c),300)}),e.on("error",(u)=>{i.error(`Watcher error: ${u}`)})}async function hr(r=Bun.argv.slice(2)){let t=X(r),s=await U(process.cwd()),n=process.cwd();if(t.watch)i.cli("Starting watch mode"),i.cli("Watching for file changes");if(s.length===0){let e={...h,...t};if(e.clean)Y(n,e.outDir);await T(e,n)}else{for(let{options:e,rootDir:o}of s)if(e.clean)Y(o,e.outDir);await Promise.all(s.map(async({options:e,rootDir:o})=>{let a={...h,...e,...t};await T(a,o)}))}if(!t.watch)process.exit(0)}async function T(r,t){if(r.watch)await K(r,t);else await O(r,t)}function Y(r,t){let s=Z.default.join(r,t);if(v.default.existsSync(s))try{v.default.rmSync(s,{recursive:!0,force:!0})}catch(n){i.error(`Failed to clean output directory: ${n}`)}v.default.mkdirSync(s,{recursive:!0})}hr().catch((r)=>{R(r),process.exit(1)});})