Files
zero-fucks-given/docs/core/devtools/module-generator/backend.md
T

4.5 KiB

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 <table>_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

apps/backend/modules/<ModuleName>/
├── api/                     # controller, create/update validators, routes.ts
├── config/permissions.ts
├── controller/<entity>_controller.ts
├── model/<entity>.ts
├── policy/<entity>_policy.ts
├── validators/              # <entity>_create/_update_validator.ts
└── routes.ts

apps/backend/tests/modules/<ModuleName>/   # <entity>.spec.ts, <entity>.api.spec.ts

<entity> 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 (<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/<entity> 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/<name>, 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.

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.