@oracle/oraclejet-audit 16.1.3 → 17.0.0

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 (145) hide show
  1. package/corePackMigrator/cli.js +1 -1
  2. package/corePackMigrator/corePackMigrator.js +2 -2
  3. package/corePackMigrator/metadata/actionCardMetadata.json +10 -0
  4. package/corePackMigrator/metadata/avatarMetadata.json +11 -1
  5. package/corePackMigrator/metadata/bindIfMetadata.json +4 -0
  6. package/corePackMigrator/metadata/buttonMetadata.json +65 -49
  7. package/corePackMigrator/metadata/chartMetadata.json +53 -0
  8. package/corePackMigrator/metadata/collapsibleMetadata.json +27 -12
  9. package/corePackMigrator/metadata/conveyorBeltMetadata.json +34 -0
  10. package/corePackMigrator/metadata/datePickerMetadata.json +43 -0
  11. package/corePackMigrator/metadata/drawerLayoutMetadata.json +18 -0
  12. package/corePackMigrator/metadata/drawerPopupMetadata.json +27 -14
  13. package/corePackMigrator/metadata/filePickerMetadata.json +20 -7
  14. package/corePackMigrator/metadata/formLayoutMetadata.json +11 -1
  15. package/corePackMigrator/metadata/highlightTextMetadata.json +10 -0
  16. package/corePackMigrator/metadata/inputDateMetadata.json +110 -0
  17. package/corePackMigrator/metadata/inputNumberMetadata.json +107 -75
  18. package/corePackMigrator/metadata/inputPasswordMetadata.json +111 -75
  19. package/corePackMigrator/metadata/inputTextMetadata.json +118 -81
  20. package/corePackMigrator/metadata/labelValueMetadata.json +245 -0
  21. package/corePackMigrator/metadata/legendItemMetadata.json +11 -1
  22. package/corePackMigrator/metadata/legendMetadata.json +59 -49
  23. package/corePackMigrator/metadata/listItemLayoutMetadata.json +11 -1
  24. package/corePackMigrator/metadata/listviewMetadata.json +104 -63
  25. package/corePackMigrator/metadata/messageBannerMetadata.json +10 -0
  26. package/corePackMigrator/metadata/messagesMetadata.json +11 -1
  27. package/corePackMigrator/metadata/progressBarMetadata.json +11 -1
  28. package/corePackMigrator/metadata/progressCircleMetadata.json +10 -0
  29. package/corePackMigrator/metadata/radiosetMetadata.json +11 -1
  30. package/corePackMigrator/metadata/ratingGaugeMetadata.json +113 -87
  31. package/corePackMigrator/metadata/selectManyMetadata.json +72 -42
  32. package/corePackMigrator/metadata/selectSingleMetadata.json +61 -46
  33. package/corePackMigrator/metadata/selectorMetadata.json +1 -1
  34. package/corePackMigrator/metadata/statusMeterGaugeMetadata.json +1 -1
  35. package/corePackMigrator/metadata/tagCloudMetadata.json +10 -0
  36. package/corePackMigrator/metadata/textAreaMetadata.json +88 -46
  37. package/corePackMigrator/resource/astUtils.js +1 -1
  38. package/corePackMigrator/resource/componentMigrator.js +1 -1
  39. package/corePackMigrator/resource/fileScanner.js +1 -1
  40. package/corePackMigrator/resource/htmlUtils.js +1 -1
  41. package/corePackMigrator/resource/manifest.json +137 -36
  42. package/corePackMigrator/resource/testUtils.js +6 -0
  43. package/corePackMigrator/templates/componentMetaData.json +118 -14
  44. package/corePackMigrator/templates/migrationConfig.json +4 -0
  45. package/corePackMigrator/utilities/deltaWebElementAPIs.js +6 -0
  46. package/corePackMigrator/utilities/logging.js +1 -1
  47. package/jaf-amd.js +1 -1
  48. package/lib/AstJson.js +1 -1
  49. package/lib/Components.js +1 -1
  50. package/lib/Config.js +1 -1
  51. package/lib/ConfigEx.js +6 -0
  52. package/lib/ConfigLib.js +1 -1
  53. package/lib/MetaLib.js +1 -1
  54. package/lib/OjCPack.js +1 -1
  55. package/lib/RegTypes.js +1 -1
  56. package/lib/RulePack.js +1 -1
  57. package/lib/RuleSet.js +1 -1
  58. package/lib/Rules.js +1 -1
  59. package/lib/TsxUtils.js +1 -1
  60. package/lib/checkage.js +1 -1
  61. package/lib/defaults.js +1 -1
  62. package/lib/extends.js +1 -1
  63. package/lib/migrator.js +1 -1
  64. package/lib/ns.js +1 -1
  65. package/libext/expparser.js +1 -1
  66. package/meta/16.1.0/jetauditmeta.js +1 -1
  67. package/meta/17.0.0/jetauditmeta.js +9 -0
  68. package/meta/metaverlist.json +1 -1
  69. package/package.json +3 -3
  70. package/profiles/best-practice.json +97 -78
  71. package/profiles/redwood-strict.json +22 -14
  72. package/rulepacks/csp/csp-json-unsafe-expr.js +1 -1
  73. package/rulepacks/jetwc/jetwc-bootstrap.js +1 -1
  74. package/rulepacks/jetwc/jetwc-css-scoping.js +1 -1
  75. package/rulepacks/jetwc/jetwc-displayname.js +1 -1
  76. package/rulepacks/jetwc/jetwc-jet-version.js +1 -1
  77. package/rulepacks/jetwc/jetwc-markdown-link.js +1 -1
  78. package/rulepacks/jetwc/jetwc-namespace.js +1 -1
  79. package/rulepacks/jetwc/jetwc-nls-languages.js +1 -1
  80. package/rulepacks/jetwc/jetwc-property-nesting.js +1 -1
  81. package/rulepacks/jetwc/jetwc-property-translatable.js +1 -1
  82. package/rulepacks/jetwc/jetwc-require-paths.js +1 -1
  83. package/rulepacks/jetwc/jetwc-reserved-property.js +1 -1
  84. package/rulepacks/jetwc/jetwc-schema.js +1 -1
  85. package/rulepacks/jetwc/jetwc-standard-files.js +1 -1
  86. package/rulepacks/jetwc/jetwc-vb-category.js +1 -1
  87. package/rulepacks/jetwc/rules.json +1 -1
  88. package/rulepacks/jetwc-lib/jetwcutils-auditComponentCacheManager.js +1 -1
  89. package/rulepacks/jetwc-lib/jetwcutils-commonListenerImpls.js +1 -1
  90. package/rulepacks/jetwc-lib/jetwcutils-componentAuditUtils.js +1 -1
  91. package/rulepacks/jetwc-lib/jetwcutils-componentFinder.js +1 -1
  92. package/rulepacks/jetwc-lib/jetwcutils-tsxUtils.js +1 -1
  93. package/rulepacks/jetwco/jetwco-bootstrap.js +1 -1
  94. package/rulepacks/jetwco/jetwco-component-api-baseline-changes.js +1 -1
  95. package/rulepacks/jetwco/jetwco-component-api-changes.js +1 -1
  96. package/rulepacks/jetwco/jetwco-component-api-controlled-changes.js +1 -1
  97. package/rulepacks/jetwco/jetwco-license-info.js +1 -1
  98. package/rulepacks/jetwco/jetwco-prerelease-cdn.js +1 -1
  99. package/rulepacks/jetwco/jetwco-validate-applied-audits.js +1 -1
  100. package/rulepacks/jetwco/rules.json +1 -1
  101. package/rules/jet/helpers/cssHelper.js +1 -1
  102. package/rules/jet/helpers/has-attrib-value.js +6 -0
  103. package/rules/jet/helpers/tsx/has-prop-value.js +6 -0
  104. package/rules/jet/msgid.json +1 -1
  105. package/rules/jet/oj-acc-button-label.js +6 -0
  106. package/rules/jet/oj-css-style-bp-display.js +1 -1
  107. package/rules/jet/oj-html-attr-expr-writeback.js +1 -1
  108. package/rules/jet/oj-html-bindif-test.js +1 -1
  109. package/rules/jet/oj-html-binding-as-slot-child.js +1 -1
  110. package/rules/jet/oj-html-bp-button-xs-chroming.js +6 -0
  111. package/rules/jet/oj-html-bp-title-to-tooltip.js +6 -0
  112. package/rules/jet/oj-html-button-size-chroming.js +6 -0
  113. package/rules/jet/oj-html-dlg-title.js +1 -1
  114. package/rules/jet/oj-html-form-bindif.js +1 -1
  115. package/rules/jet/oj-html-ko-comment.js +1 -1
  116. package/rules/jet/oj-html-ko-databind.js +1 -1
  117. package/rules/jet/oj-html-ojattr-value.js +1 -1
  118. package/rules/jet/oj-html-ojtag-ns.js +1 -1
  119. package/rules/jet/oj-html-redwood-clear-icon.js +6 -0
  120. package/rules/jet/oj-html-slot-default.js +1 -1
  121. package/rules/jet/oj-html-slot-pref-content.js +1 -1
  122. package/rules/jet/oj-html-style-abs-units.js +1 -1
  123. package/rules/jet/oj-html-style-bp-color.js +1 -1
  124. package/rules/jet/oj-html-style-bp-display.js +1 -1
  125. package/rules/jet/oj-html-style-bp-font-family.js +1 -1
  126. package/rules/jet/oj-html-style-bp-font.js +1 -1
  127. package/rules/jet/oj-html-style-bp-margin-padding.js +6 -0
  128. package/rules/jet/oj-html-wctag-maintenance.js +1 -1
  129. package/rules/jet/oj-tsx-acc-button-label.js +6 -0
  130. package/rules/jet/oj-tsx-bp-button-xs-chroming.js +6 -0
  131. package/rules/jet/oj-tsx-bp-title-to-tooltip.js +6 -0
  132. package/rules/jet/oj-tsx-button-size-chroming.js +6 -0
  133. package/rules/jet/oj-tsx-dlg-title.js +1 -1
  134. package/rules/jet/oj-tsx-form-bindif.js +1 -1
  135. package/rules/jet/oj-tsx-ojtag-ns.js +1 -1
  136. package/rules/jet/oj-tsx-redwood-clear-icon.js +6 -0
  137. package/rules/jet/oj-tsx-slot-default.js +6 -0
  138. package/rules/jet/oj-tsx-slot-pref-content.js +1 -1
  139. package/rules/jet/oj-tsx-style-abs-units.js +6 -0
  140. package/rules/jet/oj-tsx-style-bp-margin-padding.js +6 -0
  141. package/rules/jet/oj-tsx-wctag-maintenance.js +1 -1
  142. package/rules/jet/rules.json +1 -1
  143. package/schema/component-schema.json +1 -1
  144. package/src/JafCore.js +1 -1
  145. package/types/index.d.ts +3 -0
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const Utils=require("../jetwc-lib/jetwcutils-componentAuditUtils");const TsxUtils=require("../jetwc-lib/jetwcutils-tsxUtils");const ruleDef=function(){};ruleDef.prototype.getName=function(){return"jetwc-standard-files"};ruleDef.prototype.getShortDescription=function(){return"Checks for the existence of standard informational files"};ruleDef.prototype.getDescription=function(){return"This rule ensures that standard files such as readmes are included"};ruleDef.prototype.register=function(context){return{compjson:this._doAudit,Program:this._doVComponentAudit}};ruleDef.prototype._doAudit=function(context){const componentMetadata=context.suppData.obj;if(componentMetadata){const fullName=Utils.getComponentFullName(componentMetadata);this._checkForStandardFiles(context,fullName,componentMetadata.version,componentMetadata.type)}};ruleDef.prototype._doVComponentAudit=function(context){const componentInfo=TsxUtils.matchToVComponentImpl(context,context.filepath);if(componentInfo){this._checkForStandardFiles(context,componentInfo.fullName,componentInfo.version,"composite")}};ruleDef.prototype._checkForStandardFiles=function(context,fullName,version,componentType){const componentFiles=context.utils.fsUtils.readDir(Utils.getDirectoryName(context.filepath));const checkForFiles=context.rulePack.getRuleOptions().files;checkForFiles.forEach(requiredFile=>{let exclusion=false;switch(requiredFile.toLowerCase()){case"changelog.md":case"changelog.txt":case"changes.txt":if(componentType&&componentType==="reference"){exclusion=true}else{if(version&&context.utils.semVerUtils.gt("1.0.1",version)){exclusion=true}}break}if(!exclusion){let hits=componentFiles.filter(compFile=>compFile.name===requiredFile&&compFile.isFile);if(hits.length===0){const issue=new context.Issue(`Required supporting file ${requiredFile} is not present for component ${fullName}`);context.reporter.addIssue(issue,context)}}})};module.exports=ruleDef;
6
+ const Utils=require("../jetwc-lib/jetwcutils-componentAuditUtils");const TsxUtils=require("../jetwc-lib/jetwcutils-tsxUtils");const ruleDef=function(){};ruleDef.prototype.getName=function(){return"jetwc-standard-files"};ruleDef.prototype.getShortDescription=function(){return"Checks for the existence of standard informational files"};ruleDef.prototype.getDescription=function(){return"This rule ensures that standard files such as readmes are included"};ruleDef.prototype.register=function(context){return{compjson:this._doAudit,Program:this._doVComponentAudit}};ruleDef.prototype._doAudit=function(context){const componentMetadata=context.suppData.obj;if(componentMetadata){const fullName=Utils.getComponentFullName(componentMetadata);this._checkForStandardFiles(context,fullName,componentMetadata.version,componentMetadata.type)}};ruleDef.prototype._doVComponentAudit=function(context){const componentInfo=TsxUtils.matchToVComponentImpl(context,context.filepath);if(componentInfo){this._checkForStandardFiles(context,componentInfo.fullName,componentInfo.version,"composite")}};ruleDef.prototype._checkForStandardFiles=function(context,fullName,version,componentType){const componentFiles=context.utils.fsUtils.readDir(Utils.getDirectoryName(context.filepath));const checkForFiles=context.rulePack.getRuleCustomOption("files");checkForFiles.forEach(requiredFile=>{let exclusion=false;switch(requiredFile.toLowerCase()){case"changelog.md":case"changelog.txt":case"changes.txt":if(componentType&&componentType==="reference"){exclusion=true}else{if(version&&context.utils.semVerUtils.gt("1.0.1",version)){exclusion=true}}break}if(!exclusion){let hits=componentFiles.filter(compFile=>compFile.name===requiredFile&&compFile.isFile);if(hits.length===0){const issue=new context.Issue(`Required supporting file ${requiredFile} is not present for component ${fullName}`);context.reporter.addIssue(issue,context)}}})};module.exports=ruleDef;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const Utils=require("../jetwc-lib/jetwcutils-componentAuditUtils");const TsxUtils=require("../jetwc-lib/jetwcutils-tsxUtils");const ruleDef=function(){};ruleDef.prototype.getName=function(){return"jetwc-vb-category"};ruleDef.prototype.getShortDescription=function(){return"Verify the category specified "};ruleDef.prototype.getDescription=function(){return"This rule is configured with your preferred Visual Builder component palette category"};ruleDef.prototype.register=function(context){return{compjson:this._doAudit,Program:this._doVComponentAudit}};ruleDef.prototype._doAudit=function(context){if(context.suppData.obj){const meta=context.suppData.obj;const fullName=Utils.getComponentFullName(meta);const componentType=Utils.getComponentType(meta);let category;if(meta.extension&&meta.extension.catalog){category=meta.extension.catalog.category}this._checkCategory(context,fullName,componentType,category)}};ruleDef.prototype._doVComponentAudit=function(context){const componentInfo=TsxUtils.matchToVComponentImpl(context,context.filepath);if(componentInfo){let category;if(componentInfo.extension&&componentInfo.extension.catalog){category=componentInfo.extension.catalog.category}this._checkCategory(context,componentInfo.fullName,componentInfo.type,category,true)}};ruleDef.prototype._checkCategory=function(context,fullName,componentType,category,isVComponent){let issue;const ruleOptions=context.rulePack.getRuleOptions();if(ruleOptions.categories&&ruleOptions.categories.length>0){switch(componentType){case"composite":case"vbcs-pattern":if(category){if(ruleOptions.categories.filter(cat=>cat===category).length===0){issue=new context.Issue(`Component ${fullName} (${isVComponent?"vcomponent":componentType}) has an unexpected palette category set of '${category}'`);issue.setMsgKey(context.ruleName+"_2");context.reporter.addIssue(issue,context)}}else{issue=new context.Issue(`Component ${fullName} (${isVComponent?"vcomponent":componentType}) does not have a palette category set`);issue.setMsgKey(context.ruleName+"_1");context.reporter.addIssue(issue,context)}break;default:break}}};module.exports=ruleDef;
6
+ const Utils=require("../jetwc-lib/jetwcutils-componentAuditUtils");const TsxUtils=require("../jetwc-lib/jetwcutils-tsxUtils");const ruleDef=function(){};ruleDef.prototype.getName=function(){return"jetwc-vb-category"};ruleDef.prototype.getShortDescription=function(){return"Verify the category specified "};ruleDef.prototype.getDescription=function(){return"This rule is configured with your preferred Visual Builder component palette category"};ruleDef.prototype.register=function(context){return{compjson:this._doAudit,Program:this._doVComponentAudit}};ruleDef.prototype._doAudit=function(context){if(context.suppData.obj){const meta=context.suppData.obj;const fullName=Utils.getComponentFullName(meta);const componentType=Utils.getComponentType(meta);let category;if(meta.extension&&meta.extension.catalog){category=meta.extension.catalog.category}this._checkCategory(context,fullName,componentType,category)}};ruleDef.prototype._doVComponentAudit=function(context){const componentInfo=TsxUtils.matchToVComponentImpl(context,context.filepath);if(componentInfo){let category;if(componentInfo.extension&&componentInfo.extension.catalog){category=componentInfo.extension.catalog.category}this._checkCategory(context,componentInfo.fullName,componentInfo.type,category,true)}};ruleDef.prototype._checkCategory=function(context,fullName,componentType,category,isVComponent){let issue;const allowedCategories=context.rulePack.getRuleCustomOption("categories");if(allowedCategories?.length>0&&Array.isArray(allowedCategories)){switch(componentType){case"composite":case"vbcs-pattern":if(category){if(allowedCategories.filter(cat=>cat===category).length===0){issue=new context.Issue(`Component ${fullName} (${isVComponent?"vcomponent":componentType}) has an unexpected palette category set of '${category}'`);issue.setMsgKey(context.ruleName+"_2");context.reporter.addIssue(issue,context)}}else{issue=new context.Issue(`Component ${fullName} (${isVComponent?"vcomponent":componentType}) does not have a palette category set`);issue.setMsgKey(context.ruleName+"_1");context.reporter.addIssue(issue,context)}break;default:break}}};module.exports=ruleDef;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- {"title":"Extended Audit Rules for JET Custom Component Authors","prefix":"JETWC","version":"1.28.1","rules":{"jetwc-bootstrap":{"group":"jetwc-do-not-disable","enabled":true,"severity":"info","debug":false,"diagnosticFile":"jetwc-diagnostics","auditBuildOutput":false,"testMode":false,"$required":true,"filetype":["tsx","css","html","js","json","md","ts"],"amd":false},"jetwc-component-foldername":{"group":"jetwc-structure","severity":"blocker","filetype":["json","tsx"],"amd":false},"jetwc-component-location":{"group":"jetwc-structure","severity":"blocker","filetype":["json","tsx"],"amd":false},"jetwc-pack-children":{"group":"jetwc-dependencies","severity":"blocker","filetype":["json"],"amd":false},"jetwc-packable-components":{"group":"jetwc-structure","severity":"blocker","filetype":["json"],"amd":false},"jetwc-component-dependencies":{"group":"jetwc-dependencies","severity":"blocker","filetype":["json","tsx"],"amd":false},"jetwc-prerelease-version":{"group":"jetwc-pre-release","severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-prerelease-dependencies":{"group":"jetwc-pre-release","severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-namespace":{"group":"jetwc-api","enabled":false,"namespaces":[],"severity":"blocker","filetype":["json","tsx"],"amd":false},"jetwc-vb-category":{"group":"jetwc-vb","enabled":false,"categories":[],"severity":"minor","filetype":["json","tsx"],"amd":false},"jetwc-jet-version":{"group":"jetwc-pre-release","enabled":false,"versionMatch":"upperLimit","severity":"blocker","filetype":["json","tsx"],"amd":false},"jetwc-absolute-jetversion":{"group":"jetwc-dependencies","enabled":true,"severity":"minor","filetype":["json","tsx"],"amd":false},"jetwc-semantic-version":{"group":"jetwc-dependencies","severity":"blocker","filetype":["json","tsx"],"amd":false},"jetwc-standard-files":{"group":"jetwc-structure","enabled":true,"files":["README.md","CHANGELOG.md"],"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-loader-file":{"group":["jetwc-structure","jet-js"],"enabled":true,"severity":"critical","filetype":["json","js","ts","tsx"],"amd":false},"jetwc-version-openrange":{"group":"jetwc-dependencies","severity":"major","filetype":["json","tsx"],"amd":false},"jetwc-displayname":{"group":"jetwc-vb","enabled":true,"limits":{"component":{"length":30,"words":4},"property":{"length":30,"words":4},"event":{"length":30,"words":4},"slot":{"length":30,"words":4},"template":{"length":40,"words":8}},"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-nls-root":{"group":"jetwc-nls","enabled":true,"severity":"info","filetype":["js","ts","tsx"],"amd":false},"jetwc-require-paths":{"group":"jetwc-dependencies","enabled":true,"severity":"blocker","standardPaths":["require","exports","ojs","oj-c","knockout","hammerjs","persist","jquery","vb","preact","@opentelemetry"],"filetype":["js","ts","tsx"],"amd":false},"jetwc-vb-icon":{"group":"jetwc-vb","enabled":true,"severity":"major","filetype":["json","tsx"],"amd":false},"jetwc-template-slots":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["html","tsx"],"amd":false},"jetwc-slots":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["html","tsx"],"amd":false},"jetwc-events":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["js","ts","tsx"],"amd":false},"jetwc-property-nesting":{"group":"jetwc-api","enabled":true,"depth":3,"severity":"minor","filetype":["json","tsx"],"amd":false},"jetwc-nls-languages":{"group":"jetwc-nls","enabled":false,"locales":[],"strict":false,"severity":"major","filetype":["js","ts"],"amd":false},"jetwc-event-displayname":{"group":"jetwc-vb","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-nested-defaults":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["json","tsx"],"amd":false},"jetwc-methods":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["js","ts"],"amd":false},"jetwc-property-changed":{"group":"jetwc-api","enabled":true,"severity":"minor","filetype":["js","ts"],"amd":false},"jetwc-writeback-required":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["js","ts"],"amd":false},"jetwc-oj-register":{"group":"jetwc-deprecations","enabled":true,"severity":"minor","filetype":["js","ts"],"amd":false},"jetwc-register-with-promises":{"group":"jetwc-deprecations","enabled":true,"severity":"minor","filetype":["js","ts"],"amd":false},"jetwc-register-css":{"group":"jetwc-deprecations","enabled":true,"severity":"minor","filetype":["js","ts"],"amd":false},"jetwc-deprecated-lifecycle":{"group":"jetwc-deprecations","enabled":true,"severity":"major","filetype":["js","ts"],"amd":false},"jetwc-aria-redefinition":{"group":"jetwc-api","enabled":true,"severity":"minor","filetype":["json","tsx"],"amd":false},"jetwc-public-modules":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["json"],"amd":false},"jetwc-disabled-property":{"group":"jetwc-api","enabled":true,"severity":"minor","filetype":["json"],"amd":false},"jetwc-reserved-property":{"group":"jetwc-api","enabled":true,"severity":"major","reserved":["slot","key","ref","children"],"filetype":["json","tsx"],"amd":false},"jetwc-prerelease-pattern":{"group":"jetwc-api","enabled":true,"severity":"minor","filetype":["json","tsx"],"amd":false},"jetwc-ojcss":{"group":"jetwc-theming","enabled":true,"severity":"minor","filetype":["js","ts","tsx"],"amd":false},"jetwc-dynamic-slot-context":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["json"],"amd":false},"jetwc-dynamic-slots-naming":{"group":"jetwc-api","enabled":true,"severity":"minor","filetype":["json"],"amd":false},"jetwc-unused-slots":{"group":"jetwc-api","enabled":true,"severity":"info","filetype":["html"],"amd":false},"jetwc-unused-events":{"group":"jetwc-api","enabled":true,"severity":"info","filetype":["js","ts"],"amd":false},"jetwc-compjson-bp-obj":{"group":"jetwc-api","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-compjson-bp-ar":{"group":"jetwc-api","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-component-displayname":{"group":"jetwc-vb","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-method-displayname":{"group":"jetwc-vb","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-property-displayname":{"group":"jetwc-vb","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-slot-displayname":{"group":"jetwc-vb","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-data-property-prefix":{"group":"jetwc-api","enabled":true,"severity":"minor","filetype":["json","tsx"],"amd":false},"jetwc-schema":{"group":"jetwc-api","enabled":true,"severity":"blocker","ignoreAdditionalProperties":false,"filetype":["json","tsx"],"amd":false},"jetwc-component-type":{"group":"jetwc-api","enabled":true,"severity":"info","filetype":["json"],"amd":false},"jetwc-subproperty-writeback":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["html"],"amd":false},"jetwc-required-subproperty":{"group":"jetwc-api","enabled":true,"severity":"minor","filetype":["json"],"amd":false},"jetwc-vcomponent-jetversion":{"group":"jetwc-dependencies","enabled":true,"severity":"blocker","filetype":["tsx"],"amd":false},"jetwc-vcomponent-version":{"group":"jetwc-dependencies","enabled":true,"severity":"blocker","filetype":["tsx"],"amd":false},"jetwc-vcomponent-loader":{"group":"jetwc-structure","enabled":true,"severity":"blocker","filetype":["ts"],"amd":false},"jetwc-markdown-link":{"group":"jetwc-doc","enabled":true,"severity":"minor","filetype":["md"],"amd":false},"jetwc-css-oj-complete":{"group":"jetwc-css","enabled":true,"severity":"major","filetype":["css"],"amd":false},"jetwc-supproperty-propagation":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["html"],"amd":false},"jetwc-css-scoping":{"group":"jetwc-css","enabled":true,"severity":"blocker","filetype":["css"],"amd":false,"allowPackScoping":true},"jetwc-exchange-images":{"group":"jetwc-structure","enabled":true,"severity":"major","filetype":["json","tsx"],"amd":false},"jetwc-property-translatable":{"group":"jetwc-vb","enabled":false,"severity":"minor","filetype":["json","tsx"],"amd":false,"translatableProperties":[],"expressionMatch":false},"jetwc-status-since":{"group":"jetwc-api","enabled":true,"severity":"blocker","filetype":["json","tsx"],"amd":false},"jetwc-reference-npm-path":{"group":"jetwc-structure","enabled":true,"severity":"major","filetype":["json"],"amd":false},"jetwc-css-pack-load-path":{"group":"jetwc-dependencies","enabled":true,"severity":"blocker","filetype":["js","ts","tsx"],"amd":false},"jetwc-well-formed-description":{"group":"jetwc-api","enabled":false,"severity":"info","filetype":["json","tsx"],"amd":false}}}
6
+ {"title":"Extended Audit Rules for JET Custom Component Authors","prefix":"JETWC","version":"1.29.0","rules":{"jetwc-bootstrap":{"group":"jetwc-do-not-disable","enabled":true,"severity":"info","$required":true,"filetype":["tsx","css","html","js","json","md","ts"],"amd":false,"customOpts":{"debug":false,"diagnosticFile":"jetwc-diagnostics","auditBuildOutput":false,"testMode":false}},"jetwc-component-foldername":{"group":"jetwc-structure","severity":"blocker","filetype":["json","tsx"],"amd":false},"jetwc-component-location":{"group":"jetwc-structure","severity":"blocker","filetype":["json","tsx"],"amd":false},"jetwc-pack-children":{"group":"jetwc-dependencies","severity":"blocker","filetype":["json"],"amd":false},"jetwc-packable-components":{"group":"jetwc-structure","severity":"blocker","filetype":["json"],"amd":false},"jetwc-component-dependencies":{"group":"jetwc-dependencies","severity":"blocker","filetype":["json","tsx"],"amd":false},"jetwc-prerelease-version":{"group":"jetwc-pre-release","severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-prerelease-dependencies":{"group":"jetwc-pre-release","severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-namespace":{"group":"jetwc-api","enabled":false,"severity":"blocker","filetype":["json","tsx"],"amd":false,"customOpts":{"namespaces":[]}},"jetwc-vb-category":{"group":"jetwc-vb","enabled":false,"severity":"minor","filetype":["json","tsx"],"amd":false,"customOpts":{"categories":[]}},"jetwc-jet-version":{"group":"jetwc-pre-release","enabled":false,"severity":"blocker","filetype":["json","tsx"],"amd":false,"customOpts":{"versionMatch":"upperLimit"}},"jetwc-absolute-jetversion":{"group":"jetwc-dependencies","enabled":true,"severity":"minor","filetype":["json","tsx"],"amd":false},"jetwc-semantic-version":{"group":"jetwc-dependencies","severity":"blocker","filetype":["json","tsx"],"amd":false},"jetwc-standard-files":{"group":"jetwc-structure","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false,"customOpts":{"files":["README.md","CHANGELOG.md"]}},"jetwc-loader-file":{"group":["jetwc-structure","jet-js"],"enabled":true,"severity":"critical","filetype":["json","js","ts","tsx"],"amd":false},"jetwc-version-openrange":{"group":"jetwc-dependencies","severity":"major","filetype":["json","tsx"],"amd":false},"jetwc-displayname":{"group":"jetwc-vb","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false,"customOpts":{"limits":{"component":{"length":30,"words":4},"property":{"length":30,"words":4},"event":{"length":30,"words":4},"slot":{"length":30,"words":4},"template":{"length":40,"words":8}}}},"jetwc-nls-root":{"group":"jetwc-nls","enabled":true,"severity":"info","filetype":["js","ts","tsx"],"amd":false},"jetwc-require-paths":{"group":"jetwc-dependencies","enabled":true,"severity":"blocker","filetype":["js","ts","tsx"],"amd":false,"customOpts":{"standardPaths":["require","exports","ojs","oj-c","knockout","hammerjs","persist","jquery","vb","preact","@opentelemetry"]}},"jetwc-vb-icon":{"group":"jetwc-vb","enabled":true,"severity":"major","filetype":["json","tsx"],"amd":false},"jetwc-template-slots":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["html","tsx"],"amd":false},"jetwc-slots":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["html","tsx"],"amd":false},"jetwc-events":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["js","ts","tsx"],"amd":false},"jetwc-property-nesting":{"group":"jetwc-api","enabled":true,"severity":"minor","filetype":["json","tsx"],"amd":false,"customOpts":{"depth":3}},"jetwc-nls-languages":{"group":"jetwc-nls","enabled":false,"severity":"major","filetype":["js","ts"],"amd":false,"customOpts":{"locales":[],"strict":false}},"jetwc-event-displayname":{"group":"jetwc-vb","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-nested-defaults":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["json","tsx"],"amd":false},"jetwc-methods":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["js","ts"],"amd":false},"jetwc-property-changed":{"group":"jetwc-api","enabled":true,"severity":"minor","filetype":["js","ts"],"amd":false},"jetwc-writeback-required":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["js","ts"],"amd":false},"jetwc-oj-register":{"group":"jetwc-deprecations","enabled":true,"severity":"minor","filetype":["js","ts"],"amd":false},"jetwc-register-with-promises":{"group":"jetwc-deprecations","enabled":true,"severity":"minor","filetype":["js","ts"],"amd":false},"jetwc-register-css":{"group":"jetwc-deprecations","enabled":true,"severity":"minor","filetype":["js","ts"],"amd":false},"jetwc-deprecated-lifecycle":{"group":"jetwc-deprecations","enabled":true,"severity":"major","filetype":["js","ts"],"amd":false},"jetwc-aria-redefinition":{"group":"jetwc-api","enabled":true,"severity":"minor","filetype":["json","tsx"],"amd":false},"jetwc-public-modules":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["json"],"amd":false},"jetwc-disabled-property":{"group":"jetwc-api","enabled":true,"severity":"minor","filetype":["json"],"amd":false},"jetwc-reserved-property":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["json","tsx"],"amd":false,"customOpts":{"reserved":["slot","key","ref","children"]}},"jetwc-prerelease-pattern":{"group":"jetwc-api","enabled":true,"severity":"minor","filetype":["json","tsx"],"amd":false},"jetwc-ojcss":{"group":"jetwc-theming","enabled":true,"severity":"minor","filetype":["js","ts","tsx"],"amd":false},"jetwc-dynamic-slot-context":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["json"],"amd":false},"jetwc-dynamic-slots-naming":{"group":"jetwc-api","enabled":true,"severity":"minor","filetype":["json"],"amd":false},"jetwc-unused-slots":{"group":"jetwc-api","enabled":true,"severity":"info","filetype":["html"],"amd":false},"jetwc-unused-events":{"group":"jetwc-api","enabled":true,"severity":"info","filetype":["js","ts"],"amd":false},"jetwc-compjson-bp-obj":{"group":"jetwc-api","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-compjson-bp-ar":{"group":"jetwc-api","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-component-displayname":{"group":"jetwc-vb","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-method-displayname":{"group":"jetwc-vb","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-property-displayname":{"group":"jetwc-vb","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-slot-displayname":{"group":"jetwc-vb","enabled":true,"severity":"info","filetype":["json","tsx"],"amd":false},"jetwc-data-property-prefix":{"group":"jetwc-api","enabled":true,"severity":"minor","filetype":["json","tsx"],"amd":false},"jetwc-schema":{"group":"jetwc-api","enabled":true,"severity":"blocker","filetype":["json","tsx"],"amd":false,"customOpts":{"ignoreAdditionalProperties":false}},"jetwc-component-type":{"group":"jetwc-api","enabled":true,"severity":"info","filetype":["json"],"amd":false},"jetwc-subproperty-writeback":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["html"],"amd":false},"jetwc-required-subproperty":{"group":"jetwc-api","enabled":true,"severity":"minor","filetype":["json"],"amd":false},"jetwc-vcomponent-jetversion":{"group":"jetwc-dependencies","enabled":true,"severity":"blocker","filetype":["tsx"],"amd":false},"jetwc-vcomponent-version":{"group":"jetwc-dependencies","enabled":true,"severity":"blocker","filetype":["tsx"],"amd":false},"jetwc-vcomponent-loader":{"group":"jetwc-structure","enabled":true,"severity":"blocker","filetype":["ts"],"amd":false},"jetwc-markdown-link":{"group":"jetwc-doc","enabled":true,"severity":"minor","filetype":["md"],"amd":false},"jetwc-css-oj-complete":{"group":"jetwc-css","enabled":true,"severity":"major","filetype":["css"],"amd":false},"jetwc-supproperty-propagation":{"group":"jetwc-api","enabled":true,"severity":"major","filetype":["html"],"amd":false},"jetwc-css-scoping":{"group":"jetwc-css","enabled":true,"severity":"blocker","filetype":["css"],"amd":false,"customOpts":{"allowPackScoping":true}},"jetwc-exchange-images":{"group":"jetwc-structure","enabled":true,"severity":"major","filetype":["json","tsx"],"amd":false},"jetwc-property-translatable":{"group":"jetwc-vb","enabled":false,"severity":"minor","filetype":["json","tsx"],"amd":false,"customOpts":{"translatableProperties":[],"expressionMatch":false}},"jetwc-status-since":{"group":"jetwc-api","enabled":true,"severity":"blocker","filetype":["json","tsx"],"amd":false},"jetwc-reference-npm-path":{"group":"jetwc-structure","enabled":true,"severity":"major","filetype":["json"],"amd":false},"jetwc-css-pack-load-path":{"group":"jetwc-dependencies","enabled":true,"severity":"blocker","filetype":["js","ts","tsx"],"amd":false},"jetwc-well-formed-description":{"group":"jetwc-api","enabled":false,"severity":"info","filetype":["json","tsx"],"amd":false}}}
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const path=require("path");const NetUtils=require("../../lib/NetUtils");const AuditComponentCacheManager=function(context,ruleName,exchangeURL){const msg=context.utils.msgLib;this.cacheFolder=`jaftmp@-${context.rulePack.getPrefix()}`;this.fsUtils=context.utils.fsUtils;this.exchangeURL=exchangeURL;this.ruleName=ruleName;this._ensureLocalCache();this.baselineOpts=context.rulePack.getRuleOption("baseline",ruleName);if(this.baselineOpts&&Object.entries(this.baselineOpts).length>0){this.baselineIndexFileName=path.join(this.cacheFolder,`${this._getObjectHashSignature(this.baselineOpts)}.json`)}else{this.baselineIndexFileName=null}};AuditComponentCacheManager.prototype.isBaselineIndexAvailable=function(){return this.baselineIndexFileName!==null};AuditComponentCacheManager.prototype.getBaselineOpts=function(){return this.baselineOpts};AuditComponentCacheManager.prototype.readComponentCacheIndexFile=function(){if(this.baselineIndexFileName){if(this.fsUtils.fileExistsSync(this.baselineIndexFileName)){return this.fsUtils.readJsonSync(this.baselineIndexFileName)}else{return{}}}else{return}};AuditComponentCacheManager.prototype.writeComponentCacheIndexFile=function(index){if(this.baselineIndexFileName){this.fsUtils.writeJsonSync(index,this.baselineIndexFileName)}};AuditComponentCacheManager.prototype.removeLocalCache=function(){if(this.fsUtils.pathExistsSync(this.cacheFolder)){this.fsUtils.deleteFolderSync(this.cacheFolder,true)}};AuditComponentCacheManager.prototype.generateComponentCachePath=function(component,componentVersion){const mungedVersion=componentVersion.replace(/\./g,"-");return path.join(this.cacheFolder,`${component}@${mungedVersion}-component.json`)};AuditComponentCacheManager.prototype.existsInComponentCache=function(component,componentVersion){const cacheFile=this.generateComponentCachePath(component,componentVersion);return this.fsUtils.fileExistsSync(cacheFile)};AuditComponentCacheManager.prototype.writeToComponentCache=function(component,componentVersion,metadata){if(metadata){const cacheFile=this.generateComponentCachePath(component,componentVersion);this.fsUtils.writeJsonSync(metadata,cacheFile)}};AuditComponentCacheManager.prototype.readFromComponentCache=function(component,componentVersion){const cacheFile=this.generateComponentCachePath(component,componentVersion);return this.fsUtils.readJsonSync(cacheFile)};AuditComponentCacheManager.prototype.getComponentMetadata=function(component,componentVersion){if(this.existsInComponentCache(component,componentVersion)){return this.readFromComponentCache(component,componentVersion)}else{try{const netUtils=new NetUtils;const getResp=netUtils.loadUrl(`${this.exchangeURL}components/${component}/versions/${componentVersion}`);if(getResp.statusCode=200&&getResp.body){const cachedDef=JSON.parse(getResp.body).component;this.writeToComponentCache(component,componentVersion,cachedDef);return cachedDef}else{this.msg.error(`The exchange component ${component}@${componentVersion} needed by the rule ${this.ruleName} cannot be retrieved, ensure it is public`)}}catch(e){this.msg.error(`Unable to read component ${component}@${componentVersion} for rule ${this.ruleName}:\n${JSON.stringify(e)}`)};}return};AuditComponentCacheManager.prototype._ensureLocalCache=function(){if(!this.fsUtils.pathExistsSync(this.cacheFolder)){this.fsUtils.createFolderSync(this.cacheFolder)}};AuditComponentCacheManager.prototype._getObjectHashSignature=function(sourceObject){const sourceAsStringArray=Array.from(JSON.stringify(sourceObject));return sourceAsStringArray.reduce((hash,c)=>Math.imul(31,hash)+c.charCodeAt(0)|0,0)};module.exports=AuditComponentCacheManager;
6
+ const path=require("path");const NetUtils=require("../../lib/NetUtils");const AuditComponentCacheManager=function(context,ruleName,exchangeURL){this.msg=context.utils.msgLib;this.cacheFolder=`jaftmp@-${context.rulePack.getPrefix()}`;this.fsUtils=context.utils.fsUtils;this.exchangeURL=exchangeURL;this.ruleName=ruleName;this._ensureLocalCache();this.baselineOpts=context.rulePack.getRuleCustomOption("baseline",ruleName);if(this.baselineOpts&&Object.entries(this.baselineOpts).length>0){this.baselineIndexFileName=path.join(this.cacheFolder,`${this._getObjectHashSignature(this.baselineOpts)}.json`)}else{this.baselineIndexFileName=null}};AuditComponentCacheManager.prototype.isBaselineIndexAvailable=function(){return this.baselineIndexFileName!==null};AuditComponentCacheManager.prototype.getBaselineOpts=function(){return this.baselineOpts};AuditComponentCacheManager.prototype.readComponentCacheIndexFile=function(){if(this.baselineIndexFileName){if(this.fsUtils.fileExistsSync(this.baselineIndexFileName)){return this.fsUtils.readJsonSync(this.baselineIndexFileName)}else{return{}}}else{return}};AuditComponentCacheManager.prototype.writeComponentCacheIndexFile=function(index){if(this.baselineIndexFileName){this.fsUtils.writeJsonSync(index,this.baselineIndexFileName)}};AuditComponentCacheManager.prototype.removeLocalCache=function(){if(this.fsUtils.pathExistsSync(this.cacheFolder)){this.fsUtils.deleteFolderSync(this.cacheFolder,true)}};AuditComponentCacheManager.prototype.generateComponentCachePath=function(component,componentVersion){const mungedVersion=componentVersion.replace(/\./g,"-");return path.join(this.cacheFolder,`${component}@${mungedVersion}-component.json`)};AuditComponentCacheManager.prototype.existsInComponentCache=function(component,componentVersion){const cacheFile=this.generateComponentCachePath(component,componentVersion);return this.fsUtils.fileExistsSync(cacheFile)};AuditComponentCacheManager.prototype.writeToComponentCache=function(component,componentVersion,metadata){if(metadata){const cacheFile=this.generateComponentCachePath(component,componentVersion);this.fsUtils.writeJsonSync(metadata,cacheFile)}};AuditComponentCacheManager.prototype.readFromComponentCache=function(component,componentVersion){const cacheFile=this.generateComponentCachePath(component,componentVersion);return this.fsUtils.readJsonSync(cacheFile)};AuditComponentCacheManager.prototype.getComponentMetadata=function(component,componentVersion){if(this.existsInComponentCache(component,componentVersion)){return this.readFromComponentCache(component,componentVersion)}else{try{const netUtils=new NetUtils;const getResp=netUtils.loadUrl(`${this.exchangeURL}components/${component}/versions/${componentVersion}`);if(getResp.statusCode=200&&getResp.body){const cachedDef=JSON.parse(getResp.body).component;this.writeToComponentCache(component,componentVersion,cachedDef);return cachedDef}else{this.msg.error(`The exchange component ${component}@${componentVersion} needed by the rule ${this.ruleName} cannot be retrieved, ensure it is public`)}}catch(e){this.msg.error(`Unable to read component ${component}@${componentVersion} for rule ${this.ruleName}:\n${JSON.stringify(e)}`)};}return};AuditComponentCacheManager.prototype._ensureLocalCache=function(){if(!this.fsUtils.pathExistsSync(this.cacheFolder)){this.fsUtils.createFolderSync(this.cacheFolder)}};AuditComponentCacheManager.prototype._getObjectHashSignature=function(sourceObject){const sourceAsStringArray=Array.from(JSON.stringify(sourceObject));return sourceAsStringArray.reduce((hash,c)=>Math.imul(31,hash)+c.charCodeAt(0)|0,0)};module.exports=AuditComponentCacheManager;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const NetUtils=require("../../lib/NetUtils");const EXCHANGE_URL_OPTION="exchangeURL";function checkForExchangeConfiguration(auditContext){const{msgLib}=auditContext.utils;let exchangeURL;if(auditContext.rulePack.getRuleOptions()){exchangeURL=auditContext.rulePack.getRuleOptions()[EXCHANGE_URL_OPTION]}if((!exchangeURL||exchangeURL.length===0)&&auditContext.rulePack.getExtension()){exchangeURL=auditContext.rulePack.getExtension()[EXCHANGE_URL_OPTION]}if(exchangeURL&&exchangeURL.length>0){exchangeURL=exchangeURL.endsWith("/")?exchangeURL:`${exchangeURL}/`;const netUtils=new NetUtils;const statusResp=netUtils.loadUrl(`${exchangeURL}status`);if(statusResp.statusCode===200){return exchangeURL}else{msgLib.error(`The supplied ${EXCHANGE_URL_OPTION} value '${this.exchangeURL}' for the rule ${auditContext.ruleName} does not appear to be valid, the rule will be disabled`);auditContext.rulePack.disableRule();return}}else{msgLib.error(`The ${EXCHANGE_URL_OPTION} configuration option has not been defined for rule ${auditContext.ruleName}, the rule will be disabled`);auditContext.rulePack.disableRule();return}}module.exports={checkForExchangeConfiguration};
6
+ const NetUtils=require("../../lib/NetUtils");const EXCHANGE_URL_OPTION="exchangeURL";function checkForExchangeConfiguration(auditContext){const{msgLib}=auditContext.utils;let exchangeURL=auditContext.userDefs?.[EXCHANGE_URL_OPTION]??auditContext.rulePack.getRuleCustomOption(EXCHANGE_URL_OPTION);if((!exchangeURL||exchangeURL.length===0)&&auditContext.rulePack.getExtension()){exchangeURL=auditContext.rulePack.getExtension()[EXCHANGE_URL_OPTION]}if(exchangeURL&&exchangeURL.length>0){exchangeURL=exchangeURL.endsWith("/")?exchangeURL:`${exchangeURL}/`;const netUtils=new NetUtils;const statusResp=netUtils.loadUrl(`${exchangeURL}status`);if(statusResp.statusCode===200){return exchangeURL}else{msgLib.error(`The supplied ${EXCHANGE_URL_OPTION} value '${this.exchangeURL}' for the rule ${auditContext.ruleName} does not appear to be valid, the rule will be disabled`);auditContext.rulePack.disableRule();return}}else{msgLib.error(`The ${EXCHANGE_URL_OPTION} configuration option has not been defined for rule ${auditContext.ruleName}, the rule will be disabled`);auditContext.rulePack.disableRule();return}}module.exports={checkForExchangeConfiguration};
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const path=require("path");const Utils=function(){this.rootPoint=this.toJAFPath(path.resolve(".")).length+1;this.isWindows=path.sep!=="/";this.noJSWarnDone=false};Utils.prototype.getKeyPathInfoForRulepack=function(context,auditBase){const paths={isBuiltOutput:false,componentRootFolder:null,exchangeCacheFolder:null,generalSourceRoot:"src",jsSource:null,tsSource:null,base:null};let jetConfig=context.ojetConfig;if(!jetConfig&&auditBase){const remoteConfig=path.join(auditBase,"oraclejetconfig.json");if(context.utils.fsUtils.pathExistsSync(remoteConfig)){jetConfig=context.utils.fsUtils.readJsonSync(remoteConfig)}}let jsDir="js";let tsDir="ts";paths.isBuiltOutput=context.rulePack.getRuleOptions().auditBuildOutput;paths.base=path.resolve(auditBase);if(jetConfig){jsDir=jetConfig.paths.source.javascript||"js";tsDir=jetConfig.paths.source.typescript||"ts";paths.exchangeCacheFolder=jetConfig.paths.source.exchangeComponents||"jet_components";paths.componentRootFolder=jetConfig.paths.source.components||"jet-composites";if(!paths.isBuiltOutput){paths.generalSourceRoot=jetConfig.paths.source.common||"src"}else{paths.generalSourceRoot=jetConfig.paths.staging.web||"web"}}paths.jsSource=this.toJAFPath(path.join(paths.generalSourceRoot,jsDir));if(!paths.isBuiltOutput){paths.tsSource=this.toJAFPath(path.join(paths.generalSourceRoot,tsDir))}return paths};Utils.prototype.matchComponentPath=function(context,checkPathBase,recursion){let checkPath=this.toJAFPath(checkPathBase);let componentMatch;if(context.rulePack.getExtension()&&context.rulePack.getExtension().hasOwnProperty("allAuditableFilePaths")){if(context.rulePack.getExtension().allAuditableFilePaths.has(checkPath)){const x=context.rulePack.getExtension().allAuditableFilePaths;componentMatch=context.rulePack.getExtension().allAuditableFilePaths.get(checkPath)}else if(checkPath.includes(context.rulePack.getExtension().componentHome)){if(context.rulePack.getExtension().auditableComponentPaths.has(checkPath)){componentMatch=context.rulePack.getExtension().auditableComponentPaths.get(checkPath)}else{const parentPath=path.resolve(checkPathBase,".."+path.sep);componentMatch=this.matchComponentPath(context,parentPath,true)}if(!recursion){context.rulePack.getExtension().allAuditableFilePaths.set(checkPath,componentMatch)}}else{context.rulePack.getExtension().allAuditableFilePaths.set(checkPath)}}else{this.reportMissingBootstrapInfo(context,"allAuditableFilePaths")}return componentMatch};Utils.prototype.reportMissingBootstrapInfo=function(context,checkTopic){const msg=context.utils.msgLib;const extnContext=context.rulePack.getExtension();if(!extnContext||!extnContext.bootStrap){const bootstrapRule=context.rulePack.getPrefix().toLowerCase()+"-bootstrap";if(context.rulePack.isRuleDisabled(bootstrapRule)){msg.error(`You must enable the ${bootstrapRule} rule to run in order to carry out a full component set audit`)}else{msg.error(`Apparent bootstrap error, no information cached for ${checkTopic}`)}context.rulePack.setExtension({...extnContext,bootStrap:true})}};Utils.prototype.componentInfo=function(context,componentName){if(context.rulePack.getExtension()&&context.rulePack.getExtension().hasOwnProperty("allComponents")){return context.rulePack.getExtension().allComponents.get(componentName)}else{this.reportMissingBootstrapInfo(context,"allComponents")}return};Utils.prototype.getComponentFullName=function(metadata){return metadata.pack?`${metadata.pack}-${metadata.name}`:metadata.name};Utils.prototype.getComponentType=function(metadata){return metadata.type?metadata.type:"composite"};Utils.prototype.flattenComponentProperties=function(metaDef,valueAttribute,filterCondition,parentPath){let flattenedProps=[];if(metaDef.hasOwnProperty("properties")){const propArray=Object.keys(metaDef.properties);propArray.forEach(propertyName=>{const propertyMetadata=metaDef.properties[propertyName];let key;if(!parentPath){key=propertyName}else{key=parentPath+"."+propertyName}if(!filterCondition||filterCondition(propertyName,propertyMetadata)){flattenedProps.push({key:key,value:metaDef.properties[propertyName][valueAttribute]})}const subPropsArray=this.flattenComponentProperties(metaDef.properties[propertyName],valueAttribute,filterCondition,key);flattenedProps=flattenedProps.concat(subPropsArray)})}return flattenedProps};Utils.prototype.setupFileMethodMapping=function(context,node){const NT=context.utils.AstUtils.getNodeTypes();const fileName=context.filepath;const withinComponent=this.matchComponentPath(context,path.dirname(fileName));if(withinComponent&&node.parent){if(node.parent.type===NT.ASSIGNMENT_EXPR&&node.parent.operator==="="){if(node.parent.left&&node.parent.left.property&&node.parent.left.property.type==NT.IDENTIFIER&&node.parent.left.property.name){const methodDef={name:node.parent.left.property.name,parameters:node.params?node.params.length:0};this.cacheFileMethod(context,fileName,methodDef)}}else if(node.parent.type===NT.METH_DEF&&node.parent.kind==="method"){if(node.parent.key&&node.parent.key.name){const methodDef={name:node.parent.key.name,parameters:node.params?node.params.length:0};this.cacheFileMethod(context,fileName,methodDef)}}else if(node.parent.type===NT.CLASS_PROP||node.parent.type===NT.PROPERTY_DEF){if(node.parent.key&&node.parent.key.name){const methodDef={name:node.parent.key.name,parameters:node.params?node.params.length:0};this.cacheFileMethod(context,fileName,methodDef)}}}};Utils.prototype.setupFileMethodMappingFromMethodDefintion=function(context,node){const NT=context.utils.AstUtils.getNodeTypes();const fileName=context.filepath;const withinComponent=this.matchComponentPath(context,path.dirname(fileName));if(withinComponent){const methodDef={parameters:0};if(node.key&&node.key.type===NT.IDENTIFIER){methodDef.name=node.key.name;if(node.value&&node.value.type===NT.FUNC_EXPR&&node.value.params){methodDef.parameters=node.value.params.length}}if(methodDef.name){this.cacheFileMethod(context,fileName,methodDef)}}};Utils.prototype.cacheFileMethod=function(context,filePath,methodDef){if(!context.rulePack.getExtension().allDefinedFileMethods){context.rulePack.getExtension().allDefinedFileMethods=new Map}if(!context.rulePack.getExtension().allDefinedFileMethods.has(filePath)){context.rulePack.getExtension().allDefinedFileMethods.set(filePath,{methods:new Map})}if(!context.rulePack.getExtension().allDefinedFileMethods.get(filePath).methods.has(methodDef.name)){context.rulePack.getExtension().allDefinedFileMethods.get(filePath).methods.set(methodDef.name,methodDef)}};Utils.prototype.deriveViewModels=function(context,node){const fileName=context.filepath;if(context.rulePack.getExtension()&&context.rulePack.getExtension().hasOwnProperty("allComponents")){const withinComponent=this.matchComponentPath(context,path.dirname(fileName));const componentInfo=context.rulePack.getExtension().allComponents.get(withinComponent);if(withinComponent&&componentInfo&&componentInfo.type==="composite"&&!componentInfo.viewModel.resolved){const targetLoaderExt=componentInfo.language==="tsx"?".ts":`.${componentInfo.language}`;if(path.basename(fileName,targetLoaderExt)==="loader"){switch(componentInfo.language){case"js":case"ts":const registerInfo=this.getLoaderRegisterInfo(context,node);if(registerInfo){const vmRelativeFilePath=this._mapVMToImpl(context,node,registerInfo.viewModel,componentInfo.language==="ts");if(vmRelativeFilePath){const fullVMPath=this._expandPathInContext(context,withinComponent,vmRelativeFilePath);if(fullVMPath){componentInfo.viewModel={path:this.toJAFPath(path.resolve(".",`${fullVMPath}.${componentInfo.language}`)),resolved:true,skip:false}}}}break;case"tsx":break}}}}else{this.reportMissingBootstrapInfo(context,"allComponents")}};Utils.prototype.getLoaderRegisterInfo=function(context,node){const msg=context.utils.msgLib;const NT=context.utils.AstUtils.getNodeTypes();let registerInfo;if(node.callee.type=NT.MEMBER_EXPR&&node.callee.object&&node.arguments&&node.arguments.length>0){let isRegister=false;let oldStyle=false;switch(node.callee.object.type){case NT.IDENTIFIER:if(node.callee.object.name==="Composite"){isRegister=this._astPropertyIdentifierName(context,node.callee,"register")}break;case NT.MEMBER_EXPR:if(node.callee.property&&node.callee.property.type===NT.IDENTIFIER&&node.callee.property.name==="register"){if(this._astPropertyIdentifierName(context,node.callee.object,"Composite")){isRegister=node.callee.object.object&&node.callee.object.object.type===NT.IDENTIFIER&&node.callee.object.object.name==="oj";if(isRegister){oldStyle=true}}}break}if(isRegister){registerInfo={oldStyle:oldStyle};const tagArg=node.arguments[0];const def=node.arguments[1];registerInfo.tag=tagArg.type===NT.LITERAL?tagArg.value:"?";if(def.type===NT.OBJ_EXPR){vmProp=def.properties.filter(prop=>prop.key.name==="viewModel");if(vmProp.length===1){switch(vmProp[0].value.type){case NT.IDENTIFIER:registerInfo.viewModel=vmProp[0].value.name;break;case NT.OBJ_EXPR:if(vmProp[0].value.properties&&vmProp[0].value.properties[0]&&vmProp[0].value.properties[0].key.name==="inline"){registerInfo.viewModel=vmProp[0].value.properties[0].value.name;registerInfo.usesPromises=true}break;case NT.MEMBER_EXPR:if(vmProp[0].value.property&&vmProp[0].value.property.type===NT.IDENTIFIER){registerInfo.viewModel=vmProp[0].value.object.name;registerInfo.transpiled=true}break;case"TSAsExpression":if(vmProp[0].value.expression&&vmProp[0].value.expression.type===NT.IDENTIFIER){registerInfo.viewModel=vmProp[0].value.expression.name}else if(vmProp[0].value.expression&&vmProp[0].value.expression.type===NT.AS_EXPR){registerInfo.viewModel=vmProp[0].value.expression.expression.name;msg.msg(`WARNING: Component loader file ${context.filepath} attempts to redefine the composite.register viewModel interface`)}break}}const cssCheck=def.properties.filter(prop=>prop.key.name==="css");if(cssCheck.length>0){registerInfo.registerCSS=true}}}}return registerInfo};Utils.prototype._astPropertyIdentifierName=function(context,node,checkName){const NT=context.utils.AstUtils.getNodeTypes();return node&&node.property&&node.property.type===NT.IDENTIFIER&&node.property.name===checkName};Utils.prototype._mapVMToImpl=function(context,node,vmName,useImports){let vmPathDef;if(vmName){let rootNode=node;if(useImports){vmPathDef=this._getImportPath(context,rootNode,vmName)}else{vmPathDef=this._getDefineStatementPath(context,rootNode,vmName);if(!vmPathDef){vmPathDef=this._mapToRequireAssignment(context,node,vmName)}}}return vmPathDef};Utils.prototype._mapToRequireAssignment=function(context,node,vmName){const NT=context.utils.AstUtils.getNodeTypes();let requirePath;const vmDeclNode=this._locateDeclaration(context,node,vmName);if(vmDeclNode.type===NT.CALL_EXPR&&vmDeclNode.callee.type===NT.IDENTIFIER&&vmDeclNode.callee.name==="require"){if(vmDeclNode.arguments&&vmDeclNode.arguments.length===1&&vmDeclNode.arguments[0].type===NT.LITERAL){requirePath=vmDeclNode.arguments[0].value}}return requirePath};Utils.prototype._getImportPath=function(context,node,importAs){const NT=context.utils.AstUtils.getNodeTypes();const bodyNodeArray=context.utils.AstUtils.getBody();let definePath;for(let i=0;i<bodyNodeArray.length;i++){const testNode=bodyNodeArray[i];switch(testNode.type){case"ImportDeclaration":if(testNode.specifiers&&Array.isArray(testNode.specifiers)&&testNode.specifiers.length===1&&(testNode.specifiers[0].type===NT.IMPORT_DEF_SPECIFIER||testNode.specifiers[0].type===NT.IMPORT_SPECIFIER)&&testNode.specifiers[0].local&&testNode.specifiers[0].local.name===importAs){definePath=testNode.source.value}break;case"TSImportEqualsDeclaration":if(testNode.id&&testNode.id.type===NT.IDENTIFIER&&testNode.id.name===importAs&&testNode.moduleReference&&testNode.moduleReference.type===NT.EXTERN_MOD_REF&&testNode.moduleReference.expression&&testNode.moduleReference.expression.type===NT.LITERAL){definePath=testNode.moduleReference.expression.value}break}if(definePath){;break}}return definePath};Utils.prototype._getDefineStatementPath=function(context,node,defineParam){const NT=context.utils.AstUtils.getNodeTypes();let checkNode=node.parent;let definePath;while(checkNode){if(checkNode.type===NT.CALL_EXPR&&checkNode.callee.name==="define"){definePath=context.utils.AstUtils.parseDefine(checkNode)[defineParam]}checkNode=checkNode.parent}return definePath};Utils.prototype._expandPathInContext=function(context,componentName,requirePath){let targetPath=requirePath;const parsePluginParts=requirePath.split("!");if(parsePluginParts.length>1){targetPath=parsePluginParts[1]}let pathParts=targetPath.split("/");const decodeRoot=pathParts[0];if(decodeRoot==="."){pathParts[0]=this.rootPathForComponent(context,componentName)}else{const remotePart=this.rootPathForComponent(context,decodeRoot);if(!remotePart){pathParts=[]}else{pathParts[0]=remotePart}}return pathParts.join("/")};Utils.prototype.rootPathForComponent=function(context,componentName){if(context.rulePack.getExtension().allComponents.has(componentName)){return context.rulePack.getExtension().allComponents.get(componentName).rootFolder}};Utils.prototype.getVMMethodsForLocalComposite=function(context,component){let vmMethods;const msg=context.utils.msgLib;const opts=context.rulePack.getRuleOptions();if(component.local&&component.type==="composite"){if(!component.viewModel.skip){if(!component.viewModel.resolved&&!component.viewModel.warned){if(!opts.testMode){msg.msg(`Warning: unable to derive the correct viewModel implementation for component ${component.fullName}, either your audit run does not include .js/.ts files, or you may need to set 'extension.audit.jetwc.viewModel' in the metadata to provide a hint`)}component.viewModel.warned=true}else{const rpState=context.rulePack.getExtension();if(rpState.allDefinedFileMethods&&rpState.allDefinedFileMethods.size>0){const vmMethodDef=rpState.allDefinedFileMethods.get(component.viewModel.path);if(vmMethodDef){vmMethods=vmMethodDef.methods}}else{if(!this.noJSWarnDone){msg.msg("Error: No JavaScript / TypeScript files have been processed. You need to ensure that your audit fileset includes .js, .ts, html and .json files to enable all audits in this rule-set. Use the ojaf --dryrun command to determine what files are covered by the audit");this.noJSWarnDone=true}}}}}return vmMethods};Utils.prototype.decomposeAssignment=function(auditContext,assignmentNode){const NT=auditContext.utils.AstUtils.getNodeTypes();const breakdown=[];this._walkAssignmentNodes(auditContext,assignmentNode.left,breakdown);if(!breakdown.includes("this")){const parentAssignment=breakdown[breakdown.length-1];const initialAssignmentNode=this._locateDeclaration(auditContext,assignmentNode,parentAssignment);if(initialAssignmentNode){if(initialAssignmentNode==="<parameter>"){breakdown.push("<parameter>")}else if(initialAssignmentNode.type===NT.THIS_EXPR){breakdown.push("this")}else if(initialAssignmentNode.type===NT.IDENTIFIER){breakdown.push(initialAssignmentNode.name);const indirectAssignmentNode=this._locateDeclaration(auditContext,assignmentNode,initialAssignmentNode.name);if(indirectAssignmentNode==="<parameter>"){breakdown.push("<parameter>")}else if(indirectAssignmentNode.type===NT.THIS_EXPR){breakdown.push("this")}}}}return breakdown};Utils.prototype._walkAssignmentNodes=function(context,node,accumulator){const NT=context.utils.AstUtils.getNodeTypes();switch(node.type){case NT.MEMBER_EXPR:accumulator.push(node.property.name);if(node.object){this._walkAssignmentNodes(context,node.object,accumulator)}break;case NT.IDENTIFIER:accumulator.push(node.name);break;case NT.THIS_EXPR:accumulator.push("this");break}};Utils.prototype._locateDeclaration=function(context,node,searchVariable){const NT=context.utils.AstUtils.getNodeTypes();let initialAssignment;let workingNode=node;while(!initialAssignment){if(workingNode.body&&workingNode.body.length>0){workingNode.body.forEach(bodyNode=>{if(bodyNode.type===NT.VAR_DECLARATION){bodyNode.declarations.forEach(declNode=>{if(declNode.id.type===NT.IDENTIFIER&&declNode.id.name===searchVariable){initialAssignment=declNode.init}})}})}else if(workingNode.params&&workingNode.params.length>0){workingNode.params.forEach(paramNode=>{if(paramNode.name===searchVariable){initialAssignment="<parameter>"}})}if(!workingNode.parent){break}else{workingNode=workingNode.parent}}return initialAssignment};Utils.prototype.extractComponentInfoFromJSONFile=function(auditContext,componentFolder,fileName,isLocal,fromPrecompile){const msg=auditContext.utils.msgLib;let componentInfo={};const mdFile=`${componentFolder}/${fileName}`;const compMetadata=auditContext.utils.fsUtils.readJsonSync(mdFile);if(compMetadata!==null){return this.extractComponentInfoFromMetadata(auditContext,compMetadata,componentFolder,isLocal,fromPrecompile)}else{msg.error(`Invalid JSON in component metadata ${mdFile}, component ignored`)}return};Utils.prototype.extractComponentInfoFromMetadata=function(auditContext,compMetadata,componentFolder,isLocal,fromPrecompile){const msg=auditContext.utils.msgLib;let componentInfo={};componentInfo.name=compMetadata.name;componentInfo.pack=compMetadata.pack;if(fromPrecompile&&compMetadata.pack){if(compMetadata.name.startsWith(`${compMetadata.pack}-`)){componentInfo.name=compMetadata.name.substring(compMetadata.pack.length+1)}}componentInfo.fullName=componentInfo.pack?`${componentInfo.pack}-${componentInfo.name}`:componentInfo.name;componentInfo.displayName=compMetadata.displayName;componentInfo.description=compMetadata.description;componentInfo.version=compMetadata.version;componentInfo.jetVersion=compMetadata.jetVersion;componentInfo.license=compMetadata.license;componentInfo.extension=compMetadata.extension;if(compMetadata.icon){componentInfo.icon=compMetadata.icon}componentInfo.type=compMetadata.type?compMetadata.type:"composite";componentInfo.subcomponentType=compMetadata.subcomponentType;componentInfo.local=isLocal;componentInfo.rootFolder=this.toJAFPath(componentFolder);componentInfo.requirePaths=new Set;switch(componentInfo.type){case"reference":if(compMetadata.extension&&compMetadata.extension.oracle&&compMetadata.extension.oracle.businessApprovals){componentInfo.ba=compMetadata.extension.oracle.businessApprovals}if(compMetadata.paths&&compMetadata.paths.name){componentInfo.requirePaths.add(compMetadata.paths.name)}else{const extractPathSegments=compMetadata.package.split("/");if(extractPathSegments.length>1){componentInfo.requirePaths.add(extractPathSegments[1])}else{componentInfo.requirePaths.add(extractPathSegments[0])}}break;case"composite":if(compMetadata.styleClasses){componentInfo.styleClasses=compMetadata.styleClasses}if(compMetadata.styleVariables){componentInfo.styleVariables=compMetadata.styleVariables}if(compMetadata.slots){componentInfo.slots=compMetadata.slots}if(compMetadata.properties){componentInfo.properties=compMetadata.properties}if(compMetadata.events){componentInfo.events=compMetadata.events}if(compMetadata.methods&&Object.keys(compMetadata.methods).length>0){componentInfo.methods=compMetadata.methods}componentInfo.viewModel={resolved:false};if(compMetadata&&compMetadata.extension&&compMetadata.extension.audit&&compMetadata.extension.audit.jetwc&&compMetadata.extension.audit.jetwc.hasOwnProperty("viewModel")){const overrideVM=compMetadata.extension.audit.jetwc.viewModel;if(overrideVM){componentInfo.viewModel={path:this.toJAFPath(path.resolve(".",componentInfo.rootFolder,overrideVM)),resolved:true,skip:false}}else{componentInfo.viewModel={skip:true}}}case"resource":componentInfo.requirePaths.add(".");if(compMetadata.pack){componentInfo.requirePaths.add(`${componentInfo.pack}/${componentInfo.name}`)}else{componentInfo.requirePaths.add(componentInfo.name)}if(compMetadata.dependencies){componentInfo.dependencies=[];Object.keys(compMetadata.dependencies).forEach(depname=>{componentInfo.dependencies.push({name:depname,range:compMetadata.dependencies[depname]})})}break}return componentInfo};Utils.prototype.diagnosticReplacer=function(key,value){if(value instanceof Map){return Array.from(value).map(([vKey,vValue])=>{return{[vKey]:vValue?vValue:""}})}if(value instanceof Set){return Array.from(value)}return value};Utils.prototype.toJAFPath=function(sourcePath){if(sourcePath&&this.isWindows){return sourcePath.replace(/\\\\|\\/g,"/")}return sourcePath};Utils.prototype.toNativePath=function(sourcePath){if(sourcePath&&this.isWindows){return sourcePath.replace(/\//g,"\\")}return sourcePath};Utils.prototype.getDirectoryName=function(filePath){return path.dirname(filePath)};Utils.prototype.shouldIgnoreCheck=function(context,auditName,componentName,scope,target){let ignore=false;const checkComponentDef=context.rulePack.getExtension().allComponents.get(componentName);if(checkComponentDef){let targetDef;if(scope&&checkComponentDef[scope]){if(target.includes(".")&&scope==="properties"){targetDef=this.getPropertyAttributeFromPath(context,componentName,target)}else{targetDef=checkComponentDef[scope][target==="__default__"?"":target]}}else{targetDef=checkComponentDef}if(targetDef&&targetDef.extension&&targetDef.extension.hasOwnProperty("audit")&&targetDef.extension.audit.hasOwnProperty("ignore")){const ignoreArray=targetDef.extension.audit.ignore;ignore=ignoreArray.includes(auditName)}}return ignore};Utils.prototype.getPropertyAttributeFromPath=function(context,componentName,targetPath,attribute){const checkComponentDef=context.rulePack.getExtension().allComponents.get(componentName);let targetDef;if(checkComponentDef&&checkComponentDef.properties){if(targetPath.includes(".")){const propPath=targetPath.split(".");targetDef=checkComponentDef.properties[propPath[0]];for(let i=1;i<propPath.length;i++){targetDef=targetDef.properties[propPath[i]]}}else{targetDef=checkComponentDef.properties[targetPath]}}if(attribute){return targetDef[attribute]}else{return targetDef}};Utils.prototype.detectComponentSourceType=function(context,componentPathRoot,isVComponent){let componentImplType;if(isVComponent){componentImplType="tsx"}else{const{fsUtils}=context.utils;if(fsUtils.fileExistsSync(`${componentPathRoot}/loader.js`)){componentImplType="js"}else if(fsUtils.fileExistsSync(path.join(componentPathRoot,"loader.ts"))){componentImplType="ts"}else{const pathSegs=componentPathRoot.toLowerCase().split("/");if(pathSegs.includes("js")){componentImplType="js"}else{componentImplType="ts"}}}return componentImplType};Utils.prototype.safeSetExtension=function(context,extnValue){let existingContext=context.rulePack.getExtension();if(!existingContext){existingContext={}}const newContext={...existingContext,...extnValue};context.rulePack.setExtension(newContext)};Utils.prototype.disableRulePack=function(context){const rulesInPack=context.rulePack.getEnabledRuleList();rulesInPack.forEach(rule=>{context.rulePack.disableRule(rule)})};Utils.prototype.isMonoPackMember=function(context,metadata){let mpMember=false;const owningPack=metadata.pack;if(owningPack){const packInfo=this.componentInfo(context,owningPack);if(packInfo&&packInfo.type==="mono-pack"){mpMember=true}}return mpMember};Utils.prototype.cloneObject=function(o){return JSON.parse(JSON.stringify(o))};module.exports=new Utils;
6
+ const path=require("path");const Utils=function(){this.rootPoint=this.toJAFPath(path.resolve(".")).length+1;this.isWindows=path.sep!=="/";this.noJSWarnDone=false};Utils.prototype.getKeyPathInfoForRulepack=function(context,auditBase){const paths={isBuiltOutput:false,componentRootFolder:null,exchangeCacheFolder:null,generalSourceRoot:"src",jsSource:null,tsSource:null,base:null};let jetConfig=context.ojetConfig;if(!jetConfig&&auditBase){const remoteConfig=path.join(auditBase,"oraclejetconfig.json");if(context.utils.fsUtils.pathExistsSync(remoteConfig)){jetConfig=context.utils.fsUtils.readJsonSync(remoteConfig)}}let jsDir="js";let tsDir="ts";paths.isBuiltOutput=context.rulePack.getRuleCustomOption("auditBuildOutput");paths.base=path.resolve(auditBase);if(jetConfig){jsDir=jetConfig.paths.source.javascript||"js";tsDir=jetConfig.paths.source.typescript||"ts";paths.exchangeCacheFolder=jetConfig.paths.source.exchangeComponents||"jet_components";paths.componentRootFolder=jetConfig.paths.source.components||"jet-composites";if(!paths.isBuiltOutput){paths.generalSourceRoot=jetConfig.paths.source.common||"src"}else{paths.generalSourceRoot=jetConfig.paths.staging.web||"web"}}paths.jsSource=this.toJAFPath(path.join(paths.generalSourceRoot,jsDir));if(!paths.isBuiltOutput){paths.tsSource=this.toJAFPath(path.join(paths.generalSourceRoot,tsDir))}return paths};Utils.prototype.matchComponentPath=function(context,checkPathBase,recursion){let checkPath=this.toJAFPath(checkPathBase);let componentMatch;if(context.rulePack.getExtension()&&context.rulePack.getExtension().hasOwnProperty("allAuditableFilePaths")){if(context.rulePack.getExtension().allAuditableFilePaths.has(checkPath)){const x=context.rulePack.getExtension().allAuditableFilePaths;componentMatch=context.rulePack.getExtension().allAuditableFilePaths.get(checkPath)}else if(checkPath.includes(context.rulePack.getExtension().componentHome)){if(context.rulePack.getExtension().auditableComponentPaths.has(checkPath)){componentMatch=context.rulePack.getExtension().auditableComponentPaths.get(checkPath)}else{const parentPath=path.resolve(checkPathBase,".."+path.sep);componentMatch=this.matchComponentPath(context,parentPath,true)}if(!recursion){context.rulePack.getExtension().allAuditableFilePaths.set(checkPath,componentMatch)}}else{context.rulePack.getExtension().allAuditableFilePaths.set(checkPath)}}else{this.reportMissingBootstrapInfo(context,"allAuditableFilePaths")}return componentMatch};Utils.prototype.reportMissingBootstrapInfo=function(context,checkTopic){const msg=context.utils.msgLib;const extnContext=context.rulePack.getExtension();if(!extnContext||!extnContext.bootStrap){const bootstrapRule=context.rulePack.getPrefix().toLowerCase()+"-bootstrap";if(context.rulePack.isRuleDisabled(bootstrapRule)){msg.error(`You must enable the ${bootstrapRule} rule to run in order to carry out a full component set audit`)}else{msg.error(`Apparent bootstrap error, no information cached for ${checkTopic}`)}context.rulePack.setExtension({...extnContext,bootStrap:true})}};Utils.prototype.componentInfo=function(context,componentName){if(context.rulePack.getExtension()&&context.rulePack.getExtension().hasOwnProperty("allComponents")){return context.rulePack.getExtension().allComponents.get(componentName)}else{this.reportMissingBootstrapInfo(context,"allComponents")}return};Utils.prototype.getComponentFullName=function(metadata){return metadata.pack?`${metadata.pack}-${metadata.name}`:metadata.name};Utils.prototype.getComponentType=function(metadata){return metadata.type?metadata.type:"composite"};Utils.prototype.flattenComponentProperties=function(metaDef,valueAttribute,filterCondition,parentPath){let flattenedProps=[];if(metaDef.hasOwnProperty("properties")){const propArray=Object.keys(metaDef.properties);propArray.forEach(propertyName=>{const propertyMetadata=metaDef.properties[propertyName];let key;if(!parentPath){key=propertyName}else{key=parentPath+"."+propertyName}if(!filterCondition||filterCondition(propertyName,propertyMetadata)){flattenedProps.push({key:key,value:metaDef.properties[propertyName][valueAttribute]})}const subPropsArray=this.flattenComponentProperties(metaDef.properties[propertyName],valueAttribute,filterCondition,key);flattenedProps=flattenedProps.concat(subPropsArray)})}return flattenedProps};Utils.prototype.setupFileMethodMapping=function(context,node){const NT=context.utils.AstUtils.getNodeTypes();const fileName=context.filepath;const withinComponent=this.matchComponentPath(context,path.dirname(fileName));if(withinComponent&&node.parent){if(node.parent.type===NT.ASSIGNMENT_EXPR&&node.parent.operator==="="){if(node.parent.left&&node.parent.left.property&&node.parent.left.property.type==NT.IDENTIFIER&&node.parent.left.property.name){const methodDef={name:node.parent.left.property.name,parameters:node.params?node.params.length:0};this.cacheFileMethod(context,fileName,methodDef)}}else if(node.parent.type===NT.METH_DEF&&node.parent.kind==="method"){if(node.parent.key&&node.parent.key.name){const methodDef={name:node.parent.key.name,parameters:node.params?node.params.length:0};this.cacheFileMethod(context,fileName,methodDef)}}else if(node.parent.type===NT.CLASS_PROP||node.parent.type===NT.PROPERTY_DEF){if(node.parent.key&&node.parent.key.name){const methodDef={name:node.parent.key.name,parameters:node.params?node.params.length:0};this.cacheFileMethod(context,fileName,methodDef)}}}};Utils.prototype.setupFileMethodMappingFromMethodDefintion=function(context,node){const NT=context.utils.AstUtils.getNodeTypes();const fileName=context.filepath;const withinComponent=this.matchComponentPath(context,path.dirname(fileName));if(withinComponent){const methodDef={parameters:0};if(node.key&&node.key.type===NT.IDENTIFIER){methodDef.name=node.key.name;if(node.value&&node.value.type===NT.FUNC_EXPR&&node.value.params){methodDef.parameters=node.value.params.length}}if(methodDef.name){this.cacheFileMethod(context,fileName,methodDef)}}};Utils.prototype.cacheFileMethod=function(context,filePath,methodDef){if(!context.rulePack.getExtension().allDefinedFileMethods){context.rulePack.getExtension().allDefinedFileMethods=new Map}if(!context.rulePack.getExtension().allDefinedFileMethods.has(filePath)){context.rulePack.getExtension().allDefinedFileMethods.set(filePath,{methods:new Map})}if(!context.rulePack.getExtension().allDefinedFileMethods.get(filePath).methods.has(methodDef.name)){context.rulePack.getExtension().allDefinedFileMethods.get(filePath).methods.set(methodDef.name,methodDef)}};Utils.prototype.deriveViewModels=function(context,node){const fileName=context.filepath;if(context.rulePack.getExtension()&&context.rulePack.getExtension().hasOwnProperty("allComponents")){const withinComponent=this.matchComponentPath(context,path.dirname(fileName));const componentInfo=context.rulePack.getExtension().allComponents.get(withinComponent);if(withinComponent&&componentInfo&&componentInfo.type==="composite"&&!componentInfo.viewModel.resolved){const targetLoaderExt=componentInfo.language==="tsx"?".ts":`.${componentInfo.language}`;if(path.basename(fileName,targetLoaderExt)==="loader"){switch(componentInfo.language){case"js":case"ts":const registerInfo=this.getLoaderRegisterInfo(context,node);if(registerInfo){const vmRelativeFilePath=this._mapVMToImpl(context,node,registerInfo.viewModel,componentInfo.language==="ts");if(vmRelativeFilePath){const fullVMPath=this._expandPathInContext(context,withinComponent,vmRelativeFilePath);if(fullVMPath){componentInfo.viewModel={path:this.toJAFPath(path.resolve(".",`${fullVMPath}.${componentInfo.language}`)),resolved:true,skip:false}}}}break;case"tsx":break}}}}else{this.reportMissingBootstrapInfo(context,"allComponents")}};Utils.prototype.getLoaderRegisterInfo=function(context,node){const msg=context.utils.msgLib;const NT=context.utils.AstUtils.getNodeTypes();let registerInfo;if(node.callee.type=NT.MEMBER_EXPR&&node.callee.object&&node.arguments&&node.arguments.length>0){let isRegister=false;let oldStyle=false;switch(node.callee.object.type){case NT.IDENTIFIER:if(node.callee.object.name==="Composite"){isRegister=this._astPropertyIdentifierName(context,node.callee,"register")}break;case NT.MEMBER_EXPR:if(node.callee.property&&node.callee.property.type===NT.IDENTIFIER&&node.callee.property.name==="register"){if(this._astPropertyIdentifierName(context,node.callee.object,"Composite")){isRegister=node.callee.object.object&&node.callee.object.object.type===NT.IDENTIFIER&&node.callee.object.object.name==="oj";if(isRegister){oldStyle=true}}}break}if(isRegister){registerInfo={oldStyle:oldStyle};const tagArg=node.arguments[0];const def=node.arguments[1];registerInfo.tag=tagArg.type===NT.LITERAL?tagArg.value:"?";if(def.type===NT.OBJ_EXPR){vmProp=def.properties.filter(prop=>prop.key.name==="viewModel");if(vmProp.length===1){switch(vmProp[0].value.type){case NT.IDENTIFIER:registerInfo.viewModel=vmProp[0].value.name;break;case NT.OBJ_EXPR:if(vmProp[0].value.properties&&vmProp[0].value.properties[0]&&vmProp[0].value.properties[0].key.name==="inline"){registerInfo.viewModel=vmProp[0].value.properties[0].value.name;registerInfo.usesPromises=true}break;case NT.MEMBER_EXPR:if(vmProp[0].value.property&&vmProp[0].value.property.type===NT.IDENTIFIER){registerInfo.viewModel=vmProp[0].value.object.name;registerInfo.transpiled=true}break;case"TSAsExpression":if(vmProp[0].value.expression&&vmProp[0].value.expression.type===NT.IDENTIFIER){registerInfo.viewModel=vmProp[0].value.expression.name}else if(vmProp[0].value.expression&&vmProp[0].value.expression.type===NT.AS_EXPR){registerInfo.viewModel=vmProp[0].value.expression.expression.name;msg.msg(`WARNING: Component loader file ${context.filepath} attempts to redefine the composite.register viewModel interface`)}break}}const cssCheck=def.properties.filter(prop=>prop.key.name==="css");if(cssCheck.length>0){registerInfo.registerCSS=true}}}}return registerInfo};Utils.prototype._astPropertyIdentifierName=function(context,node,checkName){const NT=context.utils.AstUtils.getNodeTypes();return node&&node.property&&node.property.type===NT.IDENTIFIER&&node.property.name===checkName};Utils.prototype._mapVMToImpl=function(context,node,vmName,useImports){let vmPathDef;if(vmName){let rootNode=node;if(useImports){vmPathDef=this._getImportPath(context,rootNode,vmName)}else{vmPathDef=this._getDefineStatementPath(context,rootNode,vmName);if(!vmPathDef){vmPathDef=this._mapToRequireAssignment(context,node,vmName)}}}return vmPathDef};Utils.prototype._mapToRequireAssignment=function(context,node,vmName){const NT=context.utils.AstUtils.getNodeTypes();let requirePath;const vmDeclNode=this._locateDeclaration(context,node,vmName);if(vmDeclNode.type===NT.CALL_EXPR&&vmDeclNode.callee.type===NT.IDENTIFIER&&vmDeclNode.callee.name==="require"){if(vmDeclNode.arguments&&vmDeclNode.arguments.length===1&&vmDeclNode.arguments[0].type===NT.LITERAL){requirePath=vmDeclNode.arguments[0].value}}return requirePath};Utils.prototype._getImportPath=function(context,node,importAs){const NT=context.utils.AstUtils.getNodeTypes();const bodyNodeArray=context.utils.AstUtils.getBody();let definePath;for(let i=0;i<bodyNodeArray.length;i++){const testNode=bodyNodeArray[i];switch(testNode.type){case"ImportDeclaration":if(testNode.specifiers&&Array.isArray(testNode.specifiers)&&testNode.specifiers.length===1&&(testNode.specifiers[0].type===NT.IMPORT_DEF_SPECIFIER||testNode.specifiers[0].type===NT.IMPORT_SPECIFIER)&&testNode.specifiers[0].local&&testNode.specifiers[0].local.name===importAs){definePath=testNode.source.value}break;case"TSImportEqualsDeclaration":if(testNode.id&&testNode.id.type===NT.IDENTIFIER&&testNode.id.name===importAs&&testNode.moduleReference&&testNode.moduleReference.type===NT.EXTERN_MOD_REF&&testNode.moduleReference.expression&&testNode.moduleReference.expression.type===NT.LITERAL){definePath=testNode.moduleReference.expression.value}break}if(definePath){;break}}return definePath};Utils.prototype._getDefineStatementPath=function(context,node,defineParam){const NT=context.utils.AstUtils.getNodeTypes();let checkNode=node.parent;let definePath;while(checkNode){if(checkNode.type===NT.CALL_EXPR&&checkNode.callee.name==="define"){definePath=context.utils.AstUtils.parseDefine(checkNode)[defineParam]}checkNode=checkNode.parent}return definePath};Utils.prototype._expandPathInContext=function(context,componentName,requirePath){let targetPath=requirePath;const parsePluginParts=requirePath.split("!");if(parsePluginParts.length>1){targetPath=parsePluginParts[1]}let pathParts=targetPath.split("/");const decodeRoot=pathParts[0];if(decodeRoot==="."){pathParts[0]=this.rootPathForComponent(context,componentName)}else{const remotePart=this.rootPathForComponent(context,decodeRoot);if(!remotePart){pathParts=[]}else{pathParts[0]=remotePart}}return pathParts.join("/")};Utils.prototype.rootPathForComponent=function(context,componentName){if(context.rulePack.getExtension().allComponents.has(componentName)){return context.rulePack.getExtension().allComponents.get(componentName).rootFolder}};Utils.prototype.getVMMethodsForLocalComposite=function(context,component){let vmMethods;const msg=context.utils.msgLib;const opts=context.rulePack.getRuleCustomOptions();if(component.local&&component.type==="composite"){if(!component.viewModel.skip){if(!component.viewModel.resolved&&!component.viewModel.warned){if(!opts.testMode){msg.msg(`Warning: unable to derive the correct viewModel implementation for component ${component.fullName}, either your audit run does not include .js/.ts files, or you may need to set 'extension.audit.jetwc.viewModel' in the metadata to provide a hint`)}component.viewModel.warned=true}else{const rpState=context.rulePack.getExtension();if(rpState.allDefinedFileMethods&&rpState.allDefinedFileMethods.size>0){const vmMethodDef=rpState.allDefinedFileMethods.get(component.viewModel.path);if(vmMethodDef){vmMethods=vmMethodDef.methods}}else{if(!this.noJSWarnDone){msg.msg("Error: No JavaScript / TypeScript files have been processed. You need to ensure that your audit fileset includes .js, .ts, html and .json files to enable all audits in this rule-set. Use the ojaf --dryrun command to determine what files are covered by the audit");this.noJSWarnDone=true}}}}}return vmMethods};Utils.prototype.decomposeAssignment=function(auditContext,assignmentNode){const NT=auditContext.utils.AstUtils.getNodeTypes();const breakdown=[];this._walkAssignmentNodes(auditContext,assignmentNode.left,breakdown);if(!breakdown.includes("this")){const parentAssignment=breakdown[breakdown.length-1];const initialAssignmentNode=this._locateDeclaration(auditContext,assignmentNode,parentAssignment);if(initialAssignmentNode){if(initialAssignmentNode==="<parameter>"){breakdown.push("<parameter>")}else if(initialAssignmentNode.type===NT.THIS_EXPR){breakdown.push("this")}else if(initialAssignmentNode.type===NT.IDENTIFIER){breakdown.push(initialAssignmentNode.name);const indirectAssignmentNode=this._locateDeclaration(auditContext,assignmentNode,initialAssignmentNode.name);if(indirectAssignmentNode==="<parameter>"){breakdown.push("<parameter>")}else if(indirectAssignmentNode.type===NT.THIS_EXPR){breakdown.push("this")}}}}return breakdown};Utils.prototype._walkAssignmentNodes=function(context,node,accumulator){const NT=context.utils.AstUtils.getNodeTypes();switch(node.type){case NT.MEMBER_EXPR:accumulator.push(node.property.name);if(node.object){this._walkAssignmentNodes(context,node.object,accumulator)}break;case NT.IDENTIFIER:accumulator.push(node.name);break;case NT.THIS_EXPR:accumulator.push("this");break}};Utils.prototype._locateDeclaration=function(context,node,searchVariable){const NT=context.utils.AstUtils.getNodeTypes();let initialAssignment;let workingNode=node;while(!initialAssignment){if(workingNode.body&&workingNode.body.length>0){workingNode.body.forEach(bodyNode=>{if(bodyNode.type===NT.VAR_DECLARATION){bodyNode.declarations.forEach(declNode=>{if(declNode.id.type===NT.IDENTIFIER&&declNode.id.name===searchVariable){initialAssignment=declNode.init}})}})}else if(workingNode.params&&workingNode.params.length>0){workingNode.params.forEach(paramNode=>{if(paramNode.name===searchVariable){initialAssignment="<parameter>"}})}if(!workingNode.parent){break}else{workingNode=workingNode.parent}}return initialAssignment};Utils.prototype.extractComponentInfoFromJSONFile=function(auditContext,componentFolder,fileName,isLocal,fromPrecompile){const msg=auditContext.utils.msgLib;let componentInfo={};const mdFile=`${componentFolder}/${fileName}`;const compMetadata=auditContext.utils.fsUtils.readJsonSync(mdFile);if(compMetadata!==null){return this.extractComponentInfoFromMetadata(auditContext,compMetadata,componentFolder,isLocal,fromPrecompile)}else{msg.error(`Invalid JSON in component metadata ${mdFile}, component ignored`)}return};Utils.prototype.extractComponentInfoFromMetadata=function(auditContext,compMetadata,componentFolder,isLocal,fromPrecompile){const msg=auditContext.utils.msgLib;let componentInfo={};componentInfo.name=compMetadata.name;componentInfo.pack=compMetadata.pack;if(fromPrecompile&&compMetadata.pack){if(compMetadata.name.startsWith(`${compMetadata.pack}-`)){componentInfo.name=compMetadata.name.substring(compMetadata.pack.length+1)}}componentInfo.fullName=componentInfo.pack?`${componentInfo.pack}-${componentInfo.name}`:componentInfo.name;componentInfo.displayName=compMetadata.displayName;componentInfo.description=compMetadata.description;componentInfo.version=compMetadata.version;componentInfo.jetVersion=compMetadata.jetVersion;componentInfo.license=compMetadata.license;componentInfo.extension=compMetadata.extension;if(compMetadata.icon){componentInfo.icon=compMetadata.icon}componentInfo.type=compMetadata.type?compMetadata.type:"composite";componentInfo.subcomponentType=compMetadata.subcomponentType;componentInfo.local=isLocal;componentInfo.rootFolder=this.toJAFPath(componentFolder);componentInfo.requirePaths=new Set;switch(componentInfo.type){case"reference":if(compMetadata.extension&&compMetadata.extension.oracle&&compMetadata.extension.oracle.businessApprovals){componentInfo.ba=compMetadata.extension.oracle.businessApprovals}if(compMetadata.paths&&compMetadata.paths.name){componentInfo.requirePaths.add(compMetadata.paths.name)}else{const extractPathSegments=compMetadata.package.split("/");if(extractPathSegments.length>1){componentInfo.requirePaths.add(extractPathSegments[1])}else{componentInfo.requirePaths.add(extractPathSegments[0])}}break;case"composite":if(compMetadata.styleClasses){componentInfo.styleClasses=compMetadata.styleClasses}if(compMetadata.styleVariables){componentInfo.styleVariables=compMetadata.styleVariables}if(compMetadata.slots){componentInfo.slots=compMetadata.slots}if(compMetadata.properties){componentInfo.properties=compMetadata.properties}if(compMetadata.events){componentInfo.events=compMetadata.events}if(compMetadata.methods&&Object.keys(compMetadata.methods).length>0){componentInfo.methods=compMetadata.methods}componentInfo.viewModel={resolved:false};if(compMetadata&&compMetadata.extension&&compMetadata.extension.audit&&compMetadata.extension.audit.jetwc&&compMetadata.extension.audit.jetwc.hasOwnProperty("viewModel")){const overrideVM=compMetadata.extension.audit.jetwc.viewModel;if(overrideVM){componentInfo.viewModel={path:this.toJAFPath(path.resolve(".",componentInfo.rootFolder,overrideVM)),resolved:true,skip:false}}else{componentInfo.viewModel={skip:true}}}case"resource":componentInfo.requirePaths.add(".");if(compMetadata.pack){componentInfo.requirePaths.add(`${componentInfo.pack}/${componentInfo.name}`)}else{componentInfo.requirePaths.add(componentInfo.name)}if(compMetadata.dependencies){componentInfo.dependencies=[];Object.keys(compMetadata.dependencies).forEach(depname=>{componentInfo.dependencies.push({name:depname,range:compMetadata.dependencies[depname]})})}break}return componentInfo};Utils.prototype.diagnosticReplacer=function(key,value){if(value instanceof Map){return Array.from(value).map(([vKey,vValue])=>{return{[vKey]:vValue?vValue:""}})}if(value instanceof Set){return Array.from(value)}return value};Utils.prototype.toJAFPath=function(sourcePath){if(sourcePath&&this.isWindows){return sourcePath.replace(/\\\\|\\/g,"/")}return sourcePath};Utils.prototype.toNativePath=function(sourcePath){if(sourcePath&&this.isWindows){return sourcePath.replace(/\//g,"\\")}return sourcePath};Utils.prototype.getDirectoryName=function(filePath){return path.dirname(filePath)};Utils.prototype.shouldIgnoreCheck=function(context,auditName,componentName,scope,target){let ignore=false;const checkComponentDef=context.rulePack.getExtension().allComponents.get(componentName);if(checkComponentDef){let targetDef;if(scope&&checkComponentDef[scope]){if(target.includes(".")&&scope==="properties"){targetDef=this.getPropertyAttributeFromPath(context,componentName,target)}else{targetDef=checkComponentDef[scope][target==="__default__"?"":target]}}else{targetDef=checkComponentDef}if(targetDef&&targetDef.extension&&targetDef.extension.hasOwnProperty("audit")&&targetDef.extension.audit.hasOwnProperty("ignore")){const ignoreArray=targetDef.extension.audit.ignore;ignore=ignoreArray.includes(auditName)}}return ignore};Utils.prototype.getPropertyAttributeFromPath=function(context,componentName,targetPath,attribute){const checkComponentDef=context.rulePack.getExtension().allComponents.get(componentName);let targetDef;if(checkComponentDef&&checkComponentDef.properties){if(targetPath.includes(".")){const propPath=targetPath.split(".");targetDef=checkComponentDef.properties[propPath[0]];for(let i=1;i<propPath.length;i++){targetDef=targetDef.properties[propPath[i]]}}else{targetDef=checkComponentDef.properties[targetPath]}}if(attribute){return targetDef[attribute]}else{return targetDef}};Utils.prototype.detectComponentSourceType=function(context,componentPathRoot,isVComponent){let componentImplType;if(isVComponent){componentImplType="tsx"}else{const{fsUtils}=context.utils;if(fsUtils.fileExistsSync(`${componentPathRoot}/loader.js`)){componentImplType="js"}else if(fsUtils.fileExistsSync(path.join(componentPathRoot,"loader.ts"))){componentImplType="ts"}else{const pathSegs=componentPathRoot.toLowerCase().split("/");if(pathSegs.includes("js")){componentImplType="js"}else{componentImplType="ts"}}}return componentImplType};Utils.prototype.safeSetExtension=function(context,extnValue){let existingContext=context.rulePack.getExtension();if(!existingContext){existingContext={}}const newContext={...existingContext,...extnValue};context.rulePack.setExtension(newContext)};Utils.prototype.disableRulePack=function(context){const rulesInPack=context.rulePack.getEnabledRuleList();rulesInPack.forEach(rule=>{context.rulePack.disableRule(rule)})};Utils.prototype.isMonoPackMember=function(context,metadata){let mpMember=false;const owningPack=metadata.pack;if(owningPack){const packInfo=this.componentInfo(context,owningPack);if(packInfo&&packInfo.type==="mono-pack"){mpMember=true}}return mpMember};Utils.prototype.cloneObject=function(o){return JSON.parse(JSON.stringify(o))};module.exports=new Utils;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const path=require("path");const Utils=require("./jetwcutils-componentAuditUtils");const tsxUtils=require("./jetwcutils-tsxUtils");const ComponentFinder=function(){this.runOnce=false};ComponentFinder.prototype.findAllComponents=function(auditContext,auditBase,projectPathInfo,componentRoots){const msg=auditContext.utils.msgLib;const metadataPatches=this._readPatchFile(auditContext,auditBase);let masterComponentList=[];if(!this.runOnce||auditContext.rulePack.getRuleOptions().testMode){if(projectPathInfo.exchangeCacheFolder){masterComponentList=masterComponentList.concat(this._discoverComponentsFromRoot(path.join(projectPathInfo.base,projectPathInfo.exchangeCacheFolder),false,false,auditContext,null,metadataPatches))}if(componentRoots&&componentRoots.length>0){componentRoots.forEach(root=>{let target=root;if(auditContext.utils.fsUtils.getFileTypeSync(target)==="f"){target=path.dirname(root);msg.msg(`Warning: Incorrectly defined "components" array entry in JAF configuration file. Entries should list folders only not explicit file names.\n Bad entry: "${root}"\nAudit will process the "${target}" folder instead.\n`)}masterComponentList=masterComponentList.concat(this._discoverComponentsFromRoot(target,true,projectPathInfo.isBuiltOutput,auditContext,null,metadataPatches))})}else{if(projectPathInfo.componentRootFolder){masterComponentList=masterComponentList.concat(this._discoverComponentsFromRoot(path.join(projectPathInfo.base,projectPathInfo.jsSource,projectPathInfo.componentRootFolder),true,projectPathInfo.isBuiltOutput,auditContext,null,metadataPatches));if(projectPathInfo.tsSource&&projectPathInfo.tsSource!==projectPathInfo.jsSource){masterComponentList=masterComponentList.concat(this._discoverComponentsFromRoot(path.join(projectPathInfo.base,projectPathInfo.tsSource,projectPathInfo.componentRootFolder),true,false,auditContext,null,metadataPatches))}}}this.runOnce=true;this.masterComponentList=masterComponentList}return this.masterComponentList};ComponentFinder.prototype._discoverComponentsFromRoot=function(rootDir,isLocal,builtOutput,auditContext,parentPack,metadataPatches){const msg=auditContext.utils.msgLib;let componentArray=[];if(auditContext.utils.fsUtils.pathExistsSync(rootDir)){const compFileStructure=auditContext.utils.fsUtils.readDir(rootDir);compFileStructure.forEach(l1file=>{let componentInfo;if(!l1file.isFile&&l1file.files.length>0){l1file.files.forEach(l2file=>{if(!builtOutput){if(l2file.isFile&&l2file.name==="component.json"){componentInfo=Utils.extractComponentInfoFromJSONFile(auditContext,path.join(rootDir,l1file.name),"component.json",isLocal,false);componentArray.push(componentInfo);if(componentInfo.type&&componentInfo.type==="pack"){const packMembers=this._discoverComponentsFromRoot(Utils.toJAFPath(path.join(rootDir,l1file.name)),isLocal,false,auditContext,componentInfo.name,metadataPatches);componentArray=componentArray.concat(packMembers)}}else if(l2file.isFile&&path.extname(l2file.name)===".tsx"){componentInfo=tsxUtils.extractComponentInfoFromTSXFile(auditContext,path.join(rootDir,l1file.name),l2file.name,metadataPatches);if(componentInfo){componentArray.push(componentInfo)}}}else{if(!l2file.isFile&&l2file.files.length>0){l2file.files.forEach(l3file=>{if(l3file.isFile&&l3file.name==="component.json"){componentInfo=Utils.extractComponentInfoFromJSONFile(auditContext,path.join(rootDir,l1file.name,l2file.name),"component.json",isLocal,false);if(!componentInfo.pack){componentArray.push(componentInfo);if(componentInfo.type==="pack"){const packMembers=this._discoverComponentsFromRoot(Utils.toJAFPath(path.join(rootDir,l1file.name,l2file.name)),isLocal,false,auditContext,componentInfo.name,metadataPatches);componentArray=componentArray.concat(packMembers)}}}else if(l3file.isFile&&path.extname(l3file.name)===".tsx"){componentInfo=tsxUtils.extractComponentInfoFromTSXFile(auditContext,path.join(rootDir,l1file.name,l2file.name),l3file.name,metadataPatches);if(componentInfo){componentArray.push(componentInfo)}}})}}})}else{if(l1file.isFile&&l1file.name==="component.json"){componentInfo=Utils.extractComponentInfoFromJSONFile(auditContext,rootDir,"component.json",isLocal,false);if(componentInfo.type!=="pack"||componentInfo.name!==parentPack){componentArray.push(componentInfo)}}else if(l1file.isFile&&path.extname(l1file.name)===".tsx"){componentInfo=tsxUtils.extractComponentInfoFromTSXFile(auditContext,rootDir,l1file.name,metadataPatches);if(componentInfo){componentArray.push(componentInfo)}}}})}return componentArray};ComponentFinder.prototype._readPatchFile=function(auditContext,auditBase){const{fsUtils,msgLib}=auditContext.utils;const metadataPatchInstructionFile=auditContext.userDefs?.VComponentMetadataPatches;let actualPatchFilePath;if(metadataPatchInstructionFile){if(fsUtils.fileExistsSync(metadataPatchInstructionFile)){actualPatchFilePath=metadataPatchInstructionFile}else if(fsUtils.fileExistsSync(path.join(auditBase,metadataPatchInstructionFile))){actualPatchFilePath=path.join(auditBase,metadataPatchInstructionFile)}}if(actualPatchFilePath){return fsUtils.readJsonSync(actualPatchFilePath)}return};module.exports=new ComponentFinder;
6
+ const path=require("path");const Utils=require("./jetwcutils-componentAuditUtils");const tsxUtils=require("./jetwcutils-tsxUtils");const ComponentFinder=function(){this.runOnce=false};ComponentFinder.prototype.findAllComponents=function(auditContext,auditBase,projectPathInfo,componentRoots){const msg=auditContext.utils.msgLib;const metadataPatches=this._readPatchFile(auditContext,auditBase);let masterComponentList=[];if(!this.runOnce||auditContext.rulePack.getRuleCustomOption("testMode")){if(projectPathInfo.exchangeCacheFolder){masterComponentList=masterComponentList.concat(this._discoverComponentsFromRoot(path.join(projectPathInfo.base,projectPathInfo.exchangeCacheFolder),false,false,auditContext,null,metadataPatches))}if(componentRoots&&componentRoots.length>0){componentRoots.forEach(root=>{let target=root;if(auditContext.utils.fsUtils.getFileTypeSync(target)==="f"){target=path.dirname(root);msg.msg(`Warning: Incorrectly defined "components" array entry in JAF configuration file. Entries should list folders only not explicit file names.\n Bad entry: "${root}"\nAudit will process the "${target}" folder instead.\n`)}masterComponentList=masterComponentList.concat(this._discoverComponentsFromRoot(target,true,projectPathInfo.isBuiltOutput,auditContext,null,metadataPatches))})}else{if(projectPathInfo.componentRootFolder){masterComponentList=masterComponentList.concat(this._discoverComponentsFromRoot(path.join(projectPathInfo.base,projectPathInfo.jsSource,projectPathInfo.componentRootFolder),true,projectPathInfo.isBuiltOutput,auditContext,null,metadataPatches));if(projectPathInfo.tsSource&&projectPathInfo.tsSource!==projectPathInfo.jsSource){masterComponentList=masterComponentList.concat(this._discoverComponentsFromRoot(path.join(projectPathInfo.base,projectPathInfo.tsSource,projectPathInfo.componentRootFolder),true,false,auditContext,null,metadataPatches))}}}this.runOnce=true;this.masterComponentList=masterComponentList}return this.masterComponentList};ComponentFinder.prototype._discoverComponentsFromRoot=function(rootDir,isLocal,builtOutput,auditContext,parentPack,metadataPatches){const msg=auditContext.utils.msgLib;let componentArray=[];if(auditContext.utils.fsUtils.pathExistsSync(rootDir)){const compFileStructure=auditContext.utils.fsUtils.readDir(rootDir);compFileStructure.forEach(l1file=>{let componentInfo;if(!l1file.isFile&&l1file.files.length>0){l1file.files.forEach(l2file=>{if(!builtOutput){if(l2file.isFile&&l2file.name==="component.json"){componentInfo=Utils.extractComponentInfoFromJSONFile(auditContext,path.join(rootDir,l1file.name),"component.json",isLocal,false);componentArray.push(componentInfo);if(componentInfo.type&&componentInfo.type==="pack"){const packMembers=this._discoverComponentsFromRoot(Utils.toJAFPath(path.join(rootDir,l1file.name)),isLocal,false,auditContext,componentInfo.name,metadataPatches);componentArray=componentArray.concat(packMembers)}}else if(l2file.isFile&&path.extname(l2file.name)===".tsx"){componentInfo=tsxUtils.extractComponentInfoFromTSXFile(auditContext,path.join(rootDir,l1file.name),l2file.name,metadataPatches);if(componentInfo){componentArray.push(componentInfo)}}}else{if(!l2file.isFile&&l2file.files.length>0){l2file.files.forEach(l3file=>{if(l3file.isFile&&l3file.name==="component.json"){componentInfo=Utils.extractComponentInfoFromJSONFile(auditContext,path.join(rootDir,l1file.name,l2file.name),"component.json",isLocal,false);if(!componentInfo.pack){componentArray.push(componentInfo);if(componentInfo.type==="pack"){const packMembers=this._discoverComponentsFromRoot(Utils.toJAFPath(path.join(rootDir,l1file.name,l2file.name)),isLocal,false,auditContext,componentInfo.name,metadataPatches);componentArray=componentArray.concat(packMembers)}}}else if(l3file.isFile&&path.extname(l3file.name)===".tsx"){componentInfo=tsxUtils.extractComponentInfoFromTSXFile(auditContext,path.join(rootDir,l1file.name,l2file.name),l3file.name,metadataPatches);if(componentInfo){componentArray.push(componentInfo)}}})}}})}else{if(l1file.isFile&&l1file.name==="component.json"){componentInfo=Utils.extractComponentInfoFromJSONFile(auditContext,rootDir,"component.json",isLocal,false);if(componentInfo.type!=="pack"||componentInfo.name!==parentPack){componentArray.push(componentInfo)}}else if(l1file.isFile&&path.extname(l1file.name)===".tsx"){componentInfo=tsxUtils.extractComponentInfoFromTSXFile(auditContext,rootDir,l1file.name,metadataPatches);if(componentInfo){componentArray.push(componentInfo)}}}})}return componentArray};ComponentFinder.prototype._readPatchFile=function(auditContext,auditBase){const{fsUtils,msgLib}=auditContext.utils;const metadataPatchInstructionFile=auditContext.userDefs?.VComponentMetadataPatches;let actualPatchFilePath;if(metadataPatchInstructionFile){if(fsUtils.fileExistsSync(metadataPatchInstructionFile)){actualPatchFilePath=metadataPatchInstructionFile}else if(fsUtils.fileExistsSync(path.join(auditBase,metadataPatchInstructionFile))){actualPatchFilePath=path.join(auditBase,metadataPatchInstructionFile)}}if(actualPatchFilePath){return fsUtils.readJsonSync(actualPatchFilePath)}return};module.exports=new ComponentFinder;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const Utils=require("./jetwcutils-componentAuditUtils");const path=require("path");const TsxUtils=function(){};TsxUtils.prototype.extractComponentInfoFromTSXFile=function(auditContext,componentFolder,fileName,metadataPatches){const{msgLib,fsUtils}=auditContext.utils;const packRegEx=/@ojmetadata[\s]*pack[\s]*[\"|'](?<pack>[a-zA-Z\-0-9]*)[\"|']/mg;const versionRegEx=/@ojmetadata[\s]*version[\s]*[\"|'](?<version>[\.0-9\-a-zA-Z]*)[\"|']/mg;const jetVersionRegEx=/@ojmetadata[\s]*jetVersion[\s]*[\"|'](?<version>[\.0-9\-a-zA-Z^~><=]*)[\"|']/mg;const tsxFile=path.join(componentFolder,fileName);const fileAsStr=auditContext.utils.fsUtils.readFileSync(tsxFile);const componentIdentification=this.getVComponentElementNameAndImpl(fileAsStr,msgLib);const fullName=componentIdentification.elementName;const className=componentIdentification.class;const componentName=this.getVComponentComponentName(fileAsStr);let precompiledInfo=auditContext.utils.metaLib.getTagMetadata(fullName);if(!precompiledInfo&&auditContext.rulePack.getRuleOptions().hasOwnProperty("precompileCache")&&auditContext.rulePack.getRuleOptions().testMode){msgLib.info(`Test mode, bypassing Typescript compilation...`);const jsonLoc=path.join(auditContext.rulePack.getRuleOptions().precompileCache,`${fullName}.json`);if(fsUtils.fileExistsSync(jsonLoc)){precompiledInfo=fsUtils.readJsonSync(jsonLoc)}else{msgLib.error(`Missing test mode metadata for ${jsonLoc}`)}}if(precompiledInfo){if(metadataPatches){let componentPatches;if(precompiledInfo.pack){componentPatches=metadataPatches?.[precompiledInfo.pack]?.[precompiledInfo.name]}else{componentPatches=metadataPatches?.[precompiledInfo.name]}if(componentPatches&&Array.isArray(componentPatches)){msgLib.info(`Processing metadata type patches for ${fullName} [${componentPatches.length} patch(es) specified]`);componentPatches.forEach(patch=>{switch(patch.target){case"property":this._handlePropertyTypePatch(patch,precompiledInfo);break;case"method":this._handleMethodTypePatch(patch,precompiledInfo);break;case"event":this._handleEventDetailTypePatch(patch,precompiledInfo);break;case"slot":this._handleSlotDataTypePatch(patch,precompiledInfo);break}})}}const componentInfo=Utils.extractComponentInfoFromMetadata(auditContext,precompiledInfo,componentFolder,true,true);componentInfo.compiledMetadata=precompiledInfo;componentInfo.vcomponent=true;componentInfo.viewModel={resolved:true,path:Utils.toJAFPath(tsxFile)};componentInfo.viewModel.className=className;if(!componentName){componentInfo.inferredName=true}if(componentInfo.pack){const matchPack=packRegEx.exec(fileAsStr);if(!matchPack||!matchPack.groups.pack){componentInfo.inferredPack=true}}const matchVer=versionRegEx.exec(fileAsStr);if(!matchVer||!matchVer.groups.version){componentInfo.inferredVersion=true}const matchJetVer=jetVersionRegEx.exec(fileAsStr);if(!matchJetVer||!matchJetVer.groups.version){componentInfo.inferredJetVersion=true}return componentInfo}else{if(fullName){msgLib.error(`Unable to audit VComponent ${fullName}, pre-compiled metadata is not available`)}return}};TsxUtils.prototype.getVComponentElementNameAndImpl=function(sourceCode,msgLib){var resolvedElementName,implementationClass;const elementRegExForFunction=/export const\s*(?<className>\w+)[\w\s\<\>:]*=\s*registerCustomElement[\s<>\w]*\(\s*[\"\'](?<fullName>[\w-]*)\s*[\"\']\s*,/mg;const matchElementFunction=elementRegExForFunction.exec(sourceCode);if(matchElementFunction&&matchElementFunction.groups&&matchElementFunction.groups.fullName&&matchElementFunction.groups.className){resolvedElementName=matchElementFunction.groups.fullName;implementationClass=matchElementFunction.groups.className}else{const elementRegExForClass=/\s*@customElement\s*\(\s*[\"\']\s*(?<fullName>[\w-]*)\s*[\"\']\s*\)/mg;const matchElementClass=elementRegExForClass.exec(sourceCode);if(matchElementClass&&matchElementClass.groups&&matchElementClass.groups.fullName){resolvedElementName=matchElementClass.groups.fullName}const elementRegExForClassImpl=/[\s]*export[\s]*class[\s]*(?<className>[a-zA-Z\-0-9_]*)[\s]*extends[\s]*(?<superClass>[a-zA-Z\-0-9_]*)/mg;while((classDef=elementRegExForClassImpl.exec(sourceCode))!==null){if(classDef.groups.superClass==="Component"){implementationClass=classDef.groups.className}}}if(resolvedElementName&&!implementationClass){msgLib.info(`WARNING: Unable to determine VComponent class-name for ${resolvedElementName}`)}return{elementName:resolvedElementName,class:implementationClass}};TsxUtils.prototype.getVComponentComponentName=function(sourceCode){const nameRegEx=/@ojmetadata[\s]*name [\"|'](?<componentName>[a-zA-Z\-0-9]*)[\"|']/mg;const matchElement=nameRegEx.exec(sourceCode);if(matchElement&&matchElement.groups&&matchElement.groups.componentName){return matchElement.groups.componentName}else{return}};TsxUtils.prototype.matchToVComponentImpl=function(auditContext,testFileName){let componentInfo;let fileNameCanonical=Utils.toJAFPath(testFileName);if(fileNameCanonical.endsWith(".tsx")){const componentMatch=Utils.matchComponentPath(auditContext,fileNameCanonical);if(componentMatch){const testPossibleComponentInfo=Utils.componentInfo(auditContext,componentMatch);if(testPossibleComponentInfo.viewModel&&fileNameCanonical===testPossibleComponentInfo.viewModel.path){componentInfo=testPossibleComponentInfo}}}return componentInfo};TsxUtils.prototype._handlePropertyTypePatch=function(patch,metadata){this._patchPropertyViaPath(patch,patch.locator.split("."),metadata)};TsxUtils.prototype._patchPropertyViaPath=function(patch,path,node){const contactProp=path.shift();if(node.properties?.hasOwnProperty(contactProp)){if(path.length>0){this._patchPropertyViaPath(patch,path,node.properties[contactProp])}else{const propDef=node.properties[contactProp];const existingType=propDef.type;if(this._verifyType(existingType,patch)){propDef.type=patch.patchType}}}};TsxUtils.prototype._verifyType=function(existingType,patch){let expectedTypeMatches=existingType===patch?.expectedType||!patch?.expectedType;let abortNoMatch=false;if(patch.enforceMatch){if(!expectedTypeMatches){abortNoMatch=true}}return!abortNoMatch};TsxUtils.prototype._handleMethodTypePatch=function(patch,metadata){const locatorSegs=patch.locator.split(":");const methodName=locatorSegs[0];const methodTarget=locatorSegs[1];if(metadata.methods?.hasOwnProperty(methodName)){const methodDef=metadata.methods[methodName];if(methodTarget==="return"){this._patchMethodReturnType(patch,methodDef)}else{this._patchMethodParamType(patch,methodDef,methodTarget)}}};TsxUtils.prototype._patchMethodParamType=function(patch,methodDef,parameterName){let paramDef;for(let i=0;i<methodDef.params.length;i++){if(methodDef.params[i].name===parameterName){paramDef=methodDef.params[i]}}const existingType=paramDef.type;if(this._verifyType(existingType,patch)){paramDef.type=patch.patchType}};TsxUtils.prototype._patchMethodReturnType=function(patch,methodDef){const existingType=methodDef.return;if(this._verifyType(existingType,patch)){methodDef.return=patch.patchType}};TsxUtils.prototype._handleEventDetailTypePatch=function(patch,metadata){const locatorSegs=patch.locator.split(":");const eventName=locatorSegs[0];const detailName=locatorSegs[1];if(metadata.events?.hasOwnProperty(eventName)){const eventDef=metadata.events[eventName];if(eventDef.detail?.hasOwnProperty(detailName)){const existingType=eventDef.detail[detailName].type;if(this._verifyType(existingType,patch)){eventDef.detail[detailName].type=patch.patchType}}}};TsxUtils.prototype._handleSlotDataTypePatch=function(patch,metadata){const locatorSegs=patch.locator.split(":");const slotName=locatorSegs[0];const dataName=locatorSegs[1];if(metadata.slots?.hasOwnProperty(slotName)){const slotDef=metadata.slots[slotName];if(slotDef.data?.hasOwnProperty(dataName)){const existingType=slotDef.data[dataName].type;if(this._verifyType(existingType,patch)){slotDef.data[dataName].type=patch.patchType}}}};module.exports=new TsxUtils;
6
+ const Utils=require("./jetwcutils-componentAuditUtils");const path=require("path");const TsxUtils=function(){};TsxUtils.prototype.extractComponentInfoFromTSXFile=function(auditContext,componentFolder,fileName,metadataPatches){const{msgLib,fsUtils}=auditContext.utils;const packRegEx=/@ojmetadata[\s]*pack[\s]*[\"|'](?<pack>[a-zA-Z\-0-9]*)[\"|']/mg;const versionRegEx=/@ojmetadata[\s]*version[\s]*[\"|'](?<version>[\.0-9\-a-zA-Z]*)[\"|']/mg;const jetVersionRegEx=/@ojmetadata[\s]*jetVersion[\s]*[\"|'](?<version>[\.0-9\-a-zA-Z^~><=]*)[\"|']/mg;const tsxFile=path.join(componentFolder,fileName);const fileAsStr=auditContext.utils.fsUtils.readFileSync(tsxFile);const componentIdentification=this.getVComponentElementNameAndImpl(fileAsStr,msgLib);const fullName=componentIdentification.elementName;const className=componentIdentification.class;const componentName=this.getVComponentComponentName(fileAsStr);let precompiledInfo=auditContext.utils.metaLib.getTagMetadata(fullName);if(!precompiledInfo&&auditContext.rulePack.getRuleCustomOptions().hasOwnProperty("precompileCache")&&auditContext.rulePack.getRuleCustomOption("testMode")){msgLib.info(`Test mode, bypassing Typescript compilation...`);const jsonLoc=path.join(auditContext.rulePack.getRuleCustomOption("precompileCache"),`${fullName}.json`);if(fsUtils.fileExistsSync(jsonLoc)){precompiledInfo=fsUtils.readJsonSync(jsonLoc)}else{msgLib.error(`Missing test mode metadata for ${jsonLoc}`)}}if(precompiledInfo){if(metadataPatches){let componentPatches;if(precompiledInfo.pack){componentPatches=metadataPatches?.[precompiledInfo.pack]?.[precompiledInfo.name]}else{componentPatches=metadataPatches?.[precompiledInfo.name]}if(componentPatches&&Array.isArray(componentPatches)){msgLib.info(`Processing metadata type patches for ${fullName} [${componentPatches.length} patch(es) specified]`);componentPatches.forEach(patch=>{switch(patch.target){case"property":this._handlePropertyTypePatch(patch,precompiledInfo);break;case"method":this._handleMethodTypePatch(patch,precompiledInfo);break;case"event":this._handleEventDetailTypePatch(patch,precompiledInfo);break;case"slot":this._handleSlotDataTypePatch(patch,precompiledInfo);break}})}}const componentInfo=Utils.extractComponentInfoFromMetadata(auditContext,precompiledInfo,componentFolder,true,true);componentInfo.compiledMetadata=precompiledInfo;componentInfo.vcomponent=true;componentInfo.viewModel={resolved:true,path:Utils.toJAFPath(tsxFile)};componentInfo.viewModel.className=className;if(!componentName){componentInfo.inferredName=true}if(componentInfo.pack){const matchPack=packRegEx.exec(fileAsStr);if(!matchPack||!matchPack.groups.pack){componentInfo.inferredPack=true}}const matchVer=versionRegEx.exec(fileAsStr);if(!matchVer||!matchVer.groups.version){componentInfo.inferredVersion=true}const matchJetVer=jetVersionRegEx.exec(fileAsStr);if(!matchJetVer||!matchJetVer.groups.version){componentInfo.inferredJetVersion=true}return componentInfo}else{if(fullName){msgLib.error(`Unable to audit VComponent ${fullName}, pre-compiled metadata is not available`)}return}};TsxUtils.prototype.getVComponentElementNameAndImpl=function(sourceCode,msgLib){var resolvedElementName,implementationClass;const elementRegExForFunction=/export const\s*(?<className>\w+)[\w\s\<\>:]*=\s*registerCustomElement[\s<>,\w]*\(\s*[\"\'](?<fullName>[\w-]*)\s*[\"\']\s*,/mg;const matchElementFunction=elementRegExForFunction.exec(sourceCode);if(matchElementFunction&&matchElementFunction.groups&&matchElementFunction.groups.fullName&&matchElementFunction.groups.className){resolvedElementName=matchElementFunction.groups.fullName;implementationClass=matchElementFunction.groups.className}else{const elementRegExForClass=/\s*@customElement\s*\(\s*[\"\']\s*(?<fullName>[\w-]*)\s*[\"\']\s*\)/mg;const matchElementClass=elementRegExForClass.exec(sourceCode);if(matchElementClass&&matchElementClass.groups&&matchElementClass.groups.fullName){resolvedElementName=matchElementClass.groups.fullName}const elementRegExForClassImpl=/[\s]*export[\s]*class[\s]*(?<className>[a-zA-Z\-0-9_]*)[\s<>,\w]*extends[\s]*(?<superClass>[a-zA-Z\-0-9_]*)/mg;while((classDef=elementRegExForClassImpl.exec(sourceCode))!==null){if(classDef.groups.superClass==="Component"){implementationClass=classDef.groups.className}}}if(resolvedElementName&&!implementationClass){msgLib.error(`Unable to determine VComponent class-name for ${resolvedElementName}`)}return{elementName:resolvedElementName,class:implementationClass}};TsxUtils.prototype.getVComponentComponentName=function(sourceCode){const nameRegEx=/@ojmetadata[\s]*name [\"|'](?<componentName>[a-zA-Z\-0-9]*)[\"|']/mg;const matchElement=nameRegEx.exec(sourceCode);if(matchElement&&matchElement.groups&&matchElement.groups.componentName){return matchElement.groups.componentName}else{return}};TsxUtils.prototype.matchToVComponentImpl=function(auditContext,testFileName){let componentInfo;let fileNameCanonical=Utils.toJAFPath(testFileName);if(fileNameCanonical.endsWith(".tsx")){const componentMatch=Utils.matchComponentPath(auditContext,fileNameCanonical);if(componentMatch){const testPossibleComponentInfo=Utils.componentInfo(auditContext,componentMatch);if(testPossibleComponentInfo.viewModel&&fileNameCanonical===testPossibleComponentInfo.viewModel.path){componentInfo=testPossibleComponentInfo}}}return componentInfo};TsxUtils.prototype._handlePropertyTypePatch=function(patch,metadata){this._patchPropertyViaPath(patch,patch.locator.split("."),metadata)};TsxUtils.prototype._patchPropertyViaPath=function(patch,path,node){const contactProp=path.shift();if(node.properties?.hasOwnProperty(contactProp)){if(path.length>0){this._patchPropertyViaPath(patch,path,node.properties[contactProp])}else{const propDef=node.properties[contactProp];const existingType=propDef.type;if(this._verifyType(existingType,patch)){propDef.type=patch.patchType}}}};TsxUtils.prototype._verifyType=function(existingType,patch){let expectedTypeMatches=existingType===patch?.expectedType||!patch?.expectedType;let abortNoMatch=false;if(patch.enforceMatch){if(!expectedTypeMatches){abortNoMatch=true}}return!abortNoMatch};TsxUtils.prototype._handleMethodTypePatch=function(patch,metadata){const locatorSegs=patch.locator.split(":");const methodName=locatorSegs[0];const methodTarget=locatorSegs[1];if(metadata.methods?.hasOwnProperty(methodName)){const methodDef=metadata.methods[methodName];if(methodTarget==="return"){this._patchMethodReturnType(patch,methodDef)}else{this._patchMethodParamType(patch,methodDef,methodTarget)}}};TsxUtils.prototype._patchMethodParamType=function(patch,methodDef,parameterName){let paramDef;for(let i=0;i<methodDef.params.length;i++){if(methodDef.params[i].name===parameterName){paramDef=methodDef.params[i]}}const existingType=paramDef.type;if(this._verifyType(existingType,patch)){paramDef.type=patch.patchType}};TsxUtils.prototype._patchMethodReturnType=function(patch,methodDef){const existingType=methodDef.return;if(this._verifyType(existingType,patch)){methodDef.return=patch.patchType}};TsxUtils.prototype._handleEventDetailTypePatch=function(patch,metadata){const locatorSegs=patch.locator.split(":");const eventName=locatorSegs[0];const detailName=locatorSegs[1];if(metadata.events?.hasOwnProperty(eventName)){const eventDef=metadata.events[eventName];if(eventDef.detail?.hasOwnProperty(detailName)){const existingType=eventDef.detail[detailName].type;if(this._verifyType(existingType,patch)){eventDef.detail[detailName].type=patch.patchType}}}};TsxUtils.prototype._handleSlotDataTypePatch=function(patch,metadata){const locatorSegs=patch.locator.split(":");const slotName=locatorSegs[0];const dataName=locatorSegs[1];if(metadata.slots?.hasOwnProperty(slotName)){const slotDef=metadata.slots[slotName];if(slotDef.data?.hasOwnProperty(dataName)){const existingType=slotDef.data[dataName].type;if(this._verifyType(existingType,patch)){slotDef.data[dataName].type=patch.patchType}}}};module.exports=new TsxUtils;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const path=require("path");const Utils=require("../jetwc-lib/jetwcutils-componentAuditUtils");const componentFinder=require("../jetwc-lib/jetwcutils-componentFinder");const ruleDef=function(){};ruleDef.prototype.getName=function(){return"jetwco-bootstrap"};ruleDef.prototype.getShortDescription=function(){return"Bootstrap processing for the JETWCO rulset"};ruleDef.prototype.getDescription=function(){return"This rule is for internal use by the ruleset and should not be disabled"};ruleDef.prototype.register=function(context){this.componentRoots=context.config.components;this.auditBase=context.config.base;this.typeScriptCompile=context.config.typescript&&context.config.typescript.compile;return{startupRP:this._getAllVisibleComponents,closedownRP:this._reportDiagnostics}};ruleDef.prototype._getAllVisibleComponents=function(context){const{msgLib}=context.utils;msgLib.info(`builtinJetWcOracleRules (${context.rulePack.getPackInfo().prefix}): ${context.rulePack.getPackInfo().version}`);const projectPathInfo=Utils.getKeyPathInfoForRulepack(context,this.auditBase);const componentRootFolder=context.rulePack.getRuleOptions().componentRoot||projectPathInfo.componentRootFolder;const exchangeURL=context.rulePack.getRuleOptions().exchangeURL;const masterComponentList=componentFinder.findAllComponents(context,this.auditBase,projectPathInfo,this.componentRoots);if(masterComponentList&&masterComponentList.length>0){const allComponentsMap=masterComponentList.reduce((wmap,component)=>{if(!projectPathInfo.isBuiltOutput||projectPathInfo.isBuiltOutput&&!wmap.has(component.fullName)){wmap.set(component.fullName,component)}return wmap},new Map);const referenceComponents=new Map;const componentPaths=new Map;allComponentsMap.forEach(component=>{component.language=Utils.detectComponentSourceType(context,component.rootFolder);switch(component.type){case"reference":referenceComponents.set(component.fullName,component.ba);break;case"composite":case"resource":if(component.local){if(component.dependencies){Object.values(component.dependencies).forEach(dependencyName=>{if(allComponentsMap.has(dependencyName)){const proxyPaths=allComponentsMap.get(dependencyName).requirePaths;proxyPaths.forEach(path=>{component.requirePaths.add(path)})}})}componentPaths.set(component.rootFolder,component.fullName)}break}});context.rulePack.setExtension({rulepackVersion:context.rulePack.getPackInfo().version,bootStrap:true,exchangeURL:exchangeURL,platform:Utils.isWindows?"Windows":"Unix-like",precompiled:this.typeScriptCompile,componentHome:`/${componentRootFolder}/`,auditBuildOutput:projectPathInfo.isBuiltOutput,discoveredPaths:projectPathInfo,componentRoots:this.componentRoots,allReferenceComponents:referenceComponents,allComponents:allComponentsMap,auditableComponentPaths:componentPaths,allAuditableFilePaths:new Map})}else{msgLib.error(`No components have been discovered from the JAF configuration for the ${context.rulePack.getPackInfo().prefix} ruleset to process. You will need to configure the "components" array to point at your component root folder`);Utils.disableRulePack(context)}};ruleDef.prototype._reportDiagnostics=function(context){const msgLib=context.utils.msgLib;const opts=context.rulePack.getRuleOptions();const diagnostics=context.rulePack.getExtension();if(!opts.testMode){let foundVMMapping=0;let candidateLocal=0;if(diagnostics&&diagnostics.allComponents&&diagnostics.allComponents.length>0){diagnostics.allComponents.forEach((component,compName)=>{if(component.local&&component.type==="composite"){candidateLocal++;if(component.viewModel&&component.viewModel.resolved){foundVMMapping++}}});if(foundVMMapping!==candidateLocal){msgLib.error(`Error: Audit was only able to map ${foundVMMapping} out of ${candidateLocal} components to their viewModels. Some audits will be unable to operate.`)}}}if(opts.debug&&opts.diagnosticFile&&diagnostics){msgLib.msg(`Writing JETWCO diagnostics to ${opts.diagnosticFile}.json`);const dFile=Utils.toJAFPath(path.join(path.resolve("."),opts.diagnosticFile+".json"));context.utils.fsUtils.writeJsonSync(diagnostics,dFile,{spaces:2,replacer:Utils.diagnosticReplacer})}};module.exports=ruleDef;
6
+ const path=require("path");const Utils=require("../jetwc-lib/jetwcutils-componentAuditUtils");const componentFinder=require("../jetwc-lib/jetwcutils-componentFinder");const ruleDef=function(){};ruleDef.prototype.getName=function(){return"jetwco-bootstrap"};ruleDef.prototype.getShortDescription=function(){return"Bootstrap processing for the JETWCO rulset"};ruleDef.prototype.getDescription=function(){return"This rule is for internal use by the ruleset and should not be disabled"};ruleDef.prototype.register=function(context){this.componentRoots=context.config.components;this.auditBase=context.config.base;this.typeScriptCompile=context.config.typescript&&context.config.typescript.compile;return{startupRP:this._getAllVisibleComponents,closedownRP:this._reportDiagnostics}};ruleDef.prototype._getAllVisibleComponents=function(context){const{msgLib}=context.utils;msgLib.info(`builtinJetWcOracleRules (${context.rulePack.getPackInfo().prefix}): ${context.rulePack.getPackInfo().version}`);const projectPathInfo=Utils.getKeyPathInfoForRulepack(context,this.auditBase);const componentRootFolder=context.rulePack.getRuleCustomOption("componentRoot")??projectPathInfo.componentRootFolder;const exchangeURL=context.userDefs?.["exchangeURL"]??context.rulePack.getRuleCustomOption("exchangeURL");const masterComponentList=componentFinder.findAllComponents(context,this.auditBase,projectPathInfo,this.componentRoots);if(masterComponentList&&masterComponentList.length>0){const allComponentsMap=masterComponentList.reduce((wmap,component)=>{if(!projectPathInfo.isBuiltOutput||projectPathInfo.isBuiltOutput&&!wmap.has(component.fullName)){wmap.set(component.fullName,component)}return wmap},new Map);const referenceComponents=new Map;const componentPaths=new Map;allComponentsMap.forEach(component=>{component.language=Utils.detectComponentSourceType(context,component.rootFolder);switch(component.type){case"reference":referenceComponents.set(component.fullName,component.ba);break;case"composite":case"resource":if(component.local){if(component.dependencies){Object.values(component.dependencies).forEach(dependencyName=>{if(allComponentsMap.has(dependencyName)){const proxyPaths=allComponentsMap.get(dependencyName).requirePaths;proxyPaths.forEach(path=>{component.requirePaths.add(path)})}})}componentPaths.set(component.rootFolder,component.fullName)}break}});context.rulePack.setExtension({rulepackVersion:context.rulePack.getPackInfo().version,bootStrap:true,exchangeURL:exchangeURL,platform:Utils.isWindows?"Windows":"Unix-like",precompiled:this.typeScriptCompile,componentHome:`/${componentRootFolder}/`,auditBuildOutput:projectPathInfo.isBuiltOutput,discoveredPaths:projectPathInfo,componentRoots:this.componentRoots,allReferenceComponents:referenceComponents,allComponents:allComponentsMap,auditableComponentPaths:componentPaths,allAuditableFilePaths:new Map})}else{msgLib.error(`No components have been discovered from the JAF configuration for the ${context.rulePack.getPackInfo().prefix} ruleset to process. You will need to configure the "components" array to point at your component root folder`);Utils.disableRulePack(context)}};ruleDef.prototype._reportDiagnostics=function(context){const msgLib=context.utils.msgLib;const opts=context.rulePack.getRuleCustomOptions();const diagnostics=context.rulePack.getExtension();if(!opts.testMode){let foundVMMapping=0;let candidateLocal=0;if(diagnostics&&diagnostics.allComponents&&diagnostics.allComponents.length>0){diagnostics.allComponents.forEach((component,compName)=>{if(component.local&&component.type==="composite"){candidateLocal++;if(component.viewModel&&component.viewModel.resolved){foundVMMapping++}}});if(foundVMMapping!==candidateLocal){msgLib.error(`Error: Audit was only able to map ${foundVMMapping} out of ${candidateLocal} components to their viewModels. Some audits will be unable to operate.`)}}}if(opts.debug&&opts.diagnosticFile&&diagnostics){msgLib.msg(`Writing JETWCO diagnostics to ${opts.diagnosticFile}.json`);const dFile=Utils.toJAFPath(path.join(path.resolve("."),opts.diagnosticFile+".json"));context.utils.fsUtils.writeJsonSync(diagnostics,dFile,{spaces:2,replacer:Utils.diagnosticReplacer})}};module.exports=ruleDef;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const Utils=require("../jetwc-lib/jetwcutils-componentAuditUtils");const AuditComponentCacheManager=require("../jetwc-lib/jetwcutils-auditComponentCacheManager");const NetUtils=require("../../lib/NetUtils");const CommonImpl=require("../jetwc-lib/jetwcutils-commonListenerImpls");const TsxUtils=require("../jetwc-lib/jetwcutils-tsxUtils");const ruleDef=function(){};ruleDef.prototype.getName=function(){return"jetwco-component-api-baseline-changes"};ruleDef.prototype.getShortDescription=function(){return"Check components for API changes against a base version"};ruleDef.prototype.getDescription=function(){return"This audit compares the APIs exposed by components with a designated baseline version of a component in the Exchange Catalog and checks if the component APIs have changed"};ruleDef.prototype.register=function(context){return{startaudit:this._auditPrep,closedownRP:this._dealWithCache,compjson:this._doAudit,Program:this._doVComponentAudit}};ruleDef.prototype._auditPrep=function(context){let baselineConfigured=false;let baselineMetadata=[];this.exchangeURL=CommonImpl.checkForExchangeConfiguration(context);if(this.exchangeURL){this.acCache=new AuditComponentCacheManager(context,this.getName());if(this.acCache.isBaselineIndexAvailable()){const exchangeRoot=this.exchangeURL;let baselineIndex=this.acCache.readComponentCacheIndexFile();if(Object.entries(baselineIndex).length===0){const baselineConfiguration=this.acCache.getBaselineOpts();let exchangeReadError=false;for(const[baselineComponent,baselineComponentVersion]of Object.entries(baselineConfiguration)){const eachComponentInfo=this._cacheBaselineMetadataForComponent(context,baselineComponent,baselineComponentVersion,exchangeRoot);if(!eachComponentInfo.inError){baselineMetadata=baselineMetadata.concat(eachComponentInfo.metadata)}else{exchangeReadError=true}}if(!exchangeReadError){baselineMetadata.forEach(component=>{const fullName=Utils.getComponentFullName(component);baselineIndex[fullName]=component.version;if(!this.acCache.existsInComponentCache(fullName,component.version)){this.acCache.writeToComponentCache(fullName,component.version,component)}});this.acCache.writeComponentCacheIndexFile(baselineIndex)}}if(Object.entries(baselineIndex).length>0){baselineConfigured=true;if(Object.keys(baselineIndex).length>0){Utils.safeSetExtension(context,{baselineIndex:baselineIndex})}}}}};ruleDef.prototype._cacheBaselineMetadataForComponent=function(auditContext,componentName,componentVersion,exchangeUrl){const msg=auditContext.utils.msgLib;let componentMetaArray=[];let inErrorCondition=false;try{let componentMeta;if(this.acCache.existsInComponentCache(componentName,componentVersion)){componentMeta=this.acCache.readFromComponentCache(componentName,componentVersion)}else{const netUtils=new NetUtils;const componentMetaResp=netUtils.loadUrl(`${exchangeUrl}/components/${componentName}/versions/${componentVersion}`);if(componentMetaResp.statusCode===200&&componentMetaResp.body){const componentResponseMeta=JSON.parse(componentMetaResp.body);componentMeta=componentResponseMeta.component}else if(componentMetaResp.statusCode===403){msg.info(`${auditContext.ruleName} - Baseline component ${componentName}@${componentVersion} cannot be read - skipping`)}else{const issue=new auditContext.Issue(`Unexpected error for the rule ${auditContext.ruleName} reading ${componentName}@${componentVersion}: Response ${componentMetaResp.statusCode} (${exchangeUrl})`);issue.setMsgKey("jetwco-component-api-baseline-changes_2");auditContext.reporter.addIssue(issue,auditContext,"critical");inErrorCondition=true}}if(!inErrorCondition&&componentMeta){const compType=componentMeta.type?componentMeta.type:"composite";if(compType==="pack"){const dependents=componentMeta.dependencies;if(dependents){for(const[packComponent,packComponentVersion]of Object.entries(dependents)){const eachPackMemberInfo=this._cacheBaselineMetadataForComponent(auditContext,packComponent,packComponentVersion,exchangeUrl);if(!eachPackMemberInfo.inError){componentMetaArray=componentMetaArray.concat(eachPackMemberInfo.metadata)}else{inErrorCondition=true}}}}componentMetaArray.push(componentMeta)}}catch(e){msg.error(`Exchange read error ${JSON.stringify(e)}`);const issue=new auditContext.Issue(`The exchangeURL value specified for the rule ${auditContext.ruleName} is incorrect: ${exchangeUrl}`);issue.setMsgKey("jetwco-component-api-baseline-changes_2");auditContext.reporter.addIssue(issue,context,"critical");inErrorCondition=true};return{inError:inErrorCondition,metadata:componentMetaArray}};ruleDef.prototype._dealWithCache=function(context){const shouldClearCache=context.rulePack.getRuleOption("clearCache",this.getName());if(shouldClearCache&&this.acCache){this.acCache.removeLocalCache()}};ruleDef.prototype._doAudit=function(context){if(context.suppData.obj){const meta=context.suppData.obj;const fullName=Utils.getComponentFullName(meta);const componentType=Utils.getComponentType(meta);this._baselineCheck(context,fullName,componentType,meta)}};ruleDef.prototype._doVComponentAudit=function(context){const componentInfo=TsxUtils.matchToVComponentImpl(context,context.filepath);if(componentInfo){let remappedDependencies;if(componentInfo.dependencies){remappedDependencies=componentInfo.dependencies.reduce((asMap,entry)=>{asMap[entry.name]=entry.range;return asMap},{})}const meta={version:componentInfo.version,jetVersion:componentInfo.jetVersion,properties:componentInfo.properties,methods:componentInfo.methods,events:componentInfo.events,sots:componentInfo.slots,dependencies:remappedDependencies};this._baselineCheck(context,componentInfo.fullName,componentInfo.type,meta)}};ruleDef.prototype._baselineCheck=function(context,fullName,componentType,componentMeta){const baselineIndex=context.rulePack.getExtension().baselineIndex;if(componentMeta&&baselineIndex){const componentVersion=componentMeta.version;const baselineVersion=baselineIndex[fullName];if(baselineVersion){const semver=context.utils.semVerUtils;const baselineComponentMeta=this.acCache.readFromComponentCache(fullName,baselineVersion);try{switch(componentType){case"pack":this._conductCheck(this._packContentsDiff,componentMeta,baselineComponentMeta);this._conductCheck(this._packBundlesDiff,componentMeta,baselineComponentMeta);break;case"composite":this._conductCheck(this._detectJetVersionDiff,semver,componentMeta,baselineComponentMeta);this._conductCheck(this._detectDependencyDiff,semver,componentMeta,baselineComponentMeta);this._conductCheck(this._detectMethodDiff,componentMeta,baselineComponentMeta);this._conductCheck(this._detectEventDiff,componentMeta,baselineComponentMeta);this._conductCheck(this._detectSlotDiff,componentMeta,baselineComponentMeta);this._conductCheck(this._detectDynamicSlotDiff,componentMeta,baselineComponentMeta);this._conductCheck(this._detectPropertyDiff,componentMeta,baselineComponentMeta);break;case"vbcs-pattern":this._conductCheck(this._detectDependencyDiff,semver,componentMeta,baselineComponentMeta);break;case"resource":this._conductCheck(this._detectJetVersionDiff,semver,componentMeta,baselineComponentMeta);this._conductCheck(this._detectDependencyDiff,semver,componentMeta,baselineComponentMeta);this._conductCheck(this._detectPublicModulesDiff,componentMeta,baselineComponentMeta);break}}catch(auditDetail){const issue=new context.Issue(`API change for ${fullName}@${componentVersion} detected in comparison with baseline version ${baselineVersion}. Indication: ${auditDetail}`);issue.setMsgKey("jetwco-component-api-baseline-changes_1");context.reporter.addIssue(issue,context)}}}};ruleDef.prototype._conductCheck=function(checkCallback,semver,config,existingConfig){const result=checkCallback.call(this,semver,config,existingConfig);if(result){throw result}};ruleDef.prototype._detectJetVersionDiff=function(semver,config,existingConfig,claimedMinorDiff){let explanation;const componentJetVersion=config.jetVersion?config.jetVersion:"0.0.0";const existingJetVersion=existingConfig.jetVersion?existingConfig.jetVersion:"0.0.0";if(componentJetVersion!==existingJetVersion){if(existingJetVersion==="0.0.0"||componentJetVersion==="0.0.0"){explanation="JET version range has been added or removed"}else{const minVersion=semver.minVersion(componentJetVersion);const minExistingVersion=semver.minVersion(existingJetVersion);if(semver.major(minVersion)>semver.major(minExistingVersion)){explanation="minimum major JET version required has increased"}else if(semver.minor(minVersion)>semver.minor(minExistingVersion)){explanation="minimum minor JET version required has increased"}}}return explanation};ruleDef.prototype._packContentsDiff=function(config,existingConfig){let explanation;const configDeps=config.dependencies?Object.keys(config.dependencies):[];const existingDeps=existingConfig.dependencies?Object.keys(existingConfig.dependencies):[];if(configDeps.length>0){for(let i=0;i<existingDeps.length;i++){const key=existingDeps[i];if(!config.dependencies.hasOwnProperty(key)){explanation=`Pack component ${key} has been removed`;break}}}return explanation};ruleDef.prototype._packBundlesDiff=function(config,existingConfig){let explanation;const configBundles=config.bundles?Object.keys(config.bundles):[];const existingBundles=existingConfig.bundles?Object.keys(existingConfig.bundles):[];for(let i=0;i<existingBundles.length;i++){const key=existingBundles[i];if(!config.bundles.hasOwnProperty(key)){explanation=`Pack bundle '${key}' has been removed`;break}else{const configContents=config.bundles[key];const existingContents=existingConfig.bundles[key];for(let i=0;i<existingContents.length;i++){const module=existingContents[i];if(!configContents.includes(module)){explanation=`Pack bundle '${key}' entry '${module}' removed`;break}}}}return explanation};ruleDef.prototype._detectPublicModulesDiff=function(config,existingConfig){let explanation;const configPM=config.publicModules?config.publicModules:[];const existingPM=existingConfig.publicModules?existingConfig.publicModules:[];for(let i=0;i<existingPM.length;i++){const module=existingPM[i];if(!configPM.includes(module)){explanation=`Public Module entry '${module}' has been removed`;break}}return explanation};ruleDef.prototype._detectDependencyDiff=function(semver,config,existingConfig){let explanation;const configDeps=config.dependencies?Object.keys(config.dependencies):[];const existingDeps=existingConfig.dependencies?Object.keys(existingConfig.dependencies):[];if(configDeps.length>existingDeps.length){explanation="More dependencies are declared by component"}else{if(configDeps.length>0){for(let i=0;i<existingDeps.length;i++){const key=existingDeps[i];if(config.dependencies.hasOwnProperty(key)){const newDepVersion=semver.minVersion(config.dependencies[key]);const existingDepVersion=semver.minVersion(existingConfig.dependencies[key]);if(semver.major(newDepVersion)!==semver.major(existingDepVersion)){explanation="Different major version of dependency "+key;break}if(semver.minor(newDepVersion)!==semver.minor(existingDepVersion)){explanation="Different minor version of dependency "+key;break}}else{explanation=`Dependency ${key} has been removed`;break}}}}return explanation};ruleDef.prototype._detectMethodDiff=function(config,existingConfig){let explanation;const configMethods=config.methods?Object.keys(config.methods):[];const existingMethods=existingConfig.methods?Object.keys(existingConfig.methods):[];for(let i=0;i<existingMethods.length;i++){const key=existingMethods[i];if(config.methods.hasOwnProperty(key)){const configMethodParams=config.methods[key].params?config.methods[key].params:[];const existingMethodParams=existingConfig.methods[key].params?existingConfig.methods[key].params:[];for(let j=0;j<existingMethodParams.length;j++){if(j>=configMethodParams.length){explanation=`Existing method '${key}' has fewer parameters`;break}else{if(!this._compareType(configMethodParams[j],existingMethodParams[j])){explanation=`Method '${key}' parameter number:${j+1} has a changed type`;break}}}if(!explanation&&configMethodParams.length>existingMethodParams.length){explanation=`Existing method '${key}' has additional parameters`;break}}else{explanation=`Existing method '${key}' has been removed`;break}}return explanation};ruleDef.prototype._detectPropertyDiff=function(config,existingConfig){let explanation;const configProps=config.properties?Object.keys(config.properties):[];const existingProps=existingConfig.properties?Object.keys(existingConfig.properties):[];explanation=this._compareProperties(config.properties,existingConfig.properties);if(!explanation){const addedRequiredProps=configProps.filter(addedProp=>!existingProps.includes(addedProp)&&config[addedProp]&&config[addedProp].required);if(addedRequiredProps.length>0){explanation=`Required property(ies) added: ${addedRequiredProps.join(",")}`}}return explanation};ruleDef.prototype._detectEventDiff=function(config,existingConfig){let explanation;const configEvents=config.events?Object.keys(config.events):[];const existingEvents=existingConfig.events?Object.keys(existingConfig.events):[];for(let i=0;i<existingEvents.length;i++){const key=existingEvents[i];if(config.events.hasOwnProperty(key)){const configEventDetail=config.events[key].detail?config.events[key].detail:{};const existingEventDetail=existingConfig.events[key].detail?existingConfig.events[key].detail:{};const detailKeys=Object.keys(configEventDetail);const existingDetailKeys=Object.keys(existingEventDetail);for(let j=0;j<existingDetailKeys.length;j++){const detailKey=existingDetailKeys[j];if(j>=detailKeys.length||!configEventDetail.hasOwnProperty(detailKey)){explanation=`Event '${key}' has missing entries in the detail payload`;break}else{if(!this._compareType(configEventDetail[detailKey],existingEventDetail[detailKey])){explanation=`Event '${key}' detail attribute '${detailKey}' has a changed type`;break}}}if(!explanation&&config.events[key].bubbles!==existingConfig.events[key].bubbles){explanation=`Event '${key}' has a changed bubbling state`;break}if(!explanation&&config.events[key].cancelable!==existingConfig.events[key].cancelable){explanation=`Event '${key}' has changed cancelable state`;break}}else{explanation=`Event '${key}' has been removed`;break}}return explanation};ruleDef.prototype._detectSlotDiff=function(config,existingConfig){return this._detectTypedSlotDiff("slots",config,existingConfig)};ruleDef.prototype._detectDynamicSlotDiff=function(config,existingConfig){return this._detectTypedSlotDiff("dynamicSlots",config,existingConfig)};ruleDef.prototype._detectTypedSlotDiff=function(slotType,config,existingConfig){let explanation;const configSlots=config[slotType]?Object.keys(config[slotType]):[];const existingSlots=existingConfig[slotType]?Object.keys(existingConfig[slotType]):[];for(let i=0;i<existingSlots.length;i++){const key=existingSlots[i];if(config[slotType].hasOwnProperty(key)){const configSlotData=config[slotType][key].data?config[slotType][key].data:{};const existingSlotData=existingConfig[slotType][key].data?existingConfig[slotType][key].data:{};const dataKeys=Object.keys(configSlotData);const existingDataKeys=Object.keys(existingSlotData);for(let j=0;j<existingDataKeys.length;j++){const dataKey=existingDataKeys[j];if(j>=dataKeys.length||!configSlotData.hasOwnProperty(dataKey)){explanation=`Template slot '${key}' - '${dataKey}' has been removed from data definition`;break}else{if(!this._compareType(configSlotData[dataKey],existingSlotData[dataKey])){explanation=`Template slot '${key}' data attribute '${dataKey}' has a changed type`;break}}}}else{explanation=`Slot '${key}' has been removed`;break}}return explanation};ruleDef.prototype._compareType=function(newTyped,existingTyped){let matches=true;const newType=newTyped&&newTyped.type?newTyped.type:null;const existingType=existingTyped&&existingTyped.type?existingTyped.type:null;if(newType!==existingType){if(newType.includes("|")){const newTypeOptions=newType?newType.split("|"):[];const existingTypeOptions=existingType?existingType.split("|"):[];matches=existingTypeOptions.every(checkType=>newTypeOptions.includes(checkType))}else{matches=false}}return matches};ruleDef.prototype._compareProperties=function(newProps,oldProps,path){let explanation;const configProps=newProps?Object.keys(newProps):[];const existingProps=oldProps?Object.keys(oldProps):[];for(let i=0;i<existingProps.length;i++){const key=existingProps[i];if(newProps.hasOwnProperty(key)){const newProperty=newProps[key];const oldProperty=oldProps[key];if(!this._compareType(newProperty,oldProperty)){explanation=`Property type change for '${path?path:""}${key}'`;break}if(oldProperty.hasOwnProperty("enumValues")){const newOptions=newProperty.hasOwnProperty("enumValues")?newProperty.enumValues:[];if(!oldProperty.enumValues.every(checkOption=>newOptions.includes(checkOption))){explanation=`Enumeration value option removed from property '${path?path:""}${key}'`;break}}else if(newProperty.hasOwnProperty("enumValues")){explanation=`Property '${path?path:""}${key}' is now constrained by an enumeration`;break}if(!path){if(oldProperty.writeback&&!newProperty.writeback){explanation=`Property '${key}' is no longer writeback enabled`;break}if(!oldProperty.required&&newProperty.required){explanation=`Property '${key}' has been made required`;break}const oldROState=oldProperty.hasOwnProperty("readOnly")?oldProperty.readOnly:false;const newROState=newProperty.hasOwnProperty("readOnly")?newProperty.readOnly:false;if(oldROState!==newROState){explanation=`Property '${key}' readOnly state has changed`;break}const oldDefault=oldProperty.hasOwnProperty("value")?JSON.stringify(oldProperty.value):"";const newDefault=newProperty.hasOwnProperty("value")?JSON.stringify(newProperty.value):"";if(oldDefault!==newDefault){explanation=`Property '${key}' default value has changed`;break}}if(newProperty.hasOwnProperty("properties")||oldProperty.hasOwnProperty("properties")){const newSubProps=newProperty.properties?newProperty.properties:{};const oldSubProps=oldProperty.properties?oldProperty.properties:{};const propPath=path?path+key+".":key+".";explanation=this._compareProperties(newSubProps,oldSubProps,propPath);if(explanation){break}}}else{explanation=`Property '${path?path:""}${key}' has been removed`;break}}return explanation};module.exports=ruleDef;
6
+ const Utils=require("../jetwc-lib/jetwcutils-componentAuditUtils");const AuditComponentCacheManager=require("../jetwc-lib/jetwcutils-auditComponentCacheManager");const NetUtils=require("../../lib/NetUtils");const CommonImpl=require("../jetwc-lib/jetwcutils-commonListenerImpls");const TsxUtils=require("../jetwc-lib/jetwcutils-tsxUtils");const ruleDef=function(){};ruleDef.prototype.getName=function(){return"jetwco-component-api-baseline-changes"};ruleDef.prototype.getShortDescription=function(){return"Check components for API changes against a base version"};ruleDef.prototype.getDescription=function(){return"This audit compares the APIs exposed by components with a designated baseline version of a component in the Exchange Catalog and checks if the component APIs have changed"};ruleDef.prototype.register=function(context){return{startaudit:this._auditPrep,closedownRP:this._dealWithCache,compjson:this._doAudit,Program:this._doVComponentAudit}};ruleDef.prototype._auditPrep=function(context){let baselineConfigured=false;let baselineMetadata=[];this.exchangeURL=CommonImpl.checkForExchangeConfiguration(context);if(this.exchangeURL){this.acCache=new AuditComponentCacheManager(context,this.getName());if(this.acCache.isBaselineIndexAvailable()){const exchangeRoot=this.exchangeURL;let baselineIndex=this.acCache.readComponentCacheIndexFile();if(Object.entries(baselineIndex).length===0){const baselineConfiguration=this.acCache.getBaselineOpts();let exchangeReadError=false;for(const[baselineComponent,baselineComponentVersion]of Object.entries(baselineConfiguration)){const eachComponentInfo=this._cacheBaselineMetadataForComponent(context,baselineComponent,baselineComponentVersion,exchangeRoot);if(!eachComponentInfo.inError){baselineMetadata=baselineMetadata.concat(eachComponentInfo.metadata)}else{exchangeReadError=true}}if(!exchangeReadError){baselineMetadata.forEach(component=>{const fullName=Utils.getComponentFullName(component);baselineIndex[fullName]=component.version;if(!this.acCache.existsInComponentCache(fullName,component.version)){this.acCache.writeToComponentCache(fullName,component.version,component)}});this.acCache.writeComponentCacheIndexFile(baselineIndex)}}if(Object.entries(baselineIndex).length>0){baselineConfigured=true;if(Object.keys(baselineIndex).length>0){Utils.safeSetExtension(context,{baselineIndex:baselineIndex})}}}}};ruleDef.prototype._cacheBaselineMetadataForComponent=function(auditContext,componentName,componentVersion,exchangeUrl){const msg=auditContext.utils.msgLib;let componentMetaArray=[];let inErrorCondition=false;try{let componentMeta;if(this.acCache.existsInComponentCache(componentName,componentVersion)){componentMeta=this.acCache.readFromComponentCache(componentName,componentVersion)}else{const netUtils=new NetUtils;const componentMetaResp=netUtils.loadUrl(`${exchangeUrl}/components/${componentName}/versions/${componentVersion}`);if(componentMetaResp.statusCode===200&&componentMetaResp.body){const componentResponseMeta=JSON.parse(componentMetaResp.body);componentMeta=componentResponseMeta.component}else if(componentMetaResp.statusCode===403){msg.info(`${auditContext.ruleName} - Baseline component ${componentName}@${componentVersion} cannot be read - skipping`)}else{const issue=new auditContext.Issue(`Unexpected error for the rule ${auditContext.ruleName} reading ${componentName}@${componentVersion}: Response ${componentMetaResp.statusCode} (${exchangeUrl})`);issue.setMsgKey("jetwco-component-api-baseline-changes_2");auditContext.reporter.addIssue(issue,auditContext,"critical");inErrorCondition=true}}if(!inErrorCondition&&componentMeta){const compType=componentMeta.type?componentMeta.type:"composite";if(compType==="pack"){const dependents=componentMeta.dependencies;if(dependents){for(const[packComponent,packComponentVersion]of Object.entries(dependents)){const eachPackMemberInfo=this._cacheBaselineMetadataForComponent(auditContext,packComponent,packComponentVersion,exchangeUrl);if(!eachPackMemberInfo.inError){componentMetaArray=componentMetaArray.concat(eachPackMemberInfo.metadata)}else{inErrorCondition=true}}}}componentMetaArray.push(componentMeta)}}catch(e){msg.error(`Exchange read error ${JSON.stringify(e)}`);const issue=new auditContext.Issue(`The exchangeURL value specified for the rule ${auditContext.ruleName} is incorrect: ${exchangeUrl}`);issue.setMsgKey("jetwco-component-api-baseline-changes_2");auditContext.reporter.addIssue(issue,context,"critical");inErrorCondition=true};return{inError:inErrorCondition,metadata:componentMetaArray}};ruleDef.prototype._dealWithCache=function(context){const shouldClearCache=context.rulePack.getRuleCustomOption("clearCache",this.getName());if(shouldClearCache&&this.acCache){this.acCache.removeLocalCache()}};ruleDef.prototype._doAudit=function(context){if(context.suppData.obj){const meta=context.suppData.obj;const fullName=Utils.getComponentFullName(meta);const componentType=Utils.getComponentType(meta);this._baselineCheck(context,fullName,componentType,meta)}};ruleDef.prototype._doVComponentAudit=function(context){const componentInfo=TsxUtils.matchToVComponentImpl(context,context.filepath);if(componentInfo){let remappedDependencies;if(componentInfo.dependencies){remappedDependencies=componentInfo.dependencies.reduce((asMap,entry)=>{asMap[entry.name]=entry.range;return asMap},{})}const meta={version:componentInfo.version,jetVersion:componentInfo.jetVersion,properties:componentInfo.properties,methods:componentInfo.methods,events:componentInfo.events,sots:componentInfo.slots,dependencies:remappedDependencies};this._baselineCheck(context,componentInfo.fullName,componentInfo.type,meta)}};ruleDef.prototype._baselineCheck=function(context,fullName,componentType,componentMeta){const baselineIndex=context.rulePack.getExtension().baselineIndex;if(componentMeta&&baselineIndex){const componentVersion=componentMeta.version;const baselineVersion=baselineIndex[fullName];if(baselineVersion){const semver=context.utils.semVerUtils;const baselineComponentMeta=this.acCache.readFromComponentCache(fullName,baselineVersion);try{switch(componentType){case"pack":this._conductCheck(this._packContentsDiff,componentMeta,baselineComponentMeta);this._conductCheck(this._packBundlesDiff,componentMeta,baselineComponentMeta);break;case"composite":this._conductCheck(this._detectJetVersionDiff,semver,componentMeta,baselineComponentMeta);this._conductCheck(this._detectDependencyDiff,semver,componentMeta,baselineComponentMeta);this._conductCheck(this._detectMethodDiff,componentMeta,baselineComponentMeta);this._conductCheck(this._detectEventDiff,componentMeta,baselineComponentMeta);this._conductCheck(this._detectSlotDiff,componentMeta,baselineComponentMeta);this._conductCheck(this._detectDynamicSlotDiff,componentMeta,baselineComponentMeta);this._conductCheck(this._detectPropertyDiff,componentMeta,baselineComponentMeta);break;case"vbcs-pattern":this._conductCheck(this._detectDependencyDiff,semver,componentMeta,baselineComponentMeta);break;case"resource":this._conductCheck(this._detectJetVersionDiff,semver,componentMeta,baselineComponentMeta);this._conductCheck(this._detectDependencyDiff,semver,componentMeta,baselineComponentMeta);this._conductCheck(this._detectPublicModulesDiff,componentMeta,baselineComponentMeta);break}}catch(auditDetail){const issue=new context.Issue(`API change for ${fullName}@${componentVersion} detected in comparison with baseline version ${baselineVersion}. Indication: ${auditDetail}`);issue.setMsgKey("jetwco-component-api-baseline-changes_1");context.reporter.addIssue(issue,context)}}}};ruleDef.prototype._conductCheck=function(checkCallback,semver,config,existingConfig){const result=checkCallback.call(this,semver,config,existingConfig);if(result){throw result}};ruleDef.prototype._detectJetVersionDiff=function(semver,config,existingConfig,claimedMinorDiff){let explanation;const componentJetVersion=config.jetVersion?config.jetVersion:"0.0.0";const existingJetVersion=existingConfig.jetVersion?existingConfig.jetVersion:"0.0.0";if(componentJetVersion!==existingJetVersion){if(existingJetVersion==="0.0.0"||componentJetVersion==="0.0.0"){explanation="JET version range has been added or removed"}else{const minVersion=semver.minVersion(componentJetVersion);const minExistingVersion=semver.minVersion(existingJetVersion);if(semver.major(minVersion)>semver.major(minExistingVersion)){explanation="minimum major JET version required has increased"}else if(semver.minor(minVersion)>semver.minor(minExistingVersion)){explanation="minimum minor JET version required has increased"}}}return explanation};ruleDef.prototype._packContentsDiff=function(config,existingConfig){let explanation;const configDeps=config.dependencies?Object.keys(config.dependencies):[];const existingDeps=existingConfig.dependencies?Object.keys(existingConfig.dependencies):[];if(configDeps.length>0){for(let i=0;i<existingDeps.length;i++){const key=existingDeps[i];if(!config.dependencies.hasOwnProperty(key)){explanation=`Pack component ${key} has been removed`;break}}}return explanation};ruleDef.prototype._packBundlesDiff=function(config,existingConfig){let explanation;const configBundles=config.bundles?Object.keys(config.bundles):[];const existingBundles=existingConfig.bundles?Object.keys(existingConfig.bundles):[];for(let i=0;i<existingBundles.length;i++){const key=existingBundles[i];if(!config.bundles.hasOwnProperty(key)){explanation=`Pack bundle '${key}' has been removed`;break}else{const configContents=config.bundles[key];const existingContents=existingConfig.bundles[key];for(let i=0;i<existingContents.length;i++){const module=existingContents[i];if(!configContents.includes(module)){explanation=`Pack bundle '${key}' entry '${module}' removed`;break}}}}return explanation};ruleDef.prototype._detectPublicModulesDiff=function(config,existingConfig){let explanation;const configPM=config.publicModules?config.publicModules:[];const existingPM=existingConfig.publicModules?existingConfig.publicModules:[];for(let i=0;i<existingPM.length;i++){const module=existingPM[i];if(!configPM.includes(module)){explanation=`Public Module entry '${module}' has been removed`;break}}return explanation};ruleDef.prototype._detectDependencyDiff=function(semver,config,existingConfig){let explanation;const configDeps=config.dependencies?Object.keys(config.dependencies):[];const existingDeps=existingConfig.dependencies?Object.keys(existingConfig.dependencies):[];if(configDeps.length>existingDeps.length){explanation="More dependencies are declared by component"}else{if(configDeps.length>0){for(let i=0;i<existingDeps.length;i++){const key=existingDeps[i];if(config.dependencies.hasOwnProperty(key)){const newDepVersion=semver.minVersion(config.dependencies[key]);const existingDepVersion=semver.minVersion(existingConfig.dependencies[key]);if(semver.major(newDepVersion)!==semver.major(existingDepVersion)){explanation="Different major version of dependency "+key;break}if(semver.minor(newDepVersion)!==semver.minor(existingDepVersion)){explanation="Different minor version of dependency "+key;break}}else{explanation=`Dependency ${key} has been removed`;break}}}}return explanation};ruleDef.prototype._detectMethodDiff=function(config,existingConfig){let explanation;const configMethods=config.methods?Object.keys(config.methods):[];const existingMethods=existingConfig.methods?Object.keys(existingConfig.methods):[];for(let i=0;i<existingMethods.length;i++){const key=existingMethods[i];if(config.methods.hasOwnProperty(key)){const configMethodParams=config.methods[key].params?config.methods[key].params:[];const existingMethodParams=existingConfig.methods[key].params?existingConfig.methods[key].params:[];for(let j=0;j<existingMethodParams.length;j++){if(j>=configMethodParams.length){explanation=`Existing method '${key}' has fewer parameters`;break}else{if(!this._compareType(configMethodParams[j],existingMethodParams[j])){explanation=`Method '${key}' parameter number:${j+1} has a changed type`;break}}}if(!explanation&&configMethodParams.length>existingMethodParams.length){explanation=`Existing method '${key}' has additional parameters`;break}}else{explanation=`Existing method '${key}' has been removed`;break}}return explanation};ruleDef.prototype._detectPropertyDiff=function(config,existingConfig){let explanation;const configProps=config.properties?Object.keys(config.properties):[];const existingProps=existingConfig.properties?Object.keys(existingConfig.properties):[];explanation=this._compareProperties(config.properties,existingConfig.properties);if(!explanation){const addedRequiredProps=configProps.filter(addedProp=>!existingProps.includes(addedProp)&&config[addedProp]&&config[addedProp].required);if(addedRequiredProps.length>0){explanation=`Required property(ies) added: ${addedRequiredProps.join(",")}`}}return explanation};ruleDef.prototype._detectEventDiff=function(config,existingConfig){let explanation;const configEvents=config.events?Object.keys(config.events):[];const existingEvents=existingConfig.events?Object.keys(existingConfig.events):[];for(let i=0;i<existingEvents.length;i++){const key=existingEvents[i];if(config.events.hasOwnProperty(key)){const configEventDetail=config.events[key].detail?config.events[key].detail:{};const existingEventDetail=existingConfig.events[key].detail?existingConfig.events[key].detail:{};const detailKeys=Object.keys(configEventDetail);const existingDetailKeys=Object.keys(existingEventDetail);for(let j=0;j<existingDetailKeys.length;j++){const detailKey=existingDetailKeys[j];if(j>=detailKeys.length||!configEventDetail.hasOwnProperty(detailKey)){explanation=`Event '${key}' has missing entries in the detail payload`;break}else{if(!this._compareType(configEventDetail[detailKey],existingEventDetail[detailKey])){explanation=`Event '${key}' detail attribute '${detailKey}' has a changed type`;break}}}if(!explanation&&config.events[key].bubbles!==existingConfig.events[key].bubbles){explanation=`Event '${key}' has a changed bubbling state`;break}if(!explanation&&config.events[key].cancelable!==existingConfig.events[key].cancelable){explanation=`Event '${key}' has changed cancelable state`;break}}else{explanation=`Event '${key}' has been removed`;break}}return explanation};ruleDef.prototype._detectSlotDiff=function(config,existingConfig){return this._detectTypedSlotDiff("slots",config,existingConfig)};ruleDef.prototype._detectDynamicSlotDiff=function(config,existingConfig){return this._detectTypedSlotDiff("dynamicSlots",config,existingConfig)};ruleDef.prototype._detectTypedSlotDiff=function(slotType,config,existingConfig){let explanation;const configSlots=config[slotType]?Object.keys(config[slotType]):[];const existingSlots=existingConfig[slotType]?Object.keys(existingConfig[slotType]):[];for(let i=0;i<existingSlots.length;i++){const key=existingSlots[i];if(config[slotType].hasOwnProperty(key)){const configSlotData=config[slotType][key].data?config[slotType][key].data:{};const existingSlotData=existingConfig[slotType][key].data?existingConfig[slotType][key].data:{};const dataKeys=Object.keys(configSlotData);const existingDataKeys=Object.keys(existingSlotData);for(let j=0;j<existingDataKeys.length;j++){const dataKey=existingDataKeys[j];if(j>=dataKeys.length||!configSlotData.hasOwnProperty(dataKey)){explanation=`Template slot '${key}' - '${dataKey}' has been removed from data definition`;break}else{if(!this._compareType(configSlotData[dataKey],existingSlotData[dataKey])){explanation=`Template slot '${key}' data attribute '${dataKey}' has a changed type`;break}}}}else{explanation=`Slot '${key}' has been removed`;break}}return explanation};ruleDef.prototype._compareType=function(newTyped,existingTyped){let matches=true;const newType=newTyped&&newTyped.type?newTyped.type:null;const existingType=existingTyped&&existingTyped.type?existingTyped.type:null;if(newType!==existingType){if(newType.includes("|")){const newTypeOptions=newType?newType.split("|"):[];const existingTypeOptions=existingType?existingType.split("|"):[];matches=existingTypeOptions.every(checkType=>newTypeOptions.includes(checkType))}else{matches=false}}return matches};ruleDef.prototype._compareProperties=function(newProps,oldProps,path){let explanation;const configProps=newProps?Object.keys(newProps):[];const existingProps=oldProps?Object.keys(oldProps):[];for(let i=0;i<existingProps.length;i++){const key=existingProps[i];if(newProps.hasOwnProperty(key)){const newProperty=newProps[key];const oldProperty=oldProps[key];if(!this._compareType(newProperty,oldProperty)){explanation=`Property type change for '${path?path:""}${key}'`;break}if(oldProperty.hasOwnProperty("enumValues")){const newOptions=newProperty.hasOwnProperty("enumValues")?newProperty.enumValues:[];if(!oldProperty.enumValues.every(checkOption=>newOptions.includes(checkOption))){explanation=`Enumeration value option removed from property '${path?path:""}${key}'`;break}}else if(newProperty.hasOwnProperty("enumValues")){explanation=`Property '${path?path:""}${key}' is now constrained by an enumeration`;break}if(!path){if(oldProperty.writeback&&!newProperty.writeback){explanation=`Property '${key}' is no longer writeback enabled`;break}if(!oldProperty.required&&newProperty.required){explanation=`Property '${key}' has been made required`;break}const oldROState=oldProperty.hasOwnProperty("readOnly")?oldProperty.readOnly:false;const newROState=newProperty.hasOwnProperty("readOnly")?newProperty.readOnly:false;if(oldROState!==newROState){explanation=`Property '${key}' readOnly state has changed`;break}const oldDefault=oldProperty.hasOwnProperty("value")?JSON.stringify(oldProperty.value):"";const newDefault=newProperty.hasOwnProperty("value")?JSON.stringify(newProperty.value):"";if(oldDefault!==newDefault){explanation=`Property '${key}' default value has changed`;break}}if(newProperty.hasOwnProperty("properties")||oldProperty.hasOwnProperty("properties")){const newSubProps=newProperty.properties?newProperty.properties:{};const oldSubProps=oldProperty.properties?oldProperty.properties:{};const propPath=path?path+key+".":key+".";explanation=this._compareProperties(newSubProps,oldSubProps,propPath);if(explanation){break}}}else{explanation=`Property '${path?path:""}${key}' has been removed`;break}}return explanation};module.exports=ruleDef;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const AuditComponentCacheManager=require("../jetwc-lib/jetwcutils-auditComponentCacheManager");const NetUtils=require("../../lib/NetUtils");const Utils=require("../jetwc-lib/jetwcutils-componentAuditUtils");const CommonImpl=require("../jetwc-lib/jetwcutils-commonListenerImpls");const TsxUtils=require("../jetwc-lib/jetwcutils-tsxUtils");const ruleDef=function(){};ruleDef.prototype.getName=function(){return"jetwco-component-api-changes"};ruleDef.prototype.getShortDescription=function(){return"Verify that any API changes are compatible with the version number change"};ruleDef.prototype.getDescription=function(){return"This audit compares the metadata of the previous version of a component in the Exchange Catalog and verifies that any API changes are matched with an appropriate version number change according to semver rules"};ruleDef.prototype.register=function(context){return{startaudit:this._auditPrep,closedownRP:this._dealWithCache,compjson:this._doAudit,Program:this._doVComponentAudit}};ruleDef.prototype._auditPrep=function(context){this.exchangeURL=CommonImpl.checkForExchangeConfiguration(context);if(this.exchangeURL){this.acCache=new AuditComponentCacheManager(context,this.getName())}else{const issue=new context.Issue(`Invalid or Missing exchangeURL value specified for the rule ${context.ruleName}, rule execution is disabled`);issue.setMsgKey(`${context.ruleName}_2`);issue.setSeverity("critical");context.reporter.addIssue(issue,context)}};ruleDef.prototype._dealWithCache=function(context){const shouldClearCache=context.rulePack.getRuleOption("clearCache",this.getName());if(shouldClearCache&&this.acCache){this.acCache.removeLocalCache()}};ruleDef.prototype._doAudit=function(context){if(context.suppData.obj){const meta=context.suppData.obj;const fullName=Utils.getComponentFullName(meta);this._checkAPIs(context,fullName,meta)}};ruleDef.prototype._doVComponentAudit=function(context){const componentInfo=TsxUtils.matchToVComponentImpl(context,context.filepath);if(componentInfo){let remappedDependencies;if(componentInfo.dependencies){remappedDependencies=componentInfo.dependencies.reduce((asMap,entry)=>{asMap[entry.name]=entry.range;return asMap},{})}const meta={version:componentInfo.version,jetVersion:componentInfo.jetVersion,properties:componentInfo.properties,methods:componentInfo.methods,events:componentInfo.events,sots:componentInfo.slots,dependencies:remappedDependencies};this._checkAPIs(context,componentInfo.fullName,meta)}};ruleDef.prototype._checkAPIs=function(context,fullName,componentDef){const{msgLib,semVerUtils}=context.utils;let newVersion,latestMatchVersion;try{const netUtils=new NetUtils;const existingVersionsResp=netUtils.loadUrl(`${this.exchangeURL}components/${fullName}/versions`);if(existingVersionsResp.statusCode===200&&existingVersionsResp.body){const existingVersions=JSON.parse(existingVersionsResp.body);if(existingVersions.items&&existingVersions.items.length>0){newVersion=componentDef.version;let minorVersionUpdated=false;latestMatchVersion=this._findMostAppropriateComparitor(existingVersions,newVersion,semVerUtils);if(latestMatchVersion){if(this._isAPICheckNeeded(semVerUtils,newVersion,latestMatchVersion)){minorVersionUpdated=this._isEffectiveMinor(semVerUtils,newVersion,latestMatchVersion);let existingDef;if(this.acCache.existsInComponentCache(fullName,latestMatchVersion)){existingDef=this.acCache.readFromComponentCache(fullName,latestMatchVersion)}else{const uploadedResp=netUtils.loadUrl(`${this.exchangeURL}components/${fullName}/versions/${latestMatchVersion}`);if(uploadedResp.statusCode=200&&uploadedResp.body){existingDef=JSON.parse(uploadedResp.body).component;this.acCache.writeToComponentCache(fullName,latestMatchVersion,existingDef)}}if(existingDef){try{this._conductCheck(this._detectJetVersionDiff,semVerUtils,componentDef,existingDef,minorVersionUpdated);this._conductCheck(this._detectDependencyDiff,semVerUtils,componentDef,existingDef,minorVersionUpdated);this._conductCheck(this._detectMethodDiff,componentDef,existingDef,minorVersionUpdated);this._conductCheck(this._detectPropertyDiff,componentDef,existingDef,minorVersionUpdated);this._conductCheck(this._detectEventDiff,componentDef,existingDef,minorVersionUpdated);this._conductCheck(this._detectSlotDiff,componentDef,existingDef,minorVersionUpdated);this._conductCheck(this._detectDynamicSlotDiff,componentDef,existingDef,minorVersionUpdated)}catch(auditDetail){const issue=new context.Issue(`API change for ${fullName}@${newVersion} (compared with @${latestMatchVersion}) is not matched by appropriate version number update. Indication: ${auditDetail}`);issue.setMsgKey("jetwco-component-api-changes_1");context.reporter.addIssue(issue,context)}}else{msgLib.error(`Unable to obtain metadata for ${fullName}@${latestMatchVersion}`)}}else{}}}}else if(existingVersionsResp.statusCode===404||existingVersionsResp.eCode==="ENOTFOUND"){msgLib.info(`The component ${fullName} does not exist in the Exchange and so cannot be API verified against older versions. It will be skipped`)}}catch(e){msgLib.error(`Unexpected error in jetwco-component-api-changes processing component ${fullName}:\n ${JSON.stringify(e)}`)};};ruleDef.prototype._findMostAppropriateComparitor=function(existingVersions,newVersion,semver){const versions=existingVersions.items.reverse();let closestMatch,firstMatch,closestReleaseMatch;for(let i=0;i<versions.length;i++){if(semver.gte(newVersion,versions[i])){closestMatch=versions[i];if(!firstMatch){firstMatch=closestMatch}if(!this._isPreRelease(semver,closestMatch)||semver.major(closestMatch)===0){closestReleaseMatch=closestMatch;break}else{continue}}}return closestReleaseMatch?closestReleaseMatch:firstMatch};ruleDef.prototype._isPreRelease=function(semver,version){return Array.isArray(semver.prerelease(version))};ruleDef.prototype._isAPICheckNeeded=function(semver,newVersion,existingVersion){let doCheck=true;if(semver.major(newVersion)>semver.major(existingVersion)||semver.major(newVersion)===0&&semver.minor(newVersion)>semver.minor(existingVersion)){doCheck=false}return doCheck};ruleDef.prototype._isEffectiveMinor=function(semver,newVersion,existingVersion){let classAsMinor=false;if(semver.minor(newVersion)>semver.minor(existingVersion)||semver.major(newVersion)===0&&semver.patch(newVersion)>semver.patch(existingVersion)){classAsMinor=true}return classAsMinor};ruleDef.prototype._conductCheck=function(checkCallback,semver,config,existingConfig,claimedMinorDiff){const result=checkCallback.call(this,semver,config,existingConfig,claimedMinorDiff);if(result){throw result}};ruleDef.prototype._detectJetVersionDiff=function(semver,config,existingConfig,claimedMinorDiff){let explanation;const componentJetVersion=config.jetVersion?config.jetVersion:"0.0.0";const existingJetVersion=existingConfig.jetVersion?existingConfig.jetVersion:"0.0.0";if(componentJetVersion!==existingJetVersion){if(existingJetVersion==="0.0.0"||componentJetVersion==="0.0.0"){explanation="JET version range has been added or removed"}else{const minVersion=semver.minVersion(componentJetVersion);const minExistingVersion=semver.minVersion(existingJetVersion);if(semver.major(minVersion)>semver.major(minExistingVersion)){explanation="minimum major JET version required has increased"}else if(!claimedMinorDiff){if(semver.minor(minVersion)>semver.minor(minExistingVersion)){explanation="minimum minor JET version required has increased"}}}}return explanation};ruleDef.prototype._detectDependencyDiff=function(semver,config,existingConfig,claimedMinorDiff){let explanation;const configDeps=config.dependencies?Object.keys(config.dependencies):[];const existingDeps=existingConfig.dependencies?Object.keys(existingConfig.dependencies):[];if(configDeps.length>existingDeps.length){explanation="more dependencies are declared"}else{if(configDeps.length>0){for(let i=0;i<existingDeps.length;i++){const key=existingDeps[i];if(config.dependencies.hasOwnProperty(key)){const newDepVersion=semver.minVersion(config.dependencies[key]);const existingDepVersion=semver.minVersion(existingConfig.dependencies[key]);if(semver.major(newDepVersion)!==semver.major(existingDepVersion)){explanation="different major version of dependency "+key;break}if(!claimedMinorDiff){if(semver.minor(newDepVersion)!==semver.minor(existingDepVersion)){explanation="different minor version of dependency "+key;break}}}else{if(!claimedMinorDiff){explanation=`dependency ${key} has been removed`}break}}}}return explanation};ruleDef.prototype._detectMethodDiff=function(config,existingConfig,claimedMinorDiff){let explanation;const configMethods=config.methods?Object.keys(config.methods):[];const existingMethods=existingConfig.methods?Object.keys(existingConfig.methods):[];if(configMethods.length>=existingMethods.length){if(claimedMinorDiff){if(!existingMethods.every(checkName=>configMethods.includes(checkName))){explanation="existing method removed"}}else if(configMethods.length!==existingMethods.length){explanation="different number of methods declared"}}else{if(configMethods.length===0&&existingMethods.length>0){explanation="existing method(s) removed"}}if(!explanation){for(let i=0;i<existingMethods.length;i++){const key=existingMethods[i];if(config.methods.hasOwnProperty(key)){const configMethodParams=config.methods[key].params?config.methods[key].params:[];const existingMethodParams=existingConfig.methods[key].params?existingConfig.methods[key].params:[];for(let j=0;j<existingMethodParams.length;j++){if(j>=configMethodParams.length){explanation=`existing method '${key}' has fewer parameters`;break}else{if(!this._compareType(configMethodParams[j],existingMethodParams[j],claimedMinorDiff)){explanation=`method '${key}' parameter number:${j+1} has a changed type`;break}}}if(!explanation&&configMethodParams.length>existingMethodParams.length&&!claimedMinorDiff){explanation=`existing method '${key}' has additional parameters`;break}}else{explanation=`existing method '${key}' has been removed`;break}}}return explanation};ruleDef.prototype._detectPropertyDiff=function(config,existingConfig,claimedMinorDiff){let explanation;const configProps=config.properties?Object.keys(config.properties):[];const existingProps=existingConfig.properties?Object.keys(existingConfig.properties):[];if(configProps.length>=existingProps.length){if(claimedMinorDiff){if(!existingProps.every(checkName=>configProps.includes(checkName))){explanation="existing property removed"}}else if(configProps.length!==existingProps.length){explanation="different number of properties declared"}}else{if(configProps.length===0&&existingProps.length>0){explanation="existing properties removed"}}if(!explanation){explanation=this._compareProperties(config.properties,existingConfig.properties,claimedMinorDiff)}return explanation};ruleDef.prototype._detectEventDiff=function(config,existingConfig,claimedMinorDiff){let explanation;const configEvents=config.events?Object.keys(config.events):[];const existingEvents=existingConfig.events?Object.keys(existingConfig.events):[];if(configEvents.length>=existingEvents.length){if(claimedMinorDiff){if(!existingEvents.every(checkName=>configEvents.includes(checkName))){explanation="existing event removed"}}else if(configEvents.length!==existingEvents.length){explanation="different number of events declared"}}else{if(configEvents.length===0&&existingEvents.length>0){explanation="existing event(s) removed"}}if(!explanation){for(let i=0;i<existingEvents.length;i++){const key=existingEvents[i];if(config.events.hasOwnProperty(key)){const configEventDetail=config.events[key].detail?config.events[key].detail:{};const existingEventDetail=existingConfig.events[key].detail?existingConfig.events[key].detail:{};const detailKeys=Object.keys(configEventDetail);const existingDetailKeys=Object.keys(existingEventDetail);for(let j=0;j<existingDetailKeys.length;j++){const detailKey=existingDetailKeys[j];if(j>=detailKeys.length||!configEventDetail.hasOwnProperty(detailKey)){explanation=`existing event '${key}' has missing entries in the detail payload`;break}else{if(!this._compareType(configEventDetail[detailKey],existingEventDetail[detailKey],claimedMinorDiff)){explanation=`event '${key}' detail attribute '${detailKey}' has a changed type`;break}}}if(!explanation&&detailKeys.length>existingDetailKeys.length&&!claimedMinorDiff){explanation=`existing event '${key}' has additional entries in the detail payload`;break}if(!explanation&&config.events[key].bubbles!==existingConfig.events[key].bubbles){explanation=`existing event '${key}' has changed bubbling state`;break}if(!explanation&&config.events[key].cancelable!==existingConfig.events[key].cancelable){explanation=`existing event '${key}' has changed cancelable state`;break}}else{explanation=`existing event '${key}' has been removed`;break}}}return explanation};ruleDef.prototype._detectSlotDiff=function(config,existingConfig,claimedMinorDiff){return this._detectTypedSlotDiff("slots",config,existingConfig,claimedMinorDiff)};ruleDef.prototype._detectDynamicSlotDiff=function(config,existingConfig,claimedMinorDiff){return this._detectTypedSlotDiff("dynamicSlots",config,existingConfig,claimedMinorDiff)};ruleDef.prototype._detectTypedSlotDiff=function(slotType,config,existingConfig,claimedMinorDiff){let explanation;const configSlots=config[slotType]?Object.keys(config[slotType]):[];const existingSlots=existingConfig[slotType]?Object.keys(existingConfig[slotType]):[];if(configSlots.length>=existingSlots.length){if(claimedMinorDiff){if(!existingSlots.every(checkName=>configSlots.includes(checkName))){explanation="existing slot removed"}}else if(configSlots.length!==existingSlots.length){explanation="different number of slots declared"}}else{if(configSlots.length===0&&existingSlots.length>0){explanation="existing slot(s) removed"}}if(!explanation){for(let i=0;i<existingSlots.length;i++){const key=existingSlots[i];if(config[slotType].hasOwnProperty(key)){const configSlotData=config[slotType][key].data?config[slotType][key].data:{};const existingSlotData=existingConfig[slotType][key].data?existingConfig[slotType][key].data:{};const dataKeys=Object.keys(configSlotData);const existingDataKeys=Object.keys(existingSlotData);for(let j=0;j<existingDataKeys.length;j++){const dataKey=existingDataKeys[j];if(j>=dataKeys.length||!configSlotData.hasOwnProperty(dataKey)){explanation=`existing slot '${key}' has missing entries in the data payload`;break}else{if(!this._compareType(configSlotData[dataKey],existingSlotData[dataKey],claimedMinorDiff)){explanation=`slot '${key}' data attribute '${dataKey}' has a changed type`;break}}}if(!explanation&&dataKeys.length>existingDataKeys.length&&!claimedMinorDiff){explanation=`existing slot '${key}' has additional entries in the data payload`;break}}else{explanation=`existing slot '${key}' has been removed`;break}}}return explanation};ruleDef.prototype._compareType=function(newTyped,existingTyped,claimedMinorDiff){let matches=true;const newType=newTyped&&newTyped.type?newTyped.type:null;const existingType=existingTyped&&existingTyped.type?existingTyped.type:null;if(newType!==existingType){if(claimedMinorDiff){const newTypeOptions=newType?newType.split("|"):[];const existingTypeOptions=existingType?existingType.split("|"):[];matches=existingTypeOptions.every(checkType=>newTypeOptions.includes(checkType))}else{matches=false}}return matches};ruleDef.prototype._compareProperties=function(newProps,oldProps,claimedMinorDiff,path){let explanation;const configProps=newProps?Object.keys(newProps):[];const existingProps=oldProps?Object.keys(oldProps):[];for(let i=0;i<existingProps.length;i++){const key=existingProps[i];if(newProps.hasOwnProperty(key)){const newProperty=newProps[key];const oldProperty=oldProps[key];if(!this._compareType(newProperty,oldProperty,claimedMinorDiff)){explanation=`type change for property ${path?path:""}${key}`;break}if(oldProperty.hasOwnProperty("enumValues")){const newOptions=newProperty.hasOwnProperty("enumValues")?newProperty.enumValues:[];if(!oldProperty.enumValues.every(checkOption=>newOptions.includes(checkOption))){explanation=`Enumeration value option removed from property '${path?path:""}${key}'`;break}}else if(newProperty.hasOwnProperty("enumValues")){explanation=`Property '${path?path:""}${key}' is now constrained by an enumeration`;break}if(!path){if(oldProperty.writeback&&!newProperty.writeback){explanation=`property ${key} is no longer writeback enabled`;break}if(!oldProperty.required&&newProperty.required){explanation=`property ${key} has been made required`;break}if(!oldProperty.required&&newProperty.required){explanation=`Property '${key}' has been made required`;break}const oldROState=oldProperty.hasOwnProperty("readOnly")?oldProperty.readOnly:false;const newROState=newProperty.hasOwnProperty("readOnly")?newProperty.readOnly:false;if(oldROState!==newROState){explanation=`Property '${key}' readOnly state has changed`;break}}if(newProperty.hasOwnProperty("properties")||oldProperty.hasOwnProperty("properties")){const newSubProps=newProperty.properties?newProperty.properties:{};const oldSubProps=oldProperty.properties?oldProperty.properties:{};const propPath=path?path+key+".":key+".";explanation=this._compareProperties(newSubProps,oldSubProps,claimedMinorDiff,propPath);if(explanation){break}}}else{explanation=`property ${path?path:""}${key} has been removed`;break}}if(!explanation){if(!claimedMinorDiff&&configProps.length>existingProps.length){explanation=`property added ${path?"as sub-property of "+path:""}`}}return explanation};module.exports=ruleDef;
6
+ const AuditComponentCacheManager=require("../jetwc-lib/jetwcutils-auditComponentCacheManager");const NetUtils=require("../../lib/NetUtils");const Utils=require("../jetwc-lib/jetwcutils-componentAuditUtils");const CommonImpl=require("../jetwc-lib/jetwcutils-commonListenerImpls");const TsxUtils=require("../jetwc-lib/jetwcutils-tsxUtils");const ruleDef=function(){};ruleDef.prototype.getName=function(){return"jetwco-component-api-changes"};ruleDef.prototype.getShortDescription=function(){return"Verify that any API changes are compatible with the version number change"};ruleDef.prototype.getDescription=function(){return"This audit compares the metadata of the previous version of a component in the Exchange Catalog and verifies that any API changes are matched with an appropriate version number change according to semver rules"};ruleDef.prototype.register=function(context){return{startaudit:this._auditPrep,closedownRP:this._dealWithCache,compjson:this._doAudit,Program:this._doVComponentAudit}};ruleDef.prototype._auditPrep=function(context){this.exchangeURL=CommonImpl.checkForExchangeConfiguration(context);if(this.exchangeURL){this.acCache=new AuditComponentCacheManager(context,this.getName())}else{const issue=new context.Issue(`Invalid or Missing exchangeURL value specified for the rule ${context.ruleName}, rule execution is disabled`);issue.setMsgKey(`${context.ruleName}_2`);issue.setSeverity("critical");context.reporter.addIssue(issue,context)}};ruleDef.prototype._dealWithCache=function(context){const shouldClearCache=context.rulePack.getRuleCustomOption("clearCache",this.getName());if(shouldClearCache&&this.acCache){this.acCache.removeLocalCache()}};ruleDef.prototype._doAudit=function(context){if(context.suppData.obj){const meta=context.suppData.obj;const fullName=Utils.getComponentFullName(meta);this._checkAPIs(context,fullName,meta)}};ruleDef.prototype._doVComponentAudit=function(context){const componentInfo=TsxUtils.matchToVComponentImpl(context,context.filepath);if(componentInfo){let remappedDependencies;if(componentInfo.dependencies){remappedDependencies=componentInfo.dependencies.reduce((asMap,entry)=>{asMap[entry.name]=entry.range;return asMap},{})}const meta={version:componentInfo.version,jetVersion:componentInfo.jetVersion,properties:componentInfo.properties,methods:componentInfo.methods,events:componentInfo.events,sots:componentInfo.slots,dependencies:remappedDependencies};this._checkAPIs(context,componentInfo.fullName,meta)}};ruleDef.prototype._checkAPIs=function(context,fullName,componentDef){const{msgLib,semVerUtils}=context.utils;let newVersion,latestMatchVersion;try{const netUtils=new NetUtils;const existingVersionsResp=netUtils.loadUrl(`${this.exchangeURL}components/${fullName}/versions`);if(existingVersionsResp.statusCode===200&&existingVersionsResp.body){const existingVersions=JSON.parse(existingVersionsResp.body);if(existingVersions.items&&existingVersions.items.length>0){newVersion=componentDef.version;let minorVersionUpdated=false;latestMatchVersion=this._findMostAppropriateComparitor(existingVersions,newVersion,semVerUtils);if(latestMatchVersion){if(this._isAPICheckNeeded(semVerUtils,newVersion,latestMatchVersion)){minorVersionUpdated=this._isEffectiveMinor(semVerUtils,newVersion,latestMatchVersion);let existingDef;if(this.acCache.existsInComponentCache(fullName,latestMatchVersion)){existingDef=this.acCache.readFromComponentCache(fullName,latestMatchVersion)}else{const uploadedResp=netUtils.loadUrl(`${this.exchangeURL}components/${fullName}/versions/${latestMatchVersion}`);if(uploadedResp.statusCode=200&&uploadedResp.body){existingDef=JSON.parse(uploadedResp.body).component;this.acCache.writeToComponentCache(fullName,latestMatchVersion,existingDef)}}if(existingDef){try{this._conductCheck(this._detectJetVersionDiff,semVerUtils,componentDef,existingDef,minorVersionUpdated);this._conductCheck(this._detectDependencyDiff,semVerUtils,componentDef,existingDef,minorVersionUpdated);this._conductCheck(this._detectMethodDiff,componentDef,existingDef,minorVersionUpdated);this._conductCheck(this._detectPropertyDiff,componentDef,existingDef,minorVersionUpdated);this._conductCheck(this._detectEventDiff,componentDef,existingDef,minorVersionUpdated);this._conductCheck(this._detectSlotDiff,componentDef,existingDef,minorVersionUpdated);this._conductCheck(this._detectDynamicSlotDiff,componentDef,existingDef,minorVersionUpdated)}catch(auditDetail){const issue=new context.Issue(`API change for ${fullName}@${newVersion} (compared with @${latestMatchVersion}) is not matched by appropriate version number update. Indication: ${auditDetail}`);issue.setMsgKey("jetwco-component-api-changes_1");context.reporter.addIssue(issue,context)}}else{msgLib.error(`Unable to obtain metadata for ${fullName}@${latestMatchVersion}`)}}else{}}}}else if(existingVersionsResp.statusCode===404||existingVersionsResp.eCode==="ENOTFOUND"){msgLib.info(`The component ${fullName} does not exist in the Exchange and so cannot be API verified against older versions. It will be skipped`)}}catch(e){msgLib.error(`Unexpected error in jetwco-component-api-changes processing component ${fullName}:\n ${JSON.stringify(e)}`)};};ruleDef.prototype._findMostAppropriateComparitor=function(existingVersions,newVersion,semver){const versions=existingVersions.items.reverse();let closestMatch,firstMatch,closestReleaseMatch;for(let i=0;i<versions.length;i++){if(semver.gte(newVersion,versions[i])){closestMatch=versions[i];if(!firstMatch){firstMatch=closestMatch}if(!this._isPreRelease(semver,closestMatch)||semver.major(closestMatch)===0){closestReleaseMatch=closestMatch;break}else{continue}}}return closestReleaseMatch?closestReleaseMatch:firstMatch};ruleDef.prototype._isPreRelease=function(semver,version){return Array.isArray(semver.prerelease(version))};ruleDef.prototype._isAPICheckNeeded=function(semver,newVersion,existingVersion){let doCheck=true;if(semver.major(newVersion)>semver.major(existingVersion)||semver.major(newVersion)===0&&semver.minor(newVersion)>semver.minor(existingVersion)){doCheck=false}return doCheck};ruleDef.prototype._isEffectiveMinor=function(semver,newVersion,existingVersion){let classAsMinor=false;if(semver.minor(newVersion)>semver.minor(existingVersion)||semver.major(newVersion)===0&&semver.patch(newVersion)>semver.patch(existingVersion)){classAsMinor=true}return classAsMinor};ruleDef.prototype._conductCheck=function(checkCallback,semver,config,existingConfig,claimedMinorDiff){const result=checkCallback.call(this,semver,config,existingConfig,claimedMinorDiff);if(result){throw result}};ruleDef.prototype._detectJetVersionDiff=function(semver,config,existingConfig,claimedMinorDiff){let explanation;const componentJetVersion=config.jetVersion?config.jetVersion:"0.0.0";const existingJetVersion=existingConfig.jetVersion?existingConfig.jetVersion:"0.0.0";if(componentJetVersion!==existingJetVersion){if(existingJetVersion==="0.0.0"||componentJetVersion==="0.0.0"){explanation="JET version range has been added or removed"}else{const minVersion=semver.minVersion(componentJetVersion);const minExistingVersion=semver.minVersion(existingJetVersion);if(semver.major(minVersion)>semver.major(minExistingVersion)){explanation="minimum major JET version required has increased"}else if(!claimedMinorDiff){if(semver.minor(minVersion)>semver.minor(minExistingVersion)){explanation="minimum minor JET version required has increased"}}}}return explanation};ruleDef.prototype._detectDependencyDiff=function(semver,config,existingConfig,claimedMinorDiff){let explanation;const configDeps=config.dependencies?Object.keys(config.dependencies):[];const existingDeps=existingConfig.dependencies?Object.keys(existingConfig.dependencies):[];if(configDeps.length>existingDeps.length){explanation="more dependencies are declared"}else{if(configDeps.length>0){for(let i=0;i<existingDeps.length;i++){const key=existingDeps[i];if(config.dependencies.hasOwnProperty(key)){const newDepVersion=semver.minVersion(config.dependencies[key]);const existingDepVersion=semver.minVersion(existingConfig.dependencies[key]);if(semver.major(newDepVersion)!==semver.major(existingDepVersion)){explanation="different major version of dependency "+key;break}if(!claimedMinorDiff){if(semver.minor(newDepVersion)!==semver.minor(existingDepVersion)){explanation="different minor version of dependency "+key;break}}}else{if(!claimedMinorDiff){explanation=`dependency ${key} has been removed`}break}}}}return explanation};ruleDef.prototype._detectMethodDiff=function(config,existingConfig,claimedMinorDiff){let explanation;const configMethods=config.methods?Object.keys(config.methods):[];const existingMethods=existingConfig.methods?Object.keys(existingConfig.methods):[];if(configMethods.length>=existingMethods.length){if(claimedMinorDiff){if(!existingMethods.every(checkName=>configMethods.includes(checkName))){explanation="existing method removed"}}else if(configMethods.length!==existingMethods.length){explanation="different number of methods declared"}}else{if(configMethods.length===0&&existingMethods.length>0){explanation="existing method(s) removed"}}if(!explanation){for(let i=0;i<existingMethods.length;i++){const key=existingMethods[i];if(config.methods.hasOwnProperty(key)){const configMethodParams=config.methods[key].params?config.methods[key].params:[];const existingMethodParams=existingConfig.methods[key].params?existingConfig.methods[key].params:[];for(let j=0;j<existingMethodParams.length;j++){if(j>=configMethodParams.length){explanation=`existing method '${key}' has fewer parameters`;break}else{if(!this._compareType(configMethodParams[j],existingMethodParams[j],claimedMinorDiff)){explanation=`method '${key}' parameter number:${j+1} has a changed type`;break}}}if(!explanation&&configMethodParams.length>existingMethodParams.length&&!claimedMinorDiff){explanation=`existing method '${key}' has additional parameters`;break}}else{explanation=`existing method '${key}' has been removed`;break}}}return explanation};ruleDef.prototype._detectPropertyDiff=function(config,existingConfig,claimedMinorDiff){let explanation;const configProps=config.properties?Object.keys(config.properties):[];const existingProps=existingConfig.properties?Object.keys(existingConfig.properties):[];if(configProps.length>=existingProps.length){if(claimedMinorDiff){if(!existingProps.every(checkName=>configProps.includes(checkName))){explanation="existing property removed"}}else if(configProps.length!==existingProps.length){explanation="different number of properties declared"}}else{if(configProps.length===0&&existingProps.length>0){explanation="existing properties removed"}}if(!explanation){explanation=this._compareProperties(config.properties,existingConfig.properties,claimedMinorDiff)}return explanation};ruleDef.prototype._detectEventDiff=function(config,existingConfig,claimedMinorDiff){let explanation;const configEvents=config.events?Object.keys(config.events):[];const existingEvents=existingConfig.events?Object.keys(existingConfig.events):[];if(configEvents.length>=existingEvents.length){if(claimedMinorDiff){if(!existingEvents.every(checkName=>configEvents.includes(checkName))){explanation="existing event removed"}}else if(configEvents.length!==existingEvents.length){explanation="different number of events declared"}}else{if(configEvents.length===0&&existingEvents.length>0){explanation="existing event(s) removed"}}if(!explanation){for(let i=0;i<existingEvents.length;i++){const key=existingEvents[i];if(config.events.hasOwnProperty(key)){const configEventDetail=config.events[key].detail?config.events[key].detail:{};const existingEventDetail=existingConfig.events[key].detail?existingConfig.events[key].detail:{};const detailKeys=Object.keys(configEventDetail);const existingDetailKeys=Object.keys(existingEventDetail);for(let j=0;j<existingDetailKeys.length;j++){const detailKey=existingDetailKeys[j];if(j>=detailKeys.length||!configEventDetail.hasOwnProperty(detailKey)){explanation=`existing event '${key}' has missing entries in the detail payload`;break}else{if(!this._compareType(configEventDetail[detailKey],existingEventDetail[detailKey],claimedMinorDiff)){explanation=`event '${key}' detail attribute '${detailKey}' has a changed type`;break}}}if(!explanation&&detailKeys.length>existingDetailKeys.length&&!claimedMinorDiff){explanation=`existing event '${key}' has additional entries in the detail payload`;break}if(!explanation&&config.events[key].bubbles!==existingConfig.events[key].bubbles){explanation=`existing event '${key}' has changed bubbling state`;break}if(!explanation&&config.events[key].cancelable!==existingConfig.events[key].cancelable){explanation=`existing event '${key}' has changed cancelable state`;break}}else{explanation=`existing event '${key}' has been removed`;break}}}return explanation};ruleDef.prototype._detectSlotDiff=function(config,existingConfig,claimedMinorDiff){return this._detectTypedSlotDiff("slots",config,existingConfig,claimedMinorDiff)};ruleDef.prototype._detectDynamicSlotDiff=function(config,existingConfig,claimedMinorDiff){return this._detectTypedSlotDiff("dynamicSlots",config,existingConfig,claimedMinorDiff)};ruleDef.prototype._detectTypedSlotDiff=function(slotType,config,existingConfig,claimedMinorDiff){let explanation;const configSlots=config[slotType]?Object.keys(config[slotType]):[];const existingSlots=existingConfig[slotType]?Object.keys(existingConfig[slotType]):[];if(configSlots.length>=existingSlots.length){if(claimedMinorDiff){if(!existingSlots.every(checkName=>configSlots.includes(checkName))){explanation="existing slot removed"}}else if(configSlots.length!==existingSlots.length){explanation="different number of slots declared"}}else{if(configSlots.length===0&&existingSlots.length>0){explanation="existing slot(s) removed"}}if(!explanation){for(let i=0;i<existingSlots.length;i++){const key=existingSlots[i];if(config[slotType].hasOwnProperty(key)){const configSlotData=config[slotType][key].data?config[slotType][key].data:{};const existingSlotData=existingConfig[slotType][key].data?existingConfig[slotType][key].data:{};const dataKeys=Object.keys(configSlotData);const existingDataKeys=Object.keys(existingSlotData);for(let j=0;j<existingDataKeys.length;j++){const dataKey=existingDataKeys[j];if(j>=dataKeys.length||!configSlotData.hasOwnProperty(dataKey)){explanation=`existing slot '${key}' has missing entries in the data payload`;break}else{if(!this._compareType(configSlotData[dataKey],existingSlotData[dataKey],claimedMinorDiff)){explanation=`slot '${key}' data attribute '${dataKey}' has a changed type`;break}}}if(!explanation&&dataKeys.length>existingDataKeys.length&&!claimedMinorDiff){explanation=`existing slot '${key}' has additional entries in the data payload`;break}}else{explanation=`existing slot '${key}' has been removed`;break}}}return explanation};ruleDef.prototype._compareType=function(newTyped,existingTyped,claimedMinorDiff){let matches=true;const newType=newTyped&&newTyped.type?newTyped.type:null;const existingType=existingTyped&&existingTyped.type?existingTyped.type:null;if(newType!==existingType){if(claimedMinorDiff){const newTypeOptions=newType?newType.split("|"):[];const existingTypeOptions=existingType?existingType.split("|"):[];matches=existingTypeOptions.every(checkType=>newTypeOptions.includes(checkType))}else{matches=false}}return matches};ruleDef.prototype._compareProperties=function(newProps,oldProps,claimedMinorDiff,path){let explanation;const configProps=newProps?Object.keys(newProps):[];const existingProps=oldProps?Object.keys(oldProps):[];for(let i=0;i<existingProps.length;i++){const key=existingProps[i];if(newProps.hasOwnProperty(key)){const newProperty=newProps[key];const oldProperty=oldProps[key];if(!this._compareType(newProperty,oldProperty,claimedMinorDiff)){explanation=`type change for property ${path?path:""}${key}`;break}if(oldProperty.hasOwnProperty("enumValues")){const newOptions=newProperty.hasOwnProperty("enumValues")?newProperty.enumValues:[];if(!oldProperty.enumValues.every(checkOption=>newOptions.includes(checkOption))){explanation=`Enumeration value option removed from property '${path?path:""}${key}'`;break}}else if(newProperty.hasOwnProperty("enumValues")){explanation=`Property '${path?path:""}${key}' is now constrained by an enumeration`;break}if(!path){if(oldProperty.writeback&&!newProperty.writeback){explanation=`property ${key} is no longer writeback enabled`;break}if(!oldProperty.required&&newProperty.required){explanation=`property ${key} has been made required`;break}if(!oldProperty.required&&newProperty.required){explanation=`Property '${key}' has been made required`;break}const oldROState=oldProperty.hasOwnProperty("readOnly")?oldProperty.readOnly:false;const newROState=newProperty.hasOwnProperty("readOnly")?newProperty.readOnly:false;if(oldROState!==newROState){explanation=`Property '${key}' readOnly state has changed`;break}}if(newProperty.hasOwnProperty("properties")||oldProperty.hasOwnProperty("properties")){const newSubProps=newProperty.properties?newProperty.properties:{};const oldSubProps=oldProperty.properties?oldProperty.properties:{};const propPath=path?path+key+".":key+".";explanation=this._compareProperties(newSubProps,oldSubProps,claimedMinorDiff,propPath);if(explanation){break}}}else{explanation=`property ${path?path:""}${key} has been removed`;break}}if(!explanation){if(!claimedMinorDiff&&configProps.length>existingProps.length){explanation=`property added ${path?"as sub-property of "+path:""}`}}return explanation};module.exports=ruleDef;