@typeslayer/analyze-trace 0.1.13 → 0.1.15

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.mjs ADDED
@@ -0,0 +1,466 @@
1
+ import { existsSync } from "node:fs";
2
+ import { readFile, stat, writeFile } from "node:fs/promises";
3
+ import { join, normalize } from "node:path";
4
+ import { TRACE_JSON_FILENAME, TYPES_JSON_FILENAME, createTypeRegistry, depthLimits, eventPhase, event_checktypes__checkCrossProductUnion_DepthLimit, event_checktypes__checkTypeRelatedTo_DepthLimit, event_checktypes__getTypeAtFlowNode_DepthLimit, event_checktypes__instantiateType_DepthLimit, event_checktypes__recursiveTypeRelatedTo_DepthLimit, event_checktypes__removeSubtypes_DepthLimit, event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit, event_checktypes__typeRelatedToDiscriminatedType_DepthLimit, packageNameRegex, resolvedType, traceEvent, traceJsonSchema, typesJsonSchema } from "@typeslayer/validate";
5
+ import { z } from "zod/v4";
6
+
7
+ //#region src/constants.ts
8
+ const ANALYZE_TRACE_FILENAME = "analyze-trace.json";
9
+
10
+ //#endregion
11
+ //#region src/depth-limits.ts
12
+ const createDepthLimits = (traceFile) => {
13
+ const limitNamesSet = new Set(depthLimits.map((d) => d.shape.name));
14
+ const limitEvents = traceFile.filter((event) => limitNamesSet.has(event.name));
15
+ return {
16
+ checkCrossProductUnion_DepthLimit: limitEvents.filter((event) => event_checktypes__checkCrossProductUnion_DepthLimit.safeParse(event).success).sort((a, b) => a.args.size - b.args.size),
17
+ checkTypeRelatedTo_DepthLimit: limitEvents.filter((event) => event_checktypes__checkTypeRelatedTo_DepthLimit.safeParse(event).success).sort((a, b) => a.args.depth - b.args.depth),
18
+ getTypeAtFlowNode_DepthLimit: limitEvents.filter((event) => event_checktypes__getTypeAtFlowNode_DepthLimit.safeParse(event).success).sort((a, b) => a.args.flowId - b.args.flowId),
19
+ instantiateType_DepthLimit: limitEvents.filter((event) => event_checktypes__instantiateType_DepthLimit.safeParse(event).success).sort((a, b) => a.args.instantiationDepth - b.args.instantiationDepth),
20
+ recursiveTypeRelatedTo_DepthLimit: limitEvents.filter((event) => event_checktypes__recursiveTypeRelatedTo_DepthLimit.safeParse(event).success).sort((a, b) => a.args.depth - b.args.depth),
21
+ removeSubtypes_DepthLimit: limitEvents.filter((event) => event_checktypes__removeSubtypes_DepthLimit.safeParse(event).success),
22
+ traceUnionsOrIntersectionsTooLarge_DepthLimit: limitEvents.filter((event) => event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit.safeParse(event).success).sort((a, b) => a.args.sourceSize * a.args.targetSize - b.args.sourceSize * b.args.targetSize),
23
+ typeRelatedToDiscriminatedType_DepthLimit: limitEvents.filter((event) => event_checktypes__typeRelatedToDiscriminatedType_DepthLimit.safeParse(event).success).sort((a, b) => a.args.numCombinations - b.args.numCombinations)
24
+ };
25
+ };
26
+
27
+ //#endregion
28
+ //#region src/get-duplicate-node-modules.ts
29
+ async function getPackageVersion(packagePath$1) {
30
+ const packageJsonPath = join(packagePath$1, "package.json");
31
+ console.log("packageJsonPath", packageJsonPath);
32
+ if (!existsSync(packageJsonPath)) {
33
+ console.warn(`Package.json not found at ${packageJsonPath}. This may not be a node module.`);
34
+ return "unknown";
35
+ }
36
+ const jsonString = await readFile(packageJsonPath, "utf-8");
37
+ return JSON.parse(jsonString).version;
38
+ }
39
+ const getDuplicateNodeModules = async (nodeModulePaths$1) => {
40
+ const duplicates = [];
41
+ for (const [packageName$1, packagePaths] of Object.entries(nodeModulePaths$1)) {
42
+ if (packagePaths.length < 2) continue;
43
+ const instances = [];
44
+ for (const packagePath$1 of packagePaths) instances.push({
45
+ path: packagePath$1,
46
+ version: await getPackageVersion(packagePath$1)
47
+ });
48
+ duplicates.push({
49
+ name: packageName$1,
50
+ instances
51
+ });
52
+ }
53
+ return duplicates;
54
+ };
55
+
56
+ //#endregion
57
+ //#region src/get-hotspots.ts
58
+ const getHotspots = async (hotPathsTree, typesFile, options) => getHotspotsWorker({
59
+ span: hotPathsTree,
60
+ currentFile: void 0,
61
+ typeRegistry: createTypeRegistry(typesFile),
62
+ options
63
+ });
64
+ async function getHotspotsWorker({ span, currentFile, typeRegistry, options }) {
65
+ if (span.event.cat === "check") currentFile = span.event.args.path;
66
+ const children = [];
67
+ if (span.children.length) {
68
+ const sortedChildren = span.children.sort((a, b) => b.duration - a.duration);
69
+ for (const child of sortedChildren) children.push(...await getHotspotsWorker({
70
+ span: child,
71
+ currentFile,
72
+ typeRegistry,
73
+ options
74
+ }));
75
+ }
76
+ if (span.event.name !== "root") {
77
+ const hotFrame = await makeHotFrame({
78
+ span,
79
+ children,
80
+ typeRegistry
81
+ });
82
+ if (hotFrame) return [hotFrame];
83
+ }
84
+ return children;
85
+ }
86
+ const notFound = {
87
+ children: [],
88
+ resolvedType: {
89
+ id: -1,
90
+ display: "[Type Not Found]",
91
+ flags: []
92
+ }
93
+ };
94
+ function getHotType({ id, typeRegistry }) {
95
+ function worker(id$1, ancestorIds) {
96
+ if (id$1 === -1) return notFound;
97
+ const resolvedType$1 = typeRegistry[id$1];
98
+ if (!resolvedType$1) throw new Error(`Type ${id$1} not found`);
99
+ const children = [];
100
+ if (ancestorIds.indexOf(id$1) < 0) {
101
+ ancestorIds.push(id$1);
102
+ const properties = Object.keys(resolvedType$1);
103
+ for (const property of properties) switch (property) {
104
+ case "aliasTypeArguments":
105
+ case "intersectionTypes":
106
+ case "typeArguments":
107
+ case "unionTypes": {
108
+ const typeIds = resolvedType$1[property];
109
+ if (!Array.isArray(typeIds)) throw new Error(`Expected array for ${property}`);
110
+ for (const typeId of typeIds) {
111
+ const child = worker(typeId, ancestorIds);
112
+ if (child) children.push(child);
113
+ }
114
+ continue;
115
+ }
116
+ case "aliasType":
117
+ case "conditionalCheckType":
118
+ case "conditionalExtendsType":
119
+ case "conditionalFalseType":
120
+ case "conditionalTrueType":
121
+ case "constraintType":
122
+ case "evolvingArrayElementType":
123
+ case "evolvingArrayFinalType":
124
+ case "indexedAccessIndexType":
125
+ case "indexedAccessObjectType":
126
+ case "instantiatedType":
127
+ case "keyofType":
128
+ case "reverseMappedConstraintType":
129
+ case "reverseMappedMappedType":
130
+ case "reverseMappedSourceType":
131
+ case "substitutionBaseType": {
132
+ const typeId = resolvedType$1[property];
133
+ const child = worker(typeId, ancestorIds);
134
+ if (child) children.push(child);
135
+ break;
136
+ }
137
+ case "destructuringPattern":
138
+ case "display":
139
+ case "firstDeclaration":
140
+ case "flags":
141
+ case "id":
142
+ case "intrinsicName":
143
+ case "isTuple":
144
+ case "recursionId":
145
+ case "referenceLocation":
146
+ case "symbolName": break;
147
+ default: throw new Error(`Unexpected property ${property}`);
148
+ }
149
+ ancestorIds.pop();
150
+ }
151
+ return {
152
+ resolvedType: resolvedType$1,
153
+ children
154
+ };
155
+ }
156
+ return worker(id, []);
157
+ }
158
+ async function makeHotFrame({ span, children, typeRegistry }) {
159
+ const { event, duration } = span;
160
+ const timeMs = Math.round(duration / 1e3);
161
+ switch (event.name) {
162
+ case "checkSourceFile": {
163
+ const filePath = event.args.path;
164
+ const normalizedPath = normalize(filePath);
165
+ return {
166
+ description: `Check file ${normalizedPath}`,
167
+ timeMs,
168
+ path: normalizedPath,
169
+ children
170
+ };
171
+ }
172
+ case "structuredTypeRelatedTo": return {
173
+ description: `Compare types ${event.args.sourceId} and ${event.args.targetId}`,
174
+ timeMs,
175
+ children,
176
+ types: [getHotType({
177
+ id: event.args.sourceId,
178
+ typeRegistry
179
+ }), getHotType({
180
+ id: event.args.targetId,
181
+ typeRegistry
182
+ })]
183
+ };
184
+ case "getVariancesWorker": return {
185
+ description: `Determine variance of type ${event.args.id}`,
186
+ timeMs,
187
+ children,
188
+ types: [getHotType({
189
+ id: event.args.id,
190
+ typeRegistry
191
+ })]
192
+ };
193
+ case "checkExpression":
194
+ case "checkVariableDeclaration": {
195
+ const filePath = event.args.path;
196
+ const path = filePath ? { path: normalize(filePath) } : {};
197
+ return {
198
+ description: event.name,
199
+ timeMs,
200
+ ...path,
201
+ children: []
202
+ };
203
+ }
204
+ default: return;
205
+ }
206
+ }
207
+
208
+ //#endregion
209
+ //#region src/node-module-paths.ts
210
+ function getNodeModulePaths(traceJson) {
211
+ const nodeModulePaths$1 = {};
212
+ traceJson.forEach((event) => {
213
+ if (event.name !== "findSourceFile") return;
214
+ const path = event.args.fileName;
215
+ if (path) while (true) {
216
+ const match = packageNameRegex.exec(path);
217
+ if (!match) break;
218
+ const packageName$1 = match[1];
219
+ const packagePath$1 = match.input.substring(0, match.index + match[0].length);
220
+ if (packageName$1 in nodeModulePaths$1) {
221
+ const paths = nodeModulePaths$1[packageName$1];
222
+ if (paths && paths.indexOf(packagePath$1) < 0) paths.push(packagePath$1);
223
+ } else nodeModulePaths$1[packageName$1] = [packagePath$1];
224
+ }
225
+ });
226
+ return nodeModulePaths$1;
227
+ }
228
+
229
+ //#endregion
230
+ //#region src/spans.ts
231
+ function createSpans(traceFile) {
232
+ const unclosedStack = [];
233
+ const spans = [];
234
+ traceFile.forEach((event) => {
235
+ switch (event.ph) {
236
+ case eventPhase.begin:
237
+ unclosedStack.push(event);
238
+ return;
239
+ case eventPhase.end: {
240
+ const beginEvent = unclosedStack.pop();
241
+ if (!beginEvent) throw new Error("Unmatched end event");
242
+ spans.push({
243
+ event: beginEvent,
244
+ start: beginEvent.ts,
245
+ end: event.ts,
246
+ duration: event.ts - beginEvent.ts,
247
+ children: []
248
+ });
249
+ break;
250
+ }
251
+ case eventPhase.complete: {
252
+ const start = event.ts;
253
+ const duration = event.dur ?? 0;
254
+ spans.push({
255
+ event,
256
+ start,
257
+ end: start + duration,
258
+ duration,
259
+ children: []
260
+ });
261
+ break;
262
+ }
263
+ case eventPhase.instantGlobal:
264
+ case eventPhase.metadata: return;
265
+ default:
266
+ }
267
+ });
268
+ return {
269
+ firstSpanStart: Math.min(...spans.map((span) => span.start)),
270
+ lastSpanEnd: Math.max(...spans.map((span) => span.end)),
271
+ spans,
272
+ unclosedStack
273
+ };
274
+ }
275
+ function createSpanTree(parseResult$1, options) {
276
+ const { firstSpanStart, lastSpanEnd, spans, unclosedStack } = parseResult$1;
277
+ for (let i = unclosedStack.length - 1; i >= 0; i--) {
278
+ const event = unclosedStack[i];
279
+ const start = event.ts;
280
+ const end = lastSpanEnd;
281
+ spans.push({
282
+ event,
283
+ start,
284
+ end,
285
+ duration: end - start,
286
+ children: []
287
+ });
288
+ }
289
+ spans.sort((a, b) => a.start - b.start);
290
+ const root = {
291
+ event: {
292
+ name: "root",
293
+ cat: "program"
294
+ },
295
+ start: firstSpanStart,
296
+ end: lastSpanEnd,
297
+ duration: lastSpanEnd - firstSpanStart,
298
+ children: []
299
+ };
300
+ const stack = [root];
301
+ for (const span of spans) {
302
+ let i = stack.length - 1;
303
+ for (; i > 0; i--) if (stack[i].end > span.start) {
304
+ stack.length = i + 1;
305
+ break;
306
+ }
307
+ /** Microseconds */
308
+ const thresholdDuration = options.forceMillis * 1e3;
309
+ const isAboveThresholdDuration = span.duration >= thresholdDuration;
310
+ const parent = stack[i];
311
+ const parentDuration = parent.end - parent.start;
312
+ const isSignificantPortionOfParent = span.duration >= parentDuration * options.minSpanParentPercentage;
313
+ if (isAboveThresholdDuration || isSignificantPortionOfParent) {
314
+ parent.children.push(span);
315
+ stack.push(span);
316
+ }
317
+ }
318
+ return root;
319
+ }
320
+
321
+ //#endregion
322
+ //#region src/utils.ts
323
+ const absolutePath = z.string().refine((path) => {
324
+ return path.startsWith("/") || path.startsWith("C:\\") || path.startsWith("D:\\");
325
+ }, { message: "Path must be absolute" });
326
+ const project = z.object({
327
+ configFilePath: absolutePath.optional(),
328
+ tracePath: absolutePath,
329
+ typesPath: absolutePath
330
+ });
331
+ const projectResult = z.object({
332
+ project,
333
+ stdout: z.string(),
334
+ stderr: z.string(),
335
+ exitCode: z.number().optional(),
336
+ signal: z.enum(["SIGINT", "SIGTERM"]).optional()
337
+ });
338
+ const hotType = z.object({
339
+ resolvedType,
340
+ get children() {
341
+ return z.array(hotType);
342
+ }
343
+ });
344
+ const hotSpot = z.object({
345
+ description: z.string(),
346
+ timeMs: z.number(),
347
+ get children() {
348
+ return z.array(hotSpot);
349
+ },
350
+ path: absolutePath.optional(),
351
+ types: z.array(hotType).optional(),
352
+ startLine: z.number().optional(),
353
+ startChar: z.number().optional(),
354
+ startOffset: z.number().optional(),
355
+ endLine: z.number().optional(),
356
+ endChar: z.number().optional(),
357
+ endOffset: z.number().optional()
358
+ });
359
+ const duplicatedPackageInstance = z.object({
360
+ path: absolutePath,
361
+ version: z.string()
362
+ });
363
+ const duplicatedPackage = z.object({
364
+ name: z.string(),
365
+ instances: z.array(duplicatedPackageInstance)
366
+ });
367
+ const rootSpan = z.object({
368
+ name: z.literal("root"),
369
+ cat: z.literal("program")
370
+ });
371
+ const eventSpan = z.object({
372
+ event: z.union([traceEvent, rootSpan]),
373
+ start: z.number(),
374
+ end: z.number(),
375
+ duration: z.number(),
376
+ get children() {
377
+ return z.array(eventSpan);
378
+ }
379
+ });
380
+ const microseconds = z.number();
381
+ const packageName = z.string();
382
+ const packagePath = z.string();
383
+ const nodeModulePaths = z.record(packageName, z.array(packagePath));
384
+ const parseResult = z.object({
385
+ firstSpanStart: z.number(),
386
+ lastSpanEnd: z.number(),
387
+ spans: z.array(eventSpan),
388
+ unclosedStack: z.array(traceEvent)
389
+ });
390
+ const analyzeTraceOptions = z.object({
391
+ forceMillis: z.number(),
392
+ skipMillis: z.number(),
393
+ expandTypes: z.boolean(),
394
+ minSpanParentPercentage: z.number(),
395
+ importExpressionThreshold: z.number()
396
+ });
397
+ const isFile = async (path) => {
398
+ return stat(path).then((stats) => stats.isFile()).catch((_) => false);
399
+ };
400
+ const throwIfNotDirectory = async (path) => {
401
+ if (!existsSync(path) || !(await stat(path))?.isDirectory()) throw new Error(`${path} is not a directory`);
402
+ return path;
403
+ };
404
+ const analyzeTraceResult = z.object({
405
+ unterminatedEvents: z.array(traceEvent),
406
+ hotSpots: z.array(hotSpot),
407
+ duplicatePackages: z.array(duplicatedPackage),
408
+ nodeModulePaths,
409
+ depthLimits: z.object({
410
+ checkCrossProductUnion_DepthLimit: z.array(event_checktypes__checkCrossProductUnion_DepthLimit),
411
+ checkTypeRelatedTo_DepthLimit: z.array(event_checktypes__checkTypeRelatedTo_DepthLimit),
412
+ getTypeAtFlowNode_DepthLimit: z.array(event_checktypes__getTypeAtFlowNode_DepthLimit),
413
+ instantiateType_DepthLimit: z.array(event_checktypes__instantiateType_DepthLimit),
414
+ recursiveTypeRelatedTo_DepthLimit: z.array(event_checktypes__recursiveTypeRelatedTo_DepthLimit),
415
+ removeSubtypes_DepthLimit: z.array(event_checktypes__removeSubtypes_DepthLimit),
416
+ traceUnionsOrIntersectionsTooLarge_DepthLimit: z.array(event_checktypes__traceUnionsOrIntersectionsTooLarge_DepthLimit),
417
+ typeRelatedToDiscriminatedType_DepthLimit: z.array(event_checktypes__typeRelatedToDiscriminatedType_DepthLimit)
418
+ })
419
+ });
420
+
421
+ //#endregion
422
+ //#region src/analyze-trace.ts
423
+ function validateOptions(options) {
424
+ if (options.forceMillis < options.skipMillis) throw new Error("forceMillis cannot be less than skipMillis");
425
+ }
426
+ const validateTraceDir = async (traceDir) => {
427
+ await throwIfNotDirectory(traceDir);
428
+ const typesFilePath = join(traceDir, TYPES_JSON_FILENAME);
429
+ if (!existsSync(typesFilePath)) throw new Error(`types.json must exist in ${traceDir}. first run --generateTrace`);
430
+ const typesFileJson = JSON.parse(await readFile(typesFilePath, "utf8"));
431
+ const typesFile = typesJsonSchema.parse(typesFileJson);
432
+ const traceFilePath = join(traceDir, TRACE_JSON_FILENAME);
433
+ if (!existsSync(traceFilePath)) throw new Error(`trace.json must exist in ${traceDir}. first run --generateTrace`);
434
+ const traceFileJson = JSON.parse(await readFile(traceFilePath, "utf8"));
435
+ return {
436
+ traceFile: traceJsonSchema.parse(traceFileJson),
437
+ typesFile
438
+ };
439
+ };
440
+ const defaultOptions = {
441
+ forceMillis: 500,
442
+ skipMillis: 100,
443
+ expandTypes: true,
444
+ minSpanParentPercentage: .6,
445
+ importExpressionThreshold: 10
446
+ };
447
+ const analyzeTrace = async ({ traceDir, options = defaultOptions }) => {
448
+ validateOptions(options);
449
+ const { traceFile, typesFile } = await validateTraceDir(traceDir);
450
+ const nodeModulePaths$1 = getNodeModulePaths(traceFile);
451
+ const spans = createSpans(traceFile);
452
+ const hotPathsTree = createSpanTree(spans, options);
453
+ const result = {
454
+ nodeModulePaths: nodeModulePaths$1,
455
+ unterminatedEvents: spans.unclosedStack.reverse(),
456
+ hotSpots: await getHotspots(hotPathsTree, typesFile, options),
457
+ duplicatePackages: await getDuplicateNodeModules(nodeModulePaths$1),
458
+ depthLimits: createDepthLimits(traceFile)
459
+ };
460
+ await writeFile(join(traceDir, ANALYZE_TRACE_FILENAME), JSON.stringify(result, null, 2));
461
+ return result;
462
+ };
463
+
464
+ //#endregion
465
+ export { ANALYZE_TRACE_FILENAME, absolutePath, analyzeTrace, analyzeTraceOptions, analyzeTraceResult, createDepthLimits, defaultOptions, duplicatedPackage, duplicatedPackageInstance, eventSpan, hotSpot, hotType, isFile, microseconds, nodeModulePaths, packageName, packagePath, parseResult, project, projectResult, rootSpan, throwIfNotDirectory, validateOptions };
466
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +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 } = span;\n\n const timeMs = Math.round(duration / 1000);\n switch (event.name) {\n // case \"findSourceFile\":\n // TODO (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 timeMs,\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 timeMs,\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 timeMs,\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 timeMs,\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 timeMs: 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.13",
3
+ "version": "0.1.15",
4
4
  "description": "Analyze TypeScript compiler trace events to identify performance bottlenecks",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -19,33 +19,35 @@
19
19
  "node": ">=24"
20
20
  },
