6.2 KiB
Module Generator Backend
The backend generator exposes authenticated schema-inspection and generation endpoints. It renders backend files from Handlebars templates and writes frontend files using a copied template plus source strings supplied by the admin app.
Endpoints
Routes are registered in apps/backend/start/routes.ts.
| Method | Path | Controller method | Purpose |
|---|---|---|---|
GET |
/makeModule/tables |
tables |
List eligible public PostgreSQL tables |
GET |
/makeModule/columns/:table |
columns |
Return columns used to configure form/table fields |
POST |
/makeModule/generate |
generate |
Generate selected frontend and backend assets |
All three endpoints use middleware.auth().
Database Inspection
apps/backend/app/services/database_inspector.ts reads PostgreSQL information_schema.
- Table discovery is limited to the
publicschema. - framework, authentication, access-control, migration, and PostgreSQL system tables are excluded.
- columns provide
column_name,data_type, andis_nullable. - columns ending in
_idare treated as belongs-to relationship candidates. - tables containing a
<table>_idcolumn are treated as has-many relationship candidates. - searchable string and numeric columns are derived for generated resource controllers.
Relationship inference is heuristic. Review generated model imports, related class names, property names, and module availability.
Type Mapping
The controller maps database types separately for Lucid models, Vine validators, and frontend entities.
| 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 database columns receive | null in generated model/entity types and optional validation where applicable. created_at, updated_at, and deleted_at receive special handling.
Backend Output
For module name <name>, table <table>, and derived module class <ModuleName>, selected assets are written under:
apps/backend/modules/<ModuleName>/
├── api/
│ ├── controllers/<entity>_api_controller.ts
│ ├── validators/<entity>_create_api_validator.ts
│ ├── validators/<entity>_update_api_validator.ts
│ └── routes.ts
├── config/permissions.ts
├── controller/<entity>_controller.ts
├── model/<entity>.ts
├── policy/<entity>_policy.ts
├── validators/<entity>_create_validator.ts
├── validators/<entity>_update_validator.ts
└── routes.ts
Tests are written under:
apps/backend/tests/modules/<ModuleName>/
├── <entity>.spec.ts
└── <entity>.api.spec.ts
<entity> is derived by removing the final character from the selected table name. This assumes a plural table name and must be reviewed for irregular plurals.
Asset Behavior
Model
Renders apps/backend/app/templates/backend/model.hbs with columns, inferred relationships, searchable fields, and optional password hashing.
Controller and routes
Renders an authenticated resource controller with list/search/sort/pagination and CRUD actions. routes.hbs registers an apiOnly resource route and applies authentication.
Validators
Creates separate create and update Vine validators. Primary keys and timestamp/deletion fields are excluded according to controller rules. Email, password, nullable, and string trimming behavior is inferred from column names and database metadata.
Policy and permissions
Creates a Bouncer policy with view/create/update/delete checks, creates config/permissions.ts, and adds a lazy policy import to apps/backend/app/policies/main.ts when missing.
Permission slugs are derived from the module name, for example:
<name>s.view
<name>s.create
<name>s.update
<name>s.delete
Review names that are already plural because policy and frontend metadata derivation are not a general-purpose pluralization system.
API subtree
Creates a second CRUD controller and route group under /api/<entity>, plus API-specific validators and a test. The controller imports the generated model and passes it to modelToSchema for Swagger response metadata.
API routes currently do not add authentication middleware in the generated API template. Add the required authentication and authorization explicitly before exposing the route.
Frontend Writes Performed by the Backend
The backend copies apps/admin/src/modules/_template to apps/admin/src/modules/<name> and then writes:
- configured form component and form definition;
- configured datatable and list page;
- configured manage trigger, menu, and module manifest;
- generated
config/meta.ts; - database-derived
entities/Entity.ts.
See frontend.md for the complete frontend structure and payload ownership.
Template Helpers
The controller registers Handlebars helpers for eq, not, or, and and. New templates should use the existing render function and receive an explicit context object from the controller.
Extending the Backend Generator
- Add or update a Handlebars template under
apps/backend/app/templates/. - Add an explicit destination path in the controller
pathsobject. - Create its parent directory through the existing path initialization.
- Render only when the corresponding asset is selected.
- Pass normalized metadata rather than querying the database inside templates.
- Add generation tests for nullable values, dates, numeric types, passwords, and irregular names.
- Verify both backend and frontend builds after generation.
Avoid adding hidden writes. Every generated or modified destination, including shared registries such as app/policies/main.ts, should remain visible in the controller flow and documented here.