# Database (https://v2.s3.dimah.dev/docs/db)

[`@dimah-s3/db`](https://www.npmjs.com/package/@dimah-s3/db) is an optional
plugin for [`dimahS3`](https://v2.s3.dimah.dev/docs/server/setup). It keeps object ownership, upload
state, folders, and deletion history aligned with S3 without custom SQL on
every endpoint.

dimah-s3 works without a database. Add this plugin when you need ownership
checks, usage totals and quotas, file listings with folders, or server-side
tracking of each upload.

## What the plugin does [#what-the-plugin-does]

- **Tracks objects**: writes a row when an upload starts, marks it active on
  confirm, and updates it on delete.
- **Enforces ownership**: each file belongs to a scope you define (for
  example `user:123`), and upload tickets are bound to it. Download requires
  a confirmed (`active`) object owned by that scope, and delete rejects
  another scope. This is per-caller tenancy, not the route `keyPrefix`
  check: prefix isolation always runs in
  [`@dimah-s3/server`](https://v2.s3.dimah.dev/docs/server/security#route-namespace-vs-ownership).
- **Lists files**: by scope on the server, and by folder, search, and sort
  in the browser.
- **Adds folders**: logical folders, renames, moves, and typed attributes
  per object. Folders never change the S3 key.
- **Caps usage**: checks a quota at upload and again with the verified size
  at confirm.

Authentication, quota values, and business rules stay application-owned.
The plugin manages object metadata and scope isolation, and compares usage
with the limits your application supplies.

## Lifecycle [#lifecycle]

Each object moves through these statuses:

| Status    | Meaning                                               |
| --------- | ----------------------------------------------------- |
| `pending` | Upload started, not confirmed                         |
| `active`  | Confirmed in S3, with the verified size stored        |
| `deleted` | Removed from S3, row kept (soft delete)               |
| `purging` | Expired before confirm, and being cleaned up by purge |

Typical flow: pending → active → deleted. A pending row expires with its
upload ticket, and [purge](https://v2.s3.dimah.dev/docs/db/purge) cleans up rows that never reached
`active`.

## Next steps [#next-steps]

<Cards>
  <Card
    title="Database Setup"
    href="/docs/db/setup"
    description="Install, create the tables, and register the plugin."
  />
  <Card
    title="Database Lifecycle Hooks"
    href="/docs/db/lifecycle-hooks"
    description="Guards and hooks the plugin attaches to each route."
  />
  <Card
    title="API"
    href="/docs/db/api"
    description="List, move, and annotate objects, manage folders, set quotas."
  />
  <Card
    title="Purge Stale Uploads"
    href="/docs/db/purge"
    description="Clean up uploads that never confirmed."
  />
  <Card
    title="Upgrade the Schema"
    href="/docs/db/upgrade"
    description="Move a 1.x database to schema 2.0.0."
  />
  <Card
    title="Full example"
    href="https://github.com/dimah-kz/dimah-s3/tree/v2/examples/with-db"
    description="Next.js + Drizzle file manager with folders and a quota."
  />
</Cards>
