@salesforce/plugin-omnistudio-migration-tool 2.0.0-rc.6 → 2.0.0-rc.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/README.md +165 -73
  2. package/lib/commands/omnistudio/migration/assess.d.ts +23 -15
  3. package/lib/commands/omnistudio/migration/assess.js +250 -89
  4. package/lib/commands/omnistudio/migration/assess.js.map +1 -1
  5. package/lib/commands/omnistudio/migration/clean.d.ts +13 -0
  6. package/lib/commands/omnistudio/migration/clean.js +162 -0
  7. package/lib/commands/omnistudio/migration/clean.js.map +1 -0
  8. package/lib/commands/omnistudio/migration/info.d.ts +10 -16
  9. package/lib/commands/omnistudio/migration/info.js +53 -35
  10. package/lib/commands/omnistudio/migration/info.js.map +1 -1
  11. package/lib/commands/omnistudio/migration/migrate.d.ts +78 -18
  12. package/lib/commands/omnistudio/migration/migrate.js +461 -175
  13. package/lib/commands/omnistudio/migration/migrate.js.map +1 -1
  14. package/lib/error/deploymentErrors.d.ts +15 -0
  15. package/lib/error/deploymentErrors.js +35 -0
  16. package/lib/error/deploymentErrors.js.map +1 -0
  17. package/lib/error/errorInterfaces.d.ts +5 -0
  18. package/lib/error/errorInterfaces.js +9 -1
  19. package/lib/error/errorInterfaces.js.map +1 -1
  20. package/lib/javascripts/reportGeneratorUtility.js +585 -22
  21. package/lib/migration/ApexNamespaceRegistry.d.ts +49 -0
  22. package/lib/migration/ApexNamespaceRegistry.js +130 -0
  23. package/lib/migration/ApexNamespaceRegistry.js.map +1 -0
  24. package/lib/migration/CustomCssRegistry.d.ts +117 -0
  25. package/lib/migration/CustomCssRegistry.js +234 -0
  26. package/lib/migration/CustomCssRegistry.js.map +1 -0
  27. package/lib/migration/NameMappingRegistry.d.ts +134 -0
  28. package/lib/migration/NameMappingRegistry.js +411 -0
  29. package/lib/migration/NameMappingRegistry.js.map +1 -0
  30. package/lib/migration/base.d.ts +8 -6
  31. package/lib/migration/base.js +25 -8
  32. package/lib/migration/base.js.map +1 -1
  33. package/lib/migration/customLabels.d.ts +70 -0
  34. package/lib/migration/customLabels.js +177 -0
  35. package/lib/migration/customLabels.js.map +1 -0
  36. package/lib/migration/dataraptor.d.ts +13 -0
  37. package/lib/migration/dataraptor.js +205 -80
  38. package/lib/migration/dataraptor.js.map +1 -1
  39. package/lib/migration/deployer.d.ts +14 -0
  40. package/lib/migration/deployer.js +105 -0
  41. package/lib/migration/deployer.js.map +1 -0
  42. package/lib/migration/flexcard.d.ts +256 -6
  43. package/lib/migration/flexcard.js +1808 -268
  44. package/lib/migration/flexcard.js.map +1 -1
  45. package/lib/migration/globalautonumber.d.ts +8 -8
  46. package/lib/migration/globalautonumber.js +49 -24
  47. package/lib/migration/globalautonumber.js.map +1 -1
  48. package/lib/migration/interfaces.d.ts +14 -0
  49. package/lib/migration/interfaces.js.map +1 -1
  50. package/lib/migration/metadataobjnamecheck.js.map +1 -1
  51. package/lib/migration/omniscript.d.ts +218 -4
  52. package/lib/migration/omniscript.js +1709 -247
  53. package/lib/migration/omniscript.js.map +1 -1
  54. package/lib/migration/omniscriptInstance.d.ts +90 -0
  55. package/lib/migration/omniscriptInstance.js +755 -0
  56. package/lib/migration/omniscriptInstance.js.map +1 -0
  57. package/lib/migration/postMigrate.d.ts +20 -4
  58. package/lib/migration/postMigrate.js +199 -12
  59. package/lib/migration/postMigrate.js.map +1 -1
  60. package/lib/migration/premigrate.d.ts +51 -0
  61. package/lib/migration/premigrate.js +325 -0
  62. package/lib/migration/premigrate.js.map +1 -0
  63. package/lib/migration/related/ApexMigration.d.ts +3 -0
  64. package/lib/migration/related/ApexMigration.js +222 -56
  65. package/lib/migration/related/ApexMigration.js.map +1 -1
  66. package/lib/migration/related/ExperienceSiteMigration.d.ts +30 -5
  67. package/lib/migration/related/ExperienceSiteMigration.js +263 -73
  68. package/lib/migration/related/ExperienceSiteMigration.js.map +1 -1
  69. package/lib/migration/related/FlexipageMigration.d.ts +5 -5
  70. package/lib/migration/related/FlexipageMigration.js +60 -38
  71. package/lib/migration/related/FlexipageMigration.js.map +1 -1
  72. package/lib/migration/related/LwcMigration.js +45 -26
  73. package/lib/migration/related/LwcMigration.js.map +1 -1
  74. package/lib/migration/related/OmnistudioRelatedObjectMigrationFacade.js +48 -32
  75. package/lib/migration/related/OmnistudioRelatedObjectMigrationFacade.js.map +1 -1
  76. package/lib/styles/reportGenerator.css +241 -16
  77. package/lib/templates/assessmentReport.template +78 -8
  78. package/lib/templates/dashboard.template +86 -57
  79. package/lib/templates/migrationReport.template +151 -0
  80. package/lib/utils/OmnistudioSettingsPrefManager.d.ts +14 -0
  81. package/lib/utils/OmnistudioSettingsPrefManager.js +112 -0
  82. package/lib/utils/OmnistudioSettingsPrefManager.js.map +1 -0
  83. package/lib/utils/XMLUtil.js +2 -1
  84. package/lib/utils/XMLUtil.js.map +1 -1
  85. package/lib/utils/apex/executor/AnonymousApexRunner.d.ts +1 -1
  86. package/lib/utils/apex/parser/apexparser.d.ts +8 -1
  87. package/lib/utils/apex/parser/apexparser.js +79 -13
  88. package/lib/utils/apex/parser/apexparser.js.map +1 -1
  89. package/lib/utils/config/ExistingRecordCleanupService.d.ts +30 -0
  90. package/lib/utils/config/ExistingRecordCleanupService.js +266 -0
  91. package/lib/utils/config/ExistingRecordCleanupService.js.map +1 -0
  92. package/lib/utils/config/OmniStudioMetadataCleanupService.d.ts +36 -0
  93. package/lib/utils/config/OmniStudioMetadataCleanupService.js +123 -0
  94. package/lib/utils/config/OmniStudioMetadataCleanupService.js.map +1 -0
  95. package/lib/utils/config/SpecialCharacterRecordCleanupService.d.ts +17 -0
  96. package/lib/utils/config/SpecialCharacterRecordCleanupService.js +186 -0
  97. package/lib/utils/config/SpecialCharacterRecordCleanupService.js.map +1 -0
  98. package/lib/utils/constants/documentRegistry.d.ts +9 -17
  99. package/lib/utils/constants/documentRegistry.js +9 -17
  100. package/lib/utils/constants/documentRegistry.js.map +1 -1
  101. package/lib/utils/constants/stringContants.d.ts +78 -0
  102. package/lib/utils/constants/stringContants.js +91 -4
  103. package/lib/utils/constants/stringContants.js.map +1 -1
  104. package/lib/utils/customLabels.d.ts +35 -0
  105. package/lib/utils/customLabels.js +100 -0
  106. package/lib/utils/customLabels.js.map +1 -0
  107. package/lib/utils/dataModelService.d.ts +18 -0
  108. package/lib/utils/dataModelService.js +72 -0
  109. package/lib/utils/dataModelService.js.map +1 -0
  110. package/lib/utils/file/fileUtil.d.ts +3 -1
  111. package/lib/utils/file/fileUtil.js +30 -13
  112. package/lib/utils/file/fileUtil.js.map +1 -1
  113. package/lib/utils/flexipage/flexiPageTransformer.js +119 -23
  114. package/lib/utils/flexipage/flexiPageTransformer.js.map +1 -1
  115. package/lib/utils/formula/FormulaUtil.d.ts +1 -1
  116. package/lib/utils/formula/FormulaUtil.js +17 -9
  117. package/lib/utils/formula/FormulaUtil.js.map +1 -1
  118. package/lib/utils/formula/Stack.js.map +1 -1
  119. package/lib/utils/generatePackageXml.d.ts +6 -2
  120. package/lib/utils/generatePackageXml.js +73 -33
  121. package/lib/utils/generatePackageXml.js.map +1 -1
  122. package/lib/utils/index.d.ts +1 -0
  123. package/lib/utils/index.js +1 -0
  124. package/lib/utils/index.js.map +1 -1
  125. package/lib/utils/interfaces.d.ts +69 -8
  126. package/lib/utils/json/jsonutil.js.map +1 -1
  127. package/lib/utils/logger/fileLogger.js +17 -7
  128. package/lib/utils/logger/fileLogger.js.map +1 -1
  129. package/lib/utils/logger.d.ts +3 -3
  130. package/lib/utils/logger.js +10 -6
  131. package/lib/utils/logger.js.map +1 -1
  132. package/lib/utils/logging/debugtimer.js.map +1 -1
  133. package/lib/utils/lwcparser/fileutils/FileDiffUtil.js +30 -22
  134. package/lib/utils/lwcparser/fileutils/FileDiffUtil.js.map +1 -1
  135. package/lib/utils/lwcparser/fileutils/FileProcessorFactory.js.map +1 -1
  136. package/lib/utils/lwcparser/fileutils/HtmlFileProcessor.js.map +1 -1
  137. package/lib/utils/lwcparser/fileutils/JavascriptFileProcessor.js.map +1 -1
  138. package/lib/utils/lwcparser/fileutils/XmlFileProcessor.js.map +1 -1
  139. package/lib/utils/lwcparser/htmlParser/HTMLParser.js +29 -10
  140. package/lib/utils/lwcparser/htmlParser/HTMLParser.js.map +1 -1
  141. package/lib/utils/lwcparser/jsParser/JavaScriptParser.js +29 -11
  142. package/lib/utils/lwcparser/jsParser/JavaScriptParser.js.map +1 -1
  143. package/lib/utils/lwcparser/xmlParser/XmlParser.js +19 -8
  144. package/lib/utils/lwcparser/xmlParser/XmlParser.js.map +1 -1
  145. package/lib/utils/net/index.d.ts +5 -0
  146. package/lib/utils/net/index.js +40 -2
  147. package/lib/utils/net/index.js.map +1 -1
  148. package/lib/utils/omniscriptPackageManager.d.ts +31 -0
  149. package/lib/utils/omniscriptPackageManager.js +215 -0
  150. package/lib/utils/omniscriptPackageManager.js.map +1 -0
  151. package/lib/utils/orgPreferences.d.ts +25 -0
  152. package/lib/utils/orgPreferences.js +124 -8
  153. package/lib/utils/orgPreferences.js.map +1 -1
  154. package/lib/utils/orgUtils/index.d.ts +12 -5
  155. package/lib/utils/orgUtils/index.js +52 -22
  156. package/lib/utils/orgUtils/index.js.map +1 -1
  157. package/lib/utils/projectPathUtil.d.ts +1 -1
  158. package/lib/utils/projectPathUtil.js +27 -10
  159. package/lib/utils/projectPathUtil.js.map +1 -1
  160. package/lib/utils/promptUtil.d.ts +11 -1
  161. package/lib/utils/promptUtil.js +92 -0
  162. package/lib/utils/promptUtil.js.map +1 -1
  163. package/lib/utils/query/index.d.ts +1 -0
  164. package/lib/utils/query/index.js +18 -1
  165. package/lib/utils/query/index.js.map +1 -1
  166. package/lib/utils/recordPrioritization.d.ts +44 -0
  167. package/lib/utils/recordPrioritization.js +69 -0
  168. package/lib/utils/recordPrioritization.js.map +1 -0
  169. package/lib/utils/reportGenerator/reportInterfaces.d.ts +12 -0
  170. package/lib/utils/reportGenerator/reportUtil.d.ts +6 -1
  171. package/lib/utils/reportGenerator/reportUtil.js +22 -7
  172. package/lib/utils/reportGenerator/reportUtil.js.map +1 -1
  173. package/lib/utils/resultsbuilder/ApexAssessmentReporter.d.ts +1 -0
  174. package/lib/utils/resultsbuilder/ApexAssessmentReporter.js +40 -17
  175. package/lib/utils/resultsbuilder/ApexAssessmentReporter.js.map +1 -1
  176. package/lib/utils/resultsbuilder/CustomLabelAssessmentReporter.d.ts +13 -0
  177. package/lib/utils/resultsbuilder/CustomLabelAssessmentReporter.js +179 -0
  178. package/lib/utils/resultsbuilder/CustomLabelAssessmentReporter.js.map +1 -0
  179. package/lib/utils/resultsbuilder/CustomLabelMigrationReporter.d.ts +27 -0
  180. package/lib/utils/resultsbuilder/CustomLabelMigrationReporter.js +262 -0
  181. package/lib/utils/resultsbuilder/CustomLabelMigrationReporter.js.map +1 -0
  182. package/lib/utils/resultsbuilder/DRAssessmentReporter.js +38 -70
  183. package/lib/utils/resultsbuilder/DRAssessmentReporter.js.map +1 -1
  184. package/lib/utils/resultsbuilder/ExperienceSiteAssessmentReporter.d.ts +14 -0
  185. package/lib/utils/resultsbuilder/ExperienceSiteAssessmentReporter.js +143 -0
  186. package/lib/utils/resultsbuilder/ExperienceSiteAssessmentReporter.js.map +1 -0
  187. package/lib/utils/resultsbuilder/FlexcardAssessmentReporter.js +46 -85
  188. package/lib/utils/resultsbuilder/FlexcardAssessmentReporter.js.map +1 -1
  189. package/lib/utils/resultsbuilder/FlexipageAssessmentReporter.d.ts +1 -0
  190. package/lib/utils/resultsbuilder/FlexipageAssessmentReporter.js +37 -19
  191. package/lib/utils/resultsbuilder/FlexipageAssessmentReporter.js.map +1 -1
  192. package/lib/utils/resultsbuilder/GlobalAutoNumberAssessmentReporter.js +22 -14
  193. package/lib/utils/resultsbuilder/GlobalAutoNumberAssessmentReporter.js.map +1 -1
  194. package/lib/utils/resultsbuilder/IPAssessmentReporter.js +38 -71
  195. package/lib/utils/resultsbuilder/IPAssessmentReporter.js.map +1 -1
  196. package/lib/utils/resultsbuilder/LWCAssessmentReporter.d.ts +14 -0
  197. package/lib/utils/resultsbuilder/LWCAssessmentReporter.js +143 -139
  198. package/lib/utils/resultsbuilder/LWCAssessmentReporter.js.map +1 -1
  199. package/lib/utils/resultsbuilder/OSAssessmentReporter.js +41 -88
  200. package/lib/utils/resultsbuilder/OSAssessmentReporter.js.map +1 -1
  201. package/lib/utils/resultsbuilder/SaveForLaterAssessmentReporter.d.ts +12 -0
  202. package/lib/utils/resultsbuilder/SaveForLaterAssessmentReporter.js +109 -0
  203. package/lib/utils/resultsbuilder/SaveForLaterAssessmentReporter.js.map +1 -0
  204. package/lib/utils/resultsbuilder/assessmentReporter.d.ts +16 -6
  205. package/lib/utils/resultsbuilder/assessmentReporter.js +96 -152
  206. package/lib/utils/resultsbuilder/assessmentReporter.js.map +1 -1
  207. package/lib/utils/resultsbuilder/helpers/AssessmentReportHelper.d.ts +104 -0
  208. package/lib/utils/resultsbuilder/helpers/AssessmentReportHelper.js +380 -0
  209. package/lib/utils/resultsbuilder/helpers/AssessmentReportHelper.js.map +1 -0
  210. package/lib/utils/resultsbuilder/index.d.ts +37 -1
  211. package/lib/utils/resultsbuilder/index.js +582 -151
  212. package/lib/utils/resultsbuilder/index.js.map +1 -1
  213. package/lib/utils/resultsbuilder/reportingHelper.d.ts +2 -7
  214. package/lib/utils/resultsbuilder/reportingHelper.js +0 -43
  215. package/lib/utils/resultsbuilder/reportingHelper.js.map +1 -1
  216. package/lib/utils/sfcli/project/sfProject.d.ts +29 -0
  217. package/lib/utils/sfcli/project/sfProject.js +220 -2
  218. package/lib/utils/sfcli/project/sfProject.js.map +1 -1
  219. package/lib/utils/shell/cli.js +20 -14
  220. package/lib/utils/shell/cli.js.map +1 -1
  221. package/lib/utils/storageUtil.d.ts +14 -1
  222. package/lib/utils/storageUtil.js +31 -1
  223. package/lib/utils/storageUtil.js.map +1 -1
  224. package/lib/utils/stringUtils.d.ts +24 -0
  225. package/lib/utils/stringUtils.js +76 -9
  226. package/lib/utils/stringUtils.js.map +1 -1
  227. package/lib/utils/templateParser/__tests__/test.js +1 -2
  228. package/lib/utils/templateParser/__tests__/test.js.map +1 -1
  229. package/lib/utils/templateParser/generate.d.ts +1 -1
  230. package/lib/utils/templateParser/generate.js.map +1 -1
  231. package/lib/utils/templateParser/model/elementNode.d.ts +2 -2
  232. package/lib/utils/templateParser/model/elementNode.js +11 -2
  233. package/lib/utils/templateParser/model/elementNode.js.map +1 -1
  234. package/lib/utils/templateParser/model/nodeTypes.js +1 -1
  235. package/lib/utils/templateParser/model/nodeTypes.js.map +1 -1
  236. package/lib/utils/templateParser/util.d.ts +2 -2
  237. package/lib/utils/templateParser/util.js.map +1 -1
  238. package/lib/utils/validatorService.d.ts +14 -0
  239. package/lib/utils/validatorService.js +136 -0
  240. package/lib/utils/validatorService.js.map +1 -0
  241. package/messages/assess.json +220 -103
  242. package/messages/clean.json +40 -0
  243. package/messages/info.json +2 -1
  244. package/messages/migrate.json +314 -102
  245. package/oclif.manifest.json +1 -1
  246. package/package.json +49 -13
  247. package/lib/commands/basecommand.d.ts +0 -8
  248. package/lib/commands/basecommand.js +0 -13
  249. package/lib/commands/basecommand.js.map +0 -1
  250. package/lib/utils/OmniGlobalAutoNumberPrefManager.d.ts +0 -40
  251. package/lib/utils/OmniGlobalAutoNumberPrefManager.js +0 -65
  252. package/lib/utils/OmniGlobalAutoNumberPrefManager.js.map +0 -1
@@ -8,22 +8,30 @@ const VlocityCard_1 = __importDefault(require("../mappings/VlocityCard"));
8
8
  const utils_1 = require("../utils");
9
9
  const net_1 = require("../utils/net");
10
10
  const base_1 = require("./base");
11
+ const CustomCssRegistry_1 = require("./CustomCssRegistry");
11
12
  const interfaces_1 = require("./interfaces");
