UNPKG

@graphql-inspector/similar-command

Version:
140 lines (139 loc) 5.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.handler = handler; const fs_1 = require("fs"); const path_1 = require("path"); const commands_1 = require("@graphql-inspector/commands"); const core_1 = require("@graphql-inspector/core"); const logger_1 = require("@graphql-inspector/logger"); function handler({ schema, writePath, type, threshold, }) { const shouldWrite = typeof writePath !== 'undefined'; const similarMap = (0, core_1.similar)(schema, type, threshold); if (!Object.keys(similarMap).length) { logger_1.Logger.info('No similar types found'); return; } for (const typeName in similarMap) { if (Object.prototype.hasOwnProperty.call(similarMap, typeName)) { const matches = similarMap[typeName]; const prefix = (0, core_1.getTypePrefix)(schema.getType(typeName)); const sourceType = logger_1.chalk.bold(typeName); const name = matches.bestMatch.target.typeId; logger_1.Logger.log(''); logger_1.Logger.log(`${prefix} ${sourceType}`); logger_1.Logger.log(printResult(name, matches.bestMatch.rating)); for (const match of matches.ratings) { logger_1.Logger.log(printResult(match.target.typeId, match.rating)); } } } if (shouldWrite) { if (typeof writePath !== 'string') { throw new Error(`--write is not valid file path: ${writePath}`); } const absPath = (0, commands_1.ensureAbsolute)(writePath); const ext = (0, path_1.extname)(absPath).replace('.', '').toLocaleLowerCase(); let output = undefined; const results = transformMap(similarMap); if (ext === 'json') { output = outputJSON(results); } if (output) { (0, fs_1.writeFileSync)(absPath, output, 'utf8'); logger_1.Logger.success(`Available at ${absPath}\n`); } else { throw new Error(`Extension ${ext} is not supported`); } } } exports.default = (0, commands_1.createCommand)(api => { const { loaders } = api; return { command: 'similar <schema>', describe: 'Find similar types in a schema', builder(yargs) { return yargs .positional('schema', { describe: 'Point to a schema', type: 'string', demandOption: true, }) .options({ n: { alias: 'name', describe: 'Name of a type', type: 'string', }, t: { alias: 'threshold', describe: 'Threshold of similarity ratio', type: 'number', }, w: { alias: 'write', describe: 'Write a file with stats', type: 'string', }, }); }, async handler(args) { const { headers, token } = (0, commands_1.parseGlobalArgs)(args); const writePath = args.write; const type = args.name; const threshold = args.threshold; const apolloFederation = args.federation || false; const aws = args.aws || false; const method = args.method?.toUpperCase() || 'POST'; const schema = await loaders.loadSchema(args.schema, { headers, token, method, }, apolloFederation, aws); return handler({ schema, writePath, type, threshold }); }, }; }); function indent(line, space) { return line.padStart(line.length + space, ' '); } function transformMap(similarMap) { const results = {}; for (const typename in similarMap) { if (Object.prototype.hasOwnProperty.call(similarMap, typename)) { const result = similarMap[typename]; results[typename] = []; if (result.bestMatch) { results[typename].push(trasformResult(result.bestMatch)); } if (result.ratings) { results[typename].push(...result.ratings.map(trasformResult)); } } } return results; } function trasformResult(record) { return { typename: record.target.typeId, rating: record.rating, }; } function outputJSON(results) { return JSON.stringify(results); } function printResult(name, rating) { const percentage = logger_1.chalk.grey(`(${formatRating(rating)}%)`); return indent(`${printScale(rating)} ${percentage} ${name}`, 0); } function printScale(ratio) { const percentage = Math.floor(ratio * 100); const levels = [0, 30, 50, 70, 90]; return levels .map(level => percentage >= level) .map(enabled => (enabled ? logger_1.figures.bullet : logger_1.chalk.gray(logger_1.figures.bullet))) .join(''); } function formatRating(ratio) { return Math.floor(ratio * 100); }