/* * Existing manifest mutations. * * This example keeps the existing manifest JSON inline, hydrates it back into * SDK objects, removes layout content, adds different layout content, and * prints the updated manifest JSON. * * Run: * yarn -s tsn examples/manifest/existing-manifest-mutations/existing-manifest-mutations.ts \ * > examples/manifest/existing-manifest-mutations/manifest.updated.json */ import { CustomObject, CustomObjectFieldSection, CustomObjectPageLayout, type ExistingManifest, ManifestBuilder, RadioField, TextField, } from '@rippling/rippling-sdk/lib/manifest'; const existingManifestJson: ExistingManifest = { metadata: { key: 'gym_membership_management', name: 'Gym Membership Management', description: 'Small inline manifest used by the existing-manifest mutation example', }, components: [ { type: 'CUSTOM_CATEGORY', api_name: 'gym__c', name: 'Gym', description: 'Memberships, staff, schedules, and attendance', }, { type: 'CUSTOM_OBJECT', api_name: 'gym_member__c', name: 'Member', plural_label: 'Members', category_api_name: 'gym__c', description: 'Gym member profile, contact, and membership status', }, { type: 'CUSTOM_OBJECT_FIELD_SECTION', section_id: 'sec_gm_profile', model_name: 'gym_member__c', name: 'Profile', }, { type: 'CUSTOM_OBJECT_FIELD_SECTION', section_id: 'sec_gm_membership', model_name: 'gym_member__c', name: 'Membership', }, { type: 'CUSTOM_OBJECT_FIELD', custom_object_api_name: 'gym_member__c', field_api_name: 'first_name__c', field_display_name: 'First name', data_type: { field_type: 'TEXT', max_length: 80 }, is_required: true, is_unique: false, is_indexed: false, is_standard: false, section: 'sec_gm_profile', }, { type: 'CUSTOM_OBJECT_FIELD', custom_object_api_name: 'gym_member__c', field_api_name: 'last_name__c', field_display_name: 'Last name', data_type: { field_type: 'TEXT', max_length: 80 }, is_required: true, is_unique: false, is_indexed: false, is_standard: false, section: 'sec_gm_profile', }, { type: 'CUSTOM_OBJECT_FIELD', custom_object_api_name: 'gym_member__c', field_api_name: 'phone__c', field_display_name: 'Phone', data_type: { field_type: 'PHONE_NUMBER' }, is_required: false, is_unique: false, is_indexed: false, is_standard: false, section: 'sec_gm_profile', }, { type: 'CUSTOM_OBJECT_FIELD', custom_object_api_name: 'gym_member__c', field_api_name: 'membership_status__c', field_display_name: 'Membership status', data_type: { field_type: 'SELECT', options_list: ['Active', 'Frozen', 'Cancelled', 'Trial'] }, is_required: true, is_unique: false, is_indexed: false, is_standard: false, section: 'sec_gm_membership', }, { type: 'CUSTOM_OBJECT_FIELD', custom_object_api_name: 'gym_member__c', field_api_name: 'join_date__c', field_display_name: 'Join date', data_type: { field_type: 'DATE' }, is_required: false, is_unique: false, is_indexed: false, is_standard: false, section: 'sec_gm_membership', }, { type: 'CUSTOM_OBJECT_PAGE_LAYOUT', layout_id: 'layout_gym_member', api_name: 'default', object_rql_name: 'gym_member__c', name: 'Member', system_created: false, tab_edits: { newTabs: [ { key: 'member', name: 'Member', type: 'tab_with_sections', sections: [ { name: 'Profile', type: 'fields_section', key: 'member_profile_section', // The key is the page-layout section identity. Field metadata // still points at CUSTOM_OBJECT_FIELD_SECTION sec_gm_profile. fields: [ { fieldRqlName: 'first_name__c' }, { fieldRqlName: 'last_name__c' }, { fieldRqlName: 'phone__c' }, ], }, { name: 'Membership', type: 'fields_section', key: 'member_membership_section', fields: [{ fieldRqlName: 'membership_status__c' }, { fieldRqlName: 'join_date__c' }], }, ], }, ], systemTabEdits: {}, tabsOrder: ['member'], }, header_edits: { newTitleField: 'first_name__c', newDescriptionField: 'membership_status__c', }, visibility_conditions: {}, blueprint_key: 'gym_member__c', }, ], }; const manifest = ManifestBuilder.loadFromExistingJson(existingManifestJson); const memberObj = CustomObject.loadFromExisting('gym_member__c'); const profileSection = CustomObjectFieldSection.loadFromExisting('sec_gm_profile', { customObjectApiName: memberObj.getApiName(), }); const membershipSection = CustomObjectFieldSection.loadFromExisting('sec_gm_membership', { customObjectApiName: memberObj.getApiName(), }); const memberLayout = CustomObjectPageLayout.loadFromExisting('layout_gym_member', { customObjectApiName: memberObj.getApiName(), }); const preferredName = new TextField(memberObj, { apiName: 'preferred_name__c', displayName: 'Preferred name', description: 'Preferred name field', maxLength: 80, section: profileSection, }); // Remove an existing field from one section, then add a different field there. // The removed field component remains in the manifest; only this layout stops // rendering it. memberLayout .removeField('phone__c', { tabKey: 'member', section: profileSection, removeAll: false, }) .addField(preferredName, { tabKey: 'member', section: profileSection, position: 2, }); const marketingSection = new CustomObjectFieldSection(memberObj, { sectionId: 'sec_gm_marketing', name: 'Marketing', }); const marketingOptIn = new RadioField(memberObj, { apiName: 'marketing_opt_in__c', displayName: 'Marketing opt-in', description: 'Marketing opt-in field', options: ['Yes', 'No', 'Unknown'], section: marketingSection, }); const referralSource = new TextField(memberObj, { apiName: 'referral_source__c', displayName: 'Referral source', description: 'Referral source field', maxLength: 120, section: marketingSection, }); // Remove one existing section from the layout, then add a different one. // The removed section component and its fields remain in the manifest. memberLayout .removeSection(membershipSection, { tabKey: 'member', removeAll: false, }) .addSection( { name: 'Marketing', type: 'fields_section', key: 'member_marketing_section', section: marketingSection, fields: [marketingOptIn, referralSource], layout: 'two_column', }, { tabKey: 'member', position: 'end', }, ) .addHeaderField(preferredName, { key: 'preferred_name_header', canBeDeleted: true, canBeMoved: true, }) .setTitleField(preferredName) .removeDescriptionField(); console.log(manifest.preview());