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

# @hile/http

> Build Koa HTTP APIs with file-system controllers, middleware, response plugins, and Zod validation.

# @hile/http

Build Koa HTTP APIs with file-system controllers, middleware, response plugins, and Zod validation.

## Choose This Package When

| User asks for                               | Use               | Also read                                                 |
| ------------------------------------------- | ----------------- | --------------------------------------------------------- |
| Create an HTTP endpoint or Koa middleware   | `@hile/http`      | `packages/http.md`, `recipes/http-api-model-typeorm.md`   |
| Run Next.js and API controllers on one port | `@hile/http-next` | `packages/http-next.md`, `recipes/http-next-fullstack.md` |

## Use When

Use `@hile/http` for Koa-based APIs, middleware, manual routes, file-system controllers, Zod validation, and response plugins.

## Do Not Use When

* Do not use it for Next.js pages; use `@hile/http-next` when Next.js and API routes share a port.
* Do not assume Zod validation mutates/coerces Koa context data. It validates only.

## Install

```bash theme={null}
pnpm add @hile/http
```

## Imports

```ts theme={null}
import { Http, defineController, createControllerMetadata, defineResponsePlugin } from '@hile/http'
import { z } from 'zod'
```

## Copy-Paste Example

```ts theme={null}
import { defineController } from '@hile/http'

export default defineController('GET', async () => {
  return { ok: true }
})
```

File route examples:

```text theme={null}
src/controllers/index.controller.ts -> /
src/controllers/users/index.controller.ts -> /users
src/controllers/users/[id].controller.ts -> /users/:id
```

## More Examples

```ts theme={null}
import { z } from 'zod'
import { createControllerMetadata, defineController } from '@hile/http'

const bodySchema = z.object({
  username: z.string().min(1),
  age: z.number().int().nonnegative(),
})

export default defineController(
  createControllerMetadata({
    method: 'POST',
    schema: { body: bodySchema },
  }),
  async (ctx) => {
    const body = bodySchema.parse(ctx.request.body)
    return { created: true, user: body }
  },
)
```

The second parse is intentional when you need parsed/coerced data. Hile's controller validation does not write `safeParse().data` back to `ctx.request.body`.

## Runtime And Lifecycle Notes

* `new Http({ port })` creates a Koa app and a `find-my-way` router.
* `http.use(middleware)` registers Koa middleware before `listen()`.
* `http.listen()` returns a close function.
* `http.load(directory, options)` scans `*.controller.{ts,js,tsx,jsx,mjs}` by suffix.
* `defineController()` supports method-only, method-plus-middlewares, and metadata-plus-Zod forms.
* Response plugins transform handler return values and set `ctx.body` when the final result is not `undefined`.

## Anti-Patterns

* Setting `ctx.body` and returning a value from the same controller.
* Loading controllers after starting only because an old example does it; prefer load before listen in new code.
* Using old validation examples that assume Zod coercion rewrote `ctx.query`.

## Verification Checklist

* Controller files default-export `defineController(...)` or an array of controllers.
* Controllers return response values.
* Boot service awaits `http.load()` before `http.listen()`.
* Zod schemas are used for validation, and parsed data is explicitly parsed when needed.

## Related Recipes

### HTTP API + Model + TypeORM

## Complete Example

Controller:

```ts theme={null}
// src/controllers/users/[id].controller.ts
import { defineController } from '@hile/http'
import { loadModel } from '@hile/model'
import { getUser } from '../../models/users/get-user.model'

export default defineController('GET', async (ctx) => {
  return loadModel(getUser, { userId: String(ctx.params.id) })
})
```

Model:

```ts theme={null}
// src/models/users/get-user.model.ts
import { defineModel } from '@hile/model'
import typeormService from '@hile/typeorm'
import { User } from '../../entities/user.entity'

export const getUser = defineModel({
  services: [typeormService] as const,
  async main([ds], input: { userId: string }) {
    const user = await ds.getRepository(User).findOneBy({ id: input.userId })
    if (!user) return { found: false }
    return { found: true, user }
  },
})
```

Boot file:

```ts theme={null}
// src/services/http.boot.ts
import { defineService } from '@hile/core'
import { Http } from '@hile/http'

export default defineService('http', async (shutdown) => {
  const http = new Http({ port: Number(process.env.HTTP_PORT ?? 3000) })
  await http.load(new URL('../controllers', import.meta.url).pathname)
  const close = await http.listen()
  shutdown(close)
  return http
})
```

Package config:

```json theme={null}
{
  "type": "module",
  "scripts": {
    "dev": "hile start --dev --env-file .env",
    "start": "hile start --env-file .env.prod"
  },
  "hile": {
    "auto_load_packages": ["@hile/typeorm"]
  }
}
```

## Package-Local AI Guide

This package also ships `AI.md` in npm so agents can read accurate examples after installation.
