Skip to main content
Context is an object that provides access to HTTP request-related information during Sonamu API method execution. It can be injected as a parameter to API methods and is managed through AsyncLocalStorage.

Type Definition

type Context = {
  request: FastifyRequest;
  reply: FastifyReply;
  headers: IncomingHttpHeaders;
  createSSE: <T extends ZodObject>(events: T) => ReturnType<typeof createSSEFactory<T>>;
  naiteStore: NaiteStore;
  locale: string;
  /** Files uploaded in buffer mode */
  bufferedFiles?: BufferedFile[];
  /** Files uploaded in stream mode */
  uploadedFiles?: UploadedFile[];
} & AuthContext & ContextExtend;
The Context type is composed of Intersection Types (&):
  • Base Context object (request, reply, etc.)
  • AuthContext: Authentication-related properties (user, passport)
  • ContextExtend: Project-specific extension properties
This structure allows Context to be extensible while maintaining type safety.

Context Properties

request

request: FastifyRequest
The Fastify Request object representing the current HTTP request. Provides access to request URL, method, query parameters, etc.

reply

reply: FastifyReply
The Fastify Reply object representing the current HTTP response. Used for setting response headers, changing status codes, etc.

headers

headers: IncomingHttpHeaders
HTTP request headers. Same value as request.headers, provided for convenience.

createSSE

createSSE: <T extends ZodObject>(events: T) => ReturnType<typeof createSSEFactory<T>>
Function for creating Server-Sent Events (SSE) streams. Enables creating type-safe event streams using Zod schemas. Usage Example:
import { z } from "zod";

class MyModelClass extends BaseModel {
  @api()
  @stream({
    type: "sse",
    events: z.object({
      progress: z.object({ percent: z.number() }),
      complete: z.object({ result: z.string() })
    })
  })
  async processData(ctx: Context) {
    const sse = ctx.createSSE({
      progress: z.object({ percent: z.number() }),
      complete: z.object({ result: z.string() })
    });

    // Send progress
    await sse.send("progress", { percent: 50 });

    // Send completion event
    await sse.send("complete", { result: "done" });

    return sse.getResponse();
  }
}

naiteStore

naiteStore: NaiteStore
Storage used by the Naite testing framework. Used for storing mocked data or snapshot information during tests.

locale

locale: string
The locale (language setting) of the current request. This property always has a value. Parses the Accept-Language header and automatically selects one of the supported locales. If no match is found, the defaultLocale is used. Configuration Example:
// sonamu.config.ts
export default {
  i18n: {
    defaultLocale: "ko",
    supportedLocales: ["ko", "en", "ja"]
  }
} satisfies SonamuConfig;
Usage Example:
class PostModelClass extends BaseModel {
  @api({ httpMethod: "GET" })
  async findMany(ctx: Context) {
    const locale = ctx.locale; // "ko", "en", or "ja"

    // Return different responses based on locale
    const posts = await this.getPuri("r")
      .table("posts")
      .where("locale", locale)
      .select("*");

    return posts;
  }
}

bufferedFiles

bufferedFiles?: BufferedFile[]
List of files uploaded in buffer mode. This property exists when the @upload decorator is applied with the default mode (buffer) or mode: "buffer" configuration. Each file is loaded in memory, allowing flexible operations like MD5 calculation or image processing. BufferedFile Key Properties and Methods:
interface BufferedFile {
  // File information
  filename: string;       // Filename
  mimetype: string;       // MIME type (e.g., "image/png", "application/pdf")
  size: number;           // File size (bytes)
  extname: string;        // Extension (e.g., "png", "pdf")

