UNPKG

knip

Version:

Find and fix unused dependencies, exports and files in your TypeScript and JavaScript projects

88 lines (87 loc) 3.72 kB
import { IMPORT_FLAGS } from '../../../constants.js'; import { getStringValue, isStringLiteral } from '../../../typescript/ast-nodes.js'; import { isInternal } from '../../../util/path.js'; const PINO = 'pino'; export function createPinoTransportVisitor(ctx) { let pinoName; let transportName; const addTarget = (specifier, pos) => { ctx.addImport(specifier, pos, isInternal(specifier) ? IMPORT_FLAGS.ENTRY : IMPORT_FLAGS.NONE); }; const collectTargets = (obj) => { for (const prop of obj.properties) { if (prop.type !== 'Property' || prop.computed || prop.key.type !== 'Identifier') continue; const key = prop.key.name; if (key === 'target' && isStringLiteral(prop.value)) { addTarget(getStringValue(prop.value), prop.value.start); } else if ((key === 'targets' || key === 'pipeline') && prop.value.type === 'ArrayExpression') { for (const el of prop.value.elements) { if (el?.type === 'ObjectExpression') collectTargets(el); } } } }; return { Program() { pinoName = undefined; transportName = undefined; }, ImportDeclaration(node) { if (!isStringLiteral(node.source) || getStringValue(node.source) !== PINO) return; for (const spec of node.specifiers ?? []) { if (spec.type === 'ImportDefaultSpecifier') { pinoName = spec.local.name; } else if (spec.type === 'ImportSpecifier') { if (spec.imported.type === 'Identifier' && spec.imported.name === 'transport') { transportName = spec.local.name; } } } }, VariableDeclarator(node) { if (node.id.type !== 'Identifier' || node.init?.type !== 'CallExpression' || node.init.callee.type !== 'Identifier' || node.init.callee.name !== 'require' || !isStringLiteral(node.init.arguments[0]) || getStringValue(node.init.arguments[0]) !== PINO) return; pinoName ??= node.id.name; }, CallExpression(node) { if (!pinoName && !transportName) return; const callee = node.callee; const arg = node.arguments[0]; if (arg?.type !== 'ObjectExpression') return; const isPinoTransport = callee.type === 'MemberExpression' && !callee.computed && callee.object.type === 'Identifier' && callee.object.name === pinoName && callee.property.type === 'Identifier' && callee.property.name === 'transport'; const isNamedTransport = callee.type === 'Identifier' && transportName !== undefined && callee.name === transportName; if (isPinoTransport || isNamedTransport) { collectTargets(arg); return; } if (callee.type === 'Identifier' && callee.name === pinoName) { for (const prop of arg.properties) { if (prop.type === 'Property' && !prop.computed && prop.key.type === 'Identifier' && prop.key.name === 'transport' && prop.value.type === 'ObjectExpression') { collectTargets(prop.value); } } } }, }; }