do to formatters

This commit is contained in:
2026-01-24 01:22:43 +01:00
parent 891b3cf0ee
commit 705f9685b5
18 changed files with 361 additions and 760 deletions

View File

@@ -1,32 +0,0 @@
/**
* ViewModel Builder Contract
*
* Purpose: Transform ViewData into ViewModels for client-side state management
*
* Rules:
* - Deterministic and side-effect free
* - No HTTP/API calls
* - Input: ViewData (JSON-serializable template-ready data)
* - Output: ViewModel (client-only class)
* - Must be in lib/builders/view-models/
* - Must be named *ViewModelBuilder
* - Must have 'use client' directive
* - Must implement static build() method
* - Must use 'satisfies' for static type enforcement
*/
import { ViewData } from '../view-data/ViewData';
import { ViewModel } from '../view-models/ViewModel';
/**
* ViewModel Builder Contract (Static)
*
* Usage:
* export class MyViewModelBuilder {
* static build(viewData: MyViewData): MyViewModel { ... }
* }
* MyViewModelBuilder satisfies ViewModelBuilder<MyViewData, MyViewModel>;
*/
export interface ViewModelBuilder<TViewData extends ViewData, TViewModel extends ViewModel> {
build(viewData: TViewData): TViewModel;
}

View File

@@ -1,22 +1,40 @@
/**
* Formatter contract
*
*
* Deterministic, reusable, UI-only formatting/mapping logic.
*
* Based on DISPLAY_OBJECTS.md:
* - Class-based
* - Immutable
*
* Based on FORMATTERS.md:
* - Stateless (Formatters) or Immutable (Display Objects)
* - Deterministic
* - Side-effect free
* - No Intl.* or toLocale*
* - No business rules
*
* Uncle Bob says: "Data structures should not have behavior."
* Formatters ensure ViewData remains a dumb container of primitives.
*/
export interface Formatter {
/**
* Format or map the display object
*
* @returns Primitive values only (strings, numbers, booleans)
* Format or map the input to a primitive value
*
* @returns Primitive values only (strings, numbers, booleans, null)
*/
format(): unknown;
format(): string | number | boolean | null;
}
/**
* Rich Display Object contract (Client-only)
*
* Used by ViewModels to provide a rich API to the UI.
*/
export interface DisplayObject {
/**
* Primary primitive output
*/
format(): string | number | boolean | null;
/**
* Multiple primitive variants
*/
variants?(): Record<string, string | number | boolean | null>;
}

View File

@@ -1,16 +1,14 @@
import { JsonValue } from "../types/primitives";
/**
* Base interface for ViewData objects
*
* All ViewData must be JSON-serializable for SSR.
* This type ensures no class instances or functions are included.
*
* Note: We use 'any' here to allow complex DTO structures, but the
* architectural rule is that these must be plain JSON objects.
* Uncle Bob says: "Data structures should not have behavior."
* ViewData is a dumb container for primitives and nested JSON only.
*/
export interface ViewData {
[key: string]: JsonValue;
[key: string]: any;
}
/**
* Helper type to ensure a type is ViewData-compatible

View File

@@ -5,7 +5,6 @@ import { ViewData } from '@/lib/contracts/view-data/ViewData';
*
* ViewData for category icon media rendering.
*/
import { ViewData } from "../contracts/view-data/ViewData";
export interface CategoryIconViewData extends ViewData {
buffer: string; // base64 encoded