@graphql-codegen/c-sharp
Version:
GraphQL Code Generator plugin for generating CSharp code based on a GraphQL schema
338 lines (335 loc) • 15.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CSharpResolversVisitor = void 0;
const change_case_all_1 = require("change-case-all");
const graphql_1 = require("graphql");
const c_sharp_common_1 = require("@graphql-codegen/c-sharp-common");
const visitor_plugin_common_1 = require("@graphql-codegen/visitor-plugin-common");
const json_attributes_js_1 = require("./json-attributes.js");
class CSharpResolversVisitor extends visitor_plugin_common_1.BaseVisitor {
constructor(rawConfig, _schema) {
var _a;
super(rawConfig, {
enumValues: rawConfig.enumValues || {},
listType: rawConfig.listType || 'List',
namespaceName: rawConfig.namespaceName || 'GraphQLCodeGen',
className: rawConfig.className || 'Types',
emitRecords: rawConfig.emitRecords || false,
emitJsonAttributes: (_a = rawConfig.emitJsonAttributes) !== null && _a !== void 0 ? _a : true,
jsonAttributesSource: rawConfig.jsonAttributesSource || 'Newtonsoft.Json',
scalars: (0, visitor_plugin_common_1.buildScalarsFromConfig)(_schema, rawConfig, c_sharp_common_1.C_SHARP_SCALARS),
});
this._schema = _schema;
if (this._parsedConfig.emitJsonAttributes) {
this.jsonAttributesConfiguration = (0, json_attributes_js_1.getJsonAttributeSourceConfiguration)(this._parsedConfig.jsonAttributesSource);
}
}
getImports() {
const allImports = [
'System',
'System.Collections.Generic',
'System.ComponentModel.DataAnnotations',
];
if (this._parsedConfig.emitJsonAttributes) {
const jsonAttributesNamespace = this.jsonAttributesConfiguration.namespace;
allImports.push(jsonAttributesNamespace);
}
return allImports.map(i => `using ${i};`).join('\n') + '\n';
}
wrapWithNamespace(content) {
return new c_sharp_common_1.CSharpDeclarationBlock()
.asKind('namespace')
.withName(this.config.namespaceName)
.withBlock((0, visitor_plugin_common_1.indentMultiline)(content)).string;
}
wrapWithClass(content) {
return new c_sharp_common_1.CSharpDeclarationBlock()
.access('public')
.asKind('class')
.withName((0, c_sharp_common_1.convertSafeName)(this.config.className))
.withBlock((0, visitor_plugin_common_1.indentMultiline)(content)).string;
}
getEnumValue(enumName, enumOption) {
if (this.config.enumValues[enumName] &&
typeof this.config.enumValues[enumName] === 'object' &&
this.config.enumValues[enumName][enumOption]) {
return this.config.enumValues[enumName][enumOption];
}
return enumOption;
}
EnumValueDefinition(node) {
return (enumName) => {
const enumHeader = this.getFieldHeader(node);
const enumOption = (0, c_sharp_common_1.convertSafeName)(node.name);
return enumHeader + (0, visitor_plugin_common_1.indent)(this.getEnumValue(enumName, enumOption));
};
}
EnumTypeDefinition(node) {
const enumName = this.convertName(node.name);
const enumValues = node.values
.map(enumValue => enumValue(node.name.value))
.join(',\n');
const enumBlock = [enumValues].join('\n');
return new c_sharp_common_1.CSharpDeclarationBlock()
.access('public')
.asKind('enum')
.withComment(node.description)
.withName(enumName)
.withBlock(enumBlock).string;
}
getFieldHeader(node, fieldType) {
var _a;
const attributes = [];
const commentText = (0, c_sharp_common_1.transformComment)((_a = node.description) === null || _a === void 0 ? void 0 : _a.value);
const deprecationDirective = node.directives.find(v => { var _a; return ((_a = v.name) === null || _a === void 0 ? void 0 : _a.value) === 'deprecated'; });
if (deprecationDirective) {
const deprecationReason = this.getDeprecationReason(deprecationDirective);
attributes.push(`[Obsolete("${deprecationReason}")]`);
}
if (this._parsedConfig.emitJsonAttributes && node.kind === graphql_1.Kind.FIELD_DEFINITION) {
const jsonPropertyAttribute = this.jsonAttributesConfiguration.propertyAttribute;
if (jsonPropertyAttribute != null) {
attributes.push(`[${jsonPropertyAttribute}("${node.name.value}")]`);
}
}
if (node.kind === graphql_1.Kind.INPUT_VALUE_DEFINITION && fieldType.isOuterTypeRequired) {
// Should be always inserted for required fields to use in `GetInputObject()` when JSON attributes are not used
// or there are no JSON attributes in selected attribute source that provides `JsonRequired` alternative
attributes.push('[Required]');
if (this._parsedConfig.emitJsonAttributes) {
const jsonRequiredAttribute = this.jsonAttributesConfiguration.requiredAttribute;
if (jsonRequiredAttribute != null) {
attributes.push(`[${jsonRequiredAttribute}]`);
}
}
}
if (commentText || attributes.length > 0) {
const summary = commentText ? (0, visitor_plugin_common_1.indentMultiline)(commentText.trimRight()) + '\n' : '';
const attributeLines = attributes.length > 0
? attributes
.map(attr => (0, visitor_plugin_common_1.indent)(attr))
.concat('')
.join('\n')
: '';
return summary + attributeLines;
}
return '';
}
getDeprecationReason(directive) {
if (directive.name.value !== 'deprecated') {
return '';
}
const hasArguments = directive.arguments.length > 0;
let reason = 'Field no longer supported';
if (hasArguments && directive.arguments[0].value.kind === graphql_1.Kind.STRING) {
reason = directive.arguments[0].value.value;
}
return reason;
}
resolveInputFieldType(typeNode, hasDefaultValue = false) {
const innerType = (0, visitor_plugin_common_1.getBaseTypeNode)(typeNode);
const schemaType = this._schema.getType(innerType.name.value);
const listType = (0, c_sharp_common_1.getListTypeField)(typeNode);
const required = (0, c_sharp_common_1.getListInnerTypeNode)(typeNode).kind === graphql_1.Kind.NON_NULL_TYPE;
let result = null;
if ((0, graphql_1.isScalarType)(schemaType)) {
if (this.scalars[schemaType.name]) {
const baseType = this.scalars[schemaType.name];
result = new c_sharp_common_1.CSharpFieldType({
baseType: {
type: baseType,
required,
valueType: (0, c_sharp_common_1.isValueType)(baseType),
},
listType,
});
}
else {
result = new c_sharp_common_1.CSharpFieldType({
baseType: {
type: 'object',
required,
valueType: false,
},
listType,
});
}
}
else if ((0, graphql_1.isInputObjectType)(schemaType)) {
result = new c_sharp_common_1.CSharpFieldType({
baseType: {
type: `${this.convertName(schemaType.name)}`,
required,
valueType: false,
},
listType,
});
}
else if ((0, graphql_1.isEnumType)(schemaType)) {
result = new c_sharp_common_1.CSharpFieldType({
baseType: {
type: this.convertName(schemaType.name),
required,
valueType: true,
},
listType,
});
}
else {
result = new c_sharp_common_1.CSharpFieldType({
baseType: {
type: `${schemaType.name}`,
required,
valueType: false,
},
listType,
});
}
if (hasDefaultValue) {
// Required field is optional when default value specified, see #4273
(result.listType || result.baseType).required = false;
}
return result;
}
buildRecord(name, description, inputValueArray, interfaces) {
const classSummary = (0, c_sharp_common_1.transformComment)(description === null || description === void 0 ? void 0 : description.value);
const interfaceImpl = interfaces && interfaces.length > 0
? ` : ${interfaces.map(ntn => ntn.name.value).join(', ')}`
: '';
const recordMembers = inputValueArray
.map(arg => {
const fieldType = this.resolveInputFieldType(arg.type);
const fieldHeader = this.getFieldHeader(arg, fieldType);
const fieldName = (0, c_sharp_common_1.convertSafeName)((0, change_case_all_1.pascalCase)(this.convertName(arg.name)));
const csharpFieldType = (0, c_sharp_common_1.wrapFieldType)(fieldType, fieldType.listType, this.config.listType);
return (fieldHeader +
(0, visitor_plugin_common_1.indent)(`public ${csharpFieldType} ${fieldName} { get; init; } = ${fieldName};`));
})
.join('\n\n');
const recordInitializer = inputValueArray
.map(arg => {
const fieldType = this.resolveInputFieldType(arg.type);
const fieldName = (0, c_sharp_common_1.convertSafeName)((0, change_case_all_1.pascalCase)(this.convertName(arg.name)));
const csharpFieldType = (0, c_sharp_common_1.wrapFieldType)(fieldType, fieldType.listType, this.config.listType);
return `${csharpFieldType} ${fieldName}`;
})
.join(', ');
return `
#region ${name}
${classSummary}public record ${(0, c_sharp_common_1.convertSafeName)(name)}(${recordInitializer})${interfaceImpl} {
#region members
${recordMembers}
#endregion
}
#endregion`;
}
buildClass(name, description, inputValueArray, interfaces) {
const classSummary = (0, c_sharp_common_1.transformComment)(description === null || description === void 0 ? void 0 : description.value);
const interfaceImpl = interfaces && interfaces.length > 0
? ` : ${interfaces.map(ntn => ntn.name.value).join(', ')}`
: '';
const classMembers = inputValueArray
.map(arg => {
const fieldType = this.resolveInputFieldType(arg.type);
const fieldHeader = this.getFieldHeader(arg, fieldType);
const fieldName = (0, c_sharp_common_1.convertSafeName)(arg.name);
const csharpFieldType = (0, c_sharp_common_1.wrapFieldType)(fieldType, fieldType.listType, this.config.listType);
return fieldHeader + (0, visitor_plugin_common_1.indent)(`public ${csharpFieldType} ${fieldName} { get; set; }`);
})
.join('\n\n');
return `
#region ${name}
${classSummary}public class ${(0, c_sharp_common_1.convertSafeName)(name)}${interfaceImpl} {
#region members
${classMembers}
#endregion
}
#endregion`;
}
buildInterface(name, description, inputValueArray) {
const classSummary = (0, c_sharp_common_1.transformComment)(description === null || description === void 0 ? void 0 : description.value);
const classMembers = inputValueArray
.map(arg => {
const fieldType = this.resolveInputFieldType(arg.type);
const fieldHeader = this.getFieldHeader(arg, fieldType);
let fieldName;
let getterSetter;
if (this.config.emitRecords) {
// record
fieldName = (0, c_sharp_common_1.convertSafeName)((0, change_case_all_1.pascalCase)(this.convertName(arg.name)));
getterSetter = '{ get; }';
}
else {
// class
fieldName = (0, c_sharp_common_1.convertSafeName)(arg.name);
getterSetter = '{ get; set; }';
}
const csharpFieldType = (0, c_sharp_common_1.wrapFieldType)(fieldType, fieldType.listType, this.config.listType);
return fieldHeader + (0, visitor_plugin_common_1.indent)(`${csharpFieldType} ${fieldName} ${getterSetter}`);
})
.join('\n\n');
return `
${classSummary}public interface ${(0, c_sharp_common_1.convertSafeName)(name)} {
${classMembers}
}`;
}
buildInputTransformer(name, description, inputValueArray) {
const classSummary = (0, c_sharp_common_1.transformComment)(description === null || description === void 0 ? void 0 : description.value);
const classMembers = inputValueArray
.map(arg => {
const fieldType = this.resolveInputFieldType(arg.type, !!arg.defaultValue);
const fieldHeader = this.getFieldHeader(arg, fieldType);
const fieldName = (0, c_sharp_common_1.convertSafeName)(arg.name);
const csharpFieldType = (0, c_sharp_common_1.wrapFieldType)(fieldType, fieldType.listType, this.config.listType);
return fieldHeader + (0, visitor_plugin_common_1.indent)(`public ${csharpFieldType} ${fieldName} { get; set; }`);
})
.join('\n\n');
return `
#region ${name}
${classSummary}public class ${(0, c_sharp_common_1.convertSafeName)(name)} {
#region members
${classMembers}
#endregion
#region methods
public dynamic GetInputObject()
{
IDictionary<string, object> d = new System.Dynamic.ExpandoObject();
var properties = GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
foreach (var propertyInfo in properties)
{
var value = propertyInfo.GetValue(this);
var defaultValue = propertyInfo.PropertyType.IsValueType ? Activator.CreateInstance(propertyInfo.PropertyType) : null;
${this._parsedConfig.emitJsonAttributes &&
this.jsonAttributesConfiguration.requiredAttribute != null
? `
var requiredProp = propertyInfo.GetCustomAttributes(typeof(${this.jsonAttributesConfiguration.requiredAttribute}Attribute), false).Length > 0;
`
: `
var requiredProp = propertyInfo.GetCustomAttributes(typeof(RequiredAttribute), false).Length > 0;
`}
if (requiredProp || value != defaultValue)
{
d[propertyInfo.Name] = value;
}
}
return d;
}
#endregion
}
#endregion`;
}
InputObjectTypeDefinition(node) {
const name = `${this.convertName(node)}`;
return this.buildInputTransformer(name, node.description, node.fields);
}
ObjectTypeDefinition(node) {
if (this.config.emitRecords) {
return this.buildRecord(node.name.value, node.description, node.fields, node.interfaces);
}
return this.buildClass(node.name.value, node.description, node.fields, node.interfaces);
}
InterfaceTypeDefinition(node) {
return this.buildInterface(node.name.value, node.description, node.fields);
}
}
exports.CSharpResolversVisitor = CSharpResolversVisitor;