UNPKG

@graphql-codegen/typescript-oclif

Version:

GraphQL Code Generator plugin for generating a CLI tool with oclif

87 lines (84 loc) 4.19 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GraphQLRequestVisitor = void 0; const tslib_1 = require("tslib"); const auto_bind_1 = tslib_1.__importDefault(require("auto-bind")); const graphql_1 = require("graphql"); const visitor_plugin_common_1 = require("@graphql-codegen/visitor-plugin-common"); const utils_js_1 = require("./utils.js"); class GraphQLRequestVisitor extends visitor_plugin_common_1.ClientSideBaseVisitor { constructor(schema, fragments, rawConfig, info) { super(schema, fragments, rawConfig, {}); this._operationsToInclude = []; this._info = info; const { handlerPath = '../../handler' } = rawConfig; // FIXME: This is taken in part from // presets/near-operation-file/src/index.ts:139. How do I build a path relative to the outputFile in the same way? // A plugin doesn't appear to have access to the same "options.baseOutputDir" that the preset does. // const absClientPath = resolve(info.outputFile, join(options.baseOutputDir, options.presetConfig.baseTypesPath)); (0, auto_bind_1.default)(this); this._additionalImports.push(`import { Command, flags } from '@oclif/command'`); this._additionalImports.push(`import handler from '${handlerPath}'`); } buildOperation(node, documentVariableName, operationType, operationResultType, operationVariablesTypes) { this._operationsToInclude.push({ node, documentVariableName, operationType, operationResultType, operationVariablesTypes, }); return null; } // Clean client-side content (ie directives) out of the GraphQL document prior to sending to the server get definition() { const operation = this._operationsToInclude[0]; const clientOperation = (0, graphql_1.print)((0, utils_js_1.omitOclifDirectives)(operation.node)); return `const ${operation.documentVariableName} = \`\n${clientOperation}\``; } // Generate the code required for this CLI operation get cliContent() { if (this._operationsToInclude.length !== 1) { throw new Error(`Each graphql document should have exactly one operation; found ${this._operationsToInclude.length} while generating ${this._info.outputFile}.`); } const operation = this._operationsToInclude[0]; // Find the @oclif directive in the client document, if it's there const directive = operation.node.directives.find(directive => directive.name.value === 'oclif'); // Remap the directive's fields ie @oclif(description: "a name") to a more usable format const directiveValues = {}; if (directive) { directiveValues.examples = []; directive.arguments.forEach(arg => { const value = 'value' in arg.value ? arg.value.value.toString() : null; const { value: name } = arg.name; if (name === 'description') { directiveValues.description = value; } else if (name === 'example') { directiveValues.examples.push(value); } else { throw new Error(`Invalid field supplied to @oclif directive: ${name}`); } }); } const { description, examples } = directiveValues; const flags = operation.node.variableDefinitions.map(utils_js_1.getFlagConfigForVariableDefinition); return ` ${this.definition} export default class ${operation.node.name.value} extends Command { ${description ? `\nstatic description = "${description}";\n` : ''} ${examples ? `\nstatic examples: string[] = ${JSON.stringify(examples)};\n` : ''} static flags = { help: flags.help({ char: 'h' }), ${(0, visitor_plugin_common_1.indentMultiline)(flags.join(',\n'), 2)} }; async run() { const { flags } = this.parse(${operation.node.name.value}); await handler({ command: this, query: ${operation.documentVariableName}, variables: flags }); } } `; } } exports.GraphQLRequestVisitor = GraphQLRequestVisitor;