Skip to content

Commit 2279336

Browse files
feat: validate and enable metadata api
1 parent e126552 commit 2279336

File tree

7 files changed

+138
-4
lines changed

7 files changed

+138
-4
lines changed

messages/assess.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,5 +197,7 @@
197197
"invalidTypeAssessErrorMessage": "We couldn't assess your Omnistudio components in the %s namespace. Select the correct namespace and try again",
198198
"assessmentSuccessfulMessage": "Migration assessment for org %s is complete and reports are ready for review in the folder %s",
199199
"needManualInterventionAsSpecialCharsInChildFlexcardName": "Need manual intervention as child flexcards have special characters in their name",
200-
"needManualInterventionAsSpecialCharsInFlexcardName": "Need manual intervention as flexcard has special characters in name"
200+
"needManualInterventionAsSpecialCharsInFlexcardName": "Need manual intervention as flexcard has special characters in name",
201+
"errorCheckingOmniStudioMetadata": "We couldn't check whether the Omnistudio Metadata is enabled: %s. Try again later.",
202+
"omniStudioSettingsMetadataAlreadyEnabled": "OmniStudio Metadata is already enabled with standard data model. No need for migration."
201203
}

messages/migrate.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,5 +253,13 @@
253253
"errorCheckingMetadataTables": "Error checking Omnistudio metadata tables: %s",
254254
"metadataCleanupCompleted": "The Omnistudio metadata table cleanup process is complete. Total records cleaned: %s",
255255
"metadataCleanupConsentMessage": "By proceeding further, you hereby consent to clean up the Omnistudio metadata tables. Proceeding with the cleanup process will permanently delete all records from OmniUiCardConfig, OmniScriptConfig, OmniIntegrationProcConfig, and OmniDataTransformConfig tables. Do you want to proceed? [y/n]",
256-
"metadataCleanupConsentNotGiven": "You’ve not consented to proceed with the Omnistudio metadata table cleanup. We’ll not be able to proceed with the migration."
256+
"metadataCleanupConsentNotGiven": "You’ve not consented to proceed with the Omnistudio metadata table cleanup. We’ll not be able to proceed with the migration.",
257+
"omniStudioMetadataEnableConsentMessage": "As part of the migration process, the OmniStudio Metadata will be enabled. Once it is enabled, it can't be disabled. Do you want to proceed? [y/n]",
258+
"errorCheckingOmniStudioMetadata": "We couldn't check whether the Omnistudio Metadata is enabled: %s. Try again later.",
259+
"omniStudioSettingsMetadataAlreadyEnabled": "OmniStudio Metadata is already enabled with standard data model. No need for migration.",
260+
"omniStudioSettingsMetadataEnabled": "OmniStudio Metadata is enabled with standard data model.",
261+
"errorEnablingOmniStudioSettingsMetadata": "We couldn't enable the OmniStudio Metadata: %s. Please enable it manually.",
262+
"manuallyEnableOmniStudioSettingsMetadata": "Please manually enable the OmniStudio Metadata in your org's OmniStudio Settings.",
263+
"omniStudioMetadataEnableConsentNotGiven": "You’ve not consented to proceed with the OmniStudio Metadata enablement. We’ll not be able to proceed with the migration.",
264+
"checkingOmniStudioSettingsMetadataStatus": "Checking OmniStudio Metadata status..."
257265
}

