Files
neo/FIELD_TYPES_ARCHITECTURE.md

26 KiB

Field Types System Architecture

System Overview

┌─────────────────────────────────────────────────────────────────┐
│                         Frontend (Vue 3 + Nuxt)                  │
├─────────────────────────────────────────────────────────────────┤
│                                                                   │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │                    View Components                        │  │
│  ├───────────────────────────────────────────────────────────┤  │
│  │  ListView.vue    │  DetailView.vue   │   EditView.vue    │  │
│  │  - Data Table    │  - Read Display   │   - Form          │  │
│  │  - Search        │  - Sections       │   - Validation    │  │
│  │  - Sort/Filter   │  - Actions        │   - Sections      │  │
│  │  - Bulk Actions  │                   │                   │  │
│  └────────────────────────┬──────────────────────────────────┘  │
│                           │ uses                                 │
│  ┌────────────────────────▼──────────────────────────────────┐  │
│  │              FieldRenderer.vue                           │  │
│  │  Universal component for rendering any field type        │  │
│  │  - Handles LIST, DETAIL, EDIT modes                      │  │
│  │  - Type-aware rendering                                   │  │
│  │  - Validation support                                     │  │
│  └────────────────────────┬──────────────────────────────────┘  │
│                           │ uses                                 │
│  ┌────────────────────────▼──────────────────────────────────┐  │
│  │              shadcn-vue Components                       │  │
│  │  Input, Textarea, Select, Checkbox, Switch, Calendar,    │  │
│  │  Table, Badge, Dialog, Popover, etc.                     │  │
│  └───────────────────────────────────────────────────────────┘  │
│                                                                   │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │                   Composables                             │  │
│  ├───────────────────────────────────────────────────────────┤  │
│  │  useFields()          │   useViewState()                 │  │
│  │  - Map backend data   │   - CRUD operations              │  │
│  │  - Build configs      │   - State management             │  │
│  │  - Generate sections  │   - Navigation                   │  │
│  └───────────────────────────────────────────────────────────┘  │
│                                                                   │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │                   Type Definitions                        │  │
│  │  field-types.ts - TypeScript interfaces for field system │  │
│  └───────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘
                              │
                              │ HTTP/REST API
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                      Backend (NestJS)                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                   │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │                    Controllers                            │  │
│  ├───────────────────────────────────────────────────────────┤  │
│  │  SetupObjectController    │  RuntimeObjectController     │  │
│  │  - GET /objects           │  - GET /objects/:name        │  │
│  │  - GET /objects/:name     │  - GET /objects/:name/:id    │  │
│  │  - GET /ui-config ✨      │  - POST /objects/:name       │  │
│  │  - POST /objects          │  - PUT /objects/:name/:id    │  │
│  └────────────────────────┬────────────────┬─────────────────┘  │
│                           │                │                     │
│  ┌────────────────────────▼────────────────▼─────────────────┐  │
│  │                      Services                             │  │
│  ├───────────────────────────────────────────────────────────┤  │
│  │  ObjectService        │  FieldMapperService ✨           │  │
│  │  - CRUD operations    │  - Map field definitions         │  │
│  │  - Query building     │  - Generate UI configs           │  │
│  │  - Validation         │  - Default metadata              │  │
│  └────────────────────────┬──────────────────────────────────┘  │
│                           │                                      │
│  ┌────────────────────────▼──────────────────────────────────┐  │
│  │                      Models                               │  │
│  │  ObjectDefinition     │  FieldDefinition ✨              │  │
│  │  - Object metadata    │  - Field metadata                │  │
│  │                       │  - UIMetadata interface          │  │
│  └───────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘
                              │
                              │ Prisma/Knex
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                        Database (PostgreSQL)                     │
├─────────────────────────────────────────────────────────────────┤
│                                                                   │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │  object_definitions                                       │  │
│  │  - id, tenant_id, api_name, label, plural_label          │  │
│  │  - description, is_system, table_name                     │  │
│  └───────────────────────────────────────────────────────────┘  │
│                           │                                      │
│                           │ 1:many                                │
│                           ▼                                      │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │  field_definitions                                        │  │
│  │  - id, object_definition_id, api_name, label, type       │  │
│  │  - is_required, is_unique, is_system                      │  │
│  │  - ui_metadata (JSONB) ✨ NEW                            │  │
│  │    {                                                       │  │
│  │      placeholder, helpText, showOnList, showOnDetail,    │  │
│  │      showOnEdit, sortable, options, rows, min, max,      │  │
│  │      validationRules, format, prefix, suffix, etc.       │  │
│  │    }                                                       │  │
│  └───────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘

✨ = New/Enhanced component

Data Flow

1. Loading Object Definition

┌──────────┐      GET /api/setup/objects/Contact/ui-config      ┌──────────┐
│          │ ──────────────────────────────────────────────────> │          │
│ Frontend │                                                     │ Backend  │
│          │ <────────────────────────────────────────────────── │          │
└──────────┘      { objectDef with mapped fields }              └──────────┘
     │
     │ useFields().buildListViewConfig(objectDef)
     ▼
┌──────────────────────────────────────┐
│  ListViewConfig                      │
│  - objectApiName: "Contact"          │
│  - mode: "list"                      │
│  - fields: [                         │
│      {                                │
│        apiName: "firstName",         │
│        type: "text",                 │
│        showOnList: true,             │
│        ...                            │
│      }                                │
│    ]                                  │
└──────────────────────────────────────┘
     │
     │ Pass to ListView component
     ▼
┌──────────────────────────────────────┐
│  ListView renders data table         │
└──────────────────────────────────────┘

2. Fetching Records

┌──────────┐      GET /api/runtime/objects/Contact              ┌──────────┐
│          │ ──────────────────────────────────────────────────> │          │
│ Frontend │                                                     │ Backend  │
│          │ <────────────────────────────────────────────────── │          │
└──────────┘      [{ id, firstName, lastName, ... }]            └──────────┘
     │
     ▼
┌──────────────────────────────────────┐
│  ListView displays records           │
│  Each field rendered by              │
│  FieldRenderer with mode="list"      │
└──────────────────────────────────────┘

3. Field Rendering

┌─────────────────────────────────────────────────────────────┐
│  FieldRenderer                                              │
│  Props: { field, modelValue, mode }                        │
└────────────────────────┬────────────────────────────────────┘
                         │
        ┌────────────────┼────────────────┐
        │                │                │
        ▼                ▼                ▼
   mode="list"     mode="detail"    mode="edit"
        │                │                │
        ▼                ▼                ▼
  Simple text     Formatted         Input component
  or badge        display with      based on type:
  display         labels            - Input
                                    - Textarea
                                    - Select
                                    - DatePicker
                                    - Checkbox
                                    - etc.

4. Saving Record

┌──────────┐                                                    ┌──────────┐
│ EditView │ ──> User fills form ──> Validation                │          │
│          │                              │                     │          │
│          │                              ▼                     │          │
│          │                          Valid?                    │          │
│          │                          ✓ Yes                     │          │
│          │ @save event                │                       │          │
│          │ ──────────────────────────┘                       │          │
│          │                                                     │          │
│          │  POST/PUT /api/runtime/objects/Contact/:id        │ Backend  │
│ Frontend │ ──────────────────────────────────────────────────> │          │
│          │                                                     │          │
│          │ <────────────────────────────────────────────────── │          │
│          │      { saved record }                              │          │
│          │                                                     │          │
│          │ ──> Navigate to DetailView                        │          │
└──────────┘                                                    └──────────┘

Component Hierarchy

Page/App
└── ObjectViewContainer
    ├── ListView
    │   ├── Search/Filters
    │   ├── Table
    │   │   ├── TableHeader
    │   │   │   └── Sortable columns
    │   │   └── TableBody
    │   │       └── TableRow (for each record)
    │   │           └── TableCell (for each field)
    │   │               └── FieldRenderer (mode="list")
    │   └── Actions (Create, Export, etc.)
    │
    ├── DetailView
    │   ├── Header with actions
    │   └── Sections
    │       └── Card (for each section)
    │           └── FieldRenderer (mode="detail") for each field
    │
    └── EditView
        ├── Header with Save/Cancel
        └── Form
            └── Sections
                └── Card (for each section)
                    └── FieldRenderer (mode="edit") for each field
                        └── Input component based on field type

Field Type Mapping

Database Type  →  FieldType Enum  →  Component (Edit Mode)
─────────────────────────────────────────────────────────
string         →  TEXT            →  Input[type="text"]
text           →  TEXTAREA        →  Textarea
email          →  EMAIL           →  Input[type="email"]
url            →  URL             →  Input[type="url"]
integer        →  NUMBER          →  Input[type="number"]
decimal        →  NUMBER          →  Input[type="number"]
currency       →  CURRENCY        →  Input[type="number"] + prefix
boolean        →  BOOLEAN         →  Checkbox
date           →  DATE            →  DatePicker
datetime       →  DATETIME        →  DatePicker (with time)
picklist       →  SELECT          →  Select
multipicklist  →  MULTI_SELECT    →  Select[multiple]
lookup         →  BELONGS_TO      →  Combobox (relation picker)
file           →  FILE            →  FileUpload
image          →  IMAGE           →  ImageUpload
richtext       →  MARKDOWN        →  Textarea (+ preview)
json           →  JSON            →  Textarea (JSON editor)

