@perfonext/build-mcp 0.2.0 → 0.3.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/README.md +27 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/parser/types.d.ts +41 -0
- package/dist/parser/types.d.ts.map +1 -1
- package/dist/parser/webpack-stats.d.ts +15 -0
- package/dist/parser/webpack-stats.d.ts.map +1 -0
- package/dist/parser/webpack-stats.js +195 -0
- package/dist/parser/webpack-stats.js.map +1 -0
- package/dist/store.d.ts +3 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +7 -0
- package/dist/store.js.map +1 -1
- package/dist/tools/how-to-collect-stats.d.ts +3 -0
- package/dist/tools/how-to-collect-stats.d.ts.map +1 -0
- package/dist/tools/how-to-collect-stats.js +137 -0
- package/dist/tools/how-to-collect-stats.js.map +1 -0
- package/dist/tools/load-webpack-stats.d.ts +3 -0
- package/dist/tools/load-webpack-stats.d.ts.map +1 -0
- package/dist/tools/load-webpack-stats.js +49 -0
- package/dist/tools/load-webpack-stats.js.map +1 -0
- package/dist/tools/trace-import.d.ts +3 -0
- package/dist/tools/trace-import.d.ts.map +1 -0
- package/dist/tools/trace-import.js +41 -0
- package/dist/tools/trace-import.js.map +1 -0
- package/dist/tools/webpack-shared.d.ts +21 -0
- package/dist/tools/webpack-shared.d.ts.map +1 -0
- package/dist/tools/webpack-shared.js +33 -0
- package/dist/tools/webpack-shared.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,17 +12,23 @@
|
|
|
12
12
|
- compares two builds and explains which routes and chunks drove bundle growth, with
|
|
13
13
|
severity-ranked, evidence-backed fix suggestions
|
|
14
14
|
- matches chunks across builds even though Next.js fingerprints filenames with content hashes
|
|
15
|
+
- traces why a given module or npm package is bundled (import chain entry → module) when an
|
|
16
|
+
optional webpack stats file is collected
|
|
15
17
|
- keeps loaded build snapshots in memory so an MCP client can inspect them without re-reading the same build
|
|
16
18
|
|
|
17
19
|
## Inputs
|
|
18
20
|
|
|
19
|
-
The
|
|
21
|
+
The core tools read build artifacts developers already have after running `next build`:
|
|
20
22
|
|
|
21
23
|
- `.next/build-manifest.json`
|
|
22
24
|
- `.next/prerender-manifest.json` when present
|
|
23
25
|
- `.next/app-build-manifest.json` when present
|
|
24
26
|
- optional captured `next build` output text to derive build duration
|
|
25
27
|
|
|
28
|
+
Import-level attribution (`trace_import`) additionally needs a webpack module-stats file at
|
|
29
|
+
`.next/stats.json`. A stock `next build` does not emit one; `how_to_collect_stats` returns the recipe
|
|
30
|
+
to generate it. The manifest tools above never read it, so they work with or without it.
|
|
31
|
+
|
|
26
32
|
## Tools
|
|
27
33
|
|
|
28
34
|
| Tool | Description |
|
|
@@ -32,11 +38,29 @@ The MVP reads build artifacts developers already have after running `next build`
|
|
|
32
38
|
| `get_shared_chunks` | Rank shared chunks by size and show which routes depend on them |
|
|
33
39
|
| `compare_builds` | Compare a baseline and current build snapshot to show which routes and chunks grew or shrank |
|
|
34
40
|
| `explain_growth` | Severity-rank which routes and chunks drove bundle growth between two builds, with evidence-backed fix suggestions |
|
|
41
|
+
| `how_to_collect_stats` | Return the recipe (manual) or an action plan (automatic) to generate `.next/stats.json` |
|
|
42
|
+
| `load_webpack_stats` | Parse `.next/stats.json` and link it to a loaded build; required before `trace_import` |
|
|
43
|
+
| `trace_import` | Explain why a module or npm package is bundled by walking its import chain to the entry |
|
|
35
44
|
|
|
36
45
|
The output stays machine-readable and includes raw byte counts so Copilot can explain regressions, prioritise fixes, and suggest concrete dependency or import-level follow-up.
|
|
37
46
|
|
|
38
47
|
Because Next.js content-hashes emitted filenames (`framework-<hash>.js`, and CSS files named purely by hash), `compare_builds` and `explain_growth` match chunks across builds by a hash-normalized identity. This prevents a rehashed-but-unchanged chunk from being misreported as removed-and-recreated, while still flagging genuinely new chunks.
|
|
39
48
|
|
|
49
|
+
### Deep bundle attribution (optional)
|
|
50
|
+
|
|
51
|
+
The manifest tools work with zero setup. To answer "why is this package bundled?", collect a webpack
|
|
52
|
+
stats file first:
|
|
53
|
+
|
|
54
|
+
1. Call `how_to_collect_stats({ method: 'manual' | 'automatic' })` and apply the returned steps — it
|
|
55
|
+
adds `webpack-stats-plugin`, gates a `next.config` hook behind `ANALYZE=true`, and rebuilds.
|
|
56
|
+
2. Call `load_build_stats({ buildDir })` to get a `buildId`.
|
|
57
|
+
3. Call `load_webpack_stats({ buildId })` to parse the generated `.next/stats.json`.
|
|
58
|
+
4. Call `trace_import({ buildId, moduleName })` to see the import chain that pulls a module in.
|
|
59
|
+
|
|
60
|
+
If the app builds with Turbopack there is no webpack module graph, so `how_to_collect_stats` says so
|
|
61
|
+
and points back to the manifest-only tools. `trace_import` degrades gracefully with a breadcrumb when
|
|
62
|
+
no stats file is loaded — it is never an error.
|
|
63
|
+
|
|
40
64
|
## Install
|
|
41
65
|
|
|
42
66
|
Run directly with `npx`:
|
|
@@ -77,6 +101,8 @@ Add this server to VS Code settings:
|
|
|
77
101
|
- "Summarize the build footprint and tell me which routes ship the most JavaScript."
|
|
78
102
|
- "Compare my baseline and current `.next` builds and show me which routes or shared chunks grew the most."
|
|
79
103
|
- "Explain what grew between my baseline and current `.next` builds and what I should fix first."
|
|
104
|
+
- "Set up webpack stats collection so I can see why a package is bundled."
|
|
105
|
+
- "Why is `axios` in my bundle? Trace its import chain."
|
|
80
106
|
|
|
81
107
|
## Development
|
|
82
108
|
|
package/dist/index.js
CHANGED
|
@@ -6,15 +6,21 @@ import { registerGetLargestRoutes } from './tools/get-largest-routes.js';
|
|
|
6
6
|
import { registerGetSharedChunks } from './tools/get-shared-chunks.js';
|
|
7
7
|
import { registerCompareBuilds } from './tools/compare-builds.js';
|
|
8
8
|
import { registerExplainGrowth } from './tools/explain-growth.js';
|
|
9
|
+
import { registerHowToCollectStats } from './tools/how-to-collect-stats.js';
|
|
10
|
+
import { registerLoadWebpackStats } from './tools/load-webpack-stats.js';
|
|
11
|
+
import { registerTraceImport } from './tools/trace-import.js';
|
|
9
12
|
const server = new McpServer({
|
|
10
13
|
name: 'perfonext-build-mcp',
|
|
11
|
-
version: '0.
|
|
14
|
+
version: '0.3.0',
|
|
12
15
|
});
|
|
13
16
|
registerLoadBuildStats(server);
|
|
14
17
|
registerGetLargestRoutes(server);
|
|
15
18
|
registerGetSharedChunks(server);
|
|
16
19
|
registerCompareBuilds(server);
|
|
17
20
|
registerExplainGrowth(server);
|
|
21
|
+
registerHowToCollectStats(server);
|
|
22
|
+
registerLoadWebpackStats(server);
|
|
23
|
+
registerTraceImport(server);
|
|
18
24
|
const transport = new StdioServerTransport();
|
|
19
25
|
await server.connect(transport);
|
|
20
26
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,qBAAqB;IAC3B,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,sBAAsB,CAAC,MAAM,CAAC,CAAC;AAC/B,wBAAwB,CAAC,MAAM,CAAC,CAAC;AACjC,uBAAuB,CAAC,MAAM,CAAC,CAAC;AAChC,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAC9B,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAC9B,yBAAyB,CAAC,MAAM,CAAC,CAAC;AAClC,wBAAwB,CAAC,MAAM,CAAC,CAAC;AACjC,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAE5B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
package/dist/parser/types.d.ts
CHANGED
|
@@ -128,4 +128,45 @@ export interface GrowthExplanation {
|
|
|
128
128
|
topGrowingChunks: ChunkGrowthContribution[];
|
|
129
129
|
suggestions: GrowthSuggestion[];
|
|
130
130
|
}
|
|
131
|
+
export interface WebpackModuleReason {
|
|
132
|
+
moduleName: string | null;
|
|
133
|
+
userRequest: string | null;
|
|
134
|
+
}
|
|
135
|
+
export interface WebpackModule {
|
|
136
|
+
name: string;
|
|
137
|
+
packageName: string | null;
|
|
138
|
+
sizeBytes: number;
|
|
139
|
+
chunkIds: Array<string | number>;
|
|
140
|
+
reasons: WebpackModuleReason[];
|
|
141
|
+
}
|
|
142
|
+
export interface WebpackChunk {
|
|
143
|
+
id: string | number;
|
|
144
|
+
names: string[];
|
|
145
|
+
files: string[];
|
|
146
|
+
sizeBytes: number;
|
|
147
|
+
}
|
|
148
|
+
export interface ParsedWebpackStats {
|
|
149
|
+
buildId: string;
|
|
150
|
+
statsPath: string;
|
|
151
|
+
modules: WebpackModule[];
|
|
152
|
+
chunks: WebpackChunk[];
|
|
153
|
+
moduleCount: number;
|
|
154
|
+
parsedModuleCount: number;
|
|
155
|
+
}
|
|
156
|
+
export interface ImportChainNode {
|
|
157
|
+
moduleName: string;
|
|
158
|
+
packageName: string | null;
|
|
159
|
+
}
|
|
160
|
+
export interface ImportTrace {
|
|
161
|
+
moduleName: string;
|
|
162
|
+
packageName: string | null;
|
|
163
|
+
sizeBytes: number;
|
|
164
|
+
chunkFiles: string[];
|
|
165
|
+
importChain: ImportChainNode[];
|
|
166
|
+
}
|
|
167
|
+
export interface TraceImportResult {
|
|
168
|
+
query: string;
|
|
169
|
+
matchCount: number;
|
|
170
|
+
traces: ImportTrace[];
|
|
171
|
+
}
|
|
131
172
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/parser/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC;AAErD,MAAM,MAAM,sBAAsB,GAAG,KAAK,GAAG,gBAAgB,GAAG,mBAAmB,GAAG,IAAI,CAAC;AAE3F,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,sBAAsB,EAAE,sBAAsB,CAAC;IAC/C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,sBAAsB,EAAE,sBAAsB,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,uBAAuB,EAAE,MAAM,CAAC;IAChC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,wBAAwB,EAAE,MAAM,CAAC;IACjC,uBAAuB,EAAE,MAAM,CAAC;IAChC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,WAAW,EAAE,eAAe,EAAE,CAAC;CAChC;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;AAE7D,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,cAAc,CAAC;IACzB,qBAAqB,EAAE,uBAAuB,EAAE,CAAC;CAClD;AAED,MAAM,WAAW,oBAAoB;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,EAAE,cAAc,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,oBAAoB,GAC5B,qBAAqB,GACrB,WAAW,GACX,cAAc,GACd,kBAAkB,CAAC;AAEvB,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,aAAa,EAAE,kBAAkB,EAAE,CAAC;IACpC,gBAAgB,EAAE,uBAAuB,EAAE,CAAC;IAC5C,WAAW,EAAE,gBAAgB,EAAE,CAAC;CACjC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/parser/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ParsedWebpackStats, TraceImportResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the npm package an emitted module belongs to. Uses the LAST `node_modules/` segment so
|
|
4
|
+
* nested installs (`a/node_modules/b`) attribute to the inner package, and preserves scoped names
|
|
5
|
+
* (`@org/pkg`). Returns null for first-party application code.
|
|
6
|
+
*/
|
|
7
|
+
export declare function extractPackageName(moduleName: string): string | null;
|
|
8
|
+
/**
|
|
9
|
+
* Parse a webpack module-stats JSON (`.next/stats.json`) into a compact, analysis-ready shape.
|
|
10
|
+
* Only the fields the attribution tools need are retained — raw source, asset maps, and other
|
|
11
|
+
* webpack noise are dropped so a multi-MB stats file stays small in memory.
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseWebpackStats(buildDirPath: string, buildId: string): Promise<ParsedWebpackStats | null>;
|
|
14
|
+
export declare function traceImport(stats: ParsedWebpackStats, moduleName: string, limit?: number): TraceImportResult;
|
|
15
|
+
//# sourceMappingURL=webpack-stats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webpack-stats.d.ts","sourceRoot":"","sources":["../../src/parser/webpack-stats.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGV,kBAAkB,EAClB,iBAAiB,EAIlB,MAAM,YAAY,CAAC;AA6CpB;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAoBpE;AA4DD;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CA2CpC;AAmED,wBAAgB,WAAW,CACzB,KAAK,EAAE,kBAAkB,EACzB,UAAU,EAAE,MAAM,EAClB,KAAK,SAAK,GACT,iBAAiB,CAsBnB"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { join, resolve } from 'node:path';
|
|
3
|
+
const NODE_MODULES_MARKER = 'node_modules/';
|
|
4
|
+
function isRecord(value) {
|
|
5
|
+
return value !== null && typeof value === 'object';
|
|
6
|
+
}
|
|
7
|
+
function toFiniteNumber(value) {
|
|
8
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : 0;
|
|
9
|
+
}
|
|
10
|
+
function toStringArray(value) {
|
|
11
|
+
if (!Array.isArray(value)) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
return value.filter((item) => typeof item === 'string');
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the npm package an emitted module belongs to. Uses the LAST `node_modules/` segment so
|
|
18
|
+
* nested installs (`a/node_modules/b`) attribute to the inner package, and preserves scoped names
|
|
19
|
+
* (`@org/pkg`). Returns null for first-party application code.
|
|
20
|
+
*/
|
|
21
|
+
export function extractPackageName(moduleName) {
|
|
22
|
+
// Webpack `name` uses POSIX separators, but the `identifier` fallback can carry
|
|
23
|
+
// Windows backslashes — normalize so attribution works on every platform.
|
|
24
|
+
const normalized = moduleName.replace(/\\/g, '/');
|
|
25
|
+
const markerIndex = normalized.lastIndexOf(NODE_MODULES_MARKER);
|
|
26
|
+
if (markerIndex === -1) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const rest = normalized.slice(markerIndex + NODE_MODULES_MARKER.length);
|
|
30
|
+
const parts = rest.split('/').filter(Boolean);
|
|
31
|
+
if (parts.length === 0) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
if (parts[0].startsWith('@') && parts.length >= 2) {
|
|
35
|
+
return `${parts[0]}/${parts[1]}`;
|
|
36
|
+
}
|
|
37
|
+
return parts[0];
|
|
38
|
+
}
|
|
39
|
+
function normalizeReason(raw) {
|
|
40
|
+
if (!isRecord(raw)) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const moduleName = typeof raw.moduleName === 'string' ? raw.moduleName : null;
|
|
44
|
+
const userRequest = typeof raw.userRequest === 'string' ? raw.userRequest : null;
|
|
45
|
+
if (moduleName === null && userRequest === null) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return { moduleName, userRequest };
|
|
49
|
+
}
|
|
50
|
+
function normalizeModule(raw) {
|
|
51
|
+
const name = typeof raw.name === 'string'
|
|
52
|
+
? raw.name
|
|
53
|
+
: typeof raw.identifier === 'string'
|
|
54
|
+
? raw.identifier
|
|
55
|
+
: null;
|
|
56
|
+
if (!name) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const chunkIds = Array.isArray(raw.chunks)
|
|
60
|
+
? raw.chunks.filter((id) => typeof id === 'string' || typeof id === 'number')
|
|
61
|
+
: [];
|
|
62
|
+
const reasons = Array.isArray(raw.reasons)
|
|
63
|
+
? raw.reasons
|
|
64
|
+
.map(normalizeReason)
|
|
65
|
+
.filter((reason) => reason !== null)
|
|
66
|
+
: [];
|
|
67
|
+
return {
|
|
68
|
+
name,
|
|
69
|
+
packageName: extractPackageName(name),
|
|
70
|
+
sizeBytes: toFiniteNumber(raw.size),
|
|
71
|
+
chunkIds,
|
|
72
|
+
reasons,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function normalizeChunk(raw) {
|
|
76
|
+
if (raw.id === undefined || (typeof raw.id !== 'string' && typeof raw.id !== 'number')) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
id: raw.id,
|
|
81
|
+
names: toStringArray(raw.names),
|
|
82
|
+
files: toStringArray(raw.files),
|
|
83
|
+
sizeBytes: toFiniteNumber(raw.size),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Parse a webpack module-stats JSON (`.next/stats.json`) into a compact, analysis-ready shape.
|
|
88
|
+
* Only the fields the attribution tools need are retained — raw source, asset maps, and other
|
|
89
|
+
* webpack noise are dropped so a multi-MB stats file stays small in memory.
|
|
90
|
+
*/
|
|
91
|
+
export async function parseWebpackStats(buildDirPath, buildId) {
|
|
92
|
+
const buildDir = resolve(buildDirPath);
|
|
93
|
+
const statsPath = join(buildDir, 'stats.json');
|
|
94
|
+
let content;
|
|
95
|
+
try {
|
|
96
|
+
content = await readFile(statsPath, 'utf-8');
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
if (error.code === 'ENOENT') {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
let raw;
|
|
105
|
+
try {
|
|
106
|
+
raw = JSON.parse(content);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
throw new Error(`Failed to parse webpack stats JSON at ${statsPath} (build "${buildId}"): ${error.message}`);
|
|
110
|
+
}
|
|
111
|
+
const rawModules = Array.isArray(raw.modules) ? raw.modules : [];
|
|
112
|
+
const rawChunks = Array.isArray(raw.chunks) ? raw.chunks : [];
|
|
113
|
+
const modules = rawModules
|
|
114
|
+
.map(module => normalizeModule(module))
|
|
115
|
+
.filter((module) => module !== null);
|
|
116
|
+
const chunks = rawChunks
|
|
117
|
+
.map(chunk => normalizeChunk(chunk))
|
|
118
|
+
.filter((chunk) => chunk !== null);
|
|
119
|
+
return {
|
|
120
|
+
buildId,
|
|
121
|
+
statsPath,
|
|
122
|
+
modules,
|
|
123
|
+
chunks,
|
|
124
|
+
moduleCount: rawModules.length,
|
|
125
|
+
parsedModuleCount: modules.length,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function buildModuleIndex(stats) {
|
|
129
|
+
const index = new Map();
|
|
130
|
+
for (const module of stats.modules) {
|
|
131
|
+
index.set(module.name, module);
|
|
132
|
+
}
|
|
133
|
+
return index;
|
|
134
|
+
}
|
|
135
|
+
function chunkFilesForModule(module, chunkById) {
|
|
136
|
+
const files = new Set();
|
|
137
|
+
for (const chunkId of module.chunkIds) {
|
|
138
|
+
const chunk = chunkById.get(chunkId);
|
|
139
|
+
for (const file of chunk?.files ?? []) {
|
|
140
|
+
files.add(file);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return Array.from(files).sort();
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Walk a module's `reasons` upward to the nearest entry to explain why it is bundled. Picks the
|
|
147
|
+
* first resolvable parent at each step, guards against cycles, and caps depth so a pathological
|
|
148
|
+
* graph cannot loop. Returns the chain ordered from entry → target.
|
|
149
|
+
*/
|
|
150
|
+
function buildImportChain(target, moduleIndex) {
|
|
151
|
+
const chain = [
|
|
152
|
+
{ moduleName: target.name, packageName: target.packageName },
|
|
153
|
+
];
|
|
154
|
+
const visited = new Set([target.name]);
|
|
155
|
+
let current = target;
|
|
156
|
+
const maxDepth = 25;
|
|
157
|
+
for (let depth = 0; depth < maxDepth; depth += 1) {
|
|
158
|
+
const parentReason = current.reasons.find(reason => reason.moduleName !== null && !visited.has(reason.moduleName));
|
|
159
|
+
if (!parentReason || parentReason.moduleName === null) {
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
const parent = moduleIndex.get(parentReason.moduleName);
|
|
163
|
+
visited.add(parentReason.moduleName);
|
|
164
|
+
chain.push({
|
|
165
|
+
moduleName: parentReason.moduleName,
|
|
166
|
+
packageName: parent?.packageName ?? extractPackageName(parentReason.moduleName),
|
|
167
|
+
});
|
|
168
|
+
if (!parent || parent.reasons.length === 0) {
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
current = parent;
|
|
172
|
+
}
|
|
173
|
+
return chain.reverse();
|
|
174
|
+
}
|
|
175
|
+
export function traceImport(stats, moduleName, limit = 10) {
|
|
176
|
+
const query = moduleName.toLowerCase();
|
|
177
|
+
const moduleIndex = buildModuleIndex(stats);
|
|
178
|
+
const chunkById = new Map(stats.chunks.map(chunk => [chunk.id, chunk]));
|
|
179
|
+
const matches = stats.modules
|
|
180
|
+
.filter(module => module.name.toLowerCase().includes(query))
|
|
181
|
+
.sort((left, right) => right.sizeBytes - left.sizeBytes);
|
|
182
|
+
const traces = matches.slice(0, limit).map(module => ({
|
|
183
|
+
moduleName: module.name,
|
|
184
|
+
packageName: module.packageName,
|
|
185
|
+
sizeBytes: module.sizeBytes,
|
|
186
|
+
chunkFiles: chunkFilesForModule(module, chunkById),
|
|
187
|
+
importChain: buildImportChain(module, moduleIndex),
|
|
188
|
+
}));
|
|
189
|
+
return {
|
|
190
|
+
query: moduleName,
|
|
191
|
+
matchCount: matches.length,
|
|
192
|
+
traces,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=webpack-stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webpack-stats.js","sourceRoot":"","sources":["../../src/parser/webpack-stats.ts"],"names":[],"mappings":"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"}
|
package/dist/store.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import type { ParsedBuildStats } from './parser/types.js';
|
|
1
|
+
import type { ParsedBuildStats, ParsedWebpackStats } from './parser/types.js';
|
|
2
2
|
export declare function storeBuildStats(build: ParsedBuildStats): void;
|
|
3
3
|
export declare function getBuildStats(id: string): ParsedBuildStats | undefined;
|
|
4
|
+
export declare function storeWebpackStats(stats: ParsedWebpackStats): void;
|
|
5
|
+
export declare function getWebpackStats(buildId: string): ParsedWebpackStats | undefined;
|
|
4
6
|
export declare function listBuildStats(): Array<{
|
|
5
7
|
id: string;
|
|
6
8
|
buildDir: string;
|
package/dist/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAK9E,wBAAgB,eAAe,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAE7D;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAEtE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAEjE;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAE/E;AAED,wBAAgB,cAAc,IAAI,KAAK,CAAC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC,CASD"}
|
package/dist/store.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
const builds = new Map();
|
|
2
|
+
const webpackStats = new Map();
|
|
2
3
|
export function storeBuildStats(build) {
|
|
3
4
|
builds.set(build.id, build);
|
|
4
5
|
}
|
|
5
6
|
export function getBuildStats(id) {
|
|
6
7
|
return builds.get(id);
|
|
7
8
|
}
|
|
9
|
+
export function storeWebpackStats(stats) {
|
|
10
|
+
webpackStats.set(stats.buildId, stats);
|
|
11
|
+
}
|
|
12
|
+
export function getWebpackStats(buildId) {
|
|
13
|
+
return webpackStats.get(buildId);
|
|
14
|
+
}
|
|
8
15
|
export function listBuildStats() {
|
|
9
16
|
return Array.from(builds.values()).map(build => ({
|
|
10
17
|
id: build.id,
|
package/dist/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,GAAG,IAAI,GAAG,EAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,GAAG,IAAI,GAAG,EAA4B,CAAC;AACnD,MAAM,YAAY,GAAG,IAAI,GAAG,EAA8B,CAAC;AAE3D,MAAM,UAAU,eAAe,CAAC,KAAuB;IACrD,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAU;IACtC,OAAO,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAyB;IACzD,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,OAAO,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,cAAc;IAQ5B,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC/C,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM;QAC/B,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM;QAC/B,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,WAAW,EAAE,KAAK,CAAC,WAAW;KAC/B,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"how-to-collect-stats.d.ts","sourceRoot":"","sources":["../../src/tools/how-to-collect-stats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4HpE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8BjE"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const NEXT_CONFIG_WEBPACK_SNIPPET = `// next.config.ts — write .next/stats.json only when ANALYZE=true
|
|
3
|
+
import type { NextConfig } from "next";
|
|
4
|
+
import { StatsWriterPlugin } from "webpack-stats-plugin";
|
|
5
|
+
|
|
6
|
+
const nextConfig: NextConfig = {
|
|
7
|
+
webpack(config) {
|
|
8
|
+
if (process.env.ANALYZE === "true") {
|
|
9
|
+
config.plugins.push(
|
|
10
|
+
new StatsWriterPlugin({
|
|
11
|
+
filename: "stats.json", // -> .next/stats.json
|
|
12
|
+
// ids + large modulesSpace are required: without them webpack drops
|
|
13
|
+
// chunk ids and collapses the module list, yielding empty attribution.
|
|
14
|
+
stats: {
|
|
15
|
+
all: false,
|
|
16
|
+
modules: true,
|
|
17
|
+
chunks: true,
|
|
18
|
+
chunkModules: true,
|
|
19
|
+
reasons: true,
|
|
20
|
+
ids: true,
|
|
21
|
+
nestedModules: true,
|
|
22
|
+
modulesSpace: Infinity,
|
|
23
|
+
chunkModulesSpace: Infinity,
|
|
24
|
+
},
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
return config;
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default nextConfig;`;
|
|
33
|
+
function buildManualResponse(scenario) {
|
|
34
|
+
if (scenario === 'turbopack') {
|
|
35
|
+
return turbopackResponse();
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
method: 'manual',
|
|
39
|
+
steps: [
|
|
40
|
+
{
|
|
41
|
+
step: 1,
|
|
42
|
+
title: 'Add the dev dependency',
|
|
43
|
+
command: 'npm install --save-dev webpack-stats-plugin',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
step: 2,
|
|
47
|
+
title: 'Emit stats behind an ANALYZE flag in next.config',
|
|
48
|
+
snippet: NEXT_CONFIG_WEBPACK_SNIPPET,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
step: 3,
|
|
52
|
+
title: 'Build with the flag set',
|
|
53
|
+
command: 'ANALYZE=true next build',
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
producesFile: '.next/stats.json',
|
|
57
|
+
nextStep: 'Once .next/stats.json exists, call load_webpack_stats with the same buildDir and the buildId from load_build_stats.',
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function buildAutomaticResponse(scenario) {
|
|
61
|
+
if (scenario === 'turbopack') {
|
|
62
|
+
return turbopackResponse();
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
method: 'automatic',
|
|
66
|
+
actions: [
|
|
67
|
+
{
|
|
68
|
+
action: 'add-dev-dependency',
|
|
69
|
+
run: 'npm install --save-dev webpack-stats-plugin',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
action: 'edit-next-config',
|
|
73
|
+
description: 'Add a webpack hook gated behind ANALYZE=true that writes .next/stats.json.',
|
|
74
|
+
snippet: NEXT_CONFIG_WEBPACK_SNIPPET,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
action: 'add-package-script',
|
|
78
|
+
script: { analyze: 'ANALYZE=true next build' },
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
action: 'run-build',
|
|
82
|
+
run: 'npm run analyze',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
action: 'verify-output',
|
|
86
|
+
description: 'Confirm .next/stats.json exists before loading it.',
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
producesFile: '.next/stats.json',
|
|
90
|
+
nextStep: 'After .next/stats.json exists, call load_webpack_stats with the same buildDir and the buildId from load_build_stats.',
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function turbopackResponse() {
|
|
94
|
+
return {
|
|
95
|
+
method: 'unavailable',
|
|
96
|
+
scenario: 'turbopack',
|
|
97
|
+
summary: 'Turbopack has no webpack module graph, so .next/stats.json cannot be produced and trace_import cannot run.',
|
|
98
|
+
guidance: 'Run a one-off webpack build (omit --turbopack) with the stats hook to use trace_import, or stay on the manifest-only tools.',
|
|
99
|
+
manifestOnlyTools: [
|
|
100
|
+
'load_build_stats',
|
|
101
|
+
'get_largest_routes',
|
|
102
|
+
'get_shared_chunks',
|
|
103
|
+
'compare_builds',
|
|
104
|
+
'explain_growth',
|
|
105
|
+
],
|
|
106
|
+
nextStep: 'Rebuild with webpack to produce .next/stats.json, or continue with get_largest_routes / get_shared_chunks on the build you already loaded.',
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export function registerHowToCollectStats(server) {
|
|
110
|
+
server.registerTool('how_to_collect_stats', {
|
|
111
|
+
title: 'How To Collect Webpack Stats',
|
|
112
|
+
description: 'Explain how to generate the webpack stats file (.next/stats.json) required by the bundle attribution ' +
|
|
113
|
+
'tools. Choose manual (a recipe you apply yourself) or automatic (an action plan Copilot executes).',
|
|
114
|
+
inputSchema: {
|
|
115
|
+
method: z
|
|
116
|
+
.enum(['manual', 'automatic'])
|
|
117
|
+
.describe('manual: return a recipe to apply yourself. automatic: return an action plan for Copilot to execute.'),
|
|
118
|
+
scenario: z
|
|
119
|
+
.enum(['webpack', 'turbopack'])
|
|
120
|
+
.optional()
|
|
121
|
+
.describe('Collection context. Defaults to webpack. Use turbopack if the app builds with --turbopack.'),
|
|
122
|
+
},
|
|
123
|
+
}, async ({ method, scenario }) => {
|
|
124
|
+
const resolvedScenario = scenario ?? 'webpack';
|
|
125
|
+
const resolvedMethod = method;
|
|
126
|
+
const payload = resolvedMethod === 'manual'
|
|
127
|
+
? buildManualResponse(resolvedScenario)
|
|
128
|
+
: buildAutomaticResponse(resolvedScenario);
|
|
129
|
+
return {
|
|
130
|
+
content: [{
|
|
131
|
+
type: 'text',
|
|
132
|
+
text: JSON.stringify(payload, null, 2),
|
|
133
|
+
}],
|
|
134
|
+
};
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=how-to-collect-stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"how-to-collect-stats.js","sourceRoot":"","sources":["../../src/tools/how-to-collect-stats.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BA8BT,CAAC;AAE5B,SAAS,mBAAmB,CAAC,QAA4B;IACvD,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;QAC7B,OAAO,iBAAiB,EAAE,CAAC;IAC7B,CAAC;IAED,OAAO;QACL,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,CAAC;gBACP,KAAK,EAAE,wBAAwB;gBAC/B,OAAO,EAAE,6CAA6C;aACvD;YACD;gBACE,IAAI,EAAE,CAAC;gBACP,KAAK,EAAE,kDAAkD;gBACzD,OAAO,EAAE,2BAA2B;aACrC;YACD;gBACE,IAAI,EAAE,CAAC;gBACP,KAAK,EAAE,yBAAyB;gBAChC,OAAO,EAAE,yBAAyB;aACnC;SACF;QACD,YAAY,EAAE,kBAAkB;QAChC,QAAQ,EACN,qHAAqH;KACxH,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,QAA4B;IAC1D,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;QAC7B,OAAO,iBAAiB,EAAE,CAAC;IAC7B,CAAC;IAED,OAAO;QACL,MAAM,EAAE,WAAW;QACnB,OAAO,EAAE;YACP;gBACE,MAAM,EAAE,oBAAoB;gBAC5B,GAAG,EAAE,6CAA6C;aACnD;YACD;gBACE,MAAM,EAAE,kBAAkB;gBAC1B,WAAW,EAAE,4EAA4E;gBACzF,OAAO,EAAE,2BAA2B;aACrC;YACD;gBACE,MAAM,EAAE,oBAAoB;gBAC5B,MAAM,EAAE,EAAE,OAAO,EAAE,yBAAyB,EAAE;aAC/C;YACD;gBACE,MAAM,EAAE,WAAW;gBACnB,GAAG,EAAE,iBAAiB;aACvB;YACD;gBACE,MAAM,EAAE,eAAe;gBACvB,WAAW,EAAE,oDAAoD;aAClE;SACF;QACD,YAAY,EAAE,kBAAkB;QAChC,QAAQ,EACN,sHAAsH;KACzH,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO;QACL,MAAM,EAAE,aAAa;QACrB,QAAQ,EAAE,WAAW;QACrB,OAAO,EACL,4GAA4G;QAC9G,QAAQ,EACN,6HAA6H;QAC/H,iBAAiB,EAAE;YACjB,kBAAkB;YAClB,oBAAoB;YACpB,mBAAmB;YACnB,gBAAgB;YAChB,gBAAgB;SACjB;QACD,QAAQ,EACN,4IAA4I;KAC/I,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,MAAiB;IACzD,MAAM,CAAC,YAAY,CAAC,sBAAsB,EAAE;QAC1C,KAAK,EAAE,8BAA8B;QACrC,WAAW,EACT,uGAAuG;YACvG,oGAAoG;QACtG,WAAW,EAAE;YACX,MAAM,EAAE,CAAC;iBACN,IAAI,CAAC,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;iBAC7B,QAAQ,CAAC,qGAAqG,CAAC;YAClH,QAAQ,EAAE,CAAC;iBACR,IAAI,CAAC,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;iBAC9B,QAAQ,EAAE;iBACV,QAAQ,CAAC,4FAA4F,CAAC;SAC1G;KACF,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;QAChC,MAAM,gBAAgB,GAAuB,QAAQ,IAAI,SAAS,CAAC;QACnE,MAAM,cAAc,GAAqB,MAAM,CAAC;QAChD,MAAM,OAAO,GACX,cAAc,KAAK,QAAQ;YACzB,CAAC,CAAC,mBAAmB,CAAC,gBAAgB,CAAC;YACvC,CAAC,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;QAE/C,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;iBACvC,CAAC;SACH,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-webpack-stats.d.ts","sourceRoot":"","sources":["../../src/tools/load-webpack-stats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAOpE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+ChE"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { parseWebpackStats } from '../parser/webpack-stats.js';
|
|
3
|
+
import { getBuildStats, storeWebpackStats } from '../store.js';
|
|
4
|
+
import { statsTextResult } from './webpack-shared.js';
|
|
5
|
+
export function registerLoadWebpackStats(server) {
|
|
6
|
+
server.registerTool('load_webpack_stats', {
|
|
7
|
+
title: 'Load Webpack Stats',
|
|
8
|
+
description: 'Parse the webpack module stats file (.next/stats.json) and link it to a build loaded with ' +
|
|
9
|
+
'load_build_stats. Required before trace_import.',
|
|
10
|
+
inputSchema: {
|
|
11
|
+
buildId: z.string().describe('Build ID returned by load_build_stats; the stats.json is read from that build directory'),
|
|
12
|
+
},
|
|
13
|
+
}, async ({ buildId }) => {
|
|
14
|
+
const build = getBuildStats(buildId);
|
|
15
|
+
if (!build) {
|
|
16
|
+
throw new Error(`Build "${buildId}" not found. Call load_build_stats first and pass the buildId it returns.`);
|
|
17
|
+
}
|
|
18
|
+
const stats = await parseWebpackStats(build.buildDir, buildId);
|
|
19
|
+
if (!stats) {
|
|
20
|
+
return statsTextResult({
|
|
21
|
+
buildId,
|
|
22
|
+
webpackStatsLoaded: false,
|
|
23
|
+
message: `No stats.json found in ${build.buildDir}. A stock next build does not emit one.`,
|
|
24
|
+
nextStep: 'Call how_to_collect_stats to generate .next/stats.json, then load_webpack_stats again.',
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
storeWebpackStats(stats);
|
|
28
|
+
const looksCollapsed = stats.parsedModuleCount === 0 || stats.chunks.length === 0;
|
|
29
|
+
return statsTextResult({
|
|
30
|
+
buildId,
|
|
31
|
+
webpackStatsLoaded: true,
|
|
32
|
+
statsPath: stats.statsPath,
|
|
33
|
+
moduleCount: stats.moduleCount,
|
|
34
|
+
parsedModuleCount: stats.parsedModuleCount,
|
|
35
|
+
chunkCount: stats.chunks.length,
|
|
36
|
+
...(looksCollapsed
|
|
37
|
+
? {
|
|
38
|
+
warning: 'The stats file parsed but contains no usable modules/chunks. This usually means the stats ' +
|
|
39
|
+
'config collapsed the module graph (webpack groups modules once `modulesSpace` is exceeded and ' +
|
|
40
|
+
'omits chunk ids unless `ids: true`). Re-run how_to_collect_stats for the corrected config and rebuild.',
|
|
41
|
+
}
|
|
42
|
+
: {}),
|
|
43
|
+
nextStep: looksCollapsed
|
|
44
|
+
? 'Call how_to_collect_stats again, apply the corrected stats config, rebuild, then load_webpack_stats.'
|
|
45
|
+
: 'Now call trace_import with a module or package name (e.g. a heavy dependency) to see why it is bundled.',
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=load-webpack-stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-webpack-stats.js","sourceRoot":"","sources":["../../src/tools/load-webpack-stats.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,MAAM,UAAU,wBAAwB,CAAC,MAAiB;IACxD,MAAM,CAAC,YAAY,CAAC,oBAAoB,EAAE;QACxC,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EACT,4FAA4F;YAC5F,iDAAiD;QACnD,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yFAAyF,CAAC;SACxH;KACF,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QACvB,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,UAAU,OAAO,2EAA2E,CAAC,CAAC;QAChH,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC/D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,eAAe,CAAC;gBACrB,OAAO;gBACP,kBAAkB,EAAE,KAAK;gBACzB,OAAO,EAAE,0BAA0B,KAAK,CAAC,QAAQ,yCAAyC;gBAC1F,QAAQ,EAAE,wFAAwF;aACnG,CAAC,CAAC;QACL,CAAC;QAED,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACzB,MAAM,cAAc,GAAG,KAAK,CAAC,iBAAiB,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;QAClF,OAAO,eAAe,CAAC;YACrB,OAAO;YACP,kBAAkB,EAAE,IAAI;YACxB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;YAC1C,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM;YAC/B,GAAG,CAAC,cAAc;gBAChB,CAAC,CAAC;oBACE,OAAO,EACL,4FAA4F;wBAC5F,gGAAgG;wBAChG,wGAAwG;iBAC3G;gBACH,CAAC,CAAC,EAAE,CAAC;YACP,QAAQ,EAAE,cAAc;gBACtB,CAAC,CAAC,sGAAsG;gBACxG,CAAC,CAAC,yGAAyG;SAC9G,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-import.d.ts","sourceRoot":"","sources":["../../src/tools/trace-import.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAQpE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAqC3D"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { formatBytes } from '../format.js';
|
|
3
|
+
import { traceImport } from '../parser/webpack-stats.js';
|
|
4
|
+
import { getBuildStats } from '../store.js';
|
|
5
|
+
import { resolveWebpackStats, statsTextResult } from './webpack-shared.js';
|
|
6
|
+
export function registerTraceImport(server) {
|
|
7
|
+
server.registerTool('trace_import', {
|
|
8
|
+
title: 'Trace Import',
|
|
9
|
+
description: 'Explain why a module is bundled by tracing its import chain from an entry point to the module. ' +
|
|
10
|
+
'Requires load_webpack_stats first.',
|
|
11
|
+
inputSchema: {
|
|
12
|
+
buildId: z.string().describe('Build ID returned by load_build_stats'),
|
|
13
|
+
moduleName: z.string().describe('Module or package name to search for (case-insensitive substring), e.g. "lodash"'),
|
|
14
|
+
limit: z.number().int().positive().max(25).optional().describe('Maximum matching modules to trace. Defaults to 10.'),
|
|
15
|
+
},
|
|
16
|
+
}, async ({ buildId, moduleName, limit }) => {
|
|
17
|
+
const build = getBuildStats(buildId);
|
|
18
|
+
if (!build) {
|
|
19
|
+
throw new Error(`Build "${buildId}" not found. Call load_build_stats first.`);
|
|
20
|
+
}
|
|
21
|
+
const resolved = resolveWebpackStats(buildId);
|
|
22
|
+
if ('breadcrumb' in resolved) {
|
|
23
|
+
return statsTextResult(resolved.breadcrumb);
|
|
24
|
+
}
|
|
25
|
+
const result = traceImport(resolved.stats, moduleName, limit ?? 10);
|
|
26
|
+
return statsTextResult({
|
|
27
|
+
buildId,
|
|
28
|
+
query: result.query,
|
|
29
|
+
matchCount: result.matchCount,
|
|
30
|
+
traces: result.traces.map(trace => ({
|
|
31
|
+
moduleName: trace.moduleName,
|
|
32
|
+
packageName: trace.packageName,
|
|
33
|
+
sizeBytes: trace.sizeBytes,
|
|
34
|
+
sizeBytesText: formatBytes(trace.sizeBytes),
|
|
35
|
+
chunkFiles: trace.chunkFiles,
|
|
36
|
+
importChain: trace.importChain,
|
|
37
|
+
})),
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=trace-import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-import.js","sourceRoot":"","sources":["../../src/tools/trace-import.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3E,MAAM,UAAU,mBAAmB,CAAC,MAAiB;IACnD,MAAM,CAAC,YAAY,CAAC,cAAc,EAAE;QAClC,KAAK,EAAE,cAAc;QACrB,WAAW,EACT,iGAAiG;YACjG,oCAAoC;QACtC,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;YACrE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kFAAkF,CAAC;YACnH,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oDAAoD,CAAC;SACrH;KACF,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE;QAC1C,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,UAAU,OAAO,2CAA2C,CAAC,CAAC;QAChF,CAAC;QAED,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,YAAY,IAAI,QAAQ,EAAE,CAAC;YAC7B,OAAO,eAAe,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC9C,CAAC;QAED,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QACpE,OAAO,eAAe,CAAC;YACrB,OAAO;YACP,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAClC,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,aAAa,EAAE,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC;gBAC3C,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,WAAW,EAAE,KAAK,CAAC,WAAW;aAC/B,CAAC,CAAC;SACJ,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ParsedWebpackStats } from '../parser/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve loaded webpack stats for a build, or a machine-readable breadcrumb when they are absent.
|
|
4
|
+
* The attribution tools degrade gracefully: a missing stats file is guidance, not an error.
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveWebpackStats(buildId: string): {
|
|
7
|
+
stats: ParsedWebpackStats;
|
|
8
|
+
} | {
|
|
9
|
+
breadcrumb: Record<string, unknown>;
|
|
10
|
+
};
|
|
11
|
+
export declare function statsTextResult(payload: Record<string, unknown>): {
|
|
12
|
+
content: {
|
|
13
|
+
type: "text";
|
|
14
|
+
text: string;
|
|
15
|
+
}[];
|
|
16
|
+
};
|
|
17
|
+
export declare function withBytesText(bytes: number): {
|
|
18
|
+
sizeBytes: number;
|
|
19
|
+
sizeBytesText: string;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=webpack-shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webpack-shared.d.ts","sourceRoot":"","sources":["../../src/tools/webpack-shared.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,GACd;IAAE,KAAK,EAAE,kBAAkB,CAAA;CAAE,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAiBzE;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;EAO/D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAEzF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { formatBytes } from '../format.js';
|
|
2
|
+
import { getWebpackStats } from '../store.js';
|
|
3
|
+
/**
|
|
4
|
+
* Resolve loaded webpack stats for a build, or a machine-readable breadcrumb when they are absent.
|
|
5
|
+
* The attribution tools degrade gracefully: a missing stats file is guidance, not an error.
|
|
6
|
+
*/
|
|
7
|
+
export function resolveWebpackStats(buildId) {
|
|
8
|
+
const stats = getWebpackStats(buildId);
|
|
9
|
+
if (stats) {
|
|
10
|
+
return { stats };
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
breadcrumb: {
|
|
14
|
+
buildId,
|
|
15
|
+
webpackStatsLoaded: false,
|
|
16
|
+
message: 'Webpack module stats are not loaded for this build, so import-level attribution is unavailable.',
|
|
17
|
+
nextStep: 'Generate .next/stats.json via how_to_collect_stats, then call load_webpack_stats with this buildId. ' +
|
|
18
|
+
'The manifest-based tools (get_largest_routes, get_shared_chunks, compare_builds, explain_growth) work without it.',
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function statsTextResult(payload) {
|
|
23
|
+
return {
|
|
24
|
+
content: [{
|
|
25
|
+
type: 'text',
|
|
26
|
+
text: JSON.stringify(payload, null, 2),
|
|
27
|
+
}],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function withBytesText(bytes) {
|
|
31
|
+
return { sizeBytes: bytes, sizeBytesText: formatBytes(bytes) };
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=webpack-shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webpack-shared.js","sourceRoot":"","sources":["../../src/tools/webpack-shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAe;IAEf,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC;IAED,OAAO;QACL,UAAU,EAAE;YACV,OAAO;YACP,kBAAkB,EAAE,KAAK;YACzB,OAAO,EACL,iGAAiG;YACnG,QAAQ,EACN,sGAAsG;gBACtG,mHAAmH;SACtH;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAgC;IAC9D,OAAO;QACL,OAAO,EAAE,CAAC;gBACR,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;aACvC,CAAC;KACH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;AACjE,CAAC"}
|