  // File processing methods
  buffer: Buffer;                                          // File Buffer (getter)
  md5(): Promise<string>;                                  // Generate MD5 hash
  saveToDisk(diskName: string, key: string): Promise<string>;  // Save file and return URL
}
Basic Usage Example:
class FileModelClass extends BaseModel {
  @upload({ limits: { files: 10 } })
  async upload(): Promise<{ files: SonamuFile[] }> {
    const { bufferedFiles } = Sonamu.getContext();

    if (!bufferedFiles || bufferedFiles.length === 0) {
      throw new BadRequestException("No files uploaded");
    }

    const processedFiles = await Promise.all(
      bufferedFiles.map(async (file) => {
        const md5 = await file.md5();
        const key = `${md5}.${file.extname}`;
        return {
          name: file.filename,
          url: await file.saveToDisk("fs", key),
          mime_type: file.mimetype,
          size: file.size,
        };
      })
    );

    return { files: processedFiles };
  }
}
Image Processing Example:
import sharp from "sharp";

class ImageModelClass extends BaseModel {
  @upload({ limits: { files: 1 } })
  async uploadThumbnail(): Promise<{ url: string }> {
    const { bufferedFiles } = Sonamu.getContext();

    if (!bufferedFiles || bufferedFiles.length === 0) {
      throw new BadRequestException("No image uploaded");
    }

    const file = bufferedFiles[0];

    // Process image with Buffer (using getter)
    const thumbnail = await sharp(file.buffer)
      .resize(200, 200)
      .jpeg({ quality: 80 })
      .toBuffer();

    // Save processed image
    const disk = Sonamu.storage.use("fs");
    const key = `thumbnails/${await file.md5()}.jpg`;
    await disk.put(key, thumbnail);

    return { url: await disk.getUrl(key) };
  }
}

uploadedFiles

uploadedFiles?: UploadedFile[]
List of files uploaded in stream mode. This property exists when @upload({ mode: "stream" }) is configured. Files have already been streamed to storage, so only metadata like URL/key is accessible. This mode is suitable for large file uploads. UploadedFile Key Properties and Methods:
interface UploadedFile {
  // File information
  filename: string;       // Filename
  mimetype: string;       // MIME type (e.g., "image/png", "application/pdf")
  size: number;           // File size (bytes)
  extname: string;        // Extension (e.g., "png", "pdf")
  url: string;            // URL of the stored file
  signedUrl: string;      // Signed URL (with expiration)
  key: string;            // Key in storage
  diskName: string;       // Storage disk name

  // File processing methods
  download(): Promise<Buffer>;  // Download file from storage
}
Stream Mode Usage Example:
class FileModelClass extends BaseModel {
  @upload({ mode: "stream", limits: { files: 5 } })
  async uploadLargeFiles(): Promise<{ files: SonamuFile[] }> {
    const { uploadedFiles } = Sonamu.getContext();

    if (!uploadedFiles || uploadedFiles.length === 0) {
      throw new BadRequestException("No files uploaded");
    }

    // Already uploaded to storage
    return {
      files: uploadedFiles.map((file) => ({
        name: file.filename,
        url: file.url,
        mime_type: file.mimetype,
        size: file.size,
      })),
    };
  }
}
File Upload Handling:
  • Must be used with the @upload decorator
  • Buffer mode (default): Use bufferedFiles - loaded in memory, suitable for MD5 calculation/image processing
  • Stream mode: Use uploadedFiles - streamed directly to storage, suitable for large files
  • See @upload decorator documentation for more details

AuthContext Properties

Context also includes properties from AuthContext:
  • user: Current authenticated user information
  • passport: Authentication-related methods (login, logout)

Extending Context

To add custom properties to Context in your project, you can extend the ContextExtend interface:
// src/types.ts
declare module "sonamu" {
  interface ContextExtend {
    customProperty: string;
    helperMethod: () => void;
  }
}
These extended properties can be injected through contextProvider:
// sonamu.config.ts
export default {
  server: {
    apiConfig: {
      contextProvider: async (baseContext) => {
        return {
          ...baseContext,
          customProperty: "custom value",
          helperMethod: () => console.log("helper")
        };
      }
    }
  }
} satisfies SonamuConfig;