You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm using TypeORM together with type-graphql. I would like to buid a factory that build boths entities and grapqhQL schema, based on an interface. The main requirement behind is to create entites and resolvers to manage google apis that have sometimes more than 50 fields. I would like to avoid re-listing all api schemas. So I'm trying to build a factory.
I'm trying to do this by achieving 4 steps:
1- converting the interface to a class (generic factory convert function)
2- using this class to create the entity (still generic)
3- using this class to create the @ObjectType and @inputType
4- creating the resolver. (generic resolver)
Unfortunately, when building the schema, I end up with an error " Cannot determine GraphQL output type for getAllItems
I know that the issue is not in the resolver by itself, as if I create a simple class with @ObjectType, @inputType along with the entity, it works fine.
The problem are the steps before, i.e. when trying to create the Entity with a generic and abstract class or the ObjectType, InputType also using an abstract class.
I'm struggling with this for a while, any help would be appreciated.
Below is the factory part, as well as a very simple example that fails.
Factory code
import {
Arg,
ClassType,
Field,
ID,
InputType,
MiddlewareFn,
Mutation,
ObjectType,
Query,
Resolver,
UseMiddleware
} from "type-graphql";
import { Column, Entity, PrimaryColumn } from "typeorm";
// Convert GoogleSchema (interface) to Class
function BaseClass<T extends object>() {
return (function(this: T, data: T) {
Object.assign(this, data);
} as any) as new (arg: T) => T;
}
// create a entity based on class
export function GoogleApiSchemaToEntity<TGSchema>(
entityName: string,
dbSchema: string
) {
@Entity({
name: entityName,
schema: dbSchema
})
abstract class GoogleApiGenericEntity {
@PrimaryColumn({
type: "character varying",
length: 255,
nullable: false,
unique: true
})
id: string;
@Column()
schema: TGSchema;
}
return GoogleApiGenericEntity;
}
// convert Google Schema to TypeGraphQL type definituin
export default function GoogleApiSchemaToClass<TGSchema>(
TGSchemaClass: ClassType<TGSchema>
) {
@ObjectType({ isAbstract: true })
abstract class GoogleApiGenericClass {
@Field(() => ID)
id: string;
@Field(() => [TGSchemaClass])
schema: TGSchema[];
}
return GoogleApiGenericClass;
}
// generic resolver
function createGoogleApiResolvers<T extends ClassType, X extends ClassType>(
suffix: string,
outputType: T,
inputType: X,
entity: any,
middleware?: Array<MiddlewareFn<any>>
) {
@Resolver()
class GoogleApiBaseResolvers {
// get all items of entity
@UseMiddleware(...(middleware || []))
@Query(() => [outputType!]!, {
nullable: true,
name: `getAll${suffix}`
})
async getAllItems(): Promise<T[] | null> {
let items: T[] | null = null;
items = await entity.find();
return items;
}
// update an item
@UseMiddleware(...(middleware || []))
@Mutation(() => outputType!, { nullable: true, name: `updateOne${suffix}` })
async updateOneItem(
@Arg("data", () => inputType) data: X
): Promise<T | null> {
let item: T | null = new entity();
let val: any = "";
if (!data.hasOwnProperty("id")) {
return null;
}
val = data.hasOwnProperty("id");
item = (await entity.findOne({ id: val })) || null;
if (!item) {
return null;
}
await entity.update({ id: val }, { data });
return item;
}
}
return GoogleApiBaseResolvers;
}
Simple test to call the factory
// test :
interface test {
field1: string;
filed2: string;
}
// create entity base on test schema
class GOrgUnitEntity extends GoogleApiSchemaToEntity<test>("test", "public") {}
// Convert Schema$Orgunit to Class
class GOrgUnitsClass extends BaseClass<test>() {}
// create object type
@ObjectType()
export class GoogleOrganizationUnitsOutputType extends GoogleApiSchemaToClass<
GOrgUnitsClass
>(GOrgUnitsClass) {
@Field(() => [String])
otherInfo: string[];
}
@InputType()
export class GoogleOrganizationUnitsInputType extends GoogleApiSchemaToClass<
GOrgUnitsClass
>(GOrgUnitsClass) {
@Field(() => [String])
otherInfo: string[];
}
export const GOrgUnitsResolver = createGoogleApiResolvers(
"GOrgUnits",
GoogleOrganizationUnitsOutputType,
GoogleOrganizationUnitsInputType,
GOrgUnitEntity,
[]
);
// schema buidling : error is here
// Cannot determine GraphQL output type for getAllItems
const initApolloServer = async (): Promise<ApolloServer> => {
try {
const schema: GraphQLSchema = await buildSchema({
resolvers: [
GOrgUnitsResolver
]
});
const apolloServer: ApolloServer = new ApolloServer({
schema,
context: ({ req, res, info }: any) => ({ req, res, info }),
formatError: (err: GraphQLError) => FormatErrorMessageGraphQlServer(err)
});
The text was updated successfully, but these errors were encountered:
I end up with an error "Cannot determine GraphQL output type for getAllItems
When I run this code, I get "Error: Cannot determine GraphQL output type for schema"
Looks like GOrgUnitsClass used in GoogleApiSchemaToClass<GOrgUnitsClass>(GOrgUnitsClass) has to be decorated with @ObjectType() and @Fields() decorators.
Otherwise, use GraphQL JSON scalar and loose type safety.
"Looks like GOrgUnitsClass used in GoogleApiSchemaToClass(GOrgUnitsClass) has to be decorated with @ObjectType() and @fields() decorators."
By doing this, if I understand well, it means I had to retype all the interface definition, and add @field to the GOrgUnitsClass ?
This what I'd like to avoid. Is there a way to avoid this ?
And yes, sometimes the error is the one you mentionned, or the one I have reported. That's why I'm lost ;-)
Hi,
I'm using TypeORM together with type-graphql. I would like to buid a factory that build boths entities and grapqhQL schema, based on an interface. The main requirement behind is to create entites and resolvers to manage google apis that have sometimes more than 50 fields. I would like to avoid re-listing all api schemas. So I'm trying to build a factory.
I'm trying to do this by achieving 4 steps:
1- converting the interface to a class (generic factory convert function)
2- using this class to create the entity (still generic)
3- using this class to create the @ObjectType and @inputType
4- creating the resolver. (generic resolver)
Unfortunately, when building the schema, I end up with an error "
Cannot determine GraphQL output type for getAllItems
I know that the issue is not in the resolver by itself, as if I create a simple class with @ObjectType, @inputType along with the entity, it works fine.
The problem are the steps before, i.e. when trying to create the Entity with a generic and abstract class or the ObjectType, InputType also using an abstract class.
I'm struggling with this for a while, any help would be appreciated.
Below is the factory part, as well as a very simple example that fails.
Factory code
Simple test to call the factory
The text was updated successfully, but these errors were encountered: