bunup 0.1.5 → 0.1.8
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 +5 -930
- package/build/cli.mjs +5 -920
- package/build/dtsWorker.mjs +1 -0
- package/build/index.d.mts +127 -81
- package/build/index.d.ts +127 -81
- package/build/index.js +1 -8
- package/build/index.mjs +1 -6
- package/package.json +6 -7
- package/build/dtsWorker.js +0 -1
package/build/cli.js
CHANGED
|
@@ -1,930 +1,5 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var fs2 = require('fs');
|
|
5
|
-
var
|
|
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
|
-
entrypoints: options.entry.map((e) => `${rootDir}/${e}`),
|
|
175
|
-
outdir: `${rootDir}/${options.outDir}`,
|
|
176
|
-
minify: createMinifyOptions(options),
|
|
177
|
-
target: options.target,
|
|
178
|
-
splitting: options.splitting
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
function createMinifyOptions(options) {
|
|
182
|
-
const { minify, minifyWhitespace, minifyIdentifiers, minifySyntax } = options;
|
|
183
|
-
const defaultValue = minify === true;
|
|
184
|
-
return {
|
|
185
|
-
whitespace: minifyWhitespace ?? defaultValue,
|
|
186
|
-
identifiers: minifyIdentifiers ?? defaultValue,
|
|
187
|
-
syntax: minifySyntax ?? defaultValue
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// src/loaders.ts
|
|
192
|
-
async function loadConfigs(cwd) {
|
|
193
|
-
const configs = [];
|
|
194
|
-
for (const ext of [
|
|
195
|
-
".ts",
|
|
196
|
-
".js",
|
|
197
|
-
".mjs",
|
|
198
|
-
".cjs",
|
|
199
|
-
".mts",
|
|
200
|
-
".cts",
|
|
201
|
-
".json",
|
|
202
|
-
".jsonc"
|
|
203
|
-
]) {
|
|
204
|
-
const filePath = path2__default.default.join(cwd, `bunup.config${ext}`);
|
|
205
|
-
try {
|
|
206
|
-
if (!fs2__default.default.existsSync(filePath)) continue;
|
|
207
|
-
let content;
|
|
208
|
-
if (ext === ".json" || ext === ".jsonc") {
|
|
209
|
-
const text = fs2__default.default.readFileSync(filePath, "utf8");
|
|
210
|
-
content = JSON.parse(text);
|
|
211
|
-
} else {
|
|
212
|
-
const imported = await import(`file://${filePath}`);
|
|
213
|
-
content = imported.default || imported;
|
|
214
|
-
if (!content) {
|
|
215
|
-
logger.warn(`No default export found in ${filePath}`);
|
|
216
|
-
content = {};
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
if (Array.isArray(content)) {
|
|
220
|
-
for (const item of content) {
|
|
221
|
-
configs.push({
|
|
222
|
-
options: { ...DEFAULT_OPTIONS, ...item },
|
|
223
|
-
rootDir: cwd
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
} else {
|
|
227
|
-
configs.push({
|
|
228
|
-
options: { ...DEFAULT_OPTIONS, ...content },
|
|
229
|
-
rootDir: cwd
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
break;
|
|
233
|
-
} catch (error) {
|
|
234
|
-
logger.error(
|
|
235
|
-
`Failed to load config from ${filePath}: ${parseErrorMessage(error)}`
|
|
236
|
-
);
|
|
237
|
-
}
|
|
238
|
-
if (configs.length > 0) break;
|
|
239
|
-
}
|
|
240
|
-
return configs;
|
|
241
|
-
}
|
|
242
|
-
function loadPackageJson(cwd) {
|
|
243
|
-
const packageJsonPath = path2__default.default.join(cwd, "package.json");
|
|
244
|
-
try {
|
|
245
|
-
if (!fs2__default.default.existsSync(packageJsonPath)) {
|
|
246
|
-
return null;
|
|
247
|
-
}
|
|
248
|
-
const text = fs2__default.default.readFileSync(packageJsonPath, "utf8");
|
|
249
|
-
const content = JSON.parse(text);
|
|
250
|
-
return content;
|
|
251
|
-
} catch (error) {
|
|
252
|
-
logger.error(
|
|
253
|
-
`Failed to load package.json at ${packageJsonPath}: ${parseErrorMessage(error)}`
|
|
254
|
-
);
|
|
255
|
-
return null;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// src/dts/index.ts
|
|
260
|
-
async function generateDts(rootDir, entry, format, options) {
|
|
261
|
-
const { absoluteRootDir, absoluteEntry } = validateInputs(rootDir, entry);
|
|
262
|
-
const tsFiles = await collectTsFiles(absoluteEntry);
|
|
263
|
-
const dtsMap = await generateDtsContent(tsFiles);
|
|
264
|
-
return bundleDtsContent(
|
|
265
|
-
absoluteEntry,
|
|
266
|
-
dtsMap,
|
|
267
|
-
format,
|
|
268
|
-
options,
|
|
269
|
-
absoluteRootDir
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
async function collectTsFiles(entry) {
|
|
273
|
-
const visited = /* @__PURE__ */ new Set();
|
|
274
|
-
const toVisit = [entry];
|
|
275
|
-
while (toVisit.length > 0) {
|
|
276
|
-
const current = toVisit.pop();
|
|
277
|
-
if (!current || visited.has(current)) continue;
|
|
278
|
-
visited.add(current);
|
|
279
|
-
try {
|
|
280
|
-
const sourceText = await fs2__default.default.promises.readFile(current, "utf8");
|
|
281
|
-
const relativeImports = extractRelativeImports(sourceText);
|
|
282
|
-
for (const relImport of relativeImports) {
|
|
283
|
-
const importDir = path2__default.default.dirname(current);
|
|
284
|
-
const absImport = path2__default.default.resolve(importDir, relImport);
|
|
285
|
-
const possiblePaths = [
|
|
286
|
-
absImport,
|
|
287
|
-
`${absImport}.ts`,
|
|
288
|
-
`${absImport}.tsx`,
|
|
289
|
-
`${absImport}/index.ts`,
|
|
290
|
-
`${absImport}/index.tsx`
|
|
291
|
-
];
|
|
292
|
-
for (const tsFile of possiblePaths) {
|
|
293
|
-
if (fs2__default.default.existsSync(tsFile) && tsFile.endsWith(".ts") && !visited.has(tsFile)) {
|
|
294
|
-
toVisit.push(tsFile);
|
|
295
|
-
break;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
} catch (error) {
|
|
300
|
-
logger.warn(
|
|
301
|
-
`Error processing ${current}: ${error instanceof Error ? error.message : String(error)}`
|
|
302
|
-
);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
return visited;
|
|
306
|
-
}
|
|
307
|
-
function extractRelativeImports(sourceText) {
|
|
308
|
-
const imports = /* @__PURE__ */ new Set();
|
|
309
|
-
try {
|
|
310
|
-
const importExportRegex = /(?:import|export)(?:(?:[\s\n]*(?:type[\s\n]+)?(?:\*|\{[^}]*\}|[\w$]+)[\s\n]+from[\s\n]*)|[\s\n]+)(["'`])([^'"]+)\1/g;
|
|
311
|
-
let match;
|
|
312
|
-
while ((match = importExportRegex.exec(sourceText)) !== null) {
|
|
313
|
-
const importPath = match[2];
|
|
314
|
-
if (importPath.startsWith(".")) {
|
|
315
|
-
imports.add(importPath);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
const sideEffectImportRegex = /import\s+(["'`])([^'"]+)\1\s*;?/g;
|
|
319
|
-
while ((match = sideEffectImportRegex.exec(sourceText)) !== null) {
|
|
320
|
-
const importPath = match[2];
|
|
321
|
-
if (importPath.startsWith(".")) {
|
|
322
|
-
imports.add(importPath);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
const dynamicImportRegex = /import\s*\(\s*(["'`])([^'"]+)\1\s*\)/g;
|
|
326
|
-
while ((match = dynamicImportRegex.exec(sourceText)) !== null) {
|
|
327
|
-
const importPath = match[2];
|
|
328
|
-
if (importPath.startsWith(".")) {
|
|
329
|
-
imports.add(importPath);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
} catch (error) {
|
|
333
|
-
logger.warn(
|
|
334
|
-
`Error extracting imports: ${error instanceof Error ? error.message : String(error)}`
|
|
335
|
-
);
|
|
336
|
-
}
|
|
337
|
-
return Array.from(imports);
|
|
338
|
-
}
|
|
339
|
-
async function generateDtsContent(tsFiles) {
|
|
340
|
-
const dtsMap = /* @__PURE__ */ new Map();
|
|
341
|
-
await Promise.all(
|
|
342
|
-
Array.from(tsFiles).map(async (tsFile) => {
|
|
343
|
-
try {
|
|
344
|
-
const dtsPath = tsFile.replace(/\.tsx?$/, ".d.ts");
|
|
345
|
-
const sourceText = await fs2__default.default.promises.readFile(tsFile, "utf8");
|
|
346
|
-
const { code: declaration } = oxc__default.default.isolatedDeclaration(
|
|
347
|
-
tsFile,
|
|
348
|
-
sourceText
|
|
349
|
-
);
|
|
350
|
-
if (declaration) {
|
|
351
|
-
dtsMap.set(dtsPath, declaration);
|
|
352
|
-
}
|
|
353
|
-
} catch (error) {
|
|
354
|
-
logger.warn(
|
|
355
|
-
`Failed to generate declaration for ${tsFile}: ${error instanceof Error ? error.message : String(error)}`
|
|
356
|
-
);
|
|
357
|
-
}
|
|
358
|
-
})
|
|
359
|
-
);
|
|
360
|
-
return dtsMap;
|
|
361
|
-
}
|
|
362
|
-
async function bundleDtsContent(entryFile, dtsMap, format, options, rootDir) {
|
|
363
|
-
const VIRTUAL_PREFIX = "\0virtual:";
|
|
364
|
-
const entryDtsPath = entryFile.replace(/\.tsx?$/, ".d.ts");
|
|
365
|
-
const virtualEntry = `${VIRTUAL_PREFIX}${entryDtsPath}`;
|
|
366
|
-
const virtualPlugin = {
|
|
367
|
-
name: "virtual-dts",
|
|
368
|
-
resolveId(source, importer) {
|
|
369
|
-
if (source.startsWith(VIRTUAL_PREFIX)) {
|
|
370
|
-
return source;
|
|
371
|
-
}
|
|
372
|
-
if (importer?.startsWith(VIRTUAL_PREFIX)) {
|
|
373
|
-
const importerPath = importer.slice(VIRTUAL_PREFIX.length);
|
|
374
|
-
const importerDir = path2__default.default.dirname(importerPath);
|
|
375
|
-
if (source.startsWith(".")) {
|
|
376
|
-
const resolvedPath = path2__default.default.resolve(importerDir, source);
|
|
377
|
-
for (const ext of ["", ".d.ts", "/index.d.ts"]) {
|
|
378
|
-
const fullPath = `${resolvedPath}${ext}`;
|
|
379
|
-
if (dtsMap.has(fullPath)) {
|
|
380
|
-
return `${VIRTUAL_PREFIX}${fullPath}`;
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
return null;
|
|
386
|
-
},
|
|
387
|
-
load(id) {
|
|
388
|
-
if (id.startsWith(VIRTUAL_PREFIX)) {
|
|
389
|
-
const actualPath = id.slice(VIRTUAL_PREFIX.length);
|
|
390
|
-
return dtsMap.get(actualPath) || null;
|
|
391
|
-
}
|
|
392
|
-
return null;
|
|
393
|
-
}
|
|
394
|
-
};
|
|
395
|
-
const packageJson = loadPackageJson(rootDir);
|
|
396
|
-
const externalPatterns = getExternalPatterns(options, packageJson);
|
|
397
|
-
const noExternalPatterns = getNoExternalPatterns(options);
|
|
398
|
-
let bundle;
|
|
399
|
-
try {
|
|
400
|
-
bundle = await rollup.rollup({
|
|
401
|
-
input: virtualEntry,
|
|
402
|
-
onwarn(warning, handler) {
|
|
403
|
-
if (warning.code === "UNRESOLVED_IMPORT" || warning.code === "CIRCULAR_DEPENDENCY" || warning.code === "EMPTY_BUNDLE") {
|
|
404
|
-
return;
|
|
405
|
-
}
|
|
406
|
-
handler(warning);
|
|
407
|
-
},
|
|
408
|
-
plugins: [virtualPlugin, dtsPlugin__default.default()],
|
|
409
|
-
external: (source) => externalPatterns.some((re) => re.test(source)) && !noExternalPatterns.some((re) => re.test(source))
|
|
410
|
-
});
|
|
411
|
-
const { output } = await bundle.generate({ format });
|
|
412
|
-
if (!output[0]?.code) {
|
|
413
|
-
throw new Error("Generated bundle is empty");
|
|
414
|
-
}
|
|
415
|
-
return output[0].code;
|
|
416
|
-
} catch (error) {
|
|
417
|
-
throw new Error(`DTS bundling failed: ${parseErrorMessage(error)}`);
|
|
418
|
-
} finally {
|
|
419
|
-
if (bundle) await bundle.close();
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
function validateInputs(rootDir, entry) {
|
|
423
|
-
const absoluteRootDir = path2__default.default.resolve(rootDir);
|
|
424
|
-
const absoluteEntry = path2__default.default.resolve(absoluteRootDir, entry);
|
|
425
|
-
if (!fs2__default.default.existsSync(absoluteRootDir)) {
|
|
426
|
-
throw new Error(`Root directory does not exist: ${absoluteRootDir}`);
|
|
427
|
-
}
|
|
428
|
-
if (!fs2__default.default.existsSync(absoluteEntry)) {
|
|
429
|
-
throw new Error(`Entry file does not exist: ${absoluteEntry}`);
|
|
430
|
-
}
|
|
431
|
-
if (!absoluteEntry.endsWith(".ts")) {
|
|
432
|
-
throw new Error(
|
|
433
|
-
`Entry file must be a TypeScript file (.ts): ${absoluteEntry}`
|
|
434
|
-
);
|
|
435
|
-
}
|
|
436
|
-
if (path2__default.default.relative(absoluteRootDir, absoluteEntry).startsWith("..")) {
|
|
437
|
-
throw new Error(`Entry file must be within rootDir: ${absoluteEntry}`);
|
|
438
|
-
}
|
|
439
|
-
return { absoluteRootDir, absoluteEntry };
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// src/dts/worker.ts
|
|
443
|
-
self.onmessage = async (event) => {
|
|
444
|
-
const { name, rootDir, outDir, entry, format, packageType, options } = event.data;
|
|
445
|
-
try {
|
|
446
|
-
const content = await generateDts(rootDir, entry.path, format, options);
|
|
447
|
-
const extension = getDefaultDtsExtention(format, packageType);
|
|
448
|
-
const outputRelativePath = `${outDir}/${entry.name}${extension}`;
|
|
449
|
-
const outputPath = `${rootDir}/${outputRelativePath}`;
|
|
450
|
-
await Bun.write(outputPath, content);
|
|
451
|
-
const response = {
|
|
452
|
-
name,
|
|
453
|
-
success: true,
|
|
454
|
-
outputRelativePath
|
|
455
|
-
};
|
|
456
|
-
self.postMessage(response);
|
|
457
|
-
} catch (error) {
|
|
458
|
-
const response = {
|
|
459
|
-
success: false,
|
|
460
|
-
error: parseErrorMessage(error)
|
|
461
|
-
};
|
|
462
|
-
self.postMessage(response);
|
|
463
|
-
}
|
|
464
|
-
};
|
|
465
|
-
var DtsWorker = class {
|
|
466
|
-
constructor(maxWorkers = navigator.hardwareConcurrency || 4) {
|
|
467
|
-
this.workers = [];
|
|
468
|
-
this.queue = [];
|
|
469
|
-
this.busyWorkers = /* @__PURE__ */ new Set();
|
|
470
|
-
this.isShuttingDown = false;
|
|
471
|
-
this.maxWorkers = maxWorkers;
|
|
472
|
-
}
|
|
473
|
-
async process(task) {
|
|
474
|
-
if (this.isShuttingDown) {
|
|
475
|
-
throw new Error("Worker pool is shutting down");
|
|
476
|
-
}
|
|
477
|
-
return new Promise((resolve, reject) => {
|
|
478
|
-
this.queue.push({ task, resolve, reject });
|
|
479
|
-
this.processQueue();
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
|
-
processQueue() {
|
|
483
|
-
if (this.queue.length === 0 || this.isShuttingDown) return;
|
|
484
|
-
if (this.workers.length < this.maxWorkers) {
|
|
485
|
-
const worker = new Worker(path2__default.default.join(__dirname, "./dtsWorker.js"));
|
|
486
|
-
this.workers.push(worker);
|
|
487
|
-
this.assignTaskToWorker(worker);
|
|
488
|
-
} else {
|
|
489
|
-
const availableWorker = this.workers.find(
|
|
490
|
-
(w) => !this.busyWorkers.has(w)
|
|
491
|
-
);
|
|
492
|
-
if (availableWorker) {
|
|
493
|
-
this.assignTaskToWorker(availableWorker);
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
assignTaskToWorker(worker) {
|
|
498
|
-
const queueItem = this.queue.shift();
|
|
499
|
-
if (!queueItem) return;
|
|
500
|
-
const { task, resolve, reject } = queueItem;
|
|
501
|
-
this.busyWorkers.add(worker);
|
|
502
|
-
const cleanup = () => {
|
|
503
|
-
this.busyWorkers.delete(worker);
|
|
504
|
-
if (this.isShuttingDown && this.busyWorkers.size === 0) {
|
|
505
|
-
this.terminateAllWorkers();
|
|
506
|
-
} else {
|
|
507
|
-
this.processQueue();
|
|
508
|
-
}
|
|
509
|
-
};
|
|
510
|
-
worker.onmessage = (event) => {
|
|
511
|
-
if (event.data.success) {
|
|
512
|
-
logger.progress(
|
|
513
|
-
getLoggerProgressLabel("DTS", event.data.name),
|
|
514
|
-
event.data.outputRelativePath
|
|
515
|
-
);
|
|
516
|
-
resolve();
|
|
517
|
-
} else {
|
|
518
|
-
logger.error(`DTS generation failed: ${event.data.error}`);
|
|
519
|
-
reject(new Error(event.data.error));
|
|
520
|
-
}
|
|
521
|
-
cleanup();
|
|
522
|
-
};
|
|
523
|
-
worker.onerror = (error) => {
|
|
524
|
-
const errorMessage = parseErrorMessage(error);
|
|
525
|
-
logger.error(`Worker error: ${errorMessage}`);
|
|
526
|
-
reject(error);
|
|
527
|
-
cleanup();
|
|
528
|
-
};
|
|
529
|
-
worker.postMessage(task);
|
|
530
|
-
}
|
|
531
|
-
terminateAllWorkers() {
|
|
532
|
-
this.workers.forEach((worker) => {
|
|
533
|
-
try {
|
|
534
|
-
worker.terminate();
|
|
535
|
-
} catch (error) {
|
|
536
|
-
logger.error(
|
|
537
|
-
`Error terminating worker: ${parseErrorMessage(error)}`
|
|
538
|
-
);
|
|
539
|
-
}
|
|
540
|
-
});
|
|
541
|
-
this.workers = [];
|
|
542
|
-
this.busyWorkers.clear();
|
|
543
|
-
}
|
|
544
|
-
async cleanup() {
|
|
545
|
-
this.isShuttingDown = true;
|
|
546
|
-
if (this.busyWorkers.size === 0) {
|
|
547
|
-
this.terminateAllWorkers();
|
|
548
|
-
return;
|
|
549
|
-
}
|
|
550
|
-
return new Promise((resolve) => {
|
|
551
|
-
const checkInterval = setInterval(() => {
|
|
552
|
-
if (this.busyWorkers.size === 0) {
|
|
553
|
-
clearInterval(checkInterval);
|
|
554
|
-
this.terminateAllWorkers();
|
|
555
|
-
resolve();
|
|
556
|
-
}
|
|
557
|
-
}, 100);
|
|
558
|
-
setTimeout(() => {
|
|
559
|
-
clearInterval(checkInterval);
|
|
560
|
-
this.terminateAllWorkers();
|
|
561
|
-
resolve();
|
|
562
|
-
}, 5e3);
|
|
563
|
-
});
|
|
564
|
-
}
|
|
565
|
-
};
|
|
566
|
-
|
|
567
|
-
// src/helpers/entry.ts
|
|
568
|
-
function getEntryNameOnly(entry) {
|
|
569
|
-
return entry.split("/").pop()?.split(".").slice(0, -1).join(".") || "";
|
|
570
|
-
}
|
|
571
|
-
function normalizeEntryToProcessableEntries(entries) {
|
|
572
|
-
const result = [];
|
|
573
|
-
const usedNames = /* @__PURE__ */ new Set();
|
|
574
|
-
function addEntry(name, path6) {
|
|
575
|
-
if (usedNames.has(name)) {
|
|
576
|
-
const randomSuffix = generateRandomSuffix();
|
|
577
|
-
result.push({ name: `${name}_${randomSuffix}`, path: path6 });
|
|
578
|
-
} else {
|
|
579
|
-
result.push({ name, path: path6 });
|
|
580
|
-
usedNames.add(name);
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
for (const entry of entries) {
|
|
584
|
-
if (typeof entry === "string") {
|
|
585
|
-
const name = getEntryNameOnly(entry);
|
|
586
|
-
addEntry(name, entry);
|
|
587
|
-
} else {
|
|
588
|
-
Object.entries(entry).forEach(([name, path6]) => {
|
|
589
|
-
addEntry(name, path6);
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
return result;
|
|
594
|
-
}
|
|
595
|
-
function getEntryNamingFormat(extension) {
|
|
596
|
-
return `[dir]/[name]${extension}`;
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
// src/plugins/external.ts
|
|
600
|
-
function externalPlugin(externalPatterns, noExternalPatterns) {
|
|
601
|
-
return {
|
|
602
|
-
name: "bunup:external-plugin",
|
|
603
|
-
setup(build2) {
|
|
604
|
-
build2.onResolve({ filter: /.*/ }, (args) => {
|
|
605
|
-
const importPath = args.path;
|
|
606
|
-
const isExternal = externalPatterns.some((re) => re.test(importPath)) && !noExternalPatterns.some((re) => re.test(importPath));
|
|
607
|
-
if (isExternal) {
|
|
608
|
-
return { path: importPath, external: true };
|
|
609
|
-
}
|
|
610
|
-
return null;
|
|
611
|
-
});
|
|
612
|
-
}
|
|
613
|
-
};
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
// src/build.ts
|
|
617
|
-
async function build(options, rootDir) {
|
|
618
|
-
if (!options.entry || options.entry.length === 0 || !options.outDir) {
|
|
619
|
-
logger.cli(
|
|
620
|
-
"Nothing to build. Please make sure you have provided a proper bunup configuration or cli arguments."
|
|
621
|
-
);
|
|
622
|
-
return;
|
|
623
|
-
}
|
|
624
|
-
const startTime = performance.now();
|
|
625
|
-
logger.cli("Build started");
|
|
626
|
-
const packageJson = loadPackageJson(rootDir);
|
|
627
|
-
const packageType = packageJson?.type;
|
|
628
|
-
const externalPatterns = getExternalPatterns(options, packageJson);
|
|
629
|
-
const noExternalPatterns = getNoExternalPatterns(options);
|
|
630
|
-
const plugins = [externalPlugin(externalPatterns, noExternalPatterns)];
|
|
631
|
-
const processableEntries = normalizeEntryToProcessableEntries(
|
|
632
|
-
options.entry
|
|
633
|
-
);
|
|
634
|
-
const buildPromises = options.format.flatMap(
|
|
635
|
-
(fmt) => processableEntries.map(
|
|
636
|
-
(entry) => buildEntry(options, rootDir, entry, fmt, packageType, plugins)
|
|
637
|
-
)
|
|
638
|
-
);
|
|
639
|
-
try {
|
|
640
|
-
await Promise.all(buildPromises);
|
|
641
|
-
const buildTimeMs = performance.now() - startTime;
|
|
642
|
-
const timeDisplay = formatTime(buildTimeMs);
|
|
643
|
-
logger.cli(`\u26A1 Build success in ${timeDisplay}`);
|
|
644
|
-
} catch (error) {
|
|
645
|
-
logger.error("Build process encountered errors.");
|
|
646
|
-
process.exit(1);
|
|
647
|
-
}
|
|
648
|
-
if (options.dts) {
|
|
649
|
-
const dtsStartTime = performance.now();
|
|
650
|
-
logger.progress("DTS", "Bundling types");
|
|
651
|
-
const formatsToProcess = options.format.filter((fmt) => {
|
|
652
|
-
if (fmt === "iife" && !isModulePackage(packageType) && options.format.includes("cjs")) {
|
|
653
|
-
return false;
|
|
654
|
-
}
|
|
655
|
-
return true;
|
|
656
|
-
});
|
|
657
|
-
const dtsWorker = new DtsWorker();
|
|
658
|
-
try {
|
|
659
|
-
const dtsPromises = formatsToProcess.flatMap(
|
|
660
|
-
(fmt) => processableEntries.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(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
|
-
cliOptions.entry.push(arg);
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
return cliOptions;
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
// src/runtime.ts
|
|
812
|
-
(() => {
|
|
813
|
-
if (typeof Bun === "undefined") {
|
|
814
|
-
logger.error(
|
|
815
|
-
"Bunup requires Bun to run.\nTo install Bun, visit https://bun.sh/docs/installation"
|
|
816
|
-
);
|
|
817
|
-
process.exit(1);
|
|
818
|
-
}
|
|
819
|
-
})();
|
|
820
|
-
async function watch(options, rootDir) {
|
|
821
|
-
const watchPaths = /* @__PURE__ */ new Set();
|
|
822
|
-
const normalizedEntry = normalizeEntryToProcessableEntries(options.entry);
|
|
823
|
-
normalizedEntry.forEach((entry) => {
|
|
824
|
-
const entryPath = path2__default.default.resolve(rootDir, entry.path);
|
|
825
|
-
const parentDir = path2__default.default.dirname(entryPath);
|
|
826
|
-
watchPaths.add(parentDir);
|
|
827
|
-
});
|
|
828
|
-
const watcher = chokidar__default.default.watch(Array.from(watchPaths), {
|
|
829
|
-
persistent: true,
|
|
830
|
-
ignoreInitial: true,
|
|
831
|
-
awaitWriteFinish: {
|
|
832
|
-
stabilityThreshold: 100,
|
|
833
|
-
pollInterval: 50
|
|
834
|
-
},
|
|
835
|
-
atomic: true,
|
|
836
|
-
ignorePermissionErrors: true,
|
|
837
|
-
ignored: [/[\\/]\.git[\\/]/, /[\\/]node_modules[\\/]/, options.outDir]
|
|
838
|
-
});
|
|
839
|
-
let debounceTimer = null;
|
|
840
|
-
let isRebuilding = false;
|
|
841
|
-
const triggerRebuild = async (changedFile) => {
|
|
842
|
-
if (isRebuilding) return;
|
|
843
|
-
isRebuilding = true;
|
|
844
|
-
try {
|
|
845
|
-
await build(
|
|
846
|
-
{
|
|
847
|
-
...options,
|
|
848
|
-
entry: [changedFile],
|
|
849
|
-
clean: false
|
|
850
|
-
},
|
|
851
|
-
rootDir
|
|
852
|
-
);
|
|
853
|
-
} catch (error) {
|
|
854
|
-
logger.error(`Build failed: ${error}`);
|
|
855
|
-
} finally {
|
|
856
|
-
isRebuilding = false;
|
|
857
|
-
}
|
|
858
|
-
};
|
|
859
|
-
watcher.on("change", (filePath) => {
|
|
860
|
-
const changedFile = path2__default.default.relative(rootDir, filePath);
|
|
861
|
-
logger.cli(`File changed: ${changedFile}`);
|
|
862
|
-
if (debounceTimer) {
|
|
863
|
-
clearTimeout(debounceTimer);
|
|
864
|
-
}
|
|
865
|
-
debounceTimer = setTimeout(() => triggerRebuild(changedFile), 300);
|
|
866
|
-
});
|
|
867
|
-
watcher.on("error", (error) => {
|
|
868
|
-
logger.error(`Watcher error: ${error}`);
|
|
869
|
-
});
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
// src/cli.ts
|
|
873
|
-
async function main(args = Bun.argv.slice(2)) {
|
|
874
|
-
const cliOptions = parseCliOptions(args);
|
|
875
|
-
const configs = await loadConfigs(process.cwd());
|
|
876
|
-
const rootDir = process.cwd();
|
|
877
|
-
if (cliOptions.watch) {
|
|
878
|
-
logger.cli("Starting watch mode");
|
|
879
|
-
logger.cli(`Watching for file changes`);
|
|
880
|
-
}
|
|
881
|
-
if (configs.length === 0) {
|
|
882
|
-
const mergedOptions = {
|
|
883
|
-
...DEFAULT_OPTIONS,
|
|
884
|
-
...cliOptions
|
|
885
|
-
};
|
|
886
|
-
if (mergedOptions.clean) cleanOutDir(rootDir, mergedOptions.outDir);
|
|
887
|
-
await handleBuild(mergedOptions, rootDir);
|
|
888
|
-
} else {
|
|
889
|
-
for (const { options, rootDir: rootDir2 } of configs) {
|
|
890
|
-
if (options.clean) cleanOutDir(rootDir2, options.outDir);
|
|
891
|
-
}
|
|
892
|
-
await Promise.all(
|
|
893
|
-
configs.map(async ({ options, rootDir: rootDir2 }) => {
|
|
894
|
-
const mergedOptions = {
|
|
895
|
-
...DEFAULT_OPTIONS,
|
|
896
|
-
...options,
|
|
897
|
-
...cliOptions
|
|
898
|
-
};
|
|
899
|
-
await handleBuild(mergedOptions, rootDir2);
|
|
900
|
-
})
|
|
901
|
-
);
|
|
902
|
-
}
|
|
903
|
-
if (!cliOptions.watch) {
|
|
904
|
-
process.exit(0);
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
async function handleBuild(options, rootDir) {
|
|
908
|
-
if (options.watch) {
|
|
909
|
-
await watch(options, rootDir);
|
|
910
|
-
} else {
|
|
911
|
-
await build(options, rootDir);
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
function cleanOutDir(rootDir, outdir) {
|
|
915
|
-
const outdirPath = path2__default.default.join(rootDir, outdir);
|
|
916
|
-
if (fs2__default.default.existsSync(outdirPath)) {
|
|
917
|
-
try {
|
|
918
|
-
fs2__default.default.rmSync(outdirPath, { recursive: true, force: true });
|
|
919
|
-
} catch (error) {
|
|
920
|
-
logger.error(`Failed to clean output directory: ${error}`);
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
fs2__default.default.mkdirSync(outdirPath, { recursive: true });
|
|
924
|
-
}
|
|
925
|
-
main().catch((error) => {
|
|
926
|
-
handleError(error);
|
|
927
|
-
process.exit(1);
|
|
928
|
-
});
|
|
929
|
-
|
|
930
|
-
exports.main = main;
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var pr=require("node:module");var mr=Object.create;var{getPrototypeOf:gr,defineProperty:S,getOwnPropertyNames:X,getOwnPropertyDescriptor:xr}=Object,z=Object.prototype.hasOwnProperty;var g=(r,s,e)=>{e=r!=null?mr(gr(r)):{};let n=s||!r||!r.__esModule?S(e,"default",{value:r,enumerable:!0}):e;for(let t of X(r))if(!z.call(n,t))S(n,t,{get:()=>r[t],enumerable:!0});return n},I=new WeakMap,Or=(r)=>{var s=I.get(r),e;if(s)return s;if(s=S({},"__esModule",{value:!0}),r&&typeof r==="object"||typeof r==="function")X(r).map((n)=>!z.call(s,n)&&S(s,n,{get:()=>r[n],enumerable:!(e=xr(r,n))||e.enumerable}));return I.set(r,s),s};var wr=(r,s)=>{for(var e in s)S(r,e,{get:s[e],enumerable:!0,configurable:!0,set:(n)=>s[e]=()=>n})};var Ar={};wr(Ar,{main:()=>hr});module.exports=Or(Ar);var R=g(require("fs")),lr=g(require("path"));var er=g(require("path"));var $=g(require("fs")),d=g(require("path")),T=g(require("oxc-transform")),rr=require("rollup"),sr=g(require("rollup-plugin-dts"));var x=(r)=>{if(r instanceof Error)return r.message;return String(r)},K=(r,s)=>{let e=x(r),n=s?`[${s}] `:"";if(console.error(`\x1B[31m[ERROR]\x1B[0m ${n}${e}`),r instanceof Error&&r.stack)console.error("\x1B[2m"+r.stack.split(`
|
|
3
|
+
`).slice(1).join(`
|
|
4
|
+
`)+"\x1B[0m")};function H(r){return r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Y(r=8){return Math.random().toString(36).substring(2,2+r)}function Z(r,s){switch(r){case"esm":return".mjs";case"cjs":return E(s)?".cjs":".js";case"iife":return".global.js"}}function D(r,s){switch(r){case"esm":return".d.mts";case"cjs":return E(s)?".d.cts":".d.ts";case"iife":return".d.ts"}}function E(r){return r==="module"}function q(r){return r>=1000?`${(r/1000).toFixed(2)}s`:`${Math.round(r)}ms`}function F(r){if(!r)return[];return Array.from(new Set([...Object.keys(r.dependencies||{}),...Object.keys(r.peerDependencies||{})]))}function J(r,s){return r===void 0?s==="esm":r}function V(r){return r.map((s)=>typeof s==="string"?new RegExp(`^${H(s)}($|\\/|\\\\)`):s)}function B(r,s){return V(r.external||[]).concat(F(s).map((e)=>new RegExp(`^${H(e)}($|\\/|\\\\)`)))}function C(r){return V(r.noExternal||[])}var k=g(require("fs")),U=g(require("path"));var c={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,s,e){let n=" ".repeat(Math.max(0,this.MAX_LABEL_LENGTH-s.length));return`\x1B[38;5;${r}m[${s}]\x1B[0m ${n}${e}`},cli(r){let s=this.labels.cli;console.log(this.formatMessage(this.colors.cli,s,r))},info(r){let s=this.labels.info;console.log(this.formatMessage(this.colors.info,s,r))},warn(r){let s=this.labels.warn;console.warn(this.formatMessage(this.colors.warn,s,r))},error(r){let s=this.labels.error;console.error(this.formatMessage(this.colors.error,s,r))},progress(r,s){let e=String(r),n=this.colors.default;for(let[t,i]of Object.entries(this.colors.progress))if(e.includes(t)){n=i;break}console.log(this.formatMessage(n,e,s))}};function y(r,s){return`${s?`${s.replace(/-/g,"_")}_`:""}${r}`.toUpperCase()}var W={entry:[],format:["esm"],outDir:"dist",minify:!1,watch:!1,dts:!1,target:"node",external:[],clean:!0};function P(r,s){return{outdir:`${s}/${r.outDir}`,minify:dr(r),target:r.target,splitting:r.splitting}}function dr(r){let{minify:s,minifyWhitespace:e,minifyIdentifiers:n,minifySyntax:t}=r,i=s===!0;return{whitespace:e??i,identifiers:n??i,syntax:t??i}}async function b(r){let s=[];for(let e of[".ts",".js",".mjs",".cjs",".mts",".cts",".json",".jsonc"]){let n=U.default.join(r,`bunup.config${e}`);try{if(!k.default.existsSync(n))continue;let t;if(e===".json"||e===".jsonc"){let i=k.default.readFileSync(n,"utf8");t=JSON.parse(i)}else{let i=await import(`file://${n}`);if(t=i.default||i,!t)c.warn(`No default export found in ${n}`),t={}}if(Array.isArray(t))for(let i of t)s.push({options:{...W,...i},rootDir:r});else s.push({options:{...W,...t},rootDir:r});break}catch(t){c.error(`Failed to load config from ${n}: ${x(t)}`)}if(s.length>0)break}return s}function j(r){let s=U.default.join(r,"package.json");try{if(!k.default.existsSync(s))return null;let e=k.default.readFileSync(s,"utf8");return JSON.parse(e)}catch(e){return c.error(`Failed to load package.json at ${s}: ${x(e)}`),null}}async function nr(r,s,e,n){let{absoluteRootDir:t,absoluteEntry:i}=vr(r,s),o=await Wr(i),u=await Sr(o);return kr(i,u,e,n,t)}async function Wr(r){let s=new Set,e=[r];while(e.length>0){let n=e.pop();if(!n||s.has(n))continue;s.add(n);try{let t=await $.default.promises.readFile(n,"utf8"),i=$r(t);for(let o of i){let u=d.default.dirname(n),a=d.default.resolve(u,o),f=[a,`${a}.ts`,`${a}.tsx`,`${a}/index.ts`,`${a}/index.tsx`];for(let l of f)if($.default.existsSync(l)&&l.endsWith(".ts")&&!s.has(l)){e.push(l);break}}}catch(t){c.warn(`Error processing ${n}: ${t instanceof Error?t.message:String(t)}`)}}return s}function $r(r){let s=new Set;try{let e=/(?:import|export)(?:(?:[\s\n]*(?:type[\s\n]+)?(?:\*|\{[^}]*\}|[\w$]+)[\s\n]+from[\s\n]*)|[\s\n]+)(["'`])([^'"]+)\1/g,n;while((n=e.exec(r))!==null){let o=n[2];if(o.startsWith("."))s.add(o)}let t=/import\s+(["'`])([^'"]+)\1\s*;?/g;while((n=t.exec(r))!==null){let o=n[2];if(o.startsWith("."))s.add(o)}let i=/import\s*\(\s*(["'`])([^'"]+)\1\s*\)/g;while((n=i.exec(r))!==null){let o=n[2];if(o.startsWith("."))s.add(o)}}catch(e){c.warn(`Error extracting imports: ${e instanceof Error?e.message:String(e)}`)}return Array.from(s)}async function Sr(r){let s=new Map;return await Promise.all(Array.from(r).map(async(e)=>{try{let n=e.replace(/\.tsx?$/,".d.ts"),t=await $.default.promises.readFile(e,"utf8"),{code:i}=T.default.isolatedDeclaration(e,t);if(i)s.set(n,i)}catch(n){c.warn(`Failed to generate declaration for ${e}: ${n instanceof Error?n.message:String(n)}`)}})),s}async function kr(r,s,e,n,t){let u=`\x00virtual:${r.replace(/\.tsx?$/,".d.ts")}`,a={name:"virtual-dts",resolveId(m,h){if(m.startsWith("\x00virtual:"))return m;if(h?.startsWith("\x00virtual:")){let w=h.slice(9),L=d.default.dirname(w);if(m.startsWith(".")){let _=d.default.resolve(L,m);for(let M of["",".d.ts","/index.d.ts"]){let G=`${_}${M}`;if(s.has(G))return`\x00virtual:${G}`}}}return null},load(m){if(m.startsWith("\x00virtual:")){let h=m.slice(9);return s.get(h)||null}return null}},f=j(t),l=B(n,f),O=C(n),p;try{p=await rr.rollup({input:u,onwarn(h,w){if(h.code==="UNRESOLVED_IMPORT"||h.code==="CIRCULAR_DEPENDENCY"||h.code==="EMPTY_BUNDLE")return;w(h)},plugins:[a,sr.default()],external:(h)=>l.some((w)=>w.test(h))&&!O.some((w)=>w.test(h))});let{output:m}=await p.generate({format:e});if(!m[0]?.code)throw new Error("Generated bundle is empty");return m[0].code}catch(m){throw new Error(`DTS bundling failed: ${x(m)}`)}finally{if(p)await p.close()}}function vr(r,s){let e=d.default.resolve(r),n=d.default.resolve(e,s);if(!$.default.existsSync(e))throw new Error(`Root directory does not exist: ${e}`);if(!$.default.existsSync(n))throw new Error(`Entry file does not exist: ${n}`);if(!n.endsWith(".ts"))throw new Error(`Entry file must be a TypeScript file (.ts): ${n}`);if(d.default.relative(e,n).startsWith(".."))throw new Error(`Entry file must be within rootDir: ${n}`);return{absoluteRootDir:e,absoluteEntry:n}}var __dirname="/home/runner/work/bunup/bunup/src/dts";self.onmessage=async(r)=>{let{name:s,rootDir:e,outDir:n,entry:t,format:i,packageType:o,options:u}=r.data;try{let a=await nr(e,t.path,i,u),f=D(i,o),l=`${n}/${t.name}${f}`,O=`${e}/${l}`;await Bun.write(O,a);let p={name:s,success:!0,outputRelativePath:l};self.postMessage(p)}catch(a){let f={success:!1,error:x(a)};self.postMessage(f)}};class Q{workers=[];queue=[];maxWorkers;busyWorkers=new Set;isShuttingDown=!1;constructor(r=navigator.hardwareConcurrency||4){this.maxWorkers=r}async process(r){if(this.isShuttingDown)throw new Error("Worker pool is shutting down");return new Promise((s,e)=>{this.queue.push({task:r,resolve:s,reject:e}),this.processQueue()})}processQueue(){if(this.queue.length===0||this.isShuttingDown)return;if(this.workers.length<this.maxWorkers){let r=new Worker(er.default.join(__dirname,"./dtsWorker.js"));this.workers.push(r),this.assignTaskToWorker(r)}else{let r=this.workers.find((s)=>!this.busyWorkers.has(s));if(r)this.assignTaskToWorker(r)}}assignTaskToWorker(r){let s=this.queue.shift();if(!s)return;let{task:e,resolve:n,reject:t}=s;this.busyWorkers.add(r);let i=()=>{if(this.busyWorkers.delete(r),this.isShuttingDown&&this.busyWorkers.size===0)this.terminateAllWorkers();else this.processQueue()};r.onmessage=(o)=>{if(o.data.success)c.progress(y("DTS",o.data.name),o.data.outputRelativePath),n();else c.error(`DTS generation failed: ${o.data.error}`),t(new Error(o.data.error));i()},r.onerror=(o)=>{let u=x(o);c.error(`Worker error: ${u}`),t(o),i()},r.postMessage(e)}terminateAllWorkers(){this.workers.forEach((r)=>{try{r.terminate()}catch(s){c.error(`Error terminating worker: ${x(s)}`)}}),this.workers=[],this.busyWorkers.clear()}async cleanup(){if(this.isShuttingDown=!0,this.busyWorkers.size===0){this.terminateAllWorkers();return}return new Promise((r)=>{let s=setInterval(()=>{if(this.busyWorkers.size===0)clearInterval(s),this.terminateAllWorkers(),r()},100);setTimeout(()=>{clearInterval(s),this.terminateAllWorkers(),r()},5000)})}}function Er(r){return r.split("/").pop()?.split(".").slice(0,-1).join(".")||""}function v(r){let s=[],e=new Set;function n(t,i){if(e.has(t)){let o=Y();s.push({name:`${t}_${o}`,path:i})}else s.push({name:t,path:i}),e.add(t)}if(Array.isArray(r))for(let t of r){let i=Er(t);n(i,t)}else Object.entries(r).forEach(([t,i])=>{n(t,i)});return s}function tr(r,s){return`[dir]/${r}${s}`}function ir(r,s){return{name:"bunup:external-plugin",setup(e){e.onResolve({filter:/.*/},(n)=>{let t=n.path;if(r.some((o)=>o.test(t))&&!s.some((o)=>o.test(t)))return{path:t,external:!0};return null})}}}async function A(r,s){if(!r.entry||r.entry.length===0||!r.outDir){c.cli("Nothing to build. Please make sure you have provided a proper bunup configuration or cli arguments.");return}let e=performance.now();c.cli("Build started");let n=j(s),t=n?.type,i=B(r,n),o=C(r),u=[ir(i,o)],a=v(r.entry),f=r.format.flatMap((l)=>a.map((O)=>Cr(r,s,O,l,t,u)));try{await Promise.all(f);let l=performance.now()-e,O=q(l);c.cli(`⚡ Build success in ${O}`)}catch(l){c.error("Build process encountered errors."),process.exit(1)}if(r.dts){let l=performance.now();c.progress("DTS","Bundling types");let O=r.format.filter((h)=>{if(h==="iife"&&!E(t)&&r.format.includes("cjs"))return!1;return!0}),p=r.dts===!0?a:v(r.dts.entry),m=new Q;try{let h=O.flatMap((_)=>p.map((M)=>Br(r,s,M,_,t,m)));await Promise.all(h);let w=performance.now()-l,L=q(w);c.progress("DTS",`Bundled types in ${L}`)}catch(h){await m.cleanup()}await m.cleanup()}}async function Br(r,s,e,n,t,i){let o={name:r.name,rootDir:s,outDir:r.outDir,entry:e,format:n,packageType:t,options:r};await i.process(o)}async function Cr(r,s,e,n,t,i){let o=Z(n,t),u=P(r,s),a=await Bun.build({...u,entrypoints:[`${s}/${e.path}`],format:n,naming:{entry:tr(e.name,o)},splitting:J(r.splitting,n),plugins:i});if(!a.success)throw a.logs.forEach((f)=>{if(f.level==="error")c.error(f.message);else if(f.level==="warning")c.warn(f.message);else if(f.level==="info")c.info(f.message)}),new Error(`Build failed for ${e} (${n})`);c.progress(y(n,r.name),`${r.outDir}/${e.name}${o}`)}var yr={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"},jr={name:(r,s)=>{s.name=r},format:(r,s)=>{s.format=r.split(",")},outDir:(r,s)=>{s.outDir=r},minify:(r,s)=>{s.minify=!!r},watch:(r,s)=>{s.watch=!!r},dts:(r,s)=>{s.dts=!!r},external:(r,s)=>{s.external=r.split(",")},minifyWhitespace:(r,s)=>{s.minifyWhitespace=!!r},minifyIdentifiers:(r,s)=>{s.minifyIdentifiers=!!r},minifySyntax:(r,s)=>{s.minifySyntax=!!r},target:(r,s)=>{s.target=r},clean:(r,s)=>{s.clean=!!r},splitting:(r,s)=>{s.splitting=!!r},noExternal:(r,s)=>{s.noExternal=r.split(",")}};function or(r){let s={};for(let e=0;e<r.length;e++){let n=r[e];if(n.startsWith("--")||n.startsWith("-")){let t=n.startsWith("-")&&!n.startsWith("--"),i=t?n.slice(1):n.slice(2),o=t?yr[i]:i,u=jr[o];if(!u){c.error(`Unknown option: ${i}`);continue}let a=r[e+1],f=a&&!a.startsWith("-")?a:!0;if(u(f,s),typeof f==="string")e++}else{if(!s.entry)s.entry=[];if(Array.isArray(s.entry))s.entry.push(n)}}return s}(()=>{if(typeof Bun==="undefined")c.error(`Bunup requires Bun to run.
|
|
5
|
+
To install Bun, visit https://bun.sh/docs/installation`),process.exit(1)})();var N=g(require("path")),cr=g(require("chokidar"));async function ar(r,s){let e=new Set;v(r.entry).forEach((a)=>{let f=N.default.resolve(s,a.path),l=N.default.dirname(f);e.add(l)});let t=cr.default.watch(Array.from(e),{persistent:!0,ignoreInitial:!0,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50},atomic:!0,ignorePermissionErrors:!0,ignored:[/[\\/]\.git[\\/]/,/[\\/]node_modules[\\/]/,r.outDir]}),i=null,o=!1,u=async(a)=>{if(o)return;o=!0;try{await A({...r,entry:[a],clean:!1},s)}catch(f){c.error(`Build failed: ${f}`)}finally{o=!1}};t.on("change",(a)=>{let f=N.default.relative(s,a);if(c.cli(`File changed: ${f}`),i)clearTimeout(i);i=setTimeout(()=>u(f),300)}),t.on("error",(a)=>{c.error(`Watcher error: ${a}`)})}async function hr(r=Bun.argv.slice(2)){let s=or(r),e=await b(process.cwd()),n=process.cwd();if(s.watch)c.cli("Starting watch mode"),c.cli("Watching for file changes");if(e.length===0){let t={...W,...s};if(t.clean)ur(n,t.outDir);await fr(t,n)}else{for(let{options:t,rootDir:i}of e)if(t.clean)ur(i,t.outDir);await Promise.all(e.map(async({options:t,rootDir:i})=>{let o={...W,...t,...s};await fr(o,i)}))}if(!s.watch)process.exit(0)}async function fr(r,s){if(r.watch)await ar(r,s);else await A(r,s)}function ur(r,s){let e=lr.default.join(r,s);if(R.default.existsSync(e))try{R.default.rmSync(e,{recursive:!0,force:!0})}catch(n){c.error(`Failed to clean output directory: ${n}`)}R.default.mkdirSync(e,{recursive:!0})}hr().catch((r)=>{K(r),process.exit(1)});
|