View Mode Rendering

Field Type: TEXT
─────────────────────────────────────────────────────
LIST mode    │  Simple text, truncated
             │  <span>{{ value }}</span>
─────────────────────────────────────────────────────
DETAIL mode  │  Text with label
             │  <div>
             │    <Label>Name</Label>
             │    <span>{{ value }}</span>
             │  </div>
─────────────────────────────────────────────────────
EDIT mode    │  Input field
             │  <Input v-model="value" />
─────────────────────────────────────────────────────

Field Type: BOOLEAN
─────────────────────────────────────────────────────
LIST mode    │  Badge (Yes/No)
             │  <Badge>Yes</Badge>
─────────────────────────────────────────────────────
DETAIL mode  │  Checkbox (disabled) + text
             │  <Checkbox :checked="value" disabled />
             │  <span>Yes</span>
─────────────────────────────────────────────────────
EDIT mode    │  Checkbox (editable)
             │  <Checkbox v-model="value" />
─────────────────────────────────────────────────────

Field Type: SELECT
─────────────────────────────────────────────────────
LIST mode    │  Selected label
             │  <span>Active</span>
─────────────────────────────────────────────────────
DETAIL mode  │  Selected label with styling
             │  <Badge>Active</Badge>
─────────────────────────────────────────────────────
EDIT mode    │  Dropdown select
             │  <Select v-model="value">
             │    <SelectItem value="active">Active</SelectItem>
             │  </Select>
─────────────────────────────────────────────────────

API Endpoints

Setup/Configuration (Metadata)
────────────────────────────────────────────────────
GET    /api/setup/objects
       Returns: List of all object definitions

GET    /api/setup/objects/:objectName
       Returns: Object definition with fields

GET    /api/setup/objects/:objectName/ui-config ✨
       Returns: Object definition with UI-ready field configs
       (fields mapped to frontend format with UIMetadata)

POST   /api/setup/objects
       Body: { apiName, label, description, ... }
       Returns: Created object definition

POST   /api/setup/objects/:objectName/fields
       Body: { apiName, label, type, uiMetadata, ... }
       Returns: Created field definition

Runtime (Data CRUD)
────────────────────────────────────────────────────
GET    /api/runtime/objects/:objectName
       Query: { search, filters, page, pageSize }
       Returns: Array of records

GET    /api/runtime/objects/:objectName/:recordId
       Returns: Single record

POST   /api/runtime/objects/:objectName
       Body: { field1: value1, field2: value2, ... }
       Returns: Created record

PUT    /api/runtime/objects/:objectName/:recordId
       Body: { field1: value1, field2: value2, ... }
       Returns: Updated record

DELETE /api/runtime/objects/:objectName/:recordId
       Returns: Success status

Key Features

Frontend

  • Universal field renderer for 15+ field types
  • Three view modes (list, detail, edit)
  • Client-side validation with custom rules
  • Responsive design (mobile-friendly)
  • Accessible components (WCAG compliant)
  • Type-safe with TypeScript
  • Composables for easy integration
  • Demo page for testing

Backend

  • UI metadata stored in JSONB column
  • Field mapper service for transformation
  • Default metadata generation
  • Validation rule support
  • Flexible field type system
  • Multi-tenant support
  • RESTful API

Database

  • Flexible schema with JSONB metadata
  • Support for custom objects
  • Versioning and migration support
  • Indexed for performance

Extension Points

1. Custom Field Types
   └─> Add to FieldType enum
   └─> Add rendering logic to FieldRenderer.vue
   └─> Add mapping in FieldMapperService

2. Custom Validation Rules
   └─> Add to ValidationRule type
   └─> Add validation logic in EditView.vue

3. Custom Actions
   └─> Add to ViewAction interface
   └─> Handle in view components

4. Custom Sections
   └─> Configure in DetailViewConfig/EditViewConfig
   └─> Auto-generation in useFields()

5. Custom Formatting
   └─> Add to UIMetadata
   └─> Implement in FieldRenderer.vue

This architecture provides a scalable, maintainable, and extensible system for building dynamic forms and views! 🎉