21
21
  "packageManager": "pnpm@10.6.5",
22
- "main": "./dist/index.js",
23
- "types": "./dist/index.d.ts",
22
+ "main": "./dist/index.mjs",
23
+ "types": "./dist/index.d.mts",
24
24
  "exports": {
25
25
  ".": {
26
- "types": "./dist/index.d.ts",
27
- "import": "./dist/index.js"
26
+ "types": "./dist/index.d.mts",
27
+ "import": "./dist/index.mjs"
28
28
  },
29
29
  "./browser": {
30
- "types": "./dist/browser.d.ts",
31
- "import": "./dist/browser.js"
30
+ "types": "./dist/browser.d.mts",
31
+ "import": "./dist/browser.mjs"
32
32
  }
33
33
  },
34
34
  "bin": {
35
35
  "typeslayer-analyze-trace": "./bin/typeslayer-analyze-trace.mjs"
36
36
  },
37
37
  "scripts": {
38
- "build": "tsup",
39
- "dev": "tsup --watch",
38
+ "build": "tsdown",
39
+ "dev": "tsdown --watch",
40
+ "attw": "attw --pack --profile esm-only .",
40
41
  "typecheck": "tsc --noEmit"
41
42
  },
42
43
  "dependencies": {
44
+ "@typeslayer/validate": "workspace:*",
43
45
  "zod": "4.1.13"
44
46
  },
45
47
  "devDependencies": {
48
+ "@arethetypeswrong/cli": "^0.18.2",
46
49
  "@types/node": "24.10.1",
47
- "@typeslayer/validate": "workspace:*",
48
- "tsup": "8.5.1",
50
+ "tsdown": "^0.17.2",
49
51
  "typescript": "5.9.3"
50
52
  }
51
53
  }
@@ -1,4 +1,4 @@
1
- import { defineConfig } from "tsup";
1
+ import { defineConfig } from "tsdown";
2
2
 
3
3
  export default defineConfig([
4
4
  // Main Node.js build
@@ -7,11 +7,8 @@ export default defineConfig([
7
7
  format: ["esm"],
8
8
  target: "es2024",
9
9
  dts: true,
10
- splitting: false,
11
10
  sourcemap: true,
12
11
  clean: true,
13
- external: ["zod"],
14
- noExternal: ["@typeslayer/validate"],
15
12
  },
16
13
  // Browser-safe build (types only)
17
14
  {
@@ -19,10 +16,7 @@ export default defineConfig([
19
16
  format: ["esm"],
20
17
  target: "es2024",
21
18
  dts: true,
22
- splitting: false,
23
19
  sourcemap: true,
24
20
  clean: false,
25
- external: ["zod"],
26
- noExternal: ["@typeslayer/validate"],
27
21
  },
28
22
  ]);