UNPKG

@graphql-inspector/audit-command

Version:
114 lines (113 loc) 5.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.handler = handler; const tslib_1 = require("tslib"); const cli_table3_1 = tslib_1.__importDefault(require("cli-table3")); const graphql_1 = require("graphql"); const commands_1 = require("@graphql-inspector/commands"); const core_1 = require("@graphql-inspector/core"); const logger_1 = require("@graphql-inspector/logger"); exports.default = (0, commands_1.createCommand)(api => { return { command: 'audit <documents>', describe: 'Audit Fragments and Operations for a better understanding of the depth, alias count, and directive count.', builder(yargs) { return yargs .positional('documents', { describe: 'Point to some documents', type: 'string', demandOption: true, }) .options({ detail: { alias: 'd', describe: 'Print an overview of all operations and their audit breakdown.', type: 'boolean', default: false, }, complexityScalarCost: { describe: 'The cost per scalar for calculating the complexity score.', type: 'number', default: 1, }, complexityObjectCost: { describe: 'The cost per object for calculating the complexity score.', type: 'number', default: 2, }, complexityDepthCostFactor: { describe: 'The cost factor per introduced depth level for calculating the complexity score.', type: 'number', default: 1.5, }, }); }, async handler(args) { const { loaders } = api; const ignore = args.ignore || []; const documents = await loaders.loadDocuments(args.documents, { ignore, }); const complexityConfig = { scalarCost: args.complexityScalarCost, objectCost: args.complexityObjectCost, depthCostFactor: args.complexityDepthCostFactor, }; return handler({ documents, detail: args.detail, complexityConfig }); }, }; }); function handler(args) { const fragments = new Map(); const fragmentStrings = new Map(); const operations = new Map(); const getFragmentReference = (fragmentName) => fragments.get(fragmentName); const getFragmentSource = (fragmentName) => fragmentStrings.get(fragmentName); for (const record of args.documents) { if (record.document) { for (const definition of record.document.definitions) { if (definition.kind === 'FragmentDefinition') { fragments.set(definition.name.value, definition); fragmentStrings.set(definition.name.value, (0, graphql_1.print)(definition)); } else if (definition.kind === 'OperationDefinition' && definition.name) { operations.set(definition.name.value, definition); } } } } let maxDepth = 0; let maxAliases = 0; let maxDirectives = 0; let maxTokenCount = 0; let maxComplexity = 0; const results = []; for (const [name, operation] of operations.entries()) { const depth = (0, core_1.countDepth)(operation, 0, getFragmentReference); const aliases = (0, core_1.countAliases)(operation, getFragmentReference); const directives = (0, core_1.countDirectives)(operation, getFragmentReference); const tokenCount = (0, core_1.calculateTokenCount)({ source: (0, graphql_1.print)(operation), getReferencedFragmentSource: getFragmentSource, }); const complexity = (0, core_1.calculateOperationComplexity)(operation, args.complexityConfig, getFragmentReference); results.push([name, depth, aliases, directives, tokenCount, complexity.toFixed(2)]); maxDepth = Math.max(maxDepth, depth); maxAliases = Math.max(maxAliases, aliases); maxDirectives = Math.max(maxDirectives, directives); maxTokenCount = Math.max(maxTokenCount, tokenCount); maxComplexity = Math.max(maxComplexity, complexity); } if (args.detail) { const table = new cli_table3_1.default({ head: ['Operation Name', 'Depth', 'Aliases', 'Directives', 'Token Count', 'Complexity Score'], }); table.push(...results); logger_1.Logger.log(table.toString()); } logger_1.Logger.log(`Maximum depth is ${logger_1.chalk.bold(maxDepth)}`); logger_1.Logger.log(`Maximum alias amount is ${logger_1.chalk.bold(maxAliases)}`); logger_1.Logger.log(`Maximum directive amount is ${logger_1.chalk.bold(maxDirectives)}`); logger_1.Logger.log(`Maximum token count is ${logger_1.chalk.bold(maxTokenCount)}`); logger_1.Logger.log(`Maximum complexity score is ${logger_1.chalk.bold(maxComplexity.toFixed(2))}`); }