12
13
  const logger_1 = require("../utils/logger");
13
14
  const base_2 = require("./base");
14
15
  const stringContants_1 = require("../utils/constants/stringContants");
15
16
  const storageUtil_1 = require("../utils/storageUtil");
17
+ const stringUtils_1 = require("../utils/stringUtils");
18
+ const dataModelService_1 = require("../utils/dataModelService");
19
+ const recordPrioritization_1 = require("../utils/recordPrioritization");
20
+ const ApexNamespaceRegistry_1 = require("./ApexNamespaceRegistry");
16
21
  class CardMigrationTool extends base_1.BaseMigrationTool {
17
22
  constructor(namespace, connection, logger, messages, ux, allVersions) {
18
23
  super(namespace, connection, logger, messages, ux);
24
+ this.apexNamespaceRegistry = ApexNamespaceRegistry_1.ApexNamespaceRegistry.getInstance();
25
+ this.IS_STANDARD_DATA_MODEL = (0, dataModelService_1.isStandardDataModel)();
19
26
  this.allVersions = allVersions;
27
+ CustomCssRegistry_1.CustomCssRegistry.getInstance().init(connection, namespace, messages);
20
28
  }
21
29
  getName() {
22
- return 'FlexCards';
30
+ return 'Flexcards';
23
31
  }
24
32
  getRecordName(record) {
25
33
  return this.allVersions
26
- ? `${record['Name']}_${record[this.namespacePrefix + CardMigrationTool.VERSION_PROP]}`
34
+ ? `${record['Name']}_${record[this.getFieldKey(CardMigrationTool.VERSION_PROP)]}`
27
35
  : record['Name'];
28
36
  }
29
37
  getMappings() {
@@ -36,6 +44,10 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
36
44
  }
37
45
  // Perform Delete of OmniUiCard Records to start migration from scratch
38
46
  async truncate() {
47
+ if (this.IS_STANDARD_DATA_MODEL) {
48
+ logger_1.Logger.logVerbose(this.messages.getMessage('skippingTruncation'));
49
+ return;
50
+ }
39
51
  const objectName = CardMigrationTool.OMNIUICARD_NAME;
40
52
  utils_1.DebugTimer.getInstance().lap('Truncating ' + objectName);
41
53
  const ids = await utils_1.QueryTools.queryIds(this.connection, objectName);
@@ -57,19 +69,53 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
57
69
  }
58
70
  // Perform Records Migration from VlocityCard__c to OmniUiCard
59
71
  async migrate() {
60
- // Get All the Active VlocityCard__c records
61
- const cards = await this.getAllActiveCards();
62
- logger_1.Logger.log(this.messages.getMessage('foundFlexCardsToMigrate', [cards.length]));
63
- const progressBar = (0, base_2.createProgressBar)('Migrating', 'Flexcard');
72
+ const allCards = await this.getAllCards();
73
+ if ((0, dataModelService_1.isStandardDataModelWithMetadataAPIEnabled)()) {
74
+ return this.handleMigrationForStdDataModelOrgsWithMetadataAPIEnabled(allCards);
75
+ }
76
+ logger_1.Logger.log(this.messages.getMessage('foundFlexCardsToMigrate', [allCards.length]));
77
+ // Filter out FlexCards with Angular OmniScript dependencies
78
+ const cards = [];
79
+ const skippedCards = new Map();
80
+ for (const card of allCards) {
81
+ if (this.hasAngularOmniScriptDependencies(card)) {
82
+ // Skip FlexCard with Angular dependencies
83
+ logger_1.Logger.logVerbose(`${this.messages.getMessage('skipFlexcardAngularOmniScriptDependencyWarning', [card['Name']])}`);
84
+ skippedCards.set(card['Id'], {
85
+ referenceId: card['Id'],
86
+ id: '',
87
+ success: false,
88
+ hasErrors: false,
89
+ errors: [],
90
+ warnings: [this.messages.getMessage('flexCardWithAngularOmniScriptWarning')],
91
+ newName: '',
92
+ skipped: true,
93
+ });
94
+ }
95
+ else {
96
+ cards.push(card);
97
+ }
98
+ }
99
+ if (this.IS_STANDARD_DATA_MODEL) {
100
+ logger_1.Logger.log(`${this.messages.getMessage('flexCardMigrationProcessingMessage', [cards.length])}`);
101
+ }
102
+ else {
103
+ logger_1.Logger.log(`${this.messages.getMessage('flexCardMigrationProcessingMessage', [cards.length])} ${this.messages.getMessage('skippingAsAngularDependencies', [skippedCards.size])}`);
104
+ }
105
+ const progressBar = (0, base_2.createProgressBar)('Migrating', 'Flexcards');
64
106
  // Save the Vlocity Cards in OmniUiCard
65
107
  const cardUploadResponse = await this.uploadAllCards(cards, progressBar);
108
+ // Add skipped cards to the response
109
+ for (const [cardId, skippedResult] of skippedCards.entries()) {
110
+ cardUploadResponse.set(cardId, skippedResult);
111
+ }
66
112
  const records = new Map();
67
- for (let i = 0; i < cards.length; i++) {
68
- records.set(cards[i]['Id'], cards[i]);
113
+ for (let i = 0; i < allCards.length; i++) {
114
+ records.set(allCards[i]['Id'], allCards[i]);
69
115
  }
70
116
  return [
71
117
  {
72
- name: 'FlexCards',
118
+ name: 'Flexcards',
73
119
  records: records,
74
120
  results: cardUploadResponse,
75
121
  },
@@ -77,10 +123,14 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
77
123
  }
78
124
  async assess() {
79
125
  try {
126
+ const flexCards = await this.getAllCards();
127
+ if ((0, dataModelService_1.isStandardDataModelWithMetadataAPIEnabled)()) {
128
+ return this.handleAssessmentForStdDataModelOrgsWithMetadataAPIEnabled(flexCards);
129
+ }
80
130
  logger_1.Logger.log(this.messages.getMessage('startingFlexCardAssessment'));
81
- const flexCards = await this.getAllActiveCards();
82
131
  logger_1.Logger.log(this.messages.getMessage('foundFlexCardsToAssess', [flexCards.length]));
83
- const flexCardsAssessmentInfos = this.processCardComponents(flexCards);
132
+ const flexCardsAssessmentInfos = await this.processCardComponents(flexCards);
133
+ this.prepareAssessmentStorageForFlexcards(flexCardsAssessmentInfos);
84
134
  return flexCardsAssessmentInfos;
85
135
  }
86
136
  catch (err) {
@@ -93,13 +143,14 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
93
143
  async processCardComponents(flexCards) {
94
144
  const flexCardAssessmentInfos = [];
95
145
  let progressCounter = 0;
96
- const progressBar = (0, base_2.createProgressBar)('Assessing', 'Flexcard');
146
+ const progressBar = (0, base_2.createProgressBar)('Assessing', 'Flexcards');
97
147
  progressBar.start(flexCards.length, progressCounter);
98
148
  const uniqueNames = new Set();
149
+ const dupFlexCardNames = new Map();
99
150
  // Now process each OmniScript and its elements
100
151
  for (const flexCard of flexCards) {
101
152
  try {
102
- const flexCardAssessmentInfo = await this.processFlexCard(flexCard, uniqueNames);
153
+ const flexCardAssessmentInfo = await this.processFlexCard(flexCard, uniqueNames, dupFlexCardNames);
103
154
  flexCardAssessmentInfos.push(flexCardAssessmentInfo);
104
155
  }
105
156
  catch (e) {
@@ -113,6 +164,7 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
113
164
  dependenciesOS: [],
114
165
  dependenciesLWC: [],
115
166
  dependenciesApexRemoteAction: [],
167
+ dependenciesVlocityAction: [],
116
168
  infos: [],
117
169
  warnings: [],
118
170
  errors: [this.messages.getMessage('unexpectedError')],
@@ -126,10 +178,10 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
126
178
  progressBar.stop();
127
179
  return flexCardAssessmentInfos;
128
180
  }
129
- async processFlexCard(flexCard, uniqueNames) {
181
+ async processFlexCard(flexCard, uniqueNames, dupFlexCardNames) {
130
182
  const flexCardName = flexCard['Name'];
131
183
  logger_1.Logger.info(this.messages.getMessage('processingFlexCard', [flexCardName]));
132
- const version = flexCard[this.namespacePrefix + CardMigrationTool.VERSION_PROP];
184
+ const version = flexCard[this.getFieldKey(CardMigrationTool.VERSION_PROP)];
133
185
  const flexCardAssessmentInfo = {
134
186
  name: this.allVersions ? `${flexCardName}_${version}` : flexCardName,
135
187
  oldName: this.allVersions ? `${flexCardName}_${version}` : flexCardName,
@@ -140,101 +192,196 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
140
192
  dependenciesFC: [],
141
193
  dependenciesLWC: [],
142
194
  dependenciesApexRemoteAction: [],
195
+ dependenciesVlocityAction: [],
143
196
  infos: [],
144
197
  warnings: [],
145
198
  errors: [],
146
- migrationStatus: '',
199
+ migrationStatus: 'Ready for migration',
147
200
  };
148
201
  // Check for name changes due to API naming requirements
149
202
  const originalName = flexCardName;
150
203
  const cleanedName = this.cleanName(originalName);
151
- let assessmentStatus = 'Can be Automated';
204
+ let assessmentStatus = 'Ready for migration';
152
205
  flexCardAssessmentInfo.name = this.allVersions ? `${cleanedName}_${version}` : cleanedName;
153
206
  if (cleanedName !== originalName) {
154
207
  flexCardAssessmentInfo.warnings.push(this.messages.getMessage('cardNameChangeMessage', [originalName, cleanedName]));
155
- assessmentStatus = 'Has Warnings';
208
+ assessmentStatus = (0, stringUtils_1.getUpdatedAssessmentStatus)(assessmentStatus, 'Warnings');
209
+ }
210
+ // Check for duplicate names (include version when allVersions is true)
211
+ const uniqueCleanedName = this.allVersions ? `${cleanedName}_${version}` : cleanedName;
212
+ // Check for exact duplicate (same name + same version)
213
+ if (uniqueNames.has(uniqueCleanedName)) {
214
+ flexCardAssessmentInfo.warnings.push(this.messages.getMessage('duplicateCardNameMessage', [uniqueCleanedName]));
215
+ assessmentStatus = (0, stringUtils_1.getUpdatedAssessmentStatus)(assessmentStatus, 'Needs manual intervention');
216
+ }
217
+ // Check for naming conflict: different original names cleaning to same name
218
+ else if (this.allVersions && dupFlexCardNames.has(cleanedName)) {
219
+ const existingOriginalName = dupFlexCardNames.get(cleanedName);
220
+ // Only flag if the original names are different (indicates a naming conflict)
221
+ if (existingOriginalName !== originalName) {
222
+ flexCardAssessmentInfo.warnings.push(this.messages.getMessage('lowerVersionDuplicateCardNameMessage', [uniqueCleanedName]));
223
+ assessmentStatus = (0, stringUtils_1.getUpdatedAssessmentStatus)(assessmentStatus, 'Needs manual intervention');
224
+ }
156
225
  }
157
- // Check for duplicate names
158
- if (uniqueNames.has(cleanedName)) {
159
- flexCardAssessmentInfo.warnings.push(this.messages.getMessage('duplicateCardNameMessage', [cleanedName]));
160
- assessmentStatus = 'Need Manual Intervention';
226
+ // Add to tracking structures
227
+ uniqueNames.add(uniqueCleanedName);
228
+ if (this.allVersions && !dupFlexCardNames.has(cleanedName)) {
229
+ dupFlexCardNames.set(cleanedName, originalName);
161
230
  }
162
- uniqueNames.add(cleanedName);
163
- this.addToAssessmentStorage(originalName, cleanedName);
164
231
  // Check for author name changes
165
- const originalAuthor = flexCard[this.namespacePrefix + 'Author__c'];
232
+ const originalAuthor = flexCard[this.getFieldKey('Author__c')];
166
233
  if (originalAuthor) {
167
234
  const cleanedAuthor = this.cleanName(originalAuthor);
168
235
  if (cleanedAuthor !== originalAuthor) {
169
236
  flexCardAssessmentInfo.warnings.push(this.messages.getMessage('authordNameChangeMessage', [originalAuthor, cleanedAuthor]));
170
- assessmentStatus = 'Has Warnings';
237
+ assessmentStatus = (0, stringUtils_1.getUpdatedAssessmentStatus)(assessmentStatus, 'Warnings');
171
238
  }
172
239
  }
240
+ flexCardAssessmentInfo.nameMapping = {
241
+ oldName: flexCardName,
242
+ newName: cleanedName,
243
+ };
173
244
  flexCardAssessmentInfo.migrationStatus = assessmentStatus;
174
245
  this.updateDependencies(flexCard, flexCardAssessmentInfo);
246
+ // Scan custom CSS (both StaticResource-backed and inline) for managed-package
247
+ // namespace references. The helper updates `migrationStatus` itself via
248
+ // `getUpdatedAssessmentStatus`, so it never downgrades a stricter status.
249
+ await this.collectStylesheetNamespaceDependencies(flexCard, flexCardAssessmentInfo);
250
+ if (flexCardAssessmentInfo.errors.length > 0) {
251
+ flexCardAssessmentInfo.migrationStatus = 'Needs manual intervention';
252
+ }
253
+ else if (flexCardAssessmentInfo.warnings.length > 0 &&
254
+ flexCardAssessmentInfo.migrationStatus === 'Ready for migration') {
255
+ flexCardAssessmentInfo.migrationStatus = 'Warnings';
256
+ }
257
+ // Deduplicate all dependency arrays to ensure no duplicates
258
+ flexCardAssessmentInfo.dependenciesIP = [...new Set(flexCardAssessmentInfo.dependenciesIP)];
259
+ flexCardAssessmentInfo.dependenciesDR = [...new Set(flexCardAssessmentInfo.dependenciesDR)];
260
+ flexCardAssessmentInfo.dependenciesFC = [...new Set(flexCardAssessmentInfo.dependenciesFC)];
261
+ flexCardAssessmentInfo.dependenciesOS = [...new Set(flexCardAssessmentInfo.dependenciesOS)];
262
+ flexCardAssessmentInfo.dependenciesLWC = [...new Set(flexCardAssessmentInfo.dependenciesLWC)];
263
+ flexCardAssessmentInfo.dependenciesApexRemoteAction = [
264
+ ...new Set(flexCardAssessmentInfo.dependenciesApexRemoteAction),
265
+ ];
266
+ flexCardAssessmentInfo.dependenciesVlocityAction = [...new Set(flexCardAssessmentInfo.dependenciesVlocityAction)];
175
267
  return flexCardAssessmentInfo;
176
268
  }
269
+ /**
270
+ * Scan a FlexCard for two distinct kinds of namespace-bound custom CSS:
271
+ *
272
+ * 1. **StaticResource-backed stylesheet** — `Definition__c.customStyleSheet`
273
+ * stores the *Name* of a Static Resource. We look it up, fetch its body,
274
+ * and substring-check for the org's managed-package namespace. Same flow
275
+ * and same warning message as the OmniScript implementation; resource
276
+ * scans are cached by name in {@link CustomCssRegistry}, so a stylesheet
277
+ * shared between OmniScripts and FlexCards is only fetched once per run.
278
+ *
279
+ * 2. **Inline CSS** — `Styles__c.customStyles` stores raw CSS text. We
280
+ * substring-check the namespace directly against that string. No
281
+ * SOQL/REST traffic and no caching (the CSS is per-FlexCard and not
282
+ * shared across records).
283
+ *
284
+ * Both checks emit a warning into `flexCardAssessmentInfo.warnings` and bump
285
+ * `migrationStatus` to 'Needs manual intervention' (via
286
+ * `getUpdatedAssessmentStatus`, which never downgrades a stricter status).
287
+ */
288
+ async collectStylesheetNamespaceDependencies(flexCard, flexCardAssessmentInfo) {
289
+ const registry = CustomCssRegistry_1.CustomCssRegistry.getInstance();
290
+ if (!registry.isEnabled()) {
291
+ return;
292
+ }
293
+ // ---- 1. Definition__c.customStyleSheet (StaticResource name) ----
294
+ const definitionRaw = flexCard[this.getFieldKey('Definition__c')];
295
+ if (definitionRaw) {
296
+ let definition;
297
+ try {
298
+ definition = JSON.parse(definitionRaw);
299
+ }
300
+ catch (ex) {
301
+ logger_1.Logger.error(`Failed to parse Definition__c for stylesheet scan: ${flexCard['Name']}`);
302
+ definition = null;
303
+ }
304
+ const resourceName = ((definition === null || definition === void 0 ? void 0 : definition.customStyleSheet) || '').toString().trim();
305
+ if (resourceName) {
306
+ const verdict = await registry.scanResource(resourceName);
307
+ if (verdict === 'namespaceFound') {
308
+ const message = registry.buildFlexCardNamespaceWarning(resourceName);
309
+ if (message) {
310
+ flexCardAssessmentInfo.warnings.push(message);
311
+ flexCardAssessmentInfo.migrationStatus = (0, stringUtils_1.getUpdatedAssessmentStatus)(flexCardAssessmentInfo.migrationStatus, 'Needs manual intervention');
312
+ }
313
+ }
314
+ }
315
+ }
316
+ // ---- 2. Styles__c.customStyles (raw inline CSS) ----
317
+ const stylesRaw = flexCard[this.getFieldKey('Styles__c')];
318
+ if (stylesRaw) {
319
+ let styles;
320
+ try {
321
+ styles = JSON.parse(stylesRaw);
322
+ }
323
+ catch (ex) {
324
+ logger_1.Logger.error(`Failed to parse Styles__c for stylesheet scan: ${flexCard['Name']}`);
325
+ styles = null;
326
+ }
327
+ const inlineCss = styles === null || styles === void 0 ? void 0 : styles.customStyles;
328
+ if (registry.containsNamespaceInText(inlineCss)) {
329
+ const message = registry.buildInlineCssNamespaceWarning();
330
+ if (message) {
331
+ flexCardAssessmentInfo.warnings.push(message);
332
+ flexCardAssessmentInfo.migrationStatus = (0, stringUtils_1.getUpdatedAssessmentStatus)(flexCardAssessmentInfo.migrationStatus, 'Needs manual intervention');
333
+ }
334
+ }
335
+ }
336
+ }
177
337
  updateDependencies(flexCard, flexCardAssessmentInfo) {
178
338
  var _a, _b, _c, _d;
179
- let dataSource = JSON.parse(flexCard[this.namespacePrefix + 'Datasource__c'] || '{}');
180
- // Handle both camelCase and lowercase variants
181
- if (dataSource === null || dataSource === void 0 ? void 0 : dataSource.dataSource) {
182
- dataSource = dataSource.dataSource;
183
- }
184
- else if (dataSource === null || dataSource === void 0 ? void 0 : dataSource.datasource) {
185
- dataSource = dataSource.datasource;
186
- }
187
- // Check if it's a DataRaptor source
188
- if (dataSource.type === stringContants_1.Constants.DataRaptorComponentName) {
189
- const originalBundle = (_a = dataSource.value) === null || _a === void 0 ? void 0 : _a.bundle;
190
- if (originalBundle) {
191
- const cleanedBundle = this.cleanName(originalBundle);
192
- flexCardAssessmentInfo.dependenciesDR.push(cleanedBundle);
193
- // Add warning if DataRaptor name will change
194
- if (originalBundle !== cleanedBundle) {
195
- flexCardAssessmentInfo.warnings.push(this.messages.getMessage('dataRaptorNameChangeMessage', [originalBundle, cleanedBundle]));
196
- flexCardAssessmentInfo.migrationStatus = 'Has Warnings';
197
- }
198
- }
199
- }
200
- else if (dataSource.type === stringContants_1.Constants.IntegrationProcedurePluralName) {
201
- const originalIpMethod = (_b = dataSource.value) === null || _b === void 0 ? void 0 : _b.ipMethod;
202
- if (originalIpMethod) {
203
- const parts = originalIpMethod.split('_');
204
- const cleanedParts = parts.map((p) => this.cleanName(p, true));
205
- const cleanedIpMethod = cleanedParts.join('_');
206
- flexCardAssessmentInfo.dependenciesIP.push(cleanedIpMethod);
207
- // Add warning if IP name will change
208
- if (originalIpMethod !== cleanedIpMethod) {
209
- flexCardAssessmentInfo.warnings.push(this.messages.getMessage('integrationProcedureNameChangeMessage', [originalIpMethod, cleanedIpMethod]));
210
- flexCardAssessmentInfo.migrationStatus = 'Has Warnings';
211
- }
212
- // Add warning for IP references with more than 2 parts (which potentially need manual updates)
213
- if (parts.length > 2) {
214
- flexCardAssessmentInfo.warnings.push(this.messages.getMessage('integrationProcedureManualUpdateMessage', [originalIpMethod]));
215
- flexCardAssessmentInfo.migrationStatus = 'Need Manual Intervention';
339
+ const dataSourceConfig = JSON.parse(flexCard[this.getFieldKey('Datasource__c')] || '{}');
340
+ // Collect all data sources - any nested object with a 'type' property is a data source
341
+ // This handles: dataSource, datasource, event-0_0, event-1_0, etc.
342
+ const dataSources = Object.values(dataSourceConfig).filter((value) => value && typeof value === 'object' && value.type);
343
+ for (const ds of dataSources) {
344
+ // Check if it's a DataRaptor source
345
+ if (ds.type === stringContants_1.Constants.DataRaptorComponentName) {
346
+ const originalBundle = (_a = ds.value) === null || _a === void 0 ? void 0 : _a.bundle;
347
+ if (originalBundle) {
348
+ this.addDataRaptorDependency(originalBundle, flexCardAssessmentInfo);
216
349
  }
217
350
  }
218
- }
219
- else if (dataSource.type === stringContants_1.Constants.ApexRemoteComponentName) {
220
- const remoteClass = (_c = dataSource.value) === null || _c === void 0 ? void 0 : _c.remoteClass;
221
- const remoteMethod = (_d = dataSource.value) === null || _d === void 0 ? void 0 : _d.remoteMethod;
222
- logger_1.Logger.info(`Remote Action name: ${remoteClass}.${remoteMethod}`);
223
- // Avoid duplicates
224
- if (!flexCardAssessmentInfo.dependenciesApexRemoteAction.includes(`${remoteClass}.${remoteMethod}`)) {
225
- flexCardAssessmentInfo.dependenciesApexRemoteAction.push(`${remoteClass}.${remoteMethod}`);
351
+ else if (ds.type === stringContants_1.Constants.IntegrationProcedurePluralName) {
352
+ const originalIpMethod = (_b = ds.value) === null || _b === void 0 ? void 0 : _b.ipMethod;
353
+ if (originalIpMethod) {
354
+ this.addIntegrationProcedureDependency(originalIpMethod, flexCardAssessmentInfo);
355
+ }
356
+ }
357
+ else if (ds.type === stringContants_1.Constants.ApexRemoteComponentName) {
358
+ const remoteClass = (_c = ds.value) === null || _c === void 0 ? void 0 : _c.remoteClass;
359
+ const remoteMethod = (_d = ds.value) === null || _d === void 0 ? void 0 : _d.remoteMethod;
360
+ if (remoteClass && remoteMethod) {
361
+ const status = this.apexNamespaceRegistry.resolveStatus(remoteClass);
362
+ const qualifiedClass = this.apexNamespaceRegistry.getQualifiedClassName(remoteClass);
363
+ const qualifiedEntry = `${qualifiedClass}.${remoteMethod}`;
364
+ if (!flexCardAssessmentInfo.dependenciesApexRemoteAction.includes(qualifiedEntry)) {
365
+ flexCardAssessmentInfo.dependenciesApexRemoteAction.push(qualifiedEntry);
366
+ }
367
+ if (status === ApexNamespaceRegistry_1.ApexResolveStatus.NAMESPACED) {
368
+ flexCardAssessmentInfo.warnings.push(this.messages.getMessage('apexRemoteDatasourceNamespaceWarning', [remoteClass, qualifiedClass]));
369
+ }
370
+ else if (status === ApexNamespaceRegistry_1.ApexResolveStatus.NOT_FOUND) {
371
+ flexCardAssessmentInfo.errors.push(this.messages.getMessage('apexClassNotFound', [remoteClass, flexCardAssessmentInfo.name]));
372
+ }
373
+ }
226
374
  }
227
375
  }
228
- // Check for OmniScript dependencies in the card's definition
376
+ // Check for Omniscript dependencies in the card's definition
229
377
  try {
230
- const definition = JSON.parse(flexCard[this.namespacePrefix + 'Definition__c'] || '{}');
378
+ const definition = JSON.parse(flexCard[this.getFieldKey('Definition__c')] || '{}');
231
379
  if (definition && definition.states) {
232
380
  for (const state of definition.states) {
233
381
  if (state.omniscripts && Array.isArray(state.omniscripts)) {
234
382
  for (const os of state.omniscripts) {
235
383
  if (os.type && os.subtype) {
236
- const osRef = `${os.type}_${os.subtype}_${os.language || 'English'}`;
237
- flexCardAssessmentInfo.dependenciesOS.push(osRef);
384
+ this.addOmniScriptDependencyFromParts(os.type, os.subtype, os.language, flexCardAssessmentInfo);
238
385
  }
239
386
  }
240
387
  }
@@ -250,16 +397,281 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
250
397
  }
251
398
  }
252
399
  let childCards = this.readChildCardsFromDefinition(flexCard);
253
- flexCardAssessmentInfo.dependenciesFC.push(...childCards);
400
+ // Add warnings for child card name changes
401
+ for (const childCardName of childCards) {
402
+ this.addFlexCardDependency(childCardName, flexCardAssessmentInfo);
403
+ }
404
+ // Check for dependencies in events[] array
405
+ if (definition.events && Array.isArray(definition.events)) {
406
+ this.checkEventsForDependencies(definition.events, flexCardAssessmentInfo);
407
+ }
254
408
  }
255
409
  catch (err) {
256
410
  // Log the error but continue processing
257
411
  logger_1.Logger.error(`Error parsing definition for card ${flexCard.Name}: ${err.message}`);
258
412
  }
259
413
  }
414
+ /**
415
+ * Check events array for dependencies (Assessment)
416
+ * Handles: events[].actionList[].stateAction references
417
+ */
418
+ checkEventsForDependencies(events, flexCardAssessmentInfo) {
419
+ for (const event of events) {
420
+ if (!event.actionList || !Array.isArray(event.actionList)) {
421
+ continue;
422
+ }
423
+ for (const action of event.actionList) {
424
+ if (!action.stateAction) {
425
+ continue;
426
+ }
427
+ const stateAction = action.stateAction;
428
+ // Detect Vlocity Action (not supported in standard runtime FlexCards)
429
+ if (stateAction.type === stringContants_1.Constants.VlocityAction) {
430
+ this.addVlocityActionDependency(stateAction, flexCardAssessmentInfo);
431
+ }
432
+ // 1-2. Handle message.value.bundle (DataRaptor) and message.value.ipMethod (Integration Procedure)
433
+ this.processStateActionMessageForDependencies(stateAction, flexCardAssessmentInfo);
434
+ // 3. Handle cardName (FlexCard - Flyout childCard)
435
+ if (stateAction.cardName) {
436
+ this.addFlexCardDependency(stateAction.cardName, flexCardAssessmentInfo);
437
+ }
438
+ // 4. Handle flyoutLwc - FlexCard child cards
439
+ if (this.hasFlexCardFlyoutDependency(stateAction)) {
440
+ this.addFlexCardDependency(stateAction.flyoutLwc, flexCardAssessmentInfo);
441
+ }
442
+ // Handle flyoutLwc - CustomLwc with potential "cf" prefix for FlexCard reference
443
+ else if (this.hasCustomLwcFlyoutDependency(stateAction)) {
444
+ this.addCfPrefixedFlexCardDependency(stateAction.flyoutLwc, flexCardAssessmentInfo);
445
+ }
446
+ // 5. Handle osName
447
+ else if (this.hasOmniscriptFlyoutDependency(stateAction)) {
448
+ this.addOmniScriptDependency(stateAction.osName, flexCardAssessmentInfo);
449
+ }
450
+ // 6. Handle omniType.Name (OmniScript)
451
+ if (stateAction.omniType && stateAction.omniType.Name) {
452
+ this.addOmniScriptDependency(stateAction.omniType.Name, flexCardAssessmentInfo);
453
+ }
454
+ }
455
+ }
456
+ }
457
+ /**
458
+ * Shared helper to check if a "cf" prefixed LWC name references a FlexCard and add dependency (assessment phase)
459
+ * @param cfPrefixedLwcName LWC name with "cf" prefix (e.g., "cfMyFlexCard")
460
+ * @param flexCardAssessmentInfo Assessment info to add dependencies and warnings
461
+ */
462
+ addCfPrefixedFlexCardDependency(cfPrefixedLwcName, flexCardAssessmentInfo) {
463
+ if (cfPrefixedLwcName.startsWith('cf')) {
464
+ // Remove "cf" prefix to get the original FlexCard name
465
+ const originalFlexCardName = cfPrefixedLwcName.substring(2);
466
+ // Check if the FlexCard name will change and add warning
467
+ const cleanedFlexCardName = this.cleanName(originalFlexCardName);
468
+ this.addFlexCardDependency(originalFlexCardName, flexCardAssessmentInfo);
469
+ if (originalFlexCardName !== cleanedFlexCardName) {
470
+ flexCardAssessmentInfo.warnings.push(this.messages.getMessage('cardLWCNameChangeMessage', [originalFlexCardName, cleanedFlexCardName]));
471
+ flexCardAssessmentInfo.migrationStatus = (0, stringUtils_1.getUpdatedAssessmentStatus)(flexCardAssessmentInfo.migrationStatus, 'Warnings');
472
+ }
473
+ }
474
+ }
475
+ /**
476
+ * Shared helper to update a "cf" prefixed LWC name with registry (migration phase)
477
+ * @param cfPrefixedLwcName LWC name with "cf" prefix (e.g., "cfMyFlexCard")
478
+ * @returns Updated LWC name with "cf" prefix
479
+ */
480
+ updateCfPrefixedFlexCardName(cfPrefixedLwcName) {
481
+ if (cfPrefixedLwcName.startsWith('cf')) {
482
+ // Remove "cf" prefix to get the original FlexCard name
483
+ const originalFlexCardName = cfPrefixedLwcName.substring(2);
484
+ // Look up the cleaned name from registry
485
+ let cleanedFlexCardName;
486
+ if (this.nameRegistry.hasFlexCardMapping(originalFlexCardName)) {
487
+ cleanedFlexCardName = this.nameRegistry.getFlexCardCleanedName(originalFlexCardName);
488
+ }
489
+ else {
490
+ logger_1.Logger.logVerbose(`\n${this.messages.getMessage('componentMappingNotFound', ['Flexcard', originalFlexCardName])}`);
491
+ cleanedFlexCardName = this.cleanName(originalFlexCardName);
492
+ }
493
+ return `cf${cleanedFlexCardName}`;
494
+ }
495
+ return cfPrefixedLwcName;
496
+ }
497
+ /**
498
+ * Shared helper to check Custom LWC component for FlexCard dependencies (assessment phase)
499
+ * Handles customlwcname with "cf" prefix indicating FlexCard reference
500
+ */
501
+ checkCustomLwcForDependencies(component, flexCardAssessmentInfo) {
502
+ if (component.element === stringContants_1.Constants.CustomLwc && component.property) {
503
+ if (component.property.customlwcname) {
504
+ const customLwcName = component.property.customlwcname;
505
+ logger_1.Logger.info(`Custom LWC name: ${customLwcName}`);
506
+ // Check if this is a FlexCard reference (starts with "cf" prefix)
507
+ this.addCfPrefixedFlexCardDependency(customLwcName, flexCardAssessmentInfo);
508
+ // Add to LWC dependencies for tracking (avoid duplicates)
509
+ if (!flexCardAssessmentInfo.dependenciesLWC.includes(customLwcName)) {
510
+ flexCardAssessmentInfo.dependenciesLWC.push(customLwcName);
511
+ }
512
+ }
513
+ // "action" is a reserved keyword in the core runtime; flag any Custom LWC
514
+ // that defines it as a property so the user removes/renames it pre-migration.
515
+ if (Object.prototype.hasOwnProperty.call(component.property, 'action')) {
516
+ const lwcLabel = component.property.customlwcname || component.elementLabel || stringContants_1.Constants.CustomLwc;
517
+ const reservedActionMessage = this.messages.getMessage('customLwcReservedActionKey', [lwcLabel]);
518
+ flexCardAssessmentInfo.errors.push(reservedActionMessage);
519
+ flexCardAssessmentInfo.warnings.push(reservedActionMessage);
520
+ flexCardAssessmentInfo.migrationStatus = 'Needs manual intervention';
521
+ }
522
+ }
523
+ }
524
+ /**
525
+ * Shared helper to update Custom LWC component with registry (migration phase)
526
+ * Handles customlwcname with "cf" prefix indicating FlexCard reference
527
+ */
528
+ updateCustomLwcWithRegistry(component) {
529
+ if (component.element === stringContants_1.Constants.CustomLwc && component.property) {
530
+ if (component.property.customlwcname) {
531
+ const customLwcName = component.property.customlwcname;
532
+ // Check if this is a FlexCard reference (starts with "cf" prefix) and update it
533
+ if (customLwcName === null || customLwcName === void 0 ? void 0 : customLwcName.startsWith('cf')) {
534
+ const updatedLwcName = this.updateCfPrefixedFlexCardName(customLwcName);
535
+ component.property.customlwcname = updatedLwcName;
536
+ if (customLwcName !== updatedLwcName) {
537
+ const cleanedFlexCardName = updatedLwcName.substring(2);
538
+ logger_1.Logger.logVerbose(this.messages.getMessage('customLWCFlexCardReferenceUpdated', [customLwcName, cleanedFlexCardName]));
539
+ }
540
+ }
541
+ // Note: Other custom LWC names (not starting with "cf") typically don't need cleaning
542
+ }
543
+ }
544
+ }
545
+ /**
546
+ * Shared helper to update flyoutLwc value with registry (migration phase)
547
+ * Handles FlexCard child cards references
548
+ */
549
+ updateFlyoutLwcValue(stateAction) {
550
+ if (stateAction.flyoutLwc) {
551
+ if (stateAction.flyoutType === stringContants_1.Constants.ChildCard) {
552
+ // flyoutLwc is a direct FlexCard name reference
553
+ const lwcName = stateAction.flyoutLwc;
554
+ if (this.nameRegistry.hasFlexCardMapping(lwcName)) {
555
+ stateAction.flyoutLwc = this.nameRegistry.getFlexCardCleanedName(lwcName);
556
+ }
557
+ else {
558
+ logger_1.Logger.logVerbose(`\n${this.messages.getMessage('componentMappingNotFound', ['Flexcard', lwcName])}`);
559
+ stateAction.flyoutLwc = this.cleanName(lwcName);
560
+ }
561
+ }
562
+ else if (stateAction.flyoutType === stringContants_1.Constants.CustomLwc) {
563
+ // flyoutType is customLwc - update if it's a FlexCard reference with "cf" prefix
564
+ stateAction.flyoutLwc = this.updateCfPrefixedFlexCardName(stateAction.flyoutLwc);
565
+ // Note: Non-"cf" prefixed names are returned unchanged by the helper
566
+ }
567
+ }
568
+ }
569
+ /**
570
+ * Shared helper to process stateAction.message JSON for dependencies
571
+ * Handles DataRaptor bundle and Integration Procedure ipMethod references
572
+ */
573
+ processStateActionMessageForDependencies(stateAction, flexCardAssessmentInfo) {
574
+ // Only parse message for DataAction or cardAction types
575
+ if (stateAction.message &&
576
+ typeof stateAction.message === 'string' &&
577
+ stateAction.message.trim().length > 0 &&
578
+ (stateAction.type === stringContants_1.Constants.DataAction || stateAction.type === stringContants_1.Constants.CardAction)) {
579
+ try {
580
+ const messageObj = JSON.parse(stateAction.message);
581
+ if (messageObj.value) {
582
+ // DataRaptor bundle
583
+ if (messageObj.value.bundle) {
584
+ this.addDataRaptorDependency(messageObj.value.bundle, flexCardAssessmentInfo);
585
+ }
586
+ // Integration Procedure ipMethod
587
+ if (messageObj.value.ipMethod) {
588
+ this.addIntegrationProcedureDependency(messageObj.value.ipMethod, flexCardAssessmentInfo);
589
+ }
590
+ }
591
+ }
592
+ catch (e) {
593
+ // message is not valid JSON, skip
594
+ logger_1.Logger.error(`Failed to parse stateAction.message as JSON: ${e.message}`);
595
+ }
596
+ }
597
+ }
598
+ /**
599
+ * Shared helper to process stateAction.message JSON with registry updates
600
+ * Handles DataRaptor bundle and Integration Procedure ipMethod references
601
+ */
602
+ processStateActionMessageWithRegistry(stateAction, invalidIpNames) {
603
+ // Only parse message for DataAction or cardAction types
604
+ if (stateAction.message &&
605
+ typeof stateAction.message === 'string' &&
606
+ stateAction.message.trim().length > 0 &&
607
+ (stateAction.type === stringContants_1.Constants.DataAction || stateAction.type === stringContants_1.Constants.CardAction)) {
608
+ try {
609
+ const messageObj = JSON.parse(stateAction.message);
610
+ let messageUpdated = false;
611
+ if (messageObj.value) {
612
+ // DataRaptor bundle
613
+ if (messageObj.value.bundle) {
614
+ const originalBundle = messageObj.value.bundle;
615
+ if (this.nameRegistry.hasDataMapperMapping(originalBundle)) {
616
+ messageObj.value.bundle = this.nameRegistry.getDataMapperCleanedName(originalBundle);
617
+ }
618
+ else {
619
+ logger_1.Logger.logVerbose(`\n${this.messages.getMessage('componentMappingNotFound', ['DataMapper', originalBundle])}`);
620
+ messageObj.value.bundle = this.cleanName(originalBundle);
621
+ }
622
+ messageUpdated = true;
623
+ }
624
+ // Integration Procedure ipMethod
625
+ if (messageObj.value.ipMethod) {
626
+ const ipMethod = messageObj.value.ipMethod;
627
+ if (this.nameRegistry.hasIntegrationProcedureMapping(ipMethod)) {
628
+ messageObj.value.ipMethod = this.nameRegistry.getIntegrationProcedureCleanedName(ipMethod);
629
+ }
630
+ else {
631
+ logger_1.Logger.logVerbose(`\n${this.messages.getMessage('componentMappingNotFound', ['IntegrationProcedure', ipMethod])}`);
632
+ const parts = ipMethod.split('_');
633
+ messageObj.value.ipMethod = parts.map((p) => this.cleanName(p, true)).join('_');
634
+ if (parts.length > 2 && invalidIpNames) {
635
+ invalidIpNames.set(`event.actionList.stateAction.message`, ipMethod);
636
+ }
637
+ }
638
+ messageUpdated = true;
639
+ }
640
+ }
641
+ if (messageUpdated) {
642
+ stateAction.message = JSON.stringify(messageObj);
643
+ }
644
+ }
645
+ catch (e) {
646
+ // message is not valid JSON, skip
647
+ logger_1.Logger.error(`Failed to parse stateAction.message as JSON: ${e.message}`);
648
+ }
649
+ }
650
+ }
651
+ handleAssessmentForStdDataModelOrgsWithMetadataAPIEnabled(flexCards) {
652
+ logger_1.Logger.logVerbose(this.messages.getMessage('preparingStorageForMetadataEnabledOrg', [stringContants_1.Constants.Flexcard]));
653
+ let storage = storageUtil_1.StorageUtil.getOmnistudioAssessmentStorage();
654
+ this.prepareStorageForRelatedObjectsWhenMetadataAPIEnabled(storage, flexCards);
655
+ storageUtil_1.StorageUtil.printAssessmentStorage();
656
+ return [];
657
+ }
658
+ handleMigrationForStdDataModelOrgsWithMetadataAPIEnabled(flexcards) {
659
+ logger_1.Logger.logVerbose(this.messages.getMessage('preparingStorageForMetadataEnabledOrg', [stringContants_1.Constants.Flexcard]));
660
+ let storage = storageUtil_1.StorageUtil.getOmnistudioMigrationStorage();
661
+ this.prepareStorageForRelatedObjectsWhenMetadataAPIEnabled(storage, flexcards);
662
+ storageUtil_1.StorageUtil.printAssessmentStorage();
663
+ // Return empty result structure for report generation
664
+ return [
665
+ {
666
+ name: this.getName(),
667
+ results: new Map(),
668
+ records: new Map(),
669
+ },
670
+ ];
671
+ }
260
672
  readChildCardsFromDefinition(card) {
261
673
  let childs = [];
262
- const definition = JSON.parse(card[this.namespacePrefix + 'Definition__c']);
674
+ const definition = JSON.parse(card[this.getFieldKey('Definition__c')]);
263
675
  if (!definition)
264
676
  return childs;
265
677
  for (let state of definition.states || []) {
@@ -269,105 +681,205 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
269
681
  }
270
682
  return childs;
271
683
  }
272
- checkComponentForDependencies(component, flexCardAssessmentInfo) {
684
+ checkComponentForDependencies(component, flexCardAssessmentInfo, omniScriptNavigateURLWarningKeys = new Set()) {
273
685
  // Check if this component is an action element
274
686
  if (component.element === 'action' && component.property && component.property.actionList) {
275
687
  // Process each action in the actionList
276
688
  for (const action of component.property.actionList) {
277
689
  if (action.stateAction) {
690
+ // Detect Vlocity Action (not supported in standard runtime FlexCards)
691
+ if (action.stateAction.type === stringContants_1.Constants.VlocityAction) {
692
+ this.addVlocityActionDependency(action.stateAction, flexCardAssessmentInfo);
693
+ }
694
+ // Handle message field (contains DataRaptor/IP references as JSON string)
695
+ this.processStateActionMessageForDependencies(action.stateAction, flexCardAssessmentInfo);
278
696
  // Case 1: Direct OmniScript reference
279
697
  if (action.stateAction.type === stringContants_1.Constants.OmniScriptComponentName && action.stateAction.omniType) {
280
698
  const omniType = action.stateAction.omniType;
281
699
  if (omniType.Name && typeof omniType.Name === 'string') {
282
- const originalName = omniType.Name;
283
- const parts = originalName.split('/');
284
- if (parts.length >= 2) {
285
- // Check for name changes in each part
286
- const cleanedParts = parts.map((p) => this.cleanName(p));
287
- const cleanedName = cleanedParts.join('_');
288
- flexCardAssessmentInfo.dependenciesOS.push(cleanedName);
289
- // Add warning if any part of the name will change
290
- for (let i = 0; i < parts.length; i++) {
291
- if (parts[i] !== cleanedParts[i]) {
292
- flexCardAssessmentInfo.warnings.push(this.messages.getMessage('omniScriptNameChangeMessage', [parts[i], cleanedParts[i]]));
293
- flexCardAssessmentInfo.migrationStatus = 'Has Warnings';
294
- }
295
- }
296
- }
700
+ this.addOmniScriptDependency(omniType.Name, flexCardAssessmentInfo);
701
+ }
702
+ }
703
+ // MISSING PATTERN FIXED: Case 1b: Direct OmniScript reference without type check (for test compatibility)
704
+ else if (action.stateAction.omniType && !action.stateAction.type) {
705
+ const omniType = action.stateAction.omniType;
706
+ // Handle both string omniType and object with Name property
707
+ let omniTypeName;
708
+ if (typeof omniType === 'string') {
709
+ omniTypeName = omniType;
297
710
  }
711
+ else if (omniType.Name && typeof omniType.Name === 'string') {
712
+ omniTypeName = omniType.Name;
713
+ }
714
+ else {
715
+ continue; // Skip if we can't extract the name
716
+ }
717
+ this.addOmniScriptDependency(omniTypeName, flexCardAssessmentInfo);
298
718
  }
299
719
  // Case 2: Flyout OmniScript reference
300
- else if (action.stateAction.type === 'Flyout' &&
301
- action.stateAction.flyoutType === stringContants_1.Constants.OmniScriptPluralName &&
302
- action.stateAction.osName) {
720
+ else if (this.hasOmniscriptFlyoutDependency(action.stateAction)) {
303
721
  const osName = action.stateAction.osName;
304
722
  if (typeof osName === 'string') {
305
- // osName is typically in format "Omniscript/Testing/English"
306
- const originalName = osName;
307
- const parts = originalName.split('/');
308
- if (parts.length >= 2) {
309
- // Check for name changes in each part
310
- const cleanedParts = parts.map((p) => this.cleanName(p));
311
- const cleanedName = cleanedParts.join('_');
312
- flexCardAssessmentInfo.dependenciesOS.push(cleanedName);
313
- // Add warning if any part of the name will change
314
- for (let i = 0; i < parts.length; i++) {
315
- if (parts[i] !== cleanedParts[i]) {
316
- flexCardAssessmentInfo.warnings.push(this.messages.getMessage('omniScriptNameChangeMessage', [parts[i], cleanedParts[i]]));
317
- flexCardAssessmentInfo.migrationStatus = 'Has Warnings';
318
- }
319
- }
320
- }
723
+ this.addOmniScriptDependency(osName, flexCardAssessmentInfo);
321
724
  }
322
725
  }
726
+ // Case 3: Flyout childCard reference - flyoutLwc is a direct FlexCard name
727
+ else if (this.hasFlexCardFlyoutDependency(action.stateAction)) {
728
+ this.addFlexCardDependency(action.stateAction.flyoutLwc, flexCardAssessmentInfo);
729
+ }
730
+ // Case 4: Flyout CustomLwc reference - check for FlexCard reference with "cf" prefix
731
+ else if (this.hasCustomLwcFlyoutDependency(action.stateAction)) {
732
+ this.addCfPrefixedFlexCardDependency(action.stateAction.flyoutLwc, flexCardAssessmentInfo);
733
+ }
734
+ else if (this.isCustomWebPageAction(action.stateAction)) {
735
+ this.addOmniScriptNavigateURLAssessmentWarning(action.stateAction, flexCardAssessmentInfo, omniScriptNavigateURLWarningKeys);
736
+ }
323
737
  }
324
738
  }
325
739
  }
326
740
  // Check for Custom LWC component
327
- if (component.element === 'customLwc' && component.property) {
328
- // Check customlwcname property first
329
- if (component.property.customlwcname) {
330
- const customLwcName = component.property.customlwcname;
331
- logger_1.Logger.info(`Custom LWC name: ${customLwcName}`);
332
- // Avoid duplicates
333
- if (!flexCardAssessmentInfo.dependenciesLWC.includes(customLwcName)) {
334
- flexCardAssessmentInfo.dependenciesLWC.push(customLwcName);
335
- }
336
- }
337
- }
741
+ this.checkCustomLwcForDependencies(component, flexCardAssessmentInfo);
338
742
  // Check standard component actions if they exist
339
743
  if (component.actions && Array.isArray(component.actions)) {
340
744
  for (const action of component.actions) {
341
745
  if (action.stateAction && action.stateAction.omniType) {
342
746
  const omniType = action.stateAction.omniType;
343
747
  if (omniType.Name && typeof omniType.Name === 'string') {
344
- const parts = omniType.Name.split('/');
345
- if (parts.length >= 2) {
346
- const osRef = parts.join('_');
347
- flexCardAssessmentInfo.dependenciesOS.push(osRef);
348
- }
748
+ this.addOmniScriptDependency(omniType.Name, flexCardAssessmentInfo);
349
749
  }
350
750
  }
351
751
  }
352
752
  }
753
+ // MISSING PATTERN FIXED: Handle direct stateAction on component property
754
+ if (component.property && component.property.stateAction) {
755
+ // Case 1: Direct OmniScript reference on component property
756
+ if (component.property.stateAction.omniType) {
757
+ const omniType = component.property.stateAction.omniType;
758
+ if (omniType.Name && typeof omniType.Name === 'string') {
759
+ this.addOmniScriptDependency(omniType.Name, flexCardAssessmentInfo);
760
+ }
761
+ }
762
+ // Case 2: Flyout OmniScript reference on component property
763
+ if (this.hasOmniscriptFlyoutDependency(component.property.stateAction)) {
764
+ const osName = component.property.stateAction.osName;
765
+ if (typeof osName === 'string') {
766
+ this.addOmniScriptDependency(osName, flexCardAssessmentInfo);
767
+ }
768
+ }
769
+ // Case 3: Flyout childCard reference on component property - flyoutLwc is a direct FlexCard name
770
+ if (this.hasFlexCardFlyoutDependency(component.property.stateAction)) {
771
+ this.addFlexCardDependency(component.property.stateAction.flyoutLwc, flexCardAssessmentInfo);
772
+ }
773
+ // Case 4: Flyout CustomLwc reference on component property - check for FlexCard reference with "cf" prefix
774
+ if (this.hasCustomLwcFlyoutDependency(component.property.stateAction)) {
775
+ this.addCfPrefixedFlexCardDependency(component.property.stateAction.flyoutLwc, flexCardAssessmentInfo);
776
+ }
777
+ else if (this.isCustomWebPageAction(component.property.stateAction)) {
778
+ this.addOmniScriptNavigateURLAssessmentWarning(component.property.stateAction, flexCardAssessmentInfo, omniScriptNavigateURLWarningKeys);
779
+ }
780
+ }
781
+ // MISSING PATTERN FIXED: Handle omni-flyout elements (from tests)
782
+ if (component.element === stringContants_1.Constants.OmniFlyout && component.property && component.property.flyoutOmniScript) {
783
+ if (component.property.flyoutOmniScript.osName) {
784
+ const osName = component.property.flyoutOmniScript.osName;
785
+ if (typeof osName === 'string') {
786
+ this.addOmniScriptDependency(osName, flexCardAssessmentInfo);
787
+ }
788
+ }
789
+ }
790
+ // MISSING PATTERN FIXED: Handle childCardPreview elements with cardName property
791
+ if (component.element === stringContants_1.Constants.ChildCardPreview && component.property && component.property.cardName) {
792
+ this.addFlexCardDependency(component.property.cardName, flexCardAssessmentInfo);
793
+ }
353
794
  // Check child components recursively
354
795
  if (component.children && Array.isArray(component.children)) {
355
- for (const child of component.children) {
356
- this.checkComponentForDependencies(child, flexCardAssessmentInfo);
796
+ for (let childIndex = 0; childIndex < component.children.length; childIndex++) {
797
+ const child = component.children[childIndex];
798
+ this.checkComponentForDependencies(child, flexCardAssessmentInfo, omniScriptNavigateURLWarningKeys);
799
+ }
800
+ }
801
+ }
802
+ addOmniScriptNavigateURLAssessmentWarning(stateAction, flexCardAssessmentInfo, warningKeys) {
803
+ if (this.IS_STANDARD_DATA_MODEL) {
804
+ return;
805
+ }
806
+ const rewrite = this.getOmniScriptURLRewrite(stateAction);
807
+ if (!rewrite) {
808
+ return;
809
+ }
810
+ const { targetName, updatedURL, malformedTokens } = rewrite;
811
+ const summary = this.formatURLRewriteSummary(targetName, updatedURL);
812
+ if (warningKeys.has(summary)) {
813
+ return;
814
+ }
815
+ warningKeys.add(summary);
816
+ // Emit a single warning per URL: when fragment tokens are malformed, the
817
+ // dedicated malformed-token warning is the authoritative one (it already
818
+ // contains both the original URL and the "will get replaced with" line,
819
+ // PLUS the malformed-token list and the verify instruction). For clean
820
+ // URLs we fall back to the plain rewrite warning. Defense-in-depth: if
821
+ // the malformed formatter unexpectedly returns empty, fall back to the
822
+ // plain rewrite warning so the customer still sees something.
823
+ const hasMalformedTokens = Array.isArray(malformedTokens) && malformedTokens.length > 0;
824
+ let warningText = '';
825
+ if (hasMalformedTokens) {
826
+ warningText = this.formatMalformedFragmentTokenWarning(targetName, updatedURL, malformedTokens);
827
+ }
828
+ if (!warningText) {
829
+ warningText = this.messages.getMessage('webPageOmniScriptNavigationDetected', [
830
+ this.toReadableURL(targetName),
831
+ this.toReadableURL(updatedURL),
832
+ ]);
833
+ }
834
+ flexCardAssessmentInfo.warnings.push(warningText);
835
+ flexCardAssessmentInfo.migrationStatus = (0, stringUtils_1.getUpdatedAssessmentStatus)(flexCardAssessmentInfo.migrationStatus, 'Warnings');
836
+ }
837
+ /**
838
+ * Build the customer-facing warning shown when a Web Page action URL contains
839
+ * fragment tokens that decodeURIComponent couldn't parse. Centralised here so
840
+ * the assessment and migration paths emit byte-identical text.
841
+ *
842
+ * Returns an empty string when the helper is called with no malformed tokens
843
+ * (defense in depth: callers already guard, but a future caller that forgets
844
+ * shouldn't be able to produce a degenerate warning with an empty bracket).
845
+ * Non-string entries are coerced via String() so a misbehaving caller can't
846
+ * surface "undefined" / "[object Object]" to customers; duplicates are
847
+ * suppressed so a fragment like `#/Foo%/Bar/Foo%/Baz` doesn't render as
848
+ * `["Foo%", "Foo%"]`.
849
+ */
850
+ formatMalformedFragmentTokenWarning(targetName, updatedURL, malformedTokens) {
851
+ if (!Array.isArray(malformedTokens) || malformedTokens.length === 0) {
852
+ return '';
853
+ }
854
+ const seen = new Set();
855
+ const uniqueTokens = [];
856
+ for (const raw of malformedTokens) {
857
+ const t = typeof raw === 'string' ? raw : String(raw);
858
+ if (!seen.has(t)) {
859
+ seen.add(t);
860
+ uniqueTokens.push(t);
357
861
  }
358
862
  }
863
+ const tokenList = uniqueTokens.map((t) => `"${t}"`).join(', ');
864
+ return this.messages.getMessage('webPageOmniScriptUrlMalformedToken', [
865
+ tokenList,
866
+ this.toReadableURL(targetName),
867
+ this.toReadableURL(updatedURL),
868
+ ]);
359
869
  }
360
- // Query all cards that are active
361
- async getAllActiveCards() {
870
+ async getAllCards() {
362
871
  //DebugTimer.getInstance().lap('Query Vlocity Cards');
363
872
  const filters = new Map();
364
- filters.set(this.namespacePrefix + 'CardType__c', 'flex');
873
+ if (!this.IS_STANDARD_DATA_MODEL) {
874
+ filters.set(this.namespacePrefix + 'CardType__c', 'flex');
875
+ }
876
+ let flexCards;
365
877
  if (this.allVersions) {
366
878
  const sortFields = [
367
879
  { field: 'Name', direction: utils_1.SortDirection.ASC },
368
- { field: this.namespacePrefix + 'Version__c', direction: utils_1.SortDirection.ASC },
880
+ { field: this.getFieldKey('Version__c'), direction: utils_1.SortDirection.ASC },
369
881
  ];
370
- return await utils_1.QueryTools.queryWithFilterAndSort(this.connection, this.namespace, CardMigrationTool.VLOCITYCARD_NAME, this.getCardFields(), filters, sortFields).catch((err) => {
882
+ flexCards = await utils_1.QueryTools.queryWithFilterAndSort(this.connection, this.getQueryNamespace(), this.getCardObjectName(), this.getCardFields(), filters, sortFields).catch((err) => {
371
883
  if (err.errorCode === 'INVALID_TYPE') {
372
884
  throw new interfaces_1.InvalidEntityTypeError(`${CardMigrationTool.VLOCITYCARD_NAME} type is not found under this namespace`);
373
885
  }
@@ -375,37 +887,44 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
375
887
  });
376
888
  }
377
889
  else {
378
- filters.set(this.namespacePrefix + 'Active__c', true);
379
- return await utils_1.QueryTools.queryWithFilter(this.connection, this.namespace, CardMigrationTool.VLOCITYCARD_NAME, this.getCardFields(), filters).catch((err) => {
890
+ filters.set(this.getFieldKey('Active__c'), true);
891
+ flexCards = await utils_1.QueryTools.queryWithFilter(this.connection, this.getQueryNamespace(), this.getCardObjectName(), this.getCardFields(), filters).catch((err) => {
380
892
  if (err.errorCode === 'INVALID_TYPE') {
381
- throw new interfaces_1.InvalidEntityTypeError(`${CardMigrationTool.VLOCITYCARD_NAME} type is not found under this namespace`);
893
+ throw new interfaces_1.InvalidEntityTypeError(`${this.getCardObjectName()} type is not found under this namespace`);
382
894
  }
383
895
  throw err;
384
896
  });
385
897
  }
898
+ // Apply prioritization only for standard data model
899
+ if (this.IS_STANDARD_DATA_MODEL) {
900
+ return this.prioritizeFlexCardsWithoutSpecialCharacters(flexCards);
901
+ }
902
+ return flexCards;
386
903
  }
387
- // Upload All the VlocityCard__c records to OmniUiCard
904
+ // Upload All the VlocityCard__c records to OmniUiCard for custom model and update references for standard
388
905
  async uploadAllCards(cards, progressBar) {
389
906
  const cardsUploadInfo = new Map();
390
907
  const originalRecords = new Map();
391
908
  const uniqueNames = new Set();
909
+ // Map to track cleanedName -> originalName for duplicate detection
910
+ const dupFlexCardNames = new Map();
392
911
  let progressCounter = 0;
393
912
  progressBar.start(cards.length, progressCounter);
394
913
  for (let card of cards) {
395
- await this.uploadCard(cards, card, cardsUploadInfo, originalRecords, uniqueNames);
914
+ await this.uploadCard(cards, card, cardsUploadInfo, originalRecords, uniqueNames, dupFlexCardNames);
396
915
  progressBar.update(++progressCounter);
397
916
  }
398
917
  this.prepareStorageForFlexcards(cardsUploadInfo, originalRecords);
399
918
  progressBar.stop();
400
919
  return cardsUploadInfo;
401
920
  }
402
- async uploadCard(allCards, card, cardsUploadInfo, originalRecords, uniqueNames) {
921
+ async uploadCard(allCards, card, cardsUploadInfo, originalRecords, uniqueNames, dupFlexCardNames) {
403
922
  const recordId = card['Id'];
404
923
  // If we already uploaded this card, skip
405
924
  if (cardsUploadInfo.has(recordId)) {
406
925
  return;
407
926
  }
408
- const isCardActive = card[`${this.namespacePrefix}Active__c`];
927
+ const isCardActive = card[this.getFieldKey('Active__c')];
409
928
  try {
410
929
  const childCards = this.getChildCards(card);
411
930
  if (childCards.length > 0) {
@@ -413,14 +932,19 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
413
932
  // Upload child cards
414
933
  const childCard = allCards.find((c) => c['Name'] === childCardName);
415
934
  if (childCard) {
416
- await this.uploadCard(allCards, childCard, cardsUploadInfo, originalRecords, uniqueNames);
935
+ await this.uploadCard(allCards, childCard, cardsUploadInfo, originalRecords, uniqueNames, dupFlexCardNames);
417
936
  }
418
937
  }
419
938
  this.updateChildCards(card);
420
939
  }
421
940
  // Perform the transformation
422
941
  const invalidIpNames = new Map();
423
- const transformedCard = this.mapVlocityCardRecord(card, cardsUploadInfo, invalidIpNames);
942
+ const urlUpdateSummaries = new Set();
943
+ // Map keyed by rewrite summary so the emission step below can subtract
944
+ // malformed URLs from the aggregate "Updated URLs:" locations message.
945
+ // Same key for two actions on the same card => one entry (deduped).
946
+ const malformedFragmentWarnings = new Map();
947
+ const transformedCard = this.mapVlocityCardRecord(card, cardsUploadInfo, invalidIpNames, urlUpdateSummaries, malformedFragmentWarnings); // This only has the card structure, card definition is not there
424
948
  // Verify duplicated names
425
949
  let transformedCardName;
426
950
  if (this.allVersions) {
@@ -430,17 +954,50 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
430
954
  transformedCardName = transformedCard['Name'];
431
955
  }
432
956
  const transformedCardAuthorName = transformedCard['AuthorName'];
433
- if (uniqueNames.has(transformedCard['Name'])) {
434
- this.setRecordErrors(card, this.messages.getMessage('duplicatedCardName'));
957
+ // Check for duplicates using version-aware name when allVersions is true
958
+ const uniqueCheckName = this.allVersions
959
+ ? `${transformedCard['Name']}_${transformedCard['VersionNumber']}`
960
+ : transformedCard['Name'];
961
+ const originalCardName = card['Name'];
962
+ const cleanedCardName = transformedCard['Name'];
963
+ // Check for exact duplicate (same name + same version)
964
+ if (uniqueNames.has(uniqueCheckName)) {
965
+ this.setRecordErrors(card, this.messages.getMessage('duplicatedCardName', [uniqueCheckName]));
435
966
  originalRecords.set(recordId, card);
436
967
  return;
437
968
  }
438
- // Save the name for duplicated names check
439
- uniqueNames.add(transformedCard['Name']);
969
+ // Check for naming conflict: different original names cleaning to same name
970
+ else if (this.allVersions && dupFlexCardNames.has(cleanedCardName)) {
971
+ const existingOriginalName = dupFlexCardNames.get(cleanedCardName);
972
+ // Only flag if the original names are different (indicates a naming conflict)
973
+ if (existingOriginalName !== originalCardName) {
974
+ this.setRecordErrors(card, this.messages.getMessage('lowerVersionDuplicateCardName', [uniqueCheckName]));
975
+ originalRecords.set(recordId, card);
976
+ return;
977
+ }
978
+ }
979
+ // Add to tracking structures
980
+ uniqueNames.add(uniqueCheckName);
981
+ if (this.allVersions && !dupFlexCardNames.has(cleanedCardName)) {
982
+ dupFlexCardNames.set(cleanedCardName, originalCardName);
983
+ }
440
984
  // Create a map of the original records
441
985
  originalRecords.set(recordId, card);
442
986
  // Create card
443
- const uploadResult = await net_1.NetUtils.createOne(this.connection, CardMigrationTool.OMNIUICARD_NAME, recordId, transformedCard);
987
+ let uploadResult;
988
+ if (!this.IS_STANDARD_DATA_MODEL) {
989
+ uploadResult = await net_1.NetUtils.createOne(this.connection, CardMigrationTool.OMNIUICARD_NAME, recordId, transformedCard);
990
+ }
991
+ else {
992
+ const standardId = transformedCard['Id'];
993
+ delete transformedCard['Id'];
994
+ const deactivationResult = await net_1.NetUtils.updateOne(this.connection, CardMigrationTool.OMNIUICARD_NAME, standardId, standardId, {
995
+ ['IsActive']: false,
996
+ });
997
+ logger_1.Logger.logVerbose(JSON.stringify(deactivationResult)); // TODO - Add checks here
998
+ uploadResult = await net_1.NetUtils.updateOne(this.connection, CardMigrationTool.OMNIUICARD_NAME, recordId, recordId, transformedCard);
999
+ uploadResult['id'] = standardId;
1000
+ }
444
1001
  if (uploadResult) {
445
1002
  // Fix errors
446
1003
  uploadResult.errors = uploadResult.errors || [];
@@ -449,13 +1006,33 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
449
1006
  }
450
1007
  // If name has been changed, add a warning message
451
1008
  uploadResult.warnings = uploadResult.warnings || [];
452
- if (transformedCardAuthorName !== card[this.namespacePrefix + 'Author__c']) {
1009
+ if (transformedCardAuthorName !== card[this.getFieldKey('Author__c')]) {
453
1010
  uploadResult.warnings.unshift(this.messages.getMessage('cardAuthorNameChangeMessage', [transformedCardAuthorName]));
454
1011
  }
455
1012
  uploadResult.newName = transformedCardName;
1013
+ uploadResult.actualName = transformedCard['Name']; // This is required as storage needs name without version, for replacement in other references
456
1014
  if (transformedCard['Name'] !== card['Name']) {
457
1015
  uploadResult.warnings.unshift(this.messages.getMessage('cardNameChangeMessage', [transformedCardName]));
458
1016
  }
1017
+ // The count summary describes ONLY URLs that were converted cleanly
1018
+ // to the standard URL format. Malformed URLs were rewritten with
1019
+ // their bad tokens kept as-is -- claiming they were "updated to
1020
+ // standard URL format" alongside their own malformed warning would
1021
+ // contradict that warning and confuse the customer. Each malformed
1022
+ // URL is surfaced via its own dedicated bullet below which already
1023
+ // names the original URL, the rewritten URL, and the verify
1024
+ // instruction.
1025
+ const cleanRewriteSummaries = Array.from(urlUpdateSummaries).filter((summary) => !malformedFragmentWarnings.has(summary));
1026
+ if (cleanRewriteSummaries.length > 0) {
1027
+ uploadResult.warnings.unshift(this.messages.getMessage('flexCardOmniScriptNavigateURLUpdated', [String(cleanRewriteSummaries.length)]));
1028
+ }
1029
+ // Surface malformed-fragment-token warnings (one per affected URL).
1030
+ // These are intentionally emitted *instead of* the count bullet
1031
+ // above so the customer sees a single, actionable bullet per
1032
+ // malformed URL: original URL, rewrite, verify instruction.
1033
+ for (const malformedWarning of malformedFragmentWarnings.values()) {
1034
+ uploadResult.warnings.push(malformedWarning);
1035
+ }
459
1036
  if (uploadResult.id && invalidIpNames.size > 0) {
460
1037
  const val = Array.from(invalidIpNames.entries())
461
1038
  .map((e) => e[0])
@@ -485,50 +1062,120 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
485
1062
  });
486
1063
  }
487
1064
  }
488
- addToAssessmentStorage(originalName, cleanedName) {
1065
+ prepareStorageForRelatedObjectsWhenMetadataAPIEnabled(storage, flexcards) {
1066
+ for (const flexcard of flexcards) {
1067
+ const originalName = flexcard[this.getFieldKey('Name')];
1068
+ let value = {
1069
+ name: originalName,
1070
+ isDuplicate: false,
1071
+ originalName: originalName,
1072
+ migrationSuccess: true, // When metadata API is enabled, assume migration is successful
1073
+ };
1074
+ this.addKeyToStorage(originalName, value, storage);
1075
+ }
1076
+ }
1077
+ prepareAssessmentStorageForFlexcards(flexcardAssessmentInfos) {
489
1078
  let storage = storageUtil_1.StorageUtil.getOmnistudioAssessmentStorage();
490
- if (storage.fcStorage.has(originalName)) {
491
- storage.fcStorage.get(originalName).isDuplicate = true;
1079
+ for (let flexCardAssessmentInfo of flexcardAssessmentInfos) {
1080
+ try {
1081
+ if (!(flexCardAssessmentInfo === null || flexCardAssessmentInfo === void 0 ? void 0 : flexCardAssessmentInfo.nameMapping)) {
1082
+ logger_1.Logger.error(this.messages.getMessage('missingInfo'));
1083
+ return;
1084
+ }
1085
+ const originalName = flexCardAssessmentInfo.nameMapping.oldName;
1086
+ let value = {
1087
+ name: flexCardAssessmentInfo.nameMapping.newName,
1088
+ isDuplicate: false,
1089
+ originalName: originalName,
1090
+ };
1091
+ if (flexCardAssessmentInfo.errors && flexCardAssessmentInfo.errors.length > 0) {
1092
+ value.error = flexCardAssessmentInfo.errors;
1093
+ value.migrationSuccess = false;
1094
+ }
1095
+ else if (flexCardAssessmentInfo.migrationStatus === 'Needs manual intervention') {
1096
+ // Duplicate name and other critical warnings
1097
+ value.error = flexCardAssessmentInfo.warnings;
1098
+ value.migrationSuccess = false;
1099
+ }
1100
+ else {
1101
+ value.migrationSuccess = true;
1102
+ }
1103
+ this.addKeyToStorage(originalName, value, storage);
1104
+ }
1105
+ catch (error) {
1106
+ logger_1.Logger.logVerbose(this.messages.getMessage('errorWhileProcessingFlexcardStorage'));
1107
+ logger_1.Logger.error(error);
1108
+ }
1109
+ }
1110
+ storageUtil_1.StorageUtil.printAssessmentStorage();
1111
+ }
1112
+ addKeyToStorage(originalName, value, storage) {
1113
+ let finalKey = `${originalName}`;
1114
+ finalKey = finalKey.toLowerCase();
1115
+ if (storage.fcStorage.has(finalKey)) {
1116
+ if (this.allVersions) {
1117
+ const storedValue = storage.fcStorage.get(finalKey);
1118
+ if (this.isDifferentFlexcard(storedValue, originalName)) {
1119
+ this.markDuplicateKeyInStorage(value, finalKey, storage);
1120
+ }
1121
+ }
1122
+ else {
1123
+ this.markDuplicateKeyInStorage(value, finalKey, storage);
1124
+ }
492
1125
  }
493
1126
  else {
494
- storage.fcStorage.set(originalName, {
495
- name: cleanedName,
496
- isDuplicate: false,
497
- });
1127
+ // Key doesn't exist - safe to set
1128
+ storage.fcStorage.set(finalKey, value);
1129
+ }
1130
+ }
1131
+ markDuplicateKeyInStorage(value, finalKey, storage) {
1132
+ // Key already exists - handle accordingly
1133
+ logger_1.Logger.logVerbose(this.messages.getMessage('keyAlreadyInStorage', ['Flexcard', finalKey]));
1134
+ value.isDuplicate = true;
1135
+ storage.fcStorage.set(finalKey, value);
1136
+ }
1137
+ isDifferentFlexcard(storedValue, originalName) {
1138
+ if (storedValue.originalName === originalName) {
1139
+ return false;
498
1140
  }
1141
+ return true;
499
1142
  }
500
1143
  prepareStorageForFlexcards(cardsUploadInfo, originalRecords) {
501
- logger_1.Logger.logVerbose('Started preparing storage for flexcards');
1144
+ logger_1.Logger.logVerbose(this.messages.getMessage('flexcardStorageProcessingStarted'));
502
1145
  let storage = storageUtil_1.StorageUtil.getOmnistudioMigrationStorage();
503
1146
  for (let key of Array.from(originalRecords.keys())) {
504
1147
  try {
505
1148
  let oldrecord = originalRecords.get(key);
506
1149
  let newrecord = cardsUploadInfo.get(key);
1150
+ const originalName = oldrecord['Name'];
507
1151
  let value = {
508
- name: newrecord['newName'],
1152
+ name: newrecord === null || newrecord === void 0 ? void 0 : newrecord.actualName,
509
1153
  isDuplicate: false,
1154
+ originalName: originalName,
510
1155
  };
511
- if (newrecord.hasErrors) {
512
- value.error = newrecord.errors;
1156
+ if (newrecord === undefined) {
1157
+ // Card was not migrated - check if original record has error details
1158
+ if (oldrecord['errors'] && Array.isArray(oldrecord['errors'])) {
1159
+ value.error = oldrecord['errors'];
1160
+ }
1161
+ else {
1162
+ value.error = ['Migration Failed'];
1163
+ }
513
1164
  value.migrationSuccess = false;
514
1165
  }
515
1166
  else {
516
- value.migrationSuccess = true;
517
- }
518
- let finalKey = `${oldrecord['Name']}`;
519
- if (storage.fcStorage.has(finalKey)) {
520
- // Key already exists - handle accordingly
521
- logger_1.Logger.logVerbose(`Key ${finalKey} already exists in flexcard storage`);
522
- value.isDuplicate = true;
523
- storage.fcStorage.set(finalKey, value);
524
- }
525
- else {
526
- // Key doesn't exist - safe to set
527
- storage.fcStorage.set(finalKey, value);
1167
+ if (newrecord.hasErrors) {
1168
+ value.error = newrecord.errors;
1169
+ value.migrationSuccess = false;
1170
+ }
1171
+ else {
1172
+ value.migrationSuccess = true;
1173
+ }
528
1174
  }
1175
+ this.addKeyToStorage(originalName, value, storage);
529
1176
  }
530
1177
  catch (error) {
531
- logger_1.Logger.logVerbose('Error occurred while processing key for flexcard storage');
1178
+ logger_1.Logger.logVerbose(this.messages.getMessage('errorWhileProcessingFlexcardStorage'));
532
1179
  logger_1.Logger.error(error);
533
1180
  }
534
1181
  storageUtil_1.StorageUtil.printMigrationStorage();
@@ -536,7 +1183,7 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
536
1183
  }
537
1184
  getChildCards(card) {
538
1185
  let childs = [];
539
- const definition = JSON.parse(card[this.namespacePrefix + 'Definition__c']);
1186
+ const definition = JSON.parse(card[this.getFieldKey('Definition__c')]);
540
1187
  if (!definition)
541
1188
  return childs;
542
1189
  for (let state of definition.states || []) {
@@ -549,137 +1196,1030 @@ class CardMigrationTool extends base_1.BaseMigrationTool {
549
1196
  return childs;
550
1197
  }
551
1198
  updateChildCards(card) {
552
- const definition = JSON.parse(card[this.namespacePrefix + 'Definition__c']);
1199
+ const definition = JSON.parse(card[this.getFieldKey('Definition__c')]);
553
1200
  if (!definition)
554
1201
  return;
555
1202
  for (let state of definition.states || []) {
556
1203
  if (state.childCards && Array.isArray(state.childCards)) {
1204
+ const originalChildCards = [...state.childCards];
557
1205
  state.childCards = state.childCards.map((c) => this.cleanName(c));
1206
+ // Check if any child card name was changed
1207
+ for (let i = 0; i < originalChildCards.length; i++) {
1208
+ if (originalChildCards[i] !== state.childCards[i]) {
1209
+ }
1210
+ }
558
1211
  }
559
1212
  }
560
- card[this.namespacePrefix + 'Definition__c'] = JSON.stringify(definition);
1213
+ card[this.getFieldKey('Definition__c')] = JSON.stringify(definition);
561
1214
  }
562
1215
  // Maps an indivitdual VlocityCard__c record to an OmniUiCard record.
563
- mapVlocityCardRecord(cardRecord, cardsUploadInfo, invalidIpNames) {
1216
+ mapVlocityCardRecord(cardRecord, cardsUploadInfo, invalidIpNames, urlUpdateSummaries, malformedFragmentWarnings) {
1217
+ var _a, _b;
564
1218
  // Transformed object
565
- const mappedObject = {};
566
- // Get the fields of the record
567
- const recordFields = Object.keys(cardRecord);
568
- // Map individual fields
569
- recordFields.forEach((recordField) => {
570
- const cleanFieldName = this.getCleanFieldName(recordField);
571
- if (VlocityCard_1.default.hasOwnProperty(cleanFieldName) && cleanFieldName !== 'IsChildCard__c') {
572
- mappedObject[VlocityCard_1.default[cleanFieldName]] = cardRecord[recordField];
573
- // Transform ParentId__c to ClonedFromOmniUiCardKey field from uploaded response map
574
- if (cleanFieldName === 'ParentID__c' && cardsUploadInfo.has(cardRecord[`${this.namespacePrefix}ParentID__c`])) {
575
- mappedObject[VlocityCard_1.default[cleanFieldName]] = cardsUploadInfo.get(cardRecord[`${this.namespacePrefix}ParentID__c`]).id;
576
- }
577
- // CardType__c and OmniUiCardType have different picklist values
578
- if (cleanFieldName === 'CardType__c') {
579
- let ischildCard = cardRecord[`${this.namespacePrefix}IsChildCard__c`];
580
- mappedObject['OmniUiCardType'] = ischildCard ? 'Child' : 'Parent';
581
- }
582
- // Child Cards don't have version, so assigning 1
583
- if (cleanFieldName === 'Version__c') {
584
- let versionNumber = cardRecord[`${this.namespacePrefix}Version__c`];
585
- mappedObject['VersionNumber'] = versionNumber ? versionNumber : 1;
1219
+ let mappedObject = {};
1220
+ if (!this.IS_STANDARD_DATA_MODEL) {
1221
+ // Get the fields of the record
1222
+ const recordFields = Object.keys(cardRecord);
1223
+ // Map individual fields
1224
+ recordFields.forEach((recordField) => {
1225
+ const cleanFieldName = this.getCleanFieldName(recordField);
1226
+ if (VlocityCard_1.default.hasOwnProperty(cleanFieldName) && cleanFieldName !== 'IsChildCard__c') {
1227
+ mappedObject[VlocityCard_1.default[cleanFieldName]] = cardRecord[recordField];
1228
+ // Transform ParentId__c to ClonedFromOmniUiCardKey field from uploaded response map
1229
+ if (cleanFieldName === 'ParentID__c' && cardsUploadInfo.has(cardRecord[this.getFieldKey('ParentID__c')])) {
1230
+ mappedObject[VlocityCard_1.default[cleanFieldName]] = cardsUploadInfo.get(cardRecord[this.getFieldKey('ParentID__c')]).id;
1231
+ }
1232
+ // CardType__c and OmniUiCardType have different picklist values
1233
+ if (cleanFieldName === 'CardType__c') {
1234
+ let ischildCard = cardRecord[this.getFieldKey('IsChildCard__c')];
1235
+ mappedObject['OmniUiCardType'] = ischildCard ? 'Child' : 'Parent';
1236
+ }
1237
+ // Child Cards don't have version, so assigning 1
1238
+ if (cleanFieldName === 'Version__c') {
1239
+ let versionNumber = cardRecord[this.getFieldKey('Version__c')];
1240
+ mappedObject['VersionNumber'] = versionNumber ? versionNumber : 1;
1241
+ }
586
1242
  }
587
- }
588
- });
1243
+ });
1244
+ }
1245
+ else {
1246
+ mappedObject = { ...cardRecord };
1247
+ }
589
1248
  // Clean the name
590
1249
  mappedObject['Name'] = this.cleanName(mappedObject['Name']);
591
1250
  mappedObject[VlocityCard_1.default.Author__c] = this.cleanName(mappedObject[VlocityCard_1.default.Author__c]);
592
1251
  mappedObject[VlocityCard_1.default.Active__c] = false;
593
- // Update the datasource
594
- const datasource = JSON.parse(mappedObject[VlocityCard_1.default.Datasource__c] || '{}');
595
- if (datasource.dataSource) {
596
- const type = datasource.dataSource.type;
597
- if (type === stringContants_1.Constants.DataRaptorComponentName) {
598
- datasource.dataSource.value.bundle = this.cleanName(datasource.dataSource.value.bundle);
599
- }
600
- else if (type === stringContants_1.Constants.IntegrationProcedurePluralName) {
601
- const ipMethod = datasource.dataSource.value.ipMethod || '';
602
- const parts = ipMethod.split('_');
603
- const newKey = parts.map((p) => this.cleanName(p, true)).join('_');
604
- datasource.dataSource.value.ipMethod = newKey;
605
- if (parts.length > 2) {
606
- invalidIpNames.set('DataSource', ipMethod);
607
- }
1252
+ if (this.IS_STANDARD_DATA_MODEL) {
1253
+ if (mappedObject['OmniUiCardKey']) {
1254
+ mappedObject['OmniUiCardKey'] =
1255
+ mappedObject['Name'] +
1256
+ '/' +
1257
+ mappedObject[VlocityCard_1.default.Author__c] +
1258
+ '/' +
1259
+ mappedObject[VlocityCard_1.default.Version__c] +
1260
+ '.0';
608
1261
  }
609
- mappedObject[VlocityCard_1.default.Datasource__c] = JSON.stringify(datasource);
610
1262
  }
611
- // Update the propertyset datasource
612
- const propertySet = JSON.parse(mappedObject[VlocityCard_1.default.Definition__c] || '{}');
613
- if (propertySet) {
614
- if (propertySet.dataSource) {
615
- const type = propertySet.dataSource.type;
616
- if (type === 'DataRaptor') {
617
- propertySet.dataSource.value.bundle = this.cleanName(propertySet.dataSource.value.bundle);
1263
+ // Update the datasource - process any nested object with a 'type' property
1264
+ const datasource = JSON.parse(mappedObject[VlocityCard_1.default.Datasource__c] || '{}');
1265
+ let updated = false;
1266
+ // Process all keys that have objects with type property
1267
+ for (const key of Object.keys(datasource)) {
1268
+ const ds = datasource[key];
1269
+ if (!ds || typeof ds !== 'object' || !ds.type)
1270
+ continue;
1271
+ if (ds.type === stringContants_1.Constants.DataRaptorComponentName && ((_a = ds.value) === null || _a === void 0 ? void 0 : _a.bundle)) {
1272
+ ds.value.bundle = this.nameRegistry.hasDataMapperMapping(ds.value.bundle)
1273
+ ? this.nameRegistry.getDataMapperCleanedName(ds.value.bundle)
1274
+ : this.cleanName(ds.value.bundle);
1275
+ updated = true;
1276
+ }
1277
+ else if (ds.type === stringContants_1.Constants.IntegrationProcedurePluralName && ((_b = ds.value) === null || _b === void 0 ? void 0 : _b.ipMethod)) {
1278
+ const ipMethod = ds.value.ipMethod;
1279
+ if (this.nameRegistry.hasIntegrationProcedureMapping(ipMethod)) {
1280
+ ds.value.ipMethod = this.nameRegistry.getIntegrationProcedureCleanedName(ipMethod);
618
1281
  }
619
- else if (type === 'IntegrationProcedures') {
620
- const ipMethod = propertySet.dataSource.value.ipMethod || '';
1282
+ else {
621
1283
  const parts = ipMethod.split('_');
622
- const newKey = parts.map((p) => this.cleanName(p, true)).join('_');
623
- propertySet.dataSource.value.ipMethod = newKey;
624
- if (parts.length > 2) {
625
- invalidIpNames.set('DataSource', ipMethod);
626
- }
627
- }
628
- }
629
- // update the states for child cards
630
- for (let i = 0; i < (propertySet.states || []).length; i++) {
631
- const state = propertySet.states[i];
632
- // Clean childCards property
633
- if (state.childCards && Array.isArray(state.childCards)) {
634
- state.childCards = state.childCards.map((c) => this.cleanName(c));
635
- }
636
- // Fix the "components" for child cards
637
- for (let componentKey in state.components) {
638
- if (state.components.hasOwnProperty(componentKey)) {
639
- const component = state.components[componentKey];
640
- if (component.children && Array.isArray(component.children)) {
641
- this.fixChildren(component.children);
642
- }
643
- }
644
- }
645
- if (state.omniscripts && Array.isArray(state.omniscripts)) {
646
- for (let osIdx = 0; osIdx < state.omniscripts.length; osIdx++) {
647
- state.omniscripts[osIdx].type = this.cleanName(state.omniscripts[osIdx].type);
648
- state.omniscripts[osIdx].subtype = this.cleanName(state.omniscripts[osIdx].subtype);
649
- }
1284
+ ds.value.ipMethod = parts.map((p) => this.cleanName(p, true)).join('_');
1285
+ if (parts.length > 2)
1286
+ invalidIpNames.set(key, ipMethod);
650
1287
  }
1288
+ updated = true;
651
1289
  }
652
- mappedObject[VlocityCard_1.default.Definition__c] = JSON.stringify(propertySet);
653
1290
  }
1291
+ if (updated)
1292
+ mappedObject[VlocityCard_1.default.Datasource__c] = JSON.stringify(datasource);
1293
+ const isCardActive = cardRecord[this.getFieldKey('Active__c')];
1294
+ this.ensureCommunityTargets(mappedObject, isCardActive);
1295
+ // Update all dependencies comprehensively
1296
+ this.updateAllDependenciesWithRegistry(mappedObject, invalidIpNames, urlUpdateSummaries, malformedFragmentWarnings);
654
1297
  mappedObject['attributes'] = {
655
1298
  type: CardMigrationTool.OMNIUICARD_NAME,
656
1299
  referenceId: cardRecord['Id'],
657
1300
  };
658
1301
  return mappedObject;
659
1302
  }
660
- fixChildren(children) {
661
- for (let j = 0; j < children.length; j++) {
662
- const child = children[j];
663
- if (child.element === 'childCardPreview') {
664
- child.property.cardName = this.cleanName(child.property.cardName);
1303
+ /**
1304
+ * Comprehensive dependency update using NameMappingRegistry - mirrors assessment logic
1305
+ */
1306
+ updateAllDependenciesWithRegistry(mappedObject, invalidIpNames, urlUpdateSummaries, malformedFragmentWarnings) {
1307
+ // Handle propertySet (Definition) - update all dependency references
1308
+ const propertySet = JSON.parse(mappedObject[VlocityCard_1.default.Definition__c] || '{}');
1309
+ if (propertySet) {
1310
+ // Handle dataSource in propertySet
1311
+ if (propertySet.dataSource) {
1312
+ this.updateDataSourceWithRegistry(propertySet.dataSource, invalidIpNames, 'PropertySet');
665
1313
  }
666
- else if (child.element === 'action') {
667
- if (child.property && child.property.stateAction && child.property.stateAction.omniType) {
668
- const parts = (child.property.stateAction.omniType.Name || '').split('/');
669
- child.property.stateAction.omniType.Name = parts.map((p) => this.cleanName(p)).join('/');
670
- }
1314
+ // Handle states comprehensively
1315
+ if (propertySet.states && Array.isArray(propertySet.states)) {
1316
+ for (let i = 0; i < propertySet.states.length; i++) {
1317
+ const state = propertySet.states[i];
1318
+ // Handle child cards using registry
1319
+ if (state.childCards && Array.isArray(state.childCards)) {
1320
+ state.childCards = state.childCards.map((c) => {
1321
+ if (c && this.nameRegistry.hasFlexCardMapping(c)) {
1322
+ return this.nameRegistry.getFlexCardCleanedName(c);
1323
+ }
1324
+ else {
1325
+ logger_1.Logger.logVerbose(`\n${this.messages.getMessage('componentMappingNotFound', ['Flexcard', c])}`);
1326
+ return this.cleanName(c);
1327
+ }
1328
+ });
1329
+ }
1330
+ // Handle omniscripts using registry
1331
+ if (state.omniscripts && Array.isArray(state.omniscripts)) {
1332
+ for (let osIdx = 0; osIdx < state.omniscripts.length; osIdx++) {
1333
+ this.updateOmniScriptReferenceWithRegistry(state.omniscripts[osIdx]);
1334
+ }
1335
+ }
1336
+ // Handle components comprehensively using registry
1337
+ if (state.components) {
1338
+ for (const componentKey in state.components) {
1339
+ if (state.components.hasOwnProperty(componentKey)) {
1340
+ const component = state.components[componentKey];
1341
+ this.updateComponentDependenciesWithRegistry(component, urlUpdateSummaries, malformedFragmentWarnings);
1342
+ }
1343
+ }
1344
+ }
1345
+ }
671
1346
  }
672
- if (child.children && Array.isArray(child.children)) {
673
- this.fixChildren(child.children);
1347
+ // Handle events[] array references (Migration)
1348
+ if (propertySet.events && Array.isArray(propertySet.events)) {
1349
+ this.updateEventsWithRegistry(propertySet.events, invalidIpNames);
674
1350
  }
1351
+ mappedObject[VlocityCard_1.default.Definition__c] = JSON.stringify(propertySet);
675
1352
  }
676
1353
  }
1354
+ /**
1355
+ * Update events array references (Migration)
1356
+ * Handles: events[].actionList[].stateAction references
1357
+ */
1358
+ updateEventsWithRegistry(events, invalidIpNames) {
1359
+ for (const event of events) {
1360
+ if (!event.actionList || !Array.isArray(event.actionList)) {
1361
+ continue;
1362
+ }
1363
+ for (const action of event.actionList) {
1364
+ if (!action.stateAction) {
1365
+ continue;
1366
+ }
1367
+ const stateAction = action.stateAction;
1368
+ // 1-2. Handle message.value.bundle (DataRaptor) and message.value.ipMethod (Integration Procedure)
1369
+ this.processStateActionMessageWithRegistry(stateAction, invalidIpNames);
1370
+ // 3. Handle cardName (FlexCard - Flyout childCard)
1371
+ if (stateAction.cardName) {
1372
+ const originalCardName = stateAction.cardName;
1373
+ if (this.nameRegistry.hasFlexCardMapping(originalCardName)) {
1374
+ stateAction.cardName = this.nameRegistry.getFlexCardCleanedName(originalCardName);
1375
+ }
1376
+ else {
1377
+ logger_1.Logger.logVerbose(`\n${this.messages.getMessage('componentMappingNotFound', ['Flexcard', originalCardName])}`);
1378
+ stateAction.cardName = this.cleanName(originalCardName);
1379
+ }
1380
+ }
1381
+ // 4. Handle flyoutLwc (FlexCard child card and custom LWC references)
1382
+ this.updateFlyoutLwcValue(stateAction);
1383
+ if (this.hasOmniscriptFlyoutDependency(stateAction)) {
1384
+ this.updateOsNameWithRegistry(stateAction, 'osName');
1385
+ }
1386
+ // 6. Handle omniType.Name (OmniScript)
1387
+ if (stateAction.omniType && stateAction.omniType.Name) {
1388
+ this.updateOmniTypeNameWithRegistry(stateAction.omniType);
1389
+ }
1390
+ }
1391
+ }
1392
+ }
1393
+ /**
1394
+ * Update dataSource (DataRaptor, Integration Procedures, Apex Remote) using registry
1395
+ */
1396
+ updateDataSourceWithRegistry(dataSource, invalidIpNames, context) {
1397
+ var _a, _b, _c;
1398
+ const type = dataSource.type;
1399
+ if (type === stringContants_1.Constants.DataRaptorComponentName) {
1400
+ // Handle DataRaptor using registry
1401
+ const originalBundle = ((_a = dataSource.value) === null || _a === void 0 ? void 0 : _a.bundle) || '';
1402
+ if (originalBundle && this.nameRegistry.hasDataMapperMapping(originalBundle)) {
1403
+ dataSource.value.bundle = this.nameRegistry.getDataMapperCleanedName(originalBundle);
1404
+ }
1405
+ else {
1406
+ logger_1.Logger.logVerbose(`\n${this.messages.getMessage('componentMappingNotFound', ['DataMapper', originalBundle])}`);
1407
+ dataSource.value.bundle = this.cleanName(originalBundle);
1408
+ }
1409
+ }
1410
+ else if (type === stringContants_1.Constants.IntegrationProcedurePluralName) {
1411
+ // Handle Integration Procedures using registry
1412
+ const ipMethod = ((_b = dataSource.value) === null || _b === void 0 ? void 0 : _b.ipMethod) || '';
1413
+ const hasRegistryMapping = this.nameRegistry.hasIntegrationProcedureMapping(ipMethod);
1414
+ if (hasRegistryMapping) {
1415
+ const cleanedIpName = this.nameRegistry.getIntegrationProcedureCleanedName(ipMethod);
1416
+ dataSource.value.ipMethod = cleanedIpName;
1417
+ }
1418
+ else {
1419
+ logger_1.Logger.logVerbose(`\n${this.messages.getMessage('componentMappingNotFound', ['IntegrationProcedure', ipMethod])}`);
1420
+ const parts = ipMethod.split('_');
1421
+ const newKey = parts.map((p) => this.cleanName(p, true)).join('_');
1422
+ dataSource.value.ipMethod = newKey;
1423
+ if (parts.length > 2) {
1424
+ invalidIpNames.set(context, ipMethod);
1425
+ }
1426
+ }
1427
+ }
1428
+ else if (type === stringContants_1.Constants.ApexRemoteComponentName) {
1429
+ if ((_c = dataSource.value) === null || _c === void 0 ? void 0 : _c.remoteClass) {
1430
+ dataSource.value.remoteClass = this.apexNamespaceRegistry.getQualifiedClassName(dataSource.value.remoteClass);
1431
+ }
1432
+ }
1433
+ }
1434
+ /**
1435
+ * Update OmniScript reference using registry
1436
+ */
1437
+ updateOmniScriptReferenceWithRegistry(omniscriptRef) {
1438
+ const originalType = omniscriptRef.type;
1439
+ const originalSubtype = omniscriptRef.subtype;
1440
+ const language = omniscriptRef.language || 'English';
1441
+ // Construct full OmniScript name to check registry
1442
+ const fullOmniScriptName = `${originalType}_${originalSubtype}_${language}`;
1443
+ if (this.nameRegistry.hasOmniScriptMapping(fullOmniScriptName)) {
1444
+ // Registry has mapping for this OmniScript - extract cleaned parts
1445
+ const cleanedFullName = this.nameRegistry.getCleanedName(fullOmniScriptName, 'OmniScript');
1446
+ const parts = cleanedFullName.split('_');
1447
+ if (parts.length >= 2) {
1448
+ omniscriptRef.type = parts[0];
1449
+ omniscriptRef.subtype = parts[1];
1450
+ // Language doesn't typically change, but update if provided
1451
+ if (parts.length >= 3) {
1452
+ omniscriptRef.language = parts[2];
1453
+ }
1454
+ }
1455
+ }
1456
+ else {
1457
+ // No registry mapping - use original fallback approach
1458
+ logger_1.Logger.logVerbose(`\n${this.messages.getMessage('componentMappingNotFound', ['Omniscript', fullOmniScriptName])}`);
1459
+ omniscriptRef.type = this.cleanName(originalType);
1460
+ omniscriptRef.subtype = this.cleanName(originalSubtype);
1461
+ }
1462
+ }
1463
+ /**
1464
+ * Update component dependencies comprehensively
1465
+ */
1466
+ updateComponentDependenciesWithRegistry(component, urlUpdateSummaries, malformedFragmentWarnings) {
1467
+ // Handle action elements with actionList (like assessment)
1468
+ if (component.element === 'action' && component.property && component.property.actionList) {
1469
+ for (const action of component.property.actionList) {
1470
+ if (action.stateAction) {
1471
+ // Handle message field (contains DataRaptor/IP references as JSON string)
1472
+ this.processStateActionMessageWithRegistry(action.stateAction);
1473
+ // Case 1: Direct OmniScript reference
1474
+ if (action.stateAction.type === stringContants_1.Constants.OmniScriptComponentName && action.stateAction.omniType) {
1475
+ this.updateOmniTypeNameWithRegistry(action.stateAction.omniType);
1476
+ }
1477
+ // Case 2: Flyout OmniScript reference
1478
+ else if (this.hasOmniscriptFlyoutDependency(action.stateAction)) {
1479
+ this.updateOsNameWithRegistry(action.stateAction, 'osName');
1480
+ }
1481
+ // Case 3: Flyout with flyoutLwc (ChildCard or CustomLwc)
1482
+ else if (this.hasFlyoutLwc(action.stateAction)) {
1483
+ this.updateFlyoutLwcValue(action.stateAction);
1484
+ }
1485
+ // Case A: Custom Web Page action referencing OmniScript Universal Page
1486
+ else if (this.isCustomWebPageAction(action.stateAction)) {
1487
+ this.applyOmniScriptURLRewrite(action.stateAction, urlUpdateSummaries, malformedFragmentWarnings);
1488
+ }
1489
+ }
1490
+ }
1491
+ }
1492
+ // Handle Custom LWC components - special case for FlexCard references
1493
+ this.updateCustomLwcWithRegistry(component);
1494
+ // Handle standard component actions (like assessment)
1495
+ if (component.actions && Array.isArray(component.actions)) {
1496
+ for (const action of component.actions) {
1497
+ if (action.stateAction && action.stateAction.omniType) {
1498
+ this.updateOmniTypeNameWithRegistry(action.stateAction.omniType);
1499
+ }
1500
+ }
1501
+ }
1502
+ // Handle direct stateAction on component property (existing logic)
1503
+ if (component.property && component.property.stateAction) {
1504
+ if (component.property.stateAction.omniType) {
1505
+ this.updateOmniTypeNameWithRegistry(component.property.stateAction.omniType);
1506
+ }
1507
+ if (this.hasOmniscriptFlyoutDependency(component.property.stateAction)) {
1508
+ this.updateOsNameWithRegistry(component.property.stateAction, 'osName');
1509
+ }
1510
+ // Handle Flyout with flyoutLwc (ChildCard or CustomLwc)
1511
+ if (this.hasFlyoutLwc(component.property.stateAction)) {
1512
+ this.updateFlyoutLwcValue(component.property.stateAction);
1513
+ }
1514
+ if (this.isCustomWebPageAction(component.property.stateAction)) {
1515
+ this.applyOmniScriptURLRewrite(component.property.stateAction, urlUpdateSummaries, malformedFragmentWarnings);
1516
+ }
1517
+ }
1518
+ // Handle childCardPreview elements (from old fixChildren method)
1519
+ if (component.element === stringContants_1.Constants.ChildCardPreview && component.property) {
1520
+ if (component.property.cardName) {
1521
+ const originalCardName = component.property.cardName;
1522
+ if (this.nameRegistry.hasFlexCardMapping(originalCardName)) {
1523
+ component.property.cardName = this.nameRegistry.getFlexCardCleanedName(originalCardName);
1524
+ }
1525
+ else {
1526
+ logger_1.Logger.logVerbose(`\n${this.messages.getMessage('componentMappingNotFound', ['Flexcard', originalCardName])}`);
1527
+ component.property.cardName = this.cleanName(originalCardName);
1528
+ }
1529
+ }
1530
+ }
1531
+ // Handle omni-flyout elements (missing from migration logic)
1532
+ if (component.element === stringContants_1.Constants.OmniFlyout && component.property && component.property.flyoutOmniScript) {
1533
+ if (component.property.flyoutOmniScript.osName) {
1534
+ const osName = component.property.flyoutOmniScript.osName;
1535
+ if (typeof osName === 'string') {
1536
+ const parts = osName.split('/');
1537
+ if (parts.length >= 2) {
1538
+ // Construct full OmniScript name: Type_SubType_Language
1539
+ const originalOsRef = parts.join('_');
1540
+ if (this.nameRegistry.hasOmniScriptMapping(originalOsRef)) {
1541
+ // Registry has mapping - extract cleaned parts and convert back to / format
1542
+ const cleanedFullName = this.nameRegistry.getCleanedName(originalOsRef, 'OmniScript');
1543
+ const cleanedParts = cleanedFullName.split('_');
1544
+ if (cleanedParts.length >= 2) {
1545
+ component.property.flyoutOmniScript.osName = cleanedParts.join('/');
1546
+ }
1547
+ }
1548
+ else {
1549
+ // No registry mapping - use original fallback approach
1550
+ logger_1.Logger.logVerbose(`\n${this.messages.getMessage('componentMappingNotFound', ['Omniscript', originalOsRef])}`);
1551
+ component.property.flyoutOmniScript.osName =
1552
+ parts.length >= 3
1553
+ ? `${this.cleanName(parts[0])}/${this.cleanName(parts[1])}/${parts[2]}`
1554
+ : parts.map((p) => this.cleanName(p)).join('/');
1555
+ }
1556
+ }
1557
+ }
1558
+ }
1559
+ }
1560
+ // Check child components recursively
1561
+ if (component.children && Array.isArray(component.children)) {
1562
+ for (const child of component.children) {
1563
+ this.updateComponentDependenciesWithRegistry(child, urlUpdateSummaries, malformedFragmentWarnings);
1564
+ }
1565
+ }
1566
+ }
1567
+ applyOmniScriptURLRewrite(stateAction, urlUpdateSummaries, malformedFragmentWarnings) {
1568
+ if (this.IS_STANDARD_DATA_MODEL) {
1569
+ return;
1570
+ }
1571
+ const rewrite = this.getOmniScriptURLRewrite(stateAction);
1572
+ if (!rewrite) {
1573
+ return;
1574
+ }
1575
+ const { targetName, updatedURL, malformedTokens } = rewrite;
1576
+ stateAction[stringContants_1.Constants.WebPageTargetType].targetName = updatedURL;
1577
+ const summary = this.formatURLRewriteSummary(targetName, updatedURL);
1578
+ urlUpdateSummaries.add(summary);
1579
+ // Per-card collector is optional so internal/test callers can omit it
1580
+ // without forcing a signature update. The Map is keyed by the rewrite
1581
+ // summary so the emission step can later subtract malformed URLs from
1582
+ // the aggregate "Updated URLs: ..." locations message -- each malformed
1583
+ // entry already carries the original URL, the rewritten URL, and the
1584
+ // verify instruction inside its own warning, so listing it twice would
1585
+ // be redundant. Same key for two actions on the same card => one entry.
1586
+ // Defense-in-depth: skip if the formatter returns an empty string so we
1587
+ // never store a blank warning under a real summary key.
1588
+ if (malformedFragmentWarnings && Array.isArray(malformedTokens) && malformedTokens.length > 0) {
1589
+ const malformedWarning = this.formatMalformedFragmentTokenWarning(targetName, updatedURL, malformedTokens);
1590
+ if (malformedWarning) {
1591
+ malformedFragmentWarnings.set(summary, malformedWarning);
1592
+ }
1593
+ }
1594
+ }
1595
+ /** Build a human-readable "before -> after" string for warning messages only. */
1596
+ formatURLRewriteSummary(originalURL, updatedURL) {
1597
+ return `${this.toReadableURL(originalURL)} -> ${this.toReadableURL(updatedURL)}`;
1598
+ }
1599
+ /**
1600
+ * Decode a URL for DISPLAY purposes only (warning/log messages). The output
1601
+ * is lossy with respect to URL parsing semantics (e.g. an encoded `%26`
1602
+ * becomes a literal `&`) and must NOT be re-fed into a URL parser. Falls
1603
+ * back to the raw input on malformed percent sequences.
1604
+ */
1605
+ toReadableURL(url) {
1606
+ try {
1607
+ return decodeURIComponent(url);
1608
+ }
1609
+ catch {
1610
+ return url;
1611
+ }
1612
+ }
1613
+ getOmniScriptURLRewrite(stateAction) {
1614
+ var _a;
1615
+ const targetName = (_a = stateAction[stringContants_1.Constants.WebPageTargetType]) === null || _a === void 0 ? void 0 : _a.targetName;
1616
+ if (typeof targetName !== 'string') {
1617
+ return undefined;
1618
+ }
1619
+ // Fast reject: if the raw text doesn't even mention the universal-page
1620
+ // path or token, skip URL parsing entirely. This is a substring screen,
1621
+ // not a security check; the strict structural validation happens after
1622
+ // parsing in isValidOmniScriptNavigationURL.
1623
+ if (!targetName.includes(stringContants_1.Constants.OmniScriptUniversalPagePath) ||
1624
+ !targetName.includes(stringContants_1.Constants.OmniScriptUniversalPageToken)) {
1625
+ return undefined;
1626
+ }
1627
+ const parsedURL = this.tryParseURL(targetName);
1628
+ if (!parsedURL || !this.isValidOmniScriptNavigationURL(parsedURL)) {
1629
+ return undefined;
1630
+ }
1631
+ const updatedURL = this.convertToStandardOmniScriptURL(parsedURL);
1632
+ // Re-parse the fragment once more here purely to capture malformed-token
1633
+ // diagnostics for the caller. Cheap (single split + map over a short
1634
+ // string) and keeps `convertToStandardOmniScriptURL` focused on rewriting.
1635
+ const { malformedTokens } = this.parseSlashFragmentParams(parsedURL.hash);
1636
+ return { targetName, updatedURL, malformedTokens };
1637
+ }
1638
+ isCustomWebPageAction(stateAction) {
1639
+ return (stateAction === null || stateAction === void 0 ? void 0 : stateAction.type) === stringContants_1.Constants.CustomActionType && (stateAction === null || stateAction === void 0 ? void 0 : stateAction.targetType) === stringContants_1.Constants.WebPageTargetType;
1640
+ }
1641
+ /**
1642
+ * Parse a URL string without throwing. Returns the parsed URL on success or
1643
+ * undefined for:
1644
+ * - syntactically invalid input (e.g. `https://[bad`, raw spaces in host,
1645
+ * `http:///` with no host), or
1646
+ * - URLs whose scheme is not `http:` or `https:` (e.g. `javascript:`,
1647
+ * `data:`, `file:`, `mailto:`).
1648
+ *
1649
+ * See URL_PARSE_BASE for why a synthetic base is supplied.
1650
+ */
1651
+ tryParseURL(input) {
1652
+ let parsed;
1653
+ try {
1654
+ parsed = new URL(input, CardMigrationTool.URL_PARSE_BASE);
1655
+ }
1656
+ catch {
1657
+ return undefined;
1658
+ }
1659
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
1660
+ return undefined;
1661
+ }
1662
+ return parsed;
1663
+ }
1664
+ /**
1665
+ * Verify a parsed URL has the OmniScript Navigate shape. We validate against
1666
+ * the parsed components (pathname / searchParams / hash) rather than doing
1667
+ * substring matches on the raw input so callers cannot smuggle the required
1668
+ * tokens in unrelated positions (e.g. inside another query value).
1669
+ *
1670
+ * The pathname must START WITH `/apex/` and contain the universal-page
1671
+ * token. Anchoring to the prefix rejects non-http(s) schemes such as
1672
+ * `javascript:alert(1)//apex/...` whose parsed pathname does not begin
1673
+ * with `/` (it begins with the opaque body of the scheme).
1674
+ *
1675
+ * Two legitimate shapes are accepted:
1676
+ * 1. Path + query: /apex/<ns>__OmniScriptUniversalPage?OmniScriptType=...&OmniScriptSubType=...&OmniScriptLang=...
1677
+ * 2. Path + fragment: /apex/<ns>__OmniScriptUniversalPage?...#/OmniScriptType/.../OmniScriptSubType/.../OmniScriptLang/...
1678
+ */
1679
+ isValidOmniScriptNavigationURL(parsedURL) {
1680
+ if (!parsedURL.pathname.startsWith(`${stringContants_1.Constants.OmniScriptUniversalPagePath}/`)) {
1681
+ return false;
1682
+ }
1683
+ if (!parsedURL.pathname.includes(stringContants_1.Constants.OmniScriptUniversalPageToken)) {
1684
+ return false;
1685
+ }
1686
+ const fragmentKeys = new Set(this.parseSlashFragmentParams(parsedURL.hash).pairs.map(([key]) => key));
1687
+ const hasParam = (key) => parsedURL.searchParams.has(key) || fragmentKeys.has(key);
1688
+ return (hasParam(stringContants_1.Constants.OmniScriptTypeParam) &&
1689
+ hasParam(stringContants_1.Constants.OmniScriptSubTypeParam) &&
1690
+ hasParam(stringContants_1.Constants.OmniScriptLangParam));
1691
+ }
1692
+ convertToStandardOmniScriptURL(parsedURL) {
1693
+ var _a;
1694
+ const paramRenames = {
1695
+ [stringContants_1.Constants.OmniScriptTypeParam]: stringContants_1.Constants.OmniScriptStandardTypeParam,
1696
+ [stringContants_1.Constants.OmniScriptSubTypeParam]: stringContants_1.Constants.OmniScriptStandardSubTypeParam,
1697
+ [stringContants_1.Constants.OmniScriptLangParam]: stringContants_1.Constants.OmniScriptStandardLanguageParam,
1698
+ [stringContants_1.Constants.OmniScriptLayoutParam]: stringContants_1.Constants.OmniScriptStandardThemeParam,
1699
+ };
1700
+ const paramsToClean = new Set([stringContants_1.Constants.OmniScriptTypeParam, stringContants_1.Constants.OmniScriptSubTypeParam]);
1701
+ // Merge query-string params with fragment params. Query-string entries win on conflict.
1702
+ const mergedEntries = [];
1703
+ const seenKeys = new Set();
1704
+ parsedURL.searchParams.forEach((value, key) => {
1705
+ mergedEntries.push([key, value]);
1706
+ seenKeys.add(key);
1707
+ });
1708
+ for (const [key, value] of this.parseSlashFragmentParams(parsedURL.hash).pairs) {
1709
+ if (!seenKeys.has(key)) {
1710
+ mergedEntries.push([key, value]);
1711
+ seenKeys.add(key);
1712
+ }
1713
+ }
1714
+ const newSearchParams = new URLSearchParams();
1715
+ for (const [key, value] of mergedEntries) {
1716
+ const newKey = (_a = paramRenames[key]) !== null && _a !== void 0 ? _a : key;
1717
+ const newValue = paramsToClean.has(key) ? this.cleanName(value) : value;
1718
+ newSearchParams.append(newKey, newValue);
1719
+ }
1720
+ return `${stringContants_1.Constants.OmniScriptStandardPagePath}?${newSearchParams.toString()}`;
1721
+ }
1722
+ /**
1723
+ * Parse a slash-separated OmniScript fragment of the form
1724
+ * #/Key1/Value1/Key2/Value2/...
1725
+ * into [key, value] pairs. Tolerates leading `#`, leading `/`, empty values
1726
+ * (consecutive slashes), and a trailing orphan token (which is dropped).
1727
+ *
1728
+ * Tokens with malformed percent sequences (e.g. `Foo%`, `Bar%E2`) are kept
1729
+ * as-is rather than throwing; decodeURIComponent raises URIError on invalid
1730
+ * escape sequences and we don't want one bad token to crash the whole
1731
+ * FlexCard's URL rewrite. The raw (still-encoded) tokens are also returned
1732
+ * via `malformedTokens` so callers can surface them to customers as a
1733
+ * "please verify" warning rather than silently shipping a best-effort guess.
1734
+ */
1735
+ parseSlashFragmentParams(hash) {
1736
+ if (!hash) {
1737
+ return { pairs: [], malformedTokens: [] };
1738
+ }
1739
+ const trimmed = hash.replace(/^#\/?/, '');
1740
+ if (!trimmed) {
1741
+ return { pairs: [], malformedTokens: [] };
1742
+ }
1743
+ const malformedTokens = [];
1744
+ const tokens = trimmed.split('/').map((t) => {
1745
+ try {
1746
+ return decodeURIComponent(t);
1747
+ }
1748
+ catch {
1749
+ malformedTokens.push(t);
1750
+ return t;
1751
+ }
1752
+ });
1753
+ const pairs = [];
1754
+ for (let i = 0; i + 1 < tokens.length; i += 2) {
1755
+ pairs.push([tokens[i], tokens[i + 1]]);
1756
+ }
1757
+ return { pairs, malformedTokens };
1758
+ }
1759
+ /**
1760
+ * Update omniType.Name using registry (handles Type/SubType/Language format)
1761
+ */
1762
+ updateOmniTypeNameWithRegistry(omniType) {
1763
+ const originalName = omniType.Name || '';
1764
+ const parts = originalName.split('/');
1765
+ if (parts.length >= 3) {
1766
+ // Construct full OmniScript name: Type_SubType_Language
1767
+ const fullOmniScriptName = `${parts[0]}_${parts[1]}_${parts[2]}`;
1768
+ if (this.nameRegistry.hasOmniScriptMapping(fullOmniScriptName)) {
1769
+ // Registry has mapping - extract cleaned parts and convert back to / format
1770
+ const cleanedFullName = this.nameRegistry.getCleanedName(fullOmniScriptName, 'OmniScript');
1771
+ const cleanedParts = cleanedFullName.split('_');
1772
+ if (cleanedParts.length >= 3) {
1773
+ omniType.Name = cleanedParts.join('/');
1774
+ }
1775
+ }
1776
+ else {
1777
+ // No registry mapping - use original fallback approach
1778
+ logger_1.Logger.logVerbose(`\n${this.messages.getMessage('componentMappingNotFound', ['Omniscript', fullOmniScriptName])}`);
1779
+ omniType.Name =
1780
+ parts.length >= 3
1781
+ ? `${this.cleanName(parts[0])}/${this.cleanName(parts[1])}/${parts[2]}`
1782
+ : parts.map((p) => this.cleanName(p)).join('/');
1783
+ }
1784
+ }
1785
+ else {
1786
+ // Fallback for unexpected format
1787
+ omniType.Name = parts.map((p) => this.cleanName(p)).join('/');
1788
+ }
1789
+ }
1790
+ /**
1791
+ * Update osName using registry (handles Type/SubType/Language format)
1792
+ */
1793
+ updateOsNameWithRegistry(stateAction, fieldName) {
1794
+ const originalOsName = stateAction[fieldName];
1795
+ const parts = originalOsName.split('/');
1796
+ if (parts.length >= 3) {
1797
+ // Construct full OmniScript name: Type_SubType_Language
1798
+ const fullOmniScriptName = `${parts[0]}_${parts[1]}_${parts[2]}`;
1799
+ if (this.nameRegistry.hasOmniScriptMapping(fullOmniScriptName)) {
1800
+ // Registry has mapping - extract cleaned parts and convert back to / format
1801
+ const cleanedFullName = this.nameRegistry.getCleanedName(fullOmniScriptName, 'OmniScript');
1802
+ const cleanedParts = cleanedFullName.split('_');
1803
+ if (cleanedParts.length >= 3) {
1804
+ stateAction[fieldName] = cleanedParts.join('/');
1805
+ }
1806
+ }
1807
+ else {
1808
+ // No registry mapping - use original fallback approach
1809
+ logger_1.Logger.logVerbose(this.messages.getMessage('componentMappingNotFound', ['Omniscript', fullOmniScriptName]));
1810
+ stateAction[fieldName] =
1811
+ parts.length >= 3
1812
+ ? `${this.cleanName(parts[0])}/${this.cleanName(parts[1])}/${parts[2]}`
1813
+ : parts.map((p) => this.cleanName(p)).join('/');
1814
+ }
1815
+ }
1816
+ else {
1817
+ // Fallback for unexpected format
1818
+ stateAction[fieldName] = parts.map((p) => this.cleanName(p)).join('/');
1819
+ }
1820
+ }
1821
+ // ==================== Assessment Helper Methods ====================
1822
+ /**
1823
+ * Helper method to add OmniScript dependency and warnings during assessment
1824
+ * Handles osName in format "Type/SubType/Language" or "Type/SubType"
1825
+ * @param osName - OmniScript name in format "Type/SubType" or "Type/SubType/Language"
1826
+ * @param flexCardAssessmentInfo - Assessment info to update
1827
+ */
1828
+ addOmniScriptDependency(osName, flexCardAssessmentInfo) {
1829
+ if (!osName || typeof osName !== 'string') {
1830
+ return;
1831
+ }
1832
+ const parts = osName.split('/');
1833
+ if (parts.length < 2) {
1834
+ return;
1835
+ }
1836
+ const originalOsRef = parts.join('_');
1837
+ // Skip if already processed
1838
+ if (flexCardAssessmentInfo.dependenciesOS.includes(originalOsRef)) {
1839
+ return;
1840
+ }
1841
+ // Clean parts - preserve language (3rd part) as-is
1842
+ const cleanedParts = parts.length >= 3
1843
+ ? [this.cleanName(parts[0]), this.cleanName(parts[1]), parts[2]]
1844
+ : parts.map((p) => this.cleanName(p));
1845
+ const cleanedOsRef = cleanedParts.join('_');
1846
+ // Add to dependencies
1847
+ flexCardAssessmentInfo.dependenciesOS.push(originalOsRef);
1848
+ // Add warning if name will change
1849
+ if (originalOsRef !== cleanedOsRef) {
1850
+ flexCardAssessmentInfo.warnings.push(this.messages.getMessage('omniScriptNameChangeMessage', [originalOsRef, cleanedOsRef]));
1851
+ flexCardAssessmentInfo.migrationStatus = (0, stringUtils_1.getUpdatedAssessmentStatus)(flexCardAssessmentInfo.migrationStatus, 'Warnings');
1852
+ }
1853
+ }
1854
+ /**
1855
+ * Helper method to add OmniScript dependency from type/subtype/language fields
1856
+ * @param type - OmniScript type
1857
+ * @param subtype - OmniScript subtype
1858
+ * @param language - OmniScript language (defaults to 'English')
1859
+ * @param flexCardAssessmentInfo - Assessment info to update
1860
+ */
1861
+ addOmniScriptDependencyFromParts(type, subtype, language, flexCardAssessmentInfo) {
1862
+ if (!type || !subtype) {
1863
+ return;
1864
+ }
1865
+ const lang = language || 'English';
1866
+ const originalOsRef = `${type}_${subtype}_${lang}`;
1867
+ // Skip if already processed
1868
+ if (flexCardAssessmentInfo.dependenciesOS.includes(originalOsRef)) {
1869
+ return;
1870
+ }
1871
+ const cleanedOsRef = `${this.cleanName(type)}_${this.cleanName(subtype)}_${lang}`;
1872
+ // Add to dependencies
1873
+ flexCardAssessmentInfo.dependenciesOS.push(originalOsRef);
1874
+ // Add warning if name will change
1875
+ if (originalOsRef !== cleanedOsRef) {
1876
+ flexCardAssessmentInfo.warnings.push(this.messages.getMessage('omniScriptNameChangeMessage', [originalOsRef, cleanedOsRef]));
1877
+ flexCardAssessmentInfo.migrationStatus = (0, stringUtils_1.getUpdatedAssessmentStatus)(flexCardAssessmentInfo.migrationStatus, 'Warnings');
1878
+ }
1879
+ }
1880
+ /**
1881
+ * Helper method to add DataRaptor dependency and warnings during assessment
1882
+ * @param bundle - DataRaptor bundle name
1883
+ * @param flexCardAssessmentInfo - Assessment info to update
1884
+ */
1885
+ addDataRaptorDependency(bundle, flexCardAssessmentInfo) {
1886
+ if (!bundle || flexCardAssessmentInfo.dependenciesDR.includes(bundle)) {
1887
+ return;
1888
+ }
1889
+ const cleanedBundle = this.cleanName(bundle);
1890
+ flexCardAssessmentInfo.dependenciesDR.push(bundle);
1891
+ if (bundle !== cleanedBundle) {
1892
+ flexCardAssessmentInfo.warnings.push(this.messages.getMessage('dataRaptorNameChangeMessage', [bundle, cleanedBundle]));
1893
+ flexCardAssessmentInfo.migrationStatus = (0, stringUtils_1.getUpdatedAssessmentStatus)(flexCardAssessmentInfo.migrationStatus, 'Warnings');
1894
+ }
1895
+ }
1896
+ /**
1897
+ * Helper method to add Integration Procedure dependency and warnings during assessment
1898
+ * @param ipMethod - Integration Procedure method name (Type_SubType format)
1899
+ * @param flexCardAssessmentInfo - Assessment info to update
1900
+ */
1901
+ addIntegrationProcedureDependency(ipMethod, flexCardAssessmentInfo) {
1902
+ if (!ipMethod || flexCardAssessmentInfo.dependenciesIP.includes(ipMethod)) {
1903
+ return;
1904
+ }
1905
+ const parts = ipMethod.split('_');
1906
+ const cleanedParts = parts.map((p) => this.cleanName(p, true));
1907
+ const cleanedIpMethod = cleanedParts.join('_');
1908
+ flexCardAssessmentInfo.dependenciesIP.push(ipMethod);
1909
+ if (ipMethod !== cleanedIpMethod) {
1910
+ flexCardAssessmentInfo.warnings.push(this.messages.getMessage('integrationProcedureNameChangeMessage', [ipMethod, cleanedIpMethod]));
1911
+ flexCardAssessmentInfo.migrationStatus = (0, stringUtils_1.getUpdatedAssessmentStatus)(flexCardAssessmentInfo.migrationStatus, 'Warnings');
1912
+ }
1913
+ // Add manual intervention warning if IP has more than 2 parts
1914
+ if (parts.length > 2) {
1915
+ flexCardAssessmentInfo.warnings.push(this.messages.getMessage('integrationProcedureManualUpdateMessage', [ipMethod]));
1916
+ flexCardAssessmentInfo.migrationStatus = (0, stringUtils_1.getUpdatedAssessmentStatus)(flexCardAssessmentInfo.migrationStatus, 'Needs manual intervention');
1917
+ }
1918
+ }
1919
+ /**
1920
+ * Helper method to add FlexCard dependency and warnings during assessment
1921
+ * @param cardName - FlexCard name
1922
+ * @param flexCardAssessmentInfo - Assessment info to update
1923
+ */
1924
+ addFlexCardDependency(cardName, flexCardAssessmentInfo) {
1925
+ if (!cardName || flexCardAssessmentInfo.dependenciesFC.includes(cardName)) {
1926
+ return;
1927
+ }
1928
+ const cleanedCardName = this.cleanName(cardName);
1929
+ flexCardAssessmentInfo.dependenciesFC.push(cardName);
1930
+ if (cardName !== cleanedCardName) {
1931
+ flexCardAssessmentInfo.warnings.push(this.messages.getMessage('cardNameChangeMessage', [cardName, cleanedCardName]));
1932
+ flexCardAssessmentInfo.migrationStatus = (0, stringUtils_1.getUpdatedAssessmentStatus)(flexCardAssessmentInfo.migrationStatus, 'Warnings');
1933
+ }
1934
+ }
1935
+ /**
1936
+ * Helper method to flag a Vlocity Action dependency during assessment.
1937
+ * Vlocity Actions are not supported in standard runtime FlexCards, so the
1938
+ * FlexCard cannot be auto-migrated and must be manually reimplemented using
1939
+ * the FlexCard Action (cardAction) feature.
1940
+ */
1941
+ addVlocityActionDependency(stateAction, flexCardAssessmentInfo) {
1942
+ const actionName = stateAction.name || stateAction.displayName || 'Unnamed Vlocity Action';
1943
+ if (!flexCardAssessmentInfo.dependenciesVlocityAction.includes(actionName)) {
1944
+ flexCardAssessmentInfo.dependenciesVlocityAction.push(actionName);
1945
+ }
1946
+ const warning = this.messages.getMessage('vlocityActionNotSupportedMessage', [actionName]);
1947
+ if (!flexCardAssessmentInfo.warnings.includes(warning)) {
1948
+ flexCardAssessmentInfo.warnings.push(warning);
1949
+ }
1950
+ flexCardAssessmentInfo.migrationStatus = (0, stringUtils_1.getUpdatedAssessmentStatus)(flexCardAssessmentInfo.migrationStatus, 'Needs manual intervention');
1951
+ }
1952
+ // ==================== End Assessment Helper Methods ====================
677
1953
  getCardFields() {
678
- return Object.keys(VlocityCard_1.default);
1954
+ return this.IS_STANDARD_DATA_MODEL
1955
+ ? Object.values(VlocityCard_1.default).filter((value) => value !== '')
1956
+ : Object.keys(VlocityCard_1.default);
1957
+ }
1958
+ getFieldKey(fieldName) {
1959
+ return this.IS_STANDARD_DATA_MODEL ? VlocityCard_1.default[fieldName] : this.namespacePrefix + fieldName;
1960
+ }
1961
+ getQueryNamespace() {
1962
+ return this.IS_STANDARD_DATA_MODEL ? '' : this.namespace;
1963
+ }
1964
+ getCardObjectName() {
1965
+ return this.IS_STANDARD_DATA_MODEL ? CardMigrationTool.OMNIUICARD_NAME : CardMigrationTool.VLOCITYCARD_NAME;
1966
+ }
1967
+ /**
1968
+ * Check if a FlexCard has dependencies on Angular OmniScripts
1969
+ */
1970
+ hasAngularOmniScriptDependencies(card) {
1971
+ try {
1972
+ const definition = JSON.parse(card[this.getFieldKey('Definition__c')] || '{}');
1973
+ if (definition && definition.states) {
1974
+ for (const state of definition.states) {
1975
+ // Check direct OmniScript references in states
1976
+ if (state.omniscripts && Array.isArray(state.omniscripts)) {
1977
+ for (const os of state.omniscripts) {
1978
+ if (os.type && os.subtype) {
1979
+ const osRef = `${os.type}_${os.subtype}_${os.language || 'English'}`;
1980
+ if (this.nameRegistry.isAngularOmniScript(osRef)) {
1981
+ return true;
1982
+ }
1983
+ }
1984
+ }
1985
+ }
1986
+ // Check OmniScript references in component actions
1987
+ if (state.components) {
1988
+ for (const componentKey in state.components) {
1989
+ if (state.components.hasOwnProperty(componentKey)) {
1990
+ const component = state.components[componentKey];
1991
+ if (this.componentHasAngularOmniScriptDependency(component)) {
1992
+ return true;
1993
+ }
1994
+ }
1995
+ }
1996
+ }
1997
+ }
1998
+ }
1999
+ // Check OmniScript references in events[] array
2000
+ if (definition && definition.events && Array.isArray(definition.events)) {
2001
+ if (this.eventsHaveAngularOmniScriptDependency(definition.events)) {
2002
+ return true;
2003
+ }
2004
+ }
2005
+ }
2006
+ catch (err) {
2007
+ logger_1.Logger.error(`Error checking Angular dependencies for card ${card['Name']}: ${err.message}`);
2008
+ }
2009
+ return false;
2010
+ }
2011
+ /**
2012
+ * Check if events array has Angular OmniScript dependencies
2013
+ */
2014
+ eventsHaveAngularOmniScriptDependency(events) {
2015
+ for (const event of events) {
2016
+ if (!event.actionList || !Array.isArray(event.actionList)) {
2017
+ continue;
2018
+ }
2019
+ for (const action of event.actionList) {
2020
+ if (!action.stateAction) {
2021
+ continue;
2022
+ }
2023
+ const stateAction = action.stateAction;
2024
+ // Check omniType.Name
2025
+ if (stateAction.omniType) {
2026
+ if (this.checkOmniTypeForAngular(stateAction.omniType)) {
2027
+ return true;
2028
+ }
2029
+ }
2030
+ if (this.hasOmniscriptFlyoutDependency(stateAction)) {
2031
+ if (this.checkOsNameForAngular(stateAction.osName)) {
2032
+ return true;
2033
+ }
2034
+ }
2035
+ }
2036
+ }
2037
+ return false;
2038
+ }
2039
+ hasOmniscriptFlyoutDependency(stateAction) {
2040
+ return (stateAction.type === stringContants_1.Constants.Flyout &&
2041
+ stateAction.flyoutType === stringContants_1.Constants.OmniScriptPluralName &&
2042
+ stateAction.osName);
2043
+ }
2044
+ hasFlexCardFlyoutDependency(stateAction) {
2045
+ return (stateAction.type === stringContants_1.Constants.Flyout && stateAction.flyoutType === stringContants_1.Constants.ChildCard && stateAction.flyoutLwc);
2046
+ }
2047
+ hasCustomLwcFlyoutDependency(stateAction) {
2048
+ return (stateAction.type === stringContants_1.Constants.Flyout && stateAction.flyoutType === stringContants_1.Constants.CustomLwc && stateAction.flyoutLwc);
2049
+ }
2050
+ hasFlyoutLwc(stateAction) {
2051
+ return stateAction.type === stringContants_1.Constants.Flyout && stateAction.flyoutLwc;
2052
+ }
2053
+ /**
2054
+ * Recursively check if a component has Angular Omniscript dependencies
2055
+ */
2056
+ componentHasAngularOmniScriptDependency(component) {
2057
+ // Pattern 1: Handle action elements with actionList (like migration logic)
2058
+ if (component.element === 'action' && component.property && component.property.actionList) {
2059
+ for (const action of component.property.actionList) {
2060
+ if (action.stateAction) {
2061
+ // Case 1: Direct OmniScript reference with type check
2062
+ if (action.stateAction.type === stringContants_1.Constants.OmniScriptComponentName && action.stateAction.omniType) {
2063
+ if (this.checkOmniTypeForAngular(action.stateAction.omniType)) {
2064
+ return true;
2065
+ }
2066
+ }
2067
+ // Case 1b: Direct OmniScript reference without type check (for test compatibility)
2068
+ else if (action.stateAction.omniType && !action.stateAction.type) {
2069
+ if (this.checkOmniTypeForAngular(action.stateAction.omniType)) {
2070
+ return true;
2071
+ }
2072
+ }
2073
+ // Case 2: Flyout OmniScript reference
2074
+ else if (this.hasOmniscriptFlyoutDependency(action.stateAction)) {
2075
+ if (this.checkOsNameForAngular(action.stateAction.osName)) {
2076
+ return true;
2077
+ }
2078
+ }
2079
+ }
2080
+ }
2081
+ }
2082
+ // Pattern 2: Handle standard component actions (like migration logic)
2083
+ if (component.actions && Array.isArray(component.actions)) {
2084
+ for (const action of component.actions) {
2085
+ if (action.stateAction && action.stateAction.omniType) {
2086
+ if (this.checkOmniTypeForAngular(action.stateAction.omniType)) {
2087
+ return true;
2088
+ }
2089
+ }
2090
+ }
2091
+ }
2092
+ // Pattern 3: Handle direct stateAction on component property (like migration logic)
2093
+ if (component.property && component.property.stateAction) {
2094
+ if (component.property.stateAction.omniType) {
2095
+ if (this.checkOmniTypeForAngular(component.property.stateAction.omniType)) {
2096
+ return true;
2097
+ }
2098
+ }
2099
+ if (this.hasOmniscriptFlyoutDependency(component.property.stateAction)) {
2100
+ if (this.checkOsNameForAngular(component.property.stateAction.osName)) {
2101
+ return true;
2102
+ }
2103
+ }
2104
+ }
2105
+ // Pattern 4: Handle omni-flyout elements (for test compatibility)
2106
+ if (component.element === stringContants_1.Constants.OmniFlyout && component.property && component.property.flyoutOmniScript) {
2107
+ if (component.property.flyoutOmniScript.osName) {
2108
+ if (this.checkOsNameForAngular(component.property.flyoutOmniScript.osName)) {
2109
+ return true;
2110
+ }
2111
+ }
2112
+ }
2113
+ // Recursively check child components
2114
+ if (component.children && Array.isArray(component.children)) {
2115
+ for (const child of component.children) {
2116
+ if (this.componentHasAngularOmniScriptDependency(child)) {
2117
+ return true;
2118
+ }
2119
+ }
2120
+ }
2121
+ return false;
2122
+ }
2123
+ /**
2124
+ * Check if an omniType references an Angular OmniScript
2125
+ * Handles both string format and object with Name property
2126
+ */
2127
+ checkOmniTypeForAngular(omniType) {
2128
+ if (!omniType) {
2129
+ return false;
2130
+ }
2131
+ // Check if IsWebCompEnabled is explicitly false (Angular OmniScript)
2132
+ if (typeof omniType === 'object' && omniType.IsWebCompEnabled === false) {
2133
+ return true;
2134
+ }
2135
+ let omniTypeName;
2136
+ // Handle both string omniType and object with Name property
2137
+ if (typeof omniType === 'string') {
2138
+ omniTypeName = omniType;
2139
+ }
2140
+ else if (omniType.Name && typeof omniType.Name === 'string') {
2141
+ omniTypeName = omniType.Name;
2142
+ }
2143
+ else {
2144
+ return false;
2145
+ }
2146
+ const parts = omniTypeName.split('/');
2147
+ if (parts.length >= 3) {
2148
+ // Construct full OmniScript name: Type_SubType_Language
2149
+ const fullOmniScriptName = `${parts[0]}_${parts[1]}_${parts[2]}`;
2150
+ return this.nameRegistry.isAngularOmniScript(fullOmniScriptName);
2151
+ }
2152
+ return false;
2153
+ }
2154
+ /**
2155
+ * Check if an osName string references an Angular OmniScript
2156
+ * Handles Type/SubType/Language format in string
2157
+ */
2158
+ checkOsNameForAngular(osName) {
2159
+ if (!osName || typeof osName !== 'string') {
2160
+ return false;
2161
+ }
2162
+ const parts = osName.split('/');
2163
+ if (parts.length >= 3) {
2164
+ // Construct full OmniScript name: Type_SubType_Language
2165
+ const fullOmniScriptName = `${parts[0]}_${parts[1]}_${parts[2]}`;
2166
+ return this.nameRegistry.isAngularOmniScript(fullOmniScriptName);
2167
+ }
2168
+ return false;
2169
+ }
2170
+ /**
2171
+ * Ensures that the FlexCard Definition includes required Lightning Community targets
2172
+ * Adds "lightningCommunity__Page" and "lightningCommunity__Default" if missing
2173
+ * This is needed as vlocity wrapper can have flexcard which is unpublished but omniwapper needs published card
2174
+ */
2175
+ ensureCommunityTargets(mappedObject, isCardActive) {
2176
+ if (!isCardActive) {
2177
+ return;
2178
+ }
2179
+ const definition = JSON.parse(mappedObject[VlocityCard_1.default.Definition__c] || '{}');
2180
+ if (!definition || !definition.xmlObject) {
2181
+ return;
2182
+ }
2183
+ // Initialize targets structure if it doesn't exist
2184
+ if (!definition.xmlObject.targets) {
2185
+ definition.xmlObject.targets = { target: [] };
2186
+ }
2187
+ // Ensure target is an array
2188
+ if (!Array.isArray(definition.xmlObject.targets.target)) {
2189
+ definition.xmlObject.targets.target = [];
2190
+ }
2191
+ const requiredTargets = [
2192
+ 'lightning__RecordPage',
2193
+ 'lightning__AppPage',
2194
+ 'lightning__HomePage',
2195
+ 'lightningCommunity__Page',
2196
+ 'lightningCommunity__Default',
2197
+ ];
2198
+ const currentTargets = definition.xmlObject.targets.target;
2199
+ // Add missing community targets
2200
+ for (const requiredTarget of requiredTargets) {
2201
+ if (!currentTargets.includes(requiredTarget)) {
2202
+ currentTargets.push(requiredTarget);
2203
+ }
2204
+ }
2205
+ logger_1.Logger.logVerbose(`Targets processed`);
2206
+ // Save the updated definition back to the mappedObject
2207
+ mappedObject[VlocityCard_1.default.Definition__c] = JSON.stringify(definition);
2208
+ }
2209
+ /**
2210
+ * Prioritizes FlexCards by name characteristics:
2211
+ * - Clean names (alphanumeric only) are processed first
2212
+ * - Names with special characters are processed after
2213
+ * This avoids naming conflicts during migration when special characters are cleaned
2214
+ */
2215
+ prioritizeFlexCardsWithoutSpecialCharacters(flexCards) {
2216
+ const nameField = this.getFieldKey('Name');
2217
+ return (0, recordPrioritization_1.prioritizeCleanNamesFirst)(flexCards, nameField);
679
2218
  }
680
2219
  }
681
2220
  exports.CardMigrationTool = CardMigrationTool;
682
2221
  CardMigrationTool.VLOCITYCARD_NAME = 'VlocityCard__c';
683
2222
  CardMigrationTool.OMNIUICARD_NAME = 'OmniUiCard';
684
2223
  CardMigrationTool.VERSION_PROP = 'Version__c';
2224
+ CardMigrationTool.URL_PARSE_BASE = 'https://placeholder.local';
685
2225
  //# sourceMappingURL=flexcard.js.map