import type { CustomObjectFieldDerivedAggregatedField, CustomObjectFieldFormulaAttrMetas, CustomObjectFieldRqlDefinition, CustomObjectFieldSection as RestCustomObjectFieldSection, } from '../../../resources/custom-objects/fields'; import type { AnyCustomObjectDefinition, AnyFieldDefinition, BooleanFieldDefinition, CurrencyFieldDefinition, CustomObjectIdentity, DateFieldDefinition, DatetimeFieldDefinition, EmailFieldDefinition, FileFieldDefinition, FormulaFieldDefinition, FormulaFieldKind, FormulaValueByKind, LongTextFieldDefinition, LookupFieldDefinition, LookupTarget, NativeModelTarget, NumberFieldDefinition, ParentChildFieldDefinition, PercentageFieldDefinition, PhoneFieldDefinition, RadioFieldDefinition, SectionDefinition, SelectFieldDefinition, TargetApiName, TextFieldDefinition, TimeFieldDefinition, UrlFieldDefinition, } from './types'; /** * Internal helper for field factories that expose `required` and `section`. * * @typeParam TRequired - Literal boolean carried through to derived input types. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ interface BooleanLikeProps { readonly required?: TRequired; readonly section?: TSectionKey; } /** * Internal helper for choice-based field factories. * * @typeParam TRequired - Literal boolean carried through to derived input types. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ interface ChoiceProps extends BooleanLikeProps { readonly options: readonly string[]; } /** * Internal helper for numeric field factories that support decimal-place metadata. * * @typeParam TRequired - Literal boolean carried through to derived input types. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ interface NumericProps extends BooleanLikeProps { readonly decimalPlaces?: number; } /** * Internal presentation properties shared by every field factory. * * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ interface CommonFieldProps { readonly displayName: string; readonly description: string; readonly section?: TSectionKey; readonly enableHistory?: boolean; readonly formulaAttributeMetas?: CustomObjectFieldFormulaAttrMetas; readonly derivedAggregatedField?: CustomObjectFieldDerivedAggregatedField; readonly rqlDefinition?: CustomObjectFieldRqlDefinition; readonly restSection?: RestCustomObjectFieldSection; } /** * Freezes a field definition so reusable fragments stay immutable at runtime. * * @typeParam TField - Concrete field definition being frozen. */ /** * Freezes one field definition fragment before returning it to callers. * * @param field - Concrete field definition to freeze. * @returns The same field definition, frozen for safe reuse. * @typeParam TField - Concrete field definition being frozen. */ function freezeField(field: TField): TField { return Object.freeze(field); } /** * Normalizes an optional required flag into the literal type expected by field definitions. * * @typeParam TRequired - Literal boolean requested by the caller. */ /** * Normalizes an optional `required` flag into the literal boolean type used by field definitions. * * @param required - Optional literal required flag supplied by the caller. * @returns Normalized required flag, defaulting to `false`. * @typeParam TRequired - Literal boolean requested by the caller. */ function normalizeRequired(required: TRequired | undefined): TRequired { return (required ?? false) as TRequired; } /** * Declares a native Rippling model target for lookup fields. * * @param apiName - Native model API name, for example `'Employee'`. * @returns Immutable native-model target descriptor for lookup fields. * @typeParam TApiName - Native model api name, for example `'Employee'`. */ export function nativeModel(apiName: TApiName): NativeModelTarget { return Object.freeze({ kind: 'native-model-target', apiName }); } /** * Defines a single-line text field. * * @param props - Text-field metadata and presentation properties. * @returns Immutable text field definition. * @typeParam TRequired - Whether the field is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function text< TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( props: CommonFieldProps & BooleanLikeProps & { readonly unique?: boolean; readonly maxLength?: number }, ): TextFieldDefinition { return freezeField({ kind: 'text', required: normalizeRequired(props.required), writable: true, ...props }); } /** * Defines a multi-line text field. * * @param props - Long-text field metadata and presentation properties. * @returns Immutable long-text field definition. * @typeParam TRequired - Whether the field is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function longText< TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( props: CommonFieldProps & BooleanLikeProps & { readonly maxLength?: number }, ): LongTextFieldDefinition { return freezeField({ kind: 'long-text', required: normalizeRequired(props.required), writable: true, ...props, }); } /** * Defines an email-address field. * * @param props - Email-field metadata and presentation properties. * @returns Immutable email field definition. * @typeParam TRequired - Whether the field is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function email< TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( props: CommonFieldProps & BooleanLikeProps & { readonly unique?: boolean }, ): EmailFieldDefinition { return freezeField({ kind: 'email', required: normalizeRequired(props.required), writable: true, ...props, }); } /** * Defines a URL field. * * @param props - URL-field metadata and presentation properties. * @returns Immutable URL field definition. * @typeParam TRequired - Whether the field is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function url< TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( props: CommonFieldProps & BooleanLikeProps, ): UrlFieldDefinition { return freezeField({ kind: 'url', required: normalizeRequired(props.required), writable: true, ...props }); } /** * Defines a phone-number field. * * @param props - Phone-field metadata and presentation properties. * @returns Immutable phone field definition. * @typeParam TRequired - Whether the field is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function phone< TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( props: CommonFieldProps & BooleanLikeProps, ): PhoneFieldDefinition { return freezeField({ kind: 'phone', required: normalizeRequired(props.required), writable: true, ...props, }); } /** * Defines a numeric field. * * @param props - Number-field metadata and presentation properties. * @returns Immutable number field definition. * @typeParam TRequired - Whether the field is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function number< TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( props: CommonFieldProps & NumericProps & { readonly unique?: boolean }, ): NumberFieldDefinition { return freezeField({ kind: 'number', required: normalizeRequired(props.required), writable: true, ...props, }); } /** * Defines a currency field. * * @param props - Currency-field metadata and presentation properties. * @returns Immutable currency field definition. * @typeParam TRequired - Whether the field is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function currency< TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( props: CommonFieldProps & NumericProps & { readonly currency?: string }, ): CurrencyFieldDefinition { return freezeField({ kind: 'currency', required: normalizeRequired(props.required), writable: true, ...props, }); } /** * Defines a percentage field. * * @param props - Percentage-field metadata and presentation properties. * @returns Immutable percentage field definition. * @typeParam TRequired - Whether the field is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function percentage< TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( props: CommonFieldProps & BooleanLikeProps, ): PercentageFieldDefinition { return freezeField({ kind: 'percentage', required: normalizeRequired(props.required), writable: true, ...props, }); } /** * Defines a date-only field. * * @param props - Date-field metadata and presentation properties. * @returns Immutable date field definition. * @typeParam TRequired - Whether the field is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function date< TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( props: CommonFieldProps & BooleanLikeProps, ): DateFieldDefinition { return freezeField({ kind: 'date', required: normalizeRequired(props.required), writable: true, ...props }); } /** * Defines a date-time field. * * @param props - Datetime-field metadata and presentation properties. * @returns Immutable datetime field definition. * @typeParam TRequired - Whether the field is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function datetime< TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( props: CommonFieldProps & BooleanLikeProps, ): DatetimeFieldDefinition { return freezeField({ kind: 'datetime', required: normalizeRequired(props.required), writable: true, ...props, }); } /** * Defines a time-of-day field. * * @param props - Time-field metadata and presentation properties. * @returns Immutable time field definition. * @typeParam TRequired - Whether the field is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function time< TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( props: CommonFieldProps & BooleanLikeProps, ): TimeFieldDefinition { return freezeField({ kind: 'time', required: normalizeRequired(props.required), writable: true, ...props }); } /** * Defines a multi-select choice field. * * @param props - Multi-select field metadata and presentation properties. * @returns Immutable multi-select field definition. * @typeParam TRequired - Whether the field is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function select< TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( props: CommonFieldProps & ChoiceProps, ): SelectFieldDefinition { return freezeField({ kind: 'select', required: normalizeRequired(props.required), writable: true, ...props, }); } /** * Defines a single-select radio field. * * @param props - Radio-field metadata and presentation properties. * @returns Immutable radio field definition. * @typeParam TRequired - Whether the field is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function radio< TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( props: CommonFieldProps & ChoiceProps, ): RadioFieldDefinition { return freezeField({ kind: 'radio', required: normalizeRequired(props.required), writable: true, ...props, }); } /** * Defines a boolean field. * * @param props - Boolean-field metadata and presentation properties. * @returns Immutable boolean field definition. * @typeParam TRequired - Whether the field is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function boolean< TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( props: CommonFieldProps & BooleanLikeProps, ): BooleanFieldDefinition { return freezeField({ kind: 'boolean', required: normalizeRequired(props.required), writable: true, ...props, }); } /** * Defines a file attachment field. * * @param props - File-field metadata and presentation properties. * @returns Immutable file field definition. * @typeParam TRequired - Whether the field is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function file< TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( props: CommonFieldProps & BooleanLikeProps & { readonly allowedType: 'images' | 'documents' | 'any' }, ): FileFieldDefinition { return freezeField({ kind: 'file', required: normalizeRequired(props.required), writable: true, ...props }); } /** * Defines a many-to-one lookup field. * * @param target - Target object or native model referenced by the lookup. * @param props - Lookup-field metadata and presentation properties. * @returns Immutable lookup field definition. * @typeParam TTarget - Target object or native model referenced by the lookup. * @typeParam TRequired - Whether the lookup is required during record creation. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function lookup< TTarget extends LookupTarget, TRequired extends boolean = false, TSectionKey extends string | undefined = string | undefined, >( target: TTarget, props: CommonFieldProps & BooleanLikeProps & { readonly relatedDataLabel?: string; readonly lookupFilterRqlCondition?: string; }, ): LookupFieldDefinition { return freezeField({ kind: 'lookup', target, targetApiName: target.apiName as TargetApiName, required: normalizeRequired(props.required), writable: true, ...props, }); } /** * Defines a parent-child relationship field. * * @param target - Parent object definition referenced by the relationship. * @param props - Parent-child field metadata and presentation properties. * @returns Immutable parent-child field definition. * @typeParam TTarget - Parent object definition referenced by the relationship. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ export function parentChild< TTarget extends Pick, TSectionKey extends string | undefined = string | undefined, >( target: TTarget, props: CommonFieldProps & { readonly relatedDataLabel?: string; readonly parentChildType?: 'PRIMARY' | 'SECONDARY'; readonly enableParentOwnerInheritance?: boolean; readonly section?: TSectionKey; }, ): ParentChildFieldDefinition, TSectionKey> { return freezeField({ kind: 'parent-child', target, targetApiName: target.apiName as TargetApiName>, required: true, writable: true, ...props, }); } /** * Shared implementation for the public formula helpers. * * @typeParam TKind - Concrete formula-field discriminant. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ /** * Builds one immutable read-only formula field definition. * * @param kind - Concrete formula-field discriminant to produce. * @param props - Formula metadata and presentation properties. * @returns Immutable formula field definition. * @typeParam TKind - Concrete formula-field discriminant. * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ function formulaField< TKind extends FormulaFieldKind, TSectionKey extends string | undefined = string | undefined, >( kind: TKind, props: CommonFieldProps & { readonly formula: string; readonly maxLength?: number }, ): FormulaFieldDefinition { return freezeField({ ...props, kind, writable: false, required: false as const }) as FormulaFieldDefinition< TKind, FormulaValueByKind[TKind], TSectionKey >; } /** Public helper surface for read-only formula fields. */ export interface FormulaHelpers { /** * Defines a text-valued formula field. * * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ text( props: CommonFieldProps & { readonly formula: string; readonly maxLength: number }, ): FormulaFieldDefinition<'formula-text', string, TSectionKey>; /** * Defines a numeric formula field. * * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ number( props: CommonFieldProps & { readonly formula: string }, ): FormulaFieldDefinition<'formula-number', number, TSectionKey>; /** * Defines a boolean formula field. * * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ boolean( props: CommonFieldProps & { readonly formula: string }, ): FormulaFieldDefinition<'formula-boolean', boolean, TSectionKey>; /** * Defines a currency-valued formula field. * * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ currency( props: CommonFieldProps & { readonly formula: string }, ): FormulaFieldDefinition<'formula-currency', number, TSectionKey>; /** * Defines a percentage-valued formula field. * * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ percentage( props: CommonFieldProps & { readonly formula: string }, ): FormulaFieldDefinition<'formula-percentage', number, TSectionKey>; /** * Defines a date-valued formula field. * * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ date( props: CommonFieldProps & { readonly formula: string }, ): FormulaFieldDefinition<'formula-date', string, TSectionKey>; /** * Defines a URL-valued formula field. * * @typeParam TSectionKey - Allowed section-key union for the enclosing object. */ url( props: CommonFieldProps & { readonly formula: string }, ): FormulaFieldDefinition<'formula-url', string, TSectionKey>; } /** Typed helpers for read-only formula fields. */ export const formula: FormulaHelpers = Object.freeze({ text( props: CommonFieldProps & { readonly formula: string; readonly maxLength: number }, ): FormulaFieldDefinition<'formula-text', string, TSectionKey> { return formulaField('formula-text', props); }, number( props: CommonFieldProps & { readonly formula: string }, ): FormulaFieldDefinition<'formula-number', number, TSectionKey> { return formulaField('formula-number', props); }, boolean( props: CommonFieldProps & { readonly formula: string }, ): FormulaFieldDefinition<'formula-boolean', boolean, TSectionKey> { return formulaField('formula-boolean', props); }, currency( props: CommonFieldProps & { readonly formula: string }, ): FormulaFieldDefinition<'formula-currency', number, TSectionKey> { return formulaField('formula-currency', props); }, percentage( props: CommonFieldProps & { readonly formula: string }, ): FormulaFieldDefinition<'formula-percentage', number, TSectionKey> { return formulaField('formula-percentage', props); }, date( props: CommonFieldProps & { readonly formula: string }, ): FormulaFieldDefinition<'formula-date', string, TSectionKey> { return formulaField('formula-date', props); }, url( props: CommonFieldProps & { readonly formula: string }, ): FormulaFieldDefinition<'formula-url', string, TSectionKey> { return formulaField('formula-url', props); }, }); /** * Immutable helper for authoring section maps in reusable fragments. * * @param definitions - Section definitions to freeze and preserve as-is. * @returns Frozen section-definition map retaining the caller's key/value types. * @typeParam TSections - Concrete section map to preserve in the returned value. */ export function sections>>( definitions: TSections, ): TSections { return Object.freeze({ ...definitions }); }