@datadog/rspack-plugin 2.4.1 → 2.5.0
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.d.ts +23 -14
- package/dist/src/index.js +4 -3233
- package/dist/src/index.js.map +1 -1
- package/dist/src/index.mjs +12 -3229
- package/dist/src/index.mjs.map +1 -1
- package/package.json +5 -3
- package/dist/src/index.d.ts.map +0 -1
package/dist/src/index.js
CHANGED
|
@@ -1,3234 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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.1";
|
|
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("async-retry"),s=require("fs/promises"),o=require("fs"),r=require("glob"),i=require("path"),a=require("outdent"),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=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()},v=async(e,t,n)=>{const s=[],o=e.initialOptions.entryPoints,i=[],a=[];if(Array.isArray(o))for(const e of o){const t=e&&"object"==typeof e?e.in:e;i.push({path:t})}else o&&"object"==typeof o&&i.push(...Object.entries(o).map((([e,t])=>({name:e,path:t}))));const u=i.flatMap((e=>{return(t=e.path,t.includes("*")?r.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&&a.push(...r.errors.map((e=>e.text))),r.path&&s.push({name:n.name,resolved:r.path,original:n.path})}));for(const e of a)n.error(e);return await Promise.all(u),s},$=[400,403,413],k=e=>{const{auth:t,url:s,method:o="GET",getData:r,onRetry:i,type:a="text"}=e;return n((async(e,n)=>{let i;try{const e={method:o,duplex:"half"};let n={};if(t?.apiKey&&(n["DD-API-KEY"]=t.apiKey),t?.appKey&&(n["DD-APPLICATION-KEY"]=t.appKey),"function"==typeof r){const{data:t,headers:s}=await r();e.body=t,n={...n,...s}}i=await fetch(s,{...e,headers:n})}catch(t){return e(t),{}}if(!i.ok){const t=`HTTP ${i.status} ${i.statusText}`;if($.includes(i.status))return e(new Error(t)),{};throw new Error(t)}try{let e;return e="json"===a?await i.json():await i.text(),e}catch(t){return e(t),{}}}),{retries:5,onRetry:i})},S=(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)}`},D=e=>e.includes(y),E=async e=>s.rm(e,{force:!0,maxRetries:3,recursive:!0}),P=async(e,t)=>{await(async e=>s.mkdir(e,{recursive:!0}))(i.dirname(e)),await s.writeFile(e,t,{encoding:"utf-8"})},M=(e,t)=>{var n;n=i.dirname(e),o.mkdirSync(n,{recursive:!0}),o.writeFileSync(e,t,{encoding:"utf-8"})};let j=0;const O=()=>`${Date.now()}.${performance.now()}.${++j}`,z={debug:0,info:1,warn:2,error:3,none:4},T=(e,n="warn")=>s=>{const o=s.replace(/(^datadog-|-plugin$)/g,""),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),z[r]>=z[n]&&a(`${i(u)} ${p}`)};return{getLogger:t=>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")}},N="errorTracking",x="datadog-error-tracking-plugin",R=(e,n,s)=>{if(".map"!==i.extname(s))throw new Error(`The file ${t.green.bold(s)} is not a sourcemap.`);const o=s.replace(/\.map$/,""),r=o.replace(n.bundler.outDir,"");return{minifiedFilePath:o,minifiedUrl:e.minifiedPathPrefix?i.join(e.minifiedPathPrefix,r):r,relativePath:r}},A=/[/]+|[\\]+/g,F=/^[/]+|^[\\]+|[/]+$|[\\]+$/g,I=(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},q=async e=>{const t={empty:!1,exists:!0};try{0===(await o.promises.stat(e)).size&&(t.empty=!0)}catch(e){if("ENOENT"!==e.code)throw e;t.exists=!1}return t},C=async(e,t,n,s)=>{const o=await(async(e,t)=>{const[n,s]=await Promise.all([q(e.minifiedFilePath),q(e.sourcemapFilePath)]);return{file:n,sourcemap:s,repeatedPrefix:I(e.relativePath,t)}})(e,n),r=[],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(s)try{u.set("repository",{type:"string",options:{contentType:"application/json",filename:"repository"},value:JSON.stringify({data:[{files:s.trackedFilesMatcher.matchSourcemap(e.sourcemapFilePath,(t=>{a.push(`${i.basename(e.sourcemapFilePath)}: "${t}"`)})),hash:s.hash,repository_url:s.remote}],version:1})})}catch(t){a.push(`Could not attach git data for sourcemap ${e.sourcemapFilePath}: ${t.message}`)}return o.file.empty&&r.push(`Minified file is empty: ${e.minifiedFilePath}`),o.file.exists||r.push(`Minified file not found: ${e.minifiedFilePath}`),o.sourcemap.empty&&r.push(`Sourcemap file is empty: ${e.sourcemapFilePath}`),o.sourcemap.exists||r.push(`Sourcemap file not found: ${e.sourcemapFilePath}`),o.repeatedPrefix&&a.push(`The minified file path contains a repeated pattern with the minified path prefix: ${o.repeatedPrefix}`),{content:u,errors:r,warnings:a}},_=t.green.bold,L=t.yellow.bold,H=t.red.bold,W=async(e,t)=>{if("function"==typeof o.openAsBlob){const n=await o.openAsBlob(e,{type:t.contentType});return new u.File([n],t.filename)}{const n=c.Readable.toWeb(o.createReadStream(e)),s=await new Response(n).blob();return new u.File([s],t.filename,{type:t.contentType})}},B=(e,t={})=>async()=>{const n=new FormData,s=l.createGzip();for(const[t,s]of e.content){const e="file"===s.type?await W(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())}}},G=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=>C(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 k({url:t.intakeUrl,method:"POST",getData:B(p,a),onRetry:(t,n)=>{const o=`Failed to upload ${L(e.sourcemap)} | ${L(e.file)}:\n ${t.message}\nRetrying ${n}/5`;r.push(o),s.warn(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 ${_(b(Date.now()-o))}.`),l.length>0){const e=`Failed to upload some sourcemaps:\n${` - ${l.map((({metadata:e,error:t})=>e?`${H(e.file)} | ${H(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 - ${c.join("\n - ")}`)},U=async(e,n,s)=>{const o=t.green.bold,r=Object.entries(e.sourcemaps).map((([e,t])=>` - ${e}: ${o(t.toString())}`)).join("\n"),i=((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=>({...R(e,t,n),sourcemapFilePath:n,minifiedPathPrefix:e.minifiedPathPrefix})))})(e.sourcemaps,n),u=a.outdent`
|
|
2
|
+
Uploading ${o(i.length.toString())} sourcemaps with configuration:
|
|
3
|
+
${r}
|
|
4
|
+
`;s.info(u),await G(i,e.sourcemaps,n,s)},K=`https://sourcemap-intake.${process.env.DATADOG_SITE||"datadoghq.com"}/api/v2/srcmap`,J=e=>{const n=t.bold.red,s=e[N]||{},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,dryRun:!1,maxConcurrency:20,intakeUrl:process.env.DATADOG_SOURCEMAP_INTAKE_URL||s.sourcemaps.intakeUrl||K,...s.sourcemaps};o.config=e}return o},V=(e,t,n)=>{const s=((e,t)=>{const n=[],s=J(e);if(n.push(...s.errors),n.length)throw t.error(`\n - ${n.join("\n - ")}`),new Error(`Invalid configuration for ${x}.`);const o={...e[N],sourcemaps:void 0};return s.config&&(o.sourcemaps=s.config),o})(e,n);return[{name:x,enforce:"post",async writeBundle(){s.disabled||s.sourcemaps&&await U(s,t,n)}}]},Y="telemetry",Q="datadog-telemetry-plugin",X=[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}],Z=(e,t)=>({type:"gauge",tags:[...e.tags,...t.tags],metric:`${t.prefix?`${t.prefix}.`:""}${e.metric}`,points:[[t.timestamp,e.value]]}),ee=(e="")=>e.endsWith("/")?e:`${e}/`,te=(e,t)=>{let n=e;return e.split(ee(t)),n.split("!").pop().replace(/(.*)?\/node_modules\//,"/node_modules/").replace(/^((\.)*\/)+/,"")},ne=(e,t)=>e.split("!").pop().replace(ee(t),"./"),se=(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)),ne(s||"no-name",n)},oe=e=>e.replace(/^.*\/node_modules\/(@[a-z0-9][\w-.]+\/[a-z0-9][\w-.]*|[^/]+).*$/,"$1"),re=e=>e.map((e=>({type:e?.constructor?.name??typeof e,name:e?.name,value:"string"==typeof e?e:void 0}))),ie=(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(Z(s,t))}else n.add(Z(e,t))},ae=async(e,t,n,s)=>{if("string"!=typeof t&&"object"!=typeof t&&!t)return;const{report:o,metrics:r}=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=i.resolve(s,u);try{const e={},t={};p.timings&&o?.timings&&(t.timings={content:{tapables:o.timings.tapables?Array.from(o.timings.tapables.values()):null,loaders:o.timings.loaders?Array.from(o.timings.loaders.values()):null,modules:o.timings.modules?Array.from(o.timings.modules.values()):null}}),p.metrics&&(t.metrics={content:Array.from(r)});const s=Object.entries(t).map((async([t,s])=>{const o=Date.now();n.debug(`Start writing ${t}.json.`);try{await(async(e,t)=>{const n=JSON.stringify(t,null,4);return P(e,n)})(i.join(c,`${t}.json`),s.content),n.debug(`Wrote ${t}.json in ${b(Date.now()-o)}`)}catch(s){n.error(`Failed to write ${t}.json in ${b(Date.now()-o)}`),e[t]=s}}));await Promise.all(s),n.debug(`Wrote files in ${b(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}`)}},ue=t.bold.red,pe=t.bold.cyan,ce=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},le=(e,t)=>{if(!t||!t.size)return[];const n=Array.from(t.values());n.sort(ce("duration"));const s={name:`${e} duration`,values:n.map((e=>({name:e.name,value:b(e.duration)}))),top:!0};n.sort(ce("increment"));return[s,{name:`${e} hits`,values:n.map((e=>({name:e.name,value:e.increment.toString()}))),top:!0}]},de=(e,t,n)=>{const s=[];var o;n&&(s.push(...le("Loader",n.timings.loaders)),s.push(...le("Tapable",n.timings.tapables)),s.push(...le("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(ce((e=>e.dependents.size))),t.values=c.map((e=>({name:e.name,value:e.dependents.size.toString()}))),c.sort(ce((e=>e.dependencies.size))),n.values=c.map((e=>({name:e.name,value:e.dependencies.size.toString()}))),c.sort(ce("size")),s.values=c.map((e=>({name:e.name,value:d(e.size)}))),c.sort(ce("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(ce((e=>e.size))).map((e=>({name:e.name,value:d(e.size)}))),top:!0},{name:"Entry aggregated size",values:(o.build.entries||[]).sort(ce((e=>e.size))).map((e=>({name:e.name,value:d(e.size)}))),top:!0},{name:"Entry number of modules",values:(o.build.entries||[]).sort(ce((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:b(e.build.start-e.start)}),e.build.duration&&t.values.push({name:"Build duration",value:b(e.build.duration)}),e.build.writeDuration&&t.values.push({name:"Write duration",value:b(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=S(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+=` [${ue(e.value)}] ${" ".repeat(n)}${pe(e.name)}\n`}}return t})(s);t.info(r)},fe=["onStart","onLoad","onResolve","onEnd"],me=new Map,he=new Map,ge=(e,t,n)=>{const s=Object.assign({},e);for(const o of fe)s[o]=async(s,r)=>{const i=me.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=ne(e[0].path,n),a=he.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:re(e)};i.events[o].values.push(p),i.duration+=r,i.increment+=1,me.set(t,i),a.events[o].values.push(p),a.duration+=r,a.increment+=1,he.set(s,a)}}))};return s},we=(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(Q))continue;const n=s.setup;s.setup=async o=>{const r=ge(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:me,modules:he};e.report={timings:{tapables:s,modules:o}}}))}});class ye{constructor(e){this.started={},this.finished=[],this.cwd=e}buildModule(e,t){const n=se(e,t,this.cwd),s=(e=>(e.loaders||[]).map((e=>e.loader||e)).map(oe))(e);s.length||s.push("no-loader"),this.started[n]={module:te(n),timings:{start:f.performance.now(),duration:0,end:0},loaders:s}}succeedModule(e,t){const n=se(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 be{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,re(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,re(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,re(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(Q)||(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 ve=(e,t)=>async n=>{t.build.start=Date.now();const s={name:Q},o=new be(t.cwd),r=new ye(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}}}))},$e={filters:X},ke=(e,t,n)=>{let s=0;const o={start:Date.now()},r=(e=>{const t=e[Y]||{},n=t.endPoint||"https://app.datadoghq.com";return{disabled:!1,enableTracing:!1,filters:X,output:!1,prefix:"",tags:[],...t,endPoint:n.startsWith("http")?n:`https://${n}`}})(e),i=[],a={name:Q,enforce:"pre",esbuild:we(o,t,n),webpack:ve(o,t),rspack:ve(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);ie(t,i,e,o.report),await ae({report:o.report,metrics:e},r.output,n,t.bundler.outDir),de(t,n,o.report),await((e,t,n)=>{const s=Date.now();if(!t.apiKey)return void n.warn("Won't send metrics to Datadog: missing API Key.");if(!e.size)return void n.warn("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 - ")}`),k({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 ${b(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},Se=/\.(?!.*(?:\.|\/|\\))(\w{1,})/g,De=/(\?|%3F|\|)+/gi,Ee=e=>{return"unknown"===e?e:e.includes("webpack/runtime")?"runtime":(t=je(e),Se.lastIndex=0,Se.exec(t)?.[1]||"unknown");var t},Pe=["unknown","commonjsHelpers.js","vite/preload-helper.js"],Me=(e,t,n)=>{const s=new Set;for(const n of e){const e=je(n);D(n)||e===t||Pe.includes(e)||s.add(e)}return s},je=e=>e.split("!").pop().split(De).shift().replace(/^[^\w\s.,!@#$%^&*()=+~`\-/]+/,""),Oe=(e,t)=>D(t)?y:t.startsWith(e)?t:i.resolve(e,t),ze=(e,t)=>D(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(De).shift().replace(/^\/+/,""),Te=(e,t)=>Object.fromEntries(Object.entries(e).map((([e,n])=>[Oe(t,e),n]))),Ne=(e,t)=>({setup(n){const s=new Map,o=[];n.onStart((async()=>{o.push(...await v(n,e,t));for(const t of o){const n=ze(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);const r=n=>{e.build.warnings.push(n),t.warn(n)};if(!n.metafile)return void r("Missing metafile from build result.");const i=[],a=[],u=[],p=[],c=[],l={},d={},f=Te(n.metafile.inputs,o),m=Te(n.metafile.outputs,o),h=e=>{if(!D(e))return e;const t=f[Oe(o,e)];if(!t)return e;const n=t.imports.find((e=>!D(e.path)));return n?n.path:e};for(const[t,s]of Object.entries(n.metafile.inputs)){if(D(t))continue;const n=Oe(o,t),r={name:ze(e,t),filepath:n,dependents:new Set,dependencies:new Set,size:s.bytes,type:Ee(t)};l[n]=r,i.push(r)}for(const[t,i]of Object.entries(n.metafile.outputs)){const n=Oe(o,t),c=ze(e,n),f=[];for(const e of Object.keys(i.inputs)){if(D(e))continue;const t=l[Oe(o,e)];t?f.push(t):r(`Input ${e} not found for output ${c}`)}if(i.entryPoint&&!f.length){const e=l[Oe(o,i.entryPoint)];if(!e){r(`Input ${i.entryPoint} not found for output ${c}`);continue}f.push(e)}const m={name:c,filepath:n,inputs:f,size:i.bytes,type:Ee(n)};if(d[n]=m,"map"===m.type&&p.push(m),a.push(m),!i.entryPoint)continue;const g=l[Oe(o,h(i.entryPoint))];if(g){if(!s.get(g.name))continue;const e={...m,name:s.get(g.name)||g.name,outputs:[m],size:m.size};u.push(e)}}for(const e of p){const t=d[e.filepath.replace(/\.map$/,"")];t?e.inputs.push(t):r(`Could not find output for sourcemap ${e.name}`)}const g={inputs:{report:l,meta:f},outputs:{report:d,meta:m}},w=/(<runtime>|https:|file:|data:|#)/g,y=e=>!D(e)&&!e.match(w),b=(e,t,n={})=>{if(!y(e))return n;const s=t.report[e];if(!s)return r(`Could not find report's ${e}`),n;if(n[s.filepath])return n;n[s.filepath]=s;const i=t.meta[e];if(!i)return r(`Could not find metafile's ${e}`),n;if(!i.imports||!i.imports.length)return n;for(const e of i.imports){const s=Oe(o,e.path);b(s,t,n)}return n};for(const e of u){const t={},n={};for(const n of e.inputs)b(n.filepath,g.inputs,t);for(const t of e.outputs)b(t.filepath,g.outputs,n);e.inputs=Object.values(t),e.outputs=Object.values(n),e.size=e.outputs.reduce(((e,t)=>e+t.size),0),c.push(e)}for(const e of i){const t=g.inputs.meta[e.filepath];if(t)for(const n of t.imports){if(!y(n.path))continue;const t=Oe(o,n.path),s=g.inputs.report[t];s?(e.dependencies.add(s),s.dependents.add(e)):r(`Could not find input file of ${n.path}`)}else r(`Could not find metafile's ${e.name}`)}e.build.outputs=a,e.build.inputs=i,e.build.entries=c}))}}),xe=(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=je(e.id),s=n[t]||{dependencies:new Set,dependents:new Set},o=Me(new Set([...e.dynamicallyImportedIds,...e.importedIds]),t),r=Me(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={},d=n=>{e.build.warnings.push(n),t.warn(n)};for(const[e,{dependencies:t,dependents:s}]of Object.entries(n)){for(const s of t){const t=je(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=je(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:Oe(e.bundler.outDir,t),inputs:[],size:"code"in n?Buffer.byteLength(n.code,"utf8"):Buffer.byteLength(n.source,"utf8"),type:Ee(t)};if("map"===s.type&&u.push(s),"modules"in n)for(const[t,o]of Object.entries(n.modules)){if(je(t)!==t)continue;const n={name:ze(e,t),dependencies:new Set,dependents:new Set,filepath:t,size:o.originalLength,type:Ee(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 t of r){const s=n[t.filepath];if(s){for(const n of s.dependencies){const s=c[n];s?t.dependencies.add(s):d(`Could not find input for dependency ${ze(e,n)} of ${t.name}`)}for(const n of s.dependents){const s=c[n];s?t.dependents.add(s):d(`Could not find input for dependent ${ze(e,n)} of ${t.name}`)}}else d(`Could not find the import report for ${t.name}.`)}if(u.length)for(const e of u){const t=e.filepath.replace(/\.map$/,""),n=l[t];n?e.inputs.push(n):d(`Could not find output for sourcemap ${e.name}`)}const f=(t,n={})=>{if(n[t])return n;const s=ze(e,t),r=l[t];if(!r)return d(`Could not find output for ${s}`),n;n[t]=r;const i=o[s];if(!i)return d(`Could not find asset for ${s}`),n;const a=[];"imports"in i&&a.push(...i.imports),"dynamicImports"in i&&a.push(...i.dynamicImports);for(const t of a)f(Oe(e.bundler.outDir,t),n);return n};for(const e of a){const t=f(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}}},Re=(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 ")||D(e)),m=t=>{e.build.warnings.push(t),n.warn(t)},h=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 n=new Set;for(const[s,o]of Object.entries(t))o&&(c.has(o)?(m(`Module ${e.identifier()} is already indexed by ${s}.`),c.get(o)!==e&&m(`Module ${e.identifier()} is indexed with a different value.`)):n.add(o));return n},g=(e,t=[])=>{if("dependencies"in e)for(const n of e.dependencies)t.push(n),g(n,t);if("blocks"in e)for(const n of e.blocks)g(n,t);return t},w=(e,t)=>{if("request"in t&&t.request){if(c.has(t.request))return c.get(t.request);if(e.context&&c.has(Oe(e.context,t.request)))return c.get(Oe(e.context,t.request))}};s.hooks.thisCompilation.tap(t,(n=>{n.hooks.finishModules.tap(t,(t=>{for(const e of t){const t=h(e);for(const n of t)c.set(n,e)}for(const n of t){const t=n.identifier(),s=new Set(g(n).map((e=>{const s=w(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:ze(e,t),dependencies:new Set,dependents:new Set,filepath:t,type:Ee(t)};o.push(i),a.set(t,i)}for(const e of o){const t=d.get(e.filepath);if(t){for(const n of t.dependencies){const t=a.get(n);t?e.dependencies.add(t):m(`Could not find input of dependency ${n}`)}for(const n of t.dependents){const t=a.get(n);t?e.dependents.add(t):m(`Could not find input of dependent ${n}`)}}else m(`Could not find dependency report for ${e.name}`)}}))})),s.hooks.afterEmit.tap(t,(t=>{const n=t.chunks,s=t.getAssets(),c=t=>[...t.files||[],...t.auxiliaryFiles||[]].map((t=>Oe(e.bundler.outDir,t))),d=t.chunkGraph;for(const e of n){const t=c(e),n=(d?d?.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"===Ee(e))continue;const t=p.get(e)||[];p.set(e,[...t,...n])}}for(const t of s){const n={size:t.source.size()||0,name:t.name,inputs:[],filepath:Oe(e.bundler.outDir,t.name),type:Ee(t.name)};if(u.set(n.filepath,n),r.push(n),"map"===n.type){l.push(n);continue}const s=p.get(n.filepath);if(s)for(const e of s){const t=a.get(e);t?n.inputs.push(t):m(`Could not find input of ${e}`)}else m(`Could not find modules for ${n.name}`)}for(const e of l){const t=u.get(e.filepath.replace(/\.map$/,""));t?e.inputs.push(t):m(`Output not found for sourcemap ${e.name}`)}for(const[n,s]of t.entrypoints){const t=[],o=[];let r=0;const a=s.chunks.flatMap(c),p=s.chunks.filter((e=>d?d.getChunkEntryModulesIterable(e):"hasEntryModule"in e&&"function"==typeof e.hasEntryModule&&e.hasEntryModule())).flatMap((e=>Array.from(e.files))).filter((e=>e.includes(n)||s.name&&e.includes(s.name))).find((e=>"js"===Ee(e)));for(const e of a){const n=u.get(e);e&&n?"map"===n.type||t.includes(n)||(t.push(n),o.push(...n.inputs),r+=n.size):m(`Could not find output of ${JSON.stringify(e)}`)}const l={name:n,filepath:p?Oe(e.bundler.outDir,p):"unknown",size:r,inputs:Array.from(new Set(o)),outputs:t,type:p?Ee(p):"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}))},Ae="datadog-build-report-plugin",Fe=(e,t)=>[{name:Ae,enforce:"post",esbuild:Ne(e,t),rspack:Re(e,Ae,t),webpack:Re(e,Ae,t),vite:xe(e,t),rollup:xe(e,t)}],Ie=(e,t)=>{const n=((e,t)=>{const n=e.map((e=>(i.isAbsolute(e)?e:i.resolve(t,e)).split(i.sep))),s=Math.min(...n.map((e=>e.length))),o=[];for(let e=0;e<s;e++){const t=n[0][e];if(!n.every((n=>n[e]===t)))break;o.push(t)}return o.length>0?o.join(i.sep):i.sep})(e,t.cwd);n!==i.sep&&(t.cwd=n)},qe=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)},Ce=e=>{const t=new Set,n=n=>{n&&(n.dir?(e.bundler.outDir=n.dir,t.add(n.dir)):n.file&&(e.bundler.outDir=i.dirname(n.file),t.add(n.dir)),"vite"!==e.bundler.name&&Ie(Array.from(t),e))},s=()=>({options(s){if(e.bundler.rawConfig=s,s.input)if(Array.isArray(s.input))for(const e of s.input)t.add(i.dirname(e));else if("object"==typeof s.input)for(const e of Object.values(s.input))t.add(i.dirname(e));else{if("string"!=typeof s.input)throw new Error("Invalid input type");t.add(i.dirname(s.input))}"output"in s&&n(s.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=i.dirname(t.initialOptions.outfile)),t.initialOptions.absWorkingDir&&(e.cwd=t.initialOptions.absWorkingDir),t.initialOptions.metafile=!0}},webpack:qe(e),rspack:qe(e),vite:{...s(),config(n){n.root?e.cwd=n.root:Ie(Array.from(t),e)}},rollup:s()}]};class _e{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=o.readFileSync(e,"utf8"),s=JSON.parse(n);if(!s.sources)return void t("Missing 'sources' field in sourcemap.");const r=s.sources;if(0===r.length)return void t("Empty 'sources' field in sourcemap.");const i=this.matchSources(r);if(0!==i.length)return i;t(`${r.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 Le=async e=>{const t=await e.getRemotes(!0);if(0===t.length)throw new Error("No git remotes available");const n=await He(e);for(const e of t)if(e.name===n)return We(e.refs.push);return We(t[0].refs.push)},He=async e=>{try{return(await e.getConfig("clone.defaultRemoteName"))?.value??"origin"}catch(e){return"origin"}},We=e=>{try{const t=new h.URL(e);return t.username="",t.password="",t.toString()}catch{return e}},Be=async e=>e.revparse("HEAD"),Ge=async e=>(await e.raw("ls-files")).split(/\r\n|\r|\n/),Ue=(e,t)=>[{name:"datadog-git-plugin",enforce:"pre",async buildStart(){if(!(e.errorTracking?.sourcemaps&&!0!==e.disableGit))return;const n=await(async e=>{let t,n,s;return[t,n,s]=await Promise.all([Le(e),Be(e),Ge(e)]),{hash:n,remote:t,trackedFilesMatcher:new _e(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=n}}];var Ke=(e=>(e[e.BEFORE=0]="BEFORE",e[e.MIDDLE=1]="MIDDLE",e[e.AFTER=2]="AFTER",e))(Ke||{});const Je="datadog-injection-plugin",Ve=/^https?:\/\//,Ye=async(e,t,n=process.cwd())=>{let o;const r=await(async e=>"function"==typeof e.value?e.value():e.value)(e);try{if("file"===e.type)o=r.match(Ve)?await(async(e,t=5e3)=>{let n;return Promise.race([k({url:e}).finally((()=>{t&&clearTimeout(n)})),new Promise(((e,s)=>{n=setTimeout((()=>{s(new Error("Timeout"))}),t)}))])})(r):await(async(e,t=process.cwd())=>{const n=Oe(t,e);return s.readFile(n,{encoding:"utf-8"})})(r,n);else{if("code"!==e.type)throw new Error(`Invalid item type "${e.type}", only accepts "code" or "file".`);o=r}}catch(n){const s=`${e.type} - ${S(r)}`;e.fallback?(t.warn(`Fallback for "${s}": ${n.toString()}`),o=await Ye(e.fallback,t)):(t.warn(`Failed "${s}": ${n.toString()}`),o="")}return o},Qe=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`},Xe=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 Ye(r,t,n);e&&s.set(o,{value:e,position:r.position||Ke.BEFORE})}return s})(t,e,s);for(const[e,t]of o.entries())n[t.position].set(e,t.value)},Ze=(e,t,n)=>({setup(o){const{onStart:r,onLoad:a,onEnd:u,esbuild:p,initialOptions:c}=o,l=[],d=`${O()}.${Ke.MIDDLE}.${y}.js`,f=i.resolve(t.bundler.outDir,d),m=new RegExp(`${d}$`);c.inject=c.inject||[],c.inject.push(f),r((async()=>{l.push(...await v(o,t,e)),c.inject=c.inject?.filter((e=>e!==f))||[];try{await P(f,"")}catch(t){e.error(`Could not create the files: ${t.message}`)}})),a({filter:m,namespace:Je},(async()=>{const e=Qe(n[Ke.MIDDLE]);return await E(f),{contents:e||" ",resolveDir:t.cwd,loader:"js"}})),u((async o=>{if(!o.metafile)return void e.warn("Missing metafile from build result.");const r=Qe(n[Ke.BEFORE]),i=Qe(n[Ke.AFTER]);if(!r&&!i)return;const a=Object.entries(o.metafile.outputs).map((([e,n])=>{const s=n.entryPoint;if(!s)return;return l.find((e=>e.resolved.endsWith(s)))?Oe(t.cwd,e):void 0})).filter(Boolean).map((async e=>{const t=await s.readFile(e,"utf-8"),n=await p.transform(t,{loader:"default",banner:r,footer:i});await s.writeFile(e,n.code)}));await Promise.all(a)}))}}),et=y,tt="?inject-proxy",nt=e=>({banner:t=>t.isEntry?Qe(e[Ke.BEFORE]):"",async resolveId(t,n,s){if(D(t))return{id:t,moduleSideEffects:!0};if(s.isEntry&&Qe(e[Ke.MIDDLE])){const e=await this.resolve(t,n,s);if(!e||e.external)return e;return(await this.load(e)).moduleSideEffects=!0,`${e.id}${tt}`}return null},load(t){if(D(t))return Qe(e[Ke.MIDDLE]);if(t.endsWith(tt)){const e=t.slice(0,-13),n=this.getModuleInfo(e);let s=`import ${JSON.stringify(et)};\nexport * from ${JSON.stringify(e)};`;return n?.hasDefaultExport&&(s+=`export { default } from ${JSON.stringify(e)};`),s}return null},footer:t=>t.isEntry?Qe(e[Ke.AFTER]):""}),st=(e,t,n,s,o)=>r=>{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=i.resolve(n.bundler.outDir,`${O()}.${Ke.MIDDLE}.${y}.js`);"rspack"===n.bundler.name&&M(p,"");r.hooks.beforeRun.tapPromise(Je,(async()=>{await Xe(t,s,o,n.cwd)})),"rspack"===n.bundler.name&&r.hooks.done.tapPromise(Je,(async()=>{await E(p)})),r.hooks.compilation.tap(Je,(t=>{const n=()=>{const e=Qe(o[Ke.BEFORE]),n=Qe(o[Ke.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:Je,stage:s},n)}else t.hooks.optimizeChunkAssets.tap({name:Je},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}})(r.options.entry);r.options.entry=c},ot=(e,t,n,s,o)=>{const r={[Ke.BEFORE]:new Map,[Ke.MIDDLE]:new Map,[Ke.AFTER]:new Map};return[{name:Je,enforce:"post",esbuild:Ze(o,n,r),webpack:st(e,o,n,s,r),rspack:st(e,o,n,s,r),rollup:nt(r),vite:{...nt(r),enforce:"pre"},async buildStart(){["webpack","rspack"].includes(n.bundler.name)||await Xe(o,s,r,n.cwd)},resolveId:async e=>D(e)?{id:e}:null,loadInclude:e=>!!D(e)||null,load:e=>D(e)?{code:Qe(r[Ke.MIDDLE])}:null}]},rt={[Y]:$e},it="datadog-build-plugins";var at="2.5.0";const ut=(({bundler:n,version:s})=>e.createUnplugin(((e,o)=>{const r=((e={})=>({auth:{},disableGit:!1,logLevel:"warn",...e}))(e);"esbuild"===o.framework&&(o.esbuildHostName=it);const i=new Map,a=(({options:e,bundlerName:t,bundlerVersion:n,injections:s,version:o})=>{const r=process.cwd(),i="webpack"===t?n.split(".")[0]:"",a={errors:[],warnings:[],logs:[],bundler:{name:t,fullName:`${t}${i}`,variant:i,version:n}};return{auth:e.auth,pluginNames:[],bundler:{...a.bundler,outDir:r},build:a,cwd:r,inject:e=>{s.set(O(),e)},start:Date.now(),version:o}})({options:r,bundlerVersion:n.version||n.VERSION,bundlerName:o.framework,injections:i,version:s}),u=T(a.build,r.logLevel);a.pluginNames.push(it);const p=[...Fe(a,u("datadog-build-report-plugin")),...Ce(a),...Ue(r,a),...ot(n,0,a,i,u("datadog-injection-plugin"))];if(r.customPlugins){const e=r.customPlugins(r,a,u("datadog-custom-plugins"));p.push(...e)}r[N]&&!0!==r[N].disabled&&p.push(...V(r,a,u(x))),r[Y]&&!0!==r[Y].disabled&&p.push(...ke(r,a,u(Q))),a.pluginNames.push(...p.map((e=>e.name)));const c=new Set(a.pluginNames.filter((e=>a.pluginNames.filter((t=>t===e)).length>1)));if(c.size>0)throw new Error(`Duplicate plugin names: ${t.bold.red(Array.from(c).join(", "))}`);return p})))({bundler:w,version:at}).rspack,pt=at,ct=rt;exports.datadogRspackPlugin=ut,exports.helpers=ct,exports.version=pt;
|
|
3234
5
|
//# sourceMappingURL=index.js.map
|