Files

5.3 KiB

Module Generator Frontend

The generator UI collects module metadata, selected assets, form layout, and datatable configuration, converts it into TypeScript/TSX source strings, and sends them to the backend generator.

Responsibility Source (under apps/admin/src/devtools/)
Page submission, notifications, and mutation callbacks pages/ModuleGeneratorPage/index.tsx
Payload assembly pages/ModuleGeneratorPage/lib/buildGenerateModulePayload.ts
Form state, initial values, and sections view/forms/ModuleGeneratorForm/
Payload DTOs and HTTP client data/api/
React Query hooks data/queries/
Source-code builders data/builders/

The page submits through useGenerateModule; success resets the form and shows an alert, errors go through the shared React Query error helpers.

Metadata and Assets

Required metadata: name (frontend folder, backend module identity, route segment, permission-slug base), table (existing PostgreSQL table), generate (selected assets). Backend assets are all selected by default; form and datatable are opt-in.

Asset Workspace Output
model Backend Lucid model
controller Backend Authenticated resource controller and test
routes Backend Resource route registration
validator Backend Create and update Vine validators
policy Backend Bouncer policy and permission configuration
api Backend API controller, validators, routes, and test
form Frontend Form definition, component, and modal/sheet trigger
datatable Frontend List page table and menu entry

Before generation the UI reads GET /makeModule/tables (table selector) and GET /makeModule/columns/:table (field choices) — cached via React Query, columns disabled until a table is selected.

Payload Builders

buildGenerateModulePayload delegates to focused builders:

Builder Payload field Generated destination
FormSourceBuilder.buildComponent form view/forms/MainForm/Component.tsx
FormSourceBuilder.buildDefinition formDefinition view/forms/MainForm/form.ts
ManageTriggerSourceBuilder formDialog view/widgets/ManageTrigger.tsx
DataTableSourceBuilder dataTable view/widgets/DataTable.tsx
ListPageSourceBuilder list pages/ListPage/index.tsx
MenuSourceBuilder menu config/menu.ts
ModuleConfigSourceBuilder module config/module.ts

Form disabled → form, formDefinition, formDialog are null. Datatable disabled → dataTable and menu are null, and the list-page builder emits a page without a table.

Generated Frontend Architecture

apps/admin/src/modules/<name>/
├── api/           # create.ts, delete.ts, detailed.ts, keys.ts, list.ts, update.ts
├── config/        # translation/, menu.ts, messages.ts, meta.ts, module.ts, routing.tsx
├── entities/      # Entity.ts (from database columns)
├── pages/ListPage/
└── view/
    ├── forms/MainForm/    # Component.tsx, constants.ts, form.ts, index.ts, submit.ts
    ├── layouts/Layout.tsx
    └── widgets/           # DataTable.tsx, DeleteTrigger.tsx, ManageTrigger.tsx

api/ deliberately has no barrel file — each CRUD operation is its own file, imported directly (import { useCreate } from "../../../api/create"); keys.ts owns query key builders, list.ts/detailed.ts their invalidation helpers.

Layer ownership: entities/Entity.ts is shared by API hooks, forms, and widgets; api/ owns Axios calls, hooks, keys, and notifications; pages/ owns route composition and permission gates; view/forms/ owns schema, values, UI, and submission; view/widgets/ owns stateful interactions; config/ integrates routes, menu, translations, and permissions with the module registry.

Extending

To add a generated frontend artifact: add its configuration type under entities/, UI controls to ModuleGeneratorForm, a focused builder under data/builders/ (for dynamic source), the payload field to GenerateModulePayload + buildGenerateModulePayload, accept and write it in module_controller.ts, and add static structure to _template/ when every module needs it. Verify generation with and without the asset selected.