@datadog/rspack-plugin 2.4.2 → 2.5.1-dev

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/dist/src/index.js CHANGED
@@ -1,3234 +1,5 @@
1
- 'use strict';
2
-
3
- var unplugin = require('unplugin');
4
- var chalk = require('chalk');
5
- var outdent = require('outdent');
6
- var path = require('path');
7
- var retry = require('async-retry');
8
- var fsp = require('fs/promises');
9
- var fs = require('fs');
10
- var buffer = require('buffer');
11
- var PQueue = require('p-queue');
12
- var stream = require('stream');
13
- var zlib = require('zlib');
14
- var prettyBytes = require('pretty-bytes');
15
- var perf_hooks = require('perf_hooks');
16
- var glob = require('glob');
17
- var simpleGit = require('simple-git');
18
- var url = require('url');
19
- var rspack = require('@rspack/core');
20
-
21
- const logPriority = {
22
- debug: 0,
23
- info: 1,
24
- warn: 2,
25
- error: 3,
26
- none: 4
27
- };
28
- const getLoggerFactory = (build, logLevel = "warn") => (name) => {
29
- const log = (text, type = "debug") => {
30
- let color = chalk.dim;
31
- let logFn = console.log;
32
- if (type === "error") {
33
- color = chalk.red;
34
- logFn = console.error;
35
- } else if (type === "warn") {
36
- color = chalk.yellow;
37
- logFn = console.warn;
38
- } else if (type === "info") {
39
- color = chalk.cyan;
40
- logFn = console.log;
41
- }
42
- const prefix = `[${type}|${name}]`;
43
- const content = typeof text === "string" ? text : JSON.stringify(text, null, 2);
44
- build.logs.push({ pluginName: name, type, message: content, time: Date.now() });
45
- if (type === "error") {
46
- build.errors.push(content);
47
- }
48
- if (type === "warn") {
49
- build.warnings.push(content);
50
- }
51
- if (logPriority[type] >= logPriority[logLevel]) {
52
- logFn(`${color(prefix)} ${content}`);
53
- }
54
- };
55
- return {
56
- getLogger: (subName) => {
57
- const logger = getLoggerFactory(build, logLevel);
58
- return logger(`${name}:${subName}`);
59
- },
60
- error: (text) => log(text, "error"),
61
- warn: (text) => log(text, "warn"),
62
- info: (text) => log(text, "info"),
63
- debug: (text) => log(text, "debug")
64
- };
65
- };
66
- const getContext = ({
67
- options,
68
- bundlerName,
69
- bundlerVersion,
70
- injections,
71
- version
72
- }) => {
73
- const cwd = process.cwd();
74
- const variant = bundlerName === "webpack" ? bundlerVersion.split(".")[0] : "";
75
- const build = {
76
- errors: [],
77
- warnings: [],
78
- logs: []
79
- };
80
- const context = {
81
- auth: options.auth,
82
- pluginNames: [],
83
- bundler: {
84
- name: bundlerName,
85
- fullName: `${bundlerName}${variant}`,
86
- variant,
87
- outDir: cwd,
88
- version: bundlerVersion
89
- },
90
- build,
91
- cwd,
92
- inject: (item) => {
93
- injections.push(item);
94
- },
95
- start: Date.now(),
96
- version
97
- };
98
- return context;
99
- };
100
- const validateOptions$2 = (options = {}) => {
101
- return {
102
- auth: {},
103
- disableGit: false,
104
- logLevel: "warn",
105
- ...options
106
- };
107
- };
108
-
109
- const decomposePath = (options, context, sourcemapFilePath) => {
110
- if (path.extname(sourcemapFilePath) !== ".map") {
111
- throw new Error(`The file ${chalk.green.bold(sourcemapFilePath)} is not a sourcemap.`);
112
- }
113
- const minifiedFilePath = sourcemapFilePath.replace(/\.map$/, "");
114
- const relativePath = minifiedFilePath.replace(context.bundler.outDir, "");
115
- const minifiedUrl = options.minifiedPathPrefix ? path.join(options.minifiedPathPrefix, relativePath) : relativePath;
116
- return {
117
- minifiedFilePath,
118
- minifiedUrl,
119
- relativePath
120
- };
121
- };
122
- const getSourcemapsFiles = (options, context) => {
123
- if (!context.build.outputs || context.build.outputs.length === 0) {
124
- throw new Error("No output files found.");
125
- }
126
- const sourcemapFilesList = context.build.outputs.filter((file) => file.filepath.endsWith(".map")).map((file) => file.filepath);
127
- const sourcemapFiles = sourcemapFilesList.map((sourcemapFilePath) => {
128
- return {
129
- ...decomposePath(options, context, sourcemapFilePath),
130
- sourcemapFilePath,
131
- minifiedPathPrefix: options.minifiedPathPrefix
132
- };
133
- });
134
- return sourcemapFiles;
135
- };
136
-
137
- const INJECTED_FILE = "__datadog-helper-file";
138
-
139
- const formatDuration = (duration) => {
140
- const days = Math.floor(duration / 1e3 / 60 / 60 / 24);
141
- const usedDuration = duration - days * 24 * 60 * 60 * 1e3;
142
- const d = new Date(usedDuration);
143
- const hours = d.getUTCHours();
144
- const minutes = d.getUTCMinutes();
145
- const seconds = d.getUTCSeconds();
146
- const milliseconds = d.getUTCMilliseconds();
147
- return `${days ? `${days}d ` : ""}${hours ? `${hours}h ` : ""}${minutes ? `${minutes}m ` : ""}${seconds ? `${seconds}s ` : ""}${milliseconds ? `${milliseconds}ms` : ""}`.trim();
148
- };
149
- const getResolvedPath = (filepath) => {
150
- try {
151
- return require.resolve(filepath);
152
- } catch (e) {
153
- return filepath;
154
- }
155
- };
156
- const ERROR_CODES_NO_RETRY = [400, 403, 413];
157
- const NB_RETRIES = 5;
158
- const doRequest = (opts) => {
159
- const { url, method = "GET", getData, onRetry, type = "text" } = opts;
160
- return retry(
161
- async (bail, attempt) => {
162
- let response;
163
- try {
164
- const requestInit = {
165
- method,
166
- // This is needed for sending body in NodeJS' Fetch.
167
- // https://github.com/nodejs/node/issues/46221
168
- duplex: "half"
169
- };
170
- if (typeof getData === "function") {
171
- const { data, headers } = await getData();
172
- requestInit.body = data;
173
- requestInit.headers = headers;
174
- }
175
- response = await fetch(url, requestInit);
176
- } catch (error) {
177
- bail(error);
178
- return {};
179
- }
180
- if (!response.ok) {
181
- const errorMessage = `HTTP ${response.status} ${response.statusText}`;
182
- if (ERROR_CODES_NO_RETRY.includes(response.status)) {
183
- bail(new Error(errorMessage));
184
- return {};
185
- } else {
186
- throw new Error(errorMessage);
187
- }
188
- }
189
- try {
190
- let result;
191
- if (type === "json") {
192
- result = await response.json();
193
- } else {
194
- result = await response.text();
195
- }
196
- return result;
197
- } catch (error) {
198
- bail(error);
199
- return {};
200
- }
201
- },
202
- {
203
- retries: NB_RETRIES,
204
- onRetry
205
- }
206
- );
207
- };
208
- const truncateString = (str, maxLength = 60, placeholder = "[...]") => {
209
- if (str.length <= maxLength) {
210
- return str;
211
- }
212
- const stringLength = Math.max(4, maxLength - placeholder.length);
213
- const leftStop = Math.min(10, Math.floor(stringLength / 2));
214
- const rightStop = stringLength - leftStop;
215
- return `${str.slice(0, leftStop)}${placeholder}${str.slice(-rightStop)}`;
216
- };
217
- const isInjectionFile = (filename) => filename.includes(INJECTED_FILE);
218
- const rm = async (dir) => {
219
- return fsp.rm(dir, { force: true, maxRetries: 3, recursive: true });
220
- };
221
- const mkdir = async (dir) => {
222
- return fsp.mkdir(dir, { recursive: true });
223
- };
224
- const outputFile = async (filepath, data) => {
225
- await mkdir(path.dirname(filepath));
226
- await fsp.writeFile(filepath, data, { encoding: "utf-8" });
227
- };
228
- const outputJson = async (filepath, data) => {
229
- const dataString = JSON.stringify(data, null, 4);
230
- return outputFile(filepath, dataString);
231
- };
232
-
233
- const SLASH_RX = /[/]+|[\\]+/g;
234
- const SLASH_TRIM_RX = /^[/]+|^[\\]+|[/]+$|[\\]+$/g;
235
- const prefixRepeat = (filePath, prefix) => {
236
- const pathParts = filePath.replace(SLASH_TRIM_RX, "").split(SLASH_RX);
237
- const prefixParts = prefix.replace(SLASH_TRIM_RX, "").split(SLASH_RX);
238
- const normalizedPath = pathParts.join("/");
239
- let result = "";
240
- for (let i = 0; i < prefixParts.length; i += 1) {
241
- const partialPrefix = prefixParts.slice(-i).join("/");
242
- if (normalizedPath.startsWith(partialPrefix)) {
243
- result = partialPrefix;
244
- }
245
- }
246
- return result;
247
- };
248
- const checkFile = async (filePath) => {
249
- const validity = {
250
- empty: false,
251
- exists: true
252
- };
253
- try {
254
- const stats = await fs.promises.stat(filePath);
255
- if (stats.size === 0) {
256
- validity.empty = true;
257
- }
258
- } catch (error) {
259
- if (error.code === "ENOENT") {
260
- validity.exists = false;
261
- } else {
262
- throw error;
263
- }
264
- }
265
- return validity;
266
- };
267
- const getSourcemapValidity = async (sourcemap, prefix) => {
268
- const [resultMinFile, resultSourcemap] = await Promise.all([
269
- checkFile(sourcemap.minifiedFilePath),
270
- checkFile(sourcemap.sourcemapFilePath)
271
- ]);
272
- return {
273
- file: resultMinFile,
274
- sourcemap: resultSourcemap,
275
- repeatedPrefix: prefixRepeat(sourcemap.relativePath, prefix)
276
- };
277
- };
278
- const getPayload = async (sourcemap, metadata, prefix, git) => {
279
- const validity = await getSourcemapValidity(sourcemap, prefix);
280
- const errors = [];
281
- const warnings = [];
282
- const content = /* @__PURE__ */ new Map([
283
- [
284
- "event",
285
- {
286
- type: "string",
287
- options: {
288
- contentType: "application/json",
289
- filename: "event"
290
- },
291
- value: JSON.stringify({
292
- ...metadata,
293
- minified_url: sourcemap.minifiedUrl
294
- })
295
- }
296
- ],
297
- [
298
- "source_map",
299
- {
300
- type: "file",
301
- path: sourcemap.sourcemapFilePath,
302
- options: { filename: "source_map", contentType: "application/json" }
303
- }
304
- ],
305
- [
306
- "minified_file",
307
- {
308
- type: "file",
309
- path: sourcemap.minifiedFilePath,
310
- options: { filename: "minified_file", contentType: "application/javascript" }
311
- }
312
- ]
313
- ]);
314
- if (git) {
315
- try {
316
- content.set("repository", {
317
- type: "string",
318
- options: {
319
- contentType: "application/json",
320
- filename: "repository"
321
- },
322
- value: JSON.stringify({
323
- data: [
324
- {
325
- files: git.trackedFilesMatcher.matchSourcemap(
326
- sourcemap.sourcemapFilePath,
327
- (reason) => {
328
- warnings.push(
329
- `${path.basename(sourcemap.sourcemapFilePath)}: "${reason}"`
330
- );
331
- }
332
- ),
333
- hash: git.hash,
334
- repository_url: git.remote
335
- }
336
- ],
337
- // NOTE: Make sure to update the version if the format of the JSON payloads changes in any way.
338
- version: 1
339
- })
340
- });
341
- } catch (error) {
342
- warnings.push(
343
- `Could not attach git data for sourcemap ${sourcemap.sourcemapFilePath}: ${error.message}`
344
- );
345
- }
346
- }
347
- if (validity.file.empty) {
348
- errors.push(`Minified file is empty: ${sourcemap.minifiedFilePath}`);
349
- }
350
- if (!validity.file.exists) {
351
- errors.push(`Minified file not found: ${sourcemap.minifiedFilePath}`);
352
- }
353
- if (validity.sourcemap.empty) {
354
- errors.push(`Sourcemap file is empty: ${sourcemap.sourcemapFilePath}`);
355
- }
356
- if (!validity.sourcemap.exists) {
357
- errors.push(`Sourcemap file not found: ${sourcemap.sourcemapFilePath}`);
358
- }
359
- if (validity.repeatedPrefix) {
360
- warnings.push(
361
- `The minified file path contains a repeated pattern with the minified path prefix: ${validity.repeatedPrefix}`
362
- );
363
- }
364
- return { content, errors, warnings };
365
- };
366
-
367
- const green = chalk.green.bold;
368
- const yellow = chalk.yellow.bold;
369
- const red = chalk.red.bold;
370
- const getFile = async (path, options) => {
371
- if (typeof fs.openAsBlob === "function") {
372
- const blob = await fs.openAsBlob(path, { type: options.contentType });
373
- return new buffer.File([blob], options.filename);
374
- } else {
375
- const stream$1 = stream.Readable.toWeb(fs.createReadStream(path));
376
- const blob = await new Response(stream$1).blob();
377
- const file = new buffer.File([blob], options.filename, { type: options.contentType });
378
- return file;
379
- }
380
- };
381
- const getData = (payload, defaultHeaders = {}) => async () => {
382
- const form = new FormData();
383
- const gz = zlib.createGzip();
384
- for (const [key, content] of payload.content) {
385
- const value = content.type === "file" ? (
386
- // eslint-disable-next-line no-await-in-loop
387
- await getFile(content.path, content.options)
388
- ) : new Blob([content.value], { type: content.options.contentType });
389
- form.append(key, value, content.options.filename);
390
- }
391
- const req = new Request("fake://url", { method: "POST", body: form });
392
- const formStream = stream.Readable.fromWeb(req.body);
393
- const data = formStream.pipe(gz);
394
- const headers = {
395
- "Content-Encoding": "gzip",
396
- ...defaultHeaders,
397
- ...Object.fromEntries(req.headers.entries())
398
- };
399
- return { data, headers };
400
- };
401
- const upload = async (payloads, options, context, log) => {
402
- const errors = [];
403
- const warnings = [];
404
- if (!context.auth?.apiKey) {
405
- errors.push({ error: new Error("No authentication token provided") });
406
- return { errors, warnings };
407
- }
408
- if (payloads.length === 0) {
409
- warnings.push("No sourcemaps to upload");
410
- return { errors, warnings };
411
- }
412
- const Queue = PQueue.default ? PQueue.default : PQueue;
413
- const queue = new Queue({ concurrency: options.maxConcurrency });
414
- const defaultHeaders = {
415
- "DD-API-KEY": context.auth.apiKey,
416
- "DD-EVP-ORIGIN": `${context.bundler.fullName}-build-plugin_sourcemaps`,
417
- "DD-EVP-ORIGIN-VERSION": context.version
418
- };
419
- const addPromises = [];
420
- for (const payload of payloads) {
421
- const metadata = {
422
- sourcemap: payload.content.get("source_map")?.path.replace(
423
- context.bundler.outDir,
424
- "."
425
- ),
426
- file: payload.content.get("minified_file")?.path.replace(
427
- context.bundler.outDir,
428
- "."
429
- )
430
- };
431
- log.debug(`Queuing ${green(metadata.sourcemap)} | ${green(metadata.file)}`);
432
- addPromises.push(
433
- queue.add(async () => {
434
- try {
435
- await doRequest({
436
- url: options.intakeUrl,
437
- method: "POST",
438
- getData: getData(payload, defaultHeaders),
439
- // On retry we store the error as a warning.
440
- onRetry: (error, attempt) => {
441
- const warningMessage = `Failed to upload ${yellow(metadata.sourcemap)} | ${yellow(metadata.file)}:
442
- ${error.message}
443
- Retrying ${attempt}/${NB_RETRIES}`;
444
- warnings.push(warningMessage);
445
- log.warn(warningMessage);
446
- }
447
- });
448
- log.debug(`Sent ${green(metadata.sourcemap)} | ${green(metadata.file)}`);
449
- } catch (e) {
450
- errors.push({ metadata, error: e });
451
- if (options.bailOnError === true) {
452
- throw e;
453
- }
454
- }
455
- })
456
- );
457
- }
458
- await Promise.all(addPromises);
459
- await queue.onIdle();
460
- return { warnings, errors };
461
- };
462
- const sendSourcemaps = async (sourcemaps, options, context, log) => {
463
- const start = Date.now();
464
- const prefix = options.minifiedPathPrefix;
465
- const metadata = {
466
- git_repository_url: context.git?.remote,
467
- git_commit_sha: context.git?.hash,
468
- plugin_version: context.version,
469
- project_path: context.bundler.outDir,
470
- service: options.service,
471
- type: "js_sourcemap",
472
- version: options.releaseVersion
473
- };
474
- const payloads = await Promise.all(
475
- sourcemaps.map((sourcemap) => getPayload(sourcemap, metadata, prefix, context.git))
476
- );
477
- const errors = payloads.map((payload) => payload.errors).flat();
478
- const warnings = payloads.map((payload) => payload.warnings).flat();
479
- if (warnings.length > 0) {
480
- log.warn(`Warnings while preparing payloads:
481
- - ${warnings.join("\n - ")}`);
482
- }
483
- if (errors.length > 0) {
484
- const errorMsg = `Failed to prepare payloads, aborting upload :
485
- - ${errors.join("\n - ")}`;
486
- log.error(errorMsg);
487
- if (options.bailOnError === true) {
488
- throw new Error(errorMsg);
489
- }
490
- return;
491
- }
492
- const { errors: uploadErrors, warnings: uploadWarnings } = await upload(
493
- payloads,
494
- options,
495
- context,
496
- log
497
- );
498
- log.info(
499
- `Done uploading ${green(sourcemaps.length.toString())} sourcemaps in ${green(formatDuration(Date.now() - start))}.`
500
- );
501
- if (uploadErrors.length > 0) {
502
- const listOfErrors = ` - ${uploadErrors.map(({ metadata: fileMetadata, error }) => {
503
- if (fileMetadata) {
504
- return `${red(fileMetadata.file)} | ${red(fileMetadata.sourcemap)} : ${error.message}`;
505
- }
506
- return error.message;
507
- }).join("\n - ")}`;
508
- const errorMsg = `Failed to upload some sourcemaps:
509
- ${listOfErrors}`;
510
- log.error(errorMsg);
511
- if (options.bailOnError === true) {
512
- throw new Error(errorMsg);
513
- }
514
- }
515
- if (uploadWarnings.length > 0) {
516
- log.warn(`Warnings while uploading sourcemaps:
517
- - ${warnings.join("\n - ")}`);
518
- }
519
- };
520
-
521
- const uploadSourcemaps = async (options, context, log) => {
522
- const green = chalk.green.bold;
523
- const configurationString = Object.entries(options.sourcemaps).map(([key, value]) => ` - ${key}: ${green(value.toString())}`).join("\n");
524
- const sourcemaps = getSourcemapsFiles(options.sourcemaps, context);
525
- const summary = outdent.outdent`
526
- Uploading ${green(sourcemaps.length.toString())} sourcemaps with configuration:
527
- ${configurationString}
528
- `;
529
- log.info(summary);
530
- await sendSourcemaps(sourcemaps, options.sourcemaps, context, log);
531
- };
532
-
533
- const CONFIG_KEY$1 = "rum";
534
- const PLUGIN_NAME$5 = "datadog-rum-plugin";
535
-
536
- const defaultIntakeUrl = `https://sourcemap-intake.${process.env.DATADOG_SITE || "datadoghq.com"}/api/v2/srcmap`;
537
- const validateOptions$1 = (config, log) => {
538
- const errors = [];
539
- const sourcemapsResults = validateSourcemapsOptions(config);
540
- errors.push(...sourcemapsResults.errors);
541
- if (errors.length) {
542
- log.error(`
543
- - ${errors.join("\n - ")}`);
544
- throw new Error(`Invalid configuration for ${PLUGIN_NAME$5}.`);
545
- }
546
- const toReturn = {
547
- ...config[CONFIG_KEY$1],
548
- sourcemaps: void 0
549
- };
550
- if (sourcemapsResults.config) {
551
- toReturn.sourcemaps = sourcemapsResults.config;
552
- }
553
- return toReturn;
554
- };
555
- const validateMinifiedPathPrefix = (minifiedPathPrefix) => {
556
- let host;
557
- try {
558
- const objUrl = new URL(minifiedPathPrefix);
559
- host = objUrl.host;
560
- } catch {
561
- }
562
- if (!host && !minifiedPathPrefix.startsWith("/")) {
563
- return false;
564
- }
565
- return true;
566
- };
567
- const validateSourcemapsOptions = (config) => {
568
- const red = chalk.bold.red;
569
- const validatedOptions = config[CONFIG_KEY$1] || {};
570
- const toReturn = {
571
- errors: []
572
- };
573
- if (validatedOptions.sourcemaps) {
574
- if (!validatedOptions.sourcemaps.releaseVersion) {
575
- toReturn.errors.push(`${red("sourcemaps.releaseVersion")} is required.`);
576
- }
577
- if (!validatedOptions.sourcemaps.service) {
578
- toReturn.errors.push(`${red("sourcemaps.service")} is required.`);
579
- }
580
- if (!validatedOptions.sourcemaps.minifiedPathPrefix) {
581
- toReturn.errors.push(`${red("sourcemaps.minifiedPathPrefix")} is required.`);
582
- }
583
- if (validatedOptions.sourcemaps.minifiedPathPrefix) {
584
- if (!validateMinifiedPathPrefix(validatedOptions.sourcemaps.minifiedPathPrefix)) {
585
- toReturn.errors.push(
586
- `${red("sourcemaps.minifiedPathPrefix")} must be a valid URL or start with '/'.`
587
- );
588
- }
589
- }
590
- const sourcemapsWithDefaults = {
591
- bailOnError: false,
592
- dryRun: false,
593
- maxConcurrency: 20,
594
- intakeUrl: process.env.DATADOG_SOURCEMAP_INTAKE_URL || validatedOptions.sourcemaps.intakeUrl || defaultIntakeUrl,
595
- ...validatedOptions.sourcemaps
596
- };
597
- toReturn.config = sourcemapsWithDefaults;
598
- }
599
- return toReturn;
600
- };
601
-
602
- const getPlugins$1 = (opts, context, log) => {
603
- const rumOptions = validateOptions$1(opts, log);
604
- return [
605
- {
606
- name: "datadog-rum-sourcemaps-plugin",
607
- enforce: "post",
608
- async writeBundle() {
609
- if (rumOptions.disabled) {
610
- return;
611
- }
612
- if (rumOptions.sourcemaps) {
613
- await uploadSourcemaps(rumOptions, context, log);
614
- }
615
- }
616
- }
617
- ];
618
- };
619
-
620
- const CONFIG_KEY = "telemetry";
621
- const PLUGIN_NAME$4 = `datadog-telemetry-plugin`;
622
-
623
- const filterTreeMetrics = (metric) => (
624
- // Remove tree metrics because way too verbose
625
- !/modules\.tree\.(count|size)$/.test(metric.metric) ? metric : null
626
- );
627
- const filterSourcemapsAndNodeModules = (metric) => metric.tags.some(
628
- (tag) => (
629
- // Remove sourcemaps.
630
- /^assetName:.*\.map$/.test(tag) || // Remove third parties.
631
- /^moduleName:\/node_modules/.test(tag)
632
- )
633
- ) ? null : metric;
634
- const filterMetricsOnThreshold = (metric) => {
635
- const thresholds = {
636
- size: 1e5,
637
- count: 10,
638
- duration: 1e3
639
- };
640
- if (/(entries|loaders|warnings|errors)\.count$/.test(metric.metric)) {
641
- thresholds.count = 0;
642
- }
643
- if (/(modules\.(dependencies|dependents)$)/.test(metric.metric)) {
644
- thresholds.count = 30;
645
- }
646
- if (/modules\.tree\.count$/.test(metric.metric)) {
647
- thresholds.count = 150;
648
- }
649
- if (/modules\.tree\.size$/.test(metric.metric)) {
650
- thresholds.size = 15e5;
651
- }
652
- if (/entries\.size$/.test(metric.metric)) {
653
- thresholds.size = 0;
654
- }
655
- if (/entries\.modules\.count$/.test(metric.metric)) {
656
- thresholds.count = 0;
657
- }
658
- return metric.value > thresholds[metric.type] ? metric : null;
659
- };
660
- const defaultFilters = [
661
- filterTreeMetrics,
662
- filterSourcemapsAndNodeModules,
663
- filterMetricsOnThreshold
664
- ];
665
-
666
- const validateOptions = (opts) => {
667
- const options = opts[CONFIG_KEY] || {};
668
- const endPoint = options.endPoint || "https://app.datadoghq.com";
669
- return {
670
- disabled: false,
671
- enableTracing: false,
672
- filters: defaultFilters,
673
- output: false,
674
- prefix: "",
675
- tags: [],
676
- ...options,
677
- endPoint: endPoint.startsWith("http") ? endPoint : `https://${endPoint}`
678
- };
679
- };
680
- const getMetric = (metric, opts) => ({
681
- type: "gauge",
682
- tags: [...metric.tags, ...opts.tags],
683
- metric: `${opts.prefix ? `${opts.prefix}.` : ""}${metric.metric}`,
684
- points: [[opts.timestamp, metric.value]]
685
- });
686
- const getOptionsDD = (options) => {
687
- return {
688
- timestamp: Math.floor((options.timestamp || Date.now()) / 1e3),
689
- tags: options.tags,
690
- prefix: options.prefix,
691
- filters: options.filters
692
- };
693
- };
694
- const getPluginName = (opts) => typeof opts === "string" ? opts : opts.name;
695
- const formatCwd = (cwd = "") => {
696
- return cwd.endsWith("/") ? cwd : `${cwd}/`;
697
- };
698
- const getDisplayName = (name, cwd) => {
699
- let toReturn = name;
700
- name.split(formatCwd(cwd));
701
- return toReturn.split("!").pop().replace(/(.*)?\/node_modules\//, "/node_modules/").replace(/^((\.)*\/)+/, "");
702
- };
703
- const formatModuleName = (name, context) => name.split("!").pop().replace(formatCwd(context), "./");
704
- const getModulePath = (module, compilation) => {
705
- let path = module.userRequest;
706
- if (!path) {
707
- let issuer;
708
- if (compilation.moduleGraph && typeof compilation.moduleGraph.getIssuer === "function") {
709
- issuer = compilation.moduleGraph.getIssuer(module);
710
- } else {
711
- issuer = module.issuer;
712
- }
713
- path = issuer?.userRequest;
714
- if (!path) {
715
- path = module._identifier?.split("!").pop();
716
- }
717
- }
718
- return path || "unknown";
719
- };
720
- const getModuleName = (module, compilation, context) => {
721
- let name = module.name || module.userRequest;
722
- if (!name) {
723
- name = getModulePath(module, compilation);
724
- }
725
- return formatModuleName(name || "no-name", context);
726
- };
727
- const formatLoaderName = (loader) => loader.replace(/^.*\/node_modules\/(@[a-z0-9][\w-.]+\/[a-z0-9][\w-.]*|[^/]+).*$/, "$1");
728
- const getLoaderNames = (module) => (module.loaders || []).map((l) => l.loader || l).map(formatLoaderName);
729
- const getValueContext = (args) => {
730
- return args.map((arg) => ({
731
- type: arg?.constructor?.name ?? typeof arg,
732
- name: arg?.name,
733
- value: typeof arg === "string" ? arg : void 0
734
- }));
735
- };
736
-
737
- const addPluginMetrics = (plugins, metrics) => {
738
- metrics.add({
739
- metric: "plugins.count",
740
- type: "count",
741
- value: plugins.size,
742
- tags: []
743
- });
744
- for (const plugin of plugins.values()) {
745
- let pluginDuration = 0;
746
- let pluginCount = 0;
747
- for (const hook of Object.values(plugin.events)) {
748
- let hookDuration = 0;
749
- pluginCount += hook.values.length;
750
- for (const v of hook.values) {
751
- const duration = v.end - v.start;
752
- hookDuration += duration;
753
- pluginDuration += duration;
754
- }
755
- metrics.add({
756
- metric: "plugins.hooks.duration",
757
- type: "duration",
758
- value: hookDuration,
759
- tags: [`pluginName:${plugin.name}`, `hookName:${hook.name}`]
760
- }).add({
761
- metric: "plugins.hooks.increment",
762
- type: "count",
763
- value: hook.values.length,
764
- tags: [`pluginName:${plugin.name}`, `hookName:${hook.name}`]
765
- });
766
- }
767
- metrics.add({
768
- metric: "plugins.duration",
769
- type: "duration",
770
- value: pluginDuration,
771
- tags: [`pluginName:${plugin.name}`]
772
- }).add({
773
- metric: "plugins.increment",
774
- type: "count",
775
- value: pluginCount,
776
- tags: [`pluginName:${plugin.name}`]
777
- });
778
- }
779
- };
780
- const addLoaderMetrics = (loaders, metrics) => {
781
- metrics.add({
782
- metric: "loaders.count",
783
- type: "count",
784
- value: loaders.size,
785
- tags: []
786
- });
787
- for (const loader of loaders.values()) {
788
- metrics.add({
789
- metric: "loaders.duration",
790
- type: "duration",
791
- value: loader.duration,
792
- tags: [`loaderName:${loader.name}`]
793
- }).add({
794
- metric: "loaders.increment",
795
- type: "count",
796
- value: loader.increment,
797
- tags: [`loaderName:${loader.name}`]
798
- });
799
- }
800
- };
801
-
802
- const addUniversalMetrics = (globalContext, metrics) => {
803
- const inputs = globalContext.build.inputs || [];
804
- const outputs = globalContext.build.outputs || [];
805
- const entries = globalContext.build.entries || [];
806
- const nbWarnings = globalContext.build.warnings.length;
807
- const nbErrors = globalContext.build.errors.length;
808
- const duration = globalContext.build.duration;
809
- const entriesPerInput = /* @__PURE__ */ new Map();
810
- const assetsPerInput = /* @__PURE__ */ new Map();
811
- const entriesPerAsset = /* @__PURE__ */ new Map();
812
- for (const entry of entries) {
813
- for (const input of entry.inputs) {
814
- if (!entriesPerInput.has(input.filepath)) {
815
- entriesPerInput.set(input.filepath, []);
816
- }
817
- entriesPerInput.get(input.filepath).push(entry.name);
818
- }
819
- for (const output of entry.outputs) {
820
- const cleanAssetName = output.filepath.replace(/\.map$/, "");
821
- if (!entriesPerAsset.has(cleanAssetName)) {
822
- entriesPerAsset.set(cleanAssetName, []);
823
- }
824
- entriesPerAsset.get(cleanAssetName).push(entry.name);
825
- }
826
- }
827
- for (const output of outputs) {
828
- for (const input of output.inputs) {
829
- if (!assetsPerInput.has(input.filepath)) {
830
- assetsPerInput.set(input.filepath, []);
831
- }
832
- assetsPerInput.get(input.filepath).push(output.name);
833
- }
834
- }
835
- metrics.add({
836
- metric: "assets.count",
837
- type: "count",
838
- value: outputs.length,
839
- tags: []
840
- }).add({
841
- metric: "entries.count",
842
- type: "count",
843
- value: entries.length,
844
- tags: []
845
- }).add({
846
- metric: "errors.count",
847
- type: "count",
848
- value: nbErrors,
849
- tags: []
850
- }).add({
851
- metric: "modules.count",
852
- type: "count",
853
- value: inputs.length,
854
- tags: []
855
- }).add({
856
- metric: "warnings.count",
857
- type: "count",
858
- value: nbWarnings,
859
- tags: []
860
- });
861
- if (duration) {
862
- metrics.add({
863
- metric: "compilation.duration",
864
- type: "duration",
865
- value: duration,
866
- tags: []
867
- });
868
- }
869
- for (const input of inputs) {
870
- const tags = [`moduleName:${input.name}`, `moduleType:${input.type}`];
871
- if (entriesPerInput.has(input.filepath)) {
872
- tags.push(
873
- ...entriesPerInput.get(input.filepath).map((entryName) => `entryName:${entryName}`)
874
- );
875
- }
876
- if (assetsPerInput.has(input.filepath)) {
877
- tags.push(
878
- ...assetsPerInput.get(input.filepath).map((assetName) => `assetName:${assetName}`)
879
- );
880
- }
881
- metrics.add({
882
- metric: "modules.size",
883
- type: "size",
884
- value: input.size,
885
- tags
886
- }).add({
887
- metric: "modules.dependencies",
888
- type: "count",
889
- value: input.dependencies.size,
890
- tags
891
- }).add({
892
- metric: "modules.dependents",
893
- type: "count",
894
- value: input.dependents.size,
895
- tags
896
- });
897
- }
898
- for (const output of outputs) {
899
- const tags = [`assetName:${output.name}`, `assetType:${output.type}`];
900
- const cleanAssetName = output.filepath.replace(/\.map$/, "");
901
- if (entriesPerAsset.has(cleanAssetName)) {
902
- tags.push(
903
- ...entriesPerAsset.get(cleanAssetName).map((entryName) => `entryName:${entryName}`)
904
- );
905
- }
906
- metrics.add({
907
- metric: "assets.size",
908
- type: "size",
909
- value: output.size,
910
- tags
911
- }).add({
912
- metric: "assets.modules.count",
913
- type: "count",
914
- value: output.inputs.length,
915
- tags
916
- });
917
- }
918
- for (const entry of entries) {
919
- const tags = [`entryName:${entry.name}`];
920
- metrics.add({
921
- metric: "entries.size",
922
- type: "size",
923
- value: entry.size,
924
- tags
925
- }).add({
926
- metric: "entries.modules.count",
927
- type: "count",
928
- value: entry.inputs.length,
929
- tags
930
- }).add({
931
- metric: "entries.assets.count",
932
- type: "count",
933
- value: entry.outputs.length,
934
- tags
935
- });
936
- }
937
- return metrics;
938
- };
939
- const addMetrics = (globalContext, optionsDD, metricsToSend, report) => {
940
- const metrics = /* @__PURE__ */ new Set();
941
- if (report) {
942
- const { timings } = report;
943
- if (timings) {
944
- if (timings.tapables) {
945
- addPluginMetrics(timings.tapables, metrics);
946
- }
947
- if (timings.loaders) {
948
- addLoaderMetrics(timings.loaders, metrics);
949
- }
950
- }
951
- }
952
- addUniversalMetrics(globalContext, metrics);
953
- for (const metric of metrics) {
954
- if (optionsDD.filters?.length) {
955
- let filteredMetric = metric;
956
- for (const filter of optionsDD.filters) {
957
- if (!filteredMetric) {
958
- break;
959
- }
960
- filteredMetric = filter(metric);
961
- }
962
- if (filteredMetric) {
963
- metricsToSend.add(getMetric(filteredMetric, optionsDD));
964
- }
965
- } else {
966
- metricsToSend.add(getMetric(metric, optionsDD));
967
- }
968
- }
969
- };
970
-
971
- const outputFiles = async (data, outputOptions, log, cwd) => {
972
- if (typeof outputOptions !== "string" && typeof outputOptions !== "object" && !outputOptions) {
973
- return;
974
- }
975
- const { report, metrics } = data;
976
- const startWriting = Date.now();
977
- let destination = "";
978
- const files = {
979
- timings: true,
980
- metrics: true
981
- };
982
- if (typeof outputOptions === "object") {
983
- destination = outputOptions.destination;
984
- files.timings = outputOptions.timings || false;
985
- files.metrics = outputOptions.metrics || false;
986
- } else if (typeof outputOptions === "string") {
987
- destination = outputOptions;
988
- }
989
- const outputPath = path.resolve(cwd, destination);
990
- try {
991
- const errors = {};
992
- const filesToWrite = {};
993
- if (files.timings && report?.timings) {
994
- filesToWrite.timings = {
995
- content: {
996
- tapables: report.timings.tapables ? Array.from(report.timings.tapables.values()) : null,
997
- loaders: report.timings.loaders ? Array.from(report.timings.loaders.values()) : null,
998
- modules: report.timings.modules ? Array.from(report.timings.modules.values()) : null
999
- }
1000
- };
1001
- }
1002
- if (files.metrics) {
1003
- filesToWrite.metrics = { content: Array.from(metrics) };
1004
- }
1005
- const proms = Object.entries(filesToWrite).map(async ([filename, file]) => {
1006
- const start = Date.now();
1007
- log.debug(`Start writing ${filename}.json.`);
1008
- try {
1009
- await outputJson(path.join(outputPath, `${filename}.json`), file.content);
1010
- log.debug(`Wrote ${filename}.json in ${formatDuration(Date.now() - start)}`);
1011
- } catch (e) {
1012
- log.error(
1013
- `Failed to write ${filename}.json in ${formatDuration(Date.now() - start)}`
1014
- );
1015
- errors[filename] = e;
1016
- }
1017
- });
1018
- await Promise.all(proms);
1019
- log.debug(`Wrote files in ${formatDuration(Date.now() - startWriting)}.`);
1020
- const fileErrored = Object.keys(errors);
1021
- if (fileErrored.length) {
1022
- log.error(
1023
- `Couldn't write files.
1024
- ${fileErrored.map(
1025
- (file) => ` - ${file}: ${errors[file].toString()}`
1026
- )}`
1027
- );
1028
- }
1029
- } catch (e) {
1030
- log.error(`Couldn't write files. ${e}`);
1031
- }
1032
- };
1033
-
1034
- const EXTENSION_RX = /\.(?!.*(?:\.|\/|\\))(\w{1,})/g;
1035
- const QUERY_RX = /(\?|%3F|\|)+/gi;
1036
- const getExtension = (filepath) => {
1037
- EXTENSION_RX.lastIndex = 0;
1038
- return EXTENSION_RX.exec(filepath)?.[1];
1039
- };
1040
- const getType = (name) => {
1041
- if (name === "unknown") {
1042
- return name;
1043
- }
1044
- if (name.includes("webpack/runtime")) {
1045
- return "runtime";
1046
- }
1047
- return getExtension(cleanPath(name)) || "unknown";
1048
- };
1049
- const serializeBuildReport = (report) => {
1050
- const jsonReport = {
1051
- errors: report.errors,
1052
- warnings: report.warnings,
1053
- logs: report.logs,
1054
- start: report.start,
1055
- end: report.end,
1056
- duration: report.duration,
1057
- writeDuration: report.writeDuration,
1058
- entries: [],
1059
- inputs: [],
1060
- outputs: []
1061
- };
1062
- for (const entry of report.entries || []) {
1063
- const newEntry = { ...entry, inputs: [], outputs: [] };
1064
- if (entry.inputs) {
1065
- newEntry.inputs = entry.inputs.map((file) => file.filepath);
1066
- }
1067
- if (entry.outputs) {
1068
- newEntry.outputs = entry.outputs.map((file) => file.filepath);
1069
- }
1070
- jsonReport.entries.push(newEntry);
1071
- }
1072
- for (const input of report.inputs || []) {
1073
- const newInput = { ...input, dependencies: [], dependents: [] };
1074
- if (input.dependencies) {
1075
- for (const dependency of input.dependencies) {
1076
- newInput.dependencies.push(dependency.filepath);
1077
- }
1078
- }
1079
- if (input.dependents) {
1080
- for (const dependent of input.dependents) {
1081
- newInput.dependents.push(dependent.filepath);
1082
- }
1083
- }
1084
- jsonReport.inputs.push(newInput);
1085
- }
1086
- for (const output of report.outputs || []) {
1087
- const newOutput = { ...output, inputs: [] };
1088
- if (output.inputs) {
1089
- newOutput.inputs = output.inputs.map((file) => file.filepath);
1090
- }
1091
- jsonReport.outputs.push(newOutput);
1092
- }
1093
- return jsonReport;
1094
- };
1095
- const BUNDLER_SPECIFICS = ["unknown", "commonjsHelpers.js", "vite/preload-helper.js"];
1096
- const cleanReport = (report, filepath, filter) => {
1097
- const cleanedReport = /* @__PURE__ */ new Set();
1098
- for (const reportFilepath of report) {
1099
- const cleanedPath = cleanPath(reportFilepath);
1100
- if (
1101
- // Don't add injections.
1102
- isInjectionFile(reportFilepath) || // Don't add itself into it.
1103
- cleanedPath === filepath || // Remove common specific files injected by bundlers.
1104
- BUNDLER_SPECIFICS.includes(cleanedPath)
1105
- ) {
1106
- continue;
1107
- }
1108
- {
1109
- cleanedReport.add(cleanedPath);
1110
- }
1111
- }
1112
- return cleanedReport;
1113
- };
1114
- const cleanPath = (filepath) => {
1115
- return filepath.split("!").pop().split(QUERY_RX).shift().replace(/^[^\w\s.,!@#$%^&*()=+~`\-/]+/, "");
1116
- };
1117
- const getAbsolutePath = (cwd, filepath) => {
1118
- if (isInjectionFile(filepath)) {
1119
- return INJECTED_FILE;
1120
- }
1121
- if (filepath.startsWith(cwd)) {
1122
- return filepath;
1123
- }
1124
- return path.resolve(cwd, filepath);
1125
- };
1126
- const cleanName = (context, filepath) => {
1127
- if (isInjectionFile(filepath)) {
1128
- return INJECTED_FILE;
1129
- }
1130
- if (filepath === "unknown") {
1131
- return filepath;
1132
- }
1133
- if (filepath.includes("webpack/runtime")) {
1134
- return filepath.replace("webpack/runtime/", "").replace(/ +/g, "-");
1135
- }
1136
- return filepath.split("!").pop().replace(context.bundler.outDir, "").replace(context.cwd, "").split("node_modules").pop().split(QUERY_RX).shift().replace(/^\/+/, "");
1137
- };
1138
-
1139
- const TOP = 5;
1140
- const MAX_VALUE_LENGTH = 60;
1141
- const numColor = chalk.bold.red;
1142
- const nameColor = chalk.bold.cyan;
1143
- const sortDesc = (attr) => (a, b) => {
1144
- let aVal;
1145
- let bVal;
1146
- if (typeof attr === "function") {
1147
- aVal = attr(a);
1148
- bVal = attr(b);
1149
- } else {
1150
- aVal = a[attr];
1151
- bVal = b[attr];
1152
- }
1153
- if (aVal > bVal) {
1154
- return -1;
1155
- } else if (aVal < bVal) {
1156
- return 1;
1157
- } else {
1158
- return 0;
1159
- }
1160
- };
1161
- const getGeneralValues = (context) => {
1162
- const valuesToPrint = {
1163
- name: "General Numbers",
1164
- values: [],
1165
- top: false
1166
- };
1167
- const nbModules = context.build.inputs ? context.build.inputs.length : 0;
1168
- const nbAssets = context.build.outputs ? context.build.outputs.length : 0;
1169
- const nbWarnings = context.build.warnings.length;
1170
- const nbErrors = context.build.errors.length;
1171
- const nbEntries = context.build.entries ? context.build.entries.length : 0;
1172
- if (context.build.start) {
1173
- valuesToPrint.values.push({
1174
- name: "Overhead duration",
1175
- value: formatDuration(context.build.start - context.start)
1176
- });
1177
- }
1178
- if (context.build.duration) {
1179
- valuesToPrint.values.push({
1180
- name: "Build duration",
1181
- value: formatDuration(context.build.duration)
1182
- });
1183
- }
1184
- if (context.build.writeDuration) {
1185
- valuesToPrint.values.push({
1186
- name: "Write duration",
1187
- value: formatDuration(context.build.writeDuration)
1188
- });
1189
- }
1190
- valuesToPrint.values.push(
1191
- {
1192
- name: "Number of modules",
1193
- value: nbModules.toString()
1194
- },
1195
- {
1196
- name: "Number of assets",
1197
- value: nbAssets.toString()
1198
- },
1199
- {
1200
- name: "Number of entries",
1201
- value: nbEntries.toString()
1202
- },
1203
- {
1204
- name: "Number of warnings",
1205
- value: nbWarnings.toString()
1206
- },
1207
- {
1208
- name: "Number of errors",
1209
- value: nbErrors.toString()
1210
- }
1211
- );
1212
- return [valuesToPrint];
1213
- };
1214
- const getAssetsValues = (context) => {
1215
- const assetSizesToPrint = {
1216
- name: "Asset size",
1217
- values: (context.build.outputs || []).filter((output) => output.type !== "map").sort(sortDesc((output) => output.size)).map((output) => ({
1218
- name: output.name,
1219
- value: prettyBytes(output.size)
1220
- })),
1221
- top: true
1222
- };
1223
- const entrySizesToPrint = {
1224
- name: "Entry aggregated size",
1225
- values: (context.build.entries || []).sort(sortDesc((entry) => entry.size)).map((entry) => ({
1226
- name: entry.name,
1227
- value: prettyBytes(entry.size)
1228
- })),
1229
- top: true
1230
- };
1231
- const entryModulesToPrint = {
1232
- name: "Entry number of modules",
1233
- values: (context.build.entries || []).sort(sortDesc((entry) => entry.size)).map((entry) => ({
1234
- name: entry.name,
1235
- value: entry.inputs.length.toString()
1236
- })) || [],
1237
- top: true
1238
- };
1239
- return [assetSizesToPrint, entrySizesToPrint, entryModulesToPrint];
1240
- };
1241
- const getModulesValues = (context) => {
1242
- const dependentsToPrint = {
1243
- name: `Module total dependents`,
1244
- values: [],
1245
- top: true
1246
- };
1247
- const dependenciesToPrint = {
1248
- name: `Module total dependencies`,
1249
- values: [],
1250
- top: true
1251
- };
1252
- const sizesToPrint = {
1253
- name: `Module size`,
1254
- values: [],
1255
- top: true
1256
- };
1257
- const aggregatedSizesToPrint = {
1258
- name: `Module aggregated size`,
1259
- values: [],
1260
- top: true
1261
- };
1262
- const dependencies = /* @__PURE__ */ new Set();
1263
- const serializedReport = serializeBuildReport(context.build);
1264
- const inputs = /* @__PURE__ */ new Map();
1265
- const fileDependencies = /* @__PURE__ */ new Map();
1266
- const fileDependents = /* @__PURE__ */ new Map();
1267
- for (const input of serializedReport.inputs || []) {
1268
- if (input.type === "map") {
1269
- continue;
1270
- }
1271
- const dependenciesSet = new Set(input.dependencies);
1272
- const dependentsSet = new Set(input.dependents);
1273
- for (const dep of dependenciesSet) {
1274
- if (!fileDependents.has(dep)) {
1275
- fileDependents.set(dep, /* @__PURE__ */ new Set());
1276
- }
1277
- fileDependents.get(dep).add(input.filepath);
1278
- }
1279
- for (const dep of dependentsSet) {
1280
- if (!fileDependencies.has(dep)) {
1281
- fileDependencies.set(dep, /* @__PURE__ */ new Set());
1282
- }
1283
- fileDependencies.get(dep).add(input.filepath);
1284
- }
1285
- if (fileDependencies.has(input.filepath)) {
1286
- const existingDependencies = fileDependencies.get(input.filepath);
1287
- for (const dep of existingDependencies) {
1288
- dependenciesSet.add(dep);
1289
- }
1290
- }
1291
- if (fileDependents.has(input.filepath)) {
1292
- const existingDependents = fileDependents.get(input.filepath);
1293
- for (const dep of existingDependents) {
1294
- dependentsSet.add(dep);
1295
- }
1296
- }
1297
- fileDependencies.set(input.filepath, dependenciesSet);
1298
- fileDependents.set(input.filepath, dependentsSet);
1299
- inputs.set(input.filepath, {
1300
- name: input.name,
1301
- size: input.size,
1302
- dependencies: dependenciesSet,
1303
- dependents: dependentsSet
1304
- });
1305
- }
1306
- for (const [filepath, input] of inputs) {
1307
- const inputDependencies = fileDependencies.get(filepath) || /* @__PURE__ */ new Set();
1308
- const inputDependents = fileDependents.get(filepath) || /* @__PURE__ */ new Set();
1309
- let aggregatedSize = input.size;
1310
- for (const dep of inputDependencies) {
1311
- aggregatedSize += inputs.get(dep)?.size || 0;
1312
- }
1313
- dependencies.add({
1314
- name: input.name,
1315
- size: input.size,
1316
- aggregatedSize,
1317
- dependents: inputDependents,
1318
- dependencies: inputDependencies
1319
- });
1320
- }
1321
- if (!dependencies.size) {
1322
- return [dependentsToPrint, dependenciesToPrint, sizesToPrint];
1323
- }
1324
- const dependenciesArray = Array.from(dependencies);
1325
- dependenciesArray.sort(sortDesc((file) => file.dependents.size));
1326
- dependentsToPrint.values = dependenciesArray.map((file) => ({
1327
- name: file.name,
1328
- value: file.dependents.size.toString()
1329
- }));
1330
- dependenciesArray.sort(sortDesc((file) => file.dependencies.size));
1331
- dependenciesToPrint.values = dependenciesArray.map((file) => ({
1332
- name: file.name,
1333
- value: file.dependencies.size.toString()
1334
- }));
1335
- dependenciesArray.sort(sortDesc("size"));
1336
- sizesToPrint.values = dependenciesArray.map((file) => ({
1337
- name: file.name,
1338
- value: prettyBytes(file.size)
1339
- }));
1340
- dependenciesArray.sort(sortDesc("aggregatedSize"));
1341
- aggregatedSizesToPrint.values = dependenciesArray.map((file) => ({
1342
- name: file.name,
1343
- value: prettyBytes(file.aggregatedSize || file.size)
1344
- }));
1345
- return [dependentsToPrint, dependenciesToPrint, sizesToPrint, aggregatedSizesToPrint];
1346
- };
1347
- const getTimingValues = (name, timings) => {
1348
- if (!timings || !timings.size) {
1349
- return [];
1350
- }
1351
- const times = Array.from(timings.values());
1352
- times.sort(sortDesc("duration"));
1353
- const durationsToPrint = {
1354
- name: `${name} duration`,
1355
- values: times.map((module) => ({
1356
- name: module.name,
1357
- value: formatDuration(module.duration)
1358
- })),
1359
- top: true
1360
- };
1361
- times.sort(sortDesc("increment"));
1362
- const hitsToPrint = {
1363
- name: `${name} hits`,
1364
- values: times.map((module) => ({
1365
- name: module.name,
1366
- value: module.increment.toString()
1367
- })),
1368
- top: true
1369
- };
1370
- return [durationsToPrint, hitsToPrint];
1371
- };
1372
- const renderValues = (values) => {
1373
- let outputString = "";
1374
- const titlePadding = 4;
1375
- const valuePadding = 4;
1376
- for (const group of values) {
1377
- if (group.top && group.values.length >= TOP) {
1378
- group.values = group.values.slice(0, TOP);
1379
- group.name = `Top ${TOP} ${group.name}`;
1380
- }
1381
- for (const value of group.values) {
1382
- value.name = truncateString(value.name, MAX_VALUE_LENGTH);
1383
- }
1384
- }
1385
- const maxTitleWidth = Math.max(...values.map((val) => val.name.length));
1386
- const maxNameWidth = Math.max(...values.flatMap((val) => val.values.map((v) => v.name.length)));
1387
- const maxValueWidth = Math.max(
1388
- ...values.flatMap((val) => val.values.map((v) => v.value.length))
1389
- );
1390
- const totalWidth = Math.max(
1391
- maxTitleWidth + titlePadding,
1392
- maxNameWidth + maxValueWidth + valuePadding
1393
- );
1394
- for (const group of values) {
1395
- if (group.values.length === 0) {
1396
- continue;
1397
- }
1398
- const titlePad = totalWidth - (group.name.length + titlePadding);
1399
- outputString += `
1400
- == ${group.name} ${"=".repeat(titlePad)}=
1401
- `;
1402
- for (const value of group.values) {
1403
- const valuePad = maxValueWidth - value.value.length;
1404
- outputString += ` [${numColor(value.value)}] ${" ".repeat(valuePad)}${nameColor(value.name)}
1405
- `;
1406
- }
1407
- }
1408
- return outputString;
1409
- };
1410
- const outputTexts = (globalContext, log, report) => {
1411
- const valuesToPrint = [];
1412
- if (report) {
1413
- valuesToPrint.push(...getTimingValues("Loader", report.timings.loaders));
1414
- valuesToPrint.push(...getTimingValues("Tapable", report.timings.tapables));
1415
- valuesToPrint.push(...getTimingValues("Module", report.timings.modules));
1416
- }
1417
- valuesToPrint.push(...getModulesValues(globalContext));
1418
- valuesToPrint.push(...getAssetsValues(globalContext));
1419
- valuesToPrint.push(...getGeneralValues(globalContext));
1420
- const outputString = renderValues(valuesToPrint);
1421
- log.info(outputString);
1422
- };
1423
-
1424
- const sendMetrics = (metrics, auth, log) => {
1425
- const startSending = Date.now();
1426
- if (!auth.apiKey) {
1427
- log.warn(`Won't send metrics to Datadog: missing API Key.`);
1428
- return;
1429
- }
1430
- if (!metrics.size) {
1431
- log.warn(`No metrics to send.`);
1432
- return;
1433
- }
1434
- const metricIterations = /* @__PURE__ */ new Map();
1435
- for (const metric of metrics) {
1436
- if (!metricIterations.has(metric.metric)) {
1437
- metricIterations.set(metric.metric, 0);
1438
- }
1439
- metricIterations.set(metric.metric, metricIterations.get(metric.metric) + 1);
1440
- }
1441
- const metricsNames = Array.from(metricIterations.entries()).map(
1442
- ([name, count]) => `${name} - ${count}`
1443
- );
1444
- log.debug(`
1445
- Sending ${metrics.size} metrics.
1446
- Metrics:
1447
- - ${metricsNames.join("\n - ")}`);
1448
- return doRequest({
1449
- method: "POST",
1450
- url: `${auth.endPoint}/api/v1/series?api_key=${auth.apiKey}`,
1451
- getData: () => ({
1452
- data: JSON.stringify({ series: Array.from(metrics) })
1453
- })
1454
- }).then(() => {
1455
- log.debug(`Sent metrics in ${formatDuration(Date.now() - startSending)}.`);
1456
- }).catch((e) => {
1457
- log.error(`Error sending metrics ${e}`);
1458
- });
1459
- };
1460
-
1461
- const FN_TO_WRAP = ["onStart", "onLoad", "onResolve", "onEnd"];
1462
- const pluginsMap = /* @__PURE__ */ new Map();
1463
- const modulesMap = /* @__PURE__ */ new Map();
1464
- const wrapPlugins = (build, context) => {
1465
- const plugins = build.initialOptions.plugins;
1466
- if (plugins) {
1467
- const initialPlugins = plugins.map((plugin) => {
1468
- return {
1469
- ...plugin
1470
- };
1471
- });
1472
- for (const plugin of plugins) {
1473
- if (plugin.name.includes(PLUGIN_NAME$4)) {
1474
- continue;
1475
- }
1476
- const oldSetup = plugin.setup;
1477
- plugin.setup = async (esbuild) => {
1478
- const newBuildObject = getNewBuildObject(esbuild, plugin.name, context);
1479
- await oldSetup({
1480
- ...newBuildObject,
1481
- // Use non-modified plugins for other plugins
1482
- initialOptions: { ...newBuildObject.initialOptions, plugins: initialPlugins }
1483
- });
1484
- };
1485
- }
1486
- }
1487
- };
1488
- const getNewBuildObject = (build, pluginName, context) => {
1489
- const newBuildObject = Object.assign({}, build);
1490
- for (const fn of FN_TO_WRAP) {
1491
- newBuildObject[fn] = async (opts, cb) => {
1492
- const pluginTiming = pluginsMap.get(pluginName) || {
1493
- name: pluginName,
1494
- increment: 0,
1495
- duration: 0,
1496
- events: {}
1497
- };
1498
- pluginTiming.events[fn] = pluginTiming.events[fn] || {
1499
- name: fn,
1500
- values: []
1501
- };
1502
- const initialFunction = build[fn];
1503
- return initialFunction(opts, async (...args) => {
1504
- const modulePath = formatModuleName(args[0].path, context);
1505
- const moduleTiming = modulesMap.get(modulePath) || {
1506
- name: modulePath,
1507
- increment: 0,
1508
- duration: 0,
1509
- events: {}
1510
- };
1511
- moduleTiming.events[fn] = moduleTiming.events[fn] || {
1512
- name: fn,
1513
- values: []
1514
- };
1515
- const start = perf_hooks.performance.now();
1516
- try {
1517
- return await cb(...args);
1518
- } finally {
1519
- const end = perf_hooks.performance.now();
1520
- const duration = end - start;
1521
- const statsObject = {
1522
- start,
1523
- end,
1524
- duration,
1525
- context: getValueContext(args)
1526
- };
1527
- pluginTiming.events[fn].values.push(statsObject);
1528
- pluginTiming.duration += duration;
1529
- pluginTiming.increment += 1;
1530
- pluginsMap.set(pluginName, pluginTiming);
1531
- moduleTiming.events[fn].values.push(statsObject);
1532
- moduleTiming.duration += duration;
1533
- moduleTiming.increment += 1;
1534
- modulesMap.set(modulePath, moduleTiming);
1535
- }
1536
- });
1537
- };
1538
- }
1539
- return newBuildObject;
1540
- };
1541
- const getResults = () => ({ plugins: pluginsMap, modules: modulesMap });
1542
-
1543
- const getEsbuildPlugin$1 = (bundlerContext, globalContext, logger) => {
1544
- return {
1545
- setup: (build) => {
1546
- globalContext.build.start = Date.now();
1547
- build.initialOptions.metafile = true;
1548
- wrapPlugins(build, globalContext.cwd);
1549
- build.onEnd(async (result) => {
1550
- if (!result.metafile) {
1551
- logger.warn("Missing metafile, can't proceed with modules data.");
1552
- return;
1553
- }
1554
- const { plugins, modules } = getResults();
1555
- bundlerContext.report = {
1556
- timings: {
1557
- tapables: plugins,
1558
- modules
1559
- }
1560
- };
1561
- });
1562
- }
1563
- };
1564
- };
1565
-
1566
- class Loaders {
1567
- constructor(cwd) {
1568
- this.started = {};
1569
- this.finished = [];
1570
- this.cwd = cwd;
1571
- }
1572
- buildModule(module, compilation) {
1573
- const moduleName = getModuleName(module, compilation, this.cwd);
1574
- const loaders = getLoaderNames(module);
1575
- if (!loaders.length) {
1576
- loaders.push("no-loader");
1577
- }
1578
- this.started[moduleName] = {
1579
- module: getDisplayName(moduleName),
1580
- timings: {
1581
- start: perf_hooks.performance.now(),
1582
- duration: 0,
1583
- end: 0
1584
- },
1585
- loaders
1586
- };
1587
- }
1588
- succeedModule(module, compilation) {
1589
- const moduleName = getModuleName(module, compilation, this.cwd);
1590
- const event = this.started[moduleName];
1591
- if (!event) {
1592
- return;
1593
- }
1594
- event.timings.end = perf_hooks.performance.now();
1595
- event.timings.duration = event.timings.end - event.timings.start;
1596
- this.finished.push(event);
1597
- delete this.started[moduleName];
1598
- }
1599
- getResults() {
1600
- const loaders = /* @__PURE__ */ new Map();
1601
- const modules = /* @__PURE__ */ new Map();
1602
- for (const event of this.finished) {
1603
- const duration = event.timings.end - event.timings.start;
1604
- const moduleTiming = modules.get(event.module) || {
1605
- name: event.module,
1606
- increment: 0,
1607
- duration: 0,
1608
- events: {}
1609
- };
1610
- const eventName = event.loaders.join(",");
1611
- moduleTiming.events[eventName] = moduleTiming.events[eventName] || {
1612
- name: eventName,
1613
- values: []
1614
- };
1615
- moduleTiming.events[eventName].values.push(event.timings);
1616
- moduleTiming.increment += 1;
1617
- moduleTiming.duration += duration;
1618
- modules.set(event.module, moduleTiming);
1619
- for (const loader of event.loaders) {
1620
- const loaderTiming = loaders.get(loader) || {
1621
- name: loader,
1622
- increment: 0,
1623
- duration: 0,
1624
- events: {}
1625
- };
1626
- loaderTiming.increment += 1;
1627
- loaderTiming.duration += duration;
1628
- loaders.set(loader, loaderTiming);
1629
- }
1630
- }
1631
- return { loaders, modules };
1632
- }
1633
- }
1634
-
1635
- class Tapables {
1636
- constructor(cwd) {
1637
- this.monitoredTaps = {};
1638
- this.tapables = [];
1639
- this.hooks = {};
1640
- this.timings = /* @__PURE__ */ new Map();
1641
- this.ignoredHooks = [
1642
- // This one triggers a DEP_WEBPACK_COMPILATION_NORMAL_MODULE_LOADER_HOOK warning.
1643
- "normalModuleLoader"
1644
- ];
1645
- this.cwd = cwd;
1646
- }
1647
- saveResult(type, pluginName, hookName, context, start, end) {
1648
- const timing = this.timings.get(pluginName) || {
1649
- name: pluginName,
1650
- duration: 0,
1651
- increment: 0,
1652
- events: {}
1653
- };
1654
- if (!timing.events[hookName]) {
1655
- timing.events[hookName] = {
1656
- name: hookName,
1657
- values: []
1658
- };
1659
- }
1660
- timing.events[hookName].values.push({
1661
- start,
1662
- end,
1663
- duration: end - start,
1664
- context,
1665
- type
1666
- });
1667
- timing.duration += end - start;
1668
- timing.increment += 1;
1669
- this.timings.set(pluginName, timing);
1670
- }
1671
- getResults() {
1672
- const timings = this.timings;
1673
- for (const [tapableName, tapable] of this.timings) {
1674
- const timing = tapable;
1675
- timing.duration = Object.values(tapable.events).map(
1676
- (hookArray) => hookArray.values.reduce((previous, current) => {
1677
- return previous + current.end - current.start;
1678
- }, 0)
1679
- ).reduce((previous, current) => previous + current, 0);
1680
- timings.set(tapableName, timing);
1681
- }
1682
- return {
1683
- monitoredTaps: this.monitoredTaps,
1684
- tapables: this.tapables,
1685
- hooks: this.hooks,
1686
- timings
1687
- };
1688
- }
1689
- getPromiseTapPatch(type, fn, pluginName, hookName) {
1690
- return (...args) => {
1691
- this.checkNewHooks();
1692
- const startTime = perf_hooks.performance.now();
1693
- const returnValue = fn.apply(this, args);
1694
- const cb = () => {
1695
- this.saveResult(
1696
- type,
1697
- pluginName,
1698
- hookName,
1699
- getValueContext(args),
1700
- startTime,
1701
- perf_hooks.performance.now()
1702
- );
1703
- };
1704
- returnValue.then(cb, cb);
1705
- return returnValue;
1706
- };
1707
- }
1708
- getAsyncTapPatch(type, fn, pluginName, hookName) {
1709
- return (...args) => {
1710
- this.checkNewHooks();
1711
- const startTime = perf_hooks.performance.now();
1712
- const originalCB = args.pop();
1713
- const newCB = (...a) => {
1714
- this.saveResult(
1715
- type,
1716
- pluginName,
1717
- hookName,
1718
- getValueContext(args),
1719
- startTime,
1720
- perf_hooks.performance.now()
1721
- );
1722
- return originalCB(...a);
1723
- };
1724
- return fn.apply(this, [...args, newCB]);
1725
- };
1726
- }
1727
- getDefaultTapPatch(type, fn, pluginName, hookName) {
1728
- return (...args) => {
1729
- this.checkNewHooks();
1730
- const startTime = perf_hooks.performance.now();
1731
- const returnValue = fn.apply(this, args);
1732
- this.saveResult(
1733
- type,
1734
- pluginName,
1735
- hookName,
1736
- getValueContext(args),
1737
- startTime,
1738
- perf_hooks.performance.now()
1739
- );
1740
- return returnValue;
1741
- };
1742
- }
1743
- // Patch the tap so we can report its execution duration.
1744
- getTapPatch(type, fn, pluginName, hookName) {
1745
- switch (type) {
1746
- case "promise":
1747
- return this.getPromiseTapPatch(type, fn, pluginName, hookName);
1748
- case "async":
1749
- return this.getAsyncTapPatch(type, fn, pluginName, hookName);
1750
- case "default":
1751
- default:
1752
- return this.getDefaultTapPatch(type, fn, pluginName, hookName);
1753
- }
1754
- }
1755
- newTap(type, hookName, originalTap, scope) {
1756
- return (options, fn) => {
1757
- const pluginName = getPluginName(options);
1758
- const key = `${hookName}-${pluginName}`;
1759
- if (this.monitoredTaps[key]) {
1760
- return originalTap.call(scope, options, fn);
1761
- }
1762
- this.monitoredTaps[key] = true;
1763
- const newFn = this.getTapPatch(type, fn, pluginName, hookName);
1764
- return originalTap.call(scope, options, newFn);
1765
- };
1766
- }
1767
- replaceTaps(hookName, hook) {
1768
- hook.tap = this.newTap("default", hookName, hook.tap, hook);
1769
- hook.tapAsync = this.newTap("async", hookName, hook.tapAsync, hook);
1770
- hook.tapPromise = this.newTap("promise", hookName, hook.tapPromise, hook);
1771
- }
1772
- patchHook(tapableName, hookName, hook) {
1773
- if (hook._fakeHook) {
1774
- return;
1775
- }
1776
- if (tapableName.includes(PLUGIN_NAME$4)) {
1777
- return;
1778
- }
1779
- if (!this.hooks[tapableName]) {
1780
- this.hooks[tapableName] = [];
1781
- }
1782
- if (this.hooks[tapableName].includes(hookName)) {
1783
- return;
1784
- }
1785
- this.hooks[tapableName].push(hookName);
1786
- this.replaceTaps(hookName, hook);
1787
- }
1788
- patchHooks(tapable) {
1789
- const name = tapable.constructor.name;
1790
- const hooksToPatch = Object.keys(tapable.hooks).filter((hookName) => {
1791
- if (this.ignoredHooks.includes(hookName)) {
1792
- return false;
1793
- }
1794
- if (this.hooks[name]?.includes(hookName)) {
1795
- return false;
1796
- }
1797
- return true;
1798
- });
1799
- for (const hookName of hooksToPatch) {
1800
- this.patchHook(name, hookName, tapable.hooks[hookName]);
1801
- }
1802
- }
1803
- checkNewHooks() {
1804
- for (const tapable of this.tapables) {
1805
- this.patchHooks(tapable);
1806
- }
1807
- }
1808
- // Let's navigate through all the hooks we can find.
1809
- throughHooks(tapable) {
1810
- if (!this.tapables.includes(tapable)) {
1811
- this.tapables.push(tapable);
1812
- }
1813
- this.patchHooks(tapable);
1814
- }
1815
- }
1816
-
1817
- const getWebpackPlugin = (bundlerContext, globalContext) => {
1818
- return async (compiler) => {
1819
- globalContext.build.start = Date.now();
1820
- const HOOK_OPTIONS = { name: PLUGIN_NAME$4 };
1821
- const tapables = new Tapables(globalContext.cwd);
1822
- const loaders = new Loaders(globalContext.cwd);
1823
- tapables.throughHooks(compiler);
1824
- compiler.hooks.thisCompilation.tap(HOOK_OPTIONS, (compilation) => {
1825
- tapables.throughHooks(compilation);
1826
- compilation.hooks.buildModule.tap(HOOK_OPTIONS, (module) => {
1827
- loaders.buildModule(module, compilation);
1828
- });
1829
- compilation.hooks.succeedModule.tap(HOOK_OPTIONS, (module) => {
1830
- loaders.succeedModule(module, compilation);
1831
- });
1832
- });
1833
- compiler.hooks.afterEmit.tapPromise(HOOK_OPTIONS, async (compilation) => {
1834
- const { timings: tapableTimings } = tapables.getResults();
1835
- const { loaders: loadersTimings, modules: modulesTimings } = loaders.getResults();
1836
- bundlerContext.report = {
1837
- timings: {
1838
- tapables: tapableTimings,
1839
- loaders: loadersTimings,
1840
- modules: modulesTimings
1841
- }
1842
- };
1843
- });
1844
- };
1845
- };
1846
-
1847
- const helpers$2 = {
1848
- filters: defaultFilters
1849
- };
1850
- const getPlugins = (options, context, logger) => {
1851
- let realBuildEnd = 0;
1852
- const bundlerContext = {
1853
- start: Date.now()
1854
- };
1855
- const telemetryOptions = validateOptions(options);
1856
- const plugins = [];
1857
- const legacyPlugin = {
1858
- name: PLUGIN_NAME$4,
1859
- enforce: "pre",
1860
- esbuild: getEsbuildPlugin$1(bundlerContext, context, logger),
1861
- webpack: getWebpackPlugin(bundlerContext, context),
1862
- rspack: getWebpackPlugin(bundlerContext, context)
1863
- };
1864
- const universalPlugin = {
1865
- name: "datadog-universal-telemetry-plugin",
1866
- enforce: "post",
1867
- buildStart() {
1868
- context.build.start = context.build.start || Date.now();
1869
- },
1870
- buildEnd() {
1871
- realBuildEnd = Date.now();
1872
- },
1873
- // Move as much as possible in the universal plugin.
1874
- async writeBundle() {
1875
- context.build.end = Date.now();
1876
- context.build.duration = context.build.end - context.build.start;
1877
- context.build.writeDuration = context.build.end - realBuildEnd;
1878
- const metrics = /* @__PURE__ */ new Set();
1879
- const optionsDD = getOptionsDD(telemetryOptions);
1880
- addMetrics(context, optionsDD, metrics, bundlerContext.report);
1881
- await outputFiles(
1882
- { report: bundlerContext.report, metrics },
1883
- telemetryOptions.output,
1884
- logger,
1885
- context.bundler.outDir
1886
- );
1887
- outputTexts(context, logger, bundlerContext.report);
1888
- await sendMetrics(
1889
- metrics,
1890
- { apiKey: context.auth?.apiKey, endPoint: telemetryOptions.endPoint },
1891
- logger
1892
- );
1893
- }
1894
- };
1895
- if (telemetryOptions.enableTracing) {
1896
- plugins.push(legacyPlugin);
1897
- }
1898
- plugins.push(universalPlugin);
1899
- return plugins;
1900
- };
1901
-
1902
- const reIndexMeta = (obj, cwd) => Object.fromEntries(
1903
- Object.entries(obj).map(([key, value]) => {
1904
- const newKey = getAbsolutePath(cwd, key);
1905
- return [newKey, value];
1906
- })
1907
- );
1908
- const getAllEntryFiles = (filepath, cwd) => {
1909
- if (!filepath.includes("*")) {
1910
- return [filepath];
1911
- }
1912
- const files = glob.glob.sync(filepath);
1913
- return files;
1914
- };
1915
- const getEntryNames = (entrypoints, context) => {
1916
- const entryNames = /* @__PURE__ */ new Map();
1917
- if (Array.isArray(entrypoints)) {
1918
- for (const entry of entrypoints) {
1919
- const fullPath = entry && typeof entry === "object" ? entry.in : entry;
1920
- const allFiles = getAllEntryFiles(fullPath, context.cwd);
1921
- for (const file of allFiles) {
1922
- const cleanedName = cleanName(context, getResolvedPath(file));
1923
- entryNames.set(cleanedName, cleanedName);
1924
- }
1925
- }
1926
- } else if (typeof entrypoints === "object") {
1927
- const entryList = entrypoints ? Object.entries(entrypoints) : [];
1928
- for (const [entryName, entryPath] of entryList) {
1929
- const allFiles = getAllEntryFiles(entryPath, context.cwd);
1930
- for (const file of allFiles) {
1931
- const cleanedName = cleanName(context, getResolvedPath(file));
1932
- entryNames.set(cleanedName, entryName);
1933
- }
1934
- }
1935
- }
1936
- return entryNames;
1937
- };
1938
- const getEsbuildPlugin = (context, log) => {
1939
- return {
1940
- setup(build) {
1941
- const cwd = context.cwd;
1942
- const entrypoints = build.initialOptions.entryPoints;
1943
- const entryNames = getEntryNames(entrypoints, context);
1944
- build.onEnd((result) => {
1945
- for (const error of result.errors) {
1946
- context.build.errors.push(error.text);
1947
- }
1948
- for (const warning of result.warnings) {
1949
- context.build.warnings.push(warning.text);
1950
- }
1951
- const warn = (warning) => {
1952
- context.build.warnings.push(warning);
1953
- log.warn(warning);
1954
- };
1955
- if (!result.metafile) {
1956
- warn("Missing metafile from build result.");
1957
- return;
1958
- }
1959
- const inputs = [];
1960
- const outputs = [];
1961
- const tempEntryFiles = [];
1962
- const tempSourcemaps = [];
1963
- const entries = [];
1964
- const reportInputsIndexed = {};
1965
- const reportOutputsIndexed = {};
1966
- const metaInputsIndexed = reIndexMeta(result.metafile.inputs, cwd);
1967
- const metaOutputsIndexed = reIndexMeta(result.metafile.outputs, cwd);
1968
- const getRealPathFromInjectionProxy = (entryPoint) => {
1969
- if (!isInjectionFile(entryPoint)) {
1970
- return entryPoint;
1971
- }
1972
- const metaInput = metaInputsIndexed[getAbsolutePath(cwd, entryPoint)];
1973
- if (!metaInput) {
1974
- return entryPoint;
1975
- }
1976
- const actualImport = metaInput.imports.find(
1977
- (imp) => !isInjectionFile(imp.path)
1978
- );
1979
- if (!actualImport) {
1980
- return entryPoint;
1981
- }
1982
- return actualImport.path;
1983
- };
1984
- for (const [filename, input] of Object.entries(result.metafile.inputs)) {
1985
- if (isInjectionFile(filename)) {
1986
- continue;
1987
- }
1988
- const filepath = getAbsolutePath(cwd, filename);
1989
- const name = cleanName(context, filename);
1990
- const file = {
1991
- name,
1992
- filepath,
1993
- dependents: /* @__PURE__ */ new Set(),
1994
- dependencies: /* @__PURE__ */ new Set(),
1995
- size: input.bytes,
1996
- type: getType(filename)
1997
- };
1998
- reportInputsIndexed[filepath] = file;
1999
- inputs.push(file);
2000
- }
2001
- for (const [filename, output] of Object.entries(result.metafile.outputs)) {
2002
- const fullPath = getAbsolutePath(cwd, filename);
2003
- const cleanedName = cleanName(context, fullPath);
2004
- const inputFiles = [];
2005
- for (const inputName of Object.keys(output.inputs)) {
2006
- if (isInjectionFile(inputName)) {
2007
- continue;
2008
- }
2009
- const inputFound = reportInputsIndexed[getAbsolutePath(cwd, inputName)];
2010
- if (!inputFound) {
2011
- warn(`Input ${inputName} not found for output ${cleanedName}`);
2012
- continue;
2013
- }
2014
- inputFiles.push(inputFound);
2015
- }
2016
- if (output.entryPoint && !inputFiles.length) {
2017
- const inputFound = reportInputsIndexed[getAbsolutePath(cwd, output.entryPoint)];
2018
- if (!inputFound) {
2019
- warn(`Input ${output.entryPoint} not found for output ${cleanedName}`);
2020
- continue;
2021
- }
2022
- inputFiles.push(inputFound);
2023
- }
2024
- const file = {
2025
- name: cleanedName,
2026
- filepath: fullPath,
2027
- inputs: inputFiles,
2028
- size: output.bytes,
2029
- type: getType(fullPath)
2030
- };
2031
- reportOutputsIndexed[fullPath] = file;
2032
- if (file.type === "map") {
2033
- tempSourcemaps.push(file);
2034
- }
2035
- outputs.push(file);
2036
- if (!output.entryPoint) {
2037
- continue;
2038
- }
2039
- const inputFile = reportInputsIndexed[getAbsolutePath(cwd, getRealPathFromInjectionProxy(output.entryPoint))];
2040
- if (inputFile) {
2041
- if (!entryNames.get(inputFile.name)) {
2042
- continue;
2043
- }
2044
- const entry = {
2045
- ...file,
2046
- name: entryNames.get(inputFile.name) || inputFile.name,
2047
- outputs: [file],
2048
- size: file.size
2049
- };
2050
- tempEntryFiles.push(entry);
2051
- }
2052
- }
2053
- for (const sourcemap of tempSourcemaps) {
2054
- const outputFilepath = sourcemap.filepath.replace(/\.map$/, "");
2055
- const foundOutput = reportOutputsIndexed[outputFilepath];
2056
- if (!foundOutput) {
2057
- warn(`Could not find output for sourcemap ${sourcemap.name}`);
2058
- continue;
2059
- }
2060
- sourcemap.inputs.push(foundOutput);
2061
- }
2062
- const references = {
2063
- inputs: {
2064
- report: reportInputsIndexed,
2065
- meta: metaInputsIndexed
2066
- },
2067
- outputs: {
2068
- report: reportOutputsIndexed,
2069
- meta: metaOutputsIndexed
2070
- }
2071
- };
2072
- const FILE_EXCEPTIONS_RX = /(<runtime>|https:|file:|data:|#)/g;
2073
- const isFileSupported = (filePath) => {
2074
- if (isInjectionFile(filePath) || filePath.match(FILE_EXCEPTIONS_RX)) {
2075
- return false;
2076
- }
2077
- return true;
2078
- };
2079
- const getAllImports = (filePath, ref, allImports = {}) => {
2080
- if (!isFileSupported(filePath)) {
2081
- return allImports;
2082
- }
2083
- const file = ref.report[filePath];
2084
- if (!file) {
2085
- warn(`Could not find report's ${filePath}`);
2086
- return allImports;
2087
- }
2088
- if (allImports[file.filepath]) {
2089
- return allImports;
2090
- }
2091
- allImports[file.filepath] = file;
2092
- const metaFile = ref.meta[filePath];
2093
- if (!metaFile) {
2094
- warn(`Could not find metafile's ${filePath}`);
2095
- return allImports;
2096
- }
2097
- if (!metaFile.imports || !metaFile.imports.length) {
2098
- return allImports;
2099
- }
2100
- for (const imported of metaFile.imports) {
2101
- const importPath = getAbsolutePath(cwd, imported.path);
2102
- getAllImports(importPath, ref, allImports);
2103
- }
2104
- return allImports;
2105
- };
2106
- for (const entryFile of tempEntryFiles) {
2107
- const entryInputs = {};
2108
- const entryOutputs = {};
2109
- for (const input of entryFile.inputs) {
2110
- getAllImports(input.filepath, references.inputs, entryInputs);
2111
- }
2112
- for (const outputFile of entryFile.outputs) {
2113
- getAllImports(
2114
- outputFile.filepath,
2115
- references.outputs,
2116
- entryOutputs
2117
- );
2118
- }
2119
- entryFile.inputs = Object.values(entryInputs);
2120
- entryFile.outputs = Object.values(entryOutputs);
2121
- entryFile.size = entryFile.outputs.reduce(
2122
- (acc, output) => acc + output.size,
2123
- 0
2124
- );
2125
- entries.push(entryFile);
2126
- }
2127
- for (const input of inputs) {
2128
- const metaFile = references.inputs.meta[input.filepath];
2129
- if (!metaFile) {
2130
- warn(`Could not find metafile's ${input.name}`);
2131
- continue;
2132
- }
2133
- for (const dependency of metaFile.imports) {
2134
- if (!isFileSupported(dependency.path)) {
2135
- continue;
2136
- }
2137
- const dependencyPath = getAbsolutePath(cwd, dependency.path);
2138
- const dependencyFile = references.inputs.report[dependencyPath];
2139
- if (!dependencyFile) {
2140
- warn(`Could not find input file of ${dependency.path}`);
2141
- continue;
2142
- }
2143
- input.dependencies.add(dependencyFile);
2144
- dependencyFile.dependents.add(input);
2145
- }
2146
- }
2147
- context.build.outputs = outputs;
2148
- context.build.inputs = inputs;
2149
- context.build.entries = entries;
2150
- });
2151
- }
2152
- };
2153
- };
2154
-
2155
- const getRollupPlugin = (context, log) => {
2156
- const importsReport = {};
2157
- return {
2158
- onLog(level, logItem) {
2159
- if (level === "warn") {
2160
- context.build.warnings.push(logItem.message || logItem.toString());
2161
- }
2162
- },
2163
- renderError(error) {
2164
- if (error) {
2165
- context.build.errors.push(error.message);
2166
- }
2167
- },
2168
- moduleParsed(info) {
2169
- const cleanId = cleanPath(info.id);
2170
- const report = importsReport[cleanId] || {
2171
- dependencies: /* @__PURE__ */ new Set(),
2172
- dependents: /* @__PURE__ */ new Set()
2173
- };
2174
- const newDependencies = cleanReport(
2175
- /* @__PURE__ */ new Set([...info.dynamicallyImportedIds, ...info.importedIds]),
2176
- cleanId
2177
- );
2178
- const newDependents = cleanReport(
2179
- /* @__PURE__ */ new Set([...info.dynamicImporters, ...info.importers]),
2180
- cleanId
2181
- );
2182
- for (const dependent of newDependents) {
2183
- report.dependents.add(dependent);
2184
- }
2185
- for (const dependency of newDependencies) {
2186
- report.dependencies.add(dependency);
2187
- }
2188
- importsReport[cleanId] = report;
2189
- },
2190
- writeBundle(options, bundle) {
2191
- const inputs = [];
2192
- const outputs = [];
2193
- const tempEntryFiles = [];
2194
- const tempSourcemaps = [];
2195
- const entries = [];
2196
- const reportInputsIndexed = {};
2197
- const reportOutputsIndexed = {};
2198
- const warn = (warning) => {
2199
- context.build.warnings.push(warning);
2200
- log.warn(warning);
2201
- };
2202
- for (const [filepath, { dependencies, dependents }] of Object.entries(importsReport)) {
2203
- for (const dependency of dependencies) {
2204
- const cleanedDependency = cleanPath(dependency);
2205
- if (!importsReport[cleanedDependency]) {
2206
- importsReport[cleanedDependency] = {
2207
- dependencies: /* @__PURE__ */ new Set(),
2208
- dependents: /* @__PURE__ */ new Set()
2209
- };
2210
- }
2211
- if (importsReport[cleanedDependency].dependents.has(filepath)) {
2212
- continue;
2213
- }
2214
- importsReport[cleanedDependency].dependents.add(filepath);
2215
- }
2216
- for (const dependent of dependents) {
2217
- const cleanedDependent = cleanPath(dependent);
2218
- if (!importsReport[cleanedDependent]) {
2219
- importsReport[cleanedDependent] = {
2220
- dependencies: /* @__PURE__ */ new Set(),
2221
- dependents: /* @__PURE__ */ new Set()
2222
- };
2223
- }
2224
- if (importsReport[cleanedDependent].dependencies.has(filepath)) {
2225
- continue;
2226
- }
2227
- importsReport[cleanedDependent].dependencies.add(filepath);
2228
- }
2229
- }
2230
- for (const [filename, asset] of Object.entries(bundle)) {
2231
- const filepath = getAbsolutePath(context.bundler.outDir, filename);
2232
- const size = "code" in asset ? Buffer.byteLength(asset.code, "utf8") : Buffer.byteLength(asset.source, "utf8");
2233
- const file = {
2234
- name: filename,
2235
- filepath,
2236
- inputs: [],
2237
- size,
2238
- type: getType(filename)
2239
- };
2240
- if (file.type === "map") {
2241
- tempSourcemaps.push(file);
2242
- }
2243
- if ("modules" in asset) {
2244
- for (const [modulepath, module] of Object.entries(asset.modules)) {
2245
- if (cleanPath(modulepath) !== modulepath) {
2246
- continue;
2247
- }
2248
- const moduleFile = {
2249
- name: cleanName(context, modulepath),
2250
- dependencies: /* @__PURE__ */ new Set(),
2251
- dependents: /* @__PURE__ */ new Set(),
2252
- filepath: modulepath,
2253
- // Since we store as input, we use the originalLength.
2254
- size: module.originalLength,
2255
- type: getType(modulepath)
2256
- };
2257
- file.inputs.push(moduleFile);
2258
- reportInputsIndexed[moduleFile.filepath] = moduleFile;
2259
- inputs.push(moduleFile);
2260
- }
2261
- }
2262
- if ("isEntry" in asset && asset.isEntry) {
2263
- tempEntryFiles.push({ ...file, name: asset.name, size: 0, outputs: [file] });
2264
- }
2265
- reportOutputsIndexed[file.filepath] = file;
2266
- outputs.push(file);
2267
- }
2268
- for (const input of inputs) {
2269
- const importReport = importsReport[input.filepath];
2270
- if (!importReport) {
2271
- warn(`Could not find the import report for ${input.name}.`);
2272
- continue;
2273
- }
2274
- for (const dependency of importReport.dependencies) {
2275
- const foundInput = reportInputsIndexed[dependency];
2276
- if (!foundInput) {
2277
- warn(
2278
- `Could not find input for dependency ${cleanName(context, dependency)} of ${input.name}`
2279
- );
2280
- continue;
2281
- }
2282
- input.dependencies.add(foundInput);
2283
- }
2284
- for (const dependent of importReport.dependents) {
2285
- const foundInput = reportInputsIndexed[dependent];
2286
- if (!foundInput) {
2287
- warn(
2288
- `Could not find input for dependent ${cleanName(context, dependent)} of ${input.name}`
2289
- );
2290
- continue;
2291
- }
2292
- input.dependents.add(foundInput);
2293
- }
2294
- }
2295
- if (tempSourcemaps.length) {
2296
- for (const sourcemap of tempSourcemaps) {
2297
- const outputPath = sourcemap.filepath.replace(/\.map$/, "");
2298
- const foundOutput = reportOutputsIndexed[outputPath];
2299
- if (!foundOutput) {
2300
- warn(`Could not find output for sourcemap ${sourcemap.name}`);
2301
- continue;
2302
- }
2303
- sourcemap.inputs.push(foundOutput);
2304
- }
2305
- }
2306
- const getAllOutputs = (filepath, allOutputs = {}) => {
2307
- if (allOutputs[filepath]) {
2308
- return allOutputs;
2309
- }
2310
- const filename = cleanName(context, filepath);
2311
- const foundOutput = reportOutputsIndexed[filepath];
2312
- if (!foundOutput) {
2313
- warn(`Could not find output for ${filename}`);
2314
- return allOutputs;
2315
- }
2316
- allOutputs[filepath] = foundOutput;
2317
- const asset = bundle[filename];
2318
- if (!asset) {
2319
- warn(`Could not find asset for ${filename}`);
2320
- return allOutputs;
2321
- }
2322
- const imports = [];
2323
- if ("imports" in asset) {
2324
- imports.push(...asset.imports);
2325
- }
2326
- if ("dynamicImports" in asset) {
2327
- imports.push(...asset.dynamicImports);
2328
- }
2329
- for (const importName of imports) {
2330
- getAllOutputs(getAbsolutePath(context.bundler.outDir, importName), allOutputs);
2331
- }
2332
- return allOutputs;
2333
- };
2334
- for (const entryFile of tempEntryFiles) {
2335
- const entryOutputs = getAllOutputs(entryFile.filepath);
2336
- entryFile.outputs = Object.values(entryOutputs);
2337
- entryFile.inputs = Array.from(
2338
- new Set(entryFile.outputs.flatMap((output) => output.inputs))
2339
- );
2340
- entryFile.size = entryFile.outputs.reduce((acc, output) => acc + output.size, 0);
2341
- entries.push(entryFile);
2342
- }
2343
- context.build.inputs = inputs;
2344
- context.build.outputs = outputs;
2345
- context.build.entries = entries;
2346
- }
2347
- };
2348
- };
2349
-
2350
- const getXpackPlugin = (context, PLUGIN_NAME, log) => (compiler) => {
2351
- const inputs = [];
2352
- const outputs = [];
2353
- const entries = [];
2354
- const reportInputsIndexed = /* @__PURE__ */ new Map();
2355
- const reportOutputsIndexed = /* @__PURE__ */ new Map();
2356
- const modulesPerFile = /* @__PURE__ */ new Map();
2357
- const moduleIndex = /* @__PURE__ */ new Map();
2358
- const tempSourcemaps = [];
2359
- const tempDeps = /* @__PURE__ */ new Map();
2360
- const isModuleSupported = (moduleIdentifier) => {
2361
- return (
2362
- // Ignore unidentified modules and runtimes.
2363
- !!moduleIdentifier && !moduleIdentifier.startsWith("webpack/runtime") && !moduleIdentifier.includes("/webpack4/buildin/") && !moduleIdentifier.startsWith("multi ")
2364
- );
2365
- };
2366
- const warn = (warning) => {
2367
- context.build.warnings.push(warning);
2368
- log.warn(warning);
2369
- };
2370
- const getKeysToIndex = (mod) => {
2371
- const values = {
2372
- identifier: mod.identifier()
2373
- };
2374
- if ("resource" in mod && typeof mod.resource === "string") {
2375
- values.resource = mod.resource;
2376
- }
2377
- if ("request" in mod && typeof mod.request === "string") {
2378
- values.request = mod.request;
2379
- }
2380
- if ("rawRequest" in mod && typeof mod.rawRequest === "string") {
2381
- values.rawRequest = mod.rawRequest;
2382
- }
2383
- if ("userRequest" in mod && typeof mod.userRequest === "string") {
2384
- values.userRequest = mod.userRequest;
2385
- }
2386
- const keysToIndex = /* @__PURE__ */ new Set();
2387
- for (const [key, value] of Object.entries(values)) {
2388
- if (!value) {
2389
- continue;
2390
- }
2391
- if (moduleIndex.has(value)) {
2392
- warn(`Module ${mod.identifier()} is already indexed by ${key}.`);
2393
- if (moduleIndex.get(value) !== mod) {
2394
- warn(`Module ${mod.identifier()} is indexed with a different value.`);
2395
- }
2396
- } else {
2397
- keysToIndex.add(value);
2398
- }
2399
- }
2400
- return keysToIndex;
2401
- };
2402
- const getAllDependencies = (module, dependencies = []) => {
2403
- if ("dependencies" in module) {
2404
- for (const dependency of module.dependencies) {
2405
- dependencies.push(dependency);
2406
- getAllDependencies(dependency, dependencies);
2407
- }
2408
- }
2409
- if ("blocks" in module) {
2410
- for (const block of module.blocks) {
2411
- getAllDependencies(block, dependencies);
2412
- }
2413
- }
2414
- return dependencies;
2415
- };
2416
- const getModuleFromDep = (mod, dep) => {
2417
- if ("request" in dep && dep.request) {
2418
- if (moduleIndex.has(dep.request)) {
2419
- return moduleIndex.get(dep.request);
2420
- }
2421
- if (mod.context && moduleIndex.has(getAbsolutePath(mod.context, dep.request))) {
2422
- return moduleIndex.get(getAbsolutePath(mod.context, dep.request));
2423
- }
2424
- }
2425
- };
2426
- compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
2427
- compilation.hooks.finishModules.tap(
2428
- PLUGIN_NAME,
2429
- (finishedModules) => {
2430
- for (const module of finishedModules) {
2431
- const keysToIndex = getKeysToIndex(module);
2432
- for (const key of keysToIndex) {
2433
- moduleIndex.set(key, module);
2434
- }
2435
- }
2436
- for (const module of finishedModules) {
2437
- const moduleIdentifier = module.identifier();
2438
- const dependencies = new Set(
2439
- getAllDependencies(module).map((dep) => {
2440
- const mod = getModuleFromDep(module, dep);
2441
- if (!mod || !mod.identifier()) {
2442
- return false;
2443
- }
2444
- const identifier = mod.identifier();
2445
- if (!isModuleSupported(identifier)) {
2446
- return false;
2447
- }
2448
- if (identifier === moduleIdentifier) {
2449
- return false;
2450
- }
2451
- return identifier;
2452
- }).filter(Boolean)
2453
- );
2454
- if (!isModuleSupported(moduleIdentifier)) {
2455
- continue;
2456
- }
2457
- for (const depIdentifier of dependencies) {
2458
- const depDeps = tempDeps.get(depIdentifier) || {
2459
- dependencies: /* @__PURE__ */ new Set(),
2460
- dependents: /* @__PURE__ */ new Set()
2461
- };
2462
- depDeps.dependents.add(moduleIdentifier);
2463
- tempDeps.set(depIdentifier, depDeps);
2464
- }
2465
- const moduleDeps = tempDeps.get(moduleIdentifier) || {
2466
- dependents: /* @__PURE__ */ new Set(),
2467
- dependencies: /* @__PURE__ */ new Set()
2468
- };
2469
- for (const moduleDep of dependencies) {
2470
- moduleDeps.dependencies.add(moduleDep);
2471
- }
2472
- tempDeps.set(moduleIdentifier, moduleDeps);
2473
- const file = {
2474
- size: module.size() || 0,
2475
- name: cleanName(context, moduleIdentifier),
2476
- dependencies: /* @__PURE__ */ new Set(),
2477
- dependents: /* @__PURE__ */ new Set(),
2478
- filepath: moduleIdentifier,
2479
- type: getType(moduleIdentifier)
2480
- };
2481
- inputs.push(file);
2482
- reportInputsIndexed.set(moduleIdentifier, file);
2483
- }
2484
- for (const input of inputs) {
2485
- const depsReport = tempDeps.get(input.filepath);
2486
- if (!depsReport) {
2487
- warn(`Could not find dependency report for ${input.name}`);
2488
- continue;
2489
- }
2490
- for (const dependency of depsReport.dependencies) {
2491
- const depInput = reportInputsIndexed.get(dependency);
2492
- if (!depInput) {
2493
- warn(`Could not find input of dependency ${dependency}`);
2494
- continue;
2495
- }
2496
- input.dependencies.add(depInput);
2497
- }
2498
- for (const dependent of depsReport.dependents) {
2499
- const depInput = reportInputsIndexed.get(dependent);
2500
- if (!depInput) {
2501
- warn(`Could not find input of dependent ${dependent}`);
2502
- continue;
2503
- }
2504
- input.dependents.add(depInput);
2505
- }
2506
- }
2507
- }
2508
- );
2509
- });
2510
- compiler.hooks.afterEmit.tap(PLUGIN_NAME, (result) => {
2511
- const chunks = result.chunks;
2512
- const assets = result.getAssets();
2513
- const getChunkFiles = (chunk) => {
2514
- return [...chunk.files || [], ...chunk.auxiliaryFiles || []].map(
2515
- (f) => getAbsolutePath(context.bundler.outDir, f)
2516
- );
2517
- };
2518
- const chunkGraph = result.chunkGraph;
2519
- for (const chunk of chunks) {
2520
- const files = getChunkFiles(chunk);
2521
- const chunkModules = (chunkGraph ? (
2522
- // @ts-expect-error: Reconciliating Webpack 4, Webpack 5 and Rspack is hard.
2523
- chunkGraph?.getChunkModules(chunk)
2524
- ) : (
2525
- // This one is for webpack 4.
2526
- "getModules" in chunk && typeof chunk.getModules === "function" ? chunk.getModules() : []
2527
- )).flatMap((m) => {
2528
- return "modules" in m && Array.isArray(m.modules) ? m.modules.map((m2) => m2.identifier()) : m.identifier();
2529
- }).filter(isModuleSupported);
2530
- for (const file of files) {
2531
- if (getType(file) === "map") {
2532
- continue;
2533
- }
2534
- const fileModules = modulesPerFile.get(file) || [];
2535
- modulesPerFile.set(file, [...fileModules, ...chunkModules]);
2536
- }
2537
- }
2538
- for (const asset of assets) {
2539
- const file = {
2540
- size: asset.source.size() || 0,
2541
- name: asset.name,
2542
- inputs: [],
2543
- filepath: getAbsolutePath(context.bundler.outDir, asset.name),
2544
- type: getType(asset.name)
2545
- };
2546
- reportOutputsIndexed.set(file.filepath, file);
2547
- outputs.push(file);
2548
- if (file.type === "map") {
2549
- tempSourcemaps.push(file);
2550
- continue;
2551
- }
2552
- const fileModules = modulesPerFile.get(file.filepath);
2553
- if (!fileModules) {
2554
- warn(`Could not find modules for ${file.name}`);
2555
- continue;
2556
- }
2557
- for (const moduleIdentifier of fileModules) {
2558
- const inputFound = reportInputsIndexed.get(moduleIdentifier);
2559
- if (!inputFound) {
2560
- warn(`Could not find input of ${moduleIdentifier}`);
2561
- continue;
2562
- }
2563
- file.inputs.push(inputFound);
2564
- }
2565
- }
2566
- for (const sourcemap of tempSourcemaps) {
2567
- const outputFound = reportOutputsIndexed.get(
2568
- sourcemap.filepath.replace(/\.map$/, "")
2569
- );
2570
- if (!outputFound) {
2571
- warn(`Output not found for sourcemap ${sourcemap.name}`);
2572
- continue;
2573
- }
2574
- sourcemap.inputs.push(outputFound);
2575
- }
2576
- for (const [name, entrypoint] of result.entrypoints) {
2577
- const entryOutputs = [];
2578
- const entryInputs = [];
2579
- let size = 0;
2580
- const entryFiles = entrypoint.chunks.flatMap(getChunkFiles);
2581
- const entryFilename = entrypoint.chunks.filter(
2582
- (chunk) => chunkGraph ? (
2583
- // @ts-expect-error: Reconciliating Webpack 4, Webpack 5 and Rspack is hard.
2584
- chunkGraph.getChunkEntryModulesIterable(chunk)
2585
- ) : (
2586
- // This one is for webpack 4.
2587
- "hasEntryModule" in chunk && typeof chunk.hasEntryModule === "function" ? chunk.hasEntryModule() : false
2588
- )
2589
- ).flatMap((c) => Array.from(c.files)).filter(
2590
- (f) => f.includes(name) || entrypoint.name && f.includes(entrypoint.name)
2591
- ).find((f) => getType(f) === "js");
2592
- for (const file2 of entryFiles) {
2593
- const outputFound = reportOutputsIndexed.get(file2);
2594
- if (!file2 || !outputFound) {
2595
- warn(`Could not find output of ${JSON.stringify(file2)}`);
2596
- continue;
2597
- }
2598
- if (outputFound.type !== "map" && !entryOutputs.includes(outputFound)) {
2599
- entryOutputs.push(outputFound);
2600
- entryInputs.push(...outputFound.inputs);
2601
- size += outputFound.size;
2602
- }
2603
- }
2604
- const file = {
2605
- name,
2606
- filepath: entryFilename ? getAbsolutePath(context.bundler.outDir, entryFilename) : "unknown",
2607
- size,
2608
- inputs: Array.from(new Set(entryInputs)),
2609
- outputs: entryOutputs,
2610
- type: entryFilename ? getType(entryFilename) : "unknown"
2611
- };
2612
- entries.push(file);
2613
- }
2614
- for (const error of result.errors) {
2615
- context.build.errors.push(error.message);
2616
- }
2617
- for (const warning of result.warnings) {
2618
- context.build.warnings.push(warning.message);
2619
- }
2620
- context.build.inputs = inputs;
2621
- context.build.outputs = outputs;
2622
- context.build.entries = entries;
2623
- });
2624
- };
2625
-
2626
- const PLUGIN_NAME$3 = "datadog-build-report-plugin";
2627
- const getBuildReportPlugins = (context, log) => {
2628
- return [
2629
- {
2630
- name: PLUGIN_NAME$3,
2631
- enforce: "post",
2632
- esbuild: getEsbuildPlugin(context, log),
2633
- rspack: getXpackPlugin(context, PLUGIN_NAME$3, log),
2634
- webpack: getXpackPlugin(context, PLUGIN_NAME$3, log),
2635
- // Vite and Rollup have the same API.
2636
- vite: getRollupPlugin(context, log),
2637
- rollup: getRollupPlugin(context, log)
2638
- }
2639
- ];
2640
- };
2641
-
2642
- const PLUGIN_NAME$2 = "datadog-bundler-report-plugin";
2643
- const rollupPlugin = (context) => ({
2644
- options(options) {
2645
- context.bundler.rawConfig = options;
2646
- const outputOptions = options.output;
2647
- if (outputOptions) {
2648
- context.bundler.outDir = outputOptions.dir;
2649
- }
2650
- },
2651
- outputOptions(options) {
2652
- if (options.dir) {
2653
- context.bundler.outDir = options.dir;
2654
- }
2655
- }
2656
- });
2657
- const xpackPlugin = (context) => (compiler) => {
2658
- context.bundler.rawConfig = compiler.options;
2659
- if (compiler.options.output?.path) {
2660
- context.bundler.outDir = compiler.options.output.path;
2661
- }
2662
- };
2663
- const getBundlerReportPlugins = (globalContext) => {
2664
- const bundlerReportPlugin = {
2665
- name: PLUGIN_NAME$2,
2666
- enforce: "pre",
2667
- esbuild: {
2668
- setup(build) {
2669
- globalContext.bundler.rawConfig = build.initialOptions;
2670
- if (build.initialOptions.outdir) {
2671
- globalContext.bundler.outDir = build.initialOptions.outdir;
2672
- }
2673
- if (build.initialOptions.outfile) {
2674
- globalContext.bundler.outDir = path.dirname(build.initialOptions.outfile);
2675
- }
2676
- build.initialOptions.metafile = true;
2677
- }
2678
- },
2679
- webpack: xpackPlugin(globalContext),
2680
- rspack: xpackPlugin(globalContext),
2681
- // Vite and Rollup have the same API.
2682
- vite: rollupPlugin(globalContext),
2683
- rollup: rollupPlugin(globalContext)
2684
- };
2685
- return [bundlerReportPlugin];
2686
- };
2687
-
2688
- class TrackedFilesMatcher {
2689
- constructor(trackedFiles) {
2690
- this.trackedFilenames = /* @__PURE__ */ new Map();
2691
- for (const f of trackedFiles) {
2692
- const filename = this.getFilename(f);
2693
- const list = this.trackedFilenames.get(filename);
2694
- if (list) {
2695
- list.push(f);
2696
- } else {
2697
- this.trackedFilenames.set(filename, new Array(f));
2698
- }
2699
- }
2700
- }
2701
- displaySource(src) {
2702
- if (src.length <= 40) {
2703
- return src;
2704
- }
2705
- return `[...]${src.slice(-35)}`;
2706
- }
2707
- // Looks up the sources declared in the sourcemap and return a list of related tracked files.
2708
- matchSourcemap(srcmapPath, onSourcesNotFound) {
2709
- const buff = fs.readFileSync(srcmapPath, "utf8");
2710
- const srcmapObj = JSON.parse(buff);
2711
- if (!srcmapObj.sources) {
2712
- onSourcesNotFound(`Missing 'sources' field in sourcemap.`);
2713
- return void 0;
2714
- }
2715
- const sources = srcmapObj.sources;
2716
- if (sources.length === 0) {
2717
- onSourcesNotFound(`Empty 'sources' field in sourcemap.`);
2718
- return void 0;
2719
- }
2720
- const filtered = this.matchSources(sources);
2721
- if (filtered.length === 0) {
2722
- onSourcesNotFound(
2723
- `${sources.map(this.displaySource).join(", ")} not in the tracked files.`
2724
- );
2725
- return void 0;
2726
- }
2727
- return filtered;
2728
- }
2729
- matchSources(sources) {
2730
- let filtered = [];
2731
- const filenameAlreadyMatched = /* @__PURE__ */ new Set();
2732
- for (const source of sources) {
2733
- const filename = this.getFilename(source);
2734
- if (filenameAlreadyMatched.has(filename)) {
2735
- continue;
2736
- }
2737
- filenameAlreadyMatched.add(filename);
2738
- const trackedFiles = this.trackedFilenames.get(filename);
2739
- if (trackedFiles) {
2740
- filtered = filtered.concat(trackedFiles);
2741
- }
2742
- }
2743
- return filtered;
2744
- }
2745
- // Return a list of all tracked files
2746
- rawTrackedFilesList() {
2747
- let rawList = [];
2748
- this.trackedFilenames.forEach((value) => {
2749
- rawList = rawList.concat(value);
2750
- });
2751
- return rawList;
2752
- }
2753
- // Extract the filename from a path.
2754
- //
2755
- // We are removing any suffix that is after the character '?'. The only reason this is done
2756
- // is because we noticed that a non-negligible (~5%) amount of source paths from our customers
2757
- // source maps contained query parameters.
2758
- // We are assuming that the files may not actually be named with the interrogation mark but that
2759
- // it is only an artifact of the build process. The query parameters look random. It looks
2760
- // like it may be used as a trick to force a web browser to reload the file content.
2761
- // The only side effect of doing that operation is that more tracked files paths may be sent
2762
- // alongside the sourcemap which is not a problem.
2763
- // Example: webpack:///./src/folder/ui/select.vue?821e
2764
- getFilename(s) {
2765
- let start = s.lastIndexOf("/");
2766
- if (start === -1) {
2767
- start = 0;
2768
- } else {
2769
- start++;
2770
- }
2771
- let end = s.lastIndexOf("?");
2772
- if (end === -1 || end <= start) {
2773
- end = s.length;
2774
- }
2775
- return s.substring(start, end);
2776
- }
2777
- }
2778
-
2779
- const newSimpleGit = async (cwd) => {
2780
- const options = {
2781
- baseDir: cwd || process.cwd(),
2782
- binary: "git",
2783
- // We are invoking at most 3 git commands at the same time.
2784
- maxConcurrentProcesses: 3
2785
- };
2786
- try {
2787
- const git = simpleGit.simpleGit(options);
2788
- const root = await git.revparse("--show-toplevel");
2789
- options.baseDir = root;
2790
- } catch {
2791
- }
2792
- return simpleGit.simpleGit(options);
2793
- };
2794
- const gitRemote = async (git) => {
2795
- const remotes = await git.getRemotes(true);
2796
- if (remotes.length === 0) {
2797
- throw new Error("No git remotes available");
2798
- }
2799
- const defaultRemote = await getDefaultRemoteName(git);
2800
- for (const remote of remotes) {
2801
- if (remote.name === defaultRemote) {
2802
- return stripCredentials(remote.refs.push);
2803
- }
2804
- }
2805
- return stripCredentials(remotes[0].refs.push);
2806
- };
2807
- const getDefaultRemoteName = async (git) => {
2808
- try {
2809
- return (await git.getConfig("clone.defaultRemoteName"))?.value ?? "origin";
2810
- } catch (e) {
2811
- return "origin";
2812
- }
2813
- };
2814
- const stripCredentials = (remote) => {
2815
- try {
2816
- const url$1 = new url.URL(remote);
2817
- url$1.username = "";
2818
- url$1.password = "";
2819
- return url$1.toString();
2820
- } catch {
2821
- return remote;
2822
- }
2823
- };
2824
- const gitHash = async (git) => git.revparse("HEAD");
2825
- const gitTrackedFiles = async (git) => {
2826
- const files = await git.raw("ls-files");
2827
- return files.split(/\r\n|\r|\n/);
2828
- };
2829
- const getRepositoryData = async (git, repositoryURL) => {
2830
- let remote;
2831
- let hash;
2832
- let trackedFiles;
2833
- {
2834
- [remote, hash, trackedFiles] = await Promise.all([
2835
- gitRemote(git),
2836
- gitHash(git),
2837
- gitTrackedFiles(git)
2838
- ]);
2839
- }
2840
- const data = {
2841
- hash,
2842
- remote,
2843
- trackedFilesMatcher: new TrackedFilesMatcher(trackedFiles)
2844
- };
2845
- return data;
2846
- };
2847
-
2848
- const PLUGIN_NAME$1 = "datadog-git-plugin";
2849
- const getGitPlugins = (options, context) => {
2850
- return [
2851
- {
2852
- name: PLUGIN_NAME$1,
2853
- enforce: "pre",
2854
- async buildStart() {
2855
- const shouldGetGitInfo = options.rum?.sourcemaps && options.disableGit !== true;
2856
- if (!shouldGetGitInfo) {
2857
- return;
2858
- }
2859
- const repositoryData = await getRepositoryData(await newSimpleGit(context.cwd));
2860
- context.git = repositoryData;
2861
- }
2862
- }
2863
- ];
2864
- };
2865
-
2866
- const PREPARATION_PLUGIN_NAME = "datadog-injection-preparation-plugin";
2867
- const PLUGIN_NAME = "datadog-injection-plugin";
2868
- const DISTANT_FILE_RX = /^https?:\/\//;
2869
-
2870
- const MAX_TIMEOUT_IN_MS = 5e3;
2871
- const processDistantFile = async (item, timeout = MAX_TIMEOUT_IN_MS) => {
2872
- let timeoutId;
2873
- return Promise.race([
2874
- doRequest({ url: item.value }).finally(() => {
2875
- if (timeout) {
2876
- clearTimeout(timeoutId);
2877
- }
2878
- }),
2879
- new Promise((_, reject) => {
2880
- timeoutId = setTimeout(() => {
2881
- reject(new Error("Timeout"));
2882
- }, timeout);
2883
- })
2884
- ]);
2885
- };
2886
- const processLocalFile = async (item) => {
2887
- const absolutePath = getAbsolutePath(process.cwd(), item.value);
2888
- return fsp.readFile(absolutePath, { encoding: "utf-8" });
2889
- };
2890
- const processRawCode = async (item) => {
2891
- return item.value;
2892
- };
2893
- const processItem = async (item, log) => {
2894
- let result;
2895
- try {
2896
- if (item.type === "file") {
2897
- if (item.value.match(DISTANT_FILE_RX)) {
2898
- result = await processDistantFile(item);
2899
- } else {
2900
- result = await processLocalFile(item);
2901
- }
2902
- } else if (item.type === "code") {
2903
- result = await processRawCode(item);
2904
- } else {
2905
- throw new Error(`Invalid item type "${item.type}", only accepts "code" or "file".`);
2906
- }
2907
- } catch (error) {
2908
- const itemId = `${item.type} - ${truncateString(item.value)}`;
2909
- if (item.fallback) {
2910
- log.warn(`Fallback for "${itemId}": ${error.toString()}`);
2911
- result = await processItem(item.fallback, log);
2912
- } else {
2913
- log.warn(`Failed "${itemId}": ${error.toString()}`);
2914
- result = "";
2915
- }
2916
- }
2917
- return result;
2918
- };
2919
- const processInjections = async (toInject, log) => {
2920
- const proms = [];
2921
- for (const item of toInject) {
2922
- proms.push(processItem(item, log));
2923
- }
2924
- const results = await Promise.all(proms);
2925
- return results.filter(Boolean);
2926
- };
2927
-
2928
- const getInjectionPlugins = (bundler, context, toInject, log) => {
2929
- const contentToInject = [];
2930
- const getContentToInject = () => {
2931
- const before = `
2932
- /********************************************/
2933
- /* BEGIN INJECTION BY DATADOG BUILD PLUGINS */`;
2934
- const after = `
2935
- /* END INJECTION BY DATADOG BUILD PLUGINS */
2936
- /********************************************/`;
2937
- return `${before}
2938
- ${contentToInject.join("\n\n")}
2939
- ${after}`;
2940
- };
2941
- const rollupInjectionPlugin = {
2942
- banner(chunk) {
2943
- if (chunk.isEntry) {
2944
- return getContentToInject();
2945
- }
2946
- return "";
2947
- }
2948
- };
2949
- const INJECTED_FILE_PATH = `${Date.now()}.${performance.now()}.${INJECTED_FILE}.js`;
2950
- const plugins = [
2951
- // Prepare and fetch the content to inject for all bundlers.
2952
- {
2953
- name: PREPARATION_PLUGIN_NAME,
2954
- enforce: "pre",
2955
- // We use buildStart as it is the first async hook.
2956
- async buildStart() {
2957
- const results = await processInjections(toInject, log);
2958
- contentToInject.push(...results);
2959
- if (context.bundler.name !== "esbuild") {
2960
- return;
2961
- }
2962
- const absolutePathInjectFile = path.resolve(
2963
- context.bundler.outDir,
2964
- INJECTED_FILE_PATH
2965
- );
2966
- try {
2967
- if (fs.existsSync(absolutePathInjectFile)) {
2968
- log.warn(`Temporary file "${INJECTED_FILE_PATH}" already exists.`);
2969
- }
2970
- await outputFile(absolutePathInjectFile, getContentToInject());
2971
- } catch (e) {
2972
- log.error(`Could not create the file: ${e.message}`);
2973
- }
2974
- },
2975
- async buildEnd() {
2976
- if (context.bundler.name !== "esbuild") {
2977
- return;
2978
- }
2979
- const absolutePathInjectFile = path.resolve(
2980
- context.bundler.outDir,
2981
- INJECTED_FILE_PATH
2982
- );
2983
- log.debug(`Removing temporary file "${INJECTED_FILE_PATH}".`);
2984
- await rm(absolutePathInjectFile);
2985
- }
2986
- },
2987
- // Inject the file that will be home of all injected content.
2988
- // Each bundler has its own way to inject a file.
2989
- {
2990
- name: PLUGIN_NAME,
2991
- esbuild: {
2992
- setup(build) {
2993
- const { initialOptions } = build;
2994
- const absolutePathInjectFile = path.resolve(
2995
- context.bundler.outDir,
2996
- INJECTED_FILE_PATH
2997
- );
2998
- initialOptions.inject = initialOptions.inject || [];
2999
- initialOptions.inject.push(absolutePathInjectFile);
3000
- }
3001
- },
3002
- webpack: (compiler) => {
3003
- const BannerPlugin = compiler?.webpack?.BannerPlugin || bundler?.BannerPlugin || bundler?.default?.BannerPlugin;
3004
- compiler?.webpack?.ChunkGraph || bundler?.ChunkGraph || bundler?.default?.ChunkGraph;
3005
- if (!BannerPlugin) {
3006
- log.error("Missing BannerPlugin");
3007
- }
3008
- let chunkGraph;
3009
- compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
3010
- compilation.hooks.afterChunks.tap(PLUGIN_NAME, () => {
3011
- chunkGraph = compilation.chunkGraph;
3012
- });
3013
- });
3014
- compiler.options.plugins = compiler.options.plugins || [];
3015
- compiler.options.plugins.push(
3016
- new BannerPlugin({
3017
- // Not wrapped in comments.
3018
- raw: true,
3019
- // Doesn't seem to work, but it's supposed to only add
3020
- // the banner to entry modules.
3021
- entryOnly: true,
3022
- banner(data) {
3023
- if (context.bundler.variant === "5") {
3024
- if (!chunkGraph || chunkGraph.getNumberOfEntryModules(data.chunk) === 0) {
3025
- return "";
3026
- }
3027
- return getContentToInject();
3028
- } else {
3029
- if (!data.chunk?.hasEntryModule()) {
3030
- return "";
3031
- }
3032
- return getContentToInject();
3033
- }
3034
- }
3035
- })
3036
- );
3037
- },
3038
- rspack: (compiler) => {
3039
- compiler.options.plugins = compiler.options.plugins || [];
3040
- compiler.options.plugins.push(
3041
- new compiler.rspack.BannerPlugin({
3042
- // Not wrapped in comments.
3043
- raw: true,
3044
- // Only entry modules.
3045
- entryOnly: true,
3046
- banner() {
3047
- return getContentToInject();
3048
- }
3049
- })
3050
- );
3051
- },
3052
- rollup: rollupInjectionPlugin,
3053
- vite: rollupInjectionPlugin
3054
- }
3055
- ];
3056
- return plugins;
3057
- };
3058
-
3059
- const helpers$1 = {
3060
- // Each product should have a unique entry.
3061
- // #helpers-injection-marker
3062
- [CONFIG_KEY]: helpers$2
3063
- // #helpers-injection-marker
3064
- };
3065
- const HOST_NAME = "datadog-build-plugins";
3066
- const buildPluginFactory = ({
3067
- bundler,
3068
- version
3069
- }) => {
3070
- return unplugin.createUnplugin((opts, unpluginMetaContext) => {
3071
- const options = validateOptions$2(opts);
3072
- if (unpluginMetaContext.framework === "esbuild") {
3073
- unpluginMetaContext.esbuildHostName = HOST_NAME;
3074
- }
3075
- const injections = [];
3076
- const context = getContext({
3077
- options,
3078
- bundlerVersion: bundler.version || bundler.VERSION,
3079
- bundlerName: unpluginMetaContext.framework,
3080
- injections,
3081
- version
3082
- });
3083
- const getLogger = getLoggerFactory(context.build, options.logLevel);
3084
- context.pluginNames.push(HOST_NAME);
3085
- const plugins = [
3086
- // Prefill with our internal plugins.
3087
- // #internal-plugins-injection-marker
3088
- ...getBuildReportPlugins(context, getLogger("datadog-build-report-plugin")),
3089
- ...getBundlerReportPlugins(context),
3090
- ...getGitPlugins(options, context),
3091
- ...getInjectionPlugins(
3092
- bundler,
3093
- context,
3094
- injections,
3095
- getLogger("datadog-injection-plugin")
3096
- )
3097
- // #internal-plugins-injection-marker
3098
- ];
3099
- if (options.customPlugins) {
3100
- const customPlugins = options.customPlugins(
3101
- options,
3102
- context,
3103
- getLogger("datadog-custom-plugins")
3104
- );
3105
- plugins.push(...customPlugins);
3106
- }
3107
- if (options[CONFIG_KEY$1] && options[CONFIG_KEY$1].disabled !== true) {
3108
- plugins.push(
3109
- ...getPlugins$1(options, context, getLogger(PLUGIN_NAME$5))
3110
- );
3111
- }
3112
- if (options[CONFIG_KEY] && options[CONFIG_KEY].disabled !== true) {
3113
- plugins.push(
3114
- ...getPlugins(
3115
- options,
3116
- context,
3117
- getLogger(PLUGIN_NAME$4)
3118
- )
3119
- );
3120
- }
3121
- context.pluginNames.push(...plugins.map((plugin) => plugin.name));
3122
- return plugins;
3123
- });
3124
- };
3125
-
3126
- var name = "@datadog/rspack-plugin";
3127
- var packageManager = "yarn@4.0.2";
3128
- var version$1 = "2.4.2";
3129
- var license = "MIT";
3130
- var author = "Datadog";
3131
- var description = "Datadog Rspack Plugin";
3132
- var keywords = [
3133
- "datadog",
3134
- "rspack",
3135
- "bundler",
3136
- "plugin",
3137
- "unplugin"
3138
- ];
3139
- var homepage = "https://github.com/DataDog/build-plugins#readme";
3140
- var repository = {
3141
- type: "git",
3142
- url: "https://github.com/DataDog/build-plugins",
3143
- directory: "packages/published/rspack-plugin"
3144
- };
3145
- var main = "./dist/src/index.js";
3146
- var module$1 = "./dist/src/index.mjs";
3147
- var exports$1 = {
3148
- ".": "./src/index.ts"
3149
- };
3150
- var publishConfig = {
3151
- access: "public",
3152
- types: "./dist/src/index.d.ts",
3153
- exports: {
3154
- "./package.json": "./package.json",
3155
- ".": {
3156
- "import": "./dist/src/index.mjs",
3157
- require: "./dist/src/index.js",
3158
- types: "./dist/src/index.d.ts"
3159
- }
3160
- }
3161
- };
3162
- var files = [
3163
- "dist"
3164
- ];
3165
- var scripts = {
3166
- build: "yarn clean && rollup --config rollup.config.mjs",
3167
- clean: "rm -rf dist",
3168
- prepack: "yarn build",
3169
- typecheck: "tsc --noEmit",
3170
- watch: "yarn clean && rollup --config rollup.config.mjs --watch"
3171
- };
3172
- var dependencies = {
3173
- "async-retry": "1.3.3",
3174
- chalk: "2.3.1",
3175
- glob: "11.0.0",
3176
- outdent: "0.8.0",
3177
- "p-queue": "6.6.2",
3178
- "pretty-bytes": "5.6.0",
3179
- "simple-git": "3.25.0",
3180
- unplugin: "1.16.0"
3181
- };
3182
- var devDependencies = {
3183
- "@babel/core": "7.24.5",
3184
- "@babel/preset-env": "7.24.5",
3185
- "@babel/preset-typescript": "7.24.1",
3186
- "@dd/factory": "workspace:*",
3187
- "@dd/tools": "workspace:*",
3188
- "@rollup/plugin-babel": "6.0.4",
3189
- "@rollup/plugin-commonjs": "28.0.1",
3190
- "@rollup/plugin-json": "6.1.0",
3191
- "@rollup/plugin-node-resolve": "15.3.0",
3192
- "@types/babel__core": "^7",
3193
- "@types/babel__preset-env": "^7",
3194
- esbuild: "0.24.0",
3195
- rollup: "4.24.2",
3196
- "rollup-plugin-dts": "6.1.1",
3197
- "rollup-plugin-esbuild": "6.1.1",
3198
- typescript: "5.4.3"
3199
- };
3200
- var peerDependencies = {
3201
- "@rspack/core": "1.x"
3202
- };
3203
- var pkg = {
3204
- name: name,
3205
- packageManager: packageManager,
3206
- version: version$1,
3207
- license: license,
3208
- author: author,
3209
- description: description,
3210
- keywords: keywords,
3211
- homepage: homepage,
3212
- repository: repository,
3213
- main: main,
3214
- module: module$1,
3215
- exports: exports$1,
3216
- publishConfig: publishConfig,
3217
- files: files,
3218
- scripts: scripts,
3219
- dependencies: dependencies,
3220
- devDependencies: devDependencies,
3221
- peerDependencies: peerDependencies
3222
- };
3223
-
3224
- const datadogRspackPlugin = buildPluginFactory({
3225
- bundler: rspack,
3226
- version: pkg.version
3227
- }).rspack;
3228
- const version = pkg.version;
3229
- const helpers = helpers$1;
3230
-
3231
- exports.datadogRspackPlugin = datadogRspackPlugin;
3232
- exports.helpers = helpers;
3233
- exports.version = version;
1
+ "use strict";var e=require("unplugin"),t=require("chalk"),n=require("outdent"),s=require("path"),o=require("async-retry"),r=require("fs/promises"),i=require("fs"),a=require("glob"),u=require("buffer"),p=require("p-queue"),c=require("stream"),l=require("zlib"),d=require("pretty-bytes"),f=require("perf_hooks"),m=require("simple-git"),h=require("url"),g=require("module"),w=require("@rspack/core");const y="__datadog-helper-file",b=["development","production","test"],v={debug:0,info:1,warn:2,error:3,none:4},$=(e,n="warn")=>s=>{const o=(e=>e.split(">").map((e=>e.replace(/^datadog-|-plugin$/g,""))).join(">"))(s),r=(s,r="debug")=>{let i=t.dim,a=console.log;"error"===r?(i=t.red,a=console.error):"warn"===r?(i=t.yellow,a=console.warn):"info"===r&&(i=t.cyan,a=console.log);const u=`[${r}|${e.bundler.fullName}|${o}]`,p="string"==typeof s?s:JSON.stringify(s,null,2);e.logs.push({bundler:e.bundler.fullName,pluginName:o,type:r,message:p,time:Date.now()}),"error"===r&&e.errors.push(p),"warn"===r&&e.warnings.push(p),v[r]>=v[n]&&a(`${i(u)} ${p}`)};return{getLogger:t=>$(e,n)(`${o}>${t}`),error:e=>r(e,"error"),warn:e=>r(e,"warn"),info:e=>r(e,"info"),debug:e=>r(e,"debug")}},k="errorTracking",S="datadog-error-tracking-plugin",D=(e,n,o)=>{if(".map"!==s.extname(o))throw new Error(`The file ${t.green.bold(o)} is not a sourcemap.`);const r=o.replace(/\.map$/,""),i=r.replace(n.bundler.outDir,"");return{minifiedFilePath:r,minifiedUrl:e.minifiedPathPrefix?s.join(e.minifiedPathPrefix,i):i,relativePath:i}},E=e=>{const t=Math.floor(e/1e3/60/60/24),n=new Date(e-24*t*60*60*1e3),s=n.getUTCHours(),o=n.getUTCMinutes(),r=n.getUTCSeconds(),i=n.getUTCMilliseconds();return`${t?`${t}d `:""}${s?`${s}h `:""}${o?`${o}m `:""}${r?`${r}s `:""}${i?`${i}ms`:""}`.trim()},M=async(e,t,n)=>{const s=[],o=e.initialOptions.entryPoints,r=[],i=[];if(Array.isArray(o))for(const e of o){const t=e&&"object"==typeof e?e.in:e;r.push({path:t})}else o&&"object"==typeof o&&r.push(...Object.entries(o).map((([e,t])=>({name:e,path:t}))));const u=r.flatMap((e=>{return(t=e.path,t.includes("*")?a.glob.sync(t):[t]).map((t=>[e,t]));var t})).map((async([n,o])=>{const r=await e.resolve(o,{kind:"entry-point",resolveDir:t.cwd});r.errors.length&&i.push(...r.errors.map((e=>e.text))),r.path&&s.push({name:n.name,resolved:r.path,original:n.path})}));for(const e of i)n.error(e);return await Promise.all(u),s},P=[400,403,413],j=e=>{const{auth:t,url:n,method:s="GET",getData:r,type:i="text"}=e,a={retries:0===e.retries?0:e.retries||5,onRetry:e.onRetry,maxTimeout:e.maxTimeout,minTimeout:e.minTimeout};return o((async(e,o)=>{let a;try{const e={method:s,duplex:"half"};let o={};if(t?.apiKey&&(o["DD-API-KEY"]=t.apiKey),t?.appKey&&(o["DD-APPLICATION-KEY"]=t.appKey),"function"==typeof r){const{data:t,headers:n}=await r();e.body=t,o={...o,...n}}a=await fetch(n,{...e,headers:o})}catch(t){return e(t),{}}if(!a.ok){const t=`HTTP ${a.status} ${a.statusText}`;if(P.includes(a.status))return e(new Error(t)),{};throw new Error(t)}try{let e;return e="json"===i?await a.json():await a.text(),e}catch(t){return e(t),{}}}),a)},T=(e,t=60,n="[...]")=>{if(e.length<=t)return e;const s=Math.max(4,t-n.length),o=Math.min(10,Math.floor(s/2)),r=s-o;return`${e.slice(0,o)}${n}${e.slice(-r)}`},O=e=>e.includes(y),z=async e=>r.rm(e,{force:!0,maxRetries:3,recursive:!0}),N=async(e,t)=>{await(async e=>r.mkdir(e,{recursive:!0}))(s.dirname(e)),await r.writeFile(e,t,{encoding:"utf-8"})},R=(e,t)=>{var n;n=s.dirname(e),i.mkdirSync(n,{recursive:!0}),i.writeFileSync(e,t,{encoding:"utf-8"})};let x=0;const I=()=>`${Date.now()}.${performance.now()}.${++x}`,A=/[/]+|[\\]+/g,F=/^[/]+|^[\\]+|[/]+$|[\\]+$/g,q=(e,t)=>{const n=e.replace(F,"").split(A),s=t.replace(F,"").split(A),o=n.join("/");let r="";for(let e=0;e<s.length;e+=1){const t=s.slice(-e).join("/");o.startsWith(t)&&(r=t)}return r},C=async e=>{const t={empty:!1,exists:!0};try{0===(await i.promises.stat(e)).size&&(t.empty=!0)}catch(e){if("ENOENT"!==e.code)throw e;t.exists=!1}return t},L=async(e,t,n,o)=>{const r=await(async(e,t)=>{const[n,s]=await Promise.all([C(e.minifiedFilePath),C(e.sourcemapFilePath)]);return{file:n,sourcemap:s,repeatedPrefix:q(e.relativePath,t)}})(e,n),i=[],a=[],u=new Map([["event",{type:"string",options:{contentType:"application/json",filename:"event"},value:JSON.stringify({...t,minified_url:e.minifiedUrl})}],["source_map",{type:"file",path:e.sourcemapFilePath,options:{filename:"source_map",contentType:"application/json"}}],["minified_file",{type:"file",path:e.minifiedFilePath,options:{filename:"minified_file",contentType:"application/javascript"}}]]);if(o)try{u.set("repository",{type:"string",options:{contentType:"application/json",filename:"repository"},value:JSON.stringify({data:[{files:o.trackedFilesMatcher.matchSourcemap(e.sourcemapFilePath,(t=>{a.push(`${s.basename(e.sourcemapFilePath)}: "${t}"`)})),hash:o.hash,repository_url:o.remote}],version:1})})}catch(t){a.push(`Could not attach git data for sourcemap ${e.sourcemapFilePath}: ${t.message}`)}return r.file.empty&&i.push(`Minified file is empty: ${e.minifiedFilePath}`),r.file.exists||i.push(`Minified file not found: ${e.minifiedFilePath}`),r.sourcemap.empty&&i.push(`Sourcemap file is empty: ${e.sourcemapFilePath}`),r.sourcemap.exists||i.push(`Sourcemap file not found: ${e.sourcemapFilePath}`),r.repeatedPrefix&&a.push(`The minified file path contains a repeated pattern with the minified path prefix: ${r.repeatedPrefix}`),{content:u,errors:i,warnings:a}},_=t.green.bold,K=t.yellow.bold,B=t.red.bold,H=async(e,t)=>{if("function"==typeof i.openAsBlob){const n=await i.openAsBlob(e,{type:t.contentType});return new u.File([n],t.filename)}{const n=c.Readable.toWeb(i.createReadStream(e)),s=await new Response(n).blob();return new u.File([s],t.filename,{type:t.contentType})}},U=(e,t={})=>async()=>{const n=new FormData,s=l.createGzip();for(const[t,s]of e.content){const e="file"===s.type?await H(s.path,s.options):new Blob([s.value],{type:s.options.contentType});n.append(t,e,s.options.filename)}const o=new Request("fake://url",{method:"POST",body:n});return{data:c.Readable.fromWeb(o.body).pipe(s),headers:{"Content-Encoding":"gzip",...t,...Object.fromEntries(o.headers.entries())}}},W=async(e,t,n,s)=>{const o=Date.now(),r=t.minifiedPathPrefix,i={git_repository_url:n.git?.remote,git_commit_sha:n.git?.hash,plugin_version:n.version,project_path:n.bundler.outDir,service:t.service,type:"js_sourcemap",version:t.releaseVersion},a=await Promise.all(e.map((e=>L(e,i,r,n.git)))),u=a.map((e=>e.errors)).flat(),c=a.map((e=>e.warnings)).flat();if(c.length>0&&s.warn(`Warnings while preparing payloads:\n - ${c.join("\n - ")}`),u.length>0){const e=`Failed to prepare payloads, aborting upload :\n - ${u.join("\n - ")}`;if(s.error(e),!0===t.bailOnError)throw new Error(e);return}const{errors:l,warnings:d}=await(async(e,t,n,s)=>{const o=[],r=[];if(!n.auth?.apiKey)return o.push({error:new Error("No authentication token provided")}),{errors:o,warnings:r};if(0===e.length)return r.push("No sourcemaps to upload"),{errors:o,warnings:r};const i=new(p.default?p.default:p)({concurrency:t.maxConcurrency}),a={"DD-API-KEY":n.auth.apiKey,"DD-EVP-ORIGIN":`${n.bundler.fullName}-build-plugin_sourcemaps`,"DD-EVP-ORIGIN-VERSION":n.version},u=[];for(const p of e){const e={sourcemap:p.content.get("source_map")?.path.replace(n.bundler.outDir,"."),file:p.content.get("minified_file")?.path.replace(n.bundler.outDir,".")};s.debug(`Queuing ${_(e.sourcemap)} | ${_(e.file)}`),u.push(i.add((async()=>{try{await j({url:t.intakeUrl,method:"POST",getData:U(p,a),onRetry:(t,n)=>{const o=`Failed to upload ${K(e.sourcemap)} | ${K(e.file)}:\n ${t.message}\nRetrying ${n}/5`;r.push(o),s.debug(o)}}),s.debug(`Sent ${_(e.sourcemap)} | ${_(e.file)}`)}catch(n){if(o.push({metadata:e,error:n}),!0===t.bailOnError)throw n}})))}return await Promise.all(u),await i.onIdle(),{warnings:r,errors:o}})(a,t,n,s);if(s.info(`Done uploading ${_(e.length.toString())} sourcemaps in ${_(E(Date.now()-o))}.`),l.length>0){const e=`Failed to upload some sourcemaps:\n${` - ${l.map((({metadata:e,error:t})=>e?`${B(e.file)} | ${B(e.sourcemap)} : ${t.message}`:t.message)).join("\n - ")}`}`;if(s.error(e),!0===t.bailOnError)throw new Error(e)}d.length>0&&s.warn(`Warnings while uploading sourcemaps:\n - ${d.join("\n - ")}`)},G=async(e,s,o)=>{const r=t.green.bold,i=Object.entries(e.sourcemaps).map((([e,t])=>` - ${e}: ${r(t.toString())}`)).join("\n"),a=((e,t)=>{if(!t.build.outputs||0===t.build.outputs.length)throw new Error("No output files found.");return t.build.outputs.filter((e=>e.filepath.endsWith(".map"))).map((e=>e.filepath)).map((n=>({...D(e,t,n),sourcemapFilePath:n,minifiedPathPrefix:e.minifiedPathPrefix})))})(e.sourcemaps,s),u=n.outdent`
2
+ Uploading ${r(a.length.toString())} sourcemaps with configuration:
3
+ ${i}
4
+ `;o.info(u),await W(a,e.sourcemaps,s,o)},J=`https://sourcemap-intake.${process.env.DATADOG_SITE||"datadoghq.com"}/api/v2/srcmap`,V=e=>{const n=t.bold.red,s=e[k]||{},o={errors:[]};if(s.sourcemaps){s.sourcemaps.releaseVersion||o.errors.push(`${n("sourcemaps.releaseVersion")} is required.`),s.sourcemaps.service||o.errors.push(`${n("sourcemaps.service")} is required.`),s.sourcemaps.minifiedPathPrefix||o.errors.push(`${n("sourcemaps.minifiedPathPrefix")} is required.`),s.sourcemaps.minifiedPathPrefix&&((e=>{let t;try{t=new URL(e).host}catch{}return!(!t&&!e.startsWith("/"))})(s.sourcemaps.minifiedPathPrefix)||o.errors.push(`${n("sourcemaps.minifiedPathPrefix")} must be a valid URL or start with '/'.`));const e={bailOnError:!1,disableGit:!1,dryRun:!1,maxConcurrency:20,intakeUrl:process.env.DATADOG_SOURCEMAP_INTAKE_URL||s.sourcemaps.intakeUrl||J,...s.sourcemaps};o.config=e}return o},Y=(e,t)=>{const n=t.getLogger(S),s=((e,t)=>{const n=[],s=V(e);if(n.push(...s.errors),n.length)throw t.error(`\n - ${n.join("\n - ")}`),new Error(`Invalid configuration for ${S}.`);const o={...e[k],sourcemaps:void 0};return s.config&&(o.sourcemaps=s.config),o})(e,n);return[{name:S,enforce:"post",async writeBundle(){s.disabled||s.sourcemaps&&await G(s,t,n)}}]};var Q=(e=>(e[e.BEFORE=0]="BEFORE",e[e.MIDDLE=1]="MIDDLE",e[e.AFTER=2]="AFTER",e))(Q||{});const X="rum",Z="datadog-rum-plugin",ee=e=>`DD_RUM.init({${JSON.stringify(e.sdk).replace(/(^{|}$)/g,"")}});\n`,te=(e,t)=>{const n=e.sdk;if(n.clientToken)return ee(e);if(!t.auth?.apiKey||!t.auth?.appKey)throw new Error('Missing "auth.apiKey" and/or "auth.appKey" to fetch "rum.sdk.clientToken".');return async()=>{let s;try{const e=await j({url:`https://api.datadoghq.com/api/v2/rum/applications/${n.applicationId}`,type:"json",auth:t.auth});s=e.data?.attributes?.client_token}catch(e){throw new Error(`Could not fetch the clientToken: ${e.message}`)}if(!s)throw new Error("Missing clientToken in the API response.");return ee({...e,sdk:{clientToken:s,...n}})}},ne=e=>{const n=t.bold.red,s=e[X]||{},o={errors:[]};if(s.sdk){s.sdk.applicationId||o.errors.push(`Missing ${n("applicationId")} in the SDK configuration.`),e.auth?.apiKey&&e.auth?.appKey||s.sdk.clientToken||o.errors.push(`Missing ${n('"auth.apiKey"')} and/or ${n('"auth.appKey"')} to fetch missing client token.`);const t={applicationId:"unknown_application_id",allowUntrustedEvents:!1,compressIntakeRequests:!1,defaultPrivacyLevel:"mask",enablePrivacyForActionName:!1,sessionReplaySampleRate:0,sessionSampleRate:100,silentMultipleInit:!1,site:"datadoghq.com",startSessionReplayRecordingManually:!1,storeContextsAcrossPages:!1,telemetrySampleRate:20,traceSampleRate:100,trackingConsent:"granted",trackLongTasks:!1,trackResources:!1,trackUserInteractions:!1,trackViewsManually:!1};o.config={...t,...s.sdk}}return o},se=(e,t)=>{const n=((e,t)=>{const n=[],s=ne(e);if(n.push(...s.errors),n.length)throw t.error(`\n - ${n.join("\n - ")}`),new Error(`Invalid configuration for ${Z}.`);const o={...e[X],sdk:void 0};return s.config&&(o.sdk=s.config),o})(e,t.getLogger(Z));return n.sdk&&(t.inject({type:"file",position:Q.MIDDLE,value:s.join(__dirname,"./rum-browser-sdk.js")}),t.inject({type:"code",position:Q.MIDDLE,value:te(n,t)})),[]},oe="telemetry",re="datadog-telemetry-plugin",ie=[e=>/modules\.tree\.(count|size)$/.test(e.metric)?null:e,e=>e.tags.some((e=>/^assetName:.*\.map$/.test(e)||/^moduleName:\/node_modules/.test(e)))?null:e,e=>{const t={size:1e5,count:10,duration:1e3};return/(entries|loaders|warnings|errors)\.count$/.test(e.metric)&&(t.count=0),/(modules\.(dependencies|dependents)$)/.test(e.metric)&&(t.count=30),/modules\.tree\.count$/.test(e.metric)&&(t.count=150),/modules\.tree\.size$/.test(e.metric)&&(t.size=15e5),/entries\.size$/.test(e.metric)&&(t.size=0),/entries\.modules\.count$/.test(e.metric)&&(t.count=0),e.value>t[e.type]?e:null}],ae=(e,t)=>({type:"gauge",tags:[...e.tags,...t.tags],metric:`${t.prefix?`${t.prefix}.`:""}${e.metric}`,points:[[t.timestamp,e.value]]}),ue=(e="")=>e.endsWith("/")?e:`${e}/`,pe=(e,t)=>{let n=e;return e.split(ue(t)),n.split("!").pop().replace(/(.*)?\/node_modules\//,"/node_modules/").replace(/^((\.)*\/)+/,"")},ce=(e,t)=>e.split("!").pop().replace(ue(t),"./"),le=(e,t,n)=>{let s=e.name||e.userRequest;return s||(s=((e,t)=>{let n=e.userRequest;if(!n){let s;s=t.moduleGraph&&"function"==typeof t.moduleGraph.getIssuer?t.moduleGraph.getIssuer(e):e.issuer,n=s?.userRequest,n||(n=e._identifier?.split("!").pop())}return n||"unknown"})(e,t)),ce(s||"no-name",n)},de=e=>e.replace(/^.*\/node_modules\/(@[a-z0-9][\w-.]+\/[a-z0-9][\w-.]*|[^/]+).*$/,"$1"),fe=e=>e.map((e=>({type:e?.constructor?.name??typeof e,name:e?.name,value:"string"==typeof e?e:void 0}))),me=(e,t,n,s)=>{const o=new Set;if(s){const{timings:e}=s;e&&(e.tapables&&((e,t)=>{t.add({metric:"plugins.count",type:"count",value:e.size,tags:[]});for(const n of e.values()){let e=0,s=0;for(const o of Object.values(n.events)){let r=0;s+=o.values.length;for(const t of o.values){const n=t.end-t.start;r+=n,e+=n}t.add({metric:"plugins.hooks.duration",type:"duration",value:r,tags:[`pluginName:${n.name}`,`hookName:${o.name}`]}).add({metric:"plugins.hooks.increment",type:"count",value:o.values.length,tags:[`pluginName:${n.name}`,`hookName:${o.name}`]})}t.add({metric:"plugins.duration",type:"duration",value:e,tags:[`pluginName:${n.name}`]}).add({metric:"plugins.increment",type:"count",value:s,tags:[`pluginName:${n.name}`]})}})(e.tapables,o),e.loaders&&((e,t)=>{t.add({metric:"loaders.count",type:"count",value:e.size,tags:[]});for(const n of e.values())t.add({metric:"loaders.duration",type:"duration",value:n.duration,tags:[`loaderName:${n.name}`]}).add({metric:"loaders.increment",type:"count",value:n.increment,tags:[`loaderName:${n.name}`]})})(e.loaders,o))}((e,t)=>{const n=e.build.inputs||[],s=e.build.outputs||[],o=e.build.entries||[],r=e.build.warnings.length,i=e.build.errors.length,a=e.build.duration,u=new Map,p=new Map,c=new Map;for(const e of o){for(const t of e.inputs)u.has(t.filepath)||u.set(t.filepath,[]),u.get(t.filepath).push(e.name);for(const t of e.outputs){const n=t.filepath.replace(/\.map$/,"");c.has(n)||c.set(n,[]),c.get(n).push(e.name)}}for(const e of s)for(const t of e.inputs)p.has(t.filepath)||p.set(t.filepath,[]),p.get(t.filepath).push(e.name);t.add({metric:"assets.count",type:"count",value:s.length,tags:[]}).add({metric:"entries.count",type:"count",value:o.length,tags:[]}).add({metric:"errors.count",type:"count",value:i,tags:[]}).add({metric:"modules.count",type:"count",value:n.length,tags:[]}).add({metric:"warnings.count",type:"count",value:r,tags:[]}),a&&t.add({metric:"compilation.duration",type:"duration",value:a,tags:[]});for(const e of n){const n=[`moduleName:${e.name}`,`moduleType:${e.type}`];u.has(e.filepath)&&n.push(...u.get(e.filepath).map((e=>`entryName:${e}`))),p.has(e.filepath)&&n.push(...p.get(e.filepath).map((e=>`assetName:${e}`))),t.add({metric:"modules.size",type:"size",value:e.size,tags:n}).add({metric:"modules.dependencies",type:"count",value:e.dependencies.size,tags:n}).add({metric:"modules.dependents",type:"count",value:e.dependents.size,tags:n})}for(const e of s){const n=[`assetName:${e.name}`,`assetType:${e.type}`],s=e.filepath.replace(/\.map$/,"");c.has(s)&&n.push(...c.get(s).map((e=>`entryName:${e}`))),t.add({metric:"assets.size",type:"size",value:e.size,tags:n}).add({metric:"assets.modules.count",type:"count",value:e.inputs.length,tags:n})}for(const e of o){const n=[`entryName:${e.name}`];t.add({metric:"entries.size",type:"size",value:e.size,tags:n}).add({metric:"entries.modules.count",type:"count",value:e.inputs.length,tags:n}).add({metric:"entries.assets.count",type:"count",value:e.outputs.length,tags:n})}})(e,o);for(const e of o)if(t.filters?.length){let s=e;for(const n of t.filters){if(!s)break;s=n(e)}s&&n.add(ae(s,t))}else n.add(ae(e,t))},he=async(e,t,n,o)=>{if("string"!=typeof t&&"object"!=typeof t&&!t)return;const{report:r,metrics:i}=e,a=Date.now();let u="";const p={timings:!0,metrics:!0};"object"==typeof t?(u=t.destination,p.timings=t.timings||!1,p.metrics=t.metrics||!1):"string"==typeof t&&(u=t);const c=s.resolve(o,u);try{const e={},t={};p.timings&&r?.timings&&(t.timings={content:{tapables:r.timings.tapables?Array.from(r.timings.tapables.values()):null,loaders:r.timings.loaders?Array.from(r.timings.loaders.values()):null,modules:r.timings.modules?Array.from(r.timings.modules.values()):null}}),p.metrics&&(t.metrics={content:Array.from(i)});const o=Object.entries(t).map((async([t,o])=>{const r=Date.now();n.debug(`Start writing ${t}.json.`);try{await(async(e,t)=>{const n=JSON.stringify(t,null,4);return N(e,n)})(s.join(c,`${t}.json`),o.content),n.debug(`Wrote ${t}.json in ${E(Date.now()-r)}`)}catch(s){n.error(`Failed to write ${t}.json in ${E(Date.now()-r)}`),e[t]=s}}));await Promise.all(o),n.debug(`Wrote files in ${E(Date.now()-a)}.`);const u=Object.keys(e);u.length&&n.error(`Couldn't write files.\n${u.map((t=>` - ${t}: ${e[t].toString()}`))}`)}catch(e){n.error(`Couldn't write files. ${e}`)}},ge=t.bold.red,we=t.bold.cyan,ye=e=>(t,n)=>{let s,o;return"function"==typeof e?(s=e(t),o=e(n)):(s=t[e],o=n[e]),s>o?-1:s<o?1:0},be=(e,t)=>{if(!t||!t.size)return[];const n=Array.from(t.values());n.sort(ye("duration"));const s={name:`${e} duration`,values:n.map((e=>({name:e.name,value:E(e.duration)}))),top:!0};n.sort(ye("increment"));return[s,{name:`${e} hits`,values:n.map((e=>({name:e.name,value:e.increment.toString()}))),top:!0}]},ve=(e,t,n)=>{const s=[];var o;n&&(s.push(...be("Loader",n.timings.loaders)),s.push(...be("Tapable",n.timings.tapables)),s.push(...be("Module",n.timings.modules))),s.push(...(e=>{const t={name:"Module total dependents",values:[],top:!0},n={name:"Module total dependencies",values:[],top:!0},s={name:"Module size",values:[],top:!0},o={name:"Module aggregated size",values:[],top:!0},r=new Set,i=(e=>{const t={bundler:e.bundler,errors:e.errors,warnings:e.warnings,logs:e.logs,start:e.start,end:e.end,duration:e.duration,writeDuration:e.writeDuration,entries:[],inputs:[],outputs:[]};for(const n of e.entries||[]){const e={...n,inputs:[],outputs:[]};n.inputs&&(e.inputs=n.inputs.map((e=>e.filepath))),n.outputs&&(e.outputs=n.outputs.map((e=>e.filepath))),t.entries.push(e)}for(const n of e.inputs||[]){const e={...n,dependencies:[],dependents:[]};if(n.dependencies)for(const t of n.dependencies)e.dependencies.push(t.filepath);if(n.dependents)for(const t of n.dependents)e.dependents.push(t.filepath);t.inputs.push(e)}for(const n of e.outputs||[]){const e={...n,inputs:[]};n.inputs&&(e.inputs=n.inputs.map((e=>e.filepath))),t.outputs.push(e)}return t})(e.build),a=new Map,u=new Map,p=new Map;for(const e of i.inputs||[]){if("map"===e.type)continue;const t=new Set(e.dependencies),n=new Set(e.dependents);for(const n of t)p.has(n)||p.set(n,new Set),p.get(n).add(e.filepath);for(const t of n)u.has(t)||u.set(t,new Set),u.get(t).add(e.filepath);if(u.has(e.filepath)){const n=u.get(e.filepath);for(const e of n)t.add(e)}if(p.has(e.filepath)){const t=p.get(e.filepath);for(const e of t)n.add(e)}u.set(e.filepath,t),p.set(e.filepath,n),a.set(e.filepath,{name:e.name,size:e.size,dependencies:t,dependents:n})}for(const[e,t]of a){const n=u.get(e)||new Set,s=p.get(e)||new Set;let o=t.size;for(const e of n)o+=a.get(e)?.size||0;r.add({name:t.name,size:t.size,aggregatedSize:o,dependents:s,dependencies:n})}if(!r.size)return[t,n,s];const c=Array.from(r);return c.sort(ye((e=>e.dependents.size))),t.values=c.map((e=>({name:e.name,value:e.dependents.size.toString()}))),c.sort(ye((e=>e.dependencies.size))),n.values=c.map((e=>({name:e.name,value:e.dependencies.size.toString()}))),c.sort(ye("size")),s.values=c.map((e=>({name:e.name,value:d(e.size)}))),c.sort(ye("aggregatedSize")),o.values=c.map((e=>({name:e.name,value:d(e.aggregatedSize||e.size)}))),[t,n,s,o]})(e)),s.push(...(o=e,[{name:"Asset size",values:(o.build.outputs||[]).filter((e=>"map"!==e.type)).sort(ye((e=>e.size))).map((e=>({name:e.name,value:d(e.size)}))),top:!0},{name:"Entry aggregated size",values:(o.build.entries||[]).sort(ye((e=>e.size))).map((e=>({name:e.name,value:d(e.size)}))),top:!0},{name:"Entry number of modules",values:(o.build.entries||[]).sort(ye((e=>e.size))).map((e=>({name:e.name,value:e.inputs.length.toString()})))||[],top:!0}])),s.push(...(e=>{const t={name:"General Numbers",values:[],top:!1},n=e.build.inputs?e.build.inputs.length:0,s=e.build.outputs?e.build.outputs.length:0,o=e.build.warnings.length,r=e.build.errors.length,i=e.build.entries?e.build.entries.length:0;return e.build.start&&t.values.push({name:"Overhead duration",value:E(e.build.start-e.start)}),e.build.duration&&t.values.push({name:"Build duration",value:E(e.build.duration)}),e.build.writeDuration&&t.values.push({name:"Write duration",value:E(e.build.writeDuration)}),t.values.push({name:"Number of modules",value:n.toString()},{name:"Number of assets",value:s.toString()},{name:"Number of entries",value:i.toString()},{name:"Number of warnings",value:o.toString()},{name:"Number of errors",value:r.toString()}),[t]})(e));const r=(e=>{let t="";for(const t of e){t.top&&t.values.length>=5&&(t.values=t.values.slice(0,5),t.name=`Top 5 ${t.name}`);for(const e of t.values)e.name=T(e.name,60)}const n=Math.max(...e.map((e=>e.name.length))),s=Math.max(...e.flatMap((e=>e.values.map((e=>e.name.length))))),o=Math.max(...e.flatMap((e=>e.values.map((e=>e.value.length))))),r=Math.max(n+4,s+o+4);for(const n of e){if(0===n.values.length)continue;const e=r-(n.name.length+4);t+=`\n== ${n.name} ${"=".repeat(e)}=\n`;for(const e of n.values){const n=o-e.value.length;t+=` [${ge(e.value)}] ${" ".repeat(n)}${we(e.name)}\n`}}return t})(s);t.info(r)},$e=["onStart","onLoad","onResolve","onEnd"],ke=new Map,Se=new Map,De=(e,t,n)=>{const s=Object.assign({},e);for(const o of $e)s[o]=async(s,r)=>{const i=ke.get(t)||{name:t,increment:0,duration:0,events:{}};i.events[o]=i.events[o]||{name:o,values:[]};return(0,e[o])(s,(async(...e)=>{const s=ce(e[0].path,n),a=Se.get(s)||{name:s,increment:0,duration:0,events:{}};a.events[o]=a.events[o]||{name:o,values:[]};const u=f.performance.now();try{return await r(...e)}finally{const n=f.performance.now(),r=n-u,p={start:u,end:n,duration:r,context:fe(e)};i.events[o].values.push(p),i.duration+=r,i.increment+=1,ke.set(t,i),a.events[o].values.push(p),a.duration+=r,a.increment+=1,Se.set(s,a)}}))};return s},Ee=(e,t,n)=>({setup:s=>{t.build.start=Date.now(),s.initialOptions.metafile=!0,((e,t)=>{const n=e.initialOptions.plugins;if(n){const e=n.map((e=>({...e})));for(const s of n){if(s.name.includes(re))continue;const n=s.setup;s.setup=async o=>{const r=De(o,s.name,t);await n({...r,initialOptions:{...r.initialOptions,plugins:e}})}}}})(s,t.cwd),s.onEnd((async t=>{if(!t.metafile)return void n.warn("Missing metafile, can't proceed with modules data.");const{plugins:s,modules:o}={plugins:ke,modules:Se};e.report={timings:{tapables:s,modules:o}}}))}});class Me{constructor(e){this.started={},this.finished=[],this.cwd=e}buildModule(e,t){const n=le(e,t,this.cwd),s=(e=>(e.loaders||[]).map((e=>e.loader||e)).map(de))(e);s.length||s.push("no-loader"),this.started[n]={module:pe(n),timings:{start:f.performance.now(),duration:0,end:0},loaders:s}}succeedModule(e,t){const n=le(e,t,this.cwd),s=this.started[n];s&&(s.timings.end=f.performance.now(),s.timings.duration=s.timings.end-s.timings.start,this.finished.push(s),delete this.started[n])}getResults(){const e=new Map,t=new Map;for(const n of this.finished){const s=n.timings.end-n.timings.start,o=t.get(n.module)||{name:n.module,increment:0,duration:0,events:{}},r=n.loaders.join(",");o.events[r]=o.events[r]||{name:r,values:[]},o.events[r].values.push(n.timings),o.increment+=1,o.duration+=s,t.set(n.module,o);for(const t of n.loaders){const n=e.get(t)||{name:t,increment:0,duration:0,events:{}};n.increment+=1,n.duration+=s,e.set(t,n)}}return{loaders:e,modules:t}}}class Pe{constructor(e){this.monitoredTaps={},this.tapables=[],this.hooks={},this.timings=new Map,this.ignoredHooks=["normalModuleLoader"],this.cwd=e}saveResult(e,t,n,s,o,r){const i=this.timings.get(t)||{name:t,duration:0,increment:0,events:{}};i.events[n]||(i.events[n]={name:n,values:[]}),i.events[n].values.push({start:o,end:r,duration:r-o,context:s,type:e}),i.duration+=r-o,i.increment+=1,this.timings.set(t,i)}getResults(){const e=this.timings;for(const[t,n]of this.timings){const s=n;s.duration=Object.values(n.events).map((e=>e.values.reduce(((e,t)=>e+t.end-t.start),0))).reduce(((e,t)=>e+t),0),e.set(t,s)}return{monitoredTaps:this.monitoredTaps,tapables:this.tapables,hooks:this.hooks,timings:e}}getPromiseTapPatch(e,t,n,s){return(...o)=>{this.checkNewHooks();const r=f.performance.now(),i=t.apply(this,o),a=()=>{this.saveResult(e,n,s,fe(o),r,f.performance.now())};return i.then(a,a),i}}getAsyncTapPatch(e,t,n,s){return(...o)=>{this.checkNewHooks();const r=f.performance.now(),i=o.pop();return t.apply(this,[...o,(...t)=>(this.saveResult(e,n,s,fe(o),r,f.performance.now()),i(...t))])}}getDefaultTapPatch(e,t,n,s){return(...o)=>{this.checkNewHooks();const r=f.performance.now(),i=t.apply(this,o);return this.saveResult(e,n,s,fe(o),r,f.performance.now()),i}}getTapPatch(e,t,n,s){switch(e){case"promise":return this.getPromiseTapPatch(e,t,n,s);case"async":return this.getAsyncTapPatch(e,t,n,s);default:return this.getDefaultTapPatch(e,t,n,s)}}newTap(e,t,n,s){return(o,r)=>{const i="string"==typeof(a=o)?a:a.name;var a;const u=`${t}-${i}`;if(this.monitoredTaps[u])return n.call(s,o,r);this.monitoredTaps[u]=!0;const p=this.getTapPatch(e,r,i,t);return n.call(s,o,p)}}replaceTaps(e,t){t.tap=this.newTap("default",e,t.tap,t),t.tapAsync=this.newTap("async",e,t.tapAsync,t),t.tapPromise=this.newTap("promise",e,t.tapPromise,t)}patchHook(e,t,n){n._fakeHook||e.includes(re)||(this.hooks[e]||(this.hooks[e]=[]),this.hooks[e].includes(t)||(this.hooks[e].push(t),this.replaceTaps(t,n)))}patchHooks(e){const t=e.constructor.name,n=Object.keys(e.hooks).filter((e=>!this.ignoredHooks.includes(e)&&!this.hooks[t]?.includes(e)));for(const s of n)this.patchHook(t,s,e.hooks[s])}checkNewHooks(){for(const e of this.tapables)this.patchHooks(e)}throughHooks(e){this.tapables.includes(e)||this.tapables.push(e),this.patchHooks(e)}}const je=(e,t)=>async n=>{t.build.start=Date.now();const s={name:re},o=new Pe(t.cwd),r=new Me(t.cwd);o.throughHooks(n),n.hooks.thisCompilation.tap(s,(e=>{o.throughHooks(e),e.hooks.buildModule.tap(s,(t=>{r.buildModule(t,e)})),e.hooks.succeedModule.tap(s,(t=>{r.succeedModule(t,e)}))})),n.hooks.afterEmit.tapPromise(s,(async t=>{const{timings:n}=o.getResults(),{loaders:s,modules:i}=r.getResults();e.report={timings:{tapables:n,loaders:s,modules:i}}}))},Te={filters:ie},Oe=(e,t)=>{const n=t.getLogger(re);let s=0;const o={start:Date.now()},r=(e=>{const t=e[oe]||{},n=t.endPoint||"https://app.datadoghq.com";return{disabled:!1,enableTracing:!1,filters:ie,output:!1,prefix:"",tags:[],...t,endPoint:n.startsWith("http")?n:`https://${n}`}})(e),i=[],a={name:re,enforce:"pre",esbuild:Ee(o,t,n),webpack:je(o,t),rspack:je(o,t)},u={name:"datadog-universal-telemetry-plugin",enforce:"post",buildStart(){t.build.start=t.build.start||Date.now()},buildEnd(){s=Date.now()},async writeBundle(){t.build.end=Date.now(),t.build.duration=t.build.end-t.build.start,t.build.writeDuration=t.build.end-s;const e=new Set,i=(e=>({timestamp:Math.floor((e.timestamp||Date.now())/1e3),tags:e.tags,prefix:e.prefix,filters:e.filters}))(r);me(t,i,e,o.report),await he({report:o.report,metrics:e},r.output,n,t.bundler.outDir),ve(t,n,o.report),await((e,t,n)=>{const s=Date.now();if(!t.apiKey)return void n.info("Won't send metrics to Datadog: missing API Key.");if(!e.size)return void n.info("No metrics to send.");const o=new Map;for(const t of e)o.has(t.metric)||o.set(t.metric,0),o.set(t.metric,o.get(t.metric)+1);const r=Array.from(o.entries()).map((([e,t])=>`${e} - ${t}`));return n.debug(`\nSending ${e.size} metrics.\nMetrics:\n - ${r.join("\n - ")}`),j({method:"POST",url:`${t.endPoint}/api/v1/series?api_key=${t.apiKey}`,getData:()=>({data:JSON.stringify({series:Array.from(e)})})}).then((()=>{n.debug(`Sent metrics in ${E(Date.now()-s)}.`)})).catch((e=>{n.error(`Error sending metrics ${e}`)}))})(e,{apiKey:t.auth?.apiKey,endPoint:r.endPoint},n)}};return r.enableTracing&&i.push(a),i.push(u),i},ze="datadog-analytics-plugin",Ne=e=>{const t=e.getLogger(ze);return e.sendLog=async(n,s={})=>{if("production"===e.env)try{const t={name:e.bundler.name,version:e.bundler.version};await j({retries:2,minTimeout:100,url:"https://browser-http-intake.logs.datadoghq.com/v1/input/pub44d5f4eb86e1392037b7501f7adc540e",method:"POST",type:"json",getData:async()=>{const o={ddsource:`@datadog/${t.name}-plugin`,env:e.env,message:n,service:"build-plugins",bundler:t,plugins:e.pluginNames,version:e.version,team:"language-foundations",...s};return{data:JSON.stringify(o),headers:{"Content-Type":"application/json"}}}})}catch(e){t.debug(`Could not submit data to Datadog: ${e}`)}},[{name:ze,async buildStart(){await e.sendLog("Build started")}}]},Re=/\.(?!.*(?:\.|\/|\\))(\w{1,})/g,xe=/(\?|%3F|\|)+/gi,Ie=e=>{return"unknown"===e?e:e.includes("webpack/runtime")?"runtime":(t=qe(e),Re.lastIndex=0,Re.exec(t)?.[1]||"unknown");var t},Ae=["unknown","commonjsHelpers.js","vite/preload-helper.js"],Fe=(e,t,n)=>{const s=new Set;for(const n of e){const e=qe(n);O(n)||e===t||Ae.includes(e)||s.add(e)}return s},qe=e=>e.split("!").pop().split(xe).shift().replace(/^[^\w\s.,!@#$%^&*()=+~`\-/]+/,""),Ce=(e,t)=>O(t)?y:t.startsWith(e)?t:s.resolve(e,t),Le=(e,t)=>O(t)?y:"unknown"===t?t:t.includes("webpack/runtime")?t.replace("webpack/runtime/","").replace(/ +/g,"-"):t.split("!").pop().replace(e.bundler.outDir,"").replace(e.cwd,"").split("node_modules").pop().split(xe).shift().replace(/^\/+/,""),_e=(e,t)=>Object.fromEntries(Object.entries(e).map((([e,n])=>[Ce(t,e),n]))),Ke=(e,t)=>({setup(n){const s=new Map,o=[];n.onStart((async()=>{o.push(...await M(n,e,t));for(const t of o){const n=Le(e,t.resolved);t.name?s.set(n,t.name):s.set(n,n)}})),n.onEnd((n=>{const o=e.cwd;for(const t of n.errors)e.build.errors.push(t.text);for(const t of n.warnings)e.build.warnings.push(t.text);if(!n.metafile){const n="Missing metafile from build report.";return e.build.warnings.push(n),void t.warn(n)}const r=[],i=[],a=[],u=[],p=[],c={},l={},d=_e(n.metafile.inputs,o),f=_e(n.metafile.outputs,o),m=e=>{if(!O(e))return e;const t=d[Ce(o,e)];if(!t)return e;const n=t.imports.find((e=>!O(e.path)));return n?n.path:e};for(const[t,s]of Object.entries(n.metafile.inputs)){if(O(t))continue;const n=Ce(o,t),i={name:Le(e,t),filepath:n,dependents:new Set,dependencies:new Set,size:s.bytes,type:Ie(t)};c[n]=i,r.push(i)}for(const[r,p]of Object.entries(n.metafile.outputs)){const n=Ce(o,r),d=Le(e,n),f=[];for(const e of Object.keys(p.inputs)){if(O(e))continue;const n=c[Ce(o,e)];n?f.push(n):t.debug(`Input ${e} not found for output ${d}`)}if(p.entryPoint&&!f.length){const e=c[Ce(o,p.entryPoint)];if(!e){t.debug(`Input ${p.entryPoint} not found for output ${d}`);continue}f.push(e)}const h={name:d,filepath:n,inputs:f,size:p.bytes,type:Ie(n)};if(l[n]=h,"map"===h.type&&u.push(h),i.push(h),!p.entryPoint)continue;const g=c[Ce(o,m(p.entryPoint))];if(g){if(!s.get(g.name))continue;const e={...h,name:s.get(g.name)||g.name,outputs:[h],size:h.size};a.push(e)}}for(const e of u){const n=l[e.filepath.replace(/\.map$/,"")];n?e.inputs.push(n):t.debug(`Could not find output for sourcemap ${e.name}`)}const h={inputs:{report:c,meta:d},outputs:{report:l,meta:f}},g=/(<runtime>|https:|file:|data:|#)/g,w=e=>!O(e)&&!e.match(g),y=(e,n,s={})=>{if(!w(e))return s;const r=n.report[e];if(!r)return t.debug(`Could not find report's ${e}`),s;if(s[r.filepath])return s;s[r.filepath]=r;const i=n.meta[e];if(!i)return t.debug(`Could not find metafile's ${e}`),s;if(!i.imports||!i.imports.length)return s;for(const e of i.imports){const t=Ce(o,e.path);y(t,n,s)}return s};for(const e of a){const t={},n={};for(const n of e.inputs)y(n.filepath,h.inputs,t);for(const t of e.outputs)y(t.filepath,h.outputs,n);e.inputs=Object.values(t),e.outputs=Object.values(n),e.size=e.outputs.reduce(((e,t)=>e+t.size),0),p.push(e)}for(const e of r){const n=h.inputs.meta[e.filepath];if(n)for(const s of n.imports){if(!w(s.path))continue;const n=Ce(o,s.path),r=h.inputs.report[n];r?(e.dependencies.add(r),r.dependents.add(e)):t.debug(`Could not find input file of ${s.path}`)}else t.debug(`Could not find metafile's ${e.name}`)}e.build.outputs=i,e.build.inputs=r,e.build.entries=p}))}}),Be=(e,t)=>{const n={};return{onLog(t,n){"warn"===t&&e.build.warnings.push(n.message||n.toString())},renderError(t){t&&e.build.errors.push(t.message)},moduleParsed(e){const t=qe(e.id),s=n[t]||{dependencies:new Set,dependents:new Set},o=Fe(new Set([...e.dynamicallyImportedIds,...e.importedIds]),t),r=Fe(new Set([...e.dynamicImporters,...e.importers]),t);for(const e of r)s.dependents.add(e);for(const e of o)s.dependencies.add(e);n[t]=s},writeBundle(s,o){const r=[],i=[],a=[],u=[],p=[],c={},l={};for(const[e,{dependencies:t,dependents:s}]of Object.entries(n)){for(const s of t){const t=qe(s);n[t]||(n[t]={dependencies:new Set,dependents:new Set}),n[t].dependents.has(e)||n[t].dependents.add(e)}for(const t of s){const s=qe(t);n[s]||(n[s]={dependencies:new Set,dependents:new Set}),n[s].dependencies.has(e)||n[s].dependencies.add(e)}}for(const[t,n]of Object.entries(o)){const s={name:t,filepath:Ce(e.bundler.outDir,t),inputs:[],size:"code"in n?Buffer.byteLength(n.code,"utf8"):Buffer.byteLength(n.source,"utf8"),type:Ie(t)};if("map"===s.type&&u.push(s),"modules"in n)for(const[t,o]of Object.entries(n.modules)){if(qe(t)!==t)continue;const n={name:Le(e,t),dependencies:new Set,dependents:new Set,filepath:t,size:o.originalLength,type:Ie(t)};s.inputs.push(n),c[n.filepath]=n,r.push(n)}"isEntry"in n&&n.isEntry&&a.push({...s,name:n.name,size:0,outputs:[s]}),l[s.filepath]=s,i.push(s)}for(const s of r){const o=n[s.filepath];if(o){for(const n of o.dependencies){const o=c[n];o?s.dependencies.add(o):t.debug(`Could not find input for dependency ${Le(e,n)} of ${s.name}`)}for(const n of o.dependents){const o=c[n];o?s.dependents.add(o):t.debug(`Could not find input for dependent ${Le(e,n)} of ${s.name}`)}}else t.debug(`Could not find the import report for ${s.name}.`)}if(u.length)for(const e of u){const n=e.filepath.replace(/\.map$/,""),s=l[n];s?e.inputs.push(s):t.debug(`Could not find output for sourcemap ${e.name}`)}const d=(n,s={})=>{if(s[n])return s;const r=Le(e,n),i=l[n];if(!i)return t.debug(`Could not find output for ${r}`),s;s[n]=i;const a=o[r];if(!a)return t.debug(`Could not find asset for ${r}`),s;const u=[];"imports"in a&&u.push(...a.imports),"dynamicImports"in a&&u.push(...a.dynamicImports);for(const t of u)d(Ce(e.bundler.outDir,t),s);return s};for(const e of a){const t=d(e.filepath);e.outputs=Object.values(t),e.inputs=Array.from(new Set(e.outputs.flatMap((e=>e.inputs)))),e.size=e.outputs.reduce(((e,t)=>e+t.size),0),p.push(e)}e.build.inputs=r,e.build.outputs=i,e.build.entries=p}}},He=(e,t,n)=>s=>{const o=[],r=[],i=[],a=new Map,u=new Map,p=new Map,c=new Map,l=[],d=new Map,f=e=>!(!e||e.startsWith("webpack/runtime")||e.includes("/webpack4/buildin/")||e.startsWith("multi ")||O(e)),m=e=>{const t={identifier:e.identifier()};"resource"in e&&"string"==typeof e.resource&&(t.resource=e.resource),"request"in e&&"string"==typeof e.request&&(t.request=e.request),"rawRequest"in e&&"string"==typeof e.rawRequest&&(t.rawRequest=e.rawRequest),"userRequest"in e&&"string"==typeof e.userRequest&&(t.userRequest=e.userRequest);const s=new Set;for(const[o,r]of Object.entries(t))r&&(c.has(r)?(n.debug(`Module ${e.identifier()} is already indexed by ${o}.`),c.get(r)!==e&&n.debug(`Module ${e.identifier()} is indexed with a different value.`)):s.add(r));return s},h=(e,t=[])=>{if("dependencies"in e)for(const n of e.dependencies)t.push(n),h(n,t);if("blocks"in e)for(const n of e.blocks)h(n,t);return t},g=(e,t)=>{if("request"in t&&t.request){if(c.has(t.request))return c.get(t.request);if(e.context&&c.has(Ce(e.context,t.request)))return c.get(Ce(e.context,t.request))}};s.hooks.thisCompilation.tap(t,(s=>{s.hooks.finishModules.tap(t,(t=>{for(const e of t){const t=m(e);for(const n of t)c.set(n,e)}for(const n of t){const t=n.identifier(),s=new Set(h(n).map((e=>{const s=g(n,e);if(!s||!s.identifier())return!1;const o=s.identifier();return!!f(o)&&(o!==t&&o)})).filter(Boolean));if(!f(t))continue;for(const e of s){const n=d.get(e)||{dependencies:new Set,dependents:new Set};n.dependents.add(t),d.set(e,n)}const r=d.get(t)||{dependents:new Set,dependencies:new Set};for(const e of s)r.dependencies.add(e);d.set(t,r);const i={size:n.size()||0,name:Le(e,t),dependencies:new Set,dependents:new Set,filepath:t,type:Ie(t)};o.push(i),a.set(t,i)}for(const e of o){const t=d.get(e.filepath);if(t){for(const s of t.dependencies){const t=a.get(s);t?e.dependencies.add(t):n.debug(`Could not find input of dependency ${s}`)}for(const s of t.dependents){const t=a.get(s);t?e.dependents.add(t):n.debug(`Could not find input of dependent ${s}`)}}else n.debug(`Could not find dependency report for ${e.name}`)}}))})),s.hooks.afterEmit.tap(t,(t=>{const s=t.chunks,c=t.getAssets(),d=t=>[...t.files||[],...t.auxiliaryFiles||[]].map((t=>Ce(e.bundler.outDir,t))),m=t.chunkGraph;for(const e of s){const t=d(e),n=(m?m?.getChunkModules(e):"getModules"in e&&"function"==typeof e.getModules?e.getModules():[]).flatMap((e=>"modules"in e&&Array.isArray(e.modules)?e.modules.map((e=>e.identifier())):e.identifier())).filter(f);for(const e of t){if("map"===Ie(e))continue;const t=p.get(e)||[];p.set(e,[...t,...n])}}for(const t of c){const s={size:t.source.size()||0,name:t.name,inputs:[],filepath:Ce(e.bundler.outDir,t.name),type:Ie(t.name)};if(u.set(s.filepath,s),r.push(s),"map"===s.type){l.push(s);continue}const o=p.get(s.filepath);if(o)for(const e of o){const t=a.get(e);t?s.inputs.push(t):n.debug(`Could not find input of ${e}`)}else n.debug(`Could not find modules for ${s.name}`)}for(const e of l){const t=u.get(e.filepath.replace(/\.map$/,""));t?e.inputs.push(t):n.debug(`Output not found for sourcemap ${e.name}`)}for(const[s,o]of t.entrypoints){const t=[],r=[];let a=0;const p=o.chunks.flatMap(d),c=o.chunks.filter((e=>m?m.getChunkEntryModulesIterable(e):"hasEntryModule"in e&&"function"==typeof e.hasEntryModule&&e.hasEntryModule())).flatMap((e=>Array.from(e.files))).filter((e=>e.includes(s)||o.name&&e.includes(o.name))).find((e=>"js"===Ie(e)));for(const e of p){const s=u.get(e);e&&s?"map"===s.type||t.includes(s)||(t.push(s),r.push(...s.inputs),a+=s.size):n.debug(`Could not find output of ${JSON.stringify(e)}`)}const l={name:s,filepath:c?Ce(e.bundler.outDir,c):"unknown",size:a,inputs:Array.from(new Set(r)),outputs:t,type:c?Ie(c):"unknown"};i.push(l)}for(const n of t.errors)e.build.errors.push(n.message);for(const n of t.warnings)e.build.warnings.push(n.message);e.build.inputs=o,e.build.outputs=r,e.build.entries=i}))},Ue="datadog-build-report-plugin",We=e=>{const t=e.getLogger(Ue);return[{name:Ue,enforce:"post",esbuild:Ke(e,t),rspack:He(e,Ue,t),webpack:He(e,Ue,t),vite:Be(e,t),rollup:Be(e,t)}]},Ge=(e,t)=>{const n=((e,t)=>{const n=e.map((e=>(s.isAbsolute(e)?e:s.resolve(t,e)).split(s.sep))),o=Math.min(...n.map((e=>e.length))),r=[];for(let e=0;e<o;e++){const t=n[0][e];if(!n.every((n=>n[e]===t)))break;r.push(t)}return r.length>0?r.join(s.sep):s.sep})(e,t.cwd);n!==s.sep&&(t.cwd=n)},Je=e=>t=>{e.bundler.rawConfig=t.options,t.options.output?.path&&(e.bundler.outDir=t.options.output.path),t.options.context&&(e.cwd=t.options.context)},Ve=e=>{const t=new Set,n=n=>{n&&(n.dir?(e.bundler.outDir=n.dir,t.add(n.dir)):n.file&&(e.bundler.outDir=s.dirname(n.file),t.add(n.dir)),"vite"!==e.bundler.name&&Ge(Array.from(t),e))},o=()=>({options(o){if(e.bundler.rawConfig=o,o.input)if(Array.isArray(o.input))for(const e of o.input)t.add(s.dirname(e));else if("object"==typeof o.input)for(const e of Object.values(o.input))t.add(s.dirname(e));else{if("string"!=typeof o.input)throw new Error("Invalid input type");t.add(s.dirname(o.input))}"output"in o&&n(o.output)},outputOptions(e){n(e)}});return[{name:"datadog-bundler-report-plugin",enforce:"pre",esbuild:{setup(t){e.bundler.rawConfig=t.initialOptions,t.initialOptions.outdir&&(e.bundler.outDir=t.initialOptions.outdir),t.initialOptions.outfile&&(e.bundler.outDir=s.dirname(t.initialOptions.outfile)),t.initialOptions.absWorkingDir&&(e.cwd=t.initialOptions.absWorkingDir),t.initialOptions.metafile=!0}},webpack:Je(e),rspack:Je(e),vite:{...o(),config(n){n.root?e.cwd=n.root:Ge(Array.from(t),e)}},rollup:o()}]};class Ye{constructor(e){this.trackedFilenames=new Map;for(const t of e){const e=this.getFilename(t),n=this.trackedFilenames.get(e);n?n.push(t):this.trackedFilenames.set(e,new Array(t))}}displaySource(e){return e.length<=40?e:`[...]${e.slice(-35)}`}matchSourcemap(e,t){const n=i.readFileSync(e,"utf8"),s=JSON.parse(n);if(!s.sources)return void t("Missing 'sources' field in sourcemap.");const o=s.sources;if(0===o.length)return void t("Empty 'sources' field in sourcemap.");const r=this.matchSources(o);if(0!==r.length)return r;t(`${o.map(this.displaySource).join(", ")} not in the tracked files.`)}matchSources(e){let t=[];const n=new Set;for(const s of e){const e=this.getFilename(s);if(n.has(e))continue;n.add(e);const o=this.trackedFilenames.get(e);o&&(t=t.concat(o))}return t}rawTrackedFilesList(){let e=[];return this.trackedFilenames.forEach((t=>{e=e.concat(t)})),e}getFilename(e){let t=e.lastIndexOf("/");-1===t?t=0:t++;let n=e.lastIndexOf("?");return(-1===n||n<=t)&&(n=e.length),e.substring(t,n)}}const Qe=async e=>{const t=await e.getRemotes(!0);if(0===t.length)throw new Error("No git remotes available");const n=await Xe(e);for(const e of t)if(e.name===n)return Ze(e.refs.push);return Ze(t[0].refs.push)},Xe=async e=>{try{return(await e.getConfig("clone.defaultRemoteName"))?.value??"origin"}catch(e){return"origin"}},Ze=e=>{try{const t=new h.URL(e);return t.username="",t.password="",t.toString()}catch{return e}},et=async e=>e.revparse("HEAD"),tt=async e=>(await e.raw("ls-files")).split(/\r\n|\r|\n/),nt="datadog-git-plugin",st=(e,t)=>{const n=t.getLogger(nt);return[{name:nt,enforce:"pre",async buildStart(){if(e.errorTracking?.sourcemaps&&!0!==e.errorTracking?.sourcemaps.disableGit&&!0!==e.disableGit)try{const e=await(async e=>{let t,n,s;return[t,n,s]=await Promise.all([Qe(e),et(e),tt(e)]),{hash:n,remote:t,trackedFilesMatcher:new Ye(s)}})(await(async e=>{const t={baseDir:e||process.cwd(),binary:"git",maxConcurrentProcesses:3};try{const e=m.simpleGit(t),n=await e.revparse("--show-toplevel");t.baseDir=n}catch{}return m.simpleGit(t)})(t.cwd));t.git=e}catch(e){n.error(`Could not get git information: ${e.message}`)}}}]},ot="datadog-injection-plugin",rt=/^https?:\/\//,it=async(e,t,n=process.cwd())=>{let s;const o=await(async e=>"function"==typeof e.value?e.value():e.value)(e);try{if("file"===e.type)s=o.match(rt)?await(async(e,t=5e3)=>{let n;return Promise.race([j({retries:2,minTimeout:100,url:e}).finally((()=>{t&&clearTimeout(n)})),new Promise(((e,s)=>{n=setTimeout((()=>{s(new Error("Timeout"))}),t)}))])})(o):await(async(e,t=process.cwd())=>{const n=Ce(t,e);return r.readFile(n,{encoding:"utf-8"})})(o,n);else{if("code"!==e.type)throw new Error(`Invalid item type "${e.type}", only accepts "code" or "file".`);s=o}}catch(n){const r=`${e.type} - ${T(o)}`;e.fallback?(t.info(`Fallback for "${r}": ${n.toString()}`),s=await it(e.fallback,t)):(t.warn(`Failed "${r}": ${n.toString()}`),s="")}return s},at=e=>{if(0===e.size)return"";return`// begin injection by Datadog build plugins\n${Array.from(e.values()).map((e=>`(() => {${e}})();`)).join("\n\n")}\n// end injection by Datadog build plugins`},ut=async(e,t,n,s=process.cwd())=>{const o=await(async(e,t,n=process.cwd())=>{const s=new Map;for(const[o,r]of e.entries()){const e=await it(r,t,n);e&&s.set(o,{value:e,position:r.position||Q.BEFORE})}return s})(t,e,s);for(const[e,t]of o.entries())n[t.position].set(e,t.value)},pt=(e,t,n)=>({setup(o){const{onStart:i,onLoad:a,onEnd:u,esbuild:p,initialOptions:c}=o,l=[],d=`${I()}.${Q.MIDDLE}.${y}.js`,f=s.resolve(t.bundler.outDir,d),m=new RegExp(`${d}$`);c.inject=c.inject||[],c.inject.push(f),i((async()=>{l.push(...await M(o,t,e)),c.inject=c.inject?.filter((e=>e!==f))||[];try{await N(f,"")}catch(t){e.error(`Could not create the files: ${t.message}`)}})),a({filter:m,namespace:ot},(async()=>({contents:at(n[Q.MIDDLE])||" ",resolveDir:t.cwd,loader:"js"}))),u((async s=>{if(await z(f),!s.metafile)return void e.warn("Missing metafile from build result.");const o=at(n[Q.BEFORE]),i=at(n[Q.AFTER]);if(!o&&!i)return;const a=Object.entries(s.metafile.outputs).map((([e,n])=>{const s=n.entryPoint;if(!s)return;return l.find((e=>e.resolved.endsWith(s)))?Ce(t.cwd,e):void 0})).filter(Boolean).map((async e=>{const t=await r.readFile(e,"utf-8"),n=await p.transform(t,{loader:"default",banner:o,footer:i});await r.writeFile(e,n.code)}));await Promise.all(a)}))}}),ct=y,lt="?inject-proxy",dt=e=>({banner:t=>t.isEntry?at(e[Q.BEFORE]):"",async resolveId(t,n,s){if(O(t))return{id:t,moduleSideEffects:!0};if(s.isEntry&&at(e[Q.MIDDLE])){const e=await this.resolve(t,n,s);if(!e||e.external)return e;return(await this.load(e)).moduleSideEffects=!0,`${e.id}${lt}`}return null},load(t){if(O(t))return at(e[Q.MIDDLE]);if(t.endsWith(lt)){const e=t.slice(0,-13),n=this.getModuleInfo(e);let s=`import ${JSON.stringify(ct)};\nexport * from ${JSON.stringify(e)};`;return n?.hasDefaultExport&&(s+=`export { default } from ${JSON.stringify(e)};`),s}return null},footer:t=>t.isEntry?at(e[Q.AFTER]):""}),ft=(e,t,n,o,r)=>i=>{const a=new WeakMap,u=(e=>{if(!e?.sources?.ConcatSource)return g.createRequire(require.resolve("webpack"))("webpack-sources").ConcatSource;return e.sources.ConcatSource})(e),p=s.resolve(n.bundler.outDir,`${I()}.${Q.MIDDLE}.${y}.js`);"rspack"===n.bundler.name&&R(p,"");i.hooks.beforeRun.tapPromise(ot,(async()=>{await ut(t,o,r,n.cwd)})),"rspack"===n.bundler.name&&i.hooks.done.tapPromise(ot,(async()=>{await z(p)})),i.hooks.compilation.tap(ot,(t=>{const n=()=>{const e=at(r[Q.BEFORE]),n=at(r[Q.AFTER]);for(const s of t.chunks)if(s.canBeInitial())for(const o of s.files)t.updateAsset(o,(t=>{const s=a.get(t);if(!s||s.banner!==e||s.footer!==n){const s=new u(e,"\n",t,"\n",n);return a.set(t,{source:s,banner:e,footer:n}),s}return s.source}))};if(t.hooks.processAssets){const s=e.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS;t.hooks.processAssets.tap({name:ot,stage:s},n)}else t.hooks.optimizeChunkAssets.tap({name:ot},n)}));const c=(e=>{const s="webpack4"===n.bundler.fullName?p:{import:[p]},o=e=>{for(const[n,s]of Object.entries(e))"object"==typeof s?(s.import=s.import||[],s.import.unshift(p)):"string"==typeof s?e[n]=[p,s]:Array.isArray(s)?s.unshift(p):t.error("Invalid entry type: "+typeof s)};return e?"function"==typeof e?async()=>{const t=await e();return o(t),t}:"object"!=typeof e?"string"==typeof e?[s,e]:(t.error("Invalid entry type: "+typeof e),e):(o(e),e):{ddHelper:s}})(i.options.entry);i.options.entry=c},mt=(e,t)=>{const n=t.getLogger(ot),s=new Map,o={[Q.BEFORE]:new Map,[Q.MIDDLE]:new Map,[Q.AFTER]:new Map};t.inject=e=>{s.set(I(),e)};return[{name:ot,enforce:"post",esbuild:pt(n,t,o),webpack:ft(e,n,t,s,o),rspack:ft(e,n,t,s,o),rollup:dt(o),vite:{...dt(o),enforce:"pre"},async buildStart(){["webpack","rspack"].includes(t.bundler.name)||await ut(n,s,o,t.cwd)},resolveId:async e=>O(e)?{id:e}:null,loadInclude:e=>!!O(e)||null,load:e=>O(e)?{code:at(o[Q.MIDDLE])}:null}]},ht={[oe]:Te},gt="datadog-build-plugins";var wt="2.5.1-dev";const yt=(({bundler:n,version:s})=>e.createUnplugin(((e,o)=>{const r=((e={})=>({auth:{},disableGit:!1,logLevel:"warn",...e}))(e);"esbuild"===o.framework&&(o.esbuildHostName=gt);const i=(({options:e,bundlerName:t,bundlerVersion:n,version:s})=>{const o=process.cwd(),r="webpack"===t?n.split(".")[0]:"",i={errors:[],warnings:[],logs:[],bundler:{name:t,fullName:`${t}${r}`,variant:r,version:n}},a=process.env.BUILD_PLUGINS_ENV||"development",u=b.includes(a)?a:"development";return{auth:e.auth,pluginNames:[],bundler:{...i.bundler,outDir:o},build:i,cwd:o,env:u,getLogger:$(i,e.logLevel),inject:()=>{throw new Error("Inject function called before it was initialized.")},sendLog:()=>{throw new Error("SendLog function called before it was initialized.")},start:Date.now(),version:s}})({options:r,bundlerVersion:n.version||n.VERSION,bundlerName:o.framework,version:s});i.pluginNames.push(gt);const a=[...Ne(i),...We(i),...Ve(i),...st(r,i),...mt(n,i)];if(r.customPlugins){const e=r.customPlugins(r,i);a.push(...e)}r[k]&&!0!==r[k].disabled&&a.push(...Y(r,i)),r[X]&&!0!==r[X].disabled&&a.push(...se(r,i)),r[oe]&&!0!==r[oe].disabled&&a.push(...Oe(r,i)),i.pluginNames.push(...a.map((e=>e.name)));const u=new Set(i.pluginNames.filter((e=>i.pluginNames.filter((t=>t===e)).length>1)));if(u.size>0)throw new Error(`Duplicate plugin names: ${t.bold.red(Array.from(u).join(", "))}`);return a})))({bundler:w,version:wt}).rspack,bt=wt,vt=ht;exports.datadogRspackPlugin=yt,exports.helpers=vt,exports.version=bt;
3234
5
  //# sourceMappingURL=index.js.map