Cover Page
Backend Page
TypeScript with Express
Install dependencies
Change to your chatterd directory and install the PostgreSQL package:
server$ cd ~/reactive/chatterd
server$ pnpm install postgres
chatterd app
Edit main.ts:
server$ vi main.ts
and add the following import lines:
import postgres from 'postgres'
import type { Sql } from 'postgres'
We set up a pool of open connections to our PostgreSQL chatterdb database. Maintaining a pool of open connections avoids the cost of opening and closing a connection on every database operation. The password used in the call to postgress() must match the one you used when setting up Postgres earlier. The connection pool needs to be accessible to all the URL handlers, so we store it in a global variable chatterDB:
export let chatterDB: Sql
Right inside the try{} block, add:
chatterDB = postgres('postgres://chatter:chattchatt@localhost/chatterdb')
Find the initialization of app and add two routes right
after the route for /llmprompt. These serve Chatter’s two APIs: HTTP GET request, with URL endpoint getchatts/, and HTTP POST request, with endpoint postchatt/, invoking the get() or post() method respectively and each given its handler function:
.get('/getchatts/', handlers.getchatts)
.post('/postchatt/', handlers.postchatt)
The functions getchatts() and postchatt() will be implemented in handlers.ts.
We’re done with main.ts. Save and exit the file.
handlers.ts
Edit handlers.ts:
server$ vi handlers.ts
First add the following imports to the top of the file:
import { randomUUID } from 'crypto'
import type { PostgresError } from 'postgres'
import { chatterDB } from './main.js'
We define a Chatt interface to help postchatt() deserialize JSON
received from clients. Add these line right below the imports:
interface Chatt {
username: string
message: string
}
Now add a number of logging functions that, in case of error, prepare a corresponding JSON response to be returned to the client:
const logServerErr = (res: Response, errmsg: String): Response => {
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json(errmsg)
}
const logClientErr = (res: Response, errcode: number, errmsg: String): Response => {
return res.status(errcode).json(errmsg)
}
The handler getchatts() uses an open connection from the connection pool to query the database for stored chatts. By default, postgres.js retrieves each database row as a JSON object, whereas we want each row represented as an array of values only, without column name as tags. We achieve this by calling .values() on each retrieved row. Once all the rows from the database are retrieved, if no exception has been raised, we insert the resulting array of chatts into the response JSON object. Add getchatts() to your handlers.ts after the definition of the llmprompt() function.
export async function getchatts(req: Request, res: Response) {
try {
const chatts = await chatterDB`SELECT username, message, id, time FROM chatts`.values()
res.json(chatts)
} catch (error) {
logServerErr(res, `${error as PostgresError}`)
}
}
Similarly, postchatt() receives a posted chatt in the expected JSON format, deserializes into the Chatt interface, and inserts it into the database, using a connection from the pool. The UUID and time stamp of each chatt are generated at insertion time. Add postchatt() to the end of your handlers.ts:
export async function postchatt(req: Request, res: Response) {
let chatt: Chatt
try {
chatt = req.body
} catch (error) {
logClientErr(res, HttpStatus.UNPROCESSABLE_ENTITY, error.toString())
return
}
try {
await chatterDB`INSERT INTO chatts (username, message, id) VALUES (${chatt.username}, ${chatt.message}, ${randomUUID()})`
res.json({})
} catch (error) {
logClientErr(res, HttpStatus.BAD_REQUEST, `${error as PostgresError}`)
}
}
We’re done with handlers.ts. Save and exit the file.
Build and Test run
![]()
TypeScript is a compiled language, like C/C++ and unlike JavaScript and Python, which are an interpreted languages. This means you must run npx tsc each and every time you made changes to your code, for the changes to show up when you run node.
To build your server, transpile TypeScript into JavaScript:
server$ npx tsc
To run your server:
server$ sudo node main.js
# Hit ^C to end the test
You can test your implementation following the instructions in the Testing Chatter APIs section.
References
| Prepared by Sugih Jamin | Last updated July 27th, 2025 |