graphql#GraphQLFieldConfigMap TypeScript Examples
The following examples show how to use
graphql#GraphQLFieldConfigMap.
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 |
getFields(rootType: RootType): GraphQLFieldConfigMap<any, any> {
const fields: GraphQLFieldConfigMap<any, any> =
rootType === 'query'
? {
description: {
type: GraphQLString,
resolve: () => {
return this.soapEndpoint.description();
},
},
}
: {};
this.soapEndpoint.services().forEach((service: SoapService) => {
if (this.options.includeServices) {
const fieldName = service.name();
fields[fieldName] = this.createSoapServiceField(service, rootType);
} else if (this.options.includePorts) {
service.ports().forEach((port: SoapPort) => {
const fieldName = port.name();
fields[fieldName] = this.createSoapPortField(service, port, rootType);
});
} else {
service.ports().forEach((port: SoapPort) => {
port.operations().forEach((operation: SoapOperation) => {
const fieldConfig = this.createSoapOperationField(operation, rootType);
if (fieldConfig) {
fields[operation.name()] = fieldConfig;
}
});
});
}
});
return fields;
}
Example #2
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 #3
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 #4
Source File: schema-resolver.ts From graphql-mesh with MIT License | 6 votes |
private createObjectTypeConfig(soapType: SoapObjectType): GraphQLObjectTypeConfig<any, any> {
const fields = (): GraphQLFieldConfigMap<any, any> => {
const fieldMap: GraphQLFieldConfigMap<any, any> = {};
this.appendObjectTypeFields(fieldMap, soapType);
return fieldMap;
};
const interfaces = (): GraphQLInterfaceType[] => {
const interfaces: GraphQLInterfaceType[] = [];
this.appendInterfaces(interfaces, soapType);
return interfaces;
};
return {
name: this.options.outputNameResolver(soapType),
fields,
interfaces,
};
}
Example #5
Source File: schema-resolver.ts From graphql-mesh with MIT License | 6 votes |
private appendObjectTypeFields(fieldMap: GraphQLFieldConfigMap<any, any>, soapType: SoapObjectType): void {
soapType.fields.forEach((soapField: SoapField) => {
fieldMap[soapField.name] = {
type: this.resolve(soapField),
};
});
if (soapType.base) {
this.appendObjectTypeFields(fieldMap, soapType.base);
}
}
Example #6
Source File: schema-resolver.ts From graphql-mesh with MIT License | 6 votes |
private createInterfaceTypeConfig(soapType: SoapObjectType): GraphQLInterfaceTypeConfig<any, any> {
const fields = (): GraphQLFieldConfigMap<any, any> => {
const fieldMap: GraphQLFieldConfigMap<any, any> = {};
this.appendInterfaceTypeFields(fieldMap, soapType);
return fieldMap;
};
return {
name: this.options.interfaceNameResolver(soapType),
fields,
// should never be called, since the schema will not contain ambigous return types
resolveType: (value: any, context: any, info: GraphQLResolveInfo) => {
throw Error('no interface resolving available');
},
};
}
Example #7
Source File: schema-resolver.ts From graphql-mesh with MIT License | 6 votes |
private appendInterfaceTypeFields(fieldMap: GraphQLFieldConfigMap<any, any>, soapType: SoapObjectType): void {
soapType.fields.forEach((soapField: SoapField) => {
fieldMap[soapField.name] = {
type: this.resolve(soapField),
};
});
if (soapType.base) {
this.appendObjectTypeFields(fieldMap, soapType.base);
}
}
Example #8
Source File: visitor.ts From proto2graphql with MIT License | 6 votes |
function visitFields<TSource, TContext, TArgs>(
fields: protobuf.Field[],
context: Context
): GraphQLFieldConfigMap<TSource, TContext, TArgs> {
return Object.assign(
{},
...fields.map(field =>
field.partOf
? {
[field.partOf.name]: {
type: visitOneOf(field.partOf, context)
}
}
: {
[field.name]: {
type: visitFieldType(field, context)
}
}
)
);
}
Example #9
Source File: auth_builder.ts From graphql-mesh with MIT License | 5 votes |
/**
* Gets the viewer Object, resolve function, and arguments
*/
function getViewerOT<TSource, TContext, TArgs>(
name: string,
protocolName: string,
securityType: string,
queryFields: GraphQLFieldConfigMap<any, any>,
data: PreprocessingData<TSource, TContext, TArgs>,
logger: Logger
): Viewer<TSource, TContext, TArgs> {
const scheme: ProcessedSecurityScheme = data.security[protocolName];
// Resolve function:
const resolve = (root: any, args: any, context: any) => {
const security = {};
const saneProtocolName = Oas3Tools.sanitize(protocolName, Oas3Tools.CaseStyle.camelCase);
security[Oas3Tools.storeSaneName(saneProtocolName, protocolName, data.saneMap, logger)] = args;
/**
* Viewers are always root, so we can instantiate _openAPIToGraphQL here without
* previously checking for its existence
*/
return {
_openAPIToGraphQL: {
security,
},
};
};
// Arguments:
/**
* Do not sort because they are already "sorted" in preprocessing.
* Otherwise, for basic auth, "password" will appear before "username"
*/
const args = {};
if (typeof scheme === 'object') {
for (const parameterName in scheme.parameters) {
args[parameterName] = { type: new GraphQLNonNull(GraphQLString) };
}
}
let typeDescription = `A viewer for security scheme '${protocolName}'`;
/**
* HTTP authentication uses different schemes. It is not sufficient to name
* only the security type
*/
let description =
securityType === 'http'
? `A viewer that wraps all operations authenticated via security scheme ` +
`'${protocolName}', which is of type 'http' '${scheme.def.scheme}'`
: `A viewer that wraps all operations authenticated via security scheme ` +
`'${protocolName}', which is of type '${securityType}'`;
if (data.oass.length !== 1) {
typeDescription += ` in OAS '${scheme.oas.info?.title}'`;
description = `, in OAS '${scheme.oas.info?.title}`;
}
return {
type: new GraphQLObjectType({
name: Oas3Tools.capitalize(name), // Should already be sanitized and in camelCase
description: typeDescription,
fields: () => queryFields,
}),
resolve,
args,
description,
};
}
Example #10
Source File: auth_builder.ts From graphql-mesh with MIT License | 5 votes |
/**
* Create an object containing an AnyAuth viewer, its resolve function,
* and its args.
*/
function getViewerAnyAuthOT<TSource, TContext, TArgs>(
name: string,
queryFields: GraphQLFieldConfigMap<any, any>,
data: PreprocessingData<TSource, TContext, TArgs>,
includeHttpDetails: boolean,
logger: Logger
): Viewer<TSource, TContext, TArgs> {
let args = {};
for (const protocolName in data.security) {
// Create input object types for the viewer arguments
const def = createDataDef(
{ fromRef: protocolName },
data.security[protocolName].schema,
true,
data,
data.security[protocolName].oas,
logger
);
const type = getGraphQLType({
def,
data,
isInputObjectType: true,
includeHttpDetails,
logger,
});
const saneProtocolName = Oas3Tools.sanitize(protocolName, Oas3Tools.CaseStyle.camelCase);
args[Oas3Tools.storeSaneName(saneProtocolName, protocolName, data.saneMap, logger)] = { type };
}
args = sortObject(args);
// Pass object containing security information to fields
const resolve = (root: any, args: any, context: any) => {
return {
_openAPIToGraphQL: {
security: args,
},
};
};
return {
type: new GraphQLObjectType({
name: Oas3Tools.capitalize(name), // Should already be GraphQL safe
description: 'Warning: Not every request will work with this viewer type',
fields: () => queryFields,
}),
resolve,
args,
description: `A viewer that wraps operations for all available ` + `authentication mechanisms`,
};
}
Example #11
Source File: schema_builder.ts From graphql-mesh with MIT License | 4 votes |
/**
* Creates an (input) object type or return an existing one, and stores it
* in data
*
* A returned GraphQLObjectType has the following internal structure:
*
* new GraphQLObjectType({
* name // Optional name of the type
* description // Optional description of type
* fields // REQUIRED returning fields
* type // REQUIRED definition of the field type
* args // Optional definition of types
* resolve // Optional function defining how to obtain this type
* })
*/
function createOrReuseOt<TSource, TContext, TArgs>({
def,
operation,
data,
iteration,
isInputObjectType,
includeHttpDetails,
logger,
}: CreateOrReuseComplexTypeParams<TSource, TContext, TArgs>):
| GraphQLObjectType
| GraphQLInputObjectType
| GraphQLScalarType {
const translationLogger = logger.child('translation');
// Try to reuse a preexisting (input) object type
// CASE: query - reuse object type
if (!isInputObjectType) {
if (def.graphQLType && typeof def.graphQLType !== 'undefined') {
translationLogger.debug(
() =>
`Reuse object type '${def.graphQLTypeName}'` +
(typeof operation === 'object' ? ` (for operation '${operation.operationString}')` : '')
);
return def.graphQLType as GraphQLObjectType | GraphQLInputObjectType | GraphQLScalarType;
}
// CASE: mutation - reuse input object type
} else {
if (def.graphQLInputObjectType && typeof def.graphQLInputObjectType !== 'undefined') {
translationLogger.debug(
() =>
`Reuse input object type '${def.graphQLInputObjectTypeName}'` +
(typeof operation === 'object' ? ` (for operation '${operation.operationString}')` : '')
);
return def.graphQLInputObjectType as GraphQLInputObjectType;
}
}
// Cannot reuse preexisting (input) object type, therefore create one
const schema = def.schema;
const description = schema.description;
// CASE: query - create object type
if (!isInputObjectType) {
translationLogger.debug(
() =>
`Create object type '${def.graphQLTypeName}'` +
(typeof operation === 'object' ? ` (for operation '${operation.operationString}')` : '')
);
def.graphQLType = new GraphQLObjectType({
name: def.graphQLTypeName,
description,
fields: () => {
return createFields({
def,
links: def.links,
operation,
data,
iteration,
isInputObjectType: false,
includeHttpDetails,
logger,
}) as GraphQLFieldConfigMap<TSource, TContext>;
},
});
return def.graphQLType;
// CASE: mutation - create input object type
} else {
translationLogger.debug(
() =>
`Create input object type '${def.graphQLInputObjectTypeName}'` +
(typeof operation === 'object' ? ` (for operation '${operation.operationString}')` : '')
);
def.graphQLInputObjectType = new GraphQLInputObjectType({
name: def.graphQLInputObjectTypeName,
description,
fields: () => {
return createFields({
def,
links: {},
operation,
data,
iteration,
isInputObjectType: true,
includeHttpDetails,
logger,
}) as GraphQLInputFieldConfigMap;
},
});
return def.graphQLInputObjectType;
}
}
Example #12
Source File: schema_builder.ts From graphql-mesh with MIT License | 4 votes |
/**
* Creates the fields object to be used by an (input) object type
*/
function createFields<TSource, TContext, TArgs>({
def,
links,
operation,
data,
iteration,
isInputObjectType,
includeHttpDetails,
logger,
}: CreateFieldsParams<TSource, TContext, TArgs>): GraphQLFieldConfigMap<any, any> | GraphQLInputFieldConfigMap {
const translationLogger = logger.child('translation');
let fields: GraphQLFieldConfigMap<any, any> = {};
if (includeHttpDetails && !isInputObjectType) {
fields.httpDetails = {
type: GraphQLJSON,
resolve: root => root?._openAPIToGraphQL?.data,
};
}
const fieldTypeDefinitions = def.subDefinitions as {
[fieldName: string]: DataDefinition;
};
// Create fields for properties
for (const fieldTypeKey in fieldTypeDefinitions) {
const fieldTypeDefinition = fieldTypeDefinitions[fieldTypeKey];
const fieldSchema = fieldTypeDefinition.schema;
// Get object type describing the property
const objectType = getGraphQLType({
def: fieldTypeDefinition,
operation,
data,
iteration: iteration + 1,
isInputObjectType,
includeHttpDetails,
logger,
});
const requiredProperty =
typeof def.required === 'object' && def.required.includes(fieldTypeKey) && !fieldTypeDefinition.schema.nullable;
// Finally, add the object type to the fields (using sanitized field name)
if (objectType) {
const saneFieldTypeKey = Oas3Tools.sanitize(
fieldTypeKey,
!data.options.simpleNames ? Oas3Tools.CaseStyle.camelCase : Oas3Tools.CaseStyle.simple
);
const sanePropName = Oas3Tools.storeSaneName(saneFieldTypeKey, fieldTypeKey, data.saneMap, logger);
fields[sanePropName] = {
type: (requiredProperty ? new GraphQLNonNull(objectType) : objectType) as GraphQLOutputType,
description: typeof fieldSchema === 'object' ? fieldSchema.description : null,
};
} else {
handleWarning({
mitigationType: MitigationTypes.CANNOT_GET_FIELD_TYPE,
message:
`Cannot obtain GraphQL type for field '${fieldTypeKey}' in ` +
`GraphQL type '${JSON.stringify(def.schema)}'.`,
data,
logger: translationLogger,
});
}
}
if (
typeof links === 'object' && // Links are present
!isInputObjectType // Only object type (input object types cannot make use of links)
) {
for (const saneLinkKey in links) {
translationLogger.debug(`Create link '${saneLinkKey}'...`);
// Check if key is already in fields
if (saneLinkKey in fields) {
handleWarning({
mitigationType: MitigationTypes.LINK_NAME_COLLISION,
message:
`Cannot create link '${saneLinkKey}' because parent ` +
`object type already contains a field with the same (sanitized) name.`,
data,
logger: translationLogger,
});
} else {
const link = links[saneLinkKey];
// Get linked operation
let linkedOpId;
// TODO: href is yet another alternative to operationRef and operationId
if (typeof link.operationId === 'string') {
linkedOpId = link.operationId;
} else if (typeof link.operationRef === 'string') {
linkedOpId = linkOpRefToOpId({
links,
linkKey: saneLinkKey,
operation,
data,
logger,
});
}
/**
* linkedOpId may not be initialized because operationRef may lead to an
* operation object that does not have an operationId
*/
if (typeof linkedOpId === 'string' && linkedOpId in data.operations) {
const linkedOp = data.operations[linkedOpId];
// Determine parameters provided via link
const argsFromLink = link.parameters;
// Get arguments that are not provided by the linked operation
let dynamicParams = linkedOp.parameters;
if (typeof argsFromLink === 'object') {
dynamicParams = dynamicParams.filter(param => {
return typeof argsFromLink[param.name] === 'undefined';
});
}
// Get resolve function for link
const linkResolver = data.options.resolverMiddleware(
() => ({
operation: linkedOp,
argsFromLink: argsFromLink as { [key: string]: string },
data,
baseUrl: data.options.baseUrl,
requestOptions: data.options.requestOptions,
logger,
}),
getResolver
);
// Get arguments for link
const args = getArgs({
parameters: dynamicParams,
operation: linkedOp,
data,
includeHttpDetails,
logger,
});
// Get response object type
const resObjectType =
linkedOp.responseDefinition.graphQLType !== undefined
? linkedOp.responseDefinition.graphQLType
: getGraphQLType({
def: linkedOp.responseDefinition,
operation,
data,
iteration: iteration + 1,
isInputObjectType: false,
includeHttpDetails,
logger,
});
let description = link.description;
if (data.options.equivalentToMessages && description) {
description += `\n\nEquivalent to ${linkedOp.operationString}`;
}
// Finally, add the object type to the fields (using sanitized field name)
// TODO: check if fields already has this field name
fields[saneLinkKey] = {
type: resObjectType as GraphQLOutputType,
resolve: linkResolver,
args,
description,
};
} else {
handleWarning({
mitigationType: MitigationTypes.UNRESOLVABLE_LINK,
message: `Cannot resolve target of link '${saneLinkKey}'`,
data,
logger: translationLogger,
});
}
}
}
}
fields = sortObject(fields);
return fields;
}
Example #13
Source File: index.ts From graphql-mesh with MIT License | 4 votes |
async getMeshSource() {
const { schemaHeaders, serviceName, operationHeaders } = this.config;
const thriftAST = await this.idl.getWithSet(async () => {
const rawThrift = await readFileOrUrl<string>(this.config.idl, {
allowUnknownExtensions: true,
cwd: this.baseDir,
headers: schemaHeaders,
});
const parseResult = parse(rawThrift, { organize: false });
if (parseResult.type === SyntaxType.ThriftErrors) {
throw new AggregateError(parseResult.errors);
}
return parseResult;
});
const enumTypeMap = new Map<string, GraphQLEnumType>();
const outputTypeMap = new Map<string, GraphQLOutputType>();
const inputTypeMap = new Map<string, GraphQLInputType>();
const rootFields: GraphQLFieldConfigMap<any, any> = {};
const annotations: IThriftAnnotations = {};
const methodAnnotations: IMethodAnnotations = {};
const methodNames: string[] = [];
const methodParameters: {
[methodName: string]: number;
} = {};
type TypeVal = BaseTypeVal | ListTypeVal | SetTypeVal | MapTypeVal | EnumTypeVal | StructTypeVal | VoidTypeVal;
type BaseTypeVal = {
id?: number;
type: TType.BOOL | TType.BYTE | TType.DOUBLE | TType.I16 | TType.I32 | TType.I64 | TType.STRING;
};
type ListTypeVal = { id?: number; type: TType.LIST; elementType: TypeVal };
type SetTypeVal = { id?: number; type: TType.SET; elementType: TypeVal };
type MapTypeVal = { id?: number; type: TType.MAP; keyType: TypeVal; valType: TypeVal };
type EnumTypeVal = { id?: number; type: TType.ENUM };
type StructTypeVal = { id?: number; type: TType.STRUCT; name: string; fields: TypeMap };
type VoidTypeVal = { id?: number; type: TType.VOID };
type TypeMap = Record<string, TypeVal>;
const topTypeMap: TypeMap = {};
class MeshThriftClient<Context = any> extends ThriftClient<Context> {
public static readonly serviceName: string = serviceName;
public static readonly annotations: IThriftAnnotations = annotations;
public static readonly methodAnnotations: IMethodAnnotations = methodAnnotations;
public static readonly methodNames: Array<string> = methodNames;
public readonly _serviceName: string = serviceName;
public readonly _annotations: IThriftAnnotations = annotations;
public readonly _methodAnnotations: IMethodAnnotations = methodAnnotations;
public readonly _methodNames: Array<string> = methodNames;
public readonly _methodParameters?: {
[methodName: string]: number;
} = methodParameters;
writeType(typeVal: TypeVal, value: any, output: TProtocol) {
switch (typeVal.type) {
case TType.BOOL:
output.writeBool(value);
break;
case TType.BYTE:
output.writeByte(value);
break;
case TType.DOUBLE:
output.writeDouble(value);
break;
case TType.I16:
output.writeI16(value);
break;
case TType.I32:
output.writeI32(value);
break;
case TType.I64:
output.writeI64(value.toString());
break;
case TType.STRING:
output.writeString(value);
break;
case TType.STRUCT: {
output.writeStructBegin(typeVal.name);
const typeMap = typeVal.fields;
for (const argName in value) {
const argType = typeMap[argName];
const argVal = value[argName];
if (argType) {
output.writeFieldBegin(argName, argType.type, argType.id);
this.writeType(argType, argVal, output);
output.writeFieldEnd();
}
}
output.writeFieldStop();
output.writeStructEnd();
break;
}
case TType.ENUM:
// TODO: A
break;
case TType.MAP: {
const keys = Object.keys(value);
output.writeMapBegin(typeVal.keyType.type, typeVal.valType.type, keys.length);
for (const key of keys) {
this.writeType(typeVal.keyType, key, output);
const val = value[key];
this.writeType(typeVal.valType, val, output);
}
output.writeMapEnd();
break;
}
case TType.LIST:
output.writeListBegin(typeVal.elementType.type, value.length);
for (const element of value) {
this.writeType(typeVal.elementType, element, output);
}
output.writeListEnd();
break;
case TType.SET:
output.writeSetBegin(typeVal.elementType.type, value.length);
for (const element of value) {
this.writeType(typeVal.elementType, element, output);
}
output.writeSetEnd();
break;
}
}
readType(type: TType, input: TProtocol): any {
switch (type) {
case TType.BOOL:
return input.readBool();
case TType.BYTE:
return input.readByte();
case TType.DOUBLE:
return input.readDouble();
case TType.I16:
return input.readI16();
case TType.I32:
return input.readI32();
case TType.I64:
return BigInt(input.readI64().toString());
case TType.STRING:
return input.readString();
case TType.STRUCT: {
const result: any = {};
input.readStructBegin();
while (true) {
const field: IThriftField = input.readFieldBegin();
const fieldType = field.fieldType;
const fieldName = field.fieldName || 'success';
if (fieldType === TType.STOP) {
break;
}
result[fieldName] = this.readType(fieldType, input);
input.readFieldEnd();
}
input.readStructEnd();
return result;
}
case TType.ENUM:
// TODO: A
break;
case TType.MAP: {
const result: any = {};
const map = input.readMapBegin();
for (let i = 0; i < map.size; i++) {
const key = this.readType(map.keyType, input);
const value = this.readType(map.valueType, input);
result[key] = value;
}
input.readMapEnd();
return result;
}
case TType.LIST: {
const result: any[] = [];
const list = input.readListBegin();
for (let i = 0; i < list.size; i++) {
const element = this.readType(list.elementType, input);
result.push(element);
}
input.readListEnd();
return result;
}
case TType.SET: {
const result: any[] = [];
const list = input.readSetBegin();
for (let i = 0; i < list.size; i++) {
const element = this.readType(list.elementType, input);
result.push(element);
}
input.readSetEnd();
return result;
}
}
}
async doRequest(methodName: string, args: any, fields: TypeMap, context?: any) {
const Transport = this.transport;
const Protocol = this.protocol;
const writer: TTransport = new Transport();
const output: TProtocol = new Protocol(writer);
const id = this.incrementRequestId();
output.writeMessageBegin(methodName, MessageType.CALL, id);
this.writeType(
{
name: pascalCase(methodName) + '__Args',
type: TType.STRUCT,
fields,
id,
},
args,
output
);
output.writeMessageEnd();
const data: Buffer = await this.connection.send(writer.flush(), context);
const reader: TTransport = this.transport.receiver(data);
const input: TProtocol = new Protocol(reader);
const { fieldName, messageType }: IThriftMessage = input.readMessageBegin();
if (fieldName === methodName) {
if (messageType === MessageType.EXCEPTION) {
const err: TApplicationException = TApplicationExceptionCodec.decode(input);
input.readMessageEnd();
return Promise.reject(err);
} else {
const result = this.readType(TType.STRUCT, input);
input.readMessageEnd();
if (result.success != null) {
return result.success;
} else {
throw new TApplicationException(
TApplicationExceptionType.UNKNOWN,
methodName + ' failed: unknown result'
);
}
}
} else {
throw new TApplicationException(
TApplicationExceptionType.WRONG_METHOD_NAME,
'Received a response to an unknown RPC function: ' + fieldName
);
}
}
}
const thriftHttpClient = createHttpClient(MeshThriftClient, {
...this.config,
requestOptions: {
headers: operationHeaders,
},
});
function processComments(comments: Comment[]) {
return comments.map(comment => comment.value).join('\n');
}
function getGraphQLFunctionType(
functionType: FunctionType,
id = Math.random()
): { outputType: GraphQLOutputType; inputType: GraphQLInputType; typeVal: TypeVal } {
let inputType: GraphQLInputType;
let outputType: GraphQLOutputType;
let typeVal: TypeVal;
switch (functionType.type) {
case SyntaxType.BinaryKeyword:
case SyntaxType.StringKeyword:
inputType = GraphQLString;
outputType = GraphQLString;
break;
case SyntaxType.DoubleKeyword:
inputType = GraphQLFloat;
outputType = GraphQLFloat;
typeVal = typeVal! || { type: TType.DOUBLE };
break;
case SyntaxType.VoidKeyword:
typeVal = typeVal! || { type: TType.VOID };
inputType = GraphQLVoid;
outputType = GraphQLVoid;
break;
case SyntaxType.BoolKeyword:
typeVal = typeVal! || { type: TType.BOOL };
inputType = GraphQLBoolean;
outputType = GraphQLBoolean;
break;
case SyntaxType.I8Keyword:
inputType = GraphQLInt;
outputType = GraphQLInt;
typeVal = typeVal! || { type: TType.I08 };
break;
case SyntaxType.I16Keyword:
inputType = GraphQLInt;
outputType = GraphQLInt;
typeVal = typeVal! || { type: TType.I16 };
break;
case SyntaxType.I32Keyword:
inputType = GraphQLInt;
outputType = GraphQLInt;
typeVal = typeVal! || { type: TType.I32 };
break;
case SyntaxType.ByteKeyword:
inputType = GraphQLByte;
outputType = GraphQLByte;
typeVal = typeVal! || { type: TType.BYTE };
break;
case SyntaxType.I64Keyword:
inputType = GraphQLBigInt;
outputType = GraphQLBigInt;
typeVal = typeVal! || { type: TType.I64 };
break;
case SyntaxType.ListType: {
const ofTypeList = getGraphQLFunctionType(functionType.valueType, id);
inputType = new GraphQLList(ofTypeList.inputType);
outputType = new GraphQLList(ofTypeList.outputType);
typeVal = typeVal! || { type: TType.LIST, elementType: ofTypeList.typeVal };
break;
}
case SyntaxType.SetType: {
const ofSetType = getGraphQLFunctionType(functionType.valueType, id);
inputType = new GraphQLList(ofSetType.inputType);
outputType = new GraphQLList(ofSetType.outputType);
typeVal = typeVal! || { type: TType.SET, elementType: ofSetType.typeVal };
break;
}
case SyntaxType.MapType: {
inputType = GraphQLJSON;
outputType = GraphQLJSON;
const ofTypeKey = getGraphQLFunctionType(functionType.keyType, id);
const ofTypeValue = getGraphQLFunctionType(functionType.valueType, id);
typeVal = typeVal! || { type: TType.MAP, keyType: ofTypeKey.typeVal, valType: ofTypeValue.typeVal };
break;
}
case SyntaxType.Identifier: {
const typeName = functionType.value;
if (enumTypeMap.has(typeName)) {
const enumType = enumTypeMap.get(typeName)!;
inputType = enumType;
outputType = enumType;
}
if (inputTypeMap.has(typeName)) {
inputType = inputTypeMap.get(typeName)!;
}
if (outputTypeMap.has(typeName)) {
outputType = outputTypeMap.get(typeName)!;
}
typeVal = topTypeMap[typeName];
break;
}
default:
throw new Error(`Unknown function type: ${util.inspect(functionType)}!`);
}
return {
inputType: inputType!,
outputType: outputType!,
typeVal: {
...typeVal!,
id,
},
};
}
const { args: commonArgs, contextVariables } = parseInterpolationStrings(Object.values(operationHeaders || {}));
const headersFactory = getInterpolatedHeadersFactory(operationHeaders);
for (const statement of thriftAST.body) {
switch (statement.type) {
case SyntaxType.EnumDefinition:
enumTypeMap.set(
statement.name.value,
new GraphQLEnumType({
name: statement.name.value,
description: processComments(statement.comments),
values: statement.members.reduce(
(prev, curr) => ({
...prev,
[curr.name.value]: {
description: processComments(curr.comments),
value: curr.name.value,
},
}),
{} as GraphQLEnumValueConfigMap
),
})
);
break;
case SyntaxType.StructDefinition: {
const structName = statement.name.value;
const description = processComments(statement.comments);
const objectFields: GraphQLFieldConfigMap<any, any> = {};
const inputObjectFields: GraphQLInputFieldConfigMap = {};
const structTypeVal: StructTypeVal = {
id: Math.random(),
name: structName,
type: TType.STRUCT,
fields: {},
};
topTypeMap[structName] = structTypeVal;
const structFieldTypeMap = structTypeVal.fields;
for (const field of statement.fields) {
const fieldName = field.name.value;
let fieldOutputType: GraphQLOutputType;
let fieldInputType: GraphQLInputType;
const description = processComments(field.comments);
const processedFieldTypes = getGraphQLFunctionType(field.fieldType, field.fieldID?.value);
fieldOutputType = processedFieldTypes.outputType;
fieldInputType = processedFieldTypes.inputType;
if (field.requiredness === 'required') {
fieldOutputType = new GraphQLNonNull(fieldOutputType);
fieldInputType = new GraphQLNonNull(fieldInputType);
}
objectFields[fieldName] = {
type: fieldOutputType,
description,
};
inputObjectFields[fieldName] = {
type: fieldInputType,
description,
};
structFieldTypeMap[fieldName] = processedFieldTypes.typeVal;
}
outputTypeMap.set(
structName,
new GraphQLObjectType({
name: structName,
description,
fields: objectFields,
})
);
inputTypeMap.set(
structName,
new GraphQLInputObjectType({
name: structName + 'Input',
description,
fields: inputObjectFields,
})
);
break;
}
case SyntaxType.ServiceDefinition:
for (const fnIndex in statement.functions) {
const fn = statement.functions[fnIndex];
const fnName = fn.name.value;
const description = processComments(fn.comments);
const { outputType: returnType } = getGraphQLFunctionType(fn.returnType, Number(fnIndex) + 1);
const args: GraphQLFieldConfigArgumentMap = {};
for (const argName in commonArgs) {
const typeNameOrType = commonArgs[argName].type;
args[argName] = {
type:
typeof typeNameOrType === 'string' ? inputTypeMap.get(typeNameOrType) : typeNameOrType || GraphQLID,
};
}
const fieldTypeMap: TypeMap = {};
for (const field of fn.fields) {
const fieldName = field.name.value;
const fieldDescription = processComments(field.comments);
let { inputType: fieldType, typeVal } = getGraphQLFunctionType(field.fieldType, field.fieldID?.value);
if (field.requiredness === 'required') {
fieldType = new GraphQLNonNull(fieldType);
}
args[fieldName] = {
type: fieldType,
description: fieldDescription,
};
fieldTypeMap[fieldName] = typeVal;
}
rootFields[fnName] = {
type: returnType,
description,
args,
resolve: async (root, args, context, info) =>
thriftHttpClient.doRequest(fnName, args, fieldTypeMap, {
headers: headersFactory({ root, args, context, info, env: process.env }),
}),
};
methodNames.push(fnName);
methodAnnotations[fnName] = { annotations: {}, fieldAnnotations: {} };
methodParameters[fnName] = fn.fields.length + 1;
}
break;
case SyntaxType.TypedefDefinition: {
const { inputType, outputType } = getGraphQLFunctionType(statement.definitionType, Math.random());
const typeName = statement.name.value;
inputTypeMap.set(typeName, inputType);
outputTypeMap.set(typeName, outputType);
break;
}
}
}
const queryObjectType = new GraphQLObjectType({
name: 'Query',
fields: rootFields,
});
const schema = new GraphQLSchema({
query: queryObjectType,
});
return {
schema,
contextVariables,
};
}