src/commands/omnistudio/migration/migrate.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,15 @@ export default class Migrate extends OmniStudioBaseCommand {
127127
const preMigrate: PreMigrate = new PreMigrate(namespace, conn, this.logger, messages, this.ux);
128128
const isExperienceBundleMetadataAPIProgramaticallyEnabled: { value: boolean } = { value: false };
129129

130-
// Handle config tables cleanup for standard data model migration
131130
if (isStandardDataModel()) {
131+
// Get user consent to enable OmniStudio Metadata for standard data model migration
132+
const omniStudioMetadataEnableConsent = await preMigrate.getOmniStudioMetadataEnableConsent();
133+
if (!omniStudioMetadataEnableConsent) {
134+
Logger.error(messages.getMessage('omniStudioMetadataEnableConsentNotGiven'));
135+
return;
136+
}
137+
138+
// Handle config tables cleanup for standard data model migration
132139
const isMetadataCleanupSuccess = await preMigrate.handleOmniStudioMetadataCleanup();
133140
if (!isMetadataCleanupSuccess) {
134141
return;

src/migration/postMigrate.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { BaseMigrationTool } from './base';
1212
import { Deployer } from './deployer';
1313
import * as fs from 'fs';
1414
import * as path from 'path';
15+
import { isStandardDataModel } from '../utils/dataModelService';
1516

1617
export class PostMigrate extends BaseMigrationTool {
1718
private readonly org: Org;
@@ -48,6 +49,9 @@ export class PostMigrate extends BaseMigrationTool {
4849
if (designerOk) {
4950
await this.enableStandardRuntimeIfNeeded(userActionMessage);
5051
}
52+
if (isStandardDataModel()) {
53+
await this.enableOmniStudioSettingsMetadataIfNeeded(userActionMessage);
54+
}
5155
return userActionMessage;
5256
}
5357

@@ -125,6 +129,44 @@ export class PostMigrate extends BaseMigrationTool {
125129
}
126130
}
127131

132+
private async enableOmniStudioSettingsMetadataIfNeeded(userActionMessage: string[]): Promise<void> {
133+
try {
134+
Logger.logVerbose(this.messages.getMessage('checkingOmniStudioSettingsMetadataStatus'));
135+
const result = await this.settingsPrefManager.enableOmniStudioSettingsMetadata();
136+
if (result === null) {
137+
Logger.logVerbose(this.messages.getMessage('omniStudioSettingsMetadataAlreadyEnabled'));
138+
} else if (result?.success === true) {
139+
/* The API call returns true if the metadata enabling call was successful.
140+
But it takes time for the checks to run and the metadata to be enabled or reverted back.
141+
We need to wait and check for it to be enabled or reverted back.
142+
*/
143+
const maxAttempts = 12;
144+
let attempts = 0;
145+
while (attempts < maxAttempts) {
146+
await new Promise((resolve) => setTimeout(resolve, 5000));
147+
const isMetadataEnabled = await this.settingsPrefManager.isOmniStudioSettingsMetadataEnabled();
148+
if (isMetadataEnabled) {
149+
Logger.logVerbose(this.messages.getMessage('omniStudioSettingsMetadataEnabled'));
150+
break;
151+
}
152+
attempts++;
153+
}
154+
if (attempts === maxAttempts) {
155+
Logger.error(this.messages.getMessage('errorEnablingOmniStudioSettingsMetadata', ['Unknown error']));
156+
userActionMessage.push(this.messages.getMessage('manuallyEnableOmniStudioSettingsMetadata'));
157+
}
158+
} else {
159+
const errors = result?.errors?.join(', ') || 'Unknown error';
160+
Logger.error(this.messages.getMessage('errorEnablingOmniStudioSettingsMetadata', [errors]));
161+
userActionMessage.push(this.messages.getMessage('manuallyEnableOmniStudioSettingsMetadata'));
162+
}
163+
} catch (error) {
164+
const errMsg = error instanceof Error ? error.message : String(error);
165+
Logger.error(this.messages.getMessage('errorEnablingOmniStudioSettingsMetadata', [errMsg]));
166+
userActionMessage.push(this.messages.getMessage('manuallyEnableOmniStudioSettingsMetadata'));
167+
}
168+
}
169+
128170
// If we processed exp sites and switched metadata api from off->on then only we revert it
129171
public async restoreExperienceAPIMetadataSettings(
130172
isExperienceBundleMetadataAPIProgramaticallyEnabled: {

src/migration/premigrate.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,41 @@ export class PreMigrate extends BaseMigrationTool {
110110
return deploymentConfig;
111111
}
112112

113+
/**
114+
* Gets user consent for OmniStudio metadata cleanup
115+
*
116+
* @returns Promise<boolean> - true if user consents, false otherwise
117+
*/
118+
public async getOmniStudioMetadataEnableConsent(): Promise<boolean> {
119+
const askWithTimeOut = PromptUtil.askWithTimeOut(this.messages);
120+
let validResponse = false;
121+
let consent = false;
122+
123+
while (!validResponse) {
124+
try {
125+
const resp = await askWithTimeOut(
126+
Logger.prompt.bind(Logger),
127+
this.messages.getMessage('omniStudioMetadataEnableConsentMessage')
128+
);
129+
const response = typeof resp === 'string' ? resp.trim().toLowerCase() : '';
130+
131+
if (response === YES_SHORT || response === YES_LONG) {
132+
consent = true;
133+
validResponse = true;
134+
} else if (response === NO_SHORT || response === NO_LONG) {
135+
consent = false;
136+
validResponse = true;
137+
} else {
138+
Logger.error(this.messages.getMessage('invalidYesNoResponse'));
139+
}
140+
} catch (err) {
141+
Logger.error(this.messages.getMessage('requestTimedOut'));
142+
process.exit(1);
143+
}
144+
}
145+
return consent;
146+
}
147+
113148
/**
114149
* Handles OmniStudio metadata tables cleanup with user consent
115150
*

src/utils/OmnistudioSettingsPrefManager.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,36 @@ export class OmnistudioSettingsPrefManager {
7878
}
7979
return null; // Already enabled, no action needed
8080
}
81+
82+
// OmniStudio Metadata methods
83+
public async isOmniStudioSettingsMetadataEnabled(): Promise<boolean> {
84+
try {
85+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
86+
const result = (await this.connection.metadata.read('OmniStudioSettings', ['OmniStudio'])) as unknown;
87+
88+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
89+
const metadata = result as MetadataInfo;
90+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
91+
return metadata?.enableOmniStudioMetadata === 'true' || false;
92+
} catch (error) {
93+
const errMsg = error instanceof Error ? error.message : String(error);
94+
Logger.error(this.messages.getMessage('errorCheckingOmniStudioMetadata', [errMsg]));
95+
return false;
96+
}
97+
}
98+
99+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
100+
public async enableOmniStudioSettingsMetadata(): Promise<any> {
101+
const isMetadataEnabled = await this.isOmniStudioSettingsMetadataEnabled();
102+
if (isMetadataEnabled) {
103+
return null;
104+
}
105+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
106+
return await this.connection.metadata.update('OmniStudioSettings', [
107+
{
108+
fullName: 'OmniStudio',
109+
enableOmniStudioMetadata: 'true',
110+
} as MetadataInfo,
111+
]);
112+
}
81113
}

src/utils/validatorService.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Connection, Messages } from '@salesforce/core';
22
import { Logger } from '../utils/logger';
33
import { OmnistudioOrgDetails } from './orgUtils';
44
import { isStandardDataModel } from './dataModelService';
5+
import { OmnistudioSettingsPrefManager } from './OmnistudioSettingsPrefManager';
56

67
export class ValidatorService {
78
private readonly messages: Messages;
@@ -20,9 +21,16 @@ export class ValidatorService {
2021
}
2122

2223
// If data model is standard no need to check for the licences
23-
// TODO: Add metadata toggle validation
2424
const isStandard = isStandardDataModel();
2525
if (isStandard) {
26+
// Check if OmniStudio Metadata is already enabled for standard data model
27+
const omniStudioSettingsPrefManager = new OmnistudioSettingsPrefManager(this.connection, this.messages);
28+
const isOmniStudioSettingsMetadataEnabled =
29+
await omniStudioSettingsPrefManager.isOmniStudioSettingsMetadataEnabled();
30+
if (isOmniStudioSettingsMetadataEnabled) {
31+
Logger.error(this.messages.getMessage('omniStudioSettingsMetadataAlreadyEnabled'));
32+
return false;
33+
}
2634
return true;
2735
}
2836

0 commit comments

Comments
 (0)