1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, '__esModule', { value: true });
|
4 |
|
5 | function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
6 |
|
7 | const graphql = require('graphql');
|
8 | const visitorPluginCommon = require('@graphql-codegen/visitor-plugin-common');
|
9 | const autoBind = _interopDefault(require('auto-bind'));
|
10 | const path = require('path');
|
11 |
|
12 | const getFlagConfigForVariableDefinition = (definition) => {
|
13 | const { list, required, innerType } = getInnerType(definition.type);
|
14 | const oclifType = mapVariableTypeToOclifType(innerType);
|
15 | const parser = getParserForType(innerType);
|
16 | return `${definition.variable.name.value}: flags.${oclifType}({
|
17 | multiple: ${list},
|
18 | required: ${required},${parser ? `\n parse: ${parser}` : ''}
|
19 | })`;
|
20 | };
|
21 |
|
22 | const getParserForType = (type) => {
|
23 | if (type.name.value === 'Float') {
|
24 | return 'input => Number(input)';
|
25 | }
|
26 | };
|
27 | const mapVariableTypeToOclifType = (type) => {
|
28 | if (type.name.value === 'Boolean') {
|
29 | return 'boolean';
|
30 | }
|
31 | else if (['Float', 'Int'].includes(type.name.value)) {
|
32 |
|
33 |
|
34 | return 'integer';
|
35 | }
|
36 | else {
|
37 | return 'string';
|
38 | }
|
39 | };
|
40 |
|
41 | const getInnerType = (type) => {
|
42 | const result = {
|
43 | list: false,
|
44 | required: false,
|
45 | };
|
46 | let _type = type;
|
47 | while (_type.kind !== 'NamedType') {
|
48 | if (_type.kind === 'ListType') {
|
49 | result.list = true;
|
50 | }
|
51 | else if (_type.kind === 'NonNullType') {
|
52 | result.required = true;
|
53 | }
|
54 | _type = _type.type;
|
55 | }
|
56 | result.innerType = _type;
|
57 | return result;
|
58 | };
|
59 |
|
60 | const omitOclifDirectives = (node) => {
|
61 | const directives = node.directives.filter(directive => directive.name.value !== 'oclif');
|
62 | return Object.assign({}, node, { directives });
|
63 | };
|
64 |
|
65 | class GraphQLRequestVisitor extends visitorPluginCommon.ClientSideBaseVisitor {
|
66 | constructor(schema, fragments, rawConfig, info) {
|
67 | super(schema, fragments, rawConfig, {});
|
68 | this._operationsToInclude = [];
|
69 | this._info = info;
|
70 | const { handlerPath = '../../handler' } = rawConfig;
|
71 |
|
72 |
|
73 |
|
74 |
|
75 | autoBind(this);
|
76 | this._additionalImports.push(`import { Command, flags } from '@oclif/command'`);
|
77 | this._additionalImports.push(`import handler from '${handlerPath}'`);
|
78 | }
|
79 | buildOperation(node, documentVariableName, operationType, operationResultType, operationVariablesTypes) {
|
80 | this._operationsToInclude.push({
|
81 | node,
|
82 | documentVariableName,
|
83 | operationType,
|
84 | operationResultType,
|
85 | operationVariablesTypes,
|
86 | });
|
87 | return null;
|
88 | }
|
89 |
|
90 | get definition() {
|
91 | const operation = this._operationsToInclude[0];
|
92 | const clientOperation = graphql.print(omitOclifDirectives(operation.node));
|
93 | return `const ${operation.documentVariableName} = \`\n${clientOperation}\``;
|
94 | }
|
95 |
|
96 | get cliContent() {
|
97 | if (this._operationsToInclude.length !== 1) {
|
98 | throw new Error(`Each graphql document should have exactly one operation; found ${this._operationsToInclude.length} while generating ${this._info.outputFile}.`);
|
99 | }
|
100 | const operation = this._operationsToInclude[0];
|
101 |
|
102 | const directive = operation.node.directives.find(directive => directive.name.value === 'oclif');
|
103 |
|
104 | const directiveValues = {};
|
105 | if (directive) {
|
106 | directiveValues.examples = [];
|
107 | directive.arguments.forEach(arg => {
|
108 | const value = 'value' in arg.value ? arg.value.value.toString() : null;
|
109 | const { value: name } = arg.name;
|
110 | if (name === 'description') {
|
111 | directiveValues.description = value;
|
112 | }
|
113 | else if (name === 'example') {
|
114 | directiveValues.examples.push(value);
|
115 | }
|
116 | else {
|
117 | throw new Error(`Invalid field supplied to @oclif directive: ${name}`);
|
118 | }
|
119 | });
|
120 | }
|
121 | const { description, examples } = directiveValues;
|
122 | const flags = operation.node.variableDefinitions.map(getFlagConfigForVariableDefinition);
|
123 | return `
|
124 | ${this.definition}
|
125 |
|
126 | export default class ${operation.node.name.value} extends Command {
|
127 | ${description ? `\nstatic description = "${description}";\n` : ''}
|
128 | ${examples ? `\nstatic examples: string[] = ${JSON.stringify(examples)};\n` : ''}
|
129 | static flags = {
|
130 | help: flags.help({ char: 'h' }),
|
131 | ${visitorPluginCommon.indentMultiline(flags.join(',\n'), 2)}
|
132 | };
|
133 |
|
134 | async run() {
|
135 | const { flags } = this.parse(${operation.node.name.value});
|
136 | await handler({ command: this, query: ${operation.documentVariableName}, variables: flags });
|
137 | }
|
138 | }
|
139 | `;
|
140 | }
|
141 | }
|
142 |
|
143 | const plugin = (schema, documents, config, info) => {
|
144 | const allAst = graphql.concatAST(documents.reduce((prev, v) => {
|
145 | return [...prev, v.document];
|
146 | }, []));
|
147 | const allFragments = [
|
148 | ...allAst.definitions.filter(d => d.kind === graphql.Kind.FRAGMENT_DEFINITION).map(fragmentDef => ({
|
149 | node: fragmentDef,
|
150 | name: fragmentDef.name.value,
|
151 | onType: fragmentDef.typeCondition.name.value,
|
152 | isExternal: false,
|
153 | })),
|
154 | ...(config.externalFragments || []),
|
155 | ];
|
156 | const visitor = new GraphQLRequestVisitor(schema, allFragments, config, info);
|
157 | graphql.visit(allAst, { leave: visitor });
|
158 | return {
|
159 | prepend: visitor.getImports(),
|
160 | content: visitor.cliContent,
|
161 | };
|
162 | };
|
163 | const validate = async (schema, documents, config, outputFile) => {
|
164 | if (path.extname(outputFile) !== '.ts') {
|
165 | throw new Error(`Plugin "typescript-oclif" requires output file extensions to be ".ts"!`);
|
166 | }
|
167 | };
|
168 |
|
169 | exports.GraphQLRequestVisitor = GraphQLRequestVisitor;
|
170 | exports.plugin = plugin;
|
171 | exports.validate = validate;
|