Open nierennakker opened 6 years ago
please provide a proposal how do you see it implemented in vesper and lets see if we can do that
It should be possible to use the discriminator column to determine the type of the interface. Using that, writing a custom resolveType
function shouldn't be needed.
interface Test {
id: ID!
var: String!
}
type First implements Test {
id: ID!
var: String!
first: Int!
}
type Second implements Test {
id: ID!
var: String!
second: String!
}
@Entity()
@TableInheritance({ column: 'type' })
@TypeResolver('type' /* or { name: 'Test', column: 'type' } */)
class Test {
@PrimaryGeneratedColumn()
public id!: string;
@Column()
public var!: string;
@Column()
@DiscriminatorType({ first: 'First', second: 'Second' })
public type!: string; // internally matches the value of this column
}
@ChildEntity()
class First extends Test {
@Column()
public first!: number;
}
@ChildEntity()
class Second extends Test {
@Column()
public second!: string;
}
I want to know how to query interface result as well. for example we have:
interface Test {
id: ID!
var: String!
}
type First implements Test {
id: ID!
var: String!
first: Int!
}
type Second implements Test {
id: ID!
var: String!
second: String!
}
And we have our table like this:
@Entity()
@TableInheritance({ column: 'type' })
@TypeResolver('type' /* or { name: 'Test', column: 'type' } */)
class Test {
@PrimaryGeneratedColumn()
public id!: string;
@Column()
public var!: string;
@Column()
@DiscriminatorType({ first: 'First', second: 'Second' })
public type!: string; // internally matches the value of this column
}
@ChildEntity()
class First extends Test {
@Column()
public first!: number;
}
@ChildEntity()
class Second extends Test {
@Column()
public second!: string;
}
and we have query like this:
type Query {
tests: [Test]
}
Which supposes to return all records from First
and Second
, can vesper help making a union query? Joinmonster has instruction on how to do union / interface query https://join-monster.readthedocs.io/en/latest/unions/, we may be able to do something similar.
I'm using GraphQL interfaces along with TypeORM single table inheritance with Vesper. You just need to provide the resolveType
for the GraphQL interface, like this in your case:
const schema = await buildVesperSchema({
...
customResolvers: {
Test: {
__resolveType: data => data.constructor.name,
},
},
...
});
You'll now be able to use your query like this:
{
tests {
id
var
... on First {
first
}
... on Second {
second
}
}
}
Yeah @vfaramond, that's what I did in our projects too. Resolving interfaces is easy, but querying multiple entities which implements the interface at the same time can be tricky. I need to write custom sql query to union
the result myself.
e.g. I have 2 entities called Foo
and Bar
which implements Baz
, which is an abstract class
// Baz.ts
abstract class Baz {
@PrimaryGeneratedColumn() id: string;
@Column() baz: string;
}
// Foo.ts
class Foo extends Baz {
@Column() foo: string;
}
// Bar.ts
class Bar extends Baz {
@Column() bar: string;
}
And I want to query both Foo
and Bar
at the same time using a query called bazs
and I can filter them based on their common field baz
interface Baz {
baz: String
}
type Foo implements Baz {
baz: String
foo: String
}
type Bar implements Baz {
baz: String
foo: String
}
type Query {
bazs(baz: String): [Baz]
}
When I resolve bazs
query, what I do atm is to return union result:
// BazController.ts
@Controller()
export class BazController {
constructor(private readonly entityManager: EntityManager) {}
@Query()
async bazs(args: BazsArgs) {
const query = `
select id, baz, foo, NULL as bar from foo where foo.baz = $1
union
select id, baz, bar, NULL as foo from bar where bar.baz = $1`;
return this.entityManger.query(query, [args.baz]);
}
}
Because Vesper has automatic database relations resolver, I wonder if it can take 1 step further to help generate the interface query for us instead of us writing it ourselves.
Interface type and union type features are discussed at length on different use cases in other graphql server frameworks e.g. Prisma https://github.com/prismagraphql/prisma/issues/83, https://github.com/prismagraphql/prisma/issues/165. As an alternative to Prisma, I think it's good to at least know what's Vesper's plan on supporting these types.
First of all, thanks for this great framework!
I was wondering if I could use GraphQL interfaces with Vesper. I did some source digging, but I couldn't find anything about it. Also, when I run my server with an interface, a warning gets printed to the console: