perfgraph 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +280 -0
- package/dist/causal/builder.d.ts +34 -0
- package/dist/causal/builder.d.ts.map +1 -0
- package/dist/causal/builder.js +132 -0
- package/dist/causal/builder.js.map +1 -0
- package/dist/causal/index.d.ts +11 -0
- package/dist/causal/index.d.ts.map +1 -0
- package/dist/causal/index.js +10 -0
- package/dist/causal/index.js.map +1 -0
- package/dist/causal/rules/js.d.ts +49 -0
- package/dist/causal/rules/js.d.ts.map +1 -0
- package/dist/causal/rules/js.js +209 -0
- package/dist/causal/rules/js.js.map +1 -0
- package/dist/causal/rules/layout.d.ts +39 -0
- package/dist/causal/rules/layout.d.ts.map +1 -0
- package/dist/causal/rules/layout.js +169 -0
- package/dist/causal/rules/layout.js.map +1 -0
- package/dist/causal/rules/lcp.d.ts +49 -0
- package/dist/causal/rules/lcp.d.ts.map +1 -0
- package/dist/causal/rules/lcp.js +250 -0
- package/dist/causal/rules/lcp.js.map +1 -0
- package/dist/causal/rules/network.d.ts +39 -0
- package/dist/causal/rules/network.d.ts.map +1 -0
- package/dist/causal/rules/network.js +140 -0
- package/dist/causal/rules/network.js.map +1 -0
- package/dist/causal/types.d.ts +142 -0
- package/dist/causal/types.d.ts.map +1 -0
- package/dist/causal/types.js +88 -0
- package/dist/causal/types.js.map +1 -0
- package/dist/cli/analyze.d.ts +33 -0
- package/dist/cli/analyze.d.ts.map +1 -0
- package/dist/cli/analyze.js +137 -0
- package/dist/cli/analyze.js.map +1 -0
- package/dist/cli/collect.d.ts +28 -0
- package/dist/cli/collect.d.ts.map +1 -0
- package/dist/cli/collect.js +125 -0
- package/dist/cli/collect.js.map +1 -0
- package/dist/cli/extract.d.ts +31 -0
- package/dist/cli/extract.d.ts.map +1 -0
- package/dist/cli/extract.js +135 -0
- package/dist/cli/extract.js.map +1 -0
- package/dist/cli/mcp.d.ts +14 -0
- package/dist/cli/mcp.d.ts.map +1 -0
- package/dist/cli/mcp.js +53 -0
- package/dist/cli/mcp.js.map +1 -0
- package/dist/cli/normalize.d.ts +58 -0
- package/dist/cli/normalize.d.ts.map +1 -0
- package/dist/cli/normalize.js +179 -0
- package/dist/cli/normalize.js.map +1 -0
- package/dist/cli/report.d.ts +33 -0
- package/dist/cli/report.d.ts.map +1 -0
- package/dist/cli/report.js +137 -0
- package/dist/cli/report.js.map +1 -0
- package/dist/cli/run.d.ts +49 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +243 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/collect/buffer-monitor.d.ts +25 -0
- package/dist/collect/buffer-monitor.d.ts.map +1 -0
- package/dist/collect/buffer-monitor.js +69 -0
- package/dist/collect/buffer-monitor.js.map +1 -0
- package/dist/collect/console.d.ts +25 -0
- package/dist/collect/console.d.ts.map +1 -0
- package/dist/collect/console.js +82 -0
- package/dist/collect/console.js.map +1 -0
- package/dist/collect/coverage.d.ts +26 -0
- package/dist/collect/coverage.d.ts.map +1 -0
- package/dist/collect/coverage.js +99 -0
- package/dist/collect/coverage.js.map +1 -0
- package/dist/collect/dom.d.ts +37 -0
- package/dist/collect/dom.d.ts.map +1 -0
- package/dist/collect/dom.js +118 -0
- package/dist/collect/dom.js.map +1 -0
- package/dist/collect/lighthouse.d.ts +41 -0
- package/dist/collect/lighthouse.d.ts.map +1 -0
- package/dist/collect/lighthouse.js +111 -0
- package/dist/collect/lighthouse.js.map +1 -0
- package/dist/collect/network.d.ts +32 -0
- package/dist/collect/network.d.ts.map +1 -0
- package/dist/collect/network.js +236 -0
- package/dist/collect/network.js.map +1 -0
- package/dist/collect/orchestrator.d.ts +23 -0
- package/dist/collect/orchestrator.d.ts.map +1 -0
- package/dist/collect/orchestrator.js +350 -0
- package/dist/collect/orchestrator.js.map +1 -0
- package/dist/collect/performance.d.ts +28 -0
- package/dist/collect/performance.d.ts.map +1 -0
- package/dist/collect/performance.js +108 -0
- package/dist/collect/performance.js.map +1 -0
- package/dist/collect/runtime.d.ts +26 -0
- package/dist/collect/runtime.d.ts.map +1 -0
- package/dist/collect/runtime.js +81 -0
- package/dist/collect/runtime.js.map +1 -0
- package/dist/collect/session.d.ts +58 -0
- package/dist/collect/session.d.ts.map +1 -0
- package/dist/collect/session.js +162 -0
- package/dist/collect/session.js.map +1 -0
- package/dist/collect/trace.d.ts +40 -0
- package/dist/collect/trace.d.ts.map +1 -0
- package/dist/collect/trace.js +127 -0
- package/dist/collect/trace.js.map +1 -0
- package/dist/collect/types.d.ts +317 -0
- package/dist/collect/types.d.ts.map +1 -0
- package/dist/collect/types.js +12 -0
- package/dist/collect/types.js.map +1 -0
- package/dist/distill/insights.d.ts +67 -0
- package/dist/distill/insights.d.ts.map +1 -0
- package/dist/distill/insights.js +317 -0
- package/dist/distill/insights.js.map +1 -0
- package/dist/distill/summaries.d.ts +71 -0
- package/dist/distill/summaries.d.ts.map +1 -0
- package/dist/distill/summaries.js +165 -0
- package/dist/distill/summaries.js.map +1 -0
- package/dist/extract/critical-path.d.ts +17 -0
- package/dist/extract/critical-path.d.ts.map +1 -0
- package/dist/extract/critical-path.js +95 -0
- package/dist/extract/critical-path.js.map +1 -0
- package/dist/extract/index.d.ts +16 -0
- package/dist/extract/index.d.ts.map +1 -0
- package/dist/extract/index.js +32 -0
- package/dist/extract/index.js.map +1 -0
- package/dist/extract/js-hotspots.d.ts +15 -0
- package/dist/extract/js-hotspots.d.ts.map +1 -0
- package/dist/extract/js-hotspots.js +22 -0
- package/dist/extract/js-hotspots.js.map +1 -0
- package/dist/extract/layout-shifts.d.ts +19 -0
- package/dist/extract/layout-shifts.d.ts.map +1 -0
- package/dist/extract/layout-shifts.js +47 -0
- package/dist/extract/layout-shifts.js.map +1 -0
- package/dist/extract/lcp-breakdown.d.ts +19 -0
- package/dist/extract/lcp-breakdown.d.ts.map +1 -0
- package/dist/extract/lcp-breakdown.js +110 -0
- package/dist/extract/lcp-breakdown.js.map +1 -0
- package/dist/extract/main-thread.d.ts +16 -0
- package/dist/extract/main-thread.d.ts.map +1 -0
- package/dist/extract/main-thread.js +41 -0
- package/dist/extract/main-thread.js.map +1 -0
- package/dist/extract/render-blocking.d.ts +16 -0
- package/dist/extract/render-blocking.d.ts.map +1 -0
- package/dist/extract/render-blocking.js +79 -0
- package/dist/extract/render-blocking.js.map +1 -0
- package/dist/extract/third-party.d.ts +15 -0
- package/dist/extract/third-party.d.ts.map +1 -0
- package/dist/extract/third-party.js +127 -0
- package/dist/extract/third-party.js.map +1 -0
- package/dist/extract/types.d.ts +183 -0
- package/dist/extract/types.d.ts.map +1 -0
- package/dist/extract/types.js +118 -0
- package/dist/extract/types.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +188 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/handlers.d.ts +72 -0
- package/dist/mcp/handlers.d.ts.map +1 -0
- package/dist/mcp/handlers.js +285 -0
- package/dist/mcp/handlers.js.map +1 -0
- package/dist/mcp/progress.d.ts +37 -0
- package/dist/mcp/progress.d.ts.map +1 -0
- package/dist/mcp/progress.js +51 -0
- package/dist/mcp/progress.js.map +1 -0
- package/dist/mcp/prompts.d.ts +57 -0
- package/dist/mcp/prompts.d.ts.map +1 -0
- package/dist/mcp/prompts.js +225 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/resources.d.ts +48 -0
- package/dist/mcp/resources.d.ts.map +1 -0
- package/dist/mcp/resources.js +149 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/server.d.ts +34 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +452 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/types.d.ts +47 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +67 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/normalize/clock.d.ts +40 -0
- package/dist/normalize/clock.d.ts.map +1 -0
- package/dist/normalize/clock.js +96 -0
- package/dist/normalize/clock.js.map +1 -0
- package/dist/normalize/dom-ir.d.ts +16 -0
- package/dist/normalize/dom-ir.d.ts.map +1 -0
- package/dist/normalize/dom-ir.js +48 -0
- package/dist/normalize/dom-ir.js.map +1 -0
- package/dist/normalize/index.d.ts +23 -0
- package/dist/normalize/index.d.ts.map +1 -0
- package/dist/normalize/index.js +118 -0
- package/dist/normalize/index.js.map +1 -0
- package/dist/normalize/lighthouse-insights.d.ts +27 -0
- package/dist/normalize/lighthouse-insights.d.ts.map +1 -0
- package/dist/normalize/lighthouse-insights.js +318 -0
- package/dist/normalize/lighthouse-insights.js.map +1 -0
- package/dist/normalize/lighthouse-ir.d.ts +25 -0
- package/dist/normalize/lighthouse-ir.d.ts.map +1 -0
- package/dist/normalize/lighthouse-ir.js +151 -0
- package/dist/normalize/lighthouse-ir.js.map +1 -0
- package/dist/normalize/network-ir.d.ts +23 -0
- package/dist/normalize/network-ir.d.ts.map +1 -0
- package/dist/normalize/network-ir.js +180 -0
- package/dist/normalize/network-ir.js.map +1 -0
- package/dist/normalize/runtime-ir.d.ts +18 -0
- package/dist/normalize/runtime-ir.d.ts.map +1 -0
- package/dist/normalize/runtime-ir.js +114 -0
- package/dist/normalize/runtime-ir.js.map +1 -0
- package/dist/normalize/trace-ir.d.ts +20 -0
- package/dist/normalize/trace-ir.d.ts.map +1 -0
- package/dist/normalize/trace-ir.js +224 -0
- package/dist/normalize/trace-ir.js.map +1 -0
- package/dist/normalize/types.d.ts +536 -0
- package/dist/normalize/types.d.ts.map +1 -0
- package/dist/normalize/types.js +242 -0
- package/dist/normalize/types.js.map +1 -0
- package/dist/output/manifest.d.ts +44 -0
- package/dist/output/manifest.d.ts.map +1 -0
- package/dist/output/manifest.js +232 -0
- package/dist/output/manifest.js.map +1 -0
- package/dist/output/toon.d.ts +19 -0
- package/dist/output/toon.d.ts.map +1 -0
- package/dist/output/toon.js +22 -0
- package/dist/output/toon.js.map +1 -0
- package/dist/output/writer.d.ts +31 -0
- package/dist/output/writer.d.ts.map +1 -0
- package/dist/output/writer.js +51 -0
- package/dist/output/writer.js.map +1 -0
- package/dist/report/analyzer.d.ts +29 -0
- package/dist/report/analyzer.d.ts.map +1 -0
- package/dist/report/analyzer.js +330 -0
- package/dist/report/analyzer.js.map +1 -0
- package/dist/report/index.d.ts +13 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +12 -0
- package/dist/report/index.js.map +1 -0
- package/dist/report/markdown.d.ts +21 -0
- package/dist/report/markdown.d.ts.map +1 -0
- package/dist/report/markdown.js +182 -0
- package/dist/report/markdown.js.map +1 -0
- package/dist/report/remediations.d.ts +42 -0
- package/dist/report/remediations.d.ts.map +1 -0
- package/dist/report/remediations.js +179 -0
- package/dist/report/remediations.js.map +1 -0
- package/dist/report/scorer.d.ts +35 -0
- package/dist/report/scorer.d.ts.map +1 -0
- package/dist/report/scorer.js +72 -0
- package/dist/report/scorer.js.map +1 -0
- package/dist/report/types.d.ts +201 -0
- package/dist/report/types.d.ts.map +1 -0
- package/dist/report/types.js +149 -0
- package/dist/report/types.js.map +1 -0
- package/dist/shared/fs-utils.d.ts +12 -0
- package/dist/shared/fs-utils.d.ts.map +1 -0
- package/dist/shared/fs-utils.js +44 -0
- package/dist/shared/fs-utils.js.map +1 -0
- package/dist/shared/types.d.ts +69 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +18 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/shared/utils.d.ts +6 -0
- package/dist/shared/utils.d.ts.map +1 -0
- package/dist/shared/utils.js +9 -0
- package/dist/shared/utils.js.map +1 -0
- package/package.json +67 -0
package/dist/cli/mcp.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mcp` subcommand handler.
|
|
3
|
+
*
|
|
4
|
+
* Starts a MCP (Model Context Protocol) stdio server so that AI agents
|
|
5
|
+
* (Claude, OpenCode, Cursor, etc.) can invoke perfgraph tools directly.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* perfgraph mcp
|
|
9
|
+
*/
|
|
10
|
+
import { startMcpServer } from '../mcp/server.js';
|
|
11
|
+
const MCP_HELP = `
|
|
12
|
+
MCP OPTIONS
|
|
13
|
+
No flags required. Starts a MCP stdio server that listens for
|
|
14
|
+
JSON-RPC messages on stdin/stdout.
|
|
15
|
+
|
|
16
|
+
EXAMPLES
|
|
17
|
+
perfgraph mcp
|
|
18
|
+
|
|
19
|
+
MCP CLIENT CONFIG
|
|
20
|
+
{
|
|
21
|
+
"mcpServers": {
|
|
22
|
+
"perfgraph": {
|
|
23
|
+
"command": "node",
|
|
24
|
+
"args": ["dist/index.js", "mcp"]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
/**
|
|
30
|
+
* Parse CLI arguments for the mcp command and execute.
|
|
31
|
+
*/
|
|
32
|
+
export async function runMcpFromArgs(args) {
|
|
33
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
34
|
+
console.log(MCP_HELP);
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
// Any unknown flags are an error
|
|
38
|
+
for (const arg of args) {
|
|
39
|
+
if (arg.startsWith('--')) {
|
|
40
|
+
console.error(`Error: Unknown flag "${arg}"`);
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
await startMcpServer();
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
console.error(`MCP server error: ${err.message}`);
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/cli/mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;CAiBhB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAc;IACjD,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iCAAiC;IACjC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,KAAK,CAAC,wBAAwB,GAAG,GAAG,CAAC,CAAC;YAC9C,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACH,MAAM,cAAc,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,qBAAsB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7D,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `normalize` subcommand handler.
|
|
3
|
+
*
|
|
4
|
+
* Reads raw data files from a run directory and outputs the normalized
|
|
5
|
+
* Intermediate Representation (IRBundle) as JSON.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* perfgraph normalize <run-dir>
|
|
9
|
+
*
|
|
10
|
+
* The run directory should contain the JSON files produced by a single
|
|
11
|
+
* collection run (trace.json, network.json, performance.json, etc.).
|
|
12
|
+
*/
|
|
13
|
+
/** Result of the normalize command execution */
|
|
14
|
+
export interface NormalizeResult {
|
|
15
|
+
/** Whether normalization succeeded */
|
|
16
|
+
success: boolean;
|
|
17
|
+
/** Path to the input run directory */
|
|
18
|
+
runDir: string;
|
|
19
|
+
/** Version of the generated IR bundle */
|
|
20
|
+
irVersion: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Run the normalize command from a directory path.
|
|
24
|
+
*
|
|
25
|
+
* @param runDir - Path to a collection run directory
|
|
26
|
+
* @param outputFile - Optional file path to write output (defaults to stdout)
|
|
27
|
+
* @param pretty - Pretty-print JSON output (default: false)
|
|
28
|
+
* @returns NormalizeResult
|
|
29
|
+
*/
|
|
30
|
+
export declare function runNormalize(runDir: string, outputFile?: string, pretty?: boolean): Promise<NormalizeResult>;
|
|
31
|
+
/**
|
|
32
|
+
* Find the latest run directory within a parent output directory.
|
|
33
|
+
*
|
|
34
|
+
* The parent directory should contain timestamped subdirectories named in
|
|
35
|
+
* ISO 8601 format (e.g. "2025-01-15T10-30-00"). The latest is determined
|
|
36
|
+
* by name sort, which is chronological for ISO 8601 date strings.
|
|
37
|
+
*
|
|
38
|
+
* @param parentDir - Parent directory containing timestamped subdirectories
|
|
39
|
+
* @returns Path to the latest run directory
|
|
40
|
+
* @throws Error if no subdirectories are found
|
|
41
|
+
*/
|
|
42
|
+
export declare function findLatestRunDir(parentDir: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Parse CLI arguments for the normalize command and execute.
|
|
45
|
+
*
|
|
46
|
+
* Accepts:
|
|
47
|
+
* <input> (positional, required — run dir or parent dir)
|
|
48
|
+
* --output, -o <file> (optional, default: stdout)
|
|
49
|
+
* --pretty (optional, default: minified)
|
|
50
|
+
* --help, -h (show help)
|
|
51
|
+
*
|
|
52
|
+
* Mode detection:
|
|
53
|
+
* - If <input> contains JSON data files directly → treat as single run dir
|
|
54
|
+
* - If <input> contains timestamped subdirectories → use latest run dir
|
|
55
|
+
* - Otherwise → error
|
|
56
|
+
*/
|
|
57
|
+
export declare function runNormalizeFromArgs(args: string[]): Promise<NormalizeResult | null>;
|
|
58
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/cli/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAiCH,gDAAgD;AAChD,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,eAAe,CAAC,CAkB1B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAa1D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAoFjC"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `normalize` subcommand handler.
|
|
3
|
+
*
|
|
4
|
+
* Reads raw data files from a run directory and outputs the normalized
|
|
5
|
+
* Intermediate Representation (IRBundle) as JSON.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* perfgraph normalize <run-dir>
|
|
9
|
+
*
|
|
10
|
+
* The run directory should contain the JSON files produced by a single
|
|
11
|
+
* collection run (trace.json, network.json, performance.json, etc.).
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
14
|
+
import { resolve, join } from 'node:path';
|
|
15
|
+
import { normalize } from '../normalize/index.js';
|
|
16
|
+
import { loadRunDir } from '../shared/fs-utils.js';
|
|
17
|
+
/** Expected JSON filenames in a run directory */
|
|
18
|
+
const DATA_FILES = [
|
|
19
|
+
'trace.json',
|
|
20
|
+
'network.json',
|
|
21
|
+
'performance.json',
|
|
22
|
+
'runtime.json',
|
|
23
|
+
'console.json',
|
|
24
|
+
'dom.json',
|
|
25
|
+
'lighthouse.json',
|
|
26
|
+
];
|
|
27
|
+
/** Help text shown by `perfgraph normalize --help` */
|
|
28
|
+
const NORMALIZE_HELP = `
|
|
29
|
+
NORMALIZE OPTIONS
|
|
30
|
+
<input> Path to a run directory OR parent output directory (positional, required)
|
|
31
|
+
--output, -o <file> Write output to a file (default: stdout)
|
|
32
|
+
--pretty Pretty-print JSON output
|
|
33
|
+
--help, -h Show this help message
|
|
34
|
+
|
|
35
|
+
EXAMPLES
|
|
36
|
+
perfgraph normalize ./runs/2025-01-15T10-30-00
|
|
37
|
+
perfgraph normalize ./runs/2025-01-15T10-30-00 --output ir.json
|
|
38
|
+
perfgraph normalize ./runs (auto-detect latest run)
|
|
39
|
+
perfgraph normalize ./runs --pretty --output ir.json
|
|
40
|
+
`;
|
|
41
|
+
/**
|
|
42
|
+
* Run the normalize command from a directory path.
|
|
43
|
+
*
|
|
44
|
+
* @param runDir - Path to a collection run directory
|
|
45
|
+
* @param outputFile - Optional file path to write output (defaults to stdout)
|
|
46
|
+
* @param pretty - Pretty-print JSON output (default: false)
|
|
47
|
+
* @returns NormalizeResult
|
|
48
|
+
*/
|
|
49
|
+
export async function runNormalize(runDir, outputFile, pretty) {
|
|
50
|
+
const raw = loadRunDir(runDir);
|
|
51
|
+
const bundle = normalize(raw);
|
|
52
|
+
const indent = pretty ? 2 : 0;
|
|
53
|
+
const json = JSON.stringify(bundle, null, indent);
|
|
54
|
+
if (outputFile) {
|
|
55
|
+
const { writeFileSync } = await import('node:fs');
|
|
56
|
+
writeFileSync(outputFile, json, 'utf-8');
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
console.log(json);
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
success: true,
|
|
63
|
+
runDir: resolve(runDir),
|
|
64
|
+
irVersion: bundle.meta.irVersion,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Find the latest run directory within a parent output directory.
|
|
69
|
+
*
|
|
70
|
+
* The parent directory should contain timestamped subdirectories named in
|
|
71
|
+
* ISO 8601 format (e.g. "2025-01-15T10-30-00"). The latest is determined
|
|
72
|
+
* by name sort, which is chronological for ISO 8601 date strings.
|
|
73
|
+
*
|
|
74
|
+
* @param parentDir - Parent directory containing timestamped subdirectories
|
|
75
|
+
* @returns Path to the latest run directory
|
|
76
|
+
* @throws Error if no subdirectories are found
|
|
77
|
+
*/
|
|
78
|
+
export function findLatestRunDir(parentDir) {
|
|
79
|
+
const entries = readdirSync(parentDir, { withFileTypes: true });
|
|
80
|
+
const subdirs = entries
|
|
81
|
+
.filter((entry) => entry.isDirectory())
|
|
82
|
+
.map((entry) => entry.name)
|
|
83
|
+
.sort();
|
|
84
|
+
if (subdirs.length === 0) {
|
|
85
|
+
throw new Error(`Error: No collector output files found in ${parentDir}`);
|
|
86
|
+
}
|
|
87
|
+
const latest = subdirs[subdirs.length - 1];
|
|
88
|
+
return join(parentDir, latest);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Parse CLI arguments for the normalize command and execute.
|
|
92
|
+
*
|
|
93
|
+
* Accepts:
|
|
94
|
+
* <input> (positional, required — run dir or parent dir)
|
|
95
|
+
* --output, -o <file> (optional, default: stdout)
|
|
96
|
+
* --pretty (optional, default: minified)
|
|
97
|
+
* --help, -h (show help)
|
|
98
|
+
*
|
|
99
|
+
* Mode detection:
|
|
100
|
+
* - If <input> contains JSON data files directly → treat as single run dir
|
|
101
|
+
* - If <input> contains timestamped subdirectories → use latest run dir
|
|
102
|
+
* - Otherwise → error
|
|
103
|
+
*/
|
|
104
|
+
export async function runNormalizeFromArgs(args) {
|
|
105
|
+
let input;
|
|
106
|
+
let outputFile;
|
|
107
|
+
let pretty = false;
|
|
108
|
+
for (let i = 0; i < args.length; i++) {
|
|
109
|
+
const arg = args[i];
|
|
110
|
+
switch (arg) {
|
|
111
|
+
case '--output':
|
|
112
|
+
case '-o':
|
|
113
|
+
if (i + 1 >= args.length) {
|
|
114
|
+
console.error('Error: --output requires a value');
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
outputFile = args[++i];
|
|
118
|
+
break;
|
|
119
|
+
case '--pretty':
|
|
120
|
+
pretty = true;
|
|
121
|
+
break;
|
|
122
|
+
case '--help':
|
|
123
|
+
case '-h':
|
|
124
|
+
console.log(NORMALIZE_HELP);
|
|
125
|
+
return null;
|
|
126
|
+
default:
|
|
127
|
+
if (arg.startsWith('--')) {
|
|
128
|
+
console.error(`Error: Unknown flag "${arg}"`);
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
// First positional arg is the input path
|
|
132
|
+
if (!input) {
|
|
133
|
+
input = arg;
|
|
134
|
+
}
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (!input) {
|
|
139
|
+
console.error('Error: <input> is required');
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
// Validate path exists
|
|
143
|
+
const resolvedPath = resolve(input);
|
|
144
|
+
if (!existsSync(resolvedPath)) {
|
|
145
|
+
console.error(`Error: Input path does not exist: ${input}`);
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
// Validate it's a directory
|
|
149
|
+
if (!statSync(resolvedPath).isDirectory()) {
|
|
150
|
+
console.error(`Error: Input is not a directory: ${input}`);
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
// Detect mode: single run dir vs parent output dir
|
|
154
|
+
const entries = readdirSync(resolvedPath);
|
|
155
|
+
const hasDataFiles = DATA_FILES.some((f) => entries.includes(f));
|
|
156
|
+
const hasTimestampDirs = entries.some((name) => /^\d{4}-\d{2}-\d{2}T/.test(name));
|
|
157
|
+
let runDir;
|
|
158
|
+
if (hasDataFiles) {
|
|
159
|
+
// Mode 1: Single run directory (contains JSON data files directly)
|
|
160
|
+
runDir = resolvedPath;
|
|
161
|
+
}
|
|
162
|
+
else if (hasTimestampDirs) {
|
|
163
|
+
// Mode 2: Parent output directory — auto-detect latest run
|
|
164
|
+
runDir = findLatestRunDir(resolvedPath);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
console.error(`Error: No collector output files found in ${resolvedPath}`);
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
// Execute normalize with error handling
|
|
171
|
+
try {
|
|
172
|
+
return await runNormalize(runDir, outputFile, pretty);
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
console.error(String(err));
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/cli/normalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `report` subcommand handler.
|
|
3
|
+
*
|
|
4
|
+
* Reads a FeatureSet JSON file (from `perfgraph extract`), runs causal analysis,
|
|
5
|
+
* generates a comprehensive Report, and outputs as JSON.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* perfgraph report <features-file>
|
|
9
|
+
* perfgraph report --input features.json --output report.json --pretty
|
|
10
|
+
*
|
|
11
|
+
* @packageDocumentation
|
|
12
|
+
*/
|
|
13
|
+
/** Result of the report command execution */
|
|
14
|
+
export interface ReportResult {
|
|
15
|
+
/** Whether report generation succeeded */
|
|
16
|
+
success: boolean;
|
|
17
|
+
/** Path to the input FeatureSet file */
|
|
18
|
+
inputFile: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Run the report command from a FeatureSet file path.
|
|
22
|
+
*
|
|
23
|
+
* @param inputFile - Path to FeatureSet JSON file
|
|
24
|
+
* @param outputFile - Optional output file path (defaults to stdout)
|
|
25
|
+
* @param pretty - Pretty-print JSON (default: false)
|
|
26
|
+
* @returns ReportResult
|
|
27
|
+
*/
|
|
28
|
+
export declare function runReport(inputFile: string, outputFile?: string, pretty?: boolean): Promise<ReportResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Parse CLI arguments for the report command and execute.
|
|
31
|
+
*/
|
|
32
|
+
export declare function runReportFromArgs(args: string[]): Promise<ReportResult | null>;
|
|
33
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/cli/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAwBH,6CAA6C;AAC7C,MAAM,WAAW,YAAY;IAC3B,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB;AAgCD;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,YAAY,CAAC,CAkBvB;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CA2D9B"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `report` subcommand handler.
|
|
3
|
+
*
|
|
4
|
+
* Reads a FeatureSet JSON file (from `perfgraph extract`), runs causal analysis,
|
|
5
|
+
* generates a comprehensive Report, and outputs as JSON.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* perfgraph report <features-file>
|
|
9
|
+
* perfgraph report --input features.json --output report.json --pretty
|
|
10
|
+
*
|
|
11
|
+
* @packageDocumentation
|
|
12
|
+
*/
|
|
13
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
14
|
+
import { resolve } from 'node:path';
|
|
15
|
+
import { buildCausalGraph } from '../causal/index.js';
|
|
16
|
+
import { buildReport } from '../report/index.js';
|
|
17
|
+
import { FeatureSetSchema } from '../extract/types.js';
|
|
18
|
+
/** Help text shown by `perfgraph report --help` */
|
|
19
|
+
const REPORT_HELP = `
|
|
20
|
+
REPORT OPTIONS
|
|
21
|
+
<file> Path to a FeatureSet JSON file (positional, required)
|
|
22
|
+
--input, -i <file> Path to FeatureSet JSON file (alternative to positional)
|
|
23
|
+
--output, -o <file> Write output to a file (default: stdout)
|
|
24
|
+
--pretty Pretty-print JSON output
|
|
25
|
+
--help, -h Show this help message
|
|
26
|
+
|
|
27
|
+
EXAMPLES
|
|
28
|
+
perfgraph report ./features.json
|
|
29
|
+
perfgraph report ./features.json --output report.json
|
|
30
|
+
perfgraph report ./features.json --pretty
|
|
31
|
+
`;
|
|
32
|
+
/**
|
|
33
|
+
* Load and validate a FeatureSet from a JSON file.
|
|
34
|
+
*/
|
|
35
|
+
function loadFeatureSet(filePath) {
|
|
36
|
+
const resolved = resolve(filePath);
|
|
37
|
+
if (!existsSync(resolved)) {
|
|
38
|
+
throw new Error(`Error: File not found: ${filePath}`);
|
|
39
|
+
}
|
|
40
|
+
let raw;
|
|
41
|
+
try {
|
|
42
|
+
const content = readFileSync(resolved, 'utf-8');
|
|
43
|
+
raw = JSON.parse(content);
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
throw new Error(`Error: Failed to parse ${filePath}: ${err.message}`);
|
|
47
|
+
}
|
|
48
|
+
const parsed = FeatureSetSchema.safeParse(raw);
|
|
49
|
+
if (!parsed.success) {
|
|
50
|
+
const firstIssue = parsed.error.issues[0];
|
|
51
|
+
throw new Error(`Error: Invalid FeatureSet format in ${filePath}: ${firstIssue?.path.join('.') ?? ''} ${firstIssue?.message ?? ''}`);
|
|
52
|
+
}
|
|
53
|
+
return parsed.data;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Run the report command from a FeatureSet file path.
|
|
57
|
+
*
|
|
58
|
+
* @param inputFile - Path to FeatureSet JSON file
|
|
59
|
+
* @param outputFile - Optional output file path (defaults to stdout)
|
|
60
|
+
* @param pretty - Pretty-print JSON (default: false)
|
|
61
|
+
* @returns ReportResult
|
|
62
|
+
*/
|
|
63
|
+
export async function runReport(inputFile, outputFile, pretty) {
|
|
64
|
+
const features = loadFeatureSet(inputFile);
|
|
65
|
+
const graph = buildCausalGraph(features);
|
|
66
|
+
const report = buildReport(graph, features);
|
|
67
|
+
const indent = pretty ? 2 : 0;
|
|
68
|
+
const json = JSON.stringify(report, null, indent);
|
|
69
|
+
if (outputFile) {
|
|
70
|
+
const { writeFileSync } = await import('node:fs');
|
|
71
|
+
writeFileSync(outputFile, json, 'utf-8');
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
console.log(json);
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
success: true,
|
|
78
|
+
inputFile: resolve(inputFile),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Parse CLI arguments for the report command and execute.
|
|
83
|
+
*/
|
|
84
|
+
export async function runReportFromArgs(args) {
|
|
85
|
+
let inputFile;
|
|
86
|
+
let outputFile;
|
|
87
|
+
let pretty = false;
|
|
88
|
+
for (let i = 0; i < args.length; i++) {
|
|
89
|
+
const arg = args[i];
|
|
90
|
+
switch (arg) {
|
|
91
|
+
case '--input':
|
|
92
|
+
case '-i':
|
|
93
|
+
if (i + 1 >= args.length) {
|
|
94
|
+
console.error('Error: --input requires a value');
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
inputFile = args[++i];
|
|
98
|
+
break;
|
|
99
|
+
case '--output':
|
|
100
|
+
case '-o':
|
|
101
|
+
if (i + 1 >= args.length) {
|
|
102
|
+
console.error('Error: --output requires a value');
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
outputFile = args[++i];
|
|
106
|
+
break;
|
|
107
|
+
case '--pretty':
|
|
108
|
+
pretty = true;
|
|
109
|
+
break;
|
|
110
|
+
case '--help':
|
|
111
|
+
case '-h':
|
|
112
|
+
console.log(REPORT_HELP);
|
|
113
|
+
return null;
|
|
114
|
+
default:
|
|
115
|
+
if (arg.startsWith('--')) {
|
|
116
|
+
console.error(`Error: Unknown flag "${arg}"`);
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
if (!inputFile) {
|
|
120
|
+
inputFile = arg;
|
|
121
|
+
}
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (!inputFile) {
|
|
126
|
+
console.error('Error: <file> is required (positional or --input)');
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
return await runReport(inputFile, outputFile, pretty);
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
console.error(String(err));
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/cli/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `run` subcommand — full pipeline in one command.
|
|
3
|
+
*
|
|
4
|
+
* Chains collect → normalize → extract → analyze → report,
|
|
5
|
+
* writing intermediate artifacts to a temp directory and
|
|
6
|
+
* outputting only the final Report JSON.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* perfgraph run --url <url> [--output <dir>] [--runs <n>] [--pretty]
|
|
10
|
+
*/
|
|
11
|
+
/** Result of the full pipeline execution */
|
|
12
|
+
export interface RunResult {
|
|
13
|
+
/** Whether all pipeline steps succeeded */
|
|
14
|
+
success: boolean;
|
|
15
|
+
/** Path to the generated report file, if any */
|
|
16
|
+
reportFile?: string;
|
|
17
|
+
/** Run output directory path */
|
|
18
|
+
outputDir?: string;
|
|
19
|
+
/** Paths to all written artifacts */
|
|
20
|
+
files?: {
|
|
21
|
+
ir: string;
|
|
22
|
+
features: string;
|
|
23
|
+
graph: string;
|
|
24
|
+
report: string;
|
|
25
|
+
insights: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Execute the full pipeline.
|
|
30
|
+
*
|
|
31
|
+
* @param url - Target URL
|
|
32
|
+
* @param output - Base output directory for collection + final report
|
|
33
|
+
* @param runs - Number of collection runs
|
|
34
|
+
* @param pretty - Pretty-print final report
|
|
35
|
+
* @param flags - boolean flags for skipping collectors
|
|
36
|
+
* @param mobile - Device name for mobile emulation (e.g. "iPhone 13")
|
|
37
|
+
* @returns RunResult
|
|
38
|
+
*/
|
|
39
|
+
export declare function runRun(url: string, output: string, runs: number, pretty: boolean, flags: {
|
|
40
|
+
noLighthouse?: boolean;
|
|
41
|
+
noCoverage?: boolean;
|
|
42
|
+
noConsole?: boolean;
|
|
43
|
+
noDom?: boolean;
|
|
44
|
+
}, mobile?: string): Promise<RunResult | null>;
|
|
45
|
+
/**
|
|
46
|
+
* Parse CLI arguments for the run command and execute.
|
|
47
|
+
*/
|
|
48
|
+
export declare function runRunFromArgs(args: string[]): Promise<RunResult | null>;
|
|
49
|
+
//# sourceMappingURL=run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA6CH,4CAA4C;AAC5C,MAAM,WAAW,SAAS;IACxB,2CAA2C;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,KAAK,CAAC,EAAE;QACN,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,MAAM,CAC1B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,EACf,KAAK,EAAE;IACL,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,EACD,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAyH3B;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAmG3B"}
|