@typeslayer/analyze-trace 0.0.0 → 0.1.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/index.js ADDED
@@ -0,0 +1,669 @@
1
+ // src/analyze-trace.ts
2
+ import { existsSync as existsSync3 } from "fs";
3
+ import { readFile as readFile2, writeFile } from "fs/promises";
4
+ import { join as join2 } from "path";
5
+ import {
6
+ TRACE_JSON_FILENAME,
7
+ TYPES_JSON_FILENAME,
8
+ traceJsonSchema,
9
+ typesJsonSchema
10
+ } from "@typeslayer/validate";
11
+
12
+ // src/constants.ts
13
+ var ANALYZE_TRACE_FILENAME = "analyze-trace.json";
14
+
15
+ // src/depth-limits.ts
16
+ import {
17
+ depthLimits,
18
+ event_checktypes__checkCrossProductUnion_DepthLimit,
19
+ event_checktypes__checkTypeRelatedTo_DepthLimit,
20
+ event_checktypes__getTypeAtFlowNode_DepthLimit,
21
+ event_checktypes__instantiateType_DepthLimit,
22
+ event_checktypes__recursiveTypeRelatedTo_DepthLimit,
23
+ event_checktypes__removeSubtypes_DepthLimit,
24
+ event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit,
25
+ event_checktypes__typeRelatedToDiscriminatedType_DepthLimit
26
+ } from "@typeslayer/validate";
27
+ var createDepthLimits = (traceFile) => {
28
+ const limitNamesSet = new Set(
29
+ depthLimits.map((d) => d.shape.name)
30
+ );
31
+ const limitEvents = traceFile.filter((event) => limitNamesSet.has(event.name));
32
+ return {
33
+ checkCrossProductUnion_DepthLimit: limitEvents.filter(
34
+ (event) => event_checktypes__checkCrossProductUnion_DepthLimit.safeParse(event).success
35
+ ).sort((a, b) => a.args.size - b.args.size),
36
+ checkTypeRelatedTo_DepthLimit: limitEvents.filter(
37
+ (event) => event_checktypes__checkTypeRelatedTo_DepthLimit.safeParse(event).success
38
+ ).sort((a, b) => a.args.depth - b.args.depth),
39
+ getTypeAtFlowNode_DepthLimit: limitEvents.filter(
40
+ (event) => event_checktypes__getTypeAtFlowNode_DepthLimit.safeParse(event).success
41
+ ).sort((a, b) => a.args.flowId - b.args.flowId),
42
+ instantiateType_DepthLimit: limitEvents.filter(
43
+ (event) => event_checktypes__instantiateType_DepthLimit.safeParse(event).success
44
+ ).sort((a, b) => a.args.instantiationDepth - b.args.instantiationDepth),
45
+ recursiveTypeRelatedTo_DepthLimit: limitEvents.filter(
46
+ (event) => event_checktypes__recursiveTypeRelatedTo_DepthLimit.safeParse(event).success
47
+ ).sort((a, b) => a.args.depth - b.args.depth),
48
+ removeSubtypes_DepthLimit: limitEvents.filter(
49
+ (event) => event_checktypes__removeSubtypes_DepthLimit.safeParse(event).success
50
+ ),
51
+ traceUnionsOrIntersectionsTooLarge_DepthLimit: limitEvents.filter(
52
+ (event) => event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit.safeParse(
53
+ event
54
+ ).success
55
+ ).sort(
56
+ (a, b) => a.args.sourceSize * a.args.targetSize - b.args.sourceSize * b.args.targetSize
57
+ ),
58
+ typeRelatedToDiscriminatedType_DepthLimit: limitEvents.filter(
59
+ (event) => event_checktypes__typeRelatedToDiscriminatedType_DepthLimit.safeParse(
60
+ event
61
+ ).success
62
+ ).sort((a, b) => a.args.numCombinations - b.args.numCombinations)
63
+ };
64
+ };
65
+
66
+ // src/get-duplicate-node-modules.ts
67
+ import { existsSync } from "fs";
68
+ import { readFile } from "fs/promises";
69
+ import { join } from "path";
70
+ async function getPackageVersion(packagePath2) {
71
+ const packageJsonPath = join(packagePath2, "package.json");
72
+ console.log("packageJsonPath", packageJsonPath);
73
+ if (!existsSync(packageJsonPath)) {
74
+ console.warn(
75
+ `Package.json not found at ${packageJsonPath}. This may not be a node module.`
76
+ );
77
+ return "unknown";
78
+ }
79
+ const jsonString = await readFile(packageJsonPath, "utf-8");
80
+ const jsonObj = JSON.parse(jsonString);
81
+ return jsonObj.version;
82
+ }
83
+ var getDuplicateNodeModules = async (nodeModulePaths2) => {
84
+ const duplicates = [];
85
+ for (const [packageName2, packagePaths] of Object.entries(nodeModulePaths2)) {
86
+ if (packagePaths.length < 2) {
87
+ continue;
88
+ }
89
+ const instances = [];
90
+ for (const packagePath2 of packagePaths) {
91
+ instances.push({
92
+ path: packagePath2,
93
+ version: await getPackageVersion(packagePath2)
94
+ });
95
+ }
96
+ duplicates.push({
97
+ name: packageName2,
98
+ instances
99
+ });
100
+ }
101
+ return duplicates;
102
+ };
103
+
104
+ // src/get-hotspots.ts
105
+ import { normalize } from "path";
106
+ import {
107
+ createTypeRegistry
108
+ } from "@typeslayer/validate";
109
+ var getHotspots = async (hotPathsTree, typesFile, options) => getHotspotsWorker({
110
+ span: hotPathsTree,
111
+ currentFile: void 0,
112
+ typeRegistry: createTypeRegistry(typesFile),
113
+ options
114
+ });
115
+ async function getHotspotsWorker({
116
+ span,
117
+ currentFile,
118
+ typeRegistry,
119
+ options
120
+ }) {
121
+ if (span.event.cat === "check") {
122
+ currentFile = span.event.args.path;
123
+ }
124
+ const children = [];
125
+ if (span.children.length) {
126
+ const sortedChildren = span.children.sort(
127
+ (a, b) => b.duration - a.duration
128
+ );
129
+ for (const child of sortedChildren) {
130
+ children.push(
131
+ ...await getHotspotsWorker({
132
+ span: child,
133
+ currentFile,
134
+ typeRegistry,
135
+ options
136
+ })
137
+ );
138
+ }
139
+ }
140
+ if (span.event.name !== "root") {
141
+ const hotFrame = await makeHotFrame({
142
+ span,
143
+ children,
144
+ typeRegistry
145
+ });
146
+ if (hotFrame) {
147
+ return [hotFrame];
148
+ }
149
+ }
150
+ return children;
151
+ }
152
+ var notFound = {
153
+ children: [],
154
+ resolvedType: {
155
+ id: -1,
156
+ display: "[Type Not Found]",
157
+ flags: []
158
+ }
159
+ };
160
+ function getHotType({
161
+ id,
162
+ typeRegistry
163
+ }) {
164
+ function worker(id2, ancestorIds) {
165
+ if (id2 === -1) {
166
+ return notFound;
167
+ }
168
+ const resolvedType2 = typeRegistry[id2];
169
+ if (!resolvedType2) {
170
+ throw new Error(`Type ${id2} not found`);
171
+ }
172
+ const children = [];
173
+ if (ancestorIds.indexOf(id2) < 0) {
174
+ ancestorIds.push(id2);
175
+ const properties = Object.keys(resolvedType2);
176
+ for (const property of properties) {
177
+ switch (property) {
178
+ case "aliasTypeArguments":
179
+ case "intersectionTypes":
180
+ case "typeArguments":
181
+ case "unionTypes": {
182
+ const typeIds = resolvedType2[property];
183
+ if (!Array.isArray(typeIds)) {
184
+ throw new Error(`Expected array for ${property}`);
185
+ }
186
+ for (const typeId of typeIds) {
187
+ const child = worker(typeId, ancestorIds);
188
+ if (child) {
189
+ children.push(child);
190
+ }
191
+ }
192
+ continue;
193
+ }
194
+ case "aliasType":
195
+ case "conditionalCheckType":
196
+ case "conditionalExtendsType":
197
+ case "conditionalFalseType":
198
+ case "conditionalTrueType":
199
+ case "constraintType":
200
+ case "evolvingArrayElementType":
201
+ case "evolvingArrayFinalType":
202
+ case "indexedAccessIndexType":
203
+ case "indexedAccessObjectType":
204
+ case "instantiatedType":
205
+ case "keyofType":
206
+ case "reverseMappedConstraintType":
207
+ case "reverseMappedMappedType":
208
+ case "reverseMappedSourceType":
209
+ case "substitutionBaseType": {
210
+ const typeId = resolvedType2[property];
211
+ const child = worker(typeId, ancestorIds);
212
+ if (child) {
213
+ children.push(child);
214
+ }
215
+ break;
216
+ }
217
+ case "destructuringPattern":
218
+ case "display":
219
+ case "firstDeclaration":
220
+ case "flags":
221
+ case "id":
222
+ case "intrinsicName":
223
+ case "isTuple":
224
+ case "recursionId":
225
+ case "referenceLocation":
226
+ case "symbolName":
227
+ break;
228
+ default:
229
+ property;
230
+ throw new Error(`Unexpected property ${property}`);
231
+ }
232
+ }
233
+ ancestorIds.pop();
234
+ }
235
+ return {
236
+ resolvedType: resolvedType2,
237
+ children
238
+ };
239
+ }
240
+ return worker(id, []);
241
+ }
242
+ async function makeHotFrame({
243
+ span,
244
+ children,
245
+ typeRegistry
246
+ }) {
247
+ const { event, duration } = span;
248
+ const timeMs = Math.round(duration / 1e3);
249
+ switch (event.name) {
250
+ // case "findSourceFile":
251
+ // TODO (https://github.com/microsoft/typescript-analyze-trace/issues/2)
252
+ case "checkSourceFile": {
253
+ const filePath = event.args.path;
254
+ const normalizedPath = normalize(filePath);
255
+ return {
256
+ description: `Check file ${normalizedPath}`,
257
+ timeMs,
258
+ path: normalizedPath,
259
+ children
260
+ };
261
+ }
262
+ case "structuredTypeRelatedTo":
263
+ return {
264
+ description: `Compare types ${event.args.sourceId} and ${event.args.targetId}`,
265
+ timeMs,
266
+ children,
267
+ types: [
268
+ getHotType({
269
+ id: event.args.sourceId,
270
+ typeRegistry
271
+ }),
272
+ getHotType({
273
+ id: event.args.targetId,
274
+ typeRegistry
275
+ })
276
+ ]
277
+ };
278
+ case "getVariancesWorker":
279
+ return {
280
+ description: `Determine variance of type ${event.args.id}`,
281
+ timeMs,
282
+ children,
283
+ types: [getHotType({ id: event.args.id, typeRegistry })]
284
+ };
285
+ case "checkExpression":
286
+ case "checkVariableDeclaration": {
287
+ const filePath = event.args.path;
288
+ const path = filePath ? { path: normalize(filePath) } : {};
289
+ const frame = {
290
+ description: event.name,
291
+ timeMs,
292
+ ...path,
293
+ children: []
294
+ };
295
+ return frame;
296
+ }
297
+ default:
298
+ return void 0;
299
+ }
300
+ }
301
+
302
+ // src/node-module-paths.ts
303
+ import {
304
+ packageNameRegex
305
+ } from "@typeslayer/validate";
306
+ function getNodeModulePaths(traceJson) {
307
+ const nodeModulePaths2 = {};
308
+ traceJson.forEach((event) => {
309
+ if (event.name !== "findSourceFile") {
310
+ return;
311
+ }
312
+ const path = event.args.fileName;
313
+ if (path) {
314
+ while (true) {
315
+ const match = packageNameRegex.exec(path);
316
+ if (!match) {
317
+ break;
318
+ }
319
+ const packageName2 = match[1];
320
+ const packagePath2 = match.input.substring(
321
+ 0,
322
+ match.index + match[0].length
323
+ );
324
+ if (packageName2 in nodeModulePaths2) {
325
+ const paths = nodeModulePaths2[packageName2];
326
+ if (paths && paths.indexOf(packagePath2) < 0) {
327
+ paths.push(packagePath2);
328
+ }
329
+ } else {
330
+ nodeModulePaths2[packageName2] = [packagePath2];
331
+ }
332
+ }
333
+ }
334
+ });
335
+ return nodeModulePaths2;
336
+ }
337
+
338
+ // src/spans.ts
339
+ import {
340
+ eventPhase
341
+ } from "@typeslayer/validate";
342
+ function createSpans(traceFile) {
343
+ const unclosedStack = [];
344
+ const spans = [];
345
+ traceFile.forEach((event) => {
346
+ switch (event.ph) {
347
+ case eventPhase.begin:
348
+ unclosedStack.push(event);
349
+ return;
350
+ case eventPhase.end: {
351
+ const beginEvent = unclosedStack.pop();
352
+ if (!beginEvent) {
353
+ throw new Error("Unmatched end event");
354
+ }
355
+ spans.push({
356
+ event: beginEvent,
357
+ start: beginEvent.ts,
358
+ end: event.ts,
359
+ duration: event.ts - beginEvent.ts,
360
+ children: []
361
+ });
362
+ break;
363
+ }
364
+ case eventPhase.complete: {
365
+ const start = event.ts;
366
+ const duration = event.dur ?? 0;
367
+ spans.push({
368
+ event,
369
+ start,
370
+ end: start + duration,
371
+ duration,
372
+ children: []
373
+ });
374
+ break;
375
+ }
376
+ case eventPhase.instantGlobal:
377
+ case eventPhase.metadata:
378
+ return;
379
+ default:
380
+ event;
381
+ }
382
+ });
383
+ const parseResult2 = {
384
+ firstSpanStart: Math.min(...spans.map((span) => span.start)),
385
+ lastSpanEnd: Math.max(...spans.map((span) => span.end)),
386
+ spans,
387
+ unclosedStack
388
+ };
389
+ return parseResult2;
390
+ }
391
+ function createSpanTree(parseResult2, options) {
392
+ const { firstSpanStart, lastSpanEnd, spans, unclosedStack } = parseResult2;
393
+ for (let i = unclosedStack.length - 1; i >= 0; i--) {
394
+ const event = unclosedStack[i];
395
+ const start = event.ts;
396
+ const end = lastSpanEnd;
397
+ spans.push({
398
+ event,
399
+ start,
400
+ end,
401
+ duration: end - start,
402
+ children: []
403
+ });
404
+ }
405
+ spans.sort((a, b) => a.start - b.start);
406
+ const root = {
407
+ event: {
408
+ name: "root",
409
+ cat: "program"
410
+ },
411
+ start: firstSpanStart,
412
+ end: lastSpanEnd,
413
+ duration: lastSpanEnd - firstSpanStart,
414
+ children: []
415
+ };
416
+ const stack = [root];
417
+ for (const span of spans) {
418
+ let i = stack.length - 1;
419
+ for (; i > 0; i--) {
420
+ const curr = stack[i];
421
+ if (curr.end > span.start) {
422
+ stack.length = i + 1;
423
+ break;
424
+ }
425
+ }
426
+ const thresholdDuration = options.forceMillis * 1e3;
427
+ const isAboveThresholdDuration = span.duration >= thresholdDuration;
428
+ const parent = stack[i];
429
+ const parentDuration = parent.end - parent.start;
430
+ const isSignificantPortionOfParent = span.duration >= parentDuration * options.minSpanParentPercentage;
431
+ if (isAboveThresholdDuration || isSignificantPortionOfParent) {
432
+ parent.children.push(span);
433
+ stack.push(span);
434
+ }
435
+ }
436
+ return root;
437
+ }
438
+
439
+ // src/utils.ts
440
+ import { existsSync as existsSync2 } from "fs";
441
+ import { stat } from "fs/promises";
442
+ import {
443
+ event_checktypes__checkCrossProductUnion_DepthLimit as event_checktypes__checkCrossProductUnion_DepthLimit2,
444
+ event_checktypes__checkTypeRelatedTo_DepthLimit as event_checktypes__checkTypeRelatedTo_DepthLimit2,
445
+ event_checktypes__getTypeAtFlowNode_DepthLimit as event_checktypes__getTypeAtFlowNode_DepthLimit2,
446
+ event_checktypes__instantiateType_DepthLimit as event_checktypes__instantiateType_DepthLimit2,
447
+ event_checktypes__recursiveTypeRelatedTo_DepthLimit as event_checktypes__recursiveTypeRelatedTo_DepthLimit2,
448
+ event_checktypes__removeSubtypes_DepthLimit as event_checktypes__removeSubtypes_DepthLimit2,
449
+ event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit as event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit2,
450
+ event_checktypes__typeRelatedToDiscriminatedType_DepthLimit as event_checktypes__typeRelatedToDiscriminatedType_DepthLimit2,
451
+ resolvedType,
452
+ traceEvent
453
+ } from "@typeslayer/validate";
454
+ import { z } from "zod/v4";
455
+ var absolutePath = z.string().refine(
456
+ (path) => {
457
+ return path.startsWith("/") || path.startsWith("C:\\") || path.startsWith("D:\\");
458
+ },
459
+ {
460
+ message: "Path must be absolute"
461
+ }
462
+ );
463
+ var project = z.object({
464
+ configFilePath: absolutePath.optional(),
465
+ tracePath: absolutePath,
466
+ typesPath: absolutePath
467
+ });
468
+ var projectResult = z.object({
469
+ project,
470
+ stdout: z.string(),
471
+ stderr: z.string(),
472
+ exitCode: z.number().optional(),
473
+ signal: z.enum(["SIGINT", "SIGTERM"]).optional()
474
+ });
475
+ var hotType = z.object({
476
+ resolvedType,
477
+ get children() {
478
+ return z.array(hotType);
479
+ }
480
+ });
481
+ var hotSpot = z.object({
482
+ description: z.string(),
483
+ timeMs: z.number(),
484
+ get children() {
485
+ return z.array(hotSpot);
486
+ },
487
+ path: absolutePath.optional(),
488
+ types: z.array(hotType).optional(),
489
+ startLine: z.number().optional(),
490
+ startChar: z.number().optional(),
491
+ startOffset: z.number().optional(),
492
+ endLine: z.number().optional(),
493
+ endChar: z.number().optional(),
494
+ endOffset: z.number().optional()
495
+ });
496
+ var duplicatedPackageInstance = z.object({
497
+ path: absolutePath,
498
+ version: z.string()
499
+ });
500
+ var duplicatedPackage = z.object({
501
+ name: z.string(),
502
+ instances: z.array(duplicatedPackageInstance)
503
+ });
504
+ var rootSpan = z.object({
505
+ name: z.literal("root"),
506
+ cat: z.literal("program")
507
+ });
508
+ var eventSpan = z.object({
509
+ event: z.union([traceEvent, rootSpan]),
510
+ start: z.number(),
511
+ end: z.number(),
512
+ duration: z.number(),
513
+ get children() {
514
+ return z.array(eventSpan);
515
+ }
516
+ });
517
+ var microseconds = z.number();
518
+ var packageName = z.string();
519
+ var packagePath = z.string();
520
+ var nodeModulePaths = z.record(packageName, z.array(packagePath));
521
+ var parseResult = z.object({
522
+ firstSpanStart: z.number(),
523
+ lastSpanEnd: z.number(),
524
+ spans: z.array(eventSpan),
525
+ unclosedStack: z.array(traceEvent)
526
+ });
527
+ var analyzeTraceOptions = z.object({
528
+ /** Events of at least this duration (in milliseconds) will reported unconditionally */
529
+ forceMillis: z.number(),
530
+ /** Events of less than this duration (in milliseconds) will suppressed unconditionally */
531
+ skipMillis: z.number(),
532
+ /** Expand types when printing */
533
+ expandTypes: z.boolean(),
534
+ /** force showing spans that are some percentage of their parent, independent of parent time */
535
+ minSpanParentPercentage: z.number(),
536
+ /** the minimum number of emitted imports from a declaration file or bundle */
537
+ importExpressionThreshold: z.number()
538
+ });
539
+ var isFile = async (path) => {
540
+ return stat(path).then((stats) => stats.isFile()).catch((_) => false);
541
+ };
542
+ var throwIfNotDirectory = async (path) => {
543
+ if (!existsSync2(path) || !(await stat(path))?.isDirectory()) {
544
+ throw new Error(`${path} is not a directory`);
545
+ }
546
+ return path;
547
+ };
548
+ var analyzeTraceResult = z.object({
549
+ /** Events that were not closed */
550
+ unterminatedEvents: z.array(traceEvent),
551
+ /** Hot spots in the trace */
552
+ hotSpots: z.array(hotSpot),
553
+ /** Packages that are duplicated in the trace */
554
+ duplicatePackages: z.array(duplicatedPackage),
555
+ /** Paths to all node modules used in the trace */
556
+ nodeModulePaths,
557
+ /** Depth limit events grouped by their event name */
558
+ depthLimits: z.object({
559
+ checkCrossProductUnion_DepthLimit: z.array(
560
+ event_checktypes__checkCrossProductUnion_DepthLimit2
561
+ ),
562
+ checkTypeRelatedTo_DepthLimit: z.array(
563
+ event_checktypes__checkTypeRelatedTo_DepthLimit2
564
+ ),
565
+ getTypeAtFlowNode_DepthLimit: z.array(
566
+ event_checktypes__getTypeAtFlowNode_DepthLimit2
567
+ ),
568
+ instantiateType_DepthLimit: z.array(
569
+ event_checktypes__instantiateType_DepthLimit2
570
+ ),
571
+ recursiveTypeRelatedTo_DepthLimit: z.array(
572
+ event_checktypes__recursiveTypeRelatedTo_DepthLimit2
573
+ ),
574
+ removeSubtypes_DepthLimit: z.array(
575
+ event_checktypes__removeSubtypes_DepthLimit2
576
+ ),
577
+ traceUnionsOrIntersectionsTooLarge_DepthLimit: z.array(
578
+ event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit2
579
+ ),
580
+ typeRelatedToDiscriminatedType_DepthLimit: z.array(
581
+ event_checktypes__typeRelatedToDiscriminatedType_DepthLimit2
582
+ )
583
+ })
584
+ });
585
+
586
+ // src/analyze-trace.ts
587
+ function validateOptions(options) {
588
+ if (options.forceMillis < options.skipMillis) {
589
+ throw new Error("forceMillis cannot be less than skipMillis");
590
+ }
591
+ }
592
+ var validateTraceDir = async (traceDir) => {
593
+ await throwIfNotDirectory(traceDir);
594
+ const typesFilePath = join2(traceDir, TYPES_JSON_FILENAME);
595
+ if (!existsSync3(typesFilePath)) {
596
+ throw new Error(
597
+ `types.json must exist in ${traceDir}. first run --generateTrace`
598
+ );
599
+ }
600
+ const typesFileJson = JSON.parse(await readFile2(typesFilePath, "utf8"));
601
+ const typesFile = typesJsonSchema.parse(typesFileJson);
602
+ const traceFilePath = join2(traceDir, TRACE_JSON_FILENAME);
603
+ if (!existsSync3(traceFilePath)) {
604
+ throw new Error(
605
+ `trace.json must exist in ${traceDir}. first run --generateTrace`
606
+ );
607
+ }
608
+ const traceFileJson = JSON.parse(await readFile2(traceFilePath, "utf8"));
609
+ const traceFile = traceJsonSchema.parse(traceFileJson);
610
+ return {
611
+ traceFile,
612
+ typesFile
613
+ };
614
+ };
615
+ var defaultOptions = {
616
+ forceMillis: 500,
617
+ skipMillis: 100,
618
+ expandTypes: true,
619
+ minSpanParentPercentage: 0.6,
620
+ importExpressionThreshold: 10
621
+ };
622
+ var analyzeTrace = async ({
623
+ traceDir,
624
+ options = defaultOptions
625
+ }) => {
626
+ validateOptions(options);
627
+ const { traceFile, typesFile } = await validateTraceDir(traceDir);
628
+ const nodeModulePaths2 = getNodeModulePaths(traceFile);
629
+ const spans = createSpans(traceFile);
630
+ const hotPathsTree = createSpanTree(spans, options);
631
+ const result = {
632
+ nodeModulePaths: nodeModulePaths2,
633
+ unterminatedEvents: spans.unclosedStack.reverse(),
634
+ hotSpots: await getHotspots(hotPathsTree, typesFile, options),
635
+ duplicatePackages: await getDuplicateNodeModules(nodeModulePaths2),
636
+ depthLimits: createDepthLimits(traceFile)
637
+ };
638
+ await writeFile(
639
+ join2(traceDir, ANALYZE_TRACE_FILENAME),
640
+ JSON.stringify(result, null, 2)
641
+ );
642
+ return result;
643
+ };
644
+ export {
645
+ ANALYZE_TRACE_FILENAME,
646
+ absolutePath,
647
+ analyzeTrace,
648
+ analyzeTraceOptions,
649
+ analyzeTraceResult,
650
+ createDepthLimits,
651
+ defaultOptions,
652
+ duplicatedPackage,
653
+ duplicatedPackageInstance,
654
+ eventSpan,
655
+ hotSpot,
656
+ hotType,
657
+ isFile,
658
+ microseconds,
659
+ nodeModulePaths,
660
+ packageName,
661
+ packagePath,
662
+ parseResult,
663
+ project,
664
+ projectResult,
665
+ rootSpan,
666
+ throwIfNotDirectory,
667
+ validateOptions
668
+ };
669
+ //# sourceMappingURL=index.js.map