@d1g1tal/tsbuild 1.2.1 → 1.2.2

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.
@@ -0,0 +1,2401 @@
1
+ import {
2
+ BuildMessageType,
3
+ Encoding,
4
+ FileExtension,
5
+ Json,
6
+ Paths,
7
+ Platform,
8
+ __decorateElement,
9
+ __decoratorStart,
10
+ __publicField,
11
+ __runInitializers,
12
+ buildInfoFile,
13
+ cacheDirectory,
14
+ compilerOptionOverrides,
15
+ dataUnits,
16
+ defaultCleanOptions,
17
+ defaultDirOptions,
18
+ defaultEntryFile,
19
+ defaultEntryPoint,
20
+ defaultOutDirectory,
21
+ defaultSourceDirectory,
22
+ dtsCacheFile,
23
+ dtsCacheVersion,
24
+ format,
25
+ inlineTypePattern,
26
+ newLine,
27
+ processEnvExpansionPattern,
28
+ sourceScriptExtensionExpression,
29
+ toEsTarget,
30
+ toJsxRenderingMode,
31
+ typeMatcher
32
+ } from "./7FPDHUPW.js";
33
+
34
+ // src/errors.ts
35
+ import { SyntaxKind } from "typescript";
36
+ var BuildError = class extends Error {
37
+ /**
38
+ * Creates a new BuildError
39
+ * @param message - Error message
40
+ * @param code - Exit code (default: 1)
41
+ */
42
+ constructor(message, code = 1) {
43
+ super(message);
44
+ this.code = code;
45
+ this.name = "BuildError";
46
+ Error.captureStackTrace(this, this.constructor);
47
+ }
48
+ };
49
+ var TypeCheckError = class extends BuildError {
50
+ /**
51
+ * Creates a new TypeCheckError
52
+ * @param message - Error message
53
+ * @param diagnostics - Optional TypeScript diagnostics output
54
+ */
55
+ constructor(message, diagnostics) {
56
+ super(message, 1);
57
+ this.diagnostics = diagnostics;
58
+ this.name = "TypeCheckError";
59
+ }
60
+ };
61
+ var BundleError = class extends BuildError {
62
+ /**
63
+ * Creates a new BundleError
64
+ * @param message - Error message
65
+ */
66
+ constructor(message) {
67
+ super(message, 2);
68
+ this.name = "BundleError";
69
+ }
70
+ };
71
+ var ConfigurationError = class extends BuildError {
72
+ /**
73
+ * Creates a new ConfigurationError
74
+ * @param message - Error message
75
+ */
76
+ constructor(message) {
77
+ super(message, 3);
78
+ this.name = "ConfigurationError";
79
+ }
80
+ };
81
+ var UnsupportedSyntaxError = class extends BundleError {
82
+ /**
83
+ * Creates an instance of UnsupportedSyntaxError.
84
+ * @param node The node with unsupported syntax
85
+ * @param message The message to display (default: 'Syntax not yet supported')
86
+ */
87
+ constructor(node, message = "Syntax not yet supported") {
88
+ const syntaxKindName = SyntaxKind[node.kind] ?? `Unknown(${node.kind})`;
89
+ const nodeText = node.getText ? node.getText().slice(0, 100) : "<no text>";
90
+ super(`${message}: ${syntaxKindName} - "${nodeText}"`);
91
+ this.name = "UnsupportedSyntaxError";
92
+ }
93
+ };
94
+ var castError = (exception) => {
95
+ if (exception instanceof Error) {
96
+ return exception;
97
+ }
98
+ return new Error(typeof exception === "string" ? exception : "Unknown error");
99
+ };
100
+
101
+ // src/files.ts
102
+ import { dirname } from "node:path";
103
+ import { serialize, deserialize } from "node:v8";
104
+ import { brotliDecompress, brotliCompress } from "node:zlib";
105
+ import { access, constants, mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
106
+ var Files = class _Files {
107
+ constructor() {
108
+ }
109
+ /**
110
+ * Check if a file exists.
111
+ * @param filePath The path to the file.
112
+ * @returns True if the file exists, false otherwise.
113
+ */
114
+ static async exists(filePath) {
115
+ try {
116
+ await access(filePath, constants.F_OK);
117
+ return true;
118
+ } catch (error) {
119
+ if (error.code === "ENOENT") {
120
+ return false;
121
+ }
122
+ throw error;
123
+ }
124
+ }
125
+ /**
126
+ * Clear a directory by removing all files and subdirectories.
127
+ * @param directory The path to the directory to clear.
128
+ */
129
+ static async empty(directory) {
130
+ if (await _Files.exists(directory)) {
131
+ await Promise.all((await readdir(directory)).map((file) => rm(Paths.join(directory, file), defaultCleanOptions)));
132
+ }
133
+ }
134
+ /**
135
+ * Write data to a file.
136
+ * Ensures the directory exists before writing
137
+ * @param filePath The path to the file.
138
+ * @param data The data to write to the file.
139
+ * @param options Optional write file options.
140
+ */
141
+ static async write(filePath, data, options = { encoding: Encoding.utf8 }) {
142
+ await mkdir(dirname(filePath), defaultDirOptions);
143
+ await writeFile(filePath, data, options);
144
+ }
145
+ /**
146
+ * Load a file and return its contents as a string.
147
+ * @param filePath The path to the file.
148
+ * @param encoding The encoding to use when reading the file. Default is UTF-8.
149
+ * @returns The file contents as a string.
150
+ */
151
+ static async read(filePath, encoding = Encoding.utf8) {
152
+ return await readFile(this.normalizePath(filePath), { encoding });
153
+ }
154
+ /**
155
+ * Reads the contents of a directory.
156
+ * @param directoryPath The path to the directory.
157
+ * @returns An array of file and directory names within the specified directory.
158
+ */
159
+ static async readDirectory(directoryPath) {
160
+ return await readdir(directoryPath);
161
+ }
162
+ /**
163
+ * Normalize a file path to an absolute path.
164
+ * @param path The file path to normalize.
165
+ * @returns The normalized absolute path.
166
+ */
167
+ static normalizePath(path) {
168
+ return path.startsWith("/") || path.startsWith("file://") ? path : new URL(path, import.meta.url).pathname;
169
+ }
170
+ /**
171
+ * Decompress a Brotli-compressed buffer.
172
+ * Uses callback-based API wrapped in a Promise for faster performance than streaming.
173
+ * @param buffer The compressed buffer to decompress.
174
+ * @returns The decompressed buffer.
175
+ */
176
+ static decompressBuffer(buffer) {
177
+ return new Promise((resolve, reject) => brotliDecompress(buffer, (error, result) => error ? reject(error) : resolve(result)));
178
+ }
179
+ /**
180
+ * Compress data using Brotli compression.
181
+ * Uses callback-based API wrapped in a Promise for faster performance than streaming.
182
+ * @param buffer The buffer to compress.
183
+ * @returns The compressed buffer.
184
+ */
185
+ static compressBuffer(buffer) {
186
+ return new Promise((resolve, reject) => brotliCompress(buffer, (error, result) => error ? reject(error) : resolve(result)));
187
+ }
188
+ /**
189
+ * Load a file and deserialize it using V8 deserialization.
190
+ * Faster than JSON.parse for complex objects.
191
+ * @param path The path to the file.
192
+ * @returns The deserialized object.
193
+ */
194
+ static async readCompressed(path) {
195
+ return deserialize(await this.decompressBuffer(await readFile(this.normalizePath(path))));
196
+ }
197
+ /**
198
+ * Serialize an object using V8 serialization and save to a Brotli-compressed file.
199
+ * Faster than JSON.stringify for complex objects.
200
+ * @param path The path to the file.
201
+ * @param data The object to serialize and save.
202
+ */
203
+ static async writeCompressed(path, data) {
204
+ const normalizedPath = this.normalizePath(path);
205
+ await mkdir(dirname(normalizedPath), defaultDirOptions);
206
+ await writeFile(normalizedPath, await this.compressBuffer(serialize(data)));
207
+ }
208
+ };
209
+
210
+ // src/type-script-project.ts
211
+ import { Watchr } from "@d1g1tal/watchr";
212
+
213
+ // src/text-formatter.ts
214
+ import { isatty } from "node:tty";
215
+ var { env = {}, platform = "" } = process;
216
+ var isDumbTerminal = env.TERM === "dumb";
217
+ var isCompatibleTerminal = isatty(1) && env.TERM && !isDumbTerminal;
218
+ var isColorSupported = !("NO_COLOR" in env) && ("FORCE_COLOR" in env || platform === "win32" && !isDumbTerminal || isCompatibleTerminal);
219
+ var replaceClose = (index, string, close, replace, head = string.substring(0, index) + replace, tail = string.substring(index + close.length), next = tail.indexOf(close)) => {
220
+ return head + (next < 0 ? tail : replaceClose(next, tail, close, replace));
221
+ };
222
+ var clearBleed = (index, string, open, close, replace) => {
223
+ return index < 0 ? `${open}${string}${close}` : `${open}${replaceClose(index, string, close, replace)}${close}`;
224
+ };
225
+ var filterEmpty = (open, close, replace = open, at = open.length + 1) => {
226
+ return (text) => text.length ? clearBleed(text.indexOf(close, at), text, open, close, replace) : "";
227
+ };
228
+ var generateTextFormatter = (open, close, replace) => filterEmpty(`\x1B[${open}m`, `\x1B[${close}m`, replace);
229
+ var TextFormat = class {
230
+ static enabled = isColorSupported;
231
+ static reset = generateTextFormatter(0, 0);
232
+ static bold = generateTextFormatter(1, 22, "\x1B[22m\x1B[1m");
233
+ static dim = generateTextFormatter(2, 22, "\x1B[22m\x1B[2m");
234
+ static italic = generateTextFormatter(3, 23);
235
+ static underline = generateTextFormatter(4, 24);
236
+ static inverse = generateTextFormatter(7, 27);
237
+ static hidden = generateTextFormatter(8, 28);
238
+ static strikethrough = generateTextFormatter(9, 29);
239
+ static black = generateTextFormatter(30, 39);
240
+ static red = generateTextFormatter(31, 39);
241
+ static green = generateTextFormatter(32, 39);
242
+ static yellow = generateTextFormatter(33, 39);
243
+ static blue = generateTextFormatter(34, 39);
244
+ static magenta = generateTextFormatter(35, 39);
245
+ static cyan = generateTextFormatter(36, 39);
246
+ static white = generateTextFormatter(37, 39);
247
+ static gray = generateTextFormatter(90, 39);
248
+ static bgBlack = generateTextFormatter(40, 49);
249
+ static bgRed = generateTextFormatter(41, 49);
250
+ static bgGreen = generateTextFormatter(42, 49);
251
+ static bgYellow = generateTextFormatter(43, 49);
252
+ static bgBlue = generateTextFormatter(44, 49);
253
+ static bgMagenta = generateTextFormatter(45, 49);
254
+ static bgCyan = generateTextFormatter(46, 49);
255
+ static bgWhite = generateTextFormatter(47, 49);
256
+ static blackBright = generateTextFormatter(90, 39);
257
+ static redBright = generateTextFormatter(91, 39);
258
+ static greenBright = generateTextFormatter(92, 39);
259
+ static yellowBright = generateTextFormatter(93, 39);
260
+ static blueBright = generateTextFormatter(94, 39);
261
+ static magentaBright = generateTextFormatter(95, 39);
262
+ static cyanBright = generateTextFormatter(96, 39);
263
+ static whiteBright = generateTextFormatter(97, 39);
264
+ static bgBlackBright = generateTextFormatter(100, 49);
265
+ static bgRedBright = generateTextFormatter(101, 49);
266
+ static bgGreenBright = generateTextFormatter(102, 49);
267
+ static bgYellowBright = generateTextFormatter(103, 49);
268
+ static bgBlueBright = generateTextFormatter(104, 49);
269
+ static bgMagentaBright = generateTextFormatter(105, 49);
270
+ static bgCyanBright = generateTextFormatter(106, 49);
271
+ static bgWhiteBright = generateTextFormatter(107, 49);
272
+ };
273
+
274
+ // src/logger.ts
275
+ var isWrittenFiles = (data) => {
276
+ if (!Array.isArray(data)) {
277
+ return false;
278
+ }
279
+ return data.every((writtenFile) => {
280
+ return writtenFile !== null && typeof writtenFile === "object" && "path" in writtenFile && "size" in writtenFile;
281
+ });
282
+ };
283
+ var colorize = (type2, data, onlyImportant = false) => {
284
+ if (onlyImportant && (type2 === "info" || type2 === "success")) {
285
+ return data;
286
+ }
287
+ switch (type2) {
288
+ case "info":
289
+ return TextFormat.blue(data);
290
+ case "error":
291
+ return TextFormat.red(data);
292
+ case "warn":
293
+ return TextFormat.yellow(data);
294
+ default:
295
+ return TextFormat.green(data);
296
+ }
297
+ };
298
+ var prettyBytes = (bytes) => {
299
+ if (bytes === 0) {
300
+ return { value: "0", unit: "B" };
301
+ }
302
+ const exp = ~~(Math.log(bytes) / Math.log(1024));
303
+ return { value: (bytes / Math.pow(1024, exp)).toFixed(2), unit: dataUnits[exp] };
304
+ };
305
+ var Logger = class _Logger {
306
+ constructor() {
307
+ }
308
+ static EntryType = {
309
+ Info: "info",
310
+ Success: "success",
311
+ Done: "done",
312
+ Error: "error",
313
+ Warn: "warn"
314
+ };
315
+ /** Clears the console */
316
+ static clear() {
317
+ console.log("\x1Bc");
318
+ }
319
+ /**
320
+ * Logs a header box with a message.
321
+ * @param message The message to display in the header.
322
+ */
323
+ static header(message) {
324
+ const innerWidth = message.length + 2;
325
+ console.log(TextFormat.cyan(`\u256D${"\u2500".repeat(innerWidth)}\u256E${newLine}\u2502 ${message} \u2502${newLine}\u2570${"\u2500".repeat(innerWidth)}\u256F`));
326
+ }
327
+ /**
328
+ * Logs a separator line.
329
+ * @param width Optional width of the separator (default: 40).
330
+ */
331
+ static separator(width = 40) {
332
+ console.log(TextFormat.dim("\u2500".repeat(width)));
333
+ }
334
+ /**
335
+ * Logs a success message with a check mark and optional indentation.
336
+ * @param message The message to log.
337
+ * @param indent Whether to indent the message (tree structure).
338
+ */
339
+ static step(message, indent = false) {
340
+ const prefix = indent ? " \u2514\u2500" : "\u2713";
341
+ console.log(TextFormat.green(`${prefix} ${message}`));
342
+ }
343
+ /**
344
+ * Logs a success message.
345
+ * @param message The message to log.
346
+ * @param args Additional data to log.
347
+ * @returns void
348
+ */
349
+ static success(message, ...args) {
350
+ return _Logger.log(message, "success", ...args);
351
+ }
352
+ /**
353
+ * Logs an info message.
354
+ * @param message The message to log.
355
+ * @param args Additional data to log.
356
+ * @returns void
357
+ */
358
+ static info(message, ...args) {
359
+ return _Logger.log(message, "info", ...args);
360
+ }
361
+ /**
362
+ * Logs an error message.
363
+ * @param message The message to log.
364
+ * @param args Additional data to log.
365
+ * @returns void
366
+ */
367
+ static error(message, ...args) {
368
+ return _Logger.log(message, "error", ...args);
369
+ }
370
+ /**
371
+ * Logs a warning message.
372
+ * @param message The message to log.
373
+ * @param args Additional data to log.
374
+ * @returns void
375
+ */
376
+ static warn(message, ...args) {
377
+ return _Logger.log(message, "warn", ...args);
378
+ }
379
+ /**
380
+ * Logs a done message.
381
+ * @param message The message to log.
382
+ * @param type The type of the log entry.
383
+ * @param data Additional data to log.
384
+ */
385
+ static log(message, type2, ...data) {
386
+ if (data.length) {
387
+ if (isWrittenFiles(data)) {
388
+ if (message) {
389
+ console.log(colorize(type2, message, true));
390
+ }
391
+ _Logger.files(data);
392
+ } else {
393
+ console.log(colorize(type2, message, true), ...data);
394
+ }
395
+ } else {
396
+ console.log(colorize(type2, message, true));
397
+ }
398
+ }
399
+ /**
400
+ * Logs an array of WrittenFile objects in a formatted manner.
401
+ * @param files - The array of WrittenFile objects to log.
402
+ * @internal
403
+ */
404
+ static files(files) {
405
+ const maxPathLength = files.reduce((max, { path }) => Math.max(max, path.length), 0);
406
+ const formatted = files.map(({ path, size }) => ({ path, ...prettyBytes(size) }));
407
+ const maxValueLength = formatted.reduce((max, { value }) => Math.max(max, value.length), 0);
408
+ const maxUnitLength = formatted.reduce((max, { unit }) => Math.max(max, unit.length), 0);
409
+ for (let i = 0, length = formatted.length; i < length; i++) {
410
+ const { path, value, unit } = formatted[i];
411
+ const paddedPath = path.padEnd(maxPathLength);
412
+ const paddedValue = value.padStart(maxValueLength);
413
+ const paddedUnit = unit.padEnd(maxUnitLength);
414
+ const prefix = i === length - 1 ? " \u2514\u2500" : " \u251C\u2500";
415
+ console.log(`${TextFormat.dim(prefix)} ${TextFormat.bold(paddedPath)} ${TextFormat.cyan(paddedValue)} ${TextFormat.dim(paddedUnit)}`);
416
+ }
417
+ }
418
+ };
419
+
420
+ // src/dts/declaration-bundler.ts
421
+ import MagicString2 from "magic-string";
422
+ import { mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
423
+ import { basename, posix } from "node:path";
424
+
425
+ // src/dts/declaration-processor.ts
426
+ import {
427
+ canHaveModifiers,
428
+ forEachChild,
429
+ isClassDeclaration,
430
+ isEmptyStatement,
431
+ isEnumDeclaration,
432
+ isExportDeclaration,
433
+ isFunctionDeclaration,
434
+ isIdentifier,
435
+ isImportDeclaration,
436
+ isImportTypeNode,
437
+ isInterfaceDeclaration,
438
+ isLiteralTypeNode,
439
+ isModuleBlock,
440
+ isModuleDeclaration,
441
+ isNamedExports,
442
+ isNamespaceExport,
443
+ isStringLiteral,
444
+ isTypeAliasDeclaration,
445
+ isVariableStatement,
446
+ ModifierFlags,
447
+ NodeFlags,
448
+ SyntaxKind as SyntaxKind2,
449
+ getCombinedModifierFlags
450
+ } from "typescript";
451
+ import MagicString from "magic-string";
452
+ var DeclarationProcessor = class _DeclarationProcessor {
453
+ constructor() {
454
+ }
455
+ /**
456
+ * Pre-processes a declaration file before bundling.
457
+ *
458
+ * The pre-process step has the following goals:
459
+ * - Fixes the "modifiers", removing any `export` modifier and adding any missing `declare` modifier
460
+ * - Splits compound `VariableStatement` into its parts
461
+ * - Moves declarations for the same "name" to be next to each other
462
+ * - Removes any triple-slash directives and records them
463
+ * - Creates a synthetic name for any nameless "export default"
464
+ * - Resolves inline `import()` statements and generates top-level imports for them
465
+ * - Generates a separate `export {}` statement for any item which had its modifiers rewritten
466
+ * - Duplicates the identifiers of a namespace `export`, so that renaming does not break it
467
+ *
468
+ * @param sourceFile The source file to process
469
+ * @returns The pre-processed output, which includes the modified code, type references, and file references
470
+ */
471
+ static preProcess(sourceFile) {
472
+ const code = new MagicString(sourceFile.getFullText());
473
+ const declaredNames = /* @__PURE__ */ new Set();
474
+ const exportedNames = /* @__PURE__ */ new Set();
475
+ let defaultExport = "";
476
+ const inlineImports = /* @__PURE__ */ new Map();
477
+ const nameRanges = /* @__PURE__ */ new Map();
478
+ function newlineAt(node, pos) {
479
+ return node.getSourceFile().getFullText()[pos] === newLine;
480
+ }
481
+ function getStart(node) {
482
+ const start = node.getFullStart();
483
+ return start + (newlineAt(node, start) ? 1 : 0);
484
+ }
485
+ function getEnd(node) {
486
+ const end = node.getEnd();
487
+ return end + (newlineAt(node, end) ? 1 : 0);
488
+ }
489
+ function parseReferenceDirectives(fileReferences2) {
490
+ const referenceDirectives = /* @__PURE__ */ new Set();
491
+ const lineStarts = sourceFile.getLineStarts();
492
+ for (const { fileName, pos } of fileReferences2) {
493
+ referenceDirectives.add(fileName);
494
+ let end = sourceFile.getLineEndOfPosition(pos);
495
+ if (code.slice(end, end + 1) === newLine) {
496
+ end += 1;
497
+ }
498
+ code.remove(lineStarts[sourceFile.getLineAndCharacterOfPosition(pos).line], end);
499
+ }
500
+ return referenceDirectives;
501
+ }
502
+ function createNameRange(node) {
503
+ return [getStart(node), getEnd(node)];
504
+ }
505
+ function checkInlineImport(node) {
506
+ forEachChild(node, checkInlineImport);
507
+ if (isImportTypeNode(node)) {
508
+ if (!isLiteralTypeNode(node.argument) || !isStringLiteral(node.argument.literal)) {
509
+ throw new UnsupportedSyntaxError(node, "inline imports should have a literal argument");
510
+ }
511
+ const children = node.getChildren();
512
+ const token = children.find(({ kind }) => kind === SyntaxKind2.DotToken || kind === SyntaxKind2.LessThanToken);
513
+ code.overwrite(children.find(({ kind }) => kind === SyntaxKind2.ImportKeyword).getStart(), token === void 0 ? node.getEnd() : token.getStart(), createNamespaceImport(node.argument.literal.text));
514
+ }
515
+ }
516
+ function createNamespaceImport(fileId) {
517
+ let importName = inlineImports.get(fileId);
518
+ if (importName === void 0) {
519
+ let sanitized = "";
520
+ for (let i = 0; i < fileId.length; i++) {
521
+ const char = fileId[i];
522
+ const code2 = char.charCodeAt(0);
523
+ if (code2 >= 97 && code2 <= 122 || code2 >= 65 && code2 <= 90 || code2 >= 48 && code2 <= 57 || code2 === 95 || code2 === 36) {
524
+ sanitized += char;
525
+ } else {
526
+ sanitized += "_";
527
+ }
528
+ }
529
+ importName = generateUniqueName(sanitized);
530
+ inlineImports.set(fileId, importName);
531
+ }
532
+ return importName;
533
+ }
534
+ function generateUniqueName(hint) {
535
+ while (declaredNames.has(hint)) {
536
+ hint = `_${hint}`;
537
+ }
538
+ declaredNames.add(hint);
539
+ return hint;
540
+ }
541
+ function pushNamedNode(name, range) {
542
+ const nodes = nameRanges.get(name);
543
+ if (nodes === void 0) {
544
+ nameRanges.set(name, [range]);
545
+ } else {
546
+ const last = nodes[nodes.length - 1];
547
+ if (last[1] === range[0]) {
548
+ last[1] = range[1];
549
+ } else {
550
+ nodes.push(range);
551
+ }
552
+ }
553
+ }
554
+ function fixModifiers(node) {
555
+ if (!canHaveModifiers(node)) {
556
+ return;
557
+ }
558
+ let hasDeclare = false;
559
+ for (const modifier of node.modifiers ?? []) {
560
+ if (modifier.kind === SyntaxKind2.DefaultKeyword || modifier.kind === SyntaxKind2.ExportKeyword) {
561
+ code.remove(modifier.getStart(), modifier.getEnd() + getTrailingWhitespaceLength(modifier.getEnd(), node.getEnd()));
562
+ } else if (modifier.kind === SyntaxKind2.DeclareKeyword) {
563
+ hasDeclare = true;
564
+ }
565
+ }
566
+ const needsDeclare = isEnumDeclaration(node) || isClassDeclaration(node) || isFunctionDeclaration(node) || isModuleDeclaration(node) || isVariableStatement(node);
567
+ if (needsDeclare && !hasDeclare) {
568
+ code.appendRight(node.getStart(), "declare ");
569
+ }
570
+ }
571
+ function duplicateExports(module) {
572
+ if (!module.body || !isModuleBlock(module.body)) {
573
+ return;
574
+ }
575
+ for (const node of module.body.statements) {
576
+ if (isExportDeclaration(node) && node.exportClause && !isNamespaceExport(node.exportClause)) {
577
+ for (const { name, propertyName } of node.exportClause.elements) {
578
+ if (propertyName === void 0) {
579
+ code.appendLeft(name.getEnd(), ` as ${name.getText()}`);
580
+ }
581
+ }
582
+ }
583
+ }
584
+ }
585
+ function getTrailingWhitespaceLength(start, end) {
586
+ let length = 0;
587
+ while (start + length < end) {
588
+ const char = code.original[start + length];
589
+ if (char === " " || char === " " || char === newLine || char === "\r") {
590
+ length++;
591
+ } else {
592
+ break;
593
+ }
594
+ }
595
+ return length;
596
+ }
597
+ for (const node of sourceFile.statements) {
598
+ if (isImportDeclaration(node)) {
599
+ if (node.importClause?.phaseModifier === SyntaxKind2.TypeKeyword) {
600
+ const importKeywordEnd = node.getStart() + "import".length;
601
+ const typeMatch = code.slice(importKeywordEnd, node.getEnd()).match(typeMatcher);
602
+ if (typeMatch?.index !== void 0) {
603
+ const typeKeywordStart = importKeywordEnd + typeMatch.index;
604
+ const typeKeywordEnd = typeKeywordStart + "type".length;
605
+ code.remove(typeKeywordStart, typeKeywordEnd + getTrailingWhitespaceLength(typeKeywordEnd, node.getEnd()));
606
+ }
607
+ } else {
608
+ inlineTypePattern.lastIndex = 0;
609
+ let match2;
610
+ const replacements = [];
611
+ while ((match2 = inlineTypePattern.exec(code.slice(node.getStart(), node.getEnd()))) !== null) {
612
+ const typeKeywordStart = node.getStart() + match2.index + match2[1].length;
613
+ const typeKeywordEnd = typeKeywordStart + "type".length;
614
+ replacements.push({ start: typeKeywordStart, end: typeKeywordEnd + getTrailingWhitespaceLength(typeKeywordEnd, node.getEnd()) });
615
+ }
616
+ for (let i = replacements.length - 1; i >= 0; i--) {
617
+ code.remove(replacements[i].start, replacements[i].end);
618
+ }
619
+ }
620
+ } else if (isExportDeclaration(node)) {
621
+ if (node.exportClause && isNamedExports(node.exportClause) && node.exportClause.elements.length === 0 && !node.moduleSpecifier) {
622
+ code.remove(getStart(node), getEnd(node));
623
+ } else if (node.isTypeOnly) {
624
+ const exportKeywordEnd = node.getStart() + "export".length;
625
+ const nextTokenStart = node.exportClause?.getStart() ?? node.moduleSpecifier?.getStart() ?? node.getEnd();
626
+ const typeMatch = code.slice(exportKeywordEnd, nextTokenStart).match(typeMatcher);
627
+ if (typeMatch?.index !== void 0) {
628
+ const typeKeywordStart = exportKeywordEnd + typeMatch.index;
629
+ const typeKeywordEnd = typeKeywordStart + "type".length;
630
+ const afterType = code.slice(typeKeywordEnd, nextTokenStart);
631
+ code.remove(typeKeywordStart, typeKeywordEnd + afterType.length - afterType.trimStart().length);
632
+ }
633
+ }
634
+ } else if (isEnumDeclaration(node) || isFunctionDeclaration(node) || isInterfaceDeclaration(node) || isClassDeclaration(node) || isTypeAliasDeclaration(node) || isModuleDeclaration(node)) {
635
+ if (node.name) {
636
+ const name = node.name.getText();
637
+ declaredNames.add(name);
638
+ if (_DeclarationProcessor.matchesModifier(node, ModifierFlags.ExportDefault)) {
639
+ defaultExport = name;
640
+ } else if (_DeclarationProcessor.matchesModifier(node, ModifierFlags.Export)) {
641
+ exportedNames.add(name);
642
+ }
643
+ if (!(node.flags & NodeFlags.GlobalAugmentation)) {
644
+ pushNamedNode(name, createNameRange(node));
645
+ }
646
+ }
647
+ if (isModuleDeclaration(node)) {
648
+ duplicateExports(node);
649
+ }
650
+ fixModifiers(node);
651
+ } else if (isVariableStatement(node)) {
652
+ for (const { name } of node.declarationList.declarations) {
653
+ if (isIdentifier(name)) {
654
+ const nameText = name.getText();
655
+ declaredNames.add(nameText);
656
+ if (node.modifiers?.some((modifier) => modifier.kind === SyntaxKind2.DefaultKeyword)) {
657
+ defaultExport = nameText;
658
+ } else if (node.modifiers?.some((modifier) => modifier.kind === SyntaxKind2.ExportKeyword)) {
659
+ exportedNames.add(nameText);
660
+ }
661
+ }
662
+ }
663
+ fixModifiers(node);
664
+ const { declarations } = node.declarationList;
665
+ if (declarations.length === 1) {
666
+ const [{ name }] = declarations;
667
+ if (isIdentifier(name)) {
668
+ pushNamedNode(name.getText(), createNameRange(node));
669
+ }
670
+ } else {
671
+ const decls = declarations.slice();
672
+ const first = decls.shift();
673
+ pushNamedNode(first.name.getText(), [getStart(node), first.getEnd()]);
674
+ for (const declaration of decls) {
675
+ if (isIdentifier(declaration.name)) {
676
+ pushNamedNode(declaration.name.getText(), [declaration.getFullStart(), declaration.getEnd()]);
677
+ }
678
+ }
679
+ }
680
+ const { flags } = node.declarationList;
681
+ const prefix = `declare ${flags & NodeFlags.Let ? "let" : flags & NodeFlags.Const ? "const" : "var"} `;
682
+ let commaPos = 0;
683
+ for (const declarationNode of node.declarationList.getChildren().find((n) => n.kind === SyntaxKind2.SyntaxList)?.getChildren() ?? []) {
684
+ if (declarationNode.kind === SyntaxKind2.CommaToken) {
685
+ code.remove(commaPos = declarationNode.getStart(), declarationNode.getEnd());
686
+ } else if (commaPos) {
687
+ code.appendLeft(commaPos, `;${newLine}`);
688
+ const start = declarationNode.getFullStart();
689
+ const slice = code.slice(start, declarationNode.getStart());
690
+ const whitespace = slice.length - slice.trimStart().length;
691
+ if (whitespace) {
692
+ code.overwrite(start, start + whitespace, prefix);
693
+ } else {
694
+ code.appendLeft(start, prefix);
695
+ }
696
+ }
697
+ }
698
+ }
699
+ }
700
+ for (const node of sourceFile.statements) {
701
+ checkInlineImport(node);
702
+ if ((isFunctionDeclaration(node) || isClassDeclaration(node)) && !node.name) {
703
+ if (defaultExport === "") {
704
+ defaultExport = generateUniqueName("export_default");
705
+ }
706
+ const children = node.getChildren();
707
+ const index = children.findIndex((node2) => node2.kind === SyntaxKind2.ClassKeyword || node2.kind === SyntaxKind2.FunctionKeyword);
708
+ const token = children[index];
709
+ const nextToken = children[index + 1];
710
+ if (SyntaxKind2.FirstPunctuation <= nextToken.kind && nextToken.kind <= SyntaxKind2.LastPunctuation) {
711
+ code.appendLeft(nextToken.getStart(), `${code.slice(token.getEnd(), nextToken.getStart()) !== " " ? " " : ""}${defaultExport}`);
712
+ } else {
713
+ code.appendRight(token.getEnd(), ` ${defaultExport}`);
714
+ }
715
+ }
716
+ }
717
+ for (const nameRange of nameRanges.values()) {
718
+ const [start] = nameRange.pop();
719
+ for (const [rangeStart, rangeEnd] of nameRange) {
720
+ code.move(rangeStart, rangeEnd, start);
721
+ }
722
+ }
723
+ if (defaultExport !== "") {
724
+ code.append(`${newLine}export default ${defaultExport};${newLine}`);
725
+ }
726
+ if (exportedNames.size) {
727
+ code.append(`${newLine}export { ${[...exportedNames].join(", ")} };${newLine}`);
728
+ }
729
+ for (const [fileId, importName] of inlineImports.entries()) {
730
+ code.prepend(`import * as ${importName} from "${fileId}";${newLine}`);
731
+ }
732
+ const typeReferences = parseReferenceDirectives(sourceFile.typeReferenceDirectives);
733
+ const fileReferences = parseReferenceDirectives(sourceFile.referencedFiles);
734
+ return { code: code.toString(), typeReferences, fileReferences };
735
+ }
736
+ /**
737
+ * Check if a TypeScript declaration has specific modifier flags
738
+ * @param node - The TypeScript declaration node
739
+ * @param flags - The modifier flags to check for
740
+ * @returns True if the node has all the specified flags
741
+ */
742
+ static matchesModifier = (node, flags) => (getCombinedModifierFlags(node) & flags) === flags;
743
+ /**
744
+ * Post-processes a bundled declaration file to clean up bundling artifacts.
745
+ *
746
+ * @param sourceFile The source file to process
747
+ * @returns The processed source code
748
+ */
749
+ static postProcess(sourceFile) {
750
+ const magic = new MagicString(sourceFile.getFullText());
751
+ function visitNode(node) {
752
+ if (isEmptyStatement(node)) {
753
+ magic.remove(node.getStart(), node.getEnd());
754
+ return;
755
+ }
756
+ if ((isImportDeclaration(node) || isExportDeclaration(node)) && node.moduleSpecifier && isStringLiteral(node.moduleSpecifier)) {
757
+ const { text } = node.moduleSpecifier;
758
+ if (text.startsWith(".") && text.endsWith(FileExtension.DTS)) {
759
+ const replacement = text.endsWith(".d.tsx") ? text.slice(0, -6) + FileExtension.JS : text.slice(0, -5) + FileExtension.JS;
760
+ magic.overwrite(node.moduleSpecifier.getStart() + 1, node.moduleSpecifier.getEnd() - 1, replacement);
761
+ }
762
+ }
763
+ if (isModuleDeclaration(node) && node.body && isModuleBlock(node.body)) {
764
+ for (const bodyStatement of node.body.statements) {
765
+ if (isExportDeclaration(bodyStatement) && bodyStatement.exportClause && !isNamespaceExport(bodyStatement.exportClause)) {
766
+ for (const { name, propertyName } of bodyStatement.exportClause.elements) {
767
+ if (propertyName && isIdentifier(propertyName) && isIdentifier(name) && propertyName.getText() === name.getText()) {
768
+ magic.remove(propertyName.getStart(), name.getStart());
769
+ }
770
+ }
771
+ }
772
+ }
773
+ }
774
+ forEachChild(node, visitNode);
775
+ }
776
+ visitNode(sourceFile);
777
+ return magic.toString();
778
+ }
779
+ };
780
+
781
+ // src/dts/declaration-bundler.ts
782
+ import {
783
+ sys,
784
+ createSourceFile,
785
+ ScriptTarget,
786
+ isImportDeclaration as isImportDeclaration2,
787
+ isExportDeclaration as isExportDeclaration2,
788
+ isInterfaceDeclaration as isInterfaceDeclaration2,
789
+ isTypeAliasDeclaration as isTypeAliasDeclaration2,
790
+ isEnumDeclaration as isEnumDeclaration2,
791
+ isFunctionDeclaration as isFunctionDeclaration2,
792
+ isClassDeclaration as isClassDeclaration2,
793
+ isVariableStatement as isVariableStatement2,
794
+ isModuleDeclaration as isModuleDeclaration2,
795
+ isNamedExports as isNamedExports2,
796
+ isIdentifier as isIdentifier2,
797
+ isNamespaceImport,
798
+ isQualifiedName,
799
+ resolveModuleName,
800
+ isExportAssignment,
801
+ forEachChild as forEachChild2
802
+ } from "typescript";
803
+ var nodeModules = "/node_modules/";
804
+ var importPattern = /^import\s*(?:type\s*)?\{\s*([^}]+)\s*\}\s*from\s*['"]([^'"]+)['"]\s*;?\s*$/;
805
+ var typePrefixPattern = /^type:/;
806
+ function mergeImports(imports) {
807
+ const moduleImports = /* @__PURE__ */ new Map();
808
+ const nonMergeableImports = [];
809
+ for (const importStatement of imports) {
810
+ const match2 = importPattern.exec(importStatement);
811
+ if (match2) {
812
+ const [, namesString, moduleSpecifier] = match2;
813
+ const isType = importStatement.includes("import type");
814
+ const key = `${isType ? "type:" : ""}${moduleSpecifier}`;
815
+ if (!moduleImports.has(key)) {
816
+ moduleImports.set(key, { names: /* @__PURE__ */ new Set(), isType });
817
+ }
818
+ const entry = moduleImports.get(key);
819
+ for (const name of namesString.split(",")) {
820
+ entry.names.add(name.trim());
821
+ }
822
+ } else {
823
+ nonMergeableImports.push(importStatement);
824
+ }
825
+ }
826
+ const result = [];
827
+ for (const [key, { names, isType }] of moduleImports) {
828
+ result.push(`${isType ? "import type" : "import"} { ${[...names].sort().join(", ")} } from "${key.replace(typePrefixPattern, "")}";`);
829
+ }
830
+ result.push(...[...new Set(nonMergeableImports)]);
831
+ return result;
832
+ }
833
+ var DeclarationBundler = class {
834
+ /** Project declaration files from in-memory FileManager */
835
+ declarationFiles = /* @__PURE__ */ new Map();
836
+ /** External declaration files resolved from disk (node_modules) when resolve is enabled */
837
+ externalDeclarationFiles = /* @__PURE__ */ new Map();
838
+ /** d.ts Bundle Options */
839
+ options;
840
+ /** WeakMap cache for identifier collection to avoid re-parsing same source files */
841
+ identifierCache = /* @__PURE__ */ new WeakMap();
842
+ /** Module resolution cache for this bundler instance */
843
+ moduleResolutionCache = /* @__PURE__ */ new Map();
844
+ /** Pre-computed set of directory prefixes from declaration file paths for O(1) directoryExists lookups */
845
+ declarationDirs = /* @__PURE__ */ new Set();
846
+ // Create a proper module resolution host that supports both in-memory files and disk files
847
+ moduleResolutionHost = {
848
+ fileExists: (fileName) => {
849
+ return this.declarationFiles.has(fileName) || this.externalDeclarationFiles.has(fileName) || this.options.resolve && sys.fileExists(fileName);
850
+ },
851
+ readFile: (fileName) => {
852
+ const cached = this.declarationFiles.get(fileName) ?? this.externalDeclarationFiles.get(fileName);
853
+ if (cached) {
854
+ return cached.code;
855
+ }
856
+ if (!this.options.resolve) {
857
+ return void 0;
858
+ }
859
+ const rawContent = sys.readFile(fileName, Encoding.utf8);
860
+ if (rawContent !== void 0) {
861
+ const preProcessOutput = DeclarationProcessor.preProcess(createSourceFile(fileName, rawContent, ScriptTarget.Latest, true));
862
+ this.externalDeclarationFiles.set(fileName, preProcessOutput);
863
+ return preProcessOutput.code;
864
+ }
865
+ return void 0;
866
+ },
867
+ directoryExists: (dirName) => {
868
+ const normalizedDir = dirName.endsWith("/") ? dirName.slice(0, -1) : dirName;
869
+ return this.declarationDirs.has(normalizedDir) || (this.options.resolve ? sys.directoryExists(dirName) : false);
870
+ },
871
+ getCurrentDirectory: () => this.options.currentDirectory,
872
+ /* v8 ignore next */
873
+ getDirectories: () => []
874
+ };
875
+ /**
876
+ * Creates a new DTS bundler instance
877
+ * @param dtsBundleOptions - Options for the DTS bundler
878
+ */
879
+ constructor(dtsBundleOptions) {
880
+ for (const [filePath, cachedDecl] of dtsBundleOptions.declarationFiles) {
881
+ this.declarationFiles.set(sys.resolvePath(filePath), cachedDecl);
882
+ }
883
+ for (const filePath of this.declarationFiles.keys()) {
884
+ let dir = filePath.lastIndexOf("/") !== -1 ? filePath.slice(0, filePath.lastIndexOf("/")) : "";
885
+ while (dir.length > 0) {
886
+ if (this.declarationDirs.has(dir)) {
887
+ break;
888
+ }
889
+ this.declarationDirs.add(dir);
890
+ const nextSlash = dir.lastIndexOf("/");
891
+ dir = nextSlash !== -1 ? dir.slice(0, nextSlash) : "";
892
+ }
893
+ }
894
+ this.options = dtsBundleOptions;
895
+ }
896
+ /**
897
+ * Clears external declaration files and module resolution cache to free memory.
898
+ * Called after all entry points have been bundled.
899
+ */
900
+ clearExternalFiles() {
901
+ this.externalDeclarationFiles.clear();
902
+ this.moduleResolutionCache.clear();
903
+ }
904
+ /**
905
+ * Convert a source file path to its corresponding declaration file path
906
+ * @param sourcePath - Absolute path to a source file (.ts, .tsx)
907
+ * @returns The corresponding .d.ts path, or undefined if not found
908
+ */
909
+ sourceToDeclarationPath(sourcePath) {
910
+ const { outDir, rootDir } = this.options.compilerOptions;
911
+ const sourceWithoutExt = sourcePath.substring(0, sourcePath.lastIndexOf(".") || sourcePath.length);
912
+ if (rootDir) {
913
+ const dtsPath = posix.normalize(Paths.join(outDir, Paths.relative(rootDir, sourceWithoutExt) + FileExtension.DTS));
914
+ return this.declarationFiles.has(dtsPath) ? dtsPath : sourcePath;
915
+ }
916
+ let bestMatch;
917
+ let bestRelativeLength = Infinity;
918
+ for (const dtsPath of this.declarationFiles.keys()) {
919
+ if (!dtsPath.endsWith(FileExtension.DTS)) {
920
+ continue;
921
+ }
922
+ const withoutOutDir = dtsPath.startsWith(outDir + "/") ? dtsPath.slice(outDir.length + 1) : dtsPath;
923
+ const relativeDtsPath = withoutOutDir.slice(0, -FileExtension.DTS.length);
924
+ if ((sourceWithoutExt === relativeDtsPath || sourceWithoutExt.endsWith("/" + relativeDtsPath)) && relativeDtsPath.length < bestRelativeLength) {
925
+ bestRelativeLength = relativeDtsPath.length;
926
+ bestMatch = dtsPath;
927
+ }
928
+ }
929
+ return bestMatch ?? sourcePath;
930
+ }
931
+ /**
932
+ * Extract import statements from declaration file content using AST
933
+ * Handles: import { X } from 'module', import * as X from 'module', export { X } from 'module'
934
+ * @param sourceFile - The parsed source file AST
935
+ * @returns Array of module specifiers that are imported
936
+ */
937
+ extractImports({ statements }) {
938
+ const imports = [];
939
+ for (const statement of statements) {
940
+ if ((isImportDeclaration2(statement) || isExportDeclaration2(statement)) && statement.moduleSpecifier) {
941
+ imports.push(statement.moduleSpecifier.text);
942
+ }
943
+ }
944
+ return imports;
945
+ }
946
+ /**
947
+ * Check if a module specifier matches a pattern list
948
+ * @param moduleSpecifier - The module specifier to check
949
+ * @param patterns - Array of patterns to match against
950
+ * @returns True if the module matches any pattern
951
+ */
952
+ matchesPattern(moduleSpecifier, patterns) {
953
+ return patterns.some((pattern) => {
954
+ return typeof pattern === "string" ? moduleSpecifier === pattern || moduleSpecifier.startsWith(`${pattern}/`) : pattern.test(moduleSpecifier);
955
+ });
956
+ }
957
+ /**
958
+ * Check if a module specifier matches explicit external patterns
959
+ * @param moduleSpecifier - The module specifier to check
960
+ * @returns True if the module should be treated as external
961
+ */
962
+ isExternal(moduleSpecifier) {
963
+ return this.matchesPattern(moduleSpecifier, this.options.external);
964
+ }
965
+ /**
966
+ * Resolve a module import using TypeScript's resolution algorithm with path mapping support
967
+ * For bundles with resolve enabled, also loads declaration files from node_modules
968
+ * @param importPath - The module specifier to resolve
969
+ * @param containingFile - The file containing the import
970
+ * @returns Resolved file path or undefined
971
+ */
972
+ resolveModule(importPath, containingFile) {
973
+ const cacheKey = `${importPath}|${containingFile}`;
974
+ if (this.moduleResolutionCache.has(cacheKey)) {
975
+ return this.moduleResolutionCache.get(cacheKey);
976
+ }
977
+ const { resolvedModule } = resolveModuleName(importPath, containingFile, this.options.compilerOptions, this.moduleResolutionHost);
978
+ if (resolvedModule === void 0) {
979
+ return;
980
+ }
981
+ let resolvedFileName = resolvedModule.resolvedFileName;
982
+ if (this.options.compilerOptions.paths && resolvedFileName.match(sourceScriptExtensionExpression)) {
983
+ resolvedFileName = this.sourceToDeclarationPath(resolvedFileName);
984
+ }
985
+ this.moduleResolutionCache.set(cacheKey, resolvedFileName);
986
+ return resolvedFileName;
987
+ }
988
+ /**
989
+ * Build a dependency graph of all modules starting from entry point
990
+ * @param entryPoint - The entry point file path
991
+ * @returns Map of file paths to module information with bundled specifiers tracked
992
+ */
993
+ buildModuleGraph(entryPoint) {
994
+ const modules = /* @__PURE__ */ new Map();
995
+ const visited = /* @__PURE__ */ new Set();
996
+ const bundledSpecifiers = /* @__PURE__ */ new Map();
997
+ const visit = (path) => {
998
+ path = sys.resolvePath(path);
999
+ if (visited.has(path)) {
1000
+ return;
1001
+ }
1002
+ visited.add(path);
1003
+ const cached = this.declarationFiles.get(path) ?? this.externalDeclarationFiles.get(path);
1004
+ if (cached === void 0) {
1005
+ return;
1006
+ }
1007
+ const { code, typeReferences, fileReferences } = cached;
1008
+ const sourceFile = createSourceFile(path, code, ScriptTarget.Latest, true);
1009
+ const identifiers = this.collectIdentifiers(sourceFile.statements, sourceFile);
1010
+ const module = { path, code, imports: /* @__PURE__ */ new Set(), typeReferences: new Set(typeReferences), fileReferences: new Set(fileReferences), sourceFile, identifiers };
1011
+ const bundledSpecs = [];
1012
+ for (const specifier of this.extractImports(sourceFile)) {
1013
+ if (this.isExternal(specifier)) {
1014
+ continue;
1015
+ }
1016
+ const resolvedPath = this.resolveModule(specifier, path);
1017
+ if (resolvedPath?.includes(nodeModules) && !this.matchesPattern(specifier, this.options.noExternal)) {
1018
+ continue;
1019
+ }
1020
+ if (resolvedPath && (this.declarationFiles.has(resolvedPath) || this.externalDeclarationFiles.has(resolvedPath))) {
1021
+ module.imports.add(resolvedPath);
1022
+ bundledSpecs.push(specifier);
1023
+ visit(resolvedPath);
1024
+ }
1025
+ }
1026
+ modules.set(path, module);
1027
+ bundledSpecifiers.set(path, bundledSpecs);
1028
+ };
1029
+ visit(entryPoint);
1030
+ return { modules, bundledSpecifiers };
1031
+ }
1032
+ /**
1033
+ * Topological sort of modules to ensure dependencies come before dependents
1034
+ * @param modules - Map of all modules
1035
+ * @param entryPoint - Starting point for sorting
1036
+ * @returns Array of modules in dependency order
1037
+ */
1038
+ sortModules(modules, entryPoint) {
1039
+ const sorted = [];
1040
+ const visited = /* @__PURE__ */ new Set();
1041
+ const visiting = /* @__PURE__ */ new Set();
1042
+ const visitStack = [];
1043
+ const visit = (path) => {
1044
+ if (visited.has(path)) {
1045
+ return;
1046
+ }
1047
+ if (visiting.has(path)) {
1048
+ const cyclePath = [...visitStack.slice(visitStack.indexOf(path)), path].map((p) => Paths.relative(this.options.currentDirectory, p)).join(" -> ");
1049
+ Logger.warn(`Circular dependency detected: ${cyclePath}`);
1050
+ return;
1051
+ }
1052
+ visiting.add(path);
1053
+ visitStack.push(path);
1054
+ const module = modules.get(path);
1055
+ if (!module) {
1056
+ visiting.delete(path);
1057
+ visitStack.pop();
1058
+ return;
1059
+ }
1060
+ for (const importPath of module.imports) {
1061
+ visit(importPath);
1062
+ }
1063
+ visiting.delete(path);
1064
+ visitStack.pop();
1065
+ visited.add(path);
1066
+ sorted.push(module);
1067
+ };
1068
+ visit(entryPoint);
1069
+ return sorted;
1070
+ }
1071
+ /**
1072
+ * Recursively collect type and value identifiers from AST statements
1073
+ * This is more robust and performant than regex matching
1074
+ * @param statements - AST statements to analyze
1075
+ * @param sourceFile - Optional source file for caching results
1076
+ * @returns Sets of type and value identifiers
1077
+ */
1078
+ collectIdentifiers(statements, sourceFile) {
1079
+ let result;
1080
+ if (sourceFile) {
1081
+ result = this.identifierCache.get(sourceFile);
1082
+ if (result) {
1083
+ return result;
1084
+ }
1085
+ }
1086
+ const types = /* @__PURE__ */ new Set();
1087
+ const values = /* @__PURE__ */ new Set();
1088
+ const collectNestedIdentifiers = (subStatements) => {
1089
+ const { types: subTypes, values: subValues } = this.collectIdentifiers(subStatements);
1090
+ for (const type2 of subTypes) {
1091
+ types.add(type2);
1092
+ }
1093
+ for (const value of subValues) {
1094
+ values.add(value);
1095
+ }
1096
+ };
1097
+ for (const statement of statements) {
1098
+ if (isImportDeclaration2(statement)) {
1099
+ continue;
1100
+ }
1101
+ if (isInterfaceDeclaration2(statement) || isTypeAliasDeclaration2(statement)) {
1102
+ types.add(statement.name.text);
1103
+ } else if (isEnumDeclaration2(statement) || isFunctionDeclaration2(statement) || isClassDeclaration2(statement)) {
1104
+ if (statement.name) {
1105
+ values.add(statement.name.text);
1106
+ }
1107
+ } else if (isVariableStatement2(statement)) {
1108
+ for (const { name } of statement.declarationList.declarations) {
1109
+ if (isIdentifier2(name)) {
1110
+ values.add(name.text);
1111
+ }
1112
+ }
1113
+ } else if (isModuleDeclaration2(statement)) {
1114
+ if (statement.name && isIdentifier2(statement.name)) {
1115
+ values.add(statement.name.text);
1116
+ }
1117
+ collectNestedIdentifiers(statement.getChildren());
1118
+ }
1119
+ }
1120
+ result = { types, values };
1121
+ if (sourceFile) {
1122
+ this.identifierCache.set(sourceFile, result);
1123
+ }
1124
+ return result;
1125
+ }
1126
+ /**
1127
+ * Remove import/export statements from code, but preserve external imports
1128
+ * Fully AST-based approach using magic-string for efficient code manipulation
1129
+ * @param code - Declaration file content
1130
+ * @param sourceFile - Parsed source file AST (required to avoid re-parsing)
1131
+ * @param identifiers - Pre-computed type and value identifiers (to avoid re-computation)
1132
+ * @param bundledImportPaths - Array of resolved file paths that were bundled (to exclude from external imports)
1133
+ * @param renameMap - Map of renamed identifiers (name:path -> newName)
1134
+ * @param modulePath - Path of current module for looking up renames
1135
+ * @returns Object with processed code, collected external imports, and exported names (separated by type/value)
1136
+ */
1137
+ stripImportsExports(code, sourceFile, identifiers, bundledImportPaths, renameMap, modulePath) {
1138
+ const externalImports = [];
1139
+ const typeExports = [];
1140
+ const valueExports = [];
1141
+ const { types: typeIdentifiers, values: valueIdentifiers } = identifiers;
1142
+ const magic = new MagicString2(code);
1143
+ const moduleRenames = /* @__PURE__ */ new Map();
1144
+ const exportsMapper = (name) => moduleRenames.get(name) ?? name;
1145
+ for (const name of [...typeIdentifiers, ...valueIdentifiers]) {
1146
+ const renamed = renameMap.get(`${name}:${modulePath}`);
1147
+ if (renamed) {
1148
+ moduleRenames.set(name, renamed);
1149
+ }
1150
+ }
1151
+ const bundledNamespaceAliases = /* @__PURE__ */ new Set();
1152
+ for (const statement of sourceFile.statements) {
1153
+ if (isImportDeclaration2(statement)) {
1154
+ const moduleSpecifier = statement.moduleSpecifier.text;
1155
+ if (this.isExternal(moduleSpecifier) || !bundledImportPaths.includes(moduleSpecifier)) {
1156
+ externalImports.push(code.substring(statement.pos, statement.end).trim());
1157
+ } else if (statement.importClause?.namedBindings && isNamespaceImport(statement.importClause.namedBindings)) {
1158
+ bundledNamespaceAliases.add(statement.importClause.namedBindings.name.text);
1159
+ }
1160
+ magic.remove(statement.pos, statement.end);
1161
+ } else if (isExportDeclaration2(statement)) {
1162
+ if (statement.moduleSpecifier) {
1163
+ magic.remove(statement.pos, statement.end);
1164
+ continue;
1165
+ }
1166
+ if (statement.exportClause && isNamedExports2(statement.exportClause)) {
1167
+ if (statement.exportClause.elements.length > 0) {
1168
+ for (const { name, propertyName } of statement.exportClause.elements) {
1169
+ const localName = propertyName?.text ?? name.text;
1170
+ if (valueIdentifiers.has(localName)) {
1171
+ valueExports.push(localName);
1172
+ } else if (typeIdentifiers.has(localName)) {
1173
+ typeExports.push(localName);
1174
+ } else {
1175
+ valueExports.push(localName);
1176
+ }
1177
+ }
1178
+ magic.remove(statement.pos, statement.end);
1179
+ }
1180
+ }
1181
+ } else if (isExportAssignment(statement)) {
1182
+ magic.remove(statement.pos, statement.end);
1183
+ }
1184
+ }
1185
+ if (moduleRenames.size > 0) {
1186
+ const visit = (node) => {
1187
+ if (isIdentifier2(node)) {
1188
+ const renamed = moduleRenames.get(node.text);
1189
+ if (renamed) {
1190
+ magic.overwrite(node.getStart(), node.end, renamed);
1191
+ }
1192
+ }
1193
+ forEachChild2(node, visit);
1194
+ };
1195
+ for (const statement of sourceFile.statements) {
1196
+ if (!isImportDeclaration2(statement) && !isExportDeclaration2(statement) && !isExportAssignment(statement)) {
1197
+ visit(statement);
1198
+ }
1199
+ }
1200
+ }
1201
+ if (bundledNamespaceAliases.size > 0) {
1202
+ const visitQualified = (node) => {
1203
+ if (isQualifiedName(node) && isIdentifier2(node.left) && bundledNamespaceAliases.has(node.left.text)) {
1204
+ magic.remove(node.left.getStart(), node.right.getStart());
1205
+ }
1206
+ forEachChild2(node, visitQualified);
1207
+ };
1208
+ forEachChild2(sourceFile, visitQualified);
1209
+ }
1210
+ const finalValueExports = [...new Set(valueExports.map(exportsMapper))];
1211
+ const valueExportsSet = new Set(finalValueExports);
1212
+ const finalTypeExports = [...new Set(typeExports.map(exportsMapper).filter((t) => !valueExportsSet.has(t)))];
1213
+ return { code: magic.toString(), externalImports, typeExports: finalTypeExports, valueExports: finalValueExports };
1214
+ }
1215
+ /**
1216
+ * Combine modules into a single output string
1217
+ * @param sortedModules - Modules in dependency order
1218
+ * @param bundledSpecifiers - Map of module paths to their bundled import specifiers
1219
+ * @returns Object containing combined code, all exported identifiers, and all declarations from bundled modules
1220
+ */
1221
+ combineModules(sortedModules, bundledSpecifiers) {
1222
+ const allTypeReferences = [];
1223
+ const allFileReferences = [];
1224
+ const allExternalImports = [];
1225
+ const allTypeExports = [];
1226
+ const allValueExports = [];
1227
+ const codeBlocks = [];
1228
+ const allDeclarations = /* @__PURE__ */ new Set();
1229
+ const declarationSources = /* @__PURE__ */ new Map();
1230
+ const renameMap = /* @__PURE__ */ new Map();
1231
+ for (const { path, identifiers } of sortedModules) {
1232
+ for (const name of identifiers.types) {
1233
+ if (!declarationSources.has(name)) {
1234
+ declarationSources.set(name, /* @__PURE__ */ new Set());
1235
+ }
1236
+ declarationSources.get(name).add(path);
1237
+ }
1238
+ for (const name of identifiers.values) {
1239
+ if (!declarationSources.has(name)) {
1240
+ declarationSources.set(name, /* @__PURE__ */ new Set());
1241
+ }
1242
+ declarationSources.get(name).add(path);
1243
+ }
1244
+ }
1245
+ for (const [name, sourcesSet] of declarationSources) {
1246
+ if (sourcesSet.size > 1) {
1247
+ const sources = Array.from(sourcesSet);
1248
+ let suffix = 1;
1249
+ for (const modulePath of sources.slice(1)) {
1250
+ let candidate = `${name}$${suffix}`;
1251
+ while (declarationSources.has(candidate)) {
1252
+ candidate = `${name}$${++suffix}`;
1253
+ }
1254
+ renameMap.set(`${name}:${modulePath}`, candidate);
1255
+ suffix++;
1256
+ }
1257
+ }
1258
+ }
1259
+ for (const { path, typeReferences, fileReferences, sourceFile, code, identifiers } of sortedModules) {
1260
+ allTypeReferences.push(...typeReferences);
1261
+ allFileReferences.push(...fileReferences);
1262
+ const bundledForThisModule = bundledSpecifiers.get(path) || [];
1263
+ const { code: strippedCode, externalImports, typeExports, valueExports } = this.stripImportsExports(code, sourceFile, identifiers, bundledForThisModule, renameMap, path);
1264
+ allExternalImports.push(...externalImports);
1265
+ if (!path.includes(nodeModules)) {
1266
+ allValueExports.push(...valueExports);
1267
+ allTypeExports.push(...typeExports);
1268
+ for (const name of identifiers.types) {
1269
+ allDeclarations.add(name);
1270
+ }
1271
+ for (const name of identifiers.values) {
1272
+ allDeclarations.add(name);
1273
+ }
1274
+ }
1275
+ if (strippedCode.trim().length > 0) {
1276
+ codeBlocks.push(strippedCode.trim());
1277
+ }
1278
+ }
1279
+ const uniqueTypeReferences = [...new Set(allTypeReferences)];
1280
+ const uniqueFileReferences = [...new Set(allFileReferences)];
1281
+ const mergedExternalImports = mergeImports(allExternalImports);
1282
+ const finalValueExports = [...new Set(allValueExports)];
1283
+ const finalValueExportsSet = new Set(finalValueExports);
1284
+ const finalTypeExports = [...new Set(allTypeExports.filter((typeExport) => !finalValueExportsSet.has(typeExport)))];
1285
+ const outputParts = [];
1286
+ if (uniqueFileReferences.length > 0) {
1287
+ outputParts.push(...uniqueFileReferences.map((ref) => `/// <reference path="${ref}" />`), "");
1288
+ }
1289
+ if (uniqueTypeReferences.length > 0) {
1290
+ outputParts.push(...uniqueTypeReferences.map((ref) => `/// <reference types="${ref}" />`), "");
1291
+ }
1292
+ if (mergedExternalImports.length > 0) {
1293
+ outputParts.push(...mergedExternalImports, "");
1294
+ }
1295
+ outputParts.push(codeBlocks.join(newLine + newLine));
1296
+ if (finalTypeExports.length > 0 || finalValueExports.length > 0) {
1297
+ outputParts.push("");
1298
+ if (finalValueExports.length > 0) {
1299
+ outputParts.push(`export { ${finalValueExports.sort().join(", ")} };`);
1300
+ }
1301
+ if (finalTypeExports.length > 0) {
1302
+ outputParts.push(`export type { ${finalTypeExports.sort().join(", ")} };`);
1303
+ }
1304
+ }
1305
+ return { code: outputParts.join(newLine), exports: [...finalTypeExports, ...finalValueExports], allDeclarations };
1306
+ }
1307
+ /**
1308
+ * Extract exported names from a processed source file
1309
+ * @param processedSourceFile - The processed source file
1310
+ * @returns Array of exported names
1311
+ */
1312
+ getModuleExports(processedSourceFile) {
1313
+ const exports = [];
1314
+ for (const statement of processedSourceFile.statements) {
1315
+ if (isExportDeclaration2(statement) && statement.exportClause && isNamedExports2(statement.exportClause)) {
1316
+ for (const element of statement.exportClause.elements) {
1317
+ exports.push(element.name.text);
1318
+ }
1319
+ }
1320
+ }
1321
+ return exports;
1322
+ }
1323
+ /**
1324
+ * Main bundling orchestration method
1325
+ * @param entryPoint - The entry point file path
1326
+ * @returns The bundled declaration file content
1327
+ */
1328
+ bundle(entryPoint) {
1329
+ const dtsEntryPoint = this.resolveEntryPoint(entryPoint, this.options.compilerOptions);
1330
+ const { modules, bundledSpecifiers } = this.buildModuleGraph(dtsEntryPoint);
1331
+ const { code } = this.combineModules(this.sortModules(modules, dtsEntryPoint), bundledSpecifiers);
1332
+ return DeclarationProcessor.postProcess(createSourceFile(dtsEntryPoint, code, ScriptTarget.Latest, true));
1333
+ }
1334
+ /**
1335
+ * Resolve entry point from source path to declaration path
1336
+ * @param entryPoint - The entry point file path
1337
+ * @param compilerOptions - Minimal compiler options with outDir and rootDir
1338
+ * @returns Resolved declaration entry point path
1339
+ */
1340
+ resolveEntryPoint(entryPoint, compilerOptions) {
1341
+ const dtsEntryPoint = sys.resolvePath(entryPoint.endsWith(FileExtension.DTS) ? entryPoint : this.sourceToDeclarationPath(entryPoint));
1342
+ if (!this.declarationFiles.has(dtsEntryPoint)) {
1343
+ const availableFiles = Array.from(this.declarationFiles.keys());
1344
+ const entryPointFilename = basename(entryPoint);
1345
+ const similarFiles = availableFiles.filter((filePath) => filePath.includes(entryPointFilename));
1346
+ throw new BundleError(
1347
+ `Entry point declaration file not found: ${dtsEntryPoint || "unknown"}
1348
+ Original entry: ${entryPoint}
1349
+ Compiler options: outDir=${compilerOptions.outDir || "dist"}, rootDir=${compilerOptions.rootDir || "not set"}
1350
+ Similar files found:
1351
+ ${similarFiles.map((f) => ` - ${f}`).join("\n")}
1352
+ Total available files: ${availableFiles.length}`
1353
+ );
1354
+ }
1355
+ return dtsEntryPoint;
1356
+ }
1357
+ };
1358
+ async function bundleDeclarations(options) {
1359
+ await mkdir2(options.compilerOptions.outDir, defaultDirOptions);
1360
+ const dtsBundler = new DeclarationBundler(options);
1361
+ const bundleTasks = Object.entries(options.entryPoints).map(async ([entryName, entryPoint]) => {
1362
+ const outPath = Paths.join(options.compilerOptions.outDir, `${entryName}.d.ts`);
1363
+ const content = dtsBundler.bundle(entryPoint);
1364
+ await writeFile2(outPath, content, Encoding.utf8);
1365
+ return { path: Paths.relative(options.currentDirectory, outPath), size: content.length };
1366
+ });
1367
+ const results = await Promise.all(bundleTasks);
1368
+ dtsBundler.clearExternalFiles();
1369
+ return results;
1370
+ }
1371
+
1372
+ // src/plugins/output.ts
1373
+ import { extname } from "node:path";
1374
+ var FileMode = { READ_WRITE: 438, READ_WRITE_EXECUTE: 493 };
1375
+ async function fileMapper({ path, contents }) {
1376
+ const mode = extname(path) === FileExtension.JS && contents[0] === 35 && contents[1] === 33 ? FileMode.READ_WRITE_EXECUTE : FileMode.READ_WRITE;
1377
+ return Files.write(path, contents, { mode });
1378
+ }
1379
+ var outputPlugin = () => {
1380
+ return {
1381
+ name: "esbuild:output-plugin",
1382
+ /**
1383
+ * Configures the esbuild build instance to write output files to disk
1384
+ * @param build The esbuild build instance
1385
+ */
1386
+ setup(build) {
1387
+ build.onEnd(async ({ outputFiles }) => void await Promise.all(outputFiles.map(fileMapper)));
1388
+ }
1389
+ };
1390
+ };
1391
+
1392
+ // src/plugins/external-modules.ts
1393
+ var match = (id, patterns) => {
1394
+ return patterns.some((pattern) => pattern instanceof RegExp ? pattern.test(id) : id === pattern || id.startsWith(`${pattern}/`));
1395
+ };
1396
+ var externalModulesPlugin = ({ dependencies = [], noExternal = [] }) => {
1397
+ return {
1398
+ name: "esbuild:external-modules",
1399
+ /**
1400
+ * Configure the plugin to handle external modules
1401
+ * @param build The esbuild build instance
1402
+ */
1403
+ setup(build) {
1404
+ const external = true;
1405
+ build.onResolve({ filter: /.*/ }, ({ path }) => {
1406
+ switch (true) {
1407
+ case match(path, noExternal):
1408
+ return;
1409
+ case match(path, dependencies):
1410
+ return { external };
1411
+ case !Paths.isPath(path):
1412
+ return { path, external };
1413
+ default:
1414
+ return;
1415
+ }
1416
+ });
1417
+ }
1418
+ };
1419
+ };
1420
+
1421
+ // src/process-manager.ts
1422
+ var ProcessEvent = {
1423
+ exit: "exit",
1424
+ sigint: "SIGINT",
1425
+ uncaughtException: "uncaughtException"
1426
+ };
1427
+ var ProcessManager = class {
1428
+ hasHandledExit = false;
1429
+ closeableClasses = [];
1430
+ constructor() {
1431
+ process.addListener(ProcessEvent.exit, this.handleExit);
1432
+ process.addListener(ProcessEvent.sigint, this.consoleExit);
1433
+ process.addListener(ProcessEvent.uncaughtException, this.handleUncaughtException);
1434
+ }
1435
+ /**
1436
+ * Adds a closeable class to be closed on exit.
1437
+ * @param closeable The closeable class to add.
1438
+ */
1439
+ addCloseable(closeable) {
1440
+ this.closeableClasses.push(closeable);
1441
+ }
1442
+ /** Closes the process manager and removes all listeners */
1443
+ close() {
1444
+ this.closeableClasses.length = 0;
1445
+ process.removeListener(ProcessEvent.exit, this.handleExit);
1446
+ process.removeListener(ProcessEvent.sigint, this.consoleExit);
1447
+ process.removeListener(ProcessEvent.uncaughtException, this.handleUncaughtException);
1448
+ }
1449
+ /** Handles normal process exit */
1450
+ handleExit = () => {
1451
+ if (this.hasHandledExit) {
1452
+ return;
1453
+ }
1454
+ for (const closeable of this.closeableClasses) {
1455
+ closeable.close();
1456
+ }
1457
+ this.close();
1458
+ };
1459
+ /** Handles console exit (ctrl+c) */
1460
+ consoleExit = () => {
1461
+ Logger.warn("\nProcess terminated by user");
1462
+ this.hasHandledExit = true;
1463
+ for (const closeable of this.closeableClasses) {
1464
+ closeable.close();
1465
+ }
1466
+ this.close();
1467
+ process.exit(130);
1468
+ };
1469
+ /**
1470
+ * Handles uncaught exceptions and exits the process.
1471
+ * @param e The error that was uncaught.
1472
+ */
1473
+ handleUncaughtException = (e) => {
1474
+ Logger.error("Uncaught Exception...", e.stack);
1475
+ process.exit(99);
1476
+ };
1477
+ };
1478
+ var processManager = new ProcessManager();
1479
+
1480
+ // src/decorators/close-on-exit.ts
1481
+ function closeOnExit(value, _context) {
1482
+ return class extends value {
1483
+ /**
1484
+ * Creates an instance and registers it with the process manager.
1485
+ * @param args Arguments to pass to the original constructor.
1486
+ */
1487
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1488
+ constructor(...args) {
1489
+ super(...args);
1490
+ processManager.addCloseable(this);
1491
+ }
1492
+ };
1493
+ }
1494
+
1495
+ // src/decorators/performance-logger.ts
1496
+ import { PerformanceObserver, performance } from "perf_hooks";
1497
+ var type = "measure";
1498
+ var _PerformanceLogger_decorators, _init;
1499
+ _PerformanceLogger_decorators = [closeOnExit];
1500
+ var _PerformanceLogger = class _PerformanceLogger {
1501
+ performanceObserver;
1502
+ constructor() {
1503
+ this.performanceObserver = new PerformanceObserver((list) => {
1504
+ for (const { name, duration, detail: { message, result = [] } } of list.getEntriesByType(type).reverse()) {
1505
+ if (message === "Build") {
1506
+ Logger.separator();
1507
+ if (process.exitCode) {
1508
+ Logger.error(`\u2717 Build failed in ${TextFormat.cyan(_PerformanceLogger.formatDuration(duration))}
1509
+ `);
1510
+ } else {
1511
+ Logger.step(`Completed in ${TextFormat.cyan(_PerformanceLogger.formatDuration(duration))}
1512
+ `);
1513
+ }
1514
+ } else {
1515
+ Logger.step(`${message} ${TextFormat.dim(`(${_PerformanceLogger.formatDuration(duration)})`)}`);
1516
+ if (result.length > 0) {
1517
+ Logger.success("", ...result);
1518
+ }
1519
+ }
1520
+ performance.clearResourceTimings(name);
1521
+ }
1522
+ });
1523
+ this.performanceObserver.observe({ type });
1524
+ }
1525
+ /**
1526
+ * Measures the performance of a method and logs the result.
1527
+ * @param message - The message to log with the performance measurement.
1528
+ * @param logResult - Whether to log the result of the method.
1529
+ * @returns A Stage 3 method decorator that measures the performance of the method it decorates.
1530
+ */
1531
+ measure(message, logResult = false) {
1532
+ const _measure = (propertyKey, result, options) => {
1533
+ if (logResult) {
1534
+ options.detail.result = result;
1535
+ }
1536
+ ({ startTime: options.end } = performance.mark(propertyKey));
1537
+ performance.measure(propertyKey, options);
1538
+ return result;
1539
+ };
1540
+ return function(targetMethod, context) {
1541
+ const propertyKey = String(context.name);
1542
+ return function(...args) {
1543
+ const options = { start: performance.mark(propertyKey).startTime, detail: { message } };
1544
+ const result = targetMethod.apply(this, args);
1545
+ return result instanceof Promise ? result.then((r) => _measure(propertyKey, r, options)) : _measure(propertyKey, result, options);
1546
+ };
1547
+ };
1548
+ }
1549
+ /**
1550
+ * Closes the performance logger.
1551
+ */
1552
+ close() {
1553
+ this.performanceObserver.disconnect();
1554
+ }
1555
+ /**
1556
+ * Formats the duration into a human-readable string.
1557
+ * @param duration - The duration to format.
1558
+ * @returns The formatted duration string.
1559
+ */
1560
+ static formatDuration(duration) {
1561
+ const minutes = ~~(duration / 6e4) % 60;
1562
+ const seconds = ~~(duration / 1e3) % 60;
1563
+ const ms = ~~duration % 1e3;
1564
+ if (minutes > 0) {
1565
+ return `${minutes}m${seconds}s${ms}ms`;
1566
+ }
1567
+ if (seconds > 0) {
1568
+ return `${seconds}s${ms}ms`;
1569
+ }
1570
+ return `${ms}ms`;
1571
+ }
1572
+ };
1573
+ _init = __decoratorStart(null);
1574
+ _PerformanceLogger = __decorateElement(_init, 0, "PerformanceLogger", _PerformanceLogger_decorators, _PerformanceLogger);
1575
+ __runInitializers(_init, 1, _PerformanceLogger);
1576
+ var PerformanceLogger = _PerformanceLogger;
1577
+ var measure = new PerformanceLogger().measure;
1578
+
1579
+ // src/decorators/debounce.ts
1580
+ var _DebounceManager_decorators, _init2;
1581
+ _DebounceManager_decorators = [closeOnExit];
1582
+ var _DebounceManager = class _DebounceManager {
1583
+ static timers = /* @__PURE__ */ new Set();
1584
+ /**
1585
+ * Creates a debounced version of a function.
1586
+ * @param func - The function to debounce.
1587
+ * @param wait - The number of milliseconds to wait before invoking the function.
1588
+ * @returns A debounced version of the function that returns a Promise.
1589
+ */
1590
+ debounce(func, wait) {
1591
+ let timeoutId;
1592
+ let pendingResolve;
1593
+ return function(...args) {
1594
+ return new Promise((resolve, reject) => {
1595
+ if (timeoutId) {
1596
+ clearTimeout(timeoutId);
1597
+ _DebounceManager.timers.delete(timeoutId);
1598
+ }
1599
+ if (pendingResolve) {
1600
+ pendingResolve(void 0);
1601
+ }
1602
+ pendingResolve = resolve;
1603
+ timeoutId = setTimeout(() => {
1604
+ if (timeoutId) {
1605
+ _DebounceManager.timers.delete(timeoutId);
1606
+ }
1607
+ try {
1608
+ resolve(func.apply(this, args));
1609
+ } catch (error) {
1610
+ reject(castError(error));
1611
+ } finally {
1612
+ pendingResolve = void 0;
1613
+ timeoutId = void 0;
1614
+ }
1615
+ }, wait);
1616
+ _DebounceManager.timers.add(timeoutId);
1617
+ });
1618
+ };
1619
+ }
1620
+ /** Closes the manager by clearing all active timers. */
1621
+ close() {
1622
+ for (const timer of _DebounceManager.timers) {
1623
+ clearTimeout(timer);
1624
+ }
1625
+ _DebounceManager.timers.clear();
1626
+ }
1627
+ };
1628
+ _init2 = __decoratorStart(null);
1629
+ _DebounceManager = __decorateElement(_init2, 0, "DebounceManager", _DebounceManager_decorators, _DebounceManager);
1630
+ __runInitializers(_init2, 1, _DebounceManager);
1631
+ var DebounceManager = _DebounceManager;
1632
+ var debounceManager = new DebounceManager();
1633
+ function debounce(wait) {
1634
+ if (wait < 0) {
1635
+ throw new Error("\u{1F6A8} wait must be non-negative.");
1636
+ }
1637
+ return function(targetMethod, context) {
1638
+ context.addInitializer(function() {
1639
+ Object.defineProperty(this, context.name, { writable: true, configurable: true, value: debounceManager.debounce(targetMethod.bind(this), wait) });
1640
+ });
1641
+ return targetMethod;
1642
+ };
1643
+ }
1644
+
1645
+ // src/file-manager.ts
1646
+ import { sys as sys2, createSourceFile as createSourceFile2, ScriptTarget as ScriptTarget2 } from "typescript";
1647
+ var FileManager = class {
1648
+ hasEmittedFiles = false;
1649
+ declarationFiles = /* @__PURE__ */ new Map();
1650
+ cache;
1651
+ /**
1652
+ * Creates a new file manager.
1653
+ * @param buildCache - Optional build cache for incremental builds
1654
+ */
1655
+ constructor(buildCache) {
1656
+ this.cache = buildCache;
1657
+ }
1658
+ /**
1659
+ * Prepares the manager for a new TypeScript emit operation.
1660
+ * For incremental builds, restores cached (pre-processed) declarations before emit.
1661
+ * For non-incremental builds, clears all stored files.
1662
+ *
1663
+ * @example
1664
+ * ```typescript
1665
+ * await manager.initialize();
1666
+ * program.emit(undefined, manager.fileWriter, undefined, true);
1667
+ * await manager.finalize();
1668
+ * ```
1669
+ */
1670
+ async initialize() {
1671
+ this.hasEmittedFiles = false;
1672
+ if (this.cache) {
1673
+ await this.cache.restore(this.declarationFiles);
1674
+ } else {
1675
+ this.declarationFiles.clear();
1676
+ }
1677
+ }
1678
+ /**
1679
+ * Finalizes the emit operation by saving the cache if files were emitted.
1680
+ * Must be called after program.emit() to ensure cache is properly saved.
1681
+ *
1682
+ * @returns True if files were emitted (or non-incremental build), false if no changes detected
1683
+ * @example
1684
+ * ```typescript
1685
+ * await manager.initialize();
1686
+ * program.emit(undefined, manager.fileWriter, undefined, true);
1687
+ * const hasEmitted = await manager.finalize();
1688
+ * if (hasEmitted) { // Continue with build }
1689
+ * ```
1690
+ */
1691
+ async finalize() {
1692
+ if (this.cache && this.hasEmittedFiles) {
1693
+ await this.cache.save(this.declarationFiles);
1694
+ }
1695
+ return this.cache === void 0 || this.hasEmittedFiles;
1696
+ }
1697
+ /**
1698
+ * Retrieves all stored declaration files.
1699
+ * Files are already pre-processed and ready for bundling or writing to disk.
1700
+ * This is a pure getter with no side effects.
1701
+ *
1702
+ * @returns A read-only map of file paths to their pre-processed content with extracted references
1703
+ */
1704
+ getDeclarationFiles() {
1705
+ return this.declarationFiles;
1706
+ }
1707
+ /**
1708
+ * Writes all stored declaration files to disk.
1709
+ * Files are already pre-processed, so this just writes them directly.
1710
+ *
1711
+ * @param projectDirectory - Project root for calculating relative paths
1712
+ * @returns Array of written file metadata
1713
+ */
1714
+ async writeFiles(projectDirectory) {
1715
+ if (this.declarationFiles.size === 0) {
1716
+ return [];
1717
+ }
1718
+ const writeTasks = [];
1719
+ for (const [filePath, { code }] of this.declarationFiles) {
1720
+ writeTasks.push(this.writeFile(projectDirectory, filePath, code));
1721
+ }
1722
+ return Promise.all(writeTasks);
1723
+ }
1724
+ /**
1725
+ * Resolves entry points for declaration bundling.
1726
+ * This is a utility method that filters project entry points based on DTS configuration.
1727
+ *
1728
+ * @param projectEntryPoints - All entry points from project configuration
1729
+ * @param dtsEntryPoints - Optional list of entry point names to include for DTS bundling
1730
+ * @returns Filtered entry points for declaration bundling
1731
+ */
1732
+ resolveEntryPoints(projectEntryPoints, dtsEntryPoints) {
1733
+ if (!dtsEntryPoints) {
1734
+ return defaultEntryPoint in projectEntryPoints ? { [defaultEntryPoint]: projectEntryPoints[defaultEntryPoint] } : projectEntryPoints;
1735
+ }
1736
+ const result = {};
1737
+ for (const [name, path] of Object.entries(projectEntryPoints)) {
1738
+ if (dtsEntryPoints.includes(name)) {
1739
+ result[name] = path;
1740
+ }
1741
+ }
1742
+ return result;
1743
+ }
1744
+ /**
1745
+ * Closes the file manager and releases resources.
1746
+ * Clears all stored declaration files.
1747
+ */
1748
+ close() {
1749
+ this.declarationFiles.clear();
1750
+ }
1751
+ /**
1752
+ * Writes a single declaration file to disk.
1753
+ * @param projectDirectory - Project root for calculating relative paths
1754
+ * @param filePath - The full path of the declaration file to write
1755
+ * @param content - The pre-processed content of the declaration file
1756
+ * @returns Metadata of the written file
1757
+ */
1758
+ async writeFile(projectDirectory, filePath, content) {
1759
+ await Files.write(filePath, content);
1760
+ return { path: Paths.relative(projectDirectory, filePath), size: content.length };
1761
+ }
1762
+ /**
1763
+ * Function that intercepts file writes during TypeScript emit.
1764
+ * Declaration files are pre-processed and stored in memory, while .tsbuildinfo is written to disk.
1765
+ * Pre-processing happens immediately so the cache stores ready-to-use declarations.
1766
+ * @param filePath - The path of the file being written
1767
+ * @param text - The content of the file being written
1768
+ */
1769
+ fileWriter = (filePath, text) => {
1770
+ if (this.cache?.isBuildInfoFile(filePath)) {
1771
+ sys2.writeFile(filePath, text);
1772
+ } else {
1773
+ this.declarationFiles.set(filePath, DeclarationProcessor.preProcess(createSourceFile2(filePath, text, ScriptTarget2.Latest, true)));
1774
+ }
1775
+ if (!this.hasEmittedFiles) {
1776
+ this.hasEmittedFiles = true;
1777
+ }
1778
+ };
1779
+ /**
1780
+ * Custom inspection method for better type representation.
1781
+ * @returns The string 'FileManager'
1782
+ * @internal
1783
+ */
1784
+ get [Symbol.toStringTag]() {
1785
+ return "FileManager";
1786
+ }
1787
+ };
1788
+
1789
+ // src/incremental-build-cache.ts
1790
+ import { rmSync } from "node:fs";
1791
+ var IncrementalBuildCache = class {
1792
+ buildInfoPath;
1793
+ cacheDirectoryPath;
1794
+ cacheFilePath;
1795
+ /** Pre-loading promise started in constructor for async cache restoration */
1796
+ cacheLoaded;
1797
+ /** Set to true when invalidate() is called to prevent stale cache from being restored */
1798
+ invalidated = false;
1799
+ /**
1800
+ * Creates a new build cache instance and begins pre-loading the cache asynchronously.
1801
+ * @param projectRoot - Root directory of the project
1802
+ * @param tsBuildInfoFile - Path to the TypeScript build info file
1803
+ */
1804
+ constructor(projectRoot, tsBuildInfoFile) {
1805
+ this.buildInfoPath = Paths.join(projectRoot, tsBuildInfoFile);
1806
+ this.cacheDirectoryPath = Paths.join(projectRoot, cacheDirectory);
1807
+ this.cacheFilePath = Paths.join(this.cacheDirectoryPath, dtsCacheFile);
1808
+ this.cacheLoaded = this.loadCache();
1809
+ }
1810
+ /**
1811
+ * Loads the cache file asynchronously using V8 deserialization.
1812
+ * @returns The cache or undefined if cache doesn't exist, is corrupted, or has incompatible version.
1813
+ */
1814
+ async loadCache() {
1815
+ try {
1816
+ const cache = await Files.readCompressed(this.cacheFilePath);
1817
+ return cache.version === dtsCacheVersion ? cache : void 0;
1818
+ } catch {
1819
+ return void 0;
1820
+ }
1821
+ }
1822
+ /**
1823
+ * Restores cached declaration files into the provided map.
1824
+ * Waits for the pre-load promise started in constructor to complete.
1825
+ * TypeScript's incremental compilation handles staleness - it re-emits only changed files,
1826
+ * which overwrite cached entries. Unchanged files remain valid and skip re-emission.
1827
+ * @param target - The map to populate with cached declarations
1828
+ */
1829
+ async restore(target) {
1830
+ if (this.invalidated) {
1831
+ return;
1832
+ }
1833
+ const cache = await this.cacheLoaded;
1834
+ if (cache === void 0) {
1835
+ return;
1836
+ }
1837
+ for (const [fileName, content] of Object.entries(cache.files)) {
1838
+ target.set(fileName, content);
1839
+ }
1840
+ }
1841
+ /**
1842
+ * Saves declaration files to the compressed cache file with version information.
1843
+ * Uses V8 serialization for faster read performance on subsequent builds.
1844
+ * @param source - The declaration files to cache
1845
+ */
1846
+ async save(source) {
1847
+ await Files.writeCompressed(this.cacheFilePath, { version: dtsCacheVersion, files: Object.fromEntries(source) });
1848
+ }
1849
+ /** Invalidates the build cache by removing the cache directory. */
1850
+ invalidate() {
1851
+ this.invalidated = true;
1852
+ try {
1853
+ rmSync(this.cacheDirectoryPath, defaultCleanOptions);
1854
+ } catch {
1855
+ }
1856
+ }
1857
+ /**
1858
+ * Checks if a file path is the TypeScript build info file.
1859
+ * @param filePath - The file path to check
1860
+ * @returns True if the path matches the build info file
1861
+ */
1862
+ isBuildInfoFile(filePath) {
1863
+ return filePath === this.buildInfoPath;
1864
+ }
1865
+ /**
1866
+ * Custom inspection tag for type.
1867
+ * @returns The string 'IncrementalBuildCache'
1868
+ */
1869
+ get [Symbol.toStringTag]() {
1870
+ return "IncrementalBuildCache";
1871
+ }
1872
+ };
1873
+
1874
+ // src/entry-points.ts
1875
+ var importConditions = ["import", "default"];
1876
+ function stemOf(filePath) {
1877
+ const base = filePath.split("/").at(-1) ?? "";
1878
+ const dot = base.indexOf(".");
1879
+ return dot === -1 ? base : base.slice(0, dot);
1880
+ }
1881
+ var outputToSourceExtension = /* @__PURE__ */ new Map([
1882
+ [".js", ".ts"],
1883
+ [".jsx", ".tsx"],
1884
+ [".d.ts", ".ts"]
1885
+ ]);
1886
+ function unscope(name) {
1887
+ const slash = name.indexOf("/");
1888
+ return slash === -1 ? name : name.slice(slash + 1);
1889
+ }
1890
+ function outputToSourcePath(outputPath, outDir, sourceDir) {
1891
+ const normalizedOutput = outputPath.replace(/^\.\//, "");
1892
+ const normalizedOutDir = outDir.replace(/^\.\//, "").replace(/\/$/, "");
1893
+ if (!normalizedOutput.startsWith(normalizedOutDir + "/") && normalizedOutput !== normalizedOutDir) {
1894
+ return void 0;
1895
+ }
1896
+ const relativePortion = normalizedOutput.slice(normalizedOutDir.length + 1);
1897
+ for (const [outExt, srcExt] of outputToSourceExtension) {
1898
+ if (relativePortion.endsWith(outExt)) {
1899
+ const stem = relativePortion.slice(0, -outExt.length);
1900
+ return `./${sourceDir}/${stem}${srcExt}`;
1901
+ }
1902
+ }
1903
+ return void 0;
1904
+ }
1905
+ function resolveConditionalExport(exportValue) {
1906
+ if (typeof exportValue === "string") {
1907
+ return exportValue;
1908
+ }
1909
+ for (const condition of importConditions) {
1910
+ const value = exportValue[condition];
1911
+ if (typeof value === "string") {
1912
+ return value;
1913
+ }
1914
+ }
1915
+ return void 0;
1916
+ }
1917
+ function subpathToEntryName(subpath, packageName) {
1918
+ if (subpath === ".") {
1919
+ return packageName !== void 0 ? unscope(packageName) : "index";
1920
+ }
1921
+ const withoutPrefix = subpath.replace(/^\.\//, "");
1922
+ const lastSegment = withoutPrefix.lastIndexOf("/");
1923
+ return lastSegment === -1 ? withoutPrefix : withoutPrefix.slice(lastSegment + 1);
1924
+ }
1925
+ function inferEntryPoints(packageJson, outDir, sourceDir = "src") {
1926
+ const entryPoints = {};
1927
+ if (packageJson.exports !== void 0) {
1928
+ if (typeof packageJson.exports === "string") {
1929
+ const sourcePath = outputToSourcePath(packageJson.exports, outDir, sourceDir);
1930
+ if (sourcePath) {
1931
+ entryPoints[stemOf(sourcePath)] = sourcePath;
1932
+ }
1933
+ } else {
1934
+ for (const [subpath, exportValue] of Object.entries(packageJson.exports)) {
1935
+ if (subpath.includes("*")) {
1936
+ continue;
1937
+ }
1938
+ const outputPath = resolveConditionalExport(exportValue);
1939
+ if (outputPath === void 0) {
1940
+ continue;
1941
+ }
1942
+ const sourcePath = outputToSourcePath(outputPath, outDir, sourceDir);
1943
+ if (sourcePath) {
1944
+ entryPoints[subpath === "." ? stemOf(sourcePath) : subpathToEntryName(subpath, packageJson.name)] = sourcePath;
1945
+ }
1946
+ }
1947
+ }
1948
+ }
1949
+ if (packageJson.bin !== void 0) {
1950
+ const binEntries = typeof packageJson.bin === "string" ? { [packageJson.name ?? "cli"]: packageJson.bin } : packageJson.bin;
1951
+ for (const [name, outputPath] of Object.entries(binEntries)) {
1952
+ if (entryPoints[name] === void 0) {
1953
+ const sourcePath = outputToSourcePath(outputPath, outDir, sourceDir);
1954
+ if (sourcePath) {
1955
+ entryPoints[name] = sourcePath;
1956
+ }
1957
+ }
1958
+ }
1959
+ }
1960
+ if (Object.keys(entryPoints).length === 0) {
1961
+ const legacyPath = packageJson.module ?? packageJson.main;
1962
+ if (legacyPath !== void 0) {
1963
+ const sourcePath = outputToSourcePath(legacyPath, outDir, sourceDir);
1964
+ if (sourcePath) {
1965
+ entryPoints["index"] = sourcePath;
1966
+ }
1967
+ }
1968
+ }
1969
+ return Object.keys(entryPoints).length > 0 ? entryPoints : void 0;
1970
+ }
1971
+
1972
+ // src/type-script-project.ts
1973
+ import { build as esbuild, formatMessages } from "esbuild";
1974
+ import { sys as sys3, createIncrementalProgram, formatDiagnostics, formatDiagnosticsWithColorAndContext, parseJsonConfigFileContent, readConfigFile, findConfigFile } from "typescript";
1975
+ var globCharacters = /[*?\\[\]!].*$/;
1976
+ var domPredicate = (lib) => lib.toUpperCase() === "DOM";
1977
+ var diagnosticsHost = { getNewLine: () => sys3.newLine, getCurrentDirectory: sys3.getCurrentDirectory, getCanonicalFileName: (fileName) => fileName };
1978
+ var _triggerRebuild_dec, _processDeclarations_dec, _transpile_dec, _typeCheck_dec, _build_dec, _TypeScriptProject_decorators, _init3;
1979
+ _TypeScriptProject_decorators = [closeOnExit], _build_dec = [measure("Build")], _typeCheck_dec = [measure("Type-checking")], _transpile_dec = [measure("Transpile", true)], _processDeclarations_dec = [measure("Process Declarations", true)], _triggerRebuild_dec = [debounce(100)];
1980
+ var _TypeScriptProject = class _TypeScriptProject {
1981
+ /**
1982
+ * Creates a TypeScript project and prepares it for building/bundling.
1983
+ * @param directory - Project root directory (defaults to current working directory)
1984
+ * @param options - Project options to merge with tsconfig.json
1985
+ */
1986
+ constructor(directory = sys3.getCurrentDirectory(), options = {}) {
1987
+ __runInitializers(_init3, 5, this);
1988
+ __publicField(this, "fileWatcher");
1989
+ __publicField(this, "builderProgram");
1990
+ __publicField(this, "directory");
1991
+ __publicField(this, "configuration");
1992
+ __publicField(this, "fileManager");
1993
+ __publicField(this, "buildConfiguration");
1994
+ __publicField(this, "pendingChanges", []);
1995
+ __publicField(this, "buildDependencies", /* @__PURE__ */ new Set());
1996
+ __publicField(this, "dependencyPaths");
1997
+ this.directory = Paths.absolute(directory);
1998
+ this.configuration = _TypeScriptProject.resolveConfiguration(this.directory, options);
1999
+ const { buildCache, rootNames, projectReferences, configFileParsingDiagnostics, tsbuild: { entryPoints, ...tsbuildOptions }, compilerOptions: { target, outDir } } = this.configuration;
2000
+ if (buildCache !== void 0 && options.clearCache) {
2001
+ buildCache.invalidate();
2002
+ }
2003
+ this.fileManager = new FileManager(buildCache);
2004
+ this.builderProgram = createIncrementalProgram({ rootNames, options: this.configuration.compilerOptions, projectReferences, configFileParsingDiagnostics });
2005
+ const entryPointsPromise = this.getEntryPoints(entryPoints);
2006
+ entryPointsPromise.catch(() => {
2007
+ });
2008
+ this.buildConfiguration = { entryPoints: entryPointsPromise, target: toEsTarget(target), outDir, ...tsbuildOptions };
2009
+ }
2010
+ /**
2011
+ * Cleans the output directory
2012
+ * @returns A promise that resolves when the cleaning is complete.
2013
+ */
2014
+ async clean() {
2015
+ return Files.empty(this.buildConfiguration.outDir);
2016
+ }
2017
+ async build() {
2018
+ Logger.header(`\u{1F680} tsbuild v${"1.2.2"}${this.configuration.compilerOptions.incremental ? " [incremental]" : ""}`);
2019
+ try {
2020
+ const processes = [];
2021
+ const filesWereEmitted = await this.typeCheck();
2022
+ if ((filesWereEmitted || this.configuration.tsbuild.force) && !this.configuration.compilerOptions.noEmit) {
2023
+ if (this.configuration.clean) {
2024
+ await this.clean();
2025
+ }
2026
+ if (this.configuration.compilerOptions.declaration) {
2027
+ processes.push(this.processDeclarations());
2028
+ }
2029
+ if (!this.configuration.compilerOptions.emitDeclarationOnly) {
2030
+ processes.push(this.transpile());
2031
+ }
2032
+ }
2033
+ for (const result of await Promise.allSettled(processes)) {
2034
+ if (result.status === "rejected") {
2035
+ this.handleBuildError(result.reason);
2036
+ }
2037
+ }
2038
+ } catch (error) {
2039
+ this.handleBuildError(error);
2040
+ } finally {
2041
+ if (this.buildConfiguration.watch.enabled) {
2042
+ this.buildDependencies.clear();
2043
+ for (const { isDeclarationFile, fileName } of this.builderProgram.getProgram().getSourceFiles()) {
2044
+ if (!isDeclarationFile) {
2045
+ this.buildDependencies.add(Paths.relative(this.directory, fileName));
2046
+ }
2047
+ }
2048
+ if (this.fileWatcher === void 0 || this.fileWatcher.isClosed()) {
2049
+ setImmediate(() => this.watch());
2050
+ }
2051
+ }
2052
+ }
2053
+ }
2054
+ async typeCheck() {
2055
+ await this.fileManager.initialize();
2056
+ const { diagnostics } = this.builderProgram.emit(void 0, this.fileManager.fileWriter, void 0, true);
2057
+ if (diagnostics.length > 0) {
2058
+ _TypeScriptProject.handleTypeErrors("Type-checking failed", diagnostics, this.directory);
2059
+ }
2060
+ return this.fileManager.finalize();
2061
+ }
2062
+ async transpile() {
2063
+ const plugins = [outputPlugin()];
2064
+ if (this.buildConfiguration.noExternal.length > 0) {
2065
+ plugins.push(externalModulesPlugin({ dependencies: await this.getProjectDependencyPaths(), noExternal: this.buildConfiguration.noExternal }));
2066
+ }
2067
+ if (this.configuration.compilerOptions.emitDecoratorMetadata) {
2068
+ try {
2069
+ const { swcDecoratorMetadataPlugin } = await import("./DSHNVGWV.js");
2070
+ plugins.push(swcDecoratorMetadataPlugin);
2071
+ } catch {
2072
+ throw new ConfigurationError("emitDecoratorMetadata is enabled but @swc/core is not installed. Install it with: pnpm add -D @swc/core");
2073
+ }
2074
+ }
2075
+ if (this.buildConfiguration.plugins?.length) {
2076
+ plugins.push(...this.buildConfiguration.plugins);
2077
+ }
2078
+ const define = {};
2079
+ if (this.buildConfiguration.env !== void 0) {
2080
+ for (const [key, value] of Object.entries(this.buildConfiguration.env)) {
2081
+ processEnvExpansionPattern.lastIndex = 0;
2082
+ define[`import.meta.env.${key}`] = Json.serialize(value.replace(processEnvExpansionPattern, (_, envVar) => process.env[envVar] ?? ""));
2083
+ }
2084
+ }
2085
+ try {
2086
+ const { warnings, errors, metafile: { outputs } } = await esbuild({
2087
+ format,
2088
+ plugins,
2089
+ define,
2090
+ write: false,
2091
+ metafile: true,
2092
+ treeShaking: true,
2093
+ logLevel: "warning",
2094
+ tsconfigRaw: {
2095
+ compilerOptions: {
2096
+ alwaysStrict: this.configuration.compilerOptions.alwaysStrict,
2097
+ experimentalDecorators: this.configuration.compilerOptions.experimentalDecorators,
2098
+ jsx: toJsxRenderingMode(this.configuration.compilerOptions.jsx),
2099
+ jsxFactory: this.configuration.compilerOptions.jsxFactory,
2100
+ jsxFragmentFactory: this.configuration.compilerOptions.jsxFragmentFactory,
2101
+ jsxImportSource: this.configuration.compilerOptions.jsxImportSource,
2102
+ paths: this.configuration.compilerOptions.paths,
2103
+ strict: this.configuration.compilerOptions.strict,
2104
+ target: this.buildConfiguration.target,
2105
+ useDefineForClassFields: this.configuration.compilerOptions.useDefineForClassFields,
2106
+ verbatimModuleSyntax: this.configuration.compilerOptions.verbatimModuleSyntax
2107
+ }
2108
+ },
2109
+ entryPoints: await this.buildConfiguration.entryPoints,
2110
+ bundle: this.buildConfiguration.bundle,
2111
+ packages: this.buildConfiguration.packages,
2112
+ platform: this.buildConfiguration.platform,
2113
+ sourcemap: this.buildConfiguration.sourceMap,
2114
+ target: this.buildConfiguration.target,
2115
+ banner: this.buildConfiguration.banner,
2116
+ footer: this.buildConfiguration.footer,
2117
+ outdir: this.buildConfiguration.outDir,
2118
+ splitting: this.buildConfiguration.splitting,
2119
+ chunkNames: "[hash]",
2120
+ minify: this.buildConfiguration.minify,
2121
+ // Force decorator transformation even with ESNext target since Node.js doesn't support decorators yet
2122
+ supported: { decorators: false }
2123
+ });
2124
+ for (const [kind, logEntryType, messages] of [[BuildMessageType.WARNING, Logger.EntryType.Warn, warnings], [BuildMessageType.ERROR, Logger.EntryType.Error, errors]]) {
2125
+ for (const message of await formatMessages(messages, { kind, color: true })) {
2126
+ Logger.log(message, logEntryType);
2127
+ }
2128
+ if (kind === BuildMessageType.ERROR && errors.length > 0) {
2129
+ return [];
2130
+ }
2131
+ }
2132
+ const writtenFiles = [];
2133
+ for (const [outputPath, { bytes }] of Object.entries(outputs)) {
2134
+ writtenFiles.push({ path: outputPath, size: bytes });
2135
+ }
2136
+ return writtenFiles;
2137
+ } catch (error) {
2138
+ Logger.error("Transpile failed", error);
2139
+ throw error;
2140
+ }
2141
+ }
2142
+ /**
2143
+ * Watches for changes in the project files and rebuilds the project when changes are detected.
2144
+ */
2145
+ watch() {
2146
+ const targets = [];
2147
+ for (const path of this.configuration.include ?? [defaultSourceDirectory]) {
2148
+ targets.push(Paths.absolute(this.directory, path.replace(globCharacters, "")));
2149
+ }
2150
+ const rebuild = (event, stats, path, nextPath) => {
2151
+ if (stats?.size === 0 && (event === Watchr.FileEvent.add || event === Watchr.FileEvent.unlink)) {
2152
+ return;
2153
+ }
2154
+ if (this.configuration.compilerOptions.noEmit || this.buildDependencies.has(Paths.relative(this.directory, path))) {
2155
+ this.pendingChanges.push({ event, path, nextPath });
2156
+ void this.triggerRebuild();
2157
+ }
2158
+ };
2159
+ const pathsToIgnore = [...this.configuration.exclude ?? [], ...this.buildConfiguration.watch.ignore ?? []];
2160
+ this.fileWatcher = new Watchr(targets, { ...this.buildConfiguration.watch, ignore: (path) => pathsToIgnore.some((p) => path.lastIndexOf(p) > -1) }, rebuild);
2161
+ Logger.info(`Watching for changes in: ${targets.join(", ")}`);
2162
+ }
2163
+ /** Closes the project and cleans up resources. */
2164
+ close() {
2165
+ this.fileWatcher?.close();
2166
+ this.fileManager.close();
2167
+ this.buildDependencies.clear();
2168
+ this.pendingChanges.length = 0;
2169
+ }
2170
+ async processDeclarations() {
2171
+ if (!this.buildConfiguration.bundle) {
2172
+ return this.fileManager.writeFiles(this.directory);
2173
+ }
2174
+ return bundleDeclarations({
2175
+ currentDirectory: this.directory,
2176
+ declarationFiles: this.fileManager.getDeclarationFiles(),
2177
+ entryPoints: this.fileManager.resolveEntryPoints(await this.buildConfiguration.entryPoints, this.buildConfiguration.dts.entryPoints),
2178
+ resolve: this.buildConfiguration.dts.resolve,
2179
+ external: this.buildConfiguration.external ?? [],
2180
+ noExternal: this.buildConfiguration.noExternal,
2181
+ // Extract only the minimal compiler options needed for DTS bundling from configuration
2182
+ // All these properties are guaranteed to exist in TypeScriptConfiguration
2183
+ compilerOptions: {
2184
+ paths: this.configuration.compilerOptions.paths,
2185
+ rootDir: this.configuration.compilerOptions.rootDir,
2186
+ outDir: this.configuration.compilerOptions.outDir,
2187
+ moduleResolution: this.configuration.compilerOptions.moduleResolution
2188
+ }
2189
+ });
2190
+ }
2191
+ async triggerRebuild() {
2192
+ if (this.pendingChanges.length === 0) {
2193
+ return;
2194
+ }
2195
+ Logger.clear();
2196
+ Logger.info(`Rebuilding project: ${this.pendingChanges.length} file changes detected.`);
2197
+ const rootNames = [...this.builderProgram.getProgram().getRootFileNames()];
2198
+ for (const { event, path, nextPath } of this.pendingChanges) {
2199
+ if (nextPath !== void 0 && (event === Watchr.FileEvent.rename || event === Watchr.DirectoryEvent.rename)) {
2200
+ this.buildDependencies.delete(Paths.relative(this.directory, path));
2201
+ this.buildDependencies.add(Paths.relative(this.directory, nextPath));
2202
+ const index = rootNames.indexOf(path);
2203
+ if (index !== -1) {
2204
+ rootNames.splice(index, 1, nextPath);
2205
+ }
2206
+ } else {
2207
+ const index = rootNames.indexOf(path);
2208
+ if (event === Watchr.FileEvent.unlink && index !== -1) {
2209
+ rootNames.splice(index, 1);
2210
+ } else if (event === Watchr.FileEvent.add && index === -1) {
2211
+ rootNames.push(path);
2212
+ }
2213
+ }
2214
+ }
2215
+ this.pendingChanges.length = 0;
2216
+ this.builderProgram = createIncrementalProgram({ rootNames, options: this.configuration.compilerOptions, projectReferences: this.configuration.projectReferences, configFileParsingDiagnostics: this.configuration.configFileParsingDiagnostics });
2217
+ await this.build();
2218
+ }
2219
+ /**
2220
+ * Resolves configuration by merging options with tsconfig.json.
2221
+ * @param directory - Project root directory
2222
+ * @param typeScriptOptions - Partial TypeScript options to merge
2223
+ * @returns Resolved configuration and TypeScript parser results
2224
+ */
2225
+ static resolveConfiguration(directory, typeScriptOptions) {
2226
+ const configResult = readConfigFile(findConfigFile(directory, sys3.fileExists) ?? "./tsconfig.json", sys3.readFile);
2227
+ if (configResult.error !== void 0) {
2228
+ throw new ConfigurationError(formatDiagnostics([configResult.error], diagnosticsHost));
2229
+ }
2230
+ const bundle = typeScriptOptions.tsbuild?.bundle ?? configResult.config.tsbuild?.bundle ?? true;
2231
+ const platform2 = configResult.config.compilerOptions?.lib?.some(domPredicate) ? Platform.BROWSER : Platform.NODE;
2232
+ const noExternal = typeScriptOptions.tsbuild?.noExternal ?? configResult.config.tsbuild?.noExternal ?? [];
2233
+ const hasExplicitEntryPoints = typeScriptOptions.tsbuild?.entryPoints !== void 0 || configResult.config.tsbuild?.entryPoints !== void 0;
2234
+ let inferredEntryPoints;
2235
+ if (!hasExplicitEntryPoints && bundle) {
2236
+ const packageJsonContent = sys3.readFile(Paths.join(directory, "package.json"));
2237
+ if (packageJsonContent) {
2238
+ try {
2239
+ const pkgJson = JSON.parse(packageJsonContent);
2240
+ const outDir = typeScriptOptions.compilerOptions?.outDir ?? configResult.config.compilerOptions?.outDir ?? defaultOutDirectory;
2241
+ inferredEntryPoints = inferEntryPoints(pkgJson, outDir);
2242
+ } catch {
2243
+ }
2244
+ }
2245
+ }
2246
+ const defaultTsbuildConfig = {
2247
+ splitting: bundle,
2248
+ minify: false,
2249
+ force: false,
2250
+ bundle,
2251
+ sourceMap: typeScriptOptions.compilerOptions?.sourceMap ?? configResult.config.compilerOptions?.sourceMap ?? false,
2252
+ noExternal,
2253
+ packages: noExternal.length > 0 ? void 0 : platform2 === Platform.BROWSER ? "bundle" : "external",
2254
+ platform: platform2,
2255
+ dts: { resolve: platform2 !== Platform.NODE, entryPoints: bundle ? void 0 : [] },
2256
+ watch: { enabled: false, recursive: true, ignoreInitial: true, persistent: true },
2257
+ entryPoints: inferredEntryPoints ?? (bundle ? { [defaultEntryPoint]: defaultEntryFile } : { src: defaultSourceDirectory })
2258
+ };
2259
+ const baseConfig = {
2260
+ ...configResult.config,
2261
+ clean: typeScriptOptions.tsbuild?.clean ?? configResult.config.tsbuild?.clean ?? true,
2262
+ tsbuild: {
2263
+ ...defaultTsbuildConfig,
2264
+ ...configResult.config.tsbuild,
2265
+ ...typeScriptOptions.tsbuild,
2266
+ dts: { ...defaultTsbuildConfig.dts, ...configResult.config.tsbuild?.dts, ...typeScriptOptions.tsbuild?.dts },
2267
+ watch: { ...defaultTsbuildConfig.watch, ...configResult.config.tsbuild?.watch, ...typeScriptOptions.tsbuild?.watch }
2268
+ },
2269
+ compilerOptions: {
2270
+ ...{ outDir: defaultOutDirectory, noEmit: false, sourceMap: false, incremental: true, tsBuildInfoFile: Paths.join(cacheDirectory, buildInfoFile), lib: [] },
2271
+ ...configResult.config.compilerOptions,
2272
+ ...typeScriptOptions.compilerOptions
2273
+ }
2274
+ };
2275
+ const { options, fileNames, errors } = parseJsonConfigFileContent(baseConfig, sys3, directory);
2276
+ return {
2277
+ ...baseConfig,
2278
+ compilerOptions: {
2279
+ ...baseConfig.compilerOptions,
2280
+ ...options,
2281
+ ...compilerOptionOverrides
2282
+ },
2283
+ directory,
2284
+ rootNames: fileNames,
2285
+ configFileParsingDiagnostics: errors,
2286
+ buildCache: baseConfig.compilerOptions.incremental ? new IncrementalBuildCache(directory, baseConfig.compilerOptions.tsBuildInfoFile) : void 0
2287
+ };
2288
+ }
2289
+ /**
2290
+ * Gets the entry points for the project.
2291
+ * @param entryPoints - The entry points to get.
2292
+ * @returns A promise that resolves to the entry points.
2293
+ */
2294
+ async getEntryPoints(entryPoints) {
2295
+ const expandedEntryPoints = {};
2296
+ for (const [name, entryPoint] of Object.entries(entryPoints)) {
2297
+ const resolvedPath = Paths.absolute(this.directory, entryPoint);
2298
+ if (await Paths.isDirectory(resolvedPath)) {
2299
+ for (const file of await Files.readDirectory(resolvedPath)) {
2300
+ const filePath = Paths.join(resolvedPath, file);
2301
+ if (await Paths.isFile(filePath)) {
2302
+ expandedEntryPoints[Paths.parse(file).name] = filePath;
2303
+ }
2304
+ }
2305
+ } else if (await Paths.isFile(resolvedPath)) {
2306
+ expandedEntryPoints[name] = resolvedPath;
2307
+ } else {
2308
+ throw new ConfigurationError(`Entry point does not exist: ${entryPoint}`);
2309
+ }
2310
+ }
2311
+ return expandedEntryPoints;
2312
+ }
2313
+ /**
2314
+ * Gets the project dependency paths, cached after first call.
2315
+ * Reads package.json and caches it for reuse.
2316
+ * @returns A promise that resolves to an array of project dependency paths.
2317
+ */
2318
+ getProjectDependencyPaths() {
2319
+ return this.dependencyPaths ??= Files.read(Paths.absolute(this.directory, "package.json")).then((content) => {
2320
+ const { dependencies = {}, peerDependencies = {} } = Json.parse(content);
2321
+ return [.../* @__PURE__ */ new Set([...Object.keys(dependencies), ...Object.keys(peerDependencies)])];
2322
+ });
2323
+ }
2324
+ /**
2325
+ * Handles build errors by logging unexpected errors and setting appropriate exit codes.
2326
+ * Expected build failures (TypeCheckError, BundleError) are already logged when they occur,
2327
+ * so this method only logs unexpected errors to avoid duplicate output.
2328
+ * @param error - The error to handle
2329
+ */
2330
+ handleBuildError(error) {
2331
+ if (error instanceof ConfigurationError) {
2332
+ Logger.error(error.message);
2333
+ if (!this.buildConfiguration.watch.enabled) {
2334
+ process.exitCode = error.code;
2335
+ }
2336
+ return;
2337
+ }
2338
+ if (error instanceof BuildError) {
2339
+ if (!this.buildConfiguration.watch.enabled) {
2340
+ process.exitCode = error.code;
2341
+ }
2342
+ return;
2343
+ }
2344
+ Logger.error("Build failed", error);
2345
+ if (!this.buildConfiguration.watch.enabled) {
2346
+ process.exitCode = 1;
2347
+ }
2348
+ }
2349
+ /**
2350
+ * Handles type errors in the project.
2351
+ * @param message - The message to display.
2352
+ * @param diagnostics - The diagnostics to handle.
2353
+ * @param projectDirectory - The project directory.
2354
+ */
2355
+ static handleTypeErrors(message, diagnostics, projectDirectory) {
2356
+ Logger.error(formatDiagnosticsWithColorAndContext(diagnostics, diagnosticsHost));
2357
+ const filesWithErrors = /* @__PURE__ */ new Map();
2358
+ for (const { file, start } of diagnostics) {
2359
+ if (file !== void 0) {
2360
+ const { line } = file.getLineAndCharacterOfPosition(start ?? 0);
2361
+ const existing = filesWithErrors.get(file.fileName);
2362
+ if (existing !== void 0) {
2363
+ existing.count++;
2364
+ existing.line = Math.min(existing.line, line);
2365
+ } else {
2366
+ filesWithErrors.set(file.fileName, { count: 1, line });
2367
+ }
2368
+ }
2369
+ }
2370
+ const errorCount = diagnostics.length;
2371
+ const fileCount = filesWithErrors.size;
2372
+ const [[firstFileName, { line: firstLine }] = ["", { line: 0 }]] = filesWithErrors;
2373
+ const relativeFirstFileName = Paths.relative(projectDirectory, firstFileName);
2374
+ if (errorCount === 1) {
2375
+ Logger.error(`Found 1 error in ${relativeFirstFileName}:${firstLine + 1}${sys3.newLine}`);
2376
+ } else if (fileCount === 1) {
2377
+ Logger.error(`Found ${errorCount} errors in the same file, starting at: ${relativeFirstFileName}:${firstLine + 1}${sys3.newLine}`);
2378
+ } else {
2379
+ Logger.error(`Found ${errorCount} errors in ${fileCount} files.${sys3.newLine}`);
2380
+ Logger.error("Errors Files");
2381
+ for (const [fileName, { count, line }] of filesWithErrors) {
2382
+ Logger.error(` ${count} ${fileName}:${line + 1}`);
2383
+ }
2384
+ }
2385
+ throw new TypeCheckError(message, formatDiagnostics(diagnostics, diagnosticsHost));
2386
+ }
2387
+ };
2388
+ _init3 = __decoratorStart(null);
2389
+ __decorateElement(_init3, 1, "build", _build_dec, _TypeScriptProject);
2390
+ __decorateElement(_init3, 1, "typeCheck", _typeCheck_dec, _TypeScriptProject);
2391
+ __decorateElement(_init3, 1, "transpile", _transpile_dec, _TypeScriptProject);
2392
+ __decorateElement(_init3, 1, "processDeclarations", _processDeclarations_dec, _TypeScriptProject);
2393
+ __decorateElement(_init3, 1, "triggerRebuild", _triggerRebuild_dec, _TypeScriptProject);
2394
+ _TypeScriptProject = __decorateElement(_init3, 0, "TypeScriptProject", _TypeScriptProject_decorators, _TypeScriptProject);
2395
+ __runInitializers(_init3, 1, _TypeScriptProject);
2396
+ var TypeScriptProject = _TypeScriptProject;
2397
+
2398
+ export {
2399
+ BuildError,
2400
+ TypeScriptProject
2401
+ };