# Guide: Regular CRUD API

Use this path for a conventional Express service with generated CRUD routes, storage, route contracts, tests, Bruno, and OpenAPI.

## Create The Project

```bash
soap create billing-api \
  --db postgres \
  --auth jwt \
  --docs openapi \
  --contracts zod \
  --controller-layout per-route \
  --api-client bruno \
  --install \
  --git-init
```

Interactive equivalent:

```bash
soap create billing-api -i
```

In interactive mode, select:

- architecture: `regular`
- database: `postgres`
- auth: `jwt`
- docs: `openapi`
- contracts: `zod`
- controller layout: `per-route`
- API client: `bruno`
- install dependencies: yes when wanted
- git init: yes only when you want a new local repository

## Run The Service

```bash
cd billing-api
npm run build
npm test
npm start
```

Health check:

```bash
curl http://localhost:3000/health
```

## Add A CRUD Resource

```bash
soap add feature invoice \
  --crud \
  --db postgres \
  --auth jwt \
  --zone private \
  --field number:string \
  --field total:number \
  --field paid:boolean:optional \
  --bruno
```

Generated output includes:

- domain entity and entity spec
- repository port
- in-memory repository and repository spec
- Postgres SQL repository
- CRUD use-cases and use-case specs
- route contracts
- route controllers
- resource setup registration
- Bruno requests when Bruno is enabled

Use `--controller-layout per-feature` at project creation when you prefer one generated controller file per feature instead of one controller file per route.

## Add A Custom Route

```bash
soap add route approve --feature invoice \
  --method post \
  --path :id/approve \
  --auth jwt \
  --zone private \
  --policy custom:invoice-approver \
  --bruno
```

Route paths are scoped under the feature path. Feature names are not pluralized, so the example generates `/invoice/:id/approve`.

## Validate Generated Metadata

```bash
soap info
soap doctor
soap check routes
```

Run these after adding or removing resources/routes.

## Refresh API Artifacts

```bash
soap generate bruno
soap generate bruno --e2e
soap generate openapi --output openapi.json
```

`generate openapi` expects the service to be running.

## Safe Removal

```bash
soap remove route approve --feature invoice
soap remove feature invoice --dry-run
soap remove feature invoice
```

Modified generated files are skipped unless you use `--force` or `--on-conflict overwrite`.
