README
@literally/gql
One of the drawbacks of schema-first development is that graphql resolvers are defined separately from their type definitions. Unlike code-first development where type definitions and resolvers can be inlined.
But, the drawback of code-first development is that it's too verbose, and builds yet another layer of abstraction upon a language.
Can we use Javascript to enhance schema-fist development? All a schema is, is a string; and we already have ways of embedding expressions inside strings: ${expression}
. Using embedded string expressions to enhance a language with Javascript while preserving it's natural syntax was popularized in front-end programming with css-in-js
libraries like styled-components
. And it's an approach that also naturally fits for schema-first development.
We can embrace the schema-first string literal syntax, and inject resolvers as embedded expressions wrapped inside custom directives.
Here's an example:
gql`
type Query {
user(id: ID!): User! @resolve(${(_, { id }, { db }) => db.User.findMany({ id })})
notes(userId: ID!): [Notes]! @resolve(${(_, { userId }, { db }) => db.Note.findOne({ userId })})
}
type Mutation {
createNote(data: CreateNoteData!): Note! @resolve(${_, { data }, { db } => db.Note.create(data)})
}
type User {
id: ID!
username: String!
firstName: String!
lastName: String!
fullName: String! @resolve(${user => user.username})
notes: Notes! @resolve(${(user, _, { db }) => db.Note.findMany({ userId: user.id })})
}
type Notes {
id: ID!
doc: NoteDocument!
}
type CreateNoteData {
doc: NoteDocument!
}
scalar NoteDocument @resolve(${NoteDocumentScalar})
`