graphql#GraphQLFieldConfig TypeScript Examples
The following examples show how to use
graphql#GraphQLFieldConfig.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: schema-resolver.ts From graphql-mesh with MIT License | 6 votes |
createSoapServiceField(service: SoapService, rootType: RootType): GraphQLFieldConfig<any, any> {
const fieldsThunk = (): GraphQLFieldConfigMap<any, any> => {
const fields: GraphQLFieldConfigMap<any, any> = {};
service.ports().forEach((port: SoapPort) => {
if (this.options.includePorts) {
fields[port.name()] = this.createSoapPortField(service, port, rootType);
} else {
port.operations().forEach((operation: SoapOperation) => {
const fieldConfig = this.createSoapOperationField(operation, rootType);
if (fieldConfig) {
fields[operation.name()] = fieldConfig;
}
});
}
});
return fields;
};
const returnType = new GraphQLObjectType({
name: service.name() + 'Service' + (rootType === 'query' ? 'Query' : ''),
description: `Service ${service.name()}`,
fields: fieldsThunk,
});
return {
type: returnType,
description: `Service ${service.name()}`,
resolve: () => {
return {};
},
};
}
Example #2
Source File: schema-resolver.ts From graphql-mesh with MIT License | 6 votes |
createSoapPortField(service: SoapService, port: SoapPort, rootType: RootType): GraphQLFieldConfig<any, any> {
const fieldsThunk = (): GraphQLFieldConfigMap<any, any> => {
const fields: GraphQLFieldConfigMap<any, any> = {};
port.operations().forEach((operation: SoapOperation) => {
const fieldConfig = this.createSoapOperationField(operation, rootType);
if (fieldConfig) {
fields[operation.name()] = fieldConfig;
}
});
return fields;
};
const returnType = new GraphQLObjectType({
name: port.name() + 'Port' + (rootType === 'query' ? 'Query' : ''),
description: `Port ${port.name()}, service ${service.name()}`,
fields: fieldsThunk,
});
return {
type: returnType,
description: `Port ${port.name()}, service ${service.name()}`,
resolve: () => {
return {};
},
};
}
Example #3
Source File: schema-resolver.ts From graphql-mesh with MIT License | 6 votes |
getFieldConfig(operation: SoapOperation): GraphQLFieldConfig<any, any> {
const args: GraphQLFieldConfigArgumentMap = this.createSoapOperationFieldArgs(operation);
const returnType: GraphQLOutputType = this.resolveSoapOperationReturnType(operation);
const resolver: GraphQLFieldResolver<any, any, any> = this.createSoapOperationFieldResolver(operation);
return {
type: returnType,
description: `Operation ${operation.name()}, port ${operation.port().name()}, service ${operation
.service()
.name()}`,
args,
resolve: resolver,
};
}
Example #4
Source File: schema-resolver.ts From graphql-mesh with MIT License | 6 votes |
createSoapOperationField(operation: SoapOperation, rootType: RootType): GraphQLFieldConfig<any, any> {
if (this.options.selectQueryOrMutationField?.length) {
const selectionConfig = this.options.selectQueryOrMutationField.find(
configElem =>
configElem.service === operation.service().name() &&
configElem.port === operation.port().name() &&
configElem.operation === operation.name()
);
if (selectionConfig != null) {
if (selectionConfig.type === rootType) {
return this.getFieldConfig(operation);
} else {
return undefined;
}
}
}
if (this.options.selectQueryOperationsAuto) {
if (
operation.name().toLowerCase().startsWith('get') ||
operation.name().toLowerCase().startsWith('find') ||
operation.name().toLowerCase().startsWith('list') ||
operation.name().toLowerCase().startsWith('query') ||
operation.name().toLowerCase().startsWith('search')
) {
if (rootType === 'query') {
return this.getFieldConfig(operation);
}
} else {
if (rootType === 'mutation') {
return this.getFieldConfig(operation);
}
}
} else if (rootType === 'mutation') {
return this.getFieldConfig(operation);
}
return undefined;
}
Example #5
Source File: barePrefix.ts From graphql-mesh with MIT License | 6 votes |
transformSchema(schema: GraphQLSchema) {
return mapSchema(schema, {
[MapperKind.TYPE]: (type: GraphQLNamedType) => {
if (this.includeTypes && !isSpecifiedScalarType(type)) {
const currentName = type.name;
if (!this.ignoreList.includes(currentName)) {
return renameType(type, this.prefix + currentName);
}
}
return undefined;
},
[MapperKind.ROOT_OBJECT]() {
return undefined;
},
...(this.includeRootOperations && {
[MapperKind.COMPOSITE_FIELD]: (
fieldConfig: GraphQLFieldConfig<any, any>,
fieldName: string,
typeName: string
) => {
return !rootOperations.has(typeName) || // check we're in a root Type
this.ignoreList.includes(typeName) || // check if type is to be ignored
this.ignoreList.includes(`${typeName}.${fieldName}`) // check if field in type is to be ignored
? undefined // do not perform any change
: [`${this.prefix}${fieldName}`, fieldConfig]; // apply prefix
},
}),
});
}
Example #6
Source File: bareRename.ts From graphql-mesh with MIT License | 6 votes |
transformSchema(schema: GraphQLSchema) {
return mapSchema(schema, {
...(this.typesMap.size && { [MapperKind.TYPE]: type => this.renameType(type) }),
...(this.typesMap.size && { [MapperKind.ROOT_OBJECT]: type => this.renameType(type) }),
...((this.fieldsMap.size || this.argsMap.size) && {
[MapperKind.COMPOSITE_FIELD]: (
fieldConfig: GraphQLFieldConfig<any, any>,
fieldName: string,
typeName: string
) => {
const typeRules = this.fieldsMap.get(typeName);
const fieldRules = this.argsMap.get(`${typeName}.${fieldName}`);
const newFieldName = typeRules && this.matchInMap(typeRules, fieldName);
const argsMap =
fieldRules &&
Array.from(fieldRules.entries()).reduce((acc, [orName, newName]) => ({ ...acc, [newName]: orName }), {});
if (!newFieldName && !fieldRules) return undefined;
// Rename rules for type might have been emptied by matchInMap, in which case we can cleanup
if (!typeRules?.size) this.fieldsMap.delete(typeName);
if (fieldRules && fieldConfig.args) {
fieldConfig.args = Object.entries(fieldConfig.args).reduce(
(args, [argName, argConfig]) => ({
...args,
[this.matchInMap(fieldRules, argName) || argName]: argConfig,
}),
{}
);
}
// Wrap resolve fn to handle mapping renamed field name and/or renamed arguments
fieldConfig.resolve = defaultResolverComposer(fieldConfig.resolve, fieldName, argsMap);
return [newFieldName || fieldName, fieldConfig];
},
}),
});
}
Example #7
Source File: index.ts From graphql-mesh with MIT License | 5 votes |
transformSchema(schema: GraphQLSchema) {
const additionalTypeDefs =
this.typeDefs &&
loadTypedefsSync(this.typeDefs, {
cwd: this.baseDir,
loaders: [new CodeFileLoader(), new GraphQLFileLoader()],
});
const baseSchema = additionalTypeDefs ? extendSchema(schema, additionalTypeDefs[0].document) : schema;
const transformedSchema = mapSchema(baseSchema, {
[MapperKind.COMPOSITE_FIELD]: (
fieldConfig: GraphQLFieldConfig<any, any>,
currentFieldName: string,
typeName: string
) => {
const fieldKey = `${typeName}.${currentFieldName}`;
const newFieldConfig = this.replacementsMap.get(fieldKey);
if (!newFieldConfig) {
return undefined;
}
const fieldName = newFieldConfig.name || currentFieldName;
const targetFieldName = newFieldConfig.field;
const targetFieldConfig = selectObjectFields(
baseSchema,
newFieldConfig.type,
fieldName => fieldName === targetFieldName
)[targetFieldName];
if (newFieldConfig.scope === 'config') {
const targetResolver = targetFieldConfig.resolve;
targetFieldConfig.resolve = newFieldConfig.composer(targetResolver);
// replace the entire field config
return [fieldName, targetFieldConfig];
}
// override field type with the target type requested
fieldConfig.type = targetFieldConfig.type;
// If renaming fields that don't have a custom resolver, we need to map response to original field name
if (newFieldConfig.name && !fieldConfig.resolve) fieldConfig.resolve = source => source[currentFieldName];
if (newFieldConfig.scope === 'hoistValue') {
// implement value hoisting by wrapping a default composer that hoists the value from resolver result
fieldConfig.resolve = defaultHoistFieldComposer(fieldConfig.resolve || defaultFieldResolver, targetFieldName);
}
// wrap user-defined composer to current field resolver or, if not preset, defaultFieldResolver
fieldConfig.resolve = newFieldConfig.composer(fieldConfig.resolve || defaultFieldResolver);
// avoid re-iterating over replacements that have already been applied
this.replacementsMap.delete(fieldKey);
return [fieldName, fieldConfig];
},
});
return transformedSchema;
}
Example #8
Source File: index.ts From graphql-mesh with MIT License | 4 votes |
/**
* Creates a GraphQL interface from the given OpenAPI Specification 3.0.x
*/
async function translateOpenAPIToGraphQL<TSource, TContext, TArgs>(
oass: Oas3[],
{
strict,
report,
// Schema options
operationIdFieldNames,
fillEmptyResponses,
addLimitArgument,
idFormats,
selectQueryOrMutationField,
genericPayloadArgName,
simpleNames,
singularNames,
includeHttpDetails,
// Resolver options
headers,
qs,
requestOptions,
connectOptions,
baseUrl,
customResolvers,
fetch,
resolverMiddleware,
pubsub,
// Authentication options
viewer,
tokenJSONpath,
sendOAuthTokenInQuery,
// Logging options
provideErrorExtensions,
equivalentToMessages,
logger,
}: InternalOptions<TSource, TContext, TArgs>
): Promise<{ schema: GraphQLSchema; report: Report }> {
const options = {
strict,
report,
// Schema options
operationIdFieldNames,
fillEmptyResponses,
addLimitArgument,
idFormats,
selectQueryOrMutationField,
genericPayloadArgName,
simpleNames,
singularNames,
includeHttpDetails,
// Resolver options
headers,
qs,
requestOptions,
connectOptions,
baseUrl,
customResolvers,
fetch,
resolverMiddleware,
pubsub,
// Authentication options
viewer,
tokenJSONpath,
sendOAuthTokenInQuery,
// Logging options
provideErrorExtensions,
equivalentToMessages,
logger,
};
const translationLogger = options.logger.child('translation');
translationLogger.debug(`Options:`, options);
/**
* Extract information from the OASs and put it inside a data structure that
* is easier for OpenAPI-to-GraphQL to use
*/
const data: PreprocessingData<TSource, TContext, TArgs> = preprocessOas(oass, options);
preliminaryChecks(options, data, translationLogger);
// Query, Mutation, and Subscription fields
let queryFields: { [fieldName: string]: GraphQLFieldConfig<any, any> } = {};
let mutationFields: { [fieldName: string]: GraphQLFieldConfig<any, any> } = {};
let subscriptionFields: {
[fieldName: string]: GraphQLFieldConfig<any, any>;
} = {};
// Authenticated Query, Mutation, and Subscription fields
let authQueryFields: {
[fieldName: string]: {
[securityRequirement: string]: GraphQLFieldConfig<any, any>;
};
} = {};
let authMutationFields: {
[fieldName: string]: {
[securityRequirement: string]: GraphQLFieldConfig<any, any>;
};
} = {};
let authSubscriptionFields: {
[fieldName: string]: {
[securityRequirement: string]: GraphQLFieldConfig<any, any>;
};
} = {};
// Add Query and Mutation fields
Object.entries(data.operations).forEach(([operationId, operation]) => {
translationLogger.debug(`Process operation '${operation.operationString}'...`);
const field = getFieldForOperation(
operation,
options.baseUrl,
data,
requestOptions,
connectOptions,
includeHttpDetails,
pubsub,
logger
);
const saneOperationId = Oas3Tools.sanitize(operationId, Oas3Tools.CaseStyle.camelCase);
// Check if the operation should be added as a Query or Mutation
if (operation.operationType === GraphQLOperationType.Query) {
let fieldName = !singularNames
? Oas3Tools.uncapitalize(operation.responseDefinition.graphQLTypeName)
: Oas3Tools.sanitize(Oas3Tools.inferResourceNameFromPath(operation.path), Oas3Tools.CaseStyle.camelCase);
if (operation.inViewer) {
for (const securityRequirement of operation.securityRequirements) {
if (typeof authQueryFields[securityRequirement] !== 'object') {
authQueryFields[securityRequirement] = {};
}
// Avoid overwriting fields that return the same data:
if (
fieldName in authQueryFields[securityRequirement] ||
/**
* If the option is set operationIdFieldNames, the fieldName is
* forced to be the operationId
*/
operationIdFieldNames
) {
fieldName = Oas3Tools.storeSaneName(saneOperationId, operationId, data.saneMap, options.logger);
}
if (fieldName in authQueryFields[securityRequirement]) {
handleWarning({
mitigationType: MitigationTypes.DUPLICATE_FIELD_NAME,
message:
`Multiple operations have the same name ` +
`'${fieldName}' and security requirement ` +
`'${securityRequirement}'. GraphQL field names must be ` +
`unique so only one can be added to the authentication ` +
`viewer. Operation '${operation.operationString}' will be ignored.`,
data,
logger: translationLogger,
});
} else {
authQueryFields[securityRequirement][fieldName] = field;
}
}
} else {
// Avoid overwriting fields that return the same data:
if (
fieldName in queryFields ||
/**
* If the option is set operationIdFieldNames, the fieldName is
* forced to be the operationId
*/
operationIdFieldNames
) {
fieldName = Oas3Tools.storeSaneName(saneOperationId, operationId, data.saneMap, options.logger);
}
if (fieldName in queryFields) {
handleWarning({
mitigationType: MitigationTypes.DUPLICATE_FIELD_NAME,
message:
`Multiple operations have the same name ` +
`'${fieldName}'. GraphQL field names must be ` +
`unique so only one can be added to the Query object. ` +
`Operation '${operation.operationString}' will be ignored.`,
data,
logger: translationLogger,
});
} else {
queryFields[fieldName] = field;
}
}
} else {
let saneFieldName;
if (!singularNames) {
/**
* Use operationId to avoid problems differentiating operations with the
* same path but differnet methods
*/
saneFieldName = Oas3Tools.storeSaneName(saneOperationId, operationId, data.saneMap, options.logger);
} else {
const fieldName = `${operation.method}${Oas3Tools.inferResourceNameFromPath(operation.path)}`;
saneFieldName = Oas3Tools.storeSaneName(
Oas3Tools.sanitize(fieldName, Oas3Tools.CaseStyle.camelCase),
fieldName,
data.saneMap,
options.logger
);
}
if (operation.inViewer) {
for (const securityRequirement of operation.securityRequirements) {
if (typeof authMutationFields[securityRequirement] !== 'object') {
authMutationFields[securityRequirement] = {};
}
if (saneFieldName in authMutationFields[securityRequirement]) {
handleWarning({
mitigationType: MitigationTypes.DUPLICATE_FIELD_NAME,
message:
`Multiple operations have the same name ` +
`'${saneFieldName}' and security requirement ` +
`'${securityRequirement}'. GraphQL field names must be ` +
`unique so only one can be added to the authentication ` +
`viewer. Operation '${operation.operationString}' will be ignored.`,
data,
logger: translationLogger,
});
} else {
authMutationFields[securityRequirement][saneFieldName] = field;
}
}
} else {
if (saneFieldName in mutationFields) {
handleWarning({
mitigationType: MitigationTypes.DUPLICATE_FIELD_NAME,
message:
`Multiple operations have the same name ` +
`'${saneFieldName}'. GraphQL field names must be ` +
`unique so only one can be added to the Mutation object. ` +
`Operation '${operation.operationString}' will be ignored.`,
data,
logger: translationLogger,
});
} else {
mutationFields[saneFieldName] = field;
}
}
}
});
// Add Subscription fields
Object.entries(data.callbackOperations).forEach(([operationId, operation]) => {
translationLogger.debug(`Process operation '${operationId}'...`);
const field = getFieldForOperation(
operation,
options.baseUrl,
data,
requestOptions,
connectOptions,
includeHttpDetails,
pubsub,
logger
);
const saneOperationId = Oas3Tools.sanitize(operationId, Oas3Tools.CaseStyle.camelCase);
const saneFieldName = Oas3Tools.storeSaneName(saneOperationId, operationId, data.saneMap, options.logger);
if (operation.inViewer) {
for (const securityRequirement of operation.securityRequirements) {
if (typeof authSubscriptionFields[securityRequirement] !== 'object') {
authSubscriptionFields[securityRequirement] = {};
}
if (saneFieldName in authSubscriptionFields[securityRequirement]) {
handleWarning({
mitigationType: MitigationTypes.DUPLICATE_FIELD_NAME,
message:
`Multiple operations have the same name ` +
`'${saneFieldName}' and security requirement ` +
`'${securityRequirement}'. GraphQL field names must be ` +
`unique so only one can be added to the authentication ` +
`viewer. Operation '${operation.operationString}' will be ignored.`,
data,
logger: translationLogger,
});
} else {
authSubscriptionFields[securityRequirement][saneFieldName] = field;
}
}
} else {
if (saneFieldName in subscriptionFields) {
handleWarning({
mitigationType: MitigationTypes.DUPLICATE_FIELD_NAME,
message:
`Multiple operations have the same name ` +
`'${saneFieldName}'. GraphQL field names must be ` +
`unique so only one can be added to the Mutation object. ` +
`Operation '${operation.operationString}' will be ignored.`,
data,
logger: translationLogger,
});
} else {
subscriptionFields[saneFieldName] = field;
}
}
});
// Sorting fields
queryFields = sortObject(queryFields);
mutationFields = sortObject(mutationFields);
subscriptionFields = sortObject(subscriptionFields);
authQueryFields = sortObject(authQueryFields);
Object.keys(authQueryFields).forEach(key => {
authQueryFields[key] = sortObject(authQueryFields[key]);
});
authMutationFields = sortObject(authMutationFields);
Object.keys(authMutationFields).forEach(key => {
authMutationFields[key] = sortObject(authMutationFields[key]);
});
authSubscriptionFields = sortObject(authSubscriptionFields);
Object.keys(authSubscriptionFields).forEach(key => {
authSubscriptionFields[key] = sortObject(authSubscriptionFields[key]);
});
// Count created Query, Mutation, and Subscription fields
options.report.numQueriesCreated =
Object.keys(queryFields).length +
Object.keys(authQueryFields).reduce((sum, key) => {
return (sum as any) + Object.keys(authQueryFields[key]).length;
}, 0);
options.report.numMutationsCreated =
Object.keys(mutationFields).length +
Object.keys(authMutationFields).reduce((sum, key) => {
return (sum as any) + Object.keys(authMutationFields[key]).length;
}, 0);
options.report.numSubscriptionsCreated =
Object.keys(subscriptionFields).length +
Object.keys(authSubscriptionFields).reduce((sum, key) => {
return (sum as any) + Object.keys(authSubscriptionFields[key]).length;
}, 0);
/**
* Organize authenticated Query, Mutation, and Subscriptions fields into
* viewer objects.
*/
if (Object.keys(authQueryFields).length > 0) {
Object.assign(
queryFields,
createAndLoadViewer(authQueryFields, GraphQLOperationType.Query, data, includeHttpDetails, options.logger)
);
}
if (Object.keys(authMutationFields).length > 0) {
Object.assign(
mutationFields,
createAndLoadViewer(authMutationFields, GraphQLOperationType.Mutation, data, includeHttpDetails, options.logger)
);
}
if (Object.keys(authSubscriptionFields).length > 0) {
Object.assign(
subscriptionFields,
createAndLoadViewer(
authSubscriptionFields,
GraphQLOperationType.Subscription,
data,
includeHttpDetails,
options.logger
)
);
}
// Build up the schema
const schemaConfig: GraphQLSchemaConfig = {
query:
Object.keys(queryFields).length > 0
? new GraphQLObjectType({
name: 'Query',
fields: queryFields,
})
: GraphQLTools.getEmptyObjectType('Query'), // A GraphQL schema must contain a Query object type
mutation:
Object.keys(mutationFields).length > 0
? new GraphQLObjectType({
name: 'Mutation',
fields: mutationFields,
})
: null,
subscription:
Object.keys(subscriptionFields).length > 0
? new GraphQLObjectType({
name: 'Subscription',
fields: subscriptionFields,
})
: null,
};
/**
* Fill in yet undefined object types to avoid GraphQLSchema from breaking.
*
* The reason: once creating the schema, the 'fields' thunks will resolve and
* if a field references an undefined object type, GraphQL will throw.
*/
Object.entries(data.operations).forEach(([, operation]) => {
if (typeof operation.responseDefinition.graphQLType === 'undefined') {
operation.responseDefinition.graphQLType = GraphQLTools.getEmptyObjectType(
operation.responseDefinition.graphQLTypeName
);
}
});
const schema = new GraphQLSchema(schemaConfig);
return { schema, report: options.report };
}
Example #9
Source File: index.ts From graphql-mesh with MIT License | 4 votes |
/**
* Creates the field object for the given operation.
*/
function getFieldForOperation<TSource, TContext, TArgs>(
operation: Operation,
baseUrl: string,
data: PreprocessingData<TSource, TContext, TArgs>,
requestOptions: RequestOptions<TSource, TContext, TArgs>,
connectOptions: ConnectOptions,
includeHttpDetails: boolean,
pubsub: MeshPubSub,
logger: Logger
): GraphQLFieldConfig<TSource, TContext | SubscriptionContext, TArgs> {
// Create GraphQL Type for response:
const type = getGraphQLType({
def: operation.responseDefinition,
data,
operation,
includeHttpDetails,
logger,
}) as GraphQLOutputType;
const payloadSchemaName = operation.payloadDefinition ? operation.payloadDefinition.graphQLInputObjectTypeName : null;
const args: Args = getArgs({
/**
* Even though these arguments seems redundent because of the operation
* argument, the function cannot be refactored because it is also used to
* create arguments for links. The operation argument is really used to pass
* data to other functions.
*/
requestPayloadDef: operation.payloadDefinition,
parameters: operation.parameters,
operation,
data,
includeHttpDetails,
logger,
});
// Get resolver and subscribe function for Subscription fields
if (operation.operationType === GraphQLOperationType.Subscription) {
const responseSchemaName = operation.responseDefinition ? operation.responseDefinition.graphQLTypeName : null;
const resolve = getPublishResolver({
operation,
responseName: responseSchemaName,
data,
logger,
});
const subscribe = getSubscribe({
operation,
payloadName: payloadSchemaName,
data,
baseUrl,
connectOptions,
pubsub,
logger,
});
return {
type,
resolve,
subscribe,
args,
description: operation.description,
};
// Get resolver for Query and Mutation fields
} else {
const resolve = data.options.resolverMiddleware(
() => ({
operation,
payloadName: payloadSchemaName,
data,
baseUrl,
requestOptions,
logger,
}),
getResolver
);
return {
type,
resolve,
args,
description: operation.description,
};
}
}