@graphql-codegen/visitor-plugin-common
Advanced tools
Comparing version 1.0.3-alpha-fb95f3d3.1 to 1.0.3
@@ -13,2 +13,4 @@ import { ParsedConfig, RawConfig, BaseVisitor } from './base-visitor'; | ||
}; | ||
defaultMapper: ParsedMapper | null; | ||
avoidOptionals: boolean; | ||
} | ||
@@ -56,2 +58,44 @@ export interface RawResolversConfig extends RawConfig { | ||
}; | ||
/** | ||
* @name defaultMapper | ||
* @type string | ||
* @description Allow you to set the default mapper when it's not being override by `mappers` or generics. | ||
* You can specify a type name, or specify a string in `module#type` format. | ||
* The defualt value of mappers it the TypeScript type generated by `typescript` package. | ||
* | ||
* @example Replace with any | ||
* ```yml | ||
* plugins | ||
* config: | ||
* defaultMapper: any | ||
* ``` | ||
* | ||
* @example Custom Base Object | ||
* ```yml | ||
* plugins | ||
* config: | ||
* defaultMapper: ./my-file#BaseObject | ||
* ``` | ||
*/ | ||
defaultMapper?: string; | ||
/** | ||
* @name avoidOptionals | ||
* @type boolean | ||
* @description This will cause the generator to avoid using TypeScript optionals (`?`), | ||
* so all field resolvers must be implemented in order to avoid compilation errors. | ||
* | ||
* @default false | ||
* | ||
* @example | ||
* ```yml | ||
* generates: | ||
* path/to/file.ts: | ||
* plugins: | ||
* - typescript | ||
* - typescript-resolvers | ||
* config: | ||
* avoidOptionals: true | ||
* ``` | ||
*/ | ||
avoidOptionals?: boolean; | ||
} | ||
@@ -71,2 +115,3 @@ export declare class BaseResolversVisitor<TRawConfig extends RawResolversConfig = RawResolversConfig, TPluginConfig extends ParsedResolversConfig = ParsedResolversConfig> extends BaseVisitor<TRawConfig, TPluginConfig> { | ||
readonly schema: GraphQLSchema; | ||
readonly defaultMapperType: string; | ||
readonly mappersImports: string[]; | ||
@@ -84,4 +129,7 @@ protected buildMapperImport(source: string, types: string[]): string; | ||
NonNullType(node: NonNullTypeNode): string; | ||
protected getTypeToUse(name: string, node: { | ||
name: any; | ||
}): string; | ||
FieldDefinition(node: FieldDefinitionNode, key: string | number, parent: any): (parentName: string) => string; | ||
ObjectTypeDefinition(node: ObjectTypeDefinitionNode): string; | ||
ObjectTypeDefinition(node: ObjectTypeDefinitionNode, key: string | number, parent: any): string; | ||
UnionTypeDefinition(node: UnionTypeDefinitionNode, key: string | number, parent: any): string; | ||
@@ -88,0 +136,0 @@ ScalarTypeDefinition(node: ScalarTypeDefinitionNode): string; |
@@ -12,3 +12,3 @@ "use strict"; | ||
constructor(rawConfig, additionalConfig, _schema, defaultScalars = scalars_1.DEFAULT_SCALARS) { | ||
super(rawConfig, Object.assign({ contextType: mappers_1.parseMapper(rawConfig.contextType || 'any'), mappers: mappers_1.transformMappers(rawConfig.mappers || {}) }, (additionalConfig || {})), utils_1.buildScalars(_schema, defaultScalars)); | ||
super(rawConfig, Object.assign({ contextType: mappers_1.parseMapper(rawConfig.contextType || 'any'), avoidOptionals: utils_1.getConfigValue(rawConfig.avoidOptionals, false), defaultMapper: rawConfig.defaultMapper ? mappers_1.parseMapper(rawConfig.defaultMapper || 'any') : null, mappers: mappers_1.transformMappers(rawConfig.mappers || {}) }, (additionalConfig || {})), utils_1.buildScalars(_schema, defaultScalars)); | ||
this._schema = _schema; | ||
@@ -24,2 +24,5 @@ this._declarationBlockConfig = {}; | ||
} | ||
get defaultMapperType() { | ||
return this.config.defaultMapper.type; | ||
} | ||
get mappersImports() { | ||
@@ -44,2 +47,8 @@ const groupedMappers = {}; | ||
} | ||
if (this.config.defaultMapper && this.config.defaultMapper.isExternal) { | ||
if (!groupedMappers[this.config.defaultMapper.source]) { | ||
groupedMappers[this.config.defaultMapper.source] = []; | ||
} | ||
groupedMappers[this.config.defaultMapper.source].push(this.config.defaultMapper.type); | ||
} | ||
return Object.keys(groupedMappers).map(source => this.buildMapperImport(source, groupedMappers[source])); | ||
@@ -57,28 +66,58 @@ } | ||
getRootResolver() { | ||
return new utils_1.DeclarationBlock(this._declarationBlockConfig) | ||
.export() | ||
.asKind('type') | ||
.withName(this.convertName('IResolvers'), `<Context = ${this.config.contextType.type}>`) | ||
.withBlock(Object.keys(this._collectedResolvers) | ||
.map(schemaTypeName => { | ||
const resolverType = this._collectedResolvers[schemaTypeName]; | ||
return utils_1.indent(this.formatRootResolver(schemaTypeName, resolverType)); | ||
}) | ||
.join('\n')).string; | ||
const name = this.convertName('Resolvers'); | ||
const contextType = `<Context = ${this.config.contextType.type}>`; | ||
// This is here because we don't want to break IResolvers, so there is a mapping by default, | ||
// and if the developer is overriding typesPrefix, it won't get generated at all. | ||
const deprecatedIResolvers = !this.config.typesPrefix | ||
? ` | ||
/** | ||
* @deprecated | ||
* Use "Resolvers" root object instead. If you wish to get "IResolvers", add "typesPrefix: I" to your config. | ||
*/ | ||
export type IResolvers${contextType} = ${name}<Context>;` | ||
: ''; | ||
return [ | ||
new utils_1.DeclarationBlock(this._declarationBlockConfig) | ||
.export() | ||
.asKind('type') | ||
.withName(name, contextType) | ||
.withBlock(Object.keys(this._collectedResolvers) | ||
.map(schemaTypeName => { | ||
const resolverType = this._collectedResolvers[schemaTypeName]; | ||
return utils_1.indent(this.formatRootResolver(schemaTypeName, resolverType)); | ||
}) | ||
.join('\n')).string, | ||
deprecatedIResolvers, | ||
].join('\n'); | ||
} | ||
formatRootResolver(schemaTypeName, resolverType) { | ||
return `${schemaTypeName}?: ${resolverType},`; | ||
return `${schemaTypeName}${this.config.avoidOptionals ? '' : '?'}: ${resolverType},`; | ||
} | ||
getAllDirectiveResolvers() { | ||
if (Object.keys(this._collectedDirectiveResolvers).length) { | ||
return new utils_1.DeclarationBlock(this._declarationBlockConfig) | ||
.export() | ||
.asKind('type') | ||
.withName(this.convertName('IDirectiveResolvers'), `<Context = ${this.config.contextType.type}>`) | ||
.withBlock(Object.keys(this._collectedDirectiveResolvers) | ||
.map(schemaTypeName => { | ||
const resolverType = this._collectedDirectiveResolvers[schemaTypeName]; | ||
return utils_1.indent(this.formatRootResolver(schemaTypeName, resolverType)); | ||
}) | ||
.join('\n')).string; | ||
const name = this.convertName('DirectiveResolvers'); | ||
const contextType = `<Context = ${this.config.contextType.type}>`; | ||
// This is here because we don't want to break IResolvers, so there is a mapping by default, | ||
// and if the developer is overriding typesPrefix, it won't get generated at all. | ||
const deprecatedIResolvers = !this.config.typesPrefix | ||
? ` | ||
/** | ||
* @deprecated | ||
* Use "DirectiveResolvers" root object instead. If you wish to get "IDirectiveResolvers", add "typesPrefix: I" to your config. | ||
*/ | ||
export type IDirectiveResolvers${contextType} = ${name}<Context>;` | ||
: ''; | ||
return [ | ||
new utils_1.DeclarationBlock(this._declarationBlockConfig) | ||
.export() | ||
.asKind('type') | ||
.withName(name, contextType) | ||
.withBlock(Object.keys(this._collectedDirectiveResolvers) | ||
.map(schemaTypeName => { | ||
const resolverType = this._collectedDirectiveResolvers[schemaTypeName]; | ||
return utils_1.indent(this.formatRootResolver(schemaTypeName, resolverType)); | ||
}) | ||
.join('\n')).string, | ||
deprecatedIResolvers, | ||
].join('\n'); | ||
} | ||
@@ -92,3 +131,3 @@ return ''; | ||
const asString = node.type; | ||
return `ArrayOrIterable<${asString}>`; | ||
return `Array<${asString}>`; | ||
} | ||
@@ -109,2 +148,14 @@ _getScalar(name) { | ||
} | ||
getTypeToUse(name, node) { | ||
if (this.config.mappers[name]) { | ||
return this.config.mappers[name].type; | ||
} | ||
else if (this.config.defaultMapper) { | ||
return this.config.defaultMapper.type; | ||
} | ||
else if (this.config.scalars[name]) { | ||
return this._getScalar(name); | ||
} | ||
return this.convertName(typeof node.name === 'string' ? node.name : node.name.value); | ||
} | ||
FieldDefinition(node, key, parent) { | ||
@@ -114,7 +165,9 @@ const hasArguments = node.arguments && node.arguments.length > 0; | ||
const original = parent[key]; | ||
const realType = utils_1.getBaseTypeNode(original.type).name.value; | ||
const mappedType = this.config.mappers[realType] ? this._variablesTransfomer.wrapAstTypeWithModifiers(this.config.mappers[realType].type, original.type) : node.type; | ||
const baseType = utils_1.getBaseTypeNode(original.type); | ||
const realType = baseType.name.value; | ||
const typeToUse = this.getTypeToUse(realType, baseType); | ||
const mappedType = this._variablesTransfomer.wrapAstTypeWithModifiers(typeToUse, original.type); | ||
const subscriptionType = this._schema.getSubscriptionType(); | ||
const isSubscriptionType = subscriptionType && subscriptionType.name === parentName; | ||
return utils_1.indent(`${node.name}?: ${isSubscriptionType ? 'SubscriptionResolver' : 'Resolver'}<${mappedType}, ParentType, Context${hasArguments | ||
return utils_1.indent(`${node.name}${this.config.avoidOptionals ? '' : '?'}: ${isSubscriptionType ? 'SubscriptionResolver' : 'Resolver'}<${mappedType}, ParentType, Context${hasArguments | ||
? `, ${this.convertName(parentName, { | ||
@@ -130,13 +183,7 @@ useTypesPrefix: true, | ||
} | ||
ObjectTypeDefinition(node) { | ||
ObjectTypeDefinition(node, key, parent) { | ||
const name = this.convertName(node, { | ||
suffix: 'Resolvers', | ||
}); | ||
let type = null; | ||
if (this.config.mappers[node.name]) { | ||
type = this.config.mappers[node.name].type; | ||
} | ||
else { | ||
type = this.config.scalars[node.name] || this.convertName(node); | ||
} | ||
const type = this.getTypeToUse(node.name, node); | ||
const block = new utils_1.DeclarationBlock(this._declarationBlockConfig) | ||
@@ -160,6 +207,7 @@ .export() | ||
this._collectedResolvers[node.name] = name; | ||
const type = this.getTypeToUse(node.name, node); | ||
return new utils_1.DeclarationBlock(this._declarationBlockConfig) | ||
.export() | ||
.asKind('type') | ||
.withName(name, `<Context = ${this.config.contextType.type}, ParentType = ${node.name}>`) | ||
.withName(name, `<Context = ${this.config.contextType.type}, ParentType = ${type}>`) | ||
.withBlock(utils_1.indent(`__resolveType: TypeResolveFn<${possibleTypes}, ParentType, Context>`)).string; | ||
@@ -211,6 +259,7 @@ } | ||
} | ||
const type = this.getTypeToUse(node.name, node); | ||
return new utils_1.DeclarationBlock(this._declarationBlockConfig) | ||
.export() | ||
.asKind('type') | ||
.withName(name, `<Context = ${this.config.contextType.type}, ParentType = ${node.name}>`) | ||
.withName(name, `<Context = ${this.config.contextType.type}, ParentType = ${type}>`) | ||
.withBlock([utils_1.indent(`__resolveType: TypeResolveFn<${implementingTypes.map(name => `'${name}'`).join(' | ')}, ParentType, Context>,`), ...(node.fields || []).map((f) => f(node.name))].join('\n')).string; | ||
@@ -217,0 +266,0 @@ } |
@@ -20,2 +20,6 @@ import { SelectionSetNode, FieldNode, FragmentSpreadNode, InlineFragmentNode, GraphQLNamedType, GraphQLSchema } from 'graphql'; | ||
}; | ||
export declare type LoadedFragment = { | ||
name: string; | ||
onType: string; | ||
}; | ||
export declare class SelectionSetToObject { | ||
@@ -26,2 +30,3 @@ protected _scalars: ScalarsMap; | ||
protected _addTypename: boolean; | ||
protected _loadedFragments: LoadedFragment[]; | ||
protected _parentSchemaType?: GraphQLNamedType; | ||
@@ -35,3 +40,3 @@ protected _selectionSet?: SelectionSetNode; | ||
protected _queriedForTypename: boolean; | ||
constructor(_scalars: ScalarsMap, _schema: GraphQLSchema, _convertName: ConvertNameFn<BaseVisitorConvertOptions>, _addTypename: boolean, _parentSchemaType?: GraphQLNamedType, _selectionSet?: SelectionSetNode); | ||
constructor(_scalars: ScalarsMap, _schema: GraphQLSchema, _convertName: ConvertNameFn<BaseVisitorConvertOptions>, _addTypename: boolean, _loadedFragments: LoadedFragment[], _parentSchemaType?: GraphQLNamedType, _selectionSet?: SelectionSetNode); | ||
createNext(parentSchemaType: GraphQLNamedType, selectionSet: SelectionSetNode): SelectionSetToObject; | ||
@@ -38,0 +43,0 @@ protected wrapTypeWithModifiers(baseType: string, type: GraphQLObjectType | GraphQLNonNull<GraphQLObjectType> | GraphQLList<GraphQLObjectType>): string; |
@@ -9,12 +9,10 @@ "use strict"; | ||
function isRootType(type, schema) { | ||
return (graphql_1.isEqualType(type, schema.getQueryType()) || | ||
graphql_1.isEqualType(type, schema.getMutationType()) || | ||
graphql_1.isEqualType(type, schema.getSubscriptionType())); | ||
return graphql_1.isEqualType(type, schema.getQueryType()) || graphql_1.isEqualType(type, schema.getMutationType()) || graphql_1.isEqualType(type, schema.getSubscriptionType()); | ||
} | ||
const metadataFieldMap = { | ||
__schema: graphql_1.SchemaMetaFieldDef, | ||
__type: graphql_1.TypeMetaFieldDef | ||
__type: graphql_1.TypeMetaFieldDef, | ||
}; | ||
class SelectionSetToObject { | ||
constructor(_scalars, _schema, _convertName, _addTypename, _parentSchemaType, _selectionSet) { | ||
constructor(_scalars, _schema, _convertName, _addTypename, _loadedFragments, _parentSchemaType, _selectionSet) { | ||
this._scalars = _scalars; | ||
@@ -24,2 +22,3 @@ this._schema = _schema; | ||
this._addTypename = _addTypename; | ||
this._loadedFragments = _loadedFragments; | ||
this._parentSchemaType = _parentSchemaType; | ||
@@ -60,3 +59,3 @@ this._selectionSet = _selectionSet; | ||
fieldName: field.name.value, | ||
alias: field.alias.value | ||
alias: field.alias.value, | ||
}); | ||
@@ -74,3 +73,3 @@ } | ||
type: typeName, | ||
selectionSet: this.wrapTypeWithModifiers(selectionSetToObject.string, rawType) | ||
selectionSet: this.wrapTypeWithModifiers(selectionSetToObject.string, rawType), | ||
}); | ||
@@ -111,3 +110,3 @@ } | ||
const parentName = this._convertName(this._parentSchemaType.name, { | ||
useTypesPrefix: true | ||
useTypesPrefix: true, | ||
}); | ||
@@ -134,5 +133,3 @@ const typeName = this._addTypename || this._queriedForTypename ? this.buildTypeNameField() : null; | ||
} | ||
return `{ ${this.formatNamedField('__typename')}${this._queriedForTypename ? '' : '?'}: ${possibleTypes | ||
.map(t => `'${t}'`) | ||
.join(' | ')} }`; | ||
return `{ ${this.formatNamedField('__typename')}${this._queriedForTypename ? '' : '?'}: ${possibleTypes.map(t => `'${t}'`).join(' | ')} }`; | ||
} | ||
@@ -149,5 +146,3 @@ buildPrimitiveFields(parentName, fields) { | ||
} | ||
return `{ ${fields | ||
.map(aliasedField => `${this.formatNamedField(aliasedField.alias)}: ${parentName}['${aliasedField.fieldName}']`) | ||
.join(', ')} }`; | ||
return `{ ${fields.map(aliasedField => `${this.formatNamedField(aliasedField.alias)}: ${parentName}['${aliasedField.fieldName}']`).join(', ')} }`; | ||
} | ||
@@ -161,9 +156,7 @@ formatNamedField(name) { | ||
} | ||
return `{ ${fields | ||
.map(field => `${this.formatNamedField(field.alias || field.name)}: ${field.selectionSet}`) | ||
.join(', ')} }`; | ||
return `{ ${fields.map(field => `${this.formatNamedField(field.alias || field.name)}: ${field.selectionSet}`).join(', ')} }`; | ||
} | ||
buildInlineFragments(inlineFragments) { | ||
const allPossibleTypes = Object.keys(inlineFragments).map(typeName => inlineFragments[typeName].join(' & ')); | ||
return allPossibleTypes.length === 0 ? null : `(${allPossibleTypes.join(' | ')})`; | ||
return utils_1.quoteIfNeeded(allPossibleTypes, ' | '); | ||
} | ||
@@ -174,6 +167,17 @@ buildFragmentSpread(fragmentsSpread) { | ||
} | ||
return utils_1.quoteIfNeeded(fragmentsSpread.map(fragmentName => this._convertName(fragmentName, { | ||
const typeToFragment = fragmentsSpread.reduce((prev, fragmentName) => { | ||
const fragmentDef = this._loadedFragments.find(r => r.name === fragmentName); | ||
if (!prev[fragmentDef.onType]) { | ||
prev[fragmentDef.onType] = []; | ||
} | ||
prev[fragmentDef.onType].push(fragmentName); | ||
return prev; | ||
}, {}); | ||
const allPossibleTypes = Object.keys(typeToFragment).map(typeName => typeToFragment[typeName] | ||
.map(fragmentName => this._convertName(fragmentName, { | ||
suffix: 'Fragment', | ||
useTypesPrefix: true | ||
})), ' & '); | ||
useTypesPrefix: true, | ||
})) | ||
.join(' & ')); | ||
return utils_1.quoteIfNeeded(allPossibleTypes, ' | '); | ||
} | ||
@@ -180,0 +184,0 @@ } |
@@ -13,2 +13,4 @@ import { ParsedConfig, RawConfig, BaseVisitor } from './base-visitor'; | ||
}; | ||
defaultMapper: ParsedMapper | null; | ||
avoidOptionals: boolean; | ||
} | ||
@@ -56,2 +58,44 @@ export interface RawResolversConfig extends RawConfig { | ||
}; | ||
/** | ||
* @name defaultMapper | ||
* @type string | ||
* @description Allow you to set the default mapper when it's not being override by `mappers` or generics. | ||
* You can specify a type name, or specify a string in `module#type` format. | ||
* The defualt value of mappers it the TypeScript type generated by `typescript` package. | ||
* | ||
* @example Replace with any | ||
* ```yml | ||
* plugins | ||
* config: | ||
* defaultMapper: any | ||
* ``` | ||
* | ||
* @example Custom Base Object | ||
* ```yml | ||
* plugins | ||
* config: | ||
* defaultMapper: ./my-file#BaseObject | ||
* ``` | ||
*/ | ||
defaultMapper?: string; | ||
/** | ||
* @name avoidOptionals | ||
* @type boolean | ||
* @description This will cause the generator to avoid using TypeScript optionals (`?`), | ||
* so all field resolvers must be implemented in order to avoid compilation errors. | ||
* | ||
* @default false | ||
* | ||
* @example | ||
* ```yml | ||
* generates: | ||
* path/to/file.ts: | ||
* plugins: | ||
* - typescript | ||
* - typescript-resolvers | ||
* config: | ||
* avoidOptionals: true | ||
* ``` | ||
*/ | ||
avoidOptionals?: boolean; | ||
} | ||
@@ -71,2 +115,3 @@ export declare class BaseResolversVisitor<TRawConfig extends RawResolversConfig = RawResolversConfig, TPluginConfig extends ParsedResolversConfig = ParsedResolversConfig> extends BaseVisitor<TRawConfig, TPluginConfig> { | ||
readonly schema: GraphQLSchema; | ||
readonly defaultMapperType: string; | ||
readonly mappersImports: string[]; | ||
@@ -84,4 +129,7 @@ protected buildMapperImport(source: string, types: string[]): string; | ||
NonNullType(node: NonNullTypeNode): string; | ||
protected getTypeToUse(name: string, node: { | ||
name: any; | ||
}): string; | ||
FieldDefinition(node: FieldDefinitionNode, key: string | number, parent: any): (parentName: string) => string; | ||
ObjectTypeDefinition(node: ObjectTypeDefinitionNode): string; | ||
ObjectTypeDefinition(node: ObjectTypeDefinitionNode, key: string | number, parent: any): string; | ||
UnionTypeDefinition(node: UnionTypeDefinitionNode, key: string | number, parent: any): string; | ||
@@ -88,0 +136,0 @@ ScalarTypeDefinition(node: ScalarTypeDefinitionNode): string; |
import { BaseVisitor } from './base-visitor'; | ||
import * as autoBind from 'auto-bind'; | ||
import { DEFAULT_SCALARS } from './scalars'; | ||
import { DeclarationBlock, indent, getBaseTypeNode, buildScalars } from './utils'; | ||
import { DeclarationBlock, indent, getBaseTypeNode, buildScalars, getConfigValue } from './utils'; | ||
import { GraphQLObjectType } from 'graphql'; | ||
@@ -10,3 +10,3 @@ import { OperationVariablesToObject } from './variables-to-object'; | ||
constructor(rawConfig, additionalConfig, _schema, defaultScalars = DEFAULT_SCALARS) { | ||
super(rawConfig, Object.assign({ contextType: parseMapper(rawConfig.contextType || 'any'), mappers: transformMappers(rawConfig.mappers || {}) }, (additionalConfig || {})), buildScalars(_schema, defaultScalars)); | ||
super(rawConfig, Object.assign({ contextType: parseMapper(rawConfig.contextType || 'any'), avoidOptionals: getConfigValue(rawConfig.avoidOptionals, false), defaultMapper: rawConfig.defaultMapper ? parseMapper(rawConfig.defaultMapper || 'any') : null, mappers: transformMappers(rawConfig.mappers || {}) }, (additionalConfig || {})), buildScalars(_schema, defaultScalars)); | ||
this._schema = _schema; | ||
@@ -22,2 +22,5 @@ this._declarationBlockConfig = {}; | ||
} | ||
get defaultMapperType() { | ||
return this.config.defaultMapper.type; | ||
} | ||
get mappersImports() { | ||
@@ -42,2 +45,8 @@ const groupedMappers = {}; | ||
} | ||
if (this.config.defaultMapper && this.config.defaultMapper.isExternal) { | ||
if (!groupedMappers[this.config.defaultMapper.source]) { | ||
groupedMappers[this.config.defaultMapper.source] = []; | ||
} | ||
groupedMappers[this.config.defaultMapper.source].push(this.config.defaultMapper.type); | ||
} | ||
return Object.keys(groupedMappers).map(source => this.buildMapperImport(source, groupedMappers[source])); | ||
@@ -55,28 +64,58 @@ } | ||
getRootResolver() { | ||
return new DeclarationBlock(this._declarationBlockConfig) | ||
.export() | ||
.asKind('type') | ||
.withName(this.convertName('IResolvers'), `<Context = ${this.config.contextType.type}>`) | ||
.withBlock(Object.keys(this._collectedResolvers) | ||
.map(schemaTypeName => { | ||
const resolverType = this._collectedResolvers[schemaTypeName]; | ||
return indent(this.formatRootResolver(schemaTypeName, resolverType)); | ||
}) | ||
.join('\n')).string; | ||
const name = this.convertName('Resolvers'); | ||
const contextType = `<Context = ${this.config.contextType.type}>`; | ||
// This is here because we don't want to break IResolvers, so there is a mapping by default, | ||
// and if the developer is overriding typesPrefix, it won't get generated at all. | ||
const deprecatedIResolvers = !this.config.typesPrefix | ||
? ` | ||
/** | ||
* @deprecated | ||
* Use "Resolvers" root object instead. If you wish to get "IResolvers", add "typesPrefix: I" to your config. | ||
*/ | ||
export type IResolvers${contextType} = ${name}<Context>;` | ||
: ''; | ||
return [ | ||
new DeclarationBlock(this._declarationBlockConfig) | ||
.export() | ||
.asKind('type') | ||
.withName(name, contextType) | ||
.withBlock(Object.keys(this._collectedResolvers) | ||
.map(schemaTypeName => { | ||
const resolverType = this._collectedResolvers[schemaTypeName]; | ||
return indent(this.formatRootResolver(schemaTypeName, resolverType)); | ||
}) | ||
.join('\n')).string, | ||
deprecatedIResolvers, | ||
].join('\n'); | ||
} | ||
formatRootResolver(schemaTypeName, resolverType) { | ||
return `${schemaTypeName}?: ${resolverType},`; | ||
return `${schemaTypeName}${this.config.avoidOptionals ? '' : '?'}: ${resolverType},`; | ||
} | ||
getAllDirectiveResolvers() { | ||
if (Object.keys(this._collectedDirectiveResolvers).length) { | ||
return new DeclarationBlock(this._declarationBlockConfig) | ||
.export() | ||
.asKind('type') | ||
.withName(this.convertName('IDirectiveResolvers'), `<Context = ${this.config.contextType.type}>`) | ||
.withBlock(Object.keys(this._collectedDirectiveResolvers) | ||
.map(schemaTypeName => { | ||
const resolverType = this._collectedDirectiveResolvers[schemaTypeName]; | ||
return indent(this.formatRootResolver(schemaTypeName, resolverType)); | ||
}) | ||
.join('\n')).string; | ||
const name = this.convertName('DirectiveResolvers'); | ||
const contextType = `<Context = ${this.config.contextType.type}>`; | ||
// This is here because we don't want to break IResolvers, so there is a mapping by default, | ||
// and if the developer is overriding typesPrefix, it won't get generated at all. | ||
const deprecatedIResolvers = !this.config.typesPrefix | ||
? ` | ||
/** | ||
* @deprecated | ||
* Use "DirectiveResolvers" root object instead. If you wish to get "IDirectiveResolvers", add "typesPrefix: I" to your config. | ||
*/ | ||
export type IDirectiveResolvers${contextType} = ${name}<Context>;` | ||
: ''; | ||
return [ | ||
new DeclarationBlock(this._declarationBlockConfig) | ||
.export() | ||
.asKind('type') | ||
.withName(name, contextType) | ||
.withBlock(Object.keys(this._collectedDirectiveResolvers) | ||
.map(schemaTypeName => { | ||
const resolverType = this._collectedDirectiveResolvers[schemaTypeName]; | ||
return indent(this.formatRootResolver(schemaTypeName, resolverType)); | ||
}) | ||
.join('\n')).string, | ||
deprecatedIResolvers, | ||
].join('\n'); | ||
} | ||
@@ -90,3 +129,3 @@ return ''; | ||
const asString = node.type; | ||
return `ArrayOrIterable<${asString}>`; | ||
return `Array<${asString}>`; | ||
} | ||
@@ -107,2 +146,14 @@ _getScalar(name) { | ||
} | ||
getTypeToUse(name, node) { | ||
if (this.config.mappers[name]) { | ||
return this.config.mappers[name].type; | ||
} | ||
else if (this.config.defaultMapper) { | ||
return this.config.defaultMapper.type; | ||
} | ||
else if (this.config.scalars[name]) { | ||
return this._getScalar(name); | ||
} | ||
return this.convertName(typeof node.name === 'string' ? node.name : node.name.value); | ||
} | ||
FieldDefinition(node, key, parent) { | ||
@@ -112,7 +163,9 @@ const hasArguments = node.arguments && node.arguments.length > 0; | ||
const original = parent[key]; | ||
const realType = getBaseTypeNode(original.type).name.value; | ||
const mappedType = this.config.mappers[realType] ? this._variablesTransfomer.wrapAstTypeWithModifiers(this.config.mappers[realType].type, original.type) : node.type; | ||
const baseType = getBaseTypeNode(original.type); | ||
const realType = baseType.name.value; | ||
const typeToUse = this.getTypeToUse(realType, baseType); | ||
const mappedType = this._variablesTransfomer.wrapAstTypeWithModifiers(typeToUse, original.type); | ||
const subscriptionType = this._schema.getSubscriptionType(); | ||
const isSubscriptionType = subscriptionType && subscriptionType.name === parentName; | ||
return indent(`${node.name}?: ${isSubscriptionType ? 'SubscriptionResolver' : 'Resolver'}<${mappedType}, ParentType, Context${hasArguments | ||
return indent(`${node.name}${this.config.avoidOptionals ? '' : '?'}: ${isSubscriptionType ? 'SubscriptionResolver' : 'Resolver'}<${mappedType}, ParentType, Context${hasArguments | ||
? `, ${this.convertName(parentName, { | ||
@@ -128,13 +181,7 @@ useTypesPrefix: true, | ||
} | ||
ObjectTypeDefinition(node) { | ||
ObjectTypeDefinition(node, key, parent) { | ||
const name = this.convertName(node, { | ||
suffix: 'Resolvers', | ||
}); | ||
let type = null; | ||
if (this.config.mappers[node.name]) { | ||
type = this.config.mappers[node.name].type; | ||
} | ||
else { | ||
type = this.config.scalars[node.name] || this.convertName(node); | ||
} | ||
const type = this.getTypeToUse(node.name, node); | ||
const block = new DeclarationBlock(this._declarationBlockConfig) | ||
@@ -158,6 +205,7 @@ .export() | ||
this._collectedResolvers[node.name] = name; | ||
const type = this.getTypeToUse(node.name, node); | ||
return new DeclarationBlock(this._declarationBlockConfig) | ||
.export() | ||
.asKind('type') | ||
.withName(name, `<Context = ${this.config.contextType.type}, ParentType = ${node.name}>`) | ||
.withName(name, `<Context = ${this.config.contextType.type}, ParentType = ${type}>`) | ||
.withBlock(indent(`__resolveType: TypeResolveFn<${possibleTypes}, ParentType, Context>`)).string; | ||
@@ -209,6 +257,7 @@ } | ||
} | ||
const type = this.getTypeToUse(node.name, node); | ||
return new DeclarationBlock(this._declarationBlockConfig) | ||
.export() | ||
.asKind('type') | ||
.withName(name, `<Context = ${this.config.contextType.type}, ParentType = ${node.name}>`) | ||
.withName(name, `<Context = ${this.config.contextType.type}, ParentType = ${type}>`) | ||
.withBlock([indent(`__resolveType: TypeResolveFn<${implementingTypes.map(name => `'${name}'`).join(' | ')}, ParentType, Context>,`), ...(node.fields || []).map((f) => f(node.name))].join('\n')).string; | ||
@@ -215,0 +264,0 @@ } |
@@ -20,2 +20,6 @@ import { SelectionSetNode, FieldNode, FragmentSpreadNode, InlineFragmentNode, GraphQLNamedType, GraphQLSchema } from 'graphql'; | ||
}; | ||
export declare type LoadedFragment = { | ||
name: string; | ||
onType: string; | ||
}; | ||
export declare class SelectionSetToObject { | ||
@@ -26,2 +30,3 @@ protected _scalars: ScalarsMap; | ||
protected _addTypename: boolean; | ||
protected _loadedFragments: LoadedFragment[]; | ||
protected _parentSchemaType?: GraphQLNamedType; | ||
@@ -35,3 +40,3 @@ protected _selectionSet?: SelectionSetNode; | ||
protected _queriedForTypename: boolean; | ||
constructor(_scalars: ScalarsMap, _schema: GraphQLSchema, _convertName: ConvertNameFn<BaseVisitorConvertOptions>, _addTypename: boolean, _parentSchemaType?: GraphQLNamedType, _selectionSet?: SelectionSetNode); | ||
constructor(_scalars: ScalarsMap, _schema: GraphQLSchema, _convertName: ConvertNameFn<BaseVisitorConvertOptions>, _addTypename: boolean, _loadedFragments: LoadedFragment[], _parentSchemaType?: GraphQLNamedType, _selectionSet?: SelectionSetNode); | ||
createNext(parentSchemaType: GraphQLNamedType, selectionSet: SelectionSetNode): SelectionSetToObject; | ||
@@ -38,0 +43,0 @@ protected wrapTypeWithModifiers(baseType: string, type: GraphQLObjectType | GraphQLNonNull<GraphQLObjectType> | GraphQLList<GraphQLObjectType>): string; |
@@ -1,2 +0,2 @@ | ||
import { Kind, isObjectType, isUnionType, isInterfaceType, isEnumType, isEqualType, SchemaMetaFieldDef, TypeMetaFieldDef, isScalarType } from 'graphql'; | ||
import { Kind, isObjectType, isUnionType, isInterfaceType, isEnumType, isEqualType, SchemaMetaFieldDef, TypeMetaFieldDef, isScalarType, } from 'graphql'; | ||
import { getBaseType, quoteIfNeeded } from './utils'; | ||
@@ -7,12 +7,10 @@ function isMetadataFieldName(name) { | ||
function isRootType(type, schema) { | ||
return (isEqualType(type, schema.getQueryType()) || | ||
isEqualType(type, schema.getMutationType()) || | ||
isEqualType(type, schema.getSubscriptionType())); | ||
return isEqualType(type, schema.getQueryType()) || isEqualType(type, schema.getMutationType()) || isEqualType(type, schema.getSubscriptionType()); | ||
} | ||
const metadataFieldMap = { | ||
__schema: SchemaMetaFieldDef, | ||
__type: TypeMetaFieldDef | ||
__type: TypeMetaFieldDef, | ||
}; | ||
export class SelectionSetToObject { | ||
constructor(_scalars, _schema, _convertName, _addTypename, _parentSchemaType, _selectionSet) { | ||
constructor(_scalars, _schema, _convertName, _addTypename, _loadedFragments, _parentSchemaType, _selectionSet) { | ||
this._scalars = _scalars; | ||
@@ -22,2 +20,3 @@ this._schema = _schema; | ||
this._addTypename = _addTypename; | ||
this._loadedFragments = _loadedFragments; | ||
this._parentSchemaType = _parentSchemaType; | ||
@@ -58,3 +57,3 @@ this._selectionSet = _selectionSet; | ||
fieldName: field.name.value, | ||
alias: field.alias.value | ||
alias: field.alias.value, | ||
}); | ||
@@ -72,3 +71,3 @@ } | ||
type: typeName, | ||
selectionSet: this.wrapTypeWithModifiers(selectionSetToObject.string, rawType) | ||
selectionSet: this.wrapTypeWithModifiers(selectionSetToObject.string, rawType), | ||
}); | ||
@@ -109,3 +108,3 @@ } | ||
const parentName = this._convertName(this._parentSchemaType.name, { | ||
useTypesPrefix: true | ||
useTypesPrefix: true, | ||
}); | ||
@@ -132,5 +131,3 @@ const typeName = this._addTypename || this._queriedForTypename ? this.buildTypeNameField() : null; | ||
} | ||
return `{ ${this.formatNamedField('__typename')}${this._queriedForTypename ? '' : '?'}: ${possibleTypes | ||
.map(t => `'${t}'`) | ||
.join(' | ')} }`; | ||
return `{ ${this.formatNamedField('__typename')}${this._queriedForTypename ? '' : '?'}: ${possibleTypes.map(t => `'${t}'`).join(' | ')} }`; | ||
} | ||
@@ -147,5 +144,3 @@ buildPrimitiveFields(parentName, fields) { | ||
} | ||
return `{ ${fields | ||
.map(aliasedField => `${this.formatNamedField(aliasedField.alias)}: ${parentName}['${aliasedField.fieldName}']`) | ||
.join(', ')} }`; | ||
return `{ ${fields.map(aliasedField => `${this.formatNamedField(aliasedField.alias)}: ${parentName}['${aliasedField.fieldName}']`).join(', ')} }`; | ||
} | ||
@@ -159,9 +154,7 @@ formatNamedField(name) { | ||
} | ||
return `{ ${fields | ||
.map(field => `${this.formatNamedField(field.alias || field.name)}: ${field.selectionSet}`) | ||
.join(', ')} }`; | ||
return `{ ${fields.map(field => `${this.formatNamedField(field.alias || field.name)}: ${field.selectionSet}`).join(', ')} }`; | ||
} | ||
buildInlineFragments(inlineFragments) { | ||
const allPossibleTypes = Object.keys(inlineFragments).map(typeName => inlineFragments[typeName].join(' & ')); | ||
return allPossibleTypes.length === 0 ? null : `(${allPossibleTypes.join(' | ')})`; | ||
return quoteIfNeeded(allPossibleTypes, ' | '); | ||
} | ||
@@ -172,8 +165,19 @@ buildFragmentSpread(fragmentsSpread) { | ||
} | ||
return quoteIfNeeded(fragmentsSpread.map(fragmentName => this._convertName(fragmentName, { | ||
const typeToFragment = fragmentsSpread.reduce((prev, fragmentName) => { | ||
const fragmentDef = this._loadedFragments.find(r => r.name === fragmentName); | ||
if (!prev[fragmentDef.onType]) { | ||
prev[fragmentDef.onType] = []; | ||
} | ||
prev[fragmentDef.onType].push(fragmentName); | ||
return prev; | ||
}, {}); | ||
const allPossibleTypes = Object.keys(typeToFragment).map(typeName => typeToFragment[typeName] | ||
.map(fragmentName => this._convertName(fragmentName, { | ||
suffix: 'Fragment', | ||
useTypesPrefix: true | ||
})), ' & '); | ||
useTypesPrefix: true, | ||
})) | ||
.join(' & ')); | ||
return quoteIfNeeded(allPossibleTypes, ' | '); | ||
} | ||
} | ||
//# sourceMappingURL=selection-set-to-object.js.map |
{ | ||
"name": "@graphql-codegen/visitor-plugin-common", | ||
"version": "1.0.3-alpha-fb95f3d3.1+fb95f3d3", | ||
"version": "1.0.3", | ||
"license": "MIT", | ||
@@ -9,3 +9,3 @@ "scripts": { | ||
"dependencies": { | ||
"@graphql-codegen/plugin-helpers": "1.0.3-alpha-fb95f3d3.1+fb95f3d3", | ||
"@graphql-codegen/plugin-helpers": "1.0.3", | ||
"auto-bind": "2.0.0", | ||
@@ -20,3 +20,3 @@ "dependency-graph": "0.8.0", | ||
"devDependencies": { | ||
"@graphql-codegen/testing": "1.0.3-alpha-fb95f3d3.1+fb95f3d3", | ||
"@graphql-codegen/testing": "1.0.3", | ||
"@types/graphql": "14.0.7", | ||
@@ -36,3 +36,3 @@ "graphql": "14.1.1", | ||
}, | ||
"gitHead": "fb95f3d38d1340727cfb0e55086be5b03585dc12" | ||
"gitHead": "f444f37c6fc706bc182c0a39ce11025eb6b760c0" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
240678
3545
1
0
+ Added@graphql-codegen/plugin-helpers@1.0.3(transitive)
+ Addedcamel-case@3.0.0(transitive)
+ Addedchange-case@3.1.0(transitive)
+ Addedcommon-tags@1.8.0(transitive)
+ Addedconstant-case@2.0.0(transitive)
+ Addeddot-case@2.1.1(transitive)
+ Addedheader-case@1.0.1(transitive)
+ Addedimport-from@2.1.0(transitive)
+ Addedis-lower-case@1.1.3(transitive)
+ Addedis-upper-case@1.1.2(transitive)
+ Addedlower-case@1.1.4(transitive)
+ Addedlower-case-first@1.0.2(transitive)
+ Addedno-case@2.3.2(transitive)
+ Addedparam-case@2.1.1(transitive)
+ Addedpascal-case@2.0.1(transitive)
+ Addedpath-case@2.1.1(transitive)
+ Addedresolve-from@3.0.0(transitive)
+ Addedsentence-case@2.1.1(transitive)
+ Addedsnake-case@2.1.0(transitive)
+ Addedswap-case@1.1.2(transitive)
+ Addedtitle-case@2.1.1(transitive)
+ Addedupper-case@1.1.3(transitive)
+ Addedupper-case-first@1.1.2(transitive)