import { generateId } from './_helpers'; import { getExistingManifestContext, type ExistingManifestContextOptions } from './existing-manifest-context'; import type { ManifestComponentDeletion, ManifestScope } from './manifest-builder'; import { requireStringComponentField } from './_existing-component-fields'; export interface CustomFieldSectionProps { sectionId?: string; name: string; modelRqlName: string; isRipplingDefined?: boolean; identifierSlug?: string | null; displayOrder?: number | null; } /** A section that groups Custom Field V2 fields on a native or custom object. */ export class CustomFieldSection { static readonly componentType = 'CUSTOM_FIELD_SECTION' as const; static toDeletionIdentifier(sectionId: string): ManifestComponentDeletion { return { type: CustomFieldSection.componentType, section_id: sectionId }; } private readonly _sectionId: string; private readonly _name: string; private readonly _modelRqlName: string; private readonly _isRipplingDefined: boolean; private readonly _identifierSlug: string | null; private readonly _displayOrder: number | null; constructor(scope: ManifestScope, props: CustomFieldSectionProps) { this._sectionId = props.sectionId ?? generateId('cf_section'); this._name = props.name; this._modelRqlName = props.modelRqlName; this._isRipplingDefined = props.isRipplingDefined ?? false; this._identifierSlug = props.identifierSlug ?? null; this._displayOrder = props.displayOrder ?? null; scope._register(this); } static loadFromExisting( sectionId: string, options: ExistingManifestContextOptions = {}, ): CustomFieldSection { return getExistingManifestContext(options).loadCustomFieldSection(sectionId); } /** @internal Hydrates a section from existing manifest wire JSON. */ static _fromExistingComponent(scope: ManifestScope, component: Record): CustomFieldSection { return new CustomFieldSection(scope, { sectionId: requireStringComponentField(component, 'obj_id', CustomFieldSection.componentType), name: requireStringComponentField(component, 'name', CustomFieldSection.componentType), modelRqlName: requireStringComponentField( component, 'model_rql_name', CustomFieldSection.componentType, ), isRipplingDefined: component['is_rippling_defined'] === true, identifierSlug: (component['identifier_slug'] as string | null | undefined) ?? null, displayOrder: (component['display_order'] as number | null | undefined) ?? null, }); } getSectionId(): string { return this._sectionId; } getName(): string { return this._name; } getModelRqlName(): string { return this._modelRqlName; } toDict(): Record { return { type: CustomFieldSection.componentType, obj_id: this._sectionId, name: this._name, is_rippling_defined: this._isRipplingDefined, model_rql_name: this._modelRqlName, identifier_slug: this._identifierSlug, display_order: this._displayOrder, }; } }