← nopea.tech
ScaneaConsenteaMaskeaBundlesPricing
Frameworks

NestJS injectable service

Construct the Nopea instance once as a private field on the service -- every method on the class shares the same retry/redaction/budget config.

← All recipes
import { Injectable } from "@nestjs/common";
import { Controller, Post, Body } from "@nestjs/common";
import { Maskea, retries, secrets, budget } from "@nopeatech/maskea";
import OpenAI from "openai";

@Injectable()
export class ChatService {
  private openai = new OpenAI();
  private maskea = new Maskea()
    .use(retries({ max: 3 }))
    .use(budget({ maxMonthlyUsd: 50 }))
    .use(secrets({ mode: "mask" }));
  private chat = this.klaro.wrap(
    this.openai.chat.completions.create.bind(this.openai.chat.completions)
  );

  async ask(messages: { role: string; content: string }[]) {
    return this.chat({ model: "gpt-4o-mini", messages });
  }
}

@Controller("chat")
export class ChatController {
  constructor(private readonly chatService: ChatService) {}

  @Post()
  async chat(@Body() body: { messages: { role: string; content: string }[] }) {
    return this.chatService.ask(body.messages);
  }
}

Checked against the shipped @nopeatech/maskea API. Full docs at nopea.tech/maskea/docs.

More in Frameworks

Express route handler →Fastify route handler →Next.js App Router API route →Mask PII in a Next.js server action →