# Module Generator Backend
Authenticated schema-inspection and generation endpoints; backend files rendered from Handlebars templates, frontend files written from a copied template plus source strings supplied by the admin app.
## Endpoints
Registered in `apps/backend/start/routes.ts`, all behind `middleware.auth()`:
| Method | Path | Purpose |
| ------ | ---------------------------- | -------------------------------------------------- |
| `GET` | `/makeModule/tables` | List eligible public PostgreSQL tables |
| `GET` | `/makeModule/columns/:table` | Return columns used to configure form/table fields |
| `POST` | `/makeModule/generate` | Generate selected frontend and backend assets |
## Database Inspection
`database_inspector.ts` reads `information_schema`: only the `public` schema, excluding framework/auth/access-control/migration/system tables. Columns ending in `_id` become belongs-to candidates; tables containing a `
_id` column become has-many candidates; searchable string/numeric columns are derived for resource controllers. **Relationship inference is heuristic** — review generated model imports, class and property names.
## Type Mapping
| Database category | Lucid TypeScript type | Vine type | Frontend type |
| --------------------- | --------------------- | --------- | --------------- |
| integer/numeric types | `number` | `number` | `number` |
| boolean | `boolean` | `boolean` | `boolean` |
| date/timestamp | `DateTime` | `date` | `IsoDateString` |
| other values | `string` | `string` | `string` |
Nullable columns get `| null` and optional validation; `created_at`, `updated_at`, `deleted_at` receive special handling.
## Backend Output
```txt
apps/backend/modules//
├── api/ # controller, create/update validators, routes.ts
├── config/permissions.ts
├── controller/_controller.ts
├── model/.ts
├── policy/_policy.ts
├── validators/ # _create/_update_validator.ts
└── routes.ts
apps/backend/tests/modules// # .spec.ts, .api.spec.ts
```
`` is the table name minus its final character — assumes a plural table name; review irregular plurals.
## Asset Behavior
- **Model** — `model.hbs` with columns, inferred relationships, searchable fields, optional password hashing.
- **Controller and routes** — authenticated resource controller with list/search/sort/pagination and CRUD; `routes.hbs` registers an `apiOnly` resource route with authentication.
- **Validators** — separate create/update Vine validators; primary keys and timestamp/deletion fields excluded; email, password, nullable, and trimming behavior inferred from names and metadata.
- **Policy and permissions** — Bouncer policy with view/create/update/delete, `config/permissions.ts`, and a lazy policy import added to `app/policies/main.ts` when missing. Slugs derive from the module name (`s.view`, `.create`, `.update`, `.delete`) — review already-plural names, this is not a general pluralization system.
- **API subtree** — a second CRUD controller and routes under `/api/` with validators and a test; imports the model for `modelToSchema` Swagger metadata. **The generated API template adds no authentication middleware — add auth and authorization before exposing the route.**
## Frontend Writes
The backend copies `apps/admin/src/modules/_template` to `apps/admin/src/modules/`, then writes the configured form (component + definition), datatable and list page, manage trigger, menu, module manifest, generated `config/meta.ts`, and database-derived `entities/Entity.ts`. See [frontend.md](./frontend.md).
## Extending
Handlebars helpers available: `eq`, `not`, `or`, `and`. To add a generated artifact: add the template under `apps/backend/app/templates/`, an explicit destination in the controller `paths` object (parent dir via existing path initialization), render only when its asset is selected, and pass normalized metadata — never query the database inside templates. Add generation tests for nullable values, dates, numerics, passwords, and irregular names; verify both builds. No hidden writes — every destination, including shared registries like `app/policies/main.ts`, stays visible in the controller flow and documented here.