Expense Tracker App Part-4

2023-06-08

Following up to the previous post, today I am going to re-attempt to setup the graphQL server in JS. Last time I was stuck at framework / library selection - not knowing whether to use Apollo / Express or something else. Found a new tutorial here which talks about how to setup GraphQL API using Express, and also goes into the benefits, and a type system overview. One important thing this page talks about is the distinction between the GraphQL Schema Language and GraphQL Query Language. Although the difference is subtle, the schema is defined in the Schema Language which then maps on to queries that can be used by the clients.

I am also just going to focus on setting up a basic recordTransaction call first - without any custom types since that seems to complicate things a bit. Once I have that setup and I understand the mechanics properly, I can move on to using the actual types I want to use.

Lesson learnt: Never bite more than you can chew!

Express JS

So I am going to start with using the Express JS framework since it’s the simplest from what I can see. Might migrate to Apollo later since it seems to have better support for more advanced use-cases. The framework provides utilities nad a set of libraries which allows developers to build APIs and webapps - so I imagine it can be used to build REST APIs as well and as such is more general-purpose than just my specific use-case. I tried the hello world on the Express website to make sure I understood some basics and was good to go!

GraphQL in Express JS

The Express JS GraphQL utilities provide nice functions to implement the complete schema definition and webserver components. The first step is to build a schema:

Schema Definition

The schema is the type specification using which the webserver would interact with client and is defined using the GraphQL Schema Language. It can be defined in the application code file itself, or separately and then loaded - but all examples I see for ExpressJS seem to only define in source code so I’ll go with that.

var graphql = require('graphql')

const schema = graphql.buildSchema(`
  type Mutation {
    recordTransaction(postedDate: Float, amount: Float, category: String, notes: String): ID
    }
`)

const schema_str = graphql.printSchema(schema)
console.log(`Schema: ${schema_str}`)

The output looks as follows:

user@hostname:/expense_tracker_app/backend/server$ node server.js 
Schema: type Mutation {
  recordTransaction(postedDate: Float, amount: Float, category: String, notes: String): ID
}

… which is what I would expect.

Resolver

A resolver determines how a schema type would be converted to/from javascript types. A resolver is called when processing the query / mutation type when the server gets the request and the body of the function can either fetch (for a query) or mutate (for a mutation) the state of the app.

The resolver for the simple mutation above looks like so:

const resolver = {
  recordTransaction: (transaction) => {
    console.log(`postedDate: ${transaction.postedDate} amount: ${transaction.amount}\
                 category: ${transaction.category} notes: ${transaction.notes}`)
    return '0'
  },
};

Tangent

It turns out that you need to have at least one query in the graphql schema, otherwise you get an Empty root Query error. So I just added a dummy query for the sake of it and moved forward.

Start the Express server

Last step is to create the express server. This seems very boilerplate-y so I’ll just reproduce the code here with a link to the reference documentation:

const app = express();
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true,
}));

const port = 4000
app.listen(port);
console.log(`Running transaction server on: ${port}`)

Here we’re just providing the schema definition, list of resolvers and whether or not to spin up the interactive graphiql interface. Once we proceed to http://localhost:4000/graphql we see the UI which allows us to interact with our server. I tested it out with a sample query as follows:

mutation 
{
  recordTransaction(postedDate:0.0, amount: 1.0, category: "test", notes: "this is a note")
}

The response seen on the server console is:

....
Running transaction server on: 4000
postedDate: 0 amount: 1 category: test notes: this is a note
postedDate: 0 amount: 1 category: test notes: this is a note
postedDate: 0 amount: 1 category: test notes: this is a note

This is exactly what I wanted! Great Success! Next step is to connect this server to the front end to see if I can push some data into the backend from the front end.

Sad news

Looking at the readme on the express-graphql github repo it looks like the project is deprecated and developers are asked to use alternatives. I will probably do some prototyping using this library and move to something more production-grade sooner rather than later.