@typeslayer/analyze-trace 0.0.0 → 0.1.10

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 ADDED
@@ -0,0 +1,81 @@
1
+ # @typeslayer/analyze-trace
2
+
3
+ Analyze TypeScript compiler trace events to identify performance bottlenecks and compilation hot spots.
4
+
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
+
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
+
9
+ ## CLI Usage
10
+
11
+ ```bash
12
+ tsc --generateTrace ./trace-json-path
13
+ npx @typeslayer/analyze-trace trace-json-path
14
+ ```
15
+
16
+ ### Examples
17
+
18
+ ```bash
19
+ # Analyze a trace file
20
+ typeslayer-analyze-trace ./trace.json
21
+
22
+ # With custom output
23
+ typeslayer-analyze-trace ./dist/trace.json > analysis.json
24
+ ```
25
+
26
+ ## Programmatic Usage
27
+
28
+ ```ts
29
+ import { analyzeTrace } from '@typeslayer/analyze-trace';
30
+ import { readFileSync } from 'fs';
31
+
32
+ // Read and parse trace
33
+ const traceJson = JSON.parse(readFileSync('trace.json', 'utf-8'));
34
+
35
+ // Analyze
36
+ const result = analyzeTrace(traceJson);
37
+
38
+ console.log('Hot spots:', result.hotSpots);
39
+ console.log('Depth limits:', result.depthLimits);
40
+ console.log('Duplicate packages:', result.duplicatePackages);
41
+ ```
42
+
43
+ ## Analysis Output
44
+
45
+ The analyzer provides:
46
+
47
+ ### Hot Spot Detection
48
+
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
+
51
+ ### Duplicate Package Detection
52
+
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
+
55
+ ### Unterminated Events
56
+
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
+
59
+ ### Depth Limits (unique to `@typeslayer/analyze-trace`)
60
+
61
+ Type-level limits that were hit during the type checking, including:
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.` |
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.` |
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
+ | `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
+
74
+ ### Type Graph
75
+
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. 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
+ >
79
+ > This particular feature is only in the Rust version. If you'd like a wasm-build of it or something lemme know.
80
+
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.
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { statSync, writeFileSync } from "node:fs";
4
+ import { resolve } from "node:path";
5
+ import process, { exit } from "node:process";
6
+ import { ANALYZE_TRACE_FILENAME, analyzeTrace, defaultOptions } from "../dist/index.js";
7
+
8
+ const { argv } = process;
9
+
10
+ const traceDirArg = argv[2];
11
+
12
+ if (!traceDirArg) {
13
+ console.error("Gotta give a trace directory, brah.");
14
+ exit(1);
15
+ }
16
+
17
+ const traceDir = resolve(traceDirArg);
18
+
19
+ try {
20
+ const stat = statSync(traceDir);
21
+ if (!stat.isDirectory()) {
22
+ console.error(`Trace directory "${traceDir}" is not a directory.`);
23
+ exit(1);
24
+ }
25
+ } catch (err) {
26
+ if (err.code === "ENOENT") {
27
+ console.error(`Trace directory "${traceDir}" does not exist.`);
28
+ } else {
29
+ console.error(
30
+ `Error checking trace directory "${traceDir}": ${err.message}`,
31
+ );
32
+ }
33
+ exit(1);
34
+ }
35
+
36
+ console.log({ traceDir });
37
+
38
+ analyzeTrace({ traceDir, options: defaultOptions }).then((result) => {
39
+ const destination = resolve(traceDir, ANALYZE_TRACE_FILENAME);
40
+ writeFileSync(destination, JSON.stringify(result, null, 2), "utf-8");
41
+ console.log("Analysis result:", result);
42
+ });