UNPKG

knip

Version:

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

84 lines (83 loc) 3.44 kB
import { IMPORT_FLAGS } from '../../../constants.js'; import { getStringValue, isStringLiteral } from '../../../typescript/ast-nodes.js'; import { clientToPackages } from '../helpers.js'; const KNEX = 'knex'; export function createKnexClientVisitor(ctx) { const defaultNames = new Set(); const namedNames = new Set(); const addClientPackages = (obj, pos) => { for (const prop of obj.properties) { if (prop.type !== 'Property' || prop.computed || prop.key.type !== 'Identifier') continue; if (prop.key.name !== 'client') continue; if (!isStringLiteral(prop.value)) return; const client = getStringValue(prop.value); if (!client) return; for (const pkg of clientToPackages(client)) { ctx.addImport(pkg, pos, IMPORT_FLAGS.NONE); } return; } }; return { Program() { defaultNames.clear(); namedNames.clear(); }, ImportDeclaration(node) { if (!isStringLiteral(node.source) || getStringValue(node.source) !== KNEX) return; for (const spec of node.specifiers ?? []) { if (spec.type === 'ImportDefaultSpecifier') { defaultNames.add(spec.local.name); } else if (spec.type === 'ImportSpecifier') { if (spec.imported.type === 'Identifier' && spec.imported.name === KNEX) { namedNames.add(spec.local.name); } } } }, VariableDeclarator(node) { if (node.init?.type !== 'CallExpression' || node.init.callee.type !== 'Identifier' || node.init.callee.name !== 'require' || !isStringLiteral(node.init.arguments[0]) || getStringValue(node.init.arguments[0]) !== KNEX) return; if (node.id.type === 'Identifier') { defaultNames.add(node.id.name); } else if (node.id.type === 'ObjectPattern') { for (const prop of node.id.properties) { if (prop.type === 'Property' && prop.key.type === 'Identifier' && prop.key.name === KNEX && prop.value.type === 'Identifier') { namedNames.add(prop.value.name); } } } }, CallExpression(node) { if (defaultNames.size === 0 && namedNames.size === 0) return; const arg = node.arguments[0]; if (arg?.type !== 'ObjectExpression') return; const callee = node.callee; const isDirectCall = callee.type === 'Identifier' && (defaultNames.has(callee.name) || namedNames.has(callee.name)); const isNamespaceCall = callee.type === 'MemberExpression' && !callee.computed && callee.object.type === 'Identifier' && defaultNames.has(callee.object.name) && callee.property.type === 'Identifier' && callee.property.name === KNEX; if (isDirectCall || isNamespaceCall) addClientPackages(arg, arg.start); }, }; }