> ## Documentation Index
> Fetch the complete documentation index at: https://sonamu.cartanova.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Context

> Sonamu API Request Context Reference

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

```typescript theme={null}
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, session)
* `ContextExtend`: Project-specific extension properties

This structure allows Context to be extensible while maintaining type safety.

## Context Properties

### request

```typescript theme={null}
request: FastifyRequest;
```

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

### reply

```typescript theme={null}
reply: FastifyReply;
```

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

### headers

```typescript theme={null}
headers: IncomingHttpHeaders;
```

HTTP request headers. Same value as `request.headers`, provided for convenience.

### createSSE

```typescript theme={null}
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:**

```typescript theme={null}
import { z } from "zod";

const ProcessEventsSchema = z.object({
  progress: z.object({ percent: z.number() }),
  complete: z.object({ result: z.string() }),
});

class MyModelClass extends BaseModelClass {
  @stream({
    type: "sse",
    events: ProcessEventsSchema,
  })
  async processData(ctx: Context) {
    const sse = ctx.createSSE(ProcessEventsSchema);

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

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

    return sse;
  }
}
```

### naiteStore

```typescript theme={null}
naiteStore: NaiteStore;
```

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

### locale

```typescript theme={null}
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:**

```typescript theme={null}
// sonamu.config.ts
export default {
  i18n: {
    defaultLocale: "ko",
    supportedLocales: ["ko", "en", "ja"],
  },
} satisfies SonamuConfig;
```

**Usage Example:**

```typescript theme={null}
class PostModelClass extends BaseModelClass {
  @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

```typescript theme={null}
bufferedFiles?: BufferedFile[]
```

List of files uploaded in buffer mode. This property exists when the `@upload` decorator is applied with the default (`consume: "buffer"`) or `@upload({ consume: "buffer" })` configuration.

Each file is loaded in memory, allowing flexible operations like MD5 calculation or image processing.

**BufferedFile Key Properties and Methods:**

```typescript theme={null}
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:**

```typescript theme={null}
class FileModelClass extends BaseModelClass {
  @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:**

```typescript theme={null}
import sharp from "sharp";

class ImageModelClass extends BaseModelClass {
  @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

```typescript theme={null}
uploadedFiles?: UploadedFile[]
```

List of files uploaded in stream mode. This property exists when `@upload({ consume: "stream", destination: "..." })` 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:**

```typescript theme={null}
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:**

```typescript theme={null}
class FileModelClass extends BaseModelClass {
  @upload({ consume: "stream", destination: "s3", 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,
      })),
    };
  }
}
```

<Info>
  **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](/en/api-reference/decorators/upload) documentation for more details
</Info>

### AuthContext Properties

Context also includes properties from [AuthContext](/en/api-reference/context/auth-context):

* `user`: Current authenticated user information (`User | null`)
* `session`: Current session information (`Session | null`)

## Extending Context

To add custom properties to Context in your project, you can extend the `ContextExtend` interface:

```typescript theme={null}
// src/types.ts
declare module "sonamu" {
  interface ContextExtend {
    customProperty: string;
    helperMethod: () => void;
  }
}
```

These extended properties can be injected through `contextProvider`:

```typescript theme={null}
// sonamu.config.ts
export default {
  server: {
    apiConfig: {
      contextProvider: async (baseContext) => {
        return {
          ...baseContext,
          customProperty: "custom value",
          helperMethod: () => console.log("helper"),
        };
      },
    },
  },
} satisfies SonamuConfig;
```

## Related Documentation

* [AuthContext](/en/api-reference/context/auth-context)
* [Context Methods](/en/api-reference/context/methods)
* [Getting Context](/en/api-development/context/getting-context)
* [Custom Context](/en/api-development/context/custom-context)
