Relay support
Sofa is very opinionated on what it considers a model, it's a good thing to consider the Relay Design Pattern for Node, we don't need to have a method to query for each model, we simply have a node method that query all types that implements the Node interface.
interface Node {
id: ID!
}
type User implements Node {
id: ID!
displayName: String!
}
type UserEdge {
cursor: String!
node: User!
}
type PageInfo {
startCursor: String!
endCursor: String!
hasNextPage: Boolean!
hasPrevPage: Boolean!
}
type UserConnection {
edges: [UserEdge!]!
nodes: [User!]!
info: PageInfo!
}
type Query {
node(id: ID!): Node!
userConnection(
first: Int
last: Int
after: String
before: String
): UserConnection!
}
So my workaround while SOFA doesn't support this officially is the following:
import { useSofa, createSofa } from 'sofa-api';
import { wrapSchema, FilterObjectFields } from '@graphql-tools/wrap';
const nodes = schema.getImplementations(schema.getType('Node') as any)
.objects.map(({ name }) => name);
const sofaIgnore: string[] = [];
const sofaSchema = wrapSchema(graphSchema, [
new FilterObjectFields(
(typeName, fieldName) => {
if (!typeName) {
return true;
}
if (typeName.endsWith('Connection') && fieldName === 'nodes') {
// it will omit nodes, only listing edges for all connections
return false;
}
if (typeName.endsWith('Edge') && fieldName === 'node') {
// it will ignore and let a node inside an edge to retrieve full object node
sofaIgnore.push(`${typeName}.node`);
}
return true;
},
),
]);
const sofa = createSofa({
schema: sofaSchema,
ignore: sofaIgnore,
});
// Include nodes as models
sofa.models = Array.from(new Set(sofa.models.concat(nodes)));
app.use('/rest', useSofa(sofa));
The only problema that still remains that the workaround wont fix is the Node interface or interfaces in general, since Node only has the id field it only returns the id, interface should be spreading implemented object fields in the root level like:
query FetchNode ($id: ID!) {
node(id: $id) {
__typename
id
...on User {
displayName
}
}
}
Sure we can overwrite this with the execute option inside Sofa, but would be great if we could come with a better solution for Relay without the need to create a method for each model (node).