@parcel/core
Version:
206 lines (204 loc) • 7.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = dumpGraphToGraphViz;
var _BundleGraph = require("./BundleGraph");
var _RequestTracker = require("./RequestTracker");
function _path() {
const data = _interopRequireDefault(require("path"));
_path = function () {
return data;
};
return data;
}
function _graph() {
const data = require("@parcel/graph");
_graph = function () {
return data;
};
return data;
}
var _projectPath = require("./projectPath");
var _types = require("./types");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const COLORS = {
root: 'gray',
asset: 'green',
dependency: 'orange',
transformer_request: 'cyan',
file: 'gray',
default: 'white'
};
const TYPE_COLORS = {
// bundle graph
bundle: 'blue',
contains: 'grey',
internal_async: 'orange',
references: 'red',
sibling: 'green',
// asset graph
// request graph
invalidated_by_create: 'green',
invalidated_by_create_above: 'orange',
invalidate_by_update: 'cyan',
invalidated_by_delete: 'red'
};
async function dumpGraphToGraphViz(graph, name, edgeTypes) {
var _globalThis$PARCEL_DU;
if ("production" === 'production' && !process.env.PARCEL_BUILD_REPL) {
return;
}
let mode = process.env.PARCEL_BUILD_REPL ? // $FlowFixMe
(_globalThis$PARCEL_DU = globalThis.PARCEL_DUMP_GRAPHVIZ) === null || _globalThis$PARCEL_DU === void 0 ? void 0 : _globalThis$PARCEL_DU.mode : process.env.PARCEL_DUMP_GRAPHVIZ;
// $FlowFixMe[invalid-compare]
if (mode == null || mode == false) {
return;
}
let detailedSymbols = mode === 'symbols';
let GraphVizGraph = require('graphviz/lib/deps/graph').Graph;
let g = new GraphVizGraph(null, 'G');
g.type = 'digraph';
// $FlowFixMe
for (let [id, node] of graph.nodes.entries()) {
if (node == null) continue;
let n = g.addNode(nodeId(id));
// $FlowFixMe default is fine. Not every type needs to be in the map.
n.set('color', COLORS[node.type || 'default']);
n.set('shape', 'box');
n.set('style', 'filled');
let label;
if (typeof node === 'string') {
label = node;
} else if (node.assets) {
label = `(${nodeId(id)}), (assetIds: ${[...node.assets].map(a => {
let arr = a.filePath.split('/');
return arr[arr.length - 1];
}).join(', ')}) (sourceBundles: ${[...node.sourceBundles].join(', ')}) (bb ${node.bundleBehavior ?? 'none'})`;
} else if (node.type) {
label = `[${(0, _graph().fromNodeId)(id)}] ${node.type || 'No Type'}: [${node.id}]: `;
if (node.type === 'dependency') {
label += node.value.specifier;
let parts = [];
if (node.value.priority !== _types.Priority.sync) {
var _Object$entries$find;
parts.push((_Object$entries$find = Object.entries(_types.Priority).find(([, v]) => v === node.value.priority)) === null || _Object$entries$find === void 0 ? void 0 : _Object$entries$find[0]);
}
if (node.value.isOptional) parts.push('optional');
if (node.value.specifierType === _types.SpecifierType.url) parts.push('url');
if (node.hasDeferred) parts.push('deferred');
if (node.deferred) parts.push('deferred');
if (node.excluded) parts.push('excluded');
if (parts.length) label += ' (' + parts.join(', ') + ')';
if (node.value.env) label += ` (${getEnvDescription(node.value.env)})`;
let depSymbols = node.value.symbols;
if (detailedSymbols) {
if (depSymbols) {
if (depSymbols.size) {
label += '\\nsymbols: ' + [...depSymbols].map(([e, {
local
}]) => [e, local]).join(';');
}
let weakSymbols = [...depSymbols].filter(([, {
isWeak
}]) => isWeak).map(([s]) => s);
if (weakSymbols.length) {
label += '\\nweakSymbols: ' + weakSymbols.join(',');
}
if (node.usedSymbolsUp.size > 0) {
label += '\\nusedSymbolsUp: ' + [...node.usedSymbolsUp].map(([s, sAsset]) => sAsset ? `${s}(${sAsset.asset}.${sAsset.symbol ?? ''})` : sAsset === null ? `${s}(external)` : `${s}(ambiguous)`).join(',');
}
if (node.usedSymbolsDown.size > 0) {
label += '\\nusedSymbolsDown: ' + [...node.usedSymbolsDown].join(',');
}
// if (node.usedSymbolsDownDirty) label += '\\nusedSymbolsDownDirty';
// if (node.usedSymbolsUpDirtyDown)
// label += '\\nusedSymbolsUpDirtyDown';
// if (node.usedSymbolsUpDirtyUp) label += '\\nusedSymbolsUpDirtyUp';
} else {
label += '\\nsymbols: cleared';
}
}
} else if (node.type === 'asset') {
label += _path().default.basename((0, _projectPath.fromProjectPathRelative)(node.value.filePath)) + '#' + node.value.type;
if (detailedSymbols) {
if (!node.value.symbols) {
label += '\\nsymbols: cleared';
} else if (node.value.symbols.size) {
label += '\\nsymbols: ' + [...node.value.symbols].map(([e, {
local
}]) => [e, local]).join(';');
}
if (node.usedSymbols.size) {
label += '\\nusedSymbols: ' + [...node.usedSymbols].join(',');
}
// if (node.usedSymbolsDownDirty) label += '\\nusedSymbolsDownDirty';
// if (node.usedSymbolsUpDirty) label += '\\nusedSymbolsUpDirty';
} else {
label += '\\nsymbols: cleared';
}
} else if (node.type === 'asset_group') {
if (node.deferred) label += '(deferred)';
} else if (node.type === 'file') {
label += _path().default.basename(node.id);
} else if (node.type === 'transformer_request') {
label += _path().default.basename(node.value.filePath) + ` (${getEnvDescription(node.value.env)})`;
} else if (node.type === 'bundle') {
let parts = [];
if (node.value.needsStableName) parts.push('stable name');
parts.push(node.value.name);
parts.push('bb:' + (node.value.bundleBehavior ?? 'null'));
if (node.value.isPlaceholder) parts.push('placeholder');
if (parts.length) label += ' (' + parts.join(', ') + ')';
if (node.value.env) label += ` (${getEnvDescription(node.value.env)})`;
} else if (node.type === 'request') {
label = node.requestType + ':' + node.id;
}
}
n.set('label', label);
}
let edgeNames;
if (edgeTypes) {
edgeNames = Object.fromEntries(Object.entries(edgeTypes).map(([k, v]) => [v, k]));
}
for (let edge of graph.getAllEdges()) {
let gEdge = g.addEdge(nodeId(edge.from), nodeId(edge.to));
let color = null;
if (edge.type != 1 && edgeNames) {
color = TYPE_COLORS[edgeNames[edge.type]];
}
if (color != null) {
gEdge.set('color', color);
}
}
if (process.env.PARCEL_BUILD_REPL) {
var _globalThis$PARCEL_DU2;
// $FlowFixMe
(_globalThis$PARCEL_DU2 = globalThis.PARCEL_DUMP_GRAPHVIZ) === null || _globalThis$PARCEL_DU2 === void 0 || _globalThis$PARCEL_DU2.call(globalThis, name, g.to_dot());
} else {
const tempy = require('tempy');
let tmp = tempy.file({
name: `parcel-${name}.png`
});
await g.output('png', tmp);
// eslint-disable-next-line no-console
console.log('Dumped', tmp);
}
}
function nodeId(id) {
// $FlowFixMe
return `node${id}`;
}
function getEnvDescription(env) {
let description;
if (typeof env.engines.browsers === 'string') {
description = `${env.context}: ${env.engines.browsers}`;
} else if (Array.isArray(env.engines.browsers)) {
description = `${env.context}: ${env.engines.browsers.join(', ')}`;
} else if (env.engines.node) {
description = `node: ${env.engines.node}`;
} else if (env.engines.electron) {
description = `electron: ${env.engines.electron}`;
}
return description ?? '';
}