Skip to content

Commit ea06e66

Browse files
Merge branch 'release260omnistudiopackage' of https://github.com/salesforcecli/plugin-omnistudio-migration-tool into u/rajender-kumar/w-21274482/deployment
2 parents 902dc41 + b690806 commit ea06e66

File tree

16 files changed

+1095
-118
lines changed

16 files changed

+1095
-118
lines changed

messages/assess.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@
220220
"packagesHaveSameValue": "Both TheFirstInstalledOmniPackage and InstalledIndustryPackage have the same value.",
221221
"packagesHaveDifferentValue": "Both the InstalledIndustryPackage and TheFirstInstalledOmniPackage have different values.",
222222
"failedToCheckPackagesValue": "Failed to check the value of packages in Omni Interaction Configuration.",
223+
"omniStudioPermissionsNotEnabled": "The org doesn’t have Omnistudio permissions enabled. These permissions are required to migrate components. You can still run the assessment.",
224+
"skippingLicenseCheckForAssessment": "Skipping OmniStudio license check for assessment",
223225
"packageDetails": "Your org contains only the TheFirstInstalledOmniPackage Omni Interaction Configuration.",
224226
"orgUsecaseDetails": "The org is on %s data model with %s and the Omnistudio Metadata setting turned %s",
225227
"globalAutoNumberUnSupportedInOmnistudioPackage": "Feature not supported - Omni Global Auto Number is not supported in Omnistudio Foundation package orgs.",

