'Building a REST API using Express, Firestore, Cloud Functions & TypeScript

Been looking into building a REST API for my app, and trying to follow along tutorials for Firestore & Cloud Functions. Unfortunately they all seem to be outdated or straight up don't work at all. Getting slightly frustrated as I'm new to all this and just trying to get CRUD operations working to have samples to go on. One tutorial example is written very well, but also doesn't work: https://blog.logrocket.com/rest-api-firebase-cloud-functions-typescript-firestore/

The Tutorial code at least compiles, and after a tweak also gives responses. The "GetAll" works, but the addEntry / POST simply doesn't read the body of the request and returns the "title" variable as undefined and I have no idea what is going on. Any help, or pointer to a tutorial that ACTUALLY works, would be so much appreciated.

// firebase.ts

import * as admin from 'firebase-admin'

admin.initializeApp()
admin.firestore().settings({ignoreUndefinedProperties:true});

const db = admin.firestore()

export { admin, db }

...

// entryController.ts

import { Response } from 'express'
import { db } from './config/firebase'

type EntryType = {
  title: string,
  text: string,
  coverImageUrl: string
}

type Request = {
  body: EntryType,
  params: { entryId: string }
}

const addEntry = async (req: Request, res: Response) => {
  const { title, text } = req.body

  try {
    const entry = db.collection('entries').doc()
    const entryObject = {
      id: entry.id,
      title,
      text
    }

    entry.set(entryObject)

    res.status(200).send({
      status: 'success',
      message: 'entry added successfully',
      data: entryObject
    })
  } catch(error) {
      res.status(500).json(error.message)
  }
}

const getAllEntries = async (req: Request, res: Response) => {
  try {
    const allEntries: EntryType[] = []
    const querySnapshot = await db.collection('entries').get()
    querySnapshot.forEach((doc: any) => allEntries.push(doc.data()))
    return res.status(200).json(allEntries)
  } catch(error) { return res.status(500).json(error.message) }
}

export { addEntry, getAllEntries }

...

// index.ts

import * as functions from 'firebase-functions'
import * as express from 'express'

import { addEntry, getAllEntries } from './entryController'

const api = express()

api.get('/', (req, res) => res.status(200).send('Hey there!'))
api.post('/entries', addEntry)

api.get('/entries', getAllEntries)

exports.api = functions.https.onRequest(api)

...

// response in Postman

{
    "status": "success",
    "message": "entry added successfully",
    "data": {
        "id": "nPOELy2D3OHXuy4LJ2ib"
    }
}


Solution 1:[1]

I also followed through the same tutorial, and kind of struggled to get the functions working.. (partially due to my mistake), but I found a youtube tutorial on the same topic, and this helped me immensely. https://www.youtube.com/watch?v=T8SZv6h2WbY
The contents are pretty much the same as that written article, but a step by step video tutorial somehow made it easier to understand and follow through. He also provides a github code for the video so if you want a quick comparison, head over to the github - https://github.com/ebenezerdon/journal-rest-api Hope this helps debug your problem. (The controller code looks pretty much the same as what I have. Maybe there's something different with how you are making the POST request?)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Katie