npm package: @ortha/server-platform-database
Description: Fastify plugin that initialises a [Sequelize](https://sequelize.org/) connection to PostgreSQL, registers plugin-provided schemas, and decorates the Fastify instance with `sequelize` and `models`.
Latest version: 0.0.4

# @ortha/server-platform-database

Fastify plugin that initialises a [Sequelize](https://sequelize.org/) connection to PostgreSQL, registers plugin-provided schemas, and decorates the Fastify instance with `sequelize` and `models`.

## Usage

```ts
import { bootstrap } from '@ortha/server-platform-bootstrap';
import { createDatabasePlugin } from '@ortha/server-platform-database';
import { identitySchema } from '@ortha/server-identity';

await bootstrap({
    config: bootstrapConfig,
    plugins: [
        createDatabasePlugin({
            ...databaseConfig,
            schemas: [identitySchema],
            sync: true // dev only — use migrations in production
        })
    ]
});

// fastify.sequelize — Sequelize ORM instance
// fastify.models    — frozen map of all registered models
```

### Lifecycle

1. **Connect** — authenticate with PostgreSQL.
2. **Define** — each schema's `define()` is called to initialise models.
3. **Associate** — each schema's `associate()` is called with the full model registry so cross-plugin relations work.
4. **Sync** _(optional)_ — `sequelize.sync({ alter: true })` for development.
5. **Cleanup** — close the connection when Fastify shuts down.

## Writing a Schema Definition

Each domain plugin exports a `SchemaDefinition`:

```ts
import { DataTypes } from 'sequelize';
import type {
    SchemaDefinition,
    ModelRegistry
} from '@ortha/server-platform-database';
import type { Sequelize, ModelStatic, Model } from 'sequelize';

const define = (sequelize: Sequelize): Record<string, ModelStatic<Model>> => {
    const Product = sequelize.define(
        'Product',
        {
            id: {
                type: DataTypes.UUID,
                defaultValue: DataTypes.UUIDV4,
                primaryKey: true
            },
            name: { type: DataTypes.STRING, allowNull: false }
        },
        { tableName: 'products' }
    );

    return { Product };
};

const associate = (models: ModelRegistry): void => {
    models.Product.belongsTo(models.User, { foreignKey: 'createdBy' });
};

export const catalogSchema: SchemaDefinition = Object.freeze({
    id: 'catalog',
    define,
    associate
});
```

## Configuration

`DatabaseConfig`:

| Property   | Type                              | Description                                       |
| ---------- | --------------------------------- | ------------------------------------------------- |
| `host`     | `string`                          | PostgreSQL hostname                               |
| `port`     | `number`                          | PostgreSQL port                                   |
| `name`     | `string`                          | Database name                                     |
| `user`     | `string`                          | Database user                                     |
| `password` | `string`                          | Database password                                 |
| `logging`  | `boolean`                         | Route Sequelize query logs through Fastify        |
| `schemas`  | `SchemaDefinition[]` _(optional)_ | Schema definitions from domain plugins            |
| `sync`     | `boolean` _(optional)_            | Call `sequelize.sync({ alter: true })` — dev only |

Environment variables (with defaults):

```
DB_HOST=localhost
DB_PORT=5432
DB_NAME=ortha
DB_USER=ortha
DB_PASSWORD=ortha
DB_LOGGING=false
```

## Local development

Start PostgreSQL via Docker Compose from the repo root:

```bash
docker compose up -d
```

## Building

```bash
nx build server-platform-database
```