messages/migrate.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,11 @@
187187
"creatingNPMConfigFile": "Creating npm configuration file",
188188
"npmConfigFileCreated": "Npm config file created",
189189
"authKeyEnvVarNotSet": "The OMA_AUTH_KEY environment variable isn’t set. LWCs won't be deployed.",
190+
"npmNotInstalled": "We couldn't find npm on this system. LWC auto-deployment requires npm.",
191+
"lwcDeployPrerequisitesMissing": "LWC auto-deployment prerequisites aren't met: %s",
192+
"manualLwcDeploymentPrompt": "Manual LWC deployment is required. Do you want to continue with the migration? [y/n]",
193+
"manualLwcDeploymentProceeding": "Continuing the migration. Deploy the LWC components manually.",
194+
"npmAndAuthKeyRequired": "Install npm and set the OMA_AUTH_KEY environment variable, and then run the migration again.",
190195
"manualDeploymentSteps": "<a href='%s' target='_blank'>Please refer to this documentation for manual deployment process</a>",
191196
"deploymentConsentNotGiven": "Deployment consent not given, manual deployment is required",
192197
"experienceSiteException": "We’ve encountered an exception while processing Experience Cloud sites.",
@@ -284,6 +289,7 @@
284289
"deployComponentsManually": "Metadata Components deployment failed. Please deploy using generated package.xml manually using Salesforce CLI or Workbench. Check the logs for detailed error information.",
285290
"omniscriptDeploymentFailedContinuing": "Omniscript package deployment failed, continuing with report generation. Manual deployment required.",
286291
"deploymentFailedContinuing": "Deployment failed, continuing with report generation. Manual deployment required.",
292+
"manualDeploymentNeeded": "Manual deployment needed",
287293
"ensurePackageInstalled": "Please ensure omniscript customization package is properly installed: %s",
288294
"packageDeploymentFailedWithError": "Omniscript package deployment failed after %s attempts. Error: %s. Please check deployment logs and org settings.",
289295
"maxRetryAttemptsExceeded": "Maximum retry attempts (%s) exceeded for omniscript package deployment",
@@ -322,6 +328,7 @@
322328
"packagesHaveSameValue": "Both TheFirstInstalledOmniPackage and InstalledIndustryPackage have the same value.",
323329
"packagesHaveDifferentValue": "Both the InstalledIndustryPackage and TheFirstInstalledOmniPackage have different values.",
324330
"failedToCheckPackagesValue": "Failed to check the value of packages in Omni Interaction Configuration.",
331+
"omniStudioPermissionsNotEnabled": "The org doesn’t have Omnistudio permissions enabled. These permissions are required to migrate components. You can still run the assessment.",
325332
"packageDetails": "Your org contains only the TheFirstInstalledOmniPackage Omni Interaction Configuration.",
326333
"globalAutoNumberUnSupportedInOmnistudioPackage": "Feature not supported - Omni Global Auto Number is not supported in Omnistudio Foundation package orgs.",
327334
"orgUsecaseDetails": "The org is on %s data model with %s and the Omnistudio Metadata setting turned %s",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@salesforce/plugin-omnistudio-migration-tool",
33
"description": "This SFDX plugin migrates FlexCard, OmniScript, DataRaptor, and Integration Procedure custom objects to standard objects.",
4-
"version": "2.0.0-preview.28",
4+
"version": "2.0.0-preview.30",
55
"author": "Salesforce",
66
"bugs": "https://github.com/forcedotcom/cli/issues",
77
"dependencies": {

src/commands/omnistudio/migration/assess.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ export default class Assess extends SfCommand<AssessmentInfo> {
131131

132132
// Perform comprehensive validation using ValidatorService
133133
const validator = new ValidatorService(orgs, messages, conn);
134-
const isValidationPassed = await validator.validate();
134+
// Pass true to skip OmniStudio license check for assessment
135+
const isValidationPassed = await validator.validate(true);
135136

136137
if (!isValidationPassed) {
137138
return;

src/commands/omnistudio/migration/migrate.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,11 @@ export default class Migrate extends SfCommand<MigrateResult> {
279279
);
280280
generatePackageXml.createOmnistudioDeploymentXml(org.getConnection().version);
281281

282+
let deploymentFailed = false;
282283
try {
283284
await postMigrate.deploy(actionItems);
284285
} catch (error) {
286+
deploymentFailed = true;
285287
Logger.error(messages.getMessage('errorDeployingComponents'), error);
286288
Logger.logVerbose(error);
287289
// Even if deployment fails completely, continue with report generation
@@ -296,7 +298,8 @@ export default class Migrate extends SfCommand<MigrateResult> {
296298
messages,
297299
actionItems,
298300
objectsToProcess,
299-
migrateOnly
301+
migrateOnly,
302+
deploymentFailed
300303
);
301304
Logger.log(
302305
messages.getMessage('migrationSuccessfulMessage', [

src/migration/postMigrate.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,9 @@ export class PostMigrate extends BaseMigrationTool {
234234

235235
// Log the specific error details for troubleshooting
236236
Logger.logVerbose(`Deployment error details: ${errorMessage}`);
237+
238+
// Re-throw so callers (migrate.ts) can track deploymentFailed state
239+
throw error;
237240
}
238241
}
239242
}

src/migration/premigrate.ts

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { YES_SHORT, YES_LONG, NO_SHORT, NO_LONG } from '../utils/projectPathUtil
88
import { documentRegistry } from '../utils/constants/documentRegistry';
99
import { OmniStudioMetadataCleanupService } from '../utils/config/OmniStudioMetadataCleanupService';
1010
import { isStandardDataModelWithMetadataAPIEnabled } from '../utils/dataModelService';
11+
import { sfProject } from '../utils/sfcli/project/sfProject';
1112
import { BaseMigrationTool } from './base';
1213

1314
const authEnvKey = 'OMA_AUTH_KEY';
@@ -132,15 +133,9 @@ export class PreMigrate extends BaseMigrationTool {
132133
authKey: undefined,
133134
};
134135
if (consent && includeLwc) {
135-
deploymentConfig.authKey = process.env[authEnvKey];
136-
if (!deploymentConfig.authKey) {
137-
Logger.warn(this.messages.getMessage('authKeyEnvVarNotSet'));
138-
actionItems.push(
139-
`${this.messages.getMessage('authKeyEnvVarNotSet')}\n${this.messages.getMessage('manualDeploymentSteps', [
140-
documentRegistry.manualDeploymentSteps,
141-
])}`
142-
);
143-
}
136+
const lwcPrereqResult = await this.checkLwcDeployPrerequisites(actionItems);
137+
deploymentConfig.authKey = lwcPrereqResult.authKey;
138+
deploymentConfig.autoDeploy = lwcPrereqResult.autoDeploy;
144139
}
145140

146141
if (!consent) {
@@ -215,6 +210,70 @@ export class PreMigrate extends BaseMigrationTool {
215210
return await omniStudioMetadataCleanupService.cleanupOmniStudioMetadataTables();
216211
}
217212

213+
private async checkLwcDeployPrerequisites(
214+
actionItems: string[]
215+
): Promise<{ autoDeploy: boolean; authKey: string | undefined }> {
216+
const missingPrerequisites: string[] = [];
217+
218+
const isNpmAvailable = sfProject.isNpmInstalled();
219+
if (!isNpmAvailable) {
220+
missingPrerequisites.push(this.messages.getMessage('npmNotInstalled'));
221+
}
222+
223+
const authKey = process.env[authEnvKey];
224+
if (!authKey) {
225+
missingPrerequisites.push(this.messages.getMessage('authKeyEnvVarNotSet'));
226+
}
227+
228+
if (missingPrerequisites.length === 0) {
229+
return { autoDeploy: true, authKey };
230+
}
231+
232+
Logger.warn(this.messages.getMessage('lwcDeployPrerequisitesMissing', [missingPrerequisites.join(' ')]));
233+
234+
const proceedWithManual = await this.getManualLwcDeploymentConsent();
235+
236+
if (proceedWithManual) {
237+
Logger.log(this.messages.getMessage('manualLwcDeploymentProceeding'));
238+
actionItems.push(
239+
`${missingPrerequisites.join(' ')}\n${this.messages.getMessage('manualDeploymentSteps', [
240+
documentRegistry.manualDeploymentSteps,
241+
])}`
242+
);
243+
return { autoDeploy: true, authKey: undefined };
244+
}
245+
246+
Logger.error(this.messages.getMessage('npmAndAuthKeyRequired'));
247+
process.exit(1);
248+
}
249+
250+
private async getManualLwcDeploymentConsent(): Promise<boolean> {
251+
const askWithTimeOut = PromptUtil.askWithTimeOut(this.messages);
252+
const validResponse = false;
253+
254+
while (!validResponse) {
255+
try {
256+
const resp = await askWithTimeOut(
257+
Logger.prompt.bind(Logger),
258+
this.messages.getMessage('manualLwcDeploymentPrompt')
259+
);
260+
const response = typeof resp === 'string' ? resp.trim().toLowerCase() : '';
261+
262+
if (response === YES_SHORT || response === YES_LONG) {
263+
return true;
264+
} else if (response === NO_SHORT || response === NO_LONG) {
265+
return false;
266+
} else {
267+
Logger.error(this.messages.getMessage('invalidYesNoResponse'));
268+
}
269+
} catch (err) {
270+
Logger.error(this.messages.getMessage('requestTimedOut'));
271+
process.exit(1);
272+
}
273+
}
274+
return false;
275+
}
276+
218277
// This needs to be behind timeout
219278
private async getExpSiteMetadataEnableConsent(): Promise<boolean> {
220279
const question = this.messages.getMessage('consentForExperienceSites');

src/utils/constants/stringContants.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,14 @@ export const Constants = {
8282
OmniDataTransformConfigTable: 'OmniDataTransformConfig',
8383
OmniUiCardConfigTable: 'OmniUiCardConfig',
8484
};
85+
86+
export const Status = {
87+
SuccessfullyMigrated: 'Successfully migrated',
88+
Failed: 'Failed',
89+
Skipped: 'Skipped',
90+
Complete: 'Complete',
91+
ReadyForMigration: 'Ready for migration',
92+
NeedsManualIntervention: 'Needs manual intervention',
93+
ManualDeploymentNeeded: 'Manual deployment needed',
94+
SuccessfullyCompleted: 'Successfully Completed',
95+
};

src/utils/orgPreferences.ts

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Connection } from '@salesforce/core';
1+
import { Connection, Messages } from '@salesforce/core';
22
import {
33
OmniStudioSettingsMetadata,
44
ExperienceBundleSettingsMetadata,
@@ -9,6 +9,10 @@ import {
99
import { Logger } from './logger';
1010
import { Constants } from './constants/stringContants';
1111

12+
// Load messages
13+
Messages.importMessagesDirectory(__dirname);
14+
const messages = Messages.loadMessages('@salesforce/plugin-omnistudio-migration-tool', 'migrate');
15+
1216
/**
1317
* Class to manage OmniStudio organization preferences
1418
*
@@ -90,7 +94,14 @@ export class OrgPreferences {
9094
}
9195
}
9296
return enabledFlags;
93-
} catch (error) {
97+
} catch (error: unknown) {
98+
// Check if error is INVALID_TYPE for OmniInteractionConfig (indicating no OmniStudio permissions)
99+
if (this.isOmniInteractionConfigInvalidTypeError(error)) {
100+
Logger.warn(messages.getMessage('omniStudioPermissionsNotEnabled'));
101+
return []; // Return empty array instead of throwing
102+
}
103+
104+
// Generic error handling for other errors
94105
throw new Error(`Failed to check rollback flags: ${error instanceof Error ? error.message : String(error)}`);
95106
}
96107
}
@@ -204,8 +215,14 @@ export class OrgPreferences {
204215
} else {
205216
return false;
206217
}
207-
} catch (error) {
208-
// TODO: What should be the default behavior if the query fails?
218+
} catch (error: unknown) {
219+
// Check if error is INVALID_TYPE for OmniInteractionConfig (indicating no OmniStudio permissions)
220+
if (this.isOmniInteractionConfigInvalidTypeError(error)) {
221+
Logger.warn(messages.getMessage('omniStudioPermissionsNotEnabled'));
222+
return false; // Fall back to use case 1 since the org doesn't have OmniStudio permissions enabled
223+
}
224+
225+
// Generic error handling for other errors
209226
const errMsg = error instanceof Error ? error.message : String(error);
210227
Logger.error(`Error checking standard designer for namespace ${namespaceToModify}: ${errMsg}`);
211228
return false;
@@ -227,10 +244,38 @@ export class OrgPreferences {
227244
}
228245

229246
return false;
230-
} catch (error) {
247+
} catch (error: unknown) {
248+
// Check if error is INVALID_TYPE for OmniInteractionConfig (indicating no OmniStudio permissions)
249+
if (this.isOmniInteractionConfigInvalidTypeError(error)) {
250+
Logger.warn(messages.getMessage('omniStudioPermissionsNotEnabled'));
251+
return false; // Fall back to use case 1 since the org doesn't have OmniStudio permissions enabled
252+
}
253+
254+
// Generic error handling for other errors
231255
const errMsg = error instanceof Error ? error.message : String(error);
232256
Logger.error(`Error checking foundation package : ${errMsg}`);
233257
return false;
234258
}
235259
}
260+
261+
/**
262+
* Checks if an error is an INVALID_TYPE error for OmniInteractionConfig
263+
* This indicates that the org doesn't have OmniStudio permissions enabled
264+
*
265+
* @private
266+
* @static
267+
* @param {unknown} error - The error to check
268+
* @returns {boolean} True if the error is an INVALID_TYPE error for OmniInteractionConfig
269+
*/
270+
private static isOmniInteractionConfigInvalidTypeError(error: unknown): boolean {
271+
return (
272+
error !== null &&
273+
error !== undefined &&
274+
typeof error === 'object' &&
275+
'errorCode' in error &&
276+
(error as { errorCode: unknown }).errorCode === 'INVALID_TYPE' &&
277+
'message' in error &&
278+
String((error as { message: unknown }).message).includes('OmniInteractionConfig')
279+
);
280+
}
236281
}

0 commit comments

Comments
 (0)