> ## 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.

# Database

> TypeORM services, transactions, and model usage.

# Database

## 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"]
  }
}
```

## More Examples

TypeORM transaction with compensation:

```ts theme={null}
await transaction(ds, async (runner, rollback) => {
  const user = await runner.manager.save(User, input)
  rollback(() => redis.del(`user:${user.id}`))
  await runner.manager.save(AuditLog, { userId: user.id, action: 'create' })
  return user
})
```

Distributed scheduled job:

```ts theme={null}
const scheduler = new Scheduler()
scheduler.add('daily-report', '0 8 * * *', async () => {
  await sendDailyReport()
}, {
  distributed: {
    redis,
    ttl: 60_000,
    namespace: 'reports',
    policy: 'skip-if-locked',
  },
})
```

## Runtime And Lifecycle Notes

* `Cache(undefined)` removes the key unless negative caching is configured.
* `Cache#setExpire(seconds)` uses seconds.
* `defineCache` typed placeholders support `string`, `number`, and `boolean`.
* `RedisCache.loadCache()` returns `read`, `write`, `remove`, `has`, and `multi`.
* `RedisCache.removeTag(tag)` removes tagged cache entries.
* `fieldable` caches use Redis hashes and cannot combine with stale or negative cache options.
* `Scheduler.add()` supports cron strings and `{ delay }`.
* `Scheduler.load()` reads default exports from `*.schedule.*` files produced by `defineJob()`.
* `scanDirectory()` matches `.ts`, `.js`, `.tsx`, `.jsx`, and `.mjs`.

## Verification Checklist

* Manual Redis clients call `disconnect()` during cleanup.
* Manual TypeORM data sources call `destroy()` during cleanup.
* Cache keys include app/tenant prefixes when shared Redis is used.
* Scheduled jobs have clear duplicate-run policy.
