From f57178fe2212a45cae8b7a5e5577f31e142f8bb9 Mon Sep 17 00:00:00 2001 From: abhinavkumar2 Date: Thu, 14 Nov 2024 19:47:21 +0530 Subject: [PATCH] feat: added apex and lwc in migration report --- src/commands/omnistudio/migration/migrate.ts | 11 +- src/migration/interfaces.ts | 22 --- src/migration/related/ApexMigration.ts | 43 ++++-- src/migration/related/LwcMigration.ts | 8 +- .../OmnistudioRelatedObjectMigrationFacade.ts | 52 ++++--- src/utils/generatePackageXml.ts | 27 +++- src/utils/interfaces.ts | 4 + .../lwcparser/fileutils/HtmlFileProcessor.ts | 13 +- .../fileutils/JavascriptFileProcessor.ts | 13 +- .../lwcparser/fileutils/XmlFileProcessor.ts | 13 +- src/utils/resultsbuilder/index.ts | 131 +++++++++++++++++- 11 files changed, 238 insertions(+), 99 deletions(-) diff --git a/src/commands/omnistudio/migration/migrate.ts b/src/commands/omnistudio/migration/migrate.ts index 72b6fed..75ea801 100644 --- a/src/commands/omnistudio/migration/migrate.ts +++ b/src/commands/omnistudio/migration/migrate.ts @@ -176,12 +176,15 @@ export default class Migrate extends OmniStudioBaseCommand { allVersions, this.org ); - const relatedObjectMigrationResult = omnistudioRelatedObjectsMigration.migrateAll(objectMigrationResults, []); + const relatedObjectMigrationResult = omnistudioRelatedObjectsMigration.migrateAll(objectMigrationResults, [ + 'lwc', + 'apex', + ]); generatePackageXml.createChangeList( - relatedObjectMigrationResult.apexClasses, - relatedObjectMigrationResult.lwcComponents + relatedObjectMigrationResult.apexAssessmentInfos, + relatedObjectMigrationResult.lwcAssessmentInfos ); - await ResultsBuilder.generate(objectMigrationResults, conn.instanceUrl); + await ResultsBuilder.generate(objectMigrationResults, relatedObjectMigrationResult, conn.instanceUrl); // save timer to debug logger this.logger.debug(timer); diff --git a/src/migration/interfaces.ts b/src/migration/interfaces.ts index 1f89eb9..66893ff 100644 --- a/src/migration/interfaces.ts +++ b/src/migration/interfaces.ts @@ -83,28 +83,6 @@ export interface NameTransformData { nameWithSepcialCharactorSet: Set; } -export interface RelatedObjectsMigrate { - /** - * Identifies migration candidates based on the provided migration results and namespace. - * - * @param migrationResults List of migration results to identify objects from. - * @param namespace The namespace used to identify objects. - * @returns List of identified migration candidates as strings. - */ - identifyObjects(migrationResults: MigrationResult[]): Promise; - - /** - * Private method to perform the migration of related objects based on the provided candidates. - * - * @param migrationResults List of migration results to use for migration. - * @param namespace The namespace used to perform the migration. - * @param migrationCandidates List of candidates to migrate. - */ - migrateRelatedObjects(migrationResults: MigrationResult[], migrationCandidates: JSON[]): string[]; - - processObjectType(): string; -} - export type LWCComponentMigrationTool = MigrationTool; export type CustomLabelMigrationTool = MigrationTool; diff --git a/src/migration/related/ApexMigration.ts b/src/migration/related/ApexMigration.ts index 21ad0b6..3e5c864 100644 --- a/src/migration/related/ApexMigration.ts +++ b/src/migration/related/ApexMigration.ts @@ -12,12 +12,13 @@ import { SingleTokenUpdate, TokenUpdater, } from '../../utils/apex/parser/apexparser'; -import { MigrationResult, RelatedObjectsMigrate } from '../interfaces'; +import { MigrationResult } from '../interfaces'; import { sfProject } from '../../utils/sfcli/project/sfProject'; import { fileutil, File } from '../../utils/file/fileutil'; import { Logger } from '../../utils/logger'; import { ApexAssessmentInfo } from '../../utils'; import { FileDiffUtil } from '../../utils/lwcparser/fileutils/FileDiffUtil'; +import { Stringutil } from '../../utils/StringValue/stringutil'; import { BaseRelatedObjectMigration } from './BaseRealtedObjectMigration'; const APEXCLASS = 'Apexclass'; @@ -26,7 +27,7 @@ const CALLABLE = 'Callable'; const VLOCITY_OPEN_INTERFACE2 = 'VlocityOpenInterface2'; const VLOCITY_OPEN_INTERFACE = 'VlocityOpenInterface'; -export class ApexMigration extends BaseRelatedObjectMigration implements RelatedObjectsMigrate { +export class ApexMigration extends BaseRelatedObjectMigration { private readonly callableInterface: InterfaceImplements; private readonly vlocityOpenInterface2: InterfaceImplements; private readonly vlocityOpenInterface: InterfaceImplements; @@ -43,25 +44,24 @@ export class ApexMigration extends BaseRelatedObjectMigration implements Related public identifyObjects(migrationResults: MigrationResult[]): Promise { throw new Error('Method not implemented.'); } - public migrateRelatedObjects(migrationResults: MigrationResult[], migrationCandidates: JSON[]): string[] { + public migrateRelatedObjects(migrationResults: MigrationResult[], migrationCandidates: JSON[]): ApexAssessmentInfo[] { return this.migrate(); } - public migrate(): string[] { + public migrate(): ApexAssessmentInfo[] { const pwd = shell.pwd(); shell.cd(this.projectPath); const targetOrg: Org = this.org; - // sfProject.retrieve(APEXCLASS, targetOrg.getUsername()); + sfProject.retrieve(APEXCLASS, targetOrg.getUsername()); const apexAssessmentInfos = this.processApexFiles(this.projectPath); - sfProject.deploy(APEXCLASS, targetOrg.getUsername()); + // sfProject.deploy(APEXCLASS, targetOrg.getUsername()); shell.cd(pwd); - return this.mapTOName(apexAssessmentInfos); + return apexAssessmentInfos; } public assess(): ApexAssessmentInfo[] { const pwd = shell.pwd(); shell.cd(this.projectPath); - // const targetOrg: Org = this.org; - // sfProject.retrieve(APEXCLASS, this.org.getUsername()); + sfProject.retrieve(APEXCLASS, this.org.getUsername()); const apexAssessmentInfos = this.processApexFiles(this.projectPath); shell.cd(pwd); return apexAssessmentInfos; @@ -158,6 +158,19 @@ export class ApexMigration extends BaseRelatedObjectMigration implements Related for (const tokenChange of namespaceChanges.get(this.namespace)) tokenUpdates.push(new SingleTokenUpdate(this.updatedNamespace, tokenChange)); } + + const methodParameters = parser.methodParameters; + if (methodParameters.size === 0) return tokenUpdates; + const drParameters = methodParameters.get(ParameterType.DR_NAME); + if (drParameters) { + for (const token of drParameters) { + const newName = `'${Stringutil.cleanName(token.text)}'`; + if (token.text === newName) continue; + Logger.logger.info(`In Apex ${file.name} DR name ${token.text} will be updated to ${newName} `); + Logger.ux.log(`In Apex ${file.name} DR name ${token.text} will be updated to ${newName}`); + tokenUpdates.push(new SingleTokenUpdate(newName, token)); + } + } return tokenUpdates; } @@ -184,10 +197,10 @@ export class ApexMigration extends BaseRelatedObjectMigration implements Related } `; } - - private mapTOName(apexAssessmentInfos: ApexAssessmentInfo[]): string[] { - return apexAssessmentInfos.map((apexAssessmentInfo) => { - return apexAssessmentInfo.name; - }); - } + /* + private mapTOName(apexAssessmentInfos: ApexAssessmentInfo[]): string[] { + return apexAssessmentInfos.map((apexAssessmentInfo) => { + return apexAssessmentInfo.name; + }); + } */ } diff --git a/src/migration/related/LwcMigration.ts b/src/migration/related/LwcMigration.ts index 2c4caf1..ac9fdef 100644 --- a/src/migration/related/LwcMigration.ts +++ b/src/migration/related/LwcMigration.ts @@ -2,7 +2,7 @@ import * as shell from 'shelljs'; import { Org } from '@salesforce/core'; import { fileutil, File } from '../../utils/file/fileutil'; -import { MigrationResult, RelatedObjectsMigrate } from '../interfaces'; +import { MigrationResult } from '../interfaces'; import { sfProject } from '../../utils/sfcli/project/sfProject'; import { Logger } from '../../utils/logger'; import { FileProcessorFactory } from '../../utils/lwcparser/fileutils/FileProcessorFactory'; @@ -12,7 +12,7 @@ import { BaseRelatedObjectMigration } from './BaseRealtedObjectMigration'; const LWC_DIR_PATH = '/force-app/main/default/lwc'; const LWCTYPE = 'LightningComponentBundle'; -export class LwcMigration extends BaseRelatedObjectMigration implements RelatedObjectsMigrate { +export class LwcMigration extends BaseRelatedObjectMigration { public processObjectType(): string { return 'lwc'; } @@ -27,7 +27,7 @@ export class LwcMigration extends BaseRelatedObjectMigration implements RelatedO const type = 'assessment'; const pwd = shell.pwd(); shell.cd(this.projectPath); - // sfProject.retrieve(LWCTYPE, this.org.getUsername()); + sfProject.retrieve(LWCTYPE, this.org.getUsername()); const filesMap = this.processLwcFiles(this.projectPath); shell.cd(pwd); return this.processFiles(filesMap, type); @@ -40,7 +40,7 @@ export class LwcMigration extends BaseRelatedObjectMigration implements RelatedO sfProject.retrieve(LWCTYPE, targetOrg.getUsername()); const filesMap = this.processLwcFiles(this.projectPath); const LWCAssessmentInfos = this.processFiles(filesMap, 'migration'); - sfProject.deploy(LWCTYPE, targetOrg.getUsername()); + // sfProject.deploy(LWCTYPE, targetOrg.getUsername()); shell.cd(pwd); return LWCAssessmentInfos; } diff --git a/src/migration/related/OmnistudioRelatedObjectMigrationFacade.ts b/src/migration/related/OmnistudioRelatedObjectMigrationFacade.ts index 6eb22dc..a6af1ad 100644 --- a/src/migration/related/OmnistudioRelatedObjectMigrationFacade.ts +++ b/src/migration/related/OmnistudioRelatedObjectMigrationFacade.ts @@ -4,8 +4,13 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Org } from '@salesforce/core'; import '../../utils/prototypes'; -import { DebugTimer, MigratedObject } from '../../utils'; -import { RelatedObjectMigrationResult, RelatedObjectsMigrate } from '../interfaces'; +import { + ApexAssessmentInfo, + DebugTimer, + LWCAssessmentInfo, + MigratedObject, + RelatedObjectAssesmentInfo, +} from '../../utils'; import { sfProject } from '../../utils/sfcli/project/sfProject'; import { Logger } from '../../utils/logger'; import { ApexMigration } from './ApexMigration'; @@ -44,35 +49,33 @@ export default class OmnistudioRelatedObjectMigrationFacade { return process.cwd() + '/' + defaultProjectName; } } - public migrateAll(migrationResult: MigratedObject[], relatedObjects: string[]): RelatedObjectMigrationResult { + public migrateAll(migrationResult: MigratedObject[], relatedObjects: string[]): RelatedObjectAssesmentInfo { // Start the debug timer DebugTimer.getInstance().start(); // Declare an array of MigrationTool - const migrationTools: RelatedObjectsMigrate[] = []; const projectDirectory: string = OmnistudioRelatedObjectMigrationFacade.intializeProject(); const debugTimer = DebugTimer.getInstance(); debugTimer.start(); // Initialize migration tools based on the relatedObjects parameter - if (relatedObjects.includes('lwc')) { - migrationTools.push(this.createLWCComponentMigrationTool(this.namespace, projectDirectory)); - } - if (relatedObjects.includes('labels')) { - migrationTools.push(this.createCustomLabelMigrationTool(this.namespace, this.org)); - } - if (relatedObjects.includes('apex')) { - migrationTools.push(this.createApexClassMigrationTool(projectDirectory)); - } - const results = new Map(); + const apexMigrator = this.createApexClassMigrationTool(projectDirectory); + const lwcMigrator = this.createLWCComponentMigrationTool(this.namespace, projectDirectory); + let apexAssessmentInfos: ApexAssessmentInfo[] = []; + let lwcAssessmentInfos: LWCAssessmentInfo[] = []; // Proceed with migration logic - for (const migrationTool of migrationTools) { - try { - results.set(migrationTool.processObjectType(), migrationTool.migrateRelatedObjects(null, null)); - } catch (Error) { - // Log the error - Logger.logger.error(Error.message); - } + try { + apexAssessmentInfos = apexMigrator.migrate(); + } catch (Error) { + // Log the error + Logger.logger.error(Error.message); + } + try { + lwcAssessmentInfos = lwcMigrator.migrate(); + } catch (Error) { + // Log the error + Logger.logger.error(Error.message); } + // Truncate existing objects if necessary // Stop the debug timer const timer = debugTimer.stop(); @@ -81,7 +84,7 @@ export default class OmnistudioRelatedObjectMigrationFacade { Logger.logger.debug(timer); // Return results needed for --json flag - return { apexClasses: results.get('apex'), lwcComponents: results.get('lwc') }; + return { apexAssessmentInfos, lwcAssessmentInfos }; } // Factory methods to create instances of specific tools @@ -90,11 +93,6 @@ export default class OmnistudioRelatedObjectMigrationFacade { return new LwcMigration(projectPath, this.namespace, this.org); } - private createCustomLabelMigrationTool(namespace: string, org: Org): RelatedObjectsMigrate { - // Return an instance of CustomLabelMigrationTool when implemented - throw new Error('CustomLabelMigrationTool implementation is not provided yet.'); - } - private createApexClassMigrationTool(projectPath: string): ApexMigration { // Return an instance of ApexClassMigrationTool when implemented return new ApexMigration(projectPath, this.namespace, this.org); diff --git a/src/utils/generatePackageXml.ts b/src/utils/generatePackageXml.ts index cab1cd5..9777f1a 100644 --- a/src/utils/generatePackageXml.ts +++ b/src/utils/generatePackageXml.ts @@ -1,11 +1,18 @@ import * as fs from 'fs'; import * as path from 'path'; +import { ApexAssessmentInfo, LWCAssessmentInfo } from './interfaces'; export class generatePackageXml { // Method to generate package.xml with additional types - public static createChangeList(apexClasses: string[], lwcComponents: string[]): void { - const apexXml = generatePackageXml.getXmlElementforMembers(apexClasses, 'ApexClass'); - const lwcXml = generatePackageXml.getXmlElementforMembers(lwcComponents, 'LightningComponentBundle'); + public static createChangeList( + apexAssementInfos: ApexAssessmentInfo[], + lwcAssessmentInfos: LWCAssessmentInfo[] + ): void { + const apexXml = generatePackageXml.getXmlElementforMembers(this.getApexclasses(apexAssementInfos), 'ApexClass'); + const lwcXml = generatePackageXml.getXmlElementforMembers( + this.getLwcs(lwcAssessmentInfos), + 'LightningComponentBundle' + ); const additionalTypes = ` @@ -67,4 +74,18 @@ export class generatePackageXml { ${type} `; } + + private static getApexclasses(apexAssessmentInfos: ApexAssessmentInfo[]): string[] { + if (!apexAssessmentInfos || apexAssessmentInfos.length === 0) return []; + return apexAssessmentInfos.map((apexAssessmentInfo) => { + return apexAssessmentInfo.name; + }); + } + + private static getLwcs(lwcAssessmentInfos: LWCAssessmentInfo[]): string[] { + if (!lwcAssessmentInfos || lwcAssessmentInfos.length === 0) return []; + return lwcAssessmentInfos.map((lwcAssessmentInfo) => { + return lwcAssessmentInfo.name; + }); + } } diff --git a/src/utils/interfaces.ts b/src/utils/interfaces.ts index 737f091..d7571f1 100644 --- a/src/utils/interfaces.ts +++ b/src/utils/interfaces.ts @@ -78,6 +78,10 @@ export interface AssessmentInfo { dataRaptorAssessmentInfos: DataRaptorAssessmentInfo[]; } +export interface RelatedObjectAssesmentInfo { + apexAssessmentInfos: ApexAssessmentInfo[]; + lwcAssessmentInfos: LWCAssessmentInfo[]; +} export interface FlexCardAssessmentInfo { name: string; id: string; diff --git a/src/utils/lwcparser/fileutils/HtmlFileProcessor.ts b/src/utils/lwcparser/fileutils/HtmlFileProcessor.ts index e8952a5..f343397 100644 --- a/src/utils/lwcparser/fileutils/HtmlFileProcessor.ts +++ b/src/utils/lwcparser/fileutils/HtmlFileProcessor.ts @@ -16,16 +16,15 @@ export class HtmlFileProcessor implements FileProcessor { const fileDiffUtil = new FileDiffUtil(); const fileContent: Map = parse.replaceTags(namespace); if (fileContent) { + const diff = fileDiffUtil.getFileDiff( + file.name + file.ext, + fileContent.get(FileConstant.BASE_CONTENT), + fileContent.get(FileConstant.MODIFIED_CONTENT) + ); if (type != null && type === 'migration') { fileutil.saveToFile(filePath, fileContent.get(FileConstant.MODIFIED_CONTENT)); - } else { - const diff = fileDiffUtil.getFileDiff( - file.name + file.ext, - fileContent.get(FileConstant.BASE_CONTENT), - fileContent.get(FileConstant.MODIFIED_CONTENT) - ); - return diff; } + return diff; } } } diff --git a/src/utils/lwcparser/fileutils/JavascriptFileProcessor.ts b/src/utils/lwcparser/fileutils/JavascriptFileProcessor.ts index a4b3542..80d5d63 100644 --- a/src/utils/lwcparser/fileutils/JavascriptFileProcessor.ts +++ b/src/utils/lwcparser/fileutils/JavascriptFileProcessor.ts @@ -20,16 +20,15 @@ export class JavascriptFileProcessor implements FileProcessor { const filePath = file.location; const fileContent: Map = jsParser.replaceImportSource(filePath, namespace); if (fileContent) { + const diff = fileDiffUtil.getFileDiff( + file.name + file.ext, + fileContent.get(FileConstant.BASE_CONTENT), + fileContent.get(FileConstant.MODIFIED_CONTENT) + ); if (type != null && type === 'migration') { fileutil.saveToFile(filePath, fileContent.get(FileConstant.MODIFIED_CONTENT)); - } else { - const diff = fileDiffUtil.getFileDiff( - file.name + file.ext, - fileContent.get(FileConstant.BASE_CONTENT), - fileContent.get(FileConstant.MODIFIED_CONTENT) - ); - return diff; } + return diff; } } } diff --git a/src/utils/lwcparser/fileutils/XmlFileProcessor.ts b/src/utils/lwcparser/fileutils/XmlFileProcessor.ts index 2b4ab0f..268c4c7 100644 --- a/src/utils/lwcparser/fileutils/XmlFileProcessor.ts +++ b/src/utils/lwcparser/fileutils/XmlFileProcessor.ts @@ -20,16 +20,15 @@ export class XmlFileProcessor implements FileProcessor { const fileDiffUtil = new FileDiffUtil(); const fileContent: Map = parser.removeNode(XML_TAG_TO_REPLACE); if (fileContent) { + const diff = fileDiffUtil.getFileDiff( + file.name + file.ext, + fileContent.get(FileConstant.BASE_CONTENT), + fileContent.get(FileConstant.MODIFIED_CONTENT) + ); if (type != null && type === 'migration') { fileutil.saveToFile(filePath, fileContent.get(FileConstant.MODIFIED_CONTENT)); - } else { - const diff = fileDiffUtil.getFileDiff( - file.name + file.ext, - fileContent.get(FileConstant.BASE_CONTENT), - fileContent.get(FileConstant.MODIFIED_CONTENT) - ); - return diff; } + return diff; } } } diff --git a/src/utils/resultsbuilder/index.ts b/src/utils/resultsbuilder/index.ts index 4776510..d5b919b 100644 --- a/src/utils/resultsbuilder/index.ts +++ b/src/utils/resultsbuilder/index.ts @@ -1,15 +1,20 @@ import fs from 'fs'; import open from 'open'; -import { MigratedObject } from '../interfaces'; +import { ApexAssessmentInfo, LWCAssessmentInfo, MigratedObject, RelatedObjectAssesmentInfo } from '../interfaces'; export class ResultsBuilder { - public static async generate(results: MigratedObject[], instanceUrl: string): Promise { + public static async generate( + results: MigratedObject[], + relatedObjectMigrationResult: RelatedObjectAssesmentInfo, + instanceUrl: string + ): Promise { let htmlBody = ''; for (const result of results) { htmlBody += '
' + this.generateResult(result, instanceUrl); } - + htmlBody += '
' + this.generateApexAssesment(relatedObjectMigrationResult.apexAssessmentInfos); + htmlBody += '
' + this.generateLwcAssesment(relatedObjectMigrationResult.lwcAssessmentInfos); const doc = this.generateDocument(htmlBody); const fileUrl = process.cwd() + '/migrationresults.html'; fs.writeFileSync(fileUrl, doc); @@ -118,4 +123,124 @@ export class ResultsBuilder { return table; } + + private static generateMessages(messages: string[]): string { + let messageBody = ''; + for (const message of messages) { + messageBody += `
  • ${message}
  • `; + } + return messageBody; + } + private static generateApexAssesment(apexAssessmentInfos: ApexAssessmentInfo[]): string { + let tableBody = ''; + tableBody += '
    Apex Assessment
    '; + for (const apexAssessmentInfo of apexAssessmentInfos) { + const message = this.generateMessages(apexAssessmentInfo.infos); + const errors = this.generateMessages(apexAssessmentInfo.warnings); + const row = ` +
    ${apexAssessmentInfo.name}
    + +
    ${apexAssessmentInfo.diff}
    +
    ${message} +
    ${errors} + `; + tableBody += row; + } + return this.getApexAssessmentReport(tableBody); + } + + private static getApexAssessmentReport(tableContent: string): string { + const tableBody = ` +
    + + + + + + + + + + + + ${tableContent} + +
    +
    Name
    +
    +
    File reference
    +
    +
    Diff
    +
    +
    Comments
    +
    +
    Errors
    +
    +
    `; + return tableBody; + } + + private static generateLwcAssesment(lwcAssessmentInfos: LWCAssessmentInfo[]): string { + let tableBody = ''; + tableBody += ` + + + OmniStudio Migration Assessment + + + +
    + + + + `; + return this.getLWCAssesmentReport(tableBody); + } + + private static getLWCAssesmentReport(tableContent: string): string { + const tableBody = ` +
    + + + + + + + + + + ${tableContent} + +
    +
    Name
    +
    +
    File Path & Diff
    +
    +
    Errors
    +
    +
    `; + return tableBody; + } }