@typeslayer/analyze-trace 0.1.31 â 0.1.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -21
- package/bin/typeslayer-analyze-trace.mjs +24 -20
- package/dist/browser.d.mts +18 -18
- package/dist/index.d.mts +27 -27
- package/dist/index.mjs +31 -31
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
- package/src/browser.ts +1 -4
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Analyze TypeScript compiler trace events to identify performance bottlenecks and compilation hot spots.
|
|
4
4
|
|
|
5
|
-
Initially, this started as a full rewrite of [@typescript/analyze-trace](https://github.com/microsoft/typescript-analyze-trace)
|
|
5
|
+
Initially, this started as a full rewrite of [@typescript/analyze-trace](https://github.com/microsoft/typescript-analyze-trace)\*. That rewrite was successful, and new features were added during the development of [TypeSlayer](https://github.com/dimitropoulos/typeslayer) (where it was rewritten a second time in Rust).
|
|
6
6
|
|
|
7
|
-
> \* <sub>why did it need a full rewrite?<br /><br />well.. it's been unmaintained for many years and also I <a href="https://github.com/dimitropoulos">dimitropoulos</a> wanted to learn every detail of how it works.
|
|
7
|
+
> \* <sub>why did it need a full rewrite?<br /><br />well.. it's been unmaintained for many years and also I <a href="https://github.com/dimitropoulos">dimitropoulos</a> wanted to learn every detail of how it works. academically speaking, rewrites are great for that. when I looked deeper, though I saw some exceedingly interesting things (like some of the instantaneous events for type limits) that the original tool completely ignores (<a href="https://github.com/microsoft/typescript-analyze-trace/issues/1">sometimes intentionally</a>), yet some are actually quite fundamental to the goal of TypeSlayer!<br /><br /> also the original was intended as a end-of-the-pipeline CLI tool (giving nice human readable format, but only experimental JSON support) and the rewrite is though of as a middle-of-the-pipeline tool (1st-class JSON support). </sub>
|
|
8
8
|
|
|
9
9
|
## CLI Usage
|
|
10
10
|
|
|
@@ -26,18 +26,18 @@ typeslayer-analyze-trace ./dist/trace.json > analysis.json
|
|
|
26
26
|
## Programmatic Usage
|
|
27
27
|
|
|
28
28
|
```ts
|
|
29
|
-
import { analyzeTrace } from
|
|
30
|
-
import { readFileSync } from
|
|
29
|
+
import { analyzeTrace } from "@typeslayer/analyze-trace";
|
|
30
|
+
import { readFileSync } from "fs";
|
|
31
31
|
|
|
32
32
|
// Read and parse trace
|
|
33
|
-
const traceJson = JSON.parse(readFileSync(
|
|
33
|
+
const traceJson = JSON.parse(readFileSync("trace.json", "utf-8"));
|
|
34
34
|
|
|
35
35
|
// Analyze
|
|
36
36
|
const result = analyzeTrace(traceJson);
|
|
37
37
|
|
|
38
|
-
console.log(
|
|
39
|
-
console.log(
|
|
40
|
-
console.log(
|
|
38
|
+
console.log("Hot spots:", result.hotSpots);
|
|
39
|
+
console.log("Depth limits:", result.depthLimits);
|
|
40
|
+
console.log("Duplicate packages:", result.duplicatePackages);
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
## Analysis Output
|
|
@@ -46,36 +46,36 @@ The analyzer provides:
|
|
|
46
46
|
|
|
47
47
|
### Hot Spot Detection
|
|
48
48
|
|
|
49
|
-
This is a sliding scale that looks at the events that consumed the most time during compilation.
|
|
49
|
+
This is a sliding scale that looks at the events that consumed the most time during compilation. It's not a given that because something is hot it's necessarily _bad_. But, the thinking is, if you see something that's much more intensive than something else, it's worth flagging. So. There you go.
|
|
50
50
|
|
|
51
51
|
### Duplicate Package Detection
|
|
52
52
|
|
|
53
|
-
Package versions appearing in multiple locations from the same package.
|
|
53
|
+
Package versions appearing in multiple locations from the same package. This is one of those things that people often have no idea is going on, but in reality most projects have this problem. Well. "problem" might be a strong word. Similar to [Hot Spot Detection](#hot-spot-detection), you'll have to use your judgement here to decide whether it's a big deal or not. That's largely going to depend on the size/scale/usage of the thing that's duplicated.
|
|
54
54
|
|
|
55
55
|
### Unterminated Events
|
|
56
56
|
|
|
57
|
-
In a perfect world, all events created by TypeScript's trace machinery should be terminated.
|
|
57
|
+
In a perfect world, all events created by TypeScript's trace machinery should be terminated. What's that mean? Think of it like a missing JSX closing tag. The thinking here is that if that ever happens, it's guaranteed to be a symptom of something else being wrong - so the tool flags it.
|
|
58
58
|
|
|
59
59
|
### Depth Limits (unique to `@typeslayer/analyze-trace`)
|
|
60
60
|
|
|
61
61
|
Type-level limits that were hit during the type checking, including:
|
|
62
62
|
|
|
63
|
-
| Depth Limit | Error Triggered
|
|
64
|
-
| ----------------------------------------------- |
|
|
65
|
-
| `checkCrossProductUnion_DepthLimit` | triggers `TS(2590) Expression produces a union type that is too complex to represent.`
|
|
66
|
-
| `checkTypeRelatedTo_DepthLimit` | triggers `TS(2859) Excessive complexity comparing types '{0}' and '{1}'.` or `TS(2321) Excessive stack depth comparing types '{0}' and '{1}'.`
|
|
67
|
-
| `getTypeAtFlowNode_DepthLimit` | triggers `TS(2563) The containing function or module body is too large for control flow analysis.`
|
|
68
|
-
| `instantiateType_DepthLimit` | triggers `TS(2589) Type instantiation is excessively deep and possibly infinite.`
|
|
63
|
+
| Depth Limit | Error Triggered |
|
|
64
|
+
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
65
|
+
| `checkCrossProductUnion_DepthLimit` | triggers `TS(2590) Expression produces a union type that is too complex to represent.` |
|
|
66
|
+
| `checkTypeRelatedTo_DepthLimit` | triggers `TS(2859) Excessive complexity comparing types '{0}' and '{1}'.` or `TS(2321) Excessive stack depth comparing types '{0}' and '{1}'.` |
|
|
67
|
+
| `getTypeAtFlowNode_DepthLimit` | triggers `TS(2563) The containing function or module body is too large for control flow analysis.` |
|
|
68
|
+
| `instantiateType_DepthLimit` | triggers `TS(2589) Type instantiation is excessively deep and possibly infinite.` |
|
|
69
69
|
| `recursiveTypeRelatedTo_DepthLimit` | This is not currently considered a hard error by the compiler and therefore does not report to the user (unless you're a [TypeSlayer](https://github.com/dimitropoulos/typeslayer) user ð). |
|
|
70
|
-
| `removeSubtypes_DepthLimit` | triggers `TS(2590) Expression produces a union type that is too complex to represent.`
|
|
70
|
+
| `removeSubtypes_DepthLimit` | triggers `TS(2590) Expression produces a union type that is too complex to represent.` |
|
|
71
71
|
| `traceUnionsOrIntersectionsTooLarge_DepthLimit` | This is not currently considered a hard error by the compiler and therefore does not report to the user (unless you're a [TypeSlayer](https://github.com/dimitropoulos/typeslayer) user ð). |
|
|
72
72
|
| `typeRelatedToDiscriminatedType_DepthLimit` | This is not currently considered a hard error by the compiler and therefore does not report to the user (unless you're a [TypeSlayer](https://github.com/dimitropoulos/typeslayer) user ð). |
|
|
73
73
|
|
|
74
74
|
### Type Graph
|
|
75
75
|
|
|
76
76
|
> _note_:
|
|
77
|
-
> As fate would have it, when [TypeSlayer](https://github.com/dimitropoulos/typeslayer) moved from Node.js to Rust to be a Tauri app, this entire package was _again_ rewritten in Rust.
|
|
77
|
+
> As fate would have it, when [TypeSlayer](https://github.com/dimitropoulos/typeslayer) moved from Node.js to Rust to be a Tauri app, this entire package was _again_ rewritten in Rust. Since this version was fully up-and-running first, and the original has some issues, I decided to just not delete this and publish it in case others stuck in the Node ecosystem (ðŠĶ) find it useful.
|
|
78
78
|
>
|
|
79
|
-
> This particular feature is only in the Rust version.
|
|
79
|
+
> This particular feature is only in the Rust version. If you'd like a wasm-build of it or something lemme know.
|
|
80
80
|
|
|
81
|
-
This is the thing that powers the [TypeSlayer](https://github.com/dimitropoulos/typeslayer) "Type Graph".
|
|
81
|
+
This is the thing that powers the [TypeSlayer](https://github.com/dimitropoulos/typeslayer) "Type Graph". It basically takes the `types.json` output and combines it with the information in the `trace.json` to create a list of relations (of various sorts) between all the types in your project. It also compiles stats for records like "biggest union" and "most commonly included in an intersection" and literally over a doze more like that.
|
|
@@ -3,38 +3,42 @@
|
|
|
3
3
|
import { statSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
5
|
import process, { exit } from "node:process";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
ANALYZE_TRACE_FILENAME,
|
|
8
|
+
analyzeTrace,
|
|
9
|
+
defaultOptions,
|
|
10
|
+
} from "../dist/index.mjs";
|
|
7
11
|
|
|
8
12
|
const { argv } = process;
|
|
9
13
|
|
|
10
14
|
const traceDirArg = argv[2];
|
|
11
15
|
|
|
12
16
|
if (!traceDirArg) {
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
console.error("Gotta give a trace directory, brah.");
|
|
18
|
+
exit(1);
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
const traceDir = resolve(traceDirArg);
|
|
18
22
|
|
|
19
23
|
try {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
const stat = statSync(traceDir);
|
|
25
|
+
if (!stat.isDirectory()) {
|
|
26
|
+
console.error(`Trace directory "${traceDir}" is not a directory.`);
|
|
27
|
+
exit(1);
|
|
28
|
+
}
|
|
25
29
|
} catch (err) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
if (err.code === "ENOENT") {
|
|
31
|
+
console.error(`Trace directory "${traceDir}" does not exist.`);
|
|
32
|
+
} else {
|
|
33
|
+
console.error(
|
|
34
|
+
`Error checking trace directory "${traceDir}": ${err.message}`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
exit(1);
|
|
34
38
|
}
|
|
35
39
|
|
|
36
|
-
analyzeTrace({ traceDir, options: defaultOptions }).then(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
analyzeTrace({ traceDir, options: defaultOptions }).then(result => {
|
|
41
|
+
const destination = resolve(traceDir, ANALYZE_TRACE_FILENAME);
|
|
42
|
+
writeFileSync(destination, JSON.stringify(result, null, 2), "utf-8");
|
|
43
|
+
console.log("Analysis result:", result);
|
|
40
44
|
});
|
package/dist/browser.d.mts
CHANGED
|
@@ -193,34 +193,34 @@ declare const hotSpot: z.ZodObject<{
|
|
|
193
193
|
start: z.ZodObject<{
|
|
194
194
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
195
195
|
character: z.ZodNumber;
|
|
196
|
-
}, z.core.$
|
|
196
|
+
}, z.core.$strict>;
|
|
197
197
|
end: z.ZodObject<{
|
|
198
198
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
199
199
|
character: z.ZodNumber;
|
|
200
|
-
}, z.core.$
|
|
201
|
-
}, z.core.$
|
|
200
|
+
}, z.core.$strict>;
|
|
201
|
+
}, z.core.$strict>>;
|
|
202
202
|
referenceLocation: z.ZodOptional<z.ZodObject<{
|
|
203
203
|
path: z.ZodString;
|
|
204
204
|
start: z.ZodObject<{
|
|
205
205
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
206
206
|
character: z.ZodNumber;
|
|
207
|
-
}, z.core.$
|
|
207
|
+
}, z.core.$strict>;
|
|
208
208
|
end: z.ZodObject<{
|
|
209
209
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
210
210
|
character: z.ZodNumber;
|
|
211
|
-
}, z.core.$
|
|
212
|
-
}, z.core.$
|
|
211
|
+
}, z.core.$strict>;
|
|
212
|
+
}, z.core.$strict>>;
|
|
213
213
|
destructuringPattern: z.ZodOptional<z.ZodObject<{
|
|
214
214
|
path: z.ZodString;
|
|
215
215
|
start: z.ZodObject<{
|
|
216
216
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
217
217
|
character: z.ZodNumber;
|
|
218
|
-
}, z.core.$
|
|
218
|
+
}, z.core.$strict>;
|
|
219
219
|
end: z.ZodObject<{
|
|
220
220
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
221
221
|
character: z.ZodNumber;
|
|
222
|
-
}, z.core.$
|
|
223
|
-
}, z.core.$
|
|
222
|
+
}, z.core.$strict>;
|
|
223
|
+
}, z.core.$strict>>;
|
|
224
224
|
}, z.core.$strict>;
|
|
225
225
|
children: z.ZodArray<z.ZodObject< /*elided*/any, z.core.$strip>>;
|
|
226
226
|
}, z.core.$strip>>>;
|
|
@@ -3039,34 +3039,34 @@ declare const analyzeTraceResult: z.ZodObject<{
|
|
|
3039
3039
|
start: z.ZodObject<{
|
|
3040
3040
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
3041
3041
|
character: z.ZodNumber;
|
|
3042
|
-
}, z.core.$
|
|
3042
|
+
}, z.core.$strict>;
|
|
3043
3043
|
end: z.ZodObject<{
|
|
3044
3044
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
3045
3045
|
character: z.ZodNumber;
|
|
3046
|
-
}, z.core.$
|
|
3047
|
-
}, z.core.$
|
|
3046
|
+
}, z.core.$strict>;
|
|
3047
|
+
}, z.core.$strict>>;
|
|
3048
3048
|
referenceLocation: z.ZodOptional<z.ZodObject<{
|
|
3049
3049
|
path: z.ZodString;
|
|
3050
3050
|
start: z.ZodObject<{
|
|
3051
3051
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
3052
3052
|
character: z.ZodNumber;
|
|
3053
|
-
}, z.core.$
|
|
3053
|
+
}, z.core.$strict>;
|
|
3054
3054
|
end: z.ZodObject<{
|
|
3055
3055
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
3056
3056
|
character: z.ZodNumber;
|
|
3057
|
-
}, z.core.$
|
|
3058
|
-
}, z.core.$
|
|
3057
|
+
}, z.core.$strict>;
|
|
3058
|
+
}, z.core.$strict>>;
|
|
3059
3059
|
destructuringPattern: z.ZodOptional<z.ZodObject<{
|
|
3060
3060
|
path: z.ZodString;
|
|
3061
3061
|
start: z.ZodObject<{
|
|
3062
3062
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
3063
3063
|
character: z.ZodNumber;
|
|
3064
|
-
}, z.core.$
|
|
3064
|
+
}, z.core.$strict>;
|
|
3065
3065
|
end: z.ZodObject<{
|
|
3066
3066
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
3067
3067
|
character: z.ZodNumber;
|
|
3068
|
-
}, z.core.$
|
|
3069
|
-
}, z.core.$
|
|
3068
|
+
}, z.core.$strict>;
|
|
3069
|
+
}, z.core.$strict>>;
|
|
3070
3070
|
}, z.core.$strict>;
|
|
3071
3071
|
children: z.ZodArray<z.ZodObject< /*elided*/any, z.core.$strip>>;
|
|
3072
3072
|
}, z.core.$strip>>>;
|
package/dist/index.d.mts
CHANGED
|
@@ -149,34 +149,34 @@ declare const hotType: z.ZodObject<{
|
|
|
149
149
|
start: z.ZodObject<{
|
|
150
150
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
151
151
|
character: z.ZodNumber;
|
|
152
|
-
}, z.core.$
|
|
152
|
+
}, z.core.$strict>;
|
|
153
153
|
end: z.ZodObject<{
|
|
154
154
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
155
155
|
character: z.ZodNumber;
|
|
156
|
-
}, z.core.$
|
|
157
|
-
}, z.core.$
|
|
156
|
+
}, z.core.$strict>;
|
|
157
|
+
}, z.core.$strict>>;
|
|
158
158
|
referenceLocation: z.ZodOptional<z.ZodObject<{
|
|
159
159
|
path: z.ZodString;
|
|
160
160
|
start: z.ZodObject<{
|
|
161
161
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
162
162
|
character: z.ZodNumber;
|
|
163
|
-
}, z.core.$
|
|
163
|
+
}, z.core.$strict>;
|
|
164
164
|
end: z.ZodObject<{
|
|
165
165
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
166
166
|
character: z.ZodNumber;
|
|
167
|
-
}, z.core.$
|
|
168
|
-
}, z.core.$
|
|
167
|
+
}, z.core.$strict>;
|
|
168
|
+
}, z.core.$strict>>;
|
|
169
169
|
destructuringPattern: z.ZodOptional<z.ZodObject<{
|
|
170
170
|
path: z.ZodString;
|
|
171
171
|
start: z.ZodObject<{
|
|
172
172
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
173
173
|
character: z.ZodNumber;
|
|
174
|
-
}, z.core.$
|
|
174
|
+
}, z.core.$strict>;
|
|
175
175
|
end: z.ZodObject<{
|
|
176
176
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
177
177
|
character: z.ZodNumber;
|
|
178
|
-
}, z.core.$
|
|
179
|
-
}, z.core.$
|
|
178
|
+
}, z.core.$strict>;
|
|
179
|
+
}, z.core.$strict>>;
|
|
180
180
|
}, z.core.$strict>;
|
|
181
181
|
children: z.ZodArray<z.ZodObject< /*elided*/any, z.core.$strip>>;
|
|
182
182
|
}, z.core.$strip>;
|
|
@@ -312,34 +312,34 @@ declare const hotSpot: z.ZodObject<{
|
|
|
312
312
|
start: z.ZodObject<{
|
|
313
313
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
314
314
|
character: z.ZodNumber;
|
|
315
|
-
}, z.core.$
|
|
315
|
+
}, z.core.$strict>;
|
|
316
316
|
end: z.ZodObject<{
|
|
317
317
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
318
318
|
character: z.ZodNumber;
|
|
319
|
-
}, z.core.$
|
|
320
|
-
}, z.core.$
|
|
319
|
+
}, z.core.$strict>;
|
|
320
|
+
}, z.core.$strict>>;
|
|
321
321
|
referenceLocation: z.ZodOptional<z.ZodObject<{
|
|
322
322
|
path: z.ZodString;
|
|
323
323
|
start: z.ZodObject<{
|
|
324
324
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
325
325
|
character: z.ZodNumber;
|
|
326
|
-
}, z.core.$
|
|
326
|
+
}, z.core.$strict>;
|
|
327
327
|
end: z.ZodObject<{
|
|
328
328
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
329
329
|
character: z.ZodNumber;
|
|
330
|
-
}, z.core.$
|
|
331
|
-
}, z.core.$
|
|
330
|
+
}, z.core.$strict>;
|
|
331
|
+
}, z.core.$strict>>;
|
|
332
332
|
destructuringPattern: z.ZodOptional<z.ZodObject<{
|
|
333
333
|
path: z.ZodString;
|
|
334
334
|
start: z.ZodObject<{
|
|
335
335
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
336
336
|
character: z.ZodNumber;
|
|
337
|
-
}, z.core.$
|
|
337
|
+
}, z.core.$strict>;
|
|
338
338
|
end: z.ZodObject<{
|
|
339
339
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
340
340
|
character: z.ZodNumber;
|
|
341
|
-
}, z.core.$
|
|
342
|
-
}, z.core.$
|
|
341
|
+
}, z.core.$strict>;
|
|
342
|
+
}, z.core.$strict>>;
|
|
343
343
|
}, z.core.$strict>;
|
|
344
344
|
children: z.ZodArray<z.ZodObject< /*elided*/any, z.core.$strip>>;
|
|
345
345
|
}, z.core.$strip>>>;
|
|
@@ -3162,34 +3162,34 @@ declare const analyzeTraceResult: z.ZodObject<{
|
|
|
3162
3162
|
start: z.ZodObject<{
|
|
3163
3163
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
3164
3164
|
character: z.ZodNumber;
|
|
3165
|
-
}, z.core.$
|
|
3165
|
+
}, z.core.$strict>;
|
|
3166
3166
|
end: z.ZodObject<{
|
|
3167
3167
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
3168
3168
|
character: z.ZodNumber;
|
|
3169
|
-
}, z.core.$
|
|
3170
|
-
}, z.core.$
|
|
3169
|
+
}, z.core.$strict>;
|
|
3170
|
+
}, z.core.$strict>>;
|
|
3171
3171
|
referenceLocation: z.ZodOptional<z.ZodObject<{
|
|
3172
3172
|
path: z.ZodString;
|
|
3173
3173
|
start: z.ZodObject<{
|
|
3174
3174
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
3175
3175
|
character: z.ZodNumber;
|
|
3176
|
-
}, z.core.$
|
|
3176
|
+
}, z.core.$strict>;
|
|
3177
3177
|
end: z.ZodObject<{
|
|
3178
3178
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
3179
3179
|
character: z.ZodNumber;
|
|
3180
|
-
}, z.core.$
|
|
3181
|
-
}, z.core.$
|
|
3180
|
+
}, z.core.$strict>;
|
|
3181
|
+
}, z.core.$strict>>;
|
|
3182
3182
|
destructuringPattern: z.ZodOptional<z.ZodObject<{
|
|
3183
3183
|
path: z.ZodString;
|
|
3184
3184
|
start: z.ZodObject<{
|
|
3185
3185
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
3186
3186
|
character: z.ZodNumber;
|
|
3187
|
-
}, z.core.$
|
|
3187
|
+
}, z.core.$strict>;
|
|
3188
3188
|
end: z.ZodObject<{
|
|
3189
3189
|
line: z.ZodUnion<[z.ZodNumber, z.ZodLiteral<-1>]>;
|
|
3190
3190
|
character: z.ZodNumber;
|
|
3191
|
-
}, z.core.$
|
|
3192
|
-
}, z.core.$
|
|
3191
|
+
}, z.core.$strict>;
|
|
3192
|
+
}, z.core.$strict>>;
|
|
3193
3193
|
}, z.core.$strict>;
|
|
3194
3194
|
children: z.ZodArray<z.ZodObject< /*elided*/any, z.core.$strip>>;
|
|
3195
3195
|
}, z.core.$strip>>>;
|
package/dist/index.mjs
CHANGED
|
@@ -26,8 +26,8 @@ const createDepthLimits = (traceFile) => {
|
|
|
26
26
|
|
|
27
27
|
//#endregion
|
|
28
28
|
//#region src/get-duplicate-node-modules.ts
|
|
29
|
-
async function getPackageVersion(packagePath
|
|
30
|
-
const packageJsonPath = join(packagePath
|
|
29
|
+
async function getPackageVersion(packagePath) {
|
|
30
|
+
const packageJsonPath = join(packagePath, "package.json");
|
|
31
31
|
console.log("packageJsonPath", packageJsonPath);
|
|
32
32
|
if (!existsSync(packageJsonPath)) {
|
|
33
33
|
console.warn(`Package.json not found at ${packageJsonPath}. This may not be a node module.`);
|
|
@@ -36,17 +36,17 @@ async function getPackageVersion(packagePath$1) {
|
|
|
36
36
|
const jsonString = await readFile(packageJsonPath, "utf-8");
|
|
37
37
|
return JSON.parse(jsonString).version;
|
|
38
38
|
}
|
|
39
|
-
const getDuplicateNodeModules = async (nodeModulePaths
|
|
39
|
+
const getDuplicateNodeModules = async (nodeModulePaths) => {
|
|
40
40
|
const duplicates = [];
|
|
41
|
-
for (const [packageName
|
|
41
|
+
for (const [packageName, packagePaths] of Object.entries(nodeModulePaths)) {
|
|
42
42
|
if (packagePaths.length < 2) continue;
|
|
43
43
|
const instances = [];
|
|
44
|
-
for (const packagePath
|
|
45
|
-
path: packagePath
|
|
46
|
-
version: await getPackageVersion(packagePath
|
|
44
|
+
for (const packagePath of packagePaths) instances.push({
|
|
45
|
+
path: packagePath,
|
|
46
|
+
version: await getPackageVersion(packagePath)
|
|
47
47
|
});
|
|
48
48
|
duplicates.push({
|
|
49
|
-
name: packageName
|
|
49
|
+
name: packageName,
|
|
50
50
|
instances
|
|
51
51
|
});
|
|
52
52
|
}
|
|
@@ -92,20 +92,20 @@ const notFound = {
|
|
|
92
92
|
}
|
|
93
93
|
};
|
|
94
94
|
function getHotType({ id, typeRegistry }) {
|
|
95
|
-
function worker(id
|
|
96
|
-
if (id
|
|
97
|
-
const resolvedType
|
|
98
|
-
if (!resolvedType
|
|
95
|
+
function worker(id, ancestorIds) {
|
|
96
|
+
if (id === -1) return notFound;
|
|
97
|
+
const resolvedType = typeRegistry[id];
|
|
98
|
+
if (!resolvedType) throw new Error(`Type ${id} not found`);
|
|
99
99
|
const children = [];
|
|
100
|
-
if (ancestorIds.indexOf(id
|
|
101
|
-
ancestorIds.push(id
|
|
102
|
-
const properties = Object.keys(resolvedType
|
|
100
|
+
if (ancestorIds.indexOf(id) < 0) {
|
|
101
|
+
ancestorIds.push(id);
|
|
102
|
+
const properties = Object.keys(resolvedType);
|
|
103
103
|
for (const property of properties) switch (property) {
|
|
104
104
|
case "aliasTypeArguments":
|
|
105
105
|
case "intersectionTypes":
|
|
106
106
|
case "typeArguments":
|
|
107
107
|
case "unionTypes": {
|
|
108
|
-
const typeIds = resolvedType
|
|
108
|
+
const typeIds = resolvedType[property];
|
|
109
109
|
if (!Array.isArray(typeIds)) throw new Error(`Expected array for ${property}`);
|
|
110
110
|
for (const typeId of typeIds) {
|
|
111
111
|
const child = worker(typeId, ancestorIds);
|
|
@@ -129,7 +129,7 @@ function getHotType({ id, typeRegistry }) {
|
|
|
129
129
|
case "reverseMappedMappedType":
|
|
130
130
|
case "reverseMappedSourceType":
|
|
131
131
|
case "substitutionBaseType": {
|
|
132
|
-
const typeId = resolvedType
|
|
132
|
+
const typeId = resolvedType[property];
|
|
133
133
|
const child = worker(typeId, ancestorIds);
|
|
134
134
|
if (child) children.push(child);
|
|
135
135
|
break;
|
|
@@ -149,7 +149,7 @@ function getHotType({ id, typeRegistry }) {
|
|
|
149
149
|
ancestorIds.pop();
|
|
150
150
|
}
|
|
151
151
|
return {
|
|
152
|
-
resolvedType
|
|
152
|
+
resolvedType,
|
|
153
153
|
children
|
|
154
154
|
};
|
|
155
155
|
}
|
|
@@ -215,22 +215,22 @@ async function makeHotFrame({ span, children, typeRegistry }) {
|
|
|
215
215
|
//#endregion
|
|
216
216
|
//#region src/node-module-paths.ts
|
|
217
217
|
function getNodeModulePaths(traceJson) {
|
|
218
|
-
const nodeModulePaths
|
|
218
|
+
const nodeModulePaths = {};
|
|
219
219
|
traceJson.forEach((event) => {
|
|
220
220
|
if (event.name !== "findSourceFile") return;
|
|
221
221
|
const path = event.args.fileName;
|
|
222
222
|
if (path) while (true) {
|
|
223
223
|
const match = packageNameRegex.exec(path);
|
|
224
224
|
if (!match) break;
|
|
225
|
-
const packageName
|
|
226
|
-
const packagePath
|
|
227
|
-
if (packageName
|
|
228
|
-
const paths = nodeModulePaths
|
|
229
|
-
if (paths && paths.indexOf(packagePath
|
|
230
|
-
} else nodeModulePaths
|
|
225
|
+
const packageName = match[1];
|
|
226
|
+
const packagePath = match.input.substring(0, match.index + match[0].length);
|
|
227
|
+
if (packageName in nodeModulePaths) {
|
|
228
|
+
const paths = nodeModulePaths[packageName];
|
|
229
|
+
if (paths && paths.indexOf(packagePath) < 0) paths.push(packagePath);
|
|
230
|
+
} else nodeModulePaths[packageName] = [packagePath];
|
|
231
231
|
}
|
|
232
232
|
});
|
|
233
|
-
return nodeModulePaths
|
|
233
|
+
return nodeModulePaths;
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
//#endregion
|
|
@@ -279,8 +279,8 @@ function createSpans(traceFile) {
|
|
|
279
279
|
unclosedStack
|
|
280
280
|
};
|
|
281
281
|
}
|
|
282
|
-
function createSpanTree(parseResult
|
|
283
|
-
const { firstSpanStart, lastSpanEnd, spans, unclosedStack } = parseResult
|
|
282
|
+
function createSpanTree(parseResult, options) {
|
|
283
|
+
const { firstSpanStart, lastSpanEnd, spans, unclosedStack } = parseResult;
|
|
284
284
|
for (let i = unclosedStack.length - 1; i >= 0; i--) {
|
|
285
285
|
const event = unclosedStack[i];
|
|
286
286
|
const start = event.ts;
|
|
@@ -456,14 +456,14 @@ const defaultOptions = {
|
|
|
456
456
|
const analyzeTrace = async ({ traceDir, options = defaultOptions }) => {
|
|
457
457
|
validateOptions(options);
|
|
458
458
|
const { traceFile, typesFile } = await validateTraceDir(traceDir);
|
|
459
|
-
const nodeModulePaths
|
|
459
|
+
const nodeModulePaths = getNodeModulePaths(traceFile);
|
|
460
460
|
const spans = createSpans(traceFile);
|
|
461
461
|
const hotPathsTree = createSpanTree(spans, options);
|
|
462
462
|
const result = {
|
|
463
|
-
nodeModulePaths
|
|
463
|
+
nodeModulePaths,
|
|
464
464
|
unterminatedEvents: spans.unclosedStack.reverse(),
|
|
465
465
|
hotSpots: await getHotspots(hotPathsTree, typesFile, options),
|
|
466
|
-
duplicatePackages: await getDuplicateNodeModules(nodeModulePaths
|
|
466
|
+
duplicatePackages: await getDuplicateNodeModules(nodeModulePaths),
|
|
467
467
|
depthLimits: createDepthLimits(traceFile)
|
|
468
468
|
};
|
|
469
469
|
await writeFile(join(traceDir, ANALYZE_TRACE_FILENAME), JSON.stringify(result, null, 2));
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["packagePath","duplicates: DuplicatedPackage[]","packageName","nodeModulePaths","instances: DuplicatedPackageInstance[]","children: HotSpot[]","id","resolvedType","children: HotType[]","nodeModulePaths: NodeModulePaths","packageName","packagePath","nodeModulePaths","unclosedStack: TraceEvent[]","spans: EventSpan[]","parseResult","root: EventSpan","thresholdDuration: Microseconds","defaultOptions: AnalyzeTraceOptions","nodeModulePaths","result: AnalyzeTraceResult"],"sources":["../src/constants.ts","../src/depth-limits.ts","../src/get-duplicate-node-modules.ts","../src/get-hotspots.ts","../src/node-module-paths.ts","../src/spans.ts","../src/utils.ts","../src/analyze-trace.ts"],"sourcesContent":["// you may need to import this directly via ESM, otherwise Vite will complain about externalized fs dependencies\nexport const ANALYZE_TRACE_FILENAME = \"analyze-trace.json\";\n","import {\n depthLimits,\n type EventChecktypes__CheckCrossProductUnion_DepthLimit,\n type EventChecktypes__CheckTypeRelatedTo_DepthLimit,\n type EventChecktypes__GetTypeAtFlowNode_DepthLimit,\n type EventChecktypes__InstantiateType_DepthLimit,\n type EventChecktypes__RecursiveTypeRelatedTo_DepthLimit,\n type EventChecktypes__RemoveSubtypes_DepthLimit,\n type EventChecktypes__TraceUnionsOrIntersectionsTooLarge_DepthLimit,\n type EventChecktypes__TypeRelatedToDiscriminatedType_DepthLimit,\n event_checktypes__checkCrossProductUnion_DepthLimit,\n event_checktypes__checkTypeRelatedTo_DepthLimit,\n event_checktypes__getTypeAtFlowNode_DepthLimit,\n event_checktypes__instantiateType_DepthLimit,\n event_checktypes__recursiveTypeRelatedTo_DepthLimit,\n event_checktypes__removeSubtypes_DepthLimit,\n event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit,\n event_checktypes__typeRelatedToDiscriminatedType_DepthLimit,\n type TraceJsonSchema,\n} from \"@typeslayer/validate\";\n\nexport type DepthLimitsRecord = {\n checkCrossProductUnion_DepthLimit: EventChecktypes__CheckCrossProductUnion_DepthLimit[];\n checkTypeRelatedTo_DepthLimit: EventChecktypes__CheckTypeRelatedTo_DepthLimit[];\n getTypeAtFlowNode_DepthLimit: EventChecktypes__GetTypeAtFlowNode_DepthLimit[];\n instantiateType_DepthLimit: EventChecktypes__InstantiateType_DepthLimit[];\n recursiveTypeRelatedTo_DepthLimit: EventChecktypes__RecursiveTypeRelatedTo_DepthLimit[];\n removeSubtypes_DepthLimit: EventChecktypes__RemoveSubtypes_DepthLimit[];\n traceUnionsOrIntersectionsTooLarge_DepthLimit: EventChecktypes__TraceUnionsOrIntersectionsTooLarge_DepthLimit[];\n typeRelatedToDiscriminatedType_DepthLimit: EventChecktypes__TypeRelatedToDiscriminatedType_DepthLimit[];\n};\n\nexport const createDepthLimits = (traceFile: TraceJsonSchema) => {\n const limitNamesSet = new Set(\n depthLimits.map(d => d.shape.name),\n ) as unknown as Set<string>;\n const limitEvents = traceFile.filter(event => limitNamesSet.has(event.name));\n\n return {\n checkCrossProductUnion_DepthLimit: (\n limitEvents.filter(\n event =>\n event_checktypes__checkCrossProductUnion_DepthLimit.safeParse(event)\n .success,\n ) as EventChecktypes__CheckCrossProductUnion_DepthLimit[]\n ).sort((a, b) => a.args.size - b.args.size),\n\n checkTypeRelatedTo_DepthLimit: (\n limitEvents.filter(\n event =>\n event_checktypes__checkTypeRelatedTo_DepthLimit.safeParse(event)\n .success,\n ) as EventChecktypes__CheckTypeRelatedTo_DepthLimit[]\n ).sort((a, b) => a.args.depth - b.args.depth),\n\n getTypeAtFlowNode_DepthLimit: (\n limitEvents.filter(\n event =>\n event_checktypes__getTypeAtFlowNode_DepthLimit.safeParse(event)\n .success,\n ) as EventChecktypes__GetTypeAtFlowNode_DepthLimit[]\n ).sort((a, b) => a.args.flowId - b.args.flowId),\n\n instantiateType_DepthLimit: (\n limitEvents.filter(\n event =>\n event_checktypes__instantiateType_DepthLimit.safeParse(event).success,\n ) as EventChecktypes__InstantiateType_DepthLimit[]\n ).sort((a, b) => a.args.instantiationDepth - b.args.instantiationDepth),\n\n recursiveTypeRelatedTo_DepthLimit: (\n limitEvents.filter(\n event =>\n event_checktypes__recursiveTypeRelatedTo_DepthLimit.safeParse(event)\n .success,\n ) as EventChecktypes__RecursiveTypeRelatedTo_DepthLimit[]\n ).sort((a, b) => a.args.depth - b.args.depth),\n\n removeSubtypes_DepthLimit: limitEvents.filter(\n event =>\n event_checktypes__removeSubtypes_DepthLimit.safeParse(event).success,\n ) as EventChecktypes__RemoveSubtypes_DepthLimit[],\n\n traceUnionsOrIntersectionsTooLarge_DepthLimit: (\n limitEvents.filter(\n event =>\n event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit.safeParse(\n event,\n ).success,\n ) as EventChecktypes__TraceUnionsOrIntersectionsTooLarge_DepthLimit[]\n ).sort(\n (a, b) =>\n a.args.sourceSize * a.args.targetSize -\n b.args.sourceSize * b.args.targetSize,\n ),\n\n typeRelatedToDiscriminatedType_DepthLimit: (\n limitEvents.filter(\n event =>\n event_checktypes__typeRelatedToDiscriminatedType_DepthLimit.safeParse(\n event,\n ).success,\n ) as EventChecktypes__TypeRelatedToDiscriminatedType_DepthLimit[]\n ).sort((a, b) => a.args.numCombinations - b.args.numCombinations),\n } satisfies DepthLimitsRecord;\n};\n","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type {\n DuplicatedPackage,\n DuplicatedPackageInstance,\n NodeModulePaths,\n} from \"./utils\";\n\nexport async function getPackageVersion(packagePath: string) {\n const packageJsonPath = join(packagePath, \"package.json\");\n console.log(\"packageJsonPath\", packageJsonPath);\n if (!existsSync(packageJsonPath)) {\n console.warn(\n `Package.json not found at ${packageJsonPath}. This may not be a node module.`,\n );\n return \"unknown\";\n }\n const jsonString = await readFile(packageJsonPath, \"utf-8\");\n const jsonObj = JSON.parse(jsonString);\n return jsonObj.version;\n}\n\nexport const getDuplicateNodeModules = async (\n nodeModulePaths: NodeModulePaths,\n) => {\n const duplicates: DuplicatedPackage[] = [];\n for (const [packageName, packagePaths] of Object.entries(nodeModulePaths)) {\n if (packagePaths.length < 2) {\n continue;\n }\n const instances: DuplicatedPackageInstance[] = [];\n for (const packagePath of packagePaths) {\n instances.push({\n path: packagePath,\n version: await getPackageVersion(packagePath),\n });\n }\n duplicates.push({\n name: packageName,\n instances,\n });\n }\n\n return duplicates;\n};\n","import { normalize } from \"node:path\";\nimport {\n createTypeRegistry,\n type ResolvedType,\n type TypeId,\n type TypeRegistry,\n type TypesJsonSchema,\n} from \"@typeslayer/validate\";\nimport type { AnalyzeTraceOptions, EventSpan, HotSpot, HotType } from \"./utils\";\n\nexport const getHotspots = async (\n hotPathsTree: EventSpan,\n typesFile: TypesJsonSchema,\n options: AnalyzeTraceOptions,\n): Promise<HotSpot[]> =>\n getHotspotsWorker({\n span: hotPathsTree,\n currentFile: undefined,\n typeRegistry: createTypeRegistry(typesFile),\n options,\n });\n\nasync function getHotspotsWorker({\n span,\n currentFile,\n typeRegistry,\n options,\n}: {\n span: EventSpan;\n currentFile: string | undefined;\n typeRegistry: TypeRegistry;\n options: AnalyzeTraceOptions;\n}): Promise<HotSpot[]> {\n if (span.event.cat === \"check\") {\n currentFile = span.event.args.path;\n }\n\n const children: HotSpot[] = [];\n if (span.children.length) {\n // Sort slow to fast\n const sortedChildren = span.children.sort(\n (a, b) => b.duration - a.duration,\n );\n for (const child of sortedChildren) {\n children.push(\n ...(await getHotspotsWorker({\n span: child,\n currentFile,\n typeRegistry,\n options,\n })),\n );\n }\n }\n\n if (span.event.name !== \"root\") {\n const hotFrame = await makeHotFrame({\n span,\n children,\n typeRegistry,\n });\n if (hotFrame) {\n return [hotFrame];\n }\n }\n\n return children;\n}\n\nconst notFound = {\n children: [],\n resolvedType: {\n id: -1,\n display: \"[Type Not Found]\",\n flags: [],\n },\n} satisfies HotType;\n\nfunction getHotType({\n id,\n typeRegistry,\n}: {\n id: number;\n typeRegistry: TypeRegistry;\n}): HotType {\n function worker(id: TypeId, ancestorIds: TypeId[]): HotType {\n if (id === -1) {\n return notFound;\n }\n\n const resolvedType = typeRegistry[id];\n\n if (!resolvedType) {\n throw new Error(`Type ${id} not found`);\n }\n\n const children: HotType[] = [];\n\n // If there's a cycle, suppress the children, but not the type itself\n if (ancestorIds.indexOf(id) < 0) {\n ancestorIds.push(id);\n\n const properties = Object.keys(resolvedType) as (keyof ResolvedType)[];\n for (const property of properties) {\n switch (property) {\n case \"aliasTypeArguments\":\n case \"intersectionTypes\":\n case \"typeArguments\":\n case \"unionTypes\": {\n const typeIds = resolvedType[property];\n if (!Array.isArray(typeIds)) {\n throw new Error(`Expected array for ${property}`);\n }\n for (const typeId of typeIds) {\n const child = worker(typeId, ancestorIds);\n if (child) {\n children.push(child);\n }\n }\n continue;\n }\n\n case \"aliasType\":\n case \"conditionalCheckType\":\n case \"conditionalExtendsType\":\n case \"conditionalFalseType\":\n case \"conditionalTrueType\":\n case \"constraintType\":\n case \"evolvingArrayElementType\":\n case \"evolvingArrayFinalType\":\n case \"indexedAccessIndexType\":\n case \"indexedAccessObjectType\":\n case \"instantiatedType\":\n case \"keyofType\":\n case \"reverseMappedConstraintType\":\n case \"reverseMappedMappedType\":\n case \"reverseMappedSourceType\":\n case \"substitutionBaseType\": {\n const typeId = resolvedType[property] as TypeId;\n const child = worker(typeId, ancestorIds);\n if (child) {\n children.push(child);\n }\n break;\n }\n\n case \"destructuringPattern\":\n case \"display\":\n case \"firstDeclaration\":\n case \"flags\":\n case \"id\":\n case \"intrinsicName\":\n case \"isTuple\":\n case \"recursionId\":\n case \"referenceLocation\":\n case \"symbolName\":\n break;\n\n default:\n property satisfies never;\n throw new Error(`Unexpected property ${property}`);\n }\n }\n ancestorIds.pop();\n }\n\n return {\n resolvedType,\n children,\n };\n }\n\n return worker(id, []);\n}\n\nasync function makeHotFrame({\n span,\n children,\n typeRegistry,\n}: {\n span: EventSpan;\n children: HotSpot[];\n typeRegistry: TypeRegistry;\n}): Promise<HotSpot | undefined> {\n const { event, duration, start, end } = span;\n\n switch (event.name) {\n // case \"findSourceFile\":\n // (https://github.com/microsoft/typescript-analyze-trace/issues/2)\n\n case \"checkSourceFile\": {\n const filePath = event.args.path;\n const normalizedPath = normalize(filePath);\n return {\n description: `Check file ${normalizedPath}`,\n start,\n end,\n duration,\n path: normalizedPath,\n\n children,\n };\n }\n\n case \"structuredTypeRelatedTo\":\n return {\n description: `Compare types ${event.args.sourceId} and ${event.args.targetId}`,\n start,\n end,\n duration,\n children,\n types: [\n getHotType({\n id: event.args.sourceId,\n typeRegistry,\n }),\n getHotType({\n id: event.args.targetId,\n typeRegistry,\n }),\n ],\n };\n\n case \"getVariancesWorker\":\n return {\n description: `Determine variance of type ${event.args.id}`,\n start,\n end,\n duration,\n children,\n types: [getHotType({ id: event.args.id, typeRegistry })],\n };\n\n case \"checkExpression\":\n case \"checkVariableDeclaration\": {\n const filePath = event.args.path;\n const path = filePath ? { path: normalize(filePath) } : {};\n const frame: HotSpot = {\n description: event.name,\n start,\n end,\n duration,\n ...path,\n children: [],\n };\n return frame;\n }\n\n default:\n return undefined;\n }\n}\n","import {\n packageNameRegex,\n type TraceEvent,\n type TraceJsonSchema,\n} from \"@typeslayer/validate\";\nimport type { NodeModulePaths } from \"./utils\";\n\nexport function getNodeModulePaths(\n traceJson: TraceJsonSchema,\n): NodeModulePaths {\n const nodeModulePaths: NodeModulePaths = {};\n traceJson.forEach((event: TraceEvent) => {\n if (event.name !== \"findSourceFile\") {\n return;\n }\n const path = event.args.fileName;\n if (path) {\n while (true) {\n const match = packageNameRegex.exec(path);\n if (!match) {\n break;\n }\n const packageName = match[1];\n\n const packagePath = match.input.substring(\n 0,\n match.index + match[0].length,\n );\n\n if (packageName in nodeModulePaths) {\n const paths = nodeModulePaths[packageName];\n if (paths && paths.indexOf(packagePath) < 0) {\n // Usually contains exactly one element\n paths.push(packagePath);\n }\n } else {\n nodeModulePaths[packageName] = [packagePath];\n }\n }\n }\n });\n\n return nodeModulePaths;\n}\n","import {\n eventPhase,\n type TraceEvent,\n type TraceJsonSchema,\n} from \"@typeslayer/validate\";\nimport type {\n AnalyzeTraceOptions,\n EventSpan,\n Microseconds,\n ParseResult,\n} from \"./utils\";\n\n/*\n * This function takes an array of trace events and converts them into spans.\n */\nexport function createSpans(traceFile: TraceJsonSchema): ParseResult {\n // Sorted in increasing order of start time (even when below timestamp resolution)\n const unclosedStack: TraceEvent[] = [];\n\n // Sorted in increasing order of end time, then increasing order of start time (even when below timestamp resolution)\n const spans: EventSpan[] = [];\n\n traceFile.forEach((event: TraceEvent) => {\n switch (event.ph) {\n case eventPhase.begin:\n unclosedStack.push(event);\n return;\n\n case eventPhase.end: {\n const beginEvent = unclosedStack.pop();\n if (!beginEvent) {\n throw new Error(\"Unmatched end event\");\n }\n spans.push({\n event: beginEvent,\n start: beginEvent.ts,\n end: event.ts,\n duration: event.ts - beginEvent.ts,\n children: [],\n });\n break;\n }\n\n case eventPhase.complete: {\n const start = event.ts;\n const duration = event.dur ?? 0;\n spans.push({\n event,\n start,\n end: start + duration,\n duration,\n children: [],\n });\n break;\n }\n\n case eventPhase.instantGlobal:\n case eventPhase.metadata:\n return;\n\n default:\n event satisfies never;\n }\n });\n\n const parseResult: ParseResult = {\n firstSpanStart: Math.min(...spans.map(span => span.start)),\n lastSpanEnd: Math.max(...spans.map(span => span.end)),\n spans,\n unclosedStack,\n };\n return parseResult;\n}\n\nexport function createSpanTree(\n parseResult: ParseResult,\n options: AnalyzeTraceOptions,\n): EventSpan {\n const { firstSpanStart, lastSpanEnd, spans, unclosedStack } = parseResult;\n\n // Add unclosed events to the spans\n for (let i = unclosedStack.length - 1; i >= 0; i--) {\n const event = unclosedStack[i];\n const start = event.ts;\n const end = lastSpanEnd;\n spans.push({\n event,\n start,\n end,\n duration: end - start,\n children: [],\n });\n }\n\n spans.sort((a, b) => a.start - b.start);\n\n const root: EventSpan = {\n event: {\n name: \"root\",\n cat: \"program\",\n },\n start: firstSpanStart,\n end: lastSpanEnd,\n duration: lastSpanEnd - firstSpanStart,\n children: [],\n };\n const stack = [root];\n\n for (const span of spans) {\n let i = stack.length - 1;\n for (; i > 0; i--) {\n // No need to check root at stack[0]\n const curr = stack[i];\n if (curr.end > span.start) {\n // Pop down to parent\n stack.length = i + 1;\n break;\n }\n }\n\n /** Microseconds */\n const thresholdDuration: Microseconds = options.forceMillis * 1000;\n const isAboveThresholdDuration = span.duration >= thresholdDuration;\n\n const parent = stack[i];\n const parentDuration = parent.end - parent.start;\n const isSignificantPortionOfParent =\n span.duration >= parentDuration * options.minSpanParentPercentage;\n\n if (isAboveThresholdDuration || isSignificantPortionOfParent) {\n parent.children.push(span);\n stack.push(span);\n }\n }\n\n return root;\n}\n","import { existsSync } from \"node:fs\";\nimport { stat } from \"node:fs/promises\";\nimport {\n event_checktypes__checkCrossProductUnion_DepthLimit,\n event_checktypes__checkTypeRelatedTo_DepthLimit,\n event_checktypes__getTypeAtFlowNode_DepthLimit,\n event_checktypes__instantiateType_DepthLimit,\n event_checktypes__recursiveTypeRelatedTo_DepthLimit,\n event_checktypes__removeSubtypes_DepthLimit,\n event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit,\n event_checktypes__typeRelatedToDiscriminatedType_DepthLimit,\n resolvedType,\n traceEvent,\n} from \"@typeslayer/validate\";\nimport { z } from \"zod/v4\";\n\nexport const absolutePath = z.string().refine(\n path => {\n return (\n path.startsWith(\"/\") || path.startsWith(\"C:\\\\\") || path.startsWith(\"D:\\\\\")\n );\n },\n {\n message: \"Path must be absolute\",\n },\n);\nexport type AbsolutePath = z.infer<typeof absolutePath>;\n\nexport const project = z.object({\n configFilePath: absolutePath.optional(),\n tracePath: absolutePath,\n typesPath: absolutePath,\n});\nexport type Project = z.infer<typeof project>;\n\nexport const projectResult = z.object({\n project: project,\n stdout: z.string(),\n stderr: z.string(),\n exitCode: z.number().optional(),\n signal: z.enum([\"SIGINT\", \"SIGTERM\"]).optional(),\n});\nexport type ProjectResult = z.infer<typeof projectResult>;\n\nexport const hotType = z.object({\n resolvedType: resolvedType,\n get children() {\n return z.array(hotType);\n },\n});\nexport type HotType = z.infer<typeof hotType>;\n\nexport const hotSpot = z.object({\n description: z.string(),\n duration: z.number(),\n start: z.number(),\n end: z.number(),\n get children() {\n return z.array(hotSpot);\n },\n\n path: absolutePath.optional(),\n types: z.array(hotType).optional(),\n startLine: z.number().optional(),\n startChar: z.number().optional(),\n startOffset: z.number().optional(),\n endLine: z.number().optional(),\n endChar: z.number().optional(),\n endOffset: z.number().optional(),\n});\nexport type HotSpot = z.infer<typeof hotSpot>;\n\nexport const duplicatedPackageInstance = z.object({\n path: absolutePath,\n version: z.string(),\n});\nexport type DuplicatedPackageInstance = z.infer<\n typeof duplicatedPackageInstance\n>;\n\nexport const duplicatedPackage = z.object({\n name: z.string(),\n instances: z.array(duplicatedPackageInstance),\n});\nexport type DuplicatedPackage = z.infer<typeof duplicatedPackage>;\n\nexport const rootSpan = z.object({\n name: z.literal(\"root\"),\n cat: z.literal(\"program\"),\n});\nexport type RootSpan = z.infer<typeof rootSpan>;\n\nexport const eventSpan = z.object({\n event: z.union([traceEvent, rootSpan]),\n start: z.number(),\n end: z.number(),\n duration: z.number(),\n get children() {\n return z.array(eventSpan);\n },\n});\nexport type EventSpan = z.infer<typeof eventSpan>;\n\nexport const microseconds = z.number();\nexport type Microseconds = z.infer<typeof microseconds>;\n\nexport const packageName = z.string();\n\nexport const packagePath = z.string();\n\nexport const nodeModulePaths = z.record(packageName, z.array(packagePath));\n/** This is a map where the key corresponds to an NPM package and the value is an array of all files in that package that were used */\nexport type NodeModulePaths = z.infer<typeof nodeModulePaths>;\n\nexport const parseResult = z.object({\n firstSpanStart: z.number(),\n lastSpanEnd: z.number(),\n spans: z.array(eventSpan),\n unclosedStack: z.array(traceEvent),\n});\nexport type ParseResult = z.infer<typeof parseResult>;\n\nexport const analyzeTraceOptions = z.object({\n /** Events of at least this duration (in milliseconds) will reported unconditionally */\n forceMillis: z.number(),\n /** Events of less than this duration (in milliseconds) will suppressed unconditionally */\n skipMillis: z.number(),\n /** Expand types when printing */\n expandTypes: z.boolean(),\n /** force showing spans that are some percentage of their parent, independent of parent time */\n minSpanParentPercentage: z.number(),\n /** the minimum number of emitted imports from a declaration file or bundle */\n importExpressionThreshold: z.number(),\n});\nexport type AnalyzeTraceOptions = z.infer<typeof analyzeTraceOptions>;\n\nexport const isFile = async (path: string) => {\n return stat(path)\n .then(stats => stats.isFile())\n .catch(_ => false);\n};\n\nexport const throwIfNotDirectory = async (path: string) => {\n if (!existsSync(path) || !(await stat(path))?.isDirectory()) {\n throw new Error(`${path} is not a directory`);\n }\n return path;\n};\n\nexport const analyzeTraceResult = z.object({\n /** Events that were not closed */\n unterminatedEvents: z.array(traceEvent),\n /** Hot spots in the trace */\n hotSpots: z.array(hotSpot),\n /** Packages that are duplicated in the trace */\n duplicatePackages: z.array(duplicatedPackage),\n /** Paths to all node modules used in the trace */\n nodeModulePaths: nodeModulePaths,\n /** Depth limit events grouped by their event name */\n depthLimits: z.object({\n checkCrossProductUnion_DepthLimit: z.array(\n event_checktypes__checkCrossProductUnion_DepthLimit,\n ),\n checkTypeRelatedTo_DepthLimit: z.array(\n event_checktypes__checkTypeRelatedTo_DepthLimit,\n ),\n getTypeAtFlowNode_DepthLimit: z.array(\n event_checktypes__getTypeAtFlowNode_DepthLimit,\n ),\n instantiateType_DepthLimit: z.array(\n event_checktypes__instantiateType_DepthLimit,\n ),\n recursiveTypeRelatedTo_DepthLimit: z.array(\n event_checktypes__recursiveTypeRelatedTo_DepthLimit,\n ),\n removeSubtypes_DepthLimit: z.array(\n event_checktypes__removeSubtypes_DepthLimit,\n ),\n traceUnionsOrIntersectionsTooLarge_DepthLimit: z.array(\n event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit,\n ),\n typeRelatedToDiscriminatedType_DepthLimit: z.array(\n event_checktypes__typeRelatedToDiscriminatedType_DepthLimit,\n ),\n }),\n});\nexport type AnalyzeTraceResult = z.infer<typeof analyzeTraceResult>;\n","import { existsSync } from \"node:fs\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport {\n TRACE_JSON_FILENAME,\n type TraceJsonSchema,\n TYPES_JSON_FILENAME,\n type TypesJsonSchema,\n traceJsonSchema,\n typesJsonSchema,\n} from \"@typeslayer/validate\";\nimport { ANALYZE_TRACE_FILENAME } from \"./constants\";\nimport { createDepthLimits } from \"./depth-limits\";\nimport { getDuplicateNodeModules } from \"./get-duplicate-node-modules\";\nimport { getHotspots } from \"./get-hotspots\";\nimport { getNodeModulePaths } from \"./node-module-paths\";\nimport { createSpans, createSpanTree } from \"./spans\";\nimport type { AnalyzeTraceResult } from \"./utils\";\nimport {\n type AbsolutePath,\n type AnalyzeTraceOptions,\n throwIfNotDirectory,\n} from \"./utils\";\n\nexport function validateOptions(options: AnalyzeTraceOptions) {\n if (options.forceMillis < options.skipMillis) {\n throw new Error(\"forceMillis cannot be less than skipMillis\");\n }\n}\n\nconst validateTraceDir = async (\n traceDir: AbsolutePath,\n): Promise<{\n traceFile: TraceJsonSchema;\n typesFile: TypesJsonSchema;\n}> => {\n await throwIfNotDirectory(traceDir);\n\n const typesFilePath = join(traceDir, TYPES_JSON_FILENAME);\n if (!existsSync(typesFilePath)) {\n throw new Error(\n `types.json must exist in ${traceDir}. first run --generateTrace`,\n );\n }\n const typesFileJson = JSON.parse(await readFile(typesFilePath, \"utf8\"));\n const typesFile = typesJsonSchema.parse(typesFileJson);\n\n const traceFilePath = join(traceDir, TRACE_JSON_FILENAME);\n if (!existsSync(traceFilePath)) {\n throw new Error(\n `trace.json must exist in ${traceDir}. first run --generateTrace`,\n );\n }\n const traceFileJson = JSON.parse(await readFile(traceFilePath, \"utf8\"));\n const traceFile = traceJsonSchema.parse(traceFileJson);\n\n return {\n traceFile,\n typesFile,\n };\n};\n\nexport const defaultOptions: AnalyzeTraceOptions = {\n forceMillis: 500,\n skipMillis: 100,\n expandTypes: true,\n minSpanParentPercentage: 0.6,\n importExpressionThreshold: 10,\n};\n\nexport const analyzeTrace = async ({\n traceDir,\n options = defaultOptions,\n}: {\n traceDir: AbsolutePath;\n options?: AnalyzeTraceOptions;\n}) => {\n validateOptions(options);\n const { traceFile, typesFile } = await validateTraceDir(traceDir);\n\n const nodeModulePaths = getNodeModulePaths(traceFile);\n\n const spans = createSpans(traceFile);\n const hotPathsTree = createSpanTree(spans, options);\n\n const result: AnalyzeTraceResult = {\n nodeModulePaths,\n unterminatedEvents: spans.unclosedStack.reverse(),\n hotSpots: await getHotspots(hotPathsTree, typesFile, options),\n duplicatePackages: await getDuplicateNodeModules(nodeModulePaths),\n depthLimits: createDepthLimits(traceFile),\n };\n await writeFile(\n join(traceDir, ANALYZE_TRACE_FILENAME),\n JSON.stringify(result, null, 2),\n );\n\n return result;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/constants.ts","../src/depth-limits.ts","../src/get-duplicate-node-modules.ts","../src/get-hotspots.ts","../src/node-module-paths.ts","../src/spans.ts","../src/utils.ts","../src/analyze-trace.ts"],"sourcesContent":["// you may need to import this directly via ESM, otherwise Vite will complain about externalized fs dependencies\nexport const ANALYZE_TRACE_FILENAME = \"analyze-trace.json\";\n","import {\n depthLimits,\n type EventChecktypes__CheckCrossProductUnion_DepthLimit,\n type EventChecktypes__CheckTypeRelatedTo_DepthLimit,\n type EventChecktypes__GetTypeAtFlowNode_DepthLimit,\n type EventChecktypes__InstantiateType_DepthLimit,\n type EventChecktypes__RecursiveTypeRelatedTo_DepthLimit,\n type EventChecktypes__RemoveSubtypes_DepthLimit,\n type EventChecktypes__TraceUnionsOrIntersectionsTooLarge_DepthLimit,\n type EventChecktypes__TypeRelatedToDiscriminatedType_DepthLimit,\n event_checktypes__checkCrossProductUnion_DepthLimit,\n event_checktypes__checkTypeRelatedTo_DepthLimit,\n event_checktypes__getTypeAtFlowNode_DepthLimit,\n event_checktypes__instantiateType_DepthLimit,\n event_checktypes__recursiveTypeRelatedTo_DepthLimit,\n event_checktypes__removeSubtypes_DepthLimit,\n event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit,\n event_checktypes__typeRelatedToDiscriminatedType_DepthLimit,\n type TraceJsonSchema,\n} from \"@typeslayer/validate\";\n\nexport type DepthLimitsRecord = {\n checkCrossProductUnion_DepthLimit: EventChecktypes__CheckCrossProductUnion_DepthLimit[];\n checkTypeRelatedTo_DepthLimit: EventChecktypes__CheckTypeRelatedTo_DepthLimit[];\n getTypeAtFlowNode_DepthLimit: EventChecktypes__GetTypeAtFlowNode_DepthLimit[];\n instantiateType_DepthLimit: EventChecktypes__InstantiateType_DepthLimit[];\n recursiveTypeRelatedTo_DepthLimit: EventChecktypes__RecursiveTypeRelatedTo_DepthLimit[];\n removeSubtypes_DepthLimit: EventChecktypes__RemoveSubtypes_DepthLimit[];\n traceUnionsOrIntersectionsTooLarge_DepthLimit: EventChecktypes__TraceUnionsOrIntersectionsTooLarge_DepthLimit[];\n typeRelatedToDiscriminatedType_DepthLimit: EventChecktypes__TypeRelatedToDiscriminatedType_DepthLimit[];\n};\n\nexport const createDepthLimits = (traceFile: TraceJsonSchema) => {\n const limitNamesSet = new Set(\n depthLimits.map(d => d.shape.name),\n ) as unknown as Set<string>;\n const limitEvents = traceFile.filter(event => limitNamesSet.has(event.name));\n\n return {\n checkCrossProductUnion_DepthLimit: (\n limitEvents.filter(\n event =>\n event_checktypes__checkCrossProductUnion_DepthLimit.safeParse(event)\n .success,\n ) as EventChecktypes__CheckCrossProductUnion_DepthLimit[]\n ).sort((a, b) => a.args.size - b.args.size),\n\n checkTypeRelatedTo_DepthLimit: (\n limitEvents.filter(\n event =>\n event_checktypes__checkTypeRelatedTo_DepthLimit.safeParse(event)\n .success,\n ) as EventChecktypes__CheckTypeRelatedTo_DepthLimit[]\n ).sort((a, b) => a.args.depth - b.args.depth),\n\n getTypeAtFlowNode_DepthLimit: (\n limitEvents.filter(\n event =>\n event_checktypes__getTypeAtFlowNode_DepthLimit.safeParse(event)\n .success,\n ) as EventChecktypes__GetTypeAtFlowNode_DepthLimit[]\n ).sort((a, b) => a.args.flowId - b.args.flowId),\n\n instantiateType_DepthLimit: (\n limitEvents.filter(\n event =>\n event_checktypes__instantiateType_DepthLimit.safeParse(event).success,\n ) as EventChecktypes__InstantiateType_DepthLimit[]\n ).sort((a, b) => a.args.instantiationDepth - b.args.instantiationDepth),\n\n recursiveTypeRelatedTo_DepthLimit: (\n limitEvents.filter(\n event =>\n event_checktypes__recursiveTypeRelatedTo_DepthLimit.safeParse(event)\n .success,\n ) as EventChecktypes__RecursiveTypeRelatedTo_DepthLimit[]\n ).sort((a, b) => a.args.depth - b.args.depth),\n\n removeSubtypes_DepthLimit: limitEvents.filter(\n event =>\n event_checktypes__removeSubtypes_DepthLimit.safeParse(event).success,\n ) as EventChecktypes__RemoveSubtypes_DepthLimit[],\n\n traceUnionsOrIntersectionsTooLarge_DepthLimit: (\n limitEvents.filter(\n event =>\n event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit.safeParse(\n event,\n ).success,\n ) as EventChecktypes__TraceUnionsOrIntersectionsTooLarge_DepthLimit[]\n ).sort(\n (a, b) =>\n a.args.sourceSize * a.args.targetSize -\n b.args.sourceSize * b.args.targetSize,\n ),\n\n typeRelatedToDiscriminatedType_DepthLimit: (\n limitEvents.filter(\n event =>\n event_checktypes__typeRelatedToDiscriminatedType_DepthLimit.safeParse(\n event,\n ).success,\n ) as EventChecktypes__TypeRelatedToDiscriminatedType_DepthLimit[]\n ).sort((a, b) => a.args.numCombinations - b.args.numCombinations),\n } satisfies DepthLimitsRecord;\n};\n","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type {\n DuplicatedPackage,\n DuplicatedPackageInstance,\n NodeModulePaths,\n} from \"./utils\";\n\nexport async function getPackageVersion(packagePath: string) {\n const packageJsonPath = join(packagePath, \"package.json\");\n console.log(\"packageJsonPath\", packageJsonPath);\n if (!existsSync(packageJsonPath)) {\n console.warn(\n `Package.json not found at ${packageJsonPath}. This may not be a node module.`,\n );\n return \"unknown\";\n }\n const jsonString = await readFile(packageJsonPath, \"utf-8\");\n const jsonObj = JSON.parse(jsonString);\n return jsonObj.version;\n}\n\nexport const getDuplicateNodeModules = async (\n nodeModulePaths: NodeModulePaths,\n) => {\n const duplicates: DuplicatedPackage[] = [];\n for (const [packageName, packagePaths] of Object.entries(nodeModulePaths)) {\n if (packagePaths.length < 2) {\n continue;\n }\n const instances: DuplicatedPackageInstance[] = [];\n for (const packagePath of packagePaths) {\n instances.push({\n path: packagePath,\n version: await getPackageVersion(packagePath),\n });\n }\n duplicates.push({\n name: packageName,\n instances,\n });\n }\n\n return duplicates;\n};\n","import { normalize } from \"node:path\";\nimport {\n createTypeRegistry,\n type ResolvedType,\n type TypeId,\n type TypeRegistry,\n type TypesJsonSchema,\n} from \"@typeslayer/validate\";\nimport type { AnalyzeTraceOptions, EventSpan, HotSpot, HotType } from \"./utils\";\n\nexport const getHotspots = async (\n hotPathsTree: EventSpan,\n typesFile: TypesJsonSchema,\n options: AnalyzeTraceOptions,\n): Promise<HotSpot[]> =>\n getHotspotsWorker({\n span: hotPathsTree,\n currentFile: undefined,\n typeRegistry: createTypeRegistry(typesFile),\n options,\n });\n\nasync function getHotspotsWorker({\n span,\n currentFile,\n typeRegistry,\n options,\n}: {\n span: EventSpan;\n currentFile: string | undefined;\n typeRegistry: TypeRegistry;\n options: AnalyzeTraceOptions;\n}): Promise<HotSpot[]> {\n if (span.event.cat === \"check\") {\n currentFile = span.event.args.path;\n }\n\n const children: HotSpot[] = [];\n if (span.children.length) {\n // Sort slow to fast\n const sortedChildren = span.children.sort(\n (a, b) => b.duration - a.duration,\n );\n for (const child of sortedChildren) {\n children.push(\n ...(await getHotspotsWorker({\n span: child,\n currentFile,\n typeRegistry,\n options,\n })),\n );\n }\n }\n\n if (span.event.name !== \"root\") {\n const hotFrame = await makeHotFrame({\n span,\n children,\n typeRegistry,\n });\n if (hotFrame) {\n return [hotFrame];\n }\n }\n\n return children;\n}\n\nconst notFound = {\n children: [],\n resolvedType: {\n id: -1,\n display: \"[Type Not Found]\",\n flags: [],\n },\n} satisfies HotType;\n\nfunction getHotType({\n id,\n typeRegistry,\n}: {\n id: number;\n typeRegistry: TypeRegistry;\n}): HotType {\n function worker(id: TypeId, ancestorIds: TypeId[]): HotType {\n if (id === -1) {\n return notFound;\n }\n\n const resolvedType = typeRegistry[id];\n\n if (!resolvedType) {\n throw new Error(`Type ${id} not found`);\n }\n\n const children: HotType[] = [];\n\n // If there's a cycle, suppress the children, but not the type itself\n if (ancestorIds.indexOf(id) < 0) {\n ancestorIds.push(id);\n\n const properties = Object.keys(resolvedType) as (keyof ResolvedType)[];\n for (const property of properties) {\n switch (property) {\n case \"aliasTypeArguments\":\n case \"intersectionTypes\":\n case \"typeArguments\":\n case \"unionTypes\": {\n const typeIds = resolvedType[property];\n if (!Array.isArray(typeIds)) {\n throw new Error(`Expected array for ${property}`);\n }\n for (const typeId of typeIds) {\n const child = worker(typeId, ancestorIds);\n if (child) {\n children.push(child);\n }\n }\n continue;\n }\n\n case \"aliasType\":\n case \"conditionalCheckType\":\n case \"conditionalExtendsType\":\n case \"conditionalFalseType\":\n case \"conditionalTrueType\":\n case \"constraintType\":\n case \"evolvingArrayElementType\":\n case \"evolvingArrayFinalType\":\n case \"indexedAccessIndexType\":\n case \"indexedAccessObjectType\":\n case \"instantiatedType\":\n case \"keyofType\":\n case \"reverseMappedConstraintType\":\n case \"reverseMappedMappedType\":\n case \"reverseMappedSourceType\":\n case \"substitutionBaseType\": {\n const typeId = resolvedType[property] as TypeId;\n const child = worker(typeId, ancestorIds);\n if (child) {\n children.push(child);\n }\n break;\n }\n\n case \"destructuringPattern\":\n case \"display\":\n case \"firstDeclaration\":\n case \"flags\":\n case \"id\":\n case \"intrinsicName\":\n case \"isTuple\":\n case \"recursionId\":\n case \"referenceLocation\":\n case \"symbolName\":\n break;\n\n default:\n property satisfies never;\n throw new Error(`Unexpected property ${property}`);\n }\n }\n ancestorIds.pop();\n }\n\n return {\n resolvedType,\n children,\n };\n }\n\n return worker(id, []);\n}\n\nasync function makeHotFrame({\n span,\n children,\n typeRegistry,\n}: {\n span: EventSpan;\n children: HotSpot[];\n typeRegistry: TypeRegistry;\n}): Promise<HotSpot | undefined> {\n const { event, duration, start, end } = span;\n\n switch (event.name) {\n // case \"findSourceFile\":\n // (https://github.com/microsoft/typescript-analyze-trace/issues/2)\n\n case \"checkSourceFile\": {\n const filePath = event.args.path;\n const normalizedPath = normalize(filePath);\n return {\n description: `Check file ${normalizedPath}`,\n start,\n end,\n duration,\n path: normalizedPath,\n\n children,\n };\n }\n\n case \"structuredTypeRelatedTo\":\n return {\n description: `Compare types ${event.args.sourceId} and ${event.args.targetId}`,\n start,\n end,\n duration,\n children,\n types: [\n getHotType({\n id: event.args.sourceId,\n typeRegistry,\n }),\n getHotType({\n id: event.args.targetId,\n typeRegistry,\n }),\n ],\n };\n\n case \"getVariancesWorker\":\n return {\n description: `Determine variance of type ${event.args.id}`,\n start,\n end,\n duration,\n children,\n types: [getHotType({ id: event.args.id, typeRegistry })],\n };\n\n case \"checkExpression\":\n case \"checkVariableDeclaration\": {\n const filePath = event.args.path;\n const path = filePath ? { path: normalize(filePath) } : {};\n const frame: HotSpot = {\n description: event.name,\n start,\n end,\n duration,\n ...path,\n children: [],\n };\n return frame;\n }\n\n default:\n return undefined;\n }\n}\n","import {\n packageNameRegex,\n type TraceEvent,\n type TraceJsonSchema,\n} from \"@typeslayer/validate\";\nimport type { NodeModulePaths } from \"./utils\";\n\nexport function getNodeModulePaths(\n traceJson: TraceJsonSchema,\n): NodeModulePaths {\n const nodeModulePaths: NodeModulePaths = {};\n traceJson.forEach((event: TraceEvent) => {\n if (event.name !== \"findSourceFile\") {\n return;\n }\n const path = event.args.fileName;\n if (path) {\n while (true) {\n const match = packageNameRegex.exec(path);\n if (!match) {\n break;\n }\n const packageName = match[1];\n\n const packagePath = match.input.substring(\n 0,\n match.index + match[0].length,\n );\n\n if (packageName in nodeModulePaths) {\n const paths = nodeModulePaths[packageName];\n if (paths && paths.indexOf(packagePath) < 0) {\n // Usually contains exactly one element\n paths.push(packagePath);\n }\n } else {\n nodeModulePaths[packageName] = [packagePath];\n }\n }\n }\n });\n\n return nodeModulePaths;\n}\n","import {\n eventPhase,\n type TraceEvent,\n type TraceJsonSchema,\n} from \"@typeslayer/validate\";\nimport type {\n AnalyzeTraceOptions,\n EventSpan,\n Microseconds,\n ParseResult,\n} from \"./utils\";\n\n/*\n * This function takes an array of trace events and converts them into spans.\n */\nexport function createSpans(traceFile: TraceJsonSchema): ParseResult {\n // Sorted in increasing order of start time (even when below timestamp resolution)\n const unclosedStack: TraceEvent[] = [];\n\n // Sorted in increasing order of end time, then increasing order of start time (even when below timestamp resolution)\n const spans: EventSpan[] = [];\n\n traceFile.forEach((event: TraceEvent) => {\n switch (event.ph) {\n case eventPhase.begin:\n unclosedStack.push(event);\n return;\n\n case eventPhase.end: {\n const beginEvent = unclosedStack.pop();\n if (!beginEvent) {\n throw new Error(\"Unmatched end event\");\n }\n spans.push({\n event: beginEvent,\n start: beginEvent.ts,\n end: event.ts,\n duration: event.ts - beginEvent.ts,\n children: [],\n });\n break;\n }\n\n case eventPhase.complete: {\n const start = event.ts;\n const duration = event.dur ?? 0;\n spans.push({\n event,\n start,\n end: start + duration,\n duration,\n children: [],\n });\n break;\n }\n\n case eventPhase.instantGlobal:\n case eventPhase.metadata:\n return;\n\n default:\n event satisfies never;\n }\n });\n\n const parseResult: ParseResult = {\n firstSpanStart: Math.min(...spans.map(span => span.start)),\n lastSpanEnd: Math.max(...spans.map(span => span.end)),\n spans,\n unclosedStack,\n };\n return parseResult;\n}\n\nexport function createSpanTree(\n parseResult: ParseResult,\n options: AnalyzeTraceOptions,\n): EventSpan {\n const { firstSpanStart, lastSpanEnd, spans, unclosedStack } = parseResult;\n\n // Add unclosed events to the spans\n for (let i = unclosedStack.length - 1; i >= 0; i--) {\n const event = unclosedStack[i];\n const start = event.ts;\n const end = lastSpanEnd;\n spans.push({\n event,\n start,\n end,\n duration: end - start,\n children: [],\n });\n }\n\n spans.sort((a, b) => a.start - b.start);\n\n const root: EventSpan = {\n event: {\n name: \"root\",\n cat: \"program\",\n },\n start: firstSpanStart,\n end: lastSpanEnd,\n duration: lastSpanEnd - firstSpanStart,\n children: [],\n };\n const stack = [root];\n\n for (const span of spans) {\n let i = stack.length - 1;\n for (; i > 0; i--) {\n // No need to check root at stack[0]\n const curr = stack[i];\n if (curr.end > span.start) {\n // Pop down to parent\n stack.length = i + 1;\n break;\n }\n }\n\n /** Microseconds */\n const thresholdDuration: Microseconds = options.forceMillis * 1000;\n const isAboveThresholdDuration = span.duration >= thresholdDuration;\n\n const parent = stack[i];\n const parentDuration = parent.end - parent.start;\n const isSignificantPortionOfParent =\n span.duration >= parentDuration * options.minSpanParentPercentage;\n\n if (isAboveThresholdDuration || isSignificantPortionOfParent) {\n parent.children.push(span);\n stack.push(span);\n }\n }\n\n return root;\n}\n","import { existsSync } from \"node:fs\";\nimport { stat } from \"node:fs/promises\";\nimport {\n event_checktypes__checkCrossProductUnion_DepthLimit,\n event_checktypes__checkTypeRelatedTo_DepthLimit,\n event_checktypes__getTypeAtFlowNode_DepthLimit,\n event_checktypes__instantiateType_DepthLimit,\n event_checktypes__recursiveTypeRelatedTo_DepthLimit,\n event_checktypes__removeSubtypes_DepthLimit,\n event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit,\n event_checktypes__typeRelatedToDiscriminatedType_DepthLimit,\n resolvedType,\n traceEvent,\n} from \"@typeslayer/validate\";\nimport { z } from \"zod/v4\";\n\nexport const absolutePath = z.string().refine(\n path => {\n return (\n path.startsWith(\"/\") || path.startsWith(\"C:\\\\\") || path.startsWith(\"D:\\\\\")\n );\n },\n {\n message: \"Path must be absolute\",\n },\n);\nexport type AbsolutePath = z.infer<typeof absolutePath>;\n\nexport const project = z.object({\n configFilePath: absolutePath.optional(),\n tracePath: absolutePath,\n typesPath: absolutePath,\n});\nexport type Project = z.infer<typeof project>;\n\nexport const projectResult = z.object({\n project: project,\n stdout: z.string(),\n stderr: z.string(),\n exitCode: z.number().optional(),\n signal: z.enum([\"SIGINT\", \"SIGTERM\"]).optional(),\n});\nexport type ProjectResult = z.infer<typeof projectResult>;\n\nexport const hotType = z.object({\n resolvedType: resolvedType,\n get children() {\n return z.array(hotType);\n },\n});\nexport type HotType = z.infer<typeof hotType>;\n\nexport const hotSpot = z.object({\n description: z.string(),\n duration: z.number(),\n start: z.number(),\n end: z.number(),\n get children() {\n return z.array(hotSpot);\n },\n\n path: absolutePath.optional(),\n types: z.array(hotType).optional(),\n startLine: z.number().optional(),\n startChar: z.number().optional(),\n startOffset: z.number().optional(),\n endLine: z.number().optional(),\n endChar: z.number().optional(),\n endOffset: z.number().optional(),\n});\nexport type HotSpot = z.infer<typeof hotSpot>;\n\nexport const duplicatedPackageInstance = z.object({\n path: absolutePath,\n version: z.string(),\n});\nexport type DuplicatedPackageInstance = z.infer<\n typeof duplicatedPackageInstance\n>;\n\nexport const duplicatedPackage = z.object({\n name: z.string(),\n instances: z.array(duplicatedPackageInstance),\n});\nexport type DuplicatedPackage = z.infer<typeof duplicatedPackage>;\n\nexport const rootSpan = z.object({\n name: z.literal(\"root\"),\n cat: z.literal(\"program\"),\n});\nexport type RootSpan = z.infer<typeof rootSpan>;\n\nexport const eventSpan = z.object({\n event: z.union([traceEvent, rootSpan]),\n start: z.number(),\n end: z.number(),\n duration: z.number(),\n get children() {\n return z.array(eventSpan);\n },\n});\nexport type EventSpan = z.infer<typeof eventSpan>;\n\nexport const microseconds = z.number();\nexport type Microseconds = z.infer<typeof microseconds>;\n\nexport const packageName = z.string();\n\nexport const packagePath = z.string();\n\nexport const nodeModulePaths = z.record(packageName, z.array(packagePath));\n/** This is a map where the key corresponds to an NPM package and the value is an array of all files in that package that were used */\nexport type NodeModulePaths = z.infer<typeof nodeModulePaths>;\n\nexport const parseResult = z.object({\n firstSpanStart: z.number(),\n lastSpanEnd: z.number(),\n spans: z.array(eventSpan),\n unclosedStack: z.array(traceEvent),\n});\nexport type ParseResult = z.infer<typeof parseResult>;\n\nexport const analyzeTraceOptions = z.object({\n /** Events of at least this duration (in milliseconds) will reported unconditionally */\n forceMillis: z.number(),\n /** Events of less than this duration (in milliseconds) will suppressed unconditionally */\n skipMillis: z.number(),\n /** Expand types when printing */\n expandTypes: z.boolean(),\n /** force showing spans that are some percentage of their parent, independent of parent time */\n minSpanParentPercentage: z.number(),\n /** the minimum number of emitted imports from a declaration file or bundle */\n importExpressionThreshold: z.number(),\n});\nexport type AnalyzeTraceOptions = z.infer<typeof analyzeTraceOptions>;\n\nexport const isFile = async (path: string) => {\n return stat(path)\n .then(stats => stats.isFile())\n .catch(_ => false);\n};\n\nexport const throwIfNotDirectory = async (path: string) => {\n if (!existsSync(path) || !(await stat(path))?.isDirectory()) {\n throw new Error(`${path} is not a directory`);\n }\n return path;\n};\n\nexport const analyzeTraceResult = z.object({\n /** Events that were not closed */\n unterminatedEvents: z.array(traceEvent),\n /** Hot spots in the trace */\n hotSpots: z.array(hotSpot),\n /** Packages that are duplicated in the trace */\n duplicatePackages: z.array(duplicatedPackage),\n /** Paths to all node modules used in the trace */\n nodeModulePaths: nodeModulePaths,\n /** Depth limit events grouped by their event name */\n depthLimits: z.object({\n checkCrossProductUnion_DepthLimit: z.array(\n event_checktypes__checkCrossProductUnion_DepthLimit,\n ),\n checkTypeRelatedTo_DepthLimit: z.array(\n event_checktypes__checkTypeRelatedTo_DepthLimit,\n ),\n getTypeAtFlowNode_DepthLimit: z.array(\n event_checktypes__getTypeAtFlowNode_DepthLimit,\n ),\n instantiateType_DepthLimit: z.array(\n event_checktypes__instantiateType_DepthLimit,\n ),\n recursiveTypeRelatedTo_DepthLimit: z.array(\n event_checktypes__recursiveTypeRelatedTo_DepthLimit,\n ),\n removeSubtypes_DepthLimit: z.array(\n event_checktypes__removeSubtypes_DepthLimit,\n ),\n traceUnionsOrIntersectionsTooLarge_DepthLimit: z.array(\n event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit,\n ),\n typeRelatedToDiscriminatedType_DepthLimit: z.array(\n event_checktypes__typeRelatedToDiscriminatedType_DepthLimit,\n ),\n }),\n});\nexport type AnalyzeTraceResult = z.infer<typeof analyzeTraceResult>;\n","import { existsSync } from \"node:fs\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport {\n TRACE_JSON_FILENAME,\n type TraceJsonSchema,\n TYPES_JSON_FILENAME,\n type TypesJsonSchema,\n traceJsonSchema,\n typesJsonSchema,\n} from \"@typeslayer/validate\";\nimport { ANALYZE_TRACE_FILENAME } from \"./constants\";\nimport { createDepthLimits } from \"./depth-limits\";\nimport { getDuplicateNodeModules } from \"./get-duplicate-node-modules\";\nimport { getHotspots } from \"./get-hotspots\";\nimport { getNodeModulePaths } from \"./node-module-paths\";\nimport { createSpans, createSpanTree } from \"./spans\";\nimport type { AnalyzeTraceResult } from \"./utils\";\nimport {\n type AbsolutePath,\n type AnalyzeTraceOptions,\n throwIfNotDirectory,\n} from \"./utils\";\n\nexport function validateOptions(options: AnalyzeTraceOptions) {\n if (options.forceMillis < options.skipMillis) {\n throw new Error(\"forceMillis cannot be less than skipMillis\");\n }\n}\n\nconst validateTraceDir = async (\n traceDir: AbsolutePath,\n): Promise<{\n traceFile: TraceJsonSchema;\n typesFile: TypesJsonSchema;\n}> => {\n await throwIfNotDirectory(traceDir);\n\n const typesFilePath = join(traceDir, TYPES_JSON_FILENAME);\n if (!existsSync(typesFilePath)) {\n throw new Error(\n `types.json must exist in ${traceDir}. first run --generateTrace`,\n );\n }\n const typesFileJson = JSON.parse(await readFile(typesFilePath, \"utf8\"));\n const typesFile = typesJsonSchema.parse(typesFileJson);\n\n const traceFilePath = join(traceDir, TRACE_JSON_FILENAME);\n if (!existsSync(traceFilePath)) {\n throw new Error(\n `trace.json must exist in ${traceDir}. first run --generateTrace`,\n );\n }\n const traceFileJson = JSON.parse(await readFile(traceFilePath, \"utf8\"));\n const traceFile = traceJsonSchema.parse(traceFileJson);\n\n return {\n traceFile,\n typesFile,\n };\n};\n\nexport const defaultOptions: AnalyzeTraceOptions = {\n forceMillis: 500,\n skipMillis: 100,\n expandTypes: true,\n minSpanParentPercentage: 0.6,\n importExpressionThreshold: 10,\n};\n\nexport const analyzeTrace = async ({\n traceDir,\n options = defaultOptions,\n}: {\n traceDir: AbsolutePath;\n options?: AnalyzeTraceOptions;\n}) => {\n validateOptions(options);\n const { traceFile, typesFile } = await validateTraceDir(traceDir);\n\n const nodeModulePaths = getNodeModulePaths(traceFile);\n\n const spans = createSpans(traceFile);\n const hotPathsTree = createSpanTree(spans, options);\n\n const result: AnalyzeTraceResult = {\n nodeModulePaths,\n unterminatedEvents: spans.unclosedStack.reverse(),\n hotSpots: await getHotspots(hotPathsTree, typesFile, options),\n duplicatePackages: await getDuplicateNodeModules(nodeModulePaths),\n depthLimits: createDepthLimits(traceFile),\n };\n await writeFile(\n join(traceDir, ANALYZE_TRACE_FILENAME),\n JSON.stringify(result, null, 2),\n );\n\n return result;\n};\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typeslayer/analyze-trace",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.32",
|
|
4
4
|
"description": "Analyze TypeScript compiler trace events to identify performance bottlenecks",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -34,15 +34,15 @@
|
|
|
34
34
|
"typeslayer-analyze-trace": "./bin/typeslayer-analyze-trace.mjs"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@mui/icons-material": "7.3.
|
|
38
|
-
"@mui/material": "7.3.
|
|
39
|
-
"zod": "4.
|
|
40
|
-
"@typeslayer/validate": "0.1.
|
|
37
|
+
"@mui/icons-material": "7.3.8",
|
|
38
|
+
"@mui/material": "7.3.8",
|
|
39
|
+
"zod": "4.3.6",
|
|
40
|
+
"@typeslayer/validate": "0.1.32"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
44
|
-
"@types/node": "25.0
|
|
45
|
-
"tsdown": "0.
|
|
44
|
+
"@types/node": "25.3.0",
|
|
45
|
+
"tsdown": "0.20.3",
|
|
46
46
|
"typescript": "5.9.3"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
package/src/browser.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
// Browser-safe exports - only types and schemas, no Node.js APIs
|
|
2
|
-
export type {
|
|
3
|
-
TraceJsonSchema,
|
|
4
|
-
TypesJsonSchema,
|
|
5
|
-
} from "@typeslayer/validate";
|
|
2
|
+
export type { TraceJsonSchema, TypesJsonSchema } from "@typeslayer/validate";
|
|
6
3
|
export { ANALYZE_TRACE_FILENAME } from "./constants";
|
|
7
4
|
export type { DepthLimitsRecord } from "./depth-limits";
|
|
8
5
|
export * from "./info";
|