@statoscope/webpack-model
Advanced tools
Comparing version 5.5.1 to 5.6.0
import type { Size } from '@statoscope/stats-extension-compressed/dist/generator'; | ||
import type { Instance } from '@statoscope/stats-extension-package-info/dist/generator'; | ||
import Graph, { PathSolution } from '@statoscope/helpers/dist/graph'; | ||
import { Webpack } from '../webpack'; | ||
import { moduleNameResource, moduleReasonResource, moduleResource, nodeModule } from './module'; | ||
import { HandledCompilation, NormalizedAsset, NormalizedChunk, NormalizedCompilation, NormalizedFile, NormalizedModule, NormalizedPackage } from './normalize'; | ||
import { Node } from './modules-to-foam-tree'; | ||
import { HandledCompilation, ModuleGraphNodeData, NormalizedAsset, NormalizedChunk, NormalizedCompilation, NormalizedEntrypointItem, NormalizedFile, NormalizedModule, NormalizedPackage } from './normalize'; | ||
import { Node as FoamTreeNode } from './modules-to-foam-tree'; | ||
import ChunkID = Webpack.ChunkID; | ||
@@ -31,3 +32,6 @@ export declare type ResolvedStats = { | ||
statName(stat?: ResolvedStats | undefined): string; | ||
modulesToFoamTree(modules: NormalizedModule[], compressed?: boolean | undefined, hash?: string | undefined): Node; | ||
getModuleGraph(hash: string): Graph<ModuleGraphNodeData> | null; | ||
moduleGraph_getEntrypoints(module?: NormalizedModule | null | undefined, graph?: Graph<ModuleGraphNodeData> | undefined, entrypoints?: NormalizedEntrypointItem[] | undefined, max?: number): NormalizedEntrypointItem[]; | ||
moduleGraph_getPaths(from?: NormalizedModule | undefined, graph?: Graph<ModuleGraphNodeData> | undefined, to?: NormalizedModule | undefined, max?: number): PathSolution<ModuleGraphNodeData> | null; | ||
modulesToFoamTree(modules: NormalizedModule[], compressed?: boolean | undefined, hash?: string | undefined): FoamTreeNode; | ||
}; |
@@ -117,2 +117,49 @@ "use strict"; | ||
}, | ||
getModuleGraph(hash) { | ||
var _a, _b; | ||
return (_b = (_a = resolveCompilation(hash)) === null || _a === void 0 ? void 0 : _a.graph.module) !== null && _b !== void 0 ? _b : null; | ||
}, | ||
moduleGraph_getEntrypoints(module, graph, entrypoints, max = Infinity) { | ||
if (!module || !graph || !entrypoints) { | ||
return []; | ||
} | ||
const moduleNode = graph.getNode(module.name); | ||
if (!moduleNode) { | ||
return []; | ||
} | ||
let total = 0; | ||
return entrypoints.filter( | ||
// @ts-ignore | ||
(entry) => { | ||
var _a; | ||
if (total === max) { | ||
return false; | ||
} | ||
const entryModuleName = (_a = entry.data.dep) === null || _a === void 0 ? void 0 : _a.module.name; | ||
const entryModule = graph.getNode(entryModuleName); | ||
if (entryModule) { | ||
if (moduleNode === entryModule) { | ||
total++; | ||
return true; | ||
} | ||
const solution = graph.findPaths(moduleNode, entryModule, 1); | ||
if (solution.children.length) { | ||
total++; | ||
return true; | ||
} | ||
} | ||
return false; | ||
}); | ||
}, | ||
moduleGraph_getPaths(from, graph, to, max = Infinity) { | ||
if (!from || !to || !graph) { | ||
return null; | ||
} | ||
const fromNode = graph.getNode(from.name); | ||
const toNode = graph.getNode(to.name); | ||
if (!fromNode || !toNode) { | ||
return null; | ||
} | ||
return graph.findPaths(fromNode, toNode, max); | ||
}, | ||
modulesToFoamTree(modules, compressed, hash) { | ||
@@ -119,0 +166,0 @@ if (compressed && !hash) { |
import { StatsDescriptor } from '@statoscope/stats'; | ||
import { Extension } from '@statoscope/stats/spec/extension'; | ||
import { Resolver } from '@statoscope/helpers/dist/entity-resolver'; | ||
import Graph from '@statoscope/helpers/dist/graph'; | ||
import { Webpack } from '../webpack'; | ||
@@ -22,2 +23,3 @@ import { ValidationResult } from './validate'; | ||
assets: NormalizedAsset[]; | ||
dep?: NormalizedModuleDependency; | ||
}; | ||
@@ -30,6 +32,15 @@ export declare type NormalizedAsset = Omit<Webpack.Asset, 'chunks' | 'files'> & { | ||
resolvedModule: NormalizedModule | null; | ||
resolvedEntry?: NormalizedEntrypointItem | null; | ||
resolvedEntryName?: string | null; | ||
}; | ||
export declare type NormalizedReason = Webpack.Reason & { | ||
resolvedModule: NormalizedModule | null; | ||
resolvedEntry?: NormalizedEntrypointItem | null; | ||
resolvedEntryName?: string | null; | ||
}; | ||
export declare type NormalizedModuleDependency = { | ||
type: 'module'; | ||
module: NormalizedModule; | ||
reason: NormalizedReason; | ||
}; | ||
export declare type NormalizedModule = Omit<Webpack.Module, 'chunks' | 'reasons' | 'modules'> & { | ||
@@ -42,2 +53,3 @@ resolvedResource: string | null; | ||
modules: NormalizedModule[]; | ||
deps?: NormalizedModuleDependency[]; | ||
}; | ||
@@ -51,6 +63,6 @@ export declare type NormalizedPackage = { | ||
isRoot: boolean; | ||
reasons: { | ||
type: 'module'; | ||
reasons: Array<{ | ||
type: 'module' | 'entry'; | ||
data: NormalizedReason; | ||
}[]; | ||
}>; | ||
modules: NormalizedModule[]; | ||
@@ -100,2 +112,3 @@ version?: string; | ||
resolvePackage: Resolver<string, NormalizedPackage>; | ||
resolveEntrypoint: Resolver<string, NormalizedEntrypointItem>; | ||
resolveExtension: Resolver<string, NormalizedExtension<unknown, unknown> | null>; | ||
@@ -106,2 +119,5 @@ }; | ||
resolvers: CompilationResolvers; | ||
graph: { | ||
module: Graph<ModuleGraphNodeData>; | ||
}; | ||
file: NormalizedFile; | ||
@@ -115,1 +131,5 @@ }; | ||
export declare function handleRawFile(rawStatsFileDescriptor: RawStatsFileDescriptor): HandledStats; | ||
export declare type ModuleGraphNodeData = { | ||
module: NormalizedModule; | ||
entries?: NormalizedEntrypointItem[]; | ||
}; |
@@ -14,2 +14,3 @@ "use strict"; | ||
const package_json_2 = __importDefault(require("@statoscope/stats-extension-package-info/package.json")); | ||
const graph_1 = __importDefault(require("@statoscope/helpers/dist/graph")); | ||
const validate_1 = __importDefault(require("./validate")); | ||
@@ -75,2 +76,39 @@ const module_1 = require("./module"); | ||
exports.handleRawFile = handleRawFile; | ||
function buildGraph(compilation) { | ||
var _a; | ||
const moduleGraph = new graph_1.default(); | ||
const globalHandled = new Set(); | ||
for (const entry of compilation.entrypoints) { | ||
if ((_a = entry.data.dep) === null || _a === void 0 ? void 0 : _a.module) { | ||
handleModuleNode(moduleGraph, entry.data.dep.module); | ||
} | ||
} | ||
return { | ||
module: moduleGraph, | ||
}; | ||
function handleModuleNode(graph, module) { | ||
var _a, _b; | ||
if (globalHandled.has(module)) { | ||
return graph.getNode(module.name); | ||
} | ||
globalHandled.add(module); | ||
const entries = module.reasons | ||
.filter((r) => r.resolvedEntry) | ||
.map((r) => r.resolvedEntry); | ||
const node = (_a = graph.getNode(module.name)) !== null && _a !== void 0 ? _a : graph.makeNode(module.name, { module, entries }); | ||
const handled = new WeakSet(); | ||
for (const innerModule of module.modules) { | ||
handled.add(innerModule); | ||
node.addChild(handleModuleNode(graph, innerModule)); | ||
} | ||
for (const dep of (_b = module.deps) !== null && _b !== void 0 ? _b : []) { | ||
if (handled.has(dep.module)) { | ||
continue; | ||
} | ||
handled.add(dep.module); | ||
node.addChild(handleModuleNode(graph, dep.module)); | ||
} | ||
return node; | ||
} | ||
} | ||
function handleCompilation(compilation, file, parent) { | ||
@@ -108,2 +146,4 @@ var _a, _b; | ||
const resolveExtension = entity_resolver_1.default(extensions, (ext) => ext === null || ext === void 0 ? void 0 : ext.data.descriptor.name); | ||
normalized.entrypoints = prepareEntries(compilation, resolveChunk, resolveAsset); | ||
const resolveEntrypoint = entity_resolver_1.default(normalized.entrypoints, ({ name }) => name); | ||
const resolvers = { | ||
@@ -114,2 +154,3 @@ resolveModule, | ||
resolvePackage, | ||
resolveEntrypoint, | ||
resolveExtension, | ||
@@ -120,7 +161,10 @@ }; | ||
prepareAssets(compilation, resolvers); | ||
normalized.entrypoints = prepareEntries(compilation, resolvers); | ||
extractPackages(normalized, resolvers); | ||
const graph = buildGraph(normalized); | ||
return { | ||
data: normalized, | ||
resolvers, | ||
graph: { | ||
module: graph.module, | ||
}, | ||
file, | ||
@@ -154,3 +198,4 @@ }; | ||
} | ||
function prepareModule(module, { resolveChunk, resolveModule }) { | ||
function prepareModule(module, resolvers) { | ||
var _a, _b; | ||
// @ts-ignore | ||
@@ -162,2 +207,3 @@ if (module[exports.normalizedSymbol]) { | ||
module[exports.normalizedSymbol] = true; | ||
const { resolveChunk, resolveModule } = resolvers; | ||
module.resolvedResource = module_1.moduleResource(module); | ||
@@ -177,5 +223,22 @@ if (module.issuerPath) { | ||
module.reasons = module.reasons.filter((r) => r.moduleName !== module.name); | ||
module.reasons.forEach((r) => (r.resolvedModule = r.moduleName | ||
? resolveModule(r.moduleName) | ||
: null)); | ||
for (const reason of module.reasons) { | ||
normalizeReason(reason, resolvers); | ||
const resolvedModule = reason.resolvedModule; | ||
const resolvedEntry = reason.resolvedEntry; | ||
if (resolvedModule) { | ||
(_a = resolvedModule.deps) !== null && _a !== void 0 ? _a : (resolvedModule.deps = []); | ||
resolvedModule.deps.push({ | ||
type: 'module', | ||
module: module, | ||
reason: reason, | ||
}); | ||
} | ||
if (resolvedEntry) { | ||
resolvedEntry.data.dep = { | ||
type: 'module', | ||
module: (_b = reason.resolvedModule) !== null && _b !== void 0 ? _b : module, | ||
reason: reason, | ||
}; | ||
} | ||
} | ||
} | ||
@@ -186,2 +249,23 @@ else { | ||
} | ||
function normalizeReason(reason, { resolveEntrypoint, resolveModule }) { | ||
var _a; | ||
reason.resolvedModule = reason.moduleName | ||
? resolveModule(reason.moduleName) | ||
: null; | ||
if (/(?:.+ )?entry$/.test((_a = reason.type) !== null && _a !== void 0 ? _a : '')) { | ||
if (reason.loc) { | ||
let resolvedName = reason.loc; | ||
let resolved = resolveEntrypoint(resolvedName); | ||
if (!resolved) { | ||
// handle foo[0] for webpack 4 single entry | ||
resolvedName = reason.loc.slice(0, -3); | ||
resolved = resolveEntrypoint(resolvedName); | ||
} | ||
if (resolved) { | ||
reason.resolvedEntryName = resolvedName; | ||
reason.resolvedEntry = resolved; | ||
} | ||
} | ||
} | ||
} | ||
function prepareModules(compilation, resolvers) { | ||
@@ -195,2 +279,5 @@ for (const module of compilation.modules || []) { | ||
} | ||
else { | ||
module.modules = []; | ||
} | ||
} | ||
@@ -217,2 +304,5 @@ } | ||
} | ||
else { | ||
module.modules = []; | ||
} | ||
} | ||
@@ -287,3 +377,3 @@ } | ||
} | ||
function prepareEntries(compilation, { resolveChunk, resolveAsset }) { | ||
function prepareEntries(compilation, resolveChunk, resolveAsset) { | ||
const entrypoints = []; | ||
@@ -311,3 +401,3 @@ for (const name in compilation.entrypoints) { | ||
const extractModulePackages = (module) => { | ||
var _a, _b; | ||
var _a, _b, _c; | ||
const resource = module_1.moduleResource(module); | ||
@@ -344,4 +434,4 @@ if (!resource) { | ||
const instanceReasonsKeys = new Set(instance.reasons.map((reason) => { | ||
var _a; | ||
return buildReasonKey(reason.type, (_a = reason.data.moduleName) !== null && _a !== void 0 ? _a : 'unknown', reason.data.loc); | ||
var _a, _b; | ||
return buildReasonKey(reason.type, (_a = reason.data.moduleName) !== null && _a !== void 0 ? _a : 'unknown', (_b = reason.data.loc) !== null && _b !== void 0 ? _b : 'unknown'); | ||
})); | ||
@@ -354,3 +444,3 @@ for (const reason of module.reasons) { | ||
const reasonType = 'module'; | ||
const reasonKey = buildReasonKey(reasonType, (_b = reason.moduleName) !== null && _b !== void 0 ? _b : 'unknown', reason.loc); | ||
const reasonKey = buildReasonKey(reasonType, (_b = reason.moduleName) !== null && _b !== void 0 ? _b : 'unknown', (_c = reason.loc) !== null && _c !== void 0 ? _c : 'unknown'); | ||
if (!instanceReasonsKeys.has(reasonKey)) { | ||
@@ -371,2 +461,5 @@ instance.reasons.push({ type: reasonType, data: reason }); | ||
} | ||
else { | ||
module.modules = []; | ||
} | ||
} | ||
@@ -373,0 +466,0 @@ } |
{ | ||
"name": "@statoscope/webpack-model", | ||
"version": "5.5.1", | ||
"version": "5.6.0", | ||
"description": "This package contains helpers to process webpack stats", | ||
@@ -26,6 +26,6 @@ "main": "./dist/index.js", | ||
"@statoscope/extensions": "^5.5.1", | ||
"@statoscope/helpers": "^5.5.1", | ||
"@statoscope/helpers": "^5.6.0", | ||
"@statoscope/stats": "^5.3.0", | ||
"@statoscope/stats-extension-compressed": "^5.5.1", | ||
"@statoscope/stats-extension-package-info": "^5.5.1", | ||
"@statoscope/stats-extension-compressed": "^5.6.0", | ||
"@statoscope/stats-extension-package-info": "^5.6.0", | ||
"ajv": "^8.5.0", | ||
@@ -39,3 +39,3 @@ "jora": "^1.0.0-beta.5", | ||
}, | ||
"gitHead": "f89a3ff2fd4eb15c07c592b22e2dd228038de4bb" | ||
"gitHead": "08038bf4c32ec3c28b28ffee2dfb3dbe0526a630" | ||
} |
@@ -26,8 +26,9 @@ import { StatsDescriptor } from '@statoscope/stats'; | ||
type Reason = { | ||
type?: string; | ||
moduleName: string | null; | ||
loc: string; | ||
loc?: string; | ||
}; | ||
type Entrypoint = { | ||
name: string; | ||
name?: string; | ||
chunks?: Array<ChunkID | Chunk>; | ||
@@ -34,0 +35,0 @@ assets?: Array<string | File>; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
82555
1349
23