import { EnumActionCode } from '../enum-interfaces/action-code.enum'; import { IIntentGrammar } from '../enum-interfaces/narration-engine'; import { IOmegaValue } from './others'; export type SupportedActionCode = keyof ActionInputMap; export type DescriptorMap = { [A in SupportedActionCode]: IIntentDescriptor; }; export type AnyIntentDescriptor = DescriptorMap[SupportedActionCode]; export interface IIntentDescriptor { /** Unique action code – MUST match backend handler */ readonly actionCode: A; /** Human-readable label */ readonly label: string; /** Short description to guide decision maker */ readonly description: string; /** Category for grouping (optional, UI-only) */ readonly category?: string; /** Quick visual cue for fast scanning (UI-only) */ readonly quickEmoji: string; /** Input schema – descriptive only */ readonly inputs: ReadonlyArray; /** Grammar-based narration definition */ readonly narration?: IIntentGrammar; } export interface IIntentInputDescriptor { /** Logical input key */ readonly key: IntentInputKey; /** Display label */ readonly label: string; /** Input kind – NOT a form type */ readonly kind: IntentInputKind; /** Default value when composing intent */ defaultValue?: unknown; /** * defaultValueFactory * ---------------------------------------- * Factory sinh giá trị mặc định tại THỜI ĐIỂM build form, * không phải tại thời điểm định nghĩa descriptor. * * Dùng cho các giá trị có tính: * - Động theo lần tạo intent (UUID, timestamp, random code, ...) * - Phụ thuộc ngữ cảnh runtime * * ⚠️ TUYỆT ĐỐI KHÔNG dùng defaultValue cho: * - crypto.randomUUID() * - new Date() * - Date.now() * - Math.random() * * Lý do: * Descriptor là metadata tĩnh, chỉ được evaluate MỘT LẦN * khi module được load. * Việc đặt giá trị động vào defaultValue sẽ gây reuse dữ liệu, * phá vỡ lịch sử quyết định và dẫn tới bug rất khó truy vết. * * Quy tắc: * - defaultValue → literal / constant * - defaultValueFactory → dynamic / runtime value */ defaultValueFactory?: () => unknown; readonly validators?: IIntentInputValidatorSchema; /** Optional hint for humans */ readonly hint?: string; /** Validation message policy (design-time) */ readonly errorMessages?: Partial>; /** Grid layout (design-time, immutable) */ readonly row?: number; readonly flexSize?: number; /** * Design-time visibility hint. * If true, the input IS rendered in the UI, * but its wrapper element is hidden via CSS (display: none or equivalent). * * - The FormControl MUST still be created and registered. * - The value MUST still be included in the intent payload. * - This flag MUST NOT be toggled at runtime. */ hidden?: boolean; disabled?: boolean; } export interface IIntentInputValidatorSchema { required?: true; minLength?: number; maxLength?: number; min?: number; max?: number; pattern?: string; } export interface IIntentInputError { fieldKey: string; fieldLabel: string; errorCode: string; errorMessage: string; } export type IntentInputKind = 'string' | 'boolean' | 'date' | 'dropdown' | 'number' | 'reference' | 'enum' | 'timezoneId' | 'orgGardenReference' | 'orgGardenReferenceWithSeats' | 'seatDropdown' | 'seatGardenReference' | 'orgAttributeName' | 'seatAttributeName' | 'personAttributeName' | 'rCode' | 'treeId' | 'role' | 'isRoot' | 'oViewer' | 'sViewer' | 'orphanedSeats' | 'o_is_part_of_o' | 'o_has_part_o' | 's_belongs_to_o' | 'o_has_seat_s' | 's_works_under_s' | 's_manages_s'; export type IntentInputKey = 'A_ID' | 'B_ID' | 'R_CODE' | 'VF_UTC' | 'VT_UTC' | 'VT_UTC_CURRENT' | 'TIMEZONE_ID' | 'ORIGINAL_NAME' | 'IS_ROOT' | 'IS_HR' | 'CODE' | 'SHORT_CODE' | 'ID' | 'OBJECT_ID' | 'ROLE' | 'NOTE' | 'OBJECT_TYPE' | 'ATTRIBUTE_NAME' | 'VALUE_IN_STRING' | 'AVAILABLE_UTC' | 'TREE_ID' | 'TREE_NAME' | 'A_ORIGINAL_NAME' | 'B_ORIGINAL_NAME' | 'LEFT_S_CODE' | 'RIGHT_S_CODE' | 'UTC_OF_VIEW' | 'CHILD_ID' | 'TRANSACTION_ID'; export type ActionInputMap = { [EnumActionCode.CREATE_TREE]: Record; [EnumActionCode.CREATE_O]: Record; [EnumActionCode.CREATE_S]: Record; [EnumActionCode.LINK_O_O]: Record; [EnumActionCode.LINK_S_O]: Record; [EnumActionCode.LINK_S_S]: Record; [EnumActionCode.SET_O_ATTR]: Record; [EnumActionCode.SET_S_ATTR]: Record; [EnumActionCode.SET_P_ATTR]: Record; [EnumActionCode.LINK_P_S_INTERNAL]: Record; [EnumActionCode.SHORTEN_O_O]: Record; [EnumActionCode.SHORTEN_P_S]: Record; [EnumActionCode.SHORTEN_S_O]: Record; [EnumActionCode.SHORTEN_S_S]: Record; }; export type IntentDraft = { readonly actionCode: A; readonly inputSnapshot: ActionInputMap[A]; seq?: number; }; export type AnyIntentDraft = { [A in keyof ActionInputMap]: IntentDraft; }[keyof ActionInputMap];