fusion-plugin-introspect/src/cli/why.js (75 lines of code) (raw):

// @flow const {parseRuntimeMetadata} = require('./parseRuntimeMetadata.js'); const {listDependencies} = require('./listDependencies.js'); const {listSourceLines} = require('./listSourceLines.js'); module.exports.why = async (token /*: string*/) => { const data = await parseRuntimeMetadata(); const deps = listDependencies(data.server); const dep = deps.find(dep => dep.name === token); if (!dep) return ''; const explanation = [ describeType(dep, token), describeUsage(dep, token), `${token} is used by:\n` + graphParents(deps, token), `${token} depends on:\n` + graphChildren(deps, token), ]; return explanation.filter(Boolean).join('\n'); }; function describeType(dep, token) { const isPlugin = listSourceLines(dep, 'plugin').length > 0; if (isPlugin) { const types = { service: 'plugin w/ a `provides` method', middleware: 'plugin w/ a `middleware` method', both: 'plugin w/ a `provides` and `middleware` methods', value: 'value', noop: 'plugin without methods', }; //eslint-disable-next-line return `${token} token is registered with a ${types[dep.type]}\n`; } return ''; } function describeUsage(dep, token) { const verbs = { token: ' is declared in', register: ' is registered in', plugin: `'s plugin is created in`, 'alias-from': ' is aliased to another token in', // alias-from is being aliased to alias-to 'alias-to': ' is aliased from another token in', }; return Object.keys(verbs) .map(type => { const lines = listSourceLines(dep, type); if (lines.length > 0) { //eslint-disable-next-line return `${token}${verbs[type]}:\n ${lines.join('\n ')}\n`; } }) .filter(Boolean) .join('\n'); } function graphParents(deps, token, fork = true, level = 0) { const indent = `${fork ? '│' : ' '} `.repeat(level); const parents = deps .filter(dep => dep.dependencies.find(name => name === token)) .map(({name}, i, {length}) => { const fork = i < length - 1; const line = fork ? '├─' : '└─'; const parents = graphParents(deps, name, fork, level + 1); return `${indent}${line} ${name}\n${parents}`; }) .join('\n'); return parents; } function graphChildren(deps, token, fork = true, level = 0) { const indent = `${fork ? '│' : ' '} `.repeat(level); const self = deps.find(dep => dep.name === token); if (!self) return ''; const children = self.dependencies .map((dep, i, {length}) => { const fork = i < length - 1; const line = fork ? '├─' : '└─'; const children = graphChildren(deps, dep, fork, level + 1); return `${indent}${line} ${dep}\n${children}`; }) .join(''); return children; }