/*
 * Copyright (c) 2018, 2025, Oracle and/or its affiliates.
 * Licensed under The Universal Permissive License (UPL), Version 1.0
 * as shown at https://oss.oracle.com/licenses/upl/
 */
const Utils=require("../jetwc-lib/jetwcutils-componentAuditUtils");const TsxUtils=require("../jetwc-lib/jetwcutils-tsxUtils");const ruleDef=function(){};ruleDef.prototype.getName=function(){return"jetwc-status-since"};ruleDef.prototype.getShortDescription=function(){return"Verify that the since value defined in any status metadata relates to a production version"};ruleDef.prototype.getDescription=function(){return"This rule checks that the since metadata associated with deprecations and maintanence mode specifies a production version of the component as opposed to a pre-production version which is not valid"};ruleDef.prototype.register=function(context){return{compjson:this._doAudit,Program:this._doVComponentAudit}};ruleDef.prototype._doAudit=function(context){if(context.suppData.obj){let issue;const meta=context.suppData.obj;const fullName=Utils.getComponentFullName(meta);this._checkDeprecationSinceValues(context,fullName,meta)}};ruleDef.prototype._doVComponentAudit=function(context){const componentInfo=TsxUtils.matchToVComponentImpl(context,context.filepath);if(componentInfo){this._checkDeprecationSinceValues(context,componentInfo.fullName,componentInfo)}};ruleDef.prototype._checkDeprecationSinceValues=function(auditContext,fullName,metadata){const semver=auditContext.utils.semVerUtils;const allStatusSinceEntries=this._extractSinceValues(semver,metadata,[]);allStatusSinceEntries.forEach(sinceRecord=>{let issueScope="";if(sinceRecord.scope.length>0){issueScope=` (${sinceRecord.scope.join(" > ")})`}if(!sinceRecord.value){issue=new auditContext.Issue(`Component ${fullName}${issueScope} specifies a status record without a "since" value which should be added to help the consumer understand when the change was made and will be used by other audits.`);issue.setMsgKey(auditContext.ruleName+"_1");auditContext.reporter.addIssue(issue,auditContext)}else if(!sinceRecord.validSemver){issue=new auditContext.Issue(`Component ${fullName}${issueScope} specifies a status record with an invalid version number for "since" (${sinceRecord.value}). A valid semantic version number (not range) must be used.`);issue.setMsgKey(auditContext.ruleName+"_2");auditContext.reporter.addIssue(issue,auditContext)}else if(sinceRecord.preReleaseSemver){issue=new auditContext.Issue(`Component ${fullName}${issueScope} specifies a status record with a pre-release version number for "since" (${sinceRecord.value}). A production version number must be used.`);issue.setMsgKey(auditContext.ruleName+"_3");auditContext.reporter.addIssue(issue,auditContext)}})};ruleDef.prototype._extractSinceValues=function(semver,metadata,statusScope){const statusEntries=[];for(const[key,value]of Object.entries(metadata)){if(key==="status"&&Array.isArray(value)){value.forEach(statusRec=>{const sinceRec={scope:statusScope,value:null,validSemver:false,preReleaseSemver:false};if(statusRec.hasOwnProperty("since")&&typeof statusRec.since==="string"){sinceRec.value=statusRec.since;if(semver.isValid(statusRec.since)){if(semver.minVersion(statusRec.since).version===statusRec.since){sinceRec.validSemver=true;if(semver.prerelease(statusRec.since)){sinceRec.preReleaseSemver=true}}}}statusEntries.push(sinceRec)})}else if(key!=="extension"&&typeof value==="object"&&value!==null){const newScope=statusScope.concat(key);const downStreamEntries=this._extractSinceValues(semver,value,newScope);downStreamEntries.forEach(sen=>statusEntries.push(sen))}}return statusEntries};module.exports=ruleDef;