@d1g1tal/tsbuild 1.1.3 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -3
- package/dist/{VMWNQL2J.js → 7FPDHUPW.js} +18 -2
- package/dist/{7ALTNLQM.js → DSHNVGWV.js} +1 -1
- package/dist/{index.d.ts → tsbuild.d.ts} +0 -1
- package/dist/tsbuild.js +2385 -43
- package/package.json +1 -1
- package/dist/6CSXJIEW.js +0 -2385
- package/dist/index.js +0 -7
package/dist/tsbuild.js
CHANGED
|
@@ -1,45 +1,2387 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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/files.ts
|
|
35
|
+
import { dirname } from "node:path";
|
|
36
|
+
import { serialize, deserialize } from "node:v8";
|
|
37
|
+
import { brotliDecompress, brotliCompress } from "node:zlib";
|
|
38
|
+
import { access, constants, mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
39
|
+
var Files = class _Files {
|
|
40
|
+
constructor() {
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Check if a file exists.
|
|
44
|
+
* @param filePath The path to the file.
|
|
45
|
+
* @returns True if the file exists, false otherwise.
|
|
46
|
+
*/
|
|
47
|
+
static async exists(filePath) {
|
|
48
|
+
try {
|
|
49
|
+
await access(filePath, constants.F_OK);
|
|
50
|
+
return true;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
if (error.code === "ENOENT") {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Clear a directory by removing all files and subdirectories.
|
|
60
|
+
* @param directory The path to the directory to clear.
|
|
61
|
+
*/
|
|
62
|
+
static async empty(directory) {
|
|
63
|
+
if (await _Files.exists(directory)) {
|
|
64
|
+
await Promise.all((await readdir(directory)).map((file) => rm(Paths.join(directory, file), defaultCleanOptions)));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Write data to a file.
|
|
69
|
+
* Ensures the directory exists before writing
|
|
70
|
+
* @param filePath The path to the file.
|
|
71
|
+
* @param data The data to write to the file.
|
|
72
|
+
* @param options Optional write file options.
|
|
73
|
+
*/
|
|
74
|
+
static async write(filePath, data, options = { encoding: Encoding.utf8 }) {
|
|
75
|
+
await mkdir(dirname(filePath), defaultDirOptions);
|
|
76
|
+
await writeFile(filePath, data, options);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Load a file and return its contents as a string.
|
|
80
|
+
* @param filePath The path to the file.
|
|
81
|
+
* @param encoding The encoding to use when reading the file. Default is UTF-8.
|
|
82
|
+
* @returns The file contents as a string.
|
|
83
|
+
*/
|
|
84
|
+
static async read(filePath, encoding = Encoding.utf8) {
|
|
85
|
+
return await readFile(this.normalizePath(filePath), { encoding });
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Reads the contents of a directory.
|
|
89
|
+
* @param directoryPath The path to the directory.
|
|
90
|
+
* @returns An array of file and directory names within the specified directory.
|
|
91
|
+
*/
|
|
92
|
+
static async readDirectory(directoryPath) {
|
|
93
|
+
return await readdir(directoryPath);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Normalize a file path to an absolute path.
|
|
97
|
+
* @param path The file path to normalize.
|
|
98
|
+
* @returns The normalized absolute path.
|
|
99
|
+
*/
|
|
100
|
+
static normalizePath(path) {
|
|
101
|
+
return path.startsWith("/") || path.startsWith("file://") ? path : new URL(path, import.meta.url).pathname;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Decompress a Brotli-compressed buffer.
|
|
105
|
+
* Uses callback-based API wrapped in a Promise for faster performance than streaming.
|
|
106
|
+
* @param buffer The compressed buffer to decompress.
|
|
107
|
+
* @returns The decompressed buffer.
|
|
108
|
+
*/
|
|
109
|
+
static decompressBuffer(buffer) {
|
|
110
|
+
return new Promise((resolve, reject) => brotliDecompress(buffer, (error, result) => error ? reject(error) : resolve(result)));
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Compress data using Brotli compression.
|
|
114
|
+
* Uses callback-based API wrapped in a Promise for faster performance than streaming.
|
|
115
|
+
* @param buffer The buffer to compress.
|
|
116
|
+
* @returns The compressed buffer.
|
|
117
|
+
*/
|
|
118
|
+
static compressBuffer(buffer) {
|
|
119
|
+
return new Promise((resolve, reject) => brotliCompress(buffer, (error, result) => error ? reject(error) : resolve(result)));
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Load a file and deserialize it using V8 deserialization.
|
|
123
|
+
* Faster than JSON.parse for complex objects.
|
|
124
|
+
* @param path The path to the file.
|
|
125
|
+
* @returns The deserialized object.
|
|
126
|
+
*/
|
|
127
|
+
static async readCompressed(path) {
|
|
128
|
+
return deserialize(await this.decompressBuffer(await readFile(this.normalizePath(path))));
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Serialize an object using V8 serialization and save to a Brotli-compressed file.
|
|
132
|
+
* Faster than JSON.stringify for complex objects.
|
|
133
|
+
* @param path The path to the file.
|
|
134
|
+
* @param data The object to serialize and save.
|
|
135
|
+
*/
|
|
136
|
+
static async writeCompressed(path, data) {
|
|
137
|
+
const normalizedPath = this.normalizePath(path);
|
|
138
|
+
await mkdir(dirname(normalizedPath), defaultDirOptions);
|
|
139
|
+
await writeFile(normalizedPath, await this.compressBuffer(serialize(data)));
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// src/type-script-project.ts
|
|
144
|
+
import { Watchr } from "@d1g1tal/watchr";
|
|
145
|
+
|
|
146
|
+
// src/text-formatter.ts
|
|
147
|
+
import { isatty } from "node:tty";
|
|
148
|
+
var { env = {}, platform = "" } = process;
|
|
149
|
+
var isDumbTerminal = env.TERM === "dumb";
|
|
150
|
+
var isCompatibleTerminal = isatty(1) && env.TERM && !isDumbTerminal;
|
|
151
|
+
var isColorSupported = !("NO_COLOR" in env) && ("FORCE_COLOR" in env || platform === "win32" && !isDumbTerminal || isCompatibleTerminal);
|
|
152
|
+
var replaceClose = (index, string, close, replace, head = string.substring(0, index) + replace, tail = string.substring(index + close.length), next = tail.indexOf(close)) => {
|
|
153
|
+
return head + (next < 0 ? tail : replaceClose(next, tail, close, replace));
|
|
154
|
+
};
|
|
155
|
+
var clearBleed = (index, string, open, close, replace) => {
|
|
156
|
+
return index < 0 ? `${open}${string}${close}` : `${open}${replaceClose(index, string, close, replace)}${close}`;
|
|
157
|
+
};
|
|
158
|
+
var filterEmpty = (open, close, replace = open, at = open.length + 1) => {
|
|
159
|
+
return (text) => text.length ? clearBleed(text.indexOf(close, at), text, open, close, replace) : "";
|
|
160
|
+
};
|
|
161
|
+
var generateTextFormatter = (open, close, replace) => filterEmpty(`\x1B[${open}m`, `\x1B[${close}m`, replace);
|
|
162
|
+
var TextFormat = class {
|
|
163
|
+
static enabled = isColorSupported;
|
|
164
|
+
static reset = generateTextFormatter(0, 0);
|
|
165
|
+
static bold = generateTextFormatter(1, 22, "\x1B[22m\x1B[1m");
|
|
166
|
+
static dim = generateTextFormatter(2, 22, "\x1B[22m\x1B[2m");
|
|
167
|
+
static italic = generateTextFormatter(3, 23);
|
|
168
|
+
static underline = generateTextFormatter(4, 24);
|
|
169
|
+
static inverse = generateTextFormatter(7, 27);
|
|
170
|
+
static hidden = generateTextFormatter(8, 28);
|
|
171
|
+
static strikethrough = generateTextFormatter(9, 29);
|
|
172
|
+
static black = generateTextFormatter(30, 39);
|
|
173
|
+
static red = generateTextFormatter(31, 39);
|
|
174
|
+
static green = generateTextFormatter(32, 39);
|
|
175
|
+
static yellow = generateTextFormatter(33, 39);
|
|
176
|
+
static blue = generateTextFormatter(34, 39);
|
|
177
|
+
static magenta = generateTextFormatter(35, 39);
|
|
178
|
+
static cyan = generateTextFormatter(36, 39);
|
|
179
|
+
static white = generateTextFormatter(37, 39);
|
|
180
|
+
static gray = generateTextFormatter(90, 39);
|
|
181
|
+
static bgBlack = generateTextFormatter(40, 49);
|
|
182
|
+
static bgRed = generateTextFormatter(41, 49);
|
|
183
|
+
static bgGreen = generateTextFormatter(42, 49);
|
|
184
|
+
static bgYellow = generateTextFormatter(43, 49);
|
|
185
|
+
static bgBlue = generateTextFormatter(44, 49);
|
|
186
|
+
static bgMagenta = generateTextFormatter(45, 49);
|
|
187
|
+
static bgCyan = generateTextFormatter(46, 49);
|
|
188
|
+
static bgWhite = generateTextFormatter(47, 49);
|
|
189
|
+
static blackBright = generateTextFormatter(90, 39);
|
|
190
|
+
static redBright = generateTextFormatter(91, 39);
|
|
191
|
+
static greenBright = generateTextFormatter(92, 39);
|
|
192
|
+
static yellowBright = generateTextFormatter(93, 39);
|
|
193
|
+
static blueBright = generateTextFormatter(94, 39);
|
|
194
|
+
static magentaBright = generateTextFormatter(95, 39);
|
|
195
|
+
static cyanBright = generateTextFormatter(96, 39);
|
|
196
|
+
static whiteBright = generateTextFormatter(97, 39);
|
|
197
|
+
static bgBlackBright = generateTextFormatter(100, 49);
|
|
198
|
+
static bgRedBright = generateTextFormatter(101, 49);
|
|
199
|
+
static bgGreenBright = generateTextFormatter(102, 49);
|
|
200
|
+
static bgYellowBright = generateTextFormatter(103, 49);
|
|
201
|
+
static bgBlueBright = generateTextFormatter(104, 49);
|
|
202
|
+
static bgMagentaBright = generateTextFormatter(105, 49);
|
|
203
|
+
static bgCyanBright = generateTextFormatter(106, 49);
|
|
204
|
+
static bgWhiteBright = generateTextFormatter(107, 49);
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// src/logger.ts
|
|
208
|
+
var isWrittenFiles = (data) => {
|
|
209
|
+
if (!Array.isArray(data)) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
return data.every((writtenFile) => {
|
|
213
|
+
return writtenFile !== null && typeof writtenFile === "object" && "path" in writtenFile && "size" in writtenFile;
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
var colorize = (type2, data, onlyImportant = false) => {
|
|
217
|
+
if (onlyImportant && (type2 === "info" || type2 === "success")) {
|
|
218
|
+
return data;
|
|
219
|
+
}
|
|
220
|
+
switch (type2) {
|
|
221
|
+
case "info":
|
|
222
|
+
return TextFormat.blue(data);
|
|
223
|
+
case "error":
|
|
224
|
+
return TextFormat.red(data);
|
|
225
|
+
case "warn":
|
|
226
|
+
return TextFormat.yellow(data);
|
|
227
|
+
default:
|
|
228
|
+
return TextFormat.green(data);
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
var prettyBytes = (bytes) => {
|
|
232
|
+
if (bytes === 0) {
|
|
233
|
+
return { value: "0", unit: "B" };
|
|
234
|
+
}
|
|
235
|
+
const exp = ~~(Math.log(bytes) / Math.log(1024));
|
|
236
|
+
return { value: (bytes / Math.pow(1024, exp)).toFixed(2), unit: dataUnits[exp] };
|
|
237
|
+
};
|
|
238
|
+
var Logger = class _Logger {
|
|
239
|
+
constructor() {
|
|
240
|
+
}
|
|
241
|
+
static EntryType = {
|
|
242
|
+
Info: "info",
|
|
243
|
+
Success: "success",
|
|
244
|
+
Done: "done",
|
|
245
|
+
Error: "error",
|
|
246
|
+
Warn: "warn"
|
|
247
|
+
};
|
|
248
|
+
/** Clears the console */
|
|
249
|
+
static clear() {
|
|
250
|
+
console.log("\x1Bc");
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Logs a header box with a message.
|
|
254
|
+
* @param message The message to display in the header.
|
|
255
|
+
*/
|
|
256
|
+
static header(message) {
|
|
257
|
+
const innerWidth = message.length + 2;
|
|
258
|
+
console.log(TextFormat.cyan(`\u256D${"\u2500".repeat(innerWidth)}\u256E${newLine}\u2502 ${message} \u2502${newLine}\u2570${"\u2500".repeat(innerWidth)}\u256F`));
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Logs a separator line.
|
|
262
|
+
* @param width Optional width of the separator (default: 40).
|
|
263
|
+
*/
|
|
264
|
+
static separator(width = 40) {
|
|
265
|
+
console.log(TextFormat.dim("\u2500".repeat(width)));
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Logs a success message with a check mark and optional indentation.
|
|
269
|
+
* @param message The message to log.
|
|
270
|
+
* @param indent Whether to indent the message (tree structure).
|
|
271
|
+
*/
|
|
272
|
+
static step(message, indent = false) {
|
|
273
|
+
const prefix = indent ? " \u2514\u2500" : "\u2713";
|
|
274
|
+
console.log(TextFormat.green(`${prefix} ${message}`));
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Logs a success message.
|
|
278
|
+
* @param message The message to log.
|
|
279
|
+
* @param args Additional data to log.
|
|
280
|
+
* @returns void
|
|
281
|
+
*/
|
|
282
|
+
static success(message, ...args) {
|
|
283
|
+
return _Logger.log(message, "success", ...args);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Logs an info message.
|
|
287
|
+
* @param message The message to log.
|
|
288
|
+
* @param args Additional data to log.
|
|
289
|
+
* @returns void
|
|
290
|
+
*/
|
|
291
|
+
static info(message, ...args) {
|
|
292
|
+
return _Logger.log(message, "info", ...args);
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Logs an error message.
|
|
296
|
+
* @param message The message to log.
|
|
297
|
+
* @param args Additional data to log.
|
|
298
|
+
* @returns void
|
|
299
|
+
*/
|
|
300
|
+
static error(message, ...args) {
|
|
301
|
+
return _Logger.log(message, "error", ...args);
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Logs a warning message.
|
|
305
|
+
* @param message The message to log.
|
|
306
|
+
* @param args Additional data to log.
|
|
307
|
+
* @returns void
|
|
308
|
+
*/
|
|
309
|
+
static warn(message, ...args) {
|
|
310
|
+
return _Logger.log(message, "warn", ...args);
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Logs a done message.
|
|
314
|
+
* @param message The message to log.
|
|
315
|
+
* @param type The type of the log entry.
|
|
316
|
+
* @param data Additional data to log.
|
|
317
|
+
*/
|
|
318
|
+
static log(message, type2, ...data) {
|
|
319
|
+
if (data.length) {
|
|
320
|
+
if (isWrittenFiles(data)) {
|
|
321
|
+
if (message) {
|
|
322
|
+
console.log(colorize(type2, message, true));
|
|
323
|
+
}
|
|
324
|
+
_Logger.files(data);
|
|
325
|
+
} else {
|
|
326
|
+
console.log(colorize(type2, message, true), ...data);
|
|
327
|
+
}
|
|
328
|
+
} else {
|
|
329
|
+
console.log(colorize(type2, message, true));
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Logs an array of WrittenFile objects in a formatted manner.
|
|
334
|
+
* @param files - The array of WrittenFile objects to log.
|
|
335
|
+
* @internal
|
|
336
|
+
*/
|
|
337
|
+
static files(files) {
|
|
338
|
+
const maxPathLength = files.reduce((max, { path }) => Math.max(max, path.length), 0);
|
|
339
|
+
const formatted = files.map(({ path, size }) => ({ path, ...prettyBytes(size) }));
|
|
340
|
+
const maxValueLength = formatted.reduce((max, { value }) => Math.max(max, value.length), 0);
|
|
341
|
+
const maxUnitLength = formatted.reduce((max, { unit }) => Math.max(max, unit.length), 0);
|
|
342
|
+
for (let i = 0, length = formatted.length; i < length; i++) {
|
|
343
|
+
const { path, value, unit } = formatted[i];
|
|
344
|
+
const paddedPath = path.padEnd(maxPathLength);
|
|
345
|
+
const paddedValue = value.padStart(maxValueLength);
|
|
346
|
+
const paddedUnit = unit.padEnd(maxUnitLength);
|
|
347
|
+
const prefix = i === length - 1 ? " \u2514\u2500" : " \u251C\u2500";
|
|
348
|
+
console.log(`${TextFormat.dim(prefix)} ${TextFormat.bold(paddedPath)} ${TextFormat.cyan(paddedValue)} ${TextFormat.dim(paddedUnit)}`);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
// src/dts/declaration-bundler.ts
|
|
354
|
+
import MagicString2 from "magic-string";
|
|
355
|
+
import { mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
|
|
356
|
+
import { basename, posix } from "node:path";
|
|
357
|
+
|
|
358
|
+
// src/errors.ts
|
|
359
|
+
import { SyntaxKind } from "typescript";
|
|
360
|
+
var BuildError = class extends Error {
|
|
361
|
+
/**
|
|
362
|
+
* Creates a new BuildError
|
|
363
|
+
* @param message - Error message
|
|
364
|
+
* @param code - Exit code (default: 1)
|
|
365
|
+
*/
|
|
366
|
+
constructor(message, code = 1) {
|
|
367
|
+
super(message);
|
|
368
|
+
this.code = code;
|
|
369
|
+
this.name = "BuildError";
|
|
370
|
+
Error.captureStackTrace(this, this.constructor);
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
var TypeCheckError = class extends BuildError {
|
|
374
|
+
/**
|
|
375
|
+
* Creates a new TypeCheckError
|
|
376
|
+
* @param message - Error message
|
|
377
|
+
* @param diagnostics - Optional TypeScript diagnostics output
|
|
378
|
+
*/
|
|
379
|
+
constructor(message, diagnostics) {
|
|
380
|
+
super(message, 1);
|
|
381
|
+
this.diagnostics = diagnostics;
|
|
382
|
+
this.name = "TypeCheckError";
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
var BundleError = class extends BuildError {
|
|
386
|
+
/**
|
|
387
|
+
* Creates a new BundleError
|
|
388
|
+
* @param message - Error message
|
|
389
|
+
*/
|
|
390
|
+
constructor(message) {
|
|
391
|
+
super(message, 2);
|
|
392
|
+
this.name = "BundleError";
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
var ConfigurationError = class extends BuildError {
|
|
396
|
+
/**
|
|
397
|
+
* Creates a new ConfigurationError
|
|
398
|
+
* @param message - Error message
|
|
399
|
+
*/
|
|
400
|
+
constructor(message) {
|
|
401
|
+
super(message, 3);
|
|
402
|
+
this.name = "ConfigurationError";
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
var UnsupportedSyntaxError = class extends BundleError {
|
|
406
|
+
/**
|
|
407
|
+
* Creates an instance of UnsupportedSyntaxError.
|
|
408
|
+
* @param node The node with unsupported syntax
|
|
409
|
+
* @param message The message to display (default: 'Syntax not yet supported')
|
|
410
|
+
*/
|
|
411
|
+
constructor(node, message = "Syntax not yet supported") {
|
|
412
|
+
const syntaxKindName = SyntaxKind[node.kind] ?? `Unknown(${node.kind})`;
|
|
413
|
+
const nodeText = node.getText ? node.getText().slice(0, 100) : "<no text>";
|
|
414
|
+
super(`${message}: ${syntaxKindName} - "${nodeText}"`);
|
|
415
|
+
this.name = "UnsupportedSyntaxError";
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
var castError = (exception) => {
|
|
419
|
+
if (exception instanceof Error) {
|
|
420
|
+
return exception;
|
|
421
|
+
}
|
|
422
|
+
return new Error(typeof exception === "string" ? exception : "Unknown error");
|
|
423
|
+
};
|
|
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;
|
|
45
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
|
+
var outputToSourceExtension = /* @__PURE__ */ new Map([
|
|
1877
|
+
[".js", ".ts"],
|
|
1878
|
+
[".jsx", ".tsx"],
|
|
1879
|
+
[".d.ts", ".ts"]
|
|
1880
|
+
]);
|
|
1881
|
+
function unscope(name) {
|
|
1882
|
+
const slash = name.indexOf("/");
|
|
1883
|
+
return slash === -1 ? name : name.slice(slash + 1);
|
|
1884
|
+
}
|
|
1885
|
+
function outputToSourcePath(outputPath, outDir, sourceDir) {
|
|
1886
|
+
const normalizedOutput = outputPath.replace(/^\.\//, "");
|
|
1887
|
+
const normalizedOutDir = outDir.replace(/^\.\//, "").replace(/\/$/, "");
|
|
1888
|
+
if (!normalizedOutput.startsWith(normalizedOutDir + "/") && normalizedOutput !== normalizedOutDir) {
|
|
1889
|
+
return void 0;
|
|
1890
|
+
}
|
|
1891
|
+
const relativePortion = normalizedOutput.slice(normalizedOutDir.length + 1);
|
|
1892
|
+
for (const [outExt, srcExt] of outputToSourceExtension) {
|
|
1893
|
+
if (relativePortion.endsWith(outExt)) {
|
|
1894
|
+
const stem = relativePortion.slice(0, -outExt.length);
|
|
1895
|
+
return `./${sourceDir}/${stem}${srcExt}`;
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
return void 0;
|
|
1899
|
+
}
|
|
1900
|
+
function resolveConditionalExport(exportValue) {
|
|
1901
|
+
if (typeof exportValue === "string") {
|
|
1902
|
+
return exportValue;
|
|
1903
|
+
}
|
|
1904
|
+
for (const condition of importConditions) {
|
|
1905
|
+
const value = exportValue[condition];
|
|
1906
|
+
if (typeof value === "string") {
|
|
1907
|
+
return value;
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
return void 0;
|
|
1911
|
+
}
|
|
1912
|
+
function subpathToEntryName(subpath, packageName) {
|
|
1913
|
+
if (subpath === ".") {
|
|
1914
|
+
return packageName !== void 0 ? unscope(packageName) : "index";
|
|
1915
|
+
}
|
|
1916
|
+
const withoutPrefix = subpath.replace(/^\.\//, "");
|
|
1917
|
+
const lastSegment = withoutPrefix.lastIndexOf("/");
|
|
1918
|
+
return lastSegment === -1 ? withoutPrefix : withoutPrefix.slice(lastSegment + 1);
|
|
1919
|
+
}
|
|
1920
|
+
function inferEntryPoints(packageJson, outDir, sourceDir = "src") {
|
|
1921
|
+
const entryPoints = {};
|
|
1922
|
+
if (packageJson.exports !== void 0) {
|
|
1923
|
+
if (typeof packageJson.exports === "string") {
|
|
1924
|
+
const sourcePath = outputToSourcePath(packageJson.exports, outDir, sourceDir);
|
|
1925
|
+
if (sourcePath) {
|
|
1926
|
+
entryPoints[packageJson.name !== void 0 ? unscope(packageJson.name) : "index"] = sourcePath;
|
|
1927
|
+
}
|
|
1928
|
+
} else {
|
|
1929
|
+
for (const [subpath, exportValue] of Object.entries(packageJson.exports)) {
|
|
1930
|
+
if (subpath.includes("*")) {
|
|
1931
|
+
continue;
|
|
1932
|
+
}
|
|
1933
|
+
const outputPath = resolveConditionalExport(exportValue);
|
|
1934
|
+
if (outputPath === void 0) {
|
|
1935
|
+
continue;
|
|
1936
|
+
}
|
|
1937
|
+
const sourcePath = outputToSourcePath(outputPath, outDir, sourceDir);
|
|
1938
|
+
if (sourcePath) {
|
|
1939
|
+
entryPoints[subpathToEntryName(subpath, packageJson.name)] = sourcePath;
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
if (packageJson.bin !== void 0) {
|
|
1945
|
+
const binEntries = typeof packageJson.bin === "string" ? { [packageJson.name ?? "cli"]: packageJson.bin } : packageJson.bin;
|
|
1946
|
+
for (const [name, outputPath] of Object.entries(binEntries)) {
|
|
1947
|
+
if (entryPoints[name] === void 0) {
|
|
1948
|
+
const sourcePath = outputToSourcePath(outputPath, outDir, sourceDir);
|
|
1949
|
+
if (sourcePath) {
|
|
1950
|
+
entryPoints[name] = sourcePath;
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
if (Object.keys(entryPoints).length === 0) {
|
|
1956
|
+
const legacyPath = packageJson.module ?? packageJson.main;
|
|
1957
|
+
if (legacyPath !== void 0) {
|
|
1958
|
+
const sourcePath = outputToSourcePath(legacyPath, outDir, sourceDir);
|
|
1959
|
+
if (sourcePath) {
|
|
1960
|
+
entryPoints["index"] = sourcePath;
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
return Object.keys(entryPoints).length > 0 ? entryPoints : void 0;
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
// src/type-script-project.ts
|
|
1968
|
+
import { build as esbuild, formatMessages } from "esbuild";
|
|
1969
|
+
import { sys as sys3, createIncrementalProgram, formatDiagnostics, formatDiagnosticsWithColorAndContext, parseJsonConfigFileContent, readConfigFile, findConfigFile } from "typescript";
|
|
1970
|
+
var globCharacters = /[*?\\[\]!].*$/;
|
|
1971
|
+
var domPredicate = (lib) => lib.toUpperCase() === "DOM";
|
|
1972
|
+
var diagnosticsHost = { getNewLine: () => sys3.newLine, getCurrentDirectory: sys3.getCurrentDirectory, getCanonicalFileName: (fileName) => fileName };
|
|
1973
|
+
var _triggerRebuild_dec, _processDeclarations_dec, _transpile_dec, _typeCheck_dec, _build_dec, _TypeScriptProject_decorators, _init3;
|
|
1974
|
+
_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)];
|
|
1975
|
+
var _TypeScriptProject = class _TypeScriptProject {
|
|
1976
|
+
/**
|
|
1977
|
+
* Creates a TypeScript project and prepares it for building/bundling.
|
|
1978
|
+
* @param directory - Project root directory (defaults to current working directory)
|
|
1979
|
+
* @param options - Project options to merge with tsconfig.json
|
|
1980
|
+
*/
|
|
1981
|
+
constructor(directory = sys3.getCurrentDirectory(), options = {}) {
|
|
1982
|
+
__runInitializers(_init3, 5, this);
|
|
1983
|
+
__publicField(this, "fileWatcher");
|
|
1984
|
+
__publicField(this, "builderProgram");
|
|
1985
|
+
__publicField(this, "directory");
|
|
1986
|
+
__publicField(this, "configuration");
|
|
1987
|
+
__publicField(this, "fileManager");
|
|
1988
|
+
__publicField(this, "buildConfiguration");
|
|
1989
|
+
__publicField(this, "pendingChanges", []);
|
|
1990
|
+
__publicField(this, "buildDependencies", /* @__PURE__ */ new Set());
|
|
1991
|
+
__publicField(this, "dependencyPaths");
|
|
1992
|
+
this.directory = Paths.absolute(directory);
|
|
1993
|
+
this.configuration = _TypeScriptProject.resolveConfiguration(this.directory, options);
|
|
1994
|
+
const { buildCache, rootNames, projectReferences, configFileParsingDiagnostics, tsbuild: { entryPoints, ...tsbuildOptions }, compilerOptions: { target, outDir } } = this.configuration;
|
|
1995
|
+
if (buildCache !== void 0 && options.clearCache) {
|
|
1996
|
+
buildCache.invalidate();
|
|
1997
|
+
}
|
|
1998
|
+
this.fileManager = new FileManager(buildCache);
|
|
1999
|
+
this.builderProgram = createIncrementalProgram({ rootNames, options: this.configuration.compilerOptions, projectReferences, configFileParsingDiagnostics });
|
|
2000
|
+
const entryPointsPromise = this.getEntryPoints(entryPoints);
|
|
2001
|
+
entryPointsPromise.catch(() => {
|
|
2002
|
+
});
|
|
2003
|
+
this.buildConfiguration = { entryPoints: entryPointsPromise, target: toEsTarget(target), outDir, ...tsbuildOptions };
|
|
2004
|
+
}
|
|
2005
|
+
/**
|
|
2006
|
+
* Cleans the output directory
|
|
2007
|
+
* @returns A promise that resolves when the cleaning is complete.
|
|
2008
|
+
*/
|
|
2009
|
+
async clean() {
|
|
2010
|
+
return Files.empty(this.buildConfiguration.outDir);
|
|
2011
|
+
}
|
|
2012
|
+
async build() {
|
|
2013
|
+
Logger.header(`\u{1F680} tsbuild v${"1.2.1"}${this.configuration.compilerOptions.incremental ? " [incremental]" : ""}`);
|
|
2014
|
+
try {
|
|
2015
|
+
const processes = [];
|
|
2016
|
+
const filesWereEmitted = await this.typeCheck();
|
|
2017
|
+
if ((filesWereEmitted || this.configuration.tsbuild.force) && !this.configuration.compilerOptions.noEmit) {
|
|
2018
|
+
if (this.configuration.clean) {
|
|
2019
|
+
await this.clean();
|
|
2020
|
+
}
|
|
2021
|
+
if (this.configuration.compilerOptions.declaration) {
|
|
2022
|
+
processes.push(this.processDeclarations());
|
|
2023
|
+
}
|
|
2024
|
+
if (!this.configuration.compilerOptions.emitDeclarationOnly) {
|
|
2025
|
+
processes.push(this.transpile());
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
for (const result of await Promise.allSettled(processes)) {
|
|
2029
|
+
if (result.status === "rejected") {
|
|
2030
|
+
this.handleBuildError(result.reason);
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
} catch (error) {
|
|
2034
|
+
this.handleBuildError(error);
|
|
2035
|
+
} finally {
|
|
2036
|
+
if (this.buildConfiguration.watch.enabled) {
|
|
2037
|
+
this.buildDependencies.clear();
|
|
2038
|
+
for (const { isDeclarationFile, fileName } of this.builderProgram.getProgram().getSourceFiles()) {
|
|
2039
|
+
if (!isDeclarationFile) {
|
|
2040
|
+
this.buildDependencies.add(Paths.relative(this.directory, fileName));
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
if (this.fileWatcher === void 0 || this.fileWatcher.isClosed()) {
|
|
2044
|
+
setImmediate(() => this.watch());
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
async typeCheck() {
|
|
2050
|
+
await this.fileManager.initialize();
|
|
2051
|
+
const { diagnostics } = this.builderProgram.emit(void 0, this.fileManager.fileWriter, void 0, true);
|
|
2052
|
+
if (diagnostics.length > 0) {
|
|
2053
|
+
_TypeScriptProject.handleTypeErrors("Type-checking failed", diagnostics, this.directory);
|
|
2054
|
+
}
|
|
2055
|
+
return this.fileManager.finalize();
|
|
2056
|
+
}
|
|
2057
|
+
async transpile() {
|
|
2058
|
+
const plugins = [outputPlugin()];
|
|
2059
|
+
if (this.buildConfiguration.noExternal.length > 0) {
|
|
2060
|
+
plugins.push(externalModulesPlugin({ dependencies: await this.getProjectDependencyPaths(), noExternal: this.buildConfiguration.noExternal }));
|
|
2061
|
+
}
|
|
2062
|
+
if (this.configuration.compilerOptions.emitDecoratorMetadata) {
|
|
2063
|
+
try {
|
|
2064
|
+
const { swcDecoratorMetadataPlugin } = await import("./DSHNVGWV.js");
|
|
2065
|
+
plugins.push(swcDecoratorMetadataPlugin);
|
|
2066
|
+
} catch {
|
|
2067
|
+
throw new ConfigurationError("emitDecoratorMetadata is enabled but @swc/core is not installed. Install it with: pnpm add -D @swc/core");
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
if (this.buildConfiguration.plugins?.length) {
|
|
2071
|
+
plugins.push(...this.buildConfiguration.plugins);
|
|
2072
|
+
}
|
|
2073
|
+
const define = {};
|
|
2074
|
+
if (this.buildConfiguration.env !== void 0) {
|
|
2075
|
+
for (const [key, value] of Object.entries(this.buildConfiguration.env)) {
|
|
2076
|
+
processEnvExpansionPattern.lastIndex = 0;
|
|
2077
|
+
define[`import.meta.env.${key}`] = Json.serialize(value.replace(processEnvExpansionPattern, (_, envVar) => process.env[envVar] ?? ""));
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
try {
|
|
2081
|
+
const { warnings, errors, metafile: { outputs } } = await esbuild({
|
|
2082
|
+
format,
|
|
2083
|
+
plugins,
|
|
2084
|
+
define,
|
|
2085
|
+
write: false,
|
|
2086
|
+
metafile: true,
|
|
2087
|
+
treeShaking: true,
|
|
2088
|
+
logLevel: "warning",
|
|
2089
|
+
tsconfigRaw: {
|
|
2090
|
+
compilerOptions: {
|
|
2091
|
+
alwaysStrict: this.configuration.compilerOptions.alwaysStrict,
|
|
2092
|
+
experimentalDecorators: this.configuration.compilerOptions.experimentalDecorators,
|
|
2093
|
+
jsx: toJsxRenderingMode(this.configuration.compilerOptions.jsx),
|
|
2094
|
+
jsxFactory: this.configuration.compilerOptions.jsxFactory,
|
|
2095
|
+
jsxFragmentFactory: this.configuration.compilerOptions.jsxFragmentFactory,
|
|
2096
|
+
jsxImportSource: this.configuration.compilerOptions.jsxImportSource,
|
|
2097
|
+
paths: this.configuration.compilerOptions.paths,
|
|
2098
|
+
strict: this.configuration.compilerOptions.strict,
|
|
2099
|
+
target: this.buildConfiguration.target,
|
|
2100
|
+
useDefineForClassFields: this.configuration.compilerOptions.useDefineForClassFields,
|
|
2101
|
+
verbatimModuleSyntax: this.configuration.compilerOptions.verbatimModuleSyntax
|
|
2102
|
+
}
|
|
2103
|
+
},
|
|
2104
|
+
entryPoints: await this.buildConfiguration.entryPoints,
|
|
2105
|
+
bundle: this.buildConfiguration.bundle,
|
|
2106
|
+
packages: this.buildConfiguration.packages,
|
|
2107
|
+
platform: this.buildConfiguration.platform,
|
|
2108
|
+
sourcemap: this.buildConfiguration.sourceMap,
|
|
2109
|
+
target: this.buildConfiguration.target,
|
|
2110
|
+
banner: this.buildConfiguration.banner,
|
|
2111
|
+
footer: this.buildConfiguration.footer,
|
|
2112
|
+
outdir: this.buildConfiguration.outDir,
|
|
2113
|
+
splitting: this.buildConfiguration.splitting,
|
|
2114
|
+
chunkNames: "[hash]",
|
|
2115
|
+
minify: this.buildConfiguration.minify,
|
|
2116
|
+
// Force decorator transformation even with ESNext target since Node.js doesn't support decorators yet
|
|
2117
|
+
supported: { decorators: false }
|
|
2118
|
+
});
|
|
2119
|
+
for (const [kind, logEntryType, messages] of [[BuildMessageType.WARNING, Logger.EntryType.Warn, warnings], [BuildMessageType.ERROR, Logger.EntryType.Error, errors]]) {
|
|
2120
|
+
for (const message of await formatMessages(messages, { kind, color: true })) {
|
|
2121
|
+
Logger.log(message, logEntryType);
|
|
2122
|
+
}
|
|
2123
|
+
if (kind === BuildMessageType.ERROR && errors.length > 0) {
|
|
2124
|
+
return [];
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
const writtenFiles = [];
|
|
2128
|
+
for (const [outputPath, { bytes }] of Object.entries(outputs)) {
|
|
2129
|
+
writtenFiles.push({ path: outputPath, size: bytes });
|
|
2130
|
+
}
|
|
2131
|
+
return writtenFiles;
|
|
2132
|
+
} catch (error) {
|
|
2133
|
+
Logger.error("Transpile failed", error);
|
|
2134
|
+
throw error;
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
/**
|
|
2138
|
+
* Watches for changes in the project files and rebuilds the project when changes are detected.
|
|
2139
|
+
*/
|
|
2140
|
+
watch() {
|
|
2141
|
+
const targets = [];
|
|
2142
|
+
for (const path of this.configuration.include ?? [defaultSourceDirectory]) {
|
|
2143
|
+
targets.push(Paths.absolute(this.directory, path.replace(globCharacters, "")));
|
|
2144
|
+
}
|
|
2145
|
+
const rebuild = (event, stats, path, nextPath) => {
|
|
2146
|
+
if (stats?.size === 0 && (event === Watchr.FileEvent.add || event === Watchr.FileEvent.unlink)) {
|
|
2147
|
+
return;
|
|
2148
|
+
}
|
|
2149
|
+
if (this.configuration.compilerOptions.noEmit || this.buildDependencies.has(Paths.relative(this.directory, path))) {
|
|
2150
|
+
this.pendingChanges.push({ event, path, nextPath });
|
|
2151
|
+
void this.triggerRebuild();
|
|
2152
|
+
}
|
|
2153
|
+
};
|
|
2154
|
+
const pathsToIgnore = [...this.configuration.exclude ?? [], ...this.buildConfiguration.watch.ignore ?? []];
|
|
2155
|
+
this.fileWatcher = new Watchr(targets, { ...this.buildConfiguration.watch, ignore: (path) => pathsToIgnore.some((p) => path.lastIndexOf(p) > -1) }, rebuild);
|
|
2156
|
+
Logger.info(`Watching for changes in: ${targets.join(", ")}`);
|
|
2157
|
+
}
|
|
2158
|
+
/** Closes the project and cleans up resources. */
|
|
2159
|
+
close() {
|
|
2160
|
+
this.fileWatcher?.close();
|
|
2161
|
+
this.fileManager.close();
|
|
2162
|
+
this.buildDependencies.clear();
|
|
2163
|
+
this.pendingChanges.length = 0;
|
|
2164
|
+
}
|
|
2165
|
+
async processDeclarations() {
|
|
2166
|
+
if (!this.buildConfiguration.bundle) {
|
|
2167
|
+
return this.fileManager.writeFiles(this.directory);
|
|
2168
|
+
}
|
|
2169
|
+
return bundleDeclarations({
|
|
2170
|
+
currentDirectory: this.directory,
|
|
2171
|
+
declarationFiles: this.fileManager.getDeclarationFiles(),
|
|
2172
|
+
entryPoints: this.fileManager.resolveEntryPoints(await this.buildConfiguration.entryPoints, this.buildConfiguration.dts.entryPoints),
|
|
2173
|
+
resolve: this.buildConfiguration.dts.resolve,
|
|
2174
|
+
external: this.buildConfiguration.external ?? [],
|
|
2175
|
+
noExternal: this.buildConfiguration.noExternal,
|
|
2176
|
+
// Extract only the minimal compiler options needed for DTS bundling from configuration
|
|
2177
|
+
// All these properties are guaranteed to exist in TypeScriptConfiguration
|
|
2178
|
+
compilerOptions: {
|
|
2179
|
+
paths: this.configuration.compilerOptions.paths,
|
|
2180
|
+
rootDir: this.configuration.compilerOptions.rootDir,
|
|
2181
|
+
outDir: this.configuration.compilerOptions.outDir,
|
|
2182
|
+
moduleResolution: this.configuration.compilerOptions.moduleResolution
|
|
2183
|
+
}
|
|
2184
|
+
});
|
|
2185
|
+
}
|
|
2186
|
+
async triggerRebuild() {
|
|
2187
|
+
if (this.pendingChanges.length === 0) {
|
|
2188
|
+
return;
|
|
2189
|
+
}
|
|
2190
|
+
Logger.clear();
|
|
2191
|
+
Logger.info(`Rebuilding project: ${this.pendingChanges.length} file changes detected.`);
|
|
2192
|
+
const rootNames = [...this.builderProgram.getProgram().getRootFileNames()];
|
|
2193
|
+
for (const { event, path, nextPath } of this.pendingChanges) {
|
|
2194
|
+
if (nextPath !== void 0 && (event === Watchr.FileEvent.rename || event === Watchr.DirectoryEvent.rename)) {
|
|
2195
|
+
this.buildDependencies.delete(Paths.relative(this.directory, path));
|
|
2196
|
+
this.buildDependencies.add(Paths.relative(this.directory, nextPath));
|
|
2197
|
+
const index = rootNames.indexOf(path);
|
|
2198
|
+
if (index !== -1) {
|
|
2199
|
+
rootNames.splice(index, 1, nextPath);
|
|
2200
|
+
}
|
|
2201
|
+
} else {
|
|
2202
|
+
const index = rootNames.indexOf(path);
|
|
2203
|
+
if (event === Watchr.FileEvent.unlink && index !== -1) {
|
|
2204
|
+
rootNames.splice(index, 1);
|
|
2205
|
+
} else if (event === Watchr.FileEvent.add && index === -1) {
|
|
2206
|
+
rootNames.push(path);
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
this.pendingChanges.length = 0;
|
|
2211
|
+
this.builderProgram = createIncrementalProgram({ rootNames, options: this.configuration.compilerOptions, projectReferences: this.configuration.projectReferences, configFileParsingDiagnostics: this.configuration.configFileParsingDiagnostics });
|
|
2212
|
+
await this.build();
|
|
2213
|
+
}
|
|
2214
|
+
/**
|
|
2215
|
+
* Resolves configuration by merging options with tsconfig.json.
|
|
2216
|
+
* @param directory - Project root directory
|
|
2217
|
+
* @param typeScriptOptions - Partial TypeScript options to merge
|
|
2218
|
+
* @returns Resolved configuration and TypeScript parser results
|
|
2219
|
+
*/
|
|
2220
|
+
static resolveConfiguration(directory, typeScriptOptions) {
|
|
2221
|
+
const configResult = readConfigFile(findConfigFile(directory, sys3.fileExists) ?? "./tsconfig.json", sys3.readFile);
|
|
2222
|
+
if (configResult.error !== void 0) {
|
|
2223
|
+
throw new ConfigurationError(formatDiagnostics([configResult.error], diagnosticsHost));
|
|
2224
|
+
}
|
|
2225
|
+
const bundle = typeScriptOptions.tsbuild?.bundle ?? configResult.config.tsbuild?.bundle ?? true;
|
|
2226
|
+
const platform2 = configResult.config.compilerOptions?.lib?.some(domPredicate) ? Platform.BROWSER : Platform.NODE;
|
|
2227
|
+
const noExternal = typeScriptOptions.tsbuild?.noExternal ?? configResult.config.tsbuild?.noExternal ?? [];
|
|
2228
|
+
const hasExplicitEntryPoints = typeScriptOptions.tsbuild?.entryPoints !== void 0 || configResult.config.tsbuild?.entryPoints !== void 0;
|
|
2229
|
+
let inferredEntryPoints;
|
|
2230
|
+
if (!hasExplicitEntryPoints && bundle) {
|
|
2231
|
+
const packageJsonContent = sys3.readFile(Paths.join(directory, "package.json"));
|
|
2232
|
+
if (packageJsonContent) {
|
|
2233
|
+
try {
|
|
2234
|
+
const pkgJson = JSON.parse(packageJsonContent);
|
|
2235
|
+
const outDir = typeScriptOptions.compilerOptions?.outDir ?? configResult.config.compilerOptions?.outDir ?? defaultOutDirectory;
|
|
2236
|
+
inferredEntryPoints = inferEntryPoints(pkgJson, outDir);
|
|
2237
|
+
} catch {
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
const defaultTsbuildConfig = {
|
|
2242
|
+
splitting: bundle,
|
|
2243
|
+
minify: false,
|
|
2244
|
+
force: false,
|
|
2245
|
+
bundle,
|
|
2246
|
+
sourceMap: typeScriptOptions.compilerOptions?.sourceMap ?? configResult.config.compilerOptions?.sourceMap ?? false,
|
|
2247
|
+
noExternal,
|
|
2248
|
+
packages: noExternal.length > 0 ? void 0 : platform2 === Platform.BROWSER ? "bundle" : "external",
|
|
2249
|
+
platform: platform2,
|
|
2250
|
+
dts: { resolve: platform2 !== Platform.NODE, entryPoints: bundle ? void 0 : [] },
|
|
2251
|
+
watch: { enabled: false, recursive: true, ignoreInitial: true, persistent: true },
|
|
2252
|
+
entryPoints: inferredEntryPoints ?? (bundle ? { [defaultEntryPoint]: defaultEntryFile } : { src: defaultSourceDirectory })
|
|
2253
|
+
};
|
|
2254
|
+
const baseConfig = {
|
|
2255
|
+
...configResult.config,
|
|
2256
|
+
clean: typeScriptOptions.tsbuild?.clean ?? configResult.config.tsbuild?.clean ?? true,
|
|
2257
|
+
tsbuild: {
|
|
2258
|
+
...defaultTsbuildConfig,
|
|
2259
|
+
...configResult.config.tsbuild,
|
|
2260
|
+
...typeScriptOptions.tsbuild,
|
|
2261
|
+
dts: { ...defaultTsbuildConfig.dts, ...configResult.config.tsbuild?.dts, ...typeScriptOptions.tsbuild?.dts },
|
|
2262
|
+
watch: { ...defaultTsbuildConfig.watch, ...configResult.config.tsbuild?.watch, ...typeScriptOptions.tsbuild?.watch }
|
|
2263
|
+
},
|
|
2264
|
+
compilerOptions: {
|
|
2265
|
+
...{ outDir: defaultOutDirectory, noEmit: false, sourceMap: false, incremental: true, tsBuildInfoFile: Paths.join(cacheDirectory, buildInfoFile), lib: [] },
|
|
2266
|
+
...configResult.config.compilerOptions,
|
|
2267
|
+
...typeScriptOptions.compilerOptions
|
|
2268
|
+
}
|
|
2269
|
+
};
|
|
2270
|
+
const { options, fileNames, errors } = parseJsonConfigFileContent(baseConfig, sys3, directory);
|
|
2271
|
+
return {
|
|
2272
|
+
...baseConfig,
|
|
2273
|
+
compilerOptions: {
|
|
2274
|
+
...baseConfig.compilerOptions,
|
|
2275
|
+
...options,
|
|
2276
|
+
...compilerOptionOverrides
|
|
2277
|
+
},
|
|
2278
|
+
directory,
|
|
2279
|
+
rootNames: fileNames,
|
|
2280
|
+
configFileParsingDiagnostics: errors,
|
|
2281
|
+
buildCache: baseConfig.compilerOptions.incremental ? new IncrementalBuildCache(directory, baseConfig.compilerOptions.tsBuildInfoFile) : void 0
|
|
2282
|
+
};
|
|
2283
|
+
}
|
|
2284
|
+
/**
|
|
2285
|
+
* Gets the entry points for the project.
|
|
2286
|
+
* @param entryPoints - The entry points to get.
|
|
2287
|
+
* @returns A promise that resolves to the entry points.
|
|
2288
|
+
*/
|
|
2289
|
+
async getEntryPoints(entryPoints) {
|
|
2290
|
+
const expandedEntryPoints = {};
|
|
2291
|
+
for (const [name, entryPoint] of Object.entries(entryPoints)) {
|
|
2292
|
+
const resolvedPath = Paths.absolute(this.directory, entryPoint);
|
|
2293
|
+
if (await Paths.isDirectory(resolvedPath)) {
|
|
2294
|
+
for (const file of await Files.readDirectory(resolvedPath)) {
|
|
2295
|
+
const filePath = Paths.join(resolvedPath, file);
|
|
2296
|
+
if (await Paths.isFile(filePath)) {
|
|
2297
|
+
expandedEntryPoints[Paths.parse(file).name] = filePath;
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
} else if (await Paths.isFile(resolvedPath)) {
|
|
2301
|
+
expandedEntryPoints[name] = resolvedPath;
|
|
2302
|
+
} else {
|
|
2303
|
+
throw new ConfigurationError(`Entry point does not exist: ${entryPoint}`);
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
return expandedEntryPoints;
|
|
2307
|
+
}
|
|
2308
|
+
/**
|
|
2309
|
+
* Gets the project dependency paths, cached after first call.
|
|
2310
|
+
* Reads package.json and caches it for reuse.
|
|
2311
|
+
* @returns A promise that resolves to an array of project dependency paths.
|
|
2312
|
+
*/
|
|
2313
|
+
getProjectDependencyPaths() {
|
|
2314
|
+
return this.dependencyPaths ??= Files.read(Paths.absolute(this.directory, "package.json")).then((content) => {
|
|
2315
|
+
const { dependencies = {}, peerDependencies = {} } = Json.parse(content);
|
|
2316
|
+
return [.../* @__PURE__ */ new Set([...Object.keys(dependencies), ...Object.keys(peerDependencies)])];
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
2319
|
+
/**
|
|
2320
|
+
* Handles build errors by logging unexpected errors and setting appropriate exit codes.
|
|
2321
|
+
* Expected build failures (TypeCheckError, BundleError) are already logged when they occur,
|
|
2322
|
+
* so this method only logs unexpected errors to avoid duplicate output.
|
|
2323
|
+
* @param error - The error to handle
|
|
2324
|
+
*/
|
|
2325
|
+
handleBuildError(error) {
|
|
2326
|
+
if (error instanceof BuildError) {
|
|
2327
|
+
if (!this.buildConfiguration.watch.enabled) {
|
|
2328
|
+
process.exitCode = error.code;
|
|
2329
|
+
}
|
|
2330
|
+
return;
|
|
2331
|
+
}
|
|
2332
|
+
Logger.error("Build failed", error);
|
|
2333
|
+
if (!this.buildConfiguration.watch.enabled) {
|
|
2334
|
+
process.exitCode = 1;
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
/**
|
|
2338
|
+
* Handles type errors in the project.
|
|
2339
|
+
* @param message - The message to display.
|
|
2340
|
+
* @param diagnostics - The diagnostics to handle.
|
|
2341
|
+
* @param projectDirectory - The project directory.
|
|
2342
|
+
*/
|
|
2343
|
+
static handleTypeErrors(message, diagnostics, projectDirectory) {
|
|
2344
|
+
Logger.error(formatDiagnosticsWithColorAndContext(diagnostics, diagnosticsHost));
|
|
2345
|
+
const filesWithErrors = /* @__PURE__ */ new Map();
|
|
2346
|
+
for (const { file, start } of diagnostics) {
|
|
2347
|
+
if (file !== void 0) {
|
|
2348
|
+
const { line } = file.getLineAndCharacterOfPosition(start ?? 0);
|
|
2349
|
+
const existing = filesWithErrors.get(file.fileName);
|
|
2350
|
+
if (existing !== void 0) {
|
|
2351
|
+
existing.count++;
|
|
2352
|
+
existing.line = Math.min(existing.line, line);
|
|
2353
|
+
} else {
|
|
2354
|
+
filesWithErrors.set(file.fileName, { count: 1, line });
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
const errorCount = diagnostics.length;
|
|
2359
|
+
const fileCount = filesWithErrors.size;
|
|
2360
|
+
const [[firstFileName, { line: firstLine }] = ["", { line: 0 }]] = filesWithErrors;
|
|
2361
|
+
const relativeFirstFileName = Paths.relative(projectDirectory, firstFileName);
|
|
2362
|
+
if (errorCount === 1) {
|
|
2363
|
+
Logger.error(`Found 1 error in ${relativeFirstFileName}:${firstLine + 1}${sys3.newLine}`);
|
|
2364
|
+
} else if (fileCount === 1) {
|
|
2365
|
+
Logger.error(`Found ${errorCount} errors in the same file, starting at: ${relativeFirstFileName}:${firstLine + 1}${sys3.newLine}`);
|
|
2366
|
+
} else {
|
|
2367
|
+
Logger.error(`Found ${errorCount} errors in ${fileCount} files.${sys3.newLine}`);
|
|
2368
|
+
Logger.error("Errors Files");
|
|
2369
|
+
for (const [fileName, { count, line }] of filesWithErrors) {
|
|
2370
|
+
Logger.error(` ${count} ${fileName}:${line + 1}`);
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
throw new TypeCheckError(message, formatDiagnostics(diagnostics, diagnosticsHost));
|
|
2374
|
+
}
|
|
2375
|
+
};
|
|
2376
|
+
_init3 = __decoratorStart(null);
|
|
2377
|
+
__decorateElement(_init3, 1, "build", _build_dec, _TypeScriptProject);
|
|
2378
|
+
__decorateElement(_init3, 1, "typeCheck", _typeCheck_dec, _TypeScriptProject);
|
|
2379
|
+
__decorateElement(_init3, 1, "transpile", _transpile_dec, _TypeScriptProject);
|
|
2380
|
+
__decorateElement(_init3, 1, "processDeclarations", _processDeclarations_dec, _TypeScriptProject);
|
|
2381
|
+
__decorateElement(_init3, 1, "triggerRebuild", _triggerRebuild_dec, _TypeScriptProject);
|
|
2382
|
+
_TypeScriptProject = __decorateElement(_init3, 0, "TypeScriptProject", _TypeScriptProject_decorators, _TypeScriptProject);
|
|
2383
|
+
__runInitializers(_init3, 1, _TypeScriptProject);
|
|
2384
|
+
var TypeScriptProject = _TypeScriptProject;
|
|
2385
|
+
export {
|
|
2386
|
+
TypeScriptProject
|
|
2387
|
+
};
|