@graphql-codegen/typescript-vue-apollo-smart-ops
Version:
GraphQL Code Generator plugin for generating typed Vue-Apollo Smart Query and mutation functions based on GraphQL operations
238 lines (237 loc) • 10.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VueApolloVisitor = void 0;
const tslib_1 = require("tslib");
const auto_bind_1 = tslib_1.__importDefault(require("auto-bind"));
const change_case_all_1 = require("change-case-all");
const visitor_plugin_common_1 = require("@graphql-codegen/visitor-plugin-common");
function insertIf(condition, ...elements) {
return condition ? elements : [];
}
class VueApolloVisitor extends visitor_plugin_common_1.ClientSideBaseVisitor {
constructor(schema, fragments, rawConfig, documents) {
super(schema, fragments, rawConfig, {
withSmartOperationFunctions: (0, visitor_plugin_common_1.getConfigValue)(rawConfig.withSmartOperationFunctions, true),
vueApolloOperationFunctionsImportFrom: (0, visitor_plugin_common_1.getConfigValue)(rawConfig.vueApolloOperationFunctionsImportFrom, 'vue-apollo-smart-ops'),
vueApolloErrorType: (0, visitor_plugin_common_1.getConfigValue)(rawConfig.vueApolloErrorType, 'ApolloError'),
vueApolloErrorTypeImportFrom: (0, visitor_plugin_common_1.getConfigValue)(rawConfig.vueApolloErrorTypeImportFrom, 'apollo-client'),
vueApolloErrorHandlerFunction: (0, visitor_plugin_common_1.getConfigValue)(rawConfig.vueApolloErrorHandlerFunction, undefined),
vueApolloErrorHandlerFunctionImportFrom: (0, visitor_plugin_common_1.getConfigValue)(rawConfig.vueApolloErrorHandlerFunctionImportFrom, undefined),
vueAppType: (0, visitor_plugin_common_1.getConfigValue)(rawConfig.vueAppType, undefined),
vueAppTypeImportFrom: (0, visitor_plugin_common_1.getConfigValue)(rawConfig.vueAppTypeImportFrom, undefined),
addDocBlocks: (0, visitor_plugin_common_1.getConfigValue)(rawConfig.addDocBlocks, true),
});
this.imports = new Set();
this.externalImportPrefix = this.config.importOperationTypesFrom
? `${this.config.importOperationTypesFrom}.`
: '';
this._documents = documents;
(0, auto_bind_1.default)(this);
}
get vueApolloOperationFunctionsImport() {
return `import { createMutationFunction, createSmartQueryOptionsFunction, createSmartSubscriptionOptionsFunction } from '${this.config.vueApolloOperationFunctionsImportFrom}';`;
}
get vueApolloErrorTypeImport() {
return `import { ${this.config.vueApolloErrorType} } from '${this.config.vueApolloErrorTypeImportFrom}';`;
}
get vueApolloErrorHandlerFunctionImport() {
if (!this.config.vueApolloErrorHandlerFunction ||
!this.config.vueApolloErrorHandlerFunctionImportFrom) {
return '';
}
return `import { ${this.config.vueApolloErrorHandlerFunction} } from '${this.config.vueApolloErrorHandlerFunctionImportFrom}';`;
}
get vueAppTypeImport() {
if (!this.config.vueAppType || !this.config.vueAppTypeImportFrom) {
return '';
}
return `import { ${this.config.vueAppType} } from '${this.config.vueAppTypeImportFrom}';`;
}
getDocumentNodeVariable(node, documentVariableName) {
var _a;
return this.config.documentMode === visitor_plugin_common_1.DocumentMode.external
? `Operations.${(_a = node.name) === null || _a === void 0 ? void 0 : _a.value}`
: documentVariableName;
}
getImports() {
const baseImports = super.getImports();
const hasOperations = this._collectedOperations.length > 0;
if (!hasOperations) {
return baseImports;
}
return [...baseImports, ...Array.from(this.imports)];
}
buildOperationFunctionsJSDoc(node, operationName, operationType) {
var _a;
const operationFunctionName = operationType === 'Mutation' ? (0, change_case_all_1.camelCase)(operationName) : `use${operationName}`;
const operationNameWithoutSuffix = (0, change_case_all_1.camelCase)(operationName).replace(/(Query|Mutation|Subscription)$/, '');
const exampleVariables = ((_a = node.variableDefinitions) !== null && _a !== void 0 ? _a : []).map(variableDefinition => {
const name = variableDefinition.variable.name.value;
return `${name}: // value for '${name}'`;
});
switch (operationType) {
case 'Query':
return `
/**
* __${operationFunctionName}__
*
* To use a Smart Query within a Vue component, call \`${operationFunctionName}\` as the value for a query key
* in the component's \`apollo\` config, passing any options required for the query.
*
* @param options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/core/ApolloClient/#ApolloClient.query
*
* @example
* {
* apollo: {
* ${operationNameWithoutSuffix}: ${operationFunctionName}({
* variables: {${exampleVariables.length > 0
? `
* ${exampleVariables.join(`
* `)}
* `
: ''}},
* loadingKey: 'loading',
* fetchPolicy: 'no-cache',
* }),
* }
* }
*/`;
case 'Mutation':
return `
/**
* __${operationFunctionName}__
*
* To run a mutation, you call \`${operationFunctionName}\` within a Vue component and pass it
* your Vue app instance along with any options that fit your needs.
*
* @param app, a reference to your Vue app instance (which must have a \`$apollo\` property)
* @param options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/core/ApolloClient/#ApolloClient.mutate
* @param client (optional), which can be an instance of \`DollarApollo\` or the \`mutate()\` function provided by an \`<ApolloMutation>\` component
*
* @example
* const { success, data, errors } = ${operationFunctionName}(this, {
* variables: {${exampleVariables.length > 0
? `
* ${exampleVariables.join(`
* `)}
* `
: ''}},
* });
*/`;
case 'Subscription':
return `
/**
* __${operationFunctionName}__
*
* To use a Smart Subscription within a Vue component, call \`${operationFunctionName}\` as the value for a \`$subscribe\` key
* in the component's \`apollo\` config, passing any options required for the subscription.
*
* @param options that will be passed into the subscription, supported options are listed on: https://www.apollographql.com/docs/react/api/core/ApolloClient/#ApolloClient.subscribe
*
* @example
* {
* apollo: {
* $subscribe: {
* ${operationNameWithoutSuffix}: ${operationFunctionName}({
* variables: {${exampleVariables.length > 0
? `
* ${exampleVariables.join(`
* `)}
* `
: ''}},
* loadingKey: 'loading',
* fetchPolicy: 'no-cache',
* }),
* },
* }
* }
*/`;
}
}
getOperationFunctionSuffix(name, operationType) {
if (!this.config.dedupeOperationSuffix) {
return this.config.omitOperationSuffix ? '' : (0, change_case_all_1.pascalCase)(operationType);
}
if (name.includes('Query') || name.includes('Mutation') || name.includes('Subscription')) {
return '';
}
return (0, change_case_all_1.pascalCase)(operationType);
}
buildOperation(node, documentVariableName, operationType, operationResultType, operationVariablesTypes) {
var _a, _b, _c;
operationResultType = this.externalImportPrefix + operationResultType;
operationVariablesTypes = this.externalImportPrefix + operationVariablesTypes;
if (!this.config.withSmartOperationFunctions) {
// todo - throw human readable error
return '';
}
if (!((_a = node.name) === null || _a === void 0 ? void 0 : _a.value)) {
// todo - throw human readable error
return '';
}
const suffix = this.getOperationFunctionSuffix(node.name.value, operationType);
const operationName = this.convertName(node.name.value, {
suffix,
useTypesPrefix: false,
});
const operationHasVariables = ((_b = node.variableDefinitions) !== null && _b !== void 0 ? _b : []).length > 0;
const operationHasNonNullableVariable = !!((_c = node.variableDefinitions) === null || _c === void 0 ? void 0 : _c.some(({ type }) => type.kind === 'NonNullType'));
this.imports.add(this.vueApolloOperationFunctionsImport);
this.imports.add(this.vueApolloErrorTypeImport);
if (this.vueApolloErrorHandlerFunctionImport) {
this.imports.add(this.vueApolloErrorHandlerFunctionImport);
}
if (this.vueAppTypeImport) {
this.imports.add(this.vueAppTypeImport);
}
const documentNodeVariable = this.getDocumentNodeVariable(node, documentVariableName); // i.e. TestDocument
const operationFunction = this.buildOperationFunction({
operationName,
operationType,
operationResultType,
operationVariablesTypes,
operationHasNonNullableVariable,
operationHasVariables,
documentNodeVariable,
});
return [
...insertIf(this.config.addDocBlocks, [
this.buildOperationFunctionsJSDoc(node, operationName, operationType),
]),
operationFunction,
'',
].join('\n');
}
buildOperationFunction({ operationName, operationType, operationResultType, operationVariablesTypes, documentNodeVariable, }) {
const operationArguments = [documentNodeVariable];
if (this.config.vueApolloErrorHandlerFunction) {
operationArguments.push(this.config.vueApolloErrorHandlerFunction);
}
const genericTypeArguments = [
operationResultType,
operationVariablesTypes,
this.config.vueApolloErrorType,
];
if (this.config.vueAppType) {
genericTypeArguments.push(this.config.vueAppType);
}
switch (operationType) {
case 'Query': {
return `export const use${operationName} = createSmartQueryOptionsFunction<
${genericTypeArguments.join(',\n ')}
>(${operationArguments.join(', ')});`;
}
case 'Mutation': {
return `export const ${(0, change_case_all_1.camelCase)(operationName)} = createMutationFunction<
${genericTypeArguments.join(',\n ')}
>(${operationArguments.join(', ')});`;
}
case 'Subscription': {
return `export const use${operationName} = createSmartSubscriptionOptionsFunction<
${genericTypeArguments.join(',\n ')}
>(${operationArguments.join(', ')});`;
}
}
}
}
exports.VueApolloVisitor = VueApolloVisitor;