0.0.5 • Published 1 year ago

@biblioteksentralen/cloud-functions-foundation v0.0.5

Weekly downloads
-
License
ISC
Repository
-
Last release
1 year ago

Foundation for Cloud Function services

Express app with logging

To create a new Express app for Cloud Functions:

import { z } from "zod";
import { createRouter } from "@biblioteksentralen/cloud-functions-foundation";

const projectId = z.string().parse(process.env.GCP_PROJECT_ID);
const app = createApp({
  projectId,
  functionName: "api",
});

The app comes pre-configured with a Pino logging middleware with trace context from the request. The logger is added to the Express Request context, so it can be used in all request handlers:

app.get("/", async (req, res, next) => {
  req.log.info(`Hello log!`);
  // ...
});

The app is also registered with the Cloud Functions framework.

Error handling

This package provides functionality for error handling in Express 4 inspired by How to Handle Errors in Express with TypeScript.

Catching errors from async request handlers: We use express-async-errors to support throwing errors from async request handlers in Express 4. This will be supported out of the box in Express 5.

Defines AppError, a base class for known application errors. By default, these are shown in the response. If an error should not be output in responses, set isOperational: false. Unknown errors (errors not based on AppError) will never be shown. All errors (known and unknown) are logged.

import {
  AppError,
  errorHandler
} from "@biblioteksentralen/cloud-functions-foundation";

const getUserRequestHandler: RequestHandler = async (req, res, next) => {
  if (...) {
    throw new AppError('🔒 Unauthorized', {
      httpCode: 401
    });
  }
  res.end("Hello world");
};

app.get("/user", getUserRequestHandler);

// Error handler should be added at the very end, after all other handlers.
app.use(errorHandler);

There are also subclasses of AppError for common cases, such as ClientRequestError (yields 400 response) and Unauthorized (yields 401 response).

import {
  Unauthorized,
  errorHandler
} from "@biblioteksentralen/cloud-functions-foundation";

const getUserRequestHandler: RequestHandler = async (req, res, next) => {
  if (...) {
    throw new Unauthorized('🔒 Unauthorized');
  }
  res.end("Hello world");
};

app.get("/user", getUserRequestHandler);

// Error handler should be added at the very end, after all other handlers.
app.use(errorHandler);

Pub/Sub helpers

import { z } from "zod";
import {
  parsePubSubMessage,
  Request,
  Response,
} from "@biblioteksentralen/cloud-functions-foundation";

const messageSchema = z.object({
  table: z.string(),
  key: z.number(),
});

app.post("/", async (req: Request, res: Response) => {
  const message = parsePubSubMessage(req, messageSchema);
  // ...
});