# From GraphQL types to a PostgreSQL API with Simfinity.js

A series catalog starts with a small domain: a serie has a name, and each season belongs to a serie. Even that model needs list queries, create/update/delete operations, relationship resolvers, validation and database storage.

[Simfinity.js](https://simtlix.github.io/simfinity.js/) generates those recurring pieces from GraphQL object types. Version 3.2.0 provides MongoDB/Mongoose and PostgreSQL adapters, plus an optional package for exposing GraphQL operations as MCP tools. The project is open source under Apache-2.0.

This walkthrough uses the published PostgreSQL starter. It includes a nested series/season example, so there is a relationship to inspect as well as a working API.

## Start with the domain

The type definition uses the standard `graphql` package. A minimal entity looks like this:

```javascript
import {
  GraphQLID,
  GraphQLNonNull,
  GraphQLObjectType,
  GraphQLString,
} from 'graphql';

const SerieType = new GraphQLObjectType({
  name: 'Serie',
  fields: {
    id: { type: GraphQLID },
    name: { type: new GraphQLNonNull(GraphQLString) },
  },
});
```

Register the type with the PostgreSQL runtime, supplying the singular and plural operation names:

```javascript
import pg from 'pg';
import { createPostgres } from '@simtlix/simfinity-postgres';

const pool = new pg.Pool({
  connectionString: process.env.DATABASE_URL,
});
const simfinity = createPostgres({ pool, schema: 'series_api' });

simfinity.connect(null, SerieType, 'serie', 'series');
const schema = simfinity.createSchema();
await simfinity.initializeDatabase({ mode: 'create' });
```

The resulting schema can be served through GraphQL Yoga. The downloaded starter includes that server setup, shutdown handling, a `Season` type and a controller. The snippets above show the core registration flow; the starter is the complete application.

## Run the released starter

Use Node.js 22+ for the starter and PostgreSQL 15+. Download and extract the [v3.2.0 starter archive](https://simtlix.github.io/simfinity.js/releases/simfinity-3.2.0-starters.zip), then enter its `postgres` directory:

```sh
cd simfinity-3.2.0-starters/postgres
npm install
```

For a disposable local database, run:

```sh
docker run --name simfinity-postgres-demo -e POSTGRES_PASSWORD=simfinity -e POSTGRES_DB=series -p 127.0.0.1:5432:5432 -d postgres:18-alpine
```

In a POSIX shell, set the connection string and start the app:

```sh
export DATABASE_URL='postgresql://postgres:simfinity@127.0.0.1:5432/series'
npm start
```

In PowerShell, use `$env:DATABASE_URL = 'postgresql://postgres:simfinity@127.0.0.1:5432/series'` before `npm start`. If port 5432 is occupied, choose another host port and update the connection string. These credentials are for the disposable local example.

Open `http://127.0.0.1:4000/graphql`. Create a serie and its first season together:

```graphql
mutation {
  addserie(input: {
    name: "The Expanse"
    seasons: { added: [{ number: 1 }] }
  }) {
    id
    name
    createdBy
    seasons { id number }
  }
}
```

Then read it back:

```graphql
query {
  series {
    name
    seasons { number }
  }
}
```

The generated relationship resolves the season from its parent. PostgreSQL also has a real foreign key from the season's `serie` column to the serie table. The API relationship and the database constraint come from the relationship metadata in the type definitions.

## Add application rules where they belong

Generated CRUD is the starting point. Controllers and lifecycle hooks let you add domain behavior; validators, query scopes, state transitions and authorization rules provide other extension points.

Authentication remains application-owned. Configure the authorization policy and trusted request context for your deployment. The starter's fixed `quickstart-user` context is demonstration code, not a login system.

Storage initialization is explicit. `create` mode creates missing generated objects and checks existing definitions; `validate` mode checks the schema without DDL. Schema evolution still needs deliberate migrations.

## Expose selected operations to an MCP client

The optional `@simtlix/simfinity-mcp` package works with either database adapter. Once the application has initialized its GraphQL schema, tool definitions can be generated from selected operations:

```javascript
import { generateMCPTools } from '@simtlix/simfinity-mcp';

const { tools } = generateMCPTools(schema, {
  include: ['series'],
  limits: {
    maxPageSize: 100,
    defaultPagination: { page: 1, size: 20 },
  },
});

console.log(tools.map((tool) => tool.name));
```

Install that package separately when needed. Tool generation needs GraphQL; server/transport factories also use the optional MCP SDK. The [MCP guide](https://simtlix.github.io/simfinity.js/guide/mcp.html) covers transports, trusted context and authorization.

## Choosing a backend

Choose the adapter during application startup. PostgreSQL uses UUID identities, SQL constraints and its own native Model/Session APIs. MongoDB uses Mongoose, and generated mutations require a replica set or sharded cluster. Selecting an adapter does not migrate an existing database or translate arbitrary Mongoose calls into SQL.

Start with the [PostgreSQL quick start](https://simtlix.github.io/simfinity.js/guide/postgresql.html), review the [compatibility boundaries](https://simtlix.github.io/simfinity.js/compatibility.html), or explore the larger [Series Sample Project](https://github.com/simtlix/series-sample).

[Source code and issues](https://github.com/simtlix/simfinity.js)

The downloaded PostgreSQL starter was exercised locally with a nested create, query readback and database foreign-